meno-core 1.0.47 → 1.0.49
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 +2 -2
- package/dist/build-static.js +7 -7
- package/dist/chunks/{chunk-UUA5LEWF.js → chunk-6IVUG7FY.js} +138 -7
- package/dist/chunks/chunk-6IVUG7FY.js.map +7 -0
- package/dist/chunks/{chunk-XSWR3QLI.js → chunk-AZQYF6KE.js} +261 -130
- package/dist/chunks/chunk-AZQYF6KE.js.map +7 -0
- package/dist/chunks/{chunk-47UNLQUU.js → chunk-CHD5UCFF.js} +57 -12
- package/dist/chunks/chunk-CHD5UCFF.js.map +7 -0
- package/dist/chunks/{chunk-FGUZOYJX.js → chunk-EQYDSPBB.js} +435 -131
- package/dist/chunks/chunk-EQYDSPBB.js.map +7 -0
- package/dist/chunks/{chunk-IF3RATBY.js → chunk-H4JSCDNW.js} +2 -2
- package/dist/chunks/{chunk-KITQJYZV.js → chunk-J23ZX5AP.js} +40 -4
- package/dist/chunks/chunk-J23ZX5AP.js.map +7 -0
- package/dist/chunks/{chunk-LJFB5EBT.js → chunk-JER5NQVM.js} +5 -5
- package/dist/chunks/{chunk-ZTKHJQ2Z.js → chunk-KPU2XHOS.js} +5 -2
- package/dist/chunks/{chunk-ZTKHJQ2Z.js.map → chunk-KPU2XHOS.js.map} +2 -2
- package/dist/chunks/{chunk-BCLGRZ3U.js → chunk-LKAGAQ3M.js} +2 -2
- package/dist/chunks/{chunk-FED5MME6.js → chunk-S2CX6HFM.js} +262 -26
- package/dist/chunks/chunk-S2CX6HFM.js.map +7 -0
- package/dist/chunks/{configService-DYCUEURL.js → configService-CCA6AIDI.js} +3 -3
- package/dist/entries/server-router.js +9 -9
- package/dist/entries/server-router.js.map +2 -2
- package/dist/lib/client/index.js +64 -20
- package/dist/lib/client/index.js.map +3 -3
- package/dist/lib/server/index.js +1737 -296
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +50 -10
- package/dist/lib/shared/index.js.map +3 -3
- package/entries/server-router.tsx +6 -2
- package/lib/client/core/ComponentBuilder.test.ts +17 -0
- package/lib/client/core/ComponentBuilder.ts +25 -1
- package/lib/client/core/builders/embedBuilder.ts +15 -2
- package/lib/client/core/builders/linkNodeBuilder.ts +15 -2
- package/lib/client/core/builders/localeListBuilder.ts +17 -6
- package/lib/client/styles/StyleInjector.ts +3 -2
- package/lib/client/theme.ts +4 -4
- package/lib/server/cssGenerator.test.ts +64 -1
- package/lib/server/cssGenerator.ts +48 -9
- package/lib/server/index.ts +1 -1
- package/lib/server/jsonLoader.test.ts +0 -17
- package/lib/server/jsonLoader.ts +0 -81
- package/lib/server/providers/fileSystemCMSProvider.test.ts +163 -0
- package/lib/server/providers/fileSystemCMSProvider.ts +200 -11
- package/lib/server/routes/api/variables.ts +4 -2
- package/lib/server/routes/index.ts +1 -1
- package/lib/server/routes/pages.ts +23 -1
- package/lib/server/services/cmsService.test.ts +246 -0
- package/lib/server/services/cmsService.ts +122 -5
- package/lib/server/services/configService.ts +5 -0
- package/lib/server/ssr/attributeBuilder.ts +41 -0
- package/lib/server/ssr/htmlGenerator.test.ts +114 -2
- package/lib/server/ssr/htmlGenerator.ts +53 -6
- package/lib/server/ssr/liveReloadIntegration.test.ts +209 -0
- package/lib/server/ssr/ssrRenderer.test.ts +362 -1
- package/lib/server/ssr/ssrRenderer.ts +216 -72
- package/lib/server/utils/jsonLineMapper.test.ts +53 -1
- package/lib/server/utils/jsonLineMapper.ts +43 -3
- package/lib/server/webflow/buildWebflow.ts +343 -123
- package/lib/server/webflow/index.ts +1 -0
- package/lib/server/webflow/nodeToWebflow.test.ts +3170 -0
- package/lib/server/webflow/nodeToWebflow.ts +2141 -129
- package/lib/server/webflow/styleMapper.test.ts +389 -0
- package/lib/server/webflow/styleMapper.ts +517 -63
- package/lib/server/webflow/templateWrapper.ts +49 -0
- package/lib/server/webflow/types.ts +218 -18
- package/lib/shared/cssGeneration.test.ts +267 -1
- package/lib/shared/cssGeneration.ts +240 -18
- package/lib/shared/cssProperties.test.ts +247 -1
- package/lib/shared/cssProperties.ts +196 -6
- package/lib/shared/elementClassName.test.ts +15 -0
- package/lib/shared/elementClassName.ts +7 -3
- package/lib/shared/interfaces/contentProvider.ts +39 -6
- package/lib/shared/pathSecurity.ts +16 -0
- package/lib/shared/registry/nodeTypes/ListNodeType.ts +1 -1
- package/lib/shared/responsiveScaling.test.ts +143 -0
- package/lib/shared/responsiveScaling.ts +253 -2
- package/lib/shared/themeDefaults.test.ts +3 -3
- package/lib/shared/themeDefaults.ts +3 -3
- package/lib/shared/types/cms.ts +28 -3
- package/lib/shared/types/index.ts +2 -0
- package/lib/shared/types/variables.ts +37 -0
- package/lib/shared/utilityClassConfig.ts +3 -0
- package/lib/shared/utilityClassMapper.test.ts +123 -0
- package/lib/shared/utilityClassMapper.ts +179 -8
- package/lib/shared/validation/schemas.ts +15 -1
- package/lib/shared/validation/validators.ts +26 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-47UNLQUU.js.map +0 -7
- package/dist/chunks/chunk-FED5MME6.js.map +0 -7
- package/dist/chunks/chunk-FGUZOYJX.js.map +0 -7
- package/dist/chunks/chunk-KITQJYZV.js.map +0 -7
- package/dist/chunks/chunk-UUA5LEWF.js.map +0 -7
- package/dist/chunks/chunk-XSWR3QLI.js.map +0 -7
- /package/dist/chunks/{chunk-IF3RATBY.js.map → chunk-H4JSCDNW.js.map} +0 -0
- /package/dist/chunks/{chunk-LJFB5EBT.js.map → chunk-JER5NQVM.js.map} +0 -0
- /package/dist/chunks/{chunk-BCLGRZ3U.js.map → chunk-LKAGAQ3M.js.map} +0 -0
- /package/dist/chunks/{configService-DYCUEURL.js.map → configService-CCA6AIDI.js.map} +0 -0
package/dist/lib/server/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "../../chunks/chunk-4OFZP5NQ.js";
|
|
4
4
|
import {
|
|
5
5
|
buildStaticPages
|
|
6
|
-
} from "../../chunks/chunk-
|
|
6
|
+
} from "../../chunks/chunk-JER5NQVM.js";
|
|
7
7
|
import {
|
|
8
8
|
ComponentService,
|
|
9
9
|
EnumService,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
logResponseTime,
|
|
33
33
|
withErrorHandling,
|
|
34
34
|
withLogging
|
|
35
|
-
} from "../../chunks/chunk-
|
|
35
|
+
} from "../../chunks/chunk-CHD5UCFF.js";
|
|
36
36
|
import {
|
|
37
37
|
CMSService,
|
|
38
38
|
ColorService,
|
|
@@ -62,13 +62,13 @@ import {
|
|
|
62
62
|
generateThemeColorVariablesCSS,
|
|
63
63
|
generateVariablesCSS,
|
|
64
64
|
getJSValidationErrors,
|
|
65
|
+
getLocaleLinks,
|
|
65
66
|
loadBreakpointConfig,
|
|
66
67
|
loadComponentDirectory,
|
|
67
68
|
loadI18nConfig,
|
|
68
69
|
loadIconsConfig,
|
|
69
70
|
loadJSONFile,
|
|
70
71
|
loadProjectConfig,
|
|
71
|
-
loadResponsiveScalesConfig,
|
|
72
72
|
mapPageNameToPath,
|
|
73
73
|
menoFilterScript,
|
|
74
74
|
mergeLibraries,
|
|
@@ -83,11 +83,11 @@ import {
|
|
|
83
83
|
styleToString,
|
|
84
84
|
translatePath,
|
|
85
85
|
variableService
|
|
86
|
-
} from "../../chunks/chunk-
|
|
86
|
+
} from "../../chunks/chunk-EQYDSPBB.js";
|
|
87
87
|
import {
|
|
88
88
|
ConfigService,
|
|
89
89
|
configService
|
|
90
|
-
} from "../../chunks/chunk-
|
|
90
|
+
} from "../../chunks/chunk-KPU2XHOS.js";
|
|
91
91
|
import {
|
|
92
92
|
bundleFile,
|
|
93
93
|
createRuntimeServer,
|
|
@@ -116,19 +116,35 @@ import {
|
|
|
116
116
|
spawnProcess,
|
|
117
117
|
writeFile
|
|
118
118
|
} from "../../chunks/chunk-WQFG7PAH.js";
|
|
119
|
-
import "../../chunks/chunk-
|
|
120
|
-
import "../../chunks/chunk-KITQJYZV.js";
|
|
121
|
-
import "../../chunks/chunk-BCLGRZ3U.js";
|
|
119
|
+
import "../../chunks/chunk-H4JSCDNW.js";
|
|
122
120
|
import {
|
|
121
|
+
resolvePaletteColor
|
|
122
|
+
} from "../../chunks/chunk-J23ZX5AP.js";
|
|
123
|
+
import {
|
|
124
|
+
hasTemplates,
|
|
125
|
+
isHtmlMapping,
|
|
126
|
+
processCodeTemplates,
|
|
127
|
+
resolveHtmlMapping
|
|
128
|
+
} from "../../chunks/chunk-LKAGAQ3M.js";
|
|
129
|
+
import {
|
|
130
|
+
addItemUrl,
|
|
131
|
+
buildTemplateContext,
|
|
123
132
|
extractInteractiveStyleMappings,
|
|
124
133
|
generateAllInteractiveCSS,
|
|
125
134
|
generateElementClassName,
|
|
135
|
+
generateInteractiveCSS,
|
|
136
|
+
getNestedValue,
|
|
126
137
|
hasIf,
|
|
127
138
|
hasInteractiveStyleMappings,
|
|
139
|
+
isBooleanMapping,
|
|
140
|
+
isCssNamedColor,
|
|
128
141
|
isItemDraftForLocale,
|
|
129
142
|
isVoidElement,
|
|
143
|
+
resolveItemsTemplate,
|
|
144
|
+
resolvePropsFromDefinition,
|
|
145
|
+
shortHash,
|
|
130
146
|
singularize
|
|
131
|
-
} from "../../chunks/chunk-
|
|
147
|
+
} from "../../chunks/chunk-S2CX6HFM.js";
|
|
132
148
|
import {
|
|
133
149
|
DEFAULT_BREAKPOINTS,
|
|
134
150
|
DEFAULT_I18N_CONFIG,
|
|
@@ -136,8 +152,9 @@ import {
|
|
|
136
152
|
getScaleMultiplier,
|
|
137
153
|
isI18nValue,
|
|
138
154
|
resolveI18nValue,
|
|
155
|
+
resolveVariableValueAtBreakpoint,
|
|
139
156
|
scalePropertyValue
|
|
140
|
-
} from "../../chunks/chunk-
|
|
157
|
+
} from "../../chunks/chunk-AZQYF6KE.js";
|
|
141
158
|
import "../../chunks/chunk-UB44F4Z2.js";
|
|
142
159
|
import {
|
|
143
160
|
HMR_ROUTE,
|
|
@@ -798,7 +815,7 @@ function emitAttrValue(key, value, ctx) {
|
|
|
798
815
|
}
|
|
799
816
|
return `${key}="${escapeJSX(value)}"`;
|
|
800
817
|
}
|
|
801
|
-
function
|
|
818
|
+
function isHtmlMapping2(value) {
|
|
802
819
|
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
803
820
|
}
|
|
804
821
|
function isResponsiveStyle2(style) {
|
|
@@ -968,7 +985,7 @@ function resolveTemplate(text, ctx) {
|
|
|
968
985
|
return `{${trimmed}}`;
|
|
969
986
|
});
|
|
970
987
|
}
|
|
971
|
-
function
|
|
988
|
+
function hasTemplates2(text) {
|
|
972
989
|
return /\{\{.+?\}\}/.test(text);
|
|
973
990
|
}
|
|
974
991
|
function buildElementClass(ctx, label) {
|
|
@@ -987,7 +1004,7 @@ function buildAttributesString(attributes, ctx) {
|
|
|
987
1004
|
if (value) parts.push(key);
|
|
988
1005
|
} else {
|
|
989
1006
|
const strVal = String(value);
|
|
990
|
-
if (
|
|
1007
|
+
if (hasTemplates2(strVal) && ctx.isComponentDef) {
|
|
991
1008
|
const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
|
|
992
1009
|
if (fullMatch) {
|
|
993
1010
|
let expr = fullMatch[1].trim();
|
|
@@ -1009,7 +1026,7 @@ function buildAttributesString(attributes, ctx) {
|
|
|
1009
1026
|
});
|
|
1010
1027
|
parts.push(`${key}={\`${resolved}\`}`);
|
|
1011
1028
|
}
|
|
1012
|
-
} else if (ctx.listItemBinding &&
|
|
1029
|
+
} else if (ctx.listItemBinding && hasTemplates2(strVal)) {
|
|
1013
1030
|
const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
|
|
1014
1031
|
if (fullMatch) {
|
|
1015
1032
|
let expr = fullMatch[1].trim();
|
|
@@ -1084,7 +1101,7 @@ function nodeToAstro(node, ctx) {
|
|
|
1084
1101
|
return `${ind(ctx)}${transformed}
|
|
1085
1102
|
`;
|
|
1086
1103
|
}
|
|
1087
|
-
if (
|
|
1104
|
+
if (hasTemplates2(node) && ctx.isComponentDef) {
|
|
1088
1105
|
return `${ind(ctx)}${resolveTemplate(node, ctx)}
|
|
1089
1106
|
`;
|
|
1090
1107
|
}
|
|
@@ -1225,7 +1242,7 @@ function imageImportPath(srcPath, fileDepth) {
|
|
|
1225
1242
|
function isStaticImageSrc(src, ctx) {
|
|
1226
1243
|
if (!src) return false;
|
|
1227
1244
|
if (typeof src !== "string") return false;
|
|
1228
|
-
if (
|
|
1245
|
+
if (hasTemplates2(src)) return false;
|
|
1229
1246
|
if (!src.startsWith("/images/")) return false;
|
|
1230
1247
|
if (!ctx.imageMetadataMap?.has(src)) return false;
|
|
1231
1248
|
return true;
|
|
@@ -1420,7 +1437,7 @@ function emitHtmlNode(node, ctx) {
|
|
|
1420
1437
|
const style = node.style;
|
|
1421
1438
|
let isDynamic = false;
|
|
1422
1439
|
let dynamicTagVar = "";
|
|
1423
|
-
if (
|
|
1440
|
+
if (hasTemplates2(tag) && ctx.isComponentDef) {
|
|
1424
1441
|
isDynamic = true;
|
|
1425
1442
|
dynamicTagVar = `Tag_${ctx.elementPath.join("_")}`;
|
|
1426
1443
|
const resolved = tag.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
@@ -1461,7 +1478,7 @@ function emitComponentInstance(node, ctx) {
|
|
|
1461
1478
|
for (const [key, rawValue] of Object.entries(node.props)) {
|
|
1462
1479
|
if (key === "children") continue;
|
|
1463
1480
|
const value = resolveI18n(rawValue, ctx);
|
|
1464
|
-
if (typeof value === "string" &&
|
|
1481
|
+
if (typeof value === "string" && hasTemplates2(value) && ctx.isComponentDef) {
|
|
1465
1482
|
const fullMatch = value.match(/^\{\{(.+)\}\}$/);
|
|
1466
1483
|
if (fullMatch) {
|
|
1467
1484
|
let expr = fullMatch[1].trim();
|
|
@@ -1544,7 +1561,7 @@ function emitEmbedNode(node, ctx) {
|
|
|
1544
1561
|
}
|
|
1545
1562
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1546
1563
|
const attrs = buildAttributesString(node.attributes, ctx);
|
|
1547
|
-
if (
|
|
1564
|
+
if (isHtmlMapping2(node.html)) {
|
|
1548
1565
|
if (ctx.isComponentDef) {
|
|
1549
1566
|
const propRef = node.html.prop;
|
|
1550
1567
|
return `${ifExpr}${ind(ctx)}<div${classExpr.replace('"', '"oem ') || ' class="oem"'}${attrs}>
|
|
@@ -1553,7 +1570,7 @@ ${ind(ctx)}</div>
|
|
|
1553
1570
|
${emitIfClose(node, ctx)}`;
|
|
1554
1571
|
}
|
|
1555
1572
|
}
|
|
1556
|
-
if (typeof node.html === "string" &&
|
|
1573
|
+
if (typeof node.html === "string" && hasTemplates2(node.html) && ctx.isComponentDef) {
|
|
1557
1574
|
const fullMatch = node.html.match(/^\{\{(.+)\}\}$/);
|
|
1558
1575
|
if (fullMatch) {
|
|
1559
1576
|
let propRef = fullMatch[1].trim();
|
|
@@ -1619,7 +1636,7 @@ function emitLinkNode(node, ctx) {
|
|
|
1619
1636
|
}
|
|
1620
1637
|
} else {
|
|
1621
1638
|
const href = typeof nodeHref === "string" ? nodeHref : "#";
|
|
1622
|
-
if (
|
|
1639
|
+
if (hasTemplates2(href) && ctx.isComponentDef) {
|
|
1623
1640
|
const fullMatch = href.match(/^\{\{(.+)\}\}$/);
|
|
1624
1641
|
if (fullMatch) {
|
|
1625
1642
|
let expr = fullMatch[1].trim();
|
|
@@ -2935,8 +2952,8 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2935
2952
|
const themeConfig = await colorService.loadThemeConfig();
|
|
2936
2953
|
const variablesConfig = await variableService.loadConfig();
|
|
2937
2954
|
const breakpoints = await loadBreakpointConfig();
|
|
2938
|
-
const responsiveScales = await loadResponsiveScalesConfig();
|
|
2939
2955
|
await configService.load();
|
|
2956
|
+
const responsiveScales = configService.getResponsiveScales();
|
|
2940
2957
|
const globalLibraries = configService.getLibraries();
|
|
2941
2958
|
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
2942
2959
|
const imageMetadataMap = await buildImageMetadataMap();
|
|
@@ -3498,38 +3515,19 @@ export default defineConfig({${siteUrl ? `
|
|
|
3498
3515
|
|
|
3499
3516
|
// lib/server/webflow/buildWebflow.ts
|
|
3500
3517
|
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
3501
|
-
import { join as
|
|
3502
|
-
|
|
3503
|
-
// lib/server/webflow/types.ts
|
|
3504
|
-
function mapCMSFieldType(menoType) {
|
|
3505
|
-
switch (menoType) {
|
|
3506
|
-
case "string":
|
|
3507
|
-
return "PlainText";
|
|
3508
|
-
case "text":
|
|
3509
|
-
case "rich-text":
|
|
3510
|
-
return "RichText";
|
|
3511
|
-
case "number":
|
|
3512
|
-
return "Number";
|
|
3513
|
-
case "boolean":
|
|
3514
|
-
return "Switch";
|
|
3515
|
-
case "image":
|
|
3516
|
-
return "Image";
|
|
3517
|
-
case "date":
|
|
3518
|
-
return "Date";
|
|
3519
|
-
case "select":
|
|
3520
|
-
return "Option";
|
|
3521
|
-
case "file":
|
|
3522
|
-
return "File";
|
|
3523
|
-
case "reference":
|
|
3524
|
-
return "Reference";
|
|
3525
|
-
default:
|
|
3526
|
-
return "PlainText";
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3518
|
+
import { join as join3 } from "path";
|
|
3519
|
+
init_constants();
|
|
3529
3520
|
|
|
3530
3521
|
// lib/server/webflow/nodeToWebflow.ts
|
|
3531
3522
|
init_constants();
|
|
3532
3523
|
|
|
3524
|
+
// lib/server/webflow/types.ts
|
|
3525
|
+
var MENO_BIND_SENTINEL_PREFIX = "__MENO_BIND__:";
|
|
3526
|
+
var MENO_BIND_SENTINEL_SUFFIX = ":__";
|
|
3527
|
+
var MENO_BIND_SENTINEL_RE = /__MENO_BIND__:([^:]+):__/g;
|
|
3528
|
+
var MENO_BIND_SENTINEL_EXACT_RE = /^__MENO_BIND__:([^:]+):__$/;
|
|
3529
|
+
var COLLECTION_LIST_TAG = "__collection_list__";
|
|
3530
|
+
|
|
3533
3531
|
// lib/server/webflow/styleMapper.ts
|
|
3534
3532
|
var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
|
|
3535
3533
|
"opacity",
|
|
@@ -3544,6 +3542,28 @@ var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
3544
3542
|
"font-weight",
|
|
3545
3543
|
"tab-size"
|
|
3546
3544
|
]);
|
|
3545
|
+
var TIME_PROPERTIES = /* @__PURE__ */ new Set([
|
|
3546
|
+
"transition-duration",
|
|
3547
|
+
"transition-delay",
|
|
3548
|
+
"animation-duration",
|
|
3549
|
+
"animation-delay"
|
|
3550
|
+
]);
|
|
3551
|
+
function normalizeZero(cssProp, cssValue) {
|
|
3552
|
+
if (cssValue !== "0") return cssValue;
|
|
3553
|
+
if (UNITLESS_PROPERTIES.has(cssProp)) return cssValue;
|
|
3554
|
+
if (TIME_PROPERTIES.has(cssProp)) return cssValue;
|
|
3555
|
+
return "0px";
|
|
3556
|
+
}
|
|
3557
|
+
var COLOR_PROPS_CAMEL = /* @__PURE__ */ new Set(["color", "backgroundColor", "borderColor"]);
|
|
3558
|
+
function maybeWrapColorVar(camelProp, value) {
|
|
3559
|
+
if (!COLOR_PROPS_CAMEL.has(camelProp)) return value;
|
|
3560
|
+
if (!value) return value;
|
|
3561
|
+
if (value.startsWith("#")) return value;
|
|
3562
|
+
if (value.startsWith("var(")) return value;
|
|
3563
|
+
if (value.includes("(")) return value;
|
|
3564
|
+
if (isCssNamedColor(value)) return value;
|
|
3565
|
+
return `var(--${value})`;
|
|
3566
|
+
}
|
|
3547
3567
|
function isStyleMapping4(value) {
|
|
3548
3568
|
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
3549
3569
|
}
|
|
@@ -3553,6 +3573,65 @@ function isResponsiveStyle4(style) {
|
|
|
3553
3573
|
function toKebabCase(prop) {
|
|
3554
3574
|
return prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
3555
3575
|
}
|
|
3576
|
+
function splitTopLevel(value) {
|
|
3577
|
+
const out = [];
|
|
3578
|
+
let depth = 0;
|
|
3579
|
+
let buf = "";
|
|
3580
|
+
for (const ch of value.trim()) {
|
|
3581
|
+
if (ch === "(") depth++;
|
|
3582
|
+
else if (ch === ")") depth--;
|
|
3583
|
+
if (depth === 0 && /\s/.test(ch)) {
|
|
3584
|
+
if (buf) {
|
|
3585
|
+
out.push(buf);
|
|
3586
|
+
buf = "";
|
|
3587
|
+
}
|
|
3588
|
+
continue;
|
|
3589
|
+
}
|
|
3590
|
+
buf += ch;
|
|
3591
|
+
}
|
|
3592
|
+
if (buf) out.push(buf);
|
|
3593
|
+
return out;
|
|
3594
|
+
}
|
|
3595
|
+
function expandShorthand(cssProp, cssValue) {
|
|
3596
|
+
if (cssProp !== "margin" && cssProp !== "padding" && cssProp !== "gap") {
|
|
3597
|
+
return null;
|
|
3598
|
+
}
|
|
3599
|
+
const parts = splitTopLevel(cssValue);
|
|
3600
|
+
if (cssProp === "gap") {
|
|
3601
|
+
if (parts.length === 1) {
|
|
3602
|
+
const v = normalizeZero("row-gap", parts[0]);
|
|
3603
|
+
return { "row-gap": v, "column-gap": v };
|
|
3604
|
+
}
|
|
3605
|
+
if (parts.length === 2) {
|
|
3606
|
+
return {
|
|
3607
|
+
"row-gap": normalizeZero("row-gap", parts[0]),
|
|
3608
|
+
"column-gap": normalizeZero("column-gap", parts[1])
|
|
3609
|
+
};
|
|
3610
|
+
}
|
|
3611
|
+
return null;
|
|
3612
|
+
}
|
|
3613
|
+
let top, right, bottom, left;
|
|
3614
|
+
if (parts.length === 1) {
|
|
3615
|
+
top = right = bottom = left = parts[0];
|
|
3616
|
+
} else if (parts.length === 2) {
|
|
3617
|
+
top = bottom = parts[0];
|
|
3618
|
+
right = left = parts[1];
|
|
3619
|
+
} else if (parts.length === 3) {
|
|
3620
|
+
top = parts[0];
|
|
3621
|
+
right = left = parts[1];
|
|
3622
|
+
bottom = parts[2];
|
|
3623
|
+
} else if (parts.length === 4) {
|
|
3624
|
+
[top, right, bottom, left] = parts;
|
|
3625
|
+
} else {
|
|
3626
|
+
return null;
|
|
3627
|
+
}
|
|
3628
|
+
return {
|
|
3629
|
+
[`${cssProp}-top`]: normalizeZero(`${cssProp}-top`, top),
|
|
3630
|
+
[`${cssProp}-right`]: normalizeZero(`${cssProp}-right`, right),
|
|
3631
|
+
[`${cssProp}-bottom`]: normalizeZero(`${cssProp}-bottom`, bottom),
|
|
3632
|
+
[`${cssProp}-left`]: normalizeZero(`${cssProp}-left`, left)
|
|
3633
|
+
};
|
|
3634
|
+
}
|
|
3556
3635
|
function styleObjectToCSS(style) {
|
|
3557
3636
|
const css = {};
|
|
3558
3637
|
for (const [prop, value] of Object.entries(style)) {
|
|
@@ -3560,11 +3639,18 @@ function styleObjectToCSS(style) {
|
|
|
3560
3639
|
if (value === "" || value === void 0 || value === null) continue;
|
|
3561
3640
|
if (typeof value === "boolean" || typeof value === "object") continue;
|
|
3562
3641
|
const cssProp = toKebabCase(prop);
|
|
3642
|
+
let cssValue;
|
|
3563
3643
|
if (typeof value === "number") {
|
|
3564
3644
|
if (isNaN(value)) continue;
|
|
3565
|
-
|
|
3645
|
+
cssValue = UNITLESS_PROPERTIES.has(cssProp) ? String(value) : `${value}px`;
|
|
3646
|
+
} else {
|
|
3647
|
+
cssValue = maybeWrapColorVar(prop, String(value));
|
|
3648
|
+
}
|
|
3649
|
+
const expanded = expandShorthand(cssProp, cssValue);
|
|
3650
|
+
if (expanded) {
|
|
3651
|
+
Object.assign(css, expanded);
|
|
3566
3652
|
} else {
|
|
3567
|
-
css[cssProp] =
|
|
3653
|
+
css[cssProp] = normalizeZero(cssProp, cssValue);
|
|
3568
3654
|
}
|
|
3569
3655
|
}
|
|
3570
3656
|
return css;
|
|
@@ -3591,14 +3677,85 @@ function collectStyleMappings2(style) {
|
|
|
3591
3677
|
return result;
|
|
3592
3678
|
}
|
|
3593
3679
|
function postfixToPseudoState(postfix) {
|
|
3594
|
-
if (postfix.includes(":hover")) return "hover";
|
|
3595
3680
|
if (postfix.includes(":focus-visible")) return "focus-visible";
|
|
3681
|
+
if (postfix.includes(":focus-within")) return "focus-within";
|
|
3682
|
+
if (postfix.includes(":nth-child(odd)")) return "nth-child(odd)";
|
|
3683
|
+
if (postfix.includes(":nth-child(even)")) return "nth-child(even)";
|
|
3684
|
+
if (postfix.includes(":first-child")) return "first-child";
|
|
3685
|
+
if (postfix.includes(":last-child")) return "last-child";
|
|
3686
|
+
if (postfix.includes(":placeholder")) return "placeholder";
|
|
3687
|
+
if (postfix.includes(":empty")) return "empty";
|
|
3688
|
+
if (postfix.includes(":before")) return "before";
|
|
3689
|
+
if (postfix.includes(":after")) return "after";
|
|
3690
|
+
if (postfix.includes(":hover")) return "hover";
|
|
3596
3691
|
if (postfix.includes(":focus")) return "focus";
|
|
3597
3692
|
if (postfix.includes(":active")) return "active";
|
|
3598
3693
|
if (postfix.includes(":visited")) return "visited";
|
|
3694
|
+
if (postfix.includes(":pressed")) return "pressed";
|
|
3695
|
+
if (postfix.includes("::before")) return "before";
|
|
3696
|
+
if (postfix.includes("::after")) return "after";
|
|
3697
|
+
if (postfix.includes("::placeholder")) return "placeholder";
|
|
3599
3698
|
return null;
|
|
3600
3699
|
}
|
|
3601
|
-
function
|
|
3700
|
+
function isWebflowHandledRule(rule) {
|
|
3701
|
+
if (rule.prefix && rule.prefix.trim().length > 0) return false;
|
|
3702
|
+
if (!rule.postfix) return false;
|
|
3703
|
+
if (postfixToPseudoState(rule.postfix) === null) return false;
|
|
3704
|
+
const s = rule.style;
|
|
3705
|
+
if (!s || typeof s !== "object") return false;
|
|
3706
|
+
const responsiveKeys = Object.keys(s).filter((k) => k !== "base");
|
|
3707
|
+
return responsiveKeys.length === 0;
|
|
3708
|
+
}
|
|
3709
|
+
function widthToWebflowBreakpoint(maxWidthPx) {
|
|
3710
|
+
if (maxWidthPx < 480) return "tiny";
|
|
3711
|
+
if (maxWidthPx < 768) return "small";
|
|
3712
|
+
if (maxWidthPx < 992) return "medium";
|
|
3713
|
+
if (maxWidthPx < 1280) return "main";
|
|
3714
|
+
if (maxWidthPx < 1440) return "large";
|
|
3715
|
+
if (maxWidthPx < 1920) return "xl";
|
|
3716
|
+
return "xxl";
|
|
3717
|
+
}
|
|
3718
|
+
function menoBreakpointToWebflow(bpName, breakpoints) {
|
|
3719
|
+
if (bpName === "tablet") return "medium";
|
|
3720
|
+
if (bpName === "mobile") return "small";
|
|
3721
|
+
const entry = breakpoints[bpName];
|
|
3722
|
+
if (entry && typeof entry.breakpoint === "number") {
|
|
3723
|
+
return widthToWebflowBreakpoint(entry.breakpoint);
|
|
3724
|
+
}
|
|
3725
|
+
return "main";
|
|
3726
|
+
}
|
|
3727
|
+
function mergeIntoBreakpoint(cls, tier, css) {
|
|
3728
|
+
if (!cls.breakpoints) cls.breakpoints = {};
|
|
3729
|
+
cls.breakpoints[tier] = { ...cls.breakpoints[tier], ...css };
|
|
3730
|
+
}
|
|
3731
|
+
function kebabToCamel(s) {
|
|
3732
|
+
return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
3733
|
+
}
|
|
3734
|
+
function applyAutoScaling(cls, breakpoints, responsiveScales) {
|
|
3735
|
+
if (!responsiveScales?.enabled) return;
|
|
3736
|
+
const baseRef = responsiveScales.baseReference || 16;
|
|
3737
|
+
for (const [prop, baseValue] of Object.entries(cls.base)) {
|
|
3738
|
+
if (!baseValue || baseValue.includes("var(--")) continue;
|
|
3739
|
+
const camelProp = kebabToCamel(prop);
|
|
3740
|
+
for (const [bpName, bpEntry] of Object.entries(breakpoints)) {
|
|
3741
|
+
if (!bpEntry) continue;
|
|
3742
|
+
const scale = getScaleMultiplier(responsiveScales, camelProp, bpName);
|
|
3743
|
+
if (scale === null) continue;
|
|
3744
|
+
const scaled = scalePropertyValue(baseValue, baseRef, scale);
|
|
3745
|
+
if (scaled === null || scaled === baseValue) continue;
|
|
3746
|
+
const tier = menoBreakpointToWebflow(bpName, breakpoints);
|
|
3747
|
+
if (!cls.breakpoints) cls.breakpoints = {};
|
|
3748
|
+
const bucket = cls.breakpoints[tier] || {};
|
|
3749
|
+
if (bucket[prop] !== void 0) continue;
|
|
3750
|
+
bucket[prop] = scaled;
|
|
3751
|
+
cls.breakpoints[tier] = bucket;
|
|
3752
|
+
}
|
|
3753
|
+
}
|
|
3754
|
+
}
|
|
3755
|
+
function mapStylesToWebflow(className, style, interactiveStyles, breakpoints, responsiveScales, options) {
|
|
3756
|
+
const instanceProps = options?.instanceProps;
|
|
3757
|
+
const componentDefaults = options?.componentDefaults;
|
|
3758
|
+
const themeSuffix = options?.themeSuffix ?? "";
|
|
3602
3759
|
const webflowClassName = className.replace(/_/g, "-");
|
|
3603
3760
|
const primaryClass = {
|
|
3604
3761
|
name: webflowClassName,
|
|
@@ -3610,21 +3767,12 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
|
|
|
3610
3767
|
if (responsive.base) {
|
|
3611
3768
|
primaryClass.base = styleObjectToCSS(responsive.base);
|
|
3612
3769
|
}
|
|
3613
|
-
if (responsive.tablet) {
|
|
3614
|
-
if (!primaryClass.breakpoints) primaryClass.breakpoints = {};
|
|
3615
|
-
primaryClass.breakpoints.Tablet = styleObjectToCSS(responsive.tablet);
|
|
3616
|
-
}
|
|
3617
|
-
if (responsive.mobile) {
|
|
3618
|
-
if (!primaryClass.breakpoints) primaryClass.breakpoints = {};
|
|
3619
|
-
primaryClass.breakpoints.MobilePortrait = styleObjectToCSS(responsive.mobile);
|
|
3620
|
-
}
|
|
3621
3770
|
for (const [bpName, bpStyle] of Object.entries(responsive)) {
|
|
3622
|
-
if (!bpStyle || bpName === "base"
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
};
|
|
3771
|
+
if (!bpStyle || bpName === "base") continue;
|
|
3772
|
+
const css = styleObjectToCSS(bpStyle);
|
|
3773
|
+
if (Object.keys(css).length === 0) continue;
|
|
3774
|
+
const tier = menoBreakpointToWebflow(bpName, breakpoints);
|
|
3775
|
+
mergeIntoBreakpoint(primaryClass, tier, css);
|
|
3628
3776
|
}
|
|
3629
3777
|
} else {
|
|
3630
3778
|
primaryClass.base = styleObjectToCSS(style);
|
|
@@ -3632,92 +3780,546 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
|
|
|
3632
3780
|
}
|
|
3633
3781
|
if (interactiveStyles && interactiveStyles.length > 0) {
|
|
3634
3782
|
for (const rule of interactiveStyles) {
|
|
3635
|
-
if (!rule
|
|
3783
|
+
if (!isWebflowHandledRule(rule)) continue;
|
|
3784
|
+
const baseProps = isResponsiveStyle4(rule.style) ? styleObjectToCSS(rule.style.base || {}) : styleObjectToCSS(rule.style);
|
|
3785
|
+
if (Object.keys(baseProps).length === 0) continue;
|
|
3636
3786
|
const pseudoState = postfixToPseudoState(rule.postfix);
|
|
3637
3787
|
if (!pseudoState) continue;
|
|
3638
|
-
const ruleStyle = rule.style;
|
|
3639
3788
|
if (!primaryClass.pseudoStates) primaryClass.pseudoStates = {};
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
...primaryClass.pseudoStates[pseudoState],
|
|
3645
|
-
...styleObjectToCSS(responsive.base)
|
|
3646
|
-
};
|
|
3647
|
-
}
|
|
3648
|
-
} else {
|
|
3649
|
-
primaryClass.pseudoStates[pseudoState] = {
|
|
3650
|
-
...primaryClass.pseudoStates[pseudoState],
|
|
3651
|
-
...styleObjectToCSS(ruleStyle)
|
|
3652
|
-
};
|
|
3653
|
-
}
|
|
3789
|
+
primaryClass.pseudoStates[pseudoState] = {
|
|
3790
|
+
...primaryClass.pseudoStates[pseudoState],
|
|
3791
|
+
...baseProps
|
|
3792
|
+
};
|
|
3654
3793
|
}
|
|
3655
3794
|
}
|
|
3656
3795
|
const comboClasses = [];
|
|
3657
3796
|
const mappings = collectStyleMappings2(style);
|
|
3797
|
+
const comboCss = {};
|
|
3798
|
+
const comboNameParts = [];
|
|
3658
3799
|
for (const { property, mapping } of mappings) {
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
const
|
|
3663
|
-
|
|
3664
|
-
base
|
|
3665
|
-
|
|
3666
|
-
},
|
|
3667
|
-
comboParent: webflowClassName
|
|
3668
|
-
};
|
|
3669
|
-
comboClasses.push(comboClass);
|
|
3800
|
+
const defaultValue = componentDefaults?.[mapping.prop];
|
|
3801
|
+
const defaultKey = defaultValue != null ? String(defaultValue) : void 0;
|
|
3802
|
+
if (defaultKey !== void 0 && defaultKey in mapping.values) {
|
|
3803
|
+
const defaultCss = mappingValueToCSS(property, mapping.values[defaultKey]);
|
|
3804
|
+
if (defaultCss) {
|
|
3805
|
+
primaryClass.base = { ...primaryClass.base, ...defaultCss };
|
|
3806
|
+
}
|
|
3670
3807
|
}
|
|
3808
|
+
if (!instanceProps) continue;
|
|
3809
|
+
const instanceValue = instanceProps[mapping.prop];
|
|
3810
|
+
if (instanceValue == null) continue;
|
|
3811
|
+
const instanceKey = String(instanceValue);
|
|
3812
|
+
if (instanceKey === defaultKey) continue;
|
|
3813
|
+
if (!(instanceKey in mapping.values)) continue;
|
|
3814
|
+
const css = mappingValueToCSS(property, mapping.values[instanceKey]);
|
|
3815
|
+
if (!css) continue;
|
|
3816
|
+
Object.assign(comboCss, css);
|
|
3817
|
+
const part = `${sanitizeClassName(mapping.prop)}-${sanitizeClassName(instanceKey)}`;
|
|
3818
|
+
if (!comboNameParts.includes(part)) comboNameParts.push(part);
|
|
3819
|
+
}
|
|
3820
|
+
if (comboNameParts.length > 0 && Object.keys(comboCss).length > 0) {
|
|
3821
|
+
comboNameParts.sort();
|
|
3822
|
+
comboClasses.push({
|
|
3823
|
+
name: `is-${comboNameParts.join("-")}${themeSuffix}`,
|
|
3824
|
+
base: comboCss,
|
|
3825
|
+
comboParent: webflowClassName
|
|
3826
|
+
});
|
|
3827
|
+
}
|
|
3828
|
+
applyAutoScaling(primaryClass, breakpoints, responsiveScales);
|
|
3829
|
+
for (const combo of comboClasses) {
|
|
3830
|
+
applyAutoScaling(combo, breakpoints, responsiveScales);
|
|
3671
3831
|
}
|
|
3672
3832
|
return { primaryClass, comboClasses };
|
|
3673
3833
|
}
|
|
3834
|
+
function mappingValueToCSS(property, rawValue) {
|
|
3835
|
+
if (rawValue === "" || rawValue === void 0 || rawValue === null) return null;
|
|
3836
|
+
const cssProp = toKebabCase(property);
|
|
3837
|
+
const cssValueStr = typeof rawValue === "number" ? UNITLESS_PROPERTIES.has(cssProp) ? String(rawValue) : `${rawValue}px` : maybeWrapColorVar(property, String(rawValue));
|
|
3838
|
+
return expandShorthand(cssProp, cssValueStr) ?? { [cssProp]: normalizeZero(cssProp, cssValueStr) };
|
|
3839
|
+
}
|
|
3674
3840
|
function sanitizeClassName(name) {
|
|
3675
3841
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
3676
3842
|
}
|
|
3843
|
+
function buildInstanceStyleCombo(comboName, rootClassName, style, interactiveStyles, breakpoints, responsiveScales) {
|
|
3844
|
+
const base = {};
|
|
3845
|
+
const bps = {};
|
|
3846
|
+
const pseudos = {};
|
|
3847
|
+
if (style) {
|
|
3848
|
+
if (isResponsiveStyle4(style)) {
|
|
3849
|
+
const responsive = style;
|
|
3850
|
+
if (responsive.base) Object.assign(base, styleObjectToCSS(responsive.base));
|
|
3851
|
+
for (const [bpName, bpStyle] of Object.entries(responsive)) {
|
|
3852
|
+
if (!bpStyle || bpName === "base") continue;
|
|
3853
|
+
const css = styleObjectToCSS(bpStyle);
|
|
3854
|
+
if (Object.keys(css).length === 0) continue;
|
|
3855
|
+
const tier = menoBreakpointToWebflow(bpName, breakpoints);
|
|
3856
|
+
bps[tier] = { ...bps[tier], ...css };
|
|
3857
|
+
}
|
|
3858
|
+
} else {
|
|
3859
|
+
Object.assign(base, styleObjectToCSS(style));
|
|
3860
|
+
}
|
|
3861
|
+
}
|
|
3862
|
+
if (interactiveStyles && interactiveStyles.length > 0) {
|
|
3863
|
+
for (const rule of interactiveStyles) {
|
|
3864
|
+
if (!isWebflowHandledRule(rule)) continue;
|
|
3865
|
+
const ruleStyle = rule.style;
|
|
3866
|
+
const flat = isResponsiveStyle4(ruleStyle) ? ruleStyle.base : ruleStyle;
|
|
3867
|
+
if (!flat) continue;
|
|
3868
|
+
const css = styleObjectToCSS(flat);
|
|
3869
|
+
if (Object.keys(css).length === 0) continue;
|
|
3870
|
+
const pseudo = postfixToPseudoState(rule.postfix);
|
|
3871
|
+
if (!pseudo) continue;
|
|
3872
|
+
pseudos[pseudo] = { ...pseudos[pseudo], ...css };
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
if (Object.keys(base).length === 0 && Object.keys(bps).length === 0 && Object.keys(pseudos).length === 0) return null;
|
|
3876
|
+
const cls = {
|
|
3877
|
+
name: comboName,
|
|
3878
|
+
base,
|
|
3879
|
+
comboParent: rootClassName
|
|
3880
|
+
};
|
|
3881
|
+
if (Object.keys(bps).length > 0) cls.breakpoints = bps;
|
|
3882
|
+
if (Object.keys(pseudos).length > 0) cls.pseudoStates = pseudos;
|
|
3883
|
+
applyAutoScaling(cls, breakpoints, responsiveScales);
|
|
3884
|
+
return cls;
|
|
3885
|
+
}
|
|
3677
3886
|
|
|
3678
3887
|
// lib/server/webflow/nodeToWebflow.ts
|
|
3888
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
3889
|
+
import { join as join2, basename, extname } from "path";
|
|
3890
|
+
var PROMOTED_TO_WEBFLOW_COMPONENT = /* @__PURE__ */ new Set(["Navigation", "Footer"]);
|
|
3679
3891
|
function buildElementClass2(ctx, label) {
|
|
3680
|
-
|
|
3892
|
+
const generated = generateElementClassName({
|
|
3681
3893
|
fileType: ctx.fileType,
|
|
3682
3894
|
fileName: ctx.fileName,
|
|
3683
3895
|
label,
|
|
3684
3896
|
path: ctx.elementPath
|
|
3685
3897
|
});
|
|
3898
|
+
if (ctx.fileType !== "component") return generated;
|
|
3899
|
+
const stripped = generated.replace(/^c_/, "");
|
|
3900
|
+
return stripped.replace(/^([a-z0-9-]+)_\1$/, "$1");
|
|
3901
|
+
}
|
|
3902
|
+
function themedClassSuffix(ctx) {
|
|
3903
|
+
const t = ctx.currentTheme;
|
|
3904
|
+
if (!t) return "";
|
|
3905
|
+
if (ctx.defaultTheme && t === ctx.defaultTheme) return "";
|
|
3906
|
+
const safe = t.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
3907
|
+
if (!safe) return "";
|
|
3908
|
+
return `-theme-${safe}`;
|
|
3909
|
+
}
|
|
3910
|
+
function withThemeSuffix(name, ctx) {
|
|
3911
|
+
return name + themedClassSuffix(ctx);
|
|
3912
|
+
}
|
|
3913
|
+
function mintInstanceComboName(ctx, identity) {
|
|
3914
|
+
let attempt = 0;
|
|
3915
|
+
let name = `is-${shortHash(identity)}`;
|
|
3916
|
+
while (true) {
|
|
3917
|
+
const claimedBy = ctx.comboIdentityByName.get(name);
|
|
3918
|
+
if (!claimedBy || claimedBy === identity) {
|
|
3919
|
+
ctx.comboIdentityByName.set(name, identity);
|
|
3920
|
+
return name;
|
|
3921
|
+
}
|
|
3922
|
+
attempt++;
|
|
3923
|
+
name = `is-${shortHash(`${identity}#${attempt}`)}`;
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
function extractInterfaceDefaults(iface) {
|
|
3927
|
+
if (!iface) return void 0;
|
|
3928
|
+
const out = {};
|
|
3929
|
+
let any = false;
|
|
3930
|
+
for (const [key, def] of Object.entries(iface)) {
|
|
3931
|
+
if (def && "default" in def) {
|
|
3932
|
+
out[key] = def.default;
|
|
3933
|
+
any = true;
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
return any ? out : void 0;
|
|
3937
|
+
}
|
|
3938
|
+
function buildTemplateProps(ctx, instanceProps) {
|
|
3939
|
+
return {
|
|
3940
|
+
...ctx.templateContext ?? {},
|
|
3941
|
+
...ctx.cmsContext ?? {},
|
|
3942
|
+
...ctx.componentDefaults ?? {},
|
|
3943
|
+
...ctx.slotInstanceProps ?? {},
|
|
3944
|
+
...instanceProps ?? {}
|
|
3945
|
+
};
|
|
3686
3946
|
}
|
|
3687
|
-
function
|
|
3688
|
-
if (!
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3947
|
+
function resolveStringTemplate(text, ctx, instanceProps) {
|
|
3948
|
+
if (!hasTemplates(text)) return text;
|
|
3949
|
+
const out = processCodeTemplates(text, buildTemplateProps(ctx, instanceProps));
|
|
3950
|
+
return out.startsWith(RAW_HTML_PREFIX) ? flattenInlineHtmlToText(out.slice(RAW_HTML_PREFIX.length)) : out;
|
|
3951
|
+
}
|
|
3952
|
+
var HEADING_TAGS = /* @__PURE__ */ new Set(["h1", "h2", "h3", "h4", "h5", "h6"]);
|
|
3953
|
+
var LINK_LIKE_TAGS = /* @__PURE__ */ new Set(["button"]);
|
|
3954
|
+
var LIST_TAGS = /* @__PURE__ */ new Set(["ul", "ol"]);
|
|
3955
|
+
function applyHeadingMarginDefaults(cls) {
|
|
3956
|
+
const base = cls.base;
|
|
3957
|
+
if (!("margin-top" in base)) base["margin-top"] = "0px";
|
|
3958
|
+
if (!("margin-bottom" in base)) base["margin-bottom"] = "0px";
|
|
3959
|
+
}
|
|
3960
|
+
function applyParagraphMarginDefaults(cls) {
|
|
3961
|
+
const base = cls.base;
|
|
3962
|
+
if (!("margin-bottom" in base)) base["margin-bottom"] = "0px";
|
|
3963
|
+
}
|
|
3964
|
+
function applyListMarginDefaults(cls) {
|
|
3965
|
+
const base = cls.base;
|
|
3966
|
+
if (!("margin-bottom" in base)) base["margin-bottom"] = "0px";
|
|
3967
|
+
}
|
|
3968
|
+
function applyGridRowsDefault(cls) {
|
|
3969
|
+
const base = cls.base;
|
|
3970
|
+
const display = base["display"];
|
|
3971
|
+
if (display !== "grid" && display !== "inline-grid") return;
|
|
3972
|
+
if ("grid" in base) return;
|
|
3973
|
+
if ("grid-template" in base) return;
|
|
3974
|
+
if ("grid-template-rows" in base) return;
|
|
3975
|
+
base["grid-template-rows"] = "1fr";
|
|
3976
|
+
}
|
|
3977
|
+
function applyLinkTextDecorationDefault(cls) {
|
|
3978
|
+
const base = cls.base;
|
|
3979
|
+
if ("text-decoration" in base || "text-decoration-line" in base) return;
|
|
3980
|
+
base["text-decoration"] = "none";
|
|
3981
|
+
}
|
|
3982
|
+
function mergeComboClasses(inner, outer, parentName) {
|
|
3983
|
+
const innerSuffix = inner.name.startsWith("is-") ? inner.name.slice(3) : inner.name;
|
|
3984
|
+
const merged = {
|
|
3985
|
+
name: `${outer.name}_${innerSuffix}`,
|
|
3986
|
+
base: { ...inner.base, ...outer.base },
|
|
3987
|
+
comboParent: parentName
|
|
3988
|
+
};
|
|
3989
|
+
if (inner.breakpoints || outer.breakpoints) {
|
|
3990
|
+
const bps = {};
|
|
3991
|
+
const tiers = /* @__PURE__ */ new Set([
|
|
3992
|
+
...Object.keys(inner.breakpoints || {}),
|
|
3993
|
+
...Object.keys(outer.breakpoints || {})
|
|
3994
|
+
]);
|
|
3995
|
+
for (const tier of tiers) {
|
|
3996
|
+
bps[tier] = { ...inner.breakpoints?.[tier] || {}, ...outer.breakpoints?.[tier] || {} };
|
|
3997
|
+
}
|
|
3998
|
+
merged.breakpoints = bps;
|
|
3999
|
+
}
|
|
4000
|
+
if (inner.pseudoStates || outer.pseudoStates) {
|
|
4001
|
+
const ps = {};
|
|
4002
|
+
const states = /* @__PURE__ */ new Set([
|
|
4003
|
+
...Object.keys(inner.pseudoStates || {}),
|
|
4004
|
+
...Object.keys(outer.pseudoStates || {})
|
|
4005
|
+
]);
|
|
4006
|
+
for (const state of states) {
|
|
4007
|
+
ps[state] = { ...inner.pseudoStates?.[state] || {}, ...outer.pseudoStates?.[state] || {} };
|
|
4008
|
+
}
|
|
4009
|
+
merged.pseudoStates = ps;
|
|
4010
|
+
}
|
|
4011
|
+
return merged;
|
|
4012
|
+
}
|
|
4013
|
+
var IMAGE_EXT_MIME = {
|
|
4014
|
+
".png": "image/png",
|
|
4015
|
+
".jpg": "image/jpeg",
|
|
4016
|
+
".jpeg": "image/jpeg",
|
|
4017
|
+
".gif": "image/gif",
|
|
4018
|
+
".webp": "image/webp",
|
|
4019
|
+
".avif": "image/avif",
|
|
4020
|
+
".svg": "image/svg+xml",
|
|
4021
|
+
".bmp": "image/bmp",
|
|
4022
|
+
".ico": "image/x-icon"
|
|
4023
|
+
};
|
|
4024
|
+
function isAbsoluteUrl(s) {
|
|
4025
|
+
return /^[a-z][a-z0-9+.-]*:\/\//i.test(s) || s.startsWith("data:");
|
|
4026
|
+
}
|
|
4027
|
+
async function maybeInlineLocalImage(element, src) {
|
|
4028
|
+
if (!src || isAbsoluteUrl(src)) return;
|
|
4029
|
+
const projectRoot = getProjectRoot();
|
|
4030
|
+
const rel = src.replace(/^\/+/, "");
|
|
4031
|
+
const abs = join2(projectRoot, rel);
|
|
4032
|
+
if (!abs.startsWith(projectRoot)) return;
|
|
4033
|
+
try {
|
|
4034
|
+
const buf = await readFile2(abs);
|
|
4035
|
+
const ext = extname(abs).toLowerCase();
|
|
4036
|
+
const mime = IMAGE_EXT_MIME[ext] || "application/octet-stream";
|
|
4037
|
+
element.imageDataBase64 = buf.toString("base64");
|
|
4038
|
+
element.imageDataMime = mime;
|
|
4039
|
+
element.imageDataFileName = basename(abs);
|
|
4040
|
+
} catch {
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
function flattenInlineHtmlToText(raw) {
|
|
4044
|
+
const decode = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ");
|
|
4045
|
+
let out = "";
|
|
4046
|
+
const tagRe = /<!--[\s\S]*?-->|<\/?([a-zA-Z][a-zA-Z0-9]*)[^>]*>/g;
|
|
4047
|
+
let lastIndex = 0;
|
|
4048
|
+
let match;
|
|
4049
|
+
while ((match = tagRe.exec(raw)) !== null) {
|
|
4050
|
+
if (match.index > lastIndex) {
|
|
4051
|
+
out += decode(raw.slice(lastIndex, match.index));
|
|
4052
|
+
}
|
|
4053
|
+
lastIndex = match.index + match[0].length;
|
|
4054
|
+
if (match[0].startsWith("<!--")) continue;
|
|
4055
|
+
if ((match[1] || "").toLowerCase() === "br") out += "\n";
|
|
4056
|
+
}
|
|
4057
|
+
if (lastIndex < raw.length) out += decode(raw.slice(lastIndex));
|
|
4058
|
+
return out;
|
|
3704
4059
|
}
|
|
3705
|
-
function
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
4060
|
+
function resolveVarsInValue(value, ctx, breakpoint = "base") {
|
|
4061
|
+
if (!value || !ctx.themeVars && !ctx.projectVars) return value;
|
|
4062
|
+
const themeMap = ctx.themeVars ? (ctx.currentTheme && ctx.themeVars[ctx.currentTheme]) ?? (ctx.defaultTheme ? ctx.themeVars[ctx.defaultTheme] : void 0) : void 0;
|
|
4063
|
+
const projectMap = ctx.projectVars ? ctx.projectVars[breakpoint] || ctx.projectVars.base : void 0;
|
|
4064
|
+
const pattern = /var\(\s*(--[\w-]+)\s*(?:,\s*([^)]+))?\)/g;
|
|
4065
|
+
let current = value;
|
|
4066
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
4067
|
+
let changed = false;
|
|
4068
|
+
current = current.replace(pattern, (match, name, fallback) => {
|
|
4069
|
+
const resolved = (themeMap && themeMap[name]) ?? (projectMap && projectMap[name]);
|
|
4070
|
+
if (resolved !== void 0) {
|
|
4071
|
+
changed = true;
|
|
4072
|
+
return resolved;
|
|
4073
|
+
}
|
|
4074
|
+
if (fallback !== void 0) {
|
|
4075
|
+
changed = true;
|
|
4076
|
+
return fallback.trim();
|
|
4077
|
+
}
|
|
4078
|
+
return match;
|
|
4079
|
+
});
|
|
4080
|
+
if (!changed) break;
|
|
3711
4081
|
}
|
|
3712
4082
|
return current;
|
|
3713
4083
|
}
|
|
3714
|
-
function
|
|
3715
|
-
|
|
4084
|
+
function substituteVarsInStyleObject(style, ctx, breakpoint = "base") {
|
|
4085
|
+
const out = {};
|
|
4086
|
+
for (const [k, v] of Object.entries(style)) {
|
|
4087
|
+
out[k] = typeof v === "string" ? resolveVarsInValue(v, ctx, breakpoint) : v;
|
|
4088
|
+
}
|
|
4089
|
+
return out;
|
|
4090
|
+
}
|
|
4091
|
+
function projectBreakpointNames(ctx) {
|
|
4092
|
+
return Object.keys(ctx.breakpoints);
|
|
4093
|
+
}
|
|
4094
|
+
function expandResponsiveVarsInto(baseStyle, responsive, ctx) {
|
|
4095
|
+
if (!ctx.projectVars) return;
|
|
4096
|
+
const bps = projectBreakpointNames(ctx);
|
|
4097
|
+
if (bps.length === 0) return;
|
|
4098
|
+
for (const [prop, rawVal] of Object.entries(baseStyle)) {
|
|
4099
|
+
if (typeof rawVal !== "string" || !rawVal.includes("var(--")) continue;
|
|
4100
|
+
const baseResolved = resolveVarsInValue(rawVal, ctx, "base");
|
|
4101
|
+
for (const bp of bps) {
|
|
4102
|
+
const bpResolved = resolveVarsInValue(rawVal, ctx, bp);
|
|
4103
|
+
if (bpResolved === baseResolved) continue;
|
|
4104
|
+
const bucket = responsive[bp] || {};
|
|
4105
|
+
if (bucket[prop] !== void 0) continue;
|
|
4106
|
+
bucket[prop] = bpResolved;
|
|
4107
|
+
responsive[bp] = bucket;
|
|
4108
|
+
}
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
function substituteVarsInStyle(style, ctx) {
|
|
4112
|
+
if (!style) return style;
|
|
4113
|
+
if (isResponsiveStyleObject(style)) {
|
|
4114
|
+
const out = {};
|
|
4115
|
+
for (const [bp, obj] of Object.entries(style)) {
|
|
4116
|
+
if (!obj || typeof obj !== "object") continue;
|
|
4117
|
+
out[bp] = substituteVarsInStyleObject(obj, ctx, bp);
|
|
4118
|
+
}
|
|
4119
|
+
const baseObj = style.base;
|
|
4120
|
+
if (baseObj) expandResponsiveVarsInto(baseObj, out, ctx);
|
|
4121
|
+
return out;
|
|
4122
|
+
}
|
|
4123
|
+
const flatStyle = style;
|
|
4124
|
+
const baseSubstituted = substituteVarsInStyleObject(flatStyle, ctx, "base");
|
|
4125
|
+
const responsive = { base: baseSubstituted };
|
|
4126
|
+
expandResponsiveVarsInto(flatStyle, responsive, ctx);
|
|
4127
|
+
if (Object.keys(responsive).length === 1) return baseSubstituted;
|
|
4128
|
+
return responsive;
|
|
4129
|
+
}
|
|
4130
|
+
function substituteVarsInInteractive(rules, ctx) {
|
|
4131
|
+
if (!rules) return rules;
|
|
4132
|
+
return rules.map((rule) => ({
|
|
4133
|
+
...rule,
|
|
4134
|
+
style: substituteVarsInStyle(rule.style, ctx) ?? rule.style
|
|
4135
|
+
}));
|
|
4136
|
+
}
|
|
4137
|
+
function substituteVarsInStyleClass(cls, ctx) {
|
|
4138
|
+
const varBaseProps = [];
|
|
4139
|
+
for (const [k, v] of Object.entries(cls.base)) {
|
|
4140
|
+
if (typeof v === "string" && v.includes("var(--")) {
|
|
4141
|
+
varBaseProps.push({ prop: k, raw: v });
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
for (const k of Object.keys(cls.base)) {
|
|
4145
|
+
cls.base[k] = resolveVarsInValue(cls.base[k], ctx, "base");
|
|
4146
|
+
}
|
|
4147
|
+
if (cls.breakpoints) {
|
|
4148
|
+
for (const [tier, bp] of Object.entries(cls.breakpoints)) {
|
|
4149
|
+
if (!bp) continue;
|
|
4150
|
+
for (const k of Object.keys(bp)) {
|
|
4151
|
+
bp[k] = resolveVarsInValue(bp[k], ctx, tier);
|
|
4152
|
+
}
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
if (cls.pseudoStates) {
|
|
4156
|
+
for (const ps of Object.values(cls.pseudoStates)) {
|
|
4157
|
+
if (!ps) continue;
|
|
4158
|
+
for (const k of Object.keys(ps)) ps[k] = resolveVarsInValue(ps[k], ctx, "base");
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
if (varBaseProps.length === 0 || !ctx.projectVars) return;
|
|
4162
|
+
for (const bpName of Object.keys(ctx.breakpoints)) {
|
|
4163
|
+
const tier = menoBreakpointToWebflowTier(bpName, ctx.breakpoints);
|
|
4164
|
+
for (const { prop, raw } of varBaseProps) {
|
|
4165
|
+
const baseResolved = cls.base[prop];
|
|
4166
|
+
const bpResolved = resolveVarsInValue(raw, ctx, bpName);
|
|
4167
|
+
if (bpResolved === baseResolved) continue;
|
|
4168
|
+
if (!cls.breakpoints) cls.breakpoints = {};
|
|
4169
|
+
const bucket = cls.breakpoints[tier] || {};
|
|
4170
|
+
if (bucket[prop] !== void 0) continue;
|
|
4171
|
+
bucket[prop] = bpResolved;
|
|
4172
|
+
cls.breakpoints[tier] = bucket;
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
function menoBreakpointToWebflowTier(bpName, breakpoints) {
|
|
4177
|
+
if (bpName === "tablet") return "medium";
|
|
4178
|
+
if (bpName === "mobile") return "small";
|
|
4179
|
+
const entry = breakpoints[bpName];
|
|
4180
|
+
const w = entry && typeof entry.breakpoint === "number" ? entry.breakpoint : 992;
|
|
4181
|
+
if (w < 480) return "tiny";
|
|
4182
|
+
if (w < 768) return "small";
|
|
4183
|
+
if (w < 992) return "medium";
|
|
4184
|
+
if (w < 1280) return "main";
|
|
4185
|
+
if (w < 1440) return "large";
|
|
4186
|
+
if (w < 1920) return "xl";
|
|
4187
|
+
return "xxl";
|
|
4188
|
+
}
|
|
4189
|
+
function isResponsiveStyleObject(style) {
|
|
4190
|
+
return "base" in style || "tablet" in style || "mobile" in style;
|
|
4191
|
+
}
|
|
4192
|
+
function extractBaseColor(style, ctx, instanceProps) {
|
|
4193
|
+
if (!style) return void 0;
|
|
4194
|
+
const flat = isResponsiveStyleObject(style) ? style.base : style;
|
|
4195
|
+
const c = flat?.color;
|
|
4196
|
+
if (typeof c === "string") return c;
|
|
4197
|
+
if (c && typeof c === "object" && c._mapping === true) {
|
|
4198
|
+
const mapping = c;
|
|
4199
|
+
const propValue = instanceProps?.[mapping.prop] ?? ctx?.componentDefaults?.[mapping.prop];
|
|
4200
|
+
if (propValue == null) return void 0;
|
|
4201
|
+
const key = String(propValue);
|
|
4202
|
+
const raw = mapping.values[key];
|
|
4203
|
+
if (typeof raw !== "string" || raw === "") return void 0;
|
|
4204
|
+
return ctx ? resolveVarsInValue(raw, ctx) : raw;
|
|
4205
|
+
}
|
|
4206
|
+
return void 0;
|
|
4207
|
+
}
|
|
4208
|
+
function concreteColor(c) {
|
|
4209
|
+
if (!c) return void 0;
|
|
4210
|
+
const lower = c.trim().toLowerCase();
|
|
4211
|
+
if (lower === "currentcolor" || lower === "inherit" || lower === "unset" || lower === "initial") {
|
|
4212
|
+
return void 0;
|
|
4213
|
+
}
|
|
4214
|
+
return c;
|
|
4215
|
+
}
|
|
4216
|
+
function inlineCurrentColorInSvg(svg, color) {
|
|
4217
|
+
return svg.replace(/currentColor/gi, color);
|
|
4218
|
+
}
|
|
4219
|
+
function resolveTemplatesInStyleObject(style, props) {
|
|
4220
|
+
const result = {};
|
|
4221
|
+
for (const [key, value] of Object.entries(style)) {
|
|
4222
|
+
if (typeof value === "string" && hasTemplates(value)) {
|
|
4223
|
+
result[key] = processCodeTemplates(value, props);
|
|
4224
|
+
} else {
|
|
4225
|
+
result[key] = value;
|
|
4226
|
+
}
|
|
4227
|
+
}
|
|
4228
|
+
return result;
|
|
4229
|
+
}
|
|
4230
|
+
function resolveStyleTemplates(style, props) {
|
|
4231
|
+
if (!style || !props) return style;
|
|
4232
|
+
if (isResponsiveStyleObject(style)) {
|
|
4233
|
+
const result = {};
|
|
4234
|
+
for (const [bp, styleObj] of Object.entries(style)) {
|
|
4235
|
+
if (styleObj && typeof styleObj === "object") {
|
|
4236
|
+
result[bp] = resolveTemplatesInStyleObject(styleObj, props);
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
4239
|
+
return result;
|
|
4240
|
+
}
|
|
4241
|
+
return resolveTemplatesInStyleObject(style, props);
|
|
4242
|
+
}
|
|
4243
|
+
var SINGLE_TEMPLATE_RE = /^([^{]*)\{\{\s*([A-Za-z_$][\w$]*)\s*\}\}([^{]*)$/;
|
|
4244
|
+
function extractSingleTemplateProp(value) {
|
|
4245
|
+
const m = SINGLE_TEMPLATE_RE.exec(value);
|
|
4246
|
+
if (!m) return null;
|
|
4247
|
+
return { prefix: m[1] ?? "", prop: m[2], suffix: m[3] ?? "" };
|
|
3716
4248
|
}
|
|
3717
|
-
function
|
|
4249
|
+
function templatesToSyntheticMappings(style, componentDefaults, instanceProps) {
|
|
4250
|
+
const out = {};
|
|
4251
|
+
for (const [key, value] of Object.entries(style)) {
|
|
4252
|
+
if (typeof value !== "string" || !hasTemplates(value)) {
|
|
4253
|
+
out[key] = value;
|
|
4254
|
+
continue;
|
|
4255
|
+
}
|
|
4256
|
+
const parsed = extractSingleTemplateProp(value);
|
|
4257
|
+
if (!parsed) {
|
|
4258
|
+
out[key] = value;
|
|
4259
|
+
continue;
|
|
4260
|
+
}
|
|
4261
|
+
const { prop } = parsed;
|
|
4262
|
+
const defaultPropValue = componentDefaults[prop];
|
|
4263
|
+
if (defaultPropValue == null) {
|
|
4264
|
+
out[key] = value;
|
|
4265
|
+
continue;
|
|
4266
|
+
}
|
|
4267
|
+
const instancePropValue = instanceProps[prop] ?? defaultPropValue;
|
|
4268
|
+
const defaultResolved = processCodeTemplates(value, { ...instanceProps, [prop]: defaultPropValue });
|
|
4269
|
+
const instanceResolved = processCodeTemplates(value, { ...instanceProps, [prop]: instancePropValue });
|
|
4270
|
+
out[key] = {
|
|
4271
|
+
_mapping: true,
|
|
4272
|
+
prop,
|
|
4273
|
+
values: {
|
|
4274
|
+
[String(defaultPropValue)]: defaultResolved,
|
|
4275
|
+
[String(instancePropValue)]: instanceResolved
|
|
4276
|
+
}
|
|
4277
|
+
};
|
|
4278
|
+
}
|
|
4279
|
+
return out;
|
|
4280
|
+
}
|
|
4281
|
+
function convertStyleTemplatesToMappings(style, componentDefaults, instanceProps) {
|
|
4282
|
+
if (!style || !componentDefaults || !instanceProps) return style;
|
|
4283
|
+
if (isResponsiveStyleObject(style)) {
|
|
4284
|
+
const result = {};
|
|
4285
|
+
for (const [bp, styleObj] of Object.entries(style)) {
|
|
4286
|
+
if (styleObj && typeof styleObj === "object") {
|
|
4287
|
+
result[bp] = templatesToSyntheticMappings(styleObj, componentDefaults, instanceProps);
|
|
4288
|
+
}
|
|
4289
|
+
}
|
|
4290
|
+
return result;
|
|
4291
|
+
}
|
|
4292
|
+
return templatesToSyntheticMappings(style, componentDefaults, instanceProps);
|
|
4293
|
+
}
|
|
4294
|
+
function shouldRenderNode(node, instanceProps) {
|
|
4295
|
+
if (!hasIf(node)) return true;
|
|
4296
|
+
const ifValue = node.if;
|
|
4297
|
+
if (typeof ifValue === "boolean") return ifValue;
|
|
4298
|
+
if (isBooleanMapping(ifValue)) {
|
|
4299
|
+
if (!instanceProps) return true;
|
|
4300
|
+
const propValue = instanceProps[ifValue.prop];
|
|
4301
|
+
const mapped = ifValue.values[String(propValue)];
|
|
4302
|
+
return mapped !== void 0 ? Boolean(mapped) : true;
|
|
4303
|
+
}
|
|
4304
|
+
if (typeof ifValue === "string") {
|
|
4305
|
+
if (!instanceProps) return true;
|
|
4306
|
+
const resolved = processCodeTemplates(ifValue, instanceProps);
|
|
4307
|
+
return Boolean(resolved) && resolved !== "false" && resolved !== "0" && resolved !== "";
|
|
4308
|
+
}
|
|
4309
|
+
return true;
|
|
4310
|
+
}
|
|
4311
|
+
function resolveInteractiveStyleTemplates(rules, props) {
|
|
4312
|
+
if (!rules || !props) return rules;
|
|
4313
|
+
return rules.map((rule) => ({
|
|
4314
|
+
...rule,
|
|
4315
|
+
style: resolveStyleTemplates(rule.style, props) ?? rule.style
|
|
4316
|
+
}));
|
|
4317
|
+
}
|
|
4318
|
+
async function nodeToWebflow(node, ctx, instanceProps) {
|
|
3718
4319
|
if (node === null || node === void 0) return [];
|
|
3719
4320
|
if (typeof node === "string") {
|
|
3720
|
-
const text =
|
|
4321
|
+
const text = resolveStringTemplate(node, ctx, instanceProps);
|
|
4322
|
+
if (text === "" || text.trim() === "") return [];
|
|
3721
4323
|
return [{ tag: "span", textContent: text }];
|
|
3722
4324
|
}
|
|
3723
4325
|
if (typeof node === "number") {
|
|
@@ -3729,88 +4331,114 @@ function nodeToWebflow(node, ctx, instanceProps) {
|
|
|
3729
4331
|
const child = node[i];
|
|
3730
4332
|
const savedPath = [...ctx.elementPath];
|
|
3731
4333
|
ctx.elementPath = [...ctx.elementPath, i];
|
|
3732
|
-
results.push(...nodeToWebflow(child, ctx, instanceProps));
|
|
4334
|
+
results.push(...await nodeToWebflow(child, ctx, instanceProps));
|
|
3733
4335
|
ctx.elementPath = savedPath;
|
|
3734
4336
|
}
|
|
3735
4337
|
return results;
|
|
3736
4338
|
}
|
|
4339
|
+
if (!shouldRenderNode(node, instanceProps)) return [];
|
|
3737
4340
|
switch (node.type) {
|
|
3738
4341
|
case NODE_TYPE.NODE:
|
|
3739
|
-
return [emitHtmlNode2(node, ctx, instanceProps)];
|
|
4342
|
+
return [await emitHtmlNode2(node, ctx, instanceProps)];
|
|
3740
4343
|
case NODE_TYPE.COMPONENT:
|
|
3741
4344
|
return emitComponentInstance2(node, ctx, instanceProps);
|
|
3742
4345
|
case NODE_TYPE.SLOT:
|
|
3743
4346
|
return emitSlotMarker2(node, ctx, instanceProps);
|
|
3744
4347
|
case NODE_TYPE.EMBED:
|
|
3745
|
-
return [emitEmbedNode2(node, ctx, instanceProps)];
|
|
4348
|
+
return [await emitEmbedNode2(node, ctx, instanceProps)];
|
|
3746
4349
|
case NODE_TYPE.LINK:
|
|
3747
|
-
return [emitLinkNode2(node, ctx, instanceProps)];
|
|
4350
|
+
return [await emitLinkNode2(node, ctx, instanceProps)];
|
|
3748
4351
|
case NODE_TYPE.LIST:
|
|
3749
4352
|
case "cms-list":
|
|
4353
|
+
return emitListNode2(node, ctx, instanceProps);
|
|
3750
4354
|
case NODE_TYPE.LOCALE_LIST:
|
|
3751
|
-
return
|
|
4355
|
+
return emitLocaleListNode2(node, ctx, instanceProps);
|
|
3752
4356
|
default:
|
|
3753
4357
|
return [];
|
|
3754
4358
|
}
|
|
3755
4359
|
}
|
|
3756
|
-
function emitHtmlNode2(node, ctx, instanceProps) {
|
|
3757
|
-
const tag =
|
|
3758
|
-
const
|
|
3759
|
-
|
|
3760
|
-
|
|
4360
|
+
async function emitHtmlNode2(node, ctx, instanceProps) {
|
|
4361
|
+
const tag = resolveStringTemplate(node.tag, ctx, instanceProps);
|
|
4362
|
+
const attributes = {};
|
|
4363
|
+
if (node.attributes) {
|
|
4364
|
+
for (const [key, value] of Object.entries(node.attributes)) {
|
|
4365
|
+
attributes[key] = typeof value === "string" ? resolveStringTemplate(value, ctx, instanceProps) : value;
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
const themedCtx = typeof attributes.theme === "string" && attributes.theme ? { ...ctx, currentTheme: attributes.theme } : ctx;
|
|
4369
|
+
const rawStyle = node.style;
|
|
4370
|
+
const rawInteractiveStyles = node.interactiveStyles;
|
|
4371
|
+
const styleWithMappings = convertStyleTemplatesToMappings(
|
|
4372
|
+
rawStyle,
|
|
4373
|
+
ctx.componentDefaults,
|
|
4374
|
+
instanceProps
|
|
4375
|
+
);
|
|
4376
|
+
const style = substituteVarsInStyle(
|
|
4377
|
+
resolveStyleTemplates(styleWithMappings, instanceProps),
|
|
4378
|
+
themedCtx
|
|
4379
|
+
);
|
|
4380
|
+
const interactiveStyles = substituteVarsInInteractive(
|
|
4381
|
+
resolveInteractiveStyleTemplates(rawInteractiveStyles, instanceProps),
|
|
4382
|
+
themedCtx
|
|
4383
|
+
);
|
|
4384
|
+
const tagLower = tag.toLowerCase();
|
|
4385
|
+
const isHeading = HEADING_TAGS.has(tagLower);
|
|
4386
|
+
const isLinkLike = LINK_LIKE_TAGS.has(tagLower);
|
|
4387
|
+
const isParagraph = tagLower === "p";
|
|
4388
|
+
const isList = LIST_TAGS.has(tagLower);
|
|
4389
|
+
const needsClass = style || interactiveStyles && interactiveStyles.length > 0 || node.generateElementClass || isHeading || isLinkLike || isParagraph || isList;
|
|
3761
4390
|
let className;
|
|
3762
4391
|
let comboClassNames;
|
|
3763
4392
|
if (needsClass) {
|
|
3764
|
-
const elementClass = buildElementClass2(ctx, node.label);
|
|
4393
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), themedCtx);
|
|
3765
4394
|
const { primaryClass, comboClasses } = mapStylesToWebflow(
|
|
3766
4395
|
elementClass,
|
|
3767
4396
|
style,
|
|
3768
4397
|
interactiveStyles,
|
|
3769
|
-
ctx.breakpoints
|
|
4398
|
+
ctx.breakpoints,
|
|
4399
|
+
ctx.responsiveScales,
|
|
4400
|
+
{ instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(themedCtx) }
|
|
3770
4401
|
);
|
|
4402
|
+
substituteVarsInStyleClass(primaryClass, themedCtx);
|
|
4403
|
+
if (isHeading) applyHeadingMarginDefaults(primaryClass);
|
|
4404
|
+
if (isParagraph) applyParagraphMarginDefaults(primaryClass);
|
|
4405
|
+
if (isList) applyListMarginDefaults(primaryClass);
|
|
4406
|
+
if (isLinkLike) applyLinkTextDecorationDefault(primaryClass);
|
|
4407
|
+
applyGridRowsDefault(primaryClass);
|
|
3771
4408
|
className = primaryClass.name;
|
|
3772
4409
|
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
3773
4410
|
if (comboClasses.length > 0) {
|
|
3774
4411
|
comboClassNames = [];
|
|
3775
4412
|
for (const combo of comboClasses) {
|
|
4413
|
+
substituteVarsInStyleClass(combo, themedCtx);
|
|
3776
4414
|
ctx.styleClasses.set(combo.name, combo);
|
|
3777
4415
|
comboClassNames.push(combo.name);
|
|
3778
4416
|
}
|
|
3779
4417
|
}
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
if (node.attributes) {
|
|
3783
|
-
for (const [key, value] of Object.entries(node.attributes)) {
|
|
3784
|
-
if (instanceProps && typeof value === "string" && hasTemplates2(value)) {
|
|
3785
|
-
attributes[key] = resolveTemplate2(value, instanceProps);
|
|
3786
|
-
} else {
|
|
3787
|
-
attributes[key] = value;
|
|
3788
|
-
}
|
|
4418
|
+
if (ctx.interactiveStylesMap && Array.isArray(interactiveStyles) && interactiveStyles.length > 0) {
|
|
4419
|
+
ctx.interactiveStylesMap.set(primaryClass.name, interactiveStyles);
|
|
3789
4420
|
}
|
|
3790
4421
|
}
|
|
3791
4422
|
let children;
|
|
3792
4423
|
let textContent;
|
|
3793
4424
|
if (!isVoidElement(tag) && node.children) {
|
|
3794
4425
|
if (typeof node.children === "string") {
|
|
3795
|
-
textContent =
|
|
4426
|
+
textContent = resolveStringTemplate(node.children, ctx, instanceProps);
|
|
3796
4427
|
} else if (Array.isArray(node.children) && node.children.length === 1 && typeof node.children[0] === "string") {
|
|
3797
4428
|
const text = node.children[0];
|
|
3798
|
-
textContent =
|
|
4429
|
+
textContent = resolveStringTemplate(text, ctx, instanceProps);
|
|
3799
4430
|
} else {
|
|
3800
|
-
const innerCtx = { ...
|
|
3801
|
-
|
|
4431
|
+
const innerCtx = { ...themedCtx, elementPath: [...themedCtx.elementPath] };
|
|
4432
|
+
const ownColor = concreteColor(extractBaseColor(style, themedCtx, instanceProps));
|
|
4433
|
+
if (ownColor) innerCtx.inheritedColor = ownColor;
|
|
4434
|
+
children = await convertChildren(node.children, innerCtx, instanceProps);
|
|
3802
4435
|
if (children.length === 0) children = void 0;
|
|
3803
4436
|
}
|
|
3804
4437
|
}
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
if (
|
|
3808
|
-
|
|
3809
|
-
conditional = { prop: ifValue.prop, condition: "truthy" };
|
|
3810
|
-
} else if (typeof ifValue === "string") {
|
|
3811
|
-
const match = ifValue.match(/^\{\{(.+)\}\}$/);
|
|
3812
|
-
conditional = { prop: match ? match[1].trim() : ifValue, condition: "truthy" };
|
|
3813
|
-
}
|
|
4438
|
+
if (textContent && textContent.startsWith(RAW_HTML_PREFIX)) {
|
|
4439
|
+
textContent = flattenInlineHtmlToText(textContent.slice(RAW_HTML_PREFIX.length));
|
|
4440
|
+
} else if (textContent && (isHeading || isParagraph) && /<[a-zA-Z!]/.test(textContent)) {
|
|
4441
|
+
textContent = flattenInlineHtmlToText(textContent);
|
|
3814
4442
|
}
|
|
3815
4443
|
const element = { tag };
|
|
3816
4444
|
if (className) element.className = className;
|
|
@@ -3818,115 +4446,786 @@ function emitHtmlNode2(node, ctx, instanceProps) {
|
|
|
3818
4446
|
if (textContent) element.textContent = textContent;
|
|
3819
4447
|
if (children) element.children = children;
|
|
3820
4448
|
if (Object.keys(attributes).length > 0) element.attributes = attributes;
|
|
3821
|
-
if (
|
|
4449
|
+
if (tag.toLowerCase() === "img" && typeof attributes.src === "string") {
|
|
4450
|
+
await maybeInlineLocalImage(element, attributes.src);
|
|
4451
|
+
}
|
|
3822
4452
|
return element;
|
|
3823
4453
|
}
|
|
3824
|
-
function emitComponentInstance2(node, ctx, parentProps) {
|
|
4454
|
+
async function emitComponentInstance2(node, ctx, parentProps) {
|
|
3825
4455
|
const compDef = ctx.globalComponents[node.component];
|
|
3826
4456
|
if (!compDef) {
|
|
3827
4457
|
return [{ tag: "div", attributes: { "data-component": node.component } }];
|
|
3828
4458
|
}
|
|
3829
|
-
const resolvedProps = {};
|
|
3830
4459
|
const structured = compDef.component;
|
|
3831
|
-
|
|
3832
|
-
for (const [key, propDef] of Object.entries(structured.interface)) {
|
|
3833
|
-
resolvedProps[key] = propDef.default;
|
|
3834
|
-
}
|
|
3835
|
-
}
|
|
4460
|
+
const passedProps = {};
|
|
3836
4461
|
if (node.props) {
|
|
4462
|
+
const parentTemplateProps = parentProps ?? buildTemplateProps(ctx);
|
|
3837
4463
|
for (const [key, value] of Object.entries(node.props)) {
|
|
3838
4464
|
if (key === "children") continue;
|
|
3839
|
-
|
|
3840
|
-
resolvedProps[key] = resolveTemplate2(value, parentProps);
|
|
3841
|
-
} else {
|
|
3842
|
-
resolvedProps[key] = value;
|
|
3843
|
-
}
|
|
4465
|
+
passedProps[key] = typeof value === "string" && hasTemplates(value) ? processCodeTemplates(value, parentTemplateProps) : value;
|
|
3844
4466
|
}
|
|
3845
4467
|
}
|
|
4468
|
+
const resolvedProps = structured ? resolvePropsFromDefinition(
|
|
4469
|
+
structured,
|
|
4470
|
+
passedProps,
|
|
4471
|
+
node.children,
|
|
4472
|
+
ctx.locale,
|
|
4473
|
+
ctx.i18nConfig
|
|
4474
|
+
) : { ...passedProps };
|
|
4475
|
+
delete resolvedProps.children;
|
|
3846
4476
|
const body = structured?.structure || compDef.node;
|
|
3847
4477
|
if (!body) return [];
|
|
4478
|
+
const hasInstanceStyleOverrides = Boolean(structured?.acceptsStyles) && (node.style && Object.keys(node.style).length > 0 || Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0);
|
|
4479
|
+
const promotedNames = ctx.promotedComponentNames || PROMOTED_TO_WEBFLOW_COMPONENT;
|
|
4480
|
+
if (promotedNames.has(node.component) && ctx.promotedComponents && !hasInstanceStyleOverrides) {
|
|
4481
|
+
const promoted = ctx.promotedComponents;
|
|
4482
|
+
if (!promoted.has(node.component)) {
|
|
4483
|
+
const defaultProps = {};
|
|
4484
|
+
if (structured?.interface) {
|
|
4485
|
+
for (const [k, p] of Object.entries(structured.interface)) {
|
|
4486
|
+
defaultProps[k] = p.default;
|
|
4487
|
+
}
|
|
4488
|
+
}
|
|
4489
|
+
const compBodyCtx = {
|
|
4490
|
+
...ctx,
|
|
4491
|
+
fileType: "component",
|
|
4492
|
+
fileName: node.component,
|
|
4493
|
+
elementPath: [0],
|
|
4494
|
+
slotChildren: void 0,
|
|
4495
|
+
slotEmitContext: void 0,
|
|
4496
|
+
// Disable further promotion inside the component body — a Navigation
|
|
4497
|
+
// that nests Footer (or itself) would loop. Nested promoted names
|
|
4498
|
+
// inline within the registered Component's body.
|
|
4499
|
+
promotedComponents: null,
|
|
4500
|
+
componentDefaults: defaultProps
|
|
4501
|
+
};
|
|
4502
|
+
const elements = await nodeToWebflow(body, compBodyCtx, defaultProps);
|
|
4503
|
+
promoted.set(node.component, { name: node.component, elements });
|
|
4504
|
+
}
|
|
4505
|
+
const fallback = await emitInlineComponentBody(
|
|
4506
|
+
node,
|
|
4507
|
+
compDef,
|
|
4508
|
+
resolvedProps,
|
|
4509
|
+
body,
|
|
4510
|
+
{ ...ctx, promotedComponents: null },
|
|
4511
|
+
parentProps
|
|
4512
|
+
);
|
|
4513
|
+
return [{ tag: "div", componentRef: node.component, inlineFallback: fallback }];
|
|
4514
|
+
}
|
|
4515
|
+
return emitInlineComponentBody(node, compDef, resolvedProps, body, ctx, parentProps);
|
|
4516
|
+
}
|
|
4517
|
+
async function emitInlineComponentBody(node, compDef, resolvedProps, body, ctx, parentProps) {
|
|
4518
|
+
const structured = compDef.component;
|
|
4519
|
+
let effectiveChildren = node.children;
|
|
4520
|
+
let inheritedSlotEmitContext = ctx.slotEmitContext;
|
|
4521
|
+
let inheritedSlotInstanceProps = void 0;
|
|
4522
|
+
let didForwardSlot = false;
|
|
4523
|
+
if (node.children != null && typeof node.children !== "string") {
|
|
4524
|
+
const childArr = Array.isArray(node.children) ? node.children : [node.children];
|
|
4525
|
+
if (childArr.some((c) => c && typeof c === "object" && c.type === NODE_TYPE.SLOT)) {
|
|
4526
|
+
const out = [];
|
|
4527
|
+
for (const c of childArr) {
|
|
4528
|
+
if (c && typeof c === "object" && c.type === NODE_TYPE.SLOT) {
|
|
4529
|
+
didForwardSlot = true;
|
|
4530
|
+
if (ctx.slotChildren !== void 0) {
|
|
4531
|
+
const sc = ctx.slotChildren;
|
|
4532
|
+
const subArr = Array.isArray(sc) ? sc : [sc];
|
|
4533
|
+
out.push(...subArr);
|
|
4534
|
+
} else {
|
|
4535
|
+
const def = c.default;
|
|
4536
|
+
if (def !== void 0) {
|
|
4537
|
+
const defArr = Array.isArray(def) ? def : [def];
|
|
4538
|
+
out.push(...defArr);
|
|
4539
|
+
}
|
|
4540
|
+
}
|
|
4541
|
+
} else {
|
|
4542
|
+
out.push(c);
|
|
4543
|
+
}
|
|
4544
|
+
}
|
|
4545
|
+
if (didForwardSlot) {
|
|
4546
|
+
effectiveChildren = out;
|
|
4547
|
+
inheritedSlotInstanceProps = ctx.slotInstanceProps;
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
3848
4551
|
const compCtx = {
|
|
3849
4552
|
...ctx,
|
|
3850
4553
|
fileType: "component",
|
|
3851
4554
|
fileName: node.component,
|
|
3852
4555
|
elementPath: [0],
|
|
3853
|
-
slotChildren:
|
|
4556
|
+
slotChildren: effectiveChildren,
|
|
4557
|
+
slotEmitContext: didForwardSlot && inheritedSlotEmitContext ? inheritedSlotEmitContext : {
|
|
4558
|
+
fileType: ctx.fileType,
|
|
4559
|
+
fileName: ctx.fileName,
|
|
4560
|
+
elementPath: [...ctx.elementPath]
|
|
4561
|
+
},
|
|
4562
|
+
// Slot children authored alongside this instance refer to the OUTER
|
|
4563
|
+
// component's interface (the one whose body contains `<Component …>{slot
|
|
4564
|
+
// children}</Component>`). When the body hits its `<slot/>`, those
|
|
4565
|
+
// children must resolve `{{title}}` etc. against `parentProps` — not
|
|
4566
|
+
// against this component's resolved props. For forwarded slot children,
|
|
4567
|
+
// use the original outer slot's `slotInstanceProps` instead so they keep
|
|
4568
|
+
// their original authoring scope through the wrapper.
|
|
4569
|
+
slotInstanceProps: didForwardSlot ? inheritedSlotInstanceProps : parentProps,
|
|
4570
|
+
componentDefaults: extractInterfaceDefaults(structured?.interface)
|
|
3854
4571
|
};
|
|
3855
|
-
|
|
4572
|
+
const ctxTemplate = ctx.templateContext;
|
|
4573
|
+
const bodyProps = ctxTemplate ? { ...ctxTemplate, ...resolvedProps } : resolvedProps;
|
|
4574
|
+
const emitted = await nodeToWebflow(body, compCtx, bodyProps);
|
|
4575
|
+
if (structured?.acceptsStyles && emitted.length > 0 && (node.style && Object.keys(node.style).length > 0 || Array.isArray(node.interactiveStyles) && node.interactiveStyles.length > 0)) {
|
|
4576
|
+
const root = emitted[0];
|
|
4577
|
+
if (root && typeof root === "object") {
|
|
4578
|
+
if (!root.className) {
|
|
4579
|
+
const minted = withThemeSuffix(buildElementClass2(compCtx, void 0), compCtx);
|
|
4580
|
+
ctx.styleClasses.set(minted, { name: minted, base: {} });
|
|
4581
|
+
root.className = minted;
|
|
4582
|
+
}
|
|
4583
|
+
const rawStyle = node.style;
|
|
4584
|
+
const rawInteractive = node.interactiveStyles;
|
|
4585
|
+
const resolvedStyle = substituteVarsInStyle(
|
|
4586
|
+
resolveStyleTemplates(rawStyle, parentProps),
|
|
4587
|
+
ctx
|
|
4588
|
+
);
|
|
4589
|
+
const resolvedInteractive = substituteVarsInInteractive(
|
|
4590
|
+
resolveInteractiveStyleTemplates(rawInteractive, parentProps),
|
|
4591
|
+
ctx
|
|
4592
|
+
);
|
|
4593
|
+
const instanceLocClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
4594
|
+
const comboName = mintInstanceComboName(ctx, instanceLocClass);
|
|
4595
|
+
const combo = buildInstanceStyleCombo(
|
|
4596
|
+
comboName,
|
|
4597
|
+
root.className,
|
|
4598
|
+
resolvedStyle,
|
|
4599
|
+
resolvedInteractive,
|
|
4600
|
+
ctx.breakpoints,
|
|
4601
|
+
ctx.responsiveScales
|
|
4602
|
+
);
|
|
4603
|
+
if (combo) {
|
|
4604
|
+
substituteVarsInStyleClass(combo, ctx);
|
|
4605
|
+
const existingComboName = Array.isArray(root.comboClasses) && root.comboClasses.length > 0 ? root.comboClasses[0] : void 0;
|
|
4606
|
+
const inner = existingComboName ? ctx.styleClasses.get(existingComboName) : void 0;
|
|
4607
|
+
if (inner) {
|
|
4608
|
+
const merged = mergeComboClasses(inner, combo, root.className);
|
|
4609
|
+
ctx.styleClasses.set(merged.name, merged);
|
|
4610
|
+
root.comboClasses = [merged.name];
|
|
4611
|
+
} else {
|
|
4612
|
+
ctx.styleClasses.set(combo.name, combo);
|
|
4613
|
+
root.comboClasses = [combo.name];
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4617
|
+
}
|
|
4618
|
+
if (emitted.length > 0 && structured?.javascript) {
|
|
4619
|
+
const root = emitted[0];
|
|
4620
|
+
if (root && typeof root === "object") {
|
|
4621
|
+
root.attributes = root.attributes || {};
|
|
4622
|
+
const existing = root.attributes["data-component"];
|
|
4623
|
+
root.attributes["data-component"] = existing ? `${existing} ${node.component}` : node.component;
|
|
4624
|
+
const defineVars = structured.defineVars;
|
|
4625
|
+
if (defineVars) {
|
|
4626
|
+
const varsToExpose = defineVars === true ? Object.keys(structured.interface || {}) : defineVars;
|
|
4627
|
+
const propsForJS = {};
|
|
4628
|
+
for (const varName of varsToExpose) {
|
|
4629
|
+
if (resolvedProps[varName] !== void 0) {
|
|
4630
|
+
propsForJS[varName] = resolvedProps[varName];
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
let existingPropsMap = {};
|
|
4634
|
+
const existingPropsStr = root.attributes["data-props"];
|
|
4635
|
+
if (typeof existingPropsStr === "string" && existingPropsStr) {
|
|
4636
|
+
try {
|
|
4637
|
+
const parsed = JSON.parse(decodeURIComponent(existingPropsStr));
|
|
4638
|
+
if (parsed && typeof parsed === "object") {
|
|
4639
|
+
existingPropsMap = parsed;
|
|
4640
|
+
}
|
|
4641
|
+
} catch {
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
existingPropsMap[node.component] = propsForJS;
|
|
4645
|
+
root.attributes["data-props"] = encodeURIComponent(JSON.stringify(existingPropsMap));
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
return emitted;
|
|
3856
4650
|
}
|
|
3857
|
-
function emitSlotMarker2(node, ctx, instanceProps) {
|
|
4651
|
+
async function emitSlotMarker2(node, ctx, instanceProps) {
|
|
3858
4652
|
if (ctx.slotChildren) {
|
|
4653
|
+
const restored = ctx.slotEmitContext;
|
|
3859
4654
|
const parentCtx = {
|
|
3860
4655
|
...ctx,
|
|
3861
|
-
|
|
4656
|
+
...restored ? {
|
|
4657
|
+
fileType: restored.fileType,
|
|
4658
|
+
fileName: restored.fileName,
|
|
4659
|
+
elementPath: [...restored.elementPath]
|
|
4660
|
+
} : {},
|
|
4661
|
+
slotChildren: void 0,
|
|
3862
4662
|
// prevent infinite slot nesting
|
|
4663
|
+
slotEmitContext: void 0,
|
|
4664
|
+
// consumed
|
|
4665
|
+
slotInstanceProps: void 0
|
|
4666
|
+
// consumed
|
|
3863
4667
|
};
|
|
3864
|
-
|
|
4668
|
+
const slotProps = ctx.slotInstanceProps ?? instanceProps;
|
|
4669
|
+
return convertChildren(ctx.slotChildren, parentCtx, slotProps);
|
|
3865
4670
|
}
|
|
3866
4671
|
if (node.default) {
|
|
3867
4672
|
return convertChildren(node.default, ctx, instanceProps);
|
|
3868
4673
|
}
|
|
3869
4674
|
return [];
|
|
3870
4675
|
}
|
|
3871
|
-
function emitEmbedNode2(node, ctx, instanceProps) {
|
|
3872
|
-
const style =
|
|
3873
|
-
|
|
4676
|
+
async function emitEmbedNode2(node, ctx, instanceProps) {
|
|
4677
|
+
const style = substituteVarsInStyle(
|
|
4678
|
+
resolveStyleTemplates(
|
|
4679
|
+
node.style,
|
|
4680
|
+
instanceProps
|
|
4681
|
+
),
|
|
4682
|
+
ctx
|
|
4683
|
+
);
|
|
4684
|
+
const interactiveStyles = substituteVarsInInteractive(
|
|
4685
|
+
resolveInteractiveStyleTemplates(
|
|
4686
|
+
node.interactiveStyles,
|
|
4687
|
+
instanceProps
|
|
4688
|
+
),
|
|
4689
|
+
ctx
|
|
4690
|
+
);
|
|
3874
4691
|
let className;
|
|
3875
4692
|
if (style || interactiveStyles && interactiveStyles.length > 0) {
|
|
3876
|
-
const elementClass = buildElementClass2(ctx, node.label);
|
|
4693
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
3877
4694
|
const { primaryClass } = mapStylesToWebflow(
|
|
3878
4695
|
elementClass,
|
|
3879
4696
|
style,
|
|
3880
4697
|
interactiveStyles,
|
|
3881
|
-
ctx.breakpoints
|
|
4698
|
+
ctx.breakpoints,
|
|
4699
|
+
ctx.responsiveScales
|
|
3882
4700
|
);
|
|
4701
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
3883
4702
|
className = primaryClass.name;
|
|
3884
4703
|
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
3885
4704
|
}
|
|
3886
|
-
const
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
}
|
|
4705
|
+
const props = buildTemplateProps(ctx, instanceProps);
|
|
4706
|
+
let htmlStr;
|
|
4707
|
+
if (isHtmlMapping(node.html)) {
|
|
4708
|
+
htmlStr = resolveHtmlMapping(node.html, props) ?? "";
|
|
4709
|
+
} else if (typeof node.html === "string") {
|
|
4710
|
+
htmlStr = hasTemplates(node.html) ? processCodeTemplates(node.html, props) : node.html;
|
|
4711
|
+
} else {
|
|
4712
|
+
htmlStr = "";
|
|
4713
|
+
}
|
|
4714
|
+
const element = { tag: "div" };
|
|
3891
4715
|
if (className) element.className = className;
|
|
4716
|
+
const trimmed = htmlStr.trim();
|
|
4717
|
+
if (/^<svg\b/i.test(trimmed) && /<\/svg\s*>\s*$/i.test(trimmed)) {
|
|
4718
|
+
let svg = trimmed;
|
|
4719
|
+
if (/currentColor/i.test(svg)) {
|
|
4720
|
+
const resolved = concreteColor(extractBaseColor(style, ctx, instanceProps)) ?? ctx.inheritedColor;
|
|
4721
|
+
if (resolved) svg = inlineCurrentColorInSvg(svg, resolved);
|
|
4722
|
+
}
|
|
4723
|
+
element.svgSource = svg;
|
|
4724
|
+
if (node.label) element.imageAlt = node.label;
|
|
4725
|
+
return element;
|
|
4726
|
+
}
|
|
4727
|
+
const imgMatch = trimmed.match(/^<img\b([^>]*)\/?>\s*$/i);
|
|
4728
|
+
if (imgMatch) {
|
|
4729
|
+
const attrs = imgMatch[1];
|
|
4730
|
+
const src = /\bsrc\s*=\s*"([^"]*)"|\bsrc\s*=\s*'([^']*)'/i.exec(attrs);
|
|
4731
|
+
const alt = /\balt\s*=\s*"([^"]*)"|\balt\s*=\s*'([^']*)'/i.exec(attrs);
|
|
4732
|
+
if (src) {
|
|
4733
|
+
element.imageSrc = src[1] ?? src[2] ?? "";
|
|
4734
|
+
element.imageAlt = (alt?.[1] ?? alt?.[2] ?? node.label) || "";
|
|
4735
|
+
await maybeInlineLocalImage(element, element.imageSrc);
|
|
4736
|
+
return element;
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
if (trimmed.length) {
|
|
4740
|
+
element.unsupportedEmbed = {
|
|
4741
|
+
reason: "embed-not-svg-or-image",
|
|
4742
|
+
preview: trimmed.slice(0, 120),
|
|
4743
|
+
label: node.label
|
|
4744
|
+
};
|
|
4745
|
+
}
|
|
3892
4746
|
return element;
|
|
3893
4747
|
}
|
|
3894
|
-
function
|
|
3895
|
-
|
|
3896
|
-
|
|
4748
|
+
function resolveLinkHref(rawHref, ctx) {
|
|
4749
|
+
if (!rawHref) return rawHref;
|
|
4750
|
+
if (!rawHref.startsWith("/") || rawHref.startsWith("//")) return rawHref;
|
|
4751
|
+
if (!ctx.i18nConfig || !ctx.locale || !ctx.slugMappings) return rawHref;
|
|
4752
|
+
const hashIdx = rawHref.indexOf("#");
|
|
4753
|
+
const queryIdx = rawHref.indexOf("?");
|
|
4754
|
+
let cut = -1;
|
|
4755
|
+
if (hashIdx >= 0 && queryIdx >= 0) cut = Math.min(hashIdx, queryIdx);
|
|
4756
|
+
else if (hashIdx >= 0) cut = hashIdx;
|
|
4757
|
+
else if (queryIdx >= 0) cut = queryIdx;
|
|
4758
|
+
const path = cut >= 0 ? rawHref.slice(0, cut) : rawHref;
|
|
4759
|
+
const suffix = cut >= 0 ? rawHref.slice(cut) : "";
|
|
4760
|
+
if (!ctx.slugIndex) {
|
|
4761
|
+
ctx.slugIndex = buildSlugIndex(ctx.slugMappings);
|
|
4762
|
+
}
|
|
4763
|
+
const translated = translatePath(
|
|
4764
|
+
path,
|
|
4765
|
+
ctx.locale,
|
|
4766
|
+
ctx.i18nConfig.defaultLocale,
|
|
4767
|
+
ctx.i18nConfig.defaultLocale,
|
|
4768
|
+
ctx.slugIndex
|
|
4769
|
+
);
|
|
4770
|
+
return translated + suffix;
|
|
4771
|
+
}
|
|
4772
|
+
async function emitLinkNode2(node, ctx, instanceProps) {
|
|
4773
|
+
const style = substituteVarsInStyle(
|
|
4774
|
+
resolveStyleTemplates(
|
|
4775
|
+
node.style,
|
|
4776
|
+
instanceProps
|
|
4777
|
+
),
|
|
4778
|
+
ctx
|
|
4779
|
+
);
|
|
4780
|
+
const interactiveStyles = substituteVarsInInteractive(
|
|
4781
|
+
resolveInteractiveStyleTemplates(
|
|
4782
|
+
node.interactiveStyles,
|
|
4783
|
+
instanceProps
|
|
4784
|
+
),
|
|
4785
|
+
ctx
|
|
4786
|
+
);
|
|
3897
4787
|
let className;
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
const
|
|
4788
|
+
let comboClassNames;
|
|
4789
|
+
{
|
|
4790
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
4791
|
+
const { primaryClass, comboClasses } = mapStylesToWebflow(
|
|
3901
4792
|
elementClass,
|
|
3902
4793
|
style,
|
|
3903
4794
|
interactiveStyles,
|
|
3904
|
-
ctx.breakpoints
|
|
4795
|
+
ctx.breakpoints,
|
|
4796
|
+
ctx.responsiveScales,
|
|
4797
|
+
{ instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(ctx) }
|
|
3905
4798
|
);
|
|
4799
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
4800
|
+
applyLinkTextDecorationDefault(primaryClass);
|
|
4801
|
+
applyGridRowsDefault(primaryClass);
|
|
3906
4802
|
className = primaryClass.name;
|
|
3907
4803
|
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
4804
|
+
if (comboClasses.length > 0) {
|
|
4805
|
+
comboClassNames = [];
|
|
4806
|
+
for (const combo of comboClasses) {
|
|
4807
|
+
substituteVarsInStyleClass(combo, ctx);
|
|
4808
|
+
ctx.styleClasses.set(combo.name, combo);
|
|
4809
|
+
comboClassNames.push(combo.name);
|
|
4810
|
+
}
|
|
4811
|
+
}
|
|
4812
|
+
if (ctx.interactiveStylesMap && Array.isArray(interactiveStyles) && interactiveStyles.length > 0) {
|
|
4813
|
+
ctx.interactiveStylesMap.set(primaryClass.name, interactiveStyles);
|
|
4814
|
+
}
|
|
3908
4815
|
}
|
|
3909
4816
|
let href = "#";
|
|
3910
4817
|
if (typeof node.href === "string") {
|
|
3911
|
-
href =
|
|
4818
|
+
href = resolveStringTemplate(node.href, ctx, instanceProps);
|
|
3912
4819
|
}
|
|
4820
|
+
href = resolveLinkHref(href, ctx);
|
|
3913
4821
|
const attributes = { href };
|
|
3914
4822
|
if (node.attributes) {
|
|
3915
4823
|
for (const [key, value] of Object.entries(node.attributes)) {
|
|
3916
|
-
attributes[key] = value;
|
|
4824
|
+
attributes[key] = typeof value === "string" ? resolveStringTemplate(value, ctx, instanceProps) : value;
|
|
3917
4825
|
}
|
|
3918
4826
|
}
|
|
3919
4827
|
let children;
|
|
3920
4828
|
if (node.children) {
|
|
3921
|
-
|
|
4829
|
+
const ownColor = concreteColor(extractBaseColor(style, ctx, instanceProps));
|
|
4830
|
+
const childCtx = ownColor ? { ...ctx, inheritedColor: ownColor } : ctx;
|
|
4831
|
+
children = await convertChildren(node.children, childCtx, instanceProps);
|
|
3922
4832
|
if (children.length === 0) children = void 0;
|
|
3923
4833
|
}
|
|
3924
4834
|
const element = { tag: "a", attributes };
|
|
3925
4835
|
if (className) element.className = className;
|
|
4836
|
+
if (comboClassNames) element.comboClasses = comboClassNames;
|
|
3926
4837
|
if (children) element.children = children;
|
|
3927
4838
|
return element;
|
|
3928
4839
|
}
|
|
3929
|
-
function
|
|
4840
|
+
function singularize2(name) {
|
|
4841
|
+
if (name.endsWith("ies") && name.length > 3) return name.slice(0, -3) + "y";
|
|
4842
|
+
if (name.endsWith("s") && name.length > 1) return name.slice(0, -1);
|
|
4843
|
+
return name;
|
|
4844
|
+
}
|
|
4845
|
+
function resolveItemI18n(item, ctx) {
|
|
4846
|
+
if (!ctx.locale || !ctx.i18nConfig) return item;
|
|
4847
|
+
const out = {};
|
|
4848
|
+
for (const [k, v] of Object.entries(item)) {
|
|
4849
|
+
out[k] = isI18nValue(v) ? resolveI18nValue(v, ctx.locale, ctx.i18nConfig) : v;
|
|
4850
|
+
}
|
|
4851
|
+
return out;
|
|
4852
|
+
}
|
|
4853
|
+
async function getCollectionItemsForExport(node, source, ctx) {
|
|
4854
|
+
if (!ctx.cmsService) return [];
|
|
4855
|
+
let items = [];
|
|
4856
|
+
if (node.items) {
|
|
4857
|
+
const itemsField = node.items;
|
|
4858
|
+
let resolvedIds;
|
|
4859
|
+
if (typeof itemsField === "string" && itemsField.startsWith("{{")) {
|
|
4860
|
+
if (itemsField.startsWith("{{cms.") && ctx.cmsContext?.cms) {
|
|
4861
|
+
const fieldPath = itemsField.slice(6, -2);
|
|
4862
|
+
let value = ctx.cmsContext.cms;
|
|
4863
|
+
for (const part of fieldPath.split(".")) {
|
|
4864
|
+
if (value && typeof value === "object" && part in value) {
|
|
4865
|
+
value = value[part];
|
|
4866
|
+
} else {
|
|
4867
|
+
value = void 0;
|
|
4868
|
+
break;
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
if (value !== null && value !== void 0) {
|
|
4872
|
+
resolvedIds = Array.isArray(value) ? value.map((v) => String(v)) : String(value);
|
|
4873
|
+
}
|
|
4874
|
+
} else {
|
|
4875
|
+
resolvedIds = resolveItemsTemplate(
|
|
4876
|
+
itemsField,
|
|
4877
|
+
ctx.templateContext || { _type: "template" }
|
|
4878
|
+
);
|
|
4879
|
+
}
|
|
4880
|
+
if (!resolvedIds) return [];
|
|
4881
|
+
const ids = Array.isArray(resolvedIds) ? resolvedIds : [resolvedIds];
|
|
4882
|
+
items = await ctx.cmsService.getItemsByIds(source, ids);
|
|
4883
|
+
} else {
|
|
4884
|
+
const ids = Array.isArray(itemsField) ? itemsField : [itemsField];
|
|
4885
|
+
items = await ctx.cmsService.getItemsByIds(source, ids);
|
|
4886
|
+
}
|
|
4887
|
+
if (ctx.locale) {
|
|
4888
|
+
items = items.filter((it) => !isItemDraftForLocale(it, ctx.locale));
|
|
4889
|
+
}
|
|
4890
|
+
} else {
|
|
4891
|
+
items = await ctx.cmsService.queryItems({
|
|
4892
|
+
collection: source,
|
|
4893
|
+
filter: node.filter,
|
|
4894
|
+
sort: node.sort,
|
|
4895
|
+
limit: node.limit,
|
|
4896
|
+
offset: node.offset,
|
|
4897
|
+
excludeDraftLocale: ctx.locale
|
|
4898
|
+
});
|
|
4899
|
+
}
|
|
4900
|
+
if (node.excludeCurrentItem && ctx.cmsContext?.cms?._id) {
|
|
4901
|
+
const currentId = ctx.cmsContext.cms._id;
|
|
4902
|
+
items = items.filter((it) => it._id !== currentId);
|
|
4903
|
+
}
|
|
4904
|
+
return items;
|
|
4905
|
+
}
|
|
4906
|
+
function getPropItemsForExport(source, ctx, instanceProps) {
|
|
4907
|
+
if (source.startsWith("{{") && source.endsWith("}}")) {
|
|
4908
|
+
const path = source.slice(2, -2).trim();
|
|
4909
|
+
const ctxObj = ctx.templateContext;
|
|
4910
|
+
if (ctxObj) {
|
|
4911
|
+
const resolved = getNestedValue(ctxObj, path);
|
|
4912
|
+
if (Array.isArray(resolved)) return resolved;
|
|
4913
|
+
}
|
|
4914
|
+
if (instanceProps) {
|
|
4915
|
+
const resolved = getNestedValue(instanceProps, path);
|
|
4916
|
+
if (Array.isArray(resolved)) return resolved;
|
|
4917
|
+
}
|
|
4918
|
+
return [];
|
|
4919
|
+
}
|
|
4920
|
+
if (instanceProps && Array.isArray(instanceProps[source])) {
|
|
4921
|
+
return instanceProps[source];
|
|
4922
|
+
}
|
|
4923
|
+
if (ctx.cmsContext?.cms) {
|
|
4924
|
+
const cmsValue = ctx.cmsContext.cms[source];
|
|
4925
|
+
if (Array.isArray(cmsValue)) return cmsValue;
|
|
4926
|
+
}
|
|
4927
|
+
return [];
|
|
4928
|
+
}
|
|
4929
|
+
function buildBindingPlaceholderItem(schema) {
|
|
4930
|
+
const item = {};
|
|
4931
|
+
if (schema?.fields) {
|
|
4932
|
+
for (const fieldSlug of Object.keys(schema.fields)) {
|
|
4933
|
+
item[fieldSlug] = `${MENO_BIND_SENTINEL_PREFIX}${fieldSlug}${MENO_BIND_SENTINEL_SUFFIX}`;
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
item._id = `${MENO_BIND_SENTINEL_PREFIX}_id${MENO_BIND_SENTINEL_SUFFIX}`;
|
|
4937
|
+
item._slug = `${MENO_BIND_SENTINEL_PREFIX}_slug${MENO_BIND_SENTINEL_SUFFIX}`;
|
|
4938
|
+
item._url = `${MENO_BIND_SENTINEL_PREFIX}_url${MENO_BIND_SENTINEL_SUFFIX}`;
|
|
4939
|
+
return item;
|
|
4940
|
+
}
|
|
4941
|
+
function applyBindingMarkers(el) {
|
|
4942
|
+
if (typeof el.textContent === "string") {
|
|
4943
|
+
const exact = el.textContent.match(MENO_BIND_SENTINEL_EXACT_RE);
|
|
4944
|
+
if (exact) {
|
|
4945
|
+
const field = exact[1];
|
|
4946
|
+
el.menoBind = { ...el.menoBind || {}, textField: field };
|
|
4947
|
+
el.textContent = `{${field}}`;
|
|
4948
|
+
} else if (MENO_BIND_SENTINEL_RE.test(el.textContent)) {
|
|
4949
|
+
MENO_BIND_SENTINEL_RE.lastIndex = 0;
|
|
4950
|
+
const fields = [];
|
|
4951
|
+
el.textContent = el.textContent.replace(MENO_BIND_SENTINEL_RE, (_m, f) => {
|
|
4952
|
+
fields.push(f);
|
|
4953
|
+
return `{${f}}`;
|
|
4954
|
+
});
|
|
4955
|
+
if (fields.length) {
|
|
4956
|
+
el.menoBind = { ...el.menoBind || {}, textField: fields[0] };
|
|
4957
|
+
}
|
|
4958
|
+
}
|
|
4959
|
+
MENO_BIND_SENTINEL_RE.lastIndex = 0;
|
|
4960
|
+
}
|
|
4961
|
+
if (el.attributes) {
|
|
4962
|
+
const attrFields = el.menoBind?.attrFields || {};
|
|
4963
|
+
for (const [key, rawValue] of Object.entries(el.attributes)) {
|
|
4964
|
+
if (typeof rawValue !== "string") continue;
|
|
4965
|
+
const exact = rawValue.match(MENO_BIND_SENTINEL_EXACT_RE);
|
|
4966
|
+
if (exact) {
|
|
4967
|
+
attrFields[key] = exact[1];
|
|
4968
|
+
el.attributes[key] = `{${exact[1]}}`;
|
|
4969
|
+
continue;
|
|
4970
|
+
}
|
|
4971
|
+
MENO_BIND_SENTINEL_RE.lastIndex = 0;
|
|
4972
|
+
if (MENO_BIND_SENTINEL_RE.test(rawValue)) {
|
|
4973
|
+
MENO_BIND_SENTINEL_RE.lastIndex = 0;
|
|
4974
|
+
let firstField;
|
|
4975
|
+
const replaced = rawValue.replace(MENO_BIND_SENTINEL_RE, (_m, f) => {
|
|
4976
|
+
if (!firstField) firstField = f;
|
|
4977
|
+
return `{${f}}`;
|
|
4978
|
+
});
|
|
4979
|
+
if (firstField) attrFields[key] = firstField;
|
|
4980
|
+
el.attributes[key] = replaced;
|
|
4981
|
+
}
|
|
4982
|
+
MENO_BIND_SENTINEL_RE.lastIndex = 0;
|
|
4983
|
+
}
|
|
4984
|
+
if (Object.keys(attrFields).length > 0) {
|
|
4985
|
+
el.menoBind = { ...el.menoBind || {}, attrFields };
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
if (el.menoBind?.attrFields?.src && (el.imageDataBase64 || el.imageSrc)) {
|
|
4989
|
+
delete el.imageDataBase64;
|
|
4990
|
+
delete el.imageDataMime;
|
|
4991
|
+
delete el.imageDataFileName;
|
|
4992
|
+
delete el.imageSrc;
|
|
4993
|
+
}
|
|
4994
|
+
if (Array.isArray(el.children)) {
|
|
4995
|
+
for (const child of el.children) {
|
|
4996
|
+
if (typeof child !== "string") applyBindingMarkers(child);
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
if (Array.isArray(el.inlineFallback)) {
|
|
5000
|
+
for (const child of el.inlineFallback) applyBindingMarkers(child);
|
|
5001
|
+
}
|
|
5002
|
+
}
|
|
5003
|
+
function normalizeListChildren(elements) {
|
|
5004
|
+
if (!Array.isArray(elements)) return;
|
|
5005
|
+
for (const el of elements) {
|
|
5006
|
+
if (typeof el === "string") continue;
|
|
5007
|
+
const tag = (el.tag || "").toLowerCase();
|
|
5008
|
+
if ((tag === "ul" || tag === "ol") && Array.isArray(el.children)) {
|
|
5009
|
+
el.children = el.children.map((child) => {
|
|
5010
|
+
if (typeof child === "string") return { tag: "li", children: [child] };
|
|
5011
|
+
if ((child.tag || "").toLowerCase() === "li") return child;
|
|
5012
|
+
return { tag: "li", children: [child] };
|
|
5013
|
+
});
|
|
5014
|
+
}
|
|
5015
|
+
if (Array.isArray(el.children)) normalizeListChildren(el.children);
|
|
5016
|
+
if (Array.isArray(el.inlineFallback)) normalizeListChildren(el.inlineFallback);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
async function emitListNode2(node, ctx, instanceProps) {
|
|
5020
|
+
const nodeType = node.type;
|
|
5021
|
+
const isLegacyCMSList = nodeType === "cms-list";
|
|
5022
|
+
const sourceType = isLegacyCMSList ? "collection" : node.sourceType || "prop";
|
|
5023
|
+
if (sourceType === "collection" && !ctx.cmsService) return [];
|
|
5024
|
+
const rawSource = node.source || node.collection;
|
|
5025
|
+
const source = typeof rawSource === "string" ? rawSource : "";
|
|
5026
|
+
const sourceIsResolved = Array.isArray(rawSource);
|
|
5027
|
+
let variableName;
|
|
5028
|
+
if (node.itemAs) variableName = node.itemAs;
|
|
5029
|
+
else if (sourceType === "collection") variableName = singularize2(source);
|
|
5030
|
+
else variableName = "item";
|
|
5031
|
+
if (sourceType === "collection" && ctx.bindCollectionLists && ctx.cmsService && source) {
|
|
5032
|
+
const schema = ctx.cmsService.getSchema(source) || void 0;
|
|
5033
|
+
const placeholder = buildBindingPlaceholderItem(schema);
|
|
5034
|
+
const templateContext = buildTemplateContext(
|
|
5035
|
+
variableName,
|
|
5036
|
+
placeholder,
|
|
5037
|
+
0,
|
|
5038
|
+
1,
|
|
5039
|
+
ctx.templateContext
|
|
5040
|
+
);
|
|
5041
|
+
const childCtx = {
|
|
5042
|
+
...ctx,
|
|
5043
|
+
templateContext
|
|
5044
|
+
};
|
|
5045
|
+
const mergedProps = {
|
|
5046
|
+
...instanceProps || {},
|
|
5047
|
+
...templateContext
|
|
5048
|
+
};
|
|
5049
|
+
const renderedChildren = node.children ? await convertChildren(node.children, childCtx, mergedProps) : [];
|
|
5050
|
+
for (const child of renderedChildren) {
|
|
5051
|
+
if (typeof child !== "string") applyBindingMarkers(child);
|
|
5052
|
+
}
|
|
5053
|
+
return [{
|
|
5054
|
+
tag: COLLECTION_LIST_TAG,
|
|
5055
|
+
menoCollectionRef: source,
|
|
5056
|
+
children: renderedChildren
|
|
5057
|
+
}];
|
|
5058
|
+
}
|
|
5059
|
+
let items;
|
|
5060
|
+
if (sourceType === "collection") {
|
|
5061
|
+
items = await getCollectionItemsForExport(node, source, ctx);
|
|
5062
|
+
} else if (sourceIsResolved) {
|
|
5063
|
+
items = rawSource;
|
|
5064
|
+
} else if (source) {
|
|
5065
|
+
items = getPropItemsForExport(source, ctx, instanceProps);
|
|
5066
|
+
if (node.offset) items = items.slice(node.offset);
|
|
5067
|
+
if (node.limit) items = items.slice(0, node.limit);
|
|
5068
|
+
} else {
|
|
5069
|
+
items = [];
|
|
5070
|
+
}
|
|
5071
|
+
return expandListItems(node, ctx, instanceProps, items, variableName, source);
|
|
5072
|
+
}
|
|
5073
|
+
async function expandListItems(node, ctx, instanceProps, items, variableName, source) {
|
|
5074
|
+
if (items.length === 0) return [];
|
|
5075
|
+
const schema = ctx.cmsService ? ctx.cmsService.getSchema(source) || void 0 : void 0;
|
|
5076
|
+
const out = [];
|
|
5077
|
+
for (let i = 0; i < items.length; i++) {
|
|
5078
|
+
const rawItem = items[i];
|
|
5079
|
+
const enriched = schema && ctx.locale && ctx.i18nConfig ? addItemUrl(rawItem, schema, ctx.locale, ctx.i18nConfig) : rawItem;
|
|
5080
|
+
const item = resolveItemI18n(enriched, ctx);
|
|
5081
|
+
const templateContext = buildTemplateContext(
|
|
5082
|
+
variableName,
|
|
5083
|
+
item,
|
|
5084
|
+
i,
|
|
5085
|
+
items.length,
|
|
5086
|
+
ctx.templateContext
|
|
5087
|
+
);
|
|
5088
|
+
const childCtx = {
|
|
5089
|
+
...ctx,
|
|
5090
|
+
templateContext
|
|
5091
|
+
};
|
|
5092
|
+
const mergedProps = {
|
|
5093
|
+
...instanceProps || {},
|
|
5094
|
+
...templateContext
|
|
5095
|
+
};
|
|
5096
|
+
if (node.children) {
|
|
5097
|
+
const savedPath = [...childCtx.elementPath];
|
|
5098
|
+
childCtx.elementPath = [...savedPath, i];
|
|
5099
|
+
out.push(...await convertChildren(node.children, childCtx, mergedProps));
|
|
5100
|
+
childCtx.elementPath = savedPath;
|
|
5101
|
+
}
|
|
5102
|
+
}
|
|
5103
|
+
return out;
|
|
5104
|
+
}
|
|
5105
|
+
async function emitLocaleListNode2(node, ctx, instanceProps) {
|
|
5106
|
+
if (!ctx.slugMappings || !ctx.pagePath || !ctx.i18nConfig || !ctx.locale) {
|
|
5107
|
+
return [{ tag: "div", attributes: { "data-locale-list": "true" } }];
|
|
5108
|
+
}
|
|
5109
|
+
if (!ctx.slugIndex) {
|
|
5110
|
+
ctx.slugIndex = buildSlugIndex(ctx.slugMappings);
|
|
5111
|
+
}
|
|
5112
|
+
const localeLinks = getLocaleLinks(ctx.pagePath, ctx.locale, ctx.i18nConfig, ctx.slugIndex);
|
|
5113
|
+
const showCurrent = node.showCurrent !== false;
|
|
5114
|
+
const showSeparator = node.showSeparator !== false;
|
|
5115
|
+
const showFlag = node.showFlag !== false;
|
|
5116
|
+
const displayType = node.displayType || "nativeName";
|
|
5117
|
+
const localeIconMap = /* @__PURE__ */ new Map();
|
|
5118
|
+
for (const lc of ctx.i18nConfig.locales) {
|
|
5119
|
+
if (lc.icon) localeIconMap.set(lc.code, lc.icon);
|
|
5120
|
+
}
|
|
5121
|
+
const containerStyle = substituteVarsInStyle(
|
|
5122
|
+
resolveStyleTemplates(
|
|
5123
|
+
node.style,
|
|
5124
|
+
instanceProps
|
|
5125
|
+
),
|
|
5126
|
+
ctx
|
|
5127
|
+
);
|
|
5128
|
+
const containerInteractive = substituteVarsInInteractive(
|
|
5129
|
+
resolveInteractiveStyleTemplates(
|
|
5130
|
+
node.interactiveStyles,
|
|
5131
|
+
instanceProps
|
|
5132
|
+
),
|
|
5133
|
+
ctx
|
|
5134
|
+
);
|
|
5135
|
+
let containerClass;
|
|
5136
|
+
if (containerStyle || containerInteractive && containerInteractive.length > 0) {
|
|
5137
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
5138
|
+
const { primaryClass } = mapStylesToWebflow(
|
|
5139
|
+
elementClass,
|
|
5140
|
+
containerStyle,
|
|
5141
|
+
containerInteractive,
|
|
5142
|
+
ctx.breakpoints,
|
|
5143
|
+
ctx.responsiveScales
|
|
5144
|
+
);
|
|
5145
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
5146
|
+
containerClass = primaryClass.name;
|
|
5147
|
+
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
5148
|
+
}
|
|
5149
|
+
const buildSubClass = (style, suffix) => {
|
|
5150
|
+
const resolved = substituteVarsInStyle(
|
|
5151
|
+
resolveStyleTemplates(
|
|
5152
|
+
style,
|
|
5153
|
+
instanceProps
|
|
5154
|
+
),
|
|
5155
|
+
ctx
|
|
5156
|
+
);
|
|
5157
|
+
if (!resolved) return void 0;
|
|
5158
|
+
const className = withThemeSuffix(`${buildElementClass2(ctx, node.label)}-${suffix}`, ctx);
|
|
5159
|
+
const { primaryClass } = mapStylesToWebflow(className, resolved, void 0, ctx.breakpoints, ctx.responsiveScales);
|
|
5160
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
5161
|
+
if (Object.keys(primaryClass.base).length === 0 && !primaryClass.breakpoints && !primaryClass.pseudoStates) return void 0;
|
|
5162
|
+
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
5163
|
+
return primaryClass.name;
|
|
5164
|
+
};
|
|
5165
|
+
const itemClassName = buildSubClass(node.itemStyle, "item");
|
|
5166
|
+
const activeItemClassName = buildSubClass(node.activeItemStyle, "item-active");
|
|
5167
|
+
const separatorClassName = buildSubClass(node.separatorStyle, "separator");
|
|
5168
|
+
const flagClassName = buildSubClass(node.flagStyle, "flag");
|
|
5169
|
+
const linkChildren = [];
|
|
5170
|
+
for (let i = 0; i < localeLinks.length; i++) {
|
|
5171
|
+
const link = localeLinks[i];
|
|
5172
|
+
if (!showCurrent && link.isCurrent) continue;
|
|
5173
|
+
if (i > 0 && showSeparator) {
|
|
5174
|
+
const sep = { tag: "span" };
|
|
5175
|
+
if (separatorClassName) sep.className = separatorClassName;
|
|
5176
|
+
linkChildren.push(sep);
|
|
5177
|
+
}
|
|
5178
|
+
const anchor = {
|
|
5179
|
+
tag: "a",
|
|
5180
|
+
attributes: {
|
|
5181
|
+
href: link.path,
|
|
5182
|
+
hreflang: link.langTag,
|
|
5183
|
+
"data-current": link.isCurrent ? "true" : "false",
|
|
5184
|
+
"data-locale": link.locale
|
|
5185
|
+
}
|
|
5186
|
+
};
|
|
5187
|
+
if (link.isCurrent && (activeItemClassName || itemClassName)) {
|
|
5188
|
+
anchor.className = itemClassName;
|
|
5189
|
+
if (activeItemClassName) anchor.comboClasses = [activeItemClassName];
|
|
5190
|
+
} else if (itemClassName) {
|
|
5191
|
+
anchor.className = itemClassName;
|
|
5192
|
+
}
|
|
5193
|
+
const innerChildren = [];
|
|
5194
|
+
const icon = localeIconMap.get(link.locale);
|
|
5195
|
+
if (showFlag && icon) {
|
|
5196
|
+
const img = {
|
|
5197
|
+
tag: "img",
|
|
5198
|
+
attributes: { src: icon, alt: `${link.nativeName} flag` }
|
|
5199
|
+
};
|
|
5200
|
+
if (flagClassName) img.className = flagClassName;
|
|
5201
|
+
innerChildren.push(img);
|
|
5202
|
+
}
|
|
5203
|
+
let displayText;
|
|
5204
|
+
switch (displayType) {
|
|
5205
|
+
case "code":
|
|
5206
|
+
displayText = link.locale.toUpperCase();
|
|
5207
|
+
break;
|
|
5208
|
+
case "name":
|
|
5209
|
+
displayText = link.name;
|
|
5210
|
+
break;
|
|
5211
|
+
case "nativeName":
|
|
5212
|
+
default:
|
|
5213
|
+
displayText = link.nativeName;
|
|
5214
|
+
break;
|
|
5215
|
+
}
|
|
5216
|
+
innerChildren.push({ tag: "div", textContent: displayText });
|
|
5217
|
+
anchor.children = innerChildren;
|
|
5218
|
+
linkChildren.push(anchor);
|
|
5219
|
+
}
|
|
5220
|
+
const wrapper = {
|
|
5221
|
+
tag: "div",
|
|
5222
|
+
attributes: { "data-locale-list": "true" },
|
|
5223
|
+
children: linkChildren
|
|
5224
|
+
};
|
|
5225
|
+
if (containerClass) wrapper.className = containerClass;
|
|
5226
|
+
return [wrapper];
|
|
5227
|
+
}
|
|
5228
|
+
async function convertChildren(children, ctx, instanceProps) {
|
|
3930
5229
|
if (!children) return [];
|
|
3931
5230
|
if (typeof children === "string") {
|
|
3932
5231
|
return nodeToWebflow(children, ctx, instanceProps);
|
|
@@ -3946,7 +5245,7 @@ function scanJSONFiles2(dir, prefix = "") {
|
|
|
3946
5245
|
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
3947
5246
|
results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
3948
5247
|
} else if (entry.isDirectory()) {
|
|
3949
|
-
results.push(...scanJSONFiles2(
|
|
5248
|
+
results.push(...scanJSONFiles2(join3(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
|
|
3950
5249
|
}
|
|
3951
5250
|
}
|
|
3952
5251
|
return results;
|
|
@@ -3954,12 +5253,38 @@ function scanJSONFiles2(dir, prefix = "") {
|
|
|
3954
5253
|
function isCMSPage2(pageData) {
|
|
3955
5254
|
return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
|
|
3956
5255
|
}
|
|
3957
|
-
function
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
5256
|
+
function flattenCMSItemForLocale(item, locale, i18nConfig) {
|
|
5257
|
+
const flatten = (value) => {
|
|
5258
|
+
if (value === null || value === void 0) return value;
|
|
5259
|
+
if (isI18nValue(value)) {
|
|
5260
|
+
return flatten(resolveI18nValue(value, locale, i18nConfig));
|
|
5261
|
+
}
|
|
5262
|
+
if (typeof value === "object" && "__richtext__" in value) {
|
|
5263
|
+
const html = value.html;
|
|
5264
|
+
if (typeof html === "string") return RAW_HTML_PREFIX + html;
|
|
5265
|
+
}
|
|
5266
|
+
return value;
|
|
5267
|
+
};
|
|
5268
|
+
const out = {};
|
|
5269
|
+
for (const [key, value] of Object.entries(item)) {
|
|
5270
|
+
out[key] = flatten(value);
|
|
3961
5271
|
}
|
|
3962
|
-
return
|
|
5272
|
+
return out;
|
|
5273
|
+
}
|
|
5274
|
+
function resolveMetaString(value, locale, i18nConfig) {
|
|
5275
|
+
if (value === void 0 || value === null || value === "") return void 0;
|
|
5276
|
+
const resolved = isI18nValue(value) ? resolveI18nValue(value, locale, i18nConfig) : value;
|
|
5277
|
+
if (resolved === void 0 || resolved === null || resolved === "") return void 0;
|
|
5278
|
+
return String(resolved);
|
|
5279
|
+
}
|
|
5280
|
+
function buildPageMetaForLocale(meta, locale, i18nConfig) {
|
|
5281
|
+
return {
|
|
5282
|
+
description: resolveMetaString(meta.description, locale, i18nConfig),
|
|
5283
|
+
keywords: resolveMetaString(meta.keywords, locale, i18nConfig),
|
|
5284
|
+
ogTitle: resolveMetaString(meta.ogTitle, locale, i18nConfig),
|
|
5285
|
+
ogDescription: resolveMetaString(meta.ogDescription, locale, i18nConfig),
|
|
5286
|
+
ogImage: resolveMetaString(meta.ogImage, locale, i18nConfig)
|
|
5287
|
+
};
|
|
3963
5288
|
}
|
|
3964
5289
|
function scanAssets(projectRoot) {
|
|
3965
5290
|
const assets = [];
|
|
@@ -3970,7 +5295,7 @@ function scanAssets(projectRoot) {
|
|
|
3970
5295
|
{ dir: "assets", type: "file" }
|
|
3971
5296
|
];
|
|
3972
5297
|
for (const { dir, type } of assetDirs) {
|
|
3973
|
-
const fullDir =
|
|
5298
|
+
const fullDir = join3(projectRoot, dir);
|
|
3974
5299
|
if (!existsSync2(fullDir)) continue;
|
|
3975
5300
|
const files = scanJSONFiles2(fullDir).map((f) => f.replace(".json", ""));
|
|
3976
5301
|
const allFiles = scanAllFiles(fullDir);
|
|
@@ -3993,27 +5318,50 @@ function scanAllFiles(dir, prefix = "") {
|
|
|
3993
5318
|
if (entry.isFile()) {
|
|
3994
5319
|
results.push(relativePath);
|
|
3995
5320
|
} else if (entry.isDirectory()) {
|
|
3996
|
-
results.push(...scanAllFiles(
|
|
5321
|
+
results.push(...scanAllFiles(join3(dir, entry.name), relativePath));
|
|
3997
5322
|
}
|
|
3998
5323
|
}
|
|
3999
5324
|
return results;
|
|
4000
5325
|
}
|
|
4001
|
-
function
|
|
4002
|
-
const
|
|
4003
|
-
const
|
|
4004
|
-
for (const
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
vars[`--${
|
|
5326
|
+
function buildThemeVarMaps(themeConfig) {
|
|
5327
|
+
const palette = themeConfig.palette;
|
|
5328
|
+
const byTheme = {};
|
|
5329
|
+
for (const [themeName, theme] of Object.entries(themeConfig.themes)) {
|
|
5330
|
+
const vars = {};
|
|
5331
|
+
for (const [name, value] of Object.entries(theme.colors)) {
|
|
5332
|
+
vars[`--${name}`] = resolvePaletteColor(value, palette);
|
|
5333
|
+
}
|
|
5334
|
+
byTheme[themeName] = vars;
|
|
5335
|
+
}
|
|
5336
|
+
return { byTheme, defaultTheme: themeConfig.default };
|
|
5337
|
+
}
|
|
5338
|
+
function buildProjectVarMaps(variablesConfig, breakpoints, responsiveScales) {
|
|
5339
|
+
const out = { base: {} };
|
|
5340
|
+
for (const bpName of Object.keys(breakpoints)) out[bpName] = {};
|
|
5341
|
+
for (const variable of variablesConfig.variables) {
|
|
5342
|
+
if (!variable.cssVar) continue;
|
|
5343
|
+
out.base[variable.cssVar] = variable.value;
|
|
5344
|
+
for (const bpName of Object.keys(breakpoints)) {
|
|
5345
|
+
const resolved = resolveVariableValueAtBreakpoint(
|
|
5346
|
+
{ value: variable.value, type: variable.type, scales: variable.scales },
|
|
5347
|
+
bpName,
|
|
5348
|
+
responsiveScales
|
|
5349
|
+
);
|
|
5350
|
+
out[bpName][variable.cssVar] = resolved;
|
|
4008
5351
|
}
|
|
4009
5352
|
}
|
|
4010
|
-
return
|
|
5353
|
+
return out;
|
|
4011
5354
|
}
|
|
4012
|
-
async function buildWebflowPayload(
|
|
5355
|
+
async function buildWebflowPayload(options) {
|
|
5356
|
+
const bindCollectionLists = options?.bindCollectionLists === true;
|
|
5357
|
+
const promotedComponentNames = Array.isArray(options?.promotedComponentNames) ? new Set(options.promotedComponentNames.filter((n) => typeof n === "string" && n.length > 0)) : void 0;
|
|
4013
5358
|
configService.reset();
|
|
4014
5359
|
const projectConfig = await loadProjectConfig();
|
|
4015
5360
|
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
|
|
4016
5361
|
const i18nConfig = await loadI18nConfig();
|
|
5362
|
+
const requestedLocale = options?.locale;
|
|
5363
|
+
const selectedLocale = requestedLocale && i18nConfig.locales.some((l) => l.code === requestedLocale) ? requestedLocale : i18nConfig.defaultLocale;
|
|
5364
|
+
const localesToBuild = i18nConfig.locales.filter((l) => l.code === selectedLocale);
|
|
4017
5365
|
await migrateTemplatesDirectory();
|
|
4018
5366
|
const { components } = await loadComponentDirectory(projectPaths.components());
|
|
4019
5367
|
const globalComponents = {};
|
|
@@ -4026,8 +5374,8 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4026
5374
|
const themeConfig = await colorService.loadThemeConfig();
|
|
4027
5375
|
const variablesConfig = await variableService.loadConfig();
|
|
4028
5376
|
const breakpoints = await loadBreakpointConfig();
|
|
4029
|
-
const responsiveScales = await loadResponsiveScalesConfig();
|
|
4030
5377
|
await configService.load();
|
|
5378
|
+
const responsiveScales = configService.getResponsiveScales();
|
|
4031
5379
|
const pagesDir = projectPaths.pages();
|
|
4032
5380
|
if (!existsSync2(pagesDir)) {
|
|
4033
5381
|
return emptyPayload();
|
|
@@ -4040,7 +5388,7 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4040
5388
|
for (const file of pageFiles) {
|
|
4041
5389
|
const pageName = file.replace(".json", "");
|
|
4042
5390
|
const basePath = mapPageNameToPath(pageName);
|
|
4043
|
-
const pageContent = await loadJSONFile(
|
|
5391
|
+
const pageContent = await loadJSONFile(join3(pagesDir, file));
|
|
4044
5392
|
if (!pageContent) continue;
|
|
4045
5393
|
try {
|
|
4046
5394
|
const pageData = parseJSON(pageContent);
|
|
@@ -4053,16 +5401,22 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4053
5401
|
}
|
|
4054
5402
|
const allPages = [];
|
|
4055
5403
|
const allStyleClasses = /* @__PURE__ */ new Map();
|
|
5404
|
+
const allInteractiveStylesMap = /* @__PURE__ */ new Map();
|
|
5405
|
+
const allComboIdentityByName = /* @__PURE__ */ new Map();
|
|
5406
|
+
const promotedComponents = /* @__PURE__ */ new Map();
|
|
5407
|
+
const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
|
|
5408
|
+
const projectVars = buildProjectVarMaps(variablesConfig, breakpoints, responsiveScales);
|
|
5409
|
+
const { byTheme: themeVars, defaultTheme } = buildThemeVarMaps(themeConfig);
|
|
4056
5410
|
for (const file of pageFiles) {
|
|
4057
5411
|
const pageName = file.replace(".json", "");
|
|
4058
5412
|
const basePath = mapPageNameToPath(pageName);
|
|
4059
|
-
const pageContent = await loadJSONFile(
|
|
5413
|
+
const pageContent = await loadJSONFile(join3(pagesDir, file));
|
|
4060
5414
|
if (!pageContent) continue;
|
|
4061
5415
|
try {
|
|
4062
5416
|
const pageData = parseJSON(pageContent);
|
|
4063
5417
|
if (pageData.meta?.draft === true) continue;
|
|
4064
5418
|
const slugs = pageData.meta?.slugs;
|
|
4065
|
-
for (const localeConfig of
|
|
5419
|
+
for (const localeConfig of localesToBuild) {
|
|
4066
5420
|
const locale = localeConfig.code;
|
|
4067
5421
|
const isDefault = locale === i18nConfig.defaultLocale;
|
|
4068
5422
|
let slug;
|
|
@@ -4092,16 +5446,32 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4092
5446
|
fileType: "page",
|
|
4093
5447
|
fileName: pageName,
|
|
4094
5448
|
breakpoints,
|
|
4095
|
-
styleClasses: allStyleClasses
|
|
5449
|
+
styleClasses: allStyleClasses,
|
|
5450
|
+
comboIdentityByName: allComboIdentityByName,
|
|
5451
|
+
interactiveStylesMap: allInteractiveStylesMap,
|
|
5452
|
+
cmsService,
|
|
5453
|
+
i18nConfig,
|
|
5454
|
+
locale,
|
|
5455
|
+
slugMappings,
|
|
5456
|
+
pagePath: urlPath,
|
|
5457
|
+
themeVars,
|
|
5458
|
+
projectVars,
|
|
5459
|
+
defaultTheme,
|
|
5460
|
+
responsiveScales,
|
|
5461
|
+
promotedComponents,
|
|
5462
|
+
promotedComponentNames,
|
|
5463
|
+
bindCollectionLists
|
|
4096
5464
|
};
|
|
4097
5465
|
const body = pageData.root || pageData.node;
|
|
4098
|
-
const elements = body ? nodeToWebflow(body, ctx) : [];
|
|
5466
|
+
const elements = body ? await nodeToWebflow(body, ctx) : [];
|
|
5467
|
+
normalizeListChildren(elements);
|
|
5468
|
+
const pageMeta = extractPageMeta(pageData);
|
|
4099
5469
|
allPages.push({
|
|
4100
5470
|
title: result.title,
|
|
4101
5471
|
slug: slug || "index",
|
|
4102
|
-
metaDescription: typeof pageData.meta?.description === "string" ? pageData.meta.description : void 0,
|
|
4103
5472
|
elements,
|
|
4104
|
-
locale
|
|
5473
|
+
locale,
|
|
5474
|
+
...buildPageMetaForLocale(pageMeta, locale, i18nConfig)
|
|
4105
5475
|
});
|
|
4106
5476
|
}
|
|
4107
5477
|
} catch (error) {
|
|
@@ -4109,11 +5479,10 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4109
5479
|
}
|
|
4110
5480
|
}
|
|
4111
5481
|
const templatesDir = projectPaths.templates();
|
|
4112
|
-
const cmsCollections = [];
|
|
4113
5482
|
if (existsSync2(templatesDir)) {
|
|
4114
5483
|
const templateFiles = readdirSync2(templatesDir).filter((f) => f.endsWith(".json"));
|
|
4115
5484
|
for (const file of templateFiles) {
|
|
4116
|
-
const templateContent = await loadJSONFile(
|
|
5485
|
+
const templateContent = await loadJSONFile(join3(templatesDir, file));
|
|
4117
5486
|
if (!templateContent) continue;
|
|
4118
5487
|
try {
|
|
4119
5488
|
const pageData = parseJSON(templateContent);
|
|
@@ -4121,92 +5490,137 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4121
5490
|
if (!isCMSPage2(pageData)) continue;
|
|
4122
5491
|
const cmsSchema = pageData.meta.cms;
|
|
4123
5492
|
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
options: fieldDef.options
|
|
4133
|
-
});
|
|
4134
|
-
}
|
|
4135
|
-
}
|
|
4136
|
-
const resolvedItems = [];
|
|
4137
|
-
for (const item of items) {
|
|
4138
|
-
const resolved = {};
|
|
4139
|
-
for (const [key, value] of Object.entries(item)) {
|
|
4140
|
-
if (isI18nValue(value)) {
|
|
4141
|
-
resolved[key] = resolveI18nValue(value, i18nConfig.defaultLocale, i18nConfig);
|
|
4142
|
-
} else {
|
|
4143
|
-
resolved[key] = value;
|
|
4144
|
-
}
|
|
4145
|
-
}
|
|
4146
|
-
resolvedItems.push(resolved);
|
|
4147
|
-
}
|
|
4148
|
-
cmsCollections.push({
|
|
4149
|
-
name: cmsSchema.id,
|
|
4150
|
-
slug: cmsSchema.id,
|
|
4151
|
-
urlPattern: cmsSchema.urlPattern,
|
|
4152
|
-
fields,
|
|
4153
|
-
items: resolvedItems
|
|
4154
|
-
});
|
|
4155
|
-
for (const item of items) {
|
|
4156
|
-
for (const localeConfig of i18nConfig.locales) {
|
|
4157
|
-
const locale = localeConfig.code;
|
|
4158
|
-
if (isItemDraftForLocale(item, locale)) continue;
|
|
4159
|
-
const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
|
|
4160
|
-
const itemWithUrl = { ...item, _url: itemPath };
|
|
4161
|
-
const result = await renderPageSSR(
|
|
4162
|
-
pageData,
|
|
4163
|
-
globalComponents,
|
|
4164
|
-
itemPath,
|
|
4165
|
-
siteUrl,
|
|
4166
|
-
locale,
|
|
4167
|
-
i18nConfig,
|
|
4168
|
-
slugMappings,
|
|
4169
|
-
{ cms: itemWithUrl },
|
|
4170
|
-
cmsService,
|
|
4171
|
-
true
|
|
4172
|
-
);
|
|
4173
|
-
const ctx = {
|
|
4174
|
-
globalComponents,
|
|
4175
|
-
elementPath: [0],
|
|
4176
|
-
fileType: "page",
|
|
4177
|
-
fileName: file.replace(".json", ""),
|
|
4178
|
-
breakpoints,
|
|
4179
|
-
styleClasses: allStyleClasses
|
|
4180
|
-
};
|
|
4181
|
-
const body = pageData.root || pageData.node;
|
|
4182
|
-
const cmsProps = { cms: itemWithUrl };
|
|
4183
|
-
const elements = body ? nodeToWebflow(body, ctx, cmsProps) : [];
|
|
4184
|
-
const slug = itemPath.startsWith("/") ? itemPath.substring(1) : itemPath;
|
|
4185
|
-
allPages.push({
|
|
4186
|
-
title: result.title,
|
|
4187
|
-
slug,
|
|
4188
|
-
elements,
|
|
4189
|
-
locale
|
|
4190
|
-
});
|
|
5493
|
+
if (items.length === 0) continue;
|
|
5494
|
+
const item = items[0];
|
|
5495
|
+
const pageName = file.replace(".json", "");
|
|
5496
|
+
for (const localeConfig of localesToBuild) {
|
|
5497
|
+
const locale = localeConfig.code;
|
|
5498
|
+
let itemSlug = item[cmsSchema.slugField] ?? item._slug ?? item._id;
|
|
5499
|
+
if (isI18nValue(itemSlug)) {
|
|
5500
|
+
itemSlug = resolveI18nValue(itemSlug, locale, i18nConfig);
|
|
4191
5501
|
}
|
|
5502
|
+
const resolvedItemPath = cmsSchema.urlPattern.replace("{{slug}}", String(itemSlug));
|
|
5503
|
+
const isDefault = locale === i18nConfig.defaultLocale;
|
|
5504
|
+
const localizedItemPath = isDefault ? resolvedItemPath : `/${locale}${resolvedItemPath.startsWith("/") ? "" : "/"}${resolvedItemPath}`;
|
|
5505
|
+
const slug = localizedItemPath.startsWith("/") ? localizedItemPath.substring(1) : localizedItemPath;
|
|
5506
|
+
const urlPath = localizedItemPath;
|
|
5507
|
+
const flatItem = flattenCMSItemForLocale(item, locale, i18nConfig);
|
|
5508
|
+
const itemWithUrl = { ...flatItem, _url: urlPath };
|
|
5509
|
+
const ssrItem = { ...item, _url: urlPath };
|
|
5510
|
+
const result = await renderPageSSR(
|
|
5511
|
+
pageData,
|
|
5512
|
+
globalComponents,
|
|
5513
|
+
urlPath,
|
|
5514
|
+
siteUrl,
|
|
5515
|
+
locale,
|
|
5516
|
+
i18nConfig,
|
|
5517
|
+
slugMappings,
|
|
5518
|
+
{ cms: ssrItem },
|
|
5519
|
+
cmsService,
|
|
5520
|
+
true
|
|
5521
|
+
);
|
|
5522
|
+
const ctx = {
|
|
5523
|
+
globalComponents,
|
|
5524
|
+
elementPath: [0],
|
|
5525
|
+
fileType: "page",
|
|
5526
|
+
fileName: pageName,
|
|
5527
|
+
breakpoints,
|
|
5528
|
+
styleClasses: allStyleClasses,
|
|
5529
|
+
comboIdentityByName: allComboIdentityByName,
|
|
5530
|
+
interactiveStylesMap: allInteractiveStylesMap,
|
|
5531
|
+
cmsService,
|
|
5532
|
+
i18nConfig,
|
|
5533
|
+
locale,
|
|
5534
|
+
slugMappings,
|
|
5535
|
+
pagePath: urlPath,
|
|
5536
|
+
cmsContext: { cms: itemWithUrl },
|
|
5537
|
+
// Seed `templateContext` with the bound item so descendants inside
|
|
5538
|
+
// a component slot still see `cms`. `emitInlineComponentBody`
|
|
5539
|
+
// merges `ctx.templateContext` into the body's `instanceProps`
|
|
5540
|
+
// (nodeToWebflow.ts:1140-1143), and `<slot>` rendering forwards
|
|
5541
|
+
// those merged props to slot children — without this, anything
|
|
5542
|
+
// wrapped in (e.g.) Section loses the page-level CMS scope and
|
|
5543
|
+
// `{{cms.title}}` resolves to empty.
|
|
5544
|
+
templateContext: { cms: itemWithUrl },
|
|
5545
|
+
themeVars,
|
|
5546
|
+
projectVars,
|
|
5547
|
+
defaultTheme,
|
|
5548
|
+
responsiveScales,
|
|
5549
|
+
promotedComponents,
|
|
5550
|
+
promotedComponentNames,
|
|
5551
|
+
bindCollectionLists
|
|
5552
|
+
};
|
|
5553
|
+
const body = pageData.root || pageData.node;
|
|
5554
|
+
const elements = body ? await nodeToWebflow(body, ctx, { cms: itemWithUrl }) : [];
|
|
5555
|
+
normalizeListChildren(elements);
|
|
5556
|
+
const cmsPageMeta = extractPageMeta(pageData);
|
|
5557
|
+
allPages.push({
|
|
5558
|
+
title: result.title,
|
|
5559
|
+
slug,
|
|
5560
|
+
elements,
|
|
5561
|
+
locale,
|
|
5562
|
+
...buildPageMetaForLocale(cmsPageMeta, locale, i18nConfig)
|
|
5563
|
+
});
|
|
4192
5564
|
}
|
|
4193
5565
|
} catch (error) {
|
|
4194
5566
|
console.error(`Error processing template ${file}:`, error?.message);
|
|
4195
5567
|
}
|
|
4196
5568
|
}
|
|
4197
5569
|
}
|
|
4198
|
-
const
|
|
4199
|
-
|
|
4200
|
-
|
|
5570
|
+
for (const def of promotedComponents.values()) {
|
|
5571
|
+
normalizeListChildren(def.elements);
|
|
5572
|
+
}
|
|
5573
|
+
const styleClasses = Array.from(allStyleClasses.values());
|
|
4201
5574
|
const assets = scanAssets(projectPaths.project);
|
|
5575
|
+
const scripts = [];
|
|
5576
|
+
const cssBlocks = [];
|
|
5577
|
+
for (const [name, def] of Object.entries(globalComponents)) {
|
|
5578
|
+
const code = def.component?.javascript;
|
|
5579
|
+
if (typeof code === "string" && code.trim().length > 0) {
|
|
5580
|
+
scripts.push({
|
|
5581
|
+
componentName: name,
|
|
5582
|
+
code,
|
|
5583
|
+
defineVars: def.component?.defineVars
|
|
5584
|
+
});
|
|
5585
|
+
}
|
|
5586
|
+
const css = def.component?.css;
|
|
5587
|
+
if (typeof css === "string" && css.trim().length > 0) {
|
|
5588
|
+
cssBlocks.push(`/* ${name}.css */
|
|
5589
|
+
${css.trim()}`);
|
|
5590
|
+
}
|
|
5591
|
+
}
|
|
5592
|
+
const componentCss = cssBlocks.length > 0 ? cssBlocks.join("\n\n") : void 0;
|
|
5593
|
+
const interactiveCssBlocks = [];
|
|
5594
|
+
for (const [elementClass, rules] of allInteractiveStylesMap) {
|
|
5595
|
+
const customRules = rules.filter((r) => !isWebflowHandledRule(r));
|
|
5596
|
+
if (customRules.length === 0) continue;
|
|
5597
|
+
const css = generateInteractiveCSS(elementClass, customRules, breakpoints, void 0, responsiveScales);
|
|
5598
|
+
if (css && css.trim().length > 0) {
|
|
5599
|
+
interactiveCssBlocks.push(css);
|
|
5600
|
+
}
|
|
5601
|
+
}
|
|
5602
|
+
const interactiveCss = interactiveCssBlocks.length > 0 ? interactiveCssBlocks.join("\n\n") : void 0;
|
|
4202
5603
|
return {
|
|
4203
5604
|
version: 1,
|
|
4204
5605
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4205
5606
|
pages: allPages,
|
|
4206
|
-
styles:
|
|
4207
|
-
cms:
|
|
5607
|
+
styles: styleClasses,
|
|
5608
|
+
cms: [],
|
|
4208
5609
|
assets,
|
|
4209
|
-
|
|
5610
|
+
slugMappings: slugMappings.length > 0 ? slugMappings : void 0,
|
|
5611
|
+
scripts: scripts.length > 0 ? scripts : void 0,
|
|
5612
|
+
components: promotedComponents.size > 0 ? Array.from(promotedComponents.values()) : void 0,
|
|
5613
|
+
componentCss,
|
|
5614
|
+
interactiveCss,
|
|
5615
|
+
i18n: {
|
|
5616
|
+
defaultLocale: i18nConfig.defaultLocale,
|
|
5617
|
+
locales: i18nConfig.locales.map((l) => ({
|
|
5618
|
+
code: l.code,
|
|
5619
|
+
name: l.name,
|
|
5620
|
+
nativeName: l.nativeName
|
|
5621
|
+
})),
|
|
5622
|
+
selectedLocale
|
|
5623
|
+
}
|
|
4210
5624
|
};
|
|
4211
5625
|
}
|
|
4212
5626
|
function emptyPayload() {
|
|
@@ -4220,6 +5634,32 @@ function emptyPayload() {
|
|
|
4220
5634
|
};
|
|
4221
5635
|
}
|
|
4222
5636
|
|
|
5637
|
+
// lib/server/webflow/templateWrapper.ts
|
|
5638
|
+
import { readFile as readFile3 } from "fs/promises";
|
|
5639
|
+
var cachedTemplate = null;
|
|
5640
|
+
async function getWebflowTemplate(appName) {
|
|
5641
|
+
if (cachedTemplate) return cachedTemplate;
|
|
5642
|
+
const url = `https://webflow-ext.com/template/v2?name=${encodeURIComponent(appName)}`;
|
|
5643
|
+
const res = await fetch(url);
|
|
5644
|
+
if (!res.ok) throw new Error(`Failed to fetch Webflow template: ${res.status}`);
|
|
5645
|
+
cachedTemplate = await res.text();
|
|
5646
|
+
return cachedTemplate;
|
|
5647
|
+
}
|
|
5648
|
+
async function wrapInWebflowTemplate(html, manifestPath) {
|
|
5649
|
+
try {
|
|
5650
|
+
const manifest = JSON.parse(await readFile3(manifestPath, "utf-8"));
|
|
5651
|
+
const template = await getWebflowTemplate(manifest.name || "Meno Import");
|
|
5652
|
+
const headMatch = html.match(/<head[^>]*>([\s\S]*?)<\/head>/i);
|
|
5653
|
+
const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
|
|
5654
|
+
const headContent = headMatch ? headMatch[1] : "";
|
|
5655
|
+
const bodyContent = bodyMatch ? bodyMatch[1] : "";
|
|
5656
|
+
return template.replace("{{ui}}", headContent + bodyContent);
|
|
5657
|
+
} catch (err) {
|
|
5658
|
+
console.warn("Could not fetch Webflow wrapper template:", err.message);
|
|
5659
|
+
return html;
|
|
5660
|
+
}
|
|
5661
|
+
}
|
|
5662
|
+
|
|
4223
5663
|
// lib/server/index.ts
|
|
4224
5664
|
init_constants();
|
|
4225
5665
|
export {
|
|
@@ -4315,6 +5755,7 @@ export {
|
|
|
4315
5755
|
variableService,
|
|
4316
5756
|
withErrorHandling,
|
|
4317
5757
|
withLogging,
|
|
5758
|
+
wrapInWebflowTemplate,
|
|
4318
5759
|
writeFile
|
|
4319
5760
|
};
|
|
4320
5761
|
//# sourceMappingURL=index.js.map
|