@motion-proto/live-tokens 0.94.3 → 0.96.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.
Files changed (105) hide show
  1. package/.claude/skills/live-tokens-create-page/SKILL.md +7 -3
  2. package/CHANGELOG.md +115 -0
  3. package/README.md +6 -6
  4. package/dist-plugin/{chunk-7XSUHJUH.js → chunk-4J6JPSVS.js} +53 -2
  5. package/dist-plugin/{chunk-W5VQV32K.js → chunk-GYRULB2X.js} +1 -1
  6. package/dist-plugin/{chunk-ONYAIXCZ.js → chunk-QQASYPW7.js} +32 -9
  7. package/dist-plugin/index.cjs +598 -17
  8. package/dist-plugin/index.d.cts +9 -1
  9. package/dist-plugin/index.d.ts +9 -1
  10. package/dist-plugin/index.js +513 -6
  11. package/dist-plugin/migrateData/index.cjs +32 -9
  12. package/dist-plugin/migrateData/index.js +2 -2
  13. package/dist-plugin/setColors/index.cjs +32 -22
  14. package/dist-plugin/setColors/index.js +2 -15
  15. package/dist-plugin/setGeometry/index.cjs +32 -9
  16. package/dist-plugin/setGeometry/index.js +1 -1
  17. package/dist-plugin/tokensCssMigrations/index.cjs +53 -2
  18. package/dist-plugin/tokensCssMigrations/index.d.cts +9 -2
  19. package/dist-plugin/tokensCssMigrations/index.d.ts +9 -2
  20. package/dist-plugin/tokensCssMigrations/index.js +1 -1
  21. package/package.json +8 -3
  22. package/src/demo/Demo.svelte +39 -5
  23. package/src/demo/DemoBar.svelte +23 -5
  24. package/src/demo/FloatingTokenTags.css +33 -4
  25. package/src/demo/FloatingTokenTags.svelte +81 -68
  26. package/src/demo/Section.svelte +1 -7
  27. package/src/demo/SourceLinks.svelte +5 -4
  28. package/src/demo/TestingLoops.svelte +167 -35
  29. package/src/demo/evalResults.ts +7 -7
  30. package/src/demo/sections/SectionClaude.svelte +20 -13
  31. package/src/demo/sections/SectionFooter.svelte +4 -5
  32. package/src/demo/sections/SectionGetStarted.svelte +5 -6
  33. package/src/demo/sections/SectionHero.svelte +43 -23
  34. package/src/demo/sections/SectionKit.svelte +141 -45
  35. package/src/demo/sections/SectionLayers.svelte +3 -3
  36. package/src/demo/sections/SectionOffering.svelte +8 -23
  37. package/src/editor/bootstrap.ts +12 -6
  38. package/src/editor/component-editor/ImageEditor.svelte +1 -1
  39. package/src/editor/component-editor/ImageLightboxEditor.svelte +3 -4
  40. package/src/editor/component-editor/registration.ts +36 -0
  41. package/src/editor/component-editor/registry.ts +5 -12
  42. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +11 -2
  43. package/src/editor/component-editor/scaffolding/StateBlock.svelte +7 -0
  44. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +1 -2
  45. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +17 -2
  46. package/src/editor/core/store/editorPersistence.ts +6 -1
  47. package/src/editor/core/store/editorRenderer.ts +1 -4
  48. package/src/editor/core/store/editorStore.ts +5 -9
  49. package/src/editor/core/store/editorTypes.ts +2 -2
  50. package/src/editor/core/themes/migrations/2026-10-15-responsive-columns.ts +40 -0
  51. package/src/editor/core/themes/migrations/index.ts +2 -0
  52. package/src/editor/core/themes/slices/columns.ts +112 -42
  53. package/src/editor/docs/Docs.svelte +25 -22
  54. package/src/editor/docs/chapters.ts +1 -0
  55. package/src/editor/docs/content/editing-tokens.md +5 -3
  56. package/src/editor/docs/content/production-css.md +116 -0
  57. package/src/editor/docs/content/themes-workflow.md +2 -0
  58. package/src/editor/docs/content.generated.ts +3 -2
  59. package/src/editor/index.ts +2 -1
  60. package/src/editor/overlay/LiveEditorOverlay.svelte +67 -19
  61. package/src/editor/overlay/LiveTokensRouter.svelte +8 -4
  62. package/src/editor/pages/Editor.svelte +15 -1
  63. package/src/editor/pages/EditorShell.svelte +312 -99
  64. package/src/editor/skill-atlas/SkillAtlas.svelte +111 -24
  65. package/src/editor/skill-atlas/TreeCanvas.svelte +14 -0
  66. package/src/editor/skill-atlas/skillSources.generated.ts +1 -1
  67. package/src/editor/skill-atlas/trees/create-page.ts +24 -24
  68. package/src/editor/skill-atlas/wireLayout.ts +62 -0
  69. package/src/editor/ui/BezierCurveEditor.svelte +3 -0
  70. package/src/editor/ui/FontStackEditor.svelte +2 -2
  71. package/src/editor/ui/PaletteEditor.svelte +64 -6
  72. package/src/editor/ui/UIPaletteSelector.svelte +2 -0
  73. package/src/editor/ui/colors/ColorsTab.svelte +5 -2
  74. package/src/editor/ui/palette/OverridesPanel.svelte +1 -0
  75. package/src/editor/ui/palette/ScaleCurveEditor.svelte +127 -18
  76. package/src/editor/ui/sections/ColumnsSection.svelte +79 -49
  77. package/src/editor/ui/sections/ShadowsSection.svelte +14 -0
  78. package/src/editor/ui/sections/WashesSection.svelte +11 -0
  79. package/src/editor/ui/sketch/SketchTab.svelte +1 -1
  80. package/src/live-tokens/data/colors-and-type/autumn.json +1 -4
  81. package/src/live-tokens/data/colors-and-type/default.json +1 -4
  82. package/src/live-tokens/data/colors-and-type/halloween.json +1 -4
  83. package/src/live-tokens/data/colors-and-type/midnight-study.json +1 -4
  84. package/src/live-tokens/data/colors-and-type/ocean.json +1 -4
  85. package/src/live-tokens/data/colors-and-type/royal-velvet.json +1 -4
  86. package/src/live-tokens/data/colors-and-type/sketchy.json +1 -4
  87. package/src/live-tokens/data/colors-and-type/spring-meadow.json +1 -4
  88. package/src/live-tokens/data/colors-and-type/sunset.json +1 -4
  89. package/src/live-tokens/data/themes/autumn.json +1 -4
  90. package/src/live-tokens/data/themes/halloween.json +1 -4
  91. package/src/live-tokens/data/themes/midnight-study.json +1 -4
  92. package/src/live-tokens/data/themes/ocean.json +1 -4
  93. package/src/live-tokens/data/themes/royal-velvet.json +1 -4
  94. package/src/live-tokens/data/themes/sketchy.json +1 -4
  95. package/src/live-tokens/data/themes/spring-meadow.json +1 -4
  96. package/src/live-tokens/data/themes/sunset.json +1 -4
  97. package/src/live-tokens/data/tokens.generated.css +1 -4
  98. package/src/system/components/ImageLightbox.svelte +9 -2
  99. package/src/system/components/SectionDivider.svelte +4 -0
  100. package/src/system/styles/tokens.css +30 -4
  101. package/template/src/main.ts +2 -2
  102. package/template/src/pages/Home.svelte +11 -8
  103. package/template/vite.config.ts +7 -3
  104. package/src/system/assets/offering.webp +0 -0
  105. /package/dist-plugin/{chunk-O6GQ6GBH.js → chunk-A4TBP4MM.js} +0 -0
@@ -2043,6 +2043,28 @@ var colorsAndTypeMigration_2026_09_21_washColorAndOpacity = {
2043
2043
  }
2044
2044
  };
2045
2045
 
2046
+ // src/editor/core/themes/migrations/2026-10-15-responsive-columns.ts
2047
+ var RENAMES8 = {
2048
+ "--columns-gutter": "--columns-desktop-gutter",
2049
+ "--columns-margin": "--columns-desktop-margin"
2050
+ };
2051
+ var SHIPPED = {
2052
+ "--columns-count": ["12"],
2053
+ "--columns-gutter": ["32px"],
2054
+ "--columns-margin": ["0px", "0"]
2055
+ };
2056
+ var colorsAndTypeMigration_2026_10_15_responsiveColumns = {
2057
+ id: "2026-10-15-responsive-columns",
2058
+ fromVersion: 9,
2059
+ toVersion: 10,
2060
+ appliesTo: "colors-and-type",
2061
+ apply(rawVars) {
2062
+ return Object.fromEntries(
2063
+ Object.entries(rawVars).filter(([name, value]) => !SHIPPED[name]?.includes(value.trim())).map(([name, value]) => [RENAMES8[name] ?? name, value])
2064
+ );
2065
+ }
2066
+ };
2067
+
2046
2068
  // src/editor/core/themes/migrations/2026-09-21-scrim-surface.ts
2047
2069
  var STOPS2 = {
2048
2070
  "--scrim-opacity-low": "--scrim-low",
@@ -2081,7 +2103,7 @@ var componentMigration_2026_09_21_scrimSurface = {
2081
2103
  };
2082
2104
 
2083
2105
  // src/editor/core/themes/migrations/2026-09-13-cornerbadge-prefix.ts
2084
- var RENAMES8 = {
2106
+ var RENAMES9 = {
2085
2107
  cornerbadge: {
2086
2108
  "--corner-badge-margin": "--cornerbadge-margin",
2087
2109
  "--corner-badge-outer-radius": "--cornerbadge-outer-radius",
@@ -2131,7 +2153,7 @@ var componentMigration_2026_09_13_cornerbadgePrefix = {
2131
2153
  toVersion: 32,
2132
2154
  appliesTo: "component-config",
2133
2155
  apply(rawVars, meta) {
2134
- const renames = meta.component ? RENAMES8[meta.component] : void 0;
2156
+ const renames = meta.component ? RENAMES9[meta.component] : void 0;
2135
2157
  if (!renames) return { ...rawVars };
2136
2158
  const out = {};
2137
2159
  for (const [key, value] of Object.entries(rawVars)) {
@@ -2142,7 +2164,7 @@ var componentMigration_2026_09_13_cornerbadgePrefix = {
2142
2164
  };
2143
2165
 
2144
2166
  // src/editor/core/themes/migrations/2026-09-13-toggle-label.ts
2145
- var RENAMES9 = {
2167
+ var RENAMES10 = {
2146
2168
  toggle: {
2147
2169
  "--toggle-label-text": "--toggle-label",
2148
2170
  "--toggle-disabled-label-text": "--toggle-disabled-label"
@@ -2154,7 +2176,7 @@ var componentMigration_2026_09_13_toggleLabel = {
2154
2176
  toVersion: 33,
2155
2177
  appliesTo: "component-config",
2156
2178
  apply(rawVars, meta) {
2157
- const renames = meta.component ? RENAMES9[meta.component] : void 0;
2179
+ const renames = meta.component ? RENAMES10[meta.component] : void 0;
2158
2180
  if (!renames) return { ...rawVars };
2159
2181
  const out = {};
2160
2182
  for (const [key, value] of Object.entries(rawVars)) {
@@ -2165,7 +2187,7 @@ var componentMigration_2026_09_13_toggleLabel = {
2165
2187
  };
2166
2188
 
2167
2189
  // src/editor/core/themes/migrations/2026-09-13-collapsiblesection-open.ts
2168
- var RENAMES10 = {
2190
+ var RENAMES11 = {
2169
2191
  collapsiblesection: {
2170
2192
  "--collapsiblesection-chromeless-expanded-padding": "--collapsiblesection-chromeless-open-padding",
2171
2193
  "--collapsiblesection-hairline-expanded-padding": "--collapsiblesection-hairline-open-padding",
@@ -2179,7 +2201,7 @@ var componentMigration_2026_09_13_collapsiblesectionOpen = {
2179
2201
  toVersion: 34,
2180
2202
  appliesTo: "component-config",
2181
2203
  apply(rawVars, meta) {
2182
- const renames = meta.component ? RENAMES10[meta.component] : void 0;
2204
+ const renames = meta.component ? RENAMES11[meta.component] : void 0;
2183
2205
  if (!renames) return { ...rawVars };
2184
2206
  const out = {};
2185
2207
  for (const [key, value] of Object.entries(rawVars)) {
@@ -2206,7 +2228,7 @@ var BADGE_SUFFIXES = [
2206
2228
  "icon-size"
2207
2229
  ];
2208
2230
  var CORNERBADGE_SUFFIXES = ["surface", "border", "text"];
2209
- var RENAMES11 = {
2231
+ var RENAMES12 = {
2210
2232
  badge: Object.fromEntries(
2211
2233
  BADGE_SUFFIXES.map((s) => [`--badge-primary-${s}`, `--badge-brand-${s}`])
2212
2234
  ),
@@ -2220,7 +2242,7 @@ var componentMigration_2026_09_13_badgeBrand = {
2220
2242
  toVersion: 35,
2221
2243
  appliesTo: "component-config",
2222
2244
  apply(rawVars, meta) {
2223
- const renames = meta.component ? RENAMES11[meta.component] : void 0;
2245
+ const renames = meta.component ? RENAMES12[meta.component] : void 0;
2224
2246
  if (!renames) return { ...rawVars };
2225
2247
  const out = {};
2226
2248
  for (const [key, value] of Object.entries(rawVars)) {
@@ -2278,7 +2300,8 @@ var MIGRATIONS = [
2278
2300
  componentMigration_2026_09_20_imagelightboxScrim,
2279
2301
  componentMigration_2026_09_20_scrimColorAndOpacity,
2280
2302
  colorsAndTypeMigration_2026_09_21_washColorAndOpacity,
2281
- componentMigration_2026_09_21_scrimSurface
2303
+ componentMigration_2026_09_21_scrimSurface,
2304
+ colorsAndTypeMigration_2026_10_15_responsiveColumns
2282
2305
  ];
2283
2306
  function countFor(kind) {
2284
2307
  return MIGRATIONS.filter((m) => m.appliesTo === kind).length;
@@ -3561,7 +3584,7 @@ function setTokenValue(css, name, value, opts = {}) {
3561
3584
  }
3562
3585
  return changed ? lines.join("\n") : css;
3563
3586
  }
3564
- function appendMediaBlock(css, query, entries) {
3587
+ function appendMediaBlock(css, query, entries, opts = {}) {
3565
3588
  const lines = css.split("\n");
3566
3589
  const at = query.trim();
3567
3590
  const blocks = findTopLevelBlocks(lines, (line) => mediaQueryOf(line) === at);
@@ -3573,6 +3596,12 @@ function appendMediaBlock(css, query, entries) {
3573
3596
  const media = blocks.find((b) => b.end > b.start);
3574
3597
  if (!media) {
3575
3598
  const block = [`@media ${at} {`, " :root {", ...declarationLines(missing, " "), " }", "}", ""];
3599
+ const before = opts.before?.trim();
3600
+ const next = before === void 0 ? void 0 : findTopLevelBlocks(lines, (line) => mediaQueryOf(line) === before)[0];
3601
+ if (next) {
3602
+ lines.splice(next.start, 0, ...block);
3603
+ return lines.join("\n");
3604
+ }
3576
3605
  while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
3577
3606
  return [...lines, "", ...block].join("\n");
3578
3607
  }
@@ -3818,7 +3847,7 @@ var tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions = {
3818
3847
  };
3819
3848
 
3820
3849
  // vite-plugin/tokensCssMigrations/migrations/2026-07-20-line-height-rename.ts
3821
- var RENAMES12 = [
3850
+ var RENAMES13 = [
3822
3851
  ["--line-height-xs", "--line-height-none"],
3823
3852
  ["--line-height-sm", "--line-height-tighter"],
3824
3853
  ["--line-height-md", "--line-height-normal"],
@@ -3838,7 +3867,7 @@ var tokensCssMigration_2026_07_20_lineHeightRename = {
3838
3867
  description: "Reshape --line-height-{xs..xl} to leading vocabulary (none/tightest/tighter/tight/normal/relaxed); retire the 2.0 slot",
3839
3868
  apply(css) {
3840
3869
  let out = css;
3841
- for (const [oldName, newName] of RENAMES12) out = renameToken2(out, oldName, newName);
3870
+ for (const [oldName, newName] of RENAMES13) out = renameToken2(out, oldName, newName);
3842
3871
  out = removeToken(out, "--line-height-xl");
3843
3872
  out = ensureScale(out, {
3844
3873
  anchorPrefixes: ["--line-height-", "--font-size-", "--font-weight-", "--font-"],
@@ -4072,7 +4101,7 @@ var tokensCssMigration_2026_08_27_editorialLargeSteps = {
4072
4101
  };
4073
4102
 
4074
4103
  // vite-plugin/tokensCssMigrations/migrations/2026-09-01-scrim-rename.ts
4075
- var RENAMES13 = [
4104
+ var RENAMES14 = [
4076
4105
  ["--overlay-low", "--scrim-low"],
4077
4106
  ["--overlay-high", "--scrim-high"],
4078
4107
  ["--overlay", "--scrim"]
@@ -4083,7 +4112,7 @@ var tokensCssMigration_2026_09_01_scrimRename = {
4083
4112
  description: "Rename --overlay-{low,base,high} to --scrim-*; a scrim dims what is behind it",
4084
4113
  apply(css) {
4085
4114
  let out = css;
4086
- for (const [oldName, newName] of RENAMES13) out = renameToken2(out, oldName, newName);
4115
+ for (const [oldName, newName] of RENAMES14) out = renameToken2(out, oldName, newName);
4087
4116
  return out;
4088
4117
  }
4089
4118
  };
@@ -4148,7 +4177,7 @@ var tokensCssMigration_2026_09_21_tintColorAndOpacity = {
4148
4177
  };
4149
4178
 
4150
4179
  // vite-plugin/tokensCssMigrations/migrations/2026-10-08-type-scales.ts
4151
- var RENAMES14 = [
4180
+ var RENAMES15 = [
4152
4181
  ["--code-font-size", "--code-md-font-size"],
4153
4182
  ["--code-line-height", "--code-md-line-height"],
4154
4183
  ["--code-letter-spacing", "--code-md-letter-spacing"]
@@ -4912,7 +4941,7 @@ var tokensCssMigration_2026_10_08_typeScales = {
4912
4941
  description: "Rebuild the text styles as five type scales with per-viewport sizes, and rename --code-font-size, --code-line-height and --code-letter-spacing to --code-md-*",
4913
4942
  apply(css) {
4914
4943
  let out = css;
4915
- for (const [from, to] of RENAMES14) out = renameToken2(out, from, to);
4944
+ for (const [from, to] of RENAMES15) out = renameToken2(out, from, to);
4916
4945
  const values = collectTokenValues(out);
4917
4946
  for (const step of [...CARRIED, ...handDeclaredSteps(values)]) {
4918
4947
  const size = values.get(`${step.prefix}-font-size`);
@@ -4961,6 +4990,50 @@ var tokensCssMigration_2026_10_08_typeScales = {
4961
4990
  }
4962
4991
  };
4963
4992
 
4993
+ // vite-plugin/tokensCssMigrations/migrations/2026-10-15-responsive-columns.ts
4994
+ var DESKTOP = [
4995
+ {
4996
+ structural: "--columns-gutter",
4997
+ desktop: "--columns-desktop-gutter",
4998
+ shipped: "clamp(0.5rem, 1.5vw, 1.5rem)",
4999
+ value: "32px"
5000
+ },
5001
+ { structural: "--columns-margin", desktop: "--columns-desktop-margin", shipped: "0", value: "32px" }
5002
+ ];
5003
+ var SMALLER = [
5004
+ { name: "--columns-tablet-gutter", value: "24px" },
5005
+ { name: "--columns-tablet-margin", value: "24px" },
5006
+ { name: "--columns-phone-gutter", value: "16px" },
5007
+ { name: "--columns-phone-margin", value: "16px" }
5008
+ ];
5009
+ var repoints = (viewport) => DESKTOP.map(({ structural }) => ({
5010
+ name: structural,
5011
+ value: `var(${structural.replace("--columns-", `--columns-${viewport}-`)})`
5012
+ }));
5013
+ var tokensCssMigration_2026_10_15_responsiveColumns = {
5014
+ id: "2026-10-15-responsive-columns",
5015
+ kind: "breaking",
5016
+ description: "Give the column grid a gutter and margin per viewport, and re-point --columns-gutter and --columns-margin at them",
5017
+ apply(css) {
5018
+ const values = collectTokenValues(css);
5019
+ const pending = DESKTOP.filter(({ desktop }) => !values.has(desktop));
5020
+ let out = ensureScale(css, {
5021
+ anchorPrefixes: ["--columns-"],
5022
+ entries: [
5023
+ ...pending.map(({ structural, desktop, shipped, value }) => {
5024
+ const current = values.get(structural);
5025
+ return { name: desktop, value: current === void 0 || current === shipped ? value : current };
5026
+ }),
5027
+ ...SMALLER
5028
+ ]
5029
+ });
5030
+ for (const { structural, desktop } of pending) out = setTokenValue(out, structural, `var(${desktop})`);
5031
+ out = ensureScale(out, { anchorPrefixes: ["--columns-"], entries: repoints("desktop") });
5032
+ out = appendMediaBlock(out, "(max-width: 767px)", repoints("tablet"), { before: "(max-width: 480px)" });
5033
+ return appendMediaBlock(out, "(max-width: 480px)", repoints("phone"));
5034
+ }
5035
+ };
5036
+
4964
5037
  // vite-plugin/tokensCssMigrations/index.ts
4965
5038
  var TOKENS_CSS_MIGRATIONS = [
4966
5039
  tokensCssMigration_2026_05_29_typographyScaleAdditions,
@@ -4980,7 +5053,8 @@ var TOKENS_CSS_MIGRATIONS = [
4980
5053
  tokensCssMigration_2026_09_01_tintScale,
4981
5054
  tokensCssMigration_2026_09_20_scrimColorAndOpacity,
4982
5055
  tokensCssMigration_2026_09_21_tintColorAndOpacity,
4983
- tokensCssMigration_2026_10_08_typeScales
5056
+ tokensCssMigration_2026_10_08_typeScales,
5057
+ tokensCssMigration_2026_10_15_responsiveColumns
4984
5058
  ];
4985
5059
  function runTokensCssMigrations(css) {
4986
5060
  return foldMigrations(css, () => true);
@@ -5049,6 +5123,502 @@ async function checkBeforeBuild({
5049
5123
  return null;
5050
5124
  }
5051
5125
 
5126
+ // vite-plugin/productionCss/index.ts
5127
+ var import_node_crypto = require("crypto");
5128
+
5129
+ // vite-plugin/productionCss/analyze.ts
5130
+ var import_postcss = __toESM(require("postcss"), 1);
5131
+ var ROOT_SPECIFICITY = /* @__PURE__ */ new Map([
5132
+ [":root", [0, 1, 0]],
5133
+ [":root:root", [0, 2, 0]],
5134
+ [":where(:root)", [0, 0, 0]],
5135
+ ["html", [0, 0, 1]]
5136
+ ]);
5137
+ var NAME = String.raw`--(?:[\w-]|[^\x00-\x7f])+`;
5138
+ var VAR_REF = new RegExp(String.raw`var\(\s*(${NAME})`, "gi");
5139
+ var PRELUDE_NAME = new RegExp(NAME, "g");
5140
+ var SCRIPT_NAME = new RegExp(String.raw`(?<![\w-])${NAME}`, "g");
5141
+ var CSS_WIDE_KEYWORD = /^\s*(?:initial|inherit|unset|revert|revert-layer)\s*$/i;
5142
+ var varRefs = (value) => [...value.matchAll(VAR_REF)].map((m) => m[1]);
5143
+ function compareSpecificity(a, b) {
5144
+ return a[0] - b[0] || a[1] - b[1] || a[2] - b[2];
5145
+ }
5146
+ function rootSpecificity(selector) {
5147
+ let best = null;
5148
+ for (const part of selector.split(",")) {
5149
+ const specificity = ROOT_SPECIFICITY.get(part.trim());
5150
+ if (!specificity) return null;
5151
+ if (!best || compareSpecificity(specificity, best) > 0) best = specificity;
5152
+ }
5153
+ return best;
5154
+ }
5155
+ function outranks(a, b) {
5156
+ if (a.important !== b.important) return a.important;
5157
+ const bySpecificity = compareSpecificity(a.specificity, b.specificity);
5158
+ if (bySpecificity !== 0) return bySpecificity > 0;
5159
+ return a.asset !== b.asset ? a.asset > b.asset : a.order > b.order;
5160
+ }
5161
+ function winnerOf(declarations) {
5162
+ let winner = null;
5163
+ for (const d of declarations) if (d.bare && (!winner || outranks(d, winner))) winner = d;
5164
+ return winner;
5165
+ }
5166
+ function analyze({ css, js, html, keep, entries }) {
5167
+ const declarations = /* @__PURE__ */ new Map();
5168
+ const regularRefs = /* @__PURE__ */ new Set();
5169
+ const preludeNames = /* @__PURE__ */ new Set();
5170
+ const registered = /* @__PURE__ */ new Set();
5171
+ const reads = css.map(() => /* @__PURE__ */ new Set());
5172
+ css.forEach((source, asset) => {
5173
+ let order = 0;
5174
+ import_postcss.default.parse(source).walk((node) => {
5175
+ if (node.type === "atrule") {
5176
+ if (node.name.toLowerCase() === "property") registered.add(node.params.trim());
5177
+ for (const [name] of node.params.matchAll(PRELUDE_NAME)) preludeNames.add(name);
5178
+ return;
5179
+ }
5180
+ if (node.type !== "decl") return;
5181
+ const refs = varRefs(node.value);
5182
+ for (const name of refs) reads[asset].add(name);
5183
+ if (!node.prop.startsWith("--")) {
5184
+ for (const name of refs) regularRefs.add(name);
5185
+ return;
5186
+ }
5187
+ let selector = null;
5188
+ let outerRule = false;
5189
+ const atRules = [];
5190
+ for (let p = node.parent; p && p.type !== "root"; p = p.parent) {
5191
+ if (p.type === "atrule") {
5192
+ const at = p;
5193
+ atRules.unshift(`@${at.name} ${at.params}`.trim());
5194
+ } else if (p.type === "rule") {
5195
+ if (selector === null) selector = p.selector;
5196
+ else outerRule = true;
5197
+ }
5198
+ }
5199
+ const specificity = selector === null ? null : rootSpecificity(selector);
5200
+ const declaration = {
5201
+ asset,
5202
+ order: order++,
5203
+ selector,
5204
+ atRules,
5205
+ value: node.value,
5206
+ important: node.important,
5207
+ root: specificity !== null,
5208
+ bare: specificity !== null && atRules.length === 0 && !outerRule,
5209
+ specificity
5210
+ };
5211
+ const list = declarations.get(node.prop);
5212
+ if (list) list.push(declaration);
5213
+ else declarations.set(node.prop, [declaration]);
5214
+ });
5215
+ });
5216
+ const scriptNames = /* @__PURE__ */ new Set();
5217
+ for (const text2 of [...js, ...html]) {
5218
+ for (const [name] of text2.matchAll(SCRIPT_NAME)) scriptNames.add(name);
5219
+ }
5220
+ const keepNames = new Set(keep);
5221
+ const references = /* @__PURE__ */ new Map();
5222
+ for (const [name, decls] of declarations) {
5223
+ references.set(name, new Set(decls.flatMap((d) => varRefs(d.value))));
5224
+ }
5225
+ const reached = /* @__PURE__ */ new Set();
5226
+ const toReach = [...regularRefs, ...preludeNames, ...scriptNames, ...keepNames];
5227
+ while (toReach.length) {
5228
+ const name = toReach.pop();
5229
+ if (reached.has(name)) continue;
5230
+ reached.add(name);
5231
+ for (const ref2 of references.get(name) ?? []) toReach.push(ref2);
5232
+ }
5233
+ const loops = /* @__PURE__ */ new Map();
5234
+ const reachesCycle = (name) => {
5235
+ const state = loops.get(name);
5236
+ if (state !== void 0) return state !== false;
5237
+ loops.set(name, "visiting");
5238
+ let result2 = false;
5239
+ for (const ref2 of references.get(name) ?? []) {
5240
+ if (declarations.has(ref2) && reachesCycle(ref2)) result2 = true;
5241
+ }
5242
+ loops.set(name, result2);
5243
+ return result2;
5244
+ };
5245
+ const setByName = (name) => scriptNames.has(name) || keepNames.has(name) || registered.has(name);
5246
+ const entryAssets = new Set(entries);
5247
+ const winners = /* @__PURE__ */ new Map();
5248
+ const reasons = /* @__PURE__ */ new Map();
5249
+ for (const [name, decls] of declarations) {
5250
+ const winner = winnerOf(decls);
5251
+ winners.set(name, winner);
5252
+ const bare = decls.filter((d) => d.bare);
5253
+ const why = [];
5254
+ if (decls.some((d) => !d.bare)) why.push("scoped");
5255
+ if (scriptNames.has(name)) why.push("script");
5256
+ if (preludeNames.has(name)) why.push("prelude");
5257
+ if (registered.has(name)) why.push("registered");
5258
+ if (keepNames.has(name)) why.push("keep");
5259
+ if (winner && CSS_WIDE_KEYWORD.test(winner.value)) why.push("keyword");
5260
+ if (reachesCycle(name)) why.push("cycle");
5261
+ if (new Set(bare.map((d) => d.asset)).size > 1 && new Set(bare.map((d) => d.value)).size > 1) {
5262
+ why.push("assets");
5263
+ }
5264
+ if ([...references.get(name)].some((ref2) => !declarations.has(ref2) && !setByName(ref2))) why.push("undeclared");
5265
+ const declaring = new Set(decls.map((d) => d.asset));
5266
+ if (![...declaring].some((asset) => entryAssets.has(asset)) && reads.some((names, asset) => !declaring.has(asset) && names.has(name))) {
5267
+ why.push("lazy");
5268
+ }
5269
+ reasons.set(name, why);
5270
+ }
5271
+ const dependents = /* @__PURE__ */ new Map();
5272
+ for (const [name, refs] of references) {
5273
+ for (const ref2 of refs) {
5274
+ const list = dependents.get(ref2);
5275
+ if (list) list.push(name);
5276
+ else dependents.set(ref2, [name]);
5277
+ }
5278
+ }
5279
+ const dynamic = /* @__PURE__ */ new Set();
5280
+ const toSpread = [
5281
+ ...[...reasons].filter(([, why]) => why.length > 0).map(([name]) => name),
5282
+ ...scriptNames,
5283
+ ...keepNames,
5284
+ ...registered
5285
+ ];
5286
+ while (toSpread.length) {
5287
+ const name = toSpread.pop();
5288
+ if (dynamic.has(name)) continue;
5289
+ dynamic.add(name);
5290
+ for (const dependent of dependents.get(name) ?? []) toSpread.push(dependent);
5291
+ }
5292
+ const result = /* @__PURE__ */ new Map();
5293
+ for (const [name, decls] of declarations) {
5294
+ const refs = [...references.get(name)];
5295
+ const why = reasons.get(name);
5296
+ if (refs.some((ref2) => dynamic.has(ref2))) why.push("reference");
5297
+ result.set(name, {
5298
+ declarations: decls,
5299
+ references: refs,
5300
+ reached: reached.has(name),
5301
+ dynamic: why.length > 0,
5302
+ reasons: why,
5303
+ winner: winners.get(name)
5304
+ });
5305
+ }
5306
+ return result;
5307
+ }
5308
+
5309
+ // vite-plugin/productionCss/rewrite.ts
5310
+ var import_postcss2 = __toESM(require("postcss"), 1);
5311
+ var TOKEN_BEFORE_FUNCTION = /[\w\-#@\\]|[^\x00-\x7f]/;
5312
+ var VAR_NAME = /^\s*(--(?:[\w-]|[^\x00-\x7f])+)\s*(?:,|$)/;
5313
+ var JOINS_LEFT = /[\w\-#@.+\\]|[^\x00-\x7f]/;
5314
+ var JOINS_RIGHT = /[\w\-.+%(\\]|[^\x00-\x7f]/;
5315
+ var EMPTIED_AT_RULES = /* @__PURE__ */ new Set(["media", "supports", "container"]);
5316
+ var DESCRIPTOR_AT_RULES = /* @__PURE__ */ new Set(["font-face", "property", "counter-style", "font-palette-values"]);
5317
+ function skipString(value, start) {
5318
+ const quote = value[start];
5319
+ let i = start + 1;
5320
+ while (i < value.length && value[i] !== quote) i += value[i] === "\\" ? 2 : 1;
5321
+ return i + 1;
5322
+ }
5323
+ function skipComment(value, start) {
5324
+ const end = value.indexOf("*/", start + 2);
5325
+ return end < 0 ? value.length : end + 2;
5326
+ }
5327
+ function closingParen(value, open) {
5328
+ let depth = 0;
5329
+ let i = open;
5330
+ while (i < value.length) {
5331
+ const c = value[i];
5332
+ if (c === '"' || c === "'") i = skipString(value, i);
5333
+ else if (c === "/" && value[i + 1] === "*") i = skipComment(value, i);
5334
+ else {
5335
+ if (c === "\\") i += 1;
5336
+ else if (c === "(") depth += 1;
5337
+ else if (c === ")" && --depth === 0) return i;
5338
+ i += 1;
5339
+ }
5340
+ }
5341
+ return -1;
5342
+ }
5343
+ function afterUrl(value, start) {
5344
+ let i = start;
5345
+ while (/\s/.test(value[i] ?? "")) i += 1;
5346
+ if (value[i] === '"' || value[i] === "'") {
5347
+ const close = closingParen(value, start - 1);
5348
+ return close < 0 ? value.length : close + 1;
5349
+ }
5350
+ while (i < value.length && value[i] !== ")") i += value[i] === "\\" ? 2 : 1;
5351
+ return i + 1;
5352
+ }
5353
+ function functionAt(value, i, name) {
5354
+ return value.slice(i, i + name.length).toLowerCase() === name && (i === 0 || !TOKEN_BEFORE_FUNCTION.test(value[i - 1]));
5355
+ }
5356
+ function breaksBetween(left, right) {
5357
+ if (!left || !right) return false;
5358
+ return JOINS_LEFT.test(left) && JOINS_RIGHT.test(right) || left === "/" && right === "*";
5359
+ }
5360
+ function spliced(before, text2, after) {
5361
+ if (text2 === "") return breaksBetween(before, after) ? "/**/" : "";
5362
+ const head = breaksBetween(before, text2[0]) ? "/**/" : "";
5363
+ const tail = breaksBetween(text2[text2.length - 1], after) ? "/**/" : "";
5364
+ return head + text2 + tail;
5365
+ }
5366
+ function substituteValue(value, valueOf) {
5367
+ let out = "";
5368
+ let copied = 0;
5369
+ let i = 0;
5370
+ while (i < value.length) {
5371
+ const c = value[i];
5372
+ if (c === '"' || c === "'") {
5373
+ i = skipString(value, i);
5374
+ } else if (c === "/" && value[i + 1] === "*") {
5375
+ i = skipComment(value, i);
5376
+ } else if (c === "\\") {
5377
+ i += 2;
5378
+ } else if (functionAt(value, i, "url(")) {
5379
+ i = afterUrl(value, i + 4);
5380
+ } else if (functionAt(value, i, "var(")) {
5381
+ const close = closingParen(value, i + 3);
5382
+ if (close < 0) break;
5383
+ const args = value.slice(i + 4, close);
5384
+ const name = VAR_NAME.exec(args)?.[1];
5385
+ const replacement = name === void 0 ? void 0 : valueOf(name);
5386
+ out += value.slice(copied, i);
5387
+ out += replacement === void 0 ? `${value.slice(i, i + 4)}${substituteValue(args, valueOf)})` : spliced(out[out.length - 1], replacement, value[close + 1]);
5388
+ copied = i = close + 1;
5389
+ } else {
5390
+ i += 1;
5391
+ }
5392
+ }
5393
+ return out + value.slice(copied);
5394
+ }
5395
+ function staticValues(analysis) {
5396
+ const values = /* @__PURE__ */ new Map();
5397
+ const valueOf = (name) => {
5398
+ const property = analysis.get(name);
5399
+ if (!property || property.dynamic) return void 0;
5400
+ let value = values.get(name);
5401
+ if (value === void 0) {
5402
+ value = substituteValue(property.winner.value.trim(), valueOf);
5403
+ values.set(name, value);
5404
+ }
5405
+ return value;
5406
+ };
5407
+ for (const [name, property] of analysis) if (property.reached) valueOf(name);
5408
+ return values;
5409
+ }
5410
+ function droppedDeclarations(analysis, asset, { substitute }) {
5411
+ const dropped = /* @__PURE__ */ new Set();
5412
+ for (const property of analysis.values()) {
5413
+ const own = property.declarations.filter((d) => d.asset === asset);
5414
+ if (!property.reached || substitute && !property.dynamic) {
5415
+ for (const d of own) dropped.add(d.order);
5416
+ continue;
5417
+ }
5418
+ const winner = winnerOf(own);
5419
+ for (const d of own) if (d.bare && d !== winner) dropped.add(d.order);
5420
+ }
5421
+ return dropped;
5422
+ }
5423
+ var isDescriptor = (decl) => decl.parent instanceof import_postcss2.AtRule && DESCRIPTOR_AT_RULES.has(decl.parent.name.toLowerCase());
5424
+ var removableWhenEmpty = (node) => node instanceof import_postcss2.Rule || node instanceof import_postcss2.AtRule && EMPTIED_AT_RULES.has(node.name.toLowerCase());
5425
+ function removeEmptied(containers) {
5426
+ for (const container of containers) {
5427
+ let node = container;
5428
+ while (removableWhenEmpty(node) && node.nodes?.length === 0) {
5429
+ const parent = node.parent;
5430
+ node.remove();
5431
+ node = parent;
5432
+ }
5433
+ }
5434
+ }
5435
+ function rewrite(css, asset, analysis, options, values = options.substitute ? staticValues(analysis) : null) {
5436
+ const dropped = droppedDeclarations(analysis, asset, options);
5437
+ const root = import_postcss2.default.parse(css);
5438
+ const emptied = /* @__PURE__ */ new Set();
5439
+ let order = 0;
5440
+ root.walkDecls((decl) => {
5441
+ if (decl.prop.startsWith("--") && dropped.has(order++)) {
5442
+ emptied.add(decl.parent);
5443
+ decl.remove();
5444
+ return;
5445
+ }
5446
+ if (!values || isDescriptor(decl)) return;
5447
+ const value = substituteValue(decl.value, (name) => values.get(name));
5448
+ if (value !== decl.value) decl.value = value;
5449
+ });
5450
+ removeEmptied(emptied);
5451
+ return root.toString();
5452
+ }
5453
+
5454
+ // vite-plugin/productionCss/index.ts
5455
+ var text = (source) => typeof source === "string" ? source : new TextDecoder().decode(source);
5456
+ var HASH = /\[hash(?::(\d+))?\]/;
5457
+ var PLACEHOLDER = /\[(name|hash(?::\d+)?|ext|extname|format)\]/g;
5458
+ var escape = (literal) => literal.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
5459
+ var TEXT_ASSET = /\.(css|html|json|map)$/;
5460
+ function hashedFileName(fileName, pattern, content) {
5461
+ const hash = HASH.exec(pattern);
5462
+ if (!hash) return null;
5463
+ const length = hash[1] ? Number(hash[1]) : 8;
5464
+ let regex = "^";
5465
+ let last = 0;
5466
+ for (const m of pattern.matchAll(PLACEHOLDER)) {
5467
+ regex += escape(pattern.slice(last, m.index));
5468
+ if (m.index === hash.index) regex += `([A-Za-z0-9_-]{${length}})`;
5469
+ else if (m[1] === "ext") regex += "[^./]*";
5470
+ else if (m[1] === "extname") regex += "(?:\\.[^./]*)?";
5471
+ else regex += ".*?";
5472
+ last = m.index + m[0].length;
5473
+ }
5474
+ regex += escape(pattern.slice(last)) + "$";
5475
+ const match = new RegExp(regex, "d").exec(fileName);
5476
+ if (!match?.indices?.[1]) throw new Error(`live-tokens: ${fileName} does not follow the output pattern "${pattern}"`);
5477
+ const [start, end] = match.indices[1];
5478
+ const digest = (0, import_node_crypto.createHash)("sha256").update(content).digest("base64url").slice(0, length);
5479
+ return fileName.slice(0, start) + digest + fileName.slice(end);
5480
+ }
5481
+ function tails(from, to) {
5482
+ let i = 0;
5483
+ while (from[i] === to[i]) i += 1;
5484
+ const start = from.lastIndexOf("/", i) + 1;
5485
+ return [from.slice(start), to.slice(start)];
5486
+ }
5487
+ function repoint(files, renames) {
5488
+ const pairs = [...renames].map(([from, to]) => tails(from, to));
5489
+ const replace = (s) => {
5490
+ for (const [from, to] of pairs) s = s.replaceAll(from, () => to);
5491
+ return s;
5492
+ };
5493
+ const renamed = (names) => names.map((name) => renames.get(name) ?? name);
5494
+ const changed = /* @__PURE__ */ new Set();
5495
+ for (const file of files) {
5496
+ if (file.type === "chunk") {
5497
+ const code = replace(file.code);
5498
+ if (code !== file.code) {
5499
+ file.code = code;
5500
+ changed.add(file);
5501
+ }
5502
+ if (file.imports.some((name) => renames.has(name))) file.imports = renamed(file.imports);
5503
+ if (file.dynamicImports.some((name) => renames.has(name))) file.dynamicImports = renamed(file.dynamicImports);
5504
+ const map = file.sourcemapFileName && replace(file.sourcemapFileName);
5505
+ if (map && map !== file.sourcemapFileName) file.sourcemapFileName = map;
5506
+ const imported = file.viteMetadata?.importedCss;
5507
+ if (imported && [...imported].some((name) => renames.has(name))) {
5508
+ const next = renamed([...imported]);
5509
+ imported.clear();
5510
+ for (const name of next) imported.add(name);
5511
+ changed.add(file);
5512
+ }
5513
+ } else if (TEXT_ASSET.test(file.fileName)) {
5514
+ const before = text(file.source);
5515
+ const after = replace(before);
5516
+ if (after !== before) file.source = after;
5517
+ }
5518
+ const fileName = replace(file.fileName);
5519
+ if (fileName !== file.fileName) file.fileName = fileName;
5520
+ }
5521
+ return changed;
5522
+ }
5523
+ function renameRewritten(files, sheetRenames, names) {
5524
+ const affected = repoint(files, sheetRenames);
5525
+ const chunks = files.filter((f) => f.type === "chunk");
5526
+ const byName = new Map(chunks.map((c) => [c.fileName, c]));
5527
+ const imported = (c) => [...c.imports, ...c.dynamicImports].flatMap((name) => byName.get(name) ?? []);
5528
+ for (let grew = true; grew; ) {
5529
+ grew = false;
5530
+ for (const chunk of chunks) {
5531
+ if (!affected.has(chunk) && imported(chunk).some((c) => affected.has(c))) {
5532
+ affected.add(chunk);
5533
+ grew = true;
5534
+ }
5535
+ }
5536
+ }
5537
+ const identity = (c) => [c.code, ...c.viteMetadata?.importedCss ?? []].join("\0");
5538
+ const chunkRenames = /* @__PURE__ */ new Map();
5539
+ for (const chunk of affected) {
5540
+ const reached = /* @__PURE__ */ new Set([chunk]);
5541
+ const toVisit = [chunk];
5542
+ while (toVisit.length) {
5543
+ for (const next of imported(toVisit.pop())) {
5544
+ if (!reached.has(next)) {
5545
+ reached.add(next);
5546
+ toVisit.push(next);
5547
+ }
5548
+ }
5549
+ }
5550
+ reached.delete(chunk);
5551
+ const others = [...reached].sort((a, b) => a.fileName < b.fileName ? -1 : 1);
5552
+ const fileNames = chunk.isEntry ? names.entryFileNames : names.chunkFileNames;
5553
+ const pattern = typeof fileNames === "string" ? fileNames : fileNames({
5554
+ name: chunk.name,
5555
+ isEntry: chunk.isEntry,
5556
+ isDynamicEntry: chunk.isDynamicEntry,
5557
+ facadeModuleId: chunk.facadeModuleId ?? void 0,
5558
+ moduleIds: chunk.moduleIds,
5559
+ exports: chunk.exports
5560
+ });
5561
+ const renamed = hashedFileName(chunk.fileName, pattern, [chunk, ...others].map(identity).join("\0\0"));
5562
+ if (renamed !== null && renamed !== chunk.fileName) chunkRenames.set(chunk.fileName, renamed);
5563
+ }
5564
+ if (chunkRenames.size > 0) repoint(files, chunkRenames);
5565
+ }
5566
+ function entrySheets(files) {
5567
+ const chunks = new Map(files.flatMap((f) => f.type === "chunk" ? [[f.fileName, f]] : []));
5568
+ const sheets = /* @__PURE__ */ new Set();
5569
+ const seen = /* @__PURE__ */ new Set();
5570
+ const toVisit = [...chunks.values()].filter((c) => c.isEntry);
5571
+ while (toVisit.length) {
5572
+ const chunk = toVisit.pop();
5573
+ if (seen.has(chunk.fileName)) continue;
5574
+ seen.add(chunk.fileName);
5575
+ for (const sheet of chunk.viteMetadata?.importedCss ?? []) sheets.add(sheet);
5576
+ for (const name of chunk.imports) {
5577
+ const imported = chunks.get(name);
5578
+ if (imported) toVisit.push(imported);
5579
+ }
5580
+ }
5581
+ return sheets;
5582
+ }
5583
+ function rewriteBundle(bundle, { substitute = true, keep = [] }, names) {
5584
+ const files = Object.values(bundle);
5585
+ const assets = files.filter((f) => f.type === "asset");
5586
+ const sheets = assets.filter((f) => f.fileName.endsWith(".css"));
5587
+ if (sheets.length === 0) return null;
5588
+ const css = sheets.map((f) => text(f.source));
5589
+ const js = [
5590
+ ...files.flatMap((f) => f.type === "chunk" ? [f.code] : []),
5591
+ ...assets.filter((f) => /\.[cm]?js$/.test(f.fileName)).map((f) => text(f.source))
5592
+ ];
5593
+ const html = assets.filter((f) => f.fileName.endsWith(".html")).map((f) => text(f.source));
5594
+ const loadedWithPage = entrySheets(files);
5595
+ const entries = sheets.flatMap((sheet, i) => loadedWithPage.has(sheet.fileName) ? [i] : []);
5596
+ const analysis = analyze({ css, js, html, keep, entries });
5597
+ const values = substitute ? staticValues(analysis) : null;
5598
+ let bytesSaved = 0;
5599
+ const renames = /* @__PURE__ */ new Map();
5600
+ const { assetFileNames } = names;
5601
+ sheets.forEach((sheet, i) => {
5602
+ const rewritten = rewrite(css[i], i, analysis, { substitute }, values);
5603
+ bytesSaved += Buffer.byteLength(css[i]) - Buffer.byteLength(rewritten);
5604
+ if (rewritten === css[i]) return;
5605
+ sheet.source = rewritten;
5606
+ const pattern = typeof assetFileNames === "string" ? assetFileNames : assetFileNames({ type: "asset", names: sheet.names, originalFileNames: sheet.originalFileNames, source: rewritten });
5607
+ const renamed = hashedFileName(sheet.fileName, pattern, rewritten);
5608
+ if (renamed !== null && renamed !== sheet.fileName) renames.set(sheet.fileName, renamed);
5609
+ });
5610
+ if (renames.size > 0) renameRewritten(files, renames, names);
5611
+ let propertiesAfter = 0;
5612
+ for (const property of analysis.values()) {
5613
+ if (property.reached && (property.dynamic || !substitute)) propertiesAfter += 1;
5614
+ }
5615
+ return { propertiesBefore: analysis.size, propertiesAfter, bytesSaved };
5616
+ }
5617
+ function formatReport({ propertiesBefore, propertiesAfter, bytesSaved }) {
5618
+ const kB = (Math.abs(bytesSaved) / 1e3).toFixed(1);
5619
+ return `live-tokens: the production CSS declares ${propertiesAfter.toLocaleString("en-US")} of ${propertiesBefore.toLocaleString("en-US")} custom properties and is ${kB} kB ${bytesSaved >= 0 ? "smaller" : "larger"}.`;
5620
+ }
5621
+
5052
5622
  // vite-plugin/themeFileApi.ts
5053
5623
  var import_node_url2 = require("url");
5054
5624
  var import_meta2 = {};
@@ -6496,6 +7066,7 @@ data: ${JSON.stringify(state)}
6496
7066
  const isEditorOwnedJson = (file) => file.endsWith(".json") && import_path5.default.resolve(file).startsWith(dataDirs.dataDir + import_path5.default.sep);
6497
7067
  let buildLogger = null;
6498
7068
  let buildChecked = false;
7069
+ let productionCssLogger = null;
6499
7070
  return {
6500
7071
  name: "theme-file-api",
6501
7072
  config() {
@@ -6510,6 +7081,7 @@ data: ${JSON.stringify(state)}
6510
7081
  },
6511
7082
  configResolved(config) {
6512
7083
  buildLogger = config.command === "build" && opts.checks !== false ? config.logger : null;
7084
+ productionCssLogger = config.command === "build" && opts.productionCss !== false ? config.logger : null;
6513
7085
  },
6514
7086
  async buildStart() {
6515
7087
  if (!buildLogger || buildChecked) return;
@@ -6517,6 +7089,15 @@ data: ${JSON.stringify(state)}
6517
7089
  const failure = await checkBeforeBuild({ root: process.cwd(), logger: buildLogger });
6518
7090
  if (failure) this.error(failure);
6519
7091
  },
7092
+ generateBundle: {
7093
+ // After Vite's own hooks, so the bundle holds the minified CSS and index.html.
7094
+ order: "post",
7095
+ handler(output, bundle) {
7096
+ if (!productionCssLogger) return;
7097
+ const report = rewriteBundle(bundle, opts.productionCss || {}, output);
7098
+ if (report) productionCssLogger.info(formatReport(report));
7099
+ }
7100
+ },
6520
7101
  configureServer(server) {
6521
7102
  legacyLayout = detectLegacyLayout({
6522
7103
  dataDir: dataDirs.dataDir,