meno-core 1.1.4 → 1.1.6

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 (37) hide show
  1. package/dist/chunks/{chunk-ZEDLSHYQ.js → chunk-GHNLTFCN.js} +44 -12
  2. package/dist/chunks/chunk-GHNLTFCN.js.map +7 -0
  3. package/dist/chunks/{chunk-UOF4MCAD.js → chunk-KX2LPIZZ.js} +607 -16
  4. package/dist/chunks/{chunk-UOF4MCAD.js.map → chunk-KX2LPIZZ.js.map} +3 -3
  5. package/dist/chunks/{chunk-FQBIC2OB.js → chunk-YMBUSHII.js} +1 -1
  6. package/dist/chunks/{chunk-FQBIC2OB.js.map → chunk-YMBUSHII.js.map} +1 -1
  7. package/dist/lib/client/index.js +56 -12
  8. package/dist/lib/client/index.js.map +2 -2
  9. package/dist/lib/server/index.js +121 -26
  10. package/dist/lib/server/index.js.map +3 -3
  11. package/dist/lib/shared/index.js +8 -2
  12. package/dist/lib/shared/index.js.map +1 -1
  13. package/lib/client/core/ComponentBuilder.test.ts +137 -0
  14. package/lib/client/core/ComponentBuilder.ts +52 -13
  15. package/lib/client/core/builders/embedBuilder.ts +15 -1
  16. package/lib/client/core/builders/linkNodeBuilder.ts +15 -1
  17. package/lib/client/core/builders/localeListBuilder.ts +15 -1
  18. package/lib/client/templateEngine.test.ts +106 -3
  19. package/lib/client/templateEngine.ts +50 -10
  20. package/lib/server/fileWatcher.test.ts +90 -0
  21. package/lib/server/fileWatcher.ts +36 -0
  22. package/lib/server/services/configService.ts +0 -5
  23. package/lib/server/ssr/htmlGenerator.test.ts +105 -3
  24. package/lib/server/ssr/htmlGenerator.ts +94 -42
  25. package/lib/server/ssr/ssrRenderer.test.ts +100 -0
  26. package/lib/server/ssr/ssrRenderer.ts +59 -14
  27. package/lib/shared/cssGeneration.test.ts +36 -0
  28. package/lib/shared/cssGeneration.ts +6 -1
  29. package/lib/shared/tailwindThemeScale.ts +1 -0
  30. package/lib/shared/templateStyleVars.ts +49 -0
  31. package/lib/shared/types/comment.ts +9 -3
  32. package/lib/shared/utilityClassConfig.ts +469 -10
  33. package/lib/shared/utilityClassMapper.test.ts +200 -2
  34. package/lib/shared/utilityClassMapper.ts +153 -0
  35. package/lib/shared/utilityClassNames.ts +90 -0
  36. package/package.json +1 -1
  37. package/dist/chunks/chunk-ZEDLSHYQ.js.map +0 -7
@@ -20,20 +20,21 @@ import {
20
20
  resolveSlugToPageId,
21
21
  rewriteComponentRefs,
22
22
  translatePath
23
- } from "../../chunks/chunk-FQBIC2OB.js";
23
+ } from "../../chunks/chunk-YMBUSHII.js";
24
24
  import {
25
25
  syncNetlifyLocale404Block
26
26
  } from "../../chunks/chunk-2AR55GYH.js";
27
27
  import {
28
28
  deepMergeStyles,
29
29
  extractAttributesFromNode,
30
+ getTemplateVars,
30
31
  inlineSvgStyleRules,
31
32
  isHtmlMapping,
32
33
  mergeNodeStyles,
33
34
  processStructure,
34
35
  resolveHtmlMapping,
35
36
  skipEmptyTemplateAttributes
36
- } from "../../chunks/chunk-ZEDLSHYQ.js";
37
+ } from "../../chunks/chunk-GHNLTFCN.js";
37
38
  import {
38
39
  DEFAULT_BREAKPOINTS,
39
40
  DEFAULT_FLUID_RANGE,
@@ -76,6 +77,7 @@ import {
76
77
  isVoidElement,
77
78
  logRuntimeError,
78
79
  markAsSlotContent,
80
+ mergeInstanceClasses,
79
81
  mergeResponsiveStyles,
80
82
  normalizeBreakpointConfig,
81
83
  processItemPropsTemplate,
@@ -89,11 +91,12 @@ import {
89
91
  rewriteViewportUnitsInStylesheet,
90
92
  scalePropertyValue,
91
93
  singularize,
94
+ stripClassOverriddenStyleProps,
92
95
  toFriendlyError,
93
96
  validateCMSDraftItem,
94
97
  validateCMSItem,
95
98
  validateComponentDefinition
96
- } from "../../chunks/chunk-UOF4MCAD.js";
99
+ } from "../../chunks/chunk-KX2LPIZZ.js";
97
100
  import {
98
101
  DEFAULT_I18N_CONFIG,
99
102
  buildLocalizedPath,
@@ -1094,9 +1097,6 @@ var ConfigService = class {
1094
1097
  }
1095
1098
  return this.config.customCode;
1096
1099
  }
1097
- getShowMenoBadge() {
1098
- return this.config?.showMenoBadge === true;
1099
- }
1100
1100
  getImageFormat() {
1101
1101
  if (this.config?.imageFormat === "avif") return "avif";
1102
1102
  return "webp";
@@ -5549,7 +5549,11 @@ async function renderNode(node, ctx) {
5549
5549
  if (embedInteractiveStyles && embedInteractiveStyles.length > 0) {
5550
5550
  embedCssVariables = registerInteractiveStyles(ctx, elementClass2, embedInteractiveStyles);
5551
5551
  }
5552
- const embedStyleAttr = buildCssVariableStyleAttr(embedCssVariables);
5552
+ const embedTemplateVars = getTemplateVars(node);
5553
+ if (embedTemplateVars) {
5554
+ embedCssVariables = { ...embedCssVariables, ...embedTemplateVars };
5555
+ }
5556
+ const embedStyleAttr2 = buildCssVariableStyleAttr(embedCssVariables);
5553
5557
  const attrClassName3 = nodeAttributes2.className || nodeAttributes2.class || "";
5554
5558
  if (attrClassName3) {
5555
5559
  classNames.push(attrClassName3);
@@ -5558,7 +5562,7 @@ async function renderNode(node, ctx) {
5558
5562
  delete nodeAttributes2.class;
5559
5563
  const attrs2 = buildAttributes(nodeAttributes2);
5560
5564
  const classAttr2 = classNames.length > 0 ? ` class="${escapeHtml(classNames.filter(Boolean).join(" "))}"` : "";
5561
- return `<span${classAttr2}${embedStyleAttr}${attrs2}${editorAttrs(ctx, { isSlotContent: isSlotContent(node) })}>${optimizedHtml}</span>`;
5565
+ return `<span${classAttr2}${embedStyleAttr2}${attrs2}${editorAttrs(ctx, { isSlotContent: isSlotContent(node) })}>${optimizedHtml}</span>`;
5562
5566
  }
5563
5567
  const attrClassName2 = nodeAttributes2.className || nodeAttributes2.class || "";
5564
5568
  if (attrClassName2) {
@@ -5568,7 +5572,8 @@ async function renderNode(node, ctx) {
5568
5572
  delete nodeAttributes2.class;
5569
5573
  const attrs = buildAttributes(nodeAttributes2);
5570
5574
  const classAttr = classNames.length > 0 ? ` class="${escapeHtml(classNames.filter(Boolean).join(" "))}"` : "";
5571
- return `<span${classAttr}${attrs}${editorAttrs(ctx, { isSlotContent: isSlotContent(node) })}>${optimizedHtml}</span>`;
5575
+ const embedStyleAttr = buildCssVariableStyleAttr(getTemplateVars(node) ?? {});
5576
+ return `<span${classAttr}${embedStyleAttr}${attrs}${editorAttrs(ctx, { isSlotContent: isSlotContent(node) })}>${optimizedHtml}</span>`;
5572
5577
  }
5573
5578
  if (isLinkNode(node)) {
5574
5579
  let href = typeof node.href === "string" ? node.href : "#";
@@ -5609,8 +5614,12 @@ async function renderNode(node, ctx) {
5609
5614
  if (olinkInteractiveStyles && olinkInteractiveStyles.length > 0) {
5610
5615
  olinkCssVariables = registerInteractiveStyles(ctx, elementClass2, olinkInteractiveStyles);
5611
5616
  }
5612
- olinkStyleAttr = buildCssVariableStyleAttr(olinkCssVariables);
5613
5617
  }
5618
+ const olinkTemplateVars = getTemplateVars(node);
5619
+ if (olinkTemplateVars) {
5620
+ olinkCssVariables = { ...olinkCssVariables, ...olinkTemplateVars };
5621
+ }
5622
+ olinkStyleAttr = buildCssVariableStyleAttr(olinkCssVariables);
5614
5623
  const attrClassName2 = nodeAttributes2.className || nodeAttributes2.class || "";
5615
5624
  if (attrClassName2) {
5616
5625
  classNames.push(attrClassName2);
@@ -5706,6 +5715,12 @@ async function renderNode(node, ctx) {
5706
5715
  }
5707
5716
  }
5708
5717
  }
5718
+ const nodeTemplateVars = getTemplateVars(node);
5719
+ if (nodeTemplateVars) {
5720
+ for (const [varName, value] of Object.entries(nodeTemplateVars)) {
5721
+ resolvedStyle[varName] = value;
5722
+ }
5723
+ }
5709
5724
  const attrClassName = nodeAttributes.className || nodeAttributes.class || "";
5710
5725
  const nodeAttributesWithoutClass = { ...nodeAttributes };
5711
5726
  delete nodeAttributesWithoutClass.className;
@@ -5776,13 +5791,19 @@ async function renderComponent(componentName, propsWithStyleAndAttrs, children,
5776
5791
  mergeNodeStyles(rootNode, propsWithStyleAndAttrs.style);
5777
5792
  }
5778
5793
  if (propsWithStyleAndAttrs.className) {
5794
+ const instanceClassName = propsWithStyleAndAttrs.className;
5795
+ if (rootNode.style) {
5796
+ const stripped = stripClassOverriddenStyleProps(rootNode.style, instanceClassName);
5797
+ if (stripped) rootNode.style = stripped;
5798
+ else delete rootNode.style;
5799
+ }
5779
5800
  if (isHtmlNode(rootNode) || isLinkNode(rootNode)) {
5780
5801
  if (!rootNode.attributes) rootNode.attributes = {};
5781
- const existingClass = rootNode.attributes.class || "";
5782
- rootNode.attributes.class = existingClass ? `${existingClass} ${propsWithStyleAndAttrs.className}` : propsWithStyleAndAttrs.className;
5802
+ const own = (rootNode.attributes.class || "").split(/\s+/).filter(Boolean);
5803
+ rootNode.attributes.class = mergeInstanceClasses(own, instanceClassName).join(" ");
5783
5804
  } else {
5784
- const existingClassName = rootNode.props.className || "";
5785
- rootNode.props.className = existingClassName ? `${existingClassName} ${propsWithStyleAndAttrs.className}` : propsWithStyleAndAttrs.className;
5805
+ const own = (rootNode.props.className || "").split(/\s+/).filter(Boolean);
5806
+ rootNode.props.className = mergeInstanceClasses(own, instanceClassName).join(" ");
5786
5807
  }
5787
5808
  }
5788
5809
  Object.assign(rootNode.props, nodeAttributes);
@@ -6041,8 +6062,12 @@ function renderLocaleList(node, ctx) {
6041
6062
  if (localeListInteractiveStyles && localeListInteractiveStyles.length > 0) {
6042
6063
  localeListCssVariables = registerInteractiveStyles(ctx, elementClass, localeListInteractiveStyles);
6043
6064
  }
6044
- localeListStyleAttr = buildCssVariableStyleAttr(localeListCssVariables);
6045
6065
  }
6066
+ const localeListTemplateVars = getTemplateVars(node);
6067
+ if (localeListTemplateVars) {
6068
+ localeListCssVariables = { ...localeListCssVariables, ...localeListTemplateVars };
6069
+ }
6070
+ localeListStyleAttr = buildCssVariableStyleAttr(localeListCssVariables);
6046
6071
  const containerClassAttr = containerClasses.length > 0 ? ` class="${escapeHtml(containerClasses.join(" "))}"` : "";
6047
6072
  let itemClasses = [];
6048
6073
  if (node.itemStyle) {
@@ -6372,8 +6397,8 @@ function minifyCSS(code) {
6372
6397
  if (!code.trim()) return code;
6373
6398
  return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\s*([{};:,>~])\s*/g, "$1").replace(/\s+/g, " ").replace(/\{\s+/g, "{").replace(/\s+\}/g, "}").replace(/;}/g, "}").trim();
6374
6399
  }
6375
- async function collectPageCssImports(frontmatter, pagePath, nonceAttr) {
6376
- if (!frontmatter?.includes(".css")) return "";
6400
+ function extractCssImportSpecs(frontmatter) {
6401
+ if (!frontmatter?.includes(".css")) return [];
6377
6402
  const seen = /* @__PURE__ */ new Set();
6378
6403
  const specs = [];
6379
6404
  const re = /import\b[^'"]*['"]([^'"]+\.css)(?:\?[^'"]*)?['"]/g;
@@ -6385,25 +6410,63 @@ async function collectPageCssImports(frontmatter, pagePath, nonceAttr) {
6385
6410
  if (spec.endsWith("styles/theme.css")) continue;
6386
6411
  specs.push(spec);
6387
6412
  }
6388
- if (specs.length === 0) return "";
6413
+ return specs;
6414
+ }
6415
+ function usedComponentDefs(pageData, components) {
6416
+ const entries = Object.entries(components);
6417
+ const used = /* @__PURE__ */ new Map();
6418
+ let hay = JSON.stringify(pageData ?? "");
6419
+ let grew = true;
6420
+ while (grew) {
6421
+ grew = false;
6422
+ for (const [name, def] of entries) {
6423
+ if (used.has(name) || !hay.includes(`"${name}"`)) continue;
6424
+ used.set(name, def);
6425
+ hay += JSON.stringify(def ?? "");
6426
+ grew = true;
6427
+ }
6428
+ }
6429
+ return [...used.values()];
6430
+ }
6431
+ async function collectPageCssImports(pageData, components, pagePath, nonceAttr) {
6389
6432
  const pageDir = posix.join("src/pages", posix.dirname(pagePath || "/"));
6433
+ const sources = [];
6434
+ if (Object.values(components).some((d) => d?.component?._frontmatter?.includes(".css"))) {
6435
+ for (const def of usedComponentDefs(pageData, components)) {
6436
+ for (const spec of extractCssImportSpecs(def.component?._frontmatter)) {
6437
+ sources.push({ spec, baseDir: "src/components" });
6438
+ }
6439
+ }
6440
+ }
6441
+ for (const spec of extractCssImportSpecs(pageData._frontmatter)) {
6442
+ sources.push({ spec, baseDir: pageDir });
6443
+ }
6444
+ if (sources.length === 0) return "";
6390
6445
  const tags = [];
6391
- for (const spec of specs) {
6446
+ const linkedRemote = /* @__PURE__ */ new Set();
6447
+ const inlinedFiles = /* @__PURE__ */ new Set();
6448
+ for (const { spec, baseDir } of sources) {
6392
6449
  if (/^(?:https?:)?\/\//.test(spec)) {
6450
+ if (linkedRemote.has(spec)) continue;
6451
+ linkedRemote.add(spec);
6393
6452
  tags.push(`<link rel="stylesheet" href="${escapeHtml(spec)}">`);
6394
6453
  continue;
6395
6454
  }
6396
- const candidates = spec.startsWith("/") ? [spec.slice(1)] : [posix.normalize(posix.join(pageDir, spec)), `src/${spec.replace(/^(?:\.\.?\/)+/, "")}`];
6455
+ const candidates = spec.startsWith("/") ? [spec.slice(1)] : [posix.normalize(posix.join(baseDir, spec)), `src/${spec.replace(/^(?:\.\.?\/)+/, "")}`];
6397
6456
  let css = null;
6457
+ let resolved = null;
6398
6458
  for (const rel of candidates) {
6399
6459
  if (rel.startsWith("..")) continue;
6400
6460
  try {
6401
6461
  css = await readTextFile(resolveProjectPath(rel));
6462
+ resolved = rel;
6402
6463
  break;
6403
6464
  } catch {
6404
6465
  }
6405
6466
  }
6406
- if (css == null) continue;
6467
+ if (css == null || resolved == null) continue;
6468
+ if (inlinedFiles.has(resolved)) continue;
6469
+ inlinedFiles.add(resolved);
6407
6470
  const content = rewriteViewportUnitsInStylesheet(css).replace(/<\/style/gi, "<\\/style");
6408
6471
  tags.push(`<style${nonceAttr} data-meno-page-css="${escapeHtml(spec)}">${content}</style>`);
6409
6472
  }
@@ -6491,11 +6554,10 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
6491
6554
  await configService.load();
6492
6555
  const globalLibraries = configService.getLibraries() || { js: [], css: [] };
6493
6556
  const globalCustomCode = configService.getCustomCode();
6494
- const menoBadgeHtml = configService.getShowMenoBadge() ? `<style${nonceAttr}>.meno-badge{position:fixed;bottom:12px;left:12px;z-index:9999;background:#000;color:#fff;padding:4px 10px;border-radius:6px;font-size:12px;font-family:system-ui,sans-serif;text-decoration:none;opacity:0.8;transition:opacity 0.2s}.meno-badge:hover,.meno-badge:focus{opacity:1}</style><a class="meno-badge" href="https://meno.so" target="_blank" rel="noopener">Made in Meno</a>` : "";
6495
6557
  const mergedCustomCode = {
6496
6558
  head: [globalCustomCode.head, pageCustomCode?.head].filter(Boolean).join("\n"),
6497
6559
  bodyStart: [globalCustomCode.bodyStart, pageCustomCode?.bodyStart].filter(Boolean).join("\n"),
6498
- bodyEnd: [globalCustomCode.bodyEnd, pageCustomCode?.bodyEnd, menoBadgeHtml].filter(Boolean).join("\n")
6560
+ bodyEnd: [globalCustomCode.bodyEnd, pageCustomCode?.bodyEnd].filter(Boolean).join("\n")
6499
6561
  };
6500
6562
  const componentLibraries = collectComponentLibraries(components, pageData.components || {});
6501
6563
  const globalPlusComponent = mergeLibraries(globalLibraries, componentLibraries) || { js: [], css: [] };
@@ -6665,12 +6727,12 @@ ${externalJavaScript}`;
6665
6727
  const scriptPreloadTag = extScriptPath ? `<link rel="preload" href="${extScriptPath}" as="script">` : "";
6666
6728
  const imagePreloadTags = generateImagePreloadTags(rendered.preloadImages);
6667
6729
  const wsUrl = serverPort ? `'ws://localhost:${serverPort}/hmr'` : `location.origin.replace('http','ws')+'/hmr'`;
6668
- const liveReloadScript = injectLiveReload ? `<script${nonceAttr}>(function(){var ws,timer,gen=0,lastSrvRoot=null,dn=document.querySelector('meta[name="csp-nonce"]'),docNonce=dn?dn.getAttribute('content'):'';function strip(s){return s?s.replace(/[?&]_r=\\d+/,''):''}function classList(el){return (el.getAttribute('class')||'').split(/\\s+/).filter(Boolean)}function syncEl(cur,srv,old){var cc=classList(cur),sc=classList(srv),oc=old?new Set(classList(old)):new Set();var rt=cc.filter(function(c){return !oc.has(c)});var seen=new Set(),fin=[];sc.concat(rt).forEach(function(c){if(!seen.has(c)){seen.add(c);fin.push(c)}});var fs=fin.join(' ');if((cur.getAttribute('class')||'')!==fs){if(fs)cur.setAttribute('class',fs);else cur.removeAttribute('class')}for(var i=0;i<srv.attributes.length;i++){var a=srv.attributes[i];if(a.name==='class')continue;var ov=old?old.getAttribute(a.name):null;if(a.value!==ov){if(cur.getAttribute(a.name)!==a.value)cur.setAttribute(a.name,a.value)}}if(old){for(var i=0;i<old.attributes.length;i++){var a=old.attributes[i];if(a.name==='class')continue;if(!srv.hasAttribute(a.name)&&cur.hasAttribute(a.name))cur.removeAttribute(a.name)}}}function syncText(cur,srv){var cc=cur.childNodes,sc=srv.childNodes;for(var i=0;i<sc.length;i++){var s=sc[i],c=cc[i];if(s.nodeType===3&&c&&c.nodeType===3){if(c.textContent!==s.textContent)c.textContent=s.textContent}}}function ek(el){var p=el.getAttribute('data-element-path'),ci=el.getAttribute('data-cms-item-index');return ci?p+'|'+ci:p}function structKey(root){var e=root.querySelectorAll('[data-element-path]'),k=[];for(var i=0;i<e.length;i++)k.push(ek(e[i]));return k.sort().join('~')}function softSync(curR,srvR,oldR){var ce=curR.querySelectorAll('[data-element-path]');var sbp={},se=srvR.querySelectorAll('[data-element-path]');for(var i=0;i<se.length;i++)sbp[ek(se[i])]=se[i];var obp={};if(oldR){var oe=oldR.querySelectorAll('[data-element-path]');for(var i=0;i<oe.length;i++)obp[ek(oe[i])]=oe[i]}for(var i=0;i<ce.length;i++){var c=ce[i],p=ek(c),s=sbp[p];if(!s)continue;syncEl(c,s,obp[p]);syncText(c,s)}syncText(curR,srvR)}function connect(){ws=new WebSocket(${wsUrl});ws.onmessage=function(e){var d=JSON.parse(e.data);if(d.type==='hmr:libraries-update'){location.reload()}else if(d.type==='hmr:update'||d.type==='hmr:cms-update'||d.type==='hmr:colors-update'||d.type==='hmr:variables-update')hotReload()};ws.onclose=function(){clearTimeout(timer);timer=setTimeout(connect,1000)}}function hotReload(){var g=++gen;var sx=window.scrollX,sy=window.scrollY;fetch(location.href,{cache:'no-store'}).then(function(r){return r.text()}).then(function(html){if(g!==gen)return;var p=new DOMParser();var d=p.parseFromString(html,'text/html');var or=document.getElementById('root'),nr=d.getElementById('root');var oscr=document.querySelector('script[src^="/_scripts/"]'),nscr=d.querySelector('script[src^="/_scripts/"]');var oss=oscr?strip(oscr.getAttribute('src')):'',nss=nscr?strip(nscr.getAttribute('src')):'';var hardReset=(oss!==nss)||!lastSrvRoot||!or||!nr||structKey(lastSrvRoot)!==structKey(nr);if(or&&nr){if(hardReset){if(or.innerHTML!==nr.innerHTML)or.innerHTML=nr.innerHTML}else{softSync(or,nr,lastSrvRoot)}}if(nr)lastSrvRoot=nr.cloneNode(true);var os=document.getElementById('meno-styles'),ns=d.getElementById('meno-styles');if(os&&ns&&os.textContent!==ns.textContent)os.textContent=ns.textContent;var nh=d.documentElement;if(nh){var nl=nh.getAttribute('lang')||'en',nt=nh.getAttribute('theme')||'light';if(document.documentElement.getAttribute('lang')!==nl)document.documentElement.setAttribute('lang',nl);if(document.documentElement.getAttribute('theme')!==nt)document.documentElement.setAttribute('theme',nt)}var ocms=document.querySelectorAll('script[id^="meno-cms-"]'),ncms=d.querySelectorAll('script[id^="meno-cms-"]');var ock=JSON.stringify(Array.prototype.map.call(ocms,function(s){return [s.id,s.textContent]}));var nck=JSON.stringify(Array.prototype.map.call(ncms,function(s){return [s.id,s.textContent]}));if(ock!==nck){ocms.forEach(function(s){s.remove()});ncms.forEach(function(s){var c=document.createElement('script');c.type=s.type;c.id=s.id;if(docNonce)c.nonce=docNonce;c.textContent=s.textContent;document.head.appendChild(c)})}window.__menoHotReload=true;var olib=document.querySelectorAll('body > script[src^="/libraries/"]'),nlib=d.querySelectorAll('body > script[src^="/libraries/"]');var olk=JSON.stringify(Array.prototype.map.call(olib,function(s){return strip(s.getAttribute('src'))}).sort());var nlk=JSON.stringify(Array.prototype.map.call(nlib,function(s){return strip(s.getAttribute('src'))}).sort());if(olk!==nlk){olib.forEach(function(o){o.remove()});nlib.forEach(function(n){var src=n.getAttribute('src');var ls=document.createElement('script');ls.src=src+(src.indexOf('?')>-1?'&':'?')+'_r='+Date.now();document.body.appendChild(ls)})}if(!hardReset){window.scrollTo(sx,sy)}else{if(oscr)oscr.remove();if(nscr){var src=nscr.getAttribute('src');var s=document.createElement('script');s.src=src+(src.indexOf('?')>-1?'&':'?')+'_r='+Date.now();s.onload=function(){document.dispatchEvent(new Event('DOMContentLoaded'));window.scrollTo(sx,sy)};s.onerror=function(){window.scrollTo(sx,sy)};document.body.appendChild(s)}else{document.dispatchEvent(new Event('DOMContentLoaded'));window.scrollTo(sx,sy)}}}).catch(function(){location.reload()})}var iR=document.getElementById('root');if(iR)lastSrvRoot=iR.cloneNode(true);connect()})()</script>` : "";
6669
- const scrollHandlerScript = injectLiveReload ? `<script${nonceAttr}>(function(){window.addEventListener('message',function(e){if(e.data.type==='GET_SCROLL_POSITION'){window.parent.postMessage({type:'SCROLL_POSITION_RESPONSE',scrollX:window.scrollX,scrollY:window.scrollY},'*')}else if(e.data.type==='SET_SCROLL_POSITION'){window.scrollTo(e.data.scrollX,e.data.scrollY)}})})()</script>` : "";
6730
+ const liveReloadScript = injectLiveReload ? `<script${nonceAttr}>(function(){var ws,timer,gen=0,lastSrvRoot=null,dn=document.querySelector('meta[name="csp-nonce"]'),docNonce=dn?dn.getAttribute('content'):'';function strip(s){return s?s.replace(/[?&]_r=\\d+/,''):''}function iScroll(x,y){var de=document.documentElement,b=document.body,pd=de.style.scrollBehavior,pb=b?b.style.scrollBehavior:'';de.style.scrollBehavior='auto';if(b)b.style.scrollBehavior='auto';try{window.scrollTo(x,y)}catch(e){}de.style.scrollBehavior=pd;if(b)b.style.scrollBehavior=pb}function classList(el){return (el.getAttribute('class')||'').split(/\\s+/).filter(Boolean)}function syncEl(cur,srv,old){var cc=classList(cur),sc=classList(srv),oc=old?new Set(classList(old)):new Set();var rt=cc.filter(function(c){return !oc.has(c)});var seen=new Set(),fin=[];sc.concat(rt).forEach(function(c){if(!seen.has(c)){seen.add(c);fin.push(c)}});var fs=fin.join(' ');if((cur.getAttribute('class')||'')!==fs){if(fs)cur.setAttribute('class',fs);else cur.removeAttribute('class')}for(var i=0;i<srv.attributes.length;i++){var a=srv.attributes[i];if(a.name==='class')continue;var ov=old?old.getAttribute(a.name):null;if(a.value!==ov){if(cur.getAttribute(a.name)!==a.value)cur.setAttribute(a.name,a.value)}}if(old){for(var i=0;i<old.attributes.length;i++){var a=old.attributes[i];if(a.name==='class')continue;if(!srv.hasAttribute(a.name)&&cur.hasAttribute(a.name))cur.removeAttribute(a.name)}}}function syncText(cur,srv){var cc=cur.childNodes,sc=srv.childNodes;for(var i=0;i<sc.length;i++){var s=sc[i],c=cc[i];if(s.nodeType===3&&c&&c.nodeType===3){if(c.textContent!==s.textContent)c.textContent=s.textContent}}}function ek(el){var p=el.getAttribute('data-element-path'),ci=el.getAttribute('data-cms-item-index');return ci?p+'|'+ci:p}function structKey(root){var e=root.querySelectorAll('[data-element-path]'),k=[];for(var i=0;i<e.length;i++)k.push(ek(e[i]));return k.sort().join('~')}function softSync(curR,srvR,oldR){var ce=curR.querySelectorAll('[data-element-path]');var sbp={},se=srvR.querySelectorAll('[data-element-path]');for(var i=0;i<se.length;i++)sbp[ek(se[i])]=se[i];var obp={};if(oldR){var oe=oldR.querySelectorAll('[data-element-path]');for(var i=0;i<oe.length;i++)obp[ek(oe[i])]=oe[i]}for(var i=0;i<ce.length;i++){var c=ce[i],p=ek(c),s=sbp[p];if(!s)continue;syncEl(c,s,obp[p]);syncText(c,s)}syncText(curR,srvR)}function connect(){ws=new WebSocket(${wsUrl});ws.onmessage=function(e){var d=JSON.parse(e.data);if(d.type==='hmr:libraries-update'){location.reload()}else if(d.type==='hmr:update'||d.type==='hmr:cms-update'||d.type==='hmr:colors-update'||d.type==='hmr:variables-update')hotReload()};ws.onclose=function(){clearTimeout(timer);timer=setTimeout(connect,1000)}}function hotReload(){var g=++gen;var sx=window.scrollX,sy=window.scrollY;fetch(location.href,{cache:'no-store'}).then(function(r){return r.text()}).then(function(html){if(g!==gen)return;var p=new DOMParser();var d=p.parseFromString(html,'text/html');var or=document.getElementById('root'),nr=d.getElementById('root');var oscr=document.querySelector('script[src^="/_scripts/"]'),nscr=d.querySelector('script[src^="/_scripts/"]');var oss=oscr?strip(oscr.getAttribute('src')):'',nss=nscr?strip(nscr.getAttribute('src')):'';var hardReset=(oss!==nss)||!lastSrvRoot||!or||!nr||structKey(lastSrvRoot)!==structKey(nr);if(or&&nr){if(hardReset){if(or.innerHTML!==nr.innerHTML)or.innerHTML=nr.innerHTML}else{softSync(or,nr,lastSrvRoot)}}if(nr)lastSrvRoot=nr.cloneNode(true);var os=document.getElementById('meno-styles'),ns=d.getElementById('meno-styles');if(os&&ns&&os.textContent!==ns.textContent)os.textContent=ns.textContent;var ops=document.querySelectorAll('style[data-meno-page-css]'),nps=d.querySelectorAll('style[data-meno-page-css]');var pcMismatch=ops.length!==nps.length;if(!pcMismatch){for(var pi=0;pi<nps.length;pi++){if(ops[pi].getAttribute('data-meno-page-css')!==nps[pi].getAttribute('data-meno-page-css')){pcMismatch=true;break}if(ops[pi].textContent!==nps[pi].textContent)ops[pi].textContent=nps[pi].textContent}}if(pcMismatch){location.reload();return}var nh=d.documentElement;if(nh){var nl=nh.getAttribute('lang')||'en',nt=nh.getAttribute('theme')||'light';if(document.documentElement.getAttribute('lang')!==nl)document.documentElement.setAttribute('lang',nl);if(document.documentElement.getAttribute('theme')!==nt)document.documentElement.setAttribute('theme',nt)}var ocms=document.querySelectorAll('script[id^="meno-cms-"]'),ncms=d.querySelectorAll('script[id^="meno-cms-"]');var ock=JSON.stringify(Array.prototype.map.call(ocms,function(s){return [s.id,s.textContent]}));var nck=JSON.stringify(Array.prototype.map.call(ncms,function(s){return [s.id,s.textContent]}));if(ock!==nck){ocms.forEach(function(s){s.remove()});ncms.forEach(function(s){var c=document.createElement('script');c.type=s.type;c.id=s.id;if(docNonce)c.nonce=docNonce;c.textContent=s.textContent;document.head.appendChild(c)})}window.__menoHotReload=true;var olib=document.querySelectorAll('body > script[src^="/libraries/"]'),nlib=d.querySelectorAll('body > script[src^="/libraries/"]');var olk=JSON.stringify(Array.prototype.map.call(olib,function(s){return strip(s.getAttribute('src'))}).sort());var nlk=JSON.stringify(Array.prototype.map.call(nlib,function(s){return strip(s.getAttribute('src'))}).sort());if(olk!==nlk){olib.forEach(function(o){o.remove()});nlib.forEach(function(n){var src=n.getAttribute('src');var ls=document.createElement('script');ls.src=src+(src.indexOf('?')>-1?'&':'?')+'_r='+Date.now();document.body.appendChild(ls)})}if(!hardReset){iScroll(sx,sy)}else{if(oscr)oscr.remove();if(nscr){var src=nscr.getAttribute('src');var s=document.createElement('script');s.src=src+(src.indexOf('?')>-1?'&':'?')+'_r='+Date.now();s.onload=function(){document.dispatchEvent(new Event('DOMContentLoaded'));iScroll(sx,sy)};s.onerror=function(){iScroll(sx,sy)};document.body.appendChild(s)}else{document.dispatchEvent(new Event('DOMContentLoaded'));iScroll(sx,sy)}}}).catch(function(){location.reload()})}var iR=document.getElementById('root');if(iR)lastSrvRoot=iR.cloneNode(true);connect()})()</script>` : "";
6731
+ const scrollHandlerScript = injectLiveReload ? `<script${nonceAttr}>(function(){window.addEventListener('message',function(e){if(e.data.type==='GET_SCROLL_POSITION'){window.parent.postMessage({type:'SCROLL_POSITION_RESPONSE',scrollX:window.scrollX,scrollY:window.scrollY},'*')}else if(e.data.type==='SET_SCROLL_POSITION'){var de=document.documentElement,b=document.body,pd=de.style.scrollBehavior,pb=b?b.style.scrollBehavior:'';de.style.scrollBehavior='auto';if(b)b.style.scrollBehavior='auto';window.scrollTo(e.data.scrollX,e.data.scrollY);de.style.scrollBehavior=pd;if(b)b.style.scrollBehavior=pb}})})()</script>` : "";
6670
6732
  const styleContent = useBundled ? finalCSS : `
6671
6733
  ${combinedCSS.split("\n").join("\n ")}
6672
6734
  `;
6673
- const pageCssTags = await collectPageCssImports(pageData._frontmatter, pagePath, nonceAttr);
6735
+ const pageCssTags = await collectPageCssImports(pageData, components, path5, nonceAttr);
6674
6736
  const htmlDocument = `<!DOCTYPE html>
6675
6737
  <html lang="${rendered.locale}" theme="${themeConfig.default}">
6676
6738
  <head>
@@ -12452,6 +12514,7 @@ var FileWatcher = class {
12452
12514
  templatesWatcher = null;
12453
12515
  colorsWatcher = null;
12454
12516
  variablesWatcher = null;
12517
+ themeCssWatcher = null;
12455
12518
  enumsWatcher = null;
12456
12519
  cmsWatcher = null;
12457
12520
  imagesWatcher = null;
@@ -12543,6 +12606,33 @@ var FileWatcher = class {
12543
12606
  }
12544
12607
  });
12545
12608
  }
12609
+ /**
12610
+ * Start watching `src/styles/theme.css` — the token source of truth for
12611
+ * astro-format projects, where colors AND variables share the one file
12612
+ * (colors.json / variables.json were migrated away, so the two watchers
12613
+ * above never fire there). An external edit (e.g. an AI tool adding tokens)
12614
+ * must invalidate both service caches and refresh connected clients, or the
12615
+ * new tokens only appear after a dev-server restart. Deferred attach:
12616
+ * `src/styles` may not exist yet (theme.css lands later via migration or an
12617
+ * external tool). No-op in legacy JSON projects (no `src/`).
12618
+ */
12619
+ watchThemeCss(dirPath = join7(getProjectRoot(), "src", "styles")) {
12620
+ attachWhenDirExists(
12621
+ dirPath,
12622
+ () => watch(dirPath, { recursive: false }, async (_event, filename) => {
12623
+ if (filename !== "theme.css") return;
12624
+ if (this.callbacks.onColorsChange) {
12625
+ await this.callbacks.onColorsChange();
12626
+ }
12627
+ if (this.callbacks.onVariablesChange) {
12628
+ await this.callbacks.onVariablesChange();
12629
+ }
12630
+ }),
12631
+ (w) => {
12632
+ this.themeCssWatcher = w;
12633
+ }
12634
+ );
12635
+ }
12546
12636
  /**
12547
12637
  * Start watching enums.json file
12548
12638
  */
@@ -12684,6 +12774,7 @@ var FileWatcher = class {
12684
12774
  this.watchTemplates();
12685
12775
  this.watchColors();
12686
12776
  this.watchVariables();
12777
+ this.watchThemeCss();
12687
12778
  this.watchEnums();
12688
12779
  this.watchCMS();
12689
12780
  this.watchImages();
@@ -12717,6 +12808,10 @@ var FileWatcher = class {
12717
12808
  this.variablesWatcher.close();
12718
12809
  this.variablesWatcher = null;
12719
12810
  }
12811
+ if (this.themeCssWatcher) {
12812
+ this.themeCssWatcher.close();
12813
+ this.themeCssWatcher = null;
12814
+ }
12720
12815
  if (this.enumsWatcher) {
12721
12816
  this.enumsWatcher.close();
12722
12817
  this.enumsWatcher = null;