meno-core 1.0.38 → 1.0.39

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