@json-to-office/core-docx 0.38.1 → 1.0.0
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.
- package/dist/components/highcharts.d.ts +16 -6
- package/dist/components/highcharts.d.ts.map +1 -1
- package/dist/components/index.d.ts +8 -14
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/visual.d.ts +60 -18
- package/dist/components/visual.d.ts.map +1 -1
- package/dist/core/collectTocHeadings.d.ts +15 -1
- package/dist/core/collectTocHeadings.d.ts.map +1 -1
- package/dist/core/componentTransform.d.ts +30 -0
- package/dist/core/componentTransform.d.ts.map +1 -0
- package/dist/core/desugarExternals.d.ts +35 -0
- package/dist/core/desugarExternals.d.ts.map +1 -0
- package/dist/core/flattenVisuals.d.ts.map +1 -1
- package/dist/core/generateFromIr.d.ts +78 -0
- package/dist/core/generateFromIr.d.ts.map +1 -0
- package/dist/core/generationContext.d.ts +2 -2
- package/dist/core/generationContext.d.ts.map +1 -1
- package/dist/core/generator.d.ts +48 -39
- package/dist/core/generator.d.ts.map +1 -1
- package/dist/core/imageResources.d.ts +35 -0
- package/dist/core/imageResources.d.ts.map +1 -0
- package/dist/core/index.d.ts +4 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/layout.d.ts +15 -3
- package/dist/core/layout.d.ts.map +1 -1
- package/dist/core/markdownList.d.ts +21 -0
- package/dist/core/markdownList.d.ts.map +1 -0
- package/dist/core/prerasterizeVisuals.d.ts +2 -3
- package/dist/core/prerasterizeVisuals.d.ts.map +1 -1
- package/dist/core/sectionBookmarks.d.ts +15 -40
- package/dist/core/sectionBookmarks.d.ts.map +1 -1
- package/dist/core/tableModel.d.ts +188 -0
- package/dist/core/tableModel.d.ts.map +1 -0
- package/dist/core/tocField.d.ts +70 -0
- package/dist/core/tocField.d.ts.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7974 -7205
- package/dist/index.js.map +1 -1
- package/dist/ir/compiler.d.ts +49 -0
- package/dist/ir/compiler.d.ts.map +1 -0
- package/dist/ir/debug.d.ts +15 -0
- package/dist/ir/debug.d.ts.map +1 -0
- package/dist/ir/features.d.ts +19 -0
- package/dist/ir/features.d.ts.map +1 -0
- package/dist/ir/index.d.ts +16 -0
- package/dist/ir/index.d.ts.map +1 -0
- package/dist/ir/inline.d.ts +126 -0
- package/dist/ir/inline.d.ts.map +1 -0
- package/dist/ir/types.d.ts +774 -0
- package/dist/ir/types.d.ts.map +1 -0
- package/dist/ir/units.d.ts +57 -0
- package/dist/ir/units.d.ts.map +1 -0
- package/dist/ir/validation.d.ts +19 -0
- package/dist/ir/validation.d.ts.map +1 -0
- package/dist/plugin/createDocumentGenerator.d.ts +10 -3
- package/dist/plugin/createDocumentGenerator.d.ts.map +1 -1
- package/dist/plugin/example/index.d.ts.map +1 -1
- package/dist/plugin/example/index.js +8077 -7165
- package/dist/plugin/example/index.js.map +1 -1
- package/dist/plugin/index.d.ts +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/schema.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +13 -26
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/renderers/docxjs/emit.d.ts +41 -0
- package/dist/renderers/docxjs/emit.d.ts.map +1 -0
- package/dist/renderers/docxjs/index.d.ts +22 -0
- package/dist/renderers/docxjs/index.d.ts.map +1 -0
- package/dist/renderers/docxjs/styles.d.ts +12 -0
- package/dist/renderers/docxjs/styles.d.ts.map +1 -0
- package/dist/renderers/office-open/emit.d.ts +63 -0
- package/dist/renderers/office-open/emit.d.ts.map +1 -0
- package/dist/renderers/office-open/index.d.ts +25 -0
- package/dist/renderers/office-open/index.d.ts.map +1 -0
- package/dist/renderers/office-open/styles.d.ts +13 -0
- package/dist/renderers/office-open/styles.d.ts.map +1 -0
- package/dist/renderers/registry.d.ts +15 -0
- package/dist/renderers/registry.d.ts.map +1 -0
- package/dist/renderers/types.d.ts +35 -0
- package/dist/renderers/types.d.ts.map +1 -0
- package/dist/styles/themeToStyles.d.ts +12 -0
- package/dist/styles/themeToStyles.d.ts.map +1 -0
- package/dist/styles/utils/borderUtils.d.ts +13 -6
- package/dist/styles/utils/borderUtils.d.ts.map +1 -1
- package/dist/styles/utils/layoutUtils.d.ts +10 -14
- package/dist/styles/utils/layoutUtils.d.ts.map +1 -1
- package/dist/styles/utils/styleHelpers.d.ts +6 -2
- package/dist/styles/utils/styleHelpers.d.ts.map +1 -1
- package/dist/themes/overrides.d.ts +0 -2
- package/dist/themes/overrides.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +18 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/bookmarkRegistry.d.ts +13 -77
- package/dist/utils/bookmarkRegistry.d.ts.map +1 -1
- package/dist/utils/commentRegistry.d.ts +5 -43
- package/dist/utils/commentRegistry.d.ts.map +1 -1
- package/dist/utils/exampleRunner.d.ts.map +1 -1
- package/dist/utils/imageUtils.d.ts +23 -19
- package/dist/utils/imageUtils.d.ts.map +1 -1
- package/dist/utils/numberingConfig.d.ts +7 -87
- package/dist/utils/numberingConfig.d.ts.map +1 -1
- package/dist/utils/packageDocument.d.ts +0 -3
- package/dist/utils/packageDocument.d.ts.map +1 -1
- package/dist/utils/revisionUtils.d.ts +6 -67
- package/dist/utils/revisionUtils.d.ts.map +1 -1
- package/dist/utils/warningsDocument.d.ts.map +1 -1
- package/package.json +12 -4
- package/dist/cache/index.d.ts +0 -7
- package/dist/cache/index.d.ts.map +0 -1
- package/dist/cache/key-generator.d.ts +0 -34
- package/dist/cache/key-generator.d.ts.map +0 -1
- package/dist/components/columns.d.ts +0 -12
- package/dist/components/columns.d.ts.map +0 -1
- package/dist/components/heading.d.ts +0 -12
- package/dist/components/heading.d.ts.map +0 -1
- package/dist/components/image.d.ts +0 -12
- package/dist/components/image.d.ts.map +0 -1
- package/dist/components/list.d.ts +0 -12
- package/dist/components/list.d.ts.map +0 -1
- package/dist/components/paragraph.d.ts +0 -12
- package/dist/components/paragraph.d.ts.map +0 -1
- package/dist/components/section.d.ts +0 -12
- package/dist/components/section.d.ts.map +0 -1
- package/dist/components/statistic.d.ts +0 -12
- package/dist/components/statistic.d.ts.map +0 -1
- package/dist/components/table.d.ts +0 -13
- package/dist/components/table.d.ts.map +0 -1
- package/dist/components/text-box.d.ts +0 -9
- package/dist/components/text-box.d.ts.map +0 -1
- package/dist/components/toc/index.d.ts +0 -30
- package/dist/components/toc/index.d.ts.map +0 -1
- package/dist/core/cached-render.d.ts +0 -92
- package/dist/core/cached-render.d.ts.map +0 -1
- package/dist/core/content.d.ts +0 -319
- package/dist/core/content.d.ts.map +0 -1
- package/dist/core/render.d.ts +0 -48
- package/dist/core/render.d.ts.map +0 -1
- package/dist/styles/themeToDocxAdapter.d.ts +0 -22
- package/dist/styles/themeToDocxAdapter.d.ts.map +0 -1
- package/dist/styles/utils/cellUtils.d.ts +0 -55
- package/dist/styles/utils/cellUtils.d.ts.map +0 -1
- package/dist/utils/alignmentUtils.d.ts +0 -10
- package/dist/utils/alignmentUtils.d.ts.map +0 -1
- package/dist/utils/commentAnchors.d.ts +0 -39
- package/dist/utils/commentAnchors.d.ts.map +0 -1
- package/dist/utils/componentAnnotations.d.ts +0 -23
- package/dist/utils/componentAnnotations.d.ts.map +0 -1
- package/dist/utils/docxImagePositioning.d.ts +0 -19
- package/dist/utils/docxImagePositioning.d.ts.map +0 -1
- package/dist/utils/noteRegistry.d.ts +0 -43
- package/dist/utils/noteRegistry.d.ts.map +0 -1
- package/dist/utils/noteResolver.d.ts +0 -31
- package/dist/utils/noteResolver.d.ts.map +0 -1
- package/dist/utils/numberedItemsRegistry.d.ts +0 -38
- package/dist/utils/numberedItemsRegistry.d.ts.map +0 -1
- package/dist/utils/placeholderImage.d.ts +0 -31
- package/dist/utils/placeholderImage.d.ts.map +0 -1
- package/dist/utils/placeholderProcessor.d.ts +0 -58
- package/dist/utils/placeholderProcessor.d.ts.map +0 -1
- package/dist/utils/textParser.d.ts +0 -117
- package/dist/utils/textParser.d.ts.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/themes/defaults.ts","../src/templates/themes/minimal.docx.theme.json","../src/templates/themes/corporate.docx.theme.json","../src/templates/themes/modern.docx.theme.json","../src/templates/themes/apex.docx.theme.json","../src/templates/themes/devportal.docx.theme.json","../src/templates/themes/index.ts","../src/styles/utils/colorUtils.ts","../src/styles/utils/styleHelpers.ts","../src/styles/utils/layoutUtils.ts","../src/themes/json/parser.ts","../src/themes/json/validator.ts","../src/themes/json/loader.ts","../src/themes/json/index.ts","../src/styles/index.ts","../src/utils/widthUtils.ts","../src/utils/docxImagePositioning.ts","../src/core/generator.ts","../src/types/index.ts","../src/core/generationContext.ts","../src/styles/theme-resolver.ts","../src/themes/overrides.ts","../src/utils/formatters.ts","../src/styles/utils/componentDefaults.ts","../src/styles/utils/resolveComponentTree.ts","../src/core/structure.ts","../src/core/layout.ts","../src/core/render.ts","../src/utils/imageUtils.ts","../src/utils/generationContext.ts","../src/styles/themeToDocxAdapter.ts","../src/cache/index.ts","../src/cache/key-generator.ts","../src/utils/revisionUtils.ts","../src/utils/unicode.ts","../src/utils/placeholderProcessor.ts","../src/utils/textParser.ts","../src/utils/numberedItemsRegistry.ts","../src/utils/componentAnnotations.ts","../src/core/cached-render.ts","../src/core/content.ts","../src/utils/bookmarkRegistry.ts","../src/utils/commentAnchors.ts","../src/utils/commentRegistry.ts","../src/utils/noteRegistry.ts","../src/utils/noteResolver.ts","../src/utils/numberingConfig.ts","../src/components/heading.ts","../src/components/paragraph.ts","../src/utils/listLevels.ts","../src/components/list.ts","../src/components/image.ts","../src/components/text-box.ts","../src/styles/utils/borderUtils.ts","../src/styles/utils/cellUtils.ts","../src/components/table.ts","../src/components/section.ts","../src/core/sectionBookmarks.ts","../src/components/columns.ts","../src/components/statistic.ts","../src/components/toc/index.ts","../src/components/highcharts.ts","../src/utils/environment.ts","../src/utils/serviceClient.ts","../src/components/visual.ts","../src/components/text-space-after.ts","../src/plugin/createComponent.ts","../src/core/prerasterizeVisuals.ts","../src/utils/promiseLimiter.ts","../src/core/sectionOrdinals.ts","../src/core/collectTocHeadings.ts","../src/utils/numberFormatting.ts","../src/core/fontResolution.ts","../src/utils/packageDocument.ts","../src/utils/fixFloatingImageIds.ts","../src/json/parser.ts","../src/json/normalizer.ts","../src/json/filesystem.ts","../src/core/flattenVisuals.ts","../src/utils/warningsDocument.ts","../src/index.ts","../src/templates/documents/index.ts","../src/utils/exampleRunner.ts","../src/plugin/createDocumentGenerator.ts","../src/plugin/version-resolver.ts","../src/plugin/validation.ts","../src/plugin/schema.ts"],"sourcesContent":["/**\n * Default theme values and utilities for handling optional theme properties\n */\n\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\n\n/**\n * Default colors for themes\n */\nexport const DEFAULT_COLORS = {\n primary: '#000000',\n secondary: '#666666',\n accent: '#0066CC',\n text: '#000000',\n background: '#FFFFFF',\n border: '#CCCCCC',\n // Semantic colors\n textPrimary: '#000000',\n textSecondary: '#666666',\n textMuted: '#999999',\n borderPrimary: '#CCCCCC',\n borderSecondary: '#E5E5E5',\n backgroundPrimary: '#FFFFFF',\n backgroundSecondary: '#F5F5F5',\n};\n\n/**\n * Default fonts for themes\n */\nexport const DEFAULT_FONTS = {\n heading: { family: 'Arial', size: 20 },\n body: { family: 'Arial', size: 11 },\n mono: { family: 'Courier New', size: 10 },\n light: { family: 'Arial', size: 24 },\n};\n\n/**\n * Default styles for themes\n */\nexport const DEFAULT_STYLES = {\n normal: {\n font: 'body' as const,\n size: 11,\n color: '#000000',\n alignment: 'left' as const,\n lineSpacing: {\n type: 'single' as const,\n value: 1,\n },\n spacing: {\n after: 6,\n },\n },\n heading1: {\n font: 'heading' as const,\n size: 24,\n color: '#000000',\n bold: true,\n spacing: {\n before: 12,\n after: 12,\n },\n },\n heading2: {\n font: 'heading' as const,\n size: 20,\n color: '#000000',\n bold: true,\n spacing: {\n before: 10,\n after: 10,\n },\n },\n heading3: {\n font: 'heading' as const,\n size: 16,\n color: '#000000',\n bold: true,\n spacing: {\n before: 8,\n after: 8,\n },\n },\n heading4: {\n font: 'heading' as const,\n size: 14,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n heading5: {\n font: 'heading' as const,\n size: 12,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n heading6: {\n font: 'heading' as const,\n size: 11,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n};\n\n/**\n * Default page settings\n */\nexport const DEFAULT_PAGE = {\n size: 'LETTER' as const,\n margins: {\n top: 720,\n bottom: 720,\n left: 720,\n right: 720,\n header: 360,\n footer: 360,\n gutter: 0,\n },\n};\n\n/**\n * Ensures theme has all required properties with defaults\n */\nexport function ensureThemeDefaults(\n theme: Partial<ThemeConfigJson>\n): ThemeConfigJson {\n return {\n $schema: theme.$schema,\n name: theme.name || 'default',\n displayName: theme.displayName || 'Default Theme',\n description: theme.description || 'Default theme configuration',\n version: theme.version || '1.0.0',\n colors: {\n ...DEFAULT_COLORS,\n ...(theme.colors || {}),\n },\n fonts: {\n heading: { ...DEFAULT_FONTS.heading, ...(theme.fonts?.heading || {}) },\n body: { ...DEFAULT_FONTS.body, ...(theme.fonts?.body || {}) },\n mono: { ...DEFAULT_FONTS.mono, ...(theme.fonts?.mono || {}) },\n light: { ...DEFAULT_FONTS.light, ...(theme.fonts?.light || {}) },\n },\n page: {\n ...DEFAULT_PAGE,\n ...(theme.page || {}),\n margins: {\n ...DEFAULT_PAGE.margins,\n ...(theme.page?.margins || {}),\n },\n },\n styles: theme.styles,\n componentDefaults: theme.componentDefaults,\n };\n}\n\n/**\n * Type guard to check if a theme has all required properties\n */\nexport function isCompleteTheme(theme: unknown): theme is ThemeConfigJson {\n const t = theme as Record<string, unknown>;\n return (\n t &&\n typeof t === 'object' &&\n !!t.colors &&\n !!t.fonts &&\n !!t.page &&\n typeof t.name === 'string' &&\n typeof t.displayName === 'string' &&\n typeof t.description === 'string' &&\n typeof t.version === 'string'\n );\n}\n\n/**\n * Safe getter for theme colors with defaults\n */\nexport function getThemeColors(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_COLORS,\n ...(theme.colors || {}),\n };\n}\n\n/**\n * Safe getter for theme fonts with defaults\n */\nexport function getThemeFonts(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_FONTS,\n ...(theme.fonts || {}),\n };\n}\n\n/**\n * Safe getter for theme styles with defaults\n */\nexport function getThemeStyles(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_STYLES,\n ...(theme.styles || {}),\n };\n}\n\n/**\n * Safe getter for normal style with defaults\n */\nexport function getNormalStyle(theme: Partial<ThemeConfigJson>) {\n const styles = getThemeStyles(theme);\n return {\n ...DEFAULT_STYLES.normal,\n ...(styles.normal || {}),\n };\n}\n","{\n \"$schema\": \"../../../../shared/json-schemas/theme.schema.json\",\n \"name\": \"minimal\",\n \"displayName\": \"Minimal Clean\",\n \"description\": \"A clean, minimalist theme focused on readability and elegant simplicity\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#000000\",\n \"secondary\": \"#666666\",\n \"accent\": \"#2c3e50\",\n \"background\": \"#ffffff\",\n \"text\": \"#2c2c2c\",\n \"border\": \"#f0f0f0\",\n \"textPrimary\": \"#000000\",\n \"textSecondary\": \"#4a4a4a\",\n \"textMuted\": \"#999999\",\n \"borderPrimary\": \"#e0e0e0\",\n \"borderSecondary\": \"#f5f5f5\",\n \"backgroundPrimary\": \"#ffffff\",\n \"backgroundSecondary\": \"#fafafa\"\n },\n \"fonts\": {\n \"heading\": {\n \"family\": \"Arial\",\n \"size\": 24\n },\n \"body\": {\n \"family\": \"Arial\",\n \"size\": 11\n },\n \"mono\": {\n \"family\": \"Menlo\",\n \"size\": 10\n },\n \"light\": {\n \"family\": \"Arial\",\n \"size\": 24\n }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#000000\",\n \"lineSpacing\": {\n \"type\": \"multiple\",\n \"value\": 1.5\n },\n \"alignment\": \"justify\",\n \"spacing\": {\n \"after\": 9\n }\n },\n \"heading1\": {\n \"font\": \"light\",\n \"size\": 24,\n \"bold\": false,\n \"color\": \"#000000\",\n \"spacing\": {\n \"before\": 18,\n \"after\": 12\n },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"characterSpacing\": {\n \"type\": \"expanded\",\n \"value\": 1.2\n }\n },\n \"heading2\": {\n \"font\": \"light\",\n \"size\": 20,\n \"bold\": false,\n \"color\": \"#000000\",\n \"spacing\": {\n \"before\": 12,\n \"after\": 9\n },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"characterSpacing\": {\n \"type\": \"expanded\",\n \"value\": 0.8\n }\n },\n \"heading3\": {\n \"font\": \"heading\",\n \"size\": 16,\n \"bold\": false,\n \"color\": \"#2c2c2c\",\n \"spacing\": {\n \"before\": 9,\n \"after\": 6\n },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading4\": {\n \"font\": \"heading\",\n \"size\": 14,\n \"bold\": true,\n \"color\": \"#4a4a4a\",\n \"spacing\": {\n \"before\": 6,\n \"after\": 4\n },\n \"keepNext\": true\n },\n \"heading5\": {\n \"font\": \"heading\",\n \"size\": 12,\n \"bold\": false,\n \"italic\": true,\n \"color\": \"#666666\",\n \"spacing\": {\n \"before\": 4,\n \"after\": 3\n }\n },\n \"heading6\": {\n \"font\": \"light\",\n \"size\": 11,\n \"bold\": false,\n \"color\": \"#999999\",\n \"spacing\": {\n \"before\": 3,\n \"after\": 2\n }\n },\n \"title\": {\n \"font\": \"light\",\n \"bold\": false,\n \"color\": \"#000000\",\n \"alignment\": \"left\",\n \"spacing\": {\n \"before\": 0,\n \"after\": 24\n },\n \"characterSpacing\": {\n \"type\": \"condensed\",\n \"value\": 20\n }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"#666666\",\n \"alignment\": \"left\",\n \"spacing\": {\n \"before\": 0,\n \"after\": 18\n }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#f0f0f0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"•\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"left\"\n },\n \"statistic\": {\n \"alignment\": \"left\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"corporate\",\n \"displayName\": \"Corporate Professional\",\n \"description\": \"A polished corporate theme with blue accents and structured typography\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#1a365d\",\n \"secondary\": \"#2D3748\",\n \"accent\": \"#3182CE\",\n \"text\": \"#1A202C\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#1A202C\",\n \"textSecondary\": \"#4A5568\",\n \"textMuted\": \"#A0AEC0\",\n \"borderPrimary\": \"#CBD5E0\",\n \"borderSecondary\": \"#E2E8F0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F7FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Georgia\", \"size\": 26 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Georgia\", \"size\": 26 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1200,\n \"right\": 1200,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#1A202C\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.4 },\n \"alignment\": \"justify\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 26,\n \"bold\": false,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 2,\n \"color\": \"primary\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": false,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"light\",\n \"size\": 32,\n \"bold\": false,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 18 }\n },\n \"subtitle\": {\n \"font\": \"body\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2022\",\n \"indent\": 3\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"modern\",\n \"displayName\": \"Modern Clean\",\n \"description\": \"A contemporary theme with vibrant accents and generous whitespace\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#6D28D9\",\n \"secondary\": \"#1E293B\",\n \"accent\": \"#0891B2\",\n \"text\": \"#0F172A\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#0F172A\",\n \"textSecondary\": \"#475569\",\n \"textMuted\": \"#94A3B8\",\n \"borderPrimary\": \"#CBD5E1\",\n \"borderSecondary\": \"#E2E8F0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F8FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Helvetica\", \"size\": 28 },\n \"body\": { \"family\": \"Helvetica\", \"size\": 11 },\n \"mono\": { \"family\": \"Menlo\", \"size\": 10 },\n \"light\": { \"family\": \"Helvetica\", \"size\": 28 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#0F172A\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.5 },\n \"alignment\": \"left\",\n \"spacing\": { \"after\": 10 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 28,\n \"bold\": true,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 14 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 20,\n \"bold\": true,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 10 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 14,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"heading\",\n \"size\": 36,\n \"bold\": true,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 12 }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 18,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2013\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"apex\",\n \"displayName\": \"Apex Consulting\",\n \"description\": \"A premium consulting theme with deep navy, warm amber accents, and authoritative typography\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#0C2340\",\n \"secondary\": \"#1B3A5C\",\n \"accent\": \"#D4A843\",\n \"text\": \"#1A1A2E\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#D6DAE0\",\n \"textPrimary\": \"#1A1A2E\",\n \"textSecondary\": \"#4A5066\",\n \"textMuted\": \"#8B91A0\",\n \"borderPrimary\": \"#B8BCC6\",\n \"borderSecondary\": \"#E8EAF0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F4F5F8\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Georgia\", \"size\": 26 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Georgia\", \"size\": 26 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1200,\n \"right\": 1200,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"textPrimary\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.4 },\n \"alignment\": \"justify\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 26,\n \"bold\": false,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 2,\n \"color\": \"accent\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": false,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"light\",\n \"size\": 36,\n \"bold\": false,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 18 }\n },\n \"subtitle\": {\n \"font\": \"body\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#D6DAE0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2022\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"devportal\",\n \"displayName\": \"Developer Portal\",\n \"description\": \"A modern developer-focused theme with cool grays, teal accents, and monospace code styling\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#0F172A\",\n \"secondary\": \"#334155\",\n \"accent\": \"#0D9488\",\n \"text\": \"#0F172A\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#0F172A\",\n \"textSecondary\": \"#475569\",\n \"textMuted\": \"#94A3B8\",\n \"borderPrimary\": \"#CBD5E1\",\n \"borderSecondary\": \"#F1F5F9\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F8FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Helvetica\", \"size\": 24 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Helvetica\", \"size\": 24 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"textPrimary\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.5 },\n \"alignment\": \"left\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 24,\n \"bold\": true,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 1,\n \"color\": \"accent\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": true,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading4\": {\n \"font\": \"body\",\n \"size\": 12,\n \"bold\": true,\n \"color\": \"textSecondary\",\n \"spacing\": { \"before\": 8, \"after\": 4 },\n \"keepNext\": true\n },\n \"title\": {\n \"font\": \"heading\",\n \"size\": 32,\n \"bold\": true,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 12 }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2013\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","/**\n * JSON-based themes registry\n * This file provides a unified interface to JSON themes\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n isValidThemeConfig,\n type ThemeConfigJson,\n} from '@json-to-office/shared-docx';\nimport { ensureThemeDefaults } from '../../themes/defaults';\n\n// Import theme JSON files directly. Every bundled theme is imported here, so\n// which themes exist is decided by code, not by whether `dist/` happens to be\n// built and fresh — `apex` and `devportal` used to be reachable only through\n// the filesystem scan below, which meant a stale build silently served the old\n// copy and a missing one degraded to `minimal`.\nimport minimalThemeJson from './minimal.docx.theme.json';\nimport corporateThemeJson from './corporate.docx.theme.json';\nimport modernThemeJson from './modern.docx.theme.json';\nimport apexThemeJson from './apex.docx.theme.json';\nimport devportalThemeJson from './devportal.docx.theme.json';\n\n/**\n * Registry of available themes loaded from JSON files\n */\nlet _themesCache: Record<string, ThemeConfigJson> | null = null;\n\nfunction loadThemesFromJson(): Record<string, ThemeConfigJson> {\n if (_themesCache) {\n return _themesCache;\n }\n\n // Build themes from imported JSON files\n const themes: Record<string, ThemeConfigJson> = {\n minimal: ensureThemeDefaults(minimalThemeJson as ThemeConfigJson),\n corporate: ensureThemeDefaults(corporateThemeJson as ThemeConfigJson),\n modern: ensureThemeDefaults(modernThemeJson as ThemeConfigJson),\n apex: ensureThemeDefaults(apexThemeJson as ThemeConfigJson),\n devportal: ensureThemeDefaults(devportalThemeJson as ThemeConfigJson),\n };\n\n // Also try to load from file system for runtime additions (if available)\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const themesDir = path.join(__dirname, '../../../dist/templates/themes');\n\n if (fs.existsSync(themesDir)) {\n const themeFiles = fs\n .readdirSync(themesDir)\n .filter((file) => file.endsWith('.docx.theme.json'))\n .map((file) => path.basename(file, '.docx.theme.json'));\n\n for (const themeName of themeFiles) {\n if (!themes[themeName]) {\n try {\n const filePath = path.join(\n themesDir,\n `${themeName}.docx.theme.json`\n );\n const content = fs.readFileSync(filePath, 'utf8');\n const parsedTheme = JSON.parse(content);\n // Check before registering. A theme that reaches the registry is\n // never validated again, so an invalid one here renders wrong\n // rather than failing — the drift that hid dead `componentDefaults`\n // props across five themes for as long as they shipped.\n if (!isValidThemeConfig(parsedTheme)) {\n console.warn(\n `Skipping theme ${themeName}: does not match the theme schema.`\n );\n continue;\n }\n themes[themeName] = ensureThemeDefaults(parsedTheme);\n } catch (error) {\n console.warn(\n `Failed to load additional theme ${themeName}:`,\n error\n );\n }\n }\n }\n }\n } catch (error) {\n // Silently ignore if file system access fails (e.g., in bundled environment)\n }\n\n _themesCache = themes;\n return themes;\n}\n\nexport const themes = loadThemesFromJson();\n\n/**\n * Type representing valid theme names\n */\nexport type ThemeName = keyof typeof themes;\n\n/**\n * Get theme configuration by name\n * @param themeName - Name of the theme to retrieve\n * @returns Theme configuration or undefined if not found\n */\nexport const getTheme = (themeName: string): ThemeConfigJson | undefined => {\n return themes[themeName];\n};\n\n/**\n * Get theme configuration with safe fallback\n * @param themeName - Name of the theme to retrieve\n * @param fallbackTheme - Fallback theme name (default: 'minimal')\n * @returns Theme configuration (guaranteed to be defined)\n * @throws Error if neither theme nor fallback can be found\n */\nexport const getThemeWithFallback = (\n themeName: string,\n fallbackTheme: string = 'minimal'\n): ThemeConfigJson => {\n const theme = getTheme(themeName) || getTheme(fallbackTheme);\n\n if (!theme) {\n throw new Error(\n `Failed to load theme: ${themeName}. Fallback theme '${fallbackTheme}' also not found.`\n );\n }\n\n return theme;\n};\n\n/**\n * Check if a theme exists\n * @param themeName - Name of the theme to check\n * @returns True if theme exists, false otherwise\n */\nexport const hasTheme = (themeName: string): boolean => {\n return themeName in themes;\n};\n\n/**\n * Type guard to ensure theme name is valid\n * @param themeName - Theme name to validate\n * @returns True if theme name exists in registry\n */\nexport const isValidThemeName = (\n themeName: string\n): themeName is keyof typeof themes => {\n return hasTheme(themeName);\n};\n\n/**\n * Get all available theme names\n * @returns Array of theme names\n */\nexport const getThemeNames = (): string[] => {\n return Object.keys(themes);\n};\n\n// Export individual theme configs for direct access\nexport const minimalTheme = themes['minimal'];\nexport const corporateTheme = themes['corporate'];\nexport const modernTheme = themes['modern'];\n","import { ThemeConfig } from '../index';\nimport { getThemeColors } from '../../themes/defaults';\n\nexport type ColorName = keyof ReturnType<typeof getThemeColors>;\n\n// Union type for all valid color names\nexport type ValidColorName =\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'text'\n | 'background'\n | 'textPrimary'\n | 'textSecondary'\n | 'textMuted'\n | 'borderPrimary'\n | 'borderSecondary'\n | 'backgroundPrimary'\n | 'backgroundSecondary';\n\n// Type for color value that can be either a hex string or a color name\nexport type ColorValue = string; // Can be hex color or color name\n\n/**\n * Resolves a color value, which can be either a hex color string or a color name reference\n * @param colorValue - Either a hex color (e.g., '#000000') or a color name (e.g., 'primary')\n * @param theme - The theme configuration containing color definitions\n * @returns The resolved hex color value (6-character hex without #)\n * @throws Error if the color value is invalid\n */\nexport function resolveColor(\n colorValue: ColorValue,\n theme: ThemeConfig\n): string {\n // Check if it's a hex color with # prefix\n if (colorValue.startsWith('#')) {\n const hexValue = colorValue.slice(1);\n if (/^[0-9A-Fa-f]{6}$/.test(hexValue)) {\n return hexValue.toUpperCase(); // Normalize to uppercase\n }\n // Invalid hex format\n throw new Error(\n `Invalid hex color: \"${colorValue}\". Hex colors must be in format #RRGGBB (e.g., \"#000000\").`\n );\n }\n\n // If it's a color name, resolve it from the theme. Optional slots\n // (accent4-6) may be present-but-undefined, which counts as unset.\n const colors = getThemeColors(theme);\n const resolvedColor = colors[colorValue as ColorName];\n if (typeof resolvedColor === 'string') {\n // Recursively resolve in case the theme color is also a reference\n return resolveColor(resolvedColor, theme);\n }\n\n // Bare 6-digit hex, e.g. \"F0FDF4\". HexColorSchema admits it through the\n // theme-name branch, so rejecting it here would validate a document and then\n // throw while rendering it. Table cells and the chart palette already accept\n // this form; no theme color name is six hex characters, so there is no\n // ambiguity with a real token.\n if (/^[0-9A-Fa-f]{6}$/.test(colorValue)) {\n return colorValue.toUpperCase();\n }\n\n // Strict validation - throw error for invalid colors\n throw new Error(\n `Invalid color value: \"${colorValue}\". Must be a hex color with # prefix (e.g., \"#000000\") or a valid theme color name.`\n );\n}\n\n/**\n * Validates if a color name is set in the theme\n * @param colorName - The color name to validate\n * @param theme - The theme configuration\n * @returns True if the color name resolves to a value. A present-but-undefined\n * optional slot counts as unset, matching what `resolveColor` accepts.\n */\nexport function isValidColorName(\n colorName: string,\n theme: ThemeConfig\n): boolean {\n const colors = getThemeColors(theme);\n if (typeof colors[colorName as ColorName] !== 'string') return false;\n // Follow the reference chain: a token whose value names an unset slot is not\n // usable, so reporting it as valid would hand a caller a color that throws.\n try {\n resolveColor(colorName as ColorValue, theme);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Gets all available color names from a theme\n * @param theme - The theme configuration\n * @returns Array of valid color names, excluding present-but-undefined slots\n */\nexport function getAvailableColorNames(theme: ThemeConfig): string[] {\n const colors = getThemeColors(theme);\n return Object.keys(colors).filter((name) => isValidColorName(name, theme));\n}\n","import { getTheme } from '../../templates/themes';\nimport { ThemeConfig } from '../index';\nimport { resolveColor } from './colorUtils';\nimport { LineSpacing } from '@json-to-office/shared-docx';\nimport { ISpacingProperties } from 'docx';\nimport { getNormalStyle } from '../../themes/defaults';\n\n// Constants for line spacing calculations\nconst TWIPS_PER_POINT = 20;\nconst SINGLE_LINE_SPACING_POINTS = 12;\nconst SINGLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_POINTS * TWIPS_PER_POINT;\nconst DOUBLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_TWIPS * 2;\n\n/**\n * Convert points to twips for docx spacing\n * @param points - Value in points\n * @returns Value in twips (1/20 of a point)\n */\nexport function pointsToTwips(points: number): number {\n return Math.round(points * TWIPS_PER_POINT);\n}\n\n/**\n * Resolve theme configuration from either a theme object or theme name\n * @param theme - Theme configuration object (for custom themes)\n * @param themeName - Theme name (for built-in themes)\n * @returns Resolved theme configuration\n */\nexport function resolveTheme(\n theme?: ThemeConfig,\n themeName?: string\n): ThemeConfig | undefined {\n // First check if we have a theme object passed directly (for custom themes)\n if (theme) {\n return theme;\n }\n\n // If no theme object, check for built-in theme by name\n if (themeName) {\n return getTheme(themeName);\n }\n\n // Default to minimal theme if nothing else works\n return getTheme('minimal');\n}\n\n/**\n * Resolve font family from font reference (e.g., 'body', 'heading') to actual font family name\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Actual font family name (e.g., 'Arial', 'Helvetica')\n */\nexport function resolveFontFamily(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): string {\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.body?.family) {\n return 'Arial'; // fallback to Arial\n }\n if (!fontRef) {\n return theme.fonts.body.family;\n }\n return theme.fonts[fontRef]?.family || theme.fonts.body.family;\n}\n\n/**\n * Resolve font size from font reference (e.g., 'body', 'heading') to actual font size in points\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Font size in points (callers multiply by 2 for docx) or undefined if no size found\n */\nexport function resolveFontSize(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): number | undefined {\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.body?.size) {\n return undefined; // let caller handle fallback\n }\n if (!fontRef) {\n return theme.fonts.body.size;\n }\n return theme.fonts[fontRef]?.size || theme.fonts.body.size;\n}\n\n/**\n * Font properties that can be defined in font definitions\n */\nexport interface FontProperties {\n family?: string;\n size?: number;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n alignment?: 'left' | 'center' | 'right' | 'justify';\n lineSpacing?: {\n type: 'single' | 'atLeast' | 'exactly' | 'double' | 'multiple';\n value?: number;\n };\n spacing?: {\n before?: number;\n after?: number;\n };\n characterSpacing?: { type: 'condensed' | 'expanded'; value: number };\n scale?: number;\n}\n\n/**\n * Resolve all font properties from font reference.\n * Returns all formatting properties defined in the font definition.\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Object containing all font properties\n */\nexport function resolveFontProperties(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): FontProperties {\n // Default to body font if no reference provided\n const targetFontKey = fontRef || 'body';\n\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.[targetFontKey]) {\n return {\n family: 'Arial',\n size: 11,\n };\n }\n\n const fontDef = theme.fonts[targetFontKey] as FontProperties;\n\n return {\n family: fontDef.family,\n size: fontDef.size,\n color: fontDef.color,\n bold: fontDef.bold,\n italic: fontDef.italic,\n underline: fontDef.underline,\n alignment: fontDef.alignment,\n lineSpacing: fontDef.lineSpacing,\n spacing: fontDef.spacing,\n characterSpacing: fontDef.characterSpacing,\n scale: fontDef.scale,\n };\n}\n\n/**\n * Merge font properties with style overrides.\n * Style properties take precedence over font properties.\n * Only defined (non-undefined) style properties override font properties.\n * @param fontProps - Properties from font definition\n * @param styleOverrides - Properties from style definition\n * @returns Merged properties object\n */\nexport function mergeFontAndStyleProperties<T extends Partial<FontProperties>>(\n fontProps: FontProperties,\n styleOverrides: T\n): FontProperties & T {\n // Filter out undefined values from styleOverrides to prevent overwriting font properties\n // Use type-safe Object.entries approach\n const definedOverrides = Object.entries(styleOverrides).reduce<\n Record<string, unknown>\n >((acc, [key, value]) => {\n if (value !== undefined) {\n acc[key] = value;\n }\n return acc;\n }, {});\n\n return {\n ...fontProps,\n ...definedOverrides,\n } as FontProperties & T;\n}\n\n/**\n * Get body text style configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Style configuration object\n */\nexport const getBodyTextStyle = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig) {\n const normalStyle = getNormalStyle(themeConfig);\n return {\n size: (normalStyle.size || 11) * 2,\n font: resolveFontFamily(themeConfig, normalStyle.font),\n color: normalStyle.color\n ? resolveColor(normalStyle.color, themeConfig)\n : '000000',\n };\n }\n\n // Fallback\n return {\n size: 20,\n font: 'Arial',\n color: '000000',\n };\n};\n\n/**\n * Converts line spacing from theme definition to DOCX spacing options.\n * DOCX uses twips (1/20th of a point) for line spacing.\n * @param lineSpacing The line spacing object from the theme definition.\n * @returns IParagraphSpacingOptions for docx.\n */\nexport function convertLineSpacing(\n lineSpacing?: LineSpacing | number\n): ISpacingProperties | undefined {\n if (lineSpacing === undefined) {\n return undefined;\n }\n\n // Handle number (simple multiplier) case\n if (typeof lineSpacing === 'number') {\n return {\n line: Math.round(lineSpacing * SINGLE_LINE_SPACING_TWIPS),\n lineRule: 'auto',\n };\n }\n\n const { type, value } = lineSpacing;\n let line: number | undefined;\n let lineRule: 'auto' | 'exact' | 'atLeast' | undefined;\n\n switch (type) {\n case 'single':\n line = SINGLE_LINE_SPACING_TWIPS;\n lineRule = 'auto';\n break;\n case 'double':\n line = DOUBLE_LINE_SPACING_TWIPS;\n lineRule = 'auto';\n break;\n case 'atLeast':\n line = value !== undefined ? value * TWIPS_PER_POINT : undefined;\n lineRule = 'atLeast';\n break;\n case 'exactly':\n line = value !== undefined ? value * TWIPS_PER_POINT : undefined;\n lineRule = 'exact';\n break;\n case 'multiple':\n line =\n value !== undefined ? value * SINGLE_LINE_SPACING_TWIPS : undefined;\n lineRule = 'auto';\n break;\n default:\n return undefined;\n }\n\n return { line, lineRule };\n}\n","import { BorderStyle } from 'docx';\nimport { LineSpacing } from '@json-to-office/shared-docx';\nimport { ThemeConfig } from '../index';\nimport { resolveColor } from './colorUtils';\nimport {\n resolveTheme,\n resolveFontFamily,\n convertLineSpacing,\n pointsToTwips,\n} from './styleHelpers';\n\n/**\n * Subset of a theme StyleProperties entry relevant to paragraph spacing.\n */\ninterface TableParagraphStyle {\n spacing?: { before?: number; after?: number };\n lineSpacing?: LineSpacing;\n}\n\n/**\n * Resolve the paragraph spacing for a table cell/header wrapper paragraph.\n *\n * Table cells render as a single wrapper paragraph. Historically that paragraph\n * inherited the `normal` style, dragging body-prose rhythm (8–10pt after-spacing\n * + 1.4–1.5x line) into every row and inflating row height regardless of font\n * size, padding, or the cell `height` prop. Tables should be dense by default:\n * no extra paragraph spacing, single line. Vertical breathing room is the job of\n * cell padding, not paragraph spacing.\n *\n * Themes may override per context via `styles.tableCell` / `styles.tableHeader`\n * (standard StyleProperties: `spacing.before/after` in points, `lineSpacing`).\n */\nconst resolveTableParagraphSpacing = (style?: TableParagraphStyle) => {\n const lineSpacing =\n convertLineSpacing(style?.lineSpacing) ??\n convertLineSpacing({ type: 'single' });\n return {\n before:\n style?.spacing?.before !== undefined\n ? pointsToTwips(style.spacing.before)\n : 0,\n after:\n style?.spacing?.after !== undefined\n ? pointsToTwips(style.spacing.after)\n : 0,\n ...lineSpacing,\n };\n};\n\n/**\n * Standard page sizes in twips (1/20 of a point, 1/1440 of an inch).\n *\n * `code` is the OOXML `w:pgSz/@w:code` paper-size code — the Windows DEVMODE\n * `dmPaperSize` value that printer drivers key off (from `wingdi.h`:\n * DMPAPER_LETTER 1, DMPAPER_LEGAL 5, DMPAPER_A3 8, DMPAPER_A4 9). Without it a\n * driver has to infer the tray from the dimensions.\n */\nexport const PAGE_SIZES = {\n A4: { width: 11906, height: 16838, code: 9 },\n A3: { width: 16838, height: 23811, code: 8 },\n LETTER: { width: 12240, height: 15840, code: 1 },\n LEGAL: { width: 12240, height: 20160, code: 5 },\n} as const;\n\nexport interface PageDimensions {\n width: number;\n height: number;\n /** Present only for a named size; a custom size has no paper code. */\n code?: number;\n}\n\n/**\n * Get page dimensions from size (string or object).\n *\n * A custom `{ width, height }` deliberately returns no `code`: it is not one of\n * the standard papers, and claiming a code would send the driver to the wrong\n * tray.\n */\nexport function getPageDimensions(\n size: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number }\n): PageDimensions {\n if (typeof size === 'string') {\n return PAGE_SIZES[size];\n }\n return { width: size.width, height: size.height };\n}\n\n/**\n * Get table style configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Table style configuration object\n */\nexport const getTableStyle = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig && themeConfig.styles?.normal) {\n // Use normal style for run-level header/cell defaults (font, size, color).\n // Paragraph spacing is resolved separately so table rows stay dense and do\n // not inherit `normal`'s body-prose after-spacing/line height.\n const normalStyle = themeConfig.styles.normal;\n const styles = themeConfig.styles as Record<string, TableParagraphStyle>;\n return {\n cellParagraph: resolveTableParagraphSpacing(styles.tableCell),\n headerParagraph: resolveTableParagraphSpacing(styles.tableHeader),\n tableHeader: {\n fill: resolveColor(\n themeConfig.colors?.primary || '#000000',\n themeConfig\n ),\n color: resolveColor(\n themeConfig.colors?.backgroundPrimary || '#FFFFFF',\n themeConfig\n ), // Use background color for header text\n bold: true, // Headers should be bold\n size: (normalStyle.size || 11) * 2, // Convert to half-points\n font: resolveFontFamily(themeConfig, normalStyle.font),\n },\n tableCell: {\n color: resolveColor(normalStyle.color || '#000000', themeConfig),\n size: (normalStyle.size || 11) * 2, // Convert to half-points\n font: resolveFontFamily(themeConfig, normalStyle.font),\n },\n alternatingRow: {\n fill: resolveColor(\n themeConfig.colors?.accent || '#F0F0F0',\n themeConfig\n ),\n },\n borders: {\n top: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n bottom: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n left: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n right: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n },\n };\n }\n\n // This shouldn't happen with minimal themes\n return {\n cellParagraph: resolveTableParagraphSpacing(),\n headerParagraph: resolveTableParagraphSpacing(),\n tableHeader: {\n fill: '000000',\n color: 'FFFFFF',\n bold: true,\n size: 22,\n font: 'Arial',\n },\n tableCell: {\n color: '000000',\n size: 20,\n font: 'Arial',\n },\n alternatingRow: {\n fill: 'F5F5F5',\n },\n borders: {\n top: { style: BorderStyle.SINGLE, size: 1, color: '000000' },\n bottom: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: '000000',\n },\n left: { style: BorderStyle.SINGLE, size: 1, color: '000000' },\n right: {\n style: BorderStyle.SINGLE,\n size: 1,\n color: '000000',\n },\n },\n };\n};\n\n/**\n * Get document margins configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Document margins object\n */\nexport const getDocumentMargins = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig?.page?.margins) {\n return themeConfig.page.margins;\n }\n\n // Default margins for all themes (standard Word document margins)\n return {\n top: 1440, // 1 inch in twips\n right: 1440, // 1 inch in twips\n bottom: 1440, // 1 inch in twips\n left: 1440, // 1 inch in twips\n header: 720, // 0.5 inch in twips\n footer: 720, // 0.5 inch in twips\n };\n};\n\n/**\n * Get page setup configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Page setup object\n */\nexport const getPageSetup = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n const defaultMargins = getDocumentMargins(theme, themeName);\n\n if (themeConfig?.page) {\n const margins = themeConfig.page.margins || {};\n const dimensions = getPageDimensions(themeConfig.page.size);\n return {\n size: {\n width: dimensions.width,\n height: dimensions.height,\n ...(dimensions.code !== undefined && { code: dimensions.code }),\n },\n margin: {\n top: margins.top ?? defaultMargins.top ?? 1440,\n right: margins.right ?? defaultMargins.right ?? 1440,\n bottom: margins.bottom ?? defaultMargins.bottom ?? 1440,\n left: margins.left ?? defaultMargins.left ?? 1440,\n },\n };\n }\n\n // Default page setup for all themes\n return {\n size: {\n width: PAGE_SIZES.A4.width, // 210mm in twips (A4)\n height: PAGE_SIZES.A4.height, // 297mm in twips (A4)\n code: PAGE_SIZES.A4.code,\n },\n margin: {\n top: defaultMargins.top ?? 1440,\n right: defaultMargins.right ?? 1440,\n bottom: defaultMargins.bottom ?? 1440,\n left: defaultMargins.left ?? 1440,\n },\n };\n};\n","/**\n * Theme Parser using unified validation (TypeBox under the hood)\n */\n\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { validateThemeJson } from '@json-to-office/shared-docx/validation/unified';\nimport type { ValidationError } from '@json-to-office/shared-docx/validation/unified';\nimport { ensureThemeDefaults } from '../../themes/defaults';\n\n// Custom error classes with enhanced error details\nexport class ThemeValidationError extends Error {\n constructor(public errors: ValidationError[]) {\n const errorCount = errors.length;\n const errorSummary = errors\n .slice(0, 3)\n .map((error) => {\n const path = error.path\n ? error.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${error.message}`;\n })\n .join('; ');\n\n super(\n `Theme validation failed with ${errorCount} error${errorCount > 1 ? 's' : ''}: ${errorSummary}${errorCount > 3 ? '...' : ''}`\n );\n this.name = 'ThemeValidationError';\n }\n\n getDetailedErrors(): string[] {\n return this.errors.map((error) => {\n const path = error.path\n ? error.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${error.message}`;\n });\n }\n}\n\nexport class ThemeParseError extends Error {\n constructor(\n message: string,\n public cause?: Error\n ) {\n super(`Failed to parse theme: ${message}`);\n this.name = 'ThemeParseError';\n }\n}\n\n// Theme parser class with comprehensive validation and error handling\nexport class ThemeParser {\n private readonly MAX_JSON_SIZE = 1024 * 1024; // 1MB limit (pre-parse guard)\n\n parse(jsonString: string): ThemeConfigJson {\n try {\n // Input validation and sanitization\n this.validateInput(jsonString);\n\n // Use unified validator (handles parsing + position calculation)\n const result = validateThemeJson(jsonString);\n if (!result.valid) {\n throw new ThemeValidationError(result.errors || []);\n }\n\n const validated = result.data as ThemeConfigJson;\n\n // Apply defaults and return ThemeConfig\n return this.applyDefaults(validated);\n } catch (error) {\n if (\n error instanceof ThemeValidationError ||\n error instanceof ThemeParseError\n ) {\n throw error;\n }\n throw new ThemeParseError(\n `Unexpected error during theme parsing: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private validateInput(jsonString: string): void {\n // Check for null/undefined\n if (!jsonString) {\n throw new ThemeParseError('JSON string cannot be null or empty');\n }\n\n // Check string type\n if (typeof jsonString !== 'string') {\n throw new ThemeParseError('Input must be a string');\n }\n\n // Check size limits (additional robustness guard)\n if (jsonString.length > this.MAX_JSON_SIZE) {\n throw new ThemeParseError(\n `JSON string too large (${jsonString.length} bytes, max ${this.MAX_JSON_SIZE} bytes)`\n );\n }\n }\n\n private applyDefaults(parsedTheme: ThemeConfigJson): ThemeConfigJson {\n // Apply defaults to ensure all required properties are present\n // This handles partial theme configurations by merging with defaults\n return ensureThemeDefaults(parsedTheme);\n }\n\n // Utility method for validating without parsing\n validate(jsonString: string): { valid: boolean; errors?: string[] } {\n try {\n this.validateInput(jsonString);\n const result = validateThemeJson(jsonString);\n\n if (result.valid) {\n return { valid: true };\n } else {\n const errors = (result.errors || []).map((e) => {\n const path = e.path\n ? e.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${e.message}`;\n });\n return { valid: false, errors };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n error instanceof Error ? error.message : 'Unknown validation error',\n ],\n };\n }\n }\n}\n","/**\n * Theme Validator - thin wrapper over shared unified validator\n * Maintains backward-compatible API while removing duplicate logic\n */\n\nimport { validateThemeJson as validateThemeJsonUnified } from '@json-to-office/shared-docx/validation/unified';\n\n// Backward-compatible ValidationResult type used by core\nexport type ValidationResult = {\n success: boolean;\n error?: {\n issues: Array<{\n code: string;\n message: string;\n path: Array<string | number>;\n expected?: string;\n received?: string;\n type?: string;\n minimum?: number;\n maximum?: number;\n validation?: string;\n options?: string[];\n line?: number;\n column?: number;\n }>;\n };\n};\n\n// Validator function using unified shared validation\nexport function validateThemeJson(jsonString: string): ValidationResult {\n const result = validateThemeJsonUnified(jsonString);\n\n if (result.valid) {\n return { success: true };\n }\n\n const issues = (result.errors || []).map((e) => {\n const pathArray = (e.path || '')\n .split('/')\n .filter((p) => p)\n .map((p) => {\n const num = parseInt(p, 10);\n return isNaN(num) ? p : num;\n });\n\n return {\n code: e.code || 'validation_error',\n message: e.message,\n path: pathArray,\n line: e.line,\n column: e.column,\n };\n });\n\n return { success: false, error: { issues } };\n}\n\nexport function formatValidationErrors(error: {\n issues: Array<any>;\n}): string[] {\n return error.issues.map((issue) => {\n const path =\n issue.path && issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';\n let message = issue.message;\n // Keep messages simple; unified validator already includes good messages\n return `${path}${message}`;\n });\n}\n\nexport function isValidThemeJson(jsonString: string): boolean {\n const result = validateThemeJson(jsonString);\n return result.success;\n}\n\nexport function getValidationSummary(jsonString: string): {\n valid: boolean;\n errorCount: number;\n errors: string[];\n summary: string;\n} {\n const result = validateThemeJson(jsonString);\n\n if (result.success) {\n return {\n valid: true,\n errorCount: 0,\n errors: [],\n summary: 'Theme JSON is valid',\n };\n }\n\n const errors = formatValidationErrors(result.error!);\n const errorCount = errors.length;\n\n return {\n valid: false,\n errorCount,\n errors,\n summary: `Theme validation failed with ${errorCount} error${errorCount > 1 ? 's' : ''}`,\n };\n}\n","import { promises as fs } from 'fs';\nimport { normalize } from 'path';\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { ThemeParser } from './parser';\n\n// File system error class with enhanced error details\nexport class ThemeFileError extends Error {\n constructor(\n message: string,\n public path?: string,\n public _cause?: Error\n ) {\n const pathInfo = path ? ` (path: ${path})` : '';\n super(`Failed to load theme file: ${message}${pathInfo}`);\n this.name = 'ThemeFileError';\n }\n}\n\n// Theme loader class with comprehensive security and error handling\nexport class ThemeLoader {\n private parser = new ThemeParser();\n private readonly MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB limit\n private readonly ALLOWED_EXTENSIONS = ['.json'];\n\n async loadFromFile(filePath: string): Promise<ThemeConfigJson> {\n try {\n // Validate file path for security\n this.validateFilePath(filePath);\n\n // Read file with size limits\n const content = await this.readFileWithLimits(filePath);\n\n // Parse the theme content\n return this.parser.parse(content);\n } catch (error) {\n if (error instanceof ThemeFileError) {\n throw error;\n }\n\n // Handle file system errors\n if (error && typeof error === 'object' && 'code' in error) {\n const fsError = error as { code?: string; message: string };\n let message: string;\n\n switch (fsError.code) {\n case 'ENOENT':\n message = 'File not found';\n break;\n case 'EACCES':\n message = 'Permission denied';\n break;\n case 'EISDIR':\n message = 'Path is a directory, not a file';\n break;\n case 'EMFILE':\n case 'ENFILE':\n message = 'Too many open files';\n break;\n case 'ENOTDIR':\n message = 'Directory in path does not exist';\n break;\n default:\n message = `File system error: ${fsError.message}`;\n }\n\n throw new ThemeFileError(\n message,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle other errors\n throw new ThemeFileError(\n `Unexpected error: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n async loadFromUrl(_url: string): Promise<ThemeConfigJson> {\n // Future enhancement for loading themes from URLs\n // Would need additional dependencies (fetch) and security considerations\n throw new ThemeFileError(\n 'URL loading not yet implemented - use loadFromFile() instead'\n );\n }\n\n private validateFilePath(filePath: string): void {\n // Basic input validation\n if (!filePath || typeof filePath !== 'string') {\n throw new ThemeFileError('File path must be a non-empty string');\n }\n\n // Normalize the path to handle different separators and relative paths\n const normalizedPath = normalize(filePath);\n\n // Check for directory traversal attempts\n if (normalizedPath.includes('..')) {\n throw new ThemeFileError('Directory traversal is not allowed', filePath);\n }\n\n // Check for null bytes (path injection)\n if (normalizedPath.includes('\\0')) {\n throw new ThemeFileError(\n 'Null bytes in file path are not allowed',\n filePath\n );\n }\n\n // Validate file extension\n const hasValidExtension = this.ALLOWED_EXTENSIONS.some((ext) =>\n normalizedPath.toLowerCase().endsWith(ext)\n );\n\n if (!hasValidExtension) {\n throw new ThemeFileError(\n `Invalid file extension. Allowed: ${this.ALLOWED_EXTENSIONS.join(', ')}`,\n filePath\n );\n }\n\n // Additional security: ensure path is reasonable length\n if (normalizedPath.length > 1000) {\n throw new ThemeFileError('File path is too long', filePath);\n }\n }\n\n private async readFileWithLimits(filePath: string): Promise<string> {\n try {\n // Get file stats to check size before reading\n const stats = await fs.stat(filePath);\n\n // Check if it's actually a file\n if (!stats.isFile()) {\n throw new ThemeFileError('Path is not a regular file', filePath);\n }\n\n // Check file size limits\n if (stats.size > this.MAX_FILE_SIZE) {\n throw new ThemeFileError(\n `File too large (${stats.size} bytes, max ${this.MAX_FILE_SIZE} bytes)`,\n filePath\n );\n }\n\n // Check for empty file\n if (stats.size === 0) {\n throw new ThemeFileError('File is empty', filePath);\n }\n\n // Read file with proper encoding\n const content = await fs.readFile(filePath, 'utf8');\n\n // Verify content was read properly\n if (typeof content !== 'string') {\n throw new ThemeFileError('Failed to read file as text', filePath);\n }\n\n return content;\n } catch (error) {\n if (error instanceof ThemeFileError) {\n throw error;\n }\n\n // Re-throw as ThemeFileError for consistent error handling\n throw new ThemeFileError(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // Utility method to validate a file path without reading\n validateFile(filePath: string): { valid: boolean; error?: string } {\n try {\n this.validateFilePath(filePath);\n return { valid: true };\n } catch (error) {\n return {\n valid: false,\n error:\n error instanceof Error ? error.message : 'Unknown validation error',\n };\n }\n }\n\n // Utility method to get file info\n async getFileInfo(filePath: string): Promise<{\n exists: boolean;\n size?: number;\n isFile?: boolean;\n error?: string;\n }> {\n try {\n const stats = await fs.stat(filePath);\n return {\n exists: true,\n size: stats.size,\n isFile: stats.isFile(),\n };\n } catch (error) {\n return {\n exists: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n","// Public API exports for JSON theme system\nexport {\n ThemeConfigSchema,\n type ThemeConfigJson,\n isValidThemeConfig,\n /**\n * Create a minimal theme template for users to start with.\n * Defined in shared-docx next to `ThemeConfigSchema` so every consumer\n * (CLI, playground) scaffolds from one schema-checked source.\n */\n createMinimalTheme,\n} from '@json-to-office/shared-docx';\nexport { ThemeParser, ThemeValidationError, ThemeParseError } from './parser';\nexport {\n validateThemeJson,\n formatValidationErrors,\n type ValidationResult,\n} from './validator';\nexport { ThemeLoader, ThemeFileError } from './loader';\n\n// Main API functions - Core public interface for JSON theme system\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { ThemeParser } from './parser';\nimport { ThemeLoader } from './loader';\n\n// Global instances for consistent behavior\nconst themeParser = new ThemeParser();\nconst themeLoader = new ThemeLoader();\n\n/**\n * Load and parse a theme from a JSON string\n * @param jsonString - JSON string containing theme definition\n * @returns Promise<ThemeConfig> - Parsed and validated theme configuration\n * @throws ThemeParseError - If JSON is malformed or invalid\n * @throws ThemeValidationError - If theme fails schema validation\n */\nexport async function loadThemeFromJson(\n jsonString: string\n): Promise<ThemeConfigJson> {\n return themeParser.parse(jsonString);\n}\n\n/**\n * Load and parse a theme from a JSON file\n * @param filePath - Path to JSON file containing theme definition\n * @returns Promise<ThemeConfig> - Parsed and validated theme configuration\n * @throws ThemeFileError - If file cannot be read or path is invalid\n * @throws ThemeParseError - If JSON is malformed or invalid\n * @throws ThemeValidationError - If theme fails schema validation\n */\nexport async function loadThemeFromFile(\n filePath: string\n): Promise<ThemeConfigJson> {\n return themeLoader.loadFromFile(filePath);\n}\n\n/**\n * Export a theme configuration to JSON string\n * @param theme - Theme configuration to export\n * @param pretty - Whether to format JSON with indentation (default: true)\n * @returns string - Formatted JSON string\n */\nexport function exportThemeToJson(\n theme: ThemeConfigJson,\n pretty: boolean = true\n): string {\n try {\n // Since ThemeConfig is inferred from TypeBox schema, it can be directly serialized\n // The schema ensures all properties are JSON-serializable\n\n if (pretty) {\n return JSON.stringify(theme, null, 2);\n } else {\n return JSON.stringify(theme);\n }\n } catch (error) {\n throw new Error(\n `Failed to export theme to JSON: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Validate a JSON string against the theme schema without parsing\n * @param jsonString - JSON string to validate\n * @returns Validation result with success status and detailed errors\n */\nexport function validateThemeJsonString(jsonString: string) {\n return themeParser.validate(jsonString);\n}\n","/**\n * Main styles module export\n * This file provides a unified interface to the styles system\n */\n\n// Base configurations - imported from TypeBox schemas\nexport type {\n ThemeConfigJson as ThemeConfig,\n StyleDefinitions,\n DocumentMargins,\n PageDimensions,\n Page,\n FontDefinition,\n Fonts,\n ComponentDefaults,\n HeadingComponentDefaults,\n ParagraphComponentDefaults,\n ImageComponentDefaults,\n StatisticComponentDefaults,\n TableComponentDefaults,\n SectionComponentDefaults,\n ColumnsComponentDefaults,\n ListComponentDefaults,\n} from '@json-to-office/shared-docx';\nexport {\n themes,\n getTheme,\n getThemeNames,\n getThemeWithFallback,\n hasTheme,\n isValidThemeName,\n} from '../templates/themes';\n\n// Export ThemeName type separately\nexport type { ThemeName } from '../templates/themes';\n\n// Style utilities\nexport { getBodyTextStyle } from './utils/styleHelpers';\nexport {\n getTableStyle,\n getDocumentMargins,\n getPageSetup,\n getPageDimensions,\n PAGE_SIZES,\n} from './utils/layoutUtils';\n\n// Theme configurations\nexport { minimalTheme, corporateTheme, modernTheme } from '../templates/themes';\n\n// JSON Theme System (Phase 1 - Foundation complete)\nexport {\n ThemeConfigSchema,\n isValidThemeConfig,\n loadThemeFromJson,\n loadThemeFromFile,\n exportThemeToJson,\n validateThemeJsonString,\n ThemeValidationError,\n ThemeParseError,\n ThemeFileError,\n} from '../themes/json';\n\n// Export type separately\nexport type { ThemeConfigJson } from '../themes/json';\n\n// All themes now use the same structure\n// No need for backward compatibility exports\n","import { ThemeConfig } from '../styles';\nimport { getPageSetup } from '../styles';\nimport { pointsToTwips } from '../styles/utils/styleHelpers';\n\n/**\n * Compute available page width in twips (page width minus left/right margins)\n */\nexport function getAvailableWidthTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n const width = page?.size?.width || 0;\n const left = page?.margin?.left || 0;\n const right = page?.margin?.right || 0;\n return Math.max(0, width - left - right);\n}\n\n/**\n * Compute full page width in twips (ignores margins)\n */\nexport function getPageWidthTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n return page?.size?.width || 0;\n}\n\n/**\n * Compute available page height in twips (page height minus top/bottom margins)\n */\nexport function getAvailableHeightTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n const height = page?.size?.height || 0;\n const top = page?.margin?.top || 0;\n const bottom = page?.margin?.bottom || 0;\n return Math.max(0, height - top - bottom);\n}\n\n/**\n * Compute full page height in twips (ignores margins)\n */\nexport function getPageHeightTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n return page?.size?.height || 0;\n}\n\n/**\n * Parse a percentage string like \"75%\" into a fraction 0..1\n */\nexport function parsePercentageStringToFraction(\n value: string\n): number | undefined {\n const match = /^([0-9]+(?:\\.[0-9]+)?)%$/.exec(value);\n if (!match) return undefined;\n const pct = parseFloat(match[1]);\n if (pct < 0 || pct > 100) return undefined;\n return pct / 100;\n}\n\n/**\n * Resolve an offset value (twips or percentage string) to twips.\n * Numbers pass through unchanged; percentage strings are resolved against referenceTwips.\n */\nexport function resolveOffsetTwips(\n value: number | string,\n referenceTwips: number\n): number {\n if (typeof value === 'number') return value;\n const match = /^([0-9]+(?:\\.[0-9]+)?)%$/.exec(value);\n if (!match) {\n console.warn(\n `resolveOffsetTwips: invalid percentage string \"${value}\", defaulting to 0`\n );\n return 0;\n }\n return Math.round((referenceTwips * parseFloat(match[1])) / 100);\n}\n\n/**\n * Convert a numeric (points) or percentage string to twips using available width\n */\nexport function relativeLengthToTwips(\n value: number | string,\n availableWidthTwips: number\n): number {\n if (typeof value === 'number') {\n return pointsToTwips(value);\n }\n const fraction = parsePercentageStringToFraction(value);\n if (fraction === undefined) return 0;\n return Math.round(availableWidthTwips * fraction);\n}\n","import {\n TextWrappingType,\n TextWrappingSide,\n HorizontalPositionRelativeFrom,\n VerticalPositionRelativeFrom,\n HorizontalPositionAlign,\n VerticalPositionAlign,\n} from 'docx';\n\nimport type { ImageProps } from '../types';\nimport type { ThemeConfig } from '../styles';\nimport {\n resolveOffsetTwips,\n getPageWidthTwips,\n getPageHeightTwips,\n getAvailableWidthTwips,\n getAvailableHeightTwips,\n} from './widthUtils';\n\nexport type FloatingConfig = NonNullable<ImageProps['floating']>;\n\n/**\n * Conversion factor from twips to EMUs (English Metric Units).\n * - 1 inch = 914,400 EMUs\n * - 1 inch = 1,440 twips\n * - Therefore: 1 twip = 914,400 / 1,440 = 635 EMUs\n *\n * docx.js expects offset and margin values in EMUs, but our schema\n * documents these values in twips for consistency with other Word measurements.\n */\nconst TWIPS_TO_EMU = 635;\n\nexport function mapHorizontalRelative(\n rel?: FloatingConfig['horizontalPosition'] extends infer T\n ? T extends { relative?: infer R }\n ? R\n : never\n : never\n) {\n switch (rel) {\n case 'character':\n return HorizontalPositionRelativeFrom.CHARACTER;\n case 'column':\n return HorizontalPositionRelativeFrom.COLUMN;\n case 'margin':\n return HorizontalPositionRelativeFrom.MARGIN;\n case 'page':\n return HorizontalPositionRelativeFrom.PAGE;\n default:\n return undefined;\n }\n}\n\nexport function mapVerticalRelative(\n rel?: FloatingConfig['verticalPosition'] extends infer T\n ? T extends { relative?: infer R }\n ? R\n : never\n : never\n) {\n switch (rel) {\n case 'margin':\n return VerticalPositionRelativeFrom.MARGIN;\n case 'page':\n return VerticalPositionRelativeFrom.PAGE;\n case 'paragraph':\n return VerticalPositionRelativeFrom.PARAGRAPH;\n case 'line':\n return VerticalPositionRelativeFrom.LINE;\n default:\n return undefined;\n }\n}\n\nexport function mapHorizontalAlign(\n align?: 'left' | 'center' | 'right' | 'inside' | 'outside'\n) {\n switch (align) {\n case 'left':\n return HorizontalPositionAlign.LEFT;\n case 'center':\n return HorizontalPositionAlign.CENTER;\n case 'right':\n return HorizontalPositionAlign.RIGHT;\n case 'inside':\n return HorizontalPositionAlign.INSIDE;\n case 'outside':\n return HorizontalPositionAlign.OUTSIDE;\n default:\n return undefined;\n }\n}\n\nexport function mapVerticalAlign(\n align?: 'top' | 'center' | 'bottom' | 'inside' | 'outside'\n) {\n switch (align) {\n case 'top':\n return VerticalPositionAlign.TOP;\n case 'center':\n return VerticalPositionAlign.CENTER;\n case 'bottom':\n return VerticalPositionAlign.BOTTOM;\n case 'inside':\n return VerticalPositionAlign.INSIDE;\n case 'outside':\n return VerticalPositionAlign.OUTSIDE;\n default:\n return undefined;\n }\n}\n\nexport function mapWrapType(\n type?: 'none' | 'square' | 'topAndBottom' | 'around' | 'through'\n) {\n switch (type) {\n case 'none':\n return TextWrappingType.NONE;\n case 'square':\n return TextWrappingType.SQUARE;\n case 'topAndBottom':\n return TextWrappingType.TOP_AND_BOTTOM;\n case 'around':\n case 'through':\n // Map VML-style 'around' and 'through' to TIGHT (closest OOXML equivalent)\n return TextWrappingType.TIGHT;\n default:\n return undefined;\n }\n}\n\nexport function mapWrapSide(side?: 'bothSides' | 'left' | 'right' | 'largest') {\n switch (side) {\n case 'bothSides':\n return TextWrappingSide.BOTH_SIDES;\n case 'left':\n return TextWrappingSide.LEFT;\n case 'right':\n return TextWrappingSide.RIGHT;\n case 'largest':\n return TextWrappingSide.LARGEST;\n default:\n return undefined;\n }\n}\n\n/**\n * Map shared floating config to docx ImageRun floating options.\n * Also lifts wrap.margins (if present) to floating.margins as expected by docx.\n */\nexport function mapFloatingOptions(\n floating?: FloatingConfig,\n theme?: ThemeConfig,\n themeName?: string\n): any | undefined {\n if (!floating) return undefined;\n\n // Disallow 'tight' wrapping: docx emits invalid OOXML for wrapTight without polygon geometry\n // Note: TypeScript correctly prevents this at compile-time, but keep for runtime safety\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore - Intentional defensive check for runtime input validation\n if (floating.wrap?.type === 'tight') {\n throw new Error(\n \"Image floating wrap.type 'tight' is not supported due to invalid OOXML emitted by docx. Use 'square', 'topAndBottom', or 'none'.\"\n );\n }\n\n // Determine reference dimensions for percentage resolution\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n const hRef =\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(theme, themeName)\n : getPageWidthTwips(theme, themeName);\n const vRef =\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(theme, themeName)\n : getPageHeightTwips(theme, themeName);\n\n // docx.js requires BOTH horizontal and vertical positions for floating images.\n // If only one is specified, provide sensible defaults for the other.\n const hasHorizontal = Boolean(floating.horizontalPosition);\n const hasVertical = Boolean(floating.verticalPosition);\n\n const horizontalPosition = floating.horizontalPosition\n ? {\n ...(floating.horizontalPosition.relative && {\n relative: mapHorizontalRelative(floating.horizontalPosition.relative),\n }),\n ...(floating.horizontalPosition.align !== undefined && {\n align: mapHorizontalAlign(floating.horizontalPosition.align),\n }),\n ...(floating.horizontalPosition.offset !== undefined && {\n offset:\n resolveOffsetTwips(floating.horizontalPosition.offset, hRef) *\n TWIPS_TO_EMU,\n }),\n }\n : hasVertical\n ? {\n // Default horizontal: align left relative to margin\n relative: HorizontalPositionRelativeFrom.MARGIN,\n align: HorizontalPositionAlign.LEFT,\n }\n : undefined;\n\n const verticalPosition = floating.verticalPosition\n ? {\n ...(floating.verticalPosition.relative && {\n relative: mapVerticalRelative(floating.verticalPosition.relative),\n }),\n ...(floating.verticalPosition.align !== undefined && {\n align: mapVerticalAlign(floating.verticalPosition.align),\n }),\n ...(floating.verticalPosition.offset !== undefined && {\n offset:\n resolveOffsetTwips(floating.verticalPosition.offset, vRef) *\n TWIPS_TO_EMU,\n }),\n }\n : hasHorizontal\n ? {\n // Default vertical: align top relative to paragraph\n relative: VerticalPositionRelativeFrom.PARAGRAPH,\n align: VerticalPositionAlign.TOP,\n }\n : undefined;\n\n const wrap = floating.wrap\n ? {\n ...(floating.wrap.type && { type: mapWrapType(floating.wrap.type) }),\n ...(floating.wrap.side && { side: mapWrapSide(floating.wrap.side) }),\n }\n : undefined;\n\n // Convert margins from twips (or percentage) to EMUs\n const pageW = getPageWidthTwips(theme, themeName);\n const pageH = getPageHeightTwips(theme, themeName);\n const rawMargins = floating.wrap?.margins || (floating as any).margins;\n const margins = rawMargins\n ? {\n ...(rawMargins.top !== undefined && {\n top: resolveOffsetTwips(rawMargins.top, pageH) * TWIPS_TO_EMU,\n }),\n ...(rawMargins.bottom !== undefined && {\n bottom: resolveOffsetTwips(rawMargins.bottom, pageH) * TWIPS_TO_EMU,\n }),\n ...(rawMargins.left !== undefined && {\n left: resolveOffsetTwips(rawMargins.left, pageW) * TWIPS_TO_EMU,\n }),\n ...(rawMargins.right !== undefined && {\n right: resolveOffsetTwips(rawMargins.right, pageW) * TWIPS_TO_EMU,\n }),\n }\n : undefined;\n\n // Determine and validate zIndex:\n // - OOXML requires positive integer for relativeHeight\n // - Negative values cause Word to reject the document\n // - CRITICAL: docx.js uses image HEIGHT as relativeHeight when zIndex is undefined,\n // causing inconsistent values that can corrupt documents\n // - Solution: ALWAYS provide a zIndex value, defaulting to 0\n let zIndex = floating.zIndex !== undefined ? floating.zIndex : 0; // Default to 0 for ALL floating images (behindDocument or normal)\n\n // Validate: zIndex must be >= 0 (OOXML requirement)\n if (zIndex < 0) {\n console.warn(\n `Invalid zIndex value ${zIndex} for floating image. Using 0 instead. zIndex must be >= 0.`\n );\n zIndex = 0;\n }\n\n const mapped: any = {\n ...(horizontalPosition && { horizontalPosition }),\n ...(verticalPosition && { verticalPosition }),\n ...(wrap && { wrap }),\n ...(margins && { margins }),\n ...(floating.allowOverlap !== undefined && {\n allowOverlap: floating.allowOverlap,\n }),\n ...(floating.behindDocument !== undefined && {\n behindDocument: floating.behindDocument,\n }),\n ...(floating.lockAnchor !== undefined && {\n lockAnchor: floating.lockAnchor,\n }),\n ...(floating.layoutInCell !== undefined && {\n layoutInCell: floating.layoutInCell,\n }),\n zIndex, // Always include zIndex (now always defined, defaults to 0)\n };\n\n return Object.keys(mapped).length ? mapped : undefined;\n}\n","/**\n * Document Generator\n * Main orchestration functions that compose the document generation pipeline\n */\n\nimport { Document } from 'docx';\nimport { writeFileSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport {\n ComponentDefinition,\n ReportProps,\n ReportComponentDefinition,\n isReportComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { resolveThemeContext } from './generationContext';\nimport type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';\nimport { processDocument } from './structure';\nimport { applyLayout } from './layout';\nimport { renderDocument } from './render';\nimport { resolveDocumentFonts } from './fontResolution';\nimport { collectVisualProps } from './prerasterizeVisuals';\nimport { toRasterizeFontFaces } from '@json-to-office/shared/fonts/node';\nimport {\n packageDocument,\n resolveGenerationDate,\n} from '../utils/packageDocument';\n\n// JSON support imports\nimport { DocumentValidationResult } from '@json-to-office/shared-docx';\nimport type { GenerationWarning } from '@json-to-office/shared';\nimport {\n validateJsonComponent,\n JsonParsingError,\n JsonValidationError,\n} from '../json/parser';\nimport { normalizeDocument } from '../json/normalizer';\nimport { loadJsonDefinition } from '../json/filesystem';\n\n// Local generation options type\nexport interface JsonGenerationOptions {\n outputPath?: string;\n validation?: {\n /**\n * Validate the document against the schema before building, throwing on\n * errors. Defaults to `true` — invalid props are surfaced rather than\n * silently dropped into a corrupt/incomplete document.\n */\n enabled?: boolean;\n /**\n * When true, unknown/extra properties are stripped instead of rejected by\n * strict (additionalProperties:false) schemas. Escape hatch for migration.\n */\n allowUnknownFields?: boolean;\n /** @deprecated No longer consulted; retained for back-compat. */\n strict?: boolean;\n };\n customThemes?: { [key: string]: ThemeConfig };\n services?: ServicesConfig;\n fonts?: FontRuntimeOpts;\n /**\n * Optional collector for structured warnings (font resolution, etc.).\n * When provided, mirrors the plugin path's warning semantics; when absent,\n * warnings fall back to `console.warn` as before.\n */\n warnings?: GenerationWarning[];\n /** Normalize volatile OOXML values for byte-identical output. Defaults true. */\n deterministic?: boolean;\n /** Build timestamp for metadata; defaults to a stable epoch. */\n generatedAt?: string | Date;\n /**\n * Directory that relative asset paths (image `path` props) resolve against.\n * File entry points default it to the document's own directory; elsewhere\n * it falls back to `process.cwd()` (#142).\n */\n baseDir?: string;\n}\n\n// Font resolution shared with the plugin path — see ./fontResolution.ts\n\n/**\n * Type guard to check if input is a report component definition\n */\nexport function isReportComponentDefinition(\n definition: unknown\n): definition is ReportComponentDefinition {\n if (typeof definition !== 'object' || definition === null) {\n return false;\n }\n\n const def = definition as Record<string, unknown>;\n\n // Must be a report component (optionally with $schema for JSON validation).\n // `props` is optional: a propless root generates like one with `props: {}`.\n return def.name === 'docx';\n}\n\n/**\n * Generate a Word document from a report component definition\n * This is the main entry point for document generation\n */\nexport async function generateDocument(\n document: ReportComponentDefinition,\n options?: JsonGenerationOptions\n): Promise<Document> {\n // Validate that the document is a report component\n if (!document || document.name !== 'docx') {\n throw new Error('Top-level component must be a docx component');\n }\n\n // Handle JSON definitions (report components with $schema)\n if ('$schema' in document) {\n return await generateDocumentFromJson(document, options);\n }\n\n // Route through the font-aware pipeline so `options.fonts` (mode,\n // substitution, onResolved, strict) is honoured identically to the JSON\n // entry point. Previously this branch bypassed export-mode + font\n // resolution, silently ignoring `fonts.mode: 'substitute'`.\n return await generateDocumentWithCustomThemes(\n document,\n options?.customThemes,\n options?.services,\n options?.fonts,\n options?.warnings,\n resolveGenerationDate(options),\n options?.baseDir\n );\n}\n\n/**\n * Generate document from report props and components\n * Convenience function that constructs the report component\n */\nexport async function generateFromConfig(\n props: ReportProps,\n components: ComponentDefinition[],\n options?: JsonGenerationOptions\n): Promise<Document> {\n const reportComponent: ReportComponentDefinition = {\n name: 'docx',\n props,\n children: components,\n };\n\n return await generateDocument(reportComponent, options);\n}\n\n/**\n * Generate a Word document with custom themes support\n * Extends the standard pipeline to support custom theme resolution\n */\nasync function generateDocumentWithCustomThemes(\n documentIn: ReportComponentDefinition,\n customThemes?: { [key: string]: ThemeConfig },\n services?: ServicesConfig,\n fonts?: FontRuntimeOpts,\n warnings?: GenerationWarning[],\n generationDate?: Date,\n baseDir?: string\n): Promise<Document> {\n // Props defaulting, theme resolution, in-document overrides, export-mode\n // pre-pass and cache-key scoping — shared with the plugin pipeline so the\n // two cannot drift (see core/generationContext.ts).\n const { document, theme, themeName } = resolveThemeContext(documentIn, {\n customThemes,\n fonts,\n warnings,\n });\n\n // Resolve fonts for the LibreOffice preview stager (side-channel).\n // resolveDocumentFonts fires `fonts.onResolved` internally when a\n // listener is registered. The final DOCX never embeds bytes.\n //\n // A `visual` is rasterized by an out-of-process LibreOffice, which needs\n // the real font files, so a visual-bearing document forces materialization\n // even with no listener (the plain CLI path has none). Gated on the visual\n // check so fontless-by-design builds still pay no network cost.\n const hasVisual = collectVisualProps(document).length > 0;\n const resolvedFonts = await resolveDocumentFonts(\n document,\n theme,\n fonts,\n warnings,\n hasVisual\n );\n // Gate on the ENCODED faces, not on `resolvedFonts.length`: a safe-only\n // font resolves to an entry with no sources, which encodes to nothing. A\n // document with only safe fonts must send no `fonts` key at all so its\n // rasterize body — and therefore its cache key — is unchanged.\n const visualFonts = hasVisual\n ? toRasterizeFontFaces(resolvedFonts, warnings)\n : [];\n\n // Pipeline: Structure -> Layout -> Render (with caching)\n const structure = await processDocument(\n document,\n theme,\n themeName,\n generationDate\n );\n const layout = applyLayout(structure.sections, theme, themeName);\n const renderedDocument = await renderDocument(structure, layout, {\n bypassCache: false,\n services,\n baseDir,\n warnings,\n ...(visualFonts.length > 0 && { visualFonts }),\n });\n\n return renderedDocument;\n}\n\n/**\n * Generate a Word document from JSON report definition\n * Handles parsing, validation, and conversion to internal components\n */\nexport async function generateDocumentFromJson(\n jsonConfig: string | ComponentDefinition | ReportComponentDefinition,\n options?: JsonGenerationOptions\n): Promise<Document> {\n // Validate before building unless the caller opted out. This runs the same\n // plugin-unaware validator the public playground uses, so the object/buffer\n // entry point is as strict as the playground — malformed props throw instead\n // of being silently dropped into the document.\n const validation = options?.validation;\n if (validation?.enabled !== false) {\n const result = validateJsonComponent(jsonConfig, {\n allowUnknownFields: validation?.allowUnknownFields,\n });\n if (!result.valid) {\n throw new JsonValidationError(\n 'Document validation failed',\n result.errors\n );\n }\n }\n\n // Resolve to an object for the build pipeline.\n let componentToConvert: ComponentDefinition | ReportComponentDefinition;\n if (typeof jsonConfig === 'string') {\n let parsed: ComponentDefinition;\n try {\n parsed = JSON.parse(jsonConfig) as ComponentDefinition;\n } catch (error) {\n throw new JsonParsingError('Invalid JSON syntax', [\n {\n path: '',\n message: error instanceof Error ? error.message : 'Invalid JSON',\n code: 'JSON_PARSE_ERROR',\n },\n ]);\n }\n if (!isReportComponent(parsed)) {\n throw new Error('Parsed JSON must be a docx component');\n }\n componentToConvert = parsed as ReportComponentDefinition;\n } else {\n // Could be either ComponentDefinition (from JSON) or ReportComponentDefinition (internal)\n componentToConvert = jsonConfig;\n }\n\n // Normalize JSON components (handle shorthand notations and nested structures)\n // The normalizer preserves all validated properties from TypeBox\n const [reportComponent] = normalizeDocument(componentToConvert);\n\n // Generate document using custom theme-aware pipeline.\n // Font registry lives on the theme, so resolution happens inside the\n // pipeline (after theme selection).\n return await generateDocumentWithCustomThemes(\n reportComponent,\n options?.customThemes,\n options?.services,\n options?.fonts,\n options?.warnings,\n resolveGenerationDate(options),\n options?.baseDir\n );\n}\n\n/**\n * Validate JSON schema without generating document\n */\nexport function validateJsonSchema(\n jsonConfig: string | object\n): DocumentValidationResult {\n return validateJsonComponent(jsonConfig);\n}\n\n/**\n * Generate document buffer from JSON (commonly used for API responses)\n */\nexport async function generateBufferFromJson(\n jsonConfig: string | ReportComponentDefinition,\n options?: JsonGenerationOptions\n): Promise<Buffer> {\n const document = await generateDocumentFromJson(jsonConfig, options);\n return packageDocument(document, options);\n}\n\n/**\n * Generate and save document from JSON in one operation\n */\nexport async function generateAndSaveFromJson(\n jsonConfig: string | ReportComponentDefinition,\n filename: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n const document = await generateDocumentFromJson(jsonConfig, options);\n await saveDocument(document, filename, options);\n}\n\n/**\n * Generate document from JSON file\n */\nexport async function generateDocumentFromFile(\n filePath: string,\n options?: JsonGenerationOptions\n): Promise<Document> {\n const jsonDefinition = await loadJsonDefinition(filePath);\n // loadJsonDefinition returns ComponentDefinition from shared (JSON schema type)\n // generateDocumentFromJson now accepts the JSON schema type directly\n // The document's own directory is the natural base for its relative assets.\n return await generateDocumentFromJson(jsonDefinition, {\n baseDir: dirname(resolve(filePath)),\n ...options,\n });\n}\n\n/**\n * Generate document buffer from JSON file\n */\nexport async function generateBufferFromFile(\n filePath: string,\n options?: JsonGenerationOptions\n): Promise<Buffer> {\n const document = await generateDocumentFromFile(filePath, options);\n return packageDocument(document, options);\n}\n\n/**\n * Generate and save document from JSON file in one operation\n */\nexport async function generateAndSaveFromFile(\n inputFilePath: string,\n outputFilePath: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n const document = await generateDocumentFromFile(inputFilePath, options);\n await saveDocument(document, outputFilePath, options);\n}\n\n/**\n * Save a document to file\n */\nexport async function saveDocument(\n document: Document,\n filename: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n const buffer = await packageDocument(document, options);\n writeFileSync(filename, buffer);\n}\n\n/**\n * Generate and save document in one operation\n */\nexport async function generateAndSave(\n document: ReportComponentDefinition,\n filename: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n const generatedDocument = await generateDocument(document, options);\n await saveDocument(generatedDocument, filename, options);\n}\n\n/**\n * Compose multiple transform functions\n * Utility for creating custom pipelines\n */\nexport function pipe<T>(...fns: Array<(_arg: T) => T>): (_arg: T) => T {\n return (_arg: T) => fns.reduce((acc, fn) => fn(acc), _arg);\n}\n\n/**\n * Export the main API\n */\nexport const DocumentGenerator = {\n generate: generateDocument,\n generateFromConfig,\n generateFromJson: generateDocumentFromJson,\n generateFromFile: generateDocumentFromFile,\n generateBufferFromJson,\n generateBufferFromFile,\n generateAndSaveFromJson,\n generateAndSaveFromFile,\n validateJsonSchema,\n save: saveDocument,\n generateAndSave,\n isReportComponentDefinition,\n};\n","import { ISectionOptions } from 'docx';\nimport type { ThemeName } from '../styles';\nimport type { TocHeadingEntry } from '../core/collectTocHeadings';\nimport type {\n ServicesConfig,\n PptxRasterizeBatchSlideResult,\n RasterizeFontFace,\n} from '@json-to-office/shared';\n\n// Import types from shared-docx that core needs for its internal use\nimport type {\n ComponentDefinition as SharedComponentDefinition,\n ReportComponent,\n SectionComponent,\n ColumnsComponent,\n HeadingComponent,\n ParagraphComponent,\n ImageComponent,\n HighchartsComponent,\n VisualComponent,\n StatisticComponent,\n TableComponent,\n ListComponent,\n TocComponent,\n TextBoxComponent,\n\n // Import props types needed internally\n ReportProps as SharedReportProps,\n SectionProps as SharedSectionProps,\n HeadingProps as SharedHeadingProps,\n ParagraphProps as SharedParagraphProps,\n ColumnsProps as SharedColumnsProps,\n ImageProps as SharedImageProps,\n VisualProps as SharedVisualProps,\n StatisticProps as SharedStatisticProps,\n TableProps as SharedTableProps,\n ListProps as SharedListProps,\n TocProps as SharedTocProps,\n TextBoxProps as SharedTextBoxProps,\n} from '@json-to-office/shared-docx';\n\n// Import type guards from shared-docx (these are runtime functions core needs)\nexport {\n isReportComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isColumnsComponent,\n isImageComponent,\n isTextBoxComponent,\n isStatisticComponent,\n isTableComponent,\n isListComponent,\n isTocComponent,\n isHighchartsComponent,\n isVisualComponent,\n} from '@json-to-office/shared-docx';\n\n// Re-export component definitions for internal use (type aliases for clarity)\nexport type ComponentDefinition = SharedComponentDefinition;\nexport type ReportComponentDefinition = ReportComponent & {\n /** Optional schema field for JSON validation */\n $schema?: string;\n};\nexport type SectionComponentDefinition = SectionComponent;\nexport type HeadingComponentDefinition = HeadingComponent;\nexport type ParagraphComponentDefinition = ParagraphComponent;\nexport type ColumnsComponentDefinition = ColumnsComponent;\nexport type ImageComponentDefinition = ImageComponent;\nexport type VisualComponentDefinition = VisualComponent;\nexport type TextBoxComponentDefinition = TextBoxComponent;\nexport type StatisticComponentDefinition = StatisticComponent;\nexport type TableComponentDefinition = TableComponent;\nexport type ListComponentDefinition = ListComponent;\nexport type TocComponentDefinition = TocComponent;\n\n// Export StandardComponentDefinition as union of all standard component types\nexport type StandardComponentDefinition =\n | ReportComponent\n | SectionComponent\n | ColumnsComponent\n | HeadingComponent\n | ParagraphComponent\n | TextBoxComponent\n | ImageComponent\n | HighchartsComponent\n | VisualComponent\n | StatisticComponent\n | TableComponent\n | ListComponent\n | TocComponent;\n\n// Re-export props types for internal use\nexport type ReportProps = SharedReportProps;\nexport type SectionProps = SharedSectionProps;\nexport type HeadingProps = SharedHeadingProps;\nexport type ParagraphProps = SharedParagraphProps;\nexport type ColumnsProps = SharedColumnsProps;\nexport type ImageProps = SharedImageProps;\nexport type VisualProps = SharedVisualProps;\nexport type TextBoxProps = SharedTextBoxProps;\nexport type StatisticProps = SharedStatisticProps;\nexport type TableProps = SharedTableProps;\nexport type ListProps = SharedListProps;\nexport type TocProps = SharedTocProps;\n\n// Re-export ThemeName for easier access\nexport type { ThemeName };\n\n// ============================================================================\n// CORE-SPECIFIC INTERFACES\n// ============================================================================\n\nexport interface ColumnSettings {\n count: number;\n equalWidth?: boolean;\n space?: number;\n /** Optional explicit column children with widths/spaces in twips */\n children?: { width?: number; space?: number }[];\n}\n\nexport interface PageSizeOptions {\n width: number;\n height: number;\n}\n\nexport interface PageMarginOptions {\n top: number;\n right: number;\n bottom: number;\n left: number;\n header?: number;\n footer?: number;\n}\n\nexport interface PageNumberOptions {\n start?: number;\n formatType?:\n | 'decimal'\n | 'upperRoman'\n | 'lowerRoman'\n | 'upperLetter'\n | 'lowerLetter';\n}\n\nexport interface PageBorderOptions {\n top?: { style: string; size: number; color: string };\n right?: { style: string; size: number; color: string };\n bottom?: { style: string; size: number; color: string };\n left?: { style: string; size: number; color: string };\n}\n\nexport interface SectionProperties {\n page?: {\n size?: PageSizeOptions;\n margin?: PageMarginOptions;\n pageNumbers?: PageNumberOptions;\n borders?: PageBorderOptions;\n textDirection?: 'ltr' | 'rtl';\n };\n column?: ColumnSettings;\n type?: 'continuous' | 'nextColumn' | 'nextPage' | 'evenPage' | 'oddPage';\n headers?: ISectionOptions['headers'];\n footers?: ISectionOptions['footers'];\n}\n\n// Internal interfaces used by DocumentGenerator helper methods\nexport interface ImageContent {\n path: string;\n caption?: string;\n width?: number;\n height?: number;\n alignment?: 'left' | 'center' | 'right';\n}\n\nexport interface StatisticContent {\n number: string;\n description: string;\n alignment?: 'left' | 'center' | 'right';\n}\n\nexport interface TableData {\n headers: string[];\n rows: (string | SharedComponentDefinition)[][];\n style?: 'minimal' | 'classic' | 'minimal';\n}\n\n/**\n * Rendering context for components\n */\nexport interface RenderContext {\n theme: {\n name: string;\n colors: Record<string, string>;\n fonts: Record<string, string>;\n spacing: Record<string, number>;\n };\n /** Full theme configuration for custom components */\n fullTheme: import('../styles').ThemeConfig;\n document: {\n title?: string;\n subtitle?: string;\n author?: string;\n company?: string;\n date: Date;\n };\n section: {\n currentLayout: 'single' | 'multi-column';\n columnCount: number;\n pageNumber: number;\n level?: number;\n /** Bookmark ID for section-scoped TOCs (when TOC is inside a section) */\n sectionBookmarkId?: string;\n };\n utils: {\n formatDate: (_date: Date) => string;\n parseText: (_text: string) => { text: string }[];\n getStyle: (_name: string) => { name: string };\n [key: string]: unknown;\n };\n parent?: SharedComponentDefinition;\n depth: number;\n custom?: Record<string, unknown>;\n services?: ServicesConfig;\n /**\n * Per-document pre-rasterized visual results, keyed by `visualRasterKey`\n * (#153). Seeded by the renderDocument pre-pass; `renderVisualComponent`\n * consults it first and falls back to per-visual rasterization on a miss.\n */\n visualRasterResults?: ReadonlyMap<string, PptxRasterizeBatchSlideResult>;\n /**\n * Per-document font faces (base64) forwarded to the pptx rasterizer with\n * every `visual`. Seeded by renderDocument from the caller's\n * `visualFonts`; consumed by `renderVisualComponent`'s per-visual\n * fallback so a pre-pass miss still rasterizes with the right fonts.\n */\n visualFonts?: readonly RasterizeFontFace[];\n /**\n * Per-document TOC entries collected before rendering (#174). Seeded by the\n * renderDocument pre-pass; `renderTocComponent` filters them by depth, scope\n * and style mapping and passes them to docx as `cachedEntries`, so a TOC\n * field has real content for readers that do not refresh fields.\n */\n tocHeadings?: readonly TocHeadingEntry[];\n}\n","/**\n * Shared generation prologue.\n *\n * Both entry points — `generateBufferFromJson` (core) and\n * `createDocumentGenerator` (plugin) — must resolve the same theme, apply the\n * same in-document overrides, and derive the same cache key before the\n * structure → layout → render engine runs. Keeping two copies of that meant\n * `props.themeOverrides` reached only one of them (#133); this module is the\n * single definition so the next root-level prop cannot diverge (#132).\n *\n * The prologue deliberately stops before font resolution: the core path\n * resolves fonts straight after this, while the plugin path must first expand\n * custom components (which can introduce new families).\n */\n\nimport type { ReportComponentDefinition } from '../types';\nimport type { ThemeConfig } from '../styles';\nimport type {\n FontRuntimeOpts,\n GenerationWarning,\n} from '@json-to-office/shared';\nimport { applyExportMode, scopedThemeName } from '@json-to-office/shared';\nimport { resolveBuiltInTheme } from '../styles/theme-resolver';\nimport { applyThemeOverrides, themeOverridesDigest } from '../themes/overrides';\n\nexport interface ThemeContextOptions {\n customThemes?: { [key: string]: ThemeConfig };\n fonts?: FontRuntimeOpts;\n warnings?: GenerationWarning[];\n /**\n * Theme lookup for the base `props.theme` name. The plugin builder passes\n * its own (customThemes → doc-named built-in → constructor-supplied theme →\n * built-in); omit it to use customThemes → built-in. `authored` is true when\n * the name came from the document's own `props.theme` (not the 'minimal'\n * fallback), so the lookup can honor an explicitly doc-named built-in\n * without the constructor theme being shadowed for unnamed docs (#141).\n */\n resolveNamedTheme?: (\n name: string,\n warnings: GenerationWarning[] | undefined,\n authored: boolean\n ) => ThemeConfig;\n}\n\nexport interface GenerationThemeContext {\n /** The document after the export-mode pre-pass rewrote font references. */\n document: ReportComponentDefinition;\n theme: ThemeConfig;\n /** Cache key: base theme name + override digest + export-mode scope. */\n themeName: string;\n}\n\n/** customThemes lookup with the case-insensitive fallback, then built-ins. */\nfunction defaultNamedThemeLookup(\n themeName: string,\n customThemes: { [key: string]: ThemeConfig } | undefined,\n warnings?: GenerationWarning[]\n): ThemeConfig {\n if (customThemes) {\n if (customThemes[themeName]) return customThemes[themeName];\n const themeNameLower = themeName.toLowerCase();\n const matchingThemeKey = Object.keys(customThemes).find(\n (key) => key.toLowerCase() === themeNameLower\n );\n if (matchingThemeKey) return customThemes[matchingThemeKey];\n return resolveBuiltInTheme(themeName, { customThemes, warnings });\n }\n return resolveBuiltInTheme(themeName, { warnings });\n}\n\nexport function resolveThemeContext(\n documentIn: ReportComponentDefinition,\n options: ThemeContextOptions = {}\n): GenerationThemeContext {\n const { customThemes, fonts, warnings, resolveNamedTheme } = options;\n\n // A root written without a `props` key validates clean, so default it here —\n // otherwise every downstream `document.props.*` read (theme, componentDefaults,\n // noProofWords, trackRevisions, language, metadata) throws. Only `undefined`\n // is defaulted: `props: null` is malformed and must be rejected rather than\n // quietly rewritten into a valid shape.\n //\n // Both JSON entry points validate before reaching here, so null is already\n // a validation error there. `generateDocument` on a document without\n // `$schema` runs no validator at all, and used to surface this as\n // `Cannot read properties of null` from the theme read below.\n if (documentIn.props === null) {\n throw new Error(\n 'Document `props` is null. Omit it, or provide an object — ' +\n 'a null props cannot carry a theme.'\n );\n }\n const document =\n documentIn.props === undefined ? { ...documentIn, props: {} } : documentIn;\n\n const authoredThemeName = document.props.theme || undefined;\n const baseThemeName = authoredThemeName ?? 'minimal';\n let theme = resolveNamedTheme\n ? resolveNamedTheme(\n baseThemeName,\n warnings,\n authoredThemeName !== undefined\n )\n : defaultNamedThemeLookup(baseThemeName, customThemes, warnings);\n\n // In-document partial theme, merged before the export-mode pre-pass so a\n // font-family override is visible to it. The digest joins the cache key so\n // two documents sharing a theme name but not overrides never share slots.\n const themeOverrides = document.props.themeOverrides;\n let themeName = baseThemeName;\n if (themeOverrides) {\n theme = applyThemeOverrides(theme, themeOverrides);\n themeName = `${themeName}+ov:${themeOverridesDigest(themeOverrides)}`;\n }\n\n // Export-mode pre-pass: substitute (default) rewrites non-safe families to\n // safe equivalents; custom keeps refs as-is.\n const mode = applyExportMode({ doc: document, theme, fonts });\n for (const w of mode.warnings) {\n if (warnings) {\n warnings.push({\n component: 'fontRegistry',\n message: w.message,\n severity: 'warning',\n context: { code: w.code },\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] [${w.code}] ${w.message}`);\n }\n }\n\n return {\n document: mode.doc,\n theme: mode.theme,\n // Scope by mode too: substitute rewrites the theme in place, so caches\n // must not share slots with custom-mode runs keyed on the same name.\n themeName: scopedThemeName(themeName, fonts?.mode),\n };\n}\n","import type { GenerationWarning } from '@json-to-office/shared';\nimport type { ThemeConfig } from './index';\nimport {\n getThemeNames,\n getThemeWithFallback,\n hasTheme,\n} from '../templates/themes';\n\n/**\n * Resolve a built-in theme by name, reporting a miss instead of swallowing it.\n *\n * `getThemeWithFallback` renders an unknown name as `minimal`, which used to be\n * invisible: a typo, or a `--theme-path` file whose internal `name` differs\n * from its filename, produced a plausible-looking document styled by the wrong\n * theme. The fallback is kept — a bad name should not fail a render — but it\n * now surfaces as a warning naming what was asked for and what is available.\n */\nexport function resolveBuiltInTheme(\n themeName: string,\n options: {\n customThemes?: { [key: string]: ThemeConfig };\n warnings?: GenerationWarning[];\n } = {}\n): ThemeConfig {\n if (!hasTheme(themeName)) {\n const available = [\n ...getThemeNames(),\n ...Object.keys(options.customThemes ?? {}),\n ].sort();\n options.warnings?.push({\n component: 'theme',\n message: `Theme \"${themeName}\" not found; falling back to \"minimal\". Available themes: ${available.join(', ')}.`,\n severity: 'warning',\n context: { code: 'theme_not_found', requested: themeName, available },\n });\n }\n\n return getThemeWithFallback(themeName);\n}\n","/**\n * In-document theme overrides: a partial theme from the document root's\n * `themeOverrides` prop, deep-merged over the resolved named theme.\n */\n\nimport { createHash } from 'crypto';\nimport type { ThemeConfig } from '../styles';\n\nexport interface ThemeOverrides {\n colors?: Partial<ThemeConfig['colors']>;\n fonts?: Partial<ThemeConfig['fonts']>;\n styles?: ThemeConfig['styles'];\n}\n\n/**\n * Merge a partial override object over a resolved theme.\n *\n * - `colors`: per-token replacement.\n * - `fonts`: per-role merge (an override role only replaces the fields it\n * sets, so `{ heading: { family: \"Geist\" } }` keeps the theme's size).\n * - `styles`: per-style merge, one level deep — nested objects inside a style\n * (spacing, lineSpacing, borders, indent) are replaced wholesale.\n */\nexport function applyThemeOverrides(\n theme: ThemeConfig,\n overrides: ThemeOverrides | undefined\n): ThemeConfig {\n if (!overrides) return theme;\n\n const fonts = { ...theme.fonts };\n for (const [role, def] of Object.entries(overrides.fonts ?? {})) {\n const key = role as keyof ThemeConfig['fonts'];\n fonts[key] = { ...theme.fonts[key], ...def };\n }\n\n const styles: Record<string, object> = { ...(theme.styles ?? {}) };\n for (const [name, def] of Object.entries(overrides.styles ?? {})) {\n styles[name] = { ...styles[name], ...(def as object) };\n }\n\n return {\n ...theme,\n colors: { ...theme.colors, ...(overrides.colors ?? {}) },\n fonts,\n ...(Object.keys(styles).length > 0 && { styles }),\n };\n}\n\n/** Short stable digest used to scope theme-keyed caches per override set. */\nexport function themeOverridesDigest(overrides: ThemeOverrides): string {\n return createHash('sha256')\n .update(JSON.stringify(overrides))\n .digest('hex')\n .slice(0, 8);\n}\n","import { format } from 'date-fns';\n\nexport const formatDate = (\n date: Date,\n formatString: string = 'MMMM d, yyyy'\n): string => {\n return format(date, formatString);\n};\n","/**\n * Component Default Resolution System\n * Provides theme-based default configurations for components\n */\n\nimport {\n ThemeConfig,\n ComponentDefaults,\n HeadingComponentDefaults,\n ParagraphComponentDefaults,\n ImageComponentDefaults,\n StatisticComponentDefaults,\n TableComponentDefaults,\n SectionComponentDefaults,\n ColumnsComponentDefaults,\n ListComponentDefaults,\n} from '../index';\nimport {\n HeadingProps,\n ParagraphProps,\n ImageProps,\n StatisticProps,\n TableProps,\n SectionProps,\n ColumnsProps,\n ListProps,\n} from '../../types';\nimport { mergeWithDefaults } from '@json-to-office/shared';\n\n/**\n * Get component defaults from theme configuration\n */\nexport function getComponentDefaults(theme: ThemeConfig): ComponentDefaults {\n return theme.componentDefaults || {};\n}\n\n/**\n * Get default configuration for heading components\n */\nexport function getHeadingDefaults(\n theme: ThemeConfig\n): HeadingComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.heading || {};\n}\n\n/**\n * Get level-specific heading defaults from theme styles\n */\nexport function getHeadingDefaultsForLevel(\n theme: ThemeConfig,\n level: number\n): Partial<HeadingComponentDefaults> {\n const defaults: Partial<HeadingComponentDefaults> = {};\n\n // Check styles for level-specific alignment\n if (theme.styles) {\n const styleKey = `heading${level}` as\n | 'heading1'\n | 'heading2'\n | 'heading3'\n | 'heading4'\n | 'heading5'\n | 'heading6';\n const headingStyle = theme.styles[styleKey];\n\n if (headingStyle?.alignment) {\n defaults.alignment = headingStyle.alignment;\n }\n }\n\n return defaults;\n}\n\n/**\n * Get default configuration for text components\n */\nexport function getTextDefaults(\n theme: ThemeConfig\n): ParagraphComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.paragraph || {};\n}\n\n/**\n * Get default configuration for image components\n */\nexport function getImageDefaults(theme: ThemeConfig): ImageComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.image || {};\n}\n\n/**\n * Get default configuration for statistic components\n */\nexport function getStatisticDefaults(\n theme: ThemeConfig\n): StatisticComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.statistic || {};\n}\n\n/**\n * Get default configuration for table components\n */\nexport function getTableDefaults(theme: ThemeConfig): TableComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.table || {};\n}\n\n/**\n * Get default configuration for section components\n */\nexport function getSectionDefaults(\n theme: ThemeConfig\n): SectionComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.section || {};\n}\n\n/**\n * Get default configuration for columns components\n */\nexport function getColumnsDefaults(\n theme: ThemeConfig\n): ColumnsComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.columns || {};\n}\n\n/**\n * Get default configuration for list components\n */\nexport function getListDefaults(theme: ThemeConfig): ListComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.list || {};\n}\n\n// mergeWithDefaults is re-exported from @json-to-office/shared\nexport { mergeWithDefaults } from '@json-to-office/shared';\n\n/**\n * Resolve heading component props with theme defaults\n */\nexport function resolveHeadingProps(\n props: HeadingProps,\n theme: ThemeConfig\n): HeadingProps {\n const defaults = getHeadingDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve paragraph component props with theme defaults\n */\nexport function resolveParagraphProps(\n props: ParagraphProps,\n theme: ThemeConfig\n): ParagraphProps {\n const defaults = getTextDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve image component props with theme defaults\n */\nexport function resolveImageProps(\n props: ImageProps,\n theme: ThemeConfig\n): ImageProps {\n const defaults = getImageDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve statistic component props with theme defaults\n */\nexport function resolveStatisticProps(\n props: StatisticProps,\n theme: ThemeConfig\n): StatisticProps {\n const defaults = getStatisticDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve table component props with theme defaults\n */\nexport function resolveTableProps(\n props: TableProps,\n theme: ThemeConfig\n): TableProps {\n const defaults = getTableDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve section component props with theme defaults\n */\nexport function resolveSectionProps(\n props: SectionProps,\n theme: ThemeConfig\n): SectionProps {\n const defaults = getSectionDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve columns component props with theme defaults\n */\nexport function resolveColumnsProps(\n props: ColumnsProps,\n theme: ThemeConfig\n): ColumnsProps {\n const defaults = getColumnsDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve list component props with theme defaults\n */\nexport function resolveListProps(\n props: ListProps,\n theme: ThemeConfig\n): ListProps {\n const defaults = getListDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve highcharts component props with theme defaults\n */\nexport function resolveHighchartsProps(\n props: import('@json-to-office/shared-docx').HighchartsProps,\n _theme: ThemeConfig\n): import('@json-to-office/shared-docx').HighchartsProps {\n // Highcharts component doesn't have theme defaults, just return the props as-is\n return props;\n}\n\n/**\n * Resolve visual component props with theme defaults.\n * The visual is rasterized by the pptx engine, so there are no docx-side theme\n * defaults to apply — return props as-is (mirrors highcharts).\n */\nexport function resolveVisualProps(\n props: import('@json-to-office/shared-docx').VisualProps,\n _theme: ThemeConfig\n): import('@json-to-office/shared-docx').VisualProps {\n return props;\n}\n\n/**\n * Get default configuration for custom components\n */\nexport function getCustomComponentDefaults(\n theme: ThemeConfig,\n componentName: string\n): Record<string, unknown> {\n const defaults = getComponentDefaults(theme);\n // Use type assertion since we're dealing with dynamic property access\n return ((defaults as any)?.[componentName] as Record<string, unknown>) || {};\n}\n\n/**\n * Resolve custom component props with theme defaults\n */\nexport function resolveCustomComponentProps<T extends Record<string, unknown>>(\n props: T,\n theme: ThemeConfig,\n componentName: string\n): T {\n const defaults = getCustomComponentDefaults(theme, componentName);\n return mergeWithDefaults(props, defaults as Partial<T>);\n}\n","/**\n * Centralized Component Defaults Resolution\n * Walks the component tree and resolves theme componentDefaults\n * on every component before any rendering or structure processing.\n */\n\nimport { ComponentDefinition, HeadingProps } from '../../types';\nimport { ThemeConfig } from '../index';\nimport {\n resolveHeadingProps,\n resolveParagraphProps,\n resolveImageProps,\n resolveStatisticProps,\n resolveTableProps,\n resolveSectionProps,\n resolveColumnsProps,\n resolveListProps,\n resolveHighchartsProps,\n resolveVisualProps,\n resolveCustomComponentProps,\n getHeadingDefaultsForLevel,\n} from './componentDefaults';\n\n/**\n * Heading resolver that also applies level-specific style defaults\n * (alignment from theme.styles.heading{N}).\n * Moved here from heading.ts to centralize all resolution.\n */\nfunction resolveHeadingWithLevelDefaults(\n props: HeadingProps,\n theme: ThemeConfig\n): HeadingProps {\n const resolved = resolveHeadingProps(props, theme);\n const level = resolved.level || 1;\n const levelDefaults = getHeadingDefaultsForLevel(theme, level);\n return {\n ...resolved,\n // Only apply level-specific defaults if no explicit alignment in original props\n ...(props.alignment ? {} : levelDefaults),\n };\n}\n\ntype Resolver = (props: any, theme: ThemeConfig) => any;\n\nconst RESOLVER_MAP: Record<string, Resolver> = {\n heading: resolveHeadingWithLevelDefaults,\n paragraph: resolveParagraphProps,\n image: resolveImageProps,\n statistic: resolveStatisticProps,\n table: resolveTableProps,\n section: resolveSectionProps,\n columns: resolveColumnsProps,\n list: resolveListProps,\n highcharts: resolveHighchartsProps,\n visual: resolveVisualProps,\n};\n\n/**\n * Resolve componentDefaults for a single component.\n * Known components use their typed resolver; unknown names\n * fall back to resolveCustomComponentProps.\n *\n * A missing `props` key is treated as `{}` — a propless node must still pick up\n * the theme's defaults (e.g. `componentDefaults.section.pageBreak: false`).\n */\nexport function resolveComponentDefaults(\n component: ComponentDefinition,\n theme: ThemeConfig\n): ComponentDefinition {\n const props = component.props ?? {};\n\n const resolver = RESOLVER_MAP[component.name];\n const resolvedProps = resolver\n ? resolver(props, theme)\n : resolveCustomComponentProps(\n props as Record<string, unknown>,\n theme,\n component.name\n );\n\n return { ...component, props: resolvedProps };\n}\n\n/**\n * Recursively walk the component tree and resolve componentDefaults\n * on every component. Returns a new tree (no mutation).\n */\nexport function resolveComponentTree(\n components: ComponentDefinition[],\n theme: ThemeConfig\n): ComponentDefinition[] {\n return components.map((component) => {\n const resolved = resolveComponentDefaults(component, theme);\n\n const children = (resolved as any).children as\n | ComponentDefinition[]\n | undefined;\n if (children && children.length > 0) {\n return {\n ...resolved,\n children: resolveComponentTree(children, theme),\n };\n }\n\n return resolved;\n });\n}\n","/**\n * Document Structure Functions\n * Handle document hierarchy and organization without layout concerns\n */\n\nimport {\n ComponentDefinition,\n ReportProps,\n ReportComponentDefinition,\n RenderContext,\n isSectionComponent,\n isColumnsComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { formatDate } from '../utils/formatters';\nimport { resolveComponentTree } from '../styles/utils/resolveComponentTree';\nimport { mergeWithDefaults } from '../styles/utils/componentDefaults';\n\nexport interface ProcessedDocument {\n metadata: DocumentMetadata;\n sections: ProcessedSection[];\n theme: ThemeConfig;\n themeName: string;\n /** Open the generated document in track-changes mode */\n trackRevisions?: boolean;\n /** Default document language (BCP-47) applied to docDefaults proofing */\n language?: string;\n}\n\nexport interface DocumentMetadata {\n title?: string;\n subtitle?: string;\n description?: string;\n author?: string;\n company?: string;\n version?: string;\n tags?: string[];\n date: Date;\n}\n\nexport interface ProcessedSection {\n components: ComponentDefinition[];\n header?: ComponentDefinition[] | 'linkToPrevious';\n footer?: ComponentDefinition[] | 'linkToPrevious';\n /** True if this section originates from an explicit Section component */\n isExplicitSection?: boolean;\n /** Whether this section should start on a new page */\n pageBreak?: boolean;\n /** Page configuration override for this section */\n page?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n };\n}\n\n/**\n * Process document definition into structured format\n */\nexport async function processDocument(\n document: ReportComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n generationDate?: Date\n): Promise<ProcessedDocument> {\n const metadata = createDocumentMetadata(document.props, generationDate);\n\n // Merge document-level componentDefaults on top of theme-level ones\n // (document overrides theme)\n const docDefaults = document.props.componentDefaults;\n const mergedComponentDefaults = docDefaults\n ? mergeWithDefaults(docDefaults, theme.componentDefaults || {})\n : undefined;\n\n // Fold the document's known-words allowlist into the theme object so it\n // reaches every text primitive (createText/createHeading) without threading\n // a new parameter through the whole render tree. Document words are added to\n // any house-style words the theme already defines.\n const docNoProofWords = document.props.noProofWords;\n const mergedNoProofWords =\n docNoProofWords || theme.noProofWords\n ? Array.from(\n new Set([...(theme.noProofWords || []), ...(docNoProofWords || [])])\n )\n : undefined;\n\n const effectiveTheme =\n mergedComponentDefaults || mergedNoProofWords\n ? {\n ...theme,\n ...(mergedComponentDefaults && {\n componentDefaults: mergedComponentDefaults,\n }),\n ...(mergedNoProofWords && { noProofWords: mergedNoProofWords }),\n }\n : theme;\n\n // Create context with effective theme so section-title headings\n // created in extractSections also see document-level defaults\n const context = createRenderContext(\n {\n metadata,\n sections: [],\n theme: effectiveTheme,\n themeName,\n },\n effectiveTheme,\n themeName\n );\n\n // Resolve componentDefaults on every component before\n // extractSections reads any props (fixes section pageBreak, table defaults, etc.)\n const resolvedChildren = resolveComponentTree(\n document.children || [],\n effectiveTheme\n );\n\n // Extract sections from components\n const sections = await extractSections(resolvedChildren, context);\n\n return {\n metadata,\n sections,\n theme: effectiveTheme,\n themeName,\n trackRevisions: document.props.trackRevisions,\n language: document.props.language,\n };\n}\n\n/**\n * Extract document metadata from report props\n */\nexport function createDocumentMetadata(\n props: ReportProps,\n generationDate = new Date()\n): DocumentMetadata {\n return {\n title: props.metadata?.title,\n subtitle: props.metadata?.subtitle,\n description: props.metadata?.description,\n author: props.metadata?.author,\n company: props.metadata?.company,\n version: props.metadata?.version,\n tags: props.metadata?.tags,\n date: props.metadata?.date ? new Date(props.metadata.date) : generationDate,\n };\n}\n\n/**\n * Extract and flatten sections from component hierarchy\n */\nexport async function extractSections(\n components: ComponentDefinition[],\n context: RenderContext\n): Promise<ProcessedSection[]> {\n const sections: ProcessedSection[] = [];\n\n // Filter out components with enabled: false (defaults to true when not specified)\n const activeComponents = components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n\n for (const component of activeComponents) {\n if (isSectionComponent(component)) {\n const sectionComponents = await flattenComponents(\n component.children || [],\n context\n );\n\n // Determine if page break should be applied (default to true)\n const shouldPageBreak = component.props?.pageBreak !== false;\n\n sections.push({\n components: sectionComponents,\n header: component.props?.header,\n footer: component.props?.footer,\n isExplicitSection: true,\n // Page break is handled at layout level (sections render no title of\n // their own — a visible title is an explicit heading child; the\n // authoring label lives in props.meta.title and is never rendered)\n pageBreak: shouldPageBreak,\n // Preserve page configuration override if present\n page: component.props?.page,\n });\n } else {\n // Non-section components at root level become their own section\n sections.push({\n components: [component],\n isExplicitSection: false,\n });\n }\n }\n\n return sections;\n}\n\n/**\n * Flatten nested container components while preserving content components\n */\nexport async function flattenComponents(\n components: ComponentDefinition[],\n context: RenderContext\n): Promise<ComponentDefinition[]> {\n const flattened: ComponentDefinition[] = [];\n\n // Filter out components with enabled: false (defaults to true when not specified)\n const activeComponents = components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n\n for (const component of activeComponents) {\n if (isColumnsComponent(component) && component.children) {\n // Preserve columns structure but flatten its contents\n flattened.push({\n ...component,\n children: await flattenComponents(component.children, context),\n });\n } else if (isSectionComponent(component) && component.children) {\n // Flatten nested sections (their meta is authoring-only, nothing renders)\n flattened.push(...(await flattenComponents(component.children, context)));\n } else {\n // Keep content components as-is\n flattened.push(component);\n }\n }\n\n return flattened;\n}\n\n/**\n * Create render context from processed document\n */\nexport function createRenderContext(\n document: ProcessedDocument,\n theme: ThemeConfig,\n themeName: string\n): RenderContext {\n return {\n theme: {\n name: themeName,\n colors: theme.colors || {},\n fonts: theme.fonts\n ? Object.fromEntries(\n Object.entries(theme.fonts).map(([key, font]) => [key, font.family])\n )\n : {},\n spacing: { small: 120, medium: 240, large: 360, section: 480 },\n },\n fullTheme: theme,\n document: document.metadata,\n section: {\n currentLayout: 'single',\n columnCount: 1,\n pageNumber: 1,\n },\n utils: {\n formatDate: (date: Date) => formatDate(date),\n parseText: (text: string) => [{ text }],\n getStyle: (name: string) => ({ name }),\n },\n depth: 0,\n };\n}\n","/**\n * Layout Functions\n * Handle all layout concerns including columns, breaks, and section properties\n */\n\nimport { SectionType, Column as DocxColumn } from 'docx';\nimport {\n ComponentDefinition,\n ColumnSettings,\n isColumnsComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isTocComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { getPageSetup, getPageDimensions } from '../styles';\n// import { pointsToTwips } from '../styles/utils/styleHelpers';\nimport { ProcessedSection } from './structure';\nimport {\n getAvailableWidthTwips,\n relativeLengthToTwips,\n} from '../utils/widthUtils';\n\nexport interface LayoutPlan {\n sections: SectionLayout[];\n}\n\nexport interface WordSectionProperties {\n page: {\n size: {\n width: number;\n height: number;\n /**\n * OOXML `w:pgSz/@w:code` — the DEVMODE paper code printer drivers key\n * off. Set only for a named size; a custom `{width, height}` has none.\n */\n code?: number;\n };\n margin: {\n top: number;\n right: number;\n bottom: number;\n left: number;\n };\n };\n column: ColumnSettings & { children?: DocxColumn[] };\n type?: (typeof SectionType)[keyof typeof SectionType];\n}\n\nexport interface SectionLayout {\n properties: WordSectionProperties;\n components: ComponentDefinition[];\n layoutType: 'single' | 'multi-column';\n breakBefore: boolean;\n header?: ComponentDefinition[] | 'linkToPrevious';\n footer?: ComponentDefinition[] | 'linkToPrevious';\n /** True if this layout section comes from a user-defined Section component */\n isUserSection: boolean;\n /** True if this layout chunk belongs to a user-defined Section (all chunks of that section) */\n belongsToUserSection: boolean;\n /** Page configuration override for this section */\n pageOverride?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n };\n}\n\nexport interface LayoutGroup {\n layout: 'single' | 'multi-column';\n components: ComponentDefinition[];\n breakBefore: boolean;\n}\n\n/**\n * Apply layout to processed sections\n */\nexport function applyLayout(\n sections: ProcessedSection[],\n theme: ThemeConfig,\n themeName: string\n): LayoutPlan {\n const layoutSections: SectionLayout[] = [];\n\n for (let i = 0; i < sections.length; i++) {\n const section = sections[i];\n const layoutGroups = analyzeLayoutGroups(section.components);\n\n // Determine if this comes from an explicit Section component\n const isSourceUserSection = Boolean(section.isExplicitSection);\n\n // Handle sections with no components but with headers/footers\n // This ensures headers/footers are rendered even for empty sections\n if (layoutGroups.length === 0 && (section.header || section.footer)) {\n const isFirstSection = i === 0;\n const breakBefore = isFirstSection || Boolean(section.pageBreak);\n const sectionType = breakBefore ? 'nextPage' : 'continuous';\n\n layoutSections.push({\n properties: createSectionProperties(\n getColumnSettings('single'),\n theme,\n themeName,\n sectionType,\n section.page\n ),\n components: [],\n layoutType: 'single',\n breakBefore,\n header: section.header,\n footer: section.footer,\n isUserSection: isSourceUserSection,\n belongsToUserSection: isSourceUserSection,\n pageOverride: section.page,\n });\n continue;\n }\n\n for (let j = 0; j < layoutGroups.length; j++) {\n const group = layoutGroups[j];\n\n // Special handling: a single Columns component becomes its own section with explicit column children\n const isSingleColumnsGroup =\n group.components.length === 1 &&\n isColumnsComponent(group.components[0]);\n\n const columnSettings = isSingleColumnsGroup\n ? createColumnSettingsFromConfig(group.components[0], theme, themeName)\n : getColumnSettings(group.layout);\n\n // Only break page if explicitly requested or this is the first section\n const isFirstSection = i === 0 && j === 0;\n // For titleless sections with pageBreak, apply break to first layout group\n const titlelessSectionBreak = Boolean(section.pageBreak && j === 0);\n const breakBefore =\n group.breakBefore || isFirstSection || titlelessSectionBreak;\n const sectionType = breakBefore ? 'nextPage' : 'continuous';\n\n // Build content components depending on whether this is an explicit columns group\n const contentComponents = isSingleColumnsGroup\n ? processLayoutComponents(\n (\n group.components[0] as unknown as {\n children?: ComponentDefinition[];\n }\n ).children || []\n )\n : processLayoutComponents(group.components);\n\n layoutSections.push({\n properties: createSectionProperties(\n columnSettings,\n theme,\n themeName,\n sectionType,\n section.page\n ),\n components: contentComponents,\n layoutType: group.layout,\n breakBefore,\n header: section.header,\n footer: section.footer,\n // Only mark the FIRST layout section as user-defined to avoid\n // creating bookmark paragraphs in subsequent sections (e.g., when\n // transitioning to columns layout). This prevents unwanted newlines\n // at the start of column content.\n isUserSection: isSourceUserSection && j === 0,\n belongsToUserSection: isSourceUserSection,\n // Pass page override for this section\n pageOverride: section.page,\n });\n }\n }\n\n return { sections: layoutSections };\n}\n\n/**\n * Analyze components to determine layout groups\n */\nexport function analyzeLayoutGroups(\n components: ComponentDefinition[]\n): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let currentLayout: 'single' | 'multi-column' = 'single';\n let currentComponents: ComponentDefinition[] = [];\n let breakNext = false;\n\n for (const component of components) {\n // Always isolate explicit Columns components into their own group\n if (isColumnsComponent(component)) {\n if (currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentComponents = [];\n breakNext = false;\n }\n // Determine the actual layout based on the columns component configuration\n const columnsLayout = determineComponentLayout(component);\n groups.push({\n layout: columnsLayout,\n components: [component],\n breakBefore: breakNext,\n });\n breakNext = false;\n continue;\n }\n\n const componentLayout = determineComponentLayout(component);\n\n // Check for explicit break indicators\n if (hasPageBreak(component)) {\n if (currentComponents.length > 0) {\n // Finish previous group without break\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentComponents = [];\n breakNext = false;\n }\n // Start new group with break for this component\n currentComponents = [component];\n breakNext = true;\n continue;\n }\n\n // Layout change requires new group\n if (componentLayout !== currentLayout && currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentLayout = componentLayout;\n currentComponents = [component];\n breakNext = false;\n } else {\n currentComponents.push(component);\n }\n }\n\n // Add remaining components\n if (currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n }\n\n return groups;\n}\n\n/**\n * Determine layout type for a component\n */\nexport function determineComponentLayout(\n component: ComponentDefinition\n): 'single' | 'multi-column' {\n if (isColumnsComponent(component)) {\n const columns = (component as any).props?.columns;\n\n // If columns is an array with specific configurations\n if (Array.isArray(columns)) {\n // Any columns array with 2+ items is multi-column\n return columns.length >= 2 ? 'multi-column' : 'single';\n }\n\n // No valid array provided; treat as single-column\n return 'single';\n }\n\n // Check if component contains children\n if ('children' in component && (component as any).children) {\n const hasColumns = (component as any).children.some(\n (child: ComponentDefinition) => isColumnsComponent(child)\n );\n return hasColumns ? 'multi-column' : 'single';\n }\n\n return 'single';\n}\n\n/**\n * Process components for layout (insert breaks where needed)\n */\nexport function processLayoutComponents(\n components: ComponentDefinition[]\n): ComponentDefinition[] {\n const processed: ComponentDefinition[] = [];\n\n for (let i = 0; i < components.length; i++) {\n const component = components[i];\n\n // Check if this component should have a column break\n if (shouldInsertColumnBreak()) {\n // Create a new component with columnBreak flag\n if (isHeadingComponent(component)) {\n processed.push({\n ...component,\n props: {\n ...((component as any).props || {}),\n columnBreak: true,\n },\n } as ComponentDefinition);\n } else {\n processed.push(component);\n }\n } else {\n processed.push(component);\n }\n }\n\n return processed;\n}\n\n/**\n * Determine if a column break should be inserted\n */\nfunction shouldInsertColumnBreak(): boolean {\n // Logic to determine column breaks based on content distribution\n // This is simplified - could be enhanced with more sophisticated logic\n return false;\n}\n\n/**\n * Check if component indicates a page break\n */\nfunction hasPageBreak(component: ComponentDefinition): boolean {\n if (isSectionComponent(component)) {\n // Default to true for section components when pageBreak is undefined\n return component.props?.pageBreak !== false;\n }\n if (isHeadingComponent(component)) {\n return component.props.pageBreak === true;\n }\n if (isParagraphComponent(component)) {\n return component.props.pageBreak === true;\n }\n // Allow TOC components to request a page break as well\n if (isTocComponent(component)) {\n return component.props?.pageBreak === true;\n }\n return false;\n}\n\n/**\n * Get column settings for layout type\n */\nexport function getColumnSettings(\n layout: 'single' | 'multi-column'\n): ColumnSettings {\n switch (layout) {\n case 'multi-column':\n // Default multi-column layout: 2 equal-width columns\n // Note: Specific column components will override this with their own settings via createColumnSettingsFromConfig\n return {\n count: 2,\n equalWidth: true,\n space: 720, // 0.5 inch in twips\n };\n case 'single':\n default:\n return { count: 1 };\n }\n}\n\n/**\n * Create Word section properties\n */\nexport function createSectionProperties(\n columnSettings: ColumnSettings,\n theme: ThemeConfig,\n themeName: string,\n sectionType?: 'continuous' | 'nextPage',\n pageOverride?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n }\n): WordSectionProperties {\n // Get base page setup from theme\n const basePageSetup = getPageSetup(theme, themeName);\n\n // Apply section-level page overrides if present.\n //\n // The size override replaces the base size wholesale rather than merging\n // into it: a custom `{width, height}` is not a standard paper, so it must not\n // inherit the theme's paper code — which a spread over `basePageSetup.size`\n // would silently do, telling the driver to fetch A4 for a custom page.\n const pageSetup = pageOverride\n ? {\n size: pageOverride.size\n ? getPageDimensions(pageOverride.size)\n : basePageSetup.size,\n margin: {\n ...basePageSetup.margin,\n ...(pageOverride.margins || {}),\n },\n }\n : basePageSetup;\n\n const properties: WordSectionProperties = {\n page: pageSetup,\n column: {\n count: columnSettings.count,\n equalWidth: columnSettings.equalWidth,\n space: columnSettings.space,\n },\n };\n\n // If explicit children were provided, convert to docx Column instances\n if (\n (columnSettings as any).children &&\n Array.isArray((columnSettings as any).children)\n ) {\n const children = (columnSettings as any).children as {\n width?: number;\n space?: number;\n }[];\n // When we have explicit column children, ensure equalWidth is explicitly false\n // so Word doesn't override widths with equal distribution.\n properties.column.equalWidth = false;\n // Also remove top-level space to avoid conflicting with per-column spaces\n delete properties.column.space;\n\n properties.column.children = children.map(\n (c) =>\n new DocxColumn({\n width: c.width as number,\n ...(c.space !== undefined ? { space: c.space } : {}),\n })\n );\n }\n\n if (sectionType) {\n properties.type =\n sectionType === 'continuous'\n ? SectionType.CONTINUOUS\n : SectionType.NEXT_PAGE;\n }\n\n return properties;\n}\n\n/**\n * Create explicit column settings from a Columns component props\n * - width/gap accept number (points) or percentage string relative to available width\n */\nfunction createColumnSettingsFromConfig(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): ColumnSettings {\n const cfg = ((component as any).props || {}) as {\n columns?: Array<{ width?: number | string; gap?: number | string }>;\n };\n\n // Fallback to single column if no valid array is provided\n const columns = (cfg.columns || []) as Array<{\n width?: number | string;\n gap?: number | string;\n }>;\n\n if (!Array.isArray(columns) || columns.length === 0) {\n return { count: 1 };\n }\n\n const availableWidthTwips = getAvailableWidthTwips(theme, themeName);\n\n // First pass: compute defined widths/spaces; collect indexes without width\n const childSettings: { width?: number; space?: number }[] = [];\n let totalDefinedWidth = 0;\n let totalSpace = 0;\n const unspecifiedWidthIndexes: number[] = [];\n\n for (let i = 0; i < columns.length; i++) {\n const c = columns[i];\n const child: { width?: number; space?: number } = {};\n\n if (c.width !== undefined) {\n const widthTwips = relativeLengthToTwips(c.width, availableWidthTwips);\n if (widthTwips > 0) {\n child.width = widthTwips;\n totalDefinedWidth += widthTwips;\n }\n } else {\n unspecifiedWidthIndexes.push(i);\n }\n\n if (c.gap !== undefined) {\n const spaceTwips = relativeLengthToTwips(c.gap, availableWidthTwips);\n if (spaceTwips > 0) {\n child.space = spaceTwips;\n totalSpace += spaceTwips;\n }\n }\n\n childSettings.push(child);\n }\n\n // Validate that defined widths + gaps do not exceed available width (with tolerance)\n const totalUsedTwips = totalDefinedWidth + totalSpace;\n const tolerance = 0.005; // 0.5%\n const allowed = availableWidthTwips * (1 + tolerance);\n if (totalUsedTwips > allowed) {\n const usedPercent = (totalUsedTwips / availableWidthTwips) * 100;\n // Build diagnostics per column\n const details = childSettings\n .map((c, idx) => {\n const wPct = c.width\n ? ((c.width / availableWidthTwips) * 100).toFixed(1) + '%'\n : 'auto/unspecified';\n const gPct = c.space\n ? ((c.space / availableWidthTwips) * 100).toFixed(1) + '%'\n : '0%';\n return ` - Column ${idx + 1}: width=${wPct}, gap=${gPct}`;\n })\n .join('\\n');\n const suggestion =\n 'Reduce one or more widths/gaps so total <= 100%, remove the last gap, or set some widths to \"auto\" to consume remaining space.';\n throw new Error(\n `Columns configuration exceeds available width: widths + gaps = ${usedPercent.toFixed(1)}% (> 100% + ${(\n tolerance * 100\n ).toFixed(\n 1\n )}% tolerance)\\nDetails:\\n${details}\\nSuggestion: ${suggestion}`\n );\n }\n\n // Distribute remaining width equally among unspecified widths\n const remaining = Math.max(\n 0,\n availableWidthTwips - totalSpace - totalDefinedWidth\n );\n if (unspecifiedWidthIndexes.length > 0) {\n const each = Math.floor(remaining / unspecifiedWidthIndexes.length);\n for (const idx of unspecifiedWidthIndexes) {\n childSettings[idx].width = each;\n }\n }\n\n return {\n count: columns.length,\n equalWidth: false,\n children: childSettings,\n };\n}\n\n/**\n * Calculate optimal column distribution for content\n */\nexport function calculateColumnDistribution(\n components: ComponentDefinition[],\n columnCount: number\n): ComponentDefinition[][] {\n if (columnCount === 1) {\n return [components];\n }\n\n // Simple distribution - could be enhanced with content-aware logic\n const columns: ComponentDefinition[][] = Array(columnCount)\n .fill(null)\n .map(() => []);\n let currentColumn = 0;\n\n for (const component of components) {\n columns[currentColumn].push(component);\n currentColumn = (currentColumn + 1) % columnCount;\n }\n\n return columns;\n}\n","/**\n * Render Functions\n * Transform components and layout into Word document elements\n */\n\nimport {\n Document,\n Paragraph,\n Table,\n TableOfContents,\n IPropertiesOptions,\n ISectionOptions,\n TextRun,\n AlignmentType,\n BookmarkStart,\n BookmarkEnd,\n} from 'docx';\nimport {\n calculateImageDimensions,\n getImageBuffer,\n parseWidthValue,\n detectImageType,\n createTypedImageRun,\n resolveImageSource,\n} from '../utils/imageUtils';\nimport {\n getThemeColors,\n getThemeFonts,\n getNormalStyle,\n} from '../themes/defaults';\nimport {\n ComponentDefinition,\n RenderContext,\n isHeadingComponent,\n isParagraphComponent,\n isColumnsComponent,\n isImageComponent,\n isVisualComponent,\n isTextBoxComponent,\n isStatisticComponent,\n isTableComponent,\n isSectionComponent,\n isListComponent,\n isTocComponent,\n isHighchartsComponent,\n ParagraphComponentDefinition,\n ImageComponentDefinition,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createWordStyles } from '../styles/themeToDocxAdapter';\nimport { resolveFontFamily } from '../styles/utils/styleHelpers';\nimport { getPageSetup } from '../styles/utils/layoutUtils';\nimport {\n DocumentMetadata,\n ProcessedDocument,\n createRenderContext,\n} from './structure';\nimport { LayoutPlan, SectionLayout } from './layout';\nimport {\n renderComponentWithCache,\n initializeComponentCache,\n} from './cached-render';\nimport { MemoryCache } from '../cache';\nimport type { ServicesConfig, RasterizeFontFace } from '@json-to-office/shared';\nimport {\n renderHeadingComponent,\n renderParagraphComponent,\n renderListComponent,\n renderImageComponent,\n renderTableComponent,\n renderSectionComponent,\n renderColumnsComponent,\n renderStatisticComponent,\n renderTocComponent,\n renderHighchartsComponent,\n renderVisualComponent,\n renderTextBoxComponent,\n} from '../components';\nimport {\n createText,\n createHeaderElement,\n createFooterElement,\n} from './content';\nimport { mapFloatingOptions } from '../utils/docxImagePositioning';\nimport { globalBookmarkRegistry } from '../utils/bookmarkRegistry';\nimport { globalNumberingRegistry } from '../utils/numberingConfig';\nimport { globalRevisionIdRegistry } from '../utils/revisionUtils';\nimport { globalCommentRegistry } from '../utils/commentRegistry';\nimport { globalNoteRegistry } from '../utils/noteRegistry';\nimport {\n runWithGenerationDate,\n runWithBaseDir,\n runWithWarnings,\n getBaseDir,\n} from '../utils/generationContext';\nimport type { GenerationWarning } from '@json-to-office/shared';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\nimport { computeSectionOrdinals } from './sectionOrdinals';\nimport { collectDocumentOutline } from './collectTocHeadings';\nimport { globalSectionBookmarkRegistry } from './sectionBookmarks';\nimport { globalNumberedItemsRegistry } from '../utils/numberedItemsRegistry';\n\ninterface RenderDocumentOptions {\n cache?: MemoryCache;\n bypassCache?: boolean;\n services?: ServicesConfig;\n /**\n * Directory that relative asset paths (image `path` props) resolve\n * against. Defaults to `process.cwd()` when absent (#142).\n */\n baseDir?: string;\n /**\n * Font faces (base64) shipped with every `visual` rasterization so the\n * out-of-process LibreOffice renders the slide with the document's real\n * fonts instead of a system fallback. Produced by the caller from\n * `resolveDocumentFonts` via `toRasterizeFontFaces`.\n */\n visualFonts?: RasterizeFontFace[];\n /**\n * Collector for warnings raised while rendering, such as an inline SVG the\n * rasterizer could not turn into a fallback. Absent → `console.warn`.\n */\n warnings?: GenerationWarning[];\n}\n\n/**\n * Convert alignment string to docx AlignmentType\n */\nfunction getAlignment(\n alignment: string\n): (typeof AlignmentType)[keyof typeof AlignmentType] {\n switch (alignment) {\n case 'center':\n return AlignmentType.CENTER;\n case 'right':\n return AlignmentType.RIGHT;\n case 'justify':\n return AlignmentType.JUSTIFIED;\n default:\n return AlignmentType.LEFT;\n }\n}\n\ntype CorePropertyOptions = Pick<\n IPropertiesOptions,\n | 'title'\n | 'subject'\n | 'creator'\n | 'description'\n | 'keywords'\n | 'lastModifiedBy'\n | 'customProperties'\n>;\n\n/**\n * Map root `props.metadata` onto Word's document properties.\n *\n * `date` is deliberately absent: it drives placeholder resolution, not the\n * package timestamps. dcterms:created/modified come from the `generatedAt`\n * generation option (docx always stamps them with the wall clock and offers no\n * override, so packageDocument rewrites them), which is why `metadata` exposes\n * no created/modified of its own.\n * `company` and `version` have no core-property slot, so they land in\n * docProps/custom.xml.\n */\nfunction coreProperties(metadata: DocumentMetadata): CorePropertyOptions {\n const { title, subtitle, description, author, company, version, tags } =\n metadata;\n\n const customProperties = [\n ...(company ? [{ name: 'Company', value: company }] : []),\n ...(version ? [{ name: 'Version', value: version }] : []),\n ];\n\n return {\n ...(title && { title }),\n ...(subtitle && { subject: subtitle }),\n ...(description && { description }),\n // Word surfaces both names; author is the only person the document knows.\n ...(author && { creator: author, lastModifiedBy: author }),\n ...(tags && tags.length > 0 && { keywords: tags.join(', ') }),\n ...(customProperties.length > 0 && { customProperties }),\n };\n}\n\n/**\n * Render a complete document from structure and layout\n */\nexport async function renderDocument(\n structure: ProcessedDocument,\n layout: LayoutPlan,\n options?: RenderDocumentOptions\n): Promise<Document> {\n return runWithGenerationDate(structure.metadata.date, () =>\n runWithWarnings(options?.warnings, () =>\n runWithBaseDir(options?.baseDir, () =>\n globalBookmarkRegistry.runScoped(() =>\n globalRevisionIdRegistry.runScoped(() =>\n globalNumberingRegistry.runScoped(() =>\n globalSectionBookmarkRegistry.runScoped(() =>\n // Comment ids are a separate OOXML namespace from w:ins/w:del,\n // but they need the same per-render isolation: outside this nest\n // concurrent generations would interleave counters and an anchor\n // would point at another document's comment body.\n globalCommentRegistry.runScoped(() =>\n // Footnote ids are document-scoped too: a reference resolved\n // against another render's counter points at the wrong body.\n globalNoteRegistry.runScoped(() =>\n // Cross-reference targets are keyed by bookmark id, which\n // is only unique within one document.\n globalNumberedItemsRegistry.runScoped(() =>\n renderDocumentScoped(structure, layout, options)\n )\n )\n )\n )\n )\n )\n )\n )\n )\n );\n}\n\nasync function renderDocumentScoped(\n structure: ProcessedDocument,\n layout: LayoutPlan,\n options?: RenderDocumentOptions\n): Promise<Document> {\n // Initialize component cache if provided\n if (options?.cache) {\n initializeComponentCache(options.cache);\n } else if (!options?.bypassCache) {\n // Initialize with default cache unless bypassed\n initializeComponentCache();\n }\n\n const sections: ISectionOptions[] = [];\n\n // Render all layout sections\n const context = createRenderContext(\n structure,\n structure.theme,\n structure.themeName\n );\n context.services = options?.services;\n context.visualFonts = options?.visualFonts;\n\n // Coalesce the document's visual rasterizations into batched service calls\n // before the (strictly sequential) component walk begins (#153). Purely an\n // accelerator: renderVisualComponent falls back to per-visual rasterization\n // for anything the pre-pass missed, so a pre-pass failure can slow a render\n // but never break one.\n try {\n const visualRasterResults = await prerasterizeVisuals(\n layout.sections,\n options?.services?.pptx,\n { baseDir: getBaseDir(), fonts: options?.visualFonts }\n );\n if (visualRasterResults.size > 0) {\n context.visualRasterResults = visualRasterResults;\n }\n } catch (error) {\n console.warn(\n '[core-docx] Visual pre-rasterization failed; falling back to per-visual rasterization:',\n error instanceof Error ? error.message : error\n );\n }\n\n // Walk the outline before rendering so a TOC field can carry cached content\n // for readers that never refresh fields (#174), headings know their number\n // (#177), and a `[@id]` cross-reference can resolve a target that appears\n // later in the document (#182). Same catch-and-degrade discipline as the\n // visual pre-pass: a failure here costs the cached entries and the\n // cross-reference values, never the document.\n try {\n const outline = collectDocumentOutline(layout.sections);\n if (outline.entries.length > 0) {\n context.tocHeadings = outline.entries;\n }\n globalNumberedItemsRegistry.seed(outline.numberedItems);\n } catch (error) {\n console.warn(\n '[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it:',\n error instanceof Error ? error.message : error\n );\n }\n\n /**\n * Resolve every layout chunk's bookmark ordinal up front.\n *\n * When a user-defined Section spans multiple layout chunks (a columns\n * transition starts a new one), all chunks must share one bookmark id for\n * TOC scoping to work: start in the first chunk, end in the last, same\n * stable name throughout. The ordinal is a fold over the chunk list, so it\n * lives in its own pure function rather than as a counter carried through\n * this loop's header/footer bookkeeping.\n */\n const sectionOrdinals = computeSectionOrdinals(layout.sections);\n\n // Track previous section's headers/footers for 'linkToPrevious' functionality\n let previousHeader: ComponentDefinition[] | undefined = undefined;\n let previousFooter: ComponentDefinition[] | undefined = undefined;\n\n // Render all layout sections\n for (let idx = 0; idx < layout.sections.length; idx++) {\n const layoutSection = layout.sections[idx];\n const { ordinal: sectionOrdinal, closeBookmark } = sectionOrdinals[idx];\n\n // Handle 'linkToPrevious' value for headers\n let headerToUse: ComponentDefinition[] | undefined;\n if (layoutSection.header === 'linkToPrevious') {\n // Use the previous section's header\n headerToUse = previousHeader;\n } else if (layoutSection.header) {\n // Section has its own header\n headerToUse = layoutSection.header as ComponentDefinition[];\n previousHeader = headerToUse; // Update previous for next section\n } else {\n // No header explicitly set for this section.\n // Important: Word links headers/footers to previous by default.\n // To prevent unintended inheritance, emit an explicit empty header\n // when a previous header exists and caller didn't request linking.\n headerToUse = previousHeader ? [] : undefined;\n // Keep previousHeader cached for potential future explicit linkToPrevious\n }\n\n // Handle 'linkToPrevious' value for footers\n let footerToUse: ComponentDefinition[] | undefined;\n if (layoutSection.footer === 'linkToPrevious') {\n // Use the previous section's footer\n footerToUse = previousFooter;\n } else if (layoutSection.footer) {\n // Section has its own footer\n footerToUse = layoutSection.footer as ComponentDefinition[];\n previousFooter = footerToUse; // Update previous for next section\n } else {\n // No footer explicitly set for this section.\n // Prevent unintended inheritance by emitting an explicit empty footer\n // when a previous footer exists and caller didn't request linking.\n footerToUse = previousFooter ? [] : undefined;\n // Keep previousFooter cached for potential future explicit linkToPrevious\n }\n\n const sectionToRender = {\n ...layoutSection,\n header: headerToUse,\n footer: footerToUse,\n };\n\n const rendered = await renderSection(\n sectionToRender,\n structure.theme,\n structure.themeName,\n context,\n sectionOrdinal,\n closeBookmark,\n options?.bypassCache === true\n );\n\n if (rendered.children.length > 0) {\n sections.push(rendered);\n }\n }\n\n // Get all numbering configurations from the registry (already imported above)\n const numberingConfigs = globalNumberingRegistry.getAll();\n // Comment bodies collected while rendering the anchors\n const comments = globalCommentRegistry.getAll();\n // Note bodies collected while rendering their markers\n const footnotes = globalNoteRegistry.getFootnotes();\n const endnotes = globalNoteRegistry.getEndnotes();\n\n return new Document({\n styles: createWordStyles(structure.theme, structure.language),\n sections,\n ...coreProperties(structure.metadata),\n features: {\n updateFields: true, // Required for TOC fields to update correctly\n // Word opens the document in review mode (further edits are tracked)\n ...(structure.trackRevisions && { trackRevisions: true }),\n },\n // word/comments.xml, emitted only when something was actually commented\n ...(comments.length > 0 && { comments: { children: comments } }),\n // word/footnotes.xml and word/endnotes.xml bodies, keyed by the id their\n // references carry\n ...(Object.keys(footnotes).length > 0 && { footnotes }),\n ...(Object.keys(endnotes).length > 0 && { endnotes }),\n // Add numbering configurations if any lists were rendered\n ...(numberingConfigs.length > 0 && {\n numbering: {\n config: numberingConfigs as readonly {\n readonly levels: readonly import('docx').ILevelsOptions[];\n readonly reference: string;\n }[],\n },\n }),\n });\n}\n\n/**\n * Render header/footer components into paragraphs\n */\nasync function renderHeaderFooterComponents(\n components: ComponentDefinition[] | undefined,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!components || components.length === 0) {\n return [];\n }\n\n // Filter out components with enabled: false (defaults to true when not specified)\n const activeComponents = components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n\n const elements: (Paragraph | Table)[] = [];\n\n for (const component of activeComponents) {\n if (isParagraphComponent(component)) {\n const textComp = component as ParagraphComponentDefinition;\n const font = textComp.props.font;\n\n // Header/footer text has no dedicated style, so unspecified font\n // properties resolve against the theme's Normal style.\n const normalStyle = getNormalStyle(theme);\n\n // Render through the shared paragraph primitive (same as body\n // paragraphs) so headers/footers honor lineSpacing, spacing\n // (before/after) and the full font set instead of silently dropping\n // them. When the component omits lineSpacing/spacing, createText leaves\n // them unset and the Normal style supplies the baseline.\n elements.push(\n createText(textComp.props.text, theme, themeName, {\n style: 'Normal',\n alignment: textComp.props.alignment,\n // Resolve explicit run styling against the Normal style, preserving\n // prior header/footer rendering for these properties.\n fontFamily:\n font?.family ||\n resolveFontFamily(theme, normalStyle.font) ||\n getThemeFonts(theme).body.family,\n fontSize: (font?.size ?? normalStyle.size ?? 11) as number,\n // Pass the raw color/token; createText resolves it. Fall back to the\n // Normal style color, then the theme's primary text color.\n fontColor: font?.color || normalStyle.color || 'textPrimary',\n bold: font?.bold ?? false,\n italic: font?.italic ?? false,\n underline: font?.underline,\n fontWeight: (font as { fontWeight?: number } | undefined)?.fontWeight,\n boldColor: textComp.props.boldColor,\n spacing: textComp.props.spacing,\n lineSpacing: font?.lineSpacing,\n })\n );\n } else if (isImageComponent(component)) {\n const imageComp = component as ImageComponentDefinition;\n // Get image source (svg, base64, or path)\n let imageSource = resolveImageSource(imageComp.props);\n if (!imageSource) {\n elements.push(\n new Paragraph({\n children: [\n new TextRun({\n text: '[IMAGE: Missing path, base64, or svg property]',\n font: getThemeFonts(theme).body.family,\n size: 20,\n bold: true,\n color: '#FF0000',\n }),\n ],\n alignment: imageComp.props.alignment\n ? getAlignment(imageComp.props.alignment)\n : undefined,\n style: 'Normal',\n })\n );\n continue;\n }\n\n let imageBuffer: Buffer;\n let responseContentType: string | undefined;\n\n try {\n // Try to use the provided source first\n const imageResult = await getImageBuffer(imageSource);\n imageBuffer = imageResult.buffer;\n responseContentType = imageResult.contentType;\n } catch (error) {\n throw new Error(\n `Failed to load image from ${imageSource.substring(0, 50)}`\n );\n }\n\n try {\n // Get page setup from theme for proper width calculations\n const pageSetup = getPageSetup(theme);\n\n // Convert twips to pixels: 1 twip = 1/1440 inch, 1 inch = 96 pixels at 96 DPI\n const TWIPS_TO_PIXELS = 96 / 1440;\n\n // Calculate page width and content width (page - left margin - right margin) in pixels\n const pageWidthPx = Math.round(pageSetup.size.width * TWIPS_TO_PIXELS);\n const contentWidthPx = Math.round(\n (pageSetup.size.width -\n pageSetup.margin.left -\n pageSetup.margin.right) *\n TWIPS_TO_PIXELS\n );\n\n // Determine reference dimensions based on widthRelativeTo/heightRelativeTo properties\n const widthRelativeTo = imageComp.props.widthRelativeTo || 'content';\n const heightRelativeTo = imageComp.props.heightRelativeTo || 'content';\n const referenceWidthPx =\n widthRelativeTo === 'page' ? pageWidthPx : contentWidthPx;\n\n // Calculate page height and content height in pixels\n const pageHeightPx = Math.round(\n pageSetup.size.height * TWIPS_TO_PIXELS\n );\n const contentHeightPx = Math.round(\n (pageSetup.size.height -\n pageSetup.margin.top -\n pageSetup.margin.bottom) *\n TWIPS_TO_PIXELS\n );\n const referenceHeightPx =\n heightRelativeTo === 'page' ? pageHeightPx : contentHeightPx;\n\n const fallbackHeight = Math.round(referenceWidthPx * 0.6);\n\n // Parse width value if it's a string percentage (like \"90%\")\n const parsedWidth =\n typeof imageComp.props.width === 'string'\n ? parseWidthValue(imageComp.props.width, referenceWidthPx) // Use appropriate reference width\n : imageComp.props.width;\n\n // Parse height value if it's a string percentage (like \"90%\")\n const parsedHeight =\n typeof imageComp.props.height === 'string'\n ? parseWidthValue(imageComp.props.height, referenceHeightPx) // Use reference height based on heightRelativeTo\n : imageComp.props.height;\n\n // Calculate dimensions with aspect ratio preservation\n const dimensions = await calculateImageDimensions(\n imageSource,\n parsedWidth,\n parsedHeight,\n referenceWidthPx,\n fallbackHeight\n );\n\n // Map floating options if present\n const floatingOptions = mapFloatingOptions(\n imageComp.props.floating,\n theme,\n themeName\n );\n\n const imageType = detectImageType(imageSource, responseContentType);\n\n const imageRun = await createTypedImageRun({\n type: imageType,\n data: imageBuffer,\n transformation: {\n width: dimensions.width,\n height: dimensions.height,\n },\n ...(floatingOptions && { floating: floatingOptions }),\n });\n\n elements.push(\n new Paragraph({\n children: [imageRun],\n alignment: imageComp.props.alignment\n ? getAlignment(imageComp.props.alignment)\n : undefined,\n style: 'Normal',\n })\n );\n } catch (error) {\n // Fallback for missing images - log error for debugging.\n // Use the resolved source (svg/base64/path), truncated so an inline\n // data URI doesn't dump into the log or the placeholder text.\n const sourcePreview = imageSource.substring(0, 50);\n console.error(\n `[Header/Footer Image Error] Failed to render image: ${sourcePreview}...`,\n error instanceof Error ? error.message : error\n );\n elements.push(\n new Paragraph({\n children: [\n new TextRun({\n text: `[IMAGE: ${sourcePreview}]`,\n font: getThemeFonts(theme).body.family,\n size: 20,\n color: getThemeColors(theme).secondary,\n bold: true,\n }),\n ],\n style: 'Normal',\n })\n );\n }\n } else if (isTableComponent(component)) {\n // Use renderTableComponent for consistent table rendering in headers/footers\n // This ensures cellDefaults, padding, borders, and all table features work correctly\n const tables = await renderTableComponent(component, theme, themeName);\n elements.push(...tables);\n } else if (isVisualComponent(component)) {\n // A visual desugars to an image; needs the rasterization service from context.\n const visualEls = await renderVisualComponent(\n component,\n theme,\n themeName,\n context\n );\n elements.push(...visualEls);\n }\n // Other component types can be added here as needed\n }\n\n return elements;\n}\n\n/**\n * Render a section with layout\n */\nexport async function renderSection(\n section: SectionLayout,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext,\n sectionOrdinal?: number,\n closeBookmark?: boolean,\n bypassCache = false\n): Promise<ISectionOptions> {\n const elements: (Paragraph | Table | TableOfContents)[] = [];\n\n // Update context for this section\n // Generate a unique bookmark for this section so TOCs can scope to it\n const isFirstLayoutOfUserSection = section.isUserSection;\n // Every layout chunk of one user-defined section resolves to the same\n // bookmark; the registry owns the id format for both producers.\n const bookmark =\n section.belongsToUserSection && sectionOrdinal\n ? globalSectionBookmarkRegistry.forLayoutSection(sectionOrdinal)\n : undefined;\n const sharedLinkId = bookmark?.linkId;\n const sectionBookmarkId = bookmark?.id;\n\n const sectionContext: RenderContext = {\n ...context,\n section: {\n ...context.section,\n currentLayout: section.layoutType,\n columnCount: section.properties.column?.count || 1,\n // Always pass the same bookmark ID for all layout chunks of the same section\n sectionBookmarkId: sectionBookmarkId,\n },\n };\n\n // Add bookmark start before all section content so TOCs can scope to it\n if (\n sectionBookmarkId &&\n isFirstLayoutOfUserSection &&\n sharedLinkId !== undefined\n ) {\n elements.push(\n new Paragraph({\n children: [new BookmarkStart(sectionBookmarkId, sharedLinkId)],\n spacing: {\n before: 0,\n after: 0,\n line: 0,\n },\n })\n );\n }\n\n // Filter out components with enabled: false and render remaining components (with caching)\n const activeComponents = section.components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n for (const component of activeComponents) {\n const rendered = await renderComponentWithCache(\n component,\n theme,\n themeName,\n sectionContext,\n bypassCache\n );\n elements.push(...rendered);\n }\n\n // Close bookmark after section content\n if (closeBookmark && sharedLinkId !== undefined) {\n elements.push(\n new Paragraph({\n children: [new BookmarkEnd(sharedLinkId)],\n })\n );\n }\n\n // Build section options with headers/footers if defined\n let headers: ISectionOptions['headers'] | undefined;\n let footers: ISectionOptions['footers'] | undefined;\n\n if (section.header || section.footer) {\n if (section.header && section.header !== 'linkToPrevious') {\n const headerComponents = section.header as ComponentDefinition[];\n const headerParagraphs = await renderHeaderFooterComponents(\n headerComponents,\n theme,\n themeName,\n sectionContext\n );\n // If components were provided but produced no paragraphs, still create\n // an empty Header to break Word's default link-to-previous behavior.\n if (headerComponents.length === 0 || headerParagraphs.length > 0) {\n headers = {\n default: createHeaderElement(headerParagraphs),\n };\n }\n }\n\n if (section.footer && section.footer !== 'linkToPrevious') {\n const footerComponents = section.footer as ComponentDefinition[];\n const footerParagraphs = await renderHeaderFooterComponents(\n footerComponents,\n theme,\n themeName,\n sectionContext\n );\n if (footerComponents.length === 0 || footerParagraphs.length > 0) {\n footers = {\n default: createFooterElement(footerParagraphs),\n };\n }\n }\n }\n\n const sectionOptions: ISectionOptions = {\n properties: section.properties,\n children: elements,\n headers,\n footers,\n };\n\n return sectionOptions;\n}\n\n/**\n * Render a single component to Word elements\n */\nexport async function renderComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext\n): Promise<(Paragraph | Table | TableOfContents)[]> {\n if (isHeadingComponent(component)) {\n return renderHeadingComponent(component, theme, themeName);\n } else if (isParagraphComponent(component)) {\n return renderParagraphComponent(component, theme, themeName);\n } else if (isColumnsComponent(component)) {\n return await renderColumnsComponent(component, theme, themeName, context);\n } else if (isImageComponent(component)) {\n return await renderImageComponent(component, theme, themeName);\n } else if (isTextBoxComponent(component)) {\n return await renderTextBoxComponent(component, theme, themeName, context);\n } else if (isStatisticComponent(component)) {\n return renderStatisticComponent(component, theme);\n } else if (isTableComponent(component)) {\n return await renderTableComponent(component, theme, themeName);\n } else if (isListComponent(component)) {\n return renderListComponent(component, theme, themeName);\n } else if (isTocComponent(component)) {\n return renderTocComponent(component, theme, context);\n } else if (isHighchartsComponent(component)) {\n return await renderHighchartsComponent(\n component,\n theme,\n themeName,\n context\n );\n } else if (isVisualComponent(component)) {\n return await renderVisualComponent(component, theme, themeName, context);\n } else if (isSectionComponent(component)) {\n return await renderSectionComponent(component, theme, themeName, context);\n }\n\n throw new Error(\n `Unknown component type: ${(component as ComponentDefinition).name}`\n );\n}\n","import { readFileSync } from 'fs';\nimport probe from 'probe-image-size';\nimport { reportWarning, resolveFromBaseDir } from './generationContext';\nimport { ImageRun, IFloating } from 'docx';\nimport { parsePercentageStringToFraction } from './widthUtils';\n\ntype ResvgModule = typeof import('@resvg/resvg-js');\n\n/** 3x of Word's 96 DPI baseline — ~288 DPI, sharp in print and on retina. */\nconst SVG_RASTER_SCALE = 3;\nconst SVG_MAX_EDGE_PX = 4096;\nconst SVG_MIN_EDGE_PX = 16;\n/**\n * Ceiling on the whole bitmap, not just its longest side.\n *\n * An edge cap alone says nothing about area, and area is what costs memory:\n * resvg renders RGBA, so a page-sized SVG at 3x is 2382x3367 ≈ 8 MP ≈ 32 MB\n * live before it is even encoded to PNG. The annual-report templates carry two\n * dozen full-page SVGs, which took one render past 1.1 GB and had the hosted\n * playground's 512 MB container killed mid-request — the reader saw the\n * proxy's HTML error page, not a document.\n *\n * 1 MP keeps a full page near 120 DPI, which is enough for what this bitmap is:\n * Word 2016+ draws the vector, and only older readers ever fall back to it.\n * Small SVGs are unaffected — an icon at 3x is nowhere near the budget.\n */\nconst SVG_MAX_TOTAL_PX = 1_000_000;\n\nlet resvgModule: Promise<ResvgModule> | undefined;\n\nfunction loadResvg(): Promise<ResvgModule> {\n resvgModule ??= import('@resvg/resvg-js');\n return resvgModule;\n}\n\nfunction toRasterPx(px: number): number {\n return Math.min(\n SVG_MAX_EDGE_PX,\n Math.max(SVG_MIN_EDGE_PX, Math.round(px * SVG_RASTER_SCALE))\n );\n}\n\n/**\n * Shrink a `fitTo` edge until the bitmap it implies fits `SVG_MAX_TOTAL_PX`,\n * or `undefined` when nothing does.\n *\n * `aspect` is the other edge over this one, so `edge * aspect` is the edge\n * resvg derives. Area scales with the square of the edge, hence the sqrt.\n *\n * A sliver — an SVG whose viewBox is thousands of times longer than it is\n * wide — cannot be squared with both bounds at once: at `SVG_MIN_EDGE_PX` its\n * area is still `256 * aspect`, so a ratio of 10,000 is already 2.5x over\n * budget and grows from there. Clamping to the minimum edge in that case would\n * hand back exactly the oversized bitmap this budget exists to prevent, so the\n * caller is told to skip the fallback instead. Word 2016+ draws the vector\n * either way.\n */\nfunction capToPixelBudget(edge: number, aspect: number): number | undefined {\n // A degenerate ratio means the probe gave a zero or non-finite dimension;\n // there is no bitmap size that can be reasoned about.\n if (!Number.isFinite(aspect) || aspect <= 0) return undefined;\n\n const total = edge * edge * aspect;\n if (total <= SVG_MAX_TOTAL_PX) return edge;\n\n const scaled = Math.floor(edge * Math.sqrt(SVG_MAX_TOTAL_PX / total));\n return scaled >= SVG_MIN_EDGE_PX ? scaled : undefined;\n}\n\n/**\n * Rasterize inline SVG for the `fallback` slot of an SVG `ImageRun`.\n *\n * Word 2016+ draws the vector, but every older Word and non-SVG consumer\n * renders the fallback instead — so shipping the SVG bytes under a `png` type\n * gave those readers a broken image. Returns `undefined` when rasterization is\n * unavailable or fails; the caller then keeps the historical bytes, which is\n * no worse than before and never fails the render.\n */\nasync function rasterizeSvgFallback(\n svg: Buffer,\n transformation: { width: number; height: number }\n): Promise<Buffer | undefined> {\n let Resvg: ResvgModule['Resvg'];\n try {\n ({ Resvg } = await loadResvg());\n } catch (error) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_FAILED',\n `Could not load the SVG rasterizer, so inline SVG keeps a fallback that only Word 2016+ can draw: ${String(error)}`\n );\n return undefined;\n }\n\n try {\n const markup = svg.toString('utf-8');\n const probeImage = new Resvg(markup);\n // resvg scales uniformly, so pick the axis that makes the bitmap cover\n // the placed box on both — matching the box aspect is not enough.\n const wide =\n probeImage.width / probeImage.height >\n transformation.width / transformation.height;\n // resvg derives the other edge from the SVG's own aspect ratio, so the\n // budget has to be applied against that, not against the placed box.\n const mode = wide ? ('height' as const) : ('width' as const);\n const value = capToPixelBudget(\n toRasterPx(wide ? transformation.height : transformation.width),\n wide\n ? probeImage.width / probeImage.height\n : probeImage.height / probeImage.width\n );\n\n if (value === undefined) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_SKIPPED',\n 'Inline SVG is too far from square to rasterize within the fallback ' +\n 'pixel budget, so its fallback only renders in Word 2016+.'\n );\n return undefined;\n }\n\n return Buffer.from(\n new Resvg(markup, { fitTo: { mode, value } }).render().asPng()\n );\n } catch (error) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_FAILED',\n `Could not rasterize inline SVG, so its fallback only renders in Word 2016+: ${String(error)}`\n );\n return undefined;\n }\n}\n\nexport interface ImageDimensions {\n width: number;\n height: number;\n}\n\nexport interface CalculatedDimensions {\n width: number;\n height: number;\n}\n\nexport interface ImageBufferResult {\n buffer: Buffer;\n contentType?: string;\n}\n\n/**\n * Parse width value - accepts either number (pixels) or percentage string\n * @param width - Width value as number or percentage string (e.g., \"90%\")\n * @param availableWidthPx - Available document width in pixels\n * @returns Width in pixels\n */\nexport function parseWidthValue(\n width: number | string,\n availableWidthPx: number\n): number {\n if (typeof width === 'number') {\n return width;\n }\n\n // Parse percentage string using shared util while preserving error semantics\n const percentageMatch = (width as string).match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percentageMatch) {\n const pct = parseFloat(percentageMatch[1]);\n if (pct < 0 || pct > 100) {\n throw new Error(\n `Invalid percentage value: ${width}. Must be between 0% and 100%`\n );\n }\n const fraction = parsePercentageStringToFraction(width as string);\n if (fraction !== undefined) {\n return Math.round(availableWidthPx * fraction);\n }\n }\n\n throw new Error(\n `Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., \"90%\")`\n );\n}\n\n/**\n * Parse a generic dimension value (number in px or percentage string)\n * @param value - numeric pixels or percentage string (e.g., \"100%\")\n * @param availablePx - available pixels for percentage reference\n */\nexport function parseDimensionValue(\n value: number | string,\n availablePx: number\n): number {\n if (typeof value === 'number') return value;\n const percentageMatch = (value as string).match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percentageMatch) {\n const pct = parseFloat(percentageMatch[1]);\n if (pct < 0 || pct > 100) {\n throw new Error(\n `Invalid percentage value: ${value}. Must be between 0% and 100%`\n );\n }\n const fraction = parsePercentageStringToFraction(value as string);\n if (fraction !== undefined) return Math.round(availablePx * fraction);\n }\n throw new Error(\n `Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., \"90%\")`\n );\n}\n\n/**\n * Check if a string is a valid URL\n */\nexport function isValidUrl(string: string): boolean {\n try {\n const url = new URL(string);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a string is a base64 data URI\n * Supports format: data:image/[type];base64,[data]\n */\nexport function isBase64Image(string: string): boolean {\n return /^data:image\\/[a-zA-Z+]+;base64,/.test(string);\n}\n\n/**\n * Decode base64 data URI to Buffer\n * @param dataUri - Base64 data URI (e.g., \"data:image/png;base64,iVBORw0KGgo...\")\n * @returns Decoded image buffer\n */\nexport function decodeBase64Image(dataUri: string): Buffer {\n try {\n // Extract the base64 data after the comma\n const base64Data = dataUri.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid base64 data URI format');\n }\n return Buffer.from(base64Data, 'base64');\n } catch (error) {\n throw new Error(\n `Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Extract MIME type from base64 data URI\n * @param dataUri - Base64 data URI (e.g., \"data:image/svg+xml;base64,...\")\n * @returns MIME type (e.g., \"image/svg+xml\") or undefined if not found\n */\nexport function extractMimeTypeFromDataUri(\n dataUri: string\n): string | undefined {\n const match = dataUri.match(/^data:(image\\/[a-zA-Z0-9+.-]+);base64,/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Detect image type from file extension\n * @param path - File path or URL\n * @returns Image type (jpg, png, gif, bmp, svg) or undefined\n */\nexport function detectImageTypeFromExtension(\n path: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' | undefined {\n const extension = path.toLowerCase().split('.').pop()?.split('?')[0]; // Handle query params in URLs\n switch (extension) {\n case 'jpg':\n case 'jpeg':\n return 'jpg';\n case 'png':\n return 'png';\n case 'gif':\n return 'gif';\n case 'bmp':\n return 'bmp';\n case 'svg':\n return 'svg';\n default:\n return undefined;\n }\n}\n\n/**\n * Detect image type from MIME type\n * @param mimeType - MIME type string (e.g., \"image/svg+xml\", \"image/png\")\n * @returns Image type (jpg, png, gif, bmp, svg) or undefined\n */\nexport function detectImageTypeFromMimeType(\n mimeType: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' | undefined {\n const normalized = mimeType.toLowerCase();\n if (normalized.includes('svg')) return 'svg';\n if (normalized.includes('jpeg') || normalized.includes('jpg')) return 'jpg';\n if (normalized.includes('png')) return 'png';\n if (normalized.includes('gif')) return 'gif';\n if (normalized.includes('bmp')) return 'bmp';\n return undefined;\n}\n\n/**\n * Detect image type from path or base64 data URI\n * Prioritizes: response Content-Type > MIME type from base64 > file extension > default to 'png'\n * @param imagePath - File path, URL, or base64 data URI\n * @param responseContentType - Optional Content-Type header from HTTP response\n * @returns Image type (jpg, png, gif, bmp, svg)\n */\nexport function detectImageType(\n imagePath: string,\n responseContentType?: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' {\n // Highest priority: Content-Type from HTTP response\n if (responseContentType) {\n const typeFromResponse = detectImageTypeFromMimeType(responseContentType);\n if (typeFromResponse) return typeFromResponse;\n }\n\n // Check if it's a base64 data URI and extract MIME type\n if (isBase64Image(imagePath)) {\n const mimeType = extractMimeTypeFromDataUri(imagePath);\n if (mimeType) {\n const typeFromMime = detectImageTypeFromMimeType(mimeType);\n if (typeFromMime) return typeFromMime;\n }\n }\n\n // Try to detect from file extension\n const typeFromExtension = detectImageTypeFromExtension(imagePath);\n if (typeFromExtension) return typeFromExtension;\n\n // Default to PNG for backward compatibility\n return 'png';\n}\n\n/**\n * Create an ImageRun with correct type handling, including SVG fallback.\n *\n * An SVG run carries a raster `fallback` for readers that cannot draw the\n * vector — Word before 2016, and anything else consuming the package. That\n * fallback is rasterized here; if rasterization is unavailable the run keeps\n * the SVG bytes, which renders in Word 2016+ and reports a warning for the\n * rest rather than failing the document.\n */\nexport async function createTypedImageRun(opts: {\n type: 'jpg' | 'png' | 'gif' | 'bmp' | 'svg';\n data: Buffer;\n transformation: { width: number; height: number };\n floating?: IFloating;\n}): Promise<ImageRun> {\n const base = {\n data: opts.data,\n transformation: opts.transformation,\n ...(opts.floating && { floating: opts.floating }),\n };\n if (opts.type === 'svg') {\n const raster = await rasterizeSvgFallback(opts.data, opts.transformation);\n return new ImageRun({\n type: 'svg',\n ...base,\n fallback: { type: 'png', data: raster ?? opts.data },\n });\n }\n return new ImageRun({ type: opts.type, ...base });\n}\n\n/**\n * Download image from URL and return buffer\n * Uses native fetch with automatic redirect following and proper headers\n */\nexport async function downloadImageFromUrl(\n url: string\n): Promise<ImageBufferResult> {\n try {\n // Create an AbortController for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout\n\n const response = await fetch(url, {\n signal: controller.signal,\n headers: {\n 'User-Agent': 'Mozilla/5.0 (compatible; json-to-docx/1.0)',\n },\n redirect: 'follow', // Automatically follow redirects (default behavior)\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(\n `Failed to download image: HTTP ${response.status} ${response.statusText}`\n );\n }\n\n const contentType = response.headers.get('content-type') || undefined;\n\n // Get the response as an ArrayBuffer\n const arrayBuffer = await response.arrayBuffer();\n\n // Convert ArrayBuffer to Buffer\n return { buffer: Buffer.from(arrayBuffer), contentType };\n } catch (error) {\n if (error instanceof Error) {\n // Handle timeout errors\n if (error.name === 'AbortError') {\n throw new Error(\n 'Failed to download image: Request timeout after 10 seconds'\n );\n }\n throw new Error(`Failed to download image from ${url}: ${error.message}`);\n }\n throw new Error(`Failed to download image from ${url}: Unknown error`);\n }\n}\n\n/**\n * Resolve the effective image source string from image component props.\n * Precedence: raw inline `svg` markup (wrapped into an svg data URI) > `base64`\n * data URI > `path` (file/URL). Returns undefined when no source is provided.\n *\n * Raw SVG is encoded as a base64 svg+xml data URI so it flows through the same\n * pipeline as any other source (getImageBuffer / detectImageType / dimensions).\n */\nexport function resolveImageSource(props: {\n svg?: string;\n base64?: string;\n path?: string;\n}): string | undefined {\n const hasValue = (v?: string): v is string =>\n typeof v === 'string' && v.trim().length > 0;\n if (hasValue(props.svg)) {\n const encoded = Buffer.from(props.svg, 'utf-8').toString('base64');\n return `data:image/svg+xml;base64,${encoded}`;\n }\n // Blank base64/path count as absent (matching the source-conflict validator),\n // so a whitespace-only value can't shadow a real later source.\n if (hasValue(props.base64)) return props.base64;\n if (hasValue(props.path)) return props.path;\n return undefined;\n}\n\n/**\n * Get image buffer from base64 data URI, URL, or local file\n */\nexport async function getImageBuffer(\n imagePath: string\n): Promise<ImageBufferResult> {\n // Check for base64 data URI first\n if (isBase64Image(imagePath)) {\n return { buffer: decodeBase64Image(imagePath) };\n }\n // Check for URL\n if (isValidUrl(imagePath)) {\n return await downloadImageFromUrl(imagePath);\n }\n // Otherwise treat as local file path, relative to the document's base\n // directory when the generation scope set one (falls back to cwd, #142).\n return { buffer: readFileSync(resolveFromBaseDir(imagePath)) };\n}\n\n/**\n * Get the dimensions of an image file or URL\n */\nexport async function getImageDimensions(\n imagePath: string\n): Promise<ImageDimensions> {\n try {\n const { buffer: imageBuffer } = await getImageBuffer(imagePath);\n const result = probe.sync(imageBuffer);\n\n if (!result) {\n throw new Error(`Unable to determine dimensions for image: ${imagePath}`);\n }\n\n return {\n width: result.width,\n height: result.height,\n };\n } catch (error) {\n throw new Error(\n `Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Calculate missing dimension while preserving aspect ratio\n */\nexport function calculateMissingDimension(\n originalWidth: number,\n originalHeight: number,\n targetWidth?: number,\n targetHeight?: number\n): CalculatedDimensions {\n if (targetWidth && targetHeight) {\n // Both dimensions provided, use as-is\n return { width: targetWidth, height: targetHeight };\n }\n\n const aspectRatio = originalWidth / originalHeight;\n\n if (targetWidth && !targetHeight) {\n // Width provided, calculate height\n return {\n width: targetWidth,\n height: Math.round(targetWidth / aspectRatio),\n };\n }\n\n if (!targetWidth && targetHeight) {\n // Height provided, calculate width\n return {\n width: Math.round(targetHeight * aspectRatio),\n height: targetHeight,\n };\n }\n\n // Neither provided, return original dimensions\n return { width: originalWidth, height: originalHeight };\n}\n\n/**\n * Calculate image dimensions with aspect ratio preservation and fallback constraints\n */\nexport async function calculateImageDimensions(\n imagePath: string,\n targetWidth?: number,\n targetHeight?: number,\n fallbackWidth: number = 300,\n fallbackHeight: number = 180\n): Promise<CalculatedDimensions> {\n try {\n const originalDimensions = await getImageDimensions(imagePath);\n return calculateMissingDimension(\n originalDimensions.width,\n originalDimensions.height,\n targetWidth,\n targetHeight\n );\n } catch (error) {\n // If we can't read the image, use fallback logic\n if (targetWidth && targetHeight) {\n return { width: targetWidth, height: targetHeight };\n }\n\n if (targetWidth && !targetHeight) {\n // Use a default aspect ratio (16:9) for fallback\n return { width: targetWidth, height: Math.round((targetWidth * 9) / 16) };\n }\n\n if (!targetWidth && targetHeight) {\n // Use a default aspect ratio (16:9) for fallback\n return {\n width: Math.round((targetHeight * 16) / 9),\n height: targetHeight,\n };\n }\n\n // No dimensions provided and can't read image, use fallback\n return { width: fallbackWidth, height: fallbackHeight };\n }\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { isAbsolute, resolve } from 'node:path';\nimport type { GenerationWarning } from '@json-to-office/shared';\n\nconst generationDateStorage = new AsyncLocalStorage<Date>();\n\n/** Scope render-time values without leaking them across concurrent documents. */\nexport function runWithGenerationDate<T>(date: Date, callback: () => T): T {\n return generationDateStorage.run(date, callback);\n}\n\n/** Current document date, falling back to the wall clock outside generation. */\nexport function getGenerationDate(): Date {\n return generationDateStorage.getStore() ?? new Date();\n}\n\nconst baseDirStorage = new AsyncLocalStorage<string>();\n\n/**\n * Scope the document base directory for a generation run, so relative asset\n * paths (`image.props.path` et al.) resolve against the document's own\n * location rather than `process.cwd()` (#142). No baseDir → plain callback,\n * preserving the historical cwd-relative behavior.\n */\nexport function runWithBaseDir<T>(\n baseDir: string | undefined,\n callback: () => T\n): T {\n return baseDir === undefined\n ? callback()\n : baseDirStorage.run(resolve(baseDir), callback);\n}\n\n/** The active document base directory, if a generation scope set one. */\nexport function getBaseDir(): string | undefined {\n return baseDirStorage.getStore();\n}\n\n/**\n * Resolve a relative file path against the active base directory. Absolute\n * paths pass through; with no active baseDir the path is returned as-is,\n * which downstream `fs` calls resolve against cwd — the legacy behavior.\n */\nexport function resolveFromBaseDir(filePath: string): string {\n const base = baseDirStorage.getStore();\n if (!base || isAbsolute(filePath)) return filePath;\n return resolve(base, filePath);\n}\n\nconst warningsStorage = new AsyncLocalStorage<GenerationWarning[]>();\n\n/**\n * Scope a warning collector for a render, so leaf utilities can report\n * without every intermediate signature carrying a sink. No collector → plain\n * callback, and `reportWarning` falls back to `console.warn` as before.\n */\nexport function runWithWarnings<T>(\n warnings: GenerationWarning[] | undefined,\n callback: () => T\n): T {\n return warnings === undefined\n ? callback()\n : warningsStorage.run(warnings, callback);\n}\n\n/** Record a render-time warning against the active collector, if any. */\nexport function reportWarning(\n component: string,\n code: string,\n message: string,\n context?: Record<string, unknown>\n): void {\n const warnings = warningsStorage.getStore();\n if (warnings) {\n warnings.push({\n component,\n message,\n severity: 'warning',\n context: { code, ...context },\n });\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] [${code}] ${message}`);\n}\n","import {\n IStylesOptions,\n IRunStylePropertiesOptions,\n IParagraphStylePropertiesOptions,\n AlignmentType,\n TabStopPosition,\n} from 'docx';\nimport { getTheme } from '../templates/themes';\nimport type { ThemeConfig } from './index';\nimport { resolveColor } from './utils/colorUtils';\nimport {\n convertLineSpacing,\n pointsToTwips,\n resolveFontProperties,\n mergeFontAndStyleProperties,\n} from './utils/styleHelpers';\n\n// Border types for paragraph borders in theme styles\ninterface ThemeBorderDefinition {\n style: string; // e.g., 'single', 'double', 'dotted', etc.\n size: number; // width in eighths of a point (docx sz)\n color: string; // hex or theme color key\n space?: number; // space in points\n}\n\ninterface ThemeBorders {\n top?: ThemeBorderDefinition;\n bottom?: ThemeBorderDefinition;\n left?: ThemeBorderDefinition;\n right?: ThemeBorderDefinition;\n /** w:between — the rule between consecutive paragraphs sharing this set. */\n between?: ThemeBorderDefinition;\n}\n\n// Style properties for various text elements\ninterface StyleProperties {\n font?: 'heading' | 'body' | 'mono' | 'light';\n size?: number;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n alignment?: 'left' | 'center' | 'right' | 'justify';\n lineSpacing?: {\n type: 'single' | 'atLeast' | 'exactly' | 'double' | 'multiple';\n value?: number;\n };\n spacing?: {\n before?: number;\n after?: number;\n };\n characterSpacing?: { type: 'condensed' | 'expanded'; value: number };\n scale?: number;\n priority?: number;\n baseStyle?: string;\n followingStyle?: string;\n widowControl?: boolean;\n keepNext?: boolean;\n keepLinesTogether?: boolean;\n outlineLevel?: number;\n borders?: ThemeBorders;\n indent?: {\n left?: number;\n hanging?: number;\n };\n}\n\n/**\n * Type-safe style name union\n */\ntype StyleName =\n | 'normal'\n | 'heading1'\n | 'heading2'\n | 'heading3'\n | 'heading4'\n | 'heading5'\n | 'heading6'\n | 'title'\n | 'subtitle';\n\n/**\n * Type guard to check if a style name is valid\n */\nfunction isValidStyleName(name: string): name is StyleName {\n return [\n 'normal',\n 'heading1',\n 'heading2',\n 'heading3',\n 'heading4',\n 'heading5',\n 'heading6',\n 'title',\n 'subtitle',\n ].includes(name);\n}\n\n/**\n * Type-safe style getter with proper error handling\n */\nfunction getStyleSafe(\n theme: ThemeConfig,\n styleName: string\n): StyleProperties | undefined {\n if (!isValidStyleName(styleName)) {\n console.warn(`Invalid style name: ${styleName}`);\n return undefined;\n }\n return theme.styles?.[styleName] as StyleProperties | undefined;\n}\n\n/**\n * Resolves a style with baseStyle inheritance.\n * If a style has a baseStyle property, recursively resolves the base style first\n * and merges its properties with the current style (current overrides base).\n *\n * @param theme - Theme configuration\n * @param styleName - Name of the style to resolve\n * @param visited - Set of visited style names to prevent circular references\n * @returns Resolved style with all inherited properties, or undefined if not found\n */\nfunction resolveStyleWithBaseStyle(\n theme: ThemeConfig,\n styleName: string,\n visited: Set<string> = new Set()\n): StyleProperties | undefined {\n // Prevent circular references\n if (visited.has(styleName)) {\n console.warn(\n `Circular baseStyle reference detected: ${Array.from(visited).join(\n ' → '\n )} → ${styleName}`\n );\n return undefined;\n }\n\n visited.add(styleName);\n\n // Use type-safe getter instead of type assertion\n const style = getStyleSafe(theme, styleName);\n if (!style) {\n return undefined;\n }\n\n // If no baseStyle, return style as-is\n if (!style.baseStyle) {\n return style;\n }\n\n // Recursively resolve base style\n const baseStyle = resolveStyleWithBaseStyle(\n theme,\n style.baseStyle,\n new Set(visited) // Pass copy to allow different branches\n );\n\n if (!baseStyle) {\n // If baseStyle doesn't exist, just return current style\n return style;\n }\n\n // Merge: base properties first, then override with current style properties\n // Filter out undefined values from current style to preserve base style values\n const mergedStyle = mergeFontAndStyleProperties(\n baseStyle,\n style\n ) as StyleProperties;\n\n // Manually merge properties not covered by mergeFontAndStyleProperties\n // Borders: inherit from baseStyle unless explicitly provided in current style\n if (style.borders === undefined && baseStyle.borders !== undefined) {\n mergedStyle.borders = baseStyle.borders;\n } else if (style.borders !== undefined) {\n mergedStyle.borders = style.borders;\n }\n\n return mergedStyle;\n}\n\nfunction convertAlignment(\n alignment: string\n): (typeof AlignmentType)[keyof typeof AlignmentType] {\n switch (alignment) {\n case 'center':\n return AlignmentType.CENTER;\n case 'right':\n return AlignmentType.RIGHT;\n case 'justify':\n return AlignmentType.JUSTIFIED;\n default:\n return AlignmentType.LEFT;\n }\n}\n\n/**\n * Resolve spacing from new nested format\n */\nfunction resolveSpacing(spacing?: { before?: number; after?: number }): {\n before?: number;\n after?: number;\n} {\n return {\n before: spacing?.before ? pointsToTwips(spacing.before) : undefined,\n after: spacing?.after ? pointsToTwips(spacing.after) : undefined,\n };\n}\n\n/**\n * Convert merged style properties to docx run properties\n */\nfunction convertRunProperties(\n merged: any,\n theme: ThemeConfig,\n defaultColor?: string,\n defaultSize?: number\n): IRunStylePropertiesOptions {\n return {\n font: merged.family || 'Arial',\n size: (merged.size || defaultSize || 11) * 2,\n color: resolveColor(\n merged.color || defaultColor || theme.colors.text,\n theme\n ),\n ...(merged.bold !== undefined && { bold: merged.bold }),\n ...(merged.italic !== undefined && { italic: merged.italic }),\n ...(merged.underline !== undefined &&\n merged.underline && { underline: { type: 'single' } }),\n ...(merged.characterSpacing && {\n characterSpacing:\n merged.characterSpacing.type === 'condensed'\n ? -merged.characterSpacing.value\n : merged.characterSpacing.value,\n }),\n ...(merged.scale && { scale: merged.scale }),\n };\n}\n\n/**\n * Convert merged style properties to docx paragraph properties\n */\nfunction convertParagraphProperties(\n merged: any,\n styleProps?: StyleProperties,\n theme?: ThemeConfig\n): IParagraphStylePropertiesOptions {\n return {\n spacing: {\n ...resolveSpacing(merged.spacing),\n ...convertLineSpacing(merged.lineSpacing),\n },\n alignment: convertAlignment(merged.alignment || 'left'),\n ...(styleProps?.keepNext !== undefined && {\n keepNext: styleProps.keepNext,\n }),\n ...(styleProps?.keepLinesTogether !== undefined && {\n keepLines: styleProps.keepLinesTogether,\n }),\n ...(styleProps?.widowControl !== undefined && {\n widowControl: styleProps.widowControl,\n }),\n ...(styleProps?.outlineLevel !== undefined && {\n outlineLevel: styleProps.outlineLevel,\n }),\n ...(styleProps?.borders &&\n theme && {\n border: convertBorders(styleProps.borders, theme),\n }),\n ...(styleProps?.indent && {\n indent: {\n ...(styleProps.indent.left !== undefined && {\n left: styleProps.indent.left,\n }),\n ...(styleProps.indent.hanging !== undefined && {\n hanging: styleProps.indent.hanging,\n }),\n },\n }),\n } as IParagraphStylePropertiesOptions;\n}\n\n/**\n * Convert theme border definitions to docx paragraph border options\n */\ntype ConvertedBorder = {\n style: string;\n size: number;\n color: string;\n space?: number;\n};\n\nfunction convertBorders(\n borders: ThemeBorders | undefined,\n theme: ThemeConfig\n): Partial<Record<keyof ThemeBorders, ConvertedBorder>> | undefined {\n if (!borders) return undefined;\n\n const mapSide = (side?: ThemeBorderDefinition) =>\n side\n ? {\n style: side.style,\n size: side.size,\n color: resolveColor(side.color, theme),\n ...(side.space !== undefined ? { space: side.space } : {}),\n }\n : undefined;\n\n const sides: (keyof ThemeBorders)[] = [\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'between',\n ];\n const converted: Partial<Record<keyof ThemeBorders, ConvertedBorder>> = {};\n for (const side of sides) {\n const value = mapSide(borders[side]);\n if (value) converted[side] = value;\n }\n\n return Object.keys(converted).length > 0 ? converted : undefined;\n}\n\nexport interface WordStyleDefinition {\n id: string;\n name: string;\n basedOn?: string;\n next?: string;\n quickFormat?: boolean;\n run?: IRunStylePropertiesOptions;\n paragraph?: IParagraphStylePropertiesOptions;\n}\n\n/**\n * Creates Word document styles from theme configuration\n * @param themeNameOrObject The theme to use for styling (name string or theme object)\n * @returns IStylesOptions for docx Document\n */\nexport function createWordStyles(\n themeNameOrObject: string | ThemeConfig = 'minimal',\n language?: string\n): IStylesOptions {\n const theme: ThemeConfig =\n typeof themeNameOrObject === 'string'\n ? getTheme(themeNameOrObject) || getTheme('minimal')!\n : themeNameOrObject;\n\n const paragraphStyles: WordStyleDefinition[] = [\n // Normal body text style\n {\n id: 'Normal',\n name: 'Normal',\n quickFormat: true,\n run: (() => {\n const normalStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const fontProps = resolveFontProperties(theme, normalStyle?.font);\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: normalStyle?.size,\n color: normalStyle?.color,\n bold: normalStyle?.bold,\n italic: normalStyle?.italic,\n underline: normalStyle?.underline,\n characterSpacing: normalStyle?.characterSpacing,\n scale: normalStyle?.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.text);\n })(),\n paragraph: (() => {\n const normalStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const fontProps = resolveFontProperties(theme, normalStyle?.font);\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: normalStyle?.alignment,\n lineSpacing: normalStyle?.lineSpacing,\n spacing: normalStyle?.spacing,\n });\n\n return convertParagraphProperties(merged, normalStyle, theme);\n })(),\n },\n ];\n\n // Generate heading styles from theme configuration\n for (let i = 1; i <= 6; i++) {\n const headingKey = `heading${i}` as keyof typeof theme.styles;\n const rawHeadingStyle = theme.styles?.[headingKey] as\n | StyleProperties\n | undefined;\n\n if (rawHeadingStyle) {\n const headingStyle =\n resolveStyleWithBaseStyle(theme, headingKey) || rawHeadingStyle;\n paragraphStyles.push({\n id: `Heading${i}`,\n name: `Heading ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: headingStyle.size,\n color: headingStyle.color,\n bold: headingStyle.bold,\n italic: headingStyle.italic,\n underline: headingStyle.underline,\n characterSpacing: headingStyle.characterSpacing,\n scale: headingStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: headingStyle.alignment,\n lineSpacing: headingStyle.lineSpacing,\n spacing: headingStyle.spacing,\n });\n\n return convertParagraphProperties(merged, headingStyle, theme);\n })(),\n });\n } else {\n // Fallback heading style if not defined in theme\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: `Heading${i}`,\n name: `Heading ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: {\n font: fontProps.family || 'Arial',\n size: (fontProps.size || 20) * 2,\n color: resolveColor(fontProps.color || theme.colors.primary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n ...(fontProps.underline !== undefined &&\n fontProps.underline && { underline: { type: 'single' } }),\n },\n paragraph: {\n spacing: {\n before: 240 - (i - 1) * 40,\n after: 120 - (i - 1) * 20,\n ...convertLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n }\n\n // Generate display-only heading styles for text components (non-TOC, non-outline)\n for (let i = 1; i <= 6; i++) {\n const headingKey = `heading${i}` as keyof typeof theme.styles;\n const rawHeadingStyle = theme.styles?.[headingKey] as\n | StyleProperties\n | undefined;\n\n if (rawHeadingStyle) {\n const headingStyle =\n resolveStyleWithBaseStyle(theme, `heading${i}`) || rawHeadingStyle;\n\n paragraphStyles.push({\n id: `JTD_HeadingText${i}`,\n name: `Heading Text ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: headingStyle.size,\n color: headingStyle.color,\n bold: headingStyle.bold,\n italic: headingStyle.italic,\n underline: headingStyle.underline,\n characterSpacing: headingStyle.characterSpacing,\n scale: headingStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: headingStyle.alignment,\n lineSpacing: headingStyle.lineSpacing,\n spacing: headingStyle.spacing,\n });\n\n // Explicitly drop outlineLevel to avoid TOC participation\n return convertParagraphProperties(\n merged,\n { ...(headingStyle as any), outlineLevel: undefined },\n theme\n );\n })(),\n });\n } else {\n // Fallback display heading style mirrors fallback heading visuals\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: `JTD_HeadingText${i}`,\n name: `Heading Text ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: {\n font: fontProps.family || 'Arial',\n size: (fontProps.size || 20) * 2,\n color: resolveColor(fontProps.color || theme.colors.primary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n ...(fontProps.underline !== undefined &&\n fontProps.underline && { underline: { type: 'single' } }),\n },\n paragraph: {\n spacing: {\n before: 240 - (i - 1) * 40,\n after: 120 - (i - 1) * 20,\n ...convertLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n }\n\n // Add Title style from theme configuration\n if (theme.styles?.title) {\n const titleStyle =\n resolveStyleWithBaseStyle(theme, 'title') || theme.styles.title;\n paragraphStyles.push({\n id: 'Title',\n name: 'Title',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n titleStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: titleStyle.size,\n color: titleStyle.color,\n bold: titleStyle.bold,\n italic: titleStyle.italic,\n underline: titleStyle.underline,\n characterSpacing: titleStyle.characterSpacing,\n scale: titleStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n titleStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: titleStyle.alignment,\n lineSpacing: titleStyle.lineSpacing,\n spacing: titleStyle.spacing,\n });\n\n return convertParagraphProperties(merged, titleStyle, theme);\n })(),\n });\n } else {\n // Fallback title style if no theme configuration\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: 'Title',\n name: 'Title',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: {\n font: fontProps.family || 'Arial',\n size: (fontProps.size || 20) * 2,\n color: resolveColor(fontProps.color || theme.colors.primary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n ...(fontProps.underline !== undefined &&\n fontProps.underline && { underline: { type: 'single' } }),\n },\n paragraph: {\n spacing: {\n after: 400,\n ...convertLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n\n // Add Subtitle style from theme configuration\n if (theme.styles?.subtitle) {\n const subtitleStyle =\n resolveStyleWithBaseStyle(theme, 'subtitle') || theme.styles.subtitle;\n paragraphStyles.push({\n id: 'Subtitle',\n name: 'Subtitle',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n subtitleStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: subtitleStyle.size,\n color: subtitleStyle.color,\n bold: subtitleStyle.bold,\n italic: subtitleStyle.italic,\n underline: subtitleStyle.underline,\n characterSpacing: subtitleStyle.characterSpacing,\n scale: subtitleStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.secondary);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n subtitleStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: subtitleStyle.alignment,\n lineSpacing: subtitleStyle.lineSpacing,\n spacing: subtitleStyle.spacing,\n });\n\n return convertParagraphProperties(merged, subtitleStyle, theme);\n })(),\n });\n } else {\n // Fallback subtitle style if no theme configuration\n const fontProps = resolveFontProperties(theme, 'body');\n paragraphStyles.push({\n id: 'Subtitle',\n name: 'Subtitle',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: {\n font: fontProps.family || 'Arial',\n size: (fontProps.size || 11) * 2,\n color: resolveColor(fontProps.color || theme.colors.secondary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n ...(fontProps.underline !== undefined &&\n fontProps.underline && { underline: { type: 'single' } }),\n },\n paragraph: {\n spacing: {\n after: 600,\n ...convertLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n\n paragraphStyles.push(\n // Header style\n (() => {\n const fontProps = resolveFontProperties(theme, 'body');\n return {\n id: 'Header',\n name: 'Header',\n basedOn: 'Normal',\n next: 'Header',\n quickFormat: false,\n run: {\n font: fontProps.family || 'Arial',\n size: 20, // 10pt (override default)\n color: resolveColor(fontProps.color || theme.colors.secondary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n },\n paragraph: {\n alignment: 'right',\n },\n };\n })(),\n\n // Footer style\n (() => {\n const fontProps = resolveFontProperties(theme, 'body');\n return {\n id: 'Footer',\n name: 'Footer',\n basedOn: 'Normal',\n next: 'Footer',\n quickFormat: false,\n run: {\n font: fontProps.family || 'Arial',\n size: 18, // 9pt (override default)\n color: resolveColor(fontProps.color || theme.colors.secondary, theme),\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n },\n paragraph: {\n spacing: {\n before: 120,\n },\n alignment: 'center',\n // Note: Borders are applied at the paragraph instance level, not in style definitions\n },\n };\n })()\n );\n\n // Process custom styles (any additional keys in theme.styles beyond predefined ones)\n const predefinedStyleKeys = new Set([\n 'normal',\n 'heading1',\n 'heading2',\n 'heading3',\n 'heading4',\n 'heading5',\n 'heading6',\n 'title',\n 'subtitle',\n ]);\n\n if (theme.styles) {\n for (const [styleKey, styleValue] of Object.entries(theme.styles)) {\n // Skip predefined styles (already processed above)\n if (predefinedStyleKeys.has(styleKey)) {\n continue;\n }\n\n // Skip if styleValue is not defined\n if (!styleValue) {\n continue;\n }\n\n // Generate Word-compatible style ID and name\n // Special-case TOC styles to the canonical Word display name (e.g., 'TOC 1')\n const tocMatch = /^TOC([1-9])$/.exec(styleKey);\n\n // For TOC styles, DO NOT resolve baseStyle inheritance to prevent coupling with Heading styles\n // TOC styles should only use their explicitly defined properties\n const customStyle = tocMatch\n ? styleValue\n : resolveStyleWithBaseStyle(theme, styleKey) || styleValue;\n // Canonical Word style id. docx hardcodes `w:pStyle w:val=\"TOC{level}\"`\n // when it writes cached TOC entries, so a namespaced id would leave those\n // entries unstyled. docx's own default styles define no TOC id, so there\n // is nothing to collide with.\n const styleId = tocMatch ? `TOC${tocMatch[1]}` : styleKey;\n const styleName = tocMatch\n ? `TOC ${tocMatch[1]}`\n : styleKey.replace(/([A-Z])/g, ' $1').trim(); // Convert camelCase/PascalCase to Title Case\n\n // Helper: map baseStyle (theme key) to Word style ID\n const mapBaseStyleId = (base?: string) => {\n if (!base) return 'Normal';\n const lower = base.toLowerCase();\n if (lower === 'normal') return 'Normal';\n if (lower === 'title') return 'Title';\n if (lower === 'subtitle') return 'Subtitle';\n const m = lower.match(/^heading([1-6])$/);\n if (m) return `Heading${m[1]}`;\n // Assume custom style ID (already registered with same id)\n return base;\n };\n\n paragraphStyles.push({\n id: styleId,\n name: styleName,\n basedOn: tocMatch\n ? 'Normal'\n : mapBaseStyleId((customStyle as StyleProperties).baseStyle),\n next: customStyle.followingStyle || 'Normal',\n quickFormat: tocMatch\n ? false\n : customStyle.priority !== undefined\n ? true\n : false,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n customStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: customStyle.size,\n color: customStyle.color,\n bold: customStyle.bold,\n italic: customStyle.italic,\n underline: customStyle.underline,\n characterSpacing: customStyle.characterSpacing,\n scale: customStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.text);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n customStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: customStyle.alignment,\n lineSpacing: customStyle.lineSpacing,\n spacing: customStyle.spacing,\n });\n\n // Build base properties using converter\n const baseProps = convertParagraphProperties(\n merged,\n // Don't pass outlineLevel for TOC styles\n tocMatch\n ? { ...customStyle, outlineLevel: undefined }\n : customStyle,\n theme\n );\n\n // Add TOC-specific tab stops if needed\n const tabStops = (customStyle as any).tabStops;\n const defaultTocTabStops = tocMatch\n ? [{ type: 'right', position: 'max', leader: 'none' }]\n : undefined;\n const effectiveTabStops =\n tabStops && tabStops.length > 0 ? tabStops : defaultTocTabStops;\n\n return {\n ...baseProps,\n ...(effectiveTabStops && {\n tabStops: effectiveTabStops.map((ts: any) => ({\n type: ts.type,\n position:\n ts.position === 'max' ? TabStopPosition.MAX * 2 : ts.position,\n ...(ts.leader && { leader: ts.leader }),\n })),\n }),\n } as IParagraphStylePropertiesOptions;\n })(),\n });\n }\n }\n\n // Generate TOC level styles (TOC 1..6) using fixed, sober defaults.\n // These defaults do not depend on theme heading styles.\n for (let i = 1; i <= 6; i++) {\n // Skip if user already provided a custom TOC style via theme.styles (id must be 'TOC1'..'TOC6')\n if (\n theme.styles &&\n Object.prototype.hasOwnProperty.call(theme.styles, `TOC${i}`)\n ) {\n continue;\n }\n\n paragraphStyles.push({\n // Canonical id and display name — see the styleId note above.\n id: `TOC${i}`,\n name: `TOC ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: {\n font: 'Arial',\n size: 22, // 11pt\n color: resolveColor(theme.colors.text, theme),\n },\n paragraph: {\n spacing: {\n ...resolveSpacing({ before: 0, after: 6 }), // 0pt before, 6pt after\n },\n alignment: convertAlignment('left'),\n // Increase left indent per level for visual hierarchy\n indent: { left: (i - 1) * 360 }, // 0.25\" per level (360 twips)\n },\n });\n }\n\n // Note styles: docx ships built-in Footnote/Endnote Text and Reference\n // styles, but they carry Word's defaults, not the theme's — a note in a\n // Georgia document would otherwise set in Calibri. All four hooks live under\n // the `default` key, which is why that key is now always built rather than\n // being emitted only when a document language is set.\n const noteStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const bodyRun = convertRunProperties(\n mergeFontAndStyleProperties(resolveFontProperties(theme, noteStyle?.font), {\n size: noteStyle?.size,\n color: noteStyle?.color,\n }),\n theme,\n theme.colors.text\n );\n // Word's convention is note text two points below body text. `size` is in\n // half-points here, so that is four — floored so a tiny body size cannot\n // produce an illegible note.\n const noteRun = {\n ...bodyRun,\n ...(typeof bodyRun.size === 'number' && {\n size: Math.max(12, bodyRun.size - 4),\n }),\n };\n\n return {\n paragraphStyles: paragraphStyles as WordStyleDefinition[], // Cast needed due to docx typing\n default: {\n // Document-default proofing language (w:docDefaults/w:rPrDefault). Runs\n // that don't set their own w:lang inherit this, so Word spell-checks the\n // whole document in the requested language unless a component overrides\n // it.\n ...(language && {\n document: {\n run: {\n language: { value: language },\n },\n },\n }),\n // Run properties only: docx's own note paragraph defaults (single line\n // spacing, no space after) are already what a note wants, and an empty\n // spacing override would drop its line rule.\n footnoteText: { run: noteRun },\n footnoteReference: { run: { ...noteRun, superScript: true } },\n endnoteText: { run: noteRun },\n endnoteReference: { run: { ...noteRun, superScript: true } },\n },\n };\n}\n\n/**\n * Maps section levels to Word style IDs\n */\nexport function getStyleIdForLevel(level: number): string {\n const styleMap: { [key: number]: string } = {\n 1: 'Heading1',\n 2: 'Heading2',\n 3: 'Heading3',\n 4: 'Heading4',\n 5: 'Heading5',\n 6: 'Heading6',\n };\n return styleMap[level] || 'Heading1';\n}\n","/**\n * Cache Module Exports\n * Re-exports format-agnostic cache from shared + local key-generator\n */\n\nexport * from '@json-to-office/shared/cache';\nexport { CacheKeyGenerator } from './key-generator';\n","/**\n * Cache Key Generator\n * Generates deterministic cache keys for components\n */\n\nimport { createHash } from 'crypto';\nimport { ComponentDefinition, RenderContext } from '../types';\nimport { CacheKeyOptions } from '@json-to-office/shared/cache';\n\n/**\n * Cache key generator with deterministic hashing\n */\nexport class CacheKeyGenerator {\n private readonly version: string;\n\n constructor(version: string = '1.0') {\n this.version = version;\n }\n\n /**\n * Generate cache key for a component\n */\n generateKey(\n component: ComponentDefinition,\n context: RenderContext,\n options: CacheKeyOptions = {}\n ): string {\n const parts: string[] = [\n this.version,\n component.name,\n this.hashProps(component.props),\n ];\n\n if (options.includeTheme !== false) {\n parts.push(context.theme.name);\n }\n\n if (options.includeContext) {\n parts.push(this.hashContext(context));\n }\n\n if (options.additionalKeys) {\n parts.push(...options.additionalKeys);\n }\n\n if (options.version) {\n parts.push(options.version);\n }\n\n return parts.join(':');\n }\n\n /**\n * Hash component props\n */\n hashProps(props: any): string {\n if (!props) return 'null';\n\n // Sort keys for consistent hashing\n const normalized = this.normalizeObject(props);\n const json = JSON.stringify(normalized);\n\n return this.hash(json);\n }\n\n /**\n * Hash render context\n */\n private hashContext(context: RenderContext): string {\n // Only hash relevant context properties\n const relevant = {\n theme: context.theme.name,\n document: context.document,\n // Exclude runtime properties like sectionIndex, componentIndex\n };\n\n return this.hash(JSON.stringify(relevant));\n }\n\n /**\n * Normalize object for consistent hashing\n */\n private normalizeObject(obj: any): any {\n if (obj === null || obj === undefined) return obj;\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.normalizeObject(item));\n }\n\n if (obj instanceof Date) {\n return obj.toISOString();\n }\n\n if (typeof obj === 'object') {\n const sorted: any = {};\n const keys = Object.keys(obj).sort();\n\n for (const key of keys) {\n sorted[key] = this.normalizeObject(obj[key]);\n }\n\n return sorted;\n }\n\n return obj;\n }\n\n /**\n * Create hash\n */\n private hash(input: string): string {\n return createHash('sha256').update(input).digest('hex').substring(0, 16); // Use first 16 chars for shorter keys\n }\n}\n","/**\n * Revision (tracked-change) rendering utilities\n *\n * Turns `revision.segments` from the JSON definition into native Word\n * revision runs (w:ins / w:del) via docx.js InsertedTextRun / DeletedTextRun.\n */\n\nimport { TextRun, InsertedTextRun, DeletedTextRun } from 'docx';\nimport type { IRunOptions, ParagraphChild } from 'docx';\nimport type { Revision, RevisionMark } from '@json-to-office/shared-docx';\nimport { normalizeUnicodeText } from './unicode';\nimport { processTextWithPlaceholders } from './placeholderProcessor';\nimport type { TextStyle } from './textParser';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport {\n componentHasAnnotation,\n type MaybeComponent,\n} from './componentAnnotations';\n\nexport const DEFAULT_REVISION_AUTHOR = 'json-to-office';\n// Deterministic fallback so identical inputs produce byte-identical XML\nexport const DEFAULT_REVISION_DATE = '1970-01-01T00:00:00Z';\n\n/**\n * OOXML requires a numeric id on every w:ins / w:del element, unique within\n * one document. Async-local state gives each render its own deterministic\n * counter without collisions when documents render concurrently.\n */\nclass RevisionIdRegistry {\n private fallbackCounter = 0;\n private readonly scopes = new AsyncLocalStorage<{ counter: number }>();\n\n runScoped<T>(callback: () => T): T {\n return this.scopes.run({ counter: 0 }, callback);\n }\n\n next(): number {\n const state = this.scopes.getStore();\n if (state) {\n state.counter += 1;\n return state.counter;\n }\n this.fallbackCounter += 1;\n return this.fallbackCounter;\n }\n\n /** Test-only: deterministic ids for snapshot assertions. */\n clear(): void {\n const state = this.scopes.getStore();\n if (state) {\n state.counter = 0;\n } else {\n this.fallbackCounter = 0;\n }\n }\n}\n\nexport const globalRevisionIdRegistry = new RevisionIdRegistry();\n\nexport type RevisionRun = TextRun | InsertedTextRun | DeletedTextRun;\n\nconst PLACEHOLDER_PATTERN = /\\{[^}]+\\}/;\n\ntype RevisionBaseStyle = Omit<IRunOptions, 'text' | 'children'>;\n\n/**\n * Build the runs for one segment, splitting on '\\n' so line breaks render\n * as <w:br/> (mirroring createTextRunsWithNewlines on the normal path).\n */\nfunction segmentRuns(\n text: string,\n makeRun: (options: IRunOptions) => RevisionRun\n): RevisionRun[] {\n const lines = text.split('\\n');\n return lines.map((line, index) =>\n makeRun(index === 0 ? { text: line } : { text: line, break: 1 })\n );\n}\n\n/**\n * Build paragraph children from revision segments.\n *\n * Segment text is rendered literally (no markdown parsing): a `**` opened in\n * one segment could close in another, so decorator parsing cannot work\n * per-segment. The diff engine strips markdown before diffing for this\n * reason. Placeholders ({DATE}, {PAGE}, ...) are resolved for unchanged\n * segments; inside inserted/deleted text they render literally (the diff\n * summary reports those).\n */\nexport function createRevisionRuns(\n revision: Revision,\n baseStyle: RevisionBaseStyle\n): ParagraphChild[] {\n const author = revision.author || DEFAULT_REVISION_AUTHOR;\n const date = revision.date || DEFAULT_REVISION_DATE;\n\n const runs: ParagraphChild[] = [];\n for (const segment of revision.segments) {\n if (!segment.text) continue;\n const text = normalizeUnicodeText(segment.text);\n\n if (segment.type === 'insert') {\n runs.push(\n ...segmentRuns(\n text,\n (options) =>\n new InsertedTextRun({\n ...options,\n ...baseStyle,\n id: globalRevisionIdRegistry.next(),\n author,\n date,\n })\n )\n );\n } else if (segment.type === 'delete') {\n runs.push(\n ...segmentRuns(\n text,\n (options) =>\n new DeletedTextRun({\n ...options,\n ...baseStyle,\n id: globalRevisionIdRegistry.next(),\n author,\n date,\n })\n )\n );\n } else if (PLACEHOLDER_PATTERN.test(text)) {\n // Unchanged text keeps full placeholder fidelity ({DATE}, {PAGE}, ...)\n runs.push(\n ...processTextWithPlaceholders(text, baseStyle as TextStyle, {})\n );\n } else {\n runs.push(\n ...segmentRuns(\n text,\n (options) => new TextRun({ ...options, ...baseStyle })\n )\n );\n }\n }\n return runs;\n}\n\n/**\n * True when a component carries revision data anywhere in its subtree,\n * meaning its render output embeds document-scoped w:ins/w:del ids and must not\n * be served from the cross-document component cache.\n */\nexport function componentHasRevision(component: MaybeComponent): boolean {\n return componentHasAnnotation(component, 'revision');\n}\n\n/** docx's shape for a structural tracked change (`w:ins` / `w:del` attrs). */\nexport interface RevisionMarkAttributes {\n id: number;\n author: string;\n date: string;\n}\n\n/**\n * Turn a structural revision into the attribute triple docx wants, allocating\n * the document-scoped id.\n *\n * Callers must invoke this in a synchronous prefix — before any `await` — or\n * ids end up ordered by I/O completion rather than document order.\n */\nexport function createRevisionMark(mark: RevisionMark): {\n insertion?: RevisionMarkAttributes;\n deletion?: RevisionMarkAttributes;\n} {\n const attributes: RevisionMarkAttributes = {\n id: globalRevisionIdRegistry.next(),\n author: mark.author || DEFAULT_REVISION_AUTHOR,\n date: mark.date || DEFAULT_REVISION_DATE,\n };\n return mark.type === 'insert'\n ? { insertion: attributes }\n : { deletion: attributes };\n}\n\n/**\n * Render a cell's text as runs that are wholly inserted or wholly deleted,\n * matching the structural mark on the row they sit in.\n *\n * A `w:trPr/w:del` alone leaves the cell text un-struck, and accepting the\n * change would leave an empty row behind rather than removing it. Word needs\n * both halves: the row mark and every run inside it marked the same way.\n */\nexport function createMarkedTextRuns(\n text: string,\n mark: RevisionMark,\n baseStyle: RevisionBaseStyle\n): ParagraphChild[] {\n return createRevisionRuns(\n {\n author: mark.author,\n date: mark.date,\n segments: [{ type: mark.type, text }],\n },\n baseStyle\n );\n}\n","/**\n * Normalize text to NFC so composed accented characters are preserved\n * consistently across DOCX renderers (including LibreOffice).\n */\nexport function normalizeUnicodeText(text: string | null | undefined): string {\n return (text ?? '').normalize('NFC');\n}\n","/**\n * Placeholder Processing System\n * Handles dynamic content replacement in text with support for rich text formatting\n */\n\nimport {\n TextRun,\n PageNumber,\n ExternalHyperlink,\n InternalHyperlink,\n FootnoteReferenceRun,\n EndnoteReferenceRun,\n SimpleField,\n} from 'docx';\nimport {\n parseTextWithDecorators,\n buildRunCommonProps,\n buildTextRuns,\n TextStyle,\n} from './textParser';\nimport { normalizeUnicodeText } from './unicode';\nimport { getGenerationDate } from './generationContext';\n\n// Type alias for elements that can appear in a paragraph\nexport type PlaceholderChild =\n | TextRun\n | ExternalHyperlink\n | InternalHyperlink\n // A `[^id]` note marker resolves to a reference run mid-text.\n | FootnoteReferenceRun\n | EndnoteReferenceRun\n // A `[@id]` cross-reference resolves to a REF field (NumberedItemReference).\n | SimpleField;\n\n/**\n * Placeholder handler function type\n */\nexport type PlaceholderHandler = (\n _context?: PlaceholderContext\n) => PlaceholderChild | PlaceholderChild[] | string;\n\n/**\n * Context passed to placeholder handlers\n */\nexport interface PlaceholderContext {\n style?: TextStyle;\n date?: Date;\n [key: string]: unknown;\n}\n\nfunction styledPlaceholderText(\n text: string,\n context?: PlaceholderContext\n): TextRun {\n return new TextRun({\n text,\n font: context?.style?.font,\n size: context?.style?.size,\n color: context?.style?.color,\n bold: context?.style?.bold,\n italics: context?.style?.italics,\n underline: context?.style?.underline,\n language: context?.style?.language,\n noProof: context?.style?.noProof,\n });\n}\n\nfunction placeholderDate(context?: PlaceholderContext): Date {\n return context?.date ?? getGenerationDate();\n}\n\nfunction isoDate(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nfunction isoDateTime(date: Date): string {\n return date\n .toISOString()\n .replace('T', ' ')\n .replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * Placeholder registry for managing dynamic content\n */\nexport class PlaceholderRegistry {\n private static handlers = new Map<string, PlaceholderHandler>();\n\n /**\n * Register a placeholder handler\n */\n static register(name: string, handler: PlaceholderHandler): void {\n this.handlers.set(name.toUpperCase(), handler);\n }\n\n /**\n * Get a placeholder handler\n */\n static get(name: string): PlaceholderHandler | undefined {\n return this.handlers.get(name.toUpperCase());\n }\n\n /**\n * Check if a placeholder is registered\n */\n static has(name: string): boolean {\n return this.handlers.has(name.toUpperCase());\n }\n\n /**\n * Get all registered placeholder names\n */\n static getRegisteredNames(): string[] {\n return Array.from(this.handlers.keys());\n }\n\n /**\n * Clear all registered placeholders\n */\n static clear(): void {\n this.handlers.clear();\n }\n}\n\n/**\n * Process text containing placeholders and return array of paragraph children\n */\nexport function processPlaceholders(\n text: string,\n baseStyle: TextStyle = {},\n context: PlaceholderContext = {}\n): PlaceholderChild[] {\n const normalizedText = normalizeUnicodeText(text);\n const placeholderRegex = /\\{([^}]+)\\}/g;\n const result: PlaceholderChild[] = [];\n let lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = placeholderRegex.exec(normalizedText)) !== null) {\n const beforeText = normalizedText.substring(lastIndex, match.index);\n const placeholderName = match[1];\n\n // Add text before placeholder\n if (beforeText) {\n result.push(...parseTextWithDecorators(beforeText, baseStyle));\n }\n\n // Process placeholder\n const handler = PlaceholderRegistry.get(placeholderName);\n if (handler) {\n const placeholderResult = handler({ ...context, style: baseStyle });\n\n if (Array.isArray(placeholderResult)) {\n result.push(...placeholderResult);\n } else if (typeof placeholderResult === 'string') {\n result.push(...parseTextWithDecorators(placeholderResult, baseStyle));\n } else {\n result.push(placeholderResult);\n }\n } else {\n // Unknown placeholder - keep as text\n result.push(...parseTextWithDecorators(match[0], baseStyle));\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Add remaining text\n if (lastIndex < normalizedText.length) {\n const remainingText = normalizedText.substring(lastIndex);\n result.push(...parseTextWithDecorators(remainingText, baseStyle));\n }\n\n // If no placeholders found, process as normal text\n if (result.length === 0) {\n result.push(...parseTextWithDecorators(normalizedText, baseStyle));\n }\n\n return result;\n}\n\n/**\n * Process text with both decorators and placeholders\n */\nexport function processTextWithPlaceholders(\n text: string,\n baseStyle: TextStyle = {},\n context: PlaceholderContext = {},\n noProofWords?: string[]\n): PlaceholderChild[] {\n const normalizedText = normalizeUnicodeText(text);\n // Use a more sophisticated approach to handle both decorators and placeholders\n // This regex captures both markdown decorators and placeholders\n const combinedRegex =\n /(\\*\\*\\*|___)([\\s\\S]*?)\\1|(\\*\\*|__)([\\s\\S]*?)\\3|(\\*|_)([\\s\\S]*?)\\5|\\{([^}]+)\\}/g;\n const result: PlaceholderChild[] = [];\n let lastIndex = 0;\n\n let match: RegExpExecArray | null;\n while ((match = combinedRegex.exec(normalizedText)) !== null) {\n // Add any text before the match as plain text\n if (match.index > lastIndex) {\n const beforeText = normalizedText.substring(lastIndex, match.index);\n if (beforeText) {\n result.push(\n ...createTextRunsWithNewlines(beforeText, baseStyle, noProofWords)\n );\n }\n }\n\n // Check if this is a placeholder (group 7)\n if (match[7]) {\n const placeholderName = match[7];\n const handler = PlaceholderRegistry.get(placeholderName);\n if (handler) {\n const placeholderResult = handler({ ...context, style: baseStyle });\n\n if (Array.isArray(placeholderResult)) {\n result.push(...placeholderResult);\n } else if (typeof placeholderResult === 'string') {\n result.push(\n ...createTextRunsWithNewlines(\n placeholderResult,\n baseStyle,\n noProofWords\n )\n );\n } else {\n result.push(placeholderResult);\n }\n } else {\n // Unknown placeholder - keep as text\n result.push(\n ...createTextRunsWithNewlines(match[0], baseStyle, noProofWords)\n );\n }\n } else {\n // This is a decorator match - determine the style\n let decoratedText: string;\n let bold = baseStyle.bold || false;\n let italics = baseStyle.italics || false;\n\n if (match[1] === '***' || match[1] === '___') {\n // Bold + Italic\n decoratedText = match[2];\n bold = true;\n italics = true;\n } else if (match[3] === '**' || match[3] === '__') {\n // Bold\n decoratedText = match[4];\n bold = true;\n } else if (match[5] === '*' || match[5] === '_') {\n // Italic\n decoratedText = match[6];\n italics = true;\n } else {\n // This shouldn't happen with our regex, but just in case\n decoratedText = match[0];\n }\n\n // Recursively process the decorated text (it might contain placeholders)\n const decoratedTextRuns = processTextWithPlaceholders(\n decoratedText,\n {\n ...baseStyle,\n bold,\n italics,\n },\n context\n );\n result.push(...decoratedTextRuns);\n }\n\n lastIndex = match.index + match[0].length;\n }\n\n // Add any remaining text after the last match\n if (lastIndex < normalizedText.length) {\n const remainingText = normalizedText.substring(lastIndex);\n if (remainingText) {\n result.push(\n ...createTextRunsWithNewlines(remainingText, baseStyle, noProofWords)\n );\n }\n }\n\n // If no matches were found, return text runs with newlines\n if (result.length === 0 && normalizedText) {\n result.push(\n ...createTextRunsWithNewlines(normalizedText, baseStyle, noProofWords)\n );\n }\n\n return result;\n}\n\n/**\n * Helper function to create TextRuns with newlines from text\n */\nfunction createTextRunsWithNewlines(\n text: string,\n baseStyle: TextStyle,\n noProofWords?: string[]\n): TextRun[] {\n return buildTextRuns(text, buildRunCommonProps(baseStyle), {\n noProof: baseStyle.noProof,\n noProofWords,\n });\n}\n\n/**\n * Initialize built-in placeholders\n */\nexport function initializeBuiltinPlaceholders(): void {\n // PAGE placeholder\n PlaceholderRegistry.register('PAGE', (context) => {\n return new TextRun({\n children: [PageNumber.CURRENT],\n font: context?.style?.font,\n size: context?.style?.size,\n color: context?.style?.color,\n bold: context?.style?.bold,\n italics: context?.style?.italics,\n underline: context?.style?.underline,\n });\n });\n\n // TOTAL_PAGES placeholder\n PlaceholderRegistry.register('TOTAL_PAGES', (context) => {\n return new TextRun({\n children: [PageNumber.TOTAL_PAGES],\n font: context?.style?.font,\n size: context?.style?.size,\n color: context?.style?.color,\n bold: context?.style?.bold,\n italics: context?.style?.italics,\n underline: context?.style?.underline,\n });\n });\n\n // DATE placeholder\n PlaceholderRegistry.register('DATE', (context) =>\n styledPlaceholderText(isoDate(placeholderDate(context)), context)\n );\n\n // DATETIME placeholder\n PlaceholderRegistry.register('DATETIME', (context) =>\n styledPlaceholderText(isoDateTime(placeholderDate(context)), context)\n );\n\n // YEAR placeholder\n PlaceholderRegistry.register('YEAR', (context) =>\n styledPlaceholderText(\n String(placeholderDate(context).getUTCFullYear()),\n context\n )\n );\n}\n\n// Initialize built-in placeholders\ninitializeBuiltinPlaceholders();\n","import {\n TextRun,\n ExternalHyperlink,\n InternalHyperlink,\n FootnoteReferenceRun,\n EndnoteReferenceRun,\n NumberedItemReference,\n NumberedItemReferenceFormat,\n Tab,\n} from 'docx';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n type PlaceholderContext,\n} from './placeholderProcessor';\nimport { normalizeUnicodeText } from './unicode';\nimport { globalNumberedItemsRegistry } from './numberedItemsRegistry';\n\nexport interface TextStyle {\n font?: string;\n size?: number;\n color?: string;\n bold?: boolean;\n italics?: boolean;\n underline?: {\n type?:\n | 'single'\n | 'double'\n | 'thick'\n | 'dotted'\n | 'dash'\n | 'dotDash'\n | 'dotDotDash'\n | 'wave'\n | 'none'\n | 'words'\n | 'dottedHeavy'\n | 'dashedHeavy'\n | 'dashLong'\n | 'dashLongHeavy'\n | 'dashDotHeavy'\n | 'dashDotDotHeavy'\n | 'wavyHeavy'\n | 'wavyDouble';\n color?: string;\n }; // docx library expects an object or undefined, not boolean\n // Character width scaling in percent (w:w). 100 is normal.\n scale?: number;\n // Letter tracking (w:spacing) in twentieths of a point (signed).\n characterSpacing?: number;\n // Proofing language (BCP-47) for the run, e.g. { value: 'fr-FR' }\n language?: {\n value?: string;\n eastAsia?: string;\n bidirectional?: string;\n };\n // Disable spell/grammar checking for the run\n noProof?: boolean;\n}\n\nexport interface TextDecoratorOptions {\n boldColor?: string;\n placeholderContext?: PlaceholderContext;\n enableHyperlinks?: boolean;\n /**\n * \"Known words\" allowlist: each whole-word, case-insensitive occurrence is\n * emitted as its own no-proof run so Word never flags it, while surrounding\n * text stays spell-checked.\n */\n noProofWords?: string[];\n /**\n * Resolve a `[^id]` note marker to its document-scoped id and kind, or\n * undefined to leave the marker as literal text.\n *\n * Passing a resolver is what turns `[^…]` into syntax at all: without one,\n * text that merely looks like a marker (a regex character class in a code\n * sample, say) is untouched.\n */\n noteRef?: (id: string) => { id: number; endnote: boolean } | undefined;\n}\n\n/**\n * Inline note marker: `[^id]`, where id has no whitespace or `]`.\n * Deliberately not global: a shared /g regex carries `lastIndex` between\n * `.test()` calls and would skip every other marker.\n */\nconst FOOTNOTE_MARKER_REGEX = /\\[\\^([^\\]\\s]+)\\]/;\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Build a matcher for the known-words allowlist, or null when there's nothing\n * to match. Matches each word as a whole token (no letter/number directly\n * adjacent on either side) so \"Wiseair\" doesn't match inside \"Wiseairy\", while\n * internal punctuation like \"json-to-office\" is matched literally.\n */\nexport function buildNoProofWordsRegex(noProofWords?: string[]): RegExp | null {\n const words = (noProofWords || []).filter((w) => w && w.trim().length > 0);\n if (words.length === 0) return null;\n // Longest first so alternation prefers the most specific match.\n const escaped = words\n .slice()\n .sort((a, b) => b.length - a.length)\n .map(escapeRegExp);\n return new RegExp(\n `(?<![\\\\p{L}\\\\p{N}])(?:${escaped.join('|')})(?![\\\\p{L}\\\\p{N}])`,\n 'giu'\n );\n}\n\n/**\n * Split a plain string into TextRuns, marking every known-word occurrence as a\n * no-proof run via `makeRun`. When there are no known words, returns a single\n * run for the whole text.\n */\nexport function splitByNoProofWords(\n text: string,\n makeRun: (segment: string, noProof: boolean) => TextRun,\n noProofWords?: string[]\n): TextRun[] {\n const regex = buildNoProofWordsRegex(noProofWords);\n if (!regex || !text) return [makeRun(text, false)];\n\n const runs: TextRun[] = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n runs.push(makeRun(text.slice(lastIndex, match.index), false));\n }\n runs.push(makeRun(match[0], true));\n lastIndex = match.index + match[0].length;\n // Guard against zero-length matches (shouldn't happen, but be safe).\n if (regex.lastIndex === match.index) regex.lastIndex++;\n }\n if (lastIndex < text.length) {\n runs.push(makeRun(text.slice(lastIndex), false));\n }\n return runs.length > 0 ? runs : [makeRun(text, false)];\n}\n\n/**\n * Parses text with inline markdown-style decorators, placeholders, and newlines, returning an array of TextRun objects\n * Supports:\n * - **bold** or __bold__\n * - *italic* or _italic_\n * - ***bold italic*** or ___bold italic___\n * - \\n for line breaks\n * - {PLACEHOLDER} for dynamic content\n * - [link text](url) for hyperlinks (when enableHyperlinks is true)\n *\n * @param text The text to parse\n * @param baseStyle The base style to apply to all text runs\n * @param options Additional options for text decoration\n * @returns Array of TextRun and hyperlink objects with appropriate styling\n */\nexport function parseTextWithDecorators(\n text: string,\n baseStyle: TextStyle = {},\n options: TextDecoratorOptions = {}\n): PlaceholderChild[] {\n // Guard against undefined or null text\n if (!text) {\n return [new TextRun({ text: '', ...baseStyle })];\n }\n const normalizedText = normalizeUnicodeText(text);\n\n // Check if text contains placeholders\n const hasPlaceholders = /\\{[^}]+\\}/.test(normalizedText);\n\n if (hasPlaceholders) {\n // Use new placeholder processor that handles both decorators and placeholders\n return processTextWithPlaceholders(\n normalizedText,\n baseStyle,\n options.placeholderContext || {},\n options.noProofWords\n );\n }\n\n // Process hyperlinks first if enabled\n if (options.enableHyperlinks) {\n return parseTextWithHyperlinks(normalizedText, baseStyle, options);\n }\n\n // Original decorator-only processing\n const runs: PlaceholderChild[] = [];\n\n // Process decorators on the entire text first (including newlines)\n const decoratorRegex =\n /(\\*\\*\\*|___)([\\s\\S]*?)\\1|(\\*\\*|__)([\\s\\S]*?)\\3|(\\*|_)([\\s\\S]*?)\\5/g;\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = decoratorRegex.exec(normalizedText)) !== null) {\n // Add any text before the match as plain text (handle newlines)\n if (match.index > lastIndex) {\n const plainText = normalizedText.substring(lastIndex, match.index);\n if (plainText) {\n runs.push(...createTextRunsWithNewlines(plainText, baseStyle, options));\n }\n }\n\n // Determine the style based on the decorator\n let decoratedText: string;\n let bold = baseStyle.bold || false;\n let italics = baseStyle.italics || false;\n\n if (match[1] === '***' || match[1] === '___') {\n // Bold + Italic\n decoratedText = match[2];\n bold = true;\n italics = true;\n } else if (match[3] === '**' || match[3] === '__') {\n // Bold\n decoratedText = match[4];\n bold = true;\n } else if (match[5] === '*' || match[5] === '_') {\n // Italic\n decoratedText = match[6];\n italics = true;\n } else {\n // This shouldn't happen with our regex, but just in case\n decoratedText = match[0];\n }\n\n // Create decorated text runs with newlines\n const decoratedRuns = createTextRunsWithNewlines(\n decoratedText,\n baseStyle,\n options,\n {\n bold,\n italics,\n }\n );\n runs.push(...decoratedRuns);\n\n lastIndex = match.index + match[0].length;\n }\n\n // Add any remaining text after the last match\n if (lastIndex < normalizedText.length) {\n const remainingText = normalizedText.substring(lastIndex);\n if (remainingText) {\n runs.push(\n ...createTextRunsWithNewlines(remainingText, baseStyle, options)\n );\n }\n }\n\n // If no decorators were found, return text runs with newlines\n if (runs.length === 0 && normalizedText) {\n runs.push(\n ...createTextRunsWithNewlines(normalizedText, baseStyle, options)\n );\n }\n\n return runs;\n}\n\n/**\n * Run-level properties shared by every run produced for a piece of text.\n * Single assembly point for both the plain-text and placeholder paths — a\n * prop forwarded here reaches both, so the two cannot drift (issue #137).\n */\nexport function buildRunCommonProps(\n baseStyle: TextStyle,\n overrides?: { bold?: boolean; italics?: boolean; boldColor?: string }\n) {\n const bold = overrides?.bold ?? baseStyle.bold;\n const italics = overrides?.italics ?? baseStyle.italics;\n return {\n ...(baseStyle.font && { font: baseStyle.font }),\n ...(baseStyle.size && { size: baseStyle.size }),\n ...(baseStyle.color && {\n color:\n bold && overrides?.boldColor ? overrides.boldColor : baseStyle.color,\n }),\n ...(bold !== undefined && { bold }),\n ...(italics !== undefined && { italics }),\n ...(baseStyle.underline && { underline: baseStyle.underline }),\n ...(baseStyle.scale && { scale: baseStyle.scale }),\n ...(baseStyle.characterSpacing && {\n characterSpacing: baseStyle.characterSpacing,\n }),\n ...(baseStyle.language && { language: baseStyle.language }),\n };\n}\n\n/**\n * Build the runs for a single line of text: split on `\\t` into real\n * `<w:tab/>` runs (a tab char inside <w:t> would be silently dropped by\n * Word, and paragraph tabStops only apply to real tab runs), emit no-proof\n * word runs, and attach the line break to the first emitted run only.\n */\nfunction buildLineRuns(\n line: string,\n commonProps: ReturnType<typeof buildRunCommonProps>,\n opts: { needsLineBreak: boolean; noProof?: boolean; noProofWords?: string[] }\n): TextRun[] {\n const { needsLineBreak, noProof } = opts;\n // When the whole run is already no-proof, there's nothing to single out,\n // so skip word splitting and emit one run for the line.\n const wholeRunNoProof = noProof === true;\n const wordsForLine = wholeRunNoProof ? undefined : opts.noProofWords;\n\n // The line break belongs only on the first run of the line.\n let firstSegment = true;\n const lineRuns: TextRun[] = [];\n const tabSegments = line.split('\\t');\n tabSegments.forEach((tabSegment, tabIndex) => {\n if (tabIndex > 0) {\n lineRuns.push(\n new TextRun({\n children: [new Tab()],\n ...commonProps,\n ...(needsLineBreak && firstSegment && { break: 1 }),\n })\n );\n firstSegment = false;\n }\n if (!tabSegment && tabSegments.length > 1) return;\n lineRuns.push(\n ...splitByNoProofWords(\n tabSegment,\n (segment, matched) => {\n const run = new TextRun({\n text: segment,\n ...commonProps,\n ...((matched || noProof !== undefined) && {\n noProof: matched || wholeRunNoProof,\n }),\n ...(needsLineBreak && firstSegment && { break: 1 }),\n });\n firstSegment = false;\n return run;\n },\n wordsForLine\n )\n );\n });\n return lineRuns;\n}\n\n/**\n * Turn multi-line text into TextRuns: `\\n` becomes a run break, `\\t` a real\n * tab run, no-proof words their own runs. Shared by the plain-text path\n * (textParser) and the placeholder path (placeholderProcessor) so run-level\n * properties cannot diverge between them.\n */\nexport function buildTextRuns(\n text: string,\n commonProps: ReturnType<typeof buildRunCommonProps>,\n opts: { noProof?: boolean; noProofWords?: string[] } = {}\n): TextRun[] {\n const runs: TextRun[] = [];\n const lines = text.split('\\n');\n\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\n const line = lines[lineIndex];\n const needsLineBreak = lineIndex > 0;\n\n // Create runs even for empty lines if they need a break\n if (line || needsLineBreak) {\n runs.push(\n ...buildLineRuns(line, commonProps, { needsLineBreak, ...opts })\n );\n }\n }\n\n return runs;\n}\n\n/**\n * Helper function to create TextRuns with newlines from text\n */\nfunction createTextRunsWithNewlines(\n text: string,\n baseStyle: TextStyle,\n options: TextDecoratorOptions,\n overrideStyle?: { bold?: boolean; italics?: boolean }\n): PlaceholderChild[] {\n const runs = (segment: string) =>\n buildTextRuns(\n segment,\n buildRunCommonProps(baseStyle, {\n bold: overrideStyle?.bold,\n italics: overrideStyle?.italics,\n boldColor: options.boldColor,\n }),\n { noProof: baseStyle.noProof, noProofWords: options.noProofWords }\n );\n\n if (!options.noteRef) return runs(text);\n return splitNoteMarkers(text, options.noteRef, runs);\n}\n\n/**\n * Replace resolvable `[^id]` markers with footnote or endnote reference runs,\n * handing the text between them to `runs`.\n *\n * This runs at the leaf, after decorators have been parsed, so a marker inside\n * `**bold[^n]**` keeps the surrounding emphasis — splitting earlier would break\n * the `**` pair across segments and silently drop the formatting.\n *\n * A marker whose id the resolver does not know stays literal; the resolver owns\n * that decision (and any warning), so this never has to guess whether `[^a-z]`\n * was meant as syntax.\n */\nfunction splitNoteMarkers(\n text: string,\n noteRef: (id: string) => { id: number; endnote: boolean } | undefined,\n runs: (segment: string) => TextRun[]\n): PlaceholderChild[] {\n const regex = new RegExp(FOOTNOTE_MARKER_REGEX.source, 'g');\n const out: PlaceholderChild[] = [];\n\n let lastIndex = 0;\n let pending = '';\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(text)) !== null) {\n const note = noteRef(match[1]);\n if (note === undefined) {\n // Unresolved: keep the marker in the text stream verbatim.\n pending += text.slice(lastIndex, regex.lastIndex);\n lastIndex = regex.lastIndex;\n continue;\n }\n\n const before = pending + text.slice(lastIndex, match.index);\n pending = '';\n if (before) out.push(...runs(before));\n out.push(\n note.endnote\n ? new EndnoteReferenceRun(note.id)\n : new FootnoteReferenceRun(note.id)\n );\n lastIndex = regex.lastIndex;\n }\n\n if (out.length === 0) return runs(text);\n\n const trailing = pending + text.slice(lastIndex);\n if (trailing) out.push(...runs(trailing));\n return out;\n}\n\n/**\n * Cross-reference to a numbered heading or list item: `[@id]`, optionally\n * `[@id:relative|no_context|full_context|none]`.\n *\n * The id accepts every character a bookmark id can actually hold, rather than\n * a narrower slug alphabet: `id` is a free string in the schema, so an author\n * who writes `item.1` on a list item must be able to reference it. Whitespace\n * ends the token (an unclosed `[@` cannot swallow a sentence) and `:` is\n * reserved as the format separator.\n *\n * No collision with `[text](url)`: that syntax needs a `(…)` immediately after\n * the bracket, and the alternation below tries it first anyway.\n */\nconst CROSS_REFERENCE_PATTERN =\n '\\\\[@([^\\\\]\\\\s:]+)(?::(relative|no_context|full_context|none))?\\\\]';\n\n/**\n * One pass over both bracket syntaxes: parsing them separately would mean\n * re-scanning the segments between one kind of token for the other kind, while\n * the plain text between them still has to reach `parseTextWithDecorators`.\n */\nconst INLINE_TOKEN_REGEX = `\\\\[([^\\\\]]+)\\\\]\\\\(([^)]+)\\\\)|${CROSS_REFERENCE_PATTERN}`;\n\n/**\n * True when the text carries a `[@id]` token. `createHeading` renders simple\n * headings through a run builder that never reaches this parser, so it needs to\n * know when a heading is not simple after all.\n */\nexport function hasCrossReference(text: string): boolean {\n return new RegExp(CROSS_REFERENCE_PATTERN).test(text);\n}\n\nconst REFERENCE_FORMATS = {\n relative: NumberedItemReferenceFormat.RELATIVE,\n no_context: NumberedItemReferenceFormat.NO_CONTEXT,\n full_context: NumberedItemReferenceFormat.FULL_CONTEXT,\n none: NumberedItemReferenceFormat.NONE,\n} as const;\n\ntype ReferenceFormatKey = keyof typeof REFERENCE_FORMATS;\n\n/**\n * Turn one `[@id]` token into a Word REF field.\n *\n * The cached value is what makes the reference readable outside Word: headless\n * LibreOffice — and therefore the PDF export path — never updates fields, so an\n * uncached REF exports blank. Word recomputes it on open (the document sets\n * `updateFields`), so an approximate cached value is corrected there.\n *\n * An unresolvable id renders as its literal token text rather than as a field:\n * a REF pointing at a bookmark that does not exist is exactly what makes Word\n * show \"Error! Reference source not found\".\n */\nfunction createCrossReference(\n id: string,\n format: ReferenceFormatKey,\n token: string,\n baseStyle: TextStyle,\n options: TextDecoratorOptions\n): PlaceholderChild[] {\n const info = globalNumberedItemsRegistry.get(id);\n\n if (!info) {\n // An unseeded registry means no render is in progress (a unit test calling\n // the text primitives directly), so nothing has had the chance to declare\n // the target and there is no authoring mistake to report.\n if (globalNumberedItemsRegistry.isSeeded()) {\n console.warn(\n `[core-docx] Cross-reference ${token} has no target: no heading or list item declares the id \"${id}\". Rendering the token as literal text.`\n );\n }\n return buildTextRuns(\n token,\n buildRunCommonProps(baseStyle, { boldColor: options.boldColor }),\n { noProof: baseStyle.noProof, noProofWords: options.noProofWords }\n );\n }\n\n if (format === 'none') {\n return [\n new NumberedItemReference(id, info.text, {\n hyperlink: true,\n referenceFormat: REFERENCE_FORMATS.none,\n }),\n ];\n }\n\n // `relative` caches the full number: Word resolves it against the reference's\n // own position in the numbering, which generation does not know.\n const cachedValue = format === 'no_context' ? info.own : info.full;\n if (cachedValue === undefined) {\n console.warn(\n `[core-docx] Cross-reference ${token} targets an unnumbered ${info.kind} (\"${id}\"), so the field carries no cached number and reads blank until the reader updates fields. Use [@${id}:none] to reference its text instead.`\n );\n }\n\n return [\n new NumberedItemReference(id, cachedValue, {\n hyperlink: true,\n referenceFormat: REFERENCE_FORMATS[format],\n }),\n ];\n}\n\n/**\n * Parse text with hyperlinks, cross-references and decorators\n * Supports markdown-style links `[text](url)` and cross-references `[@id]`\n */\nfunction parseTextWithHyperlinks(\n text: string,\n baseStyle: TextStyle = {},\n options: TextDecoratorOptions = {}\n): PlaceholderChild[] {\n const normalizedText = normalizeUnicodeText(text);\n const runs: PlaceholderChild[] = [];\n\n // Fresh instance per call: a shared /g regex carries `lastIndex` between\n // calls and would skip tokens.\n const tokenRegex = new RegExp(INLINE_TOKEN_REGEX, 'g');\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = tokenRegex.exec(normalizedText)) !== null) {\n // Add any text before the token\n if (match.index > lastIndex) {\n const plainText = normalizedText.substring(lastIndex, match.index);\n if (plainText) {\n // Recursively parse the plain text for decorators\n const plainRuns = parseTextWithDecorators(plainText, baseStyle, {\n ...options,\n enableHyperlinks: false, // Disable hyperlinks in recursive call\n });\n runs.push(...plainRuns);\n }\n }\n\n lastIndex = match.index + match[0].length;\n\n // Group 1 is the hyperlink's text; absent means the cross-reference branch\n // of the alternation matched.\n if (match[1] === undefined) {\n runs.push(\n ...createCrossReference(\n match[3],\n (match[4] as ReferenceFormatKey | undefined) ?? 'relative',\n match[0],\n baseStyle,\n options\n )\n );\n continue;\n }\n\n const linkText = match[1];\n const linkUrl = match[2];\n\n // Determine if this is an internal or external link\n const isInternal = linkUrl.startsWith('#');\n\n // Parse the link text for decorators (bold, italic, etc.)\n const linkTextRuns = parseTextWithDecorators(linkText, baseStyle, {\n ...options,\n enableHyperlinks: false, // Disable hyperlinks in recursive call\n });\n\n // Create the appropriate hyperlink type\n if (isInternal) {\n // Internal link (bookmark)\n const bookmarkId = linkUrl.substring(1); // Remove the # prefix\n runs.push(\n new InternalHyperlink({\n children: linkTextRuns as TextRun[], // Cast needed for docx types\n anchor: bookmarkId,\n })\n );\n } else {\n // External link\n runs.push(\n new ExternalHyperlink({\n children: linkTextRuns as TextRun[], // Cast needed for docx types\n link: linkUrl,\n })\n );\n }\n }\n\n // Add any remaining text after the last token\n if (lastIndex < normalizedText.length) {\n const remainingText = normalizedText.substring(lastIndex);\n if (remainingText) {\n const remainingRuns = parseTextWithDecorators(remainingText, baseStyle, {\n ...options,\n enableHyperlinks: false, // Disable hyperlinks in recursive call\n });\n runs.push(...remainingRuns);\n }\n }\n\n // If no tokens were found, fall back to regular decorator parsing\n if (runs.length === 0 && normalizedText) {\n return parseTextWithDecorators(normalizedText, baseStyle, {\n ...options,\n enableHyperlinks: false,\n });\n }\n\n return runs;\n}\n","/**\n * Numbered Item Registry\n *\n * Cross-reference targets — numbered headings and list items — resolved by the\n * document-outline pre-pass and read back while rendering inline text.\n *\n * It is a registry rather than a field on `RenderContext` because the consumer\n * is `textParser`, which is reached through `createText`/`createHeading`/\n * `createList` and never sees the context.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\nexport interface NumberedItemInfo {\n kind: 'heading' | 'list-item';\n /** Rendered text of the target, for a `:none` (text) reference. */\n text: string;\n /** Full multilevel number (\"2.1.3\"), absent when the target is unnumbered. */\n full?: string;\n /** The target's own level counter (\"3\"), absent when unnumbered. */\n own?: string;\n}\n\ninterface NumberedItemsState {\n items: Map<string, NumberedItemInfo>;\n seeded: boolean;\n}\n\nexport class NumberedItemsRegistry {\n private readonly fallback: NumberedItemsState = {\n items: new Map(),\n seeded: false,\n };\n private readonly scopes = new AsyncLocalStorage<NumberedItemsState>();\n\n private get state(): NumberedItemsState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run({ items: new Map(), seeded: false }, callback);\n }\n\n /** Replace the contents with the pre-pass result. */\n seed(items: ReadonlyMap<string, NumberedItemInfo>): void {\n const state = this.state;\n state.items = new Map(items);\n state.seeded = true;\n }\n\n /**\n * False outside a render (a unit test calling `createText` directly). An\n * unresolved reference is then expected rather than an authoring mistake, so\n * the caller stays quiet about it.\n */\n isSeeded(): boolean {\n return this.state.seeded;\n }\n\n get(id: string): NumberedItemInfo | undefined {\n return this.state.items.get(id);\n }\n\n clear(): void {\n this.state.items.clear();\n this.state.seeded = false;\n }\n}\n\nexport const globalNumberedItemsRegistry = new NumberedItemsRegistry();\n","/**\n * Detection of per-instance annotation props anywhere in a component subtree.\n *\n * `revision` and `comment` both render as document-scoped OOXML ids allocated\n * from a per-render counter. A component carrying either must never be served\n * from the cross-document component cache, or a cached subtree replays dead ids\n * into a later document.\n *\n * The walk has to reach every place a component can hide: list items, table\n * cells (the table model is column-major, so cells are only reachable through\n * `props.columns[]`), components nested in a cell's `content`, and ordinary\n * children.\n */\n\nexport type MaybeComponent = { props?: unknown; children?: unknown[] };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** True when `value` is an object with a truthy `key`. */\nfunction hasKey(value: unknown, key: string): boolean {\n return isRecord(value) && Boolean(value[key]);\n}\n\n/** A table cell annotated directly, or holding an annotated component. */\nfunction cellHasAnnotation(cell: unknown, key: string): boolean {\n if (!isRecord(cell)) return false;\n if (hasKey(cell, key)) return true;\n const content = cell.content;\n return (\n isRecord(content) && componentHasAnnotation(content as MaybeComponent, key)\n );\n}\n\n/**\n * True when `key` appears anywhere in the component subtree: its own props,\n * list items, row-parallel structural entries, table cells, or any descendant.\n */\nexport function componentHasAnnotation(\n component: MaybeComponent,\n key: string\n): boolean {\n const props = component.props as Record<string, unknown> | undefined;\n if (props) {\n if (props[key]) return true;\n\n const items = props.items;\n if (Array.isArray(items) && items.some((item) => hasKey(item, key))) {\n return true;\n }\n\n // Row-parallel structural entries live outside the column-major cell grid.\n const rows = props.rows;\n if (Array.isArray(rows) && rows.some((row) => hasKey(row, key))) {\n return true;\n }\n\n const columns = props.columns;\n if (\n Array.isArray(columns) &&\n columns.some((column) => {\n if (!isRecord(column)) return false;\n if (cellHasAnnotation(column.header, key)) return true;\n const cells = column.cells;\n return (\n Array.isArray(cells) &&\n cells.some((cell) => cellHasAnnotation(cell, key))\n );\n })\n ) {\n return true;\n }\n }\n\n const children = component.children;\n if (Array.isArray(children)) {\n return children.some(\n (child) =>\n isRecord(child) && componentHasAnnotation(child as MaybeComponent, key)\n );\n }\n return false;\n}\n","/**\n * Cached component rendering system\n * Provides caching layer for component rendering operations\n */\n\nimport { Paragraph, Table, TableOfContents } from 'docx';\nimport { ComponentDefinition, RenderContext } from '../types';\nimport { ThemeConfig } from '../styles';\nimport {\n MemoryCache,\n CacheKeyGenerator,\n CacheConfiguration,\n CachedComponent,\n} from '../cache';\nimport { renderComponent } from './render';\nimport { componentHasRevision } from '../utils/revisionUtils';\nimport { componentHasAnnotation } from '../utils/componentAnnotations';\nimport { getBaseDir, getGenerationDate } from '../utils/generationContext';\nimport { PlaceholderRegistry } from '../utils/placeholderProcessor';\nimport { createHash } from 'crypto';\n\n// Global component cache instance\nlet componentCache: MemoryCache | null = null;\nlet cacheKeyGen: CacheKeyGenerator | null = null;\n\n/** Why a component type is never cached (see renderComponentWithCache). */\nexport type ComponentBypassReason =\n | 'dynamic-context'\n | 'bookmark-id'\n | 'revision-ids'\n | 'comment-ids';\n\nexport interface ComponentBypassStats {\n /** Component type name. */\n type: string;\n /** Renders that skipped the cache by design. */\n renders: number;\n /** The (first observed) reason this type bypasses the cache. */\n reason: ComponentBypassReason;\n}\n\n/**\n * Per-type counters for renders that deliberately skip the cache. Without\n * them the Module Breakdown is structurally blind to `toc`, `section`,\n * `visual`, `heading`, `list`, `paragraph`, and id/revision-bearing nodes —\n * they return before any cache.get, so the cache's own stats never see them\n * (#156). Only design bypasses are recorded; a caller's `bypassCache` flag\n * and a disabled cache are per-render choices, not properties of the type.\n */\nconst bypassStats = new Map<\n string,\n { renders: number; reason: ComponentBypassReason }\n>();\n\nfunction recordBypass(type: string, reason: ComponentBypassReason): void {\n const entry = bypassStats.get(type);\n if (entry) {\n entry.renders++;\n } else {\n bypassStats.set(type, { renders: 1, reason });\n }\n}\n\n/**\n * Get per-type \"uncached by design\" render counters.\n */\nexport function getComponentBypassStats(): ComponentBypassStats[] {\n return Array.from(bypassStats.entries()).map(([type, s]) => ({\n type,\n renders: s.renders,\n reason: s.reason,\n }));\n}\n\n/**\n * Placeholders that resolve from the generation date. `{PAGE}` and\n * `{TOTAL_PAGES}` are Word field codes — date-independent — while every\n * other registered placeholder (DATE, DATETIME, YEAR, custom registrations)\n * may read the date, so their presence keeps the date in the cache key.\n */\nconst DATE_INDEPENDENT_PLACEHOLDERS = new Set(['PAGE', 'TOTAL_PAGES']);\n\n/**\n * True when the serialized props/children reference a registered placeholder\n * whose output can vary with the generation date. Components without one\n * render identically across dates, so their cache keys must not embed the\n * per-render timestamp — that's what made cross-render hits impossible for\n * date-less documents (#156).\n */\nexport function usesDateSensitivePlaceholder(serialized: string): boolean {\n const placeholderRegex = /\\{([^}{]+)\\}/g;\n let match: RegExpExecArray | null;\n while ((match = placeholderRegex.exec(serialized)) !== null) {\n const name = match[1].toUpperCase();\n if (DATE_INDEPENDENT_PLACEHOLDERS.has(name)) continue;\n if (PlaceholderRegistry.has(name)) return true;\n }\n return false;\n}\n\n/**\n * Create a hash of the theme configuration for cache key generation\n * This ensures cache invalidation when theme changes\n */\nfunction createThemeHash(theme: ThemeConfig): string {\n // Serialize the theme object to JSON and create a hash\n const themeString = JSON.stringify(theme);\n return createHash('sha256').update(themeString).digest('hex').substring(0, 8);\n}\n\n/**\n * Initialize the component cache\n */\nexport function initializeComponentCache(cache?: MemoryCache): void {\n if (cache) {\n componentCache = cache;\n } else if (!componentCache) {\n // Create a default cache if none provided\n const config: CacheConfiguration = {\n enabled: true,\n evictionPolicy: 'lru',\n memory: {\n enabled: true,\n maxSize: 100, // 100MB for components\n maxEntries: 1000,\n defaultTTL: 3600, // 1 hour\n cleanupInterval: 300, // 5 minutes\n },\n performance: {\n trackMetrics: true,\n metricsSampleRate: 1.0,\n enableWarming: false,\n parallelProcessing: true,\n },\n };\n componentCache = new MemoryCache(config);\n }\n\n if (!cacheKeyGen) {\n cacheKeyGen = new CacheKeyGenerator();\n }\n}\n\n/**\n * Get the component cache instance\n */\nexport function getComponentCache(): MemoryCache | null {\n return componentCache;\n}\n\n/**\n * Clear the component cache\n */\nexport async function clearComponentCache(): Promise<void> {\n if (componentCache) {\n await componentCache.clear();\n }\n bypassStats.clear();\n}\n\n/**\n * Component types whose render output depends on per-render state that is not\n * part of the cache key.\n *\n * - 'toc' depends on section bookmark ids generated at render time; caching\n * can produce stale references to non-existent bookmarks on re-render.\n * - 'section' generates document-scoped bookmarks internally; caching would\n * duplicate bookmark ids across sections.\n * - 'visual' rasterizes via the injected services.pptx (an in-process render\n * fn or an HTTP serverUrl) which is NOT part of the cache key; caching by\n * props alone could serve a stale image when the rasterizer differs across\n * renders. The rasterizer keeps its own content-addressed disk cache, so an\n * identical visual is still cheap to re-resolve.\n * - 'heading', 'list' and 'paragraph': both explicit lists and markdown-list\n * paragraphs register numbering in the current document scope. Cached\n * paragraphs can otherwise reference definitions that only existed in a\n * previous render.\n */\nconst DYNAMIC_CONTEXT_COMPONENTS = new Set([\n 'toc',\n 'section',\n 'visual',\n 'heading',\n 'list',\n 'paragraph',\n]);\n\n/**\n * Why this component must skip the cross-document component cache, or `null`\n * when it is safe to cache.\n *\n * Kept as one named predicate so a new reason is a new clause here rather\n * than a restructuring of an inline conditional ladder.\n */\nexport function componentBypassReason(\n component: ComponentDefinition\n): ComponentBypassReason | null {\n // Revision-bearing components embed document-scoped w:ins/w:del ids from a\n // per-render counter; caching would leak ids across documents.\n if (componentHasRevision(component)) return 'revision-ids';\n // Comments do the same with their own (separate) id namespace, and a cached\n // anchor would also point at a body that lives in another document.\n if (componentHasAnnotation(component, 'comment')) return 'comment-ids';\n if ('id' in component) return 'bookmark-id';\n if (DYNAMIC_CONTEXT_COMPONENTS.has(component.name)) return 'dynamic-context';\n return null;\n}\n\n/**\n * Render a component with caching\n */\nexport async function renderComponentWithCache(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext,\n bypassCache = false\n): Promise<(Paragraph | Table | TableOfContents)[]> {\n const bypassReason = componentBypassReason(component);\n\n // Initialize cache if needed\n if (!componentCache) {\n initializeComponentCache();\n }\n\n // If cache is disabled or bypassed, render directly. Design bypasses are\n // counted so cache observability covers every component type, not only\n // the cacheable ones (#156).\n if (bypassReason !== null) {\n recordBypass(component.name, bypassReason);\n return renderComponent(component, theme, themeName, context);\n }\n if (!componentCache || bypassCache || !componentCache.getConfig().enabled) {\n return renderComponent(component, theme, themeName, context);\n }\n\n // Generate cache key for this component\n // Use theme hash instead of name to ensure cache invalidation on theme changes\n const componentProps = JSON.stringify(component.props || {});\n const themeHash = createThemeHash(theme);\n // Include minimal context for other components that might vary with context\n // For now we add section layout type and column count without exposing\n // bookmark IDs (TOC/section are bypassed above).\n const contextKey = context?.section\n ? `${context.section.currentLayout}:${context.section.columnCount}`\n : 'no-section';\n // Components that read local assets (images) resolve relative paths against\n // the active baseDir; identical props from different document directories\n // must not share cached bytes (#142).\n const baseDirKey = getBaseDir() ?? '';\n\n // For container components (columns, section, etc.), include children in cache key\n // This ensures cache invalidation when child component content changes\n const childrenKey =\n 'children' in component && component.children\n ? `:children:${JSON.stringify(component.children)}`\n : '';\n\n // Placeholder resolution is scoped to the document metadata/generatedAt\n // date — but only for components that actually reference a date-sensitive\n // placeholder (anywhere in props or children: dynamic text can hide inside\n // a table cell). Unconditionally embedding the per-render timestamp made\n // every cross-render lookup miss for date-less documents, reducing the\n // cache to an intra-render dedupe (#156).\n const generationDateKey = usesDateSensitivePlaceholder(\n componentProps + childrenKey\n )\n ? getGenerationDate().toISOString()\n : 'no-date';\n\n const cacheKey = `component:${component.name}:${themeHash}:${contextKey}:${generationDateKey}:${baseDirKey}:${componentProps}${childrenKey}`;\n\n // Try to get from cache\n const cached = await componentCache.get(cacheKey);\n\n if (cached) {\n // Cache hit - the cache internally tracks this as a hit\n // Return the rendered result from cache\n return cached.result as (Paragraph | Table | TableOfContents)[];\n }\n\n // Cache miss - render the component\n const renderStartTime = Date.now();\n const rendered = await renderComponent(component, theme, themeName, context);\n // Track render time for analytics\n Date.now() - renderStartTime;\n\n // Calculate approximate size (rough estimate)\n const componentSize = JSON.stringify(rendered).length;\n\n // Create a proper CachedComponent structure\n const cachedEntry: CachedComponent = {\n result: rendered as unknown, // Store the rendered Paragraph/Table array as result\n componentName: component.name,\n propsHash: cacheKey,\n timestamp: Date.now(),\n hits: 0,\n size: componentSize,\n dependencies: [],\n signature: cacheKey,\n lastAccessed: Date.now(),\n };\n\n // Store in cache - the cache internally tracks this as a miss\n await componentCache.set(cacheKey, cachedEntry);\n\n return rendered;\n}\n\n// Note: Component statistics are automatically tracked by the cache itself\n// The cache's updateHitStats and updateMissStats methods handle this internally\n\n/**\n * Warm the cache with frequently used components\n */\nexport async function warmComponentCache(\n components: Array<{\n component: ComponentDefinition;\n theme: ThemeConfig;\n themeName: string;\n context: RenderContext;\n }>\n): Promise<void> {\n if (\n !componentCache ||\n !componentCache.getConfig().performance.enableWarming\n ) {\n return;\n }\n\n const warmingPromises = components.map(\n async ({ component, theme, themeName, context }) => {\n await renderComponentWithCache(\n component,\n theme,\n themeName,\n context,\n false\n );\n }\n );\n\n await Promise.all(warmingPromises);\n}\n\n/**\n * Get component cache statistics, extended with per-type \"uncached by\n * design\" render counters (#156). The bypass counters exist even before the\n * cache is initialized — a document full of bypassed types never triggers\n * initialization, yet its renders are exactly what needs surfacing.\n */\nexport function getComponentCacheStats() {\n const bypassedComponents = getComponentBypassStats();\n if (!componentCache) {\n return bypassedComponents.length > 0 ? { bypassedComponents } : null;\n }\n\n return { ...componentCache.getStats(), bypassedComponents };\n}\n\n/**\n * Export component cache for persistence\n */\nexport async function exportComponentCache(): Promise<Map<\n string,\n unknown\n> | null> {\n if (!componentCache) {\n return null;\n }\n\n const keys = await componentCache.getKeys();\n const exported = new Map<string, unknown>();\n\n for (const key of keys) {\n const value = await componentCache.get(key);\n if (value) {\n exported.set(key, value);\n }\n }\n\n return exported;\n}\n\n/**\n * Import component cache from persistence\n */\nexport async function importComponentCache(\n data: Map<string, unknown>\n): Promise<void> {\n if (!componentCache) {\n initializeComponentCache();\n }\n\n for (const [key, value] of data.entries()) {\n await componentCache!.set(key, value as CachedComponent);\n }\n}\n","/**\n * Content Creation Functions\n * Pure functions for creating Word document elements without layout concerns\n */\n\nimport {\n Paragraph,\n TextRun,\n Table,\n TableRow,\n TableCell,\n AlignmentType,\n ImageRun,\n PageBreak,\n WidthType,\n BorderStyle,\n Header,\n Footer,\n PageNumber,\n ColumnBreak,\n TableLayoutType,\n VerticalAlign,\n} from 'docx';\nimport type { ParagraphChild } from 'docx';\nimport {\n calculateImageDimensions,\n getImageBuffer,\n parseWidthValue,\n parseDimensionValue,\n detectImageType,\n createTypedImageRun,\n resolveImageSource,\n} from '../utils/imageUtils';\nimport { ThemeConfig } from '../styles';\nimport { getTableStyle } from '../styles';\nimport { getThemeColors, getThemeFonts } from '../themes/defaults';\nimport {\n parseTextWithDecorators,\n splitByNoProofWords,\n hasCrossReference,\n} from '../utils/textParser';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n} from '../utils/placeholderProcessor';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport { getStyleIdForLevel } from '../styles/themeToDocxAdapter';\nimport {\n globalBookmarkRegistry,\n createBookmarkedContent,\n} from '../utils/bookmarkRegistry';\nimport {\n createMarkedTextRuns,\n createRevisionMark,\n createRevisionRuns,\n} from '../utils/revisionUtils';\nimport { openCommentRange, closeCommentRange } from '../utils/commentAnchors';\nimport { createNoteResolver } from '../utils/noteResolver';\nimport type {\n Comment,\n Note,\n Revision,\n RevisionMark,\n} from '@json-to-office/shared-docx';\nimport { resolveFontFamily } from '../styles/utils/styleHelpers';\nimport { synthesizeFamilyName } from '@json-to-office/shared';\nimport {\n ComponentDefinition,\n isParagraphComponent,\n ParagraphComponentDefinition,\n isImageComponent,\n ImageComponentDefinition,\n} from '../types';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport {\n pointsToTwips,\n convertLineSpacing as convertLineSpacingToDocx,\n} from '../styles/utils/styleHelpers';\nimport {\n resolveOffsetTwips,\n getPageWidthTwips,\n getPageHeightTwips,\n getAvailableWidthTwips,\n getAvailableHeightTwips,\n} from '../utils/widthUtils';\n\n/**\n * Resolve (family, bold, italic, fontWeight) into the values the docx lib\n * should receive. For non-RIBBI weights (anything other than 400/700),\n * rewrite the family to the canonical sub-family name (e.g. \"Inter Light\")\n * so Word / LibreOffice can resolve the matching installed face.\n * `bold: true` without fontWeight is shorthand for weight 700.\n */\nfunction applyFontWeightAlias(opts: {\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n fontWeight?: number;\n}): { font?: string; bold?: boolean; italics?: boolean } {\n if (!opts.fontFamily) {\n return { font: undefined, bold: opts.bold, italics: opts.italic };\n }\n const weight = opts.fontWeight ?? (opts.bold === true ? 700 : undefined);\n const synth = synthesizeFamilyName(\n opts.fontFamily,\n weight,\n opts.italic === true\n );\n return { font: synth.family, bold: synth.bold, italics: synth.italic };\n}\n\n/**\n * Combine the document-level known-words allowlist (carried on the theme) with\n * any component-level list, de-duplicated. Returns undefined when empty.\n */\nfunction resolveNoProofWords(\n theme: ThemeConfig,\n optionWords?: string[]\n): string[] | undefined {\n const themeWords = theme.noProofWords;\n const merged = [...(themeWords || []), ...(optionWords || [])];\n return merged.length > 0 ? Array.from(new Set(merged)) : undefined;\n}\n\nexport interface TextOptions {\n style?: string;\n alignment?: 'left' | 'center' | 'right' | 'justify';\n spacing?: {\n before?: number; // in points\n after?: number; // in points\n };\n lineSpacing?:\n | number\n | {\n type: 'single' | 'atLeast' | 'exactly' | 'double' | 'multiple';\n value?: number;\n };\n boldColor?: string;\n columnBreak?: boolean;\n // Font properties\n fontFamily?: string;\n fontSize?: number;\n fontColor?: string;\n bold?: boolean;\n /**\n * Per-run weight (100–900). Renderer picks the closest embedded variant\n * via the font-alias registry and emits the run under a synthetic family\n * (e.g. \"Inter Light\" for 300). Overrides `bold` when set.\n */\n fontWeight?: number;\n italic?: boolean;\n underline?: boolean;\n // Character width scaling in percent (w:w). 100 is normal.\n scale?: number;\n // Letter tracking (w:spacing) — value in twentieths of a point.\n characterSpacing?: { type: 'condensed' | 'expanded'; value: number };\n // Per-run language (BCP-47) for spell/grammar checking. Overrides the\n // document default for these runs.\n language?: string;\n // Disable spell/grammar checking for these runs\n noProof?: boolean;\n // Known-words allowlist: whole-word occurrences are emitted as no-proof runs.\n // Merged with any document-level list carried on the theme.\n noProofWords?: string[];\n // Additional children to prepend (e.g., bookmarks)\n prependChildren?: any[];\n // Outline level for TOC\n outlineLevel?: number;\n /**\n * Paragraph-level numbering (`w:numPr`). `false` is the explicit opt-out\n * docx writes as numId 0 — the only way a single heading escapes a numbering\n * turned on for every heading through componentDefaults.\n */\n numbering?: { reference: string; level: number } | false;\n // Bookmark ID for internal linking\n bookmarkId?: string;\n // Floating frame properties\n floating?: {\n horizontalPosition?: {\n relative?: 'margin' | 'page' | 'text';\n align?: 'left' | 'center' | 'right' | 'inside' | 'outside';\n offset?: number | string;\n };\n verticalPosition?: {\n relative?: 'margin' | 'page' | 'text';\n align?: 'top' | 'center' | 'bottom' | 'inside' | 'outside' | 'inline';\n offset?: number | string;\n };\n wrap?: {\n type: 'around' | 'none' | 'notBeside' | 'through' | 'tight' | 'auto';\n };\n lockAnchor?: boolean;\n width?: number;\n height?: number;\n };\n // Keep paragraph with next paragraph\n keepNext?: boolean;\n // Keep all lines of paragraph together\n keepLines?: boolean;\n // Paragraph indentation (w:ind) in twips. hanging and firstLine are\n // mutually exclusive (validated upstream).\n indent?: {\n left?: number;\n right?: number;\n hanging?: number;\n firstLine?: number;\n };\n // Tab stops (w:tabs). Tab characters (\\t) in text jump to these positions.\n tabStops?: {\n type: 'left' | 'right' | 'center' | 'decimal' | 'bar';\n position: number;\n leader?: 'dot' | 'hyphen' | 'underscore' | 'middleDot' | 'none';\n }[];\n // Tracked-change segments: when present, text is rendered from these\n // (as native Word revisions) instead of the plain content string\n revision?: Revision;\n // Review comment anchored to this text. The text itself is unchanged; the\n // runs are wrapped in a comment range and followed by a reference.\n comment?: Comment;\n // Note bodies bound to `[^id]` markers in this text. Without them a marker\n // is left as literal text.\n footnotes?: readonly Note[];\n endnotes?: readonly Note[];\n}\n\nexport interface ImageOptions {\n caption?: string;\n width?: number | string;\n height?: number | string;\n widthRelativeTo?: 'content' | 'page';\n heightRelativeTo?: 'content' | 'page';\n alignment?: 'left' | 'center' | 'right';\n spacing?: {\n before?: number; // in points\n after?: number; // in points\n };\n floating?: {\n horizontalPosition?: {\n relative?: 'character' | 'column' | 'margin' | 'page' | 'text';\n align?: 'left' | 'center' | 'right' | 'inside' | 'outside';\n offset?: number | string;\n };\n verticalPosition?: {\n relative?: 'margin' | 'page' | 'paragraph' | 'line' | 'text';\n align?: 'top' | 'center' | 'bottom' | 'inside' | 'outside';\n offset?: number | string;\n };\n wrap?: {\n // 'tight', 'around', 'through' are VML-style; only 'none', 'square', 'topAndBottom' are supported for images\n type: 'none' | 'square' | 'topAndBottom' | 'around' | 'tight' | 'through';\n side?: 'bothSides' | 'left' | 'right' | 'largest';\n margins?: {\n top?: number | string;\n bottom?: number | string;\n left?: number | string;\n right?: number | string;\n };\n };\n allowOverlap?: boolean;\n behindDocument?: boolean;\n lockAnchor?: boolean;\n layoutInCell?: boolean;\n zIndex?: number;\n rotation?: number;\n visibility?: 'hidden' | 'inherit';\n };\n // Keep paragraph with next paragraph\n keepNext?: boolean;\n // Keep all lines of paragraph together\n keepLines?: boolean;\n}\n\nexport interface TableOptions {\n style?: 'minimal' | 'classic' | 'minimal';\n}\n\nexport interface StatisticData {\n number: string;\n description: string;\n alignment?: 'left' | 'center' | 'right';\n}\n\nexport interface StatisticOptions {\n spacing?: {\n before?: number; // in points\n after?: number; // in points\n };\n}\n\nexport interface ListOptions {\n // Reference to the numbering configuration in the Document\n numberingReference?: string;\n // Review comment spanning the whole list: the range opens on the first\n // rendered item and closes on the last.\n comment?: Comment;\n // Note bodies bound to `[^id]` markers in the item text.\n footnotes?: readonly Note[];\n endnotes?: readonly Note[];\n spacing?: {\n before?: number; // in points\n after?: number; // in points\n item?: number; // in points\n };\n alignment?: 'left' | 'center' | 'right' | 'justify';\n}\n\n/**\n * Warn when a paragraph declares notes but renders through the revision path,\n * where markers cannot resolve.\n *\n * Supporting note references inside tracked-change runs would mean threading\n * the resolver through `createRevisionRuns` and deciding what an inserted or\n * deleted reference even means on accept/reject. Until that exists, the\n * combination is announced rather than swallowed.\n */\nfunction reportNotesUnsupportedInRevision(\n footnotes: readonly Note[] | undefined,\n endnotes: readonly Note[] | undefined,\n revision: Revision\n): void {\n const declared = [...(footnotes ?? []), ...(endnotes ?? [])];\n if (declared.length === 0) return;\n\n const text = revision.segments.map((segment) => segment.text).join('');\n const referenced = declared.filter((note) => text.includes(`[^${note.id}]`));\n console.warn(\n `Paragraph declares ${declared.length} note(s) (${declared\n .map((note) => note.id)\n .join(', ')}) alongside a \\`revision\\`. Tracked-change text renders ` +\n 'literally, so note markers are not resolved there' +\n (referenced.length > 0\n ? ` — the marker(s) ${referenced\n .map((note) => `[^${note.id}]`)\n .join(', ')} will render as literal text`\n : '') +\n '. The notes will not appear in the document.'\n );\n}\n\n/**\n * Wrap paragraph children in a comment range, or return them untouched when\n * there is no comment.\n *\n * Empty `children` is deliberately allowed: a comment on an empty table cell\n * anchors as a zero-length range plus its reference, which is what Word writes\n * for a comment on an empty selection. Dropping the comment instead would lose\n * both the anchor and the body.\n */\nfunction wrapInComment(\n children: ParagraphChild[],\n comment: Comment | undefined\n): ParagraphChild[] {\n const anchor = openCommentRange(comment);\n if (!anchor) return children;\n return [...anchor.start, ...children, ...closeCommentRange(anchor.ids)];\n}\n\n/**\n * Create a text paragraph\n */\nexport function createText(\n content: string,\n theme: ThemeConfig,\n themeName: string,\n options: TextOptions = {}\n): Paragraph {\n const normalizedContent = normalizeUnicodeText(content);\n // Always use Normal style for consistent formatting\n const style = options.style || 'Normal';\n\n // Convert points to twips for spacing\n const spacing: any = {};\n if (options.spacing?.before !== undefined) {\n spacing.before = pointsToTwips(options.spacing.before);\n }\n if (options.spacing?.after !== undefined) {\n spacing.after = pointsToTwips(options.spacing.after);\n }\n // Add line spacing if provided\n const lineSpacingConfig = convertLineSpacingToDocx(options.lineSpacing);\n if (lineSpacingConfig) {\n spacing.line = lineSpacingConfig.line;\n spacing.lineRule = lineSpacingConfig.lineRule;\n }\n\n // Build children array\n const children: ParagraphChild[] = [];\n\n // Add column break if requested\n if (options.columnBreak) {\n children.push(new ColumnBreak());\n }\n\n // Open the comment range before the text runs so the anchor covers exactly\n // the commented content (and not a preceding column break).\n const commentAnchor = openCommentRange(options.comment);\n if (commentAnchor) {\n children.push(...commentAnchor.start);\n }\n\n // Resolve the effective family so fontWeight can be aliased even when the\n // run relies on the theme's body font (no inline `family` override). Without\n // this, `{ font: { fontWeight: 300 } }` would fall through with no family\n // for the alias registry to look up.\n const hasWeightRequest = options.fontWeight != null || options.bold === true;\n const effectiveFamily =\n options.fontFamily ??\n (hasWeightRequest ? resolveFontFamily(theme, 'body') : undefined);\n const weighted = applyFontWeightAlias({\n fontFamily: effectiveFamily,\n bold: options.bold,\n italic: options.italic,\n fontWeight: options.fontWeight,\n });\n const baseTextStyle = {\n // Only emit `font` when it came from the caller or from an alias —\n // emitting the theme body family on every run would be a behavior change.\n ...((options.fontFamily ||\n (weighted.font && weighted.font !== effectiveFamily)) && {\n font: weighted.font,\n }),\n ...(options.fontSize && { size: options.fontSize * 2 }), // Convert points to half-points\n ...(options.fontColor && {\n color: resolveColor(options.fontColor, theme),\n }),\n ...(weighted.bold !== undefined && { bold: weighted.bold }),\n ...(weighted.italics !== undefined && { italics: weighted.italics }),\n ...(options.underline !== undefined && {\n underline: options.underline ? { type: 'single' as const } : undefined,\n }),\n // Character width scaling in percent (w:w)\n ...(options.scale && { scale: options.scale }),\n // Letter tracking (w:spacing, twentieths of a point; negative = condensed)\n ...(options.characterSpacing && {\n characterSpacing:\n options.characterSpacing.type === 'condensed'\n ? -options.characterSpacing.value\n : options.characterSpacing.value,\n }),\n // Proofing: per-run language and/or no-proof. Omitting language lets the\n // run inherit the document default set on docDefaults.\n ...(options.language && { language: { value: options.language } }),\n ...(options.noProof !== undefined && { noProof: options.noProof }),\n };\n\n if (options.revision) {\n // Tracked changes: render revision segments as native w:ins/w:del runs\n // (literal text, no markdown parsing). Bookmarks are preserved so\n // internal hyperlinks targeting this paragraph keep working.\n //\n // Revision segments render literally, so a `[^id]` marker inside them stays\n // literal text and its body is never emitted. Report that rather than\n // dropping the declared notes in silence.\n reportNotesUnsupportedInRevision(\n options.footnotes,\n options.endnotes,\n options.revision\n );\n const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);\n if (options.bookmarkId) {\n globalBookmarkRegistry.register(\n options.bookmarkId,\n normalizedContent,\n 'paragraph'\n );\n children.push(\n ...createBookmarkedContent(options.bookmarkId, revisionRuns)\n );\n } else {\n children.push(...revisionRuns);\n }\n } else {\n // Note bodies reach word/footnotes.xml or word/endnotes.xml only when a\n // marker resolves to them, so the resolver is built once per paragraph,\n // consulted by the parser as it walks the text, and asked afterwards what\n // went unused.\n const noteResolver = createNoteResolver(\n options.footnotes,\n options.endnotes\n );\n\n // Add text content - parseTextWithDecorators handles both decorators and newlines\n const textRuns = parseTextWithDecorators(normalizedContent, baseTextStyle, {\n boldColor: options.boldColor\n ? resolveColor(options.boldColor, theme)\n : undefined,\n enableHyperlinks: true,\n noProofWords: resolveNoProofWords(theme, options.noProofWords),\n noteRef: noteResolver?.resolve,\n });\n noteResolver?.reportUnemitted(normalizedContent);\n\n // If bookmarkId is provided, wrap text runs in a bookmark\n if (options.bookmarkId) {\n // Register bookmark\n globalBookmarkRegistry.register(\n options.bookmarkId,\n normalizedContent,\n 'paragraph'\n );\n\n // Wrap text runs in bookmark\n children.push(...createBookmarkedContent(options.bookmarkId, textRuns));\n } else {\n // No bookmark, add text runs directly\n children.push(...textRuns);\n }\n }\n\n if (commentAnchor) {\n children.push(...closeCommentRange(commentAnchor.ids));\n }\n\n // Build frame options for floating text\n const isFloating = !!options.floating;\n const frameOptions =\n isFloating && options.floating\n ? mapFrameOptions(options.floating, theme, themeName)\n : undefined;\n\n return new Paragraph({\n children,\n style,\n alignment: options.alignment ? getAlignment(options.alignment) : undefined,\n spacing,\n ...(options.outlineLevel !== undefined && {\n outlineLevel: options.outlineLevel,\n }),\n ...(frameOptions && { frame: frameOptions }),\n ...(options.keepNext !== undefined && { keepNext: options.keepNext }),\n ...(options.keepLines !== undefined && { keepLines: options.keepLines }),\n ...(options.indent && { indent: options.indent }),\n ...(options.tabStops &&\n options.tabStops.length > 0 && { tabStops: options.tabStops }),\n });\n}\n\n/**\n * Map floating frame configuration to docx.js IFrameOptions\n * IFrameOptions can be either IXYFrameOptions (absolute positioning) or IAlignmentFrameOptions (aligned positioning)\n *\n * Supports mixed positioning: alignment on one axis, offset on the other.\n * When mixing, calculates the position for the aligned axis.\n */\nfunction mapFrameOptions(\n floating: NonNullable<TextOptions['floating']>,\n theme?: ThemeConfig,\n themeName?: string\n): any {\n const hasHorizontalOffset = floating.horizontalPosition?.offset !== undefined;\n const hasVerticalOffset = floating.verticalPosition?.offset !== undefined;\n const hasHorizontalAlign = floating.horizontalPosition?.align !== undefined;\n const hasVerticalAlign = floating.verticalPosition?.align !== undefined;\n\n // Choose exactly one mode: absolute if any offset is present; otherwise alignment\n const useAbsolute = hasHorizontalOffset || hasVerticalOffset;\n\n // Base frame options\n const frameWidth = floating.width || 2880; // 2in default\n const frameHeight = floating.height || 1440; // 1in default\n\n const baseOptions: any = {\n width: frameWidth,\n height: frameHeight,\n anchor: {\n horizontal: floating.horizontalPosition?.relative || 'page',\n vertical: floating.verticalPosition?.relative || 'page',\n },\n };\n\n if (floating.wrap?.type) {\n baseOptions.wrap = floating.wrap.type;\n }\n\n // Config lockAnchor maps to docx anchorLock\n if (floating.lockAnchor !== undefined) {\n baseOptions.anchorLock = floating.lockAnchor;\n } else if ((floating as any).anchorLock !== undefined) {\n baseOptions.anchorLock = (floating as any).anchorLock;\n }\n\n if (useAbsolute) {\n const rawX = floating.horizontalPosition?.offset ?? 0;\n const rawY = floating.verticalPosition?.offset ?? 0;\n let x: number;\n let y: number;\n if (typeof rawX === 'string' || typeof rawY === 'string') {\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n const hRef =\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(theme, themeName)\n : getPageWidthTwips(theme, themeName);\n const vRef =\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(theme, themeName)\n : getPageHeightTwips(theme, themeName);\n x = resolveOffsetTwips(rawX, hRef);\n y = resolveOffsetTwips(rawY, vRef);\n } else {\n x = rawX;\n y = rawY;\n }\n return {\n type: 'absolute',\n position: { x, y },\n ...baseOptions,\n };\n }\n\n // Alignment positioning: use provided aligns; default missing axis\n const xAlign = hasHorizontalAlign\n ? floating.horizontalPosition!.align!\n : 'left';\n const yAlign = hasVerticalAlign ? floating.verticalPosition!.align! : 'top';\n return {\n type: 'alignment',\n alignment: { x: xAlign, y: yAlign },\n ...baseOptions,\n };\n}\n\n/**\n * Create a header paragraph\n */\nexport function createHeading(\n text: string,\n level: number,\n theme: ThemeConfig,\n _themeName: string,\n options: TextOptions = {}\n): Paragraph {\n const normalizedText = normalizeUnicodeText(text);\n const styleId = getStyleIdForLevel(level);\n\n // Only apply spacing if explicitly provided in options\n // This allows theme style spacing to be used by default\n const spacing: any = {};\n let hasExplicitSpacing = false;\n\n if (options.spacing?.before !== undefined) {\n spacing.before = pointsToTwips(options.spacing.before);\n hasExplicitSpacing = true;\n }\n if (options.spacing?.after !== undefined) {\n spacing.after = pointsToTwips(options.spacing.after);\n hasExplicitSpacing = true;\n }\n // Add line spacing if provided\n const lineSpacingConfig = convertLineSpacingToDocx(options.lineSpacing);\n if (lineSpacingConfig) {\n spacing.line = lineSpacingConfig.line;\n spacing.lineRule = lineSpacingConfig.lineRule;\n hasExplicitSpacing = true;\n }\n\n // Build children array\n const children: any[] = [];\n\n // Add prepended children first (e.g., bookmarks)\n if (options.prependChildren) {\n children.push(...options.prependChildren);\n }\n\n // Add column break if requested\n if (options.columnBreak) {\n children.push(new ColumnBreak());\n }\n\n // Open the comment range around the heading text only.\n const commentAnchor = openCommentRange(options.comment);\n if (commentAnchor) {\n children.push(...commentAnchor.start);\n }\n\n // Anything the inline parser has to see: markdown decorators, or a `[@id]`\n // cross-reference. Simple headings take the cheaper run builder below, which\n // treats every character as literal text.\n const hasInlineSyntax =\n /(\\*\\*\\*|___|(\\*\\*|__)|(\\*|_))/.test(normalizedText) ||\n hasCrossReference(normalizedText);\n\n // Headings default to theme.fonts.heading when no explicit family is given.\n // Resolve it so fontWeight can be aliased through the same path as body runs.\n const headingHasWeightRequest =\n options.fontWeight != null || options.bold === true;\n const headingEffectiveFamily =\n options.fontFamily ??\n (headingHasWeightRequest ? resolveFontFamily(theme, 'heading') : undefined);\n const headingWeighted = applyFontWeightAlias({\n fontFamily: headingEffectiveFamily,\n bold: options.bold,\n italic: options.italic,\n fontWeight: options.fontWeight,\n });\n // Build base text style from options (overrides theme style at run level)\n const baseTextStyle = {\n ...((options.fontFamily ||\n (headingWeighted.font &&\n headingWeighted.font !== headingEffectiveFamily)) && {\n font: headingWeighted.font,\n }),\n ...(options.fontSize && { size: options.fontSize * 2 }), // points to half-points\n ...(options.fontColor && { color: resolveColor(options.fontColor, theme) }),\n ...(headingWeighted.bold !== undefined && { bold: headingWeighted.bold }),\n ...(headingWeighted.italics !== undefined && {\n italics: headingWeighted.italics,\n }),\n ...(options.underline !== undefined && {\n underline: options.underline ? { type: 'single' as const } : undefined,\n }),\n // Character width scaling in percent (w:w)\n ...(options.scale && { scale: options.scale }),\n // Letter tracking (w:spacing, twentieths of a point; negative = condensed)\n ...(options.characterSpacing && {\n characterSpacing:\n options.characterSpacing.type === 'condensed'\n ? -options.characterSpacing.value\n : options.characterSpacing.value,\n }),\n // Proofing: per-run language and/or no-proof (see createText).\n ...(options.language && { language: { value: options.language } }),\n ...(options.noProof !== undefined && { noProof: options.noProof }),\n };\n\n // Known-words allowlist (document + component) and a run builder that marks\n // matched words as no-proof. Used by the simple (no-decorator) heading paths;\n // the decorator paths route through parseTextWithDecorators instead.\n const headingNoProofWords = resolveNoProofWords(theme, options.noProofWords);\n const makeHeadingRuns = (value: string): TextRun[] =>\n splitByNoProofWords(\n value,\n (segment, matched) =>\n new TextRun({\n text: segment,\n ...baseTextStyle,\n ...(matched && { noProof: true }),\n }),\n headingNoProofWords\n );\n\n if (options.revision) {\n // Tracked changes: revision segments replace text rendering. The TOC\n // bookmark is preserved so TOC links and cross-references keep working.\n const revisionRuns = createRevisionRuns(options.revision, baseTextStyle);\n if (options.bookmarkId) {\n globalBookmarkRegistry.register(\n options.bookmarkId,\n normalizedText,\n 'heading'\n );\n children.push(\n ...createBookmarkedContent(options.bookmarkId, revisionRuns)\n );\n } else {\n children.push(...revisionRuns);\n }\n } else if (options.bookmarkId) {\n // Register bookmark\n globalBookmarkRegistry.register(\n options.bookmarkId,\n normalizedText,\n 'heading'\n );\n\n // Wrap heading text in bookmark\n const headingTextChildren: (TextRun | any)[] = [];\n\n if (hasInlineSyntax) {\n // For headings with decorators, parse text runs first\n const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {\n boldColor: options.boldColor\n ? resolveColor(options.boldColor, theme)\n : undefined,\n enableHyperlinks: true,\n noProofWords: headingNoProofWords,\n });\n headingTextChildren.push(...textRuns);\n } else {\n // For simple headings, add single text run (split on known words)\n headingTextChildren.push(...makeHeadingRuns(normalizedText));\n }\n\n // Wrap in bookmark\n children.push(\n ...createBookmarkedContent(options.bookmarkId, headingTextChildren)\n );\n } else {\n // No bookmark, add text directly\n if (hasInlineSyntax) {\n // For headings with decorators, parse and add text runs\n const textRuns = parseTextWithDecorators(normalizedText, baseTextStyle, {\n boldColor: options.boldColor\n ? resolveColor(options.boldColor, theme)\n : undefined,\n enableHyperlinks: true,\n noProofWords: headingNoProofWords,\n });\n children.push(...textRuns);\n } else {\n // For simple headings, add single text run (split on known words)\n children.push(...makeHeadingRuns(normalizedText));\n }\n }\n\n if (commentAnchor) {\n children.push(...closeCommentRange(commentAnchor.ids));\n }\n\n return new Paragraph({\n children,\n style: styleId,\n alignment: getAlignment(options.alignment || 'left'),\n // Only override spacing if explicitly provided\n spacing: hasExplicitSpacing ? spacing : undefined,\n ...(options.keepNext !== undefined && { keepNext: options.keepNext }),\n ...(options.keepLines !== undefined && { keepLines: options.keepLines }),\n ...(options.indent && { indent: options.indent }),\n // docx creates the concrete numbering instance for the reference itself,\n // in ParagraphProperties.prepForXml.\n ...(options.numbering !== undefined && { numbering: options.numbering }),\n });\n}\n\n/**\n * Create title page content\n */\nexport function createTitleContent(\n title?: string,\n subtitle?: string\n): Paragraph[] {\n // If no title, return empty array (skip title section entirely)\n if (!title) {\n return [];\n }\n\n const normalizedTitle = normalizeUnicodeText(title);\n const elements: Paragraph[] = [];\n\n elements.push(\n new Paragraph({\n text: normalizedTitle,\n style: 'Title',\n })\n );\n\n if (subtitle) {\n const normalizedSubtitle = normalizeUnicodeText(subtitle);\n elements.push(\n new Paragraph({\n text: normalizedSubtitle,\n style: 'Subtitle',\n })\n );\n }\n\n elements.push(new Paragraph({ children: [new PageBreak()] }));\n\n return elements;\n}\n\n/**\n * Create an image with optional caption\n */\nexport async function createImage(\n path: string,\n theme: ThemeConfig,\n themeName?: string,\n options: ImageOptions = {}\n): Promise<Paragraph[]> {\n const elements: Paragraph[] = [];\n const isFloating = !!options.floating;\n const alignment = isFloating\n ? undefined\n : getAlignment(options.alignment || 'center');\n\n let imagePath = path;\n let imageBuffer: Buffer;\n let responseContentType: string | undefined;\n\n try {\n // Try to use the provided path first\n const imageResult = await getImageBuffer(imagePath);\n imageBuffer = imageResult.buffer;\n responseContentType = imageResult.contentType;\n\n // Calculate available document width/height for percentage calculations\n const {\n getAvailableWidthTwips,\n getPageWidthTwips,\n getAvailableHeightTwips,\n getPageHeightTwips,\n } = await import('../utils/widthUtils');\n const widthRef = options.widthRelativeTo || 'content';\n const heightRef = options.heightRelativeTo || 'content';\n const availableWidthTwips =\n widthRef === 'page'\n ? getPageWidthTwips(theme)\n : getAvailableWidthTwips(theme);\n const availableHeightTwips =\n heightRef === 'page'\n ? getPageHeightTwips(theme)\n : getAvailableHeightTwips(theme);\n // Convert twips to pixels: 1 twip = 1/1440 inch, 1 inch = 96 pixels (screen DPI)\n const availableWidthPx = Math.round((availableWidthTwips / 1440) * 96);\n const availableHeightPx = Math.round((availableHeightTwips / 1440) * 96);\n\n // Default size calculations (fallback)\n const columnWidthCm = 7.36;\n const pixelsPerCm = 37.795275591;\n const columnWidthPx = Math.round(columnWidthCm * pixelsPerCm);\n const fallbackHeight = Math.round(columnWidthPx * 0.6);\n\n // Parse width value (handles both number and percentage string)\n // Default to 100% if no width is specified\n const parsedWidth = parseWidthValue(\n options.width ?? '100%',\n availableWidthPx\n );\n\n // Parse height value if provided\n const parsedHeight =\n options.height !== undefined\n ? parseDimensionValue(options.height, availableHeightPx)\n : undefined;\n\n // Calculate dimensions with aspect ratio preservation\n const dimensions = await calculateImageDimensions(\n imagePath,\n parsedWidth,\n parsedHeight,\n columnWidthPx,\n fallbackHeight\n );\n\n // Build ImageRun configuration with optional floating\n const { mapFloatingOptions } = await import(\n '../utils/docxImagePositioning'\n );\n const floating = isFloating\n ? mapFloatingOptions(options.floating, theme, themeName)\n : undefined;\n\n // Detect image type from response Content-Type, path, or base64 data URI\n const imageType = detectImageType(imagePath, responseContentType);\n\n // Create ImageRun based on image type\n const imageRun = await createTypedImageRun({\n type: imageType,\n data: imageBuffer,\n transformation: { width: dimensions.width, height: dimensions.height },\n ...(floating && { floating }),\n });\n\n // Convert spacing from points to twips\n const spacing: any = {};\n if (options.spacing?.before !== undefined) {\n spacing.before = pointsToTwips(options.spacing.before);\n }\n if (options.spacing?.after !== undefined) {\n spacing.after = pointsToTwips(options.spacing.after);\n }\n\n elements.push(\n new Paragraph({\n children: [imageRun],\n alignment,\n ...(Object.keys(spacing).length > 0 && { spacing }),\n ...(options.keepNext !== undefined && { keepNext: options.keepNext }),\n ...(options.keepLines !== undefined && {\n keepLines: options.keepLines,\n }),\n })\n );\n } catch (error) {\n // If the image cannot be loaded, try the placeholder\n throw new Error(`Failed to load image from ${imagePath}`);\n }\n\n if (options.caption) {\n // Check if caption has decorators (bold/italic markers)\n const hasDecorators = /(\\*\\*\\*|___|(\\*\\*|__)|(\\*|_))/.test(options.caption);\n\n if (!hasDecorators) {\n // No decorators - use Normal style for font inheritance\n elements.push(\n new Paragraph({\n text: normalizeUnicodeText(options.caption),\n style: 'Normal',\n alignment: AlignmentType.LEFT, // Captions default to left alignment\n })\n );\n } else {\n // Has decorators - use parseTextWithDecorators (same as text component)\n const textRuns = parseTextWithDecorators(\n options.caption,\n {},\n {\n enableHyperlinks: true,\n }\n );\n\n elements.push(\n new Paragraph({\n children: textRuns,\n style: 'Normal', // Use Normal style for consistent font inheritance\n alignment: AlignmentType.LEFT, // Captions default to left alignment\n })\n );\n }\n }\n\n return elements;\n}\n\n/**\n * Create a statistic display\n */\nexport function createStatistic(\n data: StatisticData,\n options: StatisticOptions = {}\n): Paragraph[] {\n const alignment = getAlignment(data.alignment || 'center');\n const normalizedNumber = normalizeUnicodeText(data.number);\n const normalizedDescription = normalizeUnicodeText(data.description);\n\n return [\n new Paragraph({\n text: normalizedNumber,\n style: 'StatisticNumber',\n alignment,\n spacing: options.spacing,\n }),\n new Paragraph({\n text: normalizedDescription,\n style: 'StatisticDescription',\n alignment,\n }),\n ];\n}\n\n/**\n * Create a list of items using proper docx numbering\n */\nexport function createList(\n items: (\n | string\n | { text: string; level?: number; id?: string; revision?: Revision }\n )[],\n _theme: ThemeConfig,\n _themeName: string,\n options: ListOptions = {}\n): Paragraph[] {\n if (!items || items.length === 0) {\n return [];\n }\n\n const paragraphs: Paragraph[] = [];\n\n // A list-level comment spans the whole list, so its range opens on the first\n // paragraph that actually renders and closes on the last. Empty items are\n // skipped below, so neither end can be read off the item index — and docx\n // copies `children` at construction, so both ends must be known up front.\n // One resolver for the whole list: ids are declared on the list, and markers\n // may appear in any item.\n const noteResolver = createNoteResolver(options.footnotes, options.endnotes);\n\n const rendersAt = items.map((item) => {\n const text = typeof item === 'string' ? item : item.text;\n const revision = typeof item === 'object' ? item.revision : undefined;\n return Boolean(text.trim()) || Boolean(revision);\n });\n const firstRendered = rendersAt.indexOf(true);\n const lastRendered = rendersAt.lastIndexOf(true);\n const commentAnchor =\n firstRendered === -1 ? undefined : openCommentRange(options.comment);\n\n items.forEach((item, index) => {\n // Handle both string and object items\n const itemText = typeof item === 'string' ? item : item.text;\n const itemLevel = typeof item === 'object' ? item.level || 0 : 0;\n const itemRevision = typeof item === 'object' ? item.revision : undefined;\n\n // Skip empty items — unless they carry revision data (a fully deleted\n // item has empty new text but must still render its w:del runs)\n if (!itemText.trim() && !itemRevision) {\n return;\n }\n\n // Parse rich text decorators for each item\n // Don't pass font/size/color - let list items inherit from Normal paragraph style\n const textRuns = itemRevision\n ? createRevisionRuns(itemRevision, {})\n : parseTextWithDecorators(\n itemText,\n {},\n {\n enableHyperlinks: true,\n noteRef: noteResolver?.resolve,\n }\n );\n\n // Calculate spacing for this item (convert points to twips)\n const spacing: { before?: number; after?: number } = {};\n if (index === 0 && options.spacing?.before) {\n spacing.before = pointsToTwips(options.spacing.before);\n }\n if (index === items.length - 1 && options.spacing?.after) {\n spacing.after = pointsToTwips(options.spacing.after);\n } else if (options.spacing?.item) {\n spacing.after = pointsToTwips(options.spacing.item);\n }\n\n // A bookmarked item is a cross-reference target (`[@id]`) and an internal\n // link target. The bookmark wraps the text runs only — the comment range\n // stays outside it, as it does on a heading.\n const itemId = typeof item === 'object' ? item.id : undefined;\n let itemContent: ParagraphChild[] = textRuns;\n if (itemId) {\n globalBookmarkRegistry.register(itemId, itemText, 'list-item');\n itemContent = createBookmarkedContent(itemId, textRuns);\n }\n\n // Create the paragraph with proper numbering reference\n const paragraphChildren: ParagraphChild[] = [\n ...(commentAnchor && index === firstRendered ? commentAnchor.start : []),\n ...itemContent,\n ...(commentAnchor && index === lastRendered\n ? closeCommentRange(commentAnchor.ids)\n : []),\n ];\n\n const paragraph = new Paragraph({\n style: 'Normal', // Apply Normal style for font inheritance\n children: paragraphChildren,\n alignment: options.alignment\n ? getAlignment(options.alignment)\n : AlignmentType.LEFT,\n spacing,\n // Use proper docx numbering instead of prepending text\n ...(options.numberingReference && {\n numbering: {\n reference: options.numberingReference,\n level: itemLevel,\n },\n }),\n });\n\n paragraphs.push(paragraph);\n });\n\n noteResolver?.reportUnemitted(\n items\n .map((item) => (typeof item === 'string' ? item : item.text))\n .join('\\n')\n );\n\n return paragraphs;\n}\n\n/**\n * Create a table\n */\ntype TableFontConfig = {\n family?: string;\n size?: number;\n bold?: boolean;\n fontWeight?: number;\n italic?: boolean;\n underline?: boolean;\n};\n\ntype BorderColor =\n | string\n | {\n bottom?: string;\n top?: string;\n right?: string;\n left?: string;\n };\n\ntype BorderSize =\n | number\n | {\n bottom?: number;\n top?: number;\n right?: number;\n left?: number;\n };\n\ntype Padding =\n | number\n | {\n bottom?: number;\n top?: number;\n right?: number;\n left?: number;\n };\n\ntype CellDefaults = {\n color?: string;\n backgroundColor?: string;\n horizontalAlignment?: 'left' | 'center' | 'right' | 'justify';\n verticalAlignment?: 'top' | 'middle' | 'bottom';\n font?: TableFontConfig;\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n padding?: Padding;\n height?: number;\n};\n\n// After merging, borders and padding are always normalized to per-side format\ntype NormalizedCellDefaults = {\n color?: string;\n backgroundColor?: string;\n horizontalAlignment?: 'left' | 'center' | 'right' | 'justify';\n verticalAlignment?: 'top' | 'middle' | 'bottom';\n font?: TableFontConfig;\n borderColor: { top: string; right: string; bottom: string; left: string };\n borderSize: { top: number; right: number; bottom: number; left: number };\n padding?: { top: number; right: number; bottom: number; left: number };\n height?: number;\n};\n\n// Hide borders configuration - can be boolean or per-side object\ntype HideBorders =\n | boolean\n | {\n top?: boolean;\n right?: boolean;\n bottom?: boolean;\n left?: boolean;\n insideHorizontal?: boolean;\n insideVertical?: boolean;\n };\n\ntype TableConfig = {\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n hideBorders?: HideBorders;\n cellDefaults?: CellDefaults;\n headerCellDefaults?: CellDefaults;\n width?: number;\n columns: {\n /** Width in points (number) or as percentage string e.g. \"40%\" */\n width?: number | string;\n cellDefaults?: CellDefaults;\n header?: CellDefaults & {\n comment?: Comment;\n revision?: Revision;\n content?: string | ComponentDefinition;\n };\n cells?: (CellDefaults & {\n comment?: Comment;\n revision?: Revision;\n content?: string | ComponentDefinition;\n })[];\n }[];\n /** Row-parallel properties, indexed like `columns[].cells`. */\n rows?: {\n revision?: RevisionMark;\n cantSplit?: boolean;\n tableHeader?: boolean;\n }[];\n keepInOnePage?: boolean;\n keepNext?: boolean;\n repeatHeaderOnPageBreak?: boolean;\n};\n\nexport async function createTable(\n columns: TableConfig['columns'],\n tableConfig: TableConfig,\n theme: ThemeConfig,\n themeName: string,\n _options: TableOptions = {}\n): Promise<Table> {\n // Note: _options parameter is available for future table customization\n const tableStyle = getTableStyle(theme, themeName);\n\n // Determine number of rows from the first column\n const numRows = columns[0]?.cells?.length || 0;\n\n // Default values for missing cell defaults\n const getDefaultCellDefaults = (): CellDefaults => ({\n color: '000000',\n backgroundColor: 'transparent',\n horizontalAlignment: 'left',\n verticalAlignment: 'top',\n font: {\n family: 'Arial',\n size: 11,\n bold: false,\n italic: false,\n underline: false,\n },\n borderColor: '000000',\n borderSize: 1,\n });\n\n // No warning collector reaches createTable (the render path passes only\n // theme/themeName), so use the prefixed console.warn fallback the generator\n // uses when no collector is present. Deduped so a column of cells sharing the\n // same bad value warns once per table.\n const warnedCellColors = new Set<string>();\n const warnCellColor = (code: string, message: string): void => {\n if (warnedCellColors.has(message)) return;\n warnedCellColors.add(message);\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] ${code}: ${message}`);\n };\n\n // Resolve a cell color the same way paragraph/heading font colors are\n // resolved: theme name (\"primary\") or \"#RRGGBB\". Bare 6-digit hex and \"auto\"\n // are passed through — those are the only raw values OOXML itself accepts, so\n // documents relying on them predate theme resolution and must keep working.\n // \"transparent\" is a backgroundColor-only sentinel consumed at the shading\n // site; on the text path nothing consumes it and it is not a legal w:color\n // value, so it is dropped with a warning rather than emitted.\n const resolveCellColor = (\n value: string | undefined,\n prop: 'color' | 'backgroundColor'\n ): string | undefined => {\n if (value === undefined || value === 'auto') return value;\n if (value === 'transparent') {\n if (prop === 'backgroundColor') return value;\n warnCellColor(\n 'TABLE_CELL_COLOR_INVALID',\n `\"transparent\" is not a valid table cell \"color\"; ignoring it and using the table style color. It only applies to \"backgroundColor\".`\n );\n return undefined;\n }\n if (/^[0-9A-Fa-f]{6}$/.test(value)) return value.toUpperCase();\n try {\n return resolveColor(value, theme);\n } catch {\n // Passing the value through instead would not save the document: docx\n // rejects any non-hex, non-\"auto\" fill/color, so it would still fail —\n // deeper in the stack with an opaque message.\n const allowed =\n prop === 'backgroundColor'\n ? '\"auto\", or \"transparent\" for no shading'\n : 'or \"auto\"';\n throw new Error(\n `Invalid table cell ${prop}: \"${value}\". Must be a hex color with # prefix (e.g. \"#000000\"), a theme color name, ${allowed}.`\n );\n }\n };\n\n // Helper function to normalize border color to per-side format\n const normalizeBorderColor = (\n border: BorderColor | undefined\n ):\n | { top: string; right: string; bottom: string; left: string }\n | undefined => {\n if (border === undefined) return undefined;\n if (typeof border === 'string') {\n return { top: border, right: border, bottom: border, left: border };\n }\n return {\n top: border.top ?? '',\n right: border.right ?? '',\n bottom: border.bottom ?? '',\n left: border.left ?? '',\n };\n };\n\n // Helper function to normalize border size to per-side format\n const normalizeBorderSize = (\n border: BorderSize | undefined\n ):\n | { top: number; right: number; bottom: number; left: number }\n | undefined => {\n if (border === undefined) return undefined;\n if (typeof border === 'number') {\n return { top: border, right: border, bottom: border, left: border };\n }\n return {\n top: border.top ?? -1,\n right: border.right ?? -1,\n bottom: border.bottom ?? -1,\n left: border.left ?? -1,\n };\n };\n\n // Helper function to normalize padding to per-side format\n const normalizePadding = (\n padding: Padding | undefined\n ):\n | { top: number; right: number; bottom: number; left: number }\n | undefined => {\n if (padding === undefined) return undefined;\n if (typeof padding === 'number') {\n return { top: padding, right: padding, bottom: padding, left: padding };\n }\n return {\n top: padding.top ?? -1,\n right: padding.right ?? -1,\n bottom: padding.bottom ?? -1,\n left: padding.left ?? -1,\n };\n };\n\n // Helper function to merge border colors at the side level\n const mergeBorderColorPerSide = (\n ...borders: (BorderColor | undefined)[]\n ): { top: string; right: string; bottom: string; left: string } => {\n const normalized = borders.map(normalizeBorderColor);\n const defaults = getDefaultCellDefaults();\n const defaultColor =\n typeof defaults.borderColor === 'string'\n ? defaults.borderColor\n : '000000';\n\n return {\n top: normalized.find((b) => b && b.top !== '')?.top ?? defaultColor,\n right: normalized.find((b) => b && b.right !== '')?.right ?? defaultColor,\n bottom:\n normalized.find((b) => b && b.bottom !== '')?.bottom ?? defaultColor,\n left: normalized.find((b) => b && b.left !== '')?.left ?? defaultColor,\n };\n };\n\n // Helper function to merge border sizes at the side level\n const mergeBorderSizePerSide = (\n ...borders: (BorderSize | undefined)[]\n ): { top: number; right: number; bottom: number; left: number } => {\n const normalized = borders.map(normalizeBorderSize);\n const defaults = getDefaultCellDefaults();\n const defaultSize =\n typeof defaults.borderSize === 'number' ? defaults.borderSize : 1;\n\n return {\n top: normalized.find((b) => b && b.top !== -1)?.top ?? defaultSize,\n right: normalized.find((b) => b && b.right !== -1)?.right ?? defaultSize,\n bottom:\n normalized.find((b) => b && b.bottom !== -1)?.bottom ?? defaultSize,\n left: normalized.find((b) => b && b.left !== -1)?.left ?? defaultSize,\n };\n };\n\n // Helper to create border override for table outer borders based on position\n const getTableOuterBorder = (\n position: {\n isHeader?: boolean;\n isFirstCol?: boolean;\n isLastCol?: boolean;\n isLastRow?: boolean;\n },\n tableBorderColor?: BorderColor,\n tableBorderSize?: BorderSize\n ): {\n borderColor?: Partial<{\n top: string;\n right: string;\n bottom: string;\n left: string;\n }>;\n borderSize?: Partial<{\n top: number;\n right: number;\n bottom: number;\n left: number;\n }>;\n } => {\n const result: {\n borderColor?: Partial<{\n top: string;\n right: string;\n bottom: string;\n left: string;\n }>;\n borderSize?: Partial<{\n top: number;\n right: number;\n bottom: number;\n left: number;\n }>;\n } = {};\n\n if (tableBorderColor) {\n const normalizedColor = normalizeBorderColor(tableBorderColor);\n if (normalizedColor) {\n result.borderColor = {};\n if (position.isHeader && normalizedColor.top !== '')\n result.borderColor.top = normalizedColor.top;\n if (position.isFirstCol && normalizedColor.left !== '')\n result.borderColor.left = normalizedColor.left;\n if (position.isLastCol && normalizedColor.right !== '')\n result.borderColor.right = normalizedColor.right;\n if (position.isLastRow && normalizedColor.bottom !== '')\n result.borderColor.bottom = normalizedColor.bottom;\n }\n }\n\n if (tableBorderSize) {\n const normalizedSize = normalizeBorderSize(tableBorderSize);\n if (normalizedSize) {\n result.borderSize = {};\n if (position.isHeader && normalizedSize.top !== -1)\n result.borderSize.top = normalizedSize.top;\n if (position.isFirstCol && normalizedSize.left !== -1)\n result.borderSize.left = normalizedSize.left;\n if (position.isLastCol && normalizedSize.right !== -1)\n result.borderSize.right = normalizedSize.right;\n if (position.isLastRow && normalizedSize.bottom !== -1)\n result.borderSize.bottom = normalizedSize.bottom;\n }\n }\n\n return result;\n };\n\n // Helper function to merge padding at the side level\n const mergePaddingPerSide = (\n ...paddings: (Padding | undefined)[]\n ):\n | { top: number; right: number; bottom: number; left: number }\n | undefined => {\n const normalized = paddings.map(normalizePadding);\n const hasAny = normalized.some((p) => p !== undefined);\n if (!hasAny) return undefined;\n\n return {\n top: normalized.find((p) => p && p.top !== -1)?.top ?? 0,\n right: normalized.find((p) => p && p.right !== -1)?.right ?? 0,\n bottom: normalized.find((p) => p && p.bottom !== -1)?.bottom ?? 0,\n left: normalized.find((p) => p && p.left !== -1)?.left ?? 0,\n };\n };\n\n // Helper function to merge cell defaults with priority: cell > column > table outer border (for specific sides) > table cellDefaults > default\n const mergeCellDefaults = (\n tableDef?: CellDefaults,\n columnDef?: CellDefaults,\n cellDef?: Partial<CellDefaults>,\n position?: {\n isFirstCol?: boolean;\n isLastCol?: boolean;\n isLastRow?: boolean;\n },\n tableOuterBorder?: { borderColor?: BorderColor; borderSize?: BorderSize }\n ): NormalizedCellDefaults => {\n const defaults = getDefaultCellDefaults();\n\n // Merge font configs\n const mergedFont: TableFontConfig = {\n ...defaults.font,\n ...tableDef?.font,\n ...columnDef?.font,\n ...cellDef?.font,\n };\n\n // Get table outer border overrides based on position\n const outerBorder =\n position && tableOuterBorder\n ? getTableOuterBorder(\n position,\n tableOuterBorder.borderColor,\n tableOuterBorder.borderSize\n )\n : {};\n\n // Merge border colors per side (priority: cell > column > table outer border > table cellDefaults > table borderColor > default)\n // tableOuterBorder.borderColor is used twice: via outerBorder for edge-specific application,\n // and directly as fallback for ALL borders when not overridden by cellDefaults\n const mergedBorderColor = mergeBorderColorPerSide(\n cellDef?.borderColor,\n columnDef?.borderColor,\n outerBorder.borderColor as BorderColor,\n tableDef?.borderColor,\n tableOuterBorder?.borderColor // Apply table-level borderColor to all cells as fallback\n );\n\n // Merge border sizes per side (priority: cell > column > table outer border > table cellDefaults > table borderSize > default)\n const mergedBorderSize = mergeBorderSizePerSide(\n cellDef?.borderSize,\n columnDef?.borderSize,\n outerBorder.borderSize as BorderSize,\n tableDef?.borderSize,\n tableOuterBorder?.borderSize // Apply table-level borderSize to all cells as fallback\n );\n\n // Merge padding per side (priority: cell > column > table)\n const mergedPadding = mergePaddingPerSide(\n cellDef?.padding,\n columnDef?.padding,\n tableDef?.padding\n );\n\n return {\n color: resolveCellColor(\n cellDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,\n 'color'\n ),\n backgroundColor: resolveCellColor(\n cellDef?.backgroundColor ??\n columnDef?.backgroundColor ??\n tableDef?.backgroundColor ??\n defaults.backgroundColor,\n 'backgroundColor'\n ),\n horizontalAlignment:\n cellDef?.horizontalAlignment ??\n columnDef?.horizontalAlignment ??\n tableDef?.horizontalAlignment ??\n defaults.horizontalAlignment,\n verticalAlignment:\n cellDef?.verticalAlignment ??\n columnDef?.verticalAlignment ??\n tableDef?.verticalAlignment ??\n defaults.verticalAlignment,\n font: mergedFont,\n borderColor: mergedBorderColor,\n borderSize: mergedBorderSize,\n padding: mergedPadding,\n height: cellDef?.height ?? columnDef?.height ?? tableDef?.height,\n };\n };\n\n // Helper function to merge header cell defaults with priority: header > columnCellDefaults > table outer border (for specific sides) > headerCellDefaults > cellDefaults > default\n const mergeHeaderCellDefaults = (\n tableDef?: CellDefaults,\n headerTableDef?: CellDefaults,\n columnDef?: CellDefaults,\n headerDef?: Partial<CellDefaults>,\n position?: { isFirstCol?: boolean; isLastCol?: boolean },\n tableOuterBorder?: { borderColor?: BorderColor; borderSize?: BorderSize }\n ): NormalizedCellDefaults => {\n const defaults = getDefaultCellDefaults();\n\n // Merge font configs with new priority\n const mergedFont: TableFontConfig = {\n ...defaults.font,\n ...tableDef?.font,\n ...headerTableDef?.font,\n ...columnDef?.font,\n ...headerDef?.font,\n };\n\n // Get table outer border overrides based on position (headers always affect top border)\n const outerBorder =\n position && tableOuterBorder\n ? getTableOuterBorder(\n {\n isHeader: true,\n isFirstCol: position.isFirstCol,\n isLastCol: position.isLastCol,\n },\n tableOuterBorder.borderColor,\n tableOuterBorder.borderSize\n )\n : {};\n\n // Merge border colors per side (priority: header > columnCellDefaults > table outer border > headerCellDefaults > cellDefaults > table borderColor > default)\n // tableOuterBorder.borderColor is used twice: via outerBorder for edge-specific application,\n // and directly as fallback for ALL borders when not overridden by cellDefaults\n const mergedBorderColor = mergeBorderColorPerSide(\n headerDef?.borderColor,\n columnDef?.borderColor,\n outerBorder.borderColor as BorderColor,\n headerTableDef?.borderColor,\n tableDef?.borderColor,\n tableOuterBorder?.borderColor // Apply table-level borderColor to all cells as fallback\n );\n\n // Merge border sizes per side (priority: header > columnCellDefaults > table outer border > headerCellDefaults > cellDefaults > table borderSize > default)\n const mergedBorderSize = mergeBorderSizePerSide(\n headerDef?.borderSize,\n columnDef?.borderSize,\n outerBorder.borderSize as BorderSize,\n headerTableDef?.borderSize,\n tableDef?.borderSize,\n tableOuterBorder?.borderSize // Apply table-level borderSize to all cells as fallback\n );\n\n // Merge padding per side (priority: header > headerCellDefaults > columnCellDefaults > cellDefaults)\n const mergedPadding = mergePaddingPerSide(\n headerDef?.padding,\n headerTableDef?.padding,\n columnDef?.padding,\n tableDef?.padding\n );\n\n return {\n color: resolveCellColor(\n headerDef?.color ??\n headerTableDef?.color ??\n columnDef?.color ??\n tableDef?.color ??\n defaults.color,\n 'color'\n ),\n backgroundColor: resolveCellColor(\n headerDef?.backgroundColor ??\n headerTableDef?.backgroundColor ??\n columnDef?.backgroundColor ??\n tableDef?.backgroundColor ??\n defaults.backgroundColor,\n 'backgroundColor'\n ),\n horizontalAlignment:\n headerDef?.horizontalAlignment ??\n headerTableDef?.horizontalAlignment ??\n columnDef?.horizontalAlignment ??\n tableDef?.horizontalAlignment ??\n defaults.horizontalAlignment,\n verticalAlignment:\n headerDef?.verticalAlignment ??\n headerTableDef?.verticalAlignment ??\n columnDef?.verticalAlignment ??\n tableDef?.verticalAlignment ??\n defaults.verticalAlignment,\n font: mergedFont,\n borderColor: mergedBorderColor,\n borderSize: mergedBorderSize,\n padding: mergedPadding,\n height:\n headerDef?.height ??\n headerTableDef?.height ??\n columnDef?.height ??\n tableDef?.height,\n };\n };\n\n // Helper function to get border value for a specific side\n // After normalization, borders are always objects with side properties\n const getBorderValue = (\n border: {\n top: string | number;\n right: string | number;\n bottom: string | number;\n left: string | number;\n },\n side: 'top' | 'bottom' | 'left' | 'right'\n ) => {\n return border[side];\n };\n\n // Helper function to get padding value for a specific side\n // After normalization, padding is always an object with side properties or undefined\n const getPaddingValue = (\n padding:\n | { top: number; right: number; bottom: number; left: number }\n | undefined,\n side: 'top' | 'bottom' | 'left' | 'right'\n ): number | undefined => {\n if (padding === undefined) return undefined;\n return padding[side] * 20; // Convert points to twips\n };\n\n // Helper function to create margins object from padding\n // After normalization, padding is always an object with side properties or undefined\n // Returns ITableCellMarginOptions with marginUnitType set to DXA (twips)\n const createMarginsFromPadding = (\n padding:\n | { top: number; right: number; bottom: number; left: number }\n | undefined\n ) => {\n if (padding === undefined) return undefined;\n\n return {\n marginUnitType: WidthType.DXA, // Specify that values are in twips\n top: getPaddingValue(padding, 'top') ?? 0,\n bottom: getPaddingValue(padding, 'bottom') ?? 0,\n left: getPaddingValue(padding, 'left') ?? 0,\n right: getPaddingValue(padding, 'right') ?? 0,\n };\n };\n\n // Normalize hideBorders config to per-side format\n const normalizeHideBorders = (\n hideBorders: HideBorders | undefined\n ): {\n top: boolean;\n right: boolean;\n bottom: boolean;\n left: boolean;\n insideHorizontal: boolean;\n insideVertical: boolean;\n } => {\n if (hideBorders === undefined) {\n return {\n top: false,\n right: false,\n bottom: false,\n left: false,\n insideHorizontal: false,\n insideVertical: false,\n };\n }\n if (typeof hideBorders === 'boolean') {\n return {\n top: hideBorders,\n right: hideBorders,\n bottom: hideBorders,\n left: hideBorders,\n insideHorizontal: hideBorders,\n insideVertical: hideBorders,\n };\n }\n return {\n top: hideBorders.top ?? false,\n right: hideBorders.right ?? false,\n bottom: hideBorders.bottom ?? false,\n left: hideBorders.left ?? false,\n insideHorizontal: hideBorders.insideHorizontal ?? false,\n insideVertical: hideBorders.insideVertical ?? false,\n };\n };\n\n // Normalized hidden borders config\n const hiddenBorders = normalizeHideBorders(tableConfig.hideBorders);\n\n // Helper function to create border config\n const createBorder = (size: number, color: string, isHidden?: boolean) => {\n if (size === 0 || isHidden) {\n return { style: BorderStyle.NONE, size: 0, color: '000000' };\n }\n return {\n style: BorderStyle.SINGLE,\n size: size * 8, // Convert points to eighths of a point\n color: color || '000000',\n };\n };\n\n // Helper to determine if a specific border should be hidden based on cell position\n const shouldHideBorder = (\n side: 'top' | 'right' | 'bottom' | 'left',\n position: {\n isFirstRow?: boolean;\n isLastRow?: boolean;\n isFirstCol?: boolean;\n isLastCol?: boolean;\n }\n ): boolean => {\n // Map cell position to which hideBorders config applies\n // Outer borders use top/right/bottom/left, inner borders use insideHorizontal/insideVertical\n switch (side) {\n case 'top':\n return position.isFirstRow\n ? hiddenBorders.top\n : hiddenBorders.insideHorizontal;\n case 'bottom':\n return position.isLastRow\n ? hiddenBorders.bottom\n : hiddenBorders.insideHorizontal;\n case 'left':\n return position.isFirstCol\n ? hiddenBorders.left\n : hiddenBorders.insideVertical;\n case 'right':\n return position.isLastCol\n ? hiddenBorders.right\n : hiddenBorders.insideVertical;\n default:\n return false;\n }\n };\n\n // Helper function to process cell content\n const processCellContent = async (\n cell: string | ComponentDefinition | undefined,\n cellDefaults: NormalizedCellDefaults,\n baseCellStyle: typeof tableStyle.tableCell,\n comment?: Comment,\n revision?: Revision,\n /**\n * Set when the whole row is inserted or deleted. The cell's own text then\n * renders as runs marked the same way: a `w:trPr/w:del` alone leaves the\n * text un-struck, and accepting the change would leave an empty row rather\n * than remove it.\n */\n rowMark?: RevisionMark\n // ParagraphChild rather than PlaceholderChild: a revised or commented cell\n // paragraph contributes w:ins / w:del and comment-range elements, which sit\n // outside the placeholder union.\n ): Promise<ParagraphChild[]> => {\n let cellChildren: ParagraphChild[] = [];\n\n // Handle undefined or empty content. A comment on an empty cell still has\n // to anchor somewhere: Word writes a zero-length range plus the reference,\n // which is what `wrapInComment` produces for an empty child list.\n if (!cell) {\n return wrapInComment(cellChildren, comment);\n }\n\n // Create merged style with config overrides\n const cellWeighted = applyFontWeightAlias({\n fontFamily: cellDefaults.font?.family || baseCellStyle.font,\n bold: cellDefaults.font?.bold ?? false,\n italic: cellDefaults.font?.italic ?? false,\n fontWeight: cellDefaults.font?.fontWeight,\n });\n const mergedStyle = {\n font: cellWeighted.font,\n size: cellDefaults.font?.size\n ? cellDefaults.font.size * 2\n : baseCellStyle.size, // Convert to half-points\n bold: cellWeighted.bold ?? false,\n italics: cellWeighted.italics ?? false,\n underline: cellDefaults.font?.underline\n ? { type: 'single' as const }\n : undefined,\n color: cellDefaults.color || baseCellStyle.color,\n };\n\n if (typeof cell === 'object' && 'name' in cell && 'props' in cell) {\n // Handle ComponentDefinition\n if (isParagraphComponent(cell)) {\n const textComp = cell as ParagraphComponentDefinition;\n const paragraphFont = textComp.props.font;\n const paraWeighted = applyFontWeightAlias({\n fontFamily: paragraphFont?.family ?? mergedStyle.font,\n bold: paragraphFont?.bold,\n italic: paragraphFont?.italic,\n fontWeight: paragraphFont?.fontWeight,\n });\n const paragraphStyle = {\n ...mergedStyle,\n ...(paraWeighted.font && { font: paraWeighted.font }),\n ...(paragraphFont?.size && { size: paragraphFont.size * 2 }),\n ...(paraWeighted.bold !== undefined && {\n bold: paraWeighted.bold,\n }),\n ...(paraWeighted.italics !== undefined && {\n italics: paraWeighted.italics,\n }),\n ...(paragraphFont?.underline !== undefined && {\n underline: paragraphFont.underline\n ? { type: 'single' as const }\n : undefined,\n }),\n ...(paragraphFont?.color && {\n color: resolveColor(paragraphFont.color, theme),\n }),\n };\n // Tracked changes take the same revision-aware path createText uses:\n // segments render as native w:ins/w:del runs (literal text, no markdown\n // parsing) instead of being silently dropped in favour of props.text.\n const paragraphRevision = revision ?? textComp.props.revision;\n cellChildren = paragraphRevision\n ? createRevisionRuns(paragraphRevision, paragraphStyle)\n : rowMark\n ? createMarkedTextRuns(textComp.props.text, rowMark, paragraphStyle)\n : parseTextWithDecorators(textComp.props.text, paragraphStyle, {\n enableHyperlinks: true,\n });\n } else if (isImageComponent(cell)) {\n const imageComp = cell as ImageComponentDefinition;\n try {\n // Get image source (svg, base64, or path)\n const imageSource = resolveImageSource(imageComp.props);\n if (!imageSource) {\n throw new Error(\n 'Image component requires one of \"path\", \"base64\", or \"svg\" property'\n );\n }\n\n // Read from local file, URL, or base64\n const imageResult = await getImageBuffer(imageSource);\n\n // Parse width value if it's a string percentage (like \"90%\")\n const parsedWidth =\n typeof imageComp.props.width === 'string'\n ? parseWidthValue(imageComp.props.width, 300) // Use a reasonable default for table context\n : imageComp.props.width;\n\n // Parse height value if it's a string percentage (like \"90%\")\n const parsedHeight =\n typeof imageComp.props.height === 'string'\n ? parseWidthValue(imageComp.props.height, 200) // Use a reasonable default for table context\n : imageComp.props.height;\n\n // Calculate dimensions with aspect ratio preservation\n const dimensions = await calculateImageDimensions(\n imageSource,\n parsedWidth,\n parsedHeight,\n 60, // fallback width\n 20 // fallback height\n );\n\n const imgType = detectImageType(imageSource, imageResult.contentType);\n const imageRun = await createTypedImageRun({\n type: imgType,\n data: imageResult.buffer,\n transformation: {\n width: dimensions.width,\n height: dimensions.height,\n },\n });\n cellChildren = [imageRun];\n } catch (error) {\n // Fallback for missing images\n const imageSource = imageComp.props.svg?.trim()\n ? 'inline-svg'\n : imageComp.props.base64 || imageComp.props.path || 'unknown';\n cellChildren = [\n new TextRun({\n text: `[IMAGE: ${imageSource.substring(0, 50)}${imageSource.length > 50 ? '...' : ''}]`,\n font: mergedStyle.font,\n size: mergedStyle.size,\n color: '#999999',\n }),\n ];\n }\n } else {\n // Unsupported component type in table cell\n cellChildren = [\n new TextRun({\n text: `[Unsupported component type: ${cell.name}]`,\n font: mergedStyle.font,\n size: mergedStyle.size,\n color: '#999999',\n }),\n ];\n }\n } else {\n // Handle plain string\n cellChildren = revision\n ? createRevisionRuns(revision, mergedStyle)\n : rowMark\n ? createMarkedTextRuns(cell as string, rowMark, mergedStyle)\n : parseTextWithDecorators(cell as string, mergedStyle, {\n enableHyperlinks: true,\n });\n }\n\n // The comment lives on the cell, so it wraps whatever the cell rendered —\n // string, paragraph or image alike.\n return wrapInComment(cellChildren, comment);\n };\n\n // Create header row by iterating through columns\n // Calculate row height from any header cell that defines it\n const numColumns = columns.length;\n const headerHeight = columns.reduce<number | undefined>(\n (maxHeight, column, colIndex) => {\n const headerCell = column.header;\n const position = {\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === numColumns - 1,\n };\n const mergedDefaults = mergeHeaderCellDefaults(\n tableConfig.cellDefaults,\n tableConfig.headerCellDefaults,\n column.cellDefaults,\n headerCell,\n position,\n {\n borderColor: tableConfig.borderColor,\n borderSize: tableConfig.borderSize,\n }\n );\n if (mergedDefaults.height !== undefined) {\n return maxHeight !== undefined\n ? Math.max(maxHeight, mergedDefaults.height)\n : mergedDefaults.height;\n }\n return maxHeight;\n },\n undefined\n );\n\n const headerRow = new TableRow({\n // Headers repeat across page breaks unless explicitly disabled\n tableHeader: tableConfig.repeatHeaderOnPageBreak ?? true,\n height:\n headerHeight !== undefined\n ? { value: headerHeight * 20, rule: 'atLeast' as const }\n : undefined,\n children: await Promise.all(\n columns.map(async (column, colIndex) => {\n const headerCell = column.header;\n\n // Determine position for outer border application and hideBorders\n const position = {\n isFirstRow: true, // Header is always the first row\n isLastRow: numRows === 0, // Header is last row only if no data rows\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === numColumns - 1,\n };\n\n // Merge cell defaults with priority: header > columnCellDefaults > table outer border > headerCellDefaults > cellDefaults\n const mergedDefaults = mergeHeaderCellDefaults(\n tableConfig.cellDefaults,\n tableConfig.headerCellDefaults,\n column.cellDefaults,\n headerCell,\n position,\n {\n borderColor: tableConfig.borderColor,\n borderSize: tableConfig.borderSize,\n }\n );\n\n const cellChildren = await processCellContent(\n headerCell?.content,\n mergedDefaults,\n tableStyle.tableHeader,\n headerCell?.comment,\n headerCell?.revision\n );\n\n const horizontalAlignment = mergedDefaults.horizontalAlignment!;\n const verticalAlignment = getVerticalAlignment(\n mergedDefaults.verticalAlignment\n );\n\n return new TableCell({\n children: [\n new Paragraph({\n ...(tableConfig.keepInOnePage && { keepNext: true }),\n spacing: tableStyle.headerParagraph,\n alignment: getAlignment(horizontalAlignment),\n children: cellChildren,\n }),\n ],\n\n verticalAlign: verticalAlignment,\n ...(mergedDefaults.backgroundColor !== 'transparent' && {\n shading: {\n fill: mergedDefaults.backgroundColor,\n },\n }),\n margins: createMarginsFromPadding(mergedDefaults.padding),\n borders: {\n top: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'top') as number,\n getBorderValue(mergedDefaults.borderColor, 'top') as string,\n shouldHideBorder('top', position)\n ),\n bottom: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'bottom') as number,\n getBorderValue(mergedDefaults.borderColor, 'bottom') as string,\n shouldHideBorder('bottom', position)\n ),\n left: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'left') as number,\n getBorderValue(mergedDefaults.borderColor, 'left') as string,\n shouldHideBorder('left', position)\n ),\n right: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'right') as number,\n getBorderValue(mergedDefaults.borderColor, 'right') as string,\n shouldHideBorder('right', position)\n ),\n },\n });\n })\n ),\n });\n\n // Create data rows\n const dataRows = await Promise.all(\n Array.from({ length: numRows }, async (_, rowIndex) => {\n const isLastRow = rowIndex === numRows - 1;\n\n // Allocate every revision id for this row here, in the synchronous\n // prefix of the callback: `Array.from` invokes callbacks in order and\n // this runs before any await, so ids follow document order rather than\n // I/O completion. Each emitted w:ins/w:del gets its own id, as Word's\n // own output does.\n const rowProps = tableConfig.rows?.[rowIndex];\n const rowRevision = rowProps?.revision;\n const rowRevisionAttributes = rowRevision\n ? createRevisionMark(rowRevision)\n : undefined;\n\n /**\n * Each cell's closing paragraph mark carries the same change. Without it\n * an accepted deletion leaves an empty row behind, and an accepted\n * insertion leaves the row's paragraph marks untracked.\n */\n const paragraphMarks = rowRevision\n ? columns.map(() => ({ run: createRevisionMark(rowRevision) }))\n : undefined;\n\n // Calculate row height from any cell in this row that defines it\n const rowHeight = columns.reduce<number | undefined>(\n (maxHeight, column, colIndex) => {\n const cell = column.cells?.[rowIndex];\n if (cell) {\n const position = {\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === numColumns - 1,\n isLastRow,\n };\n const mergedDefaults = mergeCellDefaults(\n tableConfig.cellDefaults,\n column.cellDefaults,\n cell,\n position,\n {\n borderColor: tableConfig.borderColor,\n borderSize: tableConfig.borderSize,\n }\n );\n if (mergedDefaults.height !== undefined) {\n return maxHeight !== undefined\n ? Math.max(maxHeight, mergedDefaults.height)\n : mergedDefaults.height;\n }\n }\n return maxHeight;\n },\n undefined\n );\n\n return new TableRow({\n height:\n rowHeight !== undefined\n ? { value: rowHeight * 20, rule: 'atLeast' as const }\n : undefined,\n ...(rowProps?.cantSplit !== undefined && {\n cantSplit: rowProps.cantSplit,\n }),\n ...(rowProps?.tableHeader !== undefined && {\n tableHeader: rowProps.tableHeader,\n }),\n // w:trPr/w:ins | w:del — the row itself was inserted or deleted.\n ...rowRevisionAttributes,\n children: await Promise.all(\n columns.map(async (column, colIndex) => {\n const cell = column.cells?.[rowIndex];\n\n // Determine position for outer border application and hideBorders\n const position = {\n isFirstRow: false, // Data rows are never the first row (header is)\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === numColumns - 1,\n isLastRow,\n };\n\n if (!cell) {\n // Handle missing cell data - merge defaults properly\n const mergedDefaultsForMissing = mergeCellDefaults(\n tableConfig.cellDefaults,\n column.cellDefaults,\n undefined,\n position,\n {\n borderColor: tableConfig.borderColor,\n borderSize: tableConfig.borderSize,\n }\n );\n return new TableCell({\n children: [\n new Paragraph({\n ...((tableConfig.keepInOnePage && !isLastRow) ||\n (isLastRow && tableConfig.keepNext)\n ? { keepNext: true }\n : {}),\n spacing: tableStyle.cellParagraph,\n alignment: AlignmentType.LEFT,\n ...paragraphMarks?.[colIndex],\n children: [],\n }),\n ],\n borders: {\n top: createBorder(\n getBorderValue(\n mergedDefaultsForMissing.borderSize,\n 'top'\n ) as number,\n getBorderValue(\n mergedDefaultsForMissing.borderColor,\n 'top'\n ) as string,\n shouldHideBorder('top', position)\n ),\n bottom: createBorder(\n getBorderValue(\n mergedDefaultsForMissing.borderSize,\n 'bottom'\n ) as number,\n getBorderValue(\n mergedDefaultsForMissing.borderColor,\n 'bottom'\n ) as string,\n shouldHideBorder('bottom', position)\n ),\n left: createBorder(\n getBorderValue(\n mergedDefaultsForMissing.borderSize,\n 'left'\n ) as number,\n getBorderValue(\n mergedDefaultsForMissing.borderColor,\n 'left'\n ) as string,\n shouldHideBorder('left', position)\n ),\n right: createBorder(\n getBorderValue(\n mergedDefaultsForMissing.borderSize,\n 'right'\n ) as number,\n getBorderValue(\n mergedDefaultsForMissing.borderColor,\n 'right'\n ) as string,\n shouldHideBorder('right', position)\n ),\n },\n });\n }\n\n // Merge cell defaults with priority: cell > column > table outer border > table cellDefaults\n const mergedDefaults = mergeCellDefaults(\n tableConfig.cellDefaults,\n column.cellDefaults,\n cell,\n position,\n {\n borderColor: tableConfig.borderColor,\n borderSize: tableConfig.borderSize,\n }\n );\n\n const cellChildren = await processCellContent(\n cell.content,\n mergedDefaults,\n tableStyle.tableCell,\n cell.comment,\n cell.revision,\n rowRevision\n );\n\n const horizontalAlignment = mergedDefaults.horizontalAlignment!;\n const verticalAlignment = getVerticalAlignment(\n mergedDefaults.verticalAlignment\n );\n\n return new TableCell({\n children: [\n new Paragraph({\n ...((tableConfig.keepInOnePage && !isLastRow) ||\n (isLastRow && tableConfig.keepNext)\n ? { keepNext: true }\n : {}),\n spacing: tableStyle.cellParagraph,\n alignment: getAlignment(horizontalAlignment),\n ...paragraphMarks?.[colIndex],\n children: cellChildren,\n }),\n ],\n verticalAlign: verticalAlignment,\n ...(mergedDefaults.backgroundColor !== 'transparent' && {\n shading: {\n fill: mergedDefaults.backgroundColor,\n },\n }),\n margins: createMarginsFromPadding(mergedDefaults.padding),\n borders: {\n top: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'top') as number,\n getBorderValue(mergedDefaults.borderColor, 'top') as string,\n shouldHideBorder('top', position)\n ),\n bottom: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'bottom') as number,\n getBorderValue(\n mergedDefaults.borderColor,\n 'bottom'\n ) as string,\n shouldHideBorder('bottom', position)\n ),\n left: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'left') as number,\n getBorderValue(mergedDefaults.borderColor, 'left') as string,\n shouldHideBorder('left', position)\n ),\n right: createBorder(\n getBorderValue(mergedDefaults.borderSize, 'right') as number,\n getBorderValue(mergedDefaults.borderColor, 'right') as string,\n shouldHideBorder('right', position)\n ),\n },\n });\n })\n ),\n });\n })\n );\n\n // Calculate column widths - if any column has explicit width, use DXA for all\n const hasExplicitWidths = columns.some((col) => col.width !== undefined);\n\n let columnWidths: number[];\n let tableWidth: {\n size: number;\n type: (typeof WidthType)[keyof typeof WidthType];\n };\n\n if (hasExplicitWidths) {\n // Use explicit widths in DXA (twips) - convert from points\n const widthUtils = await import('../utils/widthUtils');\n const { getAvailableWidthTwips, relativeLengthToTwips } = widthUtils;\n\n // Get available table width in twips (page width minus margins)\n const availableTableWidth = getAvailableWidthTwips(theme, themeName);\n\n // Convert explicit column widths (points or percentage strings) to twips\n const columnsWithExplicitWidthTwips = columns.map((col) =>\n col.width !== undefined\n ? relativeLengthToTwips(col.width, availableTableWidth)\n : undefined\n );\n\n // Calculate total width used by columns with explicit widths\n const totalExplicitWidth = columnsWithExplicitWidthTwips.reduce(\n (sum: number, w) => sum + (w || 0),\n 0\n );\n\n if (totalExplicitWidth > availableTableWidth) {\n console.warn(\n `[json-to-office] Column widths total (${totalExplicitWidth} twips) exceeds available table width (${availableTableWidth} twips). Table may overflow.`\n );\n }\n\n // Count columns without explicit width\n const columnsWithoutWidth = columns.filter(\n (col) => col.width === undefined\n ).length;\n\n // Calculate remaining space and distribute among columns without explicit width\n const remainingWidth = Math.max(\n 0,\n availableTableWidth - totalExplicitWidth\n );\n const defaultColumnWidth =\n columnsWithoutWidth > 0\n ? remainingWidth / columnsWithoutWidth\n : pointsToTwips(72); // Fallback to 1 inch if all columns have explicit widths\n\n // Assign widths: use explicit width (in twips) or calculated default\n columnWidths = columnsWithExplicitWidthTwips.map(\n (w) => w || defaultColumnWidth\n );\n const totalWidth = columnWidths.reduce((sum, w) => sum + w, 0);\n tableWidth = { size: totalWidth, type: WidthType.DXA };\n } else {\n // Use percentage-based equal distribution\n const percentPerColumn = 100 / columns.length;\n columnWidths = columns.map(() => percentPerColumn);\n tableWidth = { size: tableConfig.width ?? 100, type: WidthType.PERCENTAGE };\n }\n\n return new Table({\n width: tableWidth,\n layout: TableLayoutType.FIXED,\n columnWidths: columnWidths,\n rows: [headerRow, ...dataRows],\n });\n}\n\n/**\n * Convert alignment string to docx AlignmentType\n */\nfunction getAlignment(\n alignment: string\n): (typeof AlignmentType)[keyof typeof AlignmentType] {\n switch (alignment) {\n case 'center':\n return AlignmentType.CENTER;\n case 'right':\n return AlignmentType.RIGHT;\n case 'justify':\n return AlignmentType.JUSTIFIED;\n default:\n return AlignmentType.LEFT;\n }\n}\n\n/**\n * Convert vertical alignment string to docx VerticalAlign\n */\nfunction getVerticalAlignment(\n alignment: string | undefined\n):\n | typeof VerticalAlign.TOP\n | typeof VerticalAlign.CENTER\n | typeof VerticalAlign.BOTTOM\n | undefined {\n if (!alignment) return undefined;\n\n switch (alignment) {\n case 'top':\n return VerticalAlign.TOP;\n case 'middle':\n return VerticalAlign.CENTER;\n case 'bottom':\n return VerticalAlign.BOTTOM;\n default:\n return undefined;\n }\n}\n\n/**\n * Create header element from content\n */\nexport function createHeaderElement(\n children: (Paragraph | Table)[],\n _options?: {\n position?: 'left' | 'center' | 'right';\n }\n): Header {\n return new Header({\n children: children,\n });\n}\n\n/**\n * Create footer element from content\n */\nexport function createFooterElement(\n children: (Paragraph | Table)[],\n _options?: {\n position?: 'left' | 'center' | 'right';\n }\n): Footer {\n return new Footer({\n children: children,\n });\n}\n\n/**\n * Create page number element\n */\nexport function createPageNumberElement(\n format?: string,\n alignment?: 'left' | 'center' | 'right'\n): Paragraph {\n const children: PlaceholderChild[] = [];\n\n if (format) {\n // Use placeholder processor to handle {PAGE} and other placeholders\n children.push(...processTextWithPlaceholders(format, {}));\n } else {\n // Default: just page number\n children.push(\n new TextRun({\n children: [PageNumber.CURRENT],\n })\n );\n }\n\n return new Paragraph({\n alignment: getAlignment(alignment || 'center'),\n children,\n });\n}\n\n/**\n * Create mixed content paragraph with text and image elements\n */\nexport async function createMixedContentParagraph(\n textContent: string,\n textOptions: {\n fontSize?: number;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n },\n imagePath?: string,\n imageOptions?: {\n width?: number;\n height?: number;\n },\n alignment?: 'left' | 'center' | 'right',\n theme?: import('../styles').ThemeConfig\n): Promise<Paragraph> {\n const children: (TextRun | ImageRun)[] = [];\n const normalizedTextContent = normalizeUnicodeText(textContent);\n\n // Add text content\n if (normalizedTextContent) {\n children.push(\n new TextRun({\n text: normalizedTextContent,\n font: theme ? getThemeFonts(theme).body.family : undefined,\n size: textOptions.fontSize ? textOptions.fontSize * 2 : 20, // Convert to half-points\n color:\n textOptions.color ||\n (theme ? getThemeColors(theme).textPrimary : undefined),\n bold: textOptions.bold || false,\n italics: textOptions.italic || false,\n })\n );\n }\n\n // Add image if provided\n if (imagePath) {\n try {\n const imageResult = await getImageBuffer(imagePath);\n\n // Calculate dimensions with aspect ratio preservation\n const dimensions = await calculateImageDimensions(\n imagePath,\n imageOptions?.width,\n imageOptions?.height,\n 60, // fallback width\n 20 // fallback height\n );\n\n const imgType = detectImageType(imagePath, imageResult.contentType);\n const imageRun = await createTypedImageRun({\n type: imgType,\n data: imageResult.buffer,\n transformation: { width: dimensions.width, height: dimensions.height },\n });\n\n // Add some spacing before the image\n children.push(new TextRun({ text: ' ' }));\n children.push(imageRun);\n } catch (error) {\n // Fallback for missing images\n children.push(\n new TextRun({\n text: ` [IMAGE: ${imagePath}]`,\n font: theme ? getThemeFonts(theme).body.family : undefined,\n size: (textOptions.fontSize || 10) * 2,\n color: theme ? getThemeColors(theme).secondary : undefined,\n bold: true,\n })\n );\n }\n }\n\n return new Paragraph({\n alignment: getAlignment(alignment || 'left'),\n children,\n });\n}\n\n/**\n * Create a table specifically for headers/footers with custom styling\n */\n\nexport async function createHeaderFooterTable(\n rows: (string | ComponentDefinition)[][],\n options: {\n cellAlignments?: ('left' | 'center' | 'right')[];\n fontSize?: number;\n bold?: boolean;\n color?: string;\n noBorders?: boolean;\n cellStyling?: {\n [rowIndex: number]: {\n [cellIndex: number]: {\n bold?: boolean;\n color?: string;\n fontSize?: number;\n };\n };\n };\n theme?: ThemeConfig;\n themeName?: string;\n } = {}\n): Promise<Table> {\n const {\n cellAlignments = ['left', 'right'],\n fontSize = 10,\n bold = false,\n color = '#000000',\n noBorders = true,\n cellStyling = {},\n theme,\n } = options;\n\n // Use theme's normal style for header/footer text since header/footer styles are removed\n const normalStyle = theme?.styles?.normal;\n\n const defaultFont = theme\n ? resolveFontFamily(theme, normalStyle?.font)\n : 'Arial';\n const defaultSize = normalStyle?.size || fontSize;\n const defaultColor =\n normalStyle?.color && theme\n ? resolveColor(normalStyle.color, theme)\n : color;\n\n const tableRows = await Promise.all(\n rows.map(\n async (row, rowIndex) =>\n new TableRow({\n children: await Promise.all(\n row.map(async (cell, cellIndex) => {\n const alignment = cellAlignments[cellIndex] || 'left';\n const cellStyle = cellStyling[rowIndex]?.[cellIndex] || {};\n\n let paragraphChildren: (PlaceholderChild | ImageRun)[] = [];\n\n // Handle ComponentDefinition first\n if (\n typeof cell === 'object' &&\n 'name' in cell &&\n 'props' in cell\n ) {\n // This is a ComponentDefinition\n if (isParagraphComponent(cell)) {\n const textComp = cell as ParagraphComponentDefinition;\n // Use parseTextWithDecorators to support rich text formatting\n const textStyle = {\n font:\n textComp.props.font?.family || (defaultFont as string),\n size:\n ((textComp.props.font?.size || defaultSize) as number) *\n 2, // Convert to half-points\n bold: textComp.props.font?.bold ?? false,\n color:\n (textComp.props.font?.color && theme\n ? resolveColor(textComp.props.font.color, theme)\n : undefined) || defaultColor,\n } as const;\n paragraphChildren = parseTextWithDecorators(\n textComp.props.text,\n textStyle,\n { enableHyperlinks: true }\n );\n } else if (isImageComponent(cell)) {\n const imageComp = cell as ImageComponentDefinition;\n try {\n // Get image source (svg, base64, or path)\n const imageSource = resolveImageSource(imageComp.props);\n if (!imageSource) {\n throw new Error(\n 'Image component requires one of \"path\", \"base64\", or \"svg\" property'\n );\n }\n\n // Read from local file, URL, or base64\n const imageResult = await getImageBuffer(imageSource);\n\n // Parse width value if it's a string percentage (like \"90%\")\n const parsedWidth =\n typeof imageComp.props.width === 'string'\n ? parseWidthValue(imageComp.props.width, 300) // Use a reasonable default for table context\n : imageComp.props.width;\n\n // Parse height value if it's a string percentage (like \"90%\")\n const parsedHeight =\n typeof imageComp.props.height === 'string'\n ? parseWidthValue(imageComp.props.height, 200) // Use a reasonable default for table context\n : imageComp.props.height;\n\n // Calculate dimensions with aspect ratio preservation\n const dimensions = await calculateImageDimensions(\n imageSource,\n parsedWidth,\n parsedHeight,\n 60, // fallback width\n 20 // fallback height\n );\n\n const imgType = detectImageType(\n imageSource,\n imageResult.contentType\n );\n const imageRun = await createTypedImageRun({\n type: imgType,\n data: imageResult.buffer,\n transformation: {\n width: dimensions.width,\n height: dimensions.height,\n },\n });\n paragraphChildren = [imageRun];\n } catch (error) {\n // Fallback for missing images\n const imageSource = imageComp.props.svg?.trim()\n ? 'inline-svg'\n : imageComp.props.base64 ||\n imageComp.props.path ||\n 'unknown';\n paragraphChildren = [\n new TextRun({\n text: `[IMAGE: ${imageSource.substring(0, 50)}${imageSource.length > 50 ? '...' : ''}]`,\n size: fontSize * 2,\n bold: true,\n color: '#999999',\n }),\n ];\n }\n } else {\n // Unsupported component type in table cell\n paragraphChildren = [\n new TextRun({\n text: `[Unsupported component type: ${cell.name}]`,\n size: fontSize * 2,\n color: '#999999',\n }),\n ];\n }\n } else if (typeof cell === 'string') {\n // Handle plain string text (including placeholders)\n const textStyle = {\n font: defaultFont,\n size: (cellStyle.fontSize || defaultSize) * 2,\n bold: cellStyle.bold !== undefined ? cellStyle.bold : bold,\n color: cellStyle.color || defaultColor,\n };\n\n // Use parseTextWithDecorators which now handles both decorators and placeholders\n paragraphChildren = parseTextWithDecorators(cell, textStyle, {\n enableHyperlinks: true,\n });\n }\n\n return new TableCell({\n children: [\n new Paragraph({\n alignment: getAlignment(alignment),\n children: paragraphChildren,\n }),\n ],\n margins: {\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n },\n borders: noBorders\n ? {\n top: { style: BorderStyle.NONE, size: 0 },\n bottom: { style: BorderStyle.NONE, size: 0 },\n left: { style: BorderStyle.NONE, size: 0 },\n right: { style: BorderStyle.NONE, size: 0 },\n }\n : undefined,\n });\n })\n ),\n })\n )\n );\n\n return new Table({\n width: { size: 100, type: WidthType.PERCENTAGE },\n layout: TableLayoutType.FIXED, // Lock column widths to prevent horizontal resizing\n rows: tableRows,\n borders: noBorders\n ? {\n top: { style: BorderStyle.NONE, size: 0 },\n bottom: { style: BorderStyle.NONE, size: 0 },\n left: { style: BorderStyle.NONE, size: 0 },\n right: { style: BorderStyle.NONE, size: 0 },\n insideHorizontal: { style: BorderStyle.NONE, size: 0 },\n insideVertical: { style: BorderStyle.NONE, size: 0 },\n }\n : undefined,\n });\n}\n","/**\n * Bookmark Registry\n * Utilities for managing document bookmarks for internal hyperlinks\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { BookmarkStart, BookmarkEnd } from 'docx';\nimport type { ParagraphChild } from 'docx';\n\nexport interface BookmarkInfo {\n id: string;\n title: string;\n type: string; // e.g., 'heading', 'paragraph', 'table', etc.\n}\n\ninterface BookmarkState {\n bookmarks: Map<string, BookmarkInfo>;\n /** Next `w:bookmarkStart/@w:id` for a content bookmark. */\n nextLinkId: number;\n}\n\n/**\n * Content bookmarks number from here up.\n *\n * `w:id` pairs a `bookmarkStart` with its `bookmarkEnd`, so it has to be unique\n * across the whole document — including against the section bookmarks, which\n * allocate from their own two ranges in `sectionBookmarks.ts` (layout ordinals\n * from 1, nested sections from 1_000_000). This is the third disjoint range.\n */\nconst CONTENT_LINK_ID_BASE = 2_000_000;\n\nfunction createState(): BookmarkState {\n return { bookmarks: new Map(), nextLinkId: CONTENT_LINK_ID_BASE + 1 };\n}\n\n/**\n * Slug a piece of text into a bookmark id candidate.\n *\n * Pure half of `generateId`: the document-outline pre-pass has to predict the\n * ids render will produce before any registry state exists, so the algorithm\n * cannot live inside the registry.\n */\nexport function slugifyBookmarkText(text: string): string {\n return text\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n .substring(0, 40); // Limit length\n}\n\n/**\n * Disambiguate a slug against ids already taken, appending `-1`, `-2`, … .\n * Gives up after 100 attempts and returns the colliding id, exactly as\n * `generateId` always has.\n */\nexport function dedupeBookmarkId(\n base: string,\n taken: (id: string) => boolean\n): string {\n let id = base;\n let attempt = 0;\n while (taken(id) && attempt < 100) {\n id = `${base}-${++attempt}`;\n }\n return id;\n}\n\n/**\n * Registry for managing document bookmarks\n * Used to track bookmark IDs and validate internal hyperlink targets\n */\nexport class BookmarkRegistry {\n private readonly fallback: BookmarkState = createState();\n private readonly scopes = new AsyncLocalStorage<BookmarkState>();\n\n private get state(): BookmarkState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run(createState(), callback);\n }\n\n /**\n * Register a bookmark\n */\n register(id: string, title: string, type: string): void {\n if (this.state.bookmarks.has(id)) {\n console.warn(\n `Duplicate bookmark ID: ${id}. Using the latest registration.`\n );\n }\n this.state.bookmarks.set(id, { id, title, type });\n }\n\n /**\n * A `w:id` no other bookmark in this document will use.\n *\n * docx's own `Bookmark` cannot supply one: its constructor builds a fresh\n * id generator per instance (`bookmarkUniqueNumericIdGen()`), so every\n * bookmark it emits carries `w:id=\"1\"`. Reported upstream as dolanmiu/docx\n * #3478, still unreleased as of 9.7.1. Duplicated ids leave the start/end\n * pairing ambiguous, which is why a `REF` field could not read a target's\n * text even though navigating to it by name worked.\n */\n allocateLinkId(): number {\n return this.state.nextLinkId++;\n }\n\n /**\n * Generate a unique bookmark ID from text\n * Converts text to a URL-friendly format\n */\n generateId(text: string, _type: string = 'bookmark'): string {\n return dedupeBookmarkId(slugifyBookmarkText(text), (id) =>\n this.state.bookmarks.has(id)\n );\n }\n\n /**\n * Check if a bookmark exists\n */\n exists(id: string): boolean {\n return this.state.bookmarks.has(id);\n }\n\n /**\n * Get bookmark info by ID\n */\n get(id: string): BookmarkInfo | undefined {\n return this.state.bookmarks.get(id);\n }\n\n /**\n * Get all registered bookmarks\n */\n getAll(): BookmarkInfo[] {\n return Array.from(this.state.bookmarks.values());\n }\n\n /**\n * Clear all bookmarks\n */\n clear(): void {\n this.state.bookmarks.clear();\n }\n\n /**\n * Validate that all internal hyperlink references exist\n * Returns array of missing bookmark IDs\n */\n validateReferences(referencedIds: string[]): string[] {\n const missing: string[] = [];\n for (const id of referencedIds) {\n if (!this.exists(id)) {\n missing.push(id);\n }\n }\n return missing;\n }\n}\n\n// Global registry instance\nexport const globalBookmarkRegistry = new BookmarkRegistry();\n\n/**\n * A bookmark around `children`, as the three elements OOXML actually wants:\n * `w:bookmarkStart`, the content, `w:bookmarkEnd`.\n *\n * Replaces docx's `Bookmark`, which pairs every start/end with `w:id=\"1\"`\n * (see `allocateLinkId`). Spread the result into a paragraph's children.\n */\nexport function createBookmarkedContent(\n name: string,\n children: readonly ParagraphChild[]\n): ParagraphChild[] {\n const linkId = globalBookmarkRegistry.allocateLinkId();\n return [\n new BookmarkStart(name, linkId),\n ...children,\n new BookmarkEnd(linkId),\n ];\n}\n","/**\n * Comment anchors — the `word/document.xml` half of a review comment.\n *\n * Word expects, in this order inside the commented paragraph(s):\n *\n * <w:commentRangeStart w:id=\"N\"/> …runs… <w:commentRangeEnd w:id=\"N\"/>\n * <w:r><w:commentReference w:id=\"N\"/></w:r>\n *\n * The range may span several paragraphs, in which case the start sits in the\n * first and the end plus reference in the last — which is how a list-level\n * comment is anchored.\n */\n\nimport {\n CommentRangeEnd,\n CommentRangeStart,\n CommentReference,\n TextRun,\n} from 'docx';\nimport type { ParagraphChild } from 'docx';\nimport type { Comment } from '@json-to-office/shared-docx';\nimport { globalCommentRegistry } from './commentRegistry';\n\nexport interface CommentAnchor {\n /** Every comment in the thread: the root first, then its replies. */\n ids: number[];\n /** Range-start elements to place before the commented content. */\n start: ParagraphChild[];\n}\n\n/**\n * Register `comment` (and its replies) and return the opening anchors, or\n * undefined when there is no comment. Callers must pair this with\n * `closeCommentRange`.\n *\n * A thread anchors every one of its comments over the same range, which is how\n * Word writes threads and how it groups them in the review pane.\n */\nexport function openCommentRange(\n comment: Comment | undefined\n): CommentAnchor | undefined {\n if (!comment) return undefined;\n const ids = globalCommentRegistry.register(comment);\n return { ids, start: ids.map((id) => new CommentRangeStart(id)) };\n}\n\n/**\n * The closing anchors: each range end followed by its reference run.\n *\n * `w:commentReference` is run-inner content, so it has to sit inside a `w:r`.\n * docx's `CommentReference` is the bare element; emitted as a direct child of\n * `w:p` it is schema-invalid and readers drop the comment silently (verified in\n * LibreOffice, which showed zero annotations before this wrapping).\n */\nexport function closeCommentRange(ids: readonly number[]): ParagraphChild[] {\n return ids.flatMap((id) => [\n new CommentRangeEnd(id),\n new TextRun({ children: [new CommentReference(id)] }),\n ]);\n}\n","/**\n * Comment (review annotation) registry.\n *\n * Word comment ids live in their own OOXML namespace, separate from the\n * `w:ins` / `w:del` ids in `revisionUtils.ts`, so they get their own counter —\n * but the same async-local scoping, and the registry must be entered from the\n * same `runScoped` nest, or two concurrent generations interleave counters and\n * a comment anchor points at another document's body.\n *\n * The registry holds both halves of a comment: the id used by the anchor in\n * `word/document.xml`, and the body that `renderDocument` hands to docx for\n * `word/comments.xml`.\n */\n\nimport { Paragraph, TextRun } from 'docx';\nimport type { ICommentOptions } from 'docx';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport type { Comment, CommentReply } from '@json-to-office/shared-docx';\nimport { normalizeUnicodeText } from './unicode';\n\nexport const DEFAULT_COMMENT_AUTHOR = 'json-to-office';\n// Deterministic fallback so identical inputs produce byte-identical XML\nexport const DEFAULT_COMMENT_DATE = '1970-01-01T00:00:00Z';\n\ninterface CommentState {\n counter: number;\n comments: ICommentOptions[];\n /** Whether anything in this render asked for a resolved state. */\n hasResolved: boolean;\n}\n\nfunction createState(): CommentState {\n return { counter: 0, comments: [], hasResolved: false };\n}\n\n/**\n * Initials shown on the comment bubble. Word derives them from the author when\n * the file omits them; we do it up front so the value is stable across viewers.\n */\nfunction deriveInitials(author: string): string {\n const initials = author\n .split(/[\\s._-]+/)\n .filter(Boolean)\n .map((word) => word[0])\n .join('')\n .toUpperCase()\n .slice(0, 3);\n return initials || author.slice(0, 2).toUpperCase();\n}\n\n/** Comment body paragraphs — one per line, so authors can write short lists. */\nfunction bodyParagraphs(text: string): Paragraph[] {\n return normalizeUnicodeText(text)\n .split('\\n')\n .map((line) => new Paragraph({ children: [new TextRun({ text: line })] }));\n}\n\nclass CommentRegistry {\n private fallback: CommentState = createState();\n private readonly scopes = new AsyncLocalStorage<CommentState>();\n\n private get state(): CommentState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run(createState(), callback);\n }\n\n /**\n * Register a comment thread and return every id its anchors must carry — the\n * root first, then each reply in order. Word anchors every comment in a\n * thread over the same range, so all of them need a range and a reference.\n *\n * Ids are unique and monotonic within a render. `parentId` is derived here\n * rather than authored; docx turns it into the `w15:paraIdParent` links in\n * `word/commentsExtended.xml`.\n */\n register(comment: Comment): number[] {\n const state = this.state;\n const resolved = comment.resolved;\n const rootId = ++state.counter;\n\n state.comments.push({\n ...this.toOptions(comment, rootId),\n ...(resolved !== undefined && { resolved }),\n });\n\n const ids = [rootId];\n for (const reply of comment.replies ?? []) {\n const replyId = ++state.counter;\n state.comments.push({\n ...this.toOptions(reply, replyId),\n parentId: rootId,\n // Word resolves a thread as a whole, so the flag rides every member.\n ...(resolved !== undefined && { resolved }),\n });\n ids.push(replyId);\n }\n\n if (resolved !== undefined) state.hasResolved = true;\n return ids;\n }\n\n private toOptions(\n comment: Comment | CommentReply,\n id: number\n ): ICommentOptions {\n const author = comment.author || DEFAULT_COMMENT_AUTHOR;\n return {\n id,\n author,\n initials: comment.initials || deriveInitials(author),\n date: new Date(comment.date || DEFAULT_COMMENT_DATE),\n children: bodyParagraphs(comment.text),\n };\n }\n\n /**\n * Every comment registered in this scope, in id order.\n *\n * docx writes `word/commentsExtended.xml` — and therefore any `w15:done` —\n * only when at least one comment in the document carries a `parentId`. A\n * document whose only resolved comment has no replies would silently lose\n * that state, so say so rather than dropping it quietly.\n */\n getAll(): ICommentOptions[] {\n const state = this.state;\n if (\n state.hasResolved &&\n !state.comments.some((comment) => comment.parentId !== undefined)\n ) {\n console.warn(\n 'A comment sets `resolved` but the document has no replies. Word stores ' +\n 'the resolved flag in commentsExtended.xml, which is written only for ' +\n 'threaded comments, so the flag will not survive.'\n );\n }\n return [...state.comments];\n }\n\n /** Test-only: reset the current scope's counter and bodies. */\n clear(): void {\n const state = this.scopes.getStore();\n if (state) {\n state.counter = 0;\n state.comments.length = 0;\n state.hasResolved = false;\n } else {\n this.fallback = createState();\n }\n }\n}\n\nexport const globalCommentRegistry = new CommentRegistry();\n","/**\n * Note registry — footnote and endnote bodies collected while rendering their\n * markers.\n *\n * A note has two halves in the package: a reference run in\n * `word/document.xml` and a body in `word/footnotes.xml` or\n * `word/endnotes.xml`, joined by a numeric id that is document-scoped.\n * Async-local state gives each render its own counters, so concurrent\n * generations cannot interleave ids and point a reference at another\n * document's body.\n *\n * Footnotes and endnotes are separate id spaces — they are separate parts —\n * so each gets its own counter. Both start at 1: docx writes the reserved\n * separator (-1) and continuationSeparator (0) notes itself.\n */\n\nimport { Paragraph, TextRun } from 'docx';\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { normalizeUnicodeText } from './unicode';\n\n/** docx's shape for the `footnotes` / `endnotes` document options. */\nexport type NoteBodies = Record<string, { children: Paragraph[] }>;\n\ninterface NoteState {\n footnoteCounter: number;\n endnoteCounter: number;\n footnotes: NoteBodies;\n endnotes: NoteBodies;\n}\n\nfunction createState(): NoteState {\n return {\n footnoteCounter: 0,\n endnoteCounter: 0,\n footnotes: {},\n endnotes: {},\n };\n}\n\n/** Note bodies are paragraphs — one per line, so authors can write short lists. */\nfunction bodyParagraphs(text: string, style: string): Paragraph[] {\n return normalizeUnicodeText(text)\n .split('\\n')\n .map(\n (line) =>\n new Paragraph({\n style,\n children: [new TextRun({ text: line })],\n })\n );\n}\n\nclass NoteRegistry {\n private fallback: NoteState = createState();\n private readonly scopes = new AsyncLocalStorage<NoteState>();\n\n private get state(): NoteState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run(createState(), callback);\n }\n\n /**\n * Register a footnote body and return the id its reference must use. Ids are\n * unique and monotonic within a render.\n */\n registerFootnote(text: string): number {\n const state = this.state;\n const id = ++state.footnoteCounter;\n state.footnotes[String(id)] = {\n children: bodyParagraphs(text, 'FootnoteText'),\n };\n return id;\n }\n\n /** Register an endnote body and return the id its reference must use. */\n registerEndnote(text: string): number {\n const state = this.state;\n const id = ++state.endnoteCounter;\n state.endnotes[String(id)] = {\n children: bodyParagraphs(text, 'EndnoteText'),\n };\n return id;\n }\n\n /** Every footnote registered in this scope, keyed by id. */\n getFootnotes(): NoteBodies {\n return { ...this.state.footnotes };\n }\n\n /** Every endnote registered in this scope, keyed by id. */\n getEndnotes(): NoteBodies {\n return { ...this.state.endnotes };\n }\n\n /** Test-only: reset the current scope's counters and bodies. */\n clear(): void {\n const state = this.scopes.getStore();\n if (state) {\n state.footnoteCounter = 0;\n state.endnoteCounter = 0;\n for (const key of Object.keys(state.footnotes)) {\n delete state.footnotes[key];\n }\n for (const key of Object.keys(state.endnotes)) {\n delete state.endnotes[key];\n }\n } else {\n this.fallback = createState();\n }\n }\n}\n\nexport const globalNoteRegistry = new NoteRegistry();\n","/**\n * Bind a paragraph's declared note bodies to the `[^id]` markers in its text.\n *\n * Footnotes and endnotes share the marker syntax and differ only in where Word\n * puts the body, so one resolver serves both: an id is looked up in\n * `footnotes` first, then `endnotes`.\n *\n * Registration is lazy — a body reaches its part only when a marker actually\n * resolves to it — and memoized, so repeating `[^id]` points both references at\n * the same note rather than duplicating the body.\n */\n\nimport type { Note } from '@json-to-office/shared-docx';\nimport { globalNoteRegistry } from './noteRegistry';\n\nexport interface NoteResolver {\n /** Called by the text parser for each `[^id]` marker it finds. */\n resolve: (id: string) => { id: number; endnote: boolean } | undefined;\n /**\n * Report declared bodies that never made it into the document. Call once the\n * paragraph's text has been fully parsed.\n */\n reportUnemitted: (text: string) => void;\n}\n\ninterface DeclaredNote {\n text: string;\n endnote: boolean;\n}\n\nfunction collectDeclared(\n footnotes: readonly Note[] | undefined,\n endnotes: readonly Note[] | undefined\n): Map<string, DeclaredNote> {\n const declared = new Map<string, DeclaredNote>();\n\n /**\n * First declaration wins, in both directions: within one array and across\n * the two. `[^id]` can only mean one note, and letting the last entry win\n * would make the outcome depend on authoring order while silently discarding\n * a body.\n */\n const declare = (note: Note, endnote: boolean) => {\n const existing = declared.get(note.id);\n if (existing) {\n console.warn(\n existing.endnote === endnote\n ? `Note id \"${note.id}\" is declared twice in the same ` +\n `${endnote ? 'endnotes' : 'footnotes'} array. Using the first ` +\n 'declaration and ignoring the rest.'\n : `Note id \"${note.id}\" is declared as both a footnote and an ` +\n 'endnote in the same paragraph. Using the footnote and ignoring ' +\n 'the endnote.'\n );\n return;\n }\n declared.set(note.id, { text: note.text, endnote });\n };\n\n for (const note of footnotes ?? []) declare(note, false);\n for (const note of endnotes ?? []) declare(note, true);\n return declared;\n}\n\n/**\n * Build the resolver `parseTextWithDecorators` consults for each marker, or\n * undefined when the paragraph declares no notes (which leaves `[^…]` as\n * ordinary text).\n */\nexport function createNoteResolver(\n footnotes: readonly Note[] | undefined,\n endnotes: readonly Note[] | undefined\n): NoteResolver | undefined {\n const declared = collectDeclared(footnotes, endnotes);\n if (declared.size === 0) return undefined;\n\n const registered = new Map<string, { id: number; endnote: boolean }>();\n\n return {\n resolve(id: string) {\n const existing = registered.get(id);\n if (existing !== undefined) return existing;\n\n const note = declared.get(id);\n if (note === undefined) {\n // The paragraph declares notes, so `[^id]` was meant as a marker.\n // Leave it literal rather than dropping text, but say so.\n console.warn(\n `Note marker \"[^${id}]\" has no matching entry in this paragraph's ` +\n `footnotes or endnotes (declared: ${[...declared.keys()].join(', ')}). ` +\n 'Rendering the marker as literal text.'\n );\n return undefined;\n }\n\n const resolved = {\n id: note.endnote\n ? globalNoteRegistry.registerEndnote(note.text)\n : globalNoteRegistry.registerFootnote(note.text),\n endnote: note.endnote,\n };\n registered.set(id, resolved);\n return resolved;\n },\n\n reportUnemitted(text: string) {\n for (const [id, note] of declared) {\n if (registered.has(id)) continue;\n const kind = note.endnote ? 'Endnote' : 'Footnote';\n console.warn(\n text.includes(`[^${id}]`)\n ? `${kind} \"${id}\" is declared and its marker appears in the text, ` +\n 'but the marker was not resolved — markers are not recognised ' +\n 'in text that also contains {PLACEHOLDER} substitutions. ' +\n 'The note will not appear in the document.'\n : `${kind} \"${id}\" is declared but never referenced as [^${id}] ` +\n 'in this paragraph. It will not appear in the document.'\n );\n }\n },\n };\n}\n","/**\n * Numbering Configuration Utilities\n * Utilities for creating and managing docx numbering configurations\n */\n\nimport {\n AlignmentType,\n convertInchesToTwip,\n LevelFormat,\n LevelSuffix,\n} from 'docx';\nimport type { ILevelsOptions, IRunStylePropertiesOptions } from 'docx';\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n// Type mapping from schema strings to docx LevelFormat values\nconst LEVEL_FORMAT_MAP: Record<\n string,\n (typeof LevelFormat)[keyof typeof LevelFormat]\n> = {\n decimal: LevelFormat.DECIMAL,\n upperRoman: LevelFormat.UPPER_ROMAN,\n lowerRoman: LevelFormat.LOWER_ROMAN,\n upperLetter: LevelFormat.UPPER_LETTER,\n lowerLetter: LevelFormat.LOWER_LETTER,\n bullet: LevelFormat.BULLET,\n ordinal: LevelFormat.ORDINAL,\n cardinalText: LevelFormat.CARDINAL_TEXT,\n ordinalText: LevelFormat.ORDINAL_TEXT,\n hex: LevelFormat.HEX,\n chicago: LevelFormat.CHICAGO,\n ideographDigital: LevelFormat.IDEOGRAPH__DIGITAL,\n japaneseCounting: LevelFormat.JAPANESE_COUNTING,\n aiueo: LevelFormat.AIUEO,\n iroha: LevelFormat.IROHA,\n decimalFullWidth: LevelFormat.DECIMAL_FULL_WIDTH,\n decimalHalfWidth: LevelFormat.DECIMAL_HALF_WIDTH,\n japaneseLegal: LevelFormat.JAPANESE_LEGAL,\n japaneseDigitalTenThousand: LevelFormat.JAPANESE_DIGITAL_TEN_THOUSAND,\n decimalEnclosedCircle: LevelFormat.DECIMAL_ENCLOSED_CIRCLE,\n decimalFullWidth2: LevelFormat.DECIMAL_FULL_WIDTH2,\n aiueoFullWidth: LevelFormat.AIUEO_FULL_WIDTH,\n irohaFullWidth: LevelFormat.IROHA_FULL_WIDTH,\n decimalZero: LevelFormat.DECIMAL_ZERO,\n ganada: LevelFormat.GANADA,\n chosung: LevelFormat.CHOSUNG,\n decimalEnclosedFullstop: LevelFormat.DECIMAL_ENCLOSED_FULLSTOP,\n decimalEnclosedParen: LevelFormat.DECIMAL_ENCLOSED_PARENTHESES,\n decimalEnclosedCircleChinese: LevelFormat.DECIMAL_ENCLOSED_CIRCLE_CHINESE,\n ideographEnclosedCircle: LevelFormat.IDEOGRAPH_ENCLOSED_CIRCLE,\n ideographTraditional: LevelFormat.IDEOGRAPH_TRADITIONAL,\n ideographZodiac: LevelFormat.IDEOGRAPH_ZODIAC,\n ideographZodiacTraditional: LevelFormat.IDEOGRAPH_ZODIAC_TRADITIONAL,\n taiwaneseCounting: LevelFormat.TAIWANESE_COUNTING,\n ideographLegalTraditional: LevelFormat.IDEOGRAPH_LEGAL_TRADITIONAL,\n taiwaneseCountingThousand: LevelFormat.TAIWANESE_COUNTING_THOUSAND,\n taiwaneseDigital: LevelFormat.TAIWANESE_DIGITAL,\n chineseCounting: LevelFormat.CHINESE_COUNTING,\n chineseLegalSimplified: LevelFormat.CHINESE_LEGAL_SIMPLIFIED,\n chineseCountingThousand: LevelFormat.CHINESE_COUNTING_THOUSAND,\n koreanDigital: LevelFormat.KOREAN_DIGITAL,\n koreanCounting: LevelFormat.KOREAN_COUNTING,\n koreanLegal: LevelFormat.KOREAN_LEGAL,\n koreanDigital2: LevelFormat.KOREAN_DIGITAL2,\n vietnameseCounting: LevelFormat.VIETNAMESE_COUNTING,\n russianLower: LevelFormat.RUSSIAN_LOWER,\n russianUpper: LevelFormat.RUSSIAN_UPPER,\n none: LevelFormat.NONE,\n numberInDash: LevelFormat.NUMBER_IN_DASH,\n hebrew1: LevelFormat.HEBREW1,\n hebrew2: LevelFormat.HEBREW2,\n arabicAlpha: LevelFormat.ARABIC_ALPHA,\n arabicAbjad: LevelFormat.ARABIC_ABJAD,\n hindiVowels: LevelFormat.HINDI_VOWELS,\n hindiConsonants: LevelFormat.HINDI_CONSONANTS,\n hindiNumbers: LevelFormat.HINDI_NUMBERS,\n hindiCounting: LevelFormat.HINDI_COUNTING,\n thaiLetters: LevelFormat.THAI_LETTERS,\n thaiNumbers: LevelFormat.THAI_NUMBERS,\n thaiCounting: LevelFormat.THAI_COUNTING,\n};\n\nconst ALIGNMENT_MAP: Record<\n string,\n (typeof AlignmentType)[keyof typeof AlignmentType]\n> = {\n start: AlignmentType.START,\n end: AlignmentType.END,\n left: AlignmentType.LEFT,\n right: AlignmentType.RIGHT,\n center: AlignmentType.CENTER,\n};\n\n/**\n * Styling for the marker glyph itself (`w:lvl/w:rPr`), independent of the list\n * text. `color` must already be resolved to a 6-char hex without '#'.\n */\nexport interface ListMarkerFontConfig {\n family?: string;\n /** Points. */\n size?: number;\n /** Resolved hex, no leading '#'. */\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n}\n\nexport interface ListLevelConfig {\n level: number;\n format?: string;\n text?: string;\n alignment?: string;\n indent?: {\n left?: number;\n hanging?: number;\n };\n start?: number;\n font?: ListMarkerFontConfig;\n}\n\nexport interface NumberingConfig {\n reference: string;\n levels: ListLevelConfig[];\n}\n\ntype RegisteredNumberingConfig = {\n levels: ILevelsOptions[];\n reference: string;\n};\n\ninterface NumberingState {\n configs: Map<string, RegisteredNumberingConfig>;\n counter: number;\n}\n\n/**\n * Convert schema format string to docx LevelFormat\n */\nfunction getLevelFormat(\n format?: string\n): (typeof LevelFormat)[keyof typeof LevelFormat] {\n if (!format) return LevelFormat.BULLET;\n return LEVEL_FORMAT_MAP[format] || LevelFormat.BULLET;\n}\n\n/**\n * Convert schema alignment string to docx AlignmentType\n */\nfunction getAlignment(\n alignment?: string\n): (typeof AlignmentType)[keyof typeof AlignmentType] {\n if (!alignment) return AlignmentType.LEFT;\n return ALIGNMENT_MAP[alignment] || AlignmentType.LEFT;\n}\n\n/**\n * Create a default level configuration for a given level number\n */\nfunction createDefaultLevel(\n level: number,\n format: (typeof LevelFormat)[keyof typeof LevelFormat] = LevelFormat.BULLET,\n text?: string\n): ILevelsOptions {\n const baseIndent = 0.5 * (level + 1); // Increase indent for each level\n const hangingIndent = 0.25;\n\n return {\n level,\n format,\n text: text || (format === LevelFormat.BULLET ? '•' : '%1.'),\n alignment: AlignmentType.LEFT,\n style: {\n paragraph: {\n indent: {\n left: convertInchesToTwip(baseIndent),\n hanging: convertInchesToTwip(hangingIndent),\n },\n },\n },\n };\n}\n\n/**\n * Map a marker font onto docx's level run properties. Returns undefined when\n * nothing was requested, so the emitted level keeps its previous shape.\n */\nfunction createMarkerRunStyle(\n font: ListMarkerFontConfig | undefined\n): IRunStylePropertiesOptions | undefined {\n if (!font) return undefined;\n\n const run: IRunStylePropertiesOptions = {\n ...(font.family && { font: font.family }),\n // docx run sizes are half-points.\n ...(font.size !== undefined && { size: font.size * 2 }),\n ...(font.color && { color: font.color }),\n ...(font.bold !== undefined && { bold: font.bold }),\n ...(font.italic !== undefined && { italics: font.italic }),\n ...(font.underline !== undefined && {\n underline: font.underline ? { type: 'single' as const } : undefined,\n }),\n };\n\n return Object.keys(run).length > 0 ? run : undefined;\n}\n\n/**\n * Create numbering configuration from list config\n * Returns a single config item that can be added to INumberingOptions.config array\n */\nexport function createNumberingConfig(config: NumberingConfig): {\n levels: ILevelsOptions[];\n reference: string;\n} {\n const levels: ILevelsOptions[] = [];\n\n // Process each level\n for (const levelConfig of config.levels) {\n const format = getLevelFormat(levelConfig.format);\n const alignment = getAlignment(levelConfig.alignment);\n const text =\n levelConfig.text ||\n (format === LevelFormat.BULLET ? '•' : `%${levelConfig.level + 1}.`);\n\n // Calculate indentation\n const baseIndent =\n levelConfig.indent?.left !== undefined\n ? levelConfig.indent.left / 72 // Convert points to inches\n : 0.5 * (levelConfig.level + 1);\n\n const hangingIndent =\n levelConfig.indent?.hanging !== undefined\n ? levelConfig.indent.hanging / 72 // Convert points to inches\n : 0.25;\n\n const markerRun = createMarkerRunStyle(levelConfig.font);\n\n const level: ILevelsOptions = {\n level: levelConfig.level,\n format,\n text,\n alignment,\n style: {\n paragraph: {\n indent: {\n left: convertInchesToTwip(baseIndent),\n hanging: convertInchesToTwip(hangingIndent),\n },\n },\n // The marker glyph carries its own run properties; without this it\n // inherits whatever the list paragraph resolves to.\n ...(markerRun && { run: markerRun }),\n },\n // Add start number if specified\n ...(levelConfig.start !== undefined && { start: levelConfig.start }),\n };\n\n levels.push(level);\n }\n\n return {\n reference: config.reference,\n levels,\n };\n}\n\n/**\n * Create a simple bullet list configuration\n */\nexport function createBulletListConfig(\n reference: string,\n bullet: string = '•'\n): { levels: ILevelsOptions[]; reference: string } {\n return {\n reference,\n levels: [\n createDefaultLevel(0, LevelFormat.BULLET, bullet),\n createDefaultLevel(1, LevelFormat.BULLET, '◦'),\n createDefaultLevel(2, LevelFormat.BULLET, '▪'),\n ],\n };\n}\n\n/**\n * Create a simple numbered list configuration\n */\nexport function createNumberedListConfig(\n reference: string,\n start: number = 1\n): { levels: ILevelsOptions[]; reference: string } {\n return {\n reference,\n levels: [\n { ...createDefaultLevel(0, LevelFormat.DECIMAL, '%1.'), start },\n createDefaultLevel(1, LevelFormat.LOWER_LETTER, '%2.'),\n createDefaultLevel(2, LevelFormat.LOWER_ROMAN, '%3.'),\n ],\n };\n}\n\n/**\n * The one multilevel definition every numbered heading in a document shares —\n * shared so that 1., 1.1., 1.1.1. is a single continuous sequence rather than\n * one restarting per heading.\n */\nexport const HEADING_NUMBERING_REFERENCE = 'jto-heading-numbering';\n\n/**\n * Word's built-in heading numbering: decimal at every level, each level's text\n * accumulating the ones above it, bound to `Heading1`..`Heading6` through\n * `w:lvl/w:pStyle` so Word's own \"restart/continue numbering\" UI and the `\\r`\n * cross-reference switch recognise it.\n *\n * The levels are built here rather than through `createNumberingConfig`\n * because that helper applies list indents; a numbered heading stays flush\n * left and takes its indentation from the heading style.\n */\nexport function createHeadingNumberingConfig(): {\n levels: ILevelsOptions[];\n reference: string;\n} {\n const levels: ILevelsOptions[] = [];\n\n for (let level = 0; level < 6; level++) {\n const text =\n Array.from({ length: level + 1 }, (_, i) => `%${i + 1}`).join('.') + '.';\n\n levels.push({\n level,\n format: LevelFormat.DECIMAL,\n text,\n alignment: AlignmentType.LEFT,\n start: 1,\n // A space, not the default tab: a tab would push the heading text to the\n // next tab stop and misalign it against unnumbered headings.\n suffix: LevelSuffix.SPACE,\n style: {\n paragraph: { indent: { left: 0, hanging: 0 } },\n style: `Heading${level + 1}`,\n },\n });\n }\n\n return { reference: HEADING_NUMBERING_REFERENCE, levels };\n}\n\n/**\n * The heading number as Word draws it in the document — the bare dotted number\n * plus the trailing period `lvlText` ends with.\n *\n * A cached TOC entry has to reproduce that form exactly: Word rewrites the\n * entry from the heading's own rendered text the first time it refreshes the\n * field, and an entry cached as \"1.1 Methods\" would visibly shift to\n * \"1.1. Methods\". Cross-references keep the bare number instead — Word's `\\w`\n * switch is defined as the paragraph number *without* trailing periods.\n */\nexport function headingNumberLabel(number: string): string {\n return `${number}.`;\n}\n\n/**\n * Registry for managing numbering configurations\n */\nexport class NumberingRegistry {\n private readonly fallback: NumberingState = {\n configs: new Map(),\n counter: 0,\n };\n private readonly scopes = new AsyncLocalStorage<NumberingState>();\n\n private get state(): NumberingState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run({ configs: new Map(), counter: 0 }, callback);\n }\n\n /**\n * Register a numbering configuration\n */\n register(config: { levels: ILevelsOptions[]; reference: string }): string {\n const reference = config.reference;\n this.state.configs.set(reference, config);\n return reference;\n }\n\n /**\n * Generate a unique reference ID\n */\n generateReference(prefix: string = 'list'): string {\n return `${prefix}-${++this.state.counter}`;\n }\n\n /**\n * Get all registered configurations as an array suitable for INumberingOptions\n */\n getAll(): { levels: ILevelsOptions[]; reference: string }[] {\n return Array.from(this.state.configs.values());\n }\n\n /**\n * Clear all configurations\n */\n clear(): void {\n this.state.configs.clear();\n this.state.counter = 0;\n }\n\n /**\n * Check if a reference exists\n */\n has(reference: string): boolean {\n return this.state.configs.has(reference);\n }\n\n /**\n * Get a configuration by reference\n */\n get(\n reference: string\n ): { levels: ILevelsOptions[]; reference: string } | undefined {\n return this.state.configs.get(reference);\n }\n}\n\n// Global registry instance\nexport const globalNumberingRegistry = new NumberingRegistry();\n","/**\n * Heading Component\n * Standard component for rendering heading elements in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isHeadingComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createHeading } from '../core/content';\nimport { globalBookmarkRegistry } from '../utils/bookmarkRegistry';\nimport {\n globalNumberingRegistry,\n createHeadingNumberingConfig,\n HEADING_NUMBERING_REFERENCE,\n} from '../utils/numberingConfig';\n\n/** Word supports six heading levels; deeper input renders as Heading1. */\nconst MAX_HEADING_LEVEL = 6;\n\n/**\n * Paragraph-level numbering for this heading, or undefined to leave `w:numPr`\n * off entirely.\n *\n * The shared definition is registered lazily, on the first numbered heading,\n * so a document without one carries no extra `w:abstractNum`.\n */\nfunction headingNumbering(\n numbering: boolean | undefined,\n level: number\n): { reference: string; level: number } | false | undefined {\n // An explicit false is the per-heading opt-out from a numbering that\n // componentDefaults turned on document-wide; docx writes it as numId 0.\n if (numbering === false) return false;\n if (numbering !== true) return undefined;\n\n if (!globalNumberingRegistry.has(HEADING_NUMBERING_REFERENCE)) {\n globalNumberingRegistry.register(createHeadingNumberingConfig());\n }\n\n // Mirrors getStyleIdForLevel: an out-of-range level renders as Heading1, so\n // it must number as level 1 too.\n const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;\n return { reference: HEADING_NUMBERING_REFERENCE, level: styleLevel - 1 };\n}\n\n/**\n * Render heading component\n */\nexport function renderHeadingComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): Paragraph[] {\n if (!isHeadingComponent(component)) return [];\n\n // Props are pre-resolved by resolveComponentTree (componentDefaults + level-specific defaults)\n const config = component.props;\n\n // Generate or use bookmark ID for internal linking\n // If component has id, use it; otherwise generate from heading text\n const bookmarkId =\n (component as any).id ||\n globalBookmarkRegistry.generateId(config.text, 'heading');\n\n // Create heading with optional column break and bookmark\n const header = createHeading(\n config.text,\n config.level || 1,\n theme,\n themeName,\n {\n alignment: config.alignment,\n spacing: config.spacing,\n lineSpacing: config.lineSpacing,\n columnBreak: config.columnBreak,\n // Local font overrides\n fontFamily: config.font?.family,\n fontSize: config.font?.size,\n fontColor: config.font?.color,\n bold: config.font?.bold,\n fontWeight: (config.font as { fontWeight?: number } | undefined)\n ?.fontWeight,\n italic: config.font?.italic,\n underline: config.font?.underline,\n scale: config.font?.scale,\n characterSpacing: config.font?.characterSpacing,\n // Proofing: local language override + no-proof toggle + known-words list\n language: config.language,\n noProof: config.noProof,\n noProofWords: config.noProofWords,\n // Pagination control\n keepNext: config.keepNext,\n keepLines: config.keepLines,\n // Paragraph indentation (w:ind) in twips\n indent: config.indent,\n // Bookmark ID for internal linking\n bookmarkId: bookmarkId,\n // Auto-numbering (1., 1.1., …) through the shared heading definition\n numbering: headingNumbering(config.numbering, config.level || 1),\n // Tracked-change segments (rendered as native Word revisions)\n revision: config.revision,\n // Review comment anchored to this heading's text\n comment: config.comment,\n }\n );\n\n return [header];\n}\n","/**\n * Paragraph Component\n * Standard component for rendering paragraph content in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isParagraphComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createText, createList } from '../core/content';\nimport {\n globalNumberingRegistry,\n createNumberingConfig,\n type NumberingConfig,\n type ListLevelConfig,\n} from '../utils/numberingConfig';\n\n/**\n * Parse markdown list syntax from paragraph text\n * Returns null if no list detected, or { type, items } if list found\n */\nfunction parseMarkdownList(text: string): {\n type: 'unordered' | 'ordered';\n items: { text: string; level: number }[];\n} | null {\n const lines = text.split('\\n');\n const items: { text: string; level: number }[] = [];\n let isUnordered: boolean | null = null;\n let isOrdered: boolean | null = null;\n\n for (const line of lines) {\n // Skip empty lines\n if (!line.trim()) continue;\n\n // Match unordered list: optional spaces + (- or *) + space + text\n const unorderedMatch = line.match(/^(\\s*)([-*])\\s+(.+)$/);\n if (unorderedMatch) {\n const indentLevel = Math.floor(unorderedMatch[1].length / 2); // 2 spaces = 1 level\n const text = unorderedMatch[3];\n items.push({ text, level: indentLevel });\n if (isUnordered === null) isUnordered = true;\n continue;\n }\n\n // Match ordered list: optional spaces + number + . + space + text\n const orderedMatch = line.match(/^(\\s*)(\\d+)\\.\\s+(.+)$/);\n if (orderedMatch) {\n const indentLevel = Math.floor(orderedMatch[1].length / 2); // 2 spaces = 1 level\n const text = orderedMatch[3];\n items.push({ text, level: indentLevel });\n if (isOrdered === null) isOrdered = true;\n continue;\n }\n\n // If we find a line that doesn't match list syntax, this isn't a list\n return null;\n }\n\n // If no items found, or mixed list types, not a valid list\n if (items.length === 0 || (isUnordered && isOrdered)) {\n return null;\n }\n\n return {\n type: isUnordered ? 'unordered' : 'ordered',\n items,\n };\n}\n\n/**\n * Render paragraph component\n */\nexport function renderParagraphComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): Paragraph[] {\n if (!isParagraphComponent(component)) return [];\n\n // Props are pre-resolved by resolveComponentTree\n const resolvedConfig = component.props;\n\n // Check if text contains markdown list syntax.\n // Revision paragraphs always render as plain text: their segments carry\n // literal text and cannot be re-split into list items.\n const listData = resolvedConfig.revision\n ? null\n : parseMarkdownList(resolvedConfig.text);\n\n if (listData) {\n // Text is a markdown list - render as proper docx list\n const reference =\n globalNumberingRegistry.generateReference('markdown-list');\n\n // Create appropriate numbering configuration\n const levels: ListLevelConfig[] = [];\n\n if (listData.type === 'unordered') {\n // Bullet list with different bullets for each level\n levels.push(\n { level: 0, format: 'bullet', text: '•', alignment: 'left' },\n { level: 1, format: 'bullet', text: '◦', alignment: 'left' },\n { level: 2, format: 'bullet', text: '▪', alignment: 'left' }\n );\n } else {\n // Ordered list with decimal, lowercase letter, lowercase roman\n levels.push(\n { level: 0, format: 'decimal', text: '%1.', alignment: 'left' },\n { level: 1, format: 'lowerLetter', text: '%2.', alignment: 'left' },\n { level: 2, format: 'lowerRoman', text: '%3.', alignment: 'left' }\n );\n }\n\n const numberingConfig: NumberingConfig = {\n reference,\n levels,\n };\n\n globalNumberingRegistry.register(createNumberingConfig(numberingConfig));\n\n // Create list paragraphs. Comments and notes travel with this path too:\n // a markdown list is still the same paragraph the author annotated.\n return createList(listData.items, theme, themeName, {\n numberingReference: reference,\n spacing: resolvedConfig.spacing as\n | { before?: number; after?: number; item?: number }\n | undefined,\n alignment: resolvedConfig.alignment,\n comment: resolvedConfig.comment,\n footnotes: resolvedConfig.footnotes,\n endnotes: resolvedConfig.endnotes,\n });\n }\n\n // Not a list - render as regular text paragraph\n // Map themeStyle (theme logical name) to DOCX style id\n // Supports both predefined styles and custom styles from theme.styles\n const styleFromTheme = (() => {\n const key = resolvedConfig.themeStyle;\n if (!key) return undefined;\n\n const lowerKey = key.toLowerCase();\n\n // Map predefined style names to Word style IDs\n if (lowerKey === 'normal') return 'Normal';\n if (lowerKey === 'title') return 'Title';\n if (lowerKey === 'subtitle') return 'Subtitle';\n const headingMatch = lowerKey.match(/^heading([1-6])$/);\n if (headingMatch) {\n // For paragraph components, use display-only heading styles that are visually\n // identical but do NOT participate in TOC/outline levels\n return `JTD_HeadingText${headingMatch[1]}`;\n }\n\n // For custom styles, use the exact key as the style ID\n // Custom styles are registered in themeToDocxAdapter with their exact key as ID\n return key;\n })();\n\n // Extract outline level from style if present (for TOC support)\n const outlineLevel = (() => {\n const key = resolvedConfig.themeStyle;\n if (!key) return undefined;\n\n // Never contribute paragraph component paragraphs to TOC when using heading styles\n // Even if the theme sets outlineLevel for heading styles, ignore it here\n const lowerKey = key.toLowerCase();\n const headingMatch = lowerKey.match(/^heading([1-6])$/);\n if (headingMatch) return undefined;\n\n // Check if this is a custom style with outline level\n const customStyle = theme.styles?.[key as keyof typeof theme.styles];\n if (\n customStyle &&\n typeof customStyle === 'object' &&\n 'outlineLevel' in customStyle\n ) {\n return (customStyle as any).outlineLevel;\n }\n\n return undefined;\n })();\n\n // Create text paragraph with optional column break and floating positioning\n const text = createText(resolvedConfig.text, theme, themeName, {\n style: styleFromTheme,\n spacing: resolvedConfig.spacing as\n | { before?: number; after?: number }\n | undefined,\n lineSpacing: resolvedConfig.font?.lineSpacing,\n alignment: resolvedConfig.alignment,\n boldColor: resolvedConfig.boldColor,\n columnBreak: resolvedConfig.columnBreak,\n // Pass font properties\n fontFamily: resolvedConfig.font?.family,\n fontSize: resolvedConfig.font?.size,\n fontColor: resolvedConfig.font?.color,\n bold: resolvedConfig.font?.bold,\n fontWeight: (resolvedConfig.font as { fontWeight?: number } | undefined)\n ?.fontWeight,\n italic: resolvedConfig.font?.italic,\n underline: resolvedConfig.font?.underline,\n scale: resolvedConfig.font?.scale,\n characterSpacing: resolvedConfig.font?.characterSpacing,\n // Proofing: local language override + no-proof toggle + known-words list\n language: resolvedConfig.language,\n noProof: resolvedConfig.noProof,\n noProofWords: resolvedConfig.noProofWords,\n // Pass outline level for TOC support\n outlineLevel: outlineLevel,\n // Pass floating positioning properties\n floating: resolvedConfig.floating,\n // Pass keepNext property\n keepNext: resolvedConfig.keepNext,\n // Pass keepLines property\n keepLines: resolvedConfig.keepLines,\n // Paragraph indentation (w:ind) in twips\n indent: resolvedConfig.indent,\n // Tab stops (w:tabs); \\t characters in text jump to these positions\n tabStops: resolvedConfig.tabStops,\n // Pass bookmark ID for internal linking\n bookmarkId: resolvedConfig.id,\n // Tracked-change segments (rendered as native Word revisions)\n revision: resolvedConfig.revision,\n // Review comment anchored to this paragraph's text\n comment: resolvedConfig.comment,\n // Note bodies for the `[^id]` markers in this paragraph\n footnotes: resolvedConfig.footnotes,\n endnotes: resolvedConfig.endnotes,\n });\n\n return [text];\n}\n","/**\n * Level derivation for `list` components.\n *\n * Shared by the renderer (which turns these into `w:abstractNum` levels) and by\n * the document-outline pre-pass (which needs each level's format and start to\n * predict the counter a cross-reference should cache). Keeping one definition\n * is the point: a level the renderer numbers `a., b., c.` and a pre-pass that\n * thinks it is decimal produce a field whose cached value Word overwrites on\n * refresh — the silent disagreement cross-references exist to avoid.\n */\n\nimport type { ListLevelConfig } from './numberingConfig';\n\n/** The `list` props this module reads, structurally. */\nexport interface ListLevelSource {\n items?: readonly (string | { readonly level?: number })[];\n levels?: readonly ListLevelConfig[];\n format?: string;\n bullet?: string;\n start?: number;\n indent?: number | { left?: number; hanging?: number };\n}\n\n/**\n * Convert simplified format to proper level configurations\n */\nfunction createLevelsFromSimplifiedProps(\n props: ListLevelSource\n): ListLevelConfig[] {\n const levels: ListLevelConfig[] = [];\n\n // Determine format from simplified options\n let format: string;\n let text: string | undefined;\n\n if (props.format) {\n if (props.format === 'numbered') {\n format = 'decimal';\n text = '%1.';\n } else if (props.format === 'none') {\n format = 'none';\n text = '';\n } else {\n format = props.format;\n }\n } else {\n // Default to bullet\n format = 'bullet';\n text = props.bullet || '•';\n }\n\n // Create level 0 configuration\n const level0: ListLevelConfig = {\n level: 0,\n format,\n text,\n alignment: 'left',\n start: props.start,\n };\n\n // Add indent if specified\n if (props.indent) {\n if (typeof props.indent === 'number') {\n level0.indent = { left: props.indent };\n } else {\n level0.indent = props.indent;\n }\n }\n\n levels.push(level0);\n\n // Add default sublevels for nested lists\n if (format === 'bullet') {\n levels.push(\n { level: 1, format: 'bullet', text: '◦', alignment: 'left' },\n { level: 2, format: 'bullet', text: '▪', alignment: 'left' }\n );\n } else if (format === 'decimal') {\n levels.push(\n { level: 1, format: 'lowerLetter', text: '%2.', alignment: 'left' },\n { level: 2, format: 'lowerRoman', text: '%3.', alignment: 'left' }\n );\n }\n\n return levels;\n}\n\n/**\n * Fold `props.start` into level 0.\n *\n * `start` is otherwise only read on the simplified path, so an explicit\n * `levels` array silently discarded it. A `start` declared on the level itself\n * is more specific and wins.\n */\nfunction applyListStart(\n levels: readonly ListLevelConfig[],\n start: number | undefined\n): ListLevelConfig[] {\n if (start === undefined) return [...levels];\n return levels.map((level) =>\n level.level === 0 && level.start === undefined ? { ...level, start } : level\n );\n}\n\n/**\n * Get the maximum level used in list items\n */\nexport function getMaxLevelFromItems(\n items: readonly (string | { readonly level?: number })[] | undefined\n): number {\n if (!items || !Array.isArray(items)) {\n return 0;\n }\n\n let maxLevel = 0;\n for (const item of items) {\n if (typeof item === 'object' && item.level !== undefined) {\n maxLevel = Math.max(maxLevel, item.level);\n }\n }\n return maxLevel;\n}\n\n/**\n * Fill in missing levels with default configurations\n */\nfunction fillMissingLevels(\n levels: readonly ListLevelConfig[],\n maxLevel: number\n): ListLevelConfig[] {\n // Create a map of existing levels\n const levelMap = new Map<number, ListLevelConfig>();\n for (const level of levels) {\n levelMap.set(level.level, level);\n }\n\n // Get level 0 to determine the base format\n const level0 = levelMap.get(0);\n const baseFormat = level0?.format || 'bullet';\n\n // Create default levels for any missing ones\n const result: ListLevelConfig[] = [];\n for (let i = 0; i <= maxLevel; i++) {\n if (levelMap.has(i)) {\n result.push(levelMap.get(i)!);\n } else {\n // Create default sublevel based on parent format\n if (baseFormat === 'bullet') {\n const bullets = ['•', '◦', '▪', '▫', '‣'];\n result.push({\n level: i,\n format: 'bullet',\n text: bullets[i % bullets.length],\n alignment: 'left',\n });\n } else if (baseFormat === 'decimal' || baseFormat === 'numbered') {\n const formats = ['decimal', 'lowerLetter', 'lowerRoman'];\n const format = formats[i % formats.length];\n result.push({\n level: i,\n format,\n text: `%${i + 1}.`,\n alignment: 'left',\n });\n } else {\n // For other formats, continue with the same format\n result.push({\n level: i,\n format: baseFormat,\n text: `%${i + 1}.`,\n alignment: 'left',\n });\n }\n }\n }\n\n return result;\n}\n\n/**\n * The levels a list's numbering definition ends up with: explicit `levels` when\n * given (with `props.start` folded in), otherwise the simplified shorthand —\n * either way padded out to the deepest level the items actually use.\n */\nexport function resolveListLevels(props: ListLevelSource): ListLevelConfig[] {\n const maxLevel = getMaxLevelFromItems(props.items);\n\n if (props.levels && props.levels.length > 0) {\n return fillMissingLevels(\n applyListStart(props.levels, props.start),\n maxLevel\n );\n }\n\n return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);\n}\n","/**\n * List Component\n * Standard component for rendering list elements in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isListComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createList } from '../core/content';\nimport {\n globalNumberingRegistry,\n createNumberingConfig,\n type NumberingConfig,\n type ListLevelConfig,\n type ListMarkerFontConfig,\n} from '../utils/numberingConfig';\nimport { resolveListLevels } from '../utils/listLevels';\nimport { resolveColor } from '../styles/utils/colorUtils';\n\n/**\n * Resolve a level's marker font against the theme.\n *\n * `color` accepts a theme token exactly like every other colour in the schema,\n * but the numbering config is theme-free by the time docx sees it, so the\n * token is resolved here.\n */\nfunction resolveMarkerFonts(\n levels: ListLevelConfig[],\n theme: ThemeConfig\n): ListLevelConfig[] {\n return levels.map((level) => {\n const font = level.font as ListMarkerFontConfig | undefined;\n if (!font?.color) return level;\n return {\n ...level,\n font: { ...font, color: resolveColor(font.color, theme) },\n };\n });\n}\n\n/**\n * Render list component\n */\nexport function renderListComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): Paragraph[] {\n if (!isListComponent(component)) return [];\n\n // Props are pre-resolved by resolveComponentTree\n const resolvedConfig = component.props;\n\n // Generate or use provided reference ID\n const reference =\n resolvedConfig.reference ||\n globalNumberingRegistry.generateReference('list');\n\n // Build numbering configuration if not already registered\n if (!globalNumberingRegistry.has(reference)) {\n const config: NumberingConfig = {\n reference,\n levels: resolveMarkerFonts(resolveListLevels(resolvedConfig), theme),\n };\n const numberingConfig = createNumberingConfig(config);\n globalNumberingRegistry.register(numberingConfig);\n }\n\n // Create the list paragraphs with numbering reference\n return createList(resolvedConfig.items, theme, themeName, {\n numberingReference: reference,\n spacing: resolvedConfig.spacing,\n alignment: resolvedConfig.alignment,\n // Review comment spanning the whole list\n comment: resolvedConfig.comment,\n });\n}\n","/**\n * Image Component\n * Standard component for rendering images in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isImageComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createImage } from '../core/content';\nimport { resolveImageSource } from '../utils/imageUtils';\n\n/**\n * Render image component\n */\nexport async function renderImageComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName?: string\n): Promise<Paragraph[]> {\n if (!isImageComponent(component)) return [];\n\n // Props are pre-resolved by resolveComponentTree\n const resolvedConfig = component.props;\n\n // Resolve source: inline svg > base64 > path\n const imageSource = resolveImageSource(resolvedConfig);\n\n if (!imageSource) {\n throw new Error(\n 'Image component requires one of \"path\", \"base64\", or \"svg\" property'\n );\n }\n\n return await createImage(imageSource, theme, themeName, {\n caption: resolvedConfig.caption,\n width: resolvedConfig.width,\n height: resolvedConfig.height,\n widthRelativeTo: (resolvedConfig as any).widthRelativeTo,\n heightRelativeTo: (resolvedConfig as any).heightRelativeTo,\n alignment: resolvedConfig.alignment,\n spacing: resolvedConfig.spacing,\n floating: resolvedConfig.floating,\n keepNext: resolvedConfig.keepNext,\n keepLines: resolvedConfig.keepLines,\n });\n}\n","/**\n * Text Box Component\n * Floating container that groups child paragraphs (from text/image components)\n */\n\nimport {\n Paragraph,\n Table,\n TableRow,\n TableCell,\n WidthType,\n TableAnchorType,\n RelativeHorizontalPosition,\n RelativeVerticalPosition,\n OverlapType,\n TableLayoutType,\n WpsShapeRun,\n type IWpsShapeOptions,\n} from 'docx';\nimport {\n ComponentDefinition,\n TextBoxComponentDefinition,\n isTextBoxComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\n// No direct image or text parsing here; children components render themselves\nimport { renderComponent } from '../core/render';\nimport { NONE_BORDERS } from '../styles/utils/borderUtils';\nimport { buildCellOptions, CellStyleConfig } from '../styles/utils/cellUtils';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport { mapFloatingOptions } from '../utils/docxImagePositioning';\nimport {\n resolveOffsetTwips,\n getPageWidthTwips,\n getPageHeightTwips,\n getAvailableWidthTwips,\n getAvailableHeightTwips,\n} from '../utils/widthUtils';\n\n// VML style helpers removed in favor of floating table approach\n\n// Map floating config to docx paragraph frame options to enforce wrapping at paragraph level\n\n// Map floating config to table float options for a one-cell table container\nfunction mapTableFloatOptions(\n floating?: NonNullable<TextBoxComponentDefinition['props']['floating']>,\n theme?: ThemeConfig,\n themeName?: string\n): any | undefined {\n if (!floating) return undefined;\n\n const opt: any = {};\n\n // Determine reference dimensions for percentage resolution\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n const hRef =\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(theme, themeName)\n : getPageWidthTwips(theme, themeName);\n const vRef =\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(theme, themeName)\n : getPageHeightTwips(theme, themeName);\n\n const hp = floating.horizontalPosition;\n if (hp?.relative) {\n opt.horizontalAnchor =\n hp.relative === 'margin'\n ? TableAnchorType.MARGIN\n : hp.relative === 'page'\n ? TableAnchorType.PAGE\n : TableAnchorType.TEXT;\n }\n if (hp?.offset !== undefined) {\n opt.absoluteHorizontalPosition = resolveOffsetTwips(hp.offset, hRef);\n } else if (hp?.align) {\n const map: Record<\n string,\n (typeof RelativeHorizontalPosition)[keyof typeof RelativeHorizontalPosition]\n > = {\n left: RelativeHorizontalPosition.LEFT,\n center: RelativeHorizontalPosition.CENTER,\n right: RelativeHorizontalPosition.RIGHT,\n inside: RelativeHorizontalPosition.INSIDE,\n outside: RelativeHorizontalPosition.OUTSIDE,\n };\n opt.relativeHorizontalPosition = map[hp.align];\n }\n\n const vp = floating.verticalPosition;\n if (vp?.relative) {\n opt.verticalAnchor =\n vp.relative === 'margin'\n ? TableAnchorType.MARGIN\n : vp.relative === 'page'\n ? TableAnchorType.PAGE\n : TableAnchorType.TEXT;\n }\n if (vp?.offset !== undefined) {\n opt.absoluteVerticalPosition = resolveOffsetTwips(vp.offset, vRef);\n } else if (vp?.align) {\n const mapV: Record<\n string,\n (typeof RelativeVerticalPosition)[keyof typeof RelativeVerticalPosition]\n > = {\n top: RelativeVerticalPosition.TOP,\n center: RelativeVerticalPosition.CENTER,\n bottom: RelativeVerticalPosition.BOTTOM,\n inside: RelativeVerticalPosition.INSIDE,\n outside: RelativeVerticalPosition.OUTSIDE,\n } as any;\n opt.relativeVerticalPosition = mapV[vp.align];\n }\n\n // Map wrap margins to clearance distances (resolve percentages against page dimensions)\n const pageW = getPageWidthTwips(theme, themeName);\n const pageH = getPageHeightTwips(theme, themeName);\n const m = floating.wrap?.margins;\n if (m) {\n if (m.top !== undefined) opt.topFromText = resolveOffsetTwips(m.top, pageH);\n if (m.right !== undefined)\n opt.rightFromText = resolveOffsetTwips(m.right, pageW);\n if (m.bottom !== undefined)\n opt.bottomFromText = resolveOffsetTwips(m.bottom, pageH);\n if (m.left !== undefined)\n opt.leftFromText = resolveOffsetTwips(m.left, pageW);\n }\n\n opt.overlap = OverlapType.OVERLAP;\n\n return opt;\n}\n\n/**\n * Render a text box's children with the box itself as their parent — the link\n * that makes a nested `columns` render as a table rather than as a\n * section-level column layout.\n */\nasync function renderTextBoxChildren(\n tb: TextBoxComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: import('../types').RenderContext\n): Promise<(Paragraph | Table)[]> {\n const childContext: import('../types').RenderContext = {\n ...context,\n parent: tb,\n };\n\n const rendered: (Paragraph | Table)[] = [];\n for (const child of tb.children || []) {\n rendered.push(\n ...(await renderComponent(child, theme, themeName, childContext))\n );\n }\n return rendered;\n}\n\n/**\n * Render the text box as a borderless one-cell table — the default, and the\n * only rendering with autofit, per-side borders and lazy percentage widths.\n *\n * `prerendered` carries the children a failed shape attempt already rendered:\n * rendering them again would repeat their bookmark, comment and footnote\n * registrations.\n */\nasync function renderTextBoxAsTable(\n tb: TextBoxComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n _context: import('../types').RenderContext,\n prerendered?: (Paragraph | Table)[]\n): Promise<(Paragraph | Table)[]> {\n const isInline = !tb.props.floating;\n\n if (isInline) {\n // Inline: use a one-cell table container for multi-paragraph support\n const cellChildren =\n prerendered ??\n (await renderTextBoxChildren(tb, theme, themeName, _context));\n\n const styleCfg = (tb.props as any).style as CellStyleConfig | undefined;\n const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);\n\n const row = new TableRow({ children: [new TableCell(cellOpts)] });\n const table = new Table({\n layout: TableLayoutType.FIXED, // Lock column widths\n rows: [row],\n width: { size: 100, type: WidthType.PERCENTAGE },\n borders: NONE_BORDERS,\n });\n return [table];\n }\n\n // Always use a floating one-cell table container for multi-paragraph support\n const cellChildren =\n prerendered ??\n (await renderTextBoxChildren(tb, theme, themeName, _context));\n\n const styleCfg = (tb.props as any).style as CellStyleConfig | undefined;\n const cellOpts = buildCellOptions(cellChildren, styleCfg, theme);\n\n const row = new TableRow({\n children: [new TableCell(cellOpts)],\n });\n\n const float = mapTableFloatOptions(tb.props.floating, theme, themeName);\n\n // Conversion factor: 1 pixel = 15 twips (at 96 DPI: 1440 twips/inch / 96 pixels/inch)\n const PIXELS_TO_TWIPS = 15;\n const DEFAULT_WIDTH_TWIPS = 5000; // ~333 pixels\n\n // Support width as number (pixels) or percentage string\n // Read from props.width (new location) with fallback to props.floating.width (legacy, in twips)\n const rawWidth = tb.props.width ?? (tb.props.floating as any)?.width;\n let widthSize: number;\n let widthType: (typeof WidthType)[keyof typeof WidthType];\n\n if (rawWidth === undefined) {\n // No width specified, use default\n widthSize = DEFAULT_WIDTH_TWIPS;\n widthType = WidthType.DXA;\n } else if (typeof rawWidth === 'string' && rawWidth.endsWith('%')) {\n // Percentage width\n widthSize = parseFloat(rawWidth);\n widthType = WidthType.PERCENTAGE;\n } else {\n // Number in pixels - convert to twips (DXA)\n widthSize =\n typeof rawWidth === 'number'\n ? rawWidth * PIXELS_TO_TWIPS\n : DEFAULT_WIDTH_TWIPS;\n widthType = WidthType.DXA;\n }\n\n const table = new Table({\n layout: TableLayoutType.FIXED, // Lock column widths\n rows: [row],\n width: { size: widthSize, type: widthType },\n float,\n borders: NONE_BORDERS,\n });\n return [table];\n}\n\n/** 1 px at 96 DPI in EMU (914400 EMU/inch ÷ 96 px/inch). */\nconst PIXELS_TO_EMU = 9525;\n/** 1 px at 96 DPI in twips (1440 twips/inch ÷ 96 px/inch). */\nconst TWIPS_PER_PIXEL = 15;\n\ntype TextBoxStyle = NonNullable<TextBoxComponentDefinition['props']['style']>;\ntype BorderSide = NonNullable<NonNullable<TextBoxStyle['border']>['top']>;\n\n/**\n * Resolve a `width`/`height` prop to whole pixels.\n *\n * A shape carries an absolute size in the file, so a percentage cannot stay\n * lazy the way a table's `w:tblW` can: it is resolved here against the page's\n * content box and frozen. Callers warn about that, once per text box.\n */\nfunction resolveShapeSize(\n value: number | string | undefined,\n axis: 'width' | 'height',\n theme: ThemeConfig,\n themeName: string\n): { pixels?: number; resolvedPercentage: boolean } {\n if (typeof value === 'number') {\n return { pixels: Math.round(value), resolvedPercentage: false };\n }\n if (typeof value !== 'string') return { resolvedPercentage: false };\n\n const fraction = parseFloat(value) / 100;\n if (!Number.isFinite(fraction) || fraction <= 0) {\n return { resolvedPercentage: false };\n }\n const availableTwips =\n axis === 'width'\n ? getAvailableWidthTwips(theme, themeName)\n : getAvailableHeightTwips(theme, themeName);\n return {\n pixels: Math.round((availableTwips * fraction) / TWIPS_PER_PIXEL),\n resolvedPercentage: true,\n };\n}\n\n/** Hex without the leading '#', which DrawingML's `a:srgbClr` does not take. */\nfunction shapeColor(value: string, theme: ThemeConfig): string {\n return resolveColor(value, theme).replace(/^#/, '');\n}\n\n/**\n * Collapse the per-side border config into the single `a:ln` a shape has.\n *\n * Sides are considered in top/left/bottom/right order; when they disagree, the\n * first one wins and the caller is told which.\n */\nfunction shapeOutline(\n style: TextBoxStyle | undefined,\n theme: ThemeConfig\n): {\n outline?: IWpsShapeOptions['outline'];\n ignoredSides: string[];\n unsupportedStyles: string[];\n} {\n const border = style?.border;\n if (!border) return { ignoredSides: [], unsupportedStyles: [] };\n\n const order: (keyof NonNullable<TextBoxStyle['border']>)[] = [\n 'top',\n 'left',\n 'bottom',\n 'right',\n ];\n const declared = order\n .map((side) => [side, border[side]] as const)\n .filter((entry): entry is [(typeof order)[number], BorderSide] =>\n Boolean(entry[1])\n );\n if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };\n\n // docx's OutlineOptions carries width, cap, compound and fill — there is no\n // `a:prstDash`, so a dash pattern cannot be expressed at all, and the one\n // `compoundLine` that could stand in for `double` is emitted as the enum key\n // (`cmpd=\"DOUBLE\"`) rather than the OOXML value. Drawing any of the three as\n // a plain solid line would silently change the design, so the caller falls\n // back to the table rendering, which supports all of them.\n const unsupportedStyles = [\n ...new Set(\n declared\n .map(([, config]) => config.style)\n .filter(\n (value): value is 'dashed' | 'dotted' | 'double' =>\n value === 'dashed' || value === 'dotted' || value === 'double'\n )\n ),\n ];\n if (unsupportedStyles.length > 0) {\n return { ignoredSides: [], unsupportedStyles };\n }\n\n const [, used] = declared[0];\n const differs = ({ style: s, width, color }: BorderSide): boolean =>\n s !== used.style || width !== used.width || color !== used.color;\n const ignoredSides = declared\n .slice(1)\n .filter(([, config]) => differs(config))\n .map(([side]) => side);\n\n if (used.style === 'none') return { ignoredSides, unsupportedStyles };\n\n return {\n outline: {\n type: 'solidFill',\n solidFillType: 'rgb',\n value: used.color ? shapeColor(used.color, theme) : '000000',\n ...(used.width !== undefined && {\n width: Math.round(used.width * PIXELS_TO_EMU),\n }),\n },\n ignoredSides,\n unsupportedStyles,\n };\n}\n\n/** `bodyPr` insets are EMU, like every other DrawingML length. */\nfunction shapeBodyProperties(\n style: TextBoxStyle | undefined\n): IWpsShapeOptions['bodyProperties'] {\n const padding = style?.padding;\n if (!padding) return undefined;\n\n const toEmu = (value: number | undefined) =>\n value === undefined ? undefined : Math.round(value * PIXELS_TO_EMU);\n\n return {\n margins: {\n ...(padding.top !== undefined && { top: toEmu(padding.top) }),\n ...(padding.bottom !== undefined && { bottom: toEmu(padding.bottom) }),\n ...(padding.left !== undefined && { left: toEmu(padding.left) }),\n ...(padding.right !== undefined && { right: toEmu(padding.right) }),\n },\n };\n}\n\n/**\n * A shape rendering, or the reason there is none — carrying back whatever the\n * attempt already rendered so the table fallback can reuse it.\n */\ntype ShapeAttempt =\n | { kind: 'shape'; paragraphs: Paragraph[] }\n | { kind: 'fallback'; rendered?: (Paragraph | Table)[] };\n\n/**\n * Render the text box as a native Word text box (a `wps:wsp` shape).\n *\n * Everything a shape cannot express falls back to the table rendering rather\n * than shipping a box that clips its content or quietly redraws its border.\n *\n * The two prop-only limits — a missing dimension and a dash-patterned border —\n * are rejected by `collectTextBoxShapeConflicts` during validation, where the\n * author can act on them. The guards below are the safety net for callers that\n * render without validating; they run before the children do, so the fallback\n * never renders a child twice.\n */\nasync function renderTextBoxAsShape(\n tb: TextBoxComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: import('../types').RenderContext\n): Promise<ShapeAttempt> {\n const width = resolveShapeSize(tb.props.width, 'width', theme, themeName);\n const height = resolveShapeSize(tb.props.height, 'height', theme, themeName);\n if (width.pixels === undefined || height.pixels === undefined) {\n console.warn(\n '[core-docx] text-box renderAs \"shape\" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'\n );\n return { kind: 'fallback' };\n }\n\n const style = tb.props.style;\n const { outline, ignoredSides, unsupportedStyles } = shapeOutline(\n style,\n theme\n );\n if (unsupportedStyles.length > 0) {\n console.warn(\n `[core-docx] text-box renderAs \"shape\" cannot draw a ${unsupportedStyles.join('/')} border (a shape outline has no dash pattern); falling back to table rendering, which draws it.`\n );\n return { kind: 'fallback' };\n }\n\n const rendered = await renderTextBoxChildren(tb, theme, themeName, context);\n // `WpsShapeCoreOptions.children` is `readonly Paragraph[]`: a nested\n // `columns` (which renders as a Table) has nowhere to go in a shape.\n if (rendered.some((element) => !(element instanceof Paragraph))) {\n console.warn(\n '[core-docx] text-box renderAs \"shape\" requires paragraph-only content; falling back to table rendering.'\n );\n return { kind: 'fallback', rendered };\n }\n const children = rendered as Paragraph[];\n\n if (width.resolvedPercentage || height.resolvedPercentage) {\n console.warn(\n '[core-docx] text-box renderAs \"shape\" resolves percentage sizes at generation time, against the current page content box; the shape will not reflow if the page size changes.'\n );\n }\n\n const fill = style?.shading?.fill;\n if (ignoredSides.length > 0) {\n console.warn(\n `[core-docx] text-box renderAs \"shape\" has one uniform outline; using the first declared border side and ignoring ${ignoredSides.join(', ')}.`\n );\n }\n\n // docx 9.7.1 emits `a:noFill` + `a:ln` for an outline and then `a:solidFill`\n // for the fill, which is two fill groups in the wrong order for\n // CT_ShapeProperties — Word rejects it. Verified against the packed XML, so\n // when both are asked for, the fill wins.\n const dropOutline = Boolean(fill) && Boolean(outline);\n if (dropOutline) {\n console.warn(\n '[core-docx] text-box renderAs \"shape\" cannot carry a fill and a border at once (docx emits invalid shape properties); keeping the fill and dropping the border.'\n );\n }\n\n const bodyProperties = shapeBodyProperties(style);\n const run = new WpsShapeRun({\n type: 'wps',\n children,\n transformation: { width: width.pixels, height: height.pixels },\n ...(fill && {\n solidFill: { type: 'rgb', value: shapeColor(fill, theme) } as const,\n }),\n ...(outline && !dropOutline && { outline }),\n ...(bodyProperties && { bodyProperties }),\n // Absent `floating` makes it a `wp:inline` drawing.\n ...(tb.props.floating && {\n floating: mapFloatingOptions(tb.props.floating, theme, themeName),\n }),\n });\n\n return {\n kind: 'shape',\n paragraphs: [\n new Paragraph({ children: [run], spacing: { before: 0, after: 0 } }),\n ],\n };\n}\n\nexport async function renderTextBoxComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: import('../types').RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!isTextBoxComponent(component)) return [];\n const tb = component as TextBoxComponentDefinition;\n\n if (tb.props.renderAs === 'shape') {\n const attempt = await renderTextBoxAsShape(tb, theme, themeName, context);\n if (attempt.kind === 'shape') return attempt.paragraphs;\n return renderTextBoxAsTable(\n tb,\n theme,\n themeName,\n context,\n attempt.rendered\n );\n }\n\n return renderTextBoxAsTable(tb, theme, themeName, context);\n}\n","/**\n * Border utilities for consistent border styling across modules\n */\n\nimport { BorderStyle } from 'docx';\nimport { resolveColor } from './colorUtils';\nimport { ThemeConfig } from '../index';\n\n/**\n * Standard \"no borders\" configuration for tables\n * Used when borders should be invisible/disabled\n */\nexport const NONE_BORDERS = {\n top: { style: BorderStyle.NONE, size: 0, color: '000000' },\n right: { style: BorderStyle.NONE, size: 0, color: '000000' },\n bottom: { style: BorderStyle.NONE, size: 0, color: '000000' },\n left: { style: BorderStyle.NONE, size: 0, color: '000000' },\n insideHorizontal: { style: BorderStyle.NONE, size: 0, color: '000000' },\n insideVertical: { style: BorderStyle.NONE, size: 0, color: '000000' },\n} as const;\n\n/**\n * Maps border style string to docx BorderStyle enum\n * @param s - Border style string ('dashed', 'dotted', 'double', 'none', 'single')\n * @returns Corresponding BorderStyle enum value\n */\nexport function mapBorderStyle(\n s?: string\n): (typeof BorderStyle)[keyof typeof BorderStyle] {\n switch (s) {\n case 'dashed':\n return BorderStyle.DASHED;\n case 'dotted':\n return BorderStyle.DOTTED;\n case 'double':\n return BorderStyle.DOUBLE;\n case 'none':\n return BorderStyle.NONE;\n default:\n return BorderStyle.SINGLE;\n }\n}\n\n/**\n * Border configuration object\n */\nexport interface BorderConfig {\n style?: string;\n width?: number;\n color?: string;\n}\n\n/**\n * Converts border configuration to docx border format\n * @param b - Border configuration object\n * @param theme - Theme configuration for color resolution\n * @returns Docx border object or undefined if no border\n */\nexport function convertBorder(\n b: BorderConfig | undefined,\n theme: ThemeConfig\n):\n | {\n style: (typeof BorderStyle)[keyof typeof BorderStyle];\n size: number;\n color: string;\n }\n | undefined {\n if (!b) return undefined;\n\n return {\n style: mapBorderStyle(b.style),\n size: b.width !== undefined ? Math.max(1, Math.round(b.width * 8)) : 1,\n color: b.color ? resolveColor(b.color, theme) : '000000',\n };\n}\n\n/**\n * Borders configuration for all four sides\n */\nexport interface BordersConfig {\n top?: BorderConfig;\n right?: BorderConfig;\n bottom?: BorderConfig;\n left?: BorderConfig;\n}\n\n/**\n * Converts borders configuration object to docx borders format\n * Returns undefined if no borders are defined\n * @param bordersConfig - Configuration for all four borders\n * @param theme - Theme configuration for color resolution\n * @returns Docx borders object or undefined\n */\nexport function convertBorders(\n bordersConfig: BordersConfig | undefined,\n theme: ThemeConfig\n):\n | Record<\n string,\n {\n style: (typeof BorderStyle)[keyof typeof BorderStyle];\n size: number;\n color: string;\n }\n >\n | undefined {\n if (!bordersConfig) return undefined;\n\n const borders: Record<\n string,\n {\n style: (typeof BorderStyle)[keyof typeof BorderStyle];\n size: number;\n color: string;\n }\n > = {};\n\n const top = convertBorder(bordersConfig.top, theme);\n const right = convertBorder(bordersConfig.right, theme);\n const bottom = convertBorder(bordersConfig.bottom, theme);\n const left = convertBorder(bordersConfig.left, theme);\n\n if (top) borders.top = top;\n if (right) borders.right = right;\n if (bottom) borders.bottom = bottom;\n if (left) borders.left = left;\n\n return Object.keys(borders).length > 0 ? borders : undefined;\n}\n","/**\n * Cell utilities for building table cell configurations\n */\n\nimport { Paragraph, Table } from 'docx';\nimport { pointsToTwips } from './styleHelpers';\nimport { resolveColor } from './colorUtils';\nimport { ThemeConfig } from '../index';\nimport { convertBorders, BordersConfig } from './borderUtils';\n\n/**\n * Padding configuration for all four sides\n */\nexport interface PaddingConfig {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n}\n\n/**\n * Shading configuration\n */\nexport interface ShadingConfig {\n fill?: string;\n}\n\n/**\n * Complete cell style configuration\n */\nexport interface CellStyleConfig {\n padding?: PaddingConfig;\n border?: BordersConfig;\n shading?: ShadingConfig;\n}\n\n/**\n * Builds cell options object for TableCell constructor\n * Handles margins (padding), shading, and borders consistently\n * @param children - Child elements to include in the cell\n * @param styleCfg - Style configuration for the cell\n * @param theme - Theme configuration for color resolution\n * @returns Cell options object ready for TableCell constructor\n */\nexport function buildCellOptions(\n children: (Paragraph | Table)[],\n styleCfg: CellStyleConfig | undefined,\n theme: ThemeConfig\n): {\n children: (Paragraph | Table)[];\n margins: {\n top: number;\n right: number;\n bottom: number;\n left: number;\n };\n shading?: { fill: string };\n borders?: Record<string, { style: any; size: number; color: string }>;\n} {\n const cellOpts: any = {\n children: children.length ? children : [new Paragraph({})],\n margins: {\n top: styleCfg?.padding?.top ? pointsToTwips(styleCfg.padding.top) : 0,\n right: styleCfg?.padding?.right\n ? pointsToTwips(styleCfg.padding.right)\n : 0,\n bottom: styleCfg?.padding?.bottom\n ? pointsToTwips(styleCfg.padding.bottom)\n : 0,\n left: styleCfg?.padding?.left ? pointsToTwips(styleCfg.padding.left) : 0,\n },\n };\n\n // Apply shading if configured\n if (styleCfg?.shading?.fill) {\n cellOpts.shading = { fill: resolveColor(styleCfg.shading.fill, theme) };\n }\n\n // Apply borders if configured\n if (styleCfg?.border) {\n const borders = convertBorders(styleCfg.border, theme);\n if (borders && Object.keys(borders).length > 0) {\n cellOpts.borders = borders;\n }\n }\n\n return cellOpts;\n}\n","/**\n * Table Component\n * Standard component for rendering tables in documents\n */\n\nimport { Table } from 'docx';\nimport { ComponentDefinition, isTableComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createTable } from '../core/content';\nimport type {\n Comment,\n Revision,\n RevisionMark,\n} from '@json-to-office/shared-docx';\n\ntype CellContent = string | ComponentDefinition;\n\ntype HorizontalAlignment = 'left' | 'center' | 'right' | 'justify';\n\ntype VerticalAlignment = 'top' | 'middle' | 'bottom';\n\ntype FontConfig = {\n family?: string;\n size?: number;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n};\n\ntype BorderColor =\n | string\n | {\n bottom?: string;\n top?: string;\n right?: string;\n left?: string;\n };\n\ntype BorderSize =\n | number\n | {\n bottom?: number;\n top?: number;\n right?: number;\n left?: number;\n };\n\ntype Padding =\n | number\n | {\n bottom?: number;\n top?: number;\n right?: number;\n left?: number;\n };\n\ntype CellDefaults = {\n color?: string;\n backgroundColor?: string;\n horizontalAlignment?: HorizontalAlignment;\n verticalAlignment?: VerticalAlignment;\n font?: FontConfig;\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n padding?: Padding;\n height?: number;\n};\n\ntype TableConfig = {\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n cellDefaults?: CellDefaults;\n headerCellDefaults?: CellDefaults;\n width?: number;\n columns: {\n /** Width in points (number) or as percentage string e.g. \"40%\" */\n width?: number | string;\n cellDefaults?: CellDefaults;\n header?: CellDefaults & {\n comment?: Comment;\n revision?: Revision;\n content?: CellContent;\n };\n cells?: (CellDefaults & {\n comment?: Comment;\n revision?: Revision;\n content?: CellContent;\n })[];\n }[];\n /** Row-parallel properties, indexed like `columns[].cells`. */\n rows?: {\n revision?: RevisionMark;\n cantSplit?: boolean;\n tableHeader?: boolean;\n }[];\n keepInOnePage?: boolean;\n keepNext?: boolean;\n repeatHeaderOnPageBreak?: boolean;\n};\n\n/**\n * Render table component\n * Supports new column-based format with cell defaults and legacy headers/rows format\n */\nexport async function renderTableComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): Promise<Table[]> {\n if (!isTableComponent(component)) return [];\n\n const rawConfig = component.props as any;\n const result: Table[] = [];\n\n // Check if this is the old format (has headers and rows properties)\n if (rawConfig.headers && rawConfig.rows) {\n // Convert old format to new format\n const headers = rawConfig.headers as string[];\n const rows = rawConfig.rows as string[][];\n\n const defaultCellDefaults: CellDefaults = {\n color: '000000',\n backgroundColor: 'transparent',\n horizontalAlignment: 'left',\n verticalAlignment: 'top',\n font: {\n family: 'Arial',\n size: 11,\n bold: false,\n italic: false,\n underline: false,\n },\n borderColor: '000000',\n borderSize: 1,\n };\n\n const config: TableConfig = {\n borderColor: '000000',\n borderSize: 1,\n cellDefaults: defaultCellDefaults,\n width: 100,\n columns: headers.map((header, colIndex) => ({\n cellDefaults: { ...defaultCellDefaults },\n header: {\n ...defaultCellDefaults,\n content: header,\n },\n cells: rows.map((row) => ({\n ...defaultCellDefaults,\n content: row[colIndex] || '',\n })),\n })),\n };\n\n result.push(await createTable(config.columns, config, theme, themeName));\n\n return result;\n }\n\n // New column-based format\n const config = rawConfig as TableConfig;\n\n result.push(await createTable(config.columns, config, theme, themeName));\n\n return result;\n}\n","/**\n * Section Component\n * Standard component for rendering document sections with child components\n */\n\nimport { Paragraph, Table, BookmarkStart, BookmarkEnd } from 'docx';\nimport {\n ComponentDefinition,\n RenderContext,\n isSectionComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { renderComponent } from '../core/render';\nimport { globalSectionBookmarkRegistry } from '../core/sectionBookmarks';\n\n/**\n * Render section component with bookmark support for scoped TOCs\n */\nexport async function renderSectionComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!isSectionComponent(component)) return [];\n\n const elements: (Paragraph | Table)[] = [];\n\n // Resolve this section's bookmark from the single producer, keyed by\n // component identity so re-resolving the same node never allocates twice.\n const { id: sectionBookmarkId, linkId: bookmarkLinkId } =\n globalSectionBookmarkRegistry.forSectionComponent(component);\n\n // Add bookmark in a zero-spacing paragraph at section start\n // This prevents visual gaps while maintaining bookmark functionality\n elements.push(\n new Paragraph({\n children: [new BookmarkStart(sectionBookmarkId, bookmarkLinkId)],\n spacing: {\n before: 0,\n after: 0,\n line: 0,\n },\n })\n );\n\n // Update context with section bookmark ID for child components (especially TOCs)\n const sectionContext: RenderContext = {\n ...context,\n section: {\n ...context.section,\n sectionBookmarkId,\n },\n };\n\n // Render child components with updated context\n if (component.children) {\n for (const child of component.children) {\n const childElements = await renderComponent(\n child,\n theme,\n themeName,\n sectionContext\n );\n elements.push(...childElements);\n }\n }\n\n // Add bookmark end after section content\n // Use zero spacing to prevent visual gap\n elements.push(\n new Paragraph({\n children: [new BookmarkEnd(bookmarkLinkId)],\n spacing: {\n before: 0,\n after: 0,\n line: 0,\n },\n })\n );\n\n return elements;\n}\n","/**\n * Section bookmark ids — the single producer.\n *\n * `context.section.sectionBookmarkId` is what a section-scoped TOC resolves its\n * `\\b` switch against. It used to have two independent producers writing the\n * same field from two different traversal orders: a loop-carried ordinal fold\n * over `layout.sections[]` in `core/render.ts`, and a DFS counter kept on\n * `context.custom.sectionBookmarks` in `components/section.ts`, whose value\n * shadowed the first for everything below a nested section. Consumers read\n * whichever won.\n *\n * Both call sites now allocate here. Ids stay in two disjoint namespaces\n * (`_Section_*` for layout sections, `_NestedSection_*` for section components\n * rendered inside one) with disjoint numeric link-id ranges, but there is one\n * place that decides both, and one map that remembers what a given section\n * resolved to.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\n\n/** A resolved OOXML bookmark: its name plus the numeric id start/end share. */\nexport interface SectionBookmark {\n /** `w:bookmarkStart/@w:name`, and the TOC `\\b` switch argument. */\n id: string;\n /** `w:bookmarkStart/@w:id` / `w:bookmarkEnd/@w:id`. */\n linkId: number;\n}\n\n/**\n * Nested-section link ids start well above the layout ordinals so the two\n * namespaces cannot collide inside one document.\n */\nconst NESTED_LINK_ID_BASE = 1_000_000;\n\ninterface SectionBookmarkState {\n /** Next ordinal for a section component (DFS order). */\n nextNested: number;\n /** Resolved bookmark per section component, keyed by component identity. */\n resolved: WeakMap<object, SectionBookmark>;\n}\n\nfunction createState(): SectionBookmarkState {\n return { nextNested: 1, resolved: new WeakMap() };\n}\n\n/**\n * Per-render allocation state. Async-local so concurrent document renders each\n * get their own counters, matching the bookmark/revision/numbering registries.\n */\nclass SectionBookmarkRegistry {\n private fallback: SectionBookmarkState = createState();\n private readonly scopes = new AsyncLocalStorage<SectionBookmarkState>();\n\n private get state(): SectionBookmarkState {\n return this.scopes.getStore() ?? this.fallback;\n }\n\n /** Run work with an isolated registry that follows its async call chain. */\n runScoped<T>(callback: () => T): T {\n return this.scopes.run(createState(), callback);\n }\n\n /**\n * The bookmark for a layout section, derived from its ordinal.\n *\n * Every layout chunk of one user-defined section shares an ordinal (see\n * `computeSectionOrdinals`), so they all resolve to the same bookmark — which\n * is the point: the start lands in the first chunk and the end in the last.\n */\n forLayoutSection(ordinal: number): SectionBookmark {\n return { id: `_Section_${ordinal}`, linkId: ordinal };\n }\n\n /**\n * The bookmark for a `section` component, allocated on first sight and\n * remembered so re-resolving the same component never allocates twice.\n */\n forSectionComponent(component: object): SectionBookmark {\n const state = this.state;\n const existing = state.resolved.get(component);\n if (existing) return existing;\n\n const ordinal = state.nextNested++;\n const bookmark: SectionBookmark = {\n id: `_NestedSection_${ordinal}`,\n linkId: NESTED_LINK_ID_BASE + ordinal,\n };\n state.resolved.set(component, bookmark);\n return bookmark;\n }\n\n /** Test-only: reset the unscoped fallback counters. */\n clear(): void {\n if (!this.scopes.getStore()) {\n this.fallback = createState();\n }\n }\n}\n\nexport const globalSectionBookmarkRegistry = new SectionBookmarkRegistry();\n","/**\n * Columns Component\n * Standard component for rendering content in columns layout\n */\n\nimport {\n Paragraph,\n Table,\n TableRow,\n TableCell,\n WidthType,\n BorderStyle,\n VerticalAlign,\n TableLayoutType,\n} from 'docx';\nimport {\n ComponentDefinition,\n RenderContext,\n isColumnsComponent,\n isTextBoxComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { renderComponent } from '../core/render';\nimport {\n getAvailableWidthTwips,\n relativeLengthToTwips,\n} from '../utils/widthUtils';\nimport { NONE_BORDERS } from '../styles/utils/borderUtils';\n\n/**\n * Render columns component\n */\nexport async function renderColumnsComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!isColumnsComponent(component)) return [];\n\n // Check if parent is a text-box component\n if (context.parent && isTextBoxComponent(context.parent)) {\n // Render as table-based columns when inside a text-box\n return await renderColumnsAsTable(component, theme, themeName, context);\n }\n\n // Standard section-based rendering (existing behavior)\n // Props are pre-resolved by resolveComponentTree\n const elements: (Paragraph | Table)[] = [];\n\n if (component.children) {\n for (const child of component.children) {\n const childElements = await renderComponent(\n child,\n theme,\n themeName,\n context\n );\n elements.push(...childElements);\n }\n }\n\n return elements;\n}\n\n/**\n * Render columns as a multi-column table (for use inside text-boxes)\n */\nasync function renderColumnsAsTable(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context: RenderContext\n): Promise<Table[]> {\n const cfg = (component as any).props || {};\n const columns = cfg.columns || [];\n\n // Normalize columns configuration\n let columnConfigs: Array<{ width?: number | string; gap?: number | string }> =\n [];\n if (typeof columns === 'number') {\n // Equal-width columns\n columnConfigs = Array(columns).fill({ width: 'auto' });\n } else if (Array.isArray(columns)) {\n columnConfigs = columns;\n } else {\n // Invalid config, return empty\n return [];\n }\n\n const columnCount = columnConfigs.length;\n if (columnCount === 0) return [];\n\n // Calculate column widths\n const availableWidthTwips = getAvailableWidthTwips(theme, themeName);\n const columnWidths: number[] = [];\n const columnGaps: number[] = [];\n let totalDefinedWidth = 0;\n let totalGaps = 0;\n const autoWidthIndexes: number[] = [];\n\n for (let i = 0; i < columnCount; i++) {\n const col = columnConfigs[i];\n\n // Calculate width\n if (col.width === undefined || col.width === 'auto') {\n autoWidthIndexes.push(i);\n columnWidths.push(0); // Placeholder\n } else {\n const widthTwips = relativeLengthToTwips(col.width, availableWidthTwips);\n columnWidths.push(widthTwips);\n totalDefinedWidth += widthTwips;\n }\n\n // Calculate gap (space after this column)\n if (i < columnCount - 1) {\n const gapTwips =\n col.gap !== undefined\n ? relativeLengthToTwips(col.gap, availableWidthTwips)\n : cfg.gap !== undefined\n ? relativeLengthToTwips(cfg.gap, availableWidthTwips)\n : 720; // Default: 0.5 inch\n columnGaps.push(gapTwips);\n totalGaps += gapTwips;\n } else {\n columnGaps.push(0); // No gap after last column\n }\n }\n\n // Distribute remaining width among auto-width columns\n const remainingWidth = Math.max(\n 0,\n availableWidthTwips - totalDefinedWidth - totalGaps\n );\n if (autoWidthIndexes.length > 0) {\n const autoColumnWidth = Math.floor(\n remainingWidth / autoWidthIndexes.length\n );\n for (const idx of autoWidthIndexes) {\n columnWidths[idx] = autoColumnWidth;\n }\n }\n\n // Distribute child components across columns\n const childComponents = (component as any).children || [];\n const columnContents: ComponentDefinition[][] = Array(columnCount)\n .fill(null)\n .map(() => []);\n\n // Simple distribution: round-robin\n for (let i = 0; i < childComponents.length; i++) {\n const colIndex = i % columnCount;\n columnContents[colIndex].push(childComponents[i]);\n }\n\n // Render each column's content\n const cells: TableCell[] = [];\n for (let i = 0; i < columnCount; i++) {\n const columnElements: (Paragraph | Table)[] = [];\n\n for (const child of columnContents[i]) {\n const rendered = await renderComponent(child, theme, themeName, context);\n columnElements.push(...rendered);\n }\n\n // If column is empty, add empty paragraph\n if (columnElements.length === 0) {\n columnElements.push(new Paragraph({}));\n }\n\n cells.push(\n new TableCell({\n children: columnElements,\n width: { size: columnWidths[i], type: WidthType.DXA },\n margins: {\n top: 0,\n right: columnGaps[i] / 2,\n bottom: 0,\n left: i > 0 ? columnGaps[i - 1] / 2 : 0,\n },\n verticalAlign: VerticalAlign.TOP,\n borders: {\n top: { style: BorderStyle.NONE, size: 0, color: '000000' },\n right: { style: BorderStyle.NONE, size: 0, color: '000000' },\n bottom: { style: BorderStyle.NONE, size: 0, color: '000000' },\n left: { style: BorderStyle.NONE, size: 0, color: '000000' },\n },\n })\n );\n }\n\n const row = new TableRow({ children: cells });\n const table = new Table({\n rows: [row],\n width: { size: 100, type: WidthType.PERCENTAGE },\n layout: TableLayoutType.FIXED, // Lock column widths\n borders: NONE_BORDERS,\n });\n\n return [table];\n}\n","/**\n * Statistic Component\n * Standard component for rendering statistic displays in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isStatisticComponent } from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createStatistic } from '../core/content';\n\n/**\n * Render statistic component\n */\nexport function renderStatisticComponent(\n component: ComponentDefinition,\n _theme: ThemeConfig\n): Paragraph[] {\n if (!isStatisticComponent(component)) return [];\n\n // Props are pre-resolved by resolveComponentTree\n const resolvedConfig = component.props;\n\n return createStatistic(\n {\n number: resolvedConfig.number,\n description: resolvedConfig.description,\n alignment: resolvedConfig.alignment,\n },\n {\n spacing: resolvedConfig.spacing as\n | { before?: number; after?: number }\n | undefined,\n }\n );\n}\n","/**\n * Table of Contents Component\n * Renders TOC using Word's native TableOfContents field with bookmark scoping support\n */\n\nimport {\n Paragraph,\n TableOfContents,\n AlignmentType,\n TextRun,\n StyleLevel,\n} from 'docx';\nimport type { ITableOfContentsOptions } from 'docx';\n\n/**\n * docx declares `ToCEntry` but does not export it, so mirror the shape it\n * accepts for `cachedEntries`. `page` and `href` are optional and deliberately\n * unused — see `selectCachedEntries`.\n */\ntype ToCEntry = {\n readonly title: string;\n readonly level: number;\n readonly page?: number;\n readonly href?: string;\n};\nimport type { TocProps } from '@json-to-office/shared-docx';\nimport type { ThemeConfig } from '../../styles';\nimport type { RenderContext } from '../../types';\nimport type { TocHeadingEntry } from '../../core/collectTocHeadings';\nimport { headingNumberLabel } from '../../utils/numberingConfig';\n\nexport interface TocComponentDefinition {\n name: 'toc';\n id?: string;\n props: TocProps;\n}\n\n/**\n * The Word display name a theme style key registers under: camelCase and\n * kebab/snake separators become spaces (`calloutTitle` -> `callout Title`).\n * Mirrors the naming in `themeToDocxAdapter`.\n */\nfunction toStyleDisplayName(styleId: string): string {\n return styleId\n .replace(/([A-Z])/g, ' $1')\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/**\n * Select the collected entries this TOC would show, in document order.\n *\n * Mirrors what Word's own refresh does with the field switches:\n * - `\\o` outline range: heading entries inside [depthStart, depthEnd].\n * - `\\t` style mappings: paragraphs whose `themeStyle` this TOC maps, at the\n * mapped level. Word includes these regardless of the outline range, so they\n * are not depth-filtered here either — otherwise a reader pressing F9 would\n * see a different TOC than the cached one, the exact disagreement caching is\n * meant to avoid.\n * - `\\b` bookmark: when the TOC is section-scoped, only entries from that\n * section.\n */\nfunction selectCachedEntries(\n collected: readonly TocHeadingEntry[] | undefined,\n options: {\n depthStart: number;\n depthEnd: number;\n sectionBookmarkId?: string;\n styleLevels: ReadonlyMap<string, number>;\n }\n): ToCEntry[] {\n if (!collected || collected.length === 0) return [];\n\n const { depthStart, depthEnd, sectionBookmarkId, styleLevels } = options;\n const entries: ToCEntry[] = [];\n\n for (const entry of collected) {\n if (sectionBookmarkId && entry.sectionBookmarkId !== sectionBookmarkId) {\n continue;\n }\n\n if (entry.styleId !== undefined) {\n // The entry carries the theme key; the mapping may have named the\n // display name instead.\n const level =\n styleLevels.get(entry.styleId) ??\n styleLevels.get(toStyleDisplayName(entry.styleId));\n if (level === undefined) continue;\n entries.push({ title: entry.title, level });\n continue;\n }\n\n if (entry.level < depthStart || entry.level > depthEnd) continue;\n // `page` is deliberately omitted: nothing in generation paginates, and\n // Word fills in real numbers the moment it refreshes the field.\n // A numbered heading shows its number in Word's own refresh, so the cached\n // copy has to carry it too — in the same form, trailing period included.\n entries.push({\n title: entry.number\n ? `${headingNumberLabel(entry.number)} ${entry.title}`\n : entry.title,\n level: entry.level,\n });\n }\n\n return entries;\n}\n\n/**\n * Parse and validate a depth range configuration\n * @param rawDepth - Raw depth configuration from user input\n * @param fieldName - Name of the field (for error messages)\n * @param defaultFrom - Default 'from' value if not specified\n * @param defaultTo - Default 'to' value if not specified\n * @returns Validated depth range with from and to values\n */\nfunction parseDepthRange(\n rawDepth: any,\n fieldName: string,\n defaultFrom = 1,\n defaultTo = 3\n): { from: number; to: number } {\n if (typeof rawDepth !== 'object' || rawDepth === null) {\n throw new Error(\n `${fieldName} must be a range object with optional \"from\" and/or \"to\" fields, received: ${JSON.stringify(rawDepth)}`\n );\n }\n\n // Apply defaults for missing values\n const from = rawDepth.from ?? defaultFrom;\n const to = rawDepth.to ?? defaultTo;\n\n // Validate range\n if (from < 1 || from > 6 || to < 1 || to > 6) {\n throw new Error(\n `${fieldName} range values must be between 1 and 6, received: from=${from}, to=${to}`\n );\n }\n if (from > to) {\n throw new Error(\n `${fieldName} \"from\" must be less than or equal to \"to\", received: from=${from}, to=${to}`\n );\n }\n\n return { from, to };\n}\n\n/**\n * Render TOC component using Word's native TableOfContents field with bookmark scoping\n *\n * This creates a dynamic TOC that:\n * - Auto-populates with headings from configured scope\n * - Updates automatically when document structure changes\n * - Includes clickable hyperlinks to content\n * - Shows page numbers (if enabled)\n * - Respects configured depth limits\n *\n * Scope behavior:\n * - scope: 'document' → Scans entire document (default when TOC is at report level)\n * - scope: 'section' → Scans only parent section content (uses bookmark)\n * - scope: 'auto' → Automatically detects: section if inside section, otherwise document\n */\nexport function renderTocComponent(\n component: TocComponentDefinition,\n theme: ThemeConfig,\n context?: RenderContext\n): (Paragraph | TableOfContents)[] {\n const componentProps = component.props;\n\n // Parse depth parameter - supports range with optional from/to\n const rawDepth = componentProps.depth ?? { to: 3 };\n const depthRange = parseDepthRange(rawDepth, 'TOC depth', 1, 3);\n const depthStart = depthRange.from;\n const depthEnd = depthRange.to;\n\n // Parse pageNumbersDepth parameter - controls which levels show page numbers\n let pageNumbersStart: number | undefined;\n let pageNumbersEnd: number | undefined;\n\n if (componentProps.pageNumbersDepth !== undefined) {\n const pageNumbersRange = parseDepthRange(\n componentProps.pageNumbersDepth,\n 'TOC pageNumbersDepth',\n 1,\n 3\n );\n pageNumbersStart = pageNumbersRange.from;\n pageNumbersEnd = pageNumbersRange.to;\n }\n\n // numberingStyle has no representation in Word's TOC field: the field carries\n // no numbering switch, so entries always inherit the numbering of the heading\n // styles they point at. The prop stays in the schema (documents already set it\n // and props are additionalProperties:false), but the no-op is announced rather\n // than swallowed.\n if (componentProps.numberingStyle !== undefined) {\n console.warn(\n `TOC numberingStyle \"${componentProps.numberingStyle}\" is ignored: Word's ` +\n 'table-of-contents field has no numbering switch. TOC entries inherit ' +\n 'numbering from the heading styles they reference.'\n );\n }\n\n const includePageNumbers = componentProps.includePageNumbers !== false; // default true\n const scope = componentProps.scope ?? 'auto';\n\n // Determine effective scope based on configuration and context\n const effectiveScope =\n scope === 'auto'\n ? context?.section?.sectionBookmarkId\n ? 'section'\n : 'document'\n : scope;\n\n // Get section bookmark ID if scoped to section\n const sectionBookmarkId =\n effectiveScope === 'section'\n ? context?.section?.sectionBookmarkId\n : undefined;\n\n // Validate bookmark if section-scoped\n if (effectiveScope === 'section' && !sectionBookmarkId) {\n // Log warning but gracefully fall back to document scope\n console.warn(\n 'TOC configured for section scope but no section bookmark found. Falling back to document scope.'\n );\n }\n\n const paragraphs: (Paragraph | TableOfContents)[] = [];\n\n // Add TOC title only if explicitly provided\n if (componentProps.title) {\n paragraphs.push(\n new Paragraph({\n children: [\n new TextRun({\n text: componentProps.title,\n bold: true,\n size: 28, // 14pt (size is in half-points)\n }),\n ],\n spacing: {\n before: theme.componentDefaults?.heading?.spacing?.before ?? 240,\n // Increase spacing between the title and the TOC list\n // 180 ~= 9pt, provides clearer separation by default\n after: 180,\n },\n alignment: AlignmentType.LEFT,\n })\n );\n }\n\n // Build style mappings for TOC levels based on depth\n // StyleLevel requires styleName (string) and level (number)\n const stylesWithLevels: StyleLevel[] = [];\n\n // Sections no longer synthesize a title heading (a visible title is an\n // explicit heading child), so section-scoped TOCs include every heading\n // level their bookmark covers.\n\n // Do NOT map built-in heading styles via \\t switch.\n // Use headingStyleRange (\\o) exclusively for Heading 1..6 to avoid any interference\n // between TOC styles and document heading styles.\n\n // Add custom style mappings if provided\n // These allow arbitrary theme styles to appear in the TOC at specified levels\n //\n // Style -> TOC level, for matching the collected entries below. A mapping can\n // name a style either way — by the theme key an author writes in\n // `themeStyle`, or by the Word display name the \\t switch actually needs —\n // and a collected entry always carries the theme key. Indexing both forms,\n // and looking up both forms, keeps the cached entries in step with what Word\n // collects on refresh.\n const styleLevels = new Map<string, number>();\n\n if (componentProps.styles && componentProps.styles.length > 0) {\n for (const styleMapping of componentProps.styles) {\n // The TOC \\t (stylesWithLevels) switch expects Word style DISPLAY NAMES, not IDs.\n // Our theme registers custom styles with:\n // - id: original key (e.g., \"MySpectacularStyle\")\n // - name: Title Case with spaces (e.g., \"My Spectacular Style\")\n // Convert known custom style IDs to their display names to ensure Word matches them.\n const styleId = styleMapping.styleId;\n const isCustomStyle =\n !!theme.styles &&\n Object.prototype.hasOwnProperty.call(theme.styles, styleId);\n const styleDisplayName = isCustomStyle\n ? toStyleDisplayName(styleId)\n : styleId; // If it's not a custom style key, assume it's already a display name\n\n styleLevels.set(styleId, styleMapping.level);\n styleLevels.set(styleDisplayName, styleMapping.level);\n\n stylesWithLevels.push(\n new StyleLevel(styleDisplayName, styleMapping.level)\n );\n }\n }\n\n // Create Word TOC field with optional bookmark scoping\n // The TableOfContents class generates a field code that Word will populate\n // Format (document scope): { TOC \\o \"1-N\" \\h \\z \\u }\n // Format (section scope): { TOC \\b BookmarkName \\o \"1-N\" \\h \\z \\u }\n // - \\b BookmarkName: Limit TOC to entries within specified bookmark\n // - \\o \"1-N\": Include outline levels 1 through N\n // - \\h: Make TOC entries hyperlinks\n // - \\z: Hide page numbers in web layout\n // - \\u: Use outline levels instead of TC fields\n\n // Calculate heading range for \\o switch from the parsed depth config\n const effectiveDepthStart = depthStart;\n const effectiveDepthEnd = depthEnd;\n\n // Entries collected before rendering. Word repopulates the field on open,\n // but headless LibreOffice does not — without cached content the PDF export\n // shows only the TOC title.\n const cachedEntries = selectCachedEntries(context?.tocHeadings, {\n depthStart,\n depthEnd,\n sectionBookmarkId,\n styleLevels,\n });\n\n // Build TOC options\n const tocOptions: ITableOfContentsOptions = {\n hyperlink: true, // Enable clickable hyperlinks (\\h switch)\n headingStyleRange: `${effectiveDepthStart}-${effectiveDepthEnd}`, // Outline level range (\\o switch)\n stylesWithLevels, // Style-to-TOC-level mappings (\\t switch)\n // Add bookmark scope if within a section (\\b switch)\n entriesFromBookmark: sectionBookmarkId,\n // Handle page number visibility\n // If pageNumbersDepth is specified, use it to control which levels show page numbers\n // Otherwise, respect includePageNumbers boolean (default true)\n ...(() => {\n if (pageNumbersStart !== undefined && pageNumbersEnd !== undefined) {\n // pageNumbersDepth specified: hide page numbers outside the specified range\n // Word's \\n switch omits page numbers for specified levels\n // We need to invert the logic: specify levels to OMIT, not levels to SHOW\n const levelsToOmit: string[] = [];\n\n // Omit levels before pageNumbersStart\n if (pageNumbersStart > effectiveDepthStart) {\n levelsToOmit.push(`${effectiveDepthStart}-${pageNumbersStart - 1}`);\n }\n\n // Omit levels after pageNumbersEnd\n if (pageNumbersEnd < effectiveDepthEnd) {\n levelsToOmit.push(`${pageNumbersEnd + 1}-${effectiveDepthEnd}`);\n }\n\n // Only add the option if there are levels to omit\n return levelsToOmit.length > 0\n ? { pageNumbersEntryLevelsRange: levelsToOmit.join(',') }\n : {};\n } else if (!includePageNumbers) {\n // includePageNumbers is false: omit page numbers for all levels\n return {\n pageNumbersEntryLevelsRange: `${effectiveDepthStart}-${effectiveDepthEnd}`,\n };\n } else {\n // includePageNumbers is true and no pageNumbersDepth: show page numbers for all levels\n return {};\n }\n })(),\n // Add separator between entry text and page number\n // Boolean: true = \"\\t\" (tab, default), false = \" \" (space)\n ...(componentProps.numberSeparator !== undefined\n ? {\n entryAndPageNumberSeparator: componentProps.numberSeparator\n ? '\\t'\n : ' ',\n }\n : { entryAndPageNumberSeparator: '\\t' }), // default to tab\n };\n\n // Insert TOC as a top-level block (not wrapped in a Paragraph).\n // Wrapping TableOfContents inside a Paragraph produces an empty SDT above\n // the actual entries in Word. Adding directly avoids that artifact.\n paragraphs.push(\n new TableOfContents(componentProps.title ?? 'Table of Contents', {\n ...tocOptions,\n ...(cachedEntries.length > 0 && { cachedEntries }),\n })\n );\n\n // Do not append an extra empty paragraph after TOC to avoid\n // unwanted blank lines/newlines at the end of the TOC block.\n\n // Note: Word will automatically handle:\n // - Page number display (based on document view mode)\n // - Numbering style (inherited from heading styles)\n // - Indentation (based on heading levels)\n // - Updates (right-click TOC → Update Field in Word)\n\n return paragraphs;\n}\n","/**\n * Highcharts Component\n * Standard component for generating charts using Highcharts Export Server\n */\n\nimport { Paragraph, Table } from 'docx';\nimport {\n ComponentDefinition,\n RenderContext,\n isHighchartsComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createImage } from '../core/content';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\n// Import only the types we actually use from shared package\nimport type { HighchartsProps } from '@json-to-office/shared-docx';\nimport type { HighchartsServiceConfig } from '@json-to-office/shared';\nimport { DEFAULT_CHART_THEME_COLORS } from '@json-to-office/shared';\n\n// Re-export HighchartsProps for backward compatibility\nexport type { HighchartsProps } from '@json-to-office/shared-docx';\n\n/**\n * Chart generation result\n */\nexport interface ChartGenerationResult {\n base64DataUri: string;\n width: number;\n height: number;\n}\n\nconst DEFAULT_EXPORT_SERVER_URL = 'http://localhost:7801';\n\n/**\n * Generate chart using Highcharts Export Server\n */\nasync function generateChart(\n config: HighchartsProps,\n servicesConfig?: HighchartsServiceConfig\n): Promise<ChartGenerationResult> {\n // Only run in Node.js environments\n if (!isNodeEnvironment()) {\n throw new Error(\n 'Highcharts export server requires a Node.js environment. ' +\n 'Chart generation is not available in browser environments.'\n );\n }\n\n const serverUrl = resolveServiceUrl(\n config.serverUrl,\n servicesConfig?.serverUrl,\n DEFAULT_EXPORT_SERVER_URL\n );\n\n const requestBody: Record<string, unknown> = {\n infile: config.options,\n type: 'png',\n b64: true,\n scale: config.scale,\n // Forward resources verbatim only when present so the payload stays\n // byte-identical to before for callers that omit it.\n ...(config.resources ? { resources: config.resources } : {}),\n };\n\n const response = await postJsonToService({\n url: serverUrl,\n path: '/export',\n body: requestBody,\n headers: servicesConfig?.headers,\n serviceLabel: 'Highcharts export server',\n onUnreachable: (url, cause) =>\n `Highcharts Export Server is not running at ${url}. ` +\n 'Start it with: npx highcharts-export-server --enableServer true\\n' +\n `Cause: ${cause}`,\n });\n\n const base64Data = await response.text();\n const base64DataUri = `data:image/png;base64,${base64Data}`;\n const width = config.options.chart.width;\n const height = config.options.chart.height;\n\n return {\n base64DataUri,\n width,\n height,\n };\n}\n\n/**\n * Turn one theme color value into a `#RRGGBB` string, or undefined when it\n * cannot be resolved. The theme schema lets a color be another token's name\n * (`\"accent4\": \"primary\"`), so a bare `#` prefix would post \"#primary\" to the\n * export server; `resolveColor` walks the reference chain and throws on\n * anything unresolvable, which we treat as an unset slot.\n */\nfunction toChartColor(value: string, theme: ThemeConfig): string | undefined {\n // Literal hex passes through untouched — resolveColor would upper-case it,\n // and it rejects the bare (no '#') form the schema still accepts.\n if (/^#?[0-9A-Fa-f]{6}$/.test(value)) {\n return value.startsWith('#') ? value : `#${value}`;\n }\n try {\n return `#${resolveColor(value, theme)}`;\n } catch {\n return undefined;\n }\n}\n\n/**\n * When the Highcharts config sets no top-level `colors`, series render in the\n * Highcharts default palette (blue-first) and ignore the document theme. Inject\n * the theme's chart palette — the same token list PPTX charts resolve — as\n * series colors so charts follow the theme by default. accent4-6 are optional\n * in the theme schema; slots the theme leaves unset are skipped, in both\n * formats, so the palette never carries gaps or repeats and Highcharts wraps\n * the shorter list (see DEFAULT_CHART_THEME_COLORS). Explicit `colors` always\n * wins.\n */\nfunction withThemeColors(\n config: HighchartsProps,\n theme: ThemeConfig\n): HighchartsProps {\n const options = config.options as Record<string, unknown> | undefined;\n if (!options || options.colors || !theme?.colors) return config;\n const themeColors = theme.colors as Record<string, string | undefined>;\n const palette = DEFAULT_CHART_THEME_COLORS.map((token) => {\n const value = themeColors[token];\n return typeof value === 'string' && value.length > 0\n ? toChartColor(value, theme)\n : undefined;\n }).filter((c): c is string => c !== undefined);\n if (palette.length === 0) return config;\n return {\n ...config,\n options: { ...config.options, colors: palette },\n };\n}\n\n/**\n * Render highcharts component\n */\nexport async function renderHighchartsComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n context?: RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!isHighchartsComponent(component)) return [];\n\n const config = withThemeColors(component.props as HighchartsProps, theme);\n\n // Generate the chart\n const chartResult = await generateChart(\n config,\n context?.services?.highcharts\n );\n\n // If either config.width or config.height is provided, use config dimensions only\n // Otherwise fall back to chart dimensions\n const hasConfigDimensions =\n config.width !== undefined || config.height !== undefined;\n const renderWidth = hasConfigDimensions ? config.width : chartResult.width;\n const renderHeight = hasConfigDimensions ? config.height : chartResult.height;\n\n // Add chart image using the image component with base64 data URI\n const imageParagraphs = await createImage(\n chartResult.base64DataUri,\n theme,\n themeName,\n {\n width: renderWidth,\n height: renderHeight,\n alignment: 'center',\n }\n );\n\n return imageParagraphs;\n}\n","/**\n * Environment detection utilities\n */\n\n/**\n * Check if the current environment is Node.js\n * This is used to conditionally load Node.js-only modules\n */\nexport function isNodeEnvironment(): boolean {\n // Check for Node.js-specific globals\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null &&\n typeof process.versions.node === 'string'\n );\n}\n\n/**\n * Check if Node.js built-in modules are available\n * More specific check for modules that require Node.js built-ins\n */\nexport function hasNodeBuiltins(): boolean {\n try {\n // Check if we can access Node.js built-in modules\n // This will fail in browser environments\n return (\n typeof require !== 'undefined' ||\n (typeof process !== 'undefined' &&\n typeof process.versions === 'object' &&\n typeof process.versions.node === 'string')\n );\n } catch {\n return false;\n }\n}\n","/**\n * Shared client for \"service-rendered image\" components (highcharts, visual).\n *\n * Both offload rendering to an injected HTTP service: resolve a base URL, POST a\n * JSON body with optional dynamic headers, and normalize transport errors — now\n * with a request timeout so a wedged service can't hang the render forever.\n * Callers decode the response body themselves (highcharts returns base64 text,\n * visual returns JSON), so this returns the raw Response on success.\n */\n\nexport type ServiceHeaders =\n | Record<string, string>\n | ((\n body: unknown\n ) => Record<string, string> | Promise<Record<string, string>>);\n\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n/**\n * Resolve a service base URL: per-call override → services config → default.\n * Adds an `http://` scheme to a bare host and strips trailing slashes so callers\n * can append `${url}/path` without producing a `//path` that breaks routers.\n */\nexport function resolveServiceUrl(\n propsUrl: string | undefined,\n servicesUrl: string | undefined,\n defaultUrl: string\n): string {\n const raw = (propsUrl || servicesUrl || defaultUrl).trim();\n const withScheme = /^https?:\\/\\//i.test(raw) ? raw : `http://${raw}`;\n return withScheme.replace(/\\/+$/, '');\n}\n\nexport interface PostJsonOptions {\n /** Resolved base URL (use resolveServiceUrl). */\n url: string;\n /** Path appended to the base URL, e.g. '/export' or '/rasterize'. */\n path: string;\n /** Request body (JSON-serialized). */\n body: unknown;\n /** Static headers or an async resolver receiving the body. */\n headers?: ServiceHeaders;\n /** Abort timeout in ms (default 30s). */\n timeoutMs?: number;\n /** Label used in the timeout message and the non-2xx error. */\n serviceLabel: string;\n /** Message builder for a connection failure (distinct from a timeout). */\n onUnreachable: (url: string, cause: string) => string;\n}\n\n/**\n * POST a JSON body to `${url}${path}` with a timeout. Returns the Response on a\n * 2xx; throws a normalized Error on timeout, connection failure, or non-2xx.\n */\nexport async function postJsonToService(\n opts: PostJsonOptions\n): Promise<Response> {\n const resolvedHeaders =\n typeof opts.headers === 'function'\n ? await opts.headers(opts.body)\n : opts.headers;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n };\n\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(`${opts.url}${opts.path}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.body),\n signal: controller.signal,\n });\n } catch (error) {\n if ((error as Error)?.name === 'AbortError') {\n throw new Error(\n `${opts.serviceLabel} timed out after ${timeoutMs}ms at ${opts.url}.`\n );\n }\n const cause = error instanceof Error ? error.message : String(error);\n throw new Error(opts.onUnreachable(opts.url, cause));\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new Error(\n `${opts.serviceLabel} returned ${response.status}: ${response.statusText}`\n );\n }\n return response;\n}\n","/**\n * Visual Component\n *\n * Renders a free-canvas graphic authored as a single pptx slide and embeds it\n * as a rasterized PNG. The slide is rendered to an image by an injected\n * rasterization service (`services.pptx`) — exactly the way the `highcharts`\n * component offloads chart rendering to an export server — then desugars to a\n * plain `image`.\n */\n\nimport { createHash } from 'crypto';\nimport { Paragraph, Table } from 'docx';\nimport {\n ComponentDefinition,\n RenderContext,\n isVisualComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { createImage, type ImageOptions } from '../core/content';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { getBaseDir } from '../utils/generationContext';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n type PptxServiceConfig,\n type PptxRasterizeResult,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\n\nexport const DEFAULT_RASTERIZE_SERVER_URL = 'http://localhost:7802';\n/** 1 inch = 96 CSS pixels — used to size the embedded image at its physical canvas size. */\nconst PIXELS_PER_INCH = 96;\n\n/**\n * Build a single-slide pptx presentation component definition from visual props.\n * The shape mirrors a normal `.pptx.json` document so the pptx engine renders\n * it unchanged. Exported for reuse by the `flattenVisuals` transform.\n */\nexport function buildVisualPresentation(\n props: VisualProps\n): Record<string, unknown> {\n const { canvas, elements } = props;\n\n const presentationProps: Record<string, unknown> = {\n slideWidth: canvas.width,\n slideHeight: canvas.height,\n };\n if (canvas.theme) presentationProps.theme = canvas.theme;\n\n const slideProps: Record<string, unknown> = {};\n if (canvas.background) slideProps.background = canvas.background;\n\n return {\n name: 'pptx',\n props: presentationProps,\n children: [\n {\n name: 'slide',\n props: slideProps,\n children: elements ?? [],\n },\n ],\n };\n}\n\n/**\n * Default rendered width (px) for a visual: its physical canvas inches, so a\n * 6×4 canvas prints 6×4 unless `width` overrides.\n */\nexport function defaultVisualWidthPx(props: VisualProps): number {\n return Math.round(props.canvas.width * PIXELS_PER_INCH);\n}\n\n/**\n * Shared image-placement options derived from a visual's props. Used by BOTH\n * the render-time createImage call and the flatten transform so the two\n * desugaring paths can't drift (width default, alignment default, caption,\n * spacing, floating, keepNext/keepLines all live here once).\n */\nexport function visualToImageOptions(props: VisualProps): ImageOptions {\n return {\n width: props.width ?? defaultVisualWidthPx(props),\n ...(props.height !== undefined && { height: props.height }),\n alignment: props.alignment ?? 'center',\n ...(props.caption !== undefined && { caption: props.caption }),\n ...(props.spacing !== undefined && { spacing: props.spacing }),\n ...(props.floating !== undefined && { floating: props.floating }),\n ...(props.keepNext !== undefined && { keepNext: props.keepNext }),\n ...(props.keepLines !== undefined && { keepLines: props.keepLines }),\n };\n}\n\n/**\n * Map visual props to the `image` props they desugar to (used by the\n * `flattenVisuals` transform to produce a portable, service-free document).\n */\nexport function visualToImageProps(\n props: VisualProps,\n base64DataUri: string\n): Record<string, unknown> {\n return {\n base64: base64DataUri,\n ...visualToImageOptions(props),\n ...(props.alt !== undefined && { alt: props.alt }),\n };\n}\n\n/**\n * Identity of one visual rasterization: content + resolution + (for HTTP\n * services) the target server. Keys the per-document pre-rasterization map\n * (#153); the pre-pass and the render-time lookup MUST use this one function\n * so the two sides cannot drift.\n *\n * FONTS ARE DELIBERATELY NOT PART OF THIS KEY. The map is built and consumed\n * inside a single `renderDocument` call, which has exactly one font set, so\n * the pre-pass and the render-time lookup can never disagree about fonts.\n * The load-bearing font key is the RASTERIZER's on-disk cache key, which is\n * process-wide and shared across documents and users — see `fontsDigest` in\n * jto-cli's pptx-rasterizer.ts.\n */\nexport function visualRasterKey(\n presentation: unknown,\n dpi: number,\n serverUrl?: string\n): string {\n return createHash('sha256')\n .update(JSON.stringify({ p: presentation, d: dpi, u: serverUrl ?? null }))\n .digest('hex');\n}\n\n/**\n * The serverUrl that actually differentiates a visual's rasterization. An\n * in-process `render` callback takes precedence over any serverUrl —\n * per-visual or config — so overrides only matter when rasterization would\n * go over HTTP. Deliberately keyed on `render` alone (NOT `renderBatch`):\n * per-visual fallbacks always go through `rasterizeVisualSlide`, which only\n * consults `render`, and pre-pass inclusion must match what a fallback would\n * actually do or the same visual could rasterize against two different\n * services depending on cache luck.\n */\nexport function effectiveVisualServerUrl(\n props: VisualProps,\n serviceConfig: PptxServiceConfig | undefined\n): string | undefined {\n if (serviceConfig?.render) return undefined;\n return props.serverUrl;\n}\n\n/**\n * Rasterize a single-slide presentation to a PNG via the configured service.\n * An in-process `render` callback takes precedence over an HTTP `serverUrl`.\n * Exported for the pre-rasterization pass, whose per-visual fallback must\n * behave exactly like render-time rasterization.\n */\nexport async function rasterizeVisualSlide(\n presentation: Record<string, unknown>,\n dpi: number,\n propsServerUrl: string | undefined,\n serviceConfig: PptxServiceConfig | undefined,\n baseDir: string | undefined,\n /**\n * Document fonts staged for the rasterizer's LibreOffice launch. Added\n * conditionally below so a fontless document's request body stays exactly\n * what it was before fonts existed.\n */\n fonts?: readonly RasterizeFontFace[]\n): Promise<PptxRasterizeResult> {\n if (!isNodeEnvironment()) {\n throw new Error(\n 'Visual rasterization requires a Node.js environment. ' +\n 'It is not available in browser environments.'\n );\n }\n\n // In-process renderer wins (ideal for tests and single-process hosts).\n if (serviceConfig?.render) {\n return serviceConfig.render({\n presentation,\n dpi,\n baseDir,\n ...(fonts?.length ? { fonts: [...fonts] } : {}),\n });\n }\n\n const serverUrl = resolveServiceUrl(\n propsServerUrl,\n serviceConfig?.serverUrl,\n DEFAULT_RASTERIZE_SERVER_URL\n );\n\n const response = await postJsonToService({\n url: serverUrl,\n path: '/rasterize',\n body: {\n presentation,\n dpi,\n ...(baseDir !== undefined && { baseDir }),\n ...(fonts?.length ? { fonts } : {}),\n },\n headers: serviceConfig?.headers,\n serviceLabel: 'PPTX rasterization service',\n onUnreachable: (url, cause) =>\n `PPTX rasterization service is not reachable at ${url}. ` +\n 'Configure services.pptx with a `render` callback or a running `serverUrl`.\\n' +\n `Cause: ${cause}`,\n });\n\n let result: PptxRasterizeResult;\n try {\n result = (await response.json()) as PptxRasterizeResult;\n } catch {\n throw new Error(\n 'PPTX rasterization service returned a non-JSON response (expected { base64DataUri, width, height }).'\n );\n }\n if (!result?.base64DataUri) {\n throw new Error(\n 'PPTX rasterization service returned a malformed response (missing base64DataUri).'\n );\n }\n return result;\n}\n\n/**\n * Render visual component\n */\nexport async function renderVisualComponent(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName?: string,\n context?: RenderContext\n): Promise<(Paragraph | Table)[]> {\n if (!isVisualComponent(component)) return [];\n\n const props = component.props as VisualProps;\n const serviceConfig = context?.services?.pptx;\n\n const presentation = buildVisualPresentation(props);\n const dpi = clampVisualDpi(\n props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI\n );\n\n // The per-document pre-pass batch-rasterizes visuals ahead of rendering\n // (#153). A hit uses those pixels; a recorded per-visual failure surfaces\n // here, where the error is attributable to this component. Any miss falls\n // through to per-visual rasterization, so the pre-pass can never make a\n // render worse than the sequential path.\n const preRasterized = context?.visualRasterResults?.get(\n visualRasterKey(\n presentation,\n dpi,\n effectiveVisualServerUrl(props, serviceConfig)\n )\n );\n\n let result: PptxRasterizeResult;\n if (preRasterized) {\n if (!preRasterized.ok) throw new Error(preRasterized.error);\n result = preRasterized;\n } else {\n // Relative asset paths inside the visual's nested presentation must\n // resolve against the same base directory as the docx document itself —\n // the rasterizer runs in another process/cwd (#142).\n result = await rasterizeVisualSlide(\n presentation,\n dpi,\n props.serverUrl,\n serviceConfig,\n getBaseDir(),\n context?.visualFonts\n );\n }\n\n // Size and placement options are derived once in visualToImageOptions (shared\n // with the flatten transform): default width = canvas physical inches; height\n // left unset so aspect ratio is preserved from the PNG.\n return await createImage(\n result.base64DataUri,\n theme,\n themeName,\n visualToImageOptions(props)\n );\n}\n","/**\n * Text Space After Custom Component\n * A text component with hardcoded spacing after the paragraph\n *\n * This component is provided as an example of the legacy custom component system.\n * For new custom components, use the plugin system instead:\n * @see packages/core/src/plugin/example/ for modern examples\n */\n\nimport { Type, Static } from '@sinclair/typebox';\nimport { createComponent, createVersion } from '../plugin/createComponent';\nimport type { ComponentDefinition } from '@json-to-office/shared-docx';\n\n/**\n * Props schema for text-space-after component\n */\nconst TextSpaceAfterPropsSchema = Type.Object({\n text: Type.String({\n description: 'Text content to display',\n }),\n // Retained for backwards compatibility of props shape, but not applied\n spacing: Type.Optional(\n Type.Object({\n before: Type.Optional(Type.Number()),\n after: Type.Optional(Type.Number()),\n })\n ),\n});\n\nexport type TextSpaceAfterProps = Static<typeof TextSpaceAfterPropsSchema>;\n\n/**\n * Text space after component - adds hardcoded spacing after paragraphs\n */\nexport const textSpaceAfterComponent = createComponent({\n name: 'text-space-after',\n versions: {\n '1.0.0': createVersion({\n propsSchema: TextSpaceAfterPropsSchema,\n description: 'Text component with hardcoded spacing after the paragraph',\n render: async ({ props }) => {\n // Create paragraph component with hardcoded spacing after\n const result: ComponentDefinition = {\n name: 'paragraph',\n props: {\n text: props.text,\n spacing: {\n ...props.spacing,\n after: props.spacing?.after || 12,\n },\n },\n };\n\n return [result];\n },\n }),\n },\n});\n","import type { TSchema } from '@sinclair/typebox';\nimport type { ComponentDefinition } from '@json-to-office/shared-docx';\nimport type { ThemeConfig } from '../styles';\nimport {\n createVersion as sharedCreateVersion,\n createComponent as sharedCreateComponent,\n} from '@json-to-office/shared/plugin';\nimport type {\n RenderContext as SharedRenderContext,\n RenderFunction as SharedRenderFunction,\n ComponentVersion as SharedComponentVersion,\n ComponentVersionMap as SharedComponentVersionMap,\n CustomComponent as SharedCustomComponent,\n} from '@json-to-office/shared/plugin';\n\n// ---- DOCX-specific type aliases (backward compat) ----\n\n/**\n * DOCX render context with ThemeConfig baked in\n */\nexport type RenderContext<T> = SharedRenderContext<T, ThemeConfig>;\n\nexport type RenderFunction<\n TProps,\n TComponentDefinition = ComponentDefinition,\n> = SharedRenderFunction<TProps, TComponentDefinition, ThemeConfig>;\n\nexport type ComponentVersion<\n TComponentDefinition = ComponentDefinition,\n TPropsSchema extends TSchema = TSchema,\n> = SharedComponentVersion<TComponentDefinition, TPropsSchema, ThemeConfig>;\n\nexport type ComponentVersionMap<TComponentDefinition = ComponentDefinition> =\n SharedComponentVersionMap<TComponentDefinition, ThemeConfig>;\n\nexport type CustomComponent<\n TComponentDefinition = ComponentDefinition,\n TVersions extends\n ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>,\n TName extends string = string,\n> = SharedCustomComponent<TComponentDefinition, TVersions, TName>;\n\n// ---- Re-export factory functions (thin wrappers for DOCX defaults) ----\n\nexport function createVersion<\n TPropsSchema extends TSchema,\n TComponentDefinition = ComponentDefinition,\n>(\n version: ComponentVersion<TComponentDefinition, TPropsSchema>\n): ComponentVersion<TComponentDefinition, TPropsSchema> {\n return sharedCreateVersion(version);\n}\n\nexport function createComponent<\n TComponentDefinition = ComponentDefinition,\n TVersions extends\n ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>,\n TName extends string = string,\n>(\n component: CustomComponent<TComponentDefinition, TVersions, TName>\n): CustomComponent<TComponentDefinition, TVersions, TName> {\n return sharedCreateComponent(component);\n}\n","/**\n * prerasterizeVisuals — per-document visual rasterization pre-pass (#153).\n *\n * The renderer walks components strictly in order, so each `visual` used to\n * await its own rasterization round trip: one HTTP call + one LibreOffice\n * launch per visual, ~25 of each for the bundled annual-report templates.\n * This pass runs once per document before rendering: it collects every\n * enabled visual, dedupes identical ones, and rasterizes them together —\n * through an in-process batch rasterizer, a batched HTTP call, or (failing\n * both) bounded-concurrency per-visual calls.\n *\n * Results land in a map keyed by `visualRasterKey`; `renderVisualComponent`\n * consults the map first and falls back to per-visual rasterization on any\n * miss. The pre-pass is therefore purely an accelerator: over-collection\n * wastes a little work, under-collection and every failure mode degrade to\n * the sequential status quo, never to a broken render.\n */\n\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n MAX_RASTERIZE_BATCH_SLIDES,\n type PptxServiceConfig,\n type PptxRasterizeBatchResult,\n type PptxRasterizeBatchSlideResult,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport {\n buildVisualPresentation,\n effectiveVisualServerUrl,\n rasterizeVisualSlide,\n visualRasterKey,\n DEFAULT_RASTERIZE_SERVER_URL,\n} from '../components/visual';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { createLimiter } from '../utils/promiseLimiter';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\n/** Bounded concurrency for per-visual fallback rasterizations. */\nconst DEFAULT_FALLBACK_CONCURRENCY = 4;\n/** HTTP timeout for a batch call scales with its slide count. */\nconst BATCH_TIMEOUT_BASE_MS = 30000;\nconst BATCH_TIMEOUT_PER_SLIDE_MS = 10000;\n\nexport interface PrerasterizeOptions {\n /** Directory relative asset paths resolve against (#142). */\n baseDir?: string;\n /** Max concurrent per-visual fallback rasterizations (default 4). */\n concurrency?: number;\n /**\n * Font faces staged for every slide's LibreOffice render. Request-level,\n * like `baseDir` — never per-slide: the batch schema validates each slide\n * object with `additionalProperties: false`, and a uniform slide shape is\n * what lets the server share one disk-cache key with the single path.\n */\n fonts?: readonly RasterizeFontFace[];\n}\n\n/** Cumulative pre-pass counters for cache observability (#156). */\nexport interface VisualPrepassStats {\n /** Documents that entered the pre-pass with at least one visual. */\n documents: number;\n /** Enabled visuals collected across those documents. */\n collected: number;\n /** Unique rasterization units after dedupe (identical content+dpi). */\n unique: number;\n}\n\nconst prepassStats: VisualPrepassStats = {\n documents: 0,\n collected: 0,\n unique: 0,\n};\n\n/**\n * Get cumulative per-document pre-pass counters. `collected - unique` is the\n * work the dedupe saved — the `visual` cache benefit the component cache\n * stats can never show, since `visual` bypasses that cache by design.\n */\nexport function getVisualPrepassStats(): VisualPrepassStats {\n return { ...prepassStats };\n}\n\nexport function resetVisualPrepassStats(): void {\n prepassStats.documents = 0;\n prepassStats.collected = 0;\n prepassStats.unique = 0;\n}\n\n/** One unique rasterization unit collected from the document. */\ninterface VisualRasterTarget {\n key: string;\n presentation: Record<string, unknown>;\n dpi: number;\n}\n\n/**\n * Result of one batch attempt. `schemaRejected` distinguishes \"the server\n * refused this body\" (HTTP 400) from every other failure, so the caller can\n * tell a version-skew rejection from a blip instead of treating both alike.\n */\ntype BatchOutcome =\n | { applied: true }\n | { applied: false; schemaRejected: boolean };\n\n/**\n * Collect the props of every enabled `visual` component reachable from\n * `root`. The walk is generic — every array element and object value is\n * visited — so visuals nested anywhere (columns, table cells, section\n * headers/footers, plugin containers) are found without enumerating\n * container shapes. Disabled component subtrees are pruned: they never\n * render, so rasterizing them is wasted work. Over-collection is harmless\n * (an unused map entry); under-collection is harmless (render-time\n * fallback) — which is what makes the generic walk safe.\n */\nexport function collectVisualProps(root: unknown): VisualProps[] {\n const found: VisualProps[] = [];\n // Guards against cyclic inputs (the walk accepts arbitrary objects, not\n // just parsed JSON); registered before the array branch so\n // self-referential arrays are covered too.\n const seen = new WeakSet<object>();\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return;\n if (seen.has(node)) return;\n seen.add(node);\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n const obj = node as Record<string, unknown>;\n // Only component-shaped nodes carry `enabled`; a disabled subtree never\n // renders (mirrors the render-time filters).\n if (typeof obj.name === 'string' && obj.enabled === false) return;\n if (obj.name === 'visual' && obj.props && typeof obj.props === 'object') {\n found.push(obj.props as VisualProps);\n // A visual's elements are a pptx subtree; nothing docx-renderable\n // (and no further docx visuals) can nest inside it.\n return;\n }\n for (const value of Object.values(obj)) visit(value);\n };\n visit(root);\n return found;\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * COUPLING: `postJsonToService` (utils/serviceClient.ts) is the only producer\n * of the errors this inspects, and it encodes a non-2xx as\n * `\"<serviceLabel> returned <status>: <statusText>\"`. This pattern is the one\n * place that knowledge lives; if that message format changes, change it here\n * too (a transport error or timeout carries no status and matches nothing).\n */\nconst HTTP_STATUS_IN_MESSAGE = /\\breturned (\\d{3})\\b/;\n\n/**\n * Is this failure the server rejecting our request *body* (HTTP 400) rather\n * than the server being unwell? Both rasterize schemas validate with\n * `additionalProperties: false`, so a pre-fonts render server answers a\n * `fonts`-bearing body with a hard 400 — that, and only that, is evidence\n * that dropping `fonts` could help. A timeout, a connection reset or a 5xx\n * says nothing about the body: retrying without fonts cannot fix a server\n * that is down, and must never latch the fontless downgrade.\n */\nfunction isSchemaRejection(error: unknown): boolean {\n const match = HTTP_STATUS_IN_MESSAGE.exec(toErrorMessage(error));\n return match !== null && match[1] === '400';\n}\n\nfunction* chunksOf<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) yield items.slice(i, i + size);\n}\n\n/**\n * Validate a batch response and seed the map. All-or-nothing per chunk: any\n * malformed entry rejects the whole chunk (returns false) so a drifted or\n * broken server can never half-seed the map — the caller falls back to\n * per-visual calls instead.\n */\nfunction applyBatchResponse(\n chunk: VisualRasterTarget[],\n response: unknown,\n map: Map<string, PptxRasterizeBatchSlideResult>\n): boolean {\n const results = (response as PptxRasterizeBatchResult | undefined)?.results;\n if (!Array.isArray(results) || results.length !== chunk.length) return false;\n\n const entries: Array<[string, PptxRasterizeBatchSlideResult]> = [];\n for (let i = 0; i < chunk.length; i++) {\n const item = results[i] as PptxRasterizeBatchSlideResult | undefined;\n if (\n item &&\n item.ok === true &&\n typeof item.base64DataUri === 'string' &&\n item.base64DataUri.length > 0 &&\n typeof item.width === 'number' &&\n typeof item.height === 'number'\n ) {\n entries.push([\n chunk[i].key,\n {\n ok: true,\n base64DataUri: item.base64DataUri,\n width: item.width,\n height: item.height,\n },\n ]);\n } else if (item && item.ok === false && typeof item.error === 'string') {\n entries.push([chunk[i].key, { ok: false, error: item.error }]);\n } else {\n return false;\n }\n }\n for (const [key, value] of entries) map.set(key, value);\n return true;\n}\n\n/**\n * Batch-rasterize a document's visuals ahead of rendering. Returns a map of\n * `visualRasterKey` → per-visual result (pixels or a recorded error). Never\n * throws for per-visual problems; a thrown error here indicates a pre-pass\n * bug and the caller should continue without the map.\n */\nexport async function prerasterizeVisuals(\n root: unknown,\n serviceConfig: PptxServiceConfig | undefined,\n options: PrerasterizeOptions = {}\n): Promise<Map<string, PptxRasterizeBatchSlideResult>> {\n const map = new Map<string, PptxRasterizeBatchSlideResult>();\n // Injected in-process rasterizers are environment-agnostic; only the HTTP\n // strategy needs Node. In a browser without callbacks the render-time path\n // reports the environment error with full context.\n if (\n !isNodeEnvironment() &&\n !serviceConfig?.renderBatch &&\n !serviceConfig?.render\n ) {\n return map;\n }\n\n const visuals = collectVisualProps(root);\n if (visuals.length === 0) return map;\n\n // Dedupe identical visuals: one rasterization per unique (content, dpi).\n const targets = new Map<string, VisualRasterTarget>();\n for (const props of visuals) {\n // The generic walk can reach visual-shaped nodes the renderer never\n // touches; a malformed one must not cost the document its batching.\n // Skipped visuals fall back to the render-time path, which reports the\n // error only if the node actually renders.\n try {\n const serverUrl = effectiveVisualServerUrl(props, serviceConfig);\n // A per-visual HTTP serverUrl override targets a different service than\n // the batch would; leave those to the per-visual render-time path.\n if (serverUrl !== undefined) continue;\n const presentation = buildVisualPresentation(props);\n const dpi = clampVisualDpi(\n props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI\n );\n const key = visualRasterKey(presentation, dpi, serverUrl);\n if (!targets.has(key)) targets.set(key, { key, presentation, dpi });\n } catch {\n continue;\n }\n }\n if (targets.size === 0) return map;\n\n prepassStats.documents++;\n prepassStats.collected += visuals.length;\n prepassStats.unique += targets.size;\n\n const unique = [...targets.values()];\n const limit = createLimiter(\n Math.max(1, options.concurrency ?? DEFAULT_FALLBACK_CONCURRENCY)\n );\n\n // Version skew guard. Both rasterize schemas validate with\n // `additionalProperties: false`, so a pre-fonts render server answers a\n // `fonts`-bearing body with a hard 400 instead of ignoring the field. Once\n // a fontless retry has proven that the field was the problem, stop sending\n // it for the rest of the document: fontless pixels beat a failed render.\n // Only a 400 latches this (see isSchemaRejection) — a blip must not\n // silently downgrade every remaining visual to fontless rendering.\n let fontsRejected = false;\n const requestFonts = (): readonly RasterizeFontFace[] | undefined =>\n fontsRejected || !options.fonts?.length ? undefined : options.fonts;\n\n /**\n * One visual through exactly the render-time code path, with the same\n * version-skew guard the batch path has: `/rasterize` is\n * `additionalProperties: false` too, so an old server 400s a fonts-bearing\n * per-visual body and, without this retry, a failed batch would take the\n * whole document down instead of degrading to fontless visuals.\n */\n const rasterizeOne = async (\n target: VisualRasterTarget\n ): Promise<PptxRasterizeBatchSlideResult> => {\n const fonts = requestFonts();\n const call = (\n withFonts: readonly RasterizeFontFace[] | undefined\n ): Promise<{ base64DataUri: string; width: number; height: number }> =>\n rasterizeVisualSlide(\n target.presentation,\n target.dpi,\n undefined,\n serviceConfig,\n options.baseDir,\n withFonts\n );\n try {\n return { ok: true, ...(await call(fonts)) };\n } catch (error) {\n if (!fonts || !isSchemaRejection(error)) {\n return { ok: false, error: toErrorMessage(error) };\n }\n try {\n const result = await call(undefined);\n // Dropping `fonts` fixed it: the server predates the field.\n fontsRejected = true;\n return { ok: true, ...result };\n } catch {\n // The fontless retry is speculative; when it fails too the fonts were\n // not the problem, so report the original failure and do not latch.\n return { ok: false, error: toErrorMessage(error) };\n }\n }\n };\n\n /** Per-visual fallback: exactly the render-time code path, bounded. */\n const rasterizeIndividually = async (\n chunk: VisualRasterTarget[]\n ): Promise<void> => {\n await Promise.all(\n chunk.map((target) =>\n limit(async () => {\n map.set(target.key, await rasterizeOne(target));\n })\n )\n );\n };\n\n // Strategy 1: in-process batch rasterizer.\n if (serviceConfig?.renderBatch) {\n for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {\n try {\n const response = await serviceConfig.renderBatch({\n slides: chunk.map((target) => ({\n presentation: target.presentation,\n dpi: target.dpi,\n })),\n ...(options.baseDir !== undefined && { baseDir: options.baseDir }),\n ...(options.fonts?.length ? { fonts: [...options.fonts] } : {}),\n });\n if (!applyBatchResponse(chunk, response, map)) {\n throw new Error(\n 'batch rasterizer returned a malformed result (expected index-aligned results[])'\n );\n }\n } catch (error) {\n // Any per-visual route keeps the document building: `render` first,\n // else the configured HTTP server (rasterizeVisualSlide handles both).\n // Only a renderBatch-with-nothing-else config records the batch-level\n // error per visual — there is genuinely nowhere to fall back to, and\n // inventing an HTTP call to the default localhost would replace the\n // real error with a misleading \"unreachable\" one.\n if (serviceConfig.render || serviceConfig.serverUrl) {\n await rasterizeIndividually(chunk);\n } else {\n const message = toErrorMessage(error);\n for (const target of chunk) {\n map.set(target.key, { ok: false, error: message });\n }\n }\n }\n }\n return map;\n }\n\n // Strategy 2: in-process single rasterizer — no batch surface, but the\n // pre-pass still parallelizes what the sequential renderer could not.\n if (serviceConfig?.render) {\n await rasterizeIndividually(unique);\n return map;\n }\n\n // Strategy 3: HTTP. Try the additive batch endpoint; ANY failure — an\n // older server without /rasterize/batch, a transport error, a malformed\n // response — falls back to per-visual calls (the status quo protocol).\n const serverUrl = resolveServiceUrl(\n undefined,\n serviceConfig?.serverUrl,\n DEFAULT_RASTERIZE_SERVER_URL\n );\n const postBatch = async (\n chunk: VisualRasterTarget[],\n fonts: readonly RasterizeFontFace[] | undefined\n ): Promise<BatchOutcome> => {\n let response: Response;\n try {\n response = await postJsonToService({\n url: serverUrl,\n path: '/rasterize/batch',\n body: {\n slides: chunk.map((target) => ({\n presentation: target.presentation,\n dpi: target.dpi,\n })),\n ...(options.baseDir !== undefined && { baseDir: options.baseDir }),\n ...(fonts?.length ? { fonts } : {}),\n },\n headers: serviceConfig?.headers,\n timeoutMs:\n BATCH_TIMEOUT_BASE_MS + BATCH_TIMEOUT_PER_SLIDE_MS * chunk.length,\n serviceLabel: 'PPTX batch rasterization service',\n onUnreachable: (url, cause) =>\n `PPTX rasterization service is not reachable at ${url}. Cause: ${cause}`,\n });\n } catch (error) {\n // A 400 means the server rejected the body we sent; anything else\n // (timeout, reset, 5xx) is the server, not the body.\n return { applied: false, schemaRejected: isSchemaRejection(error) };\n }\n try {\n if (applyBatchResponse(chunk, await response.json(), map)) {\n return { applied: true };\n }\n } catch {\n // Non-JSON body from a 2xx — malformed, not a schema rejection.\n }\n return { applied: false, schemaRejected: false };\n };\n\n for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {\n const fonts = requestFonts();\n let outcome = await postBatch(chunk, fonts);\n if (!outcome.applied && fonts && outcome.schemaRejected) {\n // A pre-fonts render server rejects the whole body with 400 rather\n // than ignoring the unknown field, and the usual batch→per-visual\n // fallback does not help because /rasterize rejects it identically.\n // Retry once without fonts; only latch `fontsRejected` when dropping\n // them actually fixed it, so a transient failure does not cost the rest\n // of the document its font fidelity. A non-400 failure skips the retry\n // entirely: dropping fonts cannot revive a server that is down.\n const retry = await postBatch(chunk, undefined);\n if (retry.applied) {\n fontsRejected = true;\n outcome = retry;\n }\n }\n if (!outcome.applied) await rasterizeIndividually(chunk);\n }\n return map;\n}\n","/**\n * Minimal promise pool bounding concurrent async operations. Shared by the\n * visual rasterization paths (flattenVisuals, prerasterizeVisuals) to cap\n * concurrent service calls.\n */\nexport function createLimiter(\n max: number\n): <T>(fn: () => Promise<T>) => Promise<T> {\n let active = 0;\n const queue: Array<() => void> = [];\n const release = () => {\n active--;\n queue.shift()?.();\n };\n return async function limit<T>(fn: () => Promise<T>): Promise<T> {\n // Re-check after waking: a caller arriving between release() and this\n // waiter's microtask could otherwise barge past the limit.\n while (active >= max)\n await new Promise<void>((resolve) => queue.push(resolve));\n active++;\n try {\n return await fn();\n } finally {\n release();\n }\n };\n}\n","/**\n * Section ordinal fold.\n *\n * A user-defined `section` can be split into several layout chunks (a columns\n * transition starts a new one). Every chunk of one section must share a single\n * bookmark: the start lands in the first chunk, the end in the last, and a\n * section-scoped TOC in between resolves against the same name.\n *\n * The ordinal is a fold over the chunk list, not a property of a chunk, so it\n * cannot be computed from `layout.sections[i]` alone. Computing it once up\n * front keeps the render loop free of the loop-carried counter it used to\n * thread through header/footer bookkeeping.\n */\n\n/** The chunk fields the fold depends on. */\nexport interface SectionOrdinalInput {\n /** True for the first layout chunk of a user-defined section. */\n isUserSection: boolean;\n /** True for every layout chunk of a user-defined section. */\n belongsToUserSection: boolean;\n}\n\nexport interface SectionOrdinal {\n /** 1-based ordinal shared by all chunks of one section; undefined outside. */\n ordinal?: number;\n /** True on the last chunk of a section, where the bookmark end belongs. */\n closeBookmark: boolean;\n}\n\n/**\n * Resolve the bookmark ordinal and closing chunk for every layout section.\n * Pure: same input, same output, no allocation against any registry.\n */\nexport function computeSectionOrdinals(\n sections: readonly SectionOrdinalInput[]\n): SectionOrdinal[] {\n let counter = 0;\n\n return sections.map((section, index) => {\n if (!section.belongsToUserSection) {\n if (section.isUserSection) counter++;\n return { closeBookmark: false };\n }\n\n // First chunk opens a new ordinal; later chunks reuse the one in flight.\n const ordinal = section.isUserSection ? counter + 1 : counter;\n if (section.isUserSection) counter++;\n\n // The section ends when the next chunk is not part of it — either there is\n // no next chunk, it is outside any section, or it opens the next one.\n const next = sections[index + 1];\n const closeBookmark =\n !next || !next.belongsToUserSection || next.isUserSection;\n\n return { ordinal, closeBookmark };\n });\n}\n","/**\n * collectDocumentOutline — per-document pre-pass over the layout (#174, #177,\n * #182). One walk, three outputs: TOC entries, heading numbers, and the\n * cross-reference targets `[@id]` resolves against.\n *\n * `updateFields: true` asks Word to repopulate every TOC field on open, and\n * Word obliges. Headless LibreOffice does not, so a TOC field with no cached\n * content exports to PDF as the bare word \"Contents\" — and the rasterizer path\n * goes through soffice. Collecting the entries up front lets the renderer pass\n * them to docx as `cachedEntries`, which writes real paragraphs between the\n * field's `separate` and `end` characters.\n *\n * Modelled on `prerasterizeVisuals`: a pure collection pass over the layout,\n * seeded into the render context, consulted by the component that needs it.\n * Over-collection shows a stale entry until the reader refreshes the field;\n * under-collection degrades to today's empty TOC. Neither breaks a render.\n *\n * What the walk must and must not reach:\n * - **Headers and footers are excluded by construction.** They are fields on\n * `SectionLayout`, not components in `components[]`, and `renderSection`\n * handles only paragraph/image/table there — a heading in a header renders as\n * nothing and must never appear in the TOC.\n * - **`text-box` is reachable and does hold headings.** Its children render\n * through `renderComponent` as real `Heading1..6` paragraphs, which Word's\n * `\\o` switch collects.\n * - **`columns` cannot appear here** — `applyLayout` hoists its children before\n * this runs. The descent is kept anyway for the text-box-nested case and so a\n * future layout change cannot silently drop entries.\n * - **Table cells cannot carry headings** (`processCellContent` handles only\n * paragraph and image), so tables are leaves.\n *\n * Two kinds of entry are collected, because Word populates a TOC from two\n * sources: heading components (the `\\o` outline range) and paragraphs whose\n * `themeStyle` a TOC maps via `props.styles` (the `\\t` switch). Collecting only\n * the first would make the cached entries disagree with Word's own refresh —\n * exactly the failure `cachedEntries` exists to prevent.\n *\n * The walk also owns the two counters render cannot keep itself: the heading\n * numbering sequence (a cross-reference needs the number of a heading that may\n * come later in the document) and each list's item counters.\n */\n\nimport { getStandardComponent } from '@json-to-office/shared-docx';\nimport type { ComponentDefinition } from '../types';\nimport type { SectionLayout } from './layout';\nimport { computeSectionOrdinals } from './sectionOrdinals';\nimport { globalSectionBookmarkRegistry } from './sectionBookmarks';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport {\n slugifyBookmarkText,\n dedupeBookmarkId,\n} from '../utils/bookmarkRegistry';\nimport type { NumberedItemInfo } from '../utils/numberedItemsRegistry';\nimport { resolveListLevels } from '../utils/listLevels';\nimport type { ListLevelConfig } from '../utils/numberingConfig';\nimport { formatNumberForLevel } from '../utils/numberFormatting';\n\nexport interface TocHeadingEntry {\n /** Rendered text, with markdown decorators stripped as `createHeading` does. */\n title: string;\n /** Outline level (heading) or the level its style maps to. */\n level: number;\n /**\n * `themeStyle` key for a style-mapped paragraph; undefined for a heading.\n * A TOC includes these only when its own `props.styles` maps the key.\n */\n styleId?: string;\n /** Bookmark of the layout section this entry sits in, when inside one. */\n sectionBookmarkId?: string;\n /** Multilevel number (\"2.1\") when heading numbering applies to this entry. */\n number?: string;\n}\n\nexport interface DocumentOutline {\n entries: TocHeadingEntry[];\n /** Cross-reference targets, keyed by the bookmark id render will emit. */\n numberedItems: Map<string, NumberedItemInfo>;\n}\n\n/** Word supports six heading levels; deeper input collapses onto Heading1. */\nconst MAX_HEADING_LEVEL = 6;\n/** Word supports nine list levels. */\nconst MAX_LIST_LEVEL = 9;\n\n/**\n * Strip the inline decorators `createHeading` consumes, so a cached entry shows\n * \"Results\" rather than \"**Results**\".\n */\nexport function normalizeEntryTitle(text: string): string {\n return normalizeUnicodeText(text)\n .replace(/(\\*\\*\\*|___)([\\s\\S]*?)\\1/g, '$2')\n .replace(/(\\*\\*|__)([\\s\\S]*?)\\1/g, '$2')\n .replace(/(\\*|_)([\\s\\S]*?)\\1/g, '$2')\n .trim();\n}\n\n/** Component names whose `children` a rendered heading can hide inside. */\nfunction isContainer(name: string): boolean {\n return getStandardComponent(name)?.hasChildren === true;\n}\n\nfunction isEnabled(component: ComponentDefinition): boolean {\n return !('enabled' in component && component.enabled === false);\n}\n\n/**\n * A paragraph contributes a TOC entry only through a custom `themeStyle`.\n * `heading1`..`heading6` are deliberately excluded: those map to the\n * display-only `JTD_HeadingText*` styles, which carry no outline level exactly\n * so paragraph text cannot masquerade as a heading.\n */\nfunction styleEntryKey(props: Record<string, unknown>): string | undefined {\n const themeStyle = props.themeStyle;\n if (typeof themeStyle !== 'string' || !themeStyle) return undefined;\n if (/^heading[1-6]$/i.test(themeStyle)) return undefined;\n if (['normal', 'title', 'subtitle'].includes(themeStyle.toLowerCase())) {\n return undefined;\n }\n return themeStyle;\n}\n\n/** Item shape a `list` component's `items` array can hold. */\ntype ListItem = {\n text?: unknown;\n level?: unknown;\n revision?: unknown;\n id?: unknown;\n};\n\n/** Per numbering reference: its level definitions and where each counter is. */\ninterface ListCounterState {\n levels: readonly ListLevelConfig[];\n /** One slot per list level, already decremented to \"before the start\". */\n counters: number[];\n}\n\nfunction levelStart(levels: readonly ListLevelConfig[], level: number): number {\n return levels[level]?.start ?? 1;\n}\n\n/**\n * Walk the document once and derive everything render needs to know about it up\n * front: the TOC entries, the heading numbers, and the cross-reference targets\n * keyed by the bookmark ids render will produce.\n *\n * The id prediction is the delicate part. `renderHeadingComponent` slugs a\n * heading's text and disambiguates it against bookmarks registered *so far*, so\n * this walk must see the same ids in the same order — including the explicit\n * `props.id` a paragraph registers — or a cross-reference resolves against an\n * id that never gets written.\n */\nexport function collectDocumentOutline(\n sections: readonly SectionLayout[]\n): DocumentOutline {\n const entries: TocHeadingEntry[] = [];\n const numberedItems = new Map<string, NumberedItemInfo>();\n const ordinals = computeSectionOrdinals(sections);\n\n // Bookmark ids already claimed, in walk order — the pre-pass mirror of the\n // bookmark registry render fills as it goes.\n const takenIds = new Set<string>();\n const headingCounters = new Array<number>(MAX_HEADING_LEVEL).fill(0);\n // Lists sharing an explicit `reference` share one numbering definition, so\n // their counters continue. An auto-generated reference is unique per list, so\n // such a list gets a fresh state that nothing else can reach.\n const listCounters = new Map<string, ListCounterState>();\n\n const visitHeading = (\n component: ComponentDefinition,\n props: Record<string, unknown>,\n sectionBookmarkId: string | undefined\n ): void => {\n const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n const level = typeof props.level === 'number' ? props.level : 1;\n // Mirrors getStyleIdForLevel: an out-of-range level renders as Heading1.\n const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;\n\n let full: string | undefined;\n let own: string | undefined;\n if (props.numbering === true) {\n headingCounters[styleLevel - 1] += 1;\n for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL; deeper++) {\n headingCounters[deeper] = 0;\n }\n // A level-3 heading with no level-2 above it numbers \"1.0.1\", exactly as\n // Word does; there is nothing to special-case.\n full = headingCounters.slice(0, styleLevel).join('.');\n own = String(headingCounters[styleLevel - 1]);\n }\n\n const explicitId = (component as { id?: unknown }).id;\n const bookmarkId =\n typeof explicitId === 'string' && explicitId\n ? explicitId\n : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));\n takenIds.add(bookmarkId);\n numberedItems.set(bookmarkId, {\n kind: 'heading',\n text: title,\n ...(full !== undefined && { full, own }),\n });\n\n if (title) {\n entries.push({\n title,\n level,\n sectionBookmarkId,\n ...(full !== undefined && { number: full }),\n });\n }\n };\n\n const visitList = (props: Record<string, unknown>): void => {\n const items = Array.isArray(props.items)\n ? (props.items as (string | ListItem)[])\n : [];\n if (items.length === 0) return;\n\n const reference =\n typeof props.reference === 'string' && props.reference\n ? props.reference\n : undefined;\n\n const freshState = (): ListCounterState => {\n const levels = resolveListLevels(\n props as Parameters<typeof resolveListLevels>[0]\n );\n return {\n levels,\n counters: Array.from(\n { length: MAX_LIST_LEVEL },\n (_, level) => levelStart(levels, level) - 1\n ),\n };\n };\n\n let state: ListCounterState;\n if (reference === undefined) {\n state = freshState();\n } else {\n state = listCounters.get(reference) ?? freshState();\n listCounters.set(reference, state);\n }\n\n for (const item of items) {\n const isObject = typeof item === 'object' && item !== null;\n const raw = isObject ? item.text : item;\n const text = typeof raw === 'string' ? raw : '';\n // Same skip rule as createList: an empty item renders nothing and so\n // never advances the counter.\n if (!text.trim() && !(isObject && item.revision)) continue;\n\n const rawLevel = isObject ? item.level : undefined;\n const level =\n typeof rawLevel === 'number' && rawLevel >= 0 ? rawLevel : 0;\n if (level >= MAX_LIST_LEVEL) continue;\n\n state.counters[level] += 1;\n for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {\n state.counters[deeper] = levelStart(state.levels, deeper) - 1;\n }\n\n const id = isObject ? item.id : undefined;\n if (typeof id !== 'string' || !id) continue;\n takenIds.add(id);\n // A single level's counter, not a \"1.a.i\" chain: Word's `\\r` switch on a\n // list item shows the item's own number.\n const number = formatNumberForLevel(\n state.counters[level],\n state.levels[level]?.format\n );\n numberedItems.set(id, {\n kind: 'list-item',\n text: normalizeUnicodeText(text).trim(),\n ...(number !== undefined && { full: number, own: number }),\n });\n }\n };\n\n sections.forEach((section, index) => {\n // Ordinal 0 means a continuation chunk that appears before any opening\n // chunk — there is no bookmark to scope to. `renderSection` applies the\n // same truthiness test, so the two must stay in step: making either side\n // treat 0 as a real ordinal would emit entries scoped to a `_Section_0`\n // bookmark the renderer never writes.\n const ordinal = ordinals[index]?.ordinal;\n const sectionBookmarkId = ordinal\n ? globalSectionBookmarkRegistry.forLayoutSection(ordinal).id\n : undefined;\n\n const visit = (component: ComponentDefinition): void => {\n if (!isEnabled(component)) return;\n\n const props = (component.props ?? {}) as Record<string, unknown>;\n\n if (component.name === 'heading') {\n visitHeading(component, props, sectionBookmarkId);\n return;\n }\n\n if (component.name === 'paragraph') {\n // `props.id` is the bookmark a paragraph registers when it renders;\n // claiming it here keeps a later heading slug dedupe in step.\n if (typeof props.id === 'string' && props.id) takenIds.add(props.id);\n\n const styleId = styleEntryKey(props);\n const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n if (styleId && title) {\n // Level is decided by the TOC's own style mapping, not here.\n entries.push({ title, level: 1, styleId, sectionBookmarkId });\n }\n return;\n }\n\n if (component.name === 'list') {\n visitList(props);\n return;\n }\n\n if (!isContainer(component.name)) return;\n const children = (component as { children?: ComponentDefinition[] })\n .children;\n if (Array.isArray(children)) children.forEach(visit);\n };\n\n // `section.components` only — headers and footers live on their own fields\n // and never reach the TOC.\n section.components.forEach(visit);\n });\n\n return { entries, numberedItems };\n}\n\n/**\n * Collect every TOC-eligible entry in document order, tagged with the layout\n * section it belongs to so a section-scoped TOC can filter to its own.\n */\nexport function collectTocHeadings(\n sections: readonly SectionLayout[]\n): TocHeadingEntry[] {\n return collectDocumentOutline(sections).entries;\n}\n","/**\n * Render a list counter the way Word renders it, for the cached value of a\n * cross-reference field.\n *\n * Only the formats whose glyph sequence is unambiguous are supported. Anything\n * else (bullets, CJK counting, `none`, an unknown string) returns undefined —\n * the caller then emits a field with no cached value rather than guessing a\n * number Word would disagree with on refresh.\n */\n\nconst ROMAN_NUMERALS: readonly (readonly [number, string])[] = [\n [1000, 'm'],\n [900, 'cm'],\n [500, 'd'],\n [400, 'cd'],\n [100, 'c'],\n [90, 'xc'],\n [50, 'l'],\n [40, 'xl'],\n [10, 'x'],\n [9, 'ix'],\n [5, 'v'],\n [4, 'iv'],\n [1, 'i'],\n];\n\nfunction toRoman(value: number): string {\n let remaining = value;\n let out = '';\n for (const [amount, glyph] of ROMAN_NUMERALS) {\n while (remaining >= amount) {\n out += glyph;\n remaining -= amount;\n }\n }\n return out;\n}\n\n/**\n * Word's letter sequence repeats the glyph rather than carrying: a, …, z, aa,\n * bb, …, zz, aaa. (`27` is \"aa\", not \"ab\".)\n */\nfunction toLetters(value: number): string {\n const index = (value - 1) % 26;\n const repeats = Math.floor((value - 1) / 26) + 1;\n return String.fromCharCode(97 + index).repeat(repeats);\n}\n\nexport function formatNumberForLevel(\n value: number,\n format?: string\n): string | undefined {\n if (!Number.isFinite(value) || value < 1) return undefined;\n const n = Math.floor(value);\n\n switch (format) {\n case 'decimal':\n return String(n);\n case 'lowerLetter':\n return toLetters(n);\n case 'upperLetter':\n return toLetters(n).toUpperCase();\n case 'lowerRoman':\n return toRoman(n);\n case 'upperRoman':\n return toRoman(n).toUpperCase();\n default:\n return undefined;\n }\n}\n","/**\n * Shared font-resolution helper used by BOTH entry paths into renderDocument:\n *\n * - generator.ts → generateDocumentWithCustomThemes (non-plugin)\n * - plugin/createDocumentGenerator.ts → generate (plugin-aware)\n *\n * Keeping it in one place ensures the two paths behave identically around\n * validation, SAFE_FONTS awareness, Google Fonts materialization, and the\n * `onResolved` side-channel consumed by the LibreOffice preview font stager.\n *\n * Materialization has two triggers: an `onResolved` listener, or the\n * caller's `forceMaterialize` flag (set when the document contains a\n * `visual`, whose PNG is produced by an out-of-process LibreOffice that\n * needs real font files). Both entry paths return the resolved fonts so the\n * caller can forward them to the rasterizer.\n */\n\nimport type {\n FontRuntimeOpts,\n ResolvedFont,\n GenerationWarning,\n} from '@json-to-office/shared';\nimport {\n collectFontNamesFromDocx,\n validateFontReferences,\n FontRegistry,\n documentFontRegistry,\n themeFontRegistry,\n mergeFontRegistries,\n} from '@json-to-office/shared';\nimport {\n loadFileFontSource,\n FontDiskCache,\n fetchVariableFontSource,\n} from '@json-to-office/shared/fonts/node';\nimport type { ThemeConfig } from '../styles';\nimport type { ReportComponentDefinition } from '../types';\n\nexport async function resolveDocumentFonts(\n document: ReportComponentDefinition,\n theme: ThemeConfig,\n fonts?: FontRuntimeOpts,\n warnings?: GenerationWarning[],\n /**\n * Materialize font bytes even when no `onResolved` listener is registered.\n * Set by the callers when the document contains at least one `visual`,\n * whose PNG is rendered by an out-of-process LibreOffice that needs the\n * actual font files — there is no listener on the plain CLI path, so\n * without this a visual-bearing build silently renders with fallbacks.\n */\n forceMaterialize = false\n): Promise<ResolvedFont[]> {\n const emit = (code: string, message: string) => {\n if (warnings) {\n warnings.push({\n component: 'fontRegistry',\n message,\n severity: 'warning',\n context: { code },\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] ${code}: ${message}`);\n }\n };\n\n // Walk document + theme. The document typically names fonts only indirectly\n // via `theme: \"my-theme\"`, so fonts declared in the theme JSON would be\n // invisible without this second pass.\n const names = new Set<string>();\n for (const n of collectFontNamesFromDocx(document)) names.add(n);\n for (const n of collectFontNamesFromDocx(theme as unknown)) names.add(n);\n if (names.size === 0) return [];\n\n // Merge the declared registries with runtime overrides. Precedence:\n // theme < document < fonts.extraEntries (see registry.ts's resolution\n // rules). This MUST run before validation, not after the `onResolved`\n // short-circuit below: a document with a valid registry and no preview\n // listener would otherwise still report every registered family as\n // FONT_UNRESOLVED.\n const registryEntries = mergeFontRegistries(\n themeFontRegistry(theme),\n documentFontRegistry(document),\n fonts?.extraEntries\n );\n\n // Validate unconditionally — strict mode must fire even when no consumer\n // is listening via onResolved (CLI / library callers that just want\n // build-time validation of font references).\n const validation = validateFontReferences({\n referencedNames: names,\n registeredEntries: registryEntries,\n });\n if (validation.warnings.length > 0) {\n if (fonts?.strict) {\n throw new Error(\n `Unresolved font references (strict mode):\\n` +\n validation.warnings.map((w) => ` - ${w.message}`).join('\\n')\n );\n }\n for (const w of validation.warnings) {\n emit(w.code, w.message);\n }\n }\n\n // Registry resolution (Google/URL/file fetches) runs when a consumer is\n // listening via onResolved — typically the LibreOffice preview stager —\n // or when the caller forces materialization because the document has a\n // `visual` to rasterize. Office output never embeds bytes, so skipping\n // fetches when neither applies keeps library callers off the network.\n if (!fonts?.onResolved && !forceMaterialize) return [];\n\n const registry = new FontRegistry({\n // Spread keeps baseDir/googleFonts/mode/substitution intact for\n // materializeSource; extraEntries carries the merged registry.\n opts: { ...fonts, extraEntries: registryEntries },\n fileLoader: loadFileFontSource,\n variableLoader: fetchVariableFontSource,\n diskCache: fonts?.googleFonts?.cacheDir\n ? new FontDiskCache(fonts.googleFonts.cacheDir)\n : undefined,\n });\n const resolved = await registry.resolveMany(names);\n for (const r of resolved) {\n for (const msg of r.warnings) {\n emit('FONT_UNRESOLVED', msg);\n }\n }\n // Fire the side-channel here so callers never have to remember. On the\n // force-materialize path there may be no listener at all — the resolved\n // fonts still flow back through the return value.\n fonts?.onResolved?.(resolved);\n return resolved;\n}\n","import AdmZip from 'adm-zip';\nimport { type Document, Packer } from 'docx';\nimport { fixFloatingImageIdsInBuffer } from './fixFloatingImageIds';\n\nexport interface DocumentPackageOptions {\n /** Normalize volatile OOXML metadata and ZIP timestamps. Defaults to true. */\n deterministic?: boolean;\n /** Timestamp used for generated metadata. Defaults to a stable epoch. */\n generatedAt?: string | Date;\n}\n\n/** Stable, valid OOXML/ZIP timestamp used when no build timestamp is supplied. */\nexport const DEFAULT_GENERATION_DATE = new Date('2000-01-01T00:00:00.000Z');\n\nexport function resolveGenerationDate(options?: DocumentPackageOptions): Date {\n if (options?.generatedAt !== undefined) {\n const date = new Date(options.generatedAt);\n if (Number.isNaN(date.getTime())) {\n throw new RangeError('generatedAt must be a valid date');\n }\n if (date.getUTCFullYear() < 1980) {\n throw new RangeError(\n 'generatedAt must be on or after 1980-01-01 for ZIP compatibility'\n );\n }\n return date;\n }\n\n return options?.deterministic === false\n ? new Date()\n : new Date(DEFAULT_GENERATION_DATE);\n}\n\n/** Encode a UTC instant into the packed MS-DOS date/time field ZIP headers use. */\nfunction toDosTime(date: Date): number {\n const dosDate =\n (((date.getUTCFullYear() - 1980) & 0x7f) << 9) |\n ((date.getUTCMonth() + 1) << 5) |\n date.getUTCDate();\n const dosTime =\n (date.getUTCHours() << 11) |\n (date.getUTCMinutes() << 5) |\n (date.getUTCSeconds() >> 1);\n return ((dosDate << 16) | dosTime) >>> 0;\n}\n\n/**\n * Normalize package-level values that otherwise change on every render.\n * ZIP headers are written from UTC components because DOS timestamps carry no\n * timezone; this produces identical header bits in every locale.\n */\nexport function canonicalizeDocxBuffer(\n buffer: Buffer,\n generatedAt: Date = DEFAULT_GENERATION_DATE\n): Buffer {\n const zip = new AdmZip(buffer);\n const isoTimestamp = generatedAt.toISOString();\n const coreProperties = zip.getEntry('docProps/core.xml');\n\n if (coreProperties) {\n const normalized = coreProperties\n .getData()\n .toString('utf8')\n .replace(\n /(<dcterms:(?:created|modified)\\b[^>]*>)[^<]*(<\\/dcterms:(?:created|modified)>)/g,\n `$1${isoTimestamp}$2`\n );\n zip.updateFile(coreProperties, Buffer.from(normalized, 'utf8'));\n }\n\n // AdmZip's `header.time` setter encodes the timezone-less DOS field from\n // local getters, so the emitted bits would vary by host. Write the raw field\n // from UTC components instead. Going through a reconstructed local Date is\n // not enough: a value inside a DST spring-forward gap has no local\n // representation and the runtime silently shifts it an hour.\n // `timeval` is the raw DOS field; @types/adm-zip@0.5.7 only declares the\n // `time` Date accessor that wraps it, hence the cast.\n const zipTimestamp = toDosTime(generatedAt);\n for (const entry of zip.getEntries()) {\n (entry.header as unknown as { timeval: number }).timeval = zipTimestamp;\n }\n\n return zip.toBuffer();\n}\n\n/** Package a DOCX and apply all required OOXML post-processing once. */\nexport async function packageDocument(\n document: Document,\n options?: DocumentPackageOptions\n): Promise<Buffer> {\n const packed = (await Packer.toBuffer(document)) as Buffer;\n const fixed = fixFloatingImageIdsInBuffer(packed);\n\n if (options?.deterministic === false) {\n return fixed;\n }\n\n return canonicalizeDocxBuffer(fixed, resolveGenerationDate(options));\n}\n","/**\n * Post-processing utility to fix docx.js floating image bugs\n *\n * The docx library (as of v9.7.1) has a known issue with floating images:\n * 1. Duplicate wp:docPr IDs (GitHub issue #2719)\n *\n * Historical note: We previously also post-processed relativeHeight and\n * wrapTight elements. Those steps were removed because we always provide a\n * valid zIndex upstream and we do not support 'tight' wrapping.\n *\n * This utility extracts the DOCX, fixes duplicate IDs, and re-packages it.\n */\n\nimport AdmZip from 'adm-zip';\nimport { readFile, writeFile } from 'fs/promises';\n\n/** Fix duplicate floating-image IDs without touching the filesystem. */\nexport function fixFloatingImageIdsInBuffer(buffer: Buffer): Buffer {\n const zip = new AdmZip(buffer);\n const documentEntry = zip.getEntry('word/document.xml');\n\n if (!documentEntry) {\n throw new Error('document.xml not found in DOCX');\n }\n\n let idCounter = 1;\n // `id` is not guaranteed to be the first attribute on wp:docPr: OOXML does\n // not fix attribute order and docx does not promise to preserve it. Match it\n // wherever it sits so a library-side reordering cannot silently turn this\n // pass into a no-op (which would leave every floating image on id=\"1\" and\n // make Word prompt for repair).\n const documentXml = documentEntry\n .getData()\n .toString('utf8')\n .replace(/(<wp:docPr\\b[^>]*?\\s)id=\"\\d+\"/g, (_match, prefix: string) => {\n const newId = idCounter++;\n return `${prefix}id=\"${newId}\"`;\n });\n\n zip.updateFile(documentEntry, Buffer.from(documentXml, 'utf8'));\n return zip.toBuffer();\n}\n\n/**\n * Fix floating image issues in a generated DOCX file\n * @param docxPath - Path to the DOCX file to fix\n */\nexport async function fixFloatingImageIds(docxPath: string): Promise<void> {\n const buffer = await readFile(docxPath);\n await writeFile(docxPath, fixFloatingImageIdsInBuffer(buffer));\n}\n","/**\n * JSON Document Parser - Re-exports from shared package\n *\n * This module re-exports the JSON parsing functionality from the shared package\n * and provide a clean interface for the core package.\n */\n\n// Re-export everything from shared package's JSON parser\nexport {\n JsonDocumentParser,\n JsonParsingError,\n JsonValidationError,\n parseJsonComponent,\n validateJsonComponent,\n parseJsonWithLineNumbers,\n} from '@json-to-office/shared-docx';\n\n// Re-export types needed by other modules\nexport type {\n DocumentValidationResult,\n DocumentValidationError,\n} from '@json-to-office/shared-docx';\n","/**\n * Component Normalizer - Transforms JSON components where business logic requires it\n *\n * This module ONLY handles transformations that are actually necessary:\n * 1. Columns shorthand notation (columns: 3 → array format)\n * 2. Recursive processing of nested components\n * 3. Gap application for columns\n *\n * All other properties are preserved as-is from TypeBox validation.\n * This prevents information loss and maintains single source of truth.\n */\n\nimport {\n ComponentDefinition,\n ReportComponentDefinition,\n SectionComponentDefinition,\n ColumnsComponentDefinition,\n ColumnsProps,\n} from '../types';\n\n/**\n * Normalize a component definition and its nested children\n * Preserves all validated properties - only transforms where business logic requires\n */\nexport function normalizeComponent(\n component: ComponentDefinition\n): ComponentDefinition {\n // Handle columns component with shorthand notation\n if (component.name === 'columns') {\n return normalizeColumnsComponent(component as ColumnsComponentDefinition);\n }\n\n // Handle components with children - recursively normalize\n if ('children' in component && component.children) {\n return {\n ...component, // Preserve ALL properties from validated component\n children: component.children.map(normalizeComponent),\n } as ComponentDefinition;\n }\n\n // Handle section component with header/footer arrays\n if (component.name === 'section') {\n return normalizeSectionComponent(component as SectionComponentDefinition);\n }\n\n // All other components: return as-is (already validated by TypeBox)\n return component;\n}\n\n/**\n * Normalize columns component\n * Converts shorthand notation and applies gap logic\n */\nfunction normalizeColumnsComponent(\n component: ColumnsComponentDefinition\n): ColumnsComponentDefinition {\n const cfg = component.props || ({} as any);\n\n // Helper: apply top-level gap to all columns except last where not overridden\n const applyTopLevelGap = (\n cols: Array<{ width?: unknown; gap?: unknown }>,\n topGap: unknown\n ) =>\n cols.map((c, i) => {\n const isLast = i === cols.length - 1;\n if (!isLast && c.gap === undefined && topGap !== undefined) {\n return { ...c, gap: topGap };\n }\n return c;\n });\n\n // Helper: normalize 'auto' to unspecified width (internal layout splits remainder)\n const normalizeAutoWidth = (\n cols: Array<{ width?: unknown; gap?: unknown }>\n ) =>\n cols.map((c) => ({\n ...c,\n width: c.width === 'auto' ? undefined : c.width,\n }));\n\n let columnsArray: Array<{ width?: unknown; gap?: unknown }>;\n\n if (typeof cfg.columns === 'number' && cfg.columns > 0) {\n // Shorthand: N equal-width columns; apply gap after each except last\n const n = cfg.columns as number;\n const base = Array.from(\n { length: n },\n () => ({}) as { width?: unknown; gap?: unknown }\n );\n const topLevelGap = cfg.gap !== undefined ? cfg.gap : '5%';\n columnsArray = applyTopLevelGap(base, topLevelGap);\n } else if (Array.isArray(cfg.columns)) {\n // Array form; honor per-column config\n columnsArray = cfg.columns as Array<{ width?: unknown; gap?: unknown }>;\n // Apply top-level gap unless column overrides; skip last column\n const topLevelGap = cfg.gap !== undefined ? cfg.gap : '5%';\n columnsArray = applyTopLevelGap(columnsArray, topLevelGap);\n // Normalize 'auto' widths to unspecified so layout can allocate remainder\n columnsArray = normalizeAutoWidth(columnsArray);\n } else {\n // Minimal valid shape\n columnsArray = [{}];\n }\n\n const normalizedProps: ColumnsProps = {\n columns: columnsArray,\n } as ColumnsProps;\n\n return {\n ...component, // Preserve any additional properties\n name: 'columns',\n props: normalizedProps,\n children: component.children\n ? component.children.map(normalizeComponent)\n : undefined,\n };\n}\n\n/**\n * Normalize section component\n * Handles recursive processing of header/footer component arrays\n */\nfunction normalizeSectionComponent(\n component: SectionComponentDefinition\n): SectionComponentDefinition {\n const props = component.props || ({} as any);\n\n return {\n ...component, // Preserve ALL properties\n props: {\n ...props, // Preserve ALL props properties\n header: props.header\n ? props.header === 'linkToPrevious'\n ? 'linkToPrevious'\n : props.header.map((m: ComponentDefinition) => normalizeComponent(m))\n : undefined,\n footer: props.footer\n ? props.footer === 'linkToPrevious'\n ? 'linkToPrevious'\n : props.footer.map((m: ComponentDefinition) => normalizeComponent(m))\n : undefined,\n },\n children: component.children\n ? component.children.map(normalizeComponent)\n : undefined,\n };\n}\n\n/**\n * Normalize entire document (top-level report component)\n * Returns as single-element tuple for backward compatibility\n */\nexport function normalizeDocument(\n document: ComponentDefinition | ReportComponentDefinition\n): [ReportComponentDefinition] {\n // Validate it's a report component\n if (document.name !== 'docx') {\n throw new Error(\n 'Top-level document must be a docx component with name=\"docx\"'\n );\n }\n\n const normalized = normalizeComponent(document) as ReportComponentDefinition;\n return [normalized];\n}\n\n/**\n * Validate component structure (container vs content components)\n */\nexport function validateComponentStructure(component: any): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Components that can have children\n const containerComponents = ['docx', 'section', 'columns', 'text-box'];\n\n // Check if content components have children (they shouldn't)\n if (\n !containerComponents.includes(component.name) &&\n component.children &&\n component.children.length > 0\n ) {\n errors.push(\n `Component name \"${component.name}\" cannot have child components`\n );\n }\n\n // Recursively validate child components\n if (component.children) {\n component.children.forEach(\n (childComponent: ComponentDefinition, index: number) => {\n const childResult = validateComponentStructure(childComponent);\n if (!childResult.valid) {\n errors.push(\n ...childResult.errors.map(\n (error) => `Component[${index}]: ${error}`\n )\n );\n }\n }\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { promises as fs } from 'fs';\nimport { join, resolve, isAbsolute } from 'path';\nimport { watch, FSWatcher } from 'fs';\nimport { ComponentDefinition } from '@json-to-office/shared-docx';\nimport { parseJsonWithLineNumbers } from './parser';\n\n/**\n * File System utilities for JSON report definitions\n */\n\n/**\n * Load JSON report definition from file\n * Supports both relative and absolute file paths\n */\nexport async function loadJsonDefinition(\n filePath: string\n): Promise<ComponentDefinition> {\n try {\n // Resolve path (handles both relative and absolute paths)\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Check if file exists\n await fs.access(absolutePath);\n\n // Read file content\n const fileContent = await fs.readFile(absolutePath, 'utf-8');\n\n // Parse JSON with line number tracking for better errors\n return parseJsonWithLineNumbers(fileContent) as ComponentDefinition;\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n throw new JsonFileError(\n `File not found: ${filePath}`,\n 'FILE_NOT_FOUND'\n );\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${filePath}`,\n 'PERMISSION_DENIED'\n );\n case 'EISDIR':\n throw new JsonFileError(\n `Path is a directory: ${filePath}`,\n 'IS_DIRECTORY'\n );\n default:\n throw new JsonFileError(\n `File system error: ${fsError.message}`,\n 'FS_ERROR'\n );\n }\n }\n\n // Re-throw parsing errors with file context\n if (error instanceof Error) {\n throw new JsonFileError(\n `Error loading ${filePath}: ${error.message}`,\n 'PARSE_ERROR',\n error\n );\n }\n\n throw new JsonFileError(\n `Unknown error loading ${filePath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * Load JSON definition with validation but without throwing on validation errors\n */\nexport async function loadJsonDefinitionSafe(filePath: string): Promise<{\n success: boolean;\n definition?: ComponentDefinition;\n error?: JsonFileError;\n}> {\n try {\n const definition = await loadJsonDefinition(filePath);\n return { success: true, definition };\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof JsonFileError\n ? error\n : new JsonFileError(\n error instanceof Error ? error.message : String(error),\n 'UNKNOWN_ERROR'\n ),\n };\n }\n}\n\n/**\n * Watch JSON file for changes and call callback on modifications\n * Useful for development workflows\n */\nexport function watchJsonFile(\n filePath: string,\n callback: (\n _definition: ComponentDefinition | null,\n _error?: JsonFileError\n ) => void\n): JsonFileWatcher {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Initial load\n loadJsonDefinitionSafe(absolutePath).then((result) => {\n if (result.success) {\n callback(result.definition!);\n } else {\n callback(null, result.error);\n }\n });\n\n // Set up file watcher\n const watcher = watch(absolutePath, { persistent: true }, (eventType) => {\n if (eventType === 'change') {\n // Debounce rapid file changes\n setTimeout(async () => {\n const result = await loadJsonDefinitionSafe(absolutePath);\n if (result.success) {\n callback(result.definition!);\n } else {\n callback(null, result.error);\n }\n }, 100);\n }\n });\n\n return new JsonFileWatcher(watcher, absolutePath);\n}\n\n/**\n * Watch multiple JSON files and call callback when any changes\n */\nexport function watchJsonFiles(\n filePaths: string[],\n callback: (\n _filePath: string,\n _definition: ComponentDefinition | null,\n _error?: JsonFileError\n ) => void\n): JsonFileWatcher[] {\n return filePaths.map((filePath) => {\n return watchJsonFile(filePath, (definition, error) => {\n callback(filePath, definition, error);\n });\n });\n}\n\n/**\n * Check if file exists and is accessible\n */\nexport async function checkJsonFile(filePath: string): Promise<{\n exists: boolean;\n readable: boolean;\n isDirectory: boolean;\n error?: string;\n}> {\n try {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n const stats = await fs.stat(absolutePath);\n\n return {\n exists: true,\n readable: true,\n isDirectory: stats.isDirectory(),\n };\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: 'File not found',\n };\n case 'EACCES':\n return {\n exists: true,\n readable: false,\n isDirectory: false,\n error: 'Permission denied',\n };\n default:\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: fsError.message,\n };\n }\n }\n\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Find JSON files in a directory (non-recursive)\n */\nexport async function findJsonFiles(directoryPath: string): Promise<string[]> {\n try {\n const absolutePath = isAbsolute(directoryPath)\n ? directoryPath\n : resolve(directoryPath);\n const entries = await fs.readdir(absolutePath, { withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.json'))\n .map((entry) => join(absolutePath, entry.name));\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n throw new JsonFileError(\n `Directory not found: ${directoryPath}`,\n 'DIRECTORY_NOT_FOUND'\n );\n case 'ENOTDIR':\n throw new JsonFileError(\n `Path is not a directory: ${directoryPath}`,\n 'NOT_DIRECTORY'\n );\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${directoryPath}`,\n 'PERMISSION_DENIED'\n );\n default:\n throw new JsonFileError(\n `Directory error: ${fsError.message}`,\n 'DIRECTORY_ERROR'\n );\n }\n }\n\n throw new JsonFileError(\n `Unknown error reading directory ${directoryPath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * Save JSON report definition to file\n */\nexport async function saveJsonDefinition(\n definition: ComponentDefinition,\n filePath: string,\n options: { pretty?: boolean; backup?: boolean } = {}\n): Promise<void> {\n const { pretty = true, backup = false } = options;\n\n try {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Create backup if requested\n if (backup) {\n try {\n const backupPath = `${absolutePath}.backup`;\n await fs.copyFile(absolutePath, backupPath);\n } catch (error) {\n // Ignore backup errors if original file doesn't exist\n if (\n error instanceof Error &&\n 'code' in error &&\n (error as Error & { code?: string }).code !== 'ENOENT'\n ) {\n console.warn(`Failed to create backup: ${error.message}`);\n }\n }\n }\n\n // Serialize JSON\n const jsonContent = pretty\n ? JSON.stringify(definition, null, 2)\n : JSON.stringify(definition);\n\n // Write file\n await fs.writeFile(absolutePath, jsonContent, 'utf-8');\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${filePath}`,\n 'PERMISSION_DENIED'\n );\n case 'ENOSPC':\n throw new JsonFileError(\n `No space left on device: ${filePath}`,\n 'NO_SPACE'\n );\n default:\n throw new JsonFileError(\n `Write error: ${fsError.message}`,\n 'WRITE_ERROR'\n );\n }\n }\n\n throw new JsonFileError(\n `Unknown error saving ${filePath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * File watcher wrapper class\n */\nexport class JsonFileWatcher {\n private watcher: FSWatcher;\n private filePath: string;\n\n constructor(watcher: FSWatcher, filePath: string) {\n this.watcher = watcher;\n this.filePath = filePath;\n }\n\n /**\n * Stop watching the file\n */\n public close(): void {\n this.watcher.close();\n }\n\n /**\n * Get the watched file path\n */\n public getFilePath(): string {\n return this.filePath;\n }\n}\n\n/**\n * Custom error class for file system operations\n */\nexport class JsonFileError extends Error {\n public readonly code: string;\n public readonly originalError?: Error;\n\n constructor(message: string, code: string, originalError?: Error) {\n super(message);\n this.name = 'JsonFileError';\n this.code = code;\n this.originalError = originalError;\n }\n}\n\n/**\n * Utility function to validate JSON file extension\n */\nexport function hasJsonExtension(filePath: string): boolean {\n return filePath.toLowerCase().endsWith('.json');\n}\n\n/**\n * Utility to ensure a path has .json extension\n */\nexport function ensureJsonExtension(filePath: string): string {\n return hasJsonExtension(filePath) ? filePath : `${filePath}.json`;\n}\n","/**\n * flattenVisuals — desugar `visual` components to plain `image` components ahead\n * of time, producing a portable, service-free `.docx.json`.\n *\n * The normal pipeline rasterizes `visual` nodes at render time via\n * `services.pptx`. This transform does the same desugaring offline: walk the\n * document tree, rasterize each `visual` with the supplied rasterizer, and\n * replace it with `{ name: 'image', props: { base64, ... } }`. The result builds\n * with no rasterization service configured — handy for shipping documents that\n * generate on hosts without LibreOffice/poppler.\n *\n * The walk covers every place the docx model can hold a child component, not\n * just `children`: section `props.header`/`props.footer`, and table\n * `props.columns[].cells[].content` / `props.columns[].header.content`.\n */\n\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n type PptxRasterizer,\n type PptxBatchRasterizer,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport {\n buildVisualPresentation,\n visualRasterKey,\n visualToImageProps,\n} from '../components/visual';\nimport { createLimiter } from '../utils/promiseLimiter';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\n\nconst DEFAULT_CONCURRENCY = 4;\n\nexport interface FlattenVisualsOptions {\n /** Rasterizer that turns a single-slide pptx presentation into a PNG. */\n rasterize: PptxRasterizer;\n /**\n * Batch rasterizer (#153). When provided, all visuals are collected and\n * rasterized together up front; `rasterize` remains the per-visual\n * fallback for batch failures and anything the collection missed.\n */\n rasterizeBatch?: PptxBatchRasterizer;\n /** Default DPI applied when a `visual` does not specify one (default 200). */\n dpi?: number;\n /** Max concurrent rasterizations (default 4). */\n concurrency?: number;\n /**\n * Directory that relative asset paths inside visuals resolve against —\n * the document's own directory. Absent → the rasterizer's cwd (#142).\n */\n baseDir?: string;\n /**\n * Font faces staged for each visual's LibreOffice render. Without these a\n * flattened document bakes in fontless PNGs permanently — the flatten\n * output is a portable, service-free `.docx.json`, so there is no second\n * chance to re-rasterize with the right fonts.\n */\n fonts?: readonly RasterizeFontFace[];\n}\n\ninterface FlattenCtx {\n rasterize: PptxRasterizer;\n dpi?: number;\n baseDir?: string;\n fonts?: readonly RasterizeFontFace[];\n limit: <T>(fn: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Return a deep copy of `doc` with every `visual` node replaced by the `image`\n * node it rasterizes to. With `rasterizeBatch`, visuals are pre-rasterized in\n * batches and the tree walk resolves from the batch results; otherwise (and\n * for any batch miss) visuals rasterize per-node with bounded concurrency. A\n * `visual` with `enabled: false` is left untouched (it's filtered out at render\n * anyway, so rasterizing it would be wasted work). Non-visual nodes are copied\n * structurally and otherwise unchanged.\n */\nexport async function flattenVisuals<T = unknown>(\n doc: T,\n options: FlattenVisualsOptions\n): Promise<T> {\n let rasterize = options.rasterize;\n\n if (options.rasterizeBatch) {\n // The pre-pass keys results exactly like the walk below computes its\n // requests (in-process semantics: no serverUrl), so hits are exact. A\n // pre-pass failure must not fail the flatten — misses below rasterize\n // per-visual exactly as they did before batching existed.\n const preRasterized = await prerasterizeVisuals(\n doc,\n {\n render: options.rasterize,\n renderBatch: options.rasterizeBatch,\n dpi: options.dpi,\n },\n {\n baseDir: options.baseDir,\n concurrency: options.concurrency,\n fonts: options.fonts,\n }\n ).catch(() => new Map<string, never>());\n rasterize = async (request) => {\n const hit = preRasterized.get(\n visualRasterKey(request.presentation, request.dpi)\n );\n if (hit) {\n if (!hit.ok) throw new Error(hit.error);\n return {\n base64DataUri: hit.base64DataUri,\n width: hit.width,\n height: hit.height,\n };\n }\n return options.rasterize(request);\n };\n }\n\n const ctx: FlattenCtx = {\n rasterize,\n dpi: options.dpi,\n baseDir: options.baseDir,\n fonts: options.fonts,\n limit: createLimiter(\n Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY)\n ),\n };\n return (await flattenNode(doc, ctx)) as T;\n}\n\nasync function rasterizeVisual(\n obj: Record<string, unknown>,\n ctx: FlattenCtx\n): Promise<Record<string, unknown>> {\n const props = obj.props as VisualProps;\n const dpi = clampVisualDpi(props.dpi ?? ctx.dpi ?? DEFAULT_VISUAL_DPI);\n const result = await ctx.limit(() =>\n ctx.rasterize({\n presentation: buildVisualPresentation(props),\n dpi,\n baseDir: ctx.baseDir,\n ...(ctx.fonts?.length ? { fonts: [...ctx.fonts] } : {}),\n })\n );\n const image: Record<string, unknown> = {\n name: 'image',\n props: visualToImageProps(props, result.base64DataUri),\n };\n // Preserve identity/visibility metadata from the original node.\n if (obj.id !== undefined) image.id = obj.id;\n if (obj.enabled !== undefined) image.enabled = obj.enabled;\n return image;\n}\n\nasync function flattenNode(node: unknown, ctx: FlattenCtx): Promise<unknown> {\n if (Array.isArray(node)) {\n return Promise.all(node.map((n) => flattenNode(n, ctx)));\n }\n if (!node || typeof node !== 'object') return node;\n\n const obj = node as Record<string, unknown>;\n\n // Replace an enabled visual with its rasterized image. A disabled visual is\n // left as-is (filtered at render; rasterizing it would be wasted work).\n if (obj.name === 'visual' && obj.props && obj.enabled !== false) {\n return rasterizeVisual(obj, ctx);\n }\n\n const next: Record<string, unknown> = { ...obj };\n\n if (Array.isArray(obj.children)) {\n next.children = await flattenNode(obj.children, ctx);\n }\n\n if (obj.props && typeof obj.props === 'object') {\n const props = obj.props as Record<string, unknown>;\n let propsChanged = false;\n const nextProps: Record<string, unknown> = { ...props };\n\n // Section header/footer: arrays of component definitions (or a literal\n // 'linkToPrevious' string, which flattenNode returns unchanged).\n for (const key of ['header', 'footer'] as const) {\n if (Array.isArray(props[key])) {\n nextProps[key] = await flattenNode(props[key], ctx);\n propsChanged = true;\n }\n }\n\n // Table columns: each cell's `content` and the column header's `content`\n // hold a component definition (or a string).\n if (Array.isArray(props.columns)) {\n nextProps.columns = await Promise.all(\n (props.columns as unknown[]).map((col) => flattenColumn(col, ctx))\n );\n propsChanged = true;\n }\n\n if (propsChanged) next.props = nextProps;\n }\n\n return next;\n}\n\nasync function flattenColumn(col: unknown, ctx: FlattenCtx): Promise<unknown> {\n if (!col || typeof col !== 'object') return col;\n const column = col as Record<string, unknown>;\n const nextCol: Record<string, unknown> = { ...column };\n\n const header = column.header as Record<string, unknown> | undefined;\n if (header && typeof header === 'object' && 'content' in header) {\n nextCol.header = {\n ...header,\n content: await flattenNode(header.content, ctx),\n };\n }\n\n if (Array.isArray(column.cells)) {\n nextCol.cells = await Promise.all(\n (column.cells as unknown[]).map(async (cell) => {\n if (cell && typeof cell === 'object' && 'content' in cell) {\n const c = cell as Record<string, unknown>;\n return { ...c, content: await flattenNode(c.content, ctx) };\n }\n return cell;\n })\n );\n }\n\n return nextCol;\n}\n","/**\n * Warnings Document Generator\n * Utility to generate a document from generation warnings\n */\n\nimport type { GenerationWarning } from '@json-to-office/shared-docx';\nimport type { ComponentDefinition, ReportComponentDefinition } from '../types';\n\n/**\n * Generate a report document from warnings\n * Returns null if there are no warnings\n */\nexport function generateWarningsDocument(\n warnings: GenerationWarning[] | null\n): ReportComponentDefinition | null {\n if (!warnings || warnings.length === 0) {\n return null;\n }\n\n const children: ComponentDefinition[] = [\n {\n name: 'heading',\n props: {\n level: 1,\n text: 'Document Generation Warnings',\n },\n },\n {\n name: 'paragraph',\n props: {\n text: `${warnings.length} warning(s) were generated during document processing.`,\n spacing: {\n after: 24,\n },\n },\n },\n ];\n\n // Group warnings by component\n const warningsByComponent = new Map<string, GenerationWarning[]>();\n for (const warning of warnings) {\n const existing = warningsByComponent.get(warning.component) || [];\n existing.push(warning);\n warningsByComponent.set(warning.component, existing);\n }\n\n // Create sections for each component with warnings\n for (const [componentName, componentWarnings] of warningsByComponent.entries()) {\n children.push({\n name: 'heading',\n props: {\n level: 3,\n text: `Component: ${componentName}`,\n },\n });\n\n // Add each warning as a list item with details\n const warningItems: string[] = [];\n for (const warning of componentWarnings) {\n let warningText = warning.message;\n\n // Add context if present\n if (warning.context && Object.keys(warning.context).length > 0) {\n const contextStr = Object.entries(warning.context)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ');\n warningText += ` (${contextStr})`;\n }\n\n warningItems.push(warningText);\n }\n\n children.push({\n name: 'list',\n props: {\n items: warningItems,\n spacing: {\n after: 12,\n },\n },\n });\n }\n\n return {\n name: 'docx',\n props: {\n metadata: {\n title: 'Generation Warnings',\n },\n theme: 'minimal',\n },\n children,\n };\n}\n\n/**\n * Format warnings as plain text\n * Useful for logging or text output\n */\nexport function formatWarningsText(\n warnings: GenerationWarning[] | null\n): string {\n if (!warnings || warnings.length === 0) {\n return 'No warnings generated.';\n }\n\n const lines: string[] = [\n `Document Generation Warnings (${warnings.length} total)`,\n '='.repeat(50),\n '',\n ];\n\n // Group by component\n const warningsByComponent = new Map<string, GenerationWarning[]>();\n for (const warning of warnings) {\n const existing = warningsByComponent.get(warning.component) || [];\n existing.push(warning);\n warningsByComponent.set(warning.component, existing);\n }\n\n for (const [componentName, componentWarnings] of warningsByComponent.entries()) {\n lines.push(`Component: ${componentName}`);\n lines.push('-'.repeat(30));\n\n for (let i = 0; i < componentWarnings.length; i++) {\n const warning = componentWarnings[i];\n lines.push(` ${i + 1}. ${warning.message}`);\n\n if (warning.context && Object.keys(warning.context).length > 0) {\n lines.push(` Context: ${JSON.stringify(warning.context, null, 2)}`);\n }\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","// Version information\nexport function getCoreVersion(): string {\n return 'Core v1.0.0';\n}\n\n// Core functional API\nexport {\n generateDocument,\n generateFromConfig,\n generateDocumentFromJson,\n generateDocumentFromFile,\n generateBufferFromJson,\n generateBufferFromFile,\n generateAndSaveFromJson,\n generateAndSaveFromFile,\n validateJsonSchema,\n isReportComponentDefinition,\n saveDocument,\n generateAndSave,\n DocumentGenerator as CoreDocumentGenerator,\n} from './core/generator';\n\n// Visual flattening (desugar `visual` → `image` for portable, service-free docs)\nexport {\n flattenVisuals,\n type FlattenVisualsOptions,\n} from './core/flattenVisuals';\n\n// Cache API (general purpose caching, not specific to custom components)\nexport {\n MemoryCache,\n CacheKeyGenerator,\n DEFAULT_CACHE_CONFIG,\n getCacheConfigFromEnv,\n mergeConfigs,\n ComponentCacheAnalytics,\n // Types\n type CacheConfiguration,\n type CachedComponent,\n type CacheStatistics,\n type CacheKeyOptions,\n type CacheEvents,\n type CacheAnalyticsReport,\n type ComponentPerformanceMetrics,\n type ComponentCacheTrends,\n type CacheOptimizationRecommendation,\n type TimeSeriesPoint,\n} from './cache/index';\n\n// Component cache functions from core\nexport {\n initializeComponentCache,\n getComponentCache,\n clearComponentCache,\n getComponentCacheStats,\n getComponentBypassStats,\n warmComponentCache,\n componentBypassReason,\n type ComponentBypassReason,\n type ComponentBypassStats,\n} from './core/cached-render';\nexport {\n getVisualPrepassStats,\n resetVisualPrepassStats,\n type VisualPrepassStats,\n} from './core/prerasterizeVisuals';\n\n// Legacy class-based API is now removed - use functional API above\n\n// Runtime exports (only type guards and functions)\nexport {\n // Type guards\n isReportComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isColumnsComponent,\n isImageComponent,\n isStatisticComponent,\n isTableComponent,\n isListComponent,\n isHighchartsComponent,\n isVisualComponent,\n} from './types/index';\n\n// Export core-specific types only\nexport type {\n // Core-specific types\n ImageContent,\n StatisticContent,\n TableData,\n SectionProperties,\n ColumnSettings,\n PageSizeOptions,\n PageMarginOptions,\n PageNumberOptions,\n PageBorderOptions,\n RenderContext,\n} from './types/index';\n\n// Utilities\nexport * from './utils/formatters';\nexport { parseTextWithDecorators } from './utils/textParser';\nexport { isNodeEnvironment, hasNodeBuiltins } from './utils/environment';\nexport {\n generateWarningsDocument,\n formatWarningsText,\n} from './utils/warningsDocument';\n\n// Styles and themes\nexport {\n themes,\n minimalTheme,\n corporateTheme,\n modernTheme,\n} from './styles/index';\nexport type { ThemeName } from './styles/index';\n\n// JSON Theme System\nexport {\n loadThemeFromJson,\n loadThemeFromFile,\n exportThemeToJson,\n validateThemeJsonString,\n ThemeValidationError,\n ThemeParseError,\n ThemeFileError,\n createMinimalTheme,\n} from './themes/json/index';\n\n// Examples and utilities\nexport {\n examples,\n getExample,\n getExampleNames,\n loadJsonExample,\n} from './templates/documents/index';\nexport { runExample } from './utils/exampleRunner';\n\n// Export component implementations\nimport './components/index';\n\n// Re-export types from components (excluding those that come from shared)\nexport type {\n // ChartGenerationResult is specific to the component implementation\n ChartGenerationResult,\n} from './components/highcharts';\n\n// Note: TextSpaceAfterProps and HighchartsProps types are now in shared package\n// and should be imported from there to maintain single source of truth\n\n// Plugin System API\nexport {\n // Core plugin functions\n createComponent,\n createVersion,\n createDocumentGenerator,\n\n // Validation utilities\n validateComponentProps,\n validateDocument,\n cleanComponentProps,\n ComponentValidationError,\n UnknownPreservedComponentError,\n\n // Schema utilities\n generatePluginDocumentSchema,\n exportPluginSchema,\n generateComponentSchemas,\n mergeSchemas,\n\n // Types\n type CustomComponent,\n type ComponentVersion,\n type ComponentVersionMap,\n type RenderFunction,\n type RenderContext as ComponentRenderContext,\n type DocumentGenerator,\n type DocumentGeneratorOptions,\n type GenerateOptions,\n type GenerateFileOptions,\n type GenerationResult,\n type BufferGenerationResult,\n type FileGenerationResult,\n type StandardDefinitionResult,\n type ValidationResult,\n type ValidationError,\n\n // Type utilities for custom components\n type ExtractCustomComponentType,\n type CustomComponentUnion,\n type ExtendedComponentDefinition,\n type ExtendedReportComponent,\n type InferCustomComponents,\n} from './plugin/index';\n\n// Plugin types\nexport type {\n PluginComponent,\n PluginRenderFunction,\n PluginValidationError,\n PluginValidationResult,\n} from './types/plugin';\n","/**\n * Examples registry - JSON-based examples\n * This file provides a unified interface to the JSON examples system\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { ComponentDefinition } from '@json-to-office/shared-docx';\n\nlet _dirname: string | null = null;\n\nfunction getDirname(): string {\n if (_dirname === null) {\n try {\n _dirname = path.dirname(fileURLToPath(import.meta.url));\n } catch {\n throw new Error(\n 'Cannot resolve file paths in a bundled environment. Example loading from disk is not available.'\n );\n }\n }\n return _dirname;\n}\n\n/**\n * Load a JSON example by name\n */\nexport function loadJsonExample(name: string): ComponentDefinition {\n // Since this file is bundled into dist/index.js, getDirname() will be the dist directory\n // The JSON files are copied to dist/templates/documents/ by the tsup config\n const filePath = path.join(\n getDirname(),\n 'templates',\n 'documents',\n `${name}.docx.json`\n );\n\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n return JSON.parse(content) as ComponentDefinition;\n } catch (error) {\n throw new Error(\n `Failed to load JSON example \"${name}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Get list of available JSON examples\n */\nexport function getAvailableJsonExamples(): string[] {\n // Since this file is bundled into dist/index.js, getDirname() will be the dist directory\n // The JSON files are copied to dist/templates/documents/ by the tsup config\n const examplesDir = path.join(getDirname(), 'templates', 'documents');\n\n try {\n const files = fs.readdirSync(examplesDir);\n return files\n .filter((file) => file.endsWith('.docx.json'))\n .map((file) => path.basename(file, '.docx.json'))\n .sort();\n } catch (error) {\n console.warn('Could not read JSON examples directory:', error);\n return [];\n }\n}\n\n/**\n * Example descriptions for documentation\n */\nexport const EXAMPLE_DESCRIPTIONS: Record<string, string> = {\n 'technical-guide':\n 'Arcline Platform integration guide with TOC, headers/footers, OAuth code samples, API reference tables, webhook docs, and troubleshooting',\n proposal:\n 'Apex Consulting cloud migration proposal with TOC, headers/footers, images, statistics, compliance tables, cost comparisons, and risk matrix',\n};\n\n/**\n * Registry of available JSON examples (lazy-loaded)\n * For backward compatibility, this returns ComponentDefinition objects\n */\nconst _exampleCache: Record<string, ComponentDefinition> = {};\n\nexport const examples = new Proxy({} as Record<string, ComponentDefinition>, {\n get(_target, prop: string) {\n if (!_exampleCache[prop]) {\n try {\n _exampleCache[prop] = loadJsonExample(prop);\n } catch {\n return undefined;\n }\n }\n return _exampleCache[prop];\n },\n\n ownKeys(_target) {\n return getAvailableJsonExamples();\n },\n\n has(_target, prop: string) {\n return getAvailableJsonExamples().includes(prop);\n },\n});\n\n/**\n * Get example definition by name\n */\nexport const getExample = (\n exampleName: string\n): ComponentDefinition | undefined => {\n return examples[exampleName];\n};\n\n/**\n * Get all available example names\n */\nexport const getExampleNames = (): string[] => {\n return getAvailableJsonExamples();\n};\n\n// Use loadJsonExample() directly or access via the examples proxy\nexport const technicalGuideExample = () => loadJsonExample('technical-guide');\nexport const proposalExample = () => loadJsonExample('proposal');\n\n/**\n * Print usage information\n */\nexport function printExampleUsage(): void {\n const available = getAvailableJsonExamples();\n\n console.log('📋 Available JSON Examples:');\n console.log('===========================');\n\n available.forEach((name) => {\n const description =\n EXAMPLE_DESCRIPTIONS[name] || 'No description available';\n console.log(`\\n📄 ${name}:`);\n console.log(` ${description}`);\n console.log(` Usage: loadJsonExample('${name}')`);\n });\n\n console.log('\\n🔧 Example code:');\n console.log('```typescript');\n console.log(\n 'import { loadJsonExample, generateDocumentFromJson } from \"cool-report-generator\";'\n );\n console.log('');\n console.log('const jsonConfig = loadJsonExample(\"comprehensive\");');\n console.log('const document = await generateDocumentFromJson(jsonConfig);');\n console.log('```');\n}\n","/**\n * Universal example runner utility\n * Provides common functionality for running examples\n */\n\nimport { generateDocument, saveDocument } from '../core/generator';\nimport { ReportComponentDefinition } from '../types';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport interface ExampleRunnerOptions {\n outputFilename?: string;\n outputDir?: string;\n verbose?: boolean;\n}\n\n/**\n * Run an example and generate a document\n * @param example - The example definition to run\n * @param options - Options for running the example\n */\nexport async function runExample(\n example: ReportComponentDefinition,\n options: ExampleRunnerOptions = {}\n): Promise<void> {\n const { outputFilename, outputDir, verbose = true } = options;\n\n if (!example.props) {\n throw new Error('Example must have props');\n }\n\n const reportTitle = String(example.props.metadata?.title) || 'Document';\n const baseFilename =\n outputFilename || `${reportTitle.toLowerCase().replace(/\\s+/g, '-')}.docx`;\n\n // Use output directory if provided, otherwise use default output/examples path\n const defaultOutputDir = path.join(process.cwd(), 'output', 'examples');\n const finalOutputDir = outputDir || defaultOutputDir;\n const filename = path.join(finalOutputDir, baseFilename);\n\n if (verbose) {\n console.log(`=== ${reportTitle} Generation ===\\n`);\n console.log(`Generating ${reportTitle} with modular system...`);\n }\n\n try {\n // Ensure output directory exists\n await fs.promises.mkdir(finalOutputDir, { recursive: true });\n\n const document = await generateDocument(example);\n await saveDocument(document, filename);\n\n if (verbose) {\n console.log(`✓ ${reportTitle} saved: ${filename}`);\n console.log(`\\n✅ ${reportTitle} generated successfully!`);\n }\n } catch (error) {\n if (verbose) {\n console.error(`${reportTitle} generation failed:`, error);\n }\n throw error;\n }\n}\n","import type { TSchema } from '@sinclair/typebox';\nimport type { CustomComponent } from './createComponent';\nimport type { ComponentDefinition, ReportComponentDefinition } from '../types';\nimport { type ThemeConfig } from '../styles';\nimport { resolveBuiltInTheme } from '../styles/theme-resolver';\nimport { hasTheme } from '../templates/themes';\nimport { resolveThemeContext } from '../core/generationContext';\nimport type { GenerationWarning } from '@json-to-office/shared-docx';\nimport type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';\nimport { resolveDocumentFonts } from '../core/fontResolution';\nimport { collectVisualProps } from '../core/prerasterizeVisuals';\nimport { toRasterizeFontFaces } from '@json-to-office/shared/fonts/node';\nimport type {\n ExtendedReportComponent,\n DocumentGeneratorBuilder,\n GenerateOptions,\n GenerateFileOptions,\n GenerationResult,\n BufferGenerationResult,\n FileGenerationResult,\n StandardDefinitionResult,\n ValidationResult,\n GenerationValidationOptions,\n} from './types';\nimport {\n validateDocument,\n cleanComponentProps,\n ComponentValidationError,\n DuplicateComponentError,\n} from './validation';\nimport { UnknownPreservedComponentError } from '@json-to-office/shared/plugin';\nimport { resolveComponentVersion } from './version-resolver';\nimport { generatePluginDocumentSchema, exportPluginSchema } from './schema';\nimport { processDocument } from '../core/structure';\nimport { applyLayout } from '../core/layout';\nimport { renderDocument } from '../core/render';\nimport { normalizeDocument } from '../json/normalizer';\nimport {\n packageDocument,\n resolveGenerationDate,\n} from '../utils/packageDocument';\n\n/**\n * Options for creating a document generator\n */\nexport interface DocumentGeneratorOptions {\n /** Default theme used when no custom or built-in theme matches */\n theme?: ThemeConfig;\n /** Custom themes keyed by name, resolved per-document via document.props.theme */\n customThemes?: Record<string, ThemeConfig>;\n /** Enable caching for better performance */\n enableCache?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n /** External service configuration (e.g. Highcharts export server) */\n services?: ServicesConfig;\n /** Font resolution options — extraEntries, Google Fonts config, onResolved hook. */\n fonts?: FontRuntimeOpts;\n /**\n * Default validation behavior for every generate/generateBuffer/generateFile\n * call. Per-call `options.validation` overrides these. Validation is on by\n * default; pass `{ enabled: false }` to opt out.\n */\n validation?: GenerationValidationOptions;\n /** Normalize volatile OOXML values for byte-identical output. Defaults true. */\n deterministic?: boolean;\n /** Default build timestamp for generated metadata. */\n generatedAt?: string | Date;\n /**\n * Directory that relative asset paths (image `path` props) resolve against.\n * Per-call `options.baseDir` overrides it; defaults to `process.cwd()`\n * when neither is set (#142).\n */\n baseDir?: string;\n}\n\n/**\n * Internal state held by each builder instance\n */\ninterface BuilderState {\n components: readonly CustomComponent<any, any, any>[];\n componentNames: Set<string>;\n theme?: ThemeConfig;\n customThemes?: Record<string, ThemeConfig>;\n debug: boolean;\n enableCache: boolean;\n services?: ServicesConfig;\n fonts?: FontRuntimeOpts;\n validation?: GenerationValidationOptions;\n deterministic: boolean;\n generatedAt?: string | Date;\n baseDir?: string;\n}\n\n/**\n * Create the builder implementation with the given state\n */\nfunction createBuilderImpl<\n TComponents extends readonly CustomComponent<any, any, any>[],\n>(state: BuilderState): DocumentGeneratorBuilder<TComponents> {\n // Create component map for quick lookup\n const componentMap = new Map(state.components.map((c) => [c.name, c]));\n\n /**\n * Resolve theme for a document: customThemes → doc-named built-in →\n * constructor theme → built-in resolver fallback.\n *\n * A document explicitly naming a known built-in gets it; the constructor\n * `theme` object fills in when the document names nothing or names\n * something nothing recognizes (#141). The `authored` guard on the\n * built-in step matters twice over: the unauthored 'minimal' fallback\n * must not shadow the constructor theme, and an authored UNKNOWN name\n * must still reach the constructor theme rather than silently rendering\n * the resolver's minimal fallback.\n */\n function resolveDocumentTheme(\n themeName: string,\n warnings: GenerationWarning[] | undefined,\n authored: boolean\n ): ThemeConfig {\n if (state.customThemes) {\n if (state.customThemes[themeName]) {\n return state.customThemes[themeName];\n }\n const key = Object.keys(state.customThemes).find(\n (k) => k.toLowerCase() === themeName.toLowerCase()\n );\n if (key) {\n return state.customThemes[key];\n }\n }\n if (authored && hasTheme(themeName)) {\n return resolveBuiltInTheme(themeName, {\n customThemes: state.customThemes,\n warnings,\n });\n }\n if (state.theme) {\n return state.theme;\n }\n return resolveBuiltInTheme(themeName, {\n customThemes: state.customThemes,\n warnings,\n });\n }\n\n /**\n * Process custom components in the document.\n *\n * Returns two parallel trees built in a single pass:\n * - `standard`: fully expanded — every custom component resolved to standard primitives.\n * - `preserved`: partially expanded — nodes whose name is in `preserveSet` are kept\n * verbatim (children NOT recursed); everything else is expanded the same as `standard`.\n *\n * `render()` always runs, even for preserved components, because the docx pipeline\n * builds from `standard` and we still need their warnings/font registrations.\n */\n async function processDocumentComponents(\n components: ComponentDefinition[],\n preserveSet: ReadonlySet<string> | undefined,\n warningsCollector: GenerationWarning[],\n resolvedTheme: ThemeConfig,\n validateEmitted:\n | ((emitted: ComponentDefinition[], componentLabel: string) => void)\n | undefined,\n depth = 0\n ): Promise<{\n standard: ComponentDefinition[];\n preserved: ComponentDefinition[];\n }> {\n if (depth > 20) {\n throw new Error(\n 'Maximum component nesting depth exceeded (20). Check for circular component references.'\n );\n }\n const standardOut: ComponentDefinition[] = [];\n const preservedOut: ComponentDefinition[] = [];\n\n for (const componentData of components) {\n // Safe type narrowing for custom component detection\n const componentName = (componentData as { name?: string })?.name;\n\n if (!componentName) {\n standardOut.push(componentData);\n preservedOut.push(componentData);\n continue;\n }\n\n const customComponent = componentMap.get(componentName);\n\n if (customComponent) {\n // This is a custom component - validate and process it\n try {\n const componentWithName = componentData as {\n name: string;\n version?: string;\n props?: unknown;\n children?: unknown;\n };\n\n if (!componentWithName.props) {\n throw new Error(\n `Custom component '${componentName}' must have a 'props' property. Use format: { name: '${componentName}', props: {...} }`\n );\n }\n\n // Resolve the correct version entry\n const versionEntry = resolveComponentVersion(\n customComponent.name,\n customComponent.versions,\n componentWithName.version\n );\n\n // Validate and clean the props against the resolved version's schema\n const cleanedProps = cleanComponentProps(\n versionEntry,\n componentWithName.props\n );\n\n // Process nested children if this is a container.\n // For the standard tree we need the fully-expanded children to feed render().\n let nestedChildren: unknown[] | undefined;\n if (\n componentWithName.children &&\n Array.isArray(componentWithName.children)\n ) {\n const nested = await processDocumentComponents(\n componentWithName.children as ComponentDefinition[],\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n nestedChildren = nested.standard;\n }\n\n // Create addWarning callback for this component\n const versionLabel = componentWithName.version\n ? `${customComponent.name}@${componentWithName.version}`\n : customComponent.name;\n\n const addWarning = (\n message: string,\n context?: Record<string, unknown>\n ) => {\n warningsCollector.push({\n component: versionLabel,\n message,\n severity: 'warning',\n context,\n });\n };\n\n // Call the render function with context object\n const result = await versionEntry.render({\n props: cleanedProps,\n theme: resolvedTheme,\n addWarning,\n children: nestedChildren,\n });\n\n // Ensure result is an array\n const resultComponents = (\n Array.isArray(result) ? result : [result]\n ) as ComponentDefinition[];\n\n // Validate the standard tree this render() emitted, applying the same\n // schema gate authored standard components pass through up front. The\n // pre-expansion pass never saw these nodes, so without this an invalid\n // prop produced by a plugin would ride through into standardDefinition\n // and only surface when that output is validated separately.\n if (validateEmitted) {\n validateEmitted(resultComponents, versionLabel);\n }\n\n // Recursively process the result in case it contains more custom components\n const processedResult = await processDocumentComponents(\n resultComponents,\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n standardOut.push(...processedResult.standard);\n\n if (preserveSet && preserveSet.has(componentName)) {\n // Keep this custom node verbatim in the preserved tree.\n // Per spec: do NOT recurse into authored children — leave the\n // entire subtree as the user wrote it.\n preservedOut.push(componentData);\n } else {\n // Non-preserved custom: emit the recursed expansion (which itself\n // honors preserveSet for any nested customs).\n preservedOut.push(...processedResult.preserved);\n }\n\n if (state.debug) {\n console.log(\n `Processed custom component '${versionLabel}':`,\n processedResult.standard\n );\n }\n } catch (error) {\n if (error instanceof ComponentValidationError) {\n throw error;\n }\n throw new Error(\n `Error processing custom component '${customComponent.name}': ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n } else {\n // This is a standard component or nested container - process recursively\n if (\n 'children' in componentData &&\n Array.isArray(componentData.children)\n ) {\n const processedNested = await processDocumentComponents(\n componentData.children,\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n standardOut.push({\n ...componentData,\n children: processedNested.standard,\n });\n preservedOut.push({\n ...componentData,\n children: processedNested.preserved,\n });\n } else {\n standardOut.push(componentData);\n preservedOut.push(componentData);\n }\n }\n }\n\n return { standard: standardOut, preserved: preservedOut };\n }\n\n /**\n * Add a custom component to the generator\n */\n function addComponent<TNewComponent extends CustomComponent<any, any, any>>(\n component: TNewComponent\n ): DocumentGeneratorBuilder<readonly [...TComponents, TNewComponent]> {\n if (!component.name) {\n throw new Error('Component name is required');\n }\n\n if (state.componentNames.has(component.name)) {\n throw new DuplicateComponentError(component.name);\n }\n\n // Create NEW immutable state\n const newComponentNames = new Set(state.componentNames);\n newComponentNames.add(component.name);\n\n const newState: BuilderState = {\n components: [...state.components, component],\n componentNames: newComponentNames,\n theme: state.theme,\n customThemes: state.customThemes,\n debug: state.debug,\n enableCache: state.enableCache,\n services: state.services,\n fonts: state.fonts,\n validation: state.validation,\n deterministic: state.deterministic,\n generatedAt: state.generatedAt,\n baseDir: state.baseDir,\n };\n\n // Return NEW builder with expanded type\n return createBuilderImpl<readonly [...TComponents, TNewComponent]>(\n newState\n );\n }\n\n /**\n * Resolve and validate the preserve set for a per-call options object.\n * Returns `undefined` when the caller did not opt in.\n * Throws `UnknownPreservedComponentError` when any listed name is not registered.\n */\n function resolvePreserveSet(\n options?: GenerateOptions\n ): ReadonlySet<string> | undefined {\n const list = options?.preserveCustomComponents;\n if (!list || list.length === 0) {\n return undefined;\n }\n const registered = new Set(state.componentNames);\n const unknown = list.filter((n) => !registered.has(n));\n if (unknown.length > 0) {\n throw new UnknownPreservedComponentError(\n unknown,\n Array.from(state.componentNames)\n );\n }\n return new Set(list);\n }\n\n /**\n * Shared front half of the pipeline: validate, resolve theme context,\n * expand custom components, normalize. Everything `standardDefinition`\n * needs and nothing more — fonts, structure, layout, rendering (and the\n * visual rasterization that rides on it) all happen after this point.\n */\n async function expandDocument(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<{\n modedRoot: ReportComponentDefinition;\n modedTheme: ThemeConfig;\n themeName: string;\n processed: {\n standard: ComponentDefinition[];\n preserved: ComponentDefinition[];\n };\n modedDoc: ReportComponentDefinition;\n warnings: GenerationWarning[];\n preserveSet: ReadonlySet<string> | undefined;\n }> {\n const preserveSet = resolvePreserveSet(options);\n\n // Cast to ReportComponentDefinition for internal processing. A root\n // written without a `props` key validates clean, so default it to `{}`\n // — otherwise every downstream `props.*` read throws. Only `undefined`\n // is defaulted, so a malformed `props: null` still reaches the\n // validator. Matches core/generator.ts.\n const rootIn = document as unknown as ReportComponentDefinition;\n const internalDocument: ReportComponentDefinition =\n rootIn.props === undefined ? { ...rootIn, props: {} } : rootIn;\n\n // Validate the document first (plugin-aware), unless disabled. Throwing\n // here stops a malformed document from silently building into a corrupt\n // or incomplete DOCX.\n const vOpts: GenerationValidationOptions = {\n ...state.validation,\n ...options?.validation,\n };\n if (vOpts.enabled !== false) {\n const result = validateDocument(\n internalDocument,\n state.components as unknown as CustomComponent<TSchema>[],\n { allowUnknownFields: vOpts.allowUnknownFields }\n );\n if (!result.valid) {\n throw new ComponentValidationError(\n (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: e.message,\n })),\n internalDocument\n );\n }\n }\n\n // Re-apply the same gate to the tree each custom component's render()\n // emits. The pre-expansion pass above only saw authored nodes, so a\n // standard component produced by a plugin would otherwise reach\n // standardDefinition unchecked. We validate the emitted nodes in their\n // pre-normalization form — exactly how authored nodes are validated —\n // by reusing the already-validated document props as a wrapper, so the\n // only new errors come from the emitted children. Undefined when\n // validation is disabled, which short-circuits the boundary check.\n const validateEmitted =\n vOpts.enabled === false\n ? undefined\n : (emitted: ComponentDefinition[], componentLabel: string) => {\n const result = validateDocument(\n { ...internalDocument, children: emitted },\n state.components as unknown as CustomComponent<TSchema>[],\n { allowUnknownFields: vOpts.allowUnknownFields }\n );\n if (!result.valid) {\n throw new ComponentValidationError(\n (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: `custom component '${componentLabel}' emitted invalid output — ${e.message}`,\n })),\n emitted\n );\n }\n };\n\n // Initialize warnings collector\n const warnings: GenerationWarning[] = [];\n\n // Props defaulting, theme resolution (customThemes → doc-named\n // built-in → constructor theme → built-in fallback, see\n // resolveDocumentTheme), in-document overrides, export-mode pre-pass and cache-key\n // scoping — shared with the core pipeline so the two cannot drift (see\n // core/generationContext.ts). The pre-pass runs BEFORE custom-component\n // expansion so components reading `theme.fonts.*` during render see the\n // substituted names, not the original non-safe ones.\n const {\n document: modedRoot,\n theme: modedTheme,\n themeName,\n } = resolveThemeContext(internalDocument, {\n customThemes: state.customThemes,\n fonts: state.fonts,\n warnings,\n resolveNamedTheme: resolveDocumentTheme,\n });\n\n // Process custom components to convert them to standard components.\n // Builds standard (fully expanded) and preserved (partial) trees in one pass.\n const processed = await processDocumentComponents(\n modedRoot.children || [],\n preserveSet,\n warnings,\n modedTheme,\n validateEmitted\n );\n\n // Create a new document definition with processed components\n const processedDocument: ReportComponentDefinition = {\n ...modedRoot,\n children: processed.standard,\n };\n\n // Normalize components (handle shorthand notations and nested structures)\n // We bypass JSON validation since we've already validated with custom schemas\n const [modedDoc] = normalizeDocument(processedDocument);\n\n return {\n modedRoot,\n modedTheme,\n themeName,\n processed,\n modedDoc,\n warnings,\n preserveSet,\n };\n }\n\n /**\n * Compute only the post-expansion standard definition. Runs validation,\n * theme resolution, custom-component expansion, and normalization — but\n * skips font resolution, layout, rendering, and packaging, so it never\n * touches external services (no visual rasterization, no chart export).\n * Orders of magnitude cheaper than `generate()` when you only need the\n * JSON tree.\n */\n async function expandStandardDefinition(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<StandardDefinitionResult> {\n try {\n const { modedDoc, warnings } = await expandDocument(document, options);\n return {\n standardDefinition: modedDoc,\n warnings: warnings.length > 0 ? warnings : null,\n };\n } catch (error) {\n if (state.debug) {\n console.error('Document expansion error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Generate a document\n */\n async function generate(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<GenerationResult<TComponents>> {\n try {\n const {\n modedRoot,\n modedTheme,\n themeName,\n processed,\n modedDoc,\n warnings,\n preserveSet,\n } = await expandDocument(document, options);\n\n // Resolve fonts (reads document + resolved theme). The helper fires\n // `fonts.onResolved` internally when a listener is registered\n // (LibreOffice preview stager). DOCX output itself never embeds\n // bytes; recipients rely on system-installed fonts.\n //\n // A `visual` rasterizes out-of-process via LibreOffice, which needs\n // real font files, so a visual-bearing document forces materialization\n // even with no listener registered — mirrors core/generator.ts.\n const hasVisual = collectVisualProps(modedDoc).length > 0;\n const resolvedFonts = await resolveDocumentFonts(\n modedDoc,\n modedTheme,\n state.fonts,\n warnings,\n hasVisual\n );\n // Gate on the ENCODED faces: safe-only fonts resolve to entries with\n // no sources and encode to nothing, and such a document must send no\n // `fonts` key at all (see core/generator.ts).\n const visualFonts = hasVisual\n ? toRasterizeFontFaces(resolvedFonts, warnings)\n : [];\n\n // Use the document generation pipeline directly\n const packageOptions = {\n deterministic: options?.deterministic ?? state.deterministic,\n generatedAt: options?.generatedAt ?? state.generatedAt,\n };\n const structure = await processDocument(\n modedDoc,\n modedTheme,\n themeName,\n resolveGenerationDate(packageOptions)\n );\n const layout = applyLayout(structure.sections, modedTheme, themeName);\n const generatedDocument = await renderDocument(structure, layout, {\n services: state.services,\n bypassCache: !state.enableCache,\n baseDir: options?.baseDir ?? state.baseDir,\n warnings,\n ...(visualFonts.length > 0 && { visualFonts }),\n });\n\n // Build preservedDefinition iff the caller opted in. Reuses the same\n // doc shell as standardDefinition but with partially-expanded children.\n // Not normalized — preserved subtrees are meant to be \"as authored\".\n const preservedDefinition = preserveSet\n ? ({\n ...modedRoot,\n children: processed.preserved,\n } as unknown as ExtendedReportComponent<TComponents>)\n : undefined;\n\n return {\n document: generatedDocument,\n warnings: warnings.length > 0 ? warnings : null,\n standardDefinition: modedDoc,\n preservedDefinition,\n };\n } catch (error) {\n if (state.debug) {\n console.error('Document generation error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Generate a document and return as buffer\n */\n async function generateBuffer(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<BufferGenerationResult<TComponents>> {\n const {\n document: doc,\n warnings,\n standardDefinition,\n preservedDefinition,\n } = await generate(document, options);\n const buffer = await packageDocument(doc, {\n deterministic: options?.deterministic ?? state.deterministic,\n generatedAt: options?.generatedAt ?? state.generatedAt,\n });\n return { buffer, warnings, standardDefinition, preservedDefinition };\n }\n\n /**\n * Generate a document and save to file\n */\n async function generateFile(\n document: ExtendedReportComponent<TComponents>,\n outputPath: string,\n options?: GenerateFileOptions\n ): Promise<FileGenerationResult<TComponents>> {\n const { buffer, warnings, standardDefinition, preservedDefinition } =\n await generateBuffer(document, options);\n const fs = await import('fs/promises');\n await fs.writeFile(outputPath, new Uint8Array(buffer));\n\n let preservedOutputPath: string | undefined;\n if (preservedDefinition !== undefined) {\n const path = await import('path');\n preservedOutputPath =\n options?.preservedOutputPath ??\n (() => {\n const ext = path.extname(outputPath);\n const base = ext ? outputPath.slice(0, -ext.length) : outputPath;\n return `${base}-preserved.json`;\n })();\n await fs.writeFile(\n preservedOutputPath,\n JSON.stringify(preservedDefinition, null, 2),\n 'utf8'\n );\n }\n\n return {\n warnings,\n standardDefinition,\n preservedDefinition,\n preservedOutputPath,\n };\n }\n\n /**\n * Get registered component names\n */\n function getComponentNames(): string[] {\n return Array.from(state.componentNames);\n }\n\n /**\n * Validate a document without generating it\n */\n function validate(\n document: ExtendedReportComponent<TComponents>\n ): ValidationResult {\n try {\n // Cast to ReportComponentDefinition for internal validation\n const internalDocument = document as unknown as ReportComponentDefinition;\n const result = validateDocument(\n internalDocument,\n state.components as unknown as CustomComponent<TSchema>[]\n );\n if (result.valid) {\n return { valid: true };\n }\n return {\n valid: false,\n errors: (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: e.message,\n })),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'document',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n }\n\n /**\n * @deprecated Read `standardDefinition` off `generate(...)` instead. This wrapper\n * runs the full generation pipeline (including `render()` for every custom)\n * just to surface the JSON tree, so calling it alongside `generate*` doubles\n * the work. Kept for backwards compatibility; will be removed in a future major.\n */\n async function getStandardComponentsDefinition(\n document: ExtendedReportComponent<TComponents>\n ): Promise<ReportComponentDefinition> {\n const { standardDefinition } = await generate(document);\n return standardDefinition;\n }\n\n /**\n * Generate the extended JSON schema for document validation\n */\n function generateSchema(includeStandardComponents = true): TSchema {\n return generatePluginDocumentSchema(\n state.components as unknown as CustomComponent<TSchema>[],\n includeStandardComponents\n );\n }\n\n /**\n * Export the extended JSON schema to a file\n */\n async function exportSchemaToFile(\n outputPath: string,\n options?: {\n includeStandardComponents?: boolean;\n prettyPrint?: boolean;\n }\n ): Promise<void> {\n await exportPluginSchema(\n state.components as unknown as CustomComponent<TSchema>[],\n outputPath,\n options\n );\n }\n\n // Return frozen builder object\n return Object.freeze({\n addComponent,\n generate,\n generateBuffer,\n generateFile,\n expandStandardDefinition,\n getComponentNames,\n validate,\n generateSchema,\n exportSchema: exportSchemaToFile,\n getStandardComponentsDefinition,\n });\n}\n\n/**\n * Create a document generator with chainable component registration.\n */\nexport function createDocumentGenerator(\n options: DocumentGeneratorOptions\n): DocumentGeneratorBuilder<readonly []> {\n const initialState: BuilderState = {\n components: [],\n componentNames: new Set(),\n theme: options.theme,\n customThemes: options.customThemes,\n debug: options.debug ?? false,\n enableCache: options.enableCache ?? false,\n services: options.services,\n fonts: options.fonts,\n validation: options.validation,\n deterministic: options.deterministic ?? true,\n generatedAt: options.generatedAt,\n baseDir: options.baseDir,\n };\n\n return createBuilderImpl<readonly []>(initialState);\n}\n","export { resolveComponentVersion } from '@json-to-office/shared/plugin';\n","import type { TSchema, Static } from '@sinclair/typebox';\nimport type { CustomComponent } from './createComponent';\nimport type { ReportComponentDefinition } from '../types';\nimport { resolveComponentVersion } from './version-resolver';\nimport {\n validateCustomComponentProps,\n ComponentValidationError,\n type ComponentValidationResult,\n} from '@json-to-office/shared/plugin';\nimport {\n validateDocument as validateDocumentUnified,\n type ValidationError,\n} from '@json-to-office/shared-docx/validation/unified';\nimport type { ValidationResult } from '@json-to-office/shared';\n\n// Re-export errors from shared\nexport {\n DuplicateComponentError,\n ComponentValidationError,\n UnknownPreservedComponentError,\n} from '@json-to-office/shared/plugin';\n\n/**\n * Validate a component props against a schema.\n * Accepts a narrower interface — only needs { propsSchema }.\n */\nexport function validateComponentProps<TPropsSchema extends TSchema>(\n schema: { propsSchema: TPropsSchema },\n props: unknown,\n componentName?: string,\n opts?: { clean?: boolean; applyDefaults?: boolean }\n): ComponentValidationResult<TPropsSchema> {\n // `clean` defaults to true so the render path (getValidatedProps) keeps\n // normalizing props (strip unknown + apply defaults). The validation path\n // passes `clean: false` to reject unknown keys instead of silently dropping\n // them — strict unless the caller opts into allowUnknownFields.\n return validateCustomComponentProps<TPropsSchema>(schema.propsSchema, props, {\n clean: opts?.clean ?? true,\n applyDefaults: opts?.applyDefaults ?? true,\n componentName,\n });\n}\n\n/**\n * Validate document and all custom components (version-aware).\n *\n * Standard components (paragraph, section, …) are validated against their\n * schemas via the unified validator, which is told the registered custom names\n * so it neither rejects them as unknown nor checks them against a standard\n * schema. Custom component props are then validated version-aware below. Errors\n * from both passes are merged so a single call reports the whole document.\n */\nexport function validateDocument(\n document: ReportComponentDefinition,\n customComponents: CustomComponent<any, any, any>[],\n options?: { allowUnknownFields?: boolean }\n): ValidationResult & { success: boolean } {\n const knownCustomNames = new Set(customComponents.map((c) => c.name));\n\n // Validate the standard-component structure (custom components deferred).\n const documentResult = validateDocumentUnified(document, {\n knownCustomNames,\n allowUnknownFields: options?.allowUnknownFields,\n });\n\n // Collect standard-structure errors, then append custom-component errors.\n const errors: ValidationError[] = [...(documentResult.errors || [])];\n\n function validateComponents(components: any[], pathPrefix = 'children') {\n components.forEach((componentData, index) => {\n const customComponent = customComponents.find(\n (cc) => cc.name === componentData.name\n );\n if (!customComponent) {\n return;\n }\n\n const versionEntry = resolveComponentVersion(\n customComponent.name,\n customComponent.versions,\n componentData.version\n );\n\n const validation = validateComponentProps(\n versionEntry,\n componentData.props,\n customComponent.name,\n // Reject unknown custom props unless the caller allows them.\n { clean: options?.allowUnknownFields === true }\n );\n\n if (!validation.valid && validation.errors) {\n const indexedErrors = validation.errors.map(\n (error: ValidationError) => ({\n ...error,\n path: `${pathPrefix}[${index}].${error.path}`,\n })\n );\n errors.push(...indexedErrors);\n }\n\n if (componentData.children && Array.isArray(componentData.children)) {\n validateComponents(\n componentData.children,\n `${pathPrefix}[${index}].children`\n );\n }\n });\n }\n\n if (document.children) {\n validateComponents(document.children);\n }\n\n return errors.length > 0\n ? { success: false, errors, valid: false }\n : { success: true, errors: [], valid: true };\n}\n\n/**\n * Validates component props and returns the typed props or throws.\n */\nexport function getValidatedProps<TPropsSchema extends TSchema>(\n schema: { propsSchema: TPropsSchema },\n props: unknown\n): Static<TPropsSchema> {\n const validation = validateComponentProps(schema, props);\n\n if (!validation.valid) {\n throw new ComponentValidationError(validation.errors || [], props);\n }\n\n return validation.data!;\n}\n\n// Re-export types\nexport type { ValidationError } from '@json-to-office/shared-docx/validation/unified';\nexport type { ComponentValidationResult } from '@json-to-office/shared/plugin';\n\nexport const cleanComponentProps = getValidatedProps;\n","import { Type, TSchema, TObject } from '@sinclair/typebox';\nimport { latestVersion } from '@json-to-office/shared-docx';\nimport type { CustomComponent } from './createComponent';\nimport {\n ReportPropsSchema,\n SectionPropsSchema,\n HeadingPropsSchema,\n ParagraphPropsSchema,\n ListPropsSchema,\n ImagePropsSchema,\n TablePropsSchema,\n} from '@json-to-office/shared-docx';\nimport { generateUnifiedDocumentSchema } from '@json-to-office/shared-docx/schemas/generator';\n\n// Schema cache to avoid regenerating identical schemas\nconst schemaCache = new Map<string, TSchema>();\n\n/**\n * Generate a JSON schema for plugin-enhanced documents at RUNTIME.\n *\n * Iterates each component's versions map to produce per-version\n * CustomComponentInfo entries for the unified schema generator.\n */\nexport function generatePluginDocumentSchema(\n customComponents: CustomComponent<any, any, any>[],\n includeStandardComponents = true\n): TSchema {\n // Produce per-version CustomComponentInfo entries for version-discriminated validation\n const customComponentInfos = customComponents.map((component) => {\n const versionKeys = Object.keys(component.versions);\n\n // Build per-version props entries\n const versionedProps = versionKeys.map((v) => ({\n version: v,\n propsSchema: component.versions[v].propsSchema,\n hasChildren: component.versions[v].hasChildren === true,\n description: component.versions[v].description,\n }));\n\n // propsSchema is used as fallback label — use latest version's props\n const latestKey = versionKeys.reduce((a, b) => (a > b ? a : b));\n\n return {\n name: component.name,\n propsSchema: component.versions[latestKey].propsSchema,\n hasChildren: versionKeys.some(\n (v) => component.versions[v].hasChildren === true\n ),\n versionedProps,\n };\n });\n\n return generateUnifiedDocumentSchema({\n includeStandardComponents: includeStandardComponents,\n includeTheme: true,\n customComponents: customComponentInfos,\n title: 'Plugin Document Definition',\n description: 'Document definition with custom plugin components',\n });\n}\n\n/**\n * Create a union type from an array of schemas\n */\nexport function createUnionSchema(schemas: TSchema[]): TSchema {\n if (schemas.length === 0) {\n return Type.Any();\n }\n if (schemas.length === 1) {\n return schemas[0];\n }\n return Type.Union(schemas as [TSchema, TSchema, ...TSchema[]]);\n}\n\n/**\n * Export a plugin-enhanced JSON schema to a file at RUNTIME\n */\nexport async function exportPluginSchema(\n customComponents: CustomComponent<any, any, any>[],\n outputPath: string,\n options: {\n includeStandardComponents?: boolean;\n prettyPrint?: boolean;\n } = {}\n): Promise<void> {\n const { includeStandardComponents = true, prettyPrint = true } = options;\n\n const { convertToJsonSchema, exportSchemaToFile } = await import(\n '@json-to-office/shared-docx/schemas/export'\n );\n\n const schema = generatePluginDocumentSchema(\n customComponents,\n includeStandardComponents\n );\n\n const jsonSchema = convertToJsonSchema(schema, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n });\n\n await exportSchemaToFile(jsonSchema, outputPath, { prettyPrint });\n}\n\n/**\n * Generate schemas for individual custom components (version-aware).\n * Produces per-version schemas keyed as `name` or `name@version`.\n */\nexport function generateComponentSchemas(\n customComponents: CustomComponent<any, any, any>[]\n): Record<string, TSchema> {\n const schemas: Record<string, TSchema> = {};\n\n for (const component of customComponents) {\n const versionKeys = Object.keys(component.versions);\n const latest = latestVersion(versionKeys);\n\n for (const v of versionKeys) {\n const entry = component.versions[v];\n const cacheKey = `component_${component.name}@${v}`;\n\n if (schemaCache.has(cacheKey)) {\n schemas[`${component.name}@${v}`] = schemaCache.get(cacheKey)!;\n } else {\n const schemaObj = entry.propsSchema as TObject;\n const properties = schemaObj.properties || {};\n\n const componentSchemaProps: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n version: Type.Optional(Type.Literal(v)),\n id: Type.Optional(Type.String()),\n ...properties,\n };\n\n if (entry.hasChildren) {\n componentSchemaProps.children = Type.Optional(Type.Array(Type.Any()));\n }\n\n const componentSchema = Type.Object(componentSchemaProps);\n schemaCache.set(cacheKey, componentSchema);\n schemas[`${component.name}@${v}`] = componentSchema;\n }\n }\n\n // Also add a \"default\" entry keyed by name (uses latest)\n const latestEntry = component.versions[latest];\n const defaultCacheKey = `component_${component.name}_default`;\n\n if (schemaCache.has(defaultCacheKey)) {\n schemas[component.name] = schemaCache.get(defaultCacheKey)!;\n } else {\n const schemaObj = latestEntry.propsSchema as TObject;\n const properties = schemaObj.properties || {};\n\n const componentSchemaProps: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n id: Type.Optional(Type.String()),\n ...properties,\n };\n\n if (latestEntry.hasChildren) {\n componentSchemaProps.children = Type.Optional(Type.Array(Type.Any()));\n }\n\n const componentSchema = Type.Object(componentSchemaProps);\n schemaCache.set(defaultCacheKey, componentSchema);\n schemas[component.name] = componentSchema;\n }\n }\n\n return schemas;\n}\n\n/**\n * Merge custom component schemas with standard schemas\n */\nexport function mergeSchemas(\n customComponents: CustomComponent<any, any, any>[],\n standardSchemas?: Record<string, TSchema>\n): Record<string, TSchema> {\n const customSchemas = generateComponentSchemas(customComponents);\n\n if (standardSchemas) {\n return {\n ...standardSchemas,\n ...customSchemas,\n };\n }\n\n const defaultStandardSchemas: Record<string, TSchema> = {\n docx: Type.Object({\n name: Type.Literal('docx'),\n id: Type.Optional(Type.String()),\n props: ReportPropsSchema,\n children: Type.Optional(Type.Array(Type.Any())),\n }),\n section: Type.Object({\n name: Type.Literal('section'),\n id: Type.Optional(Type.String()),\n props: SectionPropsSchema,\n children: Type.Optional(Type.Array(Type.Any())),\n }),\n heading: Type.Object({\n name: Type.Literal('heading'),\n id: Type.Optional(Type.String()),\n props: HeadingPropsSchema,\n }),\n text: Type.Object({\n name: Type.Literal('text'),\n id: Type.Optional(Type.String()),\n props: ParagraphPropsSchema,\n }),\n list: Type.Object({\n name: Type.Literal('list'),\n id: Type.Optional(Type.String()),\n props: ListPropsSchema,\n }),\n image: Type.Object({\n name: Type.Literal('image'),\n id: Type.Optional(Type.String()),\n props: ImagePropsSchema,\n }),\n table: Type.Object({\n name: Type.Literal('table'),\n id: Type.Optional(Type.String()),\n props: TablePropsSchema,\n }),\n };\n\n return {\n ...defaultStandardSchemas,\n ...customSchemas,\n };\n}\n"],"mappings":"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","names":["themes","path","fs","path","isValidThemeConfig","resolve","mergeWithDefaults","mergeWithDefaults","Paragraph","TextRun","AlignmentType","BookmarkStart","BookmarkEnd","path","createHash","TextRun","TextRun","AsyncLocalStorage","format","TextRun","createTextRunsWithNewlines","TextRun","AsyncLocalStorage","AsyncLocalStorage","TextRun","createHash","Paragraph","TextRun","AlignmentType","BorderStyle","PageNumber","AsyncLocalStorage","TextRun","TextRun","AsyncLocalStorage","createState","TextRun","AsyncLocalStorage","TextRun","Paragraph","TextRun","AsyncLocalStorage","createState","bodyParagraphs","Paragraph","TextRun","AsyncLocalStorage","Paragraph","TextRun","path","getAvailableWidthTwips","getPageWidthTwips","getAvailableHeightTwips","getPageHeightTwips","mapFloatingOptions","Paragraph","AlignmentType","BorderStyle","TextRun","relativeLengthToTwips","AlignmentType","AsyncLocalStorage","format","getAlignment","format","getAlignment","AlignmentType","AsyncLocalStorage","text","format","Paragraph","Table","TableRow","TableCell","WidthType","TableLayoutType","BorderStyle","convertBorders","Paragraph","Paragraph","convertBorders","cellChildren","styleCfg","cellOpts","row","TableRow","TableCell","table","Table","TableLayoutType","WidthType","Paragraph","config","Paragraph","BookmarkStart","BookmarkEnd","AsyncLocalStorage","createState","Paragraph","BookmarkStart","BookmarkEnd","Paragraph","Table","TableRow","TableCell","WidthType","BorderStyle","VerticalAlign","TableLayoutType","Paragraph","TableCell","WidthType","VerticalAlign","BorderStyle","TableRow","Table","TableLayoutType","Paragraph","AlignmentType","TextRun","Paragraph","TextRun","AlignmentType","createHash","createHash","clampVisualDpi","DEFAULT_VISUAL_DPI","resolve","serverUrl","clampVisualDpi","DEFAULT_VISUAL_DPI","format","MAX_HEADING_LEVEL","getAlignment","AlignmentType","Paragraph","TextRun","BookmarkStart","BookmarkEnd","AdmZip","AdmZip","coreProperties","fs","resolve","isAbsolute","isAbsolute","resolve","fs","resolve","clampVisualDpi","DEFAULT_VISUAL_DPI","clampVisualDpi","DEFAULT_VISUAL_DPI","fs","path","fileURLToPath","path","fs","toRasterizeFontFaces","ComponentValidationError","UnknownPreservedComponentError","Type","Type","ComponentValidationError","UnknownPreservedComponentError","toRasterizeFontFaces","fs","path"]}
|
|
1
|
+
{"version":3,"sources":["../src/themes/defaults.ts","../src/styles/utils/colorUtils.ts","../src/utils/generationContext.ts","../src/templates/themes/minimal.docx.theme.json","../src/templates/themes/corporate.docx.theme.json","../src/templates/themes/modern.docx.theme.json","../src/templates/themes/apex.docx.theme.json","../src/templates/themes/devportal.docx.theme.json","../src/templates/themes/index.ts","../src/styles/utils/styleHelpers.ts","../src/styles/utils/layoutUtils.ts","../src/themes/json/parser.ts","../src/themes/json/validator.ts","../src/themes/json/loader.ts","../src/themes/json/index.ts","../src/styles/index.ts","../src/utils/widthUtils.ts","../src/utils/imageUtils.ts","../src/ir/types.ts","../src/ir/units.ts","../src/renderers/docxjs/emit.ts","../src/renderers/docxjs/styles.ts","../src/ir/features.ts","../src/utils/packageDocument.ts","../src/utils/fixFloatingImageIds.ts","../src/renderers/docxjs/index.ts","../src/renderers/office-open/emit.ts","../src/renderers/office-open/styles.ts","../src/renderers/office-open/index.ts","../src/core/generator.ts","../src/types/index.ts","../src/core/generateFromIr.ts","../src/core/fontResolution.ts","../src/core/prerasterizeVisuals.ts","../src/components/visual.ts","../src/utils/environment.ts","../src/utils/serviceClient.ts","../src/utils/promiseLimiter.ts","../src/json/normalizer.ts","../src/core/desugarExternals.ts","../src/components/highcharts.ts","../src/core/componentTransform.ts","../src/core/imageResources.ts","../src/ir/compiler.ts","../src/styles/themeToStyles.ts","../src/core/sectionOrdinals.ts","../src/utils/bookmarkRegistry.ts","../src/utils/listLevels.ts","../src/core/tableModel.ts","../src/utils/revisionUtils.ts","../src/utils/commentRegistry.ts","../src/utils/numberingConfig.ts","../src/utils/unicode.ts","../src/core/collectTocHeadings.ts","../src/core/sectionBookmarks.ts","../src/utils/numberFormatting.ts","../src/core/tocField.ts","../src/core/markdownList.ts","../src/ir/inline.ts","../src/renderers/registry.ts","../src/renderers/types.ts","../src/core/generationContext.ts","../src/styles/theme-resolver.ts","../src/themes/overrides.ts","../src/core/layout.ts","../src/utils/formatters.ts","../src/styles/utils/componentDefaults.ts","../src/styles/utils/resolveComponentTree.ts","../src/core/structure.ts","../src/json/parser.ts","../src/json/filesystem.ts","../src/core/flattenVisuals.ts","../src/utils/warningsDocument.ts","../src/index.ts","../src/templates/documents/index.ts","../src/utils/exampleRunner.ts","../src/components/text-space-after.ts","../src/plugin/createComponent.ts","../src/plugin/createDocumentGenerator.ts","../src/plugin/version-resolver.ts","../src/plugin/validation.ts","../src/plugin/schema.ts"],"sourcesContent":["/**\n * Default theme values and utilities for handling optional theme properties\n */\n\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\n\n/**\n * Default colors for themes\n */\nexport const DEFAULT_COLORS = {\n primary: '#000000',\n secondary: '#666666',\n accent: '#0066CC',\n text: '#000000',\n background: '#FFFFFF',\n border: '#CCCCCC',\n // Semantic colors\n textPrimary: '#000000',\n textSecondary: '#666666',\n textMuted: '#999999',\n borderPrimary: '#CCCCCC',\n borderSecondary: '#E5E5E5',\n backgroundPrimary: '#FFFFFF',\n backgroundSecondary: '#F5F5F5',\n};\n\n/**\n * Default fonts for themes\n */\nexport const DEFAULT_FONTS = {\n heading: { family: 'Arial', size: 20 },\n body: { family: 'Arial', size: 11 },\n mono: { family: 'Courier New', size: 10 },\n light: { family: 'Arial', size: 24 },\n};\n\n/**\n * Default styles for themes\n */\nexport const DEFAULT_STYLES = {\n normal: {\n font: 'body' as const,\n size: 11,\n color: '#000000',\n alignment: 'left' as const,\n lineSpacing: {\n type: 'single' as const,\n value: 1,\n },\n spacing: {\n after: 6,\n },\n },\n heading1: {\n font: 'heading' as const,\n size: 24,\n color: '#000000',\n bold: true,\n spacing: {\n before: 12,\n after: 12,\n },\n },\n heading2: {\n font: 'heading' as const,\n size: 20,\n color: '#000000',\n bold: true,\n spacing: {\n before: 10,\n after: 10,\n },\n },\n heading3: {\n font: 'heading' as const,\n size: 16,\n color: '#000000',\n bold: true,\n spacing: {\n before: 8,\n after: 8,\n },\n },\n heading4: {\n font: 'heading' as const,\n size: 14,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n heading5: {\n font: 'heading' as const,\n size: 12,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n heading6: {\n font: 'heading' as const,\n size: 11,\n color: '#000000',\n bold: true,\n spacing: {\n before: 6,\n after: 6,\n },\n },\n};\n\n/**\n * Default page settings\n */\nexport const DEFAULT_PAGE = {\n size: 'LETTER' as const,\n margins: {\n top: 720,\n bottom: 720,\n left: 720,\n right: 720,\n header: 360,\n footer: 360,\n gutter: 0,\n },\n};\n\n/**\n * Ensures theme has all required properties with defaults\n */\nexport function ensureThemeDefaults(\n theme: Partial<ThemeConfigJson>\n): ThemeConfigJson {\n return {\n $schema: theme.$schema,\n name: theme.name || 'default',\n displayName: theme.displayName || 'Default Theme',\n description: theme.description || 'Default theme configuration',\n version: theme.version || '1.0.0',\n colors: {\n ...DEFAULT_COLORS,\n ...(theme.colors || {}),\n },\n fonts: {\n heading: { ...DEFAULT_FONTS.heading, ...(theme.fonts?.heading || {}) },\n body: { ...DEFAULT_FONTS.body, ...(theme.fonts?.body || {}) },\n mono: { ...DEFAULT_FONTS.mono, ...(theme.fonts?.mono || {}) },\n light: { ...DEFAULT_FONTS.light, ...(theme.fonts?.light || {}) },\n },\n page: {\n ...DEFAULT_PAGE,\n ...(theme.page || {}),\n margins: {\n ...DEFAULT_PAGE.margins,\n ...(theme.page?.margins || {}),\n },\n },\n styles: theme.styles,\n componentDefaults: theme.componentDefaults,\n };\n}\n\n/**\n * Type guard to check if a theme has all required properties\n */\nexport function isCompleteTheme(theme: unknown): theme is ThemeConfigJson {\n const t = theme as Record<string, unknown>;\n return (\n t &&\n typeof t === 'object' &&\n !!t.colors &&\n !!t.fonts &&\n !!t.page &&\n typeof t.name === 'string' &&\n typeof t.displayName === 'string' &&\n typeof t.description === 'string' &&\n typeof t.version === 'string'\n );\n}\n\n/**\n * Safe getter for theme colors with defaults\n */\nexport function getThemeColors(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_COLORS,\n ...(theme.colors || {}),\n };\n}\n\n/**\n * Safe getter for theme fonts with defaults\n */\nexport function getThemeFonts(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_FONTS,\n ...(theme.fonts || {}),\n };\n}\n\n/**\n * Safe getter for theme styles with defaults\n */\nexport function getThemeStyles(theme: Partial<ThemeConfigJson>) {\n return {\n ...DEFAULT_STYLES,\n ...(theme.styles || {}),\n };\n}\n\n/**\n * Safe getter for normal style with defaults\n */\nexport function getNormalStyle(theme: Partial<ThemeConfigJson>) {\n const styles = getThemeStyles(theme);\n return {\n ...DEFAULT_STYLES.normal,\n ...(styles.normal || {}),\n };\n}\n","import { ThemeConfig } from '../index';\nimport { getThemeColors } from '../../themes/defaults';\n\nexport type ColorName = keyof ReturnType<typeof getThemeColors>;\n\n// Union type for all valid color names\nexport type ValidColorName =\n | 'primary'\n | 'secondary'\n | 'accent'\n | 'text'\n | 'background'\n | 'textPrimary'\n | 'textSecondary'\n | 'textMuted'\n | 'borderPrimary'\n | 'borderSecondary'\n | 'backgroundPrimary'\n | 'backgroundSecondary';\n\n// Type for color value that can be either a hex string or a color name\nexport type ColorValue = string; // Can be hex color or color name\n\n/**\n * Resolves a color value, which can be either a hex color string or a color name reference\n * @param colorValue - Either a hex color (e.g., '#000000') or a color name (e.g., 'primary')\n * @param theme - The theme configuration containing color definitions\n * @returns The resolved hex color value (6-character hex without #)\n * @throws Error if the color value is invalid\n */\nexport function resolveColor(\n colorValue: ColorValue,\n theme: ThemeConfig\n): string {\n // Check if it's a hex color with # prefix\n if (colorValue.startsWith('#')) {\n const hexValue = colorValue.slice(1);\n if (/^[0-9A-Fa-f]{6}$/.test(hexValue)) {\n return hexValue.toUpperCase(); // Normalize to uppercase\n }\n // Invalid hex format\n throw new Error(\n `Invalid hex color: \"${colorValue}\". Hex colors must be in format #RRGGBB (e.g., \"#000000\").`\n );\n }\n\n // If it's a color name, resolve it from the theme. Optional slots\n // (accent4-6) may be present-but-undefined, which counts as unset.\n const colors = getThemeColors(theme);\n const resolvedColor = colors[colorValue as ColorName];\n if (typeof resolvedColor === 'string') {\n // Recursively resolve in case the theme color is also a reference\n return resolveColor(resolvedColor, theme);\n }\n\n // Bare 6-digit hex, e.g. \"F0FDF4\". HexColorSchema admits it through the\n // theme-name branch, so rejecting it here would validate a document and then\n // throw while rendering it. Table cells and the chart palette already accept\n // this form; no theme color name is six hex characters, so there is no\n // ambiguity with a real token.\n if (/^[0-9A-Fa-f]{6}$/.test(colorValue)) {\n return colorValue.toUpperCase();\n }\n\n // Strict validation - throw error for invalid colors\n throw new Error(\n `Invalid color value: \"${colorValue}\". Must be a hex color with # prefix (e.g., \"#000000\") or a valid theme color name.`\n );\n}\n\n/**\n * Validates if a color name is set in the theme\n * @param colorName - The color name to validate\n * @param theme - The theme configuration\n * @returns True if the color name resolves to a value. A present-but-undefined\n * optional slot counts as unset, matching what `resolveColor` accepts.\n */\nexport function isValidColorName(\n colorName: string,\n theme: ThemeConfig\n): boolean {\n const colors = getThemeColors(theme);\n if (typeof colors[colorName as ColorName] !== 'string') return false;\n // Follow the reference chain: a token whose value names an unset slot is not\n // usable, so reporting it as valid would hand a caller a color that throws.\n try {\n resolveColor(colorName as ColorValue, theme);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Gets all available color names from a theme\n * @param theme - The theme configuration\n * @returns Array of valid color names, excluding present-but-undefined slots\n */\nexport function getAvailableColorNames(theme: ThemeConfig): string[] {\n const colors = getThemeColors(theme);\n return Object.keys(colors).filter((name) => isValidColorName(name, theme));\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { isAbsolute, resolve } from 'node:path';\nimport type { GenerationWarning } from '@json-to-office/shared';\n\nconst generationDateStorage = new AsyncLocalStorage<Date>();\n\n/** Scope render-time values without leaking them across concurrent documents. */\nexport function runWithGenerationDate<T>(date: Date, callback: () => T): T {\n return generationDateStorage.run(date, callback);\n}\n\n/** Current document date, falling back to the wall clock outside generation. */\nexport function getGenerationDate(): Date {\n return generationDateStorage.getStore() ?? new Date();\n}\n\nconst baseDirStorage = new AsyncLocalStorage<string>();\n\n/**\n * Scope the document base directory for a generation run, so relative asset\n * paths (`image.props.path` et al.) resolve against the document's own\n * location rather than `process.cwd()` (#142). No baseDir → plain callback,\n * preserving the historical cwd-relative behavior.\n */\nexport function runWithBaseDir<T>(\n baseDir: string | undefined,\n callback: () => T\n): T {\n return baseDir === undefined\n ? callback()\n : baseDirStorage.run(resolve(baseDir), callback);\n}\n\n/** The active document base directory, if a generation scope set one. */\nexport function getBaseDir(): string | undefined {\n return baseDirStorage.getStore();\n}\n\n/**\n * Resolve a relative file path against the active base directory. Absolute\n * paths pass through; with no active baseDir the path is returned as-is,\n * which downstream `fs` calls resolve against cwd — the legacy behavior.\n */\nexport function resolveFromBaseDir(filePath: string): string {\n const base = baseDirStorage.getStore();\n if (!base || isAbsolute(filePath)) return filePath;\n return resolve(base, filePath);\n}\n\nconst warningsStorage = new AsyncLocalStorage<GenerationWarning[]>();\n\n/**\n * Scope a warning collector for a render, so leaf utilities can report\n * without every intermediate signature carrying a sink. No collector → plain\n * callback, and `reportWarning` falls back to `console.warn` as before.\n */\nexport function runWithWarnings<T>(\n warnings: GenerationWarning[] | undefined,\n callback: () => T\n): T {\n return warnings === undefined\n ? callback()\n : warningsStorage.run(warnings, callback);\n}\n\n/** Record a render-time warning against the active collector, if any. */\nexport function reportWarning(\n component: string,\n code: string,\n message: string,\n context?: Record<string, unknown>\n): void {\n const warnings = warningsStorage.getStore();\n if (warnings) {\n warnings.push({\n component,\n message,\n severity: 'warning',\n context: { code, ...context },\n });\n return;\n }\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] [${code}] ${message}`);\n}\n","{\n \"$schema\": \"../../../../shared/json-schemas/theme.schema.json\",\n \"name\": \"minimal\",\n \"displayName\": \"Minimal Clean\",\n \"description\": \"A clean, minimalist theme focused on readability and elegant simplicity\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#000000\",\n \"secondary\": \"#666666\",\n \"accent\": \"#2c3e50\",\n \"background\": \"#ffffff\",\n \"text\": \"#2c2c2c\",\n \"border\": \"#f0f0f0\",\n \"textPrimary\": \"#000000\",\n \"textSecondary\": \"#4a4a4a\",\n \"textMuted\": \"#999999\",\n \"borderPrimary\": \"#e0e0e0\",\n \"borderSecondary\": \"#f5f5f5\",\n \"backgroundPrimary\": \"#ffffff\",\n \"backgroundSecondary\": \"#fafafa\"\n },\n \"fonts\": {\n \"heading\": {\n \"family\": \"Arial\",\n \"size\": 24\n },\n \"body\": {\n \"family\": \"Arial\",\n \"size\": 11\n },\n \"mono\": {\n \"family\": \"Menlo\",\n \"size\": 10\n },\n \"light\": {\n \"family\": \"Arial\",\n \"size\": 24\n }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#000000\",\n \"lineSpacing\": {\n \"type\": \"multiple\",\n \"value\": 1.5\n },\n \"alignment\": \"justify\",\n \"spacing\": {\n \"after\": 9\n }\n },\n \"heading1\": {\n \"font\": \"light\",\n \"size\": 24,\n \"bold\": false,\n \"color\": \"#000000\",\n \"spacing\": {\n \"before\": 18,\n \"after\": 12\n },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"characterSpacing\": {\n \"type\": \"expanded\",\n \"value\": 1.2\n }\n },\n \"heading2\": {\n \"font\": \"light\",\n \"size\": 20,\n \"bold\": false,\n \"color\": \"#000000\",\n \"spacing\": {\n \"before\": 12,\n \"after\": 9\n },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"characterSpacing\": {\n \"type\": \"expanded\",\n \"value\": 0.8\n }\n },\n \"heading3\": {\n \"font\": \"heading\",\n \"size\": 16,\n \"bold\": false,\n \"color\": \"#2c2c2c\",\n \"spacing\": {\n \"before\": 9,\n \"after\": 6\n },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading4\": {\n \"font\": \"heading\",\n \"size\": 14,\n \"bold\": true,\n \"color\": \"#4a4a4a\",\n \"spacing\": {\n \"before\": 6,\n \"after\": 4\n },\n \"keepNext\": true\n },\n \"heading5\": {\n \"font\": \"heading\",\n \"size\": 12,\n \"bold\": false,\n \"italic\": true,\n \"color\": \"#666666\",\n \"spacing\": {\n \"before\": 4,\n \"after\": 3\n }\n },\n \"heading6\": {\n \"font\": \"light\",\n \"size\": 11,\n \"bold\": false,\n \"color\": \"#999999\",\n \"spacing\": {\n \"before\": 3,\n \"after\": 2\n }\n },\n \"title\": {\n \"font\": \"light\",\n \"bold\": false,\n \"color\": \"#000000\",\n \"alignment\": \"left\",\n \"spacing\": {\n \"before\": 0,\n \"after\": 24\n },\n \"characterSpacing\": {\n \"type\": \"condensed\",\n \"value\": 20\n }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"#666666\",\n \"alignment\": \"left\",\n \"spacing\": {\n \"before\": 0,\n \"after\": 18\n }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#f0f0f0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"•\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"left\"\n },\n \"statistic\": {\n \"alignment\": \"left\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"corporate\",\n \"displayName\": \"Corporate Professional\",\n \"description\": \"A polished corporate theme with blue accents and structured typography\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#1a365d\",\n \"secondary\": \"#2D3748\",\n \"accent\": \"#3182CE\",\n \"text\": \"#1A202C\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#1A202C\",\n \"textSecondary\": \"#4A5568\",\n \"textMuted\": \"#A0AEC0\",\n \"borderPrimary\": \"#CBD5E0\",\n \"borderSecondary\": \"#E2E8F0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F7FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Georgia\", \"size\": 26 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Georgia\", \"size\": 26 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1200,\n \"right\": 1200,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#1A202C\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.4 },\n \"alignment\": \"justify\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 26,\n \"bold\": false,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 2,\n \"color\": \"primary\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": false,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"light\",\n \"size\": 32,\n \"bold\": false,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 18 }\n },\n \"subtitle\": {\n \"font\": \"body\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2022\",\n \"indent\": 3\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"modern\",\n \"displayName\": \"Modern Clean\",\n \"description\": \"A contemporary theme with vibrant accents and generous whitespace\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#6D28D9\",\n \"secondary\": \"#1E293B\",\n \"accent\": \"#0891B2\",\n \"text\": \"#0F172A\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#0F172A\",\n \"textSecondary\": \"#475569\",\n \"textMuted\": \"#94A3B8\",\n \"borderPrimary\": \"#CBD5E1\",\n \"borderSecondary\": \"#E2E8F0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F8FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Helvetica\", \"size\": 28 },\n \"body\": { \"family\": \"Helvetica\", \"size\": 11 },\n \"mono\": { \"family\": \"Menlo\", \"size\": 10 },\n \"light\": { \"family\": \"Helvetica\", \"size\": 28 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"#0F172A\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.5 },\n \"alignment\": \"left\",\n \"spacing\": { \"after\": 10 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 28,\n \"bold\": true,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 14 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 20,\n \"bold\": true,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 10 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 14,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"heading\",\n \"size\": 36,\n \"bold\": true,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 12 }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 18,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2013\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"apex\",\n \"displayName\": \"Apex Consulting\",\n \"description\": \"A premium consulting theme with deep navy, warm amber accents, and authoritative typography\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#0C2340\",\n \"secondary\": \"#1B3A5C\",\n \"accent\": \"#D4A843\",\n \"text\": \"#1A1A2E\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#D6DAE0\",\n \"textPrimary\": \"#1A1A2E\",\n \"textSecondary\": \"#4A5066\",\n \"textMuted\": \"#8B91A0\",\n \"borderPrimary\": \"#B8BCC6\",\n \"borderSecondary\": \"#E8EAF0\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F4F5F8\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Georgia\", \"size\": 26 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Georgia\", \"size\": 26 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1200,\n \"right\": 1200,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"textPrimary\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.4 },\n \"alignment\": \"justify\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 26,\n \"bold\": false,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 2,\n \"color\": \"accent\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": false,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"title\": {\n \"font\": \"light\",\n \"size\": 36,\n \"bold\": false,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 18 }\n },\n \"subtitle\": {\n \"font\": \"body\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#D6DAE0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2022\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","{\n \"name\": \"devportal\",\n \"displayName\": \"Developer Portal\",\n \"description\": \"A modern developer-focused theme with cool grays, teal accents, and monospace code styling\",\n \"version\": \"2.0.0\",\n \"colors\": {\n \"primary\": \"#0F172A\",\n \"secondary\": \"#334155\",\n \"accent\": \"#0D9488\",\n \"text\": \"#0F172A\",\n \"background\": \"#FFFFFF\",\n \"border\": \"#E2E8F0\",\n \"textPrimary\": \"#0F172A\",\n \"textSecondary\": \"#475569\",\n \"textMuted\": \"#94A3B8\",\n \"borderPrimary\": \"#CBD5E1\",\n \"borderSecondary\": \"#F1F5F9\",\n \"backgroundPrimary\": \"#FFFFFF\",\n \"backgroundSecondary\": \"#F8FAFC\"\n },\n \"fonts\": {\n \"heading\": { \"family\": \"Helvetica\", \"size\": 24 },\n \"body\": { \"family\": \"Calibri\", \"size\": 11 },\n \"mono\": { \"family\": \"Consolas\", \"size\": 10 },\n \"light\": { \"family\": \"Helvetica\", \"size\": 24 }\n },\n \"page\": {\n \"size\": \"A4\",\n \"margins\": {\n \"top\": 1440,\n \"bottom\": 1440,\n \"left\": 1080,\n \"right\": 1080,\n \"header\": 720,\n \"footer\": 720,\n \"gutter\": 0\n }\n },\n \"styles\": {\n \"normal\": {\n \"font\": \"body\",\n \"color\": \"textPrimary\",\n \"lineSpacing\": { \"type\": \"multiple\", \"value\": 1.5 },\n \"alignment\": \"left\",\n \"spacing\": { \"after\": 8 }\n },\n \"heading1\": {\n \"font\": \"heading\",\n \"size\": 24,\n \"bold\": true,\n \"color\": \"primary\",\n \"spacing\": { \"before\": 24, \"after\": 12 },\n \"keepNext\": true,\n \"alignment\": \"left\",\n \"borders\": {\n \"bottom\": {\n \"style\": \"single\",\n \"size\": 1,\n \"color\": \"accent\",\n \"space\": 6\n }\n }\n },\n \"heading2\": {\n \"font\": \"heading\",\n \"size\": 18,\n \"bold\": true,\n \"color\": \"secondary\",\n \"spacing\": { \"before\": 18, \"after\": 8 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading3\": {\n \"font\": \"body\",\n \"size\": 13,\n \"bold\": true,\n \"color\": \"accent\",\n \"spacing\": { \"before\": 12, \"after\": 6 },\n \"keepNext\": true,\n \"alignment\": \"left\"\n },\n \"heading4\": {\n \"font\": \"body\",\n \"size\": 12,\n \"bold\": true,\n \"color\": \"textSecondary\",\n \"spacing\": { \"before\": 8, \"after\": 4 },\n \"keepNext\": true\n },\n \"title\": {\n \"font\": \"heading\",\n \"size\": 32,\n \"bold\": true,\n \"color\": \"primary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 12 }\n },\n \"subtitle\": {\n \"font\": \"light\",\n \"size\": 16,\n \"italic\": false,\n \"color\": \"textSecondary\",\n \"alignment\": \"left\",\n \"spacing\": { \"before\": 0, \"after\": 24 }\n }\n },\n \"componentDefaults\": {\n \"table\": {\n \"borderColor\": \"#E2E8F0\"\n },\n \"list\": {\n \"format\": \"bullet\",\n \"bullet\": \"\\u2013\",\n \"indent\": 3\n },\n \"image\": {\n \"alignment\": \"center\"\n },\n \"statistic\": {\n \"alignment\": \"center\"\n },\n \"section\": {\n \"pageBreak\": false\n }\n }\n}\n","/**\n * JSON-based themes registry\n * This file provides a unified interface to JSON themes\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport {\n isValidThemeConfig,\n type ThemeConfigJson,\n} from '@json-to-office/shared-docx';\nimport { ensureThemeDefaults } from '../../themes/defaults';\n\n// Import theme JSON files directly. Every bundled theme is imported here, so\n// which themes exist is decided by code, not by whether `dist/` happens to be\n// built and fresh — `apex` and `devportal` used to be reachable only through\n// the filesystem scan below, which meant a stale build silently served the old\n// copy and a missing one degraded to `minimal`.\nimport minimalThemeJson from './minimal.docx.theme.json';\nimport corporateThemeJson from './corporate.docx.theme.json';\nimport modernThemeJson from './modern.docx.theme.json';\nimport apexThemeJson from './apex.docx.theme.json';\nimport devportalThemeJson from './devportal.docx.theme.json';\n\n/**\n * Registry of available themes loaded from JSON files\n */\nlet _themesCache: Record<string, ThemeConfigJson> | null = null;\n\nfunction loadThemesFromJson(): Record<string, ThemeConfigJson> {\n if (_themesCache) {\n return _themesCache;\n }\n\n // Build themes from imported JSON files\n const themes: Record<string, ThemeConfigJson> = {\n minimal: ensureThemeDefaults(minimalThemeJson as ThemeConfigJson),\n corporate: ensureThemeDefaults(corporateThemeJson as ThemeConfigJson),\n modern: ensureThemeDefaults(modernThemeJson as ThemeConfigJson),\n apex: ensureThemeDefaults(apexThemeJson as ThemeConfigJson),\n devportal: ensureThemeDefaults(devportalThemeJson as ThemeConfigJson),\n };\n\n // Also try to load from file system for runtime additions (if available)\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n const themesDir = path.join(__dirname, '../../../dist/templates/themes');\n\n if (fs.existsSync(themesDir)) {\n const themeFiles = fs\n .readdirSync(themesDir)\n .filter((file) => file.endsWith('.docx.theme.json'))\n .map((file) => path.basename(file, '.docx.theme.json'));\n\n for (const themeName of themeFiles) {\n if (!themes[themeName]) {\n try {\n const filePath = path.join(\n themesDir,\n `${themeName}.docx.theme.json`\n );\n const content = fs.readFileSync(filePath, 'utf8');\n const parsedTheme = JSON.parse(content);\n // Check before registering. A theme that reaches the registry is\n // never validated again, so an invalid one here renders wrong\n // rather than failing — the drift that hid dead `componentDefaults`\n // props across five themes for as long as they shipped.\n if (!isValidThemeConfig(parsedTheme)) {\n console.warn(\n `Skipping theme ${themeName}: does not match the theme schema.`\n );\n continue;\n }\n themes[themeName] = ensureThemeDefaults(parsedTheme);\n } catch (error) {\n console.warn(\n `Failed to load additional theme ${themeName}:`,\n error\n );\n }\n }\n }\n }\n } catch (error) {\n // Silently ignore if file system access fails (e.g., in bundled environment)\n }\n\n _themesCache = themes;\n return themes;\n}\n\nexport const themes = loadThemesFromJson();\n\n/**\n * Type representing valid theme names\n */\nexport type ThemeName = keyof typeof themes;\n\n/**\n * Get theme configuration by name\n * @param themeName - Name of the theme to retrieve\n * @returns Theme configuration or undefined if not found\n */\nexport const getTheme = (themeName: string): ThemeConfigJson | undefined => {\n return themes[themeName];\n};\n\n/**\n * Get theme configuration with safe fallback\n * @param themeName - Name of the theme to retrieve\n * @param fallbackTheme - Fallback theme name (default: 'minimal')\n * @returns Theme configuration (guaranteed to be defined)\n * @throws Error if neither theme nor fallback can be found\n */\nexport const getThemeWithFallback = (\n themeName: string,\n fallbackTheme: string = 'minimal'\n): ThemeConfigJson => {\n const theme = getTheme(themeName) || getTheme(fallbackTheme);\n\n if (!theme) {\n throw new Error(\n `Failed to load theme: ${themeName}. Fallback theme '${fallbackTheme}' also not found.`\n );\n }\n\n return theme;\n};\n\n/**\n * Check if a theme exists\n * @param themeName - Name of the theme to check\n * @returns True if theme exists, false otherwise\n */\nexport const hasTheme = (themeName: string): boolean => {\n return themeName in themes;\n};\n\n/**\n * Type guard to ensure theme name is valid\n * @param themeName - Theme name to validate\n * @returns True if theme name exists in registry\n */\nexport const isValidThemeName = (\n themeName: string\n): themeName is keyof typeof themes => {\n return hasTheme(themeName);\n};\n\n/**\n * Get all available theme names\n * @returns Array of theme names\n */\nexport const getThemeNames = (): string[] => {\n return Object.keys(themes);\n};\n\n// Export individual theme configs for direct access\nexport const minimalTheme = themes['minimal'];\nexport const corporateTheme = themes['corporate'];\nexport const modernTheme = themes['modern'];\n","import { getTheme } from '../../templates/themes';\nimport { ThemeConfig } from '../index';\nimport { resolveColor } from './colorUtils';\nimport { LineSpacing } from '@json-to-office/shared-docx';\nimport { getNormalStyle } from '../../themes/defaults';\n\n/** `w:spacing`'s line height and rule, in the units OOXML uses. */\nexport interface LineSpacingProperties {\n line?: number;\n lineRule?: 'auto' | 'exact' | 'atLeast';\n}\n\n// Constants for line spacing calculations\nconst TWIPS_PER_POINT = 20;\nconst SINGLE_LINE_SPACING_POINTS = 12;\nconst SINGLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_POINTS * TWIPS_PER_POINT;\nconst DOUBLE_LINE_SPACING_TWIPS = SINGLE_LINE_SPACING_TWIPS * 2;\n\n/**\n * Convert points to twips for docx spacing\n * @param points - Value in points\n * @returns Value in twips (1/20 of a point)\n */\nexport function pointsToTwips(points: number): number {\n return Math.round(points * TWIPS_PER_POINT);\n}\n\n/**\n * Resolve theme configuration from either a theme object or theme name\n * @param theme - Theme configuration object (for custom themes)\n * @param themeName - Theme name (for built-in themes)\n * @returns Resolved theme configuration\n */\nexport function resolveTheme(\n theme?: ThemeConfig,\n themeName?: string\n): ThemeConfig | undefined {\n // First check if we have a theme object passed directly (for custom themes)\n if (theme) {\n return theme;\n }\n\n // If no theme object, check for built-in theme by name\n if (themeName) {\n return getTheme(themeName);\n }\n\n // Default to minimal theme if nothing else works\n return getTheme('minimal');\n}\n\n/**\n * Resolve font family from font reference (e.g., 'body', 'heading') to actual font family name\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Actual font family name (e.g., 'Arial', 'Helvetica')\n */\nexport function resolveFontFamily(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): string {\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.body?.family) {\n return 'Arial'; // fallback to Arial\n }\n if (!fontRef) {\n return theme.fonts.body.family;\n }\n return theme.fonts[fontRef]?.family || theme.fonts.body.family;\n}\n\n/**\n * Resolve font size from font reference (e.g., 'body', 'heading') to actual font size in points\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Font size in points (callers multiply by 2 for docx) or undefined if no size found\n */\nexport function resolveFontSize(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): number | undefined {\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.body?.size) {\n return undefined; // let caller handle fallback\n }\n if (!fontRef) {\n return theme.fonts.body.size;\n }\n return theme.fonts[fontRef]?.size || theme.fonts.body.size;\n}\n\n/**\n * Font properties that can be defined in font definitions\n */\nexport interface FontProperties {\n family?: string;\n size?: number;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n alignment?: 'left' | 'center' | 'right' | 'justify';\n lineSpacing?: {\n type: 'single' | 'atLeast' | 'exactly' | 'double' | 'multiple';\n value?: number;\n };\n spacing?: {\n before?: number;\n after?: number;\n };\n characterSpacing?: { type: 'condensed' | 'expanded'; value: number };\n scale?: number;\n}\n\n/**\n * Resolve all font properties from font reference.\n * Returns all formatting properties defined in the font definition.\n * @param theme - Theme configuration object\n * @param fontRef - Font reference ('body', 'heading', 'mono', 'light') or undefined\n * @returns Object containing all font properties\n */\nexport function resolveFontProperties(\n theme: ThemeConfig,\n fontRef?: 'heading' | 'body' | 'mono' | 'light'\n): FontProperties {\n // Default to body font if no reference provided\n const targetFontKey = fontRef || 'body';\n\n // Handle empty/invalid themes gracefully\n if (!theme?.fonts?.[targetFontKey]) {\n return {\n family: 'Arial',\n size: 11,\n };\n }\n\n const fontDef = theme.fonts[targetFontKey] as FontProperties;\n\n return {\n family: fontDef.family,\n size: fontDef.size,\n color: fontDef.color,\n bold: fontDef.bold,\n italic: fontDef.italic,\n underline: fontDef.underline,\n alignment: fontDef.alignment,\n lineSpacing: fontDef.lineSpacing,\n spacing: fontDef.spacing,\n characterSpacing: fontDef.characterSpacing,\n scale: fontDef.scale,\n };\n}\n\n/**\n * Merge font properties with style overrides.\n * Style properties take precedence over font properties.\n * Only defined (non-undefined) style properties override font properties.\n * @param fontProps - Properties from font definition\n * @param styleOverrides - Properties from style definition\n * @returns Merged properties object\n */\nexport function mergeFontAndStyleProperties<T extends Partial<FontProperties>>(\n fontProps: FontProperties,\n styleOverrides: T\n): FontProperties & T {\n // Filter out undefined values from styleOverrides to prevent overwriting font properties\n // Use type-safe Object.entries approach\n const definedOverrides = Object.entries(styleOverrides).reduce<\n Record<string, unknown>\n >((acc, [key, value]) => {\n if (value !== undefined) {\n acc[key] = value;\n }\n return acc;\n }, {});\n\n return {\n ...fontProps,\n ...definedOverrides,\n } as FontProperties & T;\n}\n\n/**\n * Get body text style configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Style configuration object\n */\nexport const getBodyTextStyle = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig) {\n const normalStyle = getNormalStyle(themeConfig);\n return {\n size: (normalStyle.size || 11) * 2,\n font: resolveFontFamily(themeConfig, normalStyle.font),\n color: normalStyle.color\n ? resolveColor(normalStyle.color, themeConfig)\n : '000000',\n };\n }\n\n // Fallback\n return {\n size: 20,\n font: 'Arial',\n color: '000000',\n };\n};\n\n/**\n * Converts line spacing from theme definition to DOCX spacing options.\n * DOCX uses twips (1/20th of a point) for line spacing.\n * @param lineSpacing The line spacing object from the theme definition.\n * @returns IParagraphSpacingOptions for docx.\n */\nexport function convertLineSpacing(\n lineSpacing?: LineSpacing | number\n): LineSpacingProperties | undefined {\n if (lineSpacing === undefined) {\n return undefined;\n }\n\n // Handle number (simple multiplier) case\n if (typeof lineSpacing === 'number') {\n return {\n line: Math.round(lineSpacing * SINGLE_LINE_SPACING_TWIPS),\n lineRule: 'auto',\n };\n }\n\n const { type, value } = lineSpacing;\n let line: number | undefined;\n let lineRule: 'auto' | 'exact' | 'atLeast' | undefined;\n\n switch (type) {\n case 'single':\n line = SINGLE_LINE_SPACING_TWIPS;\n lineRule = 'auto';\n break;\n case 'double':\n line = DOUBLE_LINE_SPACING_TWIPS;\n lineRule = 'auto';\n break;\n case 'atLeast':\n line = value !== undefined ? value * TWIPS_PER_POINT : undefined;\n lineRule = 'atLeast';\n break;\n case 'exactly':\n line = value !== undefined ? value * TWIPS_PER_POINT : undefined;\n lineRule = 'exact';\n break;\n case 'multiple':\n line =\n value !== undefined ? value * SINGLE_LINE_SPACING_TWIPS : undefined;\n lineRule = 'auto';\n break;\n default:\n return undefined;\n }\n\n return { line, lineRule };\n}\n","import { LineSpacing } from '@json-to-office/shared-docx';\nimport { ThemeConfig } from '../index';\nimport { resolveColor } from './colorUtils';\nimport {\n resolveTheme,\n resolveFontFamily,\n convertLineSpacing,\n pointsToTwips,\n} from './styleHelpers';\n\n/**\n * Subset of a theme StyleProperties entry relevant to paragraph spacing.\n */\ninterface TableParagraphStyle {\n spacing?: { before?: number; after?: number };\n lineSpacing?: LineSpacing;\n}\n\n/**\n * Resolve the paragraph spacing for a table cell/header wrapper paragraph.\n *\n * Table cells render as a single wrapper paragraph. Historically that paragraph\n * inherited the `normal` style, dragging body-prose rhythm (8–10pt after-spacing\n * + 1.4–1.5x line) into every row and inflating row height regardless of font\n * size, padding, or the cell `height` prop. Tables should be dense by default:\n * no extra paragraph spacing, single line. Vertical breathing room is the job of\n * cell padding, not paragraph spacing.\n *\n * Themes may override per context via `styles.tableCell` / `styles.tableHeader`\n * (standard StyleProperties: `spacing.before/after` in points, `lineSpacing`).\n */\nconst resolveTableParagraphSpacing = (style?: TableParagraphStyle) => {\n const lineSpacing =\n convertLineSpacing(style?.lineSpacing) ??\n convertLineSpacing({ type: 'single' });\n return {\n before:\n style?.spacing?.before !== undefined\n ? pointsToTwips(style.spacing.before)\n : 0,\n after:\n style?.spacing?.after !== undefined\n ? pointsToTwips(style.spacing.after)\n : 0,\n ...lineSpacing,\n };\n};\n\n/**\n * Standard page sizes in twips (1/20 of a point, 1/1440 of an inch).\n *\n * `code` is the OOXML `w:pgSz/@w:code` paper-size code — the Windows DEVMODE\n * `dmPaperSize` value that printer drivers key off (from `wingdi.h`:\n * DMPAPER_LETTER 1, DMPAPER_LEGAL 5, DMPAPER_A3 8, DMPAPER_A4 9). Without it a\n * driver has to infer the tray from the dimensions.\n */\nexport const PAGE_SIZES = {\n A4: { width: 11906, height: 16838, code: 9 },\n A3: { width: 16838, height: 23811, code: 8 },\n LETTER: { width: 12240, height: 15840, code: 1 },\n LEGAL: { width: 12240, height: 20160, code: 5 },\n} as const;\n\nexport interface PageDimensions {\n width: number;\n height: number;\n /** Present only for a named size; a custom size has no paper code. */\n code?: number;\n}\n\n/**\n * Get page dimensions from size (string or object).\n *\n * A custom `{ width, height }` deliberately returns no `code`: it is not one of\n * the standard papers, and claiming a code would send the driver to the wrong\n * tray.\n */\nexport function getPageDimensions(\n size: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number }\n): PageDimensions {\n if (typeof size === 'string') {\n return PAGE_SIZES[size];\n }\n return { width: size.width, height: size.height };\n}\n\n/**\n * Get table style configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Table style configuration object\n */\nexport const getTableStyle = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig && themeConfig.styles?.normal) {\n // Use normal style for run-level header/cell defaults (font, size, color).\n // Paragraph spacing is resolved separately so table rows stay dense and do\n // not inherit `normal`'s body-prose after-spacing/line height.\n const normalStyle = themeConfig.styles.normal;\n const styles = themeConfig.styles as Record<string, TableParagraphStyle>;\n return {\n cellParagraph: resolveTableParagraphSpacing(styles.tableCell),\n headerParagraph: resolveTableParagraphSpacing(styles.tableHeader),\n tableHeader: {\n fill: resolveColor(\n themeConfig.colors?.primary || '#000000',\n themeConfig\n ),\n color: resolveColor(\n themeConfig.colors?.backgroundPrimary || '#FFFFFF',\n themeConfig\n ), // Use background color for header text\n bold: true, // Headers should be bold\n size: (normalStyle.size || 11) * 2, // Convert to half-points\n font: resolveFontFamily(themeConfig, normalStyle.font),\n },\n tableCell: {\n color: resolveColor(normalStyle.color || '#000000', themeConfig),\n size: (normalStyle.size || 11) * 2, // Convert to half-points\n font: resolveFontFamily(themeConfig, normalStyle.font),\n },\n alternatingRow: {\n fill: resolveColor(\n themeConfig.colors?.accent || '#F0F0F0',\n themeConfig\n ),\n },\n borders: {\n top: {\n style: 'single',\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n bottom: {\n style: 'single',\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n left: {\n style: 'single',\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n right: {\n style: 'single',\n size: 1,\n color: resolveColor(\n themeConfig.colors?.secondary || '#CCCCCC',\n themeConfig\n ),\n },\n },\n };\n }\n\n // This shouldn't happen with minimal themes\n return {\n cellParagraph: resolveTableParagraphSpacing(),\n headerParagraph: resolveTableParagraphSpacing(),\n tableHeader: {\n fill: '000000',\n color: 'FFFFFF',\n bold: true,\n size: 22,\n font: 'Arial',\n },\n tableCell: {\n color: '000000',\n size: 20,\n font: 'Arial',\n },\n alternatingRow: {\n fill: 'F5F5F5',\n },\n borders: {\n top: { style: 'single', size: 1, color: '000000' },\n bottom: {\n style: 'single',\n size: 1,\n color: '000000',\n },\n left: { style: 'single', size: 1, color: '000000' },\n right: {\n style: 'single',\n size: 1,\n color: '000000',\n },\n },\n };\n};\n\n/**\n * Get document margins configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Document margins object\n */\nexport const getDocumentMargins = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n\n if (themeConfig?.page?.margins) {\n return themeConfig.page.margins;\n }\n\n // Default margins for all themes (standard Word document margins)\n return {\n top: 1440, // 1 inch in twips\n right: 1440, // 1 inch in twips\n bottom: 1440, // 1 inch in twips\n left: 1440, // 1 inch in twips\n header: 720, // 0.5 inch in twips\n footer: 720, // 0.5 inch in twips\n };\n};\n\n/**\n * Get page setup configuration\n * @param theme - Theme configuration object\n * @param themeName - Name of the theme (for fallback to built-in themes)\n * @returns Page setup object\n */\nexport const getPageSetup = (theme?: ThemeConfig, themeName?: string) => {\n const themeConfig = resolveTheme(theme, themeName);\n const defaultMargins = getDocumentMargins(theme, themeName);\n\n if (themeConfig?.page) {\n const margins = themeConfig.page.margins || {};\n const dimensions = getPageDimensions(themeConfig.page.size);\n return {\n size: {\n width: dimensions.width,\n height: dimensions.height,\n ...(dimensions.code !== undefined && { code: dimensions.code }),\n },\n margin: {\n top: margins.top ?? defaultMargins.top ?? 1440,\n right: margins.right ?? defaultMargins.right ?? 1440,\n bottom: margins.bottom ?? defaultMargins.bottom ?? 1440,\n left: margins.left ?? defaultMargins.left ?? 1440,\n },\n };\n }\n\n // Default page setup for all themes\n return {\n size: {\n width: PAGE_SIZES.A4.width, // 210mm in twips (A4)\n height: PAGE_SIZES.A4.height, // 297mm in twips (A4)\n code: PAGE_SIZES.A4.code,\n },\n margin: {\n top: defaultMargins.top ?? 1440,\n right: defaultMargins.right ?? 1440,\n bottom: defaultMargins.bottom ?? 1440,\n left: defaultMargins.left ?? 1440,\n },\n };\n};\n","/**\n * Theme Parser using unified validation (TypeBox under the hood)\n */\n\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { validateThemeJson } from '@json-to-office/shared-docx/validation/unified';\nimport type { ValidationError } from '@json-to-office/shared-docx/validation/unified';\nimport { ensureThemeDefaults } from '../../themes/defaults';\n\n// Custom error classes with enhanced error details\nexport class ThemeValidationError extends Error {\n constructor(public errors: ValidationError[]) {\n const errorCount = errors.length;\n const errorSummary = errors\n .slice(0, 3)\n .map((error) => {\n const path = error.path\n ? error.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${error.message}`;\n })\n .join('; ');\n\n super(\n `Theme validation failed with ${errorCount} error${errorCount > 1 ? 's' : ''}: ${errorSummary}${errorCount > 3 ? '...' : ''}`\n );\n this.name = 'ThemeValidationError';\n }\n\n getDetailedErrors(): string[] {\n return this.errors.map((error) => {\n const path = error.path\n ? error.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${error.message}`;\n });\n }\n}\n\nexport class ThemeParseError extends Error {\n constructor(\n message: string,\n public cause?: Error\n ) {\n super(`Failed to parse theme: ${message}`);\n this.name = 'ThemeParseError';\n }\n}\n\n// Theme parser class with comprehensive validation and error handling\nexport class ThemeParser {\n private readonly MAX_JSON_SIZE = 1024 * 1024; // 1MB limit (pre-parse guard)\n\n parse(jsonString: string): ThemeConfigJson {\n try {\n // Input validation and sanitization\n this.validateInput(jsonString);\n\n // Use unified validator (handles parsing + position calculation)\n const result = validateThemeJson(jsonString);\n if (!result.valid) {\n throw new ThemeValidationError(result.errors || []);\n }\n\n const validated = result.data as ThemeConfigJson;\n\n // Apply defaults and return ThemeConfig\n return this.applyDefaults(validated);\n } catch (error) {\n if (\n error instanceof ThemeValidationError ||\n error instanceof ThemeParseError\n ) {\n throw error;\n }\n throw new ThemeParseError(\n `Unexpected error during theme parsing: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n private validateInput(jsonString: string): void {\n // Check for null/undefined\n if (!jsonString) {\n throw new ThemeParseError('JSON string cannot be null or empty');\n }\n\n // Check string type\n if (typeof jsonString !== 'string') {\n throw new ThemeParseError('Input must be a string');\n }\n\n // Check size limits (additional robustness guard)\n if (jsonString.length > this.MAX_JSON_SIZE) {\n throw new ThemeParseError(\n `JSON string too large (${jsonString.length} bytes, max ${this.MAX_JSON_SIZE} bytes)`\n );\n }\n }\n\n private applyDefaults(parsedTheme: ThemeConfigJson): ThemeConfigJson {\n // Apply defaults to ensure all required properties are present\n // This handles partial theme configurations by merging with defaults\n return ensureThemeDefaults(parsedTheme);\n }\n\n // Utility method for validating without parsing\n validate(jsonString: string): { valid: boolean; errors?: string[] } {\n try {\n this.validateInput(jsonString);\n const result = validateThemeJson(jsonString);\n\n if (result.valid) {\n return { valid: true };\n } else {\n const errors = (result.errors || []).map((e) => {\n const path = e.path\n ? e.path.replace(/^\\//, '').replace(/\\//g, '.')\n : '';\n const pathStr = path ? `${path}: ` : '';\n return `${pathStr}${e.message}`;\n });\n return { valid: false, errors };\n }\n } catch (error) {\n return {\n valid: false,\n errors: [\n error instanceof Error ? error.message : 'Unknown validation error',\n ],\n };\n }\n }\n}\n","/**\n * Theme Validator - thin wrapper over shared unified validator\n * Maintains backward-compatible API while removing duplicate logic\n */\n\nimport { validateThemeJson as validateThemeJsonUnified } from '@json-to-office/shared-docx/validation/unified';\n\n// Backward-compatible ValidationResult type used by core\nexport type ValidationResult = {\n success: boolean;\n error?: {\n issues: Array<{\n code: string;\n message: string;\n path: Array<string | number>;\n expected?: string;\n received?: string;\n type?: string;\n minimum?: number;\n maximum?: number;\n validation?: string;\n options?: string[];\n line?: number;\n column?: number;\n }>;\n };\n};\n\n// Validator function using unified shared validation\nexport function validateThemeJson(jsonString: string): ValidationResult {\n const result = validateThemeJsonUnified(jsonString);\n\n if (result.valid) {\n return { success: true };\n }\n\n const issues = (result.errors || []).map((e) => {\n const pathArray = (e.path || '')\n .split('/')\n .filter((p) => p)\n .map((p) => {\n const num = parseInt(p, 10);\n return isNaN(num) ? p : num;\n });\n\n return {\n code: e.code || 'validation_error',\n message: e.message,\n path: pathArray,\n line: e.line,\n column: e.column,\n };\n });\n\n return { success: false, error: { issues } };\n}\n\nexport function formatValidationErrors(error: {\n issues: Array<any>;\n}): string[] {\n return error.issues.map((issue) => {\n const path =\n issue.path && issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';\n let message = issue.message;\n // Keep messages simple; unified validator already includes good messages\n return `${path}${message}`;\n });\n}\n\nexport function isValidThemeJson(jsonString: string): boolean {\n const result = validateThemeJson(jsonString);\n return result.success;\n}\n\nexport function getValidationSummary(jsonString: string): {\n valid: boolean;\n errorCount: number;\n errors: string[];\n summary: string;\n} {\n const result = validateThemeJson(jsonString);\n\n if (result.success) {\n return {\n valid: true,\n errorCount: 0,\n errors: [],\n summary: 'Theme JSON is valid',\n };\n }\n\n const errors = formatValidationErrors(result.error!);\n const errorCount = errors.length;\n\n return {\n valid: false,\n errorCount,\n errors,\n summary: `Theme validation failed with ${errorCount} error${errorCount > 1 ? 's' : ''}`,\n };\n}\n","import { promises as fs } from 'fs';\nimport { normalize } from 'path';\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { ThemeParser } from './parser';\n\n// File system error class with enhanced error details\nexport class ThemeFileError extends Error {\n constructor(\n message: string,\n public path?: string,\n public _cause?: Error\n ) {\n const pathInfo = path ? ` (path: ${path})` : '';\n super(`Failed to load theme file: ${message}${pathInfo}`);\n this.name = 'ThemeFileError';\n }\n}\n\n// Theme loader class with comprehensive security and error handling\nexport class ThemeLoader {\n private parser = new ThemeParser();\n private readonly MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB limit\n private readonly ALLOWED_EXTENSIONS = ['.json'];\n\n async loadFromFile(filePath: string): Promise<ThemeConfigJson> {\n try {\n // Validate file path for security\n this.validateFilePath(filePath);\n\n // Read file with size limits\n const content = await this.readFileWithLimits(filePath);\n\n // Parse the theme content\n return this.parser.parse(content);\n } catch (error) {\n if (error instanceof ThemeFileError) {\n throw error;\n }\n\n // Handle file system errors\n if (error && typeof error === 'object' && 'code' in error) {\n const fsError = error as { code?: string; message: string };\n let message: string;\n\n switch (fsError.code) {\n case 'ENOENT':\n message = 'File not found';\n break;\n case 'EACCES':\n message = 'Permission denied';\n break;\n case 'EISDIR':\n message = 'Path is a directory, not a file';\n break;\n case 'EMFILE':\n case 'ENFILE':\n message = 'Too many open files';\n break;\n case 'ENOTDIR':\n message = 'Directory in path does not exist';\n break;\n default:\n message = `File system error: ${fsError.message}`;\n }\n\n throw new ThemeFileError(\n message,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n\n // Handle other errors\n throw new ThemeFileError(\n `Unexpected error: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n async loadFromUrl(_url: string): Promise<ThemeConfigJson> {\n // Future enhancement for loading themes from URLs\n // Would need additional dependencies (fetch) and security considerations\n throw new ThemeFileError(\n 'URL loading not yet implemented - use loadFromFile() instead'\n );\n }\n\n private validateFilePath(filePath: string): void {\n // Basic input validation\n if (!filePath || typeof filePath !== 'string') {\n throw new ThemeFileError('File path must be a non-empty string');\n }\n\n // Normalize the path to handle different separators and relative paths\n const normalizedPath = normalize(filePath);\n\n // Check for directory traversal attempts\n if (normalizedPath.includes('..')) {\n throw new ThemeFileError('Directory traversal is not allowed', filePath);\n }\n\n // Check for null bytes (path injection)\n if (normalizedPath.includes('\\0')) {\n throw new ThemeFileError(\n 'Null bytes in file path are not allowed',\n filePath\n );\n }\n\n // Validate file extension\n const hasValidExtension = this.ALLOWED_EXTENSIONS.some((ext) =>\n normalizedPath.toLowerCase().endsWith(ext)\n );\n\n if (!hasValidExtension) {\n throw new ThemeFileError(\n `Invalid file extension. Allowed: ${this.ALLOWED_EXTENSIONS.join(', ')}`,\n filePath\n );\n }\n\n // Additional security: ensure path is reasonable length\n if (normalizedPath.length > 1000) {\n throw new ThemeFileError('File path is too long', filePath);\n }\n }\n\n private async readFileWithLimits(filePath: string): Promise<string> {\n try {\n // Get file stats to check size before reading\n const stats = await fs.stat(filePath);\n\n // Check if it's actually a file\n if (!stats.isFile()) {\n throw new ThemeFileError('Path is not a regular file', filePath);\n }\n\n // Check file size limits\n if (stats.size > this.MAX_FILE_SIZE) {\n throw new ThemeFileError(\n `File too large (${stats.size} bytes, max ${this.MAX_FILE_SIZE} bytes)`,\n filePath\n );\n }\n\n // Check for empty file\n if (stats.size === 0) {\n throw new ThemeFileError('File is empty', filePath);\n }\n\n // Read file with proper encoding\n const content = await fs.readFile(filePath, 'utf8');\n\n // Verify content was read properly\n if (typeof content !== 'string') {\n throw new ThemeFileError('Failed to read file as text', filePath);\n }\n\n return content;\n } catch (error) {\n if (error instanceof ThemeFileError) {\n throw error;\n }\n\n // Re-throw as ThemeFileError for consistent error handling\n throw new ThemeFileError(\n `Failed to read file: ${error instanceof Error ? error.message : String(error)}`,\n filePath,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n // Utility method to validate a file path without reading\n validateFile(filePath: string): { valid: boolean; error?: string } {\n try {\n this.validateFilePath(filePath);\n return { valid: true };\n } catch (error) {\n return {\n valid: false,\n error:\n error instanceof Error ? error.message : 'Unknown validation error',\n };\n }\n }\n\n // Utility method to get file info\n async getFileInfo(filePath: string): Promise<{\n exists: boolean;\n size?: number;\n isFile?: boolean;\n error?: string;\n }> {\n try {\n const stats = await fs.stat(filePath);\n return {\n exists: true,\n size: stats.size,\n isFile: stats.isFile(),\n };\n } catch (error) {\n return {\n exists: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n}\n","// Public API exports for JSON theme system\nexport {\n ThemeConfigSchema,\n type ThemeConfigJson,\n isValidThemeConfig,\n /**\n * Create a minimal theme template for users to start with.\n * Defined in shared-docx next to `ThemeConfigSchema` so every consumer\n * (CLI, playground) scaffolds from one schema-checked source.\n */\n createMinimalTheme,\n} from '@json-to-office/shared-docx';\nexport { ThemeParser, ThemeValidationError, ThemeParseError } from './parser';\nexport {\n validateThemeJson,\n formatValidationErrors,\n type ValidationResult,\n} from './validator';\nexport { ThemeLoader, ThemeFileError } from './loader';\n\n// Main API functions - Core public interface for JSON theme system\nimport type { ThemeConfigJson } from '@json-to-office/shared-docx';\nimport { ThemeParser } from './parser';\nimport { ThemeLoader } from './loader';\n\n// Global instances for consistent behavior\nconst themeParser = new ThemeParser();\nconst themeLoader = new ThemeLoader();\n\n/**\n * Load and parse a theme from a JSON string\n * @param jsonString - JSON string containing theme definition\n * @returns Promise<ThemeConfig> - Parsed and validated theme configuration\n * @throws ThemeParseError - If JSON is malformed or invalid\n * @throws ThemeValidationError - If theme fails schema validation\n */\nexport async function loadThemeFromJson(\n jsonString: string\n): Promise<ThemeConfigJson> {\n return themeParser.parse(jsonString);\n}\n\n/**\n * Load and parse a theme from a JSON file\n * @param filePath - Path to JSON file containing theme definition\n * @returns Promise<ThemeConfig> - Parsed and validated theme configuration\n * @throws ThemeFileError - If file cannot be read or path is invalid\n * @throws ThemeParseError - If JSON is malformed or invalid\n * @throws ThemeValidationError - If theme fails schema validation\n */\nexport async function loadThemeFromFile(\n filePath: string\n): Promise<ThemeConfigJson> {\n return themeLoader.loadFromFile(filePath);\n}\n\n/**\n * Export a theme configuration to JSON string\n * @param theme - Theme configuration to export\n * @param pretty - Whether to format JSON with indentation (default: true)\n * @returns string - Formatted JSON string\n */\nexport function exportThemeToJson(\n theme: ThemeConfigJson,\n pretty: boolean = true\n): string {\n try {\n // Since ThemeConfig is inferred from TypeBox schema, it can be directly serialized\n // The schema ensures all properties are JSON-serializable\n\n if (pretty) {\n return JSON.stringify(theme, null, 2);\n } else {\n return JSON.stringify(theme);\n }\n } catch (error) {\n throw new Error(\n `Failed to export theme to JSON: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Validate a JSON string against the theme schema without parsing\n * @param jsonString - JSON string to validate\n * @returns Validation result with success status and detailed errors\n */\nexport function validateThemeJsonString(jsonString: string) {\n return themeParser.validate(jsonString);\n}\n","/**\n * Main styles module export\n * This file provides a unified interface to the styles system\n */\n\n// Base configurations - imported from TypeBox schemas\nexport type {\n ThemeConfigJson as ThemeConfig,\n StyleDefinitions,\n DocumentMargins,\n PageDimensions,\n Page,\n FontDefinition,\n Fonts,\n ComponentDefaults,\n HeadingComponentDefaults,\n ParagraphComponentDefaults,\n ImageComponentDefaults,\n StatisticComponentDefaults,\n TableComponentDefaults,\n SectionComponentDefaults,\n ColumnsComponentDefaults,\n ListComponentDefaults,\n} from '@json-to-office/shared-docx';\nexport {\n themes,\n getTheme,\n getThemeNames,\n getThemeWithFallback,\n hasTheme,\n isValidThemeName,\n} from '../templates/themes';\n\n// Export ThemeName type separately\nexport type { ThemeName } from '../templates/themes';\n\n// Style utilities\nexport { getBodyTextStyle } from './utils/styleHelpers';\nexport {\n getTableStyle,\n getDocumentMargins,\n getPageSetup,\n getPageDimensions,\n PAGE_SIZES,\n} from './utils/layoutUtils';\n\n// Theme configurations\nexport { minimalTheme, corporateTheme, modernTheme } from '../templates/themes';\n\n// JSON Theme System (Phase 1 - Foundation complete)\nexport {\n ThemeConfigSchema,\n isValidThemeConfig,\n loadThemeFromJson,\n loadThemeFromFile,\n exportThemeToJson,\n validateThemeJsonString,\n ThemeValidationError,\n ThemeParseError,\n ThemeFileError,\n} from '../themes/json';\n\n// Export type separately\nexport type { ThemeConfigJson } from '../themes/json';\n\n// All themes now use the same structure\n// No need for backward compatibility exports\n","import { ThemeConfig } from '../styles';\nimport { getPageSetup } from '../styles';\nimport { pointsToTwips } from '../styles/utils/styleHelpers';\n\n/**\n * Compute available page width in twips (page width minus left/right margins)\n */\nexport function getAvailableWidthTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n const width = page?.size?.width || 0;\n const left = page?.margin?.left || 0;\n const right = page?.margin?.right || 0;\n return Math.max(0, width - left - right);\n}\n\n/**\n * Compute full page width in twips (ignores margins)\n */\nexport function getPageWidthTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n return page?.size?.width || 0;\n}\n\n/**\n * Compute available page height in twips (page height minus top/bottom margins)\n */\nexport function getAvailableHeightTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n const height = page?.size?.height || 0;\n const top = page?.margin?.top || 0;\n const bottom = page?.margin?.bottom || 0;\n return Math.max(0, height - top - bottom);\n}\n\n/**\n * Compute full page height in twips (ignores margins)\n */\nexport function getPageHeightTwips(\n theme?: ThemeConfig,\n themeName?: string\n): number {\n const page = getPageSetup(theme, themeName);\n return page?.size?.height || 0;\n}\n\n/**\n * Parse a percentage string like \"75%\" into a fraction 0..1\n */\nexport function parsePercentageStringToFraction(\n value: string\n): number | undefined {\n const match = /^([0-9]+(?:\\.[0-9]+)?)%$/.exec(value);\n if (!match) return undefined;\n const pct = parseFloat(match[1]);\n if (pct < 0 || pct > 100) return undefined;\n return pct / 100;\n}\n\n/**\n * Resolve an offset value (twips or percentage string) to twips.\n * Numbers pass through unchanged; percentage strings are resolved against referenceTwips.\n */\nexport function resolveOffsetTwips(\n value: number | string,\n referenceTwips: number\n): number {\n if (typeof value === 'number') return value;\n const match = /^([0-9]+(?:\\.[0-9]+)?)%$/.exec(value);\n if (!match) {\n console.warn(\n `resolveOffsetTwips: invalid percentage string \"${value}\", defaulting to 0`\n );\n return 0;\n }\n return Math.round((referenceTwips * parseFloat(match[1])) / 100);\n}\n\n/**\n * Convert a numeric (points) or percentage string to twips using available width\n */\nexport function relativeLengthToTwips(\n value: number | string,\n availableWidthTwips: number\n): number {\n if (typeof value === 'number') {\n return pointsToTwips(value);\n }\n const fraction = parsePercentageStringToFraction(value);\n if (fraction === undefined) return 0;\n return Math.round(availableWidthTwips * fraction);\n}\n","import { readFileSync } from 'fs';\nimport probe from 'probe-image-size';\nimport { reportWarning, resolveFromBaseDir } from './generationContext';\nimport { parsePercentageStringToFraction } from './widthUtils';\n\ntype ResvgModule = typeof import('@resvg/resvg-js');\n\n/** 3x of Word's 96 DPI baseline — ~288 DPI, sharp in print and on retina. */\nconst SVG_RASTER_SCALE = 3;\nconst SVG_MAX_EDGE_PX = 4096;\nconst SVG_MIN_EDGE_PX = 16;\n/**\n * Ceiling on the whole bitmap, not just its longest side.\n *\n * An edge cap alone says nothing about area, and area is what costs memory:\n * resvg renders RGBA, so a page-sized SVG at 3x is 2382x3367 ≈ 8 MP ≈ 32 MB\n * live before it is even encoded to PNG. The annual-report templates carry two\n * dozen full-page SVGs, which took one render past 1.1 GB and had the hosted\n * playground's 512 MB container killed mid-request — the reader saw the\n * proxy's HTML error page, not a document.\n *\n * 1 MP keeps a full page near 120 DPI, which is enough for what this bitmap is:\n * Word 2016+ draws the vector, and only older readers ever fall back to it.\n * Small SVGs are unaffected — an icon at 3x is nowhere near the budget.\n */\nconst SVG_MAX_TOTAL_PX = 1_000_000;\n\nlet resvgModule: Promise<ResvgModule> | undefined;\n\nfunction loadResvg(): Promise<ResvgModule> {\n resvgModule ??= import('@resvg/resvg-js');\n return resvgModule;\n}\n\nfunction toRasterPx(px: number): number {\n return Math.min(\n SVG_MAX_EDGE_PX,\n Math.max(SVG_MIN_EDGE_PX, Math.round(px * SVG_RASTER_SCALE))\n );\n}\n\n/**\n * Shrink a `fitTo` edge until the bitmap it implies fits `SVG_MAX_TOTAL_PX`,\n * or `undefined` when nothing does.\n *\n * `aspect` is the other edge over this one, so `edge * aspect` is the edge\n * resvg derives. Area scales with the square of the edge, hence the sqrt.\n *\n * A sliver — an SVG whose viewBox is thousands of times longer than it is\n * wide — cannot be squared with both bounds at once: at `SVG_MIN_EDGE_PX` its\n * area is still `256 * aspect`, so a ratio of 10,000 is already 2.5x over\n * budget and grows from there. Clamping to the minimum edge in that case would\n * hand back exactly the oversized bitmap this budget exists to prevent, so the\n * caller is told to skip the fallback instead. Word 2016+ draws the vector\n * either way.\n */\nfunction capToPixelBudget(edge: number, aspect: number): number | undefined {\n // A degenerate ratio means the probe gave a zero or non-finite dimension;\n // there is no bitmap size that can be reasoned about.\n if (!Number.isFinite(aspect) || aspect <= 0) return undefined;\n\n const total = edge * edge * aspect;\n if (total <= SVG_MAX_TOTAL_PX) return edge;\n\n const scaled = Math.floor(edge * Math.sqrt(SVG_MAX_TOTAL_PX / total));\n return scaled >= SVG_MIN_EDGE_PX ? scaled : undefined;\n}\n\n/**\n * Rasterize inline SVG for the `fallback` slot of an SVG `ImageRun`.\n *\n * Word 2016+ draws the vector, but every older Word and non-SVG consumer\n * renders the fallback instead — so shipping the SVG bytes under a `png` type\n * gave those readers a broken image. Returns `undefined` when rasterization is\n * unavailable or fails; the caller then keeps the historical bytes, which is\n * no worse than before and never fails the render.\n */\nexport async function rasterizeSvgFallback(\n svg: Buffer,\n transformation: { width: number; height: number }\n): Promise<Buffer | undefined> {\n let Resvg: ResvgModule['Resvg'];\n try {\n ({ Resvg } = await loadResvg());\n } catch (error) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_FAILED',\n `Could not load the SVG rasterizer, so inline SVG keeps a fallback that only Word 2016+ can draw: ${String(error)}`\n );\n return undefined;\n }\n\n try {\n const markup = svg.toString('utf-8');\n const probeImage = new Resvg(markup);\n // resvg scales uniformly, so pick the axis that makes the bitmap cover\n // the placed box on both — matching the box aspect is not enough.\n const wide =\n probeImage.width / probeImage.height >\n transformation.width / transformation.height;\n // resvg derives the other edge from the SVG's own aspect ratio, so the\n // budget has to be applied against that, not against the placed box.\n const mode = wide ? ('height' as const) : ('width' as const);\n const value = capToPixelBudget(\n toRasterPx(wide ? transformation.height : transformation.width),\n wide\n ? probeImage.width / probeImage.height\n : probeImage.height / probeImage.width\n );\n\n if (value === undefined) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_SKIPPED',\n 'Inline SVG is too far from square to rasterize within the fallback ' +\n 'pixel budget, so its fallback only renders in Word 2016+.'\n );\n return undefined;\n }\n\n return Buffer.from(\n new Resvg(markup, { fitTo: { mode, value } }).render().asPng()\n );\n } catch (error) {\n reportWarning(\n 'image',\n 'IMAGE_SVG_RASTER_FAILED',\n `Could not rasterize inline SVG, so its fallback only renders in Word 2016+: ${String(error)}`\n );\n return undefined;\n }\n}\n\nexport interface ImageDimensions {\n width: number;\n height: number;\n}\n\nexport interface CalculatedDimensions {\n width: number;\n height: number;\n}\n\nexport interface ImageBufferResult {\n buffer: Buffer;\n contentType?: string;\n}\n\n/**\n * Parse width value - accepts either number (pixels) or percentage string\n * @param width - Width value as number or percentage string (e.g., \"90%\")\n * @param availableWidthPx - Available document width in pixels\n * @returns Width in pixels\n */\nexport function parseWidthValue(\n width: number | string,\n availableWidthPx: number\n): number {\n if (typeof width === 'number') {\n return width;\n }\n\n // Parse percentage string using shared util while preserving error semantics\n const percentageMatch = (width as string).match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percentageMatch) {\n const pct = parseFloat(percentageMatch[1]);\n if (pct < 0 || pct > 100) {\n throw new Error(\n `Invalid percentage value: ${width}. Must be between 0% and 100%`\n );\n }\n const fraction = parsePercentageStringToFraction(width as string);\n if (fraction !== undefined) {\n return Math.round(availableWidthPx * fraction);\n }\n }\n\n throw new Error(\n `Invalid width value: ${width}. Expected number (pixels) or percentage string (e.g., \"90%\")`\n );\n}\n\n/**\n * Parse a generic dimension value (number in px or percentage string)\n * @param value - numeric pixels or percentage string (e.g., \"100%\")\n * @param availablePx - available pixels for percentage reference\n */\nexport function parseDimensionValue(\n value: number | string,\n availablePx: number\n): number {\n if (typeof value === 'number') return value;\n const percentageMatch = (value as string).match(/^(\\d+(?:\\.\\d+)?)%$/);\n if (percentageMatch) {\n const pct = parseFloat(percentageMatch[1]);\n if (pct < 0 || pct > 100) {\n throw new Error(\n `Invalid percentage value: ${value}. Must be between 0% and 100%`\n );\n }\n const fraction = parsePercentageStringToFraction(value as string);\n if (fraction !== undefined) return Math.round(availablePx * fraction);\n }\n throw new Error(\n `Invalid dimension value: ${value}. Expected number (pixels) or percentage string (e.g., \"90%\")`\n );\n}\n\n/**\n * Check if a string is a valid URL\n */\nexport function isValidUrl(string: string): boolean {\n try {\n const url = new URL(string);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a string is a base64 data URI\n * Supports format: data:image/[type];base64,[data]\n */\nexport function isBase64Image(string: string): boolean {\n return /^data:image\\/[a-zA-Z+]+;base64,/.test(string);\n}\n\n/**\n * Decode base64 data URI to Buffer\n * @param dataUri - Base64 data URI (e.g., \"data:image/png;base64,iVBORw0KGgo...\")\n * @returns Decoded image buffer\n */\nexport function decodeBase64Image(dataUri: string): Buffer {\n try {\n // Extract the base64 data after the comma\n const base64Data = dataUri.split(',')[1];\n if (!base64Data) {\n throw new Error('Invalid base64 data URI format');\n }\n return Buffer.from(base64Data, 'base64');\n } catch (error) {\n throw new Error(\n `Failed to decode base64 image: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Extract MIME type from base64 data URI\n * @param dataUri - Base64 data URI (e.g., \"data:image/svg+xml;base64,...\")\n * @returns MIME type (e.g., \"image/svg+xml\") or undefined if not found\n */\nexport function extractMimeTypeFromDataUri(\n dataUri: string\n): string | undefined {\n const match = dataUri.match(/^data:(image\\/[a-zA-Z0-9+.-]+);base64,/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Detect image type from file extension\n * @param path - File path or URL\n * @returns Image type (jpg, png, gif, bmp, svg) or undefined\n */\nexport function detectImageTypeFromExtension(\n path: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' | undefined {\n const extension = path.toLowerCase().split('.').pop()?.split('?')[0]; // Handle query params in URLs\n switch (extension) {\n case 'jpg':\n case 'jpeg':\n return 'jpg';\n case 'png':\n return 'png';\n case 'gif':\n return 'gif';\n case 'bmp':\n return 'bmp';\n case 'svg':\n return 'svg';\n default:\n return undefined;\n }\n}\n\n/**\n * Detect image type from MIME type\n * @param mimeType - MIME type string (e.g., \"image/svg+xml\", \"image/png\")\n * @returns Image type (jpg, png, gif, bmp, svg) or undefined\n */\nexport function detectImageTypeFromMimeType(\n mimeType: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' | undefined {\n const normalized = mimeType.toLowerCase();\n if (normalized.includes('svg')) return 'svg';\n if (normalized.includes('jpeg') || normalized.includes('jpg')) return 'jpg';\n if (normalized.includes('png')) return 'png';\n if (normalized.includes('gif')) return 'gif';\n if (normalized.includes('bmp')) return 'bmp';\n return undefined;\n}\n\n/**\n * Detect image type from path or base64 data URI\n * Prioritizes: response Content-Type > MIME type from base64 > file extension > default to 'png'\n * @param imagePath - File path, URL, or base64 data URI\n * @param responseContentType - Optional Content-Type header from HTTP response\n * @returns Image type (jpg, png, gif, bmp, svg)\n */\nexport function detectImageType(\n imagePath: string,\n responseContentType?: string\n): 'jpg' | 'png' | 'gif' | 'bmp' | 'svg' {\n // Highest priority: Content-Type from HTTP response\n if (responseContentType) {\n const typeFromResponse = detectImageTypeFromMimeType(responseContentType);\n if (typeFromResponse) return typeFromResponse;\n }\n\n // Check if it's a base64 data URI and extract MIME type\n if (isBase64Image(imagePath)) {\n const mimeType = extractMimeTypeFromDataUri(imagePath);\n if (mimeType) {\n const typeFromMime = detectImageTypeFromMimeType(mimeType);\n if (typeFromMime) return typeFromMime;\n }\n }\n\n // Try to detect from file extension\n const typeFromExtension = detectImageTypeFromExtension(imagePath);\n if (typeFromExtension) return typeFromExtension;\n\n // Default to PNG for backward compatibility\n return 'png';\n}\n\n/**\n * Download image from URL and return buffer\n * Uses native fetch with automatic redirect following and proper headers\n */\nexport async function downloadImageFromUrl(\n url: string\n): Promise<ImageBufferResult> {\n try {\n // Create an AbortController for timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout\n\n const response = await fetch(url, {\n signal: controller.signal,\n headers: {\n 'User-Agent': 'Mozilla/5.0 (compatible; json-to-docx/1.0)',\n },\n redirect: 'follow', // Automatically follow redirects (default behavior)\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(\n `Failed to download image: HTTP ${response.status} ${response.statusText}`\n );\n }\n\n const contentType = response.headers.get('content-type') || undefined;\n\n // Get the response as an ArrayBuffer\n const arrayBuffer = await response.arrayBuffer();\n\n // Convert ArrayBuffer to Buffer\n return { buffer: Buffer.from(arrayBuffer), contentType };\n } catch (error) {\n if (error instanceof Error) {\n // Handle timeout errors\n if (error.name === 'AbortError') {\n throw new Error(\n 'Failed to download image: Request timeout after 10 seconds'\n );\n }\n throw new Error(`Failed to download image from ${url}: ${error.message}`);\n }\n throw new Error(`Failed to download image from ${url}: Unknown error`);\n }\n}\n\n/**\n * Resolve the effective image source string from image component props.\n * Precedence: raw inline `svg` markup (wrapped into an svg data URI) > `base64`\n * data URI > `path` (file/URL). Returns undefined when no source is provided.\n *\n * Raw SVG is encoded as a base64 svg+xml data URI so it flows through the same\n * pipeline as any other source (getImageBuffer / detectImageType / dimensions).\n */\nexport function resolveImageSource(props: {\n svg?: string;\n base64?: string;\n path?: string;\n}): string | undefined {\n const hasValue = (v?: string): v is string =>\n typeof v === 'string' && v.trim().length > 0;\n if (hasValue(props.svg)) {\n const encoded = Buffer.from(props.svg, 'utf-8').toString('base64');\n return `data:image/svg+xml;base64,${encoded}`;\n }\n // Blank base64/path count as absent (matching the source-conflict validator),\n // so a whitespace-only value can't shadow a real later source.\n if (hasValue(props.base64)) return props.base64;\n if (hasValue(props.path)) return props.path;\n return undefined;\n}\n\n/**\n * Get image buffer from base64 data URI, URL, or local file\n */\nexport async function getImageBuffer(\n imagePath: string\n): Promise<ImageBufferResult> {\n // Check for base64 data URI first\n if (isBase64Image(imagePath)) {\n return { buffer: decodeBase64Image(imagePath) };\n }\n // Check for URL\n if (isValidUrl(imagePath)) {\n return await downloadImageFromUrl(imagePath);\n }\n // Otherwise treat as local file path, relative to the document's base\n // directory when the generation scope set one (falls back to cwd, #142).\n return { buffer: readFileSync(resolveFromBaseDir(imagePath)) };\n}\n\n/**\n * Get the dimensions of an image file or URL\n */\nexport async function getImageDimensions(\n imagePath: string\n): Promise<ImageDimensions> {\n try {\n const { buffer: imageBuffer } = await getImageBuffer(imagePath);\n return readImageDimensions(imageBuffer, imagePath);\n } catch (error) {\n throw new Error(\n `Error reading image dimensions from ${imagePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Get the dimensions of bytes already in hand.\n *\n * The point is that it takes bytes rather than a location. A caller that has\n * loaded an image and then asks `getImageDimensions` for its size fetches the\n * same URL twice — doubling the network traffic, and, if the response changes\n * between the two, embedding one image while sizing it from another (#267).\n * `label` is only used in the message.\n */\nexport function readImageDimensions(\n bytes: Buffer,\n label: string\n): ImageDimensions {\n const result = probe.sync(bytes);\n\n if (!result) {\n throw new Error(`Unable to determine dimensions for image: ${label}`);\n }\n\n return { width: result.width, height: result.height };\n}\n\n/**\n * Calculate missing dimension while preserving aspect ratio\n */\nexport function calculateMissingDimension(\n originalWidth: number,\n originalHeight: number,\n targetWidth?: number,\n targetHeight?: number\n): CalculatedDimensions {\n if (targetWidth && targetHeight) {\n // Both dimensions provided, use as-is\n return { width: targetWidth, height: targetHeight };\n }\n\n const aspectRatio = originalWidth / originalHeight;\n\n if (targetWidth && !targetHeight) {\n // Width provided, calculate height\n return {\n width: targetWidth,\n height: Math.round(targetWidth / aspectRatio),\n };\n }\n\n if (!targetWidth && targetHeight) {\n // Height provided, calculate width\n return {\n width: Math.round(targetHeight * aspectRatio),\n height: targetHeight,\n };\n }\n\n // Neither provided, return original dimensions\n return { width: originalWidth, height: originalHeight };\n}\n\n/**\n * Calculate image dimensions with aspect ratio preservation and fallback constraints\n */\nexport async function calculateImageDimensions(\n imagePath: string,\n targetWidth?: number,\n targetHeight?: number,\n fallbackWidth: number = 300,\n fallbackHeight: number = 180\n): Promise<CalculatedDimensions> {\n try {\n const originalDimensions = await getImageDimensions(imagePath);\n return calculateMissingDimension(\n originalDimensions.width,\n originalDimensions.height,\n targetWidth,\n targetHeight\n );\n } catch (error) {\n // If we can't read the image, use fallback logic\n if (targetWidth && targetHeight) {\n return { width: targetWidth, height: targetHeight };\n }\n\n if (targetWidth && !targetHeight) {\n // Use a default aspect ratio (16:9) for fallback\n return { width: targetWidth, height: Math.round((targetWidth * 9) / 16) };\n }\n\n if (!targetWidth && targetHeight) {\n // Use a default aspect ratio (16:9) for fallback\n return {\n width: Math.round((targetHeight * 16) / 9),\n height: targetHeight,\n };\n }\n\n // No dimensions provided and can't read image, use fallback\n return { width: fallbackWidth, height: fallbackHeight };\n }\n}\n","/**\n * DocxIR — the renderer-neutral description of a finished Word document.\n *\n * Plain data only: no docx.js objects, no functions, no raw OOXML, no\n * backend-specific shapes. A renderer adapter is the only thing that turns\n * these nodes into a library call.\n *\n * By the time a document reaches this form, all of the following have happened\n * upstream (see `docs/architecture/office-renderer-ir.md`):\n *\n * - schema validation and structural conflict checks\n * - custom-component expansion\n * - theme resolution — every colour here is an explicit hex value\n * - component defaults\n * - font resolution/substitution, including synthesized weight aliases\n * - the inline text mini-language: `**bold**`, `[text](url)`, `[@ref]`,\n * `[^note]`, `{PAGE}` and friends are already inline nodes, not markup\n * - section and column layout resolution\n * - authoring-only expansion: `statistic`, `visual` and `highcharts` are gone,\n * replaced by the paragraphs and images they mean\n *\n * Units — stated in every property name, never implied:\n *\n * | Concern | Unit |\n * | --- | --- |\n * | page size, margins, indents, tab stops, spacing, table widths | twips (1/1440 in) |\n * | font size | half-points |\n * | drawing offsets and extents | EMU (1/914400 in) |\n * | image intrinsic size | pixels |\n * | border width | eighths of a point |\n * | character tracking | twentieths of a point |\n * | timestamps | ISO 8601 strings |\n */\n\n/** Twips per inch. */\nexport const TWIPS_PER_INCH = 1440;\n/** Twips per point. */\nexport const TWIPS_PER_POINT = 20;\n/** English Metric Units per inch. */\nexport const EMU_PER_INCH = 914400;\n/** English Metric Units per twip. */\nexport const EMU_PER_TWIP = EMU_PER_INCH / TWIPS_PER_INCH;\n\nexport const DOCX_IR_SCHEMA_VERSION = 1;\n\n/* ------------------------------------------------------------------ *\n * Root\n * ------------------------------------------------------------------ */\n\nexport interface DocxIR {\n schemaVersion: typeof DOCX_IR_SCHEMA_VERSION;\n metadata: DocxIrMetadata;\n settings: DocxIrSettings;\n /** Resolved paragraph and character styles, in registration order. */\n styles: DocxIrStyles;\n /** Numbering definitions referenced by list paragraphs. */\n numbering: DocxIrNumbering[];\n /** Deduplicated binary assets, in first-use order. */\n resources: DocxIrResource[];\n sections: DocxIrSection[];\n /** Comment bodies, referenced by id from comment range nodes. */\n comments: DocxIrComment[];\n footnotes: DocxIrNote[];\n endnotes: DocxIrNote[];\n}\n\nexport interface DocxIrMetadata {\n title?: string;\n subject?: string;\n author?: string;\n description?: string;\n keywords?: string;\n lastModifiedBy?: string;\n /** ISO 8601. Pinned by deterministic generation. */\n createdAt?: string;\n modifiedAt?: string;\n /** Custom document properties, in declaration order. */\n custom?: DocxIrCustomProperty[];\n}\n\nexport interface DocxIrCustomProperty {\n name: string;\n value: string;\n}\n\nexport interface DocxIrSettings {\n /** Default proofing language (BCP-47). */\n language?: string;\n /** Ask the reader to refresh fields on open. */\n updateFields: boolean;\n /** Turn on Word's track-changes mode in the produced document. */\n trackRevisions: boolean;\n /** Words the proofer should skip, applied as `w:noProof` on matching runs. */\n noProofWords?: string[];\n}\n\n/* ------------------------------------------------------------------ *\n * Styles\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrStyles {\n /** Formatting every paragraph and run starts from — `w:docDefaults`. */\n defaults: DocxIrStyleDefaults;\n paragraph: DocxIrParagraphStyle[];\n character: DocxIrCharacterStyle[];\n /**\n * Overrides for styles Word defines itself.\n *\n * A backend ships its own definitions for these, carrying Word's defaults\n * rather than the document's theme — a note in a Georgia document would\n * otherwise set in Calibri. Naming the slot rather than the style id keeps\n * the two backends' built-in vocabularies from leaking into the IR.\n */\n builtIn?: DocxIrBuiltInStyles;\n}\n\nexport interface DocxIrBuiltInStyle {\n run?: DocxIrRunFormatting;\n paragraph?: DocxIrParagraphFormatting;\n}\n\nexport interface DocxIrBuiltInStyles {\n footnoteText?: DocxIrBuiltInStyle;\n footnoteReference?: DocxIrBuiltInStyle;\n endnoteText?: DocxIrBuiltInStyle;\n endnoteReference?: DocxIrBuiltInStyle;\n}\n\nexport interface DocxIrStyleDefaults {\n run: DocxIrRunFormatting;\n paragraph: DocxIrParagraphFormatting;\n}\n\nexport interface DocxIrParagraphStyle {\n /** Style id as referenced by `DocxIrParagraph.styleId`. */\n id: string;\n /** Display name, which is what a TOC `\\t` switch matches on. */\n name: string;\n basedOn?: string;\n next?: string;\n /** 0-8; present only when the style participates in the outline. */\n outlineLevel?: number;\n quickFormat?: boolean;\n run?: DocxIrRunFormatting;\n paragraph?: DocxIrParagraphFormatting;\n}\n\nexport interface DocxIrCharacterStyle {\n id: string;\n name: string;\n basedOn?: string;\n run: DocxIrRunFormatting;\n}\n\n/* ------------------------------------------------------------------ *\n * Numbering\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrNumbering {\n /** Reference name used by `DocxIrParagraph.numbering.reference`. */\n reference: string;\n levels: DocxIrNumberingLevel[];\n}\n\nexport interface DocxIrNumberingLevel {\n /** 0-based. */\n level: number;\n /** OOXML `numFmt`, e.g. `decimal`, `bullet`, `lowerRoman`. */\n format: string;\n /** OOXML `lvlText`, e.g. `%1.` or `•`. */\n text: string;\n start?: number;\n alignment?: DocxIrAlignment;\n /** What follows the marker before the text. */\n suffix?: 'tab' | 'space' | 'nothing';\n indent?: DocxIrIndent;\n /** Formatting of the marker glyph itself. */\n run?: DocxIrRunFormatting;\n /** Bind this level to a paragraph style, so Word's numbering UI follows. */\n paragraphStyleId?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Resources\n * ------------------------------------------------------------------ */\n\n/**\n * A binary asset.\n *\n * Images are held as bytes because a DOCX embeds them by value; the identity\n * used for deduplication and for debug snapshots is the content hash.\n */\nexport interface DocxIrResource {\n /** Deterministic: `res${n}` in first-use order. */\n id: string;\n kind: 'image';\n mediaType: string;\n bytes: Uint8Array;\n byteLength: number;\n /** Lowercase hex SHA-256 of `bytes`. */\n sha256: string;\n intrinsic?: DocxIrPixelSize;\n /**\n * Raster fallback for a vector image.\n *\n * Word before 2016 draws the fallback rather than the SVG, so a vector\n * resource carries one. It is a resource in its own right, referenced here.\n */\n fallbackResourceId?: string;\n}\n\nexport interface DocxIrPixelSize {\n widthPx: number;\n heightPx: number;\n}\n\n/* ------------------------------------------------------------------ *\n * Shared value types\n * ------------------------------------------------------------------ */\n\nexport type DocxIrAlignment =\n | 'left'\n | 'center'\n | 'right'\n | 'justified'\n | 'start'\n | 'end';\n\nexport type DocxIrVerticalAlign = 'top' | 'center' | 'bottom';\n\n/**\n * A resolved colour: bare 6-digit hex without `#`, never a theme token.\n *\n * Case is preserved rather than normalised. OOXML reads hex case-insensitively,\n * so normalising would change nothing a reader can see while changing the bytes\n * of every document that ever stated a colour in lower case.\n */\nexport interface DocxIrColor {\n hex: string;\n}\n\nexport interface DocxIrIndent {\n leftTwips?: number;\n rightTwips?: number;\n firstLineTwips?: number;\n hangingTwips?: number;\n}\n\nexport interface DocxIrSpacing {\n beforeTwips?: number;\n afterTwips?: number;\n /** Line height in twips, with `lineRule` deciding how it is applied. */\n lineTwips?: number;\n lineRule?: 'auto' | 'exact' | 'atLeast';\n}\n\nexport interface DocxIrTabStop {\n positionTwips: number;\n type: 'left' | 'center' | 'right' | 'decimal' | 'bar' | 'clear';\n leader?: 'none' | 'dot' | 'hyphen' | 'underscore' | 'middleDot';\n}\n\nexport interface DocxIrBorder {\n style: string;\n color?: DocxIrColor;\n /** Eighths of a point, which is the OOXML unit for `w:sz` on a border. */\n sizeEighthPoints?: number;\n /** Points, which is the OOXML unit for `w:space` on a border. */\n spacePoints?: number;\n}\n\nexport interface DocxIrBorders {\n top?: DocxIrBorder;\n bottom?: DocxIrBorder;\n left?: DocxIrBorder;\n right?: DocxIrBorder;\n insideHorizontal?: DocxIrBorder;\n insideVertical?: DocxIrBorder;\n /** `w:between` — the rule drawn between consecutive paragraphs sharing it. */\n between?: DocxIrBorder;\n}\n\nexport interface DocxIrShading {\n fill: DocxIrColor;\n pattern?: string;\n color?: DocxIrColor;\n}\n\n/* ------------------------------------------------------------------ *\n * Run formatting\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrRunFormatting {\n /** Post-substitution family, possibly a synthesized weight alias. */\n fontFamily?: string;\n /** Half-points. */\n sizeHalfPoints?: number;\n color?: DocxIrColor;\n bold?: boolean;\n italic?: boolean;\n underline?: DocxIrUnderline;\n strike?: boolean;\n doubleStrike?: boolean;\n superScript?: boolean;\n subScript?: boolean;\n smallCaps?: boolean;\n allCaps?: boolean;\n highlight?: string;\n shading?: DocxIrShading;\n /** Horizontal scale, percent. */\n scalePercent?: number;\n /** Tracking, in twentieths of a point; negative condenses. */\n characterSpacingTwentieths?: number;\n /** BCP-47. */\n language?: string;\n /** Exclude from proofing. */\n noProof?: boolean;\n}\n\nexport interface DocxIrUnderline {\n type: string;\n color?: DocxIrColor;\n}\n\n/* ------------------------------------------------------------------ *\n * Paragraph formatting\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrParagraphFormatting {\n alignment?: DocxIrAlignment;\n spacing?: DocxIrSpacing;\n indent?: DocxIrIndent;\n tabStops?: DocxIrTabStop[];\n keepNext?: boolean;\n keepLines?: boolean;\n pageBreakBefore?: boolean;\n widowControl?: boolean;\n borders?: DocxIrBorders;\n shading?: DocxIrShading;\n /** 0-8. Set explicitly when a paragraph should join the outline. */\n outlineLevel?: number;\n bidirectional?: boolean;\n}\n\n/* ------------------------------------------------------------------ *\n * Inline nodes\n * ------------------------------------------------------------------ */\n\nexport type DocxIrInline =\n | DocxIrTextRun\n | DocxIrLineBreak\n | DocxIrPageBreakRun\n | DocxIrColumnBreakRun\n | DocxIrTabRun\n | DocxIrImageRun\n | DocxIrHyperlink\n | DocxIrBookmarkStart\n | DocxIrBookmarkEnd\n | DocxIrFieldRun\n | DocxIrNoteReference\n | DocxIrCommentRangeStart\n | DocxIrCommentRangeEnd\n | DocxIrCommentReference\n | DocxIrRevisionRange\n | DocxIrShapeRun;\n\n/**\n * A native text box: a shape holding paragraphs.\n *\n * Distinct from the one-cell table a text box usually becomes. A shape carries\n * an absolute size in the file, so it has no autofit and no lazy percentage\n * width, and it draws one uniform outline rather than four sides — which is why\n * a text box only becomes one when the author asks.\n */\nexport interface DocxIrShapeRun {\n kind: 'shape';\n widthPx: number;\n heightPx: number;\n children: DocxIrParagraph[];\n fill?: DocxIrColor;\n outline?: { color: DocxIrColor; widthEmu?: number };\n /** Text insets, in EMU like every other DrawingML length. */\n insetsEmu?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n };\n /** Absent makes it an inline drawing rather than an anchored one. */\n floating?: DocxIrFloating;\n}\n\nexport interface DocxIrTextRun {\n kind: 'text';\n text: string;\n formatting?: DocxIrRunFormatting;\n /** Character style applied on top of `formatting`. */\n styleId?: string;\n}\n\nexport interface DocxIrLineBreak {\n kind: 'lineBreak';\n /** `textWrapping` is a plain newline; the others clear a floating object. */\n clear?: 'none' | 'left' | 'right' | 'all';\n}\n\nexport interface DocxIrPageBreakRun {\n kind: 'pageBreak';\n}\n\nexport interface DocxIrColumnBreakRun {\n kind: 'columnBreak';\n}\n\n/**\n * A tab, as its own run.\n *\n * A tab character inside `<w:t>` is dropped by Word and paragraph tab stops\n * only bind to real tab runs — and the run carries formatting like any other,\n * because the space it advances through is drawn in that font.\n */\nexport interface DocxIrTabRun {\n kind: 'tab';\n formatting?: DocxIrRunFormatting;\n}\n\n/**\n * An image placed inline in a paragraph.\n *\n * Floating placement lives on the paragraph, not here: OOXML anchors a floating\n * drawing to a paragraph, and modelling it on the run would misdescribe that.\n */\nexport interface DocxIrImageRun {\n kind: 'image';\n resourceId: string;\n widthEmu: number;\n heightEmu: number;\n altText?: string;\n /** Present when the drawing is anchored rather than inline. */\n floating?: DocxIrFloating;\n}\n\nexport interface DocxIrHyperlink {\n kind: 'hyperlink';\n target: DocxIrHyperlinkTarget;\n children: DocxIrInline[];\n}\n\nexport type DocxIrHyperlinkTarget =\n | { kind: 'external'; url: string }\n | { kind: 'bookmark'; anchor: string };\n\n/**\n * Bookmark boundaries.\n *\n * Emitted as explicit paired nodes with compiler-allocated ids rather than a\n * wrapper, because a bookmark range can legitimately cross paragraph and even\n * table boundaries.\n */\nexport interface DocxIrBookmarkStart {\n kind: 'bookmarkStart';\n id: number;\n name: string;\n}\n\nexport interface DocxIrBookmarkEnd {\n kind: 'bookmarkEnd';\n id: number;\n}\n\n/**\n * A Word field.\n *\n * `cachedText` is what a reader shows before it refreshes the field — headless\n * converters never refresh, so caching is the difference between a rendered\n * value and a blank.\n */\nexport interface DocxIrFieldRun {\n kind: 'field';\n /** Field instruction, e.g. `PAGE`, `NUMPAGES`, `REF _Ref123 \\\\r \\\\h`. */\n instruction: string;\n cachedText?: string;\n formatting?: DocxIrRunFormatting;\n}\n\nexport interface DocxIrNoteReference {\n kind: 'noteReference';\n noteKind: 'footnote' | 'endnote';\n /** Matches an entry in `DocxIR.footnotes` / `DocxIR.endnotes`. */\n id: number;\n}\n\nexport interface DocxIrCommentRangeStart {\n kind: 'commentRangeStart';\n id: number;\n}\n\nexport interface DocxIrCommentRangeEnd {\n kind: 'commentRangeEnd';\n id: number;\n}\n\nexport interface DocxIrCommentReference {\n kind: 'commentReference';\n id: number;\n}\n\n/**\n * Inserted or deleted content.\n *\n * A range rather than a run flag, because a revision covers a span and its\n * `id`/`author`/`date` belong to the span, not to each run inside it.\n */\nexport interface DocxIrRevisionRange {\n kind: 'revision';\n type: 'insert' | 'delete';\n id: number;\n author: string;\n /** ISO 8601. */\n date: string;\n children: DocxIrInline[];\n}\n\n/* ------------------------------------------------------------------ *\n * Floating placement\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrFloating {\n /**\n * Where the drawing sits on each axis.\n *\n * Both are optional because an author may float an image purely to change\n * how text wraps around it, stating no position at all; the anchor then\n * keeps whatever position its container gives it.\n */\n horizontal?: DocxIrFloatingPosition;\n vertical?: DocxIrFloatingPosition;\n /** Distance kept clear of surrounding text, in EMU. */\n margins?: DocxIrFloatingMargins;\n wrap?: DocxIrTextWrap;\n /** Always emitted: some backends otherwise derive it from the height. */\n zIndex: number;\n behindDocument?: boolean;\n allowOverlap?: boolean;\n /** Keep the anchor with the paragraph it is attached to. */\n lockAnchor?: boolean;\n /** Position the drawing inside its table cell rather than the page. */\n layoutInCell?: boolean;\n}\n\nexport interface DocxIrFloatingPosition {\n /**\n * OOXML's `relativeFrom`. Absent when the author named a frame of reference\n * OOXML has no element for, in which case the backend's own default applies.\n */\n relativeTo?: string;\n /** Offset in EMU. Mutually exclusive with `align`. */\n offsetEmu?: number;\n align?: string;\n}\n\nexport interface DocxIrFloatingMargins {\n topEmu?: number;\n bottomEmu?: number;\n leftEmu?: number;\n rightEmu?: number;\n}\n\nexport interface DocxIrTextWrap {\n /**\n * OOXML's own vocabulary.\n *\n * `tight` is reachable only from the authoring values `around` and `through`,\n * which have no OOXML equivalent of their own; asking for `tight` directly is\n * rejected at compile time because it needs polygon geometry no backend here\n * emits.\n */\n type: 'none' | 'square' | 'tight' | 'topAndBottom';\n side?: 'bothSides' | 'left' | 'right' | 'largest';\n}\n\n/* ------------------------------------------------------------------ *\n * Block nodes\n * ------------------------------------------------------------------ */\n\nexport type DocxIrBlock = DocxIrParagraph | DocxIrTable | DocxIrTableOfContents;\n\nexport interface DocxIrParagraph {\n kind: 'paragraph';\n /** Deterministic, path-derived: e.g. `s0.b3`, `s0.b3.r1.c0.b0`. */\n id: string;\n /** IR path for diagnostics: e.g. `sections[0].children[3]`. */\n path: string;\n children: DocxIrInline[];\n styleId?: string;\n formatting?: DocxIrParagraphFormatting;\n numbering?: DocxIrParagraphNumbering;\n /** Revision applied to the paragraph mark itself. */\n markRevision?: DocxIrParagraphMarkRevision;\n /** Anchor for a floating drawing carried by this paragraph's runs. */\n frame?: DocxIrFrame;\n}\n\n/**\n * A paragraph's place in a numbering sequence.\n *\n * `none` is not \"no numbering stated\" — that is expressed by leaving the whole\n * field out. It is an explicit detachment (OOXML `numId 0`), which is how a\n * single heading opts out of a numbering its style applies.\n */\nexport type DocxIrParagraphNumbering =\n | { none: true }\n | {\n none?: false;\n reference: string;\n /** 0-based. */\n level: number;\n };\n\nexport interface DocxIrParagraphMarkRevision {\n type: 'insert' | 'delete';\n id: number;\n author: string;\n date: string;\n}\n\n/**\n * A text frame: a paragraph positioned as a floating box.\n *\n * Distinct from `DocxIrFloating`, which positions a drawing. A frame positions\n * the paragraph itself.\n */\nexport interface DocxIrFrame {\n widthTwips: number;\n heightTwips: number;\n anchorHorizontal: string;\n anchorVertical: string;\n xTwips?: number;\n yTwips?: number;\n xAlign?: string;\n yAlign?: string;\n wrap?: string;\n rule?: 'auto' | 'exact' | 'atLeast';\n /** Keep the frame with the paragraph it is anchored to. */\n anchorLock?: boolean;\n}\n\n/* ------------------------------------------------------------------ *\n * Tables\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrTable {\n kind: 'table';\n id: string;\n path: string;\n rows: DocxIrTableRow[];\n columnGrid: DocxIrColumnGrid;\n width: DocxIrTableWidth;\n /** Fixed layout is what the pipeline has always produced. */\n layout: 'fixed' | 'autofit';\n borders?: DocxIrBorders;\n alignment?: DocxIrAlignment;\n /** Default cell margins in twips. */\n cellMargins?: DocxIrCellMargins;\n /** Keep the whole table on one page where the format allows. */\n keepInOnePage?: boolean;\n /** Float the table out of the text flow. */\n floating?: DocxIrTableFloating;\n}\n\n/**\n * The table's column grid (`w:tblGrid`).\n *\n * `twips` is the real OOXML unit. `percent` is what the pipeline writes when no\n * column states a width: the grid then carries a percentage per column rather\n * than a width, which Word tolerates because the table itself is sized in\n * percent.\n */\nexport interface DocxIrColumnGrid {\n unit: 'twips' | 'percent';\n values: number[];\n}\n\nexport type DocxIrTableWidth =\n | { kind: 'twips'; value: number }\n | { kind: 'percent'; value: number }\n | { kind: 'auto' };\n\nexport interface DocxIrCellMargins {\n topTwips?: number;\n bottomTwips?: number;\n leftTwips?: number;\n rightTwips?: number;\n}\n\nexport interface DocxIrTableRow {\n cells: DocxIrTableCell[];\n /** Row height in twips. */\n heightTwips?: number;\n heightRule?: 'auto' | 'exact' | 'atLeast';\n /** Repeat this row at the top of each page the table spans. */\n isHeader?: boolean;\n cantSplit?: boolean;\n /**\n * A revision on the row.\n *\n * Word needs both this and a matching revision on every run inside, or\n * accepting a deletion leaves an empty row behind.\n */\n revision?: DocxIrParagraphMarkRevision;\n}\n\nexport interface DocxIrTableCell {\n /** Cells hold blocks, so a cell can contain a paragraph, image or table. */\n children: DocxIrBlock[];\n columnSpan?: number;\n /** `restart` begins a vertical merge, `continue` extends it. */\n rowSpan?: 'restart' | 'continue';\n widthTwips?: number;\n verticalAlign?: DocxIrVerticalAlign;\n borders?: DocxIrBorders;\n shading?: DocxIrShading;\n margins?: DocxIrCellMargins;\n /** Rotate the cell's text. */\n textDirection?: string;\n}\n\nexport interface DocxIrTableFloating {\n horizontalAnchor?: string;\n verticalAnchor?: string;\n absoluteHorizontalPositionTwips?: number;\n absoluteVerticalPositionTwips?: number;\n relativeHorizontalPosition?: string;\n relativeVerticalPosition?: string;\n topFromTextTwips?: number;\n bottomFromTextTwips?: number;\n leftFromTextTwips?: number;\n rightFromTextTwips?: number;\n overlap?: 'never' | 'overlap';\n}\n\n/* ------------------------------------------------------------------ *\n * Table of contents\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrTableOfContents {\n kind: 'toc';\n id: string;\n path: string;\n /** Heading outline levels to include, inclusive. */\n headingRange?: { from: number; to: number };\n /** Additional paragraph styles, by display name, with their outline level. */\n styleLevels?: Array<{ styleName: string; level: number }>;\n /** Restrict the TOC to a bookmarked region. */\n bookmarkScope?: string;\n hyperlink?: boolean;\n /** The field's alias, shown while the entries are collapsed. */\n alias?: string;\n /**\n * Outline level ranges whose entries omit a page number.\n *\n * Ranges rather than a level list because that is what OOXML's `\\n` switch\n * takes, and because the levels omitted are always contiguous blocks either\n * side of the range that keeps its numbers.\n */\n omitPageNumbersForLevels?: Array<{ from: number; to: number }>;\n /** Separator between entry text and page number. */\n entrySeparator?: string;\n /**\n * Entries baked in so a reader that never refreshes fields still shows a\n * table of contents. Headless converters never refresh.\n */\n cachedEntries?: DocxIrTocEntry[];\n}\n\nexport interface DocxIrTocEntry {\n text: string;\n level: number;\n /**\n * The bookmark the entry links to, when one is known.\n *\n * A cached entry does not need one: Word rebuilds the links the moment it\n * refreshes the field, and a reader that never refreshes shows the text\n * without following it anywhere.\n */\n bookmark?: string;\n}\n\n/* ------------------------------------------------------------------ *\n * Sections\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrSection {\n id: string;\n path: string;\n children: DocxIrBlock[];\n properties: DocxIrSectionProperties;\n headers?: DocxIrHeaderFooterSet;\n footers?: DocxIrHeaderFooterSet;\n /**\n * A bookmark covering this section's content.\n *\n * OOXML has no notion of a bookmarked section, so a section that something\n * can point at — a table of contents scoped to it, an internal link — is a\n * bookmark range around its content. One authored section can be split into\n * several layout sections, which is why `opens` and `closes` are separate:\n * the range starts in the first and ends in the last, and they share an id.\n */\n bookmark?: DocxIrSectionBookmark;\n}\n\nexport interface DocxIrSectionBookmark {\n id: number;\n name: string;\n opens: boolean;\n closes: boolean;\n}\n\nexport interface DocxIrSectionProperties {\n page: DocxIrPageSetup;\n columns?: DocxIrColumns;\n /** Where this section starts relative to the previous one. */\n type?: 'nextPage' | 'nextColumn' | 'continuous' | 'evenPage' | 'oddPage';\n pageNumbers?: DocxIrPageNumbering;\n borders?: DocxIrPageBorders;\n /** Distinct first-page header/footer. */\n titlePage?: boolean;\n}\n\nexport interface DocxIrPageSetup {\n widthTwips: number;\n heightTwips: number;\n orientation: 'portrait' | 'landscape';\n /**\n * OOXML `w:pgSz/@w:code` — the paper code a printer driver keys off.\n * Present only for a named size; a custom width/height has none.\n */\n code?: number;\n margins: DocxIrPageMargins;\n}\n\nexport interface DocxIrPageMargins {\n topTwips: number;\n bottomTwips: number;\n leftTwips: number;\n rightTwips: number;\n headerTwips?: number;\n footerTwips?: number;\n gutterTwips?: number;\n}\n\nexport interface DocxIrColumns {\n count: number;\n spaceTwips?: number;\n separator?: boolean;\n equalWidth?: boolean;\n /** Explicit per-column widths; length matches `count` when present. */\n widths?: Array<{ widthTwips: number; spaceTwips?: number }>;\n}\n\nexport interface DocxIrPageNumbering {\n start?: number;\n formatType?: string;\n}\n\nexport interface DocxIrPageBorders {\n display?: string;\n offsetFrom?: 'page' | 'text';\n borders?: DocxIrBorders;\n}\n\nexport interface DocxIrHeaderFooterSet {\n default?: DocxIrHeaderFooter;\n first?: DocxIrHeaderFooter;\n even?: DocxIrHeaderFooter;\n}\n\nexport interface DocxIrHeaderFooter {\n /** Deterministic: `header:s0:default`. */\n id: string;\n children: DocxIrBlock[];\n}\n\n/* ------------------------------------------------------------------ *\n * Comments and notes\n * ------------------------------------------------------------------ */\n\nexport interface DocxIrComment {\n id: number;\n author: string;\n initials?: string;\n /** ISO 8601. */\n date: string;\n children: DocxIrBlock[];\n /** Threading: the comment this one replies to. */\n parentId?: number;\n resolved?: boolean;\n}\n\nexport interface DocxIrNote {\n id: number;\n children: DocxIrBlock[];\n}\n","/**\n * Unit and identity helpers for DocxIR construction.\n *\n * The DOCX authoring surface mixes units — points for spacing, twips for\n * indents, pixels for image sizes, inches for a visual canvas — and the IR\n * mixes none: every value is converted here, once, into the unit its property\n * name states.\n */\n\nimport { createHash } from 'node:crypto';\nimport { EMU_PER_TWIP, TWIPS_PER_INCH, TWIPS_PER_POINT } from './types';\n\n/** Points → twips. Spacing, padding and row heights are authored in points. */\nexport function pointsToTwips(points: number): number {\n return Math.round(points * TWIPS_PER_POINT);\n}\n\n/** Points → half-points, the OOXML unit for a font size. */\nexport function pointsToHalfPoints(points: number): number {\n return Math.round(points * 2);\n}\n\n/** Points → eighths of a point, the OOXML unit for a border width. */\nexport function pointsToEighthPoints(points: number): number {\n return Math.round(points * 8);\n}\n\n/** Inches → twips. */\nexport function inchesToTwips(inches: number): number {\n return Math.round(inches * TWIPS_PER_INCH);\n}\n\n/** Twips → EMU. */\nexport function twipsToEmu(twips: number): number {\n return Math.round(twips * EMU_PER_TWIP);\n}\n\n/** Pixels at 96 DPI → EMU, which is how image extents are expressed. */\nexport function pixelsToEmu(pixels: number): number {\n return Math.round(pixels * 9525);\n}\n\n/** EMU → pixels at 96 DPI, the inverse of {@link pixelsToEmu}. */\nexport function emuToPixels(emu: number): number {\n return emu / 9525;\n}\n\n/** Pixels at 96 DPI → twips. */\nexport function pixelsToTwips(pixels: number): number {\n return Math.round(pixels * 15);\n}\n\n/** Twips → pixels at 96 DPI. */\nexport function twipsToPixels(twips: number): number {\n return (twips / TWIPS_PER_INCH) * 96;\n}\n\n/**\n * Resolve a length that may be a percentage of a containing box.\n *\n * `\"50%\"` resolves against `containerTwips`; a number is already twips.\n * Anything unparseable resolves to 0 rather than throwing, matching what the\n * pre-IR pipeline did.\n */\nexport function resolveLengthTwips(\n value: number | string,\n containerTwips: number\n): number {\n if (typeof value === 'number') return Math.round(value);\n const trimmed = value.trim();\n if (trimmed.endsWith('%')) {\n const percent = Number.parseFloat(trimmed);\n return Number.isNaN(percent)\n ? 0\n : Math.round((percent / 100) * containerTwips);\n }\n const parsed = Number(trimmed);\n return Number.isNaN(parsed) ? 0 : Math.round(parsed);\n}\n\n/**\n * Build an IR colour from an already-resolved hex string.\n *\n * Theme tokens are resolved upstream; this only strips the `#` prefix, so an\n * unresolved token cannot reach the IR by accident. Case is left alone — OOXML\n * reads hex case-insensitively, so normalising it would rewrite the bytes of\n * every document that stated a colour in lower case and change nothing else.\n */\nexport function irColor(hex: string): { hex: string } {\n return { hex: hex.startsWith('#') ? hex.slice(1) : hex };\n}\n\n/** Lowercase hex SHA-256, the identity used for resources. */\nexport function sha256Hex(bytes: Uint8Array): string {\n return createHash('sha256').update(bytes).digest('hex');\n}\n\n/**\n * Deterministic block id from its position in the document tree.\n *\n * Ids are derived, never allocated from a shared counter, so two concurrent\n * generations of the same document produce the same ids.\n */\nexport function blockId(\n sectionIndex: number,\n indexPath: readonly number[]\n): string {\n return `s${sectionIndex}.${indexPath.map((i) => `b${i}`).join('.')}`;\n}\n\n/** Deterministic id for a block inside a header or footer part. */\nexport function headerFooterBlockId(\n partId: string,\n indexPath: readonly number[]\n): string {\n return `${partId}.${indexPath.map((i) => `b${i}`).join('.')}`;\n}\n","/**\n * DocxIR → docx.js objects.\n *\n * Each function maps one IR node onto the option bag docx.js expects. Every\n * cascade, default and unit conversion already happened in the compiler, so\n * this layer only translates vocabulary — with two exceptions that are\n * genuinely properties of *this* backend:\n *\n * - A line break is not a node here. docx.js expresses it as `break: 1` on the\n * run that follows, so a `lineBreak` in the IR is folded into the next run.\n * - A tab is a run containing a `Tab`, because a tab character inside `<w:t>`\n * is dropped by Word and paragraph tab stops only bind to real tab runs.\n */\n\nimport {\n AlignmentType,\n BookmarkEnd,\n BookmarkStart,\n BorderStyle,\n ColumnBreak,\n CommentRangeEnd,\n CommentRangeStart,\n CommentReference,\n DeletedTextRun,\n EndnoteReferenceRun,\n ExternalHyperlink,\n FootnoteReferenceRun,\n InsertedTextRun,\n InternalHyperlink,\n OverlapType,\n PageNumber,\n Paragraph,\n RelativeHorizontalPosition,\n RelativeVerticalPosition,\n SimpleField,\n StyleLevel,\n Tab,\n Table,\n TableAnchorType,\n TableCell,\n TableLayoutType,\n TableOfContents,\n TableRow,\n TextRun,\n VerticalAlign,\n TextWrappingType,\n WidthType,\n WpsShapeRun,\n type IFrameOptions,\n type IParagraphOptions,\n type IRunOptions,\n type ITableCellOptions,\n type ParagraphChild,\n} from 'docx';\nimport { assertNever } from '@json-to-office/shared/rendering';\nimport type {\n DocxIrBlock,\n DocxIrBorder,\n DocxIrFloating,\n DocxIrFrame,\n DocxIrImageRun,\n DocxIrInline,\n DocxIrParagraph,\n DocxIrParagraphFormatting,\n DocxIrParagraphMarkRevision,\n DocxIrRevisionRange,\n DocxIrRunFormatting,\n DocxIrShapeRun,\n DocxIrTable,\n DocxIrTableCell,\n DocxIrTableFloating,\n DocxIrTableOfContents,\n DocxIrTableRow,\n} from '../../ir/types';\n\nexport const ALIGNMENT: Readonly<\n Record<string, (typeof AlignmentType)[keyof typeof AlignmentType]>\n> = {\n left: AlignmentType.LEFT,\n center: AlignmentType.CENTER,\n right: AlignmentType.RIGHT,\n justified: AlignmentType.JUSTIFIED,\n start: AlignmentType.START,\n end: AlignmentType.END,\n};\n\n/**\n * Image runs, keyed by IR resource id.\n *\n * docx.js needs an `ImageRun` object, and building one for a vector image is\n * asynchronous — it rasterises a fallback. So the renderer builds them all\n * before the document, and this layer only places them.\n */\nexport type EmitResources = ReadonlyMap<string, ImageRunFactory>;\n\n/** Builds the run for one placement, which carries its own size and anchor. */\nexport type ImageRunFactory = (image: DocxIrImageRun) => ParagraphChild;\n\n/**\n * The field instructions docx.js has a run child for.\n *\n * Anything else would need the begin/instrText/end triple written by hand,\n * which is why an unknown instruction is refused rather than approximated.\n */\nconst PAGE_FIELD: Readonly<\n Record<string, (typeof PageNumber)[keyof typeof PageNumber]>\n> = {\n PAGE: PageNumber.CURRENT,\n NUMPAGES: PageNumber.TOTAL_PAGES,\n};\n\n/* ------------------------------------------------------------------ *\n * Runs\n * ------------------------------------------------------------------ */\n\nexport function runOptions(\n formatting: DocxIrRunFormatting | undefined\n): IRunOptions {\n if (!formatting) return {};\n const options: Record<string, unknown> = {};\n if (formatting.fontFamily) options.font = formatting.fontFamily;\n if (formatting.sizeHalfPoints !== undefined) {\n options.size = formatting.sizeHalfPoints;\n }\n if (formatting.color) options.color = formatting.color.hex;\n if (formatting.bold !== undefined) options.bold = formatting.bold;\n if (formatting.italic !== undefined) options.italics = formatting.italic;\n if (formatting.underline !== undefined) {\n options.underline = formatting.underline\n ? { type: formatting.underline.type }\n : undefined;\n }\n if (formatting.strike !== undefined) options.strike = formatting.strike;\n if (formatting.scalePercent !== undefined) {\n options.scale = formatting.scalePercent;\n }\n if (formatting.characterSpacingTwentieths !== undefined) {\n options.characterSpacing = formatting.characterSpacingTwentieths;\n }\n if (formatting.language) {\n options.language = { value: formatting.language };\n }\n if (formatting.noProof !== undefined) options.noProof = formatting.noProof;\n return options as IRunOptions;\n}\n\n/**\n * Turn inline nodes into paragraph children.\n *\n * `pendingBreaks` carries a run of `lineBreak` nodes forward onto whichever run\n * comes next, which is where docx.js puts them.\n */\nexport function inlineChildren(\n children: readonly DocxIrInline[],\n resources: EmitResources = new Map()\n): ParagraphChild[] {\n const out: ParagraphChild[] = [];\n let pendingBreaks = 0;\n\n const breakOption = (): { break?: number } => {\n if (pendingBreaks === 0) return {};\n const value = { break: pendingBreaks };\n pendingBreaks = 0;\n return value;\n };\n\n for (const child of children) {\n switch (child.kind) {\n case 'lineBreak':\n pendingBreaks += 1;\n break;\n\n case 'text':\n out.push(\n new TextRun({\n text: child.text,\n ...runOptions(child.formatting),\n ...breakOption(),\n })\n );\n break;\n\n case 'tab':\n out.push(\n new TextRun({\n children: [new Tab()],\n ...runOptions(child.formatting),\n ...breakOption(),\n })\n );\n break;\n\n case 'columnBreak':\n out.push(new ColumnBreak());\n break;\n\n case 'pageBreak':\n out.push(new TextRun({ break: 1 }));\n break;\n\n case 'bookmarkStart':\n out.push(new BookmarkStart(child.name, child.id));\n break;\n\n case 'bookmarkEnd':\n out.push(new BookmarkEnd(child.id));\n break;\n\n case 'image': {\n const build = resources.get(child.resourceId);\n if (!build) {\n throw new Error(\n `no image was prepared for resource \"${child.resourceId}\"`\n );\n }\n // A break before an image belongs on a run of its own: docx.js puts a\n // break and a drawing in the same run only by dropping one.\n const pending = breakOption();\n if (pending.break) out.push(new TextRun(pending));\n out.push(build(child));\n break;\n }\n\n case 'hyperlink':\n out.push(\n child.target.kind === 'bookmark'\n ? new InternalHyperlink({\n children: inlineChildren(\n child.children,\n resources\n ) as TextRun[],\n anchor: child.target.anchor,\n })\n : new ExternalHyperlink({\n children: inlineChildren(\n child.children,\n resources\n ) as TextRun[],\n link: child.target.url,\n })\n );\n break;\n\n case 'field': {\n if (child.instruction.startsWith('REF ')) {\n // A REF field is a whole `w:fldSimple`, not a run child, so it goes\n // in as its own element with its cached text inside.\n out.push(new SimpleField(child.instruction, child.cachedText));\n break;\n }\n const page = PAGE_FIELD[child.instruction];\n if (!page) {\n throw new Error(\n `the docxjs renderer has no emitter for the field \"${child.instruction}\"`\n );\n }\n out.push(\n new TextRun({\n children: [page],\n ...runOptions(child.formatting),\n ...breakOption(),\n })\n );\n break;\n }\n\n case 'revision':\n out.push(...emitRevision(child, breakOption()));\n break;\n\n case 'commentRangeStart':\n out.push(new CommentRangeStart(child.id));\n break;\n\n case 'commentRangeEnd':\n out.push(new CommentRangeEnd(child.id));\n break;\n\n case 'commentReference':\n // `w:commentReference` is run-inner content, so it has to sit inside a\n // `w:r`. Emitted as a direct child of `w:p` it is schema-invalid and\n // readers drop the comment without saying so.\n out.push(new TextRun({ children: [new CommentReference(child.id)] }));\n break;\n\n case 'shape':\n out.push(emitShape(child, resources));\n break;\n\n case 'noteReference':\n out.push(\n child.noteKind === 'endnote'\n ? new EndnoteReferenceRun(child.id)\n : new FootnoteReferenceRun(child.id)\n );\n break;\n\n default:\n assertNever(child, 'DocxIrInline');\n }\n }\n\n return out;\n}\n\n/**\n * A tracked change, as runs marked with its id.\n *\n * Every text child becomes a run carrying the range's `w:ins` / `w:del`\n * attributes: docx.js has no wrapper element, so the mark rides on the runs.\n */\nfunction emitRevision(\n range: DocxIrRevisionRange,\n pending: { break?: number }\n): ParagraphChild[] {\n const mark = {\n id: range.id,\n author: range.author,\n date: range.date,\n };\n const out: ParagraphChild[] = [];\n let breaks = pending.break ?? 0;\n\n for (const child of range.children) {\n if (child.kind === 'lineBreak') {\n breaks += 1;\n continue;\n }\n if (child.kind !== 'text') {\n throw new Error(\n `the docxjs renderer has no emitter for \"${child.kind}\" inside a revision`\n );\n }\n const options = {\n text: child.text,\n ...runOptions(child.formatting),\n ...(breaks > 0 ? { break: breaks } : {}),\n ...mark,\n };\n breaks = 0;\n out.push(\n range.type === 'insert'\n ? new InsertedTextRun(options)\n : new DeletedTextRun(options)\n );\n }\n\n return out;\n}\n\n/** docx.js numbers its wrap types; OOXML names them. */\nconst WRAP_TYPE: Readonly<\n Record<string, (typeof TextWrappingType)[keyof typeof TextWrappingType]>\n> = {\n none: TextWrappingType.NONE,\n square: TextWrappingType.SQUARE,\n tight: TextWrappingType.TIGHT,\n topAndBottom: TextWrappingType.TOP_AND_BOTTOM,\n};\n\n/** An IR anchor as docx.js floating options. */\nexport function floatingOptions(\n floating: DocxIrFloating\n): Record<string, unknown> {\n return {\n ...(floating.horizontal\n ? {\n horizontalPosition: {\n ...(floating.horizontal.relativeTo\n ? { relative: floating.horizontal.relativeTo }\n : {}),\n ...(floating.horizontal.align !== undefined\n ? { align: floating.horizontal.align }\n : {}),\n ...(floating.horizontal.offsetEmu !== undefined\n ? { offset: floating.horizontal.offsetEmu }\n : {}),\n },\n }\n : {}),\n ...(floating.vertical\n ? {\n verticalPosition: {\n ...(floating.vertical.relativeTo\n ? { relative: floating.vertical.relativeTo }\n : {}),\n ...(floating.vertical.align !== undefined\n ? { align: floating.vertical.align }\n : {}),\n ...(floating.vertical.offsetEmu !== undefined\n ? { offset: floating.vertical.offsetEmu }\n : {}),\n },\n }\n : {}),\n ...(floating.wrap\n ? {\n wrap: {\n type: WRAP_TYPE[floating.wrap.type],\n ...(floating.wrap.side ? { side: floating.wrap.side } : {}),\n },\n }\n : {}),\n ...(floating.margins\n ? {\n margins: {\n ...(floating.margins.topEmu !== undefined\n ? { top: floating.margins.topEmu }\n : {}),\n ...(floating.margins.bottomEmu !== undefined\n ? { bottom: floating.margins.bottomEmu }\n : {}),\n ...(floating.margins.leftEmu !== undefined\n ? { left: floating.margins.leftEmu }\n : {}),\n ...(floating.margins.rightEmu !== undefined\n ? { right: floating.margins.rightEmu }\n : {}),\n },\n }\n : {}),\n ...(floating.allowOverlap !== undefined\n ? { allowOverlap: floating.allowOverlap }\n : {}),\n ...(floating.behindDocument !== undefined\n ? { behindDocument: floating.behindDocument }\n : {}),\n ...(floating.lockAnchor !== undefined\n ? { lockAnchor: floating.lockAnchor }\n : {}),\n ...(floating.layoutInCell !== undefined\n ? { layoutInCell: floating.layoutInCell }\n : {}),\n zIndex: floating.zIndex,\n };\n}\n\n/**\n * A native text box, as a `wps:wsp` shape run.\n *\n * docx 9.7.1 emits `a:noFill` + `a:ln` for an outline and then `a:solidFill`\n * for the fill — two fill groups, in the wrong order for CT_ShapeProperties,\n * which Word rejects. The compiler resolves that conflict before it gets here,\n * so a shape never arrives with both.\n */\nfunction emitShape(\n shape: DocxIrShapeRun,\n resources: EmitResources\n): ParagraphChild {\n return new WpsShapeRun({\n type: 'wps',\n children: shape.children.map((child) => emitParagraph(child, resources)),\n transformation: { width: shape.widthPx, height: shape.heightPx },\n ...(shape.fill\n ? { solidFill: { type: 'rgb', value: shape.fill.hex } as const }\n : {}),\n ...(shape.outline\n ? {\n outline: {\n type: 'solidFill' as const,\n solidFillType: 'rgb' as const,\n value: shape.outline.color.hex,\n ...(shape.outline.widthEmu !== undefined\n ? { width: shape.outline.widthEmu }\n : {}),\n },\n }\n : {}),\n ...(shape.insetsEmu\n ? { bodyProperties: { margins: shape.insetsEmu } }\n : {}),\n ...(shape.floating ? { floating: floatingOptions(shape.floating) } : {}),\n } as ConstructorParameters<typeof WpsShapeRun>[0]);\n}\n\n/* ------------------------------------------------------------------ *\n * Paragraphs\n * ------------------------------------------------------------------ */\n\nexport function paragraphOptions(\n formatting: DocxIrParagraphFormatting | undefined\n): Partial<IParagraphOptions> {\n const options: Record<string, unknown> = {};\n if (!formatting) return options as Partial<IParagraphOptions>;\n\n if (formatting.alignment) {\n options.alignment = ALIGNMENT[formatting.alignment];\n }\n if (formatting.spacing) {\n const spacing: Record<string, unknown> = {};\n if (formatting.spacing?.beforeTwips !== undefined) {\n spacing.before = formatting.spacing.beforeTwips;\n }\n if (formatting.spacing?.afterTwips !== undefined) {\n spacing.after = formatting.spacing.afterTwips;\n }\n if (formatting.spacing.lineTwips !== undefined) {\n spacing.line = formatting.spacing.lineTwips;\n }\n // The rule stands on its own: `atLeast` with no height still says how the\n // line is measured.\n if (formatting.spacing.lineRule !== undefined) {\n spacing.lineRule = formatting.spacing.lineRule;\n }\n options.spacing = spacing;\n }\n if (formatting.indent) {\n const indent: Record<string, unknown> = {};\n if (formatting.indent.leftTwips !== undefined) {\n indent.left = formatting.indent.leftTwips;\n }\n if (formatting.indent.rightTwips !== undefined) {\n indent.right = formatting.indent.rightTwips;\n }\n if (formatting.indent.firstLineTwips !== undefined) {\n indent.firstLine = formatting.indent.firstLineTwips;\n }\n if (formatting.indent.hangingTwips !== undefined) {\n indent.hanging = formatting.indent.hangingTwips;\n }\n options.indent = indent;\n }\n if (formatting.tabStops) {\n options.tabStops = formatting.tabStops.map((stop) => ({\n position: stop.positionTwips,\n type: stop.type,\n ...(stop.leader ? { leader: stop.leader } : {}),\n }));\n }\n if (formatting.keepNext !== undefined) options.keepNext = formatting.keepNext;\n if (formatting.keepLines !== undefined) {\n options.keepLines = formatting.keepLines;\n }\n if (formatting.outlineLevel !== undefined) {\n options.outlineLevel = formatting.outlineLevel;\n }\n\n return options as Partial<IParagraphOptions>;\n}\n\nexport function emitParagraph(\n block: DocxIrParagraph,\n resources: EmitResources = new Map()\n): Paragraph {\n return new Paragraph({\n children: inlineChildren(block.children, resources),\n // A paragraph with no style named is one that deliberately has none — a\n // table cell, whose run properties come from the cell itself.\n ...(block.styleId ? { style: block.styleId } : {}),\n ...paragraphOptions(block.formatting),\n ...(block.markRevision ? { run: revisionMark(block.markRevision) } : {}),\n ...(block.frame ? { frame: frameOptions(block.frame) } : {}),\n ...(block.numbering\n ? {\n numbering: block.numbering.none\n ? // docx.js writes `numId 0` for a literal false, which is how a\n // paragraph detaches from the numbering its style applies.\n (false as const)\n : {\n reference: block.numbering.reference,\n level: block.numbering.level,\n },\n }\n : {}),\n });\n}\n\n/**\n * A paragraph positioned as a floating box (`w:framePr`).\n *\n * Exactly one positioning mode: absolute when the frame states coordinates,\n * alignment otherwise. OOXML cannot mix them, and docx.js takes the choice as\n * a discriminant.\n */\nfunction frameOptions(frame: DocxIrFrame): IFrameOptions {\n const base = {\n width: frame.widthTwips,\n height: frame.heightTwips,\n anchor: {\n horizontal: frame.anchorHorizontal,\n vertical: frame.anchorVertical,\n },\n ...(frame.wrap ? { wrap: frame.wrap } : {}),\n ...(frame.anchorLock !== undefined ? { anchorLock: frame.anchorLock } : {}),\n ...(frame.rule ? { rule: frame.rule } : {}),\n };\n\n return (\n frame.xTwips !== undefined || frame.yTwips !== undefined\n ? {\n type: 'absolute',\n position: { x: frame.xTwips ?? 0, y: frame.yTwips ?? 0 },\n ...base,\n }\n : {\n type: 'alignment',\n alignment: { x: frame.xAlign, y: frame.yAlign },\n ...base,\n }\n ) as IFrameOptions;\n}\n\nexport function emitBlock(\n block: DocxIrBlock,\n resources: EmitResources = new Map()\n): Paragraph | Table | TableOfContents {\n switch (block.kind) {\n case 'paragraph':\n return emitParagraph(block, resources);\n case 'table':\n return emitTable(block, resources);\n case 'toc':\n return emitToc(block);\n default:\n return assertNever(block, 'DocxIrBlock');\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Table of contents\n * ------------------------------------------------------------------ */\n\n/**\n * The TOC field.\n *\n * A top-level block, not a paragraph child: wrapping it in a paragraph makes\n * Word draw an empty structured-document-tag above the entries.\n */\nfunction emitToc(block: DocxIrTableOfContents): TableOfContents {\n return new TableOfContents(block.alias ?? 'Table of Contents', {\n ...(block.hyperlink !== undefined ? { hyperlink: block.hyperlink } : {}),\n ...(block.headingRange\n ? {\n headingStyleRange: `${block.headingRange.from}-${block.headingRange.to}`,\n }\n : {}),\n stylesWithLevels: (block.styleLevels ?? []).map(\n (style) => new StyleLevel(style.styleName, style.level)\n ),\n entriesFromBookmark: block.bookmarkScope,\n ...(block.omitPageNumbersForLevels?.length\n ? {\n pageNumbersEntryLevelsRange: block.omitPageNumbersForLevels\n .map((range) => `${range.from}-${range.to}`)\n .join(','),\n }\n : {}),\n ...(block.entrySeparator !== undefined\n ? { entryAndPageNumberSeparator: block.entrySeparator }\n : {}),\n ...(block.cachedEntries?.length\n ? {\n cachedEntries: block.cachedEntries.map((entry) => ({\n title: entry.text,\n level: entry.level,\n })),\n }\n : {}),\n });\n}\n\n/* ------------------------------------------------------------------ *\n * Tables\n * ------------------------------------------------------------------ */\n\nconst VERTICAL_ALIGN: Readonly<\n Record<string, (typeof VerticalAlign)[keyof typeof VerticalAlign]>\n> = {\n top: VerticalAlign.TOP,\n center: VerticalAlign.CENTER,\n bottom: VerticalAlign.BOTTOM,\n};\n\nexport function emitTable(\n block: DocxIrTable,\n resources: EmitResources = new Map()\n): Table {\n return new Table({\n width: {\n size: block.width.kind === 'auto' ? 0 : block.width.value,\n type: block.width.kind === 'twips' ? WidthType.DXA : WidthType.PERCENTAGE,\n },\n layout:\n block.layout === 'fixed'\n ? TableLayoutType.FIXED\n : TableLayoutType.AUTOFIT,\n // An empty grid is a table with nothing to say about its columns, which is\n // not the same as one whose columns are all zero wide.\n ...(block.columnGrid.values.length > 0\n ? { columnWidths: block.columnGrid.values }\n : {}),\n ...(block.borders\n ? {\n borders: {\n top: emitBorder(block.borders.top),\n right: emitBorder(block.borders.right),\n bottom: emitBorder(block.borders.bottom),\n left: emitBorder(block.borders.left),\n insideHorizontal: emitBorder(block.borders.insideHorizontal),\n insideVertical: emitBorder(block.borders.insideVertical),\n },\n }\n : {}),\n ...(block.floating ? { float: tableFloat(block.floating) } : {}),\n rows: block.rows.map((row) => emitTableRow(row, resources)),\n });\n}\n\nconst TABLE_ANCHOR: Readonly<\n Record<string, (typeof TableAnchorType)[keyof typeof TableAnchorType]>\n> = {\n margin: TableAnchorType.MARGIN,\n page: TableAnchorType.PAGE,\n text: TableAnchorType.TEXT,\n};\n\nconst HORIZONTAL_POSITION: Readonly<\n Record<\n string,\n (typeof RelativeHorizontalPosition)[keyof typeof RelativeHorizontalPosition]\n >\n> = {\n left: RelativeHorizontalPosition.LEFT,\n center: RelativeHorizontalPosition.CENTER,\n right: RelativeHorizontalPosition.RIGHT,\n inside: RelativeHorizontalPosition.INSIDE,\n outside: RelativeHorizontalPosition.OUTSIDE,\n};\n\nconst VERTICAL_POSITION: Readonly<\n Record<\n string,\n (typeof RelativeVerticalPosition)[keyof typeof RelativeVerticalPosition]\n >\n> = {\n top: RelativeVerticalPosition.TOP,\n center: RelativeVerticalPosition.CENTER,\n bottom: RelativeVerticalPosition.BOTTOM,\n inside: RelativeVerticalPosition.INSIDE,\n outside: RelativeVerticalPosition.OUTSIDE,\n};\n\n/** Where a floating table sits, in the vocabulary docx.js takes. */\nfunction tableFloat(floating: DocxIrTableFloating): Record<string, unknown> {\n return {\n ...(floating.horizontalAnchor\n ? { horizontalAnchor: TABLE_ANCHOR[floating.horizontalAnchor] }\n : {}),\n ...(floating.verticalAnchor\n ? { verticalAnchor: TABLE_ANCHOR[floating.verticalAnchor] }\n : {}),\n ...(floating.absoluteHorizontalPositionTwips !== undefined\n ? {\n absoluteHorizontalPosition: floating.absoluteHorizontalPositionTwips,\n }\n : {}),\n ...(floating.relativeHorizontalPosition\n ? {\n relativeHorizontalPosition:\n HORIZONTAL_POSITION[floating.relativeHorizontalPosition],\n }\n : {}),\n ...(floating.absoluteVerticalPositionTwips !== undefined\n ? { absoluteVerticalPosition: floating.absoluteVerticalPositionTwips }\n : {}),\n ...(floating.relativeVerticalPosition\n ? {\n relativeVerticalPosition:\n VERTICAL_POSITION[floating.relativeVerticalPosition],\n }\n : {}),\n ...(floating.topFromTextTwips !== undefined\n ? { topFromText: floating.topFromTextTwips }\n : {}),\n ...(floating.rightFromTextTwips !== undefined\n ? { rightFromText: floating.rightFromTextTwips }\n : {}),\n ...(floating.bottomFromTextTwips !== undefined\n ? { bottomFromText: floating.bottomFromTextTwips }\n : {}),\n ...(floating.leftFromTextTwips !== undefined\n ? { leftFromText: floating.leftFromTextTwips }\n : {}),\n ...(floating.overlap\n ? {\n overlap:\n floating.overlap === 'never'\n ? OverlapType.NEVER\n : OverlapType.OVERLAP,\n }\n : {}),\n };\n}\n\nfunction emitTableRow(row: DocxIrTableRow, resources: EmitResources): TableRow {\n return new TableRow({\n children: row.cells.map((cell) => emitTableCell(cell, resources)),\n ...(row.heightTwips !== undefined\n ? {\n height: { value: row.heightTwips, rule: row.heightRule ?? 'atLeast' },\n }\n : {}),\n ...(row.isHeader !== undefined ? { tableHeader: row.isHeader } : {}),\n ...(row.cantSplit !== undefined ? { cantSplit: row.cantSplit } : {}),\n ...(row.revision ? revisionMark(row.revision) : {}),\n });\n}\n\n/** `w:trPr/w:ins` or `w:trPr/w:del` — the row itself was inserted or deleted. */\nfunction revisionMark(revision: DocxIrParagraphMarkRevision): {\n insertion?: { id: number; author: string; date: string };\n deletion?: { id: number; author: string; date: string };\n} {\n const attributes = {\n id: revision.id,\n author: revision.author,\n date: revision.date,\n };\n return revision.type === 'insert'\n ? { insertion: attributes }\n : { deletion: attributes };\n}\n\nfunction emitTableCell(\n cell: DocxIrTableCell,\n resources: EmitResources\n): TableCell {\n const options: Record<string, unknown> = {\n children: cell.children.map((child) => emitBlock(child, resources)),\n };\n\n if (cell.widthTwips !== undefined) {\n options.width = { size: cell.widthTwips, type: WidthType.DXA };\n }\n if (cell.verticalAlign) {\n options.verticalAlign = VERTICAL_ALIGN[cell.verticalAlign];\n }\n if (cell.shading) options.shading = { fill: cell.shading.fill.hex };\n if (cell.margins) {\n options.margins = {\n // Stated in twips, which docx.js only believes if told the unit.\n marginUnitType: WidthType.DXA,\n top: cell.margins.topTwips ?? 0,\n bottom: cell.margins.bottomTwips ?? 0,\n left: cell.margins.leftTwips ?? 0,\n right: cell.margins.rightTwips ?? 0,\n };\n }\n if (cell.borders) {\n options.borders = {\n top: emitBorder(cell.borders.top),\n bottom: emitBorder(cell.borders.bottom),\n left: emitBorder(cell.borders.left),\n right: emitBorder(cell.borders.right),\n };\n }\n if (cell.columnSpan !== undefined) options.columnSpan = cell.columnSpan;\n if (cell.rowSpan !== undefined) options.verticalMerge = cell.rowSpan;\n\n return new TableCell(options as unknown as ITableCellOptions);\n}\n\nconst BORDER_STYLE: Readonly<\n Record<string, (typeof BorderStyle)[keyof typeof BorderStyle]>\n> = {\n none: BorderStyle.NONE,\n single: BorderStyle.SINGLE,\n double: BorderStyle.DOUBLE,\n dashed: BorderStyle.DASHED,\n dotted: BorderStyle.DOTTED,\n};\n\nfunction emitBorder(border: DocxIrBorder | undefined) {\n if (!border) return undefined;\n return {\n style: BORDER_STYLE[border.style] ?? BorderStyle.SINGLE,\n size: border.sizeEighthPoints ?? 0,\n color: border.color?.hex ?? '000000',\n };\n}\n","/**\n * DocxIR styles, as docx.js style options.\n *\n * A mechanical translation: which styles exist and what each one says was\n * decided by the compiler, and this only renames the fields and restores the\n * units docx.js expects. Nothing here reads a theme.\n */\n\nimport {\n AlignmentType,\n BorderStyle,\n LineRuleType,\n UnderlineType,\n type IBaseParagraphStyleOptions,\n type IParagraphStylePropertiesOptions,\n type IRunStylePropertiesOptions,\n type IStylesOptions,\n} from 'docx';\nimport type {\n DocxIrBorder,\n DocxIrBorders,\n DocxIrBuiltInStyle,\n DocxIrParagraphFormatting,\n DocxIrRunFormatting,\n DocxIrStyles,\n} from '../../ir/types';\nimport { ALIGNMENT } from './emit';\n\n/** Border style names, as docx.js spells them. */\nconst BORDER_STYLE: Record<\n string,\n (typeof BorderStyle)[keyof typeof BorderStyle]\n> = {\n none: BorderStyle.NONE,\n single: BorderStyle.SINGLE,\n double: BorderStyle.DOUBLE,\n dashed: BorderStyle.DASHED,\n dotted: BorderStyle.DOTTED,\n thick: BorderStyle.THICK,\n};\n\nfunction runProperties(\n formatting: DocxIrRunFormatting\n): IRunStylePropertiesOptions {\n const out: Record<string, unknown> = {};\n if (formatting.fontFamily !== undefined) out.font = formatting.fontFamily;\n if (formatting.sizeHalfPoints !== undefined) {\n out.size = formatting.sizeHalfPoints;\n }\n if (formatting.color) out.color = formatting.color.hex;\n if (formatting.bold !== undefined) out.bold = formatting.bold;\n if (formatting.italic !== undefined) out.italic = formatting.italic;\n if (formatting.underline) {\n out.underline = {\n type: formatting.underline\n .type as (typeof UnderlineType)[keyof typeof UnderlineType],\n ...(formatting.underline.color\n ? { color: formatting.underline.color.hex }\n : {}),\n };\n }\n if (formatting.strike !== undefined) out.strike = formatting.strike;\n if (formatting.superScript) out.superScript = true;\n if (formatting.subScript) out.subScript = true;\n if (formatting.smallCaps !== undefined) out.smallCaps = formatting.smallCaps;\n if (formatting.allCaps !== undefined) out.allCaps = formatting.allCaps;\n if (formatting.highlight !== undefined) out.highlight = formatting.highlight;\n if (formatting.characterSpacingTwentieths !== undefined) {\n out.characterSpacing = formatting.characterSpacingTwentieths;\n }\n if (formatting.scalePercent !== undefined)\n out.scale = formatting.scalePercent;\n if (formatting.noProof !== undefined) out.noProof = formatting.noProof;\n if (formatting.language !== undefined) {\n out.language = { value: formatting.language };\n }\n return out as IRunStylePropertiesOptions;\n}\n\nfunction border(value: DocxIrBorder) {\n return {\n style: BORDER_STYLE[value.style] ?? BorderStyle.SINGLE,\n ...(value.sizeEighthPoints !== undefined\n ? { size: value.sizeEighthPoints }\n : {}),\n ...(value.color ? { color: value.color.hex } : {}),\n ...(value.spacePoints !== undefined ? { space: value.spacePoints } : {}),\n };\n}\n\nfunction borders(value: DocxIrBorders) {\n const out: Record<string, unknown> = {};\n for (const side of ['top', 'bottom', 'left', 'right', 'between'] as const) {\n const side_ = value[side];\n if (side_) out[side] = border(side_);\n }\n return out;\n}\n\nfunction paragraphProperties(\n formatting: DocxIrParagraphFormatting\n): IParagraphStylePropertiesOptions {\n const out: Record<string, unknown> = {};\n if (formatting.spacing) {\n const spacing: Record<string, unknown> = {};\n if (formatting.spacing.beforeTwips !== undefined) {\n spacing.before = formatting.spacing.beforeTwips;\n }\n if (formatting.spacing.afterTwips !== undefined) {\n spacing.after = formatting.spacing.afterTwips;\n }\n if (formatting.spacing.lineTwips !== undefined) {\n spacing.line = formatting.spacing.lineTwips;\n }\n if (formatting.spacing.lineRule !== undefined) {\n spacing.lineRule = formatting.spacing\n .lineRule as (typeof LineRuleType)[keyof typeof LineRuleType];\n }\n out.spacing = spacing;\n }\n if (formatting.alignment !== undefined) {\n out.alignment =\n ALIGNMENT[formatting.alignment] ??\n (formatting.alignment as (typeof AlignmentType)[keyof typeof AlignmentType]);\n }\n if (formatting.keepNext !== undefined) out.keepNext = formatting.keepNext;\n if (formatting.keepLines !== undefined) out.keepLines = formatting.keepLines;\n if (formatting.widowControl !== undefined) {\n out.widowControl = formatting.widowControl;\n }\n if (formatting.pageBreakBefore !== undefined) {\n out.pageBreakBefore = formatting.pageBreakBefore;\n }\n if (formatting.outlineLevel !== undefined) {\n out.outlineLevel = formatting.outlineLevel;\n }\n if (formatting.borders) out.border = borders(formatting.borders);\n if (formatting.indent) {\n const indent: Record<string, unknown> = {};\n if (formatting.indent.leftTwips !== undefined) {\n indent.left = formatting.indent.leftTwips;\n }\n if (formatting.indent.rightTwips !== undefined) {\n indent.right = formatting.indent.rightTwips;\n }\n if (formatting.indent.firstLineTwips !== undefined) {\n indent.firstLine = formatting.indent.firstLineTwips;\n }\n if (formatting.indent.hangingTwips !== undefined) {\n indent.hanging = formatting.indent.hangingTwips;\n }\n out.indent = indent;\n }\n if (formatting.tabStops) {\n out.tabStops = formatting.tabStops.map((stop) => ({\n type: stop.type,\n position: stop.positionTwips,\n ...(stop.leader ? { leader: stop.leader } : {}),\n }));\n }\n if (formatting.bidirectional !== undefined) {\n out.bidirectional = formatting.bidirectional;\n }\n return out as IParagraphStylePropertiesOptions;\n}\n\nfunction builtIn(style: DocxIrBuiltInStyle): IBaseParagraphStyleOptions {\n return {\n ...(style.run ? { run: runProperties(style.run) } : {}),\n ...(style.paragraph\n ? { paragraph: paragraphProperties(style.paragraph) }\n : {}),\n };\n}\n\n/** Turn the IR's style set into the options docx.js builds `styles.xml` from. */\nexport function emitStyles(styles: DocxIrStyles): IStylesOptions {\n const documentDefaults = {\n ...(Object.keys(styles.defaults.run).length > 0\n ? { run: runProperties(styles.defaults.run) }\n : {}),\n ...(Object.keys(styles.defaults.paragraph).length > 0\n ? { paragraph: paragraphProperties(styles.defaults.paragraph) }\n : {}),\n };\n\n return {\n paragraphStyles: styles.paragraph.map((style) => ({\n id: style.id,\n name: style.name,\n ...(style.basedOn !== undefined ? { basedOn: style.basedOn } : {}),\n ...(style.next !== undefined ? { next: style.next } : {}),\n ...(style.quickFormat !== undefined\n ? { quickFormat: style.quickFormat }\n : {}),\n ...(style.run ? { run: runProperties(style.run) } : {}),\n ...(style.paragraph\n ? { paragraph: paragraphProperties(style.paragraph) }\n : {}),\n })),\n ...(styles.character.length > 0\n ? {\n characterStyles: styles.character.map((style) => ({\n id: style.id,\n name: style.name,\n ...(style.basedOn !== undefined ? { basedOn: style.basedOn } : {}),\n run: runProperties(style.run),\n })),\n }\n : {}),\n default: {\n ...(Object.keys(documentDefaults).length > 0\n ? { document: documentDefaults }\n : {}),\n ...(styles.builtIn?.footnoteText\n ? { footnoteText: builtIn(styles.builtIn.footnoteText) }\n : {}),\n ...(styles.builtIn?.footnoteReference\n ? { footnoteReference: builtIn(styles.builtIn.footnoteReference) }\n : {}),\n ...(styles.builtIn?.endnoteText\n ? { endnoteText: builtIn(styles.builtIn.endnoteText) }\n : {}),\n ...(styles.builtIn?.endnoteReference\n ? { endnoteReference: builtIn(styles.builtIn.endnoteReference) }\n : {}),\n },\n };\n}\n","/**\n * DOCX renderer features.\n *\n * A feature is a capability a *backend* must have, not an authoring concept.\n * The compiler records one requirement per IR node that needs one; a renderer\n * declares the set it can satisfy. Anything required but not declared fails\n * before rendering, with the IR path attached.\n *\n * The boundaries are drawn where backends actually differ. `toc` and\n * `cached-toc` are separate because writing the field is easy and baking its\n * entries is not; `footnotes` and `endnotes` are separate because a backend can\n * plausibly have one and not the other.\n */\n\nexport const DOCX_FEATURES = [\n /** Paragraphs and text runs — the floor of the format. */\n 'paragraphs',\n /** Named paragraph and character styles in `styles.xml`. */\n 'styles',\n /** Numbering definitions and numbered paragraphs. */\n 'numbering',\n /** Multiple sections with their own page setup. */\n 'sections',\n /** Multi-column section layout. */\n 'columns',\n /** Header and footer parts, including first/even variants. */\n 'headers-footers',\n 'tables',\n /** Merged table cells — column span or vertical merge. */\n 'table-merged-cells',\n /** A table positioned out of the text flow. */\n 'floating-tables',\n /** Inline images. */\n 'images',\n /** Anchored images with text wrapping. */\n 'floating-images',\n /** SVG images with a raster fallback. */\n 'svg-images',\n /** A paragraph positioned as a floating frame. */\n 'text-frames',\n /** Native shape text boxes. */\n 'text-boxes',\n /** A table-of-contents field. */\n 'toc',\n /** TOC entries baked in so an unrefreshed reader still shows them. */\n 'cached-toc',\n /** Arbitrary Word fields, e.g. PAGE, NUMPAGES, REF. */\n 'fields',\n /** Field results cached for readers that never refresh. */\n 'cached-fields',\n 'hyperlinks',\n 'bookmarks',\n /** Links and REF fields that target a bookmark. */\n 'cross-references',\n 'comments',\n /** Threaded and resolvable comments. */\n 'comment-threads',\n 'footnotes',\n 'endnotes',\n /** Inserted and deleted content. */\n 'revisions',\n /** Page, column and line breaks. */\n 'breaks',\n /** Paragraph and table shading. */\n 'shading',\n /** Paragraph, table and page borders. */\n 'borders',\n /** Tab stops. */\n 'tab-stops',\n /** Per-run proofing language and no-proof. */\n 'proofing-language',\n /** Custom document properties. */\n 'custom-properties',\n /** Right-to-left paragraph direction. */\n 'rtl',\n] as const;\n\nexport type DocxFeature = (typeof DOCX_FEATURES)[number];\n\n/** Every feature, for an adapter that claims the full surface. */\nexport const ALL_DOCX_FEATURES: ReadonlySet<DocxFeature> = new Set(\n DOCX_FEATURES\n);\n\nexport function isDocxFeature(value: string): value is DocxFeature {\n return (DOCX_FEATURES as readonly string[]).includes(value);\n}\n","import AdmZip from 'adm-zip';\n\nexport interface DocumentPackageOptions {\n /** Normalize volatile OOXML metadata and ZIP timestamps. Defaults to true. */\n deterministic?: boolean;\n /** Timestamp used for generated metadata. Defaults to a stable epoch. */\n generatedAt?: string | Date;\n}\n\n/** Stable, valid OOXML/ZIP timestamp used when no build timestamp is supplied. */\nexport const DEFAULT_GENERATION_DATE = new Date('2000-01-01T00:00:00.000Z');\n\nexport function resolveGenerationDate(options?: DocumentPackageOptions): Date {\n if (options?.generatedAt !== undefined) {\n const date = new Date(options.generatedAt);\n if (Number.isNaN(date.getTime())) {\n throw new RangeError('generatedAt must be a valid date');\n }\n if (date.getUTCFullYear() < 1980) {\n throw new RangeError(\n 'generatedAt must be on or after 1980-01-01 for ZIP compatibility'\n );\n }\n return date;\n }\n\n return options?.deterministic === false\n ? new Date()\n : new Date(DEFAULT_GENERATION_DATE);\n}\n\n/** Encode a UTC instant into the packed MS-DOS date/time field ZIP headers use. */\nfunction toDosTime(date: Date): number {\n const dosDate =\n (((date.getUTCFullYear() - 1980) & 0x7f) << 9) |\n ((date.getUTCMonth() + 1) << 5) |\n date.getUTCDate();\n const dosTime =\n (date.getUTCHours() << 11) |\n (date.getUTCMinutes() << 5) |\n (date.getUTCSeconds() >> 1);\n return ((dosDate << 16) | dosTime) >>> 0;\n}\n\n/**\n * A relationship id that is stable across runs.\n *\n * docx.js numbers most relationships `rId1`, `rId2`, … but mints ids for\n * external hyperlinks from `Math.random`, so any document containing a link\n * produced different bytes on every render. Canonicalizing them here is\n * generic package finalization — it is a property of an OOXML package, not of\n * any one backend — and it is what makes a hyperlink-bearing document\n * reproducible at all.\n */\nconst STABLE_RELATIONSHIP_ID = /^rId\\d+$/;\n\n/**\n * Rewrite volatile relationship ids to a stable sequence.\n *\n * Ids are renumbered per part, continuing past the highest number that part\n * already uses so nothing can collide with an id docx.js allocated. Order\n * follows first appearance in the owning part, which depends only on document\n * content — not on allocation order, and not on a clock.\n */\nfunction canonicalizeRelationshipIds(zip: AdmZip): void {\n // Two phases. Updating entries while walking `getEntries()` rebuilds\n // adm-zip's internal list, after which a `getEntry` lookup for the owning\n // part can miss — which renamed the relationship without renaming the\n // reference to it. Collect first, then apply.\n const relsNames = zip\n .getEntries()\n .map((entry) => entry.entryName)\n .filter((name) => /^(.*\\/)?_rels\\/(.+)\\.rels$/.test(name));\n\n const updates: Array<{ name: string; xml: string }> = [];\n\n for (const relsName of relsNames) {\n const match = /^(.*\\/)?_rels\\/(.+)\\.rels$/.exec(relsName);\n if (!match) continue;\n\n const relsEntry = zip.getEntry(relsName);\n if (!relsEntry) continue;\n const relsXml = relsEntry.getData().toString('utf8');\n\n const ids = [...relsXml.matchAll(/\\bId=\"([^\"]+)\"/g)].map((m) => m[1]);\n const unstable = ids.filter((id) => !STABLE_RELATIONSHIP_ID.test(id));\n if (unstable.length === 0) continue;\n\n const partName = `${match[1] ?? ''}${match[2]}`;\n const partEntry = zip.getEntry(partName);\n const partXml = partEntry?.getData().toString('utf8') ?? '';\n\n // First appearance in the part decides the order; anything the part never\n // references keeps its position from the relationships file.\n const ordered = [...unstable].sort((a, b) => {\n const ia = partXml.indexOf(`\"${a}\"`);\n const ib = partXml.indexOf(`\"${b}\"`);\n if (ia === ib) return unstable.indexOf(a) - unstable.indexOf(b);\n if (ia === -1) return 1;\n if (ib === -1) return -1;\n return ia - ib;\n });\n\n const highest = ids.reduce((max, id) => {\n const numeric = /^rId(\\d+)$/.exec(id);\n return numeric ? Math.max(max, Number(numeric[1])) : max;\n }, 0);\n\n const rename = new Map(\n ordered.map((id, index) => [id, `rId${highest + 1 + index}`])\n );\n\n // One pass over quoted tokens, so a freshly assigned id can never be\n // rewritten again by a later entry in the map.\n const rewrite = (xml: string): string =>\n xml.replace(/\"([^\"]+)\"/g, (whole, value: string) => {\n const replacement = rename.get(value);\n return replacement === undefined ? whole : `\"${replacement}\"`;\n });\n\n updates.push({ name: relsName, xml: rewrite(relsXml) });\n if (partEntry) {\n updates.push({ name: partName, xml: rewrite(partXml) });\n }\n }\n\n for (const update of updates) {\n const entry = zip.getEntry(update.name);\n if (entry) zip.updateFile(entry, Buffer.from(update.xml, 'utf8'));\n }\n}\n\n/**\n * Normalize package-level values that otherwise change on every render.\n * ZIP headers are written from UTC components because DOS timestamps carry no\n * timezone; this produces identical header bits in every locale.\n */\nexport function canonicalizeDocxBuffer(\n buffer: Buffer,\n generatedAt: Date = DEFAULT_GENERATION_DATE\n): Buffer {\n const zip = new AdmZip(buffer);\n canonicalizeRelationshipIds(zip);\n\n const isoTimestamp = generatedAt.toISOString();\n const coreProperties = zip.getEntry('docProps/core.xml');\n\n if (coreProperties) {\n const normalized = coreProperties\n .getData()\n .toString('utf8')\n .replace(\n /(<dcterms:(?:created|modified)\\b[^>]*>)[^<]*(<\\/dcterms:(?:created|modified)>)/g,\n `$1${isoTimestamp}$2`\n );\n zip.updateFile(coreProperties, Buffer.from(normalized, 'utf8'));\n }\n\n // AdmZip's `header.time` setter encodes the timezone-less DOS field from\n // local getters, so the emitted bits would vary by host. Write the raw field\n // from UTC components instead. Going through a reconstructed local Date is\n // not enough: a value inside a DST spring-forward gap has no local\n // representation and the runtime silently shifts it an hour.\n // `timeval` is the raw DOS field; @types/adm-zip@0.5.7 only declares the\n // `time` Date accessor that wraps it, hence the cast.\n const zipTimestamp = toDosTime(generatedAt);\n for (const entry of zip.getEntries()) {\n (entry.header as unknown as { timeval: number }).timeval = zipTimestamp;\n }\n\n return zip.toBuffer();\n}\n","/**\n * Post-processing utility to fix docx.js floating image bugs\n *\n * The docx library (as of v9.7.1) has a known issue with floating images:\n * 1. Duplicate wp:docPr IDs (GitHub issue #2719)\n *\n * Historical note: We previously also post-processed relativeHeight and\n * wrapTight elements. Those steps were removed because we always provide a\n * valid zIndex upstream and we do not support 'tight' wrapping.\n *\n * This utility extracts the DOCX, fixes duplicate IDs, and re-packages it.\n */\n\nimport AdmZip from 'adm-zip';\nimport { readFile, writeFile } from 'fs/promises';\n\n/** Fix duplicate floating-image IDs without touching the filesystem. */\nexport function fixFloatingImageIdsInBuffer(buffer: Buffer): Buffer {\n const zip = new AdmZip(buffer);\n const documentEntry = zip.getEntry('word/document.xml');\n\n if (!documentEntry) {\n throw new Error('document.xml not found in DOCX');\n }\n\n let idCounter = 1;\n // `id` is not guaranteed to be the first attribute on wp:docPr: OOXML does\n // not fix attribute order and docx does not promise to preserve it. Match it\n // wherever it sits so a library-side reordering cannot silently turn this\n // pass into a no-op (which would leave every floating image on id=\"1\" and\n // make Word prompt for repair).\n const documentXml = documentEntry\n .getData()\n .toString('utf8')\n .replace(/(<wp:docPr\\b[^>]*?\\s)id=\"\\d+\"/g, (_match, prefix: string) => {\n const newId = idCounter++;\n return `${prefix}id=\"${newId}\"`;\n });\n\n zip.updateFile(documentEntry, Buffer.from(documentXml, 'utf8'));\n return zip.toBuffer();\n}\n\n/**\n * Fix floating image issues in a generated DOCX file\n * @param docxPath - Path to the DOCX file to fix\n */\nexport async function fixFloatingImageIds(docxPath: string): Promise<void> {\n const buffer = await readFile(docxPath);\n await writeFile(docxPath, fixFloatingImageIdsInBuffer(buffer));\n}\n","/**\n * The docx.js renderer.\n *\n * This is the only place in `core-docx` production code that may import `docx`\n * once the migration completes. It consumes DocxIR and nothing else — no author\n * JSON, no `ProcessedDocument`, no theme lookups.\n *\n */\n\nimport {\n BookmarkEnd,\n BookmarkStart,\n Column,\n Document,\n Footer,\n Header,\n ImageRun,\n Packer,\n Paragraph,\n Table,\n type ICommentOptions,\n type ILevelsOptions,\n type ISectionOptions,\n} from 'docx';\nimport { emitStyles } from './styles';\nimport { rasterizeSvgFallback } from '../../utils/imageUtils';\nimport type {\n DocxIR,\n DocxIrBlock,\n DocxIrHeaderFooter,\n DocxIrInline,\n DocxIrNote,\n DocxIrNumbering,\n DocxIrSection,\n} from '../../ir/types';\nimport { ALL_DOCX_FEATURES, type DocxFeature } from '../../ir/features';\nimport {\n canonicalizeDocxBuffer,\n resolveGenerationDate,\n} from '../../utils/packageDocument';\nimport { fixFloatingImageIdsInBuffer } from '../../utils/fixFloatingImageIds';\nimport type { DocxRenderOptions, DocxRenderer, DocxRendererId } from '../types';\nimport {\n ALIGNMENT,\n emitBlock,\n floatingOptions,\n runOptions,\n type EmitResources,\n type ImageRunFactory,\n} from './emit';\nimport { emuToPixels } from '../../ir/units';\n\nexport const DOCXJS_RENDERER_ID: DocxRendererId = 'docxjs';\n\n/**\n * What this adapter can express today.\n *\n * The exclusions are the slice boundary, not backend gaps: docx.js supports all\n * of them, and each moves into this set as the compiler learns to lower it.\n */\nconst NOT_YET_EMITTED: ReadonlySet<DocxFeature> = new Set<DocxFeature>([\n 'table-merged-cells',\n 'cached-fields',\n 'shading',\n 'borders',\n 'rtl',\n]);\n\nconst DOCXJS_CAPABILITIES: ReadonlySet<DocxFeature> = new Set(\n [...ALL_DOCX_FEATURES].filter((feature) => !NOT_YET_EMITTED.has(feature))\n);\n\nexport function createDocxJsRenderer(): DocxRenderer {\n return {\n id: DOCXJS_RENDERER_ID,\n format: 'docx',\n capabilities: DOCXJS_CAPABILITIES,\n async render(\n ir: DocxIR,\n renderOptions?: DocxRenderOptions\n ): Promise<Uint8Array> {\n const resources = await prepareImages(ir);\n const document = buildDocument(ir, resources);\n const packed = (await Packer.toBuffer(document)) as Buffer;\n const fixed = fixFloatingImageIdsInBuffer(packed);\n\n if (renderOptions?.deterministic === false) return new Uint8Array(fixed);\n return new Uint8Array(\n canonicalizeDocxBuffer(\n fixed,\n resolveGenerationDate({\n deterministic: renderOptions?.deterministic,\n generatedAt: renderOptions?.generatedAt,\n })\n )\n );\n },\n };\n}\n\n/**\n * Build the docx.js object graph for an IR document.\n *\n * Exported for tests: asserting on the object graph is far cheaper, and far\n * more legible, than unzipping a package.\n */\nexport function buildDocument(\n ir: DocxIR,\n resources: EmitResources = new Map()\n): Document {\n return new Document({\n styles: emitStyles(ir.styles),\n sections: ir.sections.map((section) => sectionOptions(section, resources)),\n ...coreProperties(ir),\n features: {\n updateFields: ir.settings.updateFields,\n ...(ir.settings.trackRevisions ? { trackRevisions: true } : {}),\n },\n ...(ir.numbering.length > 0\n ? { numbering: { config: ir.numbering.map(numberingConfig) } }\n : {}),\n // word/footnotes.xml and word/endnotes.xml, keyed by the id their\n // references carry.\n ...(ir.footnotes.length > 0\n ? { footnotes: noteBodies(ir.footnotes, resources) }\n : {}),\n ...(ir.endnotes.length > 0\n ? { endnotes: noteBodies(ir.endnotes, resources) }\n : {}),\n // word/comments.xml, written only when something was actually commented.\n ...(ir.comments.length > 0\n ? {\n comments: {\n children: ir.comments.map((comment) => ({\n id: comment.id,\n author: comment.author,\n ...(comment.initials ? { initials: comment.initials } : {}),\n date: new Date(comment.date),\n children: comment.children.map((block) =>\n emitBlock(block, resources)\n ),\n ...(comment.parentId !== undefined\n ? { parentId: comment.parentId }\n : {}),\n ...(comment.resolved !== undefined\n ? { resolved: comment.resolved }\n : {}),\n })) as ICommentOptions[],\n },\n }\n : {}),\n });\n}\n\n/** Note bodies keyed by id, which is how docx.js takes them. */\nfunction noteBodies(\n notes: readonly DocxIrNote[],\n resources: EmitResources\n): Record<string, { children: Paragraph[] }> {\n const bodies: Record<string, { children: Paragraph[] }> = {};\n for (const note of notes) {\n bodies[String(note.id)] = {\n children: note.children.map(\n (block) => emitBlock(block, resources) as Paragraph\n ),\n };\n }\n return bodies;\n}\n\n/** One IR numbering definition as a docx.js abstract numbering config. */\nfunction numberingConfig(numbering: DocxIrNumbering): {\n reference: string;\n levels: ILevelsOptions[];\n} {\n return {\n reference: numbering.reference,\n levels: numbering.levels.map((level) => ({\n level: level.level,\n format: level.format as ILevelsOptions['format'],\n text: level.text,\n alignment: level.alignment ? ALIGNMENT[level.alignment] : undefined,\n ...(level.suffix ? { suffix: level.suffix } : {}),\n style: {\n ...(level.indent\n ? {\n paragraph: {\n indent: {\n ...(level.indent.leftTwips !== undefined\n ? { left: level.indent.leftTwips }\n : {}),\n ...(level.indent.hangingTwips !== undefined\n ? { hanging: level.indent.hangingTwips }\n : {}),\n },\n },\n }\n : {}),\n ...(level.run ? { run: runOptions(level.run) } : {}),\n ...(level.paragraphStyleId ? { style: level.paragraphStyleId } : {}),\n },\n ...(level.start !== undefined ? { start: level.start } : {}),\n })),\n };\n}\n\n/**\n * Build an image run factory per resource.\n *\n * Separate from `buildDocument` because a vector image has to be rasterised\n * for the fallback Word draws below 2016, and that is asynchronous while\n * building the document is not. The raster depends on the size the image is\n * drawn at, so every placement of a vector resource is rasterised up front and\n * the factory looks the right one up.\n */\nasync function prepareImages(ir: DocxIR): Promise<EmitResources> {\n const placements = collectImagePlacements(ir);\n const rasters = new Map<string, Buffer | undefined>();\n\n for (const resource of ir.resources) {\n if (resource.kind !== 'image' || resource.mediaType !== 'svg') continue;\n for (const size of placements.get(resource.id) ?? []) {\n const [width, height] = size.split('x').map(Number);\n rasters.set(\n `${resource.id}:${size}`,\n await rasterizeSvgFallback(Buffer.from(resource.bytes), {\n width,\n height,\n })\n );\n }\n }\n\n const resources = new Map<string, ImageRunFactory>();\n for (const resource of ir.resources) {\n if (resource.kind !== 'image') continue;\n const type = resource.mediaType as 'jpg' | 'png' | 'gif' | 'bmp' | 'svg';\n const data = Buffer.from(resource.bytes);\n // One run per placement: the same bytes may be drawn at two sizes, and the\n // transformation lives on the run rather than on the resource.\n resources.set(resource.id, (image) => {\n const transformation = {\n width: emuToPixels(image.widthEmu),\n height: emuToPixels(image.heightEmu),\n };\n return new ImageRun({\n type,\n data,\n transformation,\n ...(type === 'svg'\n ? {\n // Word before 2016 draws the fallback rather than the vector. A\n // raster that could not be produced falls back to the SVG bytes,\n // which is what the pipeline has always shipped.\n fallback: {\n type: 'png',\n data:\n rasters.get(\n `${image.resourceId}:${transformation.width}x${transformation.height}`\n ) ?? data,\n },\n }\n : {}),\n ...(image.floating\n ? { floating: floatingOptions(image.floating) }\n : {}),\n // `altText` is deliberately not passed. docx.js would write it into\n // `wp:docPr`, and no DOCX this pipeline has ever produced carries it —\n // adding it now would rewrite every document with an alt-bearing\n // image. The compiler warns instead, so the gap is visible.\n } as ConstructorParameters<typeof ImageRun>[0]);\n });\n }\n return resources;\n}\n\n/**\n * Every size each image resource is drawn at, as `WxH` in pixels.\n *\n * Only vector resources need this, but the walk cannot know which is which\n * without the resource list, and walking twice would cost more than it saves.\n */\nfunction collectImagePlacements(ir: DocxIR): Map<string, Set<string>> {\n const placements = new Map<string, Set<string>>();\n\n const visitInline = (inline: DocxIrInline): void => {\n if (inline.kind === 'image') {\n const key = `${emuToPixels(inline.widthEmu)}x${emuToPixels(inline.heightEmu)}`;\n const sizes = placements.get(inline.resourceId) ?? new Set<string>();\n sizes.add(key);\n placements.set(inline.resourceId, sizes);\n return;\n }\n if (inline.kind === 'hyperlink' || inline.kind === 'revision') {\n inline.children.forEach(visitInline);\n return;\n }\n if (inline.kind === 'shape') inline.children.forEach(visitBlock);\n };\n\n const visitBlock = (block: DocxIrBlock): void => {\n if (block.kind === 'paragraph') {\n block.children.forEach(visitInline);\n return;\n }\n if (block.kind === 'table') {\n for (const row of block.rows) {\n for (const cell of row.cells) cell.children.forEach(visitBlock);\n }\n }\n };\n\n for (const section of ir.sections) {\n section.children.forEach(visitBlock);\n // Every chrome slot, not only `default`: an SVG that appears solely in a\n // first-page or even-page header would otherwise reach the package with\n // its own bytes labelled `image/png` as the raster fallback (#256).\n for (const slot of ['default', 'first', 'even'] as const) {\n section.headers?.[slot]?.children.forEach(visitBlock);\n section.footers?.[slot]?.children.forEach(visitBlock);\n }\n }\n for (const comment of ir.comments) comment.children.forEach(visitBlock);\n for (const note of [...ir.footnotes, ...ir.endnotes]) {\n note.children.forEach(visitBlock);\n }\n\n return placements;\n}\n\nfunction sectionOptions(\n section: DocxIrSection,\n resources: EmitResources\n): ISectionOptions {\n const { page, columns } = section.properties;\n const options: Record<string, unknown> = {\n properties: {\n ...(section.properties.type ? { type: section.properties.type } : {}),\n page: {\n // Orientation is implied by the width/height pair, which is how the\n // pre-IR writer expressed it; stating it as well changes `w:pgSz`.\n size: {\n width: page.widthTwips,\n height: page.heightTwips,\n ...(page.code !== undefined ? { code: page.code } : {}),\n },\n margin: {\n top: page.margins.topTwips,\n right: page.margins.rightTwips,\n bottom: page.margins.bottomTwips,\n left: page.margins.leftTwips,\n ...(page.margins.headerTwips !== undefined\n ? { header: page.margins.headerTwips }\n : {}),\n ...(page.margins.footerTwips !== undefined\n ? { footer: page.margins.footerTwips }\n : {}),\n ...(page.margins.gutterTwips !== undefined\n ? { gutter: page.margins.gutterTwips }\n : {}),\n },\n },\n ...(columns\n ? {\n column: {\n count: columns.count,\n ...(columns.spaceTwips !== undefined\n ? { space: columns.spaceTwips }\n : {}),\n ...(columns.equalWidth !== undefined\n ? { equalWidth: columns.equalWidth }\n : {}),\n ...(columns.widths\n ? {\n children: columns.widths.map(\n (c) =>\n new Column({\n width: c.widthTwips,\n ...(c.spaceTwips !== undefined\n ? { space: c.spaceTwips }\n : {}),\n })\n ),\n }\n : {}),\n },\n }\n : {}),\n },\n children: sectionChildren(section, resources),\n };\n\n const headers = chromeSlots(section.headers, Header, resources);\n if (headers) options.headers = headers;\n const footers = chromeSlots(section.footers, Footer, resources);\n if (footers) options.footers = footers;\n\n return options as unknown as ISectionOptions;\n}\n\n/**\n * The `default` / `first` / `even` parts a section carries, if any.\n *\n * All three slots, not only `default`: the IR distinguishes them and dropping\n * one here would lose a whole header without any diagnostic — the same gap the\n * SVG walk had (#256).\n */\nfunction chromeSlots(\n set: DocxIrSection['headers'],\n Part: typeof Header | typeof Footer,\n resources: EmitResources\n): Record<string, Header | Footer> | undefined {\n if (!set) return undefined;\n const out: Record<string, Header | Footer> = {};\n for (const slot of ['default', 'first', 'even'] as const) {\n const part = set[slot];\n if (part) {\n out[slot] = new Part({ children: partChildren(part, resources) });\n }\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nfunction partChildren(part: DocxIrHeaderFooter, resources: EmitResources) {\n return part.children.map((block) => emitBlock(block, resources));\n}\n\n/**\n * A section's blocks, wrapped in its bookmark range when it has one.\n *\n * The anchors are zero-spacing paragraphs because OOXML has nowhere else to put\n * them: a bookmark is an inline construct, so covering a section means opening\n * one before its content and closing it after, without the anchor paragraphs\n * themselves adding visible space.\n */\nfunction sectionChildren(\n section: DocxIrSection,\n resources: EmitResources\n): (Paragraph | Table)[] {\n const blocks = section.children.map((block) => emitBlock(block, resources));\n const bookmark = section.bookmark;\n if (!bookmark) return blocks;\n\n const out: (Paragraph | Table)[] = [];\n if (bookmark.opens) {\n out.push(\n new Paragraph({\n children: [new BookmarkStart(bookmark.name, bookmark.id)],\n spacing: { before: 0, after: 0, line: 0 },\n })\n );\n }\n out.push(...blocks);\n if (bookmark.closes) {\n out.push(new Paragraph({ children: [new BookmarkEnd(bookmark.id)] }));\n }\n return out;\n}\n\nfunction coreProperties(ir: DocxIR): Record<string, unknown> {\n const { metadata } = ir;\n return {\n ...(metadata.title ? { title: metadata.title } : {}),\n ...(metadata.subject ? { subject: metadata.subject } : {}),\n ...(metadata.description ? { description: metadata.description } : {}),\n ...(metadata.author ? { creator: metadata.author } : {}),\n ...(metadata.lastModifiedBy\n ? { lastModifiedBy: metadata.lastModifiedBy }\n : {}),\n ...(metadata.keywords ? { keywords: metadata.keywords } : {}),\n ...(metadata.custom?.length ? { customProperties: metadata.custom } : {}),\n };\n}\n","/**\n * DocxIR → `@office-open/docx` options.\n *\n * The backend takes a plain JSON document rather than an object graph, so this\n * layer is a pure function from IR nodes to option bags. Its vocabulary is\n * close to the docx.js adapter's — both mirror OOXML — but the two are kept\n * separate on purpose: they disagree about enough (tagged section children,\n * `simpleField` instead of a field class, `verticalMerge` instead of a merge\n * enum) that sharing the code would mean a conditional in every function.\n *\n * Backend gaps are handled by *not declaring the capability* in `index.ts`, so\n * anything this module cannot express has already been rejected before it is\n * called. Reaching a `throw` here is a bug, not a user error.\n */\n\nimport { assertNever } from '@json-to-office/shared/rendering';\nimport type {\n DocxIrBlock,\n DocxIrBorder,\n DocxIrBorders,\n DocxIrFloating,\n DocxIrFrame,\n DocxIrHeaderFooter,\n DocxIrImageRun,\n DocxIrInline,\n DocxIrNumbering,\n DocxIrParagraph,\n DocxIrParagraphFormatting,\n DocxIrParagraphMarkRevision,\n DocxIrRevisionRange,\n DocxIrRunFormatting,\n DocxIrSection,\n DocxIrShading,\n DocxIrShapeRun,\n DocxIrTable,\n DocxIrTableCell,\n DocxIrTableFloating,\n DocxIrTableOfContents,\n DocxIrTableRow,\n} from '../../ir/types';\nimport { emuToPixels, pixelsToEmu } from '../../ir/units';\n\ntype Opts = Record<string, unknown>;\n\n/**\n * One prepared picture per placement.\n *\n * A vector image needs a rasterised fallback sized to the placement, and\n * producing it is asynchronous while this layer is not — so the renderer builds\n * the pictures first and this only places them.\n */\nexport type ImagePictureFactory = (\n image: DocxIrImageRun,\n drawingId: number\n) => Opts;\n\n/**\n * What emitting a document needs beyond the IR itself.\n *\n * `nextDrawingId` exists because the backend numbers `wp:docPr` from a\n * module-level counter whenever a drawing does not state an id. That counter is\n * process-global: the same document rendered twice comes out with different\n * ids, and two rendered at once interleave. Every drawing this adapter emits\n * therefore states its own id, allocated per render in document order — which\n * is deterministic and cannot leak between documents.\n */\nexport interface EmitContext {\n /** Prepared pictures, keyed by IR resource id. */\n pictures: ReadonlyMap<string, ImagePictureFactory>;\n /** Allocate the next `wp:docPr` id for this document. */\n nextDrawingId: () => number;\n}\n\n/** A context for content that holds no drawings, and for tests. */\nexport function emptyContext(): EmitContext {\n let next = 1;\n return { pictures: new Map(), nextDrawingId: () => next++ };\n}\n\n/**\n * Where a field becomes a whole `w:fldSimple` rather than a run child.\n *\n * The backend writes any instruction this way, with its cached result inside,\n * so there is no per-instruction table to keep — which is the one place this\n * adapter is plainly better off than the docx.js one.\n */\nfunction simpleField(instruction: string, cachedText?: string): Opts {\n return {\n simpleField: {\n instruction,\n ...(cachedText !== undefined ? { cachedValue: cachedText } : {}),\n },\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Runs\n * ------------------------------------------------------------------ */\n\nexport function runProperties(\n formatting: DocxIrRunFormatting | undefined\n): Opts {\n if (!formatting) return {};\n const out: Opts = {};\n if (formatting.fontFamily) out.font = formatting.fontFamily;\n if (formatting.sizeHalfPoints !== undefined) {\n // The backend states run size in points and doubles it on the way out,\n // where docx.js takes half-points and writes them straight through.\n out.size = formatting.sizeHalfPoints / 2;\n }\n if (formatting.color) out.color = formatting.color.hex;\n if (formatting.bold !== undefined) out.bold = formatting.bold;\n // `italic` here, `italics` in docx.js — the one run property the two spell\n // differently.\n if (formatting.italic !== undefined) out.italic = formatting.italic;\n if (formatting.underline) {\n out.underline = {\n type: formatting.underline.type,\n ...(formatting.underline.color\n ? { color: formatting.underline.color.hex }\n : {}),\n };\n }\n if (formatting.strike !== undefined) out.strike = formatting.strike;\n if (formatting.doubleStrike !== undefined) {\n out.doubleStrike = formatting.doubleStrike;\n }\n if (formatting.superScript) out.superScript = true;\n if (formatting.subScript) out.subScript = true;\n if (formatting.smallCaps !== undefined) out.smallCaps = formatting.smallCaps;\n if (formatting.allCaps !== undefined) out.allCaps = formatting.allCaps;\n if (formatting.highlight !== undefined) out.highlight = formatting.highlight;\n if (formatting.shading) out.shading = shading(formatting.shading);\n if (formatting.scalePercent !== undefined)\n out.scale = formatting.scalePercent;\n if (formatting.characterSpacingTwentieths !== undefined) {\n out.characterSpacing = formatting.characterSpacingTwentieths;\n }\n if (formatting.language) out.language = { value: formatting.language };\n if (formatting.noProof !== undefined) out.noProof = formatting.noProof;\n return out;\n}\n\nfunction shading(value: DocxIrShading): Opts {\n return {\n fill: value.fill.hex,\n ...(value.pattern ? { type: value.pattern } : {}),\n ...(value.color ? { color: value.color.hex } : {}),\n };\n}\n\n/**\n * Turn inline nodes into paragraph children.\n *\n * `pendingBreaks` carries a run of `lineBreak` nodes forward onto whichever run\n * comes next, which is where the backend puts them — `<w:br/>` is run-inner\n * content, so it has to ride on a run either way.\n */\nexport function inlineChildren(\n children: readonly DocxIrInline[],\n ctx: EmitContext = emptyContext()\n): Opts[] {\n const out: Opts[] = [];\n let pendingBreaks = 0;\n let pendingClear: string | undefined;\n\n const breakOption = (): Opts => {\n if (pendingBreaks === 0) return {};\n const value: Opts = {\n break: pendingClear\n ? { count: pendingBreaks, clear: pendingClear }\n : pendingBreaks,\n };\n pendingBreaks = 0;\n pendingClear = undefined;\n return value;\n };\n\n for (const child of children) {\n switch (child.kind) {\n case 'lineBreak':\n pendingBreaks += 1;\n if (child.clear && child.clear !== 'none') pendingClear = child.clear;\n break;\n\n case 'text':\n out.push({\n text: child.text,\n ...(child.styleId ? { style: child.styleId } : {}),\n ...runProperties(child.formatting),\n ...breakOption(),\n });\n break;\n\n case 'tab':\n out.push({\n children: [{ tab: true }],\n ...runProperties(child.formatting),\n ...breakOption(),\n });\n break;\n\n case 'pageBreak':\n out.push({ pageBreak: true });\n break;\n\n case 'columnBreak':\n out.push({ columnBreak: true });\n break;\n\n case 'bookmarkStart':\n out.push({ bookmarkStart: { id: child.id, name: child.name } });\n break;\n\n case 'bookmarkEnd':\n out.push({ bookmarkEnd: { id: child.id } });\n break;\n\n case 'image': {\n const build = ctx.pictures.get(child.resourceId);\n if (!build) {\n throw new Error(\n `no image was prepared for resource \"${child.resourceId}\"`\n );\n }\n // A break before a drawing belongs on a run of its own: a run holding\n // both a `<w:br/>` and a `<w:drawing>` puts them in one element, and\n // the break then lands inside the anchor rather than before it.\n const pending = breakOption();\n if (pending.break) out.push(pending);\n out.push({ picture: build(child, ctx.nextDrawingId()) });\n break;\n }\n\n case 'hyperlink':\n out.push({\n hyperlink: {\n ...(child.target.kind === 'bookmark'\n ? { anchor: child.target.anchor }\n : { url: child.target.url }),\n children: inlineChildren(child.children, ctx),\n },\n });\n break;\n\n case 'field':\n out.push(simpleField(child.instruction, child.cachedText));\n break;\n\n case 'revision':\n out.push(...revisionRuns(child, breakOption()));\n break;\n\n case 'commentRangeStart':\n out.push({ commentRangeStart: { id: child.id } });\n break;\n\n case 'commentRangeEnd':\n out.push({ commentRangeEnd: { id: child.id } });\n break;\n\n case 'commentReference':\n out.push({ commentReference: child.id });\n break;\n\n case 'shape':\n out.push({ wpsShape: shapeOptions(child, ctx) });\n break;\n\n case 'noteReference':\n out.push(\n child.noteKind === 'endnote'\n ? { endnoteReference: child.id }\n : { footnoteReference: child.id }\n );\n break;\n\n default:\n assertNever(child, 'DocxIrInline');\n }\n }\n\n return out;\n}\n\n/**\n * A tracked change, as an `insertion` or `deletion` wrapping its runs.\n *\n * The backend has a real wrapper element, so the id/author/date sit on the\n * range itself rather than being copied onto every run inside it.\n */\nfunction revisionRuns(range: DocxIrRevisionRange, pending: Opts): Opts[] {\n const runs: Opts[] = [];\n let breaks = typeof pending.break === 'number' ? pending.break : 0;\n\n for (const child of range.children) {\n if (child.kind === 'lineBreak') {\n breaks += 1;\n continue;\n }\n if (child.kind !== 'text') {\n throw new Error(\n `the office-open renderer has no emitter for \"${child.kind}\" inside a revision`\n );\n }\n runs.push({\n text: child.text,\n ...runProperties(child.formatting),\n ...(breaks > 0 ? { break: breaks } : {}),\n });\n breaks = 0;\n }\n\n const mark = { id: range.id, author: range.author, date: range.date };\n return [\n range.type === 'insert'\n ? { insertion: { ...mark, children: runs } }\n : { deletion: { ...mark, children: runs } },\n ];\n}\n\n/** OOXML names its wrap types; the backend numbers them, as docx.js does. */\nconst WRAP_TYPE: Readonly<Record<string, number>> = {\n none: 0,\n square: 1,\n tight: 2,\n topAndBottom: 3,\n};\n\n/** An IR anchor as the backend's floating options. */\nexport function floatingOptions(floating: DocxIrFloating): Opts {\n const position = (axis: DocxIrFloating['horizontal']): Opts => ({\n ...(axis?.relativeTo ? { relative: axis.relativeTo } : {}),\n ...(axis?.align !== undefined ? { align: axis.align } : {}),\n ...(axis?.offsetEmu !== undefined ? { offset: axis.offsetEmu } : {}),\n });\n\n return {\n ...(floating.horizontal\n ? { horizontalPosition: position(floating.horizontal) }\n : {}),\n ...(floating.vertical\n ? { verticalPosition: position(floating.vertical) }\n : {}),\n ...(floating.wrap\n ? {\n wrap: {\n type: WRAP_TYPE[floating.wrap.type],\n ...(floating.wrap.side ? { side: floating.wrap.side } : {}),\n },\n }\n : {}),\n ...(floating.margins\n ? {\n margins: {\n ...(floating.margins.topEmu !== undefined\n ? { top: floating.margins.topEmu }\n : {}),\n ...(floating.margins.bottomEmu !== undefined\n ? { bottom: floating.margins.bottomEmu }\n : {}),\n ...(floating.margins.leftEmu !== undefined\n ? { left: floating.margins.leftEmu }\n : {}),\n ...(floating.margins.rightEmu !== undefined\n ? { right: floating.margins.rightEmu }\n : {}),\n },\n }\n : {}),\n ...(floating.allowOverlap !== undefined\n ? { allowOverlap: floating.allowOverlap }\n : {}),\n ...(floating.behindDocument !== undefined\n ? { behindDocument: floating.behindDocument }\n : {}),\n ...(floating.lockAnchor !== undefined\n ? { lockAnchor: floating.lockAnchor }\n : {}),\n ...(floating.layoutInCell !== undefined\n ? { layoutInCell: floating.layoutInCell }\n : {}),\n zIndex: floating.zIndex,\n };\n}\n\n/** A native text box: a `wps:wsp` shape holding paragraphs. */\nfunction shapeOptions(shape: DocxIrShapeRun, ctx: EmitContext): Opts {\n // Allocated before the children, so ids run in document order.\n const id = String(ctx.nextDrawingId());\n return {\n altText: { id },\n children: shape.children.map((child) => paragraph(child, ctx)),\n // Raw transformation numbers are EMUs in @office-open/docx, while the IR\n // deliberately stores native shape dimensions in pixels.\n transformation: {\n width: pixelsToEmu(shape.widthPx),\n height: pixelsToEmu(shape.heightPx),\n },\n ...(shape.fill\n ? {\n fill: {\n type: 'solid',\n color: { type: 'rgb', value: shape.fill.hex },\n },\n }\n : {}),\n ...(shape.outline\n ? {\n outline: {\n ...(shape.outline.widthEmu !== undefined\n ? { width: shape.outline.widthEmu }\n : {}),\n fill: {\n type: 'solid',\n color: { type: 'rgb', value: shape.outline.color.hex },\n },\n },\n }\n : {}),\n ...(shape.insetsEmu\n ? {\n bodyProperties: {\n ...(shape.insetsEmu.top !== undefined\n ? { topInset: shape.insetsEmu.top }\n : {}),\n ...(shape.insetsEmu.bottom !== undefined\n ? { bottomInset: shape.insetsEmu.bottom }\n : {}),\n ...(shape.insetsEmu.left !== undefined\n ? { leftInset: shape.insetsEmu.left }\n : {}),\n ...(shape.insetsEmu.right !== undefined\n ? { rightInset: shape.insetsEmu.right }\n : {}),\n },\n }\n : {}),\n ...(shape.floating ? { floating: floatingOptions(shape.floating) } : {}),\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Paragraphs\n * ------------------------------------------------------------------ */\n\nexport function paragraphProperties(\n formatting: DocxIrParagraphFormatting | undefined\n): Opts {\n const out: Opts = {};\n if (!formatting) return out;\n\n if (formatting.alignment) out.alignment = alignment(formatting.alignment);\n if (formatting.spacing) {\n const spacing: Opts = {};\n if (formatting.spacing.beforeTwips !== undefined) {\n spacing.before = formatting.spacing.beforeTwips;\n }\n if (formatting.spacing.afterTwips !== undefined) {\n spacing.after = formatting.spacing.afterTwips;\n }\n if (formatting.spacing.lineTwips !== undefined) {\n spacing.line = formatting.spacing.lineTwips;\n }\n // The rule stands on its own: `atLeast` with no height still says how the\n // line is measured.\n if (formatting.spacing.lineRule !== undefined) {\n spacing.lineRule = formatting.spacing.lineRule;\n }\n out.spacing = spacing;\n }\n if (formatting.indent) {\n const indent: Opts = {};\n if (formatting.indent.leftTwips !== undefined) {\n indent.left = formatting.indent.leftTwips;\n }\n if (formatting.indent.rightTwips !== undefined) {\n indent.right = formatting.indent.rightTwips;\n }\n if (formatting.indent.firstLineTwips !== undefined) {\n indent.firstLine = formatting.indent.firstLineTwips;\n }\n if (formatting.indent.hangingTwips !== undefined) {\n indent.hanging = formatting.indent.hangingTwips;\n }\n out.indent = indent;\n }\n if (formatting.tabStops) {\n out.tabStops = formatting.tabStops.map((stop) => ({\n type: stop.type,\n position: stop.positionTwips,\n ...(stop.leader ? { leader: stop.leader } : {}),\n }));\n }\n if (formatting.keepNext !== undefined) out.keepNext = formatting.keepNext;\n if (formatting.keepLines !== undefined) out.keepLines = formatting.keepLines;\n if (formatting.widowControl !== undefined) {\n out.widowControl = formatting.widowControl;\n }\n if (formatting.pageBreakBefore !== undefined) {\n out.pageBreakBefore = formatting.pageBreakBefore;\n }\n if (formatting.outlineLevel !== undefined) {\n out.outlineLevel = formatting.outlineLevel;\n }\n if (formatting.bidirectional !== undefined) {\n out.bidirectional = formatting.bidirectional;\n }\n if (formatting.borders) out.border = borders(formatting.borders);\n if (formatting.shading) out.shading = shading(formatting.shading);\n\n return out;\n}\n\n/** `justified` is the only alignment the two vocabularies spell differently. */\nfunction alignment(value: string): string {\n return value === 'justified' ? 'both' : value;\n}\n\nexport function paragraph(\n block: DocxIrParagraph,\n ctx: EmitContext = emptyContext()\n): Opts {\n return {\n children: inlineChildren(block.children, ctx),\n // A paragraph with no style named is one that deliberately has none — a\n // table cell, whose run properties come from the cell itself.\n ...(block.styleId ? { style: block.styleId } : {}),\n ...paragraphProperties(block.formatting),\n ...(block.markRevision ? { run: revisionMark(block.markRevision) } : {}),\n ...(block.frame ? { frame: frameOptions(block.frame) } : {}),\n ...(block.numbering\n ? {\n numbering: block.numbering.none\n ? // A literal false writes `numId 0`, which is how a paragraph\n // detaches from the numbering its style applies.\n false\n : {\n reference: block.numbering.reference,\n level: block.numbering.level,\n },\n }\n : {}),\n };\n}\n\n/**\n * A paragraph positioned as a floating box (`w:framePr`).\n *\n * Exactly one positioning mode: absolute when the frame states coordinates,\n * alignment otherwise. OOXML cannot mix them, and the backend takes the choice\n * as a discriminant.\n */\nfunction frameOptions(frame: DocxIrFrame): Opts {\n const base: Opts = {\n width: frame.widthTwips,\n height: frame.heightTwips,\n anchor: {\n horizontal: frame.anchorHorizontal,\n vertical: frame.anchorVertical,\n },\n ...(frame.wrap ? { wrap: frame.wrap } : {}),\n ...(frame.anchorLock !== undefined ? { anchorLock: frame.anchorLock } : {}),\n ...(frame.rule ? { rule: frame.rule } : {}),\n };\n\n return frame.xTwips !== undefined || frame.yTwips !== undefined\n ? {\n type: 'absolute',\n position: { x: frame.xTwips ?? 0, y: frame.yTwips ?? 0 },\n ...base,\n }\n : {\n type: 'alignment',\n alignment: { x: frame.xAlign, y: frame.yAlign },\n ...base,\n };\n}\n\n/** `w:ins` / `w:del` on a paragraph mark or a row. */\nfunction revisionMark(revision: DocxIrParagraphMarkRevision): Opts {\n const attributes = {\n id: revision.id,\n author: revision.author,\n date: revision.date,\n };\n return revision.type === 'insert'\n ? { insertion: attributes }\n : { deletion: attributes };\n}\n\n/** One IR block as a tagged section child, which is how the backend takes it. */\nexport function block(\n value: DocxIrBlock,\n ctx: EmitContext = emptyContext()\n): Opts {\n switch (value.kind) {\n case 'paragraph':\n return { paragraph: paragraph(value, ctx) };\n case 'table':\n return { table: table(value, ctx) };\n case 'toc':\n return { toc: tableOfContents(value) };\n default:\n return assertNever(value, 'DocxIrBlock');\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Table of contents\n * ------------------------------------------------------------------ */\n\n/**\n * Where a cached TOC entry's page number sits.\n *\n * One twip inside `TabStopPosition.MAX`, which is the constant docx.js uses for\n * the same job — a fixed measure edge rather than one derived from the page, so\n * an entry looks the same wherever the field appears.\n */\nconst TOC_PAGE_TAB_TWIPS = 9025;\n\n/**\n * A cached TOC entry.\n *\n * Text, then a tab to the page-number stop. The number itself is left empty:\n * the IR carries no page for an entry, because nothing before a layout pass\n * knows one. Word fills both in the moment it refreshes the field; a reader\n * that never refreshes still shows the entries, which is the whole point of\n * caching them.\n */\nfunction tocEntry(entry: { text: string; level: number }): Opts {\n return {\n paragraph: {\n style: `TOC${entry.level}`,\n tabStops: [\n { type: 'right', position: TOC_PAGE_TAB_TWIPS, leader: 'dot' },\n ],\n children: [{ text: entry.text }, { children: [{ tab: true }] }],\n },\n };\n}\n\nfunction tableOfContents(value: DocxIrTableOfContents): Opts {\n return {\n alias: value.alias ?? 'Table of Contents',\n ...(value.hyperlink !== undefined ? { hyperlink: value.hyperlink } : {}),\n ...(value.headingRange\n ? {\n headingStyleRange: `${value.headingRange.from}-${value.headingRange.to}`,\n }\n : {}),\n ...(value.styleLevels?.length\n ? {\n stylesWithLevels: value.styleLevels.map((style) => ({\n styleName: style.styleName,\n level: style.level,\n })),\n }\n : {}),\n ...(value.bookmarkScope\n ? { entriesFromBookmark: value.bookmarkScope }\n : {}),\n ...(value.omitPageNumbersForLevels?.length\n ? {\n pageNumbersEntryLevelsRange: value.omitPageNumbersForLevels\n .map((range) => `${range.from}-${range.to}`)\n .join(','),\n }\n : {}),\n ...(value.entrySeparator !== undefined\n ? { entryAndPageNumberSeparator: value.entrySeparator }\n : {}),\n ...(value.cachedEntries?.length\n ? { entries: value.cachedEntries.map(tocEntry) }\n : {}),\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Tables\n * ------------------------------------------------------------------ */\n\nexport function table(value: DocxIrTable, ctx: EmitContext): Opts {\n return {\n rows: value.rows.map((row) => tableRow(row, ctx)),\n width: {\n size: value.width.kind === 'auto' ? 0 : value.width.value,\n type:\n value.width.kind === 'twips'\n ? 'dxa'\n : value.width.kind === 'percent'\n ? 'pct'\n : 'auto',\n },\n layout: value.layout,\n // An empty grid is a table with nothing to say about its columns, which is\n // not the same as one whose columns are all zero wide.\n ...(value.columnGrid.values.length > 0\n ? { columnWidths: value.columnGrid.values }\n : {}),\n ...(value.alignment ? { alignment: alignment(value.alignment) } : {}),\n ...(value.borders ? { borders: borders(value.borders) } : {}),\n ...(value.cellMargins ? { margins: cellMargins(value.cellMargins) } : {}),\n ...(value.floating ? { float: tableFloat(value.floating) } : {}),\n };\n}\n\nfunction tableFloat(floating: DocxIrTableFloating): Opts {\n return {\n ...(floating.horizontalAnchor\n ? { horizontalAnchor: floating.horizontalAnchor }\n : {}),\n ...(floating.verticalAnchor\n ? { verticalAnchor: floating.verticalAnchor }\n : {}),\n ...(floating.absoluteHorizontalPositionTwips !== undefined\n ? { absoluteHorizontalPosition: floating.absoluteHorizontalPositionTwips }\n : {}),\n ...(floating.relativeHorizontalPosition\n ? { relativeHorizontalPosition: floating.relativeHorizontalPosition }\n : {}),\n ...(floating.absoluteVerticalPositionTwips !== undefined\n ? { absoluteVerticalPosition: floating.absoluteVerticalPositionTwips }\n : {}),\n ...(floating.relativeVerticalPosition\n ? { relativeVerticalPosition: floating.relativeVerticalPosition }\n : {}),\n ...(floating.topFromTextTwips !== undefined\n ? { topFromText: floating.topFromTextTwips }\n : {}),\n ...(floating.rightFromTextTwips !== undefined\n ? { rightFromText: floating.rightFromTextTwips }\n : {}),\n ...(floating.bottomFromTextTwips !== undefined\n ? { bottomFromText: floating.bottomFromTextTwips }\n : {}),\n ...(floating.leftFromTextTwips !== undefined\n ? { leftFromText: floating.leftFromTextTwips }\n : {}),\n ...(floating.overlap ? { overlap: floating.overlap } : {}),\n };\n}\n\nfunction tableRow(row: DocxIrTableRow, ctx: EmitContext): Opts {\n return {\n cells: row.cells.map((cell) => tableCell(cell, ctx)),\n ...(row.heightTwips !== undefined\n ? {\n height: { value: row.heightTwips, rule: row.heightRule ?? 'atLeast' },\n }\n : {}),\n ...(row.isHeader !== undefined ? { tableHeader: row.isHeader } : {}),\n ...(row.cantSplit !== undefined ? { cantSplit: row.cantSplit } : {}),\n ...(row.revision ? revisionMark(row.revision) : {}),\n };\n}\n\nfunction tableCell(cell: DocxIrTableCell, ctx: EmitContext): Opts {\n return {\n children: cell.children.map((child) => block(child, ctx)),\n ...(cell.widthTwips !== undefined\n ? { width: { size: cell.widthTwips, type: 'dxa' } }\n : {}),\n ...(cell.verticalAlign ? { verticalAlign: cell.verticalAlign } : {}),\n ...(cell.shading ? { shading: shading(cell.shading) } : {}),\n ...(cell.margins ? { margins: cellMargins(cell.margins) } : {}),\n ...(cell.borders ? { borders: borders(cell.borders) } : {}),\n ...(cell.columnSpan !== undefined ? { columnSpan: cell.columnSpan } : {}),\n ...(cell.rowSpan !== undefined ? { verticalMerge: cell.rowSpan } : {}),\n ...(cell.textDirection ? { textDirection: cell.textDirection } : {}),\n };\n}\n\n/** Cell margins, stated in twips, which the backend only believes if told. */\nfunction cellMargins(margins: {\n topTwips?: number;\n bottomTwips?: number;\n leftTwips?: number;\n rightTwips?: number;\n}): Opts {\n const side = (value: number | undefined): Opts | undefined =>\n value === undefined ? undefined : { size: value, type: 'dxa' };\n const out: Opts = {};\n for (const [name, value] of [\n ['top', margins.topTwips],\n ['bottom', margins.bottomTwips],\n ['left', margins.leftTwips],\n ['right', margins.rightTwips],\n ] as const) {\n const width = side(value);\n if (width) out[name] = width;\n }\n return out;\n}\n\nfunction border(value: DocxIrBorder): Opts {\n return {\n style: value.style,\n ...(value.sizeEighthPoints !== undefined\n ? { size: value.sizeEighthPoints }\n : {}),\n ...(value.color ? { color: value.color.hex } : {}),\n ...(value.spacePoints !== undefined ? { space: value.spacePoints } : {}),\n };\n}\n\nfunction borders(value: DocxIrBorders): Opts {\n const out: Opts = {};\n for (const side of [\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'insideHorizontal',\n 'insideVertical',\n 'between',\n ] as const) {\n const declared = value[side];\n if (declared) out[side] = border(declared);\n }\n return out;\n}\n\n/* ------------------------------------------------------------------ *\n * Sections\n * ------------------------------------------------------------------ */\n\nexport function section(value: DocxIrSection, ctx: EmitContext): Opts {\n const { page, columns } = value.properties;\n return {\n properties: {\n ...(value.properties.type ? { type: value.properties.type } : {}),\n ...(value.properties.titlePage !== undefined\n ? { titlePage: value.properties.titlePage }\n : {}),\n page: {\n // Orientation is implied by the width/height pair, which is how this\n // pipeline has always expressed it; stating it as well changes `w:pgSz`.\n size: {\n width: page.widthTwips,\n height: page.heightTwips,\n ...(page.code !== undefined ? { code: page.code } : {}),\n },\n margin: {\n top: page.margins.topTwips,\n right: page.margins.rightTwips,\n bottom: page.margins.bottomTwips,\n left: page.margins.leftTwips,\n ...(page.margins.headerTwips !== undefined\n ? { header: page.margins.headerTwips }\n : {}),\n ...(page.margins.footerTwips !== undefined\n ? { footer: page.margins.footerTwips }\n : {}),\n ...(page.margins.gutterTwips !== undefined\n ? { gutter: page.margins.gutterTwips }\n : {}),\n },\n ...(value.properties.pageNumbers\n ? {\n pageNumbers: {\n ...(value.properties.pageNumbers.start !== undefined\n ? { start: value.properties.pageNumbers.start }\n : {}),\n ...(value.properties.pageNumbers.formatType\n ? { formatType: value.properties.pageNumbers.formatType }\n : {}),\n },\n }\n : {}),\n ...(value.properties.borders\n ? {\n borders: {\n ...(value.properties.borders.display\n ? { display: value.properties.borders.display }\n : {}),\n ...(value.properties.borders.offsetFrom\n ? { offsetFrom: value.properties.borders.offsetFrom }\n : {}),\n ...(value.properties.borders.borders\n ? borders(value.properties.borders.borders)\n : {}),\n },\n }\n : {}),\n },\n ...(columns\n ? {\n column: {\n count: columns.count,\n ...(columns.spaceTwips !== undefined\n ? { space: columns.spaceTwips }\n : {}),\n ...(columns.separator !== undefined\n ? { separate: columns.separator }\n : {}),\n ...(columns.equalWidth !== undefined\n ? { equalWidth: columns.equalWidth }\n : {}),\n ...(columns.widths\n ? {\n children: columns.widths.map((column) => ({\n width: column.widthTwips,\n ...(column.spaceTwips !== undefined\n ? { space: column.spaceTwips }\n : {}),\n })),\n }\n : {}),\n },\n }\n : {}),\n },\n children: sectionChildren(value, ctx),\n ...(value.headers ? { headers: headerFooterSet(value.headers, ctx) } : {}),\n ...(value.footers ? { footers: headerFooterSet(value.footers, ctx) } : {}),\n };\n}\n\nfunction headerFooterSet(\n set: {\n default?: DocxIrHeaderFooter;\n first?: DocxIrHeaderFooter;\n even?: DocxIrHeaderFooter;\n },\n ctx: EmitContext\n): Opts {\n const out: Opts = {};\n for (const slot of ['default', 'first', 'even'] as const) {\n const part = set[slot];\n if (part) out[slot] = part.children.map((child) => block(child, ctx));\n }\n return out;\n}\n\n/**\n * A section's blocks, wrapped in its bookmark range when it has one.\n *\n * The backend takes a bookmark as a section child of its own, so unlike the\n * docx.js adapter there are no anchor paragraphs to carry it — the range opens\n * and closes between blocks, which is what OOXML allows and what a reader\n * expects to find.\n */\nfunction sectionChildren(value: DocxIrSection, ctx: EmitContext): Opts[] {\n const blocks = value.children.map((child) => block(child, ctx));\n const bookmark = value.bookmark;\n if (!bookmark) return blocks;\n\n return [\n ...(bookmark.opens\n ? [{ bookmarkStart: { id: bookmark.id, name: bookmark.name } }]\n : []),\n ...blocks,\n ...(bookmark.closes ? [{ bookmarkEnd: { id: bookmark.id } }] : []),\n ];\n}\n\n/* ------------------------------------------------------------------ *\n * Numbering\n * ------------------------------------------------------------------ */\n\nexport function numberingConfig(numbering: DocxIrNumbering): Opts {\n return {\n reference: numbering.reference,\n levels: numbering.levels.map((level) => ({\n level: level.level,\n format: level.format,\n text: level.text,\n ...(level.alignment ? { alignment: alignment(level.alignment) } : {}),\n ...(level.suffix ? { suffix: level.suffix } : {}),\n ...(level.start !== undefined ? { start: level.start } : {}),\n ...(level.paragraphStyleId\n ? { paragraphStyle: level.paragraphStyleId }\n : {}),\n style: {\n ...(level.indent\n ? {\n paragraph: {\n indent: {\n ...(level.indent.leftTwips !== undefined\n ? { left: level.indent.leftTwips }\n : {}),\n ...(level.indent.hangingTwips !== undefined\n ? { hanging: level.indent.hangingTwips }\n : {}),\n },\n },\n }\n : {}),\n ...(level.run ? { run: runProperties(level.run) } : {}),\n },\n })),\n };\n}\n\nexport { emuToPixels };\n","/**\n * DocxIR styles, as `@office-open/docx` style options.\n *\n * A mechanical translation: which styles exist and what each one says was\n * decided by the compiler, and this only renames the fields. Nothing here reads\n * a theme.\n */\n\nimport type { DocxIrBuiltInStyle, DocxIrStyles } from '../../ir/types';\nimport { paragraphProperties, runProperties } from './emit';\n\ntype Opts = Record<string, unknown>;\n\nfunction builtIn(style: DocxIrBuiltInStyle): Opts {\n return {\n ...(style.run ? { run: runProperties(style.run) } : {}),\n ...(style.paragraph\n ? { paragraph: paragraphProperties(style.paragraph) }\n : {}),\n };\n}\n\n/** Turn the IR's style set into the options the backend builds `styles.xml` from. */\nexport function emitStyles(styles: DocxIrStyles): Opts {\n const documentDefaults: Opts = {\n ...(Object.keys(styles.defaults.run).length > 0\n ? { run: runProperties(styles.defaults.run) }\n : {}),\n ...(Object.keys(styles.defaults.paragraph).length > 0\n ? { paragraph: paragraphProperties(styles.defaults.paragraph) }\n : {}),\n };\n\n const defaults: Opts = {\n ...(Object.keys(documentDefaults).length > 0\n ? { document: documentDefaults }\n : {}),\n };\n for (const slot of [\n 'footnoteText',\n 'footnoteReference',\n 'endnoteText',\n 'endnoteReference',\n ] as const) {\n const style = styles.builtIn?.[slot];\n if (style) defaults[slot] = builtIn(style);\n }\n\n return {\n paragraphStyles: styles.paragraph.map((style) => ({\n id: style.id,\n name: style.name,\n ...(style.basedOn !== undefined ? { basedOn: style.basedOn } : {}),\n ...(style.next !== undefined ? { next: style.next } : {}),\n ...(style.quickFormat !== undefined\n ? { quickFormat: style.quickFormat }\n : {}),\n ...(style.run ? { run: runProperties(style.run) } : {}),\n ...(style.paragraph\n ? { paragraph: paragraphProperties(style.paragraph) }\n : {}),\n })),\n ...(styles.character.length > 0\n ? {\n characterStyles: styles.character.map((style) => ({\n id: style.id,\n name: style.name,\n ...(style.basedOn !== undefined ? { basedOn: style.basedOn } : {}),\n run: runProperties(style.run),\n })),\n }\n : {}),\n ...(Object.keys(defaults).length > 0 ? { default: defaults } : {}),\n };\n}\n","/**\n * The experimental `@office-open/docx` renderer.\n *\n * Selecting it is explicit and opt-in; `docxjs` stays the default. The backend\n * is an optional peer dependency, resolved at call time so a missing package\n * surfaces as an install hint rather than a module-resolution failure.\n *\n * The capability set below is deliberately narrow. A feature is listed only\n * when it has been proven against the real package, never from its README, and\n * a gap in the backend is expressed by *omitting* the capability — which makes\n * the pipeline reject the document before any bytes exist, instead of shipping\n * a file with content quietly missing.\n */\n\nimport { ALL_DOCX_FEATURES, type DocxFeature } from '../../ir/features';\nimport type {\n DocxIR,\n DocxIrBlock,\n DocxIrInline,\n DocxIrNote,\n} from '../../ir/types';\nimport { rasterizeSvgFallback } from '../../utils/imageUtils';\nimport {\n canonicalizeDocxBuffer,\n resolveGenerationDate,\n} from '../../utils/packageDocument';\nimport type { DocxRenderOptions, DocxRenderer, DocxRendererId } from '../types';\nimport {\n block,\n emuToPixels,\n floatingOptions,\n numberingConfig,\n section,\n type EmitContext,\n type ImagePictureFactory,\n} from './emit';\nimport { emitStyles } from './styles';\n\nexport const OFFICE_OPEN_DOCX_RENDERER_ID: DocxRendererId = 'office-open';\n\n/**\n * Module specifier held in a variable so TypeScript does not resolve the\n * optional dependency at build time and the failure lands at selection time.\n */\nconst OFFICE_OPEN_DOCX = '@office-open/docx';\n\n/**\n * What this adapter does *not* declare, and why.\n *\n * - `cached-fields` — vocabulary no backend here emits; also undeclared by\n * `docxjs`.\n * - `comment-threads` — `CommentOptions` is `{id, author, initials, date,\n * children}`: it carries neither a parent nor a resolved state, so a threaded\n * reply would flatten into an unrelated top-level comment.\n * - `table-merged-cells`, `shading`, `borders`, `rtl` — vocabulary the compiler\n * does not require of any backend yet. Both adapters leave them out so the\n * declared sets keep meaning \"proven by a test\".\n */\nconst UNSUPPORTED: ReadonlySet<DocxFeature> = new Set<DocxFeature>([\n 'cached-fields',\n 'comment-threads',\n 'table-merged-cells',\n 'shading',\n 'borders',\n 'rtl',\n]);\n\nconst OFFICE_OPEN_CAPABILITIES: ReadonlySet<DocxFeature> = new Set(\n [...ALL_DOCX_FEATURES].filter((feature) => !UNSUPPORTED.has(feature))\n);\n\ninterface OfficeOpenBackend {\n generateDocument: (\n options: Record<string, unknown>,\n packerOptions?: { type?: string }\n ) => Promise<Uint8Array>;\n}\n\nexport async function createOfficeOpenDocxRenderer(): Promise<DocxRenderer> {\n // Throws `Cannot find package '@office-open/docx'` when the optional\n // dependency is absent; the registry rewrites that into an install hint.\n const backend = (await import(\n /* @vite-ignore */ OFFICE_OPEN_DOCX\n )) as unknown as OfficeOpenBackend;\n\n if (typeof backend.generateDocument !== 'function') {\n throw new Error(\n `${OFFICE_OPEN_DOCX} does not export generateDocument(); the installed version is not compatible with this adapter.`\n );\n }\n\n return {\n id: OFFICE_OPEN_DOCX_RENDERER_ID,\n format: 'docx',\n capabilities: OFFICE_OPEN_CAPABILITIES,\n async render(ir: DocxIR, options?: DocxRenderOptions): Promise<Uint8Array> {\n const document = await buildDocumentOptions(ir);\n const bytes = await backend.generateDocument(document, {\n type: 'uint8array',\n });\n const raw = Buffer.from(\n bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)\n );\n\n if (options?.deterministic === false) return new Uint8Array(raw);\n // The backend stamps ZIP entries with the wall clock, so the same\n // document rendered twice differs. Pinning those is a property of an\n // OOXML package rather than of this backend, which is why the same pass\n // runs over the default backend's output too.\n return new Uint8Array(\n canonicalizeDocxBuffer(\n raw,\n resolveGenerationDate({\n deterministic: options?.deterministic,\n generatedAt: options?.generatedAt,\n })\n )\n );\n },\n };\n}\n\n/**\n * Build the backend's document object for an IR document.\n *\n * Exported for tests: asserting on this object is far cheaper, and far more\n * legible, than unzipping a package.\n */\nexport async function buildDocumentOptions(\n ir: DocxIR\n): Promise<Record<string, unknown>> {\n // One counter for the whole document. `wp:docPr` ids only have to be unique\n // within their part, and numbering across every part is both simpler and\n // strictly stronger — see `EmitContext`.\n let nextDrawingId = 1;\n const ctx: EmitContext = {\n pictures: await prepareImages(ir),\n nextDrawingId: () => nextDrawingId++,\n };\n\n return {\n styles: emitStyles(ir.styles),\n sections: ir.sections.map((value) => section(value, ctx)),\n ...coreProperties(ir),\n features: {\n updateFields: ir.settings.updateFields,\n ...(ir.settings.trackRevisions ? { trackRevisions: true } : {}),\n },\n ...(ir.numbering.length > 0\n ? { numbering: { config: ir.numbering.map(numberingConfig) } }\n : {}),\n ...(ir.footnotes.length > 0\n ? { footnotes: noteBodies(ir.footnotes, ctx) }\n : {}),\n ...(ir.endnotes.length > 0\n ? { endnotes: noteBodies(ir.endnotes, ctx) }\n : {}),\n ...(ir.comments.length > 0\n ? {\n comments: {\n children: ir.comments.map((comment) => ({\n id: comment.id,\n author: comment.author,\n ...(comment.initials ? { initials: comment.initials } : {}),\n date: comment.date,\n children: comment.children.map((child) =>\n paragraphOf(child, ctx)\n ),\n })),\n },\n }\n : {}),\n };\n}\n\n/**\n * Note and comment bodies are paragraph options, not tagged section children.\n *\n * Anything else in one is a compiler bug rather than an author error: the\n * pipeline only ever puts paragraphs in a note or a comment.\n */\nfunction paragraphOf(\n value: DocxIrBlock,\n ctx: EmitContext\n): Record<string, unknown> {\n const emitted = block(value, ctx);\n const asParagraph = emitted.paragraph as Record<string, unknown> | undefined;\n if (!asParagraph) {\n throw new Error(\n `the office-open renderer expected a paragraph, not a \"${value.kind}\"`\n );\n }\n return asParagraph;\n}\n\n/** Note bodies keyed by id, which is how the backend takes them. */\nfunction noteBodies(\n notes: readonly DocxIrNote[],\n ctx: EmitContext\n): Record<string, { children: Record<string, unknown>[] }> {\n const bodies: Record<string, { children: Record<string, unknown>[] }> = {};\n for (const note of notes) {\n bodies[String(note.id)] = {\n children: note.children.map((child) => paragraphOf(child, ctx)),\n };\n }\n return bodies;\n}\n\n/**\n * Build a picture factory per resource.\n *\n * Separate from `buildDocumentOptions`'s synchronous work because a vector\n * image has to be rasterised for the fallback Word draws below 2016, and the\n * raster depends on the size the image is drawn at — so every placement of a\n * vector resource is rasterised up front and the factory looks the right one up.\n */\nasync function prepareImages(\n ir: DocxIR\n): Promise<ReadonlyMap<string, ImagePictureFactory>> {\n const placements = collectImagePlacements(ir);\n const rasters = new Map<string, Buffer | undefined>();\n\n for (const resource of ir.resources) {\n if (resource.kind !== 'image' || resource.mediaType !== 'svg') continue;\n for (const size of placements.get(resource.id) ?? []) {\n const [width, height] = size.split('x').map(Number);\n rasters.set(\n `${resource.id}:${size}`,\n await rasterizeSvgFallback(Buffer.from(resource.bytes), {\n width,\n height,\n })\n );\n }\n }\n\n const resources = new Map<string, ImagePictureFactory>();\n for (const resource of ir.resources) {\n if (resource.kind !== 'image') continue;\n const type = resource.mediaType;\n const data = Buffer.from(resource.bytes);\n const placementData = new Map<string, Buffer>();\n [...(placements.get(resource.id) ?? [])].forEach((size, index) => {\n placementData.set(\n size,\n index === 0 ? data : distinguishImageBytes(data, type, size)\n );\n });\n resources.set(resource.id, (image, drawingId) => {\n const rasterSize = {\n width: emuToPixels(image.widthEmu),\n height: emuToPixels(image.heightEmu),\n };\n const sizeKey = `${rasterSize.width}x${rasterSize.height}`;\n const transformation = {\n // Raw numbers are EMUs in @office-open/docx. Passing pixels here makes\n // a normal image only a few hundred EMUs wide, effectively a dot.\n width: image.widthEmu,\n height: image.heightEmu,\n };\n return {\n type,\n // @office-open/docx stores a drawing transformation on its deduplicated\n // media entry. Equivalent bytes drawn at a second size would otherwise\n // reuse the first size, so each distinct placement size gets equivalent\n // image bytes carrying a harmless format-native marker.\n data: placementData.get(sizeKey) ?? data,\n transformation,\n // The id is stated rather than left to the backend's process-global\n // counter. `name` stays empty, which is what it was before and what\n // the backend falls back to.\n altText: { id: String(drawingId) },\n ...(type === 'svg'\n ? {\n // Word before 2016 draws the fallback rather than the vector. A\n // raster that could not be produced falls back to the SVG bytes,\n // which is what this pipeline has always shipped.\n fallback: {\n type: 'png',\n data: rasters.get(`${image.resourceId}:${sizeKey}`) ?? data,\n },\n }\n : {}),\n ...(image.floating\n ? { floating: floatingOptions(image.floating) }\n : {}),\n // No `description` or `title`: no DOCX this pipeline has produced\n // carries `wp:docPr` alt text, and the compiler warns so the gap is\n // visible rather than silent.\n };\n });\n }\n return resources;\n}\n\n/**\n * Keep an image visually identical while giving a differently-sized placement\n * distinct bytes. The backend deduplicates media by bytes and, unlike OOXML,\n * keeps the drawing extent on that shared media record.\n */\nfunction distinguishImageBytes(\n data: Buffer,\n mediaType: string,\n placement: string\n): Buffer {\n const marker = Buffer.from(`json-to-office:${placement}`, 'utf8');\n\n switch (mediaType) {\n case 'png':\n return addPngTextChunk(data, marker);\n case 'jpg':\n return addJpegComment(data, marker);\n case 'gif':\n return addGifComment(data, marker);\n case 'svg':\n return Buffer.concat([\n data,\n Buffer.from(`\\n<!-- ${marker.toString('utf8')} -->`, 'utf8'),\n ]);\n case 'bmp': {\n const marked = Buffer.concat([data, marker]);\n if (\n marked.length >= 14 &&\n marked.subarray(0, 2).toString('ascii') === 'BM'\n ) {\n marked.writeUInt32LE(marked.length, 2);\n }\n return marked;\n }\n default:\n return Buffer.concat([data, marker]);\n }\n}\n\n/** Insert a valid ancillary tEXt chunk immediately before PNG's IEND chunk. */\nfunction addPngTextChunk(data: Buffer, marker: Buffer): Buffer {\n const signature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);\n if (data.length < 8 || !data.subarray(0, 8).equals(signature)) {\n return Buffer.concat([data, marker]);\n }\n\n let offset = 8;\n while (offset + 12 <= data.length) {\n const payloadLength = data.readUInt32BE(offset);\n const chunkEnd = offset + 12 + payloadLength;\n if (chunkEnd > data.length) break;\n if (data.subarray(offset + 4, offset + 8).toString('ascii') === 'IEND') {\n const payload = Buffer.concat([\n Buffer.from('json-to-office\\0', 'latin1'),\n marker,\n ]);\n const chunk = Buffer.alloc(12 + payload.length);\n chunk.writeUInt32BE(payload.length, 0);\n chunk.write('tEXt', 4, 4, 'ascii');\n payload.copy(chunk, 8);\n chunk.writeUInt32BE(\n crc32(chunk.subarray(4, 8 + payload.length)),\n 8 + payload.length\n );\n return Buffer.concat([\n data.subarray(0, offset),\n chunk,\n data.subarray(offset),\n ]);\n }\n offset = chunkEnd;\n }\n\n return Buffer.concat([data, marker]);\n}\n\n/** Insert a legal JPEG COM segment after the start-of-image marker. */\nfunction addJpegComment(data: Buffer, marker: Buffer): Buffer {\n if (data.length < 2 || data[0] !== 0xff || data[1] !== 0xd8) {\n return Buffer.concat([data, marker]);\n }\n const comment = Buffer.alloc(4 + marker.length);\n comment[0] = 0xff;\n comment[1] = 0xfe;\n comment.writeUInt16BE(marker.length + 2, 2);\n marker.copy(comment, 4);\n return Buffer.concat([data.subarray(0, 2), comment, data.subarray(2)]);\n}\n\n/** Insert a legal GIF comment extension before the trailer. */\nfunction addGifComment(data: Buffer, marker: Buffer): Buffer {\n const trailer = data.lastIndexOf(0x3b);\n if (trailer < 0 || marker.length > 255) {\n return Buffer.concat([data, marker]);\n }\n const comment = Buffer.concat([\n Buffer.from([0x21, 0xfe, marker.length]),\n marker,\n Buffer.from([0]),\n ]);\n return Buffer.concat([\n data.subarray(0, trailer),\n comment,\n data.subarray(trailer),\n ]);\n}\n\n/** CRC-32 used by PNG chunks. */\nfunction crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) {\n crc ^= byte;\n for (let bit = 0; bit < 8; bit += 1) {\n crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);\n }\n }\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/**\n * Every size each image resource is drawn at, as `WxH` in pixels.\n *\n * Only vector resources need this, but the walk cannot know which is which\n * without the resource list, and walking twice would cost more than it saves.\n */\nfunction collectImagePlacements(ir: DocxIR): Map<string, Set<string>> {\n const placements = new Map<string, Set<string>>();\n\n const visitInline = (inline: DocxIrInline): void => {\n if (inline.kind === 'image') {\n const key = `${emuToPixels(inline.widthEmu)}x${emuToPixels(inline.heightEmu)}`;\n const sizes = placements.get(inline.resourceId) ?? new Set<string>();\n sizes.add(key);\n placements.set(inline.resourceId, sizes);\n return;\n }\n if (inline.kind === 'hyperlink' || inline.kind === 'revision') {\n inline.children.forEach(visitInline);\n return;\n }\n if (inline.kind === 'shape') inline.children.forEach(visitBlock);\n };\n\n const visitBlock = (value: DocxIrBlock): void => {\n if (value.kind === 'paragraph') {\n value.children.forEach(visitInline);\n return;\n }\n if (value.kind === 'table') {\n for (const row of value.rows) {\n for (const cell of row.cells) cell.children.forEach(visitBlock);\n }\n }\n };\n\n for (const value of ir.sections) {\n value.children.forEach(visitBlock);\n for (const slot of ['default', 'first', 'even'] as const) {\n value.headers?.[slot]?.children.forEach(visitBlock);\n value.footers?.[slot]?.children.forEach(visitBlock);\n }\n }\n for (const comment of ir.comments) comment.children.forEach(visitBlock);\n for (const note of [...ir.footnotes, ...ir.endnotes]) {\n note.children.forEach(visitBlock);\n }\n\n return placements;\n}\n\nfunction coreProperties(ir: DocxIR): Record<string, unknown> {\n const { metadata } = ir;\n return {\n ...(metadata.title ? { title: metadata.title } : {}),\n ...(metadata.subject ? { subject: metadata.subject } : {}),\n ...(metadata.description ? { description: metadata.description } : {}),\n ...(metadata.author ? { creator: metadata.author } : {}),\n ...(metadata.lastModifiedBy\n ? { lastModifiedBy: metadata.lastModifiedBy }\n : {}),\n ...(metadata.keywords ? { keywords: metadata.keywords } : {}),\n ...(metadata.custom?.length ? { customProperties: metadata.custom } : {}),\n };\n}\n","/**\n * Document generation entry points.\n *\n * Every path here compiles the authoring tree to DocxIR and hands it to a\n * renderer adapter; nothing in this module knows which backend that is. The\n * default is `docxjs`, which reproduces the output this pipeline has always\n * produced — see `src/__tests__/corpus-ir-parity.test.ts`.\n *\n * The surface is buffer- and file-oriented. No entry point returns or accepts a\n * renderer-native object: the whole point of the IR is that the backend is an\n * implementation detail, and handing a caller a docx.js `Document` would make\n * it part of the contract again.\n */\n\nimport { writeFileSync } from 'fs';\nimport { dirname, resolve } from 'path';\nimport {\n ComponentDefinition,\n ReportProps,\n ReportComponentDefinition,\n isReportComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';\nimport { generateBufferViaIr } from './generateFromIr';\nimport type { DocxRendererId } from '../renderers/types';\n\n// JSON support imports\nimport {\n DOCX_RENDERER_IDS,\n DocumentValidationResult,\n} from '@json-to-office/shared-docx';\nimport type { GenerationWarning } from '@json-to-office/shared';\nimport {\n validateJsonComponent,\n JsonParsingError,\n JsonValidationError,\n} from '../json/parser';\nimport { loadJsonDefinition } from '../json/filesystem';\n\n// Local generation options type\nexport interface JsonGenerationOptions {\n outputPath?: string;\n validation?: {\n /**\n * Validate the document against the schema before building, throwing on\n * errors. Defaults to `true` — invalid props are surfaced rather than\n * silently dropped into a corrupt/incomplete document.\n */\n enabled?: boolean;\n /**\n * When true, unknown/extra properties are stripped instead of rejected by\n * strict (additionalProperties:false) schemas. Escape hatch for migration.\n */\n allowUnknownFields?: boolean;\n /** @deprecated No longer consulted; retained for back-compat. */\n strict?: boolean;\n };\n customThemes?: { [key: string]: ThemeConfig };\n services?: ServicesConfig;\n fonts?: FontRuntimeOpts;\n /**\n * Optional collector for structured warnings (font resolution, etc.).\n * When provided, mirrors the plugin path's warning semantics; when absent,\n * warnings fall back to `console.warn` as before.\n */\n warnings?: GenerationWarning[];\n /** Normalize volatile OOXML values for byte-identical output. Defaults true. */\n deterministic?: boolean;\n /** Build timestamp for metadata; defaults to a stable epoch. */\n generatedAt?: string | Date;\n /**\n * Directory that relative asset paths (image `path` props) resolve against.\n * File entry points default it to the document's own directory; elsewhere\n * it falls back to `process.cwd()` (#142).\n */\n baseDir?: string;\n /**\n * Backend to render with. Defaults to `docxjs`.\n *\n * The default reproduces byte-for-byte what this pipeline has always\n * produced; anything else is opt-in and may not.\n */\n renderer?: DocxRendererId;\n}\n\n/** A generated package, with whatever the pipeline had to say about it. */\nexport interface DocxGenerationResult {\n buffer: Buffer;\n warnings: GenerationWarning[];\n}\n\n/**\n * Type guard to check if input is a report component definition\n */\nexport function isReportComponentDefinition(\n definition: unknown\n): definition is ReportComponentDefinition {\n if (typeof definition !== 'object' || definition === null) {\n return false;\n }\n\n const def = definition as Record<string, unknown>;\n\n // Must be a report component (optionally with $schema for JSON validation).\n // `props` is optional: a propless root generates like one with `props: {}`.\n return def.name === 'docx';\n}\n\n/**\n * Generate a `.docx` buffer from a report definition, with its warnings.\n *\n * Validation runs first unless the caller opts out: the same validator the\n * playground uses, so an object or a buffer is held to the same standard as a\n * pasted document and malformed props are surfaced rather than dropped into an\n * incomplete file.\n */\nexport async function generateBufferWithWarnings(\n jsonConfig: string | ComponentDefinition | ReportComponentDefinition,\n options?: JsonGenerationOptions\n): Promise<DocxGenerationResult> {\n const document = parseDocument(jsonConfig);\n const renderer = options?.renderer ?? document.renderer;\n const validation = options?.validation;\n if (validation?.enabled !== false) {\n const result = validateJsonComponent(\n renderer && DOCX_RENDERER_IDS.includes(renderer)\n ? { ...document, renderer }\n : document,\n {\n allowUnknownFields: validation?.allowUnknownFields,\n }\n );\n const errors = result.errors.filter(\n (error) => error.code !== 'unsupported_renderer_feature'\n );\n if (errors.length > 0) {\n throw new JsonValidationError('Document validation failed', errors);\n }\n }\n\n return generateBufferViaIr(document, {\n ...(options?.customThemes ? { customThemes: options.customThemes } : {}),\n ...(options?.services ? { services: options.services } : {}),\n ...(options?.fonts ? { fonts: options.fonts } : {}),\n ...(options?.warnings ? { warnings: options.warnings } : {}),\n ...(options?.baseDir !== undefined ? { baseDir: options.baseDir } : {}),\n ...(options?.deterministic !== undefined\n ? { deterministic: options.deterministic }\n : {}),\n ...(options?.generatedAt !== undefined\n ? { generatedAt: options.generatedAt }\n : {}),\n ...(renderer ? { renderer } : {}),\n });\n}\n\n/** Resolve a JSON string or an object to the report definition to build. */\nfunction parseDocument(\n jsonConfig: string | ComponentDefinition | ReportComponentDefinition\n): ReportComponentDefinition {\n if (typeof jsonConfig !== 'string') {\n return jsonConfig as ReportComponentDefinition;\n }\n\n let parsed: ComponentDefinition;\n try {\n parsed = JSON.parse(jsonConfig) as ComponentDefinition;\n } catch (error) {\n throw new JsonParsingError('Invalid JSON syntax', [\n {\n path: '',\n message: error instanceof Error ? error.message : 'Invalid JSON',\n code: 'JSON_PARSE_ERROR',\n },\n ]);\n }\n if (!isReportComponent(parsed)) {\n throw new Error('Parsed JSON must be a docx component');\n }\n return parsed as ReportComponentDefinition;\n}\n\n/**\n * Generate a `.docx` buffer from a report definition built out of props and\n * children — the same document as passing `{ name: 'docx', props, children }`.\n */\nexport async function generateBufferFromConfig(\n props: ReportProps,\n components: ComponentDefinition[],\n options?: JsonGenerationOptions\n): Promise<Buffer> {\n return generateBufferFromJson(\n { name: 'docx', props, children: components } as ReportComponentDefinition,\n options\n );\n}\n\n/**\n * Validate JSON schema without generating document\n */\nexport function validateJsonSchema(\n jsonConfig: string | object\n): DocumentValidationResult {\n return validateJsonComponent(jsonConfig);\n}\n\n/**\n * Generate a `.docx` buffer from a report definition.\n */\nexport async function generateBufferFromJson(\n jsonConfig: string | ComponentDefinition | ReportComponentDefinition,\n options?: JsonGenerationOptions\n): Promise<Buffer> {\n const { buffer } = await generateBufferWithWarnings(jsonConfig, options);\n return buffer;\n}\n\n/**\n * Generate and save a `.docx` file from a report definition.\n */\nexport async function generateAndSaveFromJson(\n jsonConfig: string | ComponentDefinition | ReportComponentDefinition,\n filename: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n writeFileSync(filename, await generateBufferFromJson(jsonConfig, options));\n}\n\n/**\n * Generate a `.docx` buffer from a JSON file.\n *\n * The document's own directory is the natural base for its relative assets, so\n * it becomes the default `baseDir` unless the caller says otherwise.\n */\nexport async function generateBufferFromFile(\n filePath: string,\n options?: JsonGenerationOptions\n): Promise<Buffer> {\n const definition = await loadJsonDefinition(filePath);\n return generateBufferFromJson(definition, {\n baseDir: dirname(resolve(filePath)),\n ...options,\n });\n}\n\n/**\n * Generate and save a `.docx` file from a JSON file.\n */\nexport async function generateAndSaveFromFile(\n inputFilePath: string,\n outputFilePath: string,\n options?: JsonGenerationOptions\n): Promise<void> {\n writeFileSync(\n outputFilePath,\n await generateBufferFromFile(inputFilePath, options)\n );\n}\n\n/**\n * Compose multiple transform functions\n * Utility for creating custom pipelines\n */\nexport function pipe<T>(...fns: Array<(_arg: T) => T>): (_arg: T) => T {\n return (_arg: T) => fns.reduce((acc, fn) => fn(acc), _arg);\n}\n\n/**\n * The main API surface.\n *\n * Buffer- and file-oriented only: no member returns a renderer-native object.\n */\nexport const DocumentGenerator = {\n generateBufferFromJson,\n generateBufferWithWarnings,\n generateBufferFromConfig,\n generateBufferFromFile,\n generateAndSaveFromJson,\n generateAndSaveFromFile,\n validateJsonSchema,\n isReportComponentDefinition,\n};\n","import type { ThemeName } from '../styles';\nimport type { TocHeadingEntry } from '../core/collectTocHeadings';\nimport type {\n ServicesConfig,\n PptxRasterizeBatchSlideResult,\n RasterizeFontFace,\n} from '@json-to-office/shared';\n\n// Import types from shared-docx that core needs for its internal use\nimport type {\n ComponentDefinition as SharedComponentDefinition,\n ReportComponent,\n ReportComponentFor,\n SectionComponent,\n ColumnsComponent,\n HeadingComponent,\n ParagraphComponent,\n ImageComponent,\n HighchartsComponent,\n VisualComponent,\n StatisticComponent,\n TableComponent,\n ListComponent,\n TocComponent,\n TextBoxComponent,\n\n // Import props types needed internally\n ReportProps as SharedReportProps,\n SectionProps as SharedSectionProps,\n HeadingProps as SharedHeadingProps,\n ParagraphProps as SharedParagraphProps,\n ColumnsProps as SharedColumnsProps,\n ImageProps as SharedImageProps,\n VisualProps as SharedVisualProps,\n StatisticProps as SharedStatisticProps,\n TableProps as SharedTableProps,\n ListProps as SharedListProps,\n TocProps as SharedTocProps,\n TextBoxProps as SharedTextBoxProps,\n} from '@json-to-office/shared-docx';\n\n// Import type guards from shared-docx (these are runtime functions core needs)\nexport {\n isReportComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isColumnsComponent,\n isImageComponent,\n isTextBoxComponent,\n isStatisticComponent,\n isTableComponent,\n isListComponent,\n isTocComponent,\n isHighchartsComponent,\n isVisualComponent,\n} from '@json-to-office/shared-docx';\n\n// Re-export component definitions for internal use (type aliases for clarity)\nexport type ComponentDefinition = SharedComponentDefinition;\nexport type ReportComponentDefinition = ReportComponent & {\n /** Optional schema field for JSON validation */\n $schema?: string;\n};\nexport type ReportComponentDefinitionFor<\n R extends import('@json-to-office/shared-docx').DocxRendererId,\n> = ReportComponentFor<R> & {\n $schema?: string;\n};\nexport type SectionComponentDefinition = SectionComponent;\nexport type HeadingComponentDefinition = HeadingComponent;\nexport type ParagraphComponentDefinition = ParagraphComponent;\nexport type ColumnsComponentDefinition = ColumnsComponent;\nexport type ImageComponentDefinition = ImageComponent;\nexport type VisualComponentDefinition = VisualComponent;\nexport type TextBoxComponentDefinition = TextBoxComponent;\nexport type StatisticComponentDefinition = StatisticComponent;\nexport type TableComponentDefinition = TableComponent;\nexport type ListComponentDefinition = ListComponent;\nexport type TocComponentDefinition = TocComponent;\n\n// Export StandardComponentDefinition as union of all standard component types\nexport type StandardComponentDefinition =\n | ReportComponent\n | SectionComponent\n | ColumnsComponent\n | HeadingComponent\n | ParagraphComponent\n | TextBoxComponent\n | ImageComponent\n | HighchartsComponent\n | VisualComponent\n | StatisticComponent\n | TableComponent\n | ListComponent\n | TocComponent;\n\n// Re-export props types for internal use\nexport type ReportProps = SharedReportProps;\nexport type SectionProps = SharedSectionProps;\nexport type HeadingProps = SharedHeadingProps;\nexport type ParagraphProps = SharedParagraphProps;\nexport type ColumnsProps = SharedColumnsProps;\nexport type ImageProps = SharedImageProps;\nexport type VisualProps = SharedVisualProps;\nexport type TextBoxProps = SharedTextBoxProps;\nexport type StatisticProps = SharedStatisticProps;\nexport type TableProps = SharedTableProps;\nexport type ListProps = SharedListProps;\nexport type TocProps = SharedTocProps;\n\n// Re-export ThemeName for easier access\nexport type { ThemeName };\n\n// ============================================================================\n// CORE-SPECIFIC INTERFACES\n// ============================================================================\n\nexport interface ColumnSettings {\n count: number;\n equalWidth?: boolean;\n space?: number;\n /** Optional explicit column children with widths/spaces in twips */\n children?: { width?: number; space?: number }[];\n}\n\nexport interface PageSizeOptions {\n width: number;\n height: number;\n}\n\nexport interface PageMarginOptions {\n top: number;\n right: number;\n bottom: number;\n left: number;\n header?: number;\n footer?: number;\n}\n\nexport interface PageNumberOptions {\n start?: number;\n formatType?:\n | 'decimal'\n | 'upperRoman'\n | 'lowerRoman'\n | 'upperLetter'\n | 'lowerLetter';\n}\n\nexport interface PageBorderOptions {\n top?: { style: string; size: number; color: string };\n right?: { style: string; size: number; color: string };\n bottom?: { style: string; size: number; color: string };\n left?: { style: string; size: number; color: string };\n}\n\nexport interface SectionProperties {\n page?: {\n size?: PageSizeOptions;\n margin?: PageMarginOptions;\n pageNumbers?: PageNumberOptions;\n borders?: PageBorderOptions;\n textDirection?: 'ltr' | 'rtl';\n };\n column?: ColumnSettings;\n type?: 'continuous' | 'nextColumn' | 'nextPage' | 'evenPage' | 'oddPage';\n /**\n * Header and footer parts, by slot.\n *\n * Content is deliberately opaque here: a section's chrome is authored as\n * components and resolved into IR blocks, and naming a renderer's part type\n * would put that renderer back into a public type.\n */\n headers?: HeaderFooterSlots;\n footers?: HeaderFooterSlots;\n}\n\nexport interface HeaderFooterSlots {\n default?: unknown;\n first?: unknown;\n even?: unknown;\n}\n\n// Internal interfaces used by DocumentGenerator helper methods\nexport interface ImageContent {\n path: string;\n caption?: string;\n width?: number;\n height?: number;\n alignment?: 'left' | 'center' | 'right';\n}\n\nexport interface StatisticContent {\n number: string;\n description: string;\n alignment?: 'left' | 'center' | 'right';\n}\n\nexport interface TableData {\n headers: string[];\n rows: (string | SharedComponentDefinition)[][];\n style?: 'minimal' | 'classic' | 'minimal';\n}\n\n/**\n * Rendering context for components\n */\nexport interface RenderContext {\n theme: {\n name: string;\n colors: Record<string, string>;\n fonts: Record<string, string>;\n spacing: Record<string, number>;\n };\n /** Full theme configuration for custom components */\n fullTheme: import('../styles').ThemeConfig;\n document: {\n title?: string;\n subtitle?: string;\n author?: string;\n company?: string;\n date: Date;\n };\n section: {\n currentLayout: 'single' | 'multi-column';\n columnCount: number;\n pageNumber: number;\n level?: number;\n /** Bookmark ID for section-scoped TOCs (when TOC is inside a section) */\n sectionBookmarkId?: string;\n };\n utils: {\n formatDate: (_date: Date) => string;\n parseText: (_text: string) => { text: string }[];\n getStyle: (_name: string) => { name: string };\n [key: string]: unknown;\n };\n parent?: SharedComponentDefinition;\n depth: number;\n custom?: Record<string, unknown>;\n services?: ServicesConfig;\n /**\n * Per-document pre-rasterized visual results, keyed by `visualRasterKey`\n * (#153). Seeded by the renderDocument pre-pass; `renderVisualComponent`\n * consults it first and falls back to per-visual rasterization on a miss.\n */\n visualRasterResults?: ReadonlyMap<string, PptxRasterizeBatchSlideResult>;\n /**\n * Per-document font faces (base64) forwarded to the pptx rasterizer with\n * every `visual`. Seeded by renderDocument from the caller's\n * `visualFonts`; consumed by `renderVisualComponent`'s per-visual\n * fallback so a pre-pass miss still rasterizes with the right fonts.\n */\n visualFonts?: readonly RasterizeFontFace[];\n /**\n * Per-document TOC entries collected before rendering (#174). Seeded by the\n * renderDocument pre-pass; `renderTocComponent` filters them by depth, scope\n * and style mapping and passes them to docx as `cachedEntries`, so a TOC\n * field has real content for readers that do not refresh fields.\n */\n tocHeadings?: readonly TocHeadingEntry[];\n}\n","/**\n * The IR-based DOCX generation path.\n *\n * Normalisation, theme resolution, font resolution, desugaring of the\n * service-backed components, structure and layout — and then, instead of\n * building renderer objects directly, it compiles to DocxIR, checks the\n * selected backend can express what the document needs, and hands the IR to an\n * adapter.\n *\n * The shape is deliberate: everything asynchronous or fallible happens before\n * compilation, so compiling is a pure function of the document plus the\n * resources already in hand. Two compilations of the same document give the\n * same IR, which is what makes the IR comparable, cacheable and snapshottable.\n */\n\nimport { assertRendererSupports } from '@json-to-office/shared/rendering';\nimport type { GenerationWarning, ServicesConfig } from '@json-to-office/shared';\nimport type { FontRuntimeOpts } from '@json-to-office/shared';\nimport { resolveDocumentFonts } from './fontResolution';\nimport { toRasterizeFontFaces } from '@json-to-office/shared/fonts/node';\nimport { collectVisualProps } from './prerasterizeVisuals';\nimport { normalizeDocument } from '../json/normalizer';\nimport { desugarExternals } from './desugarExternals';\nimport { loadImageResources } from './imageResources';\nimport { compileDocument, type UnsupportedComponent } from '../ir/compiler';\nimport type { DocxIR } from '../ir/types';\nimport { resolveDocxRenderer } from '../renderers/registry';\nimport type { DocxRendererId } from '../renderers/types';\nimport type { ThemeConfig } from '../styles';\nimport type { ReportComponentDefinition } from '../types';\nimport { resolveGenerationDate } from '../utils/packageDocument';\nimport {\n resolveThemeContext,\n type GenerationThemeContext,\n} from './generationContext';\nimport { runWithBaseDir, runWithWarnings } from '../utils/generationContext';\nimport { applyLayout } from './layout';\nimport { processDocument } from './structure';\n\nexport interface IrDocxGenerationOptions {\n customThemes?: Record<string, ThemeConfig>;\n services?: ServicesConfig;\n fonts?: FontRuntimeOpts;\n warnings?: GenerationWarning[];\n baseDir?: string;\n deterministic?: boolean;\n generatedAt?: string | Date;\n /** Backend to render with. Defaults to `docxjs`. */\n renderer?: DocxRendererId;\n /**\n * A prologue already run by the caller.\n *\n * The plugin path has to resolve the theme before it expands custom\n * components — a component's `render` is handed the resolved theme — and\n * normalises the tree that expansion produced. Passing that result in means\n * the prologue runs once rather than twice, which matters because the\n * export-mode pre-pass inside it rewrites the document.\n */\n context?: GenerationThemeContext;\n}\n\nexport interface IrDocxGenerationResult {\n buffer: Buffer;\n warnings: GenerationWarning[];\n}\n\n/**\n * Thrown when the compiler meets something it does not lower yet.\n *\n * Silently dropping it would be worse than failing: the document would look\n * complete and not be. This disappears as the compiler covers the surface.\n */\nexport class UncompiledComponentError extends Error {\n public readonly code = 'UNCOMPILED_COMPONENT';\n public readonly components: readonly UnsupportedComponent[];\n\n constructor(components: readonly UnsupportedComponent[]) {\n const names = [...new Set(components.map((c) => c.name))]\n .map((n) => `\"${n}\"`)\n .join(', ');\n super(\n `The DocxIR compiler does not lower ${names} yet, so the IR path would ` +\n `drop ${components.length} item(s):\\n` +\n components\n .map(\n (c) =>\n ` - ${c.name} at ${c.path}${c.detail ? ` (${c.detail})` : ''}`\n )\n .join('\\n')\n );\n this.name = 'UncompiledComponentError';\n this.components = [...components];\n }\n}\n\nexport interface CompiledDocx {\n ir: DocxIR;\n theme: ThemeConfig;\n warnings: GenerationWarning[];\n required: ReturnType<typeof compileDocument>['required'];\n unsupported: UnsupportedComponent[];\n}\n\n/**\n * Compile a report definition to DocxIR without rendering it.\n *\n * Scoped rather than plain: a relative image path resolves against the\n * document's own directory, and leaf utilities report warnings into the\n * caller's collector, both through async-local state that has to be entered\n * before the walk begins.\n */\nexport async function compileDocumentToIr(\n document: ReportComponentDefinition,\n options: IrDocxGenerationOptions = {},\n collector?: GenerationWarning[]\n): Promise<CompiledDocx> {\n const warnings = collector ?? options.warnings ?? [];\n return runWithWarnings(warnings, () =>\n runWithBaseDir(options.baseDir, () =>\n compileDocumentScoped(document, options, warnings)\n )\n );\n}\n\nasync function compileDocumentScoped(\n document: ReportComponentDefinition,\n options: IrDocxGenerationOptions,\n warnings: GenerationWarning[]\n): Promise<CompiledDocx> {\n // Authoring shorthand — string children, bare props, nested containers — is\n // expanded before anything reads the tree, exactly as every other caller\n // does. Skipping it would make the IR path see a different document from the\n // one the rest of the pipeline sees.\n const context =\n options.context ??\n resolveThemeContext(normalizeDocument(document)[0], {\n customThemes: options.customThemes,\n fonts: options.fonts,\n warnings,\n });\n\n // Fonts resolve for the LibreOffice preview stager's side-channel:\n // `resolveDocumentFonts` fires `fonts.onResolved` when a listener is\n // registered. The package never embeds the bytes.\n //\n // A `visual` is rasterized by an out-of-process LibreOffice that needs the\n // real font files, so a visual-bearing document forces materialisation even\n // with no listener. Gated on that check so a fontless-by-design build still\n // pays no network cost.\n const hasVisual = collectVisualProps(context.document).length > 0;\n const resolvedFonts = await resolveDocumentFonts(\n context.document,\n context.theme,\n options.fonts,\n warnings,\n hasVisual\n );\n // Gated on the ENCODED faces, not on how many fonts resolved: a safe-only\n // font resolves to an entry with no sources, which encodes to nothing, and a\n // document with only safe fonts must send no `fonts` key at all so its\n // rasterize request — and so its cache key — is unchanged.\n const visualFonts = hasVisual\n ? toRasterizeFontFaces(resolvedFonts, warnings)\n : [];\n\n // Charts and visuals become images before anything else reads the tree: they\n // are the only components that need a service, and past this point nothing\n // does.\n const desugared = await desugarExternals(context.document, {\n theme: context.theme,\n ...(options.services ? { services: options.services } : {}),\n ...(options.baseDir !== undefined ? { baseDir: options.baseDir } : {}),\n ...(visualFonts.length > 0 ? { visualFonts } : {}),\n });\n\n // One date for the whole build: the metadata Word shows, the `{DATE}` a\n // paragraph resolves and the timestamps the package is pinned to all have to\n // agree, or a document says it was made at two different moments.\n const structure = await processDocument(\n desugared,\n context.theme,\n context.themeName,\n resolveGenerationDate(options)\n );\n const layout = applyLayout(\n structure.sections,\n context.theme,\n context.themeName\n );\n // Image bytes are fetched up front so compilation itself stays synchronous\n // and pure: same document, same map, same IR.\n const images = await loadImageResources(\n layout.sections.flatMap((section) => [\n ...section.components,\n ...(Array.isArray(section.header) ? section.header : []),\n ...(Array.isArray(section.footer) ? section.footer : []),\n ])\n );\n const compiled = compileDocument(structure, layout, warnings, images, {\n // A caller that collects nothing still needs to hear about a dropped\n // value, so warnings go to the console when there is no collector.\n echoWarnings: options.warnings === undefined,\n });\n\n return {\n ir: compiled.ir,\n theme: context.theme,\n warnings: compiled.warnings,\n required: compiled.required,\n unsupported: compiled.unsupported,\n };\n}\n\n/** Generate a `.docx` buffer through DocxIR and the selected renderer. */\nexport async function generateBufferViaIr(\n document: ReportComponentDefinition,\n options: IrDocxGenerationOptions = {}\n): Promise<IrDocxGenerationResult> {\n const warnings = options.warnings ?? [];\n // The same scope covers rendering, not only compiling: an adapter reports\n // through the same leaf helpers, and a warning raised while packaging bytes\n // belongs to the caller that asked for them.\n //\n // `options` is passed through unchanged, so the compiler can still tell\n // whether the caller supplied a collector — a caller that did not still\n // needs to hear about a dropped value, on the console.\n return runWithWarnings(warnings, () =>\n runWithBaseDir(options.baseDir, () =>\n renderScoped(document, options, warnings)\n )\n );\n}\n\nasync function renderScoped(\n document: ReportComponentDefinition,\n options: IrDocxGenerationOptions,\n warnings: GenerationWarning[]\n): Promise<IrDocxGenerationResult> {\n const compiled = await compileDocumentToIr(document, options, warnings);\n\n if (compiled.unsupported.length > 0) {\n throw new UncompiledComponentError(compiled.unsupported);\n }\n\n const renderer = await resolveDocxRenderer(options.renderer);\n assertRendererSupports(compiled.required, renderer);\n\n const bytes = await renderer.render(compiled.ir, {\n ...(options.deterministic !== undefined\n ? { deterministic: options.deterministic }\n : {}),\n ...(options.generatedAt !== undefined\n ? { generatedAt: toDate(options.generatedAt) }\n : {}),\n warnings: compiled.warnings,\n });\n\n return { buffer: Buffer.from(bytes), warnings: compiled.warnings };\n}\n\nfunction toDate(value: Date | string): Date {\n return value instanceof Date ? value : new Date(value);\n}\n","/**\n * Shared font-resolution helper used by BOTH entry paths into renderDocument:\n *\n * - generator.ts → generateDocumentWithCustomThemes (non-plugin)\n * - plugin/createDocumentGenerator.ts → generate (plugin-aware)\n *\n * Keeping it in one place ensures the two paths behave identically around\n * validation, SAFE_FONTS awareness, Google Fonts materialization, and the\n * `onResolved` side-channel consumed by the LibreOffice preview font stager.\n *\n * Materialization has two triggers: an `onResolved` listener, or the\n * caller's `forceMaterialize` flag (set when the document contains a\n * `visual`, whose PNG is produced by an out-of-process LibreOffice that\n * needs real font files). Both entry paths return the resolved fonts so the\n * caller can forward them to the rasterizer.\n */\n\nimport type {\n FontRuntimeOpts,\n ResolvedFont,\n GenerationWarning,\n} from '@json-to-office/shared';\nimport {\n collectFontNamesFromDocx,\n validateFontReferences,\n FontRegistry,\n documentFontRegistry,\n themeFontRegistry,\n mergeFontRegistries,\n} from '@json-to-office/shared';\nimport {\n loadFileFontSource,\n FontDiskCache,\n fetchVariableFontSource,\n} from '@json-to-office/shared/fonts/node';\nimport type { ThemeConfig } from '../styles';\nimport type { ReportComponentDefinition } from '../types';\n\nexport async function resolveDocumentFonts(\n document: ReportComponentDefinition,\n theme: ThemeConfig,\n fonts?: FontRuntimeOpts,\n warnings?: GenerationWarning[],\n /**\n * Materialize font bytes even when no `onResolved` listener is registered.\n * Set by the callers when the document contains at least one `visual`,\n * whose PNG is rendered by an out-of-process LibreOffice that needs the\n * actual font files — there is no listener on the plain CLI path, so\n * without this a visual-bearing build silently renders with fallbacks.\n */\n forceMaterialize = false\n): Promise<ResolvedFont[]> {\n const emit = (code: string, message: string) => {\n if (warnings) {\n warnings.push({\n component: 'fontRegistry',\n message,\n severity: 'warning',\n context: { code },\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] ${code}: ${message}`);\n }\n };\n\n // Walk document + theme. The document typically names fonts only indirectly\n // via `theme: \"my-theme\"`, so fonts declared in the theme JSON would be\n // invisible without this second pass.\n const names = new Set<string>();\n for (const n of collectFontNamesFromDocx(document)) names.add(n);\n for (const n of collectFontNamesFromDocx(theme as unknown)) names.add(n);\n if (names.size === 0) return [];\n\n // Merge the declared registries with runtime overrides. Precedence:\n // theme < document < fonts.extraEntries (see registry.ts's resolution\n // rules). This MUST run before validation, not after the `onResolved`\n // short-circuit below: a document with a valid registry and no preview\n // listener would otherwise still report every registered family as\n // FONT_UNRESOLVED.\n const registryEntries = mergeFontRegistries(\n themeFontRegistry(theme),\n documentFontRegistry(document),\n fonts?.extraEntries\n );\n\n // Validate unconditionally — strict mode must fire even when no consumer\n // is listening via onResolved (CLI / library callers that just want\n // build-time validation of font references).\n const validation = validateFontReferences({\n referencedNames: names,\n registeredEntries: registryEntries,\n });\n if (validation.warnings.length > 0) {\n if (fonts?.strict) {\n throw new Error(\n `Unresolved font references (strict mode):\\n` +\n validation.warnings.map((w) => ` - ${w.message}`).join('\\n')\n );\n }\n for (const w of validation.warnings) {\n emit(w.code, w.message);\n }\n }\n\n // Registry resolution (Google/URL/file fetches) runs when a consumer is\n // listening via onResolved — typically the LibreOffice preview stager —\n // or when the caller forces materialization because the document has a\n // `visual` to rasterize. Office output never embeds bytes, so skipping\n // fetches when neither applies keeps library callers off the network.\n if (!fonts?.onResolved && !forceMaterialize) return [];\n\n const registry = new FontRegistry({\n // Spread keeps baseDir/googleFonts/mode/substitution intact for\n // materializeSource; extraEntries carries the merged registry.\n opts: { ...fonts, extraEntries: registryEntries },\n fileLoader: loadFileFontSource,\n variableLoader: fetchVariableFontSource,\n diskCache: fonts?.googleFonts?.cacheDir\n ? new FontDiskCache(fonts.googleFonts.cacheDir)\n : undefined,\n });\n const resolved = await registry.resolveMany(names);\n for (const r of resolved) {\n for (const msg of r.warnings) {\n emit('FONT_UNRESOLVED', msg);\n }\n }\n // Fire the side-channel here so callers never have to remember. On the\n // force-materialize path there may be no listener at all — the resolved\n // fonts still flow back through the return value.\n fonts?.onResolved?.(resolved);\n return resolved;\n}\n","/**\n * prerasterizeVisuals — per-document visual rasterization pre-pass (#153).\n *\n * The renderer walks components strictly in order, so each `visual` used to\n * await its own rasterization round trip: one HTTP call + one LibreOffice\n * launch per visual, ~25 of each for the bundled annual-report templates.\n * This pass runs once per document before rendering: it collects every\n * enabled visual, dedupes identical ones, and rasterizes them together —\n * through an in-process batch rasterizer, a batched HTTP call, or (failing\n * both) bounded-concurrency per-visual calls.\n *\n * Results land in a map keyed by `visualRasterKey`; `renderVisualComponent`\n * consults the map first and falls back to per-visual rasterization on any\n * miss. The pre-pass is therefore purely an accelerator: over-collection\n * wastes a little work, under-collection and every failure mode degrade to\n * the sequential status quo, never to a broken render.\n */\n\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n MAX_RASTERIZE_BATCH_SLIDES,\n type PptxServiceConfig,\n type PptxRasterizeBatchResult,\n type PptxRasterizeBatchSlideResult,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport {\n buildVisualPresentation,\n effectiveVisualServerUrl,\n rasterizeVisualSlide,\n visualRasterKey,\n DEFAULT_RASTERIZE_SERVER_URL,\n} from '../components/visual';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { createLimiter } from '../utils/promiseLimiter';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\n/** Bounded concurrency for per-visual fallback rasterizations. */\nconst DEFAULT_FALLBACK_CONCURRENCY = 4;\n/** HTTP timeout for a batch call scales with its slide count. */\nconst BATCH_TIMEOUT_BASE_MS = 30000;\nconst BATCH_TIMEOUT_PER_SLIDE_MS = 10000;\n\nexport interface PrerasterizeOptions {\n /** Directory relative asset paths resolve against (#142). */\n baseDir?: string;\n /** Max concurrent per-visual fallback rasterizations (default 4). */\n concurrency?: number;\n /**\n * Font faces staged for every slide's LibreOffice render. Request-level,\n * like `baseDir` — never per-slide: the batch schema validates each slide\n * object with `additionalProperties: false`, and a uniform slide shape is\n * what lets the server share one disk-cache key with the single path.\n */\n fonts?: readonly RasterizeFontFace[];\n}\n\n/** Cumulative pre-pass counters for visual-work observability (#156). */\nexport interface VisualPrepassStats {\n /** Documents that entered the pre-pass with at least one visual. */\n documents: number;\n /** Enabled visuals collected across those documents. */\n collected: number;\n /** Unique rasterization units after dedupe (identical content+dpi). */\n unique: number;\n}\n\nconst prepassStats: VisualPrepassStats = {\n documents: 0,\n collected: 0,\n unique: 0,\n};\n\n/**\n * Get cumulative per-document pre-pass counters. `collected - unique` is the\n * work saved by batch-internal deduplication.\n */\nexport function getVisualPrepassStats(): VisualPrepassStats {\n return { ...prepassStats };\n}\n\nexport function resetVisualPrepassStats(): void {\n prepassStats.documents = 0;\n prepassStats.collected = 0;\n prepassStats.unique = 0;\n}\n\n/** One unique rasterization unit collected from the document. */\ninterface VisualRasterTarget {\n key: string;\n presentation: Record<string, unknown>;\n dpi: number;\n}\n\n/**\n * Result of one batch attempt. `schemaRejected` distinguishes \"the server\n * refused this body\" (HTTP 400) from every other failure, so the caller can\n * tell a version-skew rejection from a blip instead of treating both alike.\n */\ntype BatchOutcome =\n | { applied: true }\n | { applied: false; schemaRejected: boolean };\n\n/**\n * Collect the props of every enabled `visual` component reachable from\n * `root`. The walk is generic — every array element and object value is\n * visited — so visuals nested anywhere (columns, table cells, section\n * headers/footers, plugin containers) are found without enumerating\n * container shapes. Disabled component subtrees are pruned: they never\n * render, so rasterizing them is wasted work. Over-collection is harmless\n * (an unused map entry); under-collection is harmless (render-time\n * fallback) — which is what makes the generic walk safe.\n */\nexport function collectVisualProps(root: unknown): VisualProps[] {\n const found: VisualProps[] = [];\n // Guards against cyclic inputs (the walk accepts arbitrary objects, not\n // just parsed JSON); registered before the array branch so\n // self-referential arrays are covered too.\n const seen = new WeakSet<object>();\n const visit = (node: unknown): void => {\n if (!node || typeof node !== 'object') return;\n if (seen.has(node)) return;\n seen.add(node);\n if (Array.isArray(node)) {\n for (const item of node) visit(item);\n return;\n }\n const obj = node as Record<string, unknown>;\n // Only component-shaped nodes carry `enabled`; a disabled subtree never\n // renders (mirrors the render-time filters).\n if (typeof obj.name === 'string' && obj.enabled === false) return;\n if (obj.name === 'visual' && obj.props && typeof obj.props === 'object') {\n found.push(obj.props as VisualProps);\n // A visual's elements are a pptx subtree; nothing docx-renderable\n // (and no further docx visuals) can nest inside it.\n return;\n }\n for (const value of Object.values(obj)) visit(value);\n };\n visit(root);\n return found;\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * COUPLING: `postJsonToService` (utils/serviceClient.ts) is the only producer\n * of the errors this inspects, and it encodes a non-2xx as\n * `\"<serviceLabel> returned <status>: <statusText>\"`. This pattern is the one\n * place that knowledge lives; if that message format changes, change it here\n * too (a transport error or timeout carries no status and matches nothing).\n */\nconst HTTP_STATUS_IN_MESSAGE = /\\breturned (\\d{3})\\b/;\n\n/**\n * Is this failure the server rejecting our request *body* (HTTP 400) rather\n * than the server being unwell? Both rasterize schemas validate with\n * `additionalProperties: false`, so a pre-fonts render server answers a\n * `fonts`-bearing body with a hard 400 — that, and only that, is evidence\n * that dropping `fonts` could help. A timeout, a connection reset or a 5xx\n * says nothing about the body: retrying without fonts cannot fix a server\n * that is down, and must never latch the fontless downgrade.\n */\nfunction isSchemaRejection(error: unknown): boolean {\n const match = HTTP_STATUS_IN_MESSAGE.exec(toErrorMessage(error));\n return match !== null && match[1] === '400';\n}\n\nfunction* chunksOf<T>(items: T[], size: number): Generator<T[]> {\n for (let i = 0; i < items.length; i += size) yield items.slice(i, i + size);\n}\n\n/**\n * Validate a batch response and seed the map. All-or-nothing per chunk: any\n * malformed entry rejects the whole chunk (returns false) so a drifted or\n * broken server can never half-seed the map — the caller falls back to\n * per-visual calls instead.\n */\nfunction applyBatchResponse(\n chunk: VisualRasterTarget[],\n response: unknown,\n map: Map<string, PptxRasterizeBatchSlideResult>\n): boolean {\n const results = (response as PptxRasterizeBatchResult | undefined)?.results;\n if (!Array.isArray(results) || results.length !== chunk.length) return false;\n\n const entries: Array<[string, PptxRasterizeBatchSlideResult]> = [];\n for (let i = 0; i < chunk.length; i++) {\n const item = results[i] as PptxRasterizeBatchSlideResult | undefined;\n if (\n item &&\n item.ok === true &&\n typeof item.base64DataUri === 'string' &&\n item.base64DataUri.length > 0 &&\n typeof item.width === 'number' &&\n typeof item.height === 'number'\n ) {\n entries.push([\n chunk[i].key,\n {\n ok: true,\n base64DataUri: item.base64DataUri,\n width: item.width,\n height: item.height,\n },\n ]);\n } else if (item && item.ok === false && typeof item.error === 'string') {\n entries.push([chunk[i].key, { ok: false, error: item.error }]);\n } else {\n return false;\n }\n }\n for (const [key, value] of entries) map.set(key, value);\n return true;\n}\n\n/**\n * Batch-rasterize a document's visuals ahead of rendering. Returns a map of\n * `visualRasterKey` → per-visual result (pixels or a recorded error). Never\n * throws for per-visual problems; a thrown error here indicates a pre-pass\n * bug and the caller should continue without the map.\n */\nexport async function prerasterizeVisuals(\n root: unknown,\n serviceConfig: PptxServiceConfig | undefined,\n options: PrerasterizeOptions = {}\n): Promise<Map<string, PptxRasterizeBatchSlideResult>> {\n const map = new Map<string, PptxRasterizeBatchSlideResult>();\n // Injected in-process rasterizers are environment-agnostic; only the HTTP\n // strategy needs Node. In a browser without callbacks the render-time path\n // reports the environment error with full context.\n if (\n !isNodeEnvironment() &&\n !serviceConfig?.renderBatch &&\n !serviceConfig?.render\n ) {\n return map;\n }\n\n const visuals = collectVisualProps(root);\n if (visuals.length === 0) return map;\n\n // Dedupe identical visuals: one rasterization per unique (content, dpi).\n const targets = new Map<string, VisualRasterTarget>();\n for (const props of visuals) {\n // The generic walk can reach visual-shaped nodes the renderer never\n // touches; a malformed one must not cost the document its batching.\n // Skipped visuals fall back to the render-time path, which reports the\n // error only if the node actually renders.\n try {\n const serverUrl = effectiveVisualServerUrl(props, serviceConfig);\n // A per-visual HTTP serverUrl override targets a different service than\n // the batch would; leave those to the per-visual render-time path.\n if (serverUrl !== undefined) continue;\n const presentation = buildVisualPresentation(props);\n const dpi = clampVisualDpi(\n props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI\n );\n const key = visualRasterKey(presentation, dpi, serverUrl);\n if (!targets.has(key)) targets.set(key, { key, presentation, dpi });\n } catch {\n continue;\n }\n }\n if (targets.size === 0) return map;\n\n prepassStats.documents++;\n prepassStats.collected += visuals.length;\n prepassStats.unique += targets.size;\n\n const unique = [...targets.values()];\n const limit = createLimiter(\n Math.max(1, options.concurrency ?? DEFAULT_FALLBACK_CONCURRENCY)\n );\n\n // Version skew guard. Both rasterize schemas validate with\n // `additionalProperties: false`, so a pre-fonts render server answers a\n // `fonts`-bearing body with a hard 400 instead of ignoring the field. Once\n // a fontless retry has proven that the field was the problem, stop sending\n // it for the rest of the document: fontless pixels beat a failed render.\n // Only a 400 latches this (see isSchemaRejection) — a blip must not\n // silently downgrade every remaining visual to fontless rendering.\n let fontsRejected = false;\n const requestFonts = (): readonly RasterizeFontFace[] | undefined =>\n fontsRejected || !options.fonts?.length ? undefined : options.fonts;\n\n /**\n * One visual through exactly the render-time code path, with the same\n * version-skew guard the batch path has: `/rasterize` is\n * `additionalProperties: false` too, so an old server 400s a fonts-bearing\n * per-visual body and, without this retry, a failed batch would take the\n * whole document down instead of degrading to fontless visuals.\n */\n const rasterizeOne = async (\n target: VisualRasterTarget\n ): Promise<PptxRasterizeBatchSlideResult> => {\n const fonts = requestFonts();\n const call = (\n withFonts: readonly RasterizeFontFace[] | undefined\n ): Promise<{ base64DataUri: string; width: number; height: number }> =>\n rasterizeVisualSlide(\n target.presentation,\n target.dpi,\n undefined,\n serviceConfig,\n options.baseDir,\n withFonts\n );\n try {\n return { ok: true, ...(await call(fonts)) };\n } catch (error) {\n if (!fonts || !isSchemaRejection(error)) {\n return { ok: false, error: toErrorMessage(error) };\n }\n try {\n const result = await call(undefined);\n // Dropping `fonts` fixed it: the server predates the field.\n fontsRejected = true;\n return { ok: true, ...result };\n } catch {\n // The fontless retry is speculative; when it fails too the fonts were\n // not the problem, so report the original failure and do not latch.\n return { ok: false, error: toErrorMessage(error) };\n }\n }\n };\n\n /** Per-visual fallback: exactly the render-time code path, bounded. */\n const rasterizeIndividually = async (\n chunk: VisualRasterTarget[]\n ): Promise<void> => {\n await Promise.all(\n chunk.map((target) =>\n limit(async () => {\n map.set(target.key, await rasterizeOne(target));\n })\n )\n );\n };\n\n // Strategy 1: in-process batch rasterizer.\n if (serviceConfig?.renderBatch) {\n for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {\n try {\n const response = await serviceConfig.renderBatch({\n slides: chunk.map((target) => ({\n presentation: target.presentation,\n dpi: target.dpi,\n })),\n ...(options.baseDir !== undefined && { baseDir: options.baseDir }),\n ...(options.fonts?.length ? { fonts: [...options.fonts] } : {}),\n });\n if (!applyBatchResponse(chunk, response, map)) {\n throw new Error(\n 'batch rasterizer returned a malformed result (expected index-aligned results[])'\n );\n }\n } catch (error) {\n // Any per-visual route keeps the document building: `render` first,\n // else the configured HTTP server (rasterizeVisualSlide handles both).\n // Only a renderBatch-with-nothing-else config records the batch-level\n // error per visual — there is genuinely nowhere to fall back to, and\n // inventing an HTTP call to the default localhost would replace the\n // real error with a misleading \"unreachable\" one.\n if (serviceConfig.render || serviceConfig.serverUrl) {\n await rasterizeIndividually(chunk);\n } else {\n const message = toErrorMessage(error);\n for (const target of chunk) {\n map.set(target.key, { ok: false, error: message });\n }\n }\n }\n }\n return map;\n }\n\n // Strategy 2: in-process single rasterizer — no batch surface, but the\n // pre-pass still parallelizes what the sequential renderer could not.\n if (serviceConfig?.render) {\n await rasterizeIndividually(unique);\n return map;\n }\n\n // Strategy 3: HTTP. Try the additive batch endpoint; ANY failure — an\n // older server without /rasterize/batch, a transport error, a malformed\n // response — falls back to per-visual calls (the status quo protocol).\n const serverUrl = resolveServiceUrl(\n undefined,\n serviceConfig?.serverUrl,\n DEFAULT_RASTERIZE_SERVER_URL\n );\n const postBatch = async (\n chunk: VisualRasterTarget[],\n fonts: readonly RasterizeFontFace[] | undefined\n ): Promise<BatchOutcome> => {\n let response: Response;\n try {\n response = await postJsonToService({\n url: serverUrl,\n path: '/rasterize/batch',\n body: {\n slides: chunk.map((target) => ({\n presentation: target.presentation,\n dpi: target.dpi,\n })),\n ...(options.baseDir !== undefined && { baseDir: options.baseDir }),\n ...(fonts?.length ? { fonts } : {}),\n },\n headers: serviceConfig?.headers,\n timeoutMs:\n BATCH_TIMEOUT_BASE_MS + BATCH_TIMEOUT_PER_SLIDE_MS * chunk.length,\n serviceLabel: 'PPTX batch rasterization service',\n onUnreachable: (url, cause) =>\n `PPTX rasterization service is not reachable at ${url}. Cause: ${cause}`,\n });\n } catch (error) {\n // A 400 means the server rejected the body we sent; anything else\n // (timeout, reset, 5xx) is the server, not the body.\n return { applied: false, schemaRejected: isSchemaRejection(error) };\n }\n try {\n if (applyBatchResponse(chunk, await response.json(), map)) {\n return { applied: true };\n }\n } catch {\n // Non-JSON body from a 2xx — malformed, not a schema rejection.\n }\n return { applied: false, schemaRejected: false };\n };\n\n for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {\n const fonts = requestFonts();\n let outcome = await postBatch(chunk, fonts);\n if (!outcome.applied && fonts && outcome.schemaRejected) {\n // A pre-fonts render server rejects the whole body with 400 rather\n // than ignoring the unknown field, and the usual batch→per-visual\n // fallback does not help because /rasterize rejects it identically.\n // Retry once without fonts; only latch `fontsRejected` when dropping\n // them actually fixed it, so a transient failure does not cost the rest\n // of the document its font fidelity. A non-400 failure skips the retry\n // entirely: dropping fonts cannot revive a server that is down.\n const retry = await postBatch(chunk, undefined);\n if (retry.applied) {\n fontsRejected = true;\n outcome = retry;\n }\n }\n if (!outcome.applied) await rasterizeIndividually(chunk);\n }\n return map;\n}\n","/**\n * The `visual` component: a free-canvas graphic authored as a single pptx\n * slide.\n *\n * Nothing here renders a document. A visual has no OOXML form of its own — an\n * injected rasterization service (`services.pptx`) draws the slide into a PNG\n * and it becomes a plain `image`, exactly as a `highcharts` becomes one. What\n * lives here is the presentation that gets sent, the identity that keys the\n * batch, and the image props the result desugars to.\n */\n\nimport { createHash } from 'crypto';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport type {\n PptxServiceConfig,\n PptxRasterizeResult,\n RasterizeFontFace,\n} from '@json-to-office/shared';\n\nexport const DEFAULT_RASTERIZE_SERVER_URL = 'http://localhost:7802';\n/** 1 inch = 96 CSS pixels — used to size the embedded image at its physical canvas size. */\nconst PIXELS_PER_INCH = 96;\n\n/**\n * Build a single-slide pptx presentation component definition from visual props.\n * The shape mirrors a normal `.pptx.json` document so the pptx engine renders\n * it unchanged. Exported for reuse by the `flattenVisuals` transform.\n */\nexport function buildVisualPresentation(\n props: VisualProps\n): Record<string, unknown> {\n const { canvas, elements } = props;\n\n const presentationProps: Record<string, unknown> = {\n slideWidth: canvas.width,\n slideHeight: canvas.height,\n };\n if (canvas.theme) presentationProps.theme = canvas.theme;\n\n const slideProps: Record<string, unknown> = {};\n if (canvas.background) slideProps.background = canvas.background;\n\n return {\n name: 'pptx',\n props: presentationProps,\n children: [\n {\n name: 'slide',\n props: slideProps,\n children: elements ?? [],\n },\n ],\n };\n}\n\n/**\n * Where an image sits on the page, and how big it is.\n *\n * The authoring surface of the `image` component a visual desugars into, so\n * this is the shape a visual's placement props have to land in.\n */\nexport interface ImageOptions {\n caption?: string;\n width?: number | string;\n height?: number | string;\n widthRelativeTo?: 'content' | 'page';\n heightRelativeTo?: 'content' | 'page';\n alignment?: 'left' | 'center' | 'right';\n spacing?: {\n before?: number; // in points\n after?: number; // in points\n };\n floating?: {\n horizontalPosition?: {\n relative?: 'character' | 'column' | 'margin' | 'page' | 'text';\n align?: 'left' | 'center' | 'right' | 'inside' | 'outside';\n offset?: number | string;\n };\n verticalPosition?: {\n relative?: 'margin' | 'page' | 'paragraph' | 'line' | 'text';\n align?: 'top' | 'center' | 'bottom' | 'inside' | 'outside';\n offset?: number | string;\n };\n wrap?: {\n // 'tight', 'around', 'through' are VML-style; only 'none', 'square', 'topAndBottom' are supported for images\n type: 'none' | 'square' | 'topAndBottom' | 'around' | 'tight' | 'through';\n side?: 'bothSides' | 'left' | 'right' | 'largest';\n margins?: {\n top?: number | string;\n bottom?: number | string;\n left?: number | string;\n right?: number | string;\n };\n };\n allowOverlap?: boolean;\n behindDocument?: boolean;\n lockAnchor?: boolean;\n layoutInCell?: boolean;\n zIndex?: number;\n rotation?: number;\n visibility?: 'hidden' | 'inherit';\n };\n // Keep paragraph with next paragraph\n keepNext?: boolean;\n // Keep all lines of paragraph together\n keepLines?: boolean;\n}\n\n/**\n * Default rendered width (px) for a visual: its physical canvas inches, so a\n * 6×4 canvas prints 6×4 unless `width` overrides.\n */\nexport function defaultVisualWidthPx(props: VisualProps): number {\n return Math.round(props.canvas.width * PIXELS_PER_INCH);\n}\n\n/**\n * Shared image-placement options derived from a visual's props. Used by BOTH\n * desugaring paths — the generation pre-pass and the offline flatten transform\n * — so the two cannot drift: width default, alignment default, caption,\n * spacing, floating and the keep flags all live here once.\n */\nexport function visualToImageOptions(props: VisualProps): ImageOptions {\n return {\n width: props.width ?? defaultVisualWidthPx(props),\n ...(props.height !== undefined && { height: props.height }),\n alignment: props.alignment ?? 'center',\n ...(props.caption !== undefined && { caption: props.caption }),\n ...(props.spacing !== undefined && { spacing: props.spacing }),\n ...(props.floating !== undefined && { floating: props.floating }),\n ...(props.keepNext !== undefined && { keepNext: props.keepNext }),\n ...(props.keepLines !== undefined && { keepLines: props.keepLines }),\n };\n}\n\n/**\n * Map visual props to the `image` props they desugar to (used by the\n * `flattenVisuals` transform to produce a portable, service-free document).\n */\nexport function visualToImageProps(\n props: VisualProps,\n base64DataUri: string\n): Record<string, unknown> {\n return {\n base64: base64DataUri,\n ...visualToImageOptions(props),\n ...(props.alt !== undefined && { alt: props.alt }),\n };\n}\n\n/**\n * Identity of one visual rasterization: content + resolution + (for HTTP\n * services) the target server. Keys the per-document pre-rasterization map\n * (#153); the pre-pass and the render-time lookup MUST use this one function\n * so the two sides cannot drift.\n *\n * FONTS ARE DELIBERATELY NOT PART OF THIS KEY. The map is built and consumed\n * inside a single `renderDocument` call, which has exactly one font set, so\n * the pre-pass and the render-time lookup can never disagree about fonts.\n * The load-bearing font key is the RASTERIZER's on-disk cache key, which is\n * process-wide and shared across documents and users — see `fontsDigest` in\n * jto-cli's pptx-rasterizer.ts.\n */\nexport function visualRasterKey(\n presentation: unknown,\n dpi: number,\n serverUrl?: string\n): string {\n return createHash('sha256')\n .update(JSON.stringify({ p: presentation, d: dpi, u: serverUrl ?? null }))\n .digest('hex');\n}\n\n/**\n * The serverUrl that actually differentiates a visual's rasterization. An\n * in-process `render` callback takes precedence over any serverUrl —\n * per-visual or config — so overrides only matter when rasterization would\n * go over HTTP. Deliberately keyed on `render` alone (NOT `renderBatch`):\n * per-visual fallbacks always go through `rasterizeVisualSlide`, which only\n * consults `render`, and pre-pass inclusion must match what a fallback would\n * actually do or the same visual could rasterize against two different\n * services depending on cache luck.\n */\nexport function effectiveVisualServerUrl(\n props: VisualProps,\n serviceConfig: PptxServiceConfig | undefined\n): string | undefined {\n if (serviceConfig?.render) return undefined;\n return props.serverUrl;\n}\n\n/**\n * Rasterize a single-slide presentation to a PNG via the configured service.\n * An in-process `render` callback takes precedence over an HTTP `serverUrl`.\n * Exported for the pre-rasterization pass, whose per-visual fallback must\n * behave exactly like render-time rasterization.\n */\nexport async function rasterizeVisualSlide(\n presentation: Record<string, unknown>,\n dpi: number,\n propsServerUrl: string | undefined,\n serviceConfig: PptxServiceConfig | undefined,\n baseDir: string | undefined,\n /**\n * Document fonts staged for the rasterizer's LibreOffice launch. Added\n * conditionally below so a fontless document's request body stays exactly\n * what it was before fonts existed.\n */\n fonts?: readonly RasterizeFontFace[]\n): Promise<PptxRasterizeResult> {\n if (!isNodeEnvironment()) {\n throw new Error(\n 'Visual rasterization requires a Node.js environment. ' +\n 'It is not available in browser environments.'\n );\n }\n\n // In-process renderer wins (ideal for tests and single-process hosts).\n if (serviceConfig?.render) {\n return serviceConfig.render({\n presentation,\n dpi,\n baseDir,\n ...(fonts?.length ? { fonts: [...fonts] } : {}),\n });\n }\n\n const serverUrl = resolveServiceUrl(\n propsServerUrl,\n serviceConfig?.serverUrl,\n DEFAULT_RASTERIZE_SERVER_URL\n );\n\n const response = await postJsonToService({\n url: serverUrl,\n path: '/rasterize',\n body: {\n presentation,\n dpi,\n ...(baseDir !== undefined && { baseDir }),\n ...(fonts?.length ? { fonts } : {}),\n },\n headers: serviceConfig?.headers,\n serviceLabel: 'PPTX rasterization service',\n onUnreachable: (url, cause) =>\n `PPTX rasterization service is not reachable at ${url}. ` +\n 'Configure services.pptx with a `render` callback or a running `serverUrl`.\\n' +\n `Cause: ${cause}`,\n });\n\n let result: PptxRasterizeResult;\n try {\n result = (await response.json()) as PptxRasterizeResult;\n } catch {\n throw new Error(\n 'PPTX rasterization service returned a non-JSON response (expected { base64DataUri, width, height }).'\n );\n }\n if (!result?.base64DataUri) {\n throw new Error(\n 'PPTX rasterization service returned a malformed response (missing base64DataUri).'\n );\n }\n return result;\n}\n","/**\n * Environment detection utilities\n */\n\n/**\n * Check if the current environment is Node.js\n * This is used to conditionally load Node.js-only modules\n */\nexport function isNodeEnvironment(): boolean {\n // Check for Node.js-specific globals\n return (\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null &&\n typeof process.versions.node === 'string'\n );\n}\n\n/**\n * Check if Node.js built-in modules are available\n * More specific check for modules that require Node.js built-ins\n */\nexport function hasNodeBuiltins(): boolean {\n try {\n // Check if we can access Node.js built-in modules\n // This will fail in browser environments\n return (\n typeof require !== 'undefined' ||\n (typeof process !== 'undefined' &&\n typeof process.versions === 'object' &&\n typeof process.versions.node === 'string')\n );\n } catch {\n return false;\n }\n}\n","/**\n * Shared client for \"service-rendered image\" components (highcharts, visual).\n *\n * Both offload rendering to an injected HTTP service: resolve a base URL, POST a\n * JSON body with optional dynamic headers, and normalize transport errors — now\n * with a request timeout so a wedged service can't hang the render forever.\n * Callers decode the response body themselves (highcharts returns base64 text,\n * visual returns JSON), so this returns the raw Response on success.\n */\n\nexport type ServiceHeaders =\n | Record<string, string>\n | ((\n body: unknown\n ) => Record<string, string> | Promise<Record<string, string>>);\n\nconst DEFAULT_TIMEOUT_MS = 30000;\n\n/**\n * Resolve a service base URL: per-call override → services config → default.\n * Adds an `http://` scheme to a bare host and strips trailing slashes so callers\n * can append `${url}/path` without producing a `//path` that breaks routers.\n */\nexport function resolveServiceUrl(\n propsUrl: string | undefined,\n servicesUrl: string | undefined,\n defaultUrl: string\n): string {\n const raw = (propsUrl || servicesUrl || defaultUrl).trim();\n const withScheme = /^https?:\\/\\//i.test(raw) ? raw : `http://${raw}`;\n return withScheme.replace(/\\/+$/, '');\n}\n\nexport interface PostJsonOptions {\n /** Resolved base URL (use resolveServiceUrl). */\n url: string;\n /** Path appended to the base URL, e.g. '/export' or '/rasterize'. */\n path: string;\n /** Request body (JSON-serialized). */\n body: unknown;\n /** Static headers or an async resolver receiving the body. */\n headers?: ServiceHeaders;\n /** Abort timeout in ms (default 30s). */\n timeoutMs?: number;\n /** Label used in the timeout message and the non-2xx error. */\n serviceLabel: string;\n /** Message builder for a connection failure (distinct from a timeout). */\n onUnreachable: (url: string, cause: string) => string;\n}\n\n/**\n * POST a JSON body to `${url}${path}` with a timeout. Returns the Response on a\n * 2xx; throws a normalized Error on timeout, connection failure, or non-2xx.\n */\nexport async function postJsonToService(\n opts: PostJsonOptions\n): Promise<Response> {\n const resolvedHeaders =\n typeof opts.headers === 'function'\n ? await opts.headers(opts.body)\n : opts.headers;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...resolvedHeaders,\n };\n\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(`${opts.url}${opts.path}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(opts.body),\n signal: controller.signal,\n });\n } catch (error) {\n if ((error as Error)?.name === 'AbortError') {\n throw new Error(\n `${opts.serviceLabel} timed out after ${timeoutMs}ms at ${opts.url}.`\n );\n }\n const cause = error instanceof Error ? error.message : String(error);\n throw new Error(opts.onUnreachable(opts.url, cause));\n } finally {\n clearTimeout(timer);\n }\n\n if (!response.ok) {\n throw new Error(\n `${opts.serviceLabel} returned ${response.status}: ${response.statusText}`\n );\n }\n return response;\n}\n","/**\n * Minimal promise pool bounding concurrent async operations. Shared by the\n * visual rasterization paths (flattenVisuals, prerasterizeVisuals) to cap\n * concurrent service calls.\n */\nexport function createLimiter(\n max: number\n): <T>(fn: () => Promise<T>) => Promise<T> {\n let active = 0;\n const queue: Array<() => void> = [];\n const release = () => {\n active--;\n queue.shift()?.();\n };\n return async function limit<T>(fn: () => Promise<T>): Promise<T> {\n // Re-check after waking: a caller arriving between release() and this\n // waiter's microtask could otherwise barge past the limit.\n while (active >= max)\n await new Promise<void>((resolve) => queue.push(resolve));\n active++;\n try {\n return await fn();\n } finally {\n release();\n }\n };\n}\n","/**\n * Component Normalizer - Transforms JSON components where business logic requires it\n *\n * This module ONLY handles transformations that are actually necessary:\n * 1. Columns shorthand notation (columns: 3 → array format)\n * 2. Recursive processing of nested components\n * 3. Gap application for columns\n *\n * All other properties are preserved as-is from TypeBox validation.\n * This prevents information loss and maintains single source of truth.\n */\n\nimport {\n ComponentDefinition,\n ReportComponentDefinition,\n SectionComponentDefinition,\n ColumnsComponentDefinition,\n ColumnsProps,\n} from '../types';\n\n/**\n * Normalize a component definition and its nested children\n * Preserves all validated properties - only transforms where business logic requires\n */\nexport function normalizeComponent(\n component: ComponentDefinition\n): ComponentDefinition {\n // Handle columns component with shorthand notation\n if (component.name === 'columns') {\n return normalizeColumnsComponent(component as ColumnsComponentDefinition);\n }\n\n // Handle components with children - recursively normalize\n if ('children' in component && component.children) {\n return {\n ...component, // Preserve ALL properties from validated component\n children: component.children.map(normalizeComponent),\n } as ComponentDefinition;\n }\n\n // Handle section component with header/footer arrays\n if (component.name === 'section') {\n return normalizeSectionComponent(component as SectionComponentDefinition);\n }\n\n // All other components: return as-is (already validated by TypeBox)\n return component;\n}\n\n/**\n * Normalize columns component\n * Converts shorthand notation and applies gap logic\n */\nfunction normalizeColumnsComponent(\n component: ColumnsComponentDefinition\n): ColumnsComponentDefinition {\n const cfg = component.props || ({} as any);\n\n // Helper: apply top-level gap to all columns except last where not overridden\n const applyTopLevelGap = (\n cols: Array<{ width?: unknown; gap?: unknown }>,\n topGap: unknown\n ) =>\n cols.map((c, i) => {\n const isLast = i === cols.length - 1;\n if (!isLast && c.gap === undefined && topGap !== undefined) {\n return { ...c, gap: topGap };\n }\n return c;\n });\n\n // Helper: normalize 'auto' to unspecified width (internal layout splits remainder)\n const normalizeAutoWidth = (\n cols: Array<{ width?: unknown; gap?: unknown }>\n ) =>\n cols.map((c) => ({\n ...c,\n width: c.width === 'auto' ? undefined : c.width,\n }));\n\n let columnsArray: Array<{ width?: unknown; gap?: unknown }>;\n\n if (typeof cfg.columns === 'number' && cfg.columns > 0) {\n // Shorthand: N equal-width columns; apply gap after each except last\n const n = cfg.columns as number;\n const base = Array.from(\n { length: n },\n () => ({}) as { width?: unknown; gap?: unknown }\n );\n const topLevelGap = cfg.gap !== undefined ? cfg.gap : '5%';\n columnsArray = applyTopLevelGap(base, topLevelGap);\n } else if (Array.isArray(cfg.columns)) {\n // Array form; honor per-column config\n columnsArray = cfg.columns as Array<{ width?: unknown; gap?: unknown }>;\n // Apply top-level gap unless column overrides; skip last column\n const topLevelGap = cfg.gap !== undefined ? cfg.gap : '5%';\n columnsArray = applyTopLevelGap(columnsArray, topLevelGap);\n // Normalize 'auto' widths to unspecified so layout can allocate remainder\n columnsArray = normalizeAutoWidth(columnsArray);\n } else {\n // Minimal valid shape\n columnsArray = [{}];\n }\n\n const normalizedProps: ColumnsProps = {\n columns: columnsArray,\n } as ColumnsProps;\n\n return {\n ...component, // Preserve any additional properties\n name: 'columns',\n props: normalizedProps,\n children: component.children\n ? component.children.map(normalizeComponent)\n : undefined,\n };\n}\n\n/**\n * Normalize section component\n * Handles recursive processing of header/footer component arrays\n */\nfunction normalizeSectionComponent(\n component: SectionComponentDefinition\n): SectionComponentDefinition {\n const props = component.props || ({} as any);\n\n return {\n ...component, // Preserve ALL properties\n props: {\n ...props, // Preserve ALL props properties\n header: props.header\n ? props.header === 'linkToPrevious'\n ? 'linkToPrevious'\n : props.header.map((m: ComponentDefinition) => normalizeComponent(m))\n : undefined,\n footer: props.footer\n ? props.footer === 'linkToPrevious'\n ? 'linkToPrevious'\n : props.footer.map((m: ComponentDefinition) => normalizeComponent(m))\n : undefined,\n },\n children: component.children\n ? component.children.map(normalizeComponent)\n : undefined,\n };\n}\n\n/**\n * Normalize entire document (top-level report component)\n * Returns as single-element tuple for backward compatibility\n */\nexport function normalizeDocument(\n document: ComponentDefinition | ReportComponentDefinition\n): [ReportComponentDefinition] {\n // Validate it's a report component\n if (document.name !== 'docx') {\n throw new Error(\n 'Top-level document must be a docx component with name=\"docx\"'\n );\n }\n\n const normalized = normalizeComponent(document) as ReportComponentDefinition;\n return [normalized];\n}\n\n/**\n * Validate component structure (container vs content components)\n */\nexport function validateComponentStructure(component: any): {\n valid: boolean;\n errors: string[];\n} {\n const errors: string[] = [];\n\n // Components that can have children\n const containerComponents = ['docx', 'section', 'columns', 'text-box'];\n\n // Check if content components have children (they shouldn't)\n if (\n !containerComponents.includes(component.name) &&\n component.children &&\n component.children.length > 0\n ) {\n errors.push(\n `Component name \"${component.name}\" cannot have child components`\n );\n }\n\n // Recursively validate child components\n if (component.children) {\n component.children.forEach(\n (childComponent: ComponentDefinition, index: number) => {\n const childResult = validateComponentStructure(childComponent);\n if (!childResult.valid) {\n errors.push(\n ...childResult.errors.map(\n (error) => `Component[${index}]: ${error}`\n )\n );\n }\n }\n );\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","/**\n * Turn components that need an external service into plain `image` components,\n * before anything else looks at the document.\n *\n * A `visual` is a nested presentation rendered by LibreOffice; a `highcharts`\n * is a chart rendered by an export server. Both end up as a PNG in the package,\n * and neither has an OOXML form of its own — so rather than teaching the\n * compiler about services, they are desugared here and the compiler only ever\n * sees an image.\n *\n * That keeps compilation a pure function of the document. Everything that can\n * fail, block on a network call or depend on a machine's LibreOffice happens in\n * this pass; what comes out is a document that builds anywhere.\n */\n\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n type RasterizeFontFace,\n type ServicesConfig,\n} from '@json-to-office/shared';\nimport type { VisualProps, HighchartsProps } from '@json-to-office/shared-docx';\nimport type { ThemeConfig } from '../styles';\nimport {\n buildVisualPresentation,\n effectiveVisualServerUrl,\n rasterizeVisualSlide,\n visualRasterKey,\n visualToImageProps,\n} from '../components/visual';\nimport { renderChartToImageProps } from '../components/highcharts';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\nimport { transformComponents, withNodeIdentity } from './componentTransform';\n\nexport interface DesugarExternalsOptions {\n theme: ThemeConfig;\n services?: ServicesConfig;\n /** Directory relative asset paths inside a visual resolve against. */\n baseDir?: string;\n /** Font faces staged for each visual's LibreOffice render. */\n visualFonts?: readonly RasterizeFontFace[];\n}\n\n/**\n * Replace every `visual` and `highcharts` in `document` with its image.\n *\n * Visuals are rasterized in one batch first: the document walk is sequential,\n * and without the batch each visual would cost its own service round trip and\n * its own LibreOffice launch — about twenty-five of each for the bundled\n * templates. The batch is only an accelerator, though: anything it misses, or a\n * batch that fails outright, falls back to rasterizing that visual on its own.\n */\nexport async function desugarExternals<T>(\n document: T,\n options: DesugarExternalsOptions\n): Promise<T> {\n const prerastered = await prerasterizeVisuals(\n document,\n options.services?.pptx,\n {\n ...(options.baseDir !== undefined ? { baseDir: options.baseDir } : {}),\n ...(options.visualFonts ? { fonts: options.visualFonts } : {}),\n }\n ).catch(() => new Map<string, never>());\n\n return transformComponents(document, async (node) => {\n // A disabled component is filtered out before it renders, so paying a\n // service call for it would be wasted work.\n if (node.enabled === false) return undefined;\n\n if (node.name === 'visual') {\n return withNodeIdentity(node, {\n name: 'image',\n props: await visualImageProps(\n node.props as VisualProps,\n prerastered,\n options\n ),\n });\n }\n\n if (node.name === 'highcharts') {\n return withNodeIdentity(node, {\n name: 'image',\n props: await renderChartToImageProps(\n node.props as HighchartsProps,\n options.theme,\n options.services?.highcharts\n ),\n });\n }\n\n return undefined;\n });\n}\n\nasync function visualImageProps(\n props: VisualProps,\n prerastered: ReadonlyMap<string, { ok: boolean }>,\n options: DesugarExternalsOptions\n): Promise<Record<string, unknown>> {\n const serviceConfig = options.services?.pptx;\n const presentation = buildVisualPresentation(props);\n const dpi = clampVisualDpi(\n props.dpi ?? serviceConfig?.dpi ?? DEFAULT_VISUAL_DPI\n );\n\n // A hit uses the batch's pixels. A recorded per-visual failure surfaces here,\n // where the error is attributable to this component rather than to the batch.\n const hit = prerastered.get(\n visualRasterKey(\n presentation,\n dpi,\n effectiveVisualServerUrl(props, serviceConfig)\n )\n ) as\n | { ok: true; base64DataUri: string }\n | { ok: false; error: string }\n | undefined;\n\n if (hit) {\n if (!hit.ok) throw new Error(hit.error);\n return visualToImageProps(props, hit.base64DataUri);\n }\n\n // Relative asset paths inside the nested presentation must resolve against\n // the document's own directory: the rasterizer runs in another process, with\n // another working directory.\n const result = await rasterizeVisualSlide(\n presentation,\n dpi,\n props.serverUrl,\n serviceConfig,\n options.baseDir,\n options.visualFonts\n );\n return visualToImageProps(props, result.base64DataUri);\n}\n","/**\n * The `highcharts` component: a chart drawn by an export server.\n *\n * Nothing here renders a document. A chart has no OOXML form of its own — it\n * becomes a PNG and then an `image` — so what lives here is the request the\n * export server needs, the theme palette that goes into it, and the image props\n * the result desugars to.\n */\n\nimport { ThemeConfig } from '../styles';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport { isNodeEnvironment } from '../utils/environment';\nimport { resolveServiceUrl, postJsonToService } from '../utils/serviceClient';\n\n// Import only the types we actually use from shared package\nimport type { HighchartsProps } from '@json-to-office/shared-docx';\nimport type { HighchartsServiceConfig } from '@json-to-office/shared';\nimport { DEFAULT_CHART_THEME_COLORS } from '@json-to-office/shared';\n\n// Re-export HighchartsProps for backward compatibility\nexport type { HighchartsProps } from '@json-to-office/shared-docx';\n\n/**\n * Chart generation result\n */\nexport interface ChartGenerationResult {\n base64DataUri: string;\n width: number;\n height: number;\n}\n\nconst DEFAULT_EXPORT_SERVER_URL = 'http://localhost:7801';\n\n/**\n * Generate chart using Highcharts Export Server\n */\nasync function generateChart(\n config: HighchartsProps,\n servicesConfig?: HighchartsServiceConfig\n): Promise<ChartGenerationResult> {\n // Only run in Node.js environments\n if (!isNodeEnvironment()) {\n throw new Error(\n 'Highcharts export server requires a Node.js environment. ' +\n 'Chart generation is not available in browser environments.'\n );\n }\n\n const serverUrl = resolveServiceUrl(\n config.serverUrl,\n servicesConfig?.serverUrl,\n DEFAULT_EXPORT_SERVER_URL\n );\n\n const requestBody: Record<string, unknown> = {\n infile: config.options,\n type: 'png',\n b64: true,\n scale: config.scale,\n // Forward resources verbatim only when present so the payload stays\n // byte-identical to before for callers that omit it.\n ...(config.resources ? { resources: config.resources } : {}),\n };\n\n const response = await postJsonToService({\n url: serverUrl,\n path: '/export',\n body: requestBody,\n headers: servicesConfig?.headers,\n serviceLabel: 'Highcharts export server',\n onUnreachable: (url, cause) =>\n `Highcharts Export Server is not running at ${url}. ` +\n 'Start it with: npx highcharts-export-server --enableServer true\\n' +\n `Cause: ${cause}`,\n });\n\n const base64Data = await response.text();\n const base64DataUri = `data:image/png;base64,${base64Data}`;\n const width = config.options.chart.width;\n const height = config.options.chart.height;\n\n return {\n base64DataUri,\n width,\n height,\n };\n}\n\n/**\n * Turn one theme color value into a `#RRGGBB` string, or undefined when it\n * cannot be resolved. The theme schema lets a color be another token's name\n * (`\"accent4\": \"primary\"`), so a bare `#` prefix would post \"#primary\" to the\n * export server; `resolveColor` walks the reference chain and throws on\n * anything unresolvable, which we treat as an unset slot.\n */\nfunction toChartColor(value: string, theme: ThemeConfig): string | undefined {\n // Literal hex passes through untouched — resolveColor would upper-case it,\n // and it rejects the bare (no '#') form the schema still accepts.\n if (/^#?[0-9A-Fa-f]{6}$/.test(value)) {\n return value.startsWith('#') ? value : `#${value}`;\n }\n try {\n return `#${resolveColor(value, theme)}`;\n } catch {\n return undefined;\n }\n}\n\n/**\n * When the Highcharts config sets no top-level `colors`, series render in the\n * Highcharts default palette (blue-first) and ignore the document theme. Inject\n * the theme's chart palette — the same token list PPTX charts resolve — as\n * series colors so charts follow the theme by default. accent4-6 are optional\n * in the theme schema; slots the theme leaves unset are skipped, in both\n * formats, so the palette never carries gaps or repeats and Highcharts wraps\n * the shorter list (see DEFAULT_CHART_THEME_COLORS). Explicit `colors` always\n * wins.\n */\nfunction withThemeColors(\n config: HighchartsProps,\n theme: ThemeConfig\n): HighchartsProps {\n const options = config.options as Record<string, unknown> | undefined;\n if (!options || options.colors || !theme?.colors) return config;\n const themeColors = theme.colors as Record<string, string | undefined>;\n const palette = DEFAULT_CHART_THEME_COLORS.map((token) => {\n const value = themeColors[token];\n return typeof value === 'string' && value.length > 0\n ? toChartColor(value, theme)\n : undefined;\n }).filter((c): c is string => c !== undefined);\n if (palette.length === 0) return config;\n return {\n ...config,\n options: { ...config.options, colors: palette },\n };\n}\n\n/**\n * Map a chart's props to the `image` props it desugars to.\n *\n * Shared by the render-time component and the DocxIR desugaring pass so the two\n * cannot drift on the one decision that is not obvious: an explicit `width` or\n * `height` on the component replaces the chart's own canvas size outright,\n * rather than merging with it — stating one and inheriting the other would\n * distort the chart.\n */\nexport async function renderChartToImageProps(\n props: HighchartsProps,\n theme: ThemeConfig,\n servicesConfig?: HighchartsServiceConfig\n): Promise<Record<string, unknown>> {\n const config = withThemeColors(props, theme);\n const chart = await generateChart(config, servicesConfig);\n\n const hasConfigDimensions =\n config.width !== undefined || config.height !== undefined;\n\n return {\n base64: chart.base64DataUri,\n width: hasConfigDimensions ? config.width : chart.width,\n height: hasConfigDimensions ? config.height : chart.height,\n alignment: 'center',\n };\n}\n","/**\n * Walk a document tree and replace components.\n *\n * The docx model holds child components in more places than `children`: a\n * section's `header` and `footer`, and a table's `columns[].header.content` and\n * `columns[].cells[].content`. Any transform that misses one of those quietly\n * leaves part of the document behind, which is exactly the kind of bug that\n * only shows up in the one template that puts a chart in a table cell.\n *\n * So the walk lives here, once, and transforms supply only the decision about\n * what to replace.\n */\n\n/**\n * Decide what one component becomes.\n *\n * Return a replacement node to substitute it — the walk does not descend into\n * a replacement — or `undefined` to leave the node alone and keep walking.\n */\nexport type ComponentReplacer = (\n node: Record<string, unknown>\n) => Promise<Record<string, unknown> | undefined>;\n\n/** Return a deep copy of `doc` with `replace` applied to every component. */\nexport async function transformComponents<T>(\n doc: T,\n replace: ComponentReplacer\n): Promise<T> {\n return (await walk(doc, replace)) as T;\n}\n\nasync function walk(\n node: unknown,\n replace: ComponentReplacer\n): Promise<unknown> {\n if (Array.isArray(node)) {\n return Promise.all(node.map((child) => walk(child, replace)));\n }\n if (!node || typeof node !== 'object') return node;\n\n const obj = node as Record<string, unknown>;\n if (typeof obj.name === 'string' && obj.props) {\n const replacement = await replace(obj);\n if (replacement) return replacement;\n }\n\n const next: Record<string, unknown> = { ...obj };\n\n if (Array.isArray(obj.children)) {\n next.children = await walk(obj.children, replace);\n }\n\n if (obj.props && typeof obj.props === 'object') {\n const props = obj.props as Record<string, unknown>;\n let changed = false;\n const nextProps: Record<string, unknown> = { ...props };\n\n // Section header/footer: arrays of component definitions, or the literal\n // `'linkToPrevious'`, which the walk returns unchanged.\n for (const key of ['header', 'footer'] as const) {\n if (Array.isArray(props[key])) {\n nextProps[key] = await walk(props[key], replace);\n changed = true;\n }\n }\n\n // Table columns: a cell's `content` and the column header's `content` each\n // hold a component definition (or a string).\n if (Array.isArray(props.columns)) {\n nextProps.columns = await Promise.all(\n (props.columns as unknown[]).map((column) =>\n walkColumn(column, replace)\n )\n );\n changed = true;\n }\n\n if (changed) next.props = nextProps;\n }\n\n return next;\n}\n\nasync function walkColumn(\n column: unknown,\n replace: ComponentReplacer\n): Promise<unknown> {\n if (!column || typeof column !== 'object') return column;\n const source = column as Record<string, unknown>;\n const next: Record<string, unknown> = { ...source };\n\n const header = source.header as Record<string, unknown> | undefined;\n if (header && typeof header === 'object' && 'content' in header) {\n next.header = { ...header, content: await walk(header.content, replace) };\n }\n\n if (Array.isArray(source.cells)) {\n next.cells = await Promise.all(\n (source.cells as unknown[]).map(async (cell) => {\n if (cell && typeof cell === 'object' && 'content' in cell) {\n const source = cell as Record<string, unknown>;\n return { ...source, content: await walk(source.content, replace) };\n }\n return cell;\n })\n );\n }\n\n return next;\n}\n\n/**\n * Carry a node's identity and visibility onto its replacement.\n *\n * A desugared node is still the component the author wrote: an `id` other\n * things link to, and an `enabled` flag something downstream may act on, both\n * have to survive the substitution.\n */\nexport function withNodeIdentity(\n original: Record<string, unknown>,\n replacement: Record<string, unknown>\n): Record<string, unknown> {\n const out = { ...replacement };\n if (original.id !== undefined) out.id = original.id;\n if (original.enabled !== undefined) out.enabled = original.enabled;\n return out;\n}\n","/**\n * Load every image a document references, before anything is compiled.\n *\n * A DOCX embeds images by value, so the bytes have to be in hand to build one —\n * and fetching them is asynchronous, while compiling to IR is not. Keeping the\n * compiler synchronous is worth a pre-pass: it makes compilation a pure\n * function of the document plus this map, which is what lets the IR be compared,\n * cached and snapshotted.\n *\n * Sources are deduplicated, so the same image used ten times is fetched once\n * and embedded once.\n */\n\nimport type { ComponentDefinition } from '../types';\nimport {\n getImageBuffer,\n readImageDimensions,\n resolveImageSource,\n} from '../utils/imageUtils';\n\nexport interface LoadedImage {\n bytes: Buffer;\n /** From the HTTP response, when the source was fetched over the network. */\n contentType?: string;\n /** Pixel size as stored, when it could be read. */\n intrinsic?: { width: number; height: number };\n}\n\n/**\n * Images by source string.\n *\n * A source that could not be loaded is absent rather than recorded as an\n * error: the compiler reports it against the component's own path, which is\n * more use than an error attached to a URL.\n */\nexport type ImageResources = ReadonlyMap<string, LoadedImage>;\n\n/** Load every image source in `components`, following nested content. */\nexport async function loadImageResources(\n components: Iterable<ComponentDefinition | undefined>\n): Promise<ImageResources> {\n const sources = new Set<string>();\n for (const component of components) collectSources(component, sources);\n\n const loaded = new Map<string, LoadedImage>();\n await Promise.all(\n [...sources].map(async (source) => {\n try {\n const result = await getImageBuffer(source);\n // Probed from the bytes just loaded, never by loading the source a\n // second time: a URL fetched twice is twice the traffic, and a URL\n // whose response changes would embed one image and size it from\n // another (#267).\n const intrinsic = readIntrinsic(result.buffer, source);\n loaded.set(source, {\n bytes: result.buffer,\n ...(result.contentType ? { contentType: result.contentType } : {}),\n ...(intrinsic ? { intrinsic } : {}),\n });\n } catch {\n // Left out of the map; the compiler reports it against the component.\n }\n })\n );\n return loaded;\n}\n\nfunction readIntrinsic(\n bytes: Buffer,\n source: string\n): { width: number; height: number } | undefined {\n try {\n return readImageDimensions(bytes, source);\n } catch {\n // An unreadable header is not a failure to load: the image still embeds,\n // it just cannot contribute an aspect ratio.\n return undefined;\n }\n}\n\n/**\n * Every image source under one component.\n *\n * Images hide in more places than the component tree suggests — inside table\n * cells, inside header and footer content — so this walks the shapes that can\n * hold one rather than only a component's `children`.\n */\nfunction collectSources(\n component: ComponentDefinition | undefined,\n out: Set<string>\n): void {\n if (!component || typeof component !== 'object') return;\n\n if (component.name === 'image') {\n const source = resolveImageSource(\n (component.props ?? {}) as {\n svg?: string;\n base64?: string;\n path?: string;\n }\n );\n if (source) out.add(source);\n }\n\n const children = (component as { children?: ComponentDefinition[] }).children;\n for (const child of children ?? []) collectSources(child, out);\n\n const props = (component.props ?? {}) as Record<string, unknown>;\n for (const key of ['header', 'footer'] as const) {\n const part = props[key];\n if (Array.isArray(part)) {\n for (const child of part)\n collectSources(child as ComponentDefinition, out);\n }\n }\n\n const columns = props.columns;\n if (Array.isArray(columns)) {\n for (const column of columns as Record<string, unknown>[]) {\n const header = column?.header as { content?: unknown } | undefined;\n collectCellSource(header?.content, out);\n const cells = column?.cells;\n if (Array.isArray(cells)) {\n for (const cell of cells as { content?: unknown }[]) {\n collectCellSource(cell?.content, out);\n }\n }\n }\n }\n}\n\nfunction collectCellSource(content: unknown, out: Set<string>): void {\n if (content && typeof content === 'object') {\n collectSources(content as ComponentDefinition, out);\n }\n}\n","/**\n * Compile a processed document into DocxIR.\n *\n * The input is the authoring tree after schema validation, custom-component\n * expansion, theme resolution and component defaults (`ProcessedDocument`),\n * paired with the section and column plan (`LayoutPlan`). What remains, and\n * what this module does, is the last mile: the inline mini-language becomes\n * inline nodes, points become twips and half-points, theme colour tokens become\n * hex, and a font weight becomes the family alias it resolves to.\n *\n * No renderer is imported here, and none may be. The output is plain data.\n *\n * Scope: this is the first vertical slice — document metadata and settings,\n * sections and page setup, headers and footers, paragraphs and headings with\n * their runs, bookmarks, inline images and simple tables. Anything outside it\n * is reported through `unsupported`, so a caller can tell \"not yet compiled\"\n * from \"compiled to nothing\", and the default pipeline stays on the pre-IR path\n * until the gap closes.\n */\n\nimport {\n FeatureRequirementCollector,\n type FeatureRequirement,\n} from '@json-to-office/shared/rendering';\nimport type { GenerationWarning } from '@json-to-office/shared';\nimport { synthesizeFamilyName } from '@json-to-office/shared';\nimport type { LayoutPlan, SectionLayout } from '../core/layout';\nimport type { ProcessedDocument } from '../core/structure';\nimport type { ComponentDefinition } from '../types';\nimport type { ThemeConfig } from '../styles';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport { createDocumentStyles } from '../styles/themeToStyles';\nimport { resolveFontFamily } from '../styles/utils/styleHelpers';\nimport { getNormalStyle, getThemeFonts } from '../themes/defaults';\nimport { computeSectionOrdinals } from '../core/sectionOrdinals';\nimport {\n dedupeBookmarkId,\n slugifyBookmarkText,\n} from '../utils/bookmarkRegistry';\nimport { resolveListLevels, type ListLevelSource } from '../utils/listLevels';\nimport {\n resolveTableModel,\n type ResolvedBorder,\n type ResolvedCell,\n type ResolvedRow,\n type ResolvedTable,\n type TableSource,\n} from '../core/tableModel';\nimport { getPageSetup, getTableStyle } from '../styles/utils/layoutUtils';\nimport {\n DEFAULT_REVISION_AUTHOR,\n DEFAULT_REVISION_DATE,\n} from '../utils/revisionUtils';\nimport {\n DEFAULT_COMMENT_AUTHOR,\n DEFAULT_COMMENT_DATE,\n} from '../utils/commentRegistry';\nimport type { ImageResources, LoadedImage } from '../core/imageResources';\nimport {\n calculateMissingDimension,\n detectImageType,\n parseDimensionValue,\n parseWidthValue,\n resolveImageSource,\n} from '../utils/imageUtils';\nimport {\n getAvailableHeightTwips,\n getAvailableWidthTwips,\n getPageHeightTwips,\n getPageWidthTwips,\n relativeLengthToTwips,\n resolveOffsetTwips,\n} from '../utils/widthUtils';\nimport {\n HEADING_NUMBERING_REFERENCE,\n type ListLevelConfig,\n type ListMarkerFontConfig,\n} from '../utils/numberingConfig';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport {\n collectDocumentOutline,\n type NumberedItemInfo,\n type TocHeadingEntry,\n} from '../core/collectTocHeadings';\nimport { resolveTocField } from '../core/tocField';\nimport { parseMarkdownList } from '../core/markdownList';\nimport {\n containsCrossReference,\n containsLink,\n containsPlaceholder,\n containsUnsupportedSyntax,\n parseInline,\n parseLiteral,\n type CrossReferenceFormat,\n type PlaceholderResolution,\n} from './inline';\nimport type { DocxFeature } from './features';\nimport {\n DOCX_IR_SCHEMA_VERSION,\n type DocxIR,\n type DocxIrAlignment,\n type DocxIrBlock,\n type DocxIrBorder,\n type DocxIrBorders,\n type DocxIrColor,\n type DocxIrComment,\n type DocxIrNote,\n type DocxIrFloating,\n type DocxIrFloatingPosition,\n type DocxIrFrame,\n type DocxIrHeaderFooter,\n type DocxIrImageRun,\n type DocxIrInline,\n type DocxIrNumbering,\n type DocxIrNumberingLevel,\n type DocxIrParagraph,\n type DocxIrParagraphFormatting,\n type DocxIrParagraphMarkRevision,\n type DocxIrResource,\n type DocxIrRunFormatting,\n type DocxIrSection,\n type DocxIrSectionProperties,\n type DocxIrSpacing,\n type DocxIrTableCell,\n type DocxIrTableFloating,\n type DocxIrTableWidth,\n type DocxIrTableRow,\n type DocxIrTextWrap,\n type DocxIrVerticalAlign,\n} from './types';\nimport {\n blockId,\n headerFooterBlockId,\n inchesToTwips,\n irColor,\n pixelsToEmu,\n pointsToEighthPoints,\n pointsToHalfPoints,\n pointsToTwips,\n sha256Hex,\n twipsToEmu,\n twipsToPixels,\n} from './units';\n\n/** A component the compiler does not yet lower into IR. */\nexport interface UnsupportedComponent {\n name: string;\n path: string;\n /** What about it is not handled, when the component itself is. */\n detail?: string;\n}\n\nexport interface DocxCompileResult {\n ir: DocxIR;\n /** Backend capabilities the IR needs, with the IR path that needs them. */\n required: readonly FeatureRequirement<DocxFeature>[];\n warnings: GenerationWarning[];\n /**\n * What the compiler could not lower. Empty once the migration is complete;\n * until then this is what keeps the pre-IR path authoritative instead of\n * silently dropping content.\n */\n unsupported: UnsupportedComponent[];\n}\n\n/**\n * Content bookmarks number from here up.\n *\n * `w:id` pairs a `bookmarkStart` with its `bookmarkEnd`, so it has to be unique\n * across the whole document. Section bookmarks take two lower ranges — layout\n * ordinals from 1, nested sections from 1_000_000 (see `sectionBookmarks.ts`) —\n * and this is the third disjoint one.\n */\nconst CONTENT_BOOKMARK_ID_BASE = 2_000_000;\n\n/** One line of single spacing, in twips — the unit `w:line` counts in. */\nconst SINGLE_LINE_TWIPS = 240;\n\n/** Shared mutable state for one compilation. Never module-global. */\ninterface CompileContext {\n theme: ThemeConfig;\n themeName: string;\n warnings: GenerationWarning[];\n features: FeatureRequirementCollector<DocxFeature>;\n unsupported: UnsupportedComponent[];\n resources: DocxIrResource[];\n resourcesByHash: Map<string, string>;\n /** Content bookmark ids, allocated in document order from {@link CONTENT_BOOKMARK_ID_BASE}. */\n nextBookmarkId: number;\n /**\n * Bookmark names already taken, in document order.\n *\n * A heading with no author-supplied id slugs its text, and two headings can\n * easily slug to the same thing — so the slug is disambiguated against every\n * name allocated before it, explicit ones included.\n */\n bookmarkNames: Set<string>;\n styleIds: Set<string>;\n /** Numbering definitions, in the order the lists that need them appear. */\n numbering: DocxIrNumbering[];\n numberingByReference: Map<string, DocxIrNumbering>;\n /**\n * Counter behind the generated `list-1`, `markdown-list-2`, … references.\n *\n * One counter for both kinds: they share a namespace, so a document that\n * mixes them must not produce two definitions with the same name.\n */\n listCounter: number;\n /** Warning messages already collected, so one bad value warns once. */\n warnedMessages: Set<string>;\n /** Echo warnings to the console, because the caller collects none itself. */\n echoWarnings: boolean;\n /**\n * Ids for `w:ins` / `w:del`, allocated in document order.\n *\n * OOXML wants a number on every tracked change, unique within the document;\n * allocating them here rather than while rendering is what keeps two\n * compilations of the same document identical.\n */\n nextRevisionId: number;\n /** Comment bodies, in id order, with the ids their anchors carry. */\n comments: DocxIrComment[];\n /** Note bodies, in the order their markers resolved. */\n footnotes: DocxIrNote[];\n endnotes: DocxIrNote[];\n commentCounter: number;\n /** Whether anything in this document asked for a resolved state. */\n hasResolvedComment: boolean;\n /**\n * Cross-reference targets, from the document-outline pre-pass.\n *\n * A `[@id]` may point forward, so nothing but a walk of the whole document\n * can resolve it — which is why it is computed once, before compiling.\n */\n numberedItems: ReadonlyMap<string, NumberedItemInfo>;\n /** Every heading and mapped-style paragraph, for a TOC's cached entries. */\n tocEntries: readonly TocHeadingEntry[];\n /** Image bytes, loaded before compilation started. */\n images: ImageResources;\n /**\n * When this document was generated.\n *\n * A `{DATE}` placeholder resolves against it here rather than at render\n * time, so the document says when it was made and two compilations of the\n * same document agree.\n */\n generatedAt: Date;\n}\n\nexport function compileDocument(\n structure: ProcessedDocument,\n layout: LayoutPlan,\n warnings: GenerationWarning[] = [],\n images: ImageResources = new Map(),\n options: { echoWarnings?: boolean } = {}\n): DocxCompileResult {\n const styles = createDocumentStyles(structure.theme, structure.language);\n // Walk the outline before compiling so a cross-reference can resolve a target\n // that appears later in the document, and a TOC field can carry cached\n // entries. Same catch-and-degrade discipline as the pre-IR path: a failure\n // here costs the cached values, never the document.\n const outline = collectOutline(layout, warnings);\n const ctx: CompileContext = {\n theme: structure.theme,\n themeName: structure.themeName,\n warnings,\n features: new FeatureRequirementCollector<DocxFeature>(),\n unsupported: [],\n resources: [],\n resourcesByHash: new Map(),\n nextBookmarkId: CONTENT_BOOKMARK_ID_BASE + 1,\n bookmarkNames: new Set(),\n styleIds: new Set([\n ...styles.paragraph.map((s) => s.id),\n ...styles.character.map((s) => s.id),\n ]),\n numbering: [],\n numberingByReference: new Map(),\n listCounter: 0,\n warnedMessages: new Set(),\n echoWarnings: options.echoWarnings === true,\n nextRevisionId: 1,\n comments: [],\n footnotes: [],\n endnotes: [],\n commentCounter: 0,\n hasResolvedComment: false,\n numberedItems: outline.numberedItems,\n tocEntries: outline.entries,\n images,\n generatedAt: structure.metadata.date,\n };\n\n ctx.features.require('paragraphs', 'sections');\n ctx.features.require('styles', 'styles');\n if (layout.sections.length > 1) ctx.features.require('sections', 'sections');\n\n // A user-defined section can be split across several layout sections; the\n // fold decides which one opens the shared bookmark and which one closes it.\n const ordinals = computeSectionOrdinals(layout.sections);\n const chrome = resolveSectionChrome(layout.sections);\n const sections = layout.sections.map((section, index) =>\n compileSection(section, index, ordinals[index], chrome[index], ctx)\n );\n\n // A resolved flag lives in `word/commentsExtended.xml`, which is written only\n // for threaded comments. A document whose only resolved comment has no\n // replies would lose that state, so say so rather than dropping it quietly.\n if (\n ctx.hasResolvedComment &&\n !ctx.comments.some((comment) => comment.parentId !== undefined)\n ) {\n warnOnce(\n ctx,\n 'comment',\n 'A comment sets `resolved` but the document has no replies. Word stores ' +\n 'the resolved flag in commentsExtended.xml, which is written only for ' +\n 'threaded comments, so the flag will not survive.'\n );\n }\n\n const metadata = compileMetadata(structure);\n // `docProps/custom.xml` is a part of its own, and a backend that does not\n // write it would drop the properties without saying so.\n if (metadata.custom?.length) {\n ctx.features.require('custom-properties', 'metadata.custom');\n }\n\n const ir: DocxIR = {\n schemaVersion: DOCX_IR_SCHEMA_VERSION,\n metadata,\n settings: {\n ...(structure.language ? { language: structure.language } : {}),\n updateFields: true,\n trackRevisions: structure.trackRevisions === true,\n ...(noProofWords(structure.theme)\n ? { noProofWords: noProofWords(structure.theme) }\n : {}),\n },\n styles,\n numbering: ctx.numbering,\n resources: ctx.resources,\n sections,\n comments: ctx.comments,\n footnotes: ctx.footnotes,\n endnotes: ctx.endnotes,\n };\n\n return {\n ir,\n required: ctx.features.list(),\n warnings: ctx.warnings,\n unsupported: ctx.unsupported,\n };\n}\n\n/**\n * The document outline, or an empty one if the walk fails.\n *\n * A failure here costs the cached cross-reference values and the TOC entries,\n * never the document itself — a reader that refreshes fields still sees the\n * right numbers.\n */\nfunction collectOutline(\n layout: LayoutPlan,\n warnings: GenerationWarning[]\n): ReturnType<typeof collectDocumentOutline> {\n try {\n return collectDocumentOutline(layout.sections);\n } catch (error) {\n warnings.push({\n component: 'document',\n message:\n '[core-docx] Document outline collection failed; the TOC field will rely on the reader refreshing it: ' +\n (error instanceof Error ? error.message : String(error)),\n });\n return { entries: [], numberedItems: new Map() };\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Document level\n * ------------------------------------------------------------------ */\n\n/**\n * Core and custom document properties.\n *\n * `subtitle` lands in the `subject` slot and `company`/`version` have no core\n * slot at all, so they become custom properties — the same mapping the pre-IR\n * writer used. Created and modified timestamps are pinned during packaging, so\n * the value here is only a placeholder.\n */\nfunction compileMetadata(structure: ProcessedDocument): DocxIR['metadata'] {\n const { metadata } = structure;\n const timestamp = metadata.date.toISOString();\n const custom = [\n ...(metadata.company ? [{ name: 'Company', value: metadata.company }] : []),\n ...(metadata.version ? [{ name: 'Version', value: metadata.version }] : []),\n ];\n\n return {\n ...(metadata.title ? { title: metadata.title } : {}),\n ...(metadata.subtitle ? { subject: metadata.subtitle } : {}),\n ...(metadata.description ? { description: metadata.description } : {}),\n ...(metadata.author\n ? { author: metadata.author, lastModifiedBy: metadata.author }\n : {}),\n ...(metadata.tags?.length ? { keywords: metadata.tags.join(', ') } : {}),\n ...(custom.length > 0 ? { custom } : {}),\n createdAt: timestamp,\n modifiedAt: timestamp,\n };\n}\n\nfunction noProofWords(theme: ThemeConfig): string[] | undefined {\n const words = (theme as { noProofWords?: string[] }).noProofWords;\n return words && words.length > 0 ? words : undefined;\n}\n\n/** The document-wide allowlist plus a component's own, de-duplicated. */\nfunction mergeNoProofWords(\n themeWords: string[] | undefined,\n componentWords: unknown\n): string[] | undefined {\n const own = Array.isArray(componentWords) ? (componentWords as string[]) : [];\n const merged = [...(themeWords ?? []), ...own];\n return merged.length > 0 ? [...new Set(merged)] : undefined;\n}\n\n/* ------------------------------------------------------------------ *\n * Sections\n * ------------------------------------------------------------------ */\n\n/** A section's header and footer content, after inheritance is resolved. */\ninterface SectionChrome {\n header?: ComponentDefinition[];\n footer?: ComponentDefinition[];\n}\n\n/**\n * Decide what each section's header and footer actually contain.\n *\n * Word links a section's page chrome to the previous section's unless the\n * section says otherwise, so \"no header here\" cannot be expressed by leaving\n * the header out — it has to be an explicit empty one. Three cases:\n *\n * - `linkToPrevious` repeats the previous section's content;\n * - stated content is used as written, and becomes what the next section may\n * inherit or has to override;\n * - nothing stated after a section that had chrome becomes an empty part,\n * which is what breaks the link.\n *\n * A document whose sections never set a header or footer stays free of both.\n */\nfunction resolveSectionChrome(\n sections: readonly SectionLayout[]\n): SectionChrome[] {\n let previousHeader: ComponentDefinition[] | undefined;\n let previousFooter: ComponentDefinition[] | undefined;\n\n return sections.map((section) => {\n const resolve = (\n part: SectionLayout['header'],\n previous: ComponentDefinition[] | undefined\n ): {\n resolved: ComponentDefinition[] | undefined;\n previous: ComponentDefinition[] | undefined;\n } => {\n if (part === 'linkToPrevious') return { resolved: previous, previous };\n if (part) return { resolved: part, previous: part };\n return { resolved: previous ? [] : undefined, previous };\n };\n\n const header = resolve(section.header, previousHeader);\n previousHeader = header.previous;\n const footer = resolve(section.footer, previousFooter);\n previousFooter = footer.previous;\n\n return {\n ...(header.resolved ? { header: header.resolved } : {}),\n ...(footer.resolved ? { footer: footer.resolved } : {}),\n };\n });\n}\n\nfunction compileSection(\n section: SectionLayout,\n index: number,\n ordinal: { ordinal?: number; closeBookmark: boolean },\n chrome: SectionChrome,\n ctx: CompileContext\n): DocxIrSection {\n const path = `sections[${index}]`;\n const { page, column } = section.properties;\n\n if (column && column.count > 1) {\n ctx.features.require('columns', `${path}.properties.columns`);\n }\n\n const children: DocxIrBlock[] = [];\n // Every layout chunk of one user-defined section resolves to the same\n // bookmark, which is what a section-scoped table of contents restricts to.\n const sectionBookmarkName =\n section.belongsToUserSection && ordinal.ordinal !== undefined\n ? `_Section_${ordinal.ordinal}`\n : undefined;\n\n section.components.forEach((component, i) => {\n if ('enabled' in component && component.enabled === false) return;\n children.push(\n ...compileComponent(component, {\n ctx,\n path: `${path}.children[${i}]`,\n id: blockId(index, [i]),\n ...(sectionBookmarkName ? { sectionBookmarkName } : {}),\n })\n );\n });\n\n const compiled: DocxIrSection = {\n id: `s${index}`,\n path,\n children,\n properties: {\n page: {\n widthTwips: page.size.width,\n heightTwips: page.size.height,\n orientation:\n page.size.width > page.size.height ? 'landscape' : 'portrait',\n ...(page.size.code !== undefined ? { code: page.size.code } : {}),\n margins: {\n topTwips: page.margin.top,\n bottomTwips: page.margin.bottom,\n leftTwips: page.margin.left,\n rightTwips: page.margin.right,\n ...(page.margin.header !== undefined\n ? { headerTwips: page.margin.header }\n : {}),\n ...(page.margin.footer !== undefined\n ? { footerTwips: page.margin.footer }\n : {}),\n ...(page.margin.gutter !== undefined\n ? { gutterTwips: page.margin.gutter }\n : {}),\n },\n },\n // A chunk that starts on a new page says so; the rest continue the flow.\n // The layout stage already decided which, so it is carried rather than\n // re-derived from `breakBefore`: a section can be continuous without the\n // two agreeing.\n ...(section.properties.type\n ? { type: sectionType(section.properties.type) }\n : {}),\n ...(column\n ? {\n columns: {\n count: column.count,\n ...(column.space !== undefined\n ? { spaceTwips: column.space }\n : {}),\n ...(column.equalWidth !== undefined\n ? { equalWidth: column.equalWidth }\n : {}),\n ...(column.widths\n ? {\n widths: column.widths.map((c) => ({\n widthTwips: c.width,\n ...(c.space !== undefined ? { spaceTwips: c.space } : {}),\n })),\n }\n : {}),\n },\n }\n : {}),\n },\n };\n\n if (ordinal.ordinal !== undefined) {\n compiled.bookmark = {\n id: ordinal.ordinal,\n name: `_Section_${ordinal.ordinal}`,\n opens: section.isUserSection,\n closes: ordinal.closeBookmark,\n };\n ctx.features.require('bookmarks', `${path}.bookmark`);\n }\n\n const headers = compilePart(chrome.header, 'header', index, ctx);\n if (headers) compiled.headers = { default: headers };\n const footers = compilePart(chrome.footer, 'footer', index, ctx);\n if (footers) compiled.footers = { default: footers };\n\n if (headers || footers) {\n ctx.features.require('headers-footers', `${path}.headers`);\n }\n\n return compiled;\n}\n\n/**\n * The layout stage's section-start value, restated as the IR's own.\n *\n * The two vocabularies happen to coincide today; mapping rather than casting\n * means the IR union stays the authority if either side moves.\n */\nfunction sectionType(\n value: string\n): DocxIrSectionProperties['type'] | undefined {\n switch (value) {\n case 'nextPage':\n case 'nextColumn':\n case 'continuous':\n case 'evenPage':\n case 'oddPage':\n return value;\n default:\n return undefined;\n }\n}\n\nfunction compilePart(\n part: ComponentDefinition[] | undefined,\n kind: 'header' | 'footer',\n sectionIndex: number,\n ctx: CompileContext\n): DocxIrHeaderFooter | undefined {\n if (!part) return undefined;\n\n const id = `${kind}:s${sectionIndex}:default`;\n const children: DocxIrBlock[] = [];\n // `enabled: false` is stripped from body content while sections are being\n // flattened; header and footer content never passes through that, so it is\n // filtered here instead.\n const active = part.filter(\n (component) => !('enabled' in component && component.enabled === false)\n );\n active.forEach((component, i) => {\n const scope: ComponentScope = {\n ctx,\n path: `sections[${sectionIndex}].${kind}s.default.children[${i}]`,\n id: headerFooterBlockId(id, [i]),\n };\n children.push(\n ...(component.name === 'paragraph'\n ? compileChromeParagraph(component, scope)\n : component.name === 'image'\n ? compileChromeImage(component, scope)\n : compileComponent(component, scope))\n );\n });\n\n // An empty part is deliberate — it is what breaks Word's link to the\n // previous section — and disabling every component in one is the same\n // statement said differently: the author supplied chrome for this section and\n // asked for none of it. Only *active* content that compiles to nothing falls\n // back to inheritance, because that is a lowering gap rather than an\n // instruction, and inheriting is the older behaviour.\n if (children.length === 0 && active.length > 0) return undefined;\n\n return { id, children };\n}\n\n/**\n * A paragraph inside a header or footer.\n *\n * Page chrome has no style of its own, so every run states its family, size,\n * colour and weight, resolved against the theme's Normal style rather than\n * inherited. That also makes it a narrower component than a body paragraph:\n * only text, alignment, font and spacing apply here. Indentation, tab stops,\n * bookmarks, notes, comments, revisions and the keep flags have never been\n * carried into page chrome and still are not.\n */\nfunction compileChromeParagraph(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const text = String(props.text ?? '');\n\n if (reportUnlowered(component, props, text, scope)) return [];\n\n const font = (props.font ?? {}) as Record<string, any>;\n const normal = getNormalStyle(ctx.theme);\n const chromeProps: Record<string, any> = {\n text,\n ...(props.alignment ? { alignment: props.alignment } : {}),\n ...(props.spacing ? { spacing: props.spacing } : {}),\n ...(props.boldColor ? { boldColor: props.boldColor } : {}),\n font: {\n family:\n font.family ||\n resolveFontFamily(ctx.theme, normal.font) ||\n getThemeFonts(ctx.theme).body.family,\n size: font.size ?? normal.size ?? 11,\n color: font.color || normal.color || 'textPrimary',\n bold: font.bold ?? false,\n italic: font.italic ?? false,\n ...(font.underline !== undefined ? { underline: font.underline } : {}),\n ...(font.fontWeight !== undefined ? { fontWeight: font.fontWeight } : {}),\n ...(font.lineSpacing !== undefined\n ? { lineSpacing: font.lineSpacing }\n : {}),\n },\n };\n\n return [\n paragraphNode(scope, compileRuns(chromeProps, text, ctx, scope.path), {\n styleId: 'Normal',\n formatting: paragraphFormatting(chromeProps, ctx, {\n alwaysSpacing: true,\n }),\n }),\n ];\n}\n\n/**\n * An image inside a header or footer.\n *\n * Narrower than a body image, and differently sized: page chrome has no\n * caption, no spacing and no keep flags, its paragraph names the Normal style,\n * and it is only aligned when the author said so. A width given as a number is\n * taken literally rather than defaulting to the full measure — an unsized\n * chrome image draws at its own resolution.\n */\nfunction compileChromeImage(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n\n const source = resolveImageSource(props);\n if (!source) {\n ctx.unsupported.push({\n name: 'image',\n path,\n detail: 'missing path, base64 or svg',\n });\n return [];\n }\n\n const loaded = ctx.images.get(source);\n if (!loaded) {\n throw new Error(`Failed to load image from ${source.substring(0, 50)}`);\n }\n\n const mediaType = detectImageType(source, loaded.contentType);\n if (mediaType === 'svg') ctx.features.require('svg-images', path);\n\n const page = getPageSetup(ctx.theme);\n const pageWidthPx = Math.round(twipsToPixels(page.size.width));\n const contentWidthPx = Math.round(\n twipsToPixels(page.size.width - page.margin.left - page.margin.right)\n );\n const pageHeightPx = Math.round(twipsToPixels(page.size.height));\n const contentHeightPx = Math.round(\n twipsToPixels(page.size.height - page.margin.top - page.margin.bottom)\n );\n const referenceWidthPx =\n props.widthRelativeTo === 'page' ? pageWidthPx : contentWidthPx;\n const referenceHeightPx =\n props.heightRelativeTo === 'page' ? pageHeightPx : contentHeightPx;\n\n // Only a percentage is resolved against the reference; a number is a pixel\n // count and an absent width is genuinely absent.\n const targetWidth =\n typeof props.width === 'string'\n ? parseWidthValue(props.width, referenceWidthPx)\n : (props.width as number | undefined);\n const targetHeight =\n typeof props.height === 'string'\n ? parseWidthValue(props.height, referenceHeightPx)\n : (props.height as number | undefined);\n\n const size = loaded.intrinsic\n ? calculateMissingDimension(\n loaded.intrinsic.width,\n loaded.intrinsic.height,\n targetWidth,\n targetHeight\n )\n : fallbackSize(targetWidth, targetHeight, {\n width: referenceWidthPx,\n height: Math.round(referenceWidthPx * 0.6),\n });\n\n ctx.features.require('images', path);\n if (props.floating) ctx.features.require('floating-images', path);\n\n const image: DocxIrImageRun = {\n kind: 'image',\n resourceId: declareResource(loaded, mediaType, ctx),\n widthEmu: pixelsToEmu(size.width),\n heightEmu: pixelsToEmu(size.height),\n ...(props.floating\n ? { floating: compileFloating(props.floating, ctx, path) }\n : {}),\n };\n\n return [\n {\n kind: 'paragraph',\n id: scope.id,\n path,\n styleId: 'Normal',\n children: [image],\n ...(props.alignment\n ? { formatting: { alignment: compileAlignment(props.alignment)! } }\n : {}),\n },\n ];\n}\n\n/* ------------------------------------------------------------------ *\n * Components\n * ------------------------------------------------------------------ */\n\ninterface ComponentScope {\n ctx: CompileContext;\n path: string;\n id: string;\n /**\n * The bookmark covering the section this component sits in, if any.\n *\n * A table of contents scoped to its own section needs it; nothing else does.\n */\n sectionBookmarkName?: string;\n}\n\nfunction compileComponent(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n switch (component.name) {\n case 'paragraph':\n return compileParagraph(component, scope);\n case 'heading':\n return compileHeading(component, scope);\n case 'list':\n return compileList(component, scope);\n case 'statistic':\n return compileStatistic(component, scope);\n case 'toc':\n return compileToc(component, scope);\n case 'text-box':\n return compileTextBox(component, scope);\n case 'columns':\n return compileColumns(component, scope);\n case 'image':\n return compileImage(component, scope);\n case 'table':\n return compileTable(component, scope);\n default:\n scope.ctx.unsupported.push({\n name: component.name,\n path: scope.path,\n });\n return [];\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Paragraphs and headings\n * ------------------------------------------------------------------ */\n\n/**\n * The levels a markdown list always defines.\n *\n * Three of them, whatever depth the text actually reaches: the syntax has no\n * way to declare its own numbering, so the definition is fixed.\n */\nconst MARKDOWN_LIST_LEVELS: Readonly<Record<string, ListLevelConfig[]>> = {\n unordered: [\n { level: 0, format: 'bullet', text: '•', alignment: 'left' },\n { level: 1, format: 'bullet', text: '◦', alignment: 'left' },\n { level: 2, format: 'bullet', text: '▪', alignment: 'left' },\n ],\n ordered: [\n { level: 0, format: 'decimal', text: '%1.', alignment: 'left' },\n { level: 1, format: 'lowerLetter', text: '%2.', alignment: 'left' },\n { level: 2, format: 'lowerRoman', text: '%3.', alignment: 'left' },\n ],\n};\n\n/**\n * Markdown decorators.\n *\n * A heading reaches the inline parser only when its text carries one of these\n * or a cross-reference; anything else is rendered character for character.\n */\nconst DECORATED = /(\\*\\*\\*|___|(\\*\\*|__)|(\\*|_))/;\n\nfunction compileParagraph(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const text = String(props.text ?? '');\n\n if (reportUnlowered(component, props, text, scope)) return [];\n\n // A paragraph whose whole text is a markdown list is a list, and has always\n // rendered as one. A revision paragraph never is: its segments carry literal\n // text and cannot be re-split into items.\n const markdown = props.revision ? null : parseMarkdownList(text);\n if (markdown) {\n return compileList(\n {\n ...component,\n props: {\n items: markdown.items,\n ...(props.spacing ? { spacing: props.spacing } : {}),\n ...(props.alignment ? { alignment: props.alignment } : {}),\n ...(props.comment ? { comment: props.comment } : {}),\n ...(props.footnotes ? { footnotes: props.footnotes } : {}),\n ...(props.endnotes ? { endnotes: props.endnotes } : {}),\n },\n } as ComponentDefinition,\n scope,\n 'markdown-list',\n MARKDOWN_LIST_LEVELS[markdown.type]\n );\n }\n\n const styleId = paragraphStyleId(props.themeStyle);\n if (styleId && !ctx.styleIds.has(styleId)) ctx.styleIds.add(styleId);\n\n const children = compileRuns(props, text, ctx, path);\n // A paragraph is a bookmark target only when the author asked for one, and\n // the id is a prop — unlike a heading, whose id sits on the component.\n const bookmarkName = typeof props.id === 'string' ? props.id : undefined;\n\n return [\n paragraphNode(scope, children, {\n ...(styleId ? { styleId } : {}),\n ...(props.floating\n ? { frame: compileFrame(props.floating, ctx, path) }\n : {}),\n formatting: paragraphFormatting(props, ctx, {\n outlineLevel: customOutlineLevel(props.themeStyle, ctx.theme),\n // A paragraph always states its spacing, even when empty, so a\n // paragraph with none is distinguishable from a heading, which\n // deliberately leaves its style's spacing alone.\n alwaysSpacing: true,\n }),\n bookmarkName,\n ...(props.comment\n ? { commentIds: declareComment(props.comment, ctx, path) }\n : {}),\n }),\n ];\n}\n\nfunction compileHeading(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const text = String(props.text ?? '');\n\n if (reportUnlowered(component, props, text, scope)) return [];\n\n const level = headingLevel(props.level);\n // A heading with no decorators is rendered character for character — the\n // cheaper path the writer has always taken, and the reason a bare link in a\n // heading stays literal text.\n const children = compileRuns(\n props,\n text,\n ctx,\n path,\n DECORATED.test(text) || containsCrossReference(text) ? 'inline' : 'literal'\n );\n\n // A heading is always a bookmark target: an explicit id, or a slug of the\n // text. That is what makes it reachable from a TOC or an internal link.\n const bookmarkName =\n (typeof component.id === 'string' ? component.id : undefined) ??\n dedupeBookmarkId(slugifyBookmarkText(text), (id) =>\n ctx.bookmarkNames.has(id)\n );\n\n return [\n paragraphNode(scope, children, {\n styleId: `Heading${level}`,\n // A heading with no stated alignment is left-aligned; its style's own\n // spacing is left untouched.\n formatting: paragraphFormatting(props, ctx, { defaultAlignment: 'left' }),\n bookmarkName,\n ...(props.comment\n ? { commentIds: declareComment(props.comment, ctx, path) }\n : {}),\n numberingNone: props.numbering === false,\n ...(props.numbering === true\n ? { numbering: declareHeadingNumbering(level, ctx, path) }\n : {}),\n }),\n ];\n}\n\n/**\n * The one numbering definition every numbered heading shares.\n *\n * Shared so that 1., 1.1., 1.1.1. is a single continuous sequence rather than\n * one that restarts at each heading. Levels bind to `Heading1`..`Heading6`\n * through `pStyle`, which is what makes Word's own restart/continue UI and the\n * `\\r` cross-reference switch recognise them.\n */\nfunction declareHeadingNumbering(\n level: number,\n ctx: CompileContext,\n path: string\n): { reference: string; level: number } {\n if (!ctx.numberingByReference.has(HEADING_NUMBERING_REFERENCE)) {\n const numbering: DocxIrNumbering = {\n reference: HEADING_NUMBERING_REFERENCE,\n levels: Array.from({ length: 6 }, (_, index) => ({\n level: index,\n format: 'decimal',\n // Each level accumulates the ones above it: %1, %1.%2, %1.%2.%3, …\n text: `${Array.from({ length: index + 1 }, (_, i) => `%${i + 1}`).join('.')}.`,\n alignment: 'left' as const,\n start: 1,\n // A space, not the default tab: a tab would push the heading text to\n // the next tab stop and misalign it against unnumbered headings.\n suffix: 'space' as const,\n // A numbered heading stays flush left and takes its indentation from\n // the heading style, so the level supplies none of its own.\n indent: { leftTwips: 0, hangingTwips: 0 },\n paragraphStyleId: `Heading${index + 1}`,\n })),\n };\n ctx.numbering.push(numbering);\n ctx.numberingByReference.set(HEADING_NUMBERING_REFERENCE, numbering);\n }\n\n ctx.features.require('numbering', path);\n return { reference: HEADING_NUMBERING_REFERENCE, level: level - 1 };\n}\n\n/* ------------------------------------------------------------------ *\n * Text boxes\n * ------------------------------------------------------------------ */\n\n/**\n * Columns nested inside a text box, as a one-row table.\n *\n * At the top level a `columns` component becomes a section with a real column\n * layout, and the layout stage has already unwrapped it by the time the\n * compiler runs. Inside a text box there is no section to give, so the columns\n * become cells: children are dealt round-robin across them, and the gap between\n * two columns is split as a margin on each side of the boundary.\n */\nfunction compileColumns(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const configs = columnConfigs(props.columns);\n if (configs.length === 0) return [];\n\n const available = getAvailableWidthTwips(ctx.theme, ctx.themeName);\n const { widths, gaps } = columnMetrics(configs, props.gap, available);\n\n // Round-robin: the only distribution available without measuring text, and\n // the one this has always used.\n const contents: ComponentDefinition[][] = configs.map(() => []);\n const children =\n (component as { children?: ComponentDefinition[] }).children ?? [];\n children.forEach((child, index) => {\n contents[index % configs.length].push(child);\n });\n\n ctx.features.require('tables', path);\n\n return [\n {\n kind: 'table',\n id: scope.id,\n path,\n columnGrid: { unit: 'twips', values: [] },\n width: { kind: 'percent', value: 100 },\n layout: 'fixed',\n borders: NO_BORDERS,\n rows: [\n {\n cells: configs.map((_, index) => {\n const blocks = contents[index].flatMap((child, childIndex) =>\n compileComponent(child, {\n ...scope,\n path: `${path}.children[${index}][${childIndex}]`,\n id: `${scope.id}:c${index}:${childIndex}`,\n })\n );\n return {\n // An empty column is still a column: it needs a paragraph or the\n // cell has no content at all.\n children: blocks.length\n ? blocks\n : [\n {\n kind: 'paragraph' as const,\n id: `${scope.id}:c${index}:empty`,\n path: `${path}.children[${index}][0]`,\n children: [],\n },\n ],\n widthTwips: widths[index],\n margins: {\n topTwips: 0,\n rightTwips: gaps[index] / 2,\n bottomTwips: 0,\n leftTwips: index > 0 ? gaps[index - 1] / 2 : 0,\n },\n verticalAlign: 'top' as const,\n borders: {\n top: NO_BORDERS.top,\n right: NO_BORDERS.right,\n bottom: NO_BORDERS.bottom,\n left: NO_BORDERS.left,\n },\n };\n }),\n },\n ],\n },\n ];\n}\n\n/** A column count or an explicit list, as a list either way. */\nfunction columnConfigs(\n columns: unknown\n): Array<{ width?: number | string; gap?: number | string }> {\n if (typeof columns === 'number') {\n return Array.from({ length: columns }, () => ({ width: 'auto' as const }));\n }\n return Array.isArray(columns) ? columns : [];\n}\n\n/**\n * Column widths and the gaps between them, in twips.\n *\n * Stated widths are taken as written; whatever the page has left over after\n * them and the gaps is split evenly between the columns that stated none.\n */\nfunction columnMetrics(\n configs: Array<{ width?: number | string; gap?: number | string }>,\n defaultGap: number | string | undefined,\n available: number\n): { widths: number[]; gaps: number[] } {\n const widths: number[] = [];\n const gaps: number[] = [];\n const autoIndexes: number[] = [];\n let stated = 0;\n let totalGaps = 0;\n\n configs.forEach((column, index) => {\n if (column.width === undefined || column.width === 'auto') {\n autoIndexes.push(index);\n widths.push(0);\n } else {\n const width = relativeLengthToTwips(column.width, available);\n widths.push(width);\n stated += width;\n }\n\n if (index < configs.length - 1) {\n // Half an inch between columns unless something says otherwise.\n const gap =\n column.gap !== undefined\n ? relativeLengthToTwips(column.gap, available)\n : defaultGap !== undefined\n ? relativeLengthToTwips(defaultGap, available)\n : 720;\n gaps.push(gap);\n totalGaps += gap;\n } else {\n gaps.push(0);\n }\n });\n\n if (autoIndexes.length > 0) {\n const share = Math.floor(\n Math.max(0, available - stated - totalGaps) / autoIndexes.length\n );\n for (const index of autoIndexes) widths[index] = share;\n }\n\n return { widths, gaps };\n}\n\n/** 1px at 96 DPI in twips — 1440 twips per inch over 96 pixels per inch. */\nconst TWIPS_PER_PIXEL = 15;\n\n/** ~333px, the width a floating text box takes when it states none. */\nconst DEFAULT_TEXT_BOX_WIDTH_TWIPS = 5000;\n\n/**\n * A text box: a borderless one-cell table holding its children.\n *\n * A table rather than a shape because that is the only rendering with autofit,\n * per-side borders and a width that stays a percentage — a shape freezes all\n * three at generation time. `renderAs: 'shape'` asks for the other one.\n */\nfunction compileTextBox(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n\n const children: DocxIrBlock[] = [];\n const contents =\n (component as { children?: ComponentDefinition[] }).children ?? [];\n contents.forEach((child, index) => {\n children.push(\n ...compileComponent(child, {\n ...scope,\n path: `${path}.children[${index}]`,\n id: `${scope.id}:c${index}`,\n })\n );\n });\n\n const style = props.style as Record<string, any> | undefined;\n const padding = style?.padding as Record<string, number> | undefined;\n\n if (props.renderAs === 'shape') {\n const shape = compileShape(props, children, scope);\n if (shape) return shape;\n // Everything a shape cannot express falls back to the table below, rather\n // than shipping a box that clips its content or redraws its border.\n }\n\n ctx.features.require('tables', path);\n if (props.floating) ctx.features.require('floating-tables', path);\n\n return [\n {\n kind: 'table',\n id: scope.id,\n path,\n // No grid: one cell, whose width the table itself decides.\n columnGrid: { unit: 'twips', values: [] },\n width: textBoxWidth(props),\n layout: 'fixed',\n // The container is invisible; whatever border the author asked for is\n // drawn by the cell inside it.\n borders: NO_BORDERS,\n ...(props.floating\n ? { floating: compileTableFloat(props.floating, ctx) }\n : {}),\n rows: [\n {\n cells: [\n {\n // A cell with nothing in it still needs a paragraph, or the row\n // has no content at all and Word rejects the table.\n children: children.length\n ? children\n : [\n {\n kind: 'paragraph',\n id: `${scope.id}:empty`,\n path: `${path}.children[0]`,\n children: [],\n },\n ],\n margins: {\n topTwips: padding?.top ? pointsToTwips(padding.top) : 0,\n rightTwips: padding?.right ? pointsToTwips(padding.right) : 0,\n bottomTwips: padding?.bottom\n ? pointsToTwips(padding.bottom)\n : 0,\n leftTwips: padding?.left ? pointsToTwips(padding.left) : 0,\n },\n ...(style?.shading?.fill\n ? {\n shading: {\n fill: irColor(\n resolveColor(style.shading.fill, ctx.theme)\n ),\n },\n }\n : {}),\n ...(compileBorders(style?.border, ctx)\n ? { borders: compileBorders(style?.border, ctx)! }\n : {}),\n },\n ],\n },\n ],\n },\n ];\n}\n\n/** 1px at 96 DPI in EMU — 914400 EMU per inch over 96 pixels per inch. */\nconst EMU_PER_PIXEL = 9525;\n\n/**\n * A text box as a native Word shape, or nothing when it cannot be one.\n *\n * A shape has no autofit, one uniform outline and no dash patterns, so a text\n * box that needs any of those is better served by the table rendering. Each\n * refusal says why: the author asked for something the shape cannot draw, and\n * silently drawing something else would change the design.\n */\nfunction compileShape(\n props: Record<string, any>,\n children: DocxIrBlock[],\n scope: ComponentScope\n): DocxIrBlock[] | undefined {\n const { ctx, path } = scope;\n const width = shapeSize(props.width, 'width', ctx);\n const height = shapeSize(props.height, 'height', ctx);\n\n if (width.pixels === undefined || height.pixels === undefined) {\n warnOnce(\n ctx,\n 'text-box',\n '[core-docx] text-box renderAs \"shape\" needs an explicit width and height (a shape has no autofit); falling back to table rendering.'\n );\n return undefined;\n }\n\n const style = props.style as Record<string, any> | undefined;\n const outline = shapeOutline(style, ctx);\n if (outline.unsupportedStyles.length > 0) {\n warnOnce(\n ctx,\n 'text-box',\n `[core-docx] text-box renderAs \"shape\" cannot draw a ${outline.unsupportedStyles.join('/')} border (a shape outline has no dash pattern); falling back to table rendering, which draws it.`\n );\n return undefined;\n }\n\n // A shape holds paragraphs and nothing else: a nested `columns` renders as a\n // table, which has nowhere to go inside one.\n if (children.some((child) => child.kind !== 'paragraph')) {\n warnOnce(\n ctx,\n 'text-box',\n '[core-docx] text-box renderAs \"shape\" requires paragraph-only content; falling back to table rendering.'\n );\n return undefined;\n }\n\n if (width.resolvedPercentage || height.resolvedPercentage) {\n warnOnce(\n ctx,\n 'text-box',\n '[core-docx] text-box renderAs \"shape\" resolves percentage sizes at generation time, against the current page content box; the shape will not reflow if the page size changes.'\n );\n }\n if (outline.ignoredSides.length > 0) {\n warnOnce(\n ctx,\n 'text-box',\n `[core-docx] text-box renderAs \"shape\" has one uniform outline; using the first declared border side and ignoring ${outline.ignoredSides.join(', ')}.`\n );\n }\n\n // A shape cannot carry both: the two fill groups come out in the wrong order\n // for CT_ShapeProperties and Word rejects the document. The fill wins.\n const fill = style?.shading?.fill as string | undefined;\n const dropOutline = Boolean(fill) && Boolean(outline.outline);\n if (dropOutline) {\n warnOnce(\n ctx,\n 'text-box',\n '[core-docx] text-box renderAs \"shape\" cannot carry a fill and a border at once (docx emits invalid shape properties); keeping the fill and dropping the border.'\n );\n }\n\n ctx.features.require('text-boxes', path);\n if (props.floating) ctx.features.require('floating-images', path);\n\n const insets = shapeInsets(\n style?.padding as Record<string, number> | undefined\n );\n\n return [\n {\n kind: 'paragraph',\n id: scope.id,\n path,\n formatting: { spacing: { beforeTwips: 0, afterTwips: 0 } },\n children: [\n {\n kind: 'shape',\n widthPx: width.pixels,\n heightPx: height.pixels,\n children: children as DocxIrParagraph[],\n ...(fill ? { fill: irColor(resolveColor(fill, ctx.theme)) } : {}),\n ...(outline.outline && !dropOutline\n ? { outline: outline.outline }\n : {}),\n ...(insets ? { insetsEmu: insets } : {}),\n ...(props.floating\n ? { floating: compileFloating(props.floating, ctx, path) }\n : {}),\n },\n ],\n },\n ];\n}\n\n/**\n * A shape's `width`/`height`, in whole pixels.\n *\n * A shape carries an absolute size in the file, so a percentage cannot stay\n * lazy the way a table's `w:tblW` can: it is resolved against the page's\n * content box and frozen here.\n */\nfunction shapeSize(\n value: unknown,\n axis: 'width' | 'height',\n ctx: CompileContext\n): { pixels?: number; resolvedPercentage: boolean } {\n if (typeof value === 'number') {\n return { pixels: Math.round(value), resolvedPercentage: false };\n }\n if (typeof value !== 'string') return { resolvedPercentage: false };\n\n const fraction = parseFloat(value) / 100;\n if (!Number.isFinite(fraction) || fraction <= 0) {\n return { resolvedPercentage: false };\n }\n const availableTwips =\n axis === 'width'\n ? getAvailableWidthTwips(ctx.theme, ctx.themeName)\n : getAvailableHeightTwips(ctx.theme, ctx.themeName);\n return {\n pixels: Math.round((availableTwips * fraction) / TWIPS_PER_PIXEL),\n resolvedPercentage: true,\n };\n}\n\n/**\n * The per-side border config collapsed into the single outline a shape has.\n *\n * Sides are read in top/left/bottom/right order; when they disagree, the first\n * one wins and the caller is told which were dropped. A dash pattern has no\n * DrawingML equivalent at all, so it is reported instead of flattened.\n */\nfunction shapeOutline(\n style: Record<string, any> | undefined,\n ctx: CompileContext\n): {\n outline?: { color: DocxIrColor; widthEmu?: number };\n ignoredSides: string[];\n unsupportedStyles: string[];\n} {\n const border = style?.border as Record<string, any> | undefined;\n if (!border) return { ignoredSides: [], unsupportedStyles: [] };\n\n const declared = (['top', 'left', 'bottom', 'right'] as const)\n .map((side) => [side, border[side]] as const)\n .filter((entry) => Boolean(entry[1]));\n if (declared.length === 0) return { ignoredSides: [], unsupportedStyles: [] };\n\n const unsupportedStyles = [\n ...new Set(\n declared\n .map(([, config]) => config.style)\n .filter(\n (value) =>\n value === 'dashed' || value === 'dotted' || value === 'double'\n )\n ),\n ] as string[];\n if (unsupportedStyles.length > 0) {\n return { ignoredSides: [], unsupportedStyles };\n }\n\n const [, used] = declared[0];\n const ignoredSides = declared\n .slice(1)\n .filter(\n ([, config]) =>\n config.style !== used.style ||\n config.width !== used.width ||\n config.color !== used.color\n )\n .map(([side]) => side as string);\n\n if (used.style === 'none') return { ignoredSides, unsupportedStyles };\n\n return {\n outline: {\n color: irColor(\n used.color ? resolveColor(used.color, ctx.theme) : '000000'\n ),\n ...(used.width !== undefined\n ? { widthEmu: Math.round(used.width * EMU_PER_PIXEL) }\n : {}),\n },\n ignoredSides,\n unsupportedStyles,\n };\n}\n\n/** `bodyPr` insets are EMU, like every other DrawingML length. */\nfunction shapeInsets(\n padding: Record<string, number> | undefined\n):\n | { top?: number; bottom?: number; left?: number; right?: number }\n | undefined {\n if (!padding) return undefined;\n const toEmu = (value: number | undefined) =>\n value === undefined ? undefined : Math.round(value * EMU_PER_PIXEL);\n return {\n ...(padding.top !== undefined ? { top: toEmu(padding.top)! } : {}),\n ...(padding.bottom !== undefined ? { bottom: toEmu(padding.bottom)! } : {}),\n ...(padding.left !== undefined ? { left: toEmu(padding.left)! } : {}),\n ...(padding.right !== undefined ? { right: toEmu(padding.right)! } : {}),\n };\n}\n\n/** Every side off, which is how the container stays invisible. */\nconst NO_BORDERS = {\n top: { style: 'none', sizeEighthPoints: 0, color: { hex: '000000' } },\n right: { style: 'none', sizeEighthPoints: 0, color: { hex: '000000' } },\n bottom: { style: 'none', sizeEighthPoints: 0, color: { hex: '000000' } },\n left: { style: 'none', sizeEighthPoints: 0, color: { hex: '000000' } },\n insideHorizontal: {\n style: 'none',\n sizeEighthPoints: 0,\n color: { hex: '000000' },\n },\n insideVertical: {\n style: 'none',\n sizeEighthPoints: 0,\n color: { hex: '000000' },\n },\n} as const;\n\n/**\n * How wide a text box is.\n *\n * An inline one always fills the measure — the cell inside it is what has a\n * size. A floating one is as wide as it says: a number is pixels, a percentage\n * stays one, and saying nothing means about 3.5 inches.\n */\nfunction textBoxWidth(props: Record<string, any>): DocxIrTableWidth {\n if (!props.floating) return { kind: 'percent', value: 100 };\n\n const raw = props.width ?? props.floating?.width;\n if (raw === undefined) {\n return { kind: 'twips', value: DEFAULT_TEXT_BOX_WIDTH_TWIPS };\n }\n if (typeof raw === 'string' && raw.endsWith('%')) {\n return { kind: 'percent', value: parseFloat(raw) };\n }\n return {\n kind: 'twips',\n value:\n typeof raw === 'number'\n ? raw * TWIPS_PER_PIXEL\n : DEFAULT_TEXT_BOX_WIDTH_TWIPS,\n };\n}\n\n/** Per-side borders as the authoring surface states them. */\nfunction compileBorders(\n border: Record<string, any> | undefined,\n ctx: CompileContext\n): DocxIrBorders | undefined {\n if (!border) return undefined;\n const side = (value: Record<string, any> | undefined) =>\n value\n ? {\n style: String(value.style ?? 'single'),\n // Points to eighths of a point, never thinner than the hairline a\n // reader can actually see.\n sizeEighthPoints:\n value.width !== undefined\n ? Math.max(1, Math.round(value.width * 8))\n : 1,\n color: irColor(\n value.color ? resolveColor(value.color, ctx.theme) : '000000'\n ),\n }\n : undefined;\n\n const borders: DocxIrBorders = {\n ...(side(border.top) ? { top: side(border.top)! } : {}),\n ...(side(border.right) ? { right: side(border.right)! } : {}),\n ...(side(border.bottom) ? { bottom: side(border.bottom)! } : {}),\n ...(side(border.left) ? { left: side(border.left)! } : {}),\n };\n return Object.keys(borders).length > 0 ? borders : undefined;\n}\n\n/**\n * Where a floating table sits.\n *\n * A table anchors differently from a drawing: in twips against an anchor rather\n * than in EMU against a frame of reference, and with clearance distances rather\n * than wrap margins.\n */\nfunction compileTableFloat(\n floating: Record<string, any>,\n ctx: CompileContext\n): DocxIrTableFloating {\n const anchor = (relative: unknown): string | undefined =>\n relative === 'margin' || relative === 'page'\n ? relative\n : relative\n ? 'text'\n : undefined;\n\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n const hRef =\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(ctx.theme, ctx.themeName)\n : getPageWidthTwips(ctx.theme, ctx.themeName);\n const vRef =\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(ctx.theme, ctx.themeName)\n : getPageHeightTwips(ctx.theme, ctx.themeName);\n\n const horizontal = floating.horizontalPosition;\n const vertical = floating.verticalPosition;\n const pageWidth = getPageWidthTwips(ctx.theme, ctx.themeName);\n const pageHeight = getPageHeightTwips(ctx.theme, ctx.themeName);\n const margins = floating.wrap?.margins as Record<string, any> | undefined;\n\n return {\n ...(anchor(hRelative) ? { horizontalAnchor: anchor(hRelative)! } : {}),\n ...(anchor(vRelative) ? { verticalAnchor: anchor(vRelative)! } : {}),\n ...(horizontal?.offset !== undefined\n ? {\n absoluteHorizontalPositionTwips: resolveOffsetTwips(\n horizontal.offset,\n hRef\n ),\n }\n : horizontal?.align\n ? { relativeHorizontalPosition: horizontal.align }\n : {}),\n ...(vertical?.offset !== undefined\n ? {\n absoluteVerticalPositionTwips: resolveOffsetTwips(\n vertical.offset,\n vRef\n ),\n }\n : vertical?.align\n ? { relativeVerticalPosition: vertical.align }\n : {}),\n ...(margins?.top !== undefined\n ? { topFromTextTwips: resolveOffsetTwips(margins.top, pageHeight) }\n : {}),\n ...(margins?.right !== undefined\n ? { rightFromTextTwips: resolveOffsetTwips(margins.right, pageWidth) }\n : {}),\n ...(margins?.bottom !== undefined\n ? { bottomFromTextTwips: resolveOffsetTwips(margins.bottom, pageHeight) }\n : {}),\n ...(margins?.left !== undefined\n ? { leftFromTextTwips: resolveOffsetTwips(margins.left, pageWidth) }\n : {}),\n overlap: 'overlap',\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Table of contents\n * ------------------------------------------------------------------ */\n\n/**\n * A table of contents: an optional title paragraph, then the field itself.\n *\n * The field is a top-level block rather than a paragraph's child. Wrapping it\n * in one produces an empty structured-document-tag above the entries in Word.\n */\nfunction compileToc(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n\n const field = resolveTocField(props, ctx.theme, {\n ...(scope.sectionBookmarkName\n ? { sectionBookmarkId: scope.sectionBookmarkName }\n : {}),\n collected: ctx.tocEntries,\n });\n for (const message of field.warnings) warnOnce(ctx, 'toc', message);\n\n const blocks: DocxIrBlock[] = [];\n\n if (props.title) {\n blocks.push({\n kind: 'paragraph',\n id: `${scope.id}:title`,\n path: `${path}.title`,\n // No style, not even Normal: a title with an outline level would collect\n // itself into the very list it introduces. It carries its own weight and\n // size instead.\n children: [\n {\n kind: 'text',\n text: String(props.title),\n formatting: { bold: true, sizeHalfPoints: 28 },\n },\n ],\n formatting: {\n alignment: 'left',\n spacing: {\n beforeTwips:\n (ctx.theme.componentDefaults as any)?.heading?.spacing?.before ??\n 240,\n // ~9pt, which separates the title from the list clearly enough to\n // read as a heading rather than a first entry.\n afterTwips: 180,\n },\n },\n });\n }\n\n ctx.features.require('toc', path);\n if (field.entries.length > 0) ctx.features.require('cached-toc', path);\n\n blocks.push({\n kind: 'toc',\n id: scope.id,\n path,\n alias: String(props.title ?? 'Table of Contents'),\n headingRange: field.headingRange,\n ...(field.styleLevels.length > 0 ? { styleLevels: field.styleLevels } : {}),\n ...(field.bookmarkScope ? { bookmarkScope: field.bookmarkScope } : {}),\n hyperlink: true,\n ...(field.omitPageNumbersForLevels.length > 0\n ? { omitPageNumbersForLevels: field.omitPageNumbersForLevels }\n : {}),\n entrySeparator: field.entrySeparator,\n ...(field.entries.length > 0 ? { cachedEntries: field.entries } : {}),\n });\n\n return blocks;\n}\n\n/* ------------------------------------------------------------------ *\n * Statistics\n * ------------------------------------------------------------------ */\n\n/**\n * A statistic: a figure and its caption, as two styled paragraphs.\n *\n * The text is taken literally — no decorators, no links — because a statistic\n * is a number and a label, not prose. Its spacing is stated in twips: the\n * authoring value has always been passed to the writer unconverted, and\n * reinterpreting it now would move every statistic in every document.\n */\nfunction compileStatistic(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const alignment = compileAlignment(props.alignment) ?? 'center';\n\n // Stating `spacing` at all, even empty, is a statement: it produces a\n // `w:spacing` element that overrides whatever the style would apply.\n const spacing: DocxIrSpacing | undefined = props.spacing\n ? {\n ...(props.spacing.before !== undefined\n ? { beforeTwips: props.spacing.before }\n : {}),\n ...(props.spacing.after !== undefined\n ? { afterTwips: props.spacing.after }\n : {}),\n }\n : undefined;\n\n const line = (\n text: unknown,\n styleId: string,\n suffix: string,\n formatting: DocxIrParagraphFormatting\n ): DocxIrParagraph => {\n const value = normalizeUnicodeText(String(text ?? ''));\n return {\n kind: 'paragraph',\n id: `${scope.id}:${suffix}`,\n path: `${path}.${suffix}`,\n styleId,\n formatting,\n // Nothing to say is not the same as saying nothing: an empty statistic\n // line is a styled blank paragraph, with no run inside it at all.\n children: value ? [{ kind: 'text', text: value }] : [],\n };\n };\n\n return [\n line(props.number, 'StatisticNumber', 'number', {\n alignment,\n ...(spacing ? { spacing } : {}),\n }),\n line(props.description, 'StatisticDescription', 'description', {\n alignment,\n }),\n ];\n}\n\n/* ------------------------------------------------------------------ *\n * Lists\n * ------------------------------------------------------------------ */\n\n/**\n * A list: one numbering definition plus one paragraph per item.\n *\n * The levels come from `resolveListLevels`, shared with the outline pre-pass so\n * a cross-reference cannot predict a different marker from the one drawn. List\n * items deliberately carry no run formatting of their own — they inherit the\n * Normal style, which is what makes a list look like the body text around it.\n */\nfunction compileList(\n component: ComponentDefinition,\n scope: ComponentScope,\n referencePrefix = 'list',\n /** Levels to use as written, instead of deriving them from the props. */\n explicitLevels?: ListLevelConfig[]\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n\n const items = (props.items ?? []) as ListItem[];\n if (items.length === 0) return [];\n\n // One binding for the whole list: ids are declared on the list, and markers\n // may appear in any item.\n const notes = createNoteBinding(props.footnotes, props.endnotes, ctx);\n\n // A markdown list states its levels in full rather than deriving them: it\n // always defines three, however few the text actually uses.\n const reference = declareNumbering(\n props,\n ctx,\n referencePrefix,\n explicitLevels\n );\n const blocks: DocxIrBlock[] = [];\n\n // A list-level comment spans the whole list, so its range opens on the first\n // item that actually renders and closes on the last. Empty items are skipped\n // below, so neither end can be read off the item index.\n const rendersAt = items.map((item) => {\n const text = typeof item === 'string' ? item : String(item.text ?? '');\n const revision = typeof item === 'object' ? item.revision : undefined;\n return Boolean(text.trim()) || revision !== undefined;\n });\n const firstRendered = rendersAt.indexOf(true);\n const lastRendered = rendersAt.lastIndexOf(true);\n const commentIds =\n firstRendered !== -1 && props.comment\n ? declareComment(props.comment, ctx, path)\n : undefined;\n\n items.forEach((item, index) => {\n const text = typeof item === 'string' ? item : String(item.text ?? '');\n const level = typeof item === 'object' ? item.level ?? 0 : 0;\n const revision = typeof item === 'object' ? item.revision : undefined;\n const itemPath = `${path}.items[${index}]`;\n\n // An item with nothing in it is not a bullet with no text; it is not an\n // item at all — unless it is a deletion, whose new text is empty by\n // definition and which still has to render its struck-through runs.\n if (!text.trim() && revision === undefined) return;\n\n if (revision === undefined) {\n const syntax = containsUnsupportedSyntax(text);\n if (syntax) {\n ctx.unsupported.push({ name: 'list', path: itemPath, detail: syntax });\n return;\n }\n } else {\n ctx.features.require('revisions', itemPath);\n }\n\n blocks.push(\n paragraphNode(\n { ctx, path: itemPath, id: `${scope.id}:i${index}` },\n revision === undefined\n ? parseInline(text, {\n base: {},\n hyperlinks: true,\n ...(notes ? { resolveNote: notes.resolve } : {}),\n resolvePlaceholder: placeholderResolver(ctx),\n resolveCrossReference: crossReferenceResolver(ctx, itemPath),\n })\n : compileRevision(revision as Record<string, any>, {}, ctx),\n {\n styleId: 'Normal',\n formatting: {\n alignment: compileAlignment(props.alignment) ?? 'left',\n spacing: itemSpacing(props.spacing, index, items.length),\n },\n ...(commentIds && index === firstRendered\n ? { commentOpen: commentIds }\n : {}),\n ...(commentIds && index === lastRendered\n ? { commentClose: commentIds }\n : {}),\n ...(typeof item === 'object' && typeof item.id === 'string'\n ? { bookmarkName: item.id }\n : {}),\n numbering: { reference, level },\n }\n )\n );\n });\n\n notes?.reportUnemitted(\n items\n .map((item) =>\n typeof item === 'string' ? item : String(item.text ?? '')\n )\n .join('\\n')\n );\n\n if (blocks.length > 0) ctx.features.require('numbering', path);\n return blocks;\n}\n\ntype ListItem =\n | string\n | {\n text?: string;\n level?: number;\n id?: string;\n revision?: Record<string, unknown>;\n };\n\n/**\n * Spacing for one list item.\n *\n * `before` sits on the first item and `after` on the last, so the list as a\n * whole is spaced from its surroundings; `item` spaces every other item from\n * the next one.\n */\nfunction itemSpacing(\n spacing: { before?: number; after?: number; item?: number } | undefined,\n index: number,\n count: number\n): DocxIrSpacing {\n const out: DocxIrSpacing = {};\n if (index === 0 && spacing?.before) {\n out.beforeTwips = pointsToTwips(spacing.before);\n }\n if (index === count - 1 && spacing?.after) {\n out.afterTwips = pointsToTwips(spacing.after);\n } else if (spacing?.item) {\n out.afterTwips = pointsToTwips(spacing.item);\n }\n return out;\n}\n\n/**\n * Register this list's numbering definition and return its reference.\n *\n * A stated `reference` lets several lists share one definition — and continue\n * one numbering sequence — so the first list to claim it wins and the rest just\n * point at it.\n */\nfunction declareNumbering(\n props: Record<string, any>,\n ctx: CompileContext,\n prefix = 'list',\n explicitLevels?: ListLevelConfig[]\n): string {\n const reference =\n typeof props.reference === 'string' && props.reference\n ? props.reference\n : `${prefix}-${++ctx.listCounter}`;\n\n if (ctx.numberingByReference.has(reference)) return reference;\n\n const numbering: DocxIrNumbering = {\n reference,\n levels: (explicitLevels ?? resolveListLevels(props as ListLevelSource)).map(\n (level) => compileNumberingLevel(level, ctx)\n ),\n };\n ctx.numbering.push(numbering);\n ctx.numberingByReference.set(reference, numbering);\n return reference;\n}\n\n/**\n * One numbering level, with every default resolved.\n *\n * Indents are stated in points by authors and in inches by the defaults; both\n * become twips here so no renderer has to know either.\n */\nfunction compileNumberingLevel(\n level: ListLevelConfig,\n ctx: CompileContext\n): DocxIrNumberingLevel {\n const format = level.format || 'bullet';\n const text =\n level.text || (format === 'bullet' ? '•' : `%${level.level + 1}.`);\n const leftInches =\n level.indent?.left !== undefined\n ? level.indent.left / 72\n : 0.5 * (level.level + 1);\n const hangingInches =\n level.indent?.hanging !== undefined ? level.indent.hanging / 72 : 0.25;\n\n return {\n level: level.level,\n format,\n text,\n alignment: markerAlignment(level.alignment),\n indent: {\n leftTwips: inchesToTwips(leftInches),\n hangingTwips: inchesToTwips(hangingInches),\n },\n ...(level.start !== undefined ? { start: level.start } : {}),\n ...(markerRunFormatting(level.font, ctx)\n ? { run: markerRunFormatting(level.font, ctx)! }\n : {}),\n };\n}\n\n/**\n * How a marker sits in its own space (`w:lvlJc`).\n *\n * Wider than paragraph alignment: a marker may be `start`/`end`-aligned, which\n * follows the reading direction, and there is nothing to justify. Anything\n * unrecognised is left-aligned.\n */\nfunction markerAlignment(value: unknown): DocxIrAlignment {\n switch (value) {\n case 'start':\n case 'end':\n case 'right':\n case 'center':\n return value;\n default:\n return 'left';\n }\n}\n\n/** The marker glyph's own formatting, resolved against the theme. */\nfunction markerRunFormatting(\n font: ListMarkerFontConfig | undefined,\n ctx: CompileContext\n): DocxIrRunFormatting | undefined {\n if (!font) return undefined;\n const run: DocxIrRunFormatting = {\n ...(font.family ? { fontFamily: font.family } : {}),\n ...(font.size !== undefined\n ? { sizeHalfPoints: pointsToHalfPoints(font.size) }\n : {}),\n ...(font.color\n ? { color: irColor(resolveColor(font.color, ctx.theme)) }\n : {}),\n ...(font.bold !== undefined ? { bold: font.bold } : {}),\n ...(font.italic !== undefined ? { italic: font.italic } : {}),\n ...(font.underline !== undefined\n ? { underline: font.underline ? { type: 'single' } : undefined }\n : {}),\n };\n return Object.keys(run).length > 0 ? run : undefined;\n}\n\n/**\n * Wrap runs into a paragraph, adding the bookmark pair when there is one.\n *\n * Bookmark ids are allocated here, in document order, so two concurrent\n * compilations of the same document produce the same ids.\n */\nfunction paragraphNode(\n scope: ComponentScope,\n children: DocxIrInline[],\n options: {\n styleId?: string;\n formatting?: DocxIrParagraphFormatting;\n bookmarkName?: string;\n numberingNone?: boolean;\n numbering?: { reference: string; level: number };\n /** Position this paragraph as a floating box. */\n frame?: DocxIrFrame;\n /** Ids of a comment thread anchored over this paragraph's content. */\n commentIds?: readonly number[];\n /**\n * Halves of a range that spans more than this paragraph.\n *\n * A comment on a whole list opens on its first item and closes on its\n * last, so the two ends land on different paragraphs.\n */\n commentOpen?: readonly number[];\n commentClose?: readonly number[];\n }\n): DocxIrParagraph {\n const { ctx } = scope;\n let content = children;\n\n if (options.bookmarkName) {\n ctx.bookmarkNames.add(options.bookmarkName);\n const id = ctx.nextBookmarkId++;\n // A bookmark covers the text, not a break that happens to precede it —\n // a link to this paragraph should land on its content, not on the column\n // boundary before it.\n const breakCount = children.findIndex((c) => c.kind !== 'columnBreak');\n const split = breakCount === -1 ? children.length : breakCount;\n content = [\n ...children.slice(0, split),\n { kind: 'bookmarkStart', id, name: options.bookmarkName },\n ...children.slice(split),\n { kind: 'bookmarkEnd', id },\n ];\n ctx.features.require('bookmarks', scope.path);\n }\n\n const opening = options.commentIds ?? options.commentOpen;\n const closing = options.commentIds ?? options.commentClose;\n if (opening?.length || closing?.length) {\n // The range opens after a leading break so it covers exactly the commented\n // content, and closes around the bookmark rather than inside it.\n const breakCount = content.findIndex((c) => c.kind !== 'columnBreak');\n const split = breakCount === -1 ? content.length : breakCount;\n content = [\n ...content.slice(0, split),\n ...(opening ?? []).map((id) => ({\n kind: 'commentRangeStart' as const,\n id,\n })),\n ...content.slice(split),\n ...(closing ? closeComment(closing) : []),\n ];\n ctx.features.require('comments', scope.path);\n }\n\n return {\n kind: 'paragraph',\n id: scope.id,\n path: scope.path,\n children: content,\n // Body text always names a style; leaving it out is how a table cell says\n // it has none.\n styleId: options.styleId ?? 'Normal',\n ...(options.frame ? { frame: options.frame } : {}),\n ...(options.formatting ? { formatting: options.formatting } : {}),\n ...(options.numberingNone\n ? { numbering: { none: true as const } }\n : options.numbering\n ? { numbering: options.numbering }\n : {}),\n };\n}\n\n/**\n * Report anything about this component the slice does not lower.\n *\n * Returns true when the component was reported, in which case it is not\n * compiled — refusing beats emitting a paragraph with its annotations missing.\n */\nfunction reportUnlowered(\n component: ComponentDefinition,\n props: Record<string, unknown>,\n text: string,\n scope: ComponentScope\n): boolean {\n void props;\n const syntax = containsUnsupportedSyntax(text);\n if (syntax) {\n scope.ctx.unsupported.push({\n name: component.name,\n path: scope.path,\n detail: syntax,\n });\n return true;\n }\n\n return false;\n}\n\nfunction compileRuns(\n props: Record<string, any>,\n text: string,\n ctx: CompileContext,\n path: string,\n mode: 'inline' | 'literal' = 'inline'\n): DocxIrInline[] {\n const font = (props.font ?? {}) as Record<string, any>;\n const base = runFormatting(font, props, ctx);\n\n if (base.language) ctx.features.require('proofing-language', path);\n if (base.noProof) ctx.features.require('proofing-language', path);\n\n // The document's allowlist reaches every paragraph — `processDocument` folds\n // it into the theme — and a paragraph may add words of its own on top.\n const words = mergeNoProofWords(noProofWords(ctx.theme), props.noProofWords);\n\n const children: DocxIrInline[] = [];\n if (props.columnBreak) {\n children.push({ kind: 'columnBreak' });\n ctx.features.require('breaks', path);\n }\n\n const notes = createNoteBinding(props.footnotes, props.endnotes, ctx);\n\n if (props.revision) {\n // Revision segments render literally, so a `[^id]` marker inside them\n // stays literal text and its body is never emitted. Report that rather\n // than dropping the declared notes in silence.\n reportNotesInRevision(props, ctx);\n ctx.features.require('revisions', path);\n return [\n ...(props.columnBreak ? [{ kind: 'columnBreak' as const }] : []),\n ...compileRevision(props.revision, base, ctx),\n ];\n }\n\n const parseOptions = {\n base,\n ...(props.boldColor\n ? { boldColor: irColor(resolveColor(props.boldColor, ctx.theme)) }\n : {}),\n ...(words ? { noProofWords: words } : {}),\n resolvePlaceholder: placeholderResolver(ctx),\n ...(notes ? { resolveNote: notes.resolve } : {}),\n resolveCrossReference: (\n id: string,\n format: CrossReferenceFormat,\n token: string\n ) => resolveCrossReference(id, format, token, ctx, path),\n };\n children.push(\n ...(mode === 'literal'\n ? parseLiteral(text, parseOptions)\n : parseInline(text, { ...parseOptions, hyperlinks: true }))\n );\n if (mode === 'inline' && containsLink(text)) {\n ctx.features.require('hyperlinks', path);\n }\n if (mode === 'inline' && containsPlaceholder(text)) {\n ctx.features.require('fields', path);\n }\n notes?.reportUnemitted(text);\n\n return children;\n}\n\n/** Bind the placeholder resolver to one compilation's generation date. */\nfunction placeholderResolver(\n ctx: CompileContext\n): (name: string) => PlaceholderResolution | undefined {\n return (name) => resolvePlaceholder(name, ctx.generatedAt);\n}\n\n/** Bind the cross-reference resolver to one compilation and one path. */\nfunction crossReferenceResolver(\n ctx: CompileContext,\n path: string\n): (\n id: string,\n format: CrossReferenceFormat,\n token: string\n) => DocxIrInline | undefined {\n return (id, format, token) =>\n resolveCrossReference(id, format, token, ctx, path);\n}\n\n/** OOXML's REF switches, by the format an author asks for. */\nconst REFERENCE_SWITCH: Readonly<Record<CrossReferenceFormat, string>> = {\n relative: '\\\\r',\n no_context: '\\\\n',\n full_context: '\\\\w',\n none: '',\n};\n\n/**\n * Turn one `[@id]` token into a REF field.\n *\n * The cached value is what makes the reference readable outside Word: headless\n * LibreOffice — and therefore the PDF export path — never updates fields, so an\n * uncached REF exports blank. Word recomputes it on open (the document sets\n * `updateFields`), so an approximate cached value is corrected there.\n *\n * `relative` caches the full number: Word resolves it against the reference's\n * own position in the numbering, which generation does not know.\n */\nfunction resolveCrossReference(\n id: string,\n format: CrossReferenceFormat,\n token: string,\n ctx: CompileContext,\n path: string\n): DocxIrInline | undefined {\n const info = ctx.numberedItems.get(id);\n if (!info) {\n warnOnce(\n ctx,\n 'cross-reference',\n `[core-docx] Cross-reference ${token} has no target: no heading or list item declares the id \"${id}\". Rendering the token as literal text.`\n );\n return undefined;\n }\n\n const cachedText =\n format === 'none'\n ? info.text\n : format === 'no_context'\n ? info.own\n : info.full;\n\n if (format !== 'none' && cachedText === undefined) {\n warnOnce(\n ctx,\n 'cross-reference',\n `[core-docx] Cross-reference ${token} targets an unnumbered ${info.kind} (\"${id}\"), so the field carries no cached number and reads blank until the reader updates fields. Use [@${id}:none] to reference its text instead.`\n );\n }\n\n ctx.features.require('cross-references', path);\n return {\n kind: 'field',\n // `\\\\h` makes the field a hyperlink to its target, which is what lets a\n // reader click through to the thing being referenced.\n instruction: `REF ${id} ${['\\\\h', REFERENCE_SWITCH[format]].filter(Boolean).join(' ')}`,\n ...(cachedText !== undefined ? { cachedText } : {}),\n };\n}\n\n/**\n * Bind a component's declared note bodies to the `[^id]` markers in its text.\n *\n * Footnotes and endnotes share the marker syntax and differ only in where Word\n * puts the body, so one resolver serves both: an id is looked up in `footnotes`\n * first, then `endnotes`. Registration is lazy — a body reaches its part only\n * when a marker actually resolves to it — and memoised, so repeating `[^id]`\n * points both references at one note rather than duplicating the body.\n */\nfunction createNoteBinding(\n footnotes: unknown,\n endnotes: unknown,\n ctx: CompileContext\n): NoteBinding | undefined {\n const declared = new Map<string, { text: string; endnote: boolean }>();\n\n /**\n * First declaration wins, in both directions: within one array and across\n * the two. `[^id]` can only mean one note, and letting the last entry win\n * would make the outcome depend on authoring order while silently discarding\n * a body.\n */\n const declare = (note: { id: string; text: string }, endnote: boolean) => {\n const existing = declared.get(note.id);\n if (existing) {\n warnOnce(\n ctx,\n endnote ? 'endnote' : 'footnote',\n existing.endnote === endnote\n ? `Note id \"${note.id}\" is declared twice in the same ` +\n `${endnote ? 'endnotes' : 'footnotes'} array. Using the first ` +\n 'declaration and ignoring the rest.'\n : `Note id \"${note.id}\" is declared as both a footnote and an ` +\n 'endnote in the same paragraph. Using the footnote and ignoring ' +\n 'the endnote.'\n );\n return;\n }\n declared.set(note.id, { text: note.text, endnote });\n };\n\n for (const note of (footnotes ?? []) as { id: string; text: string }[]) {\n declare(note, false);\n }\n for (const note of (endnotes ?? []) as { id: string; text: string }[]) {\n declare(note, true);\n }\n if (declared.size === 0) return undefined;\n\n const registered = new Map<\n string,\n { id: number; noteKind: 'footnote' | 'endnote' }\n >();\n\n return {\n resolve(id: string) {\n const existing = registered.get(id);\n if (existing !== undefined) return existing;\n\n const note = declared.get(id);\n if (note === undefined) {\n // The component declares notes, so `[^id]` was meant as a marker.\n // Leave it literal rather than dropping text, but say so.\n warnOnce(\n ctx,\n 'footnote',\n `Note marker \"[^${id}]\" has no matching entry in this paragraph's ` +\n `footnotes or endnotes (declared: ${[...declared.keys()].join(', ')}). ` +\n 'Rendering the marker as literal text.'\n );\n return undefined;\n }\n\n const bodies = note.endnote ? ctx.endnotes : ctx.footnotes;\n const resolved = {\n id: bodies.length + 1,\n noteKind: note.endnote ? ('endnote' as const) : ('footnote' as const),\n };\n bodies.push({\n id: resolved.id,\n // One paragraph per line, so an author can write a short list.\n children: normalizeUnicodeText(note.text)\n .split('\\n')\n .map((line, index) => ({\n kind: 'paragraph' as const,\n id: `${note.endnote ? 'endnote' : 'footnote'}${resolved.id}:p${index}`,\n path: `${note.endnote ? 'endnotes' : 'footnotes'}[${resolved.id}].children[${index}]`,\n styleId: note.endnote ? 'EndnoteText' : 'FootnoteText',\n children: [{ kind: 'text' as const, text: line }],\n })),\n });\n registered.set(id, resolved);\n ctx.features.require(note.endnote ? 'endnotes' : 'footnotes', 'notes');\n return resolved;\n },\n\n reportUnemitted(text: string) {\n for (const [id, note] of declared) {\n if (registered.has(id)) continue;\n const kind = note.endnote ? 'Endnote' : 'Footnote';\n warnOnce(\n ctx,\n note.endnote ? 'endnote' : 'footnote',\n text.includes(`[^${id}]`)\n ? `${kind} \"${id}\" is declared and its marker appears in the text, ` +\n 'but the marker was not resolved — markers are not recognised ' +\n 'in text that also contains {PLACEHOLDER} substitutions. ' +\n 'The note will not appear in the document.'\n : `${kind} \"${id}\" is declared but never referenced as [^${id}] ` +\n 'in this paragraph. It will not appear in the document.'\n );\n }\n },\n };\n}\n\n/**\n * Say why a revised paragraph's declared notes will not appear.\n *\n * Tracked-change text renders literally, so a marker inside it is never\n * resolved and the body it names is never emitted. Naming the markers that are\n * actually present makes the difference between \"you declared a note you never\n * used\" and \"your note is in the document but will not render\".\n */\nfunction reportNotesInRevision(\n props: Record<string, any>,\n ctx: CompileContext\n): void {\n const declared = [\n ...((props.footnotes ?? []) as { id: string }[]),\n ...((props.endnotes ?? []) as { id: string }[]),\n ];\n if (declared.length === 0) return;\n\n const text = ((props.revision?.segments ?? []) as { text?: string }[])\n .map((segment) => segment.text ?? '')\n .join('');\n const referenced = declared.filter((note) => text.includes(`[^${note.id}]`));\n\n warnOnce(\n ctx,\n 'footnote',\n `Paragraph declares ${declared.length} note(s) (${declared\n .map((note) => note.id)\n .join(', ')}) alongside a \\`revision\\`. Tracked-change text renders ` +\n 'literally, so note markers are not resolved there' +\n (referenced.length > 0\n ? ` — the marker(s) ${referenced\n .map((note) => `[^${note.id}]`)\n .join(', ')} will render as literal text`\n : '') +\n '. The notes will not appear in the document.'\n );\n}\n\ninterface NoteBinding {\n resolve: (\n id: string\n ) => { id: number; noteKind: 'footnote' | 'endnote' } | undefined;\n reportUnemitted: (text: string) => void;\n}\n\n/**\n * Register a comment thread and return the ids its anchors must carry.\n *\n * Every comment in a thread anchors over the same range — root first, then\n * each reply in order — which is how Word writes threads and how it groups\n * them in the review pane.\n */\nfunction declareComment(\n comment: Record<string, any>,\n ctx: CompileContext,\n path: string\n): number[] {\n const resolved = comment.resolved as boolean | undefined;\n const replies = (comment.replies ?? []) as Record<string, any>[];\n // A reply and a resolved state both live in `word/commentsExtended.xml`,\n // which a backend has to write on purpose. Requiring the feature is what\n // stops one that cannot from flattening a thread into unrelated comments.\n if (replies.length > 0 || resolved !== undefined) {\n ctx.features.require('comment-threads', path);\n }\n const rootId = ++ctx.commentCounter;\n const toComment = (\n source: Record<string, any>,\n id: number,\n parentId?: number\n ): DocxIrComment => {\n const author = (source.author as string) || DEFAULT_COMMENT_AUTHOR;\n return {\n id,\n author,\n initials: (source.initials as string) || deriveInitials(author),\n date: String(source.date || DEFAULT_COMMENT_DATE),\n // One paragraph per line, so an author can write a short list.\n children: normalizeUnicodeText(String(source.text ?? ''))\n .split('\\n')\n .map((line, index) => ({\n kind: 'paragraph' as const,\n id: `comment${id}:p${index}`,\n path: `comments[${id}].children[${index}]`,\n children: [{ kind: 'text' as const, text: line }],\n })),\n ...(parentId !== undefined ? { parentId } : {}),\n ...(resolved !== undefined ? { resolved } : {}),\n };\n };\n\n ctx.comments.push(toComment(comment, rootId));\n const ids = [rootId];\n for (const reply of replies) {\n const replyId = ++ctx.commentCounter;\n // Word resolves a thread as a whole, so the flag rides every member.\n ctx.comments.push(toComment(reply, replyId, rootId));\n ids.push(replyId);\n }\n\n if (resolved !== undefined) ctx.hasResolvedComment = true;\n return ids;\n}\n\n/**\n * Initials shown on the comment bubble.\n *\n * Word derives them from the author when the file omits them; doing it here\n * makes the value stable across viewers instead of viewer-dependent.\n */\nfunction deriveInitials(author: string): string {\n const initials = author\n .split(/[\\s._-]+/)\n .filter(Boolean)\n .map((word) => word[0])\n .join('')\n .toUpperCase()\n .slice(0, 3);\n return initials || author.slice(0, 2).toUpperCase();\n}\n\n/** The anchors that close a comment range: each end, then its reference run. */\nfunction closeComment(ids: readonly number[]): DocxIrInline[] {\n return ids.flatMap((id) => [\n { kind: 'commentRangeEnd' as const, id },\n { kind: 'commentReference' as const, id },\n ]);\n}\n\n/**\n * Tracked-change segments, as revision ranges and plain runs.\n *\n * Segment text is literal — no decorators. A `**` opened in one segment could\n * close in another, so per-segment decorator parsing cannot work; the diff\n * engine strips markdown before diffing for the same reason. Placeholders are\n * still resolved, but only in unchanged text: inside an insertion or a deletion\n * they stay as written, because what was changed is the token, not its value.\n *\n * Each emitted run gets its own range, and so its own id, which is what the\n * pipeline has always produced.\n */\nfunction compileRevision(\n revision: Record<string, any>,\n base: DocxIrRunFormatting,\n ctx: CompileContext\n): DocxIrInline[] {\n const author = revision.author || DEFAULT_REVISION_AUTHOR;\n const date = revision.date || DEFAULT_REVISION_DATE;\n const out: DocxIrInline[] = [];\n\n for (const segment of (revision.segments ?? []) as {\n type?: string;\n text?: string;\n }[]) {\n if (!segment.text) continue;\n const text = normalizeUnicodeText(segment.text);\n\n if (segment.type === 'insert' || segment.type === 'delete') {\n for (const line of literalLines(text, base)) {\n out.push({\n kind: 'revision',\n type: segment.type,\n id: ctx.nextRevisionId++,\n author,\n date,\n children: line,\n });\n }\n continue;\n }\n\n // Unchanged text is literal too — the same segment rule applies — unless it\n // carries a placeholder, which is resolved as it would be anywhere else.\n if (containsPlaceholder(text)) {\n out.push(\n ...parseInline(text, {\n base,\n resolvePlaceholder: placeholderResolver(ctx),\n })\n );\n continue;\n }\n for (const line of literalLines(text, base)) out.push(...line);\n }\n\n return out;\n}\n\n/**\n * One run per line, character for character.\n *\n * A revision segment carries no mini-language at all: a `**` opened in one\n * segment could close in another, so nothing inside one can be parsed. Even an\n * empty line becomes a run, because the break is what makes it visible.\n */\nfunction literalLines(\n text: string,\n base: DocxIrRunFormatting\n): DocxIrInline[][] {\n const formatting = Object.keys(base).length > 0 ? base : undefined;\n return text.split('\\n').map((line, index) => [\n ...(index > 0 ? [{ kind: 'lineBreak' as const }] : []),\n {\n kind: 'text' as const,\n text: line,\n ...(formatting ? { formatting } : {}),\n },\n ]);\n}\n\n/**\n * What each built-in `{PLACEHOLDER}` stands for.\n *\n * A page number is a field: only Word knows which page a run lands on, so the\n * document carries the instruction and Word computes it. A date is not — it is\n * resolved once, at generation time, so the document says when it was made\n * rather than when it was opened. An unrecognised name resolves to nothing and\n * stays as the characters the author typed.\n */\nfunction resolvePlaceholder(\n name: string,\n generatedAt: Date\n): PlaceholderResolution | undefined {\n switch (name.toUpperCase()) {\n case 'PAGE':\n return { kind: 'field', instruction: 'PAGE' };\n case 'TOTAL_PAGES':\n return { kind: 'field', instruction: 'NUMPAGES' };\n case 'DATE':\n return { kind: 'text', text: isoDate(generatedAt) };\n case 'DATETIME':\n return { kind: 'text', text: isoDateTime(generatedAt) };\n case 'YEAR':\n return { kind: 'text', text: String(generatedAt.getUTCFullYear()) };\n default:\n return undefined;\n }\n}\n\nfunction isoDate(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nfunction isoDateTime(date: Date): string {\n return date\n .toISOString()\n .replace('T', ' ')\n .replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * Resolve the run formatting shared by every run in a paragraph.\n *\n * A numeric weight, or `bold: true`, resolves to a synthesized family alias —\n * the same rule the rest of the pipeline uses, applied once here so no run has\n * to re-derive it. The family is only stated when the author asked for one, or\n * when aliasing produced a different one; emitting the theme body family on\n * every run would change every document.\n */\nfunction runFormatting(\n font: Record<string, any>,\n props: Record<string, any>,\n ctx: CompileContext\n): DocxIrRunFormatting {\n const hasWeightRequest = font.fontWeight != null || font.bold === true;\n const effectiveFamily =\n font.family ??\n (hasWeightRequest ? resolveBodyFamily(ctx.theme) : undefined);\n\n const weighted = applyFontWeightAlias({\n fontFamily: effectiveFamily,\n bold: font.bold,\n italic: font.italic,\n fontWeight: font.fontWeight,\n });\n\n const formatting: DocxIrRunFormatting = {};\n if (font.family || (weighted.font && weighted.font !== effectiveFamily)) {\n formatting.fontFamily = weighted.font;\n }\n if (font.size) formatting.sizeHalfPoints = pointsToHalfPoints(font.size);\n if (font.color)\n formatting.color = irColor(resolveColor(font.color, ctx.theme));\n if (weighted.bold !== undefined) formatting.bold = weighted.bold;\n if (weighted.italic !== undefined) formatting.italic = weighted.italic;\n if (font.underline !== undefined) {\n formatting.underline = font.underline ? { type: 'single' } : undefined;\n }\n if (font.scale) formatting.scalePercent = font.scale;\n if (font.characterSpacing) {\n const { type, value } = font.characterSpacing as {\n type?: string;\n value: number;\n };\n formatting.characterSpacingTwentieths =\n type === 'condensed' ? -value : value;\n }\n if (props.language) formatting.language = props.language;\n if (props.noProof !== undefined) formatting.noProof = props.noProof;\n\n return formatting;\n}\n\nfunction applyFontWeightAlias(opts: {\n fontFamily?: string;\n bold?: boolean;\n italic?: boolean;\n fontWeight?: number;\n}): { font?: string; bold?: boolean; italic?: boolean } {\n if (!opts.fontFamily) {\n return { bold: opts.bold, italic: opts.italic };\n }\n const weight = opts.fontWeight ?? (opts.bold === true ? 700 : undefined);\n const synth = synthesizeFamilyName(\n opts.fontFamily,\n weight,\n opts.italic === true\n );\n return { font: synth.family, bold: synth.bold, italic: synth.italic };\n}\n\nfunction resolveBodyFamily(theme: ThemeConfig): string | undefined {\n return (theme.fonts as { body?: { family?: string } } | undefined)?.body\n ?.family;\n}\n\nfunction paragraphFormatting(\n props: Record<string, any>,\n ctx: CompileContext,\n extra: {\n outlineLevel?: number;\n alwaysSpacing?: boolean;\n defaultAlignment?: DocxIrParagraphFormatting['alignment'];\n } = {}\n): DocxIrParagraphFormatting | undefined {\n const formatting: DocxIrParagraphFormatting = {};\n\n const alignment = compileAlignment(props.alignment) ?? extra.defaultAlignment;\n if (alignment) formatting.alignment = alignment;\n const spacing = compileSpacing(props, ctx);\n if (spacing) formatting.spacing = spacing;\n else if (extra.alwaysSpacing) formatting.spacing = {};\n if (props.indent) {\n formatting.indent = {\n ...(props.indent.left !== undefined\n ? { leftTwips: props.indent.left }\n : {}),\n ...(props.indent.right !== undefined\n ? { rightTwips: props.indent.right }\n : {}),\n ...(props.indent.firstLine !== undefined\n ? { firstLineTwips: props.indent.firstLine }\n : {}),\n ...(props.indent.hanging !== undefined\n ? { hangingTwips: props.indent.hanging }\n : {}),\n };\n }\n if (Array.isArray(props.tabStops) && props.tabStops.length > 0) {\n formatting.tabStops = props.tabStops.map(\n (stop: { position: number; type?: string; leader?: string }) => ({\n positionTwips: stop.position,\n type: (stop.type ?? 'left') as never,\n ...(stop.leader ? { leader: stop.leader as never } : {}),\n })\n );\n ctx.features.require('tab-stops', 'formatting');\n }\n if (props.keepNext !== undefined) formatting.keepNext = props.keepNext;\n if (props.keepLines !== undefined) formatting.keepLines = props.keepLines;\n if (extra.outlineLevel !== undefined) {\n formatting.outlineLevel = extra.outlineLevel;\n }\n\n return Object.keys(formatting).length > 0 ? formatting : undefined;\n}\n\n/**\n * Authoring alignment, in the IR's vocabulary.\n *\n * Authoring says `justify`; OOXML calls the same thing `both`, which the IR\n * spells `justified`. Anything else an author writes falls back to left — the\n * rule the pipeline has always applied rather than rejecting the value.\n */\nfunction compileAlignment(value: unknown): DocxIrAlignment | undefined {\n if (value === undefined || value === null) return undefined;\n switch (value) {\n case 'center':\n return 'center';\n case 'right':\n return 'right';\n case 'justify':\n return 'justified';\n default:\n return 'left';\n }\n}\n\nfunction compileSpacing(\n props: Record<string, any>,\n ctx: CompileContext\n): DocxIrSpacing | undefined {\n const spacing: DocxIrSpacing = {};\n if (props.spacing?.before !== undefined) {\n spacing.beforeTwips = pointsToTwips(props.spacing.before);\n }\n if (props.spacing?.after !== undefined) {\n spacing.afterTwips = pointsToTwips(props.spacing.after);\n }\n\n // A paragraph carries line spacing inside `font`; a heading states it at the\n // top level. Both spellings are authoring surface, so both are read here.\n const lineSpacing = props.lineSpacing ?? (props.font ?? {}).lineSpacing;\n if (lineSpacing !== undefined) {\n const resolved = compileLineSpacing(lineSpacing);\n if (resolved) {\n if (resolved.lineTwips !== undefined)\n spacing.lineTwips = resolved.lineTwips;\n spacing.lineRule = resolved.lineRule;\n }\n }\n void ctx;\n\n return Object.keys(spacing).length > 0 ? spacing : undefined;\n}\n\n/**\n * Line spacing, in the two forms the authoring surface accepts.\n *\n * A bare number is a multiple of single spacing, which OOXML expresses as\n * 240ths; the named forms map onto the same field with a different rule.\n */\nfunction compileLineSpacing(\n value: unknown\n): { lineTwips?: number; lineRule: DocxIrSpacing['lineRule'] } | undefined {\n if (typeof value === 'number') {\n return { lineTwips: value * SINGLE_LINE_TWIPS, lineRule: 'auto' };\n }\n if (typeof value !== 'object' || value === null) return undefined;\n\n const { type, value: amount } = value as { type?: string; value?: number };\n // A type with no value still states its rule: `atLeast` with nothing to go\n // on means \"at least whatever the style says\", not \"no line spacing\".\n switch (type) {\n case 'single':\n return { lineTwips: SINGLE_LINE_TWIPS, lineRule: 'auto' };\n case 'double':\n return { lineTwips: 2 * SINGLE_LINE_TWIPS, lineRule: 'auto' };\n case 'atLeast':\n return {\n ...(amount !== undefined ? { lineTwips: pointsToTwips(amount) } : {}),\n lineRule: 'atLeast',\n };\n case 'exactly':\n return {\n ...(amount !== undefined ? { lineTwips: pointsToTwips(amount) } : {}),\n lineRule: 'exact',\n };\n case 'multiple':\n return {\n ...(amount !== undefined\n ? { lineTwips: amount * SINGLE_LINE_TWIPS }\n : {}),\n lineRule: 'auto',\n };\n default:\n return undefined;\n }\n}\n\nfunction paragraphStyleId(themeStyle: unknown): string | undefined {\n if (typeof themeStyle !== 'string' || !themeStyle) return undefined;\n const key = themeStyle.toLowerCase();\n if (key === 'normal') return 'Normal';\n if (key === 'title') return 'Title';\n if (key === 'subtitle') return 'Subtitle';\n const heading = /^heading([1-6])$/.exec(key);\n // A paragraph asking for a heading *look* gets the display-only clone, which\n // carries no outline level and so never enters a table of contents.\n if (heading) return `JTD_HeadingText${heading[1]}`;\n return themeStyle;\n}\n\nfunction customOutlineLevel(\n themeStyle: unknown,\n theme: ThemeConfig\n): number | undefined {\n if (typeof themeStyle !== 'string' || !themeStyle) return undefined;\n if (/^heading[1-6]$/.test(themeStyle.toLowerCase())) return undefined;\n const style = (theme.styles as Record<string, unknown> | undefined)?.[\n themeStyle\n ];\n if (style && typeof style === 'object' && 'outlineLevel' in style) {\n return (style as { outlineLevel?: number }).outlineLevel;\n }\n return undefined;\n}\n\nfunction headingLevel(level: unknown): number {\n const value = typeof level === 'number' ? level : 1;\n return value >= 1 && value <= 6 ? value : 1;\n}\n\n/* ------------------------------------------------------------------ *\n * Images\n * ------------------------------------------------------------------ */\n\n/** Image props this slice does not lower. */\nconst UNLOWERED_IMAGE_PROPS = ['comment'] as const;\n\n/**\n * An image, and the caption paragraph that may follow it.\n *\n * The bytes were loaded before compilation started; what happens here is the\n * sizing — a width may be a percentage of the text column or of the page, and a\n * missing dimension is derived from the image's own aspect ratio.\n */\nfunction compileImage(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n\n for (const prop of UNLOWERED_IMAGE_PROPS) {\n if (props[prop] !== undefined) {\n ctx.unsupported.push({ name: 'image', path, detail: prop });\n return [];\n }\n }\n\n const source = resolveImageSource(props);\n if (!source) {\n throw new Error(\n 'Image component requires one of \"path\", \"base64\", or \"svg\" property'\n );\n }\n\n const loaded = ctx.images.get(source);\n if (!loaded) throw new Error(`Failed to load image from ${source}`);\n\n const mediaType = detectImageType(source, loaded.contentType);\n if (mediaType === 'svg') ctx.features.require('svg-images', path);\n\n if (typeof props.alt === 'string' && props.alt) {\n warnOnce(\n ctx,\n 'image',\n `Alt text is not written to the document: the DOCX pipeline has never ` +\n `emitted \\`wp:docPr\\` descriptions, so the image at ${path} will have ` +\n `none. The text is preserved in the IR.`\n );\n }\n\n const size = imagePixelSize(props, loaded, ctx);\n const resourceId = declareResource(loaded, mediaType, ctx);\n\n const image: DocxIrImageRun = {\n kind: 'image',\n resourceId,\n widthEmu: pixelsToEmu(size.width),\n heightEmu: pixelsToEmu(size.height),\n ...(typeof props.alt === 'string' && props.alt\n ? { altText: props.alt }\n : {}),\n ...(props.floating\n ? { floating: compileFloating(props.floating, ctx, path) }\n : {}),\n };\n\n ctx.features.require('images', path);\n if (props.floating) ctx.features.require('floating-images', path);\n\n const spacing: DocxIrSpacing = {};\n if (props.spacing?.before !== undefined) {\n spacing.beforeTwips = pointsToTwips(props.spacing.before);\n }\n if (props.spacing?.after !== undefined) {\n spacing.afterTwips = pointsToTwips(props.spacing.after);\n }\n\n const blocks: DocxIrBlock[] = [\n {\n kind: 'paragraph',\n id: scope.id,\n path,\n children: [image],\n formatting: {\n // A floating image is anchored, so aligning its paragraph would move\n // the anchor rather than the picture.\n ...(props.floating\n ? {}\n : { alignment: compileAlignment(props.alignment) ?? 'center' }),\n ...(Object.keys(spacing).length > 0 ? { spacing } : {}),\n ...(props.keepNext !== undefined ? { keepNext: props.keepNext } : {}),\n ...(props.keepLines !== undefined\n ? { keepLines: props.keepLines }\n : {}),\n },\n },\n ];\n\n if (props.caption) {\n const caption = String(props.caption);\n const syntax = containsUnsupportedSyntax(caption);\n if (syntax) {\n ctx.unsupported.push({ name: 'image', path, detail: syntax });\n return [];\n }\n blocks.push({\n kind: 'paragraph',\n id: `${scope.id}:caption`,\n path: `${path}.caption`,\n styleId: 'Normal',\n // Captions default to left alignment, whatever the figure did.\n formatting: { alignment: 'left' },\n // A caption reaches the parser only when it carries a decorator, which\n // is why a link in an otherwise plain caption stays literal.\n children: DECORATED.test(caption)\n ? parseInline(caption, {\n base: {},\n hyperlinks: true,\n resolvePlaceholder: placeholderResolver(ctx),\n resolveCrossReference: crossReferenceResolver(ctx, path),\n })\n : parseLiteral(caption, { base: {} }),\n });\n }\n\n return blocks;\n}\n\n/**\n * The frames of reference OOXML actually has, per axis.\n *\n * An author may name one OOXML cannot express — `text` vertically, say — and\n * the anchor then states no frame at all rather than an invented one, leaving\n * the backend to apply its own default.\n */\nfunction relativeFrom(\n value: unknown,\n axis: 'horizontal' | 'vertical'\n): string | undefined {\n const allowed =\n axis === 'horizontal'\n ? ['character', 'column', 'margin', 'page']\n : ['margin', 'page', 'paragraph', 'line'];\n return typeof value === 'string' && allowed.includes(value)\n ? value\n : undefined;\n}\n\n/** The alignments OOXML has, per axis. */\nfunction alignValue(\n value: unknown,\n axis: 'horizontal' | 'vertical'\n): string | undefined {\n const allowed =\n axis === 'horizontal'\n ? ['left', 'center', 'right', 'inside', 'outside']\n : ['top', 'center', 'bottom', 'inside', 'outside'];\n return typeof value === 'string' && allowed.includes(value)\n ? value\n : undefined;\n}\n\n/**\n * Authoring wrap types, in OOXML's vocabulary.\n *\n * `around` and `through` are VML spellings with no OOXML element of their own;\n * tight wrapping is the closest thing OOXML has, which is what they have always\n * produced.\n */\nfunction wrapType(value: string): DocxIrTextWrap['type'] {\n switch (value) {\n case 'none':\n return 'none';\n case 'square':\n return 'square';\n case 'topAndBottom':\n return 'topAndBottom';\n case 'around':\n case 'through':\n return 'tight';\n default:\n return 'square';\n }\n}\n\n/**\n * The size the image is drawn at, in pixels.\n *\n * A width defaults to the full measure. Percentages resolve against the text\n * column, or the page when the author said so. Whichever dimension is left\n * unstated comes from the image's own proportions; when those cannot be read,\n * the pre-IR fallbacks stand in — 16:9, or a 7.36cm column.\n */\nfunction imagePixelSize(\n props: Record<string, any>,\n loaded: LoadedImage,\n ctx: CompileContext\n): { width: number; height: number } {\n const widthRef = props.widthRelativeTo === 'page' ? 'page' : 'content';\n const heightRef = props.heightRelativeTo === 'page' ? 'page' : 'content';\n const availableWidthPx = Math.round(\n twipsToPixels(\n widthRef === 'page'\n ? getPageWidthTwips(ctx.theme)\n : getAvailableWidthTwips(ctx.theme)\n )\n );\n const availableHeightPx = Math.round(\n twipsToPixels(\n heightRef === 'page'\n ? getPageHeightTwips(ctx.theme)\n : getAvailableHeightTwips(ctx.theme)\n )\n );\n\n const targetWidth = parseWidthValue(props.width ?? '100%', availableWidthPx);\n const targetHeight =\n props.height !== undefined\n ? parseDimensionValue(props.height, availableHeightPx)\n : undefined;\n\n if (loaded.intrinsic) {\n return calculateMissingDimension(\n loaded.intrinsic.width,\n loaded.intrinsic.height,\n targetWidth,\n targetHeight\n );\n }\n\n return fallbackSize(targetWidth, targetHeight, {\n width: FALLBACK_IMAGE_WIDTH_PX,\n height: FALLBACK_IMAGE_HEIGHT_PX,\n });\n}\n\n/**\n * The size to draw at when the image's own proportions cannot be read.\n *\n * One stated dimension implies the other at 16:9; neither leaves only the\n * caller's fallback box.\n */\nfunction fallbackSize(\n targetWidth: number | undefined,\n targetHeight: number | undefined,\n fallback: { width: number; height: number }\n): { width: number; height: number } {\n if (targetWidth && targetHeight) {\n return { width: targetWidth, height: targetHeight };\n }\n if (targetWidth) {\n return { width: targetWidth, height: Math.round((targetWidth * 9) / 16) };\n }\n if (targetHeight) {\n return { width: Math.round((targetHeight * 16) / 9), height: targetHeight };\n }\n return fallback;\n}\n\n/** 7.36cm at 96dpi — the column width the pipeline falls back to. */\nconst FALLBACK_IMAGE_WIDTH_PX = Math.round(7.36 * 37.795275591);\nconst FALLBACK_IMAGE_HEIGHT_PX = Math.round(FALLBACK_IMAGE_WIDTH_PX * 0.6);\n\n/**\n * Register an image's bytes, reusing a resource with the same content.\n *\n * Identity is the hash, not the source: two components pointing at different\n * URLs that return the same bytes embed once.\n */\nfunction declareResource(\n loaded: LoadedImage,\n mediaType: string,\n ctx: CompileContext\n): string {\n const bytes = new Uint8Array(loaded.bytes);\n const sha256 = sha256Hex(bytes);\n const existing = ctx.resourcesByHash.get(sha256);\n if (existing) return existing;\n\n const id = `res${ctx.resources.length + 1}`;\n ctx.resources.push({\n id,\n kind: 'image',\n mediaType,\n bytes,\n byteLength: bytes.byteLength,\n sha256,\n ...(loaded.intrinsic\n ? {\n intrinsic: {\n widthPx: loaded.intrinsic.width,\n heightPx: loaded.intrinsic.height,\n },\n }\n : {}),\n });\n ctx.resourcesByHash.set(sha256, id);\n return id;\n}\n\n/**\n * A paragraph positioned as a floating box (`w:framePr`).\n *\n * Distinct from a floating drawing: this positions the paragraph itself, so it\n * is measured in twips rather than EMU and has no wrap margins of its own.\n * Exactly one positioning mode applies — absolute if either axis states an\n * offset, alignment otherwise — because OOXML cannot mix them on one frame.\n */\nfunction compileFrame(\n floating: Record<string, any>,\n ctx: CompileContext,\n path: string\n): DocxIrFrame {\n ctx.features.require('text-frames', path);\n const hasHorizontalOffset = floating.horizontalPosition?.offset !== undefined;\n const hasVerticalOffset = floating.verticalPosition?.offset !== undefined;\n const useAbsolute = hasHorizontalOffset || hasVerticalOffset;\n\n const frame: DocxIrFrame = {\n // 2in by 1in when the author gave no size.\n widthTwips: floating.width || 2880,\n heightTwips: floating.height || 1440,\n anchorHorizontal: floating.horizontalPosition?.relative || 'page',\n anchorVertical: floating.verticalPosition?.relative || 'page',\n ...(floating.wrap?.type ? { wrap: floating.wrap.type } : {}),\n };\n\n const anchorLock = floating.lockAnchor ?? floating.anchorLock;\n if (anchorLock !== undefined) frame.anchorLock = anchorLock;\n\n if (useAbsolute) {\n const rawX = floating.horizontalPosition?.offset ?? 0;\n const rawY = floating.verticalPosition?.offset ?? 0;\n if (typeof rawX === 'string' || typeof rawY === 'string') {\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n frame.xTwips = resolveOffsetTwips(\n rawX,\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(ctx.theme, ctx.themeName)\n : getPageWidthTwips(ctx.theme, ctx.themeName)\n );\n frame.yTwips = resolveOffsetTwips(\n rawY,\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(ctx.theme, ctx.themeName)\n : getPageHeightTwips(ctx.theme, ctx.themeName)\n );\n } else {\n frame.xTwips = rawX;\n frame.yTwips = rawY;\n }\n return frame;\n }\n\n frame.xAlign = floating.horizontalPosition?.align ?? 'left';\n frame.yAlign = floating.verticalPosition?.align ?? 'top';\n return frame;\n}\n\n/**\n * Where a floating image sits, in EMU.\n *\n * Both axes are always stated: a drawing anchored on one axis only has no\n * defined position on the other, so the unstated one falls back to the top-left\n * of its natural container.\n */\nfunction compileFloating(\n floating: Record<string, any>,\n ctx: CompileContext,\n path: string\n): DocxIrFloating {\n if (floating.wrap?.type === 'tight') {\n throw new Error(\n \"Image floating wrap.type 'tight' is not supported due to invalid OOXML emitted by docx. Use 'square', 'topAndBottom', or 'none'.\"\n );\n }\n\n const hRelative = floating.horizontalPosition?.relative;\n const vRelative = floating.verticalPosition?.relative;\n const hRef =\n hRelative && hRelative !== 'page'\n ? getAvailableWidthTwips(ctx.theme, ctx.themeName)\n : getPageWidthTwips(ctx.theme, ctx.themeName);\n const vRef =\n vRelative && vRelative !== 'page'\n ? getAvailableHeightTwips(ctx.theme, ctx.themeName)\n : getPageHeightTwips(ctx.theme, ctx.themeName);\n\n const hasHorizontal = Boolean(floating.horizontalPosition);\n const hasVertical = Boolean(floating.verticalPosition);\n\n const position = (\n stated: Record<string, any> | undefined,\n reference: number,\n axis: 'horizontal' | 'vertical',\n fallback: DocxIrFloatingPosition,\n present: boolean\n ): DocxIrFloatingPosition | undefined => {\n if (!stated) return present ? fallback : undefined;\n const relativeTo = relativeFrom(stated.relative, axis);\n const align = alignValue(stated.align, axis);\n return {\n ...(relativeTo ? { relativeTo } : {}),\n ...(align ? { align } : {}),\n ...(stated.offset !== undefined\n ? {\n offsetEmu: twipsToEmu(resolveOffsetTwips(stated.offset, reference)),\n }\n : {}),\n };\n };\n\n const pageWidth = getPageWidthTwips(ctx.theme, ctx.themeName);\n const pageHeight = getPageHeightTwips(ctx.theme, ctx.themeName);\n const rawMargins = floating.wrap?.margins ?? floating.margins;\n const margin = (value: unknown, reference: number): number | undefined =>\n value === undefined\n ? undefined\n : twipsToEmu(resolveOffsetTwips(value as number | string, reference));\n\n // OOXML reads `relativeHeight` as a positive integer, and a backend with no\n // value to use may derive one from the image height — which differs per\n // image and can invalidate the document. So it is always stated.\n let zIndex = floating.zIndex ?? 0;\n if (zIndex < 0) {\n warnOnce(\n ctx,\n 'image',\n `Invalid zIndex value ${zIndex} for floating image at ${path}. Using 0 instead. zIndex must be >= 0.`\n );\n zIndex = 0;\n }\n\n const horizontal = position(\n floating.horizontalPosition,\n hRef,\n 'horizontal',\n { relativeTo: 'margin', align: 'left' },\n hasVertical\n );\n const vertical = position(\n floating.verticalPosition,\n vRef,\n 'vertical',\n { relativeTo: 'paragraph', align: 'top' },\n hasHorizontal\n );\n\n return {\n ...(horizontal ? { horizontal } : {}),\n ...(vertical ? { vertical } : {}),\n ...(floating.wrap\n ? {\n wrap: {\n ...(floating.wrap.type\n ? { type: wrapType(floating.wrap.type) }\n : {}),\n ...(floating.wrap.side ? { side: floating.wrap.side } : {}),\n } as DocxIrTextWrap,\n }\n : {}),\n ...(rawMargins\n ? {\n margins: {\n ...(margin(rawMargins.top, pageHeight) !== undefined\n ? { topEmu: margin(rawMargins.top, pageHeight)! }\n : {}),\n ...(margin(rawMargins.bottom, pageHeight) !== undefined\n ? { bottomEmu: margin(rawMargins.bottom, pageHeight)! }\n : {}),\n ...(margin(rawMargins.left, pageWidth) !== undefined\n ? { leftEmu: margin(rawMargins.left, pageWidth)! }\n : {}),\n ...(margin(rawMargins.right, pageWidth) !== undefined\n ? { rightEmu: margin(rawMargins.right, pageWidth)! }\n : {}),\n },\n }\n : {}),\n ...(floating.allowOverlap !== undefined\n ? { allowOverlap: floating.allowOverlap }\n : {}),\n ...(floating.behindDocument !== undefined\n ? { behindDocument: floating.behindDocument }\n : {}),\n ...(floating.lockAnchor !== undefined\n ? { lockAnchor: floating.lockAnchor }\n : {}),\n ...(floating.layoutInCell !== undefined\n ? { layoutInCell: floating.layoutInCell }\n : {}),\n zIndex,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Tables\n * ------------------------------------------------------------------ */\n\n/**\n * A table.\n *\n * Every cascade — cell over column over table, per border side — and the column\n * grid come from `resolveTableModel`, which the pre-IR writer shares. What is\n * left here is turning each resolved cell into a paragraph and its runs.\n */\nfunction compileTable(\n component: ComponentDefinition,\n scope: ComponentScope\n): DocxIrBlock[] {\n const { ctx, path } = scope;\n const props = (component.props ?? {}) as Record<string, any>;\n const source = tableSource(props);\n\n if (source.columns.length === 0) {\n ctx.unsupported.push({ name: 'table', path, detail: 'no columns' });\n return [];\n }\n\n const style = getTableStyle(ctx.theme, ctx.themeName);\n const model = resolveTableModel<unknown, unknown, unknown>(\n source,\n ctx.theme,\n ctx.themeName,\n { onWarning: (code, message) => warnOnce(ctx, 'table', message, code) }\n );\n\n if (model.overflow) {\n warnOnce(\n ctx,\n 'table',\n `Column widths total (${model.overflow.totalTwips} twips) exceeds available table width (${model.overflow.availableTwips} twips). Table may overflow.`\n );\n }\n\n // A cell may carry an annotation or a nested component this slice does not\n // lower; refusing the whole table beats emitting one with a cell missing.\n const blocker = tableBlocker(model, path);\n if (blocker) {\n ctx.unsupported.push({ name: 'table', ...blocker });\n return [];\n }\n\n const rows: DocxIrTableRow[] = [\n compileTableRow(model.header, style.headerParagraph, style.tableHeader, {\n ctx,\n path: `${path}.header`,\n id: `${scope.id}:h`,\n // Headers repeat across page breaks unless the source disabled it.\n isHeader: model.repeatHeader,\n }),\n ...model.rows.map((row, index) =>\n compileTableRow(row, style.cellParagraph, style.tableCell, {\n ctx,\n path: `${path}.rows[${index}]`,\n id: `${scope.id}:r${index}`,\n ...(row.tableHeader !== undefined ? { isHeader: row.tableHeader } : {}),\n ...(row.cantSplit !== undefined ? { cantSplit: row.cantSplit } : {}),\n })\n ),\n ];\n\n ctx.features.require('tables', path);\n\n return [\n {\n kind: 'table',\n id: scope.id,\n path,\n rows,\n columnGrid: model.columnGrid,\n width:\n model.width.unit === 'twips'\n ? { kind: 'twips', value: model.width.size }\n : { kind: 'percent', value: model.width.size },\n // Fixed layout is what the pipeline has always produced.\n layout: 'fixed',\n },\n ];\n}\n\n/**\n * The table as the model wants it, whichever way the author wrote it.\n *\n * `headers`/`rows` is the original flat shape: a header row and a row of\n * strings each. It has no per-cell or per-column settings, so every cell is\n * given the same explicit defaults the flat shape has always rendered with.\n */\nfunction tableSource(\n props: Record<string, any>\n): TableSource<unknown, unknown, unknown> {\n if (!Array.isArray(props.headers) || !Array.isArray(props.rows)) {\n return { ...props, columns: props.columns ?? [] } as TableSource<\n unknown,\n unknown,\n unknown\n >;\n }\n\n const headers = props.headers as string[];\n const rows = props.rows as string[][];\n const cellDefaults = {\n color: '000000',\n backgroundColor: 'transparent',\n horizontalAlignment: 'left' as const,\n verticalAlignment: 'top' as const,\n font: {\n family: 'Arial',\n size: 11,\n bold: false,\n italic: false,\n underline: false,\n },\n borderColor: '000000',\n borderSize: 1,\n };\n\n return {\n borderColor: '000000',\n borderSize: 1,\n cellDefaults,\n width: 100,\n columns: headers.map((header, colIndex) => ({\n cellDefaults: { ...cellDefaults },\n header: { ...cellDefaults, content: header },\n cells: rows.map((row) => ({\n ...cellDefaults,\n content: row[colIndex] || '',\n })),\n })),\n };\n}\n\n/** The first thing about this table the slice cannot lower, if any. */\nfunction tableBlocker(\n model: ResolvedTable<unknown, unknown, unknown>,\n path: string\n): { path: string; detail: string } | undefined {\n const rows = [model.header, ...model.rows];\n for (const [rowIndex, row] of rows.entries()) {\n const rowPath = row.isHeader\n ? `${path}.header`\n : `${path}.rows[${rowIndex - 1}]`;\n for (const [colIndex, cell] of row.cells.entries()) {\n const cellPath = `${rowPath}.cells[${colIndex}]`;\n const content = cell.content;\n if (content === undefined || typeof content === 'string') {\n if (content && containsUnsupportedSyntax(content)) {\n return {\n path: cellPath,\n detail: containsUnsupportedSyntax(content)!,\n };\n }\n continue;\n }\n // An image or a paragraph is rendered; anything else falls back to a\n // placeholder run, which is content in its own right — the cell says\n // what it could not render rather than going blank.\n if (content.name !== 'paragraph') continue;\n const text = String((content.props as { text?: unknown })?.text ?? '');\n const syntax = containsUnsupportedSyntax(text);\n if (syntax) return { path: cellPath, detail: syntax };\n }\n }\n return undefined;\n}\n\n/** Base run style for a cell, from the theme's table styles. */\ntype TableBaseStyle = ReturnType<typeof getTableStyle>['tableCell'] & {\n bold?: boolean;\n};\n\nfunction compileTableRow(\n row: ResolvedRow<unknown, unknown, unknown>,\n spacing: ReturnType<typeof getTableStyle>['cellParagraph'],\n baseStyle: TableBaseStyle,\n scope: ComponentScope & { isHeader?: boolean; cantSplit?: boolean }\n): DocxIrTableRow {\n const { ctx } = scope;\n const rowRevision = row.revision as RowRevision | undefined;\n\n // Ids are allocated in the order the pipeline has always allocated them:\n // the row's own mark first, then one per cell for the paragraph marks, and\n // only then whatever the cell contents need.\n const rowMark = rowRevision\n ? {\n type: rowRevision.type,\n id: ctx.nextRevisionId++,\n author: rowRevision.author || DEFAULT_REVISION_AUTHOR,\n date: rowRevision.date || DEFAULT_REVISION_DATE,\n }\n : undefined;\n const paragraphMarks = rowRevision\n ? row.cells.map(() => ({\n type: rowRevision.type,\n id: ctx.nextRevisionId++,\n author: rowRevision.author || DEFAULT_REVISION_AUTHOR,\n date: rowRevision.date || DEFAULT_REVISION_DATE,\n }))\n : undefined;\n if (rowRevision) ctx.features.require('revisions', scope.path);\n\n return {\n cells: row.cells.map((cell, colIndex) =>\n compileTableCell(\n cell,\n spacing,\n baseStyle,\n row.keepNext,\n {\n ctx: scope.ctx,\n path: `${scope.path}.cells[${colIndex}]`,\n id: `${scope.id}:c${colIndex}`,\n },\n rowRevision,\n paragraphMarks?.[colIndex]\n )\n ),\n ...(rowMark ? { revision: rowMark } : {}),\n ...(row.height !== undefined\n ? {\n heightTwips: pointsToTwips(row.height),\n heightRule: 'atLeast' as const,\n }\n : {}),\n ...(scope.isHeader !== undefined ? { isHeader: scope.isHeader } : {}),\n ...(scope.cantSplit !== undefined ? { cantSplit: scope.cantSplit } : {}),\n };\n}\n\n/** A structural tracked change on a table row. */\ninterface RowRevision {\n type: 'insert' | 'delete';\n author?: string;\n date?: string;\n}\n\nfunction compileTableCell(\n cell: ResolvedCell<unknown, unknown>,\n spacing: ReturnType<typeof getTableStyle>['cellParagraph'],\n baseStyle: TableBaseStyle,\n keepNext: boolean,\n scope: ComponentScope,\n rowRevision?: RowRevision,\n markRevision?: DocxIrParagraphMarkRevision\n): DocxIrTableCell {\n const paragraph: DocxIrParagraph = {\n kind: 'paragraph',\n id: scope.id,\n path: scope.path,\n // A cell paragraph names no style: it takes its run properties from the\n // cell, not from Normal, so naming one would layer body-prose spacing back\n // on top of the dense table spacing.\n children: cellChildren(cell, baseStyle, scope, rowRevision),\n formatting: {\n alignment: cell.missing\n ? 'left'\n : compileAlignment(cell.horizontalAlignment)!,\n spacing: {\n beforeTwips: spacing.before,\n afterTwips: spacing.after,\n ...(spacing.line !== undefined\n ? { lineTwips: spacing.line, lineRule: lineRule(spacing.lineRule) }\n : {}),\n },\n ...(keepNext ? { keepNext: true } : {}),\n },\n ...(markRevision ? { markRevision } : {}),\n };\n\n return {\n children: [paragraph],\n ...(cell.missing\n ? {}\n : {\n verticalAlign: verticalAlign(cell.verticalAlignment),\n ...(cell.backgroundColor !== undefined &&\n cell.backgroundColor !== 'transparent'\n ? { shading: { fill: { hex: cell.backgroundColor } } }\n : {}),\n ...(cell.padding\n ? {\n margins: {\n topTwips: pointsToTwips(cell.padding.top),\n bottomTwips: pointsToTwips(cell.padding.bottom),\n leftTwips: pointsToTwips(cell.padding.left),\n rightTwips: pointsToTwips(cell.padding.right),\n },\n }\n : {}),\n }),\n borders: {\n top: compileTableBorder(cell.borders.top),\n bottom: compileTableBorder(cell.borders.bottom),\n left: compileTableBorder(cell.borders.left),\n right: compileTableBorder(cell.borders.right),\n },\n };\n}\n\n/**\n * A cell's runs.\n *\n * A cell inside an inserted or deleted row renders as runs marked the same\n * way: a `w:trPr/w:del` alone leaves the text un-struck, and accepting the\n * change would leave an empty row behind rather than removing it. A cell that\n * carries its own revision states it directly.\n */\nfunction cellChildren(\n cell: ResolvedCell<unknown, unknown>,\n baseStyle: TableBaseStyle,\n scope: ComponentScope,\n rowRevision?: RowRevision\n): DocxIrInline[] {\n const { ctx } = scope;\n // A comment on an empty cell still has to anchor somewhere: Word writes a\n // zero-length range plus the reference, so the anchors are placed before the\n // content is known to exist.\n const comment = cell.comment as Record<string, any> | undefined;\n const commentIds = comment\n ? declareComment(comment, ctx, scope.path)\n : undefined;\n const wrap = (children: DocxIrInline[]): DocxIrInline[] =>\n commentIds\n ? [\n ...commentIds.map((id) => ({\n kind: 'commentRangeStart' as const,\n id,\n })),\n ...children,\n ...closeComment(commentIds),\n ]\n : children;\n\n if (cell.missing) return wrap([]);\n\n const content = cell.content;\n const base = cellRunFormatting(cell, baseStyle, ctx);\n if (content !== undefined && typeof content !== 'string') {\n if (content.name === 'image') {\n return wrap(cellImage(content, base, ctx));\n }\n if (content.name !== 'paragraph') {\n // The cell says what it could not render, in the same grey the missing\n // image placeholder uses.\n return wrap([\n {\n kind: 'text',\n text: `[Unsupported component type: ${content.name}]`,\n formatting: placeholderFormatting(base),\n },\n ]);\n }\n }\n\n const text = cellText(cell);\n if (text === undefined) return wrap([]);\n\n const revision =\n (cell.revision as Record<string, any> | undefined) ??\n cellComponentRevision(cell);\n if (revision) {\n ctx.features.require('revisions', '');\n return wrap(compileRevision(revision, base, ctx));\n }\n if (rowRevision) {\n return wrap(\n compileRevision(\n {\n author: rowRevision.author,\n date: rowRevision.date,\n segments: [{ type: rowRevision.type, text }],\n },\n base,\n ctx\n )\n );\n }\n return wrap(\n parseInline(text, {\n base,\n hyperlinks: true,\n resolvePlaceholder: placeholderResolver(ctx),\n resolveCrossReference: crossReferenceResolver(ctx, 'table'),\n })\n );\n}\n\n/**\n * An image inside a table cell.\n *\n * Sized against a notional 300×200 box rather than the page: a cell has no\n * width the compiler can see, and those are the reference dimensions this path\n * has always used. An image that cannot be loaded leaves a placeholder naming\n * its source rather than an empty cell.\n */\nfunction cellImage(\n component: ComponentDefinition,\n base: DocxIrRunFormatting,\n ctx: CompileContext\n): DocxIrInline[] {\n const props = (component.props ?? {}) as Record<string, any>;\n const source = resolveImageSource(props);\n const loaded = source ? ctx.images.get(source) : undefined;\n\n if (!source || !loaded) {\n const preview = String(\n props.svg?.trim() ? 'inline-svg' : props.base64 || props.path || 'unknown'\n );\n return [\n {\n kind: 'text',\n text: `[IMAGE: ${preview.substring(0, 50)}${preview.length > 50 ? '...' : ''}]`,\n formatting: placeholderFormatting(base),\n },\n ];\n }\n\n const targetWidth =\n typeof props.width === 'string'\n ? parseWidthValue(props.width, 300)\n : (props.width as number | undefined);\n const targetHeight =\n typeof props.height === 'string'\n ? parseWidthValue(props.height, 200)\n : (props.height as number | undefined);\n\n const size = loaded.intrinsic\n ? calculateMissingDimension(\n loaded.intrinsic.width,\n loaded.intrinsic.height,\n targetWidth,\n targetHeight\n )\n : fallbackSize(targetWidth, targetHeight, { width: 60, height: 20 });\n\n const mediaType = detectImageType(source, loaded.contentType);\n if (mediaType === 'svg') ctx.features.require('svg-images', 'table');\n ctx.features.require('images', 'table');\n\n return [\n {\n kind: 'image',\n resourceId: declareResource(loaded, mediaType, ctx),\n widthEmu: pixelsToEmu(size.width),\n heightEmu: pixelsToEmu(size.height),\n },\n ];\n}\n\n/** The grey a cell uses to say what it could not render. */\nfunction placeholderFormatting(base: DocxIrRunFormatting): DocxIrRunFormatting {\n return {\n ...(base.fontFamily ? { fontFamily: base.fontFamily } : {}),\n ...(base.sizeHalfPoints !== undefined\n ? { sizeHalfPoints: base.sizeHalfPoints }\n : {}),\n color: irColor('#999999'),\n };\n}\n\n/** A revision stated on the `paragraph` component inside a cell. */\nfunction cellComponentRevision(\n cell: ResolvedCell<unknown, unknown>\n): Record<string, any> | undefined {\n const content = cell.content;\n if (content === undefined || typeof content === 'string') return undefined;\n return (content.props as { revision?: Record<string, any> })?.revision;\n}\n\n/**\n * The text a cell renders.\n *\n * A cell holding a `paragraph` renders that paragraph's text; a cell holding\n * nothing renders nothing at all, which is not the same as rendering an empty\n * string — an empty string still produces a run.\n */\nfunction cellText(cell: ResolvedCell<unknown, unknown>): string | undefined {\n const content = cell.content;\n if (content === undefined || content === '') return undefined;\n if (typeof content === 'string') return content;\n return String((content.props as { text?: unknown })?.text ?? '');\n}\n\n/**\n * The run formatting a cell's text starts from.\n *\n * The cell's own font wins over the theme's table style, and a numeric weight\n * resolves to the synthesized family alias exactly as it does in body text.\n */\nfunction cellRunFormatting(\n cell: ResolvedCell<unknown, unknown>,\n baseStyle: TableBaseStyle,\n ctx: CompileContext\n): DocxIrRunFormatting {\n const content = cell.content;\n const componentFont =\n content !== undefined && typeof content !== 'string'\n ? (content.props as { font?: Record<string, any> })?.font ?? undefined\n : undefined;\n\n const weighted = applyFontWeightAlias({\n fontFamily: cell.font?.family || baseStyle.font,\n bold: cell.font?.bold ?? false,\n italic: cell.font?.italic ?? false,\n fontWeight: cell.font?.fontWeight,\n });\n\n const formatting: DocxIrRunFormatting = {\n ...(weighted.font ? { fontFamily: weighted.font } : {}),\n sizeHalfPoints: cell.font?.size ? cell.font.size * 2 : baseStyle.size,\n bold: weighted.bold ?? false,\n italic: weighted.italic ?? false,\n ...(cell.font?.underline ? { underline: { type: 'single' } } : {}),\n ...(cell.color || baseStyle.color\n ? { color: irColor(cell.color || baseStyle.color) }\n : {}),\n };\n\n if (!componentFont) return formatting;\n\n // A paragraph component inside the cell layers its own font on top.\n const paraWeighted = applyFontWeightAlias({\n fontFamily: componentFont.family ?? formatting.fontFamily,\n bold: componentFont.bold,\n italic: componentFont.italic,\n fontWeight: componentFont.fontWeight,\n });\n\n return {\n ...formatting,\n ...(paraWeighted.font ? { fontFamily: paraWeighted.font } : {}),\n ...(componentFont.size ? { sizeHalfPoints: componentFont.size * 2 } : {}),\n ...(paraWeighted.bold !== undefined ? { bold: paraWeighted.bold } : {}),\n ...(paraWeighted.italic !== undefined\n ? { italic: paraWeighted.italic }\n : {}),\n ...(componentFont.underline !== undefined\n ? {\n underline: componentFont.underline\n ? { type: 'single' as const }\n : undefined,\n }\n : {}),\n ...(componentFont.color\n ? { color: irColor(resolveColor(componentFont.color, ctx.theme)) }\n : {}),\n };\n}\n\n/**\n * One side of a cell border.\n *\n * A zero size and a hidden side are the same thing to OOXML — `none` — and the\n * distinction between them is only meaningful to the author.\n */\nfunction compileTableBorder(border: ResolvedBorder): DocxIrBorder {\n if (border.size === 0 || border.hidden) {\n return { style: 'none', sizeEighthPoints: 0, color: { hex: '000000' } };\n }\n return {\n style: 'single',\n sizeEighthPoints: pointsToEighthPoints(border.size),\n color: irColor(border.color || '000000'),\n };\n}\n\nfunction verticalAlign(\n value: 'top' | 'middle' | 'bottom'\n): DocxIrVerticalAlign {\n return value === 'middle' ? 'center' : value;\n}\n\n/** The theme's line rule, in the IR's vocabulary. */\nfunction lineRule(value: unknown): DocxIrSpacing['lineRule'] {\n if (value === 'exactly' || value === 'exact') return 'exact';\n if (value === 'atLeast') return 'atLeast';\n return 'auto';\n}\n\n/**\n * Report a warning once per compilation, keyed by its message.\n *\n * Collected either way, and echoed to the console when the caller supplied no\n * collector of its own — the same contract `reportWarning` gives every other\n * leaf in the pipeline. Without the echo a warning a caller never asked to\n * collect would simply disappear.\n */\nfunction warnOnce(\n ctx: CompileContext,\n component: string,\n message: string,\n code?: string\n): void {\n if (ctx.warnedMessages.has(message)) return;\n ctx.warnedMessages.add(message);\n ctx.warnings.push({\n component,\n message,\n severity: 'warning',\n ...(code ? { context: { code } } : {}),\n });\n if (ctx.echoWarnings) {\n // eslint-disable-next-line no-console\n console.warn(code ? `[json-to-docx] ${code}: ${message}` : message);\n }\n}\n","/**\n * A theme, compiled into the document's style set.\n *\n * The output is DocxIR: style ids and their resolved formatting, in the units\n * OOXML uses, naming no backend. Both adapters map it to their own option\n * shape, so which styles a document defines — and what each one says — is\n * decided once, here, rather than once per renderer.\n */\n\nimport { getTheme } from '../templates/themes';\n\n/**\n * A right tab at the text-measure edge, which is where a TOC page number sits.\n *\n * Twice `TabStopPosition.MAX` (9026 twips) — the historical value, kept\n * because it is what every recorded document was produced with.\n */\nconst RIGHT_MARGIN_TAB_TWIPS = 9026 * 2;\nimport type {\n DocxIrAlignment,\n DocxIrBorder,\n DocxIrBorders,\n DocxIrCharacterStyle,\n DocxIrParagraphFormatting,\n DocxIrParagraphStyle,\n DocxIrRunFormatting,\n DocxIrStyles,\n DocxIrTabStop,\n} from '../ir/types';\nimport type { ThemeConfig } from './index';\nimport { resolveColor } from './utils/colorUtils';\nimport {\n convertLineSpacing,\n pointsToTwips,\n resolveFontProperties,\n mergeFontAndStyleProperties,\n} from './utils/styleHelpers';\n\n// Border types for paragraph borders in theme styles\ninterface ThemeBorderDefinition {\n style: string; // e.g., 'single', 'double', 'dotted', etc.\n size: number; // width in eighths of a point (docx sz)\n color: string; // hex or theme color key\n space?: number; // space in points\n}\n\ninterface ThemeBorders {\n top?: ThemeBorderDefinition;\n bottom?: ThemeBorderDefinition;\n left?: ThemeBorderDefinition;\n right?: ThemeBorderDefinition;\n /** w:between — the rule between consecutive paragraphs sharing this set. */\n between?: ThemeBorderDefinition;\n}\n\n// Style properties for various text elements\ninterface StyleProperties {\n font?: 'heading' | 'body' | 'mono' | 'light';\n size?: number;\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n alignment?: 'left' | 'center' | 'right' | 'justify';\n lineSpacing?: {\n type: 'single' | 'atLeast' | 'exactly' | 'double' | 'multiple';\n value?: number;\n };\n spacing?: {\n before?: number;\n after?: number;\n };\n characterSpacing?: { type: 'condensed' | 'expanded'; value: number };\n scale?: number;\n priority?: number;\n baseStyle?: string;\n followingStyle?: string;\n widowControl?: boolean;\n keepNext?: boolean;\n keepLinesTogether?: boolean;\n outlineLevel?: number;\n borders?: ThemeBorders;\n indent?: {\n left?: number;\n hanging?: number;\n };\n}\n\n/**\n * Type-safe style name union\n */\ntype StyleName =\n | 'normal'\n | 'heading1'\n | 'heading2'\n | 'heading3'\n | 'heading4'\n | 'heading5'\n | 'heading6'\n | 'title'\n | 'subtitle';\n\n/**\n * Type guard to check if a style name is valid\n */\nfunction isValidStyleName(name: string): name is StyleName {\n return [\n 'normal',\n 'heading1',\n 'heading2',\n 'heading3',\n 'heading4',\n 'heading5',\n 'heading6',\n 'title',\n 'subtitle',\n ].includes(name);\n}\n\n/**\n * Type-safe style getter with proper error handling\n */\nfunction getStyleSafe(\n theme: ThemeConfig,\n styleName: string\n): StyleProperties | undefined {\n if (!isValidStyleName(styleName)) {\n console.warn(`Invalid style name: ${styleName}`);\n return undefined;\n }\n return theme.styles?.[styleName] as StyleProperties | undefined;\n}\n\n/**\n * Resolves a style with baseStyle inheritance.\n * If a style has a baseStyle property, recursively resolves the base style first\n * and merges its properties with the current style (current overrides base).\n *\n * @param theme - Theme configuration\n * @param styleName - Name of the style to resolve\n * @param visited - Set of visited style names to prevent circular references\n * @returns Resolved style with all inherited properties, or undefined if not found\n */\nfunction resolveStyleWithBaseStyle(\n theme: ThemeConfig,\n styleName: string,\n visited: Set<string> = new Set()\n): StyleProperties | undefined {\n // Prevent circular references\n if (visited.has(styleName)) {\n console.warn(\n `Circular baseStyle reference detected: ${Array.from(visited).join(\n ' → '\n )} → ${styleName}`\n );\n return undefined;\n }\n\n visited.add(styleName);\n\n // Use type-safe getter instead of type assertion\n const style = getStyleSafe(theme, styleName);\n if (!style) {\n return undefined;\n }\n\n // If no baseStyle, return style as-is\n if (!style.baseStyle) {\n return style;\n }\n\n // Recursively resolve base style\n const baseStyle = resolveStyleWithBaseStyle(\n theme,\n style.baseStyle,\n new Set(visited) // Pass copy to allow different branches\n );\n\n if (!baseStyle) {\n // If baseStyle doesn't exist, just return current style\n return style;\n }\n\n // Merge: base properties first, then override with current style properties\n // Filter out undefined values from current style to preserve base style values\n const mergedStyle = mergeFontAndStyleProperties(\n baseStyle,\n style\n ) as StyleProperties;\n\n // Manually merge properties not covered by mergeFontAndStyleProperties\n // Borders: inherit from baseStyle unless explicitly provided in current style\n if (style.borders === undefined && baseStyle.borders !== undefined) {\n mergedStyle.borders = baseStyle.borders;\n } else if (style.borders !== undefined) {\n mergedStyle.borders = style.borders;\n }\n\n return mergedStyle;\n}\n\nfunction convertAlignment(alignment: string): DocxIrAlignment {\n switch (alignment) {\n case 'center':\n return 'center';\n case 'right':\n return 'right';\n case 'justify':\n return 'justified';\n default:\n return 'left';\n }\n}\n\n/**\n * Resolve spacing from new nested format\n */\nfunction resolveSpacing(spacing?: { before?: number; after?: number }): {\n beforeTwips?: number;\n afterTwips?: number;\n} {\n return {\n ...(spacing?.before ? { beforeTwips: pointsToTwips(spacing.before) } : {}),\n ...(spacing?.after ? { afterTwips: pointsToTwips(spacing.after) } : {}),\n };\n}\n\n/**\n * Convert merged style properties to docx run properties\n */\nfunction convertRunProperties(\n merged: any,\n theme: ThemeConfig,\n defaultColor?: string,\n defaultSize?: number\n): DocxIrRunFormatting {\n return {\n fontFamily: merged.family || 'Arial',\n sizeHalfPoints: (merged.size || defaultSize || 11) * 2,\n color: {\n hex: resolveColor(\n merged.color || defaultColor || theme.colors.text,\n theme\n ),\n },\n ...(merged.bold !== undefined && { bold: merged.bold }),\n ...(merged.italic !== undefined && { italic: merged.italic }),\n ...(merged.underline !== undefined &&\n merged.underline && { underline: { type: 'single' } }),\n ...(merged.characterSpacing && {\n characterSpacingTwentieths:\n merged.characterSpacing.type === 'condensed'\n ? -merged.characterSpacing.value\n : merged.characterSpacing.value,\n }),\n ...(merged.scale && { scalePercent: merged.scale }),\n };\n}\n\n/** `convertLineSpacing`'s result, in the IR's vocabulary. */\nfunction irLineSpacing(lineSpacing?: unknown): {\n lineTwips?: number;\n lineRule?: 'auto' | 'exact' | 'atLeast';\n} {\n const converted = convertLineSpacing(lineSpacing as never);\n if (!converted) return {};\n return {\n ...(typeof converted.line === 'number'\n ? { lineTwips: converted.line }\n : {}),\n ...(converted.lineRule\n ? { lineRule: converted.lineRule as 'auto' | 'exact' | 'atLeast' }\n : {}),\n };\n}\n\n/**\n * Convert merged style properties to docx paragraph properties\n */\nfunction convertParagraphProperties(\n merged: any,\n styleProps?: StyleProperties,\n theme?: ThemeConfig\n): DocxIrParagraphFormatting {\n return {\n spacing: {\n ...resolveSpacing(merged.spacing),\n ...irLineSpacing(merged.lineSpacing),\n },\n alignment: convertAlignment(merged.alignment || 'left'),\n ...(styleProps?.keepNext !== undefined && {\n keepNext: styleProps.keepNext,\n }),\n ...(styleProps?.keepLinesTogether !== undefined && {\n keepLines: styleProps.keepLinesTogether,\n }),\n ...(styleProps?.widowControl !== undefined && {\n widowControl: styleProps.widowControl,\n }),\n ...(styleProps?.outlineLevel !== undefined && {\n outlineLevel: styleProps.outlineLevel,\n }),\n ...(styleProps?.borders &&\n theme && {\n borders: convertBorders(styleProps.borders, theme),\n }),\n ...(styleProps?.indent && {\n indent: {\n ...(styleProps.indent.left !== undefined && {\n leftTwips: styleProps.indent.left,\n }),\n ...(styleProps.indent.hanging !== undefined && {\n hangingTwips: styleProps.indent.hanging,\n }),\n },\n }),\n };\n}\n\n/**\n * Convert theme border definitions to docx paragraph border options\n */\nfunction convertBorders(\n borders: ThemeBorders | undefined,\n theme: ThemeConfig\n): DocxIrBorders | undefined {\n if (!borders) return undefined;\n\n const mapSide = (side?: ThemeBorderDefinition): DocxIrBorder | undefined =>\n side\n ? {\n style: side.style,\n sizeEighthPoints: side.size,\n color: { hex: resolveColor(side.color, theme) },\n ...(side.space !== undefined ? { spacePoints: side.space } : {}),\n }\n : undefined;\n\n const sides: (keyof ThemeBorders)[] = [\n 'top',\n 'bottom',\n 'left',\n 'right',\n 'between',\n ];\n const converted: DocxIrBorders = {};\n for (const side of sides) {\n const value = mapSide(borders[side]);\n if (value) converted[side] = value;\n }\n\n return Object.keys(converted).length > 0 ? converted : undefined;\n}\n\n/**\n * Compile a theme into the document's style set.\n *\n * @param themeNameOrObject The theme to use for styling (name string or theme object)\n * @param language Document-default proofing language (BCP-47)\n */\n/**\n * The run a fallback style uses when the theme declares nothing for it.\n *\n * Only the font's own properties are read, so `bold`/`italic`/`underline`\n * appear only when the font declares them — which is why this is not\n * `convertRunProperties` with an empty style.\n */\nfunction fallbackRun(\n fontProps: any,\n theme: ThemeConfig,\n defaultColor: string,\n defaultSize: number\n): DocxIrRunFormatting {\n return {\n fontFamily: fontProps.family || 'Arial',\n sizeHalfPoints: (fontProps.size || defaultSize) * 2,\n color: { hex: resolveColor(fontProps.color || defaultColor, theme) },\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n ...(fontProps.underline !== undefined &&\n fontProps.underline && { underline: { type: 'single' } }),\n };\n}\n\n/** Header and footer runs, which pin their own size rather than inherit one. */\nfunction chromeRun(\n fontProps: any,\n theme: ThemeConfig,\n sizeHalfPoints: number\n): DocxIrRunFormatting {\n return {\n fontFamily: fontProps.family || 'Arial',\n sizeHalfPoints,\n color: {\n hex: resolveColor(fontProps.color || theme.colors.secondary, theme),\n },\n ...(fontProps.bold !== undefined && { bold: fontProps.bold }),\n ...(fontProps.italic !== undefined && { italic: fontProps.italic }),\n };\n}\n\nexport function createDocumentStyles(\n themeNameOrObject: string | ThemeConfig = 'minimal',\n language?: string\n): DocxIrStyles {\n const theme: ThemeConfig =\n typeof themeNameOrObject === 'string'\n ? getTheme(themeNameOrObject) || getTheme('minimal')!\n : themeNameOrObject;\n\n const paragraphStyles: DocxIrParagraphStyle[] = [\n // Normal body text style\n {\n id: 'Normal',\n name: 'Normal',\n quickFormat: true,\n run: (() => {\n const normalStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const fontProps = resolveFontProperties(theme, normalStyle?.font);\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: normalStyle?.size,\n color: normalStyle?.color,\n bold: normalStyle?.bold,\n italic: normalStyle?.italic,\n underline: normalStyle?.underline,\n characterSpacing: normalStyle?.characterSpacing,\n scale: normalStyle?.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.text);\n })(),\n paragraph: (() => {\n const normalStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const fontProps = resolveFontProperties(theme, normalStyle?.font);\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: normalStyle?.alignment,\n lineSpacing: normalStyle?.lineSpacing,\n spacing: normalStyle?.spacing,\n });\n\n return convertParagraphProperties(merged, normalStyle, theme);\n })(),\n },\n ];\n\n // Generate heading styles from theme configuration\n for (let i = 1; i <= 6; i++) {\n const headingKey = `heading${i}` as keyof typeof theme.styles;\n const rawHeadingStyle = theme.styles?.[headingKey] as\n | StyleProperties\n | undefined;\n\n if (rawHeadingStyle) {\n const headingStyle =\n resolveStyleWithBaseStyle(theme, headingKey) || rawHeadingStyle;\n paragraphStyles.push({\n id: `Heading${i}`,\n name: `Heading ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: headingStyle.size,\n color: headingStyle.color,\n bold: headingStyle.bold,\n italic: headingStyle.italic,\n underline: headingStyle.underline,\n characterSpacing: headingStyle.characterSpacing,\n scale: headingStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: headingStyle.alignment,\n lineSpacing: headingStyle.lineSpacing,\n spacing: headingStyle.spacing,\n });\n\n return convertParagraphProperties(merged, headingStyle, theme);\n })(),\n });\n } else {\n // Fallback heading style if not defined in theme\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: `Heading${i}`,\n name: `Heading ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: fallbackRun(fontProps, theme, theme.colors.primary, 20),\n paragraph: {\n spacing: {\n beforeTwips: 240 - (i - 1) * 40,\n afterTwips: 120 - (i - 1) * 20,\n ...irLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n }\n\n // Generate display-only heading styles for text components (non-TOC, non-outline)\n for (let i = 1; i <= 6; i++) {\n const headingKey = `heading${i}` as keyof typeof theme.styles;\n const rawHeadingStyle = theme.styles?.[headingKey] as\n | StyleProperties\n | undefined;\n\n if (rawHeadingStyle) {\n const headingStyle =\n resolveStyleWithBaseStyle(theme, `heading${i}`) || rawHeadingStyle;\n\n paragraphStyles.push({\n id: `JTD_HeadingText${i}`,\n name: `Heading Text ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: headingStyle.size,\n color: headingStyle.color,\n bold: headingStyle.bold,\n italic: headingStyle.italic,\n underline: headingStyle.underline,\n characterSpacing: headingStyle.characterSpacing,\n scale: headingStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n headingStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: headingStyle.alignment,\n lineSpacing: headingStyle.lineSpacing,\n spacing: headingStyle.spacing,\n });\n\n // Explicitly drop outlineLevel to avoid TOC participation\n return convertParagraphProperties(\n merged,\n { ...(headingStyle as any), outlineLevel: undefined },\n theme\n );\n })(),\n });\n } else {\n // Fallback display heading style mirrors fallback heading visuals\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: `JTD_HeadingText${i}`,\n name: `Heading Text ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: fallbackRun(fontProps, theme, theme.colors.primary, 20),\n paragraph: {\n spacing: {\n beforeTwips: 240 - (i - 1) * 40,\n afterTwips: 120 - (i - 1) * 20,\n ...irLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n }\n\n // Add Title style from theme configuration\n if (theme.styles?.title) {\n const titleStyle =\n resolveStyleWithBaseStyle(theme, 'title') || theme.styles.title;\n paragraphStyles.push({\n id: 'Title',\n name: 'Title',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n titleStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: titleStyle.size,\n color: titleStyle.color,\n bold: titleStyle.bold,\n italic: titleStyle.italic,\n underline: titleStyle.underline,\n characterSpacing: titleStyle.characterSpacing,\n scale: titleStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.primary, 20);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n titleStyle.font || 'heading'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: titleStyle.alignment,\n lineSpacing: titleStyle.lineSpacing,\n spacing: titleStyle.spacing,\n });\n\n return convertParagraphProperties(merged, titleStyle, theme);\n })(),\n });\n } else {\n // Fallback title style if no theme configuration\n const fontProps = resolveFontProperties(theme, 'heading');\n paragraphStyles.push({\n id: 'Title',\n name: 'Title',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: fallbackRun(fontProps, theme, theme.colors.primary, 20),\n paragraph: {\n spacing: {\n afterTwips: 400,\n ...irLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n\n // Add Subtitle style from theme configuration\n if (theme.styles?.subtitle) {\n const subtitleStyle =\n resolveStyleWithBaseStyle(theme, 'subtitle') || theme.styles.subtitle;\n paragraphStyles.push({\n id: 'Subtitle',\n name: 'Subtitle',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n subtitleStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: subtitleStyle.size,\n color: subtitleStyle.color,\n bold: subtitleStyle.bold,\n italic: subtitleStyle.italic,\n underline: subtitleStyle.underline,\n characterSpacing: subtitleStyle.characterSpacing,\n scale: subtitleStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.secondary);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n subtitleStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: subtitleStyle.alignment,\n lineSpacing: subtitleStyle.lineSpacing,\n spacing: subtitleStyle.spacing,\n });\n\n return convertParagraphProperties(merged, subtitleStyle, theme);\n })(),\n });\n } else {\n // Fallback subtitle style if no theme configuration\n const fontProps = resolveFontProperties(theme, 'body');\n paragraphStyles.push({\n id: 'Subtitle',\n name: 'Subtitle',\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: true,\n run: fallbackRun(fontProps, theme, theme.colors.secondary, 11),\n paragraph: {\n spacing: {\n afterTwips: 600,\n ...irLineSpacing(fontProps.lineSpacing),\n },\n alignment: convertAlignment(fontProps.alignment || 'left'),\n },\n });\n }\n\n paragraphStyles.push(\n // Header style\n (() => {\n const fontProps = resolveFontProperties(theme, 'body');\n return {\n id: 'Header',\n name: 'Header',\n basedOn: 'Normal',\n next: 'Header',\n quickFormat: false,\n run: chromeRun(fontProps, theme, 20),\n paragraph: {\n alignment: 'right',\n },\n };\n })(),\n\n // Footer style\n (() => {\n const fontProps = resolveFontProperties(theme, 'body');\n return {\n id: 'Footer',\n name: 'Footer',\n basedOn: 'Normal',\n next: 'Footer',\n quickFormat: false,\n run: chromeRun(fontProps, theme, 18),\n paragraph: {\n spacing: {\n beforeTwips: 120,\n },\n alignment: 'center',\n // Note: Borders are applied at the paragraph instance level, not in style definitions\n },\n };\n })()\n );\n\n // Process custom styles (any additional keys in theme.styles beyond predefined ones)\n const predefinedStyleKeys = new Set([\n 'normal',\n 'heading1',\n 'heading2',\n 'heading3',\n 'heading4',\n 'heading5',\n 'heading6',\n 'title',\n 'subtitle',\n ]);\n\n if (theme.styles) {\n for (const [styleKey, styleValue] of Object.entries(theme.styles)) {\n // Skip predefined styles (already processed above)\n if (predefinedStyleKeys.has(styleKey)) {\n continue;\n }\n\n // Skip if styleValue is not defined\n if (!styleValue) {\n continue;\n }\n\n // Generate Word-compatible style ID and name\n // Special-case TOC styles to the canonical Word display name (e.g., 'TOC 1')\n const tocMatch = /^TOC([1-9])$/.exec(styleKey);\n\n // For TOC styles, DO NOT resolve baseStyle inheritance to prevent coupling with Heading styles\n // TOC styles should only use their explicitly defined properties\n const customStyle = tocMatch\n ? styleValue\n : resolveStyleWithBaseStyle(theme, styleKey) || styleValue;\n // Canonical Word style id. docx hardcodes `w:pStyle w:val=\"TOC{level}\"`\n // when it writes cached TOC entries, so a namespaced id would leave those\n // entries unstyled. docx's own default styles define no TOC id, so there\n // is nothing to collide with.\n const styleId = tocMatch ? `TOC${tocMatch[1]}` : styleKey;\n const styleName = tocMatch\n ? `TOC ${tocMatch[1]}`\n : styleKey.replace(/([A-Z])/g, ' $1').trim(); // Convert camelCase/PascalCase to Title Case\n\n // Helper: map baseStyle (theme key) to Word style ID\n const mapBaseStyleId = (base?: string) => {\n if (!base) return 'Normal';\n const lower = base.toLowerCase();\n if (lower === 'normal') return 'Normal';\n if (lower === 'title') return 'Title';\n if (lower === 'subtitle') return 'Subtitle';\n const m = lower.match(/^heading([1-6])$/);\n if (m) return `Heading${m[1]}`;\n // Assume custom style ID (already registered with same id)\n return base;\n };\n\n paragraphStyles.push({\n id: styleId,\n name: styleName,\n basedOn: tocMatch\n ? 'Normal'\n : mapBaseStyleId((customStyle as StyleProperties).baseStyle),\n next: customStyle.followingStyle || 'Normal',\n quickFormat: tocMatch\n ? false\n : customStyle.priority !== undefined\n ? true\n : false,\n run: (() => {\n const fontProps = resolveFontProperties(\n theme,\n customStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n size: customStyle.size,\n color: customStyle.color,\n bold: customStyle.bold,\n italic: customStyle.italic,\n underline: customStyle.underline,\n characterSpacing: customStyle.characterSpacing,\n scale: customStyle.scale,\n });\n\n return convertRunProperties(merged, theme, theme.colors.text);\n })(),\n paragraph: (() => {\n const fontProps = resolveFontProperties(\n theme,\n customStyle.font || 'body'\n );\n const merged = mergeFontAndStyleProperties(fontProps, {\n alignment: customStyle.alignment,\n lineSpacing: customStyle.lineSpacing,\n spacing: customStyle.spacing,\n });\n\n // Build base properties using converter\n const baseProps = convertParagraphProperties(\n merged,\n // Don't pass outlineLevel for TOC styles\n tocMatch\n ? { ...customStyle, outlineLevel: undefined }\n : customStyle,\n theme\n );\n\n // Add TOC-specific tab stops if needed\n const tabStops = (customStyle as any).tabStops;\n const defaultTocTabStops = tocMatch\n ? [{ type: 'right', position: 'max', leader: 'none' }]\n : undefined;\n const effectiveTabStops =\n tabStops && tabStops.length > 0 ? tabStops : defaultTocTabStops;\n\n return {\n ...baseProps,\n ...(effectiveTabStops && {\n tabStops: effectiveTabStops.map(\n (ts: any): DocxIrTabStop => ({\n type: ts.type,\n positionTwips:\n ts.position === 'max'\n ? RIGHT_MARGIN_TAB_TWIPS\n : ts.position,\n ...(ts.leader && { leader: ts.leader }),\n })\n ),\n }),\n };\n })(),\n });\n }\n }\n\n // Generate TOC level styles (TOC 1..6) using fixed, sober defaults.\n // These defaults do not depend on theme heading styles.\n for (let i = 1; i <= 6; i++) {\n // Skip if user already provided a custom TOC style via theme.styles (id must be 'TOC1'..'TOC6')\n if (\n theme.styles &&\n Object.prototype.hasOwnProperty.call(theme.styles, `TOC${i}`)\n ) {\n continue;\n }\n\n paragraphStyles.push({\n // Canonical id and display name — see the styleId note above.\n id: `TOC${i}`,\n name: `TOC ${i}`,\n basedOn: 'Normal',\n next: 'Normal',\n quickFormat: false,\n run: {\n fontFamily: 'Arial',\n sizeHalfPoints: 22, // 11pt\n color: { hex: resolveColor(theme.colors.text, theme) },\n },\n paragraph: {\n spacing: {\n ...resolveSpacing({ before: 0, after: 6 }), // 0pt before, 6pt after\n },\n alignment: convertAlignment('left'),\n // Increase left indent per level for visual hierarchy\n indent: { leftTwips: (i - 1) * 360 }, // 0.25\" per level (360 twips)\n },\n });\n }\n\n // Note styles: docx ships built-in Footnote/Endnote Text and Reference\n // styles, but they carry Word's defaults, not the theme's — a note in a\n // Georgia document would otherwise set in Calibri. All four hooks live under\n // the `default` key, which is why that key is now always built rather than\n // being emitted only when a document language is set.\n const noteStyle =\n resolveStyleWithBaseStyle(theme, 'normal') || theme.styles?.normal;\n const bodyRun = convertRunProperties(\n mergeFontAndStyleProperties(resolveFontProperties(theme, noteStyle?.font), {\n size: noteStyle?.size,\n color: noteStyle?.color,\n }),\n theme,\n theme.colors.text\n );\n // Word's convention is note text two points below body text. `size` is in\n // half-points here, so that is four — floored so a tiny body size cannot\n // produce an illegible note.\n const noteRun: DocxIrRunFormatting = {\n ...bodyRun,\n ...(typeof bodyRun.sizeHalfPoints === 'number' && {\n sizeHalfPoints: Math.max(12, bodyRun.sizeHalfPoints - 4),\n }),\n };\n\n return {\n // Document defaults (`w:docDefaults`). A run that states no `w:lang` of its\n // own inherits this, so Word proofs the whole document in the requested\n // language unless a component overrides it.\n defaults: {\n run: { ...(language ? { language } : {}) },\n paragraph: {},\n },\n paragraph: paragraphStyles,\n character: [] as DocxIrCharacterStyle[],\n // Run properties only: the note paragraph defaults a backend already ships\n // (single line spacing, no space after) are what a note wants, and an empty\n // spacing override would drop its line rule.\n builtIn: {\n footnoteText: { run: noteRun },\n footnoteReference: { run: { ...noteRun, superScript: true } },\n endnoteText: { run: noteRun },\n endnoteReference: { run: { ...noteRun, superScript: true } },\n },\n };\n}\n","/**\n * Section ordinal fold.\n *\n * A user-defined `section` can be split into several layout chunks (a columns\n * transition starts a new one). Every chunk of one section must share a single\n * bookmark: the start lands in the first chunk, the end in the last, and a\n * section-scoped TOC in between resolves against the same name.\n *\n * The ordinal is a fold over the chunk list, not a property of a chunk, so it\n * cannot be computed from `layout.sections[i]` alone. Computing it once up\n * front keeps the render loop free of the loop-carried counter it used to\n * thread through header/footer bookkeeping.\n */\n\n/** The chunk fields the fold depends on. */\nexport interface SectionOrdinalInput {\n /** True for the first layout chunk of a user-defined section. */\n isUserSection: boolean;\n /** True for every layout chunk of a user-defined section. */\n belongsToUserSection: boolean;\n}\n\nexport interface SectionOrdinal {\n /** 1-based ordinal shared by all chunks of one section; undefined outside. */\n ordinal?: number;\n /** True on the last chunk of a section, where the bookmark end belongs. */\n closeBookmark: boolean;\n}\n\n/**\n * Resolve the bookmark ordinal and closing chunk for every layout section.\n * Pure: same input, same output, no allocation against any registry.\n */\nexport function computeSectionOrdinals(\n sections: readonly SectionOrdinalInput[]\n): SectionOrdinal[] {\n let counter = 0;\n\n return sections.map((section, index) => {\n if (!section.belongsToUserSection) {\n if (section.isUserSection) counter++;\n return { closeBookmark: false };\n }\n\n // First chunk opens a new ordinal; later chunks reuse the one in flight.\n const ordinal = section.isUserSection ? counter + 1 : counter;\n if (section.isUserSection) counter++;\n\n // The section ends when the next chunk is not part of it — either there is\n // no next chunk, it is outside any section, or it opens the next one.\n const next = sections[index + 1];\n const closeBookmark =\n !next || !next.belongsToUserSection || next.isUserSection;\n\n return { ordinal, closeBookmark };\n });\n}\n","/**\n * Naming a bookmark.\n *\n * A heading with no author-supplied id is addressable by a slug of its text, so\n * the slug has to be derivable identically by whoever writes the bookmark and\n * whoever points at it — the compiler and the document-outline pre-pass both\n * call this, and a disagreement would be a cross-reference resolving against an\n * id that never gets written.\n *\n * This used to be a registry with per-render state; the compiler numbers its\n * own bookmarks now, so what is left is the naming.\n */\n\n/** Slug a piece of text into a bookmark id candidate. */\nexport function slugifyBookmarkText(text: string): string {\n return text\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n .substring(0, 40); // Limit length\n}\n\n/**\n * Disambiguate a slug against ids already taken, appending `-1`, `-2`, … .\n *\n * Gives up after 100 attempts and returns the colliding id: a document with a\n * hundred headings slugging identically has a naming problem no suffix fixes.\n */\nexport function dedupeBookmarkId(\n base: string,\n taken: (id: string) => boolean\n): string {\n let id = base;\n let attempt = 0;\n while (taken(id) && attempt < 100) {\n id = `${base}-${++attempt}`;\n }\n return id;\n}\n","/**\n * Level derivation for `list` components.\n *\n * Shared by the renderer (which turns these into `w:abstractNum` levels) and by\n * the document-outline pre-pass (which needs each level's format and start to\n * predict the counter a cross-reference should cache). Keeping one definition\n * is the point: a level the renderer numbers `a., b., c.` and a pre-pass that\n * thinks it is decimal produce a field whose cached value Word overwrites on\n * refresh — the silent disagreement cross-references exist to avoid.\n */\n\nimport type { ListLevelConfig } from './numberingConfig';\n\n/** The `list` props this module reads, structurally. */\nexport interface ListLevelSource {\n items?: readonly (string | { readonly level?: number })[];\n levels?: readonly ListLevelConfig[];\n format?: string;\n bullet?: string;\n start?: number;\n indent?: number | { left?: number; hanging?: number };\n}\n\n/**\n * Convert simplified format to proper level configurations\n */\nfunction createLevelsFromSimplifiedProps(\n props: ListLevelSource\n): ListLevelConfig[] {\n const levels: ListLevelConfig[] = [];\n\n // Determine format from simplified options\n let format: string;\n let text: string | undefined;\n\n if (props.format) {\n if (props.format === 'numbered') {\n format = 'decimal';\n text = '%1.';\n } else if (props.format === 'none') {\n format = 'none';\n text = '';\n } else {\n format = props.format;\n }\n } else {\n // Default to bullet\n format = 'bullet';\n text = props.bullet || '•';\n }\n\n // Create level 0 configuration\n const level0: ListLevelConfig = {\n level: 0,\n format,\n text,\n alignment: 'left',\n start: props.start,\n };\n\n // Add indent if specified\n if (props.indent) {\n if (typeof props.indent === 'number') {\n level0.indent = { left: props.indent };\n } else {\n level0.indent = props.indent;\n }\n }\n\n levels.push(level0);\n\n // Add default sublevels for nested lists\n if (format === 'bullet') {\n levels.push(\n { level: 1, format: 'bullet', text: '◦', alignment: 'left' },\n { level: 2, format: 'bullet', text: '▪', alignment: 'left' }\n );\n } else if (format === 'decimal') {\n levels.push(\n { level: 1, format: 'lowerLetter', text: '%2.', alignment: 'left' },\n { level: 2, format: 'lowerRoman', text: '%3.', alignment: 'left' }\n );\n }\n\n return levels;\n}\n\n/**\n * Fold `props.start` into level 0.\n *\n * `start` is otherwise only read on the simplified path, so an explicit\n * `levels` array silently discarded it. A `start` declared on the level itself\n * is more specific and wins.\n */\nfunction applyListStart(\n levels: readonly ListLevelConfig[],\n start: number | undefined\n): ListLevelConfig[] {\n if (start === undefined) return [...levels];\n return levels.map((level) =>\n level.level === 0 && level.start === undefined ? { ...level, start } : level\n );\n}\n\n/**\n * Get the maximum level used in list items\n */\nexport function getMaxLevelFromItems(\n items: readonly (string | { readonly level?: number })[] | undefined\n): number {\n if (!items || !Array.isArray(items)) {\n return 0;\n }\n\n let maxLevel = 0;\n for (const item of items) {\n if (typeof item === 'object' && item.level !== undefined) {\n maxLevel = Math.max(maxLevel, item.level);\n }\n }\n return maxLevel;\n}\n\n/**\n * Fill in missing levels with default configurations\n */\nfunction fillMissingLevels(\n levels: readonly ListLevelConfig[],\n maxLevel: number\n): ListLevelConfig[] {\n // Create a map of existing levels\n const levelMap = new Map<number, ListLevelConfig>();\n for (const level of levels) {\n levelMap.set(level.level, level);\n }\n\n // Get level 0 to determine the base format\n const level0 = levelMap.get(0);\n const baseFormat = level0?.format || 'bullet';\n\n // Create default levels for any missing ones\n const result: ListLevelConfig[] = [];\n for (let i = 0; i <= maxLevel; i++) {\n if (levelMap.has(i)) {\n result.push(levelMap.get(i)!);\n } else {\n // Create default sublevel based on parent format\n if (baseFormat === 'bullet') {\n const bullets = ['•', '◦', '▪', '▫', '‣'];\n result.push({\n level: i,\n format: 'bullet',\n text: bullets[i % bullets.length],\n alignment: 'left',\n });\n } else if (baseFormat === 'decimal' || baseFormat === 'numbered') {\n const formats = ['decimal', 'lowerLetter', 'lowerRoman'];\n const format = formats[i % formats.length];\n result.push({\n level: i,\n format,\n text: `%${i + 1}.`,\n alignment: 'left',\n });\n } else {\n // For other formats, continue with the same format\n result.push({\n level: i,\n format: baseFormat,\n text: `%${i + 1}.`,\n alignment: 'left',\n });\n }\n }\n }\n\n return result;\n}\n\n/**\n * The levels a list's numbering definition ends up with: explicit `levels` when\n * given (with `props.start` folded in), otherwise the simplified shorthand —\n * either way padded out to the deepest level the items actually use.\n */\nexport function resolveListLevels(props: ListLevelSource): ListLevelConfig[] {\n const maxLevel = getMaxLevelFromItems(props.items);\n\n if (props.levels && props.levels.length > 0) {\n return fillMissingLevels(\n applyListStart(props.levels, props.start),\n maxLevel\n );\n }\n\n return fillMissingLevels(createLevelsFromSimplifiedProps(props), maxLevel);\n}\n","/**\n * The `table` component, resolved down to plain numbers and colours.\n *\n * A table's authoring surface is layered: a value may come from the cell, the\n * column, the table's header defaults, the table's cell defaults, the table's\n * own border settings, or the built-in defaults — and borders, sizes and\n * padding each cascade *per side*, so a cell can take its left border from one\n * layer and its top from another. Getting that cascade right is the whole job,\n * and it has nothing to do with any renderer.\n *\n * So it lives here, once. Both the pre-IR writer (`createTable`) and the DocxIR\n * compiler resolve a table through this module and then only translate the\n * result into their own vocabulary. Two copies of these rules would drift, and\n * the drift would be invisible until a border quietly changed colour.\n *\n * Everything returned is resolved: colours are 6-digit hex without `#`, border\n * sizes are points, padding and heights are points. Nothing here loads content\n * or touches the filesystem.\n */\n\nimport type { ComponentDefinition } from '../types';\nimport type { ThemeConfig } from '../styles';\nimport { resolveColor } from '../styles/utils/colorUtils';\nimport {\n getAvailableWidthTwips,\n relativeLengthToTwips,\n} from '../utils/widthUtils';\nimport { pointsToTwips } from '../styles/utils/styleHelpers';\n\n/* ------------------------------------------------------------------ *\n * Authoring shapes\n * ------------------------------------------------------------------ */\n\nexport type TableCellContent = string | ComponentDefinition;\n\nexport type TableFontConfig = {\n family?: string;\n size?: number;\n bold?: boolean;\n fontWeight?: number;\n italic?: boolean;\n underline?: boolean;\n};\n\nexport type BorderColor =\n | string\n | { bottom?: string; top?: string; right?: string; left?: string };\n\nexport type BorderSize =\n | number\n | { bottom?: number; top?: number; right?: number; left?: number };\n\nexport type Padding =\n | number\n | { bottom?: number; top?: number; right?: number; left?: number };\n\nexport type CellDefaults = {\n color?: string;\n backgroundColor?: string;\n horizontalAlignment?: 'left' | 'center' | 'right' | 'justify';\n verticalAlignment?: 'top' | 'middle' | 'bottom';\n font?: TableFontConfig;\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n padding?: Padding;\n height?: number;\n};\n\nexport type HideBorders =\n | boolean\n | {\n top?: boolean;\n right?: boolean;\n bottom?: boolean;\n left?: boolean;\n insideHorizontal?: boolean;\n insideVertical?: boolean;\n };\n\n/** A cell as written, plus the annotations that ride along with it. */\nexport type TableCellSource<TComment, TRevision> = CellDefaults & {\n comment?: TComment;\n revision?: TRevision;\n content?: TableCellContent;\n};\n\nexport type TableColumnSource<TComment, TRevision> = {\n /** Width in points (number) or as a percentage string, e.g. `\"40%\"`. */\n width?: number | string;\n cellDefaults?: CellDefaults;\n header?: TableCellSource<TComment, TRevision>;\n cells?: TableCellSource<TComment, TRevision>[];\n};\n\nexport type TableSource<TComment, TRevision, TRowRevision> = {\n borderColor?: BorderColor;\n borderSize?: BorderSize;\n hideBorders?: HideBorders;\n cellDefaults?: CellDefaults;\n headerCellDefaults?: CellDefaults;\n width?: number;\n columns: TableColumnSource<TComment, TRevision>[];\n /** Row-parallel properties, indexed like `columns[].cells`. */\n rows?: {\n revision?: TRowRevision;\n cantSplit?: boolean;\n tableHeader?: boolean;\n }[];\n keepInOnePage?: boolean;\n keepNext?: boolean;\n repeatHeaderOnPageBreak?: boolean;\n};\n\n/* ------------------------------------------------------------------ *\n * Resolved shapes\n * ------------------------------------------------------------------ */\n\nexport interface ResolvedSides<T> {\n top: T;\n right: T;\n bottom: T;\n left: T;\n}\n\n/** One side of a cell's border, after the cascade and the hide rules. */\nexport interface ResolvedBorder {\n /** Points. Zero means no border. */\n size: number;\n /** 6-digit hex, no `#`. */\n color: string;\n /** True when `hideBorders` suppressed this side for this cell. */\n hidden: boolean;\n}\n\nexport interface ResolvedCell<TComment, TRevision> {\n content?: TableCellContent;\n comment?: TComment;\n revision?: TRevision;\n /** Text colour: hex, `auto`, or undefined to inherit the table style. */\n color?: string;\n /** Fill: hex, `auto`, or the `transparent` sentinel meaning \"no shading\". */\n backgroundColor?: string;\n horizontalAlignment: 'left' | 'center' | 'right' | 'justify';\n verticalAlignment: 'top' | 'middle' | 'bottom';\n font: TableFontConfig;\n borders: ResolvedSides<ResolvedBorder>;\n /** Points, per side. Absent when no layer asked for padding. */\n padding?: ResolvedSides<number>;\n /**\n * A cell the source never wrote, kept only so the grid stays rectangular.\n *\n * It draws its borders and nothing else — no fill, no padding, no content —\n * which is what tells a renderer to leave it empty rather than style it.\n */\n missing?: boolean;\n}\n\nexport interface ResolvedRow<TComment, TRevision, TRowRevision> {\n cells: ResolvedCell<TComment, TRevision>[];\n /** Points; the tallest height any cell in the row asked for. */\n height?: number;\n isHeader: boolean;\n /** Set only when the source stated it. */\n tableHeader?: boolean;\n cantSplit?: boolean;\n revision?: TRowRevision;\n /** Every cell paragraph in the row keeps with the next one. */\n keepNext: boolean;\n}\n\n/**\n * The table's column grid.\n *\n * `twips` is the real OOXML unit. `percent` is what the pipeline has always\n * written when no column states a width — the grid then carries a percentage\n * per column rather than a width, which Word tolerates because the table\n * itself is sized in percent.\n */\nexport interface ResolvedColumnGrid {\n unit: 'twips' | 'percent';\n values: number[];\n}\n\nexport interface ResolvedTable<TComment, TRevision, TRowRevision> {\n columnGrid: ResolvedColumnGrid;\n width: { size: number; unit: 'twips' | 'percent' };\n header: ResolvedRow<TComment, TRevision, TRowRevision>;\n rows: ResolvedRow<TComment, TRevision, TRowRevision>[];\n /** Headers repeat across page breaks unless the source disabled it. */\n repeatHeader: boolean;\n /** Emitted when the column widths cannot fit the page. */\n overflow?: { totalTwips: number; availableTwips: number };\n}\n\n/* ------------------------------------------------------------------ *\n * Defaults\n * ------------------------------------------------------------------ */\n\n/** What a cell looks like before any layer has said anything. */\nfunction baseDefaults(): Required<\n Pick<\n CellDefaults,\n | 'color'\n | 'backgroundColor'\n | 'horizontalAlignment'\n | 'verticalAlignment'\n | 'font'\n | 'borderColor'\n | 'borderSize'\n >\n> {\n return {\n color: '000000',\n backgroundColor: 'transparent',\n horizontalAlignment: 'left',\n verticalAlignment: 'top',\n font: {\n family: 'Arial',\n size: 11,\n bold: false,\n italic: false,\n underline: false,\n },\n borderColor: '000000',\n borderSize: 1,\n };\n}\n\n/**\n * Sentinels for \"this layer did not say\".\n *\n * Normalising a per-side value has to distinguish \"not stated\" from a real\n * value so a lower layer can still win, and the two sentinels are what the\n * cascade searches past.\n */\nconst UNSET_COLOR = '';\nconst UNSET_SIZE = -1;\n\n/* ------------------------------------------------------------------ *\n * Per-side cascades\n * ------------------------------------------------------------------ */\n\nfunction normalizeBorderColor(\n border: BorderColor | undefined\n): ResolvedSides<string> | undefined {\n if (border === undefined) return undefined;\n if (typeof border === 'string') {\n return { top: border, right: border, bottom: border, left: border };\n }\n return {\n top: border.top ?? UNSET_COLOR,\n right: border.right ?? UNSET_COLOR,\n bottom: border.bottom ?? UNSET_COLOR,\n left: border.left ?? UNSET_COLOR,\n };\n}\n\nfunction normalizeBorderSize(\n border: BorderSize | undefined\n): ResolvedSides<number> | undefined {\n if (border === undefined) return undefined;\n if (typeof border === 'number') {\n return { top: border, right: border, bottom: border, left: border };\n }\n return {\n top: border.top ?? UNSET_SIZE,\n right: border.right ?? UNSET_SIZE,\n bottom: border.bottom ?? UNSET_SIZE,\n left: border.left ?? UNSET_SIZE,\n };\n}\n\nfunction normalizePadding(\n padding: Padding | undefined\n): ResolvedSides<number> | undefined {\n if (padding === undefined) return undefined;\n if (typeof padding === 'number') {\n return { top: padding, right: padding, bottom: padding, left: padding };\n }\n return {\n top: padding.top ?? UNSET_SIZE,\n right: padding.right ?? UNSET_SIZE,\n bottom: padding.bottom ?? UNSET_SIZE,\n left: padding.left ?? UNSET_SIZE,\n };\n}\n\n/** First layer to state a colour for each side wins, side by side. */\nfunction mergeBorderColorPerSide(\n ...borders: (BorderColor | undefined)[]\n): ResolvedSides<string> {\n const normalized = borders.map(normalizeBorderColor);\n const fallback = baseDefaults().borderColor as string;\n const pick = (side: keyof ResolvedSides<string>): string =>\n normalized.find((b) => b && b[side] !== UNSET_COLOR)?.[side] ?? fallback;\n\n return {\n top: pick('top'),\n right: pick('right'),\n bottom: pick('bottom'),\n left: pick('left'),\n };\n}\n\nfunction mergeBorderSizePerSide(\n ...borders: (BorderSize | undefined)[]\n): ResolvedSides<number> {\n const normalized = borders.map(normalizeBorderSize);\n const fallback = baseDefaults().borderSize as number;\n const pick = (side: keyof ResolvedSides<number>): number =>\n normalized.find((b) => b && b[side] !== UNSET_SIZE)?.[side] ?? fallback;\n\n return {\n top: pick('top'),\n right: pick('right'),\n bottom: pick('bottom'),\n left: pick('left'),\n };\n}\n\n/**\n * Padding, or nothing.\n *\n * Unlike borders there is no built-in padding: if no layer asked for any, the\n * cell keeps whatever margins the document defines rather than being pinned to\n * zero.\n */\nfunction mergePaddingPerSide(\n ...paddings: (Padding | undefined)[]\n): ResolvedSides<number> | undefined {\n const normalized = paddings.map(normalizePadding);\n if (!normalized.some((p) => p !== undefined)) return undefined;\n const pick = (side: keyof ResolvedSides<number>): number =>\n normalized.find((p) => p && p[side] !== UNSET_SIZE)?.[side] ?? 0;\n\n return {\n top: pick('top'),\n right: pick('right'),\n bottom: pick('bottom'),\n left: pick('left'),\n };\n}\n\n/**\n * The table's own border applied to the cells on its outside edge.\n *\n * A table-level border is a border around the *table*, so it only reaches the\n * sides of a cell that face outwards. It is applied a second time, to every\n * side, as the last fallback before the built-in default — that is what makes\n * `borderColor: '#ccc'` on a table colour the inner grid too.\n */\nfunction outerBorderOverride(\n position: {\n isHeader?: boolean;\n isFirstCol?: boolean;\n isLastCol?: boolean;\n isLastRow?: boolean;\n },\n tableBorderColor?: BorderColor,\n tableBorderSize?: BorderSize\n): {\n borderColor?: Partial<ResolvedSides<string>>;\n borderSize?: Partial<ResolvedSides<number>>;\n} {\n const result: {\n borderColor?: Partial<ResolvedSides<string>>;\n borderSize?: Partial<ResolvedSides<number>>;\n } = {};\n\n const color = normalizeBorderColor(tableBorderColor);\n if (tableBorderColor && color) {\n result.borderColor = {};\n if (position.isHeader && color.top !== UNSET_COLOR) {\n result.borderColor.top = color.top;\n }\n if (position.isFirstCol && color.left !== UNSET_COLOR) {\n result.borderColor.left = color.left;\n }\n if (position.isLastCol && color.right !== UNSET_COLOR) {\n result.borderColor.right = color.right;\n }\n if (position.isLastRow && color.bottom !== UNSET_COLOR) {\n result.borderColor.bottom = color.bottom;\n }\n }\n\n const size = normalizeBorderSize(tableBorderSize);\n if (tableBorderSize && size) {\n result.borderSize = {};\n if (position.isHeader && size.top !== UNSET_SIZE) {\n result.borderSize.top = size.top;\n }\n if (position.isFirstCol && size.left !== UNSET_SIZE) {\n result.borderSize.left = size.left;\n }\n if (position.isLastCol && size.right !== UNSET_SIZE) {\n result.borderSize.right = size.right;\n }\n if (position.isLastRow && size.bottom !== UNSET_SIZE) {\n result.borderSize.bottom = size.bottom;\n }\n }\n\n return result;\n}\n\nfunction normalizeHideBorders(\n hideBorders: HideBorders | undefined\n): ResolvedSides<boolean> & {\n insideHorizontal: boolean;\n insideVertical: boolean;\n} {\n if (hideBorders === undefined) {\n return {\n top: false,\n right: false,\n bottom: false,\n left: false,\n insideHorizontal: false,\n insideVertical: false,\n };\n }\n if (typeof hideBorders === 'boolean') {\n return {\n top: hideBorders,\n right: hideBorders,\n bottom: hideBorders,\n left: hideBorders,\n insideHorizontal: hideBorders,\n insideVertical: hideBorders,\n };\n }\n return {\n top: hideBorders.top ?? false,\n right: hideBorders.right ?? false,\n bottom: hideBorders.bottom ?? false,\n left: hideBorders.left ?? false,\n insideHorizontal: hideBorders.insideHorizontal ?? false,\n insideVertical: hideBorders.insideVertical ?? false,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Colours\n * ------------------------------------------------------------------ */\n\nexport interface TableModelOptions {\n /** Reports a value that could not be used. Deduplicated by the caller. */\n onWarning?: (code: string, message: string) => void;\n}\n\n/**\n * Resolve a cell colour the way every other colour in the schema resolves.\n *\n * Bare 6-digit hex and `auto` pass through: they are the only raw values OOXML\n * itself accepts, so documents relying on them predate theme resolution and\n * must keep working. `transparent` is a `backgroundColor`-only sentinel — on\n * the text path nothing consumes it and it is not a legal `w:color`, so it is\n * dropped with a warning rather than emitted.\n */\nfunction resolveCellColor(\n value: string | undefined,\n prop: 'color' | 'backgroundColor',\n theme: ThemeConfig,\n options: TableModelOptions\n): string | undefined {\n if (value === undefined || value === 'auto') return value;\n if (value === 'transparent') {\n if (prop === 'backgroundColor') return value;\n options.onWarning?.(\n 'TABLE_CELL_COLOR_INVALID',\n `\"transparent\" is not a valid table cell \"color\"; ignoring it and using the table style color. It only applies to \"backgroundColor\".`\n );\n return undefined;\n }\n if (/^[0-9A-Fa-f]{6}$/.test(value)) return value.toUpperCase();\n try {\n return resolveColor(value, theme);\n } catch {\n // Passing the value through instead would not save the document: no\n // renderer can emit a non-hex, non-\"auto\" fill, so it would still fail —\n // deeper in the stack with an opaque message.\n const allowed =\n prop === 'backgroundColor'\n ? '\"auto\", or \"transparent\" for no shading'\n : 'or \"auto\"';\n throw new Error(\n `Invalid table cell ${prop}: \"${value}\". Must be a hex color with # prefix (e.g. \"#000000\"), a theme color name, ${allowed}.`\n );\n }\n}\n\n/* ------------------------------------------------------------------ *\n * The cascade\n * ------------------------------------------------------------------ */\n\ntype MergedCell = Omit<\n ResolvedCell<never, never>,\n 'content' | 'comment' | 'revision' | 'borders'\n> & {\n borderColor: ResolvedSides<string>;\n borderSize: ResolvedSides<number>;\n height?: number;\n};\n\n/**\n * A body cell's resolved properties.\n *\n * Priority, highest first: the cell, the column, the table border on the sides\n * that face out, the table's cell defaults, the table border everywhere, the\n * built-in defaults.\n */\nfunction mergeCellDefaults(\n tableDef: CellDefaults | undefined,\n columnDef: CellDefaults | undefined,\n cellDef: CellDefaults | undefined,\n position: { isFirstCol?: boolean; isLastCol?: boolean; isLastRow?: boolean },\n tableOuterBorder: { borderColor?: BorderColor; borderSize?: BorderSize },\n theme: ThemeConfig,\n options: TableModelOptions\n): MergedCell {\n const defaults = baseDefaults();\n const outer = outerBorderOverride(\n position,\n tableOuterBorder.borderColor,\n tableOuterBorder.borderSize\n );\n\n return {\n color: resolveCellColor(\n cellDef?.color ?? columnDef?.color ?? tableDef?.color ?? defaults.color,\n 'color',\n theme,\n options\n ),\n backgroundColor: resolveCellColor(\n cellDef?.backgroundColor ??\n columnDef?.backgroundColor ??\n tableDef?.backgroundColor ??\n defaults.backgroundColor,\n 'backgroundColor',\n theme,\n options\n ),\n horizontalAlignment:\n cellDef?.horizontalAlignment ??\n columnDef?.horizontalAlignment ??\n tableDef?.horizontalAlignment ??\n defaults.horizontalAlignment,\n verticalAlignment:\n cellDef?.verticalAlignment ??\n columnDef?.verticalAlignment ??\n tableDef?.verticalAlignment ??\n defaults.verticalAlignment,\n font: {\n ...defaults.font,\n ...tableDef?.font,\n ...columnDef?.font,\n ...cellDef?.font,\n },\n borderColor: mergeBorderColorPerSide(\n cellDef?.borderColor,\n columnDef?.borderColor,\n outer.borderColor as BorderColor,\n tableDef?.borderColor,\n tableOuterBorder.borderColor\n ),\n borderSize: mergeBorderSizePerSide(\n cellDef?.borderSize,\n columnDef?.borderSize,\n outer.borderSize as BorderSize,\n tableDef?.borderSize,\n tableOuterBorder.borderSize\n ),\n padding: mergePaddingPerSide(\n cellDef?.padding,\n columnDef?.padding,\n tableDef?.padding\n ),\n height: cellDef?.height ?? columnDef?.height ?? tableDef?.height,\n };\n}\n\n/**\n * A header cell's resolved properties.\n *\n * Same shape as a body cell with one extra layer — the table's header defaults\n * — and the table border always reaching the top, because the header row is\n * always the table's top edge.\n */\nfunction mergeHeaderCellDefaults(\n tableDef: CellDefaults | undefined,\n headerTableDef: CellDefaults | undefined,\n columnDef: CellDefaults | undefined,\n headerDef: CellDefaults | undefined,\n position: { isFirstCol?: boolean; isLastCol?: boolean },\n tableOuterBorder: { borderColor?: BorderColor; borderSize?: BorderSize },\n theme: ThemeConfig,\n options: TableModelOptions\n): MergedCell {\n const defaults = baseDefaults();\n const outer = outerBorderOverride(\n {\n isHeader: true,\n isFirstCol: position.isFirstCol,\n isLastCol: position.isLastCol,\n },\n tableOuterBorder.borderColor,\n tableOuterBorder.borderSize\n );\n\n return {\n color: resolveCellColor(\n headerDef?.color ??\n headerTableDef?.color ??\n columnDef?.color ??\n tableDef?.color ??\n defaults.color,\n 'color',\n theme,\n options\n ),\n backgroundColor: resolveCellColor(\n headerDef?.backgroundColor ??\n headerTableDef?.backgroundColor ??\n columnDef?.backgroundColor ??\n tableDef?.backgroundColor ??\n defaults.backgroundColor,\n 'backgroundColor',\n theme,\n options\n ),\n horizontalAlignment:\n headerDef?.horizontalAlignment ??\n headerTableDef?.horizontalAlignment ??\n columnDef?.horizontalAlignment ??\n tableDef?.horizontalAlignment ??\n defaults.horizontalAlignment,\n verticalAlignment:\n headerDef?.verticalAlignment ??\n headerTableDef?.verticalAlignment ??\n columnDef?.verticalAlignment ??\n tableDef?.verticalAlignment ??\n defaults.verticalAlignment,\n font: {\n ...defaults.font,\n ...tableDef?.font,\n ...headerTableDef?.font,\n ...columnDef?.font,\n ...headerDef?.font,\n },\n borderColor: mergeBorderColorPerSide(\n headerDef?.borderColor,\n columnDef?.borderColor,\n outer.borderColor as BorderColor,\n headerTableDef?.borderColor,\n tableDef?.borderColor,\n tableOuterBorder.borderColor\n ),\n borderSize: mergeBorderSizePerSide(\n headerDef?.borderSize,\n columnDef?.borderSize,\n outer.borderSize as BorderSize,\n headerTableDef?.borderSize,\n tableDef?.borderSize,\n tableOuterBorder.borderSize\n ),\n padding: mergePaddingPerSide(\n headerDef?.padding,\n headerTableDef?.padding,\n columnDef?.padding,\n tableDef?.padding\n ),\n height:\n headerDef?.height ??\n headerTableDef?.height ??\n columnDef?.height ??\n tableDef?.height,\n };\n}\n\n/* ------------------------------------------------------------------ *\n * Entry point\n * ------------------------------------------------------------------ */\n\n/**\n * Resolve a whole table.\n *\n * The generic parameters keep the annotation types (`comment`, `revision`) out\n * of this module: it carries them through untouched, so neither the pre-IR\n * writer's docx-shaped types nor the IR's own have to be known here.\n */\nexport function resolveTableModel<TComment, TRevision, TRowRevision>(\n source: TableSource<TComment, TRevision, TRowRevision>,\n theme: ThemeConfig,\n themeName: string,\n options: TableModelOptions = {}\n): ResolvedTable<TComment, TRevision, TRowRevision> {\n const columns = source.columns ?? [];\n const columnCount = columns.length;\n const rowCount = columns[0]?.cells?.length ?? 0;\n const hidden = normalizeHideBorders(source.hideBorders);\n const outerBorder = {\n borderColor: source.borderColor,\n borderSize: source.borderSize,\n };\n\n /** Which `hideBorders` switch governs one side of one cell. */\n const isHidden = (\n side: 'top' | 'right' | 'bottom' | 'left',\n position: {\n isFirstRow?: boolean;\n isLastRow?: boolean;\n isFirstCol?: boolean;\n isLastCol?: boolean;\n }\n ): boolean => {\n switch (side) {\n case 'top':\n return position.isFirstRow ? hidden.top : hidden.insideHorizontal;\n case 'bottom':\n return position.isLastRow ? hidden.bottom : hidden.insideHorizontal;\n case 'left':\n return position.isFirstCol ? hidden.left : hidden.insideVertical;\n case 'right':\n return position.isLastCol ? hidden.right : hidden.insideVertical;\n }\n };\n\n const borders = (\n merged: MergedCell,\n position: {\n isFirstRow?: boolean;\n isLastRow?: boolean;\n isFirstCol?: boolean;\n isLastCol?: boolean;\n }\n ): ResolvedSides<ResolvedBorder> => ({\n top: {\n size: merged.borderSize.top,\n color: merged.borderColor.top,\n hidden: isHidden('top', position),\n },\n right: {\n size: merged.borderSize.right,\n color: merged.borderColor.right,\n hidden: isHidden('right', position),\n },\n bottom: {\n size: merged.borderSize.bottom,\n color: merged.borderColor.bottom,\n hidden: isHidden('bottom', position),\n },\n left: {\n size: merged.borderSize.left,\n color: merged.borderColor.left,\n hidden: isHidden('left', position),\n },\n });\n\n /** The tallest height any cell in a row asked for. */\n const tallest = (heights: (number | undefined)[]): number | undefined =>\n heights.reduce<number | undefined>(\n (max, height) =>\n height === undefined\n ? max\n : max === undefined\n ? height\n : Math.max(max, height),\n undefined\n );\n\n // -- header row ---------------------------------------------------\n const headerMerges = columns.map((column, colIndex) =>\n mergeHeaderCellDefaults(\n source.cellDefaults,\n source.headerCellDefaults,\n column.cellDefaults,\n column.header,\n { isFirstCol: colIndex === 0, isLastCol: colIndex === columnCount - 1 },\n outerBorder,\n theme,\n options\n )\n );\n\n const header: ResolvedRow<TComment, TRevision, TRowRevision> = {\n isHeader: true,\n height: tallest(headerMerges.map((m) => m.height)),\n keepNext: source.keepInOnePage === true,\n cells: columns.map((column, colIndex) => {\n const merged = headerMerges[colIndex];\n const position = {\n isFirstRow: true,\n // The header is the last row too when the table has no body.\n isLastRow: rowCount === 0,\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === columnCount - 1,\n };\n return {\n ...(column.header?.content !== undefined\n ? { content: column.header.content }\n : {}),\n ...(column.header?.comment !== undefined\n ? { comment: column.header.comment }\n : {}),\n ...(column.header?.revision !== undefined\n ? { revision: column.header.revision }\n : {}),\n color: merged.color,\n backgroundColor: merged.backgroundColor,\n horizontalAlignment: merged.horizontalAlignment,\n verticalAlignment: merged.verticalAlignment,\n font: merged.font,\n borders: borders(merged, position),\n ...(merged.padding ? { padding: merged.padding } : {}),\n };\n }),\n };\n\n // -- body rows ----------------------------------------------------\n const rows = Array.from({ length: rowCount }, (_, rowIndex) => {\n const isLastRow = rowIndex === rowCount - 1;\n const rowProps = source.rows?.[rowIndex];\n\n const merges = columns.map((column, colIndex) =>\n mergeCellDefaults(\n source.cellDefaults,\n column.cellDefaults,\n column.cells?.[rowIndex],\n {\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === columnCount - 1,\n isLastRow,\n },\n outerBorder,\n theme,\n options\n )\n );\n\n const row: ResolvedRow<TComment, TRevision, TRowRevision> = {\n isHeader: false,\n // A height stated on a column or the table applies to a row only where\n // that row actually has a cell; an absent cell contributes nothing.\n height: tallest(\n merges.map((merged, colIndex) =>\n columns[colIndex].cells?.[rowIndex] ? merged.height : undefined\n )\n ),\n keepNext:\n (source.keepInOnePage === true && !isLastRow) ||\n (isLastRow && source.keepNext === true),\n ...(rowProps?.cantSplit !== undefined\n ? { cantSplit: rowProps.cantSplit }\n : {}),\n ...(rowProps?.tableHeader !== undefined\n ? { tableHeader: rowProps.tableHeader }\n : {}),\n ...(rowProps?.revision !== undefined\n ? { revision: rowProps.revision }\n : {}),\n cells: columns.map((column, colIndex) => {\n const cell = column.cells?.[rowIndex];\n const merged = merges[colIndex];\n const position = {\n // Data rows are never the first row; the header is.\n isFirstRow: false,\n isFirstCol: colIndex === 0,\n isLastCol: colIndex === columnCount - 1,\n isLastRow,\n };\n // A row longer than this column keeps the cell — with its borders, so\n // the grid stays closed — but nothing else about it.\n if (!cell) {\n return {\n horizontalAlignment: 'left' as const,\n verticalAlignment: merged.verticalAlignment,\n font: merged.font,\n borders: borders(merged, position),\n missing: true,\n };\n }\n return {\n ...(cell.content !== undefined ? { content: cell.content } : {}),\n ...(cell.comment !== undefined ? { comment: cell.comment } : {}),\n ...(cell.revision !== undefined ? { revision: cell.revision } : {}),\n color: merged.color,\n backgroundColor: merged.backgroundColor,\n horizontalAlignment: merged.horizontalAlignment,\n verticalAlignment: merged.verticalAlignment,\n font: merged.font,\n borders: borders(merged, position),\n ...(merged.padding ? { padding: merged.padding } : {}),\n };\n }),\n };\n return row;\n });\n\n return {\n ...resolveWidths(source, columns, theme, themeName),\n header,\n rows,\n repeatHeader: source.repeatHeaderOnPageBreak ?? true,\n };\n}\n\n/**\n * Column widths and the table's own width.\n *\n * Two modes, and which one applies is decided by whether *any* column states a\n * width. With explicit widths everything is in twips and the table is as wide\n * as its columns; with none, the columns split the table evenly and the table\n * is sized as a percentage of the text column.\n */\nfunction resolveWidths<TComment, TRevision, TRowRevision>(\n source: TableSource<TComment, TRevision, TRowRevision>,\n columns: TableColumnSource<TComment, TRevision>[],\n theme: ThemeConfig,\n themeName: string\n): Pick<\n ResolvedTable<TComment, TRevision, TRowRevision>,\n 'columnGrid' | 'width' | 'overflow'\n> {\n const hasExplicitWidths = columns.some((col) => col.width !== undefined);\n\n if (!hasExplicitWidths) {\n const share = 100 / columns.length;\n return {\n columnGrid: { unit: 'percent', values: columns.map(() => share) },\n width: { size: source.width ?? 100, unit: 'percent' },\n };\n }\n\n const available = getAvailableWidthTwips(theme, themeName);\n const stated = columns.map((col) =>\n col.width !== undefined\n ? relativeLengthToTwips(col.width, available)\n : undefined\n );\n const totalStated = stated.reduce<number>((sum, w) => sum + (w ?? 0), 0);\n const unstatedCount = columns.filter((col) => col.width === undefined).length;\n\n // Whatever the stated columns left over, split between the rest. With every\n // column stated there is nothing to share, so an inch stands in — it is only\n // reached when the value is never used.\n const remaining = Math.max(0, available - totalStated);\n const shareOfRemainder =\n unstatedCount > 0 ? remaining / unstatedCount : pointsToTwips(72);\n\n const values = stated.map((w) => w || shareOfRemainder);\n return {\n columnGrid: { unit: 'twips', values },\n width: {\n size: values.reduce((sum, w) => sum + w, 0),\n unit: 'twips',\n },\n ...(totalStated > available\n ? { overflow: { totalTwips: totalStated, availableTwips: available } }\n : {}),\n };\n}\n","/**\n * Tracked-change defaults.\n *\n * The ids, the runs and the registry that used to hand them out all live in the\n * compiler now — it allocates every `w:ins`/`w:del` id itself, per compilation,\n * in document order. What is left is the two values a revision falls back to\n * when the author states neither, which are shared with the schema.\n */\n\nexport const DEFAULT_REVISION_AUTHOR = 'json-to-office';\n/** A fixed instant, so identical inputs produce byte-identical XML. */\nexport const DEFAULT_REVISION_DATE = '1970-01-01T00:00:00Z';\n","/**\n * Review-comment defaults.\n *\n * The ids and the bodies live in the compiler now — it numbers every comment\n * itself, per compilation, and carries the bodies in the IR. What is left is\n * the two values a comment falls back to when the author states neither.\n */\n\nexport const DEFAULT_COMMENT_AUTHOR = 'json-to-office';\n/** A fixed instant, so identical inputs produce byte-identical XML. */\nexport const DEFAULT_COMMENT_DATE = '1970-01-01T00:00:00Z';\n","/**\n * How a list numbers itself.\n *\n * The level shapes an author can state, plus the two constants a numbered\n * heading needs. Turning any of it into OOXML is the compiler's and the\n * adapter's job — this module builds nothing, so both the outline pre-pass and\n * the compiler can read the same declarations without either pulling in a\n * renderer.\n */\n\n/**\n * Styling for the marker glyph itself (`w:lvl/w:rPr`), independent of the list\n * text. `color` must already be resolved to a 6-char hex without '#'.\n */\nexport interface ListMarkerFontConfig {\n family?: string;\n /** Points. */\n size?: number;\n /** Resolved hex, no leading '#'. */\n color?: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n}\n\nexport interface ListLevelConfig {\n level: number;\n format?: string;\n text?: string;\n alignment?: string;\n indent?: {\n left?: number;\n hanging?: number;\n };\n start?: number;\n font?: ListMarkerFontConfig;\n}\n\n/**\n * The one multilevel definition every numbered heading in a document shares —\n * shared so that 1., 1.1., 1.1.1. is a single continuous sequence rather than\n * one restarting per heading.\n */\nexport const HEADING_NUMBERING_REFERENCE = 'jto-heading-numbering';\n\n/**\n * The heading number as Word draws it in the document — the bare dotted number\n * plus the trailing period `lvlText` ends with.\n *\n * A cached TOC entry has to reproduce that form exactly: Word rewrites the\n * entry from the heading's own rendered text the first time it refreshes the\n * field, and an entry cached as \"1.1 Methods\" would visibly shift to\n * \"1.1. Methods\". Cross-references keep the bare number instead — Word's `\\w`\n * switch is defined as the paragraph number *without* trailing periods.\n */\nexport function headingNumberLabel(number: string): string {\n return `${number}.`;\n}\n","/**\n * Normalize text to NFC so composed accented characters are preserved\n * consistently across DOCX renderers (including LibreOffice).\n */\nexport function normalizeUnicodeText(text: string | null | undefined): string {\n return (text ?? '').normalize('NFC');\n}\n","/**\n * collectDocumentOutline — per-document pre-pass over the layout (#174, #177,\n * #182). One walk, three outputs: TOC entries, heading numbers, and the\n * cross-reference targets `[@id]` resolves against.\n *\n * `updateFields: true` asks Word to repopulate every TOC field on open, and\n * Word obliges. Headless LibreOffice does not, so a TOC field with no cached\n * content exports to PDF as the bare word \"Contents\" — and the rasterizer path\n * goes through soffice. Collecting the entries up front lets the renderer pass\n * them to docx as `cachedEntries`, which writes real paragraphs between the\n * field's `separate` and `end` characters.\n *\n * Modelled on `prerasterizeVisuals`: a pure collection pass over the layout,\n * seeded into the render context, consulted by the component that needs it.\n * Over-collection shows a stale entry until the reader refreshes the field;\n * under-collection degrades to today's empty TOC. Neither breaks a render.\n *\n * What the walk must and must not reach:\n * - **Headers and footers are excluded by construction.** They are fields on\n * `SectionLayout`, not components in `components[]`, and `renderSection`\n * handles only paragraph/image/table there — a heading in a header renders as\n * nothing and must never appear in the TOC.\n * - **`text-box` is reachable and does hold headings.** Its children render\n * through `renderComponent` as real `Heading1..6` paragraphs, which Word's\n * `\\o` switch collects.\n * - **`columns` cannot appear here** — `applyLayout` hoists its children before\n * this runs. The descent is kept anyway for the text-box-nested case and so a\n * future layout change cannot silently drop entries.\n * - **Table cells cannot carry headings** (`processCellContent` handles only\n * paragraph and image), so tables are leaves.\n *\n * Two kinds of entry are collected, because Word populates a TOC from two\n * sources: heading components (the `\\o` outline range) and paragraphs whose\n * `themeStyle` a TOC maps via `props.styles` (the `\\t` switch). Collecting only\n * the first would make the cached entries disagree with Word's own refresh —\n * exactly the failure `cachedEntries` exists to prevent.\n *\n * The walk also owns the two counters render cannot keep itself: the heading\n * numbering sequence (a cross-reference needs the number of a heading that may\n * come later in the document) and each list's item counters.\n */\n\nimport { getStandardComponent } from '@json-to-office/shared-docx';\nimport type { ComponentDefinition } from '../types';\nimport type { SectionLayout } from './layout';\nimport { computeSectionOrdinals } from './sectionOrdinals';\nimport { sectionBookmark } from './sectionBookmarks';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport {\n slugifyBookmarkText,\n dedupeBookmarkId,\n} from '../utils/bookmarkRegistry';\n/**\n * A cross-reference target: a numbered heading or list item.\n *\n * Resolved by the outline pre-pass and read back while text is compiled, which\n * is why a `[@id]` can point at something further down the document.\n */\nexport interface NumberedItemInfo {\n kind: 'heading' | 'list-item';\n /** Rendered text of the target, for a `:none` (text) reference. */\n text: string;\n /** Full multilevel number (\"2.1.3\"), absent when the target is unnumbered. */\n full?: string;\n /** The target's own level counter (\"3\"), absent when unnumbered. */\n own?: string;\n}\nimport { resolveListLevels } from '../utils/listLevels';\nimport type { ListLevelConfig } from '../utils/numberingConfig';\nimport { formatNumberForLevel } from '../utils/numberFormatting';\n\nexport interface TocHeadingEntry {\n /** Rendered text, with markdown decorators stripped as `createHeading` does. */\n title: string;\n /** Outline level (heading) or the level its style maps to. */\n level: number;\n /**\n * `themeStyle` key for a style-mapped paragraph; undefined for a heading.\n * A TOC includes these only when its own `props.styles` maps the key.\n */\n styleId?: string;\n /** Bookmark of the layout section this entry sits in, when inside one. */\n sectionBookmarkId?: string;\n /** Multilevel number (\"2.1\") when heading numbering applies to this entry. */\n number?: string;\n}\n\nexport interface DocumentOutline {\n entries: TocHeadingEntry[];\n /** Cross-reference targets, keyed by the bookmark id render will emit. */\n numberedItems: Map<string, NumberedItemInfo>;\n}\n\n/** Word supports six heading levels; deeper input collapses onto Heading1. */\nconst MAX_HEADING_LEVEL = 6;\n/** Word supports nine list levels. */\nconst MAX_LIST_LEVEL = 9;\n\n/**\n * Strip the inline decorators `createHeading` consumes, so a cached entry shows\n * \"Results\" rather than \"**Results**\".\n */\nexport function normalizeEntryTitle(text: string): string {\n return normalizeUnicodeText(text)\n .replace(/(\\*\\*\\*|___)([\\s\\S]*?)\\1/g, '$2')\n .replace(/(\\*\\*|__)([\\s\\S]*?)\\1/g, '$2')\n .replace(/(\\*|_)([\\s\\S]*?)\\1/g, '$2')\n .trim();\n}\n\n/** Component names whose `children` a rendered heading can hide inside. */\nfunction isContainer(name: string): boolean {\n return getStandardComponent(name)?.hasChildren === true;\n}\n\nfunction isEnabled(component: ComponentDefinition): boolean {\n return !('enabled' in component && component.enabled === false);\n}\n\n/**\n * A paragraph contributes a TOC entry only through a custom `themeStyle`.\n * `heading1`..`heading6` are deliberately excluded: those map to the\n * display-only `JTD_HeadingText*` styles, which carry no outline level exactly\n * so paragraph text cannot masquerade as a heading.\n */\nfunction styleEntryKey(props: Record<string, unknown>): string | undefined {\n const themeStyle = props.themeStyle;\n if (typeof themeStyle !== 'string' || !themeStyle) return undefined;\n if (/^heading[1-6]$/i.test(themeStyle)) return undefined;\n if (['normal', 'title', 'subtitle'].includes(themeStyle.toLowerCase())) {\n return undefined;\n }\n return themeStyle;\n}\n\n/** Item shape a `list` component's `items` array can hold. */\ntype ListItem = {\n text?: unknown;\n level?: unknown;\n revision?: unknown;\n id?: unknown;\n};\n\n/** Per numbering reference: its level definitions and where each counter is. */\ninterface ListCounterState {\n levels: readonly ListLevelConfig[];\n /** One slot per list level, already decremented to \"before the start\". */\n counters: number[];\n}\n\nfunction levelStart(levels: readonly ListLevelConfig[], level: number): number {\n return levels[level]?.start ?? 1;\n}\n\n/**\n * Walk the document once and derive everything render needs to know about it up\n * front: the TOC entries, the heading numbers, and the cross-reference targets\n * keyed by the bookmark ids render will produce.\n *\n * The id prediction is the delicate part. `renderHeadingComponent` slugs a\n * heading's text and disambiguates it against bookmarks registered *so far*, so\n * this walk must see the same ids in the same order — including the explicit\n * `props.id` a paragraph registers — or a cross-reference resolves against an\n * id that never gets written.\n */\nexport function collectDocumentOutline(\n sections: readonly SectionLayout[]\n): DocumentOutline {\n const entries: TocHeadingEntry[] = [];\n const numberedItems = new Map<string, NumberedItemInfo>();\n const ordinals = computeSectionOrdinals(sections);\n\n // Bookmark ids already claimed, in walk order — the pre-pass mirror of the\n // bookmark registry render fills as it goes.\n const takenIds = new Set<string>();\n const headingCounters = new Array<number>(MAX_HEADING_LEVEL).fill(0);\n // Lists sharing an explicit `reference` share one numbering definition, so\n // their counters continue. An auto-generated reference is unique per list, so\n // such a list gets a fresh state that nothing else can reach.\n const listCounters = new Map<string, ListCounterState>();\n\n const visitHeading = (\n component: ComponentDefinition,\n props: Record<string, unknown>,\n sectionBookmarkId: string | undefined\n ): void => {\n const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n const level = typeof props.level === 'number' ? props.level : 1;\n // Mirrors getStyleIdForLevel: an out-of-range level renders as Heading1.\n const styleLevel = level >= 1 && level <= MAX_HEADING_LEVEL ? level : 1;\n\n let full: string | undefined;\n let own: string | undefined;\n if (props.numbering === true) {\n headingCounters[styleLevel - 1] += 1;\n for (let deeper = styleLevel; deeper < MAX_HEADING_LEVEL; deeper++) {\n headingCounters[deeper] = 0;\n }\n // A level-3 heading with no level-2 above it numbers \"1.0.1\", exactly as\n // Word does; there is nothing to special-case.\n full = headingCounters.slice(0, styleLevel).join('.');\n own = String(headingCounters[styleLevel - 1]);\n }\n\n const explicitId = (component as { id?: unknown }).id;\n const bookmarkId =\n typeof explicitId === 'string' && explicitId\n ? explicitId\n : dedupeBookmarkId(slugifyBookmarkText(text), (id) => takenIds.has(id));\n takenIds.add(bookmarkId);\n numberedItems.set(bookmarkId, {\n kind: 'heading',\n text: title,\n ...(full !== undefined && { full, own }),\n });\n\n if (title) {\n entries.push({\n title,\n level,\n sectionBookmarkId,\n ...(full !== undefined && { number: full }),\n });\n }\n };\n\n const visitList = (props: Record<string, unknown>): void => {\n const items = Array.isArray(props.items)\n ? (props.items as (string | ListItem)[])\n : [];\n if (items.length === 0) return;\n\n const reference =\n typeof props.reference === 'string' && props.reference\n ? props.reference\n : undefined;\n\n const freshState = (): ListCounterState => {\n const levels = resolveListLevels(\n props as Parameters<typeof resolveListLevels>[0]\n );\n return {\n levels,\n counters: Array.from(\n { length: MAX_LIST_LEVEL },\n (_, level) => levelStart(levels, level) - 1\n ),\n };\n };\n\n let state: ListCounterState;\n if (reference === undefined) {\n state = freshState();\n } else {\n state = listCounters.get(reference) ?? freshState();\n listCounters.set(reference, state);\n }\n\n for (const item of items) {\n const isObject = typeof item === 'object' && item !== null;\n const raw = isObject ? item.text : item;\n const text = typeof raw === 'string' ? raw : '';\n // Same skip rule as createList: an empty item renders nothing and so\n // never advances the counter.\n if (!text.trim() && !(isObject && item.revision)) continue;\n\n const rawLevel = isObject ? item.level : undefined;\n const level =\n typeof rawLevel === 'number' && rawLevel >= 0 ? rawLevel : 0;\n if (level >= MAX_LIST_LEVEL) continue;\n\n state.counters[level] += 1;\n for (let deeper = level + 1; deeper < MAX_LIST_LEVEL; deeper++) {\n state.counters[deeper] = levelStart(state.levels, deeper) - 1;\n }\n\n const id = isObject ? item.id : undefined;\n if (typeof id !== 'string' || !id) continue;\n takenIds.add(id);\n // A single level's counter, not a \"1.a.i\" chain: Word's `\\r` switch on a\n // list item shows the item's own number.\n const number = formatNumberForLevel(\n state.counters[level],\n state.levels[level]?.format\n );\n numberedItems.set(id, {\n kind: 'list-item',\n text: normalizeUnicodeText(text).trim(),\n ...(number !== undefined && { full: number, own: number }),\n });\n }\n };\n\n sections.forEach((section, index) => {\n // Ordinal 0 means a continuation chunk that appears before any opening\n // chunk — there is no bookmark to scope to. `renderSection` applies the\n // same truthiness test, so the two must stay in step: making either side\n // treat 0 as a real ordinal would emit entries scoped to a `_Section_0`\n // bookmark the renderer never writes.\n const ordinal = ordinals[index]?.ordinal;\n const sectionBookmarkId = ordinal ? sectionBookmark(ordinal).id : undefined;\n\n const visit = (component: ComponentDefinition): void => {\n if (!isEnabled(component)) return;\n\n const props = (component.props ?? {}) as Record<string, unknown>;\n\n if (component.name === 'heading') {\n visitHeading(component, props, sectionBookmarkId);\n return;\n }\n\n if (component.name === 'paragraph') {\n // `props.id` is the bookmark a paragraph registers when it renders;\n // claiming it here keeps a later heading slug dedupe in step.\n if (typeof props.id === 'string' && props.id) takenIds.add(props.id);\n\n const styleId = styleEntryKey(props);\n const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n if (styleId && title) {\n // Level is decided by the TOC's own style mapping, not here.\n entries.push({ title, level: 1, styleId, sectionBookmarkId });\n }\n return;\n }\n\n if (component.name === 'list') {\n visitList(props);\n return;\n }\n\n if (!isContainer(component.name)) return;\n const children = (component as { children?: ComponentDefinition[] })\n .children;\n if (Array.isArray(children)) children.forEach(visit);\n };\n\n // `section.components` only — headers and footers live on their own fields\n // and never reach the TOC.\n section.components.forEach(visit);\n });\n\n return { entries, numberedItems };\n}\n\n/**\n * Collect every TOC-eligible entry in document order, tagged with the layout\n * section it belongs to so a section-scoped TOC can filter to its own.\n */\nexport function collectTocHeadings(\n sections: readonly SectionLayout[]\n): TocHeadingEntry[] {\n return collectDocumentOutline(sections).entries;\n}\n","/**\n * The bookmark a section is addressable by.\n *\n * `w:bookmarkStart/@w:name` is what a section-scoped table of contents resolves\n * its `\\b` switch against, so the name has to be derivable identically by\n * whoever writes the bookmark and whoever points at it. It is derived from the\n * section's ordinal, and both sides call this.\n *\n * This used to be a registry with per-render state, because the pre-IR writer\n * had two producers allocating from two different traversal orders. The\n * compiler has one, so a pure function is enough.\n */\n\n/** A resolved OOXML bookmark: its name plus the numeric id its ends share. */\nexport interface SectionBookmark {\n /** `w:bookmarkStart/@w:name`, and the TOC `\\b` switch argument. */\n id: string;\n /** `w:bookmarkStart/@w:id` / `w:bookmarkEnd/@w:id`. */\n linkId: number;\n}\n\n/**\n * The bookmark for a layout section, derived from its ordinal.\n *\n * Every layout chunk of one user-defined section shares an ordinal (see\n * `computeSectionOrdinals`), so they all resolve to the same bookmark — which\n * is the point: the start lands in the first chunk and the end in the last.\n */\nexport function sectionBookmark(ordinal: number): SectionBookmark {\n return { id: `_Section_${ordinal}`, linkId: ordinal };\n}\n","/**\n * Render a list counter the way Word renders it, for the cached value of a\n * cross-reference field.\n *\n * Only the formats whose glyph sequence is unambiguous are supported. Anything\n * else (bullets, CJK counting, `none`, an unknown string) returns undefined —\n * the caller then emits a field with no cached value rather than guessing a\n * number Word would disagree with on refresh.\n */\n\nconst ROMAN_NUMERALS: readonly (readonly [number, string])[] = [\n [1000, 'm'],\n [900, 'cm'],\n [500, 'd'],\n [400, 'cd'],\n [100, 'c'],\n [90, 'xc'],\n [50, 'l'],\n [40, 'xl'],\n [10, 'x'],\n [9, 'ix'],\n [5, 'v'],\n [4, 'iv'],\n [1, 'i'],\n];\n\nfunction toRoman(value: number): string {\n let remaining = value;\n let out = '';\n for (const [amount, glyph] of ROMAN_NUMERALS) {\n while (remaining >= amount) {\n out += glyph;\n remaining -= amount;\n }\n }\n return out;\n}\n\n/**\n * Word's letter sequence repeats the glyph rather than carrying: a, …, z, aa,\n * bb, …, zz, aaa. (`27` is \"aa\", not \"ab\".)\n */\nfunction toLetters(value: number): string {\n const index = (value - 1) % 26;\n const repeats = Math.floor((value - 1) / 26) + 1;\n return String.fromCharCode(97 + index).repeat(repeats);\n}\n\nexport function formatNumberForLevel(\n value: number,\n format?: string\n): string | undefined {\n if (!Number.isFinite(value) || value < 1) return undefined;\n const n = Math.floor(value);\n\n switch (format) {\n case 'decimal':\n return String(n);\n case 'lowerLetter':\n return toLetters(n);\n case 'upperLetter':\n return toLetters(n).toUpperCase();\n case 'lowerRoman':\n return toRoman(n);\n case 'upperRoman':\n return toRoman(n).toUpperCase();\n default:\n return undefined;\n }\n}\n","/**\n * The `toc` component, resolved into the switches a Word field needs.\n *\n * A table of contents is a field: Word repopulates it on open from the outline\n * and the switches the field carries. Deciding what those switches say — which\n * outline levels, which extra styles, which region, which levels keep their\n * page numbers — is a reading of the authoring props with no renderer in it.\n *\n * The cached entries are the other half. Word refreshes the field, but headless\n * LibreOffice does not, so without them a PDF export shows only the title. What\n * is cached must be exactly what Word would collect, or a reader pressing F9\n * sees the table change under them — the disagreement caching exists to avoid.\n */\n\nimport type { ThemeConfig } from '../styles';\nimport type { TocHeadingEntry } from './collectTocHeadings';\nimport { headingNumberLabel } from '../utils/numberingConfig';\n\nexport interface TocFieldEntry {\n text: string;\n level: number;\n}\n\nexport interface ResolvedTocField {\n /** `\\o` — heading outline levels to include, inclusive. */\n headingRange: { from: number; to: number };\n /** `\\t` — extra paragraph styles, by Word display name, with their level. */\n styleLevels: Array<{ styleName: string; level: number }>;\n /** `\\b` — restrict to a bookmarked region. */\n bookmarkScope?: string;\n /** `\\n` — level ranges whose entries omit a page number. */\n omitPageNumbersForLevels: Array<{ from: number; to: number }>;\n /** What separates an entry's text from its page number. */\n entrySeparator: string;\n entries: TocFieldEntry[];\n /** Things the field cannot express, to be reported by the caller. */\n warnings: string[];\n}\n\n/**\n * The Word display name a theme style key registers under: camelCase and\n * kebab/snake separators become spaces (`calloutTitle` → `callout Title`).\n * Mirrors the naming in `themeToDocxAdapter`.\n */\nexport function toStyleDisplayName(styleId: string): string {\n return styleId\n .replace(/([A-Z])/g, ' $1')\n .replace(/[-_]+/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\n/** Validate a `{from, to}` depth range, filling in the defaults. */\nfunction parseDepthRange(\n rawDepth: unknown,\n fieldName: string,\n defaultFrom = 1,\n defaultTo = 3\n): { from: number; to: number } {\n if (typeof rawDepth !== 'object' || rawDepth === null) {\n throw new Error(\n `${fieldName} must be a range object with optional \"from\" and/or \"to\" fields, received: ${JSON.stringify(rawDepth)}`\n );\n }\n\n const { from = defaultFrom, to = defaultTo } = rawDepth as {\n from?: number;\n to?: number;\n };\n\n if (from < 1 || from > 6 || to < 1 || to > 6) {\n throw new Error(\n `${fieldName} range values must be between 1 and 6, received: from=${from}, to=${to}`\n );\n }\n if (from > to) {\n throw new Error(\n `${fieldName} \"from\" must be less than or equal to \"to\", received: from=${from}, to=${to}`\n );\n }\n\n return { from, to };\n}\n\n/**\n * The entries this TOC would show, in document order.\n *\n * Mirrors what Word's own refresh does with the switches:\n * - `\\o` outline range: heading entries inside [from, to];\n * - `\\t` style mappings: paragraphs whose `themeStyle` this TOC maps, at the\n * mapped level — Word includes those whatever the outline range says, so they\n * are not depth-filtered here either;\n * - `\\b` bookmark: when the TOC is section-scoped, only that section's entries.\n */\nfunction selectEntries(\n collected: readonly TocHeadingEntry[] | undefined,\n options: {\n depthStart: number;\n depthEnd: number;\n bookmarkScope?: string;\n styleLevels: ReadonlyMap<string, number>;\n }\n): TocFieldEntry[] {\n if (!collected || collected.length === 0) return [];\n\n const { depthStart, depthEnd, bookmarkScope, styleLevels } = options;\n const entries: TocFieldEntry[] = [];\n\n for (const entry of collected) {\n if (bookmarkScope && entry.sectionBookmarkId !== bookmarkScope) continue;\n\n if (entry.styleId !== undefined) {\n // The entry carries the theme key; the mapping may have named the\n // display name instead.\n const level =\n styleLevels.get(entry.styleId) ??\n styleLevels.get(toStyleDisplayName(entry.styleId));\n if (level === undefined) continue;\n entries.push({ text: entry.title, level });\n continue;\n }\n\n if (entry.level < depthStart || entry.level > depthEnd) continue;\n // No page number: nothing in generation paginates, and Word fills in real\n // numbers the moment it refreshes. A numbered heading shows its number in\n // that refresh, so the cached copy carries it too — same form, trailing\n // period included, or the entry visibly shifts on the first F9.\n entries.push({\n text: entry.number\n ? `${headingNumberLabel(entry.number)} ${entry.title}`\n : entry.title,\n level: entry.level,\n });\n }\n\n return entries;\n}\n\nexport interface TocFieldSource {\n depth?: unknown;\n pageNumbersDepth?: unknown;\n includePageNumbers?: boolean;\n numberingStyle?: string;\n numberSeparator?: boolean;\n scope?: 'auto' | 'document' | 'section';\n styles?: Array<{ styleId: string; level: number }>;\n title?: string;\n}\n\n/** Resolve a `toc` component's props into field switches and cached entries. */\nexport function resolveTocField(\n props: TocFieldSource,\n theme: ThemeConfig,\n context: {\n /** The bookmark of the section this TOC sits in, if any. */\n sectionBookmarkId?: string;\n /** Every heading and mapped-style paragraph in the document, in order. */\n collected?: readonly TocHeadingEntry[];\n }\n): ResolvedTocField {\n const warnings: string[] = [];\n const headingRange = parseDepthRange(\n props.depth ?? { to: 3 },\n 'TOC depth',\n 1,\n 3\n );\n\n const pageNumbers =\n props.pageNumbersDepth !== undefined\n ? parseDepthRange(props.pageNumbersDepth, 'TOC pageNumbersDepth', 1, 3)\n : undefined;\n\n // `numberingStyle` has no representation in the field: it carries no\n // numbering switch, so entries always inherit the numbering of the heading\n // styles they point at. The prop stays in the schema — documents already set\n // it — but the no-op is announced rather than swallowed.\n if (props.numberingStyle !== undefined) {\n warnings.push(\n `TOC numberingStyle \"${props.numberingStyle}\" is ignored: Word's ` +\n 'table-of-contents field has no numbering switch. TOC entries inherit ' +\n 'numbering from the heading styles they reference.'\n );\n }\n\n const scope = props.scope ?? 'auto';\n const effectiveScope =\n scope === 'auto'\n ? context.sectionBookmarkId\n ? 'section'\n : 'document'\n : scope;\n const bookmarkScope =\n effectiveScope === 'section' ? context.sectionBookmarkId : undefined;\n\n if (effectiveScope === 'section' && !bookmarkScope) {\n warnings.push(\n 'TOC configured for section scope but no section bookmark found. Falling back to document scope.'\n );\n }\n\n // A mapping may name a style either way — by the theme key an author writes\n // in `themeStyle`, or by the Word display name the `\\t` switch needs — and a\n // collected entry always carries the theme key. Indexing both keeps the\n // cached entries in step with what Word collects on refresh.\n const styleLevels = new Map<string, number>();\n const styleSwitches: Array<{ styleName: string; level: number }> = [];\n for (const mapping of props.styles ?? []) {\n const isCustomStyle =\n !!theme.styles &&\n Object.prototype.hasOwnProperty.call(theme.styles, mapping.styleId);\n const displayName = isCustomStyle\n ? toStyleDisplayName(mapping.styleId)\n : mapping.styleId;\n\n styleLevels.set(mapping.styleId, mapping.level);\n styleLevels.set(displayName, mapping.level);\n styleSwitches.push({ styleName: displayName, level: mapping.level });\n }\n\n return {\n headingRange,\n styleLevels: styleSwitches,\n ...(bookmarkScope ? { bookmarkScope } : {}),\n omitPageNumbersForLevels: omittedLevels(\n headingRange,\n pageNumbers,\n props.includePageNumbers !== false\n ),\n // A boolean chooses between a tab and a space; a tab is the default.\n entrySeparator: props.numberSeparator === false ? ' ' : '\\t',\n entries: selectEntries(context.collected, {\n depthStart: headingRange.from,\n depthEnd: headingRange.to,\n bookmarkScope,\n styleLevels,\n }),\n warnings,\n };\n}\n\n/**\n * Which levels lose their page numbers.\n *\n * The `\\n` switch names the levels to *omit*, so a stated \"show page numbers\n * for 2-3\" becomes \"omit 1 and 4-6\" — the blocks either side of the range that\n * keeps them.\n */\nfunction omittedLevels(\n headingRange: { from: number; to: number },\n pageNumbers: { from: number; to: number } | undefined,\n includePageNumbers: boolean\n): Array<{ from: number; to: number }> {\n if (pageNumbers) {\n const omitted: Array<{ from: number; to: number }> = [];\n if (pageNumbers.from > headingRange.from) {\n omitted.push({ from: headingRange.from, to: pageNumbers.from - 1 });\n }\n if (pageNumbers.to < headingRange.to) {\n omitted.push({ from: pageNumbers.to + 1, to: headingRange.to });\n }\n return omitted;\n }\n return includePageNumbers ? [] : [headingRange];\n}\n","/**\n * Markdown list syntax inside a paragraph's text.\n *\n * A paragraph whose whole text is `- one\\n- two` is a list, not prose, and has\n * always rendered as one. Detecting that is a pure reading of the text with no\n * renderer in it, so both the pre-IR writer and the DocxIR compiler read it\n * here rather than each deciding for itself what counts as a list.\n */\n\nexport interface MarkdownList {\n type: 'unordered' | 'ordered';\n items: { text: string; level: number }[];\n}\n\n/**\n * Parse markdown list syntax from paragraph text\n * Returns null if no list detected, or { type, items } if list found\n */\nexport function parseMarkdownList(text: string): MarkdownList | null {\n const lines = text.split('\\n');\n const items: { text: string; level: number }[] = [];\n let isUnordered: boolean | null = null;\n let isOrdered: boolean | null = null;\n\n for (const line of lines) {\n // Skip empty lines\n if (!line.trim()) continue;\n\n // Match unordered list: optional spaces + (- or *) + space + text\n const unorderedMatch = line.match(/^(\\s*)([-*])\\s+(.+)$/);\n if (unorderedMatch) {\n const indentLevel = Math.floor(unorderedMatch[1].length / 2); // 2 spaces = 1 level\n const text = unorderedMatch[3];\n items.push({ text, level: indentLevel });\n if (isUnordered === null) isUnordered = true;\n continue;\n }\n\n // Match ordered list: optional spaces + number + . + space + text\n const orderedMatch = line.match(/^(\\s*)(\\d+)\\.\\s+(.+)$/);\n if (orderedMatch) {\n const indentLevel = Math.floor(orderedMatch[1].length / 2); // 2 spaces = 1 level\n const text = orderedMatch[3];\n items.push({ text, level: indentLevel });\n if (isOrdered === null) isOrdered = true;\n continue;\n }\n\n // If we find a line that doesn't match list syntax, this isn't a list\n return null;\n }\n\n // If no items found, or mixed list types, not a valid list\n if (items.length === 0 || (isUnordered && isOrdered)) {\n return null;\n }\n\n return {\n type: isUnordered ? 'unordered' : 'ordered',\n items,\n };\n}\n","/**\n * The inline text mini-language, parsed into IR nodes.\n *\n * Authoring writes `**bold**`, `\\n`, `\\t` and friends inside a single string.\n * By the time DocxIR exists none of that is markup any more: it is text runs,\n * line breaks and tab runs, each carrying resolved formatting.\n *\n * This is deliberately a separate module from `compiler.ts`. The mini-language\n * is the one piece of DOCX authoring with its own grammar, and it is where the\n * subtle rules live — a decorator pair may straddle a newline, a tab has to\n * become a real tab run because a tab character inside `<w:t>` is dropped, and\n * a no-proof word has to be its own run so the flag can sit on it alone.\n *\n * Scope: decorators, line breaks, tabs, no-proof words, `[text](target)` links\n * and `{PLACEHOLDER}` tokens. Cross-references and note markers are recognised\n * only so the compiler can refuse them explicitly rather than render them as\n * the literal characters an author wrote as markup — see\n * `containsUnsupportedSyntax`.\n */\n\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport type { DocxIrInline, DocxIrRunFormatting } from './types';\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * A matcher for the known-words allowlist, or null when there is nothing to\n * match.\n *\n * Each word matches as a whole token — no letter or digit directly either side\n * — so `Wiseair` does not match inside `Wiseairy`, while internal punctuation\n * like `json-to-office` matches literally.\n */\nexport function buildNoProofWordsRegex(noProofWords?: string[]): RegExp | null {\n const words = (noProofWords ?? []).filter((word) => word?.trim().length > 0);\n if (words.length === 0) return null;\n // Longest first, so the alternation prefers the most specific match.\n const escaped = words\n .slice()\n .sort((a, b) => b.length - a.length)\n .map(escapeRegExp);\n return new RegExp(\n `(?<![\\\\p{L}\\\\p{N}])(?:${escaped.join('|')})(?![\\\\p{L}\\\\p{N}])`,\n 'giu'\n );\n}\n\n/**\n * Decorator pairs, longest first so `***` wins over `**` and `*`.\n *\n * `[\\s\\S]` rather than `.` because a decorated span may cross a newline; the\n * line break inside it still has to break the line.\n */\nconst DECORATOR =\n /(\\*\\*\\*|___)([\\s\\S]*?)\\1|(\\*\\*|__)([\\s\\S]*?)\\3|(\\*|_)([\\s\\S]*?)\\5/g;\n\n/** Markdown link syntax: `[text](target)`. */\nconst LINK = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n\n/**\n * Decorators and `{PLACEHOLDER}` in one pass.\n *\n * They cannot be parsed separately: a placeholder may sit inside a decorated\n * span, and a decorated span may sit between two placeholders.\n */\nconst DECORATOR_OR_PLACEHOLDER =\n /(\\*\\*\\*|___)([\\s\\S]*?)\\1|(\\*\\*|__)([\\s\\S]*?)\\3|(\\*|_)([\\s\\S]*?)\\5|\\{([^}]+)\\}/g;\n\n/** `{NAME}`, the placeholder syntax. */\nconst PLACEHOLDER = /\\{([^}]+)\\}/;\n\n/** Syntax this parser does not lower, each with the feature that would cover it. */\nconst UNSUPPORTED_SYNTAX: ReadonlyArray<{\n pattern: RegExp;\n what: string;\n}> = [];\n\n/** `[@id]` or `[@id:format]`, the cross-reference syntax. */\nconst CROSS_REFERENCE =\n /\\[@([^\\]\\s:]+)(?::(relative|no_context|full_context|none))?\\]/;\n\n/**\n * One pass over both bracket syntaxes.\n *\n * Parsing them separately would mean re-scanning the segments between one kind\n * of token for the other kind, while the plain text between them still has to\n * reach the decorator parser.\n */\nconst INLINE_TOKEN = new RegExp(\n `${LINK.source}|${CROSS_REFERENCE.source}`,\n 'g'\n);\n\n/** `[^id]`, the note marker syntax. */\nconst NOTE_MARKER = /\\[\\^([^\\]\\s]+)\\]/g;\n\n/** True when the text carries a `{PLACEHOLDER}` token. */\nexport function containsPlaceholder(text: string): boolean {\n return PLACEHOLDER.test(text);\n}\n\n/** True when the text carries a `[@id]` cross-reference. */\nexport function containsCrossReference(text: string): boolean {\n return new RegExp(CROSS_REFERENCE.source).test(text);\n}\n\n/** True when the text carries a `[text](target)` link. */\nexport function containsLink(text: string): boolean {\n return new RegExp(LINK.source).test(text);\n}\n\n/**\n * Name the first piece of syntax in `text` this parser cannot lower.\n *\n * The compiler calls this before parsing so an unsupported construct is\n * reported rather than silently rendered as the literal characters an author\n * wrote as markup.\n */\nexport function containsUnsupportedSyntax(text: string): string | undefined {\n for (const { pattern, what } of UNSUPPORTED_SYNTAX) {\n if (pattern.test(text)) return what;\n }\n return undefined;\n}\n\nexport interface ParseInlineOptions {\n /** Formatting every run starts from. */\n base: DocxIrRunFormatting;\n /**\n * Lower `[text](target)` into hyperlink nodes.\n *\n * Off by default: a component that does not accept links renders the\n * brackets as the literal characters the author typed, which is what the\n * pipeline has always done.\n */\n hyperlinks?: boolean;\n /**\n * Colour applied to a run only because a decorator made it bold.\n *\n * A separate colour for emphasised text is an authoring feature, so it is\n * resolved here rather than left for a renderer to infer from `bold`.\n */\n boldColor?: { hex: string };\n /** Words to mark `noProof`, each split into a run of its own. */\n noProofWords?: string[];\n /**\n * Resolve a `{NAME}` token. Returning nothing leaves it as literal text.\n *\n * A placeholder's meaning is document state — the generation date, the page\n * being drawn — so the compiler supplies it rather than this module knowing\n * any of it.\n */\n resolvePlaceholder?: (name: string) => PlaceholderResolution | undefined;\n /**\n * Resolve a `[^id]` marker to a note. Returning nothing leaves it literal.\n *\n * Resolution happens at the leaf, after decorators: a marker inside\n * `**bold[^n]**` keeps the surrounding emphasis, which splitting earlier\n * would break by cutting the `**` pair across segments.\n */\n resolveNote?: (\n id: string\n ) => { id: number; noteKind: 'footnote' | 'endnote' } | undefined;\n /**\n * Resolve a `[@id]` token to a field, or to nothing to leave it literal.\n *\n * The target may appear later in the document, so only a pre-pass over the\n * whole outline can answer this — which is why the compiler supplies it.\n */\n resolveCrossReference?: (\n id: string,\n format: CrossReferenceFormat,\n token: string\n ) => DocxIrInline | undefined;\n}\n\n/** The `\\r`-style switches a `[@id:format]` token may ask for. */\nexport type CrossReferenceFormat =\n | 'relative'\n | 'no_context'\n | 'full_context'\n | 'none';\n\n/**\n * Parse authored text into inline IR nodes.\n *\n * The shape of the output mirrors what the format needs rather than what the\n * grammar looked like: a decorated span becomes runs with `bold`/`italic` set,\n * a `\\n` becomes a `lineBreak` node, a `\\t` becomes a `tab` node.\n */\nexport function parseInline(\n text: string,\n options: ParseInlineOptions\n): DocxIrInline[] {\n const normalized = normalizeUnicodeText(text);\n if (!normalized) {\n return [\n { kind: 'text', text: '', formatting: emptyToUndefined(options.base) },\n ];\n }\n // A placeholder-bearing text takes its own parser, which is also where\n // decorators are handled for it — links and note markers never reach it,\n // exactly as in the pre-IR writer.\n if (containsPlaceholder(normalized)) {\n return parsePlaceholders(normalized, options);\n }\n if (options.hyperlinks) return parseLinks(normalized, options);\n return parseDecorated(normalized, options);\n}\n\n/**\n * A placeholder resolved to something concrete.\n *\n * `field` is a live field Word recomputes (a page number); `text` is resolved\n * once, at generation time (a date). An unknown name resolves to nothing and\n * the token stays as the characters the author typed.\n */\nexport type PlaceholderResolution =\n | { kind: 'field'; instruction: string }\n | { kind: 'text'; text: string };\n\n/**\n * Split on decorators and placeholders together.\n *\n * A decorated span is re-parsed rather than emitted directly, because it may\n * contain a placeholder of its own; the emphasis it applies is folded into the\n * base style for that pass.\n */\nfunction parsePlaceholders(\n normalized: string,\n parseOptions: ParseInlineOptions\n): DocxIrInline[] {\n // Two things the placeholder path has never done, reproduced rather than\n // tidied: it does not consult a separate colour for emphasised text, so a\n // bold span alongside a placeholder keeps the paragraph's colour; and it does\n // not recognise `[^id]` markers, so one written alongside a placeholder stays\n // as the characters the author typed. The note binding reports that.\n const options: ParseInlineOptions = {\n ...parseOptions,\n boldColor: undefined,\n resolveNote: undefined,\n };\n const out: DocxIrInline[] = [];\n const token = new RegExp(DECORATOR_OR_PLACEHOLDER.source, 'g');\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n const literal = (text: string, base = options.base): void => {\n if (!text) return;\n out.push(...parseLiteralLines(text, { ...options, base }));\n };\n\n while ((match = token.exec(normalized)) !== null) {\n if (match.index > lastIndex) {\n literal(normalized.slice(lastIndex, match.index));\n }\n lastIndex = match.index + match[0].length;\n\n if (match[7]) {\n const resolved = options.resolvePlaceholder?.(match[7]);\n if (!resolved) {\n // Unknown name: the token stays as written.\n literal(match[0]);\n } else if (resolved.kind === 'text') {\n literal(resolved.text);\n } else {\n // A field run carries only the character formatting a reader sees on\n // the number itself. Proofing language, scale and letter spacing are\n // properties of prose, and the pipeline has never put them on a field.\n const formatting = emptyToUndefined({\n fontFamily: options.base.fontFamily,\n sizeHalfPoints: options.base.sizeHalfPoints,\n color: options.base.color,\n bold: options.base.bold,\n italic: options.base.italic,\n underline: options.base.underline,\n });\n out.push({\n kind: 'field',\n instruction: resolved.instruction,\n ...(formatting ? { formatting } : {}),\n });\n }\n continue;\n }\n\n const style = decoratedStyle(match, options.base);\n out.push(\n ...parsePlaceholders(decoratedText(match), {\n ...options,\n base: { ...options.base, ...style },\n // No-proof words do not survive into a decorated span here: the\n // recursion has always been entered without them.\n noProofWords: undefined,\n })\n );\n }\n\n if (lastIndex < normalized.length) literal(normalized.slice(lastIndex));\n if (out.length === 0 && normalized) literal(normalized);\n return out;\n}\n\n/** Text split on newlines, tabs and no-proof words, with no other syntax. */\nfunction parseLiteralLines(\n text: string,\n options: ParseInlineOptions\n): DocxIrInline[] {\n const out: DocxIrInline[] = [];\n pushSegment(out, text, options);\n return out;\n}\n\n/**\n * Text with no mini-language at all.\n *\n * A heading with no decorators and no cross-reference is rendered character for\n * character: brackets stay brackets, and a newline stays inside the text rather\n * than breaking the line. Only no-proof words are still split out, because the\n * flag has to sit on exactly those runs.\n */\nexport function parseLiteral(\n text: string,\n options: ParseInlineOptions\n): DocxIrInline[] {\n const out: DocxIrInline[] = [];\n pushWords(\n out,\n normalizeUnicodeText(text),\n emptyToUndefined(options.base),\n options\n );\n return out;\n}\n\n/**\n * Split on `[text](target)`, parsing each side for decorators.\n *\n * A link's own text is parsed the same way any other span is, so\n * `[**bold link**](url)` keeps its emphasis: the link wraps runs rather than\n * being one.\n */\nfunction parseLinks(\n normalized: string,\n options: ParseInlineOptions\n): DocxIrInline[] {\n const out: DocxIrInline[] = [];\n const token = new RegExp(INLINE_TOKEN.source, 'g');\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = token.exec(normalized)) !== null) {\n if (match.index > lastIndex) {\n out.push(\n ...parseDecorated(normalized.slice(lastIndex, match.index), options)\n );\n }\n lastIndex = match.index + match[0].length;\n\n // Group 1 is the link's text; absent means the cross-reference branch of\n // the alternation matched.\n if (match[1] === undefined) {\n const resolved = options.resolveCrossReference?.(\n match[3],\n (match[4] as CrossReferenceFormat | undefined) ?? 'relative',\n match[0]\n );\n if (resolved) out.push(resolved);\n else out.push(...parseDecorated(match[0], options));\n continue;\n }\n\n const [, linkText, target] = match;\n out.push({\n kind: 'hyperlink',\n // A `#anchor` target names a bookmark in this document and needs no\n // relationship; anything else leaves the document.\n target: target.startsWith('#')\n ? { kind: 'bookmark', anchor: target.slice(1) }\n : { kind: 'external', url: target },\n children: parseDecorated(linkText, options),\n });\n }\n\n if (lastIndex < normalized.length) {\n out.push(...parseDecorated(normalized.slice(lastIndex), options));\n }\n\n if (out.length === 0) return parseDecorated(normalized, options);\n return out;\n}\n\nfunction parseDecorated(\n normalized: string,\n options: ParseInlineOptions\n): DocxIrInline[] {\n const out: DocxIrInline[] = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n const decorator = new RegExp(DECORATOR.source, 'g');\n\n while ((match = decorator.exec(normalized)) !== null) {\n if (match.index > lastIndex) {\n pushSegment(out, normalized.slice(lastIndex, match.index), options);\n }\n pushSegment(\n out,\n decoratedText(match),\n options,\n decoratedStyle(match, options.base)\n );\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < normalized.length) {\n pushSegment(out, normalized.slice(lastIndex), options);\n }\n\n if (out.length === 0) pushSegment(out, normalized, options);\n return out;\n}\n\nfunction decoratedText(match: RegExpExecArray): string {\n if (match[1]) return match[2];\n if (match[3]) return match[4];\n if (match[5]) return match[6];\n return match[0];\n}\n\n/**\n * The formatting a decorator imposes.\n *\n * Both flags are stated, not just the one the decorator names: `**bold**` means\n * bold *and not italic*, so the run says so rather than inheriting whatever the\n * surrounding style had.\n */\nfunction decoratedStyle(\n match: RegExpExecArray,\n base: DocxIrRunFormatting\n): { bold: boolean; italic: boolean } {\n const bold = base.bold ?? false;\n const italic = base.italic ?? false;\n if (match[1]) return { bold: true, italic: true };\n if (match[3]) return { bold: true, italic };\n if (match[5]) return { bold, italic: true };\n return { bold, italic };\n}\n\n/**\n * Emit the nodes for one span of text sharing formatting.\n *\n * Splits on `\\n` into lines and on `\\t` within a line, then splits each\n * remaining piece around any no-proof word.\n */\nfunction pushSegment(\n out: DocxIrInline[],\n text: string,\n options: ParseInlineOptions,\n override: { bold?: boolean; italic?: boolean } = {}\n): void {\n const bold = override.bold ?? options.base.bold;\n const italic = override.italic ?? options.base.italic;\n const formatting = runFormatting(options, { bold, italic });\n\n const lines = text.split('\\n');\n for (const [lineIndex, line] of lines.entries()) {\n // A blank line is only worth a node when a break precedes it: a blank line\n // in the middle of a paragraph is a visible gap, whereas an empty segment\n // — between two decorators, say — is nothing at all.\n if (!line && lineIndex === 0) continue;\n if (lineIndex > 0) out.push({ kind: 'lineBreak' });\n if (!line) {\n out.push({ kind: 'text', text: '', formatting });\n continue;\n }\n\n const tabSegments = line.split('\\t');\n for (const [tabIndex, segment] of tabSegments.entries()) {\n if (tabIndex > 0) out.push({ kind: 'tab', formatting });\n // An empty piece around a tab carries nothing; a line that is *only*\n // empty still needs its run so the break has somewhere to sit.\n if (!segment && tabSegments.length > 1) continue;\n pushWords(out, segment, formatting, options);\n }\n }\n}\n\n/**\n * Split around no-proof words so the flag sits on exactly those runs.\n *\n * A run already marked `noProof` has nothing to single out, so it stays whole.\n */\nfunction pushWords(\n out: DocxIrInline[],\n text: string,\n formatting: DocxIrRunFormatting | undefined,\n options: ParseInlineOptions\n): void {\n if (options.resolveNote) {\n splitNoteMarkers(out, text, formatting, options);\n return;\n }\n pushNoProofWords(out, text, formatting, options);\n}\n\n/**\n * Replace resolvable `[^id]` markers with note reference nodes.\n *\n * A marker whose id the resolver does not know stays literal; the resolver owns\n * that decision, and the warning that goes with it, so this never has to guess\n * whether `[^a-z]` was meant as syntax.\n */\nfunction splitNoteMarkers(\n out: DocxIrInline[],\n text: string,\n formatting: DocxIrRunFormatting | undefined,\n options: ParseInlineOptions\n): void {\n const regex = new RegExp(NOTE_MARKER.source, 'g');\n let lastIndex = 0;\n let pending = '';\n let match: RegExpExecArray | null;\n\n while ((match = regex.exec(text)) !== null) {\n const note = options.resolveNote!(match[1]);\n if (note === undefined) {\n // Unresolved: the marker stays in the text stream verbatim.\n pending += text.slice(lastIndex, regex.lastIndex);\n lastIndex = regex.lastIndex;\n continue;\n }\n\n const before = pending + text.slice(lastIndex, match.index);\n pending = '';\n if (before) pushNoProofWords(out, before, formatting, options);\n out.push({\n kind: 'noteReference',\n noteKind: note.noteKind,\n id: note.id,\n });\n lastIndex = regex.lastIndex;\n }\n\n const rest = pending + text.slice(lastIndex);\n if (rest) pushNoProofWords(out, rest, formatting, options);\n}\n\nfunction pushNoProofWords(\n out: DocxIrInline[],\n text: string,\n formatting: DocxIrRunFormatting | undefined,\n options: ParseInlineOptions\n): void {\n const wholeRunNoProof = options.base.noProof === true;\n const regex = wholeRunNoProof\n ? null\n : buildNoProofWordsRegex(options.noProofWords);\n\n if (!regex) {\n out.push({ kind: 'text', text, formatting });\n return;\n }\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n out.push({\n kind: 'text',\n text: text.slice(lastIndex, match.index),\n formatting,\n });\n }\n out.push({\n kind: 'text',\n text: match[0],\n formatting: { ...formatting, noProof: true },\n });\n lastIndex = match.index + match[0].length;\n if (regex.lastIndex === match.index) regex.lastIndex += 1;\n }\n if (lastIndex < text.length) {\n out.push({ kind: 'text', text: text.slice(lastIndex), formatting });\n }\n}\n\n/**\n * Formatting for one run.\n *\n * `boldColor` applies only where a decorator actually made the run bold, which\n * is why the colour is chosen here and not on the base style.\n */\nfunction runFormatting(\n options: ParseInlineOptions,\n state: { bold?: boolean; italic?: boolean }\n): DocxIrRunFormatting | undefined {\n const formatting: DocxIrRunFormatting = { ...options.base };\n if (state.bold !== undefined) formatting.bold = state.bold;\n if (state.italic !== undefined) formatting.italic = state.italic;\n if (state.bold && options.boldColor && options.base.color) {\n formatting.color = options.boldColor;\n }\n return emptyToUndefined(formatting);\n}\n\nfunction emptyToUndefined(\n formatting: DocxIrRunFormatting\n): DocxIrRunFormatting | undefined {\n const entries = Object.entries(formatting).filter(\n ([, value]) => value !== undefined\n );\n return entries.length === 0\n ? undefined\n : (Object.fromEntries(entries) as DocxIrRunFormatting);\n}\n","/**\n * DOCX renderer registry.\n *\n * Adapters are registered as async factories so an optional backend is only\n * imported when it is actually selected — choosing `docxjs` never loads\n * `@office-open/docx`, and a missing optional dependency surfaces as an\n * actionable install hint rather than a bare module-resolution failure.\n */\n\nimport { RendererRegistry } from '@json-to-office/shared/rendering';\nimport type { DocxFeature } from '../ir/features';\nimport type { DocxIR } from '../ir/types';\nimport {\n DEFAULT_DOCX_RENDERER_ID,\n type DocxRenderer,\n type DocxRendererId,\n} from './types';\n\nconst registry = new RendererRegistry<DocxIR, DocxFeature, DocxRendererId>(\n 'docx',\n DEFAULT_DOCX_RENDERER_ID\n);\n\nregistry.register('docxjs', async () => {\n const { createDocxJsRenderer } = await import('./docxjs/index');\n return createDocxJsRenderer();\n});\n\nregistry.register('office-open', async () => {\n const { createOfficeOpenDocxRenderer } = await import('./office-open/index');\n return createOfficeOpenDocxRenderer();\n});\n\n/** Resolve a renderer by id, defaulting to `docxjs`. */\nexport function resolveDocxRenderer(\n id?: DocxRendererId\n): Promise<DocxRenderer> {\n return registry.resolve(id);\n}\n\n/** Renderer ids registered for DOCX. */\nexport function docxRendererIds(): readonly DocxRendererId[] {\n return registry.ids();\n}\n\nexport function isDocxRendererId(value: string): value is DocxRendererId {\n return registry.has(value);\n}\n","/**\n * DOCX renderer contracts.\n *\n * Format-specific bindings of the shared `OfficeRenderer` contract. Nothing in\n * this file imports a backend; the adapters under `docxjs/` and `office-open/`\n * do, and they are the only places allowed to.\n */\n\nimport type {\n OfficeRenderer,\n RenderOptions,\n} from '@json-to-office/shared/rendering';\nimport type { GenerationWarning } from '@json-to-office/shared';\nimport type { DocxFeature } from '../ir/features';\nimport type { DocxIR } from '../ir/types';\nimport {\n DEFAULT_DOCX_RENDERER_ID,\n type DocxRendererId,\n} from '@json-to-office/shared-docx';\n\n/**\n * Renderer ids available for DOCX.\n *\n * `docxjs` is the default and must keep producing today's output.\n * `office-open` is experimental and opt-in.\n */\nexport { DEFAULT_DOCX_RENDERER_ID };\nexport type { DocxRendererId };\n\n/**\n * Render options for DOCX.\n *\n * Adds a warning sink to the shared contract: post-render repairs can find\n * problems the author should hear about, and those belong in the same\n * structured list as the rest of the pipeline rather than on `console`.\n */\nexport interface DocxRenderOptions extends RenderOptions {\n warnings?: GenerationWarning[];\n}\n\nexport interface DocxRenderer\n extends OfficeRenderer<DocxIR, DocxFeature, DocxRendererId> {\n render(document: DocxIR, options?: DocxRenderOptions): Promise<Uint8Array>;\n}\n\nexport type { RenderOptions };\n","/**\n * Shared generation prologue.\n *\n * Both entry points — `generateBufferFromJson` (core) and\n * `createDocumentGenerator` (plugin) — must resolve the same theme, apply the\n * same in-document overrides, and apply the same export mode before the\n * structure → layout → render engine runs. Keeping two copies of that meant\n * `props.themeOverrides` reached only one of them (#133); this module is the\n * single definition so the next root-level prop cannot diverge (#132).\n *\n * The prologue deliberately stops before font resolution: the core path\n * resolves fonts straight after this, while the plugin path must first expand\n * custom components (which can introduce new families).\n */\n\nimport type { ReportComponentDefinition } from '../types';\nimport type { ThemeConfig } from '../styles';\nimport type {\n FontRuntimeOpts,\n GenerationWarning,\n} from '@json-to-office/shared';\nimport { applyExportMode } from '@json-to-office/shared';\nimport { resolveBuiltInTheme } from '../styles/theme-resolver';\nimport { applyThemeOverrides } from '../themes/overrides';\n\nexport interface ThemeContextOptions {\n customThemes?: { [key: string]: ThemeConfig };\n fonts?: FontRuntimeOpts;\n warnings?: GenerationWarning[];\n /**\n * Theme lookup for the base `props.theme` name. The plugin builder passes\n * its own (customThemes → doc-named built-in → constructor-supplied theme →\n * built-in); omit it to use customThemes → built-in. `authored` is true when\n * the name came from the document's own `props.theme` (not the 'minimal'\n * fallback), so the lookup can honor an explicitly doc-named built-in\n * without the constructor theme being shadowed for unnamed docs (#141).\n */\n resolveNamedTheme?: (\n name: string,\n warnings: GenerationWarning[] | undefined,\n authored: boolean\n ) => ThemeConfig;\n}\n\nexport interface GenerationThemeContext {\n /** The document after the export-mode pre-pass rewrote font references. */\n document: ReportComponentDefinition;\n theme: ThemeConfig;\n /** Base theme name, retained for built-in fallback lookups. */\n themeName: string;\n}\n\n/** customThemes lookup with the case-insensitive fallback, then built-ins. */\nfunction defaultNamedThemeLookup(\n themeName: string,\n customThemes: { [key: string]: ThemeConfig } | undefined,\n warnings?: GenerationWarning[]\n): ThemeConfig {\n if (customThemes) {\n if (customThemes[themeName]) return customThemes[themeName];\n const themeNameLower = themeName.toLowerCase();\n const matchingThemeKey = Object.keys(customThemes).find(\n (key) => key.toLowerCase() === themeNameLower\n );\n if (matchingThemeKey) return customThemes[matchingThemeKey];\n return resolveBuiltInTheme(themeName, { customThemes, warnings });\n }\n return resolveBuiltInTheme(themeName, { warnings });\n}\n\nexport function resolveThemeContext(\n documentIn: ReportComponentDefinition,\n options: ThemeContextOptions = {}\n): GenerationThemeContext {\n const { customThemes, fonts, warnings, resolveNamedTheme } = options;\n\n // A root written without a `props` key validates clean, so default it here —\n // otherwise every downstream `document.props.*` read (theme, componentDefaults,\n // noProofWords, trackRevisions, language, metadata) throws. Only `undefined`\n // is defaulted: `props: null` is malformed and must be rejected rather than\n // quietly rewritten into a valid shape.\n //\n // Both JSON entry points validate before reaching here, so null is already\n // a validation error there. `generateDocument` on a document without\n // `$schema` runs no validator at all, and used to surface this as\n // `Cannot read properties of null` from the theme read below.\n if (documentIn.props === null) {\n throw new Error(\n 'Document `props` is null. Omit it, or provide an object — ' +\n 'a null props cannot carry a theme.'\n );\n }\n const document =\n documentIn.props === undefined ? { ...documentIn, props: {} } : documentIn;\n\n const authoredThemeName = document.props.theme || undefined;\n const baseThemeName = authoredThemeName ?? 'minimal';\n let theme = resolveNamedTheme\n ? resolveNamedTheme(\n baseThemeName,\n warnings,\n authoredThemeName !== undefined\n )\n : defaultNamedThemeLookup(baseThemeName, customThemes, warnings);\n\n // In-document partial theme, merged before the export-mode pre-pass so a\n // font-family override is visible to it.\n const themeOverrides = document.props.themeOverrides;\n if (themeOverrides) {\n theme = applyThemeOverrides(theme, themeOverrides);\n }\n\n // Export-mode pre-pass: substitute (default) rewrites non-safe families to\n // safe equivalents; custom keeps refs as-is.\n const mode = applyExportMode({ doc: document, theme, fonts });\n for (const w of mode.warnings) {\n if (warnings) {\n warnings.push({\n component: 'fontRegistry',\n message: w.message,\n severity: 'warning',\n context: { code: w.code },\n });\n } else {\n // eslint-disable-next-line no-console\n console.warn(`[json-to-docx] [${w.code}] ${w.message}`);\n }\n }\n\n return {\n document: mode.doc,\n theme: mode.theme,\n themeName: baseThemeName,\n };\n}\n","import type { GenerationWarning } from '@json-to-office/shared';\nimport type { ThemeConfig } from './index';\nimport {\n getThemeNames,\n getThemeWithFallback,\n hasTheme,\n} from '../templates/themes';\n\n/**\n * Resolve a built-in theme by name, reporting a miss instead of swallowing it.\n *\n * `getThemeWithFallback` renders an unknown name as `minimal`, which used to be\n * invisible: a typo, or a `--theme-path` file whose internal `name` differs\n * from its filename, produced a plausible-looking document styled by the wrong\n * theme. The fallback is kept — a bad name should not fail a render — but it\n * now surfaces as a warning naming what was asked for and what is available.\n */\nexport function resolveBuiltInTheme(\n themeName: string,\n options: {\n customThemes?: { [key: string]: ThemeConfig };\n warnings?: GenerationWarning[];\n } = {}\n): ThemeConfig {\n if (!hasTheme(themeName)) {\n const available = [\n ...getThemeNames(),\n ...Object.keys(options.customThemes ?? {}),\n ].sort();\n options.warnings?.push({\n component: 'theme',\n message: `Theme \"${themeName}\" not found; falling back to \"minimal\". Available themes: ${available.join(', ')}.`,\n severity: 'warning',\n context: { code: 'theme_not_found', requested: themeName, available },\n });\n }\n\n return getThemeWithFallback(themeName);\n}\n","/**\n * In-document theme overrides: a partial theme from the document root's\n * `themeOverrides` prop, deep-merged over the resolved named theme.\n */\n\nimport type { ThemeConfig } from '../styles';\n\nexport interface ThemeOverrides {\n colors?: Partial<ThemeConfig['colors']>;\n fonts?: Partial<ThemeConfig['fonts']>;\n styles?: ThemeConfig['styles'];\n}\n\n/**\n * Merge a partial override object over a resolved theme.\n *\n * - `colors`: per-token replacement.\n * - `fonts`: per-role merge (an override role only replaces the fields it\n * sets, so `{ heading: { family: \"Geist\" } }` keeps the theme's size).\n * - `styles`: per-style merge, one level deep — nested objects inside a style\n * (spacing, lineSpacing, borders, indent) are replaced wholesale.\n */\nexport function applyThemeOverrides(\n theme: ThemeConfig,\n overrides: ThemeOverrides | undefined\n): ThemeConfig {\n if (!overrides) return theme;\n\n const fonts = { ...theme.fonts };\n for (const [role, def] of Object.entries(overrides.fonts ?? {})) {\n const key = role as keyof ThemeConfig['fonts'];\n fonts[key] = { ...theme.fonts[key], ...def };\n }\n\n const styles: Record<string, object> = { ...(theme.styles ?? {}) };\n for (const [name, def] of Object.entries(overrides.styles ?? {})) {\n styles[name] = { ...styles[name], ...(def as object) };\n }\n\n return {\n ...theme,\n colors: { ...theme.colors, ...(overrides.colors ?? {}) },\n fonts,\n ...(Object.keys(styles).length > 0 && { styles }),\n };\n}\n","/**\n * Layout Functions\n * Handle all layout concerns including columns, breaks, and section properties\n */\n\nimport {\n ComponentDefinition,\n ColumnSettings,\n isColumnsComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isTocComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { getPageSetup, getPageDimensions } from '../styles';\n// import { pointsToTwips } from '../styles/utils/styleHelpers';\nimport { ProcessedSection } from './structure';\nimport {\n getAvailableWidthTwips,\n relativeLengthToTwips,\n} from '../utils/widthUtils';\n\nexport interface LayoutPlan {\n sections: SectionLayout[];\n}\n\nexport interface WordSectionProperties {\n page: {\n size: {\n width: number;\n height: number;\n /**\n * OOXML `w:pgSz/@w:code` — the DEVMODE paper code printer drivers key\n * off. Set only for a named size; a custom `{width, height}` has none.\n */\n code?: number;\n };\n margin: {\n top: number;\n right: number;\n bottom: number;\n left: number;\n // Present only when a section overrides them; the theme's page setup\n // states the four edges and leaves these to Word's own defaults.\n header?: number;\n footer?: number;\n gutter?: number;\n };\n };\n column: ColumnSettings & {\n /**\n * The same explicit columns as `children`, in twips.\n *\n * `children` holds docx `Column` instances, which keep their width and\n * space private, so anything downstream of a renderer boundary cannot read\n * them back. This is the plain-numbers copy the DocxIR compiler reads.\n */\n widths?: Array<{ width: number; space?: number }>;\n };\n type?: 'continuous' | 'nextColumn' | 'nextPage' | 'evenPage' | 'oddPage';\n}\n\nexport interface SectionLayout {\n properties: WordSectionProperties;\n components: ComponentDefinition[];\n layoutType: 'single' | 'multi-column';\n breakBefore: boolean;\n header?: ComponentDefinition[] | 'linkToPrevious';\n footer?: ComponentDefinition[] | 'linkToPrevious';\n /** True if this layout section comes from a user-defined Section component */\n isUserSection: boolean;\n /** True if this layout chunk belongs to a user-defined Section (all chunks of that section) */\n belongsToUserSection: boolean;\n /** Page configuration override for this section */\n pageOverride?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n };\n}\n\nexport interface LayoutGroup {\n layout: 'single' | 'multi-column';\n components: ComponentDefinition[];\n breakBefore: boolean;\n}\n\n/**\n * Apply layout to processed sections\n */\nexport function applyLayout(\n sections: ProcessedSection[],\n theme: ThemeConfig,\n themeName: string\n): LayoutPlan {\n const layoutSections: SectionLayout[] = [];\n\n for (let i = 0; i < sections.length; i++) {\n const section = sections[i];\n const layoutGroups = analyzeLayoutGroups(section.components);\n\n // Determine if this comes from an explicit Section component\n const isSourceUserSection = Boolean(section.isExplicitSection);\n\n // Handle sections with no components but with headers/footers\n // This ensures headers/footers are rendered even for empty sections\n if (layoutGroups.length === 0 && (section.header || section.footer)) {\n const isFirstSection = i === 0;\n const breakBefore = isFirstSection || Boolean(section.pageBreak);\n const sectionType = breakBefore ? 'nextPage' : 'continuous';\n\n layoutSections.push({\n properties: createSectionProperties(\n getColumnSettings('single'),\n theme,\n themeName,\n sectionType,\n section.page\n ),\n components: [],\n layoutType: 'single',\n breakBefore,\n header: section.header,\n footer: section.footer,\n isUserSection: isSourceUserSection,\n belongsToUserSection: isSourceUserSection,\n pageOverride: section.page,\n });\n continue;\n }\n\n for (let j = 0; j < layoutGroups.length; j++) {\n const group = layoutGroups[j];\n\n // Special handling: a single Columns component becomes its own section with explicit column children\n const isSingleColumnsGroup =\n group.components.length === 1 &&\n isColumnsComponent(group.components[0]);\n\n const columnSettings = isSingleColumnsGroup\n ? createColumnSettingsFromConfig(group.components[0], theme, themeName)\n : getColumnSettings(group.layout);\n\n // Only break page if explicitly requested or this is the first section\n const isFirstSection = i === 0 && j === 0;\n // For titleless sections with pageBreak, apply break to first layout group\n const titlelessSectionBreak = Boolean(section.pageBreak && j === 0);\n const breakBefore =\n group.breakBefore || isFirstSection || titlelessSectionBreak;\n const sectionType = breakBefore ? 'nextPage' : 'continuous';\n\n // Build content components depending on whether this is an explicit columns group\n const contentComponents = isSingleColumnsGroup\n ? processLayoutComponents(\n (\n group.components[0] as unknown as {\n children?: ComponentDefinition[];\n }\n ).children || []\n )\n : processLayoutComponents(group.components);\n\n layoutSections.push({\n properties: createSectionProperties(\n columnSettings,\n theme,\n themeName,\n sectionType,\n section.page\n ),\n components: contentComponents,\n layoutType: group.layout,\n breakBefore,\n header: section.header,\n footer: section.footer,\n // Only mark the FIRST layout section as user-defined to avoid\n // creating bookmark paragraphs in subsequent sections (e.g., when\n // transitioning to columns layout). This prevents unwanted newlines\n // at the start of column content.\n isUserSection: isSourceUserSection && j === 0,\n belongsToUserSection: isSourceUserSection,\n // Pass page override for this section\n pageOverride: section.page,\n });\n }\n }\n\n return { sections: layoutSections };\n}\n\n/**\n * Analyze components to determine layout groups\n */\nexport function analyzeLayoutGroups(\n components: ComponentDefinition[]\n): LayoutGroup[] {\n const groups: LayoutGroup[] = [];\n let currentLayout: 'single' | 'multi-column' = 'single';\n let currentComponents: ComponentDefinition[] = [];\n let breakNext = false;\n\n for (const component of components) {\n // Always isolate explicit Columns components into their own group\n if (isColumnsComponent(component)) {\n if (currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentComponents = [];\n breakNext = false;\n }\n // Determine the actual layout based on the columns component configuration\n const columnsLayout = determineComponentLayout(component);\n groups.push({\n layout: columnsLayout,\n components: [component],\n breakBefore: breakNext,\n });\n breakNext = false;\n continue;\n }\n\n const componentLayout = determineComponentLayout(component);\n\n // Check for explicit break indicators\n if (hasPageBreak(component)) {\n if (currentComponents.length > 0) {\n // Finish previous group without break\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentComponents = [];\n breakNext = false;\n }\n // Start new group with break for this component\n currentComponents = [component];\n breakNext = true;\n continue;\n }\n\n // Layout change requires new group\n if (componentLayout !== currentLayout && currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n currentLayout = componentLayout;\n currentComponents = [component];\n breakNext = false;\n } else {\n currentComponents.push(component);\n }\n }\n\n // Add remaining components\n if (currentComponents.length > 0) {\n groups.push({\n layout: currentLayout,\n components: currentComponents,\n breakBefore: breakNext,\n });\n }\n\n return groups;\n}\n\n/**\n * Determine layout type for a component\n */\nexport function determineComponentLayout(\n component: ComponentDefinition\n): 'single' | 'multi-column' {\n if (isColumnsComponent(component)) {\n const columns = (component as any).props?.columns;\n\n // If columns is an array with specific configurations\n if (Array.isArray(columns)) {\n // Any columns array with 2+ items is multi-column\n return columns.length >= 2 ? 'multi-column' : 'single';\n }\n\n // No valid array provided; treat as single-column\n return 'single';\n }\n\n // Check if component contains children\n if ('children' in component && (component as any).children) {\n const hasColumns = (component as any).children.some(\n (child: ComponentDefinition) => isColumnsComponent(child)\n );\n return hasColumns ? 'multi-column' : 'single';\n }\n\n return 'single';\n}\n\n/**\n * Process components for layout (insert breaks where needed)\n */\nexport function processLayoutComponents(\n components: ComponentDefinition[]\n): ComponentDefinition[] {\n const processed: ComponentDefinition[] = [];\n\n for (let i = 0; i < components.length; i++) {\n const component = components[i];\n\n // Check if this component should have a column break\n if (shouldInsertColumnBreak()) {\n // Create a new component with columnBreak flag\n if (isHeadingComponent(component)) {\n processed.push({\n ...component,\n props: {\n ...((component as any).props || {}),\n columnBreak: true,\n },\n } as ComponentDefinition);\n } else {\n processed.push(component);\n }\n } else {\n processed.push(component);\n }\n }\n\n return processed;\n}\n\n/**\n * Determine if a column break should be inserted\n */\nfunction shouldInsertColumnBreak(): boolean {\n // Logic to determine column breaks based on content distribution\n // This is simplified - could be enhanced with more sophisticated logic\n return false;\n}\n\n/**\n * Check if component indicates a page break\n */\nfunction hasPageBreak(component: ComponentDefinition): boolean {\n if (isSectionComponent(component)) {\n // Default to true for section components when pageBreak is undefined\n return component.props?.pageBreak !== false;\n }\n if (isHeadingComponent(component)) {\n return component.props.pageBreak === true;\n }\n if (isParagraphComponent(component)) {\n return component.props.pageBreak === true;\n }\n // Allow TOC components to request a page break as well\n if (isTocComponent(component)) {\n return component.props?.pageBreak === true;\n }\n return false;\n}\n\n/**\n * Get column settings for layout type\n */\nexport function getColumnSettings(\n layout: 'single' | 'multi-column'\n): ColumnSettings {\n switch (layout) {\n case 'multi-column':\n // Default multi-column layout: 2 equal-width columns\n // Note: Specific column components will override this with their own settings via createColumnSettingsFromConfig\n return {\n count: 2,\n equalWidth: true,\n space: 720, // 0.5 inch in twips\n };\n case 'single':\n default:\n return { count: 1 };\n }\n}\n\n/**\n * Create Word section properties\n */\nexport function createSectionProperties(\n columnSettings: ColumnSettings,\n theme: ThemeConfig,\n themeName: string,\n sectionType?: 'continuous' | 'nextPage',\n pageOverride?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n }\n): WordSectionProperties {\n // Get base page setup from theme\n const basePageSetup = getPageSetup(theme, themeName);\n\n // Apply section-level page overrides if present.\n //\n // The size override replaces the base size wholesale rather than merging\n // into it: a custom `{width, height}` is not a standard paper, so it must not\n // inherit the theme's paper code — which a spread over `basePageSetup.size`\n // would silently do, telling the driver to fetch A4 for a custom page.\n const pageSetup = pageOverride\n ? {\n size: pageOverride.size\n ? getPageDimensions(pageOverride.size)\n : basePageSetup.size,\n margin: {\n ...basePageSetup.margin,\n ...(pageOverride.margins || {}),\n },\n }\n : basePageSetup;\n\n const properties: WordSectionProperties = {\n page: pageSetup,\n column: {\n count: columnSettings.count,\n equalWidth: columnSettings.equalWidth,\n space: columnSettings.space,\n },\n };\n\n if (\n (columnSettings as any).children &&\n Array.isArray((columnSettings as any).children)\n ) {\n const children = (columnSettings as any).children as {\n width?: number;\n space?: number;\n }[];\n // When we have explicit column children, ensure equalWidth is explicitly false\n // so Word doesn't override widths with equal distribution.\n properties.column.equalWidth = false;\n // Also remove top-level space to avoid conflicting with per-column spaces\n delete properties.column.space;\n\n properties.column.widths = children.map((c) => ({\n width: c.width as number,\n ...(c.space !== undefined ? { space: c.space } : {}),\n }));\n }\n\n if (sectionType) {\n properties.type = sectionType === 'continuous' ? 'continuous' : 'nextPage';\n }\n\n return properties;\n}\n\n/**\n * Create explicit column settings from a Columns component props\n * - width/gap accept number (points) or percentage string relative to available width\n */\nfunction createColumnSettingsFromConfig(\n component: ComponentDefinition,\n theme: ThemeConfig,\n themeName: string\n): ColumnSettings {\n const cfg = ((component as any).props || {}) as {\n columns?: Array<{ width?: number | string; gap?: number | string }>;\n };\n\n // Fallback to single column if no valid array is provided\n const columns = (cfg.columns || []) as Array<{\n width?: number | string;\n gap?: number | string;\n }>;\n\n if (!Array.isArray(columns) || columns.length === 0) {\n return { count: 1 };\n }\n\n const availableWidthTwips = getAvailableWidthTwips(theme, themeName);\n\n // First pass: compute defined widths/spaces; collect indexes without width\n const childSettings: { width?: number; space?: number }[] = [];\n let totalDefinedWidth = 0;\n let totalSpace = 0;\n const unspecifiedWidthIndexes: number[] = [];\n\n for (let i = 0; i < columns.length; i++) {\n const c = columns[i];\n const child: { width?: number; space?: number } = {};\n\n if (c.width !== undefined) {\n const widthTwips = relativeLengthToTwips(c.width, availableWidthTwips);\n if (widthTwips > 0) {\n child.width = widthTwips;\n totalDefinedWidth += widthTwips;\n }\n } else {\n unspecifiedWidthIndexes.push(i);\n }\n\n if (c.gap !== undefined) {\n const spaceTwips = relativeLengthToTwips(c.gap, availableWidthTwips);\n if (spaceTwips > 0) {\n child.space = spaceTwips;\n totalSpace += spaceTwips;\n }\n }\n\n childSettings.push(child);\n }\n\n // Validate that defined widths + gaps do not exceed available width (with tolerance)\n const totalUsedTwips = totalDefinedWidth + totalSpace;\n const tolerance = 0.005; // 0.5%\n const allowed = availableWidthTwips * (1 + tolerance);\n if (totalUsedTwips > allowed) {\n const usedPercent = (totalUsedTwips / availableWidthTwips) * 100;\n // Build diagnostics per column\n const details = childSettings\n .map((c, idx) => {\n const wPct = c.width\n ? ((c.width / availableWidthTwips) * 100).toFixed(1) + '%'\n : 'auto/unspecified';\n const gPct = c.space\n ? ((c.space / availableWidthTwips) * 100).toFixed(1) + '%'\n : '0%';\n return ` - Column ${idx + 1}: width=${wPct}, gap=${gPct}`;\n })\n .join('\\n');\n const suggestion =\n 'Reduce one or more widths/gaps so total <= 100%, remove the last gap, or set some widths to \"auto\" to consume remaining space.';\n throw new Error(\n `Columns configuration exceeds available width: widths + gaps = ${usedPercent.toFixed(1)}% (> 100% + ${(\n tolerance * 100\n ).toFixed(\n 1\n )}% tolerance)\\nDetails:\\n${details}\\nSuggestion: ${suggestion}`\n );\n }\n\n // Distribute remaining width equally among unspecified widths\n const remaining = Math.max(\n 0,\n availableWidthTwips - totalSpace - totalDefinedWidth\n );\n if (unspecifiedWidthIndexes.length > 0) {\n const each = Math.floor(remaining / unspecifiedWidthIndexes.length);\n for (const idx of unspecifiedWidthIndexes) {\n childSettings[idx].width = each;\n }\n }\n\n return {\n count: columns.length,\n equalWidth: false,\n children: childSettings,\n };\n}\n\n/**\n * Calculate optimal column distribution for content\n */\nexport function calculateColumnDistribution(\n components: ComponentDefinition[],\n columnCount: number\n): ComponentDefinition[][] {\n if (columnCount === 1) {\n return [components];\n }\n\n // Simple distribution - could be enhanced with content-aware logic\n const columns: ComponentDefinition[][] = Array(columnCount)\n .fill(null)\n .map(() => []);\n let currentColumn = 0;\n\n for (const component of components) {\n columns[currentColumn].push(component);\n currentColumn = (currentColumn + 1) % columnCount;\n }\n\n return columns;\n}\n","import { format } from 'date-fns';\n\nexport const formatDate = (\n date: Date,\n formatString: string = 'MMMM d, yyyy'\n): string => {\n return format(date, formatString);\n};\n","/**\n * Component Default Resolution System\n * Provides theme-based default configurations for components\n */\n\nimport {\n ThemeConfig,\n ComponentDefaults,\n HeadingComponentDefaults,\n ParagraphComponentDefaults,\n ImageComponentDefaults,\n StatisticComponentDefaults,\n TableComponentDefaults,\n SectionComponentDefaults,\n ColumnsComponentDefaults,\n ListComponentDefaults,\n} from '../index';\nimport {\n HeadingProps,\n ParagraphProps,\n ImageProps,\n StatisticProps,\n TableProps,\n SectionProps,\n ColumnsProps,\n ListProps,\n} from '../../types';\nimport { mergeWithDefaults } from '@json-to-office/shared';\n\n/**\n * Get component defaults from theme configuration\n */\nexport function getComponentDefaults(theme: ThemeConfig): ComponentDefaults {\n return theme.componentDefaults || {};\n}\n\n/**\n * Get default configuration for heading components\n */\nexport function getHeadingDefaults(\n theme: ThemeConfig\n): HeadingComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.heading || {};\n}\n\n/**\n * Get level-specific heading defaults from theme styles\n */\nexport function getHeadingDefaultsForLevel(\n theme: ThemeConfig,\n level: number\n): Partial<HeadingComponentDefaults> {\n const defaults: Partial<HeadingComponentDefaults> = {};\n\n // Check styles for level-specific alignment\n if (theme.styles) {\n const styleKey = `heading${level}` as\n | 'heading1'\n | 'heading2'\n | 'heading3'\n | 'heading4'\n | 'heading5'\n | 'heading6';\n const headingStyle = theme.styles[styleKey];\n\n if (headingStyle?.alignment) {\n defaults.alignment = headingStyle.alignment;\n }\n }\n\n return defaults;\n}\n\n/**\n * Get default configuration for text components\n */\nexport function getTextDefaults(\n theme: ThemeConfig\n): ParagraphComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.paragraph || {};\n}\n\n/**\n * Get default configuration for image components\n */\nexport function getImageDefaults(theme: ThemeConfig): ImageComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.image || {};\n}\n\n/**\n * Get default configuration for statistic components\n */\nexport function getStatisticDefaults(\n theme: ThemeConfig\n): StatisticComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.statistic || {};\n}\n\n/**\n * Get default configuration for table components\n */\nexport function getTableDefaults(theme: ThemeConfig): TableComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.table || {};\n}\n\n/**\n * Get default configuration for section components\n */\nexport function getSectionDefaults(\n theme: ThemeConfig\n): SectionComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.section || {};\n}\n\n/**\n * Get default configuration for columns components\n */\nexport function getColumnsDefaults(\n theme: ThemeConfig\n): ColumnsComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.columns || {};\n}\n\n/**\n * Get default configuration for list components\n */\nexport function getListDefaults(theme: ThemeConfig): ListComponentDefaults {\n const defaults = getComponentDefaults(theme);\n return defaults?.list || {};\n}\n\n// mergeWithDefaults is re-exported from @json-to-office/shared\nexport { mergeWithDefaults } from '@json-to-office/shared';\n\n/**\n * Resolve heading component props with theme defaults\n */\nexport function resolveHeadingProps(\n props: HeadingProps,\n theme: ThemeConfig\n): HeadingProps {\n const defaults = getHeadingDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve paragraph component props with theme defaults\n */\nexport function resolveParagraphProps(\n props: ParagraphProps,\n theme: ThemeConfig\n): ParagraphProps {\n const defaults = getTextDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve image component props with theme defaults\n */\nexport function resolveImageProps(\n props: ImageProps,\n theme: ThemeConfig\n): ImageProps {\n const defaults = getImageDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve statistic component props with theme defaults\n */\nexport function resolveStatisticProps(\n props: StatisticProps,\n theme: ThemeConfig\n): StatisticProps {\n const defaults = getStatisticDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve table component props with theme defaults\n */\nexport function resolveTableProps(\n props: TableProps,\n theme: ThemeConfig\n): TableProps {\n const defaults = getTableDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve section component props with theme defaults\n */\nexport function resolveSectionProps(\n props: SectionProps,\n theme: ThemeConfig\n): SectionProps {\n const defaults = getSectionDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve columns component props with theme defaults\n */\nexport function resolveColumnsProps(\n props: ColumnsProps,\n theme: ThemeConfig\n): ColumnsProps {\n const defaults = getColumnsDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve list component props with theme defaults\n */\nexport function resolveListProps(\n props: ListProps,\n theme: ThemeConfig\n): ListProps {\n const defaults = getListDefaults(theme);\n return mergeWithDefaults(props, defaults);\n}\n\n/**\n * Resolve highcharts component props with theme defaults\n */\nexport function resolveHighchartsProps(\n props: import('@json-to-office/shared-docx').HighchartsProps,\n _theme: ThemeConfig\n): import('@json-to-office/shared-docx').HighchartsProps {\n // Highcharts component doesn't have theme defaults, just return the props as-is\n return props;\n}\n\n/**\n * Resolve visual component props with theme defaults.\n * The visual is rasterized by the pptx engine, so there are no docx-side theme\n * defaults to apply — return props as-is (mirrors highcharts).\n */\nexport function resolveVisualProps(\n props: import('@json-to-office/shared-docx').VisualProps,\n _theme: ThemeConfig\n): import('@json-to-office/shared-docx').VisualProps {\n return props;\n}\n\n/**\n * Get default configuration for custom components\n */\nexport function getCustomComponentDefaults(\n theme: ThemeConfig,\n componentName: string\n): Record<string, unknown> {\n const defaults = getComponentDefaults(theme);\n // Use type assertion since we're dealing with dynamic property access\n return ((defaults as any)?.[componentName] as Record<string, unknown>) || {};\n}\n\n/**\n * Resolve custom component props with theme defaults\n */\nexport function resolveCustomComponentProps<T extends Record<string, unknown>>(\n props: T,\n theme: ThemeConfig,\n componentName: string\n): T {\n const defaults = getCustomComponentDefaults(theme, componentName);\n return mergeWithDefaults(props, defaults as Partial<T>);\n}\n","/**\n * Centralized Component Defaults Resolution\n * Walks the component tree and resolves theme componentDefaults\n * on every component before any rendering or structure processing.\n */\n\nimport { ComponentDefinition, HeadingProps } from '../../types';\nimport { ThemeConfig } from '../index';\nimport {\n resolveHeadingProps,\n resolveParagraphProps,\n resolveImageProps,\n resolveStatisticProps,\n resolveTableProps,\n resolveSectionProps,\n resolveColumnsProps,\n resolveListProps,\n resolveHighchartsProps,\n resolveVisualProps,\n resolveCustomComponentProps,\n getHeadingDefaultsForLevel,\n} from './componentDefaults';\n\n/**\n * Heading resolver that also applies level-specific style defaults\n * (alignment from theme.styles.heading{N}).\n * Moved here from heading.ts to centralize all resolution.\n */\nfunction resolveHeadingWithLevelDefaults(\n props: HeadingProps,\n theme: ThemeConfig\n): HeadingProps {\n const resolved = resolveHeadingProps(props, theme);\n const level = resolved.level || 1;\n const levelDefaults = getHeadingDefaultsForLevel(theme, level);\n return {\n ...resolved,\n // Only apply level-specific defaults if no explicit alignment in original props\n ...(props.alignment ? {} : levelDefaults),\n };\n}\n\ntype Resolver = (props: any, theme: ThemeConfig) => any;\n\nconst RESOLVER_MAP: Record<string, Resolver> = {\n heading: resolveHeadingWithLevelDefaults,\n paragraph: resolveParagraphProps,\n image: resolveImageProps,\n statistic: resolveStatisticProps,\n table: resolveTableProps,\n section: resolveSectionProps,\n columns: resolveColumnsProps,\n list: resolveListProps,\n highcharts: resolveHighchartsProps,\n visual: resolveVisualProps,\n};\n\n/**\n * Resolve componentDefaults for a single component.\n * Known components use their typed resolver; unknown names\n * fall back to resolveCustomComponentProps.\n *\n * A missing `props` key is treated as `{}` — a propless node must still pick up\n * the theme's defaults (e.g. `componentDefaults.section.pageBreak: false`).\n */\nexport function resolveComponentDefaults(\n component: ComponentDefinition,\n theme: ThemeConfig\n): ComponentDefinition {\n const props = component.props ?? {};\n\n const resolver = RESOLVER_MAP[component.name];\n const resolvedProps = resolver\n ? resolver(props, theme)\n : resolveCustomComponentProps(\n props as Record<string, unknown>,\n theme,\n component.name\n );\n\n return { ...component, props: resolvedProps };\n}\n\n/**\n * Recursively walk the component tree and resolve componentDefaults\n * on every component. Returns a new tree (no mutation).\n */\nexport function resolveComponentTree(\n components: ComponentDefinition[],\n theme: ThemeConfig\n): ComponentDefinition[] {\n return components.map((component) => {\n const resolved = resolveComponentDefaults(component, theme);\n\n const children = (resolved as any).children as\n | ComponentDefinition[]\n | undefined;\n if (children && children.length > 0) {\n return {\n ...resolved,\n children: resolveComponentTree(children, theme),\n };\n }\n\n return resolved;\n });\n}\n","/**\n * Document Structure Functions\n * Handle document hierarchy and organization without layout concerns\n */\n\nimport {\n ComponentDefinition,\n ReportProps,\n ReportComponentDefinition,\n RenderContext,\n isSectionComponent,\n isColumnsComponent,\n} from '../types';\nimport { ThemeConfig } from '../styles';\nimport { formatDate } from '../utils/formatters';\nimport { resolveComponentTree } from '../styles/utils/resolveComponentTree';\nimport { mergeWithDefaults } from '../styles/utils/componentDefaults';\n\nexport interface ProcessedDocument {\n metadata: DocumentMetadata;\n sections: ProcessedSection[];\n theme: ThemeConfig;\n themeName: string;\n /** Open the generated document in track-changes mode */\n trackRevisions?: boolean;\n /** Default document language (BCP-47) applied to docDefaults proofing */\n language?: string;\n}\n\nexport interface DocumentMetadata {\n title?: string;\n subtitle?: string;\n description?: string;\n author?: string;\n company?: string;\n version?: string;\n tags?: string[];\n date: Date;\n}\n\nexport interface ProcessedSection {\n components: ComponentDefinition[];\n header?: ComponentDefinition[] | 'linkToPrevious';\n footer?: ComponentDefinition[] | 'linkToPrevious';\n /** True if this section originates from an explicit Section component */\n isExplicitSection?: boolean;\n /** Whether this section should start on a new page */\n pageBreak?: boolean;\n /** Page configuration override for this section */\n page?: {\n size?: 'A4' | 'A3' | 'LETTER' | 'LEGAL' | { width: number; height: number };\n margins?: {\n top?: number;\n bottom?: number;\n left?: number;\n right?: number;\n header?: number;\n footer?: number;\n gutter?: number;\n };\n };\n}\n\n/**\n * Process document definition into structured format\n */\nexport async function processDocument(\n document: ReportComponentDefinition,\n theme: ThemeConfig,\n themeName: string,\n generationDate?: Date\n): Promise<ProcessedDocument> {\n const metadata = createDocumentMetadata(document.props, generationDate);\n\n // Merge document-level componentDefaults on top of theme-level ones\n // (document overrides theme)\n const docDefaults = document.props.componentDefaults;\n const mergedComponentDefaults = docDefaults\n ? mergeWithDefaults(docDefaults, theme.componentDefaults || {})\n : undefined;\n\n // Fold the document's known-words allowlist into the theme object so it\n // reaches every text primitive (createText/createHeading) without threading\n // a new parameter through the whole render tree. Document words are added to\n // any house-style words the theme already defines.\n const docNoProofWords = document.props.noProofWords;\n const mergedNoProofWords =\n docNoProofWords || theme.noProofWords\n ? Array.from(\n new Set([...(theme.noProofWords || []), ...(docNoProofWords || [])])\n )\n : undefined;\n\n const effectiveTheme =\n mergedComponentDefaults || mergedNoProofWords\n ? {\n ...theme,\n ...(mergedComponentDefaults && {\n componentDefaults: mergedComponentDefaults,\n }),\n ...(mergedNoProofWords && { noProofWords: mergedNoProofWords }),\n }\n : theme;\n\n // Create context with effective theme so section-title headings\n // created in extractSections also see document-level defaults\n const context = createRenderContext(\n {\n metadata,\n sections: [],\n theme: effectiveTheme,\n themeName,\n },\n effectiveTheme,\n themeName\n );\n\n // Resolve componentDefaults on every component before\n // extractSections reads any props (fixes section pageBreak, table defaults, etc.)\n const resolvedChildren = resolveComponentTree(\n document.children || [],\n effectiveTheme\n );\n\n // Extract sections from components\n const sections = await extractSections(resolvedChildren, context);\n\n return {\n metadata,\n sections,\n theme: effectiveTheme,\n themeName,\n trackRevisions: document.props.trackRevisions,\n language: document.props.language,\n };\n}\n\n/**\n * Extract document metadata from report props\n */\nexport function createDocumentMetadata(\n props: ReportProps,\n generationDate = new Date()\n): DocumentMetadata {\n return {\n title: props.metadata?.title,\n subtitle: props.metadata?.subtitle,\n description: props.metadata?.description,\n author: props.metadata?.author,\n company: props.metadata?.company,\n version: props.metadata?.version,\n tags: props.metadata?.tags,\n date: props.metadata?.date ? new Date(props.metadata.date) : generationDate,\n };\n}\n\n/**\n * Extract and flatten sections from component hierarchy\n */\nexport async function extractSections(\n components: ComponentDefinition[],\n context: RenderContext\n): Promise<ProcessedSection[]> {\n const sections: ProcessedSection[] = [];\n\n // Filter out components with enabled: false (defaults to true when not specified)\n const activeComponents = components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n\n for (const component of activeComponents) {\n if (isSectionComponent(component)) {\n const sectionComponents = await flattenComponents(\n component.children || [],\n context\n );\n\n // Determine if page break should be applied (default to true)\n const shouldPageBreak = component.props?.pageBreak !== false;\n\n sections.push({\n components: sectionComponents,\n header: component.props?.header,\n footer: component.props?.footer,\n isExplicitSection: true,\n // Page break is handled at layout level (sections render no title of\n // their own — a visible title is an explicit heading child; the\n // authoring label lives in props.meta.title and is never rendered)\n pageBreak: shouldPageBreak,\n // Preserve page configuration override if present\n page: component.props?.page,\n });\n } else {\n // Non-section components at root level become their own section\n sections.push({\n components: [component],\n isExplicitSection: false,\n });\n }\n }\n\n return sections;\n}\n\n/**\n * Flatten nested container components while preserving content components\n */\nexport async function flattenComponents(\n components: ComponentDefinition[],\n context: RenderContext\n): Promise<ComponentDefinition[]> {\n const flattened: ComponentDefinition[] = [];\n\n // Filter out components with enabled: false (defaults to true when not specified)\n const activeComponents = components.filter(\n (m) => !('enabled' in m && m.enabled === false)\n );\n\n for (const component of activeComponents) {\n if (isColumnsComponent(component) && component.children) {\n // Preserve columns structure but flatten its contents\n flattened.push({\n ...component,\n children: await flattenComponents(component.children, context),\n });\n } else if (isSectionComponent(component) && component.children) {\n // Flatten nested sections (their meta is authoring-only, nothing renders)\n flattened.push(...(await flattenComponents(component.children, context)));\n } else {\n // Keep content components as-is\n flattened.push(component);\n }\n }\n\n return flattened;\n}\n\n/**\n * Create render context from processed document\n */\nexport function createRenderContext(\n document: ProcessedDocument,\n theme: ThemeConfig,\n themeName: string\n): RenderContext {\n return {\n theme: {\n name: themeName,\n colors: theme.colors || {},\n fonts: theme.fonts\n ? Object.fromEntries(\n Object.entries(theme.fonts).map(([key, font]) => [key, font.family])\n )\n : {},\n spacing: { small: 120, medium: 240, large: 360, section: 480 },\n },\n fullTheme: theme,\n document: document.metadata,\n section: {\n currentLayout: 'single',\n columnCount: 1,\n pageNumber: 1,\n },\n utils: {\n formatDate: (date: Date) => formatDate(date),\n parseText: (text: string) => [{ text }],\n getStyle: (name: string) => ({ name }),\n },\n depth: 0,\n };\n}\n","/**\n * JSON Document Parser - Re-exports from shared package\n *\n * This module re-exports the JSON parsing functionality from the shared package\n * and provide a clean interface for the core package.\n */\n\n// Re-export everything from shared package's JSON parser\nexport {\n JsonDocumentParser,\n JsonParsingError,\n JsonValidationError,\n parseJsonComponent,\n validateJsonComponent,\n parseJsonWithLineNumbers,\n} from '@json-to-office/shared-docx';\n\n// Re-export types needed by other modules\nexport type {\n DocumentValidationResult,\n DocumentValidationError,\n} from '@json-to-office/shared-docx';\n","import { promises as fs } from 'fs';\nimport { join, resolve, isAbsolute } from 'path';\nimport { watch, FSWatcher } from 'fs';\nimport { ComponentDefinition } from '@json-to-office/shared-docx';\nimport { parseJsonWithLineNumbers } from './parser';\n\n/**\n * File System utilities for JSON report definitions\n */\n\n/**\n * Load JSON report definition from file\n * Supports both relative and absolute file paths\n */\nexport async function loadJsonDefinition(\n filePath: string\n): Promise<ComponentDefinition> {\n try {\n // Resolve path (handles both relative and absolute paths)\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Check if file exists\n await fs.access(absolutePath);\n\n // Read file content\n const fileContent = await fs.readFile(absolutePath, 'utf-8');\n\n // Parse JSON with line number tracking for better errors\n return parseJsonWithLineNumbers(fileContent) as ComponentDefinition;\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n throw new JsonFileError(\n `File not found: ${filePath}`,\n 'FILE_NOT_FOUND'\n );\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${filePath}`,\n 'PERMISSION_DENIED'\n );\n case 'EISDIR':\n throw new JsonFileError(\n `Path is a directory: ${filePath}`,\n 'IS_DIRECTORY'\n );\n default:\n throw new JsonFileError(\n `File system error: ${fsError.message}`,\n 'FS_ERROR'\n );\n }\n }\n\n // Re-throw parsing errors with file context\n if (error instanceof Error) {\n throw new JsonFileError(\n `Error loading ${filePath}: ${error.message}`,\n 'PARSE_ERROR',\n error\n );\n }\n\n throw new JsonFileError(\n `Unknown error loading ${filePath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * Load JSON definition with validation but without throwing on validation errors\n */\nexport async function loadJsonDefinitionSafe(filePath: string): Promise<{\n success: boolean;\n definition?: ComponentDefinition;\n error?: JsonFileError;\n}> {\n try {\n const definition = await loadJsonDefinition(filePath);\n return { success: true, definition };\n } catch (error) {\n return {\n success: false,\n error:\n error instanceof JsonFileError\n ? error\n : new JsonFileError(\n error instanceof Error ? error.message : String(error),\n 'UNKNOWN_ERROR'\n ),\n };\n }\n}\n\n/**\n * Watch JSON file for changes and call callback on modifications\n * Useful for development workflows\n */\nexport function watchJsonFile(\n filePath: string,\n callback: (\n _definition: ComponentDefinition | null,\n _error?: JsonFileError\n ) => void\n): JsonFileWatcher {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Initial load\n loadJsonDefinitionSafe(absolutePath).then((result) => {\n if (result.success) {\n callback(result.definition!);\n } else {\n callback(null, result.error);\n }\n });\n\n // Set up file watcher\n const watcher = watch(absolutePath, { persistent: true }, (eventType) => {\n if (eventType === 'change') {\n // Debounce rapid file changes\n setTimeout(async () => {\n const result = await loadJsonDefinitionSafe(absolutePath);\n if (result.success) {\n callback(result.definition!);\n } else {\n callback(null, result.error);\n }\n }, 100);\n }\n });\n\n return new JsonFileWatcher(watcher, absolutePath);\n}\n\n/**\n * Watch multiple JSON files and call callback when any changes\n */\nexport function watchJsonFiles(\n filePaths: string[],\n callback: (\n _filePath: string,\n _definition: ComponentDefinition | null,\n _error?: JsonFileError\n ) => void\n): JsonFileWatcher[] {\n return filePaths.map((filePath) => {\n return watchJsonFile(filePath, (definition, error) => {\n callback(filePath, definition, error);\n });\n });\n}\n\n/**\n * Check if file exists and is accessible\n */\nexport async function checkJsonFile(filePath: string): Promise<{\n exists: boolean;\n readable: boolean;\n isDirectory: boolean;\n error?: string;\n}> {\n try {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n const stats = await fs.stat(absolutePath);\n\n return {\n exists: true,\n readable: true,\n isDirectory: stats.isDirectory(),\n };\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: 'File not found',\n };\n case 'EACCES':\n return {\n exists: true,\n readable: false,\n isDirectory: false,\n error: 'Permission denied',\n };\n default:\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: fsError.message,\n };\n }\n }\n\n return {\n exists: false,\n readable: false,\n isDirectory: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n/**\n * Find JSON files in a directory (non-recursive)\n */\nexport async function findJsonFiles(directoryPath: string): Promise<string[]> {\n try {\n const absolutePath = isAbsolute(directoryPath)\n ? directoryPath\n : resolve(directoryPath);\n const entries = await fs.readdir(absolutePath, { withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.json'))\n .map((entry) => join(absolutePath, entry.name));\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'ENOENT':\n throw new JsonFileError(\n `Directory not found: ${directoryPath}`,\n 'DIRECTORY_NOT_FOUND'\n );\n case 'ENOTDIR':\n throw new JsonFileError(\n `Path is not a directory: ${directoryPath}`,\n 'NOT_DIRECTORY'\n );\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${directoryPath}`,\n 'PERMISSION_DENIED'\n );\n default:\n throw new JsonFileError(\n `Directory error: ${fsError.message}`,\n 'DIRECTORY_ERROR'\n );\n }\n }\n\n throw new JsonFileError(\n `Unknown error reading directory ${directoryPath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * Save JSON report definition to file\n */\nexport async function saveJsonDefinition(\n definition: ComponentDefinition,\n filePath: string,\n options: { pretty?: boolean; backup?: boolean } = {}\n): Promise<void> {\n const { pretty = true, backup = false } = options;\n\n try {\n const absolutePath = isAbsolute(filePath) ? filePath : resolve(filePath);\n\n // Create backup if requested\n if (backup) {\n try {\n const backupPath = `${absolutePath}.backup`;\n await fs.copyFile(absolutePath, backupPath);\n } catch (error) {\n // Ignore backup errors if original file doesn't exist\n if (\n error instanceof Error &&\n 'code' in error &&\n (error as Error & { code?: string }).code !== 'ENOENT'\n ) {\n console.warn(`Failed to create backup: ${error.message}`);\n }\n }\n }\n\n // Serialize JSON\n const jsonContent = pretty\n ? JSON.stringify(definition, null, 2)\n : JSON.stringify(definition);\n\n // Write file\n await fs.writeFile(absolutePath, jsonContent, 'utf-8');\n } catch (error) {\n if (error instanceof Error && 'code' in error) {\n const fsError = error as Error & { code?: string };\n\n switch (fsError.code) {\n case 'EACCES':\n throw new JsonFileError(\n `Permission denied: ${filePath}`,\n 'PERMISSION_DENIED'\n );\n case 'ENOSPC':\n throw new JsonFileError(\n `No space left on device: ${filePath}`,\n 'NO_SPACE'\n );\n default:\n throw new JsonFileError(\n `Write error: ${fsError.message}`,\n 'WRITE_ERROR'\n );\n }\n }\n\n throw new JsonFileError(\n `Unknown error saving ${filePath}`,\n 'UNKNOWN_ERROR'\n );\n }\n}\n\n/**\n * File watcher wrapper class\n */\nexport class JsonFileWatcher {\n private watcher: FSWatcher;\n private filePath: string;\n\n constructor(watcher: FSWatcher, filePath: string) {\n this.watcher = watcher;\n this.filePath = filePath;\n }\n\n /**\n * Stop watching the file\n */\n public close(): void {\n this.watcher.close();\n }\n\n /**\n * Get the watched file path\n */\n public getFilePath(): string {\n return this.filePath;\n }\n}\n\n/**\n * Custom error class for file system operations\n */\nexport class JsonFileError extends Error {\n public readonly code: string;\n public readonly originalError?: Error;\n\n constructor(message: string, code: string, originalError?: Error) {\n super(message);\n this.name = 'JsonFileError';\n this.code = code;\n this.originalError = originalError;\n }\n}\n\n/**\n * Utility function to validate JSON file extension\n */\nexport function hasJsonExtension(filePath: string): boolean {\n return filePath.toLowerCase().endsWith('.json');\n}\n\n/**\n * Utility to ensure a path has .json extension\n */\nexport function ensureJsonExtension(filePath: string): string {\n return hasJsonExtension(filePath) ? filePath : `${filePath}.json`;\n}\n","/**\n * flattenVisuals — desugar `visual` components to plain `image` components ahead\n * of time, producing a portable, service-free `.docx.json`.\n *\n * The normal pipeline rasterizes `visual` nodes at render time via\n * `services.pptx`. This transform does the same desugaring offline: walk the\n * document tree, rasterize each `visual` with the supplied rasterizer, and\n * replace it with `{ name: 'image', props: { base64, ... } }`. The result builds\n * with no rasterization service configured — handy for shipping documents that\n * generate on hosts without LibreOffice/poppler.\n *\n * The walk covers every place the docx model can hold a child component, not\n * just `children`: section `props.header`/`props.footer`, and table\n * `props.columns[].cells[].content` / `props.columns[].header.content`.\n */\n\nimport {\n clampVisualDpi,\n DEFAULT_VISUAL_DPI,\n type PptxRasterizer,\n type PptxBatchRasterizer,\n type RasterizeFontFace,\n} from '@json-to-office/shared';\nimport type { VisualProps } from '@json-to-office/shared-docx';\nimport {\n buildVisualPresentation,\n visualRasterKey,\n visualToImageProps,\n} from '../components/visual';\nimport { createLimiter } from '../utils/promiseLimiter';\nimport { transformComponents, withNodeIdentity } from './componentTransform';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\n\nconst DEFAULT_CONCURRENCY = 4;\n\nexport interface FlattenVisualsOptions {\n /** Rasterizer that turns a single-slide pptx presentation into a PNG. */\n rasterize: PptxRasterizer;\n /**\n * Batch rasterizer (#153). When provided, all visuals are collected and\n * rasterized together up front; `rasterize` remains the per-visual\n * fallback for batch failures and anything the collection missed.\n */\n rasterizeBatch?: PptxBatchRasterizer;\n /** Default DPI applied when a `visual` does not specify one (default 200). */\n dpi?: number;\n /** Max concurrent rasterizations (default 4). */\n concurrency?: number;\n /**\n * Directory that relative asset paths inside visuals resolve against —\n * the document's own directory. Absent → the rasterizer's cwd (#142).\n */\n baseDir?: string;\n /**\n * Font faces staged for each visual's LibreOffice render. Without these a\n * flattened document bakes in fontless PNGs permanently — the flatten\n * output is a portable, service-free `.docx.json`, so there is no second\n * chance to re-rasterize with the right fonts.\n */\n fonts?: readonly RasterizeFontFace[];\n}\n\ninterface FlattenCtx {\n rasterize: PptxRasterizer;\n dpi?: number;\n baseDir?: string;\n fonts?: readonly RasterizeFontFace[];\n limit: <T>(fn: () => Promise<T>) => Promise<T>;\n}\n\n/**\n * Return a deep copy of `doc` with every `visual` node replaced by the `image`\n * node it rasterizes to. With `rasterizeBatch`, visuals are pre-rasterized in\n * batches and the tree walk resolves from the batch results; otherwise (and\n * for any batch miss) visuals rasterize per-node with bounded concurrency. A\n * `visual` with `enabled: false` is left untouched (it's filtered out at render\n * anyway, so rasterizing it would be wasted work). Non-visual nodes are copied\n * structurally and otherwise unchanged.\n */\nexport async function flattenVisuals<T = unknown>(\n doc: T,\n options: FlattenVisualsOptions\n): Promise<T> {\n let rasterize = options.rasterize;\n\n if (options.rasterizeBatch) {\n // The pre-pass keys results exactly like the walk below computes its\n // requests (in-process semantics: no serverUrl), so hits are exact. A\n // pre-pass failure must not fail the flatten — misses below rasterize\n // per-visual exactly as they did before batching existed.\n const preRasterized = await prerasterizeVisuals(\n doc,\n {\n render: options.rasterize,\n renderBatch: options.rasterizeBatch,\n dpi: options.dpi,\n },\n {\n baseDir: options.baseDir,\n concurrency: options.concurrency,\n fonts: options.fonts,\n }\n ).catch(() => new Map<string, never>());\n rasterize = async (request) => {\n const hit = preRasterized.get(\n visualRasterKey(request.presentation, request.dpi)\n );\n if (hit) {\n if (!hit.ok) throw new Error(hit.error);\n return {\n base64DataUri: hit.base64DataUri,\n width: hit.width,\n height: hit.height,\n };\n }\n return options.rasterize(request);\n };\n }\n\n const ctx: FlattenCtx = {\n rasterize,\n dpi: options.dpi,\n baseDir: options.baseDir,\n fonts: options.fonts,\n limit: createLimiter(\n Math.max(1, options.concurrency ?? DEFAULT_CONCURRENCY)\n ),\n };\n return transformComponents(doc, async (node) =>\n // A disabled visual is left as-is: it is filtered out at render anyway, so\n // rasterizing it would be wasted work.\n node.name === 'visual' && node.enabled !== false\n ? rasterizeVisual(node, ctx)\n : undefined\n );\n}\n\nasync function rasterizeVisual(\n obj: Record<string, unknown>,\n ctx: FlattenCtx\n): Promise<Record<string, unknown>> {\n const props = obj.props as VisualProps;\n const dpi = clampVisualDpi(props.dpi ?? ctx.dpi ?? DEFAULT_VISUAL_DPI);\n const result = await ctx.limit(() =>\n ctx.rasterize({\n presentation: buildVisualPresentation(props),\n dpi,\n baseDir: ctx.baseDir,\n ...(ctx.fonts?.length ? { fonts: [...ctx.fonts] } : {}),\n })\n );\n return withNodeIdentity(obj, {\n name: 'image',\n props: visualToImageProps(props, result.base64DataUri),\n });\n}\n","/**\n * Warnings Document Generator\n * Utility to generate a document from generation warnings\n */\n\nimport type { GenerationWarning } from '@json-to-office/shared-docx';\nimport type { ComponentDefinition, ReportComponentDefinition } from '../types';\n\n/**\n * Generate a report document from warnings\n * Returns null if there are no warnings\n */\nexport function generateWarningsDocument(\n warnings: GenerationWarning[] | null\n): ReportComponentDefinition | null {\n if (!warnings || warnings.length === 0) {\n return null;\n }\n\n const children: ComponentDefinition[] = [\n {\n name: 'heading',\n props: {\n level: 1,\n text: 'Document Generation Warnings',\n },\n },\n {\n name: 'paragraph',\n props: {\n text: `${warnings.length} warning(s) were generated during document processing.`,\n spacing: {\n after: 24,\n },\n },\n },\n ];\n\n // Group warnings by component\n const warningsByComponent = new Map<string, GenerationWarning[]>();\n for (const warning of warnings) {\n const existing = warningsByComponent.get(warning.component) || [];\n existing.push(warning);\n warningsByComponent.set(warning.component, existing);\n }\n\n // Create sections for each component with warnings\n for (const [\n componentName,\n componentWarnings,\n ] of warningsByComponent.entries()) {\n children.push({\n name: 'heading',\n props: {\n level: 3,\n text: `Component: ${componentName}`,\n },\n });\n\n // Add each warning as a list item with details\n const warningItems: string[] = [];\n for (const warning of componentWarnings) {\n let warningText = warning.message;\n\n // Add context if present\n if (warning.context && Object.keys(warning.context).length > 0) {\n const contextStr = Object.entries(warning.context)\n .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)\n .join(', ');\n warningText += ` (${contextStr})`;\n }\n\n warningItems.push(warningText);\n }\n\n children.push({\n name: 'list',\n props: {\n items: warningItems,\n spacing: {\n after: 12,\n },\n },\n });\n }\n\n return {\n name: 'docx',\n props: {\n metadata: {\n title: 'Generation Warnings',\n },\n theme: 'minimal',\n },\n children,\n };\n}\n\n/**\n * Format warnings as plain text\n * Useful for logging or text output\n */\nexport function formatWarningsText(\n warnings: GenerationWarning[] | null\n): string {\n if (!warnings || warnings.length === 0) {\n return 'No warnings generated.';\n }\n\n const lines: string[] = [\n `Document Generation Warnings (${warnings.length} total)`,\n '='.repeat(50),\n '',\n ];\n\n // Group by component\n const warningsByComponent = new Map<string, GenerationWarning[]>();\n for (const warning of warnings) {\n const existing = warningsByComponent.get(warning.component) || [];\n existing.push(warning);\n warningsByComponent.set(warning.component, existing);\n }\n\n for (const [\n componentName,\n componentWarnings,\n ] of warningsByComponent.entries()) {\n lines.push(`Component: ${componentName}`);\n lines.push('-'.repeat(30));\n\n for (let i = 0; i < componentWarnings.length; i++) {\n const warning = componentWarnings[i];\n lines.push(` ${i + 1}. ${warning.message}`);\n\n if (warning.context && Object.keys(warning.context).length > 0) {\n lines.push(` Context: ${JSON.stringify(warning.context, null, 2)}`);\n }\n }\n\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","// Version information\nexport function getCoreVersion(): string {\n return 'Core v1.0.0';\n}\n\n// Core functional API — buffer and file oriented. No export returns or accepts\n// a renderer-native object; the backend is chosen with the `renderer` option.\nexport {\n generateBufferFromJson,\n generateBufferWithWarnings,\n generateBufferFromConfig,\n generateBufferFromFile,\n generateAndSaveFromJson,\n generateAndSaveFromFile,\n validateJsonSchema,\n isReportComponentDefinition,\n DocumentGenerator as CoreDocumentGenerator,\n type DocxGenerationResult,\n} from './core/generator';\n\n// Renderer selection. The IR itself stays internal to this package for now.\nexport type { DocxRendererId } from './renderers/types';\nexport { DEFAULT_DOCX_RENDERER_ID } from './renderers/types';\nexport { docxRendererIds, isDocxRendererId } from './renderers/registry';\nexport { UncompiledComponentError } from './core/generateFromIr';\n\n// Visual flattening (desugar `visual` → `image` for portable, service-free docs)\nexport {\n flattenVisuals,\n type FlattenVisualsOptions,\n} from './core/flattenVisuals';\n\nexport {\n getVisualPrepassStats,\n resetVisualPrepassStats,\n type VisualPrepassStats,\n} from './core/prerasterizeVisuals';\n\n// Legacy class-based API is now removed - use functional API above\n\n// Runtime exports (only type guards and functions)\nexport {\n // Type guards\n isReportComponent,\n isSectionComponent,\n isHeadingComponent,\n isParagraphComponent,\n isColumnsComponent,\n isImageComponent,\n isStatisticComponent,\n isTableComponent,\n isListComponent,\n isHighchartsComponent,\n isVisualComponent,\n} from './types/index';\n\n// Export core-specific types only\nexport type {\n ReportComponentDefinition,\n ReportComponentDefinitionFor,\n // Core-specific types\n ImageContent,\n StatisticContent,\n TableData,\n SectionProperties,\n ColumnSettings,\n PageSizeOptions,\n PageMarginOptions,\n PageNumberOptions,\n PageBorderOptions,\n RenderContext,\n} from './types/index';\n\n// Utilities\nexport * from './utils/formatters';\nexport { isNodeEnvironment, hasNodeBuiltins } from './utils/environment';\nexport {\n generateWarningsDocument,\n formatWarningsText,\n} from './utils/warningsDocument';\n\n// Styles and themes\nexport {\n themes,\n minimalTheme,\n corporateTheme,\n modernTheme,\n} from './styles/index';\nexport type { ThemeName } from './styles/index';\n\n// JSON Theme System\nexport {\n loadThemeFromJson,\n loadThemeFromFile,\n exportThemeToJson,\n validateThemeJsonString,\n ThemeValidationError,\n ThemeParseError,\n ThemeFileError,\n createMinimalTheme,\n} from './themes/json/index';\n\n// Examples and utilities\nexport {\n examples,\n getExample,\n getExampleNames,\n loadJsonExample,\n} from './templates/documents/index';\nexport { runExample } from './utils/exampleRunner';\n\n// Export component implementations\nimport './components/index';\n\n// Re-export types from components (excluding those that come from shared)\nexport type {\n // ChartGenerationResult is specific to the component implementation\n ChartGenerationResult,\n} from './components/highcharts';\n\n// Note: TextSpaceAfterProps and HighchartsProps types are now in shared package\n// and should be imported from there to maintain single source of truth\n\n// Plugin System API\nexport {\n // Core plugin functions\n createComponent,\n createVersion,\n createDocumentGenerator,\n\n // Validation utilities\n validateComponentProps,\n validateDocument,\n cleanComponentProps,\n ComponentValidationError,\n UnknownPreservedComponentError,\n\n // Schema utilities\n generatePluginDocumentSchema,\n exportPluginSchema,\n generateComponentSchemas,\n mergeSchemas,\n\n // Types\n type CustomComponent,\n type ComponentVersion,\n type ComponentVersionMap,\n type RenderFunction,\n type RenderContext as ComponentRenderContext,\n type DocumentGenerator,\n type DocumentGeneratorOptions,\n type GenerateOptions,\n type GenerateFileOptions,\n type BufferGenerationResult,\n type FileGenerationResult,\n type StandardDefinitionResult,\n type ValidationResult,\n type ValidationError,\n\n // Type utilities for custom components\n type ExtractCustomComponentType,\n type CustomComponentUnion,\n type ExtendedComponentDefinition,\n type ExtendedReportComponent,\n type InferCustomComponents,\n} from './plugin/index';\n\n// Plugin types\nexport type {\n PluginComponent,\n PluginRenderFunction,\n PluginValidationError,\n PluginValidationResult,\n} from './types/plugin';\n","/**\n * Examples registry - JSON-based examples\n * This file provides a unified interface to the JSON examples system\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\nimport { ComponentDefinition } from '@json-to-office/shared-docx';\n\nlet _dirname: string | null = null;\n\nfunction getDirname(): string {\n if (_dirname === null) {\n try {\n _dirname = path.dirname(fileURLToPath(import.meta.url));\n } catch {\n throw new Error(\n 'Cannot resolve file paths in a bundled environment. Example loading from disk is not available.'\n );\n }\n }\n return _dirname;\n}\n\n/**\n * Load a JSON example by name\n */\nexport function loadJsonExample(name: string): ComponentDefinition {\n // Since this file is bundled into dist/index.js, getDirname() will be the dist directory\n // The JSON files are copied to dist/templates/documents/ by the tsup config\n const filePath = path.join(\n getDirname(),\n 'templates',\n 'documents',\n `${name}.docx.json`\n );\n\n try {\n const content = fs.readFileSync(filePath, 'utf8');\n return JSON.parse(content) as ComponentDefinition;\n } catch (error) {\n throw new Error(\n `Failed to load JSON example \"${name}\": ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\n/**\n * Get list of available JSON examples\n */\nexport function getAvailableJsonExamples(): string[] {\n // Since this file is bundled into dist/index.js, getDirname() will be the dist directory\n // The JSON files are copied to dist/templates/documents/ by the tsup config\n const examplesDir = path.join(getDirname(), 'templates', 'documents');\n\n try {\n const files = fs.readdirSync(examplesDir);\n return files\n .filter((file) => file.endsWith('.docx.json'))\n .map((file) => path.basename(file, '.docx.json'))\n .sort();\n } catch (error) {\n console.warn('Could not read JSON examples directory:', error);\n return [];\n }\n}\n\n/**\n * Example descriptions for documentation\n */\nexport const EXAMPLE_DESCRIPTIONS: Record<string, string> = {\n 'technical-guide':\n 'Arcline Platform integration guide with TOC, headers/footers, OAuth code samples, API reference tables, webhook docs, and troubleshooting',\n proposal:\n 'Apex Consulting cloud migration proposal with TOC, headers/footers, images, statistics, compliance tables, cost comparisons, and risk matrix',\n};\n\n/**\n * Registry of available JSON examples (lazy-loaded)\n * For backward compatibility, this returns ComponentDefinition objects\n */\nconst _exampleCache: Record<string, ComponentDefinition> = {};\n\nexport const examples = new Proxy({} as Record<string, ComponentDefinition>, {\n get(_target, prop: string) {\n if (!_exampleCache[prop]) {\n try {\n _exampleCache[prop] = loadJsonExample(prop);\n } catch {\n return undefined;\n }\n }\n return _exampleCache[prop];\n },\n\n ownKeys(_target) {\n return getAvailableJsonExamples();\n },\n\n has(_target, prop: string) {\n return getAvailableJsonExamples().includes(prop);\n },\n});\n\n/**\n * Get example definition by name\n */\nexport const getExample = (\n exampleName: string\n): ComponentDefinition | undefined => {\n return examples[exampleName];\n};\n\n/**\n * Get all available example names\n */\nexport const getExampleNames = (): string[] => {\n return getAvailableJsonExamples();\n};\n\n// Use loadJsonExample() directly or access via the examples proxy\nexport const technicalGuideExample = () => loadJsonExample('technical-guide');\nexport const proposalExample = () => loadJsonExample('proposal');\n\n/**\n * Print usage information\n */\nexport function printExampleUsage(): void {\n const available = getAvailableJsonExamples();\n\n console.log('📋 Available JSON Examples:');\n console.log('===========================');\n\n available.forEach((name) => {\n const description =\n EXAMPLE_DESCRIPTIONS[name] || 'No description available';\n console.log(`\\n📄 ${name}:`);\n console.log(` ${description}`);\n console.log(` Usage: loadJsonExample('${name}')`);\n });\n\n console.log('\\n🔧 Example code:');\n console.log('```typescript');\n console.log(\n 'import { loadJsonExample, generateDocumentFromJson } from \"cool-report-generator\";'\n );\n console.log('');\n console.log('const jsonConfig = loadJsonExample(\"comprehensive\");');\n console.log('const document = await generateDocumentFromJson(jsonConfig);');\n console.log('```');\n}\n","/**\n * Universal example runner utility\n * Provides common functionality for running examples\n */\n\nimport { generateAndSaveFromJson } from '../core/generator';\nimport { ReportComponentDefinition } from '../types';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport interface ExampleRunnerOptions {\n outputFilename?: string;\n outputDir?: string;\n verbose?: boolean;\n}\n\n/**\n * Run an example and generate a document\n * @param example - The example definition to run\n * @param options - Options for running the example\n */\nexport async function runExample(\n example: ReportComponentDefinition,\n options: ExampleRunnerOptions = {}\n): Promise<void> {\n const { outputFilename, outputDir, verbose = true } = options;\n\n if (!example.props) {\n throw new Error('Example must have props');\n }\n\n const reportTitle = String(example.props.metadata?.title) || 'Document';\n const baseFilename =\n outputFilename || `${reportTitle.toLowerCase().replace(/\\s+/g, '-')}.docx`;\n\n // Use output directory if provided, otherwise use default output/examples path\n const defaultOutputDir = path.join(process.cwd(), 'output', 'examples');\n const finalOutputDir = outputDir || defaultOutputDir;\n const filename = path.join(finalOutputDir, baseFilename);\n\n if (verbose) {\n console.log(`=== ${reportTitle} Generation ===\\n`);\n console.log(`Generating ${reportTitle} with modular system...`);\n }\n\n try {\n // Ensure output directory exists\n await fs.promises.mkdir(finalOutputDir, { recursive: true });\n\n await generateAndSaveFromJson(example, filename);\n\n if (verbose) {\n console.log(`✓ ${reportTitle} saved: ${filename}`);\n console.log(`\\n✅ ${reportTitle} generated successfully!`);\n }\n } catch (error) {\n if (verbose) {\n console.error(`${reportTitle} generation failed:`, error);\n }\n throw error;\n }\n}\n","/**\n * Text Space After Custom Component\n * A text component with hardcoded spacing after the paragraph\n *\n * This component is provided as an example of the legacy custom component system.\n * For new custom components, use the plugin system instead:\n * @see packages/core/src/plugin/example/ for modern examples\n */\n\nimport { Type, Static } from '@sinclair/typebox';\nimport { createComponent, createVersion } from '../plugin/createComponent';\nimport type { ComponentDefinition } from '@json-to-office/shared-docx';\n\n/**\n * Props schema for text-space-after component\n */\nconst TextSpaceAfterPropsSchema = Type.Object({\n text: Type.String({\n description: 'Text content to display',\n }),\n // Retained for backwards compatibility of props shape, but not applied\n spacing: Type.Optional(\n Type.Object({\n before: Type.Optional(Type.Number()),\n after: Type.Optional(Type.Number()),\n })\n ),\n});\n\nexport type TextSpaceAfterProps = Static<typeof TextSpaceAfterPropsSchema>;\n\n/**\n * Text space after component - adds hardcoded spacing after paragraphs\n */\nexport const textSpaceAfterComponent = createComponent({\n name: 'text-space-after',\n versions: {\n '1.0.0': createVersion({\n propsSchema: TextSpaceAfterPropsSchema,\n description: 'Text component with hardcoded spacing after the paragraph',\n render: async ({ props }) => {\n // Create paragraph component with hardcoded spacing after\n const result: ComponentDefinition = {\n name: 'paragraph',\n props: {\n text: props.text,\n spacing: {\n ...props.spacing,\n after: props.spacing?.after || 12,\n },\n },\n };\n\n return [result];\n },\n }),\n },\n});\n","import type { TSchema } from '@sinclair/typebox';\nimport type { ComponentDefinition } from '@json-to-office/shared-docx';\nimport type { ThemeConfig } from '../styles';\nimport {\n createVersion as sharedCreateVersion,\n createComponent as sharedCreateComponent,\n} from '@json-to-office/shared/plugin';\nimport type {\n RenderContext as SharedRenderContext,\n RenderFunction as SharedRenderFunction,\n ComponentVersion as SharedComponentVersion,\n ComponentVersionMap as SharedComponentVersionMap,\n CustomComponent as SharedCustomComponent,\n} from '@json-to-office/shared/plugin';\n\n// ---- DOCX-specific type aliases (backward compat) ----\n\n/**\n * DOCX render context with ThemeConfig baked in\n */\nexport type RenderContext<T> = SharedRenderContext<T, ThemeConfig>;\n\nexport type RenderFunction<\n TProps,\n TComponentDefinition = ComponentDefinition,\n> = SharedRenderFunction<TProps, TComponentDefinition, ThemeConfig>;\n\nexport type ComponentVersion<\n TComponentDefinition = ComponentDefinition,\n TPropsSchema extends TSchema = TSchema,\n> = SharedComponentVersion<TComponentDefinition, TPropsSchema, ThemeConfig>;\n\nexport type ComponentVersionMap<TComponentDefinition = ComponentDefinition> =\n SharedComponentVersionMap<TComponentDefinition, ThemeConfig>;\n\nexport type CustomComponent<\n TComponentDefinition = ComponentDefinition,\n TVersions extends\n ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>,\n TName extends string = string,\n> = SharedCustomComponent<TComponentDefinition, TVersions, TName>;\n\n// ---- Re-export factory functions (thin wrappers for DOCX defaults) ----\n\nexport function createVersion<\n TPropsSchema extends TSchema,\n TComponentDefinition = ComponentDefinition,\n>(\n version: ComponentVersion<TComponentDefinition, TPropsSchema>\n): ComponentVersion<TComponentDefinition, TPropsSchema> {\n return sharedCreateVersion(version);\n}\n\nexport function createComponent<\n TComponentDefinition = ComponentDefinition,\n TVersions extends\n ComponentVersionMap<TComponentDefinition> = ComponentVersionMap<TComponentDefinition>,\n TName extends string = string,\n>(\n component: CustomComponent<TComponentDefinition, TVersions, TName>\n): CustomComponent<TComponentDefinition, TVersions, TName> {\n return sharedCreateComponent(component);\n}\n","import type { TSchema } from '@sinclair/typebox';\nimport type { CustomComponent } from './createComponent';\nimport type { ComponentDefinition, ReportComponentDefinition } from '../types';\nimport type { DocxRendererId } from '../renderers/types';\nimport { type ThemeConfig } from '../styles';\nimport { resolveBuiltInTheme } from '../styles/theme-resolver';\nimport { hasTheme } from '../templates/themes';\nimport { resolveThemeContext } from '../core/generationContext';\nimport type { GenerationWarning } from '@json-to-office/shared-docx';\nimport type { ServicesConfig, FontRuntimeOpts } from '@json-to-office/shared';\nimport type {\n ExtendedReportComponent,\n DocumentGeneratorBuilder,\n GenerateOptions,\n GenerateFileOptions,\n BufferGenerationResult,\n FileGenerationResult,\n StandardDefinitionResult,\n ValidationResult,\n GenerationValidationOptions,\n} from './types';\nimport {\n validateDocument,\n cleanComponentProps,\n ComponentValidationError,\n DuplicateComponentError,\n} from './validation';\nimport { UnknownPreservedComponentError } from '@json-to-office/shared/plugin';\nimport { resolveComponentVersion } from './version-resolver';\nimport { generatePluginDocumentSchema, exportPluginSchema } from './schema';\nimport { generateBufferViaIr } from '../core/generateFromIr';\nimport { normalizeDocument } from '../json/normalizer';\n\n/**\n * Options for creating a document generator\n */\nexport interface DocumentGeneratorOptions {\n /** Default theme used when no custom or built-in theme matches */\n theme?: ThemeConfig;\n /** Custom themes keyed by name, resolved per-document via document.props.theme */\n customThemes?: Record<string, ThemeConfig>;\n /** Enable debug logging */\n debug?: boolean;\n /** External service configuration (e.g. Highcharts export server) */\n services?: ServicesConfig;\n /** Font resolution options — extraEntries, Google Fonts config, onResolved hook. */\n fonts?: FontRuntimeOpts;\n /**\n * Default validation behavior for every generateBuffer/generateFile\n * call. Per-call `options.validation` overrides these. Validation is on by\n * default; pass `{ enabled: false }` to opt out.\n */\n validation?: GenerationValidationOptions;\n /** Normalize volatile OOXML values for byte-identical output. Defaults true. */\n deterministic?: boolean;\n /** Default build timestamp for generated metadata. */\n generatedAt?: string | Date;\n /**\n * Directory that relative asset paths (image `path` props) resolve against.\n * Per-call `options.baseDir` overrides it; defaults to `process.cwd()`\n * when neither is set (#142).\n */\n baseDir?: string;\n /**\n * Backend that turns the compiled document into bytes.\n *\n * Defaults to `docxjs`, which is what every existing caller gets.\n * `office-open` is experimental and opt-in: it declares a subset of features\n * and fails before rendering on anything outside it.\n */\n renderer?: DocxRendererId;\n}\n\n/**\n * Internal state held by each builder instance\n */\ninterface BuilderState {\n components: readonly CustomComponent<any, any, any>[];\n componentNames: Set<string>;\n theme?: ThemeConfig;\n customThemes?: Record<string, ThemeConfig>;\n debug: boolean;\n services?: ServicesConfig;\n fonts?: FontRuntimeOpts;\n validation?: GenerationValidationOptions;\n deterministic: boolean;\n generatedAt?: string | Date;\n baseDir?: string;\n renderer?: DocxRendererId;\n}\n\n/**\n * Create the builder implementation with the given state\n */\nfunction createBuilderImpl<\n TComponents extends readonly CustomComponent<any, any, any>[],\n>(state: BuilderState): DocumentGeneratorBuilder<TComponents> {\n // Create component map for quick lookup\n const componentMap = new Map(state.components.map((c) => [c.name, c]));\n\n /**\n * Resolve theme for a document: customThemes → doc-named built-in →\n * constructor theme → built-in resolver fallback.\n *\n * A document explicitly naming a known built-in gets it; the constructor\n * `theme` object fills in when the document names nothing or names\n * something nothing recognizes (#141). The `authored` guard on the\n * built-in step matters twice over: the unauthored 'minimal' fallback\n * must not shadow the constructor theme, and an authored UNKNOWN name\n * must still reach the constructor theme rather than silently rendering\n * the resolver's minimal fallback.\n */\n function resolveDocumentTheme(\n themeName: string,\n warnings: GenerationWarning[] | undefined,\n authored: boolean\n ): ThemeConfig {\n if (state.customThemes) {\n if (state.customThemes[themeName]) {\n return state.customThemes[themeName];\n }\n const key = Object.keys(state.customThemes).find(\n (k) => k.toLowerCase() === themeName.toLowerCase()\n );\n if (key) {\n return state.customThemes[key];\n }\n }\n if (authored && hasTheme(themeName)) {\n return resolveBuiltInTheme(themeName, {\n customThemes: state.customThemes,\n warnings,\n });\n }\n if (state.theme) {\n return state.theme;\n }\n return resolveBuiltInTheme(themeName, {\n customThemes: state.customThemes,\n warnings,\n });\n }\n\n /**\n * Process custom components in the document.\n *\n * Returns two parallel trees built in a single pass:\n * - `standard`: fully expanded — every custom component resolved to standard primitives.\n * - `preserved`: partially expanded — nodes whose name is in `preserveSet` are kept\n * verbatim (children NOT recursed); everything else is expanded the same as `standard`.\n *\n * `render()` always runs, even for preserved components, because the docx pipeline\n * builds from `standard` and we still need their warnings/font registrations.\n */\n async function processDocumentComponents(\n components: ComponentDefinition[],\n preserveSet: ReadonlySet<string> | undefined,\n warningsCollector: GenerationWarning[],\n resolvedTheme: ThemeConfig,\n validateEmitted:\n | ((emitted: ComponentDefinition[], componentLabel: string) => void)\n | undefined,\n depth = 0\n ): Promise<{\n standard: ComponentDefinition[];\n preserved: ComponentDefinition[];\n }> {\n if (depth > 20) {\n throw new Error(\n 'Maximum component nesting depth exceeded (20). Check for circular component references.'\n );\n }\n const standardOut: ComponentDefinition[] = [];\n const preservedOut: ComponentDefinition[] = [];\n\n for (const componentData of components) {\n // Safe type narrowing for custom component detection\n const componentName = (componentData as { name?: string })?.name;\n\n if (!componentName) {\n standardOut.push(componentData);\n preservedOut.push(componentData);\n continue;\n }\n\n const customComponent = componentMap.get(componentName);\n\n if (customComponent) {\n // This is a custom component - validate and process it\n try {\n const componentWithName = componentData as {\n name: string;\n version?: string;\n props?: unknown;\n children?: unknown;\n };\n\n if (!componentWithName.props) {\n throw new Error(\n `Custom component '${componentName}' must have a 'props' property. Use format: { name: '${componentName}', props: {...} }`\n );\n }\n\n // Resolve the correct version entry\n const versionEntry = resolveComponentVersion(\n customComponent.name,\n customComponent.versions,\n componentWithName.version\n );\n\n // Validate and clean the props against the resolved version's schema\n const cleanedProps = cleanComponentProps(\n versionEntry,\n componentWithName.props\n );\n\n // Process nested children if this is a container.\n // For the standard tree we need the fully-expanded children to feed render().\n let nestedChildren: unknown[] | undefined;\n if (\n componentWithName.children &&\n Array.isArray(componentWithName.children)\n ) {\n const nested = await processDocumentComponents(\n componentWithName.children as ComponentDefinition[],\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n nestedChildren = nested.standard;\n }\n\n // Create addWarning callback for this component\n const versionLabel = componentWithName.version\n ? `${customComponent.name}@${componentWithName.version}`\n : customComponent.name;\n\n const addWarning = (\n message: string,\n context?: Record<string, unknown>\n ) => {\n warningsCollector.push({\n component: versionLabel,\n message,\n severity: 'warning',\n context,\n });\n };\n\n // Call the render function with context object\n const result = await versionEntry.render({\n props: cleanedProps,\n theme: resolvedTheme,\n addWarning,\n children: nestedChildren,\n });\n\n // Ensure result is an array\n const resultComponents = (\n Array.isArray(result) ? result : [result]\n ) as ComponentDefinition[];\n\n // Validate the standard tree this render() emitted, applying the same\n // schema gate authored standard components pass through up front. The\n // pre-expansion pass never saw these nodes, so without this an invalid\n // prop produced by a plugin would ride through into standardDefinition\n // and only surface when that output is validated separately.\n if (validateEmitted) {\n validateEmitted(resultComponents, versionLabel);\n }\n\n // Recursively process the result in case it contains more custom components\n const processedResult = await processDocumentComponents(\n resultComponents,\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n standardOut.push(...processedResult.standard);\n\n if (preserveSet && preserveSet.has(componentName)) {\n // Keep this custom node verbatim in the preserved tree.\n // Per spec: do NOT recurse into authored children — leave the\n // entire subtree as the user wrote it.\n preservedOut.push(componentData);\n } else {\n // Non-preserved custom: emit the recursed expansion (which itself\n // honors preserveSet for any nested customs).\n preservedOut.push(...processedResult.preserved);\n }\n\n if (state.debug) {\n console.log(\n `Processed custom component '${versionLabel}':`,\n processedResult.standard\n );\n }\n } catch (error) {\n if (error instanceof ComponentValidationError) {\n throw error;\n }\n throw new Error(\n `Error processing custom component '${customComponent.name}': ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n } else {\n // This is a standard component or nested container - process recursively\n if (\n 'children' in componentData &&\n Array.isArray(componentData.children)\n ) {\n const processedNested = await processDocumentComponents(\n componentData.children,\n preserveSet,\n warningsCollector,\n resolvedTheme,\n validateEmitted,\n depth + 1\n );\n standardOut.push({\n ...componentData,\n children: processedNested.standard,\n });\n preservedOut.push({\n ...componentData,\n children: processedNested.preserved,\n });\n } else {\n standardOut.push(componentData);\n preservedOut.push(componentData);\n }\n }\n }\n\n return { standard: standardOut, preserved: preservedOut };\n }\n\n /**\n * Add a custom component to the generator\n */\n function addComponent<TNewComponent extends CustomComponent<any, any, any>>(\n component: TNewComponent\n ): DocumentGeneratorBuilder<readonly [...TComponents, TNewComponent]> {\n if (!component.name) {\n throw new Error('Component name is required');\n }\n\n if (state.componentNames.has(component.name)) {\n throw new DuplicateComponentError(component.name);\n }\n\n // Create NEW immutable state\n const newComponentNames = new Set(state.componentNames);\n newComponentNames.add(component.name);\n\n const newState: BuilderState = {\n components: [...state.components, component],\n componentNames: newComponentNames,\n theme: state.theme,\n customThemes: state.customThemes,\n debug: state.debug,\n services: state.services,\n fonts: state.fonts,\n validation: state.validation,\n deterministic: state.deterministic,\n generatedAt: state.generatedAt,\n baseDir: state.baseDir,\n renderer: state.renderer,\n };\n\n // Return NEW builder with expanded type\n return createBuilderImpl<readonly [...TComponents, TNewComponent]>(\n newState\n );\n }\n\n /**\n * Resolve and validate the preserve set for a per-call options object.\n * Returns `undefined` when the caller did not opt in.\n * Throws `UnknownPreservedComponentError` when any listed name is not registered.\n */\n function resolvePreserveSet(\n options?: GenerateOptions\n ): ReadonlySet<string> | undefined {\n const list = options?.preserveCustomComponents;\n if (!list || list.length === 0) {\n return undefined;\n }\n const registered = new Set(state.componentNames);\n const unknown = list.filter((n) => !registered.has(n));\n if (unknown.length > 0) {\n throw new UnknownPreservedComponentError(\n unknown,\n Array.from(state.componentNames)\n );\n }\n return new Set(list);\n }\n\n /**\n * Shared front half of the pipeline: validate, resolve theme context,\n * expand custom components, normalize. Everything `standardDefinition`\n * needs and nothing more — fonts, structure, layout, rendering (and the\n * visual rasterization that rides on it) all happen after this point.\n */\n async function expandDocument(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<{\n modedRoot: ReportComponentDefinition;\n modedTheme: ThemeConfig;\n themeName: string;\n processed: {\n standard: ComponentDefinition[];\n preserved: ComponentDefinition[];\n };\n modedDoc: ReportComponentDefinition;\n warnings: GenerationWarning[];\n preserveSet: ReadonlySet<string> | undefined;\n }> {\n const preserveSet = resolvePreserveSet(options);\n\n // Cast to ReportComponentDefinition for internal processing. A root\n // written without a `props` key validates clean, so default it to `{}`\n // — otherwise every downstream `props.*` read throws. Only `undefined`\n // is defaulted, so a malformed `props: null` still reaches the\n // validator. Matches core/generator.ts.\n const rootIn = document as unknown as ReportComponentDefinition;\n const internalDocument: ReportComponentDefinition =\n rootIn.props === undefined ? { ...rootIn, props: {} } : rootIn;\n const renderer =\n options?.renderer ?? state.renderer ?? internalDocument.renderer;\n const validationDocument =\n renderer === undefined\n ? internalDocument\n : { ...internalDocument, renderer };\n\n // Validate the document first (plugin-aware), unless disabled. Throwing\n // here stops a malformed document from silently building into a corrupt\n // or incomplete DOCX.\n const vOpts: GenerationValidationOptions = {\n ...state.validation,\n ...options?.validation,\n };\n if (vOpts.enabled !== false) {\n const result = validateDocument(\n validationDocument,\n state.components as unknown as CustomComponent<TSchema>[],\n { allowUnknownFields: vOpts.allowUnknownFields }\n );\n if (!result.valid) {\n throw new ComponentValidationError(\n (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: e.message,\n })),\n internalDocument\n );\n }\n }\n\n // Re-apply the same gate to the tree each custom component's render()\n // emits. The pre-expansion pass above only saw authored nodes, so a\n // standard component produced by a plugin would otherwise reach\n // standardDefinition unchecked. We validate the emitted nodes in their\n // pre-normalization form — exactly how authored nodes are validated —\n // by reusing the already-validated document props as a wrapper, so the\n // only new errors come from the emitted children. Undefined when\n // validation is disabled, which short-circuits the boundary check.\n const validateEmitted =\n vOpts.enabled === false\n ? undefined\n : (emitted: ComponentDefinition[], componentLabel: string) => {\n const result = validateDocument(\n {\n ...internalDocument,\n ...(renderer !== undefined ? { renderer } : {}),\n children: emitted,\n },\n state.components as unknown as CustomComponent<TSchema>[],\n { allowUnknownFields: vOpts.allowUnknownFields }\n );\n if (!result.valid) {\n throw new ComponentValidationError(\n (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: `custom component '${componentLabel}' emitted invalid output — ${e.message}`,\n })),\n emitted\n );\n }\n };\n\n // Initialize warnings collector\n const warnings: GenerationWarning[] = [];\n\n // Props defaulting, theme resolution (customThemes → doc-named\n // built-in → constructor theme → built-in fallback, see\n // resolveDocumentTheme), in-document overrides and export-mode pre-pass —\n // shared with the core pipeline so the two cannot drift (see\n // core/generationContext.ts). The pre-pass runs BEFORE custom-component\n // expansion so components reading `theme.fonts.*` during render see the\n // substituted names, not the original non-safe ones.\n const {\n document: modedRoot,\n theme: modedTheme,\n themeName,\n } = resolveThemeContext(internalDocument, {\n customThemes: state.customThemes,\n fonts: state.fonts,\n warnings,\n resolveNamedTheme: resolveDocumentTheme,\n });\n\n // Process custom components to convert them to standard components.\n // Builds standard (fully expanded) and preserved (partial) trees in one pass.\n const processed = await processDocumentComponents(\n modedRoot.children || [],\n preserveSet,\n warnings,\n modedTheme,\n validateEmitted\n );\n\n // Create a new document definition with processed components\n const processedDocument: ReportComponentDefinition = {\n ...modedRoot,\n children: processed.standard,\n };\n\n // Normalize components (handle shorthand notations and nested structures)\n // We bypass JSON validation since we've already validated with custom schemas\n const [modedDoc] = normalizeDocument(processedDocument);\n\n return {\n modedRoot,\n modedTheme,\n themeName,\n processed,\n modedDoc,\n warnings,\n preserveSet,\n };\n }\n\n /**\n * Compute only the post-expansion standard definition. Runs validation,\n * theme resolution, custom-component expansion, and normalization — but\n * skips font resolution, layout, rendering, and packaging, so it never\n * touches external services (no visual rasterization, no chart export).\n * Orders of magnitude cheaper than `generateBuffer()` when you only need the\n * JSON tree.\n */\n async function expandStandardDefinition(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<StandardDefinitionResult> {\n try {\n const { modedDoc, warnings } = await expandDocument(document, options);\n return {\n standardDefinition: modedDoc,\n warnings: warnings.length > 0 ? warnings : null,\n };\n } catch (error) {\n if (state.debug) {\n console.error('Document expansion error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Generate a document as a `.docx` buffer.\n *\n * The custom components are expanded first, then the standard tree it\n * produced goes through the same DocxIR pipeline every other entry point\n * uses — a plugin document and a plain one are the same document by the time\n * anything renders.\n */\n async function generateBuffer(\n document: ExtendedReportComponent<TComponents>,\n options?: GenerateOptions\n ): Promise<BufferGenerationResult<TComponents>> {\n try {\n const {\n modedRoot,\n modedTheme,\n themeName,\n processed,\n modedDoc,\n warnings,\n preserveSet,\n } = await expandDocument(document, options);\n\n const baseDir = options?.baseDir ?? state.baseDir;\n const deterministic = options?.deterministic ?? state.deterministic;\n const generatedAt = options?.generatedAt ?? state.generatedAt;\n const renderer =\n options?.renderer ?? state.renderer ?? modedRoot.renderer;\n\n const { buffer } = await generateBufferViaIr(modedDoc, {\n // The prologue already ran: the theme had to be resolved before custom\n // components expanded, because each one's `render` is handed it.\n context: { document: modedDoc, theme: modedTheme, themeName },\n ...(state.services ? { services: state.services } : {}),\n ...(state.fonts ? { fonts: state.fonts } : {}),\n ...(baseDir !== undefined ? { baseDir } : {}),\n ...(deterministic !== undefined ? { deterministic } : {}),\n ...(generatedAt !== undefined ? { generatedAt } : {}),\n ...(renderer !== undefined ? { renderer } : {}),\n warnings,\n });\n\n // Build preservedDefinition iff the caller opted in. Reuses the same\n // doc shell as standardDefinition but with partially-expanded children.\n // Not normalized — preserved subtrees are meant to be \"as authored\".\n const preservedDefinition = preserveSet\n ? ({\n ...modedRoot,\n children: processed.preserved,\n } as unknown as ExtendedReportComponent<TComponents>)\n : undefined;\n\n return {\n buffer,\n warnings: warnings.length > 0 ? warnings : null,\n standardDefinition: modedDoc,\n preservedDefinition,\n };\n } catch (error) {\n if (state.debug) {\n console.error('Document generation error:', error);\n }\n throw error;\n }\n }\n\n /**\n * Generate a document and save to file\n */\n async function generateFile(\n document: ExtendedReportComponent<TComponents>,\n outputPath: string,\n options?: GenerateFileOptions\n ): Promise<FileGenerationResult<TComponents>> {\n const { buffer, warnings, standardDefinition, preservedDefinition } =\n await generateBuffer(document, options);\n const fs = await import('fs/promises');\n await fs.writeFile(outputPath, new Uint8Array(buffer));\n\n let preservedOutputPath: string | undefined;\n if (preservedDefinition !== undefined) {\n const path = await import('path');\n preservedOutputPath =\n options?.preservedOutputPath ??\n (() => {\n const ext = path.extname(outputPath);\n const base = ext ? outputPath.slice(0, -ext.length) : outputPath;\n return `${base}-preserved.json`;\n })();\n await fs.writeFile(\n preservedOutputPath,\n JSON.stringify(preservedDefinition, null, 2),\n 'utf8'\n );\n }\n\n return {\n warnings,\n standardDefinition,\n preservedDefinition,\n preservedOutputPath,\n };\n }\n\n /**\n * Get registered component names\n */\n function getComponentNames(): string[] {\n return Array.from(state.componentNames);\n }\n\n /**\n * Validate a document without generating it\n */\n function validate(\n document: ExtendedReportComponent<TComponents>\n ): ValidationResult {\n try {\n // Cast to ReportComponentDefinition for internal validation\n const internalDocument = document as unknown as ReportComponentDefinition;\n const result = validateDocument(\n internalDocument,\n state.components as unknown as CustomComponent<TSchema>[]\n );\n if (result.valid) {\n return { valid: true };\n }\n return {\n valid: false,\n errors: (result.errors ?? []).map((e) => ({\n path: e.path ?? '',\n message: e.message,\n })),\n };\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n path: 'document',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n }\n\n /**\n * @deprecated Read `standardDefinition` off `generateBuffer(...)` instead.\n * This wrapper expands every custom component just to surface the JSON tree,\n * so calling it alongside a generate doubles that work. Kept for backwards\n * compatibility; will be removed in a future major.\n */\n async function getStandardComponentsDefinition(\n document: ExtendedReportComponent<TComponents>\n ): Promise<ReportComponentDefinition> {\n const { modedDoc } = await expandDocument(document);\n return modedDoc;\n }\n\n /**\n * Generate the extended JSON schema for document validation\n */\n function generateSchema(includeStandardComponents = true): TSchema {\n return generatePluginDocumentSchema(\n state.components as unknown as CustomComponent<TSchema>[],\n includeStandardComponents\n );\n }\n\n /**\n * Export the extended JSON schema to a file\n */\n async function exportSchemaToFile(\n outputPath: string,\n options?: {\n includeStandardComponents?: boolean;\n prettyPrint?: boolean;\n }\n ): Promise<void> {\n await exportPluginSchema(\n state.components as unknown as CustomComponent<TSchema>[],\n outputPath,\n options\n );\n }\n\n // Return frozen builder object\n return Object.freeze({\n addComponent,\n generateBuffer,\n generateFile,\n expandStandardDefinition,\n getComponentNames,\n validate,\n generateSchema,\n exportSchema: exportSchemaToFile,\n getStandardComponentsDefinition,\n });\n}\n\n/**\n * Create a document generator with chainable component registration.\n */\nexport function createDocumentGenerator(\n options: DocumentGeneratorOptions\n): DocumentGeneratorBuilder<readonly []> {\n const initialState: BuilderState = {\n components: [],\n componentNames: new Set(),\n theme: options.theme,\n customThemes: options.customThemes,\n debug: options.debug ?? false,\n services: options.services,\n fonts: options.fonts,\n validation: options.validation,\n deterministic: options.deterministic ?? true,\n generatedAt: options.generatedAt,\n baseDir: options.baseDir,\n renderer: options.renderer,\n };\n\n return createBuilderImpl<readonly []>(initialState);\n}\n","export { resolveComponentVersion } from '@json-to-office/shared/plugin';\n","import type { TSchema, Static } from '@sinclair/typebox';\nimport type { CustomComponent } from './createComponent';\nimport type { ReportComponentDefinition } from '../types';\nimport { resolveComponentVersion } from './version-resolver';\nimport {\n validateCustomComponentProps,\n ComponentValidationError,\n type ComponentValidationResult,\n} from '@json-to-office/shared/plugin';\nimport {\n validateDocument as validateDocumentUnified,\n type ValidationError,\n} from '@json-to-office/shared-docx/validation/unified';\nimport type { ValidationResult } from '@json-to-office/shared';\n\n// Re-export errors from shared\nexport {\n DuplicateComponentError,\n ComponentValidationError,\n UnknownPreservedComponentError,\n} from '@json-to-office/shared/plugin';\n\n/**\n * Validate a component props against a schema.\n * Accepts a narrower interface — only needs { propsSchema }.\n */\nexport function validateComponentProps<TPropsSchema extends TSchema>(\n schema: { propsSchema: TPropsSchema },\n props: unknown,\n componentName?: string,\n opts?: { clean?: boolean; applyDefaults?: boolean }\n): ComponentValidationResult<TPropsSchema> {\n // `clean` defaults to true so the render path (getValidatedProps) keeps\n // normalizing props (strip unknown + apply defaults). The validation path\n // passes `clean: false` to reject unknown keys instead of silently dropping\n // them — strict unless the caller opts into allowUnknownFields.\n return validateCustomComponentProps<TPropsSchema>(schema.propsSchema, props, {\n clean: opts?.clean ?? true,\n applyDefaults: opts?.applyDefaults ?? true,\n componentName,\n });\n}\n\n/**\n * Validate document and all custom components (version-aware).\n *\n * Standard components (paragraph, section, …) are validated against their\n * schemas via the unified validator, which is told the registered custom names\n * so it neither rejects them as unknown nor checks them against a standard\n * schema. Custom component props are then validated version-aware below. Errors\n * from both passes are merged so a single call reports the whole document.\n */\nexport function validateDocument(\n document: ReportComponentDefinition,\n customComponents: CustomComponent<any, any, any>[],\n options?: { allowUnknownFields?: boolean }\n): ValidationResult & { success: boolean } {\n const knownCustomNames = new Set(customComponents.map((c) => c.name));\n\n // Validate the standard-component structure (custom components deferred).\n const documentResult = validateDocumentUnified(document, {\n knownCustomNames,\n allowUnknownFields: options?.allowUnknownFields,\n });\n\n // Collect standard-structure errors, then append custom-component errors.\n const errors: ValidationError[] = [...(documentResult.errors || [])];\n\n function validateComponents(components: any[], pathPrefix = 'children') {\n components.forEach((componentData, index) => {\n const customComponent = customComponents.find(\n (cc) => cc.name === componentData.name\n );\n if (!customComponent) {\n return;\n }\n\n const versionEntry = resolveComponentVersion(\n customComponent.name,\n customComponent.versions,\n componentData.version\n );\n\n const validation = validateComponentProps(\n versionEntry,\n componentData.props,\n customComponent.name,\n // Reject unknown custom props unless the caller allows them.\n { clean: options?.allowUnknownFields === true }\n );\n\n if (!validation.valid && validation.errors) {\n const indexedErrors = validation.errors.map(\n (error: ValidationError) => ({\n ...error,\n path: `${pathPrefix}[${index}].${error.path}`,\n })\n );\n errors.push(...indexedErrors);\n }\n\n if (componentData.children && Array.isArray(componentData.children)) {\n validateComponents(\n componentData.children,\n `${pathPrefix}[${index}].children`\n );\n }\n });\n }\n\n if (document.children) {\n validateComponents(document.children);\n }\n\n return errors.length > 0\n ? { success: false, errors, valid: false }\n : { success: true, errors: [], valid: true };\n}\n\n/**\n * Validates component props and returns the typed props or throws.\n */\nexport function getValidatedProps<TPropsSchema extends TSchema>(\n schema: { propsSchema: TPropsSchema },\n props: unknown\n): Static<TPropsSchema> {\n const validation = validateComponentProps(schema, props);\n\n if (!validation.valid) {\n throw new ComponentValidationError(validation.errors || [], props);\n }\n\n return validation.data!;\n}\n\n// Re-export types\nexport type { ValidationError } from '@json-to-office/shared-docx/validation/unified';\nexport type { ComponentValidationResult } from '@json-to-office/shared/plugin';\n\nexport const cleanComponentProps = getValidatedProps;\n","import { Type, TSchema, TObject } from '@sinclair/typebox';\nimport { latestVersion } from '@json-to-office/shared-docx';\nimport type { CustomComponent } from './createComponent';\nimport {\n ReportPropsSchema,\n SectionPropsSchema,\n HeadingPropsSchema,\n ParagraphPropsSchema,\n ListPropsSchema,\n ImagePropsSchema,\n TablePropsSchema,\n} from '@json-to-office/shared-docx';\nimport { generateUnifiedDocumentSchema } from '@json-to-office/shared-docx/schemas/generator';\n\n/**\n * Generate a JSON schema for plugin-enhanced documents at RUNTIME.\n *\n * Iterates each component's versions map to produce per-version\n * CustomComponentInfo entries for the unified schema generator.\n */\nexport function generatePluginDocumentSchema(\n customComponents: CustomComponent<any, any, any>[],\n includeStandardComponents = true\n): TSchema {\n // Produce per-version CustomComponentInfo entries for version-discriminated validation\n const customComponentInfos = customComponents.map((component) => {\n const versionKeys = Object.keys(component.versions);\n\n // Build per-version props entries\n const versionedProps = versionKeys.map((v) => ({\n version: v,\n propsSchema: component.versions[v].propsSchema,\n hasChildren: component.versions[v].hasChildren === true,\n description: component.versions[v].description,\n }));\n\n // propsSchema is used as fallback label — use latest version's props\n const latestKey = versionKeys.reduce((a, b) => (a > b ? a : b));\n\n return {\n name: component.name,\n propsSchema: component.versions[latestKey].propsSchema,\n hasChildren: versionKeys.some(\n (v) => component.versions[v].hasChildren === true\n ),\n versionedProps,\n };\n });\n\n return generateUnifiedDocumentSchema({\n includeStandardComponents: includeStandardComponents,\n includeTheme: true,\n customComponents: customComponentInfos,\n title: 'Plugin Document Definition',\n description: 'Document definition with custom plugin components',\n });\n}\n\n/**\n * Create a union type from an array of schemas\n */\nexport function createUnionSchema(schemas: TSchema[]): TSchema {\n if (schemas.length === 0) {\n return Type.Any();\n }\n if (schemas.length === 1) {\n return schemas[0];\n }\n return Type.Union(schemas as [TSchema, TSchema, ...TSchema[]]);\n}\n\n/**\n * Export a plugin-enhanced JSON schema to a file at RUNTIME\n */\nexport async function exportPluginSchema(\n customComponents: CustomComponent<any, any, any>[],\n outputPath: string,\n options: {\n includeStandardComponents?: boolean;\n prettyPrint?: boolean;\n } = {}\n): Promise<void> {\n const { includeStandardComponents = true, prettyPrint = true } = options;\n\n const { convertToJsonSchema, exportSchemaToFile } = await import(\n '@json-to-office/shared-docx/schemas/export'\n );\n\n const schema = generatePluginDocumentSchema(\n customComponents,\n includeStandardComponents\n );\n\n const jsonSchema = convertToJsonSchema(schema, {\n $schema: 'http://json-schema.org/draft-07/schema#',\n });\n\n await exportSchemaToFile(jsonSchema, outputPath, { prettyPrint });\n}\n\n/**\n * Generate schemas for individual custom components (version-aware).\n * Produces per-version schemas keyed as `name` or `name@version`.\n */\nexport function generateComponentSchemas(\n customComponents: CustomComponent<any, any, any>[]\n): Record<string, TSchema> {\n const schemas: Record<string, TSchema> = {};\n\n for (const component of customComponents) {\n const versionKeys = Object.keys(component.versions);\n const latest = latestVersion(versionKeys);\n\n for (const v of versionKeys) {\n const entry = component.versions[v];\n const schemaObj = entry.propsSchema as TObject;\n const properties = schemaObj.properties || {};\n\n const componentSchemaProps: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n version: Type.Optional(Type.Literal(v)),\n id: Type.Optional(Type.String()),\n ...properties,\n };\n\n if (entry.hasChildren) {\n componentSchemaProps.children = Type.Optional(Type.Array(Type.Any()));\n }\n\n schemas[`${component.name}@${v}`] = Type.Object(componentSchemaProps);\n }\n\n // Also add a \"default\" entry keyed by name (uses latest)\n const latestEntry = component.versions[latest];\n const schemaObj = latestEntry.propsSchema as TObject;\n const properties = schemaObj.properties || {};\n\n const componentSchemaProps: Record<string, TSchema> = {\n name: Type.Literal(component.name),\n id: Type.Optional(Type.String()),\n ...properties,\n };\n\n if (latestEntry.hasChildren) {\n componentSchemaProps.children = Type.Optional(Type.Array(Type.Any()));\n }\n\n schemas[component.name] = Type.Object(componentSchemaProps);\n }\n\n return schemas;\n}\n\n/**\n * Merge custom component schemas with standard schemas\n */\nexport function mergeSchemas(\n customComponents: CustomComponent<any, any, any>[],\n standardSchemas?: Record<string, TSchema>\n): Record<string, TSchema> {\n const customSchemas = generateComponentSchemas(customComponents);\n\n if (standardSchemas) {\n return {\n ...standardSchemas,\n ...customSchemas,\n };\n }\n\n const defaultStandardSchemas: Record<string, TSchema> = {\n docx: Type.Object({\n name: Type.Literal('docx'),\n id: Type.Optional(Type.String()),\n props: ReportPropsSchema,\n children: Type.Optional(Type.Array(Type.Any())),\n }),\n section: Type.Object({\n name: Type.Literal('section'),\n id: Type.Optional(Type.String()),\n props: SectionPropsSchema,\n children: Type.Optional(Type.Array(Type.Any())),\n }),\n heading: Type.Object({\n name: Type.Literal('heading'),\n id: Type.Optional(Type.String()),\n props: HeadingPropsSchema,\n }),\n text: Type.Object({\n name: Type.Literal('text'),\n id: Type.Optional(Type.String()),\n props: ParagraphPropsSchema,\n }),\n list: Type.Object({\n name: Type.Literal('list'),\n id: Type.Optional(Type.String()),\n props: ListPropsSchema,\n }),\n image: Type.Object({\n name: Type.Literal('image'),\n id: Type.Optional(Type.String()),\n props: ImagePropsSchema,\n }),\n table: Type.Object({\n name: Type.Literal('table'),\n id: Type.Optional(Type.String()),\n props: TablePropsSchema,\n }),\n };\n\n return {\n ...defaultStandardSchemas,\n ...customSchemas,\n };\n}\n"],"mappings":"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","names":["themes","lineRule","path","fs","path","isValidThemeConfig","path","TWIPS_PER_POINT","createHash","pointsToTwips","TWIPS_PER_POINT","block","border","BorderStyle","BORDER_STYLE","init_styles","coreProperties","AdmZip","BookmarkEnd","BookmarkStart","Paragraph","section","block","init_styles","assertNever","runProperties","inlineChildren","floatingOptions","WRAP_TYPE","paragraphProperties","borders","block","revisionMark","frameOptions","tableFloat","border","sectionChildren","numberingConfig","init_emit","builtIn","runProperties","paragraphProperties","emitStyles","init_styles","init_emit","prepareImages","emitStyles","coreProperties","numberingConfig","noteBodies","collectImagePlacements","floatingOptions","init_emit","init_styles","resolve","registry","resolve","serverUrl","clampVisualDpi","DEFAULT_VISUAL_DPI","source","clampVisualDpi","DEFAULT_VISUAL_DPI","alignment","borders","section","format","border","borders","format","section","text","noProofWords","section","resolve","path","_","pointsToTwips","border","borders","alignment","format","runFormatting","paragraph","createDocxJsRenderer","createOfficeOpenDocxRenderer","section","sectionType","mergeWithDefaults","mergeWithDefaults","section","fs","resolve","isAbsolute","isAbsolute","resolve","fs","resolve","clampVisualDpi","DEFAULT_VISUAL_DPI","clampVisualDpi","DEFAULT_VISUAL_DPI","fs","path","fileURLToPath","path","fs","ComponentValidationError","UnknownPreservedComponentError","Type","schemaObj","properties","componentSchemaProps","Type","ComponentValidationError","UnknownPreservedComponentError","fs","path"]}
|