meno-core 1.0.52 → 1.0.53

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 (135) hide show
  1. package/build-astro.ts +183 -13
  2. package/build-next.ts +1361 -0
  3. package/build-static.ts +7 -5
  4. package/dist/bin/cli.js +2 -2
  5. package/dist/build-static.js +6 -6
  6. package/dist/chunks/{chunk-HNLUO36W.js → chunk-GZHGVVW3.js} +2 -2
  7. package/dist/chunks/chunk-GZHGVVW3.js.map +7 -0
  8. package/dist/chunks/{chunk-LPVETICS.js → chunk-H3GJ4H2U.js} +185 -1
  9. package/dist/chunks/chunk-H3GJ4H2U.js.map +7 -0
  10. package/dist/chunks/{chunk-CXCBV2M7.js → chunk-IGYR22T6.js} +76 -270
  11. package/dist/chunks/chunk-IGYR22T6.js.map +7 -0
  12. package/dist/chunks/{chunk-LHLHPYSP.js → chunk-JGP5A3Y5.js} +12 -11
  13. package/dist/chunks/chunk-JGP5A3Y5.js.map +7 -0
  14. package/dist/chunks/{chunk-7NIC4I3V.js → chunk-JGWFTO6P.js} +167 -21
  15. package/dist/chunks/chunk-JGWFTO6P.js.map +7 -0
  16. package/dist/chunks/{chunk-EDQSMAMP.js → chunk-O3NAGJP4.js} +85 -4
  17. package/dist/chunks/chunk-O3NAGJP4.js.map +7 -0
  18. package/dist/chunks/{chunk-H4JSCDNW.js → chunk-QB2LNO4W.js} +24 -1
  19. package/dist/chunks/chunk-QB2LNO4W.js.map +7 -0
  20. package/dist/chunks/{chunk-A725KYFK.js → chunk-R6XHAFBF.js} +561 -112
  21. package/dist/chunks/chunk-R6XHAFBF.js.map +7 -0
  22. package/dist/chunks/{chunk-J23ZX5AP.js → chunk-X754AHS5.js} +277 -1
  23. package/dist/chunks/chunk-X754AHS5.js.map +7 -0
  24. package/dist/chunks/{chunk-2QK6U5UK.js → chunk-YBLHKYFF.js} +12 -2
  25. package/dist/chunks/chunk-YBLHKYFF.js.map +7 -0
  26. package/dist/chunks/{constants-GWBAD66U.js → constants-STK2YBIW.js} +2 -2
  27. package/dist/entries/server-router.js +7 -7
  28. package/dist/lib/client/index.js +354 -59
  29. package/dist/lib/client/index.js.map +4 -4
  30. package/dist/lib/server/index.js +1458 -190
  31. package/dist/lib/server/index.js.map +4 -4
  32. package/dist/lib/shared/index.js +202 -34
  33. package/dist/lib/shared/index.js.map +4 -4
  34. package/dist/lib/test-utils/index.js +1 -1
  35. package/entries/client-router.tsx +5 -165
  36. package/lib/client/ErrorBoundary.test.tsx +27 -25
  37. package/lib/client/ErrorBoundary.tsx +34 -19
  38. package/lib/client/core/ComponentBuilder.ts +19 -2
  39. package/lib/client/core/builders/embedBuilder.ts +8 -4
  40. package/lib/client/core/builders/listBuilder.ts +23 -4
  41. package/lib/client/fontFamiliesService.test.ts +76 -0
  42. package/lib/client/fontFamiliesService.ts +69 -0
  43. package/lib/client/hmrCssReload.ts +160 -0
  44. package/lib/client/hooks/useColorVariables.ts +2 -0
  45. package/lib/client/index.ts +4 -0
  46. package/lib/client/meno-filter/ui.ts +2 -0
  47. package/lib/client/routing/RouteLoader.test.ts +2 -2
  48. package/lib/client/routing/RouteLoader.ts +8 -2
  49. package/lib/client/routing/Router.tsx +81 -15
  50. package/lib/client/scripts/ScriptExecutor.test.ts +143 -0
  51. package/lib/client/scripts/ScriptExecutor.ts +56 -2
  52. package/lib/client/styles/StyleInjector.ts +20 -5
  53. package/lib/client/styles/UtilityClassCollector.ts +7 -1
  54. package/lib/client/styles/cspNonce.test.ts +67 -0
  55. package/lib/client/styles/cspNonce.ts +63 -0
  56. package/lib/client/templateEngine.test.ts +80 -0
  57. package/lib/client/templateEngine.ts +5 -0
  58. package/lib/server/astro/cmsPageEmitter.ts +35 -5
  59. package/lib/server/astro/componentEmitter.ts +61 -5
  60. package/lib/server/astro/nodeToAstro.ts +149 -11
  61. package/lib/server/astro/normalizeOrphanTemplateProps.test.ts +264 -0
  62. package/lib/server/astro/normalizeOrphanTemplateProps.ts +184 -0
  63. package/lib/server/createServer.ts +11 -0
  64. package/lib/server/draftPageStore.ts +49 -0
  65. package/lib/server/fileWatcher.ts +62 -2
  66. package/lib/server/index.ts +13 -1
  67. package/lib/server/providers/fileSystemPageProvider.ts +8 -0
  68. package/lib/server/routes/api/components.ts +9 -4
  69. package/lib/server/routes/api/core-routes.ts +2 -2
  70. package/lib/server/routes/api/pages.ts +14 -22
  71. package/lib/server/routes/api/shared.ts +56 -0
  72. package/lib/server/routes/index.ts +90 -0
  73. package/lib/server/routes/pages.ts +13 -6
  74. package/lib/server/services/componentService.test.ts +199 -2
  75. package/lib/server/services/componentService.ts +354 -49
  76. package/lib/server/services/fileWatcherService.ts +4 -24
  77. package/lib/server/services/pageService.test.ts +23 -0
  78. package/lib/server/services/pageService.ts +124 -6
  79. package/lib/server/ssr/attributeBuilder.ts +8 -2
  80. package/lib/server/ssr/buildErrorOverlay.ts +1 -1
  81. package/lib/server/ssr/errorOverlay.test.ts +21 -2
  82. package/lib/server/ssr/errorOverlay.ts +38 -11
  83. package/lib/server/ssr/htmlGenerator.test.ts +53 -13
  84. package/lib/server/ssr/htmlGenerator.ts +71 -27
  85. package/lib/server/ssr/liveReloadIntegration.test.ts +123 -2
  86. package/lib/server/ssr/ssrRenderer.test.ts +67 -0
  87. package/lib/server/ssr/ssrRenderer.ts +94 -9
  88. package/lib/server/websocketManager.ts +0 -1
  89. package/lib/shared/componentRefs.ts +45 -0
  90. package/lib/shared/constants.ts +8 -0
  91. package/lib/shared/cssGeneration.ts +2 -0
  92. package/lib/shared/cssProperties.ts +184 -0
  93. package/lib/shared/expressionEvaluator.ts +54 -0
  94. package/lib/shared/fontCss.ts +101 -0
  95. package/lib/shared/fontLoader.ts +8 -86
  96. package/lib/shared/friendlyError.test.ts +87 -0
  97. package/lib/shared/friendlyError.ts +121 -0
  98. package/lib/shared/hrefRefs.test.ts +130 -0
  99. package/lib/shared/hrefRefs.ts +100 -0
  100. package/lib/shared/index.ts +52 -0
  101. package/lib/shared/inlineSvgStyleRules.test.ts +108 -0
  102. package/lib/shared/inlineSvgStyleRules.ts +134 -0
  103. package/lib/shared/interfaces/contentProvider.ts +13 -0
  104. package/lib/shared/itemTemplateUtils.test.ts +14 -0
  105. package/lib/shared/itemTemplateUtils.ts +4 -1
  106. package/lib/shared/registry/NodeTypeDefinition.ts +1 -1
  107. package/lib/shared/registry/nodeTypes/LinkNodeType.ts +1 -1
  108. package/lib/shared/slugTranslator.test.ts +24 -0
  109. package/lib/shared/slugTranslator.ts +24 -0
  110. package/lib/shared/styleNodeUtils.ts +4 -1
  111. package/lib/shared/tree/PathBuilder.test.ts +128 -1
  112. package/lib/shared/tree/PathBuilder.ts +83 -31
  113. package/lib/shared/types/comment.ts +99 -0
  114. package/lib/shared/types/index.ts +12 -0
  115. package/lib/shared/types/rendering.ts +8 -0
  116. package/lib/shared/utilityClassConfig.ts +4 -2
  117. package/lib/shared/utilityClassMapper.test.ts +24 -0
  118. package/lib/shared/validation/commentValidators.ts +69 -0
  119. package/lib/shared/validation/index.ts +1 -0
  120. package/lib/shared/viewportUnits.integration.test.ts +42 -0
  121. package/lib/shared/viewportUnits.test.ts +103 -0
  122. package/lib/shared/viewportUnits.ts +63 -0
  123. package/lib/test-utils/dom-setup.ts +6 -0
  124. package/package.json +1 -1
  125. package/dist/chunks/chunk-2QK6U5UK.js.map +0 -7
  126. package/dist/chunks/chunk-7NIC4I3V.js.map +0 -7
  127. package/dist/chunks/chunk-A725KYFK.js.map +0 -7
  128. package/dist/chunks/chunk-CXCBV2M7.js.map +0 -7
  129. package/dist/chunks/chunk-EDQSMAMP.js.map +0 -7
  130. package/dist/chunks/chunk-H4JSCDNW.js.map +0 -7
  131. package/dist/chunks/chunk-HNLUO36W.js.map +0 -7
  132. package/dist/chunks/chunk-J23ZX5AP.js.map +0 -7
  133. package/dist/chunks/chunk-LHLHPYSP.js.map +0 -7
  134. package/dist/chunks/chunk-LPVETICS.js.map +0 -7
  135. /package/dist/chunks/{constants-GWBAD66U.js.map → constants-STK2YBIW.js.map} +0 -0
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../lib/client/templateEngine.ts", "../../lib/shared/styleNodeUtils.ts", "../../lib/shared/attributeNodeUtils.ts"],
4
- "sourcesContent": ["/**\n * Template Engine\n * Handles template evaluation with {{expression}} syntax and style mappings\n *\n * Security: Uses jsep for safe expression parsing instead of eval/new Function()\n */\n\nimport type { StyleMapping, HtmlMapping, ComponentDefinition, StructuredComponentDefinition, ComponentNode, HtmlNode, ComponentInstanceNode, EmbedNode, SlotMarker, StyleObject, ResponsiveStyleObject, StyleValue, TemplateContext } from '../shared/types';\nimport { isResponsiveStyle } from '../shared/styleUtils';\nimport { normalizeStyle as normalizeStyleShared, mergeResponsiveStyles } from '../shared/responsiveStyleUtils';\nimport { DEFAULT_BREAKPOINTS } from '../shared/breakpoints';\nimport { NODE_TYPE } from '../shared/constants';\nimport { isValidNodeType, isComponentNode, isHtmlNode, isSlotMarker, isEmbedNode, isLocaleListNode, isLinkNode, isCMSListNode, isListNode } from '../shared/nodeUtils';\nimport { applyStylesToNode } from '../shared/styleNodeUtils';\nimport { isRichTextMarker, richTextMarkerToHtml } from '../shared/propResolver';\nimport { isTiptapDocument, tiptapToHtml } from '../shared/richtext';\nimport { hasItemTemplates } from '../shared/itemTemplateUtils';\nimport { safeEvaluate } from '../shared/expressionEvaluator';\nimport { RAW_HTML_PREFIX } from '../shared/constants';\nimport { getGlobalTemplateContext } from '../shared/globalTemplateContext';\n\n// Re-export for backward compatibility\nexport { isResponsiveStyle };\n\n/**\n * Normalize a style value - if it's responsive, merge it; if it's flat, return as-is\n * Uses 'all' strategy for editor compatibility (merges all breakpoints)\n */\nexport function normalizeStyle(style: StyleValue | null | undefined): StyleObject | null {\n return normalizeStyleShared(style, 'all');\n}\n\n/**\n * Helper to add a processed item to an array, handling both single items and arrays\n * Converts numbers to strings to match ComponentNode['children'] type\n */\nfunction addProcessedItemToArray(\n item: ComponentNode | (ComponentNode | string)[] | string | number | Record<string, unknown> | null,\n array: Array<ComponentNode | string>\n): void {\n if (item === null) return;\n\n if (Array.isArray(item)) {\n array.push(...item);\n } else if (typeof item === 'number') {\n // Convert numbers to strings to match ComponentNode['children'] type\n array.push(String(item));\n } else {\n array.push(item as ComponentNode | string);\n }\n}\n\n/**\n * Link mapping interface for link nodes\n */\nexport interface LinkMapping {\n _mapping: true;\n prop: string;\n values?: Record<string, { href: string; target?: string }>;\n}\n\n/**\n * Type guard for link mappings\n */\nexport function isLinkMapping(value: unknown): value is LinkMapping {\n if (!value || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n // values is optional - when empty/missing, acts as passthrough for link-type props\n return obj._mapping === true && typeof obj.prop === 'string' && (obj.values === undefined || typeof obj.values === 'object');\n}\n\n/**\n * Resolves a link mapping object to its actual value based on current props\n *\n * Supports two modes:\n * 1. Value mapping: Maps a prop value to a predefined link object\n * { _mapping: true, prop: \"variant\", values: { primary: { href: \"/products\" } } }\n *\n * 2. Passthrough: When values is empty/missing, uses the prop directly if it's a link object\n * { _mapping: true, prop: \"link\" } - uses props.link directly\n *\n * @example\n * // Value mapping\n * resolveLinkMapping(\n * { _mapping: true, prop: \"variant\", values: { primary: { href: \"/products\" } } },\n * { variant: \"primary\" }\n * ) // { href: \"/products\" }\n *\n * @example\n * // Passthrough mode\n * resolveLinkMapping(\n * { _mapping: true, prop: \"link\" },\n * { link: { href: \"/about\", target: \"_blank\" } }\n * ) // { href: \"/about\", target: \"_blank\" }\n */\nexport function resolveLinkMapping(\n mappingObj: unknown,\n props: Record<string, unknown> | undefined\n): { href: string; target?: string } | undefined {\n if (!isLinkMapping(mappingObj)) {\n return undefined;\n }\n\n // Guard against undefined props\n if (!props) {\n return undefined;\n }\n\n const { prop, values } = mappingObj;\n const propValue = props[prop];\n if (propValue === undefined || propValue === null) {\n return undefined;\n }\n\n // Passthrough mode: if prop value is already a link object, use it directly\n if (typeof propValue === 'object' && propValue !== null && 'href' in propValue) {\n return propValue as { href: string; target?: string };\n }\n\n // Value mapping mode: look up the prop value in the values map\n if (values) {\n const mappedValue = values[String(propValue)];\n return mappedValue;\n }\n\n return undefined;\n}\n\n/**\n * Type guard for HTML mappings (embed node html property)\n */\nexport function isHtmlMapping(value: unknown): value is HtmlMapping {\n if (!value || typeof value !== 'object') return false;\n const obj = value as Record<string, unknown>;\n return obj._mapping === true && typeof obj.prop === 'string';\n}\n\n/**\n * Resolves an HTML mapping object to its actual value based on current props\n *\n * Supports two modes:\n * 1. Value mapping: Maps a prop value to a predefined HTML string\n * { _mapping: true, prop: \"icon\", values: { arrow: \"<svg>...</svg>\", check: \"<svg>...</svg>\" } }\n *\n * 2. Passthrough: When values is omitted/empty, uses the prop directly if it's a string\n * { _mapping: true, prop: \"svgContent\" } - uses props.svgContent directly\n */\nexport function resolveHtmlMapping(\n mappingObj: unknown,\n props: Record<string, unknown> | undefined\n): string | undefined {\n if (!isHtmlMapping(mappingObj)) {\n return undefined;\n }\n\n if (!props) {\n return undefined;\n }\n\n const { prop, values } = mappingObj;\n const propValue = props[prop];\n if (propValue === undefined || propValue === null) {\n return undefined;\n }\n\n // Value mapping mode: look up the prop value in the values map\n if (values && Object.keys(values).length > 0) {\n return values[String(propValue)];\n }\n\n // Passthrough mode: use the prop value directly if it's a string\n if (typeof propValue === 'string') {\n return propValue;\n }\n\n return undefined;\n}\n\n/**\n * Resolves a style mapping object to its actual value based on current props\n *\n * @example\n * resolveStyleMapping(\n * { _mapping: true, prop: \"variant\", values: { primary: \"#0070f3\", secondary: \"#f3f4f6\" } },\n * { variant: \"primary\" }\n * ) // \"#0070f3\"\n */\nexport function resolveStyleMapping(\n mappingObj: unknown,\n props: Record<string, unknown> | undefined\n): string | number | undefined {\n if (!mappingObj || typeof mappingObj !== 'object') {\n return undefined;\n }\n\n const mapping = mappingObj as StyleMapping;\n if (!mapping || !mapping._mapping) {\n return undefined;\n }\n\n const { prop, values } = mapping;\n if (!prop || !values || typeof values !== 'object') {\n return undefined;\n }\n\n // Guard against undefined props\n if (!props) {\n return undefined;\n }\n\n const propValue = props[prop];\n if (propValue === undefined || propValue === null) {\n return undefined;\n }\n\n const mappedValue = values[String(propValue)];\n return mappedValue !== undefined ? mappedValue : undefined;\n}\n\n/**\n * Process a single style value - resolves mappings and evaluates templates.\n * Skips item templates ({{item.field}}, {{varName.field}}) which are resolved later during rendering.\n *\n * @param styleValue - The style value to process (may be string, number, or mapping object)\n * @param props - Component props for resolving mappings and templates\n * @returns The processed style value, or undefined if the value should be skipped\n */\nfunction processStyleValue(\n styleValue: unknown,\n props: Record<string, unknown> | undefined\n): string | number | undefined {\n // First try style mapping resolution\n const resolved = resolveStyleMapping(styleValue, props);\n if (resolved !== undefined) {\n return resolved;\n }\n\n // String values - evaluate templates (but skip item templates)\n if (typeof styleValue === 'string') {\n if (hasTemplates(styleValue) && !hasItemTemplates(styleValue)) {\n return processCodeTemplates(styleValue, props);\n }\n return styleValue;\n }\n\n // Number values - pass through\n if (typeof styleValue === 'number') {\n return styleValue;\n }\n\n return undefined;\n}\n\n/**\n * Build evaluation context for template processing.\n * Merges global context, props, componentDef, and optionally itemContext.\n *\n * @param context - The TemplateContext containing props and componentDef\n * @param includeItemContext - Whether to include itemContext from the context object\n * @returns A flat object suitable for template evaluation\n */\nfunction buildEvalContext(\n context: TemplateContext,\n includeItemContext: boolean = false\n): Record<string, unknown> {\n const evalContext: Record<string, unknown> = {\n ...getGlobalTemplateContext(),\n ...context.props\n };\n\n if (context.componentDef && typeof context.componentDef === 'object') {\n Object.assign(evalContext, context.componentDef as Record<string, unknown>);\n }\n\n if (includeItemContext) {\n const itemContext = (context as Record<string, unknown>).itemContext as Record<string, unknown> | undefined;\n if (itemContext) {\n Object.assign(evalContext, itemContext);\n }\n }\n\n return evalContext;\n}\n\n/** Maximum allowed expression length to prevent DoS via complex expressions */\nconst MAX_EXPRESSION_LENGTH = 500;\n\n/** Maximum recursion depth to prevent stack overflow from circular references */\nconst MAX_RECURSION_DEPTH = 100;\n\n/**\n * Evaluates a template string with the given context\n * Template format: {{expression}}\n * Handles undefined variables gracefully by returning undefined instead of throwing\n *\n * Security: Uses jsep for safe expression parsing - only whitelisted AST nodes are evaluated.\n * No eval/new Function is used, preventing arbitrary code execution.\n *\n * @example\n * evaluateTemplate(\"{{name}}\", { name: \"John\" }) // \"John\"\n * evaluateTemplate(\"{{count + 1}}\", { count: 5 }) // 6\n * evaluateTemplate(\"{{undefinedVar}}\", {}) // undefined (no error thrown)\n */\nexport function evaluateTemplate(\n template: string,\n context: Record<string, unknown>\n): unknown {\n if (typeof template !== 'string') return template;\n\n const templateMatch = template.match(/^\\{\\{(.+)\\}\\}$/);\n if (!templateMatch) return template;\n\n const expression = templateMatch[1].trim();\n\n // Security: Expression length limit to prevent DoS\n if (expression.length > MAX_EXPRESSION_LENGTH) {\n console.warn('Template expression too long:', expression.slice(0, 50) + '...');\n return template;\n }\n\n try {\n // Use safe expression evaluator (jsep-based, no eval/new Function)\n const result = safeEvaluate(expression, context);\n // If result is undefined, return template string for backward compatibility\n return result === undefined ? template : result;\n } catch (error) {\n console.error('Template evaluation error:', error, 'Expression:', expression, 'Context:', context);\n // Return original template string on error for backward compatibility\n return template;\n }\n}\n\n/**\n * Checks if a code string contains any template patterns {{...}}\n */\nexport function hasTemplates(code: string): boolean {\n if (typeof code !== 'string') return false;\n return /\\{\\{[^}]+\\}\\}/.test(code);\n}\n\n/**\n * Processes template strings in JavaScript or CSS code\n * Replaces {{propName}} or {{expression}} with evaluated values\n * \n * @example\n * processCodeTemplates(\"console.log('{{name}}');\", { name: \"John\" })\n * // \"console.log('John');\"\n * \n * processCodeTemplates(\".card { color: {{color}}; }\", { color: \"#ff0000\" })\n * // \".card { color: #ff0000; }\"\n */\nexport function processCodeTemplates(\n code: string,\n context: Record<string, unknown> | undefined\n): string {\n if (typeof code !== 'string') return code;\n\n // Guard against undefined context\n if (!context) {\n return code;\n }\n\n // Match all {{...}} patterns in the code\n return code.replace(/\\{\\{([^}]+)\\}\\}/g, (match: string, expression: string): string => {\n const trimmedExpr = expression.trim();\n\n // Security: Expression length limit to prevent DoS\n if (trimmedExpr.length > MAX_EXPRESSION_LENGTH) {\n console.warn('Code template expression too long:', trimmedExpr.slice(0, 50) + '...');\n return match;\n }\n\n try {\n // Use safe expression evaluator (jsep-based, no eval/new Function)\n const result = safeEvaluate(trimmedExpr, context);\n\n // Convert result to string, handling various types\n if (result === null || result === undefined) {\n return '';\n }\n if (typeof result === 'string') {\n return result;\n }\n if (typeof result === 'number' || typeof result === 'boolean') {\n return String(result);\n }\n // Handle rich-text markers - extract HTML content for interpolation\n if (isRichTextMarker(result)) {\n return richTextMarkerToHtml(result);\n }\n // For objects/arrays, stringify them\n return JSON.stringify(result);\n } catch (error) {\n console.error('Code template evaluation error:', error, 'Expression:', trimmedExpr, 'Context:', context);\n // Return original template if evaluation fails\n return match;\n }\n });\n}\n\n/**\n * Processes a component structure recursively, evaluating templates\n * @param context - Template context containing props, componentDef, and extensible namespaces (e.g., cms, page)\n * @param viewportWidth - Optional viewport width for responsive style resolution. If provided, uses 'viewport' strategy; otherwise uses 'all' strategy.\n * @param instanceChildren - Optional children from component instance to replace { type: \"children\" } markers\n * @param preserveResponsiveStyles - Whether to preserve responsive style objects (for SSR)\n * @param depth - Internal recursion depth counter to prevent stack overflow\n */\nexport function processStructure(\n structure: ComponentNode | ComponentNode[] | string | number | null | undefined,\n context: TemplateContext,\n viewportWidth?: number,\n instanceChildren?: ComponentNode['children'],\n preserveResponsiveStyles: boolean = false,\n depth: number = 0\n): ComponentNode | (ComponentNode | string)[] | string | number | Record<string, unknown> | null {\n try {\n // Guard against excessive recursion (circular references or very deep structures)\n if (depth > MAX_RECURSION_DEPTH) {\n console.warn(`processStructure: Maximum recursion depth (${MAX_RECURSION_DEPTH}) exceeded. Possible circular reference.`);\n return null;\n }\n\n // Handle null/undefined\n if (structure === null || structure === undefined) return null;\n\n // Preserve boolean values (don't convert false to null)\n if (typeof structure === 'boolean') {\n return structure;\n }\n\n if (typeof structure === 'string') {\n // Build evaluation context with item context for nested template resolution\n const evalContext = buildEvalContext(context, true);\n\n // Check if entire string is a complete template {{expr}}\n // Use evaluateTemplate to preserve type (objects, arrays, numbers)\n if (/^\\{\\{.+\\}\\}$/.test(structure) && !hasItemTemplates(structure)) {\n const result = evaluateTemplate(structure, evalContext);\n // Check for rich-text marker - extract HTML content with RAW_HTML_PREFIX\n // The prefix signals to ComponentBuilder.processTextNode to render as HTML\n if (isRichTextMarker(result)) {\n return RAW_HTML_PREFIX + richTextMarkerToHtml(result);\n }\n if (typeof result === 'string' || typeof result === 'number') {\n return result;\n }\n if (result === undefined || result === null) {\n return '';\n }\n // Return objects as-is (e.g., link objects { href, target })\n // The caller (e.g., href handling) will process them appropriately\n if (typeof result === 'object') {\n return result as Record<string, unknown>;\n }\n return String(result);\n }\n\n // Check if string contains partial templates like \"heading-{{size}}\"\n // Use processCodeTemplates for string interpolation\n // BUT skip if it contains CMS item templates ({{item.field}}, {{varName.field}}, etc.)\n // Those will be processed later by processItemTemplate with proper context\n if (hasTemplates(structure) && !hasItemTemplates(structure)) {\n return processCodeTemplates(structure, evalContext);\n }\n\n // No templates - return as-is\n return structure;\n }\n \n if (Array.isArray(structure)) {\n const processed: Array<ComponentNode | string> = [];\n for (const item of structure) {\n // Check if this is a slot marker\n if (isSlotMarker(item)) {\n // Replace marker with instance children (if provided)\n if (instanceChildren) {\n const childrenArray = Array.isArray(instanceChildren) ? instanceChildren : [instanceChildren];\n for (const child of childrenArray) {\n const processedChild = processStructure(child, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n addProcessedItemToArray(processedChild, processed);\n }\n } else if ('default' in item && (item as SlotMarker).default !== undefined) {\n // Fallback: use slot's default content if no instance children provided\n const defaultContent = (item as SlotMarker).default;\n const defaultsArray = Array.isArray(defaultContent) ? defaultContent : [defaultContent];\n for (const defaultChild of defaultsArray) {\n const processedChild = processStructure(defaultChild, context, viewportWidth, undefined, preserveResponsiveStyles, depth + 1);\n addProcessedItemToArray(processedChild, processed);\n }\n }\n // If no instance children AND no default, marker renders nothing (skip it)\n } else {\n // Regular item - process normally\n const processedItem = processStructure(item, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n addProcessedItemToArray(processedItem, processed);\n }\n }\n return processed;\n }\n \n if (typeof structure === 'object' && !Array.isArray(structure) && structure !== null) {\n // Check if this is a slot marker (shouldn't happen here since we handle it in array processing, but guard anyway)\n if (isSlotMarker(structure)) {\n // This shouldn't happen in object processing, but if it does, return instance children or default\n if (instanceChildren) {\n const processed: Array<ComponentNode | string> = [];\n const childrenArray = Array.isArray(instanceChildren) ? instanceChildren : [instanceChildren];\n for (const child of childrenArray) {\n const processedChild = processStructure(child, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n addProcessedItemToArray(processedChild, processed);\n }\n return processed.length === 1 ? processed[0] : processed;\n }\n // Fallback: use slot's default content\n if ('default' in structure && (structure as SlotMarker).default !== undefined) {\n const defaultContent = (structure as SlotMarker).default;\n const processed: Array<ComponentNode | string> = [];\n const defaultsArray = Array.isArray(defaultContent) ? defaultContent : [defaultContent];\n for (const defaultChild of defaultsArray) {\n const processedChild = processStructure(defaultChild, context, viewportWidth, undefined, preserveResponsiveStyles, depth + 1);\n addProcessedItemToArray(processedChild, processed);\n }\n return processed.length === 1 ? processed[0] : processed;\n }\n return null;\n }\n \n // Check if this is a valid node structure or a plain object (like props)\n const inputNode = structure as ComponentNode;\n const hasValidNodeType = inputNode.type && isValidNodeType(inputNode.type);\n\n // If no valid node type, treat as plain object and process values recursively\n // This handles props objects like { text: \"{{text}}\", isMarginBottom: false }\n if (!hasValidNodeType) {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(structure)) {\n const processedValue = processStructure(value as ComponentNode | string | number | null, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n if (processedValue !== null && processedValue !== undefined) {\n result[key] = processedValue;\n }\n }\n return result;\n }\n\n const preservedType = inputNode.type;\n\n // Create base processed object based on type\n let processed: ComponentNode;\n if (preservedType === NODE_TYPE.COMPONENT) {\n processed = {\n type: NODE_TYPE.COMPONENT,\n component: '',\n props: {},\n children: [] as Array<ComponentNode | string>\n } as ComponentInstanceNode;\n } else if (preservedType === NODE_TYPE.EMBED) {\n // Handle embed nodes - they have html content, not children\n processed = {\n type: NODE_TYPE.EMBED,\n html: '',\n } as unknown as ComponentNode;\n } else if (preservedType === NODE_TYPE.LINK) {\n // Handle link nodes - they have href property\n processed = {\n type: NODE_TYPE.LINK,\n href: '',\n children: [] as Array<ComponentNode | string>\n } as unknown as ComponentNode;\n } else if (preservedType === NODE_TYPE.LOCALE_LIST) {\n // Handle locale-list nodes - they have style, itemStyle, activeItemStyle properties\n processed = {\n type: NODE_TYPE.LOCALE_LIST,\n } as unknown as ComponentNode;\n } else if (preservedType === NODE_TYPE.LIST || (preservedType as string) === 'cms-list') {\n // Handle list nodes (unified - handles both prop and collection source types)\n // Also supports legacy 'cms-list' type for migration\n processed = {\n type: NODE_TYPE.LIST,\n source: '',\n children: [] as Array<ComponentNode | string>\n } as unknown as ComponentNode;\n } else {\n processed = {\n type: NODE_TYPE.NODE,\n tag: 'div',\n children: [] as Array<ComponentNode | string>\n } as HtmlNode;\n }\n \n // First pass: process all keys and resolve style mappings\n let resolvedStyle: StyleValue | null = null;\n \n for (const [key, value] of Object.entries(structure)) {\n try {\n if (key === 'children') {\n const processedChildren = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n if (Array.isArray(processedChildren)) {\n processed.children = processedChildren;\n } else if (processedChildren !== null && processedChildren !== undefined) {\n processed.children = [processedChildren as ComponentNode | string];\n }\n } else if (key === 'tag') {\n // Handle tag for HTML nodes\n if (isHtmlNode(processed)) {\n if (typeof value === 'string') {\n // Process template in tag (e.g., \"h{{size}}\" -> \"h1\")\n const evalContext = buildEvalContext(context, false);\n // Use processCodeTemplates to handle partial templates like \"h{{size}}\"\n processed.tag = processCodeTemplates(value, evalContext);\n } else if (value === false) {\n // Preserve boolean false for fragment mode (no container)\n (processed as Record<string, unknown>).tag = false;\n } else {\n processed.tag = String(value);\n }\n }\n } else if (key === 'component') {\n if (isComponentNode(processed)) {\n if (typeof value === 'string') {\n processed.component = value;\n } else {\n processed.component = String(value);\n }\n }\n } else if (key === 'html') {\n // Handle html property for embed nodes - process templates like {{propName}}\n if (preservedType === NODE_TYPE.EMBED && isEmbedNode(processed)) {\n if (isHtmlMapping(value)) {\n // Resolve HTML mapping to actual content\n const resolved = resolveHtmlMapping(value, context.props);\n processed.html = resolved ?? '';\n } else if (typeof value === 'string') {\n // Build evaluation context with item context for nested template resolution\n const evalContext = buildEvalContext(context, true);\n // Check if entire string is a complete template {{expr}}\n if (/^\\{\\{.+\\}\\}$/.test(value) && !hasItemTemplates(value)) {\n const result = evaluateTemplate(value, evalContext);\n processed.html = result === undefined || result === null ? '' : String(result);\n } else if (hasTemplates(value) && !hasItemTemplates(value)) {\n // Use processCodeTemplates to handle partial templates\n processed.html = processCodeTemplates(value, evalContext);\n } else {\n processed.html = value;\n }\n } else if (typeof value === 'object' && value !== null && (value as Record<string, unknown>)._mapping === true) {\n // HtmlMapping object that isHtmlMapping somehow missed \u2014 resolve it defensively\n const resolved = resolveHtmlMapping(value, context.props);\n processed.html = resolved ?? '';\n } else {\n processed.html = '';\n }\n }\n } else if (key === 'type') {\n // Preserve type field if valid - but don't change the structure type\n if (typeof value === 'string' && isValidNodeType(value)) {\n // Only update if type actually changed\n if (value === NODE_TYPE.COMPONENT && !isComponentNode(processed)) {\n // Convert to component node\n const p = processed as Record<string, unknown>;\n const newProcessed: ComponentInstanceNode = {\n type: NODE_TYPE.COMPONENT,\n component: '',\n props: (p.props || {}) as ComponentInstanceNode['props'],\n children: p.children as ComponentInstanceNode['children'],\n style: p.style as ComponentInstanceNode['style']\n };\n processed = newProcessed;\n } else if (value === NODE_TYPE.NODE && !isHtmlNode(processed)) {\n // Convert to HTML node\n const p = processed as Record<string, unknown>;\n const newProcessed: HtmlNode = {\n type: NODE_TYPE.NODE,\n tag: (p.component as string) || 'div',\n children: p.children as HtmlNode['children'],\n style: p.style as HtmlNode['style']\n };\n processed = newProcessed;\n }\n }\n } else if (key === 'style' && typeof value === 'object' && value !== null) {\n // Process style at top level - DO NOT recursively call processStructure\n // as it would mangle style mapping objects { _mapping: true, prop: \"size\", values: {...} }\n // into ComponentNode structures. Style objects need special handling.\n const processedStyle = value as Record<string, unknown>;\n if (processedStyle && typeof processedStyle === 'object' && !Array.isArray(processedStyle)) {\n // Check if it's a responsive style object\n const styleEvalContext = buildEvalContext(context, false);\n if (isResponsiveStyle(processedStyle as StyleValue)) {\n // Preserve responsive styles (for both SSR and editor)\n // responsiveStylesToClasses will generate prefixed classes (t-, mob-)\n // CSS media queries will handle displaying the correct styles based on viewport\n const resolvedResponsive: ResponsiveStyleObject = {};\n for (const [bkeyName, bkeyValue] of Object.entries(processedStyle)) {\n if (typeof bkeyValue === 'object' && bkeyValue !== null) {\n resolvedResponsive[bkeyName] = {};\n for (const [styleKey, styleValue] of Object.entries(bkeyValue)) {\n const processedValue = processStyleValue(styleValue, styleEvalContext);\n if (processedValue !== undefined) {\n resolvedResponsive[bkeyName]![styleKey] = processedValue;\n }\n }\n }\n }\n resolvedStyle = resolvedResponsive;\n } else {\n // Legacy flat style object - resolve mappings and evaluate templates\n resolvedStyle = {};\n for (const [styleKey, styleValue] of Object.entries(processedStyle)) {\n const processedValue = processStyleValue(styleValue, styleEvalContext);\n if (processedValue !== undefined) {\n resolvedStyle[styleKey] = processedValue;\n }\n }\n }\n }\n } else if (key === 'props' && typeof value === 'object' && value !== null) {\n // Process non-style props (for instance props only)\n const processedProps = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n // Merge non-style props (style is handled separately at top level)\n if (typeof processedProps === 'object' && !Array.isArray(processedProps) && processedProps !== null && processed.props) {\n const propsObj = processedProps as unknown as Record<string, unknown>;\n Object.assign(processed.props, propsObj);\n // Remove style from props since we handle it at top level\n if ((processed.props as Record<string, unknown>).style !== undefined) {\n delete (processed.props as Record<string, unknown>).style;\n }\n }\n } else if (key === 'hover') {\n // Skip hover for now - it's not a standard React prop\n // Could be implemented with onMouseEnter/onMouseLeave\n } else if (key === 'href' && preservedType === NODE_TYPE.LINK && isLinkNode(processed)) {\n // Special handling for href in link nodes - resolve link mappings\n const pLink = processed as Record<string, unknown>;\n if (isLinkMapping(value)) {\n const resolved = resolveLinkMapping(value, context.props);\n if (resolved) {\n processed.href = resolved.href;\n if (resolved.target) {\n pLink.attributes = {\n ...((pLink.attributes as Record<string, unknown>) || {}),\n target: resolved.target\n };\n }\n } else {\n processed.href = '#';\n }\n } else {\n // Regular href value - process as template\n const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n if (processedValue !== null && processedValue !== undefined) {\n // Check if result is a link object (from link-type prop like {{link}})\n if (typeof processedValue === 'object' && processedValue !== null && 'href' in processedValue) {\n // Unwrap nested link objects (e.g., {href: {href: \"/path\"}} from double-wrapped list item templates)\n let linkObj = processedValue as { href: unknown; target?: string };\n while (typeof linkObj.href === 'object' && linkObj.href !== null && 'href' in (linkObj.href as Record<string, unknown>)) {\n const nested = linkObj.href as { href: unknown; target?: string };\n if (!linkObj.target && nested.target) linkObj = { ...linkObj, target: nested.target };\n linkObj = { ...linkObj, href: nested.href };\n }\n processed.href = linkObj.href as string;\n if (linkObj.target) {\n pLink.attributes = {\n ...((pLink.attributes as Record<string, unknown>) || {}),\n target: linkObj.target\n };\n }\n } else {\n processed.href = processedValue as string;\n }\n }\n }\n } else if (key === 'attributes' && typeof value === 'object' && value !== null) {\n // Special handling for attributes - process templates but don't treat as node structure\n // This preserves type=\"checkbox\" etc. which would otherwise be caught by node type handling\n const processedAttributes: Record<string, unknown> = {};\n const evalContext = buildEvalContext(context, false);\n for (const [attrKey, attrValue] of Object.entries(value)) {\n if (typeof attrValue === 'string' && hasTemplates(attrValue)) {\n // Check if entire string is a complete template {{expr}} - preserve type (boolean, number)\n if (/^\\{\\{.+\\}\\}$/.test(attrValue)) {\n const result = evaluateTemplate(attrValue, evalContext);\n // Skip attribute if complete template resolved to empty string\n if (result === '') continue;\n // Keep the original type (boolean, number, string)\n processedAttributes[attrKey] = result === attrValue ? attrValue : result;\n } else {\n // Partial template like \"prefix-{{value}}\" - always string\n processedAttributes[attrKey] = processCodeTemplates(attrValue, evalContext);\n }\n } else {\n processedAttributes[attrKey] = attrValue;\n }\n }\n (processed as unknown as Record<string, unknown>).attributes = processedAttributes;\n } else if (key === 'interactiveStyles' && Array.isArray(value)) {\n // Special handling for interactiveStyles - preserve as-is without mangling\n // Interactive styles contain StyleMapping objects that shouldn't be converted to nodes\n (processed as unknown as Record<string, unknown>).interactiveStyles = value;\n } else if (key === 'source' && preservedType === NODE_TYPE.LIST) {\n // Pre-resolve a bare prop-name source against the current component's\n // props. Without this, a list with `sourceType: \"prop\"` placed inside\n // another component's slot would fail to resolve at SSR time, because\n // by then `ctx.componentResolvedProps` belongs to the slot host (not\n // the component whose prop this references). The {{template}} form is\n // already handled by the default-recursion branch below.\n const structureRec = structure as Record<string, unknown>;\n const sourceType = (structureRec.sourceType as string | undefined) ?? 'prop';\n if (\n sourceType === 'prop' &&\n typeof value === 'string' &&\n value !== '' &&\n !hasTemplates(value) &&\n context.props &&\n Array.isArray((context.props as Record<string, unknown>)[value])\n ) {\n (processed as unknown as Record<string, unknown>).source = (context.props as Record<string, unknown>)[value];\n } else {\n const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n if (processedValue !== null && processedValue !== undefined) {\n (processed as unknown as Record<string, unknown>).source = processedValue;\n }\n }\n } else if (key !== 'type' && key !== 'children' && key !== 'style' && key !== 'props') {\n const processedValue = processStructure(value as ComponentNode | ComponentNode[] | string | number | null | undefined, context, viewportWidth, instanceChildren, preserveResponsiveStyles, depth + 1);\n // Only assign if it's a valid value\n if (processedValue !== null && processedValue !== undefined) {\n // Store extra properties on the node object\n (processed as unknown as Record<string, unknown>)[key] = processedValue;\n }\n }\n } catch (error) {\n console.error(`Error processing key \"${key}\":`, error);\n // Continue processing other keys\n }\n }\n \n // Apply resolved styles to the processed node based on its type\n // Both SSR and Editor now preserve responsive styles for proper utility class generation\n if (resolvedStyle && Object.keys(resolvedStyle).length > 0) {\n if (isResponsiveStyle(resolvedStyle)) {\n // Apply responsive styles directly to node.style or props.style\n if (isComponentNode(processed)) {\n (processed as unknown as Record<string, unknown>).style = resolvedStyle as ResponsiveStyleObject;\n } else if (isHtmlNode(processed) || isEmbedNode(processed) || isLocaleListNode(processed) || isLinkNode(processed) || isListNode(processed)) {\n processed.style = resolvedStyle as ResponsiveStyleObject;\n }\n } else {\n // Legacy flat style object\n applyStylesToNode(processed, resolvedStyle);\n }\n }\n \n return processed;\n }\n \n return structure;\n } catch (error) {\n console.error('Error in processStructure:', error);\n throw error; // Re-throw so it can be caught by error boundary\n }\n}\n\n", "/**\n * Utilities for working with styles in ComponentNode structures\n * Provides helper functions for applying and merging styles based on node type\n */\n\nimport type { ComponentNode, HtmlNode, ComponentInstanceNode, StyleValue, ResponsiveStyleObject } from './types';\nimport { isComponentNode, isHtmlNode, isEmbedNode, isListNode, isLinkNode } from './nodeUtils';\nimport { isResponsiveStyle } from './styleUtils';\n\n/**\n * Apply styles to a ComponentNode based on its type\n * - HTML nodes: styles go at top level (node.style)\n * - Component instances: styles go in props.style\n */\nexport function applyStylesToNode(\n node: ComponentNode,\n styles: StyleValue | Record<string, string | number> | null | undefined,\n viewportWidth?: number\n): ComponentNode {\n if (!styles) return node;\n\n if (isComponentNode(node)) {\n // Component instance: put styles in props.style\n if (!node.props) {\n node.props = {};\n }\n\n node.props.style = { ...(node.props.style || {}), ...styles };\n } else if (isHtmlNode(node) || isEmbedNode(node) || isListNode(node) || isLinkNode(node)) {\n // HTML node, Embed node, List node, and Link node: put styles at top level\n node.style = styles as StyleValue;\n }\n\n return node;\n}\n\n/**\n * Deep-merge two style objects, handling responsive breakpoint keys.\n * When both are responsive ({ base, tablet, mobile }), merges per breakpoint\n * so that instance properties override structure properties within each breakpoint\n * rather than replacing the entire breakpoint object.\n */\nfunction deepMergeStyles(\n existing: StyleValue | Record<string, any>,\n instance: StyleValue | Record<string, any> | null | undefined\n): StyleValue {\n if (!instance) return existing as StyleValue;\n\n const bothResponsive =\n isResponsiveStyle(existing as StyleValue) && isResponsiveStyle(instance as StyleValue);\n\n if (bothResponsive) {\n const e = existing as Record<string, any>;\n const i = instance as Record<string, any>;\n const merged: Record<string, any> = {};\n const keys = new Set([...Object.keys(e), ...Object.keys(i)]);\n for (const key of keys) {\n if (e[key] && i[key] && typeof e[key] === 'object' && typeof i[key] === 'object') {\n merged[key] = { ...e[key], ...i[key] };\n } else {\n merged[key] = i[key] !== undefined ? i[key] : e[key];\n }\n }\n return merged as StyleValue;\n }\n\n // Flat styles: shallow merge (instance overrides)\n return { ...(existing as Record<string, any>), ...(instance as Record<string, any>) } as StyleValue;\n}\n\n/**\n * Merge instance styles with structure styles for a ComponentNode\n * Instance styles override structure styles\n */\nexport function mergeNodeStyles(\n node: ComponentNode,\n instanceStyles: StyleValue | Record<string, string | number> | null | undefined,\n viewportWidth?: number\n): ComponentNode {\n if (!instanceStyles) return node;\n\n if (isHtmlNode(node) || isEmbedNode(node) || isListNode(node) || isLinkNode(node)) {\n // For HTML nodes, Embed nodes, List nodes, and Link nodes: merge instance styles with existing top-level styles\n const existingStyle = node.style;\n if (existingStyle && typeof existingStyle === 'object') {\n node.style = deepMergeStyles(existingStyle, instanceStyles);\n } else {\n node.style = instanceStyles as StyleValue;\n }\n } else if (isComponentNode(node)) {\n // For component instances: merge into props.style\n if (!node.props) {\n node.props = {};\n }\n const existingStyle = node.props.style;\n if (existingStyle && typeof existingStyle === 'object') {\n node.props.style = deepMergeStyles(existingStyle, instanceStyles);\n } else {\n node.props.style = instanceStyles;\n }\n }\n\n return node;\n}\n\n/**\n * Extract styles from a ComponentNode based on its type\n * Returns a flat style object ready for React props\n */\nexport function extractStylesFromNode(\n node: ComponentNode,\n viewportWidth?: number\n): Record<string, string | number> {\n if (isComponentNode(node)) {\n // Component instance: styles are in props.style\n const style = node.props?.style;\n if (!style) return {};\n\n return style as Record<string, string | number>;\n } else if (isHtmlNode(node) || isEmbedNode(node) || isLinkNode(node)) {\n // HTML node, Embed node, and Link node: styles are at top level\n const style = node.style;\n if (!style) return {};\n\n return style as Record<string, string | number>;\n }\n\n return {};\n}\n\n", "/**\n * Utilities for working with attributes in ComponentNode structures\n * Provides helper functions for extracting and applying attributes based on node type\n */\n\nimport type { ComponentNode } from './types';\nimport { isComponentNode, isHtmlNode } from './nodeUtils';\n\n/**\n * Extract attributes from a ComponentNode\n * Attributes are stored at the top level of the node (like styles)\n * Returns a record of attributes ready for React props\n */\nexport function extractAttributesFromNode(\n node: ComponentNode\n): Record<string, string | number | boolean> {\n if (!node || typeof node !== 'object') {\n return {};\n }\n\n // Attributes are stored at top level for both HTML nodes and component instances\n if ('attributes' in node && node.attributes) {\n return node.attributes as Record<string, string | number | boolean>;\n }\n\n return {};\n}\n\n/**\n * Remove attributes that were entirely template expressions (e.g., \"{{fade}}\")\n * and resolved to empty string \"\". Static attributes and partial templates are unchanged.\n */\nexport function skipEmptyTemplateAttributes(\n original: Record<string, unknown>,\n resolved: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(resolved)) {\n const orig = original[key];\n if (\n typeof orig === 'string' &&\n /^\\{\\{.+\\}\\}$/.test(orig) &&\n value === ''\n ) {\n continue;\n }\n result[key] = value;\n }\n return result;\n}\n\n/**\n * Apply attributes to a ComponentNode\n * Attributes go at top level (node.attributes)\n */\nexport function applyAttributesToNode(\n node: ComponentNode,\n attributes: Record<string, string | number | boolean> | null | undefined\n): ComponentNode {\n if (!attributes || Object.keys(attributes).length === 0) {\n return node;\n }\n\n if (isComponentNode(node) || isHtmlNode(node)) {\n return {\n ...node,\n attributes: { ...(node.attributes || {}), ...attributes }\n };\n }\n\n return node;\n}\n\n"],
5
- "mappings": "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",
6
- "names": ["normalizeStyle", "processed"]
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../lib/shared/slugify.ts"],
4
- "sourcesContent": ["/**\n * Slugify utilities for CMS filenames\n * Converts text to URL-safe slugs and handles i18n value extraction\n */\n\nimport { isI18nValue } from './i18n';\n\n/**\n * Convert string to URL-safe slug\n * - Lowercase\n * - Remove diacritics (accented characters)\n * - Replace spaces with hyphens\n * - Remove special characters\n */\nexport function slugify(text: string): string {\n if (!text) return '';\n\n return text\n .toLowerCase()\n .normalize('NFD') // Decompose accented chars (\u00E9 -> e + \u0301)\n .replace(/[\\u0300-\\u036f]/g, '') // Remove diacritics\n .replace(/[^a-z0-9\\s-]/g, '') // Remove special chars\n .trim()\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/-+/g, '-') // Collapse multiple hyphens\n .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens\n}\n\n/**\n * Extract string value from potentially i18n field\n * Uses specified locale if i18n, or returns string directly\n *\n * @param value - String or i18n object\n * @param defaultLocale - Locale to use for i18n extraction (default: 'en')\n * @returns Extracted string value\n */\nexport function extractStringValue(\n value: unknown,\n defaultLocale: string = 'en'\n): string {\n // Direct string\n if (typeof value === 'string') {\n return value;\n }\n\n // i18n object: { _i18n: true, en: \"hello\", pl: \"cze\u015B\u0107\" }\n if (isI18nValue(value)) {\n // Try default locale first\n if (typeof value[defaultLocale] === 'string') {\n return value[defaultLocale] as string;\n }\n // Fall back to first available locale\n for (const key of Object.keys(value)) {\n if (key !== '_i18n' && typeof value[key] === 'string') {\n return value[key] as string;\n }\n }\n }\n\n // Not a string or i18n object\n return '';\n}\n\n/**\n * Generate a unique filename from base slug\n * Appends -1, -2, etc. suffix if duplicate exists\n *\n * @param baseSlug - Base slug to use\n * @param existingFilenames - Array of existing filenames to check against\n * @returns Unique filename\n */\nexport function generateUniqueFilename(\n baseSlug: string,\n existingFilenames: string[]\n): string {\n if (!baseSlug) {\n baseSlug = 'untitled';\n }\n\n // If base slug is unique, use it directly\n if (!existingFilenames.includes(baseSlug)) {\n return baseSlug;\n }\n\n // Append counter suffix until unique\n let counter = 1;\n let candidate = `${baseSlug}-${counter}`;\n while (existingFilenames.includes(candidate)) {\n counter++;\n candidate = `${baseSlug}-${counter}`;\n }\n\n return candidate;\n}\n\n/**\n * Generate filename from item data\n * Extracts title field value, slugifies it, and ensures uniqueness\n *\n * @param item - CMS item data\n * @param titleField - Name of the field to use for title (default: 'title')\n * @param existingFilenames - Array of existing filenames\n * @param defaultLocale - Default locale for i18n extraction\n * @returns Unique filename\n */\nexport function generateFilenameFromItem(\n item: Record<string, unknown>,\n titleField: string = 'title',\n existingFilenames: string[] = [],\n defaultLocale: string = 'en'\n): string {\n // Try to get title from specified field\n const titleValue = item[titleField];\n const titleString = extractStringValue(titleValue, defaultLocale);\n const baseSlug = slugify(titleString);\n\n return generateUniqueFilename(baseSlug, existingFilenames);\n}\n"],
5
- "mappings": ";;;;;AAcO,SAAS,QAAQ,MAAsB;AAC5C,MAAI,CAAC,KAAM,QAAO;AAElB,SAAO,KACJ,YAAY,EACZ,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,iBAAiB,EAAE,EAC3B,KAAK,EACL,QAAQ,QAAQ,GAAG,EACnB,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AACzB;AAUO,SAAS,mBACd,OACA,gBAAwB,MAChB;AAER,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI,YAAY,KAAK,GAAG;AAEtB,QAAI,OAAO,MAAM,aAAa,MAAM,UAAU;AAC5C,aAAO,MAAM,aAAa;AAAA,IAC5B;AAEA,eAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,UAAI,QAAQ,WAAW,OAAO,MAAM,GAAG,MAAM,UAAU;AACrD,eAAO,MAAM,GAAG;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAGA,SAAO;AACT;AAUO,SAAS,uBACd,UACA,mBACQ;AACR,MAAI,CAAC,UAAU;AACb,eAAW;AAAA,EACb;AAGA,MAAI,CAAC,kBAAkB,SAAS,QAAQ,GAAG;AACzC,WAAO;AAAA,EACT;AAGA,MAAI,UAAU;AACd,MAAI,YAAY,GAAG,QAAQ,IAAI,OAAO;AACtC,SAAO,kBAAkB,SAAS,SAAS,GAAG;AAC5C;AACA,gBAAY,GAAG,QAAQ,IAAI,OAAO;AAAA,EACpC;AAEA,SAAO;AACT;AAYO,SAAS,yBACd,MACA,aAAqB,SACrB,oBAA8B,CAAC,GAC/B,gBAAwB,MAChB;AAER,QAAM,aAAa,KAAK,UAAU;AAClC,QAAM,cAAc,mBAAmB,YAAY,aAAa;AAChE,QAAM,WAAW,QAAQ,WAAW;AAEpC,SAAO,uBAAuB,UAAU,iBAAiB;AAC3D;",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../lib/server/ssr/buildErrorOverlay.ts"],
4
- "sourcesContent": ["/**\n * Build Error Overlay Generator\n * Generates an HTML page showing build errors when the static server detects _errors.json\n */\n\nexport interface BuildError {\n file: string; // e.g., \"pages/posts.json\"\n message: string; // Error message\n type: string; // 'minify' | 'render' | 'parse' | 'cms'\n}\n\nexport interface BuildErrorsData {\n errors: BuildError[];\n timestamp: number;\n}\n\n/**\n * Escape HTML to prevent XSS in error messages\n */\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n/**\n * Safely encode data for embedding in a script tag\n */\nfunction safeJsonForScript(data: unknown): string {\n return JSON.stringify(data)\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/&/g, '\\\\u0026');\n}\n\n/**\n * Generate HTML page showing build errors.\n *\n * @param data Build errors payload to render\n * @param cspNonce Per-request CSP nonce \u2014 when set, stamped on the inline\n * `<script>` so it executes under a strict (nonce-based)\n * script-src policy without `'unsafe-inline'`. Callers in a\n * plain static-serve context may omit it (no CSP is enforced\n * by the static server itself).\n */\nexport function generateBuildErrorPage(data: BuildErrorsData, cspNonce?: string): string {\n const { errors, timestamp } = data;\n const timeStr = new Date(timestamp).toLocaleTimeString();\n const nonceAttr = cspNonce ? ` nonce=\"${cspNonce}\"` : '';\n\n // Generate plain text for copying to AI\n const plainTextErrors = errors.map(err =>\n `[${err.type.toUpperCase()}] ${err.file}\\n${err.message}`\n ).join('\\n\\n');\n const copyText = `Build failed with ${errors.length} error(s):\\n\\n${plainTextErrors}`;\n\n const errorListHtml = errors.map((err) => `\n <div class=\"error-item\">\n <div class=\"error-item-header\">\n <div class=\"error-type\">${escapeHtml(err.type)}</div>\n <div class=\"error-file\">${escapeHtml(err.file)}</div>\n </div>\n <div class=\"error-message\">${escapeHtml(err.message)}</div>\n </div>\n `).join('');\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Build Failed</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n\n body {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: linear-gradient(135deg, #0f0f1a 0%, #1a1a2e 100%);\n color: #e2e8f0;\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n }\n\n .container {\n max-width: 720px;\n width: 100%;\n }\n\n .card {\n background: rgba(30, 30, 50, 0.8);\n backdrop-filter: blur(20px);\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 16px;\n overflow: hidden;\n box-shadow:\n 0 4px 6px rgba(0, 0, 0, 0.1),\n 0 20px 50px rgba(0, 0, 0, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.05);\n }\n\n .header {\n background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%);\n padding: 20px 24px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .header-left {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .header-icon {\n width: 32px;\n height: 32px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .header-icon svg {\n width: 18px;\n height: 18px;\n stroke: white;\n }\n\n .header-title {\n font-size: 16px;\n font-weight: 600;\n letter-spacing: -0.01em;\n }\n\n .error-count {\n background: rgba(0, 0, 0, 0.25);\n padding: 6px 14px;\n border-radius: 100px;\n font-size: 13px;\n font-weight: 500;\n }\n\n .body {\n padding: 20px;\n max-height: 50vh;\n overflow-y: auto;\n }\n\n .body::-webkit-scrollbar {\n width: 6px;\n }\n\n .body::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .body::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 3px;\n }\n\n .error-item {\n background: rgba(0, 0, 0, 0.3);\n border: 1px solid rgba(255, 255, 255, 0.06);\n border-radius: 10px;\n padding: 14px 16px;\n margin-bottom: 10px;\n transition: border-color 0.15s;\n }\n\n .error-item:last-child { margin-bottom: 0; }\n\n .error-item:hover {\n border-color: rgba(255, 255, 255, 0.12);\n }\n\n .error-item-header {\n display: flex;\n align-items: center;\n gap: 10px;\n margin-bottom: 10px;\n }\n\n .error-type {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n padding: 4px 8px;\n border-radius: 4px;\n background: rgba(239, 68, 68, 0.2);\n color: #fca5a5;\n }\n\n .error-file {\n font-family: 'SF Mono', 'Fira Code', Menlo, Monaco, monospace;\n font-size: 12px;\n color: #94a3b8;\n }\n\n .error-message {\n font-family: 'SF Mono', 'Fira Code', Menlo, Monaco, monospace;\n font-size: 12px;\n line-height: 1.7;\n color: #f87171;\n white-space: pre-wrap;\n word-break: break-word;\n background: rgba(0, 0, 0, 0.2);\n padding: 10px 12px;\n border-radius: 6px;\n border-left: 2px solid #dc2626;\n }\n\n .footer {\n padding: 16px 20px;\n background: rgba(0, 0, 0, 0.2);\n border-top: 1px solid rgba(255, 255, 255, 0.06);\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n }\n\n .footer-info {\n font-size: 12px;\n color: #64748b;\n }\n\n .footer-actions {\n display: flex;\n gap: 8px;\n }\n\n .btn {\n border: none;\n padding: 10px 16px;\n border-radius: 8px;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.15s;\n }\n\n .btn svg {\n width: 14px;\n height: 14px;\n }\n\n .btn-secondary {\n background: rgba(255, 255, 255, 0.08);\n color: #e2e8f0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n }\n\n .btn-secondary:hover {\n background: rgba(255, 255, 255, 0.12);\n border-color: rgba(255, 255, 255, 0.15);\n }\n\n .btn-primary {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .btn-primary:hover {\n background: linear-gradient(135deg, #60a5fa 0%, #3b82f6 100%);\n }\n\n .btn-success {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%) !important;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"card\">\n <div class=\"header\">\n <div class=\"header-left\">\n <div class=\"header-icon\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"></line>\n </svg>\n </div>\n <span class=\"header-title\">Build Failed</span>\n </div>\n <span class=\"error-count\">${errors.length} error${errors.length === 1 ? '' : 's'}</span>\n </div>\n <div class=\"body\">\n ${errorListHtml}\n </div>\n <div class=\"footer\">\n <div class=\"footer-info\">Failed at ${timeStr}</div>\n <div class=\"footer-actions\">\n <button class=\"btn btn-secondary\" id=\"copyBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"></rect>\n <path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"></path>\n </svg>\n <span>Copy</span>\n </button>\n <button class=\"btn btn-primary\" id=\"refreshBtn\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"23 4 23 10 17 10\"></polyline>\n <path d=\"M20.49 15a9 9 0 1 1-2.12-9.36L23 10\"></path>\n </svg>\n Refresh\n </button>\n </div>\n </div>\n </div>\n </div>\n <script${nonceAttr}>\n (function() {\n var copyBtn = document.getElementById('copyBtn');\n var copyText = ${safeJsonForScript(copyText)};\n\n copyBtn.addEventListener('click', function() {\n navigator.clipboard.writeText(copyText).then(function() {\n var span = copyBtn.querySelector('span');\n var original = span.textContent;\n span.textContent = 'Copied!';\n copyBtn.classList.add('btn-success');\n setTimeout(function() {\n span.textContent = original;\n copyBtn.classList.remove('btn-success');\n }, 2000);\n }).catch(function(err) {\n console.error('Failed to copy:', err);\n });\n });\n\n // Refresh button \u2014 handler attached here (instead of onclick) so the\n // page works under a strict (nonce-based) script-src CSP that bars\n // inline event-handler attributes.\n var refreshBtn = document.getElementById('refreshBtn');\n if (refreshBtn) {\n refreshBtn.addEventListener('click', function() {\n location.reload();\n });\n }\n })();\n </script>\n</body>\n</html>`;\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../lib/shared/types/components.ts", "../../lib/shared/types/errors.ts", "../../lib/shared/types/colors.ts", "../../lib/shared/types/variables.ts", "../../lib/shared/pathSecurity.ts"],
4
- "sourcesContent": ["/**\n * Component Definition Types\n * Improved type safety with stricter types\n */\n\nimport type { ComponentNode } from './nodes';\nimport type { LibrariesConfig } from './libraries';\n\n/**\n * Prop type definitions\n */\nexport type PropType = 'string' | 'select' | 'boolean' | 'number' | 'link' | 'file' | 'rich-text' | 'embed' | 'list';\n\n/**\n * Project-level enum configuration\n * Keys are enum names, values are arrays of options\n */\nexport type EnumsConfig = Record<string, readonly string[]>;\n\n/**\n * Internationalization (i18n) value object\n * Keys are locale codes (e.g., 'en', 'pl', 'de')\n * Values can be strings (for string props) or arrays (for list props)\n */\nexport interface I18nValue {\n _i18n: true;\n [locale: string]: string | unknown[] | true; // true is for the _i18n marker, arrays for list props\n}\n\n/**\n * Locale configuration with metadata\n */\nexport interface LocaleConfig {\n code: string; // URL prefix & translation key (e.g., \"en\", \"pl\")\n name: string; // English name for admin UI (e.g., \"Polish\")\n nativeName: string; // Native name for public UI (e.g., \"Polski\")\n langTag: string; // BCP 47 language tag for SEO (e.g., \"pl-PL\")\n icon?: string; // Optional flag icon path (e.g., \"/icons/flag-en.svg\")\n}\n\n/**\n * Internationalization configuration\n */\nexport interface I18nConfig {\n defaultLocale: string;\n locales: LocaleConfig[];\n}\n\n/**\n * Value resolver function type\n * Used for transforming field values (e.g., i18n resolution)\n */\nexport type ValueResolver = (value: unknown) => unknown;\n\n/**\n * Link prop value type\n */\nexport interface LinkPropValue {\n href: string;\n target?: '_blank';\n}\n\n/**\n * Base prop definition without list-specific fields\n */\nexport interface BasePropDefinition {\n type: Exclude<PropType, 'list'>;\n default?: string | number | boolean | I18nValue | LinkPropValue;\n options?: readonly string[]; // Required for \"select\" type (inline options)\n enumName?: string; // For \"select\" type: reference to project-level enum\n accept?: string; // For \"file\" type: MIME pattern like \"image/*\", \"video/*\"\n editor?: 'basic' | 'extended'; // For 'rich-text' type: which editor to use\n}\n\n/**\n * List item schema - defines the structure of each item in a list prop\n * Uses the same prop types as component interfaces (except nested lists)\n */\nexport type ListItemSchema = Record<string, BasePropDefinition>;\n\n/**\n * List item value type\n * Supports i18n values for localized string fields\n */\nexport type ListItemValue = Record<string, string | number | boolean | LinkPropValue | I18nValue | null>;\n\n/**\n * List prop definition - for array/list data\n */\nexport interface ListPropDefinition {\n type: 'list';\n /** Schema defining the structure of each list item */\n itemSchema: ListItemSchema;\n /** Default value is an array of items */\n default?: ListItemValue[];\n}\n\n/**\n * Prop definition with improved type safety\n */\nexport type PropDefinition = BasePropDefinition | ListPropDefinition;\n\n/**\n * Type guard to check if a prop definition is a list type\n */\nexport function isListPropDefinition(def: PropDefinition): def is ListPropDefinition {\n return def.type === 'list';\n}\n\n/**\n * Type guard to check if a prop definition is a base (non-list) type\n */\nexport function isBasePropDefinition(def: PropDefinition): def is BasePropDefinition {\n return def.type !== 'list';\n}\n\n/**\n * Structured component definition\n */\nexport interface StructuredComponentDefinition {\n interface?: Record<string, PropDefinition>;\n structure?: ComponentNode;\n javascript?: string; // Vanilla JS code to be rendered at end of HTML\n css?: string; // CSS code to be rendered in <style> tag in <head>\n category?: string; // Component category for organization\n /**\n * Define which props are available as JavaScript variables (Astro-style define:vars)\n * - true: all props from interface are exposed\n * - string[]: only specified props are exposed\n * - undefined: no automatic prop injection (backward compatible)\n */\n defineVars?: true | string[];\n /** External JS/CSS libraries required by this component */\n libraries?: LibrariesConfig;\n /** Whether instances of this component can have styles applied to the wrapper */\n acceptsStyles?: boolean;\n}\n\n/**\n * Component definition\n * Supports both new format (just component) and legacy format (type/props/children/component)\n */\nexport interface ComponentDefinition {\n type?: string; // Legacy format\n props?: Record<string, unknown>; // Legacy format\n children?: unknown[]; // Legacy format\n component: StructuredComponentDefinition;\n}\n\n/**\n * Line range for element line number tracking\n */\nexport interface LineRange {\n startLine: number;\n endLine: number;\n}\n\n/**\n * JSON page structure\n */\nexport interface JSONPage {\n meta?: import('./api').PageMetaData;\n components?: Record<string, ComponentDefinition>;\n root?: ComponentNode;\n _lineMap?: Record<string, LineRange>;\n}\n\n/**\n * Page data type that can be either a JSONPage or a component definition structure\n */\nexport type PageData = JSONPage | {\n component: {\n structure?: ComponentNode;\n interface?: Record<string, PropDefinition>;\n javascript?: string;\n css?: string;\n acceptsStyles?: boolean;\n }\n};\n\n/**\n * Page data with component structure (for type narrowing)\n */\nexport interface PageDataWithComponent {\n component: {\n structure?: ComponentNode;\n interface?: Record<string, PropDefinition>;\n javascript?: string;\n css?: string;\n libraries?: LibrariesConfig;\n acceptsStyles?: boolean;\n };\n}\n", "/**\n * Error Types\n * Structured error types for validation and type safety\n */\n\n/**\n * Validation error with context\n */\nexport interface ValidationError {\n path?: string;\n message: string;\n receivedValue?: unknown;\n expectedType?: string;\n}\n\n/**\n * Type safety error\n * Errors from type mismatches or invalid data structures\n */\nexport interface TypeSafetyError extends Error {\n readonly path?: string;\n readonly receivedValue?: unknown;\n readonly expectedType?: string;\n}\n\n/**\n * Result type for operations that can fail\n * Replaces null returns with explicit success/failure\n */\nexport type Result<T> =\n | { success: true; data: T }\n | { success: false; error: ValidationError };\n\n/**\n * Create a validation error\n */\nexport function createValidationError(\n message: string,\n options?: {\n path?: string;\n receivedValue?: unknown;\n expectedType?: string;\n }\n): ValidationError {\n return {\n message,\n ...options,\n };\n}\n\n/**\n * Create a type safety error\n */\nexport function createTypeSafetyError(\n message: string,\n options?: {\n path?: string;\n receivedValue?: unknown;\n expectedType?: string;\n }\n): TypeSafetyError {\n const error = new Error(message) as TypeSafetyError;\n Object.defineProperty(error, 'path', { value: options?.path, writable: false });\n Object.defineProperty(error, 'receivedValue', { value: options?.receivedValue, writable: false });\n Object.defineProperty(error, 'expectedType', { value: options?.expectedType, writable: false });\n return error;\n}\n\n\n", "/**\n * Color Variables Types\n * Handles color variable definitions and configuration\n */\n\n/**\n * Color variables configuration\n * Maps semantic color names to their hex/rgb values\n */\nexport interface ColorVariables {\n colors: Record<string, string>;\n}\n\n/**\n * Theme configuration with color set and metadata\n */\nexport interface Theme {\n label: string;\n colors: Record<string, string>;\n}\n\n/**\n * Theme configuration file structure\n * Supports multiple named themes with a default theme\n */\nexport interface ThemeConfig {\n default: string;\n palette?: Record<string, string>;\n themes: Record<string, Theme>;\n}\n\n/**\n * Resolve a color value through the palette.\n * If value matches a palette key, returns the palette hex; otherwise returns value as-is.\n */\nexport function resolvePaletteColor(value: string, palette?: Record<string, string>): string {\n if (!palette) return value;\n return palette[value] ?? value;\n}\n\n/**\n * Color variable entry for editor display\n */\nexport interface ColorVariableEntry {\n name: string;\n value: string;\n}\n\n/**\n * Theme entry for theme selector\n */\nexport interface ThemeEntry {\n name: string;\n label: string;\n}\n", "/**\n * CSS Variables Types\n * Defines types for the variables.json configuration file\n */\n\n/**\n * Category type for a CSS variable\n * Maps to responsiveScales categories for automatic responsive scaling\n * 'none' means no responsive scaling is applied\n */\nexport type VariableType = 'fontSize' | 'padding' | 'margin' | 'gap' | 'borderRadius' | 'size' | 'none';\n\n/**\n * UI filtering group for a CSS variable.\n * Controls which variables appear in the picker based on the CSS property being edited.\n */\nexport type VariableGroup =\n | 'font-family' | 'font-size' | 'font-weight'\n | 'line-height' | 'letter-spacing'\n | 'margin' | 'padding' | 'gap'\n | 'size'\n | 'position'\n | 'border-radius' | 'border-width'\n | 'outline'\n | 'shadow'\n | 'filter'\n | 'duration'\n | 'aspect-ratio'\n | 'opacity' | 'z-index'\n | 'text-align'\n | 'other';\n\n/** Predefined variable groups for UI dropdowns */\nexport const VARIABLE_GROUPS: { value: VariableGroup; label: string }[] = [\n { value: 'font-family', label: 'Font Family' },\n { value: 'font-size', label: 'Font Size' },\n { value: 'font-weight', label: 'Font Weight' },\n { value: 'line-height', label: 'Line Height' },\n { value: 'letter-spacing', label: 'Letter Spacing' },\n { value: 'margin', label: 'Margin' },\n { value: 'padding', label: 'Padding' },\n { value: 'gap', label: 'Gap' },\n { value: 'size', label: 'Size' },\n { value: 'position', label: 'Position' },\n { value: 'border-radius', label: 'Border Radius' },\n { value: 'border-width', label: 'Border Width' },\n { value: 'outline', label: 'Outline' },\n { value: 'shadow', label: 'Shadow' },\n { value: 'filter', label: 'Filter' },\n { value: 'duration', label: 'Duration' },\n { value: 'aspect-ratio', label: 'Aspect Ratio' },\n { value: 'opacity', label: 'Opacity' },\n { value: 'z-index', label: 'Z-Index' },\n { value: 'text-align', label: 'Text Align' },\n { value: 'other', label: 'Other' },\n];\n\n/** All valid group string values */\nexport const VARIABLE_GROUP_VALUES: VariableGroup[] = VARIABLE_GROUPS.map(g => g.value);\n\n/** Maps CSS property names to variable groups */\nconst CSS_PROPERTY_TO_GROUP: Record<string, VariableGroup> = {\n 'font-family': 'font-family',\n 'font-size': 'font-size',\n 'font-weight': 'font-weight',\n 'line-height': 'line-height',\n 'letter-spacing': 'letter-spacing',\n 'text-align': 'text-align',\n 'opacity': 'opacity',\n 'z-index': 'z-index',\n 'top': 'position',\n 'right': 'position',\n 'bottom': 'position',\n 'left': 'position',\n 'inset': 'position',\n 'inset-block': 'position',\n 'inset-inline': 'position',\n 'inset-block-start': 'position',\n 'inset-block-end': 'position',\n 'inset-inline-start': 'position',\n 'inset-inline-end': 'position',\n 'box-shadow': 'shadow',\n 'text-shadow': 'shadow',\n 'filter': 'filter',\n 'backdrop-filter': 'filter',\n 'aspect-ratio': 'aspect-ratio',\n 'transition-duration': 'duration',\n 'animation-duration': 'duration',\n 'transition-delay': 'duration',\n 'animation-delay': 'duration',\n};\n\n/** Prefix-based mappings for CSS properties */\nconst CSS_PROPERTY_PREFIX_GROUPS: { prefix: string; group: VariableGroup }[] = [\n { prefix: 'margin', group: 'margin' },\n { prefix: 'padding', group: 'padding' },\n { prefix: 'gap', group: 'gap' },\n { prefix: 'row-gap', group: 'gap' },\n { prefix: 'column-gap', group: 'gap' },\n { prefix: 'width', group: 'size' },\n { prefix: 'height', group: 'size' },\n { prefix: 'min-width', group: 'size' },\n { prefix: 'max-width', group: 'size' },\n { prefix: 'min-height', group: 'size' },\n { prefix: 'max-height', group: 'size' },\n { prefix: 'border-radius', group: 'border-radius' },\n { prefix: 'border-top-left-radius', group: 'border-radius' },\n { prefix: 'border-top-right-radius', group: 'border-radius' },\n { prefix: 'border-bottom-left-radius', group: 'border-radius' },\n { prefix: 'border-bottom-right-radius', group: 'border-radius' },\n { prefix: 'border-width', group: 'border-width' },\n { prefix: 'border-top-width', group: 'border-width' },\n { prefix: 'border-right-width', group: 'border-width' },\n { prefix: 'border-bottom-width', group: 'border-width' },\n { prefix: 'border-left-width', group: 'border-width' },\n { prefix: 'outline-width', group: 'outline' },\n { prefix: 'outline-offset', group: 'outline' },\n];\n\n/**\n * Determines which variable group a CSS property belongs to.\n * Returns null if no group matches (show all variables).\n */\nexport function getGroupForProperty(prop: string): VariableGroup | null {\n // Normalize camelCase to kebab-case (e.g., \"fontFamily\" \u2192 \"font-family\")\n const normalized = prop.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`);\n\n // Exact match first\n if (normalized in CSS_PROPERTY_TO_GROUP) {\n return CSS_PROPERTY_TO_GROUP[normalized];\n }\n // Prefix-based match (handles margin-top, padding-left, etc.)\n for (const { prefix, group } of CSS_PROPERTY_PREFIX_GROUPS) {\n if (normalized === prefix || normalized.startsWith(prefix + '-')) {\n return group;\n }\n }\n return null;\n}\n\n/**\n * A single CSS custom property definition\n */\nexport interface CSSVariable {\n /** Display name (e.g., \"H1 Font Size\") */\n name: string;\n /** Optional prop name alias for organizational purposes */\n prop_name?: string;\n /** CSS custom property name (e.g., \"--h1-fs\") */\n cssVar: string;\n /** Base value (e.g., \"48px\") */\n value: string;\n /** Category for responsive scaling */\n type: VariableType;\n /** Optional per-variable breakpoint scale overrides */\n scales?: Record<string, string>;\n /** Optional UI filtering group for the variable picker */\n group?: VariableGroup;\n}\n\n/**\n * Variables configuration file structure (variables.json)\n */\nexport interface VariablesConfig {\n variables: CSSVariable[];\n}\n\n/** Predefined variable scaling types for UI dropdowns */\nexport const VARIABLE_TYPES: { value: VariableType; label: string }[] = [\n { value: 'fontSize', label: 'Font Size' },\n { value: 'padding', label: 'Padding' },\n { value: 'margin', label: 'Margin' },\n { value: 'gap', label: 'Gap' },\n { value: 'borderRadius', label: 'Border Radius' },\n { value: 'size', label: 'Width / Height' },\n { value: 'none', label: 'None' },\n];\n\n/** All valid variable scaling type values */\nexport const VARIABLE_TYPE_VALUES: VariableType[] = VARIABLE_TYPES.map(t => t.value);\n\n/**\n * Returns an abbreviation for a variable group by taking the first letter of each word.\n * e.g. 'letter-spacing' -> 'ls', 'font-size' -> 'fs', 'spacing' -> 's'\n */\nexport function getGroupAbbreviation(group: string): string {\n return group.split('-').map(w => w[0] || '').join('');\n}\n\n/**\n * Infers a default scaling type from a variable group and optional CSS property.\n */\nexport function getDefaultScalingType(group: string, cssProperty?: string): VariableType {\n if (group === 'font-size') return 'fontSize';\n if (group === 'margin') return 'margin';\n if (group === 'padding') return 'padding';\n if (group === 'gap') return 'gap';\n if (group === 'border-radius') return 'borderRadius';\n if (group === 'size') return 'size';\n return 'none';\n}\n\n/**\n * Generates a short CSS variable name with collision detection.\n * e.g. name=\"Heading\", group=\"letter-spacing\" -> \"--h-ls\"\n * If taken, extends prefix: \"--he-ls\", \"--hea-ls\", etc.\n */\nexport function generateShortCssVar(\n name: string,\n group: string,\n existingVariables: CSSVariable[]\n): string {\n const trimmed = name.trim();\n if (!trimmed) return '--';\n if (!group) {\n // No group: just kebab-case the name\n const base = '--' + trimmed.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n return ensureUnique(base, existingVariables);\n }\n\n const groupAbbr = getGroupAbbreviation(group);\n const kebabName = trimmed.toLowerCase().replace(/\\s+/g, '-').replace(/[^a-z0-9-]/g, '');\n const words = kebabName.split('-').filter(Boolean);\n const existingNames = new Set(existingVariables.map(v => v.cssVar));\n\n // Try progressively longer prefixes from the name\n // Start with first letter of each word, then extend first word\n const initials = words.map(w => w[0] || '').join('');\n const initialCandidate = `--${initials}-${groupAbbr}`;\n if (!existingNames.has(initialCandidate)) return initialCandidate;\n\n // Extend first word progressively\n const firstWord = words[0] || '';\n for (let len = 2; len <= firstWord.length; len++) {\n const prefix = firstWord.slice(0, len) + (words.length > 1 ? words.slice(1).map(w => w[0] || '').join('') : '');\n const candidate = `--${prefix}-${groupAbbr}`;\n if (!existingNames.has(candidate)) return candidate;\n }\n\n // Full kebab name with group abbreviation\n const fullCandidate = `--${kebabName}-${groupAbbr}`;\n if (!existingNames.has(fullCandidate)) return fullCandidate;\n\n // Numeric suffix fallback\n let i = 2;\n while (existingNames.has(`${fullCandidate}-${i}`)) i++;\n return `${fullCandidate}-${i}`;\n}\n\nfunction ensureUnique(base: string, existingVariables: CSSVariable[]): string {\n const existingNames = new Set(existingVariables.map(v => v.cssVar));\n if (!existingNames.has(base)) return base;\n let i = 2;\n while (existingNames.has(`${base}-${i}`)) i++;\n return `${base}-${i}`;\n}\n", "/**\n * Path Security Utilities\n * Provides path traversal protection for file system operations\n */\n\nimport { resolve, sep } from 'path';\n\n/**\n * Error thrown when a path traversal attack is detected\n */\nexport class PathTraversalError extends Error {\n constructor(\n public readonly requestedPath: string,\n public readonly rootPath: string\n ) {\n super(`Path traversal detected: \"${requestedPath}\" escapes root \"${rootPath}\"`);\n this.name = 'PathTraversalError';\n }\n}\n\n/**\n * Check if a resolved path is within the allowed root directory\n * Uses path.resolve() to normalize and handle .. sequences\n *\n * @param requestedPath - The path to validate (can be relative or absolute)\n * @param rootPath - The root directory that paths must be within\n * @returns true if the path is within root, false otherwise\n */\nexport function isPathWithinRoot(requestedPath: string, rootPath: string): boolean {\n const normalizedRoot = resolve(rootPath);\n const normalizedPath = resolve(rootPath, requestedPath);\n\n // Check that normalized path starts with root + separator\n // Adding separator prevents /project-backup from matching /project\n return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + sep);\n}\n\n/**\n * Resolve a path safely, throwing if it would escape the root\n *\n * @param rootPath - The root directory\n * @param segments - Path segments to join\n * @returns The resolved path\n * @throws PathTraversalError if path escapes root\n */\nexport function resolveSafePath(rootPath: string, ...segments: string[]): string {\n const normalizedRoot = resolve(rootPath);\n const normalizedPath = resolve(normalizedRoot, ...segments);\n\n if (!normalizedPath.startsWith(normalizedRoot + sep) && normalizedPath !== normalizedRoot) {\n throw new PathTraversalError(segments.join(sep), rootPath);\n }\n\n return normalizedPath;\n}\n\n/**\n * Validate that a filename/identifier contains no path traversal sequences\n * Use for collection names, filenames, etc.\n *\n * @param name - The name to validate\n * @returns true if safe, false if contains traversal sequences\n */\nexport function isSafePathSegment(name: string): boolean {\n // Reject empty names\n if (!name || name.trim() === '') return false;\n\n // Reject names with path separators\n if (name.includes('/') || name.includes('\\\\')) return false;\n\n // Reject . and ..\n if (name === '.' || name === '..') return false;\n\n // Reject names starting with .. (e.g., \"..foo\")\n if (name.startsWith('..')) return false;\n\n // Reject null bytes (used in some attacks)\n if (name.includes('\\0')) return false;\n\n return true;\n}\n\n/**\n * Regex for valid CMS identifiers (collection names, filenames)\n * Allows alphanumeric, underscore, hyphen\n */\nexport const SAFE_IDENTIFIER_REGEX = /^[a-zA-Z0-9_-]+$/;\n\n/**\n * Validate a CMS identifier (stricter than isSafePathSegment)\n * Use for collection IDs and filenames that should only contain safe chars\n */\nexport function isValidIdentifier(name: string): boolean {\n return SAFE_IDENTIFIER_REGEX.test(name);\n}\n\n/**\n * Suffix used for CMS draft files: `{filename}.draft.json`. The provider must\n * never accept user-supplied filenames ending in `.draft`, because that would\n * clash with the draft-suffix convention and let a user shadow another item's\n * draft file.\n */\nexport const CMS_DRAFT_SUFFIX = '.draft';\n\n/**\n * True when a user-supplied CMS filename collides with the reserved `.draft`\n * suffix. Use as a hard reject in CMS provider write paths.\n */\nexport function isReservedDraftFilename(filename: string): boolean {\n return filename.endsWith(CMS_DRAFT_SUFFIX);\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "version": 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 // 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
- "names": ["minifyJS", "isDevBuild"]
7
- }