meno-core 1.1.1 → 1.1.2

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.
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  CMS_DRAFT_SUFFIX,
3
+ VARIABLE_GROUPS,
3
4
  buildSlugIndex,
4
5
  collectComponentLibraries,
5
6
  createLogger,
@@ -8,6 +9,7 @@ import {
8
9
  fontFaceCss,
9
10
  fontPreloadLinks,
10
11
  generateLibraryTags,
12
+ getDefaultScalingType,
11
13
  getLocaleLinks,
12
14
  isPathWithinRoot,
13
15
  isReservedDraftFilename,
@@ -18,7 +20,7 @@ import {
18
20
  resolveSlugToPageId,
19
21
  rewriteComponentRefs,
20
22
  translatePath
21
- } from "../../chunks/chunk-QWTQZHG3.js";
23
+ } from "../../chunks/chunk-FQBIC2OB.js";
22
24
  import {
23
25
  syncNetlifyLocale404Block
24
26
  } from "../../chunks/chunk-2AR55GYH.js";
@@ -457,13 +459,13 @@ async function bundleWithBun(entrypoint, opts) {
457
459
  const code = await result.outputs[0].text();
458
460
  return { code, success: true, errors: [] };
459
461
  }
460
- const errors = (result.logs || []).map((log6) => {
462
+ const errors = (result.logs || []).map((log7) => {
461
463
  const parts = [];
462
- if (log6.position?.file) parts.push(`File: ${log6.position.file}`);
463
- if (log6.position?.line) parts.push(`Line ${log6.position.line}:${log6.position.column || 0}`);
464
- if (log6.position?.lineText) parts.push(log6.position.lineText);
465
- if (log6.message) parts.push(log6.message);
466
- return parts.length > 0 ? parts.join("\n") : String(log6);
464
+ if (log7.position?.file) parts.push(`File: ${log7.position.file}`);
465
+ if (log7.position?.line) parts.push(`Line ${log7.position.line}:${log7.position.column || 0}`);
466
+ if (log7.position?.lineText) parts.push(log7.position.lineText);
467
+ if (log7.message) parts.push(log7.message);
468
+ return parts.length > 0 ? parts.join("\n") : String(log7);
467
469
  });
468
470
  return { code: "", success: false, errors };
469
471
  } catch (err) {
@@ -471,12 +473,12 @@ async function bundleWithBun(entrypoint, opts) {
471
473
  if (opts.throw) throw err;
472
474
  const errors = [];
473
475
  if (be.logs && Array.isArray(be.logs)) {
474
- for (const log6 of be.logs) {
476
+ for (const log7 of be.logs) {
475
477
  const parts = [];
476
- if (log6.position?.line) parts.push(`Line ${log6.position.line}:${log6.position.column || 0}`);
477
- if (log6.position?.lineText) parts.push(log6.position.lineText);
478
- if (log6.message) parts.push(log6.message);
479
- errors.push(parts.length > 0 ? parts.join("\n") : String(log6));
478
+ if (log7.position?.line) parts.push(`Line ${log7.position.line}:${log7.position.column || 0}`);
479
+ if (log7.position?.lineText) parts.push(log7.position.lineText);
480
+ if (log7.message) parts.push(log7.message);
481
+ errors.push(parts.length > 0 ? parts.join("\n") : String(log7));
480
482
  }
481
483
  } else {
482
484
  errors.push(be.message || String(err));
@@ -486,8 +488,8 @@ async function bundleWithBun(entrypoint, opts) {
486
488
  }
487
489
  async function minifyWithBun(code) {
488
490
  const { writeFile: writeFile3, rm: _rm } = await import("node:fs/promises");
489
- const { join: join9 } = await import("node:path");
490
- const tempFile = join9("/tmp", `meno-minify-${Date.now()}.js`);
491
+ const { join: join10 } = await import("node:path");
492
+ const tempFile = join10("/tmp", `meno-minify-${Date.now()}.js`);
491
493
  try {
492
494
  await writeFile3(tempFile, code, "utf-8");
493
495
  const result = await Bun.build({
@@ -506,12 +508,12 @@ async function minifyWithBun(code) {
506
508
  const { inspect: inspect2 } = await import("../../chunks/fs-G3ANWEFP.js");
507
509
  let details = "";
508
510
  if (be.logs && Array.isArray(be.logs)) {
509
- details = be.logs.map((log6) => {
511
+ details = be.logs.map((log7) => {
510
512
  const parts = [];
511
- if (log6.position?.line) parts.push(`Line ${log6.position.line}:${log6.position.column || 0}`);
512
- if (log6.position?.lineText) parts.push(log6.position.lineText);
513
- if (log6.message) parts.push(log6.message);
514
- return parts.length > 0 ? parts.join("\n") : String(log6);
513
+ if (log7.position?.line) parts.push(`Line ${log7.position.line}:${log7.position.column || 0}`);
514
+ if (log7.position?.lineText) parts.push(log7.position.lineText);
515
+ if (log7.message) parts.push(log7.message);
516
+ return parts.length > 0 ? parts.join("\n") : String(log7);
515
517
  }).join("\n\n");
516
518
  }
517
519
  if (!details) {
@@ -524,16 +526,16 @@ async function minifyWithBun(code) {
524
526
  return { code: "", success: false, errors: [details] };
525
527
  } finally {
526
528
  try {
527
- const { rm } = await import("node:fs/promises");
528
- await rm(tempFile, { force: true });
529
+ const { rm: rm2 } = await import("node:fs/promises");
530
+ await rm2(tempFile, { force: true });
529
531
  } catch {
530
532
  }
531
533
  }
532
534
  }
533
535
  async function validateWithBun(code) {
534
- const { writeFile: writeFile3, rm } = await import("node:fs/promises");
535
- const { join: join9 } = await import("node:path");
536
- const tempFile = join9("/tmp", `meno-validate-${Date.now()}-${Math.random().toString(36).slice(2)}.js`);
536
+ const { writeFile: writeFile3, rm: rm2 } = await import("node:fs/promises");
537
+ const { join: join10 } = await import("node:path");
538
+ const tempFile = join10("/tmp", `meno-validate-${Date.now()}-${Math.random().toString(36).slice(2)}.js`);
537
539
  try {
538
540
  await writeFile3(tempFile, code, "utf-8");
539
541
  await Bun.build({
@@ -547,12 +549,12 @@ async function validateWithBun(code) {
547
549
  const { inspect: inspect2 } = await import("../../chunks/fs-G3ANWEFP.js");
548
550
  let details = "";
549
551
  if (be.logs && Array.isArray(be.logs)) {
550
- details = be.logs.map((log6) => {
552
+ details = be.logs.map((log7) => {
551
553
  const parts = [];
552
- if (log6.position?.line) parts.push(`Line ${log6.position.line}:${log6.position.column || 0}`);
553
- if (log6.position?.lineText) parts.push(log6.position.lineText);
554
- if (log6.message) parts.push(log6.message);
555
- return parts.length > 0 ? parts.join("\n") : String(log6);
554
+ if (log7.position?.line) parts.push(`Line ${log7.position.line}:${log7.position.column || 0}`);
555
+ if (log7.position?.lineText) parts.push(log7.position.lineText);
556
+ if (log7.message) parts.push(log7.message);
557
+ return parts.length > 0 ? parts.join("\n") : String(log7);
556
558
  }).join("\n\n");
557
559
  }
558
560
  if (!details) {
@@ -565,7 +567,7 @@ async function validateWithBun(code) {
565
567
  return details || "Unknown JavaScript error";
566
568
  } finally {
567
569
  try {
568
- await rm(tempFile, { force: true });
570
+ await rm2(tempFile, { force: true });
569
571
  } catch {
570
572
  }
571
573
  }
@@ -1690,6 +1692,9 @@ async function handleComponentsConfigRoute() {
1690
1692
  }
1691
1693
  }
1692
1694
 
1695
+ // lib/server/services/ColorService.ts
1696
+ import { existsSync as existsSync3 } from "node:fs";
1697
+
1693
1698
  // lib/server/services/CachedConfigLoader.ts
1694
1699
  var CachedConfigLoader = class {
1695
1700
  config = null;
@@ -1730,8 +1735,511 @@ var CachedConfigLoader = class {
1730
1735
  }
1731
1736
  };
1732
1737
 
1738
+ // lib/server/themeCssStore.ts
1739
+ import { existsSync as existsSync2, readFileSync } from "node:fs";
1740
+ import { rm } from "node:fs/promises";
1741
+ import { join as join2 } from "node:path";
1742
+
1743
+ // lib/server/themeCssCodec.ts
1744
+ var COLORS_LABEL = "Colors";
1745
+ var OTHER_LABEL = "Other";
1746
+ var HEADER_BANNER = `/*
1747
+ * Meno design tokens \u2014 theme.css is the source of truth for this project's colors and
1748
+ * variables. Edit values here, or use the Studio color/variable panels. Variables are
1749
+ * grouped by the comment sections below; the @media regions are regenerated on save
1750
+ * (responsive scaling is configured in project.config.json).
1751
+ */`;
1752
+ var AUTO_BANNER = "/* === Responsive scaling \u2014 auto-generated from project.config.json; regenerated on save === */";
1753
+ var OVERRIDES_BANNER = "/* === Responsive overrides \u2014 per-variable; preserved across regen === */";
1754
+ function sectionLabelForGroup(group) {
1755
+ if (!group || group === "other") return OTHER_LABEL;
1756
+ return VARIABLE_GROUPS.find((g) => g.value === group)?.label ?? OTHER_LABEL;
1757
+ }
1758
+ var LABEL_TO_GROUP = new Map(VARIABLE_GROUPS.map((g) => [g.label.toLowerCase(), g.value]));
1759
+ function groupForSectionLabel(label) {
1760
+ return LABEL_TO_GROUP.get(label.trim().toLowerCase()) ?? null;
1761
+ }
1762
+ function isColorValue(value) {
1763
+ const v = value.trim().toLowerCase();
1764
+ if (/^#[0-9a-f]{3,8}$/.test(v)) return true;
1765
+ if (/^(rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color)\(/.test(v)) return true;
1766
+ if (v === "transparent" || v === "currentcolor") return true;
1767
+ return false;
1768
+ }
1769
+ function inferGroup(cssVar, value) {
1770
+ const v = value.trim().toLowerCase();
1771
+ if (/^\d+(\.\d+)?m?s$/.test(v)) return "duration";
1772
+ if (/^(normal|bold|lighter|bolder)$/.test(v)) return "font-weight";
1773
+ if (/^\d+$/.test(v)) {
1774
+ const n = Number(v);
1775
+ if (n >= 100 && n <= 900 && n % 100 === 0) return "font-weight";
1776
+ }
1777
+ if (/^\d*\.\d+$/.test(v) || /^[1-9](\.\d+)?$/.test(v)) return "line-height";
1778
+ const name = cssVar.replace(/^--/, "").toLowerCase();
1779
+ for (const g of VARIABLE_GROUPS) {
1780
+ if (g.value !== "other" && name.includes(g.value)) return g.value;
1781
+ }
1782
+ return "other";
1783
+ }
1784
+ function groupVariables(variables) {
1785
+ const buckets = /* @__PURE__ */ new Map();
1786
+ for (const v of variables) {
1787
+ const label = sectionLabelForGroup(v.group);
1788
+ (buckets.get(label) ?? buckets.set(label, []).get(label)).push(v);
1789
+ }
1790
+ const ordered = [];
1791
+ for (const g of VARIABLE_GROUPS) {
1792
+ if (g.value === "other") continue;
1793
+ const vars = buckets.get(g.label);
1794
+ if (vars?.length) {
1795
+ ordered.push({ label: g.label, vars });
1796
+ buckets.delete(g.label);
1797
+ }
1798
+ }
1799
+ for (const [label, vars] of buckets) if (vars.length) ordered.push({ label, vars });
1800
+ return ordered;
1801
+ }
1802
+ function buildAutoMediaBlocks(scalable, cfg) {
1803
+ const { breakpoints, responsiveScales } = cfg;
1804
+ const baseRef = responsiveScales.baseReference || 16;
1805
+ const sorted = Object.entries(breakpoints).sort((a, b) => b[1].breakpoint - a[1].breakpoint);
1806
+ const blocks = [];
1807
+ for (const [bpName, bp] of sorted) {
1808
+ const lines = [];
1809
+ for (const v of scalable) {
1810
+ if (v.scales?.[bpName] !== void 0) continue;
1811
+ const categoryScales = responsiveScales[v.type];
1812
+ const scale = categoryScales?.[bpName];
1813
+ if (scale == null) continue;
1814
+ const scaled = scalePropertyValue(v.value, baseRef, scale);
1815
+ if (scaled !== null && scaled !== v.value) lines.push(` ${v.cssVar}: ${scaled};`);
1816
+ }
1817
+ if (lines.length) blocks.push(`@media (max-width: ${bp.breakpoint}px) {
1818
+ :root {
1819
+ ${lines.join("\n")}
1820
+ }
1821
+ }`);
1822
+ }
1823
+ return blocks.join("\n\n");
1824
+ }
1825
+ function buildOverrideMediaBlocks(variables, breakpoints) {
1826
+ const sorted = Object.entries(breakpoints).sort((a, b) => b[1].breakpoint - a[1].breakpoint);
1827
+ const blocks = [];
1828
+ for (const [bpName, bp] of sorted) {
1829
+ const lines = [];
1830
+ for (const v of variables) {
1831
+ const override = v.scales?.[bpName];
1832
+ if (override !== void 0 && override !== v.value) lines.push(` ${v.cssVar}: ${override};`);
1833
+ }
1834
+ if (lines.length) blocks.push(`@media (max-width: ${bp.breakpoint}px) {
1835
+ :root {
1836
+ ${lines.join("\n")}
1837
+ }
1838
+ }`);
1839
+ }
1840
+ return blocks.join("\n\n");
1841
+ }
1842
+ function serializeThemeCss(model, scaleConfig2) {
1843
+ const { themes, variables, raw = [] } = model;
1844
+ const palette = themes?.palette;
1845
+ const defaultName = themes?.default ?? "default";
1846
+ const defaultTheme = themes?.themes?.[defaultName];
1847
+ const sections = [];
1848
+ const colorEntries = Object.entries(defaultTheme?.colors ?? {});
1849
+ if (colorEntries.length) {
1850
+ sections.push(
1851
+ [
1852
+ ` /* ${COLORS_LABEL}: ${defaultName} */`,
1853
+ ...colorEntries.map(([k, val]) => ` --${k}: ${resolvePaletteColor(val, palette)};`)
1854
+ ].join("\n")
1855
+ );
1856
+ }
1857
+ for (const { label, vars } of groupVariables(variables)) {
1858
+ sections.push([` /* ${label} */`, ...vars.map((v) => ` ${v.cssVar}: ${v.value};`)].join("\n"));
1859
+ }
1860
+ const blocks = [HEADER_BANNER];
1861
+ blocks.push(sections.length ? `:root {
1862
+ ${sections.join("\n\n")}
1863
+ }` : ":root {}");
1864
+ for (const [name, theme] of Object.entries(themes?.themes ?? {})) {
1865
+ if (name === defaultName) continue;
1866
+ const lines = Object.entries(theme.colors ?? {}).map(
1867
+ ([k, val]) => ` --${k}: ${resolvePaletteColor(val, palette)};`
1868
+ );
1869
+ if (lines.length) blocks.push(`[theme="${name}"] {
1870
+ ${lines.join("\n")}
1871
+ }`);
1872
+ }
1873
+ if (scaleConfig2.responsiveScales?.enabled) {
1874
+ const auto = buildAutoMediaBlocks(
1875
+ variables.filter((v) => v.type && v.type !== "none"),
1876
+ scaleConfig2
1877
+ );
1878
+ if (auto) blocks.push(AUTO_BANNER, auto);
1879
+ }
1880
+ const overrides = buildOverrideMediaBlocks(variables, scaleConfig2.breakpoints);
1881
+ if (overrides) blocks.push(OVERRIDES_BANNER, overrides);
1882
+ for (const r of raw) {
1883
+ const t = r.trim();
1884
+ if (t) blocks.push(t);
1885
+ }
1886
+ return `${blocks.join("\n\n")}
1887
+ `;
1888
+ }
1889
+ function skipString(s, i) {
1890
+ const q = s[i];
1891
+ i++;
1892
+ while (i < s.length) {
1893
+ if (s[i] === "\\") {
1894
+ i += 2;
1895
+ continue;
1896
+ }
1897
+ if (s[i] === q) return i + 1;
1898
+ i++;
1899
+ }
1900
+ return i;
1901
+ }
1902
+ function readBlock(s, open) {
1903
+ let i = open + 1;
1904
+ let depth = 1;
1905
+ const bodyStart = i;
1906
+ while (i < s.length && depth > 0) {
1907
+ if (s[i] === "/" && s[i + 1] === "*") {
1908
+ const e = s.indexOf("*/", i + 2);
1909
+ i = e === -1 ? s.length : e + 2;
1910
+ continue;
1911
+ }
1912
+ if (s[i] === '"' || s[i] === "'") {
1913
+ i = skipString(s, i);
1914
+ continue;
1915
+ }
1916
+ if (s[i] === "{") depth++;
1917
+ else if (s[i] === "}") {
1918
+ depth--;
1919
+ if (depth === 0) break;
1920
+ }
1921
+ i++;
1922
+ }
1923
+ return { body: s.slice(bodyStart, i), end: i < s.length ? i + 1 : s.length };
1924
+ }
1925
+ function scanTopLevel(css) {
1926
+ const nodes = [];
1927
+ let i = 0;
1928
+ while (i < css.length) {
1929
+ while (i < css.length && /\s/.test(css[i])) i++;
1930
+ if (i >= css.length) break;
1931
+ if (css[i] === "/" && css[i + 1] === "*") {
1932
+ const e = css.indexOf("*/", i + 2);
1933
+ const stop = e === -1 ? css.length : e + 2;
1934
+ const text = css.slice(i, stop);
1935
+ nodes.push({ kind: "comment", text, raw: text });
1936
+ i = stop;
1937
+ continue;
1938
+ }
1939
+ const start = i;
1940
+ while (i < css.length) {
1941
+ const c = css[i];
1942
+ if (c === "/" && css[i + 1] === "*") {
1943
+ const e = css.indexOf("*/", i + 2);
1944
+ i = e === -1 ? css.length : e + 2;
1945
+ continue;
1946
+ }
1947
+ if (c === '"' || c === "'") {
1948
+ i = skipString(css, i);
1949
+ continue;
1950
+ }
1951
+ if (c === "{" || c === ";") break;
1952
+ i++;
1953
+ }
1954
+ if (i < css.length && css[i] === "{") {
1955
+ const prelude = css.slice(start, i).trim();
1956
+ const { body, end } = readBlock(css, i);
1957
+ nodes.push({ kind: "block", prelude, body, raw: css.slice(start, end) });
1958
+ i = end;
1959
+ } else {
1960
+ const stop = i < css.length ? i + 1 : css.length;
1961
+ const raw = css.slice(start, stop).trim();
1962
+ if (raw) nodes.push({ kind: "statement", raw });
1963
+ i = stop;
1964
+ }
1965
+ }
1966
+ return nodes;
1967
+ }
1968
+ function scanDeclarations(body) {
1969
+ const items = [];
1970
+ let i = 0;
1971
+ while (i < body.length) {
1972
+ while (i < body.length && /\s/.test(body[i])) i++;
1973
+ if (i >= body.length) break;
1974
+ if (body[i] === "/" && body[i + 1] === "*") {
1975
+ const e = body.indexOf("*/", i + 2);
1976
+ const stop = e === -1 ? body.length : e + 2;
1977
+ items.push({ kind: "comment", text: body.slice(i, stop) });
1978
+ i = stop;
1979
+ continue;
1980
+ }
1981
+ const start = i;
1982
+ while (i < body.length) {
1983
+ const c = body[i];
1984
+ if (c === "/" && body[i + 1] === "*") {
1985
+ const e = body.indexOf("*/", i + 2);
1986
+ i = e === -1 ? body.length : e + 2;
1987
+ continue;
1988
+ }
1989
+ if (c === '"' || c === "'") {
1990
+ i = skipString(body, i);
1991
+ continue;
1992
+ }
1993
+ if (c === ";") break;
1994
+ i++;
1995
+ }
1996
+ const text = body.slice(start, i).trim();
1997
+ i = i < body.length ? i + 1 : body.length;
1998
+ const colon = text.indexOf(":");
1999
+ if (colon > 0) {
2000
+ items.push({ kind: "decl", prop: text.slice(0, colon).trim(), value: text.slice(colon + 1).trim() });
2001
+ }
2002
+ }
2003
+ return items;
2004
+ }
2005
+ function commentInner(text) {
2006
+ return text.replace(/^\/\*+/, "").replace(/\*+\/$/, "").trim();
2007
+ }
2008
+ function isHeaderBanner(text) {
2009
+ const t = commentInner(text);
2010
+ return /meno design tokens/i.test(t) || /AUTO-GENERATED by meno-astro/i.test(t);
2011
+ }
2012
+ function prettifyName(name) {
2013
+ return name.replace(/[-_]/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\b\w/g, (c) => c.toUpperCase());
2014
+ }
2015
+ function maxWidthPx(prelude) {
2016
+ const m = prelude.match(/max-width:\s*(\d+)px/i);
2017
+ return m ? Number(m[1]) : null;
2018
+ }
2019
+ function bpNameForPx(px, breakpoints) {
2020
+ for (const [name, entry] of Object.entries(breakpoints)) if (entry.breakpoint === px) return name;
2021
+ return null;
2022
+ }
2023
+ function parseThemeCss(css, breakpoints) {
2024
+ const themesMap = {};
2025
+ const variables = [];
2026
+ const varByCssVar = /* @__PURE__ */ new Map();
2027
+ const raw = [];
2028
+ let defaultName = null;
2029
+ let region = null;
2030
+ for (const node of scanTopLevel(css)) {
2031
+ if (node.kind === "comment") {
2032
+ if (isHeaderBanner(node.text)) continue;
2033
+ const inner = commentInner(node.text);
2034
+ if (/responsive overrides/i.test(inner)) {
2035
+ region = "overrides";
2036
+ continue;
2037
+ }
2038
+ if (/responsive scaling|auto-generated from project\.config/i.test(inner)) {
2039
+ region = "auto";
2040
+ continue;
2041
+ }
2042
+ raw.push(node.raw);
2043
+ continue;
2044
+ }
2045
+ if (node.kind === "statement") {
2046
+ raw.push(node.raw);
2047
+ continue;
2048
+ }
2049
+ const sel = node.prelude;
2050
+ if (sel === ":root") {
2051
+ let section = null;
2052
+ for (const it of scanDeclarations(node.body)) {
2053
+ if (it.kind === "comment") {
2054
+ const inner = commentInner(it.text);
2055
+ if (/^colors\b/i.test(inner)) {
2056
+ section = "colors";
2057
+ const dn = inner.match(/^colors\s*:\s*([\w-]+)/i);
2058
+ if (dn) defaultName = dn[1];
2059
+ } else {
2060
+ const g = groupForSectionLabel(inner);
2061
+ if (g) section = g;
2062
+ }
2063
+ continue;
2064
+ }
2065
+ if (!it.prop.startsWith("--")) continue;
2066
+ const name = it.prop.slice(2);
2067
+ if (section === "colors" || section === null && isColorValue(it.value)) {
2068
+ const dn = defaultName ??= "default";
2069
+ (themesMap[dn] ??= { colors: {} }).colors[name] = it.value;
2070
+ } else {
2071
+ const group = section ?? inferGroup(it.prop, it.value);
2072
+ const v = { cssVar: it.prop, value: it.value, type: getDefaultScalingType(group), group };
2073
+ variables.push(v);
2074
+ varByCssVar.set(it.prop, v);
2075
+ }
2076
+ }
2077
+ continue;
2078
+ }
2079
+ const themeMatch = sel.match(/^\[theme=["']?([^"'\]]+)["']?\]$/);
2080
+ if (themeMatch) {
2081
+ const theme = themesMap[themeMatch[1]] ??= { colors: {} };
2082
+ for (const it of scanDeclarations(node.body)) {
2083
+ if (it.kind === "decl" && it.prop.startsWith("--")) theme.colors[it.prop.slice(2)] = it.value;
2084
+ }
2085
+ continue;
2086
+ }
2087
+ if (/^@media\b/i.test(sel)) {
2088
+ const px = maxWidthPx(sel);
2089
+ if (region === "auto") continue;
2090
+ const bpName = px != null && breakpoints ? bpNameForPx(px, breakpoints) : null;
2091
+ if (!bpName) {
2092
+ raw.push(node.raw);
2093
+ continue;
2094
+ }
2095
+ for (const inner of scanTopLevel(node.body)) {
2096
+ if (inner.kind !== "block" || inner.prelude !== ":root") continue;
2097
+ for (const it of scanDeclarations(inner.body)) {
2098
+ if (it.kind !== "decl" || !it.prop.startsWith("--")) continue;
2099
+ const v = varByCssVar.get(it.prop);
2100
+ if (v) (v.scales ??= {})[bpName] = it.value;
2101
+ }
2102
+ }
2103
+ continue;
2104
+ }
2105
+ raw.push(node.raw);
2106
+ }
2107
+ if (!defaultName) defaultName = Object.keys(themesMap)[0] ?? "default";
2108
+ (themesMap[defaultName] ??= { colors: {} }).label ??= prettifyName(defaultName);
2109
+ for (const [name, t] of Object.entries(themesMap)) t.label ??= prettifyName(name);
2110
+ return { themes: { default: defaultName, themes: themesMap }, variables, raw };
2111
+ }
2112
+
2113
+ // lib/server/themeCssStore.ts
2114
+ var log2 = createLogger("themeCssStore");
2115
+ function themeCssPath(root = getProjectRoot()) {
2116
+ return join2(root, "src", "styles", "theme.css");
2117
+ }
2118
+ function isThemeCssProject(root = getProjectRoot()) {
2119
+ if (existsSync2(themeCssPath(root))) return true;
2120
+ if (existsSync2(join2(root, "src", "pages"))) return true;
2121
+ try {
2122
+ const cfg = JSON.parse(readFileSync(join2(root, "project.config.json"), "utf8"));
2123
+ if (cfg.format === "astro") return true;
2124
+ } catch {
2125
+ }
2126
+ return false;
2127
+ }
2128
+ var writeChain = Promise.resolve();
2129
+ function enqueue(fn) {
2130
+ const run = writeChain.then(fn, fn);
2131
+ writeChain = run.then(
2132
+ () => void 0,
2133
+ () => void 0
2134
+ );
2135
+ return run;
2136
+ }
2137
+ async function readJsonSafe(path3) {
2138
+ try {
2139
+ return JSON.parse(await readTextFile(path3));
2140
+ } catch {
2141
+ return null;
2142
+ }
2143
+ }
2144
+ function scaleConfig() {
2145
+ return { breakpoints: configService.getBreakpoints(), responsiveScales: configService.getResponsiveScales() };
2146
+ }
2147
+ function emptyModel() {
2148
+ return { themes: { default: "default", themes: { default: { colors: {} } } }, variables: [], raw: [] };
2149
+ }
2150
+ async function readModel(root) {
2151
+ const path3 = themeCssPath(root);
2152
+ if (!await fileExists(path3)) return emptyModel();
2153
+ return parseThemeCss(await readTextFile(path3), configService.getBreakpoints());
2154
+ }
2155
+ async function writeModel(root, model) {
2156
+ const css = serializeThemeCss(model, scaleConfig());
2157
+ await ensureDir(join2(root, "src", "styles"));
2158
+ await writeFile(themeCssPath(root), css);
2159
+ }
2160
+ function hasColors(themes) {
2161
+ return Object.values(themes.themes ?? {}).some((t) => Object.keys(t.colors ?? {}).length > 0);
2162
+ }
2163
+ function mergeThemes(current, incoming) {
2164
+ if (!incoming?.themes) return current;
2165
+ if (!hasColors(current)) return incoming;
2166
+ const out = { default: current.default, palette: current.palette, themes: { ...current.themes } };
2167
+ for (const [name, theme] of Object.entries(incoming.themes)) {
2168
+ const existing = out.themes[name];
2169
+ out.themes[name] = existing ? { ...existing, colors: { ...theme.colors, ...existing.colors } } : theme;
2170
+ }
2171
+ return out;
2172
+ }
2173
+ function mergeVariables(current, incoming) {
2174
+ if (!incoming?.length) return current;
2175
+ const seen = new Set(current.map((v) => v.cssVar));
2176
+ return [...current, ...incoming.filter((v) => !seen.has(v.cssVar))];
2177
+ }
2178
+ var AUTHORED_MARKER = "Meno design tokens";
2179
+ async function migrateIfNeeded(root) {
2180
+ const colorsJson = join2(root, "colors.json");
2181
+ const variablesJson = join2(root, "variables.json");
2182
+ const hasColorsJson = existsSync2(colorsJson);
2183
+ const hasVarsJson = existsSync2(variablesJson);
2184
+ if (!hasColorsJson && !hasVarsJson) return;
2185
+ try {
2186
+ const jsonColors = hasColorsJson ? await readJsonSafe(colorsJson) : null;
2187
+ const jsonVars = hasVarsJson ? await readJsonSafe(variablesJson) : null;
2188
+ let current = emptyModel();
2189
+ let authored = false;
2190
+ if (await fileExists(themeCssPath(root))) {
2191
+ const text = await readTextFile(themeCssPath(root));
2192
+ authored = text.includes(AUTHORED_MARKER);
2193
+ current = parseThemeCss(text, configService.getBreakpoints());
2194
+ }
2195
+ const base = authored ? current : emptyModel();
2196
+ const merged = {
2197
+ themes: mergeThemes(base.themes, jsonColors?.themes ? jsonColors : null),
2198
+ variables: mergeVariables(base.variables, jsonVars?.variables),
2199
+ raw: current.raw
2200
+ };
2201
+ await writeModel(root, merged);
2202
+ await rm(colorsJson, { force: true });
2203
+ await rm(variablesJson, { force: true });
2204
+ log2.info("Folded colors.json / variables.json into src/styles/theme.css");
2205
+ } catch (err) {
2206
+ log2.warn("theme.css migration failed; keeping JSON files:", err);
2207
+ }
2208
+ }
2209
+ async function loadThemeModel(root = getProjectRoot()) {
2210
+ await configService.load();
2211
+ return enqueue(async () => {
2212
+ await migrateIfNeeded(root);
2213
+ return readModel(root);
2214
+ });
2215
+ }
2216
+ async function saveColors(themes, root = getProjectRoot()) {
2217
+ await configService.load();
2218
+ return enqueue(async () => {
2219
+ await migrateIfNeeded(root);
2220
+ const current = await readModel(root);
2221
+ await writeModel(root, { themes, variables: current.variables, raw: current.raw });
2222
+ });
2223
+ }
2224
+ async function saveVariables(variables, root = getProjectRoot()) {
2225
+ await configService.load();
2226
+ return enqueue(async () => {
2227
+ await migrateIfNeeded(root);
2228
+ const current = await readModel(root);
2229
+ await writeModel(root, { themes: current.themes, variables, raw: current.raw });
2230
+ });
2231
+ }
2232
+ async function regenerateThemeCss(root = getProjectRoot()) {
2233
+ await configService.load();
2234
+ return enqueue(async () => {
2235
+ await migrateIfNeeded(root);
2236
+ if (!await fileExists(themeCssPath(root))) return;
2237
+ await writeModel(root, await readModel(root));
2238
+ });
2239
+ }
2240
+
1733
2241
  // lib/server/services/ColorService.ts
1734
- var log2 = createLogger("ColorService");
2242
+ var log3 = createLogger("ColorService");
1735
2243
  var ColorService = class extends CachedConfigLoader {
1736
2244
  /**
1737
2245
  * Load theme configuration from colors.json
@@ -1740,9 +2248,19 @@ var ColorService = class extends CachedConfigLoader {
1740
2248
  return this.load();
1741
2249
  }
1742
2250
  /**
1743
- * Perform the actual loading from file
2251
+ * Perform the actual loading from file.
2252
+ * Astro projects read colors from `src/styles/theme.css` (the token source of truth);
2253
+ * legacy JSON projects read `colors.json`.
1744
2254
  */
1745
2255
  async performLoad() {
2256
+ if (isThemeCssProject()) {
2257
+ try {
2258
+ return (await loadThemeModel()).themes;
2259
+ } catch (error) {
2260
+ log3.warn("Failed to load colors from theme.css:", error);
2261
+ return this.getDefaultThemeConfig();
2262
+ }
2263
+ }
1746
2264
  try {
1747
2265
  const content = await loadJSONFile(projectPaths.colors());
1748
2266
  if (content) {
@@ -1752,7 +2270,7 @@ var ColorService = class extends CachedConfigLoader {
1752
2270
  }
1753
2271
  }
1754
2272
  } catch (error) {
1755
- log2.warn("Failed to load colors.json:", error);
2273
+ log3.warn("Failed to load colors.json:", error);
1756
2274
  }
1757
2275
  return this.getDefaultThemeConfig();
1758
2276
  }
@@ -1832,6 +2350,23 @@ var ColorService = class extends CachedConfigLoader {
1832
2350
  * Distinguishes between missing file, invalid JSON, and valid config
1833
2351
  */
1834
2352
  async getConfigWithStatus() {
2353
+ if (isThemeCssProject()) {
2354
+ const filePath2 = themeCssPath();
2355
+ if (!existsSync3(filePath2)) {
2356
+ return { status: "missing", config: this.getMinimalConfig(), filePath: filePath2 };
2357
+ }
2358
+ try {
2359
+ const model = await loadThemeModel();
2360
+ return { status: "valid", config: model.themes, filePath: filePath2 };
2361
+ } catch (error) {
2362
+ return {
2363
+ status: "invalid",
2364
+ config: this.getMinimalConfig(),
2365
+ error: error instanceof Error ? error.message : "Parse error",
2366
+ filePath: filePath2
2367
+ };
2368
+ }
2369
+ }
1835
2370
  const filePath = projectPaths.colors();
1836
2371
  try {
1837
2372
  const content = await loadJSONFile(filePath);
@@ -1882,7 +2417,7 @@ var ColorService = class extends CachedConfigLoader {
1882
2417
  const config = await this.loadThemeConfig();
1883
2418
  return Object.entries(config.themes).map(([name, theme]) => ({
1884
2419
  name,
1885
- label: theme.label
2420
+ label: theme.label ?? name
1886
2421
  }));
1887
2422
  }
1888
2423
  /**
@@ -1916,12 +2451,15 @@ var ColorService = class extends CachedConfigLoader {
1916
2451
  return this.loadThemeConfig();
1917
2452
  }
1918
2453
  /**
1919
- * Save theme configuration to colors.json
2454
+ * Save theme configuration. Astro projects write the colors half of
2455
+ * `src/styles/theme.css` (preserving variables); legacy JSON projects write `colors.json`.
1920
2456
  */
1921
2457
  async saveThemeConfig(config) {
1922
- const colorsPath = projectPaths.colors();
1923
- const content = JSON.stringify(config, null, 2);
1924
- await writeFile(colorsPath, content);
2458
+ if (isThemeCssProject()) {
2459
+ await saveColors(config);
2460
+ } else {
2461
+ await writeFile(projectPaths.colors(), JSON.stringify(config, null, 2));
2462
+ }
1925
2463
  this.setCache(config);
1926
2464
  }
1927
2465
  };
@@ -1948,7 +2486,8 @@ async function handleColorsStatusRoute() {
1948
2486
  }
1949
2487
 
1950
2488
  // lib/server/services/VariableService.ts
1951
- var log3 = createLogger("VariableService");
2489
+ import { existsSync as existsSync4 } from "node:fs";
2490
+ var log4 = createLogger("VariableService");
1952
2491
  var VariableService = class extends CachedConfigLoader {
1953
2492
  /**
1954
2493
  * Load variables configuration from variables.json
@@ -1957,6 +2496,14 @@ var VariableService = class extends CachedConfigLoader {
1957
2496
  return this.load();
1958
2497
  }
1959
2498
  async performLoad() {
2499
+ if (isThemeCssProject()) {
2500
+ try {
2501
+ return { variables: (await loadThemeModel()).variables };
2502
+ } catch (error) {
2503
+ log4.warn("Failed to load variables from theme.css:", error);
2504
+ return this.getDefaultConfig();
2505
+ }
2506
+ }
1960
2507
  try {
1961
2508
  const content = await loadJSONFile(projectPaths.variables());
1962
2509
  if (content) {
@@ -1966,7 +2513,7 @@ var VariableService = class extends CachedConfigLoader {
1966
2513
  }
1967
2514
  }
1968
2515
  } catch (error) {
1969
- log3.warn("Failed to load variables.json:", error);
2516
+ log4.warn("Failed to load variables.json:", error);
1970
2517
  }
1971
2518
  return this.getDefaultConfig();
1972
2519
  }
@@ -1979,7 +2526,7 @@ var VariableService = class extends CachedConfigLoader {
1979
2526
  migrateConfig(config) {
1980
2527
  for (const variable of config.variables) {
1981
2528
  if (variable.group === "spacing") {
1982
- const lower = `${variable.cssVar} ${variable.name}`.toLowerCase();
2529
+ const lower = `${variable.cssVar} ${variable.name ?? ""}`.toLowerCase();
1983
2530
  if (lower.includes("margin")) {
1984
2531
  variable.group = "margin";
1985
2532
  } else if (lower.includes("gap")) {
@@ -1995,6 +2542,22 @@ var VariableService = class extends CachedConfigLoader {
1995
2542
  * Get config with status info (for editor UI)
1996
2543
  */
1997
2544
  async getConfigWithStatus() {
2545
+ if (isThemeCssProject()) {
2546
+ const filePath2 = themeCssPath();
2547
+ if (!existsSync4(filePath2)) {
2548
+ return { status: "missing", config: this.getDefaultConfig(), filePath: filePath2 };
2549
+ }
2550
+ try {
2551
+ return { status: "valid", config: { variables: (await loadThemeModel()).variables }, filePath: filePath2 };
2552
+ } catch (error) {
2553
+ return {
2554
+ status: "invalid",
2555
+ config: this.getDefaultConfig(),
2556
+ error: error instanceof Error ? error.message : "Parse error",
2557
+ filePath: filePath2
2558
+ };
2559
+ }
2560
+ }
1998
2561
  const filePath = projectPaths.variables();
1999
2562
  try {
2000
2563
  const content = await loadJSONFile(filePath);
@@ -2021,12 +2584,15 @@ var VariableService = class extends CachedConfigLoader {
2021
2584
  }
2022
2585
  }
2023
2586
  /**
2024
- * Save variables configuration to variables.json
2587
+ * Save variables configuration. Astro projects write the variables half of
2588
+ * `src/styles/theme.css` (preserving colors); legacy JSON projects write `variables.json`.
2025
2589
  */
2026
2590
  async saveConfig(config) {
2027
- const variablesPath = projectPaths.variables();
2028
- const content = JSON.stringify(config, null, 2);
2029
- await writeFile(variablesPath, content);
2591
+ if (isThemeCssProject()) {
2592
+ await saveVariables(config.variables);
2593
+ } else {
2594
+ await writeFile(projectPaths.variables(), JSON.stringify(config, null, 2));
2595
+ }
2030
2596
  this.setCache(config);
2031
2597
  }
2032
2598
  };
@@ -2142,7 +2708,7 @@ async function handleVariablesCSSRoute() {
2142
2708
  }
2143
2709
 
2144
2710
  // lib/server/services/EnumService.ts
2145
- var log4 = createLogger("EnumService");
2711
+ var log5 = createLogger("EnumService");
2146
2712
  var EnumService = class extends CachedConfigLoader {
2147
2713
  /**
2148
2714
  * Load enums configuration from enums.json
@@ -2162,7 +2728,7 @@ var EnumService = class extends CachedConfigLoader {
2162
2728
  return this.validateEnums(data);
2163
2729
  }
2164
2730
  } catch (error) {
2165
- log4.warn("Failed to parse enums.json:", error);
2731
+ log5.warn("Failed to parse enums.json:", error);
2166
2732
  }
2167
2733
  }
2168
2734
  if (configContent) {
@@ -8440,8 +9006,8 @@ ${plainTextErrors}`;
8440
9006
  }
8441
9007
 
8442
9008
  // lib/server/services/pageService.ts
8443
- import { existsSync as existsSync2, readdirSync as readdirSync2, mkdirSync, rmdirSync } from "node:fs";
8444
- import { join as join3 } from "node:path";
9009
+ import { existsSync as existsSync5, readdirSync as readdirSync2, mkdirSync, rmdirSync } from "node:fs";
9010
+ import { join as join4 } from "node:path";
8445
9011
 
8446
9012
  // lib/server/utils/jsonLineMapper.ts
8447
9013
  function buildLineMap(jsonText) {
@@ -8853,7 +9419,7 @@ var PageService = class {
8853
9419
  */
8854
9420
  getAllFolders() {
8855
9421
  const pagesDir = this.pagesBaseDir();
8856
- if (!existsSync2(pagesDir)) {
9422
+ if (!existsSync5(pagesDir)) {
8857
9423
  return [];
8858
9424
  }
8859
9425
  const collectFolders = (dir, prefix) => {
@@ -8864,7 +9430,7 @@ var PageService = class {
8864
9430
  if (!entry.isDirectory()) continue;
8865
9431
  const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
8866
9432
  result.push(relativePath);
8867
- result.push(...collectFolders(join3(dir, entry.name), relativePath));
9433
+ result.push(...collectFolders(join4(dir, entry.name), relativePath));
8868
9434
  }
8869
9435
  return result;
8870
9436
  } catch {
@@ -8895,8 +9461,8 @@ var PageService = class {
8895
9461
  }
8896
9462
  }
8897
9463
  const pagesDir = this.pagesBaseDir();
8898
- const folderPath = join3(pagesDir, trimmed);
8899
- if (existsSync2(folderPath)) {
9464
+ const folderPath = join4(pagesDir, trimmed);
9465
+ if (existsSync5(folderPath)) {
8900
9466
  throw new Error("Folder already exists");
8901
9467
  }
8902
9468
  mkdirSync(folderPath, { recursive: true });
@@ -8917,18 +9483,18 @@ var PageService = class {
8917
9483
  const pageName = pagePath === "/" ? "index" : pagePath.substring(1);
8918
9484
  const slashIndex = pageName.lastIndexOf("/");
8919
9485
  const baseName = slashIndex >= 0 ? pageName.substring(slashIndex + 1) : pageName;
8920
- const sourceFile = join3(pagesDir, `${pageName}${ext}`);
8921
- const targetFile = newFolder ? join3(pagesDir, newFolder, `${baseName}${ext}`) : join3(pagesDir, `${baseName}${ext}`);
9486
+ const sourceFile = join4(pagesDir, `${pageName}${ext}`);
9487
+ const targetFile = newFolder ? join4(pagesDir, newFolder, `${baseName}${ext}`) : join4(pagesDir, `${baseName}${ext}`);
8922
9488
  if (!isPathWithinRoot(sourceFile, pagesDir) || !isPathWithinRoot(targetFile, pagesDir)) {
8923
9489
  throw new Error(`movePage path escapes pages dir: ${pagePath} -> ${newFolder}`);
8924
9490
  }
8925
9491
  if (newFolder) {
8926
- const targetDir = join3(pagesDir, newFolder);
8927
- if (!existsSync2(targetDir)) {
9492
+ const targetDir = join4(pagesDir, newFolder);
9493
+ if (!existsSync5(targetDir)) {
8928
9494
  mkdirSync(targetDir, { recursive: true });
8929
9495
  }
8930
9496
  }
8931
- if (!existsSync2(sourceFile)) {
9497
+ if (!existsSync5(sourceFile)) {
8932
9498
  throw new Error(`Page not found: ${pagePath}`);
8933
9499
  }
8934
9500
  await rename2(sourceFile, targetFile);
@@ -8940,7 +9506,7 @@ var PageService = class {
8940
9506
  const lineMap = buildLineMap(content);
8941
9507
  this.pageCache.set(newPath, content, lineMap);
8942
9508
  }
8943
- const sourceDir = slashIndex >= 0 ? join3(pagesDir, pageName.substring(0, slashIndex)) : null;
9509
+ const sourceDir = slashIndex >= 0 ? join4(pagesDir, pageName.substring(0, slashIndex)) : null;
8944
9510
  if (sourceDir && sourceDir !== pagesDir) {
8945
9511
  try {
8946
9512
  const remaining = readdirSync2(sourceDir);
@@ -8989,12 +9555,12 @@ var PageService = class {
8989
9555
  const { rename: rename2 } = await import("node:fs/promises");
8990
9556
  const pagesDir = this.pagesBaseDir();
8991
9557
  const ext = this.pageExt();
8992
- const sourceFile = join3(pagesDir, `${oldName}${ext}`);
8993
- const targetFile = join3(pagesDir, `${newName}${ext}`);
8994
- if (!existsSync2(sourceFile)) {
9558
+ const sourceFile = join4(pagesDir, `${oldName}${ext}`);
9559
+ const targetFile = join4(pagesDir, `${newName}${ext}`);
9560
+ if (!existsSync5(sourceFile)) {
8995
9561
  throw new Error(`Page not found: ${oldPath}`);
8996
9562
  }
8997
- if (existsSync2(targetFile)) {
9563
+ if (existsSync5(targetFile)) {
8998
9564
  throw new Error(`Page already exists: ${newPath}`);
8999
9565
  }
9000
9566
  await rename2(sourceFile, targetFile);
@@ -9044,8 +9610,8 @@ var PageService = class {
9044
9610
  };
9045
9611
 
9046
9612
  // lib/server/services/componentService.ts
9047
- import { join as join4 } from "node:path";
9048
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync as readdirSync3, rmdirSync as rmdirSync2 } from "node:fs";
9613
+ import { join as join5 } from "node:path";
9614
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, readdirSync as readdirSync3, rmdirSync as rmdirSync2 } from "node:fs";
9049
9615
  var ComponentService = class {
9050
9616
  components = /* @__PURE__ */ new Map();
9051
9617
  componentCategories = /* @__PURE__ */ new Map();
@@ -9277,7 +9843,7 @@ var ComponentService = class {
9277
9843
  const componentsDir = this.componentsBaseDir();
9278
9844
  if (!isSafePathSegment(name)) throw new Error(`unsafe component name: ${name}`);
9279
9845
  const cat = this.resolveComponentCategory(name, category);
9280
- const dir = cat ? join4(componentsDir, cat) : componentsDir;
9846
+ const dir = cat ? join5(componentsDir, cat) : componentsDir;
9281
9847
  if (!isPathWithinRoot(dir, componentsDir)) throw new Error(`component category escapes components dir: ${cat}`);
9282
9848
  return dir;
9283
9849
  }
@@ -9308,10 +9874,10 @@ var ComponentService = class {
9308
9874
  */
9309
9875
  findComponentCategoryOnDisk(name) {
9310
9876
  const componentsDir = this.componentsBaseDir();
9311
- if (!existsSync3(componentsDir)) return void 0;
9877
+ if (!existsSync6(componentsDir)) return void 0;
9312
9878
  const ext = this.writer ? null : ".json";
9313
9879
  const existsAt = (dir) => {
9314
- if (ext) return existsSync3(join4(dir, `${name}${ext}`));
9880
+ if (ext) return existsSync6(join5(dir, `${name}${ext}`));
9315
9881
  try {
9316
9882
  return readdirSync3(dir, { withFileTypes: true }).some(
9317
9883
  (e) => e.isFile() && (e.name === `${name}.json` || e.name === `${name}.astro`)
@@ -9323,7 +9889,7 @@ var ComponentService = class {
9323
9889
  if (existsAt(componentsDir)) return void 0;
9324
9890
  try {
9325
9891
  for (const entry of readdirSync3(componentsDir, { withFileTypes: true })) {
9326
- if (entry.isDirectory() && existsAt(join4(componentsDir, entry.name))) {
9892
+ if (entry.isDirectory() && existsAt(join5(componentsDir, entry.name))) {
9327
9893
  return entry.name;
9328
9894
  }
9329
9895
  }
@@ -9350,7 +9916,7 @@ var ComponentService = class {
9350
9916
  */
9351
9917
  async getComponentJavaScript(name) {
9352
9918
  const componentDir = this.getComponentDir(name);
9353
- const jsFilePath = join4(componentDir, `${name}.js`);
9919
+ const jsFilePath = join5(componentDir, `${name}.js`);
9354
9920
  try {
9355
9921
  if (await fileExists(jsFilePath)) {
9356
9922
  return await readTextFile(jsFilePath);
@@ -9398,15 +9964,15 @@ var ComponentService = class {
9398
9964
  const dataWithJS = javascript !== void 0 ? { ...dataWithoutJS, component: { ...dataWithoutJS.component, javascript } } : dataWithoutJS;
9399
9965
  const targetCategory = this.resolveComponentCategory(name, category);
9400
9966
  const componentsDir = this.componentsBaseDir();
9401
- const componentDir = targetCategory ? join4(componentsDir, targetCategory) : componentsDir;
9967
+ const componentDir = targetCategory ? join5(componentsDir, targetCategory) : componentsDir;
9402
9968
  if (this.writer) {
9403
9969
  await this.writer.writeComponent(componentDir, name, dataWithJS);
9404
9970
  } else {
9405
9971
  const writeFile3 = this.fs ? this.fs.writeFile.bind(this.fs) : (await import("node:fs/promises")).writeFile;
9406
- if (targetCategory && !existsSync3(componentDir)) {
9972
+ if (targetCategory && !existsSync6(componentDir)) {
9407
9973
  mkdirSync2(componentDir, { recursive: true });
9408
9974
  }
9409
- const filePath = join4(componentDir, `${name}.json`);
9975
+ const filePath = join5(componentDir, `${name}.json`);
9410
9976
  await writeFile3(filePath, JSON.stringify(dataWithoutJS, null, 2), "utf-8");
9411
9977
  }
9412
9978
  this.components.set(name, dataWithJS);
@@ -9439,9 +10005,9 @@ var ComponentService = class {
9439
10005
  return;
9440
10006
  }
9441
10007
  const writeFile3 = this.fs ? this.fs.writeFile.bind(this.fs) : (await import("node:fs/promises")).writeFile;
9442
- const jsFilePath = join4(componentDir, `${name}.js`);
10008
+ const jsFilePath = join5(componentDir, `${name}.js`);
9443
10009
  await writeFile3(jsFilePath, javascript || "", "utf-8");
9444
- const componentPath = join4(componentDir, `${name}.json`);
10010
+ const componentPath = join5(componentDir, `${name}.json`);
9445
10011
  const componentData = await loadJSONFile(componentPath);
9446
10012
  if (componentData) {
9447
10013
  const parsed = parseJSON(componentData);
@@ -9485,9 +10051,9 @@ var ComponentService = class {
9485
10051
  return;
9486
10052
  }
9487
10053
  const writeFile3 = this.fs ? this.fs.writeFile.bind(this.fs) : (await import("node:fs/promises")).writeFile;
9488
- const cssFilePath = join4(componentDir, `${name}.css`);
10054
+ const cssFilePath = join5(componentDir, `${name}.css`);
9489
10055
  await writeFile3(cssFilePath, css || "", "utf-8");
9490
- const componentPath = join4(componentDir, `${name}.json`);
10056
+ const componentPath = join5(componentDir, `${name}.json`);
9491
10057
  const componentData = await loadJSONFile(componentPath);
9492
10058
  if (componentData) {
9493
10059
  const parsed = parseJSON(componentData);
@@ -9520,7 +10086,7 @@ var ComponentService = class {
9520
10086
  */
9521
10087
  getAllFolders() {
9522
10088
  const componentsDir = this.componentsBaseDir();
9523
- if (!existsSync3(componentsDir)) {
10089
+ if (!existsSync6(componentsDir)) {
9524
10090
  return [];
9525
10091
  }
9526
10092
  try {
@@ -9555,8 +10121,8 @@ var ComponentService = class {
9555
10121
  throw new Error("Folder name can only contain lowercase letters, numbers, dashes, and underscores");
9556
10122
  }
9557
10123
  const componentsDir = this.componentsBaseDir();
9558
- const folderPath = join4(componentsDir, folderName);
9559
- if (existsSync3(folderPath)) {
10124
+ const folderPath = join5(componentsDir, folderName);
10125
+ if (existsSync6(folderPath)) {
9560
10126
  throw new Error("Folder already exists");
9561
10127
  }
9562
10128
  mkdirSync2(folderPath, { recursive: true });
@@ -9589,20 +10155,20 @@ var ComponentService = class {
9589
10155
  return;
9590
10156
  }
9591
10157
  const componentsDir = this.componentsBaseDir();
9592
- const sourceDir = currentCategory ? join4(componentsDir, currentCategory) : componentsDir;
9593
- const targetDir = targetCategory ? join4(componentsDir, targetCategory) : componentsDir;
10158
+ const sourceDir = currentCategory ? join5(componentsDir, currentCategory) : componentsDir;
10159
+ const targetDir = targetCategory ? join5(componentsDir, targetCategory) : componentsDir;
9594
10160
  if (this.writer) {
9595
10161
  await this.writer.moveComponent(sourceDir, targetDir, name);
9596
10162
  } else {
9597
- if (targetCategory && !existsSync3(targetDir)) {
10163
+ if (targetCategory && !existsSync6(targetDir)) {
9598
10164
  mkdirSync2(targetDir, { recursive: true });
9599
10165
  }
9600
10166
  const extensions = [".json", ".js", ".css"];
9601
10167
  const { rename: rename2 } = await import("node:fs/promises");
9602
10168
  for (const ext of extensions) {
9603
- const sourcePath = join4(sourceDir, `${name}${ext}`);
9604
- const targetPath = join4(targetDir, `${name}${ext}`);
9605
- if (existsSync3(sourcePath)) {
10169
+ const sourcePath = join5(sourceDir, `${name}${ext}`);
10170
+ const targetPath = join5(targetDir, `${name}${ext}`);
10171
+ if (existsSync6(sourcePath)) {
9606
10172
  await rename2(sourcePath, targetPath);
9607
10173
  }
9608
10174
  }
@@ -9657,7 +10223,7 @@ var ComponentService = class {
9657
10223
  }
9658
10224
  const category = this.componentCategories.get(oldName);
9659
10225
  const componentsDir = this.componentsBaseDir();
9660
- const dir = category ? join4(componentsDir, category) : componentsDir;
10226
+ const dir = category ? join5(componentsDir, category) : componentsDir;
9661
10227
  if (this.writer) {
9662
10228
  if (await this.writer.componentExists(dir, trimmedNew)) {
9663
10229
  throw new Error(`Component "${trimmedNew}" already exists in components/${category ?? ""}`);
@@ -9665,15 +10231,15 @@ var ComponentService = class {
9665
10231
  await this.writer.moveComponent(dir, dir, oldName, trimmedNew);
9666
10232
  } else {
9667
10233
  for (const ext of [".json", ".js", ".css"]) {
9668
- if (existsSync3(join4(dir, `${trimmedNew}${ext}`))) {
10234
+ if (existsSync6(join5(dir, `${trimmedNew}${ext}`))) {
9669
10235
  throw new Error(`File "${trimmedNew}${ext}" already exists in components/${category ?? ""}`);
9670
10236
  }
9671
10237
  }
9672
10238
  const { rename: rename2 } = await import("node:fs/promises");
9673
10239
  for (const ext of [".json", ".js", ".css"]) {
9674
- const src = join4(dir, `${oldName}${ext}`);
9675
- const dst = join4(dir, `${trimmedNew}${ext}`);
9676
- if (existsSync3(src)) {
10240
+ const src = join5(dir, `${oldName}${ext}`);
10241
+ const dst = join5(dir, `${trimmedNew}${ext}`);
10242
+ if (existsSync6(src)) {
9677
10243
  await rename2(src, dst);
9678
10244
  }
9679
10245
  }
@@ -9691,7 +10257,7 @@ var ComponentService = class {
9691
10257
  if (!structure) continue;
9692
10258
  if (rewriteComponentRefs(structure, oldName, trimmedNew)) {
9693
10259
  const otherCategory = this.componentCategories.get(name);
9694
- const otherDir = otherCategory ? join4(componentsDir, otherCategory) : componentsDir;
10260
+ const otherDir = otherCategory ? join5(componentsDir, otherCategory) : componentsDir;
9695
10261
  const persisted = JSON.parse(JSON.stringify(otherDef));
9696
10262
  if (persisted?.component?.javascript !== void 0) {
9697
10263
  delete persisted.component.javascript;
@@ -9699,7 +10265,7 @@ var ComponentService = class {
9699
10265
  if (this.writer) {
9700
10266
  await this.writer.writeComponent(otherDir, name, persisted);
9701
10267
  } else {
9702
- await writeFile3(join4(otherDir, `${name}.json`), JSON.stringify(persisted, null, 2), "utf-8");
10268
+ await writeFile3(join5(otherDir, `${name}.json`), JSON.stringify(persisted, null, 2), "utf-8");
9703
10269
  }
9704
10270
  componentRefs++;
9705
10271
  }
@@ -10239,9 +10805,9 @@ var CMSService = class {
10239
10805
  };
10240
10806
 
10241
10807
  // lib/server/providers/fileSystemCMSProvider.ts
10242
- import { existsSync as existsSync4, readdirSync as readdirSync4, mkdirSync as mkdirSync3 } from "node:fs";
10243
- import { join as join5 } from "node:path";
10244
- var log5 = createLogger("FileSystemCMSProvider");
10808
+ import { existsSync as existsSync7, readdirSync as readdirSync4, mkdirSync as mkdirSync3 } from "node:fs";
10809
+ import { join as join6 } from "node:path";
10810
+ var log6 = createLogger("FileSystemCMSProvider");
10245
10811
  var DRAFT_FILE_SUFFIX = `${CMS_DRAFT_SUFFIX}.json`;
10246
10812
  async function loadJSONFile2(filePath) {
10247
10813
  try {
@@ -10250,7 +10816,7 @@ async function loadJSONFile2(filePath) {
10250
10816
  }
10251
10817
  return null;
10252
10818
  } catch (error) {
10253
- log5.warn(`Failed to parse JSON at ${filePath}:`, error instanceof Error ? error.message : error);
10819
+ log6.warn(`Failed to parse JSON at ${filePath}:`, error instanceof Error ? error.message : error);
10254
10820
  return null;
10255
10821
  }
10256
10822
  }
@@ -10312,14 +10878,14 @@ var FileSystemCMSProvider = class {
10312
10878
  return this.schemaCache;
10313
10879
  }
10314
10880
  const schemas = /* @__PURE__ */ new Map();
10315
- if (!existsSync4(this.templatesDir)) {
10881
+ if (!existsSync7(this.templatesDir)) {
10316
10882
  return schemas;
10317
10883
  }
10318
10884
  const files = readdirSync4(this.templatesDir);
10319
10885
  const jsonFiles = files.filter((f) => f.endsWith(".json"));
10320
10886
  const results = await Promise.all(
10321
10887
  jsonFiles.map(async (file) => {
10322
- const filePath = join5(this.templatesDir, file);
10888
+ const filePath = join6(this.templatesDir, file);
10323
10889
  const content = await loadJSONFile2(filePath);
10324
10890
  return { filePath, content };
10325
10891
  })
@@ -10344,15 +10910,15 @@ var FileSystemCMSProvider = class {
10344
10910
  */
10345
10911
  async getItems(collection) {
10346
10912
  this.validateCollection(collection);
10347
- const collectionDir = join5(this.cmsDir, collection);
10348
- if (!existsSync4(collectionDir)) {
10913
+ const collectionDir = join6(this.cmsDir, collection);
10914
+ if (!existsSync7(collectionDir)) {
10349
10915
  return [];
10350
10916
  }
10351
10917
  const files = readdirSync4(collectionDir);
10352
10918
  const jsonFiles = files.filter((f) => f.endsWith(".json") && !f.endsWith(DRAFT_FILE_SUFFIX));
10353
10919
  const results = await Promise.all(
10354
10920
  jsonFiles.map(async (file) => {
10355
- const filePath = join5(collectionDir, file);
10921
+ const filePath = join6(collectionDir, file);
10356
10922
  const content = await loadJSONFile2(filePath);
10357
10923
  return { file, filePath, content };
10358
10924
  })
@@ -10366,7 +10932,7 @@ var FileSystemCMSProvider = class {
10366
10932
  if (validation.valid) {
10367
10933
  items.push(validation.data);
10368
10934
  } else {
10369
- log5.warn(`Invalid CMS item at ${filePath}:`, validation.errors);
10935
+ log6.warn(`Invalid CMS item at ${filePath}:`, validation.errors);
10370
10936
  }
10371
10937
  }
10372
10938
  }
@@ -10385,7 +10951,7 @@ var FileSystemCMSProvider = class {
10385
10951
  async getItemByFilename(collection, filename) {
10386
10952
  this.validateCollection(collection);
10387
10953
  this.validateFilename(filename);
10388
- const filePath = join5(this.cmsDir, collection, `${filename}.json`);
10954
+ const filePath = join6(this.cmsDir, collection, `${filename}.json`);
10389
10955
  const content = await loadJSONFile2(filePath);
10390
10956
  if (!content || typeof content !== "object") {
10391
10957
  return null;
@@ -10395,7 +10961,7 @@ var FileSystemCMSProvider = class {
10395
10961
  if (validation.valid) {
10396
10962
  return validation.data;
10397
10963
  }
10398
- log5.warn(`Invalid CMS item at ${filePath}:`, validation.errors);
10964
+ log6.warn(`Invalid CMS item at ${filePath}:`, validation.errors);
10399
10965
  return null;
10400
10966
  }
10401
10967
  /**
@@ -10437,12 +11003,12 @@ var FileSystemCMSProvider = class {
10437
11003
  throw new Error("Cannot derive filename: item is missing _id, _filename, and a usable slug-field value.");
10438
11004
  }
10439
11005
  this.validateFilename(filename);
10440
- const collectionDir = join5(this.cmsDir, collection);
10441
- if (!existsSync4(collectionDir)) {
11006
+ const collectionDir = join6(this.cmsDir, collection);
11007
+ if (!existsSync7(collectionDir)) {
10442
11008
  mkdirSync3(collectionDir, { recursive: true });
10443
11009
  }
10444
11010
  const itemData = stripTransient(item);
10445
- const filePath = join5(collectionDir, `${filename}.json`);
11011
+ const filePath = join6(collectionDir, `${filename}.json`);
10446
11012
  await writeFile3(filePath, JSON.stringify(itemData, null, 2), "utf-8");
10447
11013
  }
10448
11014
  /**
@@ -10452,18 +11018,18 @@ var FileSystemCMSProvider = class {
10452
11018
  this.validateCollection(collection);
10453
11019
  this.validateFilename(filename);
10454
11020
  const { unlink } = await import("node:fs/promises");
10455
- const publishedPath = join5(this.cmsDir, collection, `${filename}.json`);
10456
- if (existsSync4(publishedPath)) {
11021
+ const publishedPath = join6(this.cmsDir, collection, `${filename}.json`);
11022
+ if (existsSync7(publishedPath)) {
10457
11023
  await unlink(publishedPath);
10458
11024
  }
10459
11025
  const draftPath = this.draftPath(collection, filename);
10460
- if (existsSync4(draftPath)) {
11026
+ if (existsSync7(draftPath)) {
10461
11027
  await unlink(draftPath);
10462
11028
  }
10463
11029
  }
10464
11030
  // ---- Draft helpers ----------------------------------------------------
10465
11031
  draftPath(collection, filename) {
10466
- return join5(this.cmsDir, collection, `${filename}${DRAFT_FILE_SUFFIX}`);
11032
+ return join6(this.cmsDir, collection, `${filename}${DRAFT_FILE_SUFFIX}`);
10467
11033
  }
10468
11034
  /**
10469
11035
  * Get the draft version of an item, or null if no draft file exists.
@@ -10490,12 +11056,12 @@ var FileSystemCMSProvider = class {
10490
11056
  */
10491
11057
  async getAllDrafts(collection) {
10492
11058
  this.validateCollection(collection);
10493
- const collectionDir = join5(this.cmsDir, collection);
10494
- if (!existsSync4(collectionDir)) return [];
11059
+ const collectionDir = join6(this.cmsDir, collection);
11060
+ if (!existsSync7(collectionDir)) return [];
10495
11061
  const files = readdirSync4(collectionDir).filter((f) => f.endsWith(DRAFT_FILE_SUFFIX));
10496
11062
  const results = await Promise.all(
10497
11063
  files.map(async (file) => {
10498
- const filePath = join5(collectionDir, file);
11064
+ const filePath = join6(collectionDir, file);
10499
11065
  const content = await loadJSONFile2(filePath);
10500
11066
  return { file, content };
10501
11067
  })
@@ -10517,7 +11083,7 @@ var FileSystemCMSProvider = class {
10517
11083
  async hasDraft(collection, filename) {
10518
11084
  this.validateCollection(collection);
10519
11085
  this.validateFilename(filename);
10520
- return existsSync4(this.draftPath(collection, filename));
11086
+ return existsSync7(this.draftPath(collection, filename));
10521
11087
  }
10522
11088
  /**
10523
11089
  * Save the draft version of an item. Loose validation — drafts may have
@@ -10551,8 +11117,8 @@ var FileSystemCMSProvider = class {
10551
11117
  throw new Error("Cannot derive draft filename: item is missing _id, _filename, and a usable slug-field value.");
10552
11118
  }
10553
11119
  this.validateFilename(filename);
10554
- const collectionDir = join5(this.cmsDir, collection);
10555
- if (!existsSync4(collectionDir)) {
11120
+ const collectionDir = join6(this.cmsDir, collection);
11121
+ if (!existsSync7(collectionDir)) {
10556
11122
  mkdirSync3(collectionDir, { recursive: true });
10557
11123
  }
10558
11124
  const itemData = stripTransient(item);
@@ -10572,7 +11138,7 @@ var FileSystemCMSProvider = class {
10572
11138
  this.validateFilename(filename);
10573
11139
  const { unlink } = await import("node:fs/promises");
10574
11140
  const filePath = this.draftPath(collection, filename);
10575
- if (existsSync4(filePath)) {
11141
+ if (existsSync7(filePath)) {
10576
11142
  await unlink(filePath);
10577
11143
  }
10578
11144
  }
@@ -10600,14 +11166,14 @@ var FileSystemCMSProvider = class {
10600
11166
  const messages = validation.errors.map((e) => `${e.path}: ${e.message}`).join(", ");
10601
11167
  throw new Error(`Cannot publish invalid draft: ${messages}`);
10602
11168
  }
10603
- const collectionDir = join5(this.cmsDir, collection);
10604
- if (!existsSync4(collectionDir)) {
11169
+ const collectionDir = join6(this.cmsDir, collection);
11170
+ if (!existsSync7(collectionDir)) {
10605
11171
  mkdirSync3(collectionDir, { recursive: true });
10606
11172
  }
10607
11173
  const itemData = stripTransient(validation.data);
10608
- const publishedPath = join5(collectionDir, `${filename}.json`);
11174
+ const publishedPath = join6(collectionDir, `${filename}.json`);
10609
11175
  await writeFile3(publishedPath, JSON.stringify(itemData, null, 2), "utf-8");
10610
- if (existsSync4(draftFilePath)) {
11176
+ if (existsSync7(draftFilePath)) {
10611
11177
  await unlink(draftFilePath);
10612
11178
  }
10613
11179
  return normalizeItem(itemData, filename);
@@ -10628,18 +11194,18 @@ var FileSystemCMSProvider = class {
10628
11194
  );
10629
11195
  }
10630
11196
  const { writeFile: writeFile3, mkdir } = await import("node:fs/promises");
10631
- if (!existsSync4(this.templatesDir)) {
11197
+ if (!existsSync7(this.templatesDir)) {
10632
11198
  await mkdir(this.templatesDir, { recursive: true });
10633
11199
  }
10634
- const pageFilePath = join5(this.templatesDir, `${collectionId}.json`);
10635
- if (existsSync4(pageFilePath)) {
11200
+ const pageFilePath = join6(this.templatesDir, `${collectionId}.json`);
11201
+ if (existsSync7(pageFilePath)) {
10636
11202
  throw new Error(`Page file already exists: templates/${collectionId}.json`);
10637
11203
  }
10638
11204
  await writeFile3(pageFilePath, JSON.stringify(pageData, null, 2), "utf-8");
10639
11205
  const schemaSource = pageData?.meta?.cms?.source;
10640
11206
  if (schemaSource !== "sanity") {
10641
- const collectionDir = join5(this.cmsDir, collectionId);
10642
- if (!existsSync4(collectionDir)) {
11207
+ const collectionDir = join6(this.cmsDir, collectionId);
11208
+ if (!existsSync7(collectionDir)) {
10643
11209
  await mkdir(collectionDir, { recursive: true });
10644
11210
  }
10645
11211
  }
@@ -10656,8 +11222,8 @@ var FileSystemCMSProvider = class {
10656
11222
  );
10657
11223
  }
10658
11224
  const { readFile: readFile2, writeFile: writeFile3 } = await import("node:fs/promises");
10659
- const pageFilePath = join5(this.templatesDir, `${collectionId}.json`);
10660
- if (!existsSync4(pageFilePath)) {
11225
+ const pageFilePath = join6(this.templatesDir, `${collectionId}.json`);
11226
+ if (!existsSync7(pageFilePath)) {
10661
11227
  throw new Error(`Collection not found: ${collectionId}`);
10662
11228
  }
10663
11229
  const content = await readFile2(pageFilePath, "utf-8");
@@ -10783,8 +11349,8 @@ var DraftPageStore = class {
10783
11349
  };
10784
11350
 
10785
11351
  // lib/server/fileWatcher.ts
10786
- import { watch, existsSync as existsSync5, statSync, readdirSync as readdirSync5 } from "node:fs";
10787
- import { basename as basename2, dirname as dirname2, join as join6, relative } from "node:path";
11352
+ import { watch, existsSync as existsSync8, statSync, readdirSync as readdirSync5 } from "node:fs";
11353
+ import { basename as basename2, dirname as dirname2, join as join7, relative } from "node:path";
10788
11354
  function watchRecursive(root, listener) {
10789
11355
  const nested = [];
10790
11356
  const watchedDirs = /* @__PURE__ */ new Set();
@@ -10800,7 +11366,7 @@ function watchRecursive(root, listener) {
10800
11366
  attachDir(abs);
10801
11367
  try {
10802
11368
  for (const e of readdirSync5(abs, { withFileTypes: true })) {
10803
- const child = join6(abs, e.name);
11369
+ const child = join7(abs, e.name);
10804
11370
  if (e.isDirectory()) coverNewDir(child);
10805
11371
  else listener("rename", relative(root, child));
10806
11372
  }
@@ -10814,7 +11380,7 @@ function watchRecursive(root, listener) {
10814
11380
  try {
10815
11381
  w = watch(absDir, { recursive: true }, (event, filename) => {
10816
11382
  if (!filename) return;
10817
- const abs = join6(absDir, filename);
11383
+ const abs = join7(absDir, filename);
10818
11384
  listener(event, relative(root, abs));
10819
11385
  coverNewDir(abs);
10820
11386
  });
@@ -10840,19 +11406,19 @@ function watchRecursive(root, listener) {
10840
11406
  return handle;
10841
11407
  }
10842
11408
  function attachWhenDirExists(dirPath, attach, setWatcher) {
10843
- if (existsSync5(dirPath)) {
11409
+ if (existsSync8(dirPath)) {
10844
11410
  setWatcher(attach());
10845
11411
  return;
10846
11412
  }
10847
11413
  const parentDir = dirname2(dirPath);
10848
11414
  const targetName = basename2(dirPath);
10849
- if (!existsSync5(parentDir)) {
11415
+ if (!existsSync8(parentDir)) {
10850
11416
  return;
10851
11417
  }
10852
11418
  let parentWatcher = null;
10853
11419
  parentWatcher = watch(parentDir, (_event, filename) => {
10854
11420
  if (filename !== targetName) return;
10855
- if (!existsSync5(dirPath)) return;
11421
+ if (!existsSync8(dirPath)) return;
10856
11422
  parentWatcher?.close();
10857
11423
  parentWatcher = null;
10858
11424
  setWatcher(attach());
@@ -10882,7 +11448,7 @@ var FileWatcher = class {
10882
11448
  * Watches both .json and .js files to detect component definition and JavaScript changes
10883
11449
  */
10884
11450
  watchComponents(dirPath = projectPaths.components()) {
10885
- if (!existsSync5(dirPath)) {
11451
+ if (!existsSync8(dirPath)) {
10886
11452
  return;
10887
11453
  }
10888
11454
  this.componentsWatcher = watchRecursive(dirPath, async (_event, filename) => {
@@ -10898,7 +11464,7 @@ var FileWatcher = class {
10898
11464
  * Start watching pages directory
10899
11465
  */
10900
11466
  watchPages(dirPath = projectPaths.pages()) {
10901
- if (!existsSync5(dirPath)) {
11467
+ if (!existsSync8(dirPath)) {
10902
11468
  return;
10903
11469
  }
10904
11470
  this.pagesWatcher = watchRecursive(dirPath, async (_event, filename) => {
@@ -10938,7 +11504,7 @@ var FileWatcher = class {
10938
11504
  * Start watching colors.json file
10939
11505
  */
10940
11506
  watchColors(filePath = projectPaths.colors()) {
10941
- if (!existsSync5(filePath)) {
11507
+ if (!existsSync8(filePath)) {
10942
11508
  return;
10943
11509
  }
10944
11510
  const dirPath = getProjectRoot();
@@ -10995,7 +11561,7 @@ var FileWatcher = class {
10995
11561
  * Start watching images directory for new source images
10996
11562
  */
10997
11563
  watchImages(dirPath = projectPaths.images()) {
10998
- if (!existsSync5(dirPath)) {
11564
+ if (!existsSync8(dirPath)) {
10999
11565
  return;
11000
11566
  }
11001
11567
  this.imagesWatcher = watch(dirPath, { recursive: false }, async (event, filename) => {
@@ -11022,7 +11588,7 @@ var FileWatcher = class {
11022
11588
  * Start watching libraries directory for CSS/JS changes
11023
11589
  */
11024
11590
  watchLibraries(dirPath = projectPaths.libraries()) {
11025
- if (!existsSync5(dirPath)) {
11591
+ if (!existsSync8(dirPath)) {
11026
11592
  return;
11027
11593
  }
11028
11594
  this.librariesWatcher = watchRecursive(dirPath, async (_event, filename) => {
@@ -11046,7 +11612,7 @@ var FileWatcher = class {
11046
11612
  * early-out and the first collection's item edits wouldn't live-reload until a
11047
11613
  * dev-server restart.
11048
11614
  */
11049
- watchAstroPages(dirPath = join6(getProjectRoot(), "src", "pages")) {
11615
+ watchAstroPages(dirPath = join7(getProjectRoot(), "src", "pages")) {
11050
11616
  attachWhenDirExists(
11051
11617
  dirPath,
11052
11618
  () => watchRecursive(dirPath, async (_event, filename) => {
@@ -11063,7 +11629,7 @@ var FileWatcher = class {
11063
11629
  }
11064
11630
  );
11065
11631
  }
11066
- watchAstroComponents(dirPath = join6(getProjectRoot(), "src", "components")) {
11632
+ watchAstroComponents(dirPath = join7(getProjectRoot(), "src", "components")) {
11067
11633
  attachWhenDirExists(
11068
11634
  dirPath,
11069
11635
  () => watchRecursive(dirPath, async (_event, filename) => {
@@ -11076,7 +11642,7 @@ var FileWatcher = class {
11076
11642
  }
11077
11643
  );
11078
11644
  }
11079
- watchAstroContent(dirPath = join6(getProjectRoot(), "src", "content")) {
11645
+ watchAstroContent(dirPath = join7(getProjectRoot(), "src", "content")) {
11080
11646
  attachWhenDirExists(
11081
11647
  dirPath,
11082
11648
  () => watchRecursive(dirPath, async (_event, filename) => {
@@ -11279,22 +11845,22 @@ var FileWatcherService = class {
11279
11845
  };
11280
11846
 
11281
11847
  // lib/server/migrateTemplates.ts
11282
- import { existsSync as existsSync6 } from "node:fs";
11848
+ import { existsSync as existsSync9 } from "node:fs";
11283
11849
  import { rename } from "node:fs/promises";
11284
- import { join as join7 } from "node:path";
11850
+ import { join as join8 } from "node:path";
11285
11851
  async function migrateTemplatesDirectory() {
11286
- const oldDir = join7(projectPaths.pages(), "templates");
11852
+ const oldDir = join8(projectPaths.pages(), "templates");
11287
11853
  const newDir = projectPaths.templates();
11288
- if (!existsSync6(oldDir)) return;
11289
- if (existsSync6(newDir)) return;
11854
+ if (!existsSync9(oldDir)) return;
11855
+ if (existsSync9(newDir)) return;
11290
11856
  await rename(oldDir, newDir);
11291
11857
  console.log("Migrated CMS templates: pages/templates/ \u2192 templates/");
11292
11858
  }
11293
11859
 
11294
11860
  // build-astro.ts
11295
- import { existsSync as existsSync7, readdirSync as readdirSync6, mkdirSync as mkdirSync4, rmSync, statSync as statSync2, copyFileSync, writeFileSync } from "node:fs";
11861
+ import { existsSync as existsSync10, readdirSync as readdirSync6, mkdirSync as mkdirSync4, rmSync, statSync as statSync2, copyFileSync, writeFileSync } from "node:fs";
11296
11862
  import { writeFile as writeFile2, readFile } from "node:fs/promises";
11297
- import { join as join8 } from "node:path";
11863
+ import { join as join9 } from "node:path";
11298
11864
  import { createHash } from "node:crypto";
11299
11865
 
11300
11866
  // lib/server/astro/tailwindMapper.ts
@@ -14147,23 +14713,23 @@ function writePageScript(javascript, scriptsDir) {
14147
14713
  if (!javascript) return [];
14148
14714
  const hash = hashContent3(javascript);
14149
14715
  const scriptFile = `${hash}.js`;
14150
- if (!existsSync7(scriptsDir)) {
14716
+ if (!existsSync10(scriptsDir)) {
14151
14717
  mkdirSync4(scriptsDir, { recursive: true });
14152
14718
  }
14153
- const fullScriptPath = join8(scriptsDir, scriptFile);
14154
- if (!existsSync7(fullScriptPath)) {
14719
+ const fullScriptPath = join9(scriptsDir, scriptFile);
14720
+ if (!existsSync10(fullScriptPath)) {
14155
14721
  writeFileSync(fullScriptPath, javascript, "utf-8");
14156
14722
  }
14157
14723
  return [`/_scripts/${scriptFile}`];
14158
14724
  }
14159
14725
  function copyDirectory(src, dest, filter) {
14160
- if (!existsSync7(src)) return;
14161
- if (!existsSync7(dest)) mkdirSync4(dest, { recursive: true });
14726
+ if (!existsSync10(src)) return;
14727
+ if (!existsSync10(dest)) mkdirSync4(dest, { recursive: true });
14162
14728
  const files = readdirSync6(src);
14163
14729
  for (const file of files) {
14164
14730
  if (filter && !filter(file)) continue;
14165
- const srcPath = join8(src, file);
14166
- const destPath = join8(dest, file);
14731
+ const srcPath = join9(src, file);
14732
+ const destPath = join9(dest, file);
14167
14733
  const stat = statSync2(srcPath);
14168
14734
  if (stat.isDirectory()) copyDirectory(srcPath, destPath, filter);
14169
14735
  else copyFileSync(srcPath, destPath);
@@ -14180,13 +14746,13 @@ function isCMSPage(pageData) {
14180
14746
  }
14181
14747
  function scanJSONFiles(dir, prefix = "") {
14182
14748
  const results = [];
14183
- if (!existsSync7(dir)) return results;
14749
+ if (!existsSync10(dir)) return results;
14184
14750
  const entries = readdirSync6(dir, { withFileTypes: true });
14185
14751
  for (const entry of entries) {
14186
14752
  if (entry.isFile() && entry.name.endsWith(".json")) {
14187
14753
  results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
14188
14754
  } else if (entry.isDirectory()) {
14189
- results.push(...scanJSONFiles(join8(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
14755
+ results.push(...scanJSONFiles(join9(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
14190
14756
  }
14191
14757
  }
14192
14758
  return results;
@@ -14352,23 +14918,23 @@ async function buildAstroProject(_projectRoot, outputDir) {
14352
14918
  const globalLibraries = configService.getLibraries();
14353
14919
  const componentLibraries = collectComponentLibraries(globalComponents);
14354
14920
  const imageMetadataMap = await buildImageMetadataMap();
14355
- const outDir = outputDir || join8(projectPaths.project, "astro-export");
14356
- if (existsSync7(outDir)) {
14921
+ const outDir = outputDir || join9(projectPaths.project, "astro-export");
14922
+ if (existsSync10(outDir)) {
14357
14923
  rmSync(outDir, { recursive: true, force: true });
14358
14924
  }
14359
14925
  mkdirSync4(outDir, { recursive: true });
14360
- const srcDir = join8(outDir, "src");
14361
- const pagesOutDir = join8(srcDir, "pages");
14362
- const layoutsDir = join8(srcDir, "layouts");
14363
- const stylesDir = join8(srcDir, "styles");
14364
- const componentsOutDir = join8(srcDir, "components");
14365
- const publicDir = join8(outDir, "public");
14366
- const scriptsDir = join8(publicDir, "_scripts");
14926
+ const srcDir = join9(outDir, "src");
14927
+ const pagesOutDir = join9(srcDir, "pages");
14928
+ const layoutsDir = join9(srcDir, "layouts");
14929
+ const stylesDir = join9(srcDir, "styles");
14930
+ const componentsOutDir = join9(srcDir, "components");
14931
+ const publicDir = join9(outDir, "public");
14932
+ const scriptsDir = join9(publicDir, "_scripts");
14367
14933
  for (const d of [srcDir, pagesOutDir, layoutsDir, stylesDir, componentsOutDir, publicDir]) {
14368
14934
  mkdirSync4(d, { recursive: true });
14369
14935
  }
14370
14936
  const pagesDir = projectPaths.pages();
14371
- if (!existsSync7(pagesDir)) {
14937
+ if (!existsSync10(pagesDir)) {
14372
14938
  console.error("Pages directory not found!");
14373
14939
  return { pages: 0, cmsPages: 0, collections: 0, errors: 1 };
14374
14940
  }
@@ -14381,7 +14947,7 @@ async function buildAstroProject(_projectRoot, outputDir) {
14381
14947
  for (const file of pageFiles) {
14382
14948
  const pageName = file.replace(".json", "");
14383
14949
  const basePath = mapPageNameToPath(pageName);
14384
- const pageContent = await loadJSONFile(join8(pagesDir, file));
14950
+ const pageContent = await loadJSONFile(join9(pagesDir, file));
14385
14951
  if (!pageContent) continue;
14386
14952
  try {
14387
14953
  const pageData = parseJSON(pageContent);
@@ -14440,7 +15006,7 @@ async function buildAstroProject(_projectRoot, outputDir) {
14440
15006
  for (const file of pageFiles) {
14441
15007
  const pageName = file.replace(".json", "");
14442
15008
  const basePath = mapPageNameToPath(pageName);
14443
- const pageContent = await loadJSONFile(join8(pagesDir, file));
15009
+ const pageContent = await loadJSONFile(join9(pagesDir, file));
14444
15010
  if (!pageContent) {
14445
15011
  console.warn(` Skipping ${basePath} (empty file)`);
14446
15012
  errorCount++;
@@ -14498,8 +15064,8 @@ async function buildAstroProject(_projectRoot, outputDir) {
14498
15064
  if (!css.url.startsWith("/")) continue;
14499
15065
  const shouldInline = css.inline !== false;
14500
15066
  const relPath = css.url.slice(1);
14501
- const srcPath = join8(projectPaths.project, relPath);
14502
- if (!existsSync7(srcPath)) continue;
15067
+ const srcPath = join9(projectPaths.project, relPath);
15068
+ if (!existsSync10(srcPath)) continue;
14503
15069
  if (shouldInline) {
14504
15070
  try {
14505
15071
  inlineContents.set(css.url, await readFile(srcPath, "utf-8"));
@@ -14513,7 +15079,7 @@ async function buildAstroProject(_projectRoot, outputDir) {
14513
15079
  for (const js of buildLibraries.js || []) {
14514
15080
  if (js.url.startsWith("/")) {
14515
15081
  const relPath = js.url.slice(1);
14516
- if (existsSync7(join8(projectPaths.project, relPath))) {
15082
+ if (existsSync10(join9(projectPaths.project, relPath))) {
14517
15083
  localLibsToCopy.push(relPath);
14518
15084
  }
14519
15085
  }
@@ -14534,9 +15100,9 @@ async function buildAstroProject(_projectRoot, outputDir) {
14534
15100
  const cmsConsumerComponents = computeCmsConsumerComponents(globalComponents);
14535
15101
  const collectionUrlExpr = /* @__PURE__ */ new Map();
14536
15102
  const mergedRichTextFields = /* @__PURE__ */ new Set();
14537
- if (existsSync7(templatesDir)) {
15103
+ if (existsSync10(templatesDir)) {
14538
15104
  for (const file of readdirSync6(templatesDir).filter((f) => f.endsWith(".json"))) {
14539
- const tc = await loadJSONFile(join8(templatesDir, file));
15105
+ const tc = await loadJSONFile(join9(templatesDir, file));
14540
15106
  if (!tc) continue;
14541
15107
  try {
14542
15108
  const pd = parseJSON(tc);
@@ -14550,10 +15116,10 @@ async function buildAstroProject(_projectRoot, outputDir) {
14550
15116
  }
14551
15117
  }
14552
15118
  }
14553
- if (existsSync7(templatesDir)) {
15119
+ if (existsSync10(templatesDir)) {
14554
15120
  const templateFiles = readdirSync6(templatesDir).filter((f) => f.endsWith(".json"));
14555
15121
  for (const file of templateFiles) {
14556
- const templateContent = await loadJSONFile(join8(templatesDir, file));
15122
+ const templateContent = await loadJSONFile(join9(templatesDir, file));
14557
15123
  if (!templateContent) continue;
14558
15124
  try {
14559
15125
  const pageData = parseJSON(templateContent);
@@ -14642,9 +15208,9 @@ async function buildAstroProject(_projectRoot, outputDir) {
14642
15208
  cmsConsumers: cmsConsumerComponents,
14643
15209
  collectionUrlExpr
14644
15210
  });
14645
- const astroFileFull = join8(pagesOutDir, astroFilePath);
15211
+ const astroFileFull = join9(pagesOutDir, astroFilePath);
14646
15212
  const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
14647
- if (!existsSync7(astroFileDir)) {
15213
+ if (!existsSync10(astroFileDir)) {
14648
15214
  mkdirSync4(astroFileDir, { recursive: true });
14649
15215
  }
14650
15216
  await writeFile2(astroFileFull, astroContent, "utf-8");
@@ -14676,7 +15242,7 @@ async function buildAstroProject(_projectRoot, outputDir) {
14676
15242
 
14677
15243
  ${safelistDirectives}` : `@import "tailwindcss";`;
14678
15244
  const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined].filter(Boolean).join("\n\n");
14679
- await writeFile2(join8(stylesDir, "global.css"), globalCSS, "utf-8");
15245
+ await writeFile2(join9(stylesDir, "global.css"), globalCSS, "utf-8");
14680
15246
  const escForTemplateLiteral = (s) => s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
14681
15247
  const customHeadLiteral = escForTemplateLiteral(customCode.head || "");
14682
15248
  const customBodyStartLiteral = escForTemplateLiteral(customCode.bodyStart || "");
@@ -14723,7 +15289,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
14723
15289
  </body>
14724
15290
  </html>
14725
15291
  `;
14726
- await writeFile2(join8(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
15292
+ await writeFile2(join9(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
14727
15293
  const emittableComponents = normalizeOrphanTemplateProps(globalComponents);
14728
15294
  let _componentFileCount = 0;
14729
15295
  for (const [compName, compDef] of Object.entries(emittableComponents)) {
@@ -14742,7 +15308,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
14742
15308
  collectionUrlExpr
14743
15309
  }
14744
15310
  );
14745
- await writeFile2(join8(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
15311
+ await writeFile2(join9(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
14746
15312
  _componentFileCount++;
14747
15313
  } catch (error) {
14748
15314
  console.warn(
@@ -14793,9 +15359,9 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
14793
15359
  scriptPaths = writePageScript(result.javascript, scriptsDir);
14794
15360
  astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
14795
15361
  }
14796
- const astroFileFull = join8(pagesOutDir, result.astroFilePath);
15362
+ const astroFileFull = join9(pagesOutDir, result.astroFilePath);
14797
15363
  const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
14798
- if (!existsSync7(astroFileDir)) {
15364
+ if (!existsSync10(astroFileDir)) {
14799
15365
  mkdirSync4(astroFileDir, { recursive: true });
14800
15366
  }
14801
15367
  await writeFile2(astroFileFull, astroContent, "utf-8");
@@ -14816,31 +15382,31 @@ export const GET: APIRoute = () => {
14816
15382
  });
14817
15383
  };
14818
15384
  `;
14819
- await writeFile2(join8(pagesOutDir, "robots.txt.ts"), robotsTsContent, "utf-8");
15385
+ await writeFile2(join9(pagesOutDir, "robots.txt.ts"), robotsTsContent, "utf-8");
14820
15386
  let collectionCount = 0;
14821
15387
  if (templateSchemas.length > 0) {
14822
- const contentDir = join8(srcDir, "content");
15388
+ const contentDir = join9(srcDir, "content");
14823
15389
  mkdirSync4(contentDir, { recursive: true });
14824
15390
  const collectionDefs = [];
14825
15391
  for (const schema of templateSchemas) {
14826
- const collectionDir = join8(contentDir, schema.id);
15392
+ const collectionDir = join9(contentDir, schema.id);
14827
15393
  mkdirSync4(collectionDir, { recursive: true });
14828
15394
  const richTextFieldNames = Object.entries(schema.fields || {}).filter(([, fd]) => fd.type === "rich-text").map(([fn]) => fn);
14829
- const cmsItemsDir = join8(projectPaths.cms(), schema.id);
14830
- if (existsSync7(cmsItemsDir)) {
15395
+ const cmsItemsDir = join9(projectPaths.cms(), schema.id);
15396
+ if (existsSync10(cmsItemsDir)) {
14831
15397
  const isDevBuild = process.env.MENO_DEV_BUILD === "true";
14832
15398
  const itemFiles = readdirSync6(cmsItemsDir).filter(
14833
15399
  (f) => f.endsWith(".json") && (isDevBuild || !f.endsWith(`${CMS_DRAFT_SUFFIX}.json`))
14834
15400
  );
14835
15401
  for (const itemFile of itemFiles) {
14836
15402
  try {
14837
- const rawContent = await readFile(join8(cmsItemsDir, itemFile), "utf-8");
15403
+ const rawContent = await readFile(join9(cmsItemsDir, itemFile), "utf-8");
14838
15404
  const item = JSON.parse(rawContent);
14839
15405
  const resolved = { ...item };
14840
15406
  for (const fieldName of richTextFieldNames) {
14841
15407
  resolved[fieldName] = serializeRichTextValue(resolved[fieldName]);
14842
15408
  }
14843
- await writeFile2(join8(collectionDir, itemFile), JSON.stringify(resolved, null, 2), "utf-8");
15409
+ await writeFile2(join9(collectionDir, itemFile), JSON.stringify(resolved, null, 2), "utf-8");
14844
15410
  } catch (err) {
14845
15411
  console.warn(
14846
15412
  ` Warning: could not process CMS item ${itemFile}: ${err instanceof Error ? err.message : String(err)}`
@@ -14873,29 +15439,29 @@ ${collectionDefs.join(",\n")}
14873
15439
 
14874
15440
  export { collections };
14875
15441
  `;
14876
- await writeFile2(join8(srcDir, "content.config.ts"), configContent, "utf-8");
15442
+ await writeFile2(join9(srcDir, "content.config.ts"), configContent, "utf-8");
14877
15443
  }
14878
- const imagesSrcDir = join8(projectPaths.project, "images");
14879
- if (existsSync7(imagesSrcDir)) {
14880
- copyDirectory(imagesSrcDir, join8(srcDir, "assets", "images"), shouldCopyImageForAstro);
14881
- copyDirectory(imagesSrcDir, join8(publicDir, "images"));
15444
+ const imagesSrcDir = join9(projectPaths.project, "images");
15445
+ if (existsSync10(imagesSrcDir)) {
15446
+ copyDirectory(imagesSrcDir, join9(srcDir, "assets", "images"), shouldCopyImageForAstro);
15447
+ copyDirectory(imagesSrcDir, join9(publicDir, "images"));
14882
15448
  }
14883
15449
  const publicAssetDirs = ["fonts", "icons", "videos", "assets"];
14884
15450
  for (const dir of publicAssetDirs) {
14885
- const srcAssetDir = join8(projectPaths.project, dir);
14886
- if (existsSync7(srcAssetDir)) {
14887
- copyDirectory(srcAssetDir, join8(publicDir, dir));
15451
+ const srcAssetDir = join9(projectPaths.project, dir);
15452
+ if (existsSync10(srcAssetDir)) {
15453
+ copyDirectory(srcAssetDir, join9(publicDir, dir));
14888
15454
  }
14889
15455
  }
14890
- const librariesDir = join8(projectPaths.project, "libraries");
14891
- if (existsSync7(librariesDir)) {
14892
- copyDirectory(librariesDir, join8(publicDir, "libraries"));
15456
+ const librariesDir = join9(projectPaths.project, "libraries");
15457
+ if (existsSync10(librariesDir)) {
15458
+ copyDirectory(librariesDir, join9(publicDir, "libraries"));
14893
15459
  }
14894
15460
  for (const relPath of localLibsToCopy) {
14895
- const srcPath = join8(projectPaths.project, relPath);
14896
- const destPath = join8(publicDir, relPath);
15461
+ const srcPath = join9(projectPaths.project, relPath);
15462
+ const destPath = join9(publicDir, relPath);
14897
15463
  const destDir = destPath.substring(0, destPath.lastIndexOf("/"));
14898
- if (destDir && !existsSync7(destDir)) mkdirSync4(destDir, { recursive: true });
15464
+ if (destDir && !existsSync10(destDir)) mkdirSync4(destDir, { recursive: true });
14899
15465
  copyFileSync(srcPath, destPath);
14900
15466
  }
14901
15467
  const packageJson = {
@@ -14918,7 +15484,7 @@ export { collections };
14918
15484
  tailwindcss: "^4.0.0"
14919
15485
  }
14920
15486
  };
14921
- await writeFile2(join8(outDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
15487
+ await writeFile2(join9(outDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
14922
15488
  const localeCodes = i18nConfig.locales.map((l) => l.code);
14923
15489
  const i18nBlock = i18nConfig.locales.length > 1 ? `
14924
15490
  i18n: {
@@ -14938,11 +15504,11 @@ export default defineConfig({${siteUrl ? `
14938
15504
  },
14939
15505
  });
14940
15506
  `;
14941
- await writeFile2(join8(outDir, "astro.config.mjs"), astroConfig, "utf-8");
15507
+ await writeFile2(join9(outDir, "astro.config.mjs"), astroConfig, "utf-8");
14942
15508
  const tsConfig = {
14943
15509
  extends: "astro/tsconfigs/strict"
14944
15510
  };
14945
- await writeFile2(join8(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
15511
+ await writeFile2(join9(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
14946
15512
  const baseNetlifyToml = `# Generated by Meno's Astro build.
14947
15513
  [build]
14948
15514
  command = "npm run build"
@@ -14952,8 +15518,8 @@ export default defineConfig({${siteUrl ? `
14952
15518
  NODE_VERSION = "22"
14953
15519
  `;
14954
15520
  const netlifyToml = syncNetlifyLocale404Block(baseNetlifyToml, i18nConfig, pageFiles.includes("404.json"));
14955
- await writeFile2(join8(outDir, "netlify.toml"), netlifyToml, "utf-8");
14956
- await writeFile2(join8(outDir, "src", "env.d.ts"), '/// <reference path="../.astro/types.d.ts" />\n', "utf-8");
15521
+ await writeFile2(join9(outDir, "netlify.toml"), netlifyToml, "utf-8");
15522
+ await writeFile2(join9(outDir, "src", "env.d.ts"), '/// <reference path="../.astro/types.d.ts" />\n', "utf-8");
14957
15523
  const totalPages = allResults.length;
14958
15524
  return {
14959
15525
  pages: totalPages - cmsPageCount,
@@ -15017,6 +15583,7 @@ export {
15017
15583
  getModuleDir,
15018
15584
  getPackageRoot,
15019
15585
  getProjectRoot,
15586
+ groupForSectionLabel,
15020
15587
  handleCollectionSchemaRoute,
15021
15588
  handleCollectionsRoute,
15022
15589
  handleCoreApiRoutes,
@@ -15025,11 +15592,15 @@ export {
15025
15592
  handleItemsRoute,
15026
15593
  handleRouteError,
15027
15594
  hashContent,
15595
+ inferGroup,
15028
15596
  inspect,
15029
15597
  isBun3 as isBun,
15598
+ isColorValue,
15599
+ isThemeCssProject,
15030
15600
  jsonResponse,
15031
15601
  lineMapToObject,
15032
15602
  loadProjectConfig,
15603
+ loadThemeModel,
15033
15604
  logError,
15034
15605
  logRequest,
15035
15606
  logResponseTime,
@@ -15039,19 +15610,25 @@ export {
15039
15610
  needsFormHandler,
15040
15611
  needsMenoFilter,
15041
15612
  packagePaths,
15613
+ parseThemeCss,
15042
15614
  processCMSPropsTemplate,
15043
15615
  processCMSTemplate,
15044
15616
  projectPaths,
15045
15617
  readJsonFile,
15046
15618
  readTextFile,
15619
+ regenerateThemeCss,
15047
15620
  renderPageSSR,
15048
15621
  resetFontConfig,
15049
15622
  resolvePackagePath,
15050
15623
  resolveProjectPath,
15624
+ saveColors,
15625
+ saveVariables,
15626
+ serializeThemeCss,
15051
15627
  serveFile,
15052
15628
  setProjectRoot,
15053
15629
  spawnProcess,
15054
15630
  styleToString,
15631
+ themeCssPath,
15055
15632
  validateJS,
15056
15633
  variableService,
15057
15634
  watchRecursive,