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.
- package/build-static.ts +18 -2
- package/dist/build-static.js +4 -4
- package/dist/chunks/{chunk-RDI56Q2W.js → chunk-2ZTKVTUO.js} +180 -27
- package/dist/chunks/chunk-2ZTKVTUO.js.map +7 -0
- package/dist/chunks/{chunk-VNAPFF4I.js → chunk-AIXKUVNG.js} +12 -6
- package/dist/chunks/{chunk-VNAPFF4I.js.map → chunk-AIXKUVNG.js.map} +2 -2
- package/dist/chunks/{chunk-7PCKKQQI.js → chunk-NRKBBQL3.js} +91 -8
- package/dist/chunks/chunk-NRKBBQL3.js.map +7 -0
- package/dist/chunks/{chunk-LDJGXCRR.js → chunk-NV25WXCA.js} +31 -22
- package/dist/chunks/chunk-NV25WXCA.js.map +7 -0
- package/dist/chunks/{chunk-RO5BCYPR.js → chunk-VNVD6LFP.js} +20 -6
- package/dist/chunks/chunk-VNVD6LFP.js.map +7 -0
- package/dist/entries/server-router.js +4 -4
- package/dist/lib/client/index.js +8 -66
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +5 -5
- package/dist/lib/shared/index.js +9 -1
- package/dist/lib/shared/index.js.map +2 -2
- package/lib/client/core/builders/listBuilder.ts +8 -98
- package/lib/client/hmr/HMRManager.tsx +1 -1
- package/lib/client/templateEngine.test.ts +23 -1
- package/lib/client/templateEngine.ts +13 -6
- package/lib/server/createServer.ts +52 -0
- package/lib/server/jsonLoader.ts +60 -12
- package/lib/server/routes/api/components.ts +20 -0
- package/lib/server/routes/index.ts +13 -1
- package/lib/server/routes/pages.ts +4 -1
- package/lib/server/services/cmsService.test.ts +0 -12
- package/lib/server/services/cmsService.ts +11 -2
- package/lib/server/services/componentService.ts +45 -5
- package/lib/server/ssr/htmlGenerator.ts +17 -4
- package/lib/server/ssr/ssrRenderer.ts +21 -5
- package/lib/shared/itemTemplateUtils.test.ts +36 -0
- package/lib/shared/itemTemplateUtils.ts +4 -1
- package/lib/shared/jsonRepair.test.ts +105 -0
- package/lib/shared/jsonRepair.ts +177 -0
- package/lib/shared/treePathUtils.ts +4 -0
- package/lib/shared/types/cms.ts +18 -2
- package/lib/shared/types/config.ts +18 -0
- package/lib/shared/types/index.ts +2 -2
- package/lib/shared/validation/schemas.ts +0 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-7PCKKQQI.js.map +0 -7
- package/dist/chunks/chunk-LDJGXCRR.js.map +0 -7
- package/dist/chunks/chunk-RDI56Q2W.js.map +0 -7
- 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
|
|
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
|
package/dist/build-static.js
CHANGED
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
hashContent,
|
|
10
10
|
injectTrackingScript,
|
|
11
11
|
isCMSPage
|
|
12
|
-
} from "./chunks/chunk-
|
|
13
|
-
import "./chunks/chunk-
|
|
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-
|
|
19
|
-
import "./chunks/chunk-
|
|
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-
|
|
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-
|
|
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 =
|
|
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
|
-
|
|
314
|
+
result: await loadSingleComponent(e.filePath, e.componentName, e.category)
|
|
186
315
|
}))
|
|
187
316
|
);
|
|
188
|
-
for (const { componentName, category,
|
|
189
|
-
if (
|
|
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,
|
|
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
|
-
|
|
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({
|
|
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
|
|
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-
|
|
3758
|
+
//# sourceMappingURL=chunk-2ZTKVTUO.js.map
|