meno-core 1.0.38 → 1.0.39
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 +914 -0
- package/dist/build-static.js +2 -2
- package/dist/chunks/{chunk-UR7L5UZ3.js → chunk-HNAS6BSS.js} +2 -2
- package/dist/chunks/{chunk-EUCAKI5U.js → chunk-W6HDII4T.js} +8 -1
- package/dist/chunks/{chunk-EUCAKI5U.js.map → chunk-W6HDII4T.js.map} +2 -2
- package/dist/chunks/{chunk-JACS3C25.js → chunk-WK5XLASY.js} +2 -2
- package/dist/entries/server-router.js +2 -2
- package/dist/lib/client/index.js +5 -3
- package/dist/lib/client/index.js.map +2 -2
- package/dist/lib/server/index.js +1840 -5
- package/dist/lib/server/index.js.map +4 -4
- package/dist/lib/shared/index.js +5 -3
- package/dist/lib/shared/index.js.map +2 -2
- package/lib/client/theme.ts +4 -1
- package/lib/server/astro/componentEmitter.ts +208 -0
- package/lib/server/astro/cssCollector.ts +147 -0
- package/lib/server/astro/index.ts +5 -0
- package/lib/server/astro/nodeToAstro.ts +771 -0
- package/lib/server/astro/pageEmitter.ts +190 -0
- package/lib/server/astro/tailwindMapper.ts +547 -0
- package/lib/server/index.ts +3 -0
- package/lib/server/ssr/htmlGenerator.ts +3 -0
- package/lib/server/ssr/ssrRenderer.test.ts +8 -4
- package/lib/server/ssr/ssrRenderer.ts +1 -3
- package/lib/shared/themeDefaults.test.ts +1 -1
- package/lib/shared/themeDefaults.ts +4 -1
- package/package.json +1 -1
- /package/dist/chunks/{chunk-UR7L5UZ3.js.map → chunk-HNAS6BSS.js.map} +0 -0
- /package/dist/chunks/{chunk-JACS3C25.js.map → chunk-WK5XLASY.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-WK5XLASY.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-HNAS6BSS.js";
|
|
36
36
|
import {
|
|
37
37
|
CMSService,
|
|
38
38
|
ColorService,
|
|
@@ -46,22 +46,37 @@ import {
|
|
|
46
46
|
clearJSValidationCache,
|
|
47
47
|
collectComponentCSS,
|
|
48
48
|
collectComponentJavaScript,
|
|
49
|
+
collectComponentLibraries,
|
|
49
50
|
colorService,
|
|
50
51
|
createI18nResolver,
|
|
51
52
|
escapeHtml,
|
|
52
53
|
extractPageMeta,
|
|
54
|
+
filterLibrariesByContext,
|
|
55
|
+
generateFontCSS,
|
|
56
|
+
generateFontPreloadTags,
|
|
57
|
+
generateLibraryTags,
|
|
53
58
|
generateMetaTags,
|
|
54
59
|
generateSSRHTML,
|
|
60
|
+
generateThemeColorVariablesCSS,
|
|
61
|
+
generateVariablesCSS,
|
|
55
62
|
getJSValidationErrors,
|
|
63
|
+
loadBreakpointConfig,
|
|
64
|
+
loadComponentDirectory,
|
|
65
|
+
loadI18nConfig,
|
|
66
|
+
loadJSONFile,
|
|
56
67
|
loadProjectConfig,
|
|
68
|
+
loadResponsiveScalesConfig,
|
|
69
|
+
mapPageNameToPath,
|
|
70
|
+
mergeLibraries,
|
|
57
71
|
migrateTemplatesDirectory,
|
|
72
|
+
parseJSON,
|
|
58
73
|
processCMSPropsTemplate,
|
|
59
74
|
processCMSTemplate,
|
|
60
75
|
renderPageSSR,
|
|
61
76
|
resetFontConfig,
|
|
62
77
|
styleToString,
|
|
63
78
|
variableService
|
|
64
|
-
} from "../../chunks/chunk-
|
|
79
|
+
} from "../../chunks/chunk-W6HDII4T.js";
|
|
65
80
|
import {
|
|
66
81
|
ConfigService,
|
|
67
82
|
configService
|
|
@@ -97,18 +112,1837 @@ import {
|
|
|
97
112
|
import "../../chunks/chunk-LIHJ6OUH.js";
|
|
98
113
|
import "../../chunks/chunk-P3FX5HJM.js";
|
|
99
114
|
import "../../chunks/chunk-AIXKUVNG.js";
|
|
100
|
-
import
|
|
101
|
-
|
|
115
|
+
import {
|
|
116
|
+
extractInteractiveStyleMappings,
|
|
117
|
+
generateAllInteractiveCSS,
|
|
118
|
+
generateElementClassName,
|
|
119
|
+
hasInteractiveStyleMappings,
|
|
120
|
+
isItemDraftForLocale,
|
|
121
|
+
isVoidElement
|
|
122
|
+
} from "../../chunks/chunk-NV25WXCA.js";
|
|
123
|
+
import {
|
|
124
|
+
DEFAULT_BREAKPOINTS,
|
|
125
|
+
isI18nValue,
|
|
126
|
+
resolveI18nValue
|
|
127
|
+
} from "../../chunks/chunk-PGH3ATYI.js";
|
|
102
128
|
import "../../chunks/chunk-UB44F4Z2.js";
|
|
103
129
|
import {
|
|
104
130
|
HMR_ROUTE,
|
|
105
131
|
MAX_PORT_ATTEMPTS,
|
|
132
|
+
NODE_TYPE,
|
|
106
133
|
SERVER_PORT,
|
|
107
134
|
SERVE_PORT,
|
|
108
135
|
init_constants
|
|
109
136
|
} from "../../chunks/chunk-KULPBDC7.js";
|
|
110
137
|
import "../../chunks/chunk-KSBZ2L7C.js";
|
|
111
138
|
|
|
139
|
+
// build-astro.ts
|
|
140
|
+
import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync } from "fs";
|
|
141
|
+
import { writeFile as writeFile2, readFile } from "fs/promises";
|
|
142
|
+
import { join } from "path";
|
|
143
|
+
import { createHash } from "crypto";
|
|
144
|
+
|
|
145
|
+
// lib/server/astro/tailwindMapper.ts
|
|
146
|
+
function isStyleMapping(value) {
|
|
147
|
+
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
148
|
+
}
|
|
149
|
+
function hasTemplateExpression(value) {
|
|
150
|
+
return /\{\{.+?\}\}/.test(value);
|
|
151
|
+
}
|
|
152
|
+
function isResponsiveStyle(style) {
|
|
153
|
+
return "base" in style || "tablet" in style || "mobile" in style;
|
|
154
|
+
}
|
|
155
|
+
var exactMatches = {
|
|
156
|
+
display: {
|
|
157
|
+
flex: "flex",
|
|
158
|
+
grid: "grid",
|
|
159
|
+
block: "block",
|
|
160
|
+
none: "hidden",
|
|
161
|
+
inline: "inline",
|
|
162
|
+
"inline-block": "inline-block",
|
|
163
|
+
"inline-flex": "inline-flex",
|
|
164
|
+
"inline-grid": "inline-grid"
|
|
165
|
+
},
|
|
166
|
+
flexDirection: {
|
|
167
|
+
column: "flex-col",
|
|
168
|
+
row: "flex-row",
|
|
169
|
+
"column-reverse": "flex-col-reverse",
|
|
170
|
+
"row-reverse": "flex-row-reverse"
|
|
171
|
+
},
|
|
172
|
+
justifyContent: {
|
|
173
|
+
center: "justify-center",
|
|
174
|
+
"flex-start": "justify-start",
|
|
175
|
+
"flex-end": "justify-end",
|
|
176
|
+
"space-between": "justify-between",
|
|
177
|
+
"space-around": "justify-around",
|
|
178
|
+
"space-evenly": "justify-evenly",
|
|
179
|
+
// camelCase aliases (component data uses camelCase)
|
|
180
|
+
spaceBetween: "justify-between",
|
|
181
|
+
spaceAround: "justify-around",
|
|
182
|
+
spaceEvenly: "justify-evenly",
|
|
183
|
+
flexStart: "justify-start",
|
|
184
|
+
flexEnd: "justify-end"
|
|
185
|
+
},
|
|
186
|
+
alignItems: {
|
|
187
|
+
center: "items-center",
|
|
188
|
+
"flex-start": "items-start",
|
|
189
|
+
"flex-end": "items-end",
|
|
190
|
+
stretch: "items-stretch",
|
|
191
|
+
baseline: "items-baseline",
|
|
192
|
+
// camelCase aliases
|
|
193
|
+
flexStart: "items-start",
|
|
194
|
+
flexEnd: "items-end"
|
|
195
|
+
},
|
|
196
|
+
alignContent: {
|
|
197
|
+
center: "content-center",
|
|
198
|
+
"flex-start": "content-start",
|
|
199
|
+
"flex-end": "content-end",
|
|
200
|
+
"space-between": "content-between",
|
|
201
|
+
"space-around": "content-around",
|
|
202
|
+
stretch: "content-stretch"
|
|
203
|
+
},
|
|
204
|
+
alignSelf: {
|
|
205
|
+
auto: "self-auto",
|
|
206
|
+
center: "self-center",
|
|
207
|
+
"flex-start": "self-start",
|
|
208
|
+
"flex-end": "self-end",
|
|
209
|
+
stretch: "self-stretch"
|
|
210
|
+
},
|
|
211
|
+
position: {
|
|
212
|
+
relative: "relative",
|
|
213
|
+
absolute: "absolute",
|
|
214
|
+
fixed: "fixed",
|
|
215
|
+
sticky: "sticky",
|
|
216
|
+
static: "static"
|
|
217
|
+
},
|
|
218
|
+
overflow: {
|
|
219
|
+
hidden: "overflow-hidden",
|
|
220
|
+
auto: "overflow-auto",
|
|
221
|
+
scroll: "overflow-scroll",
|
|
222
|
+
visible: "overflow-visible"
|
|
223
|
+
},
|
|
224
|
+
overflowX: {
|
|
225
|
+
hidden: "overflow-x-hidden",
|
|
226
|
+
auto: "overflow-x-auto",
|
|
227
|
+
scroll: "overflow-x-scroll",
|
|
228
|
+
visible: "overflow-x-visible"
|
|
229
|
+
},
|
|
230
|
+
overflowY: {
|
|
231
|
+
hidden: "overflow-y-hidden",
|
|
232
|
+
auto: "overflow-y-auto",
|
|
233
|
+
scroll: "overflow-y-scroll",
|
|
234
|
+
visible: "overflow-y-visible"
|
|
235
|
+
},
|
|
236
|
+
cursor: {
|
|
237
|
+
pointer: "cursor-pointer",
|
|
238
|
+
default: "cursor-default",
|
|
239
|
+
"not-allowed": "cursor-not-allowed",
|
|
240
|
+
grab: "cursor-grab",
|
|
241
|
+
grabbing: "cursor-grabbing",
|
|
242
|
+
text: "cursor-text",
|
|
243
|
+
move: "cursor-move",
|
|
244
|
+
wait: "cursor-wait"
|
|
245
|
+
},
|
|
246
|
+
textAlign: {
|
|
247
|
+
center: "text-center",
|
|
248
|
+
left: "text-left",
|
|
249
|
+
right: "text-right",
|
|
250
|
+
justify: "text-justify"
|
|
251
|
+
},
|
|
252
|
+
textDecoration: {
|
|
253
|
+
none: "no-underline",
|
|
254
|
+
underline: "underline",
|
|
255
|
+
"line-through": "line-through",
|
|
256
|
+
overline: "overline"
|
|
257
|
+
},
|
|
258
|
+
textTransform: {
|
|
259
|
+
uppercase: "uppercase",
|
|
260
|
+
lowercase: "lowercase",
|
|
261
|
+
capitalize: "capitalize",
|
|
262
|
+
none: "normal-case"
|
|
263
|
+
},
|
|
264
|
+
objectFit: {
|
|
265
|
+
cover: "object-cover",
|
|
266
|
+
contain: "object-contain",
|
|
267
|
+
fill: "object-fill",
|
|
268
|
+
none: "object-none",
|
|
269
|
+
"scale-down": "object-scale-down"
|
|
270
|
+
},
|
|
271
|
+
objectPosition: {
|
|
272
|
+
center: "object-center",
|
|
273
|
+
top: "object-top",
|
|
274
|
+
bottom: "object-bottom",
|
|
275
|
+
left: "object-left",
|
|
276
|
+
right: "object-right"
|
|
277
|
+
},
|
|
278
|
+
flexWrap: {
|
|
279
|
+
wrap: "flex-wrap",
|
|
280
|
+
nowrap: "flex-nowrap",
|
|
281
|
+
"wrap-reverse": "flex-wrap-reverse"
|
|
282
|
+
},
|
|
283
|
+
pointerEvents: {
|
|
284
|
+
none: "pointer-events-none",
|
|
285
|
+
auto: "pointer-events-auto"
|
|
286
|
+
},
|
|
287
|
+
userSelect: {
|
|
288
|
+
none: "select-none",
|
|
289
|
+
auto: "select-auto",
|
|
290
|
+
text: "select-text",
|
|
291
|
+
all: "select-all"
|
|
292
|
+
},
|
|
293
|
+
visibility: {
|
|
294
|
+
hidden: "invisible",
|
|
295
|
+
visible: "visible"
|
|
296
|
+
},
|
|
297
|
+
whiteSpace: {
|
|
298
|
+
normal: "whitespace-normal",
|
|
299
|
+
nowrap: "whitespace-nowrap",
|
|
300
|
+
pre: "whitespace-pre",
|
|
301
|
+
"pre-wrap": "whitespace-pre-wrap",
|
|
302
|
+
"pre-line": "whitespace-pre-line"
|
|
303
|
+
},
|
|
304
|
+
wordBreak: {
|
|
305
|
+
"break-all": "break-all",
|
|
306
|
+
"break-word": "break-words",
|
|
307
|
+
normal: "break-normal"
|
|
308
|
+
},
|
|
309
|
+
listStyleType: {
|
|
310
|
+
none: "list-none",
|
|
311
|
+
disc: "list-disc",
|
|
312
|
+
decimal: "list-decimal"
|
|
313
|
+
},
|
|
314
|
+
listStylePosition: {
|
|
315
|
+
inside: "list-inside",
|
|
316
|
+
outside: "list-outside"
|
|
317
|
+
},
|
|
318
|
+
boxSizing: {
|
|
319
|
+
"border-box": "box-border",
|
|
320
|
+
"content-box": "box-content"
|
|
321
|
+
},
|
|
322
|
+
gridAutoFlow: {
|
|
323
|
+
row: "grid-flow-row",
|
|
324
|
+
column: "grid-flow-col",
|
|
325
|
+
dense: "grid-flow-dense",
|
|
326
|
+
"row dense": "grid-flow-row-dense",
|
|
327
|
+
"column dense": "grid-flow-col-dense"
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
var singleValueMatches = {
|
|
331
|
+
// width/height 100%
|
|
332
|
+
"width:100%": "w-full",
|
|
333
|
+
"height:100%": "h-full",
|
|
334
|
+
"width:100vw": "w-screen",
|
|
335
|
+
"height:100vh": "h-screen",
|
|
336
|
+
"width:auto": "w-auto",
|
|
337
|
+
"height:auto": "h-auto",
|
|
338
|
+
"width:fit-content": "w-fit",
|
|
339
|
+
"height:fit-content": "h-fit",
|
|
340
|
+
"width:min-content": "w-min",
|
|
341
|
+
"height:min-content": "h-min",
|
|
342
|
+
"width:max-content": "w-max",
|
|
343
|
+
"height:max-content": "h-max",
|
|
344
|
+
"maxWidth:100%": "max-w-full",
|
|
345
|
+
"maxWidth:none": "max-w-none",
|
|
346
|
+
"maxHeight:100%": "max-h-full",
|
|
347
|
+
"maxHeight:none": "max-h-none",
|
|
348
|
+
"minWidth:0": "min-w-0",
|
|
349
|
+
"minHeight:0": "min-h-0",
|
|
350
|
+
"margin:auto": "m-auto",
|
|
351
|
+
"margin:0 auto": "mx-auto",
|
|
352
|
+
"marginLeft:auto": "ml-auto",
|
|
353
|
+
"marginRight:auto": "mr-auto",
|
|
354
|
+
"marginInline:auto": "mx-auto",
|
|
355
|
+
"borderRadius:50%": "rounded-full",
|
|
356
|
+
"borderRadius:9999px": "rounded-full",
|
|
357
|
+
"borderRadius:0": "rounded-none",
|
|
358
|
+
"flex:1": "flex-1",
|
|
359
|
+
"flex:none": "flex-none",
|
|
360
|
+
"flex:auto": "flex-auto",
|
|
361
|
+
"flexGrow:0": "grow-0",
|
|
362
|
+
"flexGrow:1": "grow",
|
|
363
|
+
"flexShrink:0": "shrink-0",
|
|
364
|
+
"flexShrink:1": "shrink",
|
|
365
|
+
"opacity:0": "opacity-0",
|
|
366
|
+
"opacity:1": "opacity-100",
|
|
367
|
+
"zIndex:0": "z-0",
|
|
368
|
+
"zIndex:10": "z-10",
|
|
369
|
+
"zIndex:20": "z-20",
|
|
370
|
+
"zIndex:30": "z-30",
|
|
371
|
+
"zIndex:40": "z-40",
|
|
372
|
+
"zIndex:50": "z-50",
|
|
373
|
+
"inset:0": "inset-0",
|
|
374
|
+
"top:0": "top-0",
|
|
375
|
+
"right:0": "right-0",
|
|
376
|
+
"bottom:0": "bottom-0",
|
|
377
|
+
"left:0": "left-0"
|
|
378
|
+
};
|
|
379
|
+
var arbitraryPrefixMap = {
|
|
380
|
+
// Spacing
|
|
381
|
+
padding: "p",
|
|
382
|
+
paddingTop: "pt",
|
|
383
|
+
paddingRight: "pr",
|
|
384
|
+
paddingBottom: "pb",
|
|
385
|
+
paddingLeft: "pl",
|
|
386
|
+
paddingInline: "px",
|
|
387
|
+
paddingBlock: "py",
|
|
388
|
+
margin: "m",
|
|
389
|
+
marginTop: "mt",
|
|
390
|
+
marginRight: "mr",
|
|
391
|
+
marginBottom: "mb",
|
|
392
|
+
marginLeft: "ml",
|
|
393
|
+
marginInline: "mx",
|
|
394
|
+
marginBlock: "my",
|
|
395
|
+
gap: "gap",
|
|
396
|
+
rowGap: "gap-y",
|
|
397
|
+
columnGap: "gap-x",
|
|
398
|
+
// Sizing
|
|
399
|
+
width: "w",
|
|
400
|
+
height: "h",
|
|
401
|
+
maxWidth: "max-w",
|
|
402
|
+
maxHeight: "max-h",
|
|
403
|
+
minWidth: "min-w",
|
|
404
|
+
minHeight: "min-h",
|
|
405
|
+
// Typography
|
|
406
|
+
fontSize: "text",
|
|
407
|
+
fontWeight: "font",
|
|
408
|
+
fontFamily: "font",
|
|
409
|
+
lineHeight: "leading",
|
|
410
|
+
letterSpacing: "tracking",
|
|
411
|
+
// Borders
|
|
412
|
+
borderRadius: "rounded",
|
|
413
|
+
borderTopLeftRadius: "rounded-tl",
|
|
414
|
+
borderTopRightRadius: "rounded-tr",
|
|
415
|
+
borderBottomLeftRadius: "rounded-bl",
|
|
416
|
+
borderBottomRightRadius: "rounded-br",
|
|
417
|
+
border: "border",
|
|
418
|
+
borderTop: "border-t",
|
|
419
|
+
borderRight: "border-r",
|
|
420
|
+
borderBottom: "border-b",
|
|
421
|
+
borderLeft: "border-l",
|
|
422
|
+
borderColor: "border",
|
|
423
|
+
// Colors
|
|
424
|
+
color: "text",
|
|
425
|
+
backgroundColor: "bg",
|
|
426
|
+
background: "bg",
|
|
427
|
+
backgroundImage: "bg",
|
|
428
|
+
// Effects
|
|
429
|
+
opacity: "opacity",
|
|
430
|
+
boxShadow: "shadow",
|
|
431
|
+
textShadow: "[text-shadow]",
|
|
432
|
+
filter: "[filter]",
|
|
433
|
+
backdropFilter: "backdrop",
|
|
434
|
+
transform: "[transform]",
|
|
435
|
+
transformOrigin: "origin",
|
|
436
|
+
transition: "transition",
|
|
437
|
+
mixBlendMode: "mix-blend",
|
|
438
|
+
clipPath: "[clip-path]",
|
|
439
|
+
// Positioning
|
|
440
|
+
top: "top",
|
|
441
|
+
right: "right",
|
|
442
|
+
bottom: "bottom",
|
|
443
|
+
left: "left",
|
|
444
|
+
inset: "inset",
|
|
445
|
+
zIndex: "z",
|
|
446
|
+
// Grid
|
|
447
|
+
gridTemplateColumns: "grid-cols",
|
|
448
|
+
gridTemplateRows: "grid-rows",
|
|
449
|
+
gridColumn: "col",
|
|
450
|
+
gridRow: "row",
|
|
451
|
+
gridAutoRows: "auto-rows",
|
|
452
|
+
gridAutoColumns: "auto-cols",
|
|
453
|
+
// Flexbox extras
|
|
454
|
+
flexGrow: "grow",
|
|
455
|
+
flexShrink: "shrink",
|
|
456
|
+
flexBasis: "basis",
|
|
457
|
+
order: "order",
|
|
458
|
+
flex: "flex",
|
|
459
|
+
// Aspect ratio
|
|
460
|
+
aspectRatio: "aspect",
|
|
461
|
+
// Outline
|
|
462
|
+
outline: "outline",
|
|
463
|
+
outlineWidth: "outline",
|
|
464
|
+
outlineOffset: "outline-offset",
|
|
465
|
+
outlineColor: "outline",
|
|
466
|
+
// Other
|
|
467
|
+
accentColor: "accent",
|
|
468
|
+
textIndent: "[text-indent]",
|
|
469
|
+
verticalAlign: "align",
|
|
470
|
+
overflowWrap: "[overflow-wrap]",
|
|
471
|
+
scrollBehavior: "scroll",
|
|
472
|
+
resize: "resize"
|
|
473
|
+
};
|
|
474
|
+
function propertyToTailwind(property, value) {
|
|
475
|
+
const strValue = String(value);
|
|
476
|
+
if (strValue === "") return null;
|
|
477
|
+
if (hasTemplateExpression(strValue)) return null;
|
|
478
|
+
const singleKey = `${property}:${strValue}`;
|
|
479
|
+
if (singleValueMatches[singleKey]) {
|
|
480
|
+
return singleValueMatches[singleKey];
|
|
481
|
+
}
|
|
482
|
+
if (exactMatches[property]?.[strValue]) {
|
|
483
|
+
return exactMatches[property][strValue];
|
|
484
|
+
}
|
|
485
|
+
if (property === "color" || property === "backgroundColor" || property === "borderColor") {
|
|
486
|
+
const prefix = property === "color" ? "text" : property === "backgroundColor" ? "bg" : "border";
|
|
487
|
+
if (strValue.includes("var(")) {
|
|
488
|
+
return `${prefix}-[${strValue}]`;
|
|
489
|
+
}
|
|
490
|
+
if (!strValue.match(/^[#\d]/) && !strValue.includes("rgb") && !strValue.includes("hsl")) {
|
|
491
|
+
return `${prefix}-[var(--${strValue})]`;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
const twPrefix = arbitraryPrefixMap[property];
|
|
495
|
+
if (!twPrefix) {
|
|
496
|
+
const cssProp = property.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
497
|
+
const sanitized2 = strValue.replace(/\s+/g, "_");
|
|
498
|
+
return `[${cssProp}:${sanitized2}]`;
|
|
499
|
+
}
|
|
500
|
+
if (twPrefix.startsWith("[")) {
|
|
501
|
+
const sanitized2 = strValue.replace(/\s+/g, "_");
|
|
502
|
+
return `${twPrefix.slice(0, -1)}:${sanitized2}]`;
|
|
503
|
+
}
|
|
504
|
+
const sanitized = strValue.replace(/\s+/g, "_");
|
|
505
|
+
if (property === "fontFamily" && !sanitized.includes(",") && !sanitized.startsWith("'")) {
|
|
506
|
+
return `${twPrefix}-['${sanitized}']`;
|
|
507
|
+
}
|
|
508
|
+
return `${twPrefix}-[${sanitized}]`;
|
|
509
|
+
}
|
|
510
|
+
function stylesToTailwind(style) {
|
|
511
|
+
const classes = [];
|
|
512
|
+
const dynamicStyles = {};
|
|
513
|
+
for (const [prop, value] of Object.entries(style)) {
|
|
514
|
+
if (isStyleMapping(value)) continue;
|
|
515
|
+
const strValue = String(value);
|
|
516
|
+
if (hasTemplateExpression(strValue)) {
|
|
517
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
518
|
+
dynamicStyles[cssProp] = strValue;
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
const twClass = propertyToTailwind(prop, value);
|
|
522
|
+
if (twClass) {
|
|
523
|
+
classes.push(twClass);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return { classes, dynamicStyles };
|
|
527
|
+
}
|
|
528
|
+
function responsiveStylesToTailwind(style, breakpoints) {
|
|
529
|
+
if (!style) return { classes: [], dynamicStyles: {} };
|
|
530
|
+
const allClasses = [];
|
|
531
|
+
const allDynamicStyles = {};
|
|
532
|
+
if (isResponsiveStyle(style)) {
|
|
533
|
+
const responsive = style;
|
|
534
|
+
if (responsive.base) {
|
|
535
|
+
const { classes, dynamicStyles } = stylesToTailwind(responsive.base);
|
|
536
|
+
allClasses.push(...classes);
|
|
537
|
+
Object.assign(allDynamicStyles, dynamicStyles);
|
|
538
|
+
}
|
|
539
|
+
if (responsive.tablet) {
|
|
540
|
+
const bpValue = breakpoints.tablet?.breakpoint ?? 1024;
|
|
541
|
+
const prefix = `max-[${bpValue}px]:`;
|
|
542
|
+
const { classes, dynamicStyles } = stylesToTailwind(responsive.tablet);
|
|
543
|
+
allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
|
|
544
|
+
Object.assign(allDynamicStyles, dynamicStyles);
|
|
545
|
+
}
|
|
546
|
+
if (responsive.mobile) {
|
|
547
|
+
const bpValue = breakpoints.mobile?.breakpoint ?? 540;
|
|
548
|
+
const prefix = `max-[${bpValue}px]:`;
|
|
549
|
+
const { classes, dynamicStyles } = stylesToTailwind(responsive.mobile);
|
|
550
|
+
allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
|
|
551
|
+
Object.assign(allDynamicStyles, dynamicStyles);
|
|
552
|
+
}
|
|
553
|
+
for (const [bpName, bpStyle] of Object.entries(responsive)) {
|
|
554
|
+
if (bpName === "base" || bpName === "tablet" || bpName === "mobile" || !bpStyle) continue;
|
|
555
|
+
const bpValue = breakpoints[bpName]?.breakpoint;
|
|
556
|
+
if (!bpValue) continue;
|
|
557
|
+
const prefix = `max-[${bpValue}px]:`;
|
|
558
|
+
const { classes, dynamicStyles } = stylesToTailwind(bpStyle);
|
|
559
|
+
allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
|
|
560
|
+
Object.assign(allDynamicStyles, dynamicStyles);
|
|
561
|
+
}
|
|
562
|
+
} else {
|
|
563
|
+
const { classes, dynamicStyles } = stylesToTailwind(style);
|
|
564
|
+
allClasses.push(...classes);
|
|
565
|
+
Object.assign(allDynamicStyles, dynamicStyles);
|
|
566
|
+
}
|
|
567
|
+
return { classes: allClasses, dynamicStyles: allDynamicStyles };
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// lib/server/astro/nodeToAstro.ts
|
|
571
|
+
init_constants();
|
|
572
|
+
function ind(ctx) {
|
|
573
|
+
return " ".repeat(ctx.indent);
|
|
574
|
+
}
|
|
575
|
+
function isStyleMapping2(value) {
|
|
576
|
+
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
577
|
+
}
|
|
578
|
+
function isLinkMapping(value) {
|
|
579
|
+
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
580
|
+
}
|
|
581
|
+
function isHtmlMapping(value) {
|
|
582
|
+
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
583
|
+
}
|
|
584
|
+
function isResponsiveStyle2(style) {
|
|
585
|
+
return "base" in style || "tablet" in style || "mobile" in style;
|
|
586
|
+
}
|
|
587
|
+
function escapeJSX(s) {
|
|
588
|
+
return s.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
589
|
+
}
|
|
590
|
+
function escapeTemplateLiteral(s) {
|
|
591
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
592
|
+
}
|
|
593
|
+
function collectStyleMappings(style) {
|
|
594
|
+
if (!style) return [];
|
|
595
|
+
const result = [];
|
|
596
|
+
if (isResponsiveStyle2(style)) {
|
|
597
|
+
const responsive = style;
|
|
598
|
+
for (const [bp, bpStyle] of Object.entries(responsive)) {
|
|
599
|
+
if (!bpStyle) continue;
|
|
600
|
+
for (const [prop, value] of Object.entries(bpStyle)) {
|
|
601
|
+
if (isStyleMapping2(value)) {
|
|
602
|
+
result.push({ property: prop, mapping: value, breakpoint: bp });
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
for (const [prop, value] of Object.entries(style)) {
|
|
608
|
+
if (isStyleMapping2(value)) {
|
|
609
|
+
result.push({ property: prop, mapping: value });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return result;
|
|
614
|
+
}
|
|
615
|
+
function mappingToClassListEntries(mapping, property, breakpointPrefix, ctx) {
|
|
616
|
+
const entries = [];
|
|
617
|
+
const values = Object.entries(mapping.values);
|
|
618
|
+
if (values.length === 0) return entries;
|
|
619
|
+
const propRef = ctx.isComponentDef ? mapping.prop : mapping.prop;
|
|
620
|
+
if (values.length === 2) {
|
|
621
|
+
const [[val1, css1], [val2, css2]] = values;
|
|
622
|
+
const cls1 = getClassForValue(property, css1, breakpointPrefix);
|
|
623
|
+
const cls2 = getClassForValue(property, css2, breakpointPrefix);
|
|
624
|
+
if (cls1 && cls2) {
|
|
625
|
+
entries.push(`${propRef} === ${JSON.stringify(coerceValue(val1))} ? '${cls1}' : '${cls2}'`);
|
|
626
|
+
}
|
|
627
|
+
} else {
|
|
628
|
+
for (const [val, cssValue] of values) {
|
|
629
|
+
const cls = getClassForValue(property, cssValue, breakpointPrefix);
|
|
630
|
+
if (cls) {
|
|
631
|
+
entries.push(`${propRef} === ${JSON.stringify(coerceValue(val))} && '${cls}'`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return entries;
|
|
636
|
+
}
|
|
637
|
+
function coerceValue(val) {
|
|
638
|
+
if (val === "true") return true;
|
|
639
|
+
if (val === "false") return false;
|
|
640
|
+
return val;
|
|
641
|
+
}
|
|
642
|
+
function getClassForValue(property, value, breakpointPrefix) {
|
|
643
|
+
const twClass = propertyToTailwind(property, value);
|
|
644
|
+
if (!twClass) return null;
|
|
645
|
+
return breakpointPrefix ? `${breakpointPrefix}${twClass}` : twClass;
|
|
646
|
+
}
|
|
647
|
+
function buildClassAndStyleExpression(style, interactiveStyles, elementClass, ctx) {
|
|
648
|
+
const result = style ? responsiveStylesToTailwind(style, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
|
|
649
|
+
const staticClasses = result.classes;
|
|
650
|
+
const dynamicStyles = result.dynamicStyles;
|
|
651
|
+
if (elementClass) {
|
|
652
|
+
staticClasses.unshift(elementClass);
|
|
653
|
+
}
|
|
654
|
+
const conditionals = [];
|
|
655
|
+
const mappings = collectStyleMappings(style);
|
|
656
|
+
for (const { property, mapping, breakpoint } of mappings) {
|
|
657
|
+
const bpValue = breakpoint === "tablet" ? ctx.breakpoints.tablet?.breakpoint ?? 1024 : breakpoint === "mobile" ? ctx.breakpoints.mobile?.breakpoint ?? 540 : 0;
|
|
658
|
+
const prefix = bpValue ? `max-[${bpValue}px]:` : "";
|
|
659
|
+
const entries = mappingToClassListEntries(mapping, property, prefix, ctx);
|
|
660
|
+
conditionals.push(...entries);
|
|
661
|
+
}
|
|
662
|
+
let styleAttr = "";
|
|
663
|
+
if (Object.keys(dynamicStyles).length > 0 && ctx.isComponentDef) {
|
|
664
|
+
const styleParts = [];
|
|
665
|
+
for (const [cssProp, value] of Object.entries(dynamicStyles)) {
|
|
666
|
+
const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
667
|
+
styleParts.push(`${cssProp}: \${${resolved.includes("${") ? resolved.replace(/\$\{(.+?)\}/g, "$1") : `'${resolved}'`}}`);
|
|
668
|
+
}
|
|
669
|
+
const entries = [];
|
|
670
|
+
for (const [cssProp, value] of Object.entries(dynamicStyles)) {
|
|
671
|
+
const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
672
|
+
entries.push(`${cssProp}: ${resolved}`);
|
|
673
|
+
}
|
|
674
|
+
styleAttr = ` style={\`${entries.join("; ")}\`}`;
|
|
675
|
+
}
|
|
676
|
+
if (interactiveStyles && interactiveStyles.length > 0 && ctx.isComponentDef && hasInteractiveStyleMappings(interactiveStyles)) {
|
|
677
|
+
const { mappings: mappings2 } = extractInteractiveStyleMappings(interactiveStyles);
|
|
678
|
+
if (mappings2.length > 0) {
|
|
679
|
+
const varParts = [];
|
|
680
|
+
for (const extracted of mappings2) {
|
|
681
|
+
const { mapping, variableIndex } = extracted;
|
|
682
|
+
const varName = `--is-${variableIndex}`;
|
|
683
|
+
const entries = Object.entries(mapping.values);
|
|
684
|
+
if (entries.length === 2) {
|
|
685
|
+
const [[val1, css1], [val2, css2]] = entries;
|
|
686
|
+
varParts.push(`'${varName}': ${mapping.prop} === ${JSON.stringify(coerceValue(val1))} ? '${css1}' : '${css2}'`);
|
|
687
|
+
} else {
|
|
688
|
+
const lookupEntries = entries.filter(([, v]) => v !== "").map(([k, v]) => `${JSON.stringify(coerceValue(k))}: '${v}'`).join(", ");
|
|
689
|
+
varParts.push(`'${varName}': ({${lookupEntries}})[${mapping.prop}] || ''`);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
if (varParts.length > 0) {
|
|
693
|
+
const existingStyleParts = styleAttr ? styleAttr.replace(/^ style=\{`/, "").replace(/`\}$/, "") : "";
|
|
694
|
+
const varStyleExpr = varParts.join(", ");
|
|
695
|
+
if (existingStyleParts) {
|
|
696
|
+
styleAttr = ` style={\`${existingStyleParts}; \${ Object.entries({${varStyleExpr}}).map(([k,v]) => \`\${k}:\${v}\`).join(';') }\`}`;
|
|
697
|
+
} else {
|
|
698
|
+
styleAttr = ` style={Object.entries({${varStyleExpr}}).map(([k,v]) => \`\${k}:\${v}\`).join(';')}`;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
let classExpr;
|
|
704
|
+
if (conditionals.length === 0) {
|
|
705
|
+
if (staticClasses.length === 0) {
|
|
706
|
+
classExpr = "";
|
|
707
|
+
} else {
|
|
708
|
+
classExpr = ` class="${staticClasses.join(" ")}"`;
|
|
709
|
+
}
|
|
710
|
+
} else {
|
|
711
|
+
const parts = [];
|
|
712
|
+
if (staticClasses.length > 0) {
|
|
713
|
+
parts.push(`'${staticClasses.join(" ")}'`);
|
|
714
|
+
}
|
|
715
|
+
parts.push(...conditionals);
|
|
716
|
+
classExpr = ` class:list={[${parts.join(", ")}]}`;
|
|
717
|
+
}
|
|
718
|
+
return { classExpr, styleAttr };
|
|
719
|
+
}
|
|
720
|
+
function resolveTemplate(text, ctx) {
|
|
721
|
+
if (!ctx.isComponentDef) {
|
|
722
|
+
return text;
|
|
723
|
+
}
|
|
724
|
+
const fullMatch = text.match(/^\{\{(.+)\}\}$/);
|
|
725
|
+
if (fullMatch) {
|
|
726
|
+
return `{${fullMatch[1].trim()}}`;
|
|
727
|
+
}
|
|
728
|
+
return text.replace(/\{\{(.+?)\}\}/g, (_, expr) => `{${expr.trim()}}`);
|
|
729
|
+
}
|
|
730
|
+
function hasTemplates(text) {
|
|
731
|
+
return /\{\{.+?\}\}/.test(text);
|
|
732
|
+
}
|
|
733
|
+
function buildElementClass(ctx, label) {
|
|
734
|
+
return generateElementClassName({
|
|
735
|
+
fileType: ctx.fileType,
|
|
736
|
+
fileName: ctx.fileName,
|
|
737
|
+
label,
|
|
738
|
+
path: ctx.elementPath
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
function buildAttributesString(attributes, ctx) {
|
|
742
|
+
if (!attributes) return "";
|
|
743
|
+
const parts = [];
|
|
744
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
745
|
+
if (typeof value === "boolean") {
|
|
746
|
+
if (value) parts.push(key);
|
|
747
|
+
} else {
|
|
748
|
+
const strVal = String(value);
|
|
749
|
+
if (hasTemplates(strVal) && ctx.isComponentDef) {
|
|
750
|
+
const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
|
|
751
|
+
if (fullMatch) {
|
|
752
|
+
parts.push(`${key}={${fullMatch[1].trim()}}`);
|
|
753
|
+
} else {
|
|
754
|
+
const resolved = strVal.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
755
|
+
parts.push(`${key}={\`${resolved}\`}`);
|
|
756
|
+
}
|
|
757
|
+
} else {
|
|
758
|
+
parts.push(`${key}="${escapeJSX(strVal)}"`);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
763
|
+
}
|
|
764
|
+
function formatPropValue(value) {
|
|
765
|
+
if (typeof value === "string") return `"${escapeJSX(value)}"`;
|
|
766
|
+
if (typeof value === "number") return `{${value}}`;
|
|
767
|
+
if (typeof value === "boolean") return `{${value}}`;
|
|
768
|
+
if (value === null || value === void 0) return `{undefined}`;
|
|
769
|
+
return `{${JSON.stringify(value)}}`;
|
|
770
|
+
}
|
|
771
|
+
function nodeToAstro(node, ctx) {
|
|
772
|
+
if (node === null || node === void 0) return "";
|
|
773
|
+
if (typeof node === "string") {
|
|
774
|
+
if (hasTemplates(node) && ctx.isComponentDef) {
|
|
775
|
+
return `${ind(ctx)}${resolveTemplate(node, ctx)}
|
|
776
|
+
`;
|
|
777
|
+
}
|
|
778
|
+
return `${ind(ctx)}${escapeJSX(node)}
|
|
779
|
+
`;
|
|
780
|
+
}
|
|
781
|
+
if (typeof node === "number") {
|
|
782
|
+
return `${ind(ctx)}${node}
|
|
783
|
+
`;
|
|
784
|
+
}
|
|
785
|
+
if (Array.isArray(node)) {
|
|
786
|
+
let result = "";
|
|
787
|
+
for (let i = 0; i < node.length; i++) {
|
|
788
|
+
const child = node[i];
|
|
789
|
+
const savedPath = [...ctx.elementPath];
|
|
790
|
+
ctx.elementPath = [...ctx.elementPath, i];
|
|
791
|
+
result += nodeToAstro(child, ctx);
|
|
792
|
+
ctx.elementPath = savedPath;
|
|
793
|
+
}
|
|
794
|
+
return result;
|
|
795
|
+
}
|
|
796
|
+
switch (node.type) {
|
|
797
|
+
case NODE_TYPE.NODE:
|
|
798
|
+
return emitHtmlNode(node, ctx);
|
|
799
|
+
case NODE_TYPE.COMPONENT:
|
|
800
|
+
return emitComponentInstance(node, ctx);
|
|
801
|
+
case NODE_TYPE.SLOT:
|
|
802
|
+
return emitSlotMarker(node, ctx);
|
|
803
|
+
case NODE_TYPE.EMBED:
|
|
804
|
+
return emitEmbedNode(node, ctx);
|
|
805
|
+
case NODE_TYPE.LINK:
|
|
806
|
+
return emitLinkNode(node, ctx);
|
|
807
|
+
case NODE_TYPE.LOCALE_LIST:
|
|
808
|
+
return emitFallback(ctx);
|
|
809
|
+
case NODE_TYPE.LIST:
|
|
810
|
+
case "cms-list":
|
|
811
|
+
return emitFallback(ctx);
|
|
812
|
+
default:
|
|
813
|
+
return emitFallback(ctx);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
function emitHtmlNode(node, ctx) {
|
|
817
|
+
let tag = node.tag;
|
|
818
|
+
const label = node.label;
|
|
819
|
+
const style = node.style;
|
|
820
|
+
let isDynamic = false;
|
|
821
|
+
let dynamicTagVar = "";
|
|
822
|
+
if (hasTemplates(tag) && ctx.isComponentDef) {
|
|
823
|
+
isDynamic = true;
|
|
824
|
+
dynamicTagVar = `Tag_${ctx.elementPath.join("_")}`;
|
|
825
|
+
const resolved = tag.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
826
|
+
if (!ctx.dynamicTags) ctx.dynamicTags = /* @__PURE__ */ new Map();
|
|
827
|
+
ctx.dynamicTags.set(dynamicTagVar, resolved);
|
|
828
|
+
tag = dynamicTagVar;
|
|
829
|
+
}
|
|
830
|
+
const ifExpr = emitIfOpen(node, ctx);
|
|
831
|
+
let elementClass = null;
|
|
832
|
+
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
833
|
+
elementClass = buildElementClass(ctx, label);
|
|
834
|
+
}
|
|
835
|
+
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
836
|
+
const attrs = buildAttributesString(node.attributes, ctx);
|
|
837
|
+
const openClose = isDynamic ? dynamicTagVar : tag;
|
|
838
|
+
if (!isDynamic && isVoidElement(tag)) {
|
|
839
|
+
return `${ifExpr}${ind(ctx)}<${tag}${classExpr}${styleAttr}${attrs} />
|
|
840
|
+
${emitIfClose(node, ctx)}`;
|
|
841
|
+
}
|
|
842
|
+
const children = emitChildren(node.children, ctx);
|
|
843
|
+
if (!children.trim() && !isDynamic) {
|
|
844
|
+
return `${ifExpr}${ind(ctx)}<${tag}${classExpr}${styleAttr}${attrs} />
|
|
845
|
+
${emitIfClose(node, ctx)}`;
|
|
846
|
+
}
|
|
847
|
+
return `${ifExpr}${ind(ctx)}<${openClose}${classExpr}${styleAttr}${attrs}>
|
|
848
|
+
` + children + `${ind(ctx)}</${openClose}>
|
|
849
|
+
${emitIfClose(node, ctx)}`;
|
|
850
|
+
}
|
|
851
|
+
function emitComponentInstance(node, ctx) {
|
|
852
|
+
const name = node.component;
|
|
853
|
+
ctx.imports.add(name);
|
|
854
|
+
const ifExpr = emitIfOpen(node, ctx);
|
|
855
|
+
const propParts = [];
|
|
856
|
+
if (node.props) {
|
|
857
|
+
for (const [key, value] of Object.entries(node.props)) {
|
|
858
|
+
if (key === "children") continue;
|
|
859
|
+
if (typeof value === "string" && hasTemplates(value) && ctx.isComponentDef) {
|
|
860
|
+
const fullMatch = value.match(/^\{\{(.+)\}\}$/);
|
|
861
|
+
if (fullMatch) {
|
|
862
|
+
propParts.push(`${key}={${fullMatch[1].trim()}}`);
|
|
863
|
+
} else {
|
|
864
|
+
const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
865
|
+
propParts.push(`${key}={\`${resolved}\`}`);
|
|
866
|
+
}
|
|
867
|
+
} else {
|
|
868
|
+
propParts.push(`${key}=${formatPropValue(value)}`);
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (node.style) {
|
|
873
|
+
const { classes: instanceClasses } = responsiveStylesToTailwind(node.style, ctx.breakpoints);
|
|
874
|
+
if (instanceClasses.length > 0) {
|
|
875
|
+
propParts.push(`class="${instanceClasses.join(" ")}"`);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const propsStr = propParts.length > 0 ? " " + propParts.join(" ") : "";
|
|
879
|
+
const children = emitChildren(node.children, ctx);
|
|
880
|
+
if (!children.trim()) {
|
|
881
|
+
return `${ifExpr}${ind(ctx)}<${name}${propsStr} />
|
|
882
|
+
${emitIfClose(node, ctx)}`;
|
|
883
|
+
}
|
|
884
|
+
return `${ifExpr}${ind(ctx)}<${name}${propsStr}>
|
|
885
|
+
` + children + `${ind(ctx)}</${name}>
|
|
886
|
+
${emitIfClose(node, ctx)}`;
|
|
887
|
+
}
|
|
888
|
+
function emitSlotMarker(node, ctx) {
|
|
889
|
+
if (node.default) {
|
|
890
|
+
const defaultContent = emitChildren(node.default, ctx);
|
|
891
|
+
if (defaultContent.trim()) {
|
|
892
|
+
return `${ind(ctx)}<slot>
|
|
893
|
+
` + defaultContent + `${ind(ctx)}</slot>
|
|
894
|
+
`;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return `${ind(ctx)}<slot />
|
|
898
|
+
`;
|
|
899
|
+
}
|
|
900
|
+
function emitEmbedNode(node, ctx) {
|
|
901
|
+
const ifExpr = emitIfOpen(node, ctx);
|
|
902
|
+
const style = node.style;
|
|
903
|
+
let elementClass = null;
|
|
904
|
+
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
905
|
+
elementClass = buildElementClass(ctx, node.label);
|
|
906
|
+
}
|
|
907
|
+
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
908
|
+
const attrs = buildAttributesString(node.attributes, ctx);
|
|
909
|
+
if (isHtmlMapping(node.html)) {
|
|
910
|
+
if (ctx.isComponentDef) {
|
|
911
|
+
const propRef = node.html.prop;
|
|
912
|
+
return `${ifExpr}${ind(ctx)}<div${classExpr.replace('"', '"oem ') || ' class="oem"'}${attrs}>
|
|
913
|
+
${ind(ctx)} <Fragment set:html={${propRef}} />
|
|
914
|
+
${ind(ctx)}</div>
|
|
915
|
+
${emitIfClose(node, ctx)}`;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
const htmlStr = typeof node.html === "string" ? node.html : "";
|
|
919
|
+
const escapedHtml = escapeTemplateLiteral(htmlStr);
|
|
920
|
+
let finalClassExpr = classExpr;
|
|
921
|
+
if (!classExpr.includes("oem")) {
|
|
922
|
+
if (classExpr) {
|
|
923
|
+
finalClassExpr = classExpr.replace(/class="/, 'class="oem ').replace(/class:list={\['/, "class:list={['oem ");
|
|
924
|
+
} else {
|
|
925
|
+
finalClassExpr = ' class="oem"';
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
return `${ifExpr}${ind(ctx)}<div${finalClassExpr}${attrs}>
|
|
929
|
+
${ind(ctx)} <Fragment set:html={\`${escapedHtml}\`} />
|
|
930
|
+
${ind(ctx)}</div>
|
|
931
|
+
${emitIfClose(node, ctx)}`;
|
|
932
|
+
}
|
|
933
|
+
function emitLinkNode(node, ctx) {
|
|
934
|
+
const ifExpr = emitIfOpen(node, ctx);
|
|
935
|
+
const style = node.style;
|
|
936
|
+
let elementClass = null;
|
|
937
|
+
if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
|
|
938
|
+
elementClass = buildElementClass(ctx, node.label);
|
|
939
|
+
}
|
|
940
|
+
const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
|
|
941
|
+
let finalClassExpr = classExpr;
|
|
942
|
+
if (!classExpr.includes("olink")) {
|
|
943
|
+
if (classExpr) {
|
|
944
|
+
finalClassExpr = classExpr.replace(/class="/, 'class="olink ').replace(/class:list={\['/, "class:list={['olink ");
|
|
945
|
+
} else {
|
|
946
|
+
finalClassExpr = ' class="olink"';
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
let hrefAttr;
|
|
950
|
+
if (isLinkMapping(node.href)) {
|
|
951
|
+
if (ctx.isComponentDef) {
|
|
952
|
+
const propRef = node.href.prop;
|
|
953
|
+
hrefAttr = ` href={${propRef}.href}`;
|
|
954
|
+
} else {
|
|
955
|
+
hrefAttr = ' href="#"';
|
|
956
|
+
}
|
|
957
|
+
} else {
|
|
958
|
+
const href = typeof node.href === "string" ? node.href : "#";
|
|
959
|
+
if (hasTemplates(href) && ctx.isComponentDef) {
|
|
960
|
+
const fullMatch = href.match(/^\{\{(.+)\}\}$/);
|
|
961
|
+
if (fullMatch) {
|
|
962
|
+
hrefAttr = ` href={${fullMatch[1].trim()}}`;
|
|
963
|
+
} else {
|
|
964
|
+
const resolved = href.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
|
|
965
|
+
hrefAttr = ` href={\`${resolved}\`}`;
|
|
966
|
+
}
|
|
967
|
+
} else {
|
|
968
|
+
hrefAttr = ` href="${escapeJSX(href)}"`;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
const attrs = buildAttributesString(node.attributes, ctx);
|
|
972
|
+
const children = emitChildren(node.children, ctx);
|
|
973
|
+
if (!children.trim()) {
|
|
974
|
+
return `${ifExpr}${ind(ctx)}<a${hrefAttr}${finalClassExpr}${styleAttr}${attrs} />
|
|
975
|
+
${emitIfClose(node, ctx)}`;
|
|
976
|
+
}
|
|
977
|
+
return `${ifExpr}${ind(ctx)}<a${hrefAttr}${finalClassExpr}${styleAttr}${attrs}>
|
|
978
|
+
` + children + `${ind(ctx)}</a>
|
|
979
|
+
${emitIfClose(node, ctx)}`;
|
|
980
|
+
}
|
|
981
|
+
function emitFallback(ctx) {
|
|
982
|
+
const pathKey = ctx.elementPath.join(".");
|
|
983
|
+
const ssrHtml = ctx.ssrFallbacks.get(pathKey);
|
|
984
|
+
if (ssrHtml) {
|
|
985
|
+
const escaped = escapeTemplateLiteral(ssrHtml);
|
|
986
|
+
return `${ind(ctx)}<Fragment set:html={\`${escaped}\`} />
|
|
987
|
+
`;
|
|
988
|
+
}
|
|
989
|
+
return `${ind(ctx)}{/* Complex node - SSR fallback not available */}
|
|
990
|
+
`;
|
|
991
|
+
}
|
|
992
|
+
function emitIfOpen(node, ctx) {
|
|
993
|
+
const ifValue = node.if;
|
|
994
|
+
if (ifValue === void 0 || ifValue === true) return "";
|
|
995
|
+
if (typeof ifValue === "boolean") {
|
|
996
|
+
return ifValue ? "" : `${ind(ctx)}{/* hidden */}
|
|
997
|
+
`;
|
|
998
|
+
}
|
|
999
|
+
if (typeof ifValue === "object" && ifValue._mapping && ctx.isComponentDef) {
|
|
1000
|
+
return `${ind(ctx)}{${ifValue.prop} && (
|
|
1001
|
+
`;
|
|
1002
|
+
}
|
|
1003
|
+
if (typeof ifValue === "string" && ctx.isComponentDef) {
|
|
1004
|
+
const fullMatch = ifValue.match(/^\{\{(.+)\}\}$/);
|
|
1005
|
+
const expr = fullMatch ? fullMatch[1].trim() : ifValue.replace(/\{\{(.+?)\}\}/g, "$1");
|
|
1006
|
+
return `${ind(ctx)}{${expr} && (
|
|
1007
|
+
`;
|
|
1008
|
+
}
|
|
1009
|
+
return "";
|
|
1010
|
+
}
|
|
1011
|
+
function emitIfClose(node, ctx) {
|
|
1012
|
+
const ifValue = node.if;
|
|
1013
|
+
if (ifValue === void 0 || ifValue === true) return "";
|
|
1014
|
+
if (typeof ifValue === "boolean") return "";
|
|
1015
|
+
if (typeof ifValue === "object" && ifValue._mapping && ctx.isComponentDef || typeof ifValue === "string" && ctx.isComponentDef) {
|
|
1016
|
+
return `${ind(ctx)})}
|
|
1017
|
+
`;
|
|
1018
|
+
}
|
|
1019
|
+
return "";
|
|
1020
|
+
}
|
|
1021
|
+
function emitChildren(children, ctx) {
|
|
1022
|
+
if (!children) return "";
|
|
1023
|
+
const innerCtx = { ...ctx, indent: ctx.indent + 1, elementPath: [...ctx.elementPath] };
|
|
1024
|
+
if (typeof children === "string") {
|
|
1025
|
+
return nodeToAstro(children, innerCtx);
|
|
1026
|
+
}
|
|
1027
|
+
if (Array.isArray(children)) {
|
|
1028
|
+
return nodeToAstro(children, innerCtx);
|
|
1029
|
+
}
|
|
1030
|
+
return nodeToAstro(children, innerCtx);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// lib/server/astro/componentEmitter.ts
|
|
1034
|
+
function propDefToTSType(def) {
|
|
1035
|
+
switch (def.type) {
|
|
1036
|
+
case "string":
|
|
1037
|
+
case "rich-text":
|
|
1038
|
+
case "file":
|
|
1039
|
+
return "string";
|
|
1040
|
+
case "number":
|
|
1041
|
+
return "number";
|
|
1042
|
+
case "boolean":
|
|
1043
|
+
return "boolean";
|
|
1044
|
+
case "select":
|
|
1045
|
+
if ("options" in def && def.options && def.options.length > 0) {
|
|
1046
|
+
return def.options.map((o) => `'${o}'`).join(" | ");
|
|
1047
|
+
}
|
|
1048
|
+
return "string";
|
|
1049
|
+
case "link":
|
|
1050
|
+
return "{ href: string; target?: string }";
|
|
1051
|
+
case "list":
|
|
1052
|
+
return "any[]";
|
|
1053
|
+
default:
|
|
1054
|
+
return "any";
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
function formatDefault(def) {
|
|
1058
|
+
if (!("default" in def) || def.default === void 0) return null;
|
|
1059
|
+
const val = def.default;
|
|
1060
|
+
if (typeof val === "string") return JSON.stringify(val);
|
|
1061
|
+
if (typeof val === "number" || typeof val === "boolean") return String(val);
|
|
1062
|
+
if (typeof val === "object" && val !== null && "_i18n" in val) {
|
|
1063
|
+
for (const [key, v] of Object.entries(val)) {
|
|
1064
|
+
if (key !== "_i18n" && typeof v === "string") return JSON.stringify(v);
|
|
1065
|
+
}
|
|
1066
|
+
return null;
|
|
1067
|
+
}
|
|
1068
|
+
if (typeof val === "object" && val !== null && "href" in val) {
|
|
1069
|
+
return JSON.stringify(val);
|
|
1070
|
+
}
|
|
1071
|
+
if (Array.isArray(val)) {
|
|
1072
|
+
return JSON.stringify(val);
|
|
1073
|
+
}
|
|
1074
|
+
return JSON.stringify(val);
|
|
1075
|
+
}
|
|
1076
|
+
function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS) {
|
|
1077
|
+
const comp = def.component;
|
|
1078
|
+
const propDefs = comp.interface || {};
|
|
1079
|
+
const structure = comp.structure;
|
|
1080
|
+
if (!structure) {
|
|
1081
|
+
return buildNoStructureComponent(name, comp);
|
|
1082
|
+
}
|
|
1083
|
+
const ctx = {
|
|
1084
|
+
imports: /* @__PURE__ */ new Set(),
|
|
1085
|
+
isComponentDef: true,
|
|
1086
|
+
componentProps: propDefs,
|
|
1087
|
+
globalComponents: allComponents,
|
|
1088
|
+
indent: 0,
|
|
1089
|
+
ssrFallbacks: /* @__PURE__ */ new Map(),
|
|
1090
|
+
elementPath: [0],
|
|
1091
|
+
fileType: "component",
|
|
1092
|
+
fileName: name,
|
|
1093
|
+
breakpoints
|
|
1094
|
+
};
|
|
1095
|
+
const templateBody = nodeToAstro(structure, ctx);
|
|
1096
|
+
const frontmatter = buildFrontmatter(name, propDefs, ctx.imports, ctx.dynamicTags);
|
|
1097
|
+
const styleSection = comp.css ? `
|
|
1098
|
+
<style>
|
|
1099
|
+
${comp.css}
|
|
1100
|
+
</style>
|
|
1101
|
+
` : "";
|
|
1102
|
+
const scriptSection = comp.javascript ? `
|
|
1103
|
+
<script>
|
|
1104
|
+
${comp.javascript}
|
|
1105
|
+
</script>
|
|
1106
|
+
` : "";
|
|
1107
|
+
return `---
|
|
1108
|
+
${frontmatter}---
|
|
1109
|
+
${templateBody}${styleSection}${scriptSection}`;
|
|
1110
|
+
}
|
|
1111
|
+
function buildFrontmatter(componentName, propDefs, imports, dynamicTags) {
|
|
1112
|
+
const lines = [];
|
|
1113
|
+
for (const imp of Array.from(imports).sort()) {
|
|
1114
|
+
lines.push(`import ${imp} from './${imp}.astro';`);
|
|
1115
|
+
}
|
|
1116
|
+
if (lines.length > 0) lines.push("");
|
|
1117
|
+
const propEntries = Object.entries(propDefs);
|
|
1118
|
+
if (propEntries.length > 0) {
|
|
1119
|
+
lines.push("interface Props {");
|
|
1120
|
+
for (const [propName, propDef] of propEntries) {
|
|
1121
|
+
if (propName === "children") continue;
|
|
1122
|
+
const tsType = propDefToTSType(propDef);
|
|
1123
|
+
const optional = "default" in propDef && propDef.default !== void 0;
|
|
1124
|
+
lines.push(` ${propName}${optional ? "?" : ""}: ${tsType};`);
|
|
1125
|
+
}
|
|
1126
|
+
lines.push("}");
|
|
1127
|
+
lines.push("");
|
|
1128
|
+
const destructParts = [];
|
|
1129
|
+
for (const [propName, propDef] of propEntries) {
|
|
1130
|
+
if (propName === "children") continue;
|
|
1131
|
+
const defaultVal = formatDefault(propDef);
|
|
1132
|
+
if (defaultVal !== null) {
|
|
1133
|
+
destructParts.push(`${propName} = ${defaultVal}`);
|
|
1134
|
+
} else {
|
|
1135
|
+
destructParts.push(propName);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (destructParts.length > 0) {
|
|
1139
|
+
if (destructParts.length <= 3 && destructParts.join(", ").length < 80) {
|
|
1140
|
+
lines.push(`const { ${destructParts.join(", ")} } = Astro.props;`);
|
|
1141
|
+
} else {
|
|
1142
|
+
lines.push("const {");
|
|
1143
|
+
for (const part of destructParts) {
|
|
1144
|
+
lines.push(` ${part},`);
|
|
1145
|
+
}
|
|
1146
|
+
lines.push("} = Astro.props;");
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
if (dynamicTags && dynamicTags.size > 0) {
|
|
1151
|
+
lines.push("");
|
|
1152
|
+
for (const [varName, templateExpr] of dynamicTags) {
|
|
1153
|
+
lines.push(`const ${varName} = \`${templateExpr}\`;`);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
if (lines.length > 0) lines.push("");
|
|
1157
|
+
return lines.join("\n");
|
|
1158
|
+
}
|
|
1159
|
+
function buildNoStructureComponent(name, comp) {
|
|
1160
|
+
let content = "---\n---\n<slot />\n";
|
|
1161
|
+
if (comp.css) content += `
|
|
1162
|
+
<style>
|
|
1163
|
+
${comp.css}
|
|
1164
|
+
</style>
|
|
1165
|
+
`;
|
|
1166
|
+
if (comp.javascript) content += `
|
|
1167
|
+
<script>
|
|
1168
|
+
${comp.javascript}
|
|
1169
|
+
</script>
|
|
1170
|
+
`;
|
|
1171
|
+
return content;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// lib/server/astro/pageEmitter.ts
|
|
1175
|
+
function escapeTemplateLiteral2(s) {
|
|
1176
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1177
|
+
}
|
|
1178
|
+
function escapeJSX2(s) {
|
|
1179
|
+
return s.replace(/&/g, "&").replace(/"/g, """);
|
|
1180
|
+
}
|
|
1181
|
+
function componentImportPath(fileDepth, componentName) {
|
|
1182
|
+
const ups = "../".repeat(fileDepth + 1);
|
|
1183
|
+
return `${ups}components/${componentName}.astro`;
|
|
1184
|
+
}
|
|
1185
|
+
function emitAstroPage(options) {
|
|
1186
|
+
const {
|
|
1187
|
+
pageData,
|
|
1188
|
+
globalComponents,
|
|
1189
|
+
title,
|
|
1190
|
+
meta,
|
|
1191
|
+
locale,
|
|
1192
|
+
theme,
|
|
1193
|
+
fontPreloads,
|
|
1194
|
+
libraryTags,
|
|
1195
|
+
scriptPaths,
|
|
1196
|
+
layoutImportPath: layoutImportPath2,
|
|
1197
|
+
fileDepth,
|
|
1198
|
+
ssrFallbacks,
|
|
1199
|
+
pageName,
|
|
1200
|
+
breakpoints: breakpointsOpt
|
|
1201
|
+
} = options;
|
|
1202
|
+
const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
|
|
1203
|
+
const root = pageData.root;
|
|
1204
|
+
if (!root) {
|
|
1205
|
+
return buildEmptyPage(layoutImportPath2, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths);
|
|
1206
|
+
}
|
|
1207
|
+
const ctx = {
|
|
1208
|
+
imports: /* @__PURE__ */ new Set(),
|
|
1209
|
+
isComponentDef: false,
|
|
1210
|
+
componentProps: {},
|
|
1211
|
+
globalComponents,
|
|
1212
|
+
indent: 1,
|
|
1213
|
+
// inside BaseLayout
|
|
1214
|
+
ssrFallbacks,
|
|
1215
|
+
elementPath: [0],
|
|
1216
|
+
fileType: "page",
|
|
1217
|
+
fileName: pageName,
|
|
1218
|
+
breakpoints
|
|
1219
|
+
};
|
|
1220
|
+
const templateBody = nodeToAstro(root, ctx);
|
|
1221
|
+
const importLines = [];
|
|
1222
|
+
importLines.push(`import BaseLayout from '${layoutImportPath2}';`);
|
|
1223
|
+
const componentImports = Array.from(ctx.imports).sort();
|
|
1224
|
+
for (const comp of componentImports) {
|
|
1225
|
+
const path = componentImportPath(fileDepth, comp);
|
|
1226
|
+
importLines.push(`import ${comp} from '${path}';`);
|
|
1227
|
+
}
|
|
1228
|
+
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
1229
|
+
const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
|
|
1230
|
+
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
1231
|
+
const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
|
|
1232
|
+
return `---
|
|
1233
|
+
${importLines.join("\n")}
|
|
1234
|
+
---
|
|
1235
|
+
<BaseLayout
|
|
1236
|
+
title="${escapeJSX2(title)}"
|
|
1237
|
+
meta={\`${escapedMeta}\`}
|
|
1238
|
+
scripts={${scriptsArrayLiteral}}
|
|
1239
|
+
locale="${locale}"
|
|
1240
|
+
theme="${theme}"
|
|
1241
|
+
fontPreloads={\`${escapedFontPreloads}\`}
|
|
1242
|
+
libraryTags={${libraryTagsLiteral}}
|
|
1243
|
+
>
|
|
1244
|
+
${templateBody}</BaseLayout>
|
|
1245
|
+
`;
|
|
1246
|
+
}
|
|
1247
|
+
function buildEmptyPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths) {
|
|
1248
|
+
const escapedMeta = escapeTemplateLiteral2(meta);
|
|
1249
|
+
const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
|
|
1250
|
+
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
1251
|
+
const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
|
|
1252
|
+
return `---
|
|
1253
|
+
import BaseLayout from '${layoutImport}';
|
|
1254
|
+
---
|
|
1255
|
+
<BaseLayout
|
|
1256
|
+
title="${escapeJSX2(title)}"
|
|
1257
|
+
meta={\`${escapedMeta}\`}
|
|
1258
|
+
scripts={${scriptsArrayLiteral}}
|
|
1259
|
+
locale="${locale}"
|
|
1260
|
+
theme="${theme}"
|
|
1261
|
+
fontPreloads={\`${escapedFontPreloads}\`}
|
|
1262
|
+
libraryTags={${libraryTagsLiteral}}
|
|
1263
|
+
>
|
|
1264
|
+
</BaseLayout>
|
|
1265
|
+
`;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// lib/server/astro/cssCollector.ts
|
|
1269
|
+
function isStyleMapping3(value) {
|
|
1270
|
+
return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
|
|
1271
|
+
}
|
|
1272
|
+
function isResponsiveStyle3(style) {
|
|
1273
|
+
return "base" in style || "tablet" in style || "mobile" in style;
|
|
1274
|
+
}
|
|
1275
|
+
function collectFromStyle(style, classes, breakpoints) {
|
|
1276
|
+
if (!style) return;
|
|
1277
|
+
if (isResponsiveStyle3(style)) {
|
|
1278
|
+
for (const [bp, bpStyle] of Object.entries(style)) {
|
|
1279
|
+
if (!bpStyle) continue;
|
|
1280
|
+
let prefix = "";
|
|
1281
|
+
if (bp !== "base") {
|
|
1282
|
+
const bpValue = breakpoints[bp]?.breakpoint;
|
|
1283
|
+
if (bpValue) {
|
|
1284
|
+
prefix = `max-[${bpValue}px]:`;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
collectFromFlatStyle(bpStyle, prefix, classes);
|
|
1288
|
+
}
|
|
1289
|
+
} else {
|
|
1290
|
+
collectFromFlatStyle(style, "", classes);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
function collectFromFlatStyle(style, prefix, classes) {
|
|
1294
|
+
for (const [property, value] of Object.entries(style)) {
|
|
1295
|
+
if (!isStyleMapping3(value)) continue;
|
|
1296
|
+
for (const [, cssValue] of Object.entries(value.values)) {
|
|
1297
|
+
const twClass = propertyToTailwind(property, cssValue);
|
|
1298
|
+
if (twClass) {
|
|
1299
|
+
classes.add(prefix ? `${prefix}${twClass}` : twClass);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
function walkNode(node, classes, breakpoints) {
|
|
1305
|
+
if (!node || typeof node === "string" || typeof node === "number") return;
|
|
1306
|
+
if (Array.isArray(node)) {
|
|
1307
|
+
for (const child of node) {
|
|
1308
|
+
walkNode(child, classes, breakpoints);
|
|
1309
|
+
}
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1312
|
+
if ("style" in node && node.style) {
|
|
1313
|
+
collectFromStyle(node.style, classes, breakpoints);
|
|
1314
|
+
}
|
|
1315
|
+
if ("interactiveStyles" in node && Array.isArray(node.interactiveStyles)) {
|
|
1316
|
+
for (const rule of node.interactiveStyles) {
|
|
1317
|
+
if (rule.style) {
|
|
1318
|
+
collectFromStyle(rule.style, classes, breakpoints);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
if ("children" in node && node.children) {
|
|
1323
|
+
if (Array.isArray(node.children)) {
|
|
1324
|
+
for (const child of node.children) {
|
|
1325
|
+
walkNode(child, classes, breakpoints);
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
function collectAllMappingClasses(componentDefs, breakpoints = DEFAULT_BREAKPOINTS) {
|
|
1331
|
+
const classes = /* @__PURE__ */ new Set();
|
|
1332
|
+
for (const def of Object.values(componentDefs)) {
|
|
1333
|
+
const structure = def.component?.structure;
|
|
1334
|
+
if (structure) {
|
|
1335
|
+
walkNode(structure, classes, breakpoints);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
return classes;
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
// build-astro.ts
|
|
1342
|
+
function hashContent2(content) {
|
|
1343
|
+
return createHash("sha256").update(content).digest("hex").slice(0, 8);
|
|
1344
|
+
}
|
|
1345
|
+
function copyDirectory(src, dest) {
|
|
1346
|
+
if (!existsSync(src)) return;
|
|
1347
|
+
if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
|
|
1348
|
+
const files = readdirSync(src);
|
|
1349
|
+
for (const file of files) {
|
|
1350
|
+
const srcPath = join(src, file);
|
|
1351
|
+
const destPath = join(dest, file);
|
|
1352
|
+
const stat = statSync(srcPath);
|
|
1353
|
+
if (stat.isDirectory()) copyDirectory(srcPath, destPath);
|
|
1354
|
+
else copyFileSync(srcPath, destPath);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
function isCMSPage(pageData) {
|
|
1358
|
+
return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
|
|
1359
|
+
}
|
|
1360
|
+
function buildCMSItemPath(urlPattern, item, slugField, locale, i18nConfig) {
|
|
1361
|
+
let slug = item[slugField] ?? item._slug ?? item._id;
|
|
1362
|
+
if (isI18nValue(slug)) {
|
|
1363
|
+
slug = resolveI18nValue(slug, locale, i18nConfig);
|
|
1364
|
+
}
|
|
1365
|
+
return urlPattern.replace("{{slug}}", String(slug));
|
|
1366
|
+
}
|
|
1367
|
+
function scanJSONFiles(dir, prefix = "") {
|
|
1368
|
+
const results = [];
|
|
1369
|
+
if (!existsSync(dir)) return results;
|
|
1370
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
1371
|
+
for (const entry of entries) {
|
|
1372
|
+
if (entry.isFile() && entry.name.endsWith(".json")) {
|
|
1373
|
+
results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
|
|
1374
|
+
} else if (entry.isDirectory()) {
|
|
1375
|
+
results.push(...scanJSONFiles(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
return results;
|
|
1379
|
+
}
|
|
1380
|
+
function layoutImportPath(fileDepth) {
|
|
1381
|
+
const ups = "../".repeat(fileDepth + 1);
|
|
1382
|
+
return `${ups}layouts/BaseLayout.astro`;
|
|
1383
|
+
}
|
|
1384
|
+
function escapeTemplateLiteral3(s) {
|
|
1385
|
+
return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
1386
|
+
}
|
|
1387
|
+
function cmsFieldToZod(field) {
|
|
1388
|
+
switch (field.type) {
|
|
1389
|
+
case "string":
|
|
1390
|
+
case "text":
|
|
1391
|
+
case "rich-text":
|
|
1392
|
+
return "z.string()";
|
|
1393
|
+
case "number":
|
|
1394
|
+
return "z.number()";
|
|
1395
|
+
case "boolean":
|
|
1396
|
+
return "z.boolean()";
|
|
1397
|
+
case "date":
|
|
1398
|
+
return "z.coerce.date()";
|
|
1399
|
+
case "select":
|
|
1400
|
+
if (field.options && field.options.length > 0) {
|
|
1401
|
+
const opts = field.options.map((o) => `'${o.replace(/'/g, "\\'")}'`).join(", ");
|
|
1402
|
+
return `z.enum([${opts}])`;
|
|
1403
|
+
}
|
|
1404
|
+
return "z.string()";
|
|
1405
|
+
case "image":
|
|
1406
|
+
case "file":
|
|
1407
|
+
return "z.string()";
|
|
1408
|
+
case "reference":
|
|
1409
|
+
return "z.string()";
|
|
1410
|
+
default:
|
|
1411
|
+
return "z.string()";
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
function buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths) {
|
|
1415
|
+
const escapedMeta = escapeTemplateLiteral3(result.meta);
|
|
1416
|
+
const escapedHTML = escapeTemplateLiteral3(result.html);
|
|
1417
|
+
const escapedFontPreloads = escapeTemplateLiteral3(fontPreloads);
|
|
1418
|
+
const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
|
|
1419
|
+
const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral3(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral3(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral3(libraryTags.bodyEndJS || "")}\` }`;
|
|
1420
|
+
return `---
|
|
1421
|
+
import BaseLayout from '${importPath}';
|
|
1422
|
+
---
|
|
1423
|
+
<BaseLayout
|
|
1424
|
+
title="${result.title.replace(/"/g, """)}"
|
|
1425
|
+
meta={\`${escapedMeta}\`}
|
|
1426
|
+
scripts={${scriptsArrayLiteral}}
|
|
1427
|
+
locale="${result.locale}"
|
|
1428
|
+
theme="${defaultTheme}"
|
|
1429
|
+
fontPreloads={\`${escapedFontPreloads}\`}
|
|
1430
|
+
libraryTags={${libraryTagsLiteral}}
|
|
1431
|
+
>
|
|
1432
|
+
<Fragment set:html={\`<div id="root">${escapedHTML}</div>\`} />
|
|
1433
|
+
</BaseLayout>
|
|
1434
|
+
`;
|
|
1435
|
+
}
|
|
1436
|
+
async function buildAstroProject(projectRoot, outputDir) {
|
|
1437
|
+
const startTime = Date.now();
|
|
1438
|
+
console.log("\u{1F3D7}\uFE0F Building Astro export...\n");
|
|
1439
|
+
configService.reset();
|
|
1440
|
+
const projectConfig = await loadProjectConfig();
|
|
1441
|
+
const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
|
|
1442
|
+
const i18nConfig = await loadI18nConfig();
|
|
1443
|
+
console.log(`\u{1F310} Locales: ${i18nConfig.locales.map((l) => l.code).join(", ")} (default: ${i18nConfig.defaultLocale})
|
|
1444
|
+
`);
|
|
1445
|
+
await migrateTemplatesDirectory();
|
|
1446
|
+
const { components, warnings, errors: compErrors } = await loadComponentDirectory(projectPaths.components());
|
|
1447
|
+
const globalComponents = {};
|
|
1448
|
+
components.forEach((value, key) => {
|
|
1449
|
+
globalComponents[key] = value;
|
|
1450
|
+
});
|
|
1451
|
+
for (const w of warnings) console.warn(` Warning: ${w}`);
|
|
1452
|
+
for (const e of compErrors) console.error(` Error: ${e}`);
|
|
1453
|
+
console.log(`Loaded ${components.size} global component(s)
|
|
1454
|
+
`);
|
|
1455
|
+
const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
|
|
1456
|
+
const cmsService = new CMSService(cmsProvider);
|
|
1457
|
+
await cmsService.initialize();
|
|
1458
|
+
console.log("CMS service initialized\n");
|
|
1459
|
+
const themeConfig = await colorService.loadThemeConfig();
|
|
1460
|
+
const variablesConfig = await variableService.loadConfig();
|
|
1461
|
+
const breakpoints = await loadBreakpointConfig();
|
|
1462
|
+
const responsiveScales = await loadResponsiveScalesConfig();
|
|
1463
|
+
await configService.load();
|
|
1464
|
+
const globalLibraries = configService.getLibraries();
|
|
1465
|
+
const componentLibraries = collectComponentLibraries(globalComponents);
|
|
1466
|
+
const outDir = outputDir || join(projectPaths.project, "astro-export");
|
|
1467
|
+
if (existsSync(outDir)) {
|
|
1468
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
1469
|
+
}
|
|
1470
|
+
mkdirSync(outDir, { recursive: true });
|
|
1471
|
+
const srcDir = join(outDir, "src");
|
|
1472
|
+
const pagesOutDir = join(srcDir, "pages");
|
|
1473
|
+
const layoutsDir = join(srcDir, "layouts");
|
|
1474
|
+
const stylesDir = join(srcDir, "styles");
|
|
1475
|
+
const componentsOutDir = join(srcDir, "components");
|
|
1476
|
+
const publicDir = join(outDir, "public");
|
|
1477
|
+
const scriptsDir = join(publicDir, "_scripts");
|
|
1478
|
+
for (const d of [srcDir, pagesOutDir, layoutsDir, stylesDir, componentsOutDir, publicDir]) {
|
|
1479
|
+
mkdirSync(d, { recursive: true });
|
|
1480
|
+
}
|
|
1481
|
+
const pagesDir = projectPaths.pages();
|
|
1482
|
+
if (!existsSync(pagesDir)) {
|
|
1483
|
+
console.error("Pages directory not found!");
|
|
1484
|
+
return { pages: 0, cmsPages: 0, collections: 0, errors: 1 };
|
|
1485
|
+
}
|
|
1486
|
+
const pageFiles = scanJSONFiles(pagesDir);
|
|
1487
|
+
if (pageFiles.length === 0) {
|
|
1488
|
+
console.warn("No pages found in ./pages directory");
|
|
1489
|
+
return { pages: 0, cmsPages: 0, collections: 0, errors: 0 };
|
|
1490
|
+
}
|
|
1491
|
+
console.log(`Found ${pageFiles.length} page(s) to process
|
|
1492
|
+
`);
|
|
1493
|
+
const slugMappings = [];
|
|
1494
|
+
for (const file of pageFiles) {
|
|
1495
|
+
const pageName = file.replace(".json", "");
|
|
1496
|
+
const basePath = mapPageNameToPath(pageName);
|
|
1497
|
+
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
1498
|
+
if (!pageContent) continue;
|
|
1499
|
+
try {
|
|
1500
|
+
const pageData = parseJSON(pageContent);
|
|
1501
|
+
if (pageData.meta?.slugs) {
|
|
1502
|
+
const pageId = basePath === "/" ? "index" : basePath.substring(1);
|
|
1503
|
+
slugMappings.push({ pageId, slugs: pageData.meta.slugs });
|
|
1504
|
+
}
|
|
1505
|
+
} catch {
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
const allResults = [];
|
|
1509
|
+
const allInteractiveStyles = /* @__PURE__ */ new Map();
|
|
1510
|
+
const allComponentCSS = /* @__PURE__ */ new Set();
|
|
1511
|
+
const jsContents = /* @__PURE__ */ new Map();
|
|
1512
|
+
let errorCount = 0;
|
|
1513
|
+
function mergeInteractiveStyles(source) {
|
|
1514
|
+
for (const [key, value] of source) {
|
|
1515
|
+
if (!allInteractiveStyles.has(key)) {
|
|
1516
|
+
allInteractiveStyles.set(key, value);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
function processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, isCMSPage2) {
|
|
1521
|
+
mergeInteractiveStyles(result.interactiveStylesMap);
|
|
1522
|
+
if (result.componentCSS) {
|
|
1523
|
+
allComponentCSS.add(result.componentCSS);
|
|
1524
|
+
}
|
|
1525
|
+
if (result.javascript) {
|
|
1526
|
+
const hash = hashContent2(result.javascript);
|
|
1527
|
+
if (!jsContents.has(hash)) {
|
|
1528
|
+
jsContents.set(hash, result.javascript);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
allResults.push({
|
|
1532
|
+
html: result.html,
|
|
1533
|
+
meta: result.meta,
|
|
1534
|
+
title: result.title,
|
|
1535
|
+
javascript: result.javascript,
|
|
1536
|
+
componentCSS: result.componentCSS,
|
|
1537
|
+
locale: result.locale,
|
|
1538
|
+
interactiveStylesMap: result.interactiveStylesMap,
|
|
1539
|
+
urlPath,
|
|
1540
|
+
fileDepth,
|
|
1541
|
+
astroFilePath,
|
|
1542
|
+
pageData,
|
|
1543
|
+
pageName,
|
|
1544
|
+
isCMSPage: isCMSPage2
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
for (const file of pageFiles) {
|
|
1548
|
+
const pageName = file.replace(".json", "");
|
|
1549
|
+
const basePath = mapPageNameToPath(pageName);
|
|
1550
|
+
const pageContent = await loadJSONFile(join(pagesDir, file));
|
|
1551
|
+
if (!pageContent) {
|
|
1552
|
+
console.warn(` Skipping ${basePath} (empty file)`);
|
|
1553
|
+
errorCount++;
|
|
1554
|
+
continue;
|
|
1555
|
+
}
|
|
1556
|
+
try {
|
|
1557
|
+
const pageData = parseJSON(pageContent);
|
|
1558
|
+
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
1559
|
+
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
1560
|
+
console.log(` Skipping draft: ${basePath}`);
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1563
|
+
const slugs = pageData.meta?.slugs;
|
|
1564
|
+
for (const localeConfig of i18nConfig.locales) {
|
|
1565
|
+
const locale = localeConfig.code;
|
|
1566
|
+
const isDefault = locale === i18nConfig.defaultLocale;
|
|
1567
|
+
let slug;
|
|
1568
|
+
if (slugs && slugs[locale]) {
|
|
1569
|
+
slug = slugs[locale];
|
|
1570
|
+
} else if (basePath === "/") {
|
|
1571
|
+
slug = "";
|
|
1572
|
+
} else {
|
|
1573
|
+
slug = basePath.substring(1);
|
|
1574
|
+
}
|
|
1575
|
+
const urlPath = isDefault ? slug === "" ? "/" : `/${slug}` : slug === "" ? `/${locale}` : `/${locale}/${slug}`;
|
|
1576
|
+
const astroFileName = slug === "" ? "index.astro" : `${slug}.astro`;
|
|
1577
|
+
const astroFilePath = isDefault ? astroFileName : `${locale}/${astroFileName}`;
|
|
1578
|
+
const fileDepth = astroFilePath.split("/").length - 1;
|
|
1579
|
+
const result = await renderPageSSR(
|
|
1580
|
+
pageData,
|
|
1581
|
+
globalComponents,
|
|
1582
|
+
urlPath,
|
|
1583
|
+
siteUrl,
|
|
1584
|
+
locale,
|
|
1585
|
+
i18nConfig,
|
|
1586
|
+
slugMappings,
|
|
1587
|
+
void 0,
|
|
1588
|
+
// cmsContext
|
|
1589
|
+
cmsService,
|
|
1590
|
+
true
|
|
1591
|
+
// isProductionBuild
|
|
1592
|
+
);
|
|
1593
|
+
processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, false);
|
|
1594
|
+
console.log(` Rendered: ${urlPath}`);
|
|
1595
|
+
}
|
|
1596
|
+
} catch (error) {
|
|
1597
|
+
console.error(` Error rendering ${basePath}:`, error?.message || error);
|
|
1598
|
+
errorCount++;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
const templatesDir = projectPaths.templates();
|
|
1602
|
+
const templateSchemas = [];
|
|
1603
|
+
let cmsPageCount = 0;
|
|
1604
|
+
if (existsSync(templatesDir)) {
|
|
1605
|
+
const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
|
|
1606
|
+
if (templateFiles.length > 0) {
|
|
1607
|
+
console.log(`
|
|
1608
|
+
Processing ${templateFiles.length} CMS template(s)...
|
|
1609
|
+
`);
|
|
1610
|
+
}
|
|
1611
|
+
for (const file of templateFiles) {
|
|
1612
|
+
const templateContent = await loadJSONFile(join(templatesDir, file));
|
|
1613
|
+
if (!templateContent) continue;
|
|
1614
|
+
try {
|
|
1615
|
+
const pageData = parseJSON(templateContent);
|
|
1616
|
+
const isDevBuild = process.env.MENO_DEV_BUILD === "true";
|
|
1617
|
+
if (pageData.meta?.draft === true && !isDevBuild) {
|
|
1618
|
+
console.log(` Skipping draft template: ${file}`);
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
if (!isCMSPage(pageData)) {
|
|
1622
|
+
console.warn(` ${file} is in templates/ but missing meta.source: "cms"`);
|
|
1623
|
+
continue;
|
|
1624
|
+
}
|
|
1625
|
+
const cmsSchema = pageData.meta.cms;
|
|
1626
|
+
templateSchemas.push(cmsSchema);
|
|
1627
|
+
console.log(` CMS Collection: ${cmsSchema.id}`);
|
|
1628
|
+
const items = await cmsService.queryItems({ collection: cmsSchema.id });
|
|
1629
|
+
if (items.length === 0) {
|
|
1630
|
+
console.log(` No items found in cms/${cmsSchema.id}/`);
|
|
1631
|
+
continue;
|
|
1632
|
+
}
|
|
1633
|
+
console.log(` Found ${items.length} item(s)`);
|
|
1634
|
+
for (const item of items) {
|
|
1635
|
+
for (const localeConfig of i18nConfig.locales) {
|
|
1636
|
+
const locale = localeConfig.code;
|
|
1637
|
+
const isDefault = locale === i18nConfig.defaultLocale;
|
|
1638
|
+
const isDevBuild2 = process.env.MENO_DEV_BUILD === "true";
|
|
1639
|
+
if (!isDevBuild2 && isItemDraftForLocale(item, locale)) {
|
|
1640
|
+
continue;
|
|
1641
|
+
}
|
|
1642
|
+
const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);
|
|
1643
|
+
const itemWithUrl = { ...item, _url: itemPath };
|
|
1644
|
+
const result = await renderPageSSR(
|
|
1645
|
+
pageData,
|
|
1646
|
+
globalComponents,
|
|
1647
|
+
itemPath,
|
|
1648
|
+
siteUrl,
|
|
1649
|
+
locale,
|
|
1650
|
+
i18nConfig,
|
|
1651
|
+
slugMappings,
|
|
1652
|
+
{ cms: itemWithUrl },
|
|
1653
|
+
cmsService,
|
|
1654
|
+
true
|
|
1655
|
+
);
|
|
1656
|
+
const pathWithoutSlash = itemPath.startsWith("/") ? itemPath.substring(1) : itemPath;
|
|
1657
|
+
const astroFilePath = isDefault ? `${pathWithoutSlash}.astro` : `${locale}/${pathWithoutSlash}.astro`;
|
|
1658
|
+
const fileDepth = astroFilePath.split("/").length - 1;
|
|
1659
|
+
const urlPath = isDefault ? itemPath : `/${locale}${itemPath}`;
|
|
1660
|
+
processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, file.replace(".json", ""), true);
|
|
1661
|
+
console.log(` Rendered: ${urlPath}`);
|
|
1662
|
+
cmsPageCount++;
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
} catch (error) {
|
|
1666
|
+
console.error(` Error processing template ${file}:`, error?.message || error);
|
|
1667
|
+
errorCount++;
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints);
|
|
1672
|
+
const fontCSS = generateFontCSS();
|
|
1673
|
+
const themeColorCSS = generateThemeColorVariablesCSS(themeConfig);
|
|
1674
|
+
const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
|
|
1675
|
+
const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints);
|
|
1676
|
+
const componentCSSCombined = Array.from(allComponentCSS).join("\n");
|
|
1677
|
+
const baseCSS = `@layer base {
|
|
1678
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1679
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; }
|
|
1680
|
+
button { background: none; border: none; padding: 0; font: inherit; cursor: pointer; outline: inherit; }
|
|
1681
|
+
img { display: block; width: 100%; height: 100%; }
|
|
1682
|
+
picture { display: block; }
|
|
1683
|
+
.olink { text-decoration: none; display: block; }
|
|
1684
|
+
.oem { display: inline-block; }
|
|
1685
|
+
}`;
|
|
1686
|
+
const tailwindDirectives = `@tailwind base;
|
|
1687
|
+
@tailwind components;
|
|
1688
|
+
@tailwind utilities;`;
|
|
1689
|
+
const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined, interactiveCSS].filter(Boolean).join("\n\n");
|
|
1690
|
+
await writeFile2(join(stylesDir, "global.css"), globalCSS, "utf-8");
|
|
1691
|
+
console.log(`
|
|
1692
|
+
Generated global.css (${(globalCSS.length / 1024).toFixed(1)} KB)`);
|
|
1693
|
+
const fontPreloads = generateFontPreloadTags();
|
|
1694
|
+
const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
|
|
1695
|
+
const buildLibraries = filterLibrariesByContext(mergedLibraries, "build");
|
|
1696
|
+
const libraryTags = generateLibraryTags(buildLibraries);
|
|
1697
|
+
const baseLayoutContent = `---
|
|
1698
|
+
import '../styles/global.css';
|
|
1699
|
+
|
|
1700
|
+
interface Props {
|
|
1701
|
+
title: string;
|
|
1702
|
+
meta?: string;
|
|
1703
|
+
scripts?: string[];
|
|
1704
|
+
locale?: string;
|
|
1705
|
+
theme?: string;
|
|
1706
|
+
fontPreloads?: string;
|
|
1707
|
+
libraryTags?: { headCSS?: string; headJS?: string; bodyEndJS?: string };
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.default || "light"}', fontPreloads = '', libraryTags = {} } = Astro.props;
|
|
1711
|
+
---
|
|
1712
|
+
<!DOCTYPE html>
|
|
1713
|
+
<html lang={locale} data-theme={theme}>
|
|
1714
|
+
<head>
|
|
1715
|
+
<meta charset="UTF-8">
|
|
1716
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1717
|
+
<Fragment set:html={fontPreloads} />
|
|
1718
|
+
<Fragment set:html={libraryTags.headCSS || ''} />
|
|
1719
|
+
<Fragment set:html={libraryTags.headJS || ''} />
|
|
1720
|
+
<Fragment set:html={meta} />
|
|
1721
|
+
<title>{title}</title>
|
|
1722
|
+
</head>
|
|
1723
|
+
<body>
|
|
1724
|
+
<slot />
|
|
1725
|
+
{scripts.map((s) => <script src={s} />)}
|
|
1726
|
+
<Fragment set:html={libraryTags.bodyEndJS || ''} />
|
|
1727
|
+
</body>
|
|
1728
|
+
</html>
|
|
1729
|
+
`;
|
|
1730
|
+
await writeFile2(join(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
|
|
1731
|
+
console.log("Generated BaseLayout.astro");
|
|
1732
|
+
let componentFileCount = 0;
|
|
1733
|
+
for (const [compName, compDef] of Object.entries(globalComponents)) {
|
|
1734
|
+
try {
|
|
1735
|
+
const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints);
|
|
1736
|
+
await writeFile2(join(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
|
|
1737
|
+
componentFileCount++;
|
|
1738
|
+
} catch (error) {
|
|
1739
|
+
console.warn(` Warning: could not generate component ${compName}: ${error?.message}`);
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
console.log(`Generated ${componentFileCount} component .astro file(s)`);
|
|
1743
|
+
const defaultTheme = themeConfig.default || "light";
|
|
1744
|
+
for (const result of allResults) {
|
|
1745
|
+
const importPath = layoutImportPath(result.fileDepth);
|
|
1746
|
+
const scriptPaths = [];
|
|
1747
|
+
if (result.javascript) {
|
|
1748
|
+
const hash = hashContent2(result.javascript);
|
|
1749
|
+
const scriptFile = `${hash}.js`;
|
|
1750
|
+
const scriptPublicPath = `/_scripts/${scriptFile}`;
|
|
1751
|
+
if (!existsSync(scriptsDir)) {
|
|
1752
|
+
mkdirSync(scriptsDir, { recursive: true });
|
|
1753
|
+
}
|
|
1754
|
+
const fullScriptPath = join(scriptsDir, scriptFile);
|
|
1755
|
+
if (!existsSync(fullScriptPath)) {
|
|
1756
|
+
await writeFile2(fullScriptPath, result.javascript, "utf-8");
|
|
1757
|
+
}
|
|
1758
|
+
scriptPaths.push(scriptPublicPath);
|
|
1759
|
+
}
|
|
1760
|
+
let astroContent;
|
|
1761
|
+
if (result.pageData && !result.isCMSPage) {
|
|
1762
|
+
try {
|
|
1763
|
+
astroContent = emitAstroPage({
|
|
1764
|
+
pageData: result.pageData,
|
|
1765
|
+
globalComponents,
|
|
1766
|
+
title: result.title,
|
|
1767
|
+
meta: result.meta,
|
|
1768
|
+
locale: result.locale,
|
|
1769
|
+
theme: defaultTheme,
|
|
1770
|
+
fontPreloads,
|
|
1771
|
+
libraryTags,
|
|
1772
|
+
scriptPaths,
|
|
1773
|
+
layoutImportPath: importPath,
|
|
1774
|
+
fileDepth: result.fileDepth,
|
|
1775
|
+
ssrFallbacks: /* @__PURE__ */ new Map(),
|
|
1776
|
+
// SSR fallbacks for complex nodes
|
|
1777
|
+
pageName: result.pageName || "index",
|
|
1778
|
+
breakpoints
|
|
1779
|
+
});
|
|
1780
|
+
} catch (error) {
|
|
1781
|
+
console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
|
|
1782
|
+
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
1783
|
+
}
|
|
1784
|
+
} else {
|
|
1785
|
+
astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
|
|
1786
|
+
}
|
|
1787
|
+
const astroFileFull = join(pagesOutDir, result.astroFilePath);
|
|
1788
|
+
const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
|
|
1789
|
+
if (!existsSync(astroFileDir)) {
|
|
1790
|
+
mkdirSync(astroFileDir, { recursive: true });
|
|
1791
|
+
}
|
|
1792
|
+
await writeFile2(astroFileFull, astroContent, "utf-8");
|
|
1793
|
+
}
|
|
1794
|
+
console.log(`Generated ${allResults.length} .astro page file(s)`);
|
|
1795
|
+
let collectionCount = 0;
|
|
1796
|
+
if (templateSchemas.length > 0) {
|
|
1797
|
+
const contentDir = join(srcDir, "content");
|
|
1798
|
+
mkdirSync(contentDir, { recursive: true });
|
|
1799
|
+
const collectionDefs = [];
|
|
1800
|
+
for (const schema of templateSchemas) {
|
|
1801
|
+
const collectionDir = join(contentDir, schema.id);
|
|
1802
|
+
mkdirSync(collectionDir, { recursive: true });
|
|
1803
|
+
const cmsItemsDir = join(projectPaths.cms(), schema.id);
|
|
1804
|
+
if (existsSync(cmsItemsDir)) {
|
|
1805
|
+
const itemFiles = readdirSync(cmsItemsDir).filter((f) => f.endsWith(".json"));
|
|
1806
|
+
for (const itemFile of itemFiles) {
|
|
1807
|
+
try {
|
|
1808
|
+
const rawContent = await readFile(join(cmsItemsDir, itemFile), "utf-8");
|
|
1809
|
+
const item = JSON.parse(rawContent);
|
|
1810
|
+
const resolved = {};
|
|
1811
|
+
for (const [key, value] of Object.entries(item)) {
|
|
1812
|
+
if (isI18nValue(value)) {
|
|
1813
|
+
resolved[key] = resolveI18nValue(value, i18nConfig.defaultLocale, i18nConfig);
|
|
1814
|
+
} else {
|
|
1815
|
+
resolved[key] = value;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
await writeFile2(
|
|
1819
|
+
join(collectionDir, itemFile),
|
|
1820
|
+
JSON.stringify(resolved, null, 2),
|
|
1821
|
+
"utf-8"
|
|
1822
|
+
);
|
|
1823
|
+
} catch (err) {
|
|
1824
|
+
console.warn(` Warning: could not process CMS item ${itemFile}: ${err?.message}`);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
const fieldDefs = [];
|
|
1829
|
+
if (schema.fields) {
|
|
1830
|
+
for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
|
|
1831
|
+
const zodType = cmsFieldToZod(fieldDef);
|
|
1832
|
+
const optional = fieldDef.required ? "" : ".optional()";
|
|
1833
|
+
fieldDefs.push(` ${fieldName}: ${zodType}${optional}`);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
collectionDefs.push(` '${schema.id}': defineCollection({
|
|
1837
|
+
type: 'data',
|
|
1838
|
+
schema: z.object({
|
|
1839
|
+
${fieldDefs.join(",\n")}
|
|
1840
|
+
})
|
|
1841
|
+
})`);
|
|
1842
|
+
collectionCount++;
|
|
1843
|
+
}
|
|
1844
|
+
const configContent = `import { z, defineCollection } from 'astro:content';
|
|
1845
|
+
|
|
1846
|
+
const collections = {
|
|
1847
|
+
${collectionDefs.join(",\n")}
|
|
1848
|
+
};
|
|
1849
|
+
|
|
1850
|
+
export { collections };
|
|
1851
|
+
`;
|
|
1852
|
+
await writeFile2(join(contentDir, "config.ts"), configContent, "utf-8");
|
|
1853
|
+
console.log(`Generated ${collectionCount} content collection(s) with config.ts`);
|
|
1854
|
+
}
|
|
1855
|
+
const assetDirs = ["fonts", "images", "icons", "videos", "assets"];
|
|
1856
|
+
let copiedAssets = 0;
|
|
1857
|
+
for (const dir of assetDirs) {
|
|
1858
|
+
const srcAssetDir = join(projectPaths.project, dir);
|
|
1859
|
+
if (existsSync(srcAssetDir)) {
|
|
1860
|
+
copyDirectory(srcAssetDir, join(publicDir, dir));
|
|
1861
|
+
copiedAssets++;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
const librariesDir = join(projectPaths.project, "libraries");
|
|
1865
|
+
if (existsSync(librariesDir)) {
|
|
1866
|
+
copyDirectory(librariesDir, join(publicDir, "libraries"));
|
|
1867
|
+
copiedAssets++;
|
|
1868
|
+
}
|
|
1869
|
+
if (copiedAssets > 0) {
|
|
1870
|
+
console.log(`Copied ${copiedAssets} asset director${copiedAssets === 1 ? "y" : "ies"} to public/`);
|
|
1871
|
+
}
|
|
1872
|
+
const packageJson = {
|
|
1873
|
+
name: "astro-export",
|
|
1874
|
+
type: "module",
|
|
1875
|
+
version: "0.0.1",
|
|
1876
|
+
private: true,
|
|
1877
|
+
scripts: {
|
|
1878
|
+
dev: "astro dev",
|
|
1879
|
+
start: "astro dev",
|
|
1880
|
+
build: "astro build",
|
|
1881
|
+
preview: "astro preview"
|
|
1882
|
+
},
|
|
1883
|
+
dependencies: {
|
|
1884
|
+
"astro": "^4.0.0",
|
|
1885
|
+
"@astrojs/sitemap": "^3.0.0",
|
|
1886
|
+
"@astrojs/tailwind": "^5.0.0",
|
|
1887
|
+
"tailwindcss": "^3.4.0"
|
|
1888
|
+
}
|
|
1889
|
+
};
|
|
1890
|
+
await writeFile2(join(outDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1891
|
+
const astroConfig = `import { defineConfig } from 'astro/config';
|
|
1892
|
+
import sitemap from '@astrojs/sitemap';
|
|
1893
|
+
import tailwind from '@astrojs/tailwind';
|
|
1894
|
+
|
|
1895
|
+
export default defineConfig({${siteUrl ? `
|
|
1896
|
+
site: '${siteUrl}',` : ""}
|
|
1897
|
+
integrations: [sitemap(), tailwind({ applyBaseStyles: false })],
|
|
1898
|
+
});
|
|
1899
|
+
`;
|
|
1900
|
+
const safelistArray = Array.from(mappingClasses);
|
|
1901
|
+
const safelistLiteral = safelistArray.length > 0 ? `
|
|
1902
|
+
safelist: [
|
|
1903
|
+
${safelistArray.map((c) => ` '${c}'`).join(",\n")}
|
|
1904
|
+
],` : "";
|
|
1905
|
+
const tailwindConfig = `/** @type {import('tailwindcss').Config} */
|
|
1906
|
+
export default {
|
|
1907
|
+
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],${safelistLiteral}
|
|
1908
|
+
theme: {
|
|
1909
|
+
extend: {},
|
|
1910
|
+
},
|
|
1911
|
+
plugins: [],
|
|
1912
|
+
};
|
|
1913
|
+
`;
|
|
1914
|
+
await writeFile2(join(outDir, "tailwind.config.mjs"), tailwindConfig, "utf-8");
|
|
1915
|
+
await writeFile2(join(outDir, "astro.config.mjs"), astroConfig, "utf-8");
|
|
1916
|
+
const tsConfig = {
|
|
1917
|
+
extends: "astro/tsconfigs/strict"
|
|
1918
|
+
};
|
|
1919
|
+
await writeFile2(join(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
|
|
1920
|
+
console.log("Generated package.json, astro.config.mjs, tailwind.config.mjs, tsconfig.json");
|
|
1921
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
1922
|
+
const totalPages = allResults.length;
|
|
1923
|
+
console.log("\n" + "=".repeat(50));
|
|
1924
|
+
console.log("Astro export complete!");
|
|
1925
|
+
console.log(` Pages: ${totalPages - cmsPageCount}`);
|
|
1926
|
+
if (cmsPageCount > 0) {
|
|
1927
|
+
console.log(` CMS pages: ${cmsPageCount}`);
|
|
1928
|
+
}
|
|
1929
|
+
if (collectionCount > 0) {
|
|
1930
|
+
console.log(` Content collections: ${collectionCount}`);
|
|
1931
|
+
}
|
|
1932
|
+
if (errorCount > 0) {
|
|
1933
|
+
console.log(` Errors: ${errorCount}`);
|
|
1934
|
+
}
|
|
1935
|
+
console.log(` Time: ${elapsed}s`);
|
|
1936
|
+
console.log(` Output: ${outDir}`);
|
|
1937
|
+
console.log("");
|
|
1938
|
+
return {
|
|
1939
|
+
pages: totalPages - cmsPageCount,
|
|
1940
|
+
cmsPages: cmsPageCount,
|
|
1941
|
+
collections: collectionCount,
|
|
1942
|
+
errors: errorCount
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
|
|
112
1946
|
// lib/server/index.ts
|
|
113
1947
|
init_constants();
|
|
114
1948
|
export {
|
|
@@ -130,6 +1964,7 @@ export {
|
|
|
130
1964
|
SERVE_PORT,
|
|
131
1965
|
VariableService,
|
|
132
1966
|
WebSocketManager,
|
|
1967
|
+
buildAstroProject,
|
|
133
1968
|
buildAttributes,
|
|
134
1969
|
buildComponentHTML,
|
|
135
1970
|
buildImageMetadataMap,
|