228 lines
9.1 KiB
Plaintext
228 lines
9.1 KiB
Plaintext
import { isBuildableCSSRequest } from "../../../vite-plugin-astro-server/util.js";
|
|
import { PROPAGATED_ASSET_FLAG } from "../../../content/consts.js";
|
|
import * as assetName from "../css-asset-name.js";
|
|
import { moduleIsTopLevelPage, walkParentInfos } from "../graph.js";
|
|
import {
|
|
eachPageData,
|
|
getPageDataByViteID,
|
|
getPageDatasByClientOnlyID,
|
|
getPageDatasByHoistedScriptId,
|
|
isHoistedScript
|
|
} from "../internal.js";
|
|
import { extendManualChunks, shouldInlineAsset } from "./util.js";
|
|
function pluginCSS(options, internals) {
|
|
return {
|
|
targets: ["client", "server"],
|
|
hooks: {
|
|
"build:before": ({ target }) => {
|
|
let plugins = rollupPluginAstroBuildCSS({
|
|
buildOptions: options,
|
|
internals,
|
|
target
|
|
});
|
|
return {
|
|
vitePlugin: plugins
|
|
};
|
|
}
|
|
}
|
|
};
|
|
}
|
|
function rollupPluginAstroBuildCSS(options) {
|
|
const { internals, buildOptions } = options;
|
|
const { settings } = buildOptions;
|
|
let resolvedConfig;
|
|
const pagesToCss = {};
|
|
const pagesToPropagatedCss = {};
|
|
const isContentCollectionCache = options.buildOptions.settings.config.output === "static" && options.buildOptions.settings.config.experimental.contentCollectionCache;
|
|
const cssBuildPlugin = {
|
|
name: "astro:rollup-plugin-build-css",
|
|
outputOptions(outputOptions) {
|
|
const assetFileNames = outputOptions.assetFileNames;
|
|
const namingIncludesHash = assetFileNames?.toString().includes("[hash]");
|
|
const createNameForParentPages = namingIncludesHash ? assetName.shortHashedName : assetName.createSlugger(settings);
|
|
extendManualChunks(outputOptions, {
|
|
after(id, meta) {
|
|
if (isBuildableCSSRequest(id)) {
|
|
if (options.target === "client") {
|
|
return internals.cssModuleToChunkIdMap.get(id);
|
|
}
|
|
for (const [pageInfo] of walkParentInfos(id, {
|
|
getModuleInfo: meta.getModuleInfo
|
|
})) {
|
|
if (new URL(pageInfo.id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG)) {
|
|
const chunkId2 = assetName.createNameHash(id, [id]);
|
|
internals.cssModuleToChunkIdMap.set(id, chunkId2);
|
|
if (isContentCollectionCache) {
|
|
const propagatedStyles = internals.propagatedStylesMap.get(pageInfo.id) ?? /* @__PURE__ */ new Set();
|
|
propagatedStyles.add({ type: "external", src: chunkId2 });
|
|
internals.propagatedStylesMap.set(pageInfo.id, propagatedStyles);
|
|
}
|
|
return chunkId2;
|
|
}
|
|
}
|
|
const chunkId = createNameForParentPages(id, meta);
|
|
internals.cssModuleToChunkIdMap.set(id, chunkId);
|
|
return chunkId;
|
|
}
|
|
}
|
|
});
|
|
},
|
|
async generateBundle(_outputOptions, bundle) {
|
|
for (const [, chunk] of Object.entries(bundle)) {
|
|
if (chunk.type !== "chunk")
|
|
continue;
|
|
if ("viteMetadata" in chunk === false)
|
|
continue;
|
|
const meta = chunk.viteMetadata;
|
|
if (meta.importedCss.size < 1)
|
|
continue;
|
|
if (options.target === "client") {
|
|
for (const id of Object.keys(chunk.modules)) {
|
|
for (const pageData of getParentClientOnlys(id, this, internals)) {
|
|
for (const importedCssImport of meta.importedCss) {
|
|
const cssToInfoRecord = pagesToCss[pageData.moduleSpecifier] ??= {};
|
|
cssToInfoRecord[importedCssImport] = { depth: -1, order: -1 };
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (const id of Object.keys(chunk.modules)) {
|
|
for (const [pageInfo, depth, order] of walkParentInfos(
|
|
id,
|
|
this,
|
|
function until(importer) {
|
|
return new URL(importer, "file://").searchParams.has(PROPAGATED_ASSET_FLAG);
|
|
}
|
|
)) {
|
|
if (new URL(pageInfo.id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG)) {
|
|
for (const parent of walkParentInfos(id, this)) {
|
|
const parentInfo = parent[0];
|
|
if (moduleIsTopLevelPage(parentInfo) === false)
|
|
continue;
|
|
const pageViteID = parentInfo.id;
|
|
const pageData = getPageDataByViteID(internals, pageViteID);
|
|
if (pageData === void 0)
|
|
continue;
|
|
for (const css of meta.importedCss) {
|
|
const propagatedStyles = pagesToPropagatedCss[pageData.moduleSpecifier] ??= {};
|
|
const existingCss = propagatedStyles[pageInfo.id] ??= /* @__PURE__ */ new Set();
|
|
existingCss.add(css);
|
|
}
|
|
}
|
|
} else if (moduleIsTopLevelPage(pageInfo)) {
|
|
const pageViteID = pageInfo.id;
|
|
const pageData = getPageDataByViteID(internals, pageViteID);
|
|
if (pageData) {
|
|
appendCSSToPage(pageData, meta, pagesToCss, depth, order);
|
|
}
|
|
} else if (options.target === "client" && isHoistedScript(internals, pageInfo.id)) {
|
|
for (const pageData of getPageDatasByHoistedScriptId(internals, pageInfo.id)) {
|
|
appendCSSToPage(pageData, meta, pagesToCss, -1, order);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const singleCssPlugin = {
|
|
name: "astro:rollup-plugin-single-css",
|
|
enforce: "post",
|
|
configResolved(config) {
|
|
resolvedConfig = config;
|
|
},
|
|
generateBundle(_, bundle) {
|
|
if (resolvedConfig.build.cssCodeSplit)
|
|
return;
|
|
const cssChunk = Object.values(bundle).find(
|
|
(chunk) => chunk.type === "asset" && chunk.name === "style.css"
|
|
);
|
|
if (cssChunk === void 0)
|
|
return;
|
|
for (const pageData of eachPageData(internals)) {
|
|
const cssToInfoMap = pagesToCss[pageData.moduleSpecifier] ??= {};
|
|
cssToInfoMap[cssChunk.fileName] = { depth: -1, order: -1 };
|
|
}
|
|
}
|
|
};
|
|
let assetsInlineLimit;
|
|
const inlineStylesheetsPlugin = {
|
|
name: "astro:rollup-plugin-inline-stylesheets",
|
|
enforce: "post",
|
|
configResolved(config) {
|
|
assetsInlineLimit = config.build.assetsInlineLimit;
|
|
},
|
|
async generateBundle(_outputOptions, bundle) {
|
|
const inlineConfig = settings.config.build.inlineStylesheets;
|
|
Object.entries(bundle).forEach(([id, stylesheet]) => {
|
|
if (stylesheet.type !== "asset" || stylesheet.name?.endsWith(".css") !== true || typeof stylesheet.source !== "string")
|
|
return;
|
|
const toBeInlined = inlineConfig === "always" ? true : inlineConfig === "never" ? false : shouldInlineAsset(stylesheet.source, stylesheet.fileName, assetsInlineLimit);
|
|
const sheet = toBeInlined ? { type: "inline", content: stylesheet.source } : { type: "external", src: stylesheet.fileName };
|
|
const pages = Array.from(eachPageData(internals));
|
|
let sheetAddedToPage = false;
|
|
pages.forEach((pageData) => {
|
|
const orderingInfo = pagesToCss[pageData.moduleSpecifier]?.[stylesheet.fileName];
|
|
if (orderingInfo !== void 0) {
|
|
pageData.styles.push({ ...orderingInfo, sheet });
|
|
sheetAddedToPage = true;
|
|
return;
|
|
}
|
|
const propagatedPaths = pagesToPropagatedCss[pageData.moduleSpecifier];
|
|
if (propagatedPaths === void 0)
|
|
return;
|
|
Object.entries(propagatedPaths).forEach(([pageInfoId, css]) => {
|
|
if (css.has(stylesheet.fileName) !== true)
|
|
return;
|
|
if (pageData.styles.some((s) => s.sheet === sheet))
|
|
return;
|
|
let propagatedStyles;
|
|
if (isContentCollectionCache) {
|
|
propagatedStyles = internals.propagatedStylesMap.get(pageInfoId) ?? internals.propagatedStylesMap.set(pageInfoId, /* @__PURE__ */ new Set()).get(pageInfoId);
|
|
} else {
|
|
propagatedStyles = pageData.propagatedStyles.get(pageInfoId) ?? pageData.propagatedStyles.set(pageInfoId, /* @__PURE__ */ new Set()).get(pageInfoId);
|
|
}
|
|
propagatedStyles.add(sheet);
|
|
sheetAddedToPage = true;
|
|
});
|
|
});
|
|
if (toBeInlined && sheetAddedToPage) {
|
|
delete bundle[id];
|
|
for (const chunk of Object.values(bundle)) {
|
|
if (chunk.type === "chunk") {
|
|
chunk.viteMetadata?.importedCss?.delete(id);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
};
|
|
return [cssBuildPlugin, singleCssPlugin, inlineStylesheetsPlugin];
|
|
}
|
|
function* getParentClientOnlys(id, ctx, internals) {
|
|
for (const [info] of walkParentInfos(id, ctx)) {
|
|
yield* getPageDatasByClientOnlyID(internals, info.id);
|
|
}
|
|
}
|
|
function appendCSSToPage(pageData, meta, pagesToCss, depth, order) {
|
|
for (const importedCssImport of meta.importedCss) {
|
|
const cssInfo = pagesToCss[pageData.moduleSpecifier]?.[importedCssImport];
|
|
if (cssInfo !== void 0) {
|
|
if (depth < cssInfo.depth) {
|
|
cssInfo.depth = depth;
|
|
}
|
|
if (cssInfo.order === -1) {
|
|
cssInfo.order = order;
|
|
} else if (order < cssInfo.order && order > -1) {
|
|
cssInfo.order = order;
|
|
}
|
|
} else {
|
|
const cssToInfoRecord = pagesToCss[pageData.moduleSpecifier] ??= {};
|
|
cssToInfoRecord[importedCssImport] = { depth, order };
|
|
}
|
|
}
|
|
}
|
|
export {
|
|
pluginCSS
|
|
};
|