meno-core 1.0.44 → 1.0.46

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 (79) hide show
  1. package/build-astro.ts +214 -63
  2. package/dist/bin/cli.js +2 -2
  3. package/dist/build-static.js +9 -9
  4. package/dist/chunks/{chunk-BXB6AX76.js → chunk-2QK6U5UK.js} +7 -3
  5. package/dist/chunks/chunk-2QK6U5UK.js.map +7 -0
  6. package/dist/chunks/{chunk-3XXLBUYA.js → chunk-77ZB6353.js} +33 -21
  7. package/dist/chunks/chunk-77ZB6353.js.map +7 -0
  8. package/dist/chunks/{chunk-5TJA272J.js → chunk-C6U5T5S5.js} +9 -9
  9. package/dist/chunks/{chunk-KPNSCQNA.js → chunk-FED5MME6.js} +285 -19
  10. package/dist/chunks/chunk-FED5MME6.js.map +7 -0
  11. package/dist/chunks/{chunk-5Z5VQRTJ.js → chunk-I7YIGZXT.js} +4 -4
  12. package/dist/chunks/{chunk-5Z5VQRTJ.js.map → chunk-I7YIGZXT.js.map} +2 -2
  13. package/dist/chunks/{chunk-46AVQA4V.js → chunk-IF3RATBY.js} +2 -2
  14. package/dist/chunks/{chunk-S2HXJTAF.js → chunk-KITQJYZV.js} +5 -1
  15. package/dist/chunks/chunk-KITQJYZV.js.map +7 -0
  16. package/dist/chunks/{chunk-G3WIPJN3.js → chunk-ORN7S4AP.js} +6 -6
  17. package/dist/chunks/{chunk-2NBGG2LJ.js → chunk-UUA5LEWF.js} +89 -4
  18. package/dist/chunks/{chunk-2NBGG2LJ.js.map → chunk-UUA5LEWF.js.map} +2 -2
  19. package/dist/chunks/{chunk-X5SH4HXS.js → chunk-XSWR3QLI.js} +33 -1
  20. package/dist/chunks/chunk-XSWR3QLI.js.map +7 -0
  21. package/dist/chunks/{chunk-YEJVSNVF.js → chunk-ZTKHJQ2Z.js} +14 -3
  22. package/dist/chunks/chunk-ZTKHJQ2Z.js.map +7 -0
  23. package/dist/chunks/{chunk-OLNQMCSR.js → chunk-ZWYDT3QJ.js} +3 -3
  24. package/dist/chunks/{configService-KYO3TXDS.js → configService-DYCUEURL.js} +4 -4
  25. package/dist/chunks/{constants-34NUGHQR.js → constants-GWBAD66U.js} +2 -2
  26. package/dist/entries/server-router.js +10 -10
  27. package/dist/lib/client/index.js +5 -5
  28. package/dist/lib/server/index.js +589 -145
  29. package/dist/lib/server/index.js.map +3 -3
  30. package/dist/lib/shared/index.js +14 -6
  31. package/dist/lib/shared/index.js.map +2 -2
  32. package/dist/lib/test-utils/index.js +1 -1
  33. package/lib/client/templateEngine.test.ts +64 -0
  34. package/lib/server/astro/astroEmitHelpers.ts +18 -0
  35. package/lib/server/astro/cmsPageEmitter.ts +31 -1
  36. package/lib/server/astro/componentEmitter.test.ts +59 -0
  37. package/lib/server/astro/componentEmitter.ts +43 -10
  38. package/lib/server/astro/cssCollector.ts +58 -11
  39. package/lib/server/astro/nodeToAstro.test.ts +397 -5
  40. package/lib/server/astro/nodeToAstro.ts +478 -63
  41. package/lib/server/astro/pageEmitter.ts +31 -1
  42. package/lib/server/astro/tailwindMapper.test.ts +119 -0
  43. package/lib/server/astro/tailwindMapper.ts +67 -1
  44. package/lib/server/runtime/httpServer.ts +12 -4
  45. package/lib/server/services/configService.ts +13 -0
  46. package/lib/server/ssr/htmlGenerator.ts +5 -2
  47. package/lib/server/ssr/jsCollector.ts +2 -2
  48. package/lib/server/ssr/ssrRenderer.test.ts +32 -0
  49. package/lib/server/ssr/ssrRenderer.ts +26 -11
  50. package/lib/shared/constants.ts +9 -2
  51. package/lib/shared/cssGeneration.test.ts +109 -3
  52. package/lib/shared/cssGeneration.ts +109 -13
  53. package/lib/shared/cssNamedColors.ts +47 -0
  54. package/lib/shared/cssProperties.ts +99 -4
  55. package/lib/shared/index.ts +1 -0
  56. package/lib/shared/nodeUtils.ts +28 -0
  57. package/lib/shared/responsiveScaling.test.ts +20 -3
  58. package/lib/shared/responsiveScaling.ts +55 -1
  59. package/lib/shared/responsiveStyleUtils.test.ts +7 -8
  60. package/lib/shared/responsiveStyleUtils.ts +6 -7
  61. package/lib/shared/types/components.ts +1 -1
  62. package/lib/shared/types/variables.test.ts +9 -2
  63. package/lib/shared/types/variables.ts +5 -1
  64. package/lib/shared/utilityClassMapper.ts +14 -1
  65. package/lib/shared/validation/propValidator.ts +6 -0
  66. package/lib/shared/validation/schemas.ts +2 -2
  67. package/package.json +1 -1
  68. package/dist/chunks/chunk-3XXLBUYA.js.map +0 -7
  69. package/dist/chunks/chunk-BXB6AX76.js.map +0 -7
  70. package/dist/chunks/chunk-KPNSCQNA.js.map +0 -7
  71. package/dist/chunks/chunk-S2HXJTAF.js.map +0 -7
  72. package/dist/chunks/chunk-X5SH4HXS.js.map +0 -7
  73. package/dist/chunks/chunk-YEJVSNVF.js.map +0 -7
  74. /package/dist/chunks/{chunk-5TJA272J.js.map → chunk-C6U5T5S5.js.map} +0 -0
  75. /package/dist/chunks/{chunk-46AVQA4V.js.map → chunk-IF3RATBY.js.map} +0 -0
  76. /package/dist/chunks/{chunk-G3WIPJN3.js.map → chunk-ORN7S4AP.js.map} +0 -0
  77. /package/dist/chunks/{chunk-OLNQMCSR.js.map → chunk-ZWYDT3QJ.js.map} +0 -0
  78. /package/dist/chunks/{configService-KYO3TXDS.js.map → configService-DYCUEURL.js.map} +0 -0
  79. /package/dist/chunks/{constants-34NUGHQR.js.map → constants-GWBAD66U.js.map} +0 -0
package/build-astro.ts CHANGED
@@ -33,7 +33,7 @@ import { generateAllInteractiveCSS } from "./lib/shared/cssGeneration";
33
33
  import { colorService } from "./lib/server/services/ColorService";
34
34
  import { variableService } from "./lib/server/services/VariableService";
35
35
  import { configService } from "./lib/server/services/configService";
36
- import { loadBreakpointConfig, loadResponsiveScalesConfig } from "./lib/server/jsonLoader";
36
+ import { loadBreakpointConfig, loadResponsiveScalesConfig, loadIconsConfig } from "./lib/server/jsonLoader";
37
37
  import type { InteractiveStyles } from "./lib/shared/types/styles";
38
38
  import { collectComponentLibraries, filterLibrariesByContext, mergeLibraries, generateLibraryTags } from "./lib/shared/libraryLoader";
39
39
  import { migrateTemplatesDirectory } from "./lib/server/migrateTemplates";
@@ -41,7 +41,8 @@ import { emitAstroComponent } from "./lib/server/astro/componentEmitter";
41
41
  import { emitAstroPage } from "./lib/server/astro/pageEmitter";
42
42
  import { emitCMSPage } from './lib/server/astro/cmsPageEmitter';
43
43
  import { collectAllMappingClasses } from "./lib/server/astro/cssCollector";
44
- import { buildImageMetadataMap } from "./lib/server/ssr/imageMetadata";
44
+ import { buildImageMetadataMap, RESPONSIVE_WIDTHS } from "./lib/server/ssr/imageMetadata";
45
+ import { needsFormHandler, formHandlerScript } from "./lib/client/scripts/formHandler";
45
46
 
46
47
 
47
48
  // ---------------------------------------------------------------------------
@@ -52,19 +53,50 @@ function hashContent(content: string): string {
52
53
  return createHash('sha256').update(content).digest('hex').slice(0, 8);
53
54
  }
54
55
 
55
- function copyDirectory(src: string, dest: string): void {
56
+ function writePageScript(javascript: string | undefined, scriptsDir: string): string[] {
57
+ if (!javascript) return [];
58
+ const hash = hashContent(javascript);
59
+ const scriptFile = `${hash}.js`;
60
+ if (!existsSync(scriptsDir)) {
61
+ mkdirSync(scriptsDir, { recursive: true });
62
+ }
63
+ const fullScriptPath = join(scriptsDir, scriptFile);
64
+ if (!existsSync(fullScriptPath)) {
65
+ writeFileSync(fullScriptPath, javascript, 'utf-8');
66
+ }
67
+ return [`/_scripts/${scriptFile}`];
68
+ }
69
+
70
+ function copyDirectory(
71
+ src: string,
72
+ dest: string,
73
+ filter?: (filename: string) => boolean,
74
+ ): void {
56
75
  if (!existsSync(src)) return;
57
76
  if (!existsSync(dest)) mkdirSync(dest, { recursive: true });
58
77
  const files = readdirSync(src);
59
78
  for (const file of files) {
79
+ if (filter && !filter(file)) continue;
60
80
  const srcPath = join(src, file);
61
81
  const destPath = join(dest, file);
62
82
  const stat = statSync(srcPath);
63
- if (stat.isDirectory()) copyDirectory(srcPath, destPath);
83
+ if (stat.isDirectory()) copyDirectory(srcPath, destPath, filter);
64
84
  else copyFileSync(srcPath, destPath);
65
85
  }
66
86
  }
67
87
 
88
+ // Astro's <Picture> re-derives responsive variants from originals at build
89
+ // time, so the pre-baked -{width}.webp/.avif files and the SSR-only
90
+ // manifest.json are dead weight in the exported project.
91
+ const imageVariantSuffixRe = new RegExp(
92
+ `-(${RESPONSIVE_WIDTHS.join('|')})\\.(webp|avif)$`,
93
+ );
94
+ function shouldCopyImageForAstro(filename: string): boolean {
95
+ if (filename === 'manifest.json') return false;
96
+ if (imageVariantSuffixRe.test(filename)) return false;
97
+ return true;
98
+ }
99
+
68
100
  function isCMSPage(pageData: JSONPage): boolean {
69
101
  return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;
70
102
  }
@@ -208,6 +240,8 @@ interface PageRenderResult {
208
240
  isCMSPage?: boolean;
209
241
  /** SSR fallback HTML for complex nodes (list, locale-list) keyed by element path */
210
242
  ssrFallbackCollector?: Map<string, string>;
243
+ /** Raw-HTML slice → processed HTML captured during SSR (for Astro exporter parity) */
244
+ processedRawHtmlCollector?: Map<string, string>;
211
245
  }
212
246
 
213
247
  interface AstroBuildStats {
@@ -372,6 +406,7 @@ export async function buildAstroProject(
372
406
  const allComponentCSS = new Set<string>();
373
407
  const jsContents = new Map<string, string>(); // hash -> JS content
374
408
  let errorCount = 0;
409
+ let projectNeedsFormHandler = false;
375
410
 
376
411
  // Helper to merge interactive styles maps
377
412
  function mergeInteractiveStyles(source: Map<string, InteractiveStyles>): void {
@@ -384,7 +419,7 @@ export async function buildAstroProject(
384
419
 
385
420
  // Helper to process a render result
386
421
  function processRenderResult(
387
- result: { html: string; meta: string; title: string; javascript: string; componentCSS?: string; locale: string; interactiveStylesMap: Map<string, InteractiveStyles>; preloadImages: any[]; neededCollections: Set<string>; ssrFallbackCollector?: Map<string, string> },
422
+ result: { html: string; meta: string; title: string; javascript: string; componentCSS?: string; locale: string; interactiveStylesMap: Map<string, InteractiveStyles>; preloadImages: any[]; neededCollections: Set<string>; ssrFallbackCollector?: Map<string, string>; processedRawHtmlCollector?: Map<string, string> },
388
423
  urlPath: string,
389
424
  astroFilePath: string,
390
425
  fileDepth: number,
@@ -408,6 +443,11 @@ export async function buildAstroProject(
408
443
  }
409
444
  }
410
445
 
446
+ // Detect forms that need the fetch handler
447
+ if (!projectNeedsFormHandler && needsFormHandler(result.html)) {
448
+ projectNeedsFormHandler = true;
449
+ }
450
+
411
451
  allResults.push({
412
452
  html: result.html,
413
453
  meta: result.meta,
@@ -423,6 +463,7 @@ export async function buildAstroProject(
423
463
  pageName,
424
464
  isCMSPage,
425
465
  ssrFallbackCollector: result.ssrFallbackCollector,
466
+ processedRawHtmlCollector: result.processedRawHtmlCollector,
426
467
  });
427
468
  }
428
469
 
@@ -499,9 +540,54 @@ export async function buildAstroProject(
499
540
  const fontPreloads = generateFontPreloadTags();
500
541
  const mergedLibraries = mergeLibraries(globalLibraries, componentLibraries);
501
542
  const buildLibraries = filterLibrariesByContext(mergedLibraries, 'build');
502
- const libraryTags = generateLibraryTags(buildLibraries);
543
+
544
+ // Mirror htmlGenerator.ts: local CSS libraries with `inline !== false` are inlined
545
+ // into a <style> tag, otherwise the file is copied to public/ so the <link href>
546
+ // resolves. This keeps any `/some-file.css` referenced in project.config.json
547
+ // libraries working, not just the special `custom.css` case.
548
+ const inlineContents = new Map<string, string>();
549
+ const localLibsToCopy: string[] = [];
550
+ for (const css of buildLibraries.css || []) {
551
+ if (!css.url.startsWith('/')) continue;
552
+ const shouldInline = css.inline !== false;
553
+ const relPath = css.url.slice(1);
554
+ const srcPath = join(projectPaths.project, relPath);
555
+ if (!existsSync(srcPath)) continue;
556
+ if (shouldInline) {
557
+ try {
558
+ inlineContents.set(css.url, await readFile(srcPath, 'utf-8'));
559
+ } catch {
560
+ localLibsToCopy.push(relPath);
561
+ }
562
+ } else {
563
+ localLibsToCopy.push(relPath);
564
+ }
565
+ }
566
+ for (const js of buildLibraries.js || []) {
567
+ if (js.url.startsWith('/')) {
568
+ const relPath = js.url.slice(1);
569
+ if (existsSync(join(projectPaths.project, relPath))) {
570
+ localLibsToCopy.push(relPath);
571
+ }
572
+ }
573
+ }
574
+ const libraryTags = generateLibraryTags(buildLibraries, inlineContents);
503
575
  const defaultTheme = themeConfig.default || 'light';
504
576
 
577
+ // Global customCode (head/bodyStart/bodyEnd) and icons from project.config.json
578
+ // are page-independent, so we bake them directly into BaseLayout.astro rather
579
+ // than plumbing them through every page's props. Mirrors htmlGenerator.ts's
580
+ // SSR output (htmlGenerator.ts:269-507 for customCode, 368-473 for icons).
581
+ const customCode = configService.getCustomCode();
582
+ const iconsConfig = await loadIconsConfig();
583
+ const faviconTag = iconsConfig.favicon
584
+ ? `<link rel="icon" href="${iconsConfig.favicon.replace(/"/g, '&quot;')}" />`
585
+ : '';
586
+ const appleTouchIconTag = iconsConfig.appleTouchIcon
587
+ ? `<link rel="apple-touch-icon" href="${iconsConfig.appleTouchIcon.replace(/"/g, '&quot;')}" />`
588
+ : '';
589
+ const iconTagsHtml = [faviconTag, appleTouchIconTag].filter(Boolean).join('\n ');
590
+
505
591
  // ---------- CMS template pages ----------
506
592
  const templatesDir = projectPaths.templates();
507
593
  const templateSchemas: CMSSchema[] = [];
@@ -626,11 +712,13 @@ export async function buildAstroProject(
626
712
  ssrFallbacks,
627
713
  pageName: file.replace('.json', ''),
628
714
  breakpoints,
715
+ responsiveScales,
629
716
  imageMetadataMap,
630
717
  i18nConfig,
631
718
  isMultiLocale: false, // Each file handles one locale
632
719
  slugMappings,
633
720
  imageFormat: configService.getImageFormat(),
721
+ processedRawHtml: metaResult.processedRawHtmlCollector,
634
722
  });
635
723
 
636
724
  const astroFileFull = join(pagesOutDir, astroFilePath);
@@ -656,13 +744,13 @@ export async function buildAstroProject(
656
744
  // 6. Generate global CSS (Tailwind + theme + interactive styles)
657
745
  // ----------------------------------------------------------
658
746
  // Collect Tailwind safelist classes from mapping variants
659
- const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints);
747
+ const mappingClasses = collectAllMappingClasses(globalComponents, breakpoints, responsiveScales);
660
748
 
661
749
  const fontCSS = generateFontCSS();
662
750
  const themeColorCSS = generateThemeColorVariablesCSS(themeConfig);
663
751
  const variablesCSS = generateVariablesCSS(variablesConfig, breakpoints, responsiveScales);
664
752
  const remConversionConfig = configService.getRemConversion();
665
- const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints, remConversionConfig);
753
+ const interactiveCSS = generateAllInteractiveCSS(allInteractiveStyles, breakpoints, remConversionConfig, responsiveScales);
666
754
  const componentCSSCombined = Array.from(allComponentCSS).join('\n');
667
755
 
668
756
  const baseCSS = `@layer base {
@@ -675,9 +763,13 @@ export async function buildAstroProject(
675
763
  .oem { display: inline-block; }
676
764
  }`;
677
765
 
678
- const tailwindDirectives = `@tailwind base;
679
- @tailwind components;
680
- @tailwind utilities;`;
766
+ const safelistClasses = Array.from(mappingClasses);
767
+ const safelistDirectives = safelistClasses
768
+ .map(c => `@source inline("${c}");`)
769
+ .join('\n');
770
+ const tailwindDirectives = safelistDirectives
771
+ ? `@import "tailwindcss";\n\n${safelistDirectives}`
772
+ : `@import "tailwindcss";`;
681
773
 
682
774
  const globalCSS = [tailwindDirectives, fontCSS, themeColorCSS, variablesCSS, baseCSS, componentCSSCombined, interactiveCSS]
683
775
  .filter(Boolean)
@@ -689,6 +781,22 @@ export async function buildAstroProject(
689
781
  // ----------------------------------------------------------
690
782
  // 7. Generate BaseLayout.astro
691
783
  // ----------------------------------------------------------
784
+ // Escape for embedding inside Astro <Fragment set:html={`...`}> template
785
+ // literals in the generated BaseLayout file.
786
+ const escForTemplateLiteral = (s: string) => s
787
+ .replace(/\\/g, '\\\\')
788
+ .replace(/`/g, '\\`')
789
+ .replace(/\$\{/g, '\\${');
790
+
791
+ const customHeadLiteral = escForTemplateLiteral(customCode.head || '');
792
+ const customBodyStartLiteral = escForTemplateLiteral(customCode.bodyStart || '');
793
+ const customBodyEndLiteral = escForTemplateLiteral(customCode.bodyEnd || '');
794
+ const iconTagsLiteral = escForTemplateLiteral(iconTagsHtml);
795
+
796
+ const formHandlerBlock = projectNeedsFormHandler
797
+ ? `\n <script is:inline>\n${formHandlerScript}\n </script>`
798
+ : '';
799
+
692
800
  const baseLayoutContent = `---
693
801
  import '../styles/global.css';
694
802
 
@@ -709,16 +817,20 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
709
817
  <head>
710
818
  <meta charset="UTF-8">
711
819
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
820
+ <Fragment set:html={\`${iconTagsLiteral}\`} />
712
821
  <Fragment set:html={fontPreloads} />
713
822
  <Fragment set:html={libraryTags.headCSS || ''} />
714
823
  <Fragment set:html={libraryTags.headJS || ''} />
715
824
  <Fragment set:html={meta} />
825
+ <Fragment set:html={\`${customHeadLiteral}\`} />
716
826
  <title>{title}</title>
717
827
  </head>
718
828
  <body>
829
+ <Fragment set:html={\`${customBodyStartLiteral}\`} />
719
830
  <slot />
720
831
  {scripts.map((s) => <script src={s} />)}
721
832
  <Fragment set:html={libraryTags.bodyEndJS || ''} />
833
+ <Fragment set:html={\`${customBodyEndLiteral}\`} />${formHandlerBlock}
722
834
  </body>
723
835
  </html>
724
836
  `;
@@ -732,7 +844,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
732
844
  let componentFileCount = 0;
733
845
  for (const [compName, compDef] of Object.entries(globalComponents)) {
734
846
  try {
735
- const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale);
847
+ const astroContent = emitAstroComponent(compName, compDef, globalComponents, breakpoints, i18nConfig.defaultLocale, responsiveScales);
736
848
  await writeFile(join(componentsOutDir, `${compName}.astro`), astroContent, 'utf-8');
737
849
  componentFileCount++;
738
850
  } catch (error: any) {
@@ -747,23 +859,8 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
747
859
  for (const result of allResults) {
748
860
  const importPath = layoutImportPath(result.fileDepth);
749
861
 
750
- // Write JavaScript to public/_scripts/ if present
751
- const scriptPaths: string[] = [];
752
- if (result.javascript) {
753
- const hash = hashContent(result.javascript);
754
- const scriptFile = `${hash}.js`;
755
- const scriptPublicPath = `/_scripts/${scriptFile}`;
756
-
757
- if (!existsSync(scriptsDir)) {
758
- mkdirSync(scriptsDir, { recursive: true });
759
- }
760
-
761
- const fullScriptPath = join(scriptsDir, scriptFile);
762
- if (!existsSync(fullScriptPath)) {
763
- await writeFile(fullScriptPath, result.javascript, 'utf-8');
764
- }
765
- scriptPaths.push(scriptPublicPath);
766
- }
862
+ // Write JavaScript to public/_scripts/ if present (only needed for SSR fallback pages)
863
+ let scriptPaths: string[] = [];
767
864
 
768
865
  let astroContent: string;
769
866
 
@@ -779,6 +876,8 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
779
876
  ? computePageSlugMap(result.pageData.meta.slugs, i18nConfig)
780
877
  : undefined;
781
878
 
879
+ // Component-structured pages don't need page-level _scripts/*.js
880
+ // because each .astro component already has its own inline <script>
782
881
  astroContent = emitAstroPage({
783
882
  pageData: result.pageData,
784
883
  globalComponents,
@@ -788,25 +887,29 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
788
887
  theme: defaultTheme,
789
888
  fontPreloads,
790
889
  libraryTags,
791
- scriptPaths,
890
+ scriptPaths: [],
792
891
  layoutImportPath: importPath,
793
892
  fileDepth: result.fileDepth,
794
893
  ssrFallbacks,
795
894
  pageName: result.pageName || 'index',
796
895
  breakpoints,
896
+ responsiveScales,
797
897
  imageMetadataMap,
798
898
  i18nConfig: i18nConfig.locales.length > 1 ? i18nConfig : undefined,
799
899
  currentPageSlugMap: pageSlugMap,
800
900
  slugMappings: i18nConfig.locales.length > 1 ? slugMappings : undefined,
801
901
  imageFormat: configService.getImageFormat(),
902
+ processedRawHtml: result.processedRawHtmlCollector,
802
903
  });
803
904
  } catch (error: any) {
804
- // Fallback to SSR HTML if component emission fails
905
+ // Fallback to SSR HTML if component emission fails — needs page-level script
805
906
  console.warn(` Warning: component emission failed for ${result.urlPath}, using SSR fallback: ${error?.message}`);
907
+ scriptPaths = writePageScript(result.javascript, scriptsDir);
806
908
  astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
807
909
  }
808
910
  } else {
809
- // Pages without pageData: use SSR fallback
911
+ // Pages without pageData: use SSR fallback — needs page-level script
912
+ scriptPaths = writePageScript(result.javascript, scriptsDir);
810
913
  astroContent = buildSSRFallbackPage(result, importPath, fontPreloads, libraryTags, defaultTheme, scriptPaths);
811
914
  }
812
915
 
@@ -821,6 +924,28 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
821
924
 
822
925
  console.log(`Generated ${allResults.length} .astro page file(s)`);
823
926
 
927
+ // ----------------------------------------------------------
928
+ // 8.5. Generate robots.txt endpoint
929
+ // ----------------------------------------------------------
930
+ const robotsTsContent = `import type { APIRoute } from 'astro';
931
+
932
+ export const GET: APIRoute = () => {
933
+ const siteUrl = import.meta.env.SITE;
934
+ const robotsTxt = [
935
+ 'User-agent: *',
936
+ 'Allow: /',
937
+ '',
938
+ siteUrl ? \`Sitemap: \${siteUrl}/sitemap-index.xml\` : '',
939
+ ].filter(Boolean).join('\\n');
940
+
941
+ return new Response(robotsTxt, {
942
+ headers: { 'Content-Type': 'text/plain; charset=utf-8' },
943
+ });
944
+ };
945
+ `;
946
+ await writeFile(join(pagesOutDir, 'robots.txt.ts'), robotsTsContent, 'utf-8');
947
+ console.log('Generated robots.txt.ts endpoint');
948
+
824
949
  // ----------------------------------------------------------
825
950
  // 9. Generate CMS content collections (if templates exist)
826
951
  // ----------------------------------------------------------
@@ -871,7 +996,7 @@ const { title, meta = '', scripts = [], locale = 'en', theme = '${themeConfig.de
871
996
  }
872
997
 
873
998
  collectionDefs.push(` '${schema.id}': defineCollection({
874
- type: 'data',
999
+ loader: glob({ pattern: '**/*.json', base: './src/content/${schema.id}' }),
875
1000
  schema: z.object({
876
1001
  ${fieldDefs.join(',\n')}
877
1002
  })
@@ -880,8 +1005,9 @@ ${fieldDefs.join(',\n')}
880
1005
  collectionCount++;
881
1006
  }
882
1007
 
883
- // Write src/content/config.ts
1008
+ // Write src/content.config.ts (Astro 6 location — legacy src/content/config.ts is rejected)
884
1009
  const configContent = `import { z, defineCollection } from 'astro:content';
1010
+ import { glob } from 'astro/loaders';
885
1011
 
886
1012
  const collections = {
887
1013
  ${collectionDefs.join(',\n')}
@@ -890,17 +1016,35 @@ ${collectionDefs.join(',\n')}
890
1016
  export { collections };
891
1017
  `;
892
1018
 
893
- await writeFile(join(contentDir, 'config.ts'), configContent, 'utf-8');
894
- console.log(`Generated ${collectionCount} content collection(s) with config.ts`);
1019
+ await writeFile(join(srcDir, 'content.config.ts'), configContent, 'utf-8');
1020
+ console.log(`Generated ${collectionCount} content collection(s) with content.config.ts`);
895
1021
  }
896
1022
 
897
1023
  // ----------------------------------------------------------
898
- // 10. Copy assets to public/
1024
+ // 10. Copy assets
899
1025
  // ----------------------------------------------------------
900
- const assetDirs = ['fonts', 'images', 'icons', 'videos', 'assets'];
1026
+ // Images go to src/assets/images so Astro's asset pipeline can process
1027
+ // them via astro:assets `<Picture>` (hashing, on-edit reprocessing).
1028
+ // Everything else stays in public/ — fonts/icons/videos need stable URLs.
901
1029
  let copiedAssets = 0;
902
1030
 
903
- for (const dir of assetDirs) {
1031
+ const imagesSrcDir = join(projectPaths.project, 'images');
1032
+ if (existsSync(imagesSrcDir)) {
1033
+ // src/assets/images: used by static <Picture> via ESM imports + Vite asset
1034
+ // pipeline. Pre-baked responsive variants and manifest.json are excluded —
1035
+ // Astro regenerates those from the originals.
1036
+ copyDirectory(imagesSrcDir, join(srcDir, 'assets', 'images'), shouldCopyImageForAstro);
1037
+ // public/images: used by the legacy <img>/<picture> srcset path and
1038
+ // rich-text image rewrites, which emit plain `/images/...` URLs pointing at
1039
+ // the pre-built variants. Without this mirror, any image not routed through
1040
+ // the static Picture path (variants referenced directly in a srcset,
1041
+ // CMS/template-bound images, component-prop images) 404s in `astro dev`.
1042
+ copyDirectory(imagesSrcDir, join(publicDir, 'images'));
1043
+ copiedAssets++;
1044
+ }
1045
+
1046
+ const publicAssetDirs = ['fonts', 'icons', 'videos', 'assets'];
1047
+ for (const dir of publicAssetDirs) {
904
1048
  const srcAssetDir = join(projectPaths.project, dir);
905
1049
  if (existsSync(srcAssetDir)) {
906
1050
  copyDirectory(srcAssetDir, join(publicDir, dir));
@@ -915,6 +1059,18 @@ export { collections };
915
1059
  copiedAssets++;
916
1060
  }
917
1061
 
1062
+ // Copy any project-root library files referenced by absolute URL in
1063
+ // project.config.json (e.g. `/custom.css`). Only copies entries we already
1064
+ // validated exist on disk during library tag generation above.
1065
+ for (const relPath of localLibsToCopy) {
1066
+ const srcPath = join(projectPaths.project, relPath);
1067
+ const destPath = join(publicDir, relPath);
1068
+ const destDir = destPath.substring(0, destPath.lastIndexOf('/'));
1069
+ if (destDir && !existsSync(destDir)) mkdirSync(destDir, { recursive: true });
1070
+ copyFileSync(srcPath, destPath);
1071
+ copiedAssets++;
1072
+ }
1073
+
918
1074
  if (copiedAssets > 0) {
919
1075
  console.log(`Copied ${copiedAssets} asset director${copiedAssets === 1 ? 'y' : 'ies'} to public/`);
920
1076
  }
@@ -936,9 +1092,14 @@ export { collections };
936
1092
  preview: 'astro preview',
937
1093
  },
938
1094
  dependencies: {
939
- 'astro': '^4.0.0',
940
- '@astrojs/tailwind': '^5.0.0',
941
- 'tailwindcss': '^3.4.0',
1095
+ 'astro': '^6.0.0',
1096
+ '@astrojs/sitemap': '^3.0.0',
1097
+ '@tailwindcss/vite': '^4.0.0',
1098
+ 'tailwindcss': '^4.0.0',
1099
+ },
1100
+ // Astro 6 expects Vite 7; pin it so npm doesn't pull Vite 8+ and warn.
1101
+ overrides: {
1102
+ 'vite': '^7.0.0',
942
1103
  },
943
1104
  };
944
1105
 
@@ -951,31 +1112,17 @@ export { collections };
951
1112
  : '';
952
1113
 
953
1114
  const astroConfig = `import { defineConfig } from 'astro/config';
954
- import tailwind from '@astrojs/tailwind';
1115
+ import tailwindcss from '@tailwindcss/vite';
1116
+ import sitemap from '@astrojs/sitemap';
955
1117
 
956
1118
  export default defineConfig({${siteUrl ? `\n site: '${siteUrl}',` : ''}${i18nBlock}
957
- integrations: [tailwind({ applyBaseStyles: false })],
958
- });
959
- `;
960
-
961
- // tailwind.config.mjs
962
- const safelistArray = Array.from(mappingClasses);
963
- const safelistLiteral = safelistArray.length > 0
964
- ? `\n safelist: [\n${safelistArray.map(c => ` '${c}'`).join(',\n')}\n ],`
965
- : '';
966
-
967
- const tailwindConfig = `/** @type {import('tailwindcss').Config} */
968
- export default {
969
- content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],${safelistLiteral}
970
- theme: {
971
- extend: {},
1119
+ integrations: [sitemap()],
1120
+ vite: {
1121
+ plugins: [tailwindcss()],
972
1122
  },
973
- plugins: [],
974
- };
1123
+ });
975
1124
  `;
976
1125
 
977
- await writeFile(join(outDir, 'tailwind.config.mjs'), tailwindConfig, 'utf-8');
978
-
979
1126
  await writeFile(join(outDir, 'astro.config.mjs'), astroConfig, 'utf-8');
980
1127
 
981
1128
  // tsconfig.json
@@ -985,7 +1132,7 @@ export default {
985
1132
 
986
1133
  await writeFile(join(outDir, 'tsconfig.json'), JSON.stringify(tsConfig, null, 2), 'utf-8');
987
1134
 
988
- console.log('Generated package.json, astro.config.mjs, tailwind.config.mjs, tsconfig.json');
1135
+ console.log('Generated package.json, astro.config.mjs, tsconfig.json');
989
1136
 
990
1137
  // ----------------------------------------------------------
991
1138
  // 12. Summary
@@ -1005,6 +1152,10 @@ export default {
1005
1152
  if (errorCount > 0) {
1006
1153
  console.log(` Errors: ${errorCount}`);
1007
1154
  }
1155
+ console.log(` SEO: sitemap (@astrojs/sitemap), robots.txt`);
1156
+ if (projectNeedsFormHandler) {
1157
+ console.log(` Forms: fetch handler injected`);
1158
+ }
1008
1159
  console.log(` Time: ${elapsed}s`);
1009
1160
  console.log(` Output: ${outDir}`);
1010
1161
  console.log('');
package/dist/bin/cli.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  createRuntimeServer,
7
7
  setProjectRoot
8
- } from "../chunks/chunk-5Z5VQRTJ.js";
8
+ } from "../chunks/chunk-I7YIGZXT.js";
9
9
  import {
10
10
  fileExists,
11
11
  serveFile
@@ -82,7 +82,7 @@ function getMatchingHeaders(pathname, headersMap) {
82
82
  return result;
83
83
  }
84
84
  async function startStaticServer(distPath) {
85
- const { SERVE_PORT } = await import("../chunks/constants-34NUGHQR.js");
85
+ const { SERVE_PORT } = await import("../chunks/constants-GWBAD66U.js");
86
86
  const headersMap = parseHeadersFile(distPath);
87
87
  const server = await createRuntimeServer({
88
88
  port: SERVE_PORT,
@@ -9,17 +9,17 @@ import {
9
9
  hashContent,
10
10
  injectTrackingScript,
11
11
  isCMSPage
12
- } from "./chunks/chunk-G3WIPJN3.js";
13
- import "./chunks/chunk-3XXLBUYA.js";
14
- import "./chunks/chunk-YEJVSNVF.js";
15
- import "./chunks/chunk-5Z5VQRTJ.js";
12
+ } from "./chunks/chunk-ORN7S4AP.js";
13
+ import "./chunks/chunk-77ZB6353.js";
14
+ import "./chunks/chunk-ZTKHJQ2Z.js";
15
+ import "./chunks/chunk-I7YIGZXT.js";
16
16
  import "./chunks/chunk-WQFG7PAH.js";
17
- import "./chunks/chunk-S2HXJTAF.js";
18
- import "./chunks/chunk-OLNQMCSR.js";
19
- import "./chunks/chunk-KPNSCQNA.js";
20
- import "./chunks/chunk-X5SH4HXS.js";
17
+ import "./chunks/chunk-KITQJYZV.js";
18
+ import "./chunks/chunk-ZWYDT3QJ.js";
19
+ import "./chunks/chunk-FED5MME6.js";
20
+ import "./chunks/chunk-XSWR3QLI.js";
21
21
  import "./chunks/chunk-UB44F4Z2.js";
22
- import "./chunks/chunk-BXB6AX76.js";
22
+ import "./chunks/chunk-2QK6U5UK.js";
23
23
  import "./chunks/chunk-KSBZ2L7C.js";
24
24
  export {
25
25
  buildCMSItemPath,
@@ -7,7 +7,7 @@ var SERVER_PORT, SERVE_PORT, API_ROUTES, HMR_ROUTE, FILE_PATTERNS, DEFAULT_TIMEO
7
7
  var init_constants = __esm({
8
8
  "lib/shared/constants.ts"() {
9
9
  SERVER_PORT = typeof process !== "undefined" && process.env?.PORT ? parseInt(process.env.PORT, 10) : 3e3;
10
- SERVE_PORT = 8080;
10
+ SERVE_PORT = typeof process !== "undefined" && process.env?.MENO_SERVE_PORT ? parseInt(process.env.MENO_SERVE_PORT, 10) : 8080;
11
11
  API_ROUTES = {
12
12
  PAGES: "/api/pages",
13
13
  COMPONENTS: "/api/components",
@@ -138,6 +138,7 @@ var init_constants = __esm({
138
138
  SET_TAB: "SET_TAB",
139
139
  COPY_ELEMENT: "COPY_ELEMENT",
140
140
  PASTE_ELEMENT: "PASTE_ELEMENT",
141
+ PASTE_ELEMENT_AFTER: "PASTE_ELEMENT_AFTER",
141
142
  ARROW_UP: "ARROW_UP",
142
143
  ARROW_DOWN: "ARROW_DOWN",
143
144
  ARROW_LEFT: "ARROW_LEFT",
@@ -170,7 +171,10 @@ var init_constants = __esm({
170
171
  // Editor → Iframe for component definition updates
171
172
  CSS_VARIABLE_UPDATE: "CSS_VARIABLE_UPDATE",
172
173
  // Editor → Iframe for instant CSS variable preview
173
- DUPLICATE_ELEMENT: "DUPLICATE_ELEMENT"
174
+ DUPLICATE_ELEMENT: "DUPLICATE_ELEMENT",
175
+ MAKE_COMPONENT: "MAKE_COMPONENT",
176
+ SWAP_TO_COMPONENT: "SWAP_TO_COMPONENT",
177
+ SMART_CONNECT: "SMART_CONNECT"
174
178
  };
175
179
  NODE_TYPE = {
176
180
  NODE: "node",
@@ -221,4 +225,4 @@ export {
221
225
  RAW_HTML_PREFIX,
222
226
  init_constants
223
227
  };
224
- //# sourceMappingURL=chunk-BXB6AX76.js.map
228
+ //# sourceMappingURL=chunk-2QK6U5UK.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../lib/shared/constants.ts"],
4
+ "sourcesContent": ["/**\n * Shared constants used across the application\n */\n\n// Read PORT from environment variable, fallback to 3000\n// Safe for browser environments where process is not defined\nexport const SERVER_PORT = typeof process !== 'undefined' && process.env?.PORT\n ? parseInt(process.env.PORT, 10)\n : 3000;\n\n// Port for serving built static files (SSR preview)\n// Reads MENO_SERVE_PORT env var so each project instance can get its own port\nexport const SERVE_PORT = typeof process !== 'undefined' && process.env?.MENO_SERVE_PORT\n ? parseInt(process.env.MENO_SERVE_PORT, 10)\n : 8080;\n\nexport const API_ROUTES = {\n PAGES: '/api/pages',\n COMPONENTS: '/api/components',\n PAGE_CONTENT: '/api/page-content', // Returns raw JSON text for a page\n PAGE_DATA: '/api/page-data', // Returns parsed JSON for a specific page\n COMPONENT_DATA: '/api/component-data', // Returns parsed JSON for a specific component\n SAVE_PAGE: '/api/save-page',\n SAVE_COMPONENT: '/api/save-component',\n SAVE_COMPONENT_JS: '/api/save-component-js', // Save JavaScript to .js file\n SAVE_COMPONENT_CSS: '/api/save-component-css', // Save CSS to .css file\n COMPONENT_CATEGORY: '/api/component-category', // Move component to category folder\n COMPONENT_FOLDER: '/api/component-folder', // Create component folder\n COMPONENT_FOLDERS: '/api/component-folders', // List all component folders\n COMPONENT_JS: '/api/component-js', // Get JavaScript from .js file\n CONFIG: '/api/config', // Get project config\n SAVE_CONFIG: '/api/save-config', // Save project config\n COMPONENTS_CONFIG: '/api/components-config', // Get components config\n SAVE_COMPONENTS_CONFIG: '/api/save-components-config', // Save components config\n SELECTION: '/api/selection', // Editor selection state (for AI integration)\n // CMS API routes\n CMS_COLLECTIONS: '/api/cms/collections', // List all CMS collections\n CMS_BASE: '/api/cms', // Base path for CMS item operations\n // Colors API routes\n COLORS_CONFIG: '/api/colors-config', // Get full colors config\n SAVE_COLORS: '/api/save-colors', // Save colors config\n // Page deletion\n DELETE_PAGE: '/api/delete-page', // Delete a page\n // Page folder management\n PAGE_FOLDER: '/api/page-folder', // Create page folder\n PAGE_FOLDERS: '/api/page-folders', // List all page folders\n MOVE_PAGE: '/api/move-page', // Move page to folder\n // Component preview\n COMPONENT_PREVIEW: '/api/component-preview', // Render component preview HTML\n // Website import\n IMPORT_WEBSITE: '/api/import-website', // Import external website for reference\n IMPORTED_WEBSITES: '/api/imported-websites', // List imported website folders\n ANALYZE_WEBSITE: '/api/analyze-website', // Analyze imported website into section map\n CONVERT_TO_MENO: '/api/convert-to-meno', // Convert imported HTML to flat Meno page JSON\n EXTRACT_CONTENT: '/api/extract-content', // Extract content from imported website for template mapping\n GENERATE_WIREFRAME_PROMPT: '/api/generate-wireframe-prompt', // Generate wireframe conversion prompt from extraction\n GENERATE_DESIGN_TOKEN_PROMPT: '/api/generate-design-token-prompt', // Generate design token extraction prompt\n GENERATE_CONTENT_PROMPT: '/api/generate-content-prompt', // Generate content conversion prompt using existing components\n GENERATE_SIMPLIFIED_PROMPT: '/api/generate-simplified-prompt', // Generate simplified prompt for Claude Code with Chrome extension\n // Multi-page import routes\n FETCH_SITEMAP: '/api/fetch-sitemap', // Fetch & parse sitemap.xml\n IMPORT_PAGE: '/api/import-page', // Import a single subpage\n ANALYZE_PAGE: '/api/analyze-page', // Analyze a subpage\n EXTRACT_PAGE_CONTENT: '/api/extract-page-content', // Extract content from a subpage\n GENERATE_HOMEPAGE_PROMPT: '/api/generate-homepage-prompt', // Homepage prompt with site structure\n GENERATE_PAGE_PROMPT: '/api/generate-page-prompt', // Per-page/template prompt\n LOAD_WEBSITE_IMPORT: '/api/load-website-import', // Load saved website import data from disk\n // Variables API routes\n VARIABLES_STATUS: '/api/variables-status', // Get variables config with status\n VARIABLES_CSS: '/api/variables-css', // Get generated CSS custom properties\n SAVE_VARIABLES: '/api/save-variables', // Save variables config\n // Enums API routes\n ENUMS: '/api/enums', // Get enums config\n SAVE_ENUMS: '/api/save-enums', // Save enums config\n // Component usage\n COMPONENT_USAGE: '/api/component-usage', // Get component usage across project\n} as const;\n\nexport const HMR_ROUTE = '/hmr';\n\nexport const FILE_PATTERNS = {\n PAGES: './pages',\n COMPONENTS: './components',\n} as const;\n\nexport const DEFAULT_TIMEOUT = 5000;\n\nexport const WEBSOCKET_STATES = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n} as const;\n\n// Timeout constants\nexport const NOT_FOUND_TIMEOUT_MS = 300;\nexport const TAB_SWITCH_DELAY_MS = 100;\nexport const IFRAME_HIGHLIGHT_DELAY_MS = 100;\nexport const TREE_SCROLL_DELAY_MS = 200;\nexport const HOVER_HIGHLIGHT_DELAY_MS = 50; // Delay before highlighting tree item after expansion\n\n// Server configuration\nexport const MAX_PORT_ATTEMPTS = 10;\n\n// Message types for iframe-parent communication\nexport const IFRAME_MESSAGE_TYPES = {\n DELETE_ELEMENT: 'DELETE_ELEMENT',\n TOGGLE_SELECTING_MODE: 'TOGGLE_SELECTING_MODE',\n SET_TAB: 'SET_TAB',\n COPY_ELEMENT: 'COPY_ELEMENT',\n PASTE_ELEMENT: 'PASTE_ELEMENT',\n PASTE_ELEMENT_AFTER: 'PASTE_ELEMENT_AFTER',\n ARROW_UP: 'ARROW_UP',\n ARROW_DOWN: 'ARROW_DOWN',\n ARROW_LEFT: 'ARROW_LEFT',\n ARROW_RIGHT: 'ARROW_RIGHT',\n OPEN_COMMAND_PALETTE: 'OPEN_COMMAND_PALETTE',\n EDIT_COMPONENT: 'EDIT_COMPONENT',\n NAVIGATE_BACK: 'NAVIGATE_BACK',\n TOGGLE_ADDING_STYLE: 'TOGGLE_ADDING_STYLE',\n MOVE_ELEMENT_UP: 'MOVE_ELEMENT_UP',\n MOVE_ELEMENT_DOWN: 'MOVE_ELEMENT_DOWN',\n NEST_INTO_PREVIOUS_SIBLING: 'NEST_INTO_PREVIOUS_SIBLING',\n NEST_INTO_NEXT_SIBLING: 'NEST_INTO_NEXT_SIBLING',\n SELECTION_CHANGED: 'SELECTION_CHANGED',\n CMS_CONTEXT_UPDATE: 'CMS_CONTEXT_UPDATE',\n CMS_CONTEXT_REQUEST: 'CMS_CONTEXT_REQUEST',\n INTERACTIVE_CSS_UPDATE: 'INTERACTIVE_CSS_UPDATE',\n INTERACTIVE_STYLES_UPDATE: 'INTERACTIVE_STYLES_UPDATE', // Registry data from iframe to editor\n UNDO_REQUEST: 'UNDO_REQUEST',\n REDO_REQUEST: 'REDO_REQUEST',\n TOGGLE_INTERACTIVITY_EDITOR: 'TOGGLE_INTERACTIVITY_EDITOR',\n SET_BREAKPOINT: 'SET_BREAKPOINT',\n PAGE_DATA_PREVIEW: 'PAGE_DATA_PREVIEW', // Editor \u2192 Iframe for component hover preview\n PAGE_DATA_PREVIEW_REVERT: 'PAGE_DATA_PREVIEW_REVERT', // Editor \u2192 Iframe to revert preview\n PAGE_DATA_COMMITTED: 'PAGE_DATA_COMMITTED', // Editor \u2192 Iframe for committed mutations\n COMPONENT_DEFINITION_COMMITTED: 'COMPONENT_DEFINITION_COMMITTED', // Editor \u2192 Iframe for component definition updates\n CSS_VARIABLE_UPDATE: 'CSS_VARIABLE_UPDATE', // Editor \u2192 Iframe for instant CSS variable preview\n DUPLICATE_ELEMENT: 'DUPLICATE_ELEMENT',\n MAKE_COMPONENT: 'MAKE_COMPONENT',\n SWAP_TO_COMPONENT: 'SWAP_TO_COMPONENT',\n SMART_CONNECT: 'SMART_CONNECT',\n} as const;\n\n// Component node type constants\nexport const NODE_TYPE = {\n NODE: 'node',\n COMPONENT: 'component',\n SLOT: 'slot',\n EMBED: 'embed',\n LINK: 'link',\n LOCALE_LIST: 'locale-list',\n LIST: 'list',\n} as const;\n\nexport type NodeType = typeof NODE_TYPE[keyof typeof NODE_TYPE];\n\n// Special path identifiers for component editing\nexport const SPECIAL_PATHS = {\n COMPONENT_INTERFACE: 'component_interface',\n COMPONENT_JAVASCRIPT: 'component_javascript',\n COMPONENT_CSS: 'component_css',\n COMPONENT_LIBRARIES: 'component_libraries',\n COMPONENT_ACCEPTS_STYLES: 'component_acceptsStyles',\n STRUCTURE_STYLE: 'structure_style',\n} as const;\n\n// Component type configuration\nexport interface ComponentTypeConfig {\n id: string;\n label: string;\n color: string;\n description?: string;\n}\n\nexport const DEFAULT_COMPONENT_TYPES: ComponentTypeConfig[] = [\n { id: 'ui', label: 'UI', color: '#3b82f6' },\n { id: 'layout', label: 'Layout', color: '#10b981' },\n { id: 'content', label: 'Content', color: '#f59e0b' },\n];\n\nexport const DEFAULT_ICON_COLOR = '#6b7280';\n\n/**\n * Marker for raw HTML content that should not be escaped\n * Used by rich-text fields to signal that content should render as HTML\n */\nexport const RAW_HTML_PREFIX = '<!--MENO_RAW_HTML-->';\n\n"],
5
+ "mappings": ";;;;;AAAA,IAMa,aAMA,YAIA,YA8DA,WAEA,eAKA,iBAEA,kBAQA,sBACA,qBACA,2BACA,sBACA,0BAGA,mBAGA,sBAwCA,WAaA,eAiBA,yBAMA,oBAMA;AA3Lb;AAAA;AAMO,IAAM,cAAc,OAAO,YAAY,eAAe,QAAQ,KAAK,OACtE,SAAS,QAAQ,IAAI,MAAM,EAAE,IAC7B;AAIG,IAAM,aAAa,OAAO,YAAY,eAAe,QAAQ,KAAK,kBACrE,SAAS,QAAQ,IAAI,iBAAiB,EAAE,IACxC;AAEG,IAAM,aAAa;AAAA,MACxB,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,cAAc;AAAA;AAAA,MACd,WAAW;AAAA;AAAA,MACX,gBAAgB;AAAA;AAAA,MAChB,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,mBAAmB;AAAA;AAAA,MACnB,oBAAoB;AAAA;AAAA,MACpB,oBAAoB;AAAA;AAAA,MACpB,kBAAkB;AAAA;AAAA,MAClB,mBAAmB;AAAA;AAAA,MACnB,cAAc;AAAA;AAAA,MACd,QAAQ;AAAA;AAAA,MACR,aAAa;AAAA;AAAA,MACb,mBAAmB;AAAA;AAAA,MACnB,wBAAwB;AAAA;AAAA,MACxB,WAAW;AAAA;AAAA;AAAA,MAEX,iBAAiB;AAAA;AAAA,MACjB,UAAU;AAAA;AAAA;AAAA,MAEV,eAAe;AAAA;AAAA,MACf,aAAa;AAAA;AAAA;AAAA,MAEb,aAAa;AAAA;AAAA;AAAA,MAEb,aAAa;AAAA;AAAA,MACb,cAAc;AAAA;AAAA,MACd,WAAW;AAAA;AAAA;AAAA,MAEX,mBAAmB;AAAA;AAAA;AAAA,MAEnB,gBAAgB;AAAA;AAAA,MAChB,mBAAmB;AAAA;AAAA,MACnB,iBAAiB;AAAA;AAAA,MACjB,iBAAiB;AAAA;AAAA,MACjB,iBAAiB;AAAA;AAAA,MACjB,2BAA2B;AAAA;AAAA,MAC3B,8BAA8B;AAAA;AAAA,MAC9B,yBAAyB;AAAA;AAAA,MACzB,4BAA4B;AAAA;AAAA;AAAA,MAE5B,eAAe;AAAA;AAAA,MACf,aAAa;AAAA;AAAA,MACb,cAAc;AAAA;AAAA,MACd,sBAAsB;AAAA;AAAA,MACtB,0BAA0B;AAAA;AAAA,MAC1B,sBAAsB;AAAA;AAAA,MACtB,qBAAqB;AAAA;AAAA;AAAA,MAErB,kBAAkB;AAAA;AAAA,MAClB,eAAe;AAAA;AAAA,MACf,gBAAgB;AAAA;AAAA;AAAA,MAEhB,OAAO;AAAA;AAAA,MACP,YAAY;AAAA;AAAA;AAAA,MAEZ,iBAAiB;AAAA;AAAA,IACnB;AAEO,IAAM,YAAY;AAElB,IAAM,gBAAgB;AAAA,MAC3B,OAAO;AAAA,MACP,YAAY;AAAA,IACd;AAEO,IAAM,kBAAkB;AAExB,IAAM,mBAAmB;AAAA,MAC9B,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAGO,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAC5B,IAAM,4BAA4B;AAClC,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B;AAGjC,IAAM,oBAAoB;AAG1B,IAAM,uBAAuB;AAAA,MAClC,gBAAgB;AAAA,MAChB,uBAAuB;AAAA,MACvB,SAAS;AAAA,MACT,cAAc;AAAA,MACd,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,sBAAsB;AAAA,MACtB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,4BAA4B;AAAA,MAC5B,wBAAwB;AAAA,MACxB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,qBAAqB;AAAA,MACrB,wBAAwB;AAAA,MACxB,2BAA2B;AAAA;AAAA,MAC3B,cAAc;AAAA,MACd,cAAc;AAAA,MACd,6BAA6B;AAAA,MAC7B,gBAAgB;AAAA,MAChB,mBAAmB;AAAA;AAAA,MACnB,0BAA0B;AAAA;AAAA,MAC1B,qBAAqB;AAAA;AAAA,MACrB,gCAAgC;AAAA;AAAA,MAChC,qBAAqB;AAAA;AAAA,MACrB,mBAAmB;AAAA,MACnB,gBAAgB;AAAA,MAChB,mBAAmB;AAAA,MACnB,eAAe;AAAA,IACjB;AAGO,IAAM,YAAY;AAAA,MACvB,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM;AAAA,IACR;AAKO,IAAM,gBAAgB;AAAA,MAC3B,qBAAqB;AAAA,MACrB,sBAAsB;AAAA,MACtB,eAAe;AAAA,MACf,qBAAqB;AAAA,MACrB,0BAA0B;AAAA,MAC1B,iBAAiB;AAAA,IACnB;AAUO,IAAM,0BAAiD;AAAA,MAC5D,EAAE,IAAI,MAAM,OAAO,MAAM,OAAO,UAAU;AAAA,MAC1C,EAAE,IAAI,UAAU,OAAO,UAAU,OAAO,UAAU;AAAA,MAClD,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,IACtD;AAEO,IAAM,qBAAqB;AAM3B,IAAM,kBAAkB;AAAA;AAAA;",
6
+ "names": []
7
+ }