meno-core 1.0.40 → 1.0.41

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.
Files changed (56) hide show
  1. package/bin/cli.ts +33 -0
  2. package/build-astro.ts +3 -27
  3. package/dist/bin/cli.js +30 -2
  4. package/dist/bin/cli.js.map +2 -2
  5. package/dist/build-static.js +7 -7
  6. package/dist/chunks/{chunk-3NOZVNM4.js → chunk-EQOSDQS2.js} +4 -4
  7. package/dist/chunks/{chunk-V4SVSX3X.js → chunk-IBR2F4IL.js} +4 -5
  8. package/dist/chunks/{chunk-V4SVSX3X.js.map → chunk-IBR2F4IL.js.map} +2 -2
  9. package/dist/chunks/{chunk-OJ5SROQN.js → chunk-IGVQF5GY.js} +8 -6
  10. package/dist/chunks/chunk-IGVQF5GY.js.map +7 -0
  11. package/dist/chunks/{chunk-Z7SAOCDG.js → chunk-LBWIHPN7.js} +5 -2
  12. package/dist/chunks/{chunk-Z7SAOCDG.js.map → chunk-LBWIHPN7.js.map} +2 -2
  13. package/dist/chunks/{chunk-A6KWUEA6.js → chunk-MKB2J6AD.js} +9 -1
  14. package/dist/chunks/chunk-MKB2J6AD.js.map +7 -0
  15. package/dist/chunks/{chunk-LOJLO2EY.js → chunk-S2HXJTAF.js} +1 -1
  16. package/dist/chunks/chunk-S2HXJTAF.js.map +7 -0
  17. package/dist/chunks/{chunk-GKICS7CF.js → chunk-SK3TLNUP.js} +120 -107
  18. package/dist/chunks/chunk-SK3TLNUP.js.map +7 -0
  19. package/dist/chunks/{chunk-MOCRENNU.js → chunk-SNUROC7E.js} +6 -6
  20. package/dist/chunks/{configService-TXBNUBBL.js → configService-MICL4S2L.js} +2 -2
  21. package/dist/chunks/{constants-L75FR445.js → constants-ZEU4TZCA.js} +2 -2
  22. package/dist/entries/server-router.js +7 -7
  23. package/dist/lib/client/index.js +9 -4
  24. package/dist/lib/client/index.js.map +2 -2
  25. package/dist/lib/server/index.js +76 -2966
  26. package/dist/lib/server/index.js.map +4 -4
  27. package/dist/lib/shared/index.js +3 -3
  28. package/dist/lib/test-utils/index.js +1 -1
  29. package/lib/client/core/ComponentBuilder.ts +1 -1
  30. package/lib/client/routing/Router.tsx +6 -0
  31. package/lib/client/templateEngine.test.ts +178 -0
  32. package/lib/client/templateEngine.ts +1 -2
  33. package/lib/server/astro/cmsPageEmitter.ts +3 -0
  34. package/lib/server/astro/componentEmitter.ts +60 -12
  35. package/lib/server/astro/nodeToAstro.test.ts +1101 -0
  36. package/lib/server/astro/nodeToAstro.ts +43 -4
  37. package/lib/server/astro/pageEmitter.ts +4 -0
  38. package/lib/server/index.ts +18 -4
  39. package/lib/server/services/configService.ts +12 -0
  40. package/lib/server/ssr/htmlGenerator.ts +0 -5
  41. package/lib/server/ssr/imageMetadata.ts +3 -3
  42. package/lib/server/ssr/ssrRenderer.ts +48 -19
  43. package/lib/shared/constants.ts +2 -0
  44. package/lib/shared/types/components.ts +8 -4
  45. package/lib/shared/validation/propValidator.ts +2 -1
  46. package/lib/shared/validation/schemas.ts +3 -1
  47. package/package.json +1 -1
  48. package/templates/index-router.html +0 -5
  49. package/dist/chunks/chunk-A6KWUEA6.js.map +0 -7
  50. package/dist/chunks/chunk-GKICS7CF.js.map +0 -7
  51. package/dist/chunks/chunk-LOJLO2EY.js.map +0 -7
  52. package/dist/chunks/chunk-OJ5SROQN.js.map +0 -7
  53. /package/dist/chunks/{chunk-3NOZVNM4.js.map → chunk-EQOSDQS2.js.map} +0 -0
  54. /package/dist/chunks/{chunk-MOCRENNU.js.map → chunk-SNUROC7E.js.map} +0 -0
  55. /package/dist/chunks/{configService-TXBNUBBL.js.map → configService-MICL4S2L.js.map} +0 -0
  56. /package/dist/chunks/{constants-L75FR445.js.map → constants-ZEU4TZCA.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  } from "../../chunks/chunk-4OFZP5NQ.js";
4
4
  import {
5
5
  buildStaticPages
6
- } from "../../chunks/chunk-3NOZVNM4.js";
6
+ } from "../../chunks/chunk-EQOSDQS2.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-MOCRENNU.js";
35
+ } from "../../chunks/chunk-SNUROC7E.js";
36
36
  import {
37
37
  CMSService,
38
38
  ColorService,
@@ -43,19 +43,15 @@ import {
43
43
  buildAttributes,
44
44
  buildComponentHTML,
45
45
  buildImageMetadataMap,
46
- buildSlugIndex,
47
46
  clearJSValidationCache,
48
47
  collectComponentCSS,
49
48
  collectComponentJavaScript,
50
- collectComponentLibraries,
51
49
  colorService,
52
50
  createI18nResolver,
53
51
  escapeHtml,
54
52
  extractPageMeta,
55
- filterLibrariesByContext,
56
53
  generateFontCSS,
57
54
  generateFontPreloadTags,
58
- generateLibraryTags,
59
55
  generateMetaTags,
60
56
  generateSSRHTML,
61
57
  generateThemeColorVariablesCSS,
@@ -68,7 +64,6 @@ import {
68
64
  loadProjectConfig,
69
65
  loadResponsiveScalesConfig,
70
66
  mapPageNameToPath,
71
- mergeLibraries,
72
67
  migrateTemplatesDirectory,
73
68
  parseJSON,
74
69
  processCMSPropsTemplate,
@@ -76,13 +71,12 @@ import {
76
71
  renderPageSSR,
77
72
  resetFontConfig,
78
73
  styleToString,
79
- translatePath,
80
74
  variableService
81
- } from "../../chunks/chunk-GKICS7CF.js";
75
+ } from "../../chunks/chunk-SK3TLNUP.js";
82
76
  import {
83
77
  ConfigService,
84
78
  configService
85
- } from "../../chunks/chunk-A6KWUEA6.js";
79
+ } from "../../chunks/chunk-MKB2J6AD.js";
86
80
  import {
87
81
  bundleFile,
88
82
  createRuntimeServer,
@@ -112,23 +106,14 @@ import {
112
106
  writeFile
113
107
  } from "../../chunks/chunk-WQFG7PAH.js";
114
108
  import "../../chunks/chunk-LIHJ6OUH.js";
115
- import "../../chunks/chunk-LOJLO2EY.js";
116
- import "../../chunks/chunk-V4SVSX3X.js";
109
+ import "../../chunks/chunk-S2HXJTAF.js";
110
+ import "../../chunks/chunk-IBR2F4IL.js";
117
111
  import {
118
- extractInteractiveStyleMappings,
119
- extractUtilityClassesFromHTML,
120
- generateAllInteractiveCSS,
121
112
  generateElementClassName,
122
- generateUtilityCSS,
123
- hasInteractiveStyleMappings,
124
113
  isItemDraftForLocale,
125
- isVoidElement,
126
- singularize
127
- } from "../../chunks/chunk-OJ5SROQN.js";
114
+ isVoidElement
115
+ } from "../../chunks/chunk-IGVQF5GY.js";
128
116
  import {
129
- DEFAULT_BREAKPOINTS,
130
- DEFAULT_I18N_CONFIG,
131
- buildLocalizedPath,
132
117
  isI18nValue,
133
118
  resolveI18nValue
134
119
  } from "../../chunks/chunk-PGH3ATYI.js";
@@ -137,2900 +122,15 @@ import {
137
122
  HMR_ROUTE,
138
123
  MAX_PORT_ATTEMPTS,
139
124
  NODE_TYPE,
140
- RAW_HTML_PREFIX,
141
125
  SERVER_PORT,
142
126
  SERVE_PORT,
143
127
  init_constants
144
- } from "../../chunks/chunk-Z7SAOCDG.js";
128
+ } from "../../chunks/chunk-LBWIHPN7.js";
145
129
  import "../../chunks/chunk-KSBZ2L7C.js";
146
130
 
147
- // build-astro.ts
148
- import { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync } from "fs";
149
- import { writeFile as writeFile2, readFile } from "fs/promises";
150
- import { join } from "path";
151
- import { createHash } from "crypto";
152
-
153
- // lib/server/astro/tailwindMapper.ts
154
- function isStyleMapping(value) {
155
- return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
156
- }
157
- function hasTemplateExpression(value) {
158
- return /\{\{.+?\}\}/.test(value);
159
- }
160
- function isResponsiveStyle(style) {
161
- return "base" in style || "tablet" in style || "mobile" in style;
162
- }
163
- var exactMatches = {
164
- display: {
165
- flex: "flex",
166
- grid: "grid",
167
- block: "block",
168
- none: "hidden",
169
- inline: "inline",
170
- "inline-block": "inline-block",
171
- "inline-flex": "inline-flex",
172
- "inline-grid": "inline-grid"
173
- },
174
- flexDirection: {
175
- column: "flex-col",
176
- row: "flex-row",
177
- "column-reverse": "flex-col-reverse",
178
- "row-reverse": "flex-row-reverse"
179
- },
180
- justifyContent: {
181
- center: "justify-center",
182
- "flex-start": "justify-start",
183
- "flex-end": "justify-end",
184
- "space-between": "justify-between",
185
- "space-around": "justify-around",
186
- "space-evenly": "justify-evenly",
187
- // camelCase aliases (component data uses camelCase)
188
- spaceBetween: "justify-between",
189
- spaceAround: "justify-around",
190
- spaceEvenly: "justify-evenly",
191
- flexStart: "justify-start",
192
- flexEnd: "justify-end"
193
- },
194
- alignItems: {
195
- center: "items-center",
196
- "flex-start": "items-start",
197
- "flex-end": "items-end",
198
- stretch: "items-stretch",
199
- baseline: "items-baseline",
200
- // camelCase aliases
201
- flexStart: "items-start",
202
- flexEnd: "items-end"
203
- },
204
- alignContent: {
205
- center: "content-center",
206
- "flex-start": "content-start",
207
- "flex-end": "content-end",
208
- "space-between": "content-between",
209
- "space-around": "content-around",
210
- stretch: "content-stretch"
211
- },
212
- alignSelf: {
213
- auto: "self-auto",
214
- center: "self-center",
215
- "flex-start": "self-start",
216
- "flex-end": "self-end",
217
- stretch: "self-stretch"
218
- },
219
- position: {
220
- relative: "relative",
221
- absolute: "absolute",
222
- fixed: "fixed",
223
- sticky: "sticky",
224
- static: "static"
225
- },
226
- overflow: {
227
- hidden: "overflow-hidden",
228
- auto: "overflow-auto",
229
- scroll: "overflow-scroll",
230
- visible: "overflow-visible"
231
- },
232
- overflowX: {
233
- hidden: "overflow-x-hidden",
234
- auto: "overflow-x-auto",
235
- scroll: "overflow-x-scroll",
236
- visible: "overflow-x-visible"
237
- },
238
- overflowY: {
239
- hidden: "overflow-y-hidden",
240
- auto: "overflow-y-auto",
241
- scroll: "overflow-y-scroll",
242
- visible: "overflow-y-visible"
243
- },
244
- cursor: {
245
- pointer: "cursor-pointer",
246
- default: "cursor-default",
247
- "not-allowed": "cursor-not-allowed",
248
- grab: "cursor-grab",
249
- grabbing: "cursor-grabbing",
250
- text: "cursor-text",
251
- move: "cursor-move",
252
- wait: "cursor-wait"
253
- },
254
- textAlign: {
255
- center: "text-center",
256
- left: "text-left",
257
- right: "text-right",
258
- justify: "text-justify"
259
- },
260
- textDecoration: {
261
- none: "no-underline",
262
- underline: "underline",
263
- "line-through": "line-through",
264
- overline: "overline"
265
- },
266
- textTransform: {
267
- uppercase: "uppercase",
268
- lowercase: "lowercase",
269
- capitalize: "capitalize",
270
- none: "normal-case"
271
- },
272
- objectFit: {
273
- cover: "object-cover",
274
- contain: "object-contain",
275
- fill: "object-fill",
276
- none: "object-none",
277
- "scale-down": "object-scale-down"
278
- },
279
- objectPosition: {
280
- center: "object-center",
281
- top: "object-top",
282
- bottom: "object-bottom",
283
- left: "object-left",
284
- right: "object-right"
285
- },
286
- flexWrap: {
287
- wrap: "flex-wrap",
288
- nowrap: "flex-nowrap",
289
- "wrap-reverse": "flex-wrap-reverse"
290
- },
291
- pointerEvents: {
292
- none: "pointer-events-none",
293
- auto: "pointer-events-auto"
294
- },
295
- userSelect: {
296
- none: "select-none",
297
- auto: "select-auto",
298
- text: "select-text",
299
- all: "select-all"
300
- },
301
- visibility: {
302
- hidden: "invisible",
303
- visible: "visible"
304
- },
305
- whiteSpace: {
306
- normal: "whitespace-normal",
307
- nowrap: "whitespace-nowrap",
308
- pre: "whitespace-pre",
309
- "pre-wrap": "whitespace-pre-wrap",
310
- "pre-line": "whitespace-pre-line"
311
- },
312
- wordBreak: {
313
- "break-all": "break-all",
314
- "break-word": "break-words",
315
- normal: "break-normal"
316
- },
317
- listStyleType: {
318
- none: "list-none",
319
- disc: "list-disc",
320
- decimal: "list-decimal"
321
- },
322
- listStylePosition: {
323
- inside: "list-inside",
324
- outside: "list-outside"
325
- },
326
- boxSizing: {
327
- "border-box": "box-border",
328
- "content-box": "box-content"
329
- },
330
- gridAutoFlow: {
331
- row: "grid-flow-row",
332
- column: "grid-flow-col",
333
- dense: "grid-flow-dense",
334
- "row dense": "grid-flow-row-dense",
335
- "column dense": "grid-flow-col-dense"
336
- }
337
- };
338
- var singleValueMatches = {
339
- // width/height 100%
340
- "width:100%": "w-full",
341
- "height:100%": "h-full",
342
- "width:100vw": "w-screen",
343
- "height:100vh": "h-screen",
344
- "width:auto": "w-auto",
345
- "height:auto": "h-auto",
346
- "width:fit-content": "w-fit",
347
- "height:fit-content": "h-fit",
348
- "width:min-content": "w-min",
349
- "height:min-content": "h-min",
350
- "width:max-content": "w-max",
351
- "height:max-content": "h-max",
352
- "maxWidth:100%": "max-w-full",
353
- "maxWidth:none": "max-w-none",
354
- "maxHeight:100%": "max-h-full",
355
- "maxHeight:none": "max-h-none",
356
- "minWidth:0": "min-w-0",
357
- "minHeight:0": "min-h-0",
358
- "margin:auto": "m-auto",
359
- "margin:0 auto": "mx-auto",
360
- "marginLeft:auto": "ml-auto",
361
- "marginRight:auto": "mr-auto",
362
- "marginInline:auto": "mx-auto",
363
- "borderRadius:50%": "rounded-full",
364
- "borderRadius:9999px": "rounded-full",
365
- "borderRadius:0": "rounded-none",
366
- "flex:1": "flex-1",
367
- "flex:none": "flex-none",
368
- "flex:auto": "flex-auto",
369
- "flexGrow:0": "grow-0",
370
- "flexGrow:1": "grow",
371
- "flexShrink:0": "shrink-0",
372
- "flexShrink:1": "shrink",
373
- "opacity:0": "opacity-0",
374
- "opacity:1": "opacity-100",
375
- "zIndex:0": "z-0",
376
- "zIndex:10": "z-10",
377
- "zIndex:20": "z-20",
378
- "zIndex:30": "z-30",
379
- "zIndex:40": "z-40",
380
- "zIndex:50": "z-50",
381
- "inset:0": "inset-0",
382
- "top:0": "top-0",
383
- "right:0": "right-0",
384
- "bottom:0": "bottom-0",
385
- "left:0": "left-0",
386
- "outline:none": "[outline:none]",
387
- "background:none": "[background:none]",
388
- "background:transparent": "[background:transparent]",
389
- "backgroundColor:transparent": "bg-transparent"
390
- };
391
- var arbitraryPrefixMap = {
392
- // Spacing
393
- padding: "p",
394
- paddingTop: "pt",
395
- paddingRight: "pr",
396
- paddingBottom: "pb",
397
- paddingLeft: "pl",
398
- paddingInline: "px",
399
- paddingBlock: "py",
400
- margin: "m",
401
- marginTop: "mt",
402
- marginRight: "mr",
403
- marginBottom: "mb",
404
- marginLeft: "ml",
405
- marginInline: "mx",
406
- marginBlock: "my",
407
- gap: "gap",
408
- rowGap: "gap-y",
409
- columnGap: "gap-x",
410
- // Sizing
411
- width: "w",
412
- height: "h",
413
- maxWidth: "max-w",
414
- maxHeight: "max-h",
415
- minWidth: "min-w",
416
- minHeight: "min-h",
417
- // Typography
418
- fontSize: "text",
419
- fontWeight: "font",
420
- fontFamily: "font",
421
- lineHeight: "leading",
422
- letterSpacing: "tracking",
423
- // Borders
424
- borderRadius: "rounded",
425
- borderTopLeftRadius: "rounded-tl",
426
- borderTopRightRadius: "rounded-tr",
427
- borderBottomLeftRadius: "rounded-bl",
428
- borderBottomRightRadius: "rounded-br",
429
- border: "border",
430
- borderTop: "border-t",
431
- borderRight: "border-r",
432
- borderBottom: "border-b",
433
- borderLeft: "border-l",
434
- borderColor: "border",
435
- // Colors
436
- color: "text",
437
- backgroundColor: "bg",
438
- background: "bg",
439
- backgroundImage: "bg",
440
- // Effects
441
- opacity: "opacity",
442
- boxShadow: "shadow",
443
- textShadow: "[text-shadow]",
444
- filter: "[filter]",
445
- backdropFilter: "backdrop",
446
- transform: "[transform]",
447
- transformOrigin: "origin",
448
- transition: "[transition]",
449
- mixBlendMode: "mix-blend",
450
- clipPath: "[clip-path]",
451
- // Positioning
452
- top: "top",
453
- right: "right",
454
- bottom: "bottom",
455
- left: "left",
456
- inset: "inset",
457
- zIndex: "z",
458
- // Grid
459
- gridTemplateColumns: "grid-cols",
460
- gridTemplateRows: "grid-rows",
461
- gridColumn: "col",
462
- gridRow: "row",
463
- gridAutoRows: "auto-rows",
464
- gridAutoColumns: "auto-cols",
465
- // Flexbox extras
466
- flexGrow: "grow",
467
- flexShrink: "shrink",
468
- flexBasis: "basis",
469
- order: "order",
470
- flex: "flex",
471
- // Aspect ratio
472
- aspectRatio: "aspect",
473
- // Outline
474
- outline: "outline",
475
- outlineWidth: "outline",
476
- outlineOffset: "outline-offset",
477
- outlineColor: "outline",
478
- // Other
479
- accentColor: "accent",
480
- textIndent: "[text-indent]",
481
- verticalAlign: "align",
482
- overflowWrap: "[overflow-wrap]",
483
- scrollBehavior: "scroll",
484
- resize: "resize"
485
- };
486
- function propertyToTailwind(property, value) {
487
- const strValue = String(value);
488
- if (strValue === "") return null;
489
- if (hasTemplateExpression(strValue)) return null;
490
- const singleKey = `${property}:${strValue}`;
491
- if (singleValueMatches[singleKey]) {
492
- return singleValueMatches[singleKey];
493
- }
494
- if (exactMatches[property]?.[strValue]) {
495
- return exactMatches[property][strValue];
496
- }
497
- if (property === "color" || property === "backgroundColor" || property === "borderColor") {
498
- const prefix = property === "color" ? "text" : property === "backgroundColor" ? "bg" : "border";
499
- if (strValue.includes("var(")) {
500
- return `${prefix}-[color:${strValue}]`;
501
- }
502
- if (!strValue.match(/^[#\d]/) && !strValue.includes("rgb") && !strValue.includes("hsl")) {
503
- return `${prefix}-[color:var(--${strValue})]`;
504
- }
505
- }
506
- if (property === "borderColor" || property === "color") {
507
- const prefix = property === "color" ? "text" : "border";
508
- const sanitized2 = strValue.replace(/\s+/g, "_");
509
- return `${prefix}-[color:${sanitized2}]`;
510
- }
511
- if (property === "border" || property === "borderTop" || property === "borderRight" || property === "borderBottom" || property === "borderLeft") {
512
- if (strValue.includes("solid") || strValue.includes("dashed") || strValue.includes("dotted") || strValue.includes("none")) {
513
- const cssProp = property.replace(/([A-Z])/g, "-$1").toLowerCase();
514
- const sanitized2 = strValue.replace(/\s+/g, "_");
515
- return `[${cssProp}:${sanitized2}]`;
516
- }
517
- }
518
- if (property === "background") {
519
- const isSimpleColor = /^(#[0-9a-fA-F]{3,8}|rgb|hsl|var\()/.test(strValue);
520
- if (!isSimpleColor) {
521
- const sanitized2 = strValue.replace(/\s+/g, "_");
522
- return `[background:${sanitized2}]`;
523
- }
524
- }
525
- const twPrefix = arbitraryPrefixMap[property];
526
- if (!twPrefix) {
527
- const cssProp = property.replace(/([A-Z])/g, "-$1").toLowerCase();
528
- const sanitized2 = strValue.replace(/\s+/g, "_");
529
- return `[${cssProp}:${sanitized2}]`;
530
- }
531
- if (twPrefix.startsWith("[")) {
532
- const sanitized2 = strValue.replace(/\s+/g, "_");
533
- return `${twPrefix.slice(0, -1)}:${sanitized2}]`;
534
- }
535
- const sanitized = strValue.replace(/\s+/g, "_");
536
- if (property === "fontSize") {
537
- return `text-[length:${sanitized}]`;
538
- }
539
- if (property === "fontFamily") {
540
- return `font-[family-name:${sanitized}]`;
541
- }
542
- if (property === "fontWeight") {
543
- return `font-[number:${sanitized}]`;
544
- }
545
- return `${twPrefix}-[${sanitized}]`;
546
- }
547
- function stylesToTailwind(style) {
548
- const classes = [];
549
- const dynamicStyles = {};
550
- const hasBorderColor = "borderColor" in style && !isStyleMapping(style.borderColor);
551
- const borderShorthands = /* @__PURE__ */ new Set([
552
- "border",
553
- "borderTop",
554
- "borderRight",
555
- "borderBottom",
556
- "borderLeft"
557
- ]);
558
- for (const [prop, value] of Object.entries(style)) {
559
- if (isStyleMapping(value)) continue;
560
- const strValue = String(value);
561
- if (hasTemplateExpression(strValue)) {
562
- const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
563
- dynamicStyles[cssProp] = strValue;
564
- continue;
565
- }
566
- if (hasBorderColor && borderShorthands.has(prop)) {
567
- const parts = strValue.split(/\s+/);
568
- const width = parts.find((p) => /^\d/.test(p) || p === "0");
569
- const borderStyle = parts.find((p) => /^(solid|dashed|dotted|double|groove|ridge|inset|outset|none|hidden)$/.test(p));
570
- const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
571
- if (width) classes.push(`[${cssProp}-width:${width}]`);
572
- if (borderStyle) classes.push(`[${cssProp}-style:${borderStyle}]`);
573
- continue;
574
- }
575
- const twClass = propertyToTailwind(prop, value);
576
- if (twClass) {
577
- classes.push(twClass);
578
- }
579
- }
580
- return { classes, dynamicStyles };
581
- }
582
- function responsiveStylesToTailwind(style, breakpoints) {
583
- if (!style) return { classes: [], dynamicStyles: {} };
584
- const allClasses = [];
585
- const allDynamicStyles = {};
586
- if (isResponsiveStyle(style)) {
587
- const responsive = style;
588
- if (responsive.base) {
589
- const { classes, dynamicStyles } = stylesToTailwind(responsive.base);
590
- allClasses.push(...classes);
591
- Object.assign(allDynamicStyles, dynamicStyles);
592
- }
593
- if (responsive.tablet) {
594
- const bpValue = breakpoints.tablet?.breakpoint ?? 1024;
595
- const prefix = `max-[${bpValue}px]:`;
596
- const { classes, dynamicStyles } = stylesToTailwind(responsive.tablet);
597
- allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
598
- Object.assign(allDynamicStyles, dynamicStyles);
599
- }
600
- if (responsive.mobile) {
601
- const bpValue = breakpoints.mobile?.breakpoint ?? 540;
602
- const prefix = `max-[${bpValue}px]:`;
603
- const { classes, dynamicStyles } = stylesToTailwind(responsive.mobile);
604
- allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
605
- Object.assign(allDynamicStyles, dynamicStyles);
606
- }
607
- for (const [bpName, bpStyle] of Object.entries(responsive)) {
608
- if (bpName === "base" || bpName === "tablet" || bpName === "mobile" || !bpStyle) continue;
609
- const bpValue = breakpoints[bpName]?.breakpoint;
610
- if (!bpValue) continue;
611
- const prefix = `max-[${bpValue}px]:`;
612
- const { classes, dynamicStyles } = stylesToTailwind(bpStyle);
613
- allClasses.push(...classes.map((cls) => `${prefix}${cls}`));
614
- Object.assign(allDynamicStyles, dynamicStyles);
615
- }
616
- } else {
617
- const { classes, dynamicStyles } = stylesToTailwind(style);
618
- allClasses.push(...classes);
619
- Object.assign(allDynamicStyles, dynamicStyles);
620
- }
621
- return { classes: allClasses, dynamicStyles: allDynamicStyles };
622
- }
623
-
624
- // lib/server/astro/nodeToAstro.ts
625
- init_constants();
626
-
627
- // lib/server/astro/templateTransformer.ts
628
- var CMS_TEMPLATE_PATTERN = /\{\{cms\.([^}]+)\}\}/g;
629
- var ITEM_TEMPLATE_PATTERN = /\{\{([^}]+)\}\}/g;
630
- function isTemplateExpression(text) {
631
- return /\{\{.+?\}\}/.test(text);
632
- }
633
- function transformCMSTemplate(text, binding = "entry", richTextFields, wrapFn) {
634
- const w = (expr) => wrapFn ? `${wrapFn}(${expr})` : expr;
635
- const fullMatch = text.match(/^\{\{cms\.([^}]+)\}\}$/);
636
- if (fullMatch) {
637
- const fieldPath = fullMatch[1].trim();
638
- const topLevelField = fieldPath.split(".")[0];
639
- if (richTextFields?.has(topLevelField)) {
640
- return `<Fragment set:html={${w(`${binding}.data.${fieldPath}`)}} />`;
641
- }
642
- return `{${w(`${binding}.data.${fieldPath}`)}}`;
643
- }
644
- if (CMS_TEMPLATE_PATTERN.test(text)) {
645
- CMS_TEMPLATE_PATTERN.lastIndex = 0;
646
- const replaced = text.replace(CMS_TEMPLATE_PATTERN, (_, fieldPath) => {
647
- return `\${${w(`${binding}.data.${fieldPath.trim()}`)}}`;
648
- });
649
- return `{\`${replaced}\`}`;
650
- }
651
- return text;
652
- }
653
- function rewriteItemVar(expr, itemVar) {
654
- if (itemVar === "item") return expr;
655
- return expr.replace(/\bitem\./g, `${itemVar}.`);
656
- }
657
- function replaceItemMetaVars(expr, indexVar, sourceVar, itemVar) {
658
- const lastExpr = sourceVar ? `(${indexVar} === ${sourceVar}.length - 1)` : `false /* itemLast not supported */`;
659
- let result = expr.replace(/\bitemIndex\b/g, indexVar).replace(/\bitemFirst\b/g, `(${indexVar} === 0)`).replace(/\bitemLast\b/g, lastExpr);
660
- if (itemVar) result = rewriteItemVar(result, itemVar);
661
- return result;
662
- }
663
- function transformItemTemplate(text, itemVar = "item", indexVar, sourceVar) {
664
- const fullMatch = text.match(/^\{\{(.+)\}\}$/);
665
- if (fullMatch) {
666
- let expr = fullMatch[1].trim();
667
- expr = rewriteItemVar(expr, itemVar);
668
- if (indexVar) expr = replaceItemMetaVars(expr, indexVar, sourceVar);
669
- if (expr.startsWith(`${itemVar}.`)) {
670
- return `{${expr}}`;
671
- }
672
- return `{${expr}}`;
673
- }
674
- if (ITEM_TEMPLATE_PATTERN.test(text)) {
675
- ITEM_TEMPLATE_PATTERN.lastIndex = 0;
676
- const replaced = text.replace(ITEM_TEMPLATE_PATTERN, (_, expr) => {
677
- let trimmed = expr.trim();
678
- trimmed = rewriteItemVar(trimmed, itemVar);
679
- if (indexVar) trimmed = replaceItemMetaVars(trimmed, indexVar, sourceVar);
680
- return `\${${trimmed}}`;
681
- });
682
- return `{\`${replaced}\`}`;
683
- }
684
- return text;
685
- }
686
-
687
- // lib/server/astro/nodeToAstro.ts
688
- function ind(ctx) {
689
- return " ".repeat(ctx.indent);
690
- }
691
- function localizeHref(href, ctx) {
692
- if (!href.startsWith("/") || href.startsWith("//")) return href;
693
- const { locale, i18nDefaultLocale, slugMappings } = ctx;
694
- if (!locale || !i18nDefaultLocale) return href;
695
- if (slugMappings && slugMappings.length > 0) {
696
- const slugIndex = buildSlugIndex(slugMappings);
697
- return translatePath(href, locale, i18nDefaultLocale, i18nDefaultLocale, slugIndex);
698
- } else if (locale !== i18nDefaultLocale) {
699
- return buildLocalizedPath(href, locale);
700
- }
701
- return href;
702
- }
703
- function isStyleMapping2(value) {
704
- return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
705
- }
706
- function isLinkMapping(value) {
707
- return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
708
- }
709
- function emitAttrValue(key, value, ctx) {
710
- if (ctx.cmsMode && /\{\{cms\./.test(value)) {
711
- const b = ctx.cmsEntryBinding || "entry";
712
- const w = (expr) => ctx.cmsWrapFn ? `${ctx.cmsWrapFn}(${expr})` : expr;
713
- const fullMatch = value.match(/^\{\{cms\.([^}]+)\}\}$/);
714
- if (fullMatch) {
715
- return `${key}={${w(`${b}.data.${fullMatch[1].trim()}`)}}`;
716
- }
717
- const replaced = value.replace(
718
- /\{\{cms\.([^}]+)\}\}/g,
719
- (_, fp) => `\${${w(`${b}.data.${fp.trim()}`)}}`
720
- );
721
- return `${key}={\`${replaced}\`}`;
722
- }
723
- if (ctx.listItemBinding && /\{\{/.test(value)) {
724
- const fullMatch = value.match(/^\{\{(.+)\}\}$/);
725
- if (fullMatch) {
726
- let expr = fullMatch[1].trim();
727
- expr = rewriteItemVar(expr, ctx.listItemBinding);
728
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
729
- return `${key}={${expr}}`;
730
- }
731
- const replaced = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
732
- let trimmed = expr.trim();
733
- trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
734
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
735
- return `\${${trimmed}}`;
736
- });
737
- return `${key}={\`${replaced}\`}`;
738
- }
739
- return `${key}="${escapeJSX(value)}"`;
740
- }
741
- function isHtmlMapping(value) {
742
- return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
743
- }
744
- function isResponsiveStyle2(style) {
745
- return "base" in style || "tablet" in style || "mobile" in style;
746
- }
747
- function escapeJSX(s) {
748
- return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
749
- }
750
- function escapeTemplateLiteral(s) {
751
- return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
752
- }
753
- function collectStyleMappings(style) {
754
- if (!style) return [];
755
- const result = [];
756
- if (isResponsiveStyle2(style)) {
757
- const responsive = style;
758
- for (const [bp, bpStyle] of Object.entries(responsive)) {
759
- if (!bpStyle) continue;
760
- for (const [prop, value] of Object.entries(bpStyle)) {
761
- if (isStyleMapping2(value)) {
762
- result.push({ property: prop, mapping: value, breakpoint: bp });
763
- }
764
- }
765
- }
766
- } else {
767
- for (const [prop, value] of Object.entries(style)) {
768
- if (isStyleMapping2(value)) {
769
- result.push({ property: prop, mapping: value });
770
- }
771
- }
772
- }
773
- return result;
774
- }
775
- function mappingToClassListEntries(mapping, property, breakpointPrefix, ctx) {
776
- const entries = [];
777
- const values = Object.entries(mapping.values);
778
- if (values.length === 0) return entries;
779
- const propRef = ctx.isComponentDef ? mapping.prop : mapping.prop;
780
- if (values.length === 2) {
781
- const [[val1, css1], [val2, css2]] = values;
782
- const cls1 = getClassForValue(property, css1, breakpointPrefix);
783
- const cls2 = getClassForValue(property, css2, breakpointPrefix);
784
- if (cls1 && cls2) {
785
- entries.push(`String(${propRef}) === ${JSON.stringify(String(coerceValue(val1)))} ? '${cls1}' : '${cls2}'`);
786
- }
787
- } else {
788
- for (const [val, cssValue] of values) {
789
- const cls = getClassForValue(property, cssValue, breakpointPrefix);
790
- if (cls) {
791
- entries.push(`String(${propRef}) === ${JSON.stringify(String(coerceValue(val)))} && '${cls}'`);
792
- }
793
- }
794
- }
795
- return entries;
796
- }
797
- function coerceValue(val) {
798
- if (val === "true") return true;
799
- if (val === "false") return false;
800
- return val;
801
- }
802
- function getClassForValue(property, value, breakpointPrefix) {
803
- const twClass = propertyToTailwind(property, value);
804
- if (!twClass) return null;
805
- return breakpointPrefix ? `${breakpointPrefix}${twClass}` : twClass;
806
- }
807
- function buildClassAndStyleExpression(style, interactiveStyles, elementClass, ctx) {
808
- const result = style ? responsiveStylesToTailwind(style, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
809
- const staticClasses = result.classes;
810
- const dynamicStyles = result.dynamicStyles;
811
- if (elementClass) {
812
- staticClasses.unshift(elementClass);
813
- }
814
- const conditionals = [];
815
- const mappings = collectStyleMappings(style);
816
- for (const { property, mapping, breakpoint } of mappings) {
817
- const bpValue = breakpoint === "tablet" ? ctx.breakpoints.tablet?.breakpoint ?? 1024 : breakpoint === "mobile" ? ctx.breakpoints.mobile?.breakpoint ?? 540 : 0;
818
- const prefix = bpValue ? `max-[${bpValue}px]:` : "";
819
- const entries = mappingToClassListEntries(mapping, property, prefix, ctx);
820
- conditionals.push(...entries);
821
- }
822
- let styleAttr = "";
823
- if (Object.keys(dynamicStyles).length > 0 && ctx.isComponentDef) {
824
- const styleParts = [];
825
- for (const [cssProp, value] of Object.entries(dynamicStyles)) {
826
- const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
827
- let trimmed = expr.trim();
828
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
829
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
830
- return `\${${trimmed}}`;
831
- });
832
- styleParts.push(`${cssProp}: \${${resolved.includes("${") ? resolved.replace(/\$\{(.+?)\}/g, "$1") : `'${resolved}'`}}`);
833
- }
834
- const entries = [];
835
- for (const [cssProp, value] of Object.entries(dynamicStyles)) {
836
- const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
837
- let trimmed = expr.trim();
838
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
839
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
840
- return `\${${trimmed}}`;
841
- });
842
- entries.push(`${cssProp}: ${resolved}`);
843
- }
844
- styleAttr = ` style={\`${entries.join("; ")}\`}`;
845
- }
846
- if (interactiveStyles && interactiveStyles.length > 0 && ctx.isComponentDef && hasInteractiveStyleMappings(interactiveStyles)) {
847
- const { mappings: mappings2 } = extractInteractiveStyleMappings(interactiveStyles);
848
- if (mappings2.length > 0) {
849
- const varParts = [];
850
- for (const extracted of mappings2) {
851
- const { mapping, variableIndex } = extracted;
852
- const varName = `--is-${variableIndex}`;
853
- const entries = Object.entries(mapping.values);
854
- if (entries.length === 2) {
855
- const [[val1, css1], [val2, css2]] = entries;
856
- varParts.push(`'${varName}': ${mapping.prop} === ${JSON.stringify(coerceValue(val1))} ? '${css1}' : '${css2}'`);
857
- } else {
858
- const lookupEntries = entries.filter(([, v]) => v !== "").map(([k, v]) => `${JSON.stringify(coerceValue(k))}: '${v}'`).join(", ");
859
- varParts.push(`'${varName}': ({${lookupEntries}})[${mapping.prop}] || ''`);
860
- }
861
- }
862
- if (varParts.length > 0) {
863
- const existingStyleParts = styleAttr ? styleAttr.replace(/^ style=\{`/, "").replace(/`\}$/, "") : "";
864
- const varStyleExpr = varParts.join(", ");
865
- if (existingStyleParts) {
866
- styleAttr = ` style={\`${existingStyleParts}; \${ Object.entries({${varStyleExpr}}).map(([k,v]) => \`\${k}:\${v}\`).join(';') }\`}`;
867
- } else {
868
- styleAttr = ` style={Object.entries({${varStyleExpr}}).map(([k,v]) => \`\${k}:\${v}\`).join(';')}`;
869
- }
870
- }
871
- }
872
- }
873
- let classExpr;
874
- if (conditionals.length === 0) {
875
- if (staticClasses.length === 0) {
876
- classExpr = "";
877
- } else {
878
- classExpr = ` class="${staticClasses.join(" ")}"`;
879
- }
880
- } else {
881
- const parts = [];
882
- if (staticClasses.length > 0) {
883
- parts.push(`'${staticClasses.join(" ")}'`);
884
- }
885
- parts.push(...conditionals);
886
- classExpr = ` class:list={[${parts.join(", ")}]}`;
887
- }
888
- return { classExpr, styleAttr };
889
- }
890
- function resolveTemplate(text, ctx) {
891
- if (!ctx.isComponentDef) {
892
- return text;
893
- }
894
- const fullMatch = text.match(/^\{\{(.+)\}\}$/);
895
- if (fullMatch) {
896
- let propName = fullMatch[1].trim();
897
- if (ctx.listItemBinding) propName = rewriteItemVar(propName, ctx.listItemBinding);
898
- if (ctx.listIndexVar) propName = replaceItemMetaVars(propName, ctx.listIndexVar, ctx.listSourceVar);
899
- if (ctx.componentProps[propName]?.type === "rich-text") {
900
- return `<Fragment set:html={${propName}} />`;
901
- }
902
- return `{${propName}}`;
903
- }
904
- return text.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
905
- let trimmed = expr.trim();
906
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
907
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
908
- return `{${trimmed}}`;
909
- });
910
- }
911
- function hasTemplates(text) {
912
- return /\{\{.+?\}\}/.test(text);
913
- }
914
- function buildElementClass(ctx, label) {
915
- return generateElementClassName({
916
- fileType: ctx.fileType,
917
- fileName: ctx.fileName,
918
- label,
919
- path: ctx.elementPath
920
- });
921
- }
922
- function buildAttributesString(attributes, ctx) {
923
- if (!attributes) return "";
924
- const parts = [];
925
- for (const [key, value] of Object.entries(attributes)) {
926
- if (typeof value === "boolean") {
927
- if (value) parts.push(key);
928
- } else {
929
- const strVal = String(value);
930
- if (hasTemplates(strVal) && ctx.isComponentDef) {
931
- const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
932
- if (fullMatch) {
933
- let expr = fullMatch[1].trim();
934
- if (ctx.listItemBinding) expr = rewriteItemVar(expr, ctx.listItemBinding);
935
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
936
- const propDef = ctx.componentProps[expr];
937
- if (propDef && propDef.type === "link") {
938
- parts.push(`${key}={${expr}?.href ?? "#"}`);
939
- } else {
940
- parts.push(`${key}={${expr} || undefined}`);
941
- }
942
- } else {
943
- const resolved = strVal.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
944
- let trimmed = expr.trim();
945
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
946
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
947
- const pd = ctx.componentProps[trimmed];
948
- return pd?.type === "link" ? `\${${trimmed}?.href ?? "#"}` : `\${${trimmed}}`;
949
- });
950
- parts.push(`${key}={\`${resolved}\`}`);
951
- }
952
- } else if (ctx.listItemBinding && hasTemplates(strVal)) {
953
- const fullMatch = strVal.match(/^\{\{(.+)\}\}$/);
954
- if (fullMatch) {
955
- let expr = fullMatch[1].trim();
956
- expr = rewriteItemVar(expr, ctx.listItemBinding);
957
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
958
- parts.push(`${key}={${expr} || undefined}`);
959
- } else {
960
- const resolved = strVal.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
961
- let trimmed = expr.trim();
962
- trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
963
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
964
- return `\${${trimmed}}`;
965
- });
966
- parts.push(`${key}={\`${resolved}\`}`);
967
- }
968
- } else if (ctx.cmsMode && /\{\{cms\./.test(strVal)) {
969
- const b = ctx.cmsEntryBinding || "entry";
970
- const w = (expr) => ctx.cmsWrapFn ? `${ctx.cmsWrapFn}(${expr})` : expr;
971
- const fullMatch = strVal.match(/^\{\{cms\.([^}]+)\}\}$/);
972
- if (fullMatch) {
973
- parts.push(`${key}={${w(`${b}.data.${fullMatch[1].trim()}`)}}`);
974
- } else {
975
- const replaced = strVal.replace(/\{\{cms\.([^}]+)\}\}/g, (_, fieldPath) => {
976
- return `\${${w(`${b}.data.${fieldPath.trim()}`)}}`;
977
- });
978
- parts.push(`${key}={\`${replaced}\`}`);
979
- }
980
- } else {
981
- parts.push(`${key}="${escapeJSX(strVal)}"`);
982
- }
983
- }
984
- }
985
- return parts.length > 0 ? " " + parts.join(" ") : "";
986
- }
987
- function formatPropValue(value) {
988
- if (typeof value === "string") return `"${escapeJSX(value)}"`;
989
- if (typeof value === "number") return `{${value}}`;
990
- if (typeof value === "boolean") return `{${value}}`;
991
- if (value === null || value === void 0) return `{undefined}`;
992
- return `{${JSON.stringify(value)}}`;
993
- }
994
- function resolveI18n(value, ctx) {
995
- if (ctx.locale && isI18nValue(value)) {
996
- return resolveI18nValue(value, ctx.locale, DEFAULT_I18N_CONFIG);
997
- }
998
- return value;
999
- }
1000
- function nodeToAstro(node, ctx) {
1001
- if (node === null || node === void 0) return "";
1002
- if (typeof node === "object" && !Array.isArray(node) && isI18nValue(node)) {
1003
- const resolved = resolveI18n(node, ctx);
1004
- if (typeof resolved === "string") {
1005
- return `${ind(ctx)}${escapeJSX(resolved)}
1006
- `;
1007
- }
1008
- if (ctx.isComponentDef && isI18nValue(resolved)) {
1009
- ctx.needsI18nResolver = true;
1010
- return `${ind(ctx)}{r(${JSON.stringify(resolved)})}
1011
- `;
1012
- }
1013
- return `${ind(ctx)}${String(resolved ?? "")}
1014
- `;
1015
- }
1016
- if (typeof node === "string") {
1017
- if (ctx.cmsMode && isTemplateExpression(node) && /\{\{cms\./.test(node)) {
1018
- const transformed = transformCMSTemplate(node, ctx.cmsEntryBinding || "entry", ctx.cmsRichTextFields, ctx.cmsWrapFn);
1019
- return `${ind(ctx)}${transformed}
1020
- `;
1021
- }
1022
- if (ctx.listItemBinding && isTemplateExpression(node)) {
1023
- const transformed = transformItemTemplate(node, ctx.listItemBinding, ctx.listIndexVar, ctx.listSourceVar);
1024
- return `${ind(ctx)}${transformed}
1025
- `;
1026
- }
1027
- if (hasTemplates(node) && ctx.isComponentDef) {
1028
- return `${ind(ctx)}${resolveTemplate(node, ctx)}
1029
- `;
1030
- }
1031
- if (node.startsWith(RAW_HTML_PREFIX)) {
1032
- const rawHtml = node.slice(RAW_HTML_PREFIX.length);
1033
- return `${ind(ctx)}<Fragment set:html={\`${escapeTemplateLiteral(rawHtml)}\`} />
1034
- `;
1035
- }
1036
- return `${ind(ctx)}${escapeJSX(node)}
1037
- `;
1038
- }
1039
- if (typeof node === "number") {
1040
- return `${ind(ctx)}${node}
1041
- `;
1042
- }
1043
- if (Array.isArray(node)) {
1044
- let result = "";
1045
- for (let i = 0; i < node.length; i++) {
1046
- const child = node[i];
1047
- const savedPath = [...ctx.elementPath];
1048
- ctx.elementPath = [...ctx.elementPath.slice(0, -1), i];
1049
- result += nodeToAstro(child, ctx);
1050
- ctx.elementPath = savedPath;
1051
- }
1052
- return result;
1053
- }
1054
- switch (node.type) {
1055
- case NODE_TYPE.NODE:
1056
- return emitHtmlNode(node, ctx);
1057
- case NODE_TYPE.COMPONENT:
1058
- return emitComponentInstance(node, ctx);
1059
- case NODE_TYPE.SLOT:
1060
- return emitSlotMarker(node, ctx);
1061
- case NODE_TYPE.EMBED:
1062
- return emitEmbedNode(node, ctx);
1063
- case NODE_TYPE.LINK:
1064
- return emitLinkNode(node, ctx);
1065
- case NODE_TYPE.LOCALE_LIST:
1066
- return emitLocaleListNode(node, ctx);
1067
- case NODE_TYPE.LIST:
1068
- case "cms-list":
1069
- return emitListNode(node, ctx);
1070
- case "image":
1071
- return emitImageTypeNode(node, ctx);
1072
- default:
1073
- return emitFallback(ctx);
1074
- }
1075
- }
1076
- var IMG_TAILWIND_PREFIXES = ["object-", "rounded", "border", "shadow", "[filter", "[transform", "mix-blend"];
1077
- var IMG_OPACITY_PATTERN = /^opacity-/;
1078
- var DEFAULT_SIZES2 = "100vw";
1079
- function splitImageClasses(allClasses) {
1080
- const imgClasses = [];
1081
- const pictureClasses = [];
1082
- for (const cls of allClasses) {
1083
- const baseCls = cls.includes(":") ? cls.split(":").pop() : cls;
1084
- if (IMG_TAILWIND_PREFIXES.some((p) => baseCls.startsWith(p)) || IMG_OPACITY_PATTERN.test(baseCls)) {
1085
- imgClasses.push(cls);
1086
- } else {
1087
- pictureClasses.push(cls);
1088
- }
1089
- }
1090
- return { pictureClasses, imgClasses };
1091
- }
1092
- function emitImageNode(node, ctx) {
1093
- const style = node.style;
1094
- let elementClass = null;
1095
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1096
- elementClass = buildElementClass(ctx, node.label);
1097
- }
1098
- const { classExpr, styleAttr } = buildClassAndStyleExpression(
1099
- style,
1100
- node.interactiveStyles,
1101
- elementClass,
1102
- ctx
1103
- );
1104
- const attrs = node.attributes || {};
1105
- const src = attrs.src;
1106
- const alt = attrs.alt;
1107
- const loading = attrs.loading;
1108
- const fetchpriority = attrs.fetchpriority;
1109
- let width = attrs.width;
1110
- let height = attrs.height;
1111
- const sizes = attrs.sizes;
1112
- const metadata = src ? ctx.imageMetadataMap?.get(String(src)) : void 0;
1113
- if (metadata) {
1114
- if (width === void 0 && metadata.width) width = metadata.width;
1115
- if (height === void 0 && metadata.height) height = metadata.height;
1116
- }
1117
- const sizesValue = sizes || DEFAULT_SIZES2;
1118
- const imageSpecificKeys = /* @__PURE__ */ new Set(["src", "alt", "loading", "width", "height", "sizes", "srcset", "fetchpriority"]);
1119
- const otherAttrs = {};
1120
- if (node.attributes) {
1121
- for (const [k, v] of Object.entries(node.attributes)) {
1122
- if (!imageSpecificKeys.has(k)) otherAttrs[k] = v;
1123
- }
1124
- }
1125
- const otherAttrsStr = buildAttributesString(otherAttrs, ctx);
1126
- let imgAttrs = "";
1127
- if (src) imgAttrs += ` ${emitAttrValue("src", String(src), ctx)}`;
1128
- if (alt !== void 0) imgAttrs += ` ${emitAttrValue("alt", String(alt), ctx)}`;
1129
- if (fetchpriority) imgAttrs += ` fetchpriority="${escapeJSX(String(fetchpriority))}"`;
1130
- if (loading) imgAttrs += ` loading="${escapeJSX(String(loading))}"`;
1131
- if (width !== void 0) imgAttrs += ` width="${escapeJSX(String(width))}"`;
1132
- if (height !== void 0) imgAttrs += ` height="${escapeJSX(String(height))}"`;
1133
- let blurStyle = "";
1134
- if (metadata?.blurHash) {
1135
- blurStyle = ` style="background-image: url(${escapeJSX(metadata.blurHash)}); background-size: cover;" onload="this.style.backgroundImage=''"`;
1136
- }
1137
- const ifExpr = emitIfOpen(node, ctx);
1138
- const ifClose = emitIfClose(node, ctx);
1139
- if (metadata?.avifSrcset) {
1140
- const classMatch = classExpr.match(/class="([^"]*)"/);
1141
- const classListMatch = classExpr.match(/class:list={\[(.+)\]}/);
1142
- if (classListMatch) {
1143
- return `${ifExpr}${ind(ctx)}<picture${classExpr}${styleAttr}>
1144
- ${ind(ctx)} <source type="image/avif" srcset="${escapeJSX(metadata.avifSrcset)}" sizes="${escapeJSX(sizesValue)}" />
1145
- ${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
1146
- ${ind(ctx)} <img${imgAttrs}${blurStyle}${otherAttrsStr} />
1147
- ${ind(ctx)}</picture>
1148
- ${ifClose}`;
1149
- }
1150
- const allClasses = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
1151
- const { pictureClasses, imgClasses } = splitImageClasses(allClasses);
1152
- const pictureClassAttr = pictureClasses.length > 0 ? ` class="${pictureClasses.join(" ")}"` : "";
1153
- const imgClassAttr = imgClasses.length > 0 ? ` class="${imgClasses.join(" ")}"` : "";
1154
- return `${ifExpr}${ind(ctx)}<picture${pictureClassAttr}${styleAttr}>
1155
- ${ind(ctx)} <source type="image/avif" srcset="${escapeJSX(metadata.avifSrcset)}" sizes="${escapeJSX(sizesValue)}" />
1156
- ${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
1157
- ${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurStyle}${otherAttrsStr} />
1158
- ${ind(ctx)}</picture>
1159
- ${ifClose}`;
1160
- }
1161
- if (metadata?.srcset) {
1162
- imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
1163
- imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
1164
- }
1165
- return `${ifExpr}${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs}${blurStyle}${otherAttrsStr} />
1166
- ${ifClose}`;
1167
- }
1168
- function emitHtmlNode(node, ctx) {
1169
- let tag = node.tag;
1170
- if (tag && /^[A-Z]/.test(tag)) {
1171
- tag = tag.toLowerCase();
1172
- }
1173
- if (tag === "img" && ctx.imageMetadataMap) {
1174
- return emitImageNode(node, ctx);
1175
- }
1176
- const label = node.label;
1177
- const style = node.style;
1178
- let isDynamic = false;
1179
- let dynamicTagVar = "";
1180
- if (hasTemplates(tag) && ctx.isComponentDef) {
1181
- isDynamic = true;
1182
- dynamicTagVar = `Tag_${ctx.elementPath.join("_")}`;
1183
- const resolved = tag.replace(/\{\{(.+?)\}\}/g, (_, expr) => `\${${expr.trim()}}`);
1184
- if (!ctx.dynamicTags) ctx.dynamicTags = /* @__PURE__ */ new Map();
1185
- ctx.dynamicTags.set(dynamicTagVar, resolved);
1186
- tag = dynamicTagVar;
1187
- }
1188
- const ifExpr = emitIfOpen(node, ctx);
1189
- let elementClass = null;
1190
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1191
- elementClass = buildElementClass(ctx, label);
1192
- }
1193
- const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
1194
- const attrs = buildAttributesString(node.attributes, ctx);
1195
- const openClose = isDynamic ? dynamicTagVar : tag;
1196
- if (!isDynamic && isVoidElement(tag)) {
1197
- return `${ifExpr}${ind(ctx)}<${tag}${classExpr}${styleAttr}${attrs} />
1198
- ${emitIfClose(node, ctx)}`;
1199
- }
1200
- const children = emitChildren(node.children, ctx);
1201
- if (!children.trim() && !isDynamic) {
1202
- return `${ifExpr}${ind(ctx)}<${tag}${classExpr}${styleAttr}${attrs} />
1203
- ${emitIfClose(node, ctx)}`;
1204
- }
1205
- return `${ifExpr}${ind(ctx)}<${openClose}${classExpr}${styleAttr}${attrs}>
1206
- ` + children + `${ind(ctx)}</${openClose}>
1207
- ${emitIfClose(node, ctx)}`;
1208
- }
1209
- function emitComponentInstance(node, ctx) {
1210
- const name = node.component;
1211
- ctx.imports.add(name);
1212
- const ifExpr = emitIfOpen(node, ctx);
1213
- const propParts = [];
1214
- if (node.props) {
1215
- for (const [key, rawValue] of Object.entries(node.props)) {
1216
- if (key === "children") continue;
1217
- const value = resolveI18n(rawValue, ctx);
1218
- if (typeof value === "string" && hasTemplates(value) && ctx.isComponentDef) {
1219
- const fullMatch = value.match(/^\{\{(.+)\}\}$/);
1220
- if (fullMatch) {
1221
- let expr = fullMatch[1].trim();
1222
- if (ctx.listItemBinding) expr = rewriteItemVar(expr, ctx.listItemBinding);
1223
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
1224
- propParts.push(`${key}={${expr}}`);
1225
- } else {
1226
- const resolved = value.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
1227
- let trimmed = expr.trim();
1228
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
1229
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
1230
- return `\${${trimmed}}`;
1231
- });
1232
- propParts.push(`${key}={\`${resolved}\`}`);
1233
- }
1234
- } else if (typeof value === "string" && ctx.cmsMode && /\{\{cms\./.test(value)) {
1235
- const b = ctx.cmsEntryBinding || "entry";
1236
- const w = (expr) => ctx.cmsWrapFn ? `${ctx.cmsWrapFn}(${expr})` : expr;
1237
- const fullMatch = value.match(/^\{\{cms\.([^}]+)\}\}$/);
1238
- if (fullMatch) {
1239
- propParts.push(`${key}={${w(`${b}.data.${fullMatch[1].trim()}`)}}`);
1240
- } else {
1241
- const replaced = value.replace(/\{\{cms\.([^}]+)\}\}/g, (_, fieldPath) => {
1242
- return `\${${w(`${b}.data.${fieldPath.trim()}`)}}`;
1243
- });
1244
- propParts.push(`${key}={\`${replaced}\`}`);
1245
- }
1246
- } else if (ctx.isComponentDef && isI18nValue(value)) {
1247
- ctx.needsI18nResolver = true;
1248
- propParts.push(`${key}={r(${JSON.stringify(value)})}`);
1249
- } else {
1250
- propParts.push(`${key}=${formatPropValue(value)}`);
1251
- }
1252
- }
1253
- }
1254
- if (node.style) {
1255
- const { classes: instanceClasses } = responsiveStylesToTailwind(node.style, ctx.breakpoints);
1256
- if (instanceClasses.length > 0) {
1257
- propParts.push(`class="${instanceClasses.join(" ")}"`);
1258
- }
1259
- }
1260
- const propsStr = propParts.length > 0 ? " " + propParts.join(" ") : "";
1261
- const children = emitChildren(node.children, ctx);
1262
- if (!children.trim()) {
1263
- return `${ifExpr}${ind(ctx)}<${name}${propsStr} />
1264
- ${emitIfClose(node, ctx)}`;
1265
- }
1266
- return `${ifExpr}${ind(ctx)}<${name}${propsStr}>
1267
- ` + children + `${ind(ctx)}</${name}>
1268
- ${emitIfClose(node, ctx)}`;
1269
- }
1270
- function emitSlotMarker(node, ctx) {
1271
- if (node.default) {
1272
- const defaultContent = emitChildren(node.default, ctx);
1273
- if (defaultContent.trim()) {
1274
- return `${ind(ctx)}<slot>
1275
- ` + defaultContent + `${ind(ctx)}</slot>
1276
- `;
1277
- }
1278
- }
1279
- return `${ind(ctx)}<slot />
1280
- `;
1281
- }
1282
- function emitEmbedNode(node, ctx) {
1283
- const ifExpr = emitIfOpen(node, ctx);
1284
- const style = node.style;
1285
- let elementClass = null;
1286
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1287
- elementClass = buildElementClass(ctx, node.label);
1288
- }
1289
- const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
1290
- const attrs = buildAttributesString(node.attributes, ctx);
1291
- if (isHtmlMapping(node.html)) {
1292
- if (ctx.isComponentDef) {
1293
- const propRef = node.html.prop;
1294
- return `${ifExpr}${ind(ctx)}<div${classExpr.replace('"', '"oem ') || ' class="oem"'}${attrs}>
1295
- ${ind(ctx)} <Fragment set:html={${propRef}} />
1296
- ${ind(ctx)}</div>
1297
- ${emitIfClose(node, ctx)}`;
1298
- }
1299
- }
1300
- const htmlStr = typeof node.html === "string" ? node.html : "";
1301
- const escapedHtml = escapeTemplateLiteral(htmlStr);
1302
- let finalClassExpr = classExpr;
1303
- if (!classExpr.includes("oem")) {
1304
- if (classExpr) {
1305
- finalClassExpr = classExpr.replace(/class="/, 'class="oem ').replace(/class:list={\['/, "class:list={['oem ");
1306
- } else {
1307
- finalClassExpr = ' class="oem"';
1308
- }
1309
- }
1310
- return `${ifExpr}${ind(ctx)}<div${finalClassExpr}${attrs}>
1311
- ${ind(ctx)} <Fragment set:html={\`${escapedHtml}\`} />
1312
- ${ind(ctx)}</div>
1313
- ${emitIfClose(node, ctx)}`;
1314
- }
1315
- function emitLinkNode(node, ctx) {
1316
- const ifExpr = emitIfOpen(node, ctx);
1317
- const style = node.style;
1318
- let elementClass = null;
1319
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1320
- elementClass = buildElementClass(ctx, node.label);
1321
- }
1322
- const { classExpr, styleAttr } = buildClassAndStyleExpression(style, node.interactiveStyles, elementClass, ctx);
1323
- let finalClassExpr = classExpr;
1324
- if (!classExpr.includes("olink")) {
1325
- if (classExpr) {
1326
- finalClassExpr = classExpr.replace(/class="/, 'class="olink ').replace(/class:list={\['/, "class:list={['olink ");
1327
- } else {
1328
- finalClassExpr = ' class="olink"';
1329
- }
1330
- }
1331
- const resolvedHref = resolveI18n(node.href, ctx);
1332
- const nodeHref = resolvedHref;
1333
- let hrefAttr;
1334
- if (isLinkMapping(nodeHref)) {
1335
- if (ctx.isComponentDef) {
1336
- const propRef = nodeHref.prop;
1337
- hrefAttr = ` href={${propRef}?.href ?? "#"}`;
1338
- } else {
1339
- hrefAttr = ' href="#"';
1340
- }
1341
- } else {
1342
- const href = typeof nodeHref === "string" ? nodeHref : "#";
1343
- if (hasTemplates(href) && ctx.isComponentDef) {
1344
- const fullMatch = href.match(/^\{\{(.+)\}\}$/);
1345
- if (fullMatch) {
1346
- let expr = fullMatch[1].trim();
1347
- if (ctx.listItemBinding) expr = rewriteItemVar(expr, ctx.listItemBinding);
1348
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
1349
- const propDef = ctx.componentProps[expr];
1350
- if (propDef && propDef.type === "link") {
1351
- hrefAttr = ` href={${expr}?.href ?? "#"}`;
1352
- } else {
1353
- hrefAttr = ` href={${expr}}`;
1354
- }
1355
- } else {
1356
- const resolved = href.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
1357
- let trimmed = expr.trim();
1358
- if (ctx.listItemBinding) trimmed = rewriteItemVar(trimmed, ctx.listItemBinding);
1359
- if (ctx.listIndexVar) trimmed = replaceItemMetaVars(trimmed, ctx.listIndexVar, ctx.listSourceVar);
1360
- const pd = ctx.componentProps[trimmed];
1361
- return pd?.type === "link" ? `\${${trimmed}?.href ?? "#"}` : `\${${trimmed}}`;
1362
- });
1363
- hrefAttr = ` href={\`${resolved}\`}`;
1364
- }
1365
- } else if (ctx.cmsMode && /\{\{cms\./.test(href)) {
1366
- const b = ctx.cmsEntryBinding || "entry";
1367
- const w = (expr) => ctx.cmsWrapFn ? `${ctx.cmsWrapFn}(${expr})` : expr;
1368
- const fullMatch = href.match(/^\{\{cms\.([^}]+)\}\}$/);
1369
- if (fullMatch) {
1370
- hrefAttr = ` href={${w(`${b}.data.${fullMatch[1].trim()}`)}}`;
1371
- } else {
1372
- const replaced = href.replace(/\{\{cms\.([^}]+)\}\}/g, (_, fieldPath) => {
1373
- return `\${${w(`${b}.data.${fieldPath.trim()}`)}}`;
1374
- });
1375
- hrefAttr = ` href={\`${replaced}\`}`;
1376
- }
1377
- } else {
1378
- const localizedHref = localizeHref(href, ctx);
1379
- hrefAttr = ` href="${escapeJSX(localizedHref)}"`;
1380
- }
1381
- }
1382
- const attrs = buildAttributesString(node.attributes, ctx);
1383
- const children = emitChildren(node.children, ctx);
1384
- if (!children.trim()) {
1385
- return `${ifExpr}${ind(ctx)}<a${hrefAttr}${finalClassExpr}${styleAttr}${attrs} />
1386
- ${emitIfClose(node, ctx)}`;
1387
- }
1388
- return `${ifExpr}${ind(ctx)}<a${hrefAttr}${finalClassExpr}${styleAttr}${attrs}>
1389
- ` + children + `${ind(ctx)}</a>
1390
- ${emitIfClose(node, ctx)}`;
1391
- }
1392
- function emitImageTypeNode(node, ctx) {
1393
- const style = node.style;
1394
- let elementClass = null;
1395
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1396
- elementClass = buildElementClass(ctx, node.label);
1397
- }
1398
- const { classExpr, styleAttr } = buildClassAndStyleExpression(
1399
- style,
1400
- node.interactiveStyles,
1401
- elementClass,
1402
- ctx
1403
- );
1404
- const src = node.src;
1405
- const alt = node.alt;
1406
- let imgAttrs = "";
1407
- if (src) imgAttrs += ` src="${escapeJSX(String(src))}"`;
1408
- if (alt !== void 0) imgAttrs += ` alt="${escapeJSX(String(alt))}"`;
1409
- const metadata = src ? ctx.imageMetadataMap?.get(String(src)) : void 0;
1410
- if (metadata) {
1411
- let width = metadata.width;
1412
- let height = metadata.height;
1413
- if (width !== void 0) imgAttrs += ` width="${width}"`;
1414
- if (height !== void 0) imgAttrs += ` height="${height}"`;
1415
- let blurStyle = "";
1416
- if (metadata.blurHash) {
1417
- blurStyle = ` style="background-image: url(${escapeJSX(metadata.blurHash)}); background-size: cover;" onload="this.style.backgroundImage=''"`;
1418
- }
1419
- const sizesValue = DEFAULT_SIZES2;
1420
- if (metadata.avifSrcset) {
1421
- const classMatch = classExpr.match(/class="([^"]*)"/);
1422
- const allClasses = classMatch ? classMatch[1].split(/\s+/).filter(Boolean) : [];
1423
- const { pictureClasses, imgClasses } = splitImageClasses(allClasses);
1424
- const pictureClassAttr = pictureClasses.length > 0 ? ` class="${pictureClasses.join(" ")}"` : "";
1425
- const imgClassAttr = imgClasses.length > 0 ? ` class="${imgClasses.join(" ")}"` : "";
1426
- return `${ind(ctx)}<picture${pictureClassAttr}${styleAttr}>
1427
- ${ind(ctx)} <source type="image/avif" srcset="${escapeJSX(metadata.avifSrcset)}" sizes="${escapeJSX(sizesValue)}" />
1428
- ${ind(ctx)} <source type="image/webp" srcset="${escapeJSX(metadata.srcset)}" sizes="${escapeJSX(sizesValue)}" />
1429
- ${ind(ctx)} <img${imgClassAttr}${imgAttrs}${blurStyle} />
1430
- ${ind(ctx)}</picture>
1431
- `;
1432
- }
1433
- if (metadata.srcset) {
1434
- imgAttrs += ` srcset="${escapeJSX(metadata.srcset)}"`;
1435
- imgAttrs += ` sizes="${escapeJSX(sizesValue)}"`;
1436
- }
1437
- }
1438
- return `${ind(ctx)}<img${classExpr}${styleAttr}${imgAttrs} />
1439
- `;
1440
- }
1441
- function emitListNode(node, ctx) {
1442
- const sourceType = node.sourceType || "prop";
1443
- const itemAs = node.itemAs || "item";
1444
- if (sourceType === "collection") {
1445
- return emitCollectionListNode(node, ctx);
1446
- }
1447
- if (!ctx.isComponentDef && !ctx.listItemBinding) {
1448
- return emitFallback(ctx);
1449
- }
1450
- let source = node.source || "items";
1451
- const templateMatch = source.match(/^\{\{(.+)\}\}$/);
1452
- if (templateMatch) {
1453
- source = templateMatch[1].trim();
1454
- }
1455
- let mapSource = source;
1456
- if (node.offset && node.limit) {
1457
- mapSource = `${source}.slice(${node.offset}, ${node.offset + node.limit})`;
1458
- } else if (node.offset) {
1459
- mapSource = `${source}.slice(${node.offset})`;
1460
- } else if (node.limit) {
1461
- mapSource = `${source}.slice(0, ${node.limit})`;
1462
- }
1463
- const indexVar = `${itemAs}Index`;
1464
- const innerCtx = {
1465
- ...ctx,
1466
- indent: ctx.indent + 1,
1467
- listItemBinding: itemAs,
1468
- listIndexVar: indexVar,
1469
- listSourceVar: mapSource,
1470
- elementPath: [...ctx.elementPath, 0]
1471
- };
1472
- const children = node.children ? node.children.map((child, i) => {
1473
- const childCtx = { ...innerCtx, elementPath: [...ctx.elementPath, i] };
1474
- const out = nodeToAstro(child, childCtx);
1475
- if (childCtx.needsI18nResolver) ctx.needsI18nResolver = true;
1476
- return out;
1477
- }).join("") : "";
1478
- return `${ind(ctx)}{${mapSource}.map((${itemAs}, ${indexVar}) => (
1479
- ` + children + `${ind(ctx)}))}
1480
- `;
1481
- }
1482
- function emitCollectionListNode(node, ctx) {
1483
- const source = node.source || "";
1484
- const itemAs = node.itemAs || singularize(source);
1485
- if (!ctx.frontmatterLines) ctx.frontmatterLines = [];
1486
- if (!ctx.astroImports) ctx.astroImports = /* @__PURE__ */ new Set();
1487
- ctx.astroImports.add("getCollection");
1488
- const collectionVar = `${source}List`;
1489
- let queryChain = `await getCollection('${source}')`;
1490
- if (node.filter) {
1491
- if (typeof node.filter === "object" && !Array.isArray(node.filter) && "field" in node.filter) {
1492
- const f = node.filter;
1493
- const op = f.operator || "eq";
1494
- if (op === "eq") {
1495
- queryChain += `.then(items => items.filter(e => e.data.${f.field} === ${JSON.stringify(f.value)}))`;
1496
- }
1497
- }
1498
- }
1499
- if (node.sort) {
1500
- const sortConfig = Array.isArray(node.sort) ? node.sort[0] : node.sort;
1501
- if (sortConfig) {
1502
- const order = sortConfig.order === "desc" ? -1 : 1;
1503
- queryChain += `.then(items => items.sort((a, b) => a.data.${sortConfig.field} > b.data.${sortConfig.field} ? ${order} : ${-order}))`;
1504
- }
1505
- }
1506
- if (node.offset || node.limit) {
1507
- const start = node.offset || 0;
1508
- const end = node.limit ? start + node.limit : void 0;
1509
- queryChain += `.then(items => items.slice(${start}${end !== void 0 ? `, ${end}` : ""}))`;
1510
- }
1511
- ctx.frontmatterLines.push(`const ${collectionVar} = ${queryChain};`);
1512
- const indexVar = `${itemAs}Index`;
1513
- const innerCtx = {
1514
- ...ctx,
1515
- indent: ctx.indent + 1,
1516
- listItemBinding: itemAs,
1517
- listIndexVar: indexVar,
1518
- listSourceVar: collectionVar,
1519
- cmsMode: true,
1520
- cmsEntryBinding: itemAs,
1521
- elementPath: [...ctx.elementPath, 0]
1522
- };
1523
- const children = node.children ? node.children.map((child, i) => {
1524
- const childCtx = { ...innerCtx, elementPath: [...ctx.elementPath, i] };
1525
- const out = nodeToAstro(child, childCtx);
1526
- if (childCtx.needsI18nResolver) ctx.needsI18nResolver = true;
1527
- return out;
1528
- }).join("") : "";
1529
- return `${ind(ctx)}{${collectionVar}.map((${itemAs}, ${indexVar}) => (
1530
- ` + children + `${ind(ctx)}))}
1531
- `;
1532
- }
1533
- function emitLocaleListNode(node, ctx) {
1534
- if (!ctx.i18nConfig || !ctx.currentPageSlugMap) {
1535
- return emitFallback(ctx);
1536
- }
1537
- const i18nConfig = ctx.i18nConfig;
1538
- const slugMap = ctx.currentPageSlugMap;
1539
- const showCurrent = node.showCurrent !== false;
1540
- const showSeparator = node.showSeparator !== false;
1541
- const showFlag = node.showFlag !== false;
1542
- const displayType = node.displayType || "nativeName";
1543
- const style = node.style;
1544
- let elementClass = null;
1545
- if (node.interactiveStyles && node.interactiveStyles.length > 0 || node.generateElementClass) {
1546
- elementClass = buildElementClass(ctx, node.label);
1547
- }
1548
- const { classExpr: containerClassExpr, styleAttr: containerStyleAttr } = buildClassAndStyleExpression(
1549
- style,
1550
- node.interactiveStyles,
1551
- elementClass,
1552
- ctx
1553
- );
1554
- const itemStyle = node.itemStyle;
1555
- const itemResult = itemStyle ? responsiveStylesToTailwind(itemStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
1556
- const itemClasses = itemResult.classes;
1557
- const activeItemStyle = node.activeItemStyle;
1558
- const activeResult = activeItemStyle ? responsiveStylesToTailwind(activeItemStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
1559
- const activeItemClasses = [...itemClasses, ...activeResult.classes];
1560
- const separatorStyle = node.separatorStyle;
1561
- const sepResult = separatorStyle ? responsiveStylesToTailwind(separatorStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
1562
- const separatorClasses = sepResult.classes;
1563
- const localeIconMap = /* @__PURE__ */ new Map();
1564
- for (const localeConfig of i18nConfig.locales) {
1565
- if (localeConfig.icon) {
1566
- localeIconMap.set(localeConfig.code, localeConfig.icon);
1567
- }
1568
- }
1569
- const flagStyle = node.flagStyle;
1570
- const flagResult = flagStyle ? responsiveStylesToTailwind(flagStyle, ctx.breakpoints) : { classes: [], dynamicStyles: {} };
1571
- const flagClasses = flagResult.classes;
1572
- const links = [];
1573
- const currentLocale = ctx.locale || i18nConfig.defaultLocale;
1574
- for (const localeConfig of i18nConfig.locales) {
1575
- const code = localeConfig.code;
1576
- const isCurrent = code === currentLocale;
1577
- if (!showCurrent && isCurrent) continue;
1578
- const path = slugMap[code] || "/";
1579
- const classes = isCurrent ? activeItemClasses : itemClasses;
1580
- const classAttr = classes.length > 0 ? ` class="${classes.join(" ")}"` : "";
1581
- const currentAttr = isCurrent ? ' data-current="true"' : ' data-current="false"';
1582
- const hreflangAttr = ` hreflang="${localeConfig.langTag}"`;
1583
- let displayText;
1584
- switch (displayType) {
1585
- case "code":
1586
- displayText = code.toUpperCase();
1587
- break;
1588
- case "name":
1589
- displayText = localeConfig.name;
1590
- break;
1591
- case "nativeName":
1592
- default:
1593
- displayText = localeConfig.nativeName;
1594
- break;
1595
- }
1596
- let linkContent = "";
1597
- const localeIcon = localeIconMap.get(code);
1598
- if (showFlag && localeIcon) {
1599
- const flagClassAttr = flagClasses.length > 0 ? ` class="${flagClasses.join(" ")}"` : "";
1600
- linkContent += `<img src="${escapeJSX(localeIcon)}" alt="${escapeJSX(localeConfig.nativeName)} flag"${flagClassAttr}>`;
1601
- }
1602
- linkContent += `<div>${escapeJSX(displayText)}</div>`;
1603
- links.push(`${ind(ctx)} <a href="${escapeJSX(path)}"${hreflangAttr}${currentAttr} data-locale="${escapeJSX(code)}"${classAttr}>${linkContent}</a>`);
1604
- }
1605
- let linksContent;
1606
- if (showSeparator && links.length > 1) {
1607
- const sepClassAttr = separatorClasses.length > 0 ? ` class="${separatorClasses.join(" ")}"` : "";
1608
- linksContent = links.join(`
1609
- ${ind(ctx)} <span${sepClassAttr}></span>
1610
- `);
1611
- } else {
1612
- linksContent = links.join("\n");
1613
- }
1614
- const attrs = buildAttributesString(node.attributes, ctx);
1615
- return `${ind(ctx)}<div data-locale-list="true"${containerClassExpr}${containerStyleAttr}${attrs}>
1616
- ` + linksContent + `
1617
- ${ind(ctx)}</div>
1618
- `;
1619
- }
1620
- function emitFallback(ctx) {
1621
- const pathKey = ctx.elementPath.join(".");
1622
- const ssrHtml = ctx.ssrFallbacks.get(pathKey);
1623
- if (ssrHtml) {
1624
- const escaped = escapeTemplateLiteral(ssrHtml);
1625
- return `${ind(ctx)}<Fragment set:html={\`${escaped}\`} />
1626
- `;
1627
- }
1628
- return `${ind(ctx)}{/* Complex node - SSR fallback not available */}
1629
- `;
1630
- }
1631
- function emitIfOpen(node, ctx) {
1632
- const ifValue = node.if;
1633
- if (ifValue === void 0 || ifValue === true) return "";
1634
- if (typeof ifValue === "boolean") {
1635
- return ifValue ? "" : `${ind(ctx)}{/* hidden */}
1636
- `;
1637
- }
1638
- if (typeof ifValue === "object" && ifValue._mapping && ctx.isComponentDef) {
1639
- const trueValues = Object.entries(ifValue.values).filter(([, v]) => v === true).map(([k]) => `'${k}'`);
1640
- if (trueValues.length === 0) return `${ind(ctx)}{/* hidden */}
1641
- `;
1642
- if (trueValues.length === 1) {
1643
- return `${ind(ctx)}{${ifValue.prop} === ${trueValues[0]} && (
1644
- `;
1645
- }
1646
- return `${ind(ctx)}{[${trueValues.join(", ")}].includes(${ifValue.prop}) && (
1647
- `;
1648
- }
1649
- if (typeof ifValue === "string") {
1650
- if (ctx.cmsMode && ifValue.includes("{{cms.")) {
1651
- const match = ifValue.match(/^\{\{cms\.([^}]+)\}\}$/);
1652
- if (match) {
1653
- const binding = ctx.cmsEntryBinding || "entry";
1654
- return `${ind(ctx)}{${binding}.data.${match[1].trim()} && (
1655
- `;
1656
- }
1657
- }
1658
- if (ctx.listItemBinding && /\{\{/.test(ifValue)) {
1659
- const match = ifValue.match(/^\{\{([^}]+)\}\}$/);
1660
- if (match) {
1661
- let expr = match[1].trim();
1662
- expr = rewriteItemVar(expr, ctx.listItemBinding);
1663
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
1664
- return `${ind(ctx)}{${expr} && (
1665
- `;
1666
- }
1667
- }
1668
- if (ctx.isComponentDef) {
1669
- const fullMatch = ifValue.match(/^\{\{(.+)\}\}$/);
1670
- let expr = fullMatch ? fullMatch[1].trim() : ifValue.replace(/\{\{(.+?)\}\}/g, "$1");
1671
- if (ctx.listItemBinding) expr = rewriteItemVar(expr, ctx.listItemBinding);
1672
- if (ctx.listIndexVar) expr = replaceItemMetaVars(expr, ctx.listIndexVar, ctx.listSourceVar);
1673
- return `${ind(ctx)}{${expr} && (
1674
- `;
1675
- }
1676
- }
1677
- return "";
1678
- }
1679
- function emitIfClose(node, ctx) {
1680
- const ifValue = node.if;
1681
- if (ifValue === void 0 || ifValue === true) return "";
1682
- if (typeof ifValue === "boolean") return "";
1683
- if (typeof ifValue === "object" && ifValue._mapping && ctx.isComponentDef) {
1684
- return `${ind(ctx)})}
1685
- `;
1686
- }
1687
- if (typeof ifValue === "string") {
1688
- const hasCmsCondition = ctx.cmsMode && ifValue.includes("{{cms.");
1689
- const hasItemCondition = ctx.listItemBinding && /\{\{/.test(ifValue);
1690
- if (hasCmsCondition || hasItemCondition || ctx.isComponentDef) {
1691
- return `${ind(ctx)})}
1692
- `;
1693
- }
1694
- }
1695
- return "";
1696
- }
1697
- function emitChildren(children, ctx) {
1698
- if (!children) return "";
1699
- const innerCtx = { ...ctx, indent: ctx.indent + 1, elementPath: [...ctx.elementPath] };
1700
- if (typeof children === "string") {
1701
- const out2 = nodeToAstro(children, innerCtx);
1702
- if (innerCtx.needsI18nResolver) ctx.needsI18nResolver = true;
1703
- return out2;
1704
- }
1705
- if (Array.isArray(children)) {
1706
- let result = "";
1707
- for (let i = 0; i < children.length; i++) {
1708
- const childCtx = { ...innerCtx, elementPath: [...ctx.elementPath, i] };
1709
- result += nodeToAstro(children[i], childCtx);
1710
- if (childCtx.needsI18nResolver) ctx.needsI18nResolver = true;
1711
- }
1712
- return result;
1713
- }
1714
- const out = nodeToAstro(children, innerCtx);
1715
- if (innerCtx.needsI18nResolver) ctx.needsI18nResolver = true;
1716
- return out;
1717
- }
1718
-
1719
- // lib/server/astro/componentEmitter.ts
1720
- function propDefToTSType(def) {
1721
- switch (def.type) {
1722
- case "string":
1723
- case "rich-text":
1724
- case "file":
1725
- return "string";
1726
- case "number":
1727
- return "number";
1728
- case "boolean":
1729
- return "boolean";
1730
- case "select":
1731
- if ("options" in def && def.options && def.options.length > 0) {
1732
- return def.options.map((o) => `'${o}'`).join(" | ");
1733
- }
1734
- return "string";
1735
- case "link":
1736
- return "{ href: string; target?: string }";
1737
- case "list":
1738
- return "any[]";
1739
- default:
1740
- return "any";
1741
- }
1742
- }
1743
- function formatDefault(def) {
1744
- if (!("default" in def) || def.default === void 0) return null;
1745
- const val = def.default;
1746
- if (typeof val === "string") return JSON.stringify(val);
1747
- if (typeof val === "number" || typeof val === "boolean") return String(val);
1748
- if (typeof val === "object" && val !== null && "_i18n" in val) {
1749
- for (const [key, v] of Object.entries(val)) {
1750
- if (key !== "_i18n" && typeof v === "string") return JSON.stringify(v);
1751
- }
1752
- return null;
1753
- }
1754
- if (typeof val === "object" && val !== null && "href" in val) {
1755
- return JSON.stringify(val);
1756
- }
1757
- if (Array.isArray(val)) {
1758
- return JSON.stringify(val);
1759
- }
1760
- return JSON.stringify(val);
1761
- }
1762
- function emitAstroComponent(name, def, allComponents, breakpoints = DEFAULT_BREAKPOINTS, defaultLocale = "en") {
1763
- const comp = def.component;
1764
- const propDefs = comp.interface || {};
1765
- const structure = comp.structure;
1766
- if (!structure) {
1767
- return buildNoStructureComponent(name, comp);
1768
- }
1769
- const ctx = {
1770
- imports: /* @__PURE__ */ new Set(),
1771
- isComponentDef: true,
1772
- componentProps: propDefs,
1773
- globalComponents: allComponents,
1774
- indent: 0,
1775
- ssrFallbacks: /* @__PURE__ */ new Map(),
1776
- elementPath: [0],
1777
- fileType: "component",
1778
- fileName: name,
1779
- breakpoints,
1780
- defaultLocale
1781
- };
1782
- const templateBody = nodeToAstro(structure, ctx);
1783
- const frontmatter = buildFrontmatter(name, propDefs, ctx.imports, ctx.dynamicTags, ctx.needsI18nResolver ? defaultLocale : void 0);
1784
- const styleSection = comp.css ? `
1785
- <style>
1786
- ${comp.css}
1787
- </style>
1788
- ` : "";
1789
- const scriptSection = comp.javascript ? buildScriptSection(comp.javascript, comp, propDefs) : "";
1790
- return `---
1791
- ${frontmatter}---
1792
- ${templateBody}${styleSection}${scriptSection}`;
1793
- }
1794
- function buildFrontmatter(componentName, propDefs, imports, dynamicTags, i18nDefaultLocale) {
1795
- const lines = [];
1796
- for (const imp of Array.from(imports).sort()) {
1797
- lines.push(`import ${imp} from './${imp}.astro';`);
1798
- }
1799
- if (lines.length > 0) lines.push("");
1800
- const propEntries = Object.entries(propDefs);
1801
- if (propEntries.length > 0) {
1802
- lines.push("interface Props {");
1803
- for (const [propName, propDef] of propEntries) {
1804
- if (propName === "children") continue;
1805
- const tsType = propDefToTSType(propDef);
1806
- const optional = "default" in propDef && propDef.default !== void 0;
1807
- lines.push(` ${propName}${optional ? "?" : ""}: ${tsType};`);
1808
- }
1809
- lines.push("}");
1810
- lines.push("");
1811
- const destructParts = [];
1812
- for (const [propName, propDef] of propEntries) {
1813
- if (propName === "children") continue;
1814
- const defaultVal = formatDefault(propDef);
1815
- if (defaultVal !== null) {
1816
- destructParts.push(`${propName} = ${defaultVal}`);
1817
- } else if (propDef.type === "link") {
1818
- destructParts.push(`${propName} = { href: "#" }`);
1819
- } else {
1820
- destructParts.push(propName);
1821
- }
1822
- }
1823
- if (destructParts.length > 0) {
1824
- if (destructParts.length <= 3 && destructParts.join(", ").length < 80) {
1825
- lines.push(`const { ${destructParts.join(", ")} } = Astro.props;`);
1826
- } else {
1827
- lines.push("const {");
1828
- for (const part of destructParts) {
1829
- lines.push(` ${part},`);
1830
- }
1831
- lines.push("} = Astro.props;");
1832
- }
1833
- }
1834
- }
1835
- if (dynamicTags && dynamicTags.size > 0) {
1836
- lines.push("");
1837
- for (const [varName, templateExpr] of dynamicTags) {
1838
- lines.push(`const ${varName} = \`${templateExpr}\`;`);
1839
- }
1840
- }
1841
- if (i18nDefaultLocale) {
1842
- lines.push("");
1843
- lines.push(`const r = (v: any) => {`);
1844
- lines.push(` if (v && typeof v === 'object' && v._i18n) {`);
1845
- lines.push(` const locale = Astro.currentLocale ?? '${i18nDefaultLocale}';`);
1846
- lines.push(` return v[locale] ?? v['${i18nDefaultLocale}'] ?? Object.values(v).find((s: any) => typeof s === 'string' && s !== '') ?? '';`);
1847
- lines.push(` }`);
1848
- lines.push(` return v ?? '';`);
1849
- lines.push(`};`);
1850
- }
1851
- if (lines.length > 0) lines.push("");
1852
- return lines.join("\n");
1853
- }
1854
- function buildNoStructureComponent(name, comp) {
1855
- let content = "---\n---\n<slot />\n";
1856
- if (comp.css) content += `
1857
- <style>
1858
- ${comp.css}
1859
- </style>
1860
- `;
1861
- if (comp.javascript) content += `
1862
- <script is:inline>
1863
- ${comp.javascript}
1864
- </script>
1865
- `;
1866
- return content;
1867
- }
1868
- function transformDefineVarsJS(js, varNames) {
1869
- let result = js;
1870
- result = result.replace(
1871
- /^\s*(const|let|var)\s+\{([^}]+)\}\s*=\s*props\s*;?\s*$/gm,
1872
- (match, _keyword, inner) => {
1873
- const names = inner.split(",").map((s) => s.trim()).filter(Boolean);
1874
- if (names.every((n) => varNames.includes(n))) return "";
1875
- return match;
1876
- }
1877
- );
1878
- const sorted = [...varNames].sort((a, b) => b.length - a.length);
1879
- for (const name of sorted) {
1880
- result = result.replace(new RegExp(`props\\.${name}\\b`, "g"), name);
1881
- }
1882
- for (const name of varNames) {
1883
- result = result.replace(
1884
- new RegExp(`^\\s*(var|let|const)\\s+${name}\\s*=[^;]*;?\\s*$`, "gm"),
1885
- ""
1886
- );
1887
- }
1888
- return result;
1889
- }
1890
- function buildScriptSection(js, comp, propDefs) {
1891
- const elInit = "const el = document.currentScript.previousElementSibling;";
1892
- if (comp.defineVars) {
1893
- const vars = comp.defineVars === true ? Object.keys(propDefs).filter((k) => k !== "children") : comp.defineVars;
1894
- if (vars.length > 0) {
1895
- const transformedJS = transformDefineVarsJS(js, vars);
1896
- const defineVarsObj = `{ ${vars.join(", ")} }`;
1897
- return `
1898
- <script define:vars={${defineVarsObj}}>
1899
- ${elInit}
1900
- ${transformedJS}
1901
- </script>
1902
- `;
1903
- }
1904
- }
1905
- return `
1906
- <script is:inline>
1907
- ${elInit}
1908
- ${js}
1909
- </script>
1910
- `;
1911
- }
1912
-
1913
- // lib/server/astro/pageEmitter.ts
1914
- function escapeTemplateLiteral2(s) {
1915
- return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
1916
- }
1917
- function escapeJSX2(s) {
1918
- return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
1919
- }
1920
- function componentImportPath(fileDepth, componentName) {
1921
- const ups = "../".repeat(fileDepth + 1);
1922
- return `${ups}components/${componentName}.astro`;
1923
- }
1924
- function emitAstroPage(options) {
1925
- const {
1926
- pageData,
1927
- globalComponents,
1928
- title,
1929
- meta,
1930
- locale,
1931
- theme,
1932
- fontPreloads,
1933
- libraryTags,
1934
- scriptPaths,
1935
- layoutImportPath: layoutImportPath2,
1936
- fileDepth,
1937
- ssrFallbacks,
1938
- pageName,
1939
- breakpoints: breakpointsOpt,
1940
- imageMetadataMap,
1941
- i18nConfig,
1942
- currentPageSlugMap,
1943
- slugMappings
1944
- } = options;
1945
- const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
1946
- const root = pageData.root;
1947
- if (!root) {
1948
- return buildEmptyPage(layoutImportPath2, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths);
1949
- }
1950
- const ctx = {
1951
- imports: /* @__PURE__ */ new Set(),
1952
- isComponentDef: false,
1953
- componentProps: {},
1954
- globalComponents,
1955
- indent: 1,
1956
- // inside BaseLayout
1957
- ssrFallbacks,
1958
- elementPath: [0],
1959
- fileType: "page",
1960
- fileName: pageName,
1961
- breakpoints,
1962
- imageMetadataMap,
1963
- locale,
1964
- i18nConfig,
1965
- currentPageSlugMap,
1966
- frontmatterLines: [],
1967
- astroImports: /* @__PURE__ */ new Set(),
1968
- slugMappings,
1969
- i18nDefaultLocale: i18nConfig?.defaultLocale
1970
- };
1971
- const templateBody = nodeToAstro(root, ctx);
1972
- const importLines = [];
1973
- if (ctx.astroImports && ctx.astroImports.size > 0) {
1974
- const astroImports = Array.from(ctx.astroImports);
1975
- importLines.push(`import { ${astroImports.join(", ")} } from 'astro:content';`);
1976
- }
1977
- importLines.push(`import BaseLayout from '${layoutImportPath2}';`);
1978
- const componentImports = Array.from(ctx.imports).sort();
1979
- for (const comp of componentImports) {
1980
- const path = componentImportPath(fileDepth, comp);
1981
- importLines.push(`import ${comp} from '${path}';`);
1982
- }
1983
- const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
1984
- const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
1985
- const escapedMeta = escapeTemplateLiteral2(meta);
1986
- const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
1987
- const extraFrontmatter = ctx.frontmatterLines && ctx.frontmatterLines.length > 0 ? "\n" + ctx.frontmatterLines.join("\n") : "";
1988
- return `---
1989
- ${importLines.join("\n")}${extraFrontmatter}
1990
- ---
1991
- <BaseLayout
1992
- title="${escapeJSX2(title)}"
1993
- meta={\`${escapedMeta}\`}
1994
- scripts={${scriptsArrayLiteral}}
1995
- locale="${locale}"
1996
- theme="${theme}"
1997
- fontPreloads={\`${escapedFontPreloads}\`}
1998
- libraryTags={${libraryTagsLiteral}}
1999
- >
2000
- <div id="root">
2001
- ${templateBody} </div>
2002
- </BaseLayout>
2003
- `;
2004
- }
2005
- function buildEmptyPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths) {
2006
- const escapedMeta = escapeTemplateLiteral2(meta);
2007
- const escapedFontPreloads = escapeTemplateLiteral2(fontPreloads);
2008
- const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
2009
- const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral2(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral2(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral2(libraryTags.bodyEndJS || "")}\` }`;
2010
- return `---
2011
- import BaseLayout from '${layoutImport}';
2012
- ---
2013
- <BaseLayout
2014
- title="${escapeJSX2(title)}"
2015
- meta={\`${escapedMeta}\`}
2016
- scripts={${scriptsArrayLiteral}}
2017
- locale="${locale}"
2018
- theme="${theme}"
2019
- fontPreloads={\`${escapedFontPreloads}\`}
2020
- libraryTags={${libraryTagsLiteral}}
2021
- >
2022
- </BaseLayout>
2023
- `;
2024
- }
2025
-
2026
- // lib/server/astro/cmsPageEmitter.ts
2027
- function escapeTemplateLiteral3(s) {
2028
- return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
2029
- }
2030
- function escapeJSX3(s) {
2031
- return s.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
2032
- }
2033
- function componentImportPath2(fileDepth, componentName) {
2034
- const ups = "../".repeat(fileDepth + 1);
2035
- return `${ups}components/${componentName}.astro`;
2036
- }
2037
- function collectRichTextFields(schema) {
2038
- const richTextFields = /* @__PURE__ */ new Set();
2039
- for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
2040
- if (fieldDef.type === "rich-text") {
2041
- richTextFields.add(fieldName);
2042
- }
2043
- }
2044
- return richTextFields;
2045
- }
2046
- function transformTitleExpression(title, binding, richTextFields, wrapFn) {
2047
- if (!/\{\{cms\./.test(title)) {
2048
- return `"${escapeJSX3(title)}"`;
2049
- }
2050
- const w = (expr) => wrapFn ? `${wrapFn}(${expr})` : expr;
2051
- const fullMatch = title.match(/^\{\{cms\.([^}]+)\}\}$/);
2052
- if (fullMatch) {
2053
- return `{${w(`${binding}.data.${fullMatch[1].trim()}`)}}`;
2054
- }
2055
- const replaced = title.replace(/\{\{cms\.([^}]+)\}\}/g, (_, fieldPath) => {
2056
- return `\${${w(`${binding}.data.${fieldPath.trim()}`)}}`;
2057
- });
2058
- return `{\`${replaced}\`}`;
2059
- }
2060
- function extractPathPrefix(urlPattern) {
2061
- const withoutLeading = urlPattern.replace(/^\//, "");
2062
- const idx = withoutLeading.indexOf("{{");
2063
- if (idx <= 0) return "";
2064
- return withoutLeading.substring(0, idx);
2065
- }
2066
- function buildGetStaticPaths(schema, isMultiLocale, i18nConfig, locale) {
2067
- const collectionId = schema.id;
2068
- const slugField = schema.slugField || "slug";
2069
- const pathPrefix = extractPathPrefix(schema.urlPattern);
2070
- const targetLocale = locale || i18nConfig.defaultLocale;
2071
- if (!isMultiLocale) {
2072
- const slugExpr = i18nConfig.locales.length > 1 ? `entry.data.${slugField}?.${targetLocale} || entry.data.${slugField} || entry.id` : `entry.data.${slugField} || entry.id`;
2073
- return [
2074
- `export async function getStaticPaths() {`,
2075
- ` const entries = await getCollection('${collectionId}');`,
2076
- ` return entries.map(entry => ({`,
2077
- ` params: { slug: ${slugExpr} },`,
2078
- ` props: { entry },`,
2079
- ` }));`,
2080
- `}`,
2081
- ``,
2082
- `const { entry } = Astro.props;`
2083
- ].join("\n");
2084
- }
2085
- const defaultLocale = i18nConfig.defaultLocale;
2086
- const locales = i18nConfig.locales;
2087
- const lines = [
2088
- `export async function getStaticPaths() {`,
2089
- ` const entries = await getCollection('${collectionId}');`,
2090
- ` const paths = [];`,
2091
- ` for (const entry of entries) {`
2092
- ];
2093
- for (const locale2 of locales) {
2094
- const code = locale2.code;
2095
- const slugExpr = `entry.data.${slugField}?.${code} || entry.data.${slugField} || entry.id`;
2096
- if (code === defaultLocale) {
2097
- if (pathPrefix) {
2098
- lines.push(
2099
- ` paths.push({`,
2100
- ` params: { slug: \`${pathPrefix}\${${slugExpr}}\` },`,
2101
- ` props: { entry, locale: '${code}' },`,
2102
- ` });`
2103
- );
2104
- } else {
2105
- lines.push(
2106
- ` paths.push({`,
2107
- ` params: { slug: ${slugExpr} },`,
2108
- ` props: { entry, locale: '${code}' },`,
2109
- ` });`
2110
- );
2111
- }
2112
- } else {
2113
- lines.push(
2114
- ` paths.push({`,
2115
- ` params: { slug: \`${code}/${pathPrefix}\${${slugExpr}}\` },`,
2116
- ` props: { entry, locale: '${code}' },`,
2117
- ` });`
2118
- );
2119
- }
2120
- }
2121
- lines.push(
2122
- ` }`,
2123
- ` return paths;`,
2124
- `}`,
2125
- ``,
2126
- `const { entry, locale = '${defaultLocale}' } = Astro.props;`
2127
- );
2128
- return lines.join("\n");
2129
- }
2130
- function emitCMSPage(options) {
2131
- const {
2132
- pageData,
2133
- globalComponents,
2134
- cmsSchema,
2135
- title,
2136
- meta,
2137
- locale,
2138
- theme,
2139
- fontPreloads,
2140
- libraryTags,
2141
- scriptPaths,
2142
- layoutImportPath: layoutImportPath2,
2143
- fileDepth,
2144
- ssrFallbacks,
2145
- pageName,
2146
- breakpoints: breakpointsOpt,
2147
- imageMetadataMap,
2148
- i18nConfig,
2149
- isMultiLocale,
2150
- slugMappings
2151
- } = options;
2152
- const breakpoints = breakpointsOpt ?? DEFAULT_BREAKPOINTS;
2153
- const binding = "entry";
2154
- const richTextFields = collectRichTextFields(cmsSchema);
2155
- const wrapFn = "r";
2156
- const root = pageData.root;
2157
- if (!root) {
2158
- return buildEmptyCMSPage(
2159
- layoutImportPath2,
2160
- title,
2161
- meta,
2162
- locale,
2163
- theme,
2164
- fontPreloads,
2165
- libraryTags,
2166
- scriptPaths,
2167
- cmsSchema,
2168
- isMultiLocale,
2169
- i18nConfig,
2170
- binding,
2171
- richTextFields
2172
- );
2173
- }
2174
- const ctx = {
2175
- imports: /* @__PURE__ */ new Set(),
2176
- isComponentDef: false,
2177
- componentProps: {},
2178
- globalComponents,
2179
- indent: 1,
2180
- // inside BaseLayout
2181
- ssrFallbacks,
2182
- elementPath: [0],
2183
- fileType: "page",
2184
- fileName: pageName,
2185
- breakpoints,
2186
- imageMetadataMap,
2187
- locale,
2188
- cmsMode: true,
2189
- cmsEntryBinding: binding,
2190
- cmsRichTextFields: richTextFields,
2191
- cmsWrapFn: wrapFn,
2192
- slugMappings,
2193
- i18nDefaultLocale: i18nConfig.defaultLocale
2194
- };
2195
- const templateBody = nodeToAstro(root, ctx);
2196
- const importLines = [];
2197
- importLines.push(`import { getCollection } from 'astro:content';`);
2198
- importLines.push(`import BaseLayout from '${layoutImportPath2}';`);
2199
- const componentImports = Array.from(ctx.imports).sort();
2200
- for (const comp of componentImports) {
2201
- const path = componentImportPath2(fileDepth, comp);
2202
- importLines.push(`import ${comp} from '${path}';`);
2203
- }
2204
- const staticPaths = buildGetStaticPaths(cmsSchema, isMultiLocale, i18nConfig, locale);
2205
- const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
2206
- const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral3(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral3(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral3(libraryTags.bodyEndJS || "")}\` }`;
2207
- const escapedMeta = escapeTemplateLiteral3(meta).replace(
2208
- /\{\{cms\.([^}]+)\}\}/g,
2209
- (_, fieldPath) => `\${${wrapFn}(${binding}.data.${fieldPath.trim()})}`
2210
- );
2211
- const escapedFontPreloads = escapeTemplateLiteral3(fontPreloads);
2212
- const titleExpr = transformTitleExpression(title, binding, richTextFields, wrapFn);
2213
- const resolverHelper = `function r(v) {
2214
- if (v && typeof v === 'object' && v._i18n) return v['${locale}'] ?? v['${i18nConfig.defaultLocale}'] ?? Object.values(v).find(x => x !== true && x !== undefined) ?? '';
2215
- return v ?? '';
2216
- }`;
2217
- return `---
2218
- ${importLines.join("\n")}
2219
-
2220
- ${staticPaths}
2221
-
2222
- ${resolverHelper}
2223
- ---
2224
- <BaseLayout
2225
- title=${titleExpr}
2226
- meta={\`${escapedMeta}\`}
2227
- scripts={${scriptsArrayLiteral}}
2228
- locale="${locale}"
2229
- theme="${theme}"
2230
- fontPreloads={\`${escapedFontPreloads}\`}
2231
- libraryTags={${libraryTagsLiteral}}
2232
- >
2233
- <div id="root">
2234
- ${templateBody} </div>
2235
- </BaseLayout>
2236
- `;
2237
- }
2238
- function buildEmptyCMSPage(layoutImport, title, meta, locale, theme, fontPreloads, libraryTags, scriptPaths, cmsSchema, isMultiLocale, i18nConfig, binding, richTextFields) {
2239
- const escapedMeta = escapeTemplateLiteral3(meta);
2240
- const escapedFontPreloads = escapeTemplateLiteral3(fontPreloads);
2241
- const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
2242
- const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral3(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral3(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral3(libraryTags.bodyEndJS || "")}\` }`;
2243
- const wrapFn = "r";
2244
- const staticPaths = buildGetStaticPaths(cmsSchema, isMultiLocale, i18nConfig, locale);
2245
- const titleExpr = transformTitleExpression(title, binding, richTextFields, wrapFn);
2246
- const resolverHelper = `function r(v) {
2247
- if (v && typeof v === 'object' && v._i18n) return v['${locale}'] ?? v['${i18nConfig.defaultLocale}'] ?? Object.values(v).find(x => x !== true && x !== undefined) ?? '';
2248
- return v ?? '';
2249
- }`;
2250
- return `---
2251
- import { getCollection } from 'astro:content';
2252
- import BaseLayout from '${layoutImport}';
2253
-
2254
- ${staticPaths}
2255
-
2256
- ${resolverHelper}
2257
- ---
2258
- <BaseLayout
2259
- title=${titleExpr}
2260
- meta={\`${escapedMeta}\`}
2261
- scripts={${scriptsArrayLiteral}}
2262
- locale="${locale}"
2263
- theme="${theme}"
2264
- fontPreloads={\`${escapedFontPreloads}\`}
2265
- libraryTags={${libraryTagsLiteral}}
2266
- >
2267
- </BaseLayout>
2268
- `;
2269
- }
2270
-
2271
- // lib/server/astro/cssCollector.ts
2272
- function isStyleMapping3(value) {
2273
- return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
2274
- }
2275
- function isResponsiveStyle3(style) {
2276
- return "base" in style || "tablet" in style || "mobile" in style;
2277
- }
2278
- function collectFromStyle(style, classes, breakpoints) {
2279
- if (!style) return;
2280
- if (isResponsiveStyle3(style)) {
2281
- for (const [bp, bpStyle] of Object.entries(style)) {
2282
- if (!bpStyle) continue;
2283
- let prefix = "";
2284
- if (bp !== "base") {
2285
- const bpValue = breakpoints[bp]?.breakpoint;
2286
- if (bpValue) {
2287
- prefix = `max-[${bpValue}px]:`;
2288
- }
2289
- }
2290
- collectFromFlatStyle(bpStyle, prefix, classes);
2291
- }
2292
- } else {
2293
- collectFromFlatStyle(style, "", classes);
2294
- }
2295
- }
2296
- function collectFromFlatStyle(style, prefix, classes) {
2297
- for (const [property, value] of Object.entries(style)) {
2298
- if (!isStyleMapping3(value)) continue;
2299
- for (const [, cssValue] of Object.entries(value.values)) {
2300
- const twClass = propertyToTailwind(property, cssValue);
2301
- if (twClass) {
2302
- classes.add(prefix ? `${prefix}${twClass}` : twClass);
2303
- }
2304
- }
2305
- }
2306
- }
2307
- function walkNode(node, classes, breakpoints) {
2308
- if (!node || typeof node === "string" || typeof node === "number") return;
2309
- if (Array.isArray(node)) {
2310
- for (const child of node) {
2311
- walkNode(child, classes, breakpoints);
2312
- }
2313
- return;
2314
- }
2315
- if ("style" in node && node.style) {
2316
- collectFromStyle(node.style, classes, breakpoints);
2317
- }
2318
- if ("interactiveStyles" in node && Array.isArray(node.interactiveStyles)) {
2319
- for (const rule of node.interactiveStyles) {
2320
- if (rule.style) {
2321
- collectFromStyle(rule.style, classes, breakpoints);
2322
- }
2323
- }
2324
- }
2325
- if ("children" in node && node.children) {
2326
- if (Array.isArray(node.children)) {
2327
- for (const child of node.children) {
2328
- walkNode(child, classes, breakpoints);
2329
- }
2330
- }
2331
- }
2332
- }
2333
- function collectAllMappingClasses(componentDefs, breakpoints = DEFAULT_BREAKPOINTS) {
2334
- const classes = /* @__PURE__ */ new Set();
2335
- for (const def of Object.values(componentDefs)) {
2336
- const structure = def.component?.structure;
2337
- if (structure) {
2338
- walkNode(structure, classes, breakpoints);
2339
- }
2340
- }
2341
- return classes;
2342
- }
2343
-
2344
- // build-astro.ts
2345
- function hashContent2(content) {
2346
- return createHash("sha256").update(content).digest("hex").slice(0, 8);
2347
- }
2348
- function copyDirectory(src, dest) {
2349
- if (!existsSync(src)) return;
2350
- if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
2351
- const files = readdirSync(src);
2352
- for (const file of files) {
2353
- const srcPath = join(src, file);
2354
- const destPath = join(dest, file);
2355
- const stat = statSync(srcPath);
2356
- if (stat.isDirectory()) copyDirectory(srcPath, destPath);
2357
- else copyFileSync(srcPath, destPath);
2358
- }
2359
- }
2360
- function isCMSPage(pageData) {
2361
- return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
2362
- }
2363
- function scanJSONFiles(dir, prefix = "") {
2364
- const results = [];
2365
- if (!existsSync(dir)) return results;
2366
- const entries = readdirSync(dir, { withFileTypes: true });
2367
- for (const entry of entries) {
2368
- if (entry.isFile() && entry.name.endsWith(".json")) {
2369
- results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
2370
- } else if (entry.isDirectory()) {
2371
- results.push(...scanJSONFiles(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
2372
- }
2373
- }
2374
- return results;
2375
- }
2376
- function layoutImportPath(fileDepth) {
2377
- const ups = "../".repeat(fileDepth + 1);
2378
- return `${ups}layouts/BaseLayout.astro`;
2379
- }
2380
- function escapeTemplateLiteral4(s) {
2381
- return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
2382
- }
2383
- function computePageSlugMap(slugs, i18nConfig) {
2384
- const map = {};
2385
- for (const localeConfig of i18nConfig.locales) {
2386
- const code = localeConfig.code;
2387
- const isDefault = code === i18nConfig.defaultLocale;
2388
- const slug = slugs[code] || "";
2389
- if (isDefault) {
2390
- map[code] = slug === "" ? "/" : `/${slug}`;
2391
- } else {
2392
- map[code] = slug === "" ? `/${code}` : `/${code}/${slug}`;
2393
- }
2394
- }
2395
- return map;
2396
- }
2397
- function cmsFieldToZod(field) {
2398
- switch (field.type) {
2399
- case "string":
2400
- case "text":
2401
- case "rich-text":
2402
- return "z.union([z.string(), z.object({ _i18n: z.literal(true) }).passthrough()])";
2403
- case "number":
2404
- return "z.number()";
2405
- case "boolean":
2406
- return "z.boolean()";
2407
- case "date":
2408
- return "z.coerce.date()";
2409
- case "select":
2410
- if (field.options && field.options.length > 0) {
2411
- const opts = field.options.map((o) => `'${o.replace(/'/g, "\\'")}'`).join(", ");
2412
- return `z.enum([${opts}])`;
2413
- }
2414
- return "z.string()";
2415
- case "image":
2416
- case "file":
2417
- return "z.string()";
2418
- case "reference":
2419
- return "z.string()";
2420
- default:
2421
- return "z.string()";
2422
- }
2423
- }
2424
- function buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths) {
2425
- const escapedMeta = escapeTemplateLiteral4(result.meta);
2426
- const escapedHTML = escapeTemplateLiteral4(result.html);
2427
- const escapedFontPreloads = escapeTemplateLiteral4(fontPreloads);
2428
- const scriptsArrayLiteral = scriptPaths.length > 0 ? `[${scriptPaths.map((s) => `"${s}"`).join(", ")}]` : "[]";
2429
- const libraryTagsLiteral = `{ headCSS: \`${escapeTemplateLiteral4(libraryTags.headCSS || "")}\`, headJS: \`${escapeTemplateLiteral4(libraryTags.headJS || "")}\`, bodyEndJS: \`${escapeTemplateLiteral4(libraryTags.bodyEndJS || "")}\` }`;
2430
- return `---
2431
- import BaseLayout from '${importPath}';
2432
- ---
2433
- <BaseLayout
2434
- title="${result.title.replace(/"/g, "&quot;")}"
2435
- meta={\`${escapedMeta}\`}
2436
- scripts={${scriptsArrayLiteral}}
2437
- locale="${result.locale}"
2438
- theme="${defaultTheme}"
2439
- fontPreloads={\`${escapedFontPreloads}\`}
2440
- libraryTags={${libraryTagsLiteral}}
2441
- >
2442
- <Fragment set:html={\`<div id="root">${escapedHTML}</div>\`} />
2443
- </BaseLayout>
2444
- `;
2445
- }
2446
- async function buildAstroProject(projectRoot, outputDir) {
2447
- const startTime = Date.now();
2448
- console.log("\u{1F3D7}\uFE0F Building Astro export...\n");
2449
- configService.reset();
2450
- const projectConfig = await loadProjectConfig();
2451
- const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "") || "";
2452
- const i18nConfig = await loadI18nConfig();
2453
- console.log(`\u{1F310} Locales: ${i18nConfig.locales.map((l) => l.code).join(", ")} (default: ${i18nConfig.defaultLocale})
2454
- `);
2455
- await migrateTemplatesDirectory();
2456
- const { components, warnings, errors: compErrors } = await loadComponentDirectory(projectPaths.components());
2457
- const globalComponents = {};
2458
- components.forEach((value, key) => {
2459
- globalComponents[key] = value;
2460
- });
2461
- for (const w of warnings) console.warn(` Warning: ${w}`);
2462
- for (const e of compErrors) console.error(` Error: ${e}`);
2463
- console.log(`Loaded ${components.size} global component(s)
2464
- `);
2465
- const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());
2466
- const cmsService = new CMSService(cmsProvider);
2467
- await cmsService.initialize();
2468
- console.log("CMS service initialized\n");
2469
- const themeConfig = await colorService.loadThemeConfig();
2470
- const variablesConfig = await variableService.loadConfig();
2471
- const breakpoints = await loadBreakpointConfig();
2472
- const responsiveScales = await loadResponsiveScalesConfig();
2473
- await configService.load();
2474
- const globalLibraries = configService.getLibraries();
2475
- const componentLibraries = collectComponentLibraries(globalComponents);
2476
- const imageMetadataMap = await buildImageMetadataMap();
2477
- if (imageMetadataMap.size > 0) {
2478
- console.log(`Loaded image metadata for ${imageMetadataMap.size} image(s)
2479
- `);
2480
- }
2481
- const outDir = outputDir || join(projectPaths.project, "astro-export");
2482
- if (existsSync(outDir)) {
2483
- rmSync(outDir, { recursive: true, force: true });
2484
- }
2485
- mkdirSync(outDir, { recursive: true });
2486
- const srcDir = join(outDir, "src");
2487
- const pagesOutDir = join(srcDir, "pages");
2488
- const layoutsDir = join(srcDir, "layouts");
2489
- const stylesDir = join(srcDir, "styles");
2490
- const componentsOutDir = join(srcDir, "components");
2491
- const publicDir = join(outDir, "public");
2492
- const scriptsDir = join(publicDir, "_scripts");
2493
- for (const d of [srcDir, pagesOutDir, layoutsDir, stylesDir, componentsOutDir, publicDir]) {
2494
- mkdirSync(d, { recursive: true });
2495
- }
2496
- const pagesDir = projectPaths.pages();
2497
- if (!existsSync(pagesDir)) {
2498
- console.error("Pages directory not found!");
2499
- return { pages: 0, cmsPages: 0, collections: 0, errors: 1 };
2500
- }
2501
- const pageFiles = scanJSONFiles(pagesDir);
2502
- if (pageFiles.length === 0) {
2503
- console.warn("No pages found in ./pages directory");
2504
- return { pages: 0, cmsPages: 0, collections: 0, errors: 0 };
2505
- }
2506
- console.log(`Found ${pageFiles.length} page(s) to process
2507
- `);
2508
- const slugMappings = [];
2509
- for (const file of pageFiles) {
2510
- const pageName = file.replace(".json", "");
2511
- const basePath = mapPageNameToPath(pageName);
2512
- const pageContent = await loadJSONFile(join(pagesDir, file));
2513
- if (!pageContent) continue;
2514
- try {
2515
- const pageData = parseJSON(pageContent);
2516
- if (pageData.meta?.slugs) {
2517
- const pageId = basePath === "/" ? "index" : basePath.substring(1);
2518
- slugMappings.push({ pageId, slugs: pageData.meta.slugs });
2519
- }
2520
- } catch {
2521
- }
2522
- }
2523
- const allResults = [];
2524
- const allInteractiveStyles = /* @__PURE__ */ new Map();
2525
- const allComponentCSS = /* @__PURE__ */ new Set();
2526
- const jsContents = /* @__PURE__ */ new Map();
2527
- let errorCount = 0;
2528
- function mergeInteractiveStyles(source) {
2529
- for (const [key, value] of source) {
2530
- if (!allInteractiveStyles.has(key)) {
2531
- allInteractiveStyles.set(key, value);
2532
- }
2533
- }
2534
- }
2535
- function processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, isCMSPage3) {
2536
- mergeInteractiveStyles(result.interactiveStylesMap);
2537
- if (result.componentCSS) {
2538
- allComponentCSS.add(result.componentCSS);
2539
- }
2540
- if (result.javascript) {
2541
- const hash = hashContent2(result.javascript);
2542
- if (!jsContents.has(hash)) {
2543
- jsContents.set(hash, result.javascript);
2544
- }
2545
- }
2546
- allResults.push({
2547
- html: result.html,
2548
- meta: result.meta,
2549
- title: result.title,
2550
- javascript: result.javascript,
2551
- componentCSS: result.componentCSS,
2552
- locale: result.locale,
2553
- interactiveStylesMap: result.interactiveStylesMap,
2554
- urlPath,
2555
- fileDepth,
2556
- astroFilePath,
2557
- pageData,
2558
- pageName,
2559
- isCMSPage: isCMSPage3,
2560
- ssrFallbackCollector: result.ssrFallbackCollector
2561
- });
2562
- }
2563
- for (const file of pageFiles) {
2564
- const pageName = file.replace(".json", "");
2565
- const basePath = mapPageNameToPath(pageName);
2566
- const pageContent = await loadJSONFile(join(pagesDir, file));
2567
- if (!pageContent) {
2568
- console.warn(` Skipping ${basePath} (empty file)`);
2569
- errorCount++;
2570
- continue;
2571
- }
2572
- try {
2573
- const pageData = parseJSON(pageContent);
2574
- const isDevBuild = process.env.MENO_DEV_BUILD === "true";
2575
- if (pageData.meta?.draft === true && !isDevBuild) {
2576
- console.log(` Skipping draft: ${basePath}`);
2577
- continue;
2578
- }
2579
- const slugs = pageData.meta?.slugs;
2580
- for (const localeConfig of i18nConfig.locales) {
2581
- const locale = localeConfig.code;
2582
- const isDefault = locale === i18nConfig.defaultLocale;
2583
- let slug;
2584
- if (slugs && slugs[locale]) {
2585
- slug = slugs[locale];
2586
- } else if (basePath === "/") {
2587
- slug = "";
2588
- } else {
2589
- slug = basePath.substring(1);
2590
- }
2591
- const urlPath = isDefault ? slug === "" ? "/" : `/${slug}` : slug === "" ? `/${locale}` : `/${locale}/${slug}`;
2592
- const astroFileName = slug === "" ? "index.astro" : `${slug}.astro`;
2593
- const astroFilePath = isDefault ? astroFileName : `${locale}/${astroFileName}`;
2594
- const fileDepth = astroFilePath.split("/").length - 1;
2595
- const result = await renderPageSSR(
2596
- pageData,
2597
- globalComponents,
2598
- urlPath,
2599
- siteUrl,
2600
- locale,
2601
- i18nConfig,
2602
- slugMappings,
2603
- void 0,
2604
- // cmsContext
2605
- cmsService,
2606
- true
2607
- // isProductionBuild
2608
- );
2609
- processRenderResult(result, urlPath, astroFilePath, fileDepth, pageData, pageName, false);
2610
- console.log(` Rendered: ${urlPath}`);
2611
- }
2612
- } catch (error) {
2613
- console.error(` Error rendering ${basePath}:`, error?.message || error);
2614
- errorCount++;
2615
- }
2616
- }
2617
- const fontPreloads = generateFontPreloadTags();
2618
- const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
2619
- const buildLibraries = filterLibrariesByContext(mergedLibraries, "build");
2620
- const libraryTags = generateLibraryTags(buildLibraries);
2621
- const defaultTheme = themeConfig.default || "light";
2622
- const templatesDir = projectPaths.templates();
2623
- const templateSchemas = [];
2624
- let cmsPageCount = 0;
2625
- if (existsSync(templatesDir)) {
2626
- const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
2627
- if (templateFiles.length > 0) {
2628
- console.log(`
2629
- Processing ${templateFiles.length} CMS template(s)...
2630
- `);
2631
- }
2632
- for (const file of templateFiles) {
2633
- const templateContent = await loadJSONFile(join(templatesDir, file));
2634
- if (!templateContent) continue;
2635
- try {
2636
- const pageData = parseJSON(templateContent);
2637
- const isDevBuild = process.env.MENO_DEV_BUILD === "true";
2638
- if (pageData.meta?.draft === true && !isDevBuild) {
2639
- console.log(` Skipping draft template: ${file}`);
2640
- continue;
2641
- }
2642
- if (!isCMSPage(pageData)) {
2643
- console.warn(` ${file} is in templates/ but missing meta.source: "cms"`);
2644
- continue;
2645
- }
2646
- const cmsSchema = pageData.meta.cms;
2647
- templateSchemas.push(cmsSchema);
2648
- console.log(` CMS Collection: ${cmsSchema.id}`);
2649
- const items = await cmsService.queryItems({ collection: cmsSchema.id });
2650
- const itemCount = items.length;
2651
- if (itemCount === 0) {
2652
- console.log(` No items found in cms/${cmsSchema.id}/`);
2653
- } else {
2654
- console.log(` Found ${itemCount} item(s)`);
2655
- }
2656
- const defaultLocale = i18nConfig.defaultLocale;
2657
- const dummyPath = cmsSchema.urlPattern.replace("{{slug}}", "__placeholder__");
2658
- const metaResult = await renderPageSSR(
2659
- pageData,
2660
- globalComponents,
2661
- dummyPath,
2662
- siteUrl,
2663
- defaultLocale,
2664
- i18nConfig,
2665
- slugMappings,
2666
- void 0,
2667
- // no CMS context - just collecting metadata
2668
- cmsService,
2669
- true
2670
- );
2671
- mergeInteractiveStyles(metaResult.interactiveStylesMap);
2672
- if (metaResult.componentCSS) {
2673
- allComponentCSS.add(metaResult.componentCSS);
2674
- }
2675
- const scriptPaths = [];
2676
- if (metaResult.javascript) {
2677
- const hash = hashContent2(metaResult.javascript);
2678
- if (!jsContents.has(hash)) {
2679
- jsContents.set(hash, metaResult.javascript);
2680
- }
2681
- scriptPaths.push(`/_scripts/${hash}.js`);
2682
- }
2683
- const isMultiLocale = i18nConfig.locales.length > 1;
2684
- const urlPatternWithoutSlash = cmsSchema.urlPattern.replace(/^\//, "");
2685
- const slugPlaceholderIdx = urlPatternWithoutSlash.indexOf("{{");
2686
- const pathPrefix = slugPlaceholderIdx > 0 ? urlPatternWithoutSlash.substring(0, slugPlaceholderIdx) : "";
2687
- const ssrFallbacks = metaResult.ssrFallbackCollector ?? /* @__PURE__ */ new Map();
2688
- const localesToEmit = isMultiLocale ? i18nConfig.locales : [{ code: i18nConfig.defaultLocale }];
2689
- for (const localeEntry of localesToEmit) {
2690
- const localeCode = localeEntry.code;
2691
- const isDefault = localeCode === i18nConfig.defaultLocale;
2692
- let astroFilePath;
2693
- if (pathPrefix) {
2694
- astroFilePath = isDefault ? `${pathPrefix}[slug].astro` : `${localeCode}/${pathPrefix}[slug].astro`;
2695
- } else {
2696
- astroFilePath = isDefault ? "[slug].astro" : `${localeCode}/[slug].astro`;
2697
- }
2698
- const fileDepth = astroFilePath.split("/").length - 1;
2699
- const importPath = layoutImportPath(fileDepth);
2700
- const astroContent = emitCMSPage({
2701
- pageData,
2702
- globalComponents,
2703
- cmsSchema,
2704
- title: String(pageData.meta?.title || cmsSchema.name),
2705
- meta: metaResult.meta,
2706
- locale: localeCode,
2707
- theme: defaultTheme,
2708
- fontPreloads,
2709
- libraryTags,
2710
- scriptPaths,
2711
- layoutImportPath: importPath,
2712
- fileDepth,
2713
- ssrFallbacks,
2714
- pageName: file.replace(".json", ""),
2715
- breakpoints,
2716
- imageMetadataMap,
2717
- i18nConfig,
2718
- isMultiLocale: false,
2719
- // Each file handles one locale
2720
- slugMappings
2721
- });
2722
- const astroFileFull = join(pagesOutDir, astroFilePath);
2723
- const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
2724
- if (!existsSync(astroFileDir)) {
2725
- mkdirSync(astroFileDir, { recursive: true });
2726
- }
2727
- await writeFile2(astroFileFull, astroContent, "utf-8");
2728
- }
2729
- console.log(` Generated: ${pathPrefix}[slug].astro (${itemCount} items \xD7 ${localesToEmit.length} locale(s))`);
2730
- cmsPageCount += itemCount * i18nConfig.locales.length;
2731
- } catch (error) {
2732
- console.error(` Error processing template ${file}:`, error?.message || error);
2733
- errorCount++;
2734
- }
2735
- }
2736
- }
2737
- const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints);
2738
- const fontCSS = generateFontCSS();
2739
- const themeColorCSS = generateThemeColorVariablesCSS(themeConfig);
2740
- const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
2741
- const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints);
2742
- const componentCSSCombined = Array.from(allComponentCSS).join("\n");
2743
- const baseCSS = `@layer base {
2744
- * { margin: 0; padding: 0; box-sizing: border-box; }
2745
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; }
2746
- button { background: none; border: none; padding: 0; font: inherit; cursor: pointer; outline: inherit; }
2747
- img { display: block; width: 100%; height: 100%; }
2748
- picture { display: block; }
2749
- .olink { text-decoration: none; display: block; }
2750
- .oem { display: inline-block; }
2751
- }`;
2752
- const tailwindDirectives = `@tailwind base;
2753
- @tailwind components;
2754
- @tailwind utilities;`;
2755
- const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined, interactiveCSS].filter(Boolean).join("\n\n");
2756
- await writeFile2(join(stylesDir, "global.css"), globalCSS, "utf-8");
2757
- console.log(`
2758
- Generated global.css (${(globalCSS.length / 1024).toFixed(1)} KB)`);
2759
- const baseLayoutContent = `---
2760
- import '../styles/global.css';
2761
-
2762
- interface Props {
2763
- title: string;
2764
- meta?: string;
2765
- scripts?: string[];
2766
- locale?: string;
2767
- theme?: string;
2768
- fontPreloads?: string;
2769
- libraryTags?: { headCSS?: string; headJS?: string; bodyEndJS?: string };
2770
- }
2771
-
2772
- const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.default || "light"}', fontPreloads = '', libraryTags = {} } = Astro.props;
2773
- ---
2774
- <!DOCTYPE html>
2775
- <html lang={locale} data-theme={theme}>
2776
- <head>
2777
- <meta charset="UTF-8">
2778
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
2779
- <Fragment set:html={fontPreloads} />
2780
- <Fragment set:html={libraryTags.headCSS || ''} />
2781
- <Fragment set:html={libraryTags.headJS || ''} />
2782
- <Fragment set:html={meta} />
2783
- <title>{title}</title>
2784
- </head>
2785
- <body>
2786
- <slot />
2787
- {scripts.map((s) => <script src={s} />)}
2788
- <Fragment set:html={libraryTags.bodyEndJS || ''} />
2789
- </body>
2790
- </html>
2791
- `;
2792
- await writeFile2(join(layoutsDir, "BaseLayout.astro"), baseLayoutContent, "utf-8");
2793
- console.log("Generated BaseLayout.astro");
2794
- let componentFileCount = 0;
2795
- for (const [compName, compDef] of Object.entries(globalComponents)) {
2796
- try {
2797
- const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale);
2798
- await writeFile2(join(componentsOutDir, `${compName}.astro`), astroContent, "utf-8");
2799
- componentFileCount++;
2800
- } catch (error) {
2801
- console.warn(` Warning: could not generate component ${compName}: ${error?.message}`);
2802
- }
2803
- }
2804
- console.log(`Generated ${componentFileCount} component .astro file(s)`);
2805
- const allFallbackHtml = [];
2806
- for (const result of allResults) {
2807
- const importPath = layoutImportPath(result.fileDepth);
2808
- const scriptPaths = [];
2809
- if (result.javascript) {
2810
- const hash = hashContent2(result.javascript);
2811
- const scriptFile = `${hash}.js`;
2812
- const scriptPublicPath = `/_scripts/${scriptFile}`;
2813
- if (!existsSync(scriptsDir)) {
2814
- mkdirSync(scriptsDir, { recursive: true });
2815
- }
2816
- const fullScriptPath = join(scriptsDir, scriptFile);
2817
- if (!existsSync(fullScriptPath)) {
2818
- await writeFile2(fullScriptPath, result.javascript, "utf-8");
2819
- }
2820
- scriptPaths.push(scriptPublicPath);
2821
- }
2822
- let astroContent;
2823
- if (result.pageData) {
2824
- try {
2825
- const ssrFallbacks = result.ssrFallbackCollector ?? /* @__PURE__ */ new Map();
2826
- ssrFallbacks.forEach((html) => {
2827
- allFallbackHtml.push(html);
2828
- });
2829
- const pageSlugMap = result.pageData.meta?.slugs ? computePageSlugMap(result.pageData.meta.slugs, i18nConfig) : void 0;
2830
- astroContent = emitAstroPage({
2831
- pageData: result.pageData,
2832
- globalComponents,
2833
- title: result.title,
2834
- meta: result.meta,
2835
- locale: result.locale,
2836
- theme: defaultTheme,
2837
- fontPreloads,
2838
- libraryTags,
2839
- scriptPaths,
2840
- layoutImportPath: importPath,
2841
- fileDepth: result.fileDepth,
2842
- ssrFallbacks,
2843
- pageName: result.pageName || "index",
2844
- breakpoints,
2845
- imageMetadataMap,
2846
- i18nConfig: i18nConfig.locales.length > 1 ? i18nConfig : void 0,
2847
- currentPageSlugMap: pageSlugMap,
2848
- slugMappings: i18nConfig.locales.length > 1 ? slugMappings : void 0
2849
- });
2850
- } catch (error) {
2851
- console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
2852
- astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
2853
- }
2854
- } else {
2855
- astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
2856
- allFallbackHtml.push(result.html);
2857
- }
2858
- const astroFileFull = join(pagesOutDir, result.astroFilePath);
2859
- const astroFileDir = astroFileFull.substring(0, astroFileFull.lastIndexOf("/"));
2860
- if (!existsSync(astroFileDir)) {
2861
- mkdirSync(astroFileDir, { recursive: true });
2862
- }
2863
- await writeFile2(astroFileFull, astroContent, "utf-8");
2864
- }
2865
- console.log(`Generated ${allResults.length} .astro page file(s)`);
2866
- if (allFallbackHtml.length > 0) {
2867
- const allClasses = /* @__PURE__ */ new Set();
2868
- for (const html of allFallbackHtml) {
2869
- for (const cls of extractUtilityClassesFromHTML(html)) {
2870
- allClasses.add(cls);
2871
- }
2872
- }
2873
- if (allClasses.size > 0) {
2874
- const utilityCSS = generateUtilityCSS(allClasses, breakpoints, responsiveScales);
2875
- if (utilityCSS) {
2876
- const existingCSS = await readFile(join(stylesDir, "global.css"), "utf-8");
2877
- await writeFile2(join(stylesDir, "global.css"), existingCSS + "\n\n/* SSR fallback utility classes */\n" + utilityCSS, "utf-8");
2878
- console.log(`Added ${allClasses.size} utility classes for SSR fallback content`);
2879
- }
2880
- }
2881
- }
2882
- let collectionCount = 0;
2883
- if (templateSchemas.length > 0) {
2884
- const contentDir = join(srcDir, "content");
2885
- mkdirSync(contentDir, { recursive: true });
2886
- const collectionDefs = [];
2887
- for (const schema of templateSchemas) {
2888
- const collectionDir = join(contentDir, schema.id);
2889
- mkdirSync(collectionDir, { recursive: true });
2890
- const cmsItemsDir = join(projectPaths.cms(), schema.id);
2891
- if (existsSync(cmsItemsDir)) {
2892
- const itemFiles = readdirSync(cmsItemsDir).filter((f) => f.endsWith(".json"));
2893
- for (const itemFile of itemFiles) {
2894
- try {
2895
- const rawContent = await readFile(join(cmsItemsDir, itemFile), "utf-8");
2896
- const item = JSON.parse(rawContent);
2897
- const resolved = { ...item };
2898
- await writeFile2(
2899
- join(collectionDir, itemFile),
2900
- JSON.stringify(resolved, null, 2),
2901
- "utf-8"
2902
- );
2903
- } catch (err) {
2904
- console.warn(` Warning: could not process CMS item ${itemFile}: ${err?.message}`);
2905
- }
2906
- }
2907
- }
2908
- const fieldDefs = [];
2909
- if (schema.fields) {
2910
- for (const [fieldName, fieldDef] of Object.entries(schema.fields)) {
2911
- const zodType = cmsFieldToZod(fieldDef);
2912
- const optional = fieldDef.required ? "" : ".optional()";
2913
- fieldDefs.push(` ${fieldName}: ${zodType}${optional}`);
2914
- }
2915
- }
2916
- collectionDefs.push(` '${schema.id}': defineCollection({
2917
- type: 'data',
2918
- schema: z.object({
2919
- ${fieldDefs.join(",\n")}
2920
- })
2921
- })`);
2922
- collectionCount++;
2923
- }
2924
- const configContent = `import { z, defineCollection } from 'astro:content';
2925
-
2926
- const collections = {
2927
- ${collectionDefs.join(",\n")}
2928
- };
2929
-
2930
- export { collections };
2931
- `;
2932
- await writeFile2(join(contentDir, "config.ts"), configContent, "utf-8");
2933
- console.log(`Generated ${collectionCount} content collection(s) with config.ts`);
2934
- }
2935
- const assetDirs = ["fonts", "images", "icons", "videos", "assets"];
2936
- let copiedAssets = 0;
2937
- for (const dir of assetDirs) {
2938
- const srcAssetDir = join(projectPaths.project, dir);
2939
- if (existsSync(srcAssetDir)) {
2940
- copyDirectory(srcAssetDir, join(publicDir, dir));
2941
- copiedAssets++;
2942
- }
2943
- }
2944
- const librariesDir = join(projectPaths.project, "libraries");
2945
- if (existsSync(librariesDir)) {
2946
- copyDirectory(librariesDir, join(publicDir, "libraries"));
2947
- copiedAssets++;
2948
- }
2949
- if (copiedAssets > 0) {
2950
- console.log(`Copied ${copiedAssets} asset director${copiedAssets === 1 ? "y" : "ies"} to public/`);
2951
- }
2952
- const packageJson = {
2953
- name: "astro-export",
2954
- type: "module",
2955
- version: "0.0.1",
2956
- private: true,
2957
- scripts: {
2958
- dev: "astro dev",
2959
- start: "astro dev",
2960
- build: "astro build",
2961
- preview: "astro preview"
2962
- },
2963
- dependencies: {
2964
- "astro": "^4.0.0",
2965
- "@astrojs/tailwind": "^5.0.0",
2966
- "tailwindcss": "^3.4.0"
2967
- }
2968
- };
2969
- await writeFile2(join(outDir, "package.json"), JSON.stringify(packageJson, null, 2), "utf-8");
2970
- const localeCodes = i18nConfig.locales.map((l) => l.code);
2971
- const i18nBlock = i18nConfig.locales.length > 1 ? `
2972
- i18n: {
2973
- defaultLocale: '${i18nConfig.defaultLocale}',
2974
- locales: [${localeCodes.map((c) => `'${c}'`).join(", ")}],
2975
- routing: { prefixDefaultLocale: false },
2976
- },` : "";
2977
- const astroConfig = `import { defineConfig } from 'astro/config';
2978
- import tailwind from '@astrojs/tailwind';
2979
-
2980
- export default defineConfig({${siteUrl ? `
2981
- site: '${siteUrl}',` : ""}${i18nBlock}
2982
- integrations: [tailwind({ applyBaseStyles: false })],
2983
- });
2984
- `;
2985
- const safelistArray = Array.from(mappingClasses);
2986
- const safelistLiteral = safelistArray.length > 0 ? `
2987
- safelist: [
2988
- ${safelistArray.map((c) => ` '${c}'`).join(",\n")}
2989
- ],` : "";
2990
- const tailwindConfig = `/** @type {import('tailwindcss').Config} */
2991
- export default {
2992
- content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],${safelistLiteral}
2993
- theme: {
2994
- extend: {},
2995
- },
2996
- plugins: [],
2997
- };
2998
- `;
2999
- await writeFile2(join(outDir, "tailwind.config.mjs"), tailwindConfig, "utf-8");
3000
- await writeFile2(join(outDir, "astro.config.mjs"), astroConfig, "utf-8");
3001
- const tsConfig = {
3002
- extends: "astro/tsconfigs/strict"
3003
- };
3004
- await writeFile2(join(outDir, "tsconfig.json"), JSON.stringify(tsConfig, null, 2), "utf-8");
3005
- console.log("Generated package.json, astro.config.mjs, tailwind.config.mjs, tsconfig.json");
3006
- const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
3007
- const totalPages = allResults.length;
3008
- console.log("\n" + "=".repeat(50));
3009
- console.log("Astro export complete!");
3010
- console.log(` Pages: ${totalPages - cmsPageCount}`);
3011
- if (cmsPageCount > 0) {
3012
- console.log(` CMS pages: ${cmsPageCount}`);
3013
- }
3014
- if (collectionCount > 0) {
3015
- console.log(` Content collections: ${collectionCount}`);
3016
- }
3017
- if (errorCount > 0) {
3018
- console.log(` Errors: ${errorCount}`);
3019
- }
3020
- console.log(` Time: ${elapsed}s`);
3021
- console.log(` Output: ${outDir}`);
3022
- console.log("");
3023
- return {
3024
- pages: totalPages - cmsPageCount,
3025
- cmsPages: cmsPageCount,
3026
- collections: collectionCount,
3027
- errors: errorCount
3028
- };
3029
- }
3030
-
3031
131
  // lib/server/webflow/buildWebflow.ts
3032
- import { existsSync as existsSync2, readdirSync as readdirSync2 } from "fs";
3033
- import { join as join2 } from "path";
132
+ import { existsSync, readdirSync } from "fs";
133
+ import { join } from "path";
3034
134
 
3035
135
  // lib/server/webflow/types.ts
3036
136
  function mapCMSFieldType(menoType) {
@@ -3076,10 +176,10 @@ var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
3076
176
  "font-weight",
3077
177
  "tab-size"
3078
178
  ]);
3079
- function isStyleMapping4(value) {
179
+ function isStyleMapping(value) {
3080
180
  return typeof value === "object" && value !== null && "_mapping" in value && value._mapping === true;
3081
181
  }
3082
- function isResponsiveStyle4(style) {
182
+ function isResponsiveStyle(style) {
3083
183
  return "base" in style || "tablet" in style || "mobile" in style;
3084
184
  }
3085
185
  function toKebabCase(prop) {
@@ -3088,7 +188,7 @@ function toKebabCase(prop) {
3088
188
  function styleObjectToCSS(style) {
3089
189
  const css = {};
3090
190
  for (const [prop, value] of Object.entries(style)) {
3091
- if (isStyleMapping4(value)) continue;
191
+ if (isStyleMapping(value)) continue;
3092
192
  if (value === "" || value === void 0 || value === null) continue;
3093
193
  if (typeof value === "boolean" || typeof value === "object") continue;
3094
194
  const cssProp = toKebabCase(prop);
@@ -3101,21 +201,21 @@ function styleObjectToCSS(style) {
3101
201
  }
3102
202
  return css;
3103
203
  }
3104
- function collectStyleMappings2(style) {
204
+ function collectStyleMappings(style) {
3105
205
  if (!style) return [];
3106
206
  const result = [];
3107
- if (isResponsiveStyle4(style)) {
207
+ if (isResponsiveStyle(style)) {
3108
208
  const base = style.base;
3109
209
  if (base) {
3110
210
  for (const [prop, value] of Object.entries(base)) {
3111
- if (isStyleMapping4(value)) {
211
+ if (isStyleMapping(value)) {
3112
212
  result.push({ property: prop, mapping: value });
3113
213
  }
3114
214
  }
3115
215
  }
3116
216
  } else {
3117
217
  for (const [prop, value] of Object.entries(style)) {
3118
- if (isStyleMapping4(value)) {
218
+ if (isStyleMapping(value)) {
3119
219
  result.push({ property: prop, mapping: value });
3120
220
  }
3121
221
  }
@@ -3137,7 +237,7 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
3137
237
  base: {}
3138
238
  };
3139
239
  if (style) {
3140
- if (isResponsiveStyle4(style)) {
240
+ if (isResponsiveStyle(style)) {
3141
241
  const responsive = style;
3142
242
  if (responsive.base) {
3143
243
  primaryClass.base = styleObjectToCSS(responsive.base);
@@ -3169,7 +269,7 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
3169
269
  if (!pseudoState) continue;
3170
270
  const ruleStyle = rule.style;
3171
271
  if (!primaryClass.pseudoStates) primaryClass.pseudoStates = {};
3172
- if (isResponsiveStyle4(ruleStyle)) {
272
+ if (isResponsiveStyle(ruleStyle)) {
3173
273
  const responsive = ruleStyle;
3174
274
  if (responsive.base) {
3175
275
  primaryClass.pseudoStates[pseudoState] = {
@@ -3186,7 +286,7 @@ function mapStylesToWebflow(className, style, interactiveStyles, breakpoints) {
3186
286
  }
3187
287
  }
3188
288
  const comboClasses = [];
3189
- const mappings = collectStyleMappings2(style);
289
+ const mappings = collectStyleMappings(style);
3190
290
  for (const { property, mapping } of mappings) {
3191
291
  for (const [value, cssValue] of Object.entries(mapping.values)) {
3192
292
  if (cssValue === "" || cssValue === void 0) continue;
@@ -3208,7 +308,7 @@ function sanitizeClassName(name) {
3208
308
  }
3209
309
 
3210
310
  // lib/server/webflow/nodeToWebflow.ts
3211
- function buildElementClass2(ctx, label) {
311
+ function buildElementClass(ctx, label) {
3212
312
  return generateElementClassName({
3213
313
  fileType: ctx.fileType,
3214
314
  fileName: ctx.fileName,
@@ -3216,7 +316,7 @@ function buildElementClass2(ctx, label) {
3216
316
  path: ctx.elementPath
3217
317
  });
3218
318
  }
3219
- function resolveTemplate2(text, props) {
319
+ function resolveTemplate(text, props) {
3220
320
  if (!props) return text;
3221
321
  return text.replace(/\{\{(.+?)\}\}/g, (_, expr) => {
3222
322
  const trimmed = expr.trim();
@@ -3243,13 +343,13 @@ function resolveNestedProp(obj, path) {
3243
343
  }
3244
344
  return current;
3245
345
  }
3246
- function hasTemplates2(text) {
346
+ function hasTemplates(text) {
3247
347
  return /\{\{.+?\}\}/.test(text);
3248
348
  }
3249
349
  function nodeToWebflow(node, ctx, instanceProps) {
3250
350
  if (node === null || node === void 0) return [];
3251
351
  if (typeof node === "string") {
3252
- const text = instanceProps ? resolveTemplate2(node, instanceProps) : node;
352
+ const text = instanceProps ? resolveTemplate(node, instanceProps) : node;
3253
353
  return [{ tag: "span", textContent: text }];
3254
354
  }
3255
355
  if (typeof node === "number") {
@@ -3268,15 +368,15 @@ function nodeToWebflow(node, ctx, instanceProps) {
3268
368
  }
3269
369
  switch (node.type) {
3270
370
  case NODE_TYPE.NODE:
3271
- return [emitHtmlNode2(node, ctx, instanceProps)];
371
+ return [emitHtmlNode(node, ctx, instanceProps)];
3272
372
  case NODE_TYPE.COMPONENT:
3273
- return emitComponentInstance2(node, ctx, instanceProps);
373
+ return emitComponentInstance(node, ctx, instanceProps);
3274
374
  case NODE_TYPE.SLOT:
3275
- return emitSlotMarker2(node, ctx, instanceProps);
375
+ return emitSlotMarker(node, ctx, instanceProps);
3276
376
  case NODE_TYPE.EMBED:
3277
- return [emitEmbedNode2(node, ctx, instanceProps)];
377
+ return [emitEmbedNode(node, ctx, instanceProps)];
3278
378
  case NODE_TYPE.LINK:
3279
- return [emitLinkNode2(node, ctx, instanceProps)];
379
+ return [emitLinkNode(node, ctx, instanceProps)];
3280
380
  case NODE_TYPE.LIST:
3281
381
  case "cms-list":
3282
382
  case NODE_TYPE.LOCALE_LIST:
@@ -3285,15 +385,15 @@ function nodeToWebflow(node, ctx, instanceProps) {
3285
385
  return [];
3286
386
  }
3287
387
  }
3288
- function emitHtmlNode2(node, ctx, instanceProps) {
3289
- const tag = hasTemplates2(node.tag) && instanceProps ? resolveTemplate2(node.tag, instanceProps) : node.tag;
388
+ function emitHtmlNode(node, ctx, instanceProps) {
389
+ const tag = hasTemplates(node.tag) && instanceProps ? resolveTemplate(node.tag, instanceProps) : node.tag;
3290
390
  const style = node.style;
3291
391
  const interactiveStyles = node.interactiveStyles;
3292
392
  const needsClass = style || interactiveStyles && interactiveStyles.length > 0 || node.generateElementClass;
3293
393
  let className;
3294
394
  let comboClassNames;
3295
395
  if (needsClass) {
3296
- const elementClass = buildElementClass2(ctx, node.label);
396
+ const elementClass = buildElementClass(ctx, node.label);
3297
397
  const { primaryClass, comboClasses } = mapStylesToWebflow(
3298
398
  elementClass,
3299
399
  style,
@@ -3313,8 +413,8 @@ function emitHtmlNode2(node, ctx, instanceProps) {
3313
413
  const attributes = {};
3314
414
  if (node.attributes) {
3315
415
  for (const [key, value] of Object.entries(node.attributes)) {
3316
- if (instanceProps && typeof value === "string" && hasTemplates2(value)) {
3317
- attributes[key] = resolveTemplate2(value, instanceProps);
416
+ if (instanceProps && typeof value === "string" && hasTemplates(value)) {
417
+ attributes[key] = resolveTemplate(value, instanceProps);
3318
418
  } else {
3319
419
  attributes[key] = value;
3320
420
  }
@@ -3324,10 +424,10 @@ function emitHtmlNode2(node, ctx, instanceProps) {
3324
424
  let textContent;
3325
425
  if (!isVoidElement(tag) && node.children) {
3326
426
  if (typeof node.children === "string") {
3327
- textContent = instanceProps ? resolveTemplate2(node.children, instanceProps) : node.children;
427
+ textContent = instanceProps ? resolveTemplate(node.children, instanceProps) : node.children;
3328
428
  } else if (Array.isArray(node.children) && node.children.length === 1 && typeof node.children[0] === "string") {
3329
429
  const text = node.children[0];
3330
- textContent = instanceProps ? resolveTemplate2(text, instanceProps) : text;
430
+ textContent = instanceProps ? resolveTemplate(text, instanceProps) : text;
3331
431
  } else {
3332
432
  const innerCtx = { ...ctx, elementPath: [...ctx.elementPath] };
3333
433
  children = convertChildren(node.children, innerCtx, instanceProps);
@@ -3353,7 +453,7 @@ function emitHtmlNode2(node, ctx, instanceProps) {
3353
453
  if (conditional) element.conditional = conditional;
3354
454
  return element;
3355
455
  }
3356
- function emitComponentInstance2(node, ctx, parentProps) {
456
+ function emitComponentInstance(node, ctx, parentProps) {
3357
457
  const compDef = ctx.globalComponents[node.component];
3358
458
  if (!compDef) {
3359
459
  return [{ tag: "div", attributes: { "data-component": node.component } }];
@@ -3368,8 +468,8 @@ function emitComponentInstance2(node, ctx, parentProps) {
3368
468
  if (node.props) {
3369
469
  for (const [key, value] of Object.entries(node.props)) {
3370
470
  if (key === "children") continue;
3371
- if (typeof value === "string" && hasTemplates2(value) && parentProps) {
3372
- resolvedProps[key] = resolveTemplate2(value, parentProps);
471
+ if (typeof value === "string" && hasTemplates(value) && parentProps) {
472
+ resolvedProps[key] = resolveTemplate(value, parentProps);
3373
473
  } else {
3374
474
  resolvedProps[key] = value;
3375
475
  }
@@ -3386,7 +486,7 @@ function emitComponentInstance2(node, ctx, parentProps) {
3386
486
  };
3387
487
  return nodeToWebflow(body, compCtx, resolvedProps);
3388
488
  }
3389
- function emitSlotMarker2(node, ctx, instanceProps) {
489
+ function emitSlotMarker(node, ctx, instanceProps) {
3390
490
  if (ctx.slotChildren) {
3391
491
  const parentCtx = {
3392
492
  ...ctx,
@@ -3400,12 +500,12 @@ function emitSlotMarker2(node, ctx, instanceProps) {
3400
500
  }
3401
501
  return [];
3402
502
  }
3403
- function emitEmbedNode2(node, ctx, instanceProps) {
503
+ function emitEmbedNode(node, ctx, instanceProps) {
3404
504
  const style = node.style;
3405
505
  const interactiveStyles = node.interactiveStyles;
3406
506
  let className;
3407
507
  if (style || interactiveStyles && interactiveStyles.length > 0) {
3408
- const elementClass = buildElementClass2(ctx, node.label);
508
+ const elementClass = buildElementClass(ctx, node.label);
3409
509
  const { primaryClass } = mapStylesToWebflow(
3410
510
  elementClass,
3411
511
  style,
@@ -3423,12 +523,12 @@ function emitEmbedNode2(node, ctx, instanceProps) {
3423
523
  if (className) element.className = className;
3424
524
  return element;
3425
525
  }
3426
- function emitLinkNode2(node, ctx, instanceProps) {
526
+ function emitLinkNode(node, ctx, instanceProps) {
3427
527
  const style = node.style;
3428
528
  const interactiveStyles = node.interactiveStyles;
3429
529
  let className;
3430
530
  if (style || interactiveStyles && interactiveStyles.length > 0) {
3431
- const elementClass = buildElementClass2(ctx, node.label);
531
+ const elementClass = buildElementClass(ctx, node.label);
3432
532
  const { primaryClass } = mapStylesToWebflow(
3433
533
  elementClass,
3434
534
  style,
@@ -3440,7 +540,7 @@ function emitLinkNode2(node, ctx, instanceProps) {
3440
540
  }
3441
541
  let href = "#";
3442
542
  if (typeof node.href === "string") {
3443
- href = instanceProps && hasTemplates2(node.href) ? resolveTemplate2(node.href, instanceProps) : node.href;
543
+ href = instanceProps && hasTemplates(node.href) ? resolveTemplate(node.href, instanceProps) : node.href;
3444
544
  }
3445
545
  const attributes = { href };
3446
546
  if (node.attributes) {
@@ -3470,20 +570,20 @@ function convertChildren(children, ctx, instanceProps) {
3470
570
  }
3471
571
 
3472
572
  // lib/server/webflow/buildWebflow.ts
3473
- function scanJSONFiles2(dir, prefix = "") {
573
+ function scanJSONFiles(dir, prefix = "") {
3474
574
  const results = [];
3475
- if (!existsSync2(dir)) return results;
3476
- const entries = readdirSync2(dir, { withFileTypes: true });
575
+ if (!existsSync(dir)) return results;
576
+ const entries = readdirSync(dir, { withFileTypes: true });
3477
577
  for (const entry of entries) {
3478
578
  if (entry.isFile() && entry.name.endsWith(".json")) {
3479
579
  results.push(prefix ? `${prefix}/${entry.name}` : entry.name);
3480
580
  } else if (entry.isDirectory()) {
3481
- results.push(...scanJSONFiles2(join2(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
581
+ results.push(...scanJSONFiles(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name));
3482
582
  }
3483
583
  }
3484
584
  return results;
3485
585
  }
3486
- function isCMSPage2(pageData) {
586
+ function isCMSPage(pageData) {
3487
587
  return pageData.meta?.source === "cms" && !!pageData.meta?.cms;
3488
588
  }
3489
589
  function buildCMSItemPath(urlPattern, item, slugField, locale, i18nConfig) {
@@ -3502,9 +602,9 @@ function scanAssets(projectRoot) {
3502
602
  { dir: "assets", type: "file" }
3503
603
  ];
3504
604
  for (const { dir, type } of assetDirs) {
3505
- const fullDir = join2(projectRoot, dir);
3506
- if (!existsSync2(fullDir)) continue;
3507
- const files = scanJSONFiles2(fullDir).map((f) => f.replace(".json", ""));
605
+ const fullDir = join(projectRoot, dir);
606
+ if (!existsSync(fullDir)) continue;
607
+ const files = scanJSONFiles(fullDir).map((f) => f.replace(".json", ""));
3508
608
  const allFiles = scanAllFiles(fullDir);
3509
609
  for (const file of allFiles) {
3510
610
  assets.push({
@@ -3518,14 +618,14 @@ function scanAssets(projectRoot) {
3518
618
  }
3519
619
  function scanAllFiles(dir, prefix = "") {
3520
620
  const results = [];
3521
- if (!existsSync2(dir)) return results;
3522
- const entries = readdirSync2(dir, { withFileTypes: true });
621
+ if (!existsSync(dir)) return results;
622
+ const entries = readdirSync(dir, { withFileTypes: true });
3523
623
  for (const entry of entries) {
3524
624
  const relativePath = prefix ? `${prefix}/${entry.name}` : entry.name;
3525
625
  if (entry.isFile()) {
3526
626
  results.push(relativePath);
3527
627
  } else if (entry.isDirectory()) {
3528
- results.push(...scanAllFiles(join2(dir, entry.name), relativePath));
628
+ results.push(...scanAllFiles(join(dir, entry.name), relativePath));
3529
629
  }
3530
630
  }
3531
631
  return results;
@@ -3561,10 +661,10 @@ async function buildWebflowPayload(projectRoot) {
3561
661
  const responsiveScales = await loadResponsiveScalesConfig();
3562
662
  await configService.load();
3563
663
  const pagesDir = projectPaths.pages();
3564
- if (!existsSync2(pagesDir)) {
664
+ if (!existsSync(pagesDir)) {
3565
665
  return emptyPayload();
3566
666
  }
3567
- const pageFiles = scanJSONFiles2(pagesDir);
667
+ const pageFiles = scanJSONFiles(pagesDir);
3568
668
  if (pageFiles.length === 0) {
3569
669
  return emptyPayload();
3570
670
  }
@@ -3572,7 +672,7 @@ async function buildWebflowPayload(projectRoot) {
3572
672
  for (const file of pageFiles) {
3573
673
  const pageName = file.replace(".json", "");
3574
674
  const basePath = mapPageNameToPath(pageName);
3575
- const pageContent = await loadJSONFile(join2(pagesDir, file));
675
+ const pageContent = await loadJSONFile(join(pagesDir, file));
3576
676
  if (!pageContent) continue;
3577
677
  try {
3578
678
  const pageData = parseJSON(pageContent);
@@ -3588,7 +688,7 @@ async function buildWebflowPayload(projectRoot) {
3588
688
  for (const file of pageFiles) {
3589
689
  const pageName = file.replace(".json", "");
3590
690
  const basePath = mapPageNameToPath(pageName);
3591
- const pageContent = await loadJSONFile(join2(pagesDir, file));
691
+ const pageContent = await loadJSONFile(join(pagesDir, file));
3592
692
  if (!pageContent) continue;
3593
693
  try {
3594
694
  const pageData = parseJSON(pageContent);
@@ -3642,15 +742,15 @@ async function buildWebflowPayload(projectRoot) {
3642
742
  }
3643
743
  const templatesDir = projectPaths.templates();
3644
744
  const cmsCollections = [];
3645
- if (existsSync2(templatesDir)) {
3646
- const templateFiles = readdirSync2(templatesDir).filter((f) => f.endsWith(".json"));
745
+ if (existsSync(templatesDir)) {
746
+ const templateFiles = readdirSync(templatesDir).filter((f) => f.endsWith(".json"));
3647
747
  for (const file of templateFiles) {
3648
- const templateContent = await loadJSONFile(join2(templatesDir, file));
748
+ const templateContent = await loadJSONFile(join(templatesDir, file));
3649
749
  if (!templateContent) continue;
3650
750
  try {
3651
751
  const pageData = parseJSON(templateContent);
3652
752
  if (pageData.meta?.draft === true) continue;
3653
- if (!isCMSPage2(pageData)) continue;
753
+ if (!isCMSPage(pageData)) continue;
3654
754
  const cmsSchema = pageData.meta.cms;
3655
755
  const items = await cmsService.queryItems({ collection: cmsSchema.id });
3656
756
  const fields = [];
@@ -3773,7 +873,6 @@ export {
3773
873
  SERVE_PORT,
3774
874
  VariableService,
3775
875
  WebSocketManager,
3776
- buildAstroProject,
3777
876
  buildAttributes,
3778
877
  buildComponentHTML,
3779
878
  buildImageMetadataMap,
@@ -3798,8 +897,12 @@ export {
3798
897
  extractPageMeta,
3799
898
  fileExists,
3800
899
  generateBuildErrorPage,
900
+ generateFontCSS,
901
+ generateFontPreloadTags,
3801
902
  generateMetaTags,
3802
903
  generateSSRHTML,
904
+ generateThemeColorVariablesCSS,
905
+ generateVariablesCSS,
3803
906
  getFileSize,
3804
907
  getJSValidationErrors,
3805
908
  getMimeType,
@@ -3818,13 +921,20 @@ export {
3818
921
  isBun,
3819
922
  jsonResponse,
3820
923
  lineMapToObject,
924
+ loadBreakpointConfig,
925
+ loadComponentDirectory,
926
+ loadI18nConfig,
927
+ loadJSONFile,
3821
928
  loadProjectConfig,
929
+ loadResponsiveScalesConfig,
3822
930
  logError,
3823
931
  logRequest,
3824
932
  logResponseTime,
933
+ mapPageNameToPath,
3825
934
  migrateTemplatesDirectory,
3826
935
  minifyJS,
3827
936
  packagePaths,
937
+ parseJSON,
3828
938
  processCMSPropsTemplate,
3829
939
  processCMSTemplate,
3830
940
  projectPaths,