@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 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 minPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;
266
- const maxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;
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 (!Number.isFinite(minPageRatio) || minPageRatio < 0 || minPageRatio > 1) {
270
- throw new RangeError(
271
- "css-doctor: minPageRatio must be a number between 0 and 1"
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 (!Number.isFinite(maxChunkSize) || !Number.isInteger(maxChunkSize) || maxChunkSize <= 0) {
275
- throw new RangeError("css-doctor: maxChunkSize must be a positive integer");
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 splitApplied = options.pageCoverage.enabled && pageNames.length > 0;
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: options.pageCoverage.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 (/^-?[_a-zA-Z][\w-]*$/.test(token)) {
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");
@@ -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 minPageRatio = pageCoverage.minPageRatio ?? DEFAULT_MIN_PAGE_RATIO;
230
- const maxChunkSize = sizeBudget.maxChunkSize ?? DEFAULT_MAX_CHUNK_SIZE;
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 (!Number.isFinite(minPageRatio) || minPageRatio < 0 || minPageRatio > 1) {
234
- throw new RangeError(
235
- "css-doctor: minPageRatio must be a number between 0 and 1"
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 (!Number.isFinite(maxChunkSize) || !Number.isInteger(maxChunkSize) || maxChunkSize <= 0) {
239
- throw new RangeError("css-doctor: maxChunkSize must be a positive integer");
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 splitApplied = options.pageCoverage.enabled && pageNames.length > 0;
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: options.pageCoverage.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 (/^-?[_a-zA-Z][\w-]*$/.test(token)) {
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":";AAAA,SAAS,gBAAgB;AACzB,SAAS,UAAU,eAAe;AAClC,SAAS,mBAAmB;AAE5B,SAAS,oBAAoB;AAC7B,SAAS,YAAY,mBAAmB;;;ACLxC,OAAO,gBAAgB;AAQvB,IAAM,sBAAsB;AAQrB,SAAS,kBACd,aACA,UAA2B,CAAC,GACpB;AACR,QAAM,SAAS,WAAW;AAAA,IACxB,QAAQ,SAAS,WAAW;AAAA,EAC9B;AACA,QAAM,QAAQ,OAAO,OAAO,OAAO,MAAM,cAAc,CAAC;AACxD,QAAM,QAAkB,CAAC;AAEzB,QAAM;AAAA,IACJ,GAAG,KAAK,IAAI,YAAY,MAAM,MAAM,QAClC,YAAY,MAAM,WAAW,IAAI,KAAK,GACxC,IAAI,OAAO,IAAI,MAAG,CAAC,IAAI,YAAY,iBAAiB,IAClD,YAAY,cACd,eAAe,OAAO,IAAI,MAAG,CAAC,IAAI;AAAA,MAChC,YAAY;AAAA,IACd,CAAC,WAAM,YAAY,YAAY,mBAAmB,CAAC,WAC9C,OAAO,IAAI,MAAG,CAAC,IAAI,eAAe,YAAY,UAAU,CAAC,MAC3D,YAAY,mBAAmB,IAC5B,IAAI,OAAO,IAAI,QAAK,YAAY,gBAAgB,UAAU,CAAC,KAC3D,MACJ,IAAI,OAAO,IAAI,MAAG,CAAC,IACjB,YAAY,SACR,OAAO,MAAM,eAAe,IAC5B,OAAO,OAAO,cAAc,CAClC;AAAA,EACJ;AAEA,aAAW,QAAQ,YAAY,OAAO;AACpC,UAAM,KAAK,GAAG,WAAW,MAAM,MAAM,CAAC;AAAA,EACxC;AAEA,MAAI,YAAY,cAAc;AAC5B,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,aAAa,aAAa,MAAM,CAAC;AAAA,EACjD;AAEA,MAAI,YAAY,kBAAkB,SAAS,GAAG;AAC5C,UAAM,KAAK,EAAE;AACb,UAAM;AAAA,MACJ,KAAK,OAAO,KAAK,qBAAqB,CAAC,IAAI,OAAO;AAAA,QAChD,IAAI,YAAY,kBAAkB,MAAM;AAAA,MAC1C,CAAC;AAAA,IACH;AAEA,eAAW,SAAS,YAAY,mBAAmB;AACjD,YAAM;AAAA,QACJ,OAAO,OAAO,QAAQ,MAAM,QAAQ,CAAC,IAAI,OAAO;AAAA,UAC9C,YAAY,MAAM,SAAS;AAAA,QAC7B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,WAAW,SAAS;AAClC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,GAAG,iBAAiB,aAAa,MAAM,CAAC;AAAA,EACrD;AAEA,MAAI,YAAY,gBAAgB,GAAG;AACjC,UAAM,KAAK,EAAE;AACb,UAAM;AAAA,MACJ,KAAK,OAAO,OAAO,QAAG,CAAC,IAAI,OAAO,KAAK,uBAAuB,CAAC,IAC1D,YAAY,aAAa,uBAC1B,YAAY,kBAAkB,IAAI,KAAK,GACzC;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,YAAY,OAAO,SAAS,GAAG;AACjC,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,KAAK,OAAO,IAAI,OAAO,KAAK,QAAQ,CAAC,CAAC,EAAE;AAEnD,eAAW,SAAS,YAAY,QAAQ;AACtC,YAAM,KAAK,OAAO,OAAO,IAAI,QAAG,CAAC,IAAI,KAAK,EAAE;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAGO,SAAS,iBAAiB,aAAyC;AACxE,UAAQ,IAAI,kBAAkB,WAAW,CAAC;AAC5C;AAEA,SAAS,WACP,MACA,QACU;AACV,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,cAAc,KAAK,SAAS,SAAS;AAC3C,QAAM,OAAO,SACT,OAAO,IAAI,QAAG,IACd,cACE,OAAO,OAAO,QAAG,IACjB,OAAO,MAAM,QAAG;AAEtB,QAAM,OAAO,GAAG,YAAY,KAAK,eAAe,CAAC,WAAM;AAAA,IACrD,KAAK;AAAA,EACP,CAAC;AACD,QAAM,YAAY,SAAS,KAAK,SAAM,KAAK,aAAa;AACxD,QAAM,QACJ,KAAK,gBAAgB,SAAS,IAC1B,gBAAa,KAAK,gBAAgB,KAAK,IAAI,CAAC,KAC5C;AAEN,QAAM,QAAQ;AAAA,IACZ,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,CAAC,IAAI,OAAO,IAAI,IAAI,CAAC,GAAG,SAAS,GAAG,OAAO,IAAI,KAAK,CAAC;AAAA,EAC7F;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,KAAK,SAAS,OAAO,IAAI,KAAK,KAAK,CAAC,EAAE;AAC5C,WAAO;AAAA,EACT;AAEA,MAAI,KAAK,OAAO;AACd,UAAM;AAAA,MACJ,SAAS,OAAO,IAAI,OAAO,CAAC,WAAW;AAAA,QACrC,KAAK,MAAM;AAAA,MACb,CAAC,IAAI,OAAO,IAAI,MAAG,CAAC,kBAAkB;AAAA,QACpC,KAAK,MAAM;AAAA,MACb,CAAC,IAAI,OAAO,IAAI,MAAG,CAAC,SAAS,KAAK,MAAM,aAAa;AAAA,IACvD;AAAA,EACF;AAEA,aAAW,WAAW,KAAK,UAAU;AACnC,UAAM,KAAK,SAAS,cAAc,SAAS,MAAM,CAAC,EAAE;AAAA,EACtD;AAEA,SAAO;AACT;AAEA,SAAS,aACP,aACA,QACU;AACV,QAAM,YAAY,YAAY,MAAM;AACpC,QAAM,OAAO,YAAY;AACzB,QAAM,SAAS;AAAA,IACb,WAAW,OAAO,mBAAmB;AAAA,IACrC,aAAa,SAAS,EAAE;AAAA,IACxB,aAAa,SAAS,EAAE;AAAA,IACxB,aAAa,SAAS,EAAE;AAAA,IACxB;AAAA,EACF,EAAE,KAAK,IAAI;AAEX,QAAM,QAAQ;AAAA,IACZ,KAAK,OAAO,KAAK,cAAc,CAAC,IAAI,OAAO;AAAA,MACzC,IAAI,KAAK,MAAM,mBAAgB,SAAS;AAAA,IAC1C,CAAC;AAAA,IACD,KAAK,OAAO,IAAI,MAAM,CAAC;AAAA,EACzB;AAEA,aAAW,OAAO,MAAM;AACtB,UAAM,WAAW,SAAS,IAAI,UAAU,mBAAmB,EAAE;AAAA,MAC3D;AAAA,IACF;AACA,UAAM,YAAY,OAAO,IAAI,gBAAgB,EAAE,SAAS,EAAE;AAC1D,UAAM,YAAY,GAAG,IAAI,SAAS,IAAI,SAAS,GAAG,SAAS,EAAE;AAC7D,UAAM,WAAW,IAAI,IAAI,gBAAgB,KAAK,QAAQ,CAAC,CAAC,IAAI,SAAS,EAAE;AACvE,UAAM,QAAQ,YAAY,IAAI,aAAa,MAAM;AAEjD,UAAM;AAAA,MACJ,KAAK,OAAO,KAAK,QAAQ,CAAC,KAAK,SAAS,KAAK,SAAS,KAAK;AAAA,QACzD;AAAA,QACA,IAAI;AAAA,QACJ,YAAY;AAAA,QACZ;AAAA,MACF,CAAC,KAAK,KAAK;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,aACA,QACU;AACV,QAAM,SAAS,YAAY;AAC3B,QAAM,QAAQ;AAAA,IACZ,KAAK,OAAO,KAAK,aAAa,CAAC,IAAI,OAAO;AAAA,MACxC,QAAQ,YAAY,OAAO,YAAY,CAAC,mBACtC,OAAO,mBAAmB,aAAa,QACzC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,YAAY;AAE3B,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,KAAK,OAAO,OAAO,IAAI,6BAA6B,CAAC,EAAE;AAC7D,WAAO;AAAA,EACT;AAEA,aAAW,SAAS,QAAQ;AAC1B,UAAM,UAAoB,CAAC;AAE3B,QAAI,MAAM,WAAW;AACnB,cAAQ,KAAK,MAAM;AAAA,IACrB;AAEA,QAAI,MAAM,SAAS,QAAW;AAC5B,cAAQ,KAAK,QAAQ,MAAM,IAAI,EAAE;AAAA,IACnC;AAEA,QAAI,MAAM,UAAU;AAClB,cAAQ,KAAK,UAAU;AAAA,IACzB;AAEA,QAAI,MAAM,gBAAgB;AACxB,cAAQ,KAAK,OAAO,OAAO,OAAO,CAAC;AAAA,IACrC;AAEA,QAAI,MAAM,WAAW;AACnB,cAAQ,KAAK,OAAO,IAAI,WAAW,CAAC;AAAA,IACtC;AAEA,UAAM;AAAA,MACJ,OAAO,OAAO,QAAQ,MAAM,QAAQ,CAAC,IAAI,OAAO;AAAA,QAC9C,YAAY,MAAM,SAAS;AAAA,MAC7B,CAAC,GAAG,QAAQ,SAAS,IAAI,IAAI,OAAO,IAAI,MAAG,CAAC,IAAI,QAAQ,KAAK,QAAK,CAAC,KAAK,EAAE;AAAA,IAC5E;AAAA,EACF;AAEA,MAAI,OAAO,gBAAgB,GAAG;AAC5B,UAAM;AAAA,MACJ,OAAO,OAAO,IAAI,+CAA+C,CAAC;AAAA,IACpE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,cACP,SACA,QACQ;AACR,QAAM,WACJ,QAAQ,SAAS,SACb,OAAO;AAAA,IACL,GAAG,QAAQ,IAAI,GACb,QAAQ,WAAW,SAAY,IAAI,QAAQ,MAAM,KAAK,EACxD;AAAA,EACF,IACA;AAEN,SAAO,GAAG,OAAO,OAAO,GAAG,CAAC,IAAI,QAAQ,GAAG,QAAQ,OAAO;AAC5D;AAEA,SAAS,cACP,UACA,OACA,cACA,QACQ;AACR,MAAI,UAAU,GAAG;AACf,WAAO,OAAO,IAAI,QAAQ;AAAA,EAC5B;AAEA,SAAO,SAAS,eACZ,OAAO,MAAM,QAAQ,IACrB,OAAO,OAAO,QAAQ;AAC5B;AAEA,SAAS,YACP,OACA,QACQ;AACR,MAAI,UAAU,UAAU;AACtB,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B;AAEA,MAAI,UAAU,QAAQ;AACpB,WAAO,OAAO,IAAI,KAAK;AAAA,EACzB;AAEA,SAAO,OAAO,QAAQ,KAAK;AAC7B;AAEA,SAAS,SAAS,OAAe,WAA2B;AAC1D,SAAO,MAAM,UAAU,YACnB,QACA,GAAG,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC;AACtC;AAEA,SAAS,YAAY,OAAuB;AAC1C,MAAI,QAAQ,MAAO;AACjB,WAAO,GAAG,KAAK;AAAA,EACjB;AAEA,MAAI,QAAQ,OAAQ,MAAO;AACzB,WAAO,IAAI,QAAQ,MAAO,QAAQ,CAAC,CAAC;AAAA,EACtC;AAEA,SAAO,IAAI,SAAS,OAAQ,OAAQ,QAAQ,CAAC,CAAC;AAChD;AAEA,SAAS,eAAe,cAA8B;AACpD,MAAI,CAAC,OAAO,SAAS,YAAY,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,SAAO,eAAe,IAClB,GAAG,aAAa,QAAQ,CAAC,CAAC,QAC1B,GAAG,aAAa,QAAQ,CAAC,CAAC;AAChC;;;AD5SA,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB,KAAK;AACpC,IAAM,wBAAwB,MAAM;AAoD7B,SAAS,UAAU,UAAgC,CAAC,GAAW;AACpE,QAAM,eAAoC;AAAA,IACxC,SAAS,QAAQ,cAAc,WAAW;AAAA,IAC1C,cACE,QAAQ,cAAc,gBACtB,QAAQ,gBACR;AAAA,IACF,aACE,QAAQ,cAAc,eAAe,QAAQ,wBAAwB,CAAC;AAAA,EAC1E;AACA,QAAM,aAAgC;AAAA,IACpC,SAAS,QAAQ,YAAY,WAAW;AAAA,IACxC,cAAc,QAAQ,YAAY,gBAAgB;AAAA,IAClD,kBAAkB,QAAQ,YAAY,oBAAoB;AAAA,EAC5D;AACA,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,yBACJ,aAAa,gBAAgB;AAC/B,QAAM,yBACJ,WAAW,gBAAgB;AAC7B,QAAM,wBAAkC,CAAC;AACzC,QAAM,eACJ,OAAO,SAAS,sBAAsB,KACtC,0BAA0B,KAC1B,0BAA0B,IACtB,yBACA;AACN,QAAM,eACJ,OAAO,SAAS,sBAAsB,KACtC,OAAO,UAAU,sBAAsB,KACvC,yBAAyB,IACrB,yBACA;AACN,MAAI,OAAO;AACX,MAAI,SAAS,QAAQ,UAAU;AAE/B,MAAI,iBAAiB,wBAAwB;AAC3C,0BAAsB;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB,wBAAwB;AAC3C,0BAAsB;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAIA,eAAa,eAAe;AAC5B,aAAW,eAAe;AAE1B,QAAM,SAAS,aAAa,QAAQ,SAAS,QAAQ,SAAS;AAAA,IAC5D,SAAS;AAAA,EACX,CAAC;AAED,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IAET,OAAO,QAAQ;AACb,UAAI,QAAQ,WAAW,OAAO;AAC5B,eAAO,UAAU,CAAC;AAClB,eAAO,MAAM,YAAY;AAAA,MAC3B;AAAA,IACF;AAAA,IAEA,eAAe,QAAQ;AACrB,aAAO,OAAO;AACd,eACE,QAAQ,WACP,OAAO,SAAS,gBAAgB,OAAO,YAAY;AAAA,IACxD;AAAA,IAEA,MAAM,eAAe,gBAAgB,QAAQ;AAC3C,UAAI;AACF,cAAM,cAAc,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,YACE,eAAe,CAAC,OAAO,KAAK,cAAc,EAAE;AAAA,YAC5C,UAAU,CAAC,UAAU,KAAK,SAAS,KAAK;AAAA,YACxC,aAAa,CAAC,gBAAgB,KAAK,YAAY,WAAW;AAAA,UAC5D;AAAA,UACA;AAAA,YACE;AAAA,YACA,cAAc;AAAA,cACZ,SAAS,aAAa,WAAW;AAAA,cACjC;AAAA,cACA,aAAa,aAAa,eAAe,CAAC;AAAA,YAC5C;AAAA,YACA,YAAY;AAAA,cACV,SAAS,WAAW,WAAW;AAAA,cAC/B;AAAA,cACA,kBAAkB,WAAW,oBAAoB;AAAA,YACnD;AAAA,YACA,iBAAiB,QAAQ;AAAA,YACzB;AAAA,YACA;AAAA,YACA,qBAAqB,QAAQ,uBAAuB;AAAA,YACpD,mBAAmB,QAAQ,qBAAqB;AAAA,UAClD;AAAA,QACF;AAEA,mBAAW,WAAW,uBAAuB;AAC3C,eAAK,KAAK,gBAAgB,OAAO,EAAE;AACnC,sBAAY,OAAO,KAAK,OAAO;AAAA,QACjC;AAEA,YAAI,QAAQ,eAAe;AACzB,cAAI;AACF,kBAAM,QAAQ,cAAc,WAAW;AAAA,UACzC,SAAS,OAAO;AACd,kBAAM,UAAU,kCAAkC,cAAc,KAAK,CAAC;AACtE,wBAAY,OAAO,KAAK,OAAO;AAC/B,iBAAK,KAAK,gBAAgB,OAAO,EAAE;AAAA,UACrC;AAAA,QACF;AAEA,YACE,WACC,YAAY,iBAAiB,KAAK,YAAY,OAAO,SAAS,IAC/D;AACA,2BAAiB,WAAW;AAAA,QAC9B;AAAA,MACF,SAAS,OAAO;AACd,aAAK;AAAA,UACH,mEAAmE,cAAc,KAAK,CAAC;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAaA,eAAe,gBACb,QACA,aACA,SAC+B;AAC/B,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,EAAE,OAAO,WAAW,IAAI,MAAM;AAAA,IAClC;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AACA,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAC/C,QAAM,cAAc,IAAI,IAAI,SAAS;AACrC,QAAM,iBAAiB,oBAAI,IAAoB;AAE/C,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,WAAW;AAClB,qBAAe,IAAI,KAAK,MAAM,KAAK,SAAS;AAAA,IAC9C;AAAA,EACF;AACA,QAAM,YAAsC,CAAC;AAC7C,QAAM,kBAA0C,CAAC;AAEjD,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,CAAC,GAAG,KAAK,OAAO,EAAE,KAAK;AACvC,cAAU,KAAK,IAAI,IAAI;AACvB,oBAAgB,KAAK,IAAI,IAAI,QAAQ;AAAA,EACvC;AAEA,QAAM,iBAAiB,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,OAAO,CAAC;AACjE,QAAM,eAAe,QAAQ,aAAa,WAAW;AACrD,QAAM,cAAoC;AAAA,IACxC,QAAQ;AAAA,IACR,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,YAAY;AAAA,IACZ,cAAc,QAAQ,aAAa;AAAA,IACnC,QAAQ,QAAQ;AAAA,IAChB,cAAc;AAAA,MACZ,SAAS,QAAQ,aAAa;AAAA,MAC9B,cAAc,QAAQ,aAAa;AAAA,IACrC;AAAA,IACA,YAAY;AAAA,MACV,SAAS,QAAQ,WAAW;AAAA,MAC5B,cAAc,QAAQ,WAAW;AAAA,MACjC,kBAAkB,QAAQ,WAAW;AAAA,MACrC,aAAa;AAAA,MACb,iBAAiB;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,IACP,WAAW;AAAA,IACX;AAAA,IACA,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,sBAAsB;AAAA,IACtB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,sBAAsB;AAAA,IACtB,mBAAmB,CAAC;AAAA,IACpB,kBAAkB,CAAC;AAAA,IACnB,aAAa,CAAC;AAAA,IACd,eAAe;AAAA,IACf,OAAO,CAAC;AAAA,IACR,QAAQ,CAAC;AAAA,EACX;AAEA,QAAM,SAAS,oBAAI,IAA4B;AAC/C,QAAM,YAAsB,CAAC;AAC7B,QAAM,kBAA4B,CAAC;AACnC,QAAM,eAAe,oBAAI,IAAsB;AAE/C,aAAW,UAAU,OAAO,OAAO,MAAM,GAAG;AAC1C,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB;AAAA,IACF;AAEA,gBAAY,kBAAkB;AAE9B,QAAI,CAAC,QAAQ,OAAO,OAAO,QAAQ,GAAG;AACpC,kBAAY,oBAAoB;AAChC;AAAA,IACF;AAEA,QAAI,iBAAiB,OAAO,UAAU,YAAY,OAAO,MAAM,CAAC,GAAG;AACjE,kBAAY,oBAAoB;AAChC;AAAA,IACF;AAEA,QACE,QAAQ,uBACR,iBAAiB,YAAY,OAAO,MAAM,CAAC,GAC3C;AACA,kBAAY,oBAAoB;AAChC;AAAA,IACF;AAEA,UAAM,kBAAkB;AAAA,MACtB,GAAI,WAAW,IAAI,OAAO,QAAQ,KAAK;AAAA,IACzC,EAAE,KAAK;AAEP,UAAM,OAAO,aAAa,QAAQ,eAAe;AAEjD,QAAI,KAAK,OAAO;AACd,kBAAY,mBAAmB;AAC/B,kBAAY,OAAO,KAAK,GAAG,KAAK,QAAQ,KAAK,KAAK,KAAK,EAAE;AACzD,kBAAY,MAAM,KAAK,IAAI;AAC3B;AAAA,IACF;AAEA,UAAM,kBAAkB,YAAY,OAAO,MAAM;AAEjD,QAAI;AACF,YAAM,WAAW,YAAY;AAAA,QAC3B,YAAY;AAAA,QACZ;AAAA,QACA,cAAc;AAAA,UACZ,SAAS;AAAA,UACT,cAAc,QAAQ,aAAa;AAAA,UACnC,aAAa,QAAQ,aAAa;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,UACV,SAAS,QAAQ,WAAW;AAAA,UAC5B,cAAc,QAAQ,WAAW;AAAA,UACjC,kBAAkB,QAAQ,WAAW;AAAA,QACvC;AAAA,QACA,QAAQ,QAAQ;AAAA,MAClB,CAAC;AAED,YAAM,eAAe,SAAS,OAAO;AAAA,QACnC,CAAC,UAAU,MAAM,SAAS,UAAa,MAAM,gBAAgB;AAAA,MAC/D;AACA,YAAM,aAAa,SAAS,OAAO;AAAA,QACjC,CAAC,UAAU,MAAM,SAAS;AAAA,MAC5B;AACA,YAAM,iBACJ,aAAa,SAAS,KACtB,aAAa,KAAK,CAAC,UAAU,MAAM,cAAc;AACnD,YAAM,iBAAiB,iBAAiB,SAAY,aAAa,CAAC;AAElE,aAAO,SAAS,gBAAgB,OAAO;AACvC,WAAK,iBAAiB,OAAO,WAAW,OAAO,QAAQ,MAAM;AAE7D,UAAI,kBAAkB;AACtB,UAAI,wBAAwB;AAE5B,iBAAW,SAAS,cAAc;AAChC,cAAM,WAAW,UAAU;AAC3B,cAAM,WAAW,WACb,OAAO,WACP,aAAa,aAAa,GAAG,MAAM,IAAI,QAAQ,MAAM,GAAG;AAC5D,2BAAmB,MAAM;AAEzB,YAAI,CAAC,UAAU;AACb,oBAAU,KAAK,QAAQ;AACvB,0BAAgB,KAAK,QAAQ;AAAA,QAC/B;AAEA,oBAAY,iBAAiB,KAAK;AAAA,UAChC;AAAA,UACA,aAAa,MAAM;AAAA,UACnB,MAAM,MAAM;AAAA,UACZ,MAAM,MAAM;AAAA,UACZ,WAAW,MAAM;AAAA,UACjB,MAAM,MAAM;AAAA,UACZ,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,UACjB,gBAAgB,MAAM;AAAA,UACtB;AAAA,QACF,CAAC;AAED,YAAI,MAAM,gBAAgB;AACxB,sBAAY,WAAW,eAAe;AAAA,QACxC;AAEA,YAAI,MAAM,WAAW;AACnB,sBAAY,WAAW,mBAAmB;AAAA,QAC5C;AAAA,MACF;AAEA,UAAI,QAAQ,qBAAqB,gBAAgB;AAC/C,eAAO,SAAS,gBACb,IAAI,CAAC,aAAa,cAAc,SAAS,QAAQ,CAAC,IAAI,EACtD,KAAK,IAAI;AAAA,MACd;AAEA,iBAAW,SAAS,YAAY;AAC9B,cAAM,OAAO,MAAM;AAEnB,YAAI,CAAC,MAAM;AACT;AAAA,QACF;AAEA,cAAM,WAAW;AAAA,UACf;AAAA,UACA,GAAG,MAAM,IAAI;AAAA,UACb,MAAM;AAAA,QACR;AACA,iCAAyB,MAAM;AAC/B,cAAM,QAAQ,aAAa,IAAI,IAAI,KAAK,CAAC;AACzC,cAAM,KAAK,QAAQ;AACnB,qBAAa,IAAI,MAAM,KAAK;AAE5B,cAAM,cAAgC;AAAA,UACpC;AAAA,UACA;AAAA,UACA,WAAW,MAAM;AAAA,QACnB;AAEA,oBAAY,kBAAkB,KAAK,WAAW;AAC9C,oBAAY,iBAAiB,KAAK;AAAA,UAChC;AAAA,UACA,aAAa,MAAM;AAAA,UACnB,MAAM,MAAM;AAAA,UACZ;AAAA,UACA,WAAW,MAAM;AAAA,UACjB,MAAM,MAAM;AAAA,UACZ,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,UACjB,gBAAgB,MAAM;AAAA,UACtB,UAAU;AAAA,QACZ,CAAC;AAED,YAAI,MAAM,gBAAgB;AACxB,sBAAY,WAAW,eAAe;AAAA,QACxC;AAEA,YAAI,MAAM,WAAW;AACnB,sBAAY,WAAW,mBAAmB;AAAA,QAC5C;AAAA,MACF;AAEA,WAAK,iBAAiB,iBAClB,kBACA,OAAO,WAAW,OAAO,QAAQ,MAAM;AAC3C,WAAK,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA,eAAe,SAAS;AAAA,MAC1B;AAEA,iBAAW,QAAQ,SAAS,OAAO;AACjC,cAAM,WAAW,OAAO,IAAI,KAAK,QAAQ;AAEzC,YAAI,CAAC,YAAY,KAAK,mBAAmB,SAAS,kBAAkB;AAClE,iBAAO,IAAI,KAAK,UAAU,IAAI;AAAA,QAChC;AAAA,MACF;AAEA,kBAAY,iBAAiB,SAAS;AACtC,kBAAY,kBAAkB;AAC9B,kBAAY,wBAAwB;AAAA,IACtC,SAAS,OAAO;AACd,kBAAY,OAAO;AAAA,QACjB,GAAG,KAAK,QAAQ,6BAA6B,cAAc,KAAK,CAAC;AAAA,MACnE;AAAA,IACF;AAEA,gBAAY,qBAAqB;AACjC,gBAAY,wBAAwB,KAAK;AACzC,gBAAY,uBAAuB,KAAK;AACxC,gBAAY,kBAAkB,KAAK;AACnC,gBAAY,cAAc,KAAK;AAC/B,gBAAY,MAAM,KAAK,IAAI;AAAA,EAC7B;AAEA,MAAI,UAAU,SAAS,GAAG;AACxB,0BAAsB,QAAQ,WAAW,QAAQ,IAAI;AAAA,EACvD;AAEA,MAAI,aAAa,OAAO,GAAG;AACzB,0BAAsB,QAAQ,cAAc,gBAAgB,QAAQ,IAAI;AAAA,EAC1E;AAEA,cAAY,cAAc,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,IAAK,CAAC,MAAM,UACzD,KAAK,SAAS,cAAc,MAAM,QAAQ;AAAA,EAC5C;AACA,cAAY,aAAa,QAAQ,YAAY,IAAI,IAAI,SAAS;AAE9D,SAAO;AACT;AAEA,SAAS,aACP,aACA,MACA,QACQ;AACR,QAAM,cAAc,YAAY,SAAS;AAAA,IACvC,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,YAAY,YAAY,WAAW;AAC5C;AAEA,SAAS,sBACP,QACA,WACA,aACA,MACM;AACN,QAAM,iBAAiB,KAAK,SAAS,GAAG,IAAI,OAAO,GAAG,IAAI;AAE1D,aAAW,CAAC,MAAM,SAAS,KAAK,WAAW;AACzC,QAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,IACF;AAEA,UAAM,YAAY,YAAY,IAAI,IAAI;AACtC,UAAM,QAAQ,UAAU,IAAI,CAAC,aAAa,GAAG,cAAc,GAAG,QAAQ,EAAE;AACxE,UAAM,aAAa,kBAAkB,QAAQ,IAAI;AACjD,UAAM,SAAS,eAAe,YAAY,OAAO,SAAS,IAAI;AAE9D,QAAI,YAAY,MAAM,GAAG;AACvB,YAAM,OAAO,MACV;AAAA,QACC,CAAC,SACC,oCAAoC,IAAI;AAAA,MAC5C,EACC,KAAK,IAAI;AAEZ,UAAI,CAAC,OAAO,OAAO,SAAS,IAAI,KAAK,OAAO,OAAO,SAAS,SAAS,GAAG;AACtE,eAAO,SAAS,OAAO,OAAO,QAAQ,WAAW,GAAG,IAAI;AAAA,UAAa;AAAA,MACvE;AACA;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ,MAAM,GAAG;AACpB;AAAA,IACF;AAEA,UAAM,UAAU,qCAAqC,KAAK,UAAU,KAAK,CAAC;AAAA;AAE1E,WAAO,OAAO,UAAU,OAAO;AAAA,EACjC;AACF;AAEA,SAAS,sBACP,QACA,WACA,MACM;AACN,QAAM,iBAAiB,KAAK,SAAS,GAAG,IAAI,OAAO,GAAG,IAAI;AAC1D,QAAM,OAAO,UACV;AAAA,IACC,CAAC,aACC,oCAAoC,cAAc,GAAG,QAAQ;AAAA,EACjE,EACC,KAAK,IAAI;AAEZ,aAAW,UAAU,OAAO,OAAO,MAAM,GAAG;AAC1C,QAAI,CAAC,YAAY,MAAM,KAAK,OAAO,OAAO,SAAS,IAAI,GAAG;AACxD;AAAA,IACF;AAEA,QAAI,OAAO,OAAO,SAAS,SAAS,GAAG;AACrC,aAAO,SAAS,OAAO,OAAO,QAAQ,WAAW,GAAG,IAAI;AAAA,UAAa;AAAA,IACvE;AAAA,EACF;AACF;AAEA,SAAS,kBACP,QACA,MACS;AACT,QAAM,QACJ,SAAS,UACL,CAAC,YAAY,IACb;AAAA,IACE,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI;AAAA,IACZ,GAAG,IAAI;AAAA,IACP,GAAG,IAAI;AAAA,EACT;AAEN,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,OAAO,IAAI;AAE1B,QAAI,YAAY,MAAM,GAAG;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,YACP,OAC8D;AAC9D,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAMlB,SACE,UAAU,SAAS,WACnB,OAAO,UAAU,aAAa,YAC9B,UAAU,SAAS,SAAS,OAAO,KACnC,OAAO,UAAU,WAAW;AAEhC;AAEA,SAAS,aACP,QACA,iBACoB;AACpB,QAAM,oBAAoB,YAAY,IAAI;AAE1C,MAAI;AACF,UAAM,MAAM,YAAY,OAAO,MAAM;AACrC,UAAM,kBAAkB,OAAO,WAAW,KAAK,MAAM;AACrD,UAAM,WAAW,WAAW,GAAG;AAC/B,UAAM,WAAW,sBAAsB,QAAQ;AAE/C,QAAI,mBAAmB,uBAAuB;AAC5C,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SACE,4BAA4BA,aAAY,qBAAqB,CAAC;AAAA,MAElE,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,UAAU,OAAO;AAAA,MACjB;AAAA,MACA,gBAAgB;AAAA,MAChB,eAAe,SAAS,MAAM;AAAA,MAC9B,WAAW,SAAS,MAAM;AAAA,MAC1B,kBAAkB,SAAS,MAAM;AAAA,MACjC,2BAA2B,SAAS,MAAM;AAAA,MAC1C,kBAAkB,SAAS,MAAM;AAAA,MACjC,eAAe,SAAS,MAAM;AAAA,MAC9B,gBAAgB,SAAS,MAAM;AAAA,MAC/B,oBAAoB,SAAS,SAAS;AAAA,MACtC,YAAY,QAAQ,YAAY,IAAI,IAAI,iBAAiB;AAAA,MACzD;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,UAAU,OAAO;AAAA,MACjB,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,WAAW;AAAA,MACX,kBAAkB;AAAA,MAClB,2BAA2B;AAAA,MAC3B,kBAAkB;AAAA,MAClB,eAAe;AAAA,MACf,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,YAAY,QAAQ,YAAY,IAAI,IAAI,iBAAiB;AAAA,MACzD;AAAA,MACA,UAAU,CAAC;AAAA,MACX,OAAO,cAAc,KAAK;AAAA,IAC5B;AAAA,EACF;AACF;AAEA,eAAe,aACb,QACA,eACA,iBAIC;AACD,QAAM,SAAS,OAAO,OAAO,MAAM,EAAE,OAAO,OAAO;AACnD,QAAM,mBAAmB,IAAI;AAAA,IAC3B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,UAAU,KAAK,CAAC;AAAA,EAC/C;AACA,QAAM,QAAQ,oBAAI,IAAsB;AACxC,QAAM,iBAAiB,IAAI;AAAA,IACzB,OAAO,OAAO,CAAC,UAAU,MAAM,OAAO,EAAE,IAAI,CAAC,UAAU,MAAM,QAAQ;AAAA,EACvE;AAEA,aAAW,SAAS,OAAO,OAAO,CAAC,UAAU,MAAM,OAAO,GAAG;AAC3D,QAAI,oBAAoB,KAAK,GAAG;AAC9B;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,MAAM,kBAAkB,WAAW,MAAM,cAAc,GAAG;AAC5D,UAAI;AACF;AAAA,UACE,MAAM,SAAS,MAAM,gBAAgB,MAAM;AAAA,UAC3C,MAAM;AAAA,QACR;AAAA,MACF,QAAQ;AAAA,MAGR;AAAA,IACF;AAEA,UAAM,cAAc,MAAM,eACvB,IAAI,CAAC,aAAa,iBAAiB,IAAI,QAAQ,CAAC,EAChD,OAAO,CAAC,UAAkC,UAAU,MAAS;AAEhE,QAAI,YAAY,SAAS,GAAG;AAK1B,iBAAW,cAAc,aAAa;AACpC,cAAMC,QAAiB;AAAA,UACrB,MAAM,eAAe,cAAc,cAAc,UAAU,CAAC,GAAG,KAAK;AAAA,UACpE,SAAS,IAAI,IAAI,MAAM,OAAO;AAAA,UAC9B,UAAU,IAAI,IAAI,MAAM,QAAQ;AAAA,UAChC,WAAW,WAAW;AAAA,QACxB;AACA,cAAM,QAAQ;AAAA,UACZ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,mBAAW,aAAa,MAAM,SAAS;AACrC,UAAAA,MAAK,QAAQ,IAAI,SAAS;AAAA,QAC5B;AAEA,mBAAW,WAAW,MAAM,UAAU;AACpC,UAAAA,MAAK,SAAS,IAAI,OAAO;AAAA,QAC3B;AAEA,cAAM,IAAIA,MAAK,MAAMA,KAAI;AAAA,MAC3B;AAEA;AAAA,IACF;AAEA,UAAM,OAAiB;AAAA,MACrB,MAAM,eAAe,cAAc,YAAY,KAAK,CAAC,GAAG,KAAK;AAAA,MAC7D,SAAS,IAAI,IAAI,MAAM,OAAO;AAAA,MAC9B,UAAU,IAAI,IAAI,MAAM,QAAQ;AAAA,MAChC,WAAW,MAAM;AAAA,IACnB;AAEA,UAAM,IAAI,KAAK,MAAM,IAAI;AAAA,EAC3B;AAEA,MAAI,iBAAiB;AACnB,eAAW,CAAC,SAAS,OAAO,KAAK,OAAO,QAAQ,eAAe,GAAG;AAChE,YAAM,OAAO,QAAQ,KAAK;AAE1B,UAAI,KAAK,WAAW,GAAG;AACrB;AAAA,MACF;AAEA,UAAI,OAAO,MAAM,IAAI,IAAI;AAEzB,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,UACL;AAAA,UACA,SAAS,oBAAI,IAAI;AAAA,UACjB,UAAU,oBAAI,IAAI;AAAA,UAClB,WAAW;AAAA,QACb;AACA,cAAM,IAAI,MAAM,IAAI;AAAA,MACtB;AAEA,iBAAW,aAAa,SAAS;AAC/B,aAAK,QAAQ,IAAI,UAAU,YAAY,CAAC;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,oBAAI,IAAyB;AAEhD,aAAW,QAAQ,MAAM,OAAO,GAAG;AACjC,eAAW,WAAW,KAAK,UAAU;AACnC,YAAM,SAAS,WAAW,IAAI,OAAO,KAAK,oBAAI,IAAY;AAC1D,aAAO,IAAI,KAAK,IAAI;AACpB,iBAAW,IAAI,SAAS,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAAA,IACzB;AAAA,EACF;AACF;AAEA,SAAS,oBACP,YACA,kBACA,eACA,uBACA,gBAAqC,oBAAI,IAAY,GAIrD;AACA,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,QAAQ,CAAC,WAAW,QAAQ;AAElC,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,WAAW,MAAM,IAAI;AAE3B,QAAI,CAAC,YAAY,QAAQ,IAAI,QAAQ,KAAK,cAAc,IAAI,QAAQ,GAAG;AACrE;AAAA,IACF;AAEA,YAAQ,IAAI,QAAQ;AAEpB,UAAM,QAAQ,iBAAiB,IAAI,QAAQ;AAE3C,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,gBAAY,MAAM,MAAM,OAAO;AAE/B,eAAW,YAAY,OAAO,KAAK,MAAM,OAAO,GAAG;AACjD,UAAI,cAAc,QAAQ,GAAG;AAC3B;AAAA,MACF;AAEA,YAAM,aAAa,cAAc,QAAQ;AAEzC,UAAI,YAAY,MAAM;AACpB,oBAAY,WAAW,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAEA,eAAW,WAAW,MAAM,cAAc,eAAe,CAAC,GAAG;AAC3D,eAAS,IAAI,OAAO;AAAA,IACtB;AAEA,UAAM,KAAK,GAAG,MAAM,OAAO;AAE3B,QAAI,uBAAuB;AACzB,YAAM,KAAK,GAAG,MAAM,cAAc;AAAA,IACpC;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,SAAS;AAC7B;AAEA,SAAS,YAAY,QAAgB,SAA4B;AAC/D,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,eAAW,SAAS,OAAO,SAAS,OAAO,GAAG;AAC5C,YAAM,QAAQ,MAAM,CAAC,KAAK,MAAM,CAAC,KAAK,MAAM,CAAC;AAE7C,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AAEA,iBAAW,SAAS,MAAM,MAAM,KAAK,GAAG;AACtC,YAAI,aAAa,KAAK,GAAG;AACvB,kBAAQ,IAAI,MAAM,YAAY,CAAC;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,aAAa,OAAwB;AAC5C,MAAI,CAAC,SAAS,MAAM,SAAS,KAAK;AAChC,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,KAAK,KAAK,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,SAAO,YAAY,KAAK,KAAK;AAC/B;AAEA,SAAS,oBAAoB,OAA+B;AAC1D,QAAM,OAAO,YAAY,KAAK;AAE9B,SACE,KAAK,WAAW,GAAG,KACnB,KAAK,WAAW,OAAO,KACvB,KAAK,SAAS,kBAAkB;AAEpC;AAEA,SAAS,cAAc,MAAsB;AAC3C,QAAM,aAAa,KAChB,KAAK,EACL,YAAY,EACZ,QAAQ,eAAe,EAAE,EACzB,QAAQ,UAAU,EAAE;AAEvB,SAAO,cAAc;AACvB;AAEA,SAAS,cAAc,OAA8B;AACnD,QAAM,OAAO,YAAY,KAAK,EAAE,YAAY;AAE5C,SAAO,KAAK,WAAW,OAAO,IAAI,KAAK,MAAM,QAAQ,MAAM,IAAI;AACjE;AAEA,SAAS,iBAAiB,UAAkB,KAAsB;AAChE,MAAI,+CAA+C,KAAK,QAAQ,GAAG;AACjE,WAAO;AAAA,EACT;AAKA,SAAO,0CAA0C,KAAK,GAAG;AAC3D;AAEA,SAAS,iBAAiB,KAAsB;AAC9C,SAAO,uBAAuB,KAAK,GAAG;AACxC;AAEA,SAAS,YAAY,OAA8B;AACjD,MAAI,MAAM,KAAK,SAAS,GAAG;AACzB,WAAO,MAAM;AAAA,EACf;AAEA,MAAI,MAAM,gBAAgB;AACxB,WAAO,SAAS,MAAM,gBAAgB,QAAQ,MAAM,cAAc,CAAC;AAAA,EACrE;AAEA,SAAO,MAAM,SAAS,QAAQ,YAAY,EAAE;AAC9C;AAEA,SAAS,eAAe,MAAc,OAAsC;AAC1E,QAAM,aAAa,KAAK,KAAK,KAAK;AAElC,MAAI,CAAC,MAAM,IAAI,UAAU,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AAEZ,SAAO,MAAM,IAAI,GAAG,UAAU,IAAI,KAAK,EAAE,GAAG;AAC1C,aAAS;AAAA,EACX;AAEA,SAAO,GAAG,UAAU,IAAI,KAAK;AAC/B;AAEA,SAAS,WAAW,OAAuC;AACzD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAMlB,SACE,UAAU,SAAS,WACnB,OAAO,UAAU,aAAa,YAC9B,UAAU,SAAS,SAAS,MAAM,MACjC,OAAO,UAAU,WAAW,YAC3B,UAAU,kBAAkB;AAElC;AAEA,SAAS,QAAQ,OAAwC;AACvD,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAYlB,SACE,UAAU,SAAS,WACnB,OAAO,UAAU,aAAa,YAC9B,OAAO,UAAU,SAAS,YAC1B,OAAO,UAAU,YAAY,aAC7B,OAAO,UAAU,SAAS,YAC1B,OAAO,UAAU,YAAY,YAC7B,UAAU,YAAY,QACtB,MAAM,QAAQ,UAAU,OAAO,KAC/B,MAAM,QAAQ,UAAU,cAAc;AAE1C;AAEA,SAAS,cAAc,UAA2B;AAChD,SAAO,4CAA4C,KAAK,QAAQ;AAClE;AAEA,SAAS,WAAW,UAA2B;AAC7C,SAAO,kBAAkB,KAAK,QAAQ;AACxC;AAEA,SAAS,sBACP,UACmB;AACnB,SAAO,SAAS,SAAS,IAAI,CAAC,aAAa;AAAA,IACzC,MAAM;AAAA,IACN,SAAS,QAAQ;AAAA,IACjB,GAAI,QAAQ,WACR;AAAA,MACE,MAAM,QAAQ,SAAS;AAAA,MACvB,QAAQ,QAAQ,SAAS;AAAA,IAC3B,IACA,CAAC;AAAA,EACP,EAAE;AACJ;AAEA,SAAS,YAAY,QAAqC;AACxD,SAAO,OAAO,WAAW,WACrB,SACA,OAAO,KAAK,MAAM,EAAE,SAAS,MAAM;AACzC;AAEA,SAASD,aAAY,OAAuB;AAC1C,MAAI,QAAQ,MAAO;AACjB,WAAO,GAAG,KAAK;AAAA,EACjB;AAEA,MAAI,QAAQ,OAAQ,MAAO;AACzB,WAAO,IAAI,QAAQ,MAAO,QAAQ,CAAC,CAAC;AAAA,EACtC;AAEA,SAAO,IAAI,SAAS,OAAQ,OAAQ,QAAQ,CAAC,CAAC;AAChD;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,KAAK,MAAM,QAAQ,GAAK,IAAI;AACrC;AAEA,SAAS,cAAc,OAAwB;AAC7C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;","names":["formatBytes","page"]}
package/package.json CHANGED
@@ -1,7 +1,29 @@
1
1
  {
2
2
  "name": "@zealakit/css-doctor-vite",
3
- "version": "1.0.0",
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
- "picocolors": "^1.1.1",
27
- "@zealakit/css-doctor-binding": "1.0.0"
48
+ "@zealakit/css-doctor-binding": "1.1.0",
49
+ "picocolors": "^1.1.1"
28
50
  },
29
51
  "peerDependencies": {
30
52
  "vite": ">=4.0.0"