meno-core 1.0.46 → 1.0.48
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 +13 -77
- package/dist/build-static.js +7 -7
- package/dist/chunks/{chunk-FED5MME6.js → chunk-3FHJUHAS.js} +5 -4
- package/dist/chunks/chunk-3FHJUHAS.js.map +7 -0
- package/dist/chunks/{chunk-XSWR3QLI.js → chunk-B2RTLDXY.js} +130 -130
- package/dist/chunks/chunk-B2RTLDXY.js.map +7 -0
- package/dist/chunks/{chunk-ZTKHJQ2Z.js → chunk-BJRKEPMP.js} +2 -2
- package/dist/chunks/{chunk-ORN7S4AP.js → chunk-D5E3OKSL.js} +5 -5
- package/dist/chunks/{chunk-KITQJYZV.js → chunk-EK4KESLU.js} +33 -3
- package/dist/chunks/chunk-EK4KESLU.js.map +7 -0
- package/dist/chunks/{chunk-C6U5T5S5.js → chunk-NKUV77SR.js} +43 -10
- package/dist/chunks/chunk-NKUV77SR.js.map +7 -0
- package/dist/chunks/{chunk-ZWYDT3QJ.js → chunk-NP76N4HQ.js} +4 -4
- package/dist/chunks/{chunk-ZWYDT3QJ.js.map → chunk-NP76N4HQ.js.map} +2 -2
- package/dist/chunks/{chunk-IF3RATBY.js → chunk-RQSTH2BS.js} +2 -2
- package/dist/chunks/{chunk-77ZB6353.js → chunk-TPQ7APVQ.js} +42 -86
- package/dist/chunks/chunk-TPQ7APVQ.js.map +7 -0
- package/dist/chunks/{configService-DYCUEURL.js → configService-IGJEC3MC.js} +3 -3
- package/dist/entries/server-router.js +8 -8
- package/dist/lib/client/index.js +16 -4
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +1803 -383
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +8 -4
- package/dist/lib/shared/index.js.map +1 -1
- package/lib/client/core/ComponentBuilder.test.ts +38 -0
- package/lib/client/core/ComponentBuilder.ts +25 -1
- package/lib/server/astro/astroEmitHelpers.ts +5 -0
- package/lib/server/astro/cmsPageEmitter.ts +15 -2
- package/lib/server/astro/componentEmitter.ts +13 -5
- package/lib/server/astro/nodeToAstro.ts +23 -9
- package/lib/server/astro/pageEmitter.ts +15 -2
- 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/routes/api/variables.ts +4 -2
- package/lib/server/ssr/htmlGenerator.test.ts +4 -4
- package/lib/server/ssr/htmlGenerator.ts +7 -2
- package/lib/server/ssr/imageMetadata.ts +15 -9
- package/lib/server/ssr/ssrRenderer.test.ts +103 -1
- package/lib/server/ssr/ssrRenderer.ts +41 -35
- 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/elementClassName.test.ts +15 -0
- package/lib/shared/elementClassName.ts +7 -3
- package/lib/shared/registry/nodeTypes/ListNodeType.ts +1 -1
- package/lib/shared/styleNodeUtils.test.ts +47 -1
- package/lib/shared/styleNodeUtils.ts +7 -7
- package/lib/shared/types/index.ts +1 -0
- package/lib/shared/types/variables.ts +37 -0
- package/package.json +1 -1
- package/dist/chunks/chunk-77ZB6353.js.map +0 -7
- package/dist/chunks/chunk-C6U5T5S5.js.map +0 -7
- package/dist/chunks/chunk-FED5MME6.js.map +0 -7
- package/dist/chunks/chunk-KITQJYZV.js.map +0 -7
- package/dist/chunks/chunk-XSWR3QLI.js.map +0 -7
- /package/dist/chunks/{chunk-ZTKHJQ2Z.js.map → chunk-BJRKEPMP.js.map} +0 -0
- /package/dist/chunks/{chunk-ORN7S4AP.js.map → chunk-D5E3OKSL.js.map} +0 -0
- /package/dist/chunks/{chunk-IF3RATBY.js.map → chunk-RQSTH2BS.js.map} +0 -0
- /package/dist/chunks/{configService-DYCUEURL.js.map → configService-IGJEC3MC.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-D5E3OKSL.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-NKUV77SR.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-TPQ7APVQ.js";
|
|
87
87
|
import {
|
|
88
88
|
ConfigService,
|
|
89
89
|
configService
|
|
90
|
-
} from "../../chunks/chunk-
|
|
90
|
+
} from "../../chunks/chunk-BJRKEPMP.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-ZWYDT3QJ.js";
|
|
119
|
+
import "../../chunks/chunk-RQSTH2BS.js";
|
|
122
120
|
import {
|
|
121
|
+
resolvePaletteColor
|
|
122
|
+
} from "../../chunks/chunk-EK4KESLU.js";
|
|
123
|
+
import {
|
|
124
|
+
hasTemplates,
|
|
125
|
+
isHtmlMapping,
|
|
126
|
+
processCodeTemplates,
|
|
127
|
+
resolveHtmlMapping
|
|
128
|
+
} from "../../chunks/chunk-NP76N4HQ.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-3FHJUHAS.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-B2RTLDXY.js";
|
|
141
158
|
import "../../chunks/chunk-UB44F4Z2.js";
|
|
142
159
|
import {
|
|
143
160
|
HMR_ROUTE,
|
|
@@ -740,6 +757,9 @@ function stripRawHtmlPrefixDeep(value) {
|
|
|
740
757
|
}
|
|
741
758
|
return value;
|
|
742
759
|
}
|
|
760
|
+
function astroComponentName(name) {
|
|
761
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
762
|
+
}
|
|
743
763
|
|
|
744
764
|
// lib/server/astro/nodeToAstro.ts
|
|
745
765
|
function ind(ctx) {
|
|
@@ -795,7 +815,7 @@ function emitAttrValue(key, value, ctx) {
|
|
|
795
815
|
}
|
|
796
816
|
return `${key}="${escapeJSX(value)}"`;
|
|
797
817
|
}
|
|
798
|
-
function
|
|
818
|
+
function isHtmlMapping2(value) {
|
|
799
819
|
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
800
820
|
}
|
|
801
821
|
function isResponsiveStyle2(style) {
|
|
@@ -965,7 +985,7 @@ function resolveTemplate(text, ctx) {
|
|
|
965
985
|
return `{${trimmed}}`;
|
|
966
986
|
});
|
|
967
987
|
}
|
|
968
|
-
function
|
|
988
|
+
function hasTemplates2(text) {
|
|
969
989
|
return /\{\{.+?\}\}/.test(text);
|
|
970
990
|
}
|
|
971
991
|
function buildElementClass(ctx, label) {
|
|
@@ -984,7 +1004,7 @@ function buildAttributesString(attributes, ctx) {
|
|
|
984
1004
|
if (value) parts.push(key);
|
|
985
1005
|
} else {
|
|
986
1006
|
const strVal = String(value);
|
|
987
|
-
if (
|
|
1007
|
+
if (hasTemplates2(strVal) && ctx.isComponentDef) {
|
|
988
1008
|
const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
|
|
989
1009
|
if (fullMatch) {
|
|
990
1010
|
let expr = fullMatch[1].trim();
|
|
@@ -1006,7 +1026,7 @@ function buildAttributesString(attributes, ctx) {
|
|
|
1006
1026
|
});
|
|
1007
1027
|
parts.push(`${key}={\`${resolved}\`}`);
|
|
1008
1028
|
}
|
|
1009
|
-
} else if (ctx.listItemBinding &&
|
|
1029
|
+
} else if (ctx.listItemBinding && hasTemplates2(strVal)) {
|
|
1010
1030
|
const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
|
|
1011
1031
|
if (fullMatch) {
|
|
1012
1032
|
let expr = fullMatch[1].trim();
|
|
@@ -1081,7 +1101,7 @@ function nodeToAstro(node, ctx) {
|
|
|
1081
1101
|
return `${ind(ctx)}${transformed}
|
|
1082
1102
|
`;
|
|
1083
1103
|
}
|
|
1084
|
-
if (
|
|
1104
|
+
if (hasTemplates2(node) && ctx.isComponentDef) {
|
|
1085
1105
|
return `${ind(ctx)}${resolveTemplate(node, ctx)}
|
|
1086
1106
|
`;
|
|
1087
1107
|
}
|
|
@@ -1222,7 +1242,7 @@ function imageImportPath(srcPath, fileDepth) {
|
|
|
1222
1242
|
function isStaticImageSrc(src, ctx) {
|
|
1223
1243
|
if (!src) return false;
|
|
1224
1244
|
if (typeof src !== "string") return false;
|
|
1225
|
-
if (
|
|
1245
|
+
if (hasTemplates2(src)) return false;
|
|
1226
1246
|
if (!src.startsWith("/images/")) return false;
|
|
1227
1247
|
if (!ctx.imageMetadataMap?.has(src)) return false;
|
|
1228
1248
|
return true;
|
|
@@ -1303,6 +1323,9 @@ function emitImageNode(node, ctx) {
|
|
|
1303
1323
|
let elementClass = null;
|
|
1304
1324
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1305
1325
|
elementClass = buildElementClass(ctx, node.label);
|
|
1326
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1327
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1328
|
+
}
|
|
1306
1329
|
}
|
|
1307
1330
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(
|
|
1308
1331
|
style,
|
|
@@ -1414,7 +1437,7 @@ function emitHtmlNode(node, ctx) {
|
|
|
1414
1437
|
const style = node.style;
|
|
1415
1438
|
let isDynamic = false;
|
|
1416
1439
|
let dynamicTagVar = "";
|
|
1417
|
-
if (
|
|
1440
|
+
if (hasTemplates2(tag) && ctx.isComponentDef) {
|
|
1418
1441
|
isDynamic = true;
|
|
1419
1442
|
dynamicTagVar = `Tag_${ctx.elementPath.join("_")}`;
|
|
1420
1443
|
const resolved = tag.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
@@ -1426,6 +1449,9 @@ function emitHtmlNode(node, ctx) {
|
|
|
1426
1449
|
let elementClass = null;
|
|
1427
1450
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1428
1451
|
elementClass = buildElementClass(ctx, label);
|
|
1452
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1453
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1454
|
+
}
|
|
1429
1455
|
}
|
|
1430
1456
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1431
1457
|
const attrs = buildAttributesString(node.attributes, ctx);
|
|
@@ -1444,15 +1470,15 @@ ${emitIfClose(node, ctx)}`;
|
|
|
1444
1470
|
${emitIfClose(node, ctx)}`;
|
|
1445
1471
|
}
|
|
1446
1472
|
function emitComponentInstance(node, ctx) {
|
|
1447
|
-
const name = node.component;
|
|
1448
|
-
ctx.imports.add(
|
|
1473
|
+
const name = astroComponentName(node.component);
|
|
1474
|
+
ctx.imports.add(node.component);
|
|
1449
1475
|
const ifExpr = emitIfOpen(node, ctx);
|
|
1450
1476
|
const propParts = [];
|
|
1451
1477
|
if (node.props) {
|
|
1452
1478
|
for (const [key, rawValue] of Object.entries(node.props)) {
|
|
1453
1479
|
if (key === "children") continue;
|
|
1454
1480
|
const value = resolveI18n(rawValue, ctx);
|
|
1455
|
-
if (typeof value === "string" &&
|
|
1481
|
+
if (typeof value === "string" && hasTemplates2(value) && ctx.isComponentDef) {
|
|
1456
1482
|
const fullMatch = value.match(/^\{\{(.+)\}\}$/);
|
|
1457
1483
|
if (fullMatch) {
|
|
1458
1484
|
let expr = fullMatch[1].trim();
|
|
@@ -1529,10 +1555,13 @@ function emitEmbedNode(node, ctx) {
|
|
|
1529
1555
|
let elementClass = null;
|
|
1530
1556
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1531
1557
|
elementClass = buildElementClass(ctx, node.label);
|
|
1558
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1559
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1560
|
+
}
|
|
1532
1561
|
}
|
|
1533
1562
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1534
1563
|
const attrs = buildAttributesString(node.attributes, ctx);
|
|
1535
|
-
if (
|
|
1564
|
+
if (isHtmlMapping2(node.html)) {
|
|
1536
1565
|
if (ctx.isComponentDef) {
|
|
1537
1566
|
const propRef = node.html.prop;
|
|
1538
1567
|
return `${ifExpr}${ind(ctx)}<div${classExpr.replace('"', '"oem ') || ' class="oem"'}${attrs}>
|
|
@@ -1541,7 +1570,7 @@ ${ind(ctx)}</div>
|
|
|
1541
1570
|
${emitIfClose(node, ctx)}`;
|
|
1542
1571
|
}
|
|
1543
1572
|
}
|
|
1544
|
-
if (typeof node.html === "string" &&
|
|
1573
|
+
if (typeof node.html === "string" && hasTemplates2(node.html) && ctx.isComponentDef) {
|
|
1545
1574
|
const fullMatch = node.html.match(/^\{\{(.+)\}\}$/);
|
|
1546
1575
|
if (fullMatch) {
|
|
1547
1576
|
let propRef = fullMatch[1].trim();
|
|
@@ -1582,6 +1611,9 @@ function emitLinkNode(node, ctx) {
|
|
|
1582
1611
|
let elementClass = null;
|
|
1583
1612
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1584
1613
|
elementClass = buildElementClass(ctx, node.label);
|
|
1614
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1615
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1616
|
+
}
|
|
1585
1617
|
}
|
|
1586
1618
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1587
1619
|
let finalClassExpr = classExpr;
|
|
@@ -1604,7 +1636,7 @@ function emitLinkNode(node, ctx) {
|
|
|
1604
1636
|
}
|
|
1605
1637
|
} else {
|
|
1606
1638
|
const href = typeof nodeHref === "string" ? nodeHref : "#";
|
|
1607
|
-
if (
|
|
1639
|
+
if (hasTemplates2(href) && ctx.isComponentDef) {
|
|
1608
1640
|
const fullMatch = href.match(/^\{\{(.+)\}\}$/);
|
|
1609
1641
|
if (fullMatch) {
|
|
1610
1642
|
let expr = fullMatch[1].trim();
|
|
@@ -1658,6 +1690,9 @@ function emitImageTypeNode(node, ctx) {
|
|
|
1658
1690
|
let elementClass = null;
|
|
1659
1691
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1660
1692
|
elementClass = buildElementClass(ctx, node.label);
|
|
1693
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1694
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1695
|
+
}
|
|
1661
1696
|
}
|
|
1662
1697
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(
|
|
1663
1698
|
style,
|
|
@@ -1838,6 +1873,9 @@ function emitLocaleListNode(node, ctx) {
|
|
|
1838
1873
|
let elementClass = null;
|
|
1839
1874
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1840
1875
|
elementClass = buildElementClass(ctx, node.label);
|
|
1876
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1877
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1878
|
+
}
|
|
1841
1879
|
}
|
|
1842
1880
|
const { classExpr: containerClassExpr, styleAttr: containerStyleAttr } = buildClassAndStyleExpression(
|
|
1843
1881
|
style,
|
|
@@ -2089,7 +2127,7 @@ function mergeClassNameOntoRoot(template) {
|
|
|
2089
2127
|
}
|
|
2090
2128
|
return prefix + tagName + ` class={className}` + attrs + close + template.slice(fullMatch.length);
|
|
2091
2129
|
}
|
|
2092
|
-
function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS, defaultLocale = "en", responsiveScales) {
|
|
2130
|
+
function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS, defaultLocale = "en", responsiveScales, remConfig) {
|
|
2093
2131
|
const comp = def.component;
|
|
2094
2132
|
const propDefs = comp.interface || {};
|
|
2095
2133
|
const structure = comp.structure;
|
|
@@ -2110,8 +2148,9 @@ function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREA
|
|
|
2110
2148
|
responsiveScales,
|
|
2111
2149
|
defaultLocale,
|
|
2112
2150
|
imageImports: /* @__PURE__ */ new Map(),
|
|
2113
|
-
fileDepth: 0
|
|
2151
|
+
fileDepth: 0,
|
|
2114
2152
|
// components live at src/components/
|
|
2153
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
2115
2154
|
};
|
|
2116
2155
|
let templateBody = nodeToAstro(structure, ctx);
|
|
2117
2156
|
templateBody = mergeClassNameOntoRoot(templateBody);
|
|
@@ -2127,16 +2166,21 @@ function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREA
|
|
|
2127
2166
|
<style>
|
|
2128
2167
|
${comp.css}
|
|
2129
2168
|
</style>
|
|
2169
|
+
` : "";
|
|
2170
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2171
|
+
<style is:global>
|
|
2172
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2173
|
+
</style>
|
|
2130
2174
|
` : "";
|
|
2131
2175
|
const scriptSection = comp.javascript ? buildScriptSection(comp.javascript, comp, propDefs) : "";
|
|
2132
2176
|
return `---
|
|
2133
2177
|
${frontmatter}---
|
|
2134
|
-
${templateBody}${styleSection}${scriptSection}`;
|
|
2178
|
+
${templateBody}${styleSection}${interactiveStyleSection}${scriptSection}`;
|
|
2135
2179
|
}
|
|
2136
2180
|
function buildFrontmatter(componentName, propDefs, imports, dynamicTags, i18nDefaultLocale, imageImports) {
|
|
2137
2181
|
const lines = [];
|
|
2138
2182
|
for (const imp of Array.from(imports).sort()) {
|
|
2139
|
-
lines.push(`import ${imp} from './${imp}.astro';`);
|
|
2183
|
+
lines.push(`import ${astroComponentName(imp)} from './${imp}.astro';`);
|
|
2140
2184
|
}
|
|
2141
2185
|
if (imageImports && imageImports.size > 0) {
|
|
2142
2186
|
lines.push(`import { Picture } from 'astro:assets';`);
|
|
@@ -2237,7 +2281,7 @@ function transformDefineVarsJS(js, varNames) {
|
|
|
2237
2281
|
return result;
|
|
2238
2282
|
}
|
|
2239
2283
|
function buildScriptSection(js, comp, propDefs) {
|
|
2240
|
-
const cleanTextNodes = `(function _w(n){var c=n.firstChild,x;while(c){x=c.nextSibling;if(c.nodeType===3){if(!c.textContent.trim())n.removeChild(c)}else if(c.nodeType===1)
|
|
2284
|
+
const cleanTextNodes = `(function _w(n){var c=n.firstChild,x;while(c){x=c.nextSibling;if(c.nodeType===3){if(!c.textContent.trim())n.removeChild(c)}else if(c.nodeType===1){if(c.tagName==='SCRIPT')n.removeChild(c);else _w(c)}c=x}})(el);`;
|
|
2241
2285
|
const deferWrapper = (innerJS) => `var el = document.currentScript.previousElementSibling;
|
|
2242
2286
|
function __init__() {
|
|
2243
2287
|
${cleanTextNodes}
|
|
@@ -2300,7 +2344,8 @@ function emitAstroPage(options) {
|
|
|
2300
2344
|
currentPageSlugMap,
|
|
2301
2345
|
slugMappings,
|
|
2302
2346
|
imageFormat,
|
|
2303
|
-
processedRawHtml
|
|
2347
|
+
processedRawHtml,
|
|
2348
|
+
remConfig
|
|
2304
2349
|
} = options;
|
|
2305
2350
|
const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
|
|
2306
2351
|
const root = pageData.root;
|
|
@@ -2331,7 +2376,8 @@ function emitAstroPage(options) {
|
|
|
2331
2376
|
imageFormat,
|
|
2332
2377
|
processedRawHtml,
|
|
2333
2378
|
imageImports: /* @__PURE__ */ new Map(),
|
|
2334
|
-
fileDepth
|
|
2379
|
+
fileDepth,
|
|
2380
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
2335
2381
|
};
|
|
2336
2382
|
const templateBody = nodeToAstro(root, ctx);
|
|
2337
2383
|
const importLines = [];
|
|
@@ -2350,13 +2396,18 @@ function emitAstroPage(options) {
|
|
|
2350
2396
|
const componentImports = Array.from(ctx.imports).sort();
|
|
2351
2397
|
for (const comp of componentImports) {
|
|
2352
2398
|
const path = componentImportPath(fileDepth, comp);
|
|
2353
|
-
importLines.push(`import ${comp} from '${path}';`);
|
|
2399
|
+
importLines.push(`import ${astroComponentName(comp)} from '${path}';`);
|
|
2354
2400
|
}
|
|
2355
2401
|
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
2356
2402
|
const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
|
|
2357
2403
|
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
2358
2404
|
const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
|
|
2359
2405
|
const extraFrontmatter = ctx.frontmatterLines && ctx.frontmatterLines.length > 0 ? "\n" + ctx.frontmatterLines.join("\n") : "";
|
|
2406
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2407
|
+
<style is:global>
|
|
2408
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2409
|
+
</style>
|
|
2410
|
+
` : "";
|
|
2360
2411
|
return `---
|
|
2361
2412
|
${importLines.join("\n")}${extraFrontmatter}
|
|
2362
2413
|
---
|
|
@@ -2372,7 +2423,7 @@ ${importLines.join("\n")}${extraFrontmatter}
|
|
|
2372
2423
|
<div id="root">
|
|
2373
2424
|
${templateBody} </div>
|
|
2374
2425
|
</BaseLayout>
|
|
2375
|
-
`;
|
|
2426
|
+
${interactiveStyleSection}`;
|
|
2376
2427
|
}
|
|
2377
2428
|
function buildEmptyPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths) {
|
|
2378
2429
|
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
@@ -2521,7 +2572,8 @@ function emitCMSPage(options) {
|
|
|
2521
2572
|
i18nConfig,
|
|
2522
2573
|
isMultiLocale,
|
|
2523
2574
|
slugMappings,
|
|
2524
|
-
processedRawHtml
|
|
2575
|
+
processedRawHtml,
|
|
2576
|
+
remConfig
|
|
2525
2577
|
} = options;
|
|
2526
2578
|
const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
|
|
2527
2579
|
const binding = "entry";
|
|
@@ -2569,7 +2621,8 @@ function emitCMSPage(options) {
|
|
|
2569
2621
|
imageFormat: options.imageFormat,
|
|
2570
2622
|
processedRawHtml,
|
|
2571
2623
|
imageImports: /* @__PURE__ */ new Map(),
|
|
2572
|
-
fileDepth
|
|
2624
|
+
fileDepth,
|
|
2625
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
2573
2626
|
};
|
|
2574
2627
|
const templateBody = nodeToAstro(root, ctx);
|
|
2575
2628
|
const importLines = [];
|
|
@@ -2585,7 +2638,7 @@ function emitCMSPage(options) {
|
|
|
2585
2638
|
const componentImports = Array.from(ctx.imports).sort();
|
|
2586
2639
|
for (const comp of componentImports) {
|
|
2587
2640
|
const path = componentImportPath2(fileDepth, comp);
|
|
2588
|
-
importLines.push(`import ${comp} from '${path}';`);
|
|
2641
|
+
importLines.push(`import ${astroComponentName(comp)} from '${path}';`);
|
|
2589
2642
|
}
|
|
2590
2643
|
const staticPaths = buildGetStaticPaths(cmsSchema, isMultiLocale, i18nConfig, locale);
|
|
2591
2644
|
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
@@ -2600,6 +2653,11 @@ function emitCMSPage(options) {
|
|
|
2600
2653
|
if (v && typeof v === 'object' && v._i18n) return v['${locale}'] ?? v['${i18nConfig.defaultLocale}'] ?? Object.values(v).find(x => x !== true && x !== undefined) ?? '';
|
|
2601
2654
|
return v ?? '';
|
|
2602
2655
|
}`;
|
|
2656
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2657
|
+
<style is:global>
|
|
2658
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2659
|
+
</style>
|
|
2660
|
+
` : "";
|
|
2603
2661
|
return `---
|
|
2604
2662
|
${importLines.join("\n")}
|
|
2605
2663
|
|
|
@@ -2619,7 +2677,7 @@ ${resolverHelper}
|
|
|
2619
2677
|
<div id="root">
|
|
2620
2678
|
${templateBody} </div>
|
|
2621
2679
|
</BaseLayout>
|
|
2622
|
-
`;
|
|
2680
|
+
${interactiveStyleSection}`;
|
|
2623
2681
|
}
|
|
2624
2682
|
function buildEmptyCMSPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths, cmsSchema, isMultiLocale, i18nConfig, binding, richTextFields) {
|
|
2625
2683
|
const escapedMeta = escapeTemplateLiteral3(meta);
|
|
@@ -2876,14 +2934,10 @@ import BaseLayout from '${importPath}';
|
|
|
2876
2934
|
`;
|
|
2877
2935
|
}
|
|
2878
2936
|
async function buildAstroProject(projectRoot, outputDir) {
|
|
2879
|
-
const startTime = Date.now();
|
|
2880
|
-
console.log("\u{1F3D7}\uFE0F Building Astro export...\n");
|
|
2881
2937
|
configService.reset();
|
|
2882
2938
|
const projectConfig = await loadProjectConfig();
|
|
2883
2939
|
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
|
|
2884
2940
|
const i18nConfig = await loadI18nConfig();
|
|
2885
|
-
console.log(`\u{1F310} Locales: ${i18nConfig.locales.map((l) => l.code).join(", ")} (default: ${i18nConfig.defaultLocale})
|
|
2886
|
-
`);
|
|
2887
2941
|
await migrateTemplatesDirectory();
|
|
2888
2942
|
const { components, warnings, errors: compErrors } = await loadComponentDirectory(projectPaths.components());
|
|
2889
2943
|
const globalComponents = {};
|
|
@@ -2892,24 +2946,17 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2892
2946
|
});
|
|
2893
2947
|
for (const w of warnings) console.warn(` Warning: ${w}`);
|
|
2894
2948
|
for (const e of compErrors) console.error(` Error: ${e}`);
|
|
2895
|
-
console.log(`Loaded ${components.size} global component(s)
|
|
2896
|
-
`);
|
|
2897
2949
|
const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
|
|
2898
2950
|
const cmsService = new CMSService(cmsProvider);
|
|
2899
2951
|
await cmsService.initialize();
|
|
2900
|
-
console.log("CMS service initialized\n");
|
|
2901
2952
|
const themeConfig = await colorService.loadThemeConfig();
|
|
2902
2953
|
const variablesConfig = await variableService.loadConfig();
|
|
2903
2954
|
const breakpoints = await loadBreakpointConfig();
|
|
2904
|
-
const responsiveScales = await loadResponsiveScalesConfig();
|
|
2905
2955
|
await configService.load();
|
|
2956
|
+
const responsiveScales = configService.getResponsiveScales();
|
|
2906
2957
|
const globalLibraries = configService.getLibraries();
|
|
2907
2958
|
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
2908
2959
|
const imageMetadataMap = await buildImageMetadataMap();
|
|
2909
|
-
if (imageMetadataMap.size > 0) {
|
|
2910
|
-
console.log(`Loaded image metadata for ${imageMetadataMap.size} image(s)
|
|
2911
|
-
`);
|
|
2912
|
-
}
|
|
2913
2960
|
const outDir = outputDir || join(projectPaths.project, "astro-export");
|
|
2914
2961
|
if (existsSync(outDir)) {
|
|
2915
2962
|
rmSync(outDir, { recursive: true, force: true });
|
|
@@ -2935,8 +2982,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2935
2982
|
console.warn("No pages found in ./pages directory");
|
|
2936
2983
|
return { pages: 0, cmsPages: 0, collections: 0, errors: 0 };
|
|
2937
2984
|
}
|
|
2938
|
-
console.log(`Found ${pageFiles.length} page(s) to process
|
|
2939
|
-
`);
|
|
2940
2985
|
const slugMappings = [];
|
|
2941
2986
|
for (const file of pageFiles) {
|
|
2942
2987
|
const pageName = file.replace(".json", "");
|
|
@@ -3010,7 +3055,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
3010
3055
|
const pageData = parseJSON(pageContent);
|
|
3011
3056
|
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
3012
3057
|
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
3013
|
-
console.log(` Skipping draft: ${basePath}`);
|
|
3014
3058
|
continue;
|
|
3015
3059
|
}
|
|
3016
3060
|
const slugs = pageData.meta?.slugs;
|
|
@@ -3044,7 +3088,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
3044
3088
|
// isProductionBuild
|
|
3045
3089
|
);
|
|
3046
3090
|
processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, false);
|
|
3047
|
-
console.log(` Rendered: ${urlPath}`);
|
|
3048
3091
|
}
|
|
3049
3092
|
} catch (error) {
|
|
3050
3093
|
console.error(` Error rendering ${basePath}:`, error?.message || error);
|
|
@@ -3087,16 +3130,12 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
3087
3130
|
const faviconTag = iconsConfig.favicon ? `<link rel="icon" href="${iconsConfig.favicon.replace(/"/g, """)}" />` : "";
|
|
3088
3131
|
const appleTouchIconTag = iconsConfig.appleTouchIcon ? `<link rel="apple-touch-icon" href="${iconsConfig.appleTouchIcon.replace(/"/g, """)}" />` : "";
|
|
3089
3132
|
const iconTagsHtml = [faviconTag, appleTouchIconTag].filter(Boolean).join("\n ");
|
|
3133
|
+
const remConversionConfig = configService.getRemConversion();
|
|
3090
3134
|
const templatesDir = projectPaths.templates();
|
|
3091
3135
|
const templateSchemas = [];
|
|
3092
3136
|
let cmsPageCount = 0;
|
|
3093
3137
|
if (existsSync(templatesDir)) {
|
|
3094
3138
|
const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
|
|
3095
|
-
if (templateFiles.length > 0) {
|
|
3096
|
-
console.log(`
|
|
3097
|
-
Processing ${templateFiles.length} CMS template(s)...
|
|
3098
|
-
`);
|
|
3099
|
-
}
|
|
3100
3139
|
for (const file of templateFiles) {
|
|
3101
3140
|
const templateContent = await loadJSONFile(join(templatesDir, file));
|
|
3102
3141
|
if (!templateContent) continue;
|
|
@@ -3104,7 +3143,6 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3104
3143
|
const pageData = parseJSON(templateContent);
|
|
3105
3144
|
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
3106
3145
|
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
3107
|
-
console.log(` Skipping draft template: ${file}`);
|
|
3108
3146
|
continue;
|
|
3109
3147
|
}
|
|
3110
3148
|
if (!isCMSPage(pageData)) {
|
|
@@ -3113,14 +3151,8 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3113
3151
|
}
|
|
3114
3152
|
const cmsSchema = pageData.meta.cms;
|
|
3115
3153
|
templateSchemas.push(cmsSchema);
|
|
3116
|
-
console.log(` CMS Collection: ${cmsSchema.id}`);
|
|
3117
3154
|
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
3118
3155
|
const itemCount = items.length;
|
|
3119
|
-
if (itemCount === 0) {
|
|
3120
|
-
console.log(` No items found in cms/${cmsSchema.id}/`);
|
|
3121
|
-
} else {
|
|
3122
|
-
console.log(` Found ${itemCount} item(s)`);
|
|
3123
|
-
}
|
|
3124
3156
|
const defaultLocale = i18nConfig.defaultLocale;
|
|
3125
3157
|
const dummyPath = cmsSchema.urlPattern.replace("{{slug}}", "__placeholder__");
|
|
3126
3158
|
const metaResult = await renderPageSSR(
|
|
@@ -3188,7 +3220,8 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3188
3220
|
// Each file handles one locale
|
|
3189
3221
|
slugMappings,
|
|
3190
3222
|
imageFormat: configService.getImageFormat(),
|
|
3191
|
-
processedRawHtml: metaResult.processedRawHtmlCollector
|
|
3223
|
+
processedRawHtml: metaResult.processedRawHtmlCollector,
|
|
3224
|
+
remConfig: remConversionConfig
|
|
3192
3225
|
});
|
|
3193
3226
|
const astroFileFull = join(pagesOutDir, astroFilePath);
|
|
3194
3227
|
const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
|
|
@@ -3197,7 +3230,6 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3197
3230
|
}
|
|
3198
3231
|
await writeFile2(astroFileFull, astroContent, "utf-8");
|
|
3199
3232
|
}
|
|
3200
|
-
console.log(` Generated: ${pathPrefix}[slug].astro (${itemCount} items \xD7 ${localesToEmit.length} locale(s))`);
|
|
3201
3233
|
cmsPageCount += itemCount * i18nConfig.locales.length;
|
|
3202
3234
|
} catch (error) {
|
|
3203
3235
|
console.error(` Error processing template ${file}:`, error?.message || error);
|
|
@@ -3209,16 +3241,14 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3209
3241
|
const fontCSS = generateFontCSS();
|
|
3210
3242
|
const themeColorCSS = generateThemeColorVariablesCSS(themeConfig);
|
|
3211
3243
|
const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
|
|
3212
|
-
const remConversionConfig = configService.getRemConversion();
|
|
3213
|
-
const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints, remConversionConfig, responsiveScales);
|
|
3214
3244
|
const componentCSSCombined = Array.from(allComponentCSS).join("\n");
|
|
3215
3245
|
const baseCSS = `@layer base {
|
|
3216
3246
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
3217
3247
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; }
|
|
3218
3248
|
button { background: none; border: none; padding: 0; font: inherit; cursor: pointer; outline: inherit; }
|
|
3219
|
-
img {
|
|
3249
|
+
img { max-width: 100%; height: auto; }
|
|
3220
3250
|
picture { display: block; }
|
|
3221
|
-
.olink { text-decoration: none; display: block; }
|
|
3251
|
+
.olink { text-decoration: none; display: block; color: inherit; }
|
|
3222
3252
|
.oem { display: inline-block; }
|
|
3223
3253
|
}`;
|
|
3224
3254
|
const safelistClasses = Array.from(mappingClasses);
|
|
@@ -3226,10 +3256,8 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
3226
3256
|
const tailwindDirectives = safelistDirectives ? `@import "tailwindcss";
|
|
3227
3257
|
|
|
3228
3258
|
${safelistDirectives}` : `@import "tailwindcss";`;
|
|
3229
|
-
const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined
|
|
3259
|
+
const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined].filter(Boolean).join("\n\n");
|
|
3230
3260
|
await writeFile2(join(stylesDir, "global.css"), globalCSS, "utf-8");
|
|
3231
|
-
console.log(`
|
|
3232
|
-
Generated global.css (${(globalCSS.length / 1024).toFixed(1)} KB)`);
|
|
3233
3261
|
const escForTemplateLiteral = (s) => s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3234
3262
|
const customHeadLiteral = escForTemplateLiteral(customCode.head || "");
|
|
3235
3263
|
const customBodyStartLiteral = escForTemplateLiteral(customCode.bodyStart || "");
|
|
@@ -3277,18 +3305,16 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
3277
3305
|
</html>
|
|
3278
3306
|
`;
|
|
3279
3307
|
await writeFile2(join(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
|
|
3280
|
-
console.log("Generated BaseLayout.astro");
|
|
3281
3308
|
let componentFileCount = 0;
|
|
3282
3309
|
for (const [compName, compDef] of Object.entries(globalComponents)) {
|
|
3283
3310
|
try {
|
|
3284
|
-
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale, responsiveScales);
|
|
3311
|
+
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale, responsiveScales, remConversionConfig);
|
|
3285
3312
|
await writeFile2(join(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
|
|
3286
3313
|
componentFileCount++;
|
|
3287
3314
|
} catch (error) {
|
|
3288
3315
|
console.warn(` Warning: could not generate component ${compName}: ${error?.message}`);
|
|
3289
3316
|
}
|
|
3290
3317
|
}
|
|
3291
|
-
console.log(`Generated ${componentFileCount} component .astro file(s)`);
|
|
3292
3318
|
for (const result of allResults) {
|
|
3293
3319
|
const importPath = layoutImportPath(result.fileDepth);
|
|
3294
3320
|
let scriptPaths = [];
|
|
@@ -3318,7 +3344,8 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
3318
3344
|
currentPageSlugMap: pageSlugMap,
|
|
3319
3345
|
slugMappings: i18nConfig.locales.length > 1 ? slugMappings : void 0,
|
|
3320
3346
|
imageFormat: configService.getImageFormat(),
|
|
3321
|
-
processedRawHtml: result.processedRawHtmlCollector
|
|
3347
|
+
processedRawHtml: result.processedRawHtmlCollector,
|
|
3348
|
+
remConfig: remConversionConfig
|
|
3322
3349
|
});
|
|
3323
3350
|
} catch (error) {
|
|
3324
3351
|
console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
|
|
@@ -3336,7 +3363,6 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
3336
3363
|
}
|
|
3337
3364
|
await writeFile2(astroFileFull, astroContent, "utf-8");
|
|
3338
3365
|
}
|
|
3339
|
-
console.log(`Generated ${allResults.length} .astro page file(s)`);
|
|
3340
3366
|
const robotsTsContent = `import type { APIRoute } from 'astro';
|
|
3341
3367
|
|
|
3342
3368
|
export const GET: APIRoute = () => {
|
|
@@ -3354,7 +3380,6 @@ export const GET: APIRoute = () => {
|
|
|
3354
3380
|
};
|
|
3355
3381
|
`;
|
|
3356
3382
|
await writeFile2(join(pagesOutDir, "robots.txt.ts"), robotsTsContent, "utf-8");
|
|
3357
|
-
console.log("Generated robots.txt.ts endpoint");
|
|
3358
3383
|
let collectionCount = 0;
|
|
3359
3384
|
if (templateSchemas.length > 0) {
|
|
3360
3385
|
const contentDir = join(srcDir, "content");
|
|
@@ -3407,27 +3432,22 @@ ${collectionDefs.join(",\n")}
|
|
|
3407
3432
|
export { collections };
|
|
3408
3433
|
`;
|
|
3409
3434
|
await writeFile2(join(srcDir, "content.config.ts"), configContent, "utf-8");
|
|
3410
|
-
console.log(`Generated ${collectionCount} content collection(s) with content.config.ts`);
|
|
3411
3435
|
}
|
|
3412
|
-
let copiedAssets = 0;
|
|
3413
3436
|
const imagesSrcDir = join(projectPaths.project, "images");
|
|
3414
3437
|
if (existsSync(imagesSrcDir)) {
|
|
3415
3438
|
copyDirectory(imagesSrcDir, join(srcDir, "assets", "images"), shouldCopyImageForAstro);
|
|
3416
3439
|
copyDirectory(imagesSrcDir, join(publicDir, "images"));
|
|
3417
|
-
copiedAssets++;
|
|
3418
3440
|
}
|
|
3419
3441
|
const publicAssetDirs = ["fonts", "icons", "videos", "assets"];
|
|
3420
3442
|
for (const dir of publicAssetDirs) {
|
|
3421
3443
|
const srcAssetDir = join(projectPaths.project, dir);
|
|
3422
3444
|
if (existsSync(srcAssetDir)) {
|
|
3423
3445
|
copyDirectory(srcAssetDir, join(publicDir, dir));
|
|
3424
|
-
copiedAssets++;
|
|
3425
3446
|
}
|
|
3426
3447
|
}
|
|
3427
3448
|
const librariesDir = join(projectPaths.project, "libraries");
|
|
3428
3449
|
if (existsSync(librariesDir)) {
|
|
3429
3450
|
copyDirectory(librariesDir, join(publicDir, "libraries"));
|
|
3430
|
-
copiedAssets++;
|
|
3431
3451
|
}
|
|
3432
3452
|
for (const relPath of localLibsToCopy) {
|
|
3433
3453
|
const srcPath = join(projectPaths.project, relPath);
|
|
@@ -3435,10 +3455,6 @@ export { collections };
|
|
|
3435
3455
|
const destDir = destPath.substring(0, destPath.lastIndexOf("/"));
|
|
3436
3456
|
if (destDir && !existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
3437
3457
|
copyFileSync(srcPath, destPath);
|
|
3438
|
-
copiedAssets++;
|
|
3439
|
-
}
|
|
3440
|
-
if (copiedAssets > 0) {
|
|
3441
|
-
console.log(`Copied ${copiedAssets} asset director${copiedAssets === 1 ? "y" : "ies"} to public/`);
|
|
3442
3458
|
}
|
|
3443
3459
|
const packageJson = {
|
|
3444
3460
|
name: "astro-export",
|
|
@@ -3487,28 +3503,8 @@ export default defineConfig({${siteUrl ? `
|
|
|
3487
3503
|
extends: "astro/tsconfigs/strict"
|
|
3488
3504
|
};
|
|
3489
3505
|
await writeFile2(join(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
|
|
3490
|
-
|
|
3491
|
-
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
3506
|
+
await writeFile2(join(outDir, "src", "env.d.ts"), '/// <reference path="../.astro/types.d.ts" />\n', "utf-8");
|
|
3492
3507
|
const totalPages = allResults.length;
|
|
3493
|
-
console.log("\n" + "=".repeat(50));
|
|
3494
|
-
console.log("Astro export complete!");
|
|
3495
|
-
console.log(` Pages: ${totalPages - cmsPageCount}`);
|
|
3496
|
-
if (cmsPageCount > 0) {
|
|
3497
|
-
console.log(` CMS pages: ${cmsPageCount}`);
|
|
3498
|
-
}
|
|
3499
|
-
if (collectionCount > 0) {
|
|
3500
|
-
console.log(` Content collections: ${collectionCount}`);
|
|
3501
|
-
}
|
|
3502
|
-
if (errorCount > 0) {
|
|
3503
|
-
console.log(` Errors: ${errorCount}`);
|
|
3504
|
-
}
|
|
3505
|
-
console.log(` SEO: sitemap (@astrojs/sitemap), robots.txt`);
|
|
3506
|
-
if (projectNeedsFormHandler) {
|
|
3507
|
-
console.log(` Forms: fetch handler injected`);
|
|
3508
|
-
}
|
|
3509
|
-
console.log(` Time: ${elapsed}s`);
|
|
3510
|
-
console.log(` Output: ${outDir}`);
|
|
3511
|
-
console.log("");
|
|
3512
3508
|
return {
|
|
3513
3509
|
pages: totalPages - cmsPageCount,
|
|
3514
3510
|
cmsPages: cmsPageCount,
|
|
@@ -3519,38 +3515,19 @@ export default defineConfig({${siteUrl ? `
|
|
|
3519
3515
|
|
|
3520
3516
|
// lib/server/webflow/buildWebflow.ts
|
|
3521
3517
|
import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
|
|
3522
|
-
import { join as
|
|
3523
|
-
|
|
3524
|
-
// lib/server/webflow/types.ts
|
|
3525
|
-
function mapCMSFieldType(menoType) {
|
|
3526
|
-
switch (menoType) {
|
|
3527
|
-
case "string":
|
|
3528
|
-
return "PlainText";
|
|
3529
|
-
case "text":
|
|
3530
|
-
case "rich-text":
|
|
3531
|
-
return "RichText";
|
|
3532
|
-
case "number":
|
|
3533
|
-
return "Number";
|
|
3534
|
-
case "boolean":
|
|
3535
|
-
return "Switch";
|
|
3536
|
-
case "image":
|
|
3537
|
-
return "Image";
|
|
3538
|
-
case "date":
|
|
3539
|
-
return "Date";
|
|
3540
|
-
case "select":
|
|
3541
|
-
return "Option";
|
|
3542
|
-
case "file":
|
|
3543
|
-
return "File";
|
|
3544
|
-
case "reference":
|
|
3545
|
-
return "Reference";
|
|
3546
|
-
default:
|
|
3547
|
-
return "PlainText";
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3518
|
+
import { join as join3 } from "path";
|
|
3519
|
+
init_constants();
|
|
3550
3520
|
|
|
3551
3521
|
// lib/server/webflow/nodeToWebflow.ts
|
|
3552
3522
|
init_constants();
|
|
3553
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
|
+
|
|
3554
3531
|
// lib/server/webflow/styleMapper.ts
|
|
3555
3532
|
var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
|
|
3556
3533
|
"opacity",
|
|
@@ -3565,6 +3542,28 @@ var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
|
|
|
3565
3542
|
"font-weight",
|
|
3566
3543
|
"tab-size"
|
|
3567
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
|
+
}
|
|
3568
3567
|
function isStyleMapping4(value) {
|
|
3569
3568
|
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
3570
3569
|
}
|
|
@@ -3574,6 +3573,65 @@ function isResponsiveStyle4(style) {
|
|
|
3574
3573
|
function toKebabCase(prop) {
|
|
3575
3574
|
return prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
3576
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
|
+
}
|
|
3577
3635
|
function styleObjectToCSS(style) {
|
|
3578
3636
|
const css = {};
|
|
3579
3637
|
for (const [prop, value] of Object.entries(style)) {
|
|
@@ -3581,11 +3639,18 @@ function styleObjectToCSS(style) {
|
|
|
3581
3639
|
if (value === "" || value === void 0 || value === null) continue;
|
|
3582
3640
|
if (typeof value === "boolean" || typeof value === "object") continue;
|
|
3583
3641
|
const cssProp = toKebabCase(prop);
|
|
3642
|
+
let cssValue;
|
|
3584
3643
|
if (typeof value === "number") {
|
|
3585
3644
|
if (isNaN(value)) continue;
|
|
3586
|
-
|
|
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);
|
|
3587
3652
|
} else {
|
|
3588
|
-
css[cssProp] =
|
|
3653
|
+
css[cssProp] = normalizeZero(cssProp, cssValue);
|
|
3589
3654
|
}
|
|
3590
3655
|
}
|
|
3591
3656
|
return css;
|
|
@@ -3612,14 +3677,85 @@ function collectStyleMappings2(style) {
|
|
|
3612
3677
|
return result;
|
|
3613
3678
|
}
|
|
3614
3679
|
function postfixToPseudoState(postfix) {
|
|
3615
|
-
if (postfix.includes(":hover")) return "hover";
|
|
3616
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";
|
|
3617
3691
|
if (postfix.includes(":focus")) return "focus";
|
|
3618
3692
|
if (postfix.includes(":active")) return "active";
|
|
3619
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";
|
|
3620
3698
|
return null;
|
|
3621
3699
|
}
|
|
3622
|
-
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 ?? "";
|
|
3623
3759
|
const webflowClassName = className.replace(/_/g, "-");
|
|
3624
3760
|
const primaryClass = {
|
|
3625
3761
|
name: webflowClassName,
|
|
@@ -3631,21 +3767,12 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
|
|
|
3631
3767
|
if (responsive.base) {
|
|
3632
3768
|
primaryClass.base = styleObjectToCSS(responsive.base);
|
|
3633
3769
|
}
|
|
3634
|
-
if (responsive.tablet) {
|
|
3635
|
-
if (!primaryClass.breakpoints) primaryClass.breakpoints = {};
|
|
3636
|
-
primaryClass.breakpoints.Tablet = styleObjectToCSS(responsive.tablet);
|
|
3637
|
-
}
|
|
3638
|
-
if (responsive.mobile) {
|
|
3639
|
-
if (!primaryClass.breakpoints) primaryClass.breakpoints = {};
|
|
3640
|
-
primaryClass.breakpoints.MobilePortrait = styleObjectToCSS(responsive.mobile);
|
|
3641
|
-
}
|
|
3642
3770
|
for (const [bpName, bpStyle] of Object.entries(responsive)) {
|
|
3643
|
-
if (!bpStyle || bpName === "base"
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
};
|
|
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);
|
|
3649
3776
|
}
|
|
3650
3777
|
} else {
|
|
3651
3778
|
primaryClass.base = styleObjectToCSS(style);
|
|
@@ -3653,92 +3780,546 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
|
|
|
3653
3780
|
}
|
|
3654
3781
|
if (interactiveStyles && interactiveStyles.length > 0) {
|
|
3655
3782
|
for (const rule of interactiveStyles) {
|
|
3656
|
-
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;
|
|
3657
3786
|
const pseudoState = postfixToPseudoState(rule.postfix);
|
|
3658
3787
|
if (!pseudoState) continue;
|
|
3659
|
-
const ruleStyle = rule.style;
|
|
3660
3788
|
if (!primaryClass.pseudoStates) primaryClass.pseudoStates = {};
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
...primaryClass.pseudoStates[pseudoState],
|
|
3666
|
-
...styleObjectToCSS(responsive.base)
|
|
3667
|
-
};
|
|
3668
|
-
}
|
|
3669
|
-
} else {
|
|
3670
|
-
primaryClass.pseudoStates[pseudoState] = {
|
|
3671
|
-
...primaryClass.pseudoStates[pseudoState],
|
|
3672
|
-
...styleObjectToCSS(ruleStyle)
|
|
3673
|
-
};
|
|
3674
|
-
}
|
|
3789
|
+
primaryClass.pseudoStates[pseudoState] = {
|
|
3790
|
+
...primaryClass.pseudoStates[pseudoState],
|
|
3791
|
+
...baseProps
|
|
3792
|
+
};
|
|
3675
3793
|
}
|
|
3676
3794
|
}
|
|
3677
3795
|
const comboClasses = [];
|
|
3678
3796
|
const mappings = collectStyleMappings2(style);
|
|
3797
|
+
const comboCss = {};
|
|
3798
|
+
const comboNameParts = [];
|
|
3679
3799
|
for (const { property, mapping } of mappings) {
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
const
|
|
3684
|
-
|
|
3685
|
-
base
|
|
3686
|
-
|
|
3687
|
-
},
|
|
3688
|
-
comboParent: webflowClassName
|
|
3689
|
-
};
|
|
3690
|
-
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
|
+
}
|
|
3691
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);
|
|
3692
3831
|
}
|
|
3693
3832
|
return { primaryClass, comboClasses };
|
|
3694
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
|
+
}
|
|
3695
3840
|
function sanitizeClassName(name) {
|
|
3696
3841
|
return name.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
3697
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
|
+
}
|
|
3698
3886
|
|
|
3699
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"]);
|
|
3700
3891
|
function buildElementClass2(ctx, label) {
|
|
3701
|
-
|
|
3892
|
+
const generated = generateElementClassName({
|
|
3702
3893
|
fileType: ctx.fileType,
|
|
3703
3894
|
fileName: ctx.fileName,
|
|
3704
3895
|
label,
|
|
3705
3896
|
path: ctx.elementPath
|
|
3706
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;
|
|
3707
3937
|
}
|
|
3708
|
-
function
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3938
|
+
function buildTemplateProps(ctx, instanceProps) {
|
|
3939
|
+
return {
|
|
3940
|
+
...ctx.templateContext ?? {},
|
|
3941
|
+
...ctx.cmsContext ?? {},
|
|
3942
|
+
...ctx.componentDefaults ?? {},
|
|
3943
|
+
...ctx.slotInstanceProps ?? {},
|
|
3944
|
+
...instanceProps ?? {}
|
|
3945
|
+
};
|
|
3946
|
+
}
|
|
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;
|
|
3725
4059
|
}
|
|
3726
|
-
function
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
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;
|
|
3732
4081
|
}
|
|
3733
4082
|
return current;
|
|
3734
4083
|
}
|
|
3735
|
-
function
|
|
3736
|
-
|
|
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] ?? "" };
|
|
4248
|
+
}
|
|
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
|
+
}));
|
|
3737
4317
|
}
|
|
3738
|
-
function nodeToWebflow(node, ctx, instanceProps) {
|
|
4318
|
+
async function nodeToWebflow(node, ctx, instanceProps) {
|
|
3739
4319
|
if (node === null || node === void 0) return [];
|
|
3740
4320
|
if (typeof node === "string") {
|
|
3741
|
-
const text =
|
|
4321
|
+
const text = resolveStringTemplate(node, ctx, instanceProps);
|
|
4322
|
+
if (text === "" || text.trim() === "") return [];
|
|
3742
4323
|
return [{ tag: "span", textContent: text }];
|
|
3743
4324
|
}
|
|
3744
4325
|
if (typeof node === "number") {
|
|
@@ -3750,88 +4331,114 @@ function nodeToWebflow(node, ctx, instanceProps) {
|
|
|
3750
4331
|
const child = node[i];
|
|
3751
4332
|
const savedPath = [...ctx.elementPath];
|
|
3752
4333
|
ctx.elementPath = [...ctx.elementPath, i];
|
|
3753
|
-
results.push(...nodeToWebflow(child, ctx, instanceProps));
|
|
4334
|
+
results.push(...await nodeToWebflow(child, ctx, instanceProps));
|
|
3754
4335
|
ctx.elementPath = savedPath;
|
|
3755
4336
|
}
|
|
3756
4337
|
return results;
|
|
3757
4338
|
}
|
|
4339
|
+
if (!shouldRenderNode(node, instanceProps)) return [];
|
|
3758
4340
|
switch (node.type) {
|
|
3759
4341
|
case NODE_TYPE.NODE:
|
|
3760
|
-
return [emitHtmlNode2(node, ctx, instanceProps)];
|
|
4342
|
+
return [await emitHtmlNode2(node, ctx, instanceProps)];
|
|
3761
4343
|
case NODE_TYPE.COMPONENT:
|
|
3762
4344
|
return emitComponentInstance2(node, ctx, instanceProps);
|
|
3763
4345
|
case NODE_TYPE.SLOT:
|
|
3764
4346
|
return emitSlotMarker2(node, ctx, instanceProps);
|
|
3765
4347
|
case NODE_TYPE.EMBED:
|
|
3766
|
-
return [emitEmbedNode2(node, ctx, instanceProps)];
|
|
4348
|
+
return [await emitEmbedNode2(node, ctx, instanceProps)];
|
|
3767
4349
|
case NODE_TYPE.LINK:
|
|
3768
|
-
return [emitLinkNode2(node, ctx, instanceProps)];
|
|
4350
|
+
return [await emitLinkNode2(node, ctx, instanceProps)];
|
|
3769
4351
|
case NODE_TYPE.LIST:
|
|
3770
4352
|
case "cms-list":
|
|
4353
|
+
return emitListNode2(node, ctx, instanceProps);
|
|
3771
4354
|
case NODE_TYPE.LOCALE_LIST:
|
|
3772
|
-
return
|
|
4355
|
+
return emitLocaleListNode2(node, ctx, instanceProps);
|
|
3773
4356
|
default:
|
|
3774
4357
|
return [];
|
|
3775
4358
|
}
|
|
3776
4359
|
}
|
|
3777
|
-
function emitHtmlNode2(node, ctx, instanceProps) {
|
|
3778
|
-
const tag =
|
|
3779
|
-
const
|
|
3780
|
-
|
|
3781
|
-
|
|
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;
|
|
3782
4390
|
let className;
|
|
3783
4391
|
let comboClassNames;
|
|
3784
4392
|
if (needsClass) {
|
|
3785
|
-
const elementClass = buildElementClass2(ctx, node.label);
|
|
4393
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), themedCtx);
|
|
3786
4394
|
const { primaryClass, comboClasses } = mapStylesToWebflow(
|
|
3787
4395
|
elementClass,
|
|
3788
4396
|
style,
|
|
3789
4397
|
interactiveStyles,
|
|
3790
|
-
ctx.breakpoints
|
|
4398
|
+
ctx.breakpoints,
|
|
4399
|
+
ctx.responsiveScales,
|
|
4400
|
+
{ instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(themedCtx) }
|
|
3791
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);
|
|
3792
4408
|
className = primaryClass.name;
|
|
3793
4409
|
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
3794
4410
|
if (comboClasses.length > 0) {
|
|
3795
4411
|
comboClassNames = [];
|
|
3796
4412
|
for (const combo of comboClasses) {
|
|
4413
|
+
substituteVarsInStyleClass(combo, themedCtx);
|
|
3797
4414
|
ctx.styleClasses.set(combo.name, combo);
|
|
3798
4415
|
comboClassNames.push(combo.name);
|
|
3799
4416
|
}
|
|
3800
4417
|
}
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
if (node.attributes) {
|
|
3804
|
-
for (const [key, value] of Object.entries(node.attributes)) {
|
|
3805
|
-
if (instanceProps && typeof value === "string" && hasTemplates2(value)) {
|
|
3806
|
-
attributes[key] = resolveTemplate2(value, instanceProps);
|
|
3807
|
-
} else {
|
|
3808
|
-
attributes[key] = value;
|
|
3809
|
-
}
|
|
4418
|
+
if (ctx.interactiveStylesMap && Array.isArray(interactiveStyles) && interactiveStyles.length > 0) {
|
|
4419
|
+
ctx.interactiveStylesMap.set(primaryClass.name, interactiveStyles);
|
|
3810
4420
|
}
|
|
3811
4421
|
}
|
|
3812
4422
|
let children;
|
|
3813
4423
|
let textContent;
|
|
3814
4424
|
if (!isVoidElement(tag) && node.children) {
|
|
3815
4425
|
if (typeof node.children === "string") {
|
|
3816
|
-
textContent =
|
|
4426
|
+
textContent = resolveStringTemplate(node.children, ctx, instanceProps);
|
|
3817
4427
|
} else if (Array.isArray(node.children) && node.children.length === 1 && typeof node.children[0] === "string") {
|
|
3818
4428
|
const text = node.children[0];
|
|
3819
|
-
textContent =
|
|
4429
|
+
textContent = resolveStringTemplate(text, ctx, instanceProps);
|
|
3820
4430
|
} else {
|
|
3821
|
-
const innerCtx = { ...
|
|
3822
|
-
|
|
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);
|
|
3823
4435
|
if (children.length === 0) children = void 0;
|
|
3824
4436
|
}
|
|
3825
4437
|
}
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
if (
|
|
3829
|
-
|
|
3830
|
-
conditional = { prop: ifValue.prop, condition: "truthy" };
|
|
3831
|
-
} else if (typeof ifValue === "string") {
|
|
3832
|
-
const match = ifValue.match(/^\{\{(.+)\}\}$/);
|
|
3833
|
-
conditional = { prop: match ? match[1].trim() : ifValue, condition: "truthy" };
|
|
3834
|
-
}
|
|
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);
|
|
3835
4442
|
}
|
|
3836
4443
|
const element = { tag };
|
|
3837
4444
|
if (className) element.className = className;
|
|
@@ -3839,115 +4446,786 @@ function emitHtmlNode2(node, ctx, instanceProps) {
|
|
|
3839
4446
|
if (textContent) element.textContent = textContent;
|
|
3840
4447
|
if (children) element.children = children;
|
|
3841
4448
|
if (Object.keys(attributes).length > 0) element.attributes = attributes;
|
|
3842
|
-
if (
|
|
4449
|
+
if (tag.toLowerCase() === "img" && typeof attributes.src === "string") {
|
|
4450
|
+
await maybeInlineLocalImage(element, attributes.src);
|
|
4451
|
+
}
|
|
3843
4452
|
return element;
|
|
3844
4453
|
}
|
|
3845
|
-
function emitComponentInstance2(node, ctx, parentProps) {
|
|
4454
|
+
async function emitComponentInstance2(node, ctx, parentProps) {
|
|
3846
4455
|
const compDef = ctx.globalComponents[node.component];
|
|
3847
4456
|
if (!compDef) {
|
|
3848
4457
|
return [{ tag: "div", attributes: { "data-component": node.component } }];
|
|
3849
4458
|
}
|
|
3850
|
-
const resolvedProps = {};
|
|
3851
4459
|
const structured = compDef.component;
|
|
3852
|
-
|
|
3853
|
-
for (const [key, propDef] of Object.entries(structured.interface)) {
|
|
3854
|
-
resolvedProps[key] = propDef.default;
|
|
3855
|
-
}
|
|
3856
|
-
}
|
|
4460
|
+
const passedProps = {};
|
|
3857
4461
|
if (node.props) {
|
|
4462
|
+
const parentTemplateProps = parentProps ?? buildTemplateProps(ctx);
|
|
3858
4463
|
for (const [key, value] of Object.entries(node.props)) {
|
|
3859
4464
|
if (key === "children") continue;
|
|
3860
|
-
|
|
3861
|
-
resolvedProps[key] = resolveTemplate2(value, parentProps);
|
|
3862
|
-
} else {
|
|
3863
|
-
resolvedProps[key] = value;
|
|
3864
|
-
}
|
|
4465
|
+
passedProps[key] = typeof value === "string" && hasTemplates(value) ? processCodeTemplates(value, parentTemplateProps) : value;
|
|
3865
4466
|
}
|
|
3866
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;
|
|
3867
4476
|
const body = structured?.structure || compDef.node;
|
|
3868
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
|
+
}
|
|
3869
4551
|
const compCtx = {
|
|
3870
4552
|
...ctx,
|
|
3871
4553
|
fileType: "component",
|
|
3872
4554
|
fileName: node.component,
|
|
3873
4555
|
elementPath: [0],
|
|
3874
|
-
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)
|
|
3875
4571
|
};
|
|
3876
|
-
|
|
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;
|
|
3877
4650
|
}
|
|
3878
|
-
function emitSlotMarker2(node, ctx, instanceProps) {
|
|
4651
|
+
async function emitSlotMarker2(node, ctx, instanceProps) {
|
|
3879
4652
|
if (ctx.slotChildren) {
|
|
4653
|
+
const restored = ctx.slotEmitContext;
|
|
3880
4654
|
const parentCtx = {
|
|
3881
4655
|
...ctx,
|
|
3882
|
-
|
|
4656
|
+
...restored ? {
|
|
4657
|
+
fileType: restored.fileType,
|
|
4658
|
+
fileName: restored.fileName,
|
|
4659
|
+
elementPath: [...restored.elementPath]
|
|
4660
|
+
} : {},
|
|
4661
|
+
slotChildren: void 0,
|
|
3883
4662
|
// prevent infinite slot nesting
|
|
4663
|
+
slotEmitContext: void 0,
|
|
4664
|
+
// consumed
|
|
4665
|
+
slotInstanceProps: void 0
|
|
4666
|
+
// consumed
|
|
3884
4667
|
};
|
|
3885
|
-
|
|
4668
|
+
const slotProps = ctx.slotInstanceProps ?? instanceProps;
|
|
4669
|
+
return convertChildren(ctx.slotChildren, parentCtx, slotProps);
|
|
3886
4670
|
}
|
|
3887
4671
|
if (node.default) {
|
|
3888
4672
|
return convertChildren(node.default, ctx, instanceProps);
|
|
3889
4673
|
}
|
|
3890
4674
|
return [];
|
|
3891
4675
|
}
|
|
3892
|
-
function emitEmbedNode2(node, ctx, instanceProps) {
|
|
3893
|
-
const style =
|
|
3894
|
-
|
|
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
|
+
);
|
|
3895
4691
|
let className;
|
|
3896
4692
|
if (style || interactiveStyles && interactiveStyles.length > 0) {
|
|
3897
|
-
const elementClass = buildElementClass2(ctx, node.label);
|
|
4693
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
3898
4694
|
const { primaryClass } = mapStylesToWebflow(
|
|
3899
4695
|
elementClass,
|
|
3900
4696
|
style,
|
|
3901
4697
|
interactiveStyles,
|
|
3902
|
-
ctx.breakpoints
|
|
4698
|
+
ctx.breakpoints,
|
|
4699
|
+
ctx.responsiveScales
|
|
3903
4700
|
);
|
|
4701
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
3904
4702
|
className = primaryClass.name;
|
|
3905
4703
|
ctx.styleClasses.set(primaryClass.name, primaryClass);
|
|
3906
4704
|
}
|
|
3907
|
-
const
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
}
|
|
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" };
|
|
3912
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
|
+
}
|
|
3913
4746
|
return element;
|
|
3914
4747
|
}
|
|
3915
|
-
function
|
|
3916
|
-
|
|
3917
|
-
|
|
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
|
+
);
|
|
3918
4787
|
let className;
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
const
|
|
4788
|
+
let comboClassNames;
|
|
4789
|
+
{
|
|
4790
|
+
const elementClass = withThemeSuffix(buildElementClass2(ctx, node.label), ctx);
|
|
4791
|
+
const { primaryClass, comboClasses } = mapStylesToWebflow(
|
|
3922
4792
|
elementClass,
|
|
3923
4793
|
style,
|
|
3924
4794
|
interactiveStyles,
|
|
3925
|
-
ctx.breakpoints
|
|
4795
|
+
ctx.breakpoints,
|
|
4796
|
+
ctx.responsiveScales,
|
|
4797
|
+
{ instanceProps, componentDefaults: ctx.componentDefaults, themeSuffix: themedClassSuffix(ctx) }
|
|
3926
4798
|
);
|
|
4799
|
+
substituteVarsInStyleClass(primaryClass, ctx);
|
|
4800
|
+
applyLinkTextDecorationDefault(primaryClass);
|
|
4801
|
+
applyGridRowsDefault(primaryClass);
|
|
3927
4802
|
className = primaryClass.name;
|
|
3928
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
|
+
}
|
|
3929
4815
|
}
|
|
3930
4816
|
let href = "#";
|
|
3931
4817
|
if (typeof node.href === "string") {
|
|
3932
|
-
href =
|
|
4818
|
+
href = resolveStringTemplate(node.href, ctx, instanceProps);
|
|
3933
4819
|
}
|
|
4820
|
+
href = resolveLinkHref(href, ctx);
|
|
3934
4821
|
const attributes = { href };
|
|
3935
4822
|
if (node.attributes) {
|
|
3936
4823
|
for (const [key, value] of Object.entries(node.attributes)) {
|
|
3937
|
-
attributes[key] = value;
|
|
4824
|
+
attributes[key] = typeof value === "string" ? resolveStringTemplate(value, ctx, instanceProps) : value;
|
|
3938
4825
|
}
|
|
3939
4826
|
}
|
|
3940
4827
|
let children;
|
|
3941
4828
|
if (node.children) {
|
|
3942
|
-
|
|
4829
|
+
const ownColor = concreteColor(extractBaseColor(style, ctx, instanceProps));
|
|
4830
|
+
const childCtx = ownColor ? { ...ctx, inheritedColor: ownColor } : ctx;
|
|
4831
|
+
children = await convertChildren(node.children, childCtx, instanceProps);
|
|
3943
4832
|
if (children.length === 0) children = void 0;
|
|
3944
4833
|
}
|
|
3945
4834
|
const element = { tag: "a", attributes };
|
|
3946
4835
|
if (className) element.className = className;
|
|
4836
|
+
if (comboClassNames) element.comboClasses = comboClassNames;
|
|
3947
4837
|
if (children) element.children = children;
|
|
3948
4838
|
return element;
|
|
3949
4839
|
}
|
|
3950
|
-
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) {
|
|
3951
5229
|
if (!children) return [];
|
|
3952
5230
|
if (typeof children === "string") {
|
|
3953
5231
|
return nodeToWebflow(children, ctx, instanceProps);
|
|
@@ -3967,7 +5245,7 @@ function scanJSONFiles2(dir, prefix = "") {
|
|
|
3967
5245
|
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
3968
5246
|
results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
3969
5247
|
} else if (entry.isDirectory()) {
|
|
3970
|
-
results.push(...scanJSONFiles2(
|
|
5248
|
+
results.push(...scanJSONFiles2(join3(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
|
|
3971
5249
|
}
|
|
3972
5250
|
}
|
|
3973
5251
|
return results;
|
|
@@ -3975,12 +5253,38 @@ function scanJSONFiles2(dir, prefix = "") {
|
|
|
3975
5253
|
function isCMSPage2(pageData) {
|
|
3976
5254
|
return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
|
|
3977
5255
|
}
|
|
3978
|
-
function
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
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);
|
|
3982
5271
|
}
|
|
3983
|
-
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
|
+
};
|
|
3984
5288
|
}
|
|
3985
5289
|
function scanAssets(projectRoot) {
|
|
3986
5290
|
const assets = [];
|
|
@@ -3991,7 +5295,7 @@ function scanAssets(projectRoot) {
|
|
|
3991
5295
|
{ dir: "assets", type: "file" }
|
|
3992
5296
|
];
|
|
3993
5297
|
for (const { dir, type } of assetDirs) {
|
|
3994
|
-
const fullDir =
|
|
5298
|
+
const fullDir = join3(projectRoot, dir);
|
|
3995
5299
|
if (!existsSync2(fullDir)) continue;
|
|
3996
5300
|
const files = scanJSONFiles2(fullDir).map((f) => f.replace(".json", ""));
|
|
3997
5301
|
const allFiles = scanAllFiles(fullDir);
|
|
@@ -4014,27 +5318,50 @@ function scanAllFiles(dir, prefix = "") {
|
|
|
4014
5318
|
if (entry.isFile()) {
|
|
4015
5319
|
results.push(relativePath);
|
|
4016
5320
|
} else if (entry.isDirectory()) {
|
|
4017
|
-
results.push(...scanAllFiles(
|
|
5321
|
+
results.push(...scanAllFiles(join3(dir, entry.name), relativePath));
|
|
4018
5322
|
}
|
|
4019
5323
|
}
|
|
4020
5324
|
return results;
|
|
4021
5325
|
}
|
|
4022
|
-
function
|
|
4023
|
-
const
|
|
4024
|
-
const
|
|
4025
|
-
for (const
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
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;
|
|
4029
5351
|
}
|
|
4030
5352
|
}
|
|
4031
|
-
return
|
|
5353
|
+
return out;
|
|
4032
5354
|
}
|
|
4033
|
-
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;
|
|
4034
5358
|
configService.reset();
|
|
4035
5359
|
const projectConfig = await loadProjectConfig();
|
|
4036
5360
|
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
|
|
4037
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);
|
|
4038
5365
|
await migrateTemplatesDirectory();
|
|
4039
5366
|
const { components } = await loadComponentDirectory(projectPaths.components());
|
|
4040
5367
|
const globalComponents = {};
|
|
@@ -4047,8 +5374,8 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4047
5374
|
const themeConfig = await colorService.loadThemeConfig();
|
|
4048
5375
|
const variablesConfig = await variableService.loadConfig();
|
|
4049
5376
|
const breakpoints = await loadBreakpointConfig();
|
|
4050
|
-
const responsiveScales = await loadResponsiveScalesConfig();
|
|
4051
5377
|
await configService.load();
|
|
5378
|
+
const responsiveScales = configService.getResponsiveScales();
|
|
4052
5379
|
const pagesDir = projectPaths.pages();
|
|
4053
5380
|
if (!existsSync2(pagesDir)) {
|
|
4054
5381
|
return emptyPayload();
|
|
@@ -4061,7 +5388,7 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4061
5388
|
for (const file of pageFiles) {
|
|
4062
5389
|
const pageName = file.replace(".json", "");
|
|
4063
5390
|
const basePath = mapPageNameToPath(pageName);
|
|
4064
|
-
const pageContent = await loadJSONFile(
|
|
5391
|
+
const pageContent = await loadJSONFile(join3(pagesDir, file));
|
|
4065
5392
|
if (!pageContent) continue;
|
|
4066
5393
|
try {
|
|
4067
5394
|
const pageData = parseJSON(pageContent);
|
|
@@ -4074,16 +5401,22 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4074
5401
|
}
|
|
4075
5402
|
const allPages = [];
|
|
4076
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);
|
|
4077
5410
|
for (const file of pageFiles) {
|
|
4078
5411
|
const pageName = file.replace(".json", "");
|
|
4079
5412
|
const basePath = mapPageNameToPath(pageName);
|
|
4080
|
-
const pageContent = await loadJSONFile(
|
|
5413
|
+
const pageContent = await loadJSONFile(join3(pagesDir, file));
|
|
4081
5414
|
if (!pageContent) continue;
|
|
4082
5415
|
try {
|
|
4083
5416
|
const pageData = parseJSON(pageContent);
|
|
4084
5417
|
if (pageData.meta?.draft === true) continue;
|
|
4085
5418
|
const slugs = pageData.meta?.slugs;
|
|
4086
|
-
for (const localeConfig of
|
|
5419
|
+
for (const localeConfig of localesToBuild) {
|
|
4087
5420
|
const locale = localeConfig.code;
|
|
4088
5421
|
const isDefault = locale === i18nConfig.defaultLocale;
|
|
4089
5422
|
let slug;
|
|
@@ -4113,16 +5446,32 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4113
5446
|
fileType: "page",
|
|
4114
5447
|
fileName: pageName,
|
|
4115
5448
|
breakpoints,
|
|
4116
|
-
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
|
|
4117
5464
|
};
|
|
4118
5465
|
const body = pageData.root || pageData.node;
|
|
4119
|
-
const elements = body ? nodeToWebflow(body, ctx) : [];
|
|
5466
|
+
const elements = body ? await nodeToWebflow(body, ctx) : [];
|
|
5467
|
+
normalizeListChildren(elements);
|
|
5468
|
+
const pageMeta = extractPageMeta(pageData);
|
|
4120
5469
|
allPages.push({
|
|
4121
5470
|
title: result.title,
|
|
4122
5471
|
slug: slug || "index",
|
|
4123
|
-
metaDescription: typeof pageData.meta?.description === "string" ? pageData.meta.description : void 0,
|
|
4124
5472
|
elements,
|
|
4125
|
-
locale
|
|
5473
|
+
locale,
|
|
5474
|
+
...buildPageMetaForLocale(pageMeta, locale, i18nConfig)
|
|
4126
5475
|
});
|
|
4127
5476
|
}
|
|
4128
5477
|
} catch (error) {
|
|
@@ -4130,11 +5479,10 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4130
5479
|
}
|
|
4131
5480
|
}
|
|
4132
5481
|
const templatesDir = projectPaths.templates();
|
|
4133
|
-
const cmsCollections = [];
|
|
4134
5482
|
if (existsSync2(templatesDir)) {
|
|
4135
5483
|
const templateFiles = readdirSync2(templatesDir).filter((f) => f.endsWith(".json"));
|
|
4136
5484
|
for (const file of templateFiles) {
|
|
4137
|
-
const templateContent = await loadJSONFile(
|
|
5485
|
+
const templateContent = await loadJSONFile(join3(templatesDir, file));
|
|
4138
5486
|
if (!templateContent) continue;
|
|
4139
5487
|
try {
|
|
4140
5488
|
const pageData = parseJSON(templateContent);
|
|
@@ -4142,92 +5490,137 @@ async function buildWebflowPayload(projectRoot) {
|
|
|
4142
5490
|
if (!isCMSPage2(pageData)) continue;
|
|
4143
5491
|
const cmsSchema = pageData.meta.cms;
|
|
4144
5492
|
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
options: fieldDef.options
|
|
4154
|
-
});
|
|
4155
|
-
}
|
|
4156
|
-
}
|
|
4157
|
-
const resolvedItems = [];
|
|
4158
|
-
for (const item of items) {
|
|
4159
|
-
const resolved = {};
|
|
4160
|
-
for (const [key, value] of Object.entries(item)) {
|
|
4161
|
-
if (isI18nValue(value)) {
|
|
4162
|
-
resolved[key] = resolveI18nValue(value, i18nConfig.defaultLocale, i18nConfig);
|
|
4163
|
-
} else {
|
|
4164
|
-
resolved[key] = value;
|
|
4165
|
-
}
|
|
4166
|
-
}
|
|
4167
|
-
resolvedItems.push(resolved);
|
|
4168
|
-
}
|
|
4169
|
-
cmsCollections.push({
|
|
4170
|
-
name: cmsSchema.id,
|
|
4171
|
-
slug: cmsSchema.id,
|
|
4172
|
-
urlPattern: cmsSchema.urlPattern,
|
|
4173
|
-
fields,
|
|
4174
|
-
items: resolvedItems
|
|
4175
|
-
});
|
|
4176
|
-
for (const item of items) {
|
|
4177
|
-
for (const localeConfig of i18nConfig.locales) {
|
|
4178
|
-
const locale = localeConfig.code;
|
|
4179
|
-
if (isItemDraftForLocale(item, locale)) continue;
|
|
4180
|
-
const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
|
|
4181
|
-
const itemWithUrl = { ...item, _url: itemPath };
|
|
4182
|
-
const result = await renderPageSSR(
|
|
4183
|
-
pageData,
|
|
4184
|
-
globalComponents,
|
|
4185
|
-
itemPath,
|
|
4186
|
-
siteUrl,
|
|
4187
|
-
locale,
|
|
4188
|
-
i18nConfig,
|
|
4189
|
-
slugMappings,
|
|
4190
|
-
{ cms: itemWithUrl },
|
|
4191
|
-
cmsService,
|
|
4192
|
-
true
|
|
4193
|
-
);
|
|
4194
|
-
const ctx = {
|
|
4195
|
-
globalComponents,
|
|
4196
|
-
elementPath: [0],
|
|
4197
|
-
fileType: "page",
|
|
4198
|
-
fileName: file.replace(".json", ""),
|
|
4199
|
-
breakpoints,
|
|
4200
|
-
styleClasses: allStyleClasses
|
|
4201
|
-
};
|
|
4202
|
-
const body = pageData.root || pageData.node;
|
|
4203
|
-
const cmsProps = { cms: itemWithUrl };
|
|
4204
|
-
const elements = body ? nodeToWebflow(body, ctx, cmsProps) : [];
|
|
4205
|
-
const slug = itemPath.startsWith("/") ? itemPath.substring(1) : itemPath;
|
|
4206
|
-
allPages.push({
|
|
4207
|
-
title: result.title,
|
|
4208
|
-
slug,
|
|
4209
|
-
elements,
|
|
4210
|
-
locale
|
|
4211
|
-
});
|
|
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);
|
|
4212
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
|
+
});
|
|
4213
5564
|
}
|
|
4214
5565
|
} catch (error) {
|
|
4215
5566
|
console.error(`Error processing template ${file}:`, error?.message);
|
|
4216
5567
|
}
|
|
4217
5568
|
}
|
|
4218
5569
|
}
|
|
4219
|
-
const
|
|
4220
|
-
|
|
4221
|
-
|
|
5570
|
+
for (const def of promotedComponents.values()) {
|
|
5571
|
+
normalizeListChildren(def.elements);
|
|
5572
|
+
}
|
|
5573
|
+
const styleClasses = Array.from(allStyleClasses.values());
|
|
4222
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;
|
|
4223
5603
|
return {
|
|
4224
5604
|
version: 1,
|
|
4225
5605
|
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4226
5606
|
pages: allPages,
|
|
4227
|
-
styles:
|
|
4228
|
-
cms:
|
|
5607
|
+
styles: styleClasses,
|
|
5608
|
+
cms: [],
|
|
4229
5609
|
assets,
|
|
4230
|
-
|
|
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
|
+
}
|
|
4231
5624
|
};
|
|
4232
5625
|
}
|
|
4233
5626
|
function emptyPayload() {
|
|
@@ -4241,6 +5634,32 @@ function emptyPayload() {
|
|
|
4241
5634
|
};
|
|
4242
5635
|
}
|
|
4243
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
|
+
|
|
4244
5663
|
// lib/server/index.ts
|
|
4245
5664
|
init_constants();
|
|
4246
5665
|
export {
|
|
@@ -4336,6 +5755,7 @@ export {
|
|
|
4336
5755
|
variableService,
|
|
4337
5756
|
withErrorHandling,
|
|
4338
5757
|
withLogging,
|
|
5758
|
+
wrapInWebflowTemplate,
|
|
4339
5759
|
writeFile
|
|
4340
5760
|
};
|
|
4341
5761
|
//# sourceMappingURL=index.js.map
|