meno-core 1.0.45 → 1.0.47
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 +211 -124
- package/dist/bin/cli.js +2 -2
- package/dist/build-static.js +7 -7
- package/dist/chunks/{chunk-NZTSJS5C.js → chunk-2QK6U5UK.js} +3 -2
- package/dist/chunks/{chunk-NZTSJS5C.js.map → chunk-2QK6U5UK.js.map} +2 -2
- package/dist/chunks/{chunk-TVH3TC2T.js → chunk-47UNLQUU.js} +6 -6
- package/dist/chunks/{chunk-F7MA62WG.js → chunk-BCLGRZ3U.js} +5 -5
- package/dist/chunks/{chunk-F7MA62WG.js.map → chunk-BCLGRZ3U.js.map} +2 -2
- package/dist/chunks/{chunk-5ZASE4IG.js → chunk-FED5MME6.js} +234 -11
- package/dist/chunks/{chunk-5ZASE4IG.js.map → chunk-FED5MME6.js.map} +3 -3
- package/dist/chunks/{chunk-BZQKEJQY.js → chunk-FGUZOYJX.js} +49 -30
- package/dist/chunks/chunk-FGUZOYJX.js.map +7 -0
- package/dist/chunks/{chunk-5Z5VQRTJ.js → chunk-I7YIGZXT.js} +4 -4
- package/dist/chunks/{chunk-5Z5VQRTJ.js.map → chunk-I7YIGZXT.js.map} +2 -2
- package/dist/chunks/{chunk-OUNJ76QM.js → chunk-LJFB5EBT.js} +5 -5
- package/dist/chunks/{chunk-GYF3ABI3.js → chunk-UUA5LEWF.js} +3 -3
- package/dist/chunks/{chunk-GYF3ABI3.js.map → chunk-UUA5LEWF.js.map} +2 -2
- package/dist/chunks/{chunk-WQSG5WHC.js → chunk-ZTKHJQ2Z.js} +2 -2
- package/dist/chunks/{configService-6KTT6GRT.js → configService-DYCUEURL.js} +3 -3
- package/dist/chunks/{constants-L5IKLB6U.js → constants-GWBAD66U.js} +2 -2
- package/dist/entries/server-router.js +7 -7
- package/dist/lib/client/index.js +7 -5
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +631 -208
- package/dist/lib/server/index.js.map +3 -3
- package/dist/lib/shared/index.js +7 -3
- package/dist/lib/shared/index.js.map +2 -2
- package/dist/lib/test-utils/index.js +1 -1
- package/lib/client/core/ComponentBuilder.test.ts +21 -0
- package/lib/client/core/ComponentBuilder.ts +8 -1
- package/lib/client/templateEngine.test.ts +64 -0
- package/lib/server/astro/astroEmitHelpers.ts +23 -0
- package/lib/server/astro/cmsPageEmitter.ts +46 -3
- package/lib/server/astro/componentEmitter.test.ts +59 -0
- package/lib/server/astro/componentEmitter.ts +53 -12
- package/lib/server/astro/cssCollector.ts +58 -11
- package/lib/server/astro/nodeToAstro.test.ts +397 -5
- package/lib/server/astro/nodeToAstro.ts +494 -65
- package/lib/server/astro/pageEmitter.ts +46 -3
- package/lib/server/astro/tailwindMapper.test.ts +119 -0
- package/lib/server/astro/tailwindMapper.ts +67 -1
- package/lib/server/runtime/httpServer.ts +12 -4
- package/lib/server/ssr/htmlGenerator.test.ts +3 -2
- package/lib/server/ssr/htmlGenerator.ts +6 -1
- package/lib/server/ssr/imageMetadata.ts +15 -9
- package/lib/server/ssr/jsCollector.ts +2 -2
- package/lib/server/ssr/ssrRenderer.test.ts +79 -0
- package/lib/server/ssr/ssrRenderer.ts +35 -20
- package/lib/shared/constants.ts +1 -0
- package/lib/shared/cssGeneration.test.ts +109 -3
- package/lib/shared/cssGeneration.ts +98 -13
- package/lib/shared/cssNamedColors.ts +47 -0
- package/lib/shared/cssProperties.ts +2 -2
- package/lib/shared/index.ts +1 -0
- package/lib/shared/styleNodeUtils.test.ts +47 -1
- package/lib/shared/styleNodeUtils.ts +7 -7
- package/package.json +1 -1
- package/dist/chunks/chunk-BZQKEJQY.js.map +0 -7
- /package/dist/chunks/{chunk-TVH3TC2T.js.map → chunk-47UNLQUU.js.map} +0 -0
- /package/dist/chunks/{chunk-OUNJ76QM.js.map → chunk-LJFB5EBT.js.map} +0 -0
- /package/dist/chunks/{chunk-WQSG5WHC.js.map → chunk-ZTKHJQ2Z.js.map} +0 -0
- /package/dist/chunks/{configService-6KTT6GRT.js.map → configService-DYCUEURL.js.map} +0 -0
- /package/dist/chunks/{constants-L5IKLB6U.js.map → constants-GWBAD66U.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-LJFB5EBT.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-47UNLQUU.js";
|
|
36
36
|
import {
|
|
37
37
|
CMSService,
|
|
38
38
|
ColorService,
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
loadBreakpointConfig,
|
|
66
66
|
loadComponentDirectory,
|
|
67
67
|
loadI18nConfig,
|
|
68
|
+
loadIconsConfig,
|
|
68
69
|
loadJSONFile,
|
|
69
70
|
loadProjectConfig,
|
|
70
71
|
loadResponsiveScalesConfig,
|
|
@@ -82,11 +83,11 @@ import {
|
|
|
82
83
|
styleToString,
|
|
83
84
|
translatePath,
|
|
84
85
|
variableService
|
|
85
|
-
} from "../../chunks/chunk-
|
|
86
|
+
} from "../../chunks/chunk-FGUZOYJX.js";
|
|
86
87
|
import {
|
|
87
88
|
ConfigService,
|
|
88
89
|
configService
|
|
89
|
-
} from "../../chunks/chunk-
|
|
90
|
+
} from "../../chunks/chunk-ZTKHJQ2Z.js";
|
|
90
91
|
import {
|
|
91
92
|
bundleFile,
|
|
92
93
|
createRuntimeServer,
|
|
@@ -100,7 +101,7 @@ import {
|
|
|
100
101
|
resolveProjectPath,
|
|
101
102
|
setProjectRoot,
|
|
102
103
|
validateJS
|
|
103
|
-
} from "../../chunks/chunk-
|
|
104
|
+
} from "../../chunks/chunk-I7YIGZXT.js";
|
|
104
105
|
import {
|
|
105
106
|
ensureDir,
|
|
106
107
|
fileExists,
|
|
@@ -117,7 +118,7 @@ import {
|
|
|
117
118
|
} from "../../chunks/chunk-WQFG7PAH.js";
|
|
118
119
|
import "../../chunks/chunk-IF3RATBY.js";
|
|
119
120
|
import "../../chunks/chunk-KITQJYZV.js";
|
|
120
|
-
import "../../chunks/chunk-
|
|
121
|
+
import "../../chunks/chunk-BCLGRZ3U.js";
|
|
121
122
|
import {
|
|
122
123
|
extractInteractiveStyleMappings,
|
|
123
124
|
generateAllInteractiveCSS,
|
|
@@ -127,13 +128,15 @@ import {
|
|
|
127
128
|
isItemDraftForLocale,
|
|
128
129
|
isVoidElement,
|
|
129
130
|
singularize
|
|
130
|
-
} from "../../chunks/chunk-
|
|
131
|
+
} from "../../chunks/chunk-FED5MME6.js";
|
|
131
132
|
import {
|
|
132
133
|
DEFAULT_BREAKPOINTS,
|
|
133
134
|
DEFAULT_I18N_CONFIG,
|
|
134
135
|
buildLocalizedPath,
|
|
136
|
+
getScaleMultiplier,
|
|
135
137
|
isI18nValue,
|
|
136
|
-
resolveI18nValue
|
|
138
|
+
resolveI18nValue,
|
|
139
|
+
scalePropertyValue
|
|
137
140
|
} from "../../chunks/chunk-XSWR3QLI.js";
|
|
138
141
|
import "../../chunks/chunk-UB44F4Z2.js";
|
|
139
142
|
import {
|
|
@@ -144,11 +147,11 @@ import {
|
|
|
144
147
|
SERVER_PORT,
|
|
145
148
|
SERVE_PORT,
|
|
146
149
|
init_constants
|
|
147
|
-
} from "../../chunks/chunk-
|
|
150
|
+
} from "../../chunks/chunk-2QK6U5UK.js";
|
|
148
151
|
import "../../chunks/chunk-KSBZ2L7C.js";
|
|
149
152
|
|
|
150
153
|
// build-astro.ts
|
|
151
|
-
import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync } from "fs";
|
|
154
|
+
import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, writeFileSync } from "fs";
|
|
152
155
|
import { writeFile as writeFile2, readFile } from "fs/promises";
|
|
153
156
|
import { join } from "path";
|
|
154
157
|
import { createHash } from "crypto";
|
|
@@ -582,7 +585,7 @@ function stylesToTailwind(style) {
|
|
|
582
585
|
}
|
|
583
586
|
return { classes, dynamicStyles };
|
|
584
587
|
}
|
|
585
|
-
function responsiveStylesToTailwind(style, breakpoints) {
|
|
588
|
+
function responsiveStylesToTailwind(style, breakpoints, responsiveScales) {
|
|
586
589
|
if (!style) return { classes: [], dynamicStyles: {} };
|
|
587
590
|
const allClasses = [];
|
|
588
591
|
const allDynamicStyles = {};
|
|
@@ -616,6 +619,9 @@ function responsiveStylesToTailwind(style, breakpoints) {
|
|
|
616
619
|
allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
|
|
617
620
|
Object.assign(allDynamicStyles, dynamicStyles);
|
|
618
621
|
}
|
|
622
|
+
if (responsiveScales?.enabled === true && responsive.base) {
|
|
623
|
+
appendAutoScaledClasses(responsive, breakpoints, responsiveScales, allClasses);
|
|
624
|
+
}
|
|
619
625
|
} else {
|
|
620
626
|
const { classes, dynamicStyles } = stylesToTailwind(style);
|
|
621
627
|
allClasses.push(...classes);
|
|
@@ -623,6 +629,35 @@ function responsiveStylesToTailwind(style, breakpoints) {
|
|
|
623
629
|
}
|
|
624
630
|
return { classes: allClasses, dynamicStyles: allDynamicStyles };
|
|
625
631
|
}
|
|
632
|
+
function appendAutoScaledClasses(responsive, breakpoints, responsiveScales, out) {
|
|
633
|
+
const base = responsive.base;
|
|
634
|
+
if (!base) return;
|
|
635
|
+
const baseRef = responsiveScales.baseReference ?? 16;
|
|
636
|
+
const sortedBps = Object.entries(breakpoints).map(([name, cfg]) => ({ name, value: cfg?.breakpoint })).filter(
|
|
637
|
+
(bp) => typeof bp.value === "number" && bp.value > 0
|
|
638
|
+
).sort((a, b) => b.value - a.value);
|
|
639
|
+
for (const [property, value] of Object.entries(base)) {
|
|
640
|
+
if (isStyleMapping(value)) continue;
|
|
641
|
+
if (value == null) continue;
|
|
642
|
+
const strValue = String(value);
|
|
643
|
+
if (strValue === "" || hasTemplateExpression(strValue)) continue;
|
|
644
|
+
for (const { name: bpName, value: bpPixels } of sortedBps) {
|
|
645
|
+
const bpBranch = responsive[bpName];
|
|
646
|
+
if (bpBranch && property in bpBranch) continue;
|
|
647
|
+
const scale = getScaleMultiplier(
|
|
648
|
+
responsiveScales,
|
|
649
|
+
property,
|
|
650
|
+
bpName
|
|
651
|
+
);
|
|
652
|
+
if (scale == null) continue;
|
|
653
|
+
const scaledValue = scalePropertyValue(strValue, baseRef, scale);
|
|
654
|
+
if (scaledValue == null || scaledValue === strValue) continue;
|
|
655
|
+
const scaledClass = propertyToTailwind(property, scaledValue);
|
|
656
|
+
if (!scaledClass) continue;
|
|
657
|
+
out.push(`max-[${bpPixels}px]:${scaledClass}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
626
661
|
|
|
627
662
|
// lib/server/astro/nodeToAstro.ts
|
|
628
663
|
init_constants();
|
|
@@ -687,6 +722,28 @@ function transformItemTemplate(text, itemVar = "item", indexVar, sourceVar) {
|
|
|
687
722
|
return text;
|
|
688
723
|
}
|
|
689
724
|
|
|
725
|
+
// lib/server/astro/astroEmitHelpers.ts
|
|
726
|
+
init_constants();
|
|
727
|
+
function stripRawHtmlPrefixDeep(value) {
|
|
728
|
+
if (typeof value === "string") {
|
|
729
|
+
return value.startsWith(RAW_HTML_PREFIX) ? value.slice(RAW_HTML_PREFIX.length) : value;
|
|
730
|
+
}
|
|
731
|
+
if (Array.isArray(value)) {
|
|
732
|
+
return value.map((item) => stripRawHtmlPrefixDeep(item));
|
|
733
|
+
}
|
|
734
|
+
if (value !== null && typeof value === "object") {
|
|
735
|
+
const out = {};
|
|
736
|
+
for (const [k, v] of Object.entries(value)) {
|
|
737
|
+
out[k] = stripRawHtmlPrefixDeep(v);
|
|
738
|
+
}
|
|
739
|
+
return out;
|
|
740
|
+
}
|
|
741
|
+
return value;
|
|
742
|
+
}
|
|
743
|
+
function astroComponentName(name) {
|
|
744
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
745
|
+
}
|
|
746
|
+
|
|
690
747
|
// lib/server/astro/nodeToAstro.ts
|
|
691
748
|
function ind(ctx) {
|
|
692
749
|
return " ".repeat(ctx.indent);
|
|
@@ -751,7 +808,7 @@ function escapeJSX(s) {
|
|
|
751
808
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
752
809
|
}
|
|
753
810
|
function escapeTemplateLiteral(s) {
|
|
754
|
-
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
811
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
755
812
|
}
|
|
756
813
|
function collectStyleMappings(style) {
|
|
757
814
|
if (!style) return [];
|
|
@@ -808,7 +865,7 @@ function getClassForValue(property, value, breakpointPrefix) {
|
|
|
808
865
|
return breakpointPrefix ? `${breakpointPrefix}${twClass}` : twClass;
|
|
809
866
|
}
|
|
810
867
|
function buildClassAndStyleExpression(style, interactiveStyles, elementClass, ctx) {
|
|
811
|
-
const result = style ? responsiveStylesToTailwind(style, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
868
|
+
const result = style ? responsiveStylesToTailwind(style, ctx.breakpoints, ctx.responsiveScales) : { classes: [], dynamicStyles: {} };
|
|
812
869
|
const staticClasses = result.classes;
|
|
813
870
|
const dynamicStyles = result.dynamicStyles;
|
|
814
871
|
if (elementClass) {
|
|
@@ -899,7 +956,7 @@ function resolveTemplate(text, ctx) {
|
|
|
899
956
|
let propName = fullMatch[1].trim();
|
|
900
957
|
if (ctx.listItemBinding) propName = rewriteItemVar(propName, ctx.listItemBinding);
|
|
901
958
|
if (ctx.listIndexVar) propName = replaceItemMetaVars(propName, ctx.listIndexVar, ctx.listSourceVar);
|
|
902
|
-
if (ctx.componentProps[propName]?.type === "rich-text") {
|
|
959
|
+
if (ctx.componentProps[propName]?.type === "rich-text" || ctx.componentProps[propName]?.type === "embed") {
|
|
903
960
|
return `<Fragment set:html={${propName}} />`;
|
|
904
961
|
}
|
|
905
962
|
return `{${propName}}`;
|
|
@@ -988,6 +1045,7 @@ function buildAttributesString(attributes, ctx) {
|
|
|
988
1045
|
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
989
1046
|
}
|
|
990
1047
|
function formatPropValue(value) {
|
|
1048
|
+
value = stripRawHtmlPrefixDeep(value);
|
|
991
1049
|
if (typeof value === "string") return `"${escapeJSX(value)}"`;
|
|
992
1050
|
if (typeof value === "number") return `{${value}}`;
|
|
993
1051
|
if (typeof value === "boolean") return `{${value}}`;
|
|
@@ -1005,12 +1063,11 @@ function nodeToAstro(node, ctx) {
|
|
|
1005
1063
|
if (typeof node === "object" && !Array.isArray(node) && isI18nValue(node)) {
|
|
1006
1064
|
const resolved = resolveI18n(node, ctx);
|
|
1007
1065
|
if (typeof resolved === "string") {
|
|
1008
|
-
return
|
|
1009
|
-
`;
|
|
1066
|
+
return nodeToAstro(resolved, ctx);
|
|
1010
1067
|
}
|
|
1011
1068
|
if (ctx.isComponentDef && isI18nValue(resolved)) {
|
|
1012
1069
|
ctx.needsI18nResolver = true;
|
|
1013
|
-
return `${ind(ctx)}{r(${JSON.stringify(resolved)})}
|
|
1070
|
+
return `${ind(ctx)}{r(${JSON.stringify(stripRawHtmlPrefixDeep(resolved))})}
|
|
1014
1071
|
`;
|
|
1015
1072
|
}
|
|
1016
1073
|
return `${ind(ctx)}${String(resolved ?? "")}
|
|
@@ -1032,7 +1089,8 @@ function nodeToAstro(node, ctx) {
|
|
|
1032
1089
|
`;
|
|
1033
1090
|
}
|
|
1034
1091
|
if (node.startsWith(RAW_HTML_PREFIX)) {
|
|
1035
|
-
const
|
|
1092
|
+
const rawSlice = node.slice(RAW_HTML_PREFIX.length);
|
|
1093
|
+
const rawHtml = ctx.processedRawHtml?.get(rawSlice) ?? rawSlice;
|
|
1036
1094
|
return `${ind(ctx)}<Fragment set:html={\`${escapeTemplateLiteral(rawHtml)}\`} />
|
|
1037
1095
|
`;
|
|
1038
1096
|
}
|
|
@@ -1079,6 +1137,7 @@ function nodeToAstro(node, ctx) {
|
|
|
1079
1137
|
var IMG_TAILWIND_PREFIXES = ["object-", "rounded", "border", "shadow", "[filter", "[transform", "mix-blend"];
|
|
1080
1138
|
var IMG_OPACITY_PATTERN = /^opacity-/;
|
|
1081
1139
|
var DEFAULT_SIZES2 = "100vw";
|
|
1140
|
+
var IMG_FILL_CLASSES = ["block", "w-full", "h-full"];
|
|
1082
1141
|
function splitImageClasses(allClasses) {
|
|
1083
1142
|
const imgClasses = [];
|
|
1084
1143
|
const pictureClasses = [];
|
|
@@ -1092,11 +1151,164 @@ function splitImageClasses(allClasses) {
|
|
|
1092
1151
|
}
|
|
1093
1152
|
return { pictureClasses, imgClasses };
|
|
1094
1153
|
}
|
|
1154
|
+
function extractPxWidth(val) {
|
|
1155
|
+
if (typeof val === "number" && Number.isFinite(val) && val > 0) return val;
|
|
1156
|
+
if (typeof val !== "string") return null;
|
|
1157
|
+
const match = val.trim().match(/^(\d+(?:\.\d+)?)px$/);
|
|
1158
|
+
if (!match) return null;
|
|
1159
|
+
const n = parseFloat(match[1]);
|
|
1160
|
+
return n > 0 ? n : null;
|
|
1161
|
+
}
|
|
1162
|
+
function computeSizesAttribute(style, breakpoints) {
|
|
1163
|
+
if (!style) return DEFAULT_SIZES2;
|
|
1164
|
+
const responsive = isResponsiveStyle2(style);
|
|
1165
|
+
const baseStyle = responsive ? style.base : style;
|
|
1166
|
+
const baseWidth = baseStyle ? extractPxWidth(baseStyle.width) : null;
|
|
1167
|
+
if (baseWidth == null) return DEFAULT_SIZES2;
|
|
1168
|
+
const bpEntries = Object.entries(breakpoints).sort(
|
|
1169
|
+
(a, b) => a[1].breakpoint - b[1].breakpoint
|
|
1170
|
+
);
|
|
1171
|
+
const parts = [];
|
|
1172
|
+
for (const [name, entry] of bpEntries) {
|
|
1173
|
+
let effective = null;
|
|
1174
|
+
if (responsive) {
|
|
1175
|
+
const bpStyle = style[name];
|
|
1176
|
+
effective = bpStyle ? extractPxWidth(bpStyle.width) : null;
|
|
1177
|
+
if (effective == null) {
|
|
1178
|
+
for (const [largerName, largerEntry] of bpEntries) {
|
|
1179
|
+
if (largerEntry.breakpoint <= entry.breakpoint) continue;
|
|
1180
|
+
const largerStyle = style[largerName];
|
|
1181
|
+
const larger = largerStyle ? extractPxWidth(largerStyle.width) : null;
|
|
1182
|
+
if (larger != null) {
|
|
1183
|
+
effective = larger;
|
|
1184
|
+
break;
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
if (effective == null) effective = baseWidth;
|
|
1189
|
+
} else {
|
|
1190
|
+
effective = baseWidth;
|
|
1191
|
+
}
|
|
1192
|
+
parts.push(`(max-width: ${entry.breakpoint}px) ${effective}px`);
|
|
1193
|
+
}
|
|
1194
|
+
parts.push(`${baseWidth}px`);
|
|
1195
|
+
return parts.join(", ");
|
|
1196
|
+
}
|
|
1197
|
+
function injectInlineStyle(styleAttr, extraCss) {
|
|
1198
|
+
if (!extraCss) return styleAttr;
|
|
1199
|
+
if (!styleAttr) return ` style="${extraCss}"`;
|
|
1200
|
+
return styleAttr.replace(/style="([^"]*)"/, (_, existing) => {
|
|
1201
|
+
const trimmed = existing.trimEnd();
|
|
1202
|
+
const sep = trimmed.length > 0 && !trimmed.endsWith(";") ? ";" : "";
|
|
1203
|
+
return `style="${existing}${sep}${extraCss}"`;
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
var PICTURE_WIDTHS = [500, 800, 1080, 1600, 2400];
|
|
1207
|
+
function imagePathToVarName(srcPath) {
|
|
1208
|
+
const stripped = srcPath.replace(/^\/+/, "").replace(/^images\//, "").replace(/\.[^.]+$/, "");
|
|
1209
|
+
const parts = stripped.split(/[/_\-\s.]+/).filter(Boolean);
|
|
1210
|
+
if (parts.length === 0) return "imgAsset";
|
|
1211
|
+
const camel = parts.map((p, i) => {
|
|
1212
|
+
const clean = p.replace(/[^a-zA-Z0-9]/g, "");
|
|
1213
|
+
if (!clean) return "";
|
|
1214
|
+
if (i === 0) return clean.toLowerCase();
|
|
1215
|
+
return clean[0].toUpperCase() + clean.slice(1).toLowerCase();
|
|
1216
|
+
}).join("");
|
|
1217
|
+
if (!camel) return "imgAsset";
|
|
1218
|
+
return "img" + camel[0].toUpperCase() + camel.slice(1);
|
|
1219
|
+
}
|
|
1220
|
+
function imageImportPath(srcPath, fileDepth) {
|
|
1221
|
+
const rest = srcPath.replace(/^\/+/, "").replace(/^images\//, "");
|
|
1222
|
+
const ups = "../".repeat(Math.max(0, fileDepth) + 1);
|
|
1223
|
+
return `${ups}assets/images/${rest}`;
|
|
1224
|
+
}
|
|
1225
|
+
function isStaticImageSrc(src, ctx) {
|
|
1226
|
+
if (!src) return false;
|
|
1227
|
+
if (typeof src !== "string") return false;
|
|
1228
|
+
if (hasTemplates(src)) return false;
|
|
1229
|
+
if (!src.startsWith("/images/")) return false;
|
|
1230
|
+
if (!ctx.imageMetadataMap?.has(src)) return false;
|
|
1231
|
+
return true;
|
|
1232
|
+
}
|
|
1233
|
+
function registerStaticImageImport(src, ctx) {
|
|
1234
|
+
if (!ctx.imageImports) ctx.imageImports = /* @__PURE__ */ new Map();
|
|
1235
|
+
const depth = ctx.fileDepth ?? 0;
|
|
1236
|
+
const importPath = imageImportPath(src, depth);
|
|
1237
|
+
for (const [existingName, existingPath] of ctx.imageImports) {
|
|
1238
|
+
if (existingPath === importPath) return existingName;
|
|
1239
|
+
}
|
|
1240
|
+
const base = imagePathToVarName(src);
|
|
1241
|
+
let name = base;
|
|
1242
|
+
let counter = 2;
|
|
1243
|
+
while (ctx.imageImports.has(name)) {
|
|
1244
|
+
name = `${base}${counter++}`;
|
|
1245
|
+
}
|
|
1246
|
+
ctx.imageImports.set(name, importPath);
|
|
1247
|
+
return name;
|
|
1248
|
+
}
|
|
1249
|
+
function splitStaticClassExpr(classExpr) {
|
|
1250
|
+
if (classExpr.includes("class:list=")) return null;
|
|
1251
|
+
const classMatch = classExpr.match(/class="([^"]*)"/);
|
|
1252
|
+
if (!classMatch) return { outerClasses: [], innerClasses: [] };
|
|
1253
|
+
const all = classMatch[1].split(/\s+/).filter(Boolean);
|
|
1254
|
+
const { pictureClasses, imgClasses } = splitImageClasses(all);
|
|
1255
|
+
return { outerClasses: pictureClasses, innerClasses: imgClasses };
|
|
1256
|
+
}
|
|
1257
|
+
function formatPictureAttributesProp(classValue, styleAttr) {
|
|
1258
|
+
const styleMatch = styleAttr.match(/style="([^"]*)"/);
|
|
1259
|
+
const parts = [];
|
|
1260
|
+
if (classValue) parts.push(`class: ${JSON.stringify(classValue)}`);
|
|
1261
|
+
if (styleMatch) parts.push(`style: ${JSON.stringify(styleMatch[1])}`);
|
|
1262
|
+
if (parts.length === 0) return "";
|
|
1263
|
+
return ` pictureAttributes={{${parts.join(", ")}}}`;
|
|
1264
|
+
}
|
|
1265
|
+
function emitStaticPictureImage(src, alt, loading, fetchpriority, sizesValue, classExpr, styleAttr, ifExpr, ifClose, blurHash, ctx) {
|
|
1266
|
+
const varName = registerStaticImageImport(src, ctx);
|
|
1267
|
+
const widthsLiteral = `[${PICTURE_WIDTHS.join(", ")}]`;
|
|
1268
|
+
const altAttr = alt !== void 0 ? ` alt="${escapeJSX(String(alt))}"` : ' alt=""';
|
|
1269
|
+
const loadingAttr = loading ? ` loading="${escapeJSX(loading)}"` : "";
|
|
1270
|
+
const fetchpriorityAttr = fetchpriority ? ` fetchpriority="${escapeJSX(fetchpriority)}"` : "";
|
|
1271
|
+
const split = splitStaticClassExpr(classExpr);
|
|
1272
|
+
if (blurHash) {
|
|
1273
|
+
const blurCss = `background-image:url(${escapeJSX(blurHash)});background-size:cover`;
|
|
1274
|
+
const blurStyleAttr = injectInlineStyle(styleAttr, blurCss);
|
|
1275
|
+
const onloadAttr = ` onload="this.parentElement.style.backgroundImage=''"`;
|
|
1276
|
+
if (split) {
|
|
1277
|
+
const outerClassValue = split.outerClasses.join(" ");
|
|
1278
|
+
const pictureAttrs = formatPictureAttributesProp(outerClassValue, blurStyleAttr);
|
|
1279
|
+
const innerClasses = [...split.innerClasses, ...IMG_FILL_CLASSES];
|
|
1280
|
+
const innerClassAttr = ` class="${innerClasses.join(" ")}"`;
|
|
1281
|
+
return `${ifExpr}${ind(ctx)}<Picture${pictureAttrs} src={${varName}}${altAttr}${innerClassAttr} formats={['avif','webp']} widths={${widthsLiteral}} sizes="${escapeJSX(sizesValue)}"${loadingAttr}${fetchpriorityAttr}${onloadAttr} />
|
|
1282
|
+
${ifClose}`;
|
|
1283
|
+
}
|
|
1284
|
+
const wrapperClassExpr = classExpr;
|
|
1285
|
+
const wrapperStyleAttr = injectInlineStyle(styleAttr, blurCss);
|
|
1286
|
+
const fillClassAttr = ` class="${IMG_FILL_CLASSES.join(" ")}"`;
|
|
1287
|
+
return `${ifExpr}${ind(ctx)}<div${wrapperClassExpr}${wrapperStyleAttr}>
|
|
1288
|
+
${ind(ctx)} <Picture pictureAttributes={{class: "${IMG_FILL_CLASSES.join(" ")}"}} src={${varName}}${altAttr}${fillClassAttr} formats={['avif','webp']} widths={${widthsLiteral}} sizes="${escapeJSX(sizesValue)}"${loadingAttr}${fetchpriorityAttr} onload="this.parentElement.parentElement.style.backgroundImage=''" />
|
|
1289
|
+
${ind(ctx)}</div>
|
|
1290
|
+
${ifClose}`;
|
|
1291
|
+
}
|
|
1292
|
+
if (split) {
|
|
1293
|
+
const outerClassValue = split.outerClasses.join(" ");
|
|
1294
|
+
const innerClassAttr = split.innerClasses.length > 0 ? ` class="${split.innerClasses.join(" ")}"` : "";
|
|
1295
|
+
const pictureAttrs = formatPictureAttributesProp(outerClassValue, styleAttr);
|
|
1296
|
+
return `${ifExpr}${ind(ctx)}<Picture${pictureAttrs} src={${varName}}${altAttr}${innerClassAttr} formats={['avif','webp']} widths={${widthsLiteral}} sizes="${escapeJSX(sizesValue)}"${loadingAttr}${fetchpriorityAttr} />
|
|
1297
|
+
${ifClose}`;
|
|
1298
|
+
}
|
|
1299
|
+
return `${ifExpr}${ind(ctx)}<div${classExpr}${styleAttr}>
|
|
1300
|
+
${ind(ctx)} <Picture src={${varName}}${altAttr} formats={['avif','webp']} widths={${widthsLiteral}} sizes="${escapeJSX(sizesValue)}"${loadingAttr}${fetchpriorityAttr} />
|
|
1301
|
+
${ind(ctx)}</div>
|
|
1302
|
+
${ifClose}`;
|
|
1303
|
+
}
|
|
1095
1304
|
function emitImageNode(node, ctx) {
|
|
1096
1305
|
const style = node.style;
|
|
1097
1306
|
let elementClass = null;
|
|
1098
1307
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1099
1308
|
elementClass = buildElementClass(ctx, node.label);
|
|
1309
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1310
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1311
|
+
}
|
|
1100
1312
|
}
|
|
1101
1313
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(
|
|
1102
1314
|
style,
|
|
@@ -1117,7 +1329,22 @@ function emitImageNode(node, ctx) {
|
|
|
1117
1329
|
if (width === void 0 && metadata.width) width = metadata.width;
|
|
1118
1330
|
if (height === void 0 && metadata.height) height = metadata.height;
|
|
1119
1331
|
}
|
|
1120
|
-
const sizesValue = sizes ||
|
|
1332
|
+
const sizesValue = sizes || computeSizesAttribute(style, ctx.breakpoints);
|
|
1333
|
+
if (isStaticImageSrc(src, ctx)) {
|
|
1334
|
+
return emitStaticPictureImage(
|
|
1335
|
+
src,
|
|
1336
|
+
alt,
|
|
1337
|
+
loading,
|
|
1338
|
+
fetchpriority,
|
|
1339
|
+
sizesValue,
|
|
1340
|
+
classExpr,
|
|
1341
|
+
styleAttr,
|
|
1342
|
+
emitIfOpen(node, ctx),
|
|
1343
|
+
emitIfClose(node, ctx),
|
|
1344
|
+
metadata?.blurHash,
|
|
1345
|
+
ctx
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1121
1348
|
const imageSpecificKeys = /* @__PURE__ */ new Set(["src", "alt", "loading", "width", "height", "sizes", "srcset", "fetchpriority"]);
|
|
1122
1349
|
const otherAttrs = {};
|
|
1123
1350
|
if (node.attributes) {
|
|
@@ -1133,31 +1360,44 @@ function emitImageNode(node, ctx) {
|
|
|
1133
1360
|
if (loading) imgAttrs += ` loading="${escapeJSX(String(loading))}"`;
|
|
1134
1361
|
if (width !== void 0) imgAttrs += ` width="${escapeJSX(String(width))}"`;
|
|
1135
1362
|
if (height !== void 0) imgAttrs += ` height="${escapeJSX(String(height))}"`;
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
}
|
|
1363
|
+
const hasAvif = !!(metadata?.avifSrcset && ctx.imageFormat !== "webp");
|
|
1364
|
+
const hasBlur = !!metadata?.blurHash;
|
|
1365
|
+
const useWrapper = hasAvif || hasBlur;
|
|
1366
|
+
const blurWrapperCss = hasBlur ? `background-image:url(${escapeJSX(metadata.blurHash)});background-size:cover` : "";
|
|
1367
|
+
const blurOnload = hasBlur ? ` onload="this.parentElement.style.backgroundImage=''"` : "";
|
|
1140
1368
|
const ifExpr = emitIfOpen(node, ctx);
|
|
1141
1369
|
const ifClose = emitIfClose(node, ctx);
|
|
1142
|
-
if (
|
|
1143
|
-
const
|
|
1370
|
+
if (useWrapper) {
|
|
1371
|
+
const imgFillClasses = IMG_FILL_CLASSES.slice();
|
|
1144
1372
|
const classListMatch = classExpr.match(/class:list={\[(.+)\]}/);
|
|
1373
|
+
const classMatch = classExpr.match(/class="([^"]*)"/);
|
|
1374
|
+
let pictureClassExpr = "";
|
|
1375
|
+
let imgClassAttr = "";
|
|
1145
1376
|
if (classListMatch) {
|
|
1146
|
-
|
|
1377
|
+
pictureClassExpr = classExpr;
|
|
1378
|
+
imgClassAttr = ` class="${imgFillClasses.join(" ")}"`;
|
|
1379
|
+
} else {
|
|
1380
|
+
const allClasses = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
|
|
1381
|
+
const { pictureClasses, imgClasses } = splitImageClasses(allClasses);
|
|
1382
|
+
const fullImgClasses = [...imgClasses, ...imgFillClasses];
|
|
1383
|
+
pictureClassExpr = pictureClasses.length > 0 ? ` class="${pictureClasses.join(" ")}"` : "";
|
|
1384
|
+
imgClassAttr = fullImgClasses.length > 0 ? ` class="${fullImgClasses.join(" ")}"` : "";
|
|
1385
|
+
}
|
|
1386
|
+
const wrapperStyleAttr = injectInlineStyle(styleAttr, blurWrapperCss);
|
|
1387
|
+
if (hasAvif) {
|
|
1388
|
+
return `${ifExpr}${ind(ctx)}<picture${pictureClassExpr}${wrapperStyleAttr}>
|
|
1147
1389
|
${ind(ctx)} <source type="image/avif" srcset="${escapeJSX(metadata.avifSrcset)}" sizes="${escapeJSX(sizesValue)}" />
|
|
1148
1390
|
${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
|
|
1149
|
-
${ind(ctx)} <img${imgAttrs}${
|
|
1391
|
+
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurOnload}${otherAttrsStr} />
|
|
1150
1392
|
${ind(ctx)}</picture>
|
|
1151
1393
|
${ifClose}`;
|
|
1152
1394
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
return `${ifExpr}${ind(ctx)}<picture${
|
|
1158
|
-
${ind(ctx)} <
|
|
1159
|
-
${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
|
|
1160
|
-
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurStyle}${otherAttrsStr} />
|
|
1395
|
+
if (metadata?.srcset) {
|
|
1396
|
+
imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
|
|
1397
|
+
imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
|
|
1398
|
+
}
|
|
1399
|
+
return `${ifExpr}${ind(ctx)}<picture${pictureClassExpr}${wrapperStyleAttr}>
|
|
1400
|
+
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurOnload}${otherAttrsStr} />
|
|
1161
1401
|
${ind(ctx)}</picture>
|
|
1162
1402
|
${ifClose}`;
|
|
1163
1403
|
}
|
|
@@ -1165,7 +1405,7 @@ ${ifClose}`;
|
|
|
1165
1405
|
imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
|
|
1166
1406
|
imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
|
|
1167
1407
|
}
|
|
1168
|
-
return `${ifExpr}${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs}${
|
|
1408
|
+
return `${ifExpr}${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs}${otherAttrsStr} />
|
|
1169
1409
|
${ifClose}`;
|
|
1170
1410
|
}
|
|
1171
1411
|
function emitHtmlNode(node, ctx) {
|
|
@@ -1192,6 +1432,9 @@ function emitHtmlNode(node, ctx) {
|
|
|
1192
1432
|
let elementClass = null;
|
|
1193
1433
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1194
1434
|
elementClass = buildElementClass(ctx, label);
|
|
1435
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1436
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1437
|
+
}
|
|
1195
1438
|
}
|
|
1196
1439
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1197
1440
|
const attrs = buildAttributesString(node.attributes, ctx);
|
|
@@ -1210,8 +1453,8 @@ ${emitIfClose(node, ctx)}`;
|
|
|
1210
1453
|
${emitIfClose(node, ctx)}`;
|
|
1211
1454
|
}
|
|
1212
1455
|
function emitComponentInstance(node, ctx) {
|
|
1213
|
-
const name = node.component;
|
|
1214
|
-
ctx.imports.add(
|
|
1456
|
+
const name = astroComponentName(node.component);
|
|
1457
|
+
ctx.imports.add(node.component);
|
|
1215
1458
|
const ifExpr = emitIfOpen(node, ctx);
|
|
1216
1459
|
const propParts = [];
|
|
1217
1460
|
if (node.props) {
|
|
@@ -1248,20 +1491,27 @@ function emitComponentInstance(node, ctx) {
|
|
|
1248
1491
|
}
|
|
1249
1492
|
} else if (ctx.isComponentDef && isI18nValue(value)) {
|
|
1250
1493
|
ctx.needsI18nResolver = true;
|
|
1251
|
-
propParts.push(`${key}={r(${JSON.stringify(value)})}`);
|
|
1494
|
+
propParts.push(`${key}={r(${JSON.stringify(stripRawHtmlPrefixDeep(value))})}`);
|
|
1252
1495
|
} else {
|
|
1253
|
-
|
|
1496
|
+
const targetInterface = ctx.globalComponents[name]?.component?.interface;
|
|
1497
|
+
const propDef = targetInterface?.[key];
|
|
1498
|
+
if (typeof value === "string" && (propDef?.type === "rich-text" || propDef?.type === "embed")) {
|
|
1499
|
+
propParts.push(`${key}={\`${escapeTemplateLiteral(stripRawHtmlPrefixDeep(value))}\`}`);
|
|
1500
|
+
} else {
|
|
1501
|
+
propParts.push(`${key}=${formatPropValue(value)}`);
|
|
1502
|
+
}
|
|
1254
1503
|
}
|
|
1255
1504
|
}
|
|
1256
1505
|
}
|
|
1257
1506
|
if (node.style) {
|
|
1258
|
-
const { classes: instanceClasses } = responsiveStylesToTailwind(node.style, ctx.breakpoints);
|
|
1507
|
+
const { classes: instanceClasses } = responsiveStylesToTailwind(node.style, ctx.breakpoints, ctx.responsiveScales);
|
|
1259
1508
|
if (instanceClasses.length > 0) {
|
|
1260
1509
|
propParts.push(`class="${instanceClasses.join(" ")}"`);
|
|
1261
1510
|
}
|
|
1262
1511
|
}
|
|
1263
1512
|
const propsStr = propParts.length > 0 ? " " + propParts.join(" ") : "";
|
|
1264
|
-
const
|
|
1513
|
+
const childCtx = { ...ctx, elementPath: [0] };
|
|
1514
|
+
const children = emitChildren(node.children, childCtx);
|
|
1265
1515
|
if (!children.trim()) {
|
|
1266
1516
|
return `${ifExpr}${ind(ctx)}<${name}${propsStr} />
|
|
1267
1517
|
${emitIfClose(node, ctx)}`;
|
|
@@ -1288,6 +1538,9 @@ function emitEmbedNode(node, ctx) {
|
|
|
1288
1538
|
let elementClass = null;
|
|
1289
1539
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1290
1540
|
elementClass = buildElementClass(ctx, node.label);
|
|
1541
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1542
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1543
|
+
}
|
|
1291
1544
|
}
|
|
1292
1545
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1293
1546
|
const attrs = buildAttributesString(node.attributes, ctx);
|
|
@@ -1341,6 +1594,9 @@ function emitLinkNode(node, ctx) {
|
|
|
1341
1594
|
let elementClass = null;
|
|
1342
1595
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1343
1596
|
elementClass = buildElementClass(ctx, node.label);
|
|
1597
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1598
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1599
|
+
}
|
|
1344
1600
|
}
|
|
1345
1601
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
1346
1602
|
let finalClassExpr = classExpr;
|
|
@@ -1417,6 +1673,9 @@ function emitImageTypeNode(node, ctx) {
|
|
|
1417
1673
|
let elementClass = null;
|
|
1418
1674
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1419
1675
|
elementClass = buildElementClass(ctx, node.label);
|
|
1676
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1677
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1678
|
+
}
|
|
1420
1679
|
}
|
|
1421
1680
|
const { classExpr, styleAttr } = buildClassAndStyleExpression(
|
|
1422
1681
|
style,
|
|
@@ -1426,30 +1685,52 @@ function emitImageTypeNode(node, ctx) {
|
|
|
1426
1685
|
);
|
|
1427
1686
|
const src = node.src;
|
|
1428
1687
|
const alt = node.alt;
|
|
1688
|
+
if (isStaticImageSrc(src, ctx)) {
|
|
1689
|
+
const staticMeta = ctx.imageMetadataMap.get(src);
|
|
1690
|
+
return emitStaticPictureImage(
|
|
1691
|
+
src,
|
|
1692
|
+
alt,
|
|
1693
|
+
void 0,
|
|
1694
|
+
void 0,
|
|
1695
|
+
computeSizesAttribute(style, ctx.breakpoints),
|
|
1696
|
+
classExpr,
|
|
1697
|
+
styleAttr,
|
|
1698
|
+
"",
|
|
1699
|
+
"",
|
|
1700
|
+
staticMeta.blurHash,
|
|
1701
|
+
ctx
|
|
1702
|
+
);
|
|
1703
|
+
}
|
|
1429
1704
|
let imgAttrs = "";
|
|
1430
1705
|
if (src) imgAttrs += ` src="${escapeJSX(String(src))}"`;
|
|
1431
1706
|
if (alt !== void 0) imgAttrs += ` alt="${escapeJSX(String(alt))}"`;
|
|
1432
1707
|
const metadata = src ? ctx.imageMetadataMap?.get(String(src)) : void 0;
|
|
1433
|
-
if (metadata) {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1708
|
+
if (!metadata) {
|
|
1709
|
+
return `${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs} />
|
|
1710
|
+
`;
|
|
1711
|
+
}
|
|
1712
|
+
if (metadata.width !== void 0) imgAttrs += ` width="${metadata.width}"`;
|
|
1713
|
+
if (metadata.height !== void 0) imgAttrs += ` height="${metadata.height}"`;
|
|
1714
|
+
const sizesValue = computeSizesAttribute(style, ctx.breakpoints);
|
|
1715
|
+
const hasAvif = !!(metadata.avifSrcset && ctx.imageFormat !== "webp");
|
|
1716
|
+
const hasBlur = !!metadata.blurHash;
|
|
1717
|
+
const useWrapper = hasAvif || hasBlur;
|
|
1718
|
+
const blurWrapperCss = hasBlur ? `background-image:url(${escapeJSX(metadata.blurHash)});background-size:cover` : "";
|
|
1719
|
+
const blurOnload = hasBlur ? ` onload="this.parentElement.style.backgroundImage=''"` : "";
|
|
1720
|
+
if (useWrapper) {
|
|
1721
|
+
const imgFillClasses = IMG_FILL_CLASSES.slice();
|
|
1722
|
+
const classMatch = classExpr.match(/class="([^"]*)"/);
|
|
1723
|
+
const allClasses = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
|
|
1724
|
+
const { pictureClasses, imgClasses } = splitImageClasses(allClasses);
|
|
1725
|
+
const fullImgClasses = [...imgClasses, ...imgFillClasses];
|
|
1726
|
+
const pictureClassAttr = pictureClasses.length > 0 ? ` class="${pictureClasses.join(" ")}"` : "";
|
|
1727
|
+
const imgClassAttr = fullImgClasses.length > 0 ? ` class="${fullImgClasses.join(" ")}"` : "";
|
|
1728
|
+
const wrapperStyleAttr = injectInlineStyle(styleAttr, blurWrapperCss);
|
|
1729
|
+
if (hasAvif) {
|
|
1730
|
+
return `${ind(ctx)}<picture${pictureClassAttr}${wrapperStyleAttr}>
|
|
1450
1731
|
${ind(ctx)} <source type="image/avif" srcset="${escapeJSX(metadata.avifSrcset)}" sizes="${escapeJSX(sizesValue)}" />
|
|
1451
1732
|
${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
|
|
1452
|
-
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${
|
|
1733
|
+
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurOnload} />
|
|
1453
1734
|
${ind(ctx)}</picture>
|
|
1454
1735
|
`;
|
|
1455
1736
|
}
|
|
@@ -1457,6 +1738,14 @@ ${ind(ctx)}</picture>
|
|
|
1457
1738
|
imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
|
|
1458
1739
|
imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
|
|
1459
1740
|
}
|
|
1741
|
+
return `${ind(ctx)}<picture${pictureClassAttr}${wrapperStyleAttr}>
|
|
1742
|
+
${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurOnload} />
|
|
1743
|
+
${ind(ctx)}</picture>
|
|
1744
|
+
`;
|
|
1745
|
+
}
|
|
1746
|
+
if (metadata.srcset) {
|
|
1747
|
+
imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
|
|
1748
|
+
imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
|
|
1460
1749
|
}
|
|
1461
1750
|
return `${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs} />
|
|
1462
1751
|
`;
|
|
@@ -1567,6 +1856,9 @@ function emitLocaleListNode(node, ctx) {
|
|
|
1567
1856
|
let elementClass = null;
|
|
1568
1857
|
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
1569
1858
|
elementClass = buildElementClass(ctx, node.label);
|
|
1859
|
+
if (elementClass && node.interactiveStyles?.length && ctx.collectedInteractiveStyles) {
|
|
1860
|
+
ctx.collectedInteractiveStyles.set(elementClass, node.interactiveStyles);
|
|
1861
|
+
}
|
|
1570
1862
|
}
|
|
1571
1863
|
const { classExpr: containerClassExpr, styleAttr: containerStyleAttr } = buildClassAndStyleExpression(
|
|
1572
1864
|
style,
|
|
@@ -1575,13 +1867,13 @@ function emitLocaleListNode(node, ctx) {
|
|
|
1575
1867
|
ctx
|
|
1576
1868
|
);
|
|
1577
1869
|
const itemStyle = node.itemStyle;
|
|
1578
|
-
const itemResult = itemStyle ? responsiveStylesToTailwind(itemStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
1870
|
+
const itemResult = itemStyle ? responsiveStylesToTailwind(itemStyle, ctx.breakpoints, ctx.responsiveScales) : { classes: [], dynamicStyles: {} };
|
|
1579
1871
|
const itemClasses = itemResult.classes;
|
|
1580
1872
|
const activeItemStyle = node.activeItemStyle;
|
|
1581
|
-
const activeResult = activeItemStyle ? responsiveStylesToTailwind(activeItemStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
1873
|
+
const activeResult = activeItemStyle ? responsiveStylesToTailwind(activeItemStyle, ctx.breakpoints, ctx.responsiveScales) : { classes: [], dynamicStyles: {} };
|
|
1582
1874
|
const activeItemClasses = [...itemClasses, ...activeResult.classes];
|
|
1583
1875
|
const separatorStyle = node.separatorStyle;
|
|
1584
|
-
const sepResult = separatorStyle ? responsiveStylesToTailwind(separatorStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
1876
|
+
const sepResult = separatorStyle ? responsiveStylesToTailwind(separatorStyle, ctx.breakpoints, ctx.responsiveScales) : { classes: [], dynamicStyles: {} };
|
|
1585
1877
|
const separatorClasses = sepResult.classes;
|
|
1586
1878
|
const localeIconMap = /* @__PURE__ */ new Map();
|
|
1587
1879
|
for (const localeConfig of i18nConfig.locales) {
|
|
@@ -1590,7 +1882,7 @@ function emitLocaleListNode(node, ctx) {
|
|
|
1590
1882
|
}
|
|
1591
1883
|
}
|
|
1592
1884
|
const flagStyle = node.flagStyle;
|
|
1593
|
-
const flagResult = flagStyle ? responsiveStylesToTailwind(flagStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
1885
|
+
const flagResult = flagStyle ? responsiveStylesToTailwind(flagStyle, ctx.breakpoints, ctx.responsiveScales) : { classes: [], dynamicStyles: {} };
|
|
1594
1886
|
const flagClasses = flagResult.classes;
|
|
1595
1887
|
const links = [];
|
|
1596
1888
|
const currentLocale = ctx.locale || i18nConfig.defaultLocale;
|
|
@@ -1776,7 +2068,7 @@ function propDefToTSType(def) {
|
|
|
1776
2068
|
}
|
|
1777
2069
|
function formatDefault(def) {
|
|
1778
2070
|
if (!("default" in def) || def.default === void 0) return null;
|
|
1779
|
-
const val = def.default;
|
|
2071
|
+
const val = stripRawHtmlPrefixDeep(def.default);
|
|
1780
2072
|
if (typeof val === "string") return JSON.stringify(val);
|
|
1781
2073
|
if (typeof val === "number" || typeof val === "boolean") return String(val);
|
|
1782
2074
|
if (typeof val === "object" && val !== null && "_i18n" in val) {
|
|
@@ -1818,7 +2110,7 @@ function mergeClassNameOntoRoot(template) {
|
|
|
1818
2110
|
}
|
|
1819
2111
|
return prefix + tagName + ` class={className}` + attrs + close + template.slice(fullMatch.length);
|
|
1820
2112
|
}
|
|
1821
|
-
function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS, defaultLocale = "en") {
|
|
2113
|
+
function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS, defaultLocale = "en", responsiveScales, remConfig) {
|
|
1822
2114
|
const comp = def.component;
|
|
1823
2115
|
const propDefs = comp.interface || {};
|
|
1824
2116
|
const structure = comp.structure;
|
|
@@ -1836,25 +2128,49 @@ function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREA
|
|
|
1836
2128
|
fileType: "component",
|
|
1837
2129
|
fileName: name,
|
|
1838
2130
|
breakpoints,
|
|
1839
|
-
|
|
2131
|
+
responsiveScales,
|
|
2132
|
+
defaultLocale,
|
|
2133
|
+
imageImports: /* @__PURE__ */ new Map(),
|
|
2134
|
+
fileDepth: 0,
|
|
2135
|
+
// components live at src/components/
|
|
2136
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
1840
2137
|
};
|
|
1841
2138
|
let templateBody = nodeToAstro(structure, ctx);
|
|
1842
2139
|
templateBody = mergeClassNameOntoRoot(templateBody);
|
|
1843
|
-
const frontmatter = buildFrontmatter(
|
|
2140
|
+
const frontmatter = buildFrontmatter(
|
|
2141
|
+
name,
|
|
2142
|
+
propDefs,
|
|
2143
|
+
ctx.imports,
|
|
2144
|
+
ctx.dynamicTags,
|
|
2145
|
+
ctx.needsI18nResolver ? defaultLocale : void 0,
|
|
2146
|
+
ctx.imageImports
|
|
2147
|
+
);
|
|
1844
2148
|
const styleSection = comp.css ? `
|
|
1845
2149
|
<style>
|
|
1846
2150
|
${comp.css}
|
|
1847
2151
|
</style>
|
|
2152
|
+
` : "";
|
|
2153
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2154
|
+
<style is:global>
|
|
2155
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2156
|
+
</style>
|
|
1848
2157
|
` : "";
|
|
1849
2158
|
const scriptSection = comp.javascript ? buildScriptSection(comp.javascript, comp, propDefs) : "";
|
|
1850
2159
|
return `---
|
|
1851
2160
|
${frontmatter}---
|
|
1852
|
-
${templateBody}${styleSection}${scriptSection}`;
|
|
2161
|
+
${templateBody}${styleSection}${interactiveStyleSection}${scriptSection}`;
|
|
1853
2162
|
}
|
|
1854
|
-
function buildFrontmatter(componentName, propDefs, imports, dynamicTags, i18nDefaultLocale) {
|
|
2163
|
+
function buildFrontmatter(componentName, propDefs, imports, dynamicTags, i18nDefaultLocale, imageImports) {
|
|
1855
2164
|
const lines = [];
|
|
1856
2165
|
for (const imp of Array.from(imports).sort()) {
|
|
1857
|
-
lines.push(`import ${imp} from './${imp}.astro';`);
|
|
2166
|
+
lines.push(`import ${astroComponentName(imp)} from './${imp}.astro';`);
|
|
2167
|
+
}
|
|
2168
|
+
if (imageImports && imageImports.size > 0) {
|
|
2169
|
+
lines.push(`import { Picture } from 'astro:assets';`);
|
|
2170
|
+
const sortedImages = Array.from(imageImports.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
2171
|
+
for (const [varName, importPath] of sortedImages) {
|
|
2172
|
+
lines.push(`import ${varName} from '${importPath}';`);
|
|
2173
|
+
}
|
|
1858
2174
|
}
|
|
1859
2175
|
if (lines.length > 0) lines.push("");
|
|
1860
2176
|
const propEntries = Object.entries(propDefs);
|
|
@@ -1948,7 +2264,13 @@ function transformDefineVarsJS(js, varNames) {
|
|
|
1948
2264
|
return result;
|
|
1949
2265
|
}
|
|
1950
2266
|
function buildScriptSection(js, comp, propDefs) {
|
|
1951
|
-
const
|
|
2267
|
+
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);`;
|
|
2268
|
+
const deferWrapper = (innerJS) => `var el = document.currentScript.previousElementSibling;
|
|
2269
|
+
function __init__() {
|
|
2270
|
+
${cleanTextNodes}
|
|
2271
|
+
${innerJS}
|
|
2272
|
+
}
|
|
2273
|
+
if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', __init__); } else { __init__(); }`;
|
|
1952
2274
|
if (comp.defineVars) {
|
|
1953
2275
|
const vars = comp.defineVars === true ? Object.keys(propDefs).filter((k) => k !== "children") : comp.defineVars;
|
|
1954
2276
|
if (vars.length > 0) {
|
|
@@ -1956,23 +2278,25 @@ function buildScriptSection(js, comp, propDefs) {
|
|
|
1956
2278
|
const defineVarsObj = `{ ${vars.join(", ")} }`;
|
|
1957
2279
|
return `
|
|
1958
2280
|
<script define:vars={${defineVarsObj}}>
|
|
1959
|
-
|
|
1960
|
-
${transformedJS}
|
|
2281
|
+
(function(){
|
|
2282
|
+
${deferWrapper(transformedJS)}
|
|
2283
|
+
})();
|
|
1961
2284
|
</script>
|
|
1962
2285
|
`;
|
|
1963
2286
|
}
|
|
1964
2287
|
}
|
|
1965
2288
|
return `
|
|
1966
2289
|
<script is:inline>
|
|
1967
|
-
|
|
1968
|
-
${js}
|
|
2290
|
+
(function(){
|
|
2291
|
+
${deferWrapper(js)}
|
|
2292
|
+
})();
|
|
1969
2293
|
</script>
|
|
1970
2294
|
`;
|
|
1971
2295
|
}
|
|
1972
2296
|
|
|
1973
2297
|
// lib/server/astro/pageEmitter.ts
|
|
1974
2298
|
function escapeTemplateLiteral2(s) {
|
|
1975
|
-
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
2299
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
1976
2300
|
}
|
|
1977
2301
|
function escapeJSX2(s) {
|
|
1978
2302
|
return s.replace(/&/g, "&").replace(/"/g, """);
|
|
@@ -1997,11 +2321,14 @@ function emitAstroPage(options) {
|
|
|
1997
2321
|
ssrFallbacks,
|
|
1998
2322
|
pageName,
|
|
1999
2323
|
breakpoints: breakpointsOpt,
|
|
2324
|
+
responsiveScales,
|
|
2000
2325
|
imageMetadataMap,
|
|
2001
2326
|
i18nConfig,
|
|
2002
2327
|
currentPageSlugMap,
|
|
2003
2328
|
slugMappings,
|
|
2004
|
-
imageFormat
|
|
2329
|
+
imageFormat,
|
|
2330
|
+
processedRawHtml,
|
|
2331
|
+
remConfig
|
|
2005
2332
|
} = options;
|
|
2006
2333
|
const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
|
|
2007
2334
|
const root = pageData.root;
|
|
@@ -2020,6 +2347,7 @@ function emitAstroPage(options) {
|
|
|
2020
2347
|
fileType: "page",
|
|
2021
2348
|
fileName: pageName,
|
|
2022
2349
|
breakpoints,
|
|
2350
|
+
responsiveScales,
|
|
2023
2351
|
imageMetadataMap,
|
|
2024
2352
|
locale,
|
|
2025
2353
|
i18nConfig,
|
|
@@ -2028,7 +2356,11 @@ function emitAstroPage(options) {
|
|
|
2028
2356
|
astroImports: /* @__PURE__ */ new Set(),
|
|
2029
2357
|
slugMappings,
|
|
2030
2358
|
i18nDefaultLocale: i18nConfig?.defaultLocale,
|
|
2031
|
-
imageFormat
|
|
2359
|
+
imageFormat,
|
|
2360
|
+
processedRawHtml,
|
|
2361
|
+
imageImports: /* @__PURE__ */ new Map(),
|
|
2362
|
+
fileDepth,
|
|
2363
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
2032
2364
|
};
|
|
2033
2365
|
const templateBody = nodeToAstro(root, ctx);
|
|
2034
2366
|
const importLines = [];
|
|
@@ -2037,16 +2369,28 @@ function emitAstroPage(options) {
|
|
|
2037
2369
|
importLines.push(`import { ${astroImports.join(", ")} } from 'astro:content';`);
|
|
2038
2370
|
}
|
|
2039
2371
|
importLines.push(`import BaseLayout from '${layoutImportPath2}';`);
|
|
2372
|
+
if (ctx.imageImports && ctx.imageImports.size > 0) {
|
|
2373
|
+
importLines.push(`import { Picture } from 'astro:assets';`);
|
|
2374
|
+
const sortedImages = Array.from(ctx.imageImports.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
2375
|
+
for (const [varName, importPath] of sortedImages) {
|
|
2376
|
+
importLines.push(`import ${varName} from '${importPath}';`);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2040
2379
|
const componentImports = Array.from(ctx.imports).sort();
|
|
2041
2380
|
for (const comp of componentImports) {
|
|
2042
2381
|
const path = componentImportPath(fileDepth, comp);
|
|
2043
|
-
importLines.push(`import ${comp} from '${path}';`);
|
|
2382
|
+
importLines.push(`import ${astroComponentName(comp)} from '${path}';`);
|
|
2044
2383
|
}
|
|
2045
2384
|
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
2046
2385
|
const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
|
|
2047
2386
|
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
2048
2387
|
const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
|
|
2049
2388
|
const extraFrontmatter = ctx.frontmatterLines && ctx.frontmatterLines.length > 0 ? "\n" + ctx.frontmatterLines.join("\n") : "";
|
|
2389
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2390
|
+
<style is:global>
|
|
2391
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2392
|
+
</style>
|
|
2393
|
+
` : "";
|
|
2050
2394
|
return `---
|
|
2051
2395
|
${importLines.join("\n")}${extraFrontmatter}
|
|
2052
2396
|
---
|
|
@@ -2062,7 +2406,7 @@ ${importLines.join("\n")}${extraFrontmatter}
|
|
|
2062
2406
|
<div id="root">
|
|
2063
2407
|
${templateBody} </div>
|
|
2064
2408
|
</BaseLayout>
|
|
2065
|
-
`;
|
|
2409
|
+
${interactiveStyleSection}`;
|
|
2066
2410
|
}
|
|
2067
2411
|
function buildEmptyPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths) {
|
|
2068
2412
|
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
@@ -2087,7 +2431,7 @@ import BaseLayout from '${layoutImport}';
|
|
|
2087
2431
|
|
|
2088
2432
|
// lib/server/astro/cmsPageEmitter.ts
|
|
2089
2433
|
function escapeTemplateLiteral3(s) {
|
|
2090
|
-
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
2434
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
2091
2435
|
}
|
|
2092
2436
|
function escapeJSX3(s) {
|
|
2093
2437
|
return s.replace(/&/g, "&").replace(/"/g, """);
|
|
@@ -2206,10 +2550,13 @@ function emitCMSPage(options) {
|
|
|
2206
2550
|
ssrFallbacks,
|
|
2207
2551
|
pageName,
|
|
2208
2552
|
breakpoints: breakpointsOpt,
|
|
2553
|
+
responsiveScales,
|
|
2209
2554
|
imageMetadataMap,
|
|
2210
2555
|
i18nConfig,
|
|
2211
2556
|
isMultiLocale,
|
|
2212
|
-
slugMappings
|
|
2557
|
+
slugMappings,
|
|
2558
|
+
processedRawHtml,
|
|
2559
|
+
remConfig
|
|
2213
2560
|
} = options;
|
|
2214
2561
|
const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
|
|
2215
2562
|
const binding = "entry";
|
|
@@ -2245,6 +2592,7 @@ function emitCMSPage(options) {
|
|
|
2245
2592
|
fileType: "page",
|
|
2246
2593
|
fileName: pageName,
|
|
2247
2594
|
breakpoints,
|
|
2595
|
+
responsiveScales,
|
|
2248
2596
|
imageMetadataMap,
|
|
2249
2597
|
locale,
|
|
2250
2598
|
cmsMode: true,
|
|
@@ -2253,16 +2601,27 @@ function emitCMSPage(options) {
|
|
|
2253
2601
|
cmsWrapFn: wrapFn,
|
|
2254
2602
|
slugMappings,
|
|
2255
2603
|
i18nDefaultLocale: i18nConfig.defaultLocale,
|
|
2256
|
-
imageFormat: options.imageFormat
|
|
2604
|
+
imageFormat: options.imageFormat,
|
|
2605
|
+
processedRawHtml,
|
|
2606
|
+
imageImports: /* @__PURE__ */ new Map(),
|
|
2607
|
+
fileDepth,
|
|
2608
|
+
collectedInteractiveStyles: /* @__PURE__ */ new Map()
|
|
2257
2609
|
};
|
|
2258
2610
|
const templateBody = nodeToAstro(root, ctx);
|
|
2259
2611
|
const importLines = [];
|
|
2260
2612
|
importLines.push(`import { getCollection } from 'astro:content';`);
|
|
2261
2613
|
importLines.push(`import BaseLayout from '${layoutImportPath2}';`);
|
|
2614
|
+
if (ctx.imageImports && ctx.imageImports.size > 0) {
|
|
2615
|
+
importLines.push(`import { Picture } from 'astro:assets';`);
|
|
2616
|
+
const sortedImages = Array.from(ctx.imageImports.entries()).sort(([a], [b]) => a.localeCompare(b));
|
|
2617
|
+
for (const [varName, importPath] of sortedImages) {
|
|
2618
|
+
importLines.push(`import ${varName} from '${importPath}';`);
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2262
2621
|
const componentImports = Array.from(ctx.imports).sort();
|
|
2263
2622
|
for (const comp of componentImports) {
|
|
2264
2623
|
const path = componentImportPath2(fileDepth, comp);
|
|
2265
|
-
importLines.push(`import ${comp} from '${path}';`);
|
|
2624
|
+
importLines.push(`import ${astroComponentName(comp)} from '${path}';`);
|
|
2266
2625
|
}
|
|
2267
2626
|
const staticPaths = buildGetStaticPaths(cmsSchema, isMultiLocale, i18nConfig, locale);
|
|
2268
2627
|
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
@@ -2277,6 +2636,11 @@ function emitCMSPage(options) {
|
|
|
2277
2636
|
if (v && typeof v === 'object' && v._i18n) return v['${locale}'] ?? v['${i18nConfig.defaultLocale}'] ?? Object.values(v).find(x => x !== true && x !== undefined) ?? '';
|
|
2278
2637
|
return v ?? '';
|
|
2279
2638
|
}`;
|
|
2639
|
+
const interactiveStyleSection = ctx.collectedInteractiveStyles.size > 0 ? `
|
|
2640
|
+
<style is:global>
|
|
2641
|
+
${generateAllInteractiveCSS(ctx.collectedInteractiveStyles, breakpoints, remConfig, responsiveScales)}
|
|
2642
|
+
</style>
|
|
2643
|
+
` : "";
|
|
2280
2644
|
return `---
|
|
2281
2645
|
${importLines.join("\n")}
|
|
2282
2646
|
|
|
@@ -2296,7 +2660,7 @@ ${resolverHelper}
|
|
|
2296
2660
|
<div id="root">
|
|
2297
2661
|
${templateBody} </div>
|
|
2298
2662
|
</BaseLayout>
|
|
2299
|
-
`;
|
|
2663
|
+
${interactiveStyleSection}`;
|
|
2300
2664
|
}
|
|
2301
2665
|
function buildEmptyCMSPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths, cmsSchema, isMultiLocale, i18nConfig, binding, richTextFields) {
|
|
2302
2666
|
const escapedMeta = escapeTemplateLiteral3(meta);
|
|
@@ -2338,25 +2702,32 @@ function isStyleMapping3(value) {
|
|
|
2338
2702
|
function isResponsiveStyle3(style) {
|
|
2339
2703
|
return "base" in style || "tablet" in style || "mobile" in style;
|
|
2340
2704
|
}
|
|
2341
|
-
function collectFromStyle(style, classes, breakpoints) {
|
|
2705
|
+
function collectFromStyle(style, classes, breakpoints, responsiveScales) {
|
|
2342
2706
|
if (!style) return;
|
|
2343
2707
|
if (isResponsiveStyle3(style)) {
|
|
2344
2708
|
for (const [bp, bpStyle] of Object.entries(style)) {
|
|
2345
2709
|
if (!bpStyle) continue;
|
|
2346
2710
|
let prefix = "";
|
|
2711
|
+
let bpName;
|
|
2347
2712
|
if (bp !== "base") {
|
|
2348
2713
|
const bpValue = breakpoints[bp]?.breakpoint;
|
|
2349
2714
|
if (bpValue) {
|
|
2350
2715
|
prefix = `max-[${bpValue}px]:`;
|
|
2716
|
+
bpName = bp;
|
|
2351
2717
|
}
|
|
2352
2718
|
}
|
|
2353
|
-
collectFromFlatStyle(bpStyle, prefix, classes);
|
|
2719
|
+
collectFromFlatStyle(bpStyle, prefix, classes, breakpoints, responsiveScales, bpName);
|
|
2354
2720
|
}
|
|
2355
2721
|
} else {
|
|
2356
|
-
collectFromFlatStyle(style, "", classes);
|
|
2722
|
+
collectFromFlatStyle(style, "", classes, breakpoints, responsiveScales);
|
|
2357
2723
|
}
|
|
2358
2724
|
}
|
|
2359
|
-
function collectFromFlatStyle(style, prefix, classes) {
|
|
2725
|
+
function collectFromFlatStyle(style, prefix, classes, breakpoints, responsiveScales, sourceBreakpoint) {
|
|
2726
|
+
const shouldAutoScale = responsiveScales?.enabled === true && sourceBreakpoint === void 0;
|
|
2727
|
+
const scaleBreakpoints = shouldAutoScale ? Object.entries(breakpoints).map(([name, cfg]) => ({ name, value: cfg?.breakpoint })).filter(
|
|
2728
|
+
(bp) => typeof bp.value === "number" && bp.value > 0
|
|
2729
|
+
).sort((a, b) => b.value - a.value) : [];
|
|
2730
|
+
const baseRef = responsiveScales?.baseReference ?? 16;
|
|
2360
2731
|
for (const [property, value] of Object.entries(style)) {
|
|
2361
2732
|
if (!isStyleMapping3(value)) continue;
|
|
2362
2733
|
for (const [, cssValue] of Object.entries(value.values)) {
|
|
@@ -2364,41 +2735,58 @@ function collectFromFlatStyle(style, prefix, classes) {
|
|
|
2364
2735
|
if (twClass) {
|
|
2365
2736
|
classes.add(prefix ? `${prefix}${twClass}` : twClass);
|
|
2366
2737
|
}
|
|
2738
|
+
if (shouldAutoScale && responsiveScales) {
|
|
2739
|
+
const strValue = String(cssValue);
|
|
2740
|
+
if (strValue === "") continue;
|
|
2741
|
+
for (const { name: bpName, value: bpPixels } of scaleBreakpoints) {
|
|
2742
|
+
const scale = getScaleMultiplier(
|
|
2743
|
+
responsiveScales,
|
|
2744
|
+
property,
|
|
2745
|
+
bpName
|
|
2746
|
+
);
|
|
2747
|
+
if (scale == null) continue;
|
|
2748
|
+
const scaledValue = scalePropertyValue(strValue, baseRef, scale);
|
|
2749
|
+
if (scaledValue == null || scaledValue === strValue) continue;
|
|
2750
|
+
const scaledClass = propertyToTailwind(property, scaledValue);
|
|
2751
|
+
if (!scaledClass) continue;
|
|
2752
|
+
classes.add(`max-[${bpPixels}px]:${scaledClass}`);
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2367
2755
|
}
|
|
2368
2756
|
}
|
|
2369
2757
|
}
|
|
2370
|
-
function walkNode(node, classes, breakpoints) {
|
|
2758
|
+
function walkNode(node, classes, breakpoints, responsiveScales) {
|
|
2371
2759
|
if (!node || typeof node === "string" || typeof node === "number") return;
|
|
2372
2760
|
if (Array.isArray(node)) {
|
|
2373
2761
|
for (const child of node) {
|
|
2374
|
-
walkNode(child, classes, breakpoints);
|
|
2762
|
+
walkNode(child, classes, breakpoints, responsiveScales);
|
|
2375
2763
|
}
|
|
2376
2764
|
return;
|
|
2377
2765
|
}
|
|
2378
2766
|
if ("style" in node && node.style) {
|
|
2379
|
-
collectFromStyle(node.style, classes, breakpoints);
|
|
2767
|
+
collectFromStyle(node.style, classes, breakpoints, responsiveScales);
|
|
2380
2768
|
}
|
|
2381
2769
|
if ("interactiveStyles" in node && Array.isArray(node.interactiveStyles)) {
|
|
2382
2770
|
for (const rule of node.interactiveStyles) {
|
|
2383
2771
|
if (rule.style) {
|
|
2384
|
-
collectFromStyle(rule.style, classes, breakpoints);
|
|
2772
|
+
collectFromStyle(rule.style, classes, breakpoints, responsiveScales);
|
|
2385
2773
|
}
|
|
2386
2774
|
}
|
|
2387
2775
|
}
|
|
2388
2776
|
if ("children" in node && node.children) {
|
|
2389
2777
|
if (Array.isArray(node.children)) {
|
|
2390
2778
|
for (const child of node.children) {
|
|
2391
|
-
walkNode(child, classes, breakpoints);
|
|
2779
|
+
walkNode(child, classes, breakpoints, responsiveScales);
|
|
2392
2780
|
}
|
|
2393
2781
|
}
|
|
2394
2782
|
}
|
|
2395
2783
|
}
|
|
2396
|
-
function collectAllMappingClasses(componentDefs, breakpoints = DEFAULT_BREAKPOINTS) {
|
|
2784
|
+
function collectAllMappingClasses(componentDefs, breakpoints = DEFAULT_BREAKPOINTS, responsiveScales) {
|
|
2397
2785
|
const classes = /* @__PURE__ */ new Set();
|
|
2398
2786
|
for (const def of Object.values(componentDefs)) {
|
|
2399
2787
|
const structure = def.component?.structure;
|
|
2400
2788
|
if (structure) {
|
|
2401
|
-
walkNode(structure, classes, breakpoints);
|
|
2789
|
+
walkNode(structure, classes, breakpoints, responsiveScales);
|
|
2402
2790
|
}
|
|
2403
2791
|
}
|
|
2404
2792
|
return classes;
|
|
@@ -2408,18 +2796,40 @@ function collectAllMappingClasses(componentDefs, breakpoints = DEFAULT_BREAKPOIN
|
|
|
2408
2796
|
function hashContent2(content) {
|
|
2409
2797
|
return createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
2410
2798
|
}
|
|
2411
|
-
function
|
|
2799
|
+
function writePageScript(javascript, scriptsDir) {
|
|
2800
|
+
if (!javascript) return [];
|
|
2801
|
+
const hash = hashContent2(javascript);
|
|
2802
|
+
const scriptFile = `${hash}.js`;
|
|
2803
|
+
if (!existsSync(scriptsDir)) {
|
|
2804
|
+
mkdirSync(scriptsDir, { recursive: true });
|
|
2805
|
+
}
|
|
2806
|
+
const fullScriptPath = join(scriptsDir, scriptFile);
|
|
2807
|
+
if (!existsSync(fullScriptPath)) {
|
|
2808
|
+
writeFileSync(fullScriptPath, javascript, "utf-8");
|
|
2809
|
+
}
|
|
2810
|
+
return [`/_scripts/${scriptFile}`];
|
|
2811
|
+
}
|
|
2812
|
+
function copyDirectory(src, dest, filter) {
|
|
2412
2813
|
if (!existsSync(src)) return;
|
|
2413
2814
|
if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
|
|
2414
2815
|
const files = readdirSync(src);
|
|
2415
2816
|
for (const file of files) {
|
|
2817
|
+
if (filter && !filter(file)) continue;
|
|
2416
2818
|
const srcPath = join(src, file);
|
|
2417
2819
|
const destPath = join(dest, file);
|
|
2418
2820
|
const stat = statSync(srcPath);
|
|
2419
|
-
if (stat.isDirectory()) copyDirectory(srcPath, destPath);
|
|
2821
|
+
if (stat.isDirectory()) copyDirectory(srcPath, destPath, filter);
|
|
2420
2822
|
else copyFileSync(srcPath, destPath);
|
|
2421
2823
|
}
|
|
2422
2824
|
}
|
|
2825
|
+
var imageVariantSuffixRe = new RegExp(
|
|
2826
|
+
`-(${RESPONSIVE_WIDTHS.join("|")})\\.(webp|avif)$`
|
|
2827
|
+
);
|
|
2828
|
+
function shouldCopyImageForAstro(filename) {
|
|
2829
|
+
if (filename === "manifest.json") return false;
|
|
2830
|
+
if (imageVariantSuffixRe.test(filename)) return false;
|
|
2831
|
+
return true;
|
|
2832
|
+
}
|
|
2423
2833
|
function isCMSPage(pageData) {
|
|
2424
2834
|
return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
|
|
2425
2835
|
}
|
|
@@ -2507,14 +2917,10 @@ import BaseLayout from '${importPath}';
|
|
|
2507
2917
|
`;
|
|
2508
2918
|
}
|
|
2509
2919
|
async function buildAstroProject(projectRoot, outputDir) {
|
|
2510
|
-
const startTime = Date.now();
|
|
2511
|
-
console.log("\u{1F3D7}\uFE0F Building Astro export...\n");
|
|
2512
2920
|
configService.reset();
|
|
2513
2921
|
const projectConfig = await loadProjectConfig();
|
|
2514
2922
|
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
|
|
2515
2923
|
const i18nConfig = await loadI18nConfig();
|
|
2516
|
-
console.log(`\u{1F310} Locales: ${i18nConfig.locales.map((l) => l.code).join(", ")} (default: ${i18nConfig.defaultLocale})
|
|
2517
|
-
`);
|
|
2518
2924
|
await migrateTemplatesDirectory();
|
|
2519
2925
|
const { components, warnings, errors: compErrors } = await loadComponentDirectory(projectPaths.components());
|
|
2520
2926
|
const globalComponents = {};
|
|
@@ -2523,12 +2929,9 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2523
2929
|
});
|
|
2524
2930
|
for (const w of warnings) console.warn(` Warning: ${w}`);
|
|
2525
2931
|
for (const e of compErrors) console.error(` Error: ${e}`);
|
|
2526
|
-
console.log(`Loaded ${components.size} global component(s)
|
|
2527
|
-
`);
|
|
2528
2932
|
const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
|
|
2529
2933
|
const cmsService = new CMSService(cmsProvider);
|
|
2530
2934
|
await cmsService.initialize();
|
|
2531
|
-
console.log("CMS service initialized\n");
|
|
2532
2935
|
const themeConfig = await colorService.loadThemeConfig();
|
|
2533
2936
|
const variablesConfig = await variableService.loadConfig();
|
|
2534
2937
|
const breakpoints = await loadBreakpointConfig();
|
|
@@ -2537,10 +2940,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2537
2940
|
const globalLibraries = configService.getLibraries();
|
|
2538
2941
|
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
2539
2942
|
const imageMetadataMap = await buildImageMetadataMap();
|
|
2540
|
-
if (imageMetadataMap.size > 0) {
|
|
2541
|
-
console.log(`Loaded image metadata for ${imageMetadataMap.size} image(s)
|
|
2542
|
-
`);
|
|
2543
|
-
}
|
|
2544
2943
|
const outDir = outputDir || join(projectPaths.project, "astro-export");
|
|
2545
2944
|
if (existsSync(outDir)) {
|
|
2546
2945
|
rmSync(outDir, { recursive: true, force: true });
|
|
@@ -2566,8 +2965,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2566
2965
|
console.warn("No pages found in ./pages directory");
|
|
2567
2966
|
return { pages: 0, cmsPages: 0, collections: 0, errors: 0 };
|
|
2568
2967
|
}
|
|
2569
|
-
console.log(`Found ${pageFiles.length} page(s) to process
|
|
2570
|
-
`);
|
|
2571
2968
|
const slugMappings = [];
|
|
2572
2969
|
for (const file of pageFiles) {
|
|
2573
2970
|
const pageName = file.replace(".json", "");
|
|
@@ -2588,6 +2985,7 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2588
2985
|
const allComponentCSS = /* @__PURE__ */ new Set();
|
|
2589
2986
|
const jsContents = /* @__PURE__ */ new Map();
|
|
2590
2987
|
let errorCount = 0;
|
|
2988
|
+
let projectNeedsFormHandler = false;
|
|
2591
2989
|
function mergeInteractiveStyles(source) {
|
|
2592
2990
|
for (const [key, value] of source) {
|
|
2593
2991
|
if (!allInteractiveStyles.has(key)) {
|
|
@@ -2606,6 +3004,9 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2606
3004
|
jsContents.set(hash, result.javascript);
|
|
2607
3005
|
}
|
|
2608
3006
|
}
|
|
3007
|
+
if (!projectNeedsFormHandler && needsFormHandler(result.html)) {
|
|
3008
|
+
projectNeedsFormHandler = true;
|
|
3009
|
+
}
|
|
2609
3010
|
allResults.push({
|
|
2610
3011
|
html: result.html,
|
|
2611
3012
|
meta: result.meta,
|
|
@@ -2620,7 +3021,8 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2620
3021
|
pageData,
|
|
2621
3022
|
pageName,
|
|
2622
3023
|
isCMSPage: isCMSPage3,
|
|
2623
|
-
ssrFallbackCollector: result.ssrFallbackCollector
|
|
3024
|
+
ssrFallbackCollector: result.ssrFallbackCollector,
|
|
3025
|
+
processedRawHtmlCollector: result.processedRawHtmlCollector
|
|
2624
3026
|
});
|
|
2625
3027
|
}
|
|
2626
3028
|
for (const file of pageFiles) {
|
|
@@ -2636,7 +3038,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2636
3038
|
const pageData = parseJSON(pageContent);
|
|
2637
3039
|
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
2638
3040
|
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
2639
|
-
console.log(` Skipping draft: ${basePath}`);
|
|
2640
3041
|
continue;
|
|
2641
3042
|
}
|
|
2642
3043
|
const slugs = pageData.meta?.slugs;
|
|
@@ -2670,7 +3071,6 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2670
3071
|
// isProductionBuild
|
|
2671
3072
|
);
|
|
2672
3073
|
processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, false);
|
|
2673
|
-
console.log(` Rendered: ${urlPath}`);
|
|
2674
3074
|
}
|
|
2675
3075
|
} catch (error) {
|
|
2676
3076
|
console.error(` Error rendering ${basePath}:`, error?.message || error);
|
|
@@ -2680,18 +3080,45 @@ async function buildAstroProject(projectRoot, outputDir) {
|
|
|
2680
3080
|
const fontPreloads = generateFontPreloadTags();
|
|
2681
3081
|
const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
|
|
2682
3082
|
const buildLibraries = filterLibrariesByContext(mergedLibraries, "build");
|
|
2683
|
-
const
|
|
3083
|
+
const inlineContents = /* @__PURE__ */ new Map();
|
|
3084
|
+
const localLibsToCopy = [];
|
|
3085
|
+
for (const css of buildLibraries.css || []) {
|
|
3086
|
+
if (!css.url.startsWith("/")) continue;
|
|
3087
|
+
const shouldInline = css.inline !== false;
|
|
3088
|
+
const relPath = css.url.slice(1);
|
|
3089
|
+
const srcPath = join(projectPaths.project, relPath);
|
|
3090
|
+
if (!existsSync(srcPath)) continue;
|
|
3091
|
+
if (shouldInline) {
|
|
3092
|
+
try {
|
|
3093
|
+
inlineContents.set(css.url, await readFile(srcPath, "utf-8"));
|
|
3094
|
+
} catch {
|
|
3095
|
+
localLibsToCopy.push(relPath);
|
|
3096
|
+
}
|
|
3097
|
+
} else {
|
|
3098
|
+
localLibsToCopy.push(relPath);
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
for (const js of buildLibraries.js || []) {
|
|
3102
|
+
if (js.url.startsWith("/")) {
|
|
3103
|
+
const relPath = js.url.slice(1);
|
|
3104
|
+
if (existsSync(join(projectPaths.project, relPath))) {
|
|
3105
|
+
localLibsToCopy.push(relPath);
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
const libraryTags = generateLibraryTags(buildLibraries, inlineContents);
|
|
2684
3110
|
const defaultTheme = themeConfig.default || "light";
|
|
3111
|
+
const customCode = configService.getCustomCode();
|
|
3112
|
+
const iconsConfig = await loadIconsConfig();
|
|
3113
|
+
const faviconTag = iconsConfig.favicon ? `<link rel="icon" href="${iconsConfig.favicon.replace(/"/g, """)}" />` : "";
|
|
3114
|
+
const appleTouchIconTag = iconsConfig.appleTouchIcon ? `<link rel="apple-touch-icon" href="${iconsConfig.appleTouchIcon.replace(/"/g, """)}" />` : "";
|
|
3115
|
+
const iconTagsHtml = [faviconTag, appleTouchIconTag].filter(Boolean).join("\n ");
|
|
3116
|
+
const remConversionConfig = configService.getRemConversion();
|
|
2685
3117
|
const templatesDir = projectPaths.templates();
|
|
2686
3118
|
const templateSchemas = [];
|
|
2687
3119
|
let cmsPageCount = 0;
|
|
2688
3120
|
if (existsSync(templatesDir)) {
|
|
2689
3121
|
const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
|
|
2690
|
-
if (templateFiles.length > 0) {
|
|
2691
|
-
console.log(`
|
|
2692
|
-
Processing ${templateFiles.length} CMS template(s)...
|
|
2693
|
-
`);
|
|
2694
|
-
}
|
|
2695
3122
|
for (const file of templateFiles) {
|
|
2696
3123
|
const templateContent = await loadJSONFile(join(templatesDir, file));
|
|
2697
3124
|
if (!templateContent) continue;
|
|
@@ -2699,7 +3126,6 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
2699
3126
|
const pageData = parseJSON(templateContent);
|
|
2700
3127
|
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
2701
3128
|
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
2702
|
-
console.log(` Skipping draft template: ${file}`);
|
|
2703
3129
|
continue;
|
|
2704
3130
|
}
|
|
2705
3131
|
if (!isCMSPage(pageData)) {
|
|
@@ -2708,14 +3134,8 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
2708
3134
|
}
|
|
2709
3135
|
const cmsSchema = pageData.meta.cms;
|
|
2710
3136
|
templateSchemas.push(cmsSchema);
|
|
2711
|
-
console.log(` CMS Collection: ${cmsSchema.id}`);
|
|
2712
3137
|
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
2713
3138
|
const itemCount = items.length;
|
|
2714
|
-
if (itemCount === 0) {
|
|
2715
|
-
console.log(` No items found in cms/${cmsSchema.id}/`);
|
|
2716
|
-
} else {
|
|
2717
|
-
console.log(` Found ${itemCount} item(s)`);
|
|
2718
|
-
}
|
|
2719
3139
|
const defaultLocale = i18nConfig.defaultLocale;
|
|
2720
3140
|
const dummyPath = cmsSchema.urlPattern.replace("{{slug}}", "__placeholder__");
|
|
2721
3141
|
const metaResult = await renderPageSSR(
|
|
@@ -2776,12 +3196,15 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
2776
3196
|
ssrFallbacks,
|
|
2777
3197
|
pageName: file.replace(".json", ""),
|
|
2778
3198
|
breakpoints,
|
|
3199
|
+
responsiveScales,
|
|
2779
3200
|
imageMetadataMap,
|
|
2780
3201
|
i18nConfig,
|
|
2781
3202
|
isMultiLocale: false,
|
|
2782
3203
|
// Each file handles one locale
|
|
2783
3204
|
slugMappings,
|
|
2784
|
-
imageFormat: configService.getImageFormat()
|
|
3205
|
+
imageFormat: configService.getImageFormat(),
|
|
3206
|
+
processedRawHtml: metaResult.processedRawHtmlCollector,
|
|
3207
|
+
remConfig: remConversionConfig
|
|
2785
3208
|
});
|
|
2786
3209
|
const astroFileFull = join(pagesOutDir, astroFilePath);
|
|
2787
3210
|
const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
|
|
@@ -2790,7 +3213,6 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
2790
3213
|
}
|
|
2791
3214
|
await writeFile2(astroFileFull, astroContent, "utf-8");
|
|
2792
3215
|
}
|
|
2793
|
-
console.log(` Generated: ${pathPrefix}[slug].astro (${itemCount} items \xD7 ${localesToEmit.length} locale(s))`);
|
|
2794
3216
|
cmsPageCount += itemCount * i18nConfig.locales.length;
|
|
2795
3217
|
} catch (error) {
|
|
2796
3218
|
console.error(` Error processing template ${file}:`, error?.message || error);
|
|
@@ -2798,29 +3220,36 @@ Processing ${templateFiles.length} CMS template(s)...
|
|
|
2798
3220
|
}
|
|
2799
3221
|
}
|
|
2800
3222
|
}
|
|
2801
|
-
const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints);
|
|
3223
|
+
const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints, responsiveScales);
|
|
2802
3224
|
const fontCSS = generateFontCSS();
|
|
2803
3225
|
const themeColorCSS = generateThemeColorVariablesCSS(themeConfig);
|
|
2804
3226
|
const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
|
|
2805
|
-
const remConversionConfig = configService.getRemConversion();
|
|
2806
|
-
const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints, remConversionConfig);
|
|
2807
3227
|
const componentCSSCombined = Array.from(allComponentCSS).join("\n");
|
|
2808
3228
|
const baseCSS = `@layer base {
|
|
2809
3229
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
2810
3230
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; }
|
|
2811
3231
|
button { background: none; border: none; padding: 0; font: inherit; cursor: pointer; outline: inherit; }
|
|
2812
|
-
img {
|
|
3232
|
+
img { max-width: 100%; height: auto; }
|
|
2813
3233
|
picture { display: block; }
|
|
2814
|
-
.olink { text-decoration: none; display: block; }
|
|
3234
|
+
.olink { text-decoration: none; display: block; color: inherit; }
|
|
2815
3235
|
.oem { display: inline-block; }
|
|
2816
3236
|
}`;
|
|
2817
|
-
const
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
3237
|
+
const safelistClasses = Array.from(mappingClasses);
|
|
3238
|
+
const safelistDirectives = safelistClasses.map((c) => `@source inline("${c}");`).join("\n");
|
|
3239
|
+
const tailwindDirectives = safelistDirectives ? `@import "tailwindcss";
|
|
3240
|
+
|
|
3241
|
+
${safelistDirectives}` : `@import "tailwindcss";`;
|
|
3242
|
+
const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined].filter(Boolean).join("\n\n");
|
|
2821
3243
|
await writeFile2(join(stylesDir, "global.css"), globalCSS, "utf-8");
|
|
2822
|
-
|
|
2823
|
-
|
|
3244
|
+
const escForTemplateLiteral = (s) => s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3245
|
+
const customHeadLiteral = escForTemplateLiteral(customCode.head || "");
|
|
3246
|
+
const customBodyStartLiteral = escForTemplateLiteral(customCode.bodyStart || "");
|
|
3247
|
+
const customBodyEndLiteral = escForTemplateLiteral(customCode.bodyEnd || "");
|
|
3248
|
+
const iconTagsLiteral = escForTemplateLiteral(iconTagsHtml);
|
|
3249
|
+
const formHandlerBlock = projectNeedsFormHandler ? `
|
|
3250
|
+
<script is:inline>
|
|
3251
|
+
${formHandlerScript}
|
|
3252
|
+
</script>` : "";
|
|
2824
3253
|
const baseLayoutContent = `---
|
|
2825
3254
|
import '../styles/global.css';
|
|
2826
3255
|
|
|
@@ -2841,48 +3270,37 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
2841
3270
|
<head>
|
|
2842
3271
|
<meta charset="UTF-8">
|
|
2843
3272
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
3273
|
+
<Fragment set:html={\`${iconTagsLiteral}\`} />
|
|
2844
3274
|
<Fragment set:html={fontPreloads} />
|
|
2845
3275
|
<Fragment set:html={libraryTags.headCSS || ''} />
|
|
2846
3276
|
<Fragment set:html={libraryTags.headJS || ''} />
|
|
2847
3277
|
<Fragment set:html={meta} />
|
|
3278
|
+
<Fragment set:html={\`${customHeadLiteral}\`} />
|
|
2848
3279
|
<title>{title}</title>
|
|
2849
3280
|
</head>
|
|
2850
3281
|
<body>
|
|
3282
|
+
<Fragment set:html={\`${customBodyStartLiteral}\`} />
|
|
2851
3283
|
<slot />
|
|
2852
3284
|
{scripts.map((s) => <script src={s} />)}
|
|
2853
3285
|
<Fragment set:html={libraryTags.bodyEndJS || ''} />
|
|
3286
|
+
<Fragment set:html={\`${customBodyEndLiteral}\`} />${formHandlerBlock}
|
|
2854
3287
|
</body>
|
|
2855
3288
|
</html>
|
|
2856
3289
|
`;
|
|
2857
3290
|
await writeFile2(join(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
|
|
2858
|
-
console.log("Generated BaseLayout.astro");
|
|
2859
3291
|
let componentFileCount = 0;
|
|
2860
3292
|
for (const [compName, compDef] of Object.entries(globalComponents)) {
|
|
2861
3293
|
try {
|
|
2862
|
-
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale);
|
|
3294
|
+
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale, responsiveScales, remConversionConfig);
|
|
2863
3295
|
await writeFile2(join(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
|
|
2864
3296
|
componentFileCount++;
|
|
2865
3297
|
} catch (error) {
|
|
2866
3298
|
console.warn(` Warning: could not generate component ${compName}: ${error?.message}`);
|
|
2867
3299
|
}
|
|
2868
3300
|
}
|
|
2869
|
-
console.log(`Generated ${componentFileCount} component .astro file(s)`);
|
|
2870
3301
|
for (const result of allResults) {
|
|
2871
3302
|
const importPath = layoutImportPath(result.fileDepth);
|
|
2872
|
-
|
|
2873
|
-
if (result.javascript) {
|
|
2874
|
-
const hash = hashContent2(result.javascript);
|
|
2875
|
-
const scriptFile = `${hash}.js`;
|
|
2876
|
-
const scriptPublicPath = `/_scripts/${scriptFile}`;
|
|
2877
|
-
if (!existsSync(scriptsDir)) {
|
|
2878
|
-
mkdirSync(scriptsDir, { recursive: true });
|
|
2879
|
-
}
|
|
2880
|
-
const fullScriptPath = join(scriptsDir, scriptFile);
|
|
2881
|
-
if (!existsSync(fullScriptPath)) {
|
|
2882
|
-
await writeFile2(fullScriptPath, result.javascript, "utf-8");
|
|
2883
|
-
}
|
|
2884
|
-
scriptPaths.push(scriptPublicPath);
|
|
2885
|
-
}
|
|
3303
|
+
let scriptPaths = [];
|
|
2886
3304
|
let astroContent;
|
|
2887
3305
|
if (result.pageData) {
|
|
2888
3306
|
try {
|
|
@@ -2897,23 +3315,28 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
2897
3315
|
theme: defaultTheme,
|
|
2898
3316
|
fontPreloads,
|
|
2899
3317
|
libraryTags,
|
|
2900
|
-
scriptPaths,
|
|
3318
|
+
scriptPaths: [],
|
|
2901
3319
|
layoutImportPath: importPath,
|
|
2902
3320
|
fileDepth: result.fileDepth,
|
|
2903
3321
|
ssrFallbacks,
|
|
2904
3322
|
pageName: result.pageName || "index",
|
|
2905
3323
|
breakpoints,
|
|
3324
|
+
responsiveScales,
|
|
2906
3325
|
imageMetadataMap,
|
|
2907
3326
|
i18nConfig: i18nConfig.locales.length > 1 ? i18nConfig : void 0,
|
|
2908
3327
|
currentPageSlugMap: pageSlugMap,
|
|
2909
3328
|
slugMappings: i18nConfig.locales.length > 1 ? slugMappings : void 0,
|
|
2910
|
-
imageFormat: configService.getImageFormat()
|
|
3329
|
+
imageFormat: configService.getImageFormat(),
|
|
3330
|
+
processedRawHtml: result.processedRawHtmlCollector,
|
|
3331
|
+
remConfig: remConversionConfig
|
|
2911
3332
|
});
|
|
2912
3333
|
} catch (error) {
|
|
2913
3334
|
console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
|
|
3335
|
+
scriptPaths = writePageScript(result.javascript, scriptsDir);
|
|
2914
3336
|
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
2915
3337
|
}
|
|
2916
3338
|
} else {
|
|
3339
|
+
scriptPaths = writePageScript(result.javascript, scriptsDir);
|
|
2917
3340
|
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
2918
3341
|
}
|
|
2919
3342
|
const astroFileFull = join(pagesOutDir, result.astroFilePath);
|
|
@@ -2923,7 +3346,23 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
2923
3346
|
}
|
|
2924
3347
|
await writeFile2(astroFileFull, astroContent, "utf-8");
|
|
2925
3348
|
}
|
|
2926
|
-
|
|
3349
|
+
const robotsTsContent = `import type { APIRoute } from 'astro';
|
|
3350
|
+
|
|
3351
|
+
export const GET: APIRoute = () => {
|
|
3352
|
+
const siteUrl = import.meta.env.SITE;
|
|
3353
|
+
const robotsTxt = [
|
|
3354
|
+
'User-agent: *',
|
|
3355
|
+
'Allow: /',
|
|
3356
|
+
'',
|
|
3357
|
+
siteUrl ? \`Sitemap: \${siteUrl}/sitemap-index.xml\` : '',
|
|
3358
|
+
].filter(Boolean).join('\\n');
|
|
3359
|
+
|
|
3360
|
+
return new Response(robotsTxt, {
|
|
3361
|
+
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
|
|
3362
|
+
});
|
|
3363
|
+
};
|
|
3364
|
+
`;
|
|
3365
|
+
await writeFile2(join(pagesOutDir, "robots.txt.ts"), robotsTsContent, "utf-8");
|
|
2927
3366
|
let collectionCount = 0;
|
|
2928
3367
|
if (templateSchemas.length > 0) {
|
|
2929
3368
|
const contentDir = join(srcDir, "content");
|
|
@@ -2959,7 +3398,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
|
|
|
2959
3398
|
}
|
|
2960
3399
|
}
|
|
2961
3400
|
collectionDefs.push(` '${schema.id}': defineCollection({
|
|
2962
|
-
|
|
3401
|
+
loader: glob({ pattern: '**/*.json', base: './src/content/${schema.id}' }),
|
|
2963
3402
|
schema: z.object({
|
|
2964
3403
|
${fieldDefs.join(",\n")}
|
|
2965
3404
|
})
|
|
@@ -2967,6 +3406,7 @@ ${fieldDefs.join(",\n")}
|
|
|
2967
3406
|
collectionCount++;
|
|
2968
3407
|
}
|
|
2969
3408
|
const configContent = `import { z, defineCollection } from 'astro:content';
|
|
3409
|
+
import { glob } from 'astro/loaders';
|
|
2970
3410
|
|
|
2971
3411
|
const collections = {
|
|
2972
3412
|
${collectionDefs.join(",\n")}
|
|
@@ -2974,25 +3414,30 @@ ${collectionDefs.join(",\n")}
|
|
|
2974
3414
|
|
|
2975
3415
|
export { collections };
|
|
2976
3416
|
`;
|
|
2977
|
-
await writeFile2(join(
|
|
2978
|
-
console.log(`Generated ${collectionCount} content collection(s) with config.ts`);
|
|
3417
|
+
await writeFile2(join(srcDir, "content.config.ts"), configContent, "utf-8");
|
|
2979
3418
|
}
|
|
2980
|
-
const
|
|
2981
|
-
|
|
2982
|
-
|
|
3419
|
+
const imagesSrcDir = join(projectPaths.project, "images");
|
|
3420
|
+
if (existsSync(imagesSrcDir)) {
|
|
3421
|
+
copyDirectory(imagesSrcDir, join(srcDir, "assets", "images"), shouldCopyImageForAstro);
|
|
3422
|
+
copyDirectory(imagesSrcDir, join(publicDir, "images"));
|
|
3423
|
+
}
|
|
3424
|
+
const publicAssetDirs = ["fonts", "icons", "videos", "assets"];
|
|
3425
|
+
for (const dir of publicAssetDirs) {
|
|
2983
3426
|
const srcAssetDir = join(projectPaths.project, dir);
|
|
2984
3427
|
if (existsSync(srcAssetDir)) {
|
|
2985
3428
|
copyDirectory(srcAssetDir, join(publicDir, dir));
|
|
2986
|
-
copiedAssets++;
|
|
2987
3429
|
}
|
|
2988
3430
|
}
|
|
2989
3431
|
const librariesDir = join(projectPaths.project, "libraries");
|
|
2990
3432
|
if (existsSync(librariesDir)) {
|
|
2991
3433
|
copyDirectory(librariesDir, join(publicDir, "libraries"));
|
|
2992
|
-
copiedAssets++;
|
|
2993
3434
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
3435
|
+
for (const relPath of localLibsToCopy) {
|
|
3436
|
+
const srcPath = join(projectPaths.project, relPath);
|
|
3437
|
+
const destPath = join(publicDir, relPath);
|
|
3438
|
+
const destDir = destPath.substring(0, destPath.lastIndexOf("/"));
|
|
3439
|
+
if (destDir && !existsSync(destDir)) mkdirSync(destDir, { recursive: true });
|
|
3440
|
+
copyFileSync(srcPath, destPath);
|
|
2996
3441
|
}
|
|
2997
3442
|
const packageJson = {
|
|
2998
3443
|
name: "astro-export",
|
|
@@ -3006,9 +3451,14 @@ export { collections };
|
|
|
3006
3451
|
preview: "astro preview"
|
|
3007
3452
|
},
|
|
3008
3453
|
dependencies: {
|
|
3009
|
-
"astro": "^
|
|
3010
|
-
"@astrojs/
|
|
3011
|
-
"tailwindcss": "^
|
|
3454
|
+
"astro": "^6.0.0",
|
|
3455
|
+
"@astrojs/sitemap": "^3.0.0",
|
|
3456
|
+
"@tailwindcss/vite": "^4.0.0",
|
|
3457
|
+
"tailwindcss": "^4.0.0"
|
|
3458
|
+
},
|
|
3459
|
+
// Astro 6 expects Vite 7; pin it so npm doesn't pull Vite 8+ and warn.
|
|
3460
|
+
overrides: {
|
|
3461
|
+
"vite": "^7.0.0"
|
|
3012
3462
|
}
|
|
3013
3463
|
};
|
|
3014
3464
|
await writeFile2(join(outDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
|
|
@@ -3020,51 +3470,24 @@ export { collections };
|
|
|
3020
3470
|
routing: { prefixDefaultLocale: false },
|
|
3021
3471
|
},` : "";
|
|
3022
3472
|
const astroConfig = `import { defineConfig } from 'astro/config';
|
|
3023
|
-
import
|
|
3473
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
3474
|
+
import sitemap from '@astrojs/sitemap';
|
|
3024
3475
|
|
|
3025
3476
|
export default defineConfig({${siteUrl ? `
|
|
3026
3477
|
site: '${siteUrl}',` : ""}${i18nBlock}
|
|
3027
|
-
integrations: [
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
const safelistArray = Array.from(mappingClasses);
|
|
3031
|
-
const safelistLiteral = safelistArray.length > 0 ? `
|
|
3032
|
-
safelist: [
|
|
3033
|
-
${safelistArray.map((c) => ` '${c}'`).join(",\n")}
|
|
3034
|
-
],` : "";
|
|
3035
|
-
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
3036
|
-
export default {
|
|
3037
|
-
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],${safelistLiteral}
|
|
3038
|
-
theme: {
|
|
3039
|
-
extend: {},
|
|
3478
|
+
integrations: [sitemap()],
|
|
3479
|
+
vite: {
|
|
3480
|
+
plugins: [tailwindcss()],
|
|
3040
3481
|
},
|
|
3041
|
-
|
|
3042
|
-
};
|
|
3482
|
+
});
|
|
3043
3483
|
`;
|
|
3044
|
-
await writeFile2(join(outDir, "tailwind.config.mjs"), tailwindConfig, "utf-8");
|
|
3045
3484
|
await writeFile2(join(outDir, "astro.config.mjs"), astroConfig, "utf-8");
|
|
3046
3485
|
const tsConfig = {
|
|
3047
3486
|
extends: "astro/tsconfigs/strict"
|
|
3048
3487
|
};
|
|
3049
3488
|
await writeFile2(join(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
|
|
3050
|
-
|
|
3051
|
-
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
3489
|
+
await writeFile2(join(outDir, "src", "env.d.ts"), '/// <reference path="../.astro/types.d.ts" />\n', "utf-8");
|
|
3052
3490
|
const totalPages = allResults.length;
|
|
3053
|
-
console.log("\n" + "=".repeat(50));
|
|
3054
|
-
console.log("Astro export complete!");
|
|
3055
|
-
console.log(` Pages: ${totalPages - cmsPageCount}`);
|
|
3056
|
-
if (cmsPageCount > 0) {
|
|
3057
|
-
console.log(` CMS pages: ${cmsPageCount}`);
|
|
3058
|
-
}
|
|
3059
|
-
if (collectionCount > 0) {
|
|
3060
|
-
console.log(` Content collections: ${collectionCount}`);
|
|
3061
|
-
}
|
|
3062
|
-
if (errorCount > 0) {
|
|
3063
|
-
console.log(` Errors: ${errorCount}`);
|
|
3064
|
-
}
|
|
3065
|
-
console.log(` Time: ${elapsed}s`);
|
|
3066
|
-
console.log(` Output: ${outDir}`);
|
|
3067
|
-
console.log("");
|
|
3068
3491
|
return {
|
|
3069
3492
|
pages: totalPages - cmsPageCount,
|
|
3070
3493
|
cmsPages: cmsPageCount,
|