@json-to-office/core-docx 0.34.0 → 0.35.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/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/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/components/heading.ts","../src/utils/numberingConfig.ts","../src/components/paragraph.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/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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 {\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 await resolveDocumentFonts(document, theme, fonts, warnings);\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 });\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} 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 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 Textbox,\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 } 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 getBaseDir,\n} from '../utils/generationContext';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\nimport { computeSectionOrdinals } from './sectionOrdinals';\nimport { collectTocHeadings } from './collectTocHeadings';\nimport { globalSectionBookmarkRegistry } from './sectionBookmarks';\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\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 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 renderDocumentScoped(structure, layout, options)\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\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() }\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 // Collect TOC entries before rendering so a TOC field can carry cached\n // content for readers that never refresh fields (#174). Same\n // catch-and-degrade discipline as the visual pre-pass: a failure here costs\n // the cached entries, never the document.\n try {\n const tocHeadings = collectTocHeadings(layout.sections);\n if (tocHeadings.length > 0) {\n context.tocHeadings = tocHeadings;\n }\n } catch (error) {\n console.warn(\n '[core-docx] TOC entry 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 = 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 | Textbox)[]> {\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 { resolveFromBaseDir } from './generationContext';\nimport { ImageRun, IFloating } from 'docx';\nimport { parsePercentageStringToFraction } from './widthUtils';\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 * TODO: SVG fallback uses raw SVG as PNG — works in Word 2016+ which renders\n * SVG natively; fallback won't render correctly in older versions.\n */\nexport function createTypedImageRun(opts: {\n type: 'jpg' | 'png' | 'gif' | 'bmp' | 'svg';\n data: Buffer;\n transformation: { width: number; height: number };\n floating?: IFloating;\n}): 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 return new ImageRun({\n type: 'svg',\n ...base,\n fallback: { type: 'png', data: 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';\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","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} 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\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 Tab,\n} from 'docx';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n type PlaceholderContext,\n} from './placeholderProcessor';\nimport { normalizeUnicodeText } from './unicode';\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 * Parse text with hyperlinks and decorators\n * Supports markdown-style links: [link text](url)\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 // Regex to match markdown-style links: [text](url)\n // This regex handles nested brackets in the link text\n const hyperlinkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = hyperlinkRegex.exec(normalizedText)) !== null) {\n // Add any text before the hyperlink\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 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 lastIndex = match.index + match[0].length;\n }\n\n // Add any remaining text after the last hyperlink\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 hyperlinks 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 * 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, Textbox } 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 | Textbox)[]> {\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 | Textbox)[];\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 Bookmark,\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} from '../utils/textParser';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n} from '../utils/placeholderProcessor';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport { getStyleIdForLevel } from '../styles/themeToDocxAdapter';\nimport { globalBookmarkRegistry } 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 // 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 new Bookmark({\n id: options.bookmarkId,\n children: revisionRuns as TextRun[],\n })\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(\n new Bookmark({\n id: options.bookmarkId,\n children: textRuns as TextRun[],\n })\n );\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 // Check if text has decorators (bold/italic markers)\n const hasDecorators = /(\\*\\*\\*|___|(\\*\\*|__)|(\\*|_))/.test(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 new Bookmark({\n id: options.bookmarkId,\n children: revisionRuns as TextRun[],\n })\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 (hasDecorators) {\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 new Bookmark({\n id: options.bookmarkId,\n children: headingTextChildren,\n })\n );\n } else {\n // No bookmark, add text directly\n if (hasDecorators) {\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 });\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 = 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: (string | { text: string; level?: number; revision?: Revision })[],\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 // Create the paragraph with proper numbering reference\n const paragraphChildren: ParagraphChild[] = [\n ...(commentAnchor && index === firstRendered ? commentAnchor.start : []),\n ...textRuns,\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 = 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 = 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 = 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';\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}\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 = { bookmarks: new Map() };\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({ bookmarks: new Map() }, 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 * 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 // Convert to lowercase, replace spaces with hyphens, remove special characters\n const baseId = text\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n .substring(0, 40); // Limit length\n\n // Ensure uniqueness by appending counter if needed\n let id = baseId;\n let attempt = 0;\n while (this.state.bookmarks.has(id) && attempt < 100) {\n id = `${baseId}-${++attempt}`;\n }\n\n return id;\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 * 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 * 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';\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 // 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 * Numbering Configuration Utilities\n * Utilities for creating and managing docx numbering configurations\n */\n\nimport { AlignmentType, convertInchesToTwip, LevelFormat } 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 * 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 * 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 * List Component\n * Standard component for rendering list elements in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isListComponent, ListProps } 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 { resolveColor } from '../styles/utils/colorUtils';\n\n/**\n * Convert simplified format to proper level configurations\n */\nfunction createLevelsFromSimplifiedProps(props: ListProps): 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 * 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 * 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: 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 */\nfunction getMaxLevelFromItems(\n items: (string | { text: string; 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: 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 * 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 // Determine the maximum level needed from items\n const maxLevel = getMaxLevelFromItems(resolvedConfig.items);\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 let levels: ListLevelConfig[];\n\n if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {\n // Use explicit level configurations, filling in missing levels\n levels = fillMissingLevels(\n applyListStart(\n resolvedConfig.levels as ListLevelConfig[],\n resolvedConfig.start\n ),\n maxLevel\n );\n } else {\n // Build from simplified options\n const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);\n levels = fillMissingLevels(baseLevels, maxLevel);\n }\n\n const config: NumberingConfig = {\n reference,\n levels: resolveMarkerFonts(levels, 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} 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 {\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\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 const isInline = !tb.props.floating;\n const childComponents = tb.children || [];\n\n if (isInline) {\n // Inline: use a one-cell table container for multi-paragraph support\n const cellChildren: (Paragraph | Table)[] = [];\n // Create context with current text-box as parent\n const childContext: import('../types').RenderContext = {\n ..._context,\n parent: tb,\n };\n for (const child of childComponents) {\n const rendered = await renderComponent(\n child,\n theme,\n themeName,\n childContext\n );\n cellChildren.push(...rendered);\n }\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\n // If there is at least one table or image child, use a floating one-cell table container\n const cellChildren: (Paragraph | Table)[] = [];\n // Create context with current text-box as parent\n const childContext: import('../types').RenderContext = {\n ..._context,\n parent: tb,\n };\n for (const child of childComponents) {\n const rendered = await renderComponent(\n child,\n theme,\n themeName,\n childContext\n );\n cellChildren.push(...rendered);\n }\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 * 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';\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 entries.push({ title: entry.title, level: entry.level });\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} 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 */\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): 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({ presentation, dpi, baseDir });\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: { presentation, dpi, ...(baseDir !== undefined && { baseDir }) },\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 );\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} 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\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 * 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\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 /** 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 try {\n const result = await rasterizeVisualSlide(\n target.presentation,\n target.dpi,\n undefined,\n serviceConfig,\n options.baseDir\n );\n map.set(target.key, { ok: true, ...result });\n } catch (error) {\n map.set(target.key, { ok: false, error: toErrorMessage(error) });\n }\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 });\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 for (const chunk of chunksOf(unique, MAX_RASTERIZE_BATCH_SLIDES)) {\n let applied = false;\n try {\n const 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 },\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 applied = applyBatchResponse(chunk, await response.json(), map);\n } catch {\n applied = false;\n }\n if (!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 * collectTocHeadings — per-document TOC entry pre-pass (#174).\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\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';\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}\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/**\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 const entries: TocHeadingEntry[] = [];\n const ordinals = computeSectionOrdinals(sections);\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 const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n if (title) {\n const level = typeof props.level === 'number' ? props.level : 1;\n entries.push({ title, level, sectionBookmarkId });\n }\n return;\n }\n\n if (component.name === 'paragraph') {\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 (!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;\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\nimport type {\n FontRuntimeOpts,\n ResolvedFont,\n GenerationWarning,\n} from '@json-to-office/shared';\nimport {\n collectFontNamesFromDocx,\n validateFontReferences,\n FontRegistry,\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): 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 // 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: fonts?.extraEntries,\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) only runs when a consumer\n // is listening via onResolved — typically the LibreOffice preview stager.\n // Office output never embeds bytes, so skipping fetches when nobody cares\n // keeps library callers from paying network cost.\n if (!fonts?.onResolved) return [];\n\n const registry = new FontRegistry({\n opts: fonts,\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. The\n // short-circuit above guarantees we only reach this point when a\n // listener is registered.\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} 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\ninterface FlattenCtx {\n rasterize: PptxRasterizer;\n dpi?: number;\n baseDir?: string;\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 { baseDir: options.baseDir, concurrency: options.concurrency }\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 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 })\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 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 await resolveDocumentFonts(modedDoc, modedTheme, state.fonts, warnings);\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 });\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsIO,SAAS,oBACd,OACiB;AACjB,SAAO;AAAA,IACL,SAAS,MAAM;AAAA,IACf,MAAM,MAAM,QAAQ;AAAA,IACpB,aAAa,MAAM,eAAe;AAAA,IAClC,aAAa,MAAM,eAAe;AAAA,IAClC,SAAS,MAAM,WAAW;AAAA,IAC1B,QAAQ;AAAA,MACN,GAAG;AAAA,MACH,GAAI,MAAM,UAAU,CAAC;AAAA,IACvB;AAAA,IACA,OAAO;AAAA,MACL,SAAS,EAAE,GAAG,cAAc,SAAS,GAAI,MAAM,OAAO,WAAW,CAAC,EAAG;AAAA,MACrE,MAAM,EAAE,GAAG,cAAc,MAAM,GAAI,MAAM,OAAO,QAAQ,CAAC,EAAG;AAAA,MAC5D,MAAM,EAAE,GAAG,cAAc,MAAM,GAAI,MAAM,OAAO,QAAQ,CAAC,EAAG;AAAA,MAC5D,OAAO,EAAE,GAAG,cAAc,OAAO,GAAI,MAAM,OAAO,SAAS,CAAC,EAAG;AAAA,IACjE;AAAA,IACA,MAAM;AAAA,MACJ,GAAG;AAAA,MACH,GAAI,MAAM,QAAQ,CAAC;AAAA,MACnB,SAAS;AAAA,QACP,GAAG,aAAa;AAAA,QAChB,GAAI,MAAM,MAAM,WAAW,CAAC;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,mBAAmB,MAAM;AAAA,EAC3B;AACF;AAuBO,SAAS,eAAe,OAAiC;AAC9D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,UAAU,CAAC;AAAA,EACvB;AACF;AAKO,SAAS,cAAc,OAAiC;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,SAAS,CAAC;AAAA,EACtB;AACF;AAKO,SAAS,eAAe,OAAiC;AAC9D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,UAAU,CAAC;AAAA,EACvB;AACF;AAKO,SAAS,eAAe,OAAiC;AAC9D,QAAM,SAAS,eAAe,KAAK;AACnC,SAAO;AAAA,IACL,GAAG,eAAe;AAAA,IAClB,GAAI,OAAO,UAAU,CAAC;AAAA,EACxB;AACF;AA/NA,IASa,gBAoBA,eAUA,gBA+EA;AAtHb;AAAA;AAAA;AASO,IAAM,iBAAiB;AAAA,MAC5B,SAAS;AAAA,MACT,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,QAAQ;AAAA;AAAA,MAER,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,qBAAqB;AAAA,IACvB;AAKO,IAAM,gBAAgB;AAAA,MAC3B,SAAS,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,MACrC,MAAM,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,MAClC,MAAM,EAAE,QAAQ,eAAe,MAAM,GAAG;AAAA,MACxC,OAAO,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,IACrC;AAKO,IAAM,iBAAiB;AAAA,MAC5B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAKO,IAAM,eAAe;AAAA,MAC1B,MAAM;AAAA,MACN,SAAS;AAAA,QACP,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA;AAAA;;;ACjIA;AAAA;AAAA;AAAA;AAAA,MACE,SAAW;AAAA,MACX,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,YAAc;AAAA,QACd,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW;AAAA,UACT,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,OAAS;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe;AAAA,YACb,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,UACA,WAAa;AAAA,UACb,SAAW;AAAA,YACT,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,QACd;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC5LA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC7C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,MAC7C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACrHA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC/C,MAAQ,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC5C,MAAQ,EAAE,QAAU,SAAS,MAAQ,GAAG;AAAA,QACxC,OAAS,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,MAC/C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,GAAG;AAAA,QAC3B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7GA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC7C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,MAC7C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACxHA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC/C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,MAC/C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,GAAG,OAAS,EAAE;AAAA,UACrC,UAAY;AAAA,QACd;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC3HA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,OAEK;AAmBP,SAAS,qBAAsD;AAC7D,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAGA,QAAMA,UAA0C;AAAA,IAC9C,SAAS,oBAAoB,0BAAmC;AAAA,IAChE,WAAW,oBAAoB,4BAAqC;AAAA,IACpE,QAAQ,oBAAoB,yBAAkC;AAAA,IAC9D,MAAM,oBAAoB,uBAAgC;AAAA,IAC1D,WAAW,oBAAoB,4BAAqC;AAAA,EACtE;AAGA,MAAI;AACF,UAAM,aAAa,cAAc,YAAY,GAAG;AAChD,UAAM,YAAY,KAAK,QAAQ,UAAU;AACzC,UAAM,YAAY,KAAK,KAAK,WAAW,gCAAgC;AAEvE,QAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,YAAM,aAAa,GAChB,YAAY,SAAS,EACrB,OAAO,CAAC,SAAS,KAAK,SAAS,kBAAkB,CAAC,EAClD,IAAI,CAAC,SAAS,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAExD,iBAAW,aAAa,YAAY;AAClC,YAAI,CAACA,QAAO,SAAS,GAAG;AACtB,cAAI;AACF,kBAAM,WAAW,KAAK;AAAA,cACpB;AAAA,cACA,GAAG,SAAS;AAAA,YACd;AACA,kBAAM,UAAU,GAAG,aAAa,UAAU,MAAM;AAChD,kBAAM,cAAc,KAAK,MAAM,OAAO;AAKtC,gBAAI,CAAC,mBAAmB,WAAW,GAAG;AACpC,sBAAQ;AAAA,gBACN,kBAAkB,SAAS;AAAA,cAC7B;AACA;AAAA,YACF;AACA,YAAAA,QAAO,SAAS,IAAI,oBAAoB,WAAW;AAAA,UACrD,SAAS,OAAO;AACd,oBAAQ;AAAA,cACN,mCAAmC,SAAS;AAAA,cAC5C;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAEA,iBAAeA;AACf,SAAOA;AACT;AA3FA,IA4BI,cAiES,QAYA,UAWA,sBAoBA,UAmBA,eAKA,cACA,gBACA;AAlKb;AAAA;AAAA;AAYA;AAOA;AACA;AACA;AACA;AACA;AAKA,IAAI,eAAuD;AAiEpD,IAAM,SAAS,mBAAmB;AAYlC,IAAM,WAAW,CAAC,cAAmD;AAC1E,aAAO,OAAO,SAAS;AAAA,IACzB;AASO,IAAM,uBAAuB,CAClC,WACA,gBAAwB,cACJ;AACpB,YAAM,QAAQ,SAAS,SAAS,KAAK,SAAS,aAAa;AAE3D,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR,yBAAyB,SAAS,qBAAqB,aAAa;AAAA,QACtE;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAOO,IAAM,WAAW,CAAC,cAA+B;AACtD,aAAO,aAAa;AAAA,IACtB;AAiBO,IAAM,gBAAgB,MAAgB;AAC3C,aAAO,OAAO,KAAK,MAAM;AAAA,IAC3B;AAGO,IAAM,eAAe,OAAO,SAAS;AACrC,IAAM,iBAAiB,OAAO,WAAW;AACzC,IAAM,cAAc,OAAO,QAAQ;AAAA;AAAA;;;ACpInC,SAAS,aACd,YACA,OACQ;AAER,MAAI,WAAW,WAAW,GAAG,GAAG;AAC9B,UAAM,WAAW,WAAW,MAAM,CAAC;AACnC,QAAI,mBAAmB,KAAK,QAAQ,GAAG;AACrC,aAAO,SAAS,YAAY;AAAA,IAC9B;AAEA,UAAM,IAAI;AAAA,MACR,uBAAuB,UAAU;AAAA,IACnC;AAAA,EACF;AAIA,QAAM,SAAS,eAAe,KAAK;AACnC,QAAM,gBAAgB,OAAO,UAAuB;AACpD,MAAI,OAAO,kBAAkB,UAAU;AAErC,WAAO,aAAa,eAAe,KAAK;AAAA,EAC1C;AAOA,MAAI,mBAAmB,KAAK,UAAU,GAAG;AACvC,WAAO,WAAW,YAAY;AAAA,EAChC;AAGA,QAAM,IAAI;AAAA,IACR,yBAAyB,UAAU;AAAA,EACrC;AACF;AApEA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACiBO,SAAS,cAAc,QAAwB;AACpD,SAAO,KAAK,MAAM,SAAS,eAAe;AAC5C;AAQO,SAAS,aACd,OACA,WACyB;AAEzB,MAAI,OAAO;AACT,WAAO;AAAA,EACT;AAGA,MAAI,WAAW;AACb,WAAO,SAAS,SAAS;AAAA,EAC3B;AAGA,SAAO,SAAS,SAAS;AAC3B;AAQO,SAAS,kBACd,OACA,SACQ;AAER,MAAI,CAAC,OAAO,OAAO,MAAM,QAAQ;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS;AACZ,WAAO,MAAM,MAAM,KAAK;AAAA,EAC1B;AACA,SAAO,MAAM,MAAM,OAAO,GAAG,UAAU,MAAM,MAAM,KAAK;AAC1D;AAoDO,SAAS,sBACd,OACA,SACgB;AAEhB,QAAM,gBAAgB,WAAW;AAGjC,MAAI,CAAC,OAAO,QAAQ,aAAa,GAAG;AAClC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,MAAM,aAAa;AAEzC,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,aAAa,QAAQ;AAAA,IACrB,SAAS,QAAQ;AAAA,IACjB,kBAAkB,QAAQ;AAAA,IAC1B,OAAO,QAAQ;AAAA,EACjB;AACF;AAUO,SAAS,4BACd,WACA,gBACoB;AAGpB,QAAM,mBAAmB,OAAO,QAAQ,cAAc,EAAE,OAEtD,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM;AACvB,QAAI,UAAU,QAAW;AACvB,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAoCO,SAAS,mBACd,aACgC;AAChC,MAAI,gBAAgB,QAAW;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,gBAAgB,UAAU;AACnC,WAAO;AAAA,MACL,MAAM,KAAK,MAAM,cAAc,yBAAyB;AAAA,MACxD,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,MAAI;AACJ,MAAI;AAEJ,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AACP,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO;AACP,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO,UAAU,SAAY,QAAQ,kBAAkB;AACvD,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO,UAAU,SAAY,QAAQ,kBAAkB;AACvD,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aACE,UAAU,SAAY,QAAQ,4BAA4B;AAC5D,iBAAW;AACX;AAAA,IACF;AACE,aAAO;AAAA,EACX;AAEA,SAAO,EAAE,MAAM,SAAS;AAC1B;AAjQA,IAQM,iBACA,4BACA,2BACA;AAXN;AAAA;AAAA;AAAA;AAEA;AAGA;AAGA,IAAM,kBAAkB;AACxB,IAAM,6BAA6B;AACnC,IAAM,4BAA4B,6BAA6B;AAC/D,IAAM,4BAA4B,4BAA4B;AAAA;AAAA;;;ACX9D,SAAS,mBAAmB;AA8ErB,SAAS,kBACd,MACgB;AAChB,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,WAAW,IAAI;AAAA,EACxB;AACA,SAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAClD;AArFA,IAgCM,8BAyBO,YAoCA,eAmHA,oBAwBA;AAxOb;AAAA;AAAA;AAGA;AACA;AA4BA,IAAM,+BAA+B,CAAC,UAAgC;AACpE,YAAM,cACJ,mBAAmB,OAAO,WAAW,KACrC,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACvC,aAAO;AAAA,QACL,QACE,OAAO,SAAS,WAAW,SACvB,cAAc,MAAM,QAAQ,MAAM,IAClC;AAAA,QACN,OACE,OAAO,SAAS,UAAU,SACtB,cAAc,MAAM,QAAQ,KAAK,IACjC;AAAA,QACN,GAAG;AAAA,MACL;AAAA,IACF;AAUO,IAAM,aAAa;AAAA,MACxB,IAAI,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC3C,IAAI,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC3C,QAAQ,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC/C,OAAO,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,IAChD;AA+BO,IAAM,gBAAgB,CAAC,OAAqB,cAAuB;AACxE,YAAM,cAAc,aAAa,OAAO,SAAS;AAEjD,UAAI,eAAe,YAAY,QAAQ,QAAQ;AAI7C,cAAM,cAAc,YAAY,OAAO;AACvC,cAAM,SAAS,YAAY;AAC3B,eAAO;AAAA,UACL,eAAe,6BAA6B,OAAO,SAAS;AAAA,UAC5D,iBAAiB,6BAA6B,OAAO,WAAW;AAAA,UAChE,aAAa;AAAA,YACX,MAAM;AAAA,cACJ,YAAY,QAAQ,WAAW;AAAA,cAC/B;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,YAAY,QAAQ,qBAAqB;AAAA,cACzC;AAAA,YACF;AAAA;AAAA,YACA,MAAM;AAAA;AAAA,YACN,OAAO,YAAY,QAAQ,MAAM;AAAA;AAAA,YACjC,MAAM,kBAAkB,aAAa,YAAY,IAAI;AAAA,UACvD;AAAA,UACA,WAAW;AAAA,YACT,OAAO,aAAa,YAAY,SAAS,WAAW,WAAW;AAAA,YAC/D,OAAO,YAAY,QAAQ,MAAM;AAAA;AAAA,YACjC,MAAM,kBAAkB,aAAa,YAAY,IAAI;AAAA,UACvD;AAAA,UACA,gBAAgB;AAAA,YACd,MAAM;AAAA,cACJ,YAAY,QAAQ,UAAU;AAAA,cAC9B;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,KAAK;AAAA,cACH,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,QAAQ;AAAA,cACN,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,MAAM;AAAA,cACJ,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,QACL,eAAe,6BAA6B;AAAA,QAC5C,iBAAiB,6BAA6B;AAAA,QAC9C,aAAa;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,WAAW;AAAA,UACT,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,gBAAgB;AAAA,UACd,MAAM;AAAA,QACR;AAAA,QACA,SAAS;AAAA,UACP,KAAK,EAAE,OAAO,YAAY,QAAQ,MAAM,GAAG,OAAO,SAAS;AAAA,UAC3D,QAAQ;AAAA,YACN,OAAO,YAAY;AAAA,YACnB,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,MAAM,EAAE,OAAO,YAAY,QAAQ,MAAM,GAAG,OAAO,SAAS;AAAA,UAC5D,OAAO;AAAA,YACL,OAAO,YAAY;AAAA,YACnB,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAQO,IAAM,qBAAqB,CAAC,OAAqB,cAAuB;AAC7E,YAAM,cAAc,aAAa,OAAO,SAAS;AAEjD,UAAI,aAAa,MAAM,SAAS;AAC9B,eAAO,YAAY,KAAK;AAAA,MAC1B;AAGA,aAAO;AAAA,QACL,KAAK;AAAA;AAAA,QACL,OAAO;AAAA;AAAA,QACP,QAAQ;AAAA;AAAA,QACR,MAAM;AAAA;AAAA,QACN,QAAQ;AAAA;AAAA,QACR,QAAQ;AAAA;AAAA,MACV;AAAA,IACF;AAQO,IAAM,eAAe,CAAC,OAAqB,cAAuB;AACvE,YAAM,cAAc,aAAa,OAAO,SAAS;AACjD,YAAM,iBAAiB,mBAAmB,OAAO,SAAS;AAE1D,UAAI,aAAa,MAAM;AACrB,cAAM,UAAU,YAAY,KAAK,WAAW,CAAC;AAC7C,cAAM,aAAa,kBAAkB,YAAY,KAAK,IAAI;AAC1D,eAAO;AAAA,UACL,MAAM;AAAA,YACJ,OAAO,WAAW;AAAA,YAClB,QAAQ,WAAW;AAAA,YACnB,GAAI,WAAW,SAAS,UAAa,EAAE,MAAM,WAAW,KAAK;AAAA,UAC/D;AAAA,UACA,QAAQ;AAAA,YACN,KAAK,QAAQ,OAAO,eAAe,OAAO;AAAA,YAC1C,OAAO,QAAQ,SAAS,eAAe,SAAS;AAAA,YAChD,QAAQ,QAAQ,UAAU,eAAe,UAAU;AAAA,YACnD,MAAM,QAAQ,QAAQ,eAAe,QAAQ;AAAA,UAC/C;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,OAAO,WAAW,GAAG;AAAA;AAAA,UACrB,QAAQ,WAAW,GAAG;AAAA;AAAA,UACtB,MAAM,WAAW,GAAG;AAAA,QACtB;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,eAAe,OAAO;AAAA,UAC3B,OAAO,eAAe,SAAS;AAAA,UAC/B,QAAQ,eAAe,UAAU;AAAA,UACjC,MAAM,eAAe,QAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACvQA,SAAS,yBAAyB;AALlC,IAUa,sBA+BA,iBAWA;AApDb;AAAA;AAAA;AAOA;AAGO,IAAM,uBAAN,cAAmC,MAAM;AAAA,MAC9C,YAAmB,QAA2B;AAC5C,cAAM,aAAa,OAAO;AAC1B,cAAM,eAAe,OAClB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,UAAU;AACd,gBAAMC,QAAO,MAAM,OACf,MAAM,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAChD;AACJ,gBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,iBAAO,GAAG,OAAO,GAAG,MAAM,OAAO;AAAA,QACnC,CAAC,EACA,KAAK,IAAI;AAEZ;AAAA,UACE,gCAAgC,UAAU,SAAS,aAAa,IAAI,MAAM,EAAE,KAAK,YAAY,GAAG,aAAa,IAAI,QAAQ,EAAE;AAAA,QAC7H;AAfiB;AAgBjB,aAAK,OAAO;AAAA,MACd;AAAA,MAEA,oBAA8B;AAC5B,eAAO,KAAK,OAAO,IAAI,CAAC,UAAU;AAChC,gBAAMA,QAAO,MAAM,OACf,MAAM,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAChD;AACJ,gBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,iBAAO,GAAG,OAAO,GAAG,MAAM,OAAO;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,MACzC,YACE,SACO,OACP;AACA,cAAM,0BAA0B,OAAO,EAAE;AAFlC;AAGP,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAGO,IAAM,cAAN,MAAkB;AAAA,MACN,gBAAgB,OAAO;AAAA;AAAA,MAExC,MAAM,YAAqC;AACzC,YAAI;AAEF,eAAK,cAAc,UAAU;AAG7B,gBAAM,SAAS,kBAAkB,UAAU;AAC3C,cAAI,CAAC,OAAO,OAAO;AACjB,kBAAM,IAAI,qBAAqB,OAAO,UAAU,CAAC,CAAC;AAAA,UACpD;AAEA,gBAAM,YAAY,OAAO;AAGzB,iBAAO,KAAK,cAAc,SAAS;AAAA,QACrC,SAAS,OAAO;AACd,cACE,iBAAiB,wBACjB,iBAAiB,iBACjB;AACA,kBAAM;AAAA,UACR;AACA,gBAAM,IAAI;AAAA,YACR,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAChG,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,cAAc,YAA0B;AAE9C,YAAI,CAAC,YAAY;AACf,gBAAM,IAAI,gBAAgB,qCAAqC;AAAA,QACjE;AAGA,YAAI,OAAO,eAAe,UAAU;AAClC,gBAAM,IAAI,gBAAgB,wBAAwB;AAAA,QACpD;AAGA,YAAI,WAAW,SAAS,KAAK,eAAe;AAC1C,gBAAM,IAAI;AAAA,YACR,0BAA0B,WAAW,MAAM,eAAe,KAAK,aAAa;AAAA,UAC9E;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,cAAc,aAA+C;AAGnE,eAAO,oBAAoB,WAAW;AAAA,MACxC;AAAA;AAAA,MAGA,SAAS,YAA2D;AAClE,YAAI;AACF,eAAK,cAAc,UAAU;AAC7B,gBAAM,SAAS,kBAAkB,UAAU;AAE3C,cAAI,OAAO,OAAO;AAChB,mBAAO,EAAE,OAAO,KAAK;AAAA,UACvB,OAAO;AACL,kBAAM,UAAU,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM;AAC9C,oBAAMA,QAAO,EAAE,OACX,EAAE,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAC5C;AACJ,oBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,qBAAO,GAAG,OAAO,GAAG,EAAE,OAAO;AAAA,YAC/B,CAAC;AACD,mBAAO,EAAE,OAAO,OAAO,OAAO;AAAA,UAChC;AAAA,QACF,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,iBAAiB,QAAQ,MAAM,UAAU;AAAA,YAC3C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACnIA,SAAS,qBAAqB,gCAAgC;AAL9D;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,YAAYC,WAAU;AAC/B,SAAS,iBAAiB;AAD1B,IAMa,gBAaA;AAnBb;AAAA;AAAA;AAGA;AAGO,IAAM,iBAAN,cAA6B,MAAM;AAAA,MACxC,YACE,SACOC,OACA,QACP;AACA,cAAM,WAAWA,QAAO,WAAWA,KAAI,MAAM;AAC7C,cAAM,8BAA8B,OAAO,GAAG,QAAQ,EAAE;AAJjD,oBAAAA;AACA;AAIP,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAGO,IAAM,cAAN,MAAkB;AAAA,MACf,SAAS,IAAI,YAAY;AAAA,MAChB,gBAAgB,KAAK,OAAO;AAAA;AAAA,MAC5B,qBAAqB,CAAC,OAAO;AAAA,MAE9C,MAAM,aAAa,UAA4C;AAC7D,YAAI;AAEF,eAAK,iBAAiB,QAAQ;AAG9B,gBAAM,UAAU,MAAM,KAAK,mBAAmB,QAAQ;AAGtD,iBAAO,KAAK,OAAO,MAAM,OAAO;AAAA,QAClC,SAAS,OAAO;AACd,cAAI,iBAAiB,gBAAgB;AACnC,kBAAM;AAAA,UACR;AAGA,cAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,kBAAM,UAAU;AAChB,gBAAI;AAEJ,oBAAQ,QAAQ,MAAM;AAAA,cACtB,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AAAA,cACL,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF;AACE,0BAAU,sBAAsB,QAAQ,OAAO;AAAA,YACjD;AAEA,kBAAM,IAAI;AAAA,cACR;AAAA,cACA;AAAA,cACA,iBAAiB,QAAQ,QAAQ;AAAA,YACnC;AAAA,UACF;AAGA,gBAAM,IAAI;AAAA,YACR,qBAAqB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC3E;AAAA,YACA,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,MAEA,MAAM,YAAY,MAAwC;AAGxD,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,iBAAiB,UAAwB;AAE/C,YAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,gBAAM,IAAI,eAAe,sCAAsC;AAAA,QACjE;AAGA,cAAM,iBAAiB,UAAU,QAAQ;AAGzC,YAAI,eAAe,SAAS,IAAI,GAAG;AACjC,gBAAM,IAAI,eAAe,sCAAsC,QAAQ;AAAA,QACzE;AAGA,YAAI,eAAe,SAAS,IAAI,GAAG;AACjC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,oBAAoB,KAAK,mBAAmB;AAAA,UAAK,CAAC,QACtD,eAAe,YAAY,EAAE,SAAS,GAAG;AAAA,QAC3C;AAEA,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI;AAAA,YACR,oCAAoC,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAAA,YACtE;AAAA,UACF;AAAA,QACF;AAGA,YAAI,eAAe,SAAS,KAAM;AAChC,gBAAM,IAAI,eAAe,yBAAyB,QAAQ;AAAA,QAC5D;AAAA,MACF;AAAA,MAEA,MAAc,mBAAmB,UAAmC;AAClE,YAAI;AAEF,gBAAM,QAAQ,MAAMD,IAAG,KAAK,QAAQ;AAGpC,cAAI,CAAC,MAAM,OAAO,GAAG;AACnB,kBAAM,IAAI,eAAe,8BAA8B,QAAQ;AAAA,UACjE;AAGA,cAAI,MAAM,OAAO,KAAK,eAAe;AACnC,kBAAM,IAAI;AAAA,cACR,mBAAmB,MAAM,IAAI,eAAe,KAAK,aAAa;AAAA,cAC9D;AAAA,YACF;AAAA,UACF;AAGA,cAAI,MAAM,SAAS,GAAG;AACpB,kBAAM,IAAI,eAAe,iBAAiB,QAAQ;AAAA,UACpD;AAGA,gBAAM,UAAU,MAAMA,IAAG,SAAS,UAAU,MAAM;AAGlD,cAAI,OAAO,YAAY,UAAU;AAC/B,kBAAM,IAAI,eAAe,+BAA+B,QAAQ;AAAA,UAClE;AAEA,iBAAO;AAAA,QACT,SAAS,OAAO;AACd,cAAI,iBAAiB,gBAAgB;AACnC,kBAAM;AAAA,UACR;AAGA,gBAAM,IAAI;AAAA,YACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC9E;AAAA,YACA,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,aAAa,UAAsD;AACjE,YAAI;AACF,eAAK,iBAAiB,QAAQ;AAC9B,iBAAO,EAAE,OAAO,KAAK;AAAA,QACvB,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,OACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,MAAM,YAAY,UAKf;AACD,YAAI;AACF,gBAAM,QAAQ,MAAMA,IAAG,KAAK,QAAQ;AACpC,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,MAAM,MAAM;AAAA,YACZ,QAAQ,MAAM,OAAO;AAAA,UACvB;AAAA,QACF,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjNA;AAAA,EACE;AAAA,EAEA,sBAAAE;AAAA,EAMA;AAAA,OACK;AAyBP,eAAsB,kBACpB,YAC0B;AAC1B,SAAO,YAAY,MAAM,UAAU;AACrC;AAUA,eAAsB,kBACpB,UAC0B;AAC1B,SAAO,YAAY,aAAa,QAAQ;AAC1C;AAQO,SAAS,kBACd,OACA,SAAkB,MACV;AACR,MAAI;AAIF,QAAI,QAAQ;AACV,aAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,IACtC,OAAO;AACL,aAAO,KAAK,UAAU,KAAK;AAAA,IAC7B;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC3F;AAAA,EACF;AACF;AAOO,SAAS,wBAAwB,YAAoB;AAC1D,SAAO,YAAY,SAAS,UAAU;AACxC;AAzFA,IA0BM,aACA;AA3BN;AAAA;AAAA;AAYA;AACA;AAKA;AAIA;AACA;AAGA,IAAM,cAAc,IAAI,YAAY;AACpC,IAAM,cAAc,IAAI,YAAY;AAAA;AAAA;;;AC3BpC;AAAA;AAAA;AAwBA;AAaA;AACA;AASA;AAGA;AAAA;AAAA;;;AClDA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,uBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,QAAM,QAAQ,MAAM,MAAM,SAAS;AACnC,QAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,QAAM,QAAQ,MAAM,QAAQ,SAAS;AACrC,SAAO,KAAK,IAAI,GAAG,QAAQ,OAAO,KAAK;AACzC;AAKO,SAAS,kBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,SAAO,MAAM,MAAM,SAAS;AAC9B;AAKO,SAAS,wBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,QAAM,SAAS,MAAM,MAAM,UAAU;AACrC,QAAM,MAAM,MAAM,QAAQ,OAAO;AACjC,QAAM,SAAS,MAAM,QAAQ,UAAU;AACvC,SAAO,KAAK,IAAI,GAAG,SAAS,MAAM,MAAM;AAC1C;AAKO,SAAS,mBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,SAAO,MAAM,MAAM,UAAU;AAC/B;AAKO,SAAS,gCACd,OACoB;AACpB,QAAM,QAAQ,2BAA2B,KAAK,KAAK;AACnD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAAM,WAAW,MAAM,CAAC,CAAC;AAC/B,MAAI,MAAM,KAAK,MAAM,IAAK,QAAO;AACjC,SAAO,MAAM;AACf;AAMO,SAAS,mBACd,OACA,gBACQ;AACR,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,QAAQ,2BAA2B,KAAK,KAAK;AACnD,MAAI,CAAC,OAAO;AACV,YAAQ;AAAA,MACN,kDAAkD,KAAK;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAO,iBAAiB,WAAW,MAAM,CAAC,CAAC,IAAK,GAAG;AACjE;AAKO,SAAS,sBACd,OACA,qBACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,cAAc,KAAK;AAAA,EAC5B;AACA,QAAM,WAAW,gCAAgC,KAAK;AACtD,MAAI,aAAa,OAAW,QAAO;AACnC,SAAO,KAAK,MAAM,sBAAsB,QAAQ;AAClD;AAnGA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;;;ACFA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAyBA,SAAS,sBACd,KAKA;AACA,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,oBACd,KAKA;AACA,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,mBACd,OACA;AACA,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,iBACd,OACA;AACA,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,YACd,MACA;AACA,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AAEH,aAAO,iBAAiB;AAAA,IAC1B;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,YAAY,MAAmD;AAC7E,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B;AACE,aAAO;AAAA,EACX;AACF;AAMO,SAAS,mBACd,UACA,OACA,WACiB;AACjB,MAAI,CAAC,SAAU,QAAO;AAMtB,MAAI,SAAS,MAAM,SAAS,SAAS;AACnC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,SAAS,oBAAoB;AAC/C,QAAM,YAAY,SAAS,kBAAkB;AAC7C,QAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,QAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AAIzC,QAAM,gBAAgB,QAAQ,SAAS,kBAAkB;AACzD,QAAM,cAAc,QAAQ,SAAS,gBAAgB;AAErD,QAAM,qBAAqB,SAAS,qBAChC;AAAA,IACE,GAAI,SAAS,mBAAmB,YAAY;AAAA,MAC1C,UAAU,sBAAsB,SAAS,mBAAmB,QAAQ;AAAA,IACtE;AAAA,IACA,GAAI,SAAS,mBAAmB,UAAU,UAAa;AAAA,MACrD,OAAO,mBAAmB,SAAS,mBAAmB,KAAK;AAAA,IAC7D;AAAA,IACA,GAAI,SAAS,mBAAmB,WAAW,UAAa;AAAA,MACtD,QACE,mBAAmB,SAAS,mBAAmB,QAAQ,IAAI,IAC3D;AAAA,IACJ;AAAA,EACF,IACA,cACE;AAAA;AAAA,IAEE,UAAU,+BAA+B;AAAA,IACzC,OAAO,wBAAwB;AAAA,EACjC,IACA;AAEN,QAAM,mBAAmB,SAAS,mBAC9B;AAAA,IACE,GAAI,SAAS,iBAAiB,YAAY;AAAA,MACxC,UAAU,oBAAoB,SAAS,iBAAiB,QAAQ;AAAA,IAClE;AAAA,IACA,GAAI,SAAS,iBAAiB,UAAU,UAAa;AAAA,MACnD,OAAO,iBAAiB,SAAS,iBAAiB,KAAK;AAAA,IACzD;AAAA,IACA,GAAI,SAAS,iBAAiB,WAAW,UAAa;AAAA,MACpD,QACE,mBAAmB,SAAS,iBAAiB,QAAQ,IAAI,IACzD;AAAA,IACJ;AAAA,EACF,IACA,gBACE;AAAA;AAAA,IAEE,UAAU,6BAA6B;AAAA,IACvC,OAAO,sBAAsB;AAAA,EAC/B,IACA;AAEN,QAAM,OAAO,SAAS,OAClB;AAAA,IACE,GAAI,SAAS,KAAK,QAAQ,EAAE,MAAM,YAAY,SAAS,KAAK,IAAI,EAAE;AAAA,IAClE,GAAI,SAAS,KAAK,QAAQ,EAAE,MAAM,YAAY,SAAS,KAAK,IAAI,EAAE;AAAA,EACpE,IACA;AAGJ,QAAM,QAAQ,kBAAkB,OAAO,SAAS;AAChD,QAAM,QAAQ,mBAAmB,OAAO,SAAS;AACjD,QAAM,aAAa,SAAS,MAAM,WAAY,SAAiB;AAC/D,QAAM,UAAU,aACZ;AAAA,IACE,GAAI,WAAW,QAAQ,UAAa;AAAA,MAClC,KAAK,mBAAmB,WAAW,KAAK,KAAK,IAAI;AAAA,IACnD;AAAA,IACA,GAAI,WAAW,WAAW,UAAa;AAAA,MACrC,QAAQ,mBAAmB,WAAW,QAAQ,KAAK,IAAI;AAAA,IACzD;AAAA,IACA,GAAI,WAAW,SAAS,UAAa;AAAA,MACnC,MAAM,mBAAmB,WAAW,MAAM,KAAK,IAAI;AAAA,IACrD;AAAA,IACA,GAAI,WAAW,UAAU,UAAa;AAAA,MACpC,OAAO,mBAAmB,WAAW,OAAO,KAAK,IAAI;AAAA,IACvD;AAAA,EACF,IACA;AAQJ,MAAI,SAAS,SAAS,WAAW,SAAY,SAAS,SAAS;AAG/D,MAAI,SAAS,GAAG;AACd,YAAQ;AAAA,MACN,wBAAwB,MAAM;AAAA,IAChC;AACA,aAAS;AAAA,EACX;AAEA,QAAM,SAAc;AAAA,IAClB,GAAI,sBAAsB,EAAE,mBAAmB;AAAA,IAC/C,GAAI,oBAAoB,EAAE,iBAAiB;AAAA,IAC3C,GAAI,QAAQ,EAAE,KAAK;AAAA,IACnB,GAAI,WAAW,EAAE,QAAQ;AAAA,IACzB,GAAI,SAAS,iBAAiB,UAAa;AAAA,MACzC,cAAc,SAAS;AAAA,IACzB;AAAA,IACA,GAAI,SAAS,mBAAmB,UAAa;AAAA,MAC3C,gBAAgB,SAAS;AAAA,IAC3B;AAAA,IACA,GAAI,SAAS,eAAe,UAAa;AAAA,MACvC,YAAY,SAAS;AAAA,IACvB;AAAA,IACA,GAAI,SAAS,iBAAiB,UAAa;AAAA,MACzC,cAAc,SAAS;AAAA,IACzB;AAAA,IACA;AAAA;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,SAAS;AAC/C;AArSA,IA8BM;AA9BN;AAAA;AAAA;AAWA;AAmBA,IAAM,eAAe;AAAA;AAAA;;;ACxBrB,SAAS,qBAAqB;AAC9B,SAAS,SAAS,WAAAC,gBAAe;;;ACkCjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;AClCP,SAAS,iBAAiB,uBAAuB;;;ACnBjD;AAeO,SAAS,oBACd,WACA,UAGI,CAAC,GACQ;AACb,MAAI,CAAC,SAAS,SAAS,GAAG;AACxB,UAAM,YAAY;AAAA,MAChB,GAAG,cAAc;AAAA,MACjB,GAAG,OAAO,KAAK,QAAQ,gBAAgB,CAAC,CAAC;AAAA,IAC3C,EAAE,KAAK;AACP,YAAQ,UAAU,KAAK;AAAA,MACrB,WAAW;AAAA,MACX,SAAS,UAAU,SAAS,6DAA6D,UAAU,KAAK,IAAI,CAAC;AAAA,MAC7G,UAAU;AAAA,MACV,SAAS,EAAE,MAAM,mBAAmB,WAAW,WAAW,UAAU;AAAA,IACtE,CAAC;AAAA,EACH;AAEA,SAAO,qBAAqB,SAAS;AACvC;;;ACjCA,SAAS,kBAAkB;AAkBpB,SAAS,oBACd,OACA,WACa;AACb,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,QAAQ,EAAE,GAAG,MAAM,MAAM;AAC/B,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,UAAU,SAAS,CAAC,CAAC,GAAG;AAC/D,UAAM,MAAM;AACZ,UAAM,GAAG,IAAI,EAAE,GAAG,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI;AAAA,EAC7C;AAEA,QAAM,SAAiC,EAAE,GAAI,MAAM,UAAU,CAAC,EAAG;AACjE,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,UAAU,UAAU,CAAC,CAAC,GAAG;AAChE,WAAO,IAAI,IAAI,EAAE,GAAG,OAAO,IAAI,GAAG,GAAI,IAAe;AAAA,EACvD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,EAAE,GAAG,MAAM,QAAQ,GAAI,UAAU,UAAU,CAAC,EAAG;AAAA,IACvD;AAAA,IACA,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK,EAAE,OAAO;AAAA,EACjD;AACF;AAGO,SAAS,qBAAqB,WAAmC;AACtE,SAAO,WAAW,QAAQ,EACvB,OAAO,KAAK,UAAU,SAAS,CAAC,EAChC,OAAO,KAAK,EACZ,MAAM,GAAG,CAAC;AACf;;;AFDA,SAAS,wBACP,WACA,cACA,UACa;AACb,MAAI,cAAc;AAChB,QAAI,aAAa,SAAS,EAAG,QAAO,aAAa,SAAS;AAC1D,UAAM,iBAAiB,UAAU,YAAY;AAC7C,UAAM,mBAAmB,OAAO,KAAK,YAAY,EAAE;AAAA,MACjD,CAAC,QAAQ,IAAI,YAAY,MAAM;AAAA,IACjC;AACA,QAAI,iBAAkB,QAAO,aAAa,gBAAgB;AAC1D,WAAO,oBAAoB,WAAW,EAAE,cAAc,SAAS,CAAC;AAAA,EAClE;AACA,SAAO,oBAAoB,WAAW,EAAE,SAAS,CAAC;AACpD;AAEO,SAAS,oBACd,YACA,UAA+B,CAAC,GACR;AACxB,QAAM,EAAE,cAAc,OAAO,UAAU,kBAAkB,IAAI;AAY7D,MAAI,WAAW,UAAU,MAAM;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,QAAM,WACJ,WAAW,UAAU,SAAY,EAAE,GAAG,YAAY,OAAO,CAAC,EAAE,IAAI;AAElE,QAAM,oBAAoB,SAAS,MAAM,SAAS;AAClD,QAAM,gBAAgB,qBAAqB;AAC3C,MAAI,QAAQ,oBACR;AAAA,IACE;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,EACxB,IACA,wBAAwB,eAAe,cAAc,QAAQ;AAKjE,QAAM,iBAAiB,SAAS,MAAM;AACtC,MAAI,YAAY;AAChB,MAAI,gBAAgB;AAClB,YAAQ,oBAAoB,OAAO,cAAc;AACjD,gBAAY,GAAG,SAAS,OAAO,qBAAqB,cAAc,CAAC;AAAA,EACrE;AAIA,QAAM,OAAO,gBAAgB,EAAE,KAAK,UAAU,OAAO,MAAM,CAAC;AAC5D,aAAW,KAAK,KAAK,UAAU;AAC7B,QAAI,UAAU;AACZ,eAAS,KAAK;AAAA,QACZ,WAAW;AAAA,QACX,SAAS,EAAE;AAAA,QACX,UAAU;AAAA,QACV,SAAS,EAAE,MAAM,EAAE,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,KAAK,mBAAmB,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,IACxD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA;AAAA;AAAA,IAGZ,WAAW,gBAAgB,WAAW,OAAO,IAAI;AAAA,EACnD;AACF;;;AG3IA,SAAS,cAAc;AAEhB,IAAM,aAAa,CACxB,MACA,eAAuB,mBACZ;AACX,SAAO,OAAO,MAAM,YAAY;AAClC;;;ACoBA,SAAS,yBAAyB;AAgHlC,SAAS,qBAAAC,0BAAyB;AA3G3B,SAAS,qBAAqB,OAAuC;AAC1E,SAAO,MAAM,qBAAqB,CAAC;AACrC;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,2BACd,OACA,OACmC;AACnC,QAAM,WAA8C,CAAC;AAGrD,MAAI,MAAM,QAAQ;AAChB,UAAM,WAAW,UAAU,KAAK;AAOhC,UAAM,eAAe,MAAM,OAAO,QAAQ;AAE1C,QAAI,cAAc,WAAW;AAC3B,eAAS,YAAY,aAAa;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,gBACd,OAC4B;AAC5B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,aAAa,CAAC;AACjC;AAKO,SAAS,iBAAiB,OAA4C;AAC3E,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,SAAS,CAAC;AAC7B;AAKO,SAAS,qBACd,OAC4B;AAC5B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,aAAa,CAAC;AACjC;AAKO,SAAS,iBAAiB,OAA4C;AAC3E,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,SAAS,CAAC;AAC7B;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,gBAAgB,OAA2C;AACzE,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,QAAQ,CAAC;AAC5B;AAQO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,sBACd,OACA,OACgB;AAChB,QAAM,WAAW,gBAAgB,KAAK;AACtC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,kBACd,OACA,OACY;AACZ,QAAM,WAAW,iBAAiB,KAAK;AACvC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,sBACd,OACA,OACgB;AAChB,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,kBACd,OACA,OACY;AACZ,QAAM,WAAW,iBAAiB,KAAK;AACvC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,iBACd,OACA,OACW;AACX,QAAM,WAAW,gBAAgB,KAAK;AACtC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,uBACd,OACA,QACuD;AAEvD,SAAO;AACT;AAOO,SAAS,mBACd,OACA,QACmD;AACnD,SAAO;AACT;AAKO,SAAS,2BACd,OACA,eACyB;AACzB,QAAM,WAAW,qBAAqB,KAAK;AAE3C,SAAS,WAAmB,aAAa,KAAiC,CAAC;AAC7E;AAKO,SAAS,4BACd,OACA,OACA,eACG;AACH,QAAM,WAAW,2BAA2B,OAAO,aAAa;AAChE,SAAO,kBAAkB,OAAO,QAAsB;AACxD;;;ACtPA,SAAS,gCACP,OACA,OACc;AACd,QAAM,WAAW,oBAAoB,OAAO,KAAK;AACjD,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,gBAAgB,2BAA2B,OAAO,KAAK;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IAEH,GAAI,MAAM,YAAY,CAAC,IAAI;AAAA,EAC7B;AACF;AAIA,IAAM,eAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AACV;AAUO,SAAS,yBACd,WACA,OACqB;AACrB,QAAM,QAAQ,UAAU,SAAS,CAAC;AAElC,QAAM,WAAW,aAAa,UAAU,IAAI;AAC5C,QAAM,gBAAgB,WAClB,SAAS,OAAO,KAAK,IACrB;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ;AAEJ,SAAO,EAAE,GAAG,WAAW,OAAO,cAAc;AAC9C;AAMO,SAAS,qBACd,YACA,OACuB;AACvB,SAAO,WAAW,IAAI,CAAC,cAAc;AACnC,UAAM,WAAW,yBAAyB,WAAW,KAAK;AAE1D,UAAM,WAAY,SAAiB;AAGnC,QAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,qBAAqB,UAAU,KAAK;AAAA,MAChD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;;;ACxCA,eAAsB,gBACpB,UACA,OACA,WACA,gBAC4B;AAC5B,QAAM,WAAW,uBAAuB,SAAS,OAAO,cAAc;AAItE,QAAM,cAAc,SAAS,MAAM;AACnC,QAAM,0BAA0B,cAC5BC,mBAAkB,aAAa,MAAM,qBAAqB,CAAC,CAAC,IAC5D;AAMJ,QAAM,kBAAkB,SAAS,MAAM;AACvC,QAAM,qBACJ,mBAAmB,MAAM,eACrB,MAAM;AAAA,IACJ,oBAAI,IAAI,CAAC,GAAI,MAAM,gBAAgB,CAAC,GAAI,GAAI,mBAAmB,CAAC,CAAE,CAAC;AAAA,EACrE,IACA;AAEN,QAAM,iBACJ,2BAA2B,qBACvB;AAAA,IACE,GAAG;AAAA,IACH,GAAI,2BAA2B;AAAA,MAC7B,mBAAmB;AAAA,IACrB;AAAA,IACA,GAAI,sBAAsB,EAAE,cAAc,mBAAmB;AAAA,EAC/D,IACA;AAIN,QAAM,UAAU;AAAA,IACd;AAAA,MACE;AAAA,MACA,UAAU,CAAC;AAAA,MACX,OAAO;AAAA,MACP;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,QAAM,mBAAmB;AAAA,IACvB,SAAS,YAAY,CAAC;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,WAAW,MAAM,gBAAgB,kBAAkB,OAAO;AAEhE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,gBAAgB,SAAS,MAAM;AAAA,IAC/B,UAAU,SAAS,MAAM;AAAA,EAC3B;AACF;AAKO,SAAS,uBACd,OACA,iBAAiB,oBAAI,KAAK,GACR;AAClB,SAAO;AAAA,IACL,OAAO,MAAM,UAAU;AAAA,IACvB,UAAU,MAAM,UAAU;AAAA,IAC1B,aAAa,MAAM,UAAU;AAAA,IAC7B,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,UAAU;AAAA,IACzB,SAAS,MAAM,UAAU;AAAA,IACzB,MAAM,MAAM,UAAU;AAAA,IACtB,MAAM,MAAM,UAAU,OAAO,IAAI,KAAK,MAAM,SAAS,IAAI,IAAI;AAAA,EAC/D;AACF;AAKA,eAAsB,gBACpB,YACA,SAC6B;AAC7B,QAAM,WAA+B,CAAC;AAGtC,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,aAAW,aAAa,kBAAkB;AACxC,QAAI,mBAAmB,SAAS,GAAG;AACjC,YAAM,oBAAoB,MAAM;AAAA,QAC9B,UAAU,YAAY,CAAC;AAAA,QACvB;AAAA,MACF;AAGA,YAAM,kBAAkB,UAAU,OAAO,cAAc;AAEvD,eAAS,KAAK;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ,UAAU,OAAO;AAAA,QACzB,QAAQ,UAAU,OAAO;AAAA,QACzB,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAInB,WAAW;AAAA;AAAA,QAEX,MAAM,UAAU,OAAO;AAAA,MACzB,CAAC;AAAA,IACH,OAAO;AAEL,eAAS,KAAK;AAAA,QACZ,YAAY,CAAC,SAAS;AAAA,QACtB,mBAAmB;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,kBACpB,YACA,SACgC;AAChC,QAAM,YAAmC,CAAC;AAG1C,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,aAAW,aAAa,kBAAkB;AACxC,QAAI,mBAAmB,SAAS,KAAK,UAAU,UAAU;AAEvD,gBAAU,KAAK;AAAA,QACb,GAAG;AAAA,QACH,UAAU,MAAM,kBAAkB,UAAU,UAAU,OAAO;AAAA,MAC/D,CAAC;AAAA,IACH,WAAW,mBAAmB,SAAS,KAAK,UAAU,UAAU;AAE9D,gBAAU,KAAK,GAAI,MAAM,kBAAkB,UAAU,UAAU,OAAO,CAAE;AAAA,IAC1E,OAAO;AAEL,gBAAU,KAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,oBACd,UACA,OACA,WACe;AACf,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,MAAM,UAAU,CAAC;AAAA,MACzB,OAAO,MAAM,QACT,OAAO;AAAA,QACL,OAAO,QAAQ,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC;AAAA,MACrE,IACA,CAAC;AAAA,MACL,SAAS,EAAE,OAAO,KAAK,QAAQ,KAAK,OAAO,KAAK,SAAS,IAAI;AAAA,IAC/D;AAAA,IACA,WAAW;AAAA,IACX,UAAU,SAAS;AAAA,IACnB,SAAS;AAAA,MACP,eAAe;AAAA,MACf,aAAa;AAAA,MACb,YAAY;AAAA,IACd;AAAA,IACA,OAAO;AAAA,MACL,YAAY,CAAC,SAAe,WAAW,IAAI;AAAA,MAC3C,WAAW,CAAC,SAAiB,CAAC,EAAE,KAAK,CAAC;AAAA,MACtC,UAAU,CAAC,UAAkB,EAAE,KAAK;AAAA,IACtC;AAAA,IACA,OAAO;AAAA,EACT;AACF;;;ACzQA,SAAS,aAAa,UAAU,kBAAkB;AAWlD;AAGA;AAkEO,SAAS,YACd,UACA,OACA,WACY;AACZ,QAAM,iBAAkC,CAAC;AAEzC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,eAAe,oBAAoB,QAAQ,UAAU;AAG3D,UAAM,sBAAsB,QAAQ,QAAQ,iBAAiB;AAI7D,QAAI,aAAa,WAAW,MAAM,QAAQ,UAAU,QAAQ,SAAS;AACnE,YAAM,iBAAiB,MAAM;AAC7B,YAAM,cAAc,kBAAkB,QAAQ,QAAQ,SAAS;AAC/D,YAAM,cAAc,cAAc,aAAa;AAE/C,qBAAe,KAAK;AAAA,QAClB,YAAY;AAAA,UACV,kBAAkB,QAAQ;AAAA,UAC1B;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,QACA,YAAY,CAAC;AAAA,QACb,YAAY;AAAA,QACZ;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,QAChB,eAAe;AAAA,QACf,sBAAsB;AAAA,QACtB,cAAc,QAAQ;AAAA,MACxB,CAAC;AACD;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,YAAM,QAAQ,aAAa,CAAC;AAG5B,YAAM,uBACJ,MAAM,WAAW,WAAW,KAC5B,mBAAmB,MAAM,WAAW,CAAC,CAAC;AAExC,YAAM,iBAAiB,uBACnB,+BAA+B,MAAM,WAAW,CAAC,GAAG,OAAO,SAAS,IACpE,kBAAkB,MAAM,MAAM;AAGlC,YAAM,iBAAiB,MAAM,KAAK,MAAM;AAExC,YAAM,wBAAwB,QAAQ,QAAQ,aAAa,MAAM,CAAC;AAClE,YAAM,cACJ,MAAM,eAAe,kBAAkB;AACzC,YAAM,cAAc,cAAc,aAAa;AAG/C,YAAM,oBAAoB,uBACtB;AAAA,QAEI,MAAM,WAAW,CAAC,EAGlB,YAAY,CAAC;AAAA,MACjB,IACA,wBAAwB,MAAM,UAAU;AAE5C,qBAAe,KAAK;AAAA,QAClB,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,QACA,YAAY;AAAA,QACZ,YAAY,MAAM;AAAA,QAClB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,QAKhB,eAAe,uBAAuB,MAAM;AAAA,QAC5C,sBAAsB;AAAA;AAAA,QAEtB,cAAc,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,eAAe;AACpC;AAKO,SAAS,oBACd,YACe;AACf,QAAM,SAAwB,CAAC;AAC/B,MAAI,gBAA2C;AAC/C,MAAI,oBAA2C,CAAC;AAChD,MAAI,YAAY;AAEhB,aAAW,aAAa,YAAY;AAElC,QAAI,mBAAmB,SAAS,GAAG;AACjC,UAAI,kBAAkB,SAAS,GAAG;AAChC,eAAO,KAAK;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,aAAa;AAAA,QACf,CAAC;AACD,4BAAoB,CAAC;AACrB,oBAAY;AAAA,MACd;AAEA,YAAM,gBAAgB,yBAAyB,SAAS;AACxD,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,YAAY,CAAC,SAAS;AAAA,QACtB,aAAa;AAAA,MACf,CAAC;AACD,kBAAY;AACZ;AAAA,IACF;AAEA,UAAM,kBAAkB,yBAAyB,SAAS;AAG1D,QAAI,aAAa,SAAS,GAAG;AAC3B,UAAI,kBAAkB,SAAS,GAAG;AAEhC,eAAO,KAAK;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,aAAa;AAAA,QACf,CAAC;AACD,4BAAoB,CAAC;AACrB,oBAAY;AAAA,MACd;AAEA,0BAAoB,CAAC,SAAS;AAC9B,kBAAY;AACZ;AAAA,IACF;AAGA,QAAI,oBAAoB,iBAAiB,kBAAkB,SAAS,GAAG;AACrE,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,aAAa;AAAA,MACf,CAAC;AACD,sBAAgB;AAChB,0BAAoB,CAAC,SAAS;AAC9B,kBAAY;AAAA,IACd,OAAO;AACL,wBAAkB,KAAK,SAAS;AAAA,IAClC;AAAA,EACF;AAGA,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKO,SAAS,yBACd,WAC2B;AAC3B,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,UAAW,UAAkB,OAAO;AAG1C,QAAI,MAAM,QAAQ,OAAO,GAAG;AAE1B,aAAO,QAAQ,UAAU,IAAI,iBAAiB;AAAA,IAChD;AAGA,WAAO;AAAA,EACT;AAGA,MAAI,cAAc,aAAc,UAAkB,UAAU;AAC1D,UAAM,aAAc,UAAkB,SAAS;AAAA,MAC7C,CAAC,UAA+B,mBAAmB,KAAK;AAAA,IAC1D;AACA,WAAO,aAAa,iBAAiB;AAAA,EACvC;AAEA,SAAO;AACT;AAKO,SAAS,wBACd,YACuB;AACvB,QAAM,YAAmC,CAAC;AAE1C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,YAAY,WAAW,CAAC;AAG9B,QAAI,wBAAwB,GAAG;AAE7B,UAAI,mBAAmB,SAAS,GAAG;AACjC,kBAAU,KAAK;AAAA,UACb,GAAG;AAAA,UACH,OAAO;AAAA,YACL,GAAK,UAAkB,SAAS,CAAC;AAAA,YACjC,aAAa;AAAA,UACf;AAAA,QACF,CAAwB;AAAA,MAC1B,OAAO;AACL,kBAAU,KAAK,SAAS;AAAA,MAC1B;AAAA,IACF,OAAO;AACL,gBAAU,KAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,0BAAmC;AAG1C,SAAO;AACT;AAKA,SAAS,aAAa,WAAyC;AAC7D,MAAI,mBAAmB,SAAS,GAAG;AAEjC,WAAO,UAAU,OAAO,cAAc;AAAA,EACxC;AACA,MAAI,mBAAmB,SAAS,GAAG;AACjC,WAAO,UAAU,MAAM,cAAc;AAAA,EACvC;AACA,MAAI,qBAAqB,SAAS,GAAG;AACnC,WAAO,UAAU,MAAM,cAAc;AAAA,EACvC;AAEA,MAAI,eAAe,SAAS,GAAG;AAC7B,WAAO,UAAU,OAAO,cAAc;AAAA,EACxC;AACA,SAAO;AACT;AAKO,SAAS,kBACd,QACgB;AAChB,UAAQ,QAAQ;AAAA,IACd,KAAK;AAGH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,OAAO;AAAA;AAAA,MACT;AAAA,IACF,KAAK;AAAA,IACL;AACE,aAAO,EAAE,OAAO,EAAE;AAAA,EACtB;AACF;AAKO,SAAS,wBACd,gBACA,OACA,WACA,aACA,cAYuB;AAEvB,QAAM,gBAAgB,aAAa,OAAO,SAAS;AAQnD,QAAM,YAAY,eACd;AAAA,IACE,MAAM,aAAa,OACf,kBAAkB,aAAa,IAAI,IACnC,cAAc;AAAA,IAClB,QAAQ;AAAA,MACN,GAAG,cAAc;AAAA,MACjB,GAAI,aAAa,WAAW,CAAC;AAAA,IAC/B;AAAA,EACF,IACA;AAEJ,QAAM,aAAoC;AAAA,IACxC,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,YAAY,eAAe;AAAA,MAC3B,OAAO,eAAe;AAAA,IACxB;AAAA,EACF;AAGA,MACG,eAAuB,YACxB,MAAM,QAAS,eAAuB,QAAQ,GAC9C;AACA,UAAM,WAAY,eAAuB;AAMzC,eAAW,OAAO,aAAa;AAE/B,WAAO,WAAW,OAAO;AAEzB,eAAW,OAAO,WAAW,SAAS;AAAA,MACpC,CAAC,MACC,IAAI,WAAW;AAAA,QACb,OAAO,EAAE;AAAA,QACT,GAAI,EAAE,UAAU,SAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAAA,MACpD,CAAC;AAAA,IACL;AAAA,EACF;AAEA,MAAI,aAAa;AACf,eAAW,OACT,gBAAgB,eACZ,YAAY,aACZ,YAAY;AAAA,EACpB;AAEA,SAAO;AACT;AAMA,SAAS,+BACP,WACA,OACA,WACgB;AAChB,QAAM,MAAQ,UAAkB,SAAS,CAAC;AAK1C,QAAM,UAAW,IAAI,WAAW,CAAC;AAKjC,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAAG;AACnD,WAAO,EAAE,OAAO,EAAE;AAAA,EACpB;AAEA,QAAM,sBAAsB,uBAAuB,OAAO,SAAS;AAGnE,QAAM,gBAAsD,CAAC;AAC7D,MAAI,oBAAoB;AACxB,MAAI,aAAa;AACjB,QAAM,0BAAoC,CAAC;AAE3C,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,IAAI,QAAQ,CAAC;AACnB,UAAM,QAA4C,CAAC;AAEnD,QAAI,EAAE,UAAU,QAAW;AACzB,YAAM,aAAa,sBAAsB,EAAE,OAAO,mBAAmB;AACrE,UAAI,aAAa,GAAG;AAClB,cAAM,QAAQ;AACd,6BAAqB;AAAA,MACvB;AAAA,IACF,OAAO;AACL,8BAAwB,KAAK,CAAC;AAAA,IAChC;AAEA,QAAI,EAAE,QAAQ,QAAW;AACvB,YAAM,aAAa,sBAAsB,EAAE,KAAK,mBAAmB;AACnE,UAAI,aAAa,GAAG;AAClB,cAAM,QAAQ;AACd,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,kBAAc,KAAK,KAAK;AAAA,EAC1B;AAGA,QAAM,iBAAiB,oBAAoB;AAC3C,QAAM,YAAY;AAClB,QAAM,UAAU,uBAAuB,IAAI;AAC3C,MAAI,iBAAiB,SAAS;AAC5B,UAAM,cAAe,iBAAiB,sBAAuB;AAE7D,UAAM,UAAU,cACb,IAAI,CAAC,GAAG,QAAQ;AACf,YAAM,OAAO,EAAE,SACT,EAAE,QAAQ,sBAAuB,KAAK,QAAQ,CAAC,IAAI,MACrD;AACJ,YAAM,OAAO,EAAE,SACT,EAAE,QAAQ,sBAAuB,KAAK,QAAQ,CAAC,IAAI,MACrD;AACJ,aAAO,cAAc,MAAM,CAAC,WAAW,IAAI,SAAS,IAAI;AAAA,IAC1D,CAAC,EACA,KAAK,IAAI;AACZ,UAAM,aACJ;AACF,UAAM,IAAI;AAAA,MACR,kEAAkE,YAAY,QAAQ,CAAC,CAAC,gBACtF,YAAY,KACZ;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,EAA2B,OAAO;AAAA,cAAiB,UAAU;AAAA,IAChE;AAAA,EACF;AAGA,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,sBAAsB,aAAa;AAAA,EACrC;AACA,MAAI,wBAAwB,SAAS,GAAG;AACtC,UAAM,OAAO,KAAK,MAAM,YAAY,wBAAwB,MAAM;AAClE,eAAW,OAAO,yBAAyB;AACzC,oBAAc,GAAG,EAAE,QAAQ;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;;;ACljBA;AAAA,EACE;AAAA,EACA,aAAAC;AAAA,EAKA,WAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAEK;;;ACjBP,SAAS,oBAAoB;AAC7B,OAAO,WAAW;;;ACDlB,SAAS,yBAAyB;AAClC,SAAS,YAAY,eAAe;AAEpC,IAAM,wBAAwB,IAAI,kBAAwB;AAGnD,SAAS,sBAAyB,MAAY,UAAsB;AACzE,SAAO,sBAAsB,IAAI,MAAM,QAAQ;AACjD;AAGO,SAAS,oBAA0B;AACxC,SAAO,sBAAsB,SAAS,KAAK,oBAAI,KAAK;AACtD;AAEA,IAAM,iBAAiB,IAAI,kBAA0B;AAQ9C,SAAS,eACd,SACA,UACG;AACH,SAAO,YAAY,SACf,SAAS,IACT,eAAe,IAAI,QAAQ,OAAO,GAAG,QAAQ;AACnD;AAGO,SAAS,aAAiC;AAC/C,SAAO,eAAe,SAAS;AACjC;AAOO,SAAS,mBAAmB,UAA0B;AAC3D,QAAM,OAAO,eAAe,SAAS;AACrC,MAAI,CAAC,QAAQ,WAAW,QAAQ,EAAG,QAAO;AAC1C,SAAO,QAAQ,MAAM,QAAQ;AAC/B;;;AD1CA;AADA,SAAS,gBAA2B;AAwB7B,SAAS,gBACd,OACA,kBACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAGA,QAAM,kBAAmB,MAAiB,MAAM,oBAAoB;AACpE,MAAI,iBAAiB;AACnB,UAAM,MAAM,WAAW,gBAAgB,CAAC,CAAC;AACzC,QAAI,MAAM,KAAK,MAAM,KAAK;AACxB,YAAM,IAAI;AAAA,QACR,6BAA6B,KAAK;AAAA,MACpC;AAAA,IACF;AACA,UAAM,WAAW,gCAAgC,KAAe;AAChE,QAAI,aAAa,QAAW;AAC1B,aAAO,KAAK,MAAM,mBAAmB,QAAQ;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,wBAAwB,KAAK;AAAA,EAC/B;AACF;AAOO,SAAS,oBACd,OACA,aACQ;AACR,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,kBAAmB,MAAiB,MAAM,oBAAoB;AACpE,MAAI,iBAAiB;AACnB,UAAM,MAAM,WAAW,gBAAgB,CAAC,CAAC;AACzC,QAAI,MAAM,KAAK,MAAM,KAAK;AACxB,YAAM,IAAI;AAAA,QACR,6BAA6B,KAAK;AAAA,MACpC;AAAA,IACF;AACA,UAAM,WAAW,gCAAgC,KAAe;AAChE,QAAI,aAAa,OAAW,QAAO,KAAK,MAAM,cAAc,QAAQ;AAAA,EACtE;AACA,QAAM,IAAI;AAAA,IACR,4BAA4B,KAAK;AAAA,EACnC;AACF;AAKO,SAAS,WAAW,QAAyB;AAClD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,MAAM;AAC1B,WAAO,IAAI,aAAa,WAAW,IAAI,aAAa;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,cAAc,QAAyB;AACrD,SAAO,kCAAkC,KAAK,MAAM;AACtD;AAOO,SAAS,kBAAkB,SAAyB;AACzD,MAAI;AAEF,UAAM,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC;AACvC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,WAAO,OAAO,KAAK,YAAY,QAAQ;AAAA,EACzC,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;AAOO,SAAS,2BACd,SACoB;AACpB,QAAM,QAAQ,QAAQ,MAAM,wCAAwC;AACpE,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC5B;AAOO,SAAS,6BACdC,OACmD;AACnD,QAAM,YAAYA,MAAK,YAAY,EAAE,MAAM,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC;AACnE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,4BACd,UACmD;AACnD,QAAM,aAAa,SAAS,YAAY;AACxC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,KAAK,EAAG,QAAO;AACtE,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,SAAO;AACT;AASO,SAAS,gBACd,WACA,qBACuC;AAEvC,MAAI,qBAAqB;AACvB,UAAM,mBAAmB,4BAA4B,mBAAmB;AACxE,QAAI,iBAAkB,QAAO;AAAA,EAC/B;AAGA,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,WAAW,2BAA2B,SAAS;AACrD,QAAI,UAAU;AACZ,YAAM,eAAe,4BAA4B,QAAQ;AACzD,UAAI,aAAc,QAAO;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,oBAAoB,6BAA6B,SAAS;AAChE,MAAI,kBAAmB,QAAO;AAG9B,SAAO;AACT;AAOO,SAAS,oBAAoB,MAKvB;AACX,QAAM,OAAO;AAAA,IACX,MAAM,KAAK;AAAA,IACX,gBAAgB,KAAK;AAAA,IACrB,GAAI,KAAK,YAAY,EAAE,UAAU,KAAK,SAAS;AAAA,EACjD;AACA,MAAI,KAAK,SAAS,OAAO;AACvB,WAAO,IAAI,SAAS;AAAA,MAClB,MAAM;AAAA,MACN,GAAG;AAAA,MACH,UAAU,EAAE,MAAM,OAAO,MAAM,KAAK,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO,IAAI,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,KAAK,CAAC;AAClD;AAMA,eAAsB,qBACpB,KAC4B;AAC5B,MAAI;AAEF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,GAAK;AAE5D,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,MACA,UAAU;AAAA;AAAA,IACZ,CAAC;AAED,iBAAa,SAAS;AAEtB,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,kCAAkC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MAC1E;AAAA,IACF;AAEA,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAG5D,UAAM,cAAc,MAAM,SAAS,YAAY;AAG/C,WAAO,EAAE,QAAQ,OAAO,KAAK,WAAW,GAAG,YAAY;AAAA,EACzD,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAE1B,UAAI,MAAM,SAAS,cAAc;AAC/B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,IAAI,MAAM,iCAAiC,GAAG,KAAK,MAAM,OAAO,EAAE;AAAA,IAC1E;AACA,UAAM,IAAI,MAAM,iCAAiC,GAAG,iBAAiB;AAAA,EACvE;AACF;AAUO,SAAS,mBAAmB,OAIZ;AACrB,QAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,EAAE,KAAK,EAAE,SAAS;AAC7C,MAAI,SAAS,MAAM,GAAG,GAAG;AACvB,UAAM,UAAU,OAAO,KAAK,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AACjE,WAAO,6BAA6B,OAAO;AAAA,EAC7C;AAGA,MAAI,SAAS,MAAM,MAAM,EAAG,QAAO,MAAM;AACzC,MAAI,SAAS,MAAM,IAAI,EAAG,QAAO,MAAM;AACvC,SAAO;AACT;AAKA,eAAsB,eACpB,WAC4B;AAE5B,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO,EAAE,QAAQ,kBAAkB,SAAS,EAAE;AAAA,EAChD;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,WAAO,MAAM,qBAAqB,SAAS;AAAA,EAC7C;AAGA,SAAO,EAAE,QAAQ,aAAa,mBAAmB,SAAS,CAAC,EAAE;AAC/D;AAKA,eAAsB,mBACpB,WAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,eAAe,SAAS;AAC9D,UAAM,SAAS,MAAM,KAAK,WAAW;AAErC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,6CAA6C,SAAS,EAAE;AAAA,IAC1E;AAEA,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,uCAAuC,SAAS,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC7G;AAAA,EACF;AACF;AAKO,SAAS,0BACd,eACA,gBACA,aACA,cACsB;AACtB,MAAI,eAAe,cAAc;AAE/B,WAAO,EAAE,OAAO,aAAa,QAAQ,aAAa;AAAA,EACpD;AAEA,QAAM,cAAc,gBAAgB;AAEpC,MAAI,eAAe,CAAC,cAAc;AAEhC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,KAAK,MAAM,cAAc,WAAW;AAAA,IAC9C;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,cAAc;AAEhC,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,eAAe,WAAW;AAAA,MAC5C,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,SAAO,EAAE,OAAO,eAAe,QAAQ,eAAe;AACxD;AAKA,eAAsB,yBACpB,WACA,aACA,cACA,gBAAwB,KACxB,iBAAyB,KACM;AAC/B,MAAI;AACF,UAAM,qBAAqB,MAAM,mBAAmB,SAAS;AAC7D,WAAO;AAAA,MACL,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,eAAe,cAAc;AAC/B,aAAO,EAAE,OAAO,aAAa,QAAQ,aAAa;AAAA,IACpD;AAEA,QAAI,eAAe,CAAC,cAAc;AAEhC,aAAO,EAAE,OAAO,aAAa,QAAQ,KAAK,MAAO,cAAc,IAAK,EAAE,EAAE;AAAA,IAC1E;AAEA,QAAI,CAAC,eAAe,cAAc;AAEhC,aAAO;AAAA,QACL,OAAO,KAAK,MAAO,eAAe,KAAM,CAAC;AAAA,QACzC,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,WAAO,EAAE,OAAO,eAAe,QAAQ,eAAe;AAAA,EACxD;AACF;;;ADrZA;;;AGnBA;AAEA;AACA;AAVA;AAAA,EAIE;AAAA,EACA;AAAA,OACK;AA8EP,SAAS,iBAAiB,MAAiC;AACzD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,IAAI;AACjB;AAKA,SAAS,aACP,OACA,WAC6B;AAC7B,MAAI,CAAC,iBAAiB,SAAS,GAAG;AAChC,YAAQ,KAAK,uBAAuB,SAAS,EAAE;AAC/C,WAAO;AAAA,EACT;AACA,SAAO,MAAM,SAAS,SAAS;AACjC;AAYA,SAAS,0BACP,OACA,WACA,UAAuB,oBAAI,IAAI,GACF;AAE7B,MAAI,QAAQ,IAAI,SAAS,GAAG;AAC1B,YAAQ;AAAA,MACN,0CAA0C,MAAM,KAAK,OAAO,EAAE;AAAA,QAC5D;AAAA,MACF,CAAC,WAAM,SAAS;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAEA,UAAQ,IAAI,SAAS;AAGrB,QAAM,QAAQ,aAAa,OAAO,SAAS;AAC3C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,IACN,IAAI,IAAI,OAAO;AAAA;AAAA,EACjB;AAEA,MAAI,CAAC,WAAW;AAEd,WAAO;AAAA,EACT;AAIA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AAIA,MAAI,MAAM,YAAY,UAAa,UAAU,YAAY,QAAW;AAClE,gBAAY,UAAU,UAAU;AAAA,EAClC,WAAW,MAAM,YAAY,QAAW;AACtC,gBAAY,UAAU,MAAM;AAAA,EAC9B;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB;AACE,aAAO,cAAc;AAAA,EACzB;AACF;AAKA,SAAS,eAAe,SAGtB;AACA,SAAO;AAAA,IACL,QAAQ,SAAS,SAAS,cAAc,QAAQ,MAAM,IAAI;AAAA,IAC1D,OAAO,SAAS,QAAQ,cAAc,QAAQ,KAAK,IAAI;AAAA,EACzD;AACF;AAKA,SAAS,qBACP,QACA,OACA,cACA,aAC4B;AAC5B,SAAO;AAAA,IACL,MAAM,OAAO,UAAU;AAAA,IACvB,OAAO,OAAO,QAAQ,eAAe,MAAM;AAAA,IAC3C,OAAO;AAAA,MACL,OAAO,SAAS,gBAAgB,MAAM,OAAO;AAAA,MAC7C;AAAA,IACF;AAAA,IACA,GAAI,OAAO,SAAS,UAAa,EAAE,MAAM,OAAO,KAAK;AAAA,IACrD,GAAI,OAAO,WAAW,UAAa,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC3D,GAAI,OAAO,cAAc,UACvB,OAAO,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,IACtD,GAAI,OAAO,oBAAoB;AAAA,MAC7B,kBACE,OAAO,iBAAiB,SAAS,cAC7B,CAAC,OAAO,iBAAiB,QACzB,OAAO,iBAAiB;AAAA,IAChC;AAAA,IACA,GAAI,OAAO,SAAS,EAAE,OAAO,OAAO,MAAM;AAAA,EAC5C;AACF;AAKA,SAAS,2BACP,QACA,YACA,OACkC;AAClC,SAAO;AAAA,IACL,SAAS;AAAA,MACP,GAAG,eAAe,OAAO,OAAO;AAAA,MAChC,GAAG,mBAAmB,OAAO,WAAW;AAAA,IAC1C;AAAA,IACA,WAAW,iBAAiB,OAAO,aAAa,MAAM;AAAA,IACtD,GAAI,YAAY,aAAa,UAAa;AAAA,MACxC,UAAU,WAAW;AAAA,IACvB;AAAA,IACA,GAAI,YAAY,sBAAsB,UAAa;AAAA,MACjD,WAAW,WAAW;AAAA,IACxB;AAAA,IACA,GAAI,YAAY,iBAAiB,UAAa;AAAA,MAC5C,cAAc,WAAW;AAAA,IAC3B;AAAA,IACA,GAAI,YAAY,iBAAiB,UAAa;AAAA,MAC5C,cAAc,WAAW;AAAA,IAC3B;AAAA,IACA,GAAI,YAAY,WACd,SAAS;AAAA,MACP,QAAQ,eAAe,WAAW,SAAS,KAAK;AAAA,IAClD;AAAA,IACF,GAAI,YAAY,UAAU;AAAA,MACxB,QAAQ;AAAA,QACN,GAAI,WAAW,OAAO,SAAS,UAAa;AAAA,UAC1C,MAAM,WAAW,OAAO;AAAA,QAC1B;AAAA,QACA,GAAI,WAAW,OAAO,YAAY,UAAa;AAAA,UAC7C,SAAS,WAAW,OAAO;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAYA,SAAS,eACP,SACA,OACkE;AAClE,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,UAAU,CAAC,SACf,OACI;AAAA,IACE,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,IACX,OAAO,aAAa,KAAK,OAAO,KAAK;AAAA,IACrC,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,EAC1D,IACA;AAEN,QAAM,QAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAAkE,CAAC;AACzE,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,QAAQ,QAAQ,IAAI,CAAC;AACnC,QAAI,MAAO,WAAU,IAAI,IAAI;AAAA,EAC/B;AAEA,SAAO,OAAO,KAAK,SAAS,EAAE,SAAS,IAAI,YAAY;AACzD;AAiBO,SAAS,iBACd,oBAA0C,WAC1C,UACgB;AAChB,QAAM,QACJ,OAAO,sBAAsB,WACzB,SAAS,iBAAiB,KAAK,SAAS,SAAS,IACjD;AAEN,QAAM,kBAAyC;AAAA;AAAA,IAE7C;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,cACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,cAAM,YAAY,sBAAsB,OAAO,aAAa,IAAI;AAChE,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,aAAa;AAAA,UACnB,OAAO,aAAa;AAAA,UACpB,MAAM,aAAa;AAAA,UACnB,QAAQ,aAAa;AAAA,UACrB,WAAW,aAAa;AAAA,UACxB,kBAAkB,aAAa;AAAA,UAC/B,OAAO,aAAa;AAAA,QACtB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,MAC9D,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,cACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,cAAM,YAAY,sBAAsB,OAAO,aAAa,IAAI;AAChE,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,aAAa;AAAA,UACxB,aAAa,aAAa;AAAA,UAC1B,SAAS,aAAa;AAAA,QACxB,CAAC;AAED,eAAO,2BAA2B,QAAQ,aAAa,KAAK;AAAA,MAC9D,GAAG;AAAA,IACL;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAM,aAAa,UAAU,CAAC;AAC9B,UAAM,kBAAkB,MAAM,SAAS,UAAU;AAIjD,QAAI,iBAAiB;AACnB,YAAM,eACJ,0BAA0B,OAAO,UAAU,KAAK;AAClD,sBAAgB,KAAK;AAAA,QACnB,IAAI,UAAU,CAAC;AAAA,QACf,MAAM,WAAW,CAAC;AAAA,QAClB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,aAAa;AAAA,YACnB,OAAO,aAAa;AAAA,YACpB,MAAM,aAAa;AAAA,YACnB,QAAQ,aAAa;AAAA,YACrB,WAAW,aAAa;AAAA,YACxB,kBAAkB,aAAa;AAAA,YAC/B,OAAO,aAAa;AAAA,UACtB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,QACrE,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,aAAa;AAAA,YACxB,aAAa,aAAa;AAAA,YAC1B,SAAS,aAAa;AAAA,UACxB,CAAC;AAED,iBAAO,2BAA2B,QAAQ,cAAc,KAAK;AAAA,QAC/D,GAAG;AAAA,MACL,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,sBAAgB,KAAK;AAAA,QACnB,IAAI,UAAU,CAAC;AAAA,QACf,MAAM,WAAW,CAAC;AAAA,QAClB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,UAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,UAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,UACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,QAC3D;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ,OAAO,IAAI,KAAK;AAAA,YACxB,OAAO,OAAO,IAAI,KAAK;AAAA,YACvB,GAAG,mBAAmB,UAAU,WAAW;AAAA,UAC7C;AAAA,UACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAM,aAAa,UAAU,CAAC;AAC9B,UAAM,kBAAkB,MAAM,SAAS,UAAU;AAIjD,QAAI,iBAAiB;AACnB,YAAM,eACJ,0BAA0B,OAAO,UAAU,CAAC,EAAE,KAAK;AAErD,sBAAgB,KAAK;AAAA,QACnB,IAAI,kBAAkB,CAAC;AAAA,QACvB,MAAM,gBAAgB,CAAC;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,aAAa;AAAA,YACnB,OAAO,aAAa;AAAA,YACpB,MAAM,aAAa;AAAA,YACnB,QAAQ,aAAa;AAAA,YACrB,WAAW,aAAa;AAAA,YACxB,kBAAkB,aAAa;AAAA,YAC/B,OAAO,aAAa;AAAA,UACtB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,QACrE,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,aAAa;AAAA,YACxB,aAAa,aAAa;AAAA,YAC1B,SAAS,aAAa;AAAA,UACxB,CAAC;AAGD,iBAAO;AAAA,YACL;AAAA,YACA,EAAE,GAAI,cAAsB,cAAc,OAAU;AAAA,YACpD;AAAA,UACF;AAAA,QACF,GAAG;AAAA,MACL,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,sBAAgB,KAAK;AAAA,QACnB,IAAI,kBAAkB,CAAC;AAAA,QACvB,MAAM,gBAAgB,CAAC;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,UAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,UAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,UACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,QAC3D;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ,OAAO,IAAI,KAAK;AAAA,YACxB,OAAO,OAAO,IAAI,KAAK;AAAA,YACvB,GAAG,mBAAmB,UAAU,WAAW;AAAA,UAC7C;AAAA,UACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,OAAO;AACvB,UAAM,aACJ,0BAA0B,OAAO,OAAO,KAAK,MAAM,OAAO;AAC5D,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,WAAW;AAAA,UACjB,OAAO,WAAW;AAAA,UAClB,MAAM,WAAW;AAAA,UACjB,QAAQ,WAAW;AAAA,UACnB,WAAW,WAAW;AAAA,UACtB,kBAAkB,WAAW;AAAA,UAC7B,OAAO,WAAW;AAAA,QACpB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,MACrE,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,WAAW;AAAA,UACtB,aAAa,WAAW;AAAA,UACxB,SAAS,WAAW;AAAA,QACtB,CAAC;AAED,eAAO,2BAA2B,QAAQ,YAAY,KAAK;AAAA,MAC7D,GAAG;AAAA,IACL,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM,UAAU,UAAU;AAAA,QAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,QAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,QAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,QAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,MAC3D;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,OAAO;AAAA,UACP,GAAG,mBAAmB,UAAU,WAAW;AAAA,QAC7C;AAAA,QACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAGA,MAAI,MAAM,QAAQ,UAAU;AAC1B,UAAM,gBACJ,0BAA0B,OAAO,UAAU,KAAK,MAAM,OAAO;AAC/D,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,cAAc,QAAQ;AAAA,QACxB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,cAAc;AAAA,UACpB,OAAO,cAAc;AAAA,UACrB,MAAM,cAAc;AAAA,UACpB,QAAQ,cAAc;AAAA,UACtB,WAAW,cAAc;AAAA,UACzB,kBAAkB,cAAc;AAAA,UAChC,OAAO,cAAc;AAAA,QACvB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS;AAAA,MACnE,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,cAAc,QAAQ;AAAA,QACxB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,cAAc;AAAA,UACzB,aAAa,cAAc;AAAA,UAC3B,SAAS,cAAc;AAAA,QACzB,CAAC;AAED,eAAO,2BAA2B,QAAQ,eAAe,KAAK;AAAA,MAChE,GAAG;AAAA,IACL,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM,UAAU,UAAU;AAAA,QAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,QAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,QACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,QAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,MAC3D;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,OAAO;AAAA,UACP,GAAG,mBAAmB,UAAU,WAAW;AAAA,QAC7C;AAAA,QACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAEA,kBAAgB;AAAA;AAAA,KAEb,MAAM;AACL,YAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,MAAM;AAAA;AAAA,UACN,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,UACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACnE;AAAA,QACA,WAAW;AAAA,UACT,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,GAAG;AAAA;AAAA,KAGF,MAAM;AACL,YAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,MAAM;AAAA;AAAA,UACN,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,UACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACnE;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ;AAAA,UACV;AAAA,UACA,WAAW;AAAA;AAAA,QAEb;AAAA,MACF;AAAA,IACF,GAAG;AAAA,EACL;AAGA,QAAM,sBAAsB,oBAAI,IAAI;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,MAAM,QAAQ;AAChB,eAAW,CAAC,UAAU,UAAU,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AAEjE,UAAI,oBAAoB,IAAI,QAAQ,GAAG;AACrC;AAAA,MACF;AAGA,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAIA,YAAM,WAAW,eAAe,KAAK,QAAQ;AAI7C,YAAM,cAAc,WAChB,aACA,0BAA0B,OAAO,QAAQ,KAAK;AAKlD,YAAM,UAAU,WAAW,MAAM,SAAS,CAAC,CAAC,KAAK;AACjD,YAAM,YAAY,WACd,OAAO,SAAS,CAAC,CAAC,KAClB,SAAS,QAAQ,YAAY,KAAK,EAAE,KAAK;AAG7C,YAAM,iBAAiB,CAAC,SAAkB;AACxC,YAAI,CAAC,KAAM,QAAO;AAClB,cAAM,QAAQ,KAAK,YAAY;AAC/B,YAAI,UAAU,SAAU,QAAO;AAC/B,YAAI,UAAU,QAAS,QAAO;AAC9B,YAAI,UAAU,WAAY,QAAO;AACjC,cAAM,IAAI,MAAM,MAAM,kBAAkB;AACxC,YAAI,EAAG,QAAO,UAAU,EAAE,CAAC,CAAC;AAE5B,eAAO;AAAA,MACT;AAEA,sBAAgB,KAAK;AAAA,QACnB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,WACL,WACA,eAAgB,YAAgC,SAAS;AAAA,QAC7D,MAAM,YAAY,kBAAkB;AAAA,QACpC,aAAa,WACT,QACA,YAAY,aAAa,SACvB,OACA;AAAA,QACN,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,YAAY,QAAQ;AAAA,UACtB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,YAAY;AAAA,YAClB,OAAO,YAAY;AAAA,YACnB,MAAM,YAAY;AAAA,YAClB,QAAQ,YAAY;AAAA,YACpB,WAAW,YAAY;AAAA,YACvB,kBAAkB,YAAY;AAAA,YAC9B,OAAO,YAAY;AAAA,UACrB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,QAC9D,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,YAAY,QAAQ;AAAA,UACtB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,YAAY;AAAA,YACvB,aAAa,YAAY;AAAA,YACzB,SAAS,YAAY;AAAA,UACvB,CAAC;AAGD,gBAAM,YAAY;AAAA,YAChB;AAAA;AAAA,YAEA,WACI,EAAE,GAAG,aAAa,cAAc,OAAU,IAC1C;AAAA,YACJ;AAAA,UACF;AAGA,gBAAM,WAAY,YAAoB;AACtC,gBAAM,qBAAqB,WACvB,CAAC,EAAE,MAAM,SAAS,UAAU,OAAO,QAAQ,OAAO,CAAC,IACnD;AACJ,gBAAM,oBACJ,YAAY,SAAS,SAAS,IAAI,WAAW;AAE/C,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,GAAI,qBAAqB;AAAA,cACvB,UAAU,kBAAkB,IAAI,CAAC,QAAa;AAAA,gBAC5C,MAAM,GAAG;AAAA,gBACT,UACE,GAAG,aAAa,QAAQ,gBAAgB,MAAM,IAAI,GAAG;AAAA,gBACvD,GAAI,GAAG,UAAU,EAAE,QAAQ,GAAG,OAAO;AAAA,cACvC,EAAE;AAAA,YACJ;AAAA,UACF;AAAA,QACF,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AAIA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAE3B,QACE,MAAM,UACN,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,MAAM,CAAC,EAAE,GAC5D;AACA;AAAA,IACF;AAEA,oBAAgB,KAAK;AAAA;AAAA,MAEnB,IAAI,MAAM,CAAC;AAAA,MACX,MAAM,OAAO,CAAC;AAAA,MACd,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM;AAAA,QACN,MAAM;AAAA;AAAA,QACN,OAAO,aAAa,MAAM,OAAO,MAAM,KAAK;AAAA,MAC9C;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,GAAG,eAAe,EAAE,QAAQ,GAAG,OAAO,EAAE,CAAC;AAAA;AAAA,QAC3C;AAAA,QACA,WAAW,iBAAiB,MAAM;AAAA;AAAA,QAElC,QAAQ,EAAE,OAAO,IAAI,KAAK,IAAI;AAAA;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH;AAOA,QAAM,YACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,QAAM,UAAU;AAAA,IACd,4BAA4B,sBAAsB,OAAO,WAAW,IAAI,GAAG;AAAA,MACzE,MAAM,WAAW;AAAA,MACjB,OAAO,WAAW;AAAA,IACpB,CAAC;AAAA,IACD;AAAA,IACA,MAAM,OAAO;AAAA,EACf;AAIA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,GAAI,OAAO,QAAQ,SAAS,YAAY;AAAA,MACtC,MAAM,KAAK,IAAI,IAAI,QAAQ,OAAO,CAAC;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA;AAAA,IACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAKP,GAAI,YAAY;AAAA,QACd,UAAU;AAAA,UACR,KAAK;AAAA,YACH,UAAU,EAAE,OAAO,SAAS;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAIA,cAAc,EAAE,KAAK,QAAQ;AAAA,MAC7B,mBAAmB,EAAE,KAAK,EAAE,GAAG,SAAS,aAAa,KAAK,EAAE;AAAA,MAC5D,aAAa,EAAE,KAAK,QAAQ;AAAA,MAC5B,kBAAkB,EAAE,KAAK,EAAE,GAAG,SAAS,aAAa,KAAK,EAAE;AAAA,IAC7D;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,OAAuB;AACxD,QAAM,WAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACA,SAAO,SAAS,KAAK,KAAK;AAC5B;;;AH54BA;AACA;;;AIpDA;AAAA;AAAA;AAAA;AAKA;AAAA,4BAAc;;;ACAd,SAAS,cAAAC,mBAAkB;AAOpB,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EAEjB,YAAY,UAAkB,OAAO;AACnC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,YACE,WACA,SACA,UAA2B,CAAC,GACpB;AACR,UAAM,QAAkB;AAAA,MACtB,KAAK;AAAA,MACL,UAAU;AAAA,MACV,KAAK,UAAU,UAAU,KAAK;AAAA,IAChC;AAEA,QAAI,QAAQ,iBAAiB,OAAO;AAClC,YAAM,KAAK,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,YAAM,KAAK,KAAK,YAAY,OAAO,CAAC;AAAA,IACtC;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,YAAM,KAAK,GAAG,QAAQ,cAAc;AAAA,IACtC;AAEA,QAAI,QAAQ,SAAS;AACnB,YAAM,KAAK,QAAQ,OAAO;AAAA,IAC5B;AAEA,WAAO,MAAM,KAAK,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,OAAoB;AAC5B,QAAI,CAAC,MAAO,QAAO;AAGnB,UAAM,aAAa,KAAK,gBAAgB,KAAK;AAC7C,UAAM,OAAO,KAAK,UAAU,UAAU;AAEtC,WAAO,KAAK,KAAK,IAAI;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,SAAgC;AAElD,UAAM,WAAW;AAAA,MACf,OAAO,QAAQ,MAAM;AAAA,MACrB,UAAU,QAAQ;AAAA;AAAA,IAEpB;AAEA,WAAO,KAAK,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,KAAe;AACrC,QAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAE9C,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI,IAAI,CAAC,SAAS,KAAK,gBAAgB,IAAI,CAAC;AAAA,IACrD;AAEA,QAAI,eAAe,MAAM;AACvB,aAAO,IAAI,YAAY;AAAA,IACzB;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,SAAc,CAAC;AACrB,YAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AAEnC,iBAAW,OAAO,MAAM;AACtB,eAAO,GAAG,IAAI,KAAK,gBAAgB,IAAI,GAAG,CAAC;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,KAAK,OAAuB;AAClC,WAAOA,YAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,EAAE;AAAA,EACzE;AACF;;;AC1GA,SAAS,WAAAC,UAAS,iBAAiB,sBAAsB;;;ACHlD,SAAS,qBAAqB,MAAyC;AAC5E,UAAQ,QAAQ,IAAI,UAAU,KAAK;AACrC;;;ACDA;AAAA,EACE,WAAAC;AAAA,EACA;AAAA,OAKK;;;ACZP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4EP,IAAM,wBAAwB;AAE9B,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAQO,SAAS,uBAAuB,cAAwC;AAC7E,QAAM,SAAS,gBAAgB,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC;AACzE,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,UAAU,MACb,MAAM,EACN,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAClC,IAAI,YAAY;AACnB,SAAO,IAAI;AAAA,IACT,yBAAyB,QAAQ,KAAK,GAAG,CAAC;AAAA,IAC1C;AAAA,EACF;AACF;AAOO,SAAS,oBACd,MACA,SACA,cACW;AACX,QAAM,QAAQ,uBAAuB,YAAY;AACjD,MAAI,CAAC,SAAS,CAAC,KAAM,QAAO,CAAC,QAAQ,MAAM,KAAK,CAAC;AAEjD,QAAM,OAAkB,CAAC;AACzB,MAAI,YAAY;AAChB,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,QAAI,MAAM,QAAQ,WAAW;AAC3B,WAAK,KAAK,QAAQ,KAAK,MAAM,WAAW,MAAM,KAAK,GAAG,KAAK,CAAC;AAAA,IAC9D;AACA,SAAK,KAAK,QAAQ,MAAM,CAAC,GAAG,IAAI,CAAC;AACjC,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAEnC,QAAI,MAAM,cAAc,MAAM,MAAO,OAAM;AAAA,EAC7C;AACA,MAAI,YAAY,KAAK,QAAQ;AAC3B,SAAK,KAAK,QAAQ,KAAK,MAAM,SAAS,GAAG,KAAK,CAAC;AAAA,EACjD;AACA,SAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,MAAM,KAAK,CAAC;AACvD;AAiBO,SAAS,wBACd,MACA,YAAuB,CAAC,GACxB,UAAgC,CAAC,GACb;AAEpB,MAAI,CAAC,MAAM;AACT,WAAO,CAAC,IAAI,QAAQ,EAAE,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC;AAAA,EACjD;AACA,QAAM,iBAAiB,qBAAqB,IAAI;AAGhD,QAAM,kBAAkB,YAAY,KAAK,cAAc;AAEvD,MAAI,iBAAiB;AAEnB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,CAAC;AAAA,MAC/B,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,MAAI,QAAQ,kBAAkB;AAC5B,WAAO,wBAAwB,gBAAgB,WAAW,OAAO;AAAA,EACnE;AAGA,QAAM,OAA2B,CAAC;AAGlC,QAAM,iBACJ;AAEF,MAAI,YAAY;AAChB,MAAI;AAEJ,UAAQ,QAAQ,eAAe,KAAK,cAAc,OAAO,MAAM;AAE7D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,YAAY,eAAe,UAAU,WAAW,MAAM,KAAK;AACjE,UAAI,WAAW;AACb,aAAK,KAAK,GAAG,2BAA2B,WAAW,WAAW,OAAO,CAAC;AAAA,MACxE;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,OAAO,UAAU,QAAQ;AAC7B,QAAI,UAAU,UAAU,WAAW;AAEnC,QAAI,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,OAAO;AAE5C,sBAAgB,MAAM,CAAC;AACvB,aAAO;AACP,gBAAU;AAAA,IACZ,WAAW,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,MAAM;AAEjD,sBAAgB,MAAM,CAAC;AACvB,aAAO;AAAA,IACT,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,KAAK;AAE/C,sBAAgB,MAAM,CAAC;AACvB,gBAAU;AAAA,IACZ,OAAO;AAEL,sBAAgB,MAAM,CAAC;AAAA,IACzB;AAGA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,SAAK,KAAK,GAAG,aAAa;AAE1B,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,WAAK;AAAA,QACH,GAAG,2BAA2B,eAAe,WAAW,OAAO;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,gBAAgB;AACvC,SAAK;AAAA,MACH,GAAG,2BAA2B,gBAAgB,WAAW,OAAO;AAAA,IAClE;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,oBACd,WACA,WACA;AACA,QAAM,OAAO,WAAW,QAAQ,UAAU;AAC1C,QAAM,UAAU,WAAW,WAAW,UAAU;AAChD,SAAO;AAAA,IACL,GAAI,UAAU,QAAQ,EAAE,MAAM,UAAU,KAAK;AAAA,IAC7C,GAAI,UAAU,QAAQ,EAAE,MAAM,UAAU,KAAK;AAAA,IAC7C,GAAI,UAAU,SAAS;AAAA,MACrB,OACE,QAAQ,WAAW,YAAY,UAAU,YAAY,UAAU;AAAA,IACnE;AAAA,IACA,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA,IACjC,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,IACvC,GAAI,UAAU,aAAa,EAAE,WAAW,UAAU,UAAU;AAAA,IAC5D,GAAI,UAAU,SAAS,EAAE,OAAO,UAAU,MAAM;AAAA,IAChD,GAAI,UAAU,oBAAoB;AAAA,MAChC,kBAAkB,UAAU;AAAA,IAC9B;AAAA,IACA,GAAI,UAAU,YAAY,EAAE,UAAU,UAAU,SAAS;AAAA,EAC3D;AACF;AAQA,SAAS,cACP,MACA,aACA,MACW;AACX,QAAM,EAAE,gBAAgB,QAAQ,IAAI;AAGpC,QAAM,kBAAkB,YAAY;AACpC,QAAM,eAAe,kBAAkB,SAAY,KAAK;AAGxD,MAAI,eAAe;AACnB,QAAM,WAAsB,CAAC;AAC7B,QAAM,cAAc,KAAK,MAAM,GAAI;AACnC,cAAY,QAAQ,CAAC,YAAY,aAAa;AAC5C,QAAI,WAAW,GAAG;AAChB,eAAS;AAAA,QACP,IAAI,QAAQ;AAAA,UACV,UAAU,CAAC,IAAI,IAAI,CAAC;AAAA,UACpB,GAAG;AAAA,UACH,GAAI,kBAAkB,gBAAgB,EAAE,OAAO,EAAE;AAAA,QACnD,CAAC;AAAA,MACH;AACA,qBAAe;AAAA,IACjB;AACA,QAAI,CAAC,cAAc,YAAY,SAAS,EAAG;AAC3C,aAAS;AAAA,MACP,GAAG;AAAA,QACD;AAAA,QACA,CAAC,SAAS,YAAY;AACpB,gBAAM,MAAM,IAAI,QAAQ;AAAA,YACtB,MAAM;AAAA,YACN,GAAG;AAAA,YACH,IAAK,WAAW,YAAY,WAAc;AAAA,cACxC,SAAS,WAAW;AAAA,YACtB;AAAA,YACA,GAAI,kBAAkB,gBAAgB,EAAE,OAAO,EAAE;AAAA,UACnD,CAAC;AACD,yBAAe;AACf,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAQO,SAAS,cACd,MACA,aACA,OAAuD,CAAC,GAC7C;AACX,QAAM,OAAkB,CAAC;AACzB,QAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,WAAS,YAAY,GAAG,YAAY,MAAM,QAAQ,aAAa;AAC7D,UAAM,OAAO,MAAM,SAAS;AAC5B,UAAM,iBAAiB,YAAY;AAGnC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK;AAAA,QACH,GAAG,cAAc,MAAM,aAAa,EAAE,gBAAgB,GAAG,KAAK,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,2BACP,MACA,WACA,SACA,eACoB;AACpB,QAAM,OAAO,CAAC,YACZ;AAAA,IACE;AAAA,IACA,oBAAoB,WAAW;AAAA,MAC7B,MAAM,eAAe;AAAA,MACrB,SAAS,eAAe;AAAA,MACxB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,IACD,EAAE,SAAS,UAAU,SAAS,cAAc,QAAQ,aAAa;AAAA,EACnE;AAEF,MAAI,CAAC,QAAQ,QAAS,QAAO,KAAK,IAAI;AACtC,SAAO,iBAAiB,MAAM,QAAQ,SAAS,IAAI;AACrD;AAcA,SAAS,iBACP,MACA,SACA,MACoB;AACpB,QAAM,QAAQ,IAAI,OAAO,sBAAsB,QAAQ,GAAG;AAC1D,QAAM,MAA0B,CAAC;AAEjC,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI;AAEJ,UAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,UAAM,OAAO,QAAQ,MAAM,CAAC,CAAC;AAC7B,QAAI,SAAS,QAAW;AAEtB,iBAAW,KAAK,MAAM,WAAW,MAAM,SAAS;AAChD,kBAAY,MAAM;AAClB;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,KAAK,MAAM,WAAW,MAAM,KAAK;AAC1D,cAAU;AACV,QAAI,OAAQ,KAAI,KAAK,GAAG,KAAK,MAAM,CAAC;AACpC,QAAI;AAAA,MACF,KAAK,UACD,IAAI,oBAAoB,KAAK,EAAE,IAC/B,IAAI,qBAAqB,KAAK,EAAE;AAAA,IACtC;AACA,gBAAY,MAAM;AAAA,EACpB;AAEA,MAAI,IAAI,WAAW,EAAG,QAAO,KAAK,IAAI;AAEtC,QAAM,WAAW,UAAU,KAAK,MAAM,SAAS;AAC/C,MAAI,SAAU,KAAI,KAAK,GAAG,KAAK,QAAQ,CAAC;AACxC,SAAO;AACT;AAMA,SAAS,wBACP,MACA,YAAuB,CAAC,GACxB,UAAgC,CAAC,GACb;AACpB,QAAM,iBAAiB,qBAAqB,IAAI;AAChD,QAAM,OAA2B,CAAC;AAIlC,QAAM,iBAAiB;AAEvB,MAAI,YAAY;AAChB,MAAI;AAEJ,UAAQ,QAAQ,eAAe,KAAK,cAAc,OAAO,MAAM;AAE7D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,YAAY,eAAe,UAAU,WAAW,MAAM,KAAK;AACjE,UAAI,WAAW;AAEb,cAAM,YAAY,wBAAwB,WAAW,WAAW;AAAA,UAC9D,GAAG;AAAA,UACH,kBAAkB;AAAA;AAAA,QACpB,CAAC;AACD,aAAK,KAAK,GAAG,SAAS;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,CAAC;AACxB,UAAM,UAAU,MAAM,CAAC;AAGvB,UAAM,aAAa,QAAQ,WAAW,GAAG;AAGzC,UAAM,eAAe,wBAAwB,UAAU,WAAW;AAAA,MAChE,GAAG;AAAA,MACH,kBAAkB;AAAA;AAAA,IACpB,CAAC;AAGD,QAAI,YAAY;AAEd,YAAM,aAAa,QAAQ,UAAU,CAAC;AACtC,WAAK;AAAA,QACH,IAAI,kBAAkB;AAAA,UACpB,UAAU;AAAA;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,WAAK;AAAA,QACH,IAAI,kBAAkB;AAAA,UACpB,UAAU;AAAA;AAAA,UACV,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAEA,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,YAAM,gBAAgB,wBAAwB,eAAe,WAAW;AAAA,QACtE,GAAG;AAAA,QACH,kBAAkB;AAAA;AAAA,MACpB,CAAC;AACD,WAAK,KAAK,GAAG,aAAa;AAAA,IAC5B;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,gBAAgB;AACvC,WAAO,wBAAwB,gBAAgB,WAAW;AAAA,MACxD,GAAG;AAAA,MACH,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AD3eA,SAAS,sBACP,MACA,SACS;AACT,SAAO,IAAIC,SAAQ;AAAA,IACjB;AAAA,IACA,MAAM,SAAS,OAAO;AAAA,IACtB,MAAM,SAAS,OAAO;AAAA,IACtB,OAAO,SAAS,OAAO;AAAA,IACvB,MAAM,SAAS,OAAO;AAAA,IACtB,SAAS,SAAS,OAAO;AAAA,IACzB,WAAW,SAAS,OAAO;AAAA,IAC3B,UAAU,SAAS,OAAO;AAAA,IAC1B,SAAS,SAAS,OAAO;AAAA,EAC3B,CAAC;AACH;AAEA,SAAS,gBAAgB,SAAoC;AAC3D,SAAO,SAAS,QAAQ,kBAAkB;AAC5C;AAEA,SAAS,QAAQ,MAAoB;AACnC,SAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE;AACvC;AAEA,SAAS,YAAY,MAAoB;AACvC,SAAO,KACJ,YAAY,EACZ,QAAQ,KAAK,GAAG,EAChB,QAAQ,aAAa,GAAG;AAC7B;AAKO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,OAAe,WAAW,oBAAI,IAAgC;AAAA;AAAA;AAAA;AAAA,EAK9D,OAAO,SAAS,MAAc,SAAmC;AAC/D,SAAK,SAAS,IAAI,KAAK,YAAY,GAAG,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI,MAA8C;AACvD,WAAO,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI,MAAuB;AAChC,WAAO,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBAA+B;AACpC,WAAO,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAc;AACnB,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;AA8DO,SAAS,4BACd,MACA,YAAuB,CAAC,GACxB,UAA8B,CAAC,GAC/B,cACoB;AACpB,QAAM,iBAAiB,qBAAqB,IAAI;AAGhD,QAAM,gBACJ;AACF,QAAM,SAA6B,CAAC;AACpC,MAAI,YAAY;AAEhB,MAAI;AACJ,UAAQ,QAAQ,cAAc,KAAK,cAAc,OAAO,MAAM;AAE5D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,aAAa,eAAe,UAAU,WAAW,MAAM,KAAK;AAClE,UAAI,YAAY;AACd,eAAO;AAAA,UACL,GAAGC,4BAA2B,YAAY,WAAW,YAAY;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,CAAC,GAAG;AACZ,YAAM,kBAAkB,MAAM,CAAC;AAC/B,YAAM,UAAU,oBAAoB,IAAI,eAAe;AACvD,UAAI,SAAS;AACX,cAAM,oBAAoB,QAAQ,EAAE,GAAG,SAAS,OAAO,UAAU,CAAC;AAElE,YAAI,MAAM,QAAQ,iBAAiB,GAAG;AACpC,iBAAO,KAAK,GAAG,iBAAiB;AAAA,QAClC,WAAW,OAAO,sBAAsB,UAAU;AAChD,iBAAO;AAAA,YACL,GAAGA;AAAA,cACD;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,iBAAiB;AAAA,QAC/B;AAAA,MACF,OAAO;AAEL,eAAO;AAAA,UACL,GAAGA,4BAA2B,MAAM,CAAC,GAAG,WAAW,YAAY;AAAA,QACjE;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI;AACJ,UAAI,OAAO,UAAU,QAAQ;AAC7B,UAAI,UAAU,UAAU,WAAW;AAEnC,UAAI,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,OAAO;AAE5C,wBAAgB,MAAM,CAAC;AACvB,eAAO;AACP,kBAAU;AAAA,MACZ,WAAW,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,MAAM;AAEjD,wBAAgB,MAAM,CAAC;AACvB,eAAO;AAAA,MACT,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,KAAK;AAE/C,wBAAgB,MAAM,CAAC;AACvB,kBAAU;AAAA,MACZ,OAAO;AAEL,wBAAgB,MAAM,CAAC;AAAA,MACzB;AAGA,YAAM,oBAAoB;AAAA,QACxB;AAAA,QACA;AAAA,UACE,GAAG;AAAA,UACH;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,aAAO,KAAK,GAAG,iBAAiB;AAAA,IAClC;AAEA,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,GAAGA,4BAA2B,eAAe,WAAW,YAAY;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,KAAK,gBAAgB;AACzC,WAAO;AAAA,MACL,GAAGA,4BAA2B,gBAAgB,WAAW,YAAY;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAASA,4BACP,MACA,WACA,cACW;AACX,SAAO,cAAc,MAAM,oBAAoB,SAAS,GAAG;AAAA,IACzD,SAAS,UAAU;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,gCAAsC;AAEpD,sBAAoB,SAAS,QAAQ,CAAC,YAAY;AAChD,WAAO,IAAIC,SAAQ;AAAA,MACjB,UAAU,CAAC,WAAW,OAAO;AAAA,MAC7B,MAAM,SAAS,OAAO;AAAA,MACtB,MAAM,SAAS,OAAO;AAAA,MACtB,OAAO,SAAS,OAAO;AAAA,MACvB,MAAM,SAAS,OAAO;AAAA,MACtB,SAAS,SAAS,OAAO;AAAA,MACzB,WAAW,SAAS,OAAO;AAAA,IAC7B,CAAC;AAAA,EACH,CAAC;AAGD,sBAAoB,SAAS,eAAe,CAAC,YAAY;AACvD,WAAO,IAAIA,SAAQ;AAAA,MACjB,UAAU,CAAC,WAAW,WAAW;AAAA,MACjC,MAAM,SAAS,OAAO;AAAA,MACtB,MAAM,SAAS,OAAO;AAAA,MACtB,OAAO,SAAS,OAAO;AAAA,MACvB,MAAM,SAAS,OAAO;AAAA,MACtB,SAAS,SAAS,OAAO;AAAA,MACzB,WAAW,SAAS,OAAO;AAAA,IAC7B,CAAC;AAAA,EACH,CAAC;AAGD,sBAAoB;AAAA,IAAS;AAAA,IAAQ,CAAC,YACpC,sBAAsB,QAAQ,gBAAgB,OAAO,CAAC,GAAG,OAAO;AAAA,EAClE;AAGA,sBAAoB;AAAA,IAAS;AAAA,IAAY,CAAC,YACxC,sBAAsB,YAAY,gBAAgB,OAAO,CAAC,GAAG,OAAO;AAAA,EACtE;AAGA,sBAAoB;AAAA,IAAS;AAAA,IAAQ,CAAC,YACpC;AAAA,MACE,OAAO,gBAAgB,OAAO,EAAE,eAAe,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AACF;AAGA,8BAA8B;;;AFxV9B,SAAS,qBAAAC,0BAAyB;;;AIGlC,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAGA,SAAS,OAAO,OAAgB,KAAsB;AACpD,SAAO,SAAS,KAAK,KAAK,QAAQ,MAAM,GAAG,CAAC;AAC9C;AAGA,SAAS,kBAAkB,MAAe,KAAsB;AAC9D,MAAI,CAAC,SAAS,IAAI,EAAG,QAAO;AAC5B,MAAI,OAAO,MAAM,GAAG,EAAG,QAAO;AAC9B,QAAM,UAAU,KAAK;AACrB,SACE,SAAS,OAAO,KAAK,uBAAuB,SAA2B,GAAG;AAE9E;AAMO,SAAS,uBACd,WACA,KACS;AACT,QAAM,QAAQ,UAAU;AACxB,MAAI,OAAO;AACT,QAAI,MAAM,GAAG,EAAG,QAAO;AAEvB,UAAM,QAAQ,MAAM;AACpB,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,CAAC,SAAS,OAAO,MAAM,GAAG,CAAC,GAAG;AACnE,aAAO;AAAA,IACT;AAGA,UAAM,OAAO,MAAM;AACnB,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,KAAK,CAAC,QAAQ,OAAO,KAAK,GAAG,CAAC,GAAG;AAC/D,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,MAAM;AACtB,QACE,MAAM,QAAQ,OAAO,KACrB,QAAQ,KAAK,CAAC,WAAW;AACvB,UAAI,CAAC,SAAS,MAAM,EAAG,QAAO;AAC9B,UAAI,kBAAkB,OAAO,QAAQ,GAAG,EAAG,QAAO;AAClD,YAAM,QAAQ,OAAO;AACrB,aACE,MAAM,QAAQ,KAAK,KACnB,MAAM,KAAK,CAAC,SAAS,kBAAkB,MAAM,GAAG,CAAC;AAAA,IAErD,CAAC,GACD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,WAAW,UAAU;AAC3B,MAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,WAAO,SAAS;AAAA,MACd,CAAC,UACC,SAAS,KAAK,KAAK,uBAAuB,OAAyB,GAAG;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AJhEO,IAAM,0BAA0B;AAEhC,IAAM,wBAAwB;AAOrC,IAAM,qBAAN,MAAyB;AAAA,EACf,kBAAkB;AAAA,EACT,SAAS,IAAIC,mBAAuC;AAAA,EAErE,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,EACjD;AAAA,EAEA,OAAe;AACb,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,WAAW;AACjB,aAAO,MAAM;AAAA,IACf;AACA,SAAK,mBAAmB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,UAAU;AAAA,IAClB,OAAO;AACL,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AACF;AAEO,IAAM,2BAA2B,IAAI,mBAAmB;AAI/D,IAAM,sBAAsB;AAQ5B,SAAS,YACP,MACA,SACe;AACf,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,SAAO,MAAM;AAAA,IAAI,CAAC,MAAM,UACtB,QAAQ,UAAU,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,MAAM,MAAM,OAAO,EAAE,CAAC;AAAA,EACjE;AACF;AAYO,SAAS,mBACd,UACA,WACkB;AAClB,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,OAAO,SAAS,QAAQ;AAE9B,QAAM,OAAyB,CAAC;AAChC,aAAW,WAAW,SAAS,UAAU;AACvC,QAAI,CAAC,QAAQ,KAAM;AACnB,UAAM,OAAO,qBAAqB,QAAQ,IAAI;AAE9C,QAAI,QAAQ,SAAS,UAAU;AAC7B,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YACC,IAAI,gBAAgB;AAAA,YAClB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,IAAI,yBAAyB,KAAK;AAAA,YAClC;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,UAAU;AACpC,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YACC,IAAI,eAAe;AAAA,YACjB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,IAAI,yBAAyB,KAAK;AAAA,YAClC;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF,WAAW,oBAAoB,KAAK,IAAI,GAAG;AAEzC,WAAK;AAAA,QACH,GAAG,4BAA4B,MAAM,WAAwB,CAAC,CAAC;AAAA,MACjE;AAAA,IACF,OAAO;AACL,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YAAY,IAAIC,SAAQ,EAAE,GAAG,SAAS,GAAG,UAAU,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,qBAAqB,WAAoC;AACvE,SAAO,uBAAuB,WAAW,UAAU;AACrD;AAgBO,SAAS,mBAAmB,MAGjC;AACA,QAAM,aAAqC;AAAA,IACzC,IAAI,yBAAyB,KAAK;AAAA,IAClC,QAAQ,KAAK,UAAU;AAAA,IACvB,MAAM,KAAK,QAAQ;AAAA,EACrB;AACA,SAAO,KAAK,SAAS,WACjB,EAAE,WAAW,WAAW,IACxB,EAAE,UAAU,WAAW;AAC7B;AAUO,SAAS,qBACd,MACA,MACA,WACkB;AAClB,SAAO;AAAA,IACL;AAAA,MACE,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,UAAU,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACtC;AAAA,IACA;AAAA,EACF;AACF;;;AKzLA,SAAS,cAAAC,mBAAkB;AAG3B,IAAI,iBAAqC;AACzC,IAAI,cAAwC;AA0B5C,IAAM,cAAc,oBAAI,IAGtB;AAEF,SAAS,aAAa,MAAc,QAAqC;AACvE,QAAM,QAAQ,YAAY,IAAI,IAAI;AAClC,MAAI,OAAO;AACT,UAAM;AAAA,EACR,OAAO;AACL,gBAAY,IAAI,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;AAAA,EAC9C;AACF;AAKO,SAAS,0BAAkD;AAChE,SAAO,MAAM,KAAK,YAAY,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO;AAAA,IAC3D;AAAA,IACA,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,EACZ,EAAE;AACJ;AAQA,IAAM,gCAAgC,oBAAI,IAAI,CAAC,QAAQ,aAAa,CAAC;AAS9D,SAAS,6BAA6B,YAA6B;AACxE,QAAM,mBAAmB;AACzB,MAAI;AACJ,UAAQ,QAAQ,iBAAiB,KAAK,UAAU,OAAO,MAAM;AAC3D,UAAM,OAAO,MAAM,CAAC,EAAE,YAAY;AAClC,QAAI,8BAA8B,IAAI,IAAI,EAAG;AAC7C,QAAI,oBAAoB,IAAI,IAAI,EAAG,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAMA,SAAS,gBAAgB,OAA4B;AAEnD,QAAM,cAAc,KAAK,UAAU,KAAK;AACxC,SAAOA,YAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,CAAC;AAC9E;AAKO,SAAS,yBAAyB,OAA2B;AAClE,MAAI,OAAO;AACT,qBAAiB;AAAA,EACnB,WAAW,CAAC,gBAAgB;AAE1B,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA;AAAA,QACT,YAAY;AAAA,QACZ,YAAY;AAAA;AAAA,QACZ,iBAAiB;AAAA;AAAA,MACnB;AAAA,MACA,aAAa;AAAA,QACX,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,eAAe;AAAA,QACf,oBAAoB;AAAA,MACtB;AAAA,IACF;AACA,qBAAiB,IAAI,0BAAY,MAAM;AAAA,EACzC;AAEA,MAAI,CAAC,aAAa;AAChB,kBAAc,IAAI,kBAAkB;AAAA,EACtC;AACF;AAKO,SAAS,oBAAwC;AACtD,SAAO;AACT;AAKA,eAAsB,sBAAqC;AACzD,MAAI,gBAAgB;AAClB,UAAM,eAAe,MAAM;AAAA,EAC7B;AACA,cAAY,MAAM;AACpB;AAoBA,IAAM,6BAA6B,oBAAI,IAAI;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,SAAS,sBACd,WAC8B;AAG9B,MAAI,qBAAqB,SAAS,EAAG,QAAO;AAG5C,MAAI,uBAAuB,WAAW,SAAS,EAAG,QAAO;AACzD,MAAI,QAAQ,UAAW,QAAO;AAC9B,MAAI,2BAA2B,IAAI,UAAU,IAAI,EAAG,QAAO;AAC3D,SAAO;AACT;AAKA,eAAsB,yBACpB,WACA,OACA,WACA,SACA,cAAc,OAC8C;AAC5D,QAAM,eAAe,sBAAsB,SAAS;AAGpD,MAAI,CAAC,gBAAgB;AACnB,6BAAyB;AAAA,EAC3B;AAKA,MAAI,iBAAiB,MAAM;AACzB,iBAAa,UAAU,MAAM,YAAY;AACzC,WAAO,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC7D;AACA,MAAI,CAAC,kBAAkB,eAAe,CAAC,eAAe,UAAU,EAAE,SAAS;AACzE,WAAO,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC7D;AAIA,QAAM,iBAAiB,KAAK,UAAU,UAAU,SAAS,CAAC,CAAC;AAC3D,QAAM,YAAY,gBAAgB,KAAK;AAIvC,QAAM,aAAa,SAAS,UACxB,GAAG,QAAQ,QAAQ,aAAa,IAAI,QAAQ,QAAQ,WAAW,KAC/D;AAIJ,QAAM,aAAa,WAAW,KAAK;AAInC,QAAM,cACJ,cAAc,aAAa,UAAU,WACjC,aAAa,KAAK,UAAU,UAAU,QAAQ,CAAC,KAC/C;AAQN,QAAM,oBAAoB;AAAA,IACxB,iBAAiB;AAAA,EACnB,IACI,kBAAkB,EAAE,YAAY,IAChC;AAEJ,QAAM,WAAW,aAAa,UAAU,IAAI,IAAI,SAAS,IAAI,UAAU,IAAI,iBAAiB,IAAI,UAAU,IAAI,cAAc,GAAG,WAAW;AAG1I,QAAM,SAAS,MAAM,eAAe,IAAI,QAAQ;AAEhD,MAAI,QAAQ;AAGV,WAAO,OAAO;AAAA,EAChB;AAGA,QAAM,kBAAkB,KAAK,IAAI;AACjC,QAAM,WAAW,MAAM,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAE3E,OAAK,IAAI,IAAI;AAGb,QAAM,gBAAgB,KAAK,UAAU,QAAQ,EAAE;AAG/C,QAAM,cAA+B;AAAA,IACnC,QAAQ;AAAA;AAAA,IACR,eAAe,UAAU;AAAA,IACzB,WAAW;AAAA,IACX,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,cAAc,CAAC;AAAA,IACf,WAAW;AAAA,IACX,cAAc,KAAK,IAAI;AAAA,EACzB;AAGA,QAAM,eAAe,IAAI,UAAU,WAAW;AAE9C,SAAO;AACT;AAQA,eAAsB,mBACpB,YAMe;AACf,MACE,CAAC,kBACD,CAAC,eAAe,UAAU,EAAE,YAAY,eACxC;AACA;AAAA,EACF;AAEA,QAAM,kBAAkB,WAAW;AAAA,IACjC,OAAO,EAAE,WAAW,OAAO,WAAW,QAAQ,MAAM;AAClD,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,eAAe;AACnC;AAQO,SAAS,yBAAyB;AACvC,QAAM,qBAAqB,wBAAwB;AACnD,MAAI,CAAC,gBAAgB;AACnB,WAAO,mBAAmB,SAAS,IAAI,EAAE,mBAAmB,IAAI;AAAA,EAClE;AAEA,SAAO,EAAE,GAAG,eAAe,SAAS,GAAG,mBAAmB;AAC5D;;;ACjWA;AAAA,EACE,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP;AACA;;;AC/BA,SAAS,qBAAAC,0BAAyB;AAgB3B,IAAM,mBAAN,MAAuB;AAAA,EACX,WAA0B,EAAE,WAAW,oBAAI,IAAI,EAAE;AAAA,EACjD,SAAS,IAAIA,mBAAiC;AAAA,EAE/D,IAAY,QAAuB;AACjC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,WAAW,oBAAI,IAAI,EAAE,GAAG,QAAQ;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,IAAY,OAAe,MAAoB;AACtD,QAAI,KAAK,MAAM,UAAU,IAAI,EAAE,GAAG;AAChC,cAAQ;AAAA,QACN,0BAA0B,EAAE;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,MAAM,UAAU,IAAI,IAAI,EAAE,IAAI,OAAO,KAAK,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,MAAc,QAAgB,YAAoB;AAE3D,UAAM,SAAS,KACZ,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,eAAe,EAAE,EACzB,UAAU,GAAG,EAAE;AAGlB,QAAI,KAAK;AACT,QAAI,UAAU;AACd,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE,KAAK,UAAU,KAAK;AACpD,WAAK,GAAG,MAAM,IAAI,EAAE,OAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAqB;AAC1B,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAsC;AACxC,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAyB;AACvB,WAAO,MAAM,KAAK,KAAK,MAAM,UAAU,OAAO,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,UAAU,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,eAAmC;AACpD,UAAM,UAAoB,CAAC;AAC3B,eAAW,MAAM,eAAe;AAC9B,UAAI,CAAC,KAAK,OAAO,EAAE,GAAG;AACpB,gBAAQ,KAAK,EAAE;AAAA,MACjB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,yBAAyB,IAAI,iBAAiB;;;ACnG3D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,OACK;;;ACJP,SAAS,WAAW,WAAAC,gBAAe;AAEnC,SAAS,qBAAAC,0BAAyB;AAI3B,IAAM,yBAAyB;AAE/B,IAAM,uBAAuB;AASpC,SAAS,cAA4B;AACnC,SAAO,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,aAAa,MAAM;AACxD;AAMA,SAAS,eAAe,QAAwB;AAC9C,QAAM,WAAW,OACd,MAAM,UAAU,EAChB,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,EACrB,KAAK,EAAE,EACP,YAAY,EACZ,MAAM,GAAG,CAAC;AACb,SAAO,YAAY,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY;AACpD;AAGA,SAAS,eAAe,MAA2B;AACjD,SAAO,qBAAqB,IAAI,EAC7B,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,IAAI,UAAU,EAAE,UAAU,CAAC,IAAIC,SAAQ,EAAE,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7E;AAEA,IAAM,kBAAN,MAAsB;AAAA,EACZ,WAAyB,YAAY;AAAA,EAC5B,SAAS,IAAIC,mBAAgC;AAAA,EAE9D,IAAY,QAAsB;AAChC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,YAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAAS,SAA4B;AACnC,UAAM,QAAQ,KAAK;AACnB,UAAM,WAAW,QAAQ;AACzB,UAAM,SAAS,EAAE,MAAM;AAEvB,UAAM,SAAS,KAAK;AAAA,MAClB,GAAG,KAAK,UAAU,SAAS,MAAM;AAAA,MACjC,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,IAC3C,CAAC;AAED,UAAM,MAAM,CAAC,MAAM;AACnB,eAAW,SAAS,QAAQ,WAAW,CAAC,GAAG;AACzC,YAAM,UAAU,EAAE,MAAM;AACxB,YAAM,SAAS,KAAK;AAAA,QAClB,GAAG,KAAK,UAAU,OAAO,OAAO;AAAA,QAChC,UAAU;AAAA;AAAA,QAEV,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,MAC3C,CAAC;AACD,UAAI,KAAK,OAAO;AAAA,IAClB;AAEA,QAAI,aAAa,OAAW,OAAM,cAAc;AAChD,WAAO;AAAA,EACT;AAAA,EAEQ,UACN,SACA,IACiB;AACjB,UAAM,SAAS,QAAQ,UAAU;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,QAAQ,YAAY,eAAe,MAAM;AAAA,MACnD,MAAM,IAAI,KAAK,QAAQ,QAAQ,oBAAoB;AAAA,MACnD,UAAU,eAAe,QAAQ,IAAI;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAA4B;AAC1B,UAAM,QAAQ,KAAK;AACnB,QACE,MAAM,eACN,CAAC,MAAM,SAAS,KAAK,CAAC,YAAY,QAAQ,aAAa,MAAS,GAChE;AACA,cAAQ;AAAA,QACN;AAAA,MAGF;AAAA,IACF;AACA,WAAO,CAAC,GAAG,MAAM,QAAQ;AAAA,EAC3B;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,UAAU;AAChB,YAAM,SAAS,SAAS;AACxB,YAAM,cAAc;AAAA,IACtB,OAAO;AACL,WAAK,WAAW,YAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,wBAAwB,IAAI,gBAAgB;;;ADrHlD,SAAS,iBACd,SAC2B;AAC3B,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,MAAM,sBAAsB,SAAS,OAAO;AAClD,SAAO,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,kBAAkB,EAAE,CAAC,EAAE;AAClE;AAUO,SAAS,kBAAkB,KAA0C;AAC1E,SAAO,IAAI,QAAQ,CAAC,OAAO;AAAA,IACzB,IAAI,gBAAgB,EAAE;AAAA,IACtB,IAAIC,SAAQ,EAAE,UAAU,CAAC,IAAI,iBAAiB,EAAE,CAAC,EAAE,CAAC;AAAA,EACtD,CAAC;AACH;;;AE3CA,SAAS,aAAAC,YAAW,WAAAC,gBAAe;AACnC,SAAS,qBAAAC,0BAAyB;AAalC,SAASC,eAAyB;AAChC,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AACF;AAGA,SAASC,gBAAe,MAAc,OAA4B;AAChE,SAAO,qBAAqB,IAAI,EAC7B,MAAM,IAAI,EACV;AAAA,IACC,CAAC,SACC,IAAIC,WAAU;AAAA,MACZ;AAAA,MACA,UAAU,CAAC,IAAIC,SAAQ,EAAE,MAAM,KAAK,CAAC,CAAC;AAAA,IACxC,CAAC;AAAA,EACL;AACJ;AAEA,IAAM,eAAN,MAAmB;AAAA,EACT,WAAsBH,aAAY;AAAA,EACzB,SAAS,IAAII,mBAA6B;AAAA,EAE3D,IAAY,QAAmB;AAC7B,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAIJ,aAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,MAAsB;AACrC,UAAM,QAAQ,KAAK;AACnB,UAAM,KAAK,EAAE,MAAM;AACnB,UAAM,UAAU,OAAO,EAAE,CAAC,IAAI;AAAA,MAC5B,UAAUC,gBAAe,MAAM,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,gBAAgB,MAAsB;AACpC,UAAM,QAAQ,KAAK;AACnB,UAAM,KAAK,EAAE,MAAM;AACnB,UAAM,SAAS,OAAO,EAAE,CAAC,IAAI;AAAA,MAC3B,UAAUA,gBAAe,MAAM,aAAa;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAA2B;AACzB,WAAO,EAAE,GAAG,KAAK,MAAM,UAAU;AAAA,EACnC;AAAA;AAAA,EAGA,cAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,MAAM,SAAS;AAAA,EAClC;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,kBAAkB;AACxB,YAAM,iBAAiB;AACvB,iBAAW,OAAO,OAAO,KAAK,MAAM,SAAS,GAAG;AAC9C,eAAO,MAAM,UAAU,GAAG;AAAA,MAC5B;AACA,iBAAW,OAAO,OAAO,KAAK,MAAM,QAAQ,GAAG;AAC7C,eAAO,MAAM,SAAS,GAAG;AAAA,MAC3B;AAAA,IACF,OAAO;AACL,WAAK,WAAWD,aAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,qBAAqB,IAAI,aAAa;;;ACtFnD,SAAS,gBACP,WACA,UAC2B;AAC3B,QAAM,WAAW,oBAAI,IAA0B;AAQ/C,QAAM,UAAU,CAAC,MAAY,YAAqB;AAChD,UAAM,WAAW,SAAS,IAAI,KAAK,EAAE;AACrC,QAAI,UAAU;AACZ,cAAQ;AAAA,QACN,SAAS,YAAY,UACjB,YAAY,KAAK,EAAE,mCACd,UAAU,aAAa,WAAW,+DAEvC,YAAY,KAAK,EAAE;AAAA,MAGzB;AACA;AAAA,IACF;AACA,aAAS,IAAI,KAAK,IAAI,EAAE,MAAM,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpD;AAEA,aAAW,QAAQ,aAAa,CAAC,EAAG,SAAQ,MAAM,KAAK;AACvD,aAAW,QAAQ,YAAY,CAAC,EAAG,SAAQ,MAAM,IAAI;AACrD,SAAO;AACT;AAOO,SAAS,mBACd,WACA,UAC0B;AAC1B,QAAM,WAAW,gBAAgB,WAAW,QAAQ;AACpD,MAAI,SAAS,SAAS,EAAG,QAAO;AAEhC,QAAM,aAAa,oBAAI,IAA8C;AAErE,SAAO;AAAA,IACL,QAAQ,IAAY;AAClB,YAAM,WAAW,WAAW,IAAI,EAAE;AAClC,UAAI,aAAa,OAAW,QAAO;AAEnC,YAAM,OAAO,SAAS,IAAI,EAAE;AAC5B,UAAI,SAAS,QAAW;AAGtB,gBAAQ;AAAA,UACN,kBAAkB,EAAE,iFACkB,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,QAEvE;AACA,eAAO;AAAA,MACT;AAEA,YAAM,WAAW;AAAA,QACf,IAAI,KAAK,UACL,mBAAmB,gBAAgB,KAAK,IAAI,IAC5C,mBAAmB,iBAAiB,KAAK,IAAI;AAAA,QACjD,SAAS,KAAK;AAAA,MAChB;AACA,iBAAW,IAAI,IAAI,QAAQ;AAC3B,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,MAAc;AAC5B,iBAAW,CAAC,IAAI,IAAI,KAAK,UAAU;AACjC,YAAI,WAAW,IAAI,EAAE,EAAG;AACxB,cAAM,OAAO,KAAK,UAAU,YAAY;AACxC,gBAAQ;AAAA,UACN,KAAK,SAAS,KAAK,EAAE,GAAG,IACpB,GAAG,IAAI,KAAK,EAAE,0NAId,GAAG,IAAI,KAAK,EAAE,2CAA2C,EAAE;AAAA,QAEjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AL5DA;AACA,SAAS,4BAA4B;AAQrC;AACA;AAIA;AAeA,SAAS,qBAAqB,MAK2B;AACvD,MAAI,CAAC,KAAK,YAAY;AACpB,WAAO,EAAE,MAAM,QAAW,MAAM,KAAK,MAAM,SAAS,KAAK,OAAO;AAAA,EAClE;AACA,QAAM,SAAS,KAAK,eAAe,KAAK,SAAS,OAAO,MAAM;AAC9D,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,IACL;AAAA,IACA,KAAK,WAAW;AAAA,EAClB;AACA,SAAO,EAAE,MAAM,MAAM,QAAQ,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AACvE;AAMA,SAAS,oBACP,OACA,aACsB;AACtB,QAAM,aAAa,MAAM;AACzB,QAAM,SAAS,CAAC,GAAI,cAAc,CAAC,GAAI,GAAI,eAAe,CAAC,CAAE;AAC7D,SAAO,OAAO,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI;AAC3D;AA2LA,SAAS,iCACP,WACA,UACA,UACM;AACN,QAAM,WAAW,CAAC,GAAI,aAAa,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC3D,MAAI,SAAS,WAAW,EAAG;AAE3B,QAAM,OAAO,SAAS,SAAS,IAAI,CAAC,YAAY,QAAQ,IAAI,EAAE,KAAK,EAAE;AACrE,QAAM,aAAa,SAAS,OAAO,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,EAAE,GAAG,CAAC;AAC3E,UAAQ;AAAA,IACN,sBAAsB,SAAS,MAAM,aAAa,SAC/C,IAAI,CAAC,SAAS,KAAK,EAAE,EACrB,KAAK,IAAI,CAAC,+GAEV,WAAW,SAAS,IACjB,yBAAoB,WACjB,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,GAAG,EAC7B,KAAK,IAAI,CAAC,iCACb,MACJ;AAAA,EACJ;AACF;AAWA,SAAS,cACP,UACA,SACkB;AAClB,QAAM,SAAS,iBAAiB,OAAO;AACvC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,CAAC,GAAG,OAAO,OAAO,GAAG,UAAU,GAAG,kBAAkB,OAAO,GAAG,CAAC;AACxE;AAKO,SAAS,WACd,SACA,OACA,WACA,UAAuB,CAAC,GACb;AACX,QAAM,oBAAoB,qBAAqB,OAAO;AAEtD,QAAM,QAAQ,QAAQ,SAAS;AAG/B,QAAM,UAAe,CAAC;AACtB,MAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,YAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,EACvD;AACA,MAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,YAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,EACrD;AAEA,QAAM,oBAAoB,mBAAyB,QAAQ,WAAW;AACtE,MAAI,mBAAmB;AACrB,YAAQ,OAAO,kBAAkB;AACjC,YAAQ,WAAW,kBAAkB;AAAA,EACvC;AAGA,QAAM,WAA6B,CAAC;AAGpC,MAAI,QAAQ,aAAa;AACvB,aAAS,KAAK,IAAI,YAAY,CAAC;AAAA,EACjC;AAIA,QAAM,gBAAgB,iBAAiB,QAAQ,OAAO;AACtD,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,cAAc,KAAK;AAAA,EACtC;AAMA,QAAM,mBAAmB,QAAQ,cAAc,QAAQ,QAAQ,SAAS;AACxE,QAAM,kBACJ,QAAQ,eACP,mBAAmB,kBAAkB,OAAO,MAAM,IAAI;AACzD,QAAM,WAAW,qBAAqB;AAAA,IACpC,YAAY;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,YAAY,QAAQ;AAAA,EACtB,CAAC;AACD,QAAM,gBAAgB;AAAA;AAAA;AAAA,IAGpB,IAAK,QAAQ,cACV,SAAS,QAAQ,SAAS,SAAS,oBAAqB;AAAA,MACzD,MAAM,SAAS;AAAA,IACjB;AAAA,IACA,GAAI,QAAQ,YAAY,EAAE,MAAM,QAAQ,WAAW,EAAE;AAAA;AAAA,IACrD,GAAI,QAAQ,aAAa;AAAA,MACvB,OAAO,aAAa,QAAQ,WAAW,KAAK;AAAA,IAC9C;AAAA,IACA,GAAI,SAAS,SAAS,UAAa,EAAE,MAAM,SAAS,KAAK;AAAA,IACzD,GAAI,SAAS,YAAY,UAAa,EAAE,SAAS,SAAS,QAAQ;AAAA,IAClE,GAAI,QAAQ,cAAc,UAAa;AAAA,MACrC,WAAW,QAAQ,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC/D;AAAA;AAAA,IAEA,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,MAAM;AAAA;AAAA,IAE5C,GAAI,QAAQ,oBAAoB;AAAA,MAC9B,kBACE,QAAQ,iBAAiB,SAAS,cAC9B,CAAC,QAAQ,iBAAiB,QAC1B,QAAQ,iBAAiB;AAAA,IACjC;AAAA;AAAA;AAAA,IAGA,GAAI,QAAQ,YAAY,EAAE,UAAU,EAAE,OAAO,QAAQ,SAAS,EAAE;AAAA,IAChE,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,EAClE;AAEA,MAAI,QAAQ,UAAU;AAQpB;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,UAAM,eAAe,mBAAmB,QAAQ,UAAU,aAAa;AACvE,QAAI,QAAQ,YAAY;AACtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,eAAS,KAAK,GAAG,YAAY;AAAA,IAC/B;AAAA,EACF,OAAO;AAKL,UAAM,eAAe;AAAA,MACnB,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAGA,UAAM,WAAW,wBAAwB,mBAAmB,eAAe;AAAA,MACzE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,MACJ,kBAAkB;AAAA,MAClB,cAAc,oBAAoB,OAAO,QAAQ,YAAY;AAAA,MAC7D,SAAS,cAAc;AAAA,IACzB,CAAC;AACD,kBAAc,gBAAgB,iBAAiB;AAG/C,QAAI,QAAQ,YAAY;AAEtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAGA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,eAAS,KAAK,GAAG,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,kBAAkB,cAAc,GAAG,CAAC;AAAA,EACvD;AAGA,QAAM,aAAa,CAAC,CAAC,QAAQ;AAC7B,QAAM,eACJ,cAAc,QAAQ,WAClB,gBAAgB,QAAQ,UAAU,OAAO,SAAS,IAClD;AAEN,SAAO,IAAIK,WAAU;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,YAAY,aAAa,QAAQ,SAAS,IAAI;AAAA,IACjE;AAAA,IACA,GAAI,QAAQ,iBAAiB,UAAa;AAAA,MACxC,cAAc,QAAQ;AAAA,IACxB;AAAA,IACA,GAAI,gBAAgB,EAAE,OAAO,aAAa;AAAA,IAC1C,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,IACnE,GAAI,QAAQ,cAAc,UAAa,EAAE,WAAW,QAAQ,UAAU;AAAA,IACtE,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC/C,GAAI,QAAQ,YACV,QAAQ,SAAS,SAAS,KAAK,EAAE,UAAU,QAAQ,SAAS;AAAA,EAChE,CAAC;AACH;AASA,SAAS,gBACP,UACA,OACA,WACK;AACL,QAAM,sBAAsB,SAAS,oBAAoB,WAAW;AACpE,QAAM,oBAAoB,SAAS,kBAAkB,WAAW;AAChE,QAAM,qBAAqB,SAAS,oBAAoB,UAAU;AAClE,QAAM,mBAAmB,SAAS,kBAAkB,UAAU;AAG9D,QAAM,cAAc,uBAAuB;AAG3C,QAAM,aAAa,SAAS,SAAS;AACrC,QAAM,cAAc,SAAS,UAAU;AAEvC,QAAM,cAAmB;AAAA,IACvB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,YAAY,SAAS,oBAAoB,YAAY;AAAA,MACrD,UAAU,SAAS,kBAAkB,YAAY;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,SAAS,MAAM,MAAM;AACvB,gBAAY,OAAO,SAAS,KAAK;AAAA,EACnC;AAGA,MAAI,SAAS,eAAe,QAAW;AACrC,gBAAY,aAAa,SAAS;AAAA,EACpC,WAAY,SAAiB,eAAe,QAAW;AACrD,gBAAY,aAAc,SAAiB;AAAA,EAC7C;AAEA,MAAI,aAAa;AACf,UAAM,OAAO,SAAS,oBAAoB,UAAU;AACpD,UAAM,OAAO,SAAS,kBAAkB,UAAU;AAClD,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU;AACxD,YAAM,YAAY,SAAS,oBAAoB;AAC/C,YAAM,YAAY,SAAS,kBAAkB;AAC7C,YAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,YAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AACzC,UAAI,mBAAmB,MAAM,IAAI;AACjC,UAAI,mBAAmB,MAAM,IAAI;AAAA,IACnC,OAAO;AACL,UAAI;AACJ,UAAI;AAAA,IACN;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,EAAE,GAAG,EAAE;AAAA,MACjB,GAAG;AAAA,IACL;AAAA,EACF;AAGA,QAAM,SAAS,qBACX,SAAS,mBAAoB,QAC7B;AACJ,QAAM,SAAS,mBAAmB,SAAS,iBAAkB,QAAS;AACtE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,EAAE,GAAG,QAAQ,GAAG,OAAO;AAAA,IAClC,GAAG;AAAA,EACL;AACF;AAKO,SAAS,cACd,MACA,OACA,OACA,YACA,UAAuB,CAAC,GACb;AACX,QAAM,iBAAiB,qBAAqB,IAAI;AAChD,QAAM,UAAU,mBAAmB,KAAK;AAIxC,QAAM,UAAe,CAAC;AACtB,MAAI,qBAAqB;AAEzB,MAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,YAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AACrD,yBAAqB;AAAA,EACvB;AACA,MAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,YAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AACnD,yBAAqB;AAAA,EACvB;AAEA,QAAM,oBAAoB,mBAAyB,QAAQ,WAAW;AACtE,MAAI,mBAAmB;AACrB,YAAQ,OAAO,kBAAkB;AACjC,YAAQ,WAAW,kBAAkB;AACrC,yBAAqB;AAAA,EACvB;AAGA,QAAM,WAAkB,CAAC;AAGzB,MAAI,QAAQ,iBAAiB;AAC3B,aAAS,KAAK,GAAG,QAAQ,eAAe;AAAA,EAC1C;AAGA,MAAI,QAAQ,aAAa;AACvB,aAAS,KAAK,IAAI,YAAY,CAAC;AAAA,EACjC;AAGA,QAAM,gBAAgB,iBAAiB,QAAQ,OAAO;AACtD,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,cAAc,KAAK;AAAA,EACtC;AAGA,QAAM,gBAAgB,gCAAgC,KAAK,cAAc;AAIzE,QAAM,0BACJ,QAAQ,cAAc,QAAQ,QAAQ,SAAS;AACjD,QAAM,yBACJ,QAAQ,eACP,0BAA0B,kBAAkB,OAAO,SAAS,IAAI;AACnE,QAAM,kBAAkB,qBAAqB;AAAA,IAC3C,YAAY;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,YAAY,QAAQ;AAAA,EACtB,CAAC;AAED,QAAM,gBAAgB;AAAA,IACpB,IAAK,QAAQ,cACV,gBAAgB,QACf,gBAAgB,SAAS,2BAA4B;AAAA,MACvD,MAAM,gBAAgB;AAAA,IACxB;AAAA,IACA,GAAI,QAAQ,YAAY,EAAE,MAAM,QAAQ,WAAW,EAAE;AAAA;AAAA,IACrD,GAAI,QAAQ,aAAa,EAAE,OAAO,aAAa,QAAQ,WAAW,KAAK,EAAE;AAAA,IACzE,GAAI,gBAAgB,SAAS,UAAa,EAAE,MAAM,gBAAgB,KAAK;AAAA,IACvE,GAAI,gBAAgB,YAAY,UAAa;AAAA,MAC3C,SAAS,gBAAgB;AAAA,IAC3B;AAAA,IACA,GAAI,QAAQ,cAAc,UAAa;AAAA,MACrC,WAAW,QAAQ,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC/D;AAAA;AAAA,IAEA,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,MAAM;AAAA;AAAA,IAE5C,GAAI,QAAQ,oBAAoB;AAAA,MAC9B,kBACE,QAAQ,iBAAiB,SAAS,cAC9B,CAAC,QAAQ,iBAAiB,QAC1B,QAAQ,iBAAiB;AAAA,IACjC;AAAA;AAAA,IAEA,GAAI,QAAQ,YAAY,EAAE,UAAU,EAAE,OAAO,QAAQ,SAAS,EAAE;AAAA,IAChE,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,EAClE;AAKA,QAAM,sBAAsB,oBAAoB,OAAO,QAAQ,YAAY;AAC3E,QAAM,kBAAkB,CAAC,UACvB;AAAA,IACE;AAAA,IACA,CAAC,SAAS,YACR,IAAIC,SAAQ;AAAA,MACV,MAAM;AAAA,MACN,GAAG;AAAA,MACH,GAAI,WAAW,EAAE,SAAS,KAAK;AAAA,IACjC,CAAC;AAAA,IACH;AAAA,EACF;AAEF,MAAI,QAAQ,UAAU;AAGpB,UAAM,eAAe,mBAAmB,QAAQ,UAAU,aAAa;AACvE,QAAI,QAAQ,YAAY;AACtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,eAAS,KAAK,GAAG,YAAY;AAAA,IAC/B;AAAA,EACF,WAAW,QAAQ,YAAY;AAE7B,2BAAuB;AAAA,MACrB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAGA,UAAM,sBAAyC,CAAC;AAEhD,QAAI,eAAe;AAEjB,YAAM,WAAW,wBAAwB,gBAAgB,eAAe;AAAA,QACtE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,QACJ,kBAAkB;AAAA,QAClB,cAAc;AAAA,MAChB,CAAC;AACD,0BAAoB,KAAK,GAAG,QAAQ;AAAA,IACtC,OAAO;AAEL,0BAAoB,KAAK,GAAG,gBAAgB,cAAc,CAAC;AAAA,IAC7D;AAGA,aAAS;AAAA,MACP,IAAI,SAAS;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AAEL,QAAI,eAAe;AAEjB,YAAM,WAAW,wBAAwB,gBAAgB,eAAe;AAAA,QACtE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,QACJ,kBAAkB;AAAA,QAClB,cAAc;AAAA,MAChB,CAAC;AACD,eAAS,KAAK,GAAG,QAAQ;AAAA,IAC3B,OAAO;AAEL,eAAS,KAAK,GAAG,gBAAgB,cAAc,CAAC;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,kBAAkB,cAAc,GAAG,CAAC;AAAA,EACvD;AAEA,SAAO,IAAID,WAAU;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,IACP,WAAW,aAAa,QAAQ,aAAa,MAAM;AAAA;AAAA,IAEnD,SAAS,qBAAqB,UAAU;AAAA,IACxC,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,IACnE,GAAI,QAAQ,cAAc,UAAa,EAAE,WAAW,QAAQ,UAAU;AAAA,IACtE,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;AAAA,EACjD,CAAC;AACH;AA0CA,eAAsB,YACpBE,OACA,OACA,WACA,UAAwB,CAAC,GACH;AACtB,QAAM,WAAwB,CAAC;AAC/B,QAAM,aAAa,CAAC,CAAC,QAAQ;AAC7B,QAAM,YAAY,aACd,SACA,aAAa,QAAQ,aAAa,QAAQ;AAE9C,MAAI,YAAYA;AAChB,MAAI;AACJ,MAAI;AAEJ,MAAI;AAEF,UAAM,cAAc,MAAM,eAAe,SAAS;AAClD,kBAAc,YAAY;AAC1B,0BAAsB,YAAY;AAGlC,UAAM;AAAA,MACJ,wBAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,yBAAAC;AAAA,MACA,oBAAAC;AAAA,IACF,IAAI,MAAM;AACV,UAAM,WAAW,QAAQ,mBAAmB;AAC5C,UAAM,YAAY,QAAQ,oBAAoB;AAC9C,UAAM,sBACJ,aAAa,SACTF,mBAAkB,KAAK,IACvBD,wBAAuB,KAAK;AAClC,UAAM,uBACJ,cAAc,SACVG,oBAAmB,KAAK,IACxBD,yBAAwB,KAAK;AAEnC,UAAM,mBAAmB,KAAK,MAAO,sBAAsB,OAAQ,EAAE;AACrE,UAAM,oBAAoB,KAAK,MAAO,uBAAuB,OAAQ,EAAE;AAGvE,UAAM,gBAAgB;AACtB,UAAM,cAAc;AACpB,UAAM,gBAAgB,KAAK,MAAM,gBAAgB,WAAW;AAC5D,UAAM,iBAAiB,KAAK,MAAM,gBAAgB,GAAG;AAIrD,UAAM,cAAc;AAAA,MAClB,QAAQ,SAAS;AAAA,MACjB;AAAA,IACF;AAGA,UAAM,eACJ,QAAQ,WAAW,SACf,oBAAoB,QAAQ,QAAQ,iBAAiB,IACrD;AAGN,UAAM,aAAa,MAAM;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,EAAE,oBAAAE,oBAAmB,IAAI,MAAM;AAGrC,UAAM,WAAW,aACbA,oBAAmB,QAAQ,UAAU,OAAO,SAAS,IACrD;AAGJ,UAAM,YAAY,gBAAgB,WAAW,mBAAmB;AAGhE,UAAM,WAAW,oBAAoB;AAAA,MACnC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,gBAAgB,EAAE,OAAO,WAAW,OAAO,QAAQ,WAAW,OAAO;AAAA,MACrE,GAAI,YAAY,EAAE,SAAS;AAAA,IAC7B,CAAC;AAGD,UAAM,UAAe,CAAC;AACtB,QAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,cAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,IACvD;AACA,QAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,IACrD;AAEA,aAAS;AAAA,MACP,IAAIC,WAAU;AAAA,QACZ,UAAU,CAAC,QAAQ;AAAA,QACnB;AAAA,QACA,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,KAAK,EAAE,QAAQ;AAAA,QACjD,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,QACnE,GAAI,QAAQ,cAAc,UAAa;AAAA,UACrC,WAAW,QAAQ;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AAEd,UAAM,IAAI,MAAM,6BAA6B,SAAS,EAAE;AAAA,EAC1D;AAEA,MAAI,QAAQ,SAAS;AAEnB,UAAM,gBAAgB,gCAAgC,KAAK,QAAQ,OAAO;AAE1E,QAAI,CAAC,eAAe;AAElB,eAAS;AAAA,QACP,IAAIA,WAAU;AAAA,UACZ,MAAM,qBAAqB,QAAQ,OAAO;AAAA,UAC1C,OAAO;AAAA,UACP,WAAWC,eAAc;AAAA;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,YAAM,WAAW;AAAA,QACf,QAAQ;AAAA,QACR,CAAC;AAAA,QACD;AAAA,UACE,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA,eAAS;AAAA,QACP,IAAID,WAAU;AAAA,UACZ,UAAU;AAAA,UACV,OAAO;AAAA;AAAA,UACP,WAAWC,eAAc;AAAA;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,gBACd,MACA,UAA4B,CAAC,GAChB;AACb,QAAM,YAAY,aAAa,KAAK,aAAa,QAAQ;AACzD,QAAM,mBAAmB,qBAAqB,KAAK,MAAM;AACzD,QAAM,wBAAwB,qBAAqB,KAAK,WAAW;AAEnE,SAAO;AAAA,IACL,IAAID,WAAU;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA,SAAS,QAAQ;AAAA,IACnB,CAAC;AAAA,IACD,IAAIA,WAAU;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAKO,SAAS,WACd,OACA,QACA,YACA,UAAuB,CAAC,GACX;AACb,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,aAA0B,CAAC;AAQjC,QAAM,eAAe,mBAAmB,QAAQ,WAAW,QAAQ,QAAQ;AAE3E,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,UAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;AACpD,UAAM,WAAW,OAAO,SAAS,WAAW,KAAK,WAAW;AAC5D,WAAO,QAAQ,KAAK,KAAK,CAAC,KAAK,QAAQ,QAAQ;AAAA,EACjD,CAAC;AACD,QAAM,gBAAgB,UAAU,QAAQ,IAAI;AAC5C,QAAM,eAAe,UAAU,YAAY,IAAI;AAC/C,QAAM,gBACJ,kBAAkB,KAAK,SAAY,iBAAiB,QAAQ,OAAO;AAErE,QAAM,QAAQ,CAAC,MAAM,UAAU;AAE7B,UAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK;AACxD,UAAM,YAAY,OAAO,SAAS,WAAW,KAAK,SAAS,IAAI;AAC/D,UAAM,eAAe,OAAO,SAAS,WAAW,KAAK,WAAW;AAIhE,QAAI,CAAC,SAAS,KAAK,KAAK,CAAC,cAAc;AACrC;AAAA,IACF;AAIA,UAAM,WAAW,eACb,mBAAmB,cAAc,CAAC,CAAC,IACnC;AAAA,MACE;AAAA,MACA,CAAC;AAAA,MACD;AAAA,QACE,kBAAkB;AAAA,QAClB,SAAS,cAAc;AAAA,MACzB;AAAA,IACF;AAGJ,UAAM,UAA+C,CAAC;AACtD,QAAI,UAAU,KAAK,QAAQ,SAAS,QAAQ;AAC1C,cAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,IACvD;AACA,QAAI,UAAU,MAAM,SAAS,KAAK,QAAQ,SAAS,OAAO;AACxD,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,IACrD,WAAW,QAAQ,SAAS,MAAM;AAChC,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,IAAI;AAAA,IACpD;AAGA,UAAM,oBAAsC;AAAA,MAC1C,GAAI,iBAAiB,UAAU,gBAAgB,cAAc,QAAQ,CAAC;AAAA,MACtE,GAAG;AAAA,MACH,GAAI,iBAAiB,UAAU,eAC3B,kBAAkB,cAAc,GAAG,IACnC,CAAC;AAAA,IACP;AAEA,UAAM,YAAY,IAAIA,WAAU;AAAA,MAC9B,OAAO;AAAA;AAAA,MACP,UAAU;AAAA,MACV,WAAW,QAAQ,YACf,aAAa,QAAQ,SAAS,IAC9BC,eAAc;AAAA,MAClB;AAAA;AAAA,MAEA,GAAI,QAAQ,sBAAsB;AAAA,QAChC,WAAW;AAAA,UACT,WAAW,QAAQ;AAAA,UACnB,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,eAAW,KAAK,SAAS;AAAA,EAC3B,CAAC;AAED,gBAAc;AAAA,IACZ,MACG,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,OAAO,KAAK,IAAK,EAC3D,KAAK,IAAI;AAAA,EACd;AAEA,SAAO;AACT;AA+GA,eAAsB,YACpB,SACA,aACA,OACA,WACA,WAAyB,CAAC,GACV;AAEhB,QAAM,aAAa,cAAc,OAAO,SAAS;AAGjD,QAAM,UAAU,QAAQ,CAAC,GAAG,OAAO,UAAU;AAG7C,QAAM,yBAAyB,OAAqB;AAAA,IAClD,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAMA,QAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAM,gBAAgB,CAAC,MAAc,YAA0B;AAC7D,QAAI,iBAAiB,IAAI,OAAO,EAAG;AACnC,qBAAiB,IAAI,OAAO;AAE5B,YAAQ,KAAK,kBAAkB,IAAI,KAAK,OAAO,EAAE;AAAA,EACnD;AASA,QAAM,mBAAmB,CACvB,OACA,SACuB;AACvB,QAAI,UAAU,UAAa,UAAU,OAAQ,QAAO;AACpD,QAAI,UAAU,eAAe;AAC3B,UAAI,SAAS,kBAAmB,QAAO;AACvC;AAAA,QACE;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,QAAI,mBAAmB,KAAK,KAAK,EAAG,QAAO,MAAM,YAAY;AAC7D,QAAI;AACF,aAAO,aAAa,OAAO,KAAK;AAAA,IAClC,QAAQ;AAIN,YAAM,UACJ,SAAS,oBACL,4CACA;AACN,YAAM,IAAI;AAAA,QACR,sBAAsB,IAAI,MAAM,KAAK,8EAA8E,OAAO;AAAA,MAC5H;AAAA,IACF;AAAA,EACF;AAGA,QAAM,uBAAuB,CAC3B,WAGe;AACf,QAAI,WAAW,OAAW,QAAO;AACjC,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,EAAE,KAAK,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,MAAM,OAAO;AAAA,IACpE;AACA,WAAO;AAAA,MACL,KAAK,OAAO,OAAO;AAAA,MACnB,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,sBAAsB,CAC1B,WAGe;AACf,QAAI,WAAW,OAAW,QAAO;AACjC,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,EAAE,KAAK,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,MAAM,OAAO;AAAA,IACpE;AACA,WAAO;AAAA,MACL,KAAK,OAAO,OAAO;AAAA,MACnB,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,mBAAmB,CACvB,YAGe;AACf,QAAI,YAAY,OAAW,QAAO;AAClC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,EAAE,KAAK,SAAS,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ;AAAA,IACxE;AACA,WAAO;AAAA,MACL,KAAK,QAAQ,OAAO;AAAA,MACpB,OAAO,QAAQ,SAAS;AAAA,MACxB,QAAQ,QAAQ,UAAU;AAAA,MAC1B,MAAM,QAAQ,QAAQ;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,0BAA0B,IAC3B,YAC8D;AACjE,UAAM,aAAa,QAAQ,IAAI,oBAAoB;AACnD,UAAM,WAAW,uBAAuB;AACxC,UAAM,eACJ,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT;AAEN,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QACE,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAC1D,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,yBAAyB,IAC1B,YAC8D;AACjE,UAAM,aAAa,QAAQ,IAAI,mBAAmB;AAClD,UAAM,WAAW,uBAAuB;AACxC,UAAM,cACJ,OAAO,SAAS,eAAe,WAAW,SAAS,aAAa;AAElE,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QACE,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAC1D,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,sBAAsB,CAC1B,UAMA,kBACA,oBAcG;AACH,UAAM,SAaF,CAAC;AAEL,QAAI,kBAAkB;AACpB,YAAM,kBAAkB,qBAAqB,gBAAgB;AAC7D,UAAI,iBAAiB;AACnB,eAAO,cAAc,CAAC;AACtB,YAAI,SAAS,YAAY,gBAAgB,QAAQ;AAC/C,iBAAO,YAAY,MAAM,gBAAgB;AAC3C,YAAI,SAAS,cAAc,gBAAgB,SAAS;AAClD,iBAAO,YAAY,OAAO,gBAAgB;AAC5C,YAAI,SAAS,aAAa,gBAAgB,UAAU;AAClD,iBAAO,YAAY,QAAQ,gBAAgB;AAC7C,YAAI,SAAS,aAAa,gBAAgB,WAAW;AACnD,iBAAO,YAAY,SAAS,gBAAgB;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,iBAAiB;AACnB,YAAM,iBAAiB,oBAAoB,eAAe;AAC1D,UAAI,gBAAgB;AAClB,eAAO,aAAa,CAAC;AACrB,YAAI,SAAS,YAAY,eAAe,QAAQ;AAC9C,iBAAO,WAAW,MAAM,eAAe;AACzC,YAAI,SAAS,cAAc,eAAe,SAAS;AACjD,iBAAO,WAAW,OAAO,eAAe;AAC1C,YAAI,SAAS,aAAa,eAAe,UAAU;AACjD,iBAAO,WAAW,QAAQ,eAAe;AAC3C,YAAI,SAAS,aAAa,eAAe,WAAW;AAClD,iBAAO,WAAW,SAAS,eAAe;AAAA,MAC9C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,sBAAsB,IACvB,aAGY;AACf,UAAM,aAAa,SAAS,IAAI,gBAAgB;AAChD,UAAM,SAAS,WAAW,KAAK,CAAC,MAAM,MAAM,MAAS;AACrD,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QAAQ,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAChE,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,oBAAoB,CACxB,UACA,WACA,SACA,UAKA,qBAC2B;AAC3B,UAAM,WAAW,uBAAuB;AAGxC,UAAM,aAA8B;AAAA,MAClC,GAAG,SAAS;AAAA,MACZ,GAAG,UAAU;AAAA,MACb,GAAG,WAAW;AAAA,MACd,GAAG,SAAS;AAAA,IACd;AAGA,UAAM,cACJ,YAAY,mBACR;AAAA,MACE;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IACnB,IACA,CAAC;AAKP,UAAM,oBAAoB;AAAA,MACxB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,mBAAmB;AAAA,MACvB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,gBAAgB;AAAA,MACpB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS,SAAS,WAAW,SAAS,UAAU,SAAS,SAAS;AAAA,QAClE;AAAA,MACF;AAAA,MACA,iBAAiB;AAAA,QACf,SAAS,mBACP,WAAW,mBACX,UAAU,mBACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,qBACE,SAAS,uBACT,WAAW,uBACX,UAAU,uBACV,SAAS;AAAA,MACX,mBACE,SAAS,qBACT,WAAW,qBACX,UAAU,qBACV,SAAS;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,QAAQ,SAAS,UAAU,WAAW,UAAU,UAAU;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,0BAA0B,CAC9B,UACA,gBACA,WACA,WACA,UACA,qBAC2B;AAC3B,UAAM,WAAW,uBAAuB;AAGxC,UAAM,aAA8B;AAAA,MAClC,GAAG,SAAS;AAAA,MACZ,GAAG,UAAU;AAAA,MACb,GAAG,gBAAgB;AAAA,MACnB,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAGA,UAAM,cACJ,YAAY,mBACR;AAAA,MACE;AAAA,QACE,UAAU;AAAA,QACV,YAAY,SAAS;AAAA,QACrB,WAAW,SAAS;AAAA,MACtB;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IACnB,IACA,CAAC;AAKP,UAAM,oBAAoB;AAAA,MACxB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,mBAAmB;AAAA,MACvB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,gBAAgB;AAAA,MACpB,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,QACL,WAAW,SACT,gBAAgB,SAChB,WAAW,SACX,UAAU,SACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,iBAAiB;AAAA,QACf,WAAW,mBACT,gBAAgB,mBAChB,WAAW,mBACX,UAAU,mBACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,qBACE,WAAW,uBACX,gBAAgB,uBAChB,WAAW,uBACX,UAAU,uBACV,SAAS;AAAA,MACX,mBACE,WAAW,qBACX,gBAAgB,qBAChB,WAAW,qBACX,UAAU,qBACV,SAAS;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,QACE,WAAW,UACX,gBAAgB,UAChB,WAAW,UACX,UAAU;AAAA,IACd;AAAA,EACF;AAIA,QAAM,iBAAiB,CACrB,QAMA,SACG;AACH,WAAO,OAAO,IAAI;AAAA,EACpB;AAIA,QAAM,kBAAkB,CACtB,SAGA,SACuB;AACvB,QAAI,YAAY,OAAW,QAAO;AAClC,WAAO,QAAQ,IAAI,IAAI;AAAA,EACzB;AAKA,QAAM,2BAA2B,CAC/B,YAGG;AACH,QAAI,YAAY,OAAW,QAAO;AAElC,WAAO;AAAA,MACL,gBAAgB,UAAU;AAAA;AAAA,MAC1B,KAAK,gBAAgB,SAAS,KAAK,KAAK;AAAA,MACxC,QAAQ,gBAAgB,SAAS,QAAQ,KAAK;AAAA,MAC9C,MAAM,gBAAgB,SAAS,MAAM,KAAK;AAAA,MAC1C,OAAO,gBAAgB,SAAS,OAAO,KAAK;AAAA,IAC9C;AAAA,EACF;AAGA,QAAM,uBAAuB,CAC3B,gBAQG;AACH,QAAI,gBAAgB,QAAW;AAC7B,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF;AACA,QAAI,OAAO,gBAAgB,WAAW;AACpC,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,MACL,KAAK,YAAY,OAAO;AAAA,MACxB,OAAO,YAAY,SAAS;AAAA,MAC5B,QAAQ,YAAY,UAAU;AAAA,MAC9B,MAAM,YAAY,QAAQ;AAAA,MAC1B,kBAAkB,YAAY,oBAAoB;AAAA,MAClD,gBAAgB,YAAY,kBAAkB;AAAA,IAChD;AAAA,EACF;AAGA,QAAM,gBAAgB,qBAAqB,YAAY,WAAW;AAGlE,QAAM,eAAe,CAAC,MAAc,OAAe,aAAuB;AACxE,QAAI,SAAS,KAAK,UAAU;AAC1B,aAAO,EAAE,OAAOC,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,IAC7D;AACA,WAAO;AAAA,MACL,OAAOA,aAAY;AAAA,MACnB,MAAM,OAAO;AAAA;AAAA,MACb,OAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAGA,QAAM,mBAAmB,CACvB,MACA,aAMY;AAGZ,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,SAAS,aACZ,cAAc,MACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,YACZ,cAAc,SACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,aACZ,cAAc,OACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,YACZ,cAAc,QACd,cAAc;AAAA,MACpB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,qBAAqB,OACzB,MACA,cACA,eACA,SACA,UAOA,YAI8B;AAC9B,QAAI,eAAiC,CAAC;AAKtC,QAAI,CAAC,MAAM;AACT,aAAO,cAAc,cAAc,OAAO;AAAA,IAC5C;AAGA,UAAM,eAAe,qBAAqB;AAAA,MACxC,YAAY,aAAa,MAAM,UAAU,cAAc;AAAA,MACvD,MAAM,aAAa,MAAM,QAAQ;AAAA,MACjC,QAAQ,aAAa,MAAM,UAAU;AAAA,MACrC,YAAY,aAAa,MAAM;AAAA,IACjC,CAAC;AACD,UAAM,cAAc;AAAA,MAClB,MAAM,aAAa;AAAA,MACnB,MAAM,aAAa,MAAM,OACrB,aAAa,KAAK,OAAO,IACzB,cAAc;AAAA;AAAA,MAClB,MAAM,aAAa,QAAQ;AAAA,MAC3B,SAAS,aAAa,WAAW;AAAA,MACjC,WAAW,aAAa,MAAM,YAC1B,EAAE,MAAM,SAAkB,IAC1B;AAAA,MACJ,OAAO,aAAa,SAAS,cAAc;AAAA,IAC7C;AAEA,QAAI,OAAO,SAAS,YAAY,UAAU,QAAQ,WAAW,MAAM;AAEjE,UAAI,qBAAqB,IAAI,GAAG;AAC9B,cAAM,WAAW;AACjB,cAAM,gBAAgB,SAAS,MAAM;AACrC,cAAM,eAAe,qBAAqB;AAAA,UACxC,YAAY,eAAe,UAAU,YAAY;AAAA,UACjD,MAAM,eAAe;AAAA,UACrB,QAAQ,eAAe;AAAA,UACvB,YAAY,eAAe;AAAA,QAC7B,CAAC;AACD,cAAM,iBAAiB;AAAA,UACrB,GAAG;AAAA,UACH,GAAI,aAAa,QAAQ,EAAE,MAAM,aAAa,KAAK;AAAA,UACnD,GAAI,eAAe,QAAQ,EAAE,MAAM,cAAc,OAAO,EAAE;AAAA,UAC1D,GAAI,aAAa,SAAS,UAAa;AAAA,YACrC,MAAM,aAAa;AAAA,UACrB;AAAA,UACA,GAAI,aAAa,YAAY,UAAa;AAAA,YACxC,SAAS,aAAa;AAAA,UACxB;AAAA,UACA,GAAI,eAAe,cAAc,UAAa;AAAA,YAC5C,WAAW,cAAc,YACrB,EAAE,MAAM,SAAkB,IAC1B;AAAA,UACN;AAAA,UACA,GAAI,eAAe,SAAS;AAAA,YAC1B,OAAO,aAAa,cAAc,OAAO,KAAK;AAAA,UAChD;AAAA,QACF;AAIA,cAAM,oBAAoB,YAAY,SAAS,MAAM;AACrD,uBAAe,oBACX,mBAAmB,mBAAmB,cAAc,IACpD,UACE,qBAAqB,SAAS,MAAM,MAAM,SAAS,cAAc,IACjE,wBAAwB,SAAS,MAAM,MAAM,gBAAgB;AAAA,UAC3D,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACT,WAAW,iBAAiB,IAAI,GAAG;AACjC,cAAM,YAAY;AAClB,YAAI;AAEF,gBAAM,cAAc,mBAAmB,UAAU,KAAK;AACtD,cAAI,CAAC,aAAa;AAChB,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,cAAc,MAAM,eAAe,WAAW;AAGpD,gBAAM,cACJ,OAAO,UAAU,MAAM,UAAU,WAC7B,gBAAgB,UAAU,MAAM,OAAO,GAAG,IAC1C,UAAU,MAAM;AAGtB,gBAAM,eACJ,OAAO,UAAU,MAAM,WAAW,WAC9B,gBAAgB,UAAU,MAAM,QAAQ,GAAG,IAC3C,UAAU,MAAM;AAGtB,gBAAM,aAAa,MAAM;AAAA,YACvB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,YACA;AAAA;AAAA,UACF;AAEA,gBAAM,UAAU,gBAAgB,aAAa,YAAY,WAAW;AACpE,gBAAM,WAAW,oBAAoB;AAAA,YACnC,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,gBAAgB;AAAA,cACd,OAAO,WAAW;AAAA,cAClB,QAAQ,WAAW;AAAA,YACrB;AAAA,UACF,CAAC;AACD,yBAAe,CAAC,QAAQ;AAAA,QAC1B,SAAS,OAAO;AAEd,gBAAM,cAAc,UAAU,MAAM,KAAK,KAAK,IAC1C,eACA,UAAU,MAAM,UAAU,UAAU,MAAM,QAAQ;AACtD,yBAAe;AAAA,YACb,IAAIC,SAAQ;AAAA,cACV,MAAM,WAAW,YAAY,UAAU,GAAG,EAAE,CAAC,GAAG,YAAY,SAAS,KAAK,QAAQ,EAAE;AAAA,cACpF,MAAM,YAAY;AAAA,cAClB,MAAM,YAAY;AAAA,cAClB,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,OAAO;AAEL,uBAAe;AAAA,UACb,IAAIA,SAAQ;AAAA,YACV,MAAM,gCAAgC,KAAK,IAAI;AAAA,YAC/C,MAAM,YAAY;AAAA,YAClB,MAAM,YAAY;AAAA,YAClB,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,OAAO;AAEL,qBAAe,WACX,mBAAmB,UAAU,WAAW,IACxC,UACE,qBAAqB,MAAgB,SAAS,WAAW,IACzD,wBAAwB,MAAgB,aAAa;AAAA,QACnD,kBAAkB;AAAA,MACpB,CAAC;AAAA,IACT;AAIA,WAAO,cAAc,cAAc,OAAO;AAAA,EAC5C;AAIA,QAAM,aAAa,QAAQ;AAC3B,QAAM,eAAe,QAAQ;AAAA,IAC3B,CAAC,WAAW,QAAQ,aAAa;AAC/B,YAAM,aAAa,OAAO;AAC1B,YAAM,WAAW;AAAA,QACf,YAAY,aAAa;AAAA,QACzB,WAAW,aAAa,aAAa;AAAA,MACvC;AACA,YAAM,iBAAiB;AAAA,QACrB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,UACE,aAAa,YAAY;AAAA,UACzB,YAAY,YAAY;AAAA,QAC1B;AAAA,MACF;AACA,UAAI,eAAe,WAAW,QAAW;AACvC,eAAO,cAAc,SACjB,KAAK,IAAI,WAAW,eAAe,MAAM,IACzC,eAAe;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,SAAS;AAAA;AAAA,IAE7B,aAAa,YAAY,2BAA2B;AAAA,IACpD,QACE,iBAAiB,SACb,EAAE,OAAO,eAAe,IAAI,MAAM,UAAmB,IACrD;AAAA,IACN,UAAU,MAAM,QAAQ;AAAA,MACtB,QAAQ,IAAI,OAAO,QAAQ,aAAa;AACtC,cAAM,aAAa,OAAO;AAG1B,cAAM,WAAW;AAAA,UACf,YAAY;AAAA;AAAA,UACZ,WAAW,YAAY;AAAA;AAAA,UACvB,YAAY,aAAa;AAAA,UACzB,WAAW,aAAa,aAAa;AAAA,QACvC;AAGA,cAAM,iBAAiB;AAAA,UACrB,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,YACE,aAAa,YAAY;AAAA,YACzB,YAAY,YAAY;AAAA,UAC1B;AAAA,QACF;AAEA,cAAM,eAAe,MAAM;AAAA,UACzB,YAAY;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,YAAY;AAAA,QACd;AAEA,cAAM,sBAAsB,eAAe;AAC3C,cAAM,oBAAoB;AAAA,UACxB,eAAe;AAAA,QACjB;AAEA,eAAO,IAAI,UAAU;AAAA,UACnB,UAAU;AAAA,YACR,IAAIH,WAAU;AAAA,cACZ,GAAI,YAAY,iBAAiB,EAAE,UAAU,KAAK;AAAA,cAClD,SAAS,WAAW;AAAA,cACpB,WAAW,aAAa,mBAAmB;AAAA,cAC3C,UAAU;AAAA,YACZ,CAAC;AAAA,UACH;AAAA,UAEA,eAAe;AAAA,UACf,GAAI,eAAe,oBAAoB,iBAAiB;AAAA,YACtD,SAAS;AAAA,cACP,MAAM,eAAe;AAAA,YACvB;AAAA,UACF;AAAA,UACA,SAAS,yBAAyB,eAAe,OAAO;AAAA,UACxD,SAAS;AAAA,YACP,KAAK;AAAA,cACH,eAAe,eAAe,YAAY,KAAK;AAAA,cAC/C,eAAe,eAAe,aAAa,KAAK;AAAA,cAChD,iBAAiB,OAAO,QAAQ;AAAA,YAClC;AAAA,YACA,QAAQ;AAAA,cACN,eAAe,eAAe,YAAY,QAAQ;AAAA,cAClD,eAAe,eAAe,aAAa,QAAQ;AAAA,cACnD,iBAAiB,UAAU,QAAQ;AAAA,YACrC;AAAA,YACA,MAAM;AAAA,cACJ,eAAe,eAAe,YAAY,MAAM;AAAA,cAChD,eAAe,eAAe,aAAa,MAAM;AAAA,cACjD,iBAAiB,QAAQ,QAAQ;AAAA,YACnC;AAAA,YACA,OAAO;AAAA,cACL,eAAe,eAAe,YAAY,OAAO;AAAA,cACjD,eAAe,eAAe,aAAa,OAAO;AAAA,cAClD,iBAAiB,SAAS,QAAQ;AAAA,YACpC;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAGD,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,OAAO,GAAG,aAAa;AACrD,YAAM,YAAY,aAAa,UAAU;AAOzC,YAAM,WAAW,YAAY,OAAO,QAAQ;AAC5C,YAAM,cAAc,UAAU;AAC9B,YAAM,wBAAwB,cAC1B,mBAAmB,WAAW,IAC9B;AAOJ,YAAM,iBAAiB,cACnB,QAAQ,IAAI,OAAO,EAAE,KAAK,mBAAmB,WAAW,EAAE,EAAE,IAC5D;AAGJ,YAAM,YAAY,QAAQ;AAAA,QACxB,CAAC,WAAW,QAAQ,aAAa;AAC/B,gBAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,cAAI,MAAM;AACR,kBAAM,WAAW;AAAA,cACf,YAAY,aAAa;AAAA,cACzB,WAAW,aAAa,aAAa;AAAA,cACrC;AAAA,YACF;AACA,kBAAM,iBAAiB;AAAA,cACrB,YAAY;AAAA,cACZ,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,gBACE,aAAa,YAAY;AAAA,gBACzB,YAAY,YAAY;AAAA,cAC1B;AAAA,YACF;AACA,gBAAI,eAAe,WAAW,QAAW;AACvC,qBAAO,cAAc,SACjB,KAAK,IAAI,WAAW,eAAe,MAAM,IACzC,eAAe;AAAA,YACrB;AAAA,UACF;AACA,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAEA,aAAO,IAAI,SAAS;AAAA,QAClB,QACE,cAAc,SACV,EAAE,OAAO,YAAY,IAAI,MAAM,UAAmB,IAClD;AAAA,QACN,GAAI,UAAU,cAAc,UAAa;AAAA,UACvC,WAAW,SAAS;AAAA,QACtB;AAAA,QACA,GAAI,UAAU,gBAAgB,UAAa;AAAA,UACzC,aAAa,SAAS;AAAA,QACxB;AAAA;AAAA,QAEA,GAAG;AAAA,QACH,UAAU,MAAM,QAAQ;AAAA,UACtB,QAAQ,IAAI,OAAO,QAAQ,aAAa;AACtC,kBAAM,OAAO,OAAO,QAAQ,QAAQ;AAGpC,kBAAM,WAAW;AAAA,cACf,YAAY;AAAA;AAAA,cACZ,YAAY,aAAa;AAAA,cACzB,WAAW,aAAa,aAAa;AAAA,cACrC;AAAA,YACF;AAEA,gBAAI,CAAC,MAAM;AAET,oBAAM,2BAA2B;AAAA,gBAC/B,YAAY;AAAA,gBACZ,OAAO;AAAA,gBACP;AAAA,gBACA;AAAA,gBACA;AAAA,kBACE,aAAa,YAAY;AAAA,kBACzB,YAAY,YAAY;AAAA,gBAC1B;AAAA,cACF;AACA,qBAAO,IAAI,UAAU;AAAA,gBACnB,UAAU;AAAA,kBACR,IAAIA,WAAU;AAAA,oBACZ,GAAK,YAAY,iBAAiB,CAAC,aAClC,aAAa,YAAY,WACtB,EAAE,UAAU,KAAK,IACjB,CAAC;AAAA,oBACL,SAAS,WAAW;AAAA,oBACpB,WAAWC,eAAc;AAAA,oBACzB,GAAG,iBAAiB,QAAQ;AAAA,oBAC5B,UAAU,CAAC;AAAA,kBACb,CAAC;AAAA,gBACH;AAAA,gBACA,SAAS;AAAA,kBACP,KAAK;AAAA,oBACH;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,OAAO,QAAQ;AAAA,kBAClC;AAAA,kBACA,QAAQ;AAAA,oBACN;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,UAAU,QAAQ;AAAA,kBACrC;AAAA,kBACA,MAAM;AAAA,oBACJ;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,QAAQ,QAAQ;AAAA,kBACnC;AAAA,kBACA,OAAO;AAAA,oBACL;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,SAAS,QAAQ;AAAA,kBACpC;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAGA,kBAAM,iBAAiB;AAAA,cACrB,YAAY;AAAA,cACZ,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,gBACE,aAAa,YAAY;AAAA,gBACzB,YAAY,YAAY;AAAA,cAC1B;AAAA,YACF;AAEA,kBAAM,eAAe,MAAM;AAAA,cACzB,KAAK;AAAA,cACL;AAAA,cACA,WAAW;AAAA,cACX,KAAK;AAAA,cACL,KAAK;AAAA,cACL;AAAA,YACF;AAEA,kBAAM,sBAAsB,eAAe;AAC3C,kBAAM,oBAAoB;AAAA,cACxB,eAAe;AAAA,YACjB;AAEA,mBAAO,IAAI,UAAU;AAAA,cACnB,UAAU;AAAA,gBACR,IAAID,WAAU;AAAA,kBACZ,GAAK,YAAY,iBAAiB,CAAC,aAClC,aAAa,YAAY,WACtB,EAAE,UAAU,KAAK,IACjB,CAAC;AAAA,kBACL,SAAS,WAAW;AAAA,kBACpB,WAAW,aAAa,mBAAmB;AAAA,kBAC3C,GAAG,iBAAiB,QAAQ;AAAA,kBAC5B,UAAU;AAAA,gBACZ,CAAC;AAAA,cACH;AAAA,cACA,eAAe;AAAA,cACf,GAAI,eAAe,oBAAoB,iBAAiB;AAAA,gBACtD,SAAS;AAAA,kBACP,MAAM,eAAe;AAAA,gBACvB;AAAA,cACF;AAAA,cACA,SAAS,yBAAyB,eAAe,OAAO;AAAA,cACxD,SAAS;AAAA,gBACP,KAAK;AAAA,kBACH,eAAe,eAAe,YAAY,KAAK;AAAA,kBAC/C,eAAe,eAAe,aAAa,KAAK;AAAA,kBAChD,iBAAiB,OAAO,QAAQ;AAAA,gBAClC;AAAA,gBACA,QAAQ;AAAA,kBACN,eAAe,eAAe,YAAY,QAAQ;AAAA,kBAClD;AAAA,oBACE,eAAe;AAAA,oBACf;AAAA,kBACF;AAAA,kBACA,iBAAiB,UAAU,QAAQ;AAAA,gBACrC;AAAA,gBACA,MAAM;AAAA,kBACJ,eAAe,eAAe,YAAY,MAAM;AAAA,kBAChD,eAAe,eAAe,aAAa,MAAM;AAAA,kBACjD,iBAAiB,QAAQ,QAAQ;AAAA,gBACnC;AAAA,gBACA,OAAO;AAAA,kBACL,eAAe,eAAe,YAAY,OAAO;AAAA,kBACjD,eAAe,eAAe,aAAa,OAAO;AAAA,kBAClD,iBAAiB,SAAS,QAAQ;AAAA,gBACpC;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,QAAM,oBAAoB,QAAQ,KAAK,CAAC,QAAQ,IAAI,UAAU,MAAS;AAEvE,MAAI;AACJ,MAAI;AAKJ,MAAI,mBAAmB;AAErB,UAAM,aAAa,MAAM;AACzB,UAAM,EAAE,wBAAAL,yBAAwB,uBAAAS,uBAAsB,IAAI;AAG1D,UAAM,sBAAsBT,wBAAuB,OAAO,SAAS;AAGnE,UAAM,gCAAgC,QAAQ;AAAA,MAAI,CAAC,QACjD,IAAI,UAAU,SACVS,uBAAsB,IAAI,OAAO,mBAAmB,IACpD;AAAA,IACN;AAGA,UAAM,qBAAqB,8BAA8B;AAAA,MACvD,CAAC,KAAa,MAAM,OAAO,KAAK;AAAA,MAChC;AAAA,IACF;AAEA,QAAI,qBAAqB,qBAAqB;AAC5C,cAAQ;AAAA,QACN,yCAAyC,kBAAkB,0CAA0C,mBAAmB;AAAA,MAC1H;AAAA,IACF;AAGA,UAAM,sBAAsB,QAAQ;AAAA,MAClC,CAAC,QAAQ,IAAI,UAAU;AAAA,IACzB,EAAE;AAGF,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA,sBAAsB;AAAA,IACxB;AACA,UAAM,qBACJ,sBAAsB,IAClB,iBAAiB,sBACjB,cAAc,EAAE;AAGtB,mBAAe,8BAA8B;AAAA,MAC3C,CAAC,MAAM,KAAK;AAAA,IACd;AACA,UAAM,aAAa,aAAa,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAC7D,iBAAa,EAAE,MAAM,YAAY,MAAM,UAAU,IAAI;AAAA,EACvD,OAAO;AAEL,UAAM,mBAAmB,MAAM,QAAQ;AACvC,mBAAe,QAAQ,IAAI,MAAM,gBAAgB;AACjD,iBAAa,EAAE,MAAM,YAAY,SAAS,KAAK,MAAM,UAAU,WAAW;AAAA,EAC5E;AAEA,SAAO,IAAI,MAAM;AAAA,IACf,OAAO;AAAA,IACP,QAAQ,gBAAgB;AAAA,IACxB;AAAA,IACA,MAAM,CAAC,WAAW,GAAG,QAAQ;AAAA,EAC/B,CAAC;AACH;AAKA,SAAS,aACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAOH,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB;AACE,aAAOA,eAAc;AAAA,EACzB;AACF;AAKA,SAAS,qBACP,WAKY;AACZ,MAAI,CAAC,UAAW,QAAO;AAEvB,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB;AACE,aAAO;AAAA,EACX;AACF;AAKO,SAAS,oBACd,UACA,UAGQ;AACR,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,oBACd,UACA,UAGQ;AACR,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,EACF,CAAC;AACH;;;AMj8EO,SAAS,uBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAG5C,QAAM,SAAS,UAAU;AAIzB,QAAM,aACH,UAAkB,MACnB,uBAAuB,WAAW,OAAO,MAAM,SAAS;AAG1D,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,OAAO,SAAS;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,MACE,WAAW,OAAO;AAAA,MAClB,SAAS,OAAO;AAAA,MAChB,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA;AAAA,MAEpB,YAAY,OAAO,MAAM;AAAA,MACzB,UAAU,OAAO,MAAM;AAAA,MACvB,WAAW,OAAO,MAAM;AAAA,MACxB,MAAM,OAAO,MAAM;AAAA,MACnB,YAAa,OAAO,MAChB;AAAA,MACJ,QAAQ,OAAO,MAAM;AAAA,MACrB,WAAW,OAAO,MAAM;AAAA,MACxB,OAAO,OAAO,MAAM;AAAA,MACpB,kBAAkB,OAAO,MAAM;AAAA;AAAA,MAE/B,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,MAChB,cAAc,OAAO;AAAA;AAAA,MAErB,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA;AAAA,MAElB,QAAQ,OAAO;AAAA;AAAA,MAEf;AAAA;AAAA,MAEA,UAAU,OAAO;AAAA;AAAA,MAEjB,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,CAAC,MAAM;AAChB;;;AClEA,SAAS,iBAAAI,gBAAe,qBAAqB,mBAAmB;AAEhE,SAAS,qBAAAC,0BAAyB;AAGlC,IAAM,mBAGF;AAAA,EACF,SAAS,YAAY;AAAA,EACrB,YAAY,YAAY;AAAA,EACxB,YAAY,YAAY;AAAA,EACxB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,QAAQ,YAAY;AAAA,EACpB,SAAS,YAAY;AAAA,EACrB,cAAc,YAAY;AAAA,EAC1B,aAAa,YAAY;AAAA,EACzB,KAAK,YAAY;AAAA,EACjB,SAAS,YAAY;AAAA,EACrB,kBAAkB,YAAY;AAAA,EAC9B,kBAAkB,YAAY;AAAA,EAC9B,OAAO,YAAY;AAAA,EACnB,OAAO,YAAY;AAAA,EACnB,kBAAkB,YAAY;AAAA,EAC9B,kBAAkB,YAAY;AAAA,EAC9B,eAAe,YAAY;AAAA,EAC3B,4BAA4B,YAAY;AAAA,EACxC,uBAAuB,YAAY;AAAA,EACnC,mBAAmB,YAAY;AAAA,EAC/B,gBAAgB,YAAY;AAAA,EAC5B,gBAAgB,YAAY;AAAA,EAC5B,aAAa,YAAY;AAAA,EACzB,QAAQ,YAAY;AAAA,EACpB,SAAS,YAAY;AAAA,EACrB,yBAAyB,YAAY;AAAA,EACrC,sBAAsB,YAAY;AAAA,EAClC,8BAA8B,YAAY;AAAA,EAC1C,yBAAyB,YAAY;AAAA,EACrC,sBAAsB,YAAY;AAAA,EAClC,iBAAiB,YAAY;AAAA,EAC7B,4BAA4B,YAAY;AAAA,EACxC,mBAAmB,YAAY;AAAA,EAC/B,2BAA2B,YAAY;AAAA,EACvC,2BAA2B,YAAY;AAAA,EACvC,kBAAkB,YAAY;AAAA,EAC9B,iBAAiB,YAAY;AAAA,EAC7B,wBAAwB,YAAY;AAAA,EACpC,yBAAyB,YAAY;AAAA,EACrC,eAAe,YAAY;AAAA,EAC3B,gBAAgB,YAAY;AAAA,EAC5B,aAAa,YAAY;AAAA,EACzB,gBAAgB,YAAY;AAAA,EAC5B,oBAAoB,YAAY;AAAA,EAChC,cAAc,YAAY;AAAA,EAC1B,cAAc,YAAY;AAAA,EAC1B,MAAM,YAAY;AAAA,EAClB,cAAc,YAAY;AAAA,EAC1B,SAAS,YAAY;AAAA,EACrB,SAAS,YAAY;AAAA,EACrB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,iBAAiB,YAAY;AAAA,EAC7B,cAAc,YAAY;AAAA,EAC1B,eAAe,YAAY;AAAA,EAC3B,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,cAAc,YAAY;AAC5B;AAEA,IAAM,gBAGF;AAAA,EACF,OAAOD,eAAc;AAAA,EACrB,KAAKA,eAAc;AAAA,EACnB,MAAMA,eAAc;AAAA,EACpB,OAAOA,eAAc;AAAA,EACrB,QAAQA,eAAc;AACxB;AAgDA,SAAS,eACPE,SACgD;AAChD,MAAI,CAACA,QAAQ,QAAO,YAAY;AAChC,SAAO,iBAAiBA,OAAM,KAAK,YAAY;AACjD;AAKA,SAASC,cACP,WACoD;AACpD,MAAI,CAAC,UAAW,QAAOH,eAAc;AACrC,SAAO,cAAc,SAAS,KAAKA,eAAc;AACnD;AAiCA,SAAS,qBACP,MACwC;AACxC,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,MAAkC;AAAA,IACtC,GAAI,KAAK,UAAU,EAAE,MAAM,KAAK,OAAO;AAAA;AAAA,IAEvC,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,OAAO,EAAE;AAAA,IACrD,GAAI,KAAK,SAAS,EAAE,OAAO,KAAK,MAAM;AAAA,IACtC,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK;AAAA,IACjD,GAAI,KAAK,WAAW,UAAa,EAAE,SAAS,KAAK,OAAO;AAAA,IACxD,GAAI,KAAK,cAAc,UAAa;AAAA,MAClC,WAAW,KAAK,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAMO,SAAS,sBAAsB,QAGpC;AACA,QAAM,SAA2B,CAAC;AAGlC,aAAW,eAAe,OAAO,QAAQ;AACvC,UAAMI,UAAS,eAAe,YAAY,MAAM;AAChD,UAAM,YAAYC,cAAa,YAAY,SAAS;AACpD,UAAM,OACJ,YAAY,SACXD,YAAW,YAAY,SAAS,WAAM,IAAI,YAAY,QAAQ,CAAC;AAGlE,UAAM,aACJ,YAAY,QAAQ,SAAS,SACzB,YAAY,OAAO,OAAO,KAC1B,OAAO,YAAY,QAAQ;AAEjC,UAAM,gBACJ,YAAY,QAAQ,YAAY,SAC5B,YAAY,OAAO,UAAU,KAC7B;AAEN,UAAM,YAAY,qBAAqB,YAAY,IAAI;AAEvD,UAAM,QAAwB;AAAA,MAC5B,OAAO,YAAY;AAAA,MACnB,QAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,WAAW;AAAA,UACT,QAAQ;AAAA,YACN,MAAM,oBAAoB,UAAU;AAAA,YACpC,SAAS,oBAAoB,aAAa;AAAA,UAC5C;AAAA,QACF;AAAA;AAAA;AAAA,QAGA,GAAI,aAAa,EAAE,KAAK,UAAU;AAAA,MACpC;AAAA;AAAA,MAEA,GAAI,YAAY,UAAU,UAAa,EAAE,OAAO,YAAY,MAAM;AAAA,IACpE;AAEA,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB;AAAA,EACF;AACF;AAuCO,IAAM,oBAAN,MAAwB;AAAA,EACZ,WAA2B;AAAA,IAC1C,SAAS,oBAAI,IAAI;AAAA,IACjB,SAAS;AAAA,EACX;AAAA,EACiB,SAAS,IAAIE,mBAAkC;AAAA,EAEhE,IAAY,QAAwB;AAClC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,SAAS,oBAAI,IAAI,GAAG,SAAS,EAAE,GAAG,QAAQ;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAAiE;AACxE,UAAM,YAAY,OAAO;AACzB,SAAK,MAAM,QAAQ,IAAI,WAAW,MAAM;AACxC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAAiB,QAAgB;AACjD,WAAO,GAAG,MAAM,IAAI,EAAE,KAAK,MAAM,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,SAA4D;AAC1D,WAAO,MAAM,KAAK,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,QAAQ,MAAM;AACzB,SAAK,MAAM,UAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAA4B;AAC9B,WAAO,KAAK,MAAM,QAAQ,IAAI,SAAS;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,IACE,WAC6D;AAC7D,WAAO,KAAK,MAAM,QAAQ,IAAI,SAAS;AAAA,EACzC;AACF;AAGO,IAAM,0BAA0B,IAAI,kBAAkB;;;ACvV7D,SAAS,kBAAkB,MAGlB;AACP,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,QAA2C,CAAC;AAClD,MAAI,cAA8B;AAClC,MAAI,YAA4B;AAEhC,aAAW,QAAQ,OAAO;AAExB,QAAI,CAAC,KAAK,KAAK,EAAG;AAGlB,UAAM,iBAAiB,KAAK,MAAM,sBAAsB;AACxD,QAAI,gBAAgB;AAClB,YAAM,cAAc,KAAK,MAAM,eAAe,CAAC,EAAE,SAAS,CAAC;AAC3D,YAAMC,QAAO,eAAe,CAAC;AAC7B,YAAM,KAAK,EAAE,MAAAA,OAAM,OAAO,YAAY,CAAC;AACvC,UAAI,gBAAgB,KAAM,eAAc;AACxC;AAAA,IACF;AAGA,UAAM,eAAe,KAAK,MAAM,uBAAuB;AACvD,QAAI,cAAc;AAChB,YAAM,cAAc,KAAK,MAAM,aAAa,CAAC,EAAE,SAAS,CAAC;AACzD,YAAMA,QAAO,aAAa,CAAC;AAC3B,YAAM,KAAK,EAAE,MAAAA,OAAM,OAAO,YAAY,CAAC;AACvC,UAAI,cAAc,KAAM,aAAY;AACpC;AAAA,IACF;AAGA,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,WAAW,KAAM,eAAe,WAAY;AACpD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,cAAc;AAAA,IAClC;AAAA,EACF;AACF;AAKO,SAAS,yBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,qBAAqB,SAAS,EAAG,QAAO,CAAC;AAG9C,QAAM,iBAAiB,UAAU;AAKjC,QAAM,WAAW,eAAe,WAC5B,OACA,kBAAkB,eAAe,IAAI;AAEzC,MAAI,UAAU;AAEZ,UAAM,YACJ,wBAAwB,kBAAkB,eAAe;AAG3D,UAAM,SAA4B,CAAC;AAEnC,QAAI,SAAS,SAAS,aAAa;AAEjC,aAAO;AAAA,QACL,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,QAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,QAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,MAC7D;AAAA,IACF,OAAO;AAEL,aAAO;AAAA,QACL,EAAE,OAAO,GAAG,QAAQ,WAAW,MAAM,OAAO,WAAW,OAAO;AAAA,QAC9D,EAAE,OAAO,GAAG,QAAQ,eAAe,MAAM,OAAO,WAAW,OAAO;AAAA,QAClE,EAAE,OAAO,GAAG,QAAQ,cAAc,MAAM,OAAO,WAAW,OAAO;AAAA,MACnE;AAAA,IACF;AAEA,UAAM,kBAAmC;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,4BAAwB,SAAS,sBAAsB,eAAe,CAAC;AAIvE,WAAO,WAAW,SAAS,OAAO,OAAO,WAAW;AAAA,MAClD,oBAAoB;AAAA,MACpB,SAAS,eAAe;AAAA,MAGxB,WAAW,eAAe;AAAA,MAC1B,SAAS,eAAe;AAAA,MACxB,WAAW,eAAe;AAAA,MAC1B,UAAU,eAAe;AAAA,IAC3B,CAAC;AAAA,EACH;AAKA,QAAM,kBAAkB,MAAM;AAC5B,UAAM,MAAM,eAAe;AAC3B,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,WAAW,IAAI,YAAY;AAGjC,QAAI,aAAa,SAAU,QAAO;AAClC,QAAI,aAAa,QAAS,QAAO;AACjC,QAAI,aAAa,WAAY,QAAO;AACpC,UAAM,eAAe,SAAS,MAAM,kBAAkB;AACtD,QAAI,cAAc;AAGhB,aAAO,kBAAkB,aAAa,CAAC,CAAC;AAAA,IAC1C;AAIA,WAAO;AAAA,EACT,GAAG;AAGH,QAAM,gBAAgB,MAAM;AAC1B,UAAM,MAAM,eAAe;AAC3B,QAAI,CAAC,IAAK,QAAO;AAIjB,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,eAAe,SAAS,MAAM,kBAAkB;AACtD,QAAI,aAAc,QAAO;AAGzB,UAAM,cAAc,MAAM,SAAS,GAAgC;AACnE,QACE,eACA,OAAO,gBAAgB,YACvB,kBAAkB,aAClB;AACA,aAAQ,YAAoB;AAAA,IAC9B;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,QAAM,OAAO,WAAW,eAAe,MAAM,OAAO,WAAW;AAAA,IAC7D,OAAO;AAAA,IACP,SAAS,eAAe;AAAA,IAGxB,aAAa,eAAe,MAAM;AAAA,IAClC,WAAW,eAAe;AAAA,IAC1B,WAAW,eAAe;AAAA,IAC1B,aAAa,eAAe;AAAA;AAAA,IAE5B,YAAY,eAAe,MAAM;AAAA,IACjC,UAAU,eAAe,MAAM;AAAA,IAC/B,WAAW,eAAe,MAAM;AAAA,IAChC,MAAM,eAAe,MAAM;AAAA,IAC3B,YAAa,eAAe,MACxB;AAAA,IACJ,QAAQ,eAAe,MAAM;AAAA,IAC7B,WAAW,eAAe,MAAM;AAAA,IAChC,OAAO,eAAe,MAAM;AAAA,IAC5B,kBAAkB,eAAe,MAAM;AAAA;AAAA,IAEvC,UAAU,eAAe;AAAA,IACzB,SAAS,eAAe;AAAA,IACxB,cAAc,eAAe;AAAA;AAAA,IAE7B;AAAA;AAAA,IAEA,UAAU,eAAe;AAAA;AAAA,IAEzB,UAAU,eAAe;AAAA;AAAA,IAEzB,WAAW,eAAe;AAAA;AAAA,IAE1B,QAAQ,eAAe;AAAA;AAAA,IAEvB,UAAU,eAAe;AAAA;AAAA,IAEzB,YAAY,eAAe;AAAA;AAAA,IAE3B,UAAU,eAAe;AAAA;AAAA,IAEzB,SAAS,eAAe;AAAA;AAAA,IAExB,WAAW,eAAe;AAAA,IAC1B,UAAU,eAAe;AAAA,EAC3B,CAAC;AAED,SAAO,CAAC,IAAI;AACd;;;ACvNA;AAKA,SAAS,gCAAgC,OAAqC;AAC5E,QAAM,SAA4B,CAAC;AAGnC,MAAIC;AACJ,MAAI;AAEJ,MAAI,MAAM,QAAQ;AAChB,QAAI,MAAM,WAAW,YAAY;AAC/B,MAAAA,UAAS;AACT,aAAO;AAAA,IACT,WAAW,MAAM,WAAW,QAAQ;AAClC,MAAAA,UAAS;AACT,aAAO;AAAA,IACT,OAAO;AACL,MAAAA,UAAS,MAAM;AAAA,IACjB;AAAA,EACF,OAAO;AAEL,IAAAA,UAAS;AACT,WAAO,MAAM,UAAU;AAAA,EACzB;AAGA,QAAM,SAA0B;AAAA,IAC9B,OAAO;AAAA,IACP,QAAAA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,OAAO,MAAM;AAAA,EACf;AAGA,MAAI,MAAM,QAAQ;AAChB,QAAI,OAAO,MAAM,WAAW,UAAU;AACpC,aAAO,SAAS,EAAE,MAAM,MAAM,OAAO;AAAA,IACvC,OAAO;AACL,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,EACF;AAEA,SAAO,KAAK,MAAM;AAGlB,MAAIA,YAAW,UAAU;AACvB,WAAO;AAAA,MACL,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,MAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,IAC7D;AAAA,EACF,WAAWA,YAAW,WAAW;AAC/B,WAAO;AAAA,MACL,EAAE,OAAO,GAAG,QAAQ,eAAe,MAAM,OAAO,WAAW,OAAO;AAAA,MAClE,EAAE,OAAO,GAAG,QAAQ,cAAc,MAAM,OAAO,WAAW,OAAO;AAAA,IACnE;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,mBACP,QACA,OACmB;AACnB,SAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,UAAM,OAAO,MAAM;AACnB,QAAI,CAAC,MAAM,MAAO,QAAO;AACzB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,EAAE,GAAG,MAAM,OAAO,aAAa,KAAK,OAAO,KAAK,EAAE;AAAA,IAC1D;AAAA,EACF,CAAC;AACH;AASA,SAAS,eACP,QACA,OACmB;AACnB,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,OAAO;AAAA,IAAI,CAAC,UACjB,MAAM,UAAU,KAAK,MAAM,UAAU,SAAY,EAAE,GAAG,OAAO,MAAM,IAAI;AAAA,EACzE;AACF;AAKA,SAAS,qBACP,OACQ;AACR,MAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,KAAK,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,WAAW;AACf,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,YAAY,KAAK,UAAU,QAAW;AACxD,iBAAW,KAAK,IAAI,UAAU,KAAK,KAAK;AAAA,IAC1C;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,kBACP,QACA,UACmB;AAEnB,QAAM,WAAW,oBAAI,IAA6B;AAClD,aAAW,SAAS,QAAQ;AAC1B,aAAS,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAGA,QAAM,SAAS,SAAS,IAAI,CAAC;AAC7B,QAAM,aAAa,QAAQ,UAAU;AAGrC,QAAM,SAA4B,CAAC;AACnC,WAAS,IAAI,GAAG,KAAK,UAAU,KAAK;AAClC,QAAI,SAAS,IAAI,CAAC,GAAG;AACnB,aAAO,KAAK,SAAS,IAAI,CAAC,CAAE;AAAA,IAC9B,OAAO;AAEL,UAAI,eAAe,UAAU;AAC3B,cAAM,UAAU,CAAC,UAAK,UAAK,UAAK,UAAK,QAAG;AACxC,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,MAAM,QAAQ,IAAI,QAAQ,MAAM;AAAA,UAChC,WAAW;AAAA,QACb,CAAC;AAAA,MACH,WAAW,eAAe,aAAa,eAAe,YAAY;AAChE,cAAM,UAAU,CAAC,WAAW,eAAe,YAAY;AACvD,cAAMA,UAAS,QAAQ,IAAI,QAAQ,MAAM;AACzC,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAAA;AAAA,UACA,MAAM,IAAI,IAAI,CAAC;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AAAA,MACH,OAAO;AAEL,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,MAAM,IAAI,IAAI,CAAC;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,oBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,gBAAgB,SAAS,EAAG,QAAO,CAAC;AAGzC,QAAM,iBAAiB,UAAU;AAGjC,QAAM,WAAW,qBAAqB,eAAe,KAAK;AAG1D,QAAM,YACJ,eAAe,aACf,wBAAwB,kBAAkB,MAAM;AAGlD,MAAI,CAAC,wBAAwB,IAAI,SAAS,GAAG;AAC3C,QAAI;AAEJ,QAAI,eAAe,UAAU,eAAe,OAAO,SAAS,GAAG;AAE7D,eAAS;AAAA,QACP;AAAA,UACE,eAAe;AAAA,UACf,eAAe;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,gCAAgC,cAAc;AACjE,eAAS,kBAAkB,YAAY,QAAQ;AAAA,IACjD;AAEA,UAAM,SAA0B;AAAA,MAC9B;AAAA,MACA,QAAQ,mBAAmB,QAAQ,KAAK;AAAA,IAC1C;AACA,UAAM,kBAAkB,sBAAsB,MAAM;AACpD,4BAAwB,SAAS,eAAe;AAAA,EAClD;AAGA,SAAO,WAAW,eAAe,OAAO,OAAO,WAAW;AAAA,IACxD,oBAAoB;AAAA,IACpB,SAAS,eAAe;AAAA,IACxB,WAAW,eAAe;AAAA;AAAA,IAE1B,SAAS,eAAe;AAAA,EAC1B,CAAC;AACH;;;AC3OA,eAAsB,qBACpB,WACA,OACA,WACsB;AACtB,MAAI,CAAC,iBAAiB,SAAS,EAAG,QAAO,CAAC;AAG1C,QAAM,iBAAiB,UAAU;AAGjC,QAAM,cAAc,mBAAmB,cAAc;AAErD,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,YAAY,aAAa,OAAO,WAAW;AAAA,IACtD,SAAS,eAAe;AAAA,IACxB,OAAO,eAAe;AAAA,IACtB,QAAQ,eAAe;AAAA,IACvB,iBAAkB,eAAuB;AAAA,IACzC,kBAAmB,eAAuB;AAAA,IAC1C,WAAW,eAAe;AAAA,IAC1B,SAAS,eAAe;AAAA,IACxB,UAAU,eAAe;AAAA,IACzB,UAAU,eAAe;AAAA,IACzB,WAAW,eAAe;AAAA,EAC5B,CAAC;AACH;;;ACxCA;AAAA,EAEE,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAAC;AAAA,OACK;;;ACXP;AADA,SAAS,eAAAC,oBAAmB;AAQrB,IAAM,eAAe;AAAA,EAC1B,KAAK,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EACzD,OAAO,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC3D,QAAQ,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC5D,MAAM,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC1D,kBAAkB,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EACtE,gBAAgB,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AACtE;AAOO,SAAS,eACd,GACgD;AAChD,UAAQ,GAAG;AAAA,IACX,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB;AACE,aAAOA,aAAY;AAAA,EACrB;AACF;AAiBO,SAAS,cACd,GACA,OAOY;AACZ,MAAI,CAAC,EAAG,QAAO;AAEf,SAAO;AAAA,IACL,OAAO,eAAe,EAAE,KAAK;AAAA,IAC7B,MAAM,EAAE,UAAU,SAAY,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI;AAAA,IACrE,OAAO,EAAE,QAAQ,aAAa,EAAE,OAAO,KAAK,IAAI;AAAA,EAClD;AACF;AAmBO,SAASC,gBACd,eACA,OAUY;AACZ,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,UAOF,CAAC;AAEL,QAAM,MAAM,cAAc,cAAc,KAAK,KAAK;AAClD,QAAM,QAAQ,cAAc,cAAc,OAAO,KAAK;AACtD,QAAM,SAAS,cAAc,cAAc,QAAQ,KAAK;AACxD,QAAM,OAAO,cAAc,cAAc,MAAM,KAAK;AAEpD,MAAI,IAAK,SAAQ,MAAM;AACvB,MAAI,MAAO,SAAQ,QAAQ;AAC3B,MAAI,OAAQ,SAAQ,SAAS;AAC7B,MAAI,KAAM,SAAQ,OAAO;AAEzB,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;;;AC5HA;AACA;AAFA,SAAS,aAAAC,kBAAwB;AAwC1B,SAAS,iBACd,UACA,UACA,OAWA;AACA,QAAM,WAAgB;AAAA,IACpB,UAAU,SAAS,SAAS,WAAW,CAAC,IAAIC,WAAU,CAAC,CAAC,CAAC;AAAA,IACzD,SAAS;AAAA,MACP,KAAK,UAAU,SAAS,MAAM,cAAc,SAAS,QAAQ,GAAG,IAAI;AAAA,MACpE,OAAO,UAAU,SAAS,QACtB,cAAc,SAAS,QAAQ,KAAK,IACpC;AAAA,MACJ,QAAQ,UAAU,SAAS,SACvB,cAAc,SAAS,QAAQ,MAAM,IACrC;AAAA,MACJ,MAAM,UAAU,SAAS,OAAO,cAAc,SAAS,QAAQ,IAAI,IAAI;AAAA,IACzE;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,MAAM;AAC3B,aAAS,UAAU,EAAE,MAAM,aAAa,SAAS,QAAQ,MAAM,KAAK,EAAE;AAAA,EACxE;AAGA,MAAI,UAAU,QAAQ;AACpB,UAAM,UAAUC,gBAAe,SAAS,QAAQ,KAAK;AACrD,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC9C,eAAS,UAAU;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;;;AF5DA;AAaA,SAAS,qBACP,UACA,OACA,WACiB;AACjB,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,MAAW,CAAC;AAGlB,QAAM,YAAY,SAAS,oBAAoB;AAC/C,QAAM,YAAY,SAAS,kBAAkB;AAC7C,QAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,QAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AAEzC,QAAM,KAAK,SAAS;AACpB,MAAI,IAAI,UAAU;AAChB,QAAI,mBACF,GAAG,aAAa,WACZ,gBAAgB,SAChB,GAAG,aAAa,SACd,gBAAgB,OAChB,gBAAgB;AAAA,EAC1B;AACA,MAAI,IAAI,WAAW,QAAW;AAC5B,QAAI,6BAA6B,mBAAmB,GAAG,QAAQ,IAAI;AAAA,EACrE,WAAW,IAAI,OAAO;AACpB,UAAM,MAGF;AAAA,MACF,MAAM,2BAA2B;AAAA,MACjC,QAAQ,2BAA2B;AAAA,MACnC,OAAO,2BAA2B;AAAA,MAClC,QAAQ,2BAA2B;AAAA,MACnC,SAAS,2BAA2B;AAAA,IACtC;AACA,QAAI,6BAA6B,IAAI,GAAG,KAAK;AAAA,EAC/C;AAEA,QAAM,KAAK,SAAS;AACpB,MAAI,IAAI,UAAU;AAChB,QAAI,iBACF,GAAG,aAAa,WACZ,gBAAgB,SAChB,GAAG,aAAa,SACd,gBAAgB,OAChB,gBAAgB;AAAA,EAC1B;AACA,MAAI,IAAI,WAAW,QAAW;AAC5B,QAAI,2BAA2B,mBAAmB,GAAG,QAAQ,IAAI;AAAA,EACnE,WAAW,IAAI,OAAO;AACpB,UAAM,OAGF;AAAA,MACF,KAAK,yBAAyB;AAAA,MAC9B,QAAQ,yBAAyB;AAAA,MACjC,QAAQ,yBAAyB;AAAA,MACjC,QAAQ,yBAAyB;AAAA,MACjC,SAAS,yBAAyB;AAAA,IACpC;AACA,QAAI,2BAA2B,KAAK,GAAG,KAAK;AAAA,EAC9C;AAGA,QAAM,QAAQ,kBAAkB,OAAO,SAAS;AAChD,QAAM,QAAQ,mBAAmB,OAAO,SAAS;AACjD,QAAM,IAAI,SAAS,MAAM;AACzB,MAAI,GAAG;AACL,QAAI,EAAE,QAAQ,OAAW,KAAI,cAAc,mBAAmB,EAAE,KAAK,KAAK;AAC1E,QAAI,EAAE,UAAU;AACd,UAAI,gBAAgB,mBAAmB,EAAE,OAAO,KAAK;AACvD,QAAI,EAAE,WAAW;AACf,UAAI,iBAAiB,mBAAmB,EAAE,QAAQ,KAAK;AACzD,QAAI,EAAE,SAAS;AACb,UAAI,eAAe,mBAAmB,EAAE,MAAM,KAAK;AAAA,EACvD;AAEA,MAAI,UAAU,YAAY;AAE1B,SAAO;AACT;AAEA,eAAsB,uBACpB,WACA,OACA,WACA,UACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAC5C,QAAM,KAAK;AAEX,QAAM,WAAW,CAAC,GAAG,MAAM;AAC3B,QAAM,kBAAkB,GAAG,YAAY,CAAC;AAExC,MAAI,UAAU;AAEZ,UAAMC,gBAAsC,CAAC;AAE7C,UAAMC,gBAAiD;AAAA,MACrD,GAAG;AAAA,MACH,QAAQ;AAAA,IACV;AACA,eAAW,SAAS,iBAAiB;AACnC,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACAA;AAAA,MACF;AACA,MAAAD,cAAa,KAAK,GAAG,QAAQ;AAAA,IAC/B;AAEA,UAAME,YAAY,GAAG,MAAc;AACnC,UAAMC,YAAW,iBAAiBH,eAAcE,WAAU,KAAK;AAE/D,UAAME,OAAM,IAAIC,UAAS,EAAE,UAAU,CAAC,IAAIC,WAAUH,SAAQ,CAAC,EAAE,CAAC;AAChE,UAAMI,SAAQ,IAAIC,OAAM;AAAA,MACtB,QAAQC,iBAAgB;AAAA;AAAA,MACxB,MAAM,CAACL,IAAG;AAAA,MACV,OAAO,EAAE,MAAM,KAAK,MAAMM,WAAU,WAAW;AAAA,MAC/C,SAAS;AAAA,IACX,CAAC;AACD,WAAO,CAACH,MAAK;AAAA,EACf;AAKA,QAAM,eAAsC,CAAC;AAE7C,QAAM,eAAiD;AAAA,IACrD,GAAG;AAAA,IACH,QAAQ;AAAA,EACV;AACA,aAAW,SAAS,iBAAiB;AACnC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,iBAAa,KAAK,GAAG,QAAQ;AAAA,EAC/B;AAEA,QAAM,WAAY,GAAG,MAAc;AACnC,QAAM,WAAW,iBAAiB,cAAc,UAAU,KAAK;AAE/D,QAAM,MAAM,IAAIF,UAAS;AAAA,IACvB,UAAU,CAAC,IAAIC,WAAU,QAAQ,CAAC;AAAA,EACpC,CAAC;AAED,QAAM,QAAQ,qBAAqB,GAAG,MAAM,UAAU,OAAO,SAAS;AAGtE,QAAM,kBAAkB;AACxB,QAAM,sBAAsB;AAI5B,QAAM,WAAW,GAAG,MAAM,SAAU,GAAG,MAAM,UAAkB;AAC/D,MAAI;AACJ,MAAI;AAEJ,MAAI,aAAa,QAAW;AAE1B,gBAAY;AACZ,gBAAYI,WAAU;AAAA,EACxB,WAAW,OAAO,aAAa,YAAY,SAAS,SAAS,GAAG,GAAG;AAEjE,gBAAY,WAAW,QAAQ;AAC/B,gBAAYA,WAAU;AAAA,EACxB,OAAO;AAEL,gBACE,OAAO,aAAa,WAChB,WAAW,kBACX;AACN,gBAAYA,WAAU;AAAA,EACxB;AAEA,QAAM,QAAQ,IAAIF,OAAM;AAAA,IACtB,QAAQC,iBAAgB;AAAA;AAAA,IACxB,MAAM,CAAC,GAAG;AAAA,IACV,OAAO,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,IAC1C;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AACD,SAAO,CAAC,KAAK;AACf;;;AGpIA,eAAsB,qBACpB,WACA,OACA,WACkB;AAClB,MAAI,CAAC,iBAAiB,SAAS,EAAG,QAAO,CAAC;AAE1C,QAAM,YAAY,UAAU;AAC5B,QAAM,SAAkB,CAAC;AAGzB,MAAI,UAAU,WAAW,UAAU,MAAM;AAEvC,UAAM,UAAU,UAAU;AAC1B,UAAM,OAAO,UAAU;AAEvB,UAAM,sBAAoC;AAAA,MACxC,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,MACb;AAAA,MACA,aAAa;AAAA,MACb,YAAY;AAAA,IACd;AAEA,UAAME,UAAsB;AAAA,MAC1B,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,OAAO;AAAA,MACP,SAAS,QAAQ,IAAI,CAAC,QAAQ,cAAc;AAAA,QAC1C,cAAc,EAAE,GAAG,oBAAoB;AAAA,QACvC,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,SAAS;AAAA,QACX;AAAA,QACA,OAAO,KAAK,IAAI,CAAC,SAAS;AAAA,UACxB,GAAG;AAAA,UACH,SAAS,IAAI,QAAQ,KAAK;AAAA,QAC5B,EAAE;AAAA,MACJ,EAAE;AAAA,IACJ;AAEA,WAAO,KAAK,MAAM,YAAYA,QAAO,SAASA,SAAQ,OAAO,SAAS,CAAC;AAEvE,WAAO;AAAA,EACT;AAGA,QAAM,SAAS;AAEf,SAAO,KAAK,MAAM,YAAY,OAAO,SAAS,QAAQ,OAAO,SAAS,CAAC;AAEvE,SAAO;AACT;;;AChKA,SAAS,aAAAC,YAAkB,eAAe,mBAAmB;;;ACa7D,SAAS,qBAAAC,0BAAyB;AAclC,IAAM,sBAAsB;AAS5B,SAASC,eAAoC;AAC3C,SAAO,EAAE,YAAY,GAAG,UAAU,oBAAI,QAAQ,EAAE;AAClD;AAMA,IAAM,0BAAN,MAA8B;AAAA,EACpB,WAAiCA,aAAY;AAAA,EACpC,SAAS,IAAID,mBAAwC;AAAA,EAEtE,IAAY,QAA8B;AACxC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAIC,aAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAiB,SAAkC;AACjD,WAAO,EAAE,IAAI,YAAY,OAAO,IAAI,QAAQ,QAAQ;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,WAAoC;AACtD,UAAM,QAAQ,KAAK;AACnB,UAAM,WAAW,MAAM,SAAS,IAAI,SAAS;AAC7C,QAAI,SAAU,QAAO;AAErB,UAAM,UAAU,MAAM;AACtB,UAAM,WAA4B;AAAA,MAChC,IAAI,kBAAkB,OAAO;AAAA,MAC7B,QAAQ,sBAAsB;AAAA,IAChC;AACA,UAAM,SAAS,IAAI,WAAW,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAc;AACZ,QAAI,CAAC,KAAK,OAAO,SAAS,GAAG;AAC3B,WAAK,WAAWA,aAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,gCAAgC,IAAI,wBAAwB;;;ADjFzE,eAAsB,uBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAE5C,QAAM,WAAkC,CAAC;AAIzC,QAAM,EAAE,IAAI,mBAAmB,QAAQ,eAAe,IACpD,8BAA8B,oBAAoB,SAAS;AAI7D,WAAS;AAAA,IACP,IAAIC,WAAU;AAAA,MACZ,UAAU,CAAC,IAAI,cAAc,mBAAmB,cAAc,CAAC;AAAA,MAC/D,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,iBAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,QAAQ;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAGA,MAAI,UAAU,UAAU;AACtB,eAAW,SAAS,UAAU,UAAU;AACtC,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,aAAa;AAAA,IAChC;AAAA,EACF;AAIA,WAAS;AAAA,IACP,IAAIA,WAAU;AAAA,MACZ,UAAU,CAAC,IAAI,YAAY,cAAc,CAAC;AAAA,MAC1C,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AE7EA;AAAA,EACE,aAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,mBAAAC;AAAA,OACK;AASP;AASA,eAAsB,uBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAG5C,MAAI,QAAQ,UAAU,mBAAmB,QAAQ,MAAM,GAAG;AAExD,WAAO,MAAM,qBAAqB,WAAW,OAAO,WAAW,OAAO;AAAA,EACxE;AAIA,QAAM,WAAkC,CAAC;AAEzC,MAAI,UAAU,UAAU;AACtB,eAAW,SAAS,UAAU,UAAU;AACtC,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,aAAa;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAe,qBACb,WACA,OACA,WACA,SACkB;AAClB,QAAM,MAAO,UAAkB,SAAS,CAAC;AACzC,QAAM,UAAU,IAAI,WAAW,CAAC;AAGhC,MAAI,gBACF,CAAC;AACH,MAAI,OAAO,YAAY,UAAU;AAE/B,oBAAgB,MAAM,OAAO,EAAE,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,EACvD,WAAW,MAAM,QAAQ,OAAO,GAAG;AACjC,oBAAgB;AAAA,EAClB,OAAO;AAEL,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,cAAc,cAAc;AAClC,MAAI,gBAAgB,EAAG,QAAO,CAAC;AAG/B,QAAM,sBAAsB,uBAAuB,OAAO,SAAS;AACnE,QAAM,eAAyB,CAAC;AAChC,QAAM,aAAuB,CAAC;AAC9B,MAAI,oBAAoB;AACxB,MAAI,YAAY;AAChB,QAAM,mBAA6B,CAAC;AAEpC,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,UAAM,MAAM,cAAc,CAAC;AAG3B,QAAI,IAAI,UAAU,UAAa,IAAI,UAAU,QAAQ;AACnD,uBAAiB,KAAK,CAAC;AACvB,mBAAa,KAAK,CAAC;AAAA,IACrB,OAAO;AACL,YAAM,aAAa,sBAAsB,IAAI,OAAO,mBAAmB;AACvE,mBAAa,KAAK,UAAU;AAC5B,2BAAqB;AAAA,IACvB;AAGA,QAAI,IAAI,cAAc,GAAG;AACvB,YAAM,WACJ,IAAI,QAAQ,SACR,sBAAsB,IAAI,KAAK,mBAAmB,IAClD,IAAI,QAAQ,SACV,sBAAsB,IAAI,KAAK,mBAAmB,IAClD;AACR,iBAAW,KAAK,QAAQ;AACxB,mBAAa;AAAA,IACf,OAAO;AACL,iBAAW,KAAK,CAAC;AAAA,IACnB;AAAA,EACF;AAGA,QAAM,iBAAiB,KAAK;AAAA,IAC1B;AAAA,IACA,sBAAsB,oBAAoB;AAAA,EAC5C;AACA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,kBAAkB,KAAK;AAAA,MAC3B,iBAAiB,iBAAiB;AAAA,IACpC;AACA,eAAW,OAAO,kBAAkB;AAClC,mBAAa,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,kBAAmB,UAAkB,YAAY,CAAC;AACxD,QAAM,iBAA0C,MAAM,WAAW,EAC9D,KAAK,IAAI,EACT,IAAI,MAAM,CAAC,CAAC;AAGf,WAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,UAAM,WAAW,IAAI;AACrB,mBAAe,QAAQ,EAAE,KAAK,gBAAgB,CAAC,CAAC;AAAA,EAClD;AAGA,QAAM,QAAqB,CAAC;AAC5B,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,UAAM,iBAAwC,CAAC;AAE/C,eAAW,SAAS,eAAe,CAAC,GAAG;AACrC,YAAM,WAAW,MAAM,gBAAgB,OAAO,OAAO,WAAW,OAAO;AACvE,qBAAe,KAAK,GAAG,QAAQ;AAAA,IACjC;AAGA,QAAI,eAAe,WAAW,GAAG;AAC/B,qBAAe,KAAK,IAAIC,WAAU,CAAC,CAAC,CAAC;AAAA,IACvC;AAEA,UAAM;AAAA,MACJ,IAAIC,WAAU;AAAA,QACZ,UAAU;AAAA,QACV,OAAO,EAAE,MAAM,aAAa,CAAC,GAAG,MAAMC,WAAU,IAAI;AAAA,QACpD,SAAS;AAAA,UACP,KAAK;AAAA,UACL,OAAO,WAAW,CAAC,IAAI;AAAA,UACvB,QAAQ;AAAA,UACR,MAAM,IAAI,IAAI,WAAW,IAAI,CAAC,IAAI,IAAI;AAAA,QACxC;AAAA,QACA,eAAeC,eAAc;AAAA,QAC7B,SAAS;AAAA,UACP,KAAK,EAAE,OAAOC,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UACzD,OAAO,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UAC3D,QAAQ,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UAC5D,MAAM,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,QAC5D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,MAAM,IAAIC,UAAS,EAAE,UAAU,MAAM,CAAC;AAC5C,QAAM,QAAQ,IAAIC,OAAM;AAAA,IACtB,MAAM,CAAC,GAAG;AAAA,IACV,OAAO,EAAE,MAAM,KAAK,MAAMJ,WAAU,WAAW;AAAA,IAC/C,QAAQK,iBAAgB;AAAA;AAAA,IACxB,SAAS;AAAA,EACX,CAAC;AAED,SAAO,CAAC,KAAK;AACf;;;AC3LO,SAAS,yBACd,WACA,QACa;AACb,MAAI,CAAC,qBAAqB,SAAS,EAAG,QAAO,CAAC;AAG9C,QAAM,iBAAiB,UAAU;AAEjC,SAAO;AAAA,IACL;AAAA,MACE,QAAQ,eAAe;AAAA,MACvB,aAAa,eAAe;AAAA,MAC5B,WAAW,eAAe;AAAA,IAC5B;AAAA,IACA;AAAA,MACE,SAAS,eAAe;AAAA,IAG1B;AAAA,EACF;AACF;;;AC7BA;AAAA,EACE,aAAAC;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,OACK;AA8BP,SAAS,mBAAmB,SAAyB;AACnD,SAAO,QACJ,QAAQ,YAAY,KAAK,EACzB,QAAQ,UAAU,GAAG,EACrB,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;AAeA,SAAS,oBACP,WACA,SAMY;AACZ,MAAI,CAAC,aAAa,UAAU,WAAW,EAAG,QAAO,CAAC;AAElD,QAAM,EAAE,YAAY,UAAU,mBAAmB,YAAY,IAAI;AACjE,QAAM,UAAsB,CAAC;AAE7B,aAAW,SAAS,WAAW;AAC7B,QAAI,qBAAqB,MAAM,sBAAsB,mBAAmB;AACtE;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,QAAW;AAG/B,YAAM,QACJ,YAAY,IAAI,MAAM,OAAO,KAC7B,YAAY,IAAI,mBAAmB,MAAM,OAAO,CAAC;AACnD,UAAI,UAAU,OAAW;AACzB,cAAQ,KAAK,EAAE,OAAO,MAAM,OAAO,MAAM,CAAC;AAC1C;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,cAAc,MAAM,QAAQ,SAAU;AAGxD,YAAQ,KAAK,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM,CAAC;AAAA,EACzD;AAEA,SAAO;AACT;AAUA,SAAS,gBACP,UACA,WACA,cAAc,GACd,YAAY,GACkB;AAC9B,MAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,8EAA8E,KAAK,UAAU,QAAQ,CAAC;AAAA,IACpH;AAAA,EACF;AAGA,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,KAAK,SAAS,MAAM;AAG1B,MAAI,OAAO,KAAK,OAAO,KAAK,KAAK,KAAK,KAAK,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,yDAAyD,IAAI,QAAQ,EAAE;AAAA,IACrF;AAAA,EACF;AACA,MAAI,OAAO,IAAI;AACb,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,8DAA8D,IAAI,QAAQ,EAAE;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,GAAG;AACpB;AAiBO,SAAS,mBACd,WACA,OACA,SACiC;AACjC,QAAM,iBAAiB,UAAU;AAGjC,QAAM,WAAW,eAAe,SAAS,EAAE,IAAI,EAAE;AACjD,QAAM,aAAa,gBAAgB,UAAU,aAAa,GAAG,CAAC;AAC9D,QAAM,aAAa,WAAW;AAC9B,QAAM,WAAW,WAAW;AAG5B,MAAI;AACJ,MAAI;AAEJ,MAAI,eAAe,qBAAqB,QAAW;AACjD,UAAM,mBAAmB;AAAA,MACvB,eAAe;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,uBAAmB,iBAAiB;AACpC,qBAAiB,iBAAiB;AAAA,EACpC;AAOA,MAAI,eAAe,mBAAmB,QAAW;AAC/C,YAAQ;AAAA,MACN,uBAAuB,eAAe,cAAc;AAAA,IAGtD;AAAA,EACF;AAEA,QAAM,qBAAqB,eAAe,uBAAuB;AACjE,QAAM,QAAQ,eAAe,SAAS;AAGtC,QAAM,iBACJ,UAAU,SACN,SAAS,SAAS,oBAChB,YACA,aACF;AAGN,QAAM,oBACJ,mBAAmB,YACf,SAAS,SAAS,oBAClB;AAGN,MAAI,mBAAmB,aAAa,CAAC,mBAAmB;AAEtD,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAA8C,CAAC;AAGrD,MAAI,eAAe,OAAO;AACxB,eAAW;AAAA,MACT,IAAIF,WAAU;AAAA,QACZ,UAAU;AAAA,UACR,IAAIE,SAAQ;AAAA,YACV,MAAM,eAAe;AAAA,YACrB,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,UACR,CAAC;AAAA,QACH;AAAA,QACA,SAAS;AAAA,UACP,QAAQ,MAAM,mBAAmB,SAAS,SAAS,UAAU;AAAA;AAAA;AAAA,UAG7D,OAAO;AAAA,QACT;AAAA,QACA,WAAWD,eAAc;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,mBAAiC,CAAC;AAmBxC,QAAM,cAAc,oBAAI,IAAoB;AAE5C,MAAI,eAAe,UAAU,eAAe,OAAO,SAAS,GAAG;AAC7D,eAAW,gBAAgB,eAAe,QAAQ;AAMhD,YAAM,UAAU,aAAa;AAC7B,YAAM,gBACJ,CAAC,CAAC,MAAM,UACR,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,OAAO;AAC5D,YAAM,mBAAmB,gBACrB,mBAAmB,OAAO,IAC1B;AAEJ,kBAAY,IAAI,SAAS,aAAa,KAAK;AAC3C,kBAAY,IAAI,kBAAkB,aAAa,KAAK;AAEpD,uBAAiB;AAAA,QACf,IAAI,WAAW,kBAAkB,aAAa,KAAK;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAaA,QAAM,sBAAsB;AAC5B,QAAM,oBAAoB;AAK1B,QAAM,gBAAgB,oBAAoB,SAAS,aAAa;AAAA,IAC9D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,aAAsC;AAAA,IAC1C,WAAW;AAAA;AAAA,IACX,mBAAmB,GAAG,mBAAmB,IAAI,iBAAiB;AAAA;AAAA,IAC9D;AAAA;AAAA;AAAA,IAEA,qBAAqB;AAAA;AAAA;AAAA;AAAA,IAIrB,IAAI,MAAM;AACR,UAAI,qBAAqB,UAAa,mBAAmB,QAAW;AAIlE,cAAM,eAAyB,CAAC;AAGhC,YAAI,mBAAmB,qBAAqB;AAC1C,uBAAa,KAAK,GAAG,mBAAmB,IAAI,mBAAmB,CAAC,EAAE;AAAA,QACpE;AAGA,YAAI,iBAAiB,mBAAmB;AACtC,uBAAa,KAAK,GAAG,iBAAiB,CAAC,IAAI,iBAAiB,EAAE;AAAA,QAChE;AAGA,eAAO,aAAa,SAAS,IACzB,EAAE,6BAA6B,aAAa,KAAK,GAAG,EAAE,IACtD,CAAC;AAAA,MACP,WAAW,CAAC,oBAAoB;AAE9B,eAAO;AAAA,UACL,6BAA6B,GAAG,mBAAmB,IAAI,iBAAiB;AAAA,QAC1E;AAAA,MACF,OAAO;AAEL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,GAAG;AAAA;AAAA;AAAA,IAGH,GAAI,eAAe,oBAAoB,SACnC;AAAA,MACE,6BAA6B,eAAe,kBACxC,MACA;AAAA,IACN,IACA,EAAE,6BAA6B,IAAK;AAAA;AAAA,EAC1C;AAKA,aAAW;AAAA,IACT,IAAI,gBAAgB,eAAe,SAAS,qBAAqB;AAAA,MAC/D,GAAG;AAAA,MACH,GAAI,cAAc,SAAS,KAAK,EAAE,cAAc;AAAA,IAClD,CAAC;AAAA,EACH;AAWA,SAAO;AACT;;;ACvXA;;;ACLO,SAAS,oBAA6B;AAE3C,SACE,OAAO,YAAY,eACnB,QAAQ,YAAY,QACpB,QAAQ,SAAS,QAAQ,QACzB,OAAO,QAAQ,SAAS,SAAS;AAErC;AAMO,SAAS,kBAA2B;AACzC,MAAI;AAGF,WACE,OAAO,cAAY,eAClB,OAAO,YAAY,eAClB,OAAO,QAAQ,aAAa,YAC5B,OAAO,QAAQ,SAAS,SAAS;AAAA,EAEvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACnBA,IAAM,qBAAqB;AAOpB,SAAS,kBACd,UACA,aACA,YACQ;AACR,QAAM,OAAO,YAAY,eAAe,YAAY,KAAK;AACzD,QAAM,aAAa,gBAAgB,KAAK,GAAG,IAAI,MAAM,UAAU,GAAG;AAClE,SAAO,WAAW,QAAQ,QAAQ,EAAE;AACtC;AAuBA,eAAsB,kBACpB,MACmB;AACnB,QAAM,kBACJ,OAAO,KAAK,YAAY,aACpB,MAAM,KAAK,QAAQ,KAAK,IAAI,IAC5B,KAAK;AACX,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,GAAG;AAAA,EACL;AAEA,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAE5D,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,KAAK,IAAI;AAAA,MAC9B,QAAQ,WAAW;AAAA,IACrB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAK,OAAiB,SAAS,cAAc;AAC3C,YAAM,IAAI;AAAA,QACR,GAAG,KAAK,YAAY,oBAAoB,SAAS,SAAS,KAAK,GAAG;AAAA,MACpE;AAAA,IACF;AACA,UAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACnE,UAAM,IAAI,MAAM,KAAK,cAAc,KAAK,KAAK,KAAK,CAAC;AAAA,EACrD,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,YAAY,aAAa,SAAS,MAAM,KAAK,SAAS,UAAU;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AF5EA,SAAS,kCAAkC;AAc3C,IAAM,4BAA4B;AAKlC,eAAe,cACb,QACA,gBACgC;AAEhC,MAAI,CAAC,kBAAkB,GAAG;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,cAAuC;AAAA,IAC3C,QAAQ,OAAO;AAAA,IACf,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO,OAAO;AAAA;AAAA;AAAA,IAGd,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,EAC5D;AAEA,QAAM,WAAW,MAAM,kBAAkB;AAAA,IACvC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,gBAAgB;AAAA,IACzB,cAAc;AAAA,IACd,eAAe,CAAC,KAAK,UACnB,8CAA8C,GAAG;AAAA,SAEvC,KAAK;AAAA,EACnB,CAAC;AAED,QAAM,aAAa,MAAM,SAAS,KAAK;AACvC,QAAM,gBAAgB,yBAAyB,UAAU;AACzD,QAAM,QAAQ,OAAO,QAAQ,MAAM;AACnC,QAAM,SAAS,OAAO,QAAQ,MAAM;AAEpC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASA,SAAS,aAAa,OAAe,OAAwC;AAG3E,MAAI,qBAAqB,KAAK,KAAK,GAAG;AACpC,WAAO,MAAM,WAAW,GAAG,IAAI,QAAQ,IAAI,KAAK;AAAA,EAClD;AACA,MAAI;AACF,WAAO,IAAI,aAAa,OAAO,KAAK,CAAC;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,SAAS,gBACP,QACA,OACiB;AACjB,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,WAAW,QAAQ,UAAU,CAAC,OAAO,OAAQ,QAAO;AACzD,QAAM,cAAc,MAAM;AAC1B,QAAM,UAAU,2BAA2B,IAAI,CAAC,UAAU;AACxD,UAAM,QAAQ,YAAY,KAAK;AAC/B,WAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAC/C,aAAa,OAAO,KAAK,IACzB;AAAA,EACN,CAAC,EAAE,OAAO,CAAC,MAAmB,MAAM,MAAS;AAC7C,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,EAAE,GAAG,OAAO,SAAS,QAAQ,QAAQ;AAAA,EAChD;AACF;AAKA,eAAsB,0BACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,sBAAsB,SAAS,EAAG,QAAO,CAAC;AAE/C,QAAM,SAAS,gBAAgB,UAAU,OAA0B,KAAK;AAGxE,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,SAAS,UAAU;AAAA,EACrB;AAIA,QAAM,sBACJ,OAAO,UAAU,UAAa,OAAO,WAAW;AAClD,QAAM,cAAc,sBAAsB,OAAO,QAAQ,YAAY;AACrE,QAAM,eAAe,sBAAsB,OAAO,SAAS,YAAY;AAGvE,QAAM,kBAAkB,MAAM;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;;;AG1KA,SAAS,cAAAE,mBAAkB;AAc3B;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAEA,IAAM,+BAA+B;AAE5C,IAAM,kBAAkB;AAOjB,SAAS,wBACd,OACyB;AACzB,QAAM,EAAE,QAAQ,SAAS,IAAI;AAE7B,QAAM,oBAA6C;AAAA,IACjD,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,EACtB;AACA,MAAI,OAAO,MAAO,mBAAkB,QAAQ,OAAO;AAEnD,QAAM,aAAsC,CAAC;AAC7C,MAAI,OAAO,WAAY,YAAW,aAAa,OAAO;AAEtD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,UAAU,YAAY,CAAC;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,qBAAqB,OAA4B;AAC/D,SAAO,KAAK,MAAM,MAAM,OAAO,QAAQ,eAAe;AACxD;AAQO,SAAS,qBAAqB,OAAkC;AACrE,SAAO;AAAA,IACL,OAAO,MAAM,SAAS,qBAAqB,KAAK;AAAA,IAChD,GAAI,MAAM,WAAW,UAAa,EAAE,QAAQ,MAAM,OAAO;AAAA,IACzD,WAAW,MAAM,aAAa;AAAA,IAC9B,GAAI,MAAM,YAAY,UAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,IAC5D,GAAI,MAAM,YAAY,UAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,IAC5D,GAAI,MAAM,aAAa,UAAa,EAAE,UAAU,MAAM,SAAS;AAAA,IAC/D,GAAI,MAAM,aAAa,UAAa,EAAE,UAAU,MAAM,SAAS;AAAA,IAC/D,GAAI,MAAM,cAAc,UAAa,EAAE,WAAW,MAAM,UAAU;AAAA,EACpE;AACF;AAMO,SAAS,mBACd,OACA,eACyB;AACzB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,GAAG,qBAAqB,KAAK;AAAA,IAC7B,GAAI,MAAM,QAAQ,UAAa,EAAE,KAAK,MAAM,IAAI;AAAA,EAClD;AACF;AAQO,SAAS,gBACd,cACA,KACA,WACQ;AACR,SAAOC,YAAW,QAAQ,EACvB,OAAO,KAAK,UAAU,EAAE,GAAG,cAAc,GAAG,KAAK,GAAG,aAAa,KAAK,CAAC,CAAC,EACxE,OAAO,KAAK;AACjB;AAYO,SAAS,yBACd,OACA,eACoB;AACpB,MAAI,eAAe,OAAQ,QAAO;AAClC,SAAO,MAAM;AACf;AAQA,eAAsB,qBACpB,cACA,KACA,gBACA,eACA,SAC8B;AAC9B,MAAI,CAAC,kBAAkB,GAAG;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAGA,MAAI,eAAe,QAAQ;AACzB,WAAO,cAAc,OAAO,EAAE,cAAc,KAAK,QAAQ,CAAC;AAAA,EAC5D;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,kBAAkB;AAAA,IACvC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM,EAAE,cAAc,KAAK,GAAI,YAAY,UAAa,EAAE,QAAQ,EAAG;AAAA,IACrE,SAAS,eAAe;AAAA,IACxB,cAAc;AAAA,IACd,eAAe,CAAC,KAAK,UACnB,kDAAkD,GAAG;AAAA,SAE3C,KAAK;AAAA,EACnB,CAAC;AAED,MAAI;AACJ,MAAI;AACF,aAAU,MAAM,SAAS,KAAK;AAAA,EAChC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,eAAe;AAC1B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,eAAsB,sBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,kBAAkB,SAAS,EAAG,QAAO,CAAC;AAE3C,QAAM,QAAQ,UAAU;AACxB,QAAM,gBAAgB,SAAS,UAAU;AAEzC,QAAM,eAAe,wBAAwB,KAAK;AAClD,QAAM,MAAM;AAAA,IACV,MAAM,OAAO,eAAe,OAAO;AAAA,EACrC;AAOA,QAAM,gBAAgB,SAAS,qBAAqB;AAAA,IAClD;AAAA,MACE;AAAA,MACA;AAAA,MACA,yBAAyB,OAAO,aAAa;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,eAAe;AACjB,QAAI,CAAC,cAAc,GAAI,OAAM,IAAI,MAAM,cAAc,KAAK;AAC1D,aAAS;AAAA,EACX,OAAO;AAIL,aAAS,MAAM;AAAA,MACb;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAKA,SAAO,MAAM;AAAA,IACX,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,qBAAqB,KAAK;AAAA,EAC5B;AACF;;;AC3PA,SAAS,YAAoB;;;ACN7B;AAAA,EACE,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,OACd;AAsCA,SAAS,cAId,SACsD;AACtD,SAAO,oBAAoB,OAAO;AACpC;AAEO,SAAS,gBAMd,WACyD;AACzD,SAAO,sBAAsB,SAAS;AACxC;;;AD9CA,IAAM,4BAA4B,KAAK,OAAO;AAAA,EAC5C,MAAM,KAAK,OAAO;AAAA,IAChB,aAAa;AAAA,EACf,CAAC;AAAA;AAAA,EAED,SAAS,KAAK;AAAA,IACZ,KAAK,OAAO;AAAA,MACV,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,MACnC,OAAO,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AACF,CAAC;AAOM,IAAM,0BAA0B,gBAAgB;AAAA,EACrD,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS,cAAc;AAAA,MACrB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,QAAQ,OAAO,EAAE,MAAM,MAAM;AAE3B,cAAM,SAA8B;AAAA,UAClC,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM,MAAM;AAAA,YACZ,SAAS;AAAA,cACP,GAAG,MAAM;AAAA,cACT,OAAO,MAAM,SAAS,SAAS;AAAA,YACjC;AAAA,UACF;AAAA,QACF;AAEA,eAAO,CAAC,MAAM;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;;;ApC2BD;;;AsClEA;AAAA,EACE,kBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA;AAAA,OAIK;;;ACpBA,SAAS,cACd,KACyC;AACzC,MAAI,SAAS;AACb,QAAM,QAA2B,CAAC;AAClC,QAAM,UAAU,MAAM;AACpB;AACA,UAAM,MAAM,IAAI;AAAA,EAClB;AACA,SAAO,eAAe,MAAS,IAAkC;AAG/D,WAAO,UAAU;AACf,YAAM,IAAI,QAAc,CAACC,aAAY,MAAM,KAAKA,QAAO,CAAC;AAC1D;AACA,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ADaA,IAAM,+BAA+B;AAErC,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AAmBnC,IAAM,eAAmC;AAAA,EACvC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AACV;AAOO,SAAS,wBAA4C;AAC1D,SAAO,EAAE,GAAG,aAAa;AAC3B;AAEO,SAAS,0BAAgC;AAC9C,eAAa,YAAY;AACzB,eAAa,YAAY;AACzB,eAAa,SAAS;AACxB;AAmBO,SAAS,mBAAmB,MAA8B;AAC/D,QAAM,QAAuB,CAAC;AAI9B,QAAM,OAAO,oBAAI,QAAgB;AACjC,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,QAAI,KAAK,IAAI,IAAI,EAAG;AACpB,SAAK,IAAI,IAAI;AACb,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,iBAAW,QAAQ,KAAM,OAAM,IAAI;AACnC;AAAA,IACF;AACA,UAAM,MAAM;AAGZ,QAAI,OAAO,IAAI,SAAS,YAAY,IAAI,YAAY,MAAO;AAC3D,QAAI,IAAI,SAAS,YAAY,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AACvE,YAAM,KAAK,IAAI,KAAoB;AAGnC;AAAA,IACF;AACA,eAAW,SAAS,OAAO,OAAO,GAAG,EAAG,OAAM,KAAK;AAAA,EACrD;AACA,QAAM,IAAI;AACV,SAAO;AACT;AAEA,SAAS,eAAe,OAAwB;AAC9C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,UAAU,SAAY,OAAY,MAA8B;AAC9D,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,KAAM,OAAM,MAAM,MAAM,GAAG,IAAI,IAAI;AAC5E;AAQA,SAAS,mBACP,OACA,UACA,KACS;AACT,QAAM,UAAW,UAAmD;AACpE,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,MAAM,OAAQ,QAAO;AAEvE,QAAM,UAA0D,CAAC;AACjE,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,QAAQ,CAAC;AACtB,QACE,QACA,KAAK,OAAO,QACZ,OAAO,KAAK,kBAAkB,YAC9B,KAAK,cAAc,SAAS,KAC5B,OAAO,KAAK,UAAU,YACtB,OAAO,KAAK,WAAW,UACvB;AACA,cAAQ,KAAK;AAAA,QACX,MAAM,CAAC,EAAE;AAAA,QACT;AAAA,UACE,IAAI;AAAA,UACJ,eAAe,KAAK;AAAA,UACpB,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH,WAAW,QAAQ,KAAK,OAAO,SAAS,OAAO,KAAK,UAAU,UAAU;AACtE,cAAQ,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA,IAC/D,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,QAAS,KAAI,IAAI,KAAK,KAAK;AACtD,SAAO;AACT;AAQA,eAAsB,oBACpB,MACA,eACA,UAA+B,CAAC,GACqB;AACrD,QAAM,MAAM,oBAAI,IAA2C;AAI3D,MACE,CAAC,kBAAkB,KACnB,CAAC,eAAe,eAChB,CAAC,eAAe,QAChB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,mBAAmB,IAAI;AACvC,MAAI,QAAQ,WAAW,EAAG,QAAO;AAGjC,QAAM,UAAU,oBAAI,IAAgC;AACpD,aAAW,SAAS,SAAS;AAK3B,QAAI;AACF,YAAMC,aAAY,yBAAyB,OAAO,aAAa;AAG/D,UAAIA,eAAc,OAAW;AAC7B,YAAM,eAAe,wBAAwB,KAAK;AAClD,YAAM,MAAMC;AAAA,QACV,MAAM,OAAO,eAAe,OAAOC;AAAA,MACrC;AACA,YAAM,MAAM,gBAAgB,cAAc,KAAKF,UAAS;AACxD,UAAI,CAAC,QAAQ,IAAI,GAAG,EAAG,SAAQ,IAAI,KAAK,EAAE,KAAK,cAAc,IAAI,CAAC;AAAA,IACpE,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,eAAa;AACb,eAAa,aAAa,QAAQ;AAClC,eAAa,UAAU,QAAQ;AAE/B,QAAM,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC;AACnC,QAAM,QAAQ;AAAA,IACZ,KAAK,IAAI,GAAG,QAAQ,eAAe,4BAA4B;AAAA,EACjE;AAGA,QAAM,wBAAwB,OAC5B,UACkB;AAClB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,QAAI,CAAC,WACT,MAAM,YAAY;AAChB,cAAI;AACF,kBAAM,SAAS,MAAM;AAAA,cACnB,OAAO;AAAA,cACP,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,YACV;AACA,gBAAI,IAAI,OAAO,KAAK,EAAE,IAAI,MAAM,GAAG,OAAO,CAAC;AAAA,UAC7C,SAAS,OAAO;AACd,gBAAI,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,OAAO,eAAe,KAAK,EAAE,CAAC;AAAA,UACjE;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,eAAe,aAAa;AAC9B,eAAW,SAAS,SAAS,QAAQ,0BAA0B,GAAG;AAChE,UAAI;AACF,cAAM,WAAW,MAAM,cAAc,YAAY;AAAA,UAC/C,QAAQ,MAAM,IAAI,CAAC,YAAY;AAAA,YAC7B,cAAc,OAAO;AAAA,YACrB,KAAK,OAAO;AAAA,UACd,EAAE;AAAA,UACF,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,QAClE,CAAC;AACD,YAAI,CAAC,mBAAmB,OAAO,UAAU,GAAG,GAAG;AAC7C,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AAOd,YAAI,cAAc,UAAU,cAAc,WAAW;AACnD,gBAAM,sBAAsB,KAAK;AAAA,QACnC,OAAO;AACL,gBAAM,UAAU,eAAe,KAAK;AACpC,qBAAW,UAAU,OAAO;AAC1B,gBAAI,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,OAAO,QAAQ,CAAC;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAIA,MAAI,eAAe,QAAQ;AACzB,UAAM,sBAAsB,MAAM;AAClC,WAAO;AAAA,EACT;AAKA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AACA,aAAW,SAAS,SAAS,QAAQ,0BAA0B,GAAG;AAChE,QAAI,UAAU;AACd,QAAI;AACF,YAAM,WAAW,MAAM,kBAAkB;AAAA,QACvC,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,QAAQ,MAAM,IAAI,CAAC,YAAY;AAAA,YAC7B,cAAc,OAAO;AAAA,YACrB,KAAK,OAAO;AAAA,UACd,EAAE;AAAA,UACF,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,QAClE;AAAA,QACA,SAAS,eAAe;AAAA,QACxB,WACE,wBAAwB,6BAA6B,MAAM;AAAA,QAC7D,cAAc;AAAA,QACd,eAAe,CAAC,KAAK,UACnB,kDAAkD,GAAG,YAAY,KAAK;AAAA,MAC1E,CAAC;AACD,gBAAU,mBAAmB,OAAO,MAAM,SAAS,KAAK,GAAG,GAAG;AAAA,IAChE,QAAQ;AACN,gBAAU;AAAA,IACZ;AACA,QAAI,CAAC,QAAS,OAAM,sBAAsB,KAAK;AAAA,EACjD;AACA,SAAO;AACT;;;AErTO,SAAS,uBACd,UACkB;AAClB,MAAI,UAAU;AAEd,SAAO,SAAS,IAAI,CAAC,SAAS,UAAU;AACtC,QAAI,CAAC,QAAQ,sBAAsB;AACjC,UAAI,QAAQ,cAAe;AAC3B,aAAO,EAAE,eAAe,MAAM;AAAA,IAChC;AAGA,UAAM,UAAU,QAAQ,gBAAgB,UAAU,IAAI;AACtD,QAAI,QAAQ,cAAe;AAI3B,UAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,UAAM,gBACJ,CAAC,QAAQ,CAAC,KAAK,wBAAwB,KAAK;AAE9C,WAAO,EAAE,SAAS,cAAc;AAAA,EAClC,CAAC;AACH;;;ACpBA,SAAS,4BAA4B;AAyB9B,SAAS,oBAAoB,MAAsB;AACxD,SAAO,qBAAqB,IAAI,EAC7B,QAAQ,6BAA6B,IAAI,EACzC,QAAQ,0BAA0B,IAAI,EACtC,QAAQ,uBAAuB,IAAI,EACnC,KAAK;AACV;AAGA,SAAS,YAAY,MAAuB;AAC1C,SAAO,qBAAqB,IAAI,GAAG,gBAAgB;AACrD;AAEA,SAAS,UAAU,WAAyC;AAC1D,SAAO,EAAE,aAAa,aAAa,UAAU,YAAY;AAC3D;AAQA,SAAS,cAAc,OAAoD;AACzE,QAAM,aAAa,MAAM;AACzB,MAAI,OAAO,eAAe,YAAY,CAAC,WAAY,QAAO;AAC1D,MAAI,kBAAkB,KAAK,UAAU,EAAG,QAAO;AAC/C,MAAI,CAAC,UAAU,SAAS,UAAU,EAAE,SAAS,WAAW,YAAY,CAAC,GAAG;AACtE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,mBACd,UACmB;AACnB,QAAM,UAA6B,CAAC;AACpC,QAAM,WAAW,uBAAuB,QAAQ;AAEhD,WAAS,QAAQ,CAAC,SAAS,UAAU;AAMnC,UAAM,UAAU,SAAS,KAAK,GAAG;AACjC,UAAM,oBAAoB,UACtB,8BAA8B,iBAAiB,OAAO,EAAE,KACxD;AAEJ,UAAM,QAAQ,CAAC,cAAyC;AACtD,UAAI,CAAC,UAAU,SAAS,EAAG;AAE3B,YAAM,QAAS,UAAU,SAAS,CAAC;AAEnC,UAAI,UAAU,SAAS,WAAW;AAChC,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,cAAM,QAAQ,oBAAoB,IAAI;AACtC,YAAI,OAAO;AACT,gBAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC9D,kBAAQ,KAAK,EAAE,OAAO,OAAO,kBAAkB,CAAC;AAAA,QAClD;AACA;AAAA,MACF;AAEA,UAAI,UAAU,SAAS,aAAa;AAClC,cAAM,UAAU,cAAc,KAAK;AACnC,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,cAAM,QAAQ,oBAAoB,IAAI;AACtC,YAAI,WAAW,OAAO;AAEpB,kBAAQ,KAAK,EAAE,OAAO,OAAO,GAAG,SAAS,kBAAkB,CAAC;AAAA,QAC9D;AACA;AAAA,MACF;AAEA,UAAI,CAAC,YAAY,UAAU,IAAI,EAAG;AAClC,YAAM,WAAY,UACf;AACH,UAAI,MAAM,QAAQ,QAAQ,EAAG,UAAS,QAAQ,KAAK;AAAA,IACrD;AAIA,YAAQ,WAAW,QAAQ,KAAK;AAAA,EAClC,CAAC;AAED,SAAO;AACT;;;AzCvCA,SAASG,cACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAOC,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB;AACE,aAAOA,eAAc;AAAA,EACzB;AACF;AAwBA,SAAS,eAAe,UAAiD;AACvE,QAAM,EAAE,OAAO,UAAU,aAAa,QAAQ,SAAS,SAAS,KAAK,IACnE;AAEF,QAAM,mBAAmB;AAAA,IACvB,GAAI,UAAU,CAAC,EAAE,MAAM,WAAW,OAAO,QAAQ,CAAC,IAAI,CAAC;AAAA,IACvD,GAAI,UAAU,CAAC,EAAE,MAAM,WAAW,OAAO,QAAQ,CAAC,IAAI,CAAC;AAAA,EACzD;AAEA,SAAO;AAAA,IACL,GAAI,SAAS,EAAE,MAAM;AAAA,IACrB,GAAI,YAAY,EAAE,SAAS,SAAS;AAAA,IACpC,GAAI,eAAe,EAAE,YAAY;AAAA;AAAA,IAEjC,GAAI,UAAU,EAAE,SAAS,QAAQ,gBAAgB,OAAO;AAAA,IACxD,GAAI,QAAQ,KAAK,SAAS,KAAK,EAAE,UAAU,KAAK,KAAK,IAAI,EAAE;AAAA,IAC3D,GAAI,iBAAiB,SAAS,KAAK,EAAE,iBAAiB;AAAA,EACxD;AACF;AAKA,eAAsB,eACpB,WACA,QACA,SACmB;AACnB,SAAO;AAAA,IAAsB,UAAU,SAAS;AAAA,IAAM,MACpD;AAAA,MAAe,SAAS;AAAA,MAAS,MAC/B,uBAAuB;AAAA,QAAU,MAC/B,yBAAyB;AAAA,UAAU,MACjC,wBAAwB;AAAA,YAAU,MAChC,8BAA8B;AAAA,cAAU;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKtC,sBAAsB;AAAA,kBAAU;AAAA;AAAA;AAAA,oBAG9B,mBAAmB;AAAA,sBAAU,MAC3B,qBAAqB,WAAW,QAAQ,OAAO;AAAA,oBACjD;AAAA;AAAA,gBACF;AAAA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,qBACb,WACA,QACA,SACmB;AAEnB,MAAI,SAAS,OAAO;AAClB,6BAAyB,QAAQ,KAAK;AAAA,EACxC,WAAW,CAAC,SAAS,aAAa;AAEhC,6BAAyB;AAAA,EAC3B;AAEA,QAAM,WAA8B,CAAC;AAGrC,QAAM,UAAU;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACA,UAAQ,WAAW,SAAS;AAO5B,MAAI;AACF,UAAM,sBAAsB,MAAM;AAAA,MAChC,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB,EAAE,SAAS,WAAW,EAAE;AAAA,IAC1B;AACA,QAAI,oBAAoB,OAAO,GAAG;AAChC,cAAQ,sBAAsB;AAAA,IAChC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AAMA,MAAI;AACF,UAAM,cAAc,mBAAmB,OAAO,QAAQ;AACtD,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,cAAc;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AAYA,QAAM,kBAAkB,uBAAuB,OAAO,QAAQ;AAG9D,MAAI,iBAAoD;AACxD,MAAI,iBAAoD;AAGxD,WAAS,MAAM,GAAG,MAAM,OAAO,SAAS,QAAQ,OAAO;AACrD,UAAM,gBAAgB,OAAO,SAAS,GAAG;AACzC,UAAM,EAAE,SAAS,gBAAgB,cAAc,IAAI,gBAAgB,GAAG;AAGtE,QAAI;AACJ,QAAI,cAAc,WAAW,kBAAkB;AAE7C,oBAAc;AAAA,IAChB,WAAW,cAAc,QAAQ;AAE/B,oBAAc,cAAc;AAC5B,uBAAiB;AAAA,IACnB,OAAO;AAKL,oBAAc,iBAAiB,CAAC,IAAI;AAAA,IAEtC;AAGA,QAAI;AACJ,QAAI,cAAc,WAAW,kBAAkB;AAE7C,oBAAc;AAAA,IAChB,WAAW,cAAc,QAAQ;AAE/B,oBAAc,cAAc;AAC5B,uBAAiB;AAAA,IACnB,OAAO;AAIL,oBAAc,iBAAiB,CAAC,IAAI;AAAA,IAEtC;AAEA,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,gBAAgB;AAAA,IAC3B;AAEA,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,eAAS,KAAK,QAAQ;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,mBAAmB,wBAAwB,OAAO;AAExD,QAAM,WAAW,sBAAsB,OAAO;AAE9C,QAAM,YAAY,mBAAmB,aAAa;AAClD,QAAM,WAAW,mBAAmB,YAAY;AAEhD,SAAO,IAAI,SAAS;AAAA,IAClB,QAAQ,iBAAiB,UAAU,OAAO,UAAU,QAAQ;AAAA,IAC5D;AAAA,IACA,GAAG,eAAe,UAAU,QAAQ;AAAA,IACpC,UAAU;AAAA,MACR,cAAc;AAAA;AAAA;AAAA,MAEd,GAAI,UAAU,kBAAkB,EAAE,gBAAgB,KAAK;AAAA,IACzD;AAAA;AAAA,IAEA,GAAI,SAAS,SAAS,KAAK,EAAE,UAAU,EAAE,UAAU,SAAS,EAAE;AAAA;AAAA;AAAA,IAG9D,GAAI,OAAO,KAAK,SAAS,EAAE,SAAS,KAAK,EAAE,UAAU;AAAA,IACrD,GAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,KAAK,EAAE,SAAS;AAAA;AAAA,IAEnD,GAAI,iBAAiB,SAAS,KAAK;AAAA,MACjC,WAAW;AAAA,QACT,QAAQ;AAAA,MAIV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAKA,eAAe,6BACb,YACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,cAAc,WAAW,WAAW,GAAG;AAC1C,WAAO,CAAC;AAAA,EACV;AAGA,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,QAAM,WAAkC,CAAC;AAEzC,aAAW,aAAa,kBAAkB;AACxC,QAAI,qBAAqB,SAAS,GAAG;AACnC,YAAM,WAAW;AACjB,YAAM,OAAO,SAAS,MAAM;AAI5B,YAAM,cAAc,eAAe,KAAK;AAOxC,eAAS;AAAA,QACP,WAAW,SAAS,MAAM,MAAM,OAAO,WAAW;AAAA,UAChD,OAAO;AAAA,UACP,WAAW,SAAS,MAAM;AAAA;AAAA;AAAA,UAG1B,YACE,MAAM,UACN,kBAAkB,OAAO,YAAY,IAAI,KACzC,cAAc,KAAK,EAAE,KAAK;AAAA,UAC5B,UAAW,MAAM,QAAQ,YAAY,QAAQ;AAAA;AAAA;AAAA,UAG7C,WAAW,MAAM,SAAS,YAAY,SAAS;AAAA,UAC/C,MAAM,MAAM,QAAQ;AAAA,UACpB,QAAQ,MAAM,UAAU;AAAA,UACxB,WAAW,MAAM;AAAA,UACjB,YAAa,MAA8C;AAAA,UAC3D,WAAW,SAAS,MAAM;AAAA,UAC1B,SAAS,SAAS,MAAM;AAAA,UACxB,aAAa,MAAM;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF,WAAW,iBAAiB,SAAS,GAAG;AACtC,YAAM,YAAY;AAElB,UAAI,cAAc,mBAAmB,UAAU,KAAK;AACpD,UAAI,CAAC,aAAa;AAChB,iBAAS;AAAA,UACP,IAAIC,WAAU;AAAA,YACZ,UAAU;AAAA,cACR,IAAIC,SAAQ;AAAA,gBACV,MAAM;AAAA,gBACN,MAAM,cAAc,KAAK,EAAE,KAAK;AAAA,gBAChC,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,YACA,WAAW,UAAU,MAAM,YACvBH,cAAa,UAAU,MAAM,SAAS,IACtC;AAAA,YACJ,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI;AACJ,UAAI;AAEJ,UAAI;AAEF,cAAM,cAAc,MAAM,eAAe,WAAW;AACpD,sBAAc,YAAY;AAC1B,8BAAsB,YAAY;AAAA,MACpC,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,6BAA6B,YAAY,UAAU,GAAG,EAAE,CAAC;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI;AAEF,cAAM,YAAY,aAAa,KAAK;AAGpC,cAAM,kBAAkB,KAAK;AAG7B,cAAM,cAAc,KAAK,MAAM,UAAU,KAAK,QAAQ,eAAe;AACrE,cAAM,iBAAiB,KAAK;AAAA,WACzB,UAAU,KAAK,QACd,UAAU,OAAO,OACjB,UAAU,OAAO,SACjB;AAAA,QACJ;AAGA,cAAM,kBAAkB,UAAU,MAAM,mBAAmB;AAC3D,cAAM,mBAAmB,UAAU,MAAM,oBAAoB;AAC7D,cAAM,mBACJ,oBAAoB,SAAS,cAAc;AAG7C,cAAM,eAAe,KAAK;AAAA,UACxB,UAAU,KAAK,SAAS;AAAA,QAC1B;AACA,cAAM,kBAAkB,KAAK;AAAA,WAC1B,UAAU,KAAK,SACd,UAAU,OAAO,MACjB,UAAU,OAAO,UACjB;AAAA,QACJ;AACA,cAAM,oBACJ,qBAAqB,SAAS,eAAe;AAE/C,cAAM,iBAAiB,KAAK,MAAM,mBAAmB,GAAG;AAGxD,cAAM,cACJ,OAAO,UAAU,MAAM,UAAU,WAC7B,gBAAgB,UAAU,MAAM,OAAO,gBAAgB,IACvD,UAAU,MAAM;AAGtB,cAAM,eACJ,OAAO,UAAU,MAAM,WAAW,WAC9B,gBAAgB,UAAU,MAAM,QAAQ,iBAAiB,IACzD,UAAU,MAAM;AAGtB,cAAM,aAAa,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAGA,cAAM,kBAAkB;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AAEA,cAAM,YAAY,gBAAgB,aAAa,mBAAmB;AAElE,cAAM,WAAW,oBAAoB;AAAA,UACnC,MAAM;AAAA,UACN,MAAM;AAAA,UACN,gBAAgB;AAAA,YACd,OAAO,WAAW;AAAA,YAClB,QAAQ,WAAW;AAAA,UACrB;AAAA,UACA,GAAI,mBAAmB,EAAE,UAAU,gBAAgB;AAAA,QACrD,CAAC;AAED,iBAAS;AAAA,UACP,IAAIE,WAAU;AAAA,YACZ,UAAU,CAAC,QAAQ;AAAA,YACnB,WAAW,UAAU,MAAM,YACvBF,cAAa,UAAU,MAAM,SAAS,IACtC;AAAA,YACJ,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AAId,cAAM,gBAAgB,YAAY,UAAU,GAAG,EAAE;AACjD,gBAAQ;AAAA,UACN,uDAAuD,aAAa;AAAA,UACpE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAC3C;AACA,iBAAS;AAAA,UACP,IAAIE,WAAU;AAAA,YACZ,UAAU;AAAA,cACR,IAAIC,SAAQ;AAAA,gBACV,MAAM,WAAW,aAAa;AAAA,gBAC9B,MAAM,cAAc,KAAK,EAAE,KAAK;AAAA,gBAChC,MAAM;AAAA,gBACN,OAAO,eAAe,KAAK,EAAE;AAAA,gBAC7B,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,YACA,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,WAAW,iBAAiB,SAAS,GAAG;AAGtC,YAAM,SAAS,MAAM,qBAAqB,WAAW,OAAO,SAAS;AACrE,eAAS,KAAK,GAAG,MAAM;AAAA,IACzB,WAAW,kBAAkB,SAAS,GAAG;AAEvC,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,SAAS;AAAA,IAC5B;AAAA,EAEF;AAEA,SAAO;AACT;AAKA,eAAsB,cACpB,SACA,OACA,WACA,SACA,gBACA,eACA,cAAc,OACY;AAC1B,QAAM,WAAoD,CAAC;AAI3D,QAAM,6BAA6B,QAAQ;AAG3C,QAAM,WACJ,QAAQ,wBAAwB,iBAC5B,8BAA8B,iBAAiB,cAAc,IAC7D;AACN,QAAM,eAAe,UAAU;AAC/B,QAAM,oBAAoB,UAAU;AAEpC,QAAM,iBAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,QAAQ;AAAA,MACX,eAAe,QAAQ;AAAA,MACvB,aAAa,QAAQ,WAAW,QAAQ,SAAS;AAAA;AAAA,MAEjD;AAAA,IACF;AAAA,EACF;AAGA,MACE,qBACA,8BACA,iBAAiB,QACjB;AACA,aAAS;AAAA,MACP,IAAID,WAAU;AAAA,QACZ,UAAU,CAAC,IAAIE,eAAc,mBAAmB,YAAY,CAAC;AAAA,QAC7D,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,mBAAmB,QAAQ,WAAW;AAAA,IAC1C,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AACA,aAAW,aAAa,kBAAkB;AACxC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,aAAS,KAAK,GAAG,QAAQ;AAAA,EAC3B;AAGA,MAAI,iBAAiB,iBAAiB,QAAW;AAC/C,aAAS;AAAA,MACP,IAAIF,WAAU;AAAA,QACZ,UAAU,CAAC,IAAIG,aAAY,YAAY,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,UAAU,QAAQ,QAAQ;AACpC,QAAI,QAAQ,UAAU,QAAQ,WAAW,kBAAkB;AACzD,YAAM,mBAAmB,QAAQ;AACjC,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,iBAAiB,WAAW,KAAK,iBAAiB,SAAS,GAAG;AAChE,kBAAU;AAAA,UACR,SAAS,oBAAoB,gBAAgB;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ,UAAU,QAAQ,WAAW,kBAAkB;AACzD,YAAM,mBAAmB,QAAQ;AACjC,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,iBAAiB,WAAW,KAAK,iBAAiB,SAAS,GAAG;AAChE,kBAAU;AAAA,UACR,SAAS,oBAAoB,gBAAgB;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAkC;AAAA,IACtC,YAAY,QAAQ;AAAA,IACpB,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,gBACpB,WACA,OACA,WACA,SAC4D;AAC5D,MAAI,mBAAmB,SAAS,GAAG;AACjC,WAAO,uBAAuB,WAAW,OAAO,SAAS;AAAA,EAC3D,WAAW,qBAAqB,SAAS,GAAG;AAC1C,WAAO,yBAAyB,WAAW,OAAO,SAAS;AAAA,EAC7D,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E,WAAW,iBAAiB,SAAS,GAAG;AACtC,WAAO,MAAM,qBAAqB,WAAW,OAAO,SAAS;AAAA,EAC/D,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E,WAAW,qBAAqB,SAAS,GAAG;AAC1C,WAAO,yBAAyB,WAAW,KAAK;AAAA,EAClD,WAAW,iBAAiB,SAAS,GAAG;AACtC,WAAO,MAAM,qBAAqB,WAAW,OAAO,SAAS;AAAA,EAC/D,WAAW,gBAAgB,SAAS,GAAG;AACrC,WAAO,oBAAoB,WAAW,OAAO,SAAS;AAAA,EACxD,WAAW,eAAe,SAAS,GAAG;AACpC,WAAO,mBAAmB,WAAW,OAAO,OAAO;AAAA,EACrD,WAAW,sBAAsB,SAAS,GAAG;AAC3C,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,kBAAkB,SAAS,GAAG;AACvC,WAAO,MAAM,sBAAsB,WAAW,OAAO,WAAW,OAAO;AAAA,EACzE,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E;AAEA,QAAM,IAAI;AAAA,IACR,2BAA4B,UAAkC,IAAI;AAAA,EACpE;AACF;;;A0CrvBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,eAAsB,qBACpB,UACA,OACA,OACA,UACyB;AACzB,QAAM,OAAO,CAAC,MAAc,YAAoB;AAC9C,QAAI,UAAU;AACZ,eAAS,KAAK;AAAA,QACZ,WAAW;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,SAAS,EAAE,KAAK;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,KAAK,kBAAkB,IAAI,KAAK,OAAO,EAAE;AAAA,IACnD;AAAA,EACF;AAKA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,KAAK,yBAAyB,QAAQ,EAAG,OAAM,IAAI,CAAC;AAC/D,aAAW,KAAK,yBAAyB,KAAgB,EAAG,OAAM,IAAI,CAAC;AACvE,MAAI,MAAM,SAAS,EAAG,QAAO,CAAC;AAK9B,QAAM,aAAa,uBAAuB;AAAA,IACxC,iBAAiB;AAAA,IACjB,mBAAmB,OAAO;AAAA,EAC5B,CAAC;AACD,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,QAAI,OAAO,QAAQ;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,IACE,WAAW,SAAS,IAAI,CAAC,MAAM,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,MAChE;AAAA,IACF;AACA,eAAW,KAAK,WAAW,UAAU;AACnC,WAAK,EAAE,MAAM,EAAE,OAAO;AAAA,IACxB;AAAA,EACF;AAMA,MAAI,CAAC,OAAO,WAAY,QAAO,CAAC;AAEhC,QAAM,WAAW,IAAI,aAAa;AAAA,IAChC,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,WAAW,OAAO,aAAa,WAC3B,IAAI,cAAc,MAAM,YAAY,QAAQ,IAC5C;AAAA,EACN,CAAC;AACD,QAAM,WAAW,MAAM,SAAS,YAAY,KAAK;AACjD,aAAW,KAAK,UAAU;AACxB,eAAW,OAAO,EAAE,UAAU;AAC5B,WAAK,mBAAmB,GAAG;AAAA,IAC7B;AAAA,EACF;AAIA,QAAM,WAAW,QAAQ;AACzB,SAAO;AACT;;;ACrGA,OAAOC,aAAY;AACnB,SAAwB,cAAc;;;ACYtC,OAAO,YAAY;AAIZ,SAAS,4BAA4B,QAAwB;AAClE,QAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,QAAM,gBAAgB,IAAI,SAAS,mBAAmB;AAEtD,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,MAAI,YAAY;AAMhB,QAAM,cAAc,cACjB,QAAQ,EACR,SAAS,MAAM,EACf,QAAQ,kCAAkC,CAAC,QAAQ,WAAmB;AACrE,UAAM,QAAQ;AACd,WAAO,GAAG,MAAM,OAAO,KAAK;AAAA,EAC9B,CAAC;AAEH,MAAI,WAAW,eAAe,OAAO,KAAK,aAAa,MAAM,CAAC;AAC9D,SAAO,IAAI,SAAS;AACtB;;;AD7BO,IAAM,0BAA0B,oBAAI,KAAK,0BAA0B;AAEnE,SAAS,sBAAsB,SAAwC;AAC5E,MAAI,SAAS,gBAAgB,QAAW;AACtC,UAAM,OAAO,IAAI,KAAK,QAAQ,WAAW;AACzC,QAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AAChC,YAAM,IAAI,WAAW,kCAAkC;AAAA,IACzD;AACA,QAAI,KAAK,eAAe,IAAI,MAAM;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,SAAS,kBAAkB,QAC9B,oBAAI,KAAK,IACT,IAAI,KAAK,uBAAuB;AACtC;AAGA,SAAS,UAAU,MAAoB;AACrC,QAAM,WACD,KAAK,eAAe,IAAI,OAAQ,QAAS,IAC1C,KAAK,YAAY,IAAI,KAAM,IAC7B,KAAK,WAAW;AAClB,QAAM,UACH,KAAK,YAAY,KAAK,KACtB,KAAK,cAAc,KAAK,IACxB,KAAK,cAAc,KAAK;AAC3B,UAAS,WAAW,KAAM,aAAa;AACzC;AAOO,SAAS,uBACd,QACA,cAAoB,yBACZ;AACR,QAAM,MAAM,IAAIC,QAAO,MAAM;AAC7B,QAAM,eAAe,YAAY,YAAY;AAC7C,QAAMC,kBAAiB,IAAI,SAAS,mBAAmB;AAEvD,MAAIA,iBAAgB;AAClB,UAAM,aAAaA,gBAChB,QAAQ,EACR,SAAS,MAAM,EACf;AAAA,MACC;AAAA,MACA,KAAK,YAAY;AAAA,IACnB;AACF,QAAI,WAAWA,iBAAgB,OAAO,KAAK,YAAY,MAAM,CAAC;AAAA,EAChE;AASA,QAAM,eAAe,UAAU,WAAW;AAC1C,aAAW,SAAS,IAAI,WAAW,GAAG;AACpC,IAAC,MAAM,OAA0C,UAAU;AAAA,EAC7D;AAEA,SAAO,IAAI,SAAS;AACtB;AAGA,eAAsB,gBACpB,UACA,SACiB;AACjB,QAAM,SAAU,MAAM,OAAO,SAAS,QAAQ;AAC9C,QAAM,QAAQ,4BAA4B,MAAM;AAEhD,MAAI,SAAS,kBAAkB,OAAO;AACpC,WAAO;AAAA,EACT;AAEA,SAAO,uBAAuB,OAAO,sBAAsB,OAAO,CAAC;AACrE;;;AE1FA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACSA,SAAS,mBACd,WACqB;AAErB,MAAI,UAAU,SAAS,WAAW;AAChC,WAAO,0BAA0B,SAAuC;AAAA,EAC1E;AAGA,MAAI,cAAc,aAAa,UAAU,UAAU;AACjD,WAAO;AAAA,MACL,GAAG;AAAA;AAAA,MACH,UAAU,UAAU,SAAS,IAAI,kBAAkB;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,WAAW;AAChC,WAAO,0BAA0B,SAAuC;AAAA,EAC1E;AAGA,SAAO;AACT;AAMA,SAAS,0BACP,WAC4B;AAC5B,QAAM,MAAM,UAAU,SAAU,CAAC;AAGjC,QAAM,mBAAmB,CACvB,MACA,WAEA,KAAK,IAAI,CAAC,GAAG,MAAM;AACjB,UAAM,SAAS,MAAM,KAAK,SAAS;AACnC,QAAI,CAAC,UAAU,EAAE,QAAQ,UAAa,WAAW,QAAW;AAC1D,aAAO,EAAE,GAAG,GAAG,KAAK,OAAO;AAAA,IAC7B;AACA,WAAO;AAAA,EACT,CAAC;AAGH,QAAM,qBAAqB,CACzB,SAEA,KAAK,IAAI,CAAC,OAAO;AAAA,IACf,GAAG;AAAA,IACH,OAAO,EAAE,UAAU,SAAS,SAAY,EAAE;AAAA,EAC5C,EAAE;AAEJ,MAAI;AAEJ,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,UAAU,GAAG;AAEtD,UAAM,IAAI,IAAI;AACd,UAAM,OAAO,MAAM;AAAA,MACjB,EAAE,QAAQ,EAAE;AAAA,MACZ,OAAO,CAAC;AAAA,IACV;AACA,UAAM,cAAc,IAAI,QAAQ,SAAY,IAAI,MAAM;AACtD,mBAAe,iBAAiB,MAAM,WAAW;AAAA,EACnD,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AAErC,mBAAe,IAAI;AAEnB,UAAM,cAAc,IAAI,QAAQ,SAAY,IAAI,MAAM;AACtD,mBAAe,iBAAiB,cAAc,WAAW;AAEzD,mBAAe,mBAAmB,YAAY;AAAA,EAChD,OAAO;AAEL,mBAAe,CAAC,CAAC,CAAC;AAAA,EACpB;AAEA,QAAM,kBAAgC;AAAA,IACpC,SAAS;AAAA,EACX;AAEA,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IACH,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU,UAAU,WAChB,UAAU,SAAS,IAAI,kBAAkB,IACzC;AAAA,EACN;AACF;AAMA,SAAS,0BACP,WAC4B;AAC5B,QAAM,QAAQ,UAAU,SAAU,CAAC;AAEnC,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IACH,OAAO;AAAA,MACL,GAAG;AAAA;AAAA,MACH,QAAQ,MAAM,SACV,MAAM,WAAW,mBACf,mBACA,MAAM,OAAO,IAAI,CAAC,MAA2B,mBAAmB,CAAC,CAAC,IACpE;AAAA,MACJ,QAAQ,MAAM,SACV,MAAM,WAAW,mBACf,mBACA,MAAM,OAAO,IAAI,CAAC,MAA2B,mBAAmB,CAAC,CAAC,IACpE;AAAA,IACN;AAAA,IACA,UAAU,UAAU,WAChB,UAAU,SAAS,IAAI,kBAAkB,IACzC;AAAA,EACN;AACF;AAMO,SAAS,kBACd,UAC6B;AAE7B,MAAI,SAAS,SAAS,QAAQ;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,mBAAmB,QAAQ;AAC9C,SAAO,CAAC,UAAU;AACpB;;;ACpKA,SAAS,YAAYC,WAAU;AAC/B,SAAS,MAAM,WAAAC,UAAS,cAAAC,mBAAkB;AAa1C,eAAsB,mBACpB,UAC8B;AAC9B,MAAI;AAEF,UAAM,eAAeC,YAAW,QAAQ,IAAI,WAAWC,SAAQ,QAAQ;AAGvE,UAAMC,IAAG,OAAO,YAAY;AAG5B,UAAM,cAAc,MAAMA,IAAG,SAAS,cAAc,OAAO;AAG3D,WAAO,yBAAyB,WAAW;AAAA,EAC7C,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,UAAU,OAAO;AAC7C,YAAM,UAAU;AAEhB,cAAQ,QAAQ,MAAM;AAAA,QACtB,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,mBAAmB,QAAQ;AAAA,YAC3B;AAAA,UACF;AAAA,QACF,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,sBAAsB,QAAQ;AAAA,YAC9B;AAAA,UACF;AAAA,QACF,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,wBAAwB,QAAQ;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AACE,gBAAM,IAAI;AAAA,YACR,sBAAsB,QAAQ,OAAO;AAAA,YACrC;AAAA,UACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,iBAAiB,OAAO;AAC1B,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,KAAK,MAAM,OAAO;AAAA,QAC3C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR,yBAAyB,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AA8RO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvB;AAAA,EACA;AAAA,EAEhB,YAAY,SAAiB,MAAc,eAAuB;AAChE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,gBAAgB;AAAA,EACvB;AACF;;;AzD9RO,SAAS,4BACd,YACyC;AACzC,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,MAAM;AAIZ,SAAO,IAAI,SAAS;AACtB;AAMA,eAAsB,iBACpB,UACA,SACmB;AAEnB,MAAI,CAAC,YAAY,SAAS,SAAS,QAAQ;AACzC,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAGA,MAAI,aAAa,UAAU;AACzB,WAAO,MAAM,yBAAyB,UAAU,OAAO;AAAA,EACzD;AAMA,SAAO,MAAM;AAAA,IACX;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,sBAAsB,OAAO;AAAA,IAC7B,SAAS;AAAA,EACX;AACF;AAMA,eAAsB,mBACpB,OACA,YACA,SACmB;AACnB,QAAM,kBAA6C;AAAA,IACjD,MAAM;AAAA,IACN;AAAA,IACA,UAAU;AAAA,EACZ;AAEA,SAAO,MAAM,iBAAiB,iBAAiB,OAAO;AACxD;AAMA,eAAe,iCACb,YACA,cACA,UACA,OACA,UACA,gBACA,SACmB;AAInB,QAAM,EAAE,UAAU,OAAO,UAAU,IAAI,oBAAoB,YAAY;AAAA,IACrE;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAKD,QAAM,qBAAqB,UAAU,OAAO,OAAO,QAAQ;AAG3D,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,SAAS,YAAY,UAAU,UAAU,OAAO,SAAS;AAC/D,QAAM,mBAAmB,MAAM,eAAe,WAAW,QAAQ;AAAA,IAC/D,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAMA,eAAsB,yBACpB,YACA,SACmB;AAKnB,QAAM,aAAa,SAAS;AAC5B,MAAI,YAAY,YAAY,OAAO;AACjC,UAAM,SAAS,sBAAsB,YAAY;AAAA,MAC/C,oBAAoB,YAAY;AAAA,IAClC,CAAC;AACD,QAAI,CAAC,OAAO,OAAO;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,OAAO,eAAe,UAAU;AAClC,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,UAAU;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,IAAI,iBAAiB,uBAAuB;AAAA,QAChD;AAAA,UACE,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,CAAC,kBAAkB,MAAM,GAAG;AAC9B,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,yBAAqB;AAAA,EACvB,OAAO;AAEL,yBAAqB;AAAA,EACvB;AAIA,QAAM,CAAC,eAAe,IAAI,kBAAkB,kBAAkB;AAK9D,SAAO,MAAM;AAAA,IACX;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,sBAAsB,OAAO;AAAA,IAC7B,SAAS;AAAA,EACX;AACF;AAKO,SAAS,mBACd,YAC0B;AAC1B,SAAO,sBAAsB,UAAU;AACzC;AAKA,eAAsB,uBACpB,YACA,SACiB;AACjB,QAAM,WAAW,MAAM,yBAAyB,YAAY,OAAO;AACnE,SAAO,gBAAgB,UAAU,OAAO;AAC1C;AAKA,eAAsB,wBACpB,YACA,UACA,SACe;AACf,QAAM,WAAW,MAAM,yBAAyB,YAAY,OAAO;AACnE,QAAM,aAAa,UAAU,UAAU,OAAO;AAChD;AAKA,eAAsB,yBACpB,UACA,SACmB;AACnB,QAAM,iBAAiB,MAAM,mBAAmB,QAAQ;AAIxD,SAAO,MAAM,yBAAyB,gBAAgB;AAAA,IACpD,SAAS,QAAQC,SAAQ,QAAQ,CAAC;AAAA,IAClC,GAAG;AAAA,EACL,CAAC;AACH;AAKA,eAAsB,uBACpB,UACA,SACiB;AACjB,QAAM,WAAW,MAAM,yBAAyB,UAAU,OAAO;AACjE,SAAO,gBAAgB,UAAU,OAAO;AAC1C;AAKA,eAAsB,wBACpB,eACA,gBACA,SACe;AACf,QAAM,WAAW,MAAM,yBAAyB,eAAe,OAAO;AACtE,QAAM,aAAa,UAAU,gBAAgB,OAAO;AACtD;AAKA,eAAsB,aACpB,UACA,UACA,SACe;AACf,QAAM,SAAS,MAAM,gBAAgB,UAAU,OAAO;AACtD,gBAAc,UAAU,MAAM;AAChC;AAKA,eAAsB,gBACpB,UACA,UACA,SACe;AACf,QAAM,oBAAoB,MAAM,iBAAiB,UAAU,OAAO;AAClE,QAAM,aAAa,mBAAmB,UAAU,OAAO;AACzD;AAaO,IAAM,oBAAoB;AAAA,EAC/B,UAAU;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AACF;;;A0DzWA;AAAA,EACE,kBAAAC;AAAA,EACA,sBAAAC;AAAA,OAGK;AAUP,IAAM,sBAAsB;AAsC5B,eAAsB,eACpB,KACA,SACY;AACZ,MAAI,YAAY,QAAQ;AAExB,MAAI,QAAQ,gBAAgB;AAK1B,UAAM,gBAAgB,MAAM;AAAA,MAC1B;AAAA,MACA;AAAA,QACE,QAAQ,QAAQ;AAAA,QAChB,aAAa,QAAQ;AAAA,QACrB,KAAK,QAAQ;AAAA,MACf;AAAA,MACA,EAAE,SAAS,QAAQ,SAAS,aAAa,QAAQ,YAAY;AAAA,IAC/D,EAAE,MAAM,MAAM,oBAAI,IAAmB,CAAC;AACtC,gBAAY,OAAO,YAAY;AAC7B,YAAM,MAAM,cAAc;AAAA,QACxB,gBAAgB,QAAQ,cAAc,QAAQ,GAAG;AAAA,MACnD;AACA,UAAI,KAAK;AACP,YAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,IAAI,KAAK;AACtC,eAAO;AAAA,UACL,eAAe,IAAI;AAAA,UACnB,OAAO,IAAI;AAAA,UACX,QAAQ,IAAI;AAAA,QACd;AAAA,MACF;AACA,aAAO,QAAQ,UAAU,OAAO;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,MAAkB;AAAA,IACtB;AAAA,IACA,KAAK,QAAQ;AAAA,IACb,SAAS,QAAQ;AAAA,IACjB,OAAO;AAAA,MACL,KAAK,IAAI,GAAG,QAAQ,eAAe,mBAAmB;AAAA,IACxD;AAAA,EACF;AACA,SAAQ,MAAM,YAAY,KAAK,GAAG;AACpC;AAEA,eAAe,gBACb,KACA,KACkC;AAClC,QAAM,QAAQ,IAAI;AAClB,QAAM,MAAMC,gBAAe,MAAM,OAAO,IAAI,OAAOC,mBAAkB;AACrE,QAAM,SAAS,MAAM,IAAI;AAAA,IAAM,MAC7B,IAAI,UAAU;AAAA,MACZ,cAAc,wBAAwB,KAAK;AAAA,MAC3C;AAAA,MACA,SAAS,IAAI;AAAA,IACf,CAAC;AAAA,EACH;AACA,QAAM,QAAiC;AAAA,IACrC,MAAM;AAAA,IACN,OAAO,mBAAmB,OAAO,OAAO,aAAa;AAAA,EACvD;AAEA,MAAI,IAAI,OAAO,OAAW,OAAM,KAAK,IAAI;AACzC,MAAI,IAAI,YAAY,OAAW,OAAM,UAAU,IAAI;AACnD,SAAO;AACT;AAEA,eAAe,YAAY,MAAe,KAAmC;AAC3E,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,QAAQ,IAAI,KAAK,IAAI,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC;AAAA,EACzD;AACA,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,QAAM,MAAM;AAIZ,MAAI,IAAI,SAAS,YAAY,IAAI,SAAS,IAAI,YAAY,OAAO;AAC/D,WAAO,gBAAgB,KAAK,GAAG;AAAA,EACjC;AAEA,QAAM,OAAgC,EAAE,GAAG,IAAI;AAE/C,MAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC/B,SAAK,WAAW,MAAM,YAAY,IAAI,UAAU,GAAG;AAAA,EACrD;AAEA,MAAI,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAC9C,UAAM,QAAQ,IAAI;AAClB,QAAI,eAAe;AACnB,UAAM,YAAqC,EAAE,GAAG,MAAM;AAItD,eAAW,OAAO,CAAC,UAAU,QAAQ,GAAY;AAC/C,UAAI,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG;AAC7B,kBAAU,GAAG,IAAI,MAAM,YAAY,MAAM,GAAG,GAAG,GAAG;AAClD,uBAAe;AAAA,MACjB;AAAA,IACF;AAIA,QAAI,MAAM,QAAQ,MAAM,OAAO,GAAG;AAChC,gBAAU,UAAU,MAAM,QAAQ;AAAA,QAC/B,MAAM,QAAsB,IAAI,CAAC,QAAQ,cAAc,KAAK,GAAG,CAAC;AAAA,MACnE;AACA,qBAAe;AAAA,IACjB;AAEA,QAAI,aAAc,MAAK,QAAQ;AAAA,EACjC;AAEA,SAAO;AACT;AAEA,eAAe,cAAc,KAAc,KAAmC;AAC5E,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,SAAS;AACf,QAAM,UAAmC,EAAE,GAAG,OAAO;AAErD,QAAM,SAAS,OAAO;AACtB,MAAI,UAAU,OAAO,WAAW,YAAY,aAAa,QAAQ;AAC/D,YAAQ,SAAS;AAAA,MACf,GAAG;AAAA,MACH,SAAS,MAAM,YAAY,OAAO,SAAS,GAAG;AAAA,IAChD;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/B,YAAQ,QAAQ,MAAM,QAAQ;AAAA,MAC3B,OAAO,MAAoB,IAAI,OAAO,SAAS;AAC9C,YAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,MAAM;AACzD,gBAAM,IAAI;AACV,iBAAO,EAAE,GAAG,GAAG,SAAS,MAAM,YAAY,EAAE,SAAS,GAAG,EAAE;AAAA,QAC5D;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;AC1MO,SAAS,yBACd,UACkC;AAClC,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,WAAkC;AAAA,IACtC;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,QACL,MAAM,GAAG,SAAS,MAAM;AAAA,QACxB,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,sBAAsB,oBAAI,IAAiC;AACjE,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,oBAAoB,IAAI,QAAQ,SAAS,KAAK,CAAC;AAChE,aAAS,KAAK,OAAO;AACrB,wBAAoB,IAAI,QAAQ,WAAW,QAAQ;AAAA,EACrD;AAGA,aAAW,CAAC,eAAe,iBAAiB,KAAK,oBAAoB,QAAQ,GAAG;AAC9E,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,MAAM,cAAc,aAAa;AAAA,MACnC;AAAA,IACF,CAAC;AAGD,UAAM,eAAyB,CAAC;AAChC,eAAW,WAAW,mBAAmB;AACvC,UAAI,cAAc,QAAQ;AAG1B,UAAI,QAAQ,WAAW,OAAO,KAAK,QAAQ,OAAO,EAAE,SAAS,GAAG;AAC9D,cAAM,aAAa,OAAO,QAAQ,QAAQ,OAAO,EAC9C,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AACZ,uBAAe,KAAK,UAAU;AAAA,MAChC;AAEA,mBAAa,KAAK,WAAW;AAAA,IAC/B;AAEA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,UAAU;AAAA,QACR,OAAO;AAAA,MACT;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAMO,SAAS,mBACd,UACQ;AACR,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB;AAAA,IACtB,iCAAiC,SAAS,MAAM;AAAA,IAChD,IAAI,OAAO,EAAE;AAAA,IACb;AAAA,EACF;AAGA,QAAM,sBAAsB,oBAAI,IAAiC;AACjE,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,oBAAoB,IAAI,QAAQ,SAAS,KAAK,CAAC;AAChE,aAAS,KAAK,OAAO;AACrB,wBAAoB,IAAI,QAAQ,WAAW,QAAQ;AAAA,EACrD;AAEA,aAAW,CAAC,eAAe,iBAAiB,KAAK,oBAAoB,QAAQ,GAAG;AAC9E,UAAM,KAAK,cAAc,aAAa,EAAE;AACxC,UAAM,KAAK,IAAI,OAAO,EAAE,CAAC;AAEzB,aAAS,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK;AACjD,YAAM,UAAU,kBAAkB,CAAC;AACnC,YAAM,KAAK,KAAK,IAAI,CAAC,KAAK,QAAQ,OAAO,EAAE;AAE3C,UAAI,QAAQ,WAAW,OAAO,KAAK,QAAQ,OAAO,EAAE,SAAS,GAAG;AAC9D,cAAM,KAAK,iBAAiB,KAAK,UAAU,QAAQ,SAAS,MAAM,CAAC,CAAC,EAAE;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC3BA;AASA;;;AClHA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,iBAAAC,sBAAqB;AAG9B,IAAI,WAA0B;AAE9B,SAAS,aAAqB;AAC5B,MAAI,aAAa,MAAM;AACrB,QAAI;AACF,iBAAWD,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC;AAAA,IACxD,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,gBAAgB,MAAmC;AAGjE,QAAM,WAAWD,MAAK;AAAA,IACpB,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG,IAAI;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAUD,IAAG,aAAa,UAAU,MAAM;AAChD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,gCAAgC,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAClG;AAAA,EACF;AACF;AAKO,SAAS,2BAAqC;AAGnD,QAAM,cAAcC,MAAK,KAAK,WAAW,GAAG,aAAa,WAAW;AAEpE,MAAI;AACF,UAAM,QAAQD,IAAG,YAAY,WAAW;AACxC,WAAO,MACJ,OAAO,CAAC,SAAS,KAAK,SAAS,YAAY,CAAC,EAC5C,IAAI,CAAC,SAASC,MAAK,SAAS,MAAM,YAAY,CAAC,EAC/C,KAAK;AAAA,EACV,SAAS,OAAO;AACd,YAAQ,KAAK,2CAA2C,KAAK;AAC7D,WAAO,CAAC;AAAA,EACV;AACF;AAgBA,IAAM,gBAAqD,CAAC;AAErD,IAAM,WAAW,IAAI,MAAM,CAAC,GAA0C;AAAA,EAC3E,IAAI,SAAS,MAAc;AACzB,QAAI,CAAC,cAAc,IAAI,GAAG;AACxB,UAAI;AACF,sBAAc,IAAI,IAAI,gBAAgB,IAAI;AAAA,MAC5C,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAAS;AACf,WAAO,yBAAyB;AAAA,EAClC;AAAA,EAEA,IAAI,SAAS,MAAc;AACzB,WAAO,yBAAyB,EAAE,SAAS,IAAI;AAAA,EACjD;AACF,CAAC;AAKM,IAAM,aAAa,CACxB,gBACoC;AACpC,SAAO,SAAS,WAAW;AAC7B;AAKO,IAAM,kBAAkB,MAAgB;AAC7C,SAAO,yBAAyB;AAClC;;;AChHA,YAAYE,WAAU;AACtB,YAAYC,SAAQ;AAapB,eAAsB,WACpB,SACA,UAAgC,CAAC,GAClB;AACf,QAAM,EAAE,gBAAgB,WAAW,UAAU,KAAK,IAAI;AAEtD,MAAI,CAAC,QAAQ,OAAO;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,QAAM,cAAc,OAAO,QAAQ,MAAM,UAAU,KAAK,KAAK;AAC7D,QAAM,eACJ,kBAAkB,GAAG,YAAY,YAAY,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAGrE,QAAM,mBAAwB,WAAK,QAAQ,IAAI,GAAG,UAAU,UAAU;AACtE,QAAM,iBAAiB,aAAa;AACpC,QAAM,WAAgB,WAAK,gBAAgB,YAAY;AAEvD,MAAI,SAAS;AACX,YAAQ,IAAI,OAAO,WAAW;AAAA,CAAmB;AACjD,YAAQ,IAAI,cAAc,WAAW,yBAAyB;AAAA,EAChE;AAEA,MAAI;AAEF,UAAS,aAAS,MAAM,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAE3D,UAAM,WAAW,MAAM,iBAAiB,OAAO;AAC/C,UAAM,aAAa,UAAU,QAAQ;AAErC,QAAI,SAAS;AACX,cAAQ,IAAI,UAAK,WAAW,WAAW,QAAQ,EAAE;AACjD,cAAQ,IAAI;AAAA,SAAO,WAAW,0BAA0B;AAAA,IAC1D;AAAA,EACF,SAAS,OAAO;AACd,QAAI,SAAS;AACX,cAAQ,MAAM,GAAG,WAAW,uBAAuB,KAAK;AAAA,IAC1D;AACA,UAAM;AAAA,EACR;AACF;;;ACzDA;;;ACLA,SAAS,+BAA+B;;;ACIxC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE,oBAAoB;AAAA,OAEf;AAIP;AAAA,EACE;AAAA,EACA,4BAAAC;AAAA,EACA;AAAA,OACK;AAMA,SAAS,uBACd,QACA,OACA,eACA,MACyC;AAKzC,SAAO,6BAA2C,OAAO,aAAa,OAAO;AAAA,IAC3E,OAAO,MAAM,SAAS;AAAA,IACtB,eAAe,MAAM,iBAAiB;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWO,SAAS,iBACd,UACA,kBACA,SACyC;AACzC,QAAM,mBAAmB,IAAI,IAAI,iBAAiB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAGpE,QAAM,iBAAiB,wBAAwB,UAAU;AAAA,IACvD;AAAA,IACA,oBAAoB,SAAS;AAAA,EAC/B,CAAC;AAGD,QAAM,SAA4B,CAAC,GAAI,eAAe,UAAU,CAAC,CAAE;AAEnE,WAAS,mBAAmB,YAAmB,aAAa,YAAY;AACtE,eAAW,QAAQ,CAAC,eAAe,UAAU;AAC3C,YAAM,kBAAkB,iBAAiB;AAAA,QACvC,CAAC,OAAO,GAAG,SAAS,cAAc;AAAA,MACpC;AACA,UAAI,CAAC,iBAAiB;AACpB;AAAA,MACF;AAEA,YAAM,eAAe;AAAA,QACnB,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,cAAc;AAAA,MAChB;AAEA,YAAM,aAAa;AAAA,QACjB;AAAA,QACA,cAAc;AAAA,QACd,gBAAgB;AAAA;AAAA,QAEhB,EAAE,OAAO,SAAS,uBAAuB,KAAK;AAAA,MAChD;AAEA,UAAI,CAAC,WAAW,SAAS,WAAW,QAAQ;AAC1C,cAAM,gBAAgB,WAAW,OAAO;AAAA,UACtC,CAAC,WAA4B;AAAA,YAC3B,GAAG;AAAA,YACH,MAAM,GAAG,UAAU,IAAI,KAAK,KAAK,MAAM,IAAI;AAAA,UAC7C;AAAA,QACF;AACA,eAAO,KAAK,GAAG,aAAa;AAAA,MAC9B;AAEA,UAAI,cAAc,YAAY,MAAM,QAAQ,cAAc,QAAQ,GAAG;AACnE;AAAA,UACE,cAAc;AAAA,UACd,GAAG,UAAU,IAAI,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,uBAAmB,SAAS,QAAQ;AAAA,EACtC;AAEA,SAAO,OAAO,SAAS,IACnB,EAAE,SAAS,OAAO,QAAQ,OAAO,MAAM,IACvC,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAC/C;AAKO,SAAS,kBACd,QACA,OACsB;AACtB,QAAM,aAAa,uBAAuB,QAAQ,KAAK;AAEvD,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI,yBAAyB,WAAW,UAAU,CAAC,GAAG,KAAK;AAAA,EACnE;AAEA,SAAO,WAAW;AACpB;AAMO,IAAM,sBAAsB;;;AF/GnC,SAAS,kCAAAC,uCAAsC;;;AG5B/C,SAAS,QAAAC,aAA8B;AACvC,SAAS,qBAAqB;AAE9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qCAAqC;AAG9C,IAAM,cAAc,oBAAI,IAAqB;AAQtC,SAAS,6BACd,kBACA,4BAA4B,MACnB;AAET,QAAM,uBAAuB,iBAAiB,IAAI,CAAC,cAAc;AAC/D,UAAM,cAAc,OAAO,KAAK,UAAU,QAAQ;AAGlD,UAAM,iBAAiB,YAAY,IAAI,CAAC,OAAO;AAAA,MAC7C,SAAS;AAAA,MACT,aAAa,UAAU,SAAS,CAAC,EAAE;AAAA,MACnC,aAAa,UAAU,SAAS,CAAC,EAAE,gBAAgB;AAAA,MACnD,aAAa,UAAU,SAAS,CAAC,EAAE;AAAA,IACrC,EAAE;AAGF,UAAM,YAAY,YAAY,OAAO,CAAC,GAAG,MAAO,IAAI,IAAI,IAAI,CAAE;AAE9D,WAAO;AAAA,MACL,MAAM,UAAU;AAAA,MAChB,aAAa,UAAU,SAAS,SAAS,EAAE;AAAA,MAC3C,aAAa,YAAY;AAAA,QACvB,CAAC,MAAM,UAAU,SAAS,CAAC,EAAE,gBAAgB;AAAA,MAC/C;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,8BAA8B;AAAA,IACnC;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACH;AAkBA,eAAsB,mBACpB,kBACA,YACA,UAGI,CAAC,GACU;AACf,QAAM,EAAE,4BAA4B,MAAM,cAAc,KAAK,IAAI;AAEjE,QAAM,EAAE,qBAAqB,mBAAmB,IAAI,MAAM,OACxD,4CACF;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAEA,QAAM,aAAa,oBAAoB,QAAQ;AAAA,IAC7C,SAAS;AAAA,EACX,CAAC;AAED,QAAM,mBAAmB,YAAY,YAAY,EAAE,YAAY,CAAC;AAClE;AAMO,SAAS,yBACd,kBACyB;AACzB,QAAM,UAAmC,CAAC;AAE1C,aAAW,aAAa,kBAAkB;AACxC,UAAM,cAAc,OAAO,KAAK,UAAU,QAAQ;AAClD,UAAM,SAAS,cAAc,WAAW;AAExC,eAAW,KAAK,aAAa;AAC3B,YAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,YAAM,WAAW,aAAa,UAAU,IAAI,IAAI,CAAC;AAEjD,UAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,gBAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,EAAE,IAAI,YAAY,IAAI,QAAQ;AAAA,MAC9D,OAAO;AACL,cAAM,YAAY,MAAM;AACxB,cAAM,aAAa,UAAU,cAAc,CAAC;AAE5C,cAAM,uBAAgD;AAAA,UACpD,MAAMC,MAAK,QAAQ,UAAU,IAAI;AAAA,UACjC,SAASA,MAAK,SAASA,MAAK,QAAQ,CAAC,CAAC;AAAA,UACtC,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,UAC/B,GAAG;AAAA,QACL;AAEA,YAAI,MAAM,aAAa;AACrB,+BAAqB,WAAWA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,QACtE;AAEA,cAAM,kBAAkBA,MAAK,OAAO,oBAAoB;AACxD,oBAAY,IAAI,UAAU,eAAe;AACzC,gBAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,EAAE,IAAI;AAAA,MACtC;AAAA,IACF;AAGA,UAAM,cAAc,UAAU,SAAS,MAAM;AAC7C,UAAM,kBAAkB,aAAa,UAAU,IAAI;AAEnD,QAAI,YAAY,IAAI,eAAe,GAAG;AACpC,cAAQ,UAAU,IAAI,IAAI,YAAY,IAAI,eAAe;AAAA,IAC3D,OAAO;AACL,YAAM,YAAY,YAAY;AAC9B,YAAM,aAAa,UAAU,cAAc,CAAC;AAE5C,YAAM,uBAAgD;AAAA,QACpD,MAAMA,MAAK,QAAQ,UAAU,IAAI;AAAA,QACjC,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,QAC/B,GAAG;AAAA,MACL;AAEA,UAAI,YAAY,aAAa;AAC3B,6BAAqB,WAAWA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,MACtE;AAEA,YAAM,kBAAkBA,MAAK,OAAO,oBAAoB;AACxD,kBAAY,IAAI,iBAAiB,eAAe;AAChD,cAAQ,UAAU,IAAI,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,aACd,kBACA,iBACyB;AACzB,QAAM,gBAAgB,yBAAyB,gBAAgB;AAE/D,MAAI,iBAAiB;AACnB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAEA,QAAM,yBAAkD;AAAA,IACtD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,UAAUA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,IAChD,CAAC;AAAA,IACD,SAASA,MAAK,OAAO;AAAA,MACnB,MAAMA,MAAK,QAAQ,SAAS;AAAA,MAC5B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,UAAUA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,IAChD,CAAC;AAAA,IACD,SAASA,MAAK,OAAO;AAAA,MACnB,MAAMA,MAAK,QAAQ,SAAS;AAAA,MAC5B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,OAAOA,MAAK,OAAO;AAAA,MACjB,MAAMA,MAAK,QAAQ,OAAO;AAAA,MAC1B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,OAAOA,MAAK,OAAO;AAAA,MACjB,MAAMA,MAAK,QAAQ,OAAO;AAAA,MAC1B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;;;AHzIA,SAAS,kBAEP,OAA4D;AAE5D,QAAM,eAAe,IAAI,IAAI,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAcrE,WAAS,qBACP,WACA,UACA,UACa;AACb,QAAI,MAAM,cAAc;AACtB,UAAI,MAAM,aAAa,SAAS,GAAG;AACjC,eAAO,MAAM,aAAa,SAAS;AAAA,MACrC;AACA,YAAM,MAAM,OAAO,KAAK,MAAM,YAAY,EAAE;AAAA,QAC1C,CAAC,MAAM,EAAE,YAAY,MAAM,UAAU,YAAY;AAAA,MACnD;AACA,UAAI,KAAK;AACP,eAAO,MAAM,aAAa,GAAG;AAAA,MAC/B;AAAA,IACF;AACA,QAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAO,oBAAoB,WAAW;AAAA,QACpC,cAAc,MAAM;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,MAAM,OAAO;AACf,aAAO,MAAM;AAAA,IACf;AACA,WAAO,oBAAoB,WAAW;AAAA,MACpC,cAAc,MAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAaA,iBAAe,0BACb,YACA,aACA,mBACA,eACA,iBAGA,QAAQ,GAIP;AACD,QAAI,QAAQ,IAAI;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,cAAqC,CAAC;AAC5C,UAAM,eAAsC,CAAC;AAE7C,eAAW,iBAAiB,YAAY;AAEtC,YAAM,gBAAiB,eAAqC;AAE5D,UAAI,CAAC,eAAe;AAClB,oBAAY,KAAK,aAAa;AAC9B,qBAAa,KAAK,aAAa;AAC/B;AAAA,MACF;AAEA,YAAM,kBAAkB,aAAa,IAAI,aAAa;AAEtD,UAAI,iBAAiB;AAEnB,YAAI;AACF,gBAAM,oBAAoB;AAO1B,cAAI,CAAC,kBAAkB,OAAO;AAC5B,kBAAM,IAAI;AAAA,cACR,qBAAqB,aAAa,wDAAwD,aAAa;AAAA,YACzG;AAAA,UACF;AAGA,gBAAM,eAAe;AAAA,YACnB,gBAAgB;AAAA,YAChB,gBAAgB;AAAA,YAChB,kBAAkB;AAAA,UACpB;AAGA,gBAAM,eAAe;AAAA,YACnB;AAAA,YACA,kBAAkB;AAAA,UACpB;AAIA,cAAI;AACJ,cACE,kBAAkB,YAClB,MAAM,QAAQ,kBAAkB,QAAQ,GACxC;AACA,kBAAM,SAAS,MAAM;AAAA,cACnB,kBAAkB;AAAA,cAClB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,YACV;AACA,6BAAiB,OAAO;AAAA,UAC1B;AAGA,gBAAM,eAAe,kBAAkB,UACnC,GAAG,gBAAgB,IAAI,IAAI,kBAAkB,OAAO,KACpD,gBAAgB;AAEpB,gBAAM,aAAa,CACjB,SACA,YACG;AACH,8BAAkB,KAAK;AAAA,cACrB,WAAW;AAAA,cACX;AAAA,cACA,UAAU;AAAA,cACV;AAAA,YACF,CAAC;AAAA,UACH;AAGA,gBAAM,SAAS,MAAM,aAAa,OAAO;AAAA,YACvC,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,YACA,UAAU;AAAA,UACZ,CAAC;AAGD,gBAAM,mBACJ,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAQ1C,cAAI,iBAAiB;AACnB,4BAAgB,kBAAkB,YAAY;AAAA,UAChD;AAGA,gBAAM,kBAAkB,MAAM;AAAA,YAC5B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,sBAAY,KAAK,GAAG,gBAAgB,QAAQ;AAE5C,cAAI,eAAe,YAAY,IAAI,aAAa,GAAG;AAIjD,yBAAa,KAAK,aAAa;AAAA,UACjC,OAAO;AAGL,yBAAa,KAAK,GAAG,gBAAgB,SAAS;AAAA,UAChD;AAEA,cAAI,MAAM,OAAO;AACf,oBAAQ;AAAA,cACN,+BAA+B,YAAY;AAAA,cAC3C,gBAAgB;AAAA,YAClB;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,cAAI,iBAAiBC,2BAA0B;AAC7C,kBAAM;AAAA,UACR;AACA,gBAAM,IAAI;AAAA,YACR,sCAAsC,gBAAgB,IAAI,MACxD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YACE,cAAc,iBACd,MAAM,QAAQ,cAAc,QAAQ,GACpC;AACA,gBAAM,kBAAkB,MAAM;AAAA,YAC5B,cAAc;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,sBAAY,KAAK;AAAA,YACf,GAAG;AAAA,YACH,UAAU,gBAAgB;AAAA,UAC5B,CAAC;AACD,uBAAa,KAAK;AAAA,YAChB,GAAG;AAAA,YACH,UAAU,gBAAgB;AAAA,UAC5B,CAAC;AAAA,QACH,OAAO;AACL,sBAAY,KAAK,aAAa;AAC9B,uBAAa,KAAK,aAAa;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,aAAa,WAAW,aAAa;AAAA,EAC1D;AAKA,WAAS,aACP,WACoE;AACpE,QAAI,CAAC,UAAU,MAAM;AACnB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,QAAI,MAAM,eAAe,IAAI,UAAU,IAAI,GAAG;AAC5C,YAAM,IAAI,wBAAwB,UAAU,IAAI;AAAA,IAClD;AAGA,UAAM,oBAAoB,IAAI,IAAI,MAAM,cAAc;AACtD,sBAAkB,IAAI,UAAU,IAAI;AAEpC,UAAM,WAAyB;AAAA,MAC7B,YAAY,CAAC,GAAG,MAAM,YAAY,SAAS;AAAA,MAC3C,gBAAgB;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,MAClB,eAAe,MAAM;AAAA,MACrB,aAAa,MAAM;AAAA,MACnB,SAAS,MAAM;AAAA,IACjB;AAGA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAOA,WAAS,mBACP,SACiC;AACjC,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AACA,UAAM,aAAa,IAAI,IAAI,MAAM,cAAc;AAC/C,UAAM,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;AACrD,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAIC;AAAA,QACR;AAAA,QACA,MAAM,KAAK,MAAM,cAAc;AAAA,MACjC;AAAA,IACF;AACA,WAAO,IAAI,IAAI,IAAI;AAAA,EACrB;AAQA,iBAAe,eACb,UACA,SAYC;AACD,UAAM,cAAc,mBAAmB,OAAO;AAO9C,UAAM,SAAS;AACf,UAAM,mBACJ,OAAO,UAAU,SAAY,EAAE,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI;AAK1D,UAAM,QAAqC;AAAA,MACzC,GAAG,MAAM;AAAA,MACT,GAAG,SAAS;AAAA,IACd;AACA,QAAI,MAAM,YAAY,OAAO;AAC3B,YAAM,SAAS;AAAA,QACb;AAAA,QACA,MAAM;AAAA,QACN,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,MACjD;AACA,UAAI,CAAC,OAAO,OAAO;AACjB,cAAM,IAAID;AAAA,WACP,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,YAChC,MAAM,EAAE,QAAQ;AAAA,YAChB,SAAS,EAAE;AAAA,UACb,EAAE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAUA,UAAM,kBACJ,MAAM,YAAY,QACd,SACA,CAAC,SAAgC,mBAA2B;AAC1D,YAAM,SAAS;AAAA,QACb,EAAE,GAAG,kBAAkB,UAAU,QAAQ;AAAA,QACzC,MAAM;AAAA,QACN,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,MACjD;AACA,UAAI,CAAC,OAAO,OAAO;AACjB,cAAM,IAAIA;AAAA,WACP,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,YAChC,MAAM,EAAE,QAAQ;AAAA,YAChB,SAAS,qBAAqB,cAAc,mCAA8B,EAAE,OAAO;AAAA,UACrF,EAAE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGN,UAAM,WAAgC,CAAC;AASvC,UAAM;AAAA,MACJ,UAAU;AAAA,MACV,OAAO;AAAA,MACP;AAAA,IACF,IAAI,oBAAoB,kBAAkB;AAAA,MACxC,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb;AAAA,MACA,mBAAmB;AAAA,IACrB,CAAC;AAID,UAAM,YAAY,MAAM;AAAA,MACtB,UAAU,YAAY,CAAC;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,oBAA+C;AAAA,MACnD,GAAG;AAAA,MACH,UAAU,UAAU;AAAA,IACtB;AAIA,UAAM,CAAC,QAAQ,IAAI,kBAAkB,iBAAiB;AAEtD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAUA,iBAAe,yBACb,UACA,SACmC;AACnC,QAAI;AACF,YAAM,EAAE,UAAU,SAAS,IAAI,MAAM,eAAe,UAAU,OAAO;AACrE,aAAO;AAAA,QACL,oBAAoB;AAAA,QACpB,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,MAC7C;AAAA,IACF,SAAS,OAAO;AACd,UAAI,MAAM,OAAO;AACf,gBAAQ,MAAM,6BAA6B,KAAK;AAAA,MAClD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAKA,iBAAe,SACb,UACA,SACwC;AACxC,QAAI;AACF,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI,MAAM,eAAe,UAAU,OAAO;AAM1C,YAAM,qBAAqB,UAAU,YAAY,MAAM,OAAO,QAAQ;AAGtE,YAAM,iBAAiB;AAAA,QACrB,eAAe,SAAS,iBAAiB,MAAM;AAAA,QAC/C,aAAa,SAAS,eAAe,MAAM;AAAA,MAC7C;AACA,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,cAAc;AAAA,MACtC;AACA,YAAM,SAAS,YAAY,UAAU,UAAU,YAAY,SAAS;AACpE,YAAM,oBAAoB,MAAM,eAAe,WAAW,QAAQ;AAAA,QAChE,UAAU,MAAM;AAAA,QAChB,aAAa,CAAC,MAAM;AAAA,QACpB,SAAS,SAAS,WAAW,MAAM;AAAA,MACrC,CAAC;AAKD,YAAM,sBAAsB,cACvB;AAAA,QACC,GAAG;AAAA,QACH,UAAU,UAAU;AAAA,MACtB,IACA;AAEJ,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,QAC3C,oBAAoB;AAAA,QACpB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,MAAM,OAAO;AACf,gBAAQ,MAAM,8BAA8B,KAAK;AAAA,MACnD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAKA,iBAAe,eACb,UACA,SAC8C;AAC9C,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,MAAM,SAAS,UAAU,OAAO;AACpC,UAAM,SAAS,MAAM,gBAAgB,KAAK;AAAA,MACxC,eAAe,SAAS,iBAAiB,MAAM;AAAA,MAC/C,aAAa,SAAS,eAAe,MAAM;AAAA,IAC7C,CAAC;AACD,WAAO,EAAE,QAAQ,UAAU,oBAAoB,oBAAoB;AAAA,EACrE;AAKA,iBAAe,aACb,UACA,YACA,SAC4C;AAC5C,UAAM,EAAE,QAAQ,UAAU,oBAAoB,oBAAoB,IAChE,MAAM,eAAe,UAAU,OAAO;AACxC,UAAME,MAAK,MAAM,OAAO,aAAa;AACrC,UAAMA,IAAG,UAAU,YAAY,IAAI,WAAW,MAAM,CAAC;AAErD,QAAI;AACJ,QAAI,wBAAwB,QAAW;AACrC,YAAMC,QAAO,MAAM,OAAO,MAAM;AAChC,4BACE,SAAS,wBACR,MAAM;AACL,cAAM,MAAMA,MAAK,QAAQ,UAAU;AACnC,cAAM,OAAO,MAAM,WAAW,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI;AACtD,eAAO,GAAG,IAAI;AAAA,MAChB,GAAG;AACL,YAAMD,IAAG;AAAA,QACP;AAAA,QACA,KAAK,UAAU,qBAAqB,MAAM,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAKA,WAAS,oBAA8B;AACrC,WAAO,MAAM,KAAK,MAAM,cAAc;AAAA,EACxC;AAKA,WAAS,SACP,UACkB;AAClB,QAAI;AAEF,YAAM,mBAAmB;AACzB,YAAM,SAAS;AAAA,QACb;AAAA,QACA,MAAM;AAAA,MACR;AACA,UAAI,OAAO,OAAO;AAChB,eAAO,EAAE,OAAO,KAAK;AAAA,MACvB;AACA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,UACxC,MAAM,EAAE,QAAQ;AAAA,UAChB,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,MACJ;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,UACN;AAAA,YACE,MAAM;AAAA,YACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAQA,iBAAe,gCACb,UACoC;AACpC,UAAM,EAAE,mBAAmB,IAAI,MAAM,SAAS,QAAQ;AACtD,WAAO;AAAA,EACT;AAKA,WAAS,eAAe,4BAA4B,MAAe;AACjE,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAKA,iBAAe,mBACb,YACA,SAIe;AACf,UAAM;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAKO,SAAS,wBACd,SACuC;AACvC,QAAM,eAA6B;AAAA,IACjC,YAAY,CAAC;AAAA,IACb,gBAAgB,oBAAI,IAAI;AAAA,IACxB,OAAO,QAAQ;AAAA,IACf,cAAc,QAAQ;AAAA,IACtB,OAAO,QAAQ,SAAS;AAAA,IACxB,aAAa,QAAQ,eAAe;AAAA,IACpC,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ,iBAAiB;AAAA,IACxC,aAAa,QAAQ;AAAA,IACrB,SAAS,QAAQ;AAAA,EACnB;AAEA,SAAO,kBAA+B,YAAY;AACpD;;;AH3yBO,SAAS,iBAAyB;AACvC,SAAO;AACT;","names":["themes","path","fs","path","isValidThemeConfig","resolve","mergeWithDefaults","mergeWithDefaults","Paragraph","TextRun","AlignmentType","BookmarkStart","BookmarkEnd","path","createHash","TextRun","TextRun","TextRun","createTextRunsWithNewlines","TextRun","AsyncLocalStorage","AsyncLocalStorage","TextRun","createHash","Paragraph","TextRun","AlignmentType","BorderStyle","PageNumber","AsyncLocalStorage","TextRun","TextRun","AsyncLocalStorage","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","AsyncLocalStorage","text","format","Table","TableRow","TableCell","WidthType","TableLayoutType","BorderStyle","convertBorders","Paragraph","Paragraph","convertBorders","cellChildren","childContext","styleCfg","cellOpts","row","TableRow","TableCell","table","Table","TableLayoutType","WidthType","config","Paragraph","AsyncLocalStorage","createState","Paragraph","Paragraph","Table","TableRow","TableCell","WidthType","BorderStyle","VerticalAlign","TableLayoutType","Paragraph","TableCell","WidthType","VerticalAlign","BorderStyle","TableRow","Table","TableLayoutType","Paragraph","AlignmentType","TextRun","createHash","createHash","clampVisualDpi","DEFAULT_VISUAL_DPI","resolve","serverUrl","clampVisualDpi","DEFAULT_VISUAL_DPI","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","ComponentValidationError","UnknownPreservedComponentError","Type","Type","ComponentValidationError","UnknownPreservedComponentError","fs","path"]}
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/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/components/heading.ts","../src/utils/numberingConfig.ts","../src/components/paragraph.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/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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 \"heading\": {\n \"numbering\": 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 ...(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 Textbox,\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 getBaseDir,\n} from '../utils/generationContext';\nimport { prerasterizeVisuals } from './prerasterizeVisuals';\nimport { computeSectionOrdinals } from './sectionOrdinals';\nimport { collectTocHeadings } from './collectTocHeadings';\nimport { globalSectionBookmarkRegistry } from './sectionBookmarks';\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\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 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 renderDocumentScoped(structure, layout, options)\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 // Collect TOC entries before rendering so a TOC field can carry cached\n // content for readers that never refresh fields (#174). Same\n // catch-and-degrade discipline as the visual pre-pass: a failure here costs\n // the cached entries, never the document.\n try {\n const tocHeadings = collectTocHeadings(layout.sections);\n if (tocHeadings.length > 0) {\n context.tocHeadings = tocHeadings;\n }\n } catch (error) {\n console.warn(\n '[core-docx] TOC entry 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 = 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 | Textbox)[]> {\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 { resolveFromBaseDir } from './generationContext';\nimport { ImageRun, IFloating } from 'docx';\nimport { parsePercentageStringToFraction } from './widthUtils';\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 * TODO: SVG fallback uses raw SVG as PNG — works in Word 2016+ which renders\n * SVG natively; fallback won't render correctly in older versions.\n */\nexport function createTypedImageRun(opts: {\n type: 'jpg' | 'png' | 'gif' | 'bmp' | 'svg';\n data: Buffer;\n transformation: { width: number; height: number };\n floating?: IFloating;\n}): 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 return new ImageRun({\n type: 'svg',\n ...base,\n fallback: { type: 'png', data: 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';\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","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} 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\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 Tab,\n} from 'docx';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n type PlaceholderContext,\n} from './placeholderProcessor';\nimport { normalizeUnicodeText } from './unicode';\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 * Parse text with hyperlinks and decorators\n * Supports markdown-style links: [link text](url)\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 // Regex to match markdown-style links: [text](url)\n // This regex handles nested brackets in the link text\n const hyperlinkRegex = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = hyperlinkRegex.exec(normalizedText)) !== null) {\n // Add any text before the hyperlink\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 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 lastIndex = match.index + match[0].length;\n }\n\n // Add any remaining text after the last hyperlink\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 hyperlinks 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 * 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, Textbox } 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 | Textbox)[]> {\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 | Textbox)[];\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 Bookmark,\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} from '../utils/textParser';\nimport {\n processTextWithPlaceholders,\n type PlaceholderChild,\n} from '../utils/placeholderProcessor';\nimport { normalizeUnicodeText } from '../utils/unicode';\nimport { getStyleIdForLevel } from '../styles/themeToDocxAdapter';\nimport { globalBookmarkRegistry } 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 // 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 new Bookmark({\n id: options.bookmarkId,\n children: revisionRuns as TextRun[],\n })\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(\n new Bookmark({\n id: options.bookmarkId,\n children: textRuns as TextRun[],\n })\n );\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 // Check if text has decorators (bold/italic markers)\n const hasDecorators = /(\\*\\*\\*|___|(\\*\\*|__)|(\\*|_))/.test(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 new Bookmark({\n id: options.bookmarkId,\n children: revisionRuns as TextRun[],\n })\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 (hasDecorators) {\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 new Bookmark({\n id: options.bookmarkId,\n children: headingTextChildren,\n })\n );\n } else {\n // No bookmark, add text directly\n if (hasDecorators) {\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 });\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 = 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: (string | { text: string; level?: number; revision?: Revision })[],\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 // Create the paragraph with proper numbering reference\n const paragraphChildren: ParagraphChild[] = [\n ...(commentAnchor && index === firstRendered ? commentAnchor.start : []),\n ...textRuns,\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 = 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 = 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 = 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';\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}\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 = { bookmarks: new Map() };\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({ bookmarks: new Map() }, 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 * 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 // Convert to lowercase, replace spaces with hyphens, remove special characters\n const baseId = text\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-]/g, '')\n .substring(0, 40); // Limit length\n\n // Ensure uniqueness by appending counter if needed\n let id = baseId;\n let attempt = 0;\n while (this.state.bookmarks.has(id) && attempt < 100) {\n id = `${baseId}-${++attempt}`;\n }\n\n return id;\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 * 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 * 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';\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 // 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 * Numbering Configuration Utilities\n * Utilities for creating and managing docx numbering configurations\n */\n\nimport { AlignmentType, convertInchesToTwip, LevelFormat } 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 * 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 * 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 * List Component\n * Standard component for rendering list elements in documents\n */\n\nimport { Paragraph } from 'docx';\nimport { ComponentDefinition, isListComponent, ListProps } 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 { resolveColor } from '../styles/utils/colorUtils';\n\n/**\n * Convert simplified format to proper level configurations\n */\nfunction createLevelsFromSimplifiedProps(props: ListProps): 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 * 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 * 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: 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 */\nfunction getMaxLevelFromItems(\n items: (string | { text: string; 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: 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 * 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 // Determine the maximum level needed from items\n const maxLevel = getMaxLevelFromItems(resolvedConfig.items);\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 let levels: ListLevelConfig[];\n\n if (resolvedConfig.levels && resolvedConfig.levels.length > 0) {\n // Use explicit level configurations, filling in missing levels\n levels = fillMissingLevels(\n applyListStart(\n resolvedConfig.levels as ListLevelConfig[],\n resolvedConfig.start\n ),\n maxLevel\n );\n } else {\n // Build from simplified options\n const baseLevels = createLevelsFromSimplifiedProps(resolvedConfig);\n levels = fillMissingLevels(baseLevels, maxLevel);\n }\n\n const config: NumberingConfig = {\n reference,\n levels: resolveMarkerFonts(levels, 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} 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 {\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\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 const isInline = !tb.props.floating;\n const childComponents = tb.children || [];\n\n if (isInline) {\n // Inline: use a one-cell table container for multi-paragraph support\n const cellChildren: (Paragraph | Table)[] = [];\n // Create context with current text-box as parent\n const childContext: import('../types').RenderContext = {\n ..._context,\n parent: tb,\n };\n for (const child of childComponents) {\n const rendered = await renderComponent(\n child,\n theme,\n themeName,\n childContext\n );\n cellChildren.push(...rendered);\n }\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\n // If there is at least one table or image child, use a floating one-cell table container\n const cellChildren: (Paragraph | Table)[] = [];\n // Create context with current text-box as parent\n const childContext: import('../types').RenderContext = {\n ..._context,\n parent: tb,\n };\n for (const child of childComponents) {\n const rendered = await renderComponent(\n child,\n theme,\n themeName,\n childContext\n );\n cellChildren.push(...rendered);\n }\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 * 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';\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 entries.push({ title: entry.title, level: entry.level });\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 * collectTocHeadings — per-document TOC entry pre-pass (#174).\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\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';\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}\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/**\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 const entries: TocHeadingEntry[] = [];\n const ordinals = computeSectionOrdinals(sections);\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 const text = typeof props.text === 'string' ? props.text : '';\n const title = normalizeEntryTitle(text);\n if (title) {\n const level = typeof props.level === 'number' ? props.level : 1;\n entries.push({ title, level, sectionBookmarkId });\n }\n return;\n }\n\n if (component.name === 'paragraph') {\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 (!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;\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 ...(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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsIO,SAAS,oBACd,OACiB;AACjB,SAAO;AAAA,IACL,SAAS,MAAM;AAAA,IACf,MAAM,MAAM,QAAQ;AAAA,IACpB,aAAa,MAAM,eAAe;AAAA,IAClC,aAAa,MAAM,eAAe;AAAA,IAClC,SAAS,MAAM,WAAW;AAAA,IAC1B,QAAQ;AAAA,MACN,GAAG;AAAA,MACH,GAAI,MAAM,UAAU,CAAC;AAAA,IACvB;AAAA,IACA,OAAO;AAAA,MACL,SAAS,EAAE,GAAG,cAAc,SAAS,GAAI,MAAM,OAAO,WAAW,CAAC,EAAG;AAAA,MACrE,MAAM,EAAE,GAAG,cAAc,MAAM,GAAI,MAAM,OAAO,QAAQ,CAAC,EAAG;AAAA,MAC5D,MAAM,EAAE,GAAG,cAAc,MAAM,GAAI,MAAM,OAAO,QAAQ,CAAC,EAAG;AAAA,MAC5D,OAAO,EAAE,GAAG,cAAc,OAAO,GAAI,MAAM,OAAO,SAAS,CAAC,EAAG;AAAA,IACjE;AAAA,IACA,MAAM;AAAA,MACJ,GAAG;AAAA,MACH,GAAI,MAAM,QAAQ,CAAC;AAAA,MACnB,SAAS;AAAA,QACP,GAAG,aAAa;AAAA,QAChB,GAAI,MAAM,MAAM,WAAW,CAAC;AAAA,MAC9B;AAAA,IACF;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,mBAAmB,MAAM;AAAA,EAC3B;AACF;AAuBO,SAAS,eAAe,OAAiC;AAC9D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,UAAU,CAAC;AAAA,EACvB;AACF;AAKO,SAAS,cAAc,OAAiC;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,SAAS,CAAC;AAAA,EACtB;AACF;AAKO,SAAS,eAAe,OAAiC;AAC9D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,MAAM,UAAU,CAAC;AAAA,EACvB;AACF;AAKO,SAAS,eAAe,OAAiC;AAC9D,QAAM,SAAS,eAAe,KAAK;AACnC,SAAO;AAAA,IACL,GAAG,eAAe;AAAA,IAClB,GAAI,OAAO,UAAU,CAAC;AAAA,EACxB;AACF;AA/NA,IASa,gBAoBA,eAUA,gBA+EA;AAtHb;AAAA;AAAA;AASO,IAAM,iBAAiB;AAAA,MAC5B,SAAS;AAAA,MACT,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,QAAQ;AAAA;AAAA,MAER,aAAa;AAAA,MACb,eAAe;AAAA,MACf,WAAW;AAAA,MACX,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,mBAAmB;AAAA,MACnB,qBAAqB;AAAA,IACvB;AAKO,IAAM,gBAAgB;AAAA,MAC3B,SAAS,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,MACrC,MAAM,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,MAClC,MAAM,EAAE,QAAQ,eAAe,MAAM,GAAG;AAAA,MACxC,OAAO,EAAE,QAAQ,SAAS,MAAM,GAAG;AAAA,IACrC;AAKO,IAAM,iBAAiB;AAAA,MAC5B,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,WAAW;AAAA,QACX,aAAa;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,QACA,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAKO,IAAM,eAAe;AAAA,MAC1B,MAAM;AAAA,MACN,SAAS;AAAA,QACP,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AAAA;AAAA;;;ACjIA;AAAA;AAAA;AAAA;AAAA,MACE,SAAW;AAAA,MACX,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,YAAc;AAAA,QACd,MAAQ;AAAA,QACR,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW;AAAA,UACT,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,QACA,OAAS;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe;AAAA,YACb,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,UACA,WAAa;AAAA,UACb,SAAW;AAAA,YACT,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,UAAY;AAAA,QACd;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,UACA,kBAAoB;AAAA,YAClB,MAAQ;AAAA,YACR,OAAS;AAAA,UACX;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,YACV,OAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC5LA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC7C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,MAC7C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACrHA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC/C,MAAQ,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC5C,MAAQ,EAAE,QAAU,SAAS,MAAQ,GAAG;AAAA,QACxC,OAAS,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,MAC/C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,GAAG;AAAA,QAC3B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7GA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC7C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,MAC7C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACxHA;AAAA;AAAA;AAAA;AAAA,MACE,MAAQ;AAAA,MACR,aAAe;AAAA,MACf,aAAe;AAAA,MACf,SAAW;AAAA,MACX,QAAU;AAAA,QACR,SAAW;AAAA,QACX,WAAa;AAAA,QACb,QAAU;AAAA,QACV,MAAQ;AAAA,QACR,YAAc;AAAA,QACd,QAAU;AAAA,QACV,aAAe;AAAA,QACf,eAAiB;AAAA,QACjB,WAAa;AAAA,QACb,eAAiB;AAAA,QACjB,iBAAmB;AAAA,QACnB,mBAAqB;AAAA,QACrB,qBAAuB;AAAA,MACzB;AAAA,MACA,OAAS;AAAA,QACP,SAAW,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,QAC/C,MAAQ,EAAE,QAAU,WAAW,MAAQ,GAAG;AAAA,QAC1C,MAAQ,EAAE,QAAU,YAAY,MAAQ,GAAG;AAAA,QAC3C,OAAS,EAAE,QAAU,aAAa,MAAQ,GAAG;AAAA,MAC/C;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW;AAAA,UACT,KAAO;AAAA,UACP,QAAU;AAAA,UACV,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,MACF;AAAA,MACA,QAAU;AAAA,QACR,QAAU;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,aAAe,EAAE,MAAQ,YAAY,OAAS,IAAI;AAAA,UAClD,WAAa;AAAA,UACb,SAAW,EAAE,OAAS,EAAE;AAAA,QAC1B;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,GAAG;AAAA,UACvC,UAAY;AAAA,UACZ,WAAa;AAAA,UACb,SAAW;AAAA,YACT,QAAU;AAAA,cACR,OAAS;AAAA,cACT,MAAQ;AAAA,cACR,OAAS;AAAA,cACT,OAAS;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,IAAI,OAAS,EAAE;AAAA,UACtC,UAAY;AAAA,UACZ,WAAa;AAAA,QACf;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,SAAW,EAAE,QAAU,GAAG,OAAS,EAAE;AAAA,UACrC,UAAY;AAAA,QACd;AAAA,QACA,OAAS;AAAA,UACP,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,QACA,UAAY;AAAA,UACV,MAAQ;AAAA,UACR,MAAQ;AAAA,UACR,QAAU;AAAA,UACV,OAAS;AAAA,UACT,WAAa;AAAA,UACb,SAAW,EAAE,QAAU,GAAG,OAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,mBAAqB;AAAA,QACnB,OAAS;AAAA,UACP,aAAe;AAAA,QACjB;AAAA,QACA,MAAQ;AAAA,UACN,QAAU;AAAA,UACV,QAAU;AAAA,UACV,QAAU;AAAA,QACZ;AAAA,QACA,OAAS;AAAA,UACP,WAAa;AAAA,QACf;AAAA,QACA,WAAa;AAAA,UACX,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,QACA,SAAW;AAAA,UACT,WAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC3HA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B;AAAA,EACE;AAAA,OAEK;AAmBP,SAAS,qBAAsD;AAC7D,MAAI,cAAc;AAChB,WAAO;AAAA,EACT;AAGA,QAAMA,UAA0C;AAAA,IAC9C,SAAS,oBAAoB,0BAAmC;AAAA,IAChE,WAAW,oBAAoB,4BAAqC;AAAA,IACpE,QAAQ,oBAAoB,yBAAkC;AAAA,IAC9D,MAAM,oBAAoB,uBAAgC;AAAA,IAC1D,WAAW,oBAAoB,4BAAqC;AAAA,EACtE;AAGA,MAAI;AACF,UAAM,aAAa,cAAc,YAAY,GAAG;AAChD,UAAM,YAAY,KAAK,QAAQ,UAAU;AACzC,UAAM,YAAY,KAAK,KAAK,WAAW,gCAAgC;AAEvE,QAAI,GAAG,WAAW,SAAS,GAAG;AAC5B,YAAM,aAAa,GAChB,YAAY,SAAS,EACrB,OAAO,CAAC,SAAS,KAAK,SAAS,kBAAkB,CAAC,EAClD,IAAI,CAAC,SAAS,KAAK,SAAS,MAAM,kBAAkB,CAAC;AAExD,iBAAW,aAAa,YAAY;AAClC,YAAI,CAACA,QAAO,SAAS,GAAG;AACtB,cAAI;AACF,kBAAM,WAAW,KAAK;AAAA,cACpB;AAAA,cACA,GAAG,SAAS;AAAA,YACd;AACA,kBAAM,UAAU,GAAG,aAAa,UAAU,MAAM;AAChD,kBAAM,cAAc,KAAK,MAAM,OAAO;AAKtC,gBAAI,CAAC,mBAAmB,WAAW,GAAG;AACpC,sBAAQ;AAAA,gBACN,kBAAkB,SAAS;AAAA,cAC7B;AACA;AAAA,YACF;AACA,YAAAA,QAAO,SAAS,IAAI,oBAAoB,WAAW;AAAA,UACrD,SAAS,OAAO;AACd,oBAAQ;AAAA,cACN,mCAAmC,SAAS;AAAA,cAC5C;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAAA,EAEhB;AAEA,iBAAeA;AACf,SAAOA;AACT;AA3FA,IA4BI,cAiES,QAYA,UAWA,sBAoBA,UAmBA,eAKA,cACA,gBACA;AAlKb;AAAA;AAAA;AAYA;AAOA;AACA;AACA;AACA;AACA;AAKA,IAAI,eAAuD;AAiEpD,IAAM,SAAS,mBAAmB;AAYlC,IAAM,WAAW,CAAC,cAAmD;AAC1E,aAAO,OAAO,SAAS;AAAA,IACzB;AASO,IAAM,uBAAuB,CAClC,WACA,gBAAwB,cACJ;AACpB,YAAM,QAAQ,SAAS,SAAS,KAAK,SAAS,aAAa;AAE3D,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR,yBAAyB,SAAS,qBAAqB,aAAa;AAAA,QACtE;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAOO,IAAM,WAAW,CAAC,cAA+B;AACtD,aAAO,aAAa;AAAA,IACtB;AAiBO,IAAM,gBAAgB,MAAgB;AAC3C,aAAO,OAAO,KAAK,MAAM;AAAA,IAC3B;AAGO,IAAM,eAAe,OAAO,SAAS;AACrC,IAAM,iBAAiB,OAAO,WAAW;AACzC,IAAM,cAAc,OAAO,QAAQ;AAAA;AAAA;;;ACpInC,SAAS,aACd,YACA,OACQ;AAER,MAAI,WAAW,WAAW,GAAG,GAAG;AAC9B,UAAM,WAAW,WAAW,MAAM,CAAC;AACnC,QAAI,mBAAmB,KAAK,QAAQ,GAAG;AACrC,aAAO,SAAS,YAAY;AAAA,IAC9B;AAEA,UAAM,IAAI;AAAA,MACR,uBAAuB,UAAU;AAAA,IACnC;AAAA,EACF;AAIA,QAAM,SAAS,eAAe,KAAK;AACnC,QAAM,gBAAgB,OAAO,UAAuB;AACpD,MAAI,OAAO,kBAAkB,UAAU;AAErC,WAAO,aAAa,eAAe,KAAK;AAAA,EAC1C;AAOA,MAAI,mBAAmB,KAAK,UAAU,GAAG;AACvC,WAAO,WAAW,YAAY;AAAA,EAChC;AAGA,QAAM,IAAI;AAAA,IACR,yBAAyB,UAAU;AAAA,EACrC;AACF;AApEA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACiBO,SAAS,cAAc,QAAwB;AACpD,SAAO,KAAK,MAAM,SAAS,eAAe;AAC5C;AAQO,SAAS,aACd,OACA,WACyB;AAEzB,MAAI,OAAO;AACT,WAAO;AAAA,EACT;AAGA,MAAI,WAAW;AACb,WAAO,SAAS,SAAS;AAAA,EAC3B;AAGA,SAAO,SAAS,SAAS;AAC3B;AAQO,SAAS,kBACd,OACA,SACQ;AAER,MAAI,CAAC,OAAO,OAAO,MAAM,QAAQ;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,CAAC,SAAS;AACZ,WAAO,MAAM,MAAM,KAAK;AAAA,EAC1B;AACA,SAAO,MAAM,MAAM,OAAO,GAAG,UAAU,MAAM,MAAM,KAAK;AAC1D;AAoDO,SAAS,sBACd,OACA,SACgB;AAEhB,QAAM,gBAAgB,WAAW;AAGjC,MAAI,CAAC,OAAO,QAAQ,aAAa,GAAG;AAClC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,MAAM,aAAa;AAEzC,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,IACnB,aAAa,QAAQ;AAAA,IACrB,SAAS,QAAQ;AAAA,IACjB,kBAAkB,QAAQ;AAAA,IAC1B,OAAO,QAAQ;AAAA,EACjB;AACF;AAUO,SAAS,4BACd,WACA,gBACoB;AAGpB,QAAM,mBAAmB,OAAO,QAAQ,cAAc,EAAE,OAEtD,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM;AACvB,QAAI,UAAU,QAAW;AACvB,UAAI,GAAG,IAAI;AAAA,IACb;AACA,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAoCO,SAAS,mBACd,aACgC;AAChC,MAAI,gBAAgB,QAAW;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,gBAAgB,UAAU;AACnC,WAAO;AAAA,MACL,MAAM,KAAK,MAAM,cAAc,yBAAyB;AAAA,MACxD,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,MAAM,IAAI;AACxB,MAAI;AACJ,MAAI;AAEJ,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AACP,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO;AACP,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO,UAAU,SAAY,QAAQ,kBAAkB;AACvD,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aAAO,UAAU,SAAY,QAAQ,kBAAkB;AACvD,iBAAW;AACX;AAAA,IACF,KAAK;AACH,aACE,UAAU,SAAY,QAAQ,4BAA4B;AAC5D,iBAAW;AACX;AAAA,IACF;AACE,aAAO;AAAA,EACX;AAEA,SAAO,EAAE,MAAM,SAAS;AAC1B;AAjQA,IAQM,iBACA,4BACA,2BACA;AAXN;AAAA;AAAA;AAAA;AAEA;AAGA;AAGA,IAAM,kBAAkB;AACxB,IAAM,6BAA6B;AACnC,IAAM,4BAA4B,6BAA6B;AAC/D,IAAM,4BAA4B,4BAA4B;AAAA;AAAA;;;ACX9D,SAAS,mBAAmB;AA8ErB,SAAS,kBACd,MACgB;AAChB,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,WAAW,IAAI;AAAA,EACxB;AACA,SAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAClD;AArFA,IAgCM,8BAyBO,YAoCA,eAmHA,oBAwBA;AAxOb;AAAA;AAAA;AAGA;AACA;AA4BA,IAAM,+BAA+B,CAAC,UAAgC;AACpE,YAAM,cACJ,mBAAmB,OAAO,WAAW,KACrC,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACvC,aAAO;AAAA,QACL,QACE,OAAO,SAAS,WAAW,SACvB,cAAc,MAAM,QAAQ,MAAM,IAClC;AAAA,QACN,OACE,OAAO,SAAS,UAAU,SACtB,cAAc,MAAM,QAAQ,KAAK,IACjC;AAAA,QACN,GAAG;AAAA,MACL;AAAA,IACF;AAUO,IAAM,aAAa;AAAA,MACxB,IAAI,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC3C,IAAI,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC3C,QAAQ,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,MAC/C,OAAO,EAAE,OAAO,OAAO,QAAQ,OAAO,MAAM,EAAE;AAAA,IAChD;AA+BO,IAAM,gBAAgB,CAAC,OAAqB,cAAuB;AACxE,YAAM,cAAc,aAAa,OAAO,SAAS;AAEjD,UAAI,eAAe,YAAY,QAAQ,QAAQ;AAI7C,cAAM,cAAc,YAAY,OAAO;AACvC,cAAM,SAAS,YAAY;AAC3B,eAAO;AAAA,UACL,eAAe,6BAA6B,OAAO,SAAS;AAAA,UAC5D,iBAAiB,6BAA6B,OAAO,WAAW;AAAA,UAChE,aAAa;AAAA,YACX,MAAM;AAAA,cACJ,YAAY,QAAQ,WAAW;AAAA,cAC/B;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,YAAY,QAAQ,qBAAqB;AAAA,cACzC;AAAA,YACF;AAAA;AAAA,YACA,MAAM;AAAA;AAAA,YACN,OAAO,YAAY,QAAQ,MAAM;AAAA;AAAA,YACjC,MAAM,kBAAkB,aAAa,YAAY,IAAI;AAAA,UACvD;AAAA,UACA,WAAW;AAAA,YACT,OAAO,aAAa,YAAY,SAAS,WAAW,WAAW;AAAA,YAC/D,OAAO,YAAY,QAAQ,MAAM;AAAA;AAAA,YACjC,MAAM,kBAAkB,aAAa,YAAY,IAAI;AAAA,UACvD;AAAA,UACA,gBAAgB;AAAA,YACd,MAAM;AAAA,cACJ,YAAY,QAAQ,UAAU;AAAA,cAC9B;AAAA,YACF;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,KAAK;AAAA,cACH,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,QAAQ;AAAA,cACN,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,MAAM;AAAA,cACJ,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,OAAO,YAAY;AAAA,cACnB,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,QAAQ,aAAa;AAAA,gBACjC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,QACL,eAAe,6BAA6B;AAAA,QAC5C,iBAAiB,6BAA6B;AAAA,QAC9C,aAAa;AAAA,UACX,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,WAAW;AAAA,UACT,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,gBAAgB;AAAA,UACd,MAAM;AAAA,QACR;AAAA,QACA,SAAS;AAAA,UACP,KAAK,EAAE,OAAO,YAAY,QAAQ,MAAM,GAAG,OAAO,SAAS;AAAA,UAC3D,QAAQ;AAAA,YACN,OAAO,YAAY;AAAA,YACnB,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,UACA,MAAM,EAAE,OAAO,YAAY,QAAQ,MAAM,GAAG,OAAO,SAAS;AAAA,UAC5D,OAAO;AAAA,YACL,OAAO,YAAY;AAAA,YACnB,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAQO,IAAM,qBAAqB,CAAC,OAAqB,cAAuB;AAC7E,YAAM,cAAc,aAAa,OAAO,SAAS;AAEjD,UAAI,aAAa,MAAM,SAAS;AAC9B,eAAO,YAAY,KAAK;AAAA,MAC1B;AAGA,aAAO;AAAA,QACL,KAAK;AAAA;AAAA,QACL,OAAO;AAAA;AAAA,QACP,QAAQ;AAAA;AAAA,QACR,MAAM;AAAA;AAAA,QACN,QAAQ;AAAA;AAAA,QACR,QAAQ;AAAA;AAAA,MACV;AAAA,IACF;AAQO,IAAM,eAAe,CAAC,OAAqB,cAAuB;AACvE,YAAM,cAAc,aAAa,OAAO,SAAS;AACjD,YAAM,iBAAiB,mBAAmB,OAAO,SAAS;AAE1D,UAAI,aAAa,MAAM;AACrB,cAAM,UAAU,YAAY,KAAK,WAAW,CAAC;AAC7C,cAAM,aAAa,kBAAkB,YAAY,KAAK,IAAI;AAC1D,eAAO;AAAA,UACL,MAAM;AAAA,YACJ,OAAO,WAAW;AAAA,YAClB,QAAQ,WAAW;AAAA,YACnB,GAAI,WAAW,SAAS,UAAa,EAAE,MAAM,WAAW,KAAK;AAAA,UAC/D;AAAA,UACA,QAAQ;AAAA,YACN,KAAK,QAAQ,OAAO,eAAe,OAAO;AAAA,YAC1C,OAAO,QAAQ,SAAS,eAAe,SAAS;AAAA,YAChD,QAAQ,QAAQ,UAAU,eAAe,UAAU;AAAA,YACnD,MAAM,QAAQ,QAAQ,eAAe,QAAQ;AAAA,UAC/C;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,OAAO,WAAW,GAAG;AAAA;AAAA,UACrB,QAAQ,WAAW,GAAG;AAAA;AAAA,UACtB,MAAM,WAAW,GAAG;AAAA,QACtB;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,eAAe,OAAO;AAAA,UAC3B,OAAO,eAAe,SAAS;AAAA,UAC/B,QAAQ,eAAe,UAAU;AAAA,UACjC,MAAM,eAAe,QAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACvQA,SAAS,yBAAyB;AALlC,IAUa,sBA+BA,iBAWA;AApDb;AAAA;AAAA;AAOA;AAGO,IAAM,uBAAN,cAAmC,MAAM;AAAA,MAC9C,YAAmB,QAA2B;AAC5C,cAAM,aAAa,OAAO;AAC1B,cAAM,eAAe,OAClB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,UAAU;AACd,gBAAMC,QAAO,MAAM,OACf,MAAM,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAChD;AACJ,gBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,iBAAO,GAAG,OAAO,GAAG,MAAM,OAAO;AAAA,QACnC,CAAC,EACA,KAAK,IAAI;AAEZ;AAAA,UACE,gCAAgC,UAAU,SAAS,aAAa,IAAI,MAAM,EAAE,KAAK,YAAY,GAAG,aAAa,IAAI,QAAQ,EAAE;AAAA,QAC7H;AAfiB;AAgBjB,aAAK,OAAO;AAAA,MACd;AAAA,MAEA,oBAA8B;AAC5B,eAAO,KAAK,OAAO,IAAI,CAAC,UAAU;AAChC,gBAAMA,QAAO,MAAM,OACf,MAAM,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAChD;AACJ,gBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,iBAAO,GAAG,OAAO,GAAG,MAAM,OAAO;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF;AAEO,IAAM,kBAAN,cAA8B,MAAM;AAAA,MACzC,YACE,SACO,OACP;AACA,cAAM,0BAA0B,OAAO,EAAE;AAFlC;AAGP,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAGO,IAAM,cAAN,MAAkB;AAAA,MACN,gBAAgB,OAAO;AAAA;AAAA,MAExC,MAAM,YAAqC;AACzC,YAAI;AAEF,eAAK,cAAc,UAAU;AAG7B,gBAAM,SAAS,kBAAkB,UAAU;AAC3C,cAAI,CAAC,OAAO,OAAO;AACjB,kBAAM,IAAI,qBAAqB,OAAO,UAAU,CAAC,CAAC;AAAA,UACpD;AAEA,gBAAM,YAAY,OAAO;AAGzB,iBAAO,KAAK,cAAc,SAAS;AAAA,QACrC,SAAS,OAAO;AACd,cACE,iBAAiB,wBACjB,iBAAiB,iBACjB;AACA,kBAAM;AAAA,UACR;AACA,gBAAM,IAAI;AAAA,YACR,0CAA0C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAChG,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,cAAc,YAA0B;AAE9C,YAAI,CAAC,YAAY;AACf,gBAAM,IAAI,gBAAgB,qCAAqC;AAAA,QACjE;AAGA,YAAI,OAAO,eAAe,UAAU;AAClC,gBAAM,IAAI,gBAAgB,wBAAwB;AAAA,QACpD;AAGA,YAAI,WAAW,SAAS,KAAK,eAAe;AAC1C,gBAAM,IAAI;AAAA,YACR,0BAA0B,WAAW,MAAM,eAAe,KAAK,aAAa;AAAA,UAC9E;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,cAAc,aAA+C;AAGnE,eAAO,oBAAoB,WAAW;AAAA,MACxC;AAAA;AAAA,MAGA,SAAS,YAA2D;AAClE,YAAI;AACF,eAAK,cAAc,UAAU;AAC7B,gBAAM,SAAS,kBAAkB,UAAU;AAE3C,cAAI,OAAO,OAAO;AAChB,mBAAO,EAAE,OAAO,KAAK;AAAA,UACvB,OAAO;AACL,kBAAM,UAAU,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM;AAC9C,oBAAMA,QAAO,EAAE,OACX,EAAE,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,OAAO,GAAG,IAC5C;AACJ,oBAAM,UAAUA,QAAO,GAAGA,KAAI,OAAO;AACrC,qBAAO,GAAG,OAAO,GAAG,EAAE,OAAO;AAAA,YAC/B,CAAC;AACD,mBAAO,EAAE,OAAO,OAAO,OAAO;AAAA,UAChC;AAAA,QACF,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,QAAQ;AAAA,cACN,iBAAiB,QAAQ,MAAM,UAAU;AAAA,YAC3C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACnIA,SAAS,qBAAqB,gCAAgC;AAL9D;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,YAAYC,WAAU;AAC/B,SAAS,iBAAiB;AAD1B,IAMa,gBAaA;AAnBb;AAAA;AAAA;AAGA;AAGO,IAAM,iBAAN,cAA6B,MAAM;AAAA,MACxC,YACE,SACOC,OACA,QACP;AACA,cAAM,WAAWA,QAAO,WAAWA,KAAI,MAAM;AAC7C,cAAM,8BAA8B,OAAO,GAAG,QAAQ,EAAE;AAJjD,oBAAAA;AACA;AAIP,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAGO,IAAM,cAAN,MAAkB;AAAA,MACf,SAAS,IAAI,YAAY;AAAA,MAChB,gBAAgB,KAAK,OAAO;AAAA;AAAA,MAC5B,qBAAqB,CAAC,OAAO;AAAA,MAE9C,MAAM,aAAa,UAA4C;AAC7D,YAAI;AAEF,eAAK,iBAAiB,QAAQ;AAG9B,gBAAM,UAAU,MAAM,KAAK,mBAAmB,QAAQ;AAGtD,iBAAO,KAAK,OAAO,MAAM,OAAO;AAAA,QAClC,SAAS,OAAO;AACd,cAAI,iBAAiB,gBAAgB;AACnC,kBAAM;AAAA,UACR;AAGA,cAAI,SAAS,OAAO,UAAU,YAAY,UAAU,OAAO;AACzD,kBAAM,UAAU;AAChB,gBAAI;AAEJ,oBAAQ,QAAQ,MAAM;AAAA,cACtB,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AAAA,cACL,KAAK;AACH,0BAAU;AACV;AAAA,cACF,KAAK;AACH,0BAAU;AACV;AAAA,cACF;AACE,0BAAU,sBAAsB,QAAQ,OAAO;AAAA,YACjD;AAEA,kBAAM,IAAI;AAAA,cACR;AAAA,cACA;AAAA,cACA,iBAAiB,QAAQ,QAAQ;AAAA,YACnC;AAAA,UACF;AAGA,gBAAM,IAAI;AAAA,YACR,qBAAqB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC3E;AAAA,YACA,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA,MAEA,MAAM,YAAY,MAAwC;AAGxD,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,iBAAiB,UAAwB;AAE/C,YAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAC7C,gBAAM,IAAI,eAAe,sCAAsC;AAAA,QACjE;AAGA,cAAM,iBAAiB,UAAU,QAAQ;AAGzC,YAAI,eAAe,SAAS,IAAI,GAAG;AACjC,gBAAM,IAAI,eAAe,sCAAsC,QAAQ;AAAA,QACzE;AAGA,YAAI,eAAe,SAAS,IAAI,GAAG;AACjC,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,oBAAoB,KAAK,mBAAmB;AAAA,UAAK,CAAC,QACtD,eAAe,YAAY,EAAE,SAAS,GAAG;AAAA,QAC3C;AAEA,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI;AAAA,YACR,oCAAoC,KAAK,mBAAmB,KAAK,IAAI,CAAC;AAAA,YACtE;AAAA,UACF;AAAA,QACF;AAGA,YAAI,eAAe,SAAS,KAAM;AAChC,gBAAM,IAAI,eAAe,yBAAyB,QAAQ;AAAA,QAC5D;AAAA,MACF;AAAA,MAEA,MAAc,mBAAmB,UAAmC;AAClE,YAAI;AAEF,gBAAM,QAAQ,MAAMD,IAAG,KAAK,QAAQ;AAGpC,cAAI,CAAC,MAAM,OAAO,GAAG;AACnB,kBAAM,IAAI,eAAe,8BAA8B,QAAQ;AAAA,UACjE;AAGA,cAAI,MAAM,OAAO,KAAK,eAAe;AACnC,kBAAM,IAAI;AAAA,cACR,mBAAmB,MAAM,IAAI,eAAe,KAAK,aAAa;AAAA,cAC9D;AAAA,YACF;AAAA,UACF;AAGA,cAAI,MAAM,SAAS,GAAG;AACpB,kBAAM,IAAI,eAAe,iBAAiB,QAAQ;AAAA,UACpD;AAGA,gBAAM,UAAU,MAAMA,IAAG,SAAS,UAAU,MAAM;AAGlD,cAAI,OAAO,YAAY,UAAU;AAC/B,kBAAM,IAAI,eAAe,+BAA+B,QAAQ;AAAA,UAClE;AAEA,iBAAO;AAAA,QACT,SAAS,OAAO;AACd,cAAI,iBAAiB,gBAAgB;AACnC,kBAAM;AAAA,UACR;AAGA,gBAAM,IAAI;AAAA,YACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC9E;AAAA,YACA,iBAAiB,QAAQ,QAAQ;AAAA,UACnC;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,aAAa,UAAsD;AACjE,YAAI;AACF,eAAK,iBAAiB,QAAQ;AAC9B,iBAAO,EAAE,OAAO,KAAK;AAAA,QACvB,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,OAAO;AAAA,YACP,OACE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,MAAM,YAAY,UAKf;AACD,YAAI;AACF,gBAAM,QAAQ,MAAMA,IAAG,KAAK,QAAQ;AACpC,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,MAAM,MAAM;AAAA,YACZ,QAAQ,MAAM,OAAO;AAAA,UACvB;AAAA,QACF,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjNA;AAAA,EACE;AAAA,EAEA,sBAAAE;AAAA,EAMA;AAAA,OACK;AAyBP,eAAsB,kBACpB,YAC0B;AAC1B,SAAO,YAAY,MAAM,UAAU;AACrC;AAUA,eAAsB,kBACpB,UAC0B;AAC1B,SAAO,YAAY,aAAa,QAAQ;AAC1C;AAQO,SAAS,kBACd,OACA,SAAkB,MACV;AACR,MAAI;AAIF,QAAI,QAAQ;AACV,aAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AAAA,IACtC,OAAO;AACL,aAAO,KAAK,UAAU,KAAK;AAAA,IAC7B;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC3F;AAAA,EACF;AACF;AAOO,SAAS,wBAAwB,YAAoB;AAC1D,SAAO,YAAY,SAAS,UAAU;AACxC;AAzFA,IA0BM,aACA;AA3BN;AAAA;AAAA;AAYA;AACA;AAKA;AAIA;AACA;AAGA,IAAM,cAAc,IAAI,YAAY;AACpC,IAAM,cAAc,IAAI,YAAY;AAAA;AAAA;;;AC3BpC;AAAA;AAAA;AAwBA;AAaA;AACA;AASA;AAGA;AAAA;AAAA;;;AClDA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOO,SAAS,uBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,QAAM,QAAQ,MAAM,MAAM,SAAS;AACnC,QAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,QAAM,QAAQ,MAAM,QAAQ,SAAS;AACrC,SAAO,KAAK,IAAI,GAAG,QAAQ,OAAO,KAAK;AACzC;AAKO,SAAS,kBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,SAAO,MAAM,MAAM,SAAS;AAC9B;AAKO,SAAS,wBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,QAAM,SAAS,MAAM,MAAM,UAAU;AACrC,QAAM,MAAM,MAAM,QAAQ,OAAO;AACjC,QAAM,SAAS,MAAM,QAAQ,UAAU;AACvC,SAAO,KAAK,IAAI,GAAG,SAAS,MAAM,MAAM;AAC1C;AAKO,SAAS,mBACd,OACA,WACQ;AACR,QAAM,OAAO,aAAa,OAAO,SAAS;AAC1C,SAAO,MAAM,MAAM,UAAU;AAC/B;AAKO,SAAS,gCACd,OACoB;AACpB,QAAM,QAAQ,2BAA2B,KAAK,KAAK;AACnD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,MAAM,WAAW,MAAM,CAAC,CAAC;AAC/B,MAAI,MAAM,KAAK,MAAM,IAAK,QAAO;AACjC,SAAO,MAAM;AACf;AAMO,SAAS,mBACd,OACA,gBACQ;AACR,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,QAAQ,2BAA2B,KAAK,KAAK;AACnD,MAAI,CAAC,OAAO;AACV,YAAQ;AAAA,MACN,kDAAkD,KAAK;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAO,iBAAiB,WAAW,MAAM,CAAC,CAAC,IAAK,GAAG;AACjE;AAKO,SAAS,sBACd,OACA,qBACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,cAAc,KAAK;AAAA,EAC5B;AACA,QAAM,WAAW,gCAAgC,KAAK;AACtD,MAAI,aAAa,OAAW,QAAO;AACnC,SAAO,KAAK,MAAM,sBAAsB,QAAQ;AAClD;AAnGA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;;;ACFA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAyBA,SAAS,sBACd,KAKA;AACA,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC,KAAK;AACH,aAAO,+BAA+B;AAAA,IACxC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,oBACd,KAKA;AACA,UAAQ,KAAK;AAAA,IACX,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC,KAAK;AACH,aAAO,6BAA6B;AAAA,IACtC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,mBACd,OACA;AACA,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC,KAAK;AACH,aAAO,wBAAwB;AAAA,IACjC;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,iBACd,OACA;AACA,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B,KAAK;AACH,aAAO,sBAAsB;AAAA,IAC/B;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,YACd,MACA;AACA,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AAAA,IACL,KAAK;AAEH,aAAO,iBAAiB;AAAA,IAC1B;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,YAAY,MAAmD;AAC7E,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B,KAAK;AACH,aAAO,iBAAiB;AAAA,IAC1B;AACE,aAAO;AAAA,EACX;AACF;AAMO,SAAS,mBACd,UACA,OACA,WACiB;AACjB,MAAI,CAAC,SAAU,QAAO;AAMtB,MAAI,SAAS,MAAM,SAAS,SAAS;AACnC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,SAAS,oBAAoB;AAC/C,QAAM,YAAY,SAAS,kBAAkB;AAC7C,QAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,QAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AAIzC,QAAM,gBAAgB,QAAQ,SAAS,kBAAkB;AACzD,QAAM,cAAc,QAAQ,SAAS,gBAAgB;AAErD,QAAM,qBAAqB,SAAS,qBAChC;AAAA,IACE,GAAI,SAAS,mBAAmB,YAAY;AAAA,MAC1C,UAAU,sBAAsB,SAAS,mBAAmB,QAAQ;AAAA,IACtE;AAAA,IACA,GAAI,SAAS,mBAAmB,UAAU,UAAa;AAAA,MACrD,OAAO,mBAAmB,SAAS,mBAAmB,KAAK;AAAA,IAC7D;AAAA,IACA,GAAI,SAAS,mBAAmB,WAAW,UAAa;AAAA,MACtD,QACE,mBAAmB,SAAS,mBAAmB,QAAQ,IAAI,IAC3D;AAAA,IACJ;AAAA,EACF,IACA,cACE;AAAA;AAAA,IAEE,UAAU,+BAA+B;AAAA,IACzC,OAAO,wBAAwB;AAAA,EACjC,IACA;AAEN,QAAM,mBAAmB,SAAS,mBAC9B;AAAA,IACE,GAAI,SAAS,iBAAiB,YAAY;AAAA,MACxC,UAAU,oBAAoB,SAAS,iBAAiB,QAAQ;AAAA,IAClE;AAAA,IACA,GAAI,SAAS,iBAAiB,UAAU,UAAa;AAAA,MACnD,OAAO,iBAAiB,SAAS,iBAAiB,KAAK;AAAA,IACzD;AAAA,IACA,GAAI,SAAS,iBAAiB,WAAW,UAAa;AAAA,MACpD,QACE,mBAAmB,SAAS,iBAAiB,QAAQ,IAAI,IACzD;AAAA,IACJ;AAAA,EACF,IACA,gBACE;AAAA;AAAA,IAEE,UAAU,6BAA6B;AAAA,IACvC,OAAO,sBAAsB;AAAA,EAC/B,IACA;AAEN,QAAM,OAAO,SAAS,OAClB;AAAA,IACE,GAAI,SAAS,KAAK,QAAQ,EAAE,MAAM,YAAY,SAAS,KAAK,IAAI,EAAE;AAAA,IAClE,GAAI,SAAS,KAAK,QAAQ,EAAE,MAAM,YAAY,SAAS,KAAK,IAAI,EAAE;AAAA,EACpE,IACA;AAGJ,QAAM,QAAQ,kBAAkB,OAAO,SAAS;AAChD,QAAM,QAAQ,mBAAmB,OAAO,SAAS;AACjD,QAAM,aAAa,SAAS,MAAM,WAAY,SAAiB;AAC/D,QAAM,UAAU,aACZ;AAAA,IACE,GAAI,WAAW,QAAQ,UAAa;AAAA,MAClC,KAAK,mBAAmB,WAAW,KAAK,KAAK,IAAI;AAAA,IACnD;AAAA,IACA,GAAI,WAAW,WAAW,UAAa;AAAA,MACrC,QAAQ,mBAAmB,WAAW,QAAQ,KAAK,IAAI;AAAA,IACzD;AAAA,IACA,GAAI,WAAW,SAAS,UAAa;AAAA,MACnC,MAAM,mBAAmB,WAAW,MAAM,KAAK,IAAI;AAAA,IACrD;AAAA,IACA,GAAI,WAAW,UAAU,UAAa;AAAA,MACpC,OAAO,mBAAmB,WAAW,OAAO,KAAK,IAAI;AAAA,IACvD;AAAA,EACF,IACA;AAQJ,MAAI,SAAS,SAAS,WAAW,SAAY,SAAS,SAAS;AAG/D,MAAI,SAAS,GAAG;AACd,YAAQ;AAAA,MACN,wBAAwB,MAAM;AAAA,IAChC;AACA,aAAS;AAAA,EACX;AAEA,QAAM,SAAc;AAAA,IAClB,GAAI,sBAAsB,EAAE,mBAAmB;AAAA,IAC/C,GAAI,oBAAoB,EAAE,iBAAiB;AAAA,IAC3C,GAAI,QAAQ,EAAE,KAAK;AAAA,IACnB,GAAI,WAAW,EAAE,QAAQ;AAAA,IACzB,GAAI,SAAS,iBAAiB,UAAa;AAAA,MACzC,cAAc,SAAS;AAAA,IACzB;AAAA,IACA,GAAI,SAAS,mBAAmB,UAAa;AAAA,MAC3C,gBAAgB,SAAS;AAAA,IAC3B;AAAA,IACA,GAAI,SAAS,eAAe,UAAa;AAAA,MACvC,YAAY,SAAS;AAAA,IACvB;AAAA,IACA,GAAI,SAAS,iBAAiB,UAAa;AAAA,MACzC,cAAc,SAAS;AAAA,IACzB;AAAA,IACA;AAAA;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,SAAS;AAC/C;AArSA,IA8BM;AA9BN;AAAA;AAAA;AAWA;AAmBA,IAAM,eAAe;AAAA;AAAA;;;ACxBrB,SAAS,qBAAqB;AAC9B,SAAS,SAAS,WAAAC,gBAAe;;;ACmCjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACnCP,SAAS,iBAAiB,uBAAuB;;;ACnBjD;AAeO,SAAS,oBACd,WACA,UAGI,CAAC,GACQ;AACb,MAAI,CAAC,SAAS,SAAS,GAAG;AACxB,UAAM,YAAY;AAAA,MAChB,GAAG,cAAc;AAAA,MACjB,GAAG,OAAO,KAAK,QAAQ,gBAAgB,CAAC,CAAC;AAAA,IAC3C,EAAE,KAAK;AACP,YAAQ,UAAU,KAAK;AAAA,MACrB,WAAW;AAAA,MACX,SAAS,UAAU,SAAS,6DAA6D,UAAU,KAAK,IAAI,CAAC;AAAA,MAC7G,UAAU;AAAA,MACV,SAAS,EAAE,MAAM,mBAAmB,WAAW,WAAW,UAAU;AAAA,IACtE,CAAC;AAAA,EACH;AAEA,SAAO,qBAAqB,SAAS;AACvC;;;ACjCA,SAAS,kBAAkB;AAkBpB,SAAS,oBACd,OACA,WACa;AACb,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,QAAQ,EAAE,GAAG,MAAM,MAAM;AAC/B,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,UAAU,SAAS,CAAC,CAAC,GAAG;AAC/D,UAAM,MAAM;AACZ,UAAM,GAAG,IAAI,EAAE,GAAG,MAAM,MAAM,GAAG,GAAG,GAAG,IAAI;AAAA,EAC7C;AAEA,QAAM,SAAiC,EAAE,GAAI,MAAM,UAAU,CAAC,EAAG;AACjE,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,UAAU,UAAU,CAAC,CAAC,GAAG;AAChE,WAAO,IAAI,IAAI,EAAE,GAAG,OAAO,IAAI,GAAG,GAAI,IAAe;AAAA,EACvD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,EAAE,GAAG,MAAM,QAAQ,GAAI,UAAU,UAAU,CAAC,EAAG;AAAA,IACvD;AAAA,IACA,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,KAAK,EAAE,OAAO;AAAA,EACjD;AACF;AAGO,SAAS,qBAAqB,WAAmC;AACtE,SAAO,WAAW,QAAQ,EACvB,OAAO,KAAK,UAAU,SAAS,CAAC,EAChC,OAAO,KAAK,EACZ,MAAM,GAAG,CAAC;AACf;;;AFDA,SAAS,wBACP,WACA,cACA,UACa;AACb,MAAI,cAAc;AAChB,QAAI,aAAa,SAAS,EAAG,QAAO,aAAa,SAAS;AAC1D,UAAM,iBAAiB,UAAU,YAAY;AAC7C,UAAM,mBAAmB,OAAO,KAAK,YAAY,EAAE;AAAA,MACjD,CAAC,QAAQ,IAAI,YAAY,MAAM;AAAA,IACjC;AACA,QAAI,iBAAkB,QAAO,aAAa,gBAAgB;AAC1D,WAAO,oBAAoB,WAAW,EAAE,cAAc,SAAS,CAAC;AAAA,EAClE;AACA,SAAO,oBAAoB,WAAW,EAAE,SAAS,CAAC;AACpD;AAEO,SAAS,oBACd,YACA,UAA+B,CAAC,GACR;AACxB,QAAM,EAAE,cAAc,OAAO,UAAU,kBAAkB,IAAI;AAY7D,MAAI,WAAW,UAAU,MAAM;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,QAAM,WACJ,WAAW,UAAU,SAAY,EAAE,GAAG,YAAY,OAAO,CAAC,EAAE,IAAI;AAElE,QAAM,oBAAoB,SAAS,MAAM,SAAS;AAClD,QAAM,gBAAgB,qBAAqB;AAC3C,MAAI,QAAQ,oBACR;AAAA,IACE;AAAA,IACA;AAAA,IACA,sBAAsB;AAAA,EACxB,IACA,wBAAwB,eAAe,cAAc,QAAQ;AAKjE,QAAM,iBAAiB,SAAS,MAAM;AACtC,MAAI,YAAY;AAChB,MAAI,gBAAgB;AAClB,YAAQ,oBAAoB,OAAO,cAAc;AACjD,gBAAY,GAAG,SAAS,OAAO,qBAAqB,cAAc,CAAC;AAAA,EACrE;AAIA,QAAM,OAAO,gBAAgB,EAAE,KAAK,UAAU,OAAO,MAAM,CAAC;AAC5D,aAAW,KAAK,KAAK,UAAU;AAC7B,QAAI,UAAU;AACZ,eAAS,KAAK;AAAA,QACZ,WAAW;AAAA,QACX,SAAS,EAAE;AAAA,QACX,UAAU;AAAA,QACV,SAAS,EAAE,MAAM,EAAE,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,KAAK,mBAAmB,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AAAA,IACxD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,KAAK;AAAA,IACf,OAAO,KAAK;AAAA;AAAA;AAAA,IAGZ,WAAW,gBAAgB,WAAW,OAAO,IAAI;AAAA,EACnD;AACF;;;AG3IA,SAAS,cAAc;AAEhB,IAAM,aAAa,CACxB,MACA,eAAuB,mBACZ;AACX,SAAO,OAAO,MAAM,YAAY;AAClC;;;ACoBA,SAAS,yBAAyB;AAgHlC,SAAS,qBAAAC,0BAAyB;AA3G3B,SAAS,qBAAqB,OAAuC;AAC1E,SAAO,MAAM,qBAAqB,CAAC;AACrC;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,2BACd,OACA,OACmC;AACnC,QAAM,WAA8C,CAAC;AAGrD,MAAI,MAAM,QAAQ;AAChB,UAAM,WAAW,UAAU,KAAK;AAOhC,UAAM,eAAe,MAAM,OAAO,QAAQ;AAE1C,QAAI,cAAc,WAAW;AAC3B,eAAS,YAAY,aAAa;AAAA,IACpC;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,gBACd,OAC4B;AAC5B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,aAAa,CAAC;AACjC;AAKO,SAAS,iBAAiB,OAA4C;AAC3E,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,SAAS,CAAC;AAC7B;AAKO,SAAS,qBACd,OAC4B;AAC5B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,aAAa,CAAC;AACjC;AAKO,SAAS,iBAAiB,OAA4C;AAC3E,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,SAAS,CAAC;AAC7B;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,mBACd,OAC0B;AAC1B,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,WAAW,CAAC;AAC/B;AAKO,SAAS,gBAAgB,OAA2C;AACzE,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,UAAU,QAAQ,CAAC;AAC5B;AAQO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,sBACd,OACA,OACgB;AAChB,QAAM,WAAW,gBAAgB,KAAK;AACtC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,kBACd,OACA,OACY;AACZ,QAAM,WAAW,iBAAiB,KAAK;AACvC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,sBACd,OACA,OACgB;AAChB,QAAM,WAAW,qBAAqB,KAAK;AAC3C,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,kBACd,OACA,OACY;AACZ,QAAM,WAAW,iBAAiB,KAAK;AACvC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,oBACd,OACA,OACc;AACd,QAAM,WAAW,mBAAmB,KAAK;AACzC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,iBACd,OACA,OACW;AACX,QAAM,WAAW,gBAAgB,KAAK;AACtC,SAAO,kBAAkB,OAAO,QAAQ;AAC1C;AAKO,SAAS,uBACd,OACA,QACuD;AAEvD,SAAO;AACT;AAOO,SAAS,mBACd,OACA,QACmD;AACnD,SAAO;AACT;AAKO,SAAS,2BACd,OACA,eACyB;AACzB,QAAM,WAAW,qBAAqB,KAAK;AAE3C,SAAS,WAAmB,aAAa,KAAiC,CAAC;AAC7E;AAKO,SAAS,4BACd,OACA,OACA,eACG;AACH,QAAM,WAAW,2BAA2B,OAAO,aAAa;AAChE,SAAO,kBAAkB,OAAO,QAAsB;AACxD;;;ACtPA,SAAS,gCACP,OACA,OACc;AACd,QAAM,WAAW,oBAAoB,OAAO,KAAK;AACjD,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,gBAAgB,2BAA2B,OAAO,KAAK;AAC7D,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IAEH,GAAI,MAAM,YAAY,CAAC,IAAI;AAAA,EAC7B;AACF;AAIA,IAAM,eAAyC;AAAA,EAC7C,SAAS;AAAA,EACT,WAAW;AAAA,EACX,OAAO;AAAA,EACP,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AACV;AAUO,SAAS,yBACd,WACA,OACqB;AACrB,QAAM,QAAQ,UAAU,SAAS,CAAC;AAElC,QAAM,WAAW,aAAa,UAAU,IAAI;AAC5C,QAAM,gBAAgB,WAClB,SAAS,OAAO,KAAK,IACrB;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,EACZ;AAEJ,SAAO,EAAE,GAAG,WAAW,OAAO,cAAc;AAC9C;AAMO,SAAS,qBACd,YACA,OACuB;AACvB,SAAO,WAAW,IAAI,CAAC,cAAc;AACnC,UAAM,WAAW,yBAAyB,WAAW,KAAK;AAE1D,UAAM,WAAY,SAAiB;AAGnC,QAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,qBAAqB,UAAU,KAAK;AAAA,MAChD;AAAA,IACF;AAEA,WAAO;AAAA,EACT,CAAC;AACH;;;ACxCA,eAAsB,gBACpB,UACA,OACA,WACA,gBAC4B;AAC5B,QAAM,WAAW,uBAAuB,SAAS,OAAO,cAAc;AAItE,QAAM,cAAc,SAAS,MAAM;AACnC,QAAM,0BAA0B,cAC5BC,mBAAkB,aAAa,MAAM,qBAAqB,CAAC,CAAC,IAC5D;AAMJ,QAAM,kBAAkB,SAAS,MAAM;AACvC,QAAM,qBACJ,mBAAmB,MAAM,eACrB,MAAM;AAAA,IACJ,oBAAI,IAAI,CAAC,GAAI,MAAM,gBAAgB,CAAC,GAAI,GAAI,mBAAmB,CAAC,CAAE,CAAC;AAAA,EACrE,IACA;AAEN,QAAM,iBACJ,2BAA2B,qBACvB;AAAA,IACE,GAAG;AAAA,IACH,GAAI,2BAA2B;AAAA,MAC7B,mBAAmB;AAAA,IACrB;AAAA,IACA,GAAI,sBAAsB,EAAE,cAAc,mBAAmB;AAAA,EAC/D,IACA;AAIN,QAAM,UAAU;AAAA,IACd;AAAA,MACE;AAAA,MACA,UAAU,CAAC;AAAA,MACX,OAAO;AAAA,MACP;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,QAAM,mBAAmB;AAAA,IACvB,SAAS,YAAY,CAAC;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,WAAW,MAAM,gBAAgB,kBAAkB,OAAO;AAEhE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,gBAAgB,SAAS,MAAM;AAAA,IAC/B,UAAU,SAAS,MAAM;AAAA,EAC3B;AACF;AAKO,SAAS,uBACd,OACA,iBAAiB,oBAAI,KAAK,GACR;AAClB,SAAO;AAAA,IACL,OAAO,MAAM,UAAU;AAAA,IACvB,UAAU,MAAM,UAAU;AAAA,IAC1B,aAAa,MAAM,UAAU;AAAA,IAC7B,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,UAAU;AAAA,IACzB,SAAS,MAAM,UAAU;AAAA,IACzB,MAAM,MAAM,UAAU;AAAA,IACtB,MAAM,MAAM,UAAU,OAAO,IAAI,KAAK,MAAM,SAAS,IAAI,IAAI;AAAA,EAC/D;AACF;AAKA,eAAsB,gBACpB,YACA,SAC6B;AAC7B,QAAM,WAA+B,CAAC;AAGtC,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,aAAW,aAAa,kBAAkB;AACxC,QAAI,mBAAmB,SAAS,GAAG;AACjC,YAAM,oBAAoB,MAAM;AAAA,QAC9B,UAAU,YAAY,CAAC;AAAA,QACvB;AAAA,MACF;AAGA,YAAM,kBAAkB,UAAU,OAAO,cAAc;AAEvD,eAAS,KAAK;AAAA,QACZ,YAAY;AAAA,QACZ,QAAQ,UAAU,OAAO;AAAA,QACzB,QAAQ,UAAU,OAAO;AAAA,QACzB,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAInB,WAAW;AAAA;AAAA,QAEX,MAAM,UAAU,OAAO;AAAA,MACzB,CAAC;AAAA,IACH,OAAO;AAEL,eAAS,KAAK;AAAA,QACZ,YAAY,CAAC,SAAS;AAAA,QACtB,mBAAmB;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,kBACpB,YACA,SACgC;AAChC,QAAM,YAAmC,CAAC;AAG1C,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,aAAW,aAAa,kBAAkB;AACxC,QAAI,mBAAmB,SAAS,KAAK,UAAU,UAAU;AAEvD,gBAAU,KAAK;AAAA,QACb,GAAG;AAAA,QACH,UAAU,MAAM,kBAAkB,UAAU,UAAU,OAAO;AAAA,MAC/D,CAAC;AAAA,IACH,WAAW,mBAAmB,SAAS,KAAK,UAAU,UAAU;AAE9D,gBAAU,KAAK,GAAI,MAAM,kBAAkB,UAAU,UAAU,OAAO,CAAE;AAAA,IAC1E,OAAO;AAEL,gBAAU,KAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,oBACd,UACA,OACA,WACe;AACf,SAAO;AAAA,IACL,OAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,MAAM,UAAU,CAAC;AAAA,MACzB,OAAO,MAAM,QACT,OAAO;AAAA,QACL,OAAO,QAAQ,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC;AAAA,MACrE,IACA,CAAC;AAAA,MACL,SAAS,EAAE,OAAO,KAAK,QAAQ,KAAK,OAAO,KAAK,SAAS,IAAI;AAAA,IAC/D;AAAA,IACA,WAAW;AAAA,IACX,UAAU,SAAS;AAAA,IACnB,SAAS;AAAA,MACP,eAAe;AAAA,MACf,aAAa;AAAA,MACb,YAAY;AAAA,IACd;AAAA,IACA,OAAO;AAAA,MACL,YAAY,CAAC,SAAe,WAAW,IAAI;AAAA,MAC3C,WAAW,CAAC,SAAiB,CAAC,EAAE,KAAK,CAAC;AAAA,MACtC,UAAU,CAAC,UAAkB,EAAE,KAAK;AAAA,IACtC;AAAA,IACA,OAAO;AAAA,EACT;AACF;;;ACzQA,SAAS,aAAa,UAAU,kBAAkB;AAWlD;AAGA;AAkEO,SAAS,YACd,UACA,OACA,WACY;AACZ,QAAM,iBAAkC,CAAC;AAEzC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,eAAe,oBAAoB,QAAQ,UAAU;AAG3D,UAAM,sBAAsB,QAAQ,QAAQ,iBAAiB;AAI7D,QAAI,aAAa,WAAW,MAAM,QAAQ,UAAU,QAAQ,SAAS;AACnE,YAAM,iBAAiB,MAAM;AAC7B,YAAM,cAAc,kBAAkB,QAAQ,QAAQ,SAAS;AAC/D,YAAM,cAAc,cAAc,aAAa;AAE/C,qBAAe,KAAK;AAAA,QAClB,YAAY;AAAA,UACV,kBAAkB,QAAQ;AAAA,UAC1B;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,QACA,YAAY,CAAC;AAAA,QACb,YAAY;AAAA,QACZ;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA,QAChB,eAAe;AAAA,QACf,sBAAsB;AAAA,QACtB,cAAc,QAAQ;AAAA,MACxB,CAAC;AACD;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,YAAM,QAAQ,aAAa,CAAC;AAG5B,YAAM,uBACJ,MAAM,WAAW,WAAW,KAC5B,mBAAmB,MAAM,WAAW,CAAC,CAAC;AAExC,YAAM,iBAAiB,uBACnB,+BAA+B,MAAM,WAAW,CAAC,GAAG,OAAO,SAAS,IACpE,kBAAkB,MAAM,MAAM;AAGlC,YAAM,iBAAiB,MAAM,KAAK,MAAM;AAExC,YAAM,wBAAwB,QAAQ,QAAQ,aAAa,MAAM,CAAC;AAClE,YAAM,cACJ,MAAM,eAAe,kBAAkB;AACzC,YAAM,cAAc,cAAc,aAAa;AAG/C,YAAM,oBAAoB,uBACtB;AAAA,QAEI,MAAM,WAAW,CAAC,EAGlB,YAAY,CAAC;AAAA,MACjB,IACA,wBAAwB,MAAM,UAAU;AAE5C,qBAAe,KAAK;AAAA,QAClB,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,QACA,YAAY;AAAA,QACZ,YAAY,MAAM;AAAA,QAClB;AAAA,QACA,QAAQ,QAAQ;AAAA,QAChB,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,QAKhB,eAAe,uBAAuB,MAAM;AAAA,QAC5C,sBAAsB;AAAA;AAAA,QAEtB,cAAc,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,eAAe;AACpC;AAKO,SAAS,oBACd,YACe;AACf,QAAM,SAAwB,CAAC;AAC/B,MAAI,gBAA2C;AAC/C,MAAI,oBAA2C,CAAC;AAChD,MAAI,YAAY;AAEhB,aAAW,aAAa,YAAY;AAElC,QAAI,mBAAmB,SAAS,GAAG;AACjC,UAAI,kBAAkB,SAAS,GAAG;AAChC,eAAO,KAAK;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,aAAa;AAAA,QACf,CAAC;AACD,4BAAoB,CAAC;AACrB,oBAAY;AAAA,MACd;AAEA,YAAM,gBAAgB,yBAAyB,SAAS;AACxD,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,YAAY,CAAC,SAAS;AAAA,QACtB,aAAa;AAAA,MACf,CAAC;AACD,kBAAY;AACZ;AAAA,IACF;AAEA,UAAM,kBAAkB,yBAAyB,SAAS;AAG1D,QAAI,aAAa,SAAS,GAAG;AAC3B,UAAI,kBAAkB,SAAS,GAAG;AAEhC,eAAO,KAAK;AAAA,UACV,QAAQ;AAAA,UACR,YAAY;AAAA,UACZ,aAAa;AAAA,QACf,CAAC;AACD,4BAAoB,CAAC;AACrB,oBAAY;AAAA,MACd;AAEA,0BAAoB,CAAC,SAAS;AAC9B,kBAAY;AACZ;AAAA,IACF;AAGA,QAAI,oBAAoB,iBAAiB,kBAAkB,SAAS,GAAG;AACrE,aAAO,KAAK;AAAA,QACV,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,aAAa;AAAA,MACf,CAAC;AACD,sBAAgB;AAChB,0BAAoB,CAAC,SAAS;AAC9B,kBAAY;AAAA,IACd,OAAO;AACL,wBAAkB,KAAK,SAAS;AAAA,IAClC;AAAA,EACF;AAGA,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO,KAAK;AAAA,MACV,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKO,SAAS,yBACd,WAC2B;AAC3B,MAAI,mBAAmB,SAAS,GAAG;AACjC,UAAM,UAAW,UAAkB,OAAO;AAG1C,QAAI,MAAM,QAAQ,OAAO,GAAG;AAE1B,aAAO,QAAQ,UAAU,IAAI,iBAAiB;AAAA,IAChD;AAGA,WAAO;AAAA,EACT;AAGA,MAAI,cAAc,aAAc,UAAkB,UAAU;AAC1D,UAAM,aAAc,UAAkB,SAAS;AAAA,MAC7C,CAAC,UAA+B,mBAAmB,KAAK;AAAA,IAC1D;AACA,WAAO,aAAa,iBAAiB;AAAA,EACvC;AAEA,SAAO;AACT;AAKO,SAAS,wBACd,YACuB;AACvB,QAAM,YAAmC,CAAC;AAE1C,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,UAAM,YAAY,WAAW,CAAC;AAG9B,QAAI,wBAAwB,GAAG;AAE7B,UAAI,mBAAmB,SAAS,GAAG;AACjC,kBAAU,KAAK;AAAA,UACb,GAAG;AAAA,UACH,OAAO;AAAA,YACL,GAAK,UAAkB,SAAS,CAAC;AAAA,YACjC,aAAa;AAAA,UACf;AAAA,QACF,CAAwB;AAAA,MAC1B,OAAO;AACL,kBAAU,KAAK,SAAS;AAAA,MAC1B;AAAA,IACF,OAAO;AACL,gBAAU,KAAK,SAAS;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,0BAAmC;AAG1C,SAAO;AACT;AAKA,SAAS,aAAa,WAAyC;AAC7D,MAAI,mBAAmB,SAAS,GAAG;AAEjC,WAAO,UAAU,OAAO,cAAc;AAAA,EACxC;AACA,MAAI,mBAAmB,SAAS,GAAG;AACjC,WAAO,UAAU,MAAM,cAAc;AAAA,EACvC;AACA,MAAI,qBAAqB,SAAS,GAAG;AACnC,WAAO,UAAU,MAAM,cAAc;AAAA,EACvC;AAEA,MAAI,eAAe,SAAS,GAAG;AAC7B,WAAO,UAAU,OAAO,cAAc;AAAA,EACxC;AACA,SAAO;AACT;AAKO,SAAS,kBACd,QACgB;AAChB,UAAQ,QAAQ;AAAA,IACd,KAAK;AAGH,aAAO;AAAA,QACL,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,OAAO;AAAA;AAAA,MACT;AAAA,IACF,KAAK;AAAA,IACL;AACE,aAAO,EAAE,OAAO,EAAE;AAAA,EACtB;AACF;AAKO,SAAS,wBACd,gBACA,OACA,WACA,aACA,cAYuB;AAEvB,QAAM,gBAAgB,aAAa,OAAO,SAAS;AAQnD,QAAM,YAAY,eACd;AAAA,IACE,MAAM,aAAa,OACf,kBAAkB,aAAa,IAAI,IACnC,cAAc;AAAA,IAClB,QAAQ;AAAA,MACN,GAAG,cAAc;AAAA,MACjB,GAAI,aAAa,WAAW,CAAC;AAAA,IAC/B;AAAA,EACF,IACA;AAEJ,QAAM,aAAoC;AAAA,IACxC,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,OAAO,eAAe;AAAA,MACtB,YAAY,eAAe;AAAA,MAC3B,OAAO,eAAe;AAAA,IACxB;AAAA,EACF;AAGA,MACG,eAAuB,YACxB,MAAM,QAAS,eAAuB,QAAQ,GAC9C;AACA,UAAM,WAAY,eAAuB;AAMzC,eAAW,OAAO,aAAa;AAE/B,WAAO,WAAW,OAAO;AAEzB,eAAW,OAAO,WAAW,SAAS;AAAA,MACpC,CAAC,MACC,IAAI,WAAW;AAAA,QACb,OAAO,EAAE;AAAA,QACT,GAAI,EAAE,UAAU,SAAY,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAAA,MACpD,CAAC;AAAA,IACL;AAAA,EACF;AAEA,MAAI,aAAa;AACf,eAAW,OACT,gBAAgB,eACZ,YAAY,aACZ,YAAY;AAAA,EACpB;AAEA,SAAO;AACT;AAMA,SAAS,+BACP,WACA,OACA,WACgB;AAChB,QAAM,MAAQ,UAAkB,SAAS,CAAC;AAK1C,QAAM,UAAW,IAAI,WAAW,CAAC;AAKjC,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAAG;AACnD,WAAO,EAAE,OAAO,EAAE;AAAA,EACpB;AAEA,QAAM,sBAAsB,uBAAuB,OAAO,SAAS;AAGnE,QAAM,gBAAsD,CAAC;AAC7D,MAAI,oBAAoB;AACxB,MAAI,aAAa;AACjB,QAAM,0BAAoC,CAAC;AAE3C,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,IAAI,QAAQ,CAAC;AACnB,UAAM,QAA4C,CAAC;AAEnD,QAAI,EAAE,UAAU,QAAW;AACzB,YAAM,aAAa,sBAAsB,EAAE,OAAO,mBAAmB;AACrE,UAAI,aAAa,GAAG;AAClB,cAAM,QAAQ;AACd,6BAAqB;AAAA,MACvB;AAAA,IACF,OAAO;AACL,8BAAwB,KAAK,CAAC;AAAA,IAChC;AAEA,QAAI,EAAE,QAAQ,QAAW;AACvB,YAAM,aAAa,sBAAsB,EAAE,KAAK,mBAAmB;AACnE,UAAI,aAAa,GAAG;AAClB,cAAM,QAAQ;AACd,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,kBAAc,KAAK,KAAK;AAAA,EAC1B;AAGA,QAAM,iBAAiB,oBAAoB;AAC3C,QAAM,YAAY;AAClB,QAAM,UAAU,uBAAuB,IAAI;AAC3C,MAAI,iBAAiB,SAAS;AAC5B,UAAM,cAAe,iBAAiB,sBAAuB;AAE7D,UAAM,UAAU,cACb,IAAI,CAAC,GAAG,QAAQ;AACf,YAAM,OAAO,EAAE,SACT,EAAE,QAAQ,sBAAuB,KAAK,QAAQ,CAAC,IAAI,MACrD;AACJ,YAAM,OAAO,EAAE,SACT,EAAE,QAAQ,sBAAuB,KAAK,QAAQ,CAAC,IAAI,MACrD;AACJ,aAAO,cAAc,MAAM,CAAC,WAAW,IAAI,SAAS,IAAI;AAAA,IAC1D,CAAC,EACA,KAAK,IAAI;AACZ,UAAM,aACJ;AACF,UAAM,IAAI;AAAA,MACR,kEAAkE,YAAY,QAAQ,CAAC,CAAC,gBACtF,YAAY,KACZ;AAAA,QACA;AAAA,MACF,CAAC;AAAA;AAAA,EAA2B,OAAO;AAAA,cAAiB,UAAU;AAAA,IAChE;AAAA,EACF;AAGA,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA,sBAAsB,aAAa;AAAA,EACrC;AACA,MAAI,wBAAwB,SAAS,GAAG;AACtC,UAAM,OAAO,KAAK,MAAM,YAAY,wBAAwB,MAAM;AAClE,eAAW,OAAO,yBAAyB;AACzC,oBAAc,GAAG,EAAE,QAAQ;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AACF;;;ACljBA;AAAA,EACE;AAAA,EACA,aAAAC;AAAA,EAKA,WAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,eAAAC;AAAA,OAEK;;;ACjBP,SAAS,oBAAoB;AAC7B,OAAO,WAAW;;;ACDlB,SAAS,yBAAyB;AAClC,SAAS,YAAY,eAAe;AAEpC,IAAM,wBAAwB,IAAI,kBAAwB;AAGnD,SAAS,sBAAyB,MAAY,UAAsB;AACzE,SAAO,sBAAsB,IAAI,MAAM,QAAQ;AACjD;AAGO,SAAS,oBAA0B;AACxC,SAAO,sBAAsB,SAAS,KAAK,oBAAI,KAAK;AACtD;AAEA,IAAM,iBAAiB,IAAI,kBAA0B;AAQ9C,SAAS,eACd,SACA,UACG;AACH,SAAO,YAAY,SACf,SAAS,IACT,eAAe,IAAI,QAAQ,OAAO,GAAG,QAAQ;AACnD;AAGO,SAAS,aAAiC;AAC/C,SAAO,eAAe,SAAS;AACjC;AAOO,SAAS,mBAAmB,UAA0B;AAC3D,QAAM,OAAO,eAAe,SAAS;AACrC,MAAI,CAAC,QAAQ,WAAW,QAAQ,EAAG,QAAO;AAC1C,SAAO,QAAQ,MAAM,QAAQ;AAC/B;;;AD1CA;AADA,SAAS,gBAA2B;AAwB7B,SAAS,gBACd,OACA,kBACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAGA,QAAM,kBAAmB,MAAiB,MAAM,oBAAoB;AACpE,MAAI,iBAAiB;AACnB,UAAM,MAAM,WAAW,gBAAgB,CAAC,CAAC;AACzC,QAAI,MAAM,KAAK,MAAM,KAAK;AACxB,YAAM,IAAI;AAAA,QACR,6BAA6B,KAAK;AAAA,MACpC;AAAA,IACF;AACA,UAAM,WAAW,gCAAgC,KAAe;AAChE,QAAI,aAAa,QAAW;AAC1B,aAAO,KAAK,MAAM,mBAAmB,QAAQ;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR,wBAAwB,KAAK;AAAA,EAC/B;AACF;AAOO,SAAS,oBACd,OACA,aACQ;AACR,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,kBAAmB,MAAiB,MAAM,oBAAoB;AACpE,MAAI,iBAAiB;AACnB,UAAM,MAAM,WAAW,gBAAgB,CAAC,CAAC;AACzC,QAAI,MAAM,KAAK,MAAM,KAAK;AACxB,YAAM,IAAI;AAAA,QACR,6BAA6B,KAAK;AAAA,MACpC;AAAA,IACF;AACA,UAAM,WAAW,gCAAgC,KAAe;AAChE,QAAI,aAAa,OAAW,QAAO,KAAK,MAAM,cAAc,QAAQ;AAAA,EACtE;AACA,QAAM,IAAI;AAAA,IACR,4BAA4B,KAAK;AAAA,EACnC;AACF;AAKO,SAAS,WAAW,QAAyB;AAClD,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,MAAM;AAC1B,WAAO,IAAI,aAAa,WAAW,IAAI,aAAa;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,cAAc,QAAyB;AACrD,SAAO,kCAAkC,KAAK,MAAM;AACtD;AAOO,SAAS,kBAAkB,SAAyB;AACzD,MAAI;AAEF,UAAM,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC;AACvC,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AACA,WAAO,OAAO,KAAK,YAAY,QAAQ;AAAA,EACzC,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;AAOO,SAAS,2BACd,SACoB;AACpB,QAAM,QAAQ,QAAQ,MAAM,wCAAwC;AACpE,SAAO,QAAQ,MAAM,CAAC,IAAI;AAC5B;AAOO,SAAS,6BACdC,OACmD;AACnD,QAAM,YAAYA,MAAK,YAAY,EAAE,MAAM,GAAG,EAAE,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC;AACnE,UAAQ,WAAW;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,4BACd,UACmD;AACnD,QAAM,aAAa,SAAS,YAAY;AACxC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,MAAM,KAAK,WAAW,SAAS,KAAK,EAAG,QAAO;AACtE,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,MAAI,WAAW,SAAS,KAAK,EAAG,QAAO;AACvC,SAAO;AACT;AASO,SAAS,gBACd,WACA,qBACuC;AAEvC,MAAI,qBAAqB;AACvB,UAAM,mBAAmB,4BAA4B,mBAAmB;AACxE,QAAI,iBAAkB,QAAO;AAAA,EAC/B;AAGA,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,WAAW,2BAA2B,SAAS;AACrD,QAAI,UAAU;AACZ,YAAM,eAAe,4BAA4B,QAAQ;AACzD,UAAI,aAAc,QAAO;AAAA,IAC3B;AAAA,EACF;AAGA,QAAM,oBAAoB,6BAA6B,SAAS;AAChE,MAAI,kBAAmB,QAAO;AAG9B,SAAO;AACT;AAOO,SAAS,oBAAoB,MAKvB;AACX,QAAM,OAAO;AAAA,IACX,MAAM,KAAK;AAAA,IACX,gBAAgB,KAAK;AAAA,IACrB,GAAI,KAAK,YAAY,EAAE,UAAU,KAAK,SAAS;AAAA,EACjD;AACA,MAAI,KAAK,SAAS,OAAO;AACvB,WAAO,IAAI,SAAS;AAAA,MAClB,MAAM;AAAA,MACN,GAAG;AAAA,MACH,UAAU,EAAE,MAAM,OAAO,MAAM,KAAK,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO,IAAI,SAAS,EAAE,MAAM,KAAK,MAAM,GAAG,KAAK,CAAC;AAClD;AAMA,eAAsB,qBACpB,KAC4B;AAC5B,MAAI;AAEF,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,GAAK;AAE5D,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ,WAAW;AAAA,MACnB,SAAS;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,MACA,UAAU;AAAA;AAAA,IACZ,CAAC;AAED,iBAAa,SAAS;AAEtB,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,kCAAkC,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,MAC1E;AAAA,IACF;AAEA,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAG5D,UAAM,cAAc,MAAM,SAAS,YAAY;AAG/C,WAAO,EAAE,QAAQ,OAAO,KAAK,WAAW,GAAG,YAAY;AAAA,EACzD,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAE1B,UAAI,MAAM,SAAS,cAAc;AAC/B,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,IAAI,MAAM,iCAAiC,GAAG,KAAK,MAAM,OAAO,EAAE;AAAA,IAC1E;AACA,UAAM,IAAI,MAAM,iCAAiC,GAAG,iBAAiB;AAAA,EACvE;AACF;AAUO,SAAS,mBAAmB,OAIZ;AACrB,QAAM,WAAW,CAAC,MAChB,OAAO,MAAM,YAAY,EAAE,KAAK,EAAE,SAAS;AAC7C,MAAI,SAAS,MAAM,GAAG,GAAG;AACvB,UAAM,UAAU,OAAO,KAAK,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AACjE,WAAO,6BAA6B,OAAO;AAAA,EAC7C;AAGA,MAAI,SAAS,MAAM,MAAM,EAAG,QAAO,MAAM;AACzC,MAAI,SAAS,MAAM,IAAI,EAAG,QAAO,MAAM;AACvC,SAAO;AACT;AAKA,eAAsB,eACpB,WAC4B;AAE5B,MAAI,cAAc,SAAS,GAAG;AAC5B,WAAO,EAAE,QAAQ,kBAAkB,SAAS,EAAE;AAAA,EAChD;AAEA,MAAI,WAAW,SAAS,GAAG;AACzB,WAAO,MAAM,qBAAqB,SAAS;AAAA,EAC7C;AAGA,SAAO,EAAE,QAAQ,aAAa,mBAAmB,SAAS,CAAC,EAAE;AAC/D;AAKA,eAAsB,mBACpB,WAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,eAAe,SAAS;AAC9D,UAAM,SAAS,MAAM,KAAK,WAAW;AAErC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,6CAA6C,SAAS,EAAE;AAAA,IAC1E;AAEA,WAAO;AAAA,MACL,OAAO,OAAO;AAAA,MACd,QAAQ,OAAO;AAAA,IACjB;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,uCAAuC,SAAS,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC7G;AAAA,EACF;AACF;AAKO,SAAS,0BACd,eACA,gBACA,aACA,cACsB;AACtB,MAAI,eAAe,cAAc;AAE/B,WAAO,EAAE,OAAO,aAAa,QAAQ,aAAa;AAAA,EACpD;AAEA,QAAM,cAAc,gBAAgB;AAEpC,MAAI,eAAe,CAAC,cAAc;AAEhC,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,KAAK,MAAM,cAAc,WAAW;AAAA,IAC9C;AAAA,EACF;AAEA,MAAI,CAAC,eAAe,cAAc;AAEhC,WAAO;AAAA,MACL,OAAO,KAAK,MAAM,eAAe,WAAW;AAAA,MAC5C,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,SAAO,EAAE,OAAO,eAAe,QAAQ,eAAe;AACxD;AAKA,eAAsB,yBACpB,WACA,aACA,cACA,gBAAwB,KACxB,iBAAyB,KACM;AAC/B,MAAI;AACF,UAAM,qBAAqB,MAAM,mBAAmB,SAAS;AAC7D,WAAO;AAAA,MACL,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,eAAe,cAAc;AAC/B,aAAO,EAAE,OAAO,aAAa,QAAQ,aAAa;AAAA,IACpD;AAEA,QAAI,eAAe,CAAC,cAAc;AAEhC,aAAO,EAAE,OAAO,aAAa,QAAQ,KAAK,MAAO,cAAc,IAAK,EAAE,EAAE;AAAA,IAC1E;AAEA,QAAI,CAAC,eAAe,cAAc;AAEhC,aAAO;AAAA,QACL,OAAO,KAAK,MAAO,eAAe,KAAM,CAAC;AAAA,QACzC,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,WAAO,EAAE,OAAO,eAAe,QAAQ,eAAe;AAAA,EACxD;AACF;;;ADrZA;;;AGnBA;AAEA;AACA;AAVA;AAAA,EAIE;AAAA,EACA;AAAA,OACK;AA8EP,SAAS,iBAAiB,MAAiC;AACzD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,IAAI;AACjB;AAKA,SAAS,aACP,OACA,WAC6B;AAC7B,MAAI,CAAC,iBAAiB,SAAS,GAAG;AAChC,YAAQ,KAAK,uBAAuB,SAAS,EAAE;AAC/C,WAAO;AAAA,EACT;AACA,SAAO,MAAM,SAAS,SAAS;AACjC;AAYA,SAAS,0BACP,OACA,WACA,UAAuB,oBAAI,IAAI,GACF;AAE7B,MAAI,QAAQ,IAAI,SAAS,GAAG;AAC1B,YAAQ;AAAA,MACN,0CAA0C,MAAM,KAAK,OAAO,EAAE;AAAA,QAC5D;AAAA,MACF,CAAC,WAAM,SAAS;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAEA,UAAQ,IAAI,SAAS;AAGrB,QAAM,QAAQ,aAAa,OAAO,SAAS;AAC3C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,IACN,IAAI,IAAI,OAAO;AAAA;AAAA,EACjB;AAEA,MAAI,CAAC,WAAW;AAEd,WAAO;AAAA,EACT;AAIA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,EACF;AAIA,MAAI,MAAM,YAAY,UAAa,UAAU,YAAY,QAAW;AAClE,gBAAY,UAAU,UAAU;AAAA,EAClC,WAAW,MAAM,YAAY,QAAW;AACtC,gBAAY,UAAU,MAAM;AAAA,EAC9B;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB;AACE,aAAO,cAAc;AAAA,EACzB;AACF;AAKA,SAAS,eAAe,SAGtB;AACA,SAAO;AAAA,IACL,QAAQ,SAAS,SAAS,cAAc,QAAQ,MAAM,IAAI;AAAA,IAC1D,OAAO,SAAS,QAAQ,cAAc,QAAQ,KAAK,IAAI;AAAA,EACzD;AACF;AAKA,SAAS,qBACP,QACA,OACA,cACA,aAC4B;AAC5B,SAAO;AAAA,IACL,MAAM,OAAO,UAAU;AAAA,IACvB,OAAO,OAAO,QAAQ,eAAe,MAAM;AAAA,IAC3C,OAAO;AAAA,MACL,OAAO,SAAS,gBAAgB,MAAM,OAAO;AAAA,MAC7C;AAAA,IACF;AAAA,IACA,GAAI,OAAO,SAAS,UAAa,EAAE,MAAM,OAAO,KAAK;AAAA,IACrD,GAAI,OAAO,WAAW,UAAa,EAAE,QAAQ,OAAO,OAAO;AAAA,IAC3D,GAAI,OAAO,cAAc,UACvB,OAAO,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,IACtD,GAAI,OAAO,oBAAoB;AAAA,MAC7B,kBACE,OAAO,iBAAiB,SAAS,cAC7B,CAAC,OAAO,iBAAiB,QACzB,OAAO,iBAAiB;AAAA,IAChC;AAAA,IACA,GAAI,OAAO,SAAS,EAAE,OAAO,OAAO,MAAM;AAAA,EAC5C;AACF;AAKA,SAAS,2BACP,QACA,YACA,OACkC;AAClC,SAAO;AAAA,IACL,SAAS;AAAA,MACP,GAAG,eAAe,OAAO,OAAO;AAAA,MAChC,GAAG,mBAAmB,OAAO,WAAW;AAAA,IAC1C;AAAA,IACA,WAAW,iBAAiB,OAAO,aAAa,MAAM;AAAA,IACtD,GAAI,YAAY,aAAa,UAAa;AAAA,MACxC,UAAU,WAAW;AAAA,IACvB;AAAA,IACA,GAAI,YAAY,sBAAsB,UAAa;AAAA,MACjD,WAAW,WAAW;AAAA,IACxB;AAAA,IACA,GAAI,YAAY,iBAAiB,UAAa;AAAA,MAC5C,cAAc,WAAW;AAAA,IAC3B;AAAA,IACA,GAAI,YAAY,iBAAiB,UAAa;AAAA,MAC5C,cAAc,WAAW;AAAA,IAC3B;AAAA,IACA,GAAI,YAAY,WACd,SAAS;AAAA,MACP,QAAQ,eAAe,WAAW,SAAS,KAAK;AAAA,IAClD;AAAA,IACF,GAAI,YAAY,UAAU;AAAA,MACxB,QAAQ;AAAA,QACN,GAAI,WAAW,OAAO,SAAS,UAAa;AAAA,UAC1C,MAAM,WAAW,OAAO;AAAA,QAC1B;AAAA,QACA,GAAI,WAAW,OAAO,YAAY,UAAa;AAAA,UAC7C,SAAS,WAAW,OAAO;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAYA,SAAS,eACP,SACA,OACkE;AAClE,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,UAAU,CAAC,SACf,OACI;AAAA,IACE,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK;AAAA,IACX,OAAO,aAAa,KAAK,OAAO,KAAK;AAAA,IACrC,GAAI,KAAK,UAAU,SAAY,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,EAC1D,IACA;AAEN,QAAM,QAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAAkE,CAAC;AACzE,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,QAAQ,QAAQ,IAAI,CAAC;AACnC,QAAI,MAAO,WAAU,IAAI,IAAI;AAAA,EAC/B;AAEA,SAAO,OAAO,KAAK,SAAS,EAAE,SAAS,IAAI,YAAY;AACzD;AAiBO,SAAS,iBACd,oBAA0C,WAC1C,UACgB;AAChB,QAAM,QACJ,OAAO,sBAAsB,WACzB,SAAS,iBAAiB,KAAK,SAAS,SAAS,IACjD;AAEN,QAAM,kBAAyC;AAAA;AAAA,IAE7C;AAAA,MACE,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,cACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,cAAM,YAAY,sBAAsB,OAAO,aAAa,IAAI;AAChE,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,aAAa;AAAA,UACnB,OAAO,aAAa;AAAA,UACpB,MAAM,aAAa;AAAA,UACnB,QAAQ,aAAa;AAAA,UACrB,WAAW,aAAa;AAAA,UACxB,kBAAkB,aAAa;AAAA,UAC/B,OAAO,aAAa;AAAA,QACtB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,MAC9D,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,cACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,cAAM,YAAY,sBAAsB,OAAO,aAAa,IAAI;AAChE,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,aAAa;AAAA,UACxB,aAAa,aAAa;AAAA,UAC1B,SAAS,aAAa;AAAA,QACxB,CAAC;AAED,eAAO,2BAA2B,QAAQ,aAAa,KAAK;AAAA,MAC9D,GAAG;AAAA,IACL;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAM,aAAa,UAAU,CAAC;AAC9B,UAAM,kBAAkB,MAAM,SAAS,UAAU;AAIjD,QAAI,iBAAiB;AACnB,YAAM,eACJ,0BAA0B,OAAO,UAAU,KAAK;AAClD,sBAAgB,KAAK;AAAA,QACnB,IAAI,UAAU,CAAC;AAAA,QACf,MAAM,WAAW,CAAC;AAAA,QAClB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,aAAa;AAAA,YACnB,OAAO,aAAa;AAAA,YACpB,MAAM,aAAa;AAAA,YACnB,QAAQ,aAAa;AAAA,YACrB,WAAW,aAAa;AAAA,YACxB,kBAAkB,aAAa;AAAA,YAC/B,OAAO,aAAa;AAAA,UACtB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,QACrE,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,aAAa;AAAA,YACxB,aAAa,aAAa;AAAA,YAC1B,SAAS,aAAa;AAAA,UACxB,CAAC;AAED,iBAAO,2BAA2B,QAAQ,cAAc,KAAK;AAAA,QAC/D,GAAG;AAAA,MACL,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,sBAAgB,KAAK;AAAA,QACnB,IAAI,UAAU,CAAC;AAAA,QACf,MAAM,WAAW,CAAC;AAAA,QAClB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,UAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,UAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,UACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,QAC3D;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ,OAAO,IAAI,KAAK;AAAA,YACxB,OAAO,OAAO,IAAI,KAAK;AAAA,YACvB,GAAG,mBAAmB,UAAU,WAAW;AAAA,UAC7C;AAAA,UACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,UAAM,aAAa,UAAU,CAAC;AAC9B,UAAM,kBAAkB,MAAM,SAAS,UAAU;AAIjD,QAAI,iBAAiB;AACnB,YAAM,eACJ,0BAA0B,OAAO,UAAU,CAAC,EAAE,KAAK;AAErD,sBAAgB,KAAK;AAAA,QACnB,IAAI,kBAAkB,CAAC;AAAA,QACvB,MAAM,gBAAgB,CAAC;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,aAAa;AAAA,YACnB,OAAO,aAAa;AAAA,YACpB,MAAM,aAAa;AAAA,YACnB,QAAQ,aAAa;AAAA,YACrB,WAAW,aAAa;AAAA,YACxB,kBAAkB,aAAa;AAAA,YAC/B,OAAO,aAAa;AAAA,UACtB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,QACrE,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,aAAa,QAAQ;AAAA,UACvB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,aAAa;AAAA,YACxB,aAAa,aAAa;AAAA,YAC1B,SAAS,aAAa;AAAA,UACxB,CAAC;AAGD,iBAAO;AAAA,YACL;AAAA,YACA,EAAE,GAAI,cAAsB,cAAc,OAAU;AAAA,YACpD;AAAA,UACF;AAAA,QACF,GAAG;AAAA,MACL,CAAC;AAAA,IACH,OAAO;AAEL,YAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,sBAAgB,KAAK;AAAA,QACnB,IAAI,kBAAkB,CAAC;AAAA,QACvB,MAAM,gBAAgB,CAAC;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,UAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,UAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,UACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,QAC3D;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ,OAAO,IAAI,KAAK;AAAA,YACxB,OAAO,OAAO,IAAI,KAAK;AAAA,YACvB,GAAG,mBAAmB,UAAU,WAAW;AAAA,UAC7C;AAAA,UACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,OAAO;AACvB,UAAM,aACJ,0BAA0B,OAAO,OAAO,KAAK,MAAM,OAAO;AAC5D,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,WAAW;AAAA,UACjB,OAAO,WAAW;AAAA,UAClB,MAAM,WAAW;AAAA,UACjB,QAAQ,WAAW;AAAA,UACnB,WAAW,WAAW;AAAA,UACtB,kBAAkB,WAAW;AAAA,UAC7B,OAAO,WAAW;AAAA,QACpB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS,EAAE;AAAA,MACrE,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,WAAW,QAAQ;AAAA,QACrB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,WAAW;AAAA,UACtB,aAAa,WAAW;AAAA,UACxB,SAAS,WAAW;AAAA,QACtB,CAAC;AAED,eAAO,2BAA2B,QAAQ,YAAY,KAAK;AAAA,MAC7D,GAAG;AAAA,IACL,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,YAAY,sBAAsB,OAAO,SAAS;AACxD,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM,UAAU,UAAU;AAAA,QAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,QAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,QAClE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,QAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,MAC3D;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,OAAO;AAAA,UACP,GAAG,mBAAmB,UAAU,WAAW;AAAA,QAC7C;AAAA,QACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAGA,MAAI,MAAM,QAAQ,UAAU;AAC1B,UAAM,gBACJ,0BAA0B,OAAO,UAAU,KAAK,MAAM,OAAO;AAC/D,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,MAAM,MAAM;AACV,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,cAAc,QAAQ;AAAA,QACxB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,MAAM,cAAc;AAAA,UACpB,OAAO,cAAc;AAAA,UACrB,MAAM,cAAc;AAAA,UACpB,QAAQ,cAAc;AAAA,UACtB,WAAW,cAAc;AAAA,UACzB,kBAAkB,cAAc;AAAA,UAChC,OAAO,cAAc;AAAA,QACvB,CAAC;AAED,eAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,SAAS;AAAA,MACnE,GAAG;AAAA,MACH,YAAY,MAAM;AAChB,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,cAAc,QAAQ;AAAA,QACxB;AACA,cAAM,SAAS,4BAA4B,WAAW;AAAA,UACpD,WAAW,cAAc;AAAA,UACzB,aAAa,cAAc;AAAA,UAC3B,SAAS,cAAc;AAAA,QACzB,CAAC;AAED,eAAO,2BAA2B,QAAQ,eAAe,KAAK;AAAA,MAChE,GAAG;AAAA,IACL,CAAC;AAAA,EACH,OAAO;AAEL,UAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,oBAAgB,KAAK;AAAA,MACnB,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM,UAAU,UAAU;AAAA,QAC1B,OAAO,UAAU,QAAQ,MAAM;AAAA,QAC/B,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,QACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,QAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACjE,GAAI,UAAU,cAAc,UAC1B,UAAU,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,EAAE;AAAA,MAC3D;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,OAAO;AAAA,UACP,GAAG,mBAAmB,UAAU,WAAW;AAAA,QAC7C;AAAA,QACA,WAAW,iBAAiB,UAAU,aAAa,MAAM;AAAA,MAC3D;AAAA,IACF,CAAC;AAAA,EACH;AAEA,kBAAgB;AAAA;AAAA,KAEb,MAAM;AACL,YAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,MAAM;AAAA;AAAA,UACN,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,UACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACnE;AAAA,QACA,WAAW;AAAA,UACT,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,GAAG;AAAA;AAAA,KAGF,MAAM;AACL,YAAM,YAAY,sBAAsB,OAAO,MAAM;AACrD,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,QACN,aAAa;AAAA,QACb,KAAK;AAAA,UACH,MAAM,UAAU,UAAU;AAAA,UAC1B,MAAM;AAAA;AAAA,UACN,OAAO,aAAa,UAAU,SAAS,MAAM,OAAO,WAAW,KAAK;AAAA,UACpE,GAAI,UAAU,SAAS,UAAa,EAAE,MAAM,UAAU,KAAK;AAAA,UAC3D,GAAI,UAAU,WAAW,UAAa,EAAE,QAAQ,UAAU,OAAO;AAAA,QACnE;AAAA,QACA,WAAW;AAAA,UACT,SAAS;AAAA,YACP,QAAQ;AAAA,UACV;AAAA,UACA,WAAW;AAAA;AAAA,QAEb;AAAA,MACF;AAAA,IACF,GAAG;AAAA,EACL;AAGA,QAAM,sBAAsB,oBAAI,IAAI;AAAA,IAClC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,MAAM,QAAQ;AAChB,eAAW,CAAC,UAAU,UAAU,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AAEjE,UAAI,oBAAoB,IAAI,QAAQ,GAAG;AACrC;AAAA,MACF;AAGA,UAAI,CAAC,YAAY;AACf;AAAA,MACF;AAIA,YAAM,WAAW,eAAe,KAAK,QAAQ;AAI7C,YAAM,cAAc,WAChB,aACA,0BAA0B,OAAO,QAAQ,KAAK;AAKlD,YAAM,UAAU,WAAW,MAAM,SAAS,CAAC,CAAC,KAAK;AACjD,YAAM,YAAY,WACd,OAAO,SAAS,CAAC,CAAC,KAClB,SAAS,QAAQ,YAAY,KAAK,EAAE,KAAK;AAG7C,YAAM,iBAAiB,CAAC,SAAkB;AACxC,YAAI,CAAC,KAAM,QAAO;AAClB,cAAM,QAAQ,KAAK,YAAY;AAC/B,YAAI,UAAU,SAAU,QAAO;AAC/B,YAAI,UAAU,QAAS,QAAO;AAC9B,YAAI,UAAU,WAAY,QAAO;AACjC,cAAM,IAAI,MAAM,MAAM,kBAAkB;AACxC,YAAI,EAAG,QAAO,UAAU,EAAE,CAAC,CAAC;AAE5B,eAAO;AAAA,MACT;AAEA,sBAAgB,KAAK;AAAA,QACnB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,WACL,WACA,eAAgB,YAAgC,SAAS;AAAA,QAC7D,MAAM,YAAY,kBAAkB;AAAA,QACpC,aAAa,WACT,QACA,YAAY,aAAa,SACvB,OACA;AAAA,QACN,MAAM,MAAM;AACV,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,YAAY,QAAQ;AAAA,UACtB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,MAAM,YAAY;AAAA,YAClB,OAAO,YAAY;AAAA,YACnB,MAAM,YAAY;AAAA,YAClB,QAAQ,YAAY;AAAA,YACpB,WAAW,YAAY;AAAA,YACvB,kBAAkB,YAAY;AAAA,YAC9B,OAAO,YAAY;AAAA,UACrB,CAAC;AAED,iBAAO,qBAAqB,QAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,QAC9D,GAAG;AAAA,QACH,YAAY,MAAM;AAChB,gBAAM,YAAY;AAAA,YAChB;AAAA,YACA,YAAY,QAAQ;AAAA,UACtB;AACA,gBAAM,SAAS,4BAA4B,WAAW;AAAA,YACpD,WAAW,YAAY;AAAA,YACvB,aAAa,YAAY;AAAA,YACzB,SAAS,YAAY;AAAA,UACvB,CAAC;AAGD,gBAAM,YAAY;AAAA,YAChB;AAAA;AAAA,YAEA,WACI,EAAE,GAAG,aAAa,cAAc,OAAU,IAC1C;AAAA,YACJ;AAAA,UACF;AAGA,gBAAM,WAAY,YAAoB;AACtC,gBAAM,qBAAqB,WACvB,CAAC,EAAE,MAAM,SAAS,UAAU,OAAO,QAAQ,OAAO,CAAC,IACnD;AACJ,gBAAM,oBACJ,YAAY,SAAS,SAAS,IAAI,WAAW;AAE/C,iBAAO;AAAA,YACL,GAAG;AAAA,YACH,GAAI,qBAAqB;AAAA,cACvB,UAAU,kBAAkB,IAAI,CAAC,QAAa;AAAA,gBAC5C,MAAM,GAAG;AAAA,gBACT,UACE,GAAG,aAAa,QAAQ,gBAAgB,MAAM,IAAI,GAAG;AAAA,gBACvD,GAAI,GAAG,UAAU,EAAE,QAAQ,GAAG,OAAO;AAAA,cACvC,EAAE;AAAA,YACJ;AAAA,UACF;AAAA,QACF,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AAIA,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAE3B,QACE,MAAM,UACN,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,MAAM,CAAC,EAAE,GAC5D;AACA;AAAA,IACF;AAEA,oBAAgB,KAAK;AAAA;AAAA,MAEnB,IAAI,MAAM,CAAC;AAAA,MACX,MAAM,OAAO,CAAC;AAAA,MACd,SAAS;AAAA,MACT,MAAM;AAAA,MACN,aAAa;AAAA,MACb,KAAK;AAAA,QACH,MAAM;AAAA,QACN,MAAM;AAAA;AAAA,QACN,OAAO,aAAa,MAAM,OAAO,MAAM,KAAK;AAAA,MAC9C;AAAA,MACA,WAAW;AAAA,QACT,SAAS;AAAA,UACP,GAAG,eAAe,EAAE,QAAQ,GAAG,OAAO,EAAE,CAAC;AAAA;AAAA,QAC3C;AAAA,QACA,WAAW,iBAAiB,MAAM;AAAA;AAAA,QAElC,QAAQ,EAAE,OAAO,IAAI,KAAK,IAAI;AAAA;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH;AAOA,QAAM,YACJ,0BAA0B,OAAO,QAAQ,KAAK,MAAM,QAAQ;AAC9D,QAAM,UAAU;AAAA,IACd,4BAA4B,sBAAsB,OAAO,WAAW,IAAI,GAAG;AAAA,MACzE,MAAM,WAAW;AAAA,MACjB,OAAO,WAAW;AAAA,IACpB,CAAC;AAAA,IACD;AAAA,IACA,MAAM,OAAO;AAAA,EACf;AAIA,QAAM,UAAU;AAAA,IACd,GAAG;AAAA,IACH,GAAI,OAAO,QAAQ,SAAS,YAAY;AAAA,MACtC,MAAM,KAAK,IAAI,IAAI,QAAQ,OAAO,CAAC;AAAA,IACrC;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA;AAAA,IACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAKP,GAAI,YAAY;AAAA,QACd,UAAU;AAAA,UACR,KAAK;AAAA,YACH,UAAU,EAAE,OAAO,SAAS;AAAA,UAC9B;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAIA,cAAc,EAAE,KAAK,QAAQ;AAAA,MAC7B,mBAAmB,EAAE,KAAK,EAAE,GAAG,SAAS,aAAa,KAAK,EAAE;AAAA,MAC5D,aAAa,EAAE,KAAK,QAAQ;AAAA,MAC5B,kBAAkB,EAAE,KAAK,EAAE,GAAG,SAAS,aAAa,KAAK,EAAE;AAAA,IAC7D;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,OAAuB;AACxD,QAAM,WAAsC;AAAA,IAC1C,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACA,SAAO,SAAS,KAAK,KAAK;AAC5B;;;AH54BA;AACA;;;AIpDA;AAAA;AAAA;AAAA;AAKA;AAAA,4BAAc;;;ACAd,SAAS,cAAAC,mBAAkB;AAOpB,IAAM,oBAAN,MAAwB;AAAA,EACZ;AAAA,EAEjB,YAAY,UAAkB,OAAO;AACnC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,YACE,WACA,SACA,UAA2B,CAAC,GACpB;AACR,UAAM,QAAkB;AAAA,MACtB,KAAK;AAAA,MACL,UAAU;AAAA,MACV,KAAK,UAAU,UAAU,KAAK;AAAA,IAChC;AAEA,QAAI,QAAQ,iBAAiB,OAAO;AAClC,YAAM,KAAK,QAAQ,MAAM,IAAI;AAAA,IAC/B;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,YAAM,KAAK,KAAK,YAAY,OAAO,CAAC;AAAA,IACtC;AAEA,QAAI,QAAQ,gBAAgB;AAC1B,YAAM,KAAK,GAAG,QAAQ,cAAc;AAAA,IACtC;AAEA,QAAI,QAAQ,SAAS;AACnB,YAAM,KAAK,QAAQ,OAAO;AAAA,IAC5B;AAEA,WAAO,MAAM,KAAK,GAAG;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,OAAoB;AAC5B,QAAI,CAAC,MAAO,QAAO;AAGnB,UAAM,aAAa,KAAK,gBAAgB,KAAK;AAC7C,UAAM,OAAO,KAAK,UAAU,UAAU;AAEtC,WAAO,KAAK,KAAK,IAAI;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,SAAgC;AAElD,UAAM,WAAW;AAAA,MACf,OAAO,QAAQ,MAAM;AAAA,MACrB,UAAU,QAAQ;AAAA;AAAA,IAEpB;AAEA,WAAO,KAAK,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,KAAe;AACrC,QAAI,QAAQ,QAAQ,QAAQ,OAAW,QAAO;AAE9C,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI,IAAI,CAAC,SAAS,KAAK,gBAAgB,IAAI,CAAC;AAAA,IACrD;AAEA,QAAI,eAAe,MAAM;AACvB,aAAO,IAAI,YAAY;AAAA,IACzB;AAEA,QAAI,OAAO,QAAQ,UAAU;AAC3B,YAAM,SAAc,CAAC;AACrB,YAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AAEnC,iBAAW,OAAO,MAAM;AACtB,eAAO,GAAG,IAAI,KAAK,gBAAgB,IAAI,GAAG,CAAC;AAAA,MAC7C;AAEA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,KAAK,OAAuB;AAClC,WAAOA,YAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,EAAE;AAAA,EACzE;AACF;;;AC1GA,SAAS,WAAAC,UAAS,iBAAiB,sBAAsB;;;ACHlD,SAAS,qBAAqB,MAAyC;AAC5E,UAAQ,QAAQ,IAAI,UAAU,KAAK;AACrC;;;ACDA;AAAA,EACE,WAAAC;AAAA,EACA;AAAA,OAKK;;;ACZP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA4EP,IAAM,wBAAwB;AAE9B,SAAS,aAAa,GAAmB;AACvC,SAAO,EAAE,QAAQ,uBAAuB,MAAM;AAChD;AAQO,SAAS,uBAAuB,cAAwC;AAC7E,QAAM,SAAS,gBAAgB,CAAC,GAAG,OAAO,CAAC,MAAM,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC;AACzE,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,QAAM,UAAU,MACb,MAAM,EACN,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAClC,IAAI,YAAY;AACnB,SAAO,IAAI;AAAA,IACT,yBAAyB,QAAQ,KAAK,GAAG,CAAC;AAAA,IAC1C;AAAA,EACF;AACF;AAOO,SAAS,oBACd,MACA,SACA,cACW;AACX,QAAM,QAAQ,uBAAuB,YAAY;AACjD,MAAI,CAAC,SAAS,CAAC,KAAM,QAAO,CAAC,QAAQ,MAAM,KAAK,CAAC;AAEjD,QAAM,OAAkB,CAAC;AACzB,MAAI,YAAY;AAChB,MAAI;AACJ,UAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,QAAI,MAAM,QAAQ,WAAW;AAC3B,WAAK,KAAK,QAAQ,KAAK,MAAM,WAAW,MAAM,KAAK,GAAG,KAAK,CAAC;AAAA,IAC9D;AACA,SAAK,KAAK,QAAQ,MAAM,CAAC,GAAG,IAAI,CAAC;AACjC,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAEnC,QAAI,MAAM,cAAc,MAAM,MAAO,OAAM;AAAA,EAC7C;AACA,MAAI,YAAY,KAAK,QAAQ;AAC3B,SAAK,KAAK,QAAQ,KAAK,MAAM,SAAS,GAAG,KAAK,CAAC;AAAA,EACjD;AACA,SAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,MAAM,KAAK,CAAC;AACvD;AAiBO,SAAS,wBACd,MACA,YAAuB,CAAC,GACxB,UAAgC,CAAC,GACb;AAEpB,MAAI,CAAC,MAAM;AACT,WAAO,CAAC,IAAI,QAAQ,EAAE,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC;AAAA,EACjD;AACA,QAAM,iBAAiB,qBAAqB,IAAI;AAGhD,QAAM,kBAAkB,YAAY,KAAK,cAAc;AAEvD,MAAI,iBAAiB;AAEnB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,QAAQ,sBAAsB,CAAC;AAAA,MAC/B,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,MAAI,QAAQ,kBAAkB;AAC5B,WAAO,wBAAwB,gBAAgB,WAAW,OAAO;AAAA,EACnE;AAGA,QAAM,OAA2B,CAAC;AAGlC,QAAM,iBACJ;AAEF,MAAI,YAAY;AAChB,MAAI;AAEJ,UAAQ,QAAQ,eAAe,KAAK,cAAc,OAAO,MAAM;AAE7D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,YAAY,eAAe,UAAU,WAAW,MAAM,KAAK;AACjE,UAAI,WAAW;AACb,aAAK,KAAK,GAAG,2BAA2B,WAAW,WAAW,OAAO,CAAC;AAAA,MACxE;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,OAAO,UAAU,QAAQ;AAC7B,QAAI,UAAU,UAAU,WAAW;AAEnC,QAAI,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,OAAO;AAE5C,sBAAgB,MAAM,CAAC;AACvB,aAAO;AACP,gBAAU;AAAA,IACZ,WAAW,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,MAAM;AAEjD,sBAAgB,MAAM,CAAC;AACvB,aAAO;AAAA,IACT,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,KAAK;AAE/C,sBAAgB,MAAM,CAAC;AACvB,gBAAU;AAAA,IACZ,OAAO;AAEL,sBAAgB,MAAM,CAAC;AAAA,IACzB;AAGA,UAAM,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,SAAK,KAAK,GAAG,aAAa;AAE1B,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,WAAK;AAAA,QACH,GAAG,2BAA2B,eAAe,WAAW,OAAO;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,gBAAgB;AACvC,SAAK;AAAA,MACH,GAAG,2BAA2B,gBAAgB,WAAW,OAAO;AAAA,IAClE;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,oBACd,WACA,WACA;AACA,QAAM,OAAO,WAAW,QAAQ,UAAU;AAC1C,QAAM,UAAU,WAAW,WAAW,UAAU;AAChD,SAAO;AAAA,IACL,GAAI,UAAU,QAAQ,EAAE,MAAM,UAAU,KAAK;AAAA,IAC7C,GAAI,UAAU,QAAQ,EAAE,MAAM,UAAU,KAAK;AAAA,IAC7C,GAAI,UAAU,SAAS;AAAA,MACrB,OACE,QAAQ,WAAW,YAAY,UAAU,YAAY,UAAU;AAAA,IACnE;AAAA,IACA,GAAI,SAAS,UAAa,EAAE,KAAK;AAAA,IACjC,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,IACvC,GAAI,UAAU,aAAa,EAAE,WAAW,UAAU,UAAU;AAAA,IAC5D,GAAI,UAAU,SAAS,EAAE,OAAO,UAAU,MAAM;AAAA,IAChD,GAAI,UAAU,oBAAoB;AAAA,MAChC,kBAAkB,UAAU;AAAA,IAC9B;AAAA,IACA,GAAI,UAAU,YAAY,EAAE,UAAU,UAAU,SAAS;AAAA,EAC3D;AACF;AAQA,SAAS,cACP,MACA,aACA,MACW;AACX,QAAM,EAAE,gBAAgB,QAAQ,IAAI;AAGpC,QAAM,kBAAkB,YAAY;AACpC,QAAM,eAAe,kBAAkB,SAAY,KAAK;AAGxD,MAAI,eAAe;AACnB,QAAM,WAAsB,CAAC;AAC7B,QAAM,cAAc,KAAK,MAAM,GAAI;AACnC,cAAY,QAAQ,CAAC,YAAY,aAAa;AAC5C,QAAI,WAAW,GAAG;AAChB,eAAS;AAAA,QACP,IAAI,QAAQ;AAAA,UACV,UAAU,CAAC,IAAI,IAAI,CAAC;AAAA,UACpB,GAAG;AAAA,UACH,GAAI,kBAAkB,gBAAgB,EAAE,OAAO,EAAE;AAAA,QACnD,CAAC;AAAA,MACH;AACA,qBAAe;AAAA,IACjB;AACA,QAAI,CAAC,cAAc,YAAY,SAAS,EAAG;AAC3C,aAAS;AAAA,MACP,GAAG;AAAA,QACD;AAAA,QACA,CAAC,SAAS,YAAY;AACpB,gBAAM,MAAM,IAAI,QAAQ;AAAA,YACtB,MAAM;AAAA,YACN,GAAG;AAAA,YACH,IAAK,WAAW,YAAY,WAAc;AAAA,cACxC,SAAS,WAAW;AAAA,YACtB;AAAA,YACA,GAAI,kBAAkB,gBAAgB,EAAE,OAAO,EAAE;AAAA,UACnD,CAAC;AACD,yBAAe;AACf,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAQO,SAAS,cACd,MACA,aACA,OAAuD,CAAC,GAC7C;AACX,QAAM,OAAkB,CAAC;AACzB,QAAM,QAAQ,KAAK,MAAM,IAAI;AAE7B,WAAS,YAAY,GAAG,YAAY,MAAM,QAAQ,aAAa;AAC7D,UAAM,OAAO,MAAM,SAAS;AAC5B,UAAM,iBAAiB,YAAY;AAGnC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK;AAAA,QACH,GAAG,cAAc,MAAM,aAAa,EAAE,gBAAgB,GAAG,KAAK,CAAC;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,2BACP,MACA,WACA,SACA,eACoB;AACpB,QAAM,OAAO,CAAC,YACZ;AAAA,IACE;AAAA,IACA,oBAAoB,WAAW;AAAA,MAC7B,MAAM,eAAe;AAAA,MACrB,SAAS,eAAe;AAAA,MACxB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,IACD,EAAE,SAAS,UAAU,SAAS,cAAc,QAAQ,aAAa;AAAA,EACnE;AAEF,MAAI,CAAC,QAAQ,QAAS,QAAO,KAAK,IAAI;AACtC,SAAO,iBAAiB,MAAM,QAAQ,SAAS,IAAI;AACrD;AAcA,SAAS,iBACP,MACA,SACA,MACoB;AACpB,QAAM,QAAQ,IAAI,OAAO,sBAAsB,QAAQ,GAAG;AAC1D,QAAM,MAA0B,CAAC;AAEjC,MAAI,YAAY;AAChB,MAAI,UAAU;AACd,MAAI;AAEJ,UAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,UAAM,OAAO,QAAQ,MAAM,CAAC,CAAC;AAC7B,QAAI,SAAS,QAAW;AAEtB,iBAAW,KAAK,MAAM,WAAW,MAAM,SAAS;AAChD,kBAAY,MAAM;AAClB;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,KAAK,MAAM,WAAW,MAAM,KAAK;AAC1D,cAAU;AACV,QAAI,OAAQ,KAAI,KAAK,GAAG,KAAK,MAAM,CAAC;AACpC,QAAI;AAAA,MACF,KAAK,UACD,IAAI,oBAAoB,KAAK,EAAE,IAC/B,IAAI,qBAAqB,KAAK,EAAE;AAAA,IACtC;AACA,gBAAY,MAAM;AAAA,EACpB;AAEA,MAAI,IAAI,WAAW,EAAG,QAAO,KAAK,IAAI;AAEtC,QAAM,WAAW,UAAU,KAAK,MAAM,SAAS;AAC/C,MAAI,SAAU,KAAI,KAAK,GAAG,KAAK,QAAQ,CAAC;AACxC,SAAO;AACT;AAMA,SAAS,wBACP,MACA,YAAuB,CAAC,GACxB,UAAgC,CAAC,GACb;AACpB,QAAM,iBAAiB,qBAAqB,IAAI;AAChD,QAAM,OAA2B,CAAC;AAIlC,QAAM,iBAAiB;AAEvB,MAAI,YAAY;AAChB,MAAI;AAEJ,UAAQ,QAAQ,eAAe,KAAK,cAAc,OAAO,MAAM;AAE7D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,YAAY,eAAe,UAAU,WAAW,MAAM,KAAK;AACjE,UAAI,WAAW;AAEb,cAAM,YAAY,wBAAwB,WAAW,WAAW;AAAA,UAC9D,GAAG;AAAA,UACH,kBAAkB;AAAA;AAAA,QACpB,CAAC;AACD,aAAK,KAAK,GAAG,SAAS;AAAA,MACxB;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,CAAC;AACxB,UAAM,UAAU,MAAM,CAAC;AAGvB,UAAM,aAAa,QAAQ,WAAW,GAAG;AAGzC,UAAM,eAAe,wBAAwB,UAAU,WAAW;AAAA,MAChE,GAAG;AAAA,MACH,kBAAkB;AAAA;AAAA,IACpB,CAAC;AAGD,QAAI,YAAY;AAEd,YAAM,aAAa,QAAQ,UAAU,CAAC;AACtC,WAAK;AAAA,QACH,IAAI,kBAAkB;AAAA,UACpB,UAAU;AAAA;AAAA,UACV,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,WAAK;AAAA,QACH,IAAI,kBAAkB;AAAA,UACpB,UAAU;AAAA;AAAA,UACV,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAEA,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,YAAM,gBAAgB,wBAAwB,eAAe,WAAW;AAAA,QACtE,GAAG;AAAA,QACH,kBAAkB;AAAA;AAAA,MACpB,CAAC;AACD,WAAK,KAAK,GAAG,aAAa;AAAA,IAC5B;AAAA,EACF;AAGA,MAAI,KAAK,WAAW,KAAK,gBAAgB;AACvC,WAAO,wBAAwB,gBAAgB,WAAW;AAAA,MACxD,GAAG;AAAA,MACH,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AD3eA,SAAS,sBACP,MACA,SACS;AACT,SAAO,IAAIC,SAAQ;AAAA,IACjB;AAAA,IACA,MAAM,SAAS,OAAO;AAAA,IACtB,MAAM,SAAS,OAAO;AAAA,IACtB,OAAO,SAAS,OAAO;AAAA,IACvB,MAAM,SAAS,OAAO;AAAA,IACtB,SAAS,SAAS,OAAO;AAAA,IACzB,WAAW,SAAS,OAAO;AAAA,IAC3B,UAAU,SAAS,OAAO;AAAA,IAC1B,SAAS,SAAS,OAAO;AAAA,EAC3B,CAAC;AACH;AAEA,SAAS,gBAAgB,SAAoC;AAC3D,SAAO,SAAS,QAAQ,kBAAkB;AAC5C;AAEA,SAAS,QAAQ,MAAoB;AACnC,SAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE;AACvC;AAEA,SAAS,YAAY,MAAoB;AACvC,SAAO,KACJ,YAAY,EACZ,QAAQ,KAAK,GAAG,EAChB,QAAQ,aAAa,GAAG;AAC7B;AAKO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,OAAe,WAAW,oBAAI,IAAgC;AAAA;AAAA;AAAA;AAAA,EAK9D,OAAO,SAAS,MAAc,SAAmC;AAC/D,SAAK,SAAS,IAAI,KAAK,YAAY,GAAG,OAAO;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI,MAA8C;AACvD,WAAO,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAI,MAAuB;AAChC,WAAO,KAAK,SAAS,IAAI,KAAK,YAAY,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBAA+B;AACpC,WAAO,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAc;AACnB,SAAK,SAAS,MAAM;AAAA,EACtB;AACF;AA8DO,SAAS,4BACd,MACA,YAAuB,CAAC,GACxB,UAA8B,CAAC,GAC/B,cACoB;AACpB,QAAM,iBAAiB,qBAAqB,IAAI;AAGhD,QAAM,gBACJ;AACF,QAAM,SAA6B,CAAC;AACpC,MAAI,YAAY;AAEhB,MAAI;AACJ,UAAQ,QAAQ,cAAc,KAAK,cAAc,OAAO,MAAM;AAE5D,QAAI,MAAM,QAAQ,WAAW;AAC3B,YAAM,aAAa,eAAe,UAAU,WAAW,MAAM,KAAK;AAClE,UAAI,YAAY;AACd,eAAO;AAAA,UACL,GAAGC,4BAA2B,YAAY,WAAW,YAAY;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AAGA,QAAI,MAAM,CAAC,GAAG;AACZ,YAAM,kBAAkB,MAAM,CAAC;AAC/B,YAAM,UAAU,oBAAoB,IAAI,eAAe;AACvD,UAAI,SAAS;AACX,cAAM,oBAAoB,QAAQ,EAAE,GAAG,SAAS,OAAO,UAAU,CAAC;AAElE,YAAI,MAAM,QAAQ,iBAAiB,GAAG;AACpC,iBAAO,KAAK,GAAG,iBAAiB;AAAA,QAClC,WAAW,OAAO,sBAAsB,UAAU;AAChD,iBAAO;AAAA,YACL,GAAGA;AAAA,cACD;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,OAAO;AACL,iBAAO,KAAK,iBAAiB;AAAA,QAC/B;AAAA,MACF,OAAO;AAEL,eAAO;AAAA,UACL,GAAGA,4BAA2B,MAAM,CAAC,GAAG,WAAW,YAAY;AAAA,QACjE;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI;AACJ,UAAI,OAAO,UAAU,QAAQ;AAC7B,UAAI,UAAU,UAAU,WAAW;AAEnC,UAAI,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,OAAO;AAE5C,wBAAgB,MAAM,CAAC;AACvB,eAAO;AACP,kBAAU;AAAA,MACZ,WAAW,MAAM,CAAC,MAAM,QAAQ,MAAM,CAAC,MAAM,MAAM;AAEjD,wBAAgB,MAAM,CAAC;AACvB,eAAO;AAAA,MACT,WAAW,MAAM,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,KAAK;AAE/C,wBAAgB,MAAM,CAAC;AACvB,kBAAU;AAAA,MACZ,OAAO;AAEL,wBAAgB,MAAM,CAAC;AAAA,MACzB;AAGA,YAAM,oBAAoB;AAAA,QACxB;AAAA,QACA;AAAA,UACE,GAAG;AAAA,UACH;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AACA,aAAO,KAAK,GAAG,iBAAiB;AAAA,IAClC;AAEA,gBAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAAA,EACrC;AAGA,MAAI,YAAY,eAAe,QAAQ;AACrC,UAAM,gBAAgB,eAAe,UAAU,SAAS;AACxD,QAAI,eAAe;AACjB,aAAO;AAAA,QACL,GAAGA,4BAA2B,eAAe,WAAW,YAAY;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,KAAK,gBAAgB;AACzC,WAAO;AAAA,MACL,GAAGA,4BAA2B,gBAAgB,WAAW,YAAY;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAASA,4BACP,MACA,WACA,cACW;AACX,SAAO,cAAc,MAAM,oBAAoB,SAAS,GAAG;AAAA,IACzD,SAAS,UAAU;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,gCAAsC;AAEpD,sBAAoB,SAAS,QAAQ,CAAC,YAAY;AAChD,WAAO,IAAIC,SAAQ;AAAA,MACjB,UAAU,CAAC,WAAW,OAAO;AAAA,MAC7B,MAAM,SAAS,OAAO;AAAA,MACtB,MAAM,SAAS,OAAO;AAAA,MACtB,OAAO,SAAS,OAAO;AAAA,MACvB,MAAM,SAAS,OAAO;AAAA,MACtB,SAAS,SAAS,OAAO;AAAA,MACzB,WAAW,SAAS,OAAO;AAAA,IAC7B,CAAC;AAAA,EACH,CAAC;AAGD,sBAAoB,SAAS,eAAe,CAAC,YAAY;AACvD,WAAO,IAAIA,SAAQ;AAAA,MACjB,UAAU,CAAC,WAAW,WAAW;AAAA,MACjC,MAAM,SAAS,OAAO;AAAA,MACtB,MAAM,SAAS,OAAO;AAAA,MACtB,OAAO,SAAS,OAAO;AAAA,MACvB,MAAM,SAAS,OAAO;AAAA,MACtB,SAAS,SAAS,OAAO;AAAA,MACzB,WAAW,SAAS,OAAO;AAAA,IAC7B,CAAC;AAAA,EACH,CAAC;AAGD,sBAAoB;AAAA,IAAS;AAAA,IAAQ,CAAC,YACpC,sBAAsB,QAAQ,gBAAgB,OAAO,CAAC,GAAG,OAAO;AAAA,EAClE;AAGA,sBAAoB;AAAA,IAAS;AAAA,IAAY,CAAC,YACxC,sBAAsB,YAAY,gBAAgB,OAAO,CAAC,GAAG,OAAO;AAAA,EACtE;AAGA,sBAAoB;AAAA,IAAS;AAAA,IAAQ,CAAC,YACpC;AAAA,MACE,OAAO,gBAAgB,OAAO,EAAE,eAAe,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AACF;AAGA,8BAA8B;;;AFxV9B,SAAS,qBAAAC,0BAAyB;;;AIGlC,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAGA,SAAS,OAAO,OAAgB,KAAsB;AACpD,SAAO,SAAS,KAAK,KAAK,QAAQ,MAAM,GAAG,CAAC;AAC9C;AAGA,SAAS,kBAAkB,MAAe,KAAsB;AAC9D,MAAI,CAAC,SAAS,IAAI,EAAG,QAAO;AAC5B,MAAI,OAAO,MAAM,GAAG,EAAG,QAAO;AAC9B,QAAM,UAAU,KAAK;AACrB,SACE,SAAS,OAAO,KAAK,uBAAuB,SAA2B,GAAG;AAE9E;AAMO,SAAS,uBACd,WACA,KACS;AACT,QAAM,QAAQ,UAAU;AACxB,MAAI,OAAO;AACT,QAAI,MAAM,GAAG,EAAG,QAAO;AAEvB,UAAM,QAAQ,MAAM;AACpB,QAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,CAAC,SAAS,OAAO,MAAM,GAAG,CAAC,GAAG;AACnE,aAAO;AAAA,IACT;AAGA,UAAM,OAAO,MAAM;AACnB,QAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,KAAK,CAAC,QAAQ,OAAO,KAAK,GAAG,CAAC,GAAG;AAC/D,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,MAAM;AACtB,QACE,MAAM,QAAQ,OAAO,KACrB,QAAQ,KAAK,CAAC,WAAW;AACvB,UAAI,CAAC,SAAS,MAAM,EAAG,QAAO;AAC9B,UAAI,kBAAkB,OAAO,QAAQ,GAAG,EAAG,QAAO;AAClD,YAAM,QAAQ,OAAO;AACrB,aACE,MAAM,QAAQ,KAAK,KACnB,MAAM,KAAK,CAAC,SAAS,kBAAkB,MAAM,GAAG,CAAC;AAAA,IAErD,CAAC,GACD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,WAAW,UAAU;AAC3B,MAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,WAAO,SAAS;AAAA,MACd,CAAC,UACC,SAAS,KAAK,KAAK,uBAAuB,OAAyB,GAAG;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AJhEO,IAAM,0BAA0B;AAEhC,IAAM,wBAAwB;AAOrC,IAAM,qBAAN,MAAyB;AAAA,EACf,kBAAkB;AAAA,EACT,SAAS,IAAIC,mBAAuC;AAAA,EAErE,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,EACjD;AAAA,EAEA,OAAe;AACb,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,WAAW;AACjB,aAAO,MAAM;AAAA,IACf;AACA,SAAK,mBAAmB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,UAAU;AAAA,IAClB,OAAO;AACL,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AACF;AAEO,IAAM,2BAA2B,IAAI,mBAAmB;AAI/D,IAAM,sBAAsB;AAQ5B,SAAS,YACP,MACA,SACe;AACf,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,SAAO,MAAM;AAAA,IAAI,CAAC,MAAM,UACtB,QAAQ,UAAU,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,MAAM,MAAM,OAAO,EAAE,CAAC;AAAA,EACjE;AACF;AAYO,SAAS,mBACd,UACA,WACkB;AAClB,QAAM,SAAS,SAAS,UAAU;AAClC,QAAM,OAAO,SAAS,QAAQ;AAE9B,QAAM,OAAyB,CAAC;AAChC,aAAW,WAAW,SAAS,UAAU;AACvC,QAAI,CAAC,QAAQ,KAAM;AACnB,UAAM,OAAO,qBAAqB,QAAQ,IAAI;AAE9C,QAAI,QAAQ,SAAS,UAAU;AAC7B,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YACC,IAAI,gBAAgB;AAAA,YAClB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,IAAI,yBAAyB,KAAK;AAAA,YAClC;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF,WAAW,QAAQ,SAAS,UAAU;AACpC,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YACC,IAAI,eAAe;AAAA,YACjB,GAAG;AAAA,YACH,GAAG;AAAA,YACH,IAAI,yBAAyB,KAAK;AAAA,YAClC;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF,WAAW,oBAAoB,KAAK,IAAI,GAAG;AAEzC,WAAK;AAAA,QACH,GAAG,4BAA4B,MAAM,WAAwB,CAAC,CAAC;AAAA,MACjE;AAAA,IACF,OAAO;AACL,WAAK;AAAA,QACH,GAAG;AAAA,UACD;AAAA,UACA,CAAC,YAAY,IAAIC,SAAQ,EAAE,GAAG,SAAS,GAAG,UAAU,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,qBAAqB,WAAoC;AACvE,SAAO,uBAAuB,WAAW,UAAU;AACrD;AAgBO,SAAS,mBAAmB,MAGjC;AACA,QAAM,aAAqC;AAAA,IACzC,IAAI,yBAAyB,KAAK;AAAA,IAClC,QAAQ,KAAK,UAAU;AAAA,IACvB,MAAM,KAAK,QAAQ;AAAA,EACrB;AACA,SAAO,KAAK,SAAS,WACjB,EAAE,WAAW,WAAW,IACxB,EAAE,UAAU,WAAW;AAC7B;AAUO,SAAS,qBACd,MACA,MACA,WACkB;AAClB,SAAO;AAAA,IACL;AAAA,MACE,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,UAAU,CAAC,EAAE,MAAM,KAAK,MAAM,KAAK,CAAC;AAAA,IACtC;AAAA,IACA;AAAA,EACF;AACF;;;AKzLA,SAAS,cAAAC,mBAAkB;AAG3B,IAAI,iBAAqC;AACzC,IAAI,cAAwC;AA0B5C,IAAM,cAAc,oBAAI,IAGtB;AAEF,SAAS,aAAa,MAAc,QAAqC;AACvE,QAAM,QAAQ,YAAY,IAAI,IAAI;AAClC,MAAI,OAAO;AACT,UAAM;AAAA,EACR,OAAO;AACL,gBAAY,IAAI,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;AAAA,EAC9C;AACF;AAKO,SAAS,0BAAkD;AAChE,SAAO,MAAM,KAAK,YAAY,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO;AAAA,IAC3D;AAAA,IACA,SAAS,EAAE;AAAA,IACX,QAAQ,EAAE;AAAA,EACZ,EAAE;AACJ;AAQA,IAAM,gCAAgC,oBAAI,IAAI,CAAC,QAAQ,aAAa,CAAC;AAS9D,SAAS,6BAA6B,YAA6B;AACxE,QAAM,mBAAmB;AACzB,MAAI;AACJ,UAAQ,QAAQ,iBAAiB,KAAK,UAAU,OAAO,MAAM;AAC3D,UAAM,OAAO,MAAM,CAAC,EAAE,YAAY;AAClC,QAAI,8BAA8B,IAAI,IAAI,EAAG;AAC7C,QAAI,oBAAoB,IAAI,IAAI,EAAG,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAMA,SAAS,gBAAgB,OAA4B;AAEnD,QAAM,cAAc,KAAK,UAAU,KAAK;AACxC,SAAOA,YAAW,QAAQ,EAAE,OAAO,WAAW,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,CAAC;AAC9E;AAKO,SAAS,yBAAyB,OAA2B;AAClE,MAAI,OAAO;AACT,qBAAiB;AAAA,EACnB,WAAW,CAAC,gBAAgB;AAE1B,UAAM,SAA6B;AAAA,MACjC,SAAS;AAAA,MACT,gBAAgB;AAAA,MAChB,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA;AAAA,QACT,YAAY;AAAA,QACZ,YAAY;AAAA;AAAA,QACZ,iBAAiB;AAAA;AAAA,MACnB;AAAA,MACA,aAAa;AAAA,QACX,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,eAAe;AAAA,QACf,oBAAoB;AAAA,MACtB;AAAA,IACF;AACA,qBAAiB,IAAI,0BAAY,MAAM;AAAA,EACzC;AAEA,MAAI,CAAC,aAAa;AAChB,kBAAc,IAAI,kBAAkB;AAAA,EACtC;AACF;AAKO,SAAS,oBAAwC;AACtD,SAAO;AACT;AAKA,eAAsB,sBAAqC;AACzD,MAAI,gBAAgB;AAClB,UAAM,eAAe,MAAM;AAAA,EAC7B;AACA,cAAY,MAAM;AACpB;AAoBA,IAAM,6BAA6B,oBAAI,IAAI;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,SAAS,sBACd,WAC8B;AAG9B,MAAI,qBAAqB,SAAS,EAAG,QAAO;AAG5C,MAAI,uBAAuB,WAAW,SAAS,EAAG,QAAO;AACzD,MAAI,QAAQ,UAAW,QAAO;AAC9B,MAAI,2BAA2B,IAAI,UAAU,IAAI,EAAG,QAAO;AAC3D,SAAO;AACT;AAKA,eAAsB,yBACpB,WACA,OACA,WACA,SACA,cAAc,OAC8C;AAC5D,QAAM,eAAe,sBAAsB,SAAS;AAGpD,MAAI,CAAC,gBAAgB;AACnB,6BAAyB;AAAA,EAC3B;AAKA,MAAI,iBAAiB,MAAM;AACzB,iBAAa,UAAU,MAAM,YAAY;AACzC,WAAO,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC7D;AACA,MAAI,CAAC,kBAAkB,eAAe,CAAC,eAAe,UAAU,EAAE,SAAS;AACzE,WAAO,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC7D;AAIA,QAAM,iBAAiB,KAAK,UAAU,UAAU,SAAS,CAAC,CAAC;AAC3D,QAAM,YAAY,gBAAgB,KAAK;AAIvC,QAAM,aAAa,SAAS,UACxB,GAAG,QAAQ,QAAQ,aAAa,IAAI,QAAQ,QAAQ,WAAW,KAC/D;AAIJ,QAAM,aAAa,WAAW,KAAK;AAInC,QAAM,cACJ,cAAc,aAAa,UAAU,WACjC,aAAa,KAAK,UAAU,UAAU,QAAQ,CAAC,KAC/C;AAQN,QAAM,oBAAoB;AAAA,IACxB,iBAAiB;AAAA,EACnB,IACI,kBAAkB,EAAE,YAAY,IAChC;AAEJ,QAAM,WAAW,aAAa,UAAU,IAAI,IAAI,SAAS,IAAI,UAAU,IAAI,iBAAiB,IAAI,UAAU,IAAI,cAAc,GAAG,WAAW;AAG1I,QAAM,SAAS,MAAM,eAAe,IAAI,QAAQ;AAEhD,MAAI,QAAQ;AAGV,WAAO,OAAO;AAAA,EAChB;AAGA,QAAM,kBAAkB,KAAK,IAAI;AACjC,QAAM,WAAW,MAAM,gBAAgB,WAAW,OAAO,WAAW,OAAO;AAE3E,OAAK,IAAI,IAAI;AAGb,QAAM,gBAAgB,KAAK,UAAU,QAAQ,EAAE;AAG/C,QAAM,cAA+B;AAAA,IACnC,QAAQ;AAAA;AAAA,IACR,eAAe,UAAU;AAAA,IACzB,WAAW;AAAA,IACX,WAAW,KAAK,IAAI;AAAA,IACpB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,cAAc,CAAC;AAAA,IACf,WAAW;AAAA,IACX,cAAc,KAAK,IAAI;AAAA,EACzB;AAGA,QAAM,eAAe,IAAI,UAAU,WAAW;AAE9C,SAAO;AACT;AAQA,eAAsB,mBACpB,YAMe;AACf,MACE,CAAC,kBACD,CAAC,eAAe,UAAU,EAAE,YAAY,eACxC;AACA;AAAA,EACF;AAEA,QAAM,kBAAkB,WAAW;AAAA,IACjC,OAAO,EAAE,WAAW,OAAO,WAAW,QAAQ,MAAM;AAClD,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,eAAe;AACnC;AAQO,SAAS,yBAAyB;AACvC,QAAM,qBAAqB,wBAAwB;AACnD,MAAI,CAAC,gBAAgB;AACnB,WAAO,mBAAmB,SAAS,IAAI,EAAE,mBAAmB,IAAI;AAAA,EAClE;AAEA,SAAO,EAAE,GAAG,eAAe,SAAS,GAAG,mBAAmB;AAC5D;;;ACjWA;AAAA,EACE,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EAEA;AAAA,EACA;AAAA,EACA,eAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP;AACA;;;AC/BA,SAAS,qBAAAC,0BAAyB;AAgB3B,IAAM,mBAAN,MAAuB;AAAA,EACX,WAA0B,EAAE,WAAW,oBAAI,IAAI,EAAE;AAAA,EACjD,SAAS,IAAIA,mBAAiC;AAAA,EAE/D,IAAY,QAAuB;AACjC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,WAAW,oBAAI,IAAI,EAAE,GAAG,QAAQ;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,IAAY,OAAe,MAAoB;AACtD,QAAI,KAAK,MAAM,UAAU,IAAI,EAAE,GAAG;AAChC,cAAQ;AAAA,QACN,0BAA0B,EAAE;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,MAAM,UAAU,IAAI,IAAI,EAAE,IAAI,OAAO,KAAK,CAAC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,MAAc,QAAgB,YAAoB;AAE3D,UAAM,SAAS,KACZ,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,eAAe,EAAE,EACzB,UAAU,GAAG,EAAE;AAGlB,QAAI,KAAK;AACT,QAAI,UAAU;AACd,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE,KAAK,UAAU,KAAK;AACpD,WAAK,GAAG,MAAM,IAAI,EAAE,OAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAqB;AAC1B,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAsC;AACxC,WAAO,KAAK,MAAM,UAAU,IAAI,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,SAAyB;AACvB,WAAO,MAAM,KAAK,KAAK,MAAM,UAAU,OAAO,CAAC;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,UAAU,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,eAAmC;AACpD,UAAM,UAAoB,CAAC;AAC3B,eAAW,MAAM,eAAe;AAC9B,UAAI,CAAC,KAAK,OAAO,EAAE,GAAG;AACpB,gBAAQ,KAAK,EAAE;AAAA,MACjB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,yBAAyB,IAAI,iBAAiB;;;ACnG3D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAAC;AAAA,OACK;;;ACJP,SAAS,WAAW,WAAAC,gBAAe;AAEnC,SAAS,qBAAAC,0BAAyB;AAI3B,IAAM,yBAAyB;AAE/B,IAAM,uBAAuB;AASpC,SAAS,cAA4B;AACnC,SAAO,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,aAAa,MAAM;AACxD;AAMA,SAAS,eAAe,QAAwB;AAC9C,QAAM,WAAW,OACd,MAAM,UAAU,EAChB,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,CAAC,CAAC,EACrB,KAAK,EAAE,EACP,YAAY,EACZ,MAAM,GAAG,CAAC;AACb,SAAO,YAAY,OAAO,MAAM,GAAG,CAAC,EAAE,YAAY;AACpD;AAGA,SAAS,eAAe,MAA2B;AACjD,SAAO,qBAAqB,IAAI,EAC7B,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,IAAI,UAAU,EAAE,UAAU,CAAC,IAAIC,SAAQ,EAAE,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;AAC7E;AAEA,IAAM,kBAAN,MAAsB;AAAA,EACZ,WAAyB,YAAY;AAAA,EAC5B,SAAS,IAAIC,mBAAgC;AAAA,EAE9D,IAAY,QAAsB;AAChC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,YAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,SAAS,SAA4B;AACnC,UAAM,QAAQ,KAAK;AACnB,UAAM,WAAW,QAAQ;AACzB,UAAM,SAAS,EAAE,MAAM;AAEvB,UAAM,SAAS,KAAK;AAAA,MAClB,GAAG,KAAK,UAAU,SAAS,MAAM;AAAA,MACjC,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,IAC3C,CAAC;AAED,UAAM,MAAM,CAAC,MAAM;AACnB,eAAW,SAAS,QAAQ,WAAW,CAAC,GAAG;AACzC,YAAM,UAAU,EAAE,MAAM;AACxB,YAAM,SAAS,KAAK;AAAA,QAClB,GAAG,KAAK,UAAU,OAAO,OAAO;AAAA,QAChC,UAAU;AAAA;AAAA,QAEV,GAAI,aAAa,UAAa,EAAE,SAAS;AAAA,MAC3C,CAAC;AACD,UAAI,KAAK,OAAO;AAAA,IAClB;AAEA,QAAI,aAAa,OAAW,OAAM,cAAc;AAChD,WAAO;AAAA,EACT;AAAA,EAEQ,UACN,SACA,IACiB;AACjB,UAAM,SAAS,QAAQ,UAAU;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU,QAAQ,YAAY,eAAe,MAAM;AAAA,MACnD,MAAM,IAAI,KAAK,QAAQ,QAAQ,oBAAoB;AAAA,MACnD,UAAU,eAAe,QAAQ,IAAI;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,SAA4B;AAC1B,UAAM,QAAQ,KAAK;AACnB,QACE,MAAM,eACN,CAAC,MAAM,SAAS,KAAK,CAAC,YAAY,QAAQ,aAAa,MAAS,GAChE;AACA,cAAQ;AAAA,QACN;AAAA,MAGF;AAAA,IACF;AACA,WAAO,CAAC,GAAG,MAAM,QAAQ;AAAA,EAC3B;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,UAAU;AAChB,YAAM,SAAS,SAAS;AACxB,YAAM,cAAc;AAAA,IACtB,OAAO;AACL,WAAK,WAAW,YAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,wBAAwB,IAAI,gBAAgB;;;ADrHlD,SAAS,iBACd,SAC2B;AAC3B,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,MAAM,sBAAsB,SAAS,OAAO;AAClD,SAAO,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,OAAO,IAAI,kBAAkB,EAAE,CAAC,EAAE;AAClE;AAUO,SAAS,kBAAkB,KAA0C;AAC1E,SAAO,IAAI,QAAQ,CAAC,OAAO;AAAA,IACzB,IAAI,gBAAgB,EAAE;AAAA,IACtB,IAAIC,SAAQ,EAAE,UAAU,CAAC,IAAI,iBAAiB,EAAE,CAAC,EAAE,CAAC;AAAA,EACtD,CAAC;AACH;;;AE3CA,SAAS,aAAAC,YAAW,WAAAC,gBAAe;AACnC,SAAS,qBAAAC,0BAAyB;AAalC,SAASC,eAAyB;AAChC,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,WAAW,CAAC;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AACF;AAGA,SAASC,gBAAe,MAAc,OAA4B;AAChE,SAAO,qBAAqB,IAAI,EAC7B,MAAM,IAAI,EACV;AAAA,IACC,CAAC,SACC,IAAIC,WAAU;AAAA,MACZ;AAAA,MACA,UAAU,CAAC,IAAIC,SAAQ,EAAE,MAAM,KAAK,CAAC,CAAC;AAAA,IACxC,CAAC;AAAA,EACL;AACJ;AAEA,IAAM,eAAN,MAAmB;AAAA,EACT,WAAsBH,aAAY;AAAA,EACzB,SAAS,IAAII,mBAA6B;AAAA,EAE3D,IAAY,QAAmB;AAC7B,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAIJ,aAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,MAAsB;AACrC,UAAM,QAAQ,KAAK;AACnB,UAAM,KAAK,EAAE,MAAM;AACnB,UAAM,UAAU,OAAO,EAAE,CAAC,IAAI;AAAA,MAC5B,UAAUC,gBAAe,MAAM,cAAc;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,gBAAgB,MAAsB;AACpC,UAAM,QAAQ,KAAK;AACnB,UAAM,KAAK,EAAE,MAAM;AACnB,UAAM,SAAS,OAAO,EAAE,CAAC,IAAI;AAAA,MAC3B,UAAUA,gBAAe,MAAM,aAAa;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAA2B;AACzB,WAAO,EAAE,GAAG,KAAK,MAAM,UAAU;AAAA,EACnC;AAAA;AAAA,EAGA,cAA0B;AACxB,WAAO,EAAE,GAAG,KAAK,MAAM,SAAS;AAAA,EAClC;AAAA;AAAA,EAGA,QAAc;AACZ,UAAM,QAAQ,KAAK,OAAO,SAAS;AACnC,QAAI,OAAO;AACT,YAAM,kBAAkB;AACxB,YAAM,iBAAiB;AACvB,iBAAW,OAAO,OAAO,KAAK,MAAM,SAAS,GAAG;AAC9C,eAAO,MAAM,UAAU,GAAG;AAAA,MAC5B;AACA,iBAAW,OAAO,OAAO,KAAK,MAAM,QAAQ,GAAG;AAC7C,eAAO,MAAM,SAAS,GAAG;AAAA,MAC3B;AAAA,IACF,OAAO;AACL,WAAK,WAAWD,aAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,qBAAqB,IAAI,aAAa;;;ACtFnD,SAAS,gBACP,WACA,UAC2B;AAC3B,QAAM,WAAW,oBAAI,IAA0B;AAQ/C,QAAM,UAAU,CAAC,MAAY,YAAqB;AAChD,UAAM,WAAW,SAAS,IAAI,KAAK,EAAE;AACrC,QAAI,UAAU;AACZ,cAAQ;AAAA,QACN,SAAS,YAAY,UACjB,YAAY,KAAK,EAAE,mCACd,UAAU,aAAa,WAAW,+DAEvC,YAAY,KAAK,EAAE;AAAA,MAGzB;AACA;AAAA,IACF;AACA,aAAS,IAAI,KAAK,IAAI,EAAE,MAAM,KAAK,MAAM,QAAQ,CAAC;AAAA,EACpD;AAEA,aAAW,QAAQ,aAAa,CAAC,EAAG,SAAQ,MAAM,KAAK;AACvD,aAAW,QAAQ,YAAY,CAAC,EAAG,SAAQ,MAAM,IAAI;AACrD,SAAO;AACT;AAOO,SAAS,mBACd,WACA,UAC0B;AAC1B,QAAM,WAAW,gBAAgB,WAAW,QAAQ;AACpD,MAAI,SAAS,SAAS,EAAG,QAAO;AAEhC,QAAM,aAAa,oBAAI,IAA8C;AAErE,SAAO;AAAA,IACL,QAAQ,IAAY;AAClB,YAAM,WAAW,WAAW,IAAI,EAAE;AAClC,UAAI,aAAa,OAAW,QAAO;AAEnC,YAAM,OAAO,SAAS,IAAI,EAAE;AAC5B,UAAI,SAAS,QAAW;AAGtB,gBAAQ;AAAA,UACN,kBAAkB,EAAE,iFACkB,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,QAEvE;AACA,eAAO;AAAA,MACT;AAEA,YAAM,WAAW;AAAA,QACf,IAAI,KAAK,UACL,mBAAmB,gBAAgB,KAAK,IAAI,IAC5C,mBAAmB,iBAAiB,KAAK,IAAI;AAAA,QACjD,SAAS,KAAK;AAAA,MAChB;AACA,iBAAW,IAAI,IAAI,QAAQ;AAC3B,aAAO;AAAA,IACT;AAAA,IAEA,gBAAgB,MAAc;AAC5B,iBAAW,CAAC,IAAI,IAAI,KAAK,UAAU;AACjC,YAAI,WAAW,IAAI,EAAE,EAAG;AACxB,cAAM,OAAO,KAAK,UAAU,YAAY;AACxC,gBAAQ;AAAA,UACN,KAAK,SAAS,KAAK,EAAE,GAAG,IACpB,GAAG,IAAI,KAAK,EAAE,0NAId,GAAG,IAAI,KAAK,EAAE,2CAA2C,EAAE;AAAA,QAEjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AL5DA;AACA,SAAS,4BAA4B;AAQrC;AACA;AAIA;AAeA,SAAS,qBAAqB,MAK2B;AACvD,MAAI,CAAC,KAAK,YAAY;AACpB,WAAO,EAAE,MAAM,QAAW,MAAM,KAAK,MAAM,SAAS,KAAK,OAAO;AAAA,EAClE;AACA,QAAM,SAAS,KAAK,eAAe,KAAK,SAAS,OAAO,MAAM;AAC9D,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,IACL;AAAA,IACA,KAAK,WAAW;AAAA,EAClB;AACA,SAAO,EAAE,MAAM,MAAM,QAAQ,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AACvE;AAMA,SAAS,oBACP,OACA,aACsB;AACtB,QAAM,aAAa,MAAM;AACzB,QAAM,SAAS,CAAC,GAAI,cAAc,CAAC,GAAI,GAAI,eAAe,CAAC,CAAE;AAC7D,SAAO,OAAO,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI;AAC3D;AA2LA,SAAS,iCACP,WACA,UACA,UACM;AACN,QAAM,WAAW,CAAC,GAAI,aAAa,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC3D,MAAI,SAAS,WAAW,EAAG;AAE3B,QAAM,OAAO,SAAS,SAAS,IAAI,CAAC,YAAY,QAAQ,IAAI,EAAE,KAAK,EAAE;AACrE,QAAM,aAAa,SAAS,OAAO,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,EAAE,GAAG,CAAC;AAC3E,UAAQ;AAAA,IACN,sBAAsB,SAAS,MAAM,aAAa,SAC/C,IAAI,CAAC,SAAS,KAAK,EAAE,EACrB,KAAK,IAAI,CAAC,+GAEV,WAAW,SAAS,IACjB,yBAAoB,WACjB,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE,GAAG,EAC7B,KAAK,IAAI,CAAC,iCACb,MACJ;AAAA,EACJ;AACF;AAWA,SAAS,cACP,UACA,SACkB;AAClB,QAAM,SAAS,iBAAiB,OAAO;AACvC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,CAAC,GAAG,OAAO,OAAO,GAAG,UAAU,GAAG,kBAAkB,OAAO,GAAG,CAAC;AACxE;AAKO,SAAS,WACd,SACA,OACA,WACA,UAAuB,CAAC,GACb;AACX,QAAM,oBAAoB,qBAAqB,OAAO;AAEtD,QAAM,QAAQ,QAAQ,SAAS;AAG/B,QAAM,UAAe,CAAC;AACtB,MAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,YAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,EACvD;AACA,MAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,YAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,EACrD;AAEA,QAAM,oBAAoB,mBAAyB,QAAQ,WAAW;AACtE,MAAI,mBAAmB;AACrB,YAAQ,OAAO,kBAAkB;AACjC,YAAQ,WAAW,kBAAkB;AAAA,EACvC;AAGA,QAAM,WAA6B,CAAC;AAGpC,MAAI,QAAQ,aAAa;AACvB,aAAS,KAAK,IAAI,YAAY,CAAC;AAAA,EACjC;AAIA,QAAM,gBAAgB,iBAAiB,QAAQ,OAAO;AACtD,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,cAAc,KAAK;AAAA,EACtC;AAMA,QAAM,mBAAmB,QAAQ,cAAc,QAAQ,QAAQ,SAAS;AACxE,QAAM,kBACJ,QAAQ,eACP,mBAAmB,kBAAkB,OAAO,MAAM,IAAI;AACzD,QAAM,WAAW,qBAAqB;AAAA,IACpC,YAAY;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,YAAY,QAAQ;AAAA,EACtB,CAAC;AACD,QAAM,gBAAgB;AAAA;AAAA;AAAA,IAGpB,IAAK,QAAQ,cACV,SAAS,QAAQ,SAAS,SAAS,oBAAqB;AAAA,MACzD,MAAM,SAAS;AAAA,IACjB;AAAA,IACA,GAAI,QAAQ,YAAY,EAAE,MAAM,QAAQ,WAAW,EAAE;AAAA;AAAA,IACrD,GAAI,QAAQ,aAAa;AAAA,MACvB,OAAO,aAAa,QAAQ,WAAW,KAAK;AAAA,IAC9C;AAAA,IACA,GAAI,SAAS,SAAS,UAAa,EAAE,MAAM,SAAS,KAAK;AAAA,IACzD,GAAI,SAAS,YAAY,UAAa,EAAE,SAAS,SAAS,QAAQ;AAAA,IAClE,GAAI,QAAQ,cAAc,UAAa;AAAA,MACrC,WAAW,QAAQ,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC/D;AAAA;AAAA,IAEA,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,MAAM;AAAA;AAAA,IAE5C,GAAI,QAAQ,oBAAoB;AAAA,MAC9B,kBACE,QAAQ,iBAAiB,SAAS,cAC9B,CAAC,QAAQ,iBAAiB,QAC1B,QAAQ,iBAAiB;AAAA,IACjC;AAAA;AAAA;AAAA,IAGA,GAAI,QAAQ,YAAY,EAAE,UAAU,EAAE,OAAO,QAAQ,SAAS,EAAE;AAAA,IAChE,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,EAClE;AAEA,MAAI,QAAQ,UAAU;AAQpB;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AACA,UAAM,eAAe,mBAAmB,QAAQ,UAAU,aAAa;AACvE,QAAI,QAAQ,YAAY;AACtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,eAAS,KAAK,GAAG,YAAY;AAAA,IAC/B;AAAA,EACF,OAAO;AAKL,UAAM,eAAe;AAAA,MACnB,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAGA,UAAM,WAAW,wBAAwB,mBAAmB,eAAe;AAAA,MACzE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,MACJ,kBAAkB;AAAA,MAClB,cAAc,oBAAoB,OAAO,QAAQ,YAAY;AAAA,MAC7D,SAAS,cAAc;AAAA,IACzB,CAAC;AACD,kBAAc,gBAAgB,iBAAiB;AAG/C,QAAI,QAAQ,YAAY;AAEtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AAGA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,eAAS,KAAK,GAAG,QAAQ;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,kBAAkB,cAAc,GAAG,CAAC;AAAA,EACvD;AAGA,QAAM,aAAa,CAAC,CAAC,QAAQ;AAC7B,QAAM,eACJ,cAAc,QAAQ,WAClB,gBAAgB,QAAQ,UAAU,OAAO,SAAS,IAClD;AAEN,SAAO,IAAIK,WAAU;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,QAAQ,YAAY,aAAa,QAAQ,SAAS,IAAI;AAAA,IACjE;AAAA,IACA,GAAI,QAAQ,iBAAiB,UAAa;AAAA,MACxC,cAAc,QAAQ;AAAA,IACxB;AAAA,IACA,GAAI,gBAAgB,EAAE,OAAO,aAAa;AAAA,IAC1C,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,IACnE,GAAI,QAAQ,cAAc,UAAa,EAAE,WAAW,QAAQ,UAAU;AAAA,IACtE,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;AAAA,IAC/C,GAAI,QAAQ,YACV,QAAQ,SAAS,SAAS,KAAK,EAAE,UAAU,QAAQ,SAAS;AAAA,EAChE,CAAC;AACH;AASA,SAAS,gBACP,UACA,OACA,WACK;AACL,QAAM,sBAAsB,SAAS,oBAAoB,WAAW;AACpE,QAAM,oBAAoB,SAAS,kBAAkB,WAAW;AAChE,QAAM,qBAAqB,SAAS,oBAAoB,UAAU;AAClE,QAAM,mBAAmB,SAAS,kBAAkB,UAAU;AAG9D,QAAM,cAAc,uBAAuB;AAG3C,QAAM,aAAa,SAAS,SAAS;AACrC,QAAM,cAAc,SAAS,UAAU;AAEvC,QAAM,cAAmB;AAAA,IACvB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,YAAY,SAAS,oBAAoB,YAAY;AAAA,MACrD,UAAU,SAAS,kBAAkB,YAAY;AAAA,IACnD;AAAA,EACF;AAEA,MAAI,SAAS,MAAM,MAAM;AACvB,gBAAY,OAAO,SAAS,KAAK;AAAA,EACnC;AAGA,MAAI,SAAS,eAAe,QAAW;AACrC,gBAAY,aAAa,SAAS;AAAA,EACpC,WAAY,SAAiB,eAAe,QAAW;AACrD,gBAAY,aAAc,SAAiB;AAAA,EAC7C;AAEA,MAAI,aAAa;AACf,UAAM,OAAO,SAAS,oBAAoB,UAAU;AACpD,UAAM,OAAO,SAAS,kBAAkB,UAAU;AAClD,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU;AACxD,YAAM,YAAY,SAAS,oBAAoB;AAC/C,YAAM,YAAY,SAAS,kBAAkB;AAC7C,YAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,YAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AACzC,UAAI,mBAAmB,MAAM,IAAI;AACjC,UAAI,mBAAmB,MAAM,IAAI;AAAA,IACnC,OAAO;AACL,UAAI;AACJ,UAAI;AAAA,IACN;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,EAAE,GAAG,EAAE;AAAA,MACjB,GAAG;AAAA,IACL;AAAA,EACF;AAGA,QAAM,SAAS,qBACX,SAAS,mBAAoB,QAC7B;AACJ,QAAM,SAAS,mBAAmB,SAAS,iBAAkB,QAAS;AACtE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,WAAW,EAAE,GAAG,QAAQ,GAAG,OAAO;AAAA,IAClC,GAAG;AAAA,EACL;AACF;AAKO,SAAS,cACd,MACA,OACA,OACA,YACA,UAAuB,CAAC,GACb;AACX,QAAM,iBAAiB,qBAAqB,IAAI;AAChD,QAAM,UAAU,mBAAmB,KAAK;AAIxC,QAAM,UAAe,CAAC;AACtB,MAAI,qBAAqB;AAEzB,MAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,YAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AACrD,yBAAqB;AAAA,EACvB;AACA,MAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,YAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AACnD,yBAAqB;AAAA,EACvB;AAEA,QAAM,oBAAoB,mBAAyB,QAAQ,WAAW;AACtE,MAAI,mBAAmB;AACrB,YAAQ,OAAO,kBAAkB;AACjC,YAAQ,WAAW,kBAAkB;AACrC,yBAAqB;AAAA,EACvB;AAGA,QAAM,WAAkB,CAAC;AAGzB,MAAI,QAAQ,iBAAiB;AAC3B,aAAS,KAAK,GAAG,QAAQ,eAAe;AAAA,EAC1C;AAGA,MAAI,QAAQ,aAAa;AACvB,aAAS,KAAK,IAAI,YAAY,CAAC;AAAA,EACjC;AAGA,QAAM,gBAAgB,iBAAiB,QAAQ,OAAO;AACtD,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,cAAc,KAAK;AAAA,EACtC;AAGA,QAAM,gBAAgB,gCAAgC,KAAK,cAAc;AAIzE,QAAM,0BACJ,QAAQ,cAAc,QAAQ,QAAQ,SAAS;AACjD,QAAM,yBACJ,QAAQ,eACP,0BAA0B,kBAAkB,OAAO,SAAS,IAAI;AACnE,QAAM,kBAAkB,qBAAqB;AAAA,IAC3C,YAAY;AAAA,IACZ,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,YAAY,QAAQ;AAAA,EACtB,CAAC;AAED,QAAM,gBAAgB;AAAA,IACpB,IAAK,QAAQ,cACV,gBAAgB,QACf,gBAAgB,SAAS,2BAA4B;AAAA,MACvD,MAAM,gBAAgB;AAAA,IACxB;AAAA,IACA,GAAI,QAAQ,YAAY,EAAE,MAAM,QAAQ,WAAW,EAAE;AAAA;AAAA,IACrD,GAAI,QAAQ,aAAa,EAAE,OAAO,aAAa,QAAQ,WAAW,KAAK,EAAE;AAAA,IACzE,GAAI,gBAAgB,SAAS,UAAa,EAAE,MAAM,gBAAgB,KAAK;AAAA,IACvE,GAAI,gBAAgB,YAAY,UAAa;AAAA,MAC3C,SAAS,gBAAgB;AAAA,IAC3B;AAAA,IACA,GAAI,QAAQ,cAAc,UAAa;AAAA,MACrC,WAAW,QAAQ,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC/D;AAAA;AAAA,IAEA,GAAI,QAAQ,SAAS,EAAE,OAAO,QAAQ,MAAM;AAAA;AAAA,IAE5C,GAAI,QAAQ,oBAAoB;AAAA,MAC9B,kBACE,QAAQ,iBAAiB,SAAS,cAC9B,CAAC,QAAQ,iBAAiB,QAC1B,QAAQ,iBAAiB;AAAA,IACjC;AAAA;AAAA,IAEA,GAAI,QAAQ,YAAY,EAAE,UAAU,EAAE,OAAO,QAAQ,SAAS,EAAE;AAAA,IAChE,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,EAClE;AAKA,QAAM,sBAAsB,oBAAoB,OAAO,QAAQ,YAAY;AAC3E,QAAM,kBAAkB,CAAC,UACvB;AAAA,IACE;AAAA,IACA,CAAC,SAAS,YACR,IAAIC,SAAQ;AAAA,MACV,MAAM;AAAA,MACN,GAAG;AAAA,MACH,GAAI,WAAW,EAAE,SAAS,KAAK;AAAA,IACjC,CAAC;AAAA,IACH;AAAA,EACF;AAEF,MAAI,QAAQ,UAAU;AAGpB,UAAM,eAAe,mBAAmB,QAAQ,UAAU,aAAa;AACvE,QAAI,QAAQ,YAAY;AACtB,6BAAuB;AAAA,QACrB,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA,eAAS;AAAA,QACP,IAAI,SAAS;AAAA,UACX,IAAI,QAAQ;AAAA,UACZ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,eAAS,KAAK,GAAG,YAAY;AAAA,IAC/B;AAAA,EACF,WAAW,QAAQ,YAAY;AAE7B,2BAAuB;AAAA,MACrB,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAGA,UAAM,sBAAyC,CAAC;AAEhD,QAAI,eAAe;AAEjB,YAAM,WAAW,wBAAwB,gBAAgB,eAAe;AAAA,QACtE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,QACJ,kBAAkB;AAAA,QAClB,cAAc;AAAA,MAChB,CAAC;AACD,0BAAoB,KAAK,GAAG,QAAQ;AAAA,IACtC,OAAO;AAEL,0BAAoB,KAAK,GAAG,gBAAgB,cAAc,CAAC;AAAA,IAC7D;AAGA,aAAS;AAAA,MACP,IAAI,SAAS;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AAEL,QAAI,eAAe;AAEjB,YAAM,WAAW,wBAAwB,gBAAgB,eAAe;AAAA,QACtE,WAAW,QAAQ,YACf,aAAa,QAAQ,WAAW,KAAK,IACrC;AAAA,QACJ,kBAAkB;AAAA,QAClB,cAAc;AAAA,MAChB,CAAC;AACD,eAAS,KAAK,GAAG,QAAQ;AAAA,IAC3B,OAAO;AAEL,eAAS,KAAK,GAAG,gBAAgB,cAAc,CAAC;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,aAAS,KAAK,GAAG,kBAAkB,cAAc,GAAG,CAAC;AAAA,EACvD;AAEA,SAAO,IAAID,WAAU;AAAA,IACnB;AAAA,IACA,OAAO;AAAA,IACP,WAAW,aAAa,QAAQ,aAAa,MAAM;AAAA;AAAA,IAEnD,SAAS,qBAAqB,UAAU;AAAA,IACxC,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,IACnE,GAAI,QAAQ,cAAc,UAAa,EAAE,WAAW,QAAQ,UAAU;AAAA,IACtE,GAAI,QAAQ,UAAU,EAAE,QAAQ,QAAQ,OAAO;AAAA,EACjD,CAAC;AACH;AA0CA,eAAsB,YACpBE,OACA,OACA,WACA,UAAwB,CAAC,GACH;AACtB,QAAM,WAAwB,CAAC;AAC/B,QAAM,aAAa,CAAC,CAAC,QAAQ;AAC7B,QAAM,YAAY,aACd,SACA,aAAa,QAAQ,aAAa,QAAQ;AAE9C,MAAI,YAAYA;AAChB,MAAI;AACJ,MAAI;AAEJ,MAAI;AAEF,UAAM,cAAc,MAAM,eAAe,SAAS;AAClD,kBAAc,YAAY;AAC1B,0BAAsB,YAAY;AAGlC,UAAM;AAAA,MACJ,wBAAAC;AAAA,MACA,mBAAAC;AAAA,MACA,yBAAAC;AAAA,MACA,oBAAAC;AAAA,IACF,IAAI,MAAM;AACV,UAAM,WAAW,QAAQ,mBAAmB;AAC5C,UAAM,YAAY,QAAQ,oBAAoB;AAC9C,UAAM,sBACJ,aAAa,SACTF,mBAAkB,KAAK,IACvBD,wBAAuB,KAAK;AAClC,UAAM,uBACJ,cAAc,SACVG,oBAAmB,KAAK,IACxBD,yBAAwB,KAAK;AAEnC,UAAM,mBAAmB,KAAK,MAAO,sBAAsB,OAAQ,EAAE;AACrE,UAAM,oBAAoB,KAAK,MAAO,uBAAuB,OAAQ,EAAE;AAGvE,UAAM,gBAAgB;AACtB,UAAM,cAAc;AACpB,UAAM,gBAAgB,KAAK,MAAM,gBAAgB,WAAW;AAC5D,UAAM,iBAAiB,KAAK,MAAM,gBAAgB,GAAG;AAIrD,UAAM,cAAc;AAAA,MAClB,QAAQ,SAAS;AAAA,MACjB;AAAA,IACF;AAGA,UAAM,eACJ,QAAQ,WAAW,SACf,oBAAoB,QAAQ,QAAQ,iBAAiB,IACrD;AAGN,UAAM,aAAa,MAAM;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,EAAE,oBAAAE,oBAAmB,IAAI,MAAM;AAGrC,UAAM,WAAW,aACbA,oBAAmB,QAAQ,UAAU,OAAO,SAAS,IACrD;AAGJ,UAAM,YAAY,gBAAgB,WAAW,mBAAmB;AAGhE,UAAM,WAAW,oBAAoB;AAAA,MACnC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,gBAAgB,EAAE,OAAO,WAAW,OAAO,QAAQ,WAAW,OAAO;AAAA,MACrE,GAAI,YAAY,EAAE,SAAS;AAAA,IAC7B,CAAC;AAGD,UAAM,UAAe,CAAC;AACtB,QAAI,QAAQ,SAAS,WAAW,QAAW;AACzC,cAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,IACvD;AACA,QAAI,QAAQ,SAAS,UAAU,QAAW;AACxC,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,IACrD;AAEA,aAAS;AAAA,MACP,IAAIC,WAAU;AAAA,QACZ,UAAU,CAAC,QAAQ;AAAA,QACnB;AAAA,QACA,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,KAAK,EAAE,QAAQ;AAAA,QACjD,GAAI,QAAQ,aAAa,UAAa,EAAE,UAAU,QAAQ,SAAS;AAAA,QACnE,GAAI,QAAQ,cAAc,UAAa;AAAA,UACrC,WAAW,QAAQ;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AAEd,UAAM,IAAI,MAAM,6BAA6B,SAAS,EAAE;AAAA,EAC1D;AAEA,MAAI,QAAQ,SAAS;AAEnB,UAAM,gBAAgB,gCAAgC,KAAK,QAAQ,OAAO;AAE1E,QAAI,CAAC,eAAe;AAElB,eAAS;AAAA,QACP,IAAIA,WAAU;AAAA,UACZ,MAAM,qBAAqB,QAAQ,OAAO;AAAA,UAC1C,OAAO;AAAA,UACP,WAAWC,eAAc;AAAA;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,YAAM,WAAW;AAAA,QACf,QAAQ;AAAA,QACR,CAAC;AAAA,QACD;AAAA,UACE,kBAAkB;AAAA,QACpB;AAAA,MACF;AAEA,eAAS;AAAA,QACP,IAAID,WAAU;AAAA,UACZ,UAAU;AAAA,UACV,OAAO;AAAA;AAAA,UACP,WAAWC,eAAc;AAAA;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,gBACd,MACA,UAA4B,CAAC,GAChB;AACb,QAAM,YAAY,aAAa,KAAK,aAAa,QAAQ;AACzD,QAAM,mBAAmB,qBAAqB,KAAK,MAAM;AACzD,QAAM,wBAAwB,qBAAqB,KAAK,WAAW;AAEnE,SAAO;AAAA,IACL,IAAID,WAAU;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,MACA,SAAS,QAAQ;AAAA,IACnB,CAAC;AAAA,IACD,IAAIA,WAAU;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAKO,SAAS,WACd,OACA,QACA,YACA,UAAuB,CAAC,GACX;AACb,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,aAA0B,CAAC;AAQjC,QAAM,eAAe,mBAAmB,QAAQ,WAAW,QAAQ,QAAQ;AAE3E,QAAM,YAAY,MAAM,IAAI,CAAC,SAAS;AACpC,UAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK;AACpD,UAAM,WAAW,OAAO,SAAS,WAAW,KAAK,WAAW;AAC5D,WAAO,QAAQ,KAAK,KAAK,CAAC,KAAK,QAAQ,QAAQ;AAAA,EACjD,CAAC;AACD,QAAM,gBAAgB,UAAU,QAAQ,IAAI;AAC5C,QAAM,eAAe,UAAU,YAAY,IAAI;AAC/C,QAAM,gBACJ,kBAAkB,KAAK,SAAY,iBAAiB,QAAQ,OAAO;AAErE,QAAM,QAAQ,CAAC,MAAM,UAAU;AAE7B,UAAM,WAAW,OAAO,SAAS,WAAW,OAAO,KAAK;AACxD,UAAM,YAAY,OAAO,SAAS,WAAW,KAAK,SAAS,IAAI;AAC/D,UAAM,eAAe,OAAO,SAAS,WAAW,KAAK,WAAW;AAIhE,QAAI,CAAC,SAAS,KAAK,KAAK,CAAC,cAAc;AACrC;AAAA,IACF;AAIA,UAAM,WAAW,eACb,mBAAmB,cAAc,CAAC,CAAC,IACnC;AAAA,MACE;AAAA,MACA,CAAC;AAAA,MACD;AAAA,QACE,kBAAkB;AAAA,QAClB,SAAS,cAAc;AAAA,MACzB;AAAA,IACF;AAGJ,UAAM,UAA+C,CAAC;AACtD,QAAI,UAAU,KAAK,QAAQ,SAAS,QAAQ;AAC1C,cAAQ,SAAS,cAAc,QAAQ,QAAQ,MAAM;AAAA,IACvD;AACA,QAAI,UAAU,MAAM,SAAS,KAAK,QAAQ,SAAS,OAAO;AACxD,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,KAAK;AAAA,IACrD,WAAW,QAAQ,SAAS,MAAM;AAChC,cAAQ,QAAQ,cAAc,QAAQ,QAAQ,IAAI;AAAA,IACpD;AAGA,UAAM,oBAAsC;AAAA,MAC1C,GAAI,iBAAiB,UAAU,gBAAgB,cAAc,QAAQ,CAAC;AAAA,MACtE,GAAG;AAAA,MACH,GAAI,iBAAiB,UAAU,eAC3B,kBAAkB,cAAc,GAAG,IACnC,CAAC;AAAA,IACP;AAEA,UAAM,YAAY,IAAIA,WAAU;AAAA,MAC9B,OAAO;AAAA;AAAA,MACP,UAAU;AAAA,MACV,WAAW,QAAQ,YACf,aAAa,QAAQ,SAAS,IAC9BC,eAAc;AAAA,MAClB;AAAA;AAAA,MAEA,GAAI,QAAQ,sBAAsB;AAAA,QAChC,WAAW;AAAA,UACT,WAAW,QAAQ;AAAA,UACnB,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAED,eAAW,KAAK,SAAS;AAAA,EAC3B,CAAC;AAED,gBAAc;AAAA,IACZ,MACG,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,OAAO,KAAK,IAAK,EAC3D,KAAK,IAAI;AAAA,EACd;AAEA,SAAO;AACT;AA+GA,eAAsB,YACpB,SACA,aACA,OACA,WACA,WAAyB,CAAC,GACV;AAEhB,QAAM,aAAa,cAAc,OAAO,SAAS;AAGjD,QAAM,UAAU,QAAQ,CAAC,GAAG,OAAO,UAAU;AAG7C,QAAM,yBAAyB,OAAqB;AAAA,IAClD,OAAO;AAAA,IACP,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,EACd;AAMA,QAAM,mBAAmB,oBAAI,IAAY;AACzC,QAAM,gBAAgB,CAAC,MAAc,YAA0B;AAC7D,QAAI,iBAAiB,IAAI,OAAO,EAAG;AACnC,qBAAiB,IAAI,OAAO;AAE5B,YAAQ,KAAK,kBAAkB,IAAI,KAAK,OAAO,EAAE;AAAA,EACnD;AASA,QAAM,mBAAmB,CACvB,OACA,SACuB;AACvB,QAAI,UAAU,UAAa,UAAU,OAAQ,QAAO;AACpD,QAAI,UAAU,eAAe;AAC3B,UAAI,SAAS,kBAAmB,QAAO;AACvC;AAAA,QACE;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,QAAI,mBAAmB,KAAK,KAAK,EAAG,QAAO,MAAM,YAAY;AAC7D,QAAI;AACF,aAAO,aAAa,OAAO,KAAK;AAAA,IAClC,QAAQ;AAIN,YAAM,UACJ,SAAS,oBACL,4CACA;AACN,YAAM,IAAI;AAAA,QACR,sBAAsB,IAAI,MAAM,KAAK,8EAA8E,OAAO;AAAA,MAC5H;AAAA,IACF;AAAA,EACF;AAGA,QAAM,uBAAuB,CAC3B,WAGe;AACf,QAAI,WAAW,OAAW,QAAO;AACjC,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,EAAE,KAAK,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,MAAM,OAAO;AAAA,IACpE;AACA,WAAO;AAAA,MACL,KAAK,OAAO,OAAO;AAAA,MACnB,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,sBAAsB,CAC1B,WAGe;AACf,QAAI,WAAW,OAAW,QAAO;AACjC,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,EAAE,KAAK,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,MAAM,OAAO;AAAA,IACpE;AACA,WAAO;AAAA,MACL,KAAK,OAAO,OAAO;AAAA,MACnB,OAAO,OAAO,SAAS;AAAA,MACvB,QAAQ,OAAO,UAAU;AAAA,MACzB,MAAM,OAAO,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,mBAAmB,CACvB,YAGe;AACf,QAAI,YAAY,OAAW,QAAO;AAClC,QAAI,OAAO,YAAY,UAAU;AAC/B,aAAO,EAAE,KAAK,SAAS,OAAO,SAAS,QAAQ,SAAS,MAAM,QAAQ;AAAA,IACxE;AACA,WAAO;AAAA,MACL,KAAK,QAAQ,OAAO;AAAA,MACpB,OAAO,QAAQ,SAAS;AAAA,MACxB,QAAQ,QAAQ,UAAU;AAAA,MAC1B,MAAM,QAAQ,QAAQ;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,0BAA0B,IAC3B,YAC8D;AACjE,UAAM,aAAa,QAAQ,IAAI,oBAAoB;AACnD,UAAM,WAAW,uBAAuB;AACxC,UAAM,eACJ,OAAO,SAAS,gBAAgB,WAC5B,SAAS,cACT;AAEN,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QACE,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAC1D,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,yBAAyB,IAC1B,YAC8D;AACjE,UAAM,aAAa,QAAQ,IAAI,mBAAmB;AAClD,UAAM,WAAW,uBAAuB;AACxC,UAAM,cACJ,OAAO,SAAS,eAAe,WAAW,SAAS,aAAa;AAElE,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QACE,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAC1D,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,sBAAsB,CAC1B,UAMA,kBACA,oBAcG;AACH,UAAM,SAaF,CAAC;AAEL,QAAI,kBAAkB;AACpB,YAAM,kBAAkB,qBAAqB,gBAAgB;AAC7D,UAAI,iBAAiB;AACnB,eAAO,cAAc,CAAC;AACtB,YAAI,SAAS,YAAY,gBAAgB,QAAQ;AAC/C,iBAAO,YAAY,MAAM,gBAAgB;AAC3C,YAAI,SAAS,cAAc,gBAAgB,SAAS;AAClD,iBAAO,YAAY,OAAO,gBAAgB;AAC5C,YAAI,SAAS,aAAa,gBAAgB,UAAU;AAClD,iBAAO,YAAY,QAAQ,gBAAgB;AAC7C,YAAI,SAAS,aAAa,gBAAgB,WAAW;AACnD,iBAAO,YAAY,SAAS,gBAAgB;AAAA,MAChD;AAAA,IACF;AAEA,QAAI,iBAAiB;AACnB,YAAM,iBAAiB,oBAAoB,eAAe;AAC1D,UAAI,gBAAgB;AAClB,eAAO,aAAa,CAAC;AACrB,YAAI,SAAS,YAAY,eAAe,QAAQ;AAC9C,iBAAO,WAAW,MAAM,eAAe;AACzC,YAAI,SAAS,cAAc,eAAe,SAAS;AACjD,iBAAO,WAAW,OAAO,eAAe;AAC1C,YAAI,SAAS,aAAa,eAAe,UAAU;AACjD,iBAAO,WAAW,QAAQ,eAAe;AAC3C,YAAI,SAAS,aAAa,eAAe,WAAW;AAClD,iBAAO,WAAW,SAAS,eAAe;AAAA,MAC9C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAGA,QAAM,sBAAsB,IACvB,aAGY;AACf,UAAM,aAAa,SAAS,IAAI,gBAAgB;AAChD,UAAM,SAAS,WAAW,KAAK,CAAC,MAAM,MAAM,MAAS;AACrD,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO;AAAA,MACL,KAAK,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO;AAAA,MACvD,OAAO,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,UAAU,EAAE,GAAG,SAAS;AAAA,MAC7D,QAAQ,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,WAAW,EAAE,GAAG,UAAU;AAAA,MAChE,MAAM,WAAW,KAAK,CAAC,MAAM,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,oBAAoB,CACxB,UACA,WACA,SACA,UAKA,qBAC2B;AAC3B,UAAM,WAAW,uBAAuB;AAGxC,UAAM,aAA8B;AAAA,MAClC,GAAG,SAAS;AAAA,MACZ,GAAG,UAAU;AAAA,MACb,GAAG,WAAW;AAAA,MACd,GAAG,SAAS;AAAA,IACd;AAGA,UAAM,cACJ,YAAY,mBACR;AAAA,MACE;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IACnB,IACA,CAAC;AAKP,UAAM,oBAAoB;AAAA,MACxB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,mBAAmB;AAAA,MACvB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,gBAAgB;AAAA,MACpB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS,SAAS,WAAW,SAAS,UAAU,SAAS,SAAS;AAAA,QAClE;AAAA,MACF;AAAA,MACA,iBAAiB;AAAA,QACf,SAAS,mBACP,WAAW,mBACX,UAAU,mBACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,qBACE,SAAS,uBACT,WAAW,uBACX,UAAU,uBACV,SAAS;AAAA,MACX,mBACE,SAAS,qBACT,WAAW,qBACX,UAAU,qBACV,SAAS;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,QAAQ,SAAS,UAAU,WAAW,UAAU,UAAU;AAAA,IAC5D;AAAA,EACF;AAGA,QAAM,0BAA0B,CAC9B,UACA,gBACA,WACA,WACA,UACA,qBAC2B;AAC3B,UAAM,WAAW,uBAAuB;AAGxC,UAAM,aAA8B;AAAA,MAClC,GAAG,SAAS;AAAA,MACZ,GAAG,UAAU;AAAA,MACb,GAAG,gBAAgB;AAAA,MACnB,GAAG,WAAW;AAAA,MACd,GAAG,WAAW;AAAA,IAChB;AAGA,UAAM,cACJ,YAAY,mBACR;AAAA,MACE;AAAA,QACE,UAAU;AAAA,QACV,YAAY,SAAS;AAAA,QACrB,WAAW,SAAS;AAAA,MACtB;AAAA,MACA,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,IACnB,IACA,CAAC;AAKP,UAAM,oBAAoB;AAAA,MACxB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,mBAAmB;AAAA,MACvB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAU;AAAA,MACV,kBAAkB;AAAA;AAAA,IACpB;AAGA,UAAM,gBAAgB;AAAA,MACpB,WAAW;AAAA,MACX,gBAAgB;AAAA,MAChB,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,QACL,WAAW,SACT,gBAAgB,SAChB,WAAW,SACX,UAAU,SACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,iBAAiB;AAAA,QACf,WAAW,mBACT,gBAAgB,mBAChB,WAAW,mBACX,UAAU,mBACV,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,qBACE,WAAW,uBACX,gBAAgB,uBAChB,WAAW,uBACX,UAAU,uBACV,SAAS;AAAA,MACX,mBACE,WAAW,qBACX,gBAAgB,qBAChB,WAAW,qBACX,UAAU,qBACV,SAAS;AAAA,MACX,MAAM;AAAA,MACN,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,QACE,WAAW,UACX,gBAAgB,UAChB,WAAW,UACX,UAAU;AAAA,IACd;AAAA,EACF;AAIA,QAAM,iBAAiB,CACrB,QAMA,SACG;AACH,WAAO,OAAO,IAAI;AAAA,EACpB;AAIA,QAAM,kBAAkB,CACtB,SAGA,SACuB;AACvB,QAAI,YAAY,OAAW,QAAO;AAClC,WAAO,QAAQ,IAAI,IAAI;AAAA,EACzB;AAKA,QAAM,2BAA2B,CAC/B,YAGG;AACH,QAAI,YAAY,OAAW,QAAO;AAElC,WAAO;AAAA,MACL,gBAAgB,UAAU;AAAA;AAAA,MAC1B,KAAK,gBAAgB,SAAS,KAAK,KAAK;AAAA,MACxC,QAAQ,gBAAgB,SAAS,QAAQ,KAAK;AAAA,MAC9C,MAAM,gBAAgB,SAAS,MAAM,KAAK;AAAA,MAC1C,OAAO,gBAAgB,SAAS,OAAO,KAAK;AAAA,IAC9C;AAAA,EACF;AAGA,QAAM,uBAAuB,CAC3B,gBAQG;AACH,QAAI,gBAAgB,QAAW;AAC7B,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF;AACA,QAAI,OAAO,gBAAgB,WAAW;AACpC,aAAO;AAAA,QACL,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,MACL,KAAK,YAAY,OAAO;AAAA,MACxB,OAAO,YAAY,SAAS;AAAA,MAC5B,QAAQ,YAAY,UAAU;AAAA,MAC9B,MAAM,YAAY,QAAQ;AAAA,MAC1B,kBAAkB,YAAY,oBAAoB;AAAA,MAClD,gBAAgB,YAAY,kBAAkB;AAAA,IAChD;AAAA,EACF;AAGA,QAAM,gBAAgB,qBAAqB,YAAY,WAAW;AAGlE,QAAM,eAAe,CAAC,MAAc,OAAe,aAAuB;AACxE,QAAI,SAAS,KAAK,UAAU;AAC1B,aAAO,EAAE,OAAOC,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,IAC7D;AACA,WAAO;AAAA,MACL,OAAOA,aAAY;AAAA,MACnB,MAAM,OAAO;AAAA;AAAA,MACb,OAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAGA,QAAM,mBAAmB,CACvB,MACA,aAMY;AAGZ,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,SAAS,aACZ,cAAc,MACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,YACZ,cAAc,SACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,aACZ,cAAc,OACd,cAAc;AAAA,MACpB,KAAK;AACH,eAAO,SAAS,YACZ,cAAc,QACd,cAAc;AAAA,MACpB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,qBAAqB,OACzB,MACA,cACA,eACA,SACA,UAOA,YAI8B;AAC9B,QAAI,eAAiC,CAAC;AAKtC,QAAI,CAAC,MAAM;AACT,aAAO,cAAc,cAAc,OAAO;AAAA,IAC5C;AAGA,UAAM,eAAe,qBAAqB;AAAA,MACxC,YAAY,aAAa,MAAM,UAAU,cAAc;AAAA,MACvD,MAAM,aAAa,MAAM,QAAQ;AAAA,MACjC,QAAQ,aAAa,MAAM,UAAU;AAAA,MACrC,YAAY,aAAa,MAAM;AAAA,IACjC,CAAC;AACD,UAAM,cAAc;AAAA,MAClB,MAAM,aAAa;AAAA,MACnB,MAAM,aAAa,MAAM,OACrB,aAAa,KAAK,OAAO,IACzB,cAAc;AAAA;AAAA,MAClB,MAAM,aAAa,QAAQ;AAAA,MAC3B,SAAS,aAAa,WAAW;AAAA,MACjC,WAAW,aAAa,MAAM,YAC1B,EAAE,MAAM,SAAkB,IAC1B;AAAA,MACJ,OAAO,aAAa,SAAS,cAAc;AAAA,IAC7C;AAEA,QAAI,OAAO,SAAS,YAAY,UAAU,QAAQ,WAAW,MAAM;AAEjE,UAAI,qBAAqB,IAAI,GAAG;AAC9B,cAAM,WAAW;AACjB,cAAM,gBAAgB,SAAS,MAAM;AACrC,cAAM,eAAe,qBAAqB;AAAA,UACxC,YAAY,eAAe,UAAU,YAAY;AAAA,UACjD,MAAM,eAAe;AAAA,UACrB,QAAQ,eAAe;AAAA,UACvB,YAAY,eAAe;AAAA,QAC7B,CAAC;AACD,cAAM,iBAAiB;AAAA,UACrB,GAAG;AAAA,UACH,GAAI,aAAa,QAAQ,EAAE,MAAM,aAAa,KAAK;AAAA,UACnD,GAAI,eAAe,QAAQ,EAAE,MAAM,cAAc,OAAO,EAAE;AAAA,UAC1D,GAAI,aAAa,SAAS,UAAa;AAAA,YACrC,MAAM,aAAa;AAAA,UACrB;AAAA,UACA,GAAI,aAAa,YAAY,UAAa;AAAA,YACxC,SAAS,aAAa;AAAA,UACxB;AAAA,UACA,GAAI,eAAe,cAAc,UAAa;AAAA,YAC5C,WAAW,cAAc,YACrB,EAAE,MAAM,SAAkB,IAC1B;AAAA,UACN;AAAA,UACA,GAAI,eAAe,SAAS;AAAA,YAC1B,OAAO,aAAa,cAAc,OAAO,KAAK;AAAA,UAChD;AAAA,QACF;AAIA,cAAM,oBAAoB,YAAY,SAAS,MAAM;AACrD,uBAAe,oBACX,mBAAmB,mBAAmB,cAAc,IACpD,UACE,qBAAqB,SAAS,MAAM,MAAM,SAAS,cAAc,IACjE,wBAAwB,SAAS,MAAM,MAAM,gBAAgB;AAAA,UAC3D,kBAAkB;AAAA,QACpB,CAAC;AAAA,MACT,WAAW,iBAAiB,IAAI,GAAG;AACjC,cAAM,YAAY;AAClB,YAAI;AAEF,gBAAM,cAAc,mBAAmB,UAAU,KAAK;AACtD,cAAI,CAAC,aAAa;AAChB,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,cAAc,MAAM,eAAe,WAAW;AAGpD,gBAAM,cACJ,OAAO,UAAU,MAAM,UAAU,WAC7B,gBAAgB,UAAU,MAAM,OAAO,GAAG,IAC1C,UAAU,MAAM;AAGtB,gBAAM,eACJ,OAAO,UAAU,MAAM,WAAW,WAC9B,gBAAgB,UAAU,MAAM,QAAQ,GAAG,IAC3C,UAAU,MAAM;AAGtB,gBAAM,aAAa,MAAM;AAAA,YACvB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA;AAAA,YACA;AAAA;AAAA,UACF;AAEA,gBAAM,UAAU,gBAAgB,aAAa,YAAY,WAAW;AACpE,gBAAM,WAAW,oBAAoB;AAAA,YACnC,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,gBAAgB;AAAA,cACd,OAAO,WAAW;AAAA,cAClB,QAAQ,WAAW;AAAA,YACrB;AAAA,UACF,CAAC;AACD,yBAAe,CAAC,QAAQ;AAAA,QAC1B,SAAS,OAAO;AAEd,gBAAM,cAAc,UAAU,MAAM,KAAK,KAAK,IAC1C,eACA,UAAU,MAAM,UAAU,UAAU,MAAM,QAAQ;AACtD,yBAAe;AAAA,YACb,IAAIC,SAAQ;AAAA,cACV,MAAM,WAAW,YAAY,UAAU,GAAG,EAAE,CAAC,GAAG,YAAY,SAAS,KAAK,QAAQ,EAAE;AAAA,cACpF,MAAM,YAAY;AAAA,cAClB,MAAM,YAAY;AAAA,cAClB,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,OAAO;AAEL,uBAAe;AAAA,UACb,IAAIA,SAAQ;AAAA,YACV,MAAM,gCAAgC,KAAK,IAAI;AAAA,YAC/C,MAAM,YAAY;AAAA,YAClB,MAAM,YAAY;AAAA,YAClB,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,OAAO;AAEL,qBAAe,WACX,mBAAmB,UAAU,WAAW,IACxC,UACE,qBAAqB,MAAgB,SAAS,WAAW,IACzD,wBAAwB,MAAgB,aAAa;AAAA,QACnD,kBAAkB;AAAA,MACpB,CAAC;AAAA,IACT;AAIA,WAAO,cAAc,cAAc,OAAO;AAAA,EAC5C;AAIA,QAAM,aAAa,QAAQ;AAC3B,QAAM,eAAe,QAAQ;AAAA,IAC3B,CAAC,WAAW,QAAQ,aAAa;AAC/B,YAAM,aAAa,OAAO;AAC1B,YAAM,WAAW;AAAA,QACf,YAAY,aAAa;AAAA,QACzB,WAAW,aAAa,aAAa;AAAA,MACvC;AACA,YAAM,iBAAiB;AAAA,QACrB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,UACE,aAAa,YAAY;AAAA,UACzB,YAAY,YAAY;AAAA,QAC1B;AAAA,MACF;AACA,UAAI,eAAe,WAAW,QAAW;AACvC,eAAO,cAAc,SACjB,KAAK,IAAI,WAAW,eAAe,MAAM,IACzC,eAAe;AAAA,MACrB;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,SAAS;AAAA;AAAA,IAE7B,aAAa,YAAY,2BAA2B;AAAA,IACpD,QACE,iBAAiB,SACb,EAAE,OAAO,eAAe,IAAI,MAAM,UAAmB,IACrD;AAAA,IACN,UAAU,MAAM,QAAQ;AAAA,MACtB,QAAQ,IAAI,OAAO,QAAQ,aAAa;AACtC,cAAM,aAAa,OAAO;AAG1B,cAAM,WAAW;AAAA,UACf,YAAY;AAAA;AAAA,UACZ,WAAW,YAAY;AAAA;AAAA,UACvB,YAAY,aAAa;AAAA,UACzB,WAAW,aAAa,aAAa;AAAA,QACvC;AAGA,cAAM,iBAAiB;AAAA,UACrB,YAAY;AAAA,UACZ,YAAY;AAAA,UACZ,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,YACE,aAAa,YAAY;AAAA,YACzB,YAAY,YAAY;AAAA,UAC1B;AAAA,QACF;AAEA,cAAM,eAAe,MAAM;AAAA,UACzB,YAAY;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,YAAY;AAAA,QACd;AAEA,cAAM,sBAAsB,eAAe;AAC3C,cAAM,oBAAoB;AAAA,UACxB,eAAe;AAAA,QACjB;AAEA,eAAO,IAAI,UAAU;AAAA,UACnB,UAAU;AAAA,YACR,IAAIH,WAAU;AAAA,cACZ,GAAI,YAAY,iBAAiB,EAAE,UAAU,KAAK;AAAA,cAClD,SAAS,WAAW;AAAA,cACpB,WAAW,aAAa,mBAAmB;AAAA,cAC3C,UAAU;AAAA,YACZ,CAAC;AAAA,UACH;AAAA,UAEA,eAAe;AAAA,UACf,GAAI,eAAe,oBAAoB,iBAAiB;AAAA,YACtD,SAAS;AAAA,cACP,MAAM,eAAe;AAAA,YACvB;AAAA,UACF;AAAA,UACA,SAAS,yBAAyB,eAAe,OAAO;AAAA,UACxD,SAAS;AAAA,YACP,KAAK;AAAA,cACH,eAAe,eAAe,YAAY,KAAK;AAAA,cAC/C,eAAe,eAAe,aAAa,KAAK;AAAA,cAChD,iBAAiB,OAAO,QAAQ;AAAA,YAClC;AAAA,YACA,QAAQ;AAAA,cACN,eAAe,eAAe,YAAY,QAAQ;AAAA,cAClD,eAAe,eAAe,aAAa,QAAQ;AAAA,cACnD,iBAAiB,UAAU,QAAQ;AAAA,YACrC;AAAA,YACA,MAAM;AAAA,cACJ,eAAe,eAAe,YAAY,MAAM;AAAA,cAChD,eAAe,eAAe,aAAa,MAAM;AAAA,cACjD,iBAAiB,QAAQ,QAAQ;AAAA,YACnC;AAAA,YACA,OAAO;AAAA,cACL,eAAe,eAAe,YAAY,OAAO;AAAA,cACjD,eAAe,eAAe,aAAa,OAAO;AAAA,cAClD,iBAAiB,SAAS,QAAQ;AAAA,YACpC;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAGD,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,MAAM,KAAK,EAAE,QAAQ,QAAQ,GAAG,OAAO,GAAG,aAAa;AACrD,YAAM,YAAY,aAAa,UAAU;AAOzC,YAAM,WAAW,YAAY,OAAO,QAAQ;AAC5C,YAAM,cAAc,UAAU;AAC9B,YAAM,wBAAwB,cAC1B,mBAAmB,WAAW,IAC9B;AAOJ,YAAM,iBAAiB,cACnB,QAAQ,IAAI,OAAO,EAAE,KAAK,mBAAmB,WAAW,EAAE,EAAE,IAC5D;AAGJ,YAAM,YAAY,QAAQ;AAAA,QACxB,CAAC,WAAW,QAAQ,aAAa;AAC/B,gBAAM,OAAO,OAAO,QAAQ,QAAQ;AACpC,cAAI,MAAM;AACR,kBAAM,WAAW;AAAA,cACf,YAAY,aAAa;AAAA,cACzB,WAAW,aAAa,aAAa;AAAA,cACrC;AAAA,YACF;AACA,kBAAM,iBAAiB;AAAA,cACrB,YAAY;AAAA,cACZ,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,gBACE,aAAa,YAAY;AAAA,gBACzB,YAAY,YAAY;AAAA,cAC1B;AAAA,YACF;AACA,gBAAI,eAAe,WAAW,QAAW;AACvC,qBAAO,cAAc,SACjB,KAAK,IAAI,WAAW,eAAe,MAAM,IACzC,eAAe;AAAA,YACrB;AAAA,UACF;AACA,iBAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAEA,aAAO,IAAI,SAAS;AAAA,QAClB,QACE,cAAc,SACV,EAAE,OAAO,YAAY,IAAI,MAAM,UAAmB,IAClD;AAAA,QACN,GAAI,UAAU,cAAc,UAAa;AAAA,UACvC,WAAW,SAAS;AAAA,QACtB;AAAA,QACA,GAAI,UAAU,gBAAgB,UAAa;AAAA,UACzC,aAAa,SAAS;AAAA,QACxB;AAAA;AAAA,QAEA,GAAG;AAAA,QACH,UAAU,MAAM,QAAQ;AAAA,UACtB,QAAQ,IAAI,OAAO,QAAQ,aAAa;AACtC,kBAAM,OAAO,OAAO,QAAQ,QAAQ;AAGpC,kBAAM,WAAW;AAAA,cACf,YAAY;AAAA;AAAA,cACZ,YAAY,aAAa;AAAA,cACzB,WAAW,aAAa,aAAa;AAAA,cACrC;AAAA,YACF;AAEA,gBAAI,CAAC,MAAM;AAET,oBAAM,2BAA2B;AAAA,gBAC/B,YAAY;AAAA,gBACZ,OAAO;AAAA,gBACP;AAAA,gBACA;AAAA,gBACA;AAAA,kBACE,aAAa,YAAY;AAAA,kBACzB,YAAY,YAAY;AAAA,gBAC1B;AAAA,cACF;AACA,qBAAO,IAAI,UAAU;AAAA,gBACnB,UAAU;AAAA,kBACR,IAAIA,WAAU;AAAA,oBACZ,GAAK,YAAY,iBAAiB,CAAC,aAClC,aAAa,YAAY,WACtB,EAAE,UAAU,KAAK,IACjB,CAAC;AAAA,oBACL,SAAS,WAAW;AAAA,oBACpB,WAAWC,eAAc;AAAA,oBACzB,GAAG,iBAAiB,QAAQ;AAAA,oBAC5B,UAAU,CAAC;AAAA,kBACb,CAAC;AAAA,gBACH;AAAA,gBACA,SAAS;AAAA,kBACP,KAAK;AAAA,oBACH;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,OAAO,QAAQ;AAAA,kBAClC;AAAA,kBACA,QAAQ;AAAA,oBACN;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,UAAU,QAAQ;AAAA,kBACrC;AAAA,kBACA,MAAM;AAAA,oBACJ;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,QAAQ,QAAQ;AAAA,kBACnC;AAAA,kBACA,OAAO;AAAA,oBACL;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA;AAAA,sBACE,yBAAyB;AAAA,sBACzB;AAAA,oBACF;AAAA,oBACA,iBAAiB,SAAS,QAAQ;AAAA,kBACpC;AAAA,gBACF;AAAA,cACF,CAAC;AAAA,YACH;AAGA,kBAAM,iBAAiB;AAAA,cACrB,YAAY;AAAA,cACZ,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,gBACE,aAAa,YAAY;AAAA,gBACzB,YAAY,YAAY;AAAA,cAC1B;AAAA,YACF;AAEA,kBAAM,eAAe,MAAM;AAAA,cACzB,KAAK;AAAA,cACL;AAAA,cACA,WAAW;AAAA,cACX,KAAK;AAAA,cACL,KAAK;AAAA,cACL;AAAA,YACF;AAEA,kBAAM,sBAAsB,eAAe;AAC3C,kBAAM,oBAAoB;AAAA,cACxB,eAAe;AAAA,YACjB;AAEA,mBAAO,IAAI,UAAU;AAAA,cACnB,UAAU;AAAA,gBACR,IAAID,WAAU;AAAA,kBACZ,GAAK,YAAY,iBAAiB,CAAC,aAClC,aAAa,YAAY,WACtB,EAAE,UAAU,KAAK,IACjB,CAAC;AAAA,kBACL,SAAS,WAAW;AAAA,kBACpB,WAAW,aAAa,mBAAmB;AAAA,kBAC3C,GAAG,iBAAiB,QAAQ;AAAA,kBAC5B,UAAU;AAAA,gBACZ,CAAC;AAAA,cACH;AAAA,cACA,eAAe;AAAA,cACf,GAAI,eAAe,oBAAoB,iBAAiB;AAAA,gBACtD,SAAS;AAAA,kBACP,MAAM,eAAe;AAAA,gBACvB;AAAA,cACF;AAAA,cACA,SAAS,yBAAyB,eAAe,OAAO;AAAA,cACxD,SAAS;AAAA,gBACP,KAAK;AAAA,kBACH,eAAe,eAAe,YAAY,KAAK;AAAA,kBAC/C,eAAe,eAAe,aAAa,KAAK;AAAA,kBAChD,iBAAiB,OAAO,QAAQ;AAAA,gBAClC;AAAA,gBACA,QAAQ;AAAA,kBACN,eAAe,eAAe,YAAY,QAAQ;AAAA,kBAClD;AAAA,oBACE,eAAe;AAAA,oBACf;AAAA,kBACF;AAAA,kBACA,iBAAiB,UAAU,QAAQ;AAAA,gBACrC;AAAA,gBACA,MAAM;AAAA,kBACJ,eAAe,eAAe,YAAY,MAAM;AAAA,kBAChD,eAAe,eAAe,aAAa,MAAM;AAAA,kBACjD,iBAAiB,QAAQ,QAAQ;AAAA,gBACnC;AAAA,gBACA,OAAO;AAAA,kBACL,eAAe,eAAe,YAAY,OAAO;AAAA,kBACjD,eAAe,eAAe,aAAa,OAAO;AAAA,kBAClD,iBAAiB,SAAS,QAAQ;AAAA,gBACpC;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAGA,QAAM,oBAAoB,QAAQ,KAAK,CAAC,QAAQ,IAAI,UAAU,MAAS;AAEvE,MAAI;AACJ,MAAI;AAKJ,MAAI,mBAAmB;AAErB,UAAM,aAAa,MAAM;AACzB,UAAM,EAAE,wBAAAL,yBAAwB,uBAAAS,uBAAsB,IAAI;AAG1D,UAAM,sBAAsBT,wBAAuB,OAAO,SAAS;AAGnE,UAAM,gCAAgC,QAAQ;AAAA,MAAI,CAAC,QACjD,IAAI,UAAU,SACVS,uBAAsB,IAAI,OAAO,mBAAmB,IACpD;AAAA,IACN;AAGA,UAAM,qBAAqB,8BAA8B;AAAA,MACvD,CAAC,KAAa,MAAM,OAAO,KAAK;AAAA,MAChC;AAAA,IACF;AAEA,QAAI,qBAAqB,qBAAqB;AAC5C,cAAQ;AAAA,QACN,yCAAyC,kBAAkB,0CAA0C,mBAAmB;AAAA,MAC1H;AAAA,IACF;AAGA,UAAM,sBAAsB,QAAQ;AAAA,MAClC,CAAC,QAAQ,IAAI,UAAU;AAAA,IACzB,EAAE;AAGF,UAAM,iBAAiB,KAAK;AAAA,MAC1B;AAAA,MACA,sBAAsB;AAAA,IACxB;AACA,UAAM,qBACJ,sBAAsB,IAClB,iBAAiB,sBACjB,cAAc,EAAE;AAGtB,mBAAe,8BAA8B;AAAA,MAC3C,CAAC,MAAM,KAAK;AAAA,IACd;AACA,UAAM,aAAa,aAAa,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AAC7D,iBAAa,EAAE,MAAM,YAAY,MAAM,UAAU,IAAI;AAAA,EACvD,OAAO;AAEL,UAAM,mBAAmB,MAAM,QAAQ;AACvC,mBAAe,QAAQ,IAAI,MAAM,gBAAgB;AACjD,iBAAa,EAAE,MAAM,YAAY,SAAS,KAAK,MAAM,UAAU,WAAW;AAAA,EAC5E;AAEA,SAAO,IAAI,MAAM;AAAA,IACf,OAAO;AAAA,IACP,QAAQ,gBAAgB;AAAA,IACxB;AAAA,IACA,MAAM,CAAC,WAAW,GAAG,QAAQ;AAAA,EAC/B,CAAC;AACH;AAKA,SAAS,aACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAOH,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB;AACE,aAAOA,eAAc;AAAA,EACzB;AACF;AAKA,SAAS,qBACP,WAKY;AACZ,MAAI,CAAC,UAAW,QAAO;AAEvB,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB,KAAK;AACH,aAAO,cAAc;AAAA,IACvB;AACE,aAAO;AAAA,EACX;AACF;AAKO,SAAS,oBACd,UACA,UAGQ;AACR,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,EACF,CAAC;AACH;AAKO,SAAS,oBACd,UACA,UAGQ;AACR,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,EACF,CAAC;AACH;;;AMj8EO,SAAS,uBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAG5C,QAAM,SAAS,UAAU;AAIzB,QAAM,aACH,UAAkB,MACnB,uBAAuB,WAAW,OAAO,MAAM,SAAS;AAG1D,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,IACP,OAAO,SAAS;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,MACE,WAAW,OAAO;AAAA,MAClB,SAAS,OAAO;AAAA,MAChB,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA;AAAA,MAEpB,YAAY,OAAO,MAAM;AAAA,MACzB,UAAU,OAAO,MAAM;AAAA,MACvB,WAAW,OAAO,MAAM;AAAA,MACxB,MAAM,OAAO,MAAM;AAAA,MACnB,YAAa,OAAO,MAChB;AAAA,MACJ,QAAQ,OAAO,MAAM;AAAA,MACrB,WAAW,OAAO,MAAM;AAAA,MACxB,OAAO,OAAO,MAAM;AAAA,MACpB,kBAAkB,OAAO,MAAM;AAAA;AAAA,MAE/B,UAAU,OAAO;AAAA,MACjB,SAAS,OAAO;AAAA,MAChB,cAAc,OAAO;AAAA;AAAA,MAErB,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA;AAAA,MAElB,QAAQ,OAAO;AAAA;AAAA,MAEf;AAAA;AAAA,MAEA,UAAU,OAAO;AAAA;AAAA,MAEjB,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAEA,SAAO,CAAC,MAAM;AAChB;;;AClEA,SAAS,iBAAAI,gBAAe,qBAAqB,mBAAmB;AAEhE,SAAS,qBAAAC,0BAAyB;AAGlC,IAAM,mBAGF;AAAA,EACF,SAAS,YAAY;AAAA,EACrB,YAAY,YAAY;AAAA,EACxB,YAAY,YAAY;AAAA,EACxB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,QAAQ,YAAY;AAAA,EACpB,SAAS,YAAY;AAAA,EACrB,cAAc,YAAY;AAAA,EAC1B,aAAa,YAAY;AAAA,EACzB,KAAK,YAAY;AAAA,EACjB,SAAS,YAAY;AAAA,EACrB,kBAAkB,YAAY;AAAA,EAC9B,kBAAkB,YAAY;AAAA,EAC9B,OAAO,YAAY;AAAA,EACnB,OAAO,YAAY;AAAA,EACnB,kBAAkB,YAAY;AAAA,EAC9B,kBAAkB,YAAY;AAAA,EAC9B,eAAe,YAAY;AAAA,EAC3B,4BAA4B,YAAY;AAAA,EACxC,uBAAuB,YAAY;AAAA,EACnC,mBAAmB,YAAY;AAAA,EAC/B,gBAAgB,YAAY;AAAA,EAC5B,gBAAgB,YAAY;AAAA,EAC5B,aAAa,YAAY;AAAA,EACzB,QAAQ,YAAY;AAAA,EACpB,SAAS,YAAY;AAAA,EACrB,yBAAyB,YAAY;AAAA,EACrC,sBAAsB,YAAY;AAAA,EAClC,8BAA8B,YAAY;AAAA,EAC1C,yBAAyB,YAAY;AAAA,EACrC,sBAAsB,YAAY;AAAA,EAClC,iBAAiB,YAAY;AAAA,EAC7B,4BAA4B,YAAY;AAAA,EACxC,mBAAmB,YAAY;AAAA,EAC/B,2BAA2B,YAAY;AAAA,EACvC,2BAA2B,YAAY;AAAA,EACvC,kBAAkB,YAAY;AAAA,EAC9B,iBAAiB,YAAY;AAAA,EAC7B,wBAAwB,YAAY;AAAA,EACpC,yBAAyB,YAAY;AAAA,EACrC,eAAe,YAAY;AAAA,EAC3B,gBAAgB,YAAY;AAAA,EAC5B,aAAa,YAAY;AAAA,EACzB,gBAAgB,YAAY;AAAA,EAC5B,oBAAoB,YAAY;AAAA,EAChC,cAAc,YAAY;AAAA,EAC1B,cAAc,YAAY;AAAA,EAC1B,MAAM,YAAY;AAAA,EAClB,cAAc,YAAY;AAAA,EAC1B,SAAS,YAAY;AAAA,EACrB,SAAS,YAAY;AAAA,EACrB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,iBAAiB,YAAY;AAAA,EAC7B,cAAc,YAAY;AAAA,EAC1B,eAAe,YAAY;AAAA,EAC3B,aAAa,YAAY;AAAA,EACzB,aAAa,YAAY;AAAA,EACzB,cAAc,YAAY;AAC5B;AAEA,IAAM,gBAGF;AAAA,EACF,OAAOD,eAAc;AAAA,EACrB,KAAKA,eAAc;AAAA,EACnB,MAAMA,eAAc;AAAA,EACpB,OAAOA,eAAc;AAAA,EACrB,QAAQA,eAAc;AACxB;AAgDA,SAAS,eACPE,SACgD;AAChD,MAAI,CAACA,QAAQ,QAAO,YAAY;AAChC,SAAO,iBAAiBA,OAAM,KAAK,YAAY;AACjD;AAKA,SAASC,cACP,WACoD;AACpD,MAAI,CAAC,UAAW,QAAOH,eAAc;AACrC,SAAO,cAAc,SAAS,KAAKA,eAAc;AACnD;AAiCA,SAAS,qBACP,MACwC;AACxC,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,MAAkC;AAAA,IACtC,GAAI,KAAK,UAAU,EAAE,MAAM,KAAK,OAAO;AAAA;AAAA,IAEvC,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,OAAO,EAAE;AAAA,IACrD,GAAI,KAAK,SAAS,EAAE,OAAO,KAAK,MAAM;AAAA,IACtC,GAAI,KAAK,SAAS,UAAa,EAAE,MAAM,KAAK,KAAK;AAAA,IACjD,GAAI,KAAK,WAAW,UAAa,EAAE,SAAS,KAAK,OAAO;AAAA,IACxD,GAAI,KAAK,cAAc,UAAa;AAAA,MAClC,WAAW,KAAK,YAAY,EAAE,MAAM,SAAkB,IAAI;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAMO,SAAS,sBAAsB,QAGpC;AACA,QAAM,SAA2B,CAAC;AAGlC,aAAW,eAAe,OAAO,QAAQ;AACvC,UAAMI,UAAS,eAAe,YAAY,MAAM;AAChD,UAAM,YAAYC,cAAa,YAAY,SAAS;AACpD,UAAM,OACJ,YAAY,SACXD,YAAW,YAAY,SAAS,WAAM,IAAI,YAAY,QAAQ,CAAC;AAGlE,UAAM,aACJ,YAAY,QAAQ,SAAS,SACzB,YAAY,OAAO,OAAO,KAC1B,OAAO,YAAY,QAAQ;AAEjC,UAAM,gBACJ,YAAY,QAAQ,YAAY,SAC5B,YAAY,OAAO,UAAU,KAC7B;AAEN,UAAM,YAAY,qBAAqB,YAAY,IAAI;AAEvD,UAAM,QAAwB;AAAA,MAC5B,OAAO,YAAY;AAAA,MACnB,QAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,WAAW;AAAA,UACT,QAAQ;AAAA,YACN,MAAM,oBAAoB,UAAU;AAAA,YACpC,SAAS,oBAAoB,aAAa;AAAA,UAC5C;AAAA,QACF;AAAA;AAAA;AAAA,QAGA,GAAI,aAAa,EAAE,KAAK,UAAU;AAAA,MACpC;AAAA;AAAA,MAEA,GAAI,YAAY,UAAU,UAAa,EAAE,OAAO,YAAY,MAAM;AAAA,IACpE;AAEA,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB;AAAA,EACF;AACF;AAuCO,IAAM,oBAAN,MAAwB;AAAA,EACZ,WAA2B;AAAA,IAC1C,SAAS,oBAAI,IAAI;AAAA,IACjB,SAAS;AAAA,EACX;AAAA,EACiB,SAAS,IAAIE,mBAAkC;AAAA,EAEhE,IAAY,QAAwB;AAClC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAI,EAAE,SAAS,oBAAI,IAAI,GAAG,SAAS,EAAE,GAAG,QAAQ;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,QAAiE;AACxE,UAAM,YAAY,OAAO;AACzB,SAAK,MAAM,QAAQ,IAAI,WAAW,MAAM;AACxC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,SAAiB,QAAgB;AACjD,WAAO,GAAG,MAAM,IAAI,EAAE,KAAK,MAAM,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,SAA4D;AAC1D,WAAO,MAAM,KAAK,KAAK,MAAM,QAAQ,OAAO,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,QAAQ,MAAM;AACzB,SAAK,MAAM,UAAU;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAA4B;AAC9B,WAAO,KAAK,MAAM,QAAQ,IAAI,SAAS;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,IACE,WAC6D;AAC7D,WAAO,KAAK,MAAM,QAAQ,IAAI,SAAS;AAAA,EACzC;AACF;AAGO,IAAM,0BAA0B,IAAI,kBAAkB;;;ACvV7D,SAAS,kBAAkB,MAGlB;AACP,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,QAA2C,CAAC;AAClD,MAAI,cAA8B;AAClC,MAAI,YAA4B;AAEhC,aAAW,QAAQ,OAAO;AAExB,QAAI,CAAC,KAAK,KAAK,EAAG;AAGlB,UAAM,iBAAiB,KAAK,MAAM,sBAAsB;AACxD,QAAI,gBAAgB;AAClB,YAAM,cAAc,KAAK,MAAM,eAAe,CAAC,EAAE,SAAS,CAAC;AAC3D,YAAMC,QAAO,eAAe,CAAC;AAC7B,YAAM,KAAK,EAAE,MAAAA,OAAM,OAAO,YAAY,CAAC;AACvC,UAAI,gBAAgB,KAAM,eAAc;AACxC;AAAA,IACF;AAGA,UAAM,eAAe,KAAK,MAAM,uBAAuB;AACvD,QAAI,cAAc;AAChB,YAAM,cAAc,KAAK,MAAM,aAAa,CAAC,EAAE,SAAS,CAAC;AACzD,YAAMA,QAAO,aAAa,CAAC;AAC3B,YAAM,KAAK,EAAE,MAAAA,OAAM,OAAO,YAAY,CAAC;AACvC,UAAI,cAAc,KAAM,aAAY;AACpC;AAAA,IACF;AAGA,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,WAAW,KAAM,eAAe,WAAY;AACpD,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM,cAAc,cAAc;AAAA,IAClC;AAAA,EACF;AACF;AAKO,SAAS,yBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,qBAAqB,SAAS,EAAG,QAAO,CAAC;AAG9C,QAAM,iBAAiB,UAAU;AAKjC,QAAM,WAAW,eAAe,WAC5B,OACA,kBAAkB,eAAe,IAAI;AAEzC,MAAI,UAAU;AAEZ,UAAM,YACJ,wBAAwB,kBAAkB,eAAe;AAG3D,UAAM,SAA4B,CAAC;AAEnC,QAAI,SAAS,SAAS,aAAa;AAEjC,aAAO;AAAA,QACL,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,QAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,QAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,MAC7D;AAAA,IACF,OAAO;AAEL,aAAO;AAAA,QACL,EAAE,OAAO,GAAG,QAAQ,WAAW,MAAM,OAAO,WAAW,OAAO;AAAA,QAC9D,EAAE,OAAO,GAAG,QAAQ,eAAe,MAAM,OAAO,WAAW,OAAO;AAAA,QAClE,EAAE,OAAO,GAAG,QAAQ,cAAc,MAAM,OAAO,WAAW,OAAO;AAAA,MACnE;AAAA,IACF;AAEA,UAAM,kBAAmC;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAEA,4BAAwB,SAAS,sBAAsB,eAAe,CAAC;AAIvE,WAAO,WAAW,SAAS,OAAO,OAAO,WAAW;AAAA,MAClD,oBAAoB;AAAA,MACpB,SAAS,eAAe;AAAA,MAGxB,WAAW,eAAe;AAAA,MAC1B,SAAS,eAAe;AAAA,MACxB,WAAW,eAAe;AAAA,MAC1B,UAAU,eAAe;AAAA,IAC3B,CAAC;AAAA,EACH;AAKA,QAAM,kBAAkB,MAAM;AAC5B,UAAM,MAAM,eAAe;AAC3B,QAAI,CAAC,IAAK,QAAO;AAEjB,UAAM,WAAW,IAAI,YAAY;AAGjC,QAAI,aAAa,SAAU,QAAO;AAClC,QAAI,aAAa,QAAS,QAAO;AACjC,QAAI,aAAa,WAAY,QAAO;AACpC,UAAM,eAAe,SAAS,MAAM,kBAAkB;AACtD,QAAI,cAAc;AAGhB,aAAO,kBAAkB,aAAa,CAAC,CAAC;AAAA,IAC1C;AAIA,WAAO;AAAA,EACT,GAAG;AAGH,QAAM,gBAAgB,MAAM;AAC1B,UAAM,MAAM,eAAe;AAC3B,QAAI,CAAC,IAAK,QAAO;AAIjB,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,eAAe,SAAS,MAAM,kBAAkB;AACtD,QAAI,aAAc,QAAO;AAGzB,UAAM,cAAc,MAAM,SAAS,GAAgC;AACnE,QACE,eACA,OAAO,gBAAgB,YACvB,kBAAkB,aAClB;AACA,aAAQ,YAAoB;AAAA,IAC9B;AAEA,WAAO;AAAA,EACT,GAAG;AAGH,QAAM,OAAO,WAAW,eAAe,MAAM,OAAO,WAAW;AAAA,IAC7D,OAAO;AAAA,IACP,SAAS,eAAe;AAAA,IAGxB,aAAa,eAAe,MAAM;AAAA,IAClC,WAAW,eAAe;AAAA,IAC1B,WAAW,eAAe;AAAA,IAC1B,aAAa,eAAe;AAAA;AAAA,IAE5B,YAAY,eAAe,MAAM;AAAA,IACjC,UAAU,eAAe,MAAM;AAAA,IAC/B,WAAW,eAAe,MAAM;AAAA,IAChC,MAAM,eAAe,MAAM;AAAA,IAC3B,YAAa,eAAe,MACxB;AAAA,IACJ,QAAQ,eAAe,MAAM;AAAA,IAC7B,WAAW,eAAe,MAAM;AAAA,IAChC,OAAO,eAAe,MAAM;AAAA,IAC5B,kBAAkB,eAAe,MAAM;AAAA;AAAA,IAEvC,UAAU,eAAe;AAAA,IACzB,SAAS,eAAe;AAAA,IACxB,cAAc,eAAe;AAAA;AAAA,IAE7B;AAAA;AAAA,IAEA,UAAU,eAAe;AAAA;AAAA,IAEzB,UAAU,eAAe;AAAA;AAAA,IAEzB,WAAW,eAAe;AAAA;AAAA,IAE1B,QAAQ,eAAe;AAAA;AAAA,IAEvB,UAAU,eAAe;AAAA;AAAA,IAEzB,YAAY,eAAe;AAAA;AAAA,IAE3B,UAAU,eAAe;AAAA;AAAA,IAEzB,SAAS,eAAe;AAAA;AAAA,IAExB,WAAW,eAAe;AAAA,IAC1B,UAAU,eAAe;AAAA,EAC3B,CAAC;AAED,SAAO,CAAC,IAAI;AACd;;;ACvNA;AAKA,SAAS,gCAAgC,OAAqC;AAC5E,QAAM,SAA4B,CAAC;AAGnC,MAAIC;AACJ,MAAI;AAEJ,MAAI,MAAM,QAAQ;AAChB,QAAI,MAAM,WAAW,YAAY;AAC/B,MAAAA,UAAS;AACT,aAAO;AAAA,IACT,WAAW,MAAM,WAAW,QAAQ;AAClC,MAAAA,UAAS;AACT,aAAO;AAAA,IACT,OAAO;AACL,MAAAA,UAAS,MAAM;AAAA,IACjB;AAAA,EACF,OAAO;AAEL,IAAAA,UAAS;AACT,WAAO,MAAM,UAAU;AAAA,EACzB;AAGA,QAAM,SAA0B;AAAA,IAC9B,OAAO;AAAA,IACP,QAAAA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,OAAO,MAAM;AAAA,EACf;AAGA,MAAI,MAAM,QAAQ;AAChB,QAAI,OAAO,MAAM,WAAW,UAAU;AACpC,aAAO,SAAS,EAAE,MAAM,MAAM,OAAO;AAAA,IACvC,OAAO;AACL,aAAO,SAAS,MAAM;AAAA,IACxB;AAAA,EACF;AAEA,SAAO,KAAK,MAAM;AAGlB,MAAIA,YAAW,UAAU;AACvB,WAAO;AAAA,MACL,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,MAC3D,EAAE,OAAO,GAAG,QAAQ,UAAU,MAAM,UAAK,WAAW,OAAO;AAAA,IAC7D;AAAA,EACF,WAAWA,YAAW,WAAW;AAC/B,WAAO;AAAA,MACL,EAAE,OAAO,GAAG,QAAQ,eAAe,MAAM,OAAO,WAAW,OAAO;AAAA,MAClE,EAAE,OAAO,GAAG,QAAQ,cAAc,MAAM,OAAO,WAAW,OAAO;AAAA,IACnE;AAAA,EACF;AAEA,SAAO;AACT;AASA,SAAS,mBACP,QACA,OACmB;AACnB,SAAO,OAAO,IAAI,CAAC,UAAU;AAC3B,UAAM,OAAO,MAAM;AACnB,QAAI,CAAC,MAAM,MAAO,QAAO;AACzB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,EAAE,GAAG,MAAM,OAAO,aAAa,KAAK,OAAO,KAAK,EAAE;AAAA,IAC1D;AAAA,EACF,CAAC;AACH;AASA,SAAS,eACP,QACA,OACmB;AACnB,MAAI,UAAU,OAAW,QAAO;AAChC,SAAO,OAAO;AAAA,IAAI,CAAC,UACjB,MAAM,UAAU,KAAK,MAAM,UAAU,SAAY,EAAE,GAAG,OAAO,MAAM,IAAI;AAAA,EACzE;AACF;AAKA,SAAS,qBACP,OACQ;AACR,MAAI,CAAC,SAAS,CAAC,MAAM,QAAQ,KAAK,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,MAAI,WAAW;AACf,aAAW,QAAQ,OAAO;AACxB,QAAI,OAAO,SAAS,YAAY,KAAK,UAAU,QAAW;AACxD,iBAAW,KAAK,IAAI,UAAU,KAAK,KAAK;AAAA,IAC1C;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,kBACP,QACA,UACmB;AAEnB,QAAM,WAAW,oBAAI,IAA6B;AAClD,aAAW,SAAS,QAAQ;AAC1B,aAAS,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAGA,QAAM,SAAS,SAAS,IAAI,CAAC;AAC7B,QAAM,aAAa,QAAQ,UAAU;AAGrC,QAAM,SAA4B,CAAC;AACnC,WAAS,IAAI,GAAG,KAAK,UAAU,KAAK;AAClC,QAAI,SAAS,IAAI,CAAC,GAAG;AACnB,aAAO,KAAK,SAAS,IAAI,CAAC,CAAE;AAAA,IAC9B,OAAO;AAEL,UAAI,eAAe,UAAU;AAC3B,cAAM,UAAU,CAAC,UAAK,UAAK,UAAK,UAAK,QAAG;AACxC,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,MAAM,QAAQ,IAAI,QAAQ,MAAM;AAAA,UAChC,WAAW;AAAA,QACb,CAAC;AAAA,MACH,WAAW,eAAe,aAAa,eAAe,YAAY;AAChE,cAAM,UAAU,CAAC,WAAW,eAAe,YAAY;AACvD,cAAMA,UAAS,QAAQ,IAAI,QAAQ,MAAM;AACzC,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAAA;AAAA,UACA,MAAM,IAAI,IAAI,CAAC;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AAAA,MACH,OAAO;AAEL,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,MAAM,IAAI,IAAI,CAAC;AAAA,UACf,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,oBACd,WACA,OACA,WACa;AACb,MAAI,CAAC,gBAAgB,SAAS,EAAG,QAAO,CAAC;AAGzC,QAAM,iBAAiB,UAAU;AAGjC,QAAM,WAAW,qBAAqB,eAAe,KAAK;AAG1D,QAAM,YACJ,eAAe,aACf,wBAAwB,kBAAkB,MAAM;AAGlD,MAAI,CAAC,wBAAwB,IAAI,SAAS,GAAG;AAC3C,QAAI;AAEJ,QAAI,eAAe,UAAU,eAAe,OAAO,SAAS,GAAG;AAE7D,eAAS;AAAA,QACP;AAAA,UACE,eAAe;AAAA,UACf,eAAe;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AAAA,IACF,OAAO;AAEL,YAAM,aAAa,gCAAgC,cAAc;AACjE,eAAS,kBAAkB,YAAY,QAAQ;AAAA,IACjD;AAEA,UAAM,SAA0B;AAAA,MAC9B;AAAA,MACA,QAAQ,mBAAmB,QAAQ,KAAK;AAAA,IAC1C;AACA,UAAM,kBAAkB,sBAAsB,MAAM;AACpD,4BAAwB,SAAS,eAAe;AAAA,EAClD;AAGA,SAAO,WAAW,eAAe,OAAO,OAAO,WAAW;AAAA,IACxD,oBAAoB;AAAA,IACpB,SAAS,eAAe;AAAA,IACxB,WAAW,eAAe;AAAA;AAAA,IAE1B,SAAS,eAAe;AAAA,EAC1B,CAAC;AACH;;;AC3OA,eAAsB,qBACpB,WACA,OACA,WACsB;AACtB,MAAI,CAAC,iBAAiB,SAAS,EAAG,QAAO,CAAC;AAG1C,QAAM,iBAAiB,UAAU;AAGjC,QAAM,cAAc,mBAAmB,cAAc;AAErD,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,YAAY,aAAa,OAAO,WAAW;AAAA,IACtD,SAAS,eAAe;AAAA,IACxB,OAAO,eAAe;AAAA,IACtB,QAAQ,eAAe;AAAA,IACvB,iBAAkB,eAAuB;AAAA,IACzC,kBAAmB,eAAuB;AAAA,IAC1C,WAAW,eAAe;AAAA,IAC1B,SAAS,eAAe;AAAA,IACxB,UAAU,eAAe;AAAA,IACzB,UAAU,eAAe;AAAA,IACzB,WAAW,eAAe;AAAA,EAC5B,CAAC;AACH;;;ACxCA;AAAA,EAEE,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAAC;AAAA,OACK;;;ACXP;AADA,SAAS,eAAAC,oBAAmB;AAQrB,IAAM,eAAe;AAAA,EAC1B,KAAK,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EACzD,OAAO,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC3D,QAAQ,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC5D,MAAM,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EAC1D,kBAAkB,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,EACtE,gBAAgB,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AACtE;AAOO,SAAS,eACd,GACgD;AAChD,UAAQ,GAAG;AAAA,IACX,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB,KAAK;AACH,aAAOA,aAAY;AAAA,IACrB;AACE,aAAOA,aAAY;AAAA,EACrB;AACF;AAiBO,SAAS,cACd,GACA,OAOY;AACZ,MAAI,CAAC,EAAG,QAAO;AAEf,SAAO;AAAA,IACL,OAAO,eAAe,EAAE,KAAK;AAAA,IAC7B,MAAM,EAAE,UAAU,SAAY,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,QAAQ,CAAC,CAAC,IAAI;AAAA,IACrE,OAAO,EAAE,QAAQ,aAAa,EAAE,OAAO,KAAK,IAAI;AAAA,EAClD;AACF;AAmBO,SAASC,gBACd,eACA,OAUY;AACZ,MAAI,CAAC,cAAe,QAAO;AAE3B,QAAM,UAOF,CAAC;AAEL,QAAM,MAAM,cAAc,cAAc,KAAK,KAAK;AAClD,QAAM,QAAQ,cAAc,cAAc,OAAO,KAAK;AACtD,QAAM,SAAS,cAAc,cAAc,QAAQ,KAAK;AACxD,QAAM,OAAO,cAAc,cAAc,MAAM,KAAK;AAEpD,MAAI,IAAK,SAAQ,MAAM;AACvB,MAAI,MAAO,SAAQ,QAAQ;AAC3B,MAAI,OAAQ,SAAQ,SAAS;AAC7B,MAAI,KAAM,SAAQ,OAAO;AAEzB,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;;;AC5HA;AACA;AAFA,SAAS,aAAAC,kBAAwB;AAwC1B,SAAS,iBACd,UACA,UACA,OAWA;AACA,QAAM,WAAgB;AAAA,IACpB,UAAU,SAAS,SAAS,WAAW,CAAC,IAAIC,WAAU,CAAC,CAAC,CAAC;AAAA,IACzD,SAAS;AAAA,MACP,KAAK,UAAU,SAAS,MAAM,cAAc,SAAS,QAAQ,GAAG,IAAI;AAAA,MACpE,OAAO,UAAU,SAAS,QACtB,cAAc,SAAS,QAAQ,KAAK,IACpC;AAAA,MACJ,QAAQ,UAAU,SAAS,SACvB,cAAc,SAAS,QAAQ,MAAM,IACrC;AAAA,MACJ,MAAM,UAAU,SAAS,OAAO,cAAc,SAAS,QAAQ,IAAI,IAAI;AAAA,IACzE;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,MAAM;AAC3B,aAAS,UAAU,EAAE,MAAM,aAAa,SAAS,QAAQ,MAAM,KAAK,EAAE;AAAA,EACxE;AAGA,MAAI,UAAU,QAAQ;AACpB,UAAM,UAAUC,gBAAe,SAAS,QAAQ,KAAK;AACrD,QAAI,WAAW,OAAO,KAAK,OAAO,EAAE,SAAS,GAAG;AAC9C,eAAS,UAAU;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;;;AF5DA;AAaA,SAAS,qBACP,UACA,OACA,WACiB;AACjB,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,MAAW,CAAC;AAGlB,QAAM,YAAY,SAAS,oBAAoB;AAC/C,QAAM,YAAY,SAAS,kBAAkB;AAC7C,QAAM,OACJ,aAAa,cAAc,SACvB,uBAAuB,OAAO,SAAS,IACvC,kBAAkB,OAAO,SAAS;AACxC,QAAM,OACJ,aAAa,cAAc,SACvB,wBAAwB,OAAO,SAAS,IACxC,mBAAmB,OAAO,SAAS;AAEzC,QAAM,KAAK,SAAS;AACpB,MAAI,IAAI,UAAU;AAChB,QAAI,mBACF,GAAG,aAAa,WACZ,gBAAgB,SAChB,GAAG,aAAa,SACd,gBAAgB,OAChB,gBAAgB;AAAA,EAC1B;AACA,MAAI,IAAI,WAAW,QAAW;AAC5B,QAAI,6BAA6B,mBAAmB,GAAG,QAAQ,IAAI;AAAA,EACrE,WAAW,IAAI,OAAO;AACpB,UAAM,MAGF;AAAA,MACF,MAAM,2BAA2B;AAAA,MACjC,QAAQ,2BAA2B;AAAA,MACnC,OAAO,2BAA2B;AAAA,MAClC,QAAQ,2BAA2B;AAAA,MACnC,SAAS,2BAA2B;AAAA,IACtC;AACA,QAAI,6BAA6B,IAAI,GAAG,KAAK;AAAA,EAC/C;AAEA,QAAM,KAAK,SAAS;AACpB,MAAI,IAAI,UAAU;AAChB,QAAI,iBACF,GAAG,aAAa,WACZ,gBAAgB,SAChB,GAAG,aAAa,SACd,gBAAgB,OAChB,gBAAgB;AAAA,EAC1B;AACA,MAAI,IAAI,WAAW,QAAW;AAC5B,QAAI,2BAA2B,mBAAmB,GAAG,QAAQ,IAAI;AAAA,EACnE,WAAW,IAAI,OAAO;AACpB,UAAM,OAGF;AAAA,MACF,KAAK,yBAAyB;AAAA,MAC9B,QAAQ,yBAAyB;AAAA,MACjC,QAAQ,yBAAyB;AAAA,MACjC,QAAQ,yBAAyB;AAAA,MACjC,SAAS,yBAAyB;AAAA,IACpC;AACA,QAAI,2BAA2B,KAAK,GAAG,KAAK;AAAA,EAC9C;AAGA,QAAM,QAAQ,kBAAkB,OAAO,SAAS;AAChD,QAAM,QAAQ,mBAAmB,OAAO,SAAS;AACjD,QAAM,IAAI,SAAS,MAAM;AACzB,MAAI,GAAG;AACL,QAAI,EAAE,QAAQ,OAAW,KAAI,cAAc,mBAAmB,EAAE,KAAK,KAAK;AAC1E,QAAI,EAAE,UAAU;AACd,UAAI,gBAAgB,mBAAmB,EAAE,OAAO,KAAK;AACvD,QAAI,EAAE,WAAW;AACf,UAAI,iBAAiB,mBAAmB,EAAE,QAAQ,KAAK;AACzD,QAAI,EAAE,SAAS;AACb,UAAI,eAAe,mBAAmB,EAAE,MAAM,KAAK;AAAA,EACvD;AAEA,MAAI,UAAU,YAAY;AAE1B,SAAO;AACT;AAEA,eAAsB,uBACpB,WACA,OACA,WACA,UACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAC5C,QAAM,KAAK;AAEX,QAAM,WAAW,CAAC,GAAG,MAAM;AAC3B,QAAM,kBAAkB,GAAG,YAAY,CAAC;AAExC,MAAI,UAAU;AAEZ,UAAMC,gBAAsC,CAAC;AAE7C,UAAMC,gBAAiD;AAAA,MACrD,GAAG;AAAA,MACH,QAAQ;AAAA,IACV;AACA,eAAW,SAAS,iBAAiB;AACnC,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,QACA;AAAA,QACA;AAAA,QACAA;AAAA,MACF;AACA,MAAAD,cAAa,KAAK,GAAG,QAAQ;AAAA,IAC/B;AAEA,UAAME,YAAY,GAAG,MAAc;AACnC,UAAMC,YAAW,iBAAiBH,eAAcE,WAAU,KAAK;AAE/D,UAAME,OAAM,IAAIC,UAAS,EAAE,UAAU,CAAC,IAAIC,WAAUH,SAAQ,CAAC,EAAE,CAAC;AAChE,UAAMI,SAAQ,IAAIC,OAAM;AAAA,MACtB,QAAQC,iBAAgB;AAAA;AAAA,MACxB,MAAM,CAACL,IAAG;AAAA,MACV,OAAO,EAAE,MAAM,KAAK,MAAMM,WAAU,WAAW;AAAA,MAC/C,SAAS;AAAA,IACX,CAAC;AACD,WAAO,CAACH,MAAK;AAAA,EACf;AAKA,QAAM,eAAsC,CAAC;AAE7C,QAAM,eAAiD;AAAA,IACrD,GAAG;AAAA,IACH,QAAQ;AAAA,EACV;AACA,aAAW,SAAS,iBAAiB;AACnC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,iBAAa,KAAK,GAAG,QAAQ;AAAA,EAC/B;AAEA,QAAM,WAAY,GAAG,MAAc;AACnC,QAAM,WAAW,iBAAiB,cAAc,UAAU,KAAK;AAE/D,QAAM,MAAM,IAAIF,UAAS;AAAA,IACvB,UAAU,CAAC,IAAIC,WAAU,QAAQ,CAAC;AAAA,EACpC,CAAC;AAED,QAAM,QAAQ,qBAAqB,GAAG,MAAM,UAAU,OAAO,SAAS;AAGtE,QAAM,kBAAkB;AACxB,QAAM,sBAAsB;AAI5B,QAAM,WAAW,GAAG,MAAM,SAAU,GAAG,MAAM,UAAkB;AAC/D,MAAI;AACJ,MAAI;AAEJ,MAAI,aAAa,QAAW;AAE1B,gBAAY;AACZ,gBAAYI,WAAU;AAAA,EACxB,WAAW,OAAO,aAAa,YAAY,SAAS,SAAS,GAAG,GAAG;AAEjE,gBAAY,WAAW,QAAQ;AAC/B,gBAAYA,WAAU;AAAA,EACxB,OAAO;AAEL,gBACE,OAAO,aAAa,WAChB,WAAW,kBACX;AACN,gBAAYA,WAAU;AAAA,EACxB;AAEA,QAAM,QAAQ,IAAIF,OAAM;AAAA,IACtB,QAAQC,iBAAgB;AAAA;AAAA,IACxB,MAAM,CAAC,GAAG;AAAA,IACV,OAAO,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,IAC1C;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AACD,SAAO,CAAC,KAAK;AACf;;;AGpIA,eAAsB,qBACpB,WACA,OACA,WACkB;AAClB,MAAI,CAAC,iBAAiB,SAAS,EAAG,QAAO,CAAC;AAE1C,QAAM,YAAY,UAAU;AAC5B,QAAM,SAAkB,CAAC;AAGzB,MAAI,UAAU,WAAW,UAAU,MAAM;AAEvC,UAAM,UAAU,UAAU;AAC1B,UAAM,OAAO,UAAU;AAEvB,UAAM,sBAAoC;AAAA,MACxC,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,MACnB,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,WAAW;AAAA,MACb;AAAA,MACA,aAAa;AAAA,MACb,YAAY;AAAA,IACd;AAEA,UAAME,UAAsB;AAAA,MAC1B,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,OAAO;AAAA,MACP,SAAS,QAAQ,IAAI,CAAC,QAAQ,cAAc;AAAA,QAC1C,cAAc,EAAE,GAAG,oBAAoB;AAAA,QACvC,QAAQ;AAAA,UACN,GAAG;AAAA,UACH,SAAS;AAAA,QACX;AAAA,QACA,OAAO,KAAK,IAAI,CAAC,SAAS;AAAA,UACxB,GAAG;AAAA,UACH,SAAS,IAAI,QAAQ,KAAK;AAAA,QAC5B,EAAE;AAAA,MACJ,EAAE;AAAA,IACJ;AAEA,WAAO,KAAK,MAAM,YAAYA,QAAO,SAASA,SAAQ,OAAO,SAAS,CAAC;AAEvE,WAAO;AAAA,EACT;AAGA,QAAM,SAAS;AAEf,SAAO,KAAK,MAAM,YAAY,OAAO,SAAS,QAAQ,OAAO,SAAS,CAAC;AAEvE,SAAO;AACT;;;AChKA,SAAS,aAAAC,YAAkB,eAAe,mBAAmB;;;ACa7D,SAAS,qBAAAC,0BAAyB;AAclC,IAAM,sBAAsB;AAS5B,SAASC,eAAoC;AAC3C,SAAO,EAAE,YAAY,GAAG,UAAU,oBAAI,QAAQ,EAAE;AAClD;AAMA,IAAM,0BAAN,MAA8B;AAAA,EACpB,WAAiCA,aAAY;AAAA,EACpC,SAAS,IAAID,mBAAwC;AAAA,EAEtE,IAAY,QAA8B;AACxC,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK;AAAA,EACxC;AAAA;AAAA,EAGA,UAAa,UAAsB;AACjC,WAAO,KAAK,OAAO,IAAIC,aAAY,GAAG,QAAQ;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,iBAAiB,SAAkC;AACjD,WAAO,EAAE,IAAI,YAAY,OAAO,IAAI,QAAQ,QAAQ;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,WAAoC;AACtD,UAAM,QAAQ,KAAK;AACnB,UAAM,WAAW,MAAM,SAAS,IAAI,SAAS;AAC7C,QAAI,SAAU,QAAO;AAErB,UAAM,UAAU,MAAM;AACtB,UAAM,WAA4B;AAAA,MAChC,IAAI,kBAAkB,OAAO;AAAA,MAC7B,QAAQ,sBAAsB;AAAA,IAChC;AACA,UAAM,SAAS,IAAI,WAAW,QAAQ;AACtC,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,QAAc;AACZ,QAAI,CAAC,KAAK,OAAO,SAAS,GAAG;AAC3B,WAAK,WAAWA,aAAY;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,gCAAgC,IAAI,wBAAwB;;;ADjFzE,eAAsB,uBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAE5C,QAAM,WAAkC,CAAC;AAIzC,QAAM,EAAE,IAAI,mBAAmB,QAAQ,eAAe,IACpD,8BAA8B,oBAAoB,SAAS;AAI7D,WAAS;AAAA,IACP,IAAIC,WAAU;AAAA,MACZ,UAAU,CAAC,IAAI,cAAc,mBAAmB,cAAc,CAAC;AAAA,MAC/D,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,iBAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,QAAQ;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAGA,MAAI,UAAU,UAAU;AACtB,eAAW,SAAS,UAAU,UAAU;AACtC,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,aAAa;AAAA,IAChC;AAAA,EACF;AAIA,WAAS;AAAA,IACP,IAAIA,WAAU;AAAA,MACZ,UAAU,CAAC,IAAI,YAAY,cAAc,CAAC;AAAA,MAC1C,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;AE7EA;AAAA,EACE,aAAAC;AAAA,EACA,SAAAC;AAAA,EACA,YAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,mBAAAC;AAAA,OACK;AASP;AASA,eAAsB,uBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,mBAAmB,SAAS,EAAG,QAAO,CAAC;AAG5C,MAAI,QAAQ,UAAU,mBAAmB,QAAQ,MAAM,GAAG;AAExD,WAAO,MAAM,qBAAqB,WAAW,OAAO,WAAW,OAAO;AAAA,EACxE;AAIA,QAAM,WAAkC,CAAC;AAEzC,MAAI,UAAU,UAAU;AACtB,eAAW,SAAS,UAAU,UAAU;AACtC,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,aAAa;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAe,qBACb,WACA,OACA,WACA,SACkB;AAClB,QAAM,MAAO,UAAkB,SAAS,CAAC;AACzC,QAAM,UAAU,IAAI,WAAW,CAAC;AAGhC,MAAI,gBACF,CAAC;AACH,MAAI,OAAO,YAAY,UAAU;AAE/B,oBAAgB,MAAM,OAAO,EAAE,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,EACvD,WAAW,MAAM,QAAQ,OAAO,GAAG;AACjC,oBAAgB;AAAA,EAClB,OAAO;AAEL,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,cAAc,cAAc;AAClC,MAAI,gBAAgB,EAAG,QAAO,CAAC;AAG/B,QAAM,sBAAsB,uBAAuB,OAAO,SAAS;AACnE,QAAM,eAAyB,CAAC;AAChC,QAAM,aAAuB,CAAC;AAC9B,MAAI,oBAAoB;AACxB,MAAI,YAAY;AAChB,QAAM,mBAA6B,CAAC;AAEpC,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,UAAM,MAAM,cAAc,CAAC;AAG3B,QAAI,IAAI,UAAU,UAAa,IAAI,UAAU,QAAQ;AACnD,uBAAiB,KAAK,CAAC;AACvB,mBAAa,KAAK,CAAC;AAAA,IACrB,OAAO;AACL,YAAM,aAAa,sBAAsB,IAAI,OAAO,mBAAmB;AACvE,mBAAa,KAAK,UAAU;AAC5B,2BAAqB;AAAA,IACvB;AAGA,QAAI,IAAI,cAAc,GAAG;AACvB,YAAM,WACJ,IAAI,QAAQ,SACR,sBAAsB,IAAI,KAAK,mBAAmB,IAClD,IAAI,QAAQ,SACV,sBAAsB,IAAI,KAAK,mBAAmB,IAClD;AACR,iBAAW,KAAK,QAAQ;AACxB,mBAAa;AAAA,IACf,OAAO;AACL,iBAAW,KAAK,CAAC;AAAA,IACnB;AAAA,EACF;AAGA,QAAM,iBAAiB,KAAK;AAAA,IAC1B;AAAA,IACA,sBAAsB,oBAAoB;AAAA,EAC5C;AACA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAM,kBAAkB,KAAK;AAAA,MAC3B,iBAAiB,iBAAiB;AAAA,IACpC;AACA,eAAW,OAAO,kBAAkB;AAClC,mBAAa,GAAG,IAAI;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,kBAAmB,UAAkB,YAAY,CAAC;AACxD,QAAM,iBAA0C,MAAM,WAAW,EAC9D,KAAK,IAAI,EACT,IAAI,MAAM,CAAC,CAAC;AAGf,WAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,UAAM,WAAW,IAAI;AACrB,mBAAe,QAAQ,EAAE,KAAK,gBAAgB,CAAC,CAAC;AAAA,EAClD;AAGA,QAAM,QAAqB,CAAC;AAC5B,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,UAAM,iBAAwC,CAAC;AAE/C,eAAW,SAAS,eAAe,CAAC,GAAG;AACrC,YAAM,WAAW,MAAM,gBAAgB,OAAO,OAAO,WAAW,OAAO;AACvE,qBAAe,KAAK,GAAG,QAAQ;AAAA,IACjC;AAGA,QAAI,eAAe,WAAW,GAAG;AAC/B,qBAAe,KAAK,IAAIC,WAAU,CAAC,CAAC,CAAC;AAAA,IACvC;AAEA,UAAM;AAAA,MACJ,IAAIC,WAAU;AAAA,QACZ,UAAU;AAAA,QACV,OAAO,EAAE,MAAM,aAAa,CAAC,GAAG,MAAMC,WAAU,IAAI;AAAA,QACpD,SAAS;AAAA,UACP,KAAK;AAAA,UACL,OAAO,WAAW,CAAC,IAAI;AAAA,UACvB,QAAQ;AAAA,UACR,MAAM,IAAI,IAAI,WAAW,IAAI,CAAC,IAAI,IAAI;AAAA,QACxC;AAAA,QACA,eAAeC,eAAc;AAAA,QAC7B,SAAS;AAAA,UACP,KAAK,EAAE,OAAOC,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UACzD,OAAO,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UAC3D,QAAQ,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,UAC5D,MAAM,EAAE,OAAOA,aAAY,MAAM,MAAM,GAAG,OAAO,SAAS;AAAA,QAC5D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,MAAM,IAAIC,UAAS,EAAE,UAAU,MAAM,CAAC;AAC5C,QAAM,QAAQ,IAAIC,OAAM;AAAA,IACtB,MAAM,CAAC,GAAG;AAAA,IACV,OAAO,EAAE,MAAM,KAAK,MAAMJ,WAAU,WAAW;AAAA,IAC/C,QAAQK,iBAAgB;AAAA;AAAA,IACxB,SAAS;AAAA,EACX,CAAC;AAED,SAAO,CAAC,KAAK;AACf;;;AC3LO,SAAS,yBACd,WACA,QACa;AACb,MAAI,CAAC,qBAAqB,SAAS,EAAG,QAAO,CAAC;AAG9C,QAAM,iBAAiB,UAAU;AAEjC,SAAO;AAAA,IACL;AAAA,MACE,QAAQ,eAAe;AAAA,MACvB,aAAa,eAAe;AAAA,MAC5B,WAAW,eAAe;AAAA,IAC5B;AAAA,IACA;AAAA,MACE,SAAS,eAAe;AAAA,IAG1B;AAAA,EACF;AACF;;;AC7BA;AAAA,EACE,aAAAC;AAAA,EACA;AAAA,EACA,iBAAAC;AAAA,EACA,WAAAC;AAAA,EACA;AAAA,OACK;AA8BP,SAAS,mBAAmB,SAAyB;AACnD,SAAO,QACJ,QAAQ,YAAY,KAAK,EACzB,QAAQ,UAAU,GAAG,EACrB,QAAQ,QAAQ,GAAG,EACnB,KAAK;AACV;AAeA,SAAS,oBACP,WACA,SAMY;AACZ,MAAI,CAAC,aAAa,UAAU,WAAW,EAAG,QAAO,CAAC;AAElD,QAAM,EAAE,YAAY,UAAU,mBAAmB,YAAY,IAAI;AACjE,QAAM,UAAsB,CAAC;AAE7B,aAAW,SAAS,WAAW;AAC7B,QAAI,qBAAqB,MAAM,sBAAsB,mBAAmB;AACtE;AAAA,IACF;AAEA,QAAI,MAAM,YAAY,QAAW;AAG/B,YAAM,QACJ,YAAY,IAAI,MAAM,OAAO,KAC7B,YAAY,IAAI,mBAAmB,MAAM,OAAO,CAAC;AACnD,UAAI,UAAU,OAAW;AACzB,cAAQ,KAAK,EAAE,OAAO,MAAM,OAAO,MAAM,CAAC;AAC1C;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,cAAc,MAAM,QAAQ,SAAU;AAGxD,YAAQ,KAAK,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM,CAAC;AAAA,EACzD;AAEA,SAAO;AACT;AAUA,SAAS,gBACP,UACA,WACA,cAAc,GACd,YAAY,GACkB;AAC9B,MAAI,OAAO,aAAa,YAAY,aAAa,MAAM;AACrD,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,8EAA8E,KAAK,UAAU,QAAQ,CAAC;AAAA,IACpH;AAAA,EACF;AAGA,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,KAAK,SAAS,MAAM;AAG1B,MAAI,OAAO,KAAK,OAAO,KAAK,KAAK,KAAK,KAAK,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,yDAAyD,IAAI,QAAQ,EAAE;AAAA,IACrF;AAAA,EACF;AACA,MAAI,OAAO,IAAI;AACb,UAAM,IAAI;AAAA,MACR,GAAG,SAAS,8DAA8D,IAAI,QAAQ,EAAE;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,GAAG;AACpB;AAiBO,SAAS,mBACd,WACA,OACA,SACiC;AACjC,QAAM,iBAAiB,UAAU;AAGjC,QAAM,WAAW,eAAe,SAAS,EAAE,IAAI,EAAE;AACjD,QAAM,aAAa,gBAAgB,UAAU,aAAa,GAAG,CAAC;AAC9D,QAAM,aAAa,WAAW;AAC9B,QAAM,WAAW,WAAW;AAG5B,MAAI;AACJ,MAAI;AAEJ,MAAI,eAAe,qBAAqB,QAAW;AACjD,UAAM,mBAAmB;AAAA,MACvB,eAAe;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,uBAAmB,iBAAiB;AACpC,qBAAiB,iBAAiB;AAAA,EACpC;AAOA,MAAI,eAAe,mBAAmB,QAAW;AAC/C,YAAQ;AAAA,MACN,uBAAuB,eAAe,cAAc;AAAA,IAGtD;AAAA,EACF;AAEA,QAAM,qBAAqB,eAAe,uBAAuB;AACjE,QAAM,QAAQ,eAAe,SAAS;AAGtC,QAAM,iBACJ,UAAU,SACN,SAAS,SAAS,oBAChB,YACA,aACF;AAGN,QAAM,oBACJ,mBAAmB,YACf,SAAS,SAAS,oBAClB;AAGN,MAAI,mBAAmB,aAAa,CAAC,mBAAmB;AAEtD,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAA8C,CAAC;AAGrD,MAAI,eAAe,OAAO;AACxB,eAAW;AAAA,MACT,IAAIF,WAAU;AAAA,QACZ,UAAU;AAAA,UACR,IAAIE,SAAQ;AAAA,YACV,MAAM,eAAe;AAAA,YACrB,MAAM;AAAA,YACN,MAAM;AAAA;AAAA,UACR,CAAC;AAAA,QACH;AAAA,QACA,SAAS;AAAA,UACP,QAAQ,MAAM,mBAAmB,SAAS,SAAS,UAAU;AAAA;AAAA;AAAA,UAG7D,OAAO;AAAA,QACT;AAAA,QACA,WAAWD,eAAc;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,mBAAiC,CAAC;AAmBxC,QAAM,cAAc,oBAAI,IAAoB;AAE5C,MAAI,eAAe,UAAU,eAAe,OAAO,SAAS,GAAG;AAC7D,eAAW,gBAAgB,eAAe,QAAQ;AAMhD,YAAM,UAAU,aAAa;AAC7B,YAAM,gBACJ,CAAC,CAAC,MAAM,UACR,OAAO,UAAU,eAAe,KAAK,MAAM,QAAQ,OAAO;AAC5D,YAAM,mBAAmB,gBACrB,mBAAmB,OAAO,IAC1B;AAEJ,kBAAY,IAAI,SAAS,aAAa,KAAK;AAC3C,kBAAY,IAAI,kBAAkB,aAAa,KAAK;AAEpD,uBAAiB;AAAA,QACf,IAAI,WAAW,kBAAkB,aAAa,KAAK;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAaA,QAAM,sBAAsB;AAC5B,QAAM,oBAAoB;AAK1B,QAAM,gBAAgB,oBAAoB,SAAS,aAAa;AAAA,IAC9D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,aAAsC;AAAA,IAC1C,WAAW;AAAA;AAAA,IACX,mBAAmB,GAAG,mBAAmB,IAAI,iBAAiB;AAAA;AAAA,IAC9D;AAAA;AAAA;AAAA,IAEA,qBAAqB;AAAA;AAAA;AAAA;AAAA,IAIrB,IAAI,MAAM;AACR,UAAI,qBAAqB,UAAa,mBAAmB,QAAW;AAIlE,cAAM,eAAyB,CAAC;AAGhC,YAAI,mBAAmB,qBAAqB;AAC1C,uBAAa,KAAK,GAAG,mBAAmB,IAAI,mBAAmB,CAAC,EAAE;AAAA,QACpE;AAGA,YAAI,iBAAiB,mBAAmB;AACtC,uBAAa,KAAK,GAAG,iBAAiB,CAAC,IAAI,iBAAiB,EAAE;AAAA,QAChE;AAGA,eAAO,aAAa,SAAS,IACzB,EAAE,6BAA6B,aAAa,KAAK,GAAG,EAAE,IACtD,CAAC;AAAA,MACP,WAAW,CAAC,oBAAoB;AAE9B,eAAO;AAAA,UACL,6BAA6B,GAAG,mBAAmB,IAAI,iBAAiB;AAAA,QAC1E;AAAA,MACF,OAAO;AAEL,eAAO,CAAC;AAAA,MACV;AAAA,IACF,GAAG;AAAA;AAAA;AAAA,IAGH,GAAI,eAAe,oBAAoB,SACnC;AAAA,MACE,6BAA6B,eAAe,kBACxC,MACA;AAAA,IACN,IACA,EAAE,6BAA6B,IAAK;AAAA;AAAA,EAC1C;AAKA,aAAW;AAAA,IACT,IAAI,gBAAgB,eAAe,SAAS,qBAAqB;AAAA,MAC/D,GAAG;AAAA,MACH,GAAI,cAAc,SAAS,KAAK,EAAE,cAAc;AAAA,IAClD,CAAC;AAAA,EACH;AAWA,SAAO;AACT;;;ACvXA;;;ACLO,SAAS,oBAA6B;AAE3C,SACE,OAAO,YAAY,eACnB,QAAQ,YAAY,QACpB,QAAQ,SAAS,QAAQ,QACzB,OAAO,QAAQ,SAAS,SAAS;AAErC;AAMO,SAAS,kBAA2B;AACzC,MAAI;AAGF,WACE,OAAO,cAAY,eAClB,OAAO,YAAY,eAClB,OAAO,QAAQ,aAAa,YAC5B,OAAO,QAAQ,SAAS,SAAS;AAAA,EAEvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACnBA,IAAM,qBAAqB;AAOpB,SAAS,kBACd,UACA,aACA,YACQ;AACR,QAAM,OAAO,YAAY,eAAe,YAAY,KAAK;AACzD,QAAM,aAAa,gBAAgB,KAAK,GAAG,IAAI,MAAM,UAAU,GAAG;AAClE,SAAO,WAAW,QAAQ,QAAQ,EAAE;AACtC;AAuBA,eAAsB,kBACpB,MACmB;AACnB,QAAM,kBACJ,OAAO,KAAK,YAAY,aACpB,MAAM,KAAK,QAAQ,KAAK,IAAI,IAC5B,KAAK;AACX,QAAM,UAAkC;AAAA,IACtC,gBAAgB;AAAA,IAChB,GAAG;AAAA,EACL;AAEA,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAE5D,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,MAAM,GAAG,KAAK,GAAG,GAAG,KAAK,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,KAAK,IAAI;AAAA,MAC9B,QAAQ,WAAW;AAAA,IACrB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAK,OAAiB,SAAS,cAAc;AAC3C,YAAM,IAAI;AAAA,QACR,GAAG,KAAK,YAAY,oBAAoB,SAAS,SAAS,KAAK,GAAG;AAAA,MACpE;AAAA,IACF;AACA,UAAM,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACnE,UAAM,IAAI,MAAM,KAAK,cAAc,KAAK,KAAK,KAAK,CAAC;AAAA,EACrD,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR,GAAG,KAAK,YAAY,aAAa,SAAS,MAAM,KAAK,SAAS,UAAU;AAAA,IAC1E;AAAA,EACF;AACA,SAAO;AACT;;;AF5EA,SAAS,kCAAkC;AAc3C,IAAM,4BAA4B;AAKlC,eAAe,cACb,QACA,gBACgC;AAEhC,MAAI,CAAC,kBAAkB,GAAG;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB;AAAA,EACF;AAEA,QAAM,cAAuC;AAAA,IAC3C,QAAQ,OAAO;AAAA,IACf,MAAM;AAAA,IACN,KAAK;AAAA,IACL,OAAO,OAAO;AAAA;AAAA;AAAA,IAGd,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,EAC5D;AAEA,QAAM,WAAW,MAAM,kBAAkB;AAAA,IACvC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,gBAAgB;AAAA,IACzB,cAAc;AAAA,IACd,eAAe,CAAC,KAAK,UACnB,8CAA8C,GAAG;AAAA,SAEvC,KAAK;AAAA,EACnB,CAAC;AAED,QAAM,aAAa,MAAM,SAAS,KAAK;AACvC,QAAM,gBAAgB,yBAAyB,UAAU;AACzD,QAAM,QAAQ,OAAO,QAAQ,MAAM;AACnC,QAAM,SAAS,OAAO,QAAQ,MAAM;AAEpC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASA,SAAS,aAAa,OAAe,OAAwC;AAG3E,MAAI,qBAAqB,KAAK,KAAK,GAAG;AACpC,WAAO,MAAM,WAAW,GAAG,IAAI,QAAQ,IAAI,KAAK;AAAA,EAClD;AACA,MAAI;AACF,WAAO,IAAI,aAAa,OAAO,KAAK,CAAC;AAAA,EACvC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,SAAS,gBACP,QACA,OACiB;AACjB,QAAM,UAAU,OAAO;AACvB,MAAI,CAAC,WAAW,QAAQ,UAAU,CAAC,OAAO,OAAQ,QAAO;AACzD,QAAM,cAAc,MAAM;AAC1B,QAAM,UAAU,2BAA2B,IAAI,CAAC,UAAU;AACxD,UAAM,QAAQ,YAAY,KAAK;AAC/B,WAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAC/C,aAAa,OAAO,KAAK,IACzB;AAAA,EACN,CAAC,EAAE,OAAO,CAAC,MAAmB,MAAM,MAAS;AAC7C,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,EAAE,GAAG,OAAO,SAAS,QAAQ,QAAQ;AAAA,EAChD;AACF;AAKA,eAAsB,0BACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,sBAAsB,SAAS,EAAG,QAAO,CAAC;AAE/C,QAAM,SAAS,gBAAgB,UAAU,OAA0B,KAAK;AAGxE,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,SAAS,UAAU;AAAA,EACrB;AAIA,QAAM,sBACJ,OAAO,UAAU,UAAa,OAAO,WAAW;AAClD,QAAM,cAAc,sBAAsB,OAAO,QAAQ,YAAY;AACrE,QAAM,eAAe,sBAAsB,OAAO,SAAS,YAAY;AAGvE,QAAM,kBAAkB,MAAM;AAAA,IAC5B,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,MACE,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;;;AG1KA,SAAS,cAAAE,mBAAkB;AAc3B;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAEA,IAAM,+BAA+B;AAE5C,IAAM,kBAAkB;AAOjB,SAAS,wBACd,OACyB;AACzB,QAAM,EAAE,QAAQ,SAAS,IAAI;AAE7B,QAAM,oBAA6C;AAAA,IACjD,YAAY,OAAO;AAAA,IACnB,aAAa,OAAO;AAAA,EACtB;AACA,MAAI,OAAO,MAAO,mBAAkB,QAAQ,OAAO;AAEnD,QAAM,aAAsC,CAAC;AAC7C,MAAI,OAAO,WAAY,YAAW,aAAa,OAAO;AAEtD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,OAAO;AAAA,QACP,UAAU,YAAY,CAAC;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AACF;AAMO,SAAS,qBAAqB,OAA4B;AAC/D,SAAO,KAAK,MAAM,MAAM,OAAO,QAAQ,eAAe;AACxD;AAQO,SAAS,qBAAqB,OAAkC;AACrE,SAAO;AAAA,IACL,OAAO,MAAM,SAAS,qBAAqB,KAAK;AAAA,IAChD,GAAI,MAAM,WAAW,UAAa,EAAE,QAAQ,MAAM,OAAO;AAAA,IACzD,WAAW,MAAM,aAAa;AAAA,IAC9B,GAAI,MAAM,YAAY,UAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,IAC5D,GAAI,MAAM,YAAY,UAAa,EAAE,SAAS,MAAM,QAAQ;AAAA,IAC5D,GAAI,MAAM,aAAa,UAAa,EAAE,UAAU,MAAM,SAAS;AAAA,IAC/D,GAAI,MAAM,aAAa,UAAa,EAAE,UAAU,MAAM,SAAS;AAAA,IAC/D,GAAI,MAAM,cAAc,UAAa,EAAE,WAAW,MAAM,UAAU;AAAA,EACpE;AACF;AAMO,SAAS,mBACd,OACA,eACyB;AACzB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,GAAG,qBAAqB,KAAK;AAAA,IAC7B,GAAI,MAAM,QAAQ,UAAa,EAAE,KAAK,MAAM,IAAI;AAAA,EAClD;AACF;AAeO,SAAS,gBACd,cACA,KACA,WACQ;AACR,SAAOC,YAAW,QAAQ,EACvB,OAAO,KAAK,UAAU,EAAE,GAAG,cAAc,GAAG,KAAK,GAAG,aAAa,KAAK,CAAC,CAAC,EACxE,OAAO,KAAK;AACjB;AAYO,SAAS,yBACd,OACA,eACoB;AACpB,MAAI,eAAe,OAAQ,QAAO;AAClC,SAAO,MAAM;AACf;AAQA,eAAsB,qBACpB,cACA,KACA,gBACA,eACA,SAMA,OAC8B;AAC9B,MAAI,CAAC,kBAAkB,GAAG;AACxB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAGA,MAAI,eAAe,QAAQ;AACzB,WAAO,cAAc,OAAO;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,OAAO,SAAS,EAAE,OAAO,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,kBAAkB;AAAA,IACvC,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,GAAI,YAAY,UAAa,EAAE,QAAQ;AAAA,MACvC,GAAI,OAAO,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,IACnC;AAAA,IACA,SAAS,eAAe;AAAA,IACxB,cAAc;AAAA,IACd,eAAe,CAAC,KAAK,UACnB,kDAAkD,GAAG;AAAA,SAE3C,KAAK;AAAA,EACnB,CAAC;AAED,MAAI;AACJ,MAAI;AACF,aAAU,MAAM,SAAS,KAAK;AAAA,EAChC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,eAAe;AAC1B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,eAAsB,sBACpB,WACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,kBAAkB,SAAS,EAAG,QAAO,CAAC;AAE3C,QAAM,QAAQ,UAAU;AACxB,QAAM,gBAAgB,SAAS,UAAU;AAEzC,QAAM,eAAe,wBAAwB,KAAK;AAClD,QAAM,MAAM;AAAA,IACV,MAAM,OAAO,eAAe,OAAO;AAAA,EACrC;AAOA,QAAM,gBAAgB,SAAS,qBAAqB;AAAA,IAClD;AAAA,MACE;AAAA,MACA;AAAA,MACA,yBAAyB,OAAO,aAAa;AAAA,IAC/C;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,eAAe;AACjB,QAAI,CAAC,cAAc,GAAI,OAAM,IAAI,MAAM,cAAc,KAAK;AAC1D,aAAS;AAAA,EACX,OAAO;AAIL,aAAS,MAAM;AAAA,MACb;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,SAAS;AAAA,IACX;AAAA,EACF;AAKA,SAAO,MAAM;AAAA,IACX,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,qBAAqB,KAAK;AAAA,EAC5B;AACF;;;ACpRA,SAAS,YAAoB;;;ACN7B;AAAA,EACE,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,OACd;AAsCA,SAAS,cAId,SACsD;AACtD,SAAO,oBAAoB,OAAO;AACpC;AAEO,SAAS,gBAMd,WACyD;AACzD,SAAO,sBAAsB,SAAS;AACxC;;;AD9CA,IAAM,4BAA4B,KAAK,OAAO;AAAA,EAC5C,MAAM,KAAK,OAAO;AAAA,IAChB,aAAa;AAAA,EACf,CAAC;AAAA;AAAA,EAED,SAAS,KAAK;AAAA,IACZ,KAAK,OAAO;AAAA,MACV,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,MACnC,OAAO,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,IACpC,CAAC;AAAA,EACH;AACF,CAAC;AAOM,IAAM,0BAA0B,gBAAgB;AAAA,EACrD,MAAM;AAAA,EACN,UAAU;AAAA,IACR,SAAS,cAAc;AAAA,MACrB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,QAAQ,OAAO,EAAE,MAAM,MAAM;AAE3B,cAAM,SAA8B;AAAA,UAClC,MAAM;AAAA,UACN,OAAO;AAAA,YACL,MAAM,MAAM;AAAA,YACZ,SAAS;AAAA,cACP,GAAG,MAAM;AAAA,cACT,OAAO,MAAM,SAAS,SAAS;AAAA,YACjC;AAAA,UACF;AAAA,QACF;AAEA,eAAO,CAAC,MAAM;AAAA,MAChB;AAAA,IACF,CAAC;AAAA,EACH;AACF,CAAC;;;ApC2BD;;;AsClEA;AAAA,EACE,kBAAAC;AAAA,EACA,sBAAAC;AAAA,EACA;AAAA,OAKK;;;ACrBA,SAAS,cACd,KACyC;AACzC,MAAI,SAAS;AACb,QAAM,QAA2B,CAAC;AAClC,QAAM,UAAU,MAAM;AACpB;AACA,UAAM,MAAM,IAAI;AAAA,EAClB;AACA,SAAO,eAAe,MAAS,IAAkC;AAG/D,WAAO,UAAU;AACf,YAAM,IAAI,QAAc,CAACC,aAAY,MAAM,KAAKA,QAAO,CAAC;AAC1D;AACA,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,UAAE;AACA,cAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ADcA,IAAM,+BAA+B;AAErC,IAAM,wBAAwB;AAC9B,IAAM,6BAA6B;AA0BnC,IAAM,eAAmC;AAAA,EACvC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AACV;AAOO,SAAS,wBAA4C;AAC1D,SAAO,EAAE,GAAG,aAAa;AAC3B;AAEO,SAAS,0BAAgC;AAC9C,eAAa,YAAY;AACzB,eAAa,YAAY;AACzB,eAAa,SAAS;AACxB;AA4BO,SAAS,mBAAmB,MAA8B;AAC/D,QAAM,QAAuB,CAAC;AAI9B,QAAM,OAAO,oBAAI,QAAgB;AACjC,QAAM,QAAQ,CAAC,SAAwB;AACrC,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,QAAI,KAAK,IAAI,IAAI,EAAG;AACpB,SAAK,IAAI,IAAI;AACb,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,iBAAW,QAAQ,KAAM,OAAM,IAAI;AACnC;AAAA,IACF;AACA,UAAM,MAAM;AAGZ,QAAI,OAAO,IAAI,SAAS,YAAY,IAAI,YAAY,MAAO;AAC3D,QAAI,IAAI,SAAS,YAAY,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AACvE,YAAM,KAAK,IAAI,KAAoB;AAGnC;AAAA,IACF;AACA,eAAW,SAAS,OAAO,OAAO,GAAG,EAAG,OAAM,KAAK;AAAA,EACrD;AACA,QAAM,IAAI;AACV,SAAO;AACT;AAEA,SAAS,eAAe,OAAwB;AAC9C,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AASA,IAAM,yBAAyB;AAW/B,SAAS,kBAAkB,OAAyB;AAClD,QAAM,QAAQ,uBAAuB,KAAK,eAAe,KAAK,CAAC;AAC/D,SAAO,UAAU,QAAQ,MAAM,CAAC,MAAM;AACxC;AAEA,UAAU,SAAY,OAAY,MAA8B;AAC9D,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,KAAM,OAAM,MAAM,MAAM,GAAG,IAAI,IAAI;AAC5E;AAQA,SAAS,mBACP,OACA,UACA,KACS;AACT,QAAM,UAAW,UAAmD;AACpE,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,MAAM,OAAQ,QAAO;AAEvE,QAAM,UAA0D,CAAC;AACjE,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,QAAQ,CAAC;AACtB,QACE,QACA,KAAK,OAAO,QACZ,OAAO,KAAK,kBAAkB,YAC9B,KAAK,cAAc,SAAS,KAC5B,OAAO,KAAK,UAAU,YACtB,OAAO,KAAK,WAAW,UACvB;AACA,cAAQ,KAAK;AAAA,QACX,MAAM,CAAC,EAAE;AAAA,QACT;AAAA,UACE,IAAI;AAAA,UACJ,eAAe,KAAK;AAAA,UACpB,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH,WAAW,QAAQ,KAAK,OAAO,SAAS,OAAO,KAAK,UAAU,UAAU;AACtE,cAAQ,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,OAAO,KAAK,MAAM,CAAC,CAAC;AAAA,IAC/D,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AACA,aAAW,CAAC,KAAK,KAAK,KAAK,QAAS,KAAI,IAAI,KAAK,KAAK;AACtD,SAAO;AACT;AAQA,eAAsB,oBACpB,MACA,eACA,UAA+B,CAAC,GACqB;AACrD,QAAM,MAAM,oBAAI,IAA2C;AAI3D,MACE,CAAC,kBAAkB,KACnB,CAAC,eAAe,eAChB,CAAC,eAAe,QAChB;AACA,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,mBAAmB,IAAI;AACvC,MAAI,QAAQ,WAAW,EAAG,QAAO;AAGjC,QAAM,UAAU,oBAAI,IAAgC;AACpD,aAAW,SAAS,SAAS;AAK3B,QAAI;AACF,YAAMC,aAAY,yBAAyB,OAAO,aAAa;AAG/D,UAAIA,eAAc,OAAW;AAC7B,YAAM,eAAe,wBAAwB,KAAK;AAClD,YAAM,MAAMC;AAAA,QACV,MAAM,OAAO,eAAe,OAAOC;AAAA,MACrC;AACA,YAAM,MAAM,gBAAgB,cAAc,KAAKF,UAAS;AACxD,UAAI,CAAC,QAAQ,IAAI,GAAG,EAAG,SAAQ,IAAI,KAAK,EAAE,KAAK,cAAc,IAAI,CAAC;AAAA,IACpE,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,eAAa;AACb,eAAa,aAAa,QAAQ;AAClC,eAAa,UAAU,QAAQ;AAE/B,QAAM,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC;AACnC,QAAM,QAAQ;AAAA,IACZ,KAAK,IAAI,GAAG,QAAQ,eAAe,4BAA4B;AAAA,EACjE;AASA,MAAI,gBAAgB;AACpB,QAAM,eAAe,MACnB,iBAAiB,CAAC,QAAQ,OAAO,SAAS,SAAY,QAAQ;AAShE,QAAM,eAAe,OACnB,WAC2C;AAC3C,UAAM,QAAQ,aAAa;AAC3B,UAAM,OAAO,CACX,cAEA;AAAA,MACE,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACF,QAAI;AACF,aAAO,EAAE,IAAI,MAAM,GAAI,MAAM,KAAK,KAAK,EAAG;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,CAAC,SAAS,CAAC,kBAAkB,KAAK,GAAG;AACvC,eAAO,EAAE,IAAI,OAAO,OAAO,eAAe,KAAK,EAAE;AAAA,MACnD;AACA,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,MAAS;AAEnC,wBAAgB;AAChB,eAAO,EAAE,IAAI,MAAM,GAAG,OAAO;AAAA,MAC/B,QAAQ;AAGN,eAAO,EAAE,IAAI,OAAO,OAAO,eAAe,KAAK,EAAE;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,wBAAwB,OAC5B,UACkB;AAClB,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,QAAI,CAAC,WACT,MAAM,YAAY;AAChB,cAAI,IAAI,OAAO,KAAK,MAAM,aAAa,MAAM,CAAC;AAAA,QAChD,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,MAAI,eAAe,aAAa;AAC9B,eAAW,SAAS,SAAS,QAAQ,0BAA0B,GAAG;AAChE,UAAI;AACF,cAAM,WAAW,MAAM,cAAc,YAAY;AAAA,UAC/C,QAAQ,MAAM,IAAI,CAAC,YAAY;AAAA,YAC7B,cAAc,OAAO;AAAA,YACrB,KAAK,OAAO;AAAA,UACd,EAAE;AAAA,UACF,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,UAChE,GAAI,QAAQ,OAAO,SAAS,EAAE,OAAO,CAAC,GAAG,QAAQ,KAAK,EAAE,IAAI,CAAC;AAAA,QAC/D,CAAC;AACD,YAAI,CAAC,mBAAmB,OAAO,UAAU,GAAG,GAAG;AAC7C,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AAOd,YAAI,cAAc,UAAU,cAAc,WAAW;AACnD,gBAAM,sBAAsB,KAAK;AAAA,QACnC,OAAO;AACL,gBAAM,UAAU,eAAe,KAAK;AACpC,qBAAW,UAAU,OAAO;AAC1B,gBAAI,IAAI,OAAO,KAAK,EAAE,IAAI,OAAO,OAAO,QAAQ,CAAC;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAIA,MAAI,eAAe,QAAQ;AACzB,UAAM,sBAAsB,MAAM;AAClC,WAAO;AAAA,EACT;AAKA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,eAAe;AAAA,IACf;AAAA,EACF;AACA,QAAM,YAAY,OAChB,OACA,UAC0B;AAC1B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,kBAAkB;AAAA,QACjC,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,QAAQ,MAAM,IAAI,CAAC,YAAY;AAAA,YAC7B,cAAc,OAAO;AAAA,YACrB,KAAK,OAAO;AAAA,UACd,EAAE;AAAA,UACF,GAAI,QAAQ,YAAY,UAAa,EAAE,SAAS,QAAQ,QAAQ;AAAA,UAChE,GAAI,OAAO,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,QACnC;AAAA,QACA,SAAS,eAAe;AAAA,QACxB,WACE,wBAAwB,6BAA6B,MAAM;AAAA,QAC7D,cAAc;AAAA,QACd,eAAe,CAAC,KAAK,UACnB,kDAAkD,GAAG,YAAY,KAAK;AAAA,MAC1E,CAAC;AAAA,IACH,SAAS,OAAO;AAGd,aAAO,EAAE,SAAS,OAAO,gBAAgB,kBAAkB,KAAK,EAAE;AAAA,IACpE;AACA,QAAI;AACF,UAAI,mBAAmB,OAAO,MAAM,SAAS,KAAK,GAAG,GAAG,GAAG;AACzD,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,IACF,QAAQ;AAAA,IAER;AACA,WAAO,EAAE,SAAS,OAAO,gBAAgB,MAAM;AAAA,EACjD;AAEA,aAAW,SAAS,SAAS,QAAQ,0BAA0B,GAAG;AAChE,UAAM,QAAQ,aAAa;AAC3B,QAAI,UAAU,MAAM,UAAU,OAAO,KAAK;AAC1C,QAAI,CAAC,QAAQ,WAAW,SAAS,QAAQ,gBAAgB;AAQvD,YAAM,QAAQ,MAAM,UAAU,OAAO,MAAS;AAC9C,UAAI,MAAM,SAAS;AACjB,wBAAgB;AAChB,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,QAAS,OAAM,sBAAsB,KAAK;AAAA,EACzD;AACA,SAAO;AACT;;;AEvaO,SAAS,uBACd,UACkB;AAClB,MAAI,UAAU;AAEd,SAAO,SAAS,IAAI,CAAC,SAAS,UAAU;AACtC,QAAI,CAAC,QAAQ,sBAAsB;AACjC,UAAI,QAAQ,cAAe;AAC3B,aAAO,EAAE,eAAe,MAAM;AAAA,IAChC;AAGA,UAAM,UAAU,QAAQ,gBAAgB,UAAU,IAAI;AACtD,QAAI,QAAQ,cAAe;AAI3B,UAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,UAAM,gBACJ,CAAC,QAAQ,CAAC,KAAK,wBAAwB,KAAK;AAE9C,WAAO,EAAE,SAAS,cAAc;AAAA,EAClC,CAAC;AACH;;;ACpBA,SAAS,4BAA4B;AAyB9B,SAAS,oBAAoB,MAAsB;AACxD,SAAO,qBAAqB,IAAI,EAC7B,QAAQ,6BAA6B,IAAI,EACzC,QAAQ,0BAA0B,IAAI,EACtC,QAAQ,uBAAuB,IAAI,EACnC,KAAK;AACV;AAGA,SAAS,YAAY,MAAuB;AAC1C,SAAO,qBAAqB,IAAI,GAAG,gBAAgB;AACrD;AAEA,SAAS,UAAU,WAAyC;AAC1D,SAAO,EAAE,aAAa,aAAa,UAAU,YAAY;AAC3D;AAQA,SAAS,cAAc,OAAoD;AACzE,QAAM,aAAa,MAAM;AACzB,MAAI,OAAO,eAAe,YAAY,CAAC,WAAY,QAAO;AAC1D,MAAI,kBAAkB,KAAK,UAAU,EAAG,QAAO;AAC/C,MAAI,CAAC,UAAU,SAAS,UAAU,EAAE,SAAS,WAAW,YAAY,CAAC,GAAG;AACtE,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,mBACd,UACmB;AACnB,QAAM,UAA6B,CAAC;AACpC,QAAM,WAAW,uBAAuB,QAAQ;AAEhD,WAAS,QAAQ,CAAC,SAAS,UAAU;AAMnC,UAAM,UAAU,SAAS,KAAK,GAAG;AACjC,UAAM,oBAAoB,UACtB,8BAA8B,iBAAiB,OAAO,EAAE,KACxD;AAEJ,UAAM,QAAQ,CAAC,cAAyC;AACtD,UAAI,CAAC,UAAU,SAAS,EAAG;AAE3B,YAAM,QAAS,UAAU,SAAS,CAAC;AAEnC,UAAI,UAAU,SAAS,WAAW;AAChC,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,cAAM,QAAQ,oBAAoB,IAAI;AACtC,YAAI,OAAO;AACT,gBAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC9D,kBAAQ,KAAK,EAAE,OAAO,OAAO,kBAAkB,CAAC;AAAA,QAClD;AACA;AAAA,MACF;AAEA,UAAI,UAAU,SAAS,aAAa;AAClC,cAAM,UAAU,cAAc,KAAK;AACnC,cAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,cAAM,QAAQ,oBAAoB,IAAI;AACtC,YAAI,WAAW,OAAO;AAEpB,kBAAQ,KAAK,EAAE,OAAO,OAAO,GAAG,SAAS,kBAAkB,CAAC;AAAA,QAC9D;AACA;AAAA,MACF;AAEA,UAAI,CAAC,YAAY,UAAU,IAAI,EAAG;AAClC,YAAM,WAAY,UACf;AACH,UAAI,MAAM,QAAQ,QAAQ,EAAG,UAAS,QAAQ,KAAK;AAAA,IACrD;AAIA,YAAQ,WAAW,QAAQ,KAAK;AAAA,EAClC,CAAC;AAED,SAAO;AACT;;;AzChCA,SAASG,cACP,WACoD;AACpD,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAOC,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB,KAAK;AACH,aAAOA,eAAc;AAAA,IACvB;AACE,aAAOA,eAAc;AAAA,EACzB;AACF;AAwBA,SAAS,eAAe,UAAiD;AACvE,QAAM,EAAE,OAAO,UAAU,aAAa,QAAQ,SAAS,SAAS,KAAK,IACnE;AAEF,QAAM,mBAAmB;AAAA,IACvB,GAAI,UAAU,CAAC,EAAE,MAAM,WAAW,OAAO,QAAQ,CAAC,IAAI,CAAC;AAAA,IACvD,GAAI,UAAU,CAAC,EAAE,MAAM,WAAW,OAAO,QAAQ,CAAC,IAAI,CAAC;AAAA,EACzD;AAEA,SAAO;AAAA,IACL,GAAI,SAAS,EAAE,MAAM;AAAA,IACrB,GAAI,YAAY,EAAE,SAAS,SAAS;AAAA,IACpC,GAAI,eAAe,EAAE,YAAY;AAAA;AAAA,IAEjC,GAAI,UAAU,EAAE,SAAS,QAAQ,gBAAgB,OAAO;AAAA,IACxD,GAAI,QAAQ,KAAK,SAAS,KAAK,EAAE,UAAU,KAAK,KAAK,IAAI,EAAE;AAAA,IAC3D,GAAI,iBAAiB,SAAS,KAAK,EAAE,iBAAiB;AAAA,EACxD;AACF;AAKA,eAAsB,eACpB,WACA,QACA,SACmB;AACnB,SAAO;AAAA,IAAsB,UAAU,SAAS;AAAA,IAAM,MACpD;AAAA,MAAe,SAAS;AAAA,MAAS,MAC/B,uBAAuB;AAAA,QAAU,MAC/B,yBAAyB;AAAA,UAAU,MACjC,wBAAwB;AAAA,YAAU,MAChC,8BAA8B;AAAA,cAAU;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKtC,sBAAsB;AAAA,kBAAU;AAAA;AAAA;AAAA,oBAG9B,mBAAmB;AAAA,sBAAU,MAC3B,qBAAqB,WAAW,QAAQ,OAAO;AAAA,oBACjD;AAAA;AAAA,gBACF;AAAA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,qBACb,WACA,QACA,SACmB;AAEnB,MAAI,SAAS,OAAO;AAClB,6BAAyB,QAAQ,KAAK;AAAA,EACxC,WAAW,CAAC,SAAS,aAAa;AAEhC,6BAAyB;AAAA,EAC3B;AAEA,QAAM,WAA8B,CAAC;AAGrC,QAAM,UAAU;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACA,UAAQ,WAAW,SAAS;AAC5B,UAAQ,cAAc,SAAS;AAO/B,MAAI;AACF,UAAM,sBAAsB,MAAM;AAAA,MAChC,OAAO;AAAA,MACP,SAAS,UAAU;AAAA,MACnB,EAAE,SAAS,WAAW,GAAG,OAAO,SAAS,YAAY;AAAA,IACvD;AACA,QAAI,oBAAoB,OAAO,GAAG;AAChC,cAAQ,sBAAsB;AAAA,IAChC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AAMA,MAAI;AACF,UAAM,cAAc,mBAAmB,OAAO,QAAQ;AACtD,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,cAAc;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ;AAAA,MACN;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AAYA,QAAM,kBAAkB,uBAAuB,OAAO,QAAQ;AAG9D,MAAI,iBAAoD;AACxD,MAAI,iBAAoD;AAGxD,WAAS,MAAM,GAAG,MAAM,OAAO,SAAS,QAAQ,OAAO;AACrD,UAAM,gBAAgB,OAAO,SAAS,GAAG;AACzC,UAAM,EAAE,SAAS,gBAAgB,cAAc,IAAI,gBAAgB,GAAG;AAGtE,QAAI;AACJ,QAAI,cAAc,WAAW,kBAAkB;AAE7C,oBAAc;AAAA,IAChB,WAAW,cAAc,QAAQ;AAE/B,oBAAc,cAAc;AAC5B,uBAAiB;AAAA,IACnB,OAAO;AAKL,oBAAc,iBAAiB,CAAC,IAAI;AAAA,IAEtC;AAGA,QAAI;AACJ,QAAI,cAAc,WAAW,kBAAkB;AAE7C,oBAAc;AAAA,IAChB,WAAW,cAAc,QAAQ;AAE/B,oBAAc,cAAc;AAC5B,uBAAiB;AAAA,IACnB,OAAO;AAIL,oBAAc,iBAAiB,CAAC,IAAI;AAAA,IAEtC;AAEA,UAAM,kBAAkB;AAAA,MACtB,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,gBAAgB;AAAA,IAC3B;AAEA,QAAI,SAAS,SAAS,SAAS,GAAG;AAChC,eAAS,KAAK,QAAQ;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,mBAAmB,wBAAwB,OAAO;AAExD,QAAM,WAAW,sBAAsB,OAAO;AAE9C,QAAM,YAAY,mBAAmB,aAAa;AAClD,QAAM,WAAW,mBAAmB,YAAY;AAEhD,SAAO,IAAI,SAAS;AAAA,IAClB,QAAQ,iBAAiB,UAAU,OAAO,UAAU,QAAQ;AAAA,IAC5D;AAAA,IACA,GAAG,eAAe,UAAU,QAAQ;AAAA,IACpC,UAAU;AAAA,MACR,cAAc;AAAA;AAAA;AAAA,MAEd,GAAI,UAAU,kBAAkB,EAAE,gBAAgB,KAAK;AAAA,IACzD;AAAA;AAAA,IAEA,GAAI,SAAS,SAAS,KAAK,EAAE,UAAU,EAAE,UAAU,SAAS,EAAE;AAAA;AAAA;AAAA,IAG9D,GAAI,OAAO,KAAK,SAAS,EAAE,SAAS,KAAK,EAAE,UAAU;AAAA,IACrD,GAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,KAAK,EAAE,SAAS;AAAA;AAAA,IAEnD,GAAI,iBAAiB,SAAS,KAAK;AAAA,MACjC,WAAW;AAAA,QACT,QAAQ;AAAA,MAIV;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAKA,eAAe,6BACb,YACA,OACA,WACA,SACgC;AAChC,MAAI,CAAC,cAAc,WAAW,WAAW,GAAG;AAC1C,WAAO,CAAC;AAAA,EACV;AAGA,QAAM,mBAAmB,WAAW;AAAA,IAClC,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AAEA,QAAM,WAAkC,CAAC;AAEzC,aAAW,aAAa,kBAAkB;AACxC,QAAI,qBAAqB,SAAS,GAAG;AACnC,YAAM,WAAW;AACjB,YAAM,OAAO,SAAS,MAAM;AAI5B,YAAM,cAAc,eAAe,KAAK;AAOxC,eAAS;AAAA,QACP,WAAW,SAAS,MAAM,MAAM,OAAO,WAAW;AAAA,UAChD,OAAO;AAAA,UACP,WAAW,SAAS,MAAM;AAAA;AAAA;AAAA,UAG1B,YACE,MAAM,UACN,kBAAkB,OAAO,YAAY,IAAI,KACzC,cAAc,KAAK,EAAE,KAAK;AAAA,UAC5B,UAAW,MAAM,QAAQ,YAAY,QAAQ;AAAA;AAAA;AAAA,UAG7C,WAAW,MAAM,SAAS,YAAY,SAAS;AAAA,UAC/C,MAAM,MAAM,QAAQ;AAAA,UACpB,QAAQ,MAAM,UAAU;AAAA,UACxB,WAAW,MAAM;AAAA,UACjB,YAAa,MAA8C;AAAA,UAC3D,WAAW,SAAS,MAAM;AAAA,UAC1B,SAAS,SAAS,MAAM;AAAA,UACxB,aAAa,MAAM;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF,WAAW,iBAAiB,SAAS,GAAG;AACtC,YAAM,YAAY;AAElB,UAAI,cAAc,mBAAmB,UAAU,KAAK;AACpD,UAAI,CAAC,aAAa;AAChB,iBAAS;AAAA,UACP,IAAIC,WAAU;AAAA,YACZ,UAAU;AAAA,cACR,IAAIC,SAAQ;AAAA,gBACV,MAAM;AAAA,gBACN,MAAM,cAAc,KAAK,EAAE,KAAK;AAAA,gBAChC,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,cACT,CAAC;AAAA,YACH;AAAA,YACA,WAAW,UAAU,MAAM,YACvBH,cAAa,UAAU,MAAM,SAAS,IACtC;AAAA,YACJ,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAEA,UAAI;AACJ,UAAI;AAEJ,UAAI;AAEF,cAAM,cAAc,MAAM,eAAe,WAAW;AACpD,sBAAc,YAAY;AAC1B,8BAAsB,YAAY;AAAA,MACpC,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,6BAA6B,YAAY,UAAU,GAAG,EAAE,CAAC;AAAA,QAC3D;AAAA,MACF;AAEA,UAAI;AAEF,cAAM,YAAY,aAAa,KAAK;AAGpC,cAAM,kBAAkB,KAAK;AAG7B,cAAM,cAAc,KAAK,MAAM,UAAU,KAAK,QAAQ,eAAe;AACrE,cAAM,iBAAiB,KAAK;AAAA,WACzB,UAAU,KAAK,QACd,UAAU,OAAO,OACjB,UAAU,OAAO,SACjB;AAAA,QACJ;AAGA,cAAM,kBAAkB,UAAU,MAAM,mBAAmB;AAC3D,cAAM,mBAAmB,UAAU,MAAM,oBAAoB;AAC7D,cAAM,mBACJ,oBAAoB,SAAS,cAAc;AAG7C,cAAM,eAAe,KAAK;AAAA,UACxB,UAAU,KAAK,SAAS;AAAA,QAC1B;AACA,cAAM,kBAAkB,KAAK;AAAA,WAC1B,UAAU,KAAK,SACd,UAAU,OAAO,MACjB,UAAU,OAAO,UACjB;AAAA,QACJ;AACA,cAAM,oBACJ,qBAAqB,SAAS,eAAe;AAE/C,cAAM,iBAAiB,KAAK,MAAM,mBAAmB,GAAG;AAGxD,cAAM,cACJ,OAAO,UAAU,MAAM,UAAU,WAC7B,gBAAgB,UAAU,MAAM,OAAO,gBAAgB,IACvD,UAAU,MAAM;AAGtB,cAAM,eACJ,OAAO,UAAU,MAAM,WAAW,WAC9B,gBAAgB,UAAU,MAAM,QAAQ,iBAAiB,IACzD,UAAU,MAAM;AAGtB,cAAM,aAAa,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAGA,cAAM,kBAAkB;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AAEA,cAAM,YAAY,gBAAgB,aAAa,mBAAmB;AAElE,cAAM,WAAW,oBAAoB;AAAA,UACnC,MAAM;AAAA,UACN,MAAM;AAAA,UACN,gBAAgB;AAAA,YACd,OAAO,WAAW;AAAA,YAClB,QAAQ,WAAW;AAAA,UACrB;AAAA,UACA,GAAI,mBAAmB,EAAE,UAAU,gBAAgB;AAAA,QACrD,CAAC;AAED,iBAAS;AAAA,UACP,IAAIE,WAAU;AAAA,YACZ,UAAU,CAAC,QAAQ;AAAA,YACnB,WAAW,UAAU,MAAM,YACvBF,cAAa,UAAU,MAAM,SAAS,IACtC;AAAA,YACJ,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AAId,cAAM,gBAAgB,YAAY,UAAU,GAAG,EAAE;AACjD,gBAAQ;AAAA,UACN,uDAAuD,aAAa;AAAA,UACpE,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAC3C;AACA,iBAAS;AAAA,UACP,IAAIE,WAAU;AAAA,YACZ,UAAU;AAAA,cACR,IAAIC,SAAQ;AAAA,gBACV,MAAM,WAAW,aAAa;AAAA,gBAC9B,MAAM,cAAc,KAAK,EAAE,KAAK;AAAA,gBAChC,MAAM;AAAA,gBACN,OAAO,eAAe,KAAK,EAAE;AAAA,gBAC7B,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,YACA,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,WAAW,iBAAiB,SAAS,GAAG;AAGtC,YAAM,SAAS,MAAM,qBAAqB,WAAW,OAAO,SAAS;AACrE,eAAS,KAAK,GAAG,MAAM;AAAA,IACzB,WAAW,kBAAkB,SAAS,GAAG;AAEvC,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,eAAS,KAAK,GAAG,SAAS;AAAA,IAC5B;AAAA,EAEF;AAEA,SAAO;AACT;AAKA,eAAsB,cACpB,SACA,OACA,WACA,SACA,gBACA,eACA,cAAc,OACY;AAC1B,QAAM,WAAoD,CAAC;AAI3D,QAAM,6BAA6B,QAAQ;AAG3C,QAAM,WACJ,QAAQ,wBAAwB,iBAC5B,8BAA8B,iBAAiB,cAAc,IAC7D;AACN,QAAM,eAAe,UAAU;AAC/B,QAAM,oBAAoB,UAAU;AAEpC,QAAM,iBAAgC;AAAA,IACpC,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,QAAQ;AAAA,MACX,eAAe,QAAQ;AAAA,MACvB,aAAa,QAAQ,WAAW,QAAQ,SAAS;AAAA;AAAA,MAEjD;AAAA,IACF;AAAA,EACF;AAGA,MACE,qBACA,8BACA,iBAAiB,QACjB;AACA,aAAS;AAAA,MACP,IAAID,WAAU;AAAA,QACZ,UAAU,CAAC,IAAIE,eAAc,mBAAmB,YAAY,CAAC;AAAA,QAC7D,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,mBAAmB,QAAQ,WAAW;AAAA,IAC1C,CAAC,MAAM,EAAE,aAAa,KAAK,EAAE,YAAY;AAAA,EAC3C;AACA,aAAW,aAAa,kBAAkB;AACxC,UAAM,WAAW,MAAM;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,aAAS,KAAK,GAAG,QAAQ;AAAA,EAC3B;AAGA,MAAI,iBAAiB,iBAAiB,QAAW;AAC/C,aAAS;AAAA,MACP,IAAIF,WAAU;AAAA,QACZ,UAAU,CAAC,IAAIG,aAAY,YAAY,CAAC;AAAA,MAC1C,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,UAAU,QAAQ,QAAQ;AACpC,QAAI,QAAQ,UAAU,QAAQ,WAAW,kBAAkB;AACzD,YAAM,mBAAmB,QAAQ;AACjC,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAGA,UAAI,iBAAiB,WAAW,KAAK,iBAAiB,SAAS,GAAG;AAChE,kBAAU;AAAA,UACR,SAAS,oBAAoB,gBAAgB;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAEA,QAAI,QAAQ,UAAU,QAAQ,WAAW,kBAAkB;AACzD,YAAM,mBAAmB,QAAQ;AACjC,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,iBAAiB,WAAW,KAAK,iBAAiB,SAAS,GAAG;AAChE,kBAAU;AAAA,UACR,SAAS,oBAAoB,gBAAgB;AAAA,QAC/C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,iBAAkC;AAAA,IACtC,YAAY,QAAQ;AAAA,IACpB,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AACT;AAKA,eAAsB,gBACpB,WACA,OACA,WACA,SAC4D;AAC5D,MAAI,mBAAmB,SAAS,GAAG;AACjC,WAAO,uBAAuB,WAAW,OAAO,SAAS;AAAA,EAC3D,WAAW,qBAAqB,SAAS,GAAG;AAC1C,WAAO,yBAAyB,WAAW,OAAO,SAAS;AAAA,EAC7D,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E,WAAW,iBAAiB,SAAS,GAAG;AACtC,WAAO,MAAM,qBAAqB,WAAW,OAAO,SAAS;AAAA,EAC/D,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E,WAAW,qBAAqB,SAAS,GAAG;AAC1C,WAAO,yBAAyB,WAAW,KAAK;AAAA,EAClD,WAAW,iBAAiB,SAAS,GAAG;AACtC,WAAO,MAAM,qBAAqB,WAAW,OAAO,SAAS;AAAA,EAC/D,WAAW,gBAAgB,SAAS,GAAG;AACrC,WAAO,oBAAoB,WAAW,OAAO,SAAS;AAAA,EACxD,WAAW,eAAe,SAAS,GAAG;AACpC,WAAO,mBAAmB,WAAW,OAAO,OAAO;AAAA,EACrD,WAAW,sBAAsB,SAAS,GAAG;AAC3C,WAAO,MAAM;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,kBAAkB,SAAS,GAAG;AACvC,WAAO,MAAM,sBAAsB,WAAW,OAAO,WAAW,OAAO;AAAA,EACzE,WAAW,mBAAmB,SAAS,GAAG;AACxC,WAAO,MAAM,uBAAuB,WAAW,OAAO,WAAW,OAAO;AAAA,EAC1E;AAEA,QAAM,IAAI;AAAA,IACR,2BAA4B,UAAkC,IAAI;AAAA,EACpE;AACF;;;A0CvvBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIP,eAAsB,qBACpB,UACA,OACA,OACA,UAQA,mBAAmB,OACM;AACzB,QAAM,OAAO,CAAC,MAAc,YAAoB;AAC9C,QAAI,UAAU;AACZ,eAAS,KAAK;AAAA,QACZ,WAAW;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,SAAS,EAAE,KAAK;AAAA,MAClB,CAAC;AAAA,IACH,OAAO;AAEL,cAAQ,KAAK,kBAAkB,IAAI,KAAK,OAAO,EAAE;AAAA,IACnD;AAAA,EACF;AAKA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,KAAK,yBAAyB,QAAQ,EAAG,OAAM,IAAI,CAAC;AAC/D,aAAW,KAAK,yBAAyB,KAAgB,EAAG,OAAM,IAAI,CAAC;AACvE,MAAI,MAAM,SAAS,EAAG,QAAO,CAAC;AAQ9B,QAAM,kBAAkB;AAAA,IACtB,kBAAkB,KAAK;AAAA,IACvB,qBAAqB,QAAQ;AAAA,IAC7B,OAAO;AAAA,EACT;AAKA,QAAM,aAAa,uBAAuB;AAAA,IACxC,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,EACrB,CAAC;AACD,MAAI,WAAW,SAAS,SAAS,GAAG;AAClC,QAAI,OAAO,QAAQ;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,IACE,WAAW,SAAS,IAAI,CAAC,MAAM,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,MAChE;AAAA,IACF;AACA,eAAW,KAAK,WAAW,UAAU;AACnC,WAAK,EAAE,MAAM,EAAE,OAAO;AAAA,IACxB;AAAA,EACF;AAOA,MAAI,CAAC,OAAO,cAAc,CAAC,iBAAkB,QAAO,CAAC;AAErD,QAAM,WAAW,IAAI,aAAa;AAAA;AAAA;AAAA,IAGhC,MAAM,EAAE,GAAG,OAAO,cAAc,gBAAgB;AAAA,IAChD,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,WAAW,OAAO,aAAa,WAC3B,IAAI,cAAc,MAAM,YAAY,QAAQ,IAC5C;AAAA,EACN,CAAC;AACD,QAAM,WAAW,MAAM,SAAS,YAAY,KAAK;AACjD,aAAW,KAAK,UAAU;AACxB,eAAW,OAAO,EAAE,UAAU;AAC5B,WAAK,mBAAmB,GAAG;AAAA,IAC7B;AAAA,EACF;AAIA,SAAO,aAAa,QAAQ;AAC5B,SAAO;AACT;;;ApD/GA,SAAS,4BAA4B;;;AqDtBrC,OAAOC,aAAY;AACnB,SAAwB,cAAc;;;ACYtC,OAAO,YAAY;AAIZ,SAAS,4BAA4B,QAAwB;AAClE,QAAM,MAAM,IAAI,OAAO,MAAM;AAC7B,QAAM,gBAAgB,IAAI,SAAS,mBAAmB;AAEtD,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,gCAAgC;AAAA,EAClD;AAEA,MAAI,YAAY;AAMhB,QAAM,cAAc,cACjB,QAAQ,EACR,SAAS,MAAM,EACf,QAAQ,kCAAkC,CAAC,QAAQ,WAAmB;AACrE,UAAM,QAAQ;AACd,WAAO,GAAG,MAAM,OAAO,KAAK;AAAA,EAC9B,CAAC;AAEH,MAAI,WAAW,eAAe,OAAO,KAAK,aAAa,MAAM,CAAC;AAC9D,SAAO,IAAI,SAAS;AACtB;;;AD7BO,IAAM,0BAA0B,oBAAI,KAAK,0BAA0B;AAEnE,SAAS,sBAAsB,SAAwC;AAC5E,MAAI,SAAS,gBAAgB,QAAW;AACtC,UAAM,OAAO,IAAI,KAAK,QAAQ,WAAW;AACzC,QAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,GAAG;AAChC,YAAM,IAAI,WAAW,kCAAkC;AAAA,IACzD;AACA,QAAI,KAAK,eAAe,IAAI,MAAM;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,SAAO,SAAS,kBAAkB,QAC9B,oBAAI,KAAK,IACT,IAAI,KAAK,uBAAuB;AACtC;AAGA,SAAS,UAAU,MAAoB;AACrC,QAAM,WACD,KAAK,eAAe,IAAI,OAAQ,QAAS,IAC1C,KAAK,YAAY,IAAI,KAAM,IAC7B,KAAK,WAAW;AAClB,QAAM,UACH,KAAK,YAAY,KAAK,KACtB,KAAK,cAAc,KAAK,IACxB,KAAK,cAAc,KAAK;AAC3B,UAAS,WAAW,KAAM,aAAa;AACzC;AAOO,SAAS,uBACd,QACA,cAAoB,yBACZ;AACR,QAAM,MAAM,IAAIC,QAAO,MAAM;AAC7B,QAAM,eAAe,YAAY,YAAY;AAC7C,QAAMC,kBAAiB,IAAI,SAAS,mBAAmB;AAEvD,MAAIA,iBAAgB;AAClB,UAAM,aAAaA,gBAChB,QAAQ,EACR,SAAS,MAAM,EACf;AAAA,MACC;AAAA,MACA,KAAK,YAAY;AAAA,IACnB;AACF,QAAI,WAAWA,iBAAgB,OAAO,KAAK,YAAY,MAAM,CAAC;AAAA,EAChE;AASA,QAAM,eAAe,UAAU,WAAW;AAC1C,aAAW,SAAS,IAAI,WAAW,GAAG;AACpC,IAAC,MAAM,OAA0C,UAAU;AAAA,EAC7D;AAEA,SAAO,IAAI,SAAS;AACtB;AAGA,eAAsB,gBACpB,UACA,SACiB;AACjB,QAAM,SAAU,MAAM,OAAO,SAAS,QAAQ;AAC9C,QAAM,QAAQ,4BAA4B,MAAM;AAEhD,MAAI,SAAS,kBAAkB,OAAO;AACpC,WAAO;AAAA,EACT;AAEA,SAAO,uBAAuB,OAAO,sBAAsB,OAAO,CAAC;AACrE;;;AE1FA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACSA,SAAS,mBACd,WACqB;AAErB,MAAI,UAAU,SAAS,WAAW;AAChC,WAAO,0BAA0B,SAAuC;AAAA,EAC1E;AAGA,MAAI,cAAc,aAAa,UAAU,UAAU;AACjD,WAAO;AAAA,MACL,GAAG;AAAA;AAAA,MACH,UAAU,UAAU,SAAS,IAAI,kBAAkB;AAAA,IACrD;AAAA,EACF;AAGA,MAAI,UAAU,SAAS,WAAW;AAChC,WAAO,0BAA0B,SAAuC;AAAA,EAC1E;AAGA,SAAO;AACT;AAMA,SAAS,0BACP,WAC4B;AAC5B,QAAM,MAAM,UAAU,SAAU,CAAC;AAGjC,QAAM,mBAAmB,CACvB,MACA,WAEA,KAAK,IAAI,CAAC,GAAG,MAAM;AACjB,UAAM,SAAS,MAAM,KAAK,SAAS;AACnC,QAAI,CAAC,UAAU,EAAE,QAAQ,UAAa,WAAW,QAAW;AAC1D,aAAO,EAAE,GAAG,GAAG,KAAK,OAAO;AAAA,IAC7B;AACA,WAAO;AAAA,EACT,CAAC;AAGH,QAAM,qBAAqB,CACzB,SAEA,KAAK,IAAI,CAAC,OAAO;AAAA,IACf,GAAG;AAAA,IACH,OAAO,EAAE,UAAU,SAAS,SAAY,EAAE;AAAA,EAC5C,EAAE;AAEJ,MAAI;AAEJ,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,UAAU,GAAG;AAEtD,UAAM,IAAI,IAAI;AACd,UAAM,OAAO,MAAM;AAAA,MACjB,EAAE,QAAQ,EAAE;AAAA,MACZ,OAAO,CAAC;AAAA,IACV;AACA,UAAM,cAAc,IAAI,QAAQ,SAAY,IAAI,MAAM;AACtD,mBAAe,iBAAiB,MAAM,WAAW;AAAA,EACnD,WAAW,MAAM,QAAQ,IAAI,OAAO,GAAG;AAErC,mBAAe,IAAI;AAEnB,UAAM,cAAc,IAAI,QAAQ,SAAY,IAAI,MAAM;AACtD,mBAAe,iBAAiB,cAAc,WAAW;AAEzD,mBAAe,mBAAmB,YAAY;AAAA,EAChD,OAAO;AAEL,mBAAe,CAAC,CAAC,CAAC;AAAA,EACpB;AAEA,QAAM,kBAAgC;AAAA,IACpC,SAAS;AAAA,EACX;AAEA,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IACH,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU,UAAU,WAChB,UAAU,SAAS,IAAI,kBAAkB,IACzC;AAAA,EACN;AACF;AAMA,SAAS,0BACP,WAC4B;AAC5B,QAAM,QAAQ,UAAU,SAAU,CAAC;AAEnC,SAAO;AAAA,IACL,GAAG;AAAA;AAAA,IACH,OAAO;AAAA,MACL,GAAG;AAAA;AAAA,MACH,QAAQ,MAAM,SACV,MAAM,WAAW,mBACf,mBACA,MAAM,OAAO,IAAI,CAAC,MAA2B,mBAAmB,CAAC,CAAC,IACpE;AAAA,MACJ,QAAQ,MAAM,SACV,MAAM,WAAW,mBACf,mBACA,MAAM,OAAO,IAAI,CAAC,MAA2B,mBAAmB,CAAC,CAAC,IACpE;AAAA,IACN;AAAA,IACA,UAAU,UAAU,WAChB,UAAU,SAAS,IAAI,kBAAkB,IACzC;AAAA,EACN;AACF;AAMO,SAAS,kBACd,UAC6B;AAE7B,MAAI,SAAS,SAAS,QAAQ;AAC5B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,mBAAmB,QAAQ;AAC9C,SAAO,CAAC,UAAU;AACpB;;;ACpKA,SAAS,YAAYC,WAAU;AAC/B,SAAS,MAAM,WAAAC,UAAS,cAAAC,mBAAkB;AAa1C,eAAsB,mBACpB,UAC8B;AAC9B,MAAI;AAEF,UAAM,eAAeC,YAAW,QAAQ,IAAI,WAAWC,SAAQ,QAAQ;AAGvE,UAAMC,IAAG,OAAO,YAAY;AAG5B,UAAM,cAAc,MAAMA,IAAG,SAAS,cAAc,OAAO;AAG3D,WAAO,yBAAyB,WAAW;AAAA,EAC7C,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,UAAU,OAAO;AAC7C,YAAM,UAAU;AAEhB,cAAQ,QAAQ,MAAM;AAAA,QACtB,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,mBAAmB,QAAQ;AAAA,YAC3B;AAAA,UACF;AAAA,QACF,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,sBAAsB,QAAQ;AAAA,YAC9B;AAAA,UACF;AAAA,QACF,KAAK;AACH,gBAAM,IAAI;AAAA,YACR,wBAAwB,QAAQ;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AACE,gBAAM,IAAI;AAAA,YACR,sBAAsB,QAAQ,OAAO;AAAA,YACrC;AAAA,UACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,iBAAiB,OAAO;AAC1B,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,KAAK,MAAM,OAAO;AAAA,QAC3C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR,yBAAyB,QAAQ;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AA8RO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvB;AAAA,EACA;AAAA,EAEhB,YAAY,SAAiB,MAAc,eAAuB;AAChE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,gBAAgB;AAAA,EACvB;AACF;;;AzD5RO,SAAS,4BACd,YACyC;AACzC,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,MAAM;AAIZ,SAAO,IAAI,SAAS;AACtB;AAMA,eAAsB,iBACpB,UACA,SACmB;AAEnB,MAAI,CAAC,YAAY,SAAS,SAAS,QAAQ;AACzC,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAGA,MAAI,aAAa,UAAU;AACzB,WAAO,MAAM,yBAAyB,UAAU,OAAO;AAAA,EACzD;AAMA,SAAO,MAAM;AAAA,IACX;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,sBAAsB,OAAO;AAAA,IAC7B,SAAS;AAAA,EACX;AACF;AAMA,eAAsB,mBACpB,OACA,YACA,SACmB;AACnB,QAAM,kBAA6C;AAAA,IACjD,MAAM;AAAA,IACN;AAAA,IACA,UAAU;AAAA,EACZ;AAEA,SAAO,MAAM,iBAAiB,iBAAiB,OAAO;AACxD;AAMA,eAAe,iCACb,YACA,cACA,UACA,OACA,UACA,gBACA,SACmB;AAInB,QAAM,EAAE,UAAU,OAAO,UAAU,IAAI,oBAAoB,YAAY;AAAA,IACrE;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAUD,QAAM,YAAY,mBAAmB,QAAQ,EAAE,SAAS;AACxD,QAAM,gBAAgB,MAAM;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAKA,QAAM,cAAc,YAChB,qBAAqB,eAAe,QAAQ,IAC5C,CAAC;AAGL,QAAM,YAAY,MAAM;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,SAAS,YAAY,UAAU,UAAU,OAAO,SAAS;AAC/D,QAAM,mBAAmB,MAAM,eAAe,WAAW,QAAQ;AAAA,IAC/D,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA,GAAI,YAAY,SAAS,KAAK,EAAE,YAAY;AAAA,EAC9C,CAAC;AAED,SAAO;AACT;AAMA,eAAsB,yBACpB,YACA,SACmB;AAKnB,QAAM,aAAa,SAAS;AAC5B,MAAI,YAAY,YAAY,OAAO;AACjC,UAAM,SAAS,sBAAsB,YAAY;AAAA,MAC/C,oBAAoB,YAAY;AAAA,IAClC,CAAC;AACD,QAAI,CAAC,OAAO,OAAO;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACJ,MAAI,OAAO,eAAe,UAAU;AAClC,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,UAAU;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,IAAI,iBAAiB,uBAAuB;AAAA,QAChD;AAAA,UACE,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,UAClD,MAAM;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,CAAC,kBAAkB,MAAM,GAAG;AAC9B,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,yBAAqB;AAAA,EACvB,OAAO;AAEL,yBAAqB;AAAA,EACvB;AAIA,QAAM,CAAC,eAAe,IAAI,kBAAkB,kBAAkB;AAK9D,SAAO,MAAM;AAAA,IACX;AAAA,IACA,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,sBAAsB,OAAO;AAAA,IAC7B,SAAS;AAAA,EACX;AACF;AAKO,SAAS,mBACd,YAC0B;AAC1B,SAAO,sBAAsB,UAAU;AACzC;AAKA,eAAsB,uBACpB,YACA,SACiB;AACjB,QAAM,WAAW,MAAM,yBAAyB,YAAY,OAAO;AACnE,SAAO,gBAAgB,UAAU,OAAO;AAC1C;AAKA,eAAsB,wBACpB,YACA,UACA,SACe;AACf,QAAM,WAAW,MAAM,yBAAyB,YAAY,OAAO;AACnE,QAAM,aAAa,UAAU,UAAU,OAAO;AAChD;AAKA,eAAsB,yBACpB,UACA,SACmB;AACnB,QAAM,iBAAiB,MAAM,mBAAmB,QAAQ;AAIxD,SAAO,MAAM,yBAAyB,gBAAgB;AAAA,IACpD,SAAS,QAAQC,SAAQ,QAAQ,CAAC;AAAA,IAClC,GAAG;AAAA,EACL,CAAC;AACH;AAKA,eAAsB,uBACpB,UACA,SACiB;AACjB,QAAM,WAAW,MAAM,yBAAyB,UAAU,OAAO;AACjE,SAAO,gBAAgB,UAAU,OAAO;AAC1C;AAKA,eAAsB,wBACpB,eACA,gBACA,SACe;AACf,QAAM,WAAW,MAAM,yBAAyB,eAAe,OAAO;AACtE,QAAM,aAAa,UAAU,gBAAgB,OAAO;AACtD;AAKA,eAAsB,aACpB,UACA,UACA,SACe;AACf,QAAM,SAAS,MAAM,gBAAgB,UAAU,OAAO;AACtD,gBAAc,UAAU,MAAM;AAChC;AAKA,eAAsB,gBACpB,UACA,UACA,SACe;AACf,QAAM,oBAAoB,MAAM,iBAAiB,UAAU,OAAO;AAClE,QAAM,aAAa,mBAAmB,UAAU,OAAO;AACzD;AAaO,IAAM,oBAAoB;AAAA,EAC/B,UAAU;AAAA,EACV;AAAA,EACA,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN;AAAA,EACA;AACF;;;A0D/XA;AAAA,EACE,kBAAAC;AAAA,EACA,sBAAAC;AAAA,OAIK;AAUP,IAAM,sBAAsB;AA8C5B,eAAsB,eACpB,KACA,SACY;AACZ,MAAI,YAAY,QAAQ;AAExB,MAAI,QAAQ,gBAAgB;AAK1B,UAAM,gBAAgB,MAAM;AAAA,MAC1B;AAAA,MACA;AAAA,QACE,QAAQ,QAAQ;AAAA,QAChB,aAAa,QAAQ;AAAA,QACrB,KAAK,QAAQ;AAAA,MACf;AAAA,MACA;AAAA,QACE,SAAS,QAAQ;AAAA,QACjB,aAAa,QAAQ;AAAA,QACrB,OAAO,QAAQ;AAAA,MACjB;AAAA,IACF,EAAE,MAAM,MAAM,oBAAI,IAAmB,CAAC;AACtC,gBAAY,OAAO,YAAY;AAC7B,YAAM,MAAM,cAAc;AAAA,QACxB,gBAAgB,QAAQ,cAAc,QAAQ,GAAG;AAAA,MACnD;AACA,UAAI,KAAK;AACP,YAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,IAAI,KAAK;AACtC,eAAO;AAAA,UACL,eAAe,IAAI;AAAA,UACnB,OAAO,IAAI;AAAA,UACX,QAAQ,IAAI;AAAA,QACd;AAAA,MACF;AACA,aAAO,QAAQ,UAAU,OAAO;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,MAAkB;AAAA,IACtB;AAAA,IACA,KAAK,QAAQ;AAAA,IACb,SAAS,QAAQ;AAAA,IACjB,OAAO,QAAQ;AAAA,IACf,OAAO;AAAA,MACL,KAAK,IAAI,GAAG,QAAQ,eAAe,mBAAmB;AAAA,IACxD;AAAA,EACF;AACA,SAAQ,MAAM,YAAY,KAAK,GAAG;AACpC;AAEA,eAAe,gBACb,KACA,KACkC;AAClC,QAAM,QAAQ,IAAI;AAClB,QAAM,MAAMC,gBAAe,MAAM,OAAO,IAAI,OAAOC,mBAAkB;AACrE,QAAM,SAAS,MAAM,IAAI;AAAA,IAAM,MAC7B,IAAI,UAAU;AAAA,MACZ,cAAc,wBAAwB,KAAK;AAAA,MAC3C;AAAA,MACA,SAAS,IAAI;AAAA,MACb,GAAI,IAAI,OAAO,SAAS,EAAE,OAAO,CAAC,GAAG,IAAI,KAAK,EAAE,IAAI,CAAC;AAAA,IACvD,CAAC;AAAA,EACH;AACA,QAAM,QAAiC;AAAA,IACrC,MAAM;AAAA,IACN,OAAO,mBAAmB,OAAO,OAAO,aAAa;AAAA,EACvD;AAEA,MAAI,IAAI,OAAO,OAAW,OAAM,KAAK,IAAI;AACzC,MAAI,IAAI,YAAY,OAAW,OAAM,UAAU,IAAI;AACnD,SAAO;AACT;AAEA,eAAe,YAAY,MAAe,KAAmC;AAC3E,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,WAAO,QAAQ,IAAI,KAAK,IAAI,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC;AAAA,EACzD;AACA,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,QAAM,MAAM;AAIZ,MAAI,IAAI,SAAS,YAAY,IAAI,SAAS,IAAI,YAAY,OAAO;AAC/D,WAAO,gBAAgB,KAAK,GAAG;AAAA,EACjC;AAEA,QAAM,OAAgC,EAAE,GAAG,IAAI;AAE/C,MAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC/B,SAAK,WAAW,MAAM,YAAY,IAAI,UAAU,GAAG;AAAA,EACrD;AAEA,MAAI,IAAI,SAAS,OAAO,IAAI,UAAU,UAAU;AAC9C,UAAM,QAAQ,IAAI;AAClB,QAAI,eAAe;AACnB,UAAM,YAAqC,EAAE,GAAG,MAAM;AAItD,eAAW,OAAO,CAAC,UAAU,QAAQ,GAAY;AAC/C,UAAI,MAAM,QAAQ,MAAM,GAAG,CAAC,GAAG;AAC7B,kBAAU,GAAG,IAAI,MAAM,YAAY,MAAM,GAAG,GAAG,GAAG;AAClD,uBAAe;AAAA,MACjB;AAAA,IACF;AAIA,QAAI,MAAM,QAAQ,MAAM,OAAO,GAAG;AAChC,gBAAU,UAAU,MAAM,QAAQ;AAAA,QAC/B,MAAM,QAAsB,IAAI,CAAC,QAAQ,cAAc,KAAK,GAAG,CAAC;AAAA,MACnE;AACA,qBAAe;AAAA,IACjB;AAEA,QAAI,aAAc,MAAK,QAAQ;AAAA,EACjC;AAEA,SAAO;AACT;AAEA,eAAe,cAAc,KAAc,KAAmC;AAC5E,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAC5C,QAAM,SAAS;AACf,QAAM,UAAmC,EAAE,GAAG,OAAO;AAErD,QAAM,SAAS,OAAO;AACtB,MAAI,UAAU,OAAO,WAAW,YAAY,aAAa,QAAQ;AAC/D,YAAQ,SAAS;AAAA,MACf,GAAG;AAAA,MACH,SAAS,MAAM,YAAY,OAAO,SAAS,GAAG;AAAA,IAChD;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/B,YAAQ,QAAQ,MAAM,QAAQ;AAAA,MAC3B,OAAO,MAAoB,IAAI,OAAO,SAAS;AAC9C,YAAI,QAAQ,OAAO,SAAS,YAAY,aAAa,MAAM;AACzD,gBAAM,IAAI;AACV,iBAAO,EAAE,GAAG,GAAG,SAAS,MAAM,YAAY,EAAE,SAAS,GAAG,EAAE;AAAA,QAC5D;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;;;ACzNO,SAAS,yBACd,UACkC;AAClC,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,WAAkC;AAAA,IACtC;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,QACL,MAAM,GAAG,SAAS,MAAM;AAAA,QACxB,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,sBAAsB,oBAAI,IAAiC;AACjE,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,oBAAoB,IAAI,QAAQ,SAAS,KAAK,CAAC;AAChE,aAAS,KAAK,OAAO;AACrB,wBAAoB,IAAI,QAAQ,WAAW,QAAQ;AAAA,EACrD;AAGA,aAAW,CAAC,eAAe,iBAAiB,KAAK,oBAAoB,QAAQ,GAAG;AAC9E,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,MAAM,cAAc,aAAa;AAAA,MACnC;AAAA,IACF,CAAC;AAGD,UAAM,eAAyB,CAAC;AAChC,eAAW,WAAW,mBAAmB;AACvC,UAAI,cAAc,QAAQ;AAG1B,UAAI,QAAQ,WAAW,OAAO,KAAK,QAAQ,OAAO,EAAE,SAAS,GAAG;AAC9D,cAAM,aAAa,OAAO,QAAQ,QAAQ,OAAO,EAC9C,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,KAAK,KAAK,UAAU,KAAK,CAAC,EAAE,EACxD,KAAK,IAAI;AACZ,uBAAe,KAAK,UAAU;AAAA,MAChC;AAEA,mBAAa,KAAK,WAAW;AAAA,IAC/B;AAEA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,OAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,UACP,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,MACL,UAAU;AAAA,QACR,OAAO;AAAA,MACT;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;AAMO,SAAS,mBACd,UACQ;AACR,MAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,QAAkB;AAAA,IACtB,iCAAiC,SAAS,MAAM;AAAA,IAChD,IAAI,OAAO,EAAE;AAAA,IACb;AAAA,EACF;AAGA,QAAM,sBAAsB,oBAAI,IAAiC;AACjE,aAAW,WAAW,UAAU;AAC9B,UAAM,WAAW,oBAAoB,IAAI,QAAQ,SAAS,KAAK,CAAC;AAChE,aAAS,KAAK,OAAO;AACrB,wBAAoB,IAAI,QAAQ,WAAW,QAAQ;AAAA,EACrD;AAEA,aAAW,CAAC,eAAe,iBAAiB,KAAK,oBAAoB,QAAQ,GAAG;AAC9E,UAAM,KAAK,cAAc,aAAa,EAAE;AACxC,UAAM,KAAK,IAAI,OAAO,EAAE,CAAC;AAEzB,aAAS,IAAI,GAAG,IAAI,kBAAkB,QAAQ,KAAK;AACjD,YAAM,UAAU,kBAAkB,CAAC;AACnC,YAAM,KAAK,KAAK,IAAI,CAAC,KAAK,QAAQ,OAAO,EAAE;AAE3C,UAAI,QAAQ,WAAW,OAAO,KAAK,QAAQ,OAAO,EAAE,SAAS,GAAG;AAC9D,cAAM,KAAK,iBAAiB,KAAK,UAAU,QAAQ,SAAS,MAAM,CAAC,CAAC,EAAE;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC3BA;AASA;;;AClHA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,iBAAAC,sBAAqB;AAG9B,IAAI,WAA0B;AAE9B,SAAS,aAAqB;AAC5B,MAAI,aAAa,MAAM;AACrB,QAAI;AACF,iBAAWD,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC;AAAA,IACxD,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,gBAAgB,MAAmC;AAGjE,QAAM,WAAWD,MAAK;AAAA,IACpB,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG,IAAI;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAUD,IAAG,aAAa,UAAU,MAAM;AAChD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,gCAAgC,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAClG;AAAA,EACF;AACF;AAKO,SAAS,2BAAqC;AAGnD,QAAM,cAAcC,MAAK,KAAK,WAAW,GAAG,aAAa,WAAW;AAEpE,MAAI;AACF,UAAM,QAAQD,IAAG,YAAY,WAAW;AACxC,WAAO,MACJ,OAAO,CAAC,SAAS,KAAK,SAAS,YAAY,CAAC,EAC5C,IAAI,CAAC,SAASC,MAAK,SAAS,MAAM,YAAY,CAAC,EAC/C,KAAK;AAAA,EACV,SAAS,OAAO;AACd,YAAQ,KAAK,2CAA2C,KAAK;AAC7D,WAAO,CAAC;AAAA,EACV;AACF;AAgBA,IAAM,gBAAqD,CAAC;AAErD,IAAM,WAAW,IAAI,MAAM,CAAC,GAA0C;AAAA,EAC3E,IAAI,SAAS,MAAc;AACzB,QAAI,CAAC,cAAc,IAAI,GAAG;AACxB,UAAI;AACF,sBAAc,IAAI,IAAI,gBAAgB,IAAI;AAAA,MAC5C,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO,cAAc,IAAI;AAAA,EAC3B;AAAA,EAEA,QAAQ,SAAS;AACf,WAAO,yBAAyB;AAAA,EAClC;AAAA,EAEA,IAAI,SAAS,MAAc;AACzB,WAAO,yBAAyB,EAAE,SAAS,IAAI;AAAA,EACjD;AACF,CAAC;AAKM,IAAM,aAAa,CACxB,gBACoC;AACpC,SAAO,SAAS,WAAW;AAC7B;AAKO,IAAM,kBAAkB,MAAgB;AAC7C,SAAO,yBAAyB;AAClC;;;AChHA,YAAYE,WAAU;AACtB,YAAYC,SAAQ;AAapB,eAAsB,WACpB,SACA,UAAgC,CAAC,GAClB;AACf,QAAM,EAAE,gBAAgB,WAAW,UAAU,KAAK,IAAI;AAEtD,MAAI,CAAC,QAAQ,OAAO;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,QAAM,cAAc,OAAO,QAAQ,MAAM,UAAU,KAAK,KAAK;AAC7D,QAAM,eACJ,kBAAkB,GAAG,YAAY,YAAY,EAAE,QAAQ,QAAQ,GAAG,CAAC;AAGrE,QAAM,mBAAwB,WAAK,QAAQ,IAAI,GAAG,UAAU,UAAU;AACtE,QAAM,iBAAiB,aAAa;AACpC,QAAM,WAAgB,WAAK,gBAAgB,YAAY;AAEvD,MAAI,SAAS;AACX,YAAQ,IAAI,OAAO,WAAW;AAAA,CAAmB;AACjD,YAAQ,IAAI,cAAc,WAAW,yBAAyB;AAAA,EAChE;AAEA,MAAI;AAEF,UAAS,aAAS,MAAM,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAE3D,UAAM,WAAW,MAAM,iBAAiB,OAAO;AAC/C,UAAM,aAAa,UAAU,QAAQ;AAErC,QAAI,SAAS;AACX,cAAQ,IAAI,UAAK,WAAW,WAAW,QAAQ,EAAE;AACjD,cAAQ,IAAI;AAAA,SAAO,WAAW,0BAA0B;AAAA,IAC1D;AAAA,EACF,SAAS,OAAO;AACd,QAAI,SAAS;AACX,cAAQ,MAAM,GAAG,WAAW,uBAAuB,KAAK;AAAA,IAC1D;AACA,UAAM;AAAA,EACR;AACF;;;ACzDA;AAMA,SAAS,wBAAAC,6BAA4B;;;ACXrC,SAAS,+BAA+B;;;ACIxC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE,oBAAoB;AAAA,OAEf;AAIP;AAAA,EACE;AAAA,EACA,4BAAAC;AAAA,EACA;AAAA,OACK;AAMA,SAAS,uBACd,QACA,OACA,eACA,MACyC;AAKzC,SAAO,6BAA2C,OAAO,aAAa,OAAO;AAAA,IAC3E,OAAO,MAAM,SAAS;AAAA,IACtB,eAAe,MAAM,iBAAiB;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAWO,SAAS,iBACd,UACA,kBACA,SACyC;AACzC,QAAM,mBAAmB,IAAI,IAAI,iBAAiB,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAGpE,QAAM,iBAAiB,wBAAwB,UAAU;AAAA,IACvD;AAAA,IACA,oBAAoB,SAAS;AAAA,EAC/B,CAAC;AAGD,QAAM,SAA4B,CAAC,GAAI,eAAe,UAAU,CAAC,CAAE;AAEnE,WAAS,mBAAmB,YAAmB,aAAa,YAAY;AACtE,eAAW,QAAQ,CAAC,eAAe,UAAU;AAC3C,YAAM,kBAAkB,iBAAiB;AAAA,QACvC,CAAC,OAAO,GAAG,SAAS,cAAc;AAAA,MACpC;AACA,UAAI,CAAC,iBAAiB;AACpB;AAAA,MACF;AAEA,YAAM,eAAe;AAAA,QACnB,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,cAAc;AAAA,MAChB;AAEA,YAAM,aAAa;AAAA,QACjB;AAAA,QACA,cAAc;AAAA,QACd,gBAAgB;AAAA;AAAA,QAEhB,EAAE,OAAO,SAAS,uBAAuB,KAAK;AAAA,MAChD;AAEA,UAAI,CAAC,WAAW,SAAS,WAAW,QAAQ;AAC1C,cAAM,gBAAgB,WAAW,OAAO;AAAA,UACtC,CAAC,WAA4B;AAAA,YAC3B,GAAG;AAAA,YACH,MAAM,GAAG,UAAU,IAAI,KAAK,KAAK,MAAM,IAAI;AAAA,UAC7C;AAAA,QACF;AACA,eAAO,KAAK,GAAG,aAAa;AAAA,MAC9B;AAEA,UAAI,cAAc,YAAY,MAAM,QAAQ,cAAc,QAAQ,GAAG;AACnE;AAAA,UACE,cAAc;AAAA,UACd,GAAG,UAAU,IAAI,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,UAAU;AACrB,uBAAmB,SAAS,QAAQ;AAAA,EACtC;AAEA,SAAO,OAAO,SAAS,IACnB,EAAE,SAAS,OAAO,QAAQ,OAAO,MAAM,IACvC,EAAE,SAAS,MAAM,QAAQ,CAAC,GAAG,OAAO,KAAK;AAC/C;AAKO,SAAS,kBACd,QACA,OACsB;AACtB,QAAM,aAAa,uBAAuB,QAAQ,KAAK;AAEvD,MAAI,CAAC,WAAW,OAAO;AACrB,UAAM,IAAI,yBAAyB,WAAW,UAAU,CAAC,GAAG,KAAK;AAAA,EACnE;AAEA,SAAO,WAAW;AACpB;AAMO,IAAM,sBAAsB;;;AF7GnC,SAAS,kCAAAC,uCAAsC;;;AG9B/C,SAAS,QAAAC,aAA8B;AACvC,SAAS,qBAAqB;AAE9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,qCAAqC;AAG9C,IAAM,cAAc,oBAAI,IAAqB;AAQtC,SAAS,6BACd,kBACA,4BAA4B,MACnB;AAET,QAAM,uBAAuB,iBAAiB,IAAI,CAAC,cAAc;AAC/D,UAAM,cAAc,OAAO,KAAK,UAAU,QAAQ;AAGlD,UAAM,iBAAiB,YAAY,IAAI,CAAC,OAAO;AAAA,MAC7C,SAAS;AAAA,MACT,aAAa,UAAU,SAAS,CAAC,EAAE;AAAA,MACnC,aAAa,UAAU,SAAS,CAAC,EAAE,gBAAgB;AAAA,MACnD,aAAa,UAAU,SAAS,CAAC,EAAE;AAAA,IACrC,EAAE;AAGF,UAAM,YAAY,YAAY,OAAO,CAAC,GAAG,MAAO,IAAI,IAAI,IAAI,CAAE;AAE9D,WAAO;AAAA,MACL,MAAM,UAAU;AAAA,MAChB,aAAa,UAAU,SAAS,SAAS,EAAE;AAAA,MAC3C,aAAa,YAAY;AAAA,QACvB,CAAC,MAAM,UAAU,SAAS,CAAC,EAAE,gBAAgB;AAAA,MAC/C;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,8BAA8B;AAAA,IACnC;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACH;AAkBA,eAAsB,mBACpB,kBACA,YACA,UAGI,CAAC,GACU;AACf,QAAM,EAAE,4BAA4B,MAAM,cAAc,KAAK,IAAI;AAEjE,QAAM,EAAE,qBAAqB,mBAAmB,IAAI,MAAM,OACxD,4CACF;AAEA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAEA,QAAM,aAAa,oBAAoB,QAAQ;AAAA,IAC7C,SAAS;AAAA,EACX,CAAC;AAED,QAAM,mBAAmB,YAAY,YAAY,EAAE,YAAY,CAAC;AAClE;AAMO,SAAS,yBACd,kBACyB;AACzB,QAAM,UAAmC,CAAC;AAE1C,aAAW,aAAa,kBAAkB;AACxC,UAAM,cAAc,OAAO,KAAK,UAAU,QAAQ;AAClD,UAAM,SAAS,cAAc,WAAW;AAExC,eAAW,KAAK,aAAa;AAC3B,YAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,YAAM,WAAW,aAAa,UAAU,IAAI,IAAI,CAAC;AAEjD,UAAI,YAAY,IAAI,QAAQ,GAAG;AAC7B,gBAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,EAAE,IAAI,YAAY,IAAI,QAAQ;AAAA,MAC9D,OAAO;AACL,cAAM,YAAY,MAAM;AACxB,cAAM,aAAa,UAAU,cAAc,CAAC;AAE5C,cAAM,uBAAgD;AAAA,UACpD,MAAMC,MAAK,QAAQ,UAAU,IAAI;AAAA,UACjC,SAASA,MAAK,SAASA,MAAK,QAAQ,CAAC,CAAC;AAAA,UACtC,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,UAC/B,GAAG;AAAA,QACL;AAEA,YAAI,MAAM,aAAa;AACrB,+BAAqB,WAAWA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,QACtE;AAEA,cAAM,kBAAkBA,MAAK,OAAO,oBAAoB;AACxD,oBAAY,IAAI,UAAU,eAAe;AACzC,gBAAQ,GAAG,UAAU,IAAI,IAAI,CAAC,EAAE,IAAI;AAAA,MACtC;AAAA,IACF;AAGA,UAAM,cAAc,UAAU,SAAS,MAAM;AAC7C,UAAM,kBAAkB,aAAa,UAAU,IAAI;AAEnD,QAAI,YAAY,IAAI,eAAe,GAAG;AACpC,cAAQ,UAAU,IAAI,IAAI,YAAY,IAAI,eAAe;AAAA,IAC3D,OAAO;AACL,YAAM,YAAY,YAAY;AAC9B,YAAM,aAAa,UAAU,cAAc,CAAC;AAE5C,YAAM,uBAAgD;AAAA,QACpD,MAAMA,MAAK,QAAQ,UAAU,IAAI;AAAA,QACjC,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,QAC/B,GAAG;AAAA,MACL;AAEA,UAAI,YAAY,aAAa;AAC3B,6BAAqB,WAAWA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,MACtE;AAEA,YAAM,kBAAkBA,MAAK,OAAO,oBAAoB;AACxD,kBAAY,IAAI,iBAAiB,eAAe;AAChD,cAAQ,UAAU,IAAI,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,aACd,kBACA,iBACyB;AACzB,QAAM,gBAAgB,yBAAyB,gBAAgB;AAE/D,MAAI,iBAAiB;AACnB,WAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAEA,QAAM,yBAAkD;AAAA,IACtD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,UAAUA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,IAChD,CAAC;AAAA,IACD,SAASA,MAAK,OAAO;AAAA,MACnB,MAAMA,MAAK,QAAQ,SAAS;AAAA,MAC5B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,MACP,UAAUA,MAAK,SAASA,MAAK,MAAMA,MAAK,IAAI,CAAC,CAAC;AAAA,IAChD,CAAC;AAAA,IACD,SAASA,MAAK,OAAO;AAAA,MACnB,MAAMA,MAAK,QAAQ,SAAS;AAAA,MAC5B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,MAAMA,MAAK,OAAO;AAAA,MAChB,MAAMA,MAAK,QAAQ,MAAM;AAAA,MACzB,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,OAAOA,MAAK,OAAO;AAAA,MACjB,MAAMA,MAAK,QAAQ,OAAO;AAAA,MAC1B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,IACD,OAAOA,MAAK,OAAO;AAAA,MACjB,MAAMA,MAAK,QAAQ,OAAO;AAAA,MAC1B,IAAIA,MAAK,SAASA,MAAK,OAAO,CAAC;AAAA,MAC/B,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;;;AHvIA,SAAS,kBAEP,OAA4D;AAE5D,QAAM,eAAe,IAAI,IAAI,MAAM,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAcrE,WAAS,qBACP,WACA,UACA,UACa;AACb,QAAI,MAAM,cAAc;AACtB,UAAI,MAAM,aAAa,SAAS,GAAG;AACjC,eAAO,MAAM,aAAa,SAAS;AAAA,MACrC;AACA,YAAM,MAAM,OAAO,KAAK,MAAM,YAAY,EAAE;AAAA,QAC1C,CAAC,MAAM,EAAE,YAAY,MAAM,UAAU,YAAY;AAAA,MACnD;AACA,UAAI,KAAK;AACP,eAAO,MAAM,aAAa,GAAG;AAAA,MAC/B;AAAA,IACF;AACA,QAAI,YAAY,SAAS,SAAS,GAAG;AACnC,aAAO,oBAAoB,WAAW;AAAA,QACpC,cAAc,MAAM;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AACA,QAAI,MAAM,OAAO;AACf,aAAO,MAAM;AAAA,IACf;AACA,WAAO,oBAAoB,WAAW;AAAA,MACpC,cAAc,MAAM;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AAaA,iBAAe,0BACb,YACA,aACA,mBACA,eACA,iBAGA,QAAQ,GAIP;AACD,QAAI,QAAQ,IAAI;AACd,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,cAAqC,CAAC;AAC5C,UAAM,eAAsC,CAAC;AAE7C,eAAW,iBAAiB,YAAY;AAEtC,YAAM,gBAAiB,eAAqC;AAE5D,UAAI,CAAC,eAAe;AAClB,oBAAY,KAAK,aAAa;AAC9B,qBAAa,KAAK,aAAa;AAC/B;AAAA,MACF;AAEA,YAAM,kBAAkB,aAAa,IAAI,aAAa;AAEtD,UAAI,iBAAiB;AAEnB,YAAI;AACF,gBAAM,oBAAoB;AAO1B,cAAI,CAAC,kBAAkB,OAAO;AAC5B,kBAAM,IAAI;AAAA,cACR,qBAAqB,aAAa,wDAAwD,aAAa;AAAA,YACzG;AAAA,UACF;AAGA,gBAAM,eAAe;AAAA,YACnB,gBAAgB;AAAA,YAChB,gBAAgB;AAAA,YAChB,kBAAkB;AAAA,UACpB;AAGA,gBAAM,eAAe;AAAA,YACnB;AAAA,YACA,kBAAkB;AAAA,UACpB;AAIA,cAAI;AACJ,cACE,kBAAkB,YAClB,MAAM,QAAQ,kBAAkB,QAAQ,GACxC;AACA,kBAAM,SAAS,MAAM;AAAA,cACnB,kBAAkB;AAAA,cAClB;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ;AAAA,YACV;AACA,6BAAiB,OAAO;AAAA,UAC1B;AAGA,gBAAM,eAAe,kBAAkB,UACnC,GAAG,gBAAgB,IAAI,IAAI,kBAAkB,OAAO,KACpD,gBAAgB;AAEpB,gBAAM,aAAa,CACjB,SACA,YACG;AACH,8BAAkB,KAAK;AAAA,cACrB,WAAW;AAAA,cACX;AAAA,cACA,UAAU;AAAA,cACV;AAAA,YACF,CAAC;AAAA,UACH;AAGA,gBAAM,SAAS,MAAM,aAAa,OAAO;AAAA,YACvC,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,YACA,UAAU;AAAA,UACZ,CAAC;AAGD,gBAAM,mBACJ,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAQ1C,cAAI,iBAAiB;AACnB,4BAAgB,kBAAkB,YAAY;AAAA,UAChD;AAGA,gBAAM,kBAAkB,MAAM;AAAA,YAC5B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,sBAAY,KAAK,GAAG,gBAAgB,QAAQ;AAE5C,cAAI,eAAe,YAAY,IAAI,aAAa,GAAG;AAIjD,yBAAa,KAAK,aAAa;AAAA,UACjC,OAAO;AAGL,yBAAa,KAAK,GAAG,gBAAgB,SAAS;AAAA,UAChD;AAEA,cAAI,MAAM,OAAO;AACf,oBAAQ;AAAA,cACN,+BAA+B,YAAY;AAAA,cAC3C,gBAAgB;AAAA,YAClB;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AACd,cAAI,iBAAiBC,2BAA0B;AAC7C,kBAAM;AAAA,UACR;AACA,gBAAM,IAAI;AAAA,YACR,sCAAsC,gBAAgB,IAAI,MACxD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CACvD;AAAA,UACF;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YACE,cAAc,iBACd,MAAM,QAAQ,cAAc,QAAQ,GACpC;AACA,gBAAM,kBAAkB,MAAM;AAAA,YAC5B,cAAc;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AACA,sBAAY,KAAK;AAAA,YACf,GAAG;AAAA,YACH,UAAU,gBAAgB;AAAA,UAC5B,CAAC;AACD,uBAAa,KAAK;AAAA,YAChB,GAAG;AAAA,YACH,UAAU,gBAAgB;AAAA,UAC5B,CAAC;AAAA,QACH,OAAO;AACL,sBAAY,KAAK,aAAa;AAC9B,uBAAa,KAAK,aAAa;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,aAAa,WAAW,aAAa;AAAA,EAC1D;AAKA,WAAS,aACP,WACoE;AACpE,QAAI,CAAC,UAAU,MAAM;AACnB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,QAAI,MAAM,eAAe,IAAI,UAAU,IAAI,GAAG;AAC5C,YAAM,IAAI,wBAAwB,UAAU,IAAI;AAAA,IAClD;AAGA,UAAM,oBAAoB,IAAI,IAAI,MAAM,cAAc;AACtD,sBAAkB,IAAI,UAAU,IAAI;AAEpC,UAAM,WAAyB;AAAA,MAC7B,YAAY,CAAC,GAAG,MAAM,YAAY,SAAS;AAAA,MAC3C,gBAAgB;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM;AAAA,MAChB,OAAO,MAAM;AAAA,MACb,YAAY,MAAM;AAAA,MAClB,eAAe,MAAM;AAAA,MACrB,aAAa,MAAM;AAAA,MACnB,SAAS,MAAM;AAAA,IACjB;AAGA,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAOA,WAAS,mBACP,SACiC;AACjC,UAAM,OAAO,SAAS;AACtB,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,aAAO;AAAA,IACT;AACA,UAAM,aAAa,IAAI,IAAI,MAAM,cAAc;AAC/C,UAAM,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;AACrD,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAIC;AAAA,QACR;AAAA,QACA,MAAM,KAAK,MAAM,cAAc;AAAA,MACjC;AAAA,IACF;AACA,WAAO,IAAI,IAAI,IAAI;AAAA,EACrB;AAQA,iBAAe,eACb,UACA,SAYC;AACD,UAAM,cAAc,mBAAmB,OAAO;AAO9C,UAAM,SAAS;AACf,UAAM,mBACJ,OAAO,UAAU,SAAY,EAAE,GAAG,QAAQ,OAAO,CAAC,EAAE,IAAI;AAK1D,UAAM,QAAqC;AAAA,MACzC,GAAG,MAAM;AAAA,MACT,GAAG,SAAS;AAAA,IACd;AACA,QAAI,MAAM,YAAY,OAAO;AAC3B,YAAM,SAAS;AAAA,QACb;AAAA,QACA,MAAM;AAAA,QACN,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,MACjD;AACA,UAAI,CAAC,OAAO,OAAO;AACjB,cAAM,IAAID;AAAA,WACP,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,YAChC,MAAM,EAAE,QAAQ;AAAA,YAChB,SAAS,EAAE;AAAA,UACb,EAAE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAUA,UAAM,kBACJ,MAAM,YAAY,QACd,SACA,CAAC,SAAgC,mBAA2B;AAC1D,YAAM,SAAS;AAAA,QACb,EAAE,GAAG,kBAAkB,UAAU,QAAQ;AAAA,QACzC,MAAM;AAAA,QACN,EAAE,oBAAoB,MAAM,mBAAmB;AAAA,MACjD;AACA,UAAI,CAAC,OAAO,OAAO;AACjB,cAAM,IAAIA;AAAA,WACP,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,YAChC,MAAM,EAAE,QAAQ;AAAA,YAChB,SAAS,qBAAqB,cAAc,mCAA8B,EAAE,OAAO;AAAA,UACrF,EAAE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGN,UAAM,WAAgC,CAAC;AASvC,UAAM;AAAA,MACJ,UAAU;AAAA,MACV,OAAO;AAAA,MACP;AAAA,IACF,IAAI,oBAAoB,kBAAkB;AAAA,MACxC,cAAc,MAAM;AAAA,MACpB,OAAO,MAAM;AAAA,MACb;AAAA,MACA,mBAAmB;AAAA,IACrB,CAAC;AAID,UAAM,YAAY,MAAM;AAAA,MACtB,UAAU,YAAY,CAAC;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,oBAA+C;AAAA,MACnD,GAAG;AAAA,MACH,UAAU,UAAU;AAAA,IACtB;AAIA,UAAM,CAAC,QAAQ,IAAI,kBAAkB,iBAAiB;AAEtD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAUA,iBAAe,yBACb,UACA,SACmC;AACnC,QAAI;AACF,YAAM,EAAE,UAAU,SAAS,IAAI,MAAM,eAAe,UAAU,OAAO;AACrE,aAAO;AAAA,QACL,oBAAoB;AAAA,QACpB,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,MAC7C;AAAA,IACF,SAAS,OAAO;AACd,UAAI,MAAM,OAAO;AACf,gBAAQ,MAAM,6BAA6B,KAAK;AAAA,MAClD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAKA,iBAAe,SACb,UACA,SACwC;AACxC,QAAI;AACF,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI,MAAM,eAAe,UAAU,OAAO;AAU1C,YAAM,YAAY,mBAAmB,QAAQ,EAAE,SAAS;AACxD,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF;AAIA,YAAM,cAAc,YAChBE,sBAAqB,eAAe,QAAQ,IAC5C,CAAC;AAGL,YAAM,iBAAiB;AAAA,QACrB,eAAe,SAAS,iBAAiB,MAAM;AAAA,QAC/C,aAAa,SAAS,eAAe,MAAM;AAAA,MAC7C;AACA,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA,sBAAsB,cAAc;AAAA,MACtC;AACA,YAAM,SAAS,YAAY,UAAU,UAAU,YAAY,SAAS;AACpE,YAAM,oBAAoB,MAAM,eAAe,WAAW,QAAQ;AAAA,QAChE,UAAU,MAAM;AAAA,QAChB,aAAa,CAAC,MAAM;AAAA,QACpB,SAAS,SAAS,WAAW,MAAM;AAAA,QACnC,GAAI,YAAY,SAAS,KAAK,EAAE,YAAY;AAAA,MAC9C,CAAC;AAKD,YAAM,sBAAsB,cACvB;AAAA,QACC,GAAG;AAAA,QACH,UAAU,UAAU;AAAA,MACtB,IACA;AAEJ,aAAO;AAAA,QACL,UAAU;AAAA,QACV,UAAU,SAAS,SAAS,IAAI,WAAW;AAAA,QAC3C,oBAAoB;AAAA,QACpB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,MAAM,OAAO;AACf,gBAAQ,MAAM,8BAA8B,KAAK;AAAA,MACnD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAKA,iBAAe,eACb,UACA,SAC8C;AAC9C,UAAM;AAAA,MACJ,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI,MAAM,SAAS,UAAU,OAAO;AACpC,UAAM,SAAS,MAAM,gBAAgB,KAAK;AAAA,MACxC,eAAe,SAAS,iBAAiB,MAAM;AAAA,MAC/C,aAAa,SAAS,eAAe,MAAM;AAAA,IAC7C,CAAC;AACD,WAAO,EAAE,QAAQ,UAAU,oBAAoB,oBAAoB;AAAA,EACrE;AAKA,iBAAe,aACb,UACA,YACA,SAC4C;AAC5C,UAAM,EAAE,QAAQ,UAAU,oBAAoB,oBAAoB,IAChE,MAAM,eAAe,UAAU,OAAO;AACxC,UAAMC,MAAK,MAAM,OAAO,aAAa;AACrC,UAAMA,IAAG,UAAU,YAAY,IAAI,WAAW,MAAM,CAAC;AAErD,QAAI;AACJ,QAAI,wBAAwB,QAAW;AACrC,YAAMC,QAAO,MAAM,OAAO,MAAM;AAChC,4BACE,SAAS,wBACR,MAAM;AACL,cAAM,MAAMA,MAAK,QAAQ,UAAU;AACnC,cAAM,OAAO,MAAM,WAAW,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI;AACtD,eAAO,GAAG,IAAI;AAAA,MAChB,GAAG;AACL,YAAMD,IAAG;AAAA,QACP;AAAA,QACA,KAAK,UAAU,qBAAqB,MAAM,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAKA,WAAS,oBAA8B;AACrC,WAAO,MAAM,KAAK,MAAM,cAAc;AAAA,EACxC;AAKA,WAAS,SACP,UACkB;AAClB,QAAI;AAEF,YAAM,mBAAmB;AACzB,YAAM,SAAS;AAAA,QACb;AAAA,QACA,MAAM;AAAA,MACR;AACA,UAAI,OAAO,OAAO;AAChB,eAAO,EAAE,OAAO,KAAK;AAAA,MACvB;AACA,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC,OAAO;AAAA,UACxC,MAAM,EAAE,QAAQ;AAAA,UAChB,SAAS,EAAE;AAAA,QACb,EAAE;AAAA,MACJ;AAAA,IACF,SAAS,OAAO;AACd,aAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,UACN;AAAA,YACE,MAAM;AAAA,YACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAChE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAQA,iBAAe,gCACb,UACoC;AACpC,UAAM,EAAE,mBAAmB,IAAI,MAAM,SAAS,QAAQ;AACtD,WAAO;AAAA,EACT;AAKA,WAAS,eAAe,4BAA4B,MAAe;AACjE,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAKA,iBAAe,mBACb,YACA,SAIe;AACf,UAAM;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,SAAO,OAAO,OAAO;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAKO,SAAS,wBACd,SACuC;AACvC,QAAM,eAA6B;AAAA,IACjC,YAAY,CAAC;AAAA,IACb,gBAAgB,oBAAI,IAAI;AAAA,IACxB,OAAO,QAAQ;AAAA,IACf,cAAc,QAAQ;AAAA,IACtB,OAAO,QAAQ,SAAS;AAAA,IACxB,aAAa,QAAQ,eAAe;AAAA,IACpC,UAAU,QAAQ;AAAA,IAClB,OAAO,QAAQ;AAAA,IACf,YAAY,QAAQ;AAAA,IACpB,eAAe,QAAQ,iBAAiB;AAAA,IACxC,aAAa,QAAQ;AAAA,IACrB,SAAS,QAAQ;AAAA,EACnB;AAEA,SAAO,kBAA+B,YAAY;AACpD;;;AH/zBO,SAAS,iBAAyB;AACvC,SAAO;AACT;","names":["themes","path","fs","path","isValidThemeConfig","resolve","mergeWithDefaults","mergeWithDefaults","Paragraph","TextRun","AlignmentType","BookmarkStart","BookmarkEnd","path","createHash","TextRun","TextRun","TextRun","createTextRunsWithNewlines","TextRun","AsyncLocalStorage","AsyncLocalStorage","TextRun","createHash","Paragraph","TextRun","AlignmentType","BorderStyle","PageNumber","AsyncLocalStorage","TextRun","TextRun","AsyncLocalStorage","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","AsyncLocalStorage","text","format","Table","TableRow","TableCell","WidthType","TableLayoutType","BorderStyle","convertBorders","Paragraph","Paragraph","convertBorders","cellChildren","childContext","styleCfg","cellOpts","row","TableRow","TableCell","table","Table","TableLayoutType","WidthType","config","Paragraph","AsyncLocalStorage","createState","Paragraph","Paragraph","Table","TableRow","TableCell","WidthType","BorderStyle","VerticalAlign","TableLayoutType","Paragraph","TableCell","WidthType","VerticalAlign","BorderStyle","TableRow","Table","TableLayoutType","Paragraph","AlignmentType","TextRun","createHash","createHash","clampVisualDpi","DEFAULT_VISUAL_DPI","resolve","serverUrl","clampVisualDpi","DEFAULT_VISUAL_DPI","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"]}