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
This commit is contained in:
parent
9e00f6d546
commit
0247b54270
23 changed files with 55 additions and 1086 deletions
5
.changeset/three-pigs-hunt.md
Normal file
5
.changeset/three-pigs-hunt.md
Normal file
|
@ -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
|
|
@ -86,7 +86,6 @@
|
||||||
"@babel/traverse": "^7.17.9",
|
"@babel/traverse": "^7.17.9",
|
||||||
"@proload/core": "^0.2.2",
|
"@proload/core": "^0.2.2",
|
||||||
"@proload/plugin-tsm": "^0.1.1",
|
"@proload/plugin-tsm": "^0.1.1",
|
||||||
"@web/parse5-utils": "^1.3.0",
|
|
||||||
"ast-types": "^0.14.2",
|
"ast-types": "^0.14.2",
|
||||||
"boxen": "^6.2.1",
|
"boxen": "^6.2.1",
|
||||||
"ci-info": "^3.3.0",
|
"ci-info": "^3.3.0",
|
||||||
|
@ -109,7 +108,6 @@
|
||||||
"micromorph": "^0.1.2",
|
"micromorph": "^0.1.2",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
"ora": "^6.1.0",
|
"ora": "^6.1.0",
|
||||||
"parse5": "^6.0.1",
|
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
|
@ -128,7 +126,6 @@
|
||||||
"sirv": "^2.0.2",
|
"sirv": "^2.0.2",
|
||||||
"slash": "^4.0.0",
|
"slash": "^4.0.0",
|
||||||
"sourcemap-codec": "^1.4.8",
|
"sourcemap-codec": "^1.4.8",
|
||||||
"srcset-parse": "^1.1.0",
|
|
||||||
"string-width": "^5.1.2",
|
"string-width": "^5.1.2",
|
||||||
"strip-ansi": "^7.0.1",
|
"strip-ansi": "^7.0.1",
|
||||||
"supports-esm": "^1.0.0",
|
"supports-esm": "^1.0.0",
|
||||||
|
@ -163,7 +160,8 @@
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
"cheerio": "^1.0.0-rc.10",
|
"cheerio": "^1.0.0-rc.10",
|
||||||
"mocha": "^9.2.2",
|
"mocha": "^9.2.2",
|
||||||
"sass": "^1.50.0"
|
"sass": "^1.50.0",
|
||||||
|
"srcset-parse": "^1.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.15.0 || >=16.0.0",
|
"node": "^14.15.0 || >=16.0.0",
|
||||||
|
|
|
@ -983,7 +983,6 @@ export interface SSRElement {
|
||||||
export interface SSRMetadata {
|
export interface SSRMetadata {
|
||||||
renderers: SSRLoadedRenderer[];
|
renderers: SSRLoadedRenderer[];
|
||||||
pathname: string;
|
pathname: string;
|
||||||
legacyBuild: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SSRResult {
|
export interface SSRResult {
|
||||||
|
|
|
@ -48,7 +48,6 @@ function printAstroHelp() {
|
||||||
['--host [optional IP]', 'Expose server on network'],
|
['--host [optional IP]', 'Expose server on network'],
|
||||||
['--config <path>', 'Specify the path to the Astro config file.'],
|
['--config <path>', 'Specify the path to the Astro config file.'],
|
||||||
['--root <path>', 'Specify the path to the project root folder.'],
|
['--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.'],
|
['--drafts', 'Include markdown draft pages in the build.'],
|
||||||
['--verbose', 'Enable verbose logging'],
|
['--verbose', 'Enable verbose logging'],
|
||||||
['--silent', 'Disable logging'],
|
['--silent', 'Disable logging'],
|
||||||
|
|
|
@ -78,7 +78,6 @@ export class App {
|
||||||
const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site);
|
const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site);
|
||||||
|
|
||||||
const result = await render({
|
const result = await render({
|
||||||
legacyBuild: false,
|
|
||||||
links,
|
links,
|
||||||
logging: this.#logging,
|
logging: this.#logging,
|
||||||
markdown: manifest.markdown,
|
markdown: manifest.markdown,
|
||||||
|
|
|
@ -193,7 +193,6 @@ async function generatePath(
|
||||||
const ssr = isBuildingToSSR(opts.astroConfig);
|
const ssr = isBuildingToSSR(opts.astroConfig);
|
||||||
const url = new URL(opts.astroConfig.base + removeLeadingForwardSlash(pathname), origin);
|
const url = new URL(opts.astroConfig.base + removeLeadingForwardSlash(pathname), origin);
|
||||||
const options: RenderOptions = {
|
const options: RenderOptions = {
|
||||||
legacyBuild: false,
|
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdown: astroConfig.markdown,
|
markdown: astroConfig.markdown,
|
||||||
|
|
|
@ -213,7 +213,6 @@ class AstroBuilder {
|
||||||
pageCount: number;
|
pageCount: number;
|
||||||
buildMode: 'static' | 'ssr';
|
buildMode: 'static' | 'ssr';
|
||||||
}) {
|
}) {
|
||||||
const buildTime = performance.now() - timeStart;
|
|
||||||
const total = getTimeStat(timeStart, performance.now());
|
const total = getTimeStat(timeStart, performance.now());
|
||||||
|
|
||||||
let messages: string[] = [];
|
let messages: string[] = [];
|
||||||
|
|
|
@ -30,24 +30,6 @@ export interface BuildInternals {
|
||||||
* A map for page-specific information by a client:only component
|
* A map for page-specific information by a client:only component
|
||||||
*/
|
*/
|
||||||
pagesByClientOnly: Map<string, Set<PageBuildData>>;
|
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 {
|
return {
|
||||||
pureCSSChunks,
|
pureCSSChunks,
|
||||||
chunkToReferenceIdMap,
|
|
||||||
astroStyleMap,
|
|
||||||
astroPageStyleMap,
|
|
||||||
hoistedScriptIdToHoistedMap,
|
hoistedScriptIdToHoistedMap,
|
||||||
entrySpecifierToBundleMap: new Map<string, string>(),
|
entrySpecifierToBundleMap: new Map<string, string>(),
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,6 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
|
||||||
vitePluginPages(opts, internals),
|
vitePluginPages(opts, internals),
|
||||||
rollupPluginAstroBuildCSS({
|
rollupPluginAstroBuildCSS({
|
||||||
internals,
|
internals,
|
||||||
legacy: false,
|
|
||||||
target: 'server',
|
target: 'server',
|
||||||
}),
|
}),
|
||||||
...(viteConfig.plugins || []),
|
...(viteConfig.plugins || []),
|
||||||
|
@ -222,7 +221,6 @@ async function clientBuild(
|
||||||
vitePluginHoistedScripts(astroConfig, internals),
|
vitePluginHoistedScripts(astroConfig, internals),
|
||||||
rollupPluginAstroBuildCSS({
|
rollupPluginAstroBuildCSS({
|
||||||
internals,
|
internals,
|
||||||
legacy: false,
|
|
||||||
target: 'client',
|
target: 'client',
|
||||||
}),
|
}),
|
||||||
...(viteConfig.plugins || []),
|
...(viteConfig.plugins || []),
|
||||||
|
|
|
@ -38,11 +38,3 @@ export function startsWithDotSlash(path: string) {
|
||||||
export function isRelativePath(path: string) {
|
export function isRelativePath(path: string) {
|
||||||
return startsWithDotDotSlash(path) || startsWithDotSlash(path);
|
return startsWithDotDotSlash(path) || startsWithDotSlash(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prependDotSlash(path: string) {
|
|
||||||
if (isRelativePath(path)) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return './' + path;
|
|
||||||
}
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ export async function getParamsAndProps(
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RenderOptions {
|
export interface RenderOptions {
|
||||||
legacyBuild: boolean;
|
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
links: Set<SSRElement>;
|
links: Set<SSRElement>;
|
||||||
markdown: MarkdownRenderingOptions;
|
markdown: MarkdownRenderingOptions;
|
||||||
|
@ -87,7 +86,6 @@ export async function render(
|
||||||
opts: RenderOptions
|
opts: RenderOptions
|
||||||
): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> {
|
): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> {
|
||||||
const {
|
const {
|
||||||
legacyBuild,
|
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
origin,
|
origin,
|
||||||
|
@ -128,7 +126,6 @@ export async function render(
|
||||||
throw new Error(`Unable to SSR non-Astro component (${route?.component})`);
|
throw new Error(`Unable to SSR non-Astro component (${route?.component})`);
|
||||||
|
|
||||||
const result = createResult({
|
const result = createResult({
|
||||||
legacyBuild,
|
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdown,
|
markdown,
|
||||||
|
|
|
@ -102,18 +102,13 @@ export async function render(
|
||||||
routeCache,
|
routeCache,
|
||||||
viteServer,
|
viteServer,
|
||||||
} = ssrOpts;
|
} = ssrOpts;
|
||||||
// TODO: clean up "legacy" flag passed through helper functions
|
|
||||||
const isLegacyBuild = false;
|
|
||||||
|
|
||||||
// Add hoisted script tags
|
// Add hoisted script tags
|
||||||
const scripts = createModuleScriptElementWithSrcSet(
|
const scripts = createModuleScriptElementWithSrcSet(
|
||||||
!isLegacyBuild && mod.hasOwnProperty('$$metadata')
|
mod.hasOwnProperty('$$metadata') ? Array.from(mod.$$metadata.hoistedScriptPaths()) : []
|
||||||
? Array.from(mod.$$metadata.hoistedScriptPaths())
|
|
||||||
: []
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Inject HMR scripts
|
// Inject HMR scripts
|
||||||
if (mod.hasOwnProperty('$$metadata') && mode === 'development' && !isLegacyBuild) {
|
if (mod.hasOwnProperty('$$metadata') && mode === 'development') {
|
||||||
scripts.add({
|
scripts.add({
|
||||||
props: { type: 'module', src: '/@vite/client' },
|
props: { type: 'module', src: '/@vite/client' },
|
||||||
children: '',
|
children: '',
|
||||||
|
@ -138,7 +133,6 @@ export async function render(
|
||||||
|
|
||||||
// Pass framework CSS in as link tags to be appended to the page.
|
// Pass framework CSS in as link tags to be appended to the page.
|
||||||
let links = new Set<SSRElement>();
|
let links = new Set<SSRElement>();
|
||||||
if (!isLegacyBuild) {
|
|
||||||
[...(await getStylesForURL(filePath, viteServer))].forEach((href) => {
|
[...(await getStylesForURL(filePath, viteServer))].forEach((href) => {
|
||||||
if (mode === 'development' && svelteStylesRE.test(href)) {
|
if (mode === 'development' && svelteStylesRE.test(href)) {
|
||||||
scripts.add({
|
scripts.add({
|
||||||
|
@ -156,11 +150,8 @@ export async function render(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
let content = await coreRender({
|
let content = await coreRender({
|
||||||
// TODO: Remove this flag once legacyBuild support is removed
|
|
||||||
legacyBuild: isLegacyBuild,
|
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdown: astroConfig.markdown,
|
markdown: astroConfig.markdown,
|
||||||
|
@ -197,41 +188,6 @@ export async function render(
|
||||||
// inject tags
|
// inject tags
|
||||||
const tags: vite.HtmlTagDescriptor[] = [];
|
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
|
// add injected tags
|
||||||
let html = injectTags(content.html, tags);
|
let html = injectTags(content.html, tags);
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ function onlyAvailableInSSR(name: string) {
|
||||||
|
|
||||||
export interface CreateResultArgs {
|
export interface CreateResultArgs {
|
||||||
ssr: boolean;
|
ssr: boolean;
|
||||||
legacyBuild: boolean;
|
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
origin: string;
|
origin: string;
|
||||||
markdown: MarkdownRenderingOptions;
|
markdown: MarkdownRenderingOptions;
|
||||||
|
@ -101,7 +100,7 @@ class Slots {
|
||||||
let renderMarkdown: any = null;
|
let renderMarkdown: any = null;
|
||||||
|
|
||||||
export function createResult(args: CreateResultArgs): SSRResult {
|
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 url = new URL(request.url);
|
||||||
const canonicalURL = createCanonicalURL('.' + pathname, site ?? url.origin);
|
const canonicalURL = createCanonicalURL('.' + pathname, site ?? url.origin);
|
||||||
|
@ -138,7 +137,6 @@ export function createResult(args: CreateResultArgs): SSRResult {
|
||||||
}
|
}
|
||||||
: onlyAvailableInSSR('Astro.redirect'),
|
: onlyAvailableInSSR('Astro.redirect'),
|
||||||
resolve(path: string) {
|
resolve(path: string) {
|
||||||
if (!legacyBuild) {
|
|
||||||
let extra = `This can be replaced with a dynamic import like so: await import("${path}")`;
|
let extra = `This can be replaced with a dynamic import like so: await import("${path}")`;
|
||||||
if (isCSSRequest(path)) {
|
if (isCSSRequest(path)) {
|
||||||
extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this:
|
extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this:
|
||||||
|
@ -169,9 +167,6 @@ ${extra}`
|
||||||
);
|
);
|
||||||
// Intentionally return an empty string so that it is not relied upon.
|
// Intentionally return an empty string so that it is not relied upon.
|
||||||
return '';
|
return '';
|
||||||
}
|
|
||||||
|
|
||||||
return astroGlobal.resolve(path);
|
|
||||||
},
|
},
|
||||||
slots: astroSlots,
|
slots: astroSlots,
|
||||||
} as unknown as AstroGlobal;
|
} as unknown as AstroGlobal;
|
||||||
|
@ -206,7 +201,6 @@ ${extra}`
|
||||||
_metadata: {
|
_metadata: {
|
||||||
renderers,
|
renderers,
|
||||||
pathname,
|
pathname,
|
||||||
legacyBuild,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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
|
// Renders a page to completion by first calling the factory callback, waiting for its result, and then appending
|
||||||
// styles and scripts into the head.
|
// styles and scripts into the head.
|
||||||
export async function renderHead(result: SSRResult): Promise<string> {
|
export async function renderHead(result: SSRResult): Promise<string> {
|
||||||
const styles = Array.from(result.styles)
|
const 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 },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
let needsHydrationStyles = false;
|
let needsHydrationStyles = false;
|
||||||
const scripts = Array.from(result.scripts)
|
const scripts = Array.from(result.scripts)
|
||||||
.filter(uniqueElements)
|
.filter(uniqueElements)
|
||||||
|
@ -568,7 +559,7 @@ export async function renderHead(result: SSRResult): Promise<string> {
|
||||||
if (needsHydrationStyles) {
|
if (needsHydrationStyles) {
|
||||||
styles.push(
|
styles.push(
|
||||||
renderElement('style', {
|
renderElement('style', {
|
||||||
props: { 'astro-style': true },
|
props: {},
|
||||||
children: 'astro-root, astro-fragment { display: contents; }',
|
children: 'astro-root, astro-fragment { display: contents; }',
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -19,27 +19,6 @@ const ASTRO_STYLE_PREFIX = '@astro-inline-style';
|
||||||
|
|
||||||
const ASTRO_PAGE_STYLE_PREFIX = '@astro-page-all-styles';
|
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) {
|
function isStyleVirtualModule(id: string) {
|
||||||
return id.startsWith(ASTRO_STYLE_PREFIX);
|
return id.startsWith(ASTRO_STYLE_PREFIX);
|
||||||
}
|
}
|
||||||
|
@ -54,12 +33,11 @@ function isRawOrUrlModule(id: string) {
|
||||||
|
|
||||||
interface PluginOptions {
|
interface PluginOptions {
|
||||||
internals: BuildInternals;
|
internals: BuildInternals;
|
||||||
legacy: boolean;
|
|
||||||
target: 'client' | 'server';
|
target: 'client' | 'server';
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin {
|
export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin {
|
||||||
const { internals, legacy } = options;
|
const { internals } = options;
|
||||||
const styleSourceMap = new Map<string, string>();
|
const styleSourceMap = new Map<string, string>();
|
||||||
|
|
||||||
function* walkStyles(
|
function* walkStyles(
|
||||||
|
@ -153,16 +131,6 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin {
|
||||||
return undefined;
|
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) {
|
async transform(value, id) {
|
||||||
if (isStyleVirtualModule(id)) {
|
if (isStyleVirtualModule(id)) {
|
||||||
styleSourceMap.set(id, value);
|
styleSourceMap.set(id, value);
|
||||||
|
@ -203,7 +171,6 @@ export function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin {
|
||||||
source: minifiedCSS,
|
source: minifiedCSS,
|
||||||
});
|
});
|
||||||
|
|
||||||
internals.chunkToReferenceIdMap.set(chunk.fileName, referenceId);
|
|
||||||
if (chunk.type === 'chunk') {
|
if (chunk.type === 'chunk') {
|
||||||
const fileName = this.getFileName(referenceId);
|
const fileName = this.getFileName(referenceId);
|
||||||
for (const pageData of getPageDatasByChunk(internals, chunk)) {
|
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
|
// 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)) {
|
for (const [chunkId, chunk] of Object.entries(bundle)) {
|
||||||
if (chunk.type === 'chunk') {
|
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.
|
// Removes imports for pure CSS chunks.
|
||||||
if (hasPureCSSChunks) {
|
if (hasPureCSSChunks) {
|
||||||
if (internals.pureCSSChunks.has(chunk) && !chunk.exports.length) {
|
if (internals.pureCSSChunks.has(chunk) && !chunk.exports.length) {
|
||||||
|
|
|
@ -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.`);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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');
|
|
||||||
}
|
|
|
@ -291,8 +291,8 @@ describe('CSS', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves Astro styles', async () => {
|
it('resolves Astro styles', async () => {
|
||||||
const style = $('style[astro-style]');
|
const astroPageCss = $('link[rel=stylesheet][href^=/src/pages/index.astro?astro&type=style]');
|
||||||
expect(style.length).to.not.equal(0);
|
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 () => {
|
it('resolves Styles from React', async () => {
|
||||||
|
|
|
@ -24,14 +24,12 @@ describe('Doctype', () => {
|
||||||
expect(html).to.match(/^<!DOCTYPE html>/i);
|
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');
|
||||||
// it('Preserves user provided doctype', async () => {
|
|
||||||
// const html = await fixture.readFile('/preserve/index.html');
|
|
||||||
|
|
||||||
// // test that Doctype included was preserved
|
// 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'));
|
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 () => {
|
it('User provided doctype is case insensitive', async () => {
|
||||||
const html = await fixture.readFile('/capital/index.html');
|
const html = await fixture.readFile('/capital/index.html');
|
||||||
|
|
|
@ -479,7 +479,6 @@ importers:
|
||||||
'@types/send': ^0.17.1
|
'@types/send': ^0.17.1
|
||||||
'@types/unist': ^2.0.6
|
'@types/unist': ^2.0.6
|
||||||
'@types/yargs-parser': ^21.0.0
|
'@types/yargs-parser': ^21.0.0
|
||||||
'@web/parse5-utils': ^1.3.0
|
|
||||||
ast-types: ^0.14.2
|
ast-types: ^0.14.2
|
||||||
astro-scripts: workspace:*
|
astro-scripts: workspace:*
|
||||||
boxen: ^6.2.1
|
boxen: ^6.2.1
|
||||||
|
@ -506,7 +505,6 @@ importers:
|
||||||
mime: ^3.0.0
|
mime: ^3.0.0
|
||||||
mocha: ^9.2.2
|
mocha: ^9.2.2
|
||||||
ora: ^6.1.0
|
ora: ^6.1.0
|
||||||
parse5: ^6.0.1
|
|
||||||
path-browserify: ^1.0.1
|
path-browserify: ^1.0.1
|
||||||
path-to-regexp: ^6.2.0
|
path-to-regexp: ^6.2.0
|
||||||
postcss: ^8.4.12
|
postcss: ^8.4.12
|
||||||
|
@ -546,7 +544,6 @@ importers:
|
||||||
'@babel/traverse': 7.17.9
|
'@babel/traverse': 7.17.9
|
||||||
'@proload/core': 0.2.2
|
'@proload/core': 0.2.2
|
||||||
'@proload/plugin-tsm': 0.1.1_@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
|
ast-types: 0.14.2
|
||||||
boxen: 6.2.1
|
boxen: 6.2.1
|
||||||
ci-info: 3.3.0
|
ci-info: 3.3.0
|
||||||
|
@ -569,7 +566,6 @@ importers:
|
||||||
micromorph: 0.1.2
|
micromorph: 0.1.2
|
||||||
mime: 3.0.0
|
mime: 3.0.0
|
||||||
ora: 6.1.0
|
ora: 6.1.0
|
||||||
parse5: 6.0.1
|
|
||||||
path-browserify: 1.0.1
|
path-browserify: 1.0.1
|
||||||
path-to-regexp: 6.2.0
|
path-to-regexp: 6.2.0
|
||||||
postcss: 8.4.12
|
postcss: 8.4.12
|
||||||
|
@ -588,7 +584,6 @@ importers:
|
||||||
sirv: 2.0.2
|
sirv: 2.0.2
|
||||||
slash: 4.0.0
|
slash: 4.0.0
|
||||||
sourcemap-codec: 1.4.8
|
sourcemap-codec: 1.4.8
|
||||||
srcset-parse: 1.1.0
|
|
||||||
string-width: 5.1.2
|
string-width: 5.1.2
|
||||||
strip-ansi: 7.0.1
|
strip-ansi: 7.0.1
|
||||||
supports-esm: 1.0.0
|
supports-esm: 1.0.0
|
||||||
|
@ -623,6 +618,7 @@ importers:
|
||||||
cheerio: 1.0.0-rc.10
|
cheerio: 1.0.0-rc.10
|
||||||
mocha: 9.2.2
|
mocha: 9.2.2
|
||||||
sass: 1.50.0
|
sass: 1.50.0
|
||||||
|
srcset-parse: 1.1.0
|
||||||
|
|
||||||
packages/astro-prism:
|
packages/astro-prism:
|
||||||
specifiers:
|
specifiers:
|
||||||
|
@ -4488,14 +4484,6 @@ packages:
|
||||||
/@vue/shared/3.2.31:
|
/@vue/shared/3.2.31:
|
||||||
resolution: {integrity: sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==}
|
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:
|
/@webcomponents/template-shadowroot/0.1.0:
|
||||||
resolution: {integrity: sha512-ry84Vft6xtRBbd4M/ptRodbOLodV5AD15TYhyRghCRgIcJJKmYmJ2v2BaaWxygENwh6Uq3zTfGPmlckKT/GXsQ==}
|
resolution: {integrity: sha512-ry84Vft6xtRBbd4M/ptRodbOLodV5AD15TYhyRghCRgIcJJKmYmJ2v2BaaWxygENwh6Uq3zTfGPmlckKT/GXsQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -9497,7 +9485,7 @@ packages:
|
||||||
|
|
||||||
/srcset-parse/1.1.0:
|
/srcset-parse/1.1.0:
|
||||||
resolution: {integrity: sha512-JWp4cG2eybkvKA1QUHGoNK6JDEYcOnSuhzNGjZuYUPqXreDl/VkkvP2sZW7Rmh+icuCttrR9ccb2WPIazyM/Cw==}
|
resolution: {integrity: sha512-JWp4cG2eybkvKA1QUHGoNK6JDEYcOnSuhzNGjZuYUPqXreDl/VkkvP2sZW7Rmh+icuCttrR9ccb2WPIazyM/Cw==}
|
||||||
dev: false
|
dev: true
|
||||||
|
|
||||||
/statuses/2.0.1:
|
/statuses/2.0.1:
|
||||||
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
|
||||||
|
|
Loading…
Reference in a new issue