@zealakit/css-doctor-vite 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +31 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +31 -10
- package/dist/index.js.map +1 -1
- package/package.json +25 -3
package/dist/index.cjs
CHANGED
|
@@ -262,18 +262,25 @@ function cssDoctor(options = {}) {
|
|
|
262
262
|
isolateVariables: options.sizeBudget?.isolateVariables ?? true
|
|
263
263
|
};
|
|
264
264
|
const report = options.report ?? true;
|
|
265
|
-
const
|
|
266
|
-
const
|
|
265
|
+
const configuredMinPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;
|
|
266
|
+
const configuredMaxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;
|
|
267
|
+
const configurationWarnings = [];
|
|
268
|
+
const minPageRatio = Number.isFinite(configuredMinPageRatio) && configuredMinPageRatio >= 0 && configuredMinPageRatio <= 1 ? configuredMinPageRatio : DEFAULT_MIN_PAGE_RATIO;
|
|
269
|
+
const maxChunkSize = Number.isFinite(configuredMaxChunkSize) && Number.isInteger(configuredMaxChunkSize) && configuredMaxChunkSize > 0 ? configuredMaxChunkSize : DEFAULT_MAX_CHUNK_SIZE;
|
|
267
270
|
let base = "/";
|
|
268
271
|
let minify = options.minify ?? true;
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
+
if (minPageRatio !== configuredMinPageRatio) {
|
|
273
|
+
configurationWarnings.push(
|
|
274
|
+
"minPageRatio must be a number between 0 and 1; using 0.5"
|
|
272
275
|
);
|
|
273
276
|
}
|
|
274
|
-
if (
|
|
275
|
-
|
|
277
|
+
if (maxChunkSize !== configuredMaxChunkSize) {
|
|
278
|
+
configurationWarnings.push(
|
|
279
|
+
"maxChunkSize must be a positive integer; using 61440"
|
|
280
|
+
);
|
|
276
281
|
}
|
|
282
|
+
pageCoverage.minPageRatio = minPageRatio;
|
|
283
|
+
sizeBudget.maxChunkSize = maxChunkSize;
|
|
277
284
|
const filter = (0, import_pluginutils.createFilter)(options.include, options.exclude, {
|
|
278
285
|
resolve: false
|
|
279
286
|
});
|
|
@@ -319,6 +326,10 @@ function cssDoctor(options = {}) {
|
|
|
319
326
|
wrapCommonImports: options.wrapCommonImports ?? false
|
|
320
327
|
}
|
|
321
328
|
);
|
|
329
|
+
for (const warning of configurationWarnings) {
|
|
330
|
+
this.warn(`[css-doctor] ${warning}`);
|
|
331
|
+
diagnostics.errors.push(warning);
|
|
332
|
+
}
|
|
322
333
|
if (options.onDiagnostics) {
|
|
323
334
|
try {
|
|
324
335
|
await options.onDiagnostics(diagnostics);
|
|
@@ -361,7 +372,8 @@ async function analyzeAndSplit(bundle, environment, options) {
|
|
|
361
372
|
pageUsage[page.name] = classes;
|
|
362
373
|
pageUsageCounts[page.name] = classes.length;
|
|
363
374
|
}
|
|
364
|
-
const
|
|
375
|
+
const hasPageClasses = pages.some((page) => page.classes.size > 0);
|
|
376
|
+
const splitApplied = options.pageCoverage.enabled && hasPageClasses;
|
|
365
377
|
const diagnostics = {
|
|
366
378
|
plugin: "vite-plugin-css-doctor",
|
|
367
379
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -436,7 +448,7 @@ async function analyzeAndSplit(bundle, environment, options) {
|
|
|
436
448
|
cssContent: originalContent,
|
|
437
449
|
pageUsage,
|
|
438
450
|
pageCoverage: {
|
|
439
|
-
enabled:
|
|
451
|
+
enabled: splitApplied,
|
|
440
452
|
minPageRatio: options.pageCoverage.minPageRatio,
|
|
441
453
|
forceCommon: options.pageCoverage.forceCommon
|
|
442
454
|
},
|
|
@@ -835,13 +847,22 @@ function scanClasses(source, classes) {
|
|
|
835
847
|
continue;
|
|
836
848
|
}
|
|
837
849
|
for (const token of value.split(/\s+/)) {
|
|
838
|
-
if (
|
|
850
|
+
if (isClassToken(token)) {
|
|
839
851
|
classes.add(token.toLowerCase());
|
|
840
852
|
}
|
|
841
853
|
}
|
|
842
854
|
}
|
|
843
855
|
}
|
|
844
856
|
}
|
|
857
|
+
function isClassToken(token) {
|
|
858
|
+
if (!token || token.length > 256) {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
if (/[`${}]/.test(token)) {
|
|
862
|
+
return false;
|
|
863
|
+
}
|
|
864
|
+
return /[A-Za-z_]/.test(token);
|
|
865
|
+
}
|
|
845
866
|
function isInternalPageEntry(chunk) {
|
|
846
867
|
const name = pageNameFor(chunk);
|
|
847
868
|
return name.startsWith("_") || name.startsWith("noop-") || name.includes("@astro-renderers");
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/reporter.ts"],"sourcesContent":["export { cssDoctor } from \"./plugin\";\nexport type {\n CssAssetDiagnostic,\n CssAssetSplitInfo,\n CssAssetWarning,\n CssAssetWarningKind,\n CssDoctorFilter,\n CssDoctorFilterPattern,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetDiagnostics,\n SizeBudgetOptions,\n} from \"./types\";\n","import { readFile } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { createFilter } from \"@rollup/pluginutils\";\nimport { analyzeCss, optimizeCss } from \"@zealakit/css-doctor-binding\";\nimport type {\n JsCssAnalysisResult,\n JsSelectorStat,\n} from \"@zealakit/css-doctor-binding\";\nimport type { Plugin } from \"vite\";\n\nimport { printDiagnostics } from \"./reporter\";\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetOptions,\n} from \"./types\";\n\nconst DEFAULT_MIN_PAGE_RATIO = 0.5;\nconst DEFAULT_MAX_CHUNK_SIZE = 60 * 1_024;\nconst LARGE_CSS_ASSET_BYTES = 500 * 1_024;\n\ntype CssAssetLike = {\n type: \"asset\";\n fileName: string;\n source: string | Uint8Array;\n};\n\ntype ViteChunkLike = {\n type: \"chunk\";\n fileName: string;\n name: string;\n isEntry: boolean;\n facadeModuleId: string | null;\n code: string;\n modules: Record<string, unknown>;\n imports: string[];\n dynamicImports: string[];\n viteMetadata?: {\n importedCss?: Set<string>;\n };\n};\n\ntype PageInfo = {\n name: string;\n classes: Set<string>;\n cssFiles: Set<string>;\n chunkFile: string | null;\n};\n\ntype EmitAsset = {\n type: \"asset\";\n name?: string;\n fileName?: string;\n source: string | Uint8Array;\n};\n\ntype AnalysisEnvironment = {\n getModuleInfo: (id: string) => { code?: string | null } | null;\n emitFile: (asset: EmitAsset) => string;\n getFileName: (referenceId: string) => string;\n};\n\n/**\n * Creates a Vite plugin that splits emitted CSS by page coverage and removes\n * selectors that no scanned page uses.\n *\n * The plugin is read-only with respect to existing assets except for replacing\n * their contents with the common chunk. New page-specific files are emitted\n * with `this.emitFile`. Read, parse, split and callback failures are contained\n * so the user's build is never interrupted.\n */\nexport function cssDoctor(options: CssDoctorViteOptions = {}): Plugin {\n const pageCoverage: PageCoverageOptions = {\n enabled: options.pageCoverage?.enabled ?? true,\n minPageRatio:\n options.pageCoverage?.minPageRatio ??\n options.minPageRatio ??\n DEFAULT_MIN_PAGE_RATIO,\n forceCommon:\n options.pageCoverage?.forceCommon ?? options.forceCommonSelectors ?? [],\n };\n const sizeBudget: SizeBudgetOptions = {\n enabled: options.sizeBudget?.enabled ?? true,\n maxChunkSize: options.sizeBudget?.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE,\n isolateVariables: options.sizeBudget?.isolateVariables ?? true,\n };\n const report = options.report ?? true;\n const minPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;\n const maxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;\n let base = \"/\";\n let minify = options.minify ?? true;\n\n if (!Number.isFinite(minPageRatio) || minPageRatio < 0 || minPageRatio > 1) {\n throw new RangeError(\n \"css-doctor: minPageRatio must be a number between 0 and 1\",\n );\n }\n\n if (\n !Number.isFinite(maxChunkSize) ||\n !Number.isInteger(maxChunkSize) ||\n maxChunkSize <= 0\n ) {\n throw new RangeError(\"css-doctor: maxChunkSize must be a positive integer\");\n }\n\n const filter = createFilter(options.include, options.exclude, {\n resolve: false,\n });\n\n return {\n name: \"vite-plugin-css-doctor\",\n apply: \"build\",\n enforce: \"post\",\n\n config(config) {\n if (options.minify === false) {\n config.build ??= {};\n config.build.cssMinify = false;\n }\n },\n\n configResolved(config) {\n base = config.base;\n minify =\n options.minify ??\n (config.mode === \"production\" || config.command === \"build\");\n },\n\n async generateBundle(_outputOptions, bundle) {\n try {\n const diagnostics = await analyzeAndSplit(\n bundle,\n {\n getModuleInfo: (id) => this.getModuleInfo(id),\n emitFile: (asset) => this.emitFile(asset),\n getFileName: (referenceId) => this.getFileName(referenceId),\n },\n {\n filter,\n pageCoverage: {\n enabled: pageCoverage.enabled ?? true,\n minPageRatio,\n forceCommon: pageCoverage.forceCommon ?? [],\n },\n sizeBudget: {\n enabled: sizeBudget.enabled ?? true,\n maxChunkSize,\n isolateVariables: sizeBudget.isolateVariables ?? true,\n },\n directPageUsage: options.pageUsage,\n base,\n minify,\n skipVueScopedStyles: options.skipVueScopedStyles ?? false,\n wrapCommonImports: options.wrapCommonImports ?? false,\n },\n );\n\n if (options.onDiagnostics) {\n try {\n await options.onDiagnostics(diagnostics);\n } catch (error) {\n const message = `onDiagnostics callback failed: ${describeError(error)}`;\n diagnostics.errors.push(message);\n this.warn(`[css-doctor] ${message}`);\n }\n }\n\n if (\n report &&\n (diagnostics.totalCssAssets > 0 || diagnostics.errors.length > 0)\n ) {\n printDiagnostics(diagnostics);\n }\n } catch (error) {\n this.warn(\n `[css-doctor] diagnostics failed without interrupting the build: ${describeError(error)}`,\n );\n }\n },\n };\n}\n\ntype SplitOptions = {\n filter: (id: string) => boolean;\n pageCoverage: Required<PageCoverageOptions> & { forceCommon: string[] };\n sizeBudget: Required<SizeBudgetOptions>;\n directPageUsage: Record<string, string[]> | undefined;\n base: string;\n minify: boolean;\n skipVueScopedStyles: boolean;\n wrapCommonImports: boolean;\n};\n\nasync function analyzeAndSplit(\n bundle: Record<string, unknown>,\n environment: AnalysisEnvironment,\n options: SplitOptions,\n): Promise<CssDoctorDiagnostics> {\n const startedAt = performance.now();\n const { pages, pagesByCss } = await collectPages(\n bundle,\n environment.getModuleInfo,\n options.directPageUsage,\n );\n const pageNames = pages.map((page) => page.name);\n const pageNameSet = new Set(pageNames);\n const pageChunkFiles = new Map<string, string>();\n\n for (const page of pages) {\n if (page.chunkFile) {\n pageChunkFiles.set(page.name, page.chunkFile);\n }\n }\n const pageUsage: Record<string, string[]> = {};\n const pageUsageCounts: Record<string, number> = {};\n\n for (const page of pages) {\n const classes = [...page.classes].sort();\n pageUsage[page.name] = classes;\n pageUsageCounts[page.name] = classes.length;\n }\n\n const splitApplied = options.pageCoverage.enabled && pageNames.length > 0;\n const diagnostics: CssDoctorDiagnostics = {\n plugin: \"vite-plugin-css-doctor\",\n generatedAt: new Date().toISOString(),\n durationMs: 0,\n minPageRatio: options.pageCoverage.minPageRatio,\n minify: options.minify,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n splitChunks: 0,\n oversizedChunks: 0,\n },\n pages: pageNames,\n pageUsage: pageUsageCounts,\n splitApplied,\n totalCssAssets: 0,\n analyzedCssAssets: 0,\n skippedCssAssets: 0,\n failedCssAssets: 0,\n totalSizeBeforeBytes: 0,\n totalSizeAfterBytes: 0,\n totalSelectors: 0,\n totalRules: 0,\n commonCssBytes: 0,\n pageSpecificCssBytes: 0,\n emittedPageChunks: [],\n emittedCssChunks: [],\n usageMatrix: [],\n deadCodeCount: 0,\n files: [],\n errors: [],\n };\n\n const matrix = new Map<string, JsSelectorStat>();\n const htmlLinks: string[] = [];\n const commonFileNames: string[] = [];\n const pageCssFiles = new Map<string, string[]>();\n\n for (const output of Object.values(bundle)) {\n if (!isCssAsset(output)) {\n continue;\n }\n\n diagnostics.totalCssAssets += 1;\n\n if (!options.filter(output.fileName)) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (isCssModuleAsset(output.fileName, sourceToCss(output.source))) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (\n options.skipVueScopedStyles &&\n isVueScopedAsset(sourceToCss(output.source))\n ) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n const associatedPages = [\n ...(pagesByCss.get(output.fileName) ?? pageNameSet),\n ].sort();\n\n const file = analyzeAsset(output, associatedPages);\n\n if (file.error) {\n diagnostics.failedCssAssets += 1;\n diagnostics.errors.push(`${file.fileName}: ${file.error}`);\n diagnostics.files.push(file);\n continue;\n }\n\n const originalContent = sourceToCss(output.source);\n\n try {\n const pipeline = optimizeCss({\n cssContent: originalContent,\n pageUsage,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n forceCommon: options.pageCoverage.forceCommon,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n },\n minify: options.minify,\n });\n\n const commonChunks = pipeline.chunks.filter(\n (chunk) => chunk.page === undefined && chunk.sourceChunk === \"common\",\n );\n const pageChunks = pipeline.chunks.filter(\n (chunk) => chunk.page !== undefined,\n );\n const commonWasSplit =\n commonChunks.length > 1 ||\n commonChunks.some((chunk) => chunk.splitDueToSize);\n const embeddedCommon = commonWasSplit ? undefined : commonChunks[0];\n\n output.source = embeddedCommon?.css ?? \"\";\n file.sizeAfterBytes = Buffer.byteLength(output.source, \"utf8\");\n\n let commonSizeBytes = 0;\n let pageSpecificSizeBytes = 0;\n\n for (const chunk of commonChunks) {\n const embedded = chunk === embeddedCommon;\n const fileName = embedded\n ? output.fileName\n : emitCssAsset(environment, `${chunk.name}.css`, chunk.css);\n commonSizeBytes += chunk.sizeBytes;\n\n if (!embedded) {\n htmlLinks.push(fileName);\n commonFileNames.push(fileName);\n }\n\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page: chunk.page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n if (options.wrapCommonImports && commonWasSplit) {\n output.source = commonFileNames\n .map((fileName) => `@import \"./${basename(fileName)}\";`)\n .join(\"\\n\");\n }\n\n for (const chunk of pageChunks) {\n const page = chunk.page;\n\n if (!page) {\n continue;\n }\n\n const fileName = emitCssAsset(\n environment,\n `${chunk.name}.css`,\n chunk.css,\n );\n pageSpecificSizeBytes += chunk.sizeBytes;\n const files = pageCssFiles.get(page) ?? [];\n files.push(fileName);\n pageCssFiles.set(page, files);\n\n const emittedPage: EmittedPageChunk = {\n page,\n fileName,\n sizeBytes: chunk.sizeBytes,\n };\n\n diagnostics.emittedPageChunks.push(emittedPage);\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded: false,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n file.sizeAfterBytes = commonWasSplit\n ? commonSizeBytes\n : Buffer.byteLength(output.source, \"utf8\");\n file.split = {\n associatedPages,\n commonSizeBytes,\n pageSpecificSizeBytes,\n deadCodeCount: pipeline.deadCodeCount,\n };\n\n for (const stat of pipeline.stats) {\n const previous = matrix.get(stat.selector);\n\n if (!previous || stat.totalOccurrences > previous.totalOccurrences) {\n matrix.set(stat.selector, stat);\n }\n }\n\n diagnostics.deadCodeCount += pipeline.deadCodeCount;\n diagnostics.commonCssBytes += commonSizeBytes;\n diagnostics.pageSpecificCssBytes += pageSpecificSizeBytes;\n } catch (error) {\n diagnostics.errors.push(\n `${file.fileName}: failed to optimize CSS: ${describeError(error)}`,\n );\n }\n\n diagnostics.analyzedCssAssets += 1;\n diagnostics.totalSizeBeforeBytes += file.sizeBeforeBytes;\n diagnostics.totalSizeAfterBytes += file.sizeAfterBytes;\n diagnostics.totalSelectors += file.selectorCount;\n diagnostics.totalRules += file.ruleCount;\n diagnostics.files.push(file);\n }\n\n if (htmlLinks.length > 0) {\n injectStylesheetLinks(bundle, htmlLinks, options.base);\n }\n\n if (pageCssFiles.size > 0) {\n injectPageChunkStyles(bundle, pageCssFiles, pageChunkFiles, options.base);\n }\n\n diagnostics.usageMatrix = [...matrix.values()].sort((left, right) =>\n left.selector.localeCompare(right.selector),\n );\n diagnostics.durationMs = roundMs(performance.now() - startedAt);\n\n return diagnostics;\n}\n\nfunction emitCssAsset(\n environment: AnalysisEnvironment,\n name: string,\n source: string,\n): string {\n const referenceId = environment.emitFile({\n type: \"asset\",\n name,\n source,\n });\n\n return environment.getFileName(referenceId);\n}\n\nfunction injectPageChunkStyles(\n bundle: Record<string, unknown>,\n cssByPage: Map<string, string[]>,\n chunkByPage: Map<string, string>,\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n\n for (const [page, fileNames] of cssByPage) {\n if (fileNames.length === 0) {\n continue;\n }\n\n const chunkFile = chunkByPage.get(page);\n const hrefs = fileNames.map((fileName) => `${normalizedBase}${fileName}`);\n const htmlOutput = findPageHtmlAsset(bundle, page);\n const output = htmlOutput ?? (chunkFile ? bundle[chunkFile] : undefined);\n\n if (isHtmlAsset(output)) {\n const tags = hrefs\n .map(\n (href) =>\n ` <link rel=\"stylesheet\" href=\"${href}\" data-css-doctor-page>`,\n )\n .join(\"\\n\");\n\n if (!output.source.includes(tags) && output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n continue;\n }\n\n if (!isChunk(output)) {\n continue;\n }\n\n const snippet = `(()=>{const __cssDoctorPageStyles=${JSON.stringify(hrefs)};if(typeof document!==\"undefined\"){for(const __cssDoctorPageHref of __cssDoctorPageStyles){if(!Array.from(document.querySelectorAll(\"link[data-css-doctor-page]\")).some((link)=>link.dataset.cssDoctorPage===__cssDoctorPageHref)){const __cssDoctorPageLink=document.createElement(\"link\");__cssDoctorPageLink.rel=\"stylesheet\";__cssDoctorPageLink.href=__cssDoctorPageHref;__cssDoctorPageLink.dataset.cssDoctorPage=__cssDoctorPageHref;document.head.append(__cssDoctorPageLink);}}}})();\\n`;\n\n output.code = snippet + output.code;\n }\n}\n\nfunction injectStylesheetLinks(\n bundle: Record<string, unknown>,\n fileNames: string[],\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const tags = fileNames\n .map(\n (fileName) =>\n ` <link rel=\"stylesheet\" href=\"${normalizedBase}${fileName}\">`,\n )\n .join(\"\\n\");\n\n for (const output of Object.values(bundle)) {\n if (!isHtmlAsset(output) || output.source.includes(tags)) {\n continue;\n }\n\n if (output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n }\n}\n\nfunction findPageHtmlAsset(\n bundle: Record<string, unknown>,\n page: string,\n): unknown {\n const names =\n page === \"index\"\n ? [\"index.html\"]\n : [\n `page-${page}/index.html`,\n `page-${page}.html`,\n `${page}/index.html`,\n `${page}.html`,\n ];\n\n for (const name of names) {\n const output = bundle[name];\n\n if (isHtmlAsset(output)) {\n return output;\n }\n }\n\n return undefined;\n}\n\nfunction isHtmlAsset(\n value: unknown,\n): value is { type: \"asset\"; fileName: string; source: string } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".html\") &&\n typeof candidate.source === \"string\"\n );\n}\n\nfunction analyzeAsset(\n output: CssAssetLike,\n associatedPages: string[],\n): CssAssetDiagnostic {\n const analysisStartedAt = performance.now();\n\n try {\n const css = sourceToCss(output.source);\n const sizeBeforeBytes = Buffer.byteLength(css, \"utf8\");\n const analysis = analyzeCss(css);\n const warnings = collectSyntaxWarnings(analysis);\n\n if (sizeBeforeBytes >= LARGE_CSS_ASSET_BYTES) {\n warnings.push({\n kind: \"large-asset\",\n message:\n `CSS asset is larger than ${formatBytes(LARGE_CSS_ASSET_BYTES)}; ` +\n \"consider route-level code splitting.\",\n });\n }\n\n return {\n fileName: output.fileName,\n sizeBeforeBytes,\n sizeAfterBytes: sizeBeforeBytes,\n selectorCount: analysis.stats.selectorCount,\n ruleCount: analysis.stats.ruleCount,\n declarationCount: analysis.stats.declarationCount,\n importantDeclarationCount: analysis.stats.importantDeclarationCount,\n uniqueClassCount: analysis.stats.uniqueClassCount,\n uniqueIdCount: analysis.stats.uniqueIdCount,\n uniqueTagCount: analysis.stats.uniqueTagCount,\n syntaxWarningCount: analysis.warnings.length,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings,\n analysis,\n };\n } catch (error) {\n return {\n fileName: output.fileName,\n sizeBeforeBytes: 0,\n sizeAfterBytes: 0,\n selectorCount: 0,\n ruleCount: 0,\n declarationCount: 0,\n importantDeclarationCount: 0,\n uniqueClassCount: 0,\n uniqueIdCount: 0,\n uniqueTagCount: 0,\n syntaxWarningCount: 0,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings: [],\n error: describeError(error),\n };\n }\n}\n\nasync function collectPages(\n bundle: Record<string, unknown>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n directPageUsage: Record<string, string[]> | undefined,\n): Promise<{\n pages: PageInfo[];\n pagesByCss: Map<string, Set<string>>;\n}> {\n const chunks = Object.values(bundle).filter(isChunk);\n const chunksByFileName = new Map(\n chunks.map((chunk) => [chunk.fileName, chunk]),\n );\n const pages = new Map<string, PageInfo>();\n const entryFileNames = new Set(\n chunks.filter((chunk) => chunk.isEntry).map((chunk) => chunk.fileName),\n );\n\n for (const entry of chunks.filter((chunk) => chunk.isEntry)) {\n if (isInternalPageEntry(entry)) {\n continue;\n }\n\n const shell = collectChunkContent(\n entry,\n chunksByFileName,\n getModuleInfo,\n false,\n );\n\n if (entry.facadeModuleId && isHtmlFile(entry.facadeModuleId)) {\n try {\n scanClasses(\n await readFile(entry.facadeModuleId, \"utf8\"),\n shell.classes,\n );\n } catch {\n // The HTML source may be virtual or removed by another plugin. The\n // generated chunk code and pageUsage option still provide coverage.\n }\n }\n\n const routeChunks = entry.dynamicImports\n .map((fileName) => chunksByFileName.get(fileName))\n .filter((chunk): chunk is ViteChunkLike => chunk !== undefined);\n\n if (routeChunks.length > 0) {\n // A SPA shell usually owns the HTML, navigation and global CSS, while\n // every direct dynamic import is a route. Treat those chunks as pages\n // and apply the shell classes/CSS to each one, instead of collapsing all\n // routes into the single index entry.\n for (const routeChunk of routeChunks) {\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(routePageName(routeChunk)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: routeChunk.fileName,\n };\n const route = collectChunkContent(\n routeChunk,\n chunksByFileName,\n getModuleInfo,\n true,\n entryFileNames,\n );\n\n for (const className of route.classes) {\n page.classes.add(className);\n }\n\n for (const cssFile of route.cssFiles) {\n page.cssFiles.add(cssFile);\n }\n\n pages.set(page.name, page);\n }\n\n continue;\n }\n\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(pageNameFor(entry)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: entry.fileName,\n };\n\n pages.set(page.name, page);\n }\n\n if (directPageUsage) {\n for (const [rawName, classes] of Object.entries(directPageUsage)) {\n const name = rawName.trim();\n\n if (name.length === 0) {\n continue;\n }\n\n let page = pages.get(name);\n\n if (!page) {\n page = {\n name,\n classes: new Set(),\n cssFiles: new Set(),\n chunkFile: null,\n };\n pages.set(name, page);\n }\n\n for (const className of classes) {\n page.classes.add(className.toLowerCase());\n }\n }\n }\n\n const pagesByCss = new Map<string, Set<string>>();\n\n for (const page of pages.values()) {\n for (const cssFile of page.cssFiles) {\n const owners = pagesByCss.get(cssFile) ?? new Set<string>();\n owners.add(page.name);\n pagesByCss.set(cssFile, owners);\n }\n }\n\n return {\n pages: [...pages.values()],\n pagesByCss,\n };\n}\n\nfunction collectChunkContent(\n startChunk: ViteChunkLike,\n chunksByFileName: Map<string, ViteChunkLike>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n includeDynamicImports: boolean,\n skipFileNames: ReadonlySet<string> = new Set<string>(),\n): {\n classes: Set<string>;\n cssFiles: Set<string>;\n} {\n const classes = new Set<string>();\n const cssFiles = new Set<string>();\n const visited = new Set<string>();\n const stack = [startChunk.fileName];\n\n while (stack.length > 0) {\n const fileName = stack.pop();\n\n if (!fileName || visited.has(fileName) || skipFileNames.has(fileName)) {\n continue;\n }\n\n visited.add(fileName);\n\n const chunk = chunksByFileName.get(fileName);\n\n if (!chunk) {\n continue;\n }\n\n scanClasses(chunk.code, classes);\n\n for (const moduleId of Object.keys(chunk.modules)) {\n if (isStyleModule(moduleId)) {\n continue;\n }\n\n const moduleInfo = getModuleInfo(moduleId);\n\n if (moduleInfo?.code) {\n scanClasses(moduleInfo.code, classes);\n }\n }\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n cssFiles.add(cssFile);\n }\n\n stack.push(...chunk.imports);\n\n if (includeDynamicImports) {\n stack.push(...chunk.dynamicImports);\n }\n }\n\n return { classes, cssFiles };\n}\n\nfunction scanClasses(source: string, classes: Set<string>): void {\n const patterns = [\n /(?:class|className)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /(?:^|[,{;\\s])(?:class|className)\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /classList\\.(?:add|remove|toggle|contains)\\(\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n ];\n\n for (const pattern of patterns) {\n for (const match of source.matchAll(pattern)) {\n const value = match[1] ?? match[2] ?? match[3];\n\n if (!value) {\n continue;\n }\n\n for (const token of value.split(/\\s+/)) {\n if (/^-?[_a-zA-Z][\\w-]*$/.test(token)) {\n classes.add(token.toLowerCase());\n }\n }\n }\n }\n}\n\nfunction isInternalPageEntry(chunk: ViteChunkLike): boolean {\n const name = pageNameFor(chunk);\n\n return (\n name.startsWith(\"_\") ||\n name.startsWith(\"noop-\") ||\n name.includes(\"@astro-renderers\")\n );\n}\n\nfunction cleanPageName(name: string): string {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/@_@[a-z]+$/i, \"\")\n .replace(/^page-/, \"\");\n\n return normalized || \"page\";\n}\n\nfunction routePageName(chunk: ViteChunkLike): string {\n const name = pageNameFor(chunk).toLowerCase();\n\n return name.startsWith(\"page-\") ? name.slice(\"page-\".length) : name;\n}\n\nfunction isCssModuleAsset(fileName: string, css: string): boolean {\n if (/\\.module\\.(css|scss|sass|less|styl|stylus)$/i.test(fileName)) {\n return true;\n }\n\n // Vite's default CSS Modules local identifier is `_local_hash_index`\n // (for example `_card_1udun_1`). The emitted asset name is hashed, so\n // detect the scoped class shape in the source as a safety boundary.\n return /\\.[A-Za-z0-9_-]+_[A-Za-z0-9]{5,}_[0-9]+/.test(css);\n}\n\nfunction isVueScopedAsset(css: string): boolean {\n return /\\[data-v-[0-9a-f]+\\]/.test(css);\n}\n\nfunction pageNameFor(chunk: ViteChunkLike): string {\n if (chunk.name.length > 0) {\n return chunk.name;\n }\n\n if (chunk.facadeModuleId) {\n return basename(chunk.facadeModuleId, extname(chunk.facadeModuleId));\n }\n\n return chunk.fileName.replace(/\\.[^.]+$/, \"\");\n}\n\nfunction uniquePageName(base: string, pages: Map<string, PageInfo>): string {\n const normalized = base.trim() || \"page\";\n\n if (!pages.has(normalized)) {\n return normalized;\n }\n\n let index = 2;\n\n while (pages.has(`${normalized}-${index}`)) {\n index += 1;\n }\n\n return `${normalized}-${index}`;\n}\n\nfunction isCssAsset(value: unknown): value is CssAssetLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".css\") &&\n (typeof candidate.source === \"string\" ||\n candidate.source instanceof Uint8Array)\n );\n}\n\nfunction isChunk(value: unknown): value is ViteChunkLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n name?: unknown;\n isEntry?: unknown;\n facadeModuleId?: unknown;\n code?: unknown;\n modules?: unknown;\n imports?: unknown;\n dynamicImports?: unknown;\n };\n\n return (\n candidate.type === \"chunk\" &&\n typeof candidate.fileName === \"string\" &&\n typeof candidate.name === \"string\" &&\n typeof candidate.isEntry === \"boolean\" &&\n typeof candidate.code === \"string\" &&\n typeof candidate.modules === \"object\" &&\n candidate.modules !== null &&\n Array.isArray(candidate.imports) &&\n Array.isArray(candidate.dynamicImports)\n );\n}\n\nfunction isStyleModule(moduleId: string): boolean {\n return /\\.(css|scss|sass|less|styl|stylus)(\\?|$)/i.test(moduleId);\n}\n\nfunction isHtmlFile(moduleId: string): boolean {\n return /\\.(html?|vue)$/i.test(moduleId);\n}\n\nfunction collectSyntaxWarnings(\n analysis: JsCssAnalysisResult,\n): CssAssetWarning[] {\n return analysis.warnings.map((warning) => ({\n kind: \"syntax\",\n message: warning.message,\n ...(warning.location\n ? {\n line: warning.location.line,\n column: warning.location.column,\n }\n : {}),\n }));\n}\n\nfunction sourceToCss(source: string | Uint8Array): string {\n return typeof source === \"string\"\n ? source\n : Buffer.from(source).toString(\"utf8\");\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction roundMs(value: number): number {\n return Math.round(value * 1_000) / 1_000;\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import picocolors from \"picocolors\";\n\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n} from \"./types\";\n\nconst MATRIX_SELECTOR_MAX = 36;\n\n/** Options for terminal rendering. Defaults to picocolors' TTY detection. */\nexport type ReporterOptions = {\n color?: boolean;\n};\n\n/** Formats diagnostics as a human-readable build report. */\nexport function formatDiagnostics(\n diagnostics: CssDoctorDiagnostics,\n options: ReporterOptions = {},\n): string {\n const colors = picocolors.createColors(\n options.color ?? picocolors.isColorSupported,\n );\n const badge = colors.bgCyan(colors.black(\"[css-doctor]\"));\n const lines: string[] = [];\n\n lines.push(\n `${badge} ${diagnostics.pages.length} page${\n diagnostics.pages.length === 1 ? \"\" : \"s\"\n } ${colors.dim(\"·\")} ${diagnostics.analyzedCssAssets}/${\n diagnostics.totalCssAssets\n } CSS assets ${colors.dim(\"·\")} ${formatBytes(\n diagnostics.totalSizeBeforeBytes,\n )} → ${formatBytes(diagnostics.totalSizeAfterBytes)} common ` +\n `${colors.dim(\"·\")} ${formatDuration(diagnostics.durationMs)}` +\n (diagnostics.skippedCssAssets > 0\n ? ` ${colors.dim(`· ${diagnostics.skippedCssAssets} skipped`)}`\n : \"\") +\n ` ${colors.dim(\"·\")} ${\n diagnostics.minify\n ? colors.green(\"Minified: YES\")\n : colors.yellow(\"Minified: NO\")\n }`,\n );\n\n for (const file of diagnostics.files) {\n lines.push(...formatFile(file, colors));\n }\n\n if (diagnostics.splitApplied) {\n lines.push(\"\");\n lines.push(...formatMatrix(diagnostics, colors));\n }\n\n if (diagnostics.emittedPageChunks.length > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.bold(\"Emitted page chunks\")} ${colors.dim(\n `(${diagnostics.emittedPageChunks.length})`,\n )}`,\n );\n\n for (const chunk of diagnostics.emittedPageChunks) {\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}`,\n );\n }\n }\n\n if (diagnostics.sizeBudget.enabled) {\n lines.push(\"\");\n lines.push(...formatSizeBudget(diagnostics, colors));\n }\n\n if (diagnostics.deadCodeCount > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.yellow(\"⚠\")} ${colors.bold(\"Dead code eliminated:\")} ` +\n `${diagnostics.deadCodeCount} selector occurrence${\n diagnostics.deadCodeCount === 1 ? \"\" : \"s\"\n }`,\n );\n }\n\n if (diagnostics.errors.length > 0) {\n lines.push(\"\");\n lines.push(` ${colors.red(colors.bold(\"Errors\"))}`);\n\n for (const error of diagnostics.errors) {\n lines.push(` ${colors.red(\"✖\")} ${error}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Prints diagnostics to stdout. */\nexport function printDiagnostics(diagnostics: CssDoctorDiagnostics): void {\n console.log(formatDiagnostics(diagnostics));\n}\n\nfunction formatFile(\n file: CssAssetDiagnostic,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const failed = file.error !== undefined;\n const hasWarnings = file.warnings.length > 0;\n const icon = failed\n ? colors.red(\"✖\")\n : hasWarnings\n ? colors.yellow(\"⚠\")\n : colors.green(\"✓\");\n\n const size = `${formatBytes(file.sizeBeforeBytes)} → ${formatBytes(\n file.sizeAfterBytes,\n )}`;\n const selectors = failed ? \"\" : ` · ${file.selectorCount} selectors`;\n const pages =\n file.associatedPages.length > 0\n ? ` · pages: ${file.associatedPages.join(\", \")}`\n : \"\";\n\n const lines = [\n ` ${icon} ${colors.bold(file.fileName)} ${colors.dim(size)}${selectors}${colors.dim(pages)}`,\n ];\n\n if (file.error) {\n lines.push(` ${colors.red(file.error)}`);\n return lines;\n }\n\n if (file.split) {\n lines.push(\n ` ${colors.dim(\"split\")} common ${formatBytes(\n file.split.commonSizeBytes,\n )} ${colors.dim(\"·\")} page-specific ${formatBytes(\n file.split.pageSpecificSizeBytes,\n )} ${colors.dim(\"·\")} dead ${file.split.deadCodeCount}`,\n );\n }\n\n for (const warning of file.warnings) {\n lines.push(` ${formatWarning(warning, colors)}`);\n }\n\n return lines;\n}\n\nfunction formatMatrix(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const pageTotal = diagnostics.pages.length;\n const rows = diagnostics.usageMatrix;\n const header = [\n \"Selector\".padEnd(MATRIX_SELECTOR_MAX),\n \"Total Used\".padStart(10),\n \"Page Usage\".padStart(10),\n \"Coverage %\".padStart(10),\n \"Assigned Chunk\",\n ].join(\" \");\n\n const lines = [\n ` ${colors.bold(\"Usage Matrix\")} ${colors.dim(\n `(${rows.length} selectors · ${pageTotal} pages)`,\n )}`,\n ` ${colors.dim(header)}`,\n ];\n\n for (const row of rows) {\n const selector = truncate(row.selector, MATRIX_SELECTOR_MAX).padEnd(\n MATRIX_SELECTOR_MAX,\n );\n const totalUsed = String(row.totalOccurrences).padStart(10);\n const pageUsage = `${row.pageCount}/${pageTotal}`.padStart(10);\n const coverage = `${(row.coverageRatio * 100).toFixed(1)}%`.padStart(10);\n const chunk = formatChunk(row.targetChunk, colors);\n\n lines.push(\n ` ${colors.cyan(selector)} ${totalUsed} ${pageUsage} ${colorCoverage(\n coverage,\n row.coverageRatio,\n diagnostics.minPageRatio,\n colors,\n )} ${chunk}`,\n );\n }\n\n return lines;\n}\n\nfunction formatSizeBudget(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const budget = diagnostics.sizeBudget;\n const lines = [\n ` ${colors.bold(\"Size budget\")} ${colors.dim(\n `(max ${formatBytes(budget.maxChunkSize)} · variables ${\n budget.isolateVariables ? \"isolated\" : \"inline\"\n })`,\n )}`,\n ];\n\n const chunks = diagnostics.emittedCssChunks;\n\n if (chunks.length === 0) {\n lines.push(` ${colors.dim(\"No CSS chunks were emitted.\")}`);\n return lines;\n }\n\n for (const chunk of chunks) {\n const markers: string[] = [];\n\n if (chunk.variables) {\n markers.push(\"vars\");\n }\n\n if (chunk.part !== undefined) {\n markers.push(`part ${chunk.part}`);\n }\n\n if (chunk.embedded) {\n markers.push(\"embedded\");\n }\n\n if (chunk.splitDueToSize) {\n markers.push(colors.yellow(\"split\"));\n }\n\n if (chunk.oversized) {\n markers.push(colors.red(\"oversized\"));\n }\n\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}${markers.length > 0 ? ` ${colors.dim(\"·\")} ${markers.join(\" · \")}` : \"\"}`,\n );\n }\n\n if (budget.splitChunks === 0) {\n lines.push(\n ` ${colors.dim(\"No chunk exceeded the configured size budget.\")}`,\n );\n }\n\n return lines;\n}\n\nfunction formatWarning(\n warning: CssAssetWarning,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n const location =\n warning.line !== undefined\n ? colors.dim(\n `${warning.line}${\n warning.column !== undefined ? `:${warning.column}` : \"\"\n } `,\n )\n : \"\";\n\n return `${colors.yellow(\"!\")} ${location}${warning.message}`;\n}\n\nfunction colorCoverage(\n coverage: string,\n ratio: number,\n minPageRatio: number,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (ratio === 0) {\n return colors.red(coverage);\n }\n\n return ratio >= minPageRatio\n ? colors.green(coverage)\n : colors.yellow(coverage);\n}\n\nfunction formatChunk(\n chunk: string,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (chunk === \"common\") {\n return colors.cyan(chunk);\n }\n\n if (chunk === \"dead\") {\n return colors.red(chunk);\n }\n\n return colors.magenta(chunk);\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength\n ? value\n : `${value.slice(0, maxLength - 1)}…`;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (!Number.isFinite(milliseconds)) {\n return \"—\";\n }\n\n return milliseconds < 1\n ? `${milliseconds.toFixed(2)} ms`\n : `${milliseconds.toFixed(1)} ms`;\n}\n"],"mappings":"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","names":["picocolors","formatBytes","page"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/plugin.ts","../src/reporter.ts"],"sourcesContent":["export { cssDoctor } from \"./plugin\";\nexport type {\n CssAssetDiagnostic,\n CssAssetSplitInfo,\n CssAssetWarning,\n CssAssetWarningKind,\n CssDoctorFilter,\n CssDoctorFilterPattern,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetDiagnostics,\n SizeBudgetOptions,\n} from \"./types\";\n","import { readFile } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { createFilter } from \"@rollup/pluginutils\";\nimport { analyzeCss, optimizeCss } from \"@zealakit/css-doctor-binding\";\nimport type {\n JsCssAnalysisResult,\n JsSelectorStat,\n} from \"@zealakit/css-doctor-binding\";\nimport type { Plugin } from \"vite\";\n\nimport { printDiagnostics } from \"./reporter\";\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetOptions,\n} from \"./types\";\n\nconst DEFAULT_MIN_PAGE_RATIO = 0.5;\nconst DEFAULT_MAX_CHUNK_SIZE = 60 * 1_024;\nconst LARGE_CSS_ASSET_BYTES = 500 * 1_024;\n\ntype CssAssetLike = {\n type: \"asset\";\n fileName: string;\n source: string | Uint8Array;\n};\n\ntype ViteChunkLike = {\n type: \"chunk\";\n fileName: string;\n name: string;\n isEntry: boolean;\n facadeModuleId: string | null;\n code: string;\n modules: Record<string, unknown>;\n imports: string[];\n dynamicImports: string[];\n viteMetadata?: {\n importedCss?: Set<string>;\n };\n};\n\ntype PageInfo = {\n name: string;\n classes: Set<string>;\n cssFiles: Set<string>;\n chunkFile: string | null;\n};\n\ntype EmitAsset = {\n type: \"asset\";\n name?: string;\n fileName?: string;\n source: string | Uint8Array;\n};\n\ntype AnalysisEnvironment = {\n getModuleInfo: (id: string) => { code?: string | null } | null;\n emitFile: (asset: EmitAsset) => string;\n getFileName: (referenceId: string) => string;\n};\n\n/**\n * Creates a Vite plugin that splits emitted CSS by page coverage and removes\n * selectors that no scanned page uses.\n *\n * The plugin is read-only with respect to existing assets except for replacing\n * their contents with the common chunk. New page-specific files are emitted\n * with `this.emitFile`. Read, parse, split and callback failures are contained\n * so the user's build is never interrupted.\n */\nexport function cssDoctor(options: CssDoctorViteOptions = {}): Plugin {\n const pageCoverage: PageCoverageOptions = {\n enabled: options.pageCoverage?.enabled ?? true,\n minPageRatio:\n options.pageCoverage?.minPageRatio ??\n options.minPageRatio ??\n DEFAULT_MIN_PAGE_RATIO,\n forceCommon:\n options.pageCoverage?.forceCommon ?? options.forceCommonSelectors ?? [],\n };\n const sizeBudget: SizeBudgetOptions = {\n enabled: options.sizeBudget?.enabled ?? true,\n maxChunkSize: options.sizeBudget?.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE,\n isolateVariables: options.sizeBudget?.isolateVariables ?? true,\n };\n const report = options.report ?? true;\n const configuredMinPageRatio =\n pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;\n const configuredMaxChunkSize =\n sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;\n const configurationWarnings: string[] = [];\n const minPageRatio =\n Number.isFinite(configuredMinPageRatio) &&\n configuredMinPageRatio >= 0 &&\n configuredMinPageRatio <= 1\n ? configuredMinPageRatio\n : DEFAULT_MIN_PAGE_RATIO;\n const maxChunkSize =\n Number.isFinite(configuredMaxChunkSize) &&\n Number.isInteger(configuredMaxChunkSize) &&\n configuredMaxChunkSize > 0\n ? configuredMaxChunkSize\n : DEFAULT_MAX_CHUNK_SIZE;\n let base = \"/\";\n let minify = options.minify ?? true;\n\n if (minPageRatio !== configuredMinPageRatio) {\n configurationWarnings.push(\n \"minPageRatio must be a number between 0 and 1; using 0.5\",\n );\n }\n\n if (maxChunkSize !== configuredMaxChunkSize) {\n configurationWarnings.push(\n \"maxChunkSize must be a positive integer; using 61440\",\n );\n }\n\n // Keep resolved configs aligned with clamped values so optimizeCss never\n // receives invalid numbers from a bad factory configuration.\n pageCoverage.minPageRatio = minPageRatio;\n sizeBudget.maxChunkSize = maxChunkSize;\n\n const filter = createFilter(options.include, options.exclude, {\n resolve: false,\n });\n\n return {\n name: \"vite-plugin-css-doctor\",\n apply: \"build\",\n enforce: \"post\",\n\n config(config) {\n if (options.minify === false) {\n config.build ??= {};\n config.build.cssMinify = false;\n }\n },\n\n configResolved(config) {\n base = config.base;\n minify =\n options.minify ??\n (config.mode === \"production\" || config.command === \"build\");\n },\n\n async generateBundle(_outputOptions, bundle) {\n try {\n const diagnostics = await analyzeAndSplit(\n bundle,\n {\n getModuleInfo: (id) => this.getModuleInfo(id),\n emitFile: (asset) => this.emitFile(asset),\n getFileName: (referenceId) => this.getFileName(referenceId),\n },\n {\n filter,\n pageCoverage: {\n enabled: pageCoverage.enabled ?? true,\n minPageRatio,\n forceCommon: pageCoverage.forceCommon ?? [],\n },\n sizeBudget: {\n enabled: sizeBudget.enabled ?? true,\n maxChunkSize,\n isolateVariables: sizeBudget.isolateVariables ?? true,\n },\n directPageUsage: options.pageUsage,\n base,\n minify,\n skipVueScopedStyles: options.skipVueScopedStyles ?? false,\n wrapCommonImports: options.wrapCommonImports ?? false,\n },\n );\n\n for (const warning of configurationWarnings) {\n this.warn(`[css-doctor] ${warning}`);\n diagnostics.errors.push(warning);\n }\n\n if (options.onDiagnostics) {\n try {\n await options.onDiagnostics(diagnostics);\n } catch (error) {\n const message = `onDiagnostics callback failed: ${describeError(error)}`;\n diagnostics.errors.push(message);\n this.warn(`[css-doctor] ${message}`);\n }\n }\n\n if (\n report &&\n (diagnostics.totalCssAssets > 0 || diagnostics.errors.length > 0)\n ) {\n printDiagnostics(diagnostics);\n }\n } catch (error) {\n this.warn(\n `[css-doctor] diagnostics failed without interrupting the build: ${describeError(error)}`,\n );\n }\n },\n };\n}\n\ntype SplitOptions = {\n filter: (id: string) => boolean;\n pageCoverage: Required<PageCoverageOptions> & { forceCommon: string[] };\n sizeBudget: Required<SizeBudgetOptions>;\n directPageUsage: Record<string, string[]> | undefined;\n base: string;\n minify: boolean;\n skipVueScopedStyles: boolean;\n wrapCommonImports: boolean;\n};\n\nasync function analyzeAndSplit(\n bundle: Record<string, unknown>,\n environment: AnalysisEnvironment,\n options: SplitOptions,\n): Promise<CssDoctorDiagnostics> {\n const startedAt = performance.now();\n const { pages, pagesByCss } = await collectPages(\n bundle,\n environment.getModuleInfo,\n options.directPageUsage,\n );\n const pageNames = pages.map((page) => page.name);\n const pageNameSet = new Set(pageNames);\n const pageChunkFiles = new Map<string, string>();\n\n for (const page of pages) {\n if (page.chunkFile) {\n pageChunkFiles.set(page.name, page.chunkFile);\n }\n }\n const pageUsage: Record<string, string[]> = {};\n const pageUsageCounts: Record<string, number> = {};\n\n for (const page of pages) {\n const classes = [...page.classes].sort();\n pageUsage[page.name] = classes;\n pageUsageCounts[page.name] = classes.length;\n }\n\n const hasPageClasses = pages.some((page) => page.classes.size > 0);\n const splitApplied = options.pageCoverage.enabled && hasPageClasses;\n const diagnostics: CssDoctorDiagnostics = {\n plugin: \"vite-plugin-css-doctor\",\n generatedAt: new Date().toISOString(),\n durationMs: 0,\n minPageRatio: options.pageCoverage.minPageRatio,\n minify: options.minify,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n splitChunks: 0,\n oversizedChunks: 0,\n },\n pages: pageNames,\n pageUsage: pageUsageCounts,\n splitApplied,\n totalCssAssets: 0,\n analyzedCssAssets: 0,\n skippedCssAssets: 0,\n failedCssAssets: 0,\n totalSizeBeforeBytes: 0,\n totalSizeAfterBytes: 0,\n totalSelectors: 0,\n totalRules: 0,\n commonCssBytes: 0,\n pageSpecificCssBytes: 0,\n emittedPageChunks: [],\n emittedCssChunks: [],\n usageMatrix: [],\n deadCodeCount: 0,\n files: [],\n errors: [],\n };\n\n const matrix = new Map<string, JsSelectorStat>();\n const htmlLinks: string[] = [];\n const commonFileNames: string[] = [];\n const pageCssFiles = new Map<string, string[]>();\n\n for (const output of Object.values(bundle)) {\n if (!isCssAsset(output)) {\n continue;\n }\n\n diagnostics.totalCssAssets += 1;\n\n if (!options.filter(output.fileName)) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (isCssModuleAsset(output.fileName, sourceToCss(output.source))) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (\n options.skipVueScopedStyles &&\n isVueScopedAsset(sourceToCss(output.source))\n ) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n const associatedPages = [\n ...(pagesByCss.get(output.fileName) ?? pageNameSet),\n ].sort();\n\n const file = analyzeAsset(output, associatedPages);\n\n if (file.error) {\n diagnostics.failedCssAssets += 1;\n diagnostics.errors.push(`${file.fileName}: ${file.error}`);\n diagnostics.files.push(file);\n continue;\n }\n\n const originalContent = sourceToCss(output.source);\n\n try {\n const pipeline = optimizeCss({\n cssContent: originalContent,\n pageUsage,\n pageCoverage: {\n enabled: splitApplied,\n minPageRatio: options.pageCoverage.minPageRatio,\n forceCommon: options.pageCoverage.forceCommon,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n },\n minify: options.minify,\n });\n\n const commonChunks = pipeline.chunks.filter(\n (chunk) => chunk.page === undefined && chunk.sourceChunk === \"common\",\n );\n const pageChunks = pipeline.chunks.filter(\n (chunk) => chunk.page !== undefined,\n );\n const commonWasSplit =\n commonChunks.length > 1 ||\n commonChunks.some((chunk) => chunk.splitDueToSize);\n const embeddedCommon = commonWasSplit ? undefined : commonChunks[0];\n\n output.source = embeddedCommon?.css ?? \"\";\n file.sizeAfterBytes = Buffer.byteLength(output.source, \"utf8\");\n\n let commonSizeBytes = 0;\n let pageSpecificSizeBytes = 0;\n\n for (const chunk of commonChunks) {\n const embedded = chunk === embeddedCommon;\n const fileName = embedded\n ? output.fileName\n : emitCssAsset(environment, `${chunk.name}.css`, chunk.css);\n commonSizeBytes += chunk.sizeBytes;\n\n if (!embedded) {\n htmlLinks.push(fileName);\n commonFileNames.push(fileName);\n }\n\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page: chunk.page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n if (options.wrapCommonImports && commonWasSplit) {\n output.source = commonFileNames\n .map((fileName) => `@import \"./${basename(fileName)}\";`)\n .join(\"\\n\");\n }\n\n for (const chunk of pageChunks) {\n const page = chunk.page;\n\n if (!page) {\n continue;\n }\n\n const fileName = emitCssAsset(\n environment,\n `${chunk.name}.css`,\n chunk.css,\n );\n pageSpecificSizeBytes += chunk.sizeBytes;\n const files = pageCssFiles.get(page) ?? [];\n files.push(fileName);\n pageCssFiles.set(page, files);\n\n const emittedPage: EmittedPageChunk = {\n page,\n fileName,\n sizeBytes: chunk.sizeBytes,\n };\n\n diagnostics.emittedPageChunks.push(emittedPage);\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded: false,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n file.sizeAfterBytes = commonWasSplit\n ? commonSizeBytes\n : Buffer.byteLength(output.source, \"utf8\");\n file.split = {\n associatedPages,\n commonSizeBytes,\n pageSpecificSizeBytes,\n deadCodeCount: pipeline.deadCodeCount,\n };\n\n for (const stat of pipeline.stats) {\n const previous = matrix.get(stat.selector);\n\n if (!previous || stat.totalOccurrences > previous.totalOccurrences) {\n matrix.set(stat.selector, stat);\n }\n }\n\n diagnostics.deadCodeCount += pipeline.deadCodeCount;\n diagnostics.commonCssBytes += commonSizeBytes;\n diagnostics.pageSpecificCssBytes += pageSpecificSizeBytes;\n } catch (error) {\n diagnostics.errors.push(\n `${file.fileName}: failed to optimize CSS: ${describeError(error)}`,\n );\n }\n\n diagnostics.analyzedCssAssets += 1;\n diagnostics.totalSizeBeforeBytes += file.sizeBeforeBytes;\n diagnostics.totalSizeAfterBytes += file.sizeAfterBytes;\n diagnostics.totalSelectors += file.selectorCount;\n diagnostics.totalRules += file.ruleCount;\n diagnostics.files.push(file);\n }\n\n if (htmlLinks.length > 0) {\n injectStylesheetLinks(bundle, htmlLinks, options.base);\n }\n\n if (pageCssFiles.size > 0) {\n injectPageChunkStyles(bundle, pageCssFiles, pageChunkFiles, options.base);\n }\n\n diagnostics.usageMatrix = [...matrix.values()].sort((left, right) =>\n left.selector.localeCompare(right.selector),\n );\n diagnostics.durationMs = roundMs(performance.now() - startedAt);\n\n return diagnostics;\n}\n\nfunction emitCssAsset(\n environment: AnalysisEnvironment,\n name: string,\n source: string,\n): string {\n const referenceId = environment.emitFile({\n type: \"asset\",\n name,\n source,\n });\n\n return environment.getFileName(referenceId);\n}\n\nfunction injectPageChunkStyles(\n bundle: Record<string, unknown>,\n cssByPage: Map<string, string[]>,\n chunkByPage: Map<string, string>,\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n\n for (const [page, fileNames] of cssByPage) {\n if (fileNames.length === 0) {\n continue;\n }\n\n const chunkFile = chunkByPage.get(page);\n const hrefs = fileNames.map((fileName) => `${normalizedBase}${fileName}`);\n const htmlOutput = findPageHtmlAsset(bundle, page);\n const output = htmlOutput ?? (chunkFile ? bundle[chunkFile] : undefined);\n\n if (isHtmlAsset(output)) {\n const tags = hrefs\n .map(\n (href) =>\n ` <link rel=\"stylesheet\" href=\"${href}\" data-css-doctor-page>`,\n )\n .join(\"\\n\");\n\n if (!output.source.includes(tags) && output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n continue;\n }\n\n if (!isChunk(output)) {\n continue;\n }\n\n const snippet = `(()=>{const __cssDoctorPageStyles=${JSON.stringify(hrefs)};if(typeof document!==\"undefined\"){for(const __cssDoctorPageHref of __cssDoctorPageStyles){if(!Array.from(document.querySelectorAll(\"link[data-css-doctor-page]\")).some((link)=>link.dataset.cssDoctorPage===__cssDoctorPageHref)){const __cssDoctorPageLink=document.createElement(\"link\");__cssDoctorPageLink.rel=\"stylesheet\";__cssDoctorPageLink.href=__cssDoctorPageHref;__cssDoctorPageLink.dataset.cssDoctorPage=__cssDoctorPageHref;document.head.append(__cssDoctorPageLink);}}}})();\\n`;\n\n output.code = snippet + output.code;\n }\n}\n\nfunction injectStylesheetLinks(\n bundle: Record<string, unknown>,\n fileNames: string[],\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const tags = fileNames\n .map(\n (fileName) =>\n ` <link rel=\"stylesheet\" href=\"${normalizedBase}${fileName}\">`,\n )\n .join(\"\\n\");\n\n for (const output of Object.values(bundle)) {\n if (!isHtmlAsset(output) || output.source.includes(tags)) {\n continue;\n }\n\n if (output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n }\n}\n\nfunction findPageHtmlAsset(\n bundle: Record<string, unknown>,\n page: string,\n): unknown {\n const names =\n page === \"index\"\n ? [\"index.html\"]\n : [\n `page-${page}/index.html`,\n `page-${page}.html`,\n `${page}/index.html`,\n `${page}.html`,\n ];\n\n for (const name of names) {\n const output = bundle[name];\n\n if (isHtmlAsset(output)) {\n return output;\n }\n }\n\n return undefined;\n}\n\nfunction isHtmlAsset(\n value: unknown,\n): value is { type: \"asset\"; fileName: string; source: string } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".html\") &&\n typeof candidate.source === \"string\"\n );\n}\n\nfunction analyzeAsset(\n output: CssAssetLike,\n associatedPages: string[],\n): CssAssetDiagnostic {\n const analysisStartedAt = performance.now();\n\n try {\n const css = sourceToCss(output.source);\n const sizeBeforeBytes = Buffer.byteLength(css, \"utf8\");\n const analysis = analyzeCss(css);\n const warnings = collectSyntaxWarnings(analysis);\n\n if (sizeBeforeBytes >= LARGE_CSS_ASSET_BYTES) {\n warnings.push({\n kind: \"large-asset\",\n message:\n `CSS asset is larger than ${formatBytes(LARGE_CSS_ASSET_BYTES)}; ` +\n \"consider route-level code splitting.\",\n });\n }\n\n return {\n fileName: output.fileName,\n sizeBeforeBytes,\n sizeAfterBytes: sizeBeforeBytes,\n selectorCount: analysis.stats.selectorCount,\n ruleCount: analysis.stats.ruleCount,\n declarationCount: analysis.stats.declarationCount,\n importantDeclarationCount: analysis.stats.importantDeclarationCount,\n uniqueClassCount: analysis.stats.uniqueClassCount,\n uniqueIdCount: analysis.stats.uniqueIdCount,\n uniqueTagCount: analysis.stats.uniqueTagCount,\n syntaxWarningCount: analysis.warnings.length,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings,\n analysis,\n };\n } catch (error) {\n return {\n fileName: output.fileName,\n sizeBeforeBytes: 0,\n sizeAfterBytes: 0,\n selectorCount: 0,\n ruleCount: 0,\n declarationCount: 0,\n importantDeclarationCount: 0,\n uniqueClassCount: 0,\n uniqueIdCount: 0,\n uniqueTagCount: 0,\n syntaxWarningCount: 0,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings: [],\n error: describeError(error),\n };\n }\n}\n\nasync function collectPages(\n bundle: Record<string, unknown>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n directPageUsage: Record<string, string[]> | undefined,\n): Promise<{\n pages: PageInfo[];\n pagesByCss: Map<string, Set<string>>;\n}> {\n const chunks = Object.values(bundle).filter(isChunk);\n const chunksByFileName = new Map(\n chunks.map((chunk) => [chunk.fileName, chunk]),\n );\n const pages = new Map<string, PageInfo>();\n const entryFileNames = new Set(\n chunks.filter((chunk) => chunk.isEntry).map((chunk) => chunk.fileName),\n );\n\n for (const entry of chunks.filter((chunk) => chunk.isEntry)) {\n if (isInternalPageEntry(entry)) {\n continue;\n }\n\n const shell = collectChunkContent(\n entry,\n chunksByFileName,\n getModuleInfo,\n false,\n );\n\n if (entry.facadeModuleId && isHtmlFile(entry.facadeModuleId)) {\n try {\n scanClasses(\n await readFile(entry.facadeModuleId, \"utf8\"),\n shell.classes,\n );\n } catch {\n // The HTML source may be virtual or removed by another plugin. The\n // generated chunk code and pageUsage option still provide coverage.\n }\n }\n\n const routeChunks = entry.dynamicImports\n .map((fileName) => chunksByFileName.get(fileName))\n .filter((chunk): chunk is ViteChunkLike => chunk !== undefined);\n\n if (routeChunks.length > 0) {\n // A SPA shell usually owns the HTML, navigation and global CSS, while\n // every direct dynamic import is a route. Treat those chunks as pages\n // and apply the shell classes/CSS to each one, instead of collapsing all\n // routes into the single index entry.\n for (const routeChunk of routeChunks) {\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(routePageName(routeChunk)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: routeChunk.fileName,\n };\n const route = collectChunkContent(\n routeChunk,\n chunksByFileName,\n getModuleInfo,\n true,\n entryFileNames,\n );\n\n for (const className of route.classes) {\n page.classes.add(className);\n }\n\n for (const cssFile of route.cssFiles) {\n page.cssFiles.add(cssFile);\n }\n\n pages.set(page.name, page);\n }\n\n continue;\n }\n\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(pageNameFor(entry)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: entry.fileName,\n };\n\n pages.set(page.name, page);\n }\n\n if (directPageUsage) {\n for (const [rawName, classes] of Object.entries(directPageUsage)) {\n const name = rawName.trim();\n\n if (name.length === 0) {\n continue;\n }\n\n let page = pages.get(name);\n\n if (!page) {\n page = {\n name,\n classes: new Set(),\n cssFiles: new Set(),\n chunkFile: null,\n };\n pages.set(name, page);\n }\n\n for (const className of classes) {\n page.classes.add(className.toLowerCase());\n }\n }\n }\n\n const pagesByCss = new Map<string, Set<string>>();\n\n for (const page of pages.values()) {\n for (const cssFile of page.cssFiles) {\n const owners = pagesByCss.get(cssFile) ?? new Set<string>();\n owners.add(page.name);\n pagesByCss.set(cssFile, owners);\n }\n }\n\n return {\n pages: [...pages.values()],\n pagesByCss,\n };\n}\n\nfunction collectChunkContent(\n startChunk: ViteChunkLike,\n chunksByFileName: Map<string, ViteChunkLike>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n includeDynamicImports: boolean,\n skipFileNames: ReadonlySet<string> = new Set<string>(),\n): {\n classes: Set<string>;\n cssFiles: Set<string>;\n} {\n const classes = new Set<string>();\n const cssFiles = new Set<string>();\n const visited = new Set<string>();\n const stack = [startChunk.fileName];\n\n while (stack.length > 0) {\n const fileName = stack.pop();\n\n if (!fileName || visited.has(fileName) || skipFileNames.has(fileName)) {\n continue;\n }\n\n visited.add(fileName);\n\n const chunk = chunksByFileName.get(fileName);\n\n if (!chunk) {\n continue;\n }\n\n scanClasses(chunk.code, classes);\n\n for (const moduleId of Object.keys(chunk.modules)) {\n if (isStyleModule(moduleId)) {\n continue;\n }\n\n const moduleInfo = getModuleInfo(moduleId);\n\n if (moduleInfo?.code) {\n scanClasses(moduleInfo.code, classes);\n }\n }\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n cssFiles.add(cssFile);\n }\n\n stack.push(...chunk.imports);\n\n if (includeDynamicImports) {\n stack.push(...chunk.dynamicImports);\n }\n }\n\n return { classes, cssFiles };\n}\n\nfunction scanClasses(source: string, classes: Set<string>): void {\n const patterns = [\n /(?:class|className)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /(?:^|[,{;\\s])(?:class|className)\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /classList\\.(?:add|remove|toggle|contains)\\(\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n ];\n\n for (const pattern of patterns) {\n for (const match of source.matchAll(pattern)) {\n const value = match[1] ?? match[2] ?? match[3];\n\n if (!value) {\n continue;\n }\n\n for (const token of value.split(/\\s+/)) {\n if (isClassToken(token)) {\n classes.add(token.toLowerCase());\n }\n }\n }\n }\n}\n\n/** Accept Tailwind-style tokens (`md:flex`, `w-1/2`, `w-[10px]`, `!p-2`). */\nfunction isClassToken(token: string): boolean {\n if (!token || token.length > 256) {\n return false;\n }\n\n // Reject template/expression leftovers while allowing arbitrary-value brackets.\n if (/[`${}]/.test(token)) {\n return false;\n }\n\n return /[A-Za-z_]/.test(token);\n}\n\nfunction isInternalPageEntry(chunk: ViteChunkLike): boolean {\n const name = pageNameFor(chunk);\n\n return (\n name.startsWith(\"_\") ||\n name.startsWith(\"noop-\") ||\n name.includes(\"@astro-renderers\")\n );\n}\n\nfunction cleanPageName(name: string): string {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/@_@[a-z]+$/i, \"\")\n .replace(/^page-/, \"\");\n\n return normalized || \"page\";\n}\n\nfunction routePageName(chunk: ViteChunkLike): string {\n const name = pageNameFor(chunk).toLowerCase();\n\n return name.startsWith(\"page-\") ? name.slice(\"page-\".length) : name;\n}\n\nfunction isCssModuleAsset(fileName: string, css: string): boolean {\n if (/\\.module\\.(css|scss|sass|less|styl|stylus)$/i.test(fileName)) {\n return true;\n }\n\n // Vite's default CSS Modules local identifier is `_local_hash_index`\n // (for example `_card_1udun_1`). The emitted asset name is hashed, so\n // detect the scoped class shape in the source as a safety boundary.\n return /\\.[A-Za-z0-9_-]+_[A-Za-z0-9]{5,}_[0-9]+/.test(css);\n}\n\nfunction isVueScopedAsset(css: string): boolean {\n return /\\[data-v-[0-9a-f]+\\]/.test(css);\n}\n\nfunction pageNameFor(chunk: ViteChunkLike): string {\n if (chunk.name.length > 0) {\n return chunk.name;\n }\n\n if (chunk.facadeModuleId) {\n return basename(chunk.facadeModuleId, extname(chunk.facadeModuleId));\n }\n\n return chunk.fileName.replace(/\\.[^.]+$/, \"\");\n}\n\nfunction uniquePageName(base: string, pages: Map<string, PageInfo>): string {\n const normalized = base.trim() || \"page\";\n\n if (!pages.has(normalized)) {\n return normalized;\n }\n\n let index = 2;\n\n while (pages.has(`${normalized}-${index}`)) {\n index += 1;\n }\n\n return `${normalized}-${index}`;\n}\n\nfunction isCssAsset(value: unknown): value is CssAssetLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".css\") &&\n (typeof candidate.source === \"string\" ||\n candidate.source instanceof Uint8Array)\n );\n}\n\nfunction isChunk(value: unknown): value is ViteChunkLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n name?: unknown;\n isEntry?: unknown;\n facadeModuleId?: unknown;\n code?: unknown;\n modules?: unknown;\n imports?: unknown;\n dynamicImports?: unknown;\n };\n\n return (\n candidate.type === \"chunk\" &&\n typeof candidate.fileName === \"string\" &&\n typeof candidate.name === \"string\" &&\n typeof candidate.isEntry === \"boolean\" &&\n typeof candidate.code === \"string\" &&\n typeof candidate.modules === \"object\" &&\n candidate.modules !== null &&\n Array.isArray(candidate.imports) &&\n Array.isArray(candidate.dynamicImports)\n );\n}\n\nfunction isStyleModule(moduleId: string): boolean {\n return /\\.(css|scss|sass|less|styl|stylus)(\\?|$)/i.test(moduleId);\n}\n\nfunction isHtmlFile(moduleId: string): boolean {\n return /\\.(html?|vue)$/i.test(moduleId);\n}\n\nfunction collectSyntaxWarnings(\n analysis: JsCssAnalysisResult,\n): CssAssetWarning[] {\n return analysis.warnings.map((warning) => ({\n kind: \"syntax\",\n message: warning.message,\n ...(warning.location\n ? {\n line: warning.location.line,\n column: warning.location.column,\n }\n : {}),\n }));\n}\n\nfunction sourceToCss(source: string | Uint8Array): string {\n return typeof source === \"string\"\n ? source\n : Buffer.from(source).toString(\"utf8\");\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction roundMs(value: number): number {\n return Math.round(value * 1_000) / 1_000;\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import picocolors from \"picocolors\";\n\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n} from \"./types\";\n\nconst MATRIX_SELECTOR_MAX = 36;\n\n/** Options for terminal rendering. Defaults to picocolors' TTY detection. */\nexport type ReporterOptions = {\n color?: boolean;\n};\n\n/** Formats diagnostics as a human-readable build report. */\nexport function formatDiagnostics(\n diagnostics: CssDoctorDiagnostics,\n options: ReporterOptions = {},\n): string {\n const colors = picocolors.createColors(\n options.color ?? picocolors.isColorSupported,\n );\n const badge = colors.bgCyan(colors.black(\"[css-doctor]\"));\n const lines: string[] = [];\n\n lines.push(\n `${badge} ${diagnostics.pages.length} page${\n diagnostics.pages.length === 1 ? \"\" : \"s\"\n } ${colors.dim(\"·\")} ${diagnostics.analyzedCssAssets}/${\n diagnostics.totalCssAssets\n } CSS assets ${colors.dim(\"·\")} ${formatBytes(\n diagnostics.totalSizeBeforeBytes,\n )} → ${formatBytes(diagnostics.totalSizeAfterBytes)} common ` +\n `${colors.dim(\"·\")} ${formatDuration(diagnostics.durationMs)}` +\n (diagnostics.skippedCssAssets > 0\n ? ` ${colors.dim(`· ${diagnostics.skippedCssAssets} skipped`)}`\n : \"\") +\n ` ${colors.dim(\"·\")} ${\n diagnostics.minify\n ? colors.green(\"Minified: YES\")\n : colors.yellow(\"Minified: NO\")\n }`,\n );\n\n for (const file of diagnostics.files) {\n lines.push(...formatFile(file, colors));\n }\n\n if (diagnostics.splitApplied) {\n lines.push(\"\");\n lines.push(...formatMatrix(diagnostics, colors));\n }\n\n if (diagnostics.emittedPageChunks.length > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.bold(\"Emitted page chunks\")} ${colors.dim(\n `(${diagnostics.emittedPageChunks.length})`,\n )}`,\n );\n\n for (const chunk of diagnostics.emittedPageChunks) {\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}`,\n );\n }\n }\n\n if (diagnostics.sizeBudget.enabled) {\n lines.push(\"\");\n lines.push(...formatSizeBudget(diagnostics, colors));\n }\n\n if (diagnostics.deadCodeCount > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.yellow(\"⚠\")} ${colors.bold(\"Dead code eliminated:\")} ` +\n `${diagnostics.deadCodeCount} selector occurrence${\n diagnostics.deadCodeCount === 1 ? \"\" : \"s\"\n }`,\n );\n }\n\n if (diagnostics.errors.length > 0) {\n lines.push(\"\");\n lines.push(` ${colors.red(colors.bold(\"Errors\"))}`);\n\n for (const error of diagnostics.errors) {\n lines.push(` ${colors.red(\"✖\")} ${error}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Prints diagnostics to stdout. */\nexport function printDiagnostics(diagnostics: CssDoctorDiagnostics): void {\n console.log(formatDiagnostics(diagnostics));\n}\n\nfunction formatFile(\n file: CssAssetDiagnostic,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const failed = file.error !== undefined;\n const hasWarnings = file.warnings.length > 0;\n const icon = failed\n ? colors.red(\"✖\")\n : hasWarnings\n ? colors.yellow(\"⚠\")\n : colors.green(\"✓\");\n\n const size = `${formatBytes(file.sizeBeforeBytes)} → ${formatBytes(\n file.sizeAfterBytes,\n )}`;\n const selectors = failed ? \"\" : ` · ${file.selectorCount} selectors`;\n const pages =\n file.associatedPages.length > 0\n ? ` · pages: ${file.associatedPages.join(\", \")}`\n : \"\";\n\n const lines = [\n ` ${icon} ${colors.bold(file.fileName)} ${colors.dim(size)}${selectors}${colors.dim(pages)}`,\n ];\n\n if (file.error) {\n lines.push(` ${colors.red(file.error)}`);\n return lines;\n }\n\n if (file.split) {\n lines.push(\n ` ${colors.dim(\"split\")} common ${formatBytes(\n file.split.commonSizeBytes,\n )} ${colors.dim(\"·\")} page-specific ${formatBytes(\n file.split.pageSpecificSizeBytes,\n )} ${colors.dim(\"·\")} dead ${file.split.deadCodeCount}`,\n );\n }\n\n for (const warning of file.warnings) {\n lines.push(` ${formatWarning(warning, colors)}`);\n }\n\n return lines;\n}\n\nfunction formatMatrix(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const pageTotal = diagnostics.pages.length;\n const rows = diagnostics.usageMatrix;\n const header = [\n \"Selector\".padEnd(MATRIX_SELECTOR_MAX),\n \"Total Used\".padStart(10),\n \"Page Usage\".padStart(10),\n \"Coverage %\".padStart(10),\n \"Assigned Chunk\",\n ].join(\" \");\n\n const lines = [\n ` ${colors.bold(\"Usage Matrix\")} ${colors.dim(\n `(${rows.length} selectors · ${pageTotal} pages)`,\n )}`,\n ` ${colors.dim(header)}`,\n ];\n\n for (const row of rows) {\n const selector = truncate(row.selector, MATRIX_SELECTOR_MAX).padEnd(\n MATRIX_SELECTOR_MAX,\n );\n const totalUsed = String(row.totalOccurrences).padStart(10);\n const pageUsage = `${row.pageCount}/${pageTotal}`.padStart(10);\n const coverage = `${(row.coverageRatio * 100).toFixed(1)}%`.padStart(10);\n const chunk = formatChunk(row.targetChunk, colors);\n\n lines.push(\n ` ${colors.cyan(selector)} ${totalUsed} ${pageUsage} ${colorCoverage(\n coverage,\n row.coverageRatio,\n diagnostics.minPageRatio,\n colors,\n )} ${chunk}`,\n );\n }\n\n return lines;\n}\n\nfunction formatSizeBudget(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const budget = diagnostics.sizeBudget;\n const lines = [\n ` ${colors.bold(\"Size budget\")} ${colors.dim(\n `(max ${formatBytes(budget.maxChunkSize)} · variables ${\n budget.isolateVariables ? \"isolated\" : \"inline\"\n })`,\n )}`,\n ];\n\n const chunks = diagnostics.emittedCssChunks;\n\n if (chunks.length === 0) {\n lines.push(` ${colors.dim(\"No CSS chunks were emitted.\")}`);\n return lines;\n }\n\n for (const chunk of chunks) {\n const markers: string[] = [];\n\n if (chunk.variables) {\n markers.push(\"vars\");\n }\n\n if (chunk.part !== undefined) {\n markers.push(`part ${chunk.part}`);\n }\n\n if (chunk.embedded) {\n markers.push(\"embedded\");\n }\n\n if (chunk.splitDueToSize) {\n markers.push(colors.yellow(\"split\"));\n }\n\n if (chunk.oversized) {\n markers.push(colors.red(\"oversized\"));\n }\n\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}${markers.length > 0 ? ` ${colors.dim(\"·\")} ${markers.join(\" · \")}` : \"\"}`,\n );\n }\n\n if (budget.splitChunks === 0) {\n lines.push(\n ` ${colors.dim(\"No chunk exceeded the configured size budget.\")}`,\n );\n }\n\n return lines;\n}\n\nfunction formatWarning(\n warning: CssAssetWarning,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n const location =\n warning.line !== undefined\n ? colors.dim(\n `${warning.line}${\n warning.column !== undefined ? `:${warning.column}` : \"\"\n } `,\n )\n : \"\";\n\n return `${colors.yellow(\"!\")} ${location}${warning.message}`;\n}\n\nfunction colorCoverage(\n coverage: string,\n ratio: number,\n minPageRatio: number,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (ratio === 0) {\n return colors.red(coverage);\n }\n\n return ratio >= minPageRatio\n ? colors.green(coverage)\n : colors.yellow(coverage);\n}\n\nfunction formatChunk(\n chunk: string,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (chunk === \"common\") {\n return colors.cyan(chunk);\n }\n\n if (chunk === \"dead\") {\n return colors.red(chunk);\n }\n\n return colors.magenta(chunk);\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength\n ? value\n : `${value.slice(0, maxLength - 1)}…`;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (!Number.isFinite(milliseconds)) {\n return \"—\";\n }\n\n return milliseconds < 1\n ? `${milliseconds.toFixed(2)} ms`\n : `${milliseconds.toFixed(1)} ms`;\n}\n"],"mappings":"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","names":["picocolors","formatBytes","page"]}
|
package/dist/index.js
CHANGED
|
@@ -226,18 +226,25 @@ function cssDoctor(options = {}) {
|
|
|
226
226
|
isolateVariables: options.sizeBudget?.isolateVariables ?? true
|
|
227
227
|
};
|
|
228
228
|
const report = options.report ?? true;
|
|
229
|
-
const
|
|
230
|
-
const
|
|
229
|
+
const configuredMinPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;
|
|
230
|
+
const configuredMaxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;
|
|
231
|
+
const configurationWarnings = [];
|
|
232
|
+
const minPageRatio = Number.isFinite(configuredMinPageRatio) && configuredMinPageRatio >= 0 && configuredMinPageRatio <= 1 ? configuredMinPageRatio : DEFAULT_MIN_PAGE_RATIO;
|
|
233
|
+
const maxChunkSize = Number.isFinite(configuredMaxChunkSize) && Number.isInteger(configuredMaxChunkSize) && configuredMaxChunkSize > 0 ? configuredMaxChunkSize : DEFAULT_MAX_CHUNK_SIZE;
|
|
231
234
|
let base = "/";
|
|
232
235
|
let minify = options.minify ?? true;
|
|
233
|
-
if (
|
|
234
|
-
|
|
235
|
-
"
|
|
236
|
+
if (minPageRatio !== configuredMinPageRatio) {
|
|
237
|
+
configurationWarnings.push(
|
|
238
|
+
"minPageRatio must be a number between 0 and 1; using 0.5"
|
|
236
239
|
);
|
|
237
240
|
}
|
|
238
|
-
if (
|
|
239
|
-
|
|
241
|
+
if (maxChunkSize !== configuredMaxChunkSize) {
|
|
242
|
+
configurationWarnings.push(
|
|
243
|
+
"maxChunkSize must be a positive integer; using 61440"
|
|
244
|
+
);
|
|
240
245
|
}
|
|
246
|
+
pageCoverage.minPageRatio = minPageRatio;
|
|
247
|
+
sizeBudget.maxChunkSize = maxChunkSize;
|
|
241
248
|
const filter = createFilter(options.include, options.exclude, {
|
|
242
249
|
resolve: false
|
|
243
250
|
});
|
|
@@ -283,6 +290,10 @@ function cssDoctor(options = {}) {
|
|
|
283
290
|
wrapCommonImports: options.wrapCommonImports ?? false
|
|
284
291
|
}
|
|
285
292
|
);
|
|
293
|
+
for (const warning of configurationWarnings) {
|
|
294
|
+
this.warn(`[css-doctor] ${warning}`);
|
|
295
|
+
diagnostics.errors.push(warning);
|
|
296
|
+
}
|
|
286
297
|
if (options.onDiagnostics) {
|
|
287
298
|
try {
|
|
288
299
|
await options.onDiagnostics(diagnostics);
|
|
@@ -325,7 +336,8 @@ async function analyzeAndSplit(bundle, environment, options) {
|
|
|
325
336
|
pageUsage[page.name] = classes;
|
|
326
337
|
pageUsageCounts[page.name] = classes.length;
|
|
327
338
|
}
|
|
328
|
-
const
|
|
339
|
+
const hasPageClasses = pages.some((page) => page.classes.size > 0);
|
|
340
|
+
const splitApplied = options.pageCoverage.enabled && hasPageClasses;
|
|
329
341
|
const diagnostics = {
|
|
330
342
|
plugin: "vite-plugin-css-doctor",
|
|
331
343
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -400,7 +412,7 @@ async function analyzeAndSplit(bundle, environment, options) {
|
|
|
400
412
|
cssContent: originalContent,
|
|
401
413
|
pageUsage,
|
|
402
414
|
pageCoverage: {
|
|
403
|
-
enabled:
|
|
415
|
+
enabled: splitApplied,
|
|
404
416
|
minPageRatio: options.pageCoverage.minPageRatio,
|
|
405
417
|
forceCommon: options.pageCoverage.forceCommon
|
|
406
418
|
},
|
|
@@ -799,13 +811,22 @@ function scanClasses(source, classes) {
|
|
|
799
811
|
continue;
|
|
800
812
|
}
|
|
801
813
|
for (const token of value.split(/\s+/)) {
|
|
802
|
-
if (
|
|
814
|
+
if (isClassToken(token)) {
|
|
803
815
|
classes.add(token.toLowerCase());
|
|
804
816
|
}
|
|
805
817
|
}
|
|
806
818
|
}
|
|
807
819
|
}
|
|
808
820
|
}
|
|
821
|
+
function isClassToken(token) {
|
|
822
|
+
if (!token || token.length > 256) {
|
|
823
|
+
return false;
|
|
824
|
+
}
|
|
825
|
+
if (/[`${}]/.test(token)) {
|
|
826
|
+
return false;
|
|
827
|
+
}
|
|
828
|
+
return /[A-Za-z_]/.test(token);
|
|
829
|
+
}
|
|
809
830
|
function isInternalPageEntry(chunk) {
|
|
810
831
|
const name = pageNameFor(chunk);
|
|
811
832
|
return name.startsWith("_") || name.startsWith("noop-") || name.includes("@astro-renderers");
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/reporter.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { createFilter } from \"@rollup/pluginutils\";\nimport { analyzeCss, optimizeCss } from \"@zealakit/css-doctor-binding\";\nimport type {\n JsCssAnalysisResult,\n JsSelectorStat,\n} from \"@zealakit/css-doctor-binding\";\nimport type { Plugin } from \"vite\";\n\nimport { printDiagnostics } from \"./reporter\";\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetOptions,\n} from \"./types\";\n\nconst DEFAULT_MIN_PAGE_RATIO = 0.5;\nconst DEFAULT_MAX_CHUNK_SIZE = 60 * 1_024;\nconst LARGE_CSS_ASSET_BYTES = 500 * 1_024;\n\ntype CssAssetLike = {\n type: \"asset\";\n fileName: string;\n source: string | Uint8Array;\n};\n\ntype ViteChunkLike = {\n type: \"chunk\";\n fileName: string;\n name: string;\n isEntry: boolean;\n facadeModuleId: string | null;\n code: string;\n modules: Record<string, unknown>;\n imports: string[];\n dynamicImports: string[];\n viteMetadata?: {\n importedCss?: Set<string>;\n };\n};\n\ntype PageInfo = {\n name: string;\n classes: Set<string>;\n cssFiles: Set<string>;\n chunkFile: string | null;\n};\n\ntype EmitAsset = {\n type: \"asset\";\n name?: string;\n fileName?: string;\n source: string | Uint8Array;\n};\n\ntype AnalysisEnvironment = {\n getModuleInfo: (id: string) => { code?: string | null } | null;\n emitFile: (asset: EmitAsset) => string;\n getFileName: (referenceId: string) => string;\n};\n\n/**\n * Creates a Vite plugin that splits emitted CSS by page coverage and removes\n * selectors that no scanned page uses.\n *\n * The plugin is read-only with respect to existing assets except for replacing\n * their contents with the common chunk. New page-specific files are emitted\n * with `this.emitFile`. Read, parse, split and callback failures are contained\n * so the user's build is never interrupted.\n */\nexport function cssDoctor(options: CssDoctorViteOptions = {}): Plugin {\n const pageCoverage: PageCoverageOptions = {\n enabled: options.pageCoverage?.enabled ?? true,\n minPageRatio:\n options.pageCoverage?.minPageRatio ??\n options.minPageRatio ??\n DEFAULT_MIN_PAGE_RATIO,\n forceCommon:\n options.pageCoverage?.forceCommon ?? options.forceCommonSelectors ?? [],\n };\n const sizeBudget: SizeBudgetOptions = {\n enabled: options.sizeBudget?.enabled ?? true,\n maxChunkSize: options.sizeBudget?.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE,\n isolateVariables: options.sizeBudget?.isolateVariables ?? true,\n };\n const report = options.report ?? true;\n const minPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;\n const maxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;\n let base = \"/\";\n let minify = options.minify ?? true;\n\n if (!Number.isFinite(minPageRatio) || minPageRatio < 0 || minPageRatio > 1) {\n throw new RangeError(\n \"css-doctor: minPageRatio must be a number between 0 and 1\",\n );\n }\n\n if (\n !Number.isFinite(maxChunkSize) ||\n !Number.isInteger(maxChunkSize) ||\n maxChunkSize <= 0\n ) {\n throw new RangeError(\"css-doctor: maxChunkSize must be a positive integer\");\n }\n\n const filter = createFilter(options.include, options.exclude, {\n resolve: false,\n });\n\n return {\n name: \"vite-plugin-css-doctor\",\n apply: \"build\",\n enforce: \"post\",\n\n config(config) {\n if (options.minify === false) {\n config.build ??= {};\n config.build.cssMinify = false;\n }\n },\n\n configResolved(config) {\n base = config.base;\n minify =\n options.minify ??\n (config.mode === \"production\" || config.command === \"build\");\n },\n\n async generateBundle(_outputOptions, bundle) {\n try {\n const diagnostics = await analyzeAndSplit(\n bundle,\n {\n getModuleInfo: (id) => this.getModuleInfo(id),\n emitFile: (asset) => this.emitFile(asset),\n getFileName: (referenceId) => this.getFileName(referenceId),\n },\n {\n filter,\n pageCoverage: {\n enabled: pageCoverage.enabled ?? true,\n minPageRatio,\n forceCommon: pageCoverage.forceCommon ?? [],\n },\n sizeBudget: {\n enabled: sizeBudget.enabled ?? true,\n maxChunkSize,\n isolateVariables: sizeBudget.isolateVariables ?? true,\n },\n directPageUsage: options.pageUsage,\n base,\n minify,\n skipVueScopedStyles: options.skipVueScopedStyles ?? false,\n wrapCommonImports: options.wrapCommonImports ?? false,\n },\n );\n\n if (options.onDiagnostics) {\n try {\n await options.onDiagnostics(diagnostics);\n } catch (error) {\n const message = `onDiagnostics callback failed: ${describeError(error)}`;\n diagnostics.errors.push(message);\n this.warn(`[css-doctor] ${message}`);\n }\n }\n\n if (\n report &&\n (diagnostics.totalCssAssets > 0 || diagnostics.errors.length > 0)\n ) {\n printDiagnostics(diagnostics);\n }\n } catch (error) {\n this.warn(\n `[css-doctor] diagnostics failed without interrupting the build: ${describeError(error)}`,\n );\n }\n },\n };\n}\n\ntype SplitOptions = {\n filter: (id: string) => boolean;\n pageCoverage: Required<PageCoverageOptions> & { forceCommon: string[] };\n sizeBudget: Required<SizeBudgetOptions>;\n directPageUsage: Record<string, string[]> | undefined;\n base: string;\n minify: boolean;\n skipVueScopedStyles: boolean;\n wrapCommonImports: boolean;\n};\n\nasync function analyzeAndSplit(\n bundle: Record<string, unknown>,\n environment: AnalysisEnvironment,\n options: SplitOptions,\n): Promise<CssDoctorDiagnostics> {\n const startedAt = performance.now();\n const { pages, pagesByCss } = await collectPages(\n bundle,\n environment.getModuleInfo,\n options.directPageUsage,\n );\n const pageNames = pages.map((page) => page.name);\n const pageNameSet = new Set(pageNames);\n const pageChunkFiles = new Map<string, string>();\n\n for (const page of pages) {\n if (page.chunkFile) {\n pageChunkFiles.set(page.name, page.chunkFile);\n }\n }\n const pageUsage: Record<string, string[]> = {};\n const pageUsageCounts: Record<string, number> = {};\n\n for (const page of pages) {\n const classes = [...page.classes].sort();\n pageUsage[page.name] = classes;\n pageUsageCounts[page.name] = classes.length;\n }\n\n const splitApplied = options.pageCoverage.enabled && pageNames.length > 0;\n const diagnostics: CssDoctorDiagnostics = {\n plugin: \"vite-plugin-css-doctor\",\n generatedAt: new Date().toISOString(),\n durationMs: 0,\n minPageRatio: options.pageCoverage.minPageRatio,\n minify: options.minify,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n splitChunks: 0,\n oversizedChunks: 0,\n },\n pages: pageNames,\n pageUsage: pageUsageCounts,\n splitApplied,\n totalCssAssets: 0,\n analyzedCssAssets: 0,\n skippedCssAssets: 0,\n failedCssAssets: 0,\n totalSizeBeforeBytes: 0,\n totalSizeAfterBytes: 0,\n totalSelectors: 0,\n totalRules: 0,\n commonCssBytes: 0,\n pageSpecificCssBytes: 0,\n emittedPageChunks: [],\n emittedCssChunks: [],\n usageMatrix: [],\n deadCodeCount: 0,\n files: [],\n errors: [],\n };\n\n const matrix = new Map<string, JsSelectorStat>();\n const htmlLinks: string[] = [];\n const commonFileNames: string[] = [];\n const pageCssFiles = new Map<string, string[]>();\n\n for (const output of Object.values(bundle)) {\n if (!isCssAsset(output)) {\n continue;\n }\n\n diagnostics.totalCssAssets += 1;\n\n if (!options.filter(output.fileName)) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (isCssModuleAsset(output.fileName, sourceToCss(output.source))) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (\n options.skipVueScopedStyles &&\n isVueScopedAsset(sourceToCss(output.source))\n ) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n const associatedPages = [\n ...(pagesByCss.get(output.fileName) ?? pageNameSet),\n ].sort();\n\n const file = analyzeAsset(output, associatedPages);\n\n if (file.error) {\n diagnostics.failedCssAssets += 1;\n diagnostics.errors.push(`${file.fileName}: ${file.error}`);\n diagnostics.files.push(file);\n continue;\n }\n\n const originalContent = sourceToCss(output.source);\n\n try {\n const pipeline = optimizeCss({\n cssContent: originalContent,\n pageUsage,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n forceCommon: options.pageCoverage.forceCommon,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n },\n minify: options.minify,\n });\n\n const commonChunks = pipeline.chunks.filter(\n (chunk) => chunk.page === undefined && chunk.sourceChunk === \"common\",\n );\n const pageChunks = pipeline.chunks.filter(\n (chunk) => chunk.page !== undefined,\n );\n const commonWasSplit =\n commonChunks.length > 1 ||\n commonChunks.some((chunk) => chunk.splitDueToSize);\n const embeddedCommon = commonWasSplit ? undefined : commonChunks[0];\n\n output.source = embeddedCommon?.css ?? \"\";\n file.sizeAfterBytes = Buffer.byteLength(output.source, \"utf8\");\n\n let commonSizeBytes = 0;\n let pageSpecificSizeBytes = 0;\n\n for (const chunk of commonChunks) {\n const embedded = chunk === embeddedCommon;\n const fileName = embedded\n ? output.fileName\n : emitCssAsset(environment, `${chunk.name}.css`, chunk.css);\n commonSizeBytes += chunk.sizeBytes;\n\n if (!embedded) {\n htmlLinks.push(fileName);\n commonFileNames.push(fileName);\n }\n\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page: chunk.page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n if (options.wrapCommonImports && commonWasSplit) {\n output.source = commonFileNames\n .map((fileName) => `@import \"./${basename(fileName)}\";`)\n .join(\"\\n\");\n }\n\n for (const chunk of pageChunks) {\n const page = chunk.page;\n\n if (!page) {\n continue;\n }\n\n const fileName = emitCssAsset(\n environment,\n `${chunk.name}.css`,\n chunk.css,\n );\n pageSpecificSizeBytes += chunk.sizeBytes;\n const files = pageCssFiles.get(page) ?? [];\n files.push(fileName);\n pageCssFiles.set(page, files);\n\n const emittedPage: EmittedPageChunk = {\n page,\n fileName,\n sizeBytes: chunk.sizeBytes,\n };\n\n diagnostics.emittedPageChunks.push(emittedPage);\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded: false,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n file.sizeAfterBytes = commonWasSplit\n ? commonSizeBytes\n : Buffer.byteLength(output.source, \"utf8\");\n file.split = {\n associatedPages,\n commonSizeBytes,\n pageSpecificSizeBytes,\n deadCodeCount: pipeline.deadCodeCount,\n };\n\n for (const stat of pipeline.stats) {\n const previous = matrix.get(stat.selector);\n\n if (!previous || stat.totalOccurrences > previous.totalOccurrences) {\n matrix.set(stat.selector, stat);\n }\n }\n\n diagnostics.deadCodeCount += pipeline.deadCodeCount;\n diagnostics.commonCssBytes += commonSizeBytes;\n diagnostics.pageSpecificCssBytes += pageSpecificSizeBytes;\n } catch (error) {\n diagnostics.errors.push(\n `${file.fileName}: failed to optimize CSS: ${describeError(error)}`,\n );\n }\n\n diagnostics.analyzedCssAssets += 1;\n diagnostics.totalSizeBeforeBytes += file.sizeBeforeBytes;\n diagnostics.totalSizeAfterBytes += file.sizeAfterBytes;\n diagnostics.totalSelectors += file.selectorCount;\n diagnostics.totalRules += file.ruleCount;\n diagnostics.files.push(file);\n }\n\n if (htmlLinks.length > 0) {\n injectStylesheetLinks(bundle, htmlLinks, options.base);\n }\n\n if (pageCssFiles.size > 0) {\n injectPageChunkStyles(bundle, pageCssFiles, pageChunkFiles, options.base);\n }\n\n diagnostics.usageMatrix = [...matrix.values()].sort((left, right) =>\n left.selector.localeCompare(right.selector),\n );\n diagnostics.durationMs = roundMs(performance.now() - startedAt);\n\n return diagnostics;\n}\n\nfunction emitCssAsset(\n environment: AnalysisEnvironment,\n name: string,\n source: string,\n): string {\n const referenceId = environment.emitFile({\n type: \"asset\",\n name,\n source,\n });\n\n return environment.getFileName(referenceId);\n}\n\nfunction injectPageChunkStyles(\n bundle: Record<string, unknown>,\n cssByPage: Map<string, string[]>,\n chunkByPage: Map<string, string>,\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n\n for (const [page, fileNames] of cssByPage) {\n if (fileNames.length === 0) {\n continue;\n }\n\n const chunkFile = chunkByPage.get(page);\n const hrefs = fileNames.map((fileName) => `${normalizedBase}${fileName}`);\n const htmlOutput = findPageHtmlAsset(bundle, page);\n const output = htmlOutput ?? (chunkFile ? bundle[chunkFile] : undefined);\n\n if (isHtmlAsset(output)) {\n const tags = hrefs\n .map(\n (href) =>\n ` <link rel=\"stylesheet\" href=\"${href}\" data-css-doctor-page>`,\n )\n .join(\"\\n\");\n\n if (!output.source.includes(tags) && output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n continue;\n }\n\n if (!isChunk(output)) {\n continue;\n }\n\n const snippet = `(()=>{const __cssDoctorPageStyles=${JSON.stringify(hrefs)};if(typeof document!==\"undefined\"){for(const __cssDoctorPageHref of __cssDoctorPageStyles){if(!Array.from(document.querySelectorAll(\"link[data-css-doctor-page]\")).some((link)=>link.dataset.cssDoctorPage===__cssDoctorPageHref)){const __cssDoctorPageLink=document.createElement(\"link\");__cssDoctorPageLink.rel=\"stylesheet\";__cssDoctorPageLink.href=__cssDoctorPageHref;__cssDoctorPageLink.dataset.cssDoctorPage=__cssDoctorPageHref;document.head.append(__cssDoctorPageLink);}}}})();\\n`;\n\n output.code = snippet + output.code;\n }\n}\n\nfunction injectStylesheetLinks(\n bundle: Record<string, unknown>,\n fileNames: string[],\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const tags = fileNames\n .map(\n (fileName) =>\n ` <link rel=\"stylesheet\" href=\"${normalizedBase}${fileName}\">`,\n )\n .join(\"\\n\");\n\n for (const output of Object.values(bundle)) {\n if (!isHtmlAsset(output) || output.source.includes(tags)) {\n continue;\n }\n\n if (output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n }\n}\n\nfunction findPageHtmlAsset(\n bundle: Record<string, unknown>,\n page: string,\n): unknown {\n const names =\n page === \"index\"\n ? [\"index.html\"]\n : [\n `page-${page}/index.html`,\n `page-${page}.html`,\n `${page}/index.html`,\n `${page}.html`,\n ];\n\n for (const name of names) {\n const output = bundle[name];\n\n if (isHtmlAsset(output)) {\n return output;\n }\n }\n\n return undefined;\n}\n\nfunction isHtmlAsset(\n value: unknown,\n): value is { type: \"asset\"; fileName: string; source: string } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".html\") &&\n typeof candidate.source === \"string\"\n );\n}\n\nfunction analyzeAsset(\n output: CssAssetLike,\n associatedPages: string[],\n): CssAssetDiagnostic {\n const analysisStartedAt = performance.now();\n\n try {\n const css = sourceToCss(output.source);\n const sizeBeforeBytes = Buffer.byteLength(css, \"utf8\");\n const analysis = analyzeCss(css);\n const warnings = collectSyntaxWarnings(analysis);\n\n if (sizeBeforeBytes >= LARGE_CSS_ASSET_BYTES) {\n warnings.push({\n kind: \"large-asset\",\n message:\n `CSS asset is larger than ${formatBytes(LARGE_CSS_ASSET_BYTES)}; ` +\n \"consider route-level code splitting.\",\n });\n }\n\n return {\n fileName: output.fileName,\n sizeBeforeBytes,\n sizeAfterBytes: sizeBeforeBytes,\n selectorCount: analysis.stats.selectorCount,\n ruleCount: analysis.stats.ruleCount,\n declarationCount: analysis.stats.declarationCount,\n importantDeclarationCount: analysis.stats.importantDeclarationCount,\n uniqueClassCount: analysis.stats.uniqueClassCount,\n uniqueIdCount: analysis.stats.uniqueIdCount,\n uniqueTagCount: analysis.stats.uniqueTagCount,\n syntaxWarningCount: analysis.warnings.length,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings,\n analysis,\n };\n } catch (error) {\n return {\n fileName: output.fileName,\n sizeBeforeBytes: 0,\n sizeAfterBytes: 0,\n selectorCount: 0,\n ruleCount: 0,\n declarationCount: 0,\n importantDeclarationCount: 0,\n uniqueClassCount: 0,\n uniqueIdCount: 0,\n uniqueTagCount: 0,\n syntaxWarningCount: 0,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings: [],\n error: describeError(error),\n };\n }\n}\n\nasync function collectPages(\n bundle: Record<string, unknown>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n directPageUsage: Record<string, string[]> | undefined,\n): Promise<{\n pages: PageInfo[];\n pagesByCss: Map<string, Set<string>>;\n}> {\n const chunks = Object.values(bundle).filter(isChunk);\n const chunksByFileName = new Map(\n chunks.map((chunk) => [chunk.fileName, chunk]),\n );\n const pages = new Map<string, PageInfo>();\n const entryFileNames = new Set(\n chunks.filter((chunk) => chunk.isEntry).map((chunk) => chunk.fileName),\n );\n\n for (const entry of chunks.filter((chunk) => chunk.isEntry)) {\n if (isInternalPageEntry(entry)) {\n continue;\n }\n\n const shell = collectChunkContent(\n entry,\n chunksByFileName,\n getModuleInfo,\n false,\n );\n\n if (entry.facadeModuleId && isHtmlFile(entry.facadeModuleId)) {\n try {\n scanClasses(\n await readFile(entry.facadeModuleId, \"utf8\"),\n shell.classes,\n );\n } catch {\n // The HTML source may be virtual or removed by another plugin. The\n // generated chunk code and pageUsage option still provide coverage.\n }\n }\n\n const routeChunks = entry.dynamicImports\n .map((fileName) => chunksByFileName.get(fileName))\n .filter((chunk): chunk is ViteChunkLike => chunk !== undefined);\n\n if (routeChunks.length > 0) {\n // A SPA shell usually owns the HTML, navigation and global CSS, while\n // every direct dynamic import is a route. Treat those chunks as pages\n // and apply the shell classes/CSS to each one, instead of collapsing all\n // routes into the single index entry.\n for (const routeChunk of routeChunks) {\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(routePageName(routeChunk)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: routeChunk.fileName,\n };\n const route = collectChunkContent(\n routeChunk,\n chunksByFileName,\n getModuleInfo,\n true,\n entryFileNames,\n );\n\n for (const className of route.classes) {\n page.classes.add(className);\n }\n\n for (const cssFile of route.cssFiles) {\n page.cssFiles.add(cssFile);\n }\n\n pages.set(page.name, page);\n }\n\n continue;\n }\n\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(pageNameFor(entry)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: entry.fileName,\n };\n\n pages.set(page.name, page);\n }\n\n if (directPageUsage) {\n for (const [rawName, classes] of Object.entries(directPageUsage)) {\n const name = rawName.trim();\n\n if (name.length === 0) {\n continue;\n }\n\n let page = pages.get(name);\n\n if (!page) {\n page = {\n name,\n classes: new Set(),\n cssFiles: new Set(),\n chunkFile: null,\n };\n pages.set(name, page);\n }\n\n for (const className of classes) {\n page.classes.add(className.toLowerCase());\n }\n }\n }\n\n const pagesByCss = new Map<string, Set<string>>();\n\n for (const page of pages.values()) {\n for (const cssFile of page.cssFiles) {\n const owners = pagesByCss.get(cssFile) ?? new Set<string>();\n owners.add(page.name);\n pagesByCss.set(cssFile, owners);\n }\n }\n\n return {\n pages: [...pages.values()],\n pagesByCss,\n };\n}\n\nfunction collectChunkContent(\n startChunk: ViteChunkLike,\n chunksByFileName: Map<string, ViteChunkLike>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n includeDynamicImports: boolean,\n skipFileNames: ReadonlySet<string> = new Set<string>(),\n): {\n classes: Set<string>;\n cssFiles: Set<string>;\n} {\n const classes = new Set<string>();\n const cssFiles = new Set<string>();\n const visited = new Set<string>();\n const stack = [startChunk.fileName];\n\n while (stack.length > 0) {\n const fileName = stack.pop();\n\n if (!fileName || visited.has(fileName) || skipFileNames.has(fileName)) {\n continue;\n }\n\n visited.add(fileName);\n\n const chunk = chunksByFileName.get(fileName);\n\n if (!chunk) {\n continue;\n }\n\n scanClasses(chunk.code, classes);\n\n for (const moduleId of Object.keys(chunk.modules)) {\n if (isStyleModule(moduleId)) {\n continue;\n }\n\n const moduleInfo = getModuleInfo(moduleId);\n\n if (moduleInfo?.code) {\n scanClasses(moduleInfo.code, classes);\n }\n }\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n cssFiles.add(cssFile);\n }\n\n stack.push(...chunk.imports);\n\n if (includeDynamicImports) {\n stack.push(...chunk.dynamicImports);\n }\n }\n\n return { classes, cssFiles };\n}\n\nfunction scanClasses(source: string, classes: Set<string>): void {\n const patterns = [\n /(?:class|className)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /(?:^|[,{;\\s])(?:class|className)\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /classList\\.(?:add|remove|toggle|contains)\\(\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n ];\n\n for (const pattern of patterns) {\n for (const match of source.matchAll(pattern)) {\n const value = match[1] ?? match[2] ?? match[3];\n\n if (!value) {\n continue;\n }\n\n for (const token of value.split(/\\s+/)) {\n if (/^-?[_a-zA-Z][\\w-]*$/.test(token)) {\n classes.add(token.toLowerCase());\n }\n }\n }\n }\n}\n\nfunction isInternalPageEntry(chunk: ViteChunkLike): boolean {\n const name = pageNameFor(chunk);\n\n return (\n name.startsWith(\"_\") ||\n name.startsWith(\"noop-\") ||\n name.includes(\"@astro-renderers\")\n );\n}\n\nfunction cleanPageName(name: string): string {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/@_@[a-z]+$/i, \"\")\n .replace(/^page-/, \"\");\n\n return normalized || \"page\";\n}\n\nfunction routePageName(chunk: ViteChunkLike): string {\n const name = pageNameFor(chunk).toLowerCase();\n\n return name.startsWith(\"page-\") ? name.slice(\"page-\".length) : name;\n}\n\nfunction isCssModuleAsset(fileName: string, css: string): boolean {\n if (/\\.module\\.(css|scss|sass|less|styl|stylus)$/i.test(fileName)) {\n return true;\n }\n\n // Vite's default CSS Modules local identifier is `_local_hash_index`\n // (for example `_card_1udun_1`). The emitted asset name is hashed, so\n // detect the scoped class shape in the source as a safety boundary.\n return /\\.[A-Za-z0-9_-]+_[A-Za-z0-9]{5,}_[0-9]+/.test(css);\n}\n\nfunction isVueScopedAsset(css: string): boolean {\n return /\\[data-v-[0-9a-f]+\\]/.test(css);\n}\n\nfunction pageNameFor(chunk: ViteChunkLike): string {\n if (chunk.name.length > 0) {\n return chunk.name;\n }\n\n if (chunk.facadeModuleId) {\n return basename(chunk.facadeModuleId, extname(chunk.facadeModuleId));\n }\n\n return chunk.fileName.replace(/\\.[^.]+$/, \"\");\n}\n\nfunction uniquePageName(base: string, pages: Map<string, PageInfo>): string {\n const normalized = base.trim() || \"page\";\n\n if (!pages.has(normalized)) {\n return normalized;\n }\n\n let index = 2;\n\n while (pages.has(`${normalized}-${index}`)) {\n index += 1;\n }\n\n return `${normalized}-${index}`;\n}\n\nfunction isCssAsset(value: unknown): value is CssAssetLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".css\") &&\n (typeof candidate.source === \"string\" ||\n candidate.source instanceof Uint8Array)\n );\n}\n\nfunction isChunk(value: unknown): value is ViteChunkLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n name?: unknown;\n isEntry?: unknown;\n facadeModuleId?: unknown;\n code?: unknown;\n modules?: unknown;\n imports?: unknown;\n dynamicImports?: unknown;\n };\n\n return (\n candidate.type === \"chunk\" &&\n typeof candidate.fileName === \"string\" &&\n typeof candidate.name === \"string\" &&\n typeof candidate.isEntry === \"boolean\" &&\n typeof candidate.code === \"string\" &&\n typeof candidate.modules === \"object\" &&\n candidate.modules !== null &&\n Array.isArray(candidate.imports) &&\n Array.isArray(candidate.dynamicImports)\n );\n}\n\nfunction isStyleModule(moduleId: string): boolean {\n return /\\.(css|scss|sass|less|styl|stylus)(\\?|$)/i.test(moduleId);\n}\n\nfunction isHtmlFile(moduleId: string): boolean {\n return /\\.(html?|vue)$/i.test(moduleId);\n}\n\nfunction collectSyntaxWarnings(\n analysis: JsCssAnalysisResult,\n): CssAssetWarning[] {\n return analysis.warnings.map((warning) => ({\n kind: \"syntax\",\n message: warning.message,\n ...(warning.location\n ? {\n line: warning.location.line,\n column: warning.location.column,\n }\n : {}),\n }));\n}\n\nfunction sourceToCss(source: string | Uint8Array): string {\n return typeof source === \"string\"\n ? source\n : Buffer.from(source).toString(\"utf8\");\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction roundMs(value: number): number {\n return Math.round(value * 1_000) / 1_000;\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import picocolors from \"picocolors\";\n\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n} from \"./types\";\n\nconst MATRIX_SELECTOR_MAX = 36;\n\n/** Options for terminal rendering. Defaults to picocolors' TTY detection. */\nexport type ReporterOptions = {\n color?: boolean;\n};\n\n/** Formats diagnostics as a human-readable build report. */\nexport function formatDiagnostics(\n diagnostics: CssDoctorDiagnostics,\n options: ReporterOptions = {},\n): string {\n const colors = picocolors.createColors(\n options.color ?? picocolors.isColorSupported,\n );\n const badge = colors.bgCyan(colors.black(\"[css-doctor]\"));\n const lines: string[] = [];\n\n lines.push(\n `${badge} ${diagnostics.pages.length} page${\n diagnostics.pages.length === 1 ? \"\" : \"s\"\n } ${colors.dim(\"·\")} ${diagnostics.analyzedCssAssets}/${\n diagnostics.totalCssAssets\n } CSS assets ${colors.dim(\"·\")} ${formatBytes(\n diagnostics.totalSizeBeforeBytes,\n )} → ${formatBytes(diagnostics.totalSizeAfterBytes)} common ` +\n `${colors.dim(\"·\")} ${formatDuration(diagnostics.durationMs)}` +\n (diagnostics.skippedCssAssets > 0\n ? ` ${colors.dim(`· ${diagnostics.skippedCssAssets} skipped`)}`\n : \"\") +\n ` ${colors.dim(\"·\")} ${\n diagnostics.minify\n ? colors.green(\"Minified: YES\")\n : colors.yellow(\"Minified: NO\")\n }`,\n );\n\n for (const file of diagnostics.files) {\n lines.push(...formatFile(file, colors));\n }\n\n if (diagnostics.splitApplied) {\n lines.push(\"\");\n lines.push(...formatMatrix(diagnostics, colors));\n }\n\n if (diagnostics.emittedPageChunks.length > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.bold(\"Emitted page chunks\")} ${colors.dim(\n `(${diagnostics.emittedPageChunks.length})`,\n )}`,\n );\n\n for (const chunk of diagnostics.emittedPageChunks) {\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}`,\n );\n }\n }\n\n if (diagnostics.sizeBudget.enabled) {\n lines.push(\"\");\n lines.push(...formatSizeBudget(diagnostics, colors));\n }\n\n if (diagnostics.deadCodeCount > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.yellow(\"⚠\")} ${colors.bold(\"Dead code eliminated:\")} ` +\n `${diagnostics.deadCodeCount} selector occurrence${\n diagnostics.deadCodeCount === 1 ? \"\" : \"s\"\n }`,\n );\n }\n\n if (diagnostics.errors.length > 0) {\n lines.push(\"\");\n lines.push(` ${colors.red(colors.bold(\"Errors\"))}`);\n\n for (const error of diagnostics.errors) {\n lines.push(` ${colors.red(\"✖\")} ${error}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Prints diagnostics to stdout. */\nexport function printDiagnostics(diagnostics: CssDoctorDiagnostics): void {\n console.log(formatDiagnostics(diagnostics));\n}\n\nfunction formatFile(\n file: CssAssetDiagnostic,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const failed = file.error !== undefined;\n const hasWarnings = file.warnings.length > 0;\n const icon = failed\n ? colors.red(\"✖\")\n : hasWarnings\n ? colors.yellow(\"⚠\")\n : colors.green(\"✓\");\n\n const size = `${formatBytes(file.sizeBeforeBytes)} → ${formatBytes(\n file.sizeAfterBytes,\n )}`;\n const selectors = failed ? \"\" : ` · ${file.selectorCount} selectors`;\n const pages =\n file.associatedPages.length > 0\n ? ` · pages: ${file.associatedPages.join(\", \")}`\n : \"\";\n\n const lines = [\n ` ${icon} ${colors.bold(file.fileName)} ${colors.dim(size)}${selectors}${colors.dim(pages)}`,\n ];\n\n if (file.error) {\n lines.push(` ${colors.red(file.error)}`);\n return lines;\n }\n\n if (file.split) {\n lines.push(\n ` ${colors.dim(\"split\")} common ${formatBytes(\n file.split.commonSizeBytes,\n )} ${colors.dim(\"·\")} page-specific ${formatBytes(\n file.split.pageSpecificSizeBytes,\n )} ${colors.dim(\"·\")} dead ${file.split.deadCodeCount}`,\n );\n }\n\n for (const warning of file.warnings) {\n lines.push(` ${formatWarning(warning, colors)}`);\n }\n\n return lines;\n}\n\nfunction formatMatrix(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const pageTotal = diagnostics.pages.length;\n const rows = diagnostics.usageMatrix;\n const header = [\n \"Selector\".padEnd(MATRIX_SELECTOR_MAX),\n \"Total Used\".padStart(10),\n \"Page Usage\".padStart(10),\n \"Coverage %\".padStart(10),\n \"Assigned Chunk\",\n ].join(\" \");\n\n const lines = [\n ` ${colors.bold(\"Usage Matrix\")} ${colors.dim(\n `(${rows.length} selectors · ${pageTotal} pages)`,\n )}`,\n ` ${colors.dim(header)}`,\n ];\n\n for (const row of rows) {\n const selector = truncate(row.selector, MATRIX_SELECTOR_MAX).padEnd(\n MATRIX_SELECTOR_MAX,\n );\n const totalUsed = String(row.totalOccurrences).padStart(10);\n const pageUsage = `${row.pageCount}/${pageTotal}`.padStart(10);\n const coverage = `${(row.coverageRatio * 100).toFixed(1)}%`.padStart(10);\n const chunk = formatChunk(row.targetChunk, colors);\n\n lines.push(\n ` ${colors.cyan(selector)} ${totalUsed} ${pageUsage} ${colorCoverage(\n coverage,\n row.coverageRatio,\n diagnostics.minPageRatio,\n colors,\n )} ${chunk}`,\n );\n }\n\n return lines;\n}\n\nfunction formatSizeBudget(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const budget = diagnostics.sizeBudget;\n const lines = [\n ` ${colors.bold(\"Size budget\")} ${colors.dim(\n `(max ${formatBytes(budget.maxChunkSize)} · variables ${\n budget.isolateVariables ? \"isolated\" : \"inline\"\n })`,\n )}`,\n ];\n\n const chunks = diagnostics.emittedCssChunks;\n\n if (chunks.length === 0) {\n lines.push(` ${colors.dim(\"No CSS chunks were emitted.\")}`);\n return lines;\n }\n\n for (const chunk of chunks) {\n const markers: string[] = [];\n\n if (chunk.variables) {\n markers.push(\"vars\");\n }\n\n if (chunk.part !== undefined) {\n markers.push(`part ${chunk.part}`);\n }\n\n if (chunk.embedded) {\n markers.push(\"embedded\");\n }\n\n if (chunk.splitDueToSize) {\n markers.push(colors.yellow(\"split\"));\n }\n\n if (chunk.oversized) {\n markers.push(colors.red(\"oversized\"));\n }\n\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}${markers.length > 0 ? ` ${colors.dim(\"·\")} ${markers.join(\" · \")}` : \"\"}`,\n );\n }\n\n if (budget.splitChunks === 0) {\n lines.push(\n ` ${colors.dim(\"No chunk exceeded the configured size budget.\")}`,\n );\n }\n\n return lines;\n}\n\nfunction formatWarning(\n warning: CssAssetWarning,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n const location =\n warning.line !== undefined\n ? colors.dim(\n `${warning.line}${\n warning.column !== undefined ? `:${warning.column}` : \"\"\n } `,\n )\n : \"\";\n\n return `${colors.yellow(\"!\")} ${location}${warning.message}`;\n}\n\nfunction colorCoverage(\n coverage: string,\n ratio: number,\n minPageRatio: number,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (ratio === 0) {\n return colors.red(coverage);\n }\n\n return ratio >= minPageRatio\n ? colors.green(coverage)\n : colors.yellow(coverage);\n}\n\nfunction formatChunk(\n chunk: string,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (chunk === \"common\") {\n return colors.cyan(chunk);\n }\n\n if (chunk === \"dead\") {\n return colors.red(chunk);\n }\n\n return colors.magenta(chunk);\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength\n ? value\n : `${value.slice(0, maxLength - 1)}…`;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (!Number.isFinite(milliseconds)) {\n return \"—\";\n }\n\n return milliseconds < 1\n ? `${milliseconds.toFixed(2)} ms`\n : `${milliseconds.toFixed(1)} ms`;\n}\n"],"mappings":"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","names":["formatBytes","page"]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/reporter.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { basename, extname } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\n\nimport { createFilter } from \"@rollup/pluginutils\";\nimport { analyzeCss, optimizeCss } from \"@zealakit/css-doctor-binding\";\nimport type {\n JsCssAnalysisResult,\n JsSelectorStat,\n} from \"@zealakit/css-doctor-binding\";\nimport type { Plugin } from \"vite\";\n\nimport { printDiagnostics } from \"./reporter\";\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n CssDoctorViteOptions,\n EmittedCssChunk,\n EmittedPageChunk,\n PageCoverageOptions,\n SizeBudgetOptions,\n} from \"./types\";\n\nconst DEFAULT_MIN_PAGE_RATIO = 0.5;\nconst DEFAULT_MAX_CHUNK_SIZE = 60 * 1_024;\nconst LARGE_CSS_ASSET_BYTES = 500 * 1_024;\n\ntype CssAssetLike = {\n type: \"asset\";\n fileName: string;\n source: string | Uint8Array;\n};\n\ntype ViteChunkLike = {\n type: \"chunk\";\n fileName: string;\n name: string;\n isEntry: boolean;\n facadeModuleId: string | null;\n code: string;\n modules: Record<string, unknown>;\n imports: string[];\n dynamicImports: string[];\n viteMetadata?: {\n importedCss?: Set<string>;\n };\n};\n\ntype PageInfo = {\n name: string;\n classes: Set<string>;\n cssFiles: Set<string>;\n chunkFile: string | null;\n};\n\ntype EmitAsset = {\n type: \"asset\";\n name?: string;\n fileName?: string;\n source: string | Uint8Array;\n};\n\ntype AnalysisEnvironment = {\n getModuleInfo: (id: string) => { code?: string | null } | null;\n emitFile: (asset: EmitAsset) => string;\n getFileName: (referenceId: string) => string;\n};\n\n/**\n * Creates a Vite plugin that splits emitted CSS by page coverage and removes\n * selectors that no scanned page uses.\n *\n * The plugin is read-only with respect to existing assets except for replacing\n * their contents with the common chunk. New page-specific files are emitted\n * with `this.emitFile`. Read, parse, split and callback failures are contained\n * so the user's build is never interrupted.\n */\nexport function cssDoctor(options: CssDoctorViteOptions = {}): Plugin {\n const pageCoverage: PageCoverageOptions = {\n enabled: options.pageCoverage?.enabled ?? true,\n minPageRatio:\n options.pageCoverage?.minPageRatio ??\n options.minPageRatio ??\n DEFAULT_MIN_PAGE_RATIO,\n forceCommon:\n options.pageCoverage?.forceCommon ?? options.forceCommonSelectors ?? [],\n };\n const sizeBudget: SizeBudgetOptions = {\n enabled: options.sizeBudget?.enabled ?? true,\n maxChunkSize: options.sizeBudget?.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE,\n isolateVariables: options.sizeBudget?.isolateVariables ?? true,\n };\n const report = options.report ?? true;\n const configuredMinPageRatio =\n pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;\n const configuredMaxChunkSize =\n sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;\n const configurationWarnings: string[] = [];\n const minPageRatio =\n Number.isFinite(configuredMinPageRatio) &&\n configuredMinPageRatio >= 0 &&\n configuredMinPageRatio <= 1\n ? configuredMinPageRatio\n : DEFAULT_MIN_PAGE_RATIO;\n const maxChunkSize =\n Number.isFinite(configuredMaxChunkSize) &&\n Number.isInteger(configuredMaxChunkSize) &&\n configuredMaxChunkSize > 0\n ? configuredMaxChunkSize\n : DEFAULT_MAX_CHUNK_SIZE;\n let base = \"/\";\n let minify = options.minify ?? true;\n\n if (minPageRatio !== configuredMinPageRatio) {\n configurationWarnings.push(\n \"minPageRatio must be a number between 0 and 1; using 0.5\",\n );\n }\n\n if (maxChunkSize !== configuredMaxChunkSize) {\n configurationWarnings.push(\n \"maxChunkSize must be a positive integer; using 61440\",\n );\n }\n\n // Keep resolved configs aligned with clamped values so optimizeCss never\n // receives invalid numbers from a bad factory configuration.\n pageCoverage.minPageRatio = minPageRatio;\n sizeBudget.maxChunkSize = maxChunkSize;\n\n const filter = createFilter(options.include, options.exclude, {\n resolve: false,\n });\n\n return {\n name: \"vite-plugin-css-doctor\",\n apply: \"build\",\n enforce: \"post\",\n\n config(config) {\n if (options.minify === false) {\n config.build ??= {};\n config.build.cssMinify = false;\n }\n },\n\n configResolved(config) {\n base = config.base;\n minify =\n options.minify ??\n (config.mode === \"production\" || config.command === \"build\");\n },\n\n async generateBundle(_outputOptions, bundle) {\n try {\n const diagnostics = await analyzeAndSplit(\n bundle,\n {\n getModuleInfo: (id) => this.getModuleInfo(id),\n emitFile: (asset) => this.emitFile(asset),\n getFileName: (referenceId) => this.getFileName(referenceId),\n },\n {\n filter,\n pageCoverage: {\n enabled: pageCoverage.enabled ?? true,\n minPageRatio,\n forceCommon: pageCoverage.forceCommon ?? [],\n },\n sizeBudget: {\n enabled: sizeBudget.enabled ?? true,\n maxChunkSize,\n isolateVariables: sizeBudget.isolateVariables ?? true,\n },\n directPageUsage: options.pageUsage,\n base,\n minify,\n skipVueScopedStyles: options.skipVueScopedStyles ?? false,\n wrapCommonImports: options.wrapCommonImports ?? false,\n },\n );\n\n for (const warning of configurationWarnings) {\n this.warn(`[css-doctor] ${warning}`);\n diagnostics.errors.push(warning);\n }\n\n if (options.onDiagnostics) {\n try {\n await options.onDiagnostics(diagnostics);\n } catch (error) {\n const message = `onDiagnostics callback failed: ${describeError(error)}`;\n diagnostics.errors.push(message);\n this.warn(`[css-doctor] ${message}`);\n }\n }\n\n if (\n report &&\n (diagnostics.totalCssAssets > 0 || diagnostics.errors.length > 0)\n ) {\n printDiagnostics(diagnostics);\n }\n } catch (error) {\n this.warn(\n `[css-doctor] diagnostics failed without interrupting the build: ${describeError(error)}`,\n );\n }\n },\n };\n}\n\ntype SplitOptions = {\n filter: (id: string) => boolean;\n pageCoverage: Required<PageCoverageOptions> & { forceCommon: string[] };\n sizeBudget: Required<SizeBudgetOptions>;\n directPageUsage: Record<string, string[]> | undefined;\n base: string;\n minify: boolean;\n skipVueScopedStyles: boolean;\n wrapCommonImports: boolean;\n};\n\nasync function analyzeAndSplit(\n bundle: Record<string, unknown>,\n environment: AnalysisEnvironment,\n options: SplitOptions,\n): Promise<CssDoctorDiagnostics> {\n const startedAt = performance.now();\n const { pages, pagesByCss } = await collectPages(\n bundle,\n environment.getModuleInfo,\n options.directPageUsage,\n );\n const pageNames = pages.map((page) => page.name);\n const pageNameSet = new Set(pageNames);\n const pageChunkFiles = new Map<string, string>();\n\n for (const page of pages) {\n if (page.chunkFile) {\n pageChunkFiles.set(page.name, page.chunkFile);\n }\n }\n const pageUsage: Record<string, string[]> = {};\n const pageUsageCounts: Record<string, number> = {};\n\n for (const page of pages) {\n const classes = [...page.classes].sort();\n pageUsage[page.name] = classes;\n pageUsageCounts[page.name] = classes.length;\n }\n\n const hasPageClasses = pages.some((page) => page.classes.size > 0);\n const splitApplied = options.pageCoverage.enabled && hasPageClasses;\n const diagnostics: CssDoctorDiagnostics = {\n plugin: \"vite-plugin-css-doctor\",\n generatedAt: new Date().toISOString(),\n durationMs: 0,\n minPageRatio: options.pageCoverage.minPageRatio,\n minify: options.minify,\n pageCoverage: {\n enabled: options.pageCoverage.enabled,\n minPageRatio: options.pageCoverage.minPageRatio,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n splitChunks: 0,\n oversizedChunks: 0,\n },\n pages: pageNames,\n pageUsage: pageUsageCounts,\n splitApplied,\n totalCssAssets: 0,\n analyzedCssAssets: 0,\n skippedCssAssets: 0,\n failedCssAssets: 0,\n totalSizeBeforeBytes: 0,\n totalSizeAfterBytes: 0,\n totalSelectors: 0,\n totalRules: 0,\n commonCssBytes: 0,\n pageSpecificCssBytes: 0,\n emittedPageChunks: [],\n emittedCssChunks: [],\n usageMatrix: [],\n deadCodeCount: 0,\n files: [],\n errors: [],\n };\n\n const matrix = new Map<string, JsSelectorStat>();\n const htmlLinks: string[] = [];\n const commonFileNames: string[] = [];\n const pageCssFiles = new Map<string, string[]>();\n\n for (const output of Object.values(bundle)) {\n if (!isCssAsset(output)) {\n continue;\n }\n\n diagnostics.totalCssAssets += 1;\n\n if (!options.filter(output.fileName)) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (isCssModuleAsset(output.fileName, sourceToCss(output.source))) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n if (\n options.skipVueScopedStyles &&\n isVueScopedAsset(sourceToCss(output.source))\n ) {\n diagnostics.skippedCssAssets += 1;\n continue;\n }\n\n const associatedPages = [\n ...(pagesByCss.get(output.fileName) ?? pageNameSet),\n ].sort();\n\n const file = analyzeAsset(output, associatedPages);\n\n if (file.error) {\n diagnostics.failedCssAssets += 1;\n diagnostics.errors.push(`${file.fileName}: ${file.error}`);\n diagnostics.files.push(file);\n continue;\n }\n\n const originalContent = sourceToCss(output.source);\n\n try {\n const pipeline = optimizeCss({\n cssContent: originalContent,\n pageUsage,\n pageCoverage: {\n enabled: splitApplied,\n minPageRatio: options.pageCoverage.minPageRatio,\n forceCommon: options.pageCoverage.forceCommon,\n },\n sizeBudget: {\n enabled: options.sizeBudget.enabled,\n maxChunkSize: options.sizeBudget.maxChunkSize,\n isolateVariables: options.sizeBudget.isolateVariables,\n },\n minify: options.minify,\n });\n\n const commonChunks = pipeline.chunks.filter(\n (chunk) => chunk.page === undefined && chunk.sourceChunk === \"common\",\n );\n const pageChunks = pipeline.chunks.filter(\n (chunk) => chunk.page !== undefined,\n );\n const commonWasSplit =\n commonChunks.length > 1 ||\n commonChunks.some((chunk) => chunk.splitDueToSize);\n const embeddedCommon = commonWasSplit ? undefined : commonChunks[0];\n\n output.source = embeddedCommon?.css ?? \"\";\n file.sizeAfterBytes = Buffer.byteLength(output.source, \"utf8\");\n\n let commonSizeBytes = 0;\n let pageSpecificSizeBytes = 0;\n\n for (const chunk of commonChunks) {\n const embedded = chunk === embeddedCommon;\n const fileName = embedded\n ? output.fileName\n : emitCssAsset(environment, `${chunk.name}.css`, chunk.css);\n commonSizeBytes += chunk.sizeBytes;\n\n if (!embedded) {\n htmlLinks.push(fileName);\n commonFileNames.push(fileName);\n }\n\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page: chunk.page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n if (options.wrapCommonImports && commonWasSplit) {\n output.source = commonFileNames\n .map((fileName) => `@import \"./${basename(fileName)}\";`)\n .join(\"\\n\");\n }\n\n for (const chunk of pageChunks) {\n const page = chunk.page;\n\n if (!page) {\n continue;\n }\n\n const fileName = emitCssAsset(\n environment,\n `${chunk.name}.css`,\n chunk.css,\n );\n pageSpecificSizeBytes += chunk.sizeBytes;\n const files = pageCssFiles.get(page) ?? [];\n files.push(fileName);\n pageCssFiles.set(page, files);\n\n const emittedPage: EmittedPageChunk = {\n page,\n fileName,\n sizeBytes: chunk.sizeBytes,\n };\n\n diagnostics.emittedPageChunks.push(emittedPage);\n diagnostics.emittedCssChunks.push({\n fileName,\n sourceChunk: chunk.sourceChunk,\n kind: chunk.kind as EmittedCssChunk[\"kind\"],\n page,\n variables: chunk.variables,\n part: chunk.part,\n sizeBytes: chunk.sizeBytes,\n oversized: chunk.oversized,\n splitDueToSize: chunk.splitDueToSize,\n embedded: false,\n });\n\n if (chunk.splitDueToSize) {\n diagnostics.sizeBudget.splitChunks += 1;\n }\n\n if (chunk.oversized) {\n diagnostics.sizeBudget.oversizedChunks += 1;\n }\n }\n\n file.sizeAfterBytes = commonWasSplit\n ? commonSizeBytes\n : Buffer.byteLength(output.source, \"utf8\");\n file.split = {\n associatedPages,\n commonSizeBytes,\n pageSpecificSizeBytes,\n deadCodeCount: pipeline.deadCodeCount,\n };\n\n for (const stat of pipeline.stats) {\n const previous = matrix.get(stat.selector);\n\n if (!previous || stat.totalOccurrences > previous.totalOccurrences) {\n matrix.set(stat.selector, stat);\n }\n }\n\n diagnostics.deadCodeCount += pipeline.deadCodeCount;\n diagnostics.commonCssBytes += commonSizeBytes;\n diagnostics.pageSpecificCssBytes += pageSpecificSizeBytes;\n } catch (error) {\n diagnostics.errors.push(\n `${file.fileName}: failed to optimize CSS: ${describeError(error)}`,\n );\n }\n\n diagnostics.analyzedCssAssets += 1;\n diagnostics.totalSizeBeforeBytes += file.sizeBeforeBytes;\n diagnostics.totalSizeAfterBytes += file.sizeAfterBytes;\n diagnostics.totalSelectors += file.selectorCount;\n diagnostics.totalRules += file.ruleCount;\n diagnostics.files.push(file);\n }\n\n if (htmlLinks.length > 0) {\n injectStylesheetLinks(bundle, htmlLinks, options.base);\n }\n\n if (pageCssFiles.size > 0) {\n injectPageChunkStyles(bundle, pageCssFiles, pageChunkFiles, options.base);\n }\n\n diagnostics.usageMatrix = [...matrix.values()].sort((left, right) =>\n left.selector.localeCompare(right.selector),\n );\n diagnostics.durationMs = roundMs(performance.now() - startedAt);\n\n return diagnostics;\n}\n\nfunction emitCssAsset(\n environment: AnalysisEnvironment,\n name: string,\n source: string,\n): string {\n const referenceId = environment.emitFile({\n type: \"asset\",\n name,\n source,\n });\n\n return environment.getFileName(referenceId);\n}\n\nfunction injectPageChunkStyles(\n bundle: Record<string, unknown>,\n cssByPage: Map<string, string[]>,\n chunkByPage: Map<string, string>,\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n\n for (const [page, fileNames] of cssByPage) {\n if (fileNames.length === 0) {\n continue;\n }\n\n const chunkFile = chunkByPage.get(page);\n const hrefs = fileNames.map((fileName) => `${normalizedBase}${fileName}`);\n const htmlOutput = findPageHtmlAsset(bundle, page);\n const output = htmlOutput ?? (chunkFile ? bundle[chunkFile] : undefined);\n\n if (isHtmlAsset(output)) {\n const tags = hrefs\n .map(\n (href) =>\n ` <link rel=\"stylesheet\" href=\"${href}\" data-css-doctor-page>`,\n )\n .join(\"\\n\");\n\n if (!output.source.includes(tags) && output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n continue;\n }\n\n if (!isChunk(output)) {\n continue;\n }\n\n const snippet = `(()=>{const __cssDoctorPageStyles=${JSON.stringify(hrefs)};if(typeof document!==\"undefined\"){for(const __cssDoctorPageHref of __cssDoctorPageStyles){if(!Array.from(document.querySelectorAll(\"link[data-css-doctor-page]\")).some((link)=>link.dataset.cssDoctorPage===__cssDoctorPageHref)){const __cssDoctorPageLink=document.createElement(\"link\");__cssDoctorPageLink.rel=\"stylesheet\";__cssDoctorPageLink.href=__cssDoctorPageHref;__cssDoctorPageLink.dataset.cssDoctorPage=__cssDoctorPageHref;document.head.append(__cssDoctorPageLink);}}}})();\\n`;\n\n output.code = snippet + output.code;\n }\n}\n\nfunction injectStylesheetLinks(\n bundle: Record<string, unknown>,\n fileNames: string[],\n base: string,\n): void {\n const normalizedBase = base.endsWith(\"/\") ? base : `${base}/`;\n const tags = fileNames\n .map(\n (fileName) =>\n ` <link rel=\"stylesheet\" href=\"${normalizedBase}${fileName}\">`,\n )\n .join(\"\\n\");\n\n for (const output of Object.values(bundle)) {\n if (!isHtmlAsset(output) || output.source.includes(tags)) {\n continue;\n }\n\n if (output.source.includes(\"</head>\")) {\n output.source = output.source.replace(\"</head>\", `${tags}\\n </head>`);\n }\n }\n}\n\nfunction findPageHtmlAsset(\n bundle: Record<string, unknown>,\n page: string,\n): unknown {\n const names =\n page === \"index\"\n ? [\"index.html\"]\n : [\n `page-${page}/index.html`,\n `page-${page}.html`,\n `${page}/index.html`,\n `${page}.html`,\n ];\n\n for (const name of names) {\n const output = bundle[name];\n\n if (isHtmlAsset(output)) {\n return output;\n }\n }\n\n return undefined;\n}\n\nfunction isHtmlAsset(\n value: unknown,\n): value is { type: \"asset\"; fileName: string; source: string } {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".html\") &&\n typeof candidate.source === \"string\"\n );\n}\n\nfunction analyzeAsset(\n output: CssAssetLike,\n associatedPages: string[],\n): CssAssetDiagnostic {\n const analysisStartedAt = performance.now();\n\n try {\n const css = sourceToCss(output.source);\n const sizeBeforeBytes = Buffer.byteLength(css, \"utf8\");\n const analysis = analyzeCss(css);\n const warnings = collectSyntaxWarnings(analysis);\n\n if (sizeBeforeBytes >= LARGE_CSS_ASSET_BYTES) {\n warnings.push({\n kind: \"large-asset\",\n message:\n `CSS asset is larger than ${formatBytes(LARGE_CSS_ASSET_BYTES)}; ` +\n \"consider route-level code splitting.\",\n });\n }\n\n return {\n fileName: output.fileName,\n sizeBeforeBytes,\n sizeAfterBytes: sizeBeforeBytes,\n selectorCount: analysis.stats.selectorCount,\n ruleCount: analysis.stats.ruleCount,\n declarationCount: analysis.stats.declarationCount,\n importantDeclarationCount: analysis.stats.importantDeclarationCount,\n uniqueClassCount: analysis.stats.uniqueClassCount,\n uniqueIdCount: analysis.stats.uniqueIdCount,\n uniqueTagCount: analysis.stats.uniqueTagCount,\n syntaxWarningCount: analysis.warnings.length,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings,\n analysis,\n };\n } catch (error) {\n return {\n fileName: output.fileName,\n sizeBeforeBytes: 0,\n sizeAfterBytes: 0,\n selectorCount: 0,\n ruleCount: 0,\n declarationCount: 0,\n importantDeclarationCount: 0,\n uniqueClassCount: 0,\n uniqueIdCount: 0,\n uniqueTagCount: 0,\n syntaxWarningCount: 0,\n analysisMs: roundMs(performance.now() - analysisStartedAt),\n associatedPages,\n warnings: [],\n error: describeError(error),\n };\n }\n}\n\nasync function collectPages(\n bundle: Record<string, unknown>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n directPageUsage: Record<string, string[]> | undefined,\n): Promise<{\n pages: PageInfo[];\n pagesByCss: Map<string, Set<string>>;\n}> {\n const chunks = Object.values(bundle).filter(isChunk);\n const chunksByFileName = new Map(\n chunks.map((chunk) => [chunk.fileName, chunk]),\n );\n const pages = new Map<string, PageInfo>();\n const entryFileNames = new Set(\n chunks.filter((chunk) => chunk.isEntry).map((chunk) => chunk.fileName),\n );\n\n for (const entry of chunks.filter((chunk) => chunk.isEntry)) {\n if (isInternalPageEntry(entry)) {\n continue;\n }\n\n const shell = collectChunkContent(\n entry,\n chunksByFileName,\n getModuleInfo,\n false,\n );\n\n if (entry.facadeModuleId && isHtmlFile(entry.facadeModuleId)) {\n try {\n scanClasses(\n await readFile(entry.facadeModuleId, \"utf8\"),\n shell.classes,\n );\n } catch {\n // The HTML source may be virtual or removed by another plugin. The\n // generated chunk code and pageUsage option still provide coverage.\n }\n }\n\n const routeChunks = entry.dynamicImports\n .map((fileName) => chunksByFileName.get(fileName))\n .filter((chunk): chunk is ViteChunkLike => chunk !== undefined);\n\n if (routeChunks.length > 0) {\n // A SPA shell usually owns the HTML, navigation and global CSS, while\n // every direct dynamic import is a route. Treat those chunks as pages\n // and apply the shell classes/CSS to each one, instead of collapsing all\n // routes into the single index entry.\n for (const routeChunk of routeChunks) {\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(routePageName(routeChunk)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: routeChunk.fileName,\n };\n const route = collectChunkContent(\n routeChunk,\n chunksByFileName,\n getModuleInfo,\n true,\n entryFileNames,\n );\n\n for (const className of route.classes) {\n page.classes.add(className);\n }\n\n for (const cssFile of route.cssFiles) {\n page.cssFiles.add(cssFile);\n }\n\n pages.set(page.name, page);\n }\n\n continue;\n }\n\n const page: PageInfo = {\n name: uniquePageName(cleanPageName(pageNameFor(entry)), pages),\n classes: new Set(shell.classes),\n cssFiles: new Set(shell.cssFiles),\n chunkFile: entry.fileName,\n };\n\n pages.set(page.name, page);\n }\n\n if (directPageUsage) {\n for (const [rawName, classes] of Object.entries(directPageUsage)) {\n const name = rawName.trim();\n\n if (name.length === 0) {\n continue;\n }\n\n let page = pages.get(name);\n\n if (!page) {\n page = {\n name,\n classes: new Set(),\n cssFiles: new Set(),\n chunkFile: null,\n };\n pages.set(name, page);\n }\n\n for (const className of classes) {\n page.classes.add(className.toLowerCase());\n }\n }\n }\n\n const pagesByCss = new Map<string, Set<string>>();\n\n for (const page of pages.values()) {\n for (const cssFile of page.cssFiles) {\n const owners = pagesByCss.get(cssFile) ?? new Set<string>();\n owners.add(page.name);\n pagesByCss.set(cssFile, owners);\n }\n }\n\n return {\n pages: [...pages.values()],\n pagesByCss,\n };\n}\n\nfunction collectChunkContent(\n startChunk: ViteChunkLike,\n chunksByFileName: Map<string, ViteChunkLike>,\n getModuleInfo: AnalysisEnvironment[\"getModuleInfo\"],\n includeDynamicImports: boolean,\n skipFileNames: ReadonlySet<string> = new Set<string>(),\n): {\n classes: Set<string>;\n cssFiles: Set<string>;\n} {\n const classes = new Set<string>();\n const cssFiles = new Set<string>();\n const visited = new Set<string>();\n const stack = [startChunk.fileName];\n\n while (stack.length > 0) {\n const fileName = stack.pop();\n\n if (!fileName || visited.has(fileName) || skipFileNames.has(fileName)) {\n continue;\n }\n\n visited.add(fileName);\n\n const chunk = chunksByFileName.get(fileName);\n\n if (!chunk) {\n continue;\n }\n\n scanClasses(chunk.code, classes);\n\n for (const moduleId of Object.keys(chunk.modules)) {\n if (isStyleModule(moduleId)) {\n continue;\n }\n\n const moduleInfo = getModuleInfo(moduleId);\n\n if (moduleInfo?.code) {\n scanClasses(moduleInfo.code, classes);\n }\n }\n\n for (const cssFile of chunk.viteMetadata?.importedCss ?? []) {\n cssFiles.add(cssFile);\n }\n\n stack.push(...chunk.imports);\n\n if (includeDynamicImports) {\n stack.push(...chunk.dynamicImports);\n }\n }\n\n return { classes, cssFiles };\n}\n\nfunction scanClasses(source: string, classes: Set<string>): void {\n const patterns = [\n /(?:class|className)\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /(?:^|[,{;\\s])(?:class|className)\\s*:\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n /classList\\.(?:add|remove|toggle|contains)\\(\\s*(?:\"([^\"]*)\"|'([^']*)'|`([^`]*)`)/g,\n ];\n\n for (const pattern of patterns) {\n for (const match of source.matchAll(pattern)) {\n const value = match[1] ?? match[2] ?? match[3];\n\n if (!value) {\n continue;\n }\n\n for (const token of value.split(/\\s+/)) {\n if (isClassToken(token)) {\n classes.add(token.toLowerCase());\n }\n }\n }\n }\n}\n\n/** Accept Tailwind-style tokens (`md:flex`, `w-1/2`, `w-[10px]`, `!p-2`). */\nfunction isClassToken(token: string): boolean {\n if (!token || token.length > 256) {\n return false;\n }\n\n // Reject template/expression leftovers while allowing arbitrary-value brackets.\n if (/[`${}]/.test(token)) {\n return false;\n }\n\n return /[A-Za-z_]/.test(token);\n}\n\nfunction isInternalPageEntry(chunk: ViteChunkLike): boolean {\n const name = pageNameFor(chunk);\n\n return (\n name.startsWith(\"_\") ||\n name.startsWith(\"noop-\") ||\n name.includes(\"@astro-renderers\")\n );\n}\n\nfunction cleanPageName(name: string): string {\n const normalized = name\n .trim()\n .toLowerCase()\n .replace(/@_@[a-z]+$/i, \"\")\n .replace(/^page-/, \"\");\n\n return normalized || \"page\";\n}\n\nfunction routePageName(chunk: ViteChunkLike): string {\n const name = pageNameFor(chunk).toLowerCase();\n\n return name.startsWith(\"page-\") ? name.slice(\"page-\".length) : name;\n}\n\nfunction isCssModuleAsset(fileName: string, css: string): boolean {\n if (/\\.module\\.(css|scss|sass|less|styl|stylus)$/i.test(fileName)) {\n return true;\n }\n\n // Vite's default CSS Modules local identifier is `_local_hash_index`\n // (for example `_card_1udun_1`). The emitted asset name is hashed, so\n // detect the scoped class shape in the source as a safety boundary.\n return /\\.[A-Za-z0-9_-]+_[A-Za-z0-9]{5,}_[0-9]+/.test(css);\n}\n\nfunction isVueScopedAsset(css: string): boolean {\n return /\\[data-v-[0-9a-f]+\\]/.test(css);\n}\n\nfunction pageNameFor(chunk: ViteChunkLike): string {\n if (chunk.name.length > 0) {\n return chunk.name;\n }\n\n if (chunk.facadeModuleId) {\n return basename(chunk.facadeModuleId, extname(chunk.facadeModuleId));\n }\n\n return chunk.fileName.replace(/\\.[^.]+$/, \"\");\n}\n\nfunction uniquePageName(base: string, pages: Map<string, PageInfo>): string {\n const normalized = base.trim() || \"page\";\n\n if (!pages.has(normalized)) {\n return normalized;\n }\n\n let index = 2;\n\n while (pages.has(`${normalized}-${index}`)) {\n index += 1;\n }\n\n return `${normalized}-${index}`;\n}\n\nfunction isCssAsset(value: unknown): value is CssAssetLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n source?: unknown;\n };\n\n return (\n candidate.type === \"asset\" &&\n typeof candidate.fileName === \"string\" &&\n candidate.fileName.endsWith(\".css\") &&\n (typeof candidate.source === \"string\" ||\n candidate.source instanceof Uint8Array)\n );\n}\n\nfunction isChunk(value: unknown): value is ViteChunkLike {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const candidate = value as {\n type?: unknown;\n fileName?: unknown;\n name?: unknown;\n isEntry?: unknown;\n facadeModuleId?: unknown;\n code?: unknown;\n modules?: unknown;\n imports?: unknown;\n dynamicImports?: unknown;\n };\n\n return (\n candidate.type === \"chunk\" &&\n typeof candidate.fileName === \"string\" &&\n typeof candidate.name === \"string\" &&\n typeof candidate.isEntry === \"boolean\" &&\n typeof candidate.code === \"string\" &&\n typeof candidate.modules === \"object\" &&\n candidate.modules !== null &&\n Array.isArray(candidate.imports) &&\n Array.isArray(candidate.dynamicImports)\n );\n}\n\nfunction isStyleModule(moduleId: string): boolean {\n return /\\.(css|scss|sass|less|styl|stylus)(\\?|$)/i.test(moduleId);\n}\n\nfunction isHtmlFile(moduleId: string): boolean {\n return /\\.(html?|vue)$/i.test(moduleId);\n}\n\nfunction collectSyntaxWarnings(\n analysis: JsCssAnalysisResult,\n): CssAssetWarning[] {\n return analysis.warnings.map((warning) => ({\n kind: \"syntax\",\n message: warning.message,\n ...(warning.location\n ? {\n line: warning.location.line,\n column: warning.location.column,\n }\n : {}),\n }));\n}\n\nfunction sourceToCss(source: string | Uint8Array): string {\n return typeof source === \"string\"\n ? source\n : Buffer.from(source).toString(\"utf8\");\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction roundMs(value: number): number {\n return Math.round(value * 1_000) / 1_000;\n}\n\nfunction describeError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","import picocolors from \"picocolors\";\n\nimport type {\n CssAssetDiagnostic,\n CssAssetWarning,\n CssDoctorDiagnostics,\n} from \"./types\";\n\nconst MATRIX_SELECTOR_MAX = 36;\n\n/** Options for terminal rendering. Defaults to picocolors' TTY detection. */\nexport type ReporterOptions = {\n color?: boolean;\n};\n\n/** Formats diagnostics as a human-readable build report. */\nexport function formatDiagnostics(\n diagnostics: CssDoctorDiagnostics,\n options: ReporterOptions = {},\n): string {\n const colors = picocolors.createColors(\n options.color ?? picocolors.isColorSupported,\n );\n const badge = colors.bgCyan(colors.black(\"[css-doctor]\"));\n const lines: string[] = [];\n\n lines.push(\n `${badge} ${diagnostics.pages.length} page${\n diagnostics.pages.length === 1 ? \"\" : \"s\"\n } ${colors.dim(\"·\")} ${diagnostics.analyzedCssAssets}/${\n diagnostics.totalCssAssets\n } CSS assets ${colors.dim(\"·\")} ${formatBytes(\n diagnostics.totalSizeBeforeBytes,\n )} → ${formatBytes(diagnostics.totalSizeAfterBytes)} common ` +\n `${colors.dim(\"·\")} ${formatDuration(diagnostics.durationMs)}` +\n (diagnostics.skippedCssAssets > 0\n ? ` ${colors.dim(`· ${diagnostics.skippedCssAssets} skipped`)}`\n : \"\") +\n ` ${colors.dim(\"·\")} ${\n diagnostics.minify\n ? colors.green(\"Minified: YES\")\n : colors.yellow(\"Minified: NO\")\n }`,\n );\n\n for (const file of diagnostics.files) {\n lines.push(...formatFile(file, colors));\n }\n\n if (diagnostics.splitApplied) {\n lines.push(\"\");\n lines.push(...formatMatrix(diagnostics, colors));\n }\n\n if (diagnostics.emittedPageChunks.length > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.bold(\"Emitted page chunks\")} ${colors.dim(\n `(${diagnostics.emittedPageChunks.length})`,\n )}`,\n );\n\n for (const chunk of diagnostics.emittedPageChunks) {\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}`,\n );\n }\n }\n\n if (diagnostics.sizeBudget.enabled) {\n lines.push(\"\");\n lines.push(...formatSizeBudget(diagnostics, colors));\n }\n\n if (diagnostics.deadCodeCount > 0) {\n lines.push(\"\");\n lines.push(\n ` ${colors.yellow(\"⚠\")} ${colors.bold(\"Dead code eliminated:\")} ` +\n `${diagnostics.deadCodeCount} selector occurrence${\n diagnostics.deadCodeCount === 1 ? \"\" : \"s\"\n }`,\n );\n }\n\n if (diagnostics.errors.length > 0) {\n lines.push(\"\");\n lines.push(` ${colors.red(colors.bold(\"Errors\"))}`);\n\n for (const error of diagnostics.errors) {\n lines.push(` ${colors.red(\"✖\")} ${error}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/** Prints diagnostics to stdout. */\nexport function printDiagnostics(diagnostics: CssDoctorDiagnostics): void {\n console.log(formatDiagnostics(diagnostics));\n}\n\nfunction formatFile(\n file: CssAssetDiagnostic,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const failed = file.error !== undefined;\n const hasWarnings = file.warnings.length > 0;\n const icon = failed\n ? colors.red(\"✖\")\n : hasWarnings\n ? colors.yellow(\"⚠\")\n : colors.green(\"✓\");\n\n const size = `${formatBytes(file.sizeBeforeBytes)} → ${formatBytes(\n file.sizeAfterBytes,\n )}`;\n const selectors = failed ? \"\" : ` · ${file.selectorCount} selectors`;\n const pages =\n file.associatedPages.length > 0\n ? ` · pages: ${file.associatedPages.join(\", \")}`\n : \"\";\n\n const lines = [\n ` ${icon} ${colors.bold(file.fileName)} ${colors.dim(size)}${selectors}${colors.dim(pages)}`,\n ];\n\n if (file.error) {\n lines.push(` ${colors.red(file.error)}`);\n return lines;\n }\n\n if (file.split) {\n lines.push(\n ` ${colors.dim(\"split\")} common ${formatBytes(\n file.split.commonSizeBytes,\n )} ${colors.dim(\"·\")} page-specific ${formatBytes(\n file.split.pageSpecificSizeBytes,\n )} ${colors.dim(\"·\")} dead ${file.split.deadCodeCount}`,\n );\n }\n\n for (const warning of file.warnings) {\n lines.push(` ${formatWarning(warning, colors)}`);\n }\n\n return lines;\n}\n\nfunction formatMatrix(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const pageTotal = diagnostics.pages.length;\n const rows = diagnostics.usageMatrix;\n const header = [\n \"Selector\".padEnd(MATRIX_SELECTOR_MAX),\n \"Total Used\".padStart(10),\n \"Page Usage\".padStart(10),\n \"Coverage %\".padStart(10),\n \"Assigned Chunk\",\n ].join(\" \");\n\n const lines = [\n ` ${colors.bold(\"Usage Matrix\")} ${colors.dim(\n `(${rows.length} selectors · ${pageTotal} pages)`,\n )}`,\n ` ${colors.dim(header)}`,\n ];\n\n for (const row of rows) {\n const selector = truncate(row.selector, MATRIX_SELECTOR_MAX).padEnd(\n MATRIX_SELECTOR_MAX,\n );\n const totalUsed = String(row.totalOccurrences).padStart(10);\n const pageUsage = `${row.pageCount}/${pageTotal}`.padStart(10);\n const coverage = `${(row.coverageRatio * 100).toFixed(1)}%`.padStart(10);\n const chunk = formatChunk(row.targetChunk, colors);\n\n lines.push(\n ` ${colors.cyan(selector)} ${totalUsed} ${pageUsage} ${colorCoverage(\n coverage,\n row.coverageRatio,\n diagnostics.minPageRatio,\n colors,\n )} ${chunk}`,\n );\n }\n\n return lines;\n}\n\nfunction formatSizeBudget(\n diagnostics: CssDoctorDiagnostics,\n colors: ReturnType<typeof picocolors.createColors>,\n): string[] {\n const budget = diagnostics.sizeBudget;\n const lines = [\n ` ${colors.bold(\"Size budget\")} ${colors.dim(\n `(max ${formatBytes(budget.maxChunkSize)} · variables ${\n budget.isolateVariables ? \"isolated\" : \"inline\"\n })`,\n )}`,\n ];\n\n const chunks = diagnostics.emittedCssChunks;\n\n if (chunks.length === 0) {\n lines.push(` ${colors.dim(\"No CSS chunks were emitted.\")}`);\n return lines;\n }\n\n for (const chunk of chunks) {\n const markers: string[] = [];\n\n if (chunk.variables) {\n markers.push(\"vars\");\n }\n\n if (chunk.part !== undefined) {\n markers.push(`part ${chunk.part}`);\n }\n\n if (chunk.embedded) {\n markers.push(\"embedded\");\n }\n\n if (chunk.splitDueToSize) {\n markers.push(colors.yellow(\"split\"));\n }\n\n if (chunk.oversized) {\n markers.push(colors.red(\"oversized\"));\n }\n\n lines.push(\n ` ${colors.magenta(chunk.fileName)} ${colors.dim(\n formatBytes(chunk.sizeBytes),\n )}${markers.length > 0 ? ` ${colors.dim(\"·\")} ${markers.join(\" · \")}` : \"\"}`,\n );\n }\n\n if (budget.splitChunks === 0) {\n lines.push(\n ` ${colors.dim(\"No chunk exceeded the configured size budget.\")}`,\n );\n }\n\n return lines;\n}\n\nfunction formatWarning(\n warning: CssAssetWarning,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n const location =\n warning.line !== undefined\n ? colors.dim(\n `${warning.line}${\n warning.column !== undefined ? `:${warning.column}` : \"\"\n } `,\n )\n : \"\";\n\n return `${colors.yellow(\"!\")} ${location}${warning.message}`;\n}\n\nfunction colorCoverage(\n coverage: string,\n ratio: number,\n minPageRatio: number,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (ratio === 0) {\n return colors.red(coverage);\n }\n\n return ratio >= minPageRatio\n ? colors.green(coverage)\n : colors.yellow(coverage);\n}\n\nfunction formatChunk(\n chunk: string,\n colors: ReturnType<typeof picocolors.createColors>,\n): string {\n if (chunk === \"common\") {\n return colors.cyan(chunk);\n }\n\n if (chunk === \"dead\") {\n return colors.red(chunk);\n }\n\n return colors.magenta(chunk);\n}\n\nfunction truncate(value: string, maxLength: number): string {\n return value.length <= maxLength\n ? value\n : `${value.slice(0, maxLength - 1)}…`;\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1_024) {\n return `${bytes} B`;\n }\n\n if (bytes < 1_024 * 1_024) {\n return `${(bytes / 1_024).toFixed(1)} KB`;\n }\n\n return `${(bytes / (1_024 * 1_024)).toFixed(1)} MB`;\n}\n\nfunction formatDuration(milliseconds: number): string {\n if (!Number.isFinite(milliseconds)) {\n return \"—\";\n }\n\n return milliseconds < 1\n ? `${milliseconds.toFixed(2)} ms`\n : `${milliseconds.toFixed(1)} ms`;\n}\n"],"mappings":"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","names":["formatBytes","page"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zealakit/css-doctor-vite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Vite plugin that analyzes emitted CSS assets with the css-doctor native engine",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"css",
|
|
7
|
+
"css-doctor",
|
|
8
|
+
"vite",
|
|
9
|
+
"vite-plugin",
|
|
10
|
+
"rollup",
|
|
11
|
+
"rollup-plugin",
|
|
12
|
+
"css-analysis",
|
|
13
|
+
"css-optimizer",
|
|
14
|
+
"dead-code-elimination",
|
|
15
|
+
"unused-css",
|
|
16
|
+
"purgecss",
|
|
17
|
+
"css-splitting",
|
|
18
|
+
"page-coverage",
|
|
19
|
+
"size-budget",
|
|
20
|
+
"code-splitting",
|
|
21
|
+
"build-tool",
|
|
22
|
+
"performance",
|
|
23
|
+
"web-performance",
|
|
24
|
+
"tailwind",
|
|
25
|
+
"frontend"
|
|
26
|
+
],
|
|
5
27
|
"author": "nqhed - Huy Edward Nguyen",
|
|
6
28
|
"type": "module",
|
|
7
29
|
"license": "MIT",
|
|
@@ -23,8 +45,8 @@
|
|
|
23
45
|
],
|
|
24
46
|
"dependencies": {
|
|
25
47
|
"@rollup/pluginutils": "^5.5.1",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
48
|
+
"@zealakit/css-doctor-binding": "1.1.0",
|
|
49
|
+
"picocolors": "^1.1.1"
|
|
28
50
|
},
|
|
29
51
|
"peerDependencies": {
|
|
30
52
|
"vite": ">=4.0.0"
|