meno-core 1.0.34 → 1.0.35

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 (46) hide show
  1. package/build-static.ts +18 -2
  2. package/dist/build-static.js +4 -4
  3. package/dist/chunks/{chunk-RDI56Q2W.js → chunk-2ZTKVTUO.js} +180 -27
  4. package/dist/chunks/chunk-2ZTKVTUO.js.map +7 -0
  5. package/dist/chunks/{chunk-VNAPFF4I.js → chunk-AIXKUVNG.js} +12 -6
  6. package/dist/chunks/{chunk-VNAPFF4I.js.map → chunk-AIXKUVNG.js.map} +2 -2
  7. package/dist/chunks/{chunk-7PCKKQQI.js → chunk-NRKBBQL3.js} +91 -8
  8. package/dist/chunks/chunk-NRKBBQL3.js.map +7 -0
  9. package/dist/chunks/{chunk-LDJGXCRR.js → chunk-NV25WXCA.js} +31 -22
  10. package/dist/chunks/chunk-NV25WXCA.js.map +7 -0
  11. package/dist/chunks/{chunk-RO5BCYPR.js → chunk-VNVD6LFP.js} +20 -6
  12. package/dist/chunks/chunk-VNVD6LFP.js.map +7 -0
  13. package/dist/entries/server-router.js +4 -4
  14. package/dist/lib/client/index.js +8 -66
  15. package/dist/lib/client/index.js.map +2 -2
  16. package/dist/lib/server/index.js +5 -5
  17. package/dist/lib/shared/index.js +9 -1
  18. package/dist/lib/shared/index.js.map +2 -2
  19. package/lib/client/core/builders/listBuilder.ts +8 -98
  20. package/lib/client/hmr/HMRManager.tsx +1 -1
  21. package/lib/client/templateEngine.test.ts +23 -1
  22. package/lib/client/templateEngine.ts +13 -6
  23. package/lib/server/createServer.ts +52 -0
  24. package/lib/server/jsonLoader.ts +60 -12
  25. package/lib/server/routes/api/components.ts +20 -0
  26. package/lib/server/routes/index.ts +13 -1
  27. package/lib/server/routes/pages.ts +4 -1
  28. package/lib/server/services/cmsService.test.ts +0 -12
  29. package/lib/server/services/cmsService.ts +11 -2
  30. package/lib/server/services/componentService.ts +45 -5
  31. package/lib/server/ssr/htmlGenerator.ts +17 -4
  32. package/lib/server/ssr/ssrRenderer.ts +21 -5
  33. package/lib/shared/itemTemplateUtils.test.ts +36 -0
  34. package/lib/shared/itemTemplateUtils.ts +4 -1
  35. package/lib/shared/jsonRepair.test.ts +105 -0
  36. package/lib/shared/jsonRepair.ts +177 -0
  37. package/lib/shared/treePathUtils.ts +4 -0
  38. package/lib/shared/types/cms.ts +18 -2
  39. package/lib/shared/types/config.ts +18 -0
  40. package/lib/shared/types/index.ts +2 -2
  41. package/lib/shared/validation/schemas.ts +0 -1
  42. package/package.json +1 -1
  43. package/dist/chunks/chunk-7PCKKQQI.js.map +0 -7
  44. package/dist/chunks/chunk-LDJGXCRR.js.map +0 -7
  45. package/dist/chunks/chunk-RDI56Q2W.js.map +0 -7
  46. package/dist/chunks/chunk-RO5BCYPR.js.map +0 -7
package/build-static.ts CHANGED
@@ -27,6 +27,7 @@ import { FileSystemCMSProvider } from "./lib/server/providers/fileSystemCMSProvi
27
27
  import { CMSService } from "./lib/server/services/cmsService";
28
28
  import { isI18nValue, resolveI18nValue } from "./lib/shared/i18n";
29
29
  import type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig, Experiment } from "./lib/shared/types";
30
+ import { isItemDraftForLocale, isItemFullyPublished } from "./lib/shared/types";
30
31
  import type { SlugMap } from "./lib/shared/slugTranslator";
31
32
  import { buildItemUrl } from "./lib/shared/itemTemplateUtils";
32
33
  import { generateMiddleware, generateTrackFunction, generateResultsFunction } from "./lib/server/ab/generateFunctions";
@@ -156,6 +157,7 @@ function copyDirectory(src: string, dest: string): void {
156
157
  }
157
158
  }
158
159
 
160
+
159
161
  /**
160
162
  * Get locale-specific output path for a page with translated slug support
161
163
  * Default locale files go to root, other locales to subdirectories
@@ -403,9 +405,11 @@ async function buildCMSTemplates(
403
405
  console.log(` Found ${items.length} item(s)`);
404
406
 
405
407
  // Prepare client data if clientData is enabled
408
+ // Filter out fully-draft items from client data (client data is locale-agnostic)
406
409
  let clientDataCollections: Map<string, ClientDataCollection> | undefined;
407
410
  if (cmsSchema.clientData?.enabled) {
408
- const clientData = prepareClientData(cmsSchema.id, items, cmsSchema.clientData);
411
+ const publishedItems = items.filter(item => isItemFullyPublished(item));
412
+ const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);
409
413
  if (clientData) {
410
414
  if (clientData.strategy === 'inline') {
411
415
  // Inline data embedded in HTML
@@ -422,6 +426,14 @@ async function buildCMSTemplates(
422
426
  for (const item of items) {
423
427
  for (const localeConfig of i18nConfig.locales) {
424
428
  const locale = localeConfig.code;
429
+
430
+ // Skip draft items per locale in production builds
431
+ const isDevBuild = process.env.MENO_DEV_BUILD === 'true';
432
+ if (!isDevBuild && isItemDraftForLocale(item, locale)) {
433
+ console.log(` ⏭️ Skipping draft: ${item._filename || item._id} [${locale}]`);
434
+ continue;
435
+ }
436
+
425
437
  const baseUrl = siteUrl || "";
426
438
  const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
427
439
 
@@ -442,6 +454,7 @@ async function buildCMSTemplates(
442
454
  returnSeparateJS: true,
443
455
  pageLibraries: pageData.meta?.libraries,
444
456
  clientDataCollections,
457
+ isProductionBuild: true,
445
458
  }) as SSRHTMLResult;
446
459
 
447
460
  // If there's JavaScript, write to external file and update HTML
@@ -688,12 +701,14 @@ export async function buildStaticPages(): Promise<void> {
688
701
  console.log(`✅ ${parts.join(', ')} copied\n`);
689
702
 
690
703
  // Load all global components
691
- const components = await loadComponentDirectory(projectPaths.components());
704
+ const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());
692
705
  const globalComponents: Record<string, ComponentDefinition> = {};
693
706
  components.forEach((value, key) => {
694
707
  globalComponents[key] = value;
695
708
  });
696
709
 
710
+ for (const warning of warnings) console.warn(`⚠️ ${warning}`);
711
+ for (const error of errors) console.error(`❌ ${error}`);
697
712
  console.log(`✅ Loaded ${components.size} global component(s)\n`);
698
713
 
699
714
  // Initialize CMS service for CMSList rendering
@@ -859,6 +874,7 @@ export async function buildStaticPages(): Promise<void> {
859
874
  cmsService,
860
875
  returnSeparateJS: true,
861
876
  pageLibraries: pageData.meta?.libraries,
877
+ isProductionBuild: true,
862
878
  }) as SSRHTMLResult;
863
879
 
864
880
  // If there's JavaScript, write to external file and update HTML
@@ -9,14 +9,14 @@ import {
9
9
  hashContent,
10
10
  injectTrackingScript,
11
11
  isCMSPage
12
- } from "./chunks/chunk-RO5BCYPR.js";
13
- import "./chunks/chunk-RDI56Q2W.js";
12
+ } from "./chunks/chunk-VNVD6LFP.js";
13
+ import "./chunks/chunk-2ZTKVTUO.js";
14
14
  import "./chunks/chunk-YSV4AG55.js";
15
15
  import "./chunks/chunk-E6L5FESH.js";
16
16
  import "./chunks/chunk-GB2LHWZF.js";
17
17
  import "./chunks/chunk-RWTKZPWJ.js";
18
- import "./chunks/chunk-VNAPFF4I.js";
19
- import "./chunks/chunk-LDJGXCRR.js";
18
+ import "./chunks/chunk-AIXKUVNG.js";
19
+ import "./chunks/chunk-NV25WXCA.js";
20
20
  import "./chunks/chunk-PGH3ATYI.js";
21
21
  import "./chunks/chunk-UB44F4Z2.js";
22
22
  import "./chunks/chunk-KULPBDC7.js";
@@ -23,7 +23,7 @@ import {
23
23
  processStructure,
24
24
  resolveHtmlMapping,
25
25
  skipEmptyTemplateAttributes
26
- } from "./chunk-VNAPFF4I.js";
26
+ } from "./chunk-AIXKUVNG.js";
27
27
  import {
28
28
  DEFAULT_PREFETCH_CONFIG,
29
29
  SSRRegistry,
@@ -43,6 +43,7 @@ import {
43
43
  isCurrentLink,
44
44
  isEmbedNode,
45
45
  isHtmlNode,
46
+ isItemDraftForLocale,
46
47
  isLinkNode,
47
48
  isListNode,
48
49
  isLocaleListNode,
@@ -59,7 +60,7 @@ import {
59
60
  singularize,
60
61
  validateCMSItem,
61
62
  validateComponentDefinition
62
- } from "./chunk-LDJGXCRR.js";
63
+ } from "./chunk-NV25WXCA.js";
63
64
  import {
64
65
  DEFAULT_BREAKPOINTS,
65
66
  DEFAULT_I18N_CONFIG,
@@ -87,6 +88,113 @@ import {
87
88
 
88
89
  // lib/server/jsonLoader.ts
89
90
  import { existsSync, readdirSync } from "fs";
91
+
92
+ // lib/shared/jsonRepair.ts
93
+ function parseJsonError(error, content) {
94
+ if (!(error instanceof SyntaxError)) {
95
+ return { message: String(error), line: 1, column: 1 };
96
+ }
97
+ const msg = error.message;
98
+ const posMatch = msg.match(/at position (\d+)/i);
99
+ if (posMatch) {
100
+ const pos = parseInt(posMatch[1], 10);
101
+ const { line, column } = offsetToLineColumn(content, pos);
102
+ return { message: msg, line, column };
103
+ }
104
+ const lineMatch = msg.match(/line (\d+)/i);
105
+ const colMatch = msg.match(/column (\d+)/i);
106
+ if (lineMatch) {
107
+ return {
108
+ message: msg,
109
+ line: parseInt(lineMatch[1], 10),
110
+ column: colMatch ? parseInt(colMatch[1], 10) : 1
111
+ };
112
+ }
113
+ return { message: msg, line: 1, column: 1 };
114
+ }
115
+ function offsetToLineColumn(content, offset) {
116
+ let line = 1;
117
+ let lastNewline = -1;
118
+ for (let i = 0; i < offset && i < content.length; i++) {
119
+ if (content[i] === "\n") {
120
+ line++;
121
+ lastNewline = i;
122
+ }
123
+ }
124
+ return { line, column: offset - lastNewline };
125
+ }
126
+ function attemptJsonRepair(content) {
127
+ try {
128
+ const data = JSON.parse(content);
129
+ return { success: true, repaired: false, data };
130
+ } catch (firstError) {
131
+ }
132
+ {
133
+ const fixed = content.replace(/,\s*([\]}])/g, "$1");
134
+ try {
135
+ const data = JSON.parse(fixed);
136
+ const trailingCommaMatch = content.match(/,\s*([\]}])/);
137
+ const pos = trailingCommaMatch ? content.indexOf(trailingCommaMatch[0]) : 0;
138
+ const { line, column } = offsetToLineColumn(content, pos);
139
+ return {
140
+ success: true,
141
+ repaired: true,
142
+ data,
143
+ repairDescription: `removed trailing comma at line ${line}`,
144
+ repairLine: line,
145
+ repairColumn: column
146
+ };
147
+ } catch {
148
+ }
149
+ }
150
+ {
151
+ const lines = content.split("\n");
152
+ let fixed = "";
153
+ let repairLine = 0;
154
+ for (let i = 0; i < lines.length; i++) {
155
+ const line = lines[i];
156
+ const trimmed = line.trimEnd();
157
+ const nextLine = i + 1 < lines.length ? lines[i + 1] : null;
158
+ if (nextLine !== null) {
159
+ const nextTrimmed = nextLine.trimStart();
160
+ const needsComma = /["\d\w\]}\-]$/.test(trimmed) && !trimmed.endsWith(",") && !trimmed.endsWith("{") && !trimmed.endsWith("[") && !trimmed.endsWith(":") && (nextTrimmed.startsWith('"') || nextTrimmed.startsWith("{") || nextTrimmed.startsWith("[") || /^\d/.test(nextTrimmed) || nextTrimmed === "true" || nextTrimmed === "false" || nextTrimmed === "null");
161
+ if (needsComma) {
162
+ fixed += trimmed + ",\n";
163
+ if (repairLine === 0) repairLine = i + 1;
164
+ } else {
165
+ fixed += line + "\n";
166
+ }
167
+ } else {
168
+ fixed += line;
169
+ }
170
+ }
171
+ try {
172
+ const data = JSON.parse(fixed);
173
+ return {
174
+ success: true,
175
+ repaired: true,
176
+ data,
177
+ repairDescription: `auto-fixed missing comma at line ${repairLine}`,
178
+ repairLine,
179
+ repairColumn: 1
180
+ };
181
+ } catch {
182
+ }
183
+ }
184
+ let errorInfo;
185
+ try {
186
+ JSON.parse(content);
187
+ errorInfo = { message: "Unknown error", line: 1, column: 1 };
188
+ } catch (e) {
189
+ errorInfo = parseJsonError(e, content);
190
+ }
191
+ return { success: false, repaired: false, error: errorInfo };
192
+ }
193
+ function formatJsonErrorMessage(fileName, error) {
194
+ return `${fileName}: JSON syntax error at line ${error.line}, column ${error.column} \u2014 ${error.message}`;
195
+ }
196
+
197
+ // lib/server/jsonLoader.ts
90
198
  async function loadJSONFile(filePath) {
91
199
  try {
92
200
  if (await fileExists(filePath)) {
@@ -112,9 +220,28 @@ async function loadFileAsText(filePath) {
112
220
  }
113
221
  async function loadSingleComponent(filePath, componentName, category) {
114
222
  const content = await loadJSONFile(filePath);
115
- if (!content) return null;
223
+ if (!content) return { component: null };
224
+ const fileName = `${componentName}.json`;
225
+ const repairResult = attemptJsonRepair(content);
226
+ if (!repairResult.success) {
227
+ return {
228
+ component: null,
229
+ error: {
230
+ componentName,
231
+ description: repairResult.error.message,
232
+ line: repairResult.error.line,
233
+ column: repairResult.error.column
234
+ }
235
+ };
236
+ }
237
+ const warning = repairResult.repaired ? {
238
+ componentName,
239
+ description: repairResult.repairDescription,
240
+ line: repairResult.repairLine ?? 1,
241
+ column: repairResult.repairColumn ?? 1
242
+ } : void 0;
116
243
  try {
117
- const parsed = parseJSON(content);
244
+ const parsed = repairResult.data;
118
245
  const validationResult = validateComponentDefinition(parsed);
119
246
  if (!validationResult.valid) {
120
247
  console.warn(
@@ -146,15 +273,17 @@ async function loadSingleComponent(filePath, componentName, category) {
146
273
  componentDef._category = category;
147
274
  componentDef._relativePath = `${category}/${componentName}`;
148
275
  }
149
- return componentDef;
276
+ return { component: componentDef, warning };
150
277
  } catch (error) {
151
- return null;
278
+ return { component: null };
152
279
  }
153
280
  }
154
281
  async function loadComponentDirectory(dirPath = "./components") {
155
282
  const components = /* @__PURE__ */ new Map();
283
+ const warnings = [];
284
+ const errors = [];
156
285
  if (!existsSync(dirPath)) {
157
- return components;
286
+ return { components, warnings, errors };
158
287
  }
159
288
  const entries = readdirSync(dirPath, { withFileTypes: true });
160
289
  const loadEntries = [];
@@ -182,19 +311,21 @@ async function loadComponentDirectory(dirPath = "./components") {
182
311
  const results = await Promise.all(
183
312
  loadEntries.map(async (e) => ({
184
313
  ...e,
185
- componentDef: await loadSingleComponent(e.filePath, e.componentName, e.category)
314
+ result: await loadSingleComponent(e.filePath, e.componentName, e.category)
186
315
  }))
187
316
  );
188
- for (const { componentName, category, componentDef } of results) {
189
- if (!componentDef) continue;
317
+ for (const { componentName, category, result } of results) {
318
+ if (result.warning) warnings.push(result.warning);
319
+ if (result.error) errors.push(result.error);
320
+ if (!result.component) continue;
190
321
  if (components.has(componentName)) {
191
322
  const location = category ? `category "${category}"` : "root level";
192
323
  console.warn(`[jsonLoader] Duplicate component name "${componentName}" found at ${location}. Skipping.`);
193
324
  continue;
194
325
  }
195
- components.set(componentName, componentDef);
326
+ components.set(componentName, result.component);
196
327
  }
197
- return components;
328
+ return { components, warnings, errors };
198
329
  }
199
330
  function mapPageNameToPath(pageName) {
200
331
  return pageName === "index" ? "/" : `/${pageName}`;
@@ -834,7 +965,7 @@ var CMSService = class {
834
965
  * @param defaultLocale - Optional default locale (URLs without prefix)
835
966
  * @returns Array of URLs
836
967
  */
837
- async getCollectionURLs(collection, locales, defaultLocale) {
968
+ async getCollectionURLs(collection, locales, defaultLocale, options) {
838
969
  if (!this.provider) {
839
970
  return [];
840
971
  }
@@ -845,11 +976,13 @@ var CMSService = class {
845
976
  for (const item of items) {
846
977
  const slugValue = item[schemaInfo.schema.slugField];
847
978
  if (typeof slugValue === "string") {
979
+ if (options?.excludeDrafts && defaultLocale && isItemDraftForLocale(item, defaultLocale)) continue;
848
980
  urls.push(
849
981
  schemaInfo.schema.urlPattern.replace("{{slug}}", slugValue)
850
982
  );
851
983
  } else if (isI18nValue(slugValue) && locales) {
852
984
  for (const locale of locales) {
985
+ if (options?.excludeDrafts && isItemDraftForLocale(item, locale)) continue;
853
986
  const localizedSlug = slugValue[locale];
854
987
  if (localizedSlug) {
855
988
  const path2 = schemaInfo.schema.urlPattern.replace("{{slug}}", localizedSlug);
@@ -914,6 +1047,9 @@ var CMSService = class {
914
1047
  return [];
915
1048
  }
916
1049
  let items = await this.getCachedItems(query.collection);
1050
+ if (query.excludeDraftLocale) {
1051
+ items = items.filter((item) => !isItemDraftForLocale(item, query.excludeDraftLocale));
1052
+ }
917
1053
  if (query.filter) {
918
1054
  items = this.applyFilters(items, query.filter);
919
1055
  }
@@ -1089,8 +1225,7 @@ var CMSService = class {
1089
1225
  }
1090
1226
  await this.provider.saveItem(ref.collection, {
1091
1227
  ...item,
1092
- [ref.fieldName]: newValue,
1093
- _updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1228
+ [ref.fieldName]: newValue
1094
1229
  });
1095
1230
  removedCount++;
1096
1231
  }
@@ -1834,7 +1969,7 @@ async function expandRichTextComponents(html, ctx) {
1834
1969
  return resolved.join("");
1835
1970
  }
1836
1971
  var ssrComponentRegistry = new SSRRegistry();
1837
- async function buildComponentHTML(node, globalComponents = {}, pageComponents = {}, locale, i18nConfig, slugMappings, pagePath, cmsContext, cmsService) {
1972
+ async function buildComponentHTML(node, globalComponents = {}, pageComponents = {}, locale, i18nConfig, slugMappings, pagePath, cmsContext, cmsService, isProductionBuild) {
1838
1973
  const interactiveStylesMap = /* @__PURE__ */ new Map();
1839
1974
  const preloadImages = [];
1840
1975
  const neededCollections = /* @__PURE__ */ new Set();
@@ -1860,8 +1995,9 @@ async function buildComponentHTML(node, globalComponents = {}, pageComponents =
1860
1995
  // Collect interactive styles during render
1861
1996
  preloadImages,
1862
1997
  // Collect high-priority images for preloading
1863
- neededCollections
1998
+ neededCollections,
1864
1999
  // Track collections that need client-side data
2000
+ isProductionBuild
1865
2001
  };
1866
2002
  const html = await renderNode(node, ctx);
1867
2003
  return { html, interactiveStylesMap, preloadImages, neededCollections };
@@ -2003,13 +2139,17 @@ async function getCollectionItems(node, source, ctx) {
2003
2139
  const ids = Array.isArray(node.items) ? node.items : [node.items];
2004
2140
  items = await ctx.cmsService.getItemsByIds(source, ids);
2005
2141
  }
2142
+ if (ctx.locale) {
2143
+ items = items.filter((item) => !isItemDraftForLocale(item, ctx.locale));
2144
+ }
2006
2145
  } else {
2007
2146
  const query = {
2008
2147
  collection: source,
2009
2148
  filter: resolveFilterTemplates(node.filter, ctx.templateContext),
2010
2149
  sort: node.sort,
2011
2150
  limit: node.limit,
2012
- offset: node.offset
2151
+ offset: node.offset,
2152
+ excludeDraftLocale: ctx.locale
2013
2153
  };
2014
2154
  items = await ctx.cmsService.queryItems(query);
2015
2155
  }
@@ -2207,7 +2347,12 @@ async function renderNode(node, ctx) {
2207
2347
  if (!ctx.templateMode && templateCtx2 && hasItemTemplates(href)) {
2208
2348
  const rawValue = resolveTemplateRawValue(href, templateCtx2);
2209
2349
  if (rawValue && typeof rawValue === "object" && "href" in rawValue) {
2210
- const linkObj = rawValue;
2350
+ let linkObj = rawValue;
2351
+ while (typeof linkObj.href === "object" && linkObj.href !== null && "href" in linkObj.href) {
2352
+ const nested = linkObj.href;
2353
+ if (!linkObj.target && nested.target) linkObj = { ...linkObj, target: nested.target };
2354
+ linkObj = { ...linkObj, href: nested.href };
2355
+ }
2211
2356
  href = String(linkObj.href);
2212
2357
  targetFromLink = linkObj.target;
2213
2358
  } else {
@@ -2643,7 +2788,7 @@ function renderLocaleList(node, ctx) {
2643
2788
  }
2644
2789
  return '<div data-locale-list="true"></div>';
2645
2790
  }
2646
- async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", baseUrl = "", locale, i18nConfig, slugMappings, cmsContext, cmsService) {
2791
+ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", baseUrl = "", locale, i18nConfig, slugMappings, cmsContext, cmsService, isProductionBuild) {
2647
2792
  const rootNode = pageData?.root || void 0;
2648
2793
  if (!rootNode) {
2649
2794
  throw new Error("Page data must have a root node");
@@ -2667,7 +2812,7 @@ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", ba
2667
2812
  }
2668
2813
  }
2669
2814
  const pageComponents = pageData?.components || {};
2670
- const { html: contentHTML, interactiveStylesMap, preloadImages, neededCollections } = rootNode ? await buildComponentHTML(rootNode, globalComponents, pageComponents, effectiveLocale, config, slugMappings, pagePath, cmsContext, cmsService) : { html: "", interactiveStylesMap: /* @__PURE__ */ new Map(), preloadImages: [], neededCollections: /* @__PURE__ */ new Set() };
2815
+ const { html: contentHTML, interactiveStylesMap, preloadImages, neededCollections } = rootNode ? await buildComponentHTML(rootNode, globalComponents, pageComponents, effectiveLocale, config, slugMappings, pagePath, cmsContext, cmsService, isProductionBuild) : { html: "", interactiveStylesMap: /* @__PURE__ */ new Map(), preloadImages: [], neededCollections: /* @__PURE__ */ new Set() };
2671
2816
  const javascript = await collectComponentJavaScript(globalComponents, pageComponents);
2672
2817
  const componentCSS = collectComponentCSS(globalComponents, pageComponents);
2673
2818
  const fullUrl = baseUrl ? `${baseUrl}${pagePath}` : pagePath;
@@ -3105,9 +3250,11 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
3105
3250
  pageLibraries,
3106
3251
  clientDataCollections,
3107
3252
  injectLiveReload = false,
3108
- isEditor = false
3253
+ isEditor = false,
3254
+ isProductionBuild = false,
3255
+ serverPort
3109
3256
  } = options;
3110
- const rendered = await renderPageSSR(pageData, components, path2, base, loc, void 0, slugs, cms, cmsServ);
3257
+ const rendered = await renderPageSSR(pageData, components, path2, base, loc, void 0, slugs, cms, cmsServ, isProductionBuild);
3111
3258
  let finalClientDataCollections = clientDataCollections;
3112
3259
  if (rendered.neededCollections.size > 0 && cmsServ) {
3113
3260
  finalClientDataCollections = clientDataCollections ? new Map(clientDataCollections) : /* @__PURE__ */ new Map();
@@ -3120,7 +3267,10 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
3120
3267
  );
3121
3268
  continue;
3122
3269
  }
3123
- const items = await cmsServ.queryItems({ collection: collectionId });
3270
+ const items = await cmsServ.queryItems({
3271
+ collection: collectionId,
3272
+ excludeDraftLocale: loc
3273
+ });
3124
3274
  const clientData = prepareClientData(collectionId, items, {
3125
3275
  ...schema.clientData,
3126
3276
  strategy: "inline"
@@ -3233,6 +3383,7 @@ button {
3233
3383
  outline: inherit;
3234
3384
  }
3235
3385
  img {
3386
+ display: block;
3236
3387
  width: 100%;
3237
3388
  height: 100%;
3238
3389
  }
@@ -3271,7 +3422,8 @@ img {
3271
3422
  const iconTags = [faviconTag, appleTouchIconTag].filter(Boolean).join("\n ");
3272
3423
  const scriptPreloadTag = extScriptPath ? `<link rel="preload" href="${extScriptPath}" as="script">` : "";
3273
3424
  const imagePreloadTags = generateImagePreloadTags(rendered.preloadImages);
3274
- const liveReloadScript = injectLiveReload ? `<script>(function(){var ws,timer,gen=0;function connect(){ws=new WebSocket(location.origin.replace('http','ws')+'/hmr');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');var nr=d.getElementById('root');if(or&&nr)or.innerHTML=nr.innerHTML;var os=document.querySelector('head style');var ns=d.querySelector('head style');if(os&&ns)os.textContent=ns.textContent;var nh=d.documentElement;if(nh){document.documentElement.setAttribute('lang',nh.getAttribute('lang')||'en');document.documentElement.setAttribute('theme',nh.getAttribute('theme')||'light')}document.querySelectorAll('script[id^="meno-cms-"]').forEach(function(s){s.remove()});d.querySelectorAll('script[id^="meno-cms-"]').forEach(function(s){var c=document.createElement('script');c.type=s.type;c.id=s.id;c.textContent=s.textContent;document.head.appendChild(c)});var oscr=document.querySelector('script[src^="/_scripts/"]');var nscr=d.querySelector('script[src^="/_scripts/"]');if(nscr){var src=nscr.getAttribute('src');if(oscr)oscr.remove();var s=document.createElement('script');s.src=src+(src.indexOf('?')>-1?'&':'?')+'_r='+Date.now();document.body.appendChild(s)}else if(oscr){oscr.remove()}window.scrollTo(sx,sy)}).catch(function(){location.reload()})}connect()})()</script>` : "";
3425
+ const wsUrl = serverPort ? `'ws://localhost:${serverPort}/hmr'` : `location.origin.replace('http','ws')+'/hmr'`;
3426
+ const liveReloadScript = injectLiveReload ? `<script>(function(){var ws,timer,gen=0;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');var nr=d.getElementById('root');if(or&&nr)or.innerHTML=nr.innerHTML;var os=document.getElementById('meno-styles');var ns=d.getElementById('meno-styles');if(os&&ns){os.parentNode.replaceChild(ns.cloneNode(true),os)}var nh=d.documentElement;if(nh){document.documentElement.setAttribute('lang',nh.getAttribute('lang')||'en');document.documentElement.setAttribute('theme',nh.getAttribute('theme')||'light')}document.querySelectorAll('script[id^="meno-cms-"]').forEach(function(s){s.remove()});d.querySelectorAll('script[id^="meno-cms-"]').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;document.querySelectorAll('body > script[src^="/libraries/"]').forEach(function(o){o.remove()});d.querySelectorAll('body > script[src^="/libraries/"]').forEach(function(n){var ls=document.createElement('script');ls.src=n.getAttribute('src')+(n.getAttribute('src').indexOf('?')>-1?'&':'?')+'_r='+Date.now();document.body.appendChild(ls)});var oscr=document.querySelector('script[src^="/_scripts/"]');var nscr=d.querySelector('script[src^="/_scripts/"]');if(nscr){var src=nscr.getAttribute('src');if(oscr)oscr.remove();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{if(oscr)oscr.remove();document.dispatchEvent(new Event('DOMContentLoaded'));window.scrollTo(sx,sy)}}).catch(function(){location.reload()})}connect()})()</script>` : "";
3275
3427
  const scrollHandlerScript = injectLiveReload ? `<script>(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>` : "";
3276
3428
  const styleContent = useBundled ? finalCSS : `
3277
3429
  ${combinedCSS.split("\n").join("\n ")}
@@ -3282,7 +3434,7 @@ img {
3282
3434
  <meta charset="UTF-8">
3283
3435
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
3284
3436
  ${iconTags ? iconTags + "\n " : ""}${scriptPreloadTag ? scriptPreloadTag + "\n " : ""}${imagePreloadTags ? imagePreloadTags + "\n " : ""}${fontPreloadTags ? fontPreloadTags + "\n " : ""}${libraryTags.headCSS ? libraryTags.headCSS + "\n " : ""}${libraryTags.headJS ? libraryTags.headJS + "\n " : ""}${rendered.meta}
3285
- ${configInlineScript}${cmsInlineScript}${clientDataScripts}<style>${styleContent}</style>
3437
+ ${configInlineScript}${cmsInlineScript}${clientDataScripts}<style id="meno-styles">${styleContent}</style>
3286
3438
  </head>
3287
3439
  <body>
3288
3440
  <div id="root">
@@ -3558,6 +3710,7 @@ async function migrateTemplatesDirectory() {
3558
3710
  }
3559
3711
 
3560
3712
  export {
3713
+ formatJsonErrorMessage,
3561
3714
  loadJSONFile,
3562
3715
  parseJSON,
3563
3716
  loadComponentDirectory,
@@ -3602,4 +3755,4 @@ export {
3602
3755
  FileSystemCMSProvider,
3603
3756
  migrateTemplatesDirectory
3604
3757
  };
3605
- //# sourceMappingURL=chunk-RDI56Q2W.js.map
3758
+ //# sourceMappingURL=chunk-2ZTKVTUO.js.map