meno-core 1.0.49 → 1.0.51

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 (66) hide show
  1. package/build-astro.ts +6 -2
  2. package/build-static.ts +8 -1
  3. package/dist/bin/cli.js +1 -1
  4. package/dist/build-static.js +5 -5
  5. package/dist/chunks/{chunk-KPU2XHOS.js → chunk-2MHDV5BF.js} +11 -1
  6. package/dist/chunks/chunk-2MHDV5BF.js.map +7 -0
  7. package/dist/chunks/{chunk-JER5NQVM.js → chunk-3KJ6SJZC.js} +5 -5
  8. package/dist/chunks/{chunk-JER5NQVM.js.map → chunk-3KJ6SJZC.js.map} +2 -2
  9. package/dist/chunks/{chunk-S2CX6HFM.js → chunk-7NIC4I3V.js} +42 -20
  10. package/dist/chunks/chunk-7NIC4I3V.js.map +7 -0
  11. package/dist/chunks/{chunk-EQYDSPBB.js → chunk-DM54NPEC.js} +114 -31
  12. package/dist/chunks/chunk-DM54NPEC.js.map +7 -0
  13. package/dist/chunks/{chunk-LKAGAQ3M.js → chunk-EDQSMAMP.js} +13 -2
  14. package/dist/chunks/{chunk-LKAGAQ3M.js.map → chunk-EDQSMAMP.js.map} +2 -2
  15. package/dist/chunks/{chunk-4OFZP5NQ.js → chunk-HNLUO36W.js} +15 -4
  16. package/dist/chunks/chunk-HNLUO36W.js.map +7 -0
  17. package/dist/chunks/{chunk-6IVUG7FY.js → chunk-LPVETICS.js} +19 -2
  18. package/dist/chunks/{chunk-6IVUG7FY.js.map → chunk-LPVETICS.js.map} +2 -2
  19. package/dist/chunks/{chunk-CHD5UCFF.js → chunk-V7CD7V7W.js} +149 -46
  20. package/dist/chunks/chunk-V7CD7V7W.js.map +7 -0
  21. package/dist/chunks/{configService-CCA6AIDI.js → configService-R3OGU2UD.js} +2 -2
  22. package/dist/entries/server-router.js +5 -5
  23. package/dist/lib/client/index.js +41 -15
  24. package/dist/lib/client/index.js.map +3 -3
  25. package/dist/lib/server/index.js +12 -10
  26. package/dist/lib/server/index.js.map +2 -2
  27. package/dist/lib/shared/index.js +2 -2
  28. package/lib/client/core/ComponentBuilder.test.ts +34 -0
  29. package/lib/client/core/ComponentBuilder.ts +25 -3
  30. package/lib/client/core/builders/embedBuilder.ts +13 -5
  31. package/lib/client/core/builders/linkNodeBuilder.ts +13 -5
  32. package/lib/client/core/builders/localeListBuilder.ts +13 -5
  33. package/lib/client/templateEngine.ts +24 -0
  34. package/lib/server/fileWatcher.test.ts +134 -0
  35. package/lib/server/fileWatcher.ts +100 -32
  36. package/lib/server/jsonLoader.ts +1 -0
  37. package/lib/server/providers/fileSystemCMSProvider.ts +46 -14
  38. package/lib/server/routes/pages.ts +37 -2
  39. package/lib/server/services/cmsService.ts +21 -0
  40. package/lib/server/services/configService.ts +21 -0
  41. package/lib/server/services/fileWatcherService.ts +17 -0
  42. package/lib/server/ssr/buildErrorOverlay.ts +22 -4
  43. package/lib/server/ssr/errorOverlay.ts +11 -3
  44. package/lib/server/ssr/htmlGenerator.nonce.test.ts +165 -0
  45. package/lib/server/ssr/htmlGenerator.ts +36 -9
  46. package/lib/server/ssr/liveReloadIntegration.test.ts +3 -1
  47. package/lib/server/ssr/metaTagGenerator.ts +35 -5
  48. package/lib/server/ssr/ssrRenderer.test.ts +258 -0
  49. package/lib/server/ssr/ssrRenderer.ts +47 -5
  50. package/lib/server/ssrRenderer.test.ts +87 -2
  51. package/lib/server/webflow/buildWebflow.ts +1 -1
  52. package/lib/server/websocketManager.test.ts +61 -6
  53. package/lib/server/websocketManager.ts +25 -1
  54. package/lib/shared/cssProperties.test.ts +28 -0
  55. package/lib/shared/cssProperties.ts +27 -1
  56. package/lib/shared/types/api.ts +10 -1
  57. package/lib/shared/types/cms.ts +18 -9
  58. package/lib/shared/validation/schemas.test.ts +93 -0
  59. package/lib/shared/validation/schemas.ts +56 -15
  60. package/package.json +1 -1
  61. package/dist/chunks/chunk-4OFZP5NQ.js.map +0 -7
  62. package/dist/chunks/chunk-CHD5UCFF.js.map +0 -7
  63. package/dist/chunks/chunk-EQYDSPBB.js.map +0 -7
  64. package/dist/chunks/chunk-KPU2XHOS.js.map +0 -7
  65. package/dist/chunks/chunk-S2CX6HFM.js.map +0 -7
  66. /package/dist/chunks/{configService-CCA6AIDI.js.map → configService-R3OGU2UD.js.map} +0 -0
package/build-astro.ts CHANGED
@@ -565,13 +565,17 @@ export async function buildAstroProject(
565
565
  // SSR output (htmlGenerator.ts:269-507 for customCode, 368-473 for icons).
566
566
  const customCode = configService.getCustomCode();
567
567
  const iconsConfig = await loadIconsConfig();
568
+ const hasDarkFavicon = !!(iconsConfig.favicon && iconsConfig.faviconDark);
568
569
  const faviconTag = iconsConfig.favicon
569
- ? `<link rel="icon" href="${iconsConfig.favicon.replace(/"/g, '&quot;')}" />`
570
+ ? `<link rel="icon" href="${iconsConfig.favicon.replace(/"/g, '&quot;')}"${hasDarkFavicon ? ' media="(prefers-color-scheme: light)"' : ''} />`
571
+ : '';
572
+ const faviconDarkTag = iconsConfig.faviconDark
573
+ ? `<link rel="icon" href="${iconsConfig.faviconDark.replace(/"/g, '&quot;')}" media="(prefers-color-scheme: dark)" />`
570
574
  : '';
571
575
  const appleTouchIconTag = iconsConfig.appleTouchIcon
572
576
  ? `<link rel="apple-touch-icon" href="${iconsConfig.appleTouchIcon.replace(/"/g, '&quot;')}" />`
573
577
  : '';
574
- const iconTagsHtml = [faviconTag, appleTouchIconTag].filter(Boolean).join('\n ');
578
+ const iconTagsHtml = [faviconTag, faviconDarkTag, appleTouchIconTag].filter(Boolean).join('\n ');
575
579
 
576
580
  const remConversionConfig = configService.getRemConversion();
577
581
 
package/build-static.ts CHANGED
@@ -812,9 +812,16 @@ export async function buildStaticPages(): Promise<void> {
812
812
  const extraFonts = cspConfig.fontSrc?.join(' ') || '';
813
813
  const extraImgs = cspConfig.imgSrc?.join(' ') || '';
814
814
 
815
+ // Production-built pages have NO executable inline scripts: page config,
816
+ // component JS, form handler, and MenoFilter all live in external
817
+ // /_scripts/{hash}.js files (returnSeparateJS: true), and the Meno
818
+ // badge's hover effect is pure CSS. Only `<script type="application/json">`
819
+ // remains inline (used as a data island for MenoFilter), which CSP
820
+ // ignores because it has no executable code. So we can drop
821
+ // `'unsafe-inline'` entirely from script-src in the generated _headers.
815
822
  const cspDirectives = [
816
823
  "default-src 'self'",
817
- `script-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),
824
+ `script-src 'self' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),
818
825
  `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),
819
826
  `img-src 'self' data: https: ${extraImgs}`.trim(),
820
827
  `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),
package/dist/bin/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateBuildErrorPage
4
- } from "../chunks/chunk-4OFZP5NQ.js";
4
+ } from "../chunks/chunk-HNLUO36W.js";
5
5
  import {
6
6
  createRuntimeServer,
7
7
  setProjectRoot
@@ -9,14 +9,14 @@ import {
9
9
  hashContent,
10
10
  injectTrackingScript,
11
11
  isCMSPage
12
- } from "./chunks/chunk-JER5NQVM.js";
13
- import "./chunks/chunk-EQYDSPBB.js";
14
- import "./chunks/chunk-KPU2XHOS.js";
12
+ } from "./chunks/chunk-3KJ6SJZC.js";
13
+ import "./chunks/chunk-DM54NPEC.js";
14
+ import "./chunks/chunk-2MHDV5BF.js";
15
15
  import "./chunks/chunk-I7YIGZXT.js";
16
16
  import "./chunks/chunk-WQFG7PAH.js";
17
17
  import "./chunks/chunk-J23ZX5AP.js";
18
- import "./chunks/chunk-LKAGAQ3M.js";
19
- import "./chunks/chunk-S2CX6HFM.js";
18
+ import "./chunks/chunk-EDQSMAMP.js";
19
+ import "./chunks/chunk-7NIC4I3V.js";
20
20
  import "./chunks/chunk-AZQYF6KE.js";
21
21
  import "./chunks/chunk-UB44F4Z2.js";
22
22
  import "./chunks/chunk-2QK6U5UK.js";
@@ -164,6 +164,16 @@ var ConfigService = class {
164
164
  }
165
165
  return this.config.icons;
166
166
  }
167
+ /**
168
+ * Get site-wide social configuration
169
+ * Returns empty object if not configured
170
+ */
171
+ getSocial() {
172
+ if (!this.config?.social || typeof this.config.social !== "object") {
173
+ return {};
174
+ }
175
+ return this.config.social;
176
+ }
167
177
  /**
168
178
  * Get libraries configuration
169
179
  * Returns empty arrays if not configured
@@ -238,4 +248,4 @@ export {
238
248
  ConfigService,
239
249
  configService
240
250
  };
241
- //# sourceMappingURL=chunk-KPU2XHOS.js.map
251
+ //# sourceMappingURL=chunk-2MHDV5BF.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../lib/server/services/configService.ts"],
4
+ "sourcesContent": ["/**\n * Config Service\n * Centralized configuration loading and access\n *\n * Consolidates multiple config loaders into a single service that loads\n * the project.config.json file once and exposes typed sections.\n */\n\nimport type { BreakpointConfig, BreakpointConfigInput, BreakpointEntry } from '../../shared/breakpoints';\nimport { DEFAULT_BREAKPOINTS, normalizeBreakpointConfig } from '../../shared/breakpoints';\nimport type { ResponsiveScales, BreakpointScales } from '../../shared/responsiveScaling';\nimport { DEFAULT_RESPONSIVE_SCALES } from '../../shared/responsiveScaling';\nimport type { I18nConfig } from '../../shared/types/components';\nimport type { LibrariesConfig, JSLibraryConfig, CSSLibraryConfig } from '../../shared/types/libraries';\nimport type { CSPConfig } from '../../shared/types/config';\nimport type { CustomCodeConfig } from '../../shared/types/api';\nimport type { RemConversionConfig } from '../../shared/pxToRem';\nimport { DEFAULT_REM_CONFIG } from '../../shared/pxToRem';\nimport { DEFAULT_I18N_CONFIG, migrateI18nConfig } from '../../shared/i18n';\nimport { projectPaths } from '../projectContext';\nimport { readTextFile, fileExists } from '../runtime';\n\n/**\n * Icons configuration\n */\nexport interface IconsConfig {\n favicon?: string;\n faviconDark?: string;\n appleTouchIcon?: string;\n}\n\n/**\n * Site-wide social configuration\n */\nexport interface SocialConfig {\n twitterHandle?: string;\n}\n\n/**\n * Raw project config structure from project.config.json\n */\nexport type ImageFormat = 'webp' | 'avif';\n\ninterface RawProjectConfig {\n breakpoints?: BreakpointConfigInput;\n responsiveScales?: Partial<ResponsiveScales>;\n i18n?: unknown;\n icons?: IconsConfig;\n social?: SocialConfig;\n libraries?: LibrariesConfig;\n csp?: CSPConfig;\n baseComponent?: string;\n imageFormat?: ImageFormat;\n remConversion?: Partial<RemConversionConfig>;\n customCode?: CustomCodeConfig;\n showMenoBadge?: boolean;\n}\n\n/**\n * ConfigService\n * Loads project configuration once and provides typed access to sections\n */\nexport class ConfigService {\n private config: RawProjectConfig | null = null;\n private loaded = false;\n\n /**\n * Load configuration from project.config.json\n * Safe to call multiple times - only loads once\n */\n async load(): Promise<void> {\n if (this.loaded) {\n return;\n }\n\n try {\n if (await fileExists(projectPaths.config())) {\n const content = await readTextFile(projectPaths.config());\n this.config = JSON.parse(content);\n }\n } catch {\n // Fall through to defaults\n this.config = null;\n }\n\n this.loaded = true;\n }\n\n /**\n * Check if configuration has been loaded\n */\n isLoaded(): boolean {\n return this.loaded;\n }\n\n /**\n * Reset the service (for testing)\n */\n reset(): void {\n this.config = null;\n this.loaded = false;\n }\n\n /**\n * Get breakpoint configuration\n * Returns validated and normalized breakpoints (always object format)\n * Supports both legacy format { tablet: 1024 } and new format { tablet: { breakpoint: 1024, previewPoint: 768 } }\n */\n getBreakpoints(): BreakpointConfig {\n if (!this.config?.breakpoints || typeof this.config.breakpoints !== 'object') {\n return { ...DEFAULT_BREAKPOINTS };\n }\n\n // Validate breakpoint values before normalization\n const validInput: BreakpointConfigInput = {};\n for (const [key, value] of Object.entries(this.config.breakpoints)) {\n if (typeof value === 'number' && value > 0) {\n // Legacy format: number\n validInput[key] = value;\n } else if (typeof value === 'object' && value !== null) {\n // New format: object with breakpoint and optional previewPoint\n const entry = value as BreakpointEntry;\n if (typeof entry.breakpoint === 'number' && entry.breakpoint > 0) {\n validInput[key] = {\n breakpoint: entry.breakpoint,\n previewPoint: typeof entry.previewPoint === 'number' && entry.previewPoint > 0\n ? entry.previewPoint\n : entry.breakpoint,\n };\n }\n }\n }\n\n // Return normalized breakpoints or defaults if none valid\n if (Object.keys(validInput).length === 0) {\n return { ...DEFAULT_BREAKPOINTS };\n }\n\n return normalizeBreakpointConfig(validInput);\n }\n\n /**\n * Get i18n configuration\n * Automatically migrates old string[] format to LocaleConfig[] format\n */\n getI18n(): I18nConfig {\n if (!this.config?.i18n) {\n return { ...DEFAULT_I18N_CONFIG };\n }\n\n return migrateI18nConfig(this.config.i18n);\n }\n\n /**\n * Deep merge scale categories, preserving user-defined breakpoints\n * while filling in missing values from defaults\n */\n private mergeScaleCategory(\n userScales: BreakpointScales | undefined,\n defaultScales: BreakpointScales | undefined\n ): BreakpointScales | undefined {\n if (!userScales && !defaultScales) return undefined;\n if (!userScales) return defaultScales ? { ...defaultScales } : undefined;\n if (!defaultScales) return { ...userScales };\n\n // User scales take precedence, but include defaults for breakpoints not specified\n return {\n ...defaultScales,\n ...userScales,\n };\n }\n\n /**\n * Get responsive scales configuration\n * Supports dynamic breakpoints - scales are keyed by breakpoint name\n * Deep merges scale categories to preserve user breakpoint definitions\n */\n getResponsiveScales(): ResponsiveScales {\n if (!this.config?.responsiveScales || typeof this.config.responsiveScales !== 'object') {\n return { ...DEFAULT_RESPONSIVE_SCALES };\n }\n\n const userScales = this.config.responsiveScales;\n\n return {\n enabled: userScales.enabled ?? DEFAULT_RESPONSIVE_SCALES.enabled,\n mode: (userScales as { mode?: 'breakpoints' | 'fluid' }).mode ?? DEFAULT_RESPONSIVE_SCALES.mode,\n baseReference: userScales.baseReference ?? DEFAULT_RESPONSIVE_SCALES.baseReference,\n fluidRange: (userScales as { fluidRange?: { min: number; max: number } }).fluidRange\n ?? (DEFAULT_RESPONSIVE_SCALES.fluidRange ? { ...DEFAULT_RESPONSIVE_SCALES.fluidRange } : undefined),\n siteMargin: (userScales as { siteMargin?: { min: number; max: number } }).siteMargin\n ?? (DEFAULT_RESPONSIVE_SCALES.siteMargin ? { ...DEFAULT_RESPONSIVE_SCALES.siteMargin } : undefined),\n fontSize: this.mergeScaleCategory(\n userScales.fontSize as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.fontSize\n ),\n padding: this.mergeScaleCategory(\n userScales.padding as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.padding\n ),\n margin: this.mergeScaleCategory(\n userScales.margin as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.margin\n ),\n gap: this.mergeScaleCategory(\n userScales.gap as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.gap\n ),\n borderRadius: this.mergeScaleCategory(\n userScales.borderRadius as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.borderRadius\n ),\n size: this.mergeScaleCategory(\n userScales.size as BreakpointScales | undefined,\n DEFAULT_RESPONSIVE_SCALES.size\n ),\n };\n }\n\n /**\n * Get rem conversion configuration\n */\n getRemConversion(): RemConversionConfig {\n if (!this.config?.remConversion || typeof this.config.remConversion !== 'object') {\n return { ...DEFAULT_REM_CONFIG };\n }\n return {\n enabled: this.config.remConversion.enabled ?? DEFAULT_REM_CONFIG.enabled,\n baseFontSize: this.config.remConversion.baseFontSize ?? DEFAULT_REM_CONFIG.baseFontSize,\n };\n }\n\n /**\n * Get icons configuration\n * Returns empty object if not configured\n */\n getIcons(): IconsConfig {\n if (!this.config?.icons || typeof this.config.icons !== 'object') {\n return {};\n }\n\n return this.config.icons;\n }\n\n /**\n * Get site-wide social configuration\n * Returns empty object if not configured\n */\n getSocial(): SocialConfig {\n if (!this.config?.social || typeof this.config.social !== 'object') {\n return {};\n }\n\n return this.config.social;\n }\n\n /**\n * Get libraries configuration\n * Returns empty arrays if not configured\n * Normalizes string URLs to object format for backwards compatibility\n */\n getLibraries(): LibrariesConfig {\n if (!this.config?.libraries || typeof this.config.libraries !== 'object') {\n return { js: [], css: [] };\n }\n\n const libs = this.config.libraries;\n\n // Normalize JS libraries: support both string URLs and object format\n const normalizedJs = Array.isArray(libs.js)\n ? libs.js.map((lib) =>\n typeof lib === 'string' ? { url: lib } : lib\n ) as JSLibraryConfig[]\n : [];\n\n // Normalize CSS libraries: support both string URLs and object format\n const normalizedCss = Array.isArray(libs.css)\n ? libs.css.map((lib) =>\n typeof lib === 'string' ? { url: lib } : lib\n ) as CSSLibraryConfig[]\n : [];\n\n return {\n js: normalizedJs,\n css: normalizedCss,\n };\n }\n\n /**\n * Get CSP configuration\n * Returns empty object if not configured\n */\n getCSP(): CSPConfig {\n if (!this.config?.csp || typeof this.config.csp !== 'object') {\n return {};\n }\n\n return this.config.csp;\n }\n\n /**\n * Get base component name for new pages\n * Returns undefined if not configured\n */\n getBaseComponent(): string | undefined {\n if (!this.config?.baseComponent || typeof this.config.baseComponent !== 'string') {\n return undefined;\n }\n return this.config.baseComponent;\n }\n\n /**\n * Get image format setting\n * Returns 'webp' (default) or 'avif'\n */\n getCustomCode(): CustomCodeConfig {\n if (!this.config?.customCode || typeof this.config.customCode !== 'object') {\n return {};\n }\n return this.config.customCode;\n }\n\n getShowMenoBadge(): boolean {\n return this.config?.showMenoBadge === true;\n }\n\n getImageFormat(): ImageFormat {\n if (this.config?.imageFormat === 'avif') return 'avif';\n return 'webp';\n }\n\n /**\n * Get raw config value by key (for extension)\n */\n getRaw<T>(key: string): T | undefined {\n if (!this.config) {\n return undefined;\n }\n return (this.config as Record<string, unknown>)[key] as T | undefined;\n }\n}\n\n/**\n * Singleton instance for global access\n * Use this for convenience, or create your own instance for testing\n */\nexport const configService = new ConfigService();\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;AA8DO,IAAM,gBAAN,MAAoB;AAAA,EACjB,SAAkC;AAAA,EAClC,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjB,MAAM,OAAsB;AAC1B,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,QAAI;AACF,UAAI,MAAM,WAAW,aAAa,OAAO,CAAC,GAAG;AAC3C,cAAM,UAAU,MAAM,aAAa,aAAa,OAAO,CAAC;AACxD,aAAK,SAAS,KAAK,MAAM,OAAO;AAAA,MAClC;AAAA,IACF,QAAQ;AAEN,WAAK,SAAS;AAAA,IAChB;AAEA,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS;AACd,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAmC;AACjC,QAAI,CAAC,KAAK,QAAQ,eAAe,OAAO,KAAK,OAAO,gBAAgB,UAAU;AAC5E,aAAO,EAAE,GAAG,oBAAoB;AAAA,IAClC;AAGA,UAAM,aAAoC,CAAC;AAC3C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,WAAW,GAAG;AAClE,UAAI,OAAO,UAAU,YAAY,QAAQ,GAAG;AAE1C,mBAAW,GAAG,IAAI;AAAA,MACpB,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AAEtD,cAAM,QAAQ;AACd,YAAI,OAAO,MAAM,eAAe,YAAY,MAAM,aAAa,GAAG;AAChE,qBAAW,GAAG,IAAI;AAAA,YAChB,YAAY,MAAM;AAAA,YAClB,cAAc,OAAO,MAAM,iBAAiB,YAAY,MAAM,eAAe,IACzE,MAAM,eACN,MAAM;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,KAAK,UAAU,EAAE,WAAW,GAAG;AACxC,aAAO,EAAE,GAAG,oBAAoB;AAAA,IAClC;AAEA,WAAO,0BAA0B,UAAU;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAsB;AACpB,QAAI,CAAC,KAAK,QAAQ,MAAM;AACtB,aAAO,EAAE,GAAG,oBAAoB;AAAA,IAClC;AAEA,WAAO,kBAAkB,KAAK,OAAO,IAAI;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBACN,YACA,eAC8B;AAC9B,QAAI,CAAC,cAAc,CAAC,cAAe,QAAO;AAC1C,QAAI,CAAC,WAAY,QAAO,gBAAgB,EAAE,GAAG,cAAc,IAAI;AAC/D,QAAI,CAAC,cAAe,QAAO,EAAE,GAAG,WAAW;AAG3C,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,sBAAwC;AACtC,QAAI,CAAC,KAAK,QAAQ,oBAAoB,OAAO,KAAK,OAAO,qBAAqB,UAAU;AACtF,aAAO,EAAE,GAAG,0BAA0B;AAAA,IACxC;AAEA,UAAM,aAAa,KAAK,OAAO;AAE/B,WAAO;AAAA,MACL,SAAS,WAAW,WAAW,0BAA0B;AAAA,MACzD,MAAO,WAAkD,QAAQ,0BAA0B;AAAA,MAC3F,eAAe,WAAW,iBAAiB,0BAA0B;AAAA,MACrE,YAAa,WAA6D,eACpE,0BAA0B,aAAa,EAAE,GAAG,0BAA0B,WAAW,IAAI;AAAA,MAC3F,YAAa,WAA6D,eACpE,0BAA0B,aAAa,EAAE,GAAG,0BAA0B,WAAW,IAAI;AAAA,MAC3F,UAAU,KAAK;AAAA,QACb,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,MACA,SAAS,KAAK;AAAA,QACZ,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,MACA,QAAQ,KAAK;AAAA,QACX,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,MACA,KAAK,KAAK;AAAA,QACR,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,MACA,cAAc,KAAK;AAAA,QACjB,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,MACA,MAAM,KAAK;AAAA,QACT,WAAW;AAAA,QACX,0BAA0B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAwC;AACtC,QAAI,CAAC,KAAK,QAAQ,iBAAiB,OAAO,KAAK,OAAO,kBAAkB,UAAU;AAChF,aAAO,EAAE,GAAG,mBAAmB;AAAA,IACjC;AACA,WAAO;AAAA,MACL,SAAS,KAAK,OAAO,cAAc,WAAW,mBAAmB;AAAA,MACjE,cAAc,KAAK,OAAO,cAAc,gBAAgB,mBAAmB;AAAA,IAC7E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAwB;AACtB,QAAI,CAAC,KAAK,QAAQ,SAAS,OAAO,KAAK,OAAO,UAAU,UAAU;AAChE,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAA0B;AACxB,QAAI,CAAC,KAAK,QAAQ,UAAU,OAAO,KAAK,OAAO,WAAW,UAAU;AAClE,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAgC;AAC9B,QAAI,CAAC,KAAK,QAAQ,aAAa,OAAO,KAAK,OAAO,cAAc,UAAU;AACxE,aAAO,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,EAAE;AAAA,IAC3B;AAEA,UAAM,OAAO,KAAK,OAAO;AAGzB,UAAM,eAAe,MAAM,QAAQ,KAAK,EAAE,IACtC,KAAK,GAAG;AAAA,MAAI,CAAC,QACX,OAAO,QAAQ,WAAW,EAAE,KAAK,IAAI,IAAI;AAAA,IAC3C,IACA,CAAC;AAGL,UAAM,gBAAgB,MAAM,QAAQ,KAAK,GAAG,IACxC,KAAK,IAAI;AAAA,MAAI,CAAC,QACZ,OAAO,QAAQ,WAAW,EAAE,KAAK,IAAI,IAAI;AAAA,IAC3C,IACA,CAAC;AAEL,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,KAAK;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAoB;AAClB,QAAI,CAAC,KAAK,QAAQ,OAAO,OAAO,KAAK,OAAO,QAAQ,UAAU;AAC5D,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAuC;AACrC,QAAI,CAAC,KAAK,QAAQ,iBAAiB,OAAO,KAAK,OAAO,kBAAkB,UAAU;AAChF,aAAO;AAAA,IACT;AACA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAkC;AAChC,QAAI,CAAC,KAAK,QAAQ,cAAc,OAAO,KAAK,OAAO,eAAe,UAAU;AAC1E,aAAO,CAAC;AAAA,IACV;AACA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,mBAA4B;AAC1B,WAAO,KAAK,QAAQ,kBAAkB;AAAA,EACxC;AAAA,EAEA,iBAA8B;AAC5B,QAAI,KAAK,QAAQ,gBAAgB,OAAQ,QAAO;AAChD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAU,KAA4B;AACpC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO;AAAA,IACT;AACA,WAAQ,KAAK,OAAmC,GAAG;AAAA,EACrD;AACF;AAMO,IAAM,gBAAgB,IAAI,cAAc;",
6
+ "names": []
7
+ }
@@ -15,7 +15,7 @@ import {
15
15
  migrateTemplatesDirectory,
16
16
  parseJSON,
17
17
  prepareClientData
18
- } from "./chunk-EQYDSPBB.js";
18
+ } from "./chunk-DM54NPEC.js";
19
19
  import {
20
20
  minifyJS,
21
21
  projectPaths
@@ -26,7 +26,7 @@ import {
26
26
  import {
27
27
  isItemDraftForLocale,
28
28
  isItemFullyPublished
29
- } from "./chunk-S2CX6HFM.js";
29
+ } from "./chunk-7NIC4I3V.js";
30
30
  import {
31
31
  isI18nValue,
32
32
  resolveI18nValue
@@ -754,7 +754,7 @@ async function buildStaticPages() {
754
754
  console.log("\u{1F3D7}\uFE0F Building static HTML files...\n");
755
755
  buildErrors.length = 0;
756
756
  clearJSValidationCache();
757
- const { configService } = await import("./configService-CCA6AIDI.js");
757
+ const { configService } = await import("./configService-R3OGU2UD.js");
758
758
  configService.reset();
759
759
  const projectConfig = await loadProjectConfig();
760
760
  const siteUrl = projectConfig.siteUrl?.replace(/\/$/, "");
@@ -920,7 +920,7 @@ async function buildStaticPages() {
920
920
  const extraImgs = cspConfig.imgSrc?.join(" ") || "";
921
921
  const cspDirectives = [
922
922
  "default-src 'self'",
923
- `script-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),
923
+ `script-src 'self' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),
924
924
  `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),
925
925
  `img-src 'self' data: https: ${extraImgs}`.trim(),
926
926
  `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),
@@ -1132,4 +1132,4 @@ export {
1132
1132
  injectTrackingScript,
1133
1133
  buildStaticPages
1134
1134
  };
1135
- //# sourceMappingURL=chunk-JER5NQVM.js.map
1135
+ //# sourceMappingURL=chunk-3KJ6SJZC.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../build-static.ts", "../../lib/server/ab/generateFunctions.ts", "../../lib/server/ab/trackingScript.ts"],
4
- "sourcesContent": ["/**\n * Static Site Generation Build Script\n * Pre-generates HTML files for all pages at build time\n * CSP-compliant: Extracts JavaScript to external files\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { writeFile, readFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport type { BuildError, BuildErrorsData } from \"./lib/server/ssr/buildErrorOverlay\";\nimport { createHash } from \"crypto\";\nimport { inspect, minifyJS as runtimeMinifyJS } from './lib/server/runtime';\nimport {\n loadJSONFile,\n loadComponentDirectory,\n mapPageNameToPath,\n parseJSON,\n loadI18nConfig\n} from \"./lib/server/jsonLoader\";\nimport { generateSSRHTML } from \"./lib/server/ssrRenderer\";\nimport type { SSRHTMLResult } from \"./lib/server/ssr/htmlGenerator\";\nimport { prepareClientData, type ClientDataCollection } from \"./lib/server/ssr/clientDataInjector\";\nimport { clearJSValidationCache, getJSValidationErrors } from \"./lib/server/ssr/jsCollector\";\nimport { projectPaths } from \"./lib/server/projectContext\";\nimport { loadProjectConfig } from \"./lib/shared/fontLoader\";\nimport { FileSystemCMSProvider } from \"./lib/server/providers/fileSystemCMSProvider\";\nimport { CMSService } from \"./lib/server/services/cmsService\";\nimport { isI18nValue, resolveI18nValue } from \"./lib/shared/i18n\";\nimport type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig, Experiment } from \"./lib/shared/types\";\nimport { isItemDraftForLocale, isItemFullyPublished } from \"./lib/shared/types\";\nimport type { SlugMap } from \"./lib/shared/slugTranslator\";\nimport { buildItemUrl } from \"./lib/shared/itemTemplateUtils\";\nimport { generateMiddleware, generateTrackFunction, generateResultsFunction } from \"./lib/server/ab/generateFunctions\";\nimport { generateTrackingScript } from \"./lib/server/ab/trackingScript\";\nimport { migrateTemplatesDirectory } from \"./lib/server/migrateTemplates\";\nimport { extractLibraryOrigins, collectComponentLibraries, filterLibrariesByContext } from \"./lib/shared/libraryLoader\";\nimport type { LibrariesConfig } from \"./lib/shared/types/libraries\";\n\n/**\n * Collect build errors for error overlay\n */\nconst buildErrors: BuildError[] = [];\n\n/**\n * Generate short hash from content for file naming\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex').slice(0, 8);\n}\n\n/**\n * Format a Bun build log entry to a readable string\n */\nexport function formatBunLog(log: any): string {\n const parts: string[] = [];\n\n // Try to get position info\n if (log.position) {\n const pos = log.position;\n if (pos.file) parts.push(`File: ${pos.file}`);\n if (pos.line !== undefined) parts.push(`Line ${pos.line}:${pos.column || 0}`);\n if (pos.lineText) parts.push(` ${pos.lineText}`);\n }\n\n // Get the message\n if (log.message) {\n parts.push(log.message);\n } else if (log.text) {\n parts.push(log.text);\n }\n\n // If we couldn't extract anything useful, stringify the whole thing\n if (parts.length === 0) {\n try {\n return JSON.stringify(log, null, 2);\n } catch {\n return String(log);\n }\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Minify JavaScript code using runtime bundler\n * Throws on error instead of silently failing\n */\nasync function minifyJS(code: string): Promise<string> {\n const result = await runtimeMinifyJS(code);\n if (result.success) {\n return result.code;\n }\n throw new Error(`JavaScript minification failed:\\n${result.errors.join('\\n\\n')}`);\n}\n\n/**\n * Track JavaScript files to avoid duplicates\n * Maps content hash -> script path\n */\nconst jsFileCache = new Map<string, string>();\n\n/**\n * Get or create script file path for given JS content\n * Returns the path to reference in HTML\n */\nasync function getScriptPath(jsContent: string, distDir: string): Promise<string> {\n // Minify JavaScript for production\n const minified = await minifyJS(jsContent);\n const hash = hashContent(minified);\n\n // Check if we already wrote this content\n if (jsFileCache.has(hash)) {\n return jsFileCache.get(hash)!;\n }\n\n // Create scripts directory if needed\n const scriptsDir = join(distDir, '_scripts');\n if (!existsSync(scriptsDir)) {\n mkdirSync(scriptsDir, { recursive: true });\n }\n\n // Write minified script file\n const scriptPath = `/_scripts/${hash}.js`;\n const fullPath = join(distDir, '_scripts', `${hash}.js`);\n await writeFile(fullPath, minified, 'utf-8');\n\n // Cache for reuse\n jsFileCache.set(hash, scriptPath);\n\n return scriptPath;\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectory(src: string, dest: string): void {\n if (!existsSync(src)) {\n return;\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const files = readdirSync(src);\n\n for (const file of files) {\n const srcPath = join(src, file);\n const destPath = join(dest, file);\n const stat = statSync(srcPath);\n\n if (stat.isDirectory()) {\n copyDirectory(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n\n/**\n * Get locale-specific output path for a page with translated slug support\n * Default locale files go to root, other locales to subdirectories\n * Uses translated slugs from meta.slugs if available\n */\nexport function getLocalizedOutputPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n distDir: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale, or fall back to default path\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n // Build filename from slug\n const fileName = slug === \"\" ? \"index.html\" : `${slug}.html`;\n\n if (locale === defaultLocale) {\n return `${distDir}/${fileName}`;\n }\n return `${distDir}/${locale}/${fileName}`;\n}\n\n/**\n * Get display path for logging (the actual URL the user will visit)\n */\nexport function getDisplayPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n if (locale === defaultLocale) {\n return slug === \"\" ? \"/\" : `/${slug}`;\n }\n return slug === \"\" ? `/${locale}` : `/${locale}/${slug}`;\n}\n\n/**\n * Generate robots.txt with sensible defaults\n */\nexport async function generateRobotsTxt(siteUrl: string, distDir: string): Promise<void> {\n const content = `User-agent: *\nAllow: /\n\nSitemap: ${siteUrl}/sitemap.xml\n`;\n await writeFile(join(distDir, 'robots.txt'), content, 'utf-8');\n}\n\n/**\n * Generate sitemap.xml from collected URLs\n */\nexport async function generateSitemap(urls: string[], siteUrl: string, distDir: string): Promise<void> {\n // Sort URLs for deterministic output\n const sortedUrls = [...urls].sort();\n\n const urlEntries = sortedUrls\n .map(url => ` <url><loc>${siteUrl}${url}</loc></url>`)\n .join('\\n');\n\n const content = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${urlEntries}\n</urlset>\n`;\n await writeFile(join(distDir, 'sitemap.xml'), content, 'utf-8');\n}\n\n/**\n * Clean dist directory, keeping only production files\n */\nfunction cleanDist(): void {\n const distDir = projectPaths.dist();\n if (!existsSync(distDir)) {\n mkdirSync(distDir, { recursive: true });\n return;\n }\n\n const files = readdirSync(distDir);\n let cleaned = 0;\n\n for (const file of files) {\n // Keep fonts, images, icons, assets, and videos\n if (\n file === \"fonts\" ||\n file === \"images\" ||\n file === \"icons\" ||\n file === \"assets\" ||\n file === \"videos\"\n ) {\n continue;\n }\n\n // Remove everything else (editor files, old HTML, etc.)\n try {\n const filePath = join(distDir, file);\n const stat = statSync(filePath);\n\n if (stat.isDirectory()) {\n rmSync(filePath, { recursive: true, force: true });\n } else {\n rmSync(filePath, { force: true });\n }\n cleaned++;\n } catch (error) {\n console.warn(`\u26A0\uFE0F Could not remove ${file}:`, error);\n }\n }\n\n if (cleaned > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleaned} file(s) from dist\\n`);\n }\n}\n\n/**\n * Check if a page is a CMS template\n */\nexport function isCMSPage(pageData: JSONPage): boolean {\n return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;\n}\n\n/**\n * Build URL path for a CMS item based on the URL pattern\n * Uses schema.slugField to get the slug value, supporting i18n slugs\n */\nexport function buildCMSItemPath(\n urlPattern: string,\n item: CMSItem,\n slugField: string,\n locale: string,\n i18nConfig: I18nConfig\n): string {\n // Get slug from the schema-defined slugField, fall back to _slug or _id\n let slug = item[slugField] ?? item._slug ?? item._id;\n\n // Resolve i18n slug to locale-specific value\n if (isI18nValue(slug)) {\n slug = resolveI18nValue(slug, locale, i18nConfig) as string;\n }\n\n return urlPattern.replace('{{slug}}', String(slug));\n}\n\n/**\n * Generate static JSON data files for collections with 'static' strategy\n * Output: /data/{collection}/index.json\n */\nasync function generateStaticDataFiles(\n staticCollections: Map<string, ClientDataCollection>,\n distDir: string\n): Promise<void> {\n if (staticCollections.size === 0) return;\n\n console.log(`\\n\uD83D\uDCE6 Generating static data files...`);\n\n for (const [collectionId, data] of staticCollections) {\n const dataDir = join(distDir, 'data', collectionId);\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const jsonPath = join(dataDir, 'index.json');\n await writeFile(jsonPath, JSON.stringify(data.items), 'utf-8');\n console.log(` \u2705 /data/${collectionId}/index.json (${data.items.length} items)`);\n }\n}\n\n/**\n * Build CMS templates from root templates/ directory\n */\nasync function buildCMSTemplates(\n templatesDir: string,\n globalComponents: Record<string, ComponentDefinition>,\n i18nConfig: I18nConfig,\n slugMappings: SlugMap[],\n distDir: string,\n cmsService: CMSService,\n generatedUrls: Set<string>,\n staticCollections: Map<string, ClientDataCollection>,\n siteUrl?: string,\n abTrackingScript?: string | null\n): Promise<{ success: number; errors: number }> {\n let successCount = 0;\n let errorCount = 0;\n\n if (!existsSync(templatesDir)) {\n return { success: 0, errors: 0 };\n }\n\n const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));\n\n if (templateFiles.length === 0) {\n return { success: 0, errors: 0 };\n }\n\n console.log(`\\n\uD83D\uDCDD Processing ${templateFiles.length} CMS template(s)...\\n`);\n\n for (const file of templateFiles) {\n const templateContent = await loadJSONFile(join(templatesDir, file));\n if (!templateContent) continue;\n\n try {\n const pageData = parseJSON<JSONPage>(templateContent);\n\n // Skip draft templates in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft template: ${file}`);\n continue;\n }\n\n if (!isCMSPage(pageData)) {\n console.warn(`\u26A0\uFE0F ${file} is in templates/ but missing meta.source: \"cms\"`);\n continue;\n }\n\n const cmsSchema = pageData.meta!.cms as CMSSchema;\n console.log(`\uD83D\uDCDD CMS Collection: ${cmsSchema.id}`);\n\n // Use shared cmsService to get items\n const items = await cmsService.queryItems({ collection: cmsSchema.id });\n\n if (items.length === 0) {\n console.log(` \u26A0\uFE0F No items found in cms/${cmsSchema.id}/`);\n continue;\n }\n\n console.log(` Found ${items.length} item(s)`);\n\n // Prepare client data if clientData is enabled\n // Filter out fully-draft items from client data (client data is locale-agnostic)\n let clientDataCollections: Map<string, ClientDataCollection> | undefined;\n if (cmsSchema.clientData?.enabled) {\n const publishedItems = items.filter(item => isItemFullyPublished(item));\n const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);\n if (clientData) {\n if (clientData.strategy === 'inline') {\n // Inline data embedded in HTML\n clientDataCollections = new Map([[cmsSchema.id, clientData]]);\n console.log(` \uD83D\uDCE6 Client data (inline): ${clientData.items.length} items (${clientData.config.fields?.length || 'all'} fields)`);\n } else if (clientData.strategy === 'static') {\n // Static data written to separate file\n staticCollections.set(cmsSchema.id, clientData);\n console.log(` \uD83D\uDCE6 Client data (static): ${clientData.items.length} items \u2192 /data/${cmsSchema.id}/index.json`);\n }\n }\n }\n\n for (const item of items) {\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n\n // Skip draft items per locale in production builds\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (!isDevBuild && isItemDraftForLocale(item, locale)) {\n console.log(` \u23ED\uFE0F Skipping draft: ${item._filename || item._id} [${locale}]`);\n continue;\n }\n\n const baseUrl = siteUrl || \"\";\n const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);\n\n // Create CMS item with computed _url for {{cms._url}} template access\n const itemWithUrl: CMSItem = { ...item, _url: itemPath };\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: itemPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsContext: { cms: itemWithUrl },\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n clientDataCollections,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (abTrackingScript) {\n finalHtml = injectTrackingScript(finalHtml, abTrackingScript);\n }\n\n const outputPath = locale === i18nConfig.defaultLocale\n ? `${distDir}${itemPath}.html`\n : `${distDir}/${locale}${itemPath}.html`;\n\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n await writeFile(outputPath, finalHtml, 'utf-8');\n\n const displayPath = locale === i18nConfig.defaultLocale ? itemPath : `/${locale}${itemPath}`;\n generatedUrls.add(displayPath);\n console.log(` \u2705 ${displayPath}`);\n successCount++;\n }\n }\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error processing ${file}:`, error);\n buildErrors.push({\n file: `templates/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'cms',\n });\n errorCount++;\n }\n }\n\n return { success: successCount, errors: errorCount };\n}\n\n/**\n * Load running experiments from experiments.json\n */\nasync function loadRunningExperiments(): Promise<Experiment[]> {\n const experimentsPath = join(projectPaths.project, 'experiments.json');\n if (!existsSync(experimentsPath)) return [];\n\n try {\n const content = await readFile(experimentsPath, 'utf-8');\n const data = JSON.parse(content);\n const experiments: Experiment[] = data.experiments || [];\n return experiments.filter(e => e.status === 'running');\n } catch {\n return [];\n }\n}\n\n/**\n * Inject A/B tracking script into HTML before </head>\n */\nexport function injectTrackingScript(html: string, trackingJs: string): string {\n const scriptTag = `<script>${trackingJs}</script>`;\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n}\n\n/**\n * Generate A/B testing Cloudflare Functions into dist/functions/\n */\nasync function generateABFunctions(experiments: Experiment[], distDir: string): Promise<void> {\n // Generate middleware\n const middlewareContent = generateMiddleware(experiments);\n if (middlewareContent) {\n const middlewarePath = join(distDir, 'functions', '_middleware.ts');\n const middlewareDir = join(distDir, 'functions');\n if (!existsSync(middlewareDir)) {\n mkdirSync(middlewareDir, { recursive: true });\n }\n await writeFile(middlewarePath, middlewareContent, 'utf-8');\n }\n\n // Generate tracking endpoint\n const trackContent = generateTrackFunction();\n const trackDir = join(distDir, 'functions', 'api');\n if (!existsSync(trackDir)) {\n mkdirSync(trackDir, { recursive: true });\n }\n await writeFile(join(trackDir, 'ab-track.ts'), trackContent, 'utf-8');\n\n // Generate results endpoint\n const resultsContent = generateResultsFunction();\n await writeFile(join(trackDir, 'ab-results.ts'), resultsContent, 'utf-8');\n}\n\n/**\n * Main build function\n */\nexport async function buildStaticPages(): Promise<void> {\n console.log(\"\uD83C\uDFD7\uFE0F Building static HTML files...\\n\");\n\n // Clear previous build errors and JS validation cache\n buildErrors.length = 0;\n clearJSValidationCache();\n\n // Reset configService to ensure it loads from the correct project directory\n const { configService } = await import(\"./lib/server/services/configService\");\n configService.reset();\n\n // Load project config first\n const projectConfig = await loadProjectConfig();\n const siteUrl = (projectConfig as { siteUrl?: string }).siteUrl?.replace(/\\/$/, ''); // Remove trailing slash\n\n // Track all generated URLs for sitemap\n const generatedUrls = new Set<string>();\n\n // Load running A/B experiments (if any)\n const runningExperiments = await loadRunningExperiments();\n let trackingScript: string | null = null;\n if (runningExperiments.length > 0) {\n const exp = runningExperiments[0]; // Use first running experiment\n trackingScript = generateTrackingScript(exp.id, exp.conversionGoals);\n console.log(`\uD83E\uDDEA A/B experiment active: \"${exp.name}\" (${exp.variants.length} variant(s))\\n`);\n }\n\n // Load i18n config for multi-locale build\n const i18nConfig = await loadI18nConfig();\n console.log(`\uD83C\uDF10 Locales: ${i18nConfig.locales.map(l => l.code).join(\", \")} (default: ${i18nConfig.defaultLocale})\\n`);\n\n // Auto-migrate pages/templates/ \u2192 templates/ if needed\n await migrateTemplatesDirectory();\n\n // Clean dist directory (removes editor files, old HTML)\n cleanDist();\n\n // Clear the JS file cache since cleanDist() removed _scripts/\n // Without this, cached entries would skip file creation on subsequent builds\n jsFileCache.clear();\n\n // Copy fonts, images, icons, and functions directories to dist\n console.log(\"\uD83D\uDCE6 Copying assets...\");\n const distDir = projectPaths.dist();\n\n // Delete old _errors.json if it exists (start fresh)\n const errorsPath = join(distDir, '_errors.json');\n if (existsSync(errorsPath)) {\n unlinkSync(errorsPath);\n }\n copyDirectory(projectPaths.fonts(), join(distDir, \"fonts\"));\n copyDirectory(projectPaths.images(), join(distDir, \"images\"));\n copyDirectory(projectPaths.icons(), join(distDir, \"icons\"));\n copyDirectory(projectPaths.assets(), join(distDir, \"assets\"));\n copyDirectory(projectPaths.videos(), join(distDir, \"videos\"));\n\n // Copy libraries folder (downloaded external JS/CSS files)\n const librariesDir = join(projectPaths.project, \"libraries\");\n if (existsSync(librariesDir)) {\n copyDirectory(librariesDir, join(distDir, \"libraries\"));\n }\n\n // Copy functions folder for Cloudflare Pages\n const functionsDir = projectPaths.functions();\n if (existsSync(functionsDir)) {\n copyDirectory(functionsDir, join(distDir, \"functions\"));\n }\n\n // Copy user-created root files for static hosting\n const hostingFiles: string[] = [];\n const rootFilesToCopy = [\n '_headers', // Netlify/Cloudflare headers\n '_redirects', // Netlify/Cloudflare redirects\n 'llms.txt', // LLM context\n 'humans.txt', // Team credits\n 'ads.txt', // Ad verification\n 'security.txt', // Security contact\n 'CNAME', // GitHub Pages domain\n 'manifest.json', // PWA manifest\n 'site.webmanifest', // PWA manifest (alt)\n ];\n\n for (const file of rootFilesToCopy) {\n const filePath = join(projectPaths.project, file);\n if (existsSync(filePath)) {\n copyFileSync(filePath, join(distDir, file));\n hostingFiles.push(file);\n }\n }\n\n // Copy .well-known directory if exists\n const wellKnownDir = join(projectPaths.project, '.well-known');\n if (existsSync(wellKnownDir)) {\n copyDirectory(wellKnownDir, join(distDir, '.well-known'));\n hostingFiles.push('.well-known/');\n }\n\n const parts = ['Assets'];\n if (existsSync(functionsDir)) parts.push('functions');\n if (hostingFiles.length > 0) parts.push(hostingFiles.join(', '));\n console.log(`\u2705 ${parts.join(', ')} copied\\n`);\n\n // Load all global components\n const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());\n const globalComponents: Record<string, ComponentDefinition> = {};\n components.forEach((value, key) => {\n globalComponents[key] = value;\n });\n\n for (const warning of warnings) console.warn(`\u26A0\uFE0F ${warning}`);\n for (const error of errors) console.error(`\u274C ${error}`);\n console.log(`\u2705 Loaded ${components.size} global component(s)\\n`);\n\n // Initialize CMS service for CMSList rendering\n const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());\n const cmsService = new CMSService(cmsProvider);\n await cmsService.initialize();\n console.log(`\u2705 CMS service initialized\\n`);\n\n // Load all pages\n const pagesDir = projectPaths.pages();\n if (!existsSync(pagesDir)) {\n console.error(\"\u274C Pages directory not found!\");\n process.exit(1);\n }\n\n // Recursively collect all .json page files (supports nested folders like pages/a/b.json)\n const pageFiles: string[] = [];\n function scanPagesDir(dir: string, prefix: string): void {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.json')) {\n pageFiles.push(prefix ? `${prefix}/${entry.name}` : entry.name);\n } else if (entry.isDirectory()) {\n scanPagesDir(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);\n }\n }\n }\n scanPagesDir(pagesDir, '');\n \n if (pageFiles.length === 0) {\n console.warn(\"\u26A0\uFE0F No pages found in ./pages directory\");\n return;\n }\n\n console.log(`\uD83D\uDCC4 Found ${pageFiles.length} page(s) to build\\n`);\n\n // First pass: collect all slug mappings and page-level libraries\n const slugMappings: SlugMap[] = [];\n const allPageLibraries: LibrariesConfig[] = [];\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n if (pageContent) {\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n if (pageData.meta?.slugs) {\n const pageId = basePath === '/' ? 'index' : basePath.substring(1);\n slugMappings.push({ pageId, slugs: pageData.meta.slugs });\n }\n if (pageData.meta?.libraries) {\n allPageLibraries.push(pageData.meta.libraries as LibrariesConfig);\n }\n } catch { /* ignore parse errors in first pass */ }\n }\n }\n\n // Generate _headers from CSP config, auto-including library CDN domains\n // Always regenerate when CSP config exists \u2014 overwrites any stale _headers file\n // that may have been copied from the project root\n {\n await configService.load();\n const cspConfig = configService.getCSP();\n if (cspConfig && Object.keys(cspConfig).length > 0) {\n // Collect all library sources: global + component + page-level\n // Note: we concatenate (not mergeLibraries) because _headers applies globally \u2014\n // we need the union of ALL origins, regardless of per-page merge modes\n const globalLibraries = configService.getLibraries();\n const componentLibraries = collectComponentLibraries(globalComponents);\n const allJs = [\n ...(globalLibraries.js || []),\n ...(componentLibraries.js || []),\n ...allPageLibraries.flatMap(p => p.js || []),\n ];\n const allCss = [\n ...(globalLibraries.css || []),\n ...(componentLibraries.css || []),\n ...allPageLibraries.flatMap(p => p.css || []),\n ];\n const allLibs: LibrariesConfig = { js: allJs, css: allCss };\n\n // Filter out CSS libs disabled for build before extracting CSP origins\n const buildLibs = filterLibrariesByContext(allLibs, 'build');\n\n // Extract CDN origins from all library URLs\n const { scriptOrigins, styleOrigins } = extractLibraryOrigins(buildLibs);\n\n const extraScripts = [\n ...(cspConfig.scriptSrc || []),\n ...Array.from(scriptOrigins),\n ].join(' ');\n const extraStyles = [\n ...(cspConfig.styleSrc || []),\n ...Array.from(styleOrigins),\n ].join(' ');\n const extraConnect = cspConfig.connectSrc?.join(' ') || '';\n const extraFrames = cspConfig.frameSrc?.join(' ') || '';\n const extraFonts = cspConfig.fontSrc?.join(' ') || '';\n const extraImgs = cspConfig.imgSrc?.join(' ') || '';\n\n const cspDirectives = [\n \"default-src 'self'\",\n `script-src 'self' 'unsafe-inline' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),\n `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),\n `img-src 'self' data: https: ${extraImgs}`.trim(),\n `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),\n `frame-src https://player.vimeo.com https://vimeo.com https://www.youtube.com https://www.youtube-nocookie.com ${extraFrames}`.trim(),\n `font-src 'self' data: ${extraFonts}`.trim(),\n \"media-src 'self' https: blob:\"\n ].join('; ');\n\n const headersContent = `/*\\n Content-Security-Policy: ${cspDirectives}\\n`;\n writeFileSync(join(distDir, '_headers'), headersContent);\n console.log(`\u2705 Generated _headers with CSP (auto-included ${scriptOrigins.size + styleOrigins.size} library origin(s))\\n`);\n }\n }\n\n let successCount = 0;\n let errorCount = 0;\n\n // Build each page for each locale\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n\n if (!pageContent) {\n console.warn(`\u26A0\uFE0F Skipping ${basePath} (empty file)`);\n errorCount++;\n continue;\n }\n\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n\n // Skip draft pages in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft: ${basePath}`);\n continue;\n }\n\n // Get translated slugs from page meta (if available)\n const slugs = pageData.meta?.slugs;\n\n // Generate HTML for each locale\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n const baseUrl = siteUrl || \"\";\n\n // Build the URL path that will be used for this locale\n const urlPath = getDisplayPath(basePath, locale, i18nConfig.defaultLocale, slugs);\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: urlPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n // Insert script reference before </body>\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (trackingScript) {\n finalHtml = injectTrackingScript(finalHtml, trackingScript);\n }\n\n // Determine locale-specific output path with translated slug\n const outputPath = getLocalizedOutputPath(basePath, locale, i18nConfig.defaultLocale, distDir, slugs);\n\n // Ensure directory exists\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf(\"/\"));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Debug: show end of HTML\n if (urlPath === '/') {\n console.log('[DEBUG] Last 500 chars of HTML:', finalHtml.slice(-500));\n }\n\n await writeFile(outputPath, finalHtml, \"utf-8\");\n\n generatedUrls.add(urlPath);\n console.log(`\u2705 Built: ${urlPath} \u2192 ${outputPath}`);\n successCount++;\n }\n\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error building ${basePath}:`, error);\n buildErrors.push({\n file: `pages/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'render',\n });\n errorCount++;\n }\n }\n\n // Build CMS templates from root templates/ directory\n const templatesDir = projectPaths.templates();\n const staticCollections = new Map<string, ClientDataCollection>();\n const cmsResult = await buildCMSTemplates(\n templatesDir,\n globalComponents,\n i18nConfig,\n slugMappings,\n distDir,\n cmsService,\n generatedUrls,\n staticCollections,\n siteUrl,\n trackingScript\n );\n successCount += cmsResult.success;\n errorCount += cmsResult.errors;\n\n // Generate static data files for collections with 'static' strategy\n await generateStaticDataFiles(staticCollections, distDir);\n\n // Generate A/B testing functions if experiments are running\n if (runningExperiments.length > 0) {\n await generateABFunctions(runningExperiments, distDir);\n console.log(`\\n\uD83E\uDDEA A/B testing functions generated (middleware, tracker, results API)`);\n }\n\n // Generate SEO files (robots.txt and sitemap.xml)\n if (siteUrl) {\n await generateRobotsTxt(siteUrl, distDir);\n await generateSitemap([...generatedUrls], siteUrl, distDir);\n console.log(`\\n\uD83D\uDD0D SEO files generated (robots.txt, sitemap.xml)`);\n } else {\n console.warn(`\\n\u26A0\uFE0F Skipping SEO files: siteUrl not configured in project.config.json`);\n }\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(`\u2728 Build complete!`);\n console.log(` \u2705 Success: ${successCount}`);\n if (errorCount > 0) {\n console.log(` \u274C Errors: ${errorCount}`);\n }\n console.log(`\\n\uD83D\uDCE6 Production files in /dist:`);\n console.log(` - *.html (Static pages with vanilla JS)`);\n console.log(` - fonts/ (Custom fonts)`);\n console.log(` - images/ (Image assets)`);\n console.log(` - icons/ (Favicon and icons)`);\n if (staticCollections.size > 0) {\n console.log(` - data/ (CMS collection data for client filtering)`);\n }\n if (existsSync(functionsDir)) {\n console.log(` - functions/ (Cloudflare Pages Functions)`);\n }\n if (runningExperiments.length > 0) {\n console.log(` - A/B testing (middleware + tracking injected)`);\n }\n if (siteUrl) {\n console.log(` - robots.txt, sitemap.xml (SEO)`);\n }\n console.log(` - No React, no client-router \u2713`);\n\n // Collect component JS validation errors\n const jsErrors = getJSValidationErrors();\n for (const { component, error } of jsErrors) {\n buildErrors.push({\n file: `components/${component}`,\n message: error,\n type: 'minify',\n });\n }\n\n // Write build errors to _errors.json for static server overlay\n if (buildErrors.length > 0) {\n // Deduplicate errors by message (same error may occur on multiple pages)\n const seenMessages = new Set<string>();\n const uniqueErrors = buildErrors.filter(err => {\n if (seenMessages.has(err.message)) return false;\n seenMessages.add(err.message);\n return true;\n });\n\n const errorsData: BuildErrorsData = {\n errors: uniqueErrors,\n timestamp: Date.now(),\n };\n await writeFile(errorsPath, JSON.stringify(errorsData, null, 2), 'utf-8');\n const countMsg = uniqueErrors.length === buildErrors.length\n ? `${uniqueErrors.length} error${uniqueErrors.length === 1 ? '' : 's'}`\n : `${uniqueErrors.length} unique error${uniqueErrors.length === 1 ? '' : 's'} (affected ${buildErrors.length} files)`;\n console.log(`\\n\u26A0\uFE0F Build errors written to dist/_errors.json (${countMsg})`);\n }\n}\n\n\n", "/**\n * A/B Testing Functions Generator\n * Generates Cloudflare Pages Functions for traffic splitting and event tracking\n * Only called at build time when experiments are running\n */\n\nimport type { Experiment } from '../../shared/types/experiments';\n\n/**\n * Generate the _middleware.ts content for traffic splitting\n */\nexport function generateMiddleware(experiments: Experiment[]): string {\n const running = experiments.filter(e => e.status === 'running');\n if (running.length === 0) return '';\n\n // Embed experiment config as JSON\n const configJSON = JSON.stringify(running.map(e => ({\n id: e.id,\n controlBranch: e.controlBranch,\n controlWeight: e.controlWeight,\n variants: e.variants.map(v => ({\n branch: v.branch,\n weight: v.weight,\n deployUrl: v.deployUrl,\n })),\n })));\n\n return `/**\n * A/B Testing Traffic Splitting Middleware\n * Auto-generated by Meno build - do not edit manually\n */\n\ninterface Env {\n AB_DB?: D1Database;\n}\n\ninterface ExperimentConfig {\n id: string;\n controlBranch: string;\n controlWeight: number;\n variants: Array<{ branch: string; weight: number; deployUrl: string }>;\n}\n\nconst EXPERIMENTS: ExperimentConfig[] = ${configJSON};\n\nfunction getCookie(request: Request, name: string): string | null {\n const cookieHeader = request.headers.get('Cookie');\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp('(?:^|;\\\\\\\\s*)' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction assignVariant(experiment: ExperimentConfig): string {\n const rand = Math.random() * 100;\n let cumulative = experiment.controlWeight;\n if (rand < cumulative) return 'control';\n for (const variant of experiment.variants) {\n cumulative += variant.weight;\n if (rand < cumulative) return variant.branch;\n }\n return 'control';\n}\n\nexport async function onRequest(context: { request: Request; next: () => Promise<Response>; env: Env }) {\n const url = new URL(context.request.url);\n\n // Skip API routes and static assets\n if (url.pathname.startsWith('/api/') || url.pathname.match(/\\\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) {\n return context.next();\n }\n\n // Use first running experiment (single experiment at a time for simplicity)\n const experiment = EXPERIMENTS[0];\n if (!experiment) return context.next();\n\n // Check for existing variant assignment (sticky sessions)\n let variant = getCookie(context.request, 'meno_variant');\n\n // If no cookie, assign a variant\n if (!variant) {\n variant = assignVariant(experiment);\n }\n\n let response: Response;\n\n if (variant === 'control') {\n // Control: serve local assets (pass through)\n response = await context.next();\n } else {\n // Variant: proxy to branch preview deploy\n const variantConfig = experiment.variants.find(v => v.branch === variant);\n if (!variantConfig) {\n response = await context.next();\n } else {\n // Fetch from the variant's deploy URL\n const variantUrl = new URL(url.pathname + url.search, variantConfig.deployUrl);\n try {\n const proxyResponse = await fetch(variantUrl.toString(), {\n method: context.request.method,\n headers: context.request.headers,\n });\n response = new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers: new Headers(proxyResponse.headers),\n });\n } catch {\n // Fallback to control if variant fetch fails\n response = await context.next();\n variant = 'control';\n }\n }\n }\n\n // Set variant cookie (30-day expiry)\n const headers = new Headers(response.headers);\n headers.append(\n 'Set-Cookie',\n \\`meno_variant=\\${encodeURIComponent(variant!)}; Path=/; Max-Age=2592000; SameSite=Lax\\`\n );\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n`;\n}\n\n/**\n * Generate the api/ab-track.ts content for event collection\n */\nexport function generateTrackFunction(): string {\n return `/**\n * A/B Testing Event Tracker\n * Auto-generated by Meno build - do not edit manually\n * POST /api/ab-track - stores pageview/conversion events in D1\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface TrackEvent {\n experimentId: string;\n visitorId: string;\n variant: string;\n eventType: 'pageview' | 'conversion';\n goalId?: string;\n url?: string;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n waitUntil: (promise: Promise<unknown>) => void;\n}\n\nexport async function onRequestPost(context: PagesContext<Env>): Promise<Response> {\n try {\n const body: TrackEvent = await context.request.json();\n\n // Validate required fields\n if (!body.experimentId || !body.visitorId || !body.variant || !body.eventType) {\n return new Response(null, { status: 400 });\n }\n\n // Validate event type\n if (body.eventType !== 'pageview' && body.eventType !== 'conversion') {\n return new Response(null, { status: 400 });\n }\n\n // Insert event into D1\n await context.env.AB_DB.prepare(\n 'INSERT INTO ab_events (experiment_id, visitor_id, variant, event_type, goal_id, url, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)'\n ).bind(\n body.experimentId,\n body.visitorId,\n body.variant,\n body.eventType,\n body.goalId || null,\n body.url || null,\n Date.now()\n ).run();\n\n return new Response(null, { status: 204 });\n } catch {\n return new Response(null, { status: 500 });\n }\n}\n`;\n}\n\n/**\n * Generate the api/ab-results.ts content for results aggregation\n */\nexport function generateResultsFunction(): string {\n return `/**\n * A/B Testing Results API\n * Auto-generated by Meno build - do not edit manually\n * GET /api/ab-results?experiment=<id> - returns aggregated results with significance\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n}\n\ninterface VariantResult {\n variant: string;\n visitors: number;\n conversions: number;\n conversionRate: number;\n lift?: number;\n pValue?: number;\n isSignificant: boolean;\n}\n\n/**\n * Two-proportion z-test for statistical significance\n */\nfunction zTest(\n conversionsA: number, visitorsA: number,\n conversionsB: number, visitorsB: number\n): number {\n if (visitorsA === 0 || visitorsB === 0) return 1;\n\n const pA = conversionsA / visitorsA;\n const pB = conversionsB / visitorsB;\n const pPool = (conversionsA + conversionsB) / (visitorsA + visitorsB);\n\n if (pPool === 0 || pPool === 1) return 1;\n\n const se = Math.sqrt(pPool * (1 - pPool) * (1 / visitorsA + 1 / visitorsB));\n if (se === 0) return 1;\n\n const z = Math.abs(pA - pB) / se;\n\n // Approximate two-tailed p-value using rational approximation\n const t = 1 / (1 + 0.2316419 * z);\n const d = 0.3989422804014327;\n const p = d * Math.exp(-z * z / 2) * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));\n return 2 * p;\n}\n\nexport async function onRequestGet(context: PagesContext<Env>): Promise<Response> {\n const url = new URL(context.request.url);\n const experimentId = url.searchParams.get('experiment');\n\n if (!experimentId) {\n return Response.json({ error: 'Missing experiment parameter' }, { status: 400 });\n }\n\n try {\n // Get unique visitors per variant\n const visitorsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as visitors FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'pageview\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Get conversions per variant\n const conversionsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as conversions FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'conversion\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Build results map\n const visitorMap = new Map<string, number>();\n const conversionMap = new Map<string, number>();\n\n for (const row of (visitorsResult.results || [])) {\n visitorMap.set(row.variant as string, row.visitors as number);\n }\n for (const row of (conversionsResult.results || [])) {\n conversionMap.set(row.variant as string, row.conversions as number);\n }\n\n // Get all variant names\n const allVariants = new Set([...visitorMap.keys(), ...conversionMap.keys()]);\n\n // Calculate results\n const variants: VariantResult[] = [];\n let controlVisitors = 0;\n let controlConversions = 0;\n\n for (const variant of allVariants) {\n const visitors = visitorMap.get(variant) || 0;\n const conversions = conversionMap.get(variant) || 0;\n const conversionRate = visitors > 0 ? conversions / visitors : 0;\n\n if (variant === 'control') {\n controlVisitors = visitors;\n controlConversions = conversions;\n }\n\n variants.push({\n variant,\n visitors,\n conversions,\n conversionRate,\n isSignificant: false,\n });\n }\n\n // Calculate lift and significance for non-control variants\n const controlRate = controlVisitors > 0 ? controlConversions / controlVisitors : 0;\n for (const result of variants) {\n if (result.variant !== 'control' && controlVisitors > 0) {\n result.lift = controlRate > 0\n ? ((result.conversionRate - controlRate) / controlRate) * 100\n : 0;\n result.pValue = zTest(\n controlConversions, controlVisitors,\n result.conversions, result.visitors\n );\n result.isSignificant = result.pValue < 0.05;\n }\n }\n\n // Sort: control first, then by variant name\n variants.sort((a, b) => {\n if (a.variant === 'control') return -1;\n if (b.variant === 'control') return 1;\n return a.variant.localeCompare(b.variant);\n });\n\n return Response.json({\n experimentId,\n variants,\n }, {\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Cache-Control': 'no-cache',\n }\n });\n } catch (error) {\n return Response.json({ error: 'Failed to query results' }, { status: 500 });\n }\n}\n`;\n}\n", "/**\n * A/B Testing Tracking Script Generator\n * Generates a lightweight client-side tracking script to be injected into HTML\n */\n\nimport type { ConversionGoal } from '../../shared/types/experiments';\n\n/**\n * Generate the tracking script content with embedded experiment config\n */\nexport function generateTrackingScript(experimentId: string, goals: ConversionGoal[]): string {\n const goalsJSON = JSON.stringify(goals);\n\n return `(function(){\nvar EXP_ID=${JSON.stringify(experimentId)};\nvar GOALS=${goalsJSON};\n\nfunction getCookie(n){var m=document.cookie.match(new RegExp('(?:^|;\\\\\\\\s*)'+n+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}\nfunction setCookie(n,v,d){var e=new Date();e.setTime(e.getTime()+d*864e5);document.cookie=n+'='+encodeURIComponent(v)+';path=/;expires='+e.toUTCString()+';SameSite=Lax'}\n\nvar variant=getCookie('meno_variant')||'control';\nvar visitor=getCookie('meno_visitor');\nif(!visitor){visitor=Math.random().toString(36).slice(2)+Date.now().toString(36);setCookie('meno_visitor',visitor,365)}\n\nfunction track(type,goalId){\ntry{navigator.sendBeacon('/api/ab-track',JSON.stringify({experimentId:EXP_ID,visitorId:visitor,variant:variant,eventType:type,goalId:goalId||null,url:location.pathname}))}catch(e){}\n}\n\ntrack('pageview');\n\nGOALS.forEach(function(g){\nif(g.type==='click'&&g.selector){\ndocument.addEventListener('click',function(e){\nif(e.target&&e.target.closest&&e.target.closest(g.selector)){track('conversion',g.id)}\n})\n}\nif(g.type==='navigation'&&g.url){\nif(location.pathname===g.url||location.href.indexOf(g.url)>-1){track('conversion',g.id)}\n}\nif(g.type==='custom'&&g.event){\nwindow.addEventListener(g.event,function(){track('conversion',g.id)})\n}\n});\n})();`;\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMA,SAAS,YAAY,aAAa,WAAW,QAAQ,UAAU,cAAc,YAAY,qBAAqB;AAC9G,SAAS,WAAW,gBAAgB;AACpC,SAAS,YAAY;AAErB,SAAS,kBAAkB;;;ACCpB,SAAS,mBAAmB,aAAmC;AACpE,QAAM,UAAU,YAAY,OAAO,OAAK,EAAE,WAAW,SAAS;AAC9D,MAAI,QAAQ,WAAW,EAAG,QAAO;AAGjC,QAAM,aAAa,KAAK,UAAU,QAAQ,IAAI,QAAM;AAAA,IAClD,IAAI,EAAE;AAAA,IACN,eAAe,EAAE;AAAA,IACjB,eAAe,EAAE;AAAA,IACjB,UAAU,EAAE,SAAS,IAAI,QAAM;AAAA,MAC7B,QAAQ,EAAE;AAAA,MACV,QAAQ,EAAE;AAAA,MACV,WAAW,EAAE;AAAA,IACf,EAAE;AAAA,EACJ,EAAE,CAAC;AAEH,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0CAgBiC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqFpD;AAKO,SAAS,wBAAgC;AAC9C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2DT;AAKO,SAAS,0BAAkC;AAChD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkJT;;;AC/UO,SAAS,uBAAuB,cAAsB,OAAiC;AAC5F,QAAM,YAAY,KAAK,UAAU,KAAK;AAEtC,SAAO;AAAA,aACI,KAAK,UAAU,YAAY,CAAC;AAAA,YAC7B,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6BrB;;;AFHA,IAAM,cAA4B,CAAC;AAK5B,SAAS,YAAY,SAAyB;AACnD,SAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC;AACtE;AAKO,SAAS,aAAa,KAAkB;AAC7C,QAAM,QAAkB,CAAC;AAGzB,MAAI,IAAI,UAAU;AAChB,UAAM,MAAM,IAAI;AAChB,QAAI,IAAI,KAAM,OAAM,KAAK,SAAS,IAAI,IAAI,EAAE;AAC5C,QAAI,IAAI,SAAS,OAAW,OAAM,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,UAAU,CAAC,EAAE;AAC5E,QAAI,IAAI,SAAU,OAAM,KAAK,KAAK,IAAI,QAAQ,EAAE;AAAA,EAClD;AAGA,MAAI,IAAI,SAAS;AACf,UAAM,KAAK,IAAI,OAAO;AAAA,EACxB,WAAW,IAAI,MAAM;AACnB,UAAM,KAAK,IAAI,IAAI;AAAA,EACrB;AAGA,MAAI,MAAM,WAAW,GAAG;AACtB,QAAI;AACF,aAAO,KAAK,UAAU,KAAK,MAAM,CAAC;AAAA,IACpC,QAAQ;AACN,aAAO,OAAO,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,eAAeA,UAAS,MAA+B;AACrD,QAAM,SAAS,MAAM,SAAgB,IAAI;AACzC,MAAI,OAAO,SAAS;AAClB,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,IAAI,MAAM;AAAA,EAAoC,OAAO,OAAO,KAAK,MAAM,CAAC,EAAE;AAClF;AAMA,IAAM,cAAc,oBAAI,IAAoB;AAM5C,eAAe,cAAc,WAAmB,SAAkC;AAEhF,QAAM,WAAW,MAAMA,UAAS,SAAS;AACzC,QAAM,OAAO,YAAY,QAAQ;AAGjC,MAAI,YAAY,IAAI,IAAI,GAAG;AACzB,WAAO,YAAY,IAAI,IAAI;AAAA,EAC7B;AAGA,QAAM,aAAa,KAAK,SAAS,UAAU;AAC3C,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,cAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,EAC3C;AAGA,QAAM,aAAa,aAAa,IAAI;AACpC,QAAM,WAAW,KAAK,SAAS,YAAY,GAAG,IAAI,KAAK;AACvD,QAAM,UAAU,UAAU,UAAU,OAAO;AAG3C,cAAY,IAAI,MAAM,UAAU;AAEhC,SAAO;AACT;AAKA,SAAS,cAAc,KAAa,MAAoB;AACtD,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB;AAAA,EACF;AAEA,MAAI,CAAC,WAAW,IAAI,GAAG;AACrB,cAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,EACrC;AAEA,QAAM,QAAQ,YAAY,GAAG;AAE7B,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK,IAAI;AAC9B,UAAM,WAAW,KAAK,MAAM,IAAI;AAChC,UAAM,OAAO,SAAS,OAAO;AAE7B,QAAI,KAAK,YAAY,GAAG;AACtB,oBAAc,SAAS,QAAQ;AAAA,IACjC,OAAO;AACL,mBAAa,SAAS,QAAQ;AAAA,IAChC;AAAA,EACF;AACF;AAQO,SAAS,uBACd,UACA,QACA,eACA,SACA,OACQ;AAER,MAAI;AACJ,MAAI,SAAS,MAAM,MAAM,GAAG;AAC1B,WAAO,MAAM,MAAM;AAAA,EACrB,WAAW,aAAa,KAAK;AAC3B,WAAO;AAAA,EACT,OAAO;AACL,WAAO,SAAS,UAAU,CAAC;AAAA,EAC7B;AAGA,QAAM,WAAW,SAAS,KAAK,eAAe,GAAG,IAAI;AAErD,MAAI,WAAW,eAAe;AAC5B,WAAO,GAAG,OAAO,IAAI,QAAQ;AAAA,EAC/B;AACA,SAAO,GAAG,OAAO,IAAI,MAAM,IAAI,QAAQ;AACzC;AAKO,SAAS,eACd,UACA,QACA,eACA,OACQ;AAER,MAAI;AACJ,MAAI,SAAS,MAAM,MAAM,GAAG;AAC1B,WAAO,MAAM,MAAM;AAAA,EACrB,WAAW,aAAa,KAAK;AAC3B,WAAO;AAAA,EACT,OAAO;AACL,WAAO,SAAS,UAAU,CAAC;AAAA,EAC7B;AAEA,MAAI,WAAW,eAAe;AAC5B,WAAO,SAAS,KAAK,MAAM,IAAI,IAAI;AAAA,EACrC;AACA,SAAO,SAAS,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,IAAI,IAAI;AACxD;AAKA,eAAsB,kBAAkB,SAAiB,SAAgC;AACvF,QAAM,UAAU;AAAA;AAAA;AAAA,WAGP,OAAO;AAAA;AAEhB,QAAM,UAAU,KAAK,SAAS,YAAY,GAAG,SAAS,OAAO;AAC/D;AAKA,eAAsB,gBAAgB,MAAgB,SAAiB,SAAgC;AAErG,QAAM,aAAa,CAAC,GAAG,IAAI,EAAE,KAAK;AAElC,QAAM,aAAa,WAChB,IAAI,SAAO,eAAe,OAAO,GAAG,GAAG,cAAc,EACrD,KAAK,IAAI;AAEZ,QAAM,UAAU;AAAA;AAAA,EAEhB,UAAU;AAAA;AAAA;AAGV,QAAM,UAAU,KAAK,SAAS,aAAa,GAAG,SAAS,OAAO;AAChE;AAKA,SAAS,YAAkB;AACzB,QAAM,UAAU,aAAa,KAAK;AAClC,MAAI,CAAC,WAAW,OAAO,GAAG;AACxB,cAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC;AAAA,EACF;AAEA,QAAM,QAAQ,YAAY,OAAO;AACjC,MAAI,UAAU;AAEd,aAAW,QAAQ,OAAO;AAExB,QACE,SAAS,WACT,SAAS,YACT,SAAS,WACT,SAAS,YACT,SAAS,UACT;AACA;AAAA,IACF;AAGA,QAAI;AACF,YAAM,WAAW,KAAK,SAAS,IAAI;AACnC,YAAM,OAAO,SAAS,QAAQ;AAE9B,UAAI,KAAK,YAAY,GAAG;AACtB,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD,OAAO;AACL,eAAO,UAAU,EAAE,OAAO,KAAK,CAAC;AAAA,MAClC;AACA;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,KAAK,kCAAwB,IAAI,KAAK,KAAK;AAAA,IACrD;AAAA,EACF;AAEA,MAAI,UAAU,GAAG;AACf,YAAQ,IAAI,qBAAc,OAAO;AAAA,CAAsB;AAAA,EACzD;AACF;AAKO,SAAS,UAAU,UAA6B;AACrD,SAAO,SAAS,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM;AAC7D;AAMO,SAAS,iBACd,YACA,MACA,WACA,QACA,YACQ;AAER,MAAI,OAAO,KAAK,SAAS,KAAK,KAAK,SAAS,KAAK;AAGjD,MAAI,YAAY,IAAI,GAAG;AACrB,WAAO,iBAAiB,MAAM,QAAQ,UAAU;AAAA,EAClD;AAEA,SAAO,WAAW,QAAQ,YAAY,OAAO,IAAI,CAAC;AACpD;AAMA,eAAe,wBACb,mBACA,SACe;AACf,MAAI,kBAAkB,SAAS,EAAG;AAElC,UAAQ,IAAI;AAAA,0CAAsC;AAElD,aAAW,CAAC,cAAc,IAAI,KAAK,mBAAmB;AACpD,UAAM,UAAU,KAAK,SAAS,QAAQ,YAAY;AAClD,QAAI,CAAC,WAAW,OAAO,GAAG;AACxB,gBAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IACxC;AACA,UAAM,WAAW,KAAK,SAAS,YAAY;AAC3C,UAAM,UAAU,UAAU,KAAK,UAAU,KAAK,KAAK,GAAG,OAAO;AAC7D,YAAQ,IAAI,mBAAc,YAAY,gBAAgB,KAAK,MAAM,MAAM,SAAS;AAAA,EAClF;AACF;AAKA,eAAe,kBACb,cACA,kBACA,YACA,cACA,SACA,YACA,eACA,mBACA,SACA,kBAC8C;AAC9C,MAAI,eAAe;AACnB,MAAI,aAAa;AAEjB,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,WAAO,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,EACjC;AAEA,QAAM,gBAAgB,YAAY,YAAY,EAAE,OAAO,OAAK,EAAE,SAAS,OAAO,CAAC;AAE/E,MAAI,cAAc,WAAW,GAAG;AAC9B,WAAO,EAAE,SAAS,GAAG,QAAQ,EAAE;AAAA,EACjC;AAEA,UAAQ,IAAI;AAAA,uBAAmB,cAAc,MAAM;AAAA,CAAuB;AAE1E,aAAW,QAAQ,eAAe;AAChC,UAAM,kBAAkB,MAAM,aAAa,KAAK,cAAc,IAAI,CAAC;AACnE,QAAI,CAAC,gBAAiB;AAEtB,QAAI;AACF,YAAM,WAAW,UAAoB,eAAe;AAGpD,YAAM,aAAa,QAAQ,IAAI,mBAAmB;AAClD,UAAI,SAAS,MAAM,UAAU,QAAQ,CAAC,YAAY;AAChD,gBAAQ,IAAI,0CAAgC,IAAI,EAAE;AAClD;AAAA,MACF;AAEA,UAAI,CAAC,UAAU,QAAQ,GAAG;AACxB,gBAAQ,KAAK,iBAAO,IAAI,kDAAkD;AAC1E;AAAA,MACF;AAEA,YAAM,YAAY,SAAS,KAAM;AACjC,cAAQ,IAAI,6BAAsB,UAAU,EAAE,EAAE;AAGhD,YAAM,QAAQ,MAAM,WAAW,WAAW,EAAE,YAAY,UAAU,GAAG,CAAC;AAEtE,UAAI,MAAM,WAAW,GAAG;AACtB,gBAAQ,IAAI,0CAAgC,UAAU,EAAE,GAAG;AAC3D;AAAA,MACF;AAEA,cAAQ,IAAI,YAAY,MAAM,MAAM,UAAU;AAI9C,UAAI;AACJ,UAAI,UAAU,YAAY,SAAS;AACjC,cAAM,iBAAiB,MAAM,OAAO,UAAQ,qBAAqB,IAAI,CAAC;AACtE,cAAM,aAAa,kBAAkB,UAAU,IAAI,gBAAgB,UAAU,UAAU;AACvF,YAAI,YAAY;AACd,cAAI,WAAW,aAAa,UAAU;AAEpC,oCAAwB,oBAAI,IAAI,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC;AAC5D,oBAAQ,IAAI,sCAA+B,WAAW,MAAM,MAAM,WAAW,WAAW,OAAO,QAAQ,UAAU,KAAK,UAAU;AAAA,UAClI,WAAW,WAAW,aAAa,UAAU;AAE3C,8BAAkB,IAAI,UAAU,IAAI,UAAU;AAC9C,oBAAQ,IAAI,sCAA+B,WAAW,MAAM,MAAM,uBAAkB,UAAU,EAAE,aAAa;AAAA,UAC/G;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,QAAQ,OAAO;AACxB,mBAAW,gBAAgB,WAAW,SAAS;AAC7C,gBAAM,SAAS,aAAa;AAG5B,gBAAMC,cAAa,QAAQ,IAAI,mBAAmB;AAClD,cAAI,CAACA,eAAc,qBAAqB,MAAM,MAAM,GAAG;AACrD,oBAAQ,IAAI,oCAA0B,KAAK,aAAa,KAAK,GAAG,KAAK,MAAM,GAAG;AAC9E;AAAA,UACF;AAEA,gBAAM,UAAU,WAAW;AAC3B,gBAAM,WAAW,iBAAiB,UAAU,YAAY,MAAM,UAAU,WAAW,QAAQ,UAAU;AAGrG,gBAAM,cAAuB,EAAE,GAAG,MAAM,MAAM,SAAS;AAGvD,gBAAM,SAAS,MAAM,gBAAgB;AAAA,YACnC;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YACV;AAAA,YACA,gBAAgB;AAAA,YAChB;AAAA,YACA;AAAA,YACA,YAAY,EAAE,KAAK,YAAY;AAAA,YAC/B;AAAA,YACA,kBAAkB;AAAA,YAClB,eAAe,SAAS,MAAM;AAAA,YAC9B,gBAAgB,SAAS,MAAM;AAAA,YAC/B;AAAA,YACA,mBAAmB;AAAA,UACrB,CAAC;AAGD,cAAI,YAAY,OAAO;AACvB,cAAI,OAAO,YAAY;AACrB,kBAAM,aAAa,MAAM,cAAc,OAAO,YAAY,OAAO;AACjE,wBAAY,UAAU,QAAQ,WAAW,kBAAkB,UAAU;AAAA,QAA4B;AAAA,UACnG;AAGA,cAAI,kBAAkB;AACpB,wBAAY,qBAAqB,WAAW,gBAAgB;AAAA,UAC9D;AAEA,gBAAM,aAAa,WAAW,WAAW,gBACrC,GAAG,OAAO,GAAG,QAAQ,UACrB,GAAG,OAAO,IAAI,MAAM,GAAG,QAAQ;AAEnC,gBAAM,YAAY,WAAW,UAAU,GAAG,WAAW,YAAY,GAAG,CAAC;AACrE,cAAI,aAAa,CAAC,WAAW,SAAS,GAAG;AACvC,sBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,UAC1C;AAEA,gBAAM,UAAU,YAAY,WAAW,OAAO;AAE9C,gBAAM,cAAc,WAAW,WAAW,gBAAgB,WAAW,IAAI,MAAM,GAAG,QAAQ;AAC1F,wBAAc,IAAI,WAAW;AAC7B,kBAAQ,IAAI,aAAQ,WAAW,EAAE;AACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAY;AAEnB,UAAI;AAEJ,UAAI,iBAAiB,OAAO;AAE1B,YAAI,YAAY,SAAS,MAAM,QAAQ,MAAM,MAAM,GAAG;AACpD,yBAAe,MAAM,OAAO,IAAI,CAAC,MAAW,EAAE,SAAS,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM;AAAA,QAC5F,WAES,MAAM,OAAO;AACpB,gBAAM,WAAW,MAAM,iBAAiB,QACnC,MAAM,MAAM,SAAS,MAAM,MAAM,UAClC,OAAO,MAAM,KAAK;AACtB,yBAAe,GAAG,MAAM,SAAS,MAAM,OAAO;AAAA;AAAA;AAAA,EAAmB,QAAQ;AAAA,QAC3E,WAES,UAAU,SAAS,MAAM,QAAQ,MAAM,IAAI,GAAG;AACrD,yBAAe,MAAM,KAAK,IAAI,YAAY,EAAE,KAAK,MAAM;AAAA,QACzD,OACK;AACH,yBAAe,MAAM,SAAS,MAAM;AAAA,QACtC;AAAA,MACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AAEtD,YAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,GAAG;AAC3C,yBAAe,MAAM,KAAK,IAAI,YAAY,EAAE,KAAK,MAAM;AAAA,QACzD,OAAO;AACL,yBAAe,OAAO,KAAK;AAAA,QAC7B;AAAA,MACF,OAAO;AACL,uBAAe,OAAO,KAAK;AAAA,MAC7B;AAGA,UAAI,iBAAiB,mBAAmB,aAAa,SAAS,iBAAiB,GAAG;AAChF,YAAI;AACF,gBAAM,YAAY,QAAQ,KAAK;AAC/B,cAAI,aAAa,cAAc,qBAAqB,UAAU,SAAS,aAAa,QAAQ;AAC1F,2BAAe;AAAA,UACjB;AAAA,QACF,QAAQ;AAAA,QAAC;AAAA,MACX;AAEA,cAAQ,MAAM,2BAAsB,IAAI,KAAK,KAAK;AAClD,kBAAY,KAAK;AAAA,QACf,MAAM,aAAa,IAAI;AAAA,QACvB,SAAS;AAAA,QACT,MAAM,aAAa,SAAS,cAAc,KAAK,aAAa,SAAS,QAAQ,IAAI,WAAW;AAAA,MAC9F,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,cAAc,QAAQ,WAAW;AACrD;AAKA,eAAe,yBAAgD;AAC7D,QAAM,kBAAkB,KAAK,aAAa,SAAS,kBAAkB;AACrE,MAAI,CAAC,WAAW,eAAe,EAAG,QAAO,CAAC;AAE1C,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,iBAAiB,OAAO;AACvD,UAAM,OAAO,KAAK,MAAM,OAAO;AAC/B,UAAM,cAA4B,KAAK,eAAe,CAAC;AACvD,WAAO,YAAY,OAAO,OAAK,EAAE,WAAW,SAAS;AAAA,EACvD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAKO,SAAS,qBAAqB,MAAc,YAA4B;AAC7E,QAAM,YAAY,WAAW,UAAU;AACvC,SAAO,KAAK,QAAQ,WAAW,GAAG,SAAS;AAAA,QAAW;AACxD;AAKA,eAAe,oBAAoB,aAA2B,SAAgC;AAE5F,QAAM,oBAAoB,mBAAmB,WAAW;AACxD,MAAI,mBAAmB;AACrB,UAAM,iBAAiB,KAAK,SAAS,aAAa,gBAAgB;AAClE,UAAM,gBAAgB,KAAK,SAAS,WAAW;AAC/C,QAAI,CAAC,WAAW,aAAa,GAAG;AAC9B,gBAAU,eAAe,EAAE,WAAW,KAAK,CAAC;AAAA,IAC9C;AACA,UAAM,UAAU,gBAAgB,mBAAmB,OAAO;AAAA,EAC5D;AAGA,QAAM,eAAe,sBAAsB;AAC3C,QAAM,WAAW,KAAK,SAAS,aAAa,KAAK;AACjD,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,cAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAAA,EACzC;AACA,QAAM,UAAU,KAAK,UAAU,aAAa,GAAG,cAAc,OAAO;AAGpE,QAAM,iBAAiB,wBAAwB;AAC/C,QAAM,UAAU,KAAK,UAAU,eAAe,GAAG,gBAAgB,OAAO;AAC1E;AAKA,eAAsB,mBAAkC;AACtD,UAAQ,IAAI,kDAAsC;AAGlD,cAAY,SAAS;AACrB,yBAAuB;AAGvB,QAAM,EAAE,cAAc,IAAI,MAAM,OAAO,6BAAqC;AAC5E,gBAAc,MAAM;AAGpB,QAAM,gBAAgB,MAAM,kBAAkB;AAC9C,QAAM,UAAW,cAAuC,SAAS,QAAQ,OAAO,EAAE;AAGlF,QAAM,gBAAgB,oBAAI,IAAY;AAGtC,QAAM,qBAAqB,MAAM,uBAAuB;AACxD,MAAI,iBAAgC;AACpC,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,MAAM,mBAAmB,CAAC;AAChC,qBAAiB,uBAAuB,IAAI,IAAI,IAAI,eAAe;AACnE,YAAQ,IAAI,qCAA8B,IAAI,IAAI,MAAM,IAAI,SAAS,MAAM;AAAA,CAAgB;AAAA,EAC7F;AAGA,QAAM,aAAa,MAAM,eAAe;AACxC,UAAQ,IAAI,sBAAe,WAAW,QAAQ,IAAI,OAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,cAAc,WAAW,aAAa;AAAA,CAAK;AAGpH,QAAM,0BAA0B;AAGhC,YAAU;AAIV,cAAY,MAAM;AAGlB,UAAQ,IAAI,6BAAsB;AAClC,QAAM,UAAU,aAAa,KAAK;AAGlC,QAAM,aAAa,KAAK,SAAS,cAAc;AAC/C,MAAI,WAAW,UAAU,GAAG;AAC1B,eAAW,UAAU;AAAA,EACvB;AACA,gBAAc,aAAa,MAAM,GAAG,KAAK,SAAS,OAAO,CAAC;AAC1D,gBAAc,aAAa,OAAO,GAAG,KAAK,SAAS,QAAQ,CAAC;AAC5D,gBAAc,aAAa,MAAM,GAAG,KAAK,SAAS,OAAO,CAAC;AAC1D,gBAAc,aAAa,OAAO,GAAG,KAAK,SAAS,QAAQ,CAAC;AAC5D,gBAAc,aAAa,OAAO,GAAG,KAAK,SAAS,QAAQ,CAAC;AAG5D,QAAM,eAAe,KAAK,aAAa,SAAS,WAAW;AAC3D,MAAI,WAAW,YAAY,GAAG;AAC5B,kBAAc,cAAc,KAAK,SAAS,WAAW,CAAC;AAAA,EACxD;AAGA,QAAM,eAAe,aAAa,UAAU;AAC5C,MAAI,WAAW,YAAY,GAAG;AAC5B,kBAAc,cAAc,KAAK,SAAS,WAAW,CAAC;AAAA,EACxD;AAGA,QAAM,eAAyB,CAAC;AAChC,QAAM,kBAAkB;AAAA,IACtB;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AAEA,aAAW,QAAQ,iBAAiB;AAClC,UAAM,WAAW,KAAK,aAAa,SAAS,IAAI;AAChD,QAAI,WAAW,QAAQ,GAAG;AACxB,mBAAa,UAAU,KAAK,SAAS,IAAI,CAAC;AAC1C,mBAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,eAAe,KAAK,aAAa,SAAS,aAAa;AAC7D,MAAI,WAAW,YAAY,GAAG;AAC5B,kBAAc,cAAc,KAAK,SAAS,aAAa,CAAC;AACxD,iBAAa,KAAK,cAAc;AAAA,EAClC;AAEA,QAAM,QAAQ,CAAC,QAAQ;AACvB,MAAI,WAAW,YAAY,EAAG,OAAM,KAAK,WAAW;AACpD,MAAI,aAAa,SAAS,EAAG,OAAM,KAAK,aAAa,KAAK,IAAI,CAAC;AAC/D,UAAQ,IAAI,UAAK,MAAM,KAAK,IAAI,CAAC;AAAA,CAAW;AAG5C,QAAM,EAAE,YAAY,UAAU,OAAO,IAAI,MAAM,uBAAuB,aAAa,WAAW,CAAC;AAC/F,QAAM,mBAAwD,CAAC;AAC/D,aAAW,QAAQ,CAAC,OAAO,QAAQ;AACjC,qBAAiB,GAAG,IAAI;AAAA,EAC1B,CAAC;AAED,aAAW,WAAW,SAAU,SAAQ,KAAK,iBAAO,OAAO,EAAE;AAC7D,aAAW,SAAS,OAAQ,SAAQ,MAAM,UAAK,KAAK,EAAE;AACtD,UAAQ,IAAI,iBAAY,WAAW,IAAI;AAAA,CAAwB;AAG/D,QAAM,cAAc,IAAI,sBAAsB,aAAa,UAAU,GAAG,aAAa,IAAI,CAAC;AAC1F,QAAM,aAAa,IAAI,WAAW,WAAW;AAC7C,QAAM,WAAW,WAAW;AAC5B,UAAQ,IAAI;AAAA,CAA6B;AAGzC,QAAM,WAAW,aAAa,MAAM;AACpC,MAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,YAAQ,MAAM,mCAA8B;AAC5C,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,YAAsB,CAAC;AAC7B,WAAS,aAAa,KAAa,QAAsB;AACvD,UAAM,UAAU,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AACxD,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,OAAO,GAAG;AAClD,kBAAU,KAAK,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,MAChE,WAAW,MAAM,YAAY,GAAG;AAC9B,qBAAa,KAAK,KAAK,MAAM,IAAI,GAAG,SAAS,GAAG,MAAM,IAAI,MAAM,IAAI,KAAK,MAAM,IAAI;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACA,eAAa,UAAU,EAAE;AAEzB,MAAI,UAAU,WAAW,GAAG;AAC1B,YAAQ,KAAK,mDAAyC;AACtD;AAAA,EACF;AAEA,UAAQ,IAAI,mBAAY,UAAU,MAAM;AAAA,CAAqB;AAG7D,QAAM,eAA0B,CAAC;AACjC,QAAM,mBAAsC,CAAC;AAC7C,aAAW,QAAQ,WAAW;AAC5B,UAAM,WAAW,KAAK,QAAQ,SAAS,EAAE;AACzC,UAAM,WAAW,kBAAkB,QAAQ;AAC3C,UAAM,cAAc,MAAM,aAAa,KAAK,UAAU,IAAI,CAAC;AAC3D,QAAI,aAAa;AACf,UAAI;AACF,cAAM,WAAW,UAAoB,WAAW;AAChD,YAAI,SAAS,MAAM,OAAO;AACxB,gBAAM,SAAS,aAAa,MAAM,UAAU,SAAS,UAAU,CAAC;AAChE,uBAAa,KAAK,EAAE,QAAQ,OAAO,SAAS,KAAK,MAAM,CAAC;AAAA,QAC1D;AACA,YAAI,SAAS,MAAM,WAAW;AAC5B,2BAAiB,KAAK,SAAS,KAAK,SAA4B;AAAA,QAClE;AAAA,MACF,QAAQ;AAAA,MAA0C;AAAA,IACpD;AAAA,EACF;AAKA;AACE,UAAM,cAAc,KAAK;AACzB,UAAM,YAAY,cAAc,OAAO;AACvC,QAAI,aAAa,OAAO,KAAK,SAAS,EAAE,SAAS,GAAG;AAIlD,YAAM,kBAAkB,cAAc,aAAa;AACnD,YAAM,qBAAqB,0BAA0B,gBAAgB;AACrE,YAAM,QAAQ;AAAA,QACZ,GAAI,gBAAgB,MAAM,CAAC;AAAA,QAC3B,GAAI,mBAAmB,MAAM,CAAC;AAAA,QAC9B,GAAG,iBAAiB,QAAQ,OAAK,EAAE,MAAM,CAAC,CAAC;AAAA,MAC7C;AACA,YAAM,SAAS;AAAA,QACb,GAAI,gBAAgB,OAAO,CAAC;AAAA,QAC5B,GAAI,mBAAmB,OAAO,CAAC;AAAA,QAC/B,GAAG,iBAAiB,QAAQ,OAAK,EAAE,OAAO,CAAC,CAAC;AAAA,MAC9C;AACA,YAAM,UAA2B,EAAE,IAAI,OAAO,KAAK,OAAO;AAG1D,YAAM,YAAY,yBAAyB,SAAS,OAAO;AAG3D,YAAM,EAAE,eAAe,aAAa,IAAI,sBAAsB,SAAS;AAEvE,YAAM,eAAe;AAAA,QACnB,GAAI,UAAU,aAAa,CAAC;AAAA,QAC5B,GAAG,MAAM,KAAK,aAAa;AAAA,MAC7B,EAAE,KAAK,GAAG;AACV,YAAM,cAAc;AAAA,QAClB,GAAI,UAAU,YAAY,CAAC;AAAA,QAC3B,GAAG,MAAM,KAAK,YAAY;AAAA,MAC5B,EAAE,KAAK,GAAG;AACV,YAAM,eAAe,UAAU,YAAY,KAAK,GAAG,KAAK;AACxD,YAAM,cAAc,UAAU,UAAU,KAAK,GAAG,KAAK;AACrD,YAAM,aAAa,UAAU,SAAS,KAAK,GAAG,KAAK;AACnD,YAAM,YAAY,UAAU,QAAQ,KAAK,GAAG,KAAK;AAEjD,YAAM,gBAAgB;AAAA,QACpB;AAAA,QACA,iIAAiI,YAAY,GAAG,KAAK;AAAA,QACrJ,2DAA2D,WAAW,GAAG,KAAK;AAAA,QAC9E,+BAA+B,SAAS,GAAG,KAAK;AAAA,QAChD,+DAA+D,YAAY,GAAG,KAAK;AAAA,QACnF,iHAAiH,WAAW,GAAG,KAAK;AAAA,QACpI,yBAAyB,UAAU,GAAG,KAAK;AAAA,QAC3C;AAAA,MACF,EAAE,KAAK,IAAI;AAEX,YAAM,iBAAiB;AAAA,6BAAkC,aAAa;AAAA;AACtE,oBAAc,KAAK,SAAS,UAAU,GAAG,cAAc;AACvD,cAAQ,IAAI,qDAAgD,cAAc,OAAO,aAAa,IAAI;AAAA,CAAuB;AAAA,IAC3H;AAAA,EACF;AAEA,MAAI,eAAe;AACnB,MAAI,aAAa;AAGjB,aAAW,QAAQ,WAAW;AAC5B,UAAM,WAAW,KAAK,QAAQ,SAAS,EAAE;AACzC,UAAM,WAAW,kBAAkB,QAAQ;AAC3C,UAAM,cAAc,MAAM,aAAa,KAAK,UAAU,IAAI,CAAC;AAE3D,QAAI,CAAC,aAAa;AAChB,cAAQ,KAAK,0BAAgB,QAAQ,eAAe;AACpD;AACA;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,UAAoB,WAAW;AAGhD,YAAM,aAAa,QAAQ,IAAI,mBAAmB;AAClD,UAAI,SAAS,MAAM,UAAU,QAAQ,CAAC,YAAY;AAChD,gBAAQ,IAAI,iCAAuB,QAAQ,EAAE;AAC7C;AAAA,MACF;AAGA,YAAM,QAAQ,SAAS,MAAM;AAG7B,iBAAW,gBAAgB,WAAW,SAAS;AAC7C,cAAM,SAAS,aAAa;AAC5B,cAAM,UAAU,WAAW;AAG3B,cAAM,UAAU,eAAe,UAAU,QAAQ,WAAW,eAAe,KAAK;AAGhF,cAAM,SAAS,MAAM,gBAAgB;AAAA,UACnC;AAAA,UACA;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA,gBAAgB;AAAA,UAChB;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB;AAAA,UAClB,eAAe,SAAS,MAAM;AAAA,UAC9B,gBAAgB,SAAS,MAAM;AAAA,UAC/B,mBAAmB;AAAA,QACrB,CAAC;AAGD,YAAI,YAAY,OAAO;AACvB,YAAI,OAAO,YAAY;AACrB,gBAAM,aAAa,MAAM,cAAc,OAAO,YAAY,OAAO;AAEjE,sBAAY,UAAU,QAAQ,WAAW,kBAAkB,UAAU;AAAA,QAA4B;AAAA,QACnG;AAGA,YAAI,gBAAgB;AAClB,sBAAY,qBAAqB,WAAW,cAAc;AAAA,QAC5D;AAGA,cAAM,aAAa,uBAAuB,UAAU,QAAQ,WAAW,eAAe,SAAS,KAAK;AAGpG,cAAM,YAAY,WAAW,UAAU,GAAG,WAAW,YAAY,GAAG,CAAC;AACrE,YAAI,aAAa,CAAC,WAAW,SAAS,GAAG;AACvC,oBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,QAC1C;AAGA,YAAI,YAAY,KAAK;AACnB,kBAAQ,IAAI,mCAAmC,UAAU,MAAM,IAAI,CAAC;AAAA,QACtE;AAEA,cAAM,UAAU,YAAY,WAAW,OAAO;AAE9C,sBAAc,IAAI,OAAO;AACzB,gBAAQ,IAAI,iBAAY,OAAO,WAAM,UAAU,EAAE;AACjD;AAAA,MACF;AAAA,IAEF,SAAS,OAAY;AAEnB,UAAI;AAEJ,UAAI,iBAAiB,OAAO;AAE1B,YAAI,YAAY,SAAS,MAAM,QAAQ,MAAM,MAAM,GAAG;AACpD,yBAAe,MAAM,OAAO,IAAI,CAAC,MAAW,EAAE,SAAS,EAAE,WAAW,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM;AAAA,QAC5F,WAES,MAAM,OAAO;AACpB,gBAAM,WAAW,MAAM,iBAAiB,QACnC,MAAM,MAAM,SAAS,MAAM,MAAM,UAClC,OAAO,MAAM,KAAK;AACtB,yBAAe,GAAG,MAAM,SAAS,MAAM,OAAO;AAAA;AAAA;AAAA,EAAmB,QAAQ;AAAA,QAC3E,WAES,UAAU,SAAS,MAAM,QAAQ,MAAM,IAAI,GAAG;AACrD,yBAAe,MAAM,KAAK,IAAI,YAAY,EAAE,KAAK,MAAM;AAAA,QACzD,OACK;AACH,yBAAe,MAAM,SAAS,MAAM;AAAA,QACtC;AAAA,MACF,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AAEtD,YAAI,MAAM,QAAQ,MAAM,QAAQ,MAAM,IAAI,GAAG;AAC3C,yBAAe,MAAM,KAAK,IAAI,YAAY,EAAE,KAAK,MAAM;AAAA,QACzD,OAAO;AACL,yBAAe,OAAO,KAAK;AAAA,QAC7B;AAAA,MACF,OAAO;AACL,uBAAe,OAAO,KAAK;AAAA,MAC7B;AAGA,UAAI,iBAAiB,mBAAmB,aAAa,SAAS,iBAAiB,GAAG;AAChF,YAAI;AACF,gBAAM,YAAY,QAAQ,KAAK;AAC/B,cAAI,aAAa,cAAc,qBAAqB,UAAU,SAAS,aAAa,QAAQ;AAC1F,2BAAe;AAAA,UACjB;AAAA,QACF,QAAQ;AAAA,QAAC;AAAA,MACX;AAEA,cAAQ,MAAM,yBAAoB,QAAQ,KAAK,KAAK;AACpD,kBAAY,KAAK;AAAA,QACf,MAAM,SAAS,IAAI;AAAA,QACnB,SAAS;AAAA,QACT,MAAM,aAAa,SAAS,cAAc,KAAK,aAAa,SAAS,QAAQ,IAAI,WAAW;AAAA,MAC9F,CAAC;AACD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,eAAe,aAAa,UAAU;AAC5C,QAAM,oBAAoB,oBAAI,IAAkC;AAChE,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,kBAAgB,UAAU;AAC1B,gBAAc,UAAU;AAGxB,QAAM,wBAAwB,mBAAmB,OAAO;AAGxD,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,oBAAoB,oBAAoB,OAAO;AACrD,YAAQ,IAAI;AAAA,6EAAyE;AAAA,EACvF;AAGA,MAAI,SAAS;AACX,UAAM,kBAAkB,SAAS,OAAO;AACxC,UAAM,gBAAgB,CAAC,GAAG,aAAa,GAAG,SAAS,OAAO;AAC1D,YAAQ,IAAI;AAAA,wDAAoD;AAAA,EAClE,OAAO;AACL,YAAQ,KAAK;AAAA,gFAAyE;AAAA,EACxF;AAEA,UAAQ,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;AACjC,UAAQ,IAAI,wBAAmB;AAC/B,UAAQ,IAAI,sBAAiB,YAAY,EAAE;AAC3C,MAAI,aAAa,GAAG;AAClB,YAAQ,IAAI,qBAAgB,UAAU,EAAE;AAAA,EAC1C;AACA,UAAQ,IAAI;AAAA,qCAAiC;AAC7C,UAAQ,IAAI,4CAA4C;AACxD,UAAQ,IAAI,4BAA4B;AACxC,UAAQ,IAAI,6BAA6B;AACzC,UAAQ,IAAI,iCAAiC;AAC7C,MAAI,kBAAkB,OAAO,GAAG;AAC9B,YAAQ,IAAI,uDAAuD;AAAA,EACrE;AACA,MAAI,WAAW,YAAY,GAAG;AAC5B,YAAQ,IAAI,8CAA8C;AAAA,EAC5D;AACA,MAAI,mBAAmB,SAAS,GAAG;AACjC,YAAQ,IAAI,mDAAmD;AAAA,EACjE;AACA,MAAI,SAAS;AACX,YAAQ,IAAI,oCAAoC;AAAA,EAClD;AACA,UAAQ,IAAI,wCAAmC;AAG/C,QAAM,WAAW,sBAAsB;AACvC,aAAW,EAAE,WAAW,MAAM,KAAK,UAAU;AAC3C,gBAAY,KAAK;AAAA,MACf,MAAM,cAAc,SAAS;AAAA,MAC7B,SAAS;AAAA,MACT,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,MAAI,YAAY,SAAS,GAAG;AAE1B,UAAM,eAAe,oBAAI,IAAY;AACrC,UAAM,eAAe,YAAY,OAAO,SAAO;AAC7C,UAAI,aAAa,IAAI,IAAI,OAAO,EAAG,QAAO;AAC1C,mBAAa,IAAI,IAAI,OAAO;AAC5B,aAAO;AAAA,IACT,CAAC;AAED,UAAM,aAA8B;AAAA,MAClC,QAAQ;AAAA,MACR,WAAW,KAAK,IAAI;AAAA,IACtB;AACA,UAAM,UAAU,YAAY,KAAK,UAAU,YAAY,MAAM,CAAC,GAAG,OAAO;AACxE,UAAM,WAAW,aAAa,WAAW,YAAY,SACjD,GAAG,aAAa,MAAM,SAAS,aAAa,WAAW,IAAI,KAAK,GAAG,KACnE,GAAG,aAAa,MAAM,gBAAgB,aAAa,WAAW,IAAI,KAAK,GAAG,cAAc,YAAY,MAAM;AAC9G,YAAQ,IAAI;AAAA,2DAAoD,QAAQ,GAAG;AAAA,EAC7E;AACF;",
4
+ "sourcesContent": ["/**\n * Static Site Generation Build Script\n * Pre-generates HTML files for all pages at build time\n * CSP-compliant: Extracts JavaScript to external files\n */\n\nimport { existsSync, readdirSync, mkdirSync, rmSync, statSync, copyFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { writeFile, readFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport type { BuildError, BuildErrorsData } from \"./lib/server/ssr/buildErrorOverlay\";\nimport { createHash } from \"crypto\";\nimport { inspect, minifyJS as runtimeMinifyJS } from './lib/server/runtime';\nimport {\n loadJSONFile,\n loadComponentDirectory,\n mapPageNameToPath,\n parseJSON,\n loadI18nConfig\n} from \"./lib/server/jsonLoader\";\nimport { generateSSRHTML } from \"./lib/server/ssrRenderer\";\nimport type { SSRHTMLResult } from \"./lib/server/ssr/htmlGenerator\";\nimport { prepareClientData, type ClientDataCollection } from \"./lib/server/ssr/clientDataInjector\";\nimport { clearJSValidationCache, getJSValidationErrors } from \"./lib/server/ssr/jsCollector\";\nimport { projectPaths } from \"./lib/server/projectContext\";\nimport { loadProjectConfig } from \"./lib/shared/fontLoader\";\nimport { FileSystemCMSProvider } from \"./lib/server/providers/fileSystemCMSProvider\";\nimport { CMSService } from \"./lib/server/services/cmsService\";\nimport { isI18nValue, resolveI18nValue } from \"./lib/shared/i18n\";\nimport type { ComponentDefinition, JSONPage, CMSSchema, CMSItem, I18nConfig, Experiment } from \"./lib/shared/types\";\nimport { isItemDraftForLocale, isItemFullyPublished } from \"./lib/shared/types\";\nimport type { SlugMap } from \"./lib/shared/slugTranslator\";\nimport { buildItemUrl } from \"./lib/shared/itemTemplateUtils\";\nimport { generateMiddleware, generateTrackFunction, generateResultsFunction } from \"./lib/server/ab/generateFunctions\";\nimport { generateTrackingScript } from \"./lib/server/ab/trackingScript\";\nimport { migrateTemplatesDirectory } from \"./lib/server/migrateTemplates\";\nimport { extractLibraryOrigins, collectComponentLibraries, filterLibrariesByContext } from \"./lib/shared/libraryLoader\";\nimport type { LibrariesConfig } from \"./lib/shared/types/libraries\";\n\n/**\n * Collect build errors for error overlay\n */\nconst buildErrors: BuildError[] = [];\n\n/**\n * Generate short hash from content for file naming\n */\nexport function hashContent(content: string): string {\n return createHash('sha256').update(content).digest('hex').slice(0, 8);\n}\n\n/**\n * Format a Bun build log entry to a readable string\n */\nexport function formatBunLog(log: any): string {\n const parts: string[] = [];\n\n // Try to get position info\n if (log.position) {\n const pos = log.position;\n if (pos.file) parts.push(`File: ${pos.file}`);\n if (pos.line !== undefined) parts.push(`Line ${pos.line}:${pos.column || 0}`);\n if (pos.lineText) parts.push(` ${pos.lineText}`);\n }\n\n // Get the message\n if (log.message) {\n parts.push(log.message);\n } else if (log.text) {\n parts.push(log.text);\n }\n\n // If we couldn't extract anything useful, stringify the whole thing\n if (parts.length === 0) {\n try {\n return JSON.stringify(log, null, 2);\n } catch {\n return String(log);\n }\n }\n\n return parts.join('\\n');\n}\n\n/**\n * Minify JavaScript code using runtime bundler\n * Throws on error instead of silently failing\n */\nasync function minifyJS(code: string): Promise<string> {\n const result = await runtimeMinifyJS(code);\n if (result.success) {\n return result.code;\n }\n throw new Error(`JavaScript minification failed:\\n${result.errors.join('\\n\\n')}`);\n}\n\n/**\n * Track JavaScript files to avoid duplicates\n * Maps content hash -> script path\n */\nconst jsFileCache = new Map<string, string>();\n\n/**\n * Get or create script file path for given JS content\n * Returns the path to reference in HTML\n */\nasync function getScriptPath(jsContent: string, distDir: string): Promise<string> {\n // Minify JavaScript for production\n const minified = await minifyJS(jsContent);\n const hash = hashContent(minified);\n\n // Check if we already wrote this content\n if (jsFileCache.has(hash)) {\n return jsFileCache.get(hash)!;\n }\n\n // Create scripts directory if needed\n const scriptsDir = join(distDir, '_scripts');\n if (!existsSync(scriptsDir)) {\n mkdirSync(scriptsDir, { recursive: true });\n }\n\n // Write minified script file\n const scriptPath = `/_scripts/${hash}.js`;\n const fullPath = join(distDir, '_scripts', `${hash}.js`);\n await writeFile(fullPath, minified, 'utf-8');\n\n // Cache for reuse\n jsFileCache.set(hash, scriptPath);\n\n return scriptPath;\n}\n\n/**\n * Recursively copy directory contents\n */\nfunction copyDirectory(src: string, dest: string): void {\n if (!existsSync(src)) {\n return;\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const files = readdirSync(src);\n\n for (const file of files) {\n const srcPath = join(src, file);\n const destPath = join(dest, file);\n const stat = statSync(srcPath);\n\n if (stat.isDirectory()) {\n copyDirectory(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n\n/**\n * Get locale-specific output path for a page with translated slug support\n * Default locale files go to root, other locales to subdirectories\n * Uses translated slugs from meta.slugs if available\n */\nexport function getLocalizedOutputPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n distDir: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale, or fall back to default path\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n // Build filename from slug\n const fileName = slug === \"\" ? \"index.html\" : `${slug}.html`;\n\n if (locale === defaultLocale) {\n return `${distDir}/${fileName}`;\n }\n return `${distDir}/${locale}/${fileName}`;\n}\n\n/**\n * Get display path for logging (the actual URL the user will visit)\n */\nexport function getDisplayPath(\n basePath: string,\n locale: string,\n defaultLocale: string,\n slugs?: Record<string, string>\n): string {\n // Get translated slug for this locale\n let slug: string;\n if (slugs && slugs[locale]) {\n slug = slugs[locale];\n } else if (basePath === \"/\") {\n slug = \"\";\n } else {\n slug = basePath.substring(1);\n }\n\n if (locale === defaultLocale) {\n return slug === \"\" ? \"/\" : `/${slug}`;\n }\n return slug === \"\" ? `/${locale}` : `/${locale}/${slug}`;\n}\n\n/**\n * Generate robots.txt with sensible defaults\n */\nexport async function generateRobotsTxt(siteUrl: string, distDir: string): Promise<void> {\n const content = `User-agent: *\nAllow: /\n\nSitemap: ${siteUrl}/sitemap.xml\n`;\n await writeFile(join(distDir, 'robots.txt'), content, 'utf-8');\n}\n\n/**\n * Generate sitemap.xml from collected URLs\n */\nexport async function generateSitemap(urls: string[], siteUrl: string, distDir: string): Promise<void> {\n // Sort URLs for deterministic output\n const sortedUrls = [...urls].sort();\n\n const urlEntries = sortedUrls\n .map(url => ` <url><loc>${siteUrl}${url}</loc></url>`)\n .join('\\n');\n\n const content = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n${urlEntries}\n</urlset>\n`;\n await writeFile(join(distDir, 'sitemap.xml'), content, 'utf-8');\n}\n\n/**\n * Clean dist directory, keeping only production files\n */\nfunction cleanDist(): void {\n const distDir = projectPaths.dist();\n if (!existsSync(distDir)) {\n mkdirSync(distDir, { recursive: true });\n return;\n }\n\n const files = readdirSync(distDir);\n let cleaned = 0;\n\n for (const file of files) {\n // Keep fonts, images, icons, assets, and videos\n if (\n file === \"fonts\" ||\n file === \"images\" ||\n file === \"icons\" ||\n file === \"assets\" ||\n file === \"videos\"\n ) {\n continue;\n }\n\n // Remove everything else (editor files, old HTML, etc.)\n try {\n const filePath = join(distDir, file);\n const stat = statSync(filePath);\n\n if (stat.isDirectory()) {\n rmSync(filePath, { recursive: true, force: true });\n } else {\n rmSync(filePath, { force: true });\n }\n cleaned++;\n } catch (error) {\n console.warn(`\u26A0\uFE0F Could not remove ${file}:`, error);\n }\n }\n\n if (cleaned > 0) {\n console.log(`\uD83E\uDDF9 Cleaned ${cleaned} file(s) from dist\\n`);\n }\n}\n\n/**\n * Check if a page is a CMS template\n */\nexport function isCMSPage(pageData: JSONPage): boolean {\n return pageData.meta?.source === 'cms' && !!pageData.meta?.cms;\n}\n\n/**\n * Build URL path for a CMS item based on the URL pattern\n * Uses schema.slugField to get the slug value, supporting i18n slugs\n */\nexport function buildCMSItemPath(\n urlPattern: string,\n item: CMSItem,\n slugField: string,\n locale: string,\n i18nConfig: I18nConfig\n): string {\n // Get slug from the schema-defined slugField, fall back to _slug or _id\n let slug = item[slugField] ?? item._slug ?? item._id;\n\n // Resolve i18n slug to locale-specific value\n if (isI18nValue(slug)) {\n slug = resolveI18nValue(slug, locale, i18nConfig) as string;\n }\n\n return urlPattern.replace('{{slug}}', String(slug));\n}\n\n/**\n * Generate static JSON data files for collections with 'static' strategy\n * Output: /data/{collection}/index.json\n */\nasync function generateStaticDataFiles(\n staticCollections: Map<string, ClientDataCollection>,\n distDir: string\n): Promise<void> {\n if (staticCollections.size === 0) return;\n\n console.log(`\\n\uD83D\uDCE6 Generating static data files...`);\n\n for (const [collectionId, data] of staticCollections) {\n const dataDir = join(distDir, 'data', collectionId);\n if (!existsSync(dataDir)) {\n mkdirSync(dataDir, { recursive: true });\n }\n const jsonPath = join(dataDir, 'index.json');\n await writeFile(jsonPath, JSON.stringify(data.items), 'utf-8');\n console.log(` \u2705 /data/${collectionId}/index.json (${data.items.length} items)`);\n }\n}\n\n/**\n * Build CMS templates from root templates/ directory\n */\nasync function buildCMSTemplates(\n templatesDir: string,\n globalComponents: Record<string, ComponentDefinition>,\n i18nConfig: I18nConfig,\n slugMappings: SlugMap[],\n distDir: string,\n cmsService: CMSService,\n generatedUrls: Set<string>,\n staticCollections: Map<string, ClientDataCollection>,\n siteUrl?: string,\n abTrackingScript?: string | null\n): Promise<{ success: number; errors: number }> {\n let successCount = 0;\n let errorCount = 0;\n\n if (!existsSync(templatesDir)) {\n return { success: 0, errors: 0 };\n }\n\n const templateFiles = readdirSync(templatesDir).filter(f => f.endsWith('.json'));\n\n if (templateFiles.length === 0) {\n return { success: 0, errors: 0 };\n }\n\n console.log(`\\n\uD83D\uDCDD Processing ${templateFiles.length} CMS template(s)...\\n`);\n\n for (const file of templateFiles) {\n const templateContent = await loadJSONFile(join(templatesDir, file));\n if (!templateContent) continue;\n\n try {\n const pageData = parseJSON<JSONPage>(templateContent);\n\n // Skip draft templates in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft template: ${file}`);\n continue;\n }\n\n if (!isCMSPage(pageData)) {\n console.warn(`\u26A0\uFE0F ${file} is in templates/ but missing meta.source: \"cms\"`);\n continue;\n }\n\n const cmsSchema = pageData.meta!.cms as CMSSchema;\n console.log(`\uD83D\uDCDD CMS Collection: ${cmsSchema.id}`);\n\n // Use shared cmsService to get items\n const items = await cmsService.queryItems({ collection: cmsSchema.id });\n\n if (items.length === 0) {\n console.log(` \u26A0\uFE0F No items found in cms/${cmsSchema.id}/`);\n continue;\n }\n\n console.log(` Found ${items.length} item(s)`);\n\n // Prepare client data if clientData is enabled\n // Filter out fully-draft items from client data (client data is locale-agnostic)\n let clientDataCollections: Map<string, ClientDataCollection> | undefined;\n if (cmsSchema.clientData?.enabled) {\n const publishedItems = items.filter(item => isItemFullyPublished(item));\n const clientData = prepareClientData(cmsSchema.id, publishedItems, cmsSchema.clientData);\n if (clientData) {\n if (clientData.strategy === 'inline') {\n // Inline data embedded in HTML\n clientDataCollections = new Map([[cmsSchema.id, clientData]]);\n console.log(` \uD83D\uDCE6 Client data (inline): ${clientData.items.length} items (${clientData.config.fields?.length || 'all'} fields)`);\n } else if (clientData.strategy === 'static') {\n // Static data written to separate file\n staticCollections.set(cmsSchema.id, clientData);\n console.log(` \uD83D\uDCE6 Client data (static): ${clientData.items.length} items \u2192 /data/${cmsSchema.id}/index.json`);\n }\n }\n }\n\n for (const item of items) {\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n\n // Skip draft items per locale in production builds\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (!isDevBuild && isItemDraftForLocale(item, locale)) {\n console.log(` \u23ED\uFE0F Skipping draft: ${item._filename || item._id} [${locale}]`);\n continue;\n }\n\n const baseUrl = siteUrl || \"\";\n const itemPath = buildCMSItemPath(cmsSchema.urlPattern, item, cmsSchema.slugField, locale, i18nConfig);\n\n // Create CMS item with computed _url for {{cms._url}} template access\n const itemWithUrl: CMSItem = { ...item, _url: itemPath };\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: itemPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsContext: { cms: itemWithUrl },\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n clientDataCollections,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (abTrackingScript) {\n finalHtml = injectTrackingScript(finalHtml, abTrackingScript);\n }\n\n const outputPath = locale === i18nConfig.defaultLocale\n ? `${distDir}${itemPath}.html`\n : `${distDir}/${locale}${itemPath}.html`;\n\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf('/'));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n await writeFile(outputPath, finalHtml, 'utf-8');\n\n const displayPath = locale === i18nConfig.defaultLocale ? itemPath : `/${locale}${itemPath}`;\n generatedUrls.add(displayPath);\n console.log(` \u2705 ${displayPath}`);\n successCount++;\n }\n }\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error processing ${file}:`, error);\n buildErrors.push({\n file: `templates/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'cms',\n });\n errorCount++;\n }\n }\n\n return { success: successCount, errors: errorCount };\n}\n\n/**\n * Load running experiments from experiments.json\n */\nasync function loadRunningExperiments(): Promise<Experiment[]> {\n const experimentsPath = join(projectPaths.project, 'experiments.json');\n if (!existsSync(experimentsPath)) return [];\n\n try {\n const content = await readFile(experimentsPath, 'utf-8');\n const data = JSON.parse(content);\n const experiments: Experiment[] = data.experiments || [];\n return experiments.filter(e => e.status === 'running');\n } catch {\n return [];\n }\n}\n\n/**\n * Inject A/B tracking script into HTML before </head>\n */\nexport function injectTrackingScript(html: string, trackingJs: string): string {\n const scriptTag = `<script>${trackingJs}</script>`;\n return html.replace('</head>', `${scriptTag}\\n</head>`);\n}\n\n/**\n * Generate A/B testing Cloudflare Functions into dist/functions/\n */\nasync function generateABFunctions(experiments: Experiment[], distDir: string): Promise<void> {\n // Generate middleware\n const middlewareContent = generateMiddleware(experiments);\n if (middlewareContent) {\n const middlewarePath = join(distDir, 'functions', '_middleware.ts');\n const middlewareDir = join(distDir, 'functions');\n if (!existsSync(middlewareDir)) {\n mkdirSync(middlewareDir, { recursive: true });\n }\n await writeFile(middlewarePath, middlewareContent, 'utf-8');\n }\n\n // Generate tracking endpoint\n const trackContent = generateTrackFunction();\n const trackDir = join(distDir, 'functions', 'api');\n if (!existsSync(trackDir)) {\n mkdirSync(trackDir, { recursive: true });\n }\n await writeFile(join(trackDir, 'ab-track.ts'), trackContent, 'utf-8');\n\n // Generate results endpoint\n const resultsContent = generateResultsFunction();\n await writeFile(join(trackDir, 'ab-results.ts'), resultsContent, 'utf-8');\n}\n\n/**\n * Main build function\n */\nexport async function buildStaticPages(): Promise<void> {\n console.log(\"\uD83C\uDFD7\uFE0F Building static HTML files...\\n\");\n\n // Clear previous build errors and JS validation cache\n buildErrors.length = 0;\n clearJSValidationCache();\n\n // Reset configService to ensure it loads from the correct project directory\n const { configService } = await import(\"./lib/server/services/configService\");\n configService.reset();\n\n // Load project config first\n const projectConfig = await loadProjectConfig();\n const siteUrl = (projectConfig as { siteUrl?: string }).siteUrl?.replace(/\\/$/, ''); // Remove trailing slash\n\n // Track all generated URLs for sitemap\n const generatedUrls = new Set<string>();\n\n // Load running A/B experiments (if any)\n const runningExperiments = await loadRunningExperiments();\n let trackingScript: string | null = null;\n if (runningExperiments.length > 0) {\n const exp = runningExperiments[0]; // Use first running experiment\n trackingScript = generateTrackingScript(exp.id, exp.conversionGoals);\n console.log(`\uD83E\uDDEA A/B experiment active: \"${exp.name}\" (${exp.variants.length} variant(s))\\n`);\n }\n\n // Load i18n config for multi-locale build\n const i18nConfig = await loadI18nConfig();\n console.log(`\uD83C\uDF10 Locales: ${i18nConfig.locales.map(l => l.code).join(\", \")} (default: ${i18nConfig.defaultLocale})\\n`);\n\n // Auto-migrate pages/templates/ \u2192 templates/ if needed\n await migrateTemplatesDirectory();\n\n // Clean dist directory (removes editor files, old HTML)\n cleanDist();\n\n // Clear the JS file cache since cleanDist() removed _scripts/\n // Without this, cached entries would skip file creation on subsequent builds\n jsFileCache.clear();\n\n // Copy fonts, images, icons, and functions directories to dist\n console.log(\"\uD83D\uDCE6 Copying assets...\");\n const distDir = projectPaths.dist();\n\n // Delete old _errors.json if it exists (start fresh)\n const errorsPath = join(distDir, '_errors.json');\n if (existsSync(errorsPath)) {\n unlinkSync(errorsPath);\n }\n copyDirectory(projectPaths.fonts(), join(distDir, \"fonts\"));\n copyDirectory(projectPaths.images(), join(distDir, \"images\"));\n copyDirectory(projectPaths.icons(), join(distDir, \"icons\"));\n copyDirectory(projectPaths.assets(), join(distDir, \"assets\"));\n copyDirectory(projectPaths.videos(), join(distDir, \"videos\"));\n\n // Copy libraries folder (downloaded external JS/CSS files)\n const librariesDir = join(projectPaths.project, \"libraries\");\n if (existsSync(librariesDir)) {\n copyDirectory(librariesDir, join(distDir, \"libraries\"));\n }\n\n // Copy functions folder for Cloudflare Pages\n const functionsDir = projectPaths.functions();\n if (existsSync(functionsDir)) {\n copyDirectory(functionsDir, join(distDir, \"functions\"));\n }\n\n // Copy user-created root files for static hosting\n const hostingFiles: string[] = [];\n const rootFilesToCopy = [\n '_headers', // Netlify/Cloudflare headers\n '_redirects', // Netlify/Cloudflare redirects\n 'llms.txt', // LLM context\n 'humans.txt', // Team credits\n 'ads.txt', // Ad verification\n 'security.txt', // Security contact\n 'CNAME', // GitHub Pages domain\n 'manifest.json', // PWA manifest\n 'site.webmanifest', // PWA manifest (alt)\n ];\n\n for (const file of rootFilesToCopy) {\n const filePath = join(projectPaths.project, file);\n if (existsSync(filePath)) {\n copyFileSync(filePath, join(distDir, file));\n hostingFiles.push(file);\n }\n }\n\n // Copy .well-known directory if exists\n const wellKnownDir = join(projectPaths.project, '.well-known');\n if (existsSync(wellKnownDir)) {\n copyDirectory(wellKnownDir, join(distDir, '.well-known'));\n hostingFiles.push('.well-known/');\n }\n\n const parts = ['Assets'];\n if (existsSync(functionsDir)) parts.push('functions');\n if (hostingFiles.length > 0) parts.push(hostingFiles.join(', '));\n console.log(`\u2705 ${parts.join(', ')} copied\\n`);\n\n // Load all global components\n const { components, warnings, errors } = await loadComponentDirectory(projectPaths.components());\n const globalComponents: Record<string, ComponentDefinition> = {};\n components.forEach((value, key) => {\n globalComponents[key] = value;\n });\n\n for (const warning of warnings) console.warn(`\u26A0\uFE0F ${warning}`);\n for (const error of errors) console.error(`\u274C ${error}`);\n console.log(`\u2705 Loaded ${components.size} global component(s)\\n`);\n\n // Initialize CMS service for CMSList rendering\n const cmsProvider = new FileSystemCMSProvider(projectPaths.templates(), projectPaths.cms());\n const cmsService = new CMSService(cmsProvider);\n await cmsService.initialize();\n console.log(`\u2705 CMS service initialized\\n`);\n\n // Load all pages\n const pagesDir = projectPaths.pages();\n if (!existsSync(pagesDir)) {\n console.error(\"\u274C Pages directory not found!\");\n process.exit(1);\n }\n\n // Recursively collect all .json page files (supports nested folders like pages/a/b.json)\n const pageFiles: string[] = [];\n function scanPagesDir(dir: string, prefix: string): void {\n const entries = readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name.endsWith('.json')) {\n pageFiles.push(prefix ? `${prefix}/${entry.name}` : entry.name);\n } else if (entry.isDirectory()) {\n scanPagesDir(join(dir, entry.name), prefix ? `${prefix}/${entry.name}` : entry.name);\n }\n }\n }\n scanPagesDir(pagesDir, '');\n \n if (pageFiles.length === 0) {\n console.warn(\"\u26A0\uFE0F No pages found in ./pages directory\");\n return;\n }\n\n console.log(`\uD83D\uDCC4 Found ${pageFiles.length} page(s) to build\\n`);\n\n // First pass: collect all slug mappings and page-level libraries\n const slugMappings: SlugMap[] = [];\n const allPageLibraries: LibrariesConfig[] = [];\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n if (pageContent) {\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n if (pageData.meta?.slugs) {\n const pageId = basePath === '/' ? 'index' : basePath.substring(1);\n slugMappings.push({ pageId, slugs: pageData.meta.slugs });\n }\n if (pageData.meta?.libraries) {\n allPageLibraries.push(pageData.meta.libraries as LibrariesConfig);\n }\n } catch { /* ignore parse errors in first pass */ }\n }\n }\n\n // Generate _headers from CSP config, auto-including library CDN domains\n // Always regenerate when CSP config exists \u2014 overwrites any stale _headers file\n // that may have been copied from the project root\n {\n await configService.load();\n const cspConfig = configService.getCSP();\n if (cspConfig && Object.keys(cspConfig).length > 0) {\n // Collect all library sources: global + component + page-level\n // Note: we concatenate (not mergeLibraries) because _headers applies globally \u2014\n // we need the union of ALL origins, regardless of per-page merge modes\n const globalLibraries = configService.getLibraries();\n const componentLibraries = collectComponentLibraries(globalComponents);\n const allJs = [\n ...(globalLibraries.js || []),\n ...(componentLibraries.js || []),\n ...allPageLibraries.flatMap(p => p.js || []),\n ];\n const allCss = [\n ...(globalLibraries.css || []),\n ...(componentLibraries.css || []),\n ...allPageLibraries.flatMap(p => p.css || []),\n ];\n const allLibs: LibrariesConfig = { js: allJs, css: allCss };\n\n // Filter out CSS libs disabled for build before extracting CSP origins\n const buildLibs = filterLibrariesByContext(allLibs, 'build');\n\n // Extract CDN origins from all library URLs\n const { scriptOrigins, styleOrigins } = extractLibraryOrigins(buildLibs);\n\n const extraScripts = [\n ...(cspConfig.scriptSrc || []),\n ...Array.from(scriptOrigins),\n ].join(' ');\n const extraStyles = [\n ...(cspConfig.styleSrc || []),\n ...Array.from(styleOrigins),\n ].join(' ');\n const extraConnect = cspConfig.connectSrc?.join(' ') || '';\n const extraFrames = cspConfig.frameSrc?.join(' ') || '';\n const extraFonts = cspConfig.fontSrc?.join(' ') || '';\n const extraImgs = cspConfig.imgSrc?.join(' ') || '';\n\n // Production-built pages have NO executable inline scripts: page config,\n // component JS, form handler, and MenoFilter all live in external\n // /_scripts/{hash}.js files (returnSeparateJS: true), and the Meno\n // badge's hover effect is pure CSS. Only `<script type=\"application/json\">`\n // remains inline (used as a data island for MenoFilter), which CSP\n // ignores because it has no executable code. So we can drop\n // `'unsafe-inline'` entirely from script-src in the generated _headers.\n const cspDirectives = [\n \"default-src 'self'\",\n `script-src 'self' https://f.vimeocdn.com https://player.vimeo.com https://www.youtube.com https://s.ytimg.com ${extraScripts}`.trim(),\n `style-src 'self' 'unsafe-inline' https://f.vimeocdn.com ${extraStyles}`.trim(),\n `img-src 'self' data: https: ${extraImgs}`.trim(),\n `connect-src 'self' https://vimeo.com https://*.vimeocdn.com ${extraConnect}`.trim(),\n `frame-src https://player.vimeo.com https://vimeo.com https://www.youtube.com https://www.youtube-nocookie.com ${extraFrames}`.trim(),\n `font-src 'self' data: ${extraFonts}`.trim(),\n \"media-src 'self' https: blob:\"\n ].join('; ');\n\n const headersContent = `/*\\n Content-Security-Policy: ${cspDirectives}\\n`;\n writeFileSync(join(distDir, '_headers'), headersContent);\n console.log(`\u2705 Generated _headers with CSP (auto-included ${scriptOrigins.size + styleOrigins.size} library origin(s))\\n`);\n }\n }\n\n let successCount = 0;\n let errorCount = 0;\n\n // Build each page for each locale\n for (const file of pageFiles) {\n const pageName = file.replace(\".json\", \"\");\n const basePath = mapPageNameToPath(pageName);\n const pageContent = await loadJSONFile(join(pagesDir, file));\n\n if (!pageContent) {\n console.warn(`\u26A0\uFE0F Skipping ${basePath} (empty file)`);\n errorCount++;\n continue;\n }\n\n try {\n const pageData = parseJSON<JSONPage>(pageContent);\n\n // Skip draft pages in production (not in dev mode)\n const isDevBuild = process.env.MENO_DEV_BUILD === 'true';\n if (pageData.meta?.draft === true && !isDevBuild) {\n console.log(`\u23ED\uFE0F Skipping draft: ${basePath}`);\n continue;\n }\n\n // Get translated slugs from page meta (if available)\n const slugs = pageData.meta?.slugs;\n\n // Generate HTML for each locale\n for (const localeConfig of i18nConfig.locales) {\n const locale = localeConfig.code;\n const baseUrl = siteUrl || \"\";\n\n // Build the URL path that will be used for this locale\n const urlPath = getDisplayPath(basePath, locale, i18nConfig.defaultLocale, slugs);\n\n // Generate HTML with JS returned separately (CSP-compliant)\n const result = await generateSSRHTML({\n pageData,\n globalComponents,\n pagePath: urlPath,\n baseUrl,\n useBuiltBundle: true,\n locale,\n slugMappings,\n cmsService,\n returnSeparateJS: true,\n pageLibraries: pageData.meta?.libraries,\n pageCustomCode: pageData.meta?.customCode,\n isProductionBuild: true,\n }) as SSRHTMLResult;\n\n // If there's JavaScript, write to external file and update HTML\n let finalHtml = result.html;\n if (result.javascript) {\n const scriptPath = await getScriptPath(result.javascript, distDir);\n // Insert script reference before </body>\n finalHtml = finalHtml.replace('</body>', ` <script src=\"${scriptPath}\" defer></script>\\n</body>`);\n }\n\n // Inject A/B tracking script if experiments are running\n if (trackingScript) {\n finalHtml = injectTrackingScript(finalHtml, trackingScript);\n }\n\n // Determine locale-specific output path with translated slug\n const outputPath = getLocalizedOutputPath(basePath, locale, i18nConfig.defaultLocale, distDir, slugs);\n\n // Ensure directory exists\n const outputDir = outputPath.substring(0, outputPath.lastIndexOf(\"/\"));\n if (outputDir && !existsSync(outputDir)) {\n mkdirSync(outputDir, { recursive: true });\n }\n\n // Debug: show end of HTML\n if (urlPath === '/') {\n console.log('[DEBUG] Last 500 chars of HTML:', finalHtml.slice(-500));\n }\n\n await writeFile(outputPath, finalHtml, \"utf-8\");\n\n generatedUrls.add(urlPath);\n console.log(`\u2705 Built: ${urlPath} \u2192 ${outputPath}`);\n successCount++;\n }\n\n } catch (error: any) {\n // Capture full error with as much detail as possible\n let errorMessage: string;\n\n if (error instanceof Error) {\n // Check for AggregateError (multiple errors)\n if ('errors' in error && Array.isArray(error.errors)) {\n errorMessage = error.errors.map((e: any) => e.stack || e.message || String(e)).join('\\n\\n');\n }\n // Check for cause chain\n else if (error.cause) {\n const causeMsg = error.cause instanceof Error\n ? (error.cause.stack || error.cause.message)\n : String(error.cause);\n errorMessage = `${error.stack || error.message}\\n\\nCaused by:\\n${causeMsg}`;\n }\n // Bun's BuildMessage has logs array\n else if ('logs' in error && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n }\n else {\n errorMessage = error.stack || error.message;\n }\n } else if (typeof error === 'object' && error !== null) {\n // Bun BuildOutput has logs\n if (error.logs && Array.isArray(error.logs)) {\n errorMessage = error.logs.map(formatBunLog).join('\\n\\n');\n } else {\n errorMessage = String(error);\n }\n } else {\n errorMessage = String(error);\n }\n\n // If we still just have \"Bundle failed\", try to get more from inspect\n if (errorMessage === 'Bundle failed' || errorMessage.includes('Bundle failed\\n')) {\n try {\n const inspected = inspect(error);\n if (inspected && inspected !== '[object Object]' && inspected.length > errorMessage.length) {\n errorMessage = inspected;\n }\n } catch {}\n }\n\n console.error(`\u274C Error building ${basePath}:`, error);\n buildErrors.push({\n file: `pages/${file}`,\n message: errorMessage,\n type: errorMessage.includes('minification') || errorMessage.includes('minify') ? 'minify' : 'render',\n });\n errorCount++;\n }\n }\n\n // Build CMS templates from root templates/ directory\n const templatesDir = projectPaths.templates();\n const staticCollections = new Map<string, ClientDataCollection>();\n const cmsResult = await buildCMSTemplates(\n templatesDir,\n globalComponents,\n i18nConfig,\n slugMappings,\n distDir,\n cmsService,\n generatedUrls,\n staticCollections,\n siteUrl,\n trackingScript\n );\n successCount += cmsResult.success;\n errorCount += cmsResult.errors;\n\n // Generate static data files for collections with 'static' strategy\n await generateStaticDataFiles(staticCollections, distDir);\n\n // Generate A/B testing functions if experiments are running\n if (runningExperiments.length > 0) {\n await generateABFunctions(runningExperiments, distDir);\n console.log(`\\n\uD83E\uDDEA A/B testing functions generated (middleware, tracker, results API)`);\n }\n\n // Generate SEO files (robots.txt and sitemap.xml)\n if (siteUrl) {\n await generateRobotsTxt(siteUrl, distDir);\n await generateSitemap([...generatedUrls], siteUrl, distDir);\n console.log(`\\n\uD83D\uDD0D SEO files generated (robots.txt, sitemap.xml)`);\n } else {\n console.warn(`\\n\u26A0\uFE0F Skipping SEO files: siteUrl not configured in project.config.json`);\n }\n\n console.log(\"\\n\" + \"=\".repeat(50));\n console.log(`\u2728 Build complete!`);\n console.log(` \u2705 Success: ${successCount}`);\n if (errorCount > 0) {\n console.log(` \u274C Errors: ${errorCount}`);\n }\n console.log(`\\n\uD83D\uDCE6 Production files in /dist:`);\n console.log(` - *.html (Static pages with vanilla JS)`);\n console.log(` - fonts/ (Custom fonts)`);\n console.log(` - images/ (Image assets)`);\n console.log(` - icons/ (Favicon and icons)`);\n if (staticCollections.size > 0) {\n console.log(` - data/ (CMS collection data for client filtering)`);\n }\n if (existsSync(functionsDir)) {\n console.log(` - functions/ (Cloudflare Pages Functions)`);\n }\n if (runningExperiments.length > 0) {\n console.log(` - A/B testing (middleware + tracking injected)`);\n }\n if (siteUrl) {\n console.log(` - robots.txt, sitemap.xml (SEO)`);\n }\n console.log(` - No React, no client-router \u2713`);\n\n // Collect component JS validation errors\n const jsErrors = getJSValidationErrors();\n for (const { component, error } of jsErrors) {\n buildErrors.push({\n file: `components/${component}`,\n message: error,\n type: 'minify',\n });\n }\n\n // Write build errors to _errors.json for static server overlay\n if (buildErrors.length > 0) {\n // Deduplicate errors by message (same error may occur on multiple pages)\n const seenMessages = new Set<string>();\n const uniqueErrors = buildErrors.filter(err => {\n if (seenMessages.has(err.message)) return false;\n seenMessages.add(err.message);\n return true;\n });\n\n const errorsData: BuildErrorsData = {\n errors: uniqueErrors,\n timestamp: Date.now(),\n };\n await writeFile(errorsPath, JSON.stringify(errorsData, null, 2), 'utf-8');\n const countMsg = uniqueErrors.length === buildErrors.length\n ? `${uniqueErrors.length} error${uniqueErrors.length === 1 ? '' : 's'}`\n : `${uniqueErrors.length} unique error${uniqueErrors.length === 1 ? '' : 's'} (affected ${buildErrors.length} files)`;\n console.log(`\\n\u26A0\uFE0F Build errors written to dist/_errors.json (${countMsg})`);\n }\n}\n\n\n", "/**\n * A/B Testing Functions Generator\n * Generates Cloudflare Pages Functions for traffic splitting and event tracking\n * Only called at build time when experiments are running\n */\n\nimport type { Experiment } from '../../shared/types/experiments';\n\n/**\n * Generate the _middleware.ts content for traffic splitting\n */\nexport function generateMiddleware(experiments: Experiment[]): string {\n const running = experiments.filter(e => e.status === 'running');\n if (running.length === 0) return '';\n\n // Embed experiment config as JSON\n const configJSON = JSON.stringify(running.map(e => ({\n id: e.id,\n controlBranch: e.controlBranch,\n controlWeight: e.controlWeight,\n variants: e.variants.map(v => ({\n branch: v.branch,\n weight: v.weight,\n deployUrl: v.deployUrl,\n })),\n })));\n\n return `/**\n * A/B Testing Traffic Splitting Middleware\n * Auto-generated by Meno build - do not edit manually\n */\n\ninterface Env {\n AB_DB?: D1Database;\n}\n\ninterface ExperimentConfig {\n id: string;\n controlBranch: string;\n controlWeight: number;\n variants: Array<{ branch: string; weight: number; deployUrl: string }>;\n}\n\nconst EXPERIMENTS: ExperimentConfig[] = ${configJSON};\n\nfunction getCookie(request: Request, name: string): string | null {\n const cookieHeader = request.headers.get('Cookie');\n if (!cookieHeader) return null;\n const match = cookieHeader.match(new RegExp('(?:^|;\\\\\\\\s*)' + name + '=([^;]*)'));\n return match ? decodeURIComponent(match[1]) : null;\n}\n\nfunction assignVariant(experiment: ExperimentConfig): string {\n const rand = Math.random() * 100;\n let cumulative = experiment.controlWeight;\n if (rand < cumulative) return 'control';\n for (const variant of experiment.variants) {\n cumulative += variant.weight;\n if (rand < cumulative) return variant.branch;\n }\n return 'control';\n}\n\nexport async function onRequest(context: { request: Request; next: () => Promise<Response>; env: Env }) {\n const url = new URL(context.request.url);\n\n // Skip API routes and static assets\n if (url.pathname.startsWith('/api/') || url.pathname.match(/\\\\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot)$/)) {\n return context.next();\n }\n\n // Use first running experiment (single experiment at a time for simplicity)\n const experiment = EXPERIMENTS[0];\n if (!experiment) return context.next();\n\n // Check for existing variant assignment (sticky sessions)\n let variant = getCookie(context.request, 'meno_variant');\n\n // If no cookie, assign a variant\n if (!variant) {\n variant = assignVariant(experiment);\n }\n\n let response: Response;\n\n if (variant === 'control') {\n // Control: serve local assets (pass through)\n response = await context.next();\n } else {\n // Variant: proxy to branch preview deploy\n const variantConfig = experiment.variants.find(v => v.branch === variant);\n if (!variantConfig) {\n response = await context.next();\n } else {\n // Fetch from the variant's deploy URL\n const variantUrl = new URL(url.pathname + url.search, variantConfig.deployUrl);\n try {\n const proxyResponse = await fetch(variantUrl.toString(), {\n method: context.request.method,\n headers: context.request.headers,\n });\n response = new Response(proxyResponse.body, {\n status: proxyResponse.status,\n statusText: proxyResponse.statusText,\n headers: new Headers(proxyResponse.headers),\n });\n } catch {\n // Fallback to control if variant fetch fails\n response = await context.next();\n variant = 'control';\n }\n }\n }\n\n // Set variant cookie (30-day expiry)\n const headers = new Headers(response.headers);\n headers.append(\n 'Set-Cookie',\n \\`meno_variant=\\${encodeURIComponent(variant!)}; Path=/; Max-Age=2592000; SameSite=Lax\\`\n );\n\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n`;\n}\n\n/**\n * Generate the api/ab-track.ts content for event collection\n */\nexport function generateTrackFunction(): string {\n return `/**\n * A/B Testing Event Tracker\n * Auto-generated by Meno build - do not edit manually\n * POST /api/ab-track - stores pageview/conversion events in D1\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface TrackEvent {\n experimentId: string;\n visitorId: string;\n variant: string;\n eventType: 'pageview' | 'conversion';\n goalId?: string;\n url?: string;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n waitUntil: (promise: Promise<unknown>) => void;\n}\n\nexport async function onRequestPost(context: PagesContext<Env>): Promise<Response> {\n try {\n const body: TrackEvent = await context.request.json();\n\n // Validate required fields\n if (!body.experimentId || !body.visitorId || !body.variant || !body.eventType) {\n return new Response(null, { status: 400 });\n }\n\n // Validate event type\n if (body.eventType !== 'pageview' && body.eventType !== 'conversion') {\n return new Response(null, { status: 400 });\n }\n\n // Insert event into D1\n await context.env.AB_DB.prepare(\n 'INSERT INTO ab_events (experiment_id, visitor_id, variant, event_type, goal_id, url, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)'\n ).bind(\n body.experimentId,\n body.visitorId,\n body.variant,\n body.eventType,\n body.goalId || null,\n body.url || null,\n Date.now()\n ).run();\n\n return new Response(null, { status: 204 });\n } catch {\n return new Response(null, { status: 500 });\n }\n}\n`;\n}\n\n/**\n * Generate the api/ab-results.ts content for results aggregation\n */\nexport function generateResultsFunction(): string {\n return `/**\n * A/B Testing Results API\n * Auto-generated by Meno build - do not edit manually\n * GET /api/ab-results?experiment=<id> - returns aggregated results with significance\n */\n\ninterface Env {\n AB_DB: D1Database;\n}\n\ninterface PagesContext<E = unknown> {\n request: Request;\n env: E;\n params: Record<string, string>;\n}\n\ninterface VariantResult {\n variant: string;\n visitors: number;\n conversions: number;\n conversionRate: number;\n lift?: number;\n pValue?: number;\n isSignificant: boolean;\n}\n\n/**\n * Two-proportion z-test for statistical significance\n */\nfunction zTest(\n conversionsA: number, visitorsA: number,\n conversionsB: number, visitorsB: number\n): number {\n if (visitorsA === 0 || visitorsB === 0) return 1;\n\n const pA = conversionsA / visitorsA;\n const pB = conversionsB / visitorsB;\n const pPool = (conversionsA + conversionsB) / (visitorsA + visitorsB);\n\n if (pPool === 0 || pPool === 1) return 1;\n\n const se = Math.sqrt(pPool * (1 - pPool) * (1 / visitorsA + 1 / visitorsB));\n if (se === 0) return 1;\n\n const z = Math.abs(pA - pB) / se;\n\n // Approximate two-tailed p-value using rational approximation\n const t = 1 / (1 + 0.2316419 * z);\n const d = 0.3989422804014327;\n const p = d * Math.exp(-z * z / 2) * t * (0.3193815 + t * (-0.3565638 + t * (1.781478 + t * (-1.821256 + t * 1.330274))));\n return 2 * p;\n}\n\nexport async function onRequestGet(context: PagesContext<Env>): Promise<Response> {\n const url = new URL(context.request.url);\n const experimentId = url.searchParams.get('experiment');\n\n if (!experimentId) {\n return Response.json({ error: 'Missing experiment parameter' }, { status: 400 });\n }\n\n try {\n // Get unique visitors per variant\n const visitorsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as visitors FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'pageview\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Get conversions per variant\n const conversionsResult = await context.env.AB_DB.prepare(\n 'SELECT variant, COUNT(DISTINCT visitor_id) as conversions FROM ab_events WHERE experiment_id = ? AND event_type = \\\\'conversion\\\\' GROUP BY variant'\n ).bind(experimentId).all();\n\n // Build results map\n const visitorMap = new Map<string, number>();\n const conversionMap = new Map<string, number>();\n\n for (const row of (visitorsResult.results || [])) {\n visitorMap.set(row.variant as string, row.visitors as number);\n }\n for (const row of (conversionsResult.results || [])) {\n conversionMap.set(row.variant as string, row.conversions as number);\n }\n\n // Get all variant names\n const allVariants = new Set([...visitorMap.keys(), ...conversionMap.keys()]);\n\n // Calculate results\n const variants: VariantResult[] = [];\n let controlVisitors = 0;\n let controlConversions = 0;\n\n for (const variant of allVariants) {\n const visitors = visitorMap.get(variant) || 0;\n const conversions = conversionMap.get(variant) || 0;\n const conversionRate = visitors > 0 ? conversions / visitors : 0;\n\n if (variant === 'control') {\n controlVisitors = visitors;\n controlConversions = conversions;\n }\n\n variants.push({\n variant,\n visitors,\n conversions,\n conversionRate,\n isSignificant: false,\n });\n }\n\n // Calculate lift and significance for non-control variants\n const controlRate = controlVisitors > 0 ? controlConversions / controlVisitors : 0;\n for (const result of variants) {\n if (result.variant !== 'control' && controlVisitors > 0) {\n result.lift = controlRate > 0\n ? ((result.conversionRate - controlRate) / controlRate) * 100\n : 0;\n result.pValue = zTest(\n controlConversions, controlVisitors,\n result.conversions, result.visitors\n );\n result.isSignificant = result.pValue < 0.05;\n }\n }\n\n // Sort: control first, then by variant name\n variants.sort((a, b) => {\n if (a.variant === 'control') return -1;\n if (b.variant === 'control') return 1;\n return a.variant.localeCompare(b.variant);\n });\n\n return Response.json({\n experimentId,\n variants,\n }, {\n headers: {\n 'Access-Control-Allow-Origin': '*',\n 'Cache-Control': 'no-cache',\n }\n });\n } catch (error) {\n return Response.json({ error: 'Failed to query results' }, { status: 500 });\n }\n}\n`;\n}\n", "/**\n * A/B Testing Tracking Script Generator\n * Generates a lightweight client-side tracking script to be injected into HTML\n */\n\nimport type { ConversionGoal } from '../../shared/types/experiments';\n\n/**\n * Generate the tracking script content with embedded experiment config\n */\nexport function generateTrackingScript(experimentId: string, goals: ConversionGoal[]): string {\n const goalsJSON = JSON.stringify(goals);\n\n return `(function(){\nvar EXP_ID=${JSON.stringify(experimentId)};\nvar GOALS=${goalsJSON};\n\nfunction getCookie(n){var m=document.cookie.match(new RegExp('(?:^|;\\\\\\\\s*)'+n+'=([^;]*)'));return m?decodeURIComponent(m[1]):null}\nfunction setCookie(n,v,d){var e=new Date();e.setTime(e.getTime()+d*864e5);document.cookie=n+'='+encodeURIComponent(v)+';path=/;expires='+e.toUTCString()+';SameSite=Lax'}\n\nvar variant=getCookie('meno_variant')||'control';\nvar visitor=getCookie('meno_visitor');\nif(!visitor){visitor=Math.random().toString(36).slice(2)+Date.now().toString(36);setCookie('meno_visitor',visitor,365)}\n\nfunction track(type,goalId){\ntry{navigator.sendBeacon('/api/ab-track',JSON.stringify({experimentId:EXP_ID,visitorId:visitor,variant:variant,eventType:type,goalId:goalId||null,url:location.pathname}))}catch(e){}\n}\n\ntrack('pageview');\n\nGOALS.forEach(function(g){\nif(g.type==='click'&&g.selector){\ndocument.addEventListener('click',function(e){\nif(e.target&&e.target.closest&&e.target.closest(g.selector)){track('conversion',g.id)}\n})\n}\nif(g.type==='navigation'&&g.url){\nif(location.pathname===g.url||location.href.indexOf(g.url)>-1){track('conversion',g.id)}\n}\nif(g.type==='custom'&&g.event){\nwindow.addEventListener(g.event,function(){track('conversion',g.id)})\n}\n});\n})();`;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["minifyJS", "isDevBuild"]
7
7
  }