meno-core 1.0.52 → 1.0.53

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 (135) hide show
  1. package/build-astro.ts +183 -13
  2. package/build-next.ts +1361 -0
  3. package/build-static.ts +7 -5
  4. package/dist/bin/cli.js +2 -2
  5. package/dist/build-static.js +6 -6
  6. package/dist/chunks/{chunk-HNLUO36W.js → chunk-GZHGVVW3.js} +2 -2
  7. package/dist/chunks/chunk-GZHGVVW3.js.map +7 -0
  8. package/dist/chunks/{chunk-LPVETICS.js → chunk-H3GJ4H2U.js} +185 -1
  9. package/dist/chunks/chunk-H3GJ4H2U.js.map +7 -0
  10. package/dist/chunks/{chunk-CXCBV2M7.js → chunk-IGYR22T6.js} +76 -270
  11. package/dist/chunks/chunk-IGYR22T6.js.map +7 -0
  12. package/dist/chunks/{chunk-LHLHPYSP.js → chunk-JGP5A3Y5.js} +12 -11
  13. package/dist/chunks/chunk-JGP5A3Y5.js.map +7 -0
  14. package/dist/chunks/{chunk-7NIC4I3V.js → chunk-JGWFTO6P.js} +167 -21
  15. package/dist/chunks/chunk-JGWFTO6P.js.map +7 -0
  16. package/dist/chunks/{chunk-EDQSMAMP.js → chunk-O3NAGJP4.js} +85 -4
  17. package/dist/chunks/chunk-O3NAGJP4.js.map +7 -0
  18. package/dist/chunks/{chunk-H4JSCDNW.js → chunk-QB2LNO4W.js} +24 -1
  19. package/dist/chunks/chunk-QB2LNO4W.js.map +7 -0
  20. package/dist/chunks/{chunk-A725KYFK.js → chunk-R6XHAFBF.js} +561 -112
  21. package/dist/chunks/chunk-R6XHAFBF.js.map +7 -0
  22. package/dist/chunks/{chunk-J23ZX5AP.js → chunk-X754AHS5.js} +277 -1
  23. package/dist/chunks/chunk-X754AHS5.js.map +7 -0
  24. package/dist/chunks/{chunk-2QK6U5UK.js → chunk-YBLHKYFF.js} +12 -2
  25. package/dist/chunks/chunk-YBLHKYFF.js.map +7 -0
  26. package/dist/chunks/{constants-GWBAD66U.js → constants-STK2YBIW.js} +2 -2
  27. package/dist/entries/server-router.js +7 -7
  28. package/dist/lib/client/index.js +354 -59
  29. package/dist/lib/client/index.js.map +4 -4
  30. package/dist/lib/server/index.js +1458 -190
  31. package/dist/lib/server/index.js.map +4 -4
  32. package/dist/lib/shared/index.js +202 -34
  33. package/dist/lib/shared/index.js.map +4 -4
  34. package/dist/lib/test-utils/index.js +1 -1
  35. package/entries/client-router.tsx +5 -165
  36. package/lib/client/ErrorBoundary.test.tsx +27 -25
  37. package/lib/client/ErrorBoundary.tsx +34 -19
  38. package/lib/client/core/ComponentBuilder.ts +19 -2
  39. package/lib/client/core/builders/embedBuilder.ts +8 -4
  40. package/lib/client/core/builders/listBuilder.ts +23 -4
  41. package/lib/client/fontFamiliesService.test.ts +76 -0
  42. package/lib/client/fontFamiliesService.ts +69 -0
  43. package/lib/client/hmrCssReload.ts +160 -0
  44. package/lib/client/hooks/useColorVariables.ts +2 -0
  45. package/lib/client/index.ts +4 -0
  46. package/lib/client/meno-filter/ui.ts +2 -0
  47. package/lib/client/routing/RouteLoader.test.ts +2 -2
  48. package/lib/client/routing/RouteLoader.ts +8 -2
  49. package/lib/client/routing/Router.tsx +81 -15
  50. package/lib/client/scripts/ScriptExecutor.test.ts +143 -0
  51. package/lib/client/scripts/ScriptExecutor.ts +56 -2
  52. package/lib/client/styles/StyleInjector.ts +20 -5
  53. package/lib/client/styles/UtilityClassCollector.ts +7 -1
  54. package/lib/client/styles/cspNonce.test.ts +67 -0
  55. package/lib/client/styles/cspNonce.ts +63 -0
  56. package/lib/client/templateEngine.test.ts +80 -0
  57. package/lib/client/templateEngine.ts +5 -0
  58. package/lib/server/astro/cmsPageEmitter.ts +35 -5
  59. package/lib/server/astro/componentEmitter.ts +61 -5
  60. package/lib/server/astro/nodeToAstro.ts +149 -11
  61. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +264 -0
  62. package/lib/server/astro/normalizeOrphanTemplateProps.ts +184 -0
  63. package/lib/server/createServer.ts +11 -0
  64. package/lib/server/draftPageStore.ts +49 -0
  65. package/lib/server/fileWatcher.ts +62 -2
  66. package/lib/server/index.ts +13 -1
  67. package/lib/server/providers/fileSystemPageProvider.ts +8 -0
  68. package/lib/server/routes/api/components.ts +9 -4
  69. package/lib/server/routes/api/core-routes.ts +2 -2
  70. package/lib/server/routes/api/pages.ts +14 -22
  71. package/lib/server/routes/api/shared.ts +56 -0
  72. package/lib/server/routes/index.ts +90 -0
  73. package/lib/server/routes/pages.ts +13 -6
  74. package/lib/server/services/componentService.test.ts +199 -2
  75. package/lib/server/services/componentService.ts +354 -49
  76. package/lib/server/services/fileWatcherService.ts +4 -24
  77. package/lib/server/services/pageService.test.ts +23 -0
  78. package/lib/server/services/pageService.ts +124 -6
  79. package/lib/server/ssr/attributeBuilder.ts +8 -2
  80. package/lib/server/ssr/buildErrorOverlay.ts +1 -1
  81. package/lib/server/ssr/errorOverlay.test.ts +21 -2
  82. package/lib/server/ssr/errorOverlay.ts +38 -11
  83. package/lib/server/ssr/htmlGenerator.test.ts +53 -13
  84. package/lib/server/ssr/htmlGenerator.ts +71 -27
  85. package/lib/server/ssr/liveReloadIntegration.test.ts +123 -2
  86. package/lib/server/ssr/ssrRenderer.test.ts +67 -0
  87. package/lib/server/ssr/ssrRenderer.ts +94 -9
  88. package/lib/server/websocketManager.ts +0 -1
  89. package/lib/shared/componentRefs.ts +45 -0
  90. package/lib/shared/constants.ts +8 -0
  91. package/lib/shared/cssGeneration.ts +2 -0
  92. package/lib/shared/cssProperties.ts +184 -0
  93. package/lib/shared/expressionEvaluator.ts +54 -0
  94. package/lib/shared/fontCss.ts +101 -0
  95. package/lib/shared/fontLoader.ts +8 -86
  96. package/lib/shared/friendlyError.test.ts +87 -0
  97. package/lib/shared/friendlyError.ts +121 -0
  98. package/lib/shared/hrefRefs.test.ts +130 -0
  99. package/lib/shared/hrefRefs.ts +100 -0
  100. package/lib/shared/index.ts +52 -0
  101. package/lib/shared/inlineSvgStyleRules.test.ts +108 -0
  102. package/lib/shared/inlineSvgStyleRules.ts +134 -0
  103. package/lib/shared/interfaces/contentProvider.ts +13 -0
  104. package/lib/shared/itemTemplateUtils.test.ts +14 -0
  105. package/lib/shared/itemTemplateUtils.ts +4 -1
  106. package/lib/shared/registry/NodeTypeDefinition.ts +1 -1
  107. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +1 -1
  108. package/lib/shared/slugTranslator.test.ts +24 -0
  109. package/lib/shared/slugTranslator.ts +24 -0
  110. package/lib/shared/styleNodeUtils.ts +4 -1
  111. package/lib/shared/tree/PathBuilder.test.ts +128 -1
  112. package/lib/shared/tree/PathBuilder.ts +83 -31
  113. package/lib/shared/types/comment.ts +99 -0
  114. package/lib/shared/types/index.ts +12 -0
  115. package/lib/shared/types/rendering.ts +8 -0
  116. package/lib/shared/utilityClassConfig.ts +4 -2
  117. package/lib/shared/utilityClassMapper.test.ts +24 -0
  118. package/lib/shared/validation/commentValidators.ts +69 -0
  119. package/lib/shared/validation/index.ts +1 -0
  120. package/lib/shared/viewportUnits.integration.test.ts +42 -0
  121. package/lib/shared/viewportUnits.test.ts +103 -0
  122. package/lib/shared/viewportUnits.ts +63 -0
  123. package/lib/test-utils/dom-setup.ts +6 -0
  124. package/package.json +1 -1
  125. package/dist/chunks/chunk-2QK6U5UK.js.map +0 -7
  126. package/dist/chunks/chunk-7NIC4I3V.js.map +0 -7
  127. package/dist/chunks/chunk-A725KYFK.js.map +0 -7
  128. package/dist/chunks/chunk-CXCBV2M7.js.map +0 -7
  129. package/dist/chunks/chunk-EDQSMAMP.js.map +0 -7
  130. package/dist/chunks/chunk-H4JSCDNW.js.map +0 -7
  131. package/dist/chunks/chunk-HNLUO36W.js.map +0 -7
  132. package/dist/chunks/chunk-J23ZX5AP.js.map +0 -7
  133. package/dist/chunks/chunk-LHLHPYSP.js.map +0 -7
  134. package/dist/chunks/chunk-LPVETICS.js.map +0 -7
  135. /package/dist/chunks/{constants-GWBAD66U.js.map → constants-STK2YBIW.js.map} +0 -0
@@ -14,19 +14,29 @@ import {
14
14
  } from "./chunk-WQFG7PAH.js";
15
15
  import {
16
16
  CMS_DRAFT_SUFFIX,
17
+ buildSlugIndex,
18
+ collectComponentLibraries,
19
+ filterLibrariesByContext,
20
+ fontFaceCss,
21
+ fontPreloadLinks,
22
+ generateLibraryTags,
23
+ getLocaleLinks,
17
24
  isReservedDraftFilename,
18
25
  isSafePathSegment,
19
26
  isValidIdentifier,
20
- resolvePaletteColor
21
- } from "./chunk-J23ZX5AP.js";
27
+ mergeLibraries,
28
+ resolvePaletteColor,
29
+ translatePath
30
+ } from "./chunk-X754AHS5.js";
22
31
  import {
23
32
  extractAttributesFromNode,
33
+ inlineSvgStyleRules,
24
34
  isHtmlMapping,
25
35
  mergeNodeStyles,
26
36
  processStructure,
27
37
  resolveHtmlMapping,
28
38
  skipEmptyTemplateAttributes
29
- } from "./chunk-EDQSMAMP.js";
39
+ } from "./chunk-O3NAGJP4.js";
30
40
  import {
31
41
  DEFAULT_PREFETCH_CONFIG,
32
42
  SSRRegistry,
@@ -62,11 +72,13 @@ import {
62
72
  resolvePropsFromDefinition,
63
73
  resolveTemplateRawValue,
64
74
  responsiveStylesToClasses,
75
+ rewriteViewportUnits,
65
76
  singularize,
77
+ toFriendlyError,
66
78
  validateCMSDraftItem,
67
79
  validateCMSItem,
68
80
  validateComponentDefinition
69
- } from "./chunk-7NIC4I3V.js";
81
+ } from "./chunk-JGWFTO6P.js";
70
82
  import {
71
83
  DEFAULT_BREAKPOINTS,
72
84
  DEFAULT_FLUID_RANGE,
@@ -91,7 +103,7 @@ import {
91
103
  NODE_TYPE,
92
104
  RAW_HTML_PREFIX,
93
105
  init_constants
94
- } from "./chunk-2QK6U5UK.js";
106
+ } from "./chunk-YBLHKYFF.js";
95
107
  import {
96
108
  __require
97
109
  } from "./chunk-KSBZ2L7C.js";
@@ -1323,57 +1335,11 @@ async function loadProjectConfig() {
1323
1335
  function getProjectConfig() {
1324
1336
  return cachedConfig || { fonts: [] };
1325
1337
  }
1326
- function getFontFormat(path2) {
1327
- if (path2.endsWith(".woff2")) return "woff2";
1328
- if (path2.endsWith(".woff")) return "woff";
1329
- if (path2.endsWith(".ttf")) return "truetype";
1330
- if (path2.endsWith(".otf")) return "opentype";
1331
- return "truetype";
1332
- }
1333
- function extractFamilyName(path2) {
1334
- const filename = path2.split("/").pop() || "Font";
1335
- const name = filename.replace(/\.(ttf|woff2?|otf)$/i, "");
1336
- return name.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
1337
- }
1338
1338
  function generateFontCSS() {
1339
- const config = getProjectConfig();
1340
- const fonts = config.fonts || [];
1341
- return fonts.filter((font) => font.path || font.src).map((font) => {
1342
- const fontPath = font.path || font.src;
1343
- const format = getFontFormat(fontPath);
1344
- const family = font.family || extractFamilyName(fontPath);
1345
- const weight = font.weight ?? 400;
1346
- const weightMax = font.weightMax;
1347
- const style = font.style ?? "normal";
1348
- const fontDisplay = font.fontDisplay;
1349
- const fontWeight = weightMax != null ? `${weight} ${weightMax}` : weight;
1350
- const unicodeRange = font.unicodeRange;
1351
- return `@font-face {
1352
- font-family: '${family}';
1353
- src: url('${fontPath}') format('${format}');
1354
- font-weight: ${fontWeight};
1355
- font-style: ${style};${fontDisplay ? `
1356
- font-display: ${fontDisplay};` : ""}${unicodeRange ? `
1357
- unicode-range: ${unicodeRange};` : ""}
1358
- }`;
1359
- }).join("\n\n");
1360
- }
1361
- function getFontMimeType(path2) {
1362
- if (path2.endsWith(".woff2")) return "font/woff2";
1363
- if (path2.endsWith(".woff")) return "font/woff";
1364
- if (path2.endsWith(".ttf")) return "font/ttf";
1365
- if (path2.endsWith(".otf")) return "font/otf";
1366
- return "font/ttf";
1339
+ return fontFaceCss(getProjectConfig().fonts || []);
1367
1340
  }
1368
1341
  function generateFontPreloadTags() {
1369
- const config = getProjectConfig();
1370
- const fonts = config.fonts || [];
1371
- if (fonts.length === 0) return "";
1372
- return fonts.filter((font) => font.path || font.src).map((font) => {
1373
- const fontPath = font.path || font.src;
1374
- const mimeType = getFontMimeType(fontPath);
1375
- return `<link rel="preload" href="${fontPath}" as="font" type="${mimeType}" crossorigin>`;
1376
- }).join("\n ");
1342
+ return fontPreloadLinks(getProjectConfig().fonts || []);
1377
1343
  }
1378
1344
 
1379
1345
  // lib/server/cssGenerator.ts
@@ -1553,80 +1519,17 @@ function styleToString(style) {
1553
1519
  const declarations = [];
1554
1520
  for (const [key, value] of Object.entries(style)) {
1555
1521
  if (value === null || value === void 0) continue;
1522
+ const rewritten = rewriteViewportUnits(String(value));
1556
1523
  if (key.startsWith("--")) {
1557
- declarations.push(`${key}: ${escapeHtml(String(value))}`);
1524
+ declarations.push(`${key}: ${escapeHtml(rewritten)}`);
1558
1525
  } else {
1559
1526
  const cssProperty = key.replace(/([A-Z])/g, "-$1").toLowerCase();
1560
- declarations.push(`${cssProperty}: ${escapeHtml(String(value))}`);
1527
+ declarations.push(`${cssProperty}: ${escapeHtml(rewritten)}`);
1561
1528
  }
1562
1529
  }
1563
1530
  return declarations.length > 0 ? declarations.join("; ") : "";
1564
1531
  }
1565
1532
 
1566
- // lib/shared/slugTranslator.ts
1567
- function buildSlugIndex(mappings) {
1568
- const index = /* @__PURE__ */ new Map();
1569
- for (const mapping of mappings) {
1570
- for (const [locale, slug] of Object.entries(mapping.slugs)) {
1571
- const key = `${locale}:${slug}`;
1572
- index.set(key, {
1573
- pageId: mapping.pageId,
1574
- slugs: mapping.slugs
1575
- });
1576
- }
1577
- }
1578
- return index;
1579
- }
1580
- function findPageBySlug(slug, locale, index) {
1581
- const key = `${locale}:${slug}`;
1582
- return index.get(key);
1583
- }
1584
- function translatePath(currentPath, targetLocale, currentLocale, defaultLocale, index) {
1585
- let slug = currentPath;
1586
- if (slug.startsWith("/")) {
1587
- slug = slug.substring(1);
1588
- }
1589
- if (currentLocale !== defaultLocale) {
1590
- if (slug.startsWith(`${currentLocale}/`)) {
1591
- slug = slug.substring(currentLocale.length + 1);
1592
- } else if (slug === currentLocale) {
1593
- slug = "";
1594
- }
1595
- }
1596
- if (slug === "" || slug === "/") {
1597
- slug = "";
1598
- }
1599
- let entry = findPageBySlug(slug, currentLocale, index);
1600
- if (!entry && currentLocale !== defaultLocale) {
1601
- entry = findPageBySlug(slug, defaultLocale, index);
1602
- }
1603
- if (!entry) {
1604
- if (targetLocale === defaultLocale) {
1605
- return slug === "" ? "/" : `/${slug}`;
1606
- }
1607
- return slug === "" ? `/${targetLocale}` : `/${targetLocale}/${slug}`;
1608
- }
1609
- const targetSlug = entry.slugs[targetLocale] ?? entry.slugs[defaultLocale] ?? slug;
1610
- if (targetLocale === defaultLocale) {
1611
- return targetSlug === "" ? "/" : `/${targetSlug}`;
1612
- }
1613
- return targetSlug === "" ? `/${targetLocale}` : `/${targetLocale}/${targetSlug}`;
1614
- }
1615
- function getLocaleLinks(currentPath, currentLocale, i18nConfig, index) {
1616
- return i18nConfig.locales.map((localeConfig) => ({
1617
- locale: localeConfig.code,
1618
- langTag: localeConfig.langTag,
1619
- name: localeConfig.name,
1620
- nativeName: localeConfig.nativeName,
1621
- path: translatePath(currentPath, localeConfig.code, currentLocale, i18nConfig.defaultLocale, index),
1622
- isCurrent: localeConfig.code === currentLocale
1623
- }));
1624
- }
1625
- function resolveSlugToPageId(slug, locale, index) {
1626
- const entry = findPageBySlug(slug, locale, index);
1627
- return entry?.pageId;
1628
- }
1629
-
1630
1533
  // lib/server/ssr/metaTagGenerator.ts
1631
1534
  function extractPageMeta(pageData) {
1632
1535
  const meta = {};
@@ -2312,6 +2215,13 @@ async function renderNestedListPlaceholder(node, ctx) {
2312
2215
  const configJson = escapeHtml(JSON.stringify(config));
2313
2216
  return `<div data-cms-list-nested="true" data-collection="${escapeHtml(sourceStr)}" data-cms-config="${configJson}"${editorAttrs(ctx, { isCMSListContainer: true })}><template data-nested-template>${templateContent}</template></div>`;
2314
2217
  }
2218
+ function renderNodeFallback(ctx, error, label) {
2219
+ console.error(`\u274C SSR render error in ${label}:`, error);
2220
+ if (!ctx.injectEditorAttrs) return "";
2221
+ const friendly = toFriendlyError(error);
2222
+ const text = `${friendly.title} \u2014 ${friendly.friendlyMessage}`;
2223
+ return `<div data-meno-render-error style="margin:8px 0;padding:12px 14px;border:1px dashed #e0a3a3;border-radius:6px;background:#fdf3f3;color:#9a3b3b;font:13px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">\u26A0\uFE0F ${escapeHtml(text)}</div>`;
2224
+ }
2315
2225
  async function processList(node, ctx) {
2316
2226
  const nodeType = node.type;
2317
2227
  const isLegacyCMSList = nodeType === "cms-list";
@@ -2346,6 +2256,7 @@ async function processList(node, ctx) {
2346
2256
  items = [];
2347
2257
  }
2348
2258
  }
2259
+ if (!Array.isArray(items)) items = [];
2349
2260
  if (node.offset && sourceType === "prop") {
2350
2261
  items = items.slice(node.offset);
2351
2262
  }
@@ -2512,7 +2423,7 @@ function registerInteractiveStyles(ctx, elementClass, interactiveStyles) {
2512
2423
  }
2513
2424
  function buildCssVariableStyleAttr(cssVariables) {
2514
2425
  if (Object.keys(cssVariables).length === 0) return "";
2515
- const styleString = Object.entries(cssVariables).map(([k, v]) => `${k}: ${v}`).join("; ");
2426
+ const styleString = Object.entries(cssVariables).map(([k, v]) => `${k}: ${rewriteViewportUnits(v)}`).join("; ");
2516
2427
  return ` style="${escapeHtml(styleString)}"`;
2517
2428
  }
2518
2429
  function arraysEqual(a, b) {
@@ -2538,6 +2449,9 @@ function editorAttrs(ctx, opts = {}) {
2538
2449
  async function renderNode(node, ctx) {
2539
2450
  const { breakpoints, viewportWidth, locale, i18nConfig, slugMappings, pagePath } = ctx;
2540
2451
  if (node === null || node === void 0) return "";
2452
+ if (typeof node === "object" && !Array.isArray(node) && node._code === true) {
2453
+ return "";
2454
+ }
2541
2455
  if (typeof node === "string" || typeof node === "number") {
2542
2456
  let text = String(node);
2543
2457
  if (ctx.templateMode) {
@@ -2593,7 +2507,11 @@ async function renderNode(node, ctx) {
2593
2507
  return "";
2594
2508
  }
2595
2509
  if (isListNode(node)) {
2596
- return await processList(node, ctx);
2510
+ try {
2511
+ return await processList(node, ctx);
2512
+ } catch (error) {
2513
+ return renderNodeFallback(ctx, error, "list");
2514
+ }
2597
2515
  }
2598
2516
  const nodeType = "type" in node ? node.type : void 0;
2599
2517
  const nodeStyle = "style" in node ? node.style : void 0;
@@ -2622,11 +2540,12 @@ async function renderNode(node, ctx) {
2622
2540
  }
2623
2541
  }
2624
2542
  const purify = getDOMPurify();
2625
- const sanitizedHtml = purify ? purify.sanitize(htmlContent, {
2626
- ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "style", "animate", "animateTransform", "animateMotion", "set"],
2627
- ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "stroke-opacity", "font-size", "font-family", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title", "attributeName", "values", "dur", "begin", "end", "repeatCount", "repeatDur", "keyTimes", "keySplines", "calcMode", "from", "to", "by", "additive", "accumulate", "type", "rotate", "keyPoints", "path"],
2543
+ const purifiedHtml = purify ? purify.sanitize(htmlContent, {
2544
+ ALLOWED_TAGS: ["svg", "path", "circle", "rect", "line", "polyline", "polygon", "g", "text", "tspan", "image", "defs", "use", "linearGradient", "radialGradient", "stop", "clipPath", "mask", "pattern", "marker", "symbol", "a", "div", "span", "p", "br", "button", "img", "iframe", "video", "audio", "source", "canvas", "b", "i", "u", "strong", "em", "sub", "sup", "mark", "s", "small", "del", "ins", "q", "abbr", "code", "pre", "blockquote", "ul", "ol", "li", "h1", "h2", "h3", "h4", "h5", "h6", "style", "animate", "animateTransform", "animateMotion", "set", "filter", "feGaussianBlur", "feOffset", "feMerge", "feMergeNode", "feColorMatrix", "feComposite", "feFlood", "feMorphology", "feBlend", "feDropShadow", "feTurbulence", "feDisplacementMap", "foreignObject"],
2545
+ ALLOWED_ATTR: ["class", "id", "style", "width", "height", "viewBox", "xmlns", "xmlns:xlink", "xlink:href", "fill", "stroke", "stroke-width", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "d", "cx", "cy", "r", "x", "y", "x1", "y1", "x2", "y2", "points", "href", "src", "alt", "target", "rel", "data-*", "aria-*", "transform", "opacity", "fill-opacity", "fill-rule", "clip-rule", "clip-path", "clipPathUnits", "mask", "mask-type", "maskUnits", "maskContentUnits", "patternUnits", "patternContentUnits", "patternTransform", "gradientUnits", "gradientTransform", "spreadMethod", "preserveAspectRatio", "marker-start", "marker-mid", "marker-end", "markerUnits", "markerWidth", "markerHeight", "refX", "refY", "orient", "paint-order", "vector-effect", "filter", "filterUnits", "primitiveUnits", "in", "in2", "result", "stdDeviation", "flood-color", "flood-opacity", "stroke-opacity", "font-size", "font-family", "font-weight", "font-style", "text-anchor", "dominant-baseline", "offset", "stop-color", "stop-opacity", "frameborder", "allowfullscreen", "allow", "title", "attributeName", "values", "dur", "begin", "end", "repeatCount", "repeatDur", "keyTimes", "keySplines", "calcMode", "from", "to", "by", "additive", "accumulate", "type", "rotate", "keyPoints", "path"],
2628
2546
  KEEP_CONTENT: true
2629
2547
  }) : htmlContent;
2548
+ const sanitizedHtml = inlineSvgStyleRules(purifiedHtml);
2630
2549
  const optimizedHtml = ctx.imageMetadataMap ? rewriteRichTextImages(sanitizedHtml, ctx.imageMetadataMap, ctx.imageFormat) : sanitizedHtml;
2631
2550
  const nodeAttributes2 = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
2632
2551
  const classNames = ["oem"];
@@ -2830,7 +2749,17 @@ async function renderComponent(componentName, propsWithStyleAndAttrs, children,
2830
2749
  const markedChildren = children ? markAsSlotContent(children) : void 0;
2831
2750
  const processedStructure = processStructure(
2832
2751
  structuredComponentDef.structure,
2833
- { props: resolvedProps, componentDef: structuredComponentDef, itemContext: ctx.templateContext },
2752
+ {
2753
+ props: resolvedProps,
2754
+ componentDef: structuredComponentDef,
2755
+ itemContext: ctx.templateContext,
2756
+ // Host (outer) component's resolved props — used as fallback scope
2757
+ // for `{{x}}` templates the child's interface doesn't declare. At
2758
+ // this point `ctx.componentResolvedProps` still belongs to the
2759
+ // outer component; it's only swapped to `resolvedProps` below when
2760
+ // we recurse via `renderNode`.
2761
+ parentProps: ctx.componentResolvedProps
2762
+ },
2834
2763
  void 0,
2835
2764
  markedChildren,
2836
2765
  true
@@ -2894,6 +2823,16 @@ async function renderComponent(componentName, propsWithStyleAndAttrs, children,
2894
2823
  existingPropsMap[componentName] = propsForJS;
2895
2824
  processedRoot.attributes["data-props"] = JSON.stringify(existingPropsMap);
2896
2825
  }
2826
+ if (componentName && (isHtmlNode(rootNode) || isLinkNode(rootNode))) {
2827
+ if (!rootNode.attributes) rootNode.attributes = {};
2828
+ if (!ctx.componentInstanceCounter) {
2829
+ ctx.componentInstanceCounter = /* @__PURE__ */ new Map();
2830
+ }
2831
+ const instanceIndex = ctx.componentInstanceCounter.get(componentName) ?? 0;
2832
+ ctx.componentInstanceCounter.set(componentName, instanceIndex + 1);
2833
+ rootNode.attributes["data-meno-component"] = componentName;
2834
+ rootNode.attributes["data-meno-component-instance"] = String(instanceIndex);
2835
+ }
2897
2836
  }
2898
2837
  return await renderNode(processedStructure, {
2899
2838
  ...ctx,
@@ -2904,8 +2843,7 @@ async function renderComponent(componentName, propsWithStyleAndAttrs, children,
2904
2843
  componentResolvedProps: resolvedProps
2905
2844
  });
2906
2845
  } catch (error) {
2907
- console.error(`\u274C SSR Error rendering component ${componentName}:`, error);
2908
- return "";
2846
+ return renderNodeFallback(ctx, error, `component ${componentName}`);
2909
2847
  }
2910
2848
  }
2911
2849
  async function renderLinkNode(propsWithStyleAndAttrs, children, ctx) {
@@ -3157,6 +3095,9 @@ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", ba
3157
3095
  if (typeof meta.ogDescription === "string") {
3158
3096
  meta = { ...meta, ogDescription: processCMSTemplate(meta.ogDescription, cmsContext.cms, effectiveLocale, config) };
3159
3097
  }
3098
+ if (typeof meta.ogImage === "string") {
3099
+ meta = { ...meta, ogImage: processCMSTemplate(meta.ogImage, cmsContext.cms, effectiveLocale, config) };
3100
+ }
3160
3101
  }
3161
3102
  const pageComponents = pageData?.components || {};
3162
3103
  const { html: contentHTML, interactiveStylesMap, preloadImages, neededCollections, ssrFallbackCollector, processedRawHtmlCollector } = rootNode ? await buildComponentHTML(rootNode, globalComponents, pageComponents, effectiveLocale, config, slugMappings, pagePath, cmsContext, cmsService, isProductionBuild, injectEditorAttrs) : { html: "", interactiveStylesMap: /* @__PURE__ */ new Map(), preloadImages: [], neededCollections: /* @__PURE__ */ new Set(), ssrFallbackCollector: /* @__PURE__ */ new Map(), processedRawHtmlCollector: /* @__PURE__ */ new Map() };
@@ -3349,134 +3290,6 @@ function generateAllInlineDataScripts(collections) {
3349
3290
  return scripts.join("\n ");
3350
3291
  }
3351
3292
 
3352
- // lib/shared/libraryLoader.ts
3353
- function escapeAttr2(str) {
3354
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3355
- }
3356
- function mergeLibraries(global, page) {
3357
- if (!page) {
3358
- return global;
3359
- }
3360
- if (page.mode === "replace") {
3361
- return {
3362
- js: page.js || [],
3363
- css: page.css || []
3364
- };
3365
- }
3366
- return {
3367
- js: [...global.js || [], ...page.js || []],
3368
- css: [...global.css || [], ...page.css || []]
3369
- };
3370
- }
3371
- function generateScriptTag(lib) {
3372
- const attrs = [`src="${escapeAttr2(lib.url)}"`];
3373
- if (lib.type === "module") {
3374
- attrs.push('type="module"');
3375
- } else {
3376
- const mode = lib.mode || "defer";
3377
- attrs.push(mode);
3378
- }
3379
- return `<script ${attrs.join(" ")}></script>`;
3380
- }
3381
- function generateInlineStyleTag(content, media) {
3382
- const attrs = media ? ` media="${escapeAttr2(media)}"` : "";
3383
- return `<style${attrs}>${content}</style>`;
3384
- }
3385
- function generateStylesheetTag(lib) {
3386
- const attrs = [
3387
- 'rel="stylesheet"',
3388
- `href="${escapeAttr2(lib.url)}"`
3389
- ];
3390
- if (lib.media) {
3391
- attrs.push(`media="${escapeAttr2(lib.media)}"`);
3392
- }
3393
- return `<link ${attrs.join(" ")}>`;
3394
- }
3395
- function generateLibraryTags(libs, inlineContents) {
3396
- const headCSS = [];
3397
- const headJS = [];
3398
- const bodyEndJS = [];
3399
- for (const css of libs.css || []) {
3400
- const inlineContent = inlineContents?.get(css.url);
3401
- if (inlineContent !== void 0) {
3402
- headCSS.push(generateInlineStyleTag(inlineContent, css.media));
3403
- } else {
3404
- headCSS.push(generateStylesheetTag(css));
3405
- }
3406
- }
3407
- for (const js of libs.js || []) {
3408
- const tag = generateScriptTag(js);
3409
- if (js.position === "head") {
3410
- headJS.push(tag);
3411
- } else {
3412
- bodyEndJS.push(tag);
3413
- }
3414
- }
3415
- return {
3416
- headCSS: headCSS.join("\n "),
3417
- headJS: headJS.join("\n "),
3418
- bodyEndJS: bodyEndJS.join("\n ")
3419
- };
3420
- }
3421
- function collectComponentLibraries(globalComponents = {}, pageComponents = {}) {
3422
- const seenJS = /* @__PURE__ */ new Set();
3423
- const seenCSS = /* @__PURE__ */ new Set();
3424
- const jsLibs = [];
3425
- const cssLibs = [];
3426
- const collect = (components) => {
3427
- for (const component of Object.values(components)) {
3428
- const libs = component?.component?.libraries;
3429
- if (!libs) continue;
3430
- for (const js of libs.js || []) {
3431
- if (!seenJS.has(js.url)) {
3432
- seenJS.add(js.url);
3433
- jsLibs.push(js);
3434
- }
3435
- }
3436
- for (const css of libs.css || []) {
3437
- if (!seenCSS.has(css.url)) {
3438
- seenCSS.add(css.url);
3439
- cssLibs.push(css);
3440
- }
3441
- }
3442
- }
3443
- };
3444
- collect(globalComponents);
3445
- collect(pageComponents);
3446
- return { js: jsLibs, css: cssLibs };
3447
- }
3448
- function extractLibraryOrigins(libs) {
3449
- const scriptOrigins = /* @__PURE__ */ new Set();
3450
- const styleOrigins = /* @__PURE__ */ new Set();
3451
- for (const js of libs.js || []) {
3452
- const origin = safeOrigin(js.url);
3453
- if (origin) scriptOrigins.add(origin);
3454
- }
3455
- for (const css of libs.css || []) {
3456
- const origin = safeOrigin(css.url);
3457
- if (origin) styleOrigins.add(origin);
3458
- }
3459
- return { scriptOrigins, styleOrigins };
3460
- }
3461
- function filterLibrariesByContext(libs, context) {
3462
- if (context === "preview") return libs;
3463
- const key = context === "editor" ? "disableEditor" : "disableBuild";
3464
- return {
3465
- js: libs.js,
3466
- css: (libs.css || []).filter((css) => !css[key])
3467
- };
3468
- }
3469
- function safeOrigin(url) {
3470
- if (!url || url.startsWith("/") || url.startsWith("./") || url.startsWith("../")) {
3471
- return null;
3472
- }
3473
- try {
3474
- return new URL(url).origin;
3475
- } catch {
3476
- return null;
3477
- }
3478
- }
3479
-
3480
3293
  // lib/server/ssr/htmlGenerator.ts
3481
3294
  function generateImagePreloadTags(preloadImages) {
3482
3295
  if (preloadImages.length === 0) return "";
@@ -3558,7 +3371,7 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
3558
3371
  await configService.load();
3559
3372
  const globalLibraries = configService.getLibraries() || { js: [], css: [] };
3560
3373
  const globalCustomCode = configService.getCustomCode();
3561
- const menoBadgeHtml = configService.getShowMenoBadge() ? `<style>.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>` : "";
3374
+ 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>` : "";
3562
3375
  const mergedCustomCode = {
3563
3376
  head: [globalCustomCode.head, pageCustomCode?.head].filter(Boolean).join("\n"),
3564
3377
  bodyStart: [globalCustomCode.bodyStart, pageCustomCode?.bodyStart].filter(Boolean).join("\n"),
@@ -3690,7 +3503,8 @@ picture {
3690
3503
  utilityCSS,
3691
3504
  interactiveCSS
3692
3505
  ].filter(Boolean).join("\n");
3693
- const finalCSS = useBundled ? minifyCSS(combinedCSS) : combinedCSS;
3506
+ const cssWithStableViewport = rewriteViewportUnits(combinedCSS);
3507
+ const finalCSS = useBundled ? minifyCSS(cssWithStableViewport) : cssWithStableViewport;
3694
3508
  const prefetchConfig = await loadPrefetchConfig();
3695
3509
  const menoConfig = prefetchConfig.enabled ? { prefetch: prefetchConfig } : {};
3696
3510
  const hasConfig = Object.keys(menoConfig).length > 0;
@@ -3712,7 +3526,7 @@ picture {
3712
3526
  const scriptPreloadTag = extScriptPath ? `<link rel="preload" href="${extScriptPath}" as="script">` : "";
3713
3527
  const imagePreloadTags = generateImagePreloadTags(rendered.preloadImages);
3714
3528
  const wsUrl = serverPort ? `'ws://localhost:${serverPort}/hmr'` : `location.origin.replace('http','ws')+'/hmr'`;
3715
- const liveReloadScript = injectLiveReload ? `<script${nonceAttr}>(function(){var ws,timer,gen=0,lastSrvRoot=null;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;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 smartUpdate(curR,srvR,oldR){var ce=curR.querySelectorAll('[data-element-path]'),se=srvR.querySelectorAll('[data-element-path]');if(ce.length!==se.length){if(curR.innerHTML!==srvR.innerHTML)curR.innerHTML=srvR.innerHTML;return}var sbp={};for(var i=0;i<se.length;i++)sbp[se[i].getAttribute('data-element-path')]=se[i];var obp={};if(oldR){var oe=oldR.querySelectorAll('[data-element-path]');for(var i=0;i<oe.length;i++)obp[oe[i].getAttribute('data-element-path')]=oe[i]}for(var i=0;i<ce.length;i++){var c=ce[i],p=c.getAttribute('data-element-path'),s=sbp[p];if(!s){if(curR.innerHTML!==srvR.innerHTML)curR.innerHTML=srvR.innerHTML;return}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');if(or&&nr)smartUpdate(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.parentNode.replaceChild(ns.cloneNode(true),os);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;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)})}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')):'';if(oss===nss){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>` : "";
3529
+ 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>` : "";
3716
3530
  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>` : "";
3717
3531
  const styleContent = useBundled ? finalCSS : `
3718
3532
  ${combinedCSS.split("\n").join("\n ")}
@@ -3722,8 +3536,9 @@ picture {
3722
3536
  <head>
3723
3537
  <meta charset="UTF-8">
3724
3538
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
3725
- ${iconTags ? iconTags + "\n " : ""}${scriptPreloadTag ? scriptPreloadTag + "\n " : ""}${imagePreloadTags ? imagePreloadTags + "\n " : ""}${fontPreloadTags ? fontPreloadTags + "\n " : ""}${libraryTags.headCSS ? libraryTags.headCSS + "\n " : ""}${libraryTags.headJS ? libraryTags.headJS + "\n " : ""}${rendered.meta}
3726
- ${configInlineScript}${cmsInlineScript}${clientDataScripts}<style id="meno-styles">${styleContent}</style>${mergedCustomCode.head ? "\n " + mergedCustomCode.head : ""}
3539
+ ${cspNonce ? `<meta name="csp-nonce" content="${cspNonce}">
3540
+ ` : ""}${iconTags ? iconTags + "\n " : ""}${scriptPreloadTag ? scriptPreloadTag + "\n " : ""}${imagePreloadTags ? imagePreloadTags + "\n " : ""}${fontPreloadTags ? fontPreloadTags + "\n " : ""}${libraryTags.headCSS ? libraryTags.headCSS + "\n " : ""}${libraryTags.headJS ? libraryTags.headJS + "\n " : ""}${rendered.meta}
3541
+ ${configInlineScript}${cmsInlineScript}${clientDataScripts}<style id="meno-styles"${nonceAttr}>${styleContent}</style>${mergedCustomCode.head ? "\n " + mergedCustomCode.head : ""}
3727
3542
  </head>
3728
3543
  <body>${mergedCustomCode.bodyStart ? "\n " + mergedCustomCode.bodyStart : ""}
3729
3544
  <div id="root">
@@ -6348,10 +6163,6 @@ export {
6348
6163
  generateFontPreloadTags,
6349
6164
  generateThemeColorVariablesCSS,
6350
6165
  generateVariablesCSS,
6351
- buildSlugIndex,
6352
- translatePath,
6353
- getLocaleLinks,
6354
- resolveSlugToPageId,
6355
6166
  escapeHtml,
6356
6167
  buildAttributes,
6357
6168
  styleToString,
@@ -6374,13 +6185,8 @@ export {
6374
6185
  menoFilterScript,
6375
6186
  needsMenoFilter,
6376
6187
  prepareClientData,
6377
- mergeLibraries,
6378
- generateLibraryTags,
6379
- collectComponentLibraries,
6380
- extractLibraryOrigins,
6381
- filterLibrariesByContext,
6382
6188
  generateSSRHTML,
6383
6189
  FileSystemCMSProvider,
6384
6190
  migrateTemplatesDirectory
6385
6191
  };
6386
- //# sourceMappingURL=chunk-CXCBV2M7.js.map
6192
+ //# sourceMappingURL=chunk-IGYR22T6.js.map