From f9c5f7ad3c835eb50ec33f439270fd525b002ca4 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Fri, 10 Sep 2021 22:11:34 +0000 Subject: [PATCH] Update tests --- .../framework-preact/src/pages/index.astro | 2 +- examples/minimal/src/pages/index.astro | 2 + package.json | 6 +- packages/astro/components/Markdown.astro | 78 +- packages/astro/package.json | 11 +- packages/astro/src/@types/astro.ts | 10 +- packages/astro/src/@types/compiler.d.ts | 45 + packages/astro/src/build/index.ts | 4 +- packages/astro/src/cli/index.ts | 2 +- packages/astro/src/dev/index.ts | 110 +- packages/astro/src/dev/messages.ts | 6 + packages/astro/src/internal/index.ts | 211 +++ packages/astro/src/preview/index.ts | 2 +- .../astro/src/runtime/__astro_component.ts | 242 --- packages/astro/src/runtime/hmr.ts | 33 + packages/astro/src/runtime/ssr.ts | 173 +- packages/astro/src/runtime/vite/config.ts | 7 +- .../astro/src/runtime/vite/plugin-astro.ts | 86 +- packages/astro/test/astro-assets.test.js | 32 +- packages/astro/test/astro-attrs.test.js | 107 +- packages/astro/test/astro-basic.test.js | 206 +-- packages/astro/test/astro-children.test.js | 140 +- packages/astro/test/astro-client-only.test.js | 69 +- packages/astro/test/astro-components.test.js | 90 +- .../astro/test/astro-css-bundling.test.js | 137 +- packages/astro/test/astro-doctype.test.js | 140 +- packages/astro/test/astro-dynamic.test.js | 113 +- packages/astro/test/astro-expr.test.js | 186 +- packages/astro/test/astro-fallback.test.js | 34 +- .../astro/test/astro-get-static-paths.test.js | 25 +- .../astro/test/astro-global-build.test.js | 23 - packages/astro/test/astro-global.test.js | 123 +- packages/astro/test/astro-hmr.test.js | 92 +- .../astro/test/astro-markdown-plugins.test.js | 71 +- packages/astro/test/astro-markdown.test.js | 311 ++-- .../astro/test/astro-pageDirectoryUrl.test.js | 30 +- packages/astro/test/astro-pages.test.js | 53 +- packages/astro/test/astro-pagination.test.js | 113 +- packages/astro/test/astro-public.test.js | 28 +- packages/astro/test/astro-rss.test.js | 29 +- .../astro/test/astro-scoped-styles.test.js | 84 +- packages/astro/test/astro-scripts.test.js | 129 +- packages/astro/test/astro-search.test.js | 29 - packages/astro/test/astro-sitemap.test.js | 24 +- packages/astro/test/astro-slots.test.js | 247 ++- packages/astro/test/astro-styles-ssr.test.js | 252 +-- packages/astro/test/astro-throw.test.js | 40 +- .../astro/test/builtins-polyfillnode.test.js | 29 +- packages/astro/test/builtins.test.js | 53 +- packages/astro/test/config-hostname.test.js | 43 - packages/astro/test/config-path.test.js | 37 - packages/astro/test/config-port.test.js | 43 - packages/astro/test/config.test.js | 79 + packages/astro/test/custom-elements.test.js | 169 +- packages/astro/test/fetch.test.js | 31 +- .../astro-assets/src/pages/index.astro | 17 +- .../fixtures/astro-attrs/snowpack.config.json | 3 - .../fixtures/astro-basic/snowpack.config.json | 3 - .../fixtures/astro-children/astro.config.mjs | 7 - .../astro-children/snowpack.config.json | 3 - .../astro-client-only/astro.config.mjs | 8 - .../astro-client-only/snowpack.config.json | 3 - .../astro-components/snowpack.config.json | 3 - .../astro-css-bundling/snowpack.config.json | 3 - .../astro-doctype/snowpack.config.json | 3 - .../fixtures/astro-dynamic/astro.config.mjs | 5 - .../astro-dynamic/snowpack.config.json | 3 - .../test/fixtures/astro-expr/astro.config.mjs | 5 - .../fixtures/astro-expr/snowpack.config.json | 3 - .../fixtures/astro-fallback/astro.config.mjs | 5 - .../astro-fallback/snowpack.config.json | 3 - .../astro-get-static-paths/astro.config.mjs | 6 - .../snowpack.config.json | 3 - .../fixtures/astro-global/astro.config.mjs | 6 - .../astro-global/snowpack.config.json | 3 - .../fixtures/astro-hmr/snowpack.config.json | 6 - .../astro-markdown-plugins/astro.config.mjs | 19 - .../snowpack.config.json | 3 - .../fixtures/astro-markdown/astro.config.mjs | 8 - .../astro-markdown/snowpack.config.json | 3 - .../astro-page-directory-url/astro.config.mjs | 5 - .../snowpack.config.json | 3 - .../fixtures/astro-pages/snowpack.config.json | 3 - .../astro-pagination/astro.config.mjs | 6 - .../astro-pagination/snowpack.config.json | 3 - .../astro-public/snowpack.config.json | 3 - .../test/fixtures/astro-rss/astro.config.mjs | 5 - .../fixtures/astro-rss/snowpack.config.json | 3 - .../astro-scripts/snowpack.config.json | 3 - .../fixtures/astro-slots/snowpack.config.json | 3 - .../astro-styles-ssr/snowpack.config.json | 3 - .../fixtures/astro-throw/snowpack.config.json | 3 - .../snowpack.config.json | 6 - .../fixtures/builtins/snowpack.config.json | 3 - .../fixtures/config-port/astro.config.mjs | 5 +- .../fixtures/custom-elements/astro.config.mjs | 6 - .../custom-elements/snowpack.config.json | 3 - .../test/fixtures/fetch/snowpack.config.json | 3 - .../fixtures/lit-element/astro.config.mjs | 17 - .../fixtures/lit-element/snowpack.config.json | 3 - .../fixtures/no-head-el/snowpack.config.json | 3 - .../fixtures/plain-markdown/astro.config.mjs | 8 - .../plain-markdown/snowpack.config.json | 3 - .../preact-component/snowpack.config.json | 3 - .../react-component/snowpack.config.json | 3 - .../vue-component/snowpack.config.json | 3 - packages/astro/test/helpers.js | 175 -- packages/astro/test/integration-docs.test.js | 41 - packages/astro/test/lit-element.test.js | 86 +- packages/astro/test/no-head-el.test.js | 57 +- packages/astro/test/plain-markdown.test.js | 74 +- packages/astro/test/preact-component.test.js | 125 +- packages/astro/test/react-component.test.js | 156 +- packages/astro/test/route-manifest.test.js | 326 ++-- packages/astro/test/snowpack-log.test.js | 83 - packages/astro/test/test-utils.js | 103 +- packages/astro/test/vue-component.test.js | 55 +- yarn.lock | 1559 +++++++++++++++-- 118 files changed, 4325 insertions(+), 3232 deletions(-) create mode 100644 packages/astro/src/@types/compiler.d.ts create mode 100644 packages/astro/src/internal/index.ts delete mode 100644 packages/astro/src/runtime/__astro_component.ts create mode 100644 packages/astro/src/runtime/hmr.ts delete mode 100644 packages/astro/test/astro-global-build.test.js delete mode 100644 packages/astro/test/astro-search.test.js delete mode 100644 packages/astro/test/config-hostname.test.js delete mode 100644 packages/astro/test/config-path.test.js delete mode 100644 packages/astro/test/config-port.test.js create mode 100644 packages/astro/test/config.test.js delete mode 100644 packages/astro/test/fixtures/astro-attrs/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-basic/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-children/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-children/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-client-only/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-client-only/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-components/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-css-bundling/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-doctype/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-dynamic/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-dynamic/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-expr/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-expr/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-fallback/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-fallback/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-get-static-paths/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-get-static-paths/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-global/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-global/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-hmr/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-markdown-plugins/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-markdown-plugins/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-markdown/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-markdown/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-pages/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-pagination/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-pagination/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-public/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-rss/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/astro-rss/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-scripts/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-slots/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-styles-ssr/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/astro-throw/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/builtins-polyfillnode/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/builtins/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/custom-elements/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/custom-elements/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/fetch/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/lit-element/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/lit-element/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/no-head-el/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/plain-markdown/astro.config.mjs delete mode 100644 packages/astro/test/fixtures/plain-markdown/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/preact-component/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/react-component/snowpack.config.json delete mode 100644 packages/astro/test/fixtures/vue-component/snowpack.config.json delete mode 100644 packages/astro/test/helpers.js delete mode 100644 packages/astro/test/integration-docs.test.js delete mode 100644 packages/astro/test/snowpack-log.test.js diff --git a/examples/framework-preact/src/pages/index.astro b/examples/framework-preact/src/pages/index.astro index aea8b83a4..00ac11e14 100644 --- a/examples/framework-preact/src/pages/index.astro +++ b/examples/framework-preact/src/pages/index.astro @@ -1,6 +1,6 @@ --- // Component Imports -import Counter from '../components/Counter.jsx' +import Counter from '../components/Counter.tsx' // Full Astro Component Syntax: diff --git a/examples/minimal/src/pages/index.astro b/examples/minimal/src/pages/index.astro index 8e9209641..94a12e9de 100644 --- a/examples/minimal/src/pages/index.astro +++ b/examples/minimal/src/pages/index.astro @@ -1,5 +1,6 @@ --- --- + @@ -7,6 +8,7 @@ Welcome to Astro + diff --git a/package.json b/package.json index cc71dc224..7cbad4381 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ }, "devDependencies": { "@changesets/cli": "^2.16.0", - "@octokit/action": "^3.15.4", + "@types/jest": "^27.0.1", "@typescript-eslint/eslint-plugin": "^4.22.0", "@typescript-eslint/parser": "^4.18.0", "autoprefixer": "^10.2.6", @@ -56,11 +56,11 @@ "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", "execa": "^5.0.0", + "jest": "^27.1.0", "lerna": "^4.0.0", "prettier": "^2.3.2", "tiny-glob": "^0.2.8", - "typescript": "^4.4.2", - "uvu": "^0.5.1" + "typescript": "^4.4.2" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" diff --git a/packages/astro/components/Markdown.astro b/packages/astro/components/Markdown.astro index 609d015d4..99999751e 100644 --- a/packages/astro/components/Markdown.astro +++ b/packages/astro/components/Markdown.astro @@ -1,12 +1,14 @@ - -import fetch from 'node-fetch'; +--- import { renderMarkdown } from '@astrojs/markdown-support'; -import { __astro_slot } from 'astro/runtime/__astro_slot.js'; -if(!('fetch' in globalThis)) { - globalThis.fetch = fetch; +export interface Props { + content?: string; } +// Internal props that should not be part of the external interface. +interface InternalProps extends Props { + $scope: string; +} const __TopLevelAstro = { site: new URL("http://localhost:3000"), @@ -64,11 +66,11 @@ async function __render(props, ...children) { $scope } = Astro.props; let html = null; + +// This flow is only triggered if a user passes `` if (content) { - const { - content: htmlContent - } = await renderMarkdown(content, { - mode: "md", + const { content: htmlContent } = await renderMarkdown(content, { + mode: 'md', $: { scopedClassName: $scope } @@ -76,55 +78,9 @@ if (content) { html = htmlContent; } - return h(Fragment, null, h(Fragment, null,(html ? html : h(Fragment, null, h(__astro_slot, { [__astroContext]: props[__astroContext] }, children))))); -} -export default { isAstroComponent: true, __render }; - -// `__renderPage()`: Render the contents of the Astro module as a page. This is a special flow, -// triggered by loading a component directly by URL. -export async function __renderPage({request, children, props, css}) { - const currentChild = { - isAstroComponent: true, - layout: typeof __layout === 'undefined' ? undefined : __layout, - content: typeof __content === 'undefined' ? undefined : __content, - __render, - }; - - const isLayout = (__astroContext in props); - if(!isLayout) { - let astroRootUIDCounter = 0; - Object.defineProperty(props, __astroContext, { - value: { - pageCSS: css, - request, - createAstroRootUID(seed) { return seed + astroRootUIDCounter++; }, - }, - writable: false, - enumerable: false - }); - } - - Object.defineProperty(props, __astroInternal, { - value: { - isPage: !isLayout - }, - writable: false, - enumerable: false - }); - - const childBodyResult = await currentChild.__render(props, children); - - // find layout, if one was given. - if (currentChild.layout) { - return currentChild.layout({ - request, - props: {content: currentChild.content, [__astroContext]: props[__astroContext]}, - children: [childBodyResult], - }); - } - - return childBodyResult; -}; - - - +/* + If we have rendered `html` for `content`, render that + Otherwise, just render the slotted content +*/ +--- +{html ? html : } diff --git a/packages/astro/package.json b/packages/astro/package.json index 77b1499dc..2b304f5af 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -17,7 +17,8 @@ "./debug": "./components/Debug.astro", "./components/*": "./components/*", "./package.json": "./package.json", - "./runtime/*": "./dist/runtime/*" + "./runtime/*": "./dist/runtime/*.js", + "./internal": "./dist/internal/index.js" }, "imports": { "#astro/*": "./dist/*.js" @@ -35,9 +36,10 @@ "dev": "astro-scripts dev \"src/**/*.ts\"", "postbuild": "astro-scripts copy \"src/**/*.astro\"", "benchmark": "node test/benchmark/dev.bench.js && node test/benchmark/build.bench.js", - "test": "uvu test -i fixtures -i benchmark -i test-utils.js" + "test": "NODE_OPTIONS=--experimental-vm-modules jest" }, "dependencies": { + "@astrojs/compiler": "^0.1.0-canary.36", "@astrojs/markdown-support": "^0.3.1", "@babel/core": "^7.15.0", "@web/rollup-plugin-html": "^1.9.1", @@ -50,10 +52,12 @@ "es-module-lexer": "^0.7.1", "esbuild": "^0.12.23", "estree-util-value-to-estree": "^1.2.0", + "etag": "^1.8.1", "fast-xml-parser": "^3.19.0", "fdir": "^5.1.0", "kleur": "^4.1.4", "mime": "^2.5.2", + "morphdom": "^2.6.1", "node-fetch": "^2.6.1", "path-to-regexp": "^6.2.0", "picomatch": "^2.3.0", @@ -67,13 +71,14 @@ "source-map": "^0.7.3", "string-width": "^5.0.0", "supports-esm": "^1.0.0", - "vite": "^2.5.1", + "vite": "^2.5.2", "yargs-parser": "^20.2.9", "zod": "^3.8.1" }, "devDependencies": { "@types/babel__core": "^7.1.15", "@types/connect": "^3.4.35", + "@types/etag": "^1.8.1", "@types/mime": "^2.0.3", "@types/node-fetch": "^2.5.12", "@types/send": "^0.17.1", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index 07fbfdebd..762e3eca0 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -3,15 +3,16 @@ import type babel from '@babel/core'; import type vite from 'vite'; import type { z } from 'zod'; import type { AstroConfigSchema } from '../config'; +import type { AstroComponentFactory } from '../internal'; export { AstroMarkdownOptions }; export interface AstroComponentMetadata { displayName: string; hydrate?: 'load' | 'idle' | 'visible' | 'media' | 'only'; + hydrateArgs?: any; componentUrl?: string; componentExport?: { value: string; namespace?: boolean }; - value?: undefined | string; } /** @@ -140,12 +141,7 @@ export interface CollectionRSS { /** Generic interface for a component (Astro, Svelte, React, etc.) */ export interface ComponentInstance { - default: { - isAstroComponent: boolean; - __render?(props: Props, ...children: any[]): string; - __renderer?: Renderer; - }; - __renderPage?: (options: RenderPageOptions) => string; + default: AstroComponentFactory; css?: string[]; getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult; } diff --git a/packages/astro/src/@types/compiler.d.ts b/packages/astro/src/@types/compiler.d.ts new file mode 100644 index 000000000..213e1c503 --- /dev/null +++ b/packages/astro/src/@types/compiler.d.ts @@ -0,0 +1,45 @@ +declare module '@astrojs/compiler' { + export type Platform = 'browser' | 'node' | 'neutral'; + export type SourceMap = any; + + export interface TransformOptions {} + + export interface TransformResult { + code: string; + map: SourceMap; + warnings: any[]; + } + + export interface TransformResults { + js: TransformResult; + css?: TransformResult; + } + + // This function transforms a single JavaScript file. It can be used to minify + // JavaScript, convert TypeScript/JSX to JavaScript, or convert newer JavaScript + // to older JavaScript. It returns a promise that is either resolved with a + // "TransformResult" object or rejected with a "TransformFailure" object. + // + // Works in node: yes + // Works in browser: yes + export declare function transform(input: string, options?: TransformOptions): Promise; + + // This configures the browser-based version of astro. It is necessary to + // call this first and wait for the returned promise to be resolved before + // making other API calls when using astro in the browser. + // + // Works in node: yes + // Works in browser: yes ("options" is required) + export declare function initialize(options: InitializeOptions): Promise; + + export interface InitializeOptions { + // The URL of the "astro.wasm" file. This must be provided when running + // astro in the browser. + wasmURL?: string; + + // By default astro runs the WebAssembly-based browser API in a web worker + // to avoid blocking the UI thread. This can be disabled by setting "worker" + // to false. + worker?: boolean; + } +} diff --git a/packages/astro/src/build/index.ts b/packages/astro/src/build/index.ts index 3dac614d8..3967e8b57 100644 --- a/packages/astro/src/build/index.ts +++ b/packages/astro/src/build/index.ts @@ -75,7 +75,7 @@ class AstroBuilder { // static pages if (pathname) { allPages.push( - ssr({ filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({ + ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({ html, name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''), })) @@ -97,7 +97,7 @@ class AstroBuilder { // TODO: throw error if conflict staticPaths.paths.forEach((staticPath) => { allPages.push( - ssr({ filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then((html) => ({ + ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then((html) => ({ html, name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''), })) diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts index 647ecfec2..ec9862361 100644 --- a/packages/astro/src/cli/index.ts +++ b/packages/astro/src/cli/index.ts @@ -10,7 +10,7 @@ import { z } from 'zod'; import { defaultLogDestination } from '../logger.js'; import build from '../build/index.js'; import devServer from '../dev/index.js'; -import { preview } from '../preview/index.js'; +import preview from '../preview/index.js'; import { reload } from './reload.js'; import { formatConfigError, loadConfig } from '../config.js'; diff --git a/packages/astro/src/dev/index.ts b/packages/astro/src/dev/index.ts index 73819616a..1bec87310 100644 --- a/packages/astro/src/dev/index.ts +++ b/packages/astro/src/dev/index.ts @@ -1,13 +1,18 @@ import type { NextFunction } from 'connect'; import type http from 'http'; -import type { AstroConfig, ManifestData, RouteCache } from '../@types/astro'; +import type { AstroConfig, ManifestData, RouteCache, RouteData } from '../@types/astro'; import type { LogOptions } from '../logger'; +import type { HmrContext, ModuleNode } from 'vite'; import chokidar from 'chokidar'; import connect from 'connect'; import mime from 'mime'; +import getEtag from 'etag'; import { performance } from 'perf_hooks'; import { fileURLToPath } from 'url'; +import { createRequire } from 'module'; +import path from 'path'; +import { promises as fs } from 'fs'; import vite from 'vite'; import { defaultLogOptions, error, info } from '../logger.js'; import { createRouteManifest, matchRoute } from '../runtime/routing.js'; @@ -16,6 +21,8 @@ import { loadViteConfig } from '../runtime/vite/config.js'; import * as msg from './messages.js'; import { errorTemplate } from './template/error.js'; +const require = createRequire(import.meta.url); + export interface DevOptions { logging: LogOptions; } @@ -39,16 +46,18 @@ export default async function dev(config: AstroConfig, options: DevOptions = { l hostname: server.hostname, port: server.port, server: server.app, - stop: server.stop, + stop: () => server.stop(), }; } /** Dev server */ -class AstroDevServer { +export class AstroDevServer { app = connect(); + httpServer: http.Server | undefined; hostname: string; port: number; + private internalCache: Map; private config: AstroConfig; private logging: LogOptions; private manifest: ManifestData; @@ -56,8 +65,10 @@ class AstroDevServer { private routeCache: RouteCache = {}; private viteServer: vite.ViteDevServer | undefined; private watcher: chokidar.FSWatcher; + private mostRecentRoute?: RouteData; constructor(config: AstroConfig, options: DevOptions) { + this.internalCache = new Map(); this.config = config; this.hostname = config.devOptions.hostname || 'localhost'; this.logging = options.logging; @@ -94,7 +105,7 @@ class AstroDevServer { host: this.hostname, }, }, - { astroConfig: this.config, logging: this.logging } + { astroConfig: this.config, logging: this.logging, devServer: this } ); this.viteServer = await vite.createServer(viteConfig); @@ -104,27 +115,24 @@ class AstroDevServer { this.app.use((req, res, next) => this.renderError(req, res, next)); // 4. listen on port - await new Promise((resolve, reject) => { - this.app - .listen(this.port, this.hostname, () => { - info(this.logging, 'astro', msg.devStart({ startupTime: performance.now() - devStart })); - info(this.logging, 'astro', msg.devHost({ host: `http://${this.hostname}:${this.port}` })); - resolve(); - }) - .on('error', (err: NodeJS.ErrnoException) => { - if (err.code && err.code === 'EADDRINUSE') { - error(this.logging, 'astro', `Address ${this.hostname}:${this.port} already in use. Try changing devOptions.port in your config file`); - } else { - error(this.logging, 'astro', err.stack); - } - reject(); - process.exit(1); - }); + this.httpServer = this.app.listen(this.port, this.hostname, () => { + info(this.logging, 'astro', msg.devStart({ startupTime: performance.now() - devStart })); + info(this.logging, 'astro', msg.devHost({ host: `http://${this.hostname}:${this.port}` })); + }); + this.httpServer.on('error', (err: NodeJS.ErrnoException) => { + if (err.code && err.code === 'EADDRINUSE') { + error(this.logging, 'astro', `Address ${this.hostname}:${this.port} already in use. Try changing devOptions.port in your config file`); + } else { + error(this.logging, 'astro', err.stack); + } + process.exit(1); }); } /** Stop dev server */ async stop() { + this.internalCache = new Map(); + if (this.httpServer) this.httpServer.close(); // close HTTP server await Promise.all([ ...(this.viteServer ? [this.viteServer.close()] : []), // close Vite server this.watcher.close(), // close chokidar @@ -138,6 +146,13 @@ class AstroDevServer { let pathname = req.url || '/'; // original request const reqStart = performance.now(); + if (pathname.startsWith('/@astro')) { + const spec = pathname.slice(2); + const url = await this.viteServer.moduleGraph.resolveUrl(spec); + req.url = url[1]; + return this.viteServer.middlewares.handle(req, res, next); + } + try { const route = matchRoute(pathname, this.manifest); @@ -147,8 +162,11 @@ class AstroDevServer { return; } + this.mostRecentRoute = route; + // handle .astro and .md pages const html = await ssr({ + astroConfig: this.config, filePath: new URL(`./${route.component}`, this.config.projectRoot), logging: this.logging, mode: 'development', @@ -168,7 +186,7 @@ class AstroDevServer { } catch (e) { const err = e as Error; this.viteServer.ssrFixStacktrace(err); - console.error(err.stack); + console.log(err.stack); const statusCode = 500; const html = errorTemplate({ statusCode, title: 'Internal Error', tabTitle: '500: Error', message: err.message }); info(this.logging, 'astro', msg.req({ url: pathname, statusCode: 500, reqTime: performance.now() - reqStart })); @@ -195,6 +213,7 @@ class AstroDevServer { const userDefined404 = this.manifest.routes.find((route) => route.component === relPages + '404.astro'); if (userDefined404) { html = await ssr({ + astroConfig: this.config, filePath: new URL(`./${userDefined404.component}`, this.config.projectRoot), logging: this.logging, mode: 'development', @@ -216,4 +235,53 @@ class AstroDevServer { res.write(html); res.end(); } + + public async handleHotUpdate({ file, modules }: HmrContext): Promise { + if (!this.viteServer) throw new Error(`AstroDevServer.start() not called`); + + for (const module of modules) { + this.viteServer.moduleGraph.invalidateModule(module); + } + + const route = this.mostRecentRoute; + const pathname = route?.pathname ?? '/'; + + if (!route) { + this.viteServer.ws.send({ + type: 'full-reload', + }); + return []; + } + + try { + // try to update the most recent route + const html = await ssr({ + astroConfig: this.config, + filePath: new URL(`./${route.component}`, this.config.projectRoot), + logging: this.logging, + mode: 'development', + origin: this.origin, + pathname, + route, + routeCache: this.routeCache, + viteServer: this.viteServer, + }); + + // TODO: log update + this.viteServer.ws.send({ + type: 'custom', + event: 'astro:reload', + data: { html }, + }); + return []; + } catch (e) { + const err = e as Error; + this.viteServer.ssrFixStacktrace(err); + console.log(err.stack); + this.viteServer.ws.send({ + type: 'full-reload', + }); + return []; + } + } } diff --git a/packages/astro/src/dev/messages.ts b/packages/astro/src/dev/messages.ts index c3fc5b94c..725d9a0f8 100644 --- a/packages/astro/src/dev/messages.ts +++ b/packages/astro/src/dev/messages.ts @@ -15,6 +15,12 @@ export function req({ url, statusCode, reqTime }: { url: string; statusCode: num return `${color(statusCode)} ${pad(url, 40)} ${dim(Math.round(reqTime) + 'ms')}`; } +/** Display */ +export function reload({ url, reqTime }: { url: string; reqTime: number }): string { + let color = yellow; + return `${pad(url, 40)} ${dim(Math.round(reqTime) + 'ms')}`; +} + /** Display dev server host and startup time */ export function devStart({ startupTime }: { startupTime: number }): string { return `${pad(`Server started`, 44)} ${dim(`${Math.round(startupTime)}ms`)}`; diff --git a/packages/astro/src/internal/index.ts b/packages/astro/src/internal/index.ts new file mode 100644 index 000000000..5b9592d88 --- /dev/null +++ b/packages/astro/src/internal/index.ts @@ -0,0 +1,211 @@ +import type { AstroComponentMetadata } from '../@types/astro'; +import { renderAstroComponent } from '../runtime/ssr.js'; + +import { valueToEstree, Value } from 'estree-util-value-to-estree'; +import * as astring from 'astring'; +import shorthash from 'shorthash'; +const { generate, GENERATOR } = astring; +// A more robust version alternative to `JSON.stringify` that can handle most values +// see https://github.com/remcohaszing/estree-util-value-to-estree#readme +const customGenerator: astring.Generator = { + ...GENERATOR, + Literal(node, state) { + if (node.raw != null) { + // escape closing script tags in strings so browsers wouldn't interpret them as + // closing the actual end tag in HTML + state.write(node.raw.replace('', '<\\/script>')); + } else { + GENERATOR.Literal(node, state); + } + }, +}; +const serialize = (value: Value) => + generate(valueToEstree(value), { + generator: customGenerator, + }); + +async function _render(child: any) { + // Special: If a child is a function, call it automatically. + // This lets you do {() => ...} without the extra boilerplate + // of wrapping it in a function and calling it. + if (typeof child === 'function') { + return await child(); + } else if (typeof child === 'string') { + return child; + } else if (!child && child !== 0) { + // do nothing, safe to ignore falsey values. + } else { + return child; + } +} + +export class AstroComponent { + private htmlParts: string[]; + private expressions: TemplateStringsArray; + + constructor(htmlParts: string[], expressions: TemplateStringsArray) { + this.htmlParts = htmlParts; + this.expressions = expressions; + } + + *[Symbol.iterator]() { + const { htmlParts, expressions } = this; + + for (let i = 0; i < htmlParts.length; i++) { + const html = htmlParts[i]; + const expression = expressions[i]; + + yield _render(html); + yield _render(expression); + } + } +} + +export function render(htmlParts: string[], ...expressions: TemplateStringsArray) { + return new AstroComponent(htmlParts, expressions); +} + +export interface AstroComponentFactory { + (result: any, props: any, slots: any): ReturnType; + isAstroComponentFactory?: boolean; +} + +export const createComponent = (cb: AstroComponentFactory) => { + // Add a flag to this callback to mark it as an Astro component + (cb as any).isAstroComponentFactory = true; + return cb; +} + +function extractHydrationDirectives(inputProps: Record): { hydrationDirective: [string, any] | null; props: Record } { + let props: Record = {}; + let hydrationDirective: [string, any] | null = null; + for (const [key, value] of Object.entries(inputProps)) { + if (key.startsWith('client:')) { + hydrationDirective = [key.split(':')[1], value]; + } else { + props[key] = value; + } + } + return { hydrationDirective, props }; +} + +interface HydrateScriptOptions { + renderer: any; + astroId: string; + props: any; +} + +/** For hydrated components, generate a +`; + + return hydrationScript; +} + +export const renderComponent = async (result: any, displayName: string, Component: unknown, _props: Record, children: any) => { + Component = await Component; + // children = await renderGenerator(children); + const { renderers } = result._metadata; + if (Component && (Component as any).isAstroComponentFactory) { + const output = await renderAstroComponent(await (Component as any)(result, Component, _props, children)) + return output; + } + + let metadata: AstroComponentMetadata = { displayName }; + + if (Component == null) { + throw new Error(`Unable to render ${metadata.displayName} because it is ${Component}!\nDid you forget to import the component or is it possible there is a typo?`); + } + // else if (typeof Component === 'string' && !isCustomElementTag(Component)) { + // throw new Error(`Astro is unable to render ${metadata.displayName}!\nIs there a renderer to handle this type of component defined in your Astro config?`); + // } + const { hydrationDirective, props } = extractHydrationDirectives(_props); + let html = ''; + + if (!hydrationDirective) { + return '
Not implemented
'; + } + metadata.hydrate = hydrationDirective[0] as AstroComponentMetadata['hydrate']; + metadata.hydrateArgs = hydrationDirective[1]; + + for (const [url, exported] of Object.entries(result._metadata.importedModules)) { + for (const [key, value] of Object.entries(exported as any)) { + if (Component === value) { + metadata.componentExport = { value: key }; + metadata.componentUrl = url; + break; + } + } + } + + let renderer = null; + for (const r of renderers) { + if (await r.ssr.check(Component, props, null)) { + renderer = r; + } + } + + ({ html } = await renderer.ssr.renderToStaticMarkup(Component, props, null)); + const astroId = shorthash.unique(html); + + result.scripts.add(await generateHydrateScript({ renderer, astroId, props }, metadata as Required)); + + return `${html}`; +}; + +export const addAttribute = (value: any, key: string) => { + if (value == null || value === false) { + return ''; + } + return ` ${key}="${value}"`; +}; + +export const spreadAttributes = (values: Record) => { + let output = ''; + for (const [key, value] of Object.entries(values)) { + output += addAttribute(value, key); + } + return output; +}; + +export const defineStyleVars = (astroId: string, vars: Record) => { + let output = '\n'; + for (const [key, value] of Object.entries(vars)) { + output += ` --${key}: ${value};\n`; + } + return `.${astroId} {${output}}`; +}; + +export const defineScriptVars = (vars: Record) => { + let output = ''; + for (const [key, value] of Object.entries(vars)) { + output += `let ${key} = ${JSON.stringify(value)};\n`; + } + return output; +}; diff --git a/packages/astro/src/preview/index.ts b/packages/astro/src/preview/index.ts index 24d8873a8..69234c988 100644 --- a/packages/astro/src/preview/index.ts +++ b/packages/astro/src/preview/index.ts @@ -13,7 +13,7 @@ interface PreviewOptions { } /** The primary dev action */ -export async function preview(config: AstroConfig, { logging }: PreviewOptions) { +export default async function preview(config: AstroConfig, { logging }: PreviewOptions) { const { dist, devOptions: { hostname, port }, diff --git a/packages/astro/src/runtime/__astro_component.ts b/packages/astro/src/runtime/__astro_component.ts deleted file mode 100644 index a1f9080bb..000000000 --- a/packages/astro/src/runtime/__astro_component.ts +++ /dev/null @@ -1,242 +0,0 @@ -import type { AstroComponentMetadata, ComponentInstance, Renderer } from '../@types/astro'; - -import hash from 'shorthash'; -import { valueToEstree, Value } from 'estree-util-value-to-estree'; -import * as astring from 'astring'; -import * as astroHtml from './html.js'; - -const { generate, GENERATOR } = astring; - -// A more robust version alternative to `JSON.stringify` that can handle most values -// see https://github.com/remcohaszing/estree-util-value-to-estree#readme -const customGenerator: astring.Generator = { - ...GENERATOR, - Literal(node, state) { - if (node.raw != null) { - // escape closing script tags in strings so browsers wouldn't interpret them as - // closing the actual end tag in HTML - state.write(node.raw.replace('', '<\\/script>')); - } else { - GENERATOR.Literal(node, state); - } - }, -}; -const serialize = (value: Value) => - generate(valueToEstree(value), { - generator: customGenerator, - }); - -declare let rendererInstances: Renderer[]; - -function isCustomElementTag(name: unknown) { - return typeof name === 'string' && /-/.test(name); -} - -const rendererCache = new Map(); - -/** For client:only components, attempt to infer the required renderer. */ -function inferClientRenderer(metadata: Partial) { - // If there's only one renderer, assume it's the required renderer - if (rendererInstances.length === 1) { - return rendererInstances[0]; - } else if (metadata.value) { - // Attempt to find the renderer by matching the hydration value - const hint = metadata.value; - let match = rendererInstances.find((instance) => instance.name === hint); - - if (!match) { - // Didn't find an exact match, try shorthand hints for the internal renderers - const fullHintName = `@astrojs/renderer-${hint}`; - match = rendererInstances.find((instance) => instance.name === fullHintName); - } - - if (!match) { - throw new Error( - `Couldn't find a renderer for <${metadata.displayName} client:only="${metadata.value}" />. Is there a renderer that matches the "${metadata.value}" hint in your Astro config?` - ); - } - return match; - } else { - // Multiple renderers included but no hint was provided - throw new Error( - `Can't determine the renderer for ${metadata.displayName}. Include a hint similar to <${metadata.displayName} client:only="react" /> when multiple renderers are included in your Astro config.` - ); - } -} - -/** For a given component, resolve the renderer. Results are cached if this instance is encountered again */ -async function resolveRenderer(Component: any, props: any = {}, children?: string, metadata: Partial = {}): Promise { - // For client:only components, the component can't be imported - // during SSR. We need to infer the required renderer. - if (metadata.hydrate === 'only') { - return inferClientRenderer(metadata); - } - - if (rendererCache.has(Component)) { - return rendererCache.get(Component); - } - - const errors: Error[] = []; - for (const renderer of rendererInstances) { - // Yes, we do want to `await` inside of this loop! - // __renderer.check can't be run in parallel, it - // returns the first match and skips any subsequent checks - try { - const shouldUse: boolean = await renderer.ssr.check(Component, props, children); - - if (shouldUse) { - rendererCache.set(Component, renderer); - return renderer; - } - } catch (err) { - errors.push(err as any); - } - } - - if (errors.length) { - // For now just throw the first error we encounter. - throw errors[0]; - } -} - -interface HydrateScriptOptions { - renderer: Renderer; - astroId: string; - props: any; -} - -const astroHtmlRendererInstance: Renderer = { - name: '@astrojs/renderer-html', - source: '', - ssr: astroHtml as any, - polyfills: [], - hydrationPolyfills: [], -}; - -/** For hydrated components, generate a -`; - - return hydrationScript; -} - -const getComponentName = (Component: any, componentProps: any) => { - if (componentProps.displayName) return componentProps.displayName; - switch (typeof Component) { - case 'function': - return Component.displayName ?? Component.name; - case 'string': - return Component; - default: { - return Component; - } - } -}; - -const prepareSlottedChildren = (children: string | Record[]) => { - const $slots: Record = { - default: '', - }; - for (const child of children) { - if (typeof child === 'string') { - $slots.default += child; - } else if (typeof child === 'object' && child['$slot']) { - if (!$slots[child['$slot']]) $slots[child['$slot']] = ''; - $slots[child['$slot']] += child.children.join('').replace(new RegExp(`slot="${child['$slot']}"\s*`, '')); - } - } - - return { $slots }; -}; - -const removeSlottedChildren = (_children: string | Record[]) => { - let children = ''; - for (const child of _children) { - if (typeof child === 'string') { - children += child; - } else if (typeof child === 'object' && child['$slot']) { - children += child.children.join(''); - } - } - - return children; -}; - -/** The main wrapper for any components in Astro files */ -export function __astro_component(Component: ComponentInstance['default'], metadata: AstroComponentMetadata = {} as any) { - if (Component == null) { - throw new Error(`Unable to render ${metadata.displayName} because it is ${Component}!\nDid you forget to import the component or is it possible there is a typo?`); - } else if (typeof Component === 'string' && !isCustomElementTag(Component)) { - throw new Error(`Astro is unable to render ${metadata.displayName}!\nIs there a renderer to handle this type of component defined in your Astro config?`); - } - - return async function __astro_component_internal(props: any, ..._children: any[]) { - if (Component.isAstroComponent && Component.__render) { - return Component.__render(props, prepareSlottedChildren(_children)); - } - const children = removeSlottedChildren(_children); - let renderer = await resolveRenderer(Component, props, children, metadata); - - if (!renderer) { - if (isCustomElementTag(Component as any)) { - renderer = astroHtmlRendererInstance; - } else { - // If the user only specifies a single renderer, but the check failed - // for some reason... just default to their preferred renderer. - renderer = rendererInstances.length === 2 ? rendererInstances[1] : undefined; - } - - if (!renderer) { - const name = getComponentName(Component, metadata); - throw new Error(`No renderer found for ${name}! Did you forget to add a renderer to your Astro config?`); - } - } - - let html = ''; - // Skip SSR for components using client:only hydration - if (metadata.hydrate !== 'only') { - const rendered = await renderer.ssr.renderToStaticMarkup(Component, props, children, metadata); - html = rendered.html; - } - - if (renderer.polyfills) { - let polyfillScripts = renderer.polyfills.map((src: string) => ``).join(''); - html = html + polyfillScripts; - } - - // If we're NOT hydrating this component, just return the HTML - if (!metadata.hydrate) { - // It's safe to remove , static content doesn't need the wrapper - return html.replace(/\<\/?astro-fragment\>/g, ''); - } - - // If we ARE hydrating this component, let's generate the hydration script - const uniqueId = props[Symbol.for('astro.context')].createAstroRootUID(html); - const uniqueIdHashed = hash.unique(uniqueId); - const script = await generateHydrateScript({ renderer, astroId: uniqueIdHashed, props }, metadata as Required); - const astroRoot = `${html}`; - return [astroRoot, script].join('\n'); - }; -} diff --git a/packages/astro/src/runtime/hmr.ts b/packages/astro/src/runtime/hmr.ts new file mode 100644 index 000000000..c64ddb6d7 --- /dev/null +++ b/packages/astro/src/runtime/hmr.ts @@ -0,0 +1,33 @@ +import 'vite/client'; + +if (import.meta.hot) { + const parser = new DOMParser(); + import.meta.hot.on('astro:reload', async ({ html }: { html: string }) => { + const { default: morphdom } = await import('morphdom'); + const doc = parser.parseFromString(html, 'text/html'); + + morphdom(document.head, doc.head, { + onBeforeElUpdated: function (fromEl, toEl) { + if (fromEl.isEqualNode(toEl)) { + return false; + } + + return true; + }, + }); + + morphdom(document.body, doc.body, { + onBeforeElUpdated: function (fromEl, toEl) { + if (fromEl.localName === 'astro-root') { + return fromEl.getAttribute('uid') !== toEl.getAttribute('uid'); + } + + if (fromEl.isEqualNode(toEl)) { + return false; + } + + return true; + }, + }); + }); +} diff --git a/packages/astro/src/runtime/ssr.ts b/packages/astro/src/runtime/ssr.ts index af576ac77..26fc3964e 100644 --- a/packages/astro/src/runtime/ssr.ts +++ b/packages/astro/src/runtime/ssr.ts @@ -1,15 +1,19 @@ import cheerio from 'cheerio'; import * as eslexer from 'es-module-lexer'; import type { ViteDevServer } from 'vite'; -import type { ComponentInstance, GetStaticPathsResult, Params, Props, RouteCache, RouteData, RuntimeMode } from '../@types/astro'; +import type { ComponentInstance, GetStaticPathsResult, Params, Props, RouteCache, RouteData, RuntimeMode, AstroConfig } from '../@types/astro'; import type { LogOptions } from '../logger'; import { fileURLToPath } from 'url'; +import path from 'path'; import { generatePaginateFunction } from './paginate.js'; import { getParams, validateGetStaticPathsModule, validateGetStaticPathsResult } from './routing.js'; -import { canonicalURL, parseNpmName } from './util.js'; +import { parseNpmName, canonicalURL as getCanonicalURL } from './util.js'; +import type { AstroComponent, AstroComponentFactory } from '../internal'; interface SSROptions { + /** an instance of the AstroConfig */ + astroConfig: AstroConfig, /** location of file on disk */ filePath: URL; /** logging options */ @@ -32,11 +36,129 @@ interface SSROptions { // this prevents client-side errors such as the "double React bug" (https://reactjs.org/warnings/invalid-hook-call-warning.html#mismatching-versions-of-react-and-react-dom) let browserHash: string | undefined; +export async function renderAstroComponent(component: InstanceType) { + let template = ''; + + for await (const value of component) { + if (value || value === 0) { + template += value; + } + } + + return template; +} + +export async function renderToString(result: any, componentFactory: AstroComponentFactory, props: any, children: any) { + const Component = componentFactory(result, props, children); + let template = await renderAstroComponent(Component); + return template +} + +async function renderPage(result: any, Component: AstroComponentFactory, props: any, children: any) { + const template = await renderToString(result, Component, props, children); + const styles = Array.from(result.styles).map(style => ``); + const scripts = Array.from(result.scripts); + return template.replace("", styles.join('\n') + scripts.join('\n') + ""); +} + +const cache = new Map(); + +// TODO: improve validation and error handling here. +async function resolveRenderers(viteServer: ViteDevServer, ids: string[]) { + const resolve = viteServer.config.createResolver(); + const renderers = await Promise.all(ids.map(async renderer => { + if (cache.has(renderer)) return cache.get(renderer); + const resolvedRenderer: any = {}; + + // We can dynamically import the renderer by itself because it shouldn't have + // any non-standard imports, the index is just meta info. + // The other entrypoints need to be loaded through Vite. + const { default: instance } = await import(renderer); + + // This resolves the renderer's entrypoints to a final URL through Vite + const getPath = async (src: string) => { + const spec = path.posix.join(instance.name, src); + const resolved = await resolve(spec); + if (!resolved) { + throw new Error(`Unable to resolve "${spec}" to a package!`) + } + return resolved; + } + + resolvedRenderer.name = instance.name; + if (instance.client) { + resolvedRenderer.source = await getPath(instance.client); + } + if (Array.isArray(instance.hydrationPolyfills)) { + resolvedRenderer.hydrationPolyfills = await Promise.all(instance.hydrationPolyfills.map((src: string) => getPath(src))); + } + if (Array.isArray(instance.polyfills)) { + resolvedRenderer.polyfills = await Promise.all(instance.polyfills.map((src: string) => getPath(src))); + } + + const { url } = await viteServer.moduleGraph.ensureEntryFromUrl(await getPath(instance.server)); + const { default: server } = await viteServer.ssrLoadModule(url); + resolvedRenderer.ssr = server; + + cache.set(renderer, resolvedRenderer); + return resolvedRenderer + })); + + return renderers; +} + +async function resolveImportedModules(viteServer: ViteDevServer, file: string) { + const { url } = await viteServer.moduleGraph.ensureEntryFromUrl(file); + const modulesByFile = viteServer.moduleGraph.getModulesByFile(url); + if (!modulesByFile) { + return {}; + } + + let importedModules: Record = {}; + const moduleNodes = Array.from(modulesByFile); + + // Loop over the importedModules and grab the exports from each one. + // We'll pass these to the shared $$result so renderers can match + // components to their exported identifier and URL + // NOTE: Important that this is parallelized as much as possible! + await Promise.all(moduleNodes.map(moduleNode => { + const entries = Array.from(moduleNode.importedModules); + + return Promise.all(entries.map(entry => { + // Skip our internal import that every module will have + if (entry.id?.endsWith('astro/dist/internal/index.js')) { + return; + } + + return viteServer.moduleGraph.ensureEntryFromUrl(entry.url).then(mod => { + if (mod.ssrModule) { + importedModules[mod.url] = mod.ssrModule; + return; + } else { + return viteServer.ssrLoadModule(mod.url).then(result => { + importedModules[mod.url] = result.ssrModule; + return; + }) + } + }) + })) + })) + + return importedModules +} + /** use Vite to SSR */ -export async function ssr({ filePath, logging, mode, origin, pathname, route, routeCache, viteServer }: SSROptions): Promise { +export async function ssr({ astroConfig, filePath, logging, mode, origin, pathname, route, routeCache, viteServer }: SSROptions): Promise { // 1. load module const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance; + // 1.5. resolve renderers and imported modules. + // important that this happens _after_ ssrLoadModule, otherwise `importedModules` would be empty + const [renderers, importedModules] = await Promise.all([ + resolveRenderers(viteServer, astroConfig.renderers), + resolveImportedModules(viteServer, fileURLToPath(filePath)) + ]); + // 2. handle dynamic routes let params: Params = {}; let pageProps: Props = {}; @@ -68,24 +190,34 @@ export async function ssr({ filePath, logging, mode, origin, pathname, route, ro // 3. render page if (!browserHash && (viteServer as any)._optimizeDepsMetadata?.browserHash) browserHash = (viteServer as any)._optimizeDepsMetadata.browserHash; // note: this is "private" and may change over time const fullURL = new URL(pathname, origin); - if (!mod.__renderPage) throw new Error(`__renderPage() undefined (${route?.component})`); - let html = await mod.__renderPage({ - request: { - params, - url: fullURL, - canonicalURL: canonicalURL(fullURL.pathname, fullURL.origin), + + const Component = await mod.default; + if (!Component) + throw new Error(`Expected an exported Astro component but recieved typeof ${typeof Component}`); + if (!Component.isAstroComponentFactory) throw new Error(`Unable to SSR non-Astro component (${route?.component})`); + + let html = await renderPage({ + styles: new Set(), + scripts: new Set(), + /** This function returns the `Astro` faux-global */ + createAstro(props: any) { + const site = new URL(origin); + const url = new URL('.' + pathname, site); + const canonicalURL = getCanonicalURL(pathname, astroConfig.buildOptions.site || origin) + return { isPage: true, site, request: { url, canonicalURL }, props }; }, - children: [], - props: pageProps, - css: mod.css || [], - }); + _metadata: { importedModules, renderers }, + }, Component, { }, null); // 4. modify response - // inject Vite HMR code (dev only) - if (mode === 'development') html = injectViteClient(html); - - // replace client hydration scripts - if (mode === 'development') html = resolveNpmImports(html); + if (mode === 'development') { + // inject Astro HMR code + html = injectAstroHMR(html); + // inject Vite HMR code + html = injectViteClient(html); + // replace client hydration scripts + html = resolveNpmImports(html); + } // 5. finish return html; @@ -96,6 +228,11 @@ function injectViteClient(html: string): string { return html.replace('', ``); } +/** Injects Astro HMR client code */ +function injectAstroHMR(html: string): string { + return html.replace('', ``); +} + /** Convert npm specifier into Vite URL */ function resolveViteNpmPackage(spec: string): string { const pkg = parseNpmName(spec); diff --git a/packages/astro/src/runtime/vite/config.ts b/packages/astro/src/runtime/vite/config.ts index 69e7d800e..f5828ccde 100644 --- a/packages/astro/src/runtime/vite/config.ts +++ b/packages/astro/src/runtime/vite/config.ts @@ -10,6 +10,7 @@ import { createRequire } from 'module'; import { getPackageJSON, parseNpmName } from '../util.js'; import astro from './plugin-astro.js'; import jsx from './plugin-jsx.js'; +import { AstroDevServer } from '../../dev'; const require = createRequire(import.meta.url); @@ -17,7 +18,7 @@ const require = createRequire(import.meta.url); type ViteConfigWithSSR = InlineConfig & { ssr?: { external?: string[]; noExternal?: string[] } }; /** Return a common starting point for all Vite actions */ -export async function loadViteConfig(viteConfig: ViteConfigWithSSR, { astroConfig, logging }: { astroConfig: AstroConfig; logging: LogOptions }): Promise { +export async function loadViteConfig(viteConfig: ViteConfigWithSSR, { astroConfig, logging, devServer }: { astroConfig: AstroConfig; logging: LogOptions, devServer?: AstroDevServer }): Promise { const optimizedDeps = new Set(); // dependencies that must be bundled for the client (Vite may not detect all of these) const dedupe = new Set(); // dependencies that can’t be duplicated (e.g. React & SolidJS) const plugins: Plugin[] = []; // Vite plugins @@ -73,7 +74,7 @@ export async function loadViteConfig(viteConfig: ViteConfigWithSSR, { astroConfi /** Always include these dependencies for optimization */ include: [...optimizedDeps], }, - plugins: [astro(astroConfig), jsx({ config: astroConfig, logging }), ...plugins], + plugins: [astro({ config: astroConfig, devServer }), jsx({ config: astroConfig, logging }), ...plugins], publicDir: fileURLToPath(astroConfig.public), resolve: { dedupe: [...dedupe], @@ -82,6 +83,8 @@ export async function loadViteConfig(viteConfig: ViteConfigWithSSR, { astroConfi server: { /** prevent serving outside of project root (will become new default soon) */ fs: { strict: true }, + /** disable HMR for test */ + hmr: process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'production' ? false : undefined, /** handle Vite URLs */ proxy: { // add proxies here diff --git a/packages/astro/src/runtime/vite/plugin-astro.ts b/packages/astro/src/runtime/vite/plugin-astro.ts index 052ec7e31..a7996ae4d 100644 --- a/packages/astro/src/runtime/vite/plugin-astro.ts +++ b/packages/astro/src/runtime/vite/plugin-astro.ts @@ -1,58 +1,36 @@ import type { Plugin } from 'vite'; import type { AstroConfig, Renderer } from '../../@types/astro.js'; +import type { LogOptions } from '../../logger'; -import { camelCase } from 'camel-case'; +import esbuild from 'esbuild'; import fs from 'fs'; -import { fileURLToPath } from 'url'; -import { markdownToH } from '../markdown.js'; +import { transform } from '@astrojs/compiler'; +import { AstroDevServer } from '../../dev/index.js'; + +interface AstroPluginOptions { + config: AstroConfig; + devServer?: AstroDevServer; +} /** Transform .astro files for Vite */ -export default function astro(config: AstroConfig): Plugin { +export default function astro({ devServer }: AstroPluginOptions): Plugin { return { name: '@astrojs/vite-plugin-astro', enforce: 'pre', // run transforms before other plugins can // note: don’t claim .astro files with resolveId() — it prevents Vite from transpiling the final JS (import.meta.globEager, etc.) async load(id) { if (id.endsWith('.astro') || id.endsWith('.md')) { - // TODO: replace with compiler - let code = await fs.promises.readFile(id, 'utf8'); - return { - code: code, - map: null, - }; - } - // inject renderers (TODO: improve this?) - if (id.endsWith('runtime/__astro_component.js')) { - let code = await fs.promises.readFile(id, 'utf8'); - let rendererCode = ''; + let source = await fs.promises.readFile(id, 'utf8'); - // add imports - config.renderers.forEach((name) => { - rendererCode += `import ${jsRef(name)} from '${name}'; -import ${jsRef(name, '_ssr')} from '${name}/server'; -`; - }); + // 1. Transform from `.astro` to valid `.ts` + const tsResult = await transform(source, { sourcefile: id }); - // initialize renderers - rendererCode += ` -function initRenderer(name, entry, ssr) { - const join = (...parts) => parts.map((part) => part.replace(/^\\./, '')).join(''); - const renderer = {}; - renderer.name = name; - renderer.ssr = ssr; - if (entry.client) renderer.source = join(name, entry.client); - if (Array.isArray(entry.hydrationPolyfills)) renderer.hydrationPolyfills = entry.hydrationPolyfills.map((src) => join(name, src)); - if (Array.isArray(entry.polyfills)) renderer.polyfills = entry.polyfills.map((src) => join(name, src)); - return renderer; -} -let rendererInstances = [ - ${config.renderers.map((name) => `initRenderer('${name}', ${jsRef(name)}, ${jsRef(name, '_ssr')})`).join(',\n')} -]; -`; + // 2. Compile `.ts` to `.js` + const { code, map } = await esbuild.transform(tsResult, { loader: 'ts', sourcemap: 'inline', sourcefile: id }); return { - code: rendererCode + code, - map: null, + code, + map, }; } @@ -64,34 +42,10 @@ let rendererInstances = [ // } return null; }, - async handleHotUpdate({ file, modules, timestamp, server, read }) { - // invalidate module - const module = server.moduleGraph.getModuleById(file); - if (module) server.moduleGraph.invalidateModule(module); - - try { - const { - default: { __render: render }, - } = await server.ssrLoadModule(file); - const html = await render(); - server.ws.send({ - type: 'custom', - event: 'astro:reload', - data: { - html, - }, - }); - } catch (e) { - server.ws.send({ - type: 'full-reload', - }); + async handleHotUpdate(context) { + if (devServer) { + return devServer.handleHotUpdate(context); } - return []; }, }; } - -/** Given any string (e.g. npm package name), generate a JS-friendly ref */ -function jsRef(name: string, suffix = ''): string { - return `__${camelCase(name)}${suffix}`; -} diff --git a/packages/astro/test/astro-assets.test.js b/packages/astro/test/astro-assets.test.js index 52890dcf6..f1d78986c 100644 --- a/packages/astro/test/astro-assets.test.js +++ b/packages/astro/test/astro-assets.test.js @@ -1,20 +1,22 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import build from '../dist/build/index.js'; +import { loadFixture } from './test-utils'; -const Assets = suite('Assets'); +let fixture; -await build({ projectRoot: 'test/fixtures/astro-assets/' }); +describe('Assets', () => { + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-assets/' }); + await fixture.build(); + }); -Assets('build the base image', () => {}); + test('built the base image', async () => { + await fixture.readFile('/images/twitter.png'); + }); -// let oneX = await readFile('/_astro/src/images/twitter.png'); -// assert.ok(oneX, 'built the base image'); + test('built the 2x image', async () => { + await fixture.readFile('/images/twitter@2x.png'); + }); -// let twoX = await readFile('/_astro/src/images/twitter@2x.png'); -// assert.ok(twoX, 'built the 2x image'); - -// let threeX = await readFile('/_astro/src/images/twitter@3x.png'); -// assert.ok(threeX, 'build the 3x image'); - -Assets.run(); + test('built the 3x image', async () => { + await fixture.readFile('/images/twitter@3x.png'); + }); +}); diff --git a/packages/astro/test/astro-attrs.test.js b/packages/astro/test/astro-attrs.test.js index 7db6e7239..f9dccccdd 100644 --- a/packages/astro/test/astro-attrs.test.js +++ b/packages/astro/test/astro-attrs.test.js @@ -1,59 +1,62 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const Attributes = suite('Attributes test'); +let fixture; +let devServer; -setup(Attributes, './fixtures/astro-attrs'); +describe('Attributes', () => { + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-attrs/' }); + devServer = await fixture.dev(); + }); -Attributes('Passes attributes to elements as expected', async ({ runtime }) => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Passes attributes to elements as expected', async () => { + const html = await fixture.fetch('/').then((res) => res.html()); + const $ = cheerio.load(html); - const $ = doc(result.contents); + const attrs = { + 'false-str': 'false', + 'true-str': 'true', + false: undefined, + true: '', + empty: '', + null: undefined, + undefined: undefined, + }; - const ids = ['false-str', 'true-str', 'false', 'true', 'empty', 'null', 'undefined']; - const specs = ['false', 'true', undefined, '', '', undefined, undefined]; + for (const [k, v] of Object.entries(attrs)) { + const attr = $(`#${k}`).attr('attr'); + expect(attr).toBe(v); + } + }); - let i = 0; - for (const id of ids) { - const spec = specs[i]; - const attr = $(`#${id}`).attr('attr'); - assert.equal(attr, spec, `Passes ${id} as "${spec}"`); - i++; - } + test('Passes boolean attributes to components as expected', async () => { + const html = await fixture.fetch('/component').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('#true').attr('attr')).toBe('attr-true'); + expect($('#true').attr('type')).toBe('boolean'); + expect($('#false').attr('attr')).toBe('attr-false'); + expect($('#false').attr('type')).toBe('boolean'); + }); + + test('Passes namespaced attributes as expected', async () => { + const html = await fixture.fetch('/namespaced').then((res) => res.text()); + const $ = cheerio.load(result.contents); + + expect($('div').attr('xmlns:happy')).toBe('https://example.com/schemas/happy'); + expect($('img').attr('happy:smile')).toBe('sweet'); + }); + + test('Passes namespaced attributes to components as expected', async () => { + const html = await fixture.fetch('/namespaced-component'); + const $ = cheerio.load(html); + + expect($('span').attr('on:click')).toEqual(Function.prototype.toString.call((event) => console.log(event))); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.close(); + }); }); - -Attributes('Passes boolean attributes to components as expected', async ({ runtime }) => { - const result = await runtime.load('/component'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - assert.equal($('#true').attr('attr'), 'attr-true'); - assert.equal($('#true').attr('type'), 'boolean'); - assert.equal($('#false').attr('attr'), 'attr-false'); - assert.equal($('#false').attr('type'), 'boolean'); -}); - -Attributes('Passes namespaced attributes as expected', async ({ runtime }) => { - const result = await runtime.load('/namespaced'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - assert.equal($('div').attr('xmlns:happy'), 'https://example.com/schemas/happy'); - assert.equal($('img').attr('happy:smile'), 'sweet'); -}); - -Attributes('Passes namespaced attributes to components as expected', async ({ runtime }) => { - const result = await runtime.load('/namespaced-component'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - assert.equal( - $('span').attr('on:click'), - Function.prototype.toString.call((event) => console.log(event)) - ); -}); - -Attributes.run(); diff --git a/packages/astro/test/astro-basic.test.js b/packages/astro/test/astro-basic.test.js index 164db697b..e56337099 100644 --- a/packages/astro/test/astro-basic.test.js +++ b/packages/astro/test/astro-basic.test.js @@ -1,123 +1,109 @@ -import { suite } from 'uvu'; -import http from 'http'; -import { promisify } from 'util'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild, setupPreview } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const Basics = suite('Basic test'); +describe('Astro basics', () => { + describe('dev', () => { + let fixture; // fixture #1. Note that .dev() and .preview() share a port, so these fixtures must be kept separate. + let devServer; -setup(Basics, './fixtures/astro-basic', { - runtimeOptions: { - mode: 'development', - }, -}); -setupBuild(Basics, './fixtures/astro-basic'); -setupPreview(Basics, './fixtures/astro-basic'); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-basic/' }); + devServer = await fixture.dev(); + }); -Basics('Can load page', async ({ runtime }) => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can load page', async () => { + const html = await fixture.fetch(`/`).then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); + expect($('h1').text()).toBe('Hello world!'); + }); - assert.equal($('h1').text(), 'Hello world!'); -}); + test('Correctly serializes boolean attributes', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); -Basics('Sets the HMR port when dynamic components used', async ({ runtime }) => { - const result = await runtime.load('/client'); - const html = result.contents; - assert.ok(/HMR_WEBSOCKET_PORT/.test(html), 'Sets the websocket port'); -}); + expect($('h1').attr('data-something')).toBe(''); + expect($('h2').attr('not-data-ok')).toBe(''); + }); -Basics('Correctly serializes boolean attributes', async ({ runtime }) => { - const result = await runtime.load('/'); - const html = result.contents; - const $ = doc(html); - assert.equal($('h1').attr('data-something'), ''); - assert.equal($('h2').attr('not-data-ok'), ''); -}); + test('Selector with an empty body', async () => { + const html = await fixture.fetch('/empty-class').then((res) => res.text()); + const $ = cheerio.load(html); -Basics('Selector with an empty body', async ({ runtime }) => { - const result = await runtime.load('/empty-class'); - const html = result.contents; - const $ = doc(html); - assert.equal($('.author').length, 1, 'author class added'); -}); + expect($('.author')).toHaveLength(1); + }); -Basics('Build does not include HMR client', async ({ build, readFile }) => { - await build().catch((err) => { - assert.ok(!err, 'Error during the build'); + test('Allows forward-slashes in mustache tags (#407)', async () => { + const html = await fixture.fetch('/forward-slash').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('a[href="/post/one"]')).toHaveLength(1); + expect($('a[href="/post/two"]')).toHaveLength(1); + expect($('a[href="/post/three"]')).toHaveLength(1); + }); + + test('Allows spread attributes (#521)', async () => { + const html = await fixture.fetch('/spread').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('#spread-leading')).toHaveLength(1); + expect($('#spread-leading').attr('a')).toBe('0'); + expect($('#spread-leading').attr('b')).toBe('1'); + expect($('#spread-leading').attr('c')).toBe('2'); + + expect($('#spread-trailing')).toHaveLength(1); + expect($('#spread-trailing').attr('a')).toBe('0'); + expect($('#spread-trailing').attr('b')).toBe('1'); + expect($('#spread-trailing').attr('c')).toBe('2'); + }); + + test('Allows spread attributes with TypeScript (#521)', async () => { + const html = await fixture.fetch('/spread').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('#spread-ts')).toHaveLength(1); + expect($('#spread-ts').attr('a')).toBe('0'); + expect($('#spread-ts').attr('b')).toBe('1'); + expect($('#spread-ts').attr('c')).toBe('2'); + }); + + test('Allows using the Fragment element to be used', async () => { + const html = await fixture.fetch('/fragment').then((res) => res.text()); + const $ = cheerio.load(html); + + // will be 1 if element rendered correctly + expect($('#one')).toHaveLength(1); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); }); - const clientHTML = await readFile('/client/index.html'); - const $ = doc(clientHTML); - assert.equal($('script[src="/_snowpack/hmr-client.js"]').length, 0, 'No HMR client script'); - const hmrPortScript = $('script').filter((i, el) => { - return $(el) - .text() - .match(/window\.HMR_WEBSOCKET_PORT/); + describe('preview', () => { + let fixture; // fixture #2. Note that .dev() and .preview() share a port, so these fixtures must be kept separate. + let previewServer; + + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-basic' }); + await fixture.build(); + previewServer = await fixture.preview(); + }); + + test('returns 200 for valid URLs', async () => { + const result = fixture.fetch('/'); + expect(result.statusCode).toBe(200); + }); + + test('returns 404 for invalid URLs', async () => { + const result = fixture.fetch('/bad-url'); + expect(result.statusCode).toBe(404); + }); + + // important: close preview server (free up port and connection) + afterAll(() => { + previewServer.close(); + }); }); - assert.equal(hmrPortScript.length, 0, 'No script setting the websocket port'); }); - -Basics('Preview server works as expected', async ({ build, previewServer }) => { - await build().catch((err) => { - assert.ok(!err, 'Error during the build'); - }); - { - const resultOrError = await promisify(http.get)(`http://localhost:${previewServer.address().port}/`).catch((err) => err); - assert.equal(resultOrError.statusCode, 200); - } - { - const resultOrError = await promisify(http.get)(`http://localhost:${previewServer.address().port}/bad-url`).catch((err) => err); - assert.equal(resultOrError.statusCode, 404); - } -}); - -Basics('Allows forward-slashes in mustache tags (#407)', async ({ runtime }) => { - const result = await runtime.load('/forward-slash'); - const html = result.contents; - const $ = doc(html); - - assert.equal($('a[href="/post/one"]').length, 1); - assert.equal($('a[href="/post/two"]').length, 1); - assert.equal($('a[href="/post/three"]').length, 1); -}); - -Basics('Allows spread attributes (#521)', async ({ runtime }) => { - const result = await runtime.load('/spread'); - const html = result.contents; - const $ = doc(html); - - assert.equal($('#spread-leading').length, 1); - assert.equal($('#spread-leading').attr('a'), '0'); - assert.equal($('#spread-leading').attr('b'), '1'); - assert.equal($('#spread-leading').attr('c'), '2'); - - assert.equal($('#spread-trailing').length, 1); - assert.equal($('#spread-trailing').attr('a'), '0'); - assert.equal($('#spread-trailing').attr('b'), '1'); - assert.equal($('#spread-trailing').attr('c'), '2'); -}); - -Basics('Allows spread attributes with TypeScript (#521)', async ({ runtime }) => { - const result = await runtime.load('/spread'); - const html = result.contents; - const $ = doc(html); - - assert.equal($('#spread-ts').length, 1); - assert.equal($('#spread-ts').attr('a'), '0'); - assert.equal($('#spread-ts').attr('b'), '1'); - assert.equal($('#spread-ts').attr('c'), '2'); -}); - -Basics('Allows using the Fragment element to be used', async ({ runtime }) => { - const result = await runtime.load('/fragment'); - assert.ok(!result.error, 'No errors thrown'); - const html = result.contents; - const $ = doc(html); - assert.equal($('#one').length, 1, 'Element in a fragment rendered'); -}); - -Basics.run(); diff --git a/packages/astro/test/astro-children.test.js b/packages/astro/test/astro-children.test.js index 9bacbd217..05f11be9c 100644 --- a/packages/astro/test/astro-children.test.js +++ b/packages/astro/test/astro-children.test.js @@ -1,75 +1,81 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const ComponentChildren = suite('Component children tests'); +describe('Component children', () => { + let fixture; + let devServer; -setup(ComponentChildren, './fixtures/astro-children'); -setupBuild(ComponentChildren, './fixtures/astro-children'); + beforeAll(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/astro-children/', + renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-vue', '@astrojs/renderer-svelte'], + }); + devServer = await fixture.dev(); + }); -ComponentChildren('Passes string children to framework components', async ({ runtime }) => { - let result = await runtime.load('/strings'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Passes string children to framework components', async () => { + const html = await fixture.fetch('/strings').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); + // test 1: Can pass text to Preact components + const $preact = $('#preact'); + expect($preact.text().trim()).toBe('Hello world'); - const $preact = $('#preact'); - assert.equal($preact.text().trim(), 'Hello world', 'Can pass text to Preact components'); + // test 2: Can pass text to Vue components + const $vue = $('#vue'); + expect($vue.text().trim()).toBe('Hello world'); - const $vue = $('#vue'); - assert.equal($vue.text().trim(), 'Hello world', 'Can pass text to Vue components'); + // test 3: Can pass text to Svelte components + const $svelte = $('#svelte'); + expect($svelte.text().trim()).toBe('Hello world'); + }); - const $svelte = $('#svelte'); - assert.equal($svelte.text().trim(), 'Hello world', 'Can pass text to Svelte components'); + test('Passes markup children to framework components', async () => { + const html = await fixture.fetch('/markup').then((res) => res.text()); + const $ = cheerio.load(html); + + // test 1: Can pass markup to Preact components + const $preact = $('#preact h1'); + expect($preact.text().trim()).toBe('Hello world'); + + // test 2: Can pass markup to Vue components + const $vue = $('#vue h1'); + expect($vue.text().trim()).toBe('Hello world'); + + // test 3: Can pass markup to Svelte components + const $svelte = $('#svelte h1'); + expect($svelte.text().trim()).toBe('Hello world'); + }); + + test('Passes multiple children to framework components', async () => { + const html = await fixture.fetch('/multiple').then((res) => res.text()); + const $ = cheerio.load(html); + + // test 1: Can pass multiple children to Preact components + const $preact = $('#preact'); + expect($preact.children()).toHaveLength(2); + expect($preact.children(':first-child').text().trim()).toBe('Hello world'); + expect($preact.children(':last-child').text().trim()).toBe('Goodbye world'); + + // test 2: Can pass multiple children to Vue components + const $vue = $('#vue'); + expect($vue.children()).toHaveLength(2); + expect($vue.children(':first-child').text().trim()).toBe('Hello world'); + expect($vue.children(':last-child').text().trim()).toBe('Goodbye world'); + + // test 3: Can pass multiple children to Svelte components + const $svelte = $('#svelte'); + expect($svelte.children()).toHaveLength(2); + expect($svelte.children(':first-child').text().trim()).toBe('Hello world'); + expect($svelte.children(':last-child').text().trim()).toBe('Goodbye world'); + }); + + test('Can build a project with component children', async () => { + expect(() => fixture.build()).not.toThrow(); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.close(); + }); }); - -ComponentChildren('Passes markup children to framework components', async ({ runtime }) => { - let result = await runtime.load('/markup'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - - const $preact = $('#preact h1'); - assert.equal($preact.text().trim(), 'Hello world', 'Can pass markup to Preact components'); - - const $vue = $('#vue h1'); - assert.equal($vue.text().trim(), 'Hello world', 'Can pass markup to Vue components'); - - const $svelte = $('#svelte h1'); - assert.equal($svelte.text().trim(), 'Hello world', 'Can pass markup to Svelte components'); -}); - -ComponentChildren('Passes multiple children to framework components', async ({ runtime }) => { - let result = await runtime.load('/multiple'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - - const $preact = $('#preact'); - assert.equal($preact.children().length, 2, 'Can pass multiple children to Preact components'); - assert.equal($preact.children(':first-child').text().trim(), 'Hello world'); - assert.equal($preact.children(':last-child').text().trim(), 'Goodbye world'); - - const $vue = $('#vue'); - assert.equal($vue.children().length, 2, 'Can pass multiple children to Vue components'); - assert.equal($vue.children(':first-child').text().trim(), 'Hello world'); - assert.equal($vue.children(':last-child').text().trim(), 'Goodbye world'); - - const $svelte = $('#svelte'); - assert.equal($svelte.children().length, 2, 'Can pass multiple children to Svelte components'); - assert.equal($svelte.children(':first-child').text().trim(), 'Hello world'); - assert.equal($svelte.children(':last-child').text().trim(), 'Goodbye world'); -}); - -ComponentChildren('Can be built', async ({ build }) => { - try { - await build(); - assert.ok(true, 'Can build a project with component children'); - } catch (err) { - console.log(err); - assert.ok(false, 'build threw'); - } -}); - -ComponentChildren.run(); diff --git a/packages/astro/test/astro-client-only.test.js b/packages/astro/test/astro-client-only.test.js index 1c4534807..c3b2cc577 100644 --- a/packages/astro/test/astro-client-only.test.js +++ b/packages/astro/test/astro-client-only.test.js @@ -1,44 +1,43 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const ClientOnlyComponents = suite('Client only components tests'); +describe('Client only components', () => { + let fixture; + let devServer; -setup(ClientOnlyComponents, './fixtures/astro-client-only'); -setupBuild(ClientOnlyComponents, './fixtures/astro-client-only'); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-client-only/' }); + devServer = await fixture.dev(); + }); -ClientOnlyComponents('Loads pages using client:only hydrator', async ({ runtime }) => { - let result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Loads pages using client:only hydrator', async () => { + const html = await fixture.fetch('/').then((res) => res.html()); + const $ = cheerio.load(html); - let html = result.contents; + // test 1: is empty + expect($('astro-root').html()).toBe(''); - const rootExp = /]*><\/astro-root>/; - assert.ok(rootExp.exec(html), 'astro-root is empty'); - - // Grab the svelte import - const exp = /import\("(.+?)"\)/g; - let match, svelteRenderer; - while ((match = exp.exec(result.contents))) { - if (match[1].includes('renderers/renderer-svelte/client.js')) { - svelteRenderer = match[1]; + // test 2: svelte renderer is on the page + const exp = /import\("(.+?)"\)/g; + let match, svelteRenderer; + while ((match = exp.exec(result.contents))) { + if (match[1].includes('renderers/renderer-svelte/client.js')) { + svelteRenderer = match[1]; + } } - } + expect(svelteRenderer).toBeTruthy(); - assert.ok(svelteRenderer, 'Svelte renderer is on the page'); + // test 3: can load svelte renderer + result = await fixture.fetch(svelteRenderer); + expect(result.statusCode).toBe(200); + }); - result = await runtime.load(svelteRenderer); - assert.equal(result.statusCode, 200, 'Can load svelte renderer'); + test('Can build a project with svelte dynamic components', async () => { + expect(() => fixture.build()).not.toThrow(); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.close(); + }); }); - -ClientOnlyComponents('Can be built', async ({ build }) => { - try { - await build(); - assert.ok(true, 'Can build a project with svelte dynamic components'); - } catch (err) { - console.log(err); - assert.ok(false, 'build threw'); - } -}); - -ClientOnlyComponents.run(); diff --git a/packages/astro/test/astro-components.test.js b/packages/astro/test/astro-components.test.js index cc1f6b759..048a21f6e 100644 --- a/packages/astro/test/astro-components.test.js +++ b/packages/astro/test/astro-components.test.js @@ -1,53 +1,55 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const Components = suite('Components tests'); +describe('Components tests', () => { + let fixture; + let devServer; -setup(Components, './fixtures/astro-components'); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-components/' }); + devServer = await fixture.dev(); + }); -Components('Astro components are able to render framework components', async ({ runtime }) => { - let result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Astro components are able to render framework components', async () => { + const html = await fixture.fetch('/').then((res) => res.html()); + const $ = cheerio.load(html); - const $ = doc(result.contents); + // test 1: Renders Astro component + const $astro = $('#astro'); + expect($astro.children()).toHaveLength(3); - const $astro = $('#astro'); - assert.equal($astro.children().length, 3, 'Renders astro component'); + // test 2: Renders React component + const $react = $('#react'); + expect($react).not.toHaveLength(0); - const $react = $('#react'); - assert.not.type($react, 'undefined', 'Renders React component'); + // test 3: Renders Vue component + const $vue = $('#vue'); + expect($vue).not.toHaveLength(0); - const $vue = $('#vue'); - assert.not.type($vue, 'undefined', 'Renders Vue component'); + // test 4: Renders Svelte component + const $svelte = $('#svelte'); + expect($svelte).not.toHaveLength(0); + }); - const $svelte = $('#svelte'); - assert.not.type($svelte, 'undefined', 'Renders Svelte component'); + test('Allows Components defined in frontmatter', async () => { + const html = await fixture.fetch('/frontmatter-component').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('h1')).toHaveLength(1); + }); + + test('Still throws an error for undefined components', async () => { + const result = await fixture.fetch('/undefined-component'); + expect(result.statusCode).toBe(500); + }); + + test('Client attrs not added', async () => { + const html = await fixture.fetch('/client').then((res) => res.text()); + expect(html).not.toEqual(expect.stringMatching(/"client:load": true/)); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.close(); + }); }); - -Components('Allows Components defined in frontmatter', async ({ runtime }) => { - const result = await runtime.load('/frontmatter-component'); - const html = result.contents; - const $ = doc(html); - - assert.equal($('h1').length, 1); -}); - -Components('Allows variables named props', async ({ runtime }) => { - const result = await runtime.load('/props-shadowing'); - assert.equal(result.statusCode, 500); -}); - -Components('Still throws an error for undefined components', async ({ runtime }) => { - const result = await runtime.load('/undefined-component'); - assert.equal(result.statusCode, 500); -}); - -Components('Svelte component', async ({ runtime }) => { - const result = await runtime.load('/client'); - const html = result.contents; - assert.ok(!/"client:load": true/.test(html), 'Client attrs not added'); -}); - -Components.run(); diff --git a/packages/astro/test/astro-css-bundling.test.js b/packages/astro/test/astro-css-bundling.test.js index 2ae4db91f..78610116b 100644 --- a/packages/astro/test/astro-css-bundling.test.js +++ b/packages/astro/test/astro-css-bundling.test.js @@ -1,11 +1,5 @@ import cheerio from 'cheerio'; -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { setupBuild } from './helpers.js'; - -const CSSBundling = suite('CSS Bundling'); - -setupBuild(CSSBundling, './fixtures/astro-css-bundling'); +import { loadFixture } from './test-utils'; // note: the hashes should be deterministic, but updating the file contents will change hashes // be careful not to test that the HTML simply contains CSS, because it always will! filename and quanity matter here (bundling). @@ -18,70 +12,75 @@ const EXPECTED_CSS = { }; const UNEXPECTED_CSS = ['/_astro/components/nav.css', '../css/typography.css', '../css/colors.css', '../css/page-index.css', '../css/page-one.css', '../css/page-two.css']; -CSSBundling('Bundles CSS', async (context) => { - await context.build(); +describe('CSS Bundling', () => { + let fixture; - const builtCSS = new Set(); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/astro-css-bundling/' }); + await fixture.build(); + }); - // for all HTML files… - for (const [filepath, css] of Object.entries(EXPECTED_CSS)) { - const html = await context.readFile(filepath); - const $ = cheerio.load(html); + test('Bundles CSS', async () => { + const builtCSS = new Set(); - // test 1: assert new bundled CSS is present - for (const href of css) { - const link = $(`link[rel="stylesheet"][href^="${href}"]`); - assert.equal(link.length, 1, 'New bundled CSS is not present'); - builtCSS.add(link.attr('href')); + // for all HTML files… + for (const [filepath, css] of Object.entries(EXPECTED_CSS)) { + const html = await fixture.readFile(filepath); + const $ = cheerio.load(html); + + // test 1: assert new bundled CSS is present + for (const href of css) { + const link = $(`link[rel="stylesheet"][href^="${href}"]`); + expect(link).toHaveLength(1); + builtCSS.add(link.attr('href')); + } + + // test 2: assert old CSS was removed + for (const href of UNEXPECTED_CSS) { + const link = $(`link[rel="stylesheet"][href="${href}"]`); + expect(link).toHaveLength(0); + } + + // test 3: preload tags was not removed and attributes was preserved + if (filepath === '/preload/index.html') { + const stylesheet = $('link[rel="stylesheet"][href^="/_astro/preload/index-"]'); + const preload = $('link[rel="preload"][href^="/_astro/preload/index-"]'); + expect(stylesheet[0].attribs.media).toBe('print'); + expect(preload).toHaveLength(1); // Preload tag was removed + } + + // test 4: preload tags was not removed and attributes was preserved + if (filepath === '/preload-merge/index.html') { + const preload = $('link[rel="preload"]'); + expect(preload).toHaveLength(1); + } + + // test 5: assert all bundled CSS was built and contains CSS + for (const url of builtCSS.keys()) { + const css = await context.readFile(url); + expect(css).toBeTruthy(); + } + + // test 6: assert ordering is preserved (typography.css before colors.css) + const bundledLoc = [...builtCSS].find((k) => k.startsWith('/_astro/common-')); + const bundledContents = await context.readFile(bundledLoc); + const typographyIndex = bundledContents.indexOf('body{'); + const colorsIndex = bundledContents.indexOf(':root{'); + expect(typographyIndex).toBeLessThan(colorsIndex); + + // test 7: assert multiple style blocks were bundled (Nav.astro includes 2 scoped style blocks) + const scopedNavStyles = [...bundledContents.matchAll('.nav.astro-')]; + expect(scopedNavStyles).toHaveLength(2); + + // test 8: assert

Icons

- - + - - - - \ No newline at end of file + diff --git a/packages/astro/test/fixtures/astro-attrs/snowpack.config.json b/packages/astro/test/fixtures/astro-attrs/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-attrs/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-basic/snowpack.config.json b/packages/astro/test/fixtures/astro-basic/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-basic/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-children/astro.config.mjs b/packages/astro/test/fixtures/astro-children/astro.config.mjs deleted file mode 100644 index 2de93dc60..000000000 --- a/packages/astro/test/fixtures/astro-children/astro.config.mjs +++ /dev/null @@ -1,7 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact', - '@astrojs/renderer-vue', - '@astrojs/renderer-svelte', - ], -}; diff --git a/packages/astro/test/fixtures/astro-children/snowpack.config.json b/packages/astro/test/fixtures/astro-children/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-children/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-client-only/astro.config.mjs b/packages/astro/test/fixtures/astro-client-only/astro.config.mjs deleted file mode 100644 index 7e94b713a..000000000 --- a/packages/astro/test/fixtures/astro-client-only/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -export default { - buildOptions: { - sitemap: false, - }, - renderers: [ - '@astrojs/renderer-svelte', - ], -}; diff --git a/packages/astro/test/fixtures/astro-client-only/snowpack.config.json b/packages/astro/test/fixtures/astro-client-only/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-client-only/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-components/snowpack.config.json b/packages/astro/test/fixtures/astro-components/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-components/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-css-bundling/snowpack.config.json b/packages/astro/test/fixtures/astro-css-bundling/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-css-bundling/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-doctype/snowpack.config.json b/packages/astro/test/fixtures/astro-doctype/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-doctype/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-dynamic/astro.config.mjs b/packages/astro/test/fixtures/astro-dynamic/astro.config.mjs deleted file mode 100644 index 09731ba28..000000000 --- a/packages/astro/test/fixtures/astro-dynamic/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - buildOptions: { - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-dynamic/snowpack.config.json b/packages/astro/test/fixtures/astro-dynamic/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-dynamic/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-expr/astro.config.mjs b/packages/astro/test/fixtures/astro-expr/astro.config.mjs deleted file mode 100644 index 6c6bb575d..000000000 --- a/packages/astro/test/fixtures/astro-expr/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact' - ] -} diff --git a/packages/astro/test/fixtures/astro-expr/snowpack.config.json b/packages/astro/test/fixtures/astro-expr/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-expr/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-fallback/astro.config.mjs b/packages/astro/test/fixtures/astro-fallback/astro.config.mjs deleted file mode 100644 index 6c6bb575d..000000000 --- a/packages/astro/test/fixtures/astro-fallback/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact' - ] -} diff --git a/packages/astro/test/fixtures/astro-fallback/snowpack.config.json b/packages/astro/test/fixtures/astro-fallback/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-fallback/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-get-static-paths/astro.config.mjs b/packages/astro/test/fixtures/astro-get-static-paths/astro.config.mjs deleted file mode 100644 index c601c31ad..000000000 --- a/packages/astro/test/fixtures/astro-get-static-paths/astro.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - buildOptions: { - site: 'https://mysite.dev/blog/', - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-get-static-paths/snowpack.config.json b/packages/astro/test/fixtures/astro-get-static-paths/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-get-static-paths/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-global/astro.config.mjs b/packages/astro/test/fixtures/astro-global/astro.config.mjs deleted file mode 100644 index c601c31ad..000000000 --- a/packages/astro/test/fixtures/astro-global/astro.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - buildOptions: { - site: 'https://mysite.dev/blog/', - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-global/snowpack.config.json b/packages/astro/test/fixtures/astro-global/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-global/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-hmr/snowpack.config.json b/packages/astro/test/fixtures/astro-hmr/snowpack.config.json deleted file mode 100644 index 6fddc0add..000000000 --- a/packages/astro/test/fixtures/astro-hmr/snowpack.config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "workspaceRoot": "../../../../../", - "devOptions": { - "hmrPort": 5555 - } -} diff --git a/packages/astro/test/fixtures/astro-markdown-plugins/astro.config.mjs b/packages/astro/test/fixtures/astro-markdown-plugins/astro.config.mjs deleted file mode 100644 index 1e95e71e3..000000000 --- a/packages/astro/test/fixtures/astro-markdown-plugins/astro.config.mjs +++ /dev/null @@ -1,19 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact' - ], - markdownOptions: { - remarkPlugins: [ - 'remark-code-titles', - 'remark-slug', - ['rehype-autolink-headings', { behavior: 'prepend' }], - ], - rehypePlugins: [ - ['rehype-toc', { headings: ["h2", "h3"] }], - ['rehype-add-classes', { 'h1,h2,h3': 'title', }], - ] - }, - buildOptions: { - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-markdown-plugins/snowpack.config.json b/packages/astro/test/fixtures/astro-markdown-plugins/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-markdown-plugins/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-markdown/astro.config.mjs b/packages/astro/test/fixtures/astro-markdown/astro.config.mjs deleted file mode 100644 index d940a67c9..000000000 --- a/packages/astro/test/fixtures/astro-markdown/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact' - ], - buildOptions: { - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-markdown/snowpack.config.json b/packages/astro/test/fixtures/astro-markdown/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-markdown/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs b/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs deleted file mode 100644 index 309bb9d5a..000000000 --- a/packages/astro/test/fixtures/astro-page-directory-url/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - buildOptions: { - pageUrlFormat: 'file' - } -}; diff --git a/packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json b/packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-page-directory-url/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-pages/snowpack.config.json b/packages/astro/test/fixtures/astro-pages/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-pages/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-pagination/astro.config.mjs b/packages/astro/test/fixtures/astro-pagination/astro.config.mjs deleted file mode 100644 index c601c31ad..000000000 --- a/packages/astro/test/fixtures/astro-pagination/astro.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default { - buildOptions: { - site: 'https://mysite.dev/blog/', - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/astro-pagination/snowpack.config.json b/packages/astro/test/fixtures/astro-pagination/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-pagination/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-public/snowpack.config.json b/packages/astro/test/fixtures/astro-public/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-public/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-rss/astro.config.mjs b/packages/astro/test/fixtures/astro-rss/astro.config.mjs deleted file mode 100644 index c19ba79f1..000000000 --- a/packages/astro/test/fixtures/astro-rss/astro.config.mjs +++ /dev/null @@ -1,5 +0,0 @@ -export default { - buildOptions: { - site: 'https://mysite.dev', - }, -}; diff --git a/packages/astro/test/fixtures/astro-rss/snowpack.config.json b/packages/astro/test/fixtures/astro-rss/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-rss/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-scripts/snowpack.config.json b/packages/astro/test/fixtures/astro-scripts/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-scripts/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-slots/snowpack.config.json b/packages/astro/test/fixtures/astro-slots/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-slots/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-styles-ssr/snowpack.config.json b/packages/astro/test/fixtures/astro-styles-ssr/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-styles-ssr/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/astro-throw/snowpack.config.json b/packages/astro/test/fixtures/astro-throw/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/astro-throw/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/builtins-polyfillnode/snowpack.config.json b/packages/astro/test/fixtures/builtins-polyfillnode/snowpack.config.json deleted file mode 100644 index 3c503c831..000000000 --- a/packages/astro/test/fixtures/builtins-polyfillnode/snowpack.config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "workspaceRoot": "../../../../../", - "packageOptions": { - "polyfillNode": false - } -} diff --git a/packages/astro/test/fixtures/builtins/snowpack.config.json b/packages/astro/test/fixtures/builtins/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/builtins/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/config-port/astro.config.mjs b/packages/astro/test/fixtures/config-port/astro.config.mjs index 61858cdae..c4407033a 100644 --- a/packages/astro/test/fixtures/config-port/astro.config.mjs +++ b/packages/astro/test/fixtures/config-port/astro.config.mjs @@ -1,6 +1,5 @@ - export default { devOptions: { - port: 3001 + port: 5001 } -} \ No newline at end of file +} diff --git a/packages/astro/test/fixtures/custom-elements/astro.config.mjs b/packages/astro/test/fixtures/custom-elements/astro.config.mjs deleted file mode 100644 index bb82dbd14..000000000 --- a/packages/astro/test/fixtures/custom-elements/astro.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ - -export default { - renderers: [ - '@astrojs/test-custom-element-renderer' - ] -} \ No newline at end of file diff --git a/packages/astro/test/fixtures/custom-elements/snowpack.config.json b/packages/astro/test/fixtures/custom-elements/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/custom-elements/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/fetch/snowpack.config.json b/packages/astro/test/fixtures/fetch/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/fetch/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/lit-element/astro.config.mjs b/packages/astro/test/fixtures/lit-element/astro.config.mjs deleted file mode 100644 index 20f741ec6..000000000 --- a/packages/astro/test/fixtures/lit-element/astro.config.mjs +++ /dev/null @@ -1,17 +0,0 @@ -export default { - // projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project. - // pages: './src/pages', // Path to Astro components, pages, and data - // dist: './dist', // When running `astro build`, path to final static output - // public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing. - buildOptions: { - // site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs. - // sitemap: true, // Generate sitemap (set to "false" to disable) - }, - devOptions: { - // port: 3000, // The port to run the dev server on. - // tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js' - }, - renderers: [ - '@astrojs/renderer-lit' - ] -}; \ No newline at end of file diff --git a/packages/astro/test/fixtures/lit-element/snowpack.config.json b/packages/astro/test/fixtures/lit-element/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/lit-element/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/no-head-el/snowpack.config.json b/packages/astro/test/fixtures/no-head-el/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/no-head-el/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/plain-markdown/astro.config.mjs b/packages/astro/test/fixtures/plain-markdown/astro.config.mjs deleted file mode 100644 index d940a67c9..000000000 --- a/packages/astro/test/fixtures/plain-markdown/astro.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -export default { - renderers: [ - '@astrojs/renderer-preact' - ], - buildOptions: { - sitemap: false, - }, -}; diff --git a/packages/astro/test/fixtures/plain-markdown/snowpack.config.json b/packages/astro/test/fixtures/plain-markdown/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/plain-markdown/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/preact-component/snowpack.config.json b/packages/astro/test/fixtures/preact-component/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/preact-component/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/react-component/snowpack.config.json b/packages/astro/test/fixtures/react-component/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/react-component/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/fixtures/vue-component/snowpack.config.json b/packages/astro/test/fixtures/vue-component/snowpack.config.json deleted file mode 100644 index 8f034781d..000000000 --- a/packages/astro/test/fixtures/vue-component/snowpack.config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "workspaceRoot": "../../../../../" -} diff --git a/packages/astro/test/helpers.js b/packages/astro/test/helpers.js deleted file mode 100644 index 569a254cc..000000000 --- a/packages/astro/test/helpers.js +++ /dev/null @@ -1,175 +0,0 @@ -import { fileURLToPath } from 'url'; -import { build as astroBuild } from '#astro/build'; -import { preview as astroPreview } from '#astro/preview'; -import { readFileSync } from 'fs'; -import { createRuntime } from '#astro/runtime'; -import { loadConfig } from '#astro/config'; -import execa from 'execa'; -import del from 'del'; - -const MAX_STARTUP_TIME = 20000; // max time startup may take -const MAX_TEST_TIME = 10000; // max time an individual test may take -const MAX_SHUTDOWN_TIME = 3000; // max time shutdown() may take - -/** setup fixtures for tests */ - -/** - * @typedef {Object} SetupOptions - * @prop {import('../src/runtime').RuntimeOptions} runtimeOptions - */ - -/** - * @param {{}} Suite - * @param {string} fixturePath - * @param {SetupOptions} setupOptions - */ -export function setup(Suite, fixturePath, { runtimeOptions = {} } = {}) { - let runtime, createRuntimeError; - const timers = {}; - - Suite.before(async (context) => { - let timeout = setTimeout(() => { - throw new Error('Startup did not complete within allowed time'); - }, MAX_STARTUP_TIME); - - const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url))); - - runtime = await createRuntime(astroConfig, { - logging: { level: 'error' }, - ...runtimeOptions, - }).catch((err) => { - createRuntimeError = err; - }); - - if (createRuntimeError) { - setTimeout(() => { - throw createRuntimeError; - }); - } - - context.runtime = runtime; - - clearTimeout(timeout); - }); - - Suite.before.each(({ __test__ }) => { - if (timers[__test__]) throw new Error(`Test "${__test__}" already declared`); - timers[__test__] = setTimeout(() => { - throw new Error(`"${__test__}" did not finish within allowed time`); - }, MAX_TEST_TIME); - }); - - Suite.after(async () => { - let timeout = setTimeout(() => { - throw new Error('Shutdown did not complete within allowed time'); - }, MAX_SHUTDOWN_TIME); - - (await runtime) && runtime.shutdown(); - - clearTimeout(timeout); - }); - - Suite.after.each(({ __test__ }) => { - clearTimeout(timers[__test__]); - }); -} - -/** - * @param {{}} Suite - * @param {string} fixturePath - * @param {SetupOptions} setupOptions - */ -export function setupPreview(Suite, fixturePath, { runtimeOptions = {} } = {}) { - let server, createRuntimeError; - const timers = {}; - - Suite.before(async (context) => { - let timeout = setTimeout(() => { - throw new Error('Startup did not complete within allowed time'); - }, MAX_STARTUP_TIME); - - const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url))); - - server = await astroPreview(astroConfig).catch((err) => { - createRuntimeError = err; - }); - - if (createRuntimeError) { - setTimeout(() => { - throw createRuntimeError; - }); - } - - context.previewServer = server; - - clearTimeout(timeout); - }); - - Suite.before.each(({ __test__ }) => { - if (timers[__test__]) throw new Error(`Test "${__test__}" already declared`); - timers[__test__] = setTimeout(() => { - throw new Error(`"${__test__}" did not finish within allowed time`); - }, MAX_TEST_TIME); - }); - - Suite.after(async () => { - let timeout = setTimeout(() => { - throw new Error('Shutdown did not complete within allowed time'); - }, MAX_SHUTDOWN_TIME); - - server && server.close(); - - clearTimeout(timeout); - }); - - Suite.after.each(({ __test__ }) => { - clearTimeout(timers[__test__]); - }); -} - -export function setupBuild(Suite, fixturePath) { - const timers = {}; - - Suite.before(async (context) => { - let timeout = setTimeout(() => { - throw new Error('Startup did not complete within allowed time'); - }, MAX_STARTUP_TIME); - - const astroConfig = await loadConfig(fileURLToPath(new URL(fixturePath, import.meta.url))); - - context.build = () => astroBuild(astroConfig, { level: 'error' }); - context.readFile = async (path) => { - const resolved = fileURLToPath(new URL(path.replace(/^\//, ''), astroConfig.dist)); - return readFileSync(resolved, { encoding: 'utf8' }); - }; - - clearTimeout(timeout); - }); - - Suite.before.each(({ __test__ }) => { - if (timers[__test__]) throw new Error(`Test "${__test__}" already declared`); - timers[__test__] = setTimeout(() => { - throw new Error(`"${__test__}" did not finish within allowed time`); - }, MAX_TEST_TIME); - }); - - Suite.after(async () => { - // Shutdown i guess. - }); - - Suite.after.each(({ __test__ }) => { - clearTimeout(timers[__test__]); - }); -} - -const cliURL = new URL('../astro.mjs', import.meta.url); -export function runDevServer(root, additionalArgs = []) { - const args = [cliURL.pathname, 'dev', '--project-root', root.pathname].concat(additionalArgs); - const proc = execa('node', args); - return proc; -} - -export async function clearCache() { - const cacheDir = new URL('../../../node_modules/.cache', import.meta.url); - await del(fileURLToPath(cacheDir)); -} diff --git a/packages/astro/test/integration-docs.test.js b/packages/astro/test/integration-docs.test.js deleted file mode 100644 index 8a693f3c9..000000000 --- a/packages/astro/test/integration-docs.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import path from 'path'; -import glob from 'tiny-glob/sync.js'; -import { fileURLToPath } from 'url'; -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { setup } from './helpers.js'; - -const SnowpackDev = suite('docs.astro.build'); -setup(SnowpackDev, '../../../docs'); - -// convert file path to its final url -function formatURL(filepath) { - return filepath - .replace(/^\/?/, '/') // add / to beginning, if missing - .replace(/(index)?\.(astro|md)$/, '') // remove .astro and .md extensions - .replace(/\/$/, ''); // remove trailing slash, if any -} - -// declaring routes individually helps us run many quick tests rather than one giant slow test -const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '../../../docs/src/pages'); -let pages = glob('**/*.{astro,md}', { cwd: root, onlyFiles: true }).map(formatURL); - -SnowpackDev('Pages successfully scanned', () => { - assert.ok(pages.length > 0); -}); - -for (const pathname of pages) { - SnowpackDev(`Loads "${pathname}"`, async ({ runtime }) => { - const result = await runtime.load(pathname); - if (result.statusCode !== 200) { - console.error(result); - } - assert.equal(result.statusCode, 200); - return; - }); -} - -// Skipped on Node '14') { - SnowpackDev.run(); -} diff --git a/packages/astro/test/lit-element.test.js b/packages/astro/test/lit-element.test.js index 6f44d055e..d2abcbe85 100644 --- a/packages/astro/test/lit-element.test.js +++ b/packages/astro/test/lit-element.test.js @@ -1,44 +1,54 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const LitElement = suite('LitElement test'); +describe('LitElement test', () => { + let fixture; + let devServer; -setup(LitElement, './fixtures/lit-element'); + beforeAll(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/lit-element/', + renderers: ['@astrojs/renderer-lit'], + }); + devServer = await fixture.dev(); + }); -LitElement('Renders a custom element by tag name', async ({ runtime }) => { - // lit SSR is not currently supported on Node.js < 13 - if (process.versions.node <= '13') { - return; - } - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Renders a custom element by tag name', async () => { + // lit SSR is not currently supported on Node.js < 13 + if (process.versions.node <= '13') { + return; + } + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = doc(html); - const $ = doc(result.contents); + // test 1: attributes rendered + expect($('my-element').attr('foo')).toBe('bar'); - assert.equal($('my-element').attr('foo'), 'bar', 'attributes rendered'); - assert.ok($('my-element').html().includes(`
Testing...
`), 'shadow rendered'); + // test 2: shadow rendered + expect($('my-element').html()).toEqual(expect.stringContaining(`
Testing...
`)); + }); + + // Skipped because not supported by Lit + test.skip('Renders a custom element by the constructor', async () => { + const html = await fixture.fetch('/ctr').then((res) => res.text()); + const $ = doc(html); + + // test 1: attributes rendered + expect($('my-element').attr('foo')).toBe('bar'); + + // test 2: shadow rendered + expect($('my-element').html()).toEqual(expect.stringContaining(`
Testing...
`)); + }); + + afterAll(async () => { + // important: close dev server (free up port and connection) + await devServer.stop(); + + // The Lit renderer adds browser globals that interfere with other tests, so remove them now. + const globals = Object.keys(globalThis.window || {}); + globals.splice(globals.indexOf('global'), 1); + for (let name of globals) { + delete globalThis[name]; + } + }); }); - -// Skipped because not supported by Lit -LitElement.skip('Renders a custom element by the constructor', async ({ runtime }) => { - const result = await runtime.load('/ctr'); - assert.ok(!result.error, `build error: ${result.error}`); - - const $ = doc(result.contents); - - assert.equal($('my-element').attr('foo'), 'bar', 'attributes rendered'); - assert.ok($('my-element').html().includes(`
Testing...
`), 'shadow rendered'); -}); - -// The Lit renderer adds browser globals that interfere with other tests, so remove them now. -LitElement.after(() => { - const globals = Object.keys(globalThis.window || {}); - globals.splice(globals.indexOf('global'), 1); - for (let name of globals) { - delete globalThis[name]; - } -}); - -LitElement.run(); diff --git a/packages/astro/test/no-head-el.test.js b/packages/astro/test/no-head-el.test.js index d3c4d9fde..e5bf6ef71 100644 --- a/packages/astro/test/no-head-el.test.js +++ b/packages/astro/test/no-head-el.test.js @@ -1,28 +1,35 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const NoHeadEl = suite('Documents without a head'); +describe('Documents without a head', () => { + let fixture; + let devServer; -setup(NoHeadEl, './fixtures/no-head-el', { - runtimeOptions: { - mode: 'development', - }, + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/no-head-el/' }); + devServer = await fixture.dev(); + }); + + test('Places style and scripts before the first non-head element', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + + // test 1: Link to css placed after + expect($('title').next().is('link')).toBe(true); + + // test 2: Link for a child component + expect($('title').next().next().is('link')).toBe(true); + + // test 3: <astro-root> style placed after <link> + expect($('title').next().next().next().is('style')).toBe(true); + + // note(drew): commented-out with Vite now handling HMR + // assert.equal($('title').next().next().next().next().is('script'), true, 'HMR script after the style'); + // assert.equal($('script[src="/_snowpack/hmr-client.js"]').length, 1, 'Only the hmr client for the page'); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); }); - -NoHeadEl('Places style and scripts before the first non-head element', async ({ runtime }) => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); - - const html = result.contents; - const $ = doc(html); - assert.equal($('title').next().is('link'), true, 'Link to css placed after the title'); - assert.equal($('title').next().next().is('link'), true, 'Link for a child component'); - assert.equal($('title').next().next().next().is('style'), true, 'astro-root style placed after the link'); - assert.equal($('title').next().next().next().next().is('script'), true, 'HMR script after the style'); - - assert.equal($('script[src="/_snowpack/hmr-client.js"]').length, 1, 'Only the hmr client for the page'); -}); - -NoHeadEl.run(); diff --git a/packages/astro/test/plain-markdown.test.js b/packages/astro/test/plain-markdown.test.js index 7a2852af9..7f11da2d6 100644 --- a/packages/astro/test/plain-markdown.test.js +++ b/packages/astro/test/plain-markdown.test.js @@ -1,37 +1,51 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const Markdown = suite('Plain Markdown tests'); +describe('Plain Markdown tests', () => { + let fixture; -setup(Markdown, './fixtures/plain-markdown'); -setupBuild(Markdown, './fixtures/plain-markdown'); + beforeAll(async () => { + fixture = await loadFixture({ + projectRoot: './fixtures/markdown-plain/', + buildOptions: { + sitemap: false, + }, + renderers: ['@astrojs/renderer-preact'], + }); + }); -Markdown('Can load a simple markdown page with Astro', async ({ runtime }) => { - const result = await runtime.load('/post'); + describe('dev', () => { + let devServer; - assert.equal(result.statusCode, 200); + beforeAll(async () => { + devServer = await fixture.dev(); + }); - const $ = doc(result.contents); + test('Can load a simple markdown page with Astro', async () => { + const html = await fixture.fetch('/post').then((res) => res.text()); + const $ = cheerio.load(html); - assert.equal($('p').first().text(), 'Hello world!'); - assert.equal($('#first').text(), 'Some content'); - assert.equal($('#interesting-topic').text(), 'Interesting Topic'); + expect($('p').first().text()).toBe('Hello world!'); + expect($('#first').text()).toBe('Some content'); + expect($('#interesting-topic').text()).toBe('Interesting Topic'); + }); + + test('Can load a realworld markdown page with Astro', async () => { + const html = await fixture.fetch('/realworld').then((res) => res.text()); + const $ = cheerio.load(html); + + expect($('pre')).toHaveLength(7); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); + }); + + describe('build', () => { + test('Builds markdown pages for prod', () => { + expect(() => fixture.build()).not.toThrow(); + }); + }); }); - -Markdown('Can load a realworld markdown page with Astro', async ({ runtime }) => { - const result = await runtime.load('/realworld'); - assert.ok(!result.error, `build error: ${result.error}`); - - assert.equal(result.statusCode, 200); - const $ = doc(result.contents); - - assert.equal($('pre').length, 7); -}); - -Markdown('Builds markdown pages for prod', async (context) => { - await context.build(); -}); - -Markdown.run(); diff --git a/packages/astro/test/preact-component.test.js b/packages/astro/test/preact-component.test.js index 021b7e8a5..64b6c6bc5 100644 --- a/packages/astro/test/preact-component.test.js +++ b/packages/astro/test/preact-component.test.js @@ -1,77 +1,84 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const PreactComponent = suite('Preact component test'); +describe('Preact component', () => { + let fixture; + let devServer; -setup(PreactComponent, './fixtures/preact-component'); -setupBuild(PreactComponent, './fixtures/preact-component'); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/preact-component/' }); + devServer = await fixture.dev(); + }); -PreactComponent('Can load class component', async ({ runtime }) => { - const result = await runtime.load('/class'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can load class component', async () => { + const html = await fixture.fetch('/class').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - assert.equal($('#class-component').length, 1, 'Can use class components'); -}); + // test 1: Can use class components + expect($('#class-component')).toHaveLength(1); + }); -PreactComponent('Can load function component', async ({ runtime }) => { - const result = await runtime.load('/fn'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can load function component', async () => { + const html = await fixture.fetch('/fn').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - assert.equal($('#fn-component').length, 1, 'Can use function components'); - assert.equal($('#arrow-fn-component').length, 1, 'Can use function components'); -}); + // test 1: Can use function components + expect($('#fn-component')).toHaveLength(1); + // test 2: Can use function components + expect($('#arrow-fn-component')).toHaveLength(1); + }); -PreactComponent('Can load TS component', async ({ runtime }) => { - const result = await runtime.load('/ts-components'); - assert.ok(!result.error, `build error: ${result.error}`); - const $ = doc(result.contents); - assert.equal($('.ts-component').length, 1, 'Can use TS components'); -}); + test('Can load TS component', async () => { + const html = await fixture.fetch('/ts-components').then((res) => res.text()); + const $ = cheerio.load(html); -PreactComponent('Can use hooks', async ({ runtime }) => { - const result = await runtime.load('/hooks'); - assert.ok(!result.error, `build error: ${result.error}`); + // test 1: Can use TS components + expect($('.ts-component')).toHaveLength(1); + }); - const $ = doc(result.contents); - assert.equal($('#world').length, 1); -}); + test('Can use hooks', async () => { + const html = await fixture.fetch('/hooks').then((res) => res.text()); + const $ = cheerio.load(html); + expect($('#world')).toHaveLength(1); + }); -PreactComponent('Can export a Fragment', async ({ runtime }) => { - const result = await runtime.load('/frag'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can export a Fragment', async () => { + const html = await fixture.fetch('/frag').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - assert.equal($('body').children().length, 0, "nothing rendered but it didn't throw."); -}); + // test 1: nothing rendered but it didn’t throw + expect($('body').children()).toHaveLength(0); + }); -PreactComponent('Can use a pragma comment', async ({ runtime }) => { - const result = await runtime.load('/pragma-comment'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can use a pragma comment', async () => { + const html = await fixture.fetch('/pragma-comment').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.'); -}); + // test 1: rendered the PragmaComment component + expect($('.pragma-comment')).toHaveLength(2); + }); -PreactComponent('Uses the new JSX transform', async ({ runtime }) => { - const result = await runtime.load('/pragma-comment'); + test('Uses the new JSX transform', async () => { + const html = await fixture.fetch('/pragma-comment').then((res) => res.text()); - // Grab the imports - const exp = /import\("(.+?)"\)/g; - let match, componentUrl; - while ((match = exp.exec(result.contents))) { - if (match[1].includes('PragmaComment.js')) { - componentUrl = match[1]; - break; + // Grab the imports + const exp = /import\("(.+?)"\)/g; + let match, componentUrl; + while ((match = exp.exec(html))) { + if (match[1].includes('PragmaComment.js')) { + componentUrl = match[1]; + break; + } } - } - const component = await runtime.load(componentUrl); - const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime')); + const component = await fixture.fetch(componentUrl).then((res) => res.text()); + const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime')); - assert.ok(jsxRuntime, 'preact/jsx-runtime is used for the component'); + // test 1: preact/jsx-runtime is used for the component + expect(jsxRuntime).toBeTruthy(); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); }); - -PreactComponent.run(); diff --git a/packages/astro/test/react-component.test.js b/packages/astro/test/react-component.test.js index 6bfde0d25..8edcea271 100644 --- a/packages/astro/test/react-component.test.js +++ b/packages/astro/test/react-component.test.js @@ -1,104 +1,98 @@ -import { fileURLToPath } from 'url'; -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { createRuntime } from '#astro/runtime'; -import { loadConfig } from '#astro/config'; -import { doc } from './test-utils.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const React = suite('React Components'); +describe('React Components', () => { + let fixture; + let devServer; -let runtime, setupError; + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/react-component/' }); + devServer = await fixture.dev(); + }); -React.before(async () => { - const astroConfig = await loadConfig(fileURLToPath(new URL('./fixtures/react-component', import.meta.url))); + test('Can load React', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); - const logging = { - level: 'error', - dest: process.stderr, - }; + // test 1: basic component renders + expect($('#react-h2').text()).toBe('Hello world!'); - try { - runtime = await createRuntime(astroConfig, { logging }); - } catch (err) { - console.error(err); - setupError = err; - } -}); + // test 2: no reactroot + expect($('#react-h2').attr('data-reactroot')).toBe(undefined); -React.after(async () => { - (await runtime) && runtime.shutdown(); -}); + // test 3: Can use function components + expect($('#arrow-fn-component')).toHaveLength(1); -React('No error creating the runtime', () => { - assert.equal(setupError, undefined); -}); + // test 4: Can use spread for components + expect($('#component-spread-props')).toHaveLength(1); -React('Can load React', async () => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + // test 5: spread props renders + expect($('#component-spread-props').text(), 'Hello world!'); - const $ = doc(result.contents); - assert.equal($('#react-h2').text(), 'Hello world!'); - assert.equal($('#react-h2').attr('data-reactroot'), undefined, 'no reactroot'); - assert.equal($('#arrow-fn-component').length, 1, 'Can use function components'); - assert.equal($('#component-spread-props').length, 1, 'Can use spread for components'); - assert.equal($('#component-spread-props').text(), 'Hello world!'); - assert.equal($('.ts-component').length, 1, 'Can use TS components'); -}); + // test 6: Can use TS components + expect($('.ts-component')).toHaveLength(1); + }); -React('Includes reactroot on hydrating components', async () => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Includes reactroot on hydrating components', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - const div = $('#research'); - assert.equal(div.attr('data-reactroot'), '', 'Has the hydration attr'); - assert.equal(div.html(), 'foo bar <!-- -->1'); -}); + const div = $('#research'); -React('Throws helpful error message on window SSR', async () => { - const result = await runtime.load('/window'); - assert.match( - result.error.toString('utf8'), - `[/window] + // test 1: has the hydration attr + expect(div.attr('data-reactroot')).toBeTruthy(); + + // test 2: renders correctly + expect(div.html()).toBe('foo bar <!-- -->1'); + }); + + test('Throws helpful error message on window SSR', async () => { + const html = await fixture.fetch('/window').then((res) => res.text()); + expect(html).toEqual( + expect.stringContaining( + `[/window] The window object is not available during server-side rendering (SSR). Try using \`import.meta.env.SSR\` to write SSR-friendly code. https://docs.astro.build/reference/api-reference/#importmeta` - ); -}); + ) + ); + }); -React('Can load Vue', async () => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can load Vue', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); + expect($('#vue-h2').text()).toBe('Hasta la vista, baby'); + }); - const $ = doc(result.contents); - assert.equal($('#vue-h2').text(), 'Hasta la vista, baby'); -}); + test('Can use a pragma comment', async () => { + const html = await fixture.fetch('/pragma-comment').then((res) => res.text()); + const $ = cheerio.load(html); -React('Can use a pragma comment', async () => { - const result = await runtime.load('/pragma-comment'); - assert.ok(!result.error, `build error: ${result.error}`); - const $ = doc(result.contents); - assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.'); -}); + // test 1: rendered the PragmaComment component + expect($('.pragma-comment')).toHaveLength(2); + }); -React('uses the new JSX transform', async () => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('uses the new JSX transform', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); - // Grab the imports - const exp = /import\("(.+?)"\)/g; - let match, componentUrl; - while ((match = exp.exec(result.contents))) { - if (match[1].includes('Research.js')) { - componentUrl = match[1]; - break; + // Grab the imports + const exp = /import\("(.+?)"\)/g; + let match, componentUrl; + while ((match = exp.exec(html))) { + if (match[1].includes('Research.js')) { + componentUrl = match[1]; + break; + } } - } - const component = await runtime.load(componentUrl); - const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime')); + const component = await fixture.fetch(componentUrl).then((res) => res.text()); + const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime')); - assert.ok(jsxRuntime, 'react/jsx-runtime is used for the component'); + // test 1: react/jsx-runtime is used for the component + expect(jsxRuntime).toBeTruthy(); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); }); - -React.run(); diff --git a/packages/astro/test/route-manifest.test.js b/packages/astro/test/route-manifest.test.js index 7f110bba6..afdc881f7 100644 --- a/packages/astro/test/route-manifest.test.js +++ b/packages/astro/test/route-manifest.test.js @@ -1,12 +1,10 @@ import { fileURLToPath } from 'url'; -import { test } from 'uvu'; -import * as assert from 'uvu/assert'; -import { createManifest } from '../dist/manifest/create.js'; +import { createRouteManifest } from '../dist/runtime/routing.js'; const cwd = new URL('./fixtures/route-manifest/', import.meta.url); const create = (dir, trailingSlash) => { - return createManifest({ + return createRouteManifest({ config: { projectRoot: cwd, pages: new URL(dir, cwd), @@ -24,199 +22,185 @@ function cleanRoutes(routes) { }); } -test('creates routes with trailingSlashes = always', () => { - const { routes } = create('basic', 'always'); - assert.equal(cleanRoutes(routes), [ - { - type: 'page', - pattern: /^\/$/, - params: [], - component: 'basic/index.astro', - path: '/', - }, +describe('route manifest', () => { + test('creates routes with trailingSlashes = always', () => { + const { routes } = create('basic', 'always'); + expect(cleanRoutes(routes)).toEqual([ + { + type: 'page', + pattern: /^\/$/, + params: [], + component: 'basic/index.astro', + pathname: '/', + }, - { - type: 'page', - pattern: /^\/about\/$/, - params: [], - component: 'basic/about.astro', - path: '/about', - }, + { + type: 'page', + pattern: /^\/about\/$/, + params: [], + component: 'basic/about.astro', + pathname: '/about', + }, - { - type: 'page', - pattern: /^\/blog\/$/, - params: [], - component: 'basic/blog/index.astro', - path: '/blog', - }, + { + type: 'page', + pattern: /^\/blog\/$/, + params: [], + component: 'basic/blog/index.astro', + pathname: '/blog', + }, - { - type: 'page', - pattern: /^\/blog\/([^/]+?)\/$/, - params: ['slug'], - component: 'basic/blog/[slug].astro', - path: null, - }, - ]); -}); + { + type: 'page', + pattern: /^\/blog\/([^/]+?)\/$/, + params: ['slug'], + component: 'basic/blog/[slug].astro', + pathname: undefined, + }, + ]); + }); -test('creates routes with trailingSlashes = never', () => { - const { routes } = create('basic', 'never'); - assert.equal(cleanRoutes(routes), [ - { - type: 'page', - pattern: /^\/$/, - params: [], - component: 'basic/index.astro', - path: '/', - }, + test('creates routes with trailingSlashes = never', () => { + const { routes } = create('basic', 'never'); + expect(cleanRoutes(routes)).toEqual([ + { + type: 'page', + pattern: /^\/$/, + params: [], + component: 'basic/index.astro', + pathname: '/', + }, - { - type: 'page', - pattern: /^\/about$/, - params: [], - component: 'basic/about.astro', - path: '/about', - }, + { + type: 'page', + pattern: /^\/about$/, + params: [], + component: 'basic/about.astro', + pathname: '/about', + }, - { - type: 'page', - pattern: /^\/blog$/, - params: [], - component: 'basic/blog/index.astro', - path: '/blog', - }, + { + type: 'page', + pattern: /^\/blog$/, + params: [], + component: 'basic/blog/index.astro', + pathname: '/blog', + }, - { - type: 'page', - pattern: /^\/blog\/([^/]+?)$/, - params: ['slug'], - component: 'basic/blog/[slug].astro', - path: null, - }, - ]); -}); + { + type: 'page', + pattern: /^\/blog\/([^/]+?)$/, + params: ['slug'], + component: 'basic/blog/[slug].astro', + pathname: undefined, + }, + ]); + }); -test('creates routes with trailingSlashes = ignore', () => { - const { routes } = create('basic', 'ignore'); - assert.equal(cleanRoutes(routes), [ - { - type: 'page', - pattern: /^\/$/, - params: [], - component: 'basic/index.astro', - path: '/', - }, + test('creates routes with trailingSlashes = ignore', () => { + const { routes } = create('basic', 'ignore'); + expect(cleanRoutes(routes)).toEqual([ + { + type: 'page', + pattern: /^\/$/, + params: [], + component: 'basic/index.astro', + pathname: '/', + }, - { - type: 'page', - pattern: /^\/about\/?$/, - params: [], - component: 'basic/about.astro', - path: '/about', - }, + { + type: 'page', + pattern: /^\/about\/?$/, + params: [], + component: 'basic/about.astro', + pathname: '/about', + }, - { - type: 'page', - pattern: /^\/blog\/?$/, - params: [], - component: 'basic/blog/index.astro', - path: '/blog', - }, + { + type: 'page', + pattern: /^\/blog\/?$/, + params: [], + component: 'basic/blog/index.astro', + pathname: '/blog', + }, - { - type: 'page', - pattern: /^\/blog\/([^/]+?)\/?$/, - params: ['slug'], - component: 'basic/blog/[slug].astro', - path: null, - }, - ]); -}); + { + type: 'page', + pattern: /^\/blog\/([^/]+?)\/?$/, + params: ['slug'], + component: 'basic/blog/[slug].astro', + pathname: undefined, + }, + ]); + }); -test('encodes invalid characters', () => { - const { routes } = create('encoding', 'always'); + test('encodes invalid characters', () => { + const { routes } = create('encoding', 'always'); - // had to remove ? and " because windows + // had to remove ? and " because windows - // const quote = 'encoding/".astro'; - const hash = 'encoding/#.astro'; - // const question_mark = 'encoding/?.astro'; + // const quote = 'encoding/".astro'; + const hash = 'encoding/#.astro'; + // const question_mark = 'encoding/?.astro'; - assert.equal( - routes.map((p) => p.pattern), - [ + expect(routes.map((p) => p.pattern)).toEqual([ // /^\/%22$/, /^\/%23\/$/, // /^\/%3F$/ - ] - ); -}); + ]); + }); -test('ignores files and directories with leading underscores', () => { - const { routes } = create('hidden-underscore', 'always'); + test('ignores files and directories with leading underscores', () => { + const { routes } = create('hidden-underscore', 'always'); - assert.equal(routes.map((r) => r.component).filter(Boolean), ['hidden-underscore/index.astro', 'hidden-underscore/e/f/g/h.astro']); -}); + expect(routes.map((r) => r.component).filter(Boolean)).toEqual(['hidden-underscore/index.astro', 'hidden-underscore/e/f/g/h.astro']); + }); -test('ignores files and directories with leading dots except .well-known', () => { - const { routes } = create('hidden-dot', 'always'); + test('ignores files and directories with leading dots except .well-known', () => { + const { routes } = create('hidden-dot', 'always'); - assert.equal(routes.map((r) => r.component).filter(Boolean), ['hidden-dot/.well-known/dnt-policy.astro']); -}); + expect(routes.map((r) => r.component).filter(Boolean)).toEqual(['hidden-dot/.well-known/dnt-policy.astro']); + }); -test('fails if dynamic params are not separated', () => { - assert.throws(() => { - create('invalid-params', 'always'); - }, /Invalid route invalid-params\/\[foo\]\[bar\]\.astro — parameters must be separated/); -}); + test('fails if dynamic params are not separated', () => { + expect(() => create('invalid-params', 'always')).toThrowError('Invalid route invalid-params/[foo][bar].astro — parameters must be separated'); + }); -test('disallows rest parameters inside segments', () => { - assert.throws( - () => { - create('invalid-rest', 'always'); - }, - /** @param {Error} e */ - (e) => { - return e.message === 'Invalid route invalid-rest/foo-[...rest]-bar.astro — rest parameter must be a standalone segment'; - } - ); -}); + test('disallows rest parameters inside segments', () => { + expect(() => create('invalid-rest', 'always')).toThrowError('Invalid route invalid-rest/foo-[...rest]-bar.astro — rest parameter must be a standalone segment'); + }); -test('ignores things that look like lockfiles', () => { - const { routes } = create('lockfiles', 'always'); - assert.equal(cleanRoutes(routes), [ - { - type: 'page', - pattern: /^\/foo\/$/, - params: [], - component: 'lockfiles/foo.astro', - path: '/foo', - }, - ]); -}); + test('ignores things that look like lockfiles', () => { + const { routes } = create('lockfiles', 'always'); + expect(cleanRoutes(routes)).toEqual([ + { + type: 'page', + pattern: /^\/foo\/$/, + params: [], + component: 'lockfiles/foo.astro', + pathname: '/foo', + }, + ]); + }); -test('allows multiple slugs', () => { - const { routes } = create('multiple-slugs', 'always'); + test('allows multiple slugs', () => { + const { routes } = create('multiple-slugs', 'always'); - assert.equal(cleanRoutes(routes), [ - { - type: 'page', - pattern: /^\/([^/]+?)\.([^/]+?)\/$/, - component: 'multiple-slugs/[file].[ext].astro', - params: ['file', 'ext'], - path: null, - }, - ]); -}); + expect(cleanRoutes(routes)).toEqual([ + { + type: 'page', + pattern: /^\/([^/]+?)\.([^/]+?)\/$/, + component: 'multiple-slugs/[file].[ext].astro', + params: ['file', 'ext'], + pathname: undefined, + }, + ]); + }); -test('sorts routes correctly', () => { - const { routes } = create('sorting', 'always'); + test('sorts routes correctly', () => { + const { routes } = create('sorting', 'always'); - assert.equal( - routes.map((p) => p.component), - [ + expect(routes.map((p) => p.component)).toEqual([ 'sorting/index.astro', 'sorting/about.astro', 'sorting/post/index.astro', @@ -231,8 +215,6 @@ test('sorts routes correctly', () => { 'sorting/[...rest]/deep/index.astro', 'sorting/[...rest]/abc.astro', 'sorting/[...rest]/index.astro', - ] - ); + ]); + }); }); - -test.run(); diff --git a/packages/astro/test/snowpack-log.test.js b/packages/astro/test/snowpack-log.test.js deleted file mode 100644 index 31a67a589..000000000 --- a/packages/astro/test/snowpack-log.test.js +++ /dev/null @@ -1,83 +0,0 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { clearCache, runDevServer } from './helpers.js'; -import isWindows from 'is-windows'; - -// Skipping this entire suite for now as it is flakey. -const skip = true; - -// For some reason Windows isn't getting anything from stdout in this test, not sure why. -if (!skip && !isWindows()) { - const SnowpackLogging = suite('snowpack logging'); - const MAX_TEST_TIME = 10000; // max time this test suite may take - - function numberOfEntries(stdout, message) { - const exp = new RegExp(message, 'g'); - let count = 0; - let res; - while ((res = exp.exec(stdout))) { - count++; - } - return count; - } - - const root = new URL('./fixtures/astro/basic/', import.meta.url); - const timers = {}; - let runError = null; - SnowpackLogging.before(async (context) => { - await clearCache(); - - let importantMessages = 0; - let stdout = ''; - try { - const process = runDevServer(root, []); - - process.stdout.setEncoding('utf8'); - for await (const chunk of process.stdout) { - stdout += chunk; - if (/Server started/.test(chunk)) { - importantMessages++; - } - if (/Ready/.test(chunk)) { - importantMessages++; - } - if (/watching for file changes/.test(chunk)) { - importantMessages++; - } - if (importantMessages === 3) { - break; - } - } - - context.stdout = stdout; - process.kill(); - } catch (err) { - console.error(err); - runError = runError; - } - }); - - SnowpackLogging.before.each(({ __test__ }) => { - timers[__test__] = setTimeout(() => { - throw new Error(`Test "${__test__}" did not finish within allowed time`); - }, MAX_TEST_TIME); - }); - - SnowpackLogging('dev server started up', () => { - assert.equal(runError, null); - }); - - SnowpackLogging('Logs Ready message once', async ({ stdout }) => { - assert.equal(numberOfEntries(stdout, 'Ready'), 1); - }); - - SnowpackLogging('Logs [waiting for file changes] once', ({ stdout }) => { - assert.equal(numberOfEntries(stdout, 'watching for file changes'), 1); - }); - - SnowpackLogging.after.each(({ __test__ }) => { - clearTimeout(timers[__test__]); - }); - - SnowpackLogging.run(); -} diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js index b53ff2f0f..3efe2d38c 100644 --- a/packages/astro/test/test-utils.js +++ b/packages/astro/test/test-utils.js @@ -1,6 +1,101 @@ -import cheerio from 'cheerio'; +import execa from 'execa'; +import fs from 'fs'; +import fetch from 'node-fetch'; +import { loadConfig } from '../dist/config.js'; +import dev from '../dist/dev/index.js'; +import build from '../dist/build/index.js'; +import preview from '../dist/preview/index.js'; -/** load html */ -export function doc(html) { - return cheerio.load(html); +let lastPort = 3000; + +/** + * Load Astro fixture + * @param {Object} inlineConfig Astro config partial (note: must specify projectRoot) + * @returns {Object} Fixture. Has the following properties: + * .config - Returns the final config. Will be automatically passed to the methods below: + * + * Dev + * .dev() - Async. Starts a dev server (note: you must call `await server.stop()` before test exit) + * .fetch() - Async. Returns a URL from the dev server (must have called .dev() before) + * + * Build + * .build() - Async. Builds into current folder (will erase previous build) + * .readFile(path) - Async. Read a file from the build. + * .preview() - Async. Starts a preview server. Note this can’t be running in same fixture as .dev() as they share ports. Also, you must call `server.close()` before test exit + * .fetch(url) - Async. Returns a URL from the prevew server (must have called .preview() before) + */ +export async function loadFixture(inlineConfig) { + if (!inlineConfig || !inlineConfig.projectRoot) throw new Error("Must provide { projectRoot: './fixtures/...' }"); + + // load config + let cwd = inlineConfig.projectRoot; + if (typeof cwd === 'string') { + try { + cwd = new URL(cwd.replace(/\/?$/, '/')); + } catch (err1) { + cwd = new URL(cwd.replace(/\/?$/, '/'), import.meta.url); + } + } + + // get unique port + lastPort += 1; // note: tests run in parallel, and every test/fixture needs its own port. Increment by 1 every time this is called (can support thousands of tests) + if (!inlineConfig.devOptions) inlineConfig.devOptions = {}; + inlineConfig.devOptions.port = lastPort; + + // merge configs + if (!inlineConfig.buildOptions) inlineConfig.buildOptions = {}; + if (inlineConfig.buildOptions.sitemap === undefined) inlineConfig.buildOptions.sitemap = false; + if (!inlineConfig.devOptions.hostname) inlineConfig.devOptions.hostname = 'localhost'; + if (!inlineConfig.dist) inlineConfig.dist = './dist/'; + if (!inlineConfig.pages) inlineConfig.pages = './src/pages/'; + if (!inlineConfig.public) inlineConfig.public = './public/'; + if (!inlineConfig.src) inlineConfig.src = './src/'; + let config = await loadConfig(cwd); + config = merge(config, { + ...inlineConfig, + projectRoot: cwd, + dist: new URL(inlineConfig.dist, cwd), + pages: new URL(inlineConfig.pages, cwd), + public: new URL(inlineConfig.public, cwd), + src: new URL(inlineConfig.src, cwd), + }); + + return { + build: (opts = {}) => build(config, { logging: 'error', ...opts }), + dev: (opts = {}) => dev(config, { logging: 'error', ...opts }), + config, + fetch: (url) => fetch(`http://${config.devOptions.hostname}:${config.devOptions.port}${url}`), + readFile: (filePath) => fs.promises.readFile(new URL(`${filePath.replace(/^\/?/, '')}`, config.dist), 'utf8'), + preview: (opts = {}) => preview(config, { logging: 'error', ...opts }), + }; +} + +/** + * Basic object merge utility. Returns new copy of merged Object. + * @param {Object} a + * @param {Object} b + * @returns {Object} + */ +function merge(a, b) { + const allKeys = new Set([...Object.keys(a), ...Object.keys(b)]); + const c = {}; + for (const k of allKeys) { + const needsObjectMerge = + typeof a[k] === 'object' && typeof b[k] === 'object' && Object.keys(a[k]).length && Object.keys(b[k]).length && !Array.isArray(a[k]) && !Array.isArray(b[k]); + if (needsObjectMerge) { + c[k] = merge(a[k] || {}, b[k] || {}); + continue; + } + c[k] = a[k]; + if (b[k] !== undefined) c[k] = b[k]; + } + return c; +} + +const cliURL = new URL('../astro.js', import.meta.url); +/** Start Dev server via CLI */ +export function devCLI(root, additionalArgs = []) { + const args = [cliURL.pathname, 'dev', '--project-root', root.pathname].concat(additionalArgs); + const proc = execa('node', args); + return proc; } diff --git a/packages/astro/test/vue-component.test.js b/packages/astro/test/vue-component.test.js index 1529d1f15..c0a62bdf8 100644 --- a/packages/astro/test/vue-component.test.js +++ b/packages/astro/test/vue-component.test.js @@ -1,26 +1,39 @@ -import { suite } from 'uvu'; -import * as assert from 'uvu/assert'; -import { doc } from './test-utils.js'; -import { setup, setupBuild } from './helpers.js'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; -const Vue = suite('Vue component test'); +describe('Vue component', () => { + let fixture; + let devServer; -setup(Vue, './fixtures/vue-component'); -setupBuild(Vue, './fixtures/vue-component'); + beforeAll(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/vue-component/' }); + devServer = await fixture.dev(); + }); -Vue('Can load Vue', async ({ runtime }) => { - const result = await runtime.load('/'); - assert.ok(!result.error, `build error: ${result.error}`); + test('Can load Vue', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerio.load(html); - const $ = doc(result.contents); - const allPreValues = $('pre') - .toArray() - .map((el) => $(el).text()); - assert.equal(allPreValues, ['0', '1', '10', '100', '1000'], 'renders all components correctly'); - assert.equal($('astro-root').length, 4, 'renders 3 astro-roots'); - assert.equal($('astro-root[uid]').length, 4, 'all astro-roots have uid attributes'); - const uniqueRootUIDs = $('astro-root').map((i, el) => $(el).attr('uid')); - assert.equal(new Set(uniqueRootUIDs).size, 4, 'all astro-roots have unique uid attributes'); + const allPreValues = $('pre') + .toArray() + .map((el) => $(el).text()); + + // test 1: renders all components correctly + expect(allPreValues).toEqual(['0', '1', '10', '100', '1000']); + + // test 2: renders 3 <astro-root>s + expect($('astro-root')).toHaveLength(4); + + // test 3: all <astro-root>s have uid attributes + expect($('astro-root[uid]')).toHaveLength(4); + + // test 5: all <astro-root>s have unique uid attributes + const uniqueRootUIDs = $('astro-root').map((i, el) => $(el).attr('uid')); + expect(new Set(uniqueRootUIDs).size).toBe(4); + }); + + // important: close dev server (free up port and connection) + afterAll(async () => { + await devServer.stop(); + }); }); - -Vue.run(); diff --git a/yarn.lock b/yarn.lock index cfe1626e6..ea6d8d72d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -106,6 +106,13 @@ "@algolia/logger-common" "4.10.5" "@algolia/requester-common" "4.10.5" +"@astrojs/compiler@^0.1.0-canary.36": + version "0.1.0-canary.36" + resolved "https://registry.yarnpkg.com/@astrojs/compiler/-/compiler-0.1.0-canary.36.tgz#097b364e28093cca883e73797db9e8d1407e4dab" + integrity sha512-T4pTA+GJQoMzfJYb9SQnQEQjqUZo1LgcLNFNkziZijAANnbCF6GBGg5d1IWCyHuMaCKvPUrAWBi0olLzzuracw== + dependencies: + typescript "^4.3.5" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -113,7 +120,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.14.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== @@ -125,7 +132,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.15.0.tgz#2dbaf8b85334796cafbb0f5793a90a2fc010b176" integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== -"@babel/core@^7.15.0": +"@babel/core@^7.1.0", "@babel/core@^7.15.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.15.0.tgz#749e57c68778b73ad8082775561f67f5196aafa8" integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== @@ -146,7 +153,7 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/generator@^7.14.8", "@babel/generator@^7.15.0": +"@babel/generator@^7.14.8", "@babel/generator@^7.15.0", "@babel/generator@^7.7.2": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.15.0.tgz#a7d0c172e0d814974bad5aa77ace543b97917f15" integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== @@ -239,7 +246,7 @@ dependencies: "@babel/types" "^7.14.5" -"@babel/helper-plugin-utils@^7.14.5": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== @@ -296,7 +303,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.8", "@babel/parser@^7.15.0": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.8", "@babel/parser@^7.15.0", "@babel/parser@^7.7.2": version "7.15.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.3.tgz#3416d9bea748052cfcb63dbcc27368105b1ed862" integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== @@ -306,6 +313,41 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.8.tgz#66fd41666b2d7b840bd5ace7f7416d5ac60208d4" integrity sha512-syoCQFOoo/fzkWDeM0dLEZi5xqurb5vuyzwIMNZRNun+N/9A4cUZeQaE7dTrB8jGaKuJRBtEOajtnmw0I5hvvA== +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-jsx@^7.10.4", "@babel/plugin-syntax-jsx@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" @@ -313,6 +355,62 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz#b82c6ce471b165b5ce420cf92914d6fb46225716" + integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + "@babel/plugin-transform-react-jsx@^7.14.5": version "7.14.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.14.9.tgz#3314b2163033abac5200a869c4de242cd50a914c" @@ -331,7 +429,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.14.5": +"@babel/template@^7.14.5", "@babel/template@^7.3.3": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4" integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== @@ -340,7 +438,7 @@ "@babel/parser" "^7.14.5" "@babel/types" "^7.14.5" -"@babel/traverse@^7.15.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.15.0", "@babel/traverse@^7.7.2": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.15.0.tgz#4cca838fd1b2a03283c1f38e141f639d60b3fc98" integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== @@ -378,7 +476,7 @@ "@babel/helper-validator-identifier" "^7.14.8" to-fast-properties "^2.0.0" -"@babel/types@^7.14.9", "@babel/types@^7.15.0", "@babel/types@^7.3.0": +"@babel/types@^7.14.9", "@babel/types@^7.15.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.15.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.0.tgz#61af11f2286c4e9c69ca8deb5f4375a73c72dcbd" integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== @@ -386,6 +484,11 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@changesets/apply-release-plan@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@changesets/apply-release-plan/-/apply-release-plan-5.0.0.tgz#11bf168acecbf4cfa2b0e6425160bac5ceeec1c3" @@ -641,6 +744,191 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.1.0.tgz#de13b603cb1d389b50c0dc6296e86e112381e43c" + integrity sha512-+Vl+xmLwAXLNlqT61gmHEixeRbS4L8MUzAjtpBCOPWH+izNI/dR16IeXjkXJdRtIVWVSf9DO1gdp67B1XorZhQ== + dependencies: + "@jest/types" "^27.1.0" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.1.0" + jest-util "^27.1.0" + slash "^3.0.0" + +"@jest/core@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.1.0.tgz#622220f18032f5869e579cecbe744527238648bf" + integrity sha512-3l9qmoknrlCFKfGdrmiQiPne+pUR4ALhKwFTYyOeKw6egfDwJkO21RJ1xf41rN8ZNFLg5W+w6+P4fUqq4EMRWA== + dependencies: + "@jest/console" "^27.1.0" + "@jest/reporters" "^27.1.0" + "@jest/test-result" "^27.1.0" + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^27.1.0" + jest-config "^27.1.0" + jest-haste-map "^27.1.0" + jest-message-util "^27.1.0" + jest-regex-util "^27.0.6" + jest-resolve "^27.1.0" + jest-resolve-dependencies "^27.1.0" + jest-runner "^27.1.0" + jest-runtime "^27.1.0" + jest-snapshot "^27.1.0" + jest-util "^27.1.0" + jest-validate "^27.1.0" + jest-watcher "^27.1.0" + micromatch "^4.0.4" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.1.0.tgz#c7224a67004759ec203d8fa44e8bc0db93f66c44" + integrity sha512-wRp50aAMY2w1U2jP1G32d6FUVBNYqmk8WaGkiIEisU48qyDV0WPtw3IBLnl7orBeggveommAkuijY+RzVnNDOQ== + dependencies: + "@jest/fake-timers" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + jest-mock "^27.1.0" + +"@jest/fake-timers@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.1.0.tgz#c0b343d8a16af17eab2cb6862e319947c0ea2abe" + integrity sha512-22Zyn8il8DzpS+30jJNVbTlm7vAtnfy1aYvNeOEHloMlGy1PCYLHa4PWlSws0hvNsMM5bON6GISjkLoQUV3oMA== + dependencies: + "@jest/types" "^27.1.0" + "@sinonjs/fake-timers" "^7.0.2" + "@types/node" "*" + jest-message-util "^27.1.0" + jest-mock "^27.1.0" + jest-util "^27.1.0" + +"@jest/globals@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.1.0.tgz#e093a49c718dd678a782c197757775534c88d3f2" + integrity sha512-73vLV4aNHAlAgjk0/QcSIzzCZSqVIPbmFROJJv9D3QUR7BI4f517gVdJpSrCHxuRH3VZFhe0yGG/tmttlMll9g== + dependencies: + "@jest/environment" "^27.1.0" + "@jest/types" "^27.1.0" + expect "^27.1.0" + +"@jest/reporters@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.1.0.tgz#02ed1e6601552c2f6447378533f77aad002781d4" + integrity sha512-5T/zlPkN2HnK3Sboeg64L5eC8iiaZueLpttdktWTJsvALEtP2YMkC5BQxwjRWQACG9SwDmz+XjjkoxXUDMDgdw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^27.1.0" + "@jest/test-result" "^27.1.0" + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^27.1.0" + jest-resolve "^27.1.0" + jest-util "^27.1.0" + jest-worker "^27.1.0" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^8.0.0" + +"@jest/source-map@^27.0.6": + version "27.0.6" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.0.6.tgz#be9e9b93565d49b0548b86e232092491fb60551f" + integrity sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.1.0.tgz#9345ae5f97f6a5287af9ebd54716cd84331d42e8" + integrity sha512-Aoz00gpDL528ODLghat3QSy6UBTD5EmmpjrhZZMK/v1Q2/rRRqTGnFxHuEkrD4z/Py96ZdOHxIWkkCKRpmnE1A== + dependencies: + "@jest/console" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.1.0.tgz#04e8b3bd735570d3d48865e74977a14dc99bff2d" + integrity sha512-lnCWawDr6Z1DAAK9l25o3AjmKGgcutq1iIbp+hC10s/HxnB8ZkUsYq1FzjOoxxZ5hW+1+AthBtvS4x9yno3V1A== + dependencies: + "@jest/test-result" "^27.1.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.1.0" + jest-runtime "^27.1.0" + +"@jest/transform@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.1.0.tgz#962e385517e3d1f62827fa39c305edcc3ca8544b" + integrity sha512-ZRGCA2ZEVJ00ubrhkTG87kyLbN6n55g1Ilq0X9nJb5bX3MhMp3O6M7KG+LvYu+nZRqG5cXsQnJEdZbdpTAV8pQ== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.1.0" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.1.0" + jest-regex-util "^27.0.6" + jest-util "^27.1.0" + micromatch "^4.0.4" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.1.0": + version "27.1.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.1.0.tgz#674a40325eab23c857ebc0689e7e191a3c5b10cc" + integrity sha512-pRP5cLIzN7I7Vp6mHKRSaZD7YpBTK7hawx5si8trMKqk4+WOdK8NEKOTO2G8PKWD1HbKMVckVB6/XHh/olhf2g== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + "@jsdevtools/rehype-toc@3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@jsdevtools/rehype-toc/-/rehype-toc-3.0.2.tgz#29c32e6b40cd4b5dafd96cb90d5057ac5dab4a51" @@ -1317,37 +1605,37 @@ npmlog "^4.1.2" write-file-atomic "^3.0.3" -"@lit-labs/ssr-client@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@lit-labs/ssr-client/-/ssr-client-1.0.0.tgz#9d5a437f575469023500b7eff3bd27632197f720" - integrity sha512-bYnX1uhE7oO/579xRoAdAHnngROQHj93bqCUqw/L4vvRyBWBIeeshoM3OjPX0DFdeJIvZy/1x29t9iaNvTB5bg== +"@lit-labs/ssr-client@^1.0.0-rc.1": + version "1.0.0-rc.2" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-client/-/ssr-client-1.0.0-rc.2.tgz#b4ebd2103e6384d72029941f6a64ccf59b5cc73d" + integrity sha512-t1rVTgrvUvVgmUdoL6VytNAKWRfzy4howS3g/2Y/XlfTicBaoDaSX16b+YUDfT5t6zgdma1mDQkLx/7yfSJTdA== dependencies: - "@lit/reactive-element" "^1.0.0" - lit "^2.0.0" - lit-html "^2.0.0" + "@lit/reactive-element" "^1.0.0-rc.1" + lit "^2.0.0-rc.1" + lit-html "^2.0.0-rc.4" -"@lit-labs/ssr@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@lit-labs/ssr/-/ssr-1.0.0.tgz#fd51dd84f8b7979156cc211e581d89a24dcc0d95" - integrity sha512-Emn0n9kB9UNaavA2YJiC5uT+qVgo+coSfFn09Bmg3DnEfin1cpwG5hG10VmL8AGfuA8vyKkSMj+Cvp6n0MZgcg== +"@lit-labs/ssr@^1.0.0-rc.1": + version "1.0.0-rc.2" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr/-/ssr-1.0.0-rc.2.tgz#e8129bd9a3c8ee35bdf89a974a1e61202973c03c" + integrity sha512-Fv8TGbWGLE3wV/QjvA5Jdh4g50iDVm9juAFVhtwtfkVj6DZdeTlrZn1jUeqegDfghSsC71RQ1SAl57iVZZvO+g== dependencies: - "@lit-labs/ssr-client" "^1.0.0" + "@lit-labs/ssr-client" "^1.0.0-rc.1" "@webcomponents/template-shadowroot" "^0.1.0" escape-html "^1.0.3" koa "^2.7.0" koa-node-resolve "^1.0.0-pre.5" koa-static "^5.0.0" - lit "^2.0.0" - lit-element "^3.0.0" - lit-html "^2.0.0" + lit "^2.0.0-rc.1" + lit-element "^3.0.0-rc.1" + lit-html "^2.0.0-rc.4" node-fetch "^2.6.0" - parse5 "^6.0.1" + parse5 "^5.1.0" resolve "^1.10.1" -"@lit/reactive-element@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.0.0.tgz#7b6e6a85709cda0370c47e425ac2f3b553696a4b" - integrity sha512-Kpgenb8UNFsKCsFhggiVvUkCbcFQSd6N8hffYEEGjz27/4rw3cTSsmP9t3q1EHOAsdum60Wo64HvuZDFpEwexA== +"@lit/reactive-element@^1.0.0-rc.1", "@lit/reactive-element@^1.0.0-rc.2": + version "1.0.0-rc.3" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.0.0-rc.3.tgz#5032f493fbf39781b187a7e2dd5d256537c8760c" + integrity sha512-Rs2px1keOQUNJUo5B+WExl5v244ZNCiN/iMVNO9evFdJjAdWCIupR/p14zRPkNHsciRBELLTcOZ379cI9O6PDg== "@ljharb/has-package-exports-patterns@0.0.1": version "0.0.1" @@ -1453,34 +1741,14 @@ node-gyp "^7.1.0" read-package-json-fast "^2.0.1" -"@octokit/action@^3.15.4": - version "3.15.4" - resolved "https://registry.yarnpkg.com/@octokit/action/-/action-3.15.4.tgz#b7bf36e34082c046231927d12537dfd08f6f1d5a" - integrity sha512-MQRdhjl03FefgJiHRQhyHVsAOIZWUwrZi9m6Kw0tS3/QWM3P64s4Nfs7rd+Vk8KvFyZE5x8c/sb/90pBVrqFPw== - dependencies: - "@octokit/auth-action" "^1.2.0" - "@octokit/core" "^3.0.0" - "@octokit/plugin-paginate-rest" "^2.2.4" - "@octokit/plugin-rest-endpoint-methods" "5.10.1" - "@octokit/types" "^6.16.1" - https-proxy-agent "^5.0.0" - -"@octokit/auth-action@^1.2.0": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@octokit/auth-action/-/auth-action-1.3.3.tgz#20004fbf0b4a7012f4f7fc2c54d263749239cd5f" - integrity sha512-8v4c/pw6HTxsF7pCgJoox/q4KKov4zkgLxEGGqLOZPSZaHf1LqdLlj5m5x5c1bKNn38uQXNvJKEnKX1qJlGeQQ== - dependencies: - "@octokit/auth-token" "^2.4.0" - "@octokit/types" "^6.0.3" - -"@octokit/auth-token@^2.4.0", "@octokit/auth-token@^2.4.4": +"@octokit/auth-token@^2.4.4": version "2.4.5" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.5.tgz#568ccfb8cb46f36441fac094ce34f7a875b197f3" integrity sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA== dependencies: "@octokit/types" "^6.0.3" -"@octokit/core@^3.0.0", "@octokit/core@^3.5.0": +"@octokit/core@^3.5.0": version "3.5.1" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== @@ -1511,16 +1779,6 @@ "@octokit/types" "^6.0.3" universal-user-agent "^6.0.0" -"@octokit/openapi-types@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.0.0.tgz#db4335de99509021f501fc4e026e6ff495fe1e62" - integrity sha512-k1iO2zKuEjjRS1EJb4FwSLk+iF6EGp+ZV0OMRViQoWhQ1fZTk9hg1xccZII5uyYoiqcbC73MRBmT45y1vp2PPg== - -"@octokit/openapi-types@^10.2.2": - version "10.2.2" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-10.2.2.tgz#6c1c839d7d169feabaf1d2a69c79439c75d979cd" - integrity sha512-EVcXQ+ZrC04cg17AMg1ofocWMxHDn17cB66ZHgYc0eUwjFtxS0oBzkyw2VqIrHBwVgtfoYrq1WMQfQmMjUwthw== - "@octokit/openapi-types@^9.5.0": version "9.7.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-9.7.0.tgz#9897cdefd629cd88af67b8dbe2e5fb19c63426b2" @@ -1531,13 +1789,6 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== -"@octokit/plugin-paginate-rest@^2.2.4": - version "2.16.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.0.tgz#09dbda2e5fbca022e3cdf76b63618f7b357c9f0c" - integrity sha512-8YYzALPMvEZ35kgy5pdYvQ22Roz+BIuEaedO575GwE2vb/ACDqQn0xQrTJR4tnZCJn7pi8+AWPVjrFDaERIyXQ== - dependencies: - "@octokit/types" "^6.26.0" - "@octokit/plugin-paginate-rest@^2.6.2": version "2.15.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.15.1.tgz#264189dd3ce881c6c33758824aac05a4002e056a" @@ -1550,14 +1801,6 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== -"@octokit/plugin-rest-endpoint-methods@5.10.1": - version "5.10.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.10.1.tgz#9683c4cf476fb6c80f668c4b468919e69c71f66a" - integrity sha512-Rf1iMl40I0dIxjh1g32qZ6Ym/uT8QWZMm2vYGG5Vi8SX1MwZvbuxEGXYgmzTUWSD3PYWSLilE2+4L8kmdLGTMg== - dependencies: - "@octokit/types" "^6.27.0" - deprecation "^2.3.1" - "@octokit/plugin-rest-endpoint-methods@5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.8.0.tgz#33b342fe41f2603fdf8b958e6652103bb3ea3f3b" @@ -1604,20 +1847,6 @@ dependencies: "@octokit/openapi-types" "^9.5.0" -"@octokit/types@^6.26.0": - version "6.26.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.26.0.tgz#b8af298485d064ad9424cb41520541c1bf820346" - integrity sha512-RDxZBAFMtqs1ZPnbUu1e7ohPNfoNhTiep4fErY7tZs995BeHu369Vsh5woMIaFbllRWEZBfvTCS4hvDnMPiHrA== - dependencies: - "@octokit/openapi-types" "^10.0.0" - -"@octokit/types@^6.27.0": - version "6.28.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.28.1.tgz#ab990d1fe952226055e81c7650480e6bacfb877c" - integrity sha512-XlxDoQLFO5JnFZgKVQTYTvXRsQFfr/GwDUU108NJ9R5yFPkA2qXhTJjYuul3vE4eLXP40FA2nysOu2zd6boE+w== - dependencies: - "@octokit/openapi-types" "^10.2.2" - "@rollup/pluginutils@^4.1.1": version "4.1.1" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.1.tgz#1d4da86dd4eded15656a57d933fda2b9a08d47ec" @@ -1652,6 +1881,20 @@ retext-smartypants "^4.0.0" unist-util-visit "^2.0.1" +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^7.0.2": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" + integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@snowpack/plugin-dotenv@^2.1.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@snowpack/plugin-dotenv/-/plugin-dotenv-2.2.0.tgz#624348a83e28ae523a7d2695cbe81f53381bc964" @@ -1684,7 +1927,7 @@ dependencies: "@types/estree" "*" -"@types/babel__core@^7.1.15": +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14", "@types/babel__core@^7.1.15": version "7.1.15" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.15.tgz#2ccfb1ad55a02c83f8e0ad327cbc332f55eb1024" integrity sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew== @@ -1710,7 +1953,7 @@ "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" -"@types/babel__traverse@*": +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": version "7.14.2" resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== @@ -1753,11 +1996,25 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.48.tgz#18dc8091b285df90db2f25aa7d906cfc394b7f74" integrity sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew== +"@types/etag@^1.8.1": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@types/etag/-/etag-1.8.1.tgz#593ca8ddb43acb3db049bd0955fd64d281ab58b9" + integrity sha512-bsKkeSqN7HYyYntFRAmzcwx/dKW4Wa+KVMTInANlI72PWLQmOpZu96j0OqHZGArW4VQwCmJPteQlXaUDeOB0WQ== + dependencies: + "@types/node" "*" + "@types/github-slugger@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@types/github-slugger/-/github-slugger-1.3.0.tgz#16ab393b30d8ae2a111ac748a015ac05a1fc5524" integrity sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g== +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + "@types/hast@^2.0.0", "@types/hast@^2.3.2": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" @@ -1765,6 +2022,33 @@ dependencies: "@types/unist" "*" +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^27.0.1": + version "27.0.1" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.0.1.tgz#fafcc997da0135865311bb1215ba16dba6bdf4ca" + integrity sha512-HTLpVXHrY69556ozYkcq47TtQJXpcWAWfkoqz+ZGz2JnmZhzlRjprCIyFnetSy8gpDWwTTGBcRVv1J1I1vBrHw== + dependencies: + jest-diff "^27.0.0" + pretty-format "^27.0.0" + "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1845,6 +2129,11 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-6.0.1.tgz#f8ae4fbcd2b9ba4ff934698e28778961f9cb22ca" integrity sha512-ARATsLdrGPUnaBvxLhUlnltcMgn7pQG312S8ccdYlnyijabrX9RN/KN/iGj9Am96CoW8e/K9628BA7Bv4XHdrA== +"@types/prettier@^2.1.5": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.3.2.tgz#fc8c2825e4ed2142473b4a81064e6e081463d1b3" + integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + "@types/prompts@^2.0.12": version "2.0.14" resolved "https://registry.yarnpkg.com/@types/prompts/-/prompts-2.0.14.tgz#10cb8899844bb0771cabe57c1becaaaca9a3b521" @@ -1865,21 +2154,33 @@ "@types/mime" "^1" "@types/node" "*" -"@types/trusted-types@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756" - integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg== +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/trusted-types@^1.0.1": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-1.0.6.tgz#569b8a08121d3203398290d602d84d73c8dcf5da" + integrity sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw== "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/yargs-parser@^20.2.1": +"@types/yargs-parser@*", "@types/yargs-parser@^20.2.1": version "20.2.1" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^4.22.0": version "4.29.3" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz#95cb8029a8bd8bd9c7f4ab95074a7cb2115adefa" @@ -2084,6 +2385,11 @@ JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -2097,6 +2403,14 @@ accepts@^1.3.5: mime-types "~2.1.24" negotiator "0.6.2" +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -2111,16 +2425,21 @@ acorn-node@^1.6.1: acorn-walk "^7.0.0" xtend "^4.0.2" -acorn-walk@^7.0.0: +acorn-walk@^7.0.0, acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^7.0.0, acorn@^7.4.0: +acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.2.4: + version "8.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.4.1.tgz#56c36251fc7cabc7096adc18f05afe814321a28c" + integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== + add-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" @@ -2265,12 +2584,17 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + any-promise@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -anymatch@~3.1.2: +anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== @@ -2448,6 +2772,41 @@ axios@^0.21.1: dependencies: follow-redirects "^1.10.0" +babel-jest@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.1.0.tgz#e96ca04554fd32274439869e2b6d24de9d91bc4e" + integrity sha512-6NrdqzaYemALGCuR97QkC/FkFIEBWP5pw5TMJoUHZTVXyOgocujp6A0JE2V6gE0HtqAAv6VKU/nI+OCR1Z4gHA== + dependencies: + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^27.0.6" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz#f7c6b3d764af21cb4a2a1ab6870117dbde15b456" + integrity sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + babel-plugin-jsx-dom-expressions@^0.29.14: version "0.29.14" resolved "https://registry.yarnpkg.com/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.29.14.tgz#f5bd1c5da2f32dd1db89d5b654c9fa02a8cd5213" @@ -2468,6 +2827,32 @@ babel-plugin-module-resolver@^4.1.0: reselect "^4.0.0" resolve "^1.13.1" +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz#909ef08e9f24a4679768be2f60a3df0856843f9d" + integrity sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw== + dependencies: + babel-plugin-jest-hoist "^27.0.6" + babel-preset-current-node-syntax "^1.0.0" + babel-preset-solid@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/babel-preset-solid/-/babel-preset-solid-1.1.1.tgz#be8a381cdc92323e3bc636f216cd24622d8183a1" @@ -2626,6 +3011,11 @@ broken-link-checker@^0.7.8: urlcache "~0.7.0" urlobj "0.0.11" +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browserslist@^4.16.6: version "4.16.8" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.8.tgz#cb868b0b554f137ba6e33de0ecff2eda403c4fb0" @@ -2637,6 +3027,13 @@ browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.75" +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -2770,6 +3167,11 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + caniuse-lite@^1.0.30001243, caniuse-lite@^1.0.30001251: version "1.0.30001251" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" @@ -2832,6 +3234,11 @@ chalk@~0.5.1: strip-ansi "^0.3.0" supports-color "^0.2.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + char-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/char-spinner/-/char-spinner-1.0.1.tgz#e6ea67bd247e107112983b7ab0479ed362800081" @@ -2937,11 +3344,16 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.2.0: +ci-info@^3.1.1, ci-info@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== +cjs-module-lexer@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40" + integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== + clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -3027,6 +3439,11 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -3294,7 +3711,7 @@ conventional-recommended-bump@^6.1.0: meow "^8.0.0" q "^1.5.1" -convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -3401,6 +3818,23 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + csstype@^2.6.8: version "2.6.17" resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.17.tgz#4cf30eb87e1d1a005d8b6510f95292413f6a1c0e" @@ -3443,6 +3877,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" @@ -3494,6 +3937,11 @@ decamelize@^1.1.0, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -3509,11 +3957,16 @@ deep-equal@~1.0.1: resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= -deep-is@^0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-user-agent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-user-agent/-/default-user-agent-1.0.0.tgz#16c46efdcaba3edc45f24f2bd4868b01b7c2adc6" @@ -3604,6 +4057,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -3631,6 +4089,11 @@ didyoumean@^1.2.2: resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037" integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw== +diff-sequences@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" + integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== + diff@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -3669,6 +4132,13 @@ domelementtype@^2.0.1, domelementtype@^2.1.0, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + domhandler@^4.0.0, domhandler@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.0.tgz#f9768a5f034be60a89a27c2e4d0f74eba0d8b059" @@ -3740,6 +4210,11 @@ electron-to-chromium@^1.3.811: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.814.tgz#418fad80c3276a46103ca72a21a8290620d83c4a" integrity sha512-0mH03cyjh6OzMlmjauGg0TLd87ErIJqWiYxMcOLKf5w6p0YEOl7DJAj7BDlXEFmCguY5CQaKVOiMjAMODO2XDw== +emittery@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" + integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3909,6 +4384,11 @@ escape-string-regexp@^1.0.0, escape-string-regexp@^1.0.2, escape-string-regexp@^ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -3919,6 +4399,18 @@ escape-string-regexp@^5.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + eslint-config-prettier@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a" @@ -4018,7 +4510,7 @@ espree@^7.3.0, espree@^7.3.1: acorn-jsx "^5.3.1" eslint-visitor-keys "^1.3.0" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -4072,7 +4564,7 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: +etag@^1.8.1, etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= @@ -4123,6 +4615,23 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +expect@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.1.0.tgz#380de0abb3a8f2299c4c6c66bbe930483b5dba9b" + integrity sha512-9kJngV5hOJgkFil4F/uXm3hVBubUK2nERVfvqNNwxxuW8ZOUwSTTSysgfzckYtv/LBzj/LJXbiAF7okHCXgdug== + dependencies: + "@jest/types" "^27.1.0" + ansi-styles "^5.0.0" + jest-get-type "^27.0.6" + jest-matcher-utils "^27.1.0" + jest-message-util "^27.1.0" + jest-regex-util "^27.0.6" + extend@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-2.0.2.tgz#1b74985400171b85554894459c978de6ef453ab7" @@ -4193,7 +4702,7 @@ fast-json-stable-stringify@^2.0.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@^2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -4210,6 +4719,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + fd-slicer@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" @@ -4450,7 +4966,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@~2.3.2: +fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -4505,6 +5021,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-pkg-repo@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-4.1.2.tgz#c4ffd60015cf091be666a0212753fc158f01a4c0" @@ -4612,7 +5133,7 @@ glob-parent@^6.0.0: dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.7" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== @@ -4943,6 +5464,18 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-minifier-terser@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" @@ -5087,7 +5620,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@^0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5323,6 +5856,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-ci@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.0.tgz#c7e7be3c9d8eef7d0fa144390bd1e4b88dc4c994" + integrity sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ== + dependencies: + ci-info "^3.1.1" + is-core-module@^2.2.0, is-core-module@^2.5.0: version "2.6.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.6.0.tgz#d7553b2526fe59b92ba3e40c8df757ec8a709e19" @@ -5369,6 +5909,11 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-generator-function@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" @@ -5470,6 +6015,11 @@ is-plain-object@^5.0.0: resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-regex@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -5579,6 +6129,458 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.1.0.tgz#42da6ea00f06274172745729d55f42b60a9dffe0" + integrity sha512-eRcb13TfQw0xiV2E98EmiEgs9a5uaBIqJChyl0G7jR9fCIvGjXovnDS6Zbku3joij4tXYcSK4SE1AXqOlUxjWg== + dependencies: + "@jest/types" "^27.1.0" + execa "^5.0.0" + throat "^6.0.1" + +jest-circus@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.1.0.tgz#24c280c90a625ea57da20ee231d25b1621979a57" + integrity sha512-6FWtHs3nZyZlMBhRf1wvAC5CirnflbGJAY1xssSAnERLiiXQRH+wY2ptBVtXjX4gz4AA2EwRV57b038LmifRbA== + dependencies: + "@jest/environment" "^27.1.0" + "@jest/test-result" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^0.7.0" + expect "^27.1.0" + is-generator-fn "^2.0.0" + jest-each "^27.1.0" + jest-matcher-utils "^27.1.0" + jest-message-util "^27.1.0" + jest-runtime "^27.1.0" + jest-snapshot "^27.1.0" + jest-util "^27.1.0" + pretty-format "^27.1.0" + slash "^3.0.0" + stack-utils "^2.0.3" + throat "^6.0.1" + +jest-cli@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.1.0.tgz#118438e4d11cf6fb66cb2b2eb5778817eab3daeb" + integrity sha512-h6zPUOUu+6oLDrXz0yOWY2YXvBLk8gQinx4HbZ7SF4V3HzasQf+ncoIbKENUMwXyf54/6dBkYXvXJos+gOHYZw== + dependencies: + "@jest/core" "^27.1.0" + "@jest/test-result" "^27.1.0" + "@jest/types" "^27.1.0" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + jest-config "^27.1.0" + jest-util "^27.1.0" + jest-validate "^27.1.0" + prompts "^2.0.1" + yargs "^16.0.3" + +jest-config@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.1.0.tgz#e6826e2baaa34c07c3839af86466870e339d9ada" + integrity sha512-GMo7f76vMYUA3b3xOdlcKeKQhKcBIgurjERO2hojo0eLkKPGcw7fyIoanH+m6KOP2bLad+fGnF8aWOJYxzNPeg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^27.1.0" + "@jest/types" "^27.1.0" + babel-jest "^27.1.0" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + is-ci "^3.0.0" + jest-circus "^27.1.0" + jest-environment-jsdom "^27.1.0" + jest-environment-node "^27.1.0" + jest-get-type "^27.0.6" + jest-jasmine2 "^27.1.0" + jest-regex-util "^27.0.6" + jest-resolve "^27.1.0" + jest-runner "^27.1.0" + jest-util "^27.1.0" + jest-validate "^27.1.0" + micromatch "^4.0.4" + pretty-format "^27.1.0" + +jest-diff@^27.0.0, jest-diff@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.1.0.tgz#c7033f25add95e2218f3c7f4c3d7b634ab6b3cd2" + integrity sha512-rjfopEYl58g/SZTsQFmspBODvMSytL16I+cirnScWTLkQVXYVZfxm78DFfdIIXc05RCYuGjxJqrdyG4PIFzcJg== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.0.6" + jest-get-type "^27.0.6" + pretty-format "^27.1.0" + +jest-docblock@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.0.6.tgz#cc78266acf7fe693ca462cbbda0ea4e639e4e5f3" + integrity sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA== + dependencies: + detect-newline "^3.0.0" + +jest-each@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.1.0.tgz#36ac75f7aeecb3b8da2a8e617ccb30a446df408c" + integrity sha512-K/cNvQlmDqQMRHF8CaQ0XPzCfjP5HMJc2bIJglrIqI9fjwpNqITle63IWE+wq4p+3v+iBgh7Wq0IdGpLx5xjDg== + dependencies: + "@jest/types" "^27.1.0" + chalk "^4.0.0" + jest-get-type "^27.0.6" + jest-util "^27.1.0" + pretty-format "^27.1.0" + +jest-environment-jsdom@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.1.0.tgz#5fb3eb8a67e02e6cc623640388d5f90e33075f18" + integrity sha512-JbwOcOxh/HOtsj56ljeXQCUJr3ivnaIlM45F5NBezFLVYdT91N5UofB1ux2B1CATsQiudcHdgTaeuqGXJqjJYQ== + dependencies: + "@jest/environment" "^27.1.0" + "@jest/fake-timers" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + jest-mock "^27.1.0" + jest-util "^27.1.0" + jsdom "^16.6.0" + +jest-environment-node@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.1.0.tgz#feea6b765f1fd4582284d4f1007df2b0a8d15b7f" + integrity sha512-JIyJ8H3wVyM4YCXp7njbjs0dIT87yhGlrXCXhDKNIg1OjurXr6X38yocnnbXvvNyqVTqSI4M9l+YfPKueqL1lw== + dependencies: + "@jest/environment" "^27.1.0" + "@jest/fake-timers" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + jest-mock "^27.1.0" + jest-util "^27.1.0" + +jest-get-type@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe" + integrity sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg== + +jest-haste-map@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.1.0.tgz#a39f456823bd6a74e3c86ad25f6fa870428326bf" + integrity sha512-7mz6LopSe+eA6cTFMf10OfLLqRoIPvmMyz5/OnSXnHO7hB0aDP1iIeLWCXzAcYU5eIJVpHr12Bk9yyq2fTW9vg== + dependencies: + "@jest/types" "^27.1.0" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^27.0.6" + jest-serializer "^27.0.6" + jest-util "^27.1.0" + jest-worker "^27.1.0" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-jasmine2@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.1.0.tgz#324a3de0b2ee20d238b2b5b844acc4571331a206" + integrity sha512-Z/NIt0wBDg3przOW2FCWtYjMn3Ip68t0SL60agD/e67jlhTyV3PIF8IzT9ecwqFbeuUSO2OT8WeJgHcalDGFzQ== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^27.1.0" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^27.1.0" + is-generator-fn "^2.0.0" + jest-each "^27.1.0" + jest-matcher-utils "^27.1.0" + jest-message-util "^27.1.0" + jest-runtime "^27.1.0" + jest-snapshot "^27.1.0" + jest-util "^27.1.0" + pretty-format "^27.1.0" + throat "^6.0.1" + +jest-leak-detector@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.1.0.tgz#fe7eb633c851e06280ec4dd248067fe232c00a79" + integrity sha512-oHvSkz1E80VyeTKBvZNnw576qU+cVqRXUD3/wKXh1zpaki47Qty2xeHg2HKie9Hqcd2l4XwircgNOWb/NiGqdA== + dependencies: + jest-get-type "^27.0.6" + pretty-format "^27.1.0" + +jest-matcher-utils@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.1.0.tgz#68afda0885db1f0b9472ce98dc4c535080785301" + integrity sha512-VmAudus2P6Yt/JVBRdTPFhUzlIN8DYJd+et5Rd9QDsO/Z82Z4iwGjo43U8Z+PTiz8CBvKvlb6Fh3oKy39hykkQ== + dependencies: + chalk "^4.0.0" + jest-diff "^27.1.0" + jest-get-type "^27.0.6" + pretty-format "^27.1.0" + +jest-message-util@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.1.0.tgz#e77692c84945d1d10ef00afdfd3d2c20bd8fb468" + integrity sha512-Eck8NFnJ5Sg36R9XguD65cf2D5+McC+NF5GIdEninoabcuoOfWrID5qJhufq5FB0DRKoiyxB61hS7MKoMD0trQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.1.0" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + pretty-format "^27.1.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.1.0.tgz#7ca6e4d09375c071661642d1c14c4711f3ab4b4f" + integrity sha512-iT3/Yhu7DwAg/0HvvLCqLvrTKTRMyJlrrfJYWzuLSf9RCAxBoIXN3HoymZxMnYsC3eD8ewGbUa9jUknwBenx2w== + dependencies: + "@jest/types" "^27.1.0" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" + integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== + +jest-resolve-dependencies@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.1.0.tgz#d32ea4a2c82f76410f6157d0ec6cde24fbff2317" + integrity sha512-Kq5XuDAELuBnrERrjFYEzu/A+i2W7l9HnPWqZEeKGEQ7m1R+6ndMbdXCVCx29Se1qwLZLgvoXwinB3SPIaitMQ== + dependencies: + "@jest/types" "^27.1.0" + jest-regex-util "^27.0.6" + jest-snapshot "^27.1.0" + +jest-resolve@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.1.0.tgz#bb22303c9e240cccdda28562e3c6fbcc6a23ac86" + integrity sha512-TXvzrLyPg0vLOwcWX38ZGYeEztSEmW+cQQKqc4HKDUwun31wsBXwotRlUz4/AYU/Fq4GhbMd/ileIWZEtcdmIA== + dependencies: + "@jest/types" "^27.1.0" + chalk "^4.0.0" + escalade "^3.1.1" + graceful-fs "^4.2.4" + jest-haste-map "^27.1.0" + jest-pnp-resolver "^1.2.2" + jest-util "^27.1.0" + jest-validate "^27.1.0" + resolve "^1.20.0" + slash "^3.0.0" + +jest-runner@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.1.0.tgz#1b28d114fb3b67407b8354c9385d47395e8ff83f" + integrity sha512-ZWPKr9M5w5gDplz1KsJ6iRmQaDT/yyAFLf18fKbb/+BLWsR1sCNC2wMT0H7pP3gDcBz0qZ6aJraSYUNAGSJGaw== + dependencies: + "@jest/console" "^27.1.0" + "@jest/environment" "^27.1.0" + "@jest/test-result" "^27.1.0" + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.8.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-docblock "^27.0.6" + jest-environment-jsdom "^27.1.0" + jest-environment-node "^27.1.0" + jest-haste-map "^27.1.0" + jest-leak-detector "^27.1.0" + jest-message-util "^27.1.0" + jest-resolve "^27.1.0" + jest-runtime "^27.1.0" + jest-util "^27.1.0" + jest-worker "^27.1.0" + source-map-support "^0.5.6" + throat "^6.0.1" + +jest-runtime@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.1.0.tgz#1a98d984ffebc16a0b4f9eaad8ab47c00a750cf5" + integrity sha512-okiR2cpGjY0RkWmUGGado6ETpFOi9oG3yV0CioYdoktkVxy5Hv0WRLWnJFuArSYS8cHMCNcceUUMGiIfgxCO9A== + dependencies: + "@jest/console" "^27.1.0" + "@jest/environment" "^27.1.0" + "@jest/fake-timers" "^27.1.0" + "@jest/globals" "^27.1.0" + "@jest/source-map" "^27.0.6" + "@jest/test-result" "^27.1.0" + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + execa "^5.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-haste-map "^27.1.0" + jest-message-util "^27.1.0" + jest-mock "^27.1.0" + jest-regex-util "^27.0.6" + jest-resolve "^27.1.0" + jest-snapshot "^27.1.0" + jest-util "^27.1.0" + jest-validate "^27.1.0" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^16.0.3" + +jest-serializer@^27.0.6: + version "27.0.6" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.0.6.tgz#93a6c74e0132b81a2d54623251c46c498bb5bec1" + integrity sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.1.0.tgz#2a063ab90064017a7e9302528be7eaea6da12d17" + integrity sha512-eaeUBoEjuuRwmiRI51oTldUsKOohB1F6fPqWKKILuDi/CStxzp2IWekVUXbuHHoz5ik33ioJhshiHpgPFbYgcA== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/parser" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.1.0" + graceful-fs "^4.2.4" + jest-diff "^27.1.0" + jest-get-type "^27.0.6" + jest-haste-map "^27.1.0" + jest-matcher-utils "^27.1.0" + jest-message-util "^27.1.0" + jest-resolve "^27.1.0" + jest-util "^27.1.0" + natural-compare "^1.4.0" + pretty-format "^27.1.0" + semver "^7.3.2" + +jest-util@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.1.0.tgz#06a53777a8cb7e4940ca8e20bf9c67dd65d9bd68" + integrity sha512-edSLD2OneYDKC6gZM1yc+wY/877s/fuJNoM1k3sOEpzFyeptSmke3SLnk1dDHk9CgTA+58mnfx3ew3J11Kes/w== + dependencies: + "@jest/types" "^27.1.0" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^3.0.0" + picomatch "^2.2.3" + +jest-validate@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.1.0.tgz#d9e82024c5e3f5cef52a600cfc456793a84c0998" + integrity sha512-QiJ+4XuSuMsfPi9zvdO//IrSRSlG6ybJhOpuqYSsuuaABaNT84h0IoD6vvQhThBOKT+DIKvl5sTM0l6is9+SRA== + dependencies: + "@jest/types" "^27.1.0" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^27.0.6" + leven "^3.1.0" + pretty-format "^27.1.0" + +jest-watcher@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.1.0.tgz#2511fcddb0e969a400f3d1daa74265f93f13ce93" + integrity sha512-ivaWTrA46aHWdgPDgPypSHiNQjyKnLBpUIHeBaGg11U+pDzZpkffGlcB1l1a014phmG0mHgkOHtOgiqJQM6yKQ== + dependencies: + "@jest/test-result" "^27.1.0" + "@jest/types" "^27.1.0" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^27.1.0" + string-length "^4.0.1" + +jest-worker@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.1.0.tgz#65f4a88e37148ed984ba8ca8492d6b376938c0aa" + integrity sha512-mO4PHb2QWLn9yRXGp7rkvXLAYuxwhq1ZYUo0LoDhg8wqvv4QizP1ZWEJOeolgbEgAWZLIEU0wsku8J+lGWfBhg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.1.0.tgz#eaab62dfdc02d8b7c814cd27b8d2d92bc46d3d69" + integrity sha512-pSQDVwRSwb109Ss13lcMtdfS9r8/w2Zz8+mTUA9VORD66GflCdl8nUFCqM96geOD2EBwWCNURrNAfQsLIDNBdg== + dependencies: + "@jest/core" "^27.1.0" + import-local "^3.0.2" + jest-cli "^27.1.0" + joi@^17.4.0: version "17.4.2" resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.2.tgz#02f4eb5cf88e515e614830239379dcbbe28ce7f7" @@ -5608,6 +6610,39 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsdom@^16.6.0: + version "16.7.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" + integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== + dependencies: + abab "^2.0.5" + acorn "^8.2.4" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + form-data "^3.0.0" + html-encoding-sniffer "^2.0.1" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.0" + parse5 "6.0.1" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.6" + xml-name-validator "^3.0.0" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -5829,6 +6864,11 @@ lerna@^4.0.0: import-local "^3.0.2" npmlog "^4.1.2" +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -5837,6 +6877,14 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + libnpmaccess@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-4.0.3.tgz#dfb0e5b0a53c315a2610d300e46b4ddeb66e7eec" @@ -5881,29 +6929,29 @@ link-types@^1.1.0: resolved "https://registry.yarnpkg.com/link-types/-/link-types-1.1.0.tgz#af65e59db52e70c1ffb18ac4c3cb056bfe796830" integrity sha1-r2XlnbUucMH/sYrEw8sFa/55aDA= -lit-element@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.0.0.tgz#0e9e64ddbc3dd6a8da4d6fbfadbc070a54cf0597" - integrity sha512-oPqRhhBBhs+AlI62QLwtWQNU/bNK/h2L1jI3IDroqZubo6XVAkyNy2dW3CRfjij8mrNlY7wULOfyyKKOnfEePA== +lit-element@^3.0.0-rc.1, lit-element@^3.0.0-rc.2: + version "3.0.0-rc.3" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-3.0.0-rc.3.tgz#cece8f092d28eb6f9c6b23e4138ff5d7260897ef" + integrity sha512-NDe7yjW18gfYQb1GIEQr1T8sB1GUAb1HB62pdAEw+SK6lUW7OFPKQqCOlRhZ6qJXsw9KxMnyYIprLZT4FZdYdQ== dependencies: - "@lit/reactive-element" "^1.0.0" - lit-html "^2.0.0" + "@lit/reactive-element" "^1.0.0-rc.2" + lit-html "^2.0.0-rc.4" -lit-html@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.0.0.tgz#ba6779269c382e66d7403a96ed99516ccc3d658b" - integrity sha512-tJsCapCmc0vtLj6harqd6HfCxnlt/RSkgowtz4SC9dFE3nSL38Tb33I5HMDiyJsRjQZRTgpVsahrnDrR9wg27w== +lit-html@^2.0.0-rc.4: + version "2.0.0-rc.4" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.0.0-rc.4.tgz#1015fa8f1f7c8c5b79999ed0bc11c3b79ff1aab5" + integrity sha512-WSLGu3vxq7y8q/oOd9I3zxyBELNLLiDk6gAYoKK4PGctI5fbh6lhnO/jVBdy0PV/vTc+cLJCA/occzx3YoNPeg== dependencies: - "@types/trusted-types" "^2.0.2" + "@types/trusted-types" "^1.0.1" -lit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lit/-/lit-2.0.0.tgz#7710095dc518d9858dde579e9c76b9eed71e98ba" - integrity sha512-pqi5O/wVzQ9Bn4ERRoYQlt1EAUWyY5Wv888vzpoArbtChc+zfUv1XohRqSdtQZYCogl0eHKd+MQwymg2XJfECg== +lit@^2.0.0-rc.1, lit@^2.0.0-rc.2: + version "2.0.0-rc.3" + resolved "https://registry.yarnpkg.com/lit/-/lit-2.0.0-rc.3.tgz#8b6a85268aba287c11125dfe57e88e0bc09beaff" + integrity sha512-UZDLWuspl7saA+WvS0e+TE3NdGGE05hOIwUPTWiibs34c5QupcEzpjB/aElt79V9bELQVNbUUwa0Ow7D1Wuszw== dependencies: - "@lit/reactive-element" "^1.0.0" - lit-element "^3.0.0" - lit-html "^2.0.0" + "@lit/reactive-element" "^1.0.0-rc.2" + lit-element "^3.0.0-rc.2" + lit-html "^2.0.0-rc.4" load-json-file@^4.0.0: version "4.0.0" @@ -6145,6 +7193,13 @@ make-fetch-happen@^9.0.1: socks-proxy-agent "^6.0.0" ssri "^8.0.0" +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + map-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" @@ -6850,6 +7905,11 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== +morphdom@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e" + integrity sha512-Y8YRbAEP3eKykroIBWrjcfMw7mmwJfjhqdpSvoqinu8Y702nAwikpXcNFDiIkyvfCLxLM9Wu95RZqo4a9jFBaA== + mri@^1.1.0: version "1.1.6" resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6" @@ -6979,6 +8039,16 @@ node-gyp@^7.1.0: tar "^6.0.2" which "^2.0.2" +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + node-releases@^1.1.75: version "1.1.75" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.75.tgz#6dd8c876b9897a1b8e5a02de26afa79bb54ebbfe" @@ -7214,6 +8284,11 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -7304,6 +8379,18 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -7354,6 +8441,11 @@ outdent@^0.5.0: resolved "https://registry.yarnpkg.com/outdent/-/outdent-0.5.0.tgz#9e10982fdc41492bb473ad13840d22f9655be2ff" integrity sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q== +p-each-series@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== + p-filter@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" @@ -7658,6 +8750,11 @@ parse5-htmlparser2-tree-adapter@^6.0.1: dependencies: parse5 "^6.0.1" +parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parse5@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" @@ -7670,11 +8767,6 @@ parse5@^5.1.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== -parse5@^6.0.0, parse5@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" - integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== - parseurl@^1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -7794,6 +8886,13 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -7928,6 +9027,11 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + prepend-http@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-3.0.1.tgz#3e724d58fd5867465b300bb9615009fa2f8ee3b6" @@ -7950,6 +9054,16 @@ prettier@^2.3.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== +pretty-format@^27.0.0, pretty-format@^27.1.0: + version "27.1.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.1.0.tgz#022f3fdb19121e0a2612f3cff8d724431461b9ca" + integrity sha512-4aGaud3w3rxAO6OXmK3fwBFQ0bctIOG3/if+jYEFGNGIs0EvuidQm3bZ9mlP2/t9epLNC/12czabfy7TZNSwVA== + dependencies: + "@jest/types" "^27.1.0" + ansi-regex "^5.0.0" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-format@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-3.8.0.tgz#bfbed56d5e9a776645f4b1ff7aa1a3ac4fa3c385" @@ -7988,7 +9102,7 @@ promise-retry@^2.0.1: err-code "^2.0.2" retry "^0.12.0" -prompts@^2.4.1: +prompts@^2.0.1, prompts@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== @@ -8053,7 +9167,7 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.28: +psl@^1.1.28, psl@^1.1.33: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== @@ -8151,6 +9265,11 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" @@ -8689,6 +9808,13 @@ sass@^1.38.1: dependencies: chokidar ">=3.0.0 <4.0.0" +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" @@ -8919,7 +10045,7 @@ source-map-js@^0.6.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== -source-map-support@~0.5.12: +source-map-support@^0.5.6, source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -9054,6 +10180,13 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" +stack-utils@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== + dependencies: + escape-string-regexp "^2.0.0" + start-server-and-test@^1.12.6: version "1.13.1" resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-1.13.1.tgz#c06eb18c3f31d610724722b7eecbdf2550b03582" @@ -9111,6 +10244,14 @@ string-hash@^1.1.1: resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -9305,13 +10446,20 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-esm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-esm/-/supports-esm-1.0.0.tgz#7cc567747d0745e2b77b331c9b9cae13cf4dc60e" @@ -9319,6 +10467,14 @@ supports-esm@^1.0.0: dependencies: has-package-exports "^1.1.0" +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + svelte-hmr@^0.14.7: version "0.14.7" resolved "https://registry.yarnpkg.com/svelte-hmr/-/svelte-hmr-0.14.7.tgz#7fa8261c7b225d9409f0a86f3b9ea5c3ca6f6607" @@ -9329,6 +10485,11 @@ svelte@^3.42.3: resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.42.3.tgz#a7687a43ff6aa12263e03cf56219cd21eff5372d" integrity sha512-pbdtdNZEx2GBqSM6XEgPoHbwtvWBwFLt/1bRmzsyXZO+i424wFnPe7O5B3GOJDPFSxPRztumAW3mL5LPzecWUg== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + table@^6.0.9: version "6.7.1" resolved "https://registry.yarnpkg.com/table/-/table-6.7.1.tgz#ee05592b7143831a8c94f3cee6aae4c1ccef33e2" @@ -9431,6 +10592,14 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + terser@^4.6.3: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" @@ -9440,6 +10609,15 @@ terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -9450,6 +10628,11 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= +throat@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375" + integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== + through2-sink@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/through2-sink/-/through2-sink-1.0.0.tgz#5f106bba1d7330dad3cba5c0ab1863923256c399" @@ -9516,6 +10699,11 @@ tmp@^0.2.1: dependencies: rimraf "^3.0.0" +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -9546,6 +10734,15 @@ tough-cookie@^2.3.1, tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tough-cookie@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + tr46@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" @@ -9636,6 +10833,18 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" @@ -9691,7 +10900,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.4.2: +typescript@^4.3.5, typescript@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== @@ -9909,7 +11118,7 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== -universalify@^0.1.0: +universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== @@ -10015,6 +11224,15 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +v8-to-istanbul@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz#4229f2a99e367f3f018fa1d5c2b8ec684667c69c" + integrity sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -10088,10 +11306,10 @@ vfile@^5.0.0: unist-util-stringify-position "^3.0.0" vfile-message "^3.0.0" -vite@^2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/vite/-/vite-2.5.1.tgz#953c71a034c07b3ae0448d57664ec9c6862f23a8" - integrity sha512-FwmLbbz8MB1pBs9dKoRDgpiqoijif8hSK1+NNUYc12/cnf+pM2UFhhQ1rcpXgbMhm/5c2USZdVAf0FSkSxaFDA== +vite@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-2.5.2.tgz#3963a4ec1e6ecae49359eddfdd67f6cb1e6e07a1" + integrity sha512-JK5uhiVyMqHiAJbgBa8rCvpP8bEhAE9dKDv1gCmP+EUP2FSPmEeW3WXlCXauPB3MDa8behPW+ntyNXqnGaxslg== dependencies: esbuild "^0.12.17" postcss "^8.3.6" @@ -10114,6 +11332,20 @@ vue@^3.2.6: "@vue/runtime-dom" "3.2.6" "@vue/shared" "3.2.6" +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + wait-on@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" @@ -10125,6 +11357,13 @@ wait-on@6.0.0: minimist "^1.2.5" rxjs "^7.1.0" +walker@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -10137,12 +11376,29 @@ web-namespaces@^2.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-2.0.0.tgz#1f6a2d7b5823329abaedeb6bdf09ef2fed35db13" integrity sha512-dE7ELZRVWh0ceQsRgkjLgsAvwTuv3kcjSY/hLjqL0llleUlQBDjE9JkB9FCBY5F2mnFEwiyJoowl8+NVGHe8dw== +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + webidl-conversions@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== -whatwg-url@^8.4.0: +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== @@ -10222,7 +11478,7 @@ win-release@^1.0.0: dependencies: semver "^5.0.1" -word-wrap@^1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -10314,6 +11570,21 @@ ws@^6.1.0: dependencies: async-limiter "~1.0.0" +ws@^7.4.6: + version "7.5.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.4.tgz#56bfa20b167427e138a7795de68d134fe92e21f9" + integrity sha512-zP9z6GXm6zC27YtspwH99T3qTG7bBFv2VIkeHstMLrLlDJuzA7tQ5ls3OJ1hOGGCzTQPniNJoHXIAOS0Jljohg== + +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -10389,7 +11660,7 @@ yargs@^15.1.0: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.2.0: +yargs@^16.0.3, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==