import { prependForwardSlash } from "@astrojs/internal-helpers/path"; import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js"; import { wrapId } from "../core/util.js"; import { inlineRE, isBuildableCSSRequest, rawRE } from "../vite-plugin-astro-server/util.js"; import { getVirtualModulePageNameForComponent } from "../vite-plugin-pages/util.js"; import { getDevCSSModuleName } from "./util.js"; import { CSS_LANGS_RE } from "../core/viteUtils.js"; import { PROPAGATED_ASSET_QUERY_PARAM } from "../content/consts.js"; import { ASTRO_CSS_EXTENSION_POST_PATTERN, MODULE_DEV_CSS, MODULE_DEV_CSS_ALL, MODULE_DEV_CSS_PREFIX, RESOLVED_MODULE_DEV_CSS, RESOLVED_MODULE_DEV_CSS_ALL, RESOLVED_MODULE_DEV_CSS_PREFIX } from "./const.js"; function getComponentFromVirtualModuleCssName(virtualModulePrefix, id) { return id.slice(virtualModulePrefix.length).replace(new RegExp(ASTRO_CSS_EXTENSION_POST_PATTERN, "g"), "."); } async function ensureModulesLoaded(env, mod, seen = /* @__PURE__ */ new Set()) { const id = mod.id ?? mod.url; if (seen.has(id)) return; seen.add(id); for (const imp of mod.importedModules) { if (!imp.id) continue; if (seen.has(imp.id)) continue; if (imp.id.includes(PROPAGATED_ASSET_QUERY_PARAM)) continue; if (imp.id === RESOLVED_MODULE_DEV_CSS || imp.id === RESOLVED_MODULE_DEV_CSS_ALL || imp.id.startsWith(RESOLVED_MODULE_DEV_CSS_PREFIX)) continue; if (!imp.transformResult) { try { await env.fetchModule(imp.id); } catch { } } await ensureModulesLoaded(env, imp, seen); } } function* collectCSSWithOrder(id, mod, seen = /* @__PURE__ */ new Set()) { seen.add(id); if (id.includes(PROPAGATED_ASSET_QUERY_PARAM)) { return; } const imported = Array.from(mod.importedModules); if (isBuildableCSSRequest(id)) { yield { id: wrapId(mod.id ?? mod.url), idKey: id, content: "", url: prependForwardSlash(wrapId(mod.url)) }; return; } else if (id.endsWith("?raw")) { return; } for (const imp of imported) { if (imp.id && !seen.has(imp?.id)) { yield* collectCSSWithOrder(imp.id, imp, seen); } } } function astroDevCssPlugin({ routesList, command }) { let server; const cssContentCache = /* @__PURE__ */ new Map(); function getCurrentEnvironment(pluginEnv) { return pluginEnv ?? server?.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]; } return [ { name: MODULE_DEV_CSS, async configureServer(viteServer) { server = viteServer; }, applyToEnvironment(env) { return env.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || env.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || env.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender; }, resolveId: { filter: { id: new RegExp(`^(${MODULE_DEV_CSS}|${MODULE_DEV_CSS_PREFIX}.*)$`) }, handler(id) { if (id === MODULE_DEV_CSS) { return RESOLVED_MODULE_DEV_CSS; } return RESOLVED_MODULE_DEV_CSS_PREFIX + id.slice(MODULE_DEV_CSS_PREFIX.length); } }, load: { filter: { id: new RegExp(`^(${RESOLVED_MODULE_DEV_CSS}|${RESOLVED_MODULE_DEV_CSS_PREFIX}.*)$`) }, async handler(id) { if (id === RESOLVED_MODULE_DEV_CSS) { return { code: `export const css = new Set()` }; } if (id.startsWith(RESOLVED_MODULE_DEV_CSS_PREFIX)) { const componentPath = getComponentFromVirtualModuleCssName( RESOLVED_MODULE_DEV_CSS_PREFIX, id ); const cssWithOrder = /* @__PURE__ */ new Map(); const componentPageId = getVirtualModulePageNameForComponent(componentPath); const env = getCurrentEnvironment(this.environment); await env?.fetchModule(componentPageId); const resolved = await env?.pluginContainer.resolveId(componentPageId); if (!resolved?.id) { return { code: "export const css = new Set()" }; } const mod = env?.moduleGraph.getModuleById(resolved.id); if (!mod) { return { code: "export const css = new Set()" }; } if (env) { await ensureModulesLoaded(env, mod); } for (const collected of collectCSSWithOrder(componentPageId, mod)) { if (!cssWithOrder.has(collected.idKey)) { const content = cssContentCache.get(collected.id) || collected.content; cssWithOrder.set(collected.idKey, { ...collected, content }); } } const cssArray = Array.from(cssWithOrder.values()); const cleanedCss = cssArray.map(({ content, id: cssId, url }) => ({ content, id: cssId, url })); return { code: `export const css = new Set(${JSON.stringify(cleanedCss)})` }; } } }, transform: { filter: { id: { include: [CSS_LANGS_RE], exclude: [rawRE, inlineRE] } }, handler(code, id) { if (command === "build") { return; } const env = getCurrentEnvironment(this.environment); const mod = env?.moduleGraph.getModuleById(id); if (mod) { cssContentCache.set(id, code); } } } }, { name: MODULE_DEV_CSS_ALL, applyToEnvironment(env) { return env.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr || env.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || env.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender; }, resolveId: { filter: { id: new RegExp(`^${MODULE_DEV_CSS_ALL}$`) }, handler() { return RESOLVED_MODULE_DEV_CSS_ALL; } }, load: { filter: { id: new RegExp(`^${RESOLVED_MODULE_DEV_CSS_ALL}$`) }, handler() { let code = `export const devCSSMap = new Map([`; for (const route of routesList.routes) { code += ` [${JSON.stringify(route.component)}, () => import(${JSON.stringify(getDevCSSModuleName(route.component))})],`; } code += "]);"; return { code }; } } } ]; } export { astroDevCssPlugin };