meno-core 1.0.49 → 1.0.51
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-astro.ts +6 -2
- package/build-static.ts +8 -1
- package/dist/bin/cli.js +1 -1
- package/dist/build-static.js +5 -5
- package/dist/chunks/{chunk-KPU2XHOS.js → chunk-2MHDV5BF.js} +11 -1
- package/dist/chunks/chunk-2MHDV5BF.js.map +7 -0
- package/dist/chunks/{chunk-JER5NQVM.js → chunk-3KJ6SJZC.js} +5 -5
- package/dist/chunks/{chunk-JER5NQVM.js.map → chunk-3KJ6SJZC.js.map} +2 -2
- package/dist/chunks/{chunk-S2CX6HFM.js → chunk-7NIC4I3V.js} +42 -20
- package/dist/chunks/chunk-7NIC4I3V.js.map +7 -0
- package/dist/chunks/{chunk-EQYDSPBB.js → chunk-DM54NPEC.js} +114 -31
- package/dist/chunks/chunk-DM54NPEC.js.map +7 -0
- package/dist/chunks/{chunk-LKAGAQ3M.js → chunk-EDQSMAMP.js} +13 -2
- package/dist/chunks/{chunk-LKAGAQ3M.js.map → chunk-EDQSMAMP.js.map} +2 -2
- package/dist/chunks/{chunk-4OFZP5NQ.js → chunk-HNLUO36W.js} +15 -4
- package/dist/chunks/chunk-HNLUO36W.js.map +7 -0
- package/dist/chunks/{chunk-6IVUG7FY.js → chunk-LPVETICS.js} +19 -2
- package/dist/chunks/{chunk-6IVUG7FY.js.map → chunk-LPVETICS.js.map} +2 -2
- package/dist/chunks/{chunk-CHD5UCFF.js → chunk-V7CD7V7W.js} +149 -46
- package/dist/chunks/chunk-V7CD7V7W.js.map +7 -0
- package/dist/chunks/{configService-CCA6AIDI.js → configService-R3OGU2UD.js} +2 -2
- package/dist/entries/server-router.js +5 -5
- package/dist/lib/client/index.js +41 -15
- package/dist/lib/client/index.js.map +3 -3
- package/dist/lib/server/index.js +12 -10
- package/dist/lib/server/index.js.map +2 -2
- package/dist/lib/shared/index.js +2 -2
- package/lib/client/core/ComponentBuilder.test.ts +34 -0
- package/lib/client/core/ComponentBuilder.ts +25 -3
- package/lib/client/core/builders/embedBuilder.ts +13 -5
- package/lib/client/core/builders/linkNodeBuilder.ts +13 -5
- package/lib/client/core/builders/localeListBuilder.ts +13 -5
- package/lib/client/templateEngine.ts +24 -0
- package/lib/server/fileWatcher.test.ts +134 -0
- package/lib/server/fileWatcher.ts +100 -32
- package/lib/server/jsonLoader.ts +1 -0
- package/lib/server/providers/fileSystemCMSProvider.ts +46 -14
- package/lib/server/routes/pages.ts +37 -2
- package/lib/server/services/cmsService.ts +21 -0
- package/lib/server/services/configService.ts +21 -0
- package/lib/server/services/fileWatcherService.ts +17 -0
- package/lib/server/ssr/buildErrorOverlay.ts +22 -4
- package/lib/server/ssr/errorOverlay.ts +11 -3
- package/lib/server/ssr/htmlGenerator.nonce.test.ts +165 -0
- package/lib/server/ssr/htmlGenerator.ts +36 -9
- package/lib/server/ssr/liveReloadIntegration.test.ts +3 -1
- package/lib/server/ssr/metaTagGenerator.ts +35 -5
- package/lib/server/ssr/ssrRenderer.test.ts +258 -0
- package/lib/server/ssr/ssrRenderer.ts +47 -5
- package/lib/server/ssrRenderer.test.ts +87 -2
- package/lib/server/webflow/buildWebflow.ts +1 -1
- package/lib/server/websocketManager.test.ts +61 -6
- package/lib/server/websocketManager.ts +25 -1
- package/lib/shared/cssProperties.test.ts +28 -0
- package/lib/shared/cssProperties.ts +27 -1
- package/lib/shared/types/api.ts +10 -1
- package/lib/shared/types/cms.ts +18 -9
- package/lib/shared/validation/schemas.test.ts +93 -0
- package/lib/shared/validation/schemas.ts +56 -15
- package/package.json +1 -1
- package/dist/chunks/chunk-4OFZP5NQ.js.map +0 -7
- package/dist/chunks/chunk-CHD5UCFF.js.map +0 -7
- package/dist/chunks/chunk-EQYDSPBB.js.map +0 -7
- package/dist/chunks/chunk-KPU2XHOS.js.map +0 -7
- package/dist/chunks/chunk-S2CX6HFM.js.map +0 -7
- /package/dist/chunks/{configService-CCA6AIDI.js.map → configService-R3OGU2UD.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
configService
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2MHDV5BF.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-
|
|
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-
|
|
69
|
+
} from "./chunk-7NIC4I3V.js";
|
|
70
70
|
import {
|
|
71
71
|
DEFAULT_BREAKPOINTS,
|
|
72
72
|
DEFAULT_FLUID_RANGE,
|
|
@@ -1070,6 +1070,25 @@ var CMSService = class {
|
|
|
1070
1070
|
await this.provider.saveDraft(collection, item);
|
|
1071
1071
|
this.itemsCache.delete(collection);
|
|
1072
1072
|
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Save a published item. Wraps the provider so the items cache is invalidated
|
|
1075
|
+
* immediately — without this, the editor's post-save refetch could hit a
|
|
1076
|
+
* stale snapshot inside the 5s TTL window and overwrite an optimistic preview.
|
|
1077
|
+
*/
|
|
1078
|
+
async saveItem(collection, item) {
|
|
1079
|
+
if (!this.provider) throw new Error("CMS provider not configured");
|
|
1080
|
+
await this.provider.saveItem(collection, item);
|
|
1081
|
+
this.itemsCache.delete(collection);
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Delete an item (and its draft sibling). Cache invalidation, same rationale
|
|
1085
|
+
* as `saveItem`.
|
|
1086
|
+
*/
|
|
1087
|
+
async deleteItem(collection, filename) {
|
|
1088
|
+
if (!this.provider) throw new Error("CMS provider not configured");
|
|
1089
|
+
await this.provider.deleteItem(collection, filename);
|
|
1090
|
+
this.itemsCache.delete(collection);
|
|
1091
|
+
}
|
|
1073
1092
|
async discardDraft(collection, filename) {
|
|
1074
1093
|
if (!this.provider) throw new Error("CMS provider not configured");
|
|
1075
1094
|
await this.provider.discardDraft(collection, filename);
|
|
@@ -1622,7 +1641,7 @@ function extractPageMeta(pageData) {
|
|
|
1622
1641
|
}
|
|
1623
1642
|
return meta;
|
|
1624
1643
|
}
|
|
1625
|
-
function generateMetaTags(meta, url = "", locale = "en", config = DEFAULT_I18N_CONFIG,
|
|
1644
|
+
function generateMetaTags(meta, url = "", locale = "en", config = DEFAULT_I18N_CONFIG, options) {
|
|
1626
1645
|
const tags = [];
|
|
1627
1646
|
const resolve = (value) => {
|
|
1628
1647
|
const resolved = resolveI18nValue(value, locale, config);
|
|
@@ -1659,11 +1678,28 @@ function generateMetaTags(meta, url = "", locale = "en", config = DEFAULT_I18N_C
|
|
|
1659
1678
|
if (url) {
|
|
1660
1679
|
tags.push(`<meta property="og:url" content="${escapeHtml(url)}" />`);
|
|
1661
1680
|
}
|
|
1681
|
+
const hasAnyMeta = title || description || ogImage || ogTitle || ogDescription;
|
|
1682
|
+
if (hasAnyMeta) {
|
|
1683
|
+
const cardType = ogImage ? "summary_large_image" : "summary";
|
|
1684
|
+
tags.push(`<meta name="twitter:card" content="${cardType}" />`);
|
|
1685
|
+
}
|
|
1686
|
+
if (ogTitle) {
|
|
1687
|
+
tags.push(`<meta name="twitter:title" content="${escapeHtml(ogTitle)}" />`);
|
|
1688
|
+
}
|
|
1689
|
+
if (ogDescription) {
|
|
1690
|
+
tags.push(`<meta name="twitter:description" content="${escapeHtml(ogDescription)}" />`);
|
|
1691
|
+
}
|
|
1692
|
+
const rawHandle = options?.social?.twitterHandle?.trim();
|
|
1693
|
+
if (rawHandle) {
|
|
1694
|
+
const handle = rawHandle.startsWith("@") ? rawHandle : `@${rawHandle}`;
|
|
1695
|
+
tags.push(`<meta name="twitter:site" content="${escapeHtml(handle)}" />`);
|
|
1696
|
+
tags.push(`<meta name="twitter:creator" content="${escapeHtml(handle)}" />`);
|
|
1697
|
+
}
|
|
1662
1698
|
if (url) {
|
|
1663
1699
|
tags.push(`<link rel="canonical" href="${escapeHtml(url)}" />`);
|
|
1664
1700
|
}
|
|
1665
|
-
if (
|
|
1666
|
-
const { slugMappings, pagePath = "/", baseUrl = "" } =
|
|
1701
|
+
if (options?.slugMappings && options.slugMappings.length > 0 && config.locales.length > 1) {
|
|
1702
|
+
const { slugMappings, pagePath = "/", baseUrl = "" } = options;
|
|
1667
1703
|
const slugIndex = buildSlugIndex(slugMappings);
|
|
1668
1704
|
const localeLinks = getLocaleLinks(pagePath, locale, config, slugIndex);
|
|
1669
1705
|
for (const link of localeLinks) {
|
|
@@ -2038,6 +2074,18 @@ function getDOMPurify() {
|
|
|
2038
2074
|
}
|
|
2039
2075
|
return _DOMPurify;
|
|
2040
2076
|
}
|
|
2077
|
+
function resolveI18nAttrs(attrs, locale, i18nConfig) {
|
|
2078
|
+
let mutated = null;
|
|
2079
|
+
const config = i18nConfig ?? DEFAULT_I18N_CONFIG;
|
|
2080
|
+
const effectiveLocale = locale || config.defaultLocale;
|
|
2081
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
2082
|
+
if (isI18nValue(value)) {
|
|
2083
|
+
mutated = mutated ?? { ...attrs };
|
|
2084
|
+
mutated[key] = resolveI18nValue(value, effectiveLocale, config);
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return mutated ?? attrs;
|
|
2088
|
+
}
|
|
2041
2089
|
function getTemplateContext(ctx) {
|
|
2042
2090
|
return ctx.templateContext || null;
|
|
2043
2091
|
}
|
|
@@ -2520,6 +2568,15 @@ async function renderNode(node, ctx) {
|
|
|
2520
2568
|
}))).join("");
|
|
2521
2569
|
}
|
|
2522
2570
|
if (typeof node !== "object") return "";
|
|
2571
|
+
if (isI18nValue(node)) {
|
|
2572
|
+
const i18nResolveConfig = i18nConfig ?? DEFAULT_I18N_CONFIG;
|
|
2573
|
+
const i18nEffectiveLocale = locale || i18nResolveConfig.defaultLocale;
|
|
2574
|
+
const resolved = resolveI18nValue(node, i18nEffectiveLocale, i18nResolveConfig);
|
|
2575
|
+
return renderNode(
|
|
2576
|
+
resolved,
|
|
2577
|
+
ctx
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2523
2580
|
if (!evaluateIfCondition(node, ctx)) {
|
|
2524
2581
|
return "";
|
|
2525
2582
|
}
|
|
@@ -2559,7 +2616,7 @@ async function renderNode(node, ctx) {
|
|
|
2559
2616
|
KEEP_CONTENT: true
|
|
2560
2617
|
}) : htmlContent;
|
|
2561
2618
|
const optimizedHtml = ctx.imageMetadataMap ? rewriteRichTextImages(sanitizedHtml, ctx.imageMetadataMap, ctx.imageFormat) : sanitizedHtml;
|
|
2562
|
-
const nodeAttributes2 = extractAttributesFromNode(node);
|
|
2619
|
+
const nodeAttributes2 = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
|
|
2563
2620
|
const classNames = ["oem"];
|
|
2564
2621
|
if (nodeStyle) {
|
|
2565
2622
|
const utilityClasses2 = processStyleToClasses(nodeStyle, ctx);
|
|
@@ -2618,7 +2675,7 @@ async function renderNode(node, ctx) {
|
|
|
2618
2675
|
href = processCMSTemplate(href, ctx.cmsContext.cms, locale, i18nConfig);
|
|
2619
2676
|
}
|
|
2620
2677
|
href = localizeHref(href, ctx);
|
|
2621
|
-
const nodeAttributes2 = extractAttributesFromNode(node);
|
|
2678
|
+
const nodeAttributes2 = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
|
|
2622
2679
|
const classNames = ["olink"];
|
|
2623
2680
|
if (nodeStyle) {
|
|
2624
2681
|
const utilityClasses2 = processStyleToClasses(nodeStyle, ctx);
|
|
@@ -2670,7 +2727,7 @@ async function renderNode(node, ctx) {
|
|
|
2670
2727
|
if (!ctx.templateMode && templateCtx && Object.keys(nodeProps).length > 0) {
|
|
2671
2728
|
nodeProps = processItemPropsTemplate(nodeProps, templateCtx, i18nResolver);
|
|
2672
2729
|
}
|
|
2673
|
-
let nodeAttributes = extractAttributesFromNode(node);
|
|
2730
|
+
let nodeAttributes = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
|
|
2674
2731
|
const originalAttributes = { ...nodeAttributes };
|
|
2675
2732
|
if (ctx.cmsContext?.cms && Object.keys(nodeAttributes).length > 0) {
|
|
2676
2733
|
nodeAttributes = processCMSPropsTemplate(nodeAttributes, ctx.cmsContext.cms, locale, i18nConfig);
|
|
@@ -3056,7 +3113,7 @@ function renderLocaleList(node, ctx) {
|
|
|
3056
3113
|
links.push(`<a href="${escapeHtml(link.path)}"${hreflangAttr}${currentAttr} data-locale="${escapeHtml(link.locale)}"${classAttrForLink}>${linkContent}</a>`);
|
|
3057
3114
|
}
|
|
3058
3115
|
const linksHTML = showSeparator ? links.join(`<span${separatorClassAttr}></span>`) : links.join("");
|
|
3059
|
-
const nodeAttributes = extractAttributesFromNode(node);
|
|
3116
|
+
const nodeAttributes = resolveI18nAttrs(extractAttributesFromNode(node), locale, i18nConfig);
|
|
3060
3117
|
const attrsStr = buildAttributes(nodeAttributes);
|
|
3061
3118
|
const localeListResult = `<div data-locale-list="true"${containerClassAttr}${localeListStyleAttr}${attrsStr}${editorAttrs(ctx)}>${linksHTML}</div>`;
|
|
3062
3119
|
if (ctx.ssrFallbackCollector && ctx.elementPath) {
|
|
@@ -3097,7 +3154,8 @@ async function renderPageSSR(pageData, globalComponents = {}, pagePath = "/", ba
|
|
|
3097
3154
|
const metaTags = generateMetaTags(meta, fullUrl, effectiveLocale, config, {
|
|
3098
3155
|
slugMappings,
|
|
3099
3156
|
pagePath,
|
|
3100
|
-
baseUrl
|
|
3157
|
+
baseUrl,
|
|
3158
|
+
social: configService.getSocial()
|
|
3101
3159
|
});
|
|
3102
3160
|
const resolvedTitle = resolveI18nValue(meta.title, effectiveLocale, config);
|
|
3103
3161
|
return {
|
|
@@ -3454,8 +3512,10 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
|
|
|
3454
3512
|
injectEditorAttrs = false,
|
|
3455
3513
|
isEditor = false,
|
|
3456
3514
|
isProductionBuild = false,
|
|
3457
|
-
serverPort
|
|
3515
|
+
serverPort,
|
|
3516
|
+
cspNonce
|
|
3458
3517
|
} = options;
|
|
3518
|
+
const nonceAttr = cspNonce ? ` nonce="${cspNonce}"` : "";
|
|
3459
3519
|
const rendered = await renderPageSSR(pageData, components, path2, base, loc, void 0, slugs, cms, cmsServ, isProductionBuild, injectEditorAttrs);
|
|
3460
3520
|
let finalClientDataCollections = clientDataCollections;
|
|
3461
3521
|
if (rendered.neededCollections.size > 0 && cmsServ) {
|
|
@@ -3486,7 +3546,7 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
|
|
|
3486
3546
|
await configService.load();
|
|
3487
3547
|
const globalLibraries = configService.getLibraries() || { js: [], css: [] };
|
|
3488
3548
|
const globalCustomCode = configService.getCustomCode();
|
|
3489
|
-
const menoBadgeHtml = configService.getShowMenoBadge() ? `<
|
|
3549
|
+
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>` : "";
|
|
3490
3550
|
const mergedCustomCode = {
|
|
3491
3551
|
head: [globalCustomCode.head, pageCustomCode?.head].filter(Boolean).join("\n"),
|
|
3492
3552
|
bodyStart: [globalCustomCode.bodyStart, pageCustomCode?.bodyStart].filter(Boolean).join("\n"),
|
|
@@ -3555,7 +3615,7 @@ async function generateSSRHTML(pageDataOrOptions, globalComponents = {}, pagePat
|
|
|
3555
3615
|
} else {
|
|
3556
3616
|
const escapedJavaScript = allJavaScript.replace(/<\/script>/gi, "<\\/script>");
|
|
3557
3617
|
componentScript = `
|
|
3558
|
-
<script>
|
|
3618
|
+
<script${nonceAttr}>
|
|
3559
3619
|
${escapedJavaScript}
|
|
3560
3620
|
</script>`;
|
|
3561
3621
|
}
|
|
@@ -3622,24 +3682,26 @@ picture {
|
|
|
3622
3682
|
const prefetchConfig = await loadPrefetchConfig();
|
|
3623
3683
|
const menoConfig = prefetchConfig.enabled ? { prefetch: prefetchConfig } : {};
|
|
3624
3684
|
const hasConfig = Object.keys(menoConfig).length > 0;
|
|
3625
|
-
const configInlineScript = hasConfig && !extScriptPath && !returnSeparateJS ? `<script>window.__MENO_CONFIG__=${JSON.stringify(menoConfig)}</script>
|
|
3685
|
+
const configInlineScript = hasConfig && !extScriptPath && !returnSeparateJS ? `<script${nonceAttr}>window.__MENO_CONFIG__=${JSON.stringify(menoConfig)}</script>
|
|
3626
3686
|
` : "";
|
|
3627
3687
|
if (hasConfig && externalJavaScript !== null) {
|
|
3628
3688
|
externalJavaScript = `window.__MENO_CONFIG__=${JSON.stringify(menoConfig)};
|
|
3629
3689
|
|
|
3630
3690
|
` + externalJavaScript;
|
|
3631
3691
|
}
|
|
3632
|
-
const cmsInlineScript = cmsTemplatePath && cms && (!useBundled || injectLiveReload) ? `<script>window.__MENO_CMS__=${JSON.stringify({ item: cms.cms, templatePath: cmsTemplatePath })}</script>
|
|
3692
|
+
const cmsInlineScript = cmsTemplatePath && cms && (!useBundled || injectLiveReload) ? `<script${nonceAttr}>window.__MENO_CMS__=${JSON.stringify({ item: cms.cms, templatePath: cmsTemplatePath })}</script>
|
|
3633
3693
|
` : "";
|
|
3634
3694
|
const clientDataScripts = finalClientDataCollections && finalClientDataCollections.size > 0 ? generateAllInlineDataScripts(finalClientDataCollections) + "\n " : "";
|
|
3635
|
-
const
|
|
3695
|
+
const hasDarkFavicon = !!(iconsConfig.favicon && iconsConfig.faviconDark);
|
|
3696
|
+
const faviconTag = iconsConfig.favicon ? `<link rel="icon" href="${escapeHtml(iconsConfig.favicon)}"${hasDarkFavicon ? ' media="(prefers-color-scheme: light)"' : ""} />` : "";
|
|
3697
|
+
const faviconDarkTag = iconsConfig.faviconDark ? `<link rel="icon" href="${escapeHtml(iconsConfig.faviconDark)}" media="(prefers-color-scheme: dark)" />` : "";
|
|
3636
3698
|
const appleTouchIconTag = iconsConfig.appleTouchIcon ? `<link rel="apple-touch-icon" href="${escapeHtml(iconsConfig.appleTouchIcon)}" />` : "";
|
|
3637
|
-
const iconTags = [faviconTag, appleTouchIconTag].filter(Boolean).join("\n ");
|
|
3699
|
+
const iconTags = [faviconTag, faviconDarkTag, appleTouchIconTag].filter(Boolean).join("\n ");
|
|
3638
3700
|
const scriptPreloadTag = extScriptPath ? `<link rel="preload" href="${extScriptPath}" as="script">` : "";
|
|
3639
3701
|
const imagePreloadTags = generateImagePreloadTags(rendered.preloadImages);
|
|
3640
3702
|
const wsUrl = serverPort ? `'ws://localhost:${serverPort}/hmr'` : `location.origin.replace('http','ws')+'/hmr'`;
|
|
3641
|
-
const liveReloadScript = injectLiveReload ? `<script>(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>` : "";
|
|
3642
|
-
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>` : "";
|
|
3703
|
+
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>` : "";
|
|
3704
|
+
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>` : "";
|
|
3643
3705
|
const styleContent = useBundled ? finalCSS : `
|
|
3644
3706
|
${combinedCSS.split("\n").join("\n ")}
|
|
3645
3707
|
`;
|
|
@@ -5833,8 +5895,10 @@ async function loadJSONFile2(filePath) {
|
|
|
5833
5895
|
}
|
|
5834
5896
|
}
|
|
5835
5897
|
function normalizeItem(content, filename, isDraft = false) {
|
|
5898
|
+
const raw = content;
|
|
5836
5899
|
const base = {
|
|
5837
|
-
...
|
|
5900
|
+
...raw,
|
|
5901
|
+
_id: raw._id || filename,
|
|
5838
5902
|
_slug: filename,
|
|
5839
5903
|
_filename: filename
|
|
5840
5904
|
};
|
|
@@ -5842,8 +5906,12 @@ function normalizeItem(content, filename, isDraft = false) {
|
|
|
5842
5906
|
return base;
|
|
5843
5907
|
}
|
|
5844
5908
|
function stripTransient(item) {
|
|
5845
|
-
const { _slug, _isDraft, _hasDraft, _url, ...rest } = item;
|
|
5846
|
-
|
|
5909
|
+
const { _slug, _isDraft, _hasDraft, _url, _filename, ...rest } = item;
|
|
5910
|
+
const out = rest;
|
|
5911
|
+
if (typeof _filename === "string" && _filename !== out._id) {
|
|
5912
|
+
out._filename = _filename;
|
|
5913
|
+
}
|
|
5914
|
+
return out;
|
|
5847
5915
|
}
|
|
5848
5916
|
var FileSystemCMSProvider = class {
|
|
5849
5917
|
constructor(templatesDir, cmsDir) {
|
|
@@ -5974,8 +6042,10 @@ var FileSystemCMSProvider = class {
|
|
|
5974
6042
|
return items.find((item) => item._id === id) || null;
|
|
5975
6043
|
}
|
|
5976
6044
|
/**
|
|
5977
|
-
* Save item to file system
|
|
5978
|
-
*
|
|
6045
|
+
* Save item to file system.
|
|
6046
|
+
* The on-disk filename is derived from `_filename` (legacy alias) when set,
|
|
6047
|
+
* otherwise from `_id` (canonical identifier; equals the filename for new
|
|
6048
|
+
* items). Falls back to the slugField value as a last resort.
|
|
5979
6049
|
*/
|
|
5980
6050
|
async saveItem(collection, item) {
|
|
5981
6051
|
this.validateCollection(collection);
|
|
@@ -5991,10 +6061,16 @@ var FileSystemCMSProvider = class {
|
|
|
5991
6061
|
} else {
|
|
5992
6062
|
const slugField = schemaInfo.schema.slugField;
|
|
5993
6063
|
const slugValue = item[slugField];
|
|
5994
|
-
|
|
6064
|
+
if (typeof slugValue === "string" && slugValue) {
|
|
6065
|
+
filename = slugValue;
|
|
6066
|
+
} else if (typeof item._id === "string" && item._id) {
|
|
6067
|
+
filename = item._id;
|
|
6068
|
+
} else {
|
|
6069
|
+
filename = String(slugValue);
|
|
6070
|
+
}
|
|
5995
6071
|
}
|
|
5996
6072
|
if (!filename || filename === "[object Object]") {
|
|
5997
|
-
throw new Error("
|
|
6073
|
+
throw new Error("Cannot derive filename: item is missing _id, _filename, and a usable slug-field value.");
|
|
5998
6074
|
}
|
|
5999
6075
|
this.validateFilename(filename);
|
|
6000
6076
|
const collectionDir = join2(this.cmsDir, collection);
|
|
@@ -6082,7 +6158,8 @@ var FileSystemCMSProvider = class {
|
|
|
6082
6158
|
/**
|
|
6083
6159
|
* Save the draft version of an item. Loose validation — drafts may have
|
|
6084
6160
|
* missing required fields or partial data. Strict validation only runs at
|
|
6085
|
-
* publish time. The
|
|
6161
|
+
* publish time. The on-disk filename is derived the same way as for
|
|
6162
|
+
* `saveItem` (prefer `_filename`, fall back to `_id`).
|
|
6086
6163
|
*/
|
|
6087
6164
|
async saveDraft(collection, item) {
|
|
6088
6165
|
this.validateCollection(collection);
|
|
@@ -6098,10 +6175,16 @@ var FileSystemCMSProvider = class {
|
|
|
6098
6175
|
} else {
|
|
6099
6176
|
const slugField = schemaInfo.schema.slugField;
|
|
6100
6177
|
const slugValue = item[slugField];
|
|
6101
|
-
|
|
6178
|
+
if (typeof slugValue === "string" && slugValue) {
|
|
6179
|
+
filename = slugValue;
|
|
6180
|
+
} else if (typeof item._id === "string" && item._id) {
|
|
6181
|
+
filename = item._id;
|
|
6182
|
+
} else {
|
|
6183
|
+
filename = String(slugValue);
|
|
6184
|
+
}
|
|
6102
6185
|
}
|
|
6103
6186
|
if (!filename || filename === "[object Object]") {
|
|
6104
|
-
throw new Error("
|
|
6187
|
+
throw new Error("Cannot derive draft filename: item is missing _id, _filename, and a usable slug-field value.");
|
|
6105
6188
|
}
|
|
6106
6189
|
this.validateFilename(filename);
|
|
6107
6190
|
const collectionDir = join2(this.cmsDir, collection);
|
|
@@ -6288,4 +6371,4 @@ export {
|
|
|
6288
6371
|
FileSystemCMSProvider,
|
|
6289
6372
|
migrateTemplatesDirectory
|
|
6290
6373
|
};
|
|
6291
|
-
//# sourceMappingURL=chunk-
|
|
6374
|
+
//# sourceMappingURL=chunk-DM54NPEC.js.map
|