diff options
author | 2022-04-19 13:52:15 -0400 | |
---|---|---|
committer | 2022-04-19 13:52:15 -0400 | |
commit | 0247b54270e2befab91b9e65029ba929ac26381d (patch) | |
tree | 185f3de5ac064fc3af43bc3bf6b0b965193f7981 | |
parent | 9e00f6d5462f75dcb4da6946db6c508260147e11 (diff) | |
download | astro-0247b54270e2befab91b9e65029ba929ac26381d.tar.gz astro-0247b54270e2befab91b9e65029ba929ac26381d.tar.zst astro-0247b54270e2befab91b9e65029ba929ac26381d.zip |
Refactor: remove all legacy build logic from codebase (#3141)
* refactor: remove legacy build flag
* refactor: remove legacy style maps
* chore: changeset
* refactor: nuke vite-plugin-build-html
* deps: remove parse5
* tests: restore user provided doctype support!
* deps: remove @web/parse5-utils
* deps: change srcset-parse to dev dep
* chore: remove unused utils
* refactor: remove unused style mapping
* unrelated fix: add .test to astro-markdown-css
* refactor: remove unused astro-style with test update
* chore: remove unused buildTime var
23 files changed, 56 insertions, 1087 deletions
diff --git a/.changeset/three-pigs-hunt.md b/.changeset/three-pigs-hunt.md new file mode 100644 index 000000000..c72222676 --- /dev/null +++ b/.changeset/three-pigs-hunt.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Astro internals: remove all legacy build logic from the codebase, now that the legacy build flag has been removed diff --git a/packages/astro/package.json b/packages/astro/package.json index 7567193fb..769285d31 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -86,7 +86,6 @@ "@babel/traverse": "^7.17.9", "@proload/core": "^0.2.2", "@proload/plugin-tsm": "^0.1.1", - "@web/parse5-utils": "^1.3.0", "ast-types": "^0.14.2", "boxen": "^6.2.1", "ci-info": "^3.3.0", @@ -109,7 +108,6 @@ "micromorph": "^0.1.2", "mime": "^3.0.0", "ora": "^6.1.0", - "parse5": "^6.0.1", "path-browserify": "^1.0.1", "path-to-regexp": "^6.2.0", "postcss": "^8.4.12", @@ -128,7 +126,6 @@ "sirv": "^2.0.2", "slash": "^4.0.0", "sourcemap-codec": "^1.4.8", - "srcset-parse": "^1.1.0", "string-width": "^5.1.2", "strip-ansi": "^7.0.1", "supports-esm": "^1.0.0", @@ -163,7 +160,8 @@ "chai": "^4.3.6", "cheerio": "^1.0.0-rc.10", "mocha": "^9.2.2", - "sass": "^1.50.0" + "sass": "^1.50.0", + "srcset-parse": "^1.1.0" }, "engines": { "node": "^14.15.0 || >=16.0.0", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index ffb62a15f..3047ae1b2 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -983,7 +983,6 @@ export interface SSRElement { export interface SSRMetadata { renderers: SSRLoadedRenderer[]; pathname: string; - legacyBuild: boolean; } export interface SSRResult { diff --git a/packages/astro/src/cli/index.ts b/packages/astro/src/cli/index.ts index 308ab6a5f..45f50f832 100644 --- a/packages/astro/src/cli/index.ts +++ b/packages/astro/src/cli/index.ts @@ -48,7 +48,6 @@ function printAstroHelp() { ['--host [optional IP]', 'Expose server on network'], ['--config <path>', 'Specify the path to the Astro config file.'], ['--root <path>', 'Specify the path to the project root folder.'], - ['--legacy-build', 'Use the build strategy prior to 0.24.0'], ['--drafts', 'Include markdown draft pages in the build.'], ['--verbose', 'Enable verbose logging'], ['--silent', 'Disable logging'], diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index c2f5d9a2e..6fb2d61be 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -78,7 +78,6 @@ export class App { const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site); const result = await render({ - legacyBuild: false, links, logging: this.#logging, markdown: manifest.markdown, diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 17b419bb4..36c25546c 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -193,7 +193,6 @@ async function generatePath( const ssr = isBuildingToSSR(opts.astroConfig); const url = new URL(opts.astroConfig.base + removeLeadingForwardSlash(pathname), origin); const options: RenderOptions = { - legacyBuild: false, links, logging, markdown: astroConfig.markdown, diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index 98c8f1e8d..d0c0a026c 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -213,7 +213,6 @@ class AstroBuilder { pageCount: number; buildMode: 'static' | 'ssr'; }) { - const buildTime = performance.now() - timeStart; const total = getTimeStat(timeStart, performance.now()); let messages: string[] = []; diff --git a/packages/astro/src/core/build/internal.ts b/packages/astro/src/core/build/internal.ts index e51e0e5da..9edde85f3 100644 --- a/packages/astro/src/core/build/internal.ts +++ b/packages/astro/src/core/build/internal.ts @@ -30,24 +30,6 @@ export interface BuildInternals { * A map for page-specific information by a client:only component */ pagesByClientOnly: Map<string, Set<PageBuildData>>; - - /** - * chunkToReferenceIdMap maps them to a hash id used to find the final file. - * @deprecated This Map is only used for the legacy build. - */ - chunkToReferenceIdMap: Map<string, string>; - - /** - * This is a mapping of pathname to the string source of all collected inline <style> for a page. - * @deprecated This Map is only used for the legacy build. - */ - astroStyleMap: Map<string, string>; - - /** - * This is a virtual JS module that imports all dependent styles for a page. - * @deprecated This Map is only used for the legacy build. - */ - astroPageStyleMap: Map<string, string>; } /** @@ -71,9 +53,6 @@ export function createBuildInternals(): BuildInternals { return { pureCSSChunks, - chunkToReferenceIdMap, - astroStyleMap, - astroPageStyleMap, hoistedScriptIdToHoistedMap, entrySpecifierToBundleMap: new Map<string, string>(), diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 6eaee4eee..0288f8bc9 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -151,7 +151,6 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp vitePluginPages(opts, internals), rollupPluginAstroBuildCSS({ internals, - legacy: false, target: 'server', }), ...(viteConfig.plugins || []), @@ -222,7 +221,6 @@ async function clientBuild( vitePluginHoistedScripts(astroConfig, internals), rollupPluginAstroBuildCSS({ internals, - legacy: false, target: 'client', }), ...(viteConfig.plugins || []), diff --git a/packages/astro/src/core/path.ts b/packages/astro/src/core/path.ts index 280d5d24f..177723177 100644 --- a/packages/astro/src/core/path.ts +++ b/packages/astro/src/core/path.ts @@ -38,11 +38,3 @@ export function startsWithDotSlash(path: string) { export function isRelativePath(path: string) { return startsWithDotDotSlash(path) || startsWithDotSlash(path); } - -export function prependDotSlash(path: string) { - if (isRelativePath(path)) { - return path; - } - - return './' + path; -} diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index 59ae6f010..0adac347e 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -66,7 +66,6 @@ export async function getParamsAndProps( } export interface RenderOptions { - legacyBuild: boolean; logging: LogOptions; links: Set<SSRElement>; markdown: MarkdownRenderingOptions; @@ -87,7 +86,6 @@ export async function render( opts: RenderOptions ): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> { const { - legacyBuild, links, logging, origin, @@ -128,7 +126,6 @@ export async function render( throw new Error(`Unable to SSR non-Astro component (${route?.component})`); const result = createResult({ - legacyBuild, links, logging, markdown, diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts index 462f8101a..410cb965b 100644 --- a/packages/astro/src/core/render/dev/index.ts +++ b/packages/astro/src/core/render/dev/index.ts @@ -102,18 +102,13 @@ export async function render( routeCache, viteServer, } = ssrOpts; - // TODO: clean up "legacy" flag passed through helper functions - const isLegacyBuild = false; - // Add hoisted script tags const scripts = createModuleScriptElementWithSrcSet( - !isLegacyBuild && mod.hasOwnProperty('$$metadata') - ? Array.from(mod.$$metadata.hoistedScriptPaths()) - : [] + mod.hasOwnProperty('$$metadata') ? Array.from(mod.$$metadata.hoistedScriptPaths()) : [] ); // Inject HMR scripts - if (mod.hasOwnProperty('$$metadata') && mode === 'development' && !isLegacyBuild) { + if (mod.hasOwnProperty('$$metadata') && mode === 'development') { scripts.add({ props: { type: 'module', src: '/@vite/client' }, children: '', @@ -138,29 +133,25 @@ export async function render( // Pass framework CSS in as link tags to be appended to the page. let links = new Set<SSRElement>(); - if (!isLegacyBuild) { - [...(await getStylesForURL(filePath, viteServer))].forEach((href) => { - if (mode === 'development' && svelteStylesRE.test(href)) { - scripts.add({ - props: { type: 'module', src: href }, - children: '', - }); - } else { - links.add({ - props: { - rel: 'stylesheet', - href, - 'data-astro-injected': true, - }, - children: '', - }); - } - }); - } + [...(await getStylesForURL(filePath, viteServer))].forEach((href) => { + if (mode === 'development' && svelteStylesRE.test(href)) { + scripts.add({ + props: { type: 'module', src: href }, + children: '', + }); + } else { + links.add({ + props: { + rel: 'stylesheet', + href, + 'data-astro-injected': true, + }, + children: '', + }); + } + }); let content = await coreRender({ - // TODO: Remove this flag once legacyBuild support is removed - legacyBuild: isLegacyBuild, links, logging, markdown: astroConfig.markdown, @@ -197,41 +188,6 @@ export async function render( // inject tags const tags: vite.HtmlTagDescriptor[] = []; - // dev only: inject Astro HMR client - if (mode === 'development' && isLegacyBuild) { - tags.push({ - tag: 'script', - attrs: { type: 'module' }, - // HACK: inject the direct contents of our `astro/runtime/client/hmr.js` to ensure - // `import.meta.hot` is properly handled by Vite - children: await getHmrScript(), - injectTo: 'head', - }); - } - - // inject CSS - if (isLegacyBuild) { - [...(await getStylesForURL(filePath, viteServer))].forEach((href) => { - if (mode === 'development' && svelteStylesRE.test(href)) { - tags.push({ - tag: 'script', - attrs: { type: 'module', src: href }, - injectTo: 'head', - }); - } else { - tags.push({ - tag: 'link', - attrs: { - rel: 'stylesheet', - href, - 'data-astro-injected': true, - }, - injectTo: 'head', - }); - } - }); - } - // add injected tags let html = injectTags(content.html, tags); diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index 8fd856084..3a8a71235 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -22,7 +22,6 @@ function onlyAvailableInSSR(name: string) { export interface CreateResultArgs { ssr: boolean; - legacyBuild: boolean; logging: LogOptions; origin: string; markdown: MarkdownRenderingOptions; @@ -101,7 +100,7 @@ class Slots { let renderMarkdown: any = null; export function createResult(args: CreateResultArgs): SSRResult { - const { legacyBuild, markdown, params, pathname, renderers, request, resolve, site } = args; + const { markdown, params, pathname, renderers, request, resolve, site } = args; const url = new URL(request.url); const canonicalURL = createCanonicalURL('.' + pathname, site ?? url.origin); @@ -138,16 +137,15 @@ export function createResult(args: CreateResultArgs): SSRResult { } : onlyAvailableInSSR('Astro.redirect'), resolve(path: string) { - if (!legacyBuild) { - let extra = `This can be replaced with a dynamic import like so: await import("${path}")`; - if (isCSSRequest(path)) { - extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this: + let extra = `This can be replaced with a dynamic import like so: await import("${path}")`; + if (isCSSRequest(path)) { + extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this: --- import "${path}"; --- `; - } else if (isScriptRequest(path)) { - extra = `It looks like you are resolving scripts. If you are adding a script tag, replace with this: + } else if (isScriptRequest(path)) { + extra = `It looks like you are resolving scripts. If you are adding a script tag, replace with this: <script type="module" src={(await import("${path}?url")).default}></script> @@ -157,21 +155,18 @@ or consider make it a module like so: import MyModule from "${path}"; </script> `; - } - - warn( - args.logging, - `deprecation`, - `${bold( - 'Astro.resolve()' - )} is deprecated. We see that you are trying to resolve ${path}. -${extra}` - ); - // Intentionally return an empty string so that it is not relied upon. - return ''; } - return astroGlobal.resolve(path); + warn( + args.logging, + `deprecation`, + `${bold( + 'Astro.resolve()' + )} is deprecated. We see that you are trying to resolve ${path}. +${extra}` + ); + // Intentionally return an empty string so that it is not relied upon. + return ''; }, slots: astroSlots, } as unknown as AstroGlobal; @@ -206,7 +201,6 @@ ${extra}` _metadata: { renderers, pathname, - legacyBuild, }, }; diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 84047025f..72b1d92c0 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -543,16 +543,7 @@ const uniqueElements = (item: any, index: number, all: any[]) => { // Renders a page to completion by first calling the factory callback, waiting for its result, and then appending // styles and scripts into the head. export async function renderHead(result: SSRResult): Promise<string> { - const styles = Array.from(result.styles) - .filter(uniqueElements) - .map((style) => { - // TODO: clean up legacyBuild from metadata - const styleChildren = !result._metadata.legacyBuild ? '' : style.children; - return renderElement('style', { - children: styleChildren, - props: { ...style.props, 'astro-style': true }, - }); - }); + const styles = []; let needsHydrationStyles = false; const scripts = Array.from(result.scripts) .filter(uniqueElements) @@ -568,7 +559,7 @@ export async function renderHead(result: SSRResult): Promise<string> { if (needsHydrationStyles) { styles.push( renderElement('style', { - props: { 'astro-style': true }, + props: {}, children: 'astro-root, astro-fragment { display: contents; }', }) ); diff --git a/packages/astro/src/vite-plugin-build-css/index.ts b/packages/astro/src/vite-plugin-build-css/index.ts index 7a856df5d..55771ffb8 100644 --- a/packages/astro/src/vite-plugin-build-css/index.ts +++ b/packages/astro/src/vite-plugin-build-css/index.ts @@ -19,27 +19,6 @@ const ASTRO_STYLE_PREFIX = '@astro-inline-style'; const ASTRO_PAGE_STYLE_PREFIX = '@astro-page-all-styles'; -export function getAstroPageStyleId(pathname: string) { - let styleId = ASTRO_PAGE_STYLE_PREFIX + pathname; - if (styleId.endsWith('/')) { - styleId += 'index'; - } - styleId += '.js'; - return styleId; -} - -export function getAstroStyleId(pathname: string) { - let styleId = ASTRO_STYLE_PREFIX + pathname; - if (styleId.endsWith('/')) { - styleId += 'index'; - } - return styleId; -} - -export function getAstroStylePathFromId(id: string) { - return id.substr(ASTRO_STYLE_PREFIX.length + 1); -} - function isStyleVirtualModule(id: string) { return id.startsWith(ASTRO_STYLE_PREFIX); } @@ -54,12 +33,11 @@ function isRawOrUrlModule(id: string) { interface PluginOptions { internals: BuildInternals; - legacy: boolean; target: 'client' | 'server'; } export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin { - const { internals, legacy } = options; + const { internals } = options; const styleSourceMap = new Map<string, string>(); function* walkStyles( @@ -153,16 +131,6 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin { return undefined; }, - async load(id) { - if (isPageStyleVirtualModule(id)) { - return internals.astroPageStyleMap.get(id) || null; - } - if (isStyleVirtualModule(id)) { - return internals.astroStyleMap.get(id) || null; - } - return null; - }, - async transform(value, id) { if (isStyleVirtualModule(id)) { styleSourceMap.set(id, value); @@ -203,7 +171,6 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin { source: minifiedCSS, }); - internals.chunkToReferenceIdMap.set(chunk.fileName, referenceId); if (chunk.type === 'chunk') { const fileName = this.getFileName(referenceId); for (const pageData of getPageDatasByChunk(internals, chunk)) { @@ -236,26 +203,10 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin { ); // Crawl the module graph to find CSS chunks to create - if (!legacy) { - await addStyles.call(this); - } + await addStyles.call(this); for (const [chunkId, chunk] of Object.entries(bundle)) { if (chunk.type === 'chunk') { - // This find shared chunks of CSS and adds them to the main CSS chunks, - // so that shared CSS is added to the page. - for (const { css: cssSet } of getPageDatasByChunk(internals, chunk)) { - for (const imp of chunk.imports) { - if (internals.chunkToReferenceIdMap.has(imp) && !pureChunkFilenames.has(imp)) { - const referenceId = internals.chunkToReferenceIdMap.get(imp)!; - const fileName = this.getFileName(referenceId); - if (!cssSet.has(fileName)) { - cssSet.add(fileName); - } - } - } - } - // Removes imports for pure CSS chunks. if (hasPureCSSChunks) { if (internals.pureCSSChunks.has(chunk) && !chunk.exports.length) { diff --git a/packages/astro/src/vite-plugin-build-html/add-rollup-input.ts b/packages/astro/src/vite-plugin-build-html/add-rollup-input.ts deleted file mode 100644 index 79feb3a7d..000000000 --- a/packages/astro/src/vite-plugin-build-html/add-rollup-input.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { InputOptions } from 'rollup'; - -function fromEntries<V>(entries: [string, V][]) { - const obj: Record<string, V> = {}; - for (const [k, v] of entries) { - obj[k] = v; - } - return obj; -} - -export function addRollupInput(inputOptions: InputOptions, newInputs: string[]): InputOptions { - // Add input module ids to existing input option, whether it's a string, array or object - // this way you can use multiple html plugins all adding their own inputs - if (!inputOptions.input) { - return { ...inputOptions, input: newInputs }; - } - - if (typeof inputOptions.input === 'string') { - return { - ...inputOptions, - input: [inputOptions.input, ...newInputs], - }; - } - - if (Array.isArray(inputOptions.input)) { - return { - ...inputOptions, - input: [...inputOptions.input, ...newInputs], - }; - } - - if (typeof inputOptions.input === 'object') { - return { - ...inputOptions, - input: { - ...inputOptions.input, - ...fromEntries(newInputs.map((i) => [i.split('/').slice(-1)[0].split('.')[0], i])), - }, - }; - } - - throw new Error(`Unknown rollup input type. Supported inputs are string, array and object.`); -} diff --git a/packages/astro/src/vite-plugin-build-html/extract-assets.ts b/packages/astro/src/vite-plugin-build-html/extract-assets.ts deleted file mode 100644 index ffc0446a3..000000000 --- a/packages/astro/src/vite-plugin-build-html/extract-assets.ts +++ /dev/null @@ -1,229 +0,0 @@ -import { Document, Element, Node } from 'parse5'; -import npath from 'path'; -import { findElements, getTagName, getAttribute, findNodes, hasAttribute } from '@web/parse5-utils'; -import adapter from 'parse5/lib/tree-adapters/default.js'; - -const hashedLinkRels = ['stylesheet', 'preload']; -const linkRels = [...hashedLinkRels, 'icon', 'manifest', 'apple-touch-icon', 'mask-icon']; -const windowsPathRE = /^[A-Z]:\//; - -function getSrcSetUrls(srcset: string) { - if (!srcset) { - return []; - } - const srcsetParts = srcset.includes(',') ? srcset.split(',') : [srcset]; - const urls = srcsetParts - .map((url) => url.trim()) - .map((url) => (url.includes(' ') ? url.split(' ')[0] : url)); - return urls; -} - -function extractFirstUrlOfSrcSet(node: Element) { - const srcset = getAttribute(node, 'srcset'); - if (!srcset) { - return ''; - } - const urls = getSrcSetUrls(srcset); - return urls[0]; -} - -function isAsset(node: Element) { - let path = ''; - switch (getTagName(node)) { - case 'img': - path = getAttribute(node, 'src') ?? ''; - break; - case 'source': - path = extractFirstUrlOfSrcSet(node) ?? ''; - break; - case 'link': - if (linkRels.includes(getAttribute(node, 'rel') ?? '')) { - path = getAttribute(node, 'href') ?? ''; - } - break; - case 'meta': - if (getAttribute(node, 'property') === 'og:image' && getAttribute(node, 'content')) { - path = getAttribute(node, 'content') ?? ''; - } - break; - case 'script': - if (getAttribute(node, 'type') !== 'module' && getAttribute(node, 'src')) { - path = getAttribute(node, 'src') ?? ''; - } - break; - default: - return false; - } - if (!path) { - return false; - } - // Windows fix: if path starts with C:/, avoid URL parsing - if (windowsPathRE.test(path)) { - return true; - } - try { - new URL(path); - return false; - } catch (e) { - return true; - } -} - -function isInlineScript(node: Element): boolean { - switch (getTagName(node)) { - case 'script': - if (getAttribute(node, 'type') === 'module' && !getAttribute(node, 'src')) { - return true; - } - return false; - default: - return false; - } -} - -function isExternalScript(node: Element): boolean { - switch (getTagName(node)) { - case 'script': - if (hasAttribute(node, 'src')) { - return true; - } - return false; - default: - return false; - } -} - -function isInlineStyle(node: Element): boolean { - return getTagName(node) === 'style'; -} - -export function isStylesheetLink(node: Element): boolean { - return getTagName(node) === 'link' && getAttribute(node, 'rel') === 'stylesheet'; -} - -export function isHashedAsset(node: Element) { - switch (getTagName(node)) { - case 'img': - return true; - case 'source': - return true; - case 'script': - return true; - case 'link': - return hashedLinkRels.includes(getAttribute(node, 'rel')!); - case 'meta': - return true; - default: - return false; - } -} - -export function resolveAssetFilePath( - browserPath: string, - htmlDir: string, - projectRootDir: string, - absolutePathPrefix?: string -) { - const _browserPath = - absolutePathPrefix && browserPath[0] === '/' - ? '/' + npath.posix.relative(absolutePathPrefix, browserPath) - : browserPath; - return npath.join( - _browserPath.startsWith('/') ? projectRootDir : htmlDir, - _browserPath.split('/').join(npath.sep) - ); -} - -export function getSourceAttribute(node: Element) { - switch (getTagName(node)) { - case 'img': { - return 'src'; - } - case 'source': { - return 'srcset'; - } - case 'link': { - return 'href'; - } - case 'script': { - return 'src'; - } - case 'meta': { - return 'content'; - } - default: - throw new Error(`Unknown node with tagname ${getTagName(node)}`); - } -} - -export interface Location { - start: number; - end: number; -} - -export function getSourcePaths(node: Element) { - const key = getSourceAttribute(node); - - let location: Location = { start: 0, end: 0 }; - const src = getAttribute(node, key); - if (node.sourceCodeLocation) { - let loc = node.sourceCodeLocation.attrs?.[key]; - if (loc) { - location.start = loc.startOffset; - location.end = loc.endOffset; - } - } - if (typeof key !== 'string' || src === '') { - throw new Error(`Missing attribute ${key} in element ${node.nodeName}`); - } - - let paths: { path: string; location: Location }[] = []; - if (src && key === 'srcset') { - paths = getSrcSetUrls(src).map((path) => ({ - path, - location, - })); - } else if (src) { - paths.push({ - path: src, - location, - }); - } - - return paths; -} - -export function getTextContent(node: Node): string { - if (adapter.isCommentNode(node)) { - return node.data || ''; - } - if (adapter.isTextNode(node)) { - return node.value || ''; - } - const subtree = findNodes(node, (n) => adapter.isTextNode(n)); - return subtree.map(getTextContent).join(''); -} - -export function getAttributes(node: Element): Record<string, any> { - return Object.fromEntries(node.attrs.map((attr) => [attr.name, attr.value])); -} - -export function findAssets(document: Document) { - return findElements(document, isAsset); -} - -export function findInlineScripts(document: Document) { - return findElements(document, isInlineScript); -} - -export function findExternalScripts(document: Document) { - return findElements(document, isExternalScript); -} - -export function findInlineStyles(document: Document) { - return findElements(document, isInlineStyle); -} - -export function findStyleLinks(document: Document) { - return findElements(document, isStylesheetLink); -} diff --git a/packages/astro/src/vite-plugin-build-html/index.ts b/packages/astro/src/vite-plugin-build-html/index.ts deleted file mode 100644 index 34f7b3730..000000000 --- a/packages/astro/src/vite-plugin-build-html/index.ts +++ /dev/null @@ -1,537 +0,0 @@ -import { - createElement, - createScript, - getAttribute, - hasAttribute, - insertBefore, - remove, - setAttribute, -} from '@web/parse5-utils'; -import { promises as fs } from 'fs'; -import parse5 from 'parse5'; -import * as npath from 'path'; -import type { OutputChunk, PluginContext, PreRenderedChunk } from 'rollup'; -import srcsetParse from 'srcset-parse'; -import type { Plugin as VitePlugin, ViteDevServer } from 'vite'; -import type { AstroConfig } from '../@types/astro'; -import type { BuildInternals } from '../core/build/internal'; -import type { AllPagesData } from '../core/build/types'; -import type { LogOptions } from '../core/logger/core.js'; -import { prependDotSlash } from '../core/path.js'; -import { render as ssrRender } from '../core/render/dev/index.js'; -import { RouteCache } from '../core/render/route-cache.js'; -import { getOutputFilename } from '../core/util.js'; -import { getAstroPageStyleId, getAstroStyleId } from '../vite-plugin-build-css/index.js'; -import { addRollupInput } from './add-rollup-input.js'; -import { - findAssets, - findExternalScripts, - findInlineScripts, - findInlineStyles, - getAttributes, - getTextContent, -} from './extract-assets.js'; -import { - hasSrcSet, - isBuildableImage, - isBuildableLink, - isHoistedScript, - isInSrcDirectory, -} from './util.js'; -import { createRequest } from '../core/request.js'; - -// This package isn't real ESM, so have to coerce it -const matchSrcset: typeof srcsetParse = (srcsetParse as any).default; - -const PLUGIN_NAME = '@astro/rollup-plugin-build'; -const ASTRO_PAGE_PREFIX = '@astro-page'; -const ASTRO_SCRIPT_PREFIX = '@astro-script'; - -const ASTRO_EMPTY = '@astro-empty'; - -interface PluginOptions { - astroConfig: AstroConfig; - internals: BuildInternals; - logging: LogOptions; - allPages: AllPagesData; - pageNames: string[]; - origin: string; - routeCache: RouteCache; - viteServer: ViteDevServer; -} - -function relativePath(from: string, to: string): string { - const rel = npath.posix.relative(from, to); - return prependDotSlash(rel); -} - -export function rollupPluginAstroScanHTML(options: PluginOptions): VitePlugin { - const { astroConfig, internals, logging, origin, allPages, routeCache, viteServer, pageNames } = - options; - - // The filepath root of the src folder - const srcRoot = astroConfig.srcDir.pathname; - // The web path of the src folter - const srcRootWeb = srcRoot.substr(astroConfig.root.pathname.length - 1); - - // A map of pages to rendered HTML - const renderedPageMap = new Map<string, string>(); - - // - const astroScriptMap = new Map<string, string>(); - const astroPageMap = new Map<string, string>(); - const astroAssetMap = new Map<string, Promise<Buffer>>(); - - const cssChunkMap = new Map<string, string[]>(); - const pageStyleImportOrder: string[] = []; - - return { - name: PLUGIN_NAME, - - enforce: 'pre', - - async options(inputOptions) { - const htmlInput: Set<string> = new Set(); - const assetInput: Set<string> = new Set(); - const jsInput: Set<string> = new Set(); - - for (const [component, pageData] of Object.entries(allPages)) { - const [renderers, mod] = pageData.preload; - - // Hydrated components are statically identified. - for (const path of mod.$$metadata.hydratedComponentPaths()) { - jsInput.add(path); - } - - for (const pathname of pageData.paths) { - pageNames.push(pathname.replace(/\/?$/, '/').replace(/^\//, '')); - const id = ASTRO_PAGE_PREFIX + pathname; - const response = await ssrRender(renderers, mod, { - astroConfig, - filePath: new URL(`./${component}`, astroConfig.root), - logging, - request: createRequest({ - url: new URL(origin + pathname), - headers: new Headers(), - logging, - ssr: false, - }), - mode: 'production', - origin, - pathname, - route: pageData.route, - routeCache, - viteServer, - }); - - if (response.type !== 'html') { - continue; - } - - const html = response.html; - renderedPageMap.set(id, html); - - const document = parse5.parse(html, { - sourceCodeLocationInfo: true, - }); - - const frontEndImports = []; - for (const script of findInlineScripts(document)) { - const astroScript = getAttribute(script, 'astro-script'); - if (astroScript) { - const js = getTextContent(script); - const scriptId = ASTRO_SCRIPT_PREFIX + astroScript; - frontEndImports.push(scriptId); - astroScriptMap.set(scriptId, js); - } - } - - for (const script of findExternalScripts(document)) { - if (isHoistedScript(script)) { - const astroScript = getAttribute(script, 'astro-script'); - const src = getAttribute(script, 'src'); - if (astroScript) { - const js = `import '${src}';`; - const scriptId = ASTRO_SCRIPT_PREFIX + astroScript; - frontEndImports.push(scriptId); - astroScriptMap.set(scriptId, js); - } - } else if (isInSrcDirectory(script, 'src', srcRoot, srcRootWeb)) { - const src = getAttribute(script, 'src'); - if (src) jsInput.add(src); - } - } - - const assetImports = []; - const styleId = getAstroStyleId(pathname); - let styles = 0; - for (const node of findInlineStyles(document)) { - if (hasAttribute(node, 'astro-style')) { - const style = getTextContent(node) || ' '; // If an empty node, add whitespace - const thisStyleId = `${styleId}/${++styles}.css`; - internals.astroStyleMap.set(thisStyleId, style); - assetImports.push(thisStyleId); - } - } - - for (let node of findAssets(document)) { - if (isBuildableLink(node, srcRoot, srcRootWeb)) { - const href = getAttribute(node, 'href')!; - assetImports.push(href); - } - - if (isBuildableImage(node, srcRoot, srcRootWeb)) { - const src = getAttribute(node, 'src'); - if (src?.startsWith(srcRoot) && !astroAssetMap.has(src)) { - astroAssetMap.set(src, fs.readFile(new URL(`file://${src}`))); - } else if (src?.startsWith(srcRootWeb) && !astroAssetMap.has(src)) { - const resolved = new URL('.' + src, astroConfig.root); - astroAssetMap.set(src, fs.readFile(resolved)); - } - } - - if (hasSrcSet(node)) { - const candidates = matchSrcset(getAttribute(node, 'srcset')!); - for (const { url } of candidates) { - if (url.startsWith(srcRoot) && !astroAssetMap.has(url)) { - astroAssetMap.set(url, fs.readFile(new URL(`file://${url}`))); - } else if (url.startsWith(srcRootWeb) && !astroAssetMap.has(url)) { - const resolved = new URL('.' + url, astroConfig.root); - astroAssetMap.set(url, fs.readFile(resolved)); - } - } - } - } - - if (frontEndImports.length) { - htmlInput.add(id); - const jsSource = frontEndImports.map((sid) => `import '${sid}';`).join('\n'); - astroPageMap.set(id, jsSource); - } - - if (assetImports.length) { - const pageStyleId = getAstroPageStyleId(pathname); - const jsSource = assetImports.map((sid) => `import '${sid}';`).join('\n'); - internals.astroPageStyleMap.set(pageStyleId, jsSource); - assetInput.add(pageStyleId); - - // preserve asset order in the order we encounter them - for (const assetHref of assetImports) { - if (!pageStyleImportOrder.includes(assetHref)) pageStyleImportOrder.push(assetHref); - } - } - } - } - - const allInputs = new Set([...jsInput, ...htmlInput, ...assetInput]); - // You always need at least 1 input, so add an placeholder just so we can build HTML/CSS - if (!allInputs.size) { - allInputs.add(ASTRO_EMPTY); - } - const outOptions = addRollupInput(inputOptions, Array.from(allInputs)); - return outOptions; - }, - - async resolveId(id) { - switch (true) { - case astroScriptMap.has(id): - case astroPageMap.has(id): - case id === ASTRO_EMPTY: { - return id; - } - } - - return undefined; - }, - - async load(id) { - // Load pages - if (astroPageMap.has(id)) { - return astroPageMap.get(id)!; - } - // Load scripts - if (astroScriptMap.has(id)) { - return astroScriptMap.get(id)!; - } - // Give this module actual code so it doesnt warn about an empty chunk - if (id === ASTRO_EMPTY) { - return 'console.log("empty");'; - } - - return null; - }, - - outputOptions(outputOptions) { - Object.assign(outputOptions, { - entryFileNames(chunk: PreRenderedChunk) { - // Removes the `@astro-page` prefix from JS chunk names. - if (chunk.name.startsWith(ASTRO_PAGE_PREFIX)) { - let pageName = chunk.name.substr(ASTRO_PAGE_PREFIX.length + 1); - if (!pageName) { - pageName = 'index'; - } - return `assets/${pageName}.[hash].js`; - } - return 'assets/[name].[hash].js'; - }, - }); - return outputOptions; - }, - - async generateBundle(this: PluginContext, _options, bundle) { - const facadeIdMap = new Map<string, string>(); - for (const [chunkId, output] of Object.entries(bundle)) { - if (output.type === 'chunk') { - const chunk = output as OutputChunk; - const id = chunk.facadeModuleId; - if (id === ASTRO_EMPTY) { - delete bundle[chunkId]; - } else if (id) { - facadeIdMap.set(id, chunk.fileName); - } - } - } - - // Emit assets (images, etc) - const assetIdMap = new Map<string, string>(); - for (const [assetPath, dataPromise] of astroAssetMap) { - const referenceId = this.emitFile({ - type: 'asset', - name: npath.basename(assetPath), - source: await dataPromise, - }); - assetIdMap.set(assetPath, referenceId); - } - - // Sort CSS in order of appearance in HTML (pageStyleImportOrder) - // This is the “global ordering” used below - const sortedCSSChunks = [...internals.pureCSSChunks]; - sortedCSSChunks.sort((a, b) => { - let aIndex = Math.min( - ...Object.keys(a.modules).map((id) => { - const i = pageStyleImportOrder.findIndex((url) => id.endsWith(url)); - return i >= 0 ? i : Infinity; // if -1 is encountered (unknown order), move to the end (Infinity) - }) - ); - let bIndex = Math.min( - ...Object.keys(b.modules).map((id) => { - const i = pageStyleImportOrder.findIndex((url) => id.endsWith(url)); - return i >= 0 ? i : Infinity; - }) - ); - return aIndex - bIndex; - }); - const sortedChunkNames = sortedCSSChunks.map(({ fileName }) => fileName); - - // Create a mapping of chunks to dependent chunks, used to add the proper - // link tags for CSS. - for (const chunk of sortedCSSChunks) { - const chunkModules = [chunk.fileName, ...chunk.imports]; - // For each HTML output, sort CSS in HTML order Note: here we actually - // want -1 to be first. Since the last CSS “wins”, we want to load - // “unknown” (-1) CSS ordering first, followed by “known” ordering at - // the end so it takes priority - chunkModules.sort((a, b) => sortedChunkNames.indexOf(a) - sortedChunkNames.indexOf(b)); - - const referenceIDs: string[] = []; - for (const chunkID of chunkModules) { - const referenceID = internals.chunkToReferenceIdMap.get(chunkID); - if (referenceID) referenceIDs.push(referenceID); - } - for (const id of Object.keys(chunk.modules)) { - cssChunkMap.set(id, referenceIDs); - } - } - - // Keep track of links added so we don't do so twice. - const linkChunksAdded = new Set<string>(); - const appendStyleChunksBefore = ( - ref: parse5.Element, - pathname: string, - referenceIds: string[] | undefined, - attrs: Record<string, any> = {} - ) => { - let added = false; - if (referenceIds) { - const lastNode = ref; - for (const referenceId of referenceIds) { - const chunkFileName = this.getFileName(referenceId); - const relPath = relativePath(pathname, '/' + chunkFileName); - - // This prevents added links more than once per type. - const key = pathname + relPath + attrs.rel || 'stylesheet'; - if (!linkChunksAdded.has(key)) { - linkChunksAdded.add(key); - insertBefore( - lastNode.parentNode, - createElement('link', { - rel: 'stylesheet', - ...attrs, - href: relPath, - }), - lastNode - ); - added = true; - } - } - } - return added; - }; - - for (const [id, html] of renderedPageMap) { - const pathname = id.substr(ASTRO_PAGE_PREFIX.length); - const document = parse5.parse(html, { - sourceCodeLocationInfo: true, - }); - - // This is the module for the page-level bundle which includes - // hoisted scripts and hydrated components. - const pageAssetId = facadeIdMap.get(id); - const bundlePath = '/' + pageAssetId; - - // Update scripts - let pageBundleAdded = false; - - // Update inline scripts. These could be hydrated component scripts or hoisted inline scripts - for (let script of findInlineScripts(document)) { - if (getAttribute(script, 'astro-script') && typeof pageAssetId === 'string') { - if (!pageBundleAdded) { - pageBundleAdded = true; - const relPath = relativePath(pathname, bundlePath); - insertBefore( - script.parentNode, - createScript({ - type: 'module', - src: relPath, - }), - script - ); - } - remove(script); - } - } - - // Update external scripts. These could be hoisted or in the src folder. - for (let script of findExternalScripts(document)) { - if (getAttribute(script, 'astro-script') && typeof pageAssetId === 'string') { - if (!pageBundleAdded) { - pageBundleAdded = true; - const relPath = relativePath(pathname, bundlePath); - insertBefore( - script.parentNode, - createScript({ - type: 'module', - src: relPath, - }), - script - ); - } - remove(script); - } else if (isInSrcDirectory(script, 'src', srcRoot, srcRootWeb)) { - let src = getAttribute(script, 'src'); - // If this is projectRoot relative, get the fullpath to match the facadeId. - if (src?.startsWith(srcRootWeb)) { - src = new URL('.' + src, astroConfig.root).pathname; - } - // On windows the facadeId doesn't start with / but does not Unix :/ - if (src && (facadeIdMap.has(src) || facadeIdMap.has(src.substr(1)))) { - const assetRootPath = '/' + (facadeIdMap.get(src) || facadeIdMap.get(src.substr(1))); - const relPath = relativePath(pathname, assetRootPath); - const attrs = getAttributes(script); - insertBefore( - script.parentNode, - createScript({ - ...attrs, - src: relPath, - }), - script - ); - remove(script); - } - } - } - - const styleId = getAstroPageStyleId(pathname); - let pageCSSAdded = false; - for (const node of findAssets(document)) { - if (isBuildableLink(node, srcRoot, srcRootWeb)) { - const rel = getAttribute(node, 'rel'); - switch (rel) { - case 'stylesheet': { - if (!pageCSSAdded) { - const attrs = getAttributes(node); - delete attrs['data-astro-injected']; - pageCSSAdded = appendStyleChunksBefore( - node, - pathname, - cssChunkMap.get(styleId), - attrs - ); - } - remove(node); - break; - } - case 'preload': { - if (getAttribute(node, 'as') === 'style') { - const attrs = getAttributes(node); - appendStyleChunksBefore(node, pathname, cssChunkMap.get(styleId), attrs); - remove(node); - } - } - } - } - - if (isBuildableImage(node, srcRoot, srcRootWeb)) { - const src = getAttribute(node, 'src')!; - const referenceId = assetIdMap.get(src); - if (referenceId) { - const fileName = this.getFileName(referenceId); - const relPath = relativePath(pathname, '/' + fileName); - setAttribute(node, 'src', relPath); - } - } - - // Could be a `source` or an `img`. - if (hasSrcSet(node)) { - const srcset = getAttribute(node, 'srcset')!; - let changedSrcset = srcset; - const urls = matchSrcset(srcset).map((c) => c.url); - for (const url of urls) { - if (assetIdMap.has(url)) { - const referenceId = assetIdMap.get(url)!; - const fileName = this.getFileName(referenceId); - const relPath = relativePath(pathname, '/' + fileName); - changedSrcset = changedSrcset.replace(url, relPath); - } - } - // If anything changed, update it - if (changedSrcset !== srcset) { - setAttribute(node, 'srcset', changedSrcset); - } - } - } - - // Page styles for <style> usage, if not already appended via links. - for (const style of findInlineStyles(document)) { - if (hasAttribute(style, 'astro-style')) { - if (!pageCSSAdded) { - pageCSSAdded = appendStyleChunksBefore(style, pathname, cssChunkMap.get(styleId)); - } - - remove(style); - } - } - - const outHTML = parse5.serialize(document); - const name = pathname.substr(1); - const outPath = getOutputFilename(astroConfig, name); - - this.emitFile({ - fileName: outPath, - source: outHTML, - type: 'asset', - }); - } - }, - }; -} diff --git a/packages/astro/src/vite-plugin-build-html/util.ts b/packages/astro/src/vite-plugin-build-html/util.ts deleted file mode 100644 index 8380b55fd..000000000 --- a/packages/astro/src/vite-plugin-build-html/util.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { getAttribute, hasAttribute, getTagName } from '@web/parse5-utils'; -import parse5 from 'parse5'; -import { isStylesheetLink } from './extract-assets.js'; - -const tagsWithSrcSet = new Set(['img', 'source']); - -function startsWithSrcRoot(pathname: string, srcRoot: string, srcRootWeb: string): boolean { - return ( - pathname.startsWith(srcRoot) || // /Users/user/project/src/styles/main.css - pathname.startsWith(srcRootWeb) || // /src/styles/main.css - `/${pathname}`.startsWith(srcRoot) - ); // Windows fix: some paths are missing leading "/" -} - -export function isInSrcDirectory( - node: parse5.Element, - attr: string, - srcRoot: string, - srcRootWeb: string -): boolean { - const value = getAttribute(node, attr); - return value ? startsWithSrcRoot(value, srcRoot, srcRootWeb) : false; -} - -export function isAstroInjectedLink(node: parse5.Element): boolean { - return isStylesheetLink(node) && getAttribute(node, 'data-astro-injected') === ''; -} - -export function isBuildableLink( - node: parse5.Element, - srcRoot: string, - srcRootWeb: string -): boolean { - if (isAstroInjectedLink(node)) { - return true; - } - - const href = getAttribute(node, 'href'); - if (typeof href !== 'string' || !href.length) { - return false; - } - - return startsWithSrcRoot(href, srcRoot, srcRootWeb); -} - -export function isBuildableImage( - node: parse5.Element, - srcRoot: string, - srcRootWeb: string -): boolean { - if (getTagName(node) === 'img') { - const src = getAttribute(node, 'src'); - return src ? startsWithSrcRoot(src, srcRoot, srcRootWeb) : false; - } - return false; -} - -export function hasSrcSet(node: parse5.Element): boolean { - return tagsWithSrcSet.has(getTagName(node)) && !!getAttribute(node, 'srcset'); -} - -export function isHoistedScript(node: parse5.Element): boolean { - return getTagName(node) === 'script' && hasAttribute(node, 'hoist'); -} diff --git a/packages/astro/test/0-css.test.js b/packages/astro/test/0-css.test.js index 423975c97..e53df8408 100644 --- a/packages/astro/test/0-css.test.js +++ b/packages/astro/test/0-css.test.js @@ -291,8 +291,8 @@ describe('CSS', function () { }); it('resolves Astro styles', async () => { - const style = $('style[astro-style]'); - expect(style.length).to.not.equal(0); + const astroPageCss = $('link[rel=stylesheet][href^=/src/pages/index.astro?astro&type=style]'); + expect(astroPageCss.length).to.equal(4, 'The index.astro page should generate 4 stylesheets, 1 for each <style> tag on the page.') }); it('resolves Styles from React', async () => { diff --git a/packages/astro/test/astro-doctype.test.js b/packages/astro/test/astro-doctype.test.js index cb9a0c63c..8387fd0a7 100644 --- a/packages/astro/test/astro-doctype.test.js +++ b/packages/astro/test/astro-doctype.test.js @@ -24,14 +24,12 @@ describe('Doctype', () => { expect(html).to.match(/^<!DOCTYPE html>/i); }); - // Note: parse5 converts this to <!DOCTYPE html> (HTML5). Uncomment if we want to support legacy doctypes. - // - // it('Preserves user provided doctype', async () => { - // const html = await fixture.readFile('/preserve/index.html'); - - // // test that Doctype included was preserved - // expect(html).to.match(new RegExp('^<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', 'i')); - // }); + it('Preserves user provided doctype', async () => { + const html = await fixture.readFile('/preserve/index.html'); + + // test that Doctype included was preserved + expect(html).to.match(new RegExp('^<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">', 'i')); + }); it('User provided doctype is case insensitive', async () => { const html = await fixture.readFile('/capital/index.html'); diff --git a/packages/astro/test/astro-markdown-css.js b/packages/astro/test/astro-markdown-css.test.js index 04e274633..04e274633 100644 --- a/packages/astro/test/astro-markdown-css.js +++ b/packages/astro/test/astro-markdown-css.test.js diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c89916cb7..16757c937 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -479,7 +479,6 @@ importers: '@types/send': ^0.17.1 '@types/unist': ^2.0.6 '@types/yargs-parser': ^21.0.0 - '@web/parse5-utils': ^1.3.0 ast-types: ^0.14.2 astro-scripts: workspace:* boxen: ^6.2.1 @@ -506,7 +505,6 @@ importers: mime: ^3.0.0 mocha: ^9.2.2 ora: ^6.1.0 - parse5: ^6.0.1 path-browserify: ^1.0.1 path-to-regexp: ^6.2.0 postcss: ^8.4.12 @@ -546,7 +544,6 @@ importers: '@babel/traverse': 7.17.9 '@proload/core': 0.2.2 '@proload/plugin-tsm': 0.1.1_@proload+core@0.2.2 - '@web/parse5-utils': 1.3.0 ast-types: 0.14.2 boxen: 6.2.1 ci-info: 3.3.0 @@ -569,7 +566,6 @@ importers: micromorph: 0.1.2 mime: 3.0.0 ora: 6.1.0 - parse5: 6.0.1 path-browserify: 1.0.1 path-to-regexp: 6.2.0 postcss: 8.4.12 @@ -588,7 +584,6 @@ importers: sirv: 2.0.2 slash: 4.0.0 sourcemap-codec: 1.4.8 - srcset-parse: 1.1.0 string-width: 5.1.2 strip-ansi: 7.0.1 supports-esm: 1.0.0 @@ -623,6 +618,7 @@ importers: cheerio: 1.0.0-rc.10 mocha: 9.2.2 sass: 1.50.0 + srcset-parse: 1.1.0 packages/astro-prism: specifiers: @@ -4488,14 +4484,6 @@ packages: /@vue/shared/3.2.31: resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==} - /@web/parse5-utils/1.3.0: - resolution: {integrity: sha512-Pgkx3ECc8EgXSlS5EyrgzSOoUbM6P8OKS471HLAyvOBcP1NCBn0to4RN/OaKASGq8qa3j+lPX9H14uA5AHEnQg==} - engines: {node: '>=10.0.0'} - dependencies: - '@types/parse5': 6.0.3 - parse5: 6.0.1 - dev: false - /@webcomponents/template-shadowroot/0.1.0: resolution: {integrity: sha512-ry84Vft6xtRBbd4M/ptRodbOLodV5AD15TYhyRghCRgIcJJKmYmJ2v2BaaWxygENwh6Uq3zTfGPmlckKT/GXsQ==} dev: false @@ -9497,7 +9485,7 @@ packages: /srcset-parse/1.1.0: resolution: {integrity: sha512-JWp4cG2eybkvKA1QUHGoNK6JDEYcOnSuhzNGjZuYUPqXreDl/VkkvP2sZW7Rmh+icuCttrR9ccb2WPIazyM/Cw==} - dev: false + dev: true /statuses/2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} |