meno-core 1.0.49 → 1.0.50

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 (53) hide show
  1. package/build-astro.ts +6 -2
  2. package/dist/build-static.js +5 -5
  3. package/dist/chunks/{chunk-JER5NQVM.js → chunk-56EUSC6D.js} +4 -4
  4. package/dist/chunks/{chunk-S2CX6HFM.js → chunk-7NIC4I3V.js} +42 -20
  5. package/dist/chunks/chunk-7NIC4I3V.js.map +7 -0
  6. package/dist/chunks/{chunk-EQYDSPBB.js → chunk-CVLFID6V.js} +64 -20
  7. package/dist/chunks/chunk-CVLFID6V.js.map +7 -0
  8. package/dist/chunks/{chunk-LKAGAQ3M.js → chunk-EDQSMAMP.js} +13 -2
  9. package/dist/chunks/{chunk-LKAGAQ3M.js.map → chunk-EDQSMAMP.js.map} +2 -2
  10. package/dist/chunks/{chunk-6IVUG7FY.js → chunk-LPVETICS.js} +19 -2
  11. package/dist/chunks/{chunk-6IVUG7FY.js.map → chunk-LPVETICS.js.map} +2 -2
  12. package/dist/chunks/{chunk-KPU2XHOS.js → chunk-PQ2HRXDR.js} +1 -1
  13. package/dist/chunks/chunk-PQ2HRXDR.js.map +7 -0
  14. package/dist/chunks/{chunk-CHD5UCFF.js → chunk-YWJJD5D6.js} +116 -32
  15. package/dist/chunks/chunk-YWJJD5D6.js.map +7 -0
  16. package/dist/chunks/{configService-CCA6AIDI.js → configService-VOY2MY2K.js} +2 -2
  17. package/dist/entries/server-router.js +5 -5
  18. package/dist/lib/client/index.js +41 -15
  19. package/dist/lib/client/index.js.map +3 -3
  20. package/dist/lib/server/index.js +11 -9
  21. package/dist/lib/server/index.js.map +2 -2
  22. package/dist/lib/shared/index.js +2 -2
  23. package/lib/client/core/ComponentBuilder.test.ts +34 -0
  24. package/lib/client/core/ComponentBuilder.ts +25 -3
  25. package/lib/client/core/builders/embedBuilder.ts +13 -5
  26. package/lib/client/core/builders/linkNodeBuilder.ts +13 -5
  27. package/lib/client/core/builders/localeListBuilder.ts +13 -5
  28. package/lib/client/templateEngine.ts +24 -0
  29. package/lib/server/fileWatcher.test.ts +134 -0
  30. package/lib/server/fileWatcher.ts +100 -32
  31. package/lib/server/jsonLoader.ts +1 -0
  32. package/lib/server/providers/fileSystemCMSProvider.ts +46 -14
  33. package/lib/server/services/configService.ts +1 -0
  34. package/lib/server/services/fileWatcherService.ts +17 -0
  35. package/lib/server/ssr/htmlGenerator.ts +11 -3
  36. package/lib/server/ssr/ssrRenderer.test.ts +258 -0
  37. package/lib/server/ssr/ssrRenderer.ts +46 -5
  38. package/lib/server/webflow/buildWebflow.ts +1 -1
  39. package/lib/server/websocketManager.test.ts +61 -6
  40. package/lib/server/websocketManager.ts +25 -1
  41. package/lib/shared/cssProperties.test.ts +28 -0
  42. package/lib/shared/cssProperties.ts +27 -1
  43. package/lib/shared/types/api.ts +10 -1
  44. package/lib/shared/types/cms.ts +18 -9
  45. package/lib/shared/validation/schemas.test.ts +93 -0
  46. package/lib/shared/validation/schemas.ts +56 -15
  47. package/package.json +1 -1
  48. package/dist/chunks/chunk-CHD5UCFF.js.map +0 -7
  49. package/dist/chunks/chunk-EQYDSPBB.js.map +0 -7
  50. package/dist/chunks/chunk-KPU2XHOS.js.map +0 -7
  51. package/dist/chunks/chunk-S2CX6HFM.js.map +0 -7
  52. /package/dist/chunks/{chunk-JER5NQVM.js.map → chunk-56EUSC6D.js.map} +0 -0
  53. /package/dist/chunks/{configService-CCA6AIDI.js.map → configService-VOY2MY2K.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  configService
3
- } from "./chunk-KPU2XHOS.js";
3
+ } from "./chunk-PQ2HRXDR.js";
4
4
  import {
5
5
  projectPaths,
6
6
  resolveProjectPath,
@@ -26,7 +26,7 @@ import {
26
26
  processStructure,
27
27
  resolveHtmlMapping,
28
28
  skipEmptyTemplateAttributes
29
- } from "./chunk-LKAGAQ3M.js";
29
+ } from "./chunk-EDQSMAMP.js";
30
30
  import {
31
31
  DEFAULT_PREFETCH_CONFIG,
32
32
  SSRRegistry,
@@ -66,7 +66,7 @@ import {
66
66
  validateCMSDraftItem,
67
67
  validateCMSItem,
68
68
  validateComponentDefinition
69
- } from "./chunk-S2CX6HFM.js";
69
+ } from "./chunk-7NIC4I3V.js";
70
70
  import {
71
71
  DEFAULT_BREAKPOINTS,
72
72
  DEFAULT_FLUID_RANGE,
@@ -2038,6 +2038,18 @@ function getDOMPurify() {
2038
2038
  }
2039
2039
  return _DOMPurify;
2040
2040
  }
2041
+ function resolveI18nAttrs(attrs, locale, i18nConfig) {
2042
+ let mutated = null;
2043
+ const config = i18nConfig ?? DEFAULT_I18N_CONFIG;
2044
+ const effectiveLocale = locale || config.defaultLocale;
2045
+ for (const [key, value] of Object.entries(attrs)) {
2046
+ if (isI18nValue(value)) {
2047
+ mutated = mutated ?? { ...attrs };
2048
+ mutated[key] = resolveI18nValue(value, effectiveLocale, config);
2049
+ }
2050
+ }
2051
+ return mutated ?? attrs;
2052
+ }
2041
2053
  function getTemplateContext(ctx) {
2042
2054
  return ctx.templateContext || null;
2043
2055
  }
@@ -2520,6 +2532,15 @@ async function renderNode(node, ctx) {
2520
2532
  }))).join("");
2521
2533
  }
2522
2534
  if (typeof node !== "object") return "";
2535
+ if (isI18nValue(node)) {
2536
+ const i18nResolveConfig = i18nConfig ?? DEFAULT_I18N_CONFIG;
2537
+ const i18nEffectiveLocale = locale || i18nResolveConfig.defaultLocale;
2538
+ const resolved = resolveI18nValue(node, i18nEffectiveLocale, i18nResolveConfig);
2539
+ return renderNode(
2540
+ resolved,
2541
+ ctx
2542
+ );
2543
+ }
2523
2544
  if (!evaluateIfCondition(node, ctx)) {
2524
2545
  return "";
2525
2546
  }
@@ -2559,7 +2580,7 @@ async function renderNode(node, ctx) {
2559
2580
  KEEP_CONTENT: true
2560
2581
  }) : htmlContent;
2561
2582
  const optimizedHtml = ctx.imageMetadataMap ? rewriteRichTextImages(sanitizedHtml, ctx.imageMetadataMap, ctx.imageFormat) : sanitizedHtml;
2562
- const nodeAttributes2 = extractAttributesFromNode(node);
2583
+ const nodeAttributes2 = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
2563
2584
  const classNames = ["oem"];
2564
2585
  if (nodeStyle) {
2565
2586
  const utilityClasses2 = processStyleToClasses(nodeStyle, ctx);
@@ -2618,7 +2639,7 @@ async function renderNode(node, ctx) {
2618
2639
  href = processCMSTemplate(href, ctx.cmsContext.cms, locale, i18nConfig);
2619
2640
  }
2620
2641
  href = localizeHref(href, ctx);
2621
- const nodeAttributes2 = extractAttributesFromNode(node);
2642
+ const nodeAttributes2 = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
2622
2643
  const classNames = ["olink"];
2623
2644
  if (nodeStyle) {
2624
2645
  const utilityClasses2 = processStyleToClasses(nodeStyle, ctx);
@@ -2670,7 +2691,7 @@ async function renderNode(node, ctx) {
2670
2691
  if (!ctx.templateMode && templateCtx && Object.keys(nodeProps).length > 0) {
2671
2692
  nodeProps = processItemPropsTemplate(nodeProps, templateCtx, i18nResolver);
2672
2693
  }
2673
- let nodeAttributes = extractAttributesFromNode(node);
2694
+ let nodeAttributes = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
2674
2695
  const originalAttributes = { ...nodeAttributes };
2675
2696
  if (ctx.cmsContext?.cms && Object.keys(nodeAttributes).length > 0) {
2676
2697
  nodeAttributes = processCMSPropsTemplate(nodeAttributes, ctx.cmsContext.cms, locale, i18nConfig);
@@ -3056,7 +3077,7 @@ function renderLocaleList(node, ctx) {
3056
3077
  links.push(`<a href="${escapeHtml(link.path)}"${hreflangAttr}${currentAttr} data-locale="${escapeHtml(link.locale)}"${classAttrForLink}>${linkContent}</a>`);
3057
3078
  }
3058
3079
  const linksHTML = showSeparator ? links.join(`<span${separatorClassAttr}></span>`) : links.join("");
3059
- const nodeAttributes = extractAttributesFromNode(node);
3080
+ const nodeAttributes = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
3060
3081
  const attrsStr = buildAttributes(nodeAttributes);
3061
3082
  const localeListResult = `<div data-locale-list="true"${containerClassAttr}${localeListStyleAttr}${attrsStr}${editorAttrs(ctx)}>${linksHTML}</div>`;
3062
3083
  if (ctx.ssrFallbackCollector && ctx.elementPath) {
@@ -3632,9 +3653,11 @@ picture {
3632
3653
  const cmsInlineScript = cmsTemplatePath && cms && (!useBundled || injectLiveReload) ? `<script>window.__MENO_CMS__=${JSON.stringify({ item: cms.cms, templatePath: cmsTemplatePath })}</script>
3633
3654
  ` : "";
3634
3655
  const clientDataScripts = finalClientDataCollections && finalClientDataCollections.size > 0 ? generateAllInlineDataScripts(finalClientDataCollections) + "\n " : "";
3635
- const faviconTag = iconsConfig.favicon ? `<link rel="icon" href="${escapeHtml(iconsConfig.favicon)}" />` : "";
3656
+ const hasDarkFavicon = !!(iconsConfig.favicon && iconsConfig.faviconDark);
3657
+ const faviconTag = iconsConfig.favicon ? `<link rel="icon" href="${escapeHtml(iconsConfig.favicon)}"${hasDarkFavicon ? ' media="(prefers-color-scheme: light)"' : ""} />` : "";
3658
+ const faviconDarkTag = iconsConfig.faviconDark ? `<link rel="icon" href="${escapeHtml(iconsConfig.faviconDark)}" media="(prefers-color-scheme: dark)" />` : "";
3636
3659
  const appleTouchIconTag = iconsConfig.appleTouchIcon ? `<link rel="apple-touch-icon" href="${escapeHtml(iconsConfig.appleTouchIcon)}" />` : "";
3637
- const iconTags = [faviconTag, appleTouchIconTag].filter(Boolean).join("\n ");
3660
+ const iconTags = [faviconTag, faviconDarkTag, appleTouchIconTag].filter(Boolean).join("\n ");
3638
3661
  const scriptPreloadTag = extScriptPath ? `<link rel="preload" href="${extScriptPath}" as="script">` : "";
3639
3662
  const imagePreloadTags = generateImagePreloadTags(rendered.preloadImages);
3640
3663
  const wsUrl = serverPort ? `'ws://localhost:${serverPort}/hmr'` : `location.origin.replace('http','ws')+'/hmr'`;
@@ -5833,8 +5856,10 @@ async function loadJSONFile2(filePath) {
5833
5856
  }
5834
5857
  }
5835
5858
  function normalizeItem(content, filename, isDraft = false) {
5859
+ const raw = content;
5836
5860
  const base = {
5837
- ...content,
5861
+ ...raw,
5862
+ _id: raw._id || filename,
5838
5863
  _slug: filename,
5839
5864
  _filename: filename
5840
5865
  };
@@ -5842,8 +5867,12 @@ function normalizeItem(content, filename, isDraft = false) {
5842
5867
  return base;
5843
5868
  }
5844
5869
  function stripTransient(item) {
5845
- const { _slug, _isDraft, _hasDraft, _url, ...rest } = item;
5846
- return rest;
5870
+ const { _slug, _isDraft, _hasDraft, _url, _filename, ...rest } = item;
5871
+ const out = rest;
5872
+ if (typeof _filename === "string" && _filename !== out._id) {
5873
+ out._filename = _filename;
5874
+ }
5875
+ return out;
5847
5876
  }
5848
5877
  var FileSystemCMSProvider = class {
5849
5878
  constructor(templatesDir, cmsDir) {
@@ -5974,8 +6003,10 @@ var FileSystemCMSProvider = class {
5974
6003
  return items.find((item) => item._id === id) || null;
5975
6004
  }
5976
6005
  /**
5977
- * Save item to file system
5978
- * Uses _filename for file path (stable, doesn't change when slug changes)
6006
+ * Save item to file system.
6007
+ * The on-disk filename is derived from `_filename` (legacy alias) when set,
6008
+ * otherwise from `_id` (canonical identifier; equals the filename for new
6009
+ * items). Falls back to the slugField value as a last resort.
5979
6010
  */
5980
6011
  async saveItem(collection, item) {
5981
6012
  this.validateCollection(collection);
@@ -5991,10 +6022,16 @@ var FileSystemCMSProvider = class {
5991
6022
  } else {
5992
6023
  const slugField = schemaInfo.schema.slugField;
5993
6024
  const slugValue = item[slugField];
5994
- filename = typeof slugValue === "string" ? slugValue : String(slugValue);
6025
+ if (typeof slugValue === "string" && slugValue) {
6026
+ filename = slugValue;
6027
+ } else if (typeof item._id === "string" && item._id) {
6028
+ filename = item._id;
6029
+ } else {
6030
+ filename = String(slugValue);
6031
+ }
5995
6032
  }
5996
6033
  if (!filename || filename === "[object Object]") {
5997
- throw new Error("Missing _filename field. Items must have _filename set on creation.");
6034
+ throw new Error("Cannot derive filename: item is missing _id, _filename, and a usable slug-field value.");
5998
6035
  }
5999
6036
  this.validateFilename(filename);
6000
6037
  const collectionDir = join2(this.cmsDir, collection);
@@ -6082,7 +6119,8 @@ var FileSystemCMSProvider = class {
6082
6119
  /**
6083
6120
  * Save the draft version of an item. Loose validation — drafts may have
6084
6121
  * missing required fields or partial data. Strict validation only runs at
6085
- * publish time. The item's `_filename` determines the target file.
6122
+ * publish time. The on-disk filename is derived the same way as for
6123
+ * `saveItem` (prefer `_filename`, fall back to `_id`).
6086
6124
  */
6087
6125
  async saveDraft(collection, item) {
6088
6126
  this.validateCollection(collection);
@@ -6098,10 +6136,16 @@ var FileSystemCMSProvider = class {
6098
6136
  } else {
6099
6137
  const slugField = schemaInfo.schema.slugField;
6100
6138
  const slugValue = item[slugField];
6101
- filename = typeof slugValue === "string" ? slugValue : String(slugValue);
6139
+ if (typeof slugValue === "string" && slugValue) {
6140
+ filename = slugValue;
6141
+ } else if (typeof item._id === "string" && item._id) {
6142
+ filename = item._id;
6143
+ } else {
6144
+ filename = String(slugValue);
6145
+ }
6102
6146
  }
6103
6147
  if (!filename || filename === "[object Object]") {
6104
- throw new Error("Missing _filename field. Drafts must have _filename set on creation.");
6148
+ throw new Error("Cannot derive draft filename: item is missing _id, _filename, and a usable slug-field value.");
6105
6149
  }
6106
6150
  this.validateFilename(filename);
6107
6151
  const collectionDir = join2(this.cmsDir, collection);
@@ -6288,4 +6332,4 @@ export {
6288
6332
  FileSystemCMSProvider,
6289
6333
  migrateTemplatesDirectory
6290
6334
  };
6291
- //# sourceMappingURL=chunk-EQYDSPBB.js.map
6335
+ //# sourceMappingURL=chunk-CVLFID6V.js.map