@hirokisakabe/pom 8.2.1 → 8.3.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/README.md +24 -24
- package/dist/autoFit/autoFit.js.map +1 -1
- package/dist/buildContext.js +3 -1
- package/dist/buildContext.js.map +1 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +4 -0
- package/dist/buildPptx.js.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +2 -1
- package/dist/calcYogaLayout/calcYogaLayout.js.map +1 -1
- package/dist/calcYogaLayout/fontLoader.js.map +1 -1
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +9 -2
- package/dist/calcYogaLayout/measureText.js.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/icons/renderIcon.js.map +1 -1
- package/dist/parseMasterPptx.js.map +1 -1
- package/dist/parseXml/coercionRules.js +6 -2
- package/dist/parseXml/coercionRules.js.map +1 -1
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js +11 -8
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.d.ts.map +1 -1
- package/dist/parseXml/serializeXml.js +1 -0
- package/dist/parseXml/serializeXml.js.map +1 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/registry/definitions/shape.js.map +1 -1
- package/dist/registry/definitions/text.js +3 -1
- package/dist/registry/definitions/text.js.map +1 -1
- package/dist/renderPptx/gradientFills.js +139 -0
- package/dist/renderPptx/gradientFills.js.map +1 -0
- package/dist/renderPptx/nodes/icon.js.map +1 -1
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +18 -14
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/nodes/tree.js.map +1 -1
- package/dist/renderPptx/renderPptx.js +6 -2
- package/dist/renderPptx/renderPptx.js.map +1 -1
- package/dist/renderPptx/textOptions.js +2 -1
- package/dist/renderPptx/textOptions.js.map +1 -1
- package/dist/renderPptx/utils/backgroundBorder.js +6 -4
- package/dist/renderPptx/utils/backgroundBorder.js.map +1 -1
- package/dist/shared/gradient.js +103 -0
- package/dist/shared/gradient.js.map +1 -0
- package/dist/shared/measureImage.js.map +1 -1
- package/dist/shared/tableUtils.js.map +1 -1
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +8 -2
- package/dist/types.js.map +1 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coercionRules.js","names":[],"sources":["../../src/parseXml/coercionRules.ts"],"sourcesContent":["/**\n * 明示的な型変換ルール定義\n *\n * Zod の内部構造(_def)に依存せず、XML 属性値の文字列→適切な型への変換ルールを\n * 静的に定義する。各ノードタイプ・子要素タイプごとに変換テーブルを持つ。\n */\n\n// ===== CoercionRule 型定義 =====\nexport type CoercionRule =\n | \"number\"\n | \"boolean\"\n | \"string\" // string, enum を含む\n | \"json\" // array, object, record, tuple → JSON.parse\n | { type: \"literal\"; value: string | number | boolean }\n | { type: \"union\"; options: CoercionRule[] }\n | { type: \"object\"; shape: Record<string, CoercionRule> };\n\n// ===== 変換関数 =====\n\nexport function coerceWithRule(\n value: string,\n rule: CoercionRule,\n): { value: unknown; error: string | null } {\n if (rule === \"number\") {\n if (value === \"\") {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to number`,\n };\n }\n const num = Number(value);\n if (isNaN(num)) {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to number`,\n };\n }\n return { value: num, error: null };\n }\n if (rule === \"boolean\") {\n if (value !== \"true\" && value !== \"false\") {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to boolean (expected \"true\" or \"false\")`,\n };\n }\n return { value: value === \"true\", error: null };\n }\n if (rule === \"string\") {\n return { value, error: null };\n }\n if (rule === \"json\") {\n try {\n return { value: JSON.parse(value), error: null };\n } catch {\n return {\n value: undefined,\n error: `Cannot parse JSON value: \"${value}\"`,\n };\n }\n }\n // オブジェクト型のルール\n if (rule.type === \"literal\") {\n return { value: rule.value, error: null };\n }\n if (rule.type === \"union\") {\n return { value: coerceUnionWithRules(value, rule.options), error: null };\n }\n if (rule.type === \"object\") {\n try {\n return { value: JSON.parse(value), error: null };\n } catch {\n return {\n value: undefined,\n error: `Cannot parse JSON value: \"${value}\"`,\n };\n }\n }\n return { value: coerceFallback(value), error: null };\n}\n\nexport function coerceUnionWithRules(\n value: string,\n options: CoercionRule[],\n): unknown {\n // boolean を試行\n if ((value === \"true\" || value === \"false\") && options.includes(\"boolean\")) {\n return value === \"true\";\n }\n\n // number を試行\n if (options.includes(\"number\")) {\n const num = Number(value);\n if (!isNaN(num) && value !== \"\") {\n return num;\n }\n }\n\n // literal を試行\n for (const opt of options) {\n if (typeof opt === \"object\" && opt.type === \"literal\") {\n if (`${opt.value as string | number}` === value) return opt.value;\n }\n }\n\n // object/json を試行(JSON パース)\n if (\n options.some(\n (opt) =>\n opt === \"json\" || (typeof opt === \"object\" && opt.type === \"object\"),\n )\n ) {\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch {\n /* ignore */\n }\n }\n }\n\n // string にフォールバック\n return value;\n}\n\nexport function coerceFallback(value: string): unknown {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n const num = Number(value);\n if (value !== \"\" && !isNaN(num)) return num;\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch {\n /* ignore */\n }\n }\n return value;\n}\n\n/**\n * CoercionRule からオブジェクト型の shape を取得する。\n * dot notation の展開で使用。\n */\nexport function getObjectShapeFromRule(\n rule: CoercionRule,\n): Record<string, CoercionRule> | undefined {\n if (typeof rule === \"object\" && rule.type === \"object\") {\n return rule.shape;\n }\n if (typeof rule === \"object\" && rule.type === \"union\") {\n const objectOpt = rule.options.find(\n (opt): opt is { type: \"object\"; shape: Record<string, CoercionRule> } =>\n typeof opt === \"object\" && opt.type === \"object\",\n );\n return objectOpt?.shape;\n }\n return undefined;\n}\n\n/**\n * boolean と object の union かどうかを判定する。\n * endArrow=\"true\" と endArrow.type=\"triangle\" の共存を許可するために使用。\n */\nexport function isBooleanObjectUnionRule(rule: CoercionRule): boolean {\n if (typeof rule === \"string\") return false;\n if (rule.type !== \"union\") return false;\n const hasBoolean = rule.options.includes(\"boolean\");\n const hasObject = rule.options.some(\n (opt) => typeof opt === \"object\" && opt.type === \"object\",\n );\n return hasBoolean && hasObject;\n}\n\ntype ResolvedMixedNotationShorthand =\n | { mode: \"merge\"; value: Record<string, unknown> }\n | { mode: \"ignore\" }\n | { mode: \"conflict\" };\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isDirectionalBoxShape(shape: Record<string, CoercionRule>): boolean {\n const keys = Object.keys(shape).sort();\n return (\n keys.length === 4 &&\n keys[0] === \"bottom\" &&\n keys[1] === \"left\" &&\n keys[2] === \"right\" &&\n keys[3] === \"top\"\n );\n}\n\n/**\n * 同一属性で shorthand と dot notation を併用したときに、\n * shorthand 側をどのように扱うかを解決する。\n *\n * - merge: shorthand をオブジェクト化して dot notation 側で上書き\n * - ignore: boolean shorthand を無視して dot notation を優先\n * - conflict: 併用不可(従来どおりエラー)\n */\nexport function resolveMixedNotationShorthand(\n value: string,\n rule: CoercionRule,\n): ResolvedMixedNotationShorthand {\n const objectShape = getObjectShapeFromRule(rule);\n if (!objectShape) return { mode: \"conflict\" };\n\n if (\n isBooleanObjectUnionRule(rule) &&\n (value === \"true\" || value === \"false\")\n ) {\n return { mode: \"ignore\" };\n }\n\n const coerced = coerceWithRule(value, rule);\n if (coerced.error !== null) return { mode: \"conflict\" };\n\n if (isPlainObject(coerced.value)) {\n return { mode: \"merge\", value: coerced.value };\n }\n\n if (typeof coerced.value === \"number\" && isDirectionalBoxShape(objectShape)) {\n return {\n mode: \"merge\",\n value: {\n top: coerced.value,\n right: coerced.value,\n bottom: coerced.value,\n left: coerced.value,\n },\n };\n }\n\n return { mode: \"conflict\" };\n}\n\n// ===== 共通変換ルール =====\n\nconst LENGTH_RULE: CoercionRule = {\n type: \"union\",\n options: [\"number\", { type: \"literal\", value: \"max\" }, \"string\"],\n};\n\nconst PADDING_RULE: CoercionRule = {\n type: \"union\",\n options: [\n \"number\",\n {\n type: \"object\",\n shape: {\n top: \"number\",\n right: \"number\",\n bottom: \"number\",\n left: \"number\",\n },\n },\n ],\n};\n\nconst BORDER_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\", dashType: \"string\" },\n};\n\nconst FILL_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", transparency: \"number\" },\n};\n\nconst SHADOW_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: {\n type: \"string\",\n opacity: \"number\",\n blur: \"number\",\n angle: \"number\",\n offset: \"number\",\n color: \"string\",\n },\n};\n\nconst UNDERLINE_RULE: CoercionRule = {\n type: \"union\",\n options: [\n \"boolean\",\n { type: \"object\", shape: { style: \"string\", color: \"string\" } },\n ],\n};\n\nconst LINE_ARROW_RULE: CoercionRule = {\n type: \"union\",\n options: [\"boolean\", { type: \"object\", shape: { type: \"string\" } }],\n};\n\nconst BACKGROUND_IMAGE_RULE: CoercionRule = {\n type: \"object\",\n shape: { src: \"string\", sizing: \"string\" },\n};\n\nconst TREE_CONNECTOR_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\" },\n};\n\nconst FLOW_CONNECTOR_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\", arrowType: \"string\" },\n};\n\nconst IMAGE_SIZING_RULE: CoercionRule = {\n type: \"object\",\n shape: {\n type: \"string\",\n w: \"number\",\n h: \"number\",\n x: \"number\",\n y: \"number\",\n },\n};\n\n// ===== Base node 属性 =====\nconst BASE_RULES: Record<string, CoercionRule> = {\n id: \"string\",\n w: LENGTH_RULE,\n h: LENGTH_RULE,\n minW: \"number\",\n maxW: \"number\",\n minH: \"number\",\n maxH: \"number\",\n padding: PADDING_RULE,\n margin: PADDING_RULE,\n backgroundColor: \"string\",\n backgroundImage: BACKGROUND_IMAGE_RULE,\n border: BORDER_STYLE_RULE,\n borderRadius: \"number\",\n opacity: \"number\",\n zIndex: \"number\",\n position: \"string\",\n top: \"number\",\n right: \"number\",\n bottom: \"number\",\n left: \"number\",\n alignSelf: \"string\",\n shadow: SHADOW_STYLE_RULE,\n};\n\n// テキスト系の共通属性\nconst TEXT_STYLE_RULES: Record<string, CoercionRule> = {\n fontSize: \"number\",\n color: \"string\",\n textAlign: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n lineHeight: \"number\",\n};\n\n// ===== ノードタイプ別の変換ルールマップ =====\nexport const NODE_COERCION_MAP: Record<string, Record<string, CoercionRule>> = {\n text: {\n ...BASE_RULES,\n text: \"string\",\n ...TEXT_STYLE_RULES,\n },\n ul: {\n ...BASE_RULES,\n items: \"json\",\n ...TEXT_STYLE_RULES,\n },\n ol: {\n ...BASE_RULES,\n items: \"json\",\n ...TEXT_STYLE_RULES,\n numberType: \"string\",\n numberStartAt: \"number\",\n },\n image: {\n ...BASE_RULES,\n src: \"string\",\n sizing: IMAGE_SIZING_RULE,\n },\n icon: {\n ...BASE_RULES,\n name: \"string\",\n size: \"number\",\n color: \"string\",\n variant: \"string\",\n bgColor: \"string\",\n },\n svg: {\n ...BASE_RULES,\n color: \"string\",\n },\n table: {\n ...BASE_RULES,\n columns: \"json\",\n rows: \"json\",\n defaultRowHeight: \"number\",\n cellBorder: BORDER_STYLE_RULE,\n },\n shape: {\n ...BASE_RULES,\n shapeType: \"string\",\n text: \"string\",\n fill: FILL_STYLE_RULE,\n line: BORDER_STYLE_RULE,\n ...TEXT_STYLE_RULES,\n },\n chart: {\n ...BASE_RULES,\n chartType: \"string\",\n data: \"json\",\n showLegend: \"boolean\",\n showTitle: \"boolean\",\n title: \"string\",\n chartColors: \"json\",\n radarStyle: \"string\",\n },\n timeline: {\n ...BASE_RULES,\n direction: \"string\",\n items: \"json\",\n },\n matrix: {\n ...BASE_RULES,\n axes: \"json\",\n quadrants: \"json\",\n items: \"json\",\n },\n tree: {\n ...BASE_RULES,\n layout: \"string\",\n nodeShape: \"string\",\n data: \"json\",\n connectorStyle: TREE_CONNECTOR_STYLE_RULE,\n nodeWidth: \"number\",\n nodeHeight: \"number\",\n levelGap: \"number\",\n siblingGap: \"number\",\n },\n flow: {\n ...BASE_RULES,\n direction: \"string\",\n nodes: \"json\",\n connections: \"json\",\n connectorStyle: FLOW_CONNECTOR_STYLE_RULE,\n nodeWidth: \"number\",\n nodeHeight: \"number\",\n nodeGap: \"number\",\n },\n processArrow: {\n ...BASE_RULES,\n direction: \"string\",\n steps: \"json\",\n itemWidth: \"number\",\n itemHeight: \"number\",\n gap: \"number\",\n fontSize: \"number\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n },\n pyramid: {\n ...BASE_RULES,\n direction: \"string\",\n levels: \"json\",\n fontSize: \"number\",\n bold: \"boolean\",\n fontFamily: \"string\",\n },\n line: {\n ...BASE_RULES,\n x1: \"number\",\n y1: \"number\",\n x2: \"number\",\n y2: \"number\",\n color: \"string\",\n lineWidth: \"number\",\n dashType: \"string\",\n beginArrow: LINE_ARROW_RULE,\n endArrow: LINE_ARROW_RULE,\n },\n arrow: {\n ...BASE_RULES,\n from: \"string\",\n to: \"string\",\n color: \"string\",\n lineWidth: \"number\",\n dashType: \"string\",\n beginArrow: LINE_ARROW_RULE,\n endArrow: LINE_ARROW_RULE,\n },\n // コンテナノード\n vstack: {\n ...BASE_RULES,\n gap: \"number\",\n alignItems: \"string\",\n justifyContent: \"string\",\n flexWrap: \"string\",\n },\n hstack: {\n ...BASE_RULES,\n gap: \"number\",\n alignItems: \"string\",\n justifyContent: \"string\",\n flexWrap: \"string\",\n },\n layer: {\n ...BASE_RULES,\n },\n};\n\n// ===== 子要素の変換ルールマップ =====\nexport const CHILD_ELEMENT_COERCION_MAP: Record<\n string,\n Record<string, CoercionRule>\n> = {\n ProcessArrowStep: {\n label: \"string\",\n color: \"string\",\n textColor: \"string\",\n },\n PyramidLevel: {\n label: \"string\",\n color: \"string\",\n textColor: \"string\",\n },\n TimelineItem: {\n date: \"string\",\n title: \"string\",\n description: \"string\",\n color: \"string\",\n },\n MatrixAxes: {\n x: \"string\",\n y: \"string\",\n },\n MatrixQuadrants: {\n topLeft: \"string\",\n topRight: \"string\",\n bottomLeft: \"string\",\n bottomRight: \"string\",\n },\n MatrixItem: {\n label: \"string\",\n x: \"number\",\n y: \"number\",\n color: \"string\",\n },\n FlowNode: {\n id: \"string\",\n shape: \"string\",\n text: \"string\",\n color: \"string\",\n textColor: \"string\",\n width: \"number\",\n height: \"number\",\n },\n FlowConnection: {\n from: \"string\",\n to: \"string\",\n label: \"string\",\n color: \"string\",\n },\n Col: {\n width: \"number\",\n },\n Td: {\n text: \"string\",\n fontSize: \"number\",\n color: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n textAlign: \"string\",\n backgroundColor: \"string\",\n colspan: \"number\",\n rowspan: \"number\",\n },\n Li: {\n text: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n color: \"string\",\n fontSize: \"number\",\n fontFamily: \"string\",\n },\n B: {},\n I: {},\n Span: { color: \"string\", fontFamily: \"string\" },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"coercionRules.js","names":[],"sources":["../../src/parseXml/coercionRules.ts"],"sourcesContent":["/**\n * 明示的な型変換ルール定義\n *\n * Zod の内部構造(_def)に依存せず、XML 属性値の文字列→適切な型への変換ルールを\n * 静的に定義する。各ノードタイプ・子要素タイプごとに変換テーブルを持つ。\n */\n\n// ===== CoercionRule 型定義 =====\nexport type CoercionRule =\n | \"number\"\n | \"boolean\"\n | \"string\" // string, enum を含む\n | \"json\" // array, object, record, tuple → JSON.parse\n | { type: \"literal\"; value: string | number | boolean }\n | { type: \"union\"; options: CoercionRule[] }\n | { type: \"object\"; shape: Record<string, CoercionRule> };\n\n// ===== 変換関数 =====\n\nexport function coerceWithRule(\n value: string,\n rule: CoercionRule,\n): { value: unknown; error: string | null } {\n if (rule === \"number\") {\n if (value === \"\") {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to number`,\n };\n }\n const num = Number(value);\n if (isNaN(num)) {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to number`,\n };\n }\n return { value: num, error: null };\n }\n if (rule === \"boolean\") {\n if (value !== \"true\" && value !== \"false\") {\n return {\n value: undefined,\n error: `Cannot convert \"${value}\" to boolean (expected \"true\" or \"false\")`,\n };\n }\n return { value: value === \"true\", error: null };\n }\n if (rule === \"string\") {\n return { value, error: null };\n }\n if (rule === \"json\") {\n try {\n return { value: JSON.parse(value), error: null };\n } catch {\n return {\n value: undefined,\n error: `Cannot parse JSON value: \"${value}\"`,\n };\n }\n }\n // オブジェクト型のルール\n if (rule.type === \"literal\") {\n return { value: rule.value, error: null };\n }\n if (rule.type === \"union\") {\n return { value: coerceUnionWithRules(value, rule.options), error: null };\n }\n if (rule.type === \"object\") {\n try {\n return { value: JSON.parse(value), error: null };\n } catch {\n return {\n value: undefined,\n error: `Cannot parse JSON value: \"${value}\"`,\n };\n }\n }\n return { value: coerceFallback(value), error: null };\n}\n\nexport function coerceUnionWithRules(\n value: string,\n options: CoercionRule[],\n): unknown {\n // boolean を試行\n if ((value === \"true\" || value === \"false\") && options.includes(\"boolean\")) {\n return value === \"true\";\n }\n\n // number を試行\n if (options.includes(\"number\")) {\n const num = Number(value);\n if (!isNaN(num) && value !== \"\") {\n return num;\n }\n }\n\n // literal を試行\n for (const opt of options) {\n if (typeof opt === \"object\" && opt.type === \"literal\") {\n if (`${opt.value as string | number}` === value) return opt.value;\n }\n }\n\n // object/json を試行(JSON パース)\n if (\n options.some(\n (opt) =>\n opt === \"json\" || (typeof opt === \"object\" && opt.type === \"object\"),\n )\n ) {\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch {\n /* ignore */\n }\n }\n }\n\n // string にフォールバック\n return value;\n}\n\nexport function coerceFallback(value: string): unknown {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n const num = Number(value);\n if (value !== \"\" && !isNaN(num)) return num;\n if (value.startsWith(\"{\") || value.startsWith(\"[\")) {\n try {\n return JSON.parse(value);\n } catch {\n /* ignore */\n }\n }\n return value;\n}\n\n/**\n * CoercionRule からオブジェクト型の shape を取得する。\n * dot notation の展開で使用。\n */\nexport function getObjectShapeFromRule(\n rule: CoercionRule,\n): Record<string, CoercionRule> | undefined {\n if (typeof rule === \"object\" && rule.type === \"object\") {\n return rule.shape;\n }\n if (typeof rule === \"object\" && rule.type === \"union\") {\n const objectOpt = rule.options.find(\n (opt): opt is { type: \"object\"; shape: Record<string, CoercionRule> } =>\n typeof opt === \"object\" && opt.type === \"object\",\n );\n return objectOpt?.shape;\n }\n return undefined;\n}\n\n/**\n * boolean と object の union かどうかを判定する。\n * endArrow=\"true\" と endArrow.type=\"triangle\" の共存を許可するために使用。\n */\nexport function isBooleanObjectUnionRule(rule: CoercionRule): boolean {\n if (typeof rule === \"string\") return false;\n if (rule.type !== \"union\") return false;\n const hasBoolean = rule.options.includes(\"boolean\");\n const hasObject = rule.options.some(\n (opt) => typeof opt === \"object\" && opt.type === \"object\",\n );\n return hasBoolean && hasObject;\n}\n\ntype ResolvedMixedNotationShorthand =\n | { mode: \"merge\"; value: Record<string, unknown> }\n | { mode: \"ignore\" }\n | { mode: \"conflict\" };\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isDirectionalBoxShape(shape: Record<string, CoercionRule>): boolean {\n const keys = Object.keys(shape).sort();\n return (\n keys.length === 4 &&\n keys[0] === \"bottom\" &&\n keys[1] === \"left\" &&\n keys[2] === \"right\" &&\n keys[3] === \"top\"\n );\n}\n\n/**\n * 同一属性で shorthand と dot notation を併用したときに、\n * shorthand 側をどのように扱うかを解決する。\n *\n * - merge: shorthand をオブジェクト化して dot notation 側で上書き\n * - ignore: boolean shorthand を無視して dot notation を優先\n * - conflict: 併用不可(従来どおりエラー)\n */\nexport function resolveMixedNotationShorthand(\n value: string,\n rule: CoercionRule,\n): ResolvedMixedNotationShorthand {\n const objectShape = getObjectShapeFromRule(rule);\n if (!objectShape) return { mode: \"conflict\" };\n\n if (\n isBooleanObjectUnionRule(rule) &&\n (value === \"true\" || value === \"false\")\n ) {\n return { mode: \"ignore\" };\n }\n\n const coerced = coerceWithRule(value, rule);\n if (coerced.error !== null) return { mode: \"conflict\" };\n\n if (isPlainObject(coerced.value)) {\n return { mode: \"merge\", value: coerced.value };\n }\n\n if (typeof coerced.value === \"number\" && isDirectionalBoxShape(objectShape)) {\n return {\n mode: \"merge\",\n value: {\n top: coerced.value,\n right: coerced.value,\n bottom: coerced.value,\n left: coerced.value,\n },\n };\n }\n\n return { mode: \"conflict\" };\n}\n\n// ===== 共通変換ルール =====\n\nconst LENGTH_RULE: CoercionRule = {\n type: \"union\",\n options: [\"number\", { type: \"literal\", value: \"max\" }, \"string\"],\n};\n\nconst PADDING_RULE: CoercionRule = {\n type: \"union\",\n options: [\n \"number\",\n {\n type: \"object\",\n shape: {\n top: \"number\",\n right: \"number\",\n bottom: \"number\",\n left: \"number\",\n },\n },\n ],\n};\n\nconst BORDER_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\", dashType: \"string\" },\n};\n\nconst FILL_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", transparency: \"number\" },\n};\n\nconst SHADOW_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: {\n type: \"string\",\n opacity: \"number\",\n blur: \"number\",\n angle: \"number\",\n offset: \"number\",\n color: \"string\",\n },\n};\n\nconst UNDERLINE_RULE: CoercionRule = {\n type: \"union\",\n options: [\n \"boolean\",\n { type: \"object\", shape: { style: \"string\", color: \"string\" } },\n ],\n};\n\nconst LINE_ARROW_RULE: CoercionRule = {\n type: \"union\",\n options: [\"boolean\", { type: \"object\", shape: { type: \"string\" } }],\n};\n\nconst BACKGROUND_IMAGE_RULE: CoercionRule = {\n type: \"object\",\n shape: { src: \"string\", sizing: \"string\" },\n};\n\nconst TREE_CONNECTOR_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\" },\n};\n\nconst FLOW_CONNECTOR_STYLE_RULE: CoercionRule = {\n type: \"object\",\n shape: { color: \"string\", width: \"number\", arrowType: \"string\" },\n};\n\nconst IMAGE_SIZING_RULE: CoercionRule = {\n type: \"object\",\n shape: {\n type: \"string\",\n w: \"number\",\n h: \"number\",\n x: \"number\",\n y: \"number\",\n },\n};\n\n// ===== Base node 属性 =====\nconst BASE_RULES: Record<string, CoercionRule> = {\n id: \"string\",\n w: LENGTH_RULE,\n h: LENGTH_RULE,\n grow: \"number\",\n minW: \"number\",\n maxW: \"number\",\n minH: \"number\",\n maxH: \"number\",\n padding: PADDING_RULE,\n margin: PADDING_RULE,\n backgroundColor: \"string\",\n backgroundGradient: \"string\",\n backgroundImage: BACKGROUND_IMAGE_RULE,\n border: BORDER_STYLE_RULE,\n borderRadius: \"number\",\n opacity: \"number\",\n zIndex: \"number\",\n position: \"string\",\n top: \"number\",\n right: \"number\",\n bottom: \"number\",\n left: \"number\",\n alignSelf: \"string\",\n shadow: SHADOW_STYLE_RULE,\n};\n\n// テキスト系の共通属性\nconst TEXT_STYLE_RULES: Record<string, CoercionRule> = {\n fontSize: \"number\",\n color: \"string\",\n textAlign: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n lineHeight: \"number\",\n};\n\n// ===== ノードタイプ別の変換ルールマップ =====\nexport const NODE_COERCION_MAP: Record<string, Record<string, CoercionRule>> = {\n text: {\n ...BASE_RULES,\n text: \"string\",\n ...TEXT_STYLE_RULES,\n letterSpacing: \"number\",\n },\n ul: {\n ...BASE_RULES,\n items: \"json\",\n ...TEXT_STYLE_RULES,\n },\n ol: {\n ...BASE_RULES,\n items: \"json\",\n ...TEXT_STYLE_RULES,\n numberType: \"string\",\n numberStartAt: \"number\",\n },\n image: {\n ...BASE_RULES,\n src: \"string\",\n sizing: IMAGE_SIZING_RULE,\n },\n icon: {\n ...BASE_RULES,\n name: \"string\",\n size: \"number\",\n color: \"string\",\n variant: \"string\",\n bgColor: \"string\",\n },\n svg: {\n ...BASE_RULES,\n color: \"string\",\n },\n table: {\n ...BASE_RULES,\n columns: \"json\",\n rows: \"json\",\n defaultRowHeight: \"number\",\n cellBorder: BORDER_STYLE_RULE,\n },\n shape: {\n ...BASE_RULES,\n shapeType: \"string\",\n text: \"string\",\n fill: FILL_STYLE_RULE,\n line: BORDER_STYLE_RULE,\n ...TEXT_STYLE_RULES,\n },\n chart: {\n ...BASE_RULES,\n chartType: \"string\",\n data: \"json\",\n showLegend: \"boolean\",\n showTitle: \"boolean\",\n title: \"string\",\n chartColors: \"json\",\n radarStyle: \"string\",\n },\n timeline: {\n ...BASE_RULES,\n direction: \"string\",\n items: \"json\",\n },\n matrix: {\n ...BASE_RULES,\n axes: \"json\",\n quadrants: \"json\",\n items: \"json\",\n },\n tree: {\n ...BASE_RULES,\n layout: \"string\",\n nodeShape: \"string\",\n data: \"json\",\n connectorStyle: TREE_CONNECTOR_STYLE_RULE,\n nodeWidth: \"number\",\n nodeHeight: \"number\",\n levelGap: \"number\",\n siblingGap: \"number\",\n },\n flow: {\n ...BASE_RULES,\n direction: \"string\",\n nodes: \"json\",\n connections: \"json\",\n connectorStyle: FLOW_CONNECTOR_STYLE_RULE,\n nodeWidth: \"number\",\n nodeHeight: \"number\",\n nodeGap: \"number\",\n },\n processArrow: {\n ...BASE_RULES,\n direction: \"string\",\n steps: \"json\",\n itemWidth: \"number\",\n itemHeight: \"number\",\n gap: \"number\",\n fontSize: \"number\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n },\n pyramid: {\n ...BASE_RULES,\n direction: \"string\",\n levels: \"json\",\n fontSize: \"number\",\n bold: \"boolean\",\n fontFamily: \"string\",\n },\n line: {\n ...BASE_RULES,\n x1: \"number\",\n y1: \"number\",\n x2: \"number\",\n y2: \"number\",\n color: \"string\",\n lineWidth: \"number\",\n dashType: \"string\",\n beginArrow: LINE_ARROW_RULE,\n endArrow: LINE_ARROW_RULE,\n },\n arrow: {\n ...BASE_RULES,\n from: \"string\",\n to: \"string\",\n color: \"string\",\n lineWidth: \"number\",\n dashType: \"string\",\n beginArrow: LINE_ARROW_RULE,\n endArrow: LINE_ARROW_RULE,\n },\n // コンテナノード\n vstack: {\n ...BASE_RULES,\n gap: \"number\",\n alignItems: \"string\",\n justifyContent: \"string\",\n flexWrap: \"string\",\n },\n hstack: {\n ...BASE_RULES,\n gap: \"number\",\n alignItems: \"string\",\n justifyContent: \"string\",\n flexWrap: \"string\",\n },\n layer: {\n ...BASE_RULES,\n },\n};\n\n// ===== 子要素の変換ルールマップ =====\nexport const CHILD_ELEMENT_COERCION_MAP: Record<\n string,\n Record<string, CoercionRule>\n> = {\n ProcessArrowStep: {\n label: \"string\",\n color: \"string\",\n textColor: \"string\",\n },\n PyramidLevel: {\n label: \"string\",\n color: \"string\",\n textColor: \"string\",\n },\n TimelineItem: {\n date: \"string\",\n title: \"string\",\n description: \"string\",\n color: \"string\",\n },\n MatrixAxes: {\n x: \"string\",\n y: \"string\",\n },\n MatrixQuadrants: {\n topLeft: \"string\",\n topRight: \"string\",\n bottomLeft: \"string\",\n bottomRight: \"string\",\n },\n MatrixItem: {\n label: \"string\",\n x: \"number\",\n y: \"number\",\n color: \"string\",\n },\n FlowNode: {\n id: \"string\",\n shape: \"string\",\n text: \"string\",\n color: \"string\",\n textColor: \"string\",\n width: \"number\",\n height: \"number\",\n },\n FlowConnection: {\n from: \"string\",\n to: \"string\",\n label: \"string\",\n color: \"string\",\n },\n Col: {\n width: \"number\",\n },\n Td: {\n text: \"string\",\n fontSize: \"number\",\n color: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n fontFamily: \"string\",\n textAlign: \"string\",\n backgroundColor: \"string\",\n colspan: \"number\",\n rowspan: \"number\",\n },\n Li: {\n text: \"string\",\n bold: \"boolean\",\n italic: \"boolean\",\n underline: UNDERLINE_RULE,\n strike: \"boolean\",\n highlight: \"string\",\n color: \"string\",\n fontSize: \"number\",\n fontFamily: \"string\",\n },\n B: {},\n I: {},\n Span: { color: \"string\", fontFamily: \"string\", letterSpacing: \"number\" },\n};\n"],"mappings":";AAmBA,SAAgB,eACd,OACA,MAC0C;CAC1C,IAAI,SAAS,UAAU;EACrB,IAAI,UAAU,IACZ,OAAO;GACL,OAAO,KAAA;GACP,OAAO,mBAAmB,MAAM;EAClC;EAEF,MAAM,MAAM,OAAO,KAAK;EACxB,IAAI,MAAM,GAAG,GACX,OAAO;GACL,OAAO,KAAA;GACP,OAAO,mBAAmB,MAAM;EAClC;EAEF,OAAO;GAAE,OAAO;GAAK,OAAO;EAAK;CACnC;CACA,IAAI,SAAS,WAAW;EACtB,IAAI,UAAU,UAAU,UAAU,SAChC,OAAO;GACL,OAAO,KAAA;GACP,OAAO,mBAAmB,MAAM;EAClC;EAEF,OAAO;GAAE,OAAO,UAAU;GAAQ,OAAO;EAAK;CAChD;CACA,IAAI,SAAS,UACX,OAAO;EAAE;EAAO,OAAO;CAAK;CAE9B,IAAI,SAAS,QACX,IAAI;EACF,OAAO;GAAE,OAAO,KAAK,MAAM,KAAK;GAAG,OAAO;EAAK;CACjD,QAAQ;EACN,OAAO;GACL,OAAO,KAAA;GACP,OAAO,6BAA6B,MAAM;EAC5C;CACF;CAGF,IAAI,KAAK,SAAS,WAChB,OAAO;EAAE,OAAO,KAAK;EAAO,OAAO;CAAK;CAE1C,IAAI,KAAK,SAAS,SAChB,OAAO;EAAE,OAAO,qBAAqB,OAAO,KAAK,OAAO;EAAG,OAAO;CAAK;CAEzE,IAAI,KAAK,SAAS,UAChB,IAAI;EACF,OAAO;GAAE,OAAO,KAAK,MAAM,KAAK;GAAG,OAAO;EAAK;CACjD,QAAQ;EACN,OAAO;GACL,OAAO,KAAA;GACP,OAAO,6BAA6B,MAAM;EAC5C;CACF;CAEF,OAAO;EAAE,OAAO,eAAe,KAAK;EAAG,OAAO;CAAK;AACrD;AAEA,SAAgB,qBACd,OACA,SACS;CAET,KAAK,UAAU,UAAU,UAAU,YAAY,QAAQ,SAAS,SAAS,GACvE,OAAO,UAAU;CAInB,IAAI,QAAQ,SAAS,QAAQ,GAAG;EAC9B,MAAM,MAAM,OAAO,KAAK;EACxB,IAAI,CAAC,MAAM,GAAG,KAAK,UAAU,IAC3B,OAAO;CAEX;CAGA,KAAK,MAAM,OAAO,SAChB,IAAI,OAAO,QAAQ,YAAY,IAAI,SAAS;MACtC,GAAG,IAAI,YAA+B,OAAO,OAAO,IAAI;CAAA;CAKhE,IACE,QAAQ,MACL,QACC,QAAQ,UAAW,OAAO,QAAQ,YAAY,IAAI,SAAS,QAC/D;MAEI,MAAM,WAAW,GAAG,KAAK,MAAM,WAAW,GAAG,GAC/C,IAAI;GACF,OAAO,KAAK,MAAM,KAAK;EACzB,QAAQ,CAER;;CAKJ,OAAO;AACT;AAEA,SAAgB,eAAe,OAAwB;CACrD,IAAI,UAAU,QAAQ,OAAO;CAC7B,IAAI,UAAU,SAAS,OAAO;CAC9B,MAAM,MAAM,OAAO,KAAK;CACxB,IAAI,UAAU,MAAM,CAAC,MAAM,GAAG,GAAG,OAAO;CACxC,IAAI,MAAM,WAAW,GAAG,KAAK,MAAM,WAAW,GAAG,GAC/C,IAAI;EACF,OAAO,KAAK,MAAM,KAAK;CACzB,QAAQ,CAER;CAEF,OAAO;AACT;;;;;AAMA,SAAgB,uBACd,MAC0C;CAC1C,IAAI,OAAO,SAAS,YAAY,KAAK,SAAS,UAC5C,OAAO,KAAK;CAEd,IAAI,OAAO,SAAS,YAAY,KAAK,SAAS,SAK5C,OAJkB,KAAK,QAAQ,MAC5B,QACC,OAAO,QAAQ,YAAY,IAAI,SAAS,QAE7B,CAAC,EAAE;AAGtB;;;;;AAMA,SAAgB,yBAAyB,MAA6B;CACpE,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,KAAK,SAAS,SAAS,OAAO;CAClC,MAAM,aAAa,KAAK,QAAQ,SAAS,SAAS;CAClD,MAAM,YAAY,KAAK,QAAQ,MAC5B,QAAQ,OAAO,QAAQ,YAAY,IAAI,SAAS,QACnD;CACA,OAAO,cAAc;AACvB;AAOA,SAAS,cAAc,OAAkD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,sBAAsB,OAA8C;CAC3E,MAAM,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,KAAK;CACrC,OACE,KAAK,WAAW,KAChB,KAAK,OAAO,YACZ,KAAK,OAAO,UACZ,KAAK,OAAO,WACZ,KAAK,OAAO;AAEhB;;;;;;;;;AAUA,SAAgB,8BACd,OACA,MACgC;CAChC,MAAM,cAAc,uBAAuB,IAAI;CAC/C,IAAI,CAAC,aAAa,OAAO,EAAE,MAAM,WAAW;CAE5C,IACE,yBAAyB,IAAI,MAC5B,UAAU,UAAU,UAAU,UAE/B,OAAO,EAAE,MAAM,SAAS;CAG1B,MAAM,UAAU,eAAe,OAAO,IAAI;CAC1C,IAAI,QAAQ,UAAU,MAAM,OAAO,EAAE,MAAM,WAAW;CAEtD,IAAI,cAAc,QAAQ,KAAK,GAC7B,OAAO;EAAE,MAAM;EAAS,OAAO,QAAQ;CAAM;CAG/C,IAAI,OAAO,QAAQ,UAAU,YAAY,sBAAsB,WAAW,GACxE,OAAO;EACL,MAAM;EACN,OAAO;GACL,KAAK,QAAQ;GACb,OAAO,QAAQ;GACf,QAAQ,QAAQ;GAChB,MAAM,QAAQ;EAChB;CACF;CAGF,OAAO,EAAE,MAAM,WAAW;AAC5B;AAIA,MAAM,cAA4B;CAChC,MAAM;CACN,SAAS;EAAC;EAAU;GAAE,MAAM;GAAW,OAAO;EAAM;EAAG;CAAQ;AACjE;AAEA,MAAM,eAA6B;CACjC,MAAM;CACN,SAAS,CACP,UACA;EACE,MAAM;EACN,OAAO;GACL,KAAK;GACL,OAAO;GACP,QAAQ;GACR,MAAM;EACR;CACF,CACF;AACF;AAEA,MAAM,oBAAkC;CACtC,MAAM;CACN,OAAO;EAAE,OAAO;EAAU,OAAO;EAAU,UAAU;CAAS;AAChE;AAEA,MAAM,kBAAgC;CACpC,MAAM;CACN,OAAO;EAAE,OAAO;EAAU,cAAc;CAAS;AACnD;AAEA,MAAM,oBAAkC;CACtC,MAAM;CACN,OAAO;EACL,MAAM;EACN,SAAS;EACT,MAAM;EACN,OAAO;EACP,QAAQ;EACR,OAAO;CACT;AACF;AAEA,MAAM,iBAA+B;CACnC,MAAM;CACN,SAAS,CACP,WACA;EAAE,MAAM;EAAU,OAAO;GAAE,OAAO;GAAU,OAAO;EAAS;CAAE,CAChE;AACF;AAEA,MAAM,kBAAgC;CACpC,MAAM;CACN,SAAS,CAAC,WAAW;EAAE,MAAM;EAAU,OAAO,EAAE,MAAM,SAAS;CAAE,CAAC;AACpE;AAEA,MAAM,wBAAsC;CAC1C,MAAM;CACN,OAAO;EAAE,KAAK;EAAU,QAAQ;CAAS;AAC3C;AAEA,MAAM,4BAA0C;CAC9C,MAAM;CACN,OAAO;EAAE,OAAO;EAAU,OAAO;CAAS;AAC5C;AAEA,MAAM,4BAA0C;CAC9C,MAAM;CACN,OAAO;EAAE,OAAO;EAAU,OAAO;EAAU,WAAW;CAAS;AACjE;AAEA,MAAM,oBAAkC;CACtC,MAAM;CACN,OAAO;EACL,MAAM;EACN,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;CACL;AACF;AAGA,MAAM,aAA2C;CAC/C,IAAI;CACJ,GAAG;CACH,GAAG;CACH,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,MAAM;CACN,SAAS;CACT,QAAQ;CACR,iBAAiB;CACjB,oBAAoB;CACpB,iBAAiB;CACjB,QAAQ;CACR,cAAc;CACd,SAAS;CACT,QAAQ;CACR,UAAU;CACV,KAAK;CACL,OAAO;CACP,QAAQ;CACR,MAAM;CACN,WAAW;CACX,QAAQ;AACV;AAGA,MAAM,mBAAiD;CACrD,UAAU;CACV,OAAO;CACP,WAAW;CACX,MAAM;CACN,QAAQ;CACR,WAAW;CACX,QAAQ;CACR,WAAW;CACX,YAAY;CACZ,YAAY;AACd;AAGA,MAAa,oBAAkE;CAC7E,MAAM;EACJ,GAAG;EACH,MAAM;EACN,GAAG;EACH,eAAe;CACjB;CACA,IAAI;EACF,GAAG;EACH,OAAO;EACP,GAAG;CACL;CACA,IAAI;EACF,GAAG;EACH,OAAO;EACP,GAAG;EACH,YAAY;EACZ,eAAe;CACjB;CACA,OAAO;EACL,GAAG;EACH,KAAK;EACL,QAAQ;CACV;CACA,MAAM;EACJ,GAAG;EACH,MAAM;EACN,MAAM;EACN,OAAO;EACP,SAAS;EACT,SAAS;CACX;CACA,KAAK;EACH,GAAG;EACH,OAAO;CACT;CACA,OAAO;EACL,GAAG;EACH,SAAS;EACT,MAAM;EACN,kBAAkB;EAClB,YAAY;CACd;CACA,OAAO;EACL,GAAG;EACH,WAAW;EACX,MAAM;EACN,MAAM;EACN,MAAM;EACN,GAAG;CACL;CACA,OAAO;EACL,GAAG;EACH,WAAW;EACX,MAAM;EACN,YAAY;EACZ,WAAW;EACX,OAAO;EACP,aAAa;EACb,YAAY;CACd;CACA,UAAU;EACR,GAAG;EACH,WAAW;EACX,OAAO;CACT;CACA,QAAQ;EACN,GAAG;EACH,MAAM;EACN,WAAW;EACX,OAAO;CACT;CACA,MAAM;EACJ,GAAG;EACH,QAAQ;EACR,WAAW;EACX,MAAM;EACN,gBAAgB;EAChB,WAAW;EACX,YAAY;EACZ,UAAU;EACV,YAAY;CACd;CACA,MAAM;EACJ,GAAG;EACH,WAAW;EACX,OAAO;EACP,aAAa;EACb,gBAAgB;EAChB,WAAW;EACX,YAAY;EACZ,SAAS;CACX;CACA,cAAc;EACZ,GAAG;EACH,WAAW;EACX,OAAO;EACP,WAAW;EACX,YAAY;EACZ,KAAK;EACL,UAAU;EACV,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,WAAW;EACX,YAAY;CACd;CACA,SAAS;EACP,GAAG;EACH,WAAW;EACX,QAAQ;EACR,UAAU;EACV,MAAM;EACN,YAAY;CACd;CACA,MAAM;EACJ,GAAG;EACH,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,OAAO;EACP,WAAW;EACX,UAAU;EACV,YAAY;EACZ,UAAU;CACZ;CACA,OAAO;EACL,GAAG;EACH,MAAM;EACN,IAAI;EACJ,OAAO;EACP,WAAW;EACX,UAAU;EACV,YAAY;EACZ,UAAU;CACZ;CAEA,QAAQ;EACN,GAAG;EACH,KAAK;EACL,YAAY;EACZ,gBAAgB;EAChB,UAAU;CACZ;CACA,QAAQ;EACN,GAAG;EACH,KAAK;EACL,YAAY;EACZ,gBAAgB;EAChB,UAAU;CACZ;CACA,OAAO,EACL,GAAG,WACL;AACF;AAGA,MAAa,6BAGT;CACF,kBAAkB;EAChB,OAAO;EACP,OAAO;EACP,WAAW;CACb;CACA,cAAc;EACZ,OAAO;EACP,OAAO;EACP,WAAW;CACb;CACA,cAAc;EACZ,MAAM;EACN,OAAO;EACP,aAAa;EACb,OAAO;CACT;CACA,YAAY;EACV,GAAG;EACH,GAAG;CACL;CACA,iBAAiB;EACf,SAAS;EACT,UAAU;EACV,YAAY;EACZ,aAAa;CACf;CACA,YAAY;EACV,OAAO;EACP,GAAG;EACH,GAAG;EACH,OAAO;CACT;CACA,UAAU;EACR,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACP,WAAW;EACX,OAAO;EACP,QAAQ;CACV;CACA,gBAAgB;EACd,MAAM;EACN,IAAI;EACJ,OAAO;EACP,OAAO;CACT;CACA,KAAK,EACH,OAAO,SACT;CACA,IAAI;EACF,MAAM;EACN,UAAU;EACV,OAAO;EACP,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,WAAW;EACX,YAAY;EACZ,WAAW;EACX,iBAAiB;EACjB,SAAS;EACT,SAAS;CACX;CACA,IAAI;EACF,MAAM;EACN,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,WAAW;EACX,OAAO;EACP,UAAU;EACV,YAAY;CACd;CACA,GAAG,CAAC;CACJ,GAAG,CAAC;CACJ,MAAM;EAAE,OAAO;EAAU,YAAY;EAAU,eAAe;CAAS;AACzE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseXml.d.ts","names":[],"sources":["../../src/parseXml/parseXml.ts"],"mappings":";;;cAgCa,aAAA,SAAsB,KAAK;EAAA,SACtB,MAAA;cACJ,MAAA;AAAA;;;;;;;AAAgB;
|
|
1
|
+
{"version":3,"file":"parseXml.d.ts","names":[],"sources":["../../src/parseXml/parseXml.ts"],"mappings":";;;cAgCa,aAAA,SAAsB,KAAK;EAAA,SACtB,MAAA;cACJ,MAAA;AAAA;;;;;;;AAAgB;AAuuC9B;;;;AAAoD;;;;;;;;;;;;;;;;iBAApC,QAAA,CAAS,SAAA,WAAoB,OAAO"}
|
|
@@ -234,7 +234,7 @@ const INLINE_FORMAT_TAGS = new Set([
|
|
|
234
234
|
function hasInlineFormatChildren(childElements) {
|
|
235
235
|
return childElements.length > 0 && childElements.every((el) => INLINE_FORMAT_TAGS.has(getTagName(el)));
|
|
236
236
|
}
|
|
237
|
-
function extractTextRuns(children, inheritBold, inheritItalic, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily) {
|
|
237
|
+
function extractTextRuns(children, inheritBold, inheritItalic, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing) {
|
|
238
238
|
const runs = [];
|
|
239
239
|
for (const child of children) if (isTextNode(child)) {
|
|
240
240
|
const run = { text: child["#text"] };
|
|
@@ -246,28 +246,31 @@ function extractTextRuns(children, inheritBold, inheritItalic, inheritHref, inhe
|
|
|
246
246
|
if (inheritColor) run.color = inheritColor;
|
|
247
247
|
if (inheritHref) run.href = inheritHref;
|
|
248
248
|
if (inheritFontFamily) run.fontFamily = inheritFontFamily;
|
|
249
|
+
if (inheritLetterSpacing !== void 0) run.letterSpacing = inheritLetterSpacing;
|
|
249
250
|
runs.push(run);
|
|
250
251
|
} else {
|
|
251
252
|
const tag = getTagName(child);
|
|
252
253
|
const innerChildren = getRawChildren(child);
|
|
253
|
-
if (tag === "B") runs.push(...extractTextRuns(innerChildren, true, inheritItalic, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily));
|
|
254
|
-
else if (tag === "I") runs.push(...extractTextRuns(innerChildren, inheritBold, true, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily));
|
|
254
|
+
if (tag === "B") runs.push(...extractTextRuns(innerChildren, true, inheritItalic, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
255
|
+
else if (tag === "I") runs.push(...extractTextRuns(innerChildren, inheritBold, true, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
255
256
|
else if (tag === "A") {
|
|
256
257
|
const href = getAttributes(child).href ?? "";
|
|
257
|
-
runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, href, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily));
|
|
258
|
-
} else if (tag === "U") runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, true, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily));
|
|
259
|
-
else if (tag === "S") runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, inheritUnderline, true, inheritHighlight, inheritColor, inheritFontFamily));
|
|
258
|
+
runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, href, inheritUnderline, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
259
|
+
} else if (tag === "U") runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, true, inheritStrike, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
260
|
+
else if (tag === "S") runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, inheritUnderline, true, inheritHighlight, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
260
261
|
else if (tag === "Mark") {
|
|
261
262
|
const rawColor = getAttributes(child).color;
|
|
262
263
|
const color = rawColor && rawColor.trim() ? rawColor : "FFFF00";
|
|
263
|
-
runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, inheritUnderline, inheritStrike, color, inheritColor, inheritFontFamily));
|
|
264
|
+
runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, inheritUnderline, inheritStrike, color, inheritColor, inheritFontFamily, inheritLetterSpacing));
|
|
264
265
|
} else if (tag === "Span") {
|
|
265
266
|
const spanAttrs = getAttributes(child);
|
|
266
267
|
const rawSpanColor = spanAttrs.color;
|
|
267
268
|
const spanColor = rawSpanColor && rawSpanColor.trim() ? rawSpanColor : inheritColor;
|
|
268
269
|
const rawSpanFontFamily = spanAttrs.fontFamily;
|
|
269
270
|
const spanFontFamily = rawSpanFontFamily && rawSpanFontFamily.trim() ? rawSpanFontFamily : inheritFontFamily;
|
|
270
|
-
|
|
271
|
+
const rawSpanLetterSpacing = spanAttrs.letterSpacing;
|
|
272
|
+
const spanLetterSpacing = rawSpanLetterSpacing && rawSpanLetterSpacing.trim() ? Number(rawSpanLetterSpacing) : inheritLetterSpacing;
|
|
273
|
+
runs.push(...extractTextRuns(innerChildren, inheritBold, inheritItalic, inheritHref, inheritUnderline, inheritStrike, inheritHighlight, spanColor, spanFontFamily, spanLetterSpacing));
|
|
271
274
|
}
|
|
272
275
|
}
|
|
273
276
|
return runs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseXml.js","names":[],"sources":["../../src/parseXml/parseXml.ts"],"sourcesContent":["import { XMLBuilder, XMLParser } from \"fast-xml-parser\";\nimport { z } from \"zod\";\nimport {\n type POMNode,\n textNodeSchema,\n ulNodeSchema,\n olNodeSchema,\n imageNodeSchema,\n tableNodeSchema,\n shapeNodeSchema,\n chartNodeSchema,\n timelineNodeSchema,\n matrixNodeSchema,\n treeNodeSchema,\n flowNodeSchema,\n processArrowNodeSchema,\n pyramidNodeSchema,\n lineNodeSchema,\n arrowNodeSchema,\n iconNodeSchema,\n} from \"../types.ts\";\nimport {\n type CoercionRule,\n NODE_COERCION_MAP,\n CHILD_ELEMENT_COERCION_MAP,\n coerceWithRule,\n coerceFallback,\n getObjectShapeFromRule,\n resolveMixedNotationShorthand,\n} from \"./coercionRules.ts\";\n\n// ===== ParseXmlError =====\nexport class ParseXmlError extends Error {\n public readonly errors: string[];\n constructor(errors: string[]) {\n const message = `XML validation failed (${errors.length} error${errors.length > 1 ? \"s\" : \"\"}):\\n${errors.map((e) => ` - ${e}`).join(\"\\n\")}`;\n super(message);\n this.name = \"ParseXmlError\";\n this.errors = errors;\n }\n}\n\n// ===== Tag name → POM node type mapping =====\nexport const TAG_TO_TYPE: Record<string, string> = {\n Text: \"text\",\n Image: \"image\",\n Table: \"table\",\n Shape: \"shape\",\n Chart: \"chart\",\n Timeline: \"timeline\",\n Matrix: \"matrix\",\n Tree: \"tree\",\n Flow: \"flow\",\n ProcessArrow: \"processArrow\",\n Pyramid: \"pyramid\",\n Ul: \"ul\",\n Ol: \"ol\",\n Line: \"line\",\n Arrow: \"arrow\",\n VStack: \"vstack\",\n HStack: \"hstack\",\n Layer: \"layer\",\n Icon: \"icon\",\n Svg: \"svg\",\n};\n\n// Reverse mapping: node type → tag name\nconst TYPE_TO_TAG: Record<string, string> = Object.fromEntries(\n Object.entries(TAG_TO_TYPE).map(([tag, type]) => [type, tag]),\n);\n\nconst CONTAINER_TYPES = new Set([\"vstack\", \"hstack\", \"layer\"]);\nconst TEXT_CONTENT_NODES = new Set([\"text\", \"shape\"]);\n// Attributes allowed on any node (e.g., x/y for Layer children positioning)\nconst UNIVERSAL_ATTRS = new Set([\"x\", \"y\"]);\n\n// ===== Validation helpers =====\nfunction getKnownAttributes(nodeType: string): string[] {\n const rules = NODE_COERCION_MAP[nodeType];\n if (!rules) return [];\n return Object.keys(rules);\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n const dp: number[][] = Array.from({ length: m + 1 }, () =>\n Array<number>(n + 1).fill(0),\n );\n for (let i = 0; i <= m; i++) dp[i][0] = i;\n for (let j = 0; j <= n; j++) dp[0][j] = j;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i][j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1][j - 1]\n : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n }\n }\n return dp[m][n];\n}\n\nfunction findClosestMatch(\n input: string,\n candidates: string[],\n): string | undefined {\n const threshold = Math.max(2, Math.floor(input.length / 2));\n let bestMatch: string | undefined;\n let bestDistance = Infinity;\n for (const candidate of candidates) {\n const dist = levenshteinDistance(\n input.toLowerCase(),\n candidate.toLowerCase(),\n );\n if (dist < bestDistance && dist <= threshold) {\n bestDistance = dist;\n bestMatch = candidate;\n }\n }\n return bestMatch;\n}\n\nfunction getKnownChildAttributes(tagName: string): string[] {\n const rules = CHILD_ELEMENT_COERCION_MAP[tagName];\n if (!rules) return [];\n return Object.keys(rules);\n}\n\n// ===== Leaf node Zod validation schemas =====\nconst leafNodeValidationSchemas: Record<string, z.ZodTypeAny> = {\n text: textNodeSchema,\n image: imageNodeSchema,\n table: tableNodeSchema,\n shape: shapeNodeSchema,\n chart: chartNodeSchema,\n timeline: timelineNodeSchema,\n matrix: matrixNodeSchema,\n tree: treeNodeSchema,\n flow: flowNodeSchema,\n processArrow: processArrowNodeSchema,\n pyramid: pyramidNodeSchema,\n line: lineNodeSchema,\n arrow: arrowNodeSchema,\n ul: ulNodeSchema,\n ol: olNodeSchema,\n icon: iconNodeSchema,\n};\n\nfunction formatZodIssue(\n issue: z.core.$ZodIssue,\n tagName: string,\n): string | null {\n const path = issue.path;\n // Skip children-related issues (validated recursively)\n if (path.length > 0 && path[0] === \"children\") return null;\n // Skip \"type\" field issues (set internally)\n if (path.length === 1 && path[0] === \"type\") return null;\n\n const attrName = path.length > 0 ? String(path[0]) : undefined;\n\n const code = issue.code;\n\n if (code === \"invalid_type\") {\n // Missing required attribute\n if (issue.input === undefined) {\n if (attrName) {\n return `<${tagName}>: Missing required attribute \"${attrName}\"`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n // Type mismatch\n if (attrName) {\n return `<${tagName}>: Invalid type for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n if (code === \"invalid_value\") {\n if (attrName) {\n const values = (issue as unknown as { values: string[] }).values;\n if (values) {\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". Expected: ${values.map((v) => `\"${v}\"`).join(\", \")}`;\n }\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n if (code === \"too_small\" || code === \"too_big\") {\n if (attrName) {\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n // Generic fallback\n if (attrName) {\n return `<${tagName}>: Attribute \"${attrName}\": ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n}\n\n// Properties that may be legitimately absent when using child element notation\n// or when the property is optional in practice (even if required in schema).\nconst CHILD_ELEMENT_PROPS: Record<string, Set<string>> = {\n flow: new Set([\"nodes\", \"connections\"]),\n table: new Set([\"columns\", \"rows\"]),\n chart: new Set([\"data\"]),\n timeline: new Set([\"items\"]),\n matrix: new Set([\"axes\", \"items\", \"quadrants\"]),\n processArrow: new Set([\"steps\"]),\n pyramid: new Set([\"levels\"]),\n tree: new Set([\"data\"]),\n ul: new Set([\"items\"]),\n ol: new Set([\"items\"]),\n icon: new Set([\"name\"]),\n svg: new Set([\"svgContent\"]),\n};\n\nfunction validateLeafNode(\n nodeType: string,\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const schema = leafNodeValidationSchemas[nodeType];\n if (!schema) return;\n const tagName = TYPE_TO_TAG[nodeType] ?? nodeType;\n const childProps = CHILD_ELEMENT_PROPS[nodeType];\n const parseResult = schema.safeParse(result);\n if (!parseResult.success) {\n const seen = new Set<string>();\n for (const issue of parseResult.error.issues) {\n // Skip only top-level missing child-element properties (path.length === 1)\n // Nested issues (e.g., data.children[0].label) must still be reported\n if (\n childProps &&\n issue.path.length === 1 &&\n childProps.has(String(issue.path[0])) &&\n issue.code === \"invalid_type\" &&\n issue.input === undefined\n ) {\n continue;\n }\n // Skip issues for universal attributes (x, y)\n if (issue.path.length > 0 && UNIVERSAL_ATTRS.has(String(issue.path[0]))) {\n continue;\n }\n const msg = formatZodIssue(issue, tagName);\n if (msg && !seen.has(msg)) {\n seen.add(msg);\n errors.push(msg);\n }\n }\n }\n}\n\n// ===== Types for XML parser output (preserveOrder mode) =====\ntype XmlNode = XmlElement | XmlTextNode;\ntype XmlTextNode = { \"#text\": string };\ninterface XmlElement {\n [tagName: string]: XmlNode[] | Record<string, string> | undefined;\n \":@\"?: Record<string, string>;\n}\n\n// ===== Coercion rule lookup =====\n\nfunction getCoercionRule(\n nodeType: string,\n propertyName: string,\n): CoercionRule | undefined {\n return NODE_COERCION_MAP[nodeType]?.[propertyName];\n}\n\n// ===== Dot notation helpers =====\n\n// ===== Dot notation expansion =====\nfunction expandDotNotation(attrs: Record<string, string>): {\n regular: Record<string, string>;\n dotGroups: Record<string, Record<string, string>>;\n} {\n const regular: Record<string, string> = {};\n const dotGroups: Record<string, Record<string, string>> = {};\n\n for (const [key, value] of Object.entries(attrs)) {\n const dotIndex = key.indexOf(\".\");\n if (dotIndex > 0) {\n const prefix = key.substring(0, dotIndex);\n const suffix = key.substring(dotIndex + 1);\n if (!dotGroups[prefix]) dotGroups[prefix] = {};\n dotGroups[prefix][suffix] = value;\n } else {\n regular[key] = value;\n }\n }\n\n return { regular, dotGroups };\n}\n\nfunction coerceDotGroup(\n prefix: string,\n subAttrs: Record<string, string>,\n rule: CoercionRule,\n tagName: string,\n errors: string[],\n): Record<string, unknown> {\n const objectShape = getObjectShapeFromRule(rule);\n\n const obj: Record<string, unknown> = {};\n if (objectShape) {\n for (const [subKey, subValue] of Object.entries(subAttrs)) {\n if (objectShape[subKey]) {\n const coerced = coerceWithRule(subValue, objectShape[subKey]);\n if (coerced.error !== null) {\n errors.push(`<${tagName}>: ${prefix}.${subKey}: ${coerced.error}`);\n } else {\n obj[subKey] = coerced.value;\n }\n } else {\n const knownSubKeys = Object.keys(objectShape);\n const suggestion = findClosestMatch(subKey, knownSubKeys);\n errors.push(\n `<${tagName}>: Unknown sub-attribute \"${prefix}.${subKey}\"${suggestion ? `. Did you mean \"${prefix}.${suggestion}\"?` : \"\"}`,\n );\n }\n }\n } else {\n errors.push(\n `<${tagName}>: Attribute \"${prefix}\" does not support dot notation`,\n );\n }\n return obj;\n}\n\n// ===== XML node helpers =====\nfunction isTextNode(node: XmlNode): node is XmlTextNode {\n return \"#text\" in node;\n}\n\nfunction getTagName(node: XmlElement): string {\n for (const key of Object.keys(node)) {\n if (key !== \":@\") return key;\n }\n throw new Error(\"No tag name found in XML element\");\n}\n\nfunction getAttributes(node: XmlElement): Record<string, string> {\n const attrs: Record<string, string> = {};\n const rawAttrs = node[\":@\"];\n if (rawAttrs) {\n for (const [key, value] of Object.entries(rawAttrs)) {\n const attrName = key.startsWith(\"@_\") ? key.slice(2) : key;\n attrs[attrName] = value.trim();\n }\n }\n return attrs;\n}\n\nfunction getChildElements(node: XmlElement): XmlElement[] {\n const tagName = getTagName(node);\n const children = node[tagName] as XmlNode[] | undefined;\n if (!children) return [];\n return children.filter((child): child is XmlElement => !isTextNode(child));\n}\n\nfunction getTextContent(node: XmlElement): string | undefined {\n const tagName = getTagName(node);\n const children = node[tagName] as XmlNode[] | undefined;\n if (!children) return undefined;\n const textParts: string[] = [];\n for (const child of children) {\n if (isTextNode(child)) {\n textParts.push(child[\"#text\"]);\n }\n }\n return textParts.length > 0 ? textParts.join(\"\") : undefined;\n}\n\nfunction getRawChildren(node: XmlElement): XmlNode[] {\n const tagName = getTagName(node);\n return (node[tagName] as XmlNode[] | undefined) ?? [];\n}\n\nconst INLINE_FORMAT_TAGS = new Set([\"B\", \"I\", \"A\", \"U\", \"S\", \"Mark\", \"Span\"]);\n\nfunction hasInlineFormatChildren(childElements: XmlElement[]): boolean {\n return (\n childElements.length > 0 &&\n childElements.every((el) => INLINE_FORMAT_TAGS.has(getTagName(el)))\n );\n}\n\ntype TextRunResult = {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n};\n\nfunction extractTextRuns(\n children: XmlNode[],\n inheritBold?: boolean,\n inheritItalic?: boolean,\n inheritHref?: string,\n inheritUnderline?: boolean,\n inheritStrike?: boolean,\n inheritHighlight?: string,\n inheritColor?: string,\n inheritFontFamily?: string,\n): TextRunResult[] {\n const runs: TextRunResult[] = [];\n for (const child of children) {\n if (isTextNode(child)) {\n const run: TextRunResult = { text: child[\"#text\"] };\n if (inheritBold) run.bold = true;\n if (inheritItalic) run.italic = true;\n if (inheritUnderline) run.underline = true;\n if (inheritStrike) run.strike = true;\n if (inheritHighlight) run.highlight = inheritHighlight;\n if (inheritColor) run.color = inheritColor;\n if (inheritHref) run.href = inheritHref;\n if (inheritFontFamily) run.fontFamily = inheritFontFamily;\n runs.push(run);\n } else {\n const tag = getTagName(child);\n const innerChildren = getRawChildren(child);\n if (tag === \"B\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n true,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"I\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n true,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"A\") {\n const href = getAttributes(child).href ?? \"\";\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n href,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"U\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n true,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"S\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n true,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"Mark\") {\n const rawColor = getAttributes(child).color;\n const color = rawColor && rawColor.trim() ? rawColor : \"FFFF00\";\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n color,\n inheritColor,\n inheritFontFamily,\n ),\n );\n } else if (tag === \"Span\") {\n const spanAttrs = getAttributes(child);\n const rawSpanColor = spanAttrs.color;\n const spanColor =\n rawSpanColor && rawSpanColor.trim() ? rawSpanColor : inheritColor;\n const rawSpanFontFamily = spanAttrs.fontFamily;\n const spanFontFamily =\n rawSpanFontFamily && rawSpanFontFamily.trim()\n ? rawSpanFontFamily\n : inheritFontFamily;\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n spanColor,\n spanFontFamily,\n ),\n );\n }\n }\n }\n return runs;\n}\n\nfunction buildRunsAndText(\n node: XmlElement,\n): { runs: TextRunResult[]; text: string } | null {\n const rawChildren = getRawChildren(node);\n const childElements = rawChildren.filter(\n (c): c is XmlElement => !isTextNode(c),\n );\n if (!hasInlineFormatChildren(childElements)) return null;\n const runs = extractTextRuns(rawChildren);\n const text = runs.map((r) => r.text).join(\"\");\n return { runs, text };\n}\n\nfunction coerceChildAttrs(\n parentTagName: string,\n tagName: string,\n attrs: Record<string, string>,\n errors: string[],\n): Record<string, unknown> {\n const rules = CHILD_ELEMENT_COERCION_MAP[tagName];\n const result: Record<string, unknown> = {};\n const { regular: regularAttrs, dotGroups } = expandDotNotation(attrs);\n\n // Process dot-notation attributes\n for (const [prefix, subAttrs] of Object.entries(dotGroups)) {\n if (rules && rules[prefix]) {\n result[prefix] = coerceDotGroup(\n prefix,\n subAttrs,\n rules[prefix],\n `${parentTagName}.${tagName}`,\n errors,\n );\n } else if (rules) {\n const knownAttrs = getKnownChildAttributes(tagName);\n const suggestion = findClosestMatch(prefix, knownAttrs);\n errors.push(\n `<${parentTagName}>.<${tagName}>: Unknown attribute \"${prefix}\"${suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"}`,\n );\n } else {\n result[prefix] = {};\n for (const [subKey, subValue] of Object.entries(subAttrs)) {\n (result[prefix] as Record<string, unknown>)[subKey] =\n coerceFallback(subValue);\n }\n }\n }\n\n // Process regular attributes\n for (const [key, value] of Object.entries(regularAttrs)) {\n if (key in dotGroups) {\n if (rules && rules[key]) {\n const resolved = resolveMixedNotationShorthand(value, rules[key]);\n if (resolved.mode === \"ignore\") {\n continue;\n }\n if (resolved.mode === \"merge\") {\n result[key] = {\n ...resolved.value,\n ...(result[key] as Record<string, unknown>),\n };\n continue;\n }\n }\n errors.push(\n `<${parentTagName}>.<${tagName}>: Attribute \"${key}\" conflicts with dot-notation attributes. Use one or the other, not both`,\n );\n continue;\n }\n if (rules && rules[key]) {\n const coerced = coerceWithRule(value, rules[key]);\n if (coerced.error !== null) {\n errors.push(`<${parentTagName}>.<${tagName}>: ${coerced.error}`);\n } else {\n result[key] = coerced.value;\n }\n } else if (rules) {\n // Unknown attribute on child element\n const knownAttrs = getKnownChildAttributes(tagName);\n const suggestion = findClosestMatch(key, knownAttrs);\n errors.push(\n `<${parentTagName}>.<${tagName}>: Unknown attribute \"${key}\"${suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"}`,\n );\n } else {\n result[key] = coerceFallback(value);\n }\n }\n return result;\n}\n\n// ===== Child element converters =====\ntype ChildElementConverter = (\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n node?: XmlElement,\n) => void;\n\nfunction convertProcessArrowChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const steps: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"ProcessArrowStep\") {\n errors.push(\n `Unknown child element <${tag}> inside <ProcessArrow>. Expected: <ProcessArrowStep>`,\n );\n continue;\n }\n steps.push(\n coerceChildAttrs(\"ProcessArrow\", tag, getAttributes(child), errors),\n );\n }\n result.steps = steps;\n}\n\nfunction convertPyramidChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const levels: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"PyramidLevel\") {\n errors.push(\n `Unknown child element <${tag}> inside <Pyramid>. Expected: <PyramidLevel>`,\n );\n continue;\n }\n levels.push(coerceChildAttrs(\"Pyramid\", tag, getAttributes(child), errors));\n }\n result.levels = levels;\n}\n\nfunction convertTimelineChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"TimelineItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <Timeline>. Expected: <TimelineItem>`,\n );\n continue;\n }\n items.push(coerceChildAttrs(\"Timeline\", tag, getAttributes(child), errors));\n }\n result.items = items;\n}\n\nfunction convertMatrixChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"MatrixAxes\":\n result.axes = coerceChildAttrs(\n \"Matrix\",\n tag,\n getAttributes(child),\n errors,\n );\n break;\n case \"MatrixQuadrants\":\n result.quadrants = coerceChildAttrs(\n \"Matrix\",\n tag,\n getAttributes(child),\n errors,\n );\n break;\n case \"MatrixItem\":\n items.push(\n coerceChildAttrs(\"Matrix\", tag, getAttributes(child), errors),\n );\n break;\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Matrix>. Expected: <MatrixAxes>, <MatrixQuadrants>, or <MatrixItem>`,\n );\n }\n }\n if (items.length > 0) {\n result.items = items;\n }\n}\n\nfunction convertFlowChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const nodes: Record<string, unknown>[] = [];\n const connections: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"FlowNode\":\n nodes.push(coerceChildAttrs(\"Flow\", tag, getAttributes(child), errors));\n break;\n case \"FlowConnection\":\n connections.push(\n coerceChildAttrs(\"Flow\", tag, getAttributes(child), errors),\n );\n break;\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Flow>. Expected: <FlowNode> or <FlowConnection>`,\n );\n }\n }\n if (nodes.length > 0) {\n result.nodes = nodes;\n }\n if (connections.length > 0) {\n result.connections = connections;\n }\n}\n\nfunction convertChartChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const data: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"ChartSeries\") {\n errors.push(\n `Unknown child element <${tag}> inside <Chart>. Expected: <ChartSeries>`,\n );\n continue;\n }\n const attrs = getAttributes(child);\n const series: Record<string, unknown> = {\n labels: [],\n values: [],\n };\n if (attrs.name !== undefined) {\n // chartDataSchema.name は z.string().optional() なのでそのまま文字列として使用\n series.name = attrs.name;\n }\n\n for (const dp of getChildElements(child)) {\n const dpTag = getTagName(dp);\n if (dpTag !== \"ChartDataPoint\") {\n errors.push(\n `Unknown child element <${dpTag}> inside <ChartSeries>. Expected: <ChartDataPoint>`,\n );\n continue;\n }\n const dpAttrs = getAttributes(dp);\n if (dpAttrs.label === undefined) {\n errors.push('<ChartDataPoint> requires a \"label\" attribute');\n }\n if (dpAttrs.value === undefined) {\n errors.push('<ChartDataPoint> requires a \"value\" attribute');\n }\n if (dpAttrs.label === undefined || dpAttrs.value === undefined) {\n continue;\n }\n const numValue = Number(dpAttrs.value);\n if (isNaN(numValue)) {\n errors.push(\n `Cannot convert \"${dpAttrs.value}\" to number in <ChartDataPoint> \"value\" attribute`,\n );\n continue;\n }\n (series.labels as string[]).push(dpAttrs.label);\n (series.values as number[]).push(numValue);\n }\n data.push(series);\n }\n result.data = data;\n}\n\nfunction convertTableChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const columns: Record<string, unknown>[] = [];\n const rows: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"Col\":\n columns.push(\n coerceChildAttrs(\"Table\", tag, getAttributes(child), errors),\n );\n break;\n case \"Tr\": {\n const rowAttrs = getAttributes(child);\n const cells: Record<string, unknown>[] = [];\n for (const cellEl of getChildElements(child)) {\n const cellTag = getTagName(cellEl);\n if (cellTag !== \"Td\") {\n errors.push(\n `Unknown child element <${cellTag}> inside <Tr>. Expected: <Td>`,\n );\n continue;\n }\n const cellAttrs = coerceChildAttrs(\n \"Tr\",\n cellTag,\n getAttributes(cellEl),\n errors,\n );\n const runsResult = buildRunsAndText(cellEl);\n if (runsResult) {\n cellAttrs.runs = runsResult.runs;\n cellAttrs.text = runsResult.text;\n } else {\n const cellText = getTextContent(cellEl);\n if (cellText !== undefined && !(\"text\" in cellAttrs)) {\n cellAttrs.text = cellText;\n }\n }\n cells.push(cellAttrs);\n }\n const row: Record<string, unknown> = { cells };\n if (rowAttrs.height !== undefined) {\n const h = Number(rowAttrs.height);\n if (isNaN(h)) {\n errors.push(\n `Cannot convert \"${rowAttrs.height}\" to number in <Tr> \"height\" attribute`,\n );\n } else {\n row.height = h;\n }\n }\n rows.push(row);\n break;\n }\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Table>. Expected: <Col> or <Tr>`,\n );\n }\n }\n if (columns.length > 0) {\n result.columns = columns;\n } else if (rows.length > 0) {\n // Col が未指定の場合、行のセル数(colspan 考慮)からデフォルトの columns を自動生成\n const maxCells = Math.max(\n ...rows.map((row) =>\n (row.cells as Record<string, unknown>[]).reduce(\n (sum, cell) => sum + ((cell.colspan as number) ?? 1),\n 0,\n ),\n ),\n );\n result.columns = Array.from({ length: maxCells }, () => ({}));\n }\n if (rows.length > 0) {\n result.rows = rows;\n }\n}\n\nfunction convertTreeItem(\n element: XmlElement,\n errors: string[],\n): Record<string, unknown> {\n const attrs = getAttributes(element);\n if (attrs.label === undefined) {\n errors.push('<TreeItem> requires a \"label\" attribute');\n }\n const item: Record<string, unknown> = {};\n if (attrs.label !== undefined) {\n item.label = attrs.label;\n }\n if (attrs.color !== undefined) {\n item.color = attrs.color;\n }\n const children = getChildElements(element);\n if (children.length > 0) {\n item.children = children\n .map((child) => {\n const tag = getTagName(child);\n if (tag !== \"TreeItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <TreeItem>. Expected: <TreeItem>`,\n );\n return null;\n }\n return convertTreeItem(child, errors);\n })\n .filter((item): item is Record<string, unknown> => item !== null);\n }\n return item;\n}\n\nfunction convertTreeChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n if (childElements.length !== 1) {\n errors.push(\n `<Tree> must have exactly 1 <TreeItem> child element, but got ${childElements.length}`,\n );\n return;\n }\n const child = childElements[0];\n const tag = getTagName(child);\n if (tag !== \"TreeItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <Tree>. Expected: <TreeItem>`,\n );\n return;\n }\n result.data = convertTreeItem(child, errors);\n}\n\nfunction convertListChildren(\n parentTag: string,\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"Li\") {\n errors.push(\n `Unknown child element <${tag}> inside <${parentTag}>. Expected: <Li>`,\n );\n continue;\n }\n const attrs = coerceChildAttrs(\n parentTag,\n tag,\n getAttributes(child),\n errors,\n );\n const runsResult = buildRunsAndText(child);\n if (runsResult) {\n attrs.runs = runsResult.runs;\n attrs.text = runsResult.text;\n } else {\n const textContent = getTextContent(child);\n if (textContent !== undefined && !(\"text\" in attrs)) {\n attrs.text = textContent;\n }\n }\n items.push(attrs);\n }\n result.items = items;\n}\n\n// SVG 要素を XML 文字列に再構築する\nconst svgBuilder = new XMLBuilder({\n preserveOrder: true,\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n});\n\nfunction serializeSvgElement(svgElement: XmlElement): string {\n return String(svgBuilder.build([svgElement]));\n}\n\nfunction convertSvgChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n if (childElements.length !== 1) {\n errors.push(\n `<Svg>: Expected exactly one <svg> child element, but found ${childElements.length} child element(s)`,\n );\n return;\n }\n\n const child = childElements[0];\n const tag = getTagName(child);\n if (tag !== \"svg\") {\n errors.push(`<Svg>: Expected <svg> child element, but found <${tag}>`);\n return;\n }\n\n result.svgContent = serializeSvgElement(child);\n}\n\nfunction convertTextInlineChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n node?: XmlElement,\n): void {\n // インラインフォーマットタグ以外の子要素がある場合はエラー\n for (const el of childElements) {\n const tag = getTagName(el);\n if (!INLINE_FORMAT_TAGS.has(tag)) {\n errors.push(\n `<Text>: Unexpected child element <${tag}>. Only <B>, <I>, <A>, <U>, <S>, <Mark>, and <Span> are allowed inside <Text>`,\n );\n return;\n }\n }\n if (!node || childElements.length === 0) return;\n const runsResult = buildRunsAndText(node);\n if (runsResult) {\n result.runs = runsResult.runs;\n result.text = runsResult.text;\n }\n}\n\nconst CHILD_ELEMENT_CONVERTERS: Record<string, ChildElementConverter> = {\n text: convertTextInlineChildren,\n ul: (childElements, result, errors) =>\n convertListChildren(\"Ul\", childElements, result, errors),\n ol: (childElements, result, errors) =>\n convertListChildren(\"Ol\", childElements, result, errors),\n processArrow: convertProcessArrowChildren,\n pyramid: convertPyramidChildren,\n timeline: convertTimelineChildren,\n matrix: convertMatrixChildren,\n flow: convertFlowChildren,\n chart: convertChartChildren,\n table: convertTableChildren,\n tree: convertTreeChildren,\n svg: convertSvgChildren,\n};\n\n// ===== Node conversion =====\nfunction convertElement(\n node: XmlElement,\n errors: string[],\n): Record<string, unknown> | null {\n const tagName = getTagName(node);\n const nodeType = TAG_TO_TYPE[tagName];\n const attrs = getAttributes(node);\n const childElements = getChildElements(node);\n const textContent = getTextContent(node);\n\n if (nodeType) {\n return convertPomNode(\n nodeType,\n tagName,\n attrs,\n childElements,\n textContent,\n errors,\n node,\n );\n } else {\n errors.push(`Unknown tag: <${tagName}>`);\n return null;\n }\n}\n\nfunction convertPomNode(\n nodeType: string,\n tagName: string,\n attrs: Record<string, string>,\n childElements: XmlElement[],\n textContent: string | undefined,\n errors: string[],\n xmlNode?: XmlElement,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { type: nodeType };\n\n // Expand dot-notation attributes (e.g., fill.color=\"hex\" → { fill: { color: \"hex\" } })\n const { regular: regularAttrs, dotGroups } = expandDotNotation(attrs);\n\n for (const [prefix, subAttrs] of Object.entries(dotGroups)) {\n if (prefix === \"type\") continue;\n const rule = getCoercionRule(nodeType, prefix);\n if (rule) {\n result[prefix] = coerceDotGroup(prefix, subAttrs, rule, tagName, errors);\n } else {\n const knownAttrs = getKnownAttributes(nodeType);\n const suggestion = findClosestMatch(prefix, knownAttrs);\n if (suggestion) {\n errors.push(\n `<${tagName}>: Unknown attribute \"${prefix}\". Did you mean \"${suggestion}\"?`,\n );\n } else {\n errors.push(`<${tagName}>: Unknown attribute \"${prefix}\"`);\n }\n }\n }\n\n for (const [key, value] of Object.entries(regularAttrs)) {\n if (key === \"type\") continue;\n // Conflict check: dot-notation and regular attribute for the same key\n if (key in dotGroups) {\n const ruleForConflict = getCoercionRule(nodeType, key);\n if (ruleForConflict) {\n const resolved = resolveMixedNotationShorthand(value, ruleForConflict);\n if (resolved.mode === \"ignore\") {\n continue;\n }\n if (resolved.mode === \"merge\") {\n result[key] = {\n ...resolved.value,\n ...(result[key] as Record<string, unknown>),\n };\n continue;\n }\n }\n errors.push(\n `<${tagName}>: Attribute \"${key}\" conflicts with dot-notation attributes (e.g., \"${key}.xxx\"). Use one or the other, not both`,\n );\n continue;\n }\n const rule = getCoercionRule(nodeType, key);\n if (rule) {\n const coerced = coerceWithRule(value, rule);\n if (coerced.error !== null) {\n errors.push(`<${tagName}>: ${coerced.error}`);\n } else {\n result[key] = coerced.value;\n }\n } else if (UNIVERSAL_ATTRS.has(key)) {\n // Allow universal attributes (e.g., x/y for Layer children)\n result[key] = coerceFallback(value);\n } else {\n // Unknown attribute\n const knownAttrs = getKnownAttributes(nodeType);\n const suggestion = findClosestMatch(key, knownAttrs);\n if (suggestion) {\n errors.push(\n `<${tagName}>: Unknown attribute \"${key}\". Did you mean \"${suggestion}\"?`,\n );\n } else {\n errors.push(`<${tagName}>: Unknown attribute \"${key}\"`);\n }\n }\n }\n\n // Text content → text property for nodes that support it\n if (textContent !== undefined && TEXT_CONTENT_NODES.has(nodeType)) {\n if (!(\"text\" in result)) {\n result.text = textContent;\n }\n }\n\n // Child element notation for complex properties\n const childConverter = CHILD_ELEMENT_CONVERTERS[nodeType];\n if (childConverter && childElements.length > 0) {\n childConverter(childElements, result, errors, xmlNode);\n }\n // Children for container nodes\n else if (CONTAINER_TYPES.has(nodeType) && childElements.length > 0) {\n const convertedChildren = childElements\n .map((child) => convertElement(child, errors))\n .filter((child): child is Record<string, unknown> => child !== null);\n result.children = convertedChildren;\n }\n // Leaf nodes that shouldn't have child elements\n else if (\n !CONTAINER_TYPES.has(nodeType) &&\n !childConverter &&\n childElements.length > 0\n ) {\n errors.push(\n `<${tagName}>: Unexpected child elements. <${tagName}> does not accept child elements`,\n );\n }\n\n // Zod validation for leaf nodes\n if (!CONTAINER_TYPES.has(nodeType)) {\n validateLeafNode(nodeType, result, errors);\n }\n\n // Icon: normalize color / bgColor\n if (nodeType === \"icon\") {\n if (typeof result.color === \"string\" && !result.color.startsWith(\"#\")) {\n result.color = `#${result.color}`;\n }\n if (typeof result.bgColor === \"string\" && !result.bgColor.startsWith(\"#\")) {\n result.bgColor = `#${result.bgColor}`;\n }\n }\n\n // Svg: normalize color and validate svgContent\n if (nodeType === \"svg\") {\n if (typeof result.color === \"string\" && !result.color.startsWith(\"#\")) {\n result.color = `#${result.color}`;\n }\n if (result.svgContent === undefined) {\n errors.push(\"<Svg>: A <svg> child element is required\");\n }\n }\n\n return result;\n}\n\n/**\n * XML 文字列を POMNode 配列に変換する。\n *\n * 最上位は `<Slide>` 要素のみが許容される。各 `<Slide>` が 1 つのスライドに\n * 対応し、その子要素がスライドのルート POMNode となる。子要素が複数ある場合は\n * 暗黙的に VStack でラップされる。\n *\n * XML タグは POM ノードタイプにマッピングされ、属性値は Zod スキーマを参照して\n * 適切な型(number, boolean, array, object)に変換される。\n * 未知のタグ名が指定された場合はエラーがスローされる。\n *\n * @example\n * ```typescript\n * import { parseXml, buildPptx } from \"@hirokisakabe/pom\";\n *\n * const xml = `\n * <Slide>\n * <VStack gap=\"16\" padding=\"32\">\n * <Text fontSize=\"32\" bold=\"true\">売上レポート</Text>\n * </VStack>\n * </Slide>\n * `;\n *\n * const nodes = parseXml(xml);\n * const pptx = await buildPptx(nodes, { w: 1280, h: 720 });\n * ```\n */\nexport function parseXml(xmlString: string): POMNode[] {\n if (!xmlString.trim()) return [];\n\n const parser = new XMLParser({\n preserveOrder: true,\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n parseAttributeValue: false,\n parseTagValue: false,\n trimValues: false,\n });\n\n const wrappedXml = `<__root__>${xmlString}</__root__>`;\n const parsed: XmlElement[] = parser.parse(wrappedXml) as XmlElement[];\n\n if (!parsed || parsed.length === 0) return [];\n\n const rootElement = parsed[0];\n const rootChildren = (rootElement[\"__root__\"] ?? []) as XmlNode[];\n\n const errors: string[] = [];\n const slideElements = rootChildren.filter(\n (child): child is XmlElement => !isTextNode(child),\n );\n\n const nodes: POMNode[] = [];\n for (const slideEl of slideElements) {\n const tagName = getTagName(slideEl);\n if (tagName !== \"Slide\") {\n errors.push(\n `Top-level element must be <Slide>, but got <${tagName}>. Wrap your slide content in <Slide>...</Slide>.`,\n );\n continue;\n }\n if (Object.keys(getAttributes(slideEl)).length > 0) {\n errors.push(`<Slide>: Attributes are not supported`);\n }\n const slideChildren = getChildElements(slideEl);\n if (slideChildren.length === 0) {\n errors.push(`<Slide> must contain at least one child element`);\n continue;\n }\n const converted = slideChildren\n .map((child) => convertElement(child, errors))\n .filter((c): c is Record<string, unknown> => c !== null);\n if (converted.length === 0) continue;\n if (converted.length === 1) {\n nodes.push(converted[0] as POMNode);\n } else {\n nodes.push({\n type: \"vstack\",\n children: converted,\n } as POMNode);\n }\n }\n\n if (errors.length > 0) {\n throw new ParseXmlError(errors);\n }\n\n return nodes;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parseXml.js","names":[],"sources":["../../src/parseXml/parseXml.ts"],"sourcesContent":["import { XMLBuilder, XMLParser } from \"fast-xml-parser\";\nimport { z } from \"zod\";\nimport {\n type POMNode,\n textNodeSchema,\n ulNodeSchema,\n olNodeSchema,\n imageNodeSchema,\n tableNodeSchema,\n shapeNodeSchema,\n chartNodeSchema,\n timelineNodeSchema,\n matrixNodeSchema,\n treeNodeSchema,\n flowNodeSchema,\n processArrowNodeSchema,\n pyramidNodeSchema,\n lineNodeSchema,\n arrowNodeSchema,\n iconNodeSchema,\n} from \"../types.ts\";\nimport {\n type CoercionRule,\n NODE_COERCION_MAP,\n CHILD_ELEMENT_COERCION_MAP,\n coerceWithRule,\n coerceFallback,\n getObjectShapeFromRule,\n resolveMixedNotationShorthand,\n} from \"./coercionRules.ts\";\n\n// ===== ParseXmlError =====\nexport class ParseXmlError extends Error {\n public readonly errors: string[];\n constructor(errors: string[]) {\n const message = `XML validation failed (${errors.length} error${errors.length > 1 ? \"s\" : \"\"}):\\n${errors.map((e) => ` - ${e}`).join(\"\\n\")}`;\n super(message);\n this.name = \"ParseXmlError\";\n this.errors = errors;\n }\n}\n\n// ===== Tag name → POM node type mapping =====\nexport const TAG_TO_TYPE: Record<string, string> = {\n Text: \"text\",\n Image: \"image\",\n Table: \"table\",\n Shape: \"shape\",\n Chart: \"chart\",\n Timeline: \"timeline\",\n Matrix: \"matrix\",\n Tree: \"tree\",\n Flow: \"flow\",\n ProcessArrow: \"processArrow\",\n Pyramid: \"pyramid\",\n Ul: \"ul\",\n Ol: \"ol\",\n Line: \"line\",\n Arrow: \"arrow\",\n VStack: \"vstack\",\n HStack: \"hstack\",\n Layer: \"layer\",\n Icon: \"icon\",\n Svg: \"svg\",\n};\n\n// Reverse mapping: node type → tag name\nconst TYPE_TO_TAG: Record<string, string> = Object.fromEntries(\n Object.entries(TAG_TO_TYPE).map(([tag, type]) => [type, tag]),\n);\n\nconst CONTAINER_TYPES = new Set([\"vstack\", \"hstack\", \"layer\"]);\nconst TEXT_CONTENT_NODES = new Set([\"text\", \"shape\"]);\n// Attributes allowed on any node (e.g., x/y for Layer children positioning)\nconst UNIVERSAL_ATTRS = new Set([\"x\", \"y\"]);\n\n// ===== Validation helpers =====\nfunction getKnownAttributes(nodeType: string): string[] {\n const rules = NODE_COERCION_MAP[nodeType];\n if (!rules) return [];\n return Object.keys(rules);\n}\n\nfunction levenshteinDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n const dp: number[][] = Array.from({ length: m + 1 }, () =>\n Array<number>(n + 1).fill(0),\n );\n for (let i = 0; i <= m; i++) dp[i][0] = i;\n for (let j = 0; j <= n; j++) dp[0][j] = j;\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i][j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1][j - 1]\n : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);\n }\n }\n return dp[m][n];\n}\n\nfunction findClosestMatch(\n input: string,\n candidates: string[],\n): string | undefined {\n const threshold = Math.max(2, Math.floor(input.length / 2));\n let bestMatch: string | undefined;\n let bestDistance = Infinity;\n for (const candidate of candidates) {\n const dist = levenshteinDistance(\n input.toLowerCase(),\n candidate.toLowerCase(),\n );\n if (dist < bestDistance && dist <= threshold) {\n bestDistance = dist;\n bestMatch = candidate;\n }\n }\n return bestMatch;\n}\n\nfunction getKnownChildAttributes(tagName: string): string[] {\n const rules = CHILD_ELEMENT_COERCION_MAP[tagName];\n if (!rules) return [];\n return Object.keys(rules);\n}\n\n// ===== Leaf node Zod validation schemas =====\nconst leafNodeValidationSchemas: Record<string, z.ZodTypeAny> = {\n text: textNodeSchema,\n image: imageNodeSchema,\n table: tableNodeSchema,\n shape: shapeNodeSchema,\n chart: chartNodeSchema,\n timeline: timelineNodeSchema,\n matrix: matrixNodeSchema,\n tree: treeNodeSchema,\n flow: flowNodeSchema,\n processArrow: processArrowNodeSchema,\n pyramid: pyramidNodeSchema,\n line: lineNodeSchema,\n arrow: arrowNodeSchema,\n ul: ulNodeSchema,\n ol: olNodeSchema,\n icon: iconNodeSchema,\n};\n\nfunction formatZodIssue(\n issue: z.core.$ZodIssue,\n tagName: string,\n): string | null {\n const path = issue.path;\n // Skip children-related issues (validated recursively)\n if (path.length > 0 && path[0] === \"children\") return null;\n // Skip \"type\" field issues (set internally)\n if (path.length === 1 && path[0] === \"type\") return null;\n\n const attrName = path.length > 0 ? String(path[0]) : undefined;\n\n const code = issue.code;\n\n if (code === \"invalid_type\") {\n // Missing required attribute\n if (issue.input === undefined) {\n if (attrName) {\n return `<${tagName}>: Missing required attribute \"${attrName}\"`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n // Type mismatch\n if (attrName) {\n return `<${tagName}>: Invalid type for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n if (code === \"invalid_value\") {\n if (attrName) {\n const values = (issue as unknown as { values: string[] }).values;\n if (values) {\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". Expected: ${values.map((v) => `\"${v}\"`).join(\", \")}`;\n }\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n if (code === \"too_small\" || code === \"too_big\") {\n if (attrName) {\n return `<${tagName}>: Invalid value for attribute \"${attrName}\". ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n }\n\n // Generic fallback\n if (attrName) {\n return `<${tagName}>: Attribute \"${attrName}\": ${issue.message}`;\n }\n return `<${tagName}>: ${issue.message}`;\n}\n\n// Properties that may be legitimately absent when using child element notation\n// or when the property is optional in practice (even if required in schema).\nconst CHILD_ELEMENT_PROPS: Record<string, Set<string>> = {\n flow: new Set([\"nodes\", \"connections\"]),\n table: new Set([\"columns\", \"rows\"]),\n chart: new Set([\"data\"]),\n timeline: new Set([\"items\"]),\n matrix: new Set([\"axes\", \"items\", \"quadrants\"]),\n processArrow: new Set([\"steps\"]),\n pyramid: new Set([\"levels\"]),\n tree: new Set([\"data\"]),\n ul: new Set([\"items\"]),\n ol: new Set([\"items\"]),\n icon: new Set([\"name\"]),\n svg: new Set([\"svgContent\"]),\n};\n\nfunction validateLeafNode(\n nodeType: string,\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const schema = leafNodeValidationSchemas[nodeType];\n if (!schema) return;\n const tagName = TYPE_TO_TAG[nodeType] ?? nodeType;\n const childProps = CHILD_ELEMENT_PROPS[nodeType];\n const parseResult = schema.safeParse(result);\n if (!parseResult.success) {\n const seen = new Set<string>();\n for (const issue of parseResult.error.issues) {\n // Skip only top-level missing child-element properties (path.length === 1)\n // Nested issues (e.g., data.children[0].label) must still be reported\n if (\n childProps &&\n issue.path.length === 1 &&\n childProps.has(String(issue.path[0])) &&\n issue.code === \"invalid_type\" &&\n issue.input === undefined\n ) {\n continue;\n }\n // Skip issues for universal attributes (x, y)\n if (issue.path.length > 0 && UNIVERSAL_ATTRS.has(String(issue.path[0]))) {\n continue;\n }\n const msg = formatZodIssue(issue, tagName);\n if (msg && !seen.has(msg)) {\n seen.add(msg);\n errors.push(msg);\n }\n }\n }\n}\n\n// ===== Types for XML parser output (preserveOrder mode) =====\ntype XmlNode = XmlElement | XmlTextNode;\ntype XmlTextNode = { \"#text\": string };\ninterface XmlElement {\n [tagName: string]: XmlNode[] | Record<string, string> | undefined;\n \":@\"?: Record<string, string>;\n}\n\n// ===== Coercion rule lookup =====\n\nfunction getCoercionRule(\n nodeType: string,\n propertyName: string,\n): CoercionRule | undefined {\n return NODE_COERCION_MAP[nodeType]?.[propertyName];\n}\n\n// ===== Dot notation helpers =====\n\n// ===== Dot notation expansion =====\nfunction expandDotNotation(attrs: Record<string, string>): {\n regular: Record<string, string>;\n dotGroups: Record<string, Record<string, string>>;\n} {\n const regular: Record<string, string> = {};\n const dotGroups: Record<string, Record<string, string>> = {};\n\n for (const [key, value] of Object.entries(attrs)) {\n const dotIndex = key.indexOf(\".\");\n if (dotIndex > 0) {\n const prefix = key.substring(0, dotIndex);\n const suffix = key.substring(dotIndex + 1);\n if (!dotGroups[prefix]) dotGroups[prefix] = {};\n dotGroups[prefix][suffix] = value;\n } else {\n regular[key] = value;\n }\n }\n\n return { regular, dotGroups };\n}\n\nfunction coerceDotGroup(\n prefix: string,\n subAttrs: Record<string, string>,\n rule: CoercionRule,\n tagName: string,\n errors: string[],\n): Record<string, unknown> {\n const objectShape = getObjectShapeFromRule(rule);\n\n const obj: Record<string, unknown> = {};\n if (objectShape) {\n for (const [subKey, subValue] of Object.entries(subAttrs)) {\n if (objectShape[subKey]) {\n const coerced = coerceWithRule(subValue, objectShape[subKey]);\n if (coerced.error !== null) {\n errors.push(`<${tagName}>: ${prefix}.${subKey}: ${coerced.error}`);\n } else {\n obj[subKey] = coerced.value;\n }\n } else {\n const knownSubKeys = Object.keys(objectShape);\n const suggestion = findClosestMatch(subKey, knownSubKeys);\n errors.push(\n `<${tagName}>: Unknown sub-attribute \"${prefix}.${subKey}\"${suggestion ? `. Did you mean \"${prefix}.${suggestion}\"?` : \"\"}`,\n );\n }\n }\n } else {\n errors.push(\n `<${tagName}>: Attribute \"${prefix}\" does not support dot notation`,\n );\n }\n return obj;\n}\n\n// ===== XML node helpers =====\nfunction isTextNode(node: XmlNode): node is XmlTextNode {\n return \"#text\" in node;\n}\n\nfunction getTagName(node: XmlElement): string {\n for (const key of Object.keys(node)) {\n if (key !== \":@\") return key;\n }\n throw new Error(\"No tag name found in XML element\");\n}\n\nfunction getAttributes(node: XmlElement): Record<string, string> {\n const attrs: Record<string, string> = {};\n const rawAttrs = node[\":@\"];\n if (rawAttrs) {\n for (const [key, value] of Object.entries(rawAttrs)) {\n const attrName = key.startsWith(\"@_\") ? key.slice(2) : key;\n attrs[attrName] = value.trim();\n }\n }\n return attrs;\n}\n\nfunction getChildElements(node: XmlElement): XmlElement[] {\n const tagName = getTagName(node);\n const children = node[tagName] as XmlNode[] | undefined;\n if (!children) return [];\n return children.filter((child): child is XmlElement => !isTextNode(child));\n}\n\nfunction getTextContent(node: XmlElement): string | undefined {\n const tagName = getTagName(node);\n const children = node[tagName] as XmlNode[] | undefined;\n if (!children) return undefined;\n const textParts: string[] = [];\n for (const child of children) {\n if (isTextNode(child)) {\n textParts.push(child[\"#text\"]);\n }\n }\n return textParts.length > 0 ? textParts.join(\"\") : undefined;\n}\n\nfunction getRawChildren(node: XmlElement): XmlNode[] {\n const tagName = getTagName(node);\n return (node[tagName] as XmlNode[] | undefined) ?? [];\n}\n\nconst INLINE_FORMAT_TAGS = new Set([\"B\", \"I\", \"A\", \"U\", \"S\", \"Mark\", \"Span\"]);\n\nfunction hasInlineFormatChildren(childElements: XmlElement[]): boolean {\n return (\n childElements.length > 0 &&\n childElements.every((el) => INLINE_FORMAT_TAGS.has(getTagName(el)))\n );\n}\n\ntype TextRunResult = {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n letterSpacing?: number;\n};\n\nfunction extractTextRuns(\n children: XmlNode[],\n inheritBold?: boolean,\n inheritItalic?: boolean,\n inheritHref?: string,\n inheritUnderline?: boolean,\n inheritStrike?: boolean,\n inheritHighlight?: string,\n inheritColor?: string,\n inheritFontFamily?: string,\n inheritLetterSpacing?: number,\n): TextRunResult[] {\n const runs: TextRunResult[] = [];\n for (const child of children) {\n if (isTextNode(child)) {\n const run: TextRunResult = { text: child[\"#text\"] };\n if (inheritBold) run.bold = true;\n if (inheritItalic) run.italic = true;\n if (inheritUnderline) run.underline = true;\n if (inheritStrike) run.strike = true;\n if (inheritHighlight) run.highlight = inheritHighlight;\n if (inheritColor) run.color = inheritColor;\n if (inheritHref) run.href = inheritHref;\n if (inheritFontFamily) run.fontFamily = inheritFontFamily;\n if (inheritLetterSpacing !== undefined)\n run.letterSpacing = inheritLetterSpacing;\n runs.push(run);\n } else {\n const tag = getTagName(child);\n const innerChildren = getRawChildren(child);\n if (tag === \"B\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n true,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"I\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n true,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"A\") {\n const href = getAttributes(child).href ?? \"\";\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n href,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"U\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n true,\n inheritStrike,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"S\") {\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n true,\n inheritHighlight,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"Mark\") {\n const rawColor = getAttributes(child).color;\n const color = rawColor && rawColor.trim() ? rawColor : \"FFFF00\";\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n color,\n inheritColor,\n inheritFontFamily,\n inheritLetterSpacing,\n ),\n );\n } else if (tag === \"Span\") {\n const spanAttrs = getAttributes(child);\n const rawSpanColor = spanAttrs.color;\n const spanColor =\n rawSpanColor && rawSpanColor.trim() ? rawSpanColor : inheritColor;\n const rawSpanFontFamily = spanAttrs.fontFamily;\n const spanFontFamily =\n rawSpanFontFamily && rawSpanFontFamily.trim()\n ? rawSpanFontFamily\n : inheritFontFamily;\n const rawSpanLetterSpacing = spanAttrs.letterSpacing;\n const spanLetterSpacing =\n rawSpanLetterSpacing && rawSpanLetterSpacing.trim()\n ? Number(rawSpanLetterSpacing)\n : inheritLetterSpacing;\n runs.push(\n ...extractTextRuns(\n innerChildren,\n inheritBold,\n inheritItalic,\n inheritHref,\n inheritUnderline,\n inheritStrike,\n inheritHighlight,\n spanColor,\n spanFontFamily,\n spanLetterSpacing,\n ),\n );\n }\n }\n }\n return runs;\n}\n\nfunction buildRunsAndText(\n node: XmlElement,\n): { runs: TextRunResult[]; text: string } | null {\n const rawChildren = getRawChildren(node);\n const childElements = rawChildren.filter(\n (c): c is XmlElement => !isTextNode(c),\n );\n if (!hasInlineFormatChildren(childElements)) return null;\n const runs = extractTextRuns(rawChildren);\n const text = runs.map((r) => r.text).join(\"\");\n return { runs, text };\n}\n\nfunction coerceChildAttrs(\n parentTagName: string,\n tagName: string,\n attrs: Record<string, string>,\n errors: string[],\n): Record<string, unknown> {\n const rules = CHILD_ELEMENT_COERCION_MAP[tagName];\n const result: Record<string, unknown> = {};\n const { regular: regularAttrs, dotGroups } = expandDotNotation(attrs);\n\n // Process dot-notation attributes\n for (const [prefix, subAttrs] of Object.entries(dotGroups)) {\n if (rules && rules[prefix]) {\n result[prefix] = coerceDotGroup(\n prefix,\n subAttrs,\n rules[prefix],\n `${parentTagName}.${tagName}`,\n errors,\n );\n } else if (rules) {\n const knownAttrs = getKnownChildAttributes(tagName);\n const suggestion = findClosestMatch(prefix, knownAttrs);\n errors.push(\n `<${parentTagName}>.<${tagName}>: Unknown attribute \"${prefix}\"${suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"}`,\n );\n } else {\n result[prefix] = {};\n for (const [subKey, subValue] of Object.entries(subAttrs)) {\n (result[prefix] as Record<string, unknown>)[subKey] =\n coerceFallback(subValue);\n }\n }\n }\n\n // Process regular attributes\n for (const [key, value] of Object.entries(regularAttrs)) {\n if (key in dotGroups) {\n if (rules && rules[key]) {\n const resolved = resolveMixedNotationShorthand(value, rules[key]);\n if (resolved.mode === \"ignore\") {\n continue;\n }\n if (resolved.mode === \"merge\") {\n result[key] = {\n ...resolved.value,\n ...(result[key] as Record<string, unknown>),\n };\n continue;\n }\n }\n errors.push(\n `<${parentTagName}>.<${tagName}>: Attribute \"${key}\" conflicts with dot-notation attributes. Use one or the other, not both`,\n );\n continue;\n }\n if (rules && rules[key]) {\n const coerced = coerceWithRule(value, rules[key]);\n if (coerced.error !== null) {\n errors.push(`<${parentTagName}>.<${tagName}>: ${coerced.error}`);\n } else {\n result[key] = coerced.value;\n }\n } else if (rules) {\n // Unknown attribute on child element\n const knownAttrs = getKnownChildAttributes(tagName);\n const suggestion = findClosestMatch(key, knownAttrs);\n errors.push(\n `<${parentTagName}>.<${tagName}>: Unknown attribute \"${key}\"${suggestion ? `. Did you mean \"${suggestion}\"?` : \"\"}`,\n );\n } else {\n result[key] = coerceFallback(value);\n }\n }\n return result;\n}\n\n// ===== Child element converters =====\ntype ChildElementConverter = (\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n node?: XmlElement,\n) => void;\n\nfunction convertProcessArrowChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const steps: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"ProcessArrowStep\") {\n errors.push(\n `Unknown child element <${tag}> inside <ProcessArrow>. Expected: <ProcessArrowStep>`,\n );\n continue;\n }\n steps.push(\n coerceChildAttrs(\"ProcessArrow\", tag, getAttributes(child), errors),\n );\n }\n result.steps = steps;\n}\n\nfunction convertPyramidChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const levels: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"PyramidLevel\") {\n errors.push(\n `Unknown child element <${tag}> inside <Pyramid>. Expected: <PyramidLevel>`,\n );\n continue;\n }\n levels.push(coerceChildAttrs(\"Pyramid\", tag, getAttributes(child), errors));\n }\n result.levels = levels;\n}\n\nfunction convertTimelineChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"TimelineItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <Timeline>. Expected: <TimelineItem>`,\n );\n continue;\n }\n items.push(coerceChildAttrs(\"Timeline\", tag, getAttributes(child), errors));\n }\n result.items = items;\n}\n\nfunction convertMatrixChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"MatrixAxes\":\n result.axes = coerceChildAttrs(\n \"Matrix\",\n tag,\n getAttributes(child),\n errors,\n );\n break;\n case \"MatrixQuadrants\":\n result.quadrants = coerceChildAttrs(\n \"Matrix\",\n tag,\n getAttributes(child),\n errors,\n );\n break;\n case \"MatrixItem\":\n items.push(\n coerceChildAttrs(\"Matrix\", tag, getAttributes(child), errors),\n );\n break;\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Matrix>. Expected: <MatrixAxes>, <MatrixQuadrants>, or <MatrixItem>`,\n );\n }\n }\n if (items.length > 0) {\n result.items = items;\n }\n}\n\nfunction convertFlowChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const nodes: Record<string, unknown>[] = [];\n const connections: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"FlowNode\":\n nodes.push(coerceChildAttrs(\"Flow\", tag, getAttributes(child), errors));\n break;\n case \"FlowConnection\":\n connections.push(\n coerceChildAttrs(\"Flow\", tag, getAttributes(child), errors),\n );\n break;\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Flow>. Expected: <FlowNode> or <FlowConnection>`,\n );\n }\n }\n if (nodes.length > 0) {\n result.nodes = nodes;\n }\n if (connections.length > 0) {\n result.connections = connections;\n }\n}\n\nfunction convertChartChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const data: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"ChartSeries\") {\n errors.push(\n `Unknown child element <${tag}> inside <Chart>. Expected: <ChartSeries>`,\n );\n continue;\n }\n const attrs = getAttributes(child);\n const series: Record<string, unknown> = {\n labels: [],\n values: [],\n };\n if (attrs.name !== undefined) {\n // chartDataSchema.name は z.string().optional() なのでそのまま文字列として使用\n series.name = attrs.name;\n }\n\n for (const dp of getChildElements(child)) {\n const dpTag = getTagName(dp);\n if (dpTag !== \"ChartDataPoint\") {\n errors.push(\n `Unknown child element <${dpTag}> inside <ChartSeries>. Expected: <ChartDataPoint>`,\n );\n continue;\n }\n const dpAttrs = getAttributes(dp);\n if (dpAttrs.label === undefined) {\n errors.push('<ChartDataPoint> requires a \"label\" attribute');\n }\n if (dpAttrs.value === undefined) {\n errors.push('<ChartDataPoint> requires a \"value\" attribute');\n }\n if (dpAttrs.label === undefined || dpAttrs.value === undefined) {\n continue;\n }\n const numValue = Number(dpAttrs.value);\n if (isNaN(numValue)) {\n errors.push(\n `Cannot convert \"${dpAttrs.value}\" to number in <ChartDataPoint> \"value\" attribute`,\n );\n continue;\n }\n (series.labels as string[]).push(dpAttrs.label);\n (series.values as number[]).push(numValue);\n }\n data.push(series);\n }\n result.data = data;\n}\n\nfunction convertTableChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const columns: Record<string, unknown>[] = [];\n const rows: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n switch (tag) {\n case \"Col\":\n columns.push(\n coerceChildAttrs(\"Table\", tag, getAttributes(child), errors),\n );\n break;\n case \"Tr\": {\n const rowAttrs = getAttributes(child);\n const cells: Record<string, unknown>[] = [];\n for (const cellEl of getChildElements(child)) {\n const cellTag = getTagName(cellEl);\n if (cellTag !== \"Td\") {\n errors.push(\n `Unknown child element <${cellTag}> inside <Tr>. Expected: <Td>`,\n );\n continue;\n }\n const cellAttrs = coerceChildAttrs(\n \"Tr\",\n cellTag,\n getAttributes(cellEl),\n errors,\n );\n const runsResult = buildRunsAndText(cellEl);\n if (runsResult) {\n cellAttrs.runs = runsResult.runs;\n cellAttrs.text = runsResult.text;\n } else {\n const cellText = getTextContent(cellEl);\n if (cellText !== undefined && !(\"text\" in cellAttrs)) {\n cellAttrs.text = cellText;\n }\n }\n cells.push(cellAttrs);\n }\n const row: Record<string, unknown> = { cells };\n if (rowAttrs.height !== undefined) {\n const h = Number(rowAttrs.height);\n if (isNaN(h)) {\n errors.push(\n `Cannot convert \"${rowAttrs.height}\" to number in <Tr> \"height\" attribute`,\n );\n } else {\n row.height = h;\n }\n }\n rows.push(row);\n break;\n }\n default:\n errors.push(\n `Unknown child element <${tag}> inside <Table>. Expected: <Col> or <Tr>`,\n );\n }\n }\n if (columns.length > 0) {\n result.columns = columns;\n } else if (rows.length > 0) {\n // Col が未指定の場合、行のセル数(colspan 考慮)からデフォルトの columns を自動生成\n const maxCells = Math.max(\n ...rows.map((row) =>\n (row.cells as Record<string, unknown>[]).reduce(\n (sum, cell) => sum + ((cell.colspan as number) ?? 1),\n 0,\n ),\n ),\n );\n result.columns = Array.from({ length: maxCells }, () => ({}));\n }\n if (rows.length > 0) {\n result.rows = rows;\n }\n}\n\nfunction convertTreeItem(\n element: XmlElement,\n errors: string[],\n): Record<string, unknown> {\n const attrs = getAttributes(element);\n if (attrs.label === undefined) {\n errors.push('<TreeItem> requires a \"label\" attribute');\n }\n const item: Record<string, unknown> = {};\n if (attrs.label !== undefined) {\n item.label = attrs.label;\n }\n if (attrs.color !== undefined) {\n item.color = attrs.color;\n }\n const children = getChildElements(element);\n if (children.length > 0) {\n item.children = children\n .map((child) => {\n const tag = getTagName(child);\n if (tag !== \"TreeItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <TreeItem>. Expected: <TreeItem>`,\n );\n return null;\n }\n return convertTreeItem(child, errors);\n })\n .filter((item): item is Record<string, unknown> => item !== null);\n }\n return item;\n}\n\nfunction convertTreeChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n if (childElements.length !== 1) {\n errors.push(\n `<Tree> must have exactly 1 <TreeItem> child element, but got ${childElements.length}`,\n );\n return;\n }\n const child = childElements[0];\n const tag = getTagName(child);\n if (tag !== \"TreeItem\") {\n errors.push(\n `Unknown child element <${tag}> inside <Tree>. Expected: <TreeItem>`,\n );\n return;\n }\n result.data = convertTreeItem(child, errors);\n}\n\nfunction convertListChildren(\n parentTag: string,\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n const items: Record<string, unknown>[] = [];\n for (const child of childElements) {\n const tag = getTagName(child);\n if (tag !== \"Li\") {\n errors.push(\n `Unknown child element <${tag}> inside <${parentTag}>. Expected: <Li>`,\n );\n continue;\n }\n const attrs = coerceChildAttrs(\n parentTag,\n tag,\n getAttributes(child),\n errors,\n );\n const runsResult = buildRunsAndText(child);\n if (runsResult) {\n attrs.runs = runsResult.runs;\n attrs.text = runsResult.text;\n } else {\n const textContent = getTextContent(child);\n if (textContent !== undefined && !(\"text\" in attrs)) {\n attrs.text = textContent;\n }\n }\n items.push(attrs);\n }\n result.items = items;\n}\n\n// SVG 要素を XML 文字列に再構築する\nconst svgBuilder = new XMLBuilder({\n preserveOrder: true,\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n});\n\nfunction serializeSvgElement(svgElement: XmlElement): string {\n return String(svgBuilder.build([svgElement]));\n}\n\nfunction convertSvgChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n): void {\n if (childElements.length !== 1) {\n errors.push(\n `<Svg>: Expected exactly one <svg> child element, but found ${childElements.length} child element(s)`,\n );\n return;\n }\n\n const child = childElements[0];\n const tag = getTagName(child);\n if (tag !== \"svg\") {\n errors.push(`<Svg>: Expected <svg> child element, but found <${tag}>`);\n return;\n }\n\n result.svgContent = serializeSvgElement(child);\n}\n\nfunction convertTextInlineChildren(\n childElements: XmlElement[],\n result: Record<string, unknown>,\n errors: string[],\n node?: XmlElement,\n): void {\n // インラインフォーマットタグ以外の子要素がある場合はエラー\n for (const el of childElements) {\n const tag = getTagName(el);\n if (!INLINE_FORMAT_TAGS.has(tag)) {\n errors.push(\n `<Text>: Unexpected child element <${tag}>. Only <B>, <I>, <A>, <U>, <S>, <Mark>, and <Span> are allowed inside <Text>`,\n );\n return;\n }\n }\n if (!node || childElements.length === 0) return;\n const runsResult = buildRunsAndText(node);\n if (runsResult) {\n result.runs = runsResult.runs;\n result.text = runsResult.text;\n }\n}\n\nconst CHILD_ELEMENT_CONVERTERS: Record<string, ChildElementConverter> = {\n text: convertTextInlineChildren,\n ul: (childElements, result, errors) =>\n convertListChildren(\"Ul\", childElements, result, errors),\n ol: (childElements, result, errors) =>\n convertListChildren(\"Ol\", childElements, result, errors),\n processArrow: convertProcessArrowChildren,\n pyramid: convertPyramidChildren,\n timeline: convertTimelineChildren,\n matrix: convertMatrixChildren,\n flow: convertFlowChildren,\n chart: convertChartChildren,\n table: convertTableChildren,\n tree: convertTreeChildren,\n svg: convertSvgChildren,\n};\n\n// ===== Node conversion =====\nfunction convertElement(\n node: XmlElement,\n errors: string[],\n): Record<string, unknown> | null {\n const tagName = getTagName(node);\n const nodeType = TAG_TO_TYPE[tagName];\n const attrs = getAttributes(node);\n const childElements = getChildElements(node);\n const textContent = getTextContent(node);\n\n if (nodeType) {\n return convertPomNode(\n nodeType,\n tagName,\n attrs,\n childElements,\n textContent,\n errors,\n node,\n );\n } else {\n errors.push(`Unknown tag: <${tagName}>`);\n return null;\n }\n}\n\nfunction convertPomNode(\n nodeType: string,\n tagName: string,\n attrs: Record<string, string>,\n childElements: XmlElement[],\n textContent: string | undefined,\n errors: string[],\n xmlNode?: XmlElement,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { type: nodeType };\n\n // Expand dot-notation attributes (e.g., fill.color=\"hex\" → { fill: { color: \"hex\" } })\n const { regular: regularAttrs, dotGroups } = expandDotNotation(attrs);\n\n for (const [prefix, subAttrs] of Object.entries(dotGroups)) {\n if (prefix === \"type\") continue;\n const rule = getCoercionRule(nodeType, prefix);\n if (rule) {\n result[prefix] = coerceDotGroup(prefix, subAttrs, rule, tagName, errors);\n } else {\n const knownAttrs = getKnownAttributes(nodeType);\n const suggestion = findClosestMatch(prefix, knownAttrs);\n if (suggestion) {\n errors.push(\n `<${tagName}>: Unknown attribute \"${prefix}\". Did you mean \"${suggestion}\"?`,\n );\n } else {\n errors.push(`<${tagName}>: Unknown attribute \"${prefix}\"`);\n }\n }\n }\n\n for (const [key, value] of Object.entries(regularAttrs)) {\n if (key === \"type\") continue;\n // Conflict check: dot-notation and regular attribute for the same key\n if (key in dotGroups) {\n const ruleForConflict = getCoercionRule(nodeType, key);\n if (ruleForConflict) {\n const resolved = resolveMixedNotationShorthand(value, ruleForConflict);\n if (resolved.mode === \"ignore\") {\n continue;\n }\n if (resolved.mode === \"merge\") {\n result[key] = {\n ...resolved.value,\n ...(result[key] as Record<string, unknown>),\n };\n continue;\n }\n }\n errors.push(\n `<${tagName}>: Attribute \"${key}\" conflicts with dot-notation attributes (e.g., \"${key}.xxx\"). Use one or the other, not both`,\n );\n continue;\n }\n const rule = getCoercionRule(nodeType, key);\n if (rule) {\n const coerced = coerceWithRule(value, rule);\n if (coerced.error !== null) {\n errors.push(`<${tagName}>: ${coerced.error}`);\n } else {\n result[key] = coerced.value;\n }\n } else if (UNIVERSAL_ATTRS.has(key)) {\n // Allow universal attributes (e.g., x/y for Layer children)\n result[key] = coerceFallback(value);\n } else {\n // Unknown attribute\n const knownAttrs = getKnownAttributes(nodeType);\n const suggestion = findClosestMatch(key, knownAttrs);\n if (suggestion) {\n errors.push(\n `<${tagName}>: Unknown attribute \"${key}\". Did you mean \"${suggestion}\"?`,\n );\n } else {\n errors.push(`<${tagName}>: Unknown attribute \"${key}\"`);\n }\n }\n }\n\n // Text content → text property for nodes that support it\n if (textContent !== undefined && TEXT_CONTENT_NODES.has(nodeType)) {\n if (!(\"text\" in result)) {\n result.text = textContent;\n }\n }\n\n // Child element notation for complex properties\n const childConverter = CHILD_ELEMENT_CONVERTERS[nodeType];\n if (childConverter && childElements.length > 0) {\n childConverter(childElements, result, errors, xmlNode);\n }\n // Children for container nodes\n else if (CONTAINER_TYPES.has(nodeType) && childElements.length > 0) {\n const convertedChildren = childElements\n .map((child) => convertElement(child, errors))\n .filter((child): child is Record<string, unknown> => child !== null);\n result.children = convertedChildren;\n }\n // Leaf nodes that shouldn't have child elements\n else if (\n !CONTAINER_TYPES.has(nodeType) &&\n !childConverter &&\n childElements.length > 0\n ) {\n errors.push(\n `<${tagName}>: Unexpected child elements. <${tagName}> does not accept child elements`,\n );\n }\n\n // Zod validation for leaf nodes\n if (!CONTAINER_TYPES.has(nodeType)) {\n validateLeafNode(nodeType, result, errors);\n }\n\n // Icon: normalize color / bgColor\n if (nodeType === \"icon\") {\n if (typeof result.color === \"string\" && !result.color.startsWith(\"#\")) {\n result.color = `#${result.color}`;\n }\n if (typeof result.bgColor === \"string\" && !result.bgColor.startsWith(\"#\")) {\n result.bgColor = `#${result.bgColor}`;\n }\n }\n\n // Svg: normalize color and validate svgContent\n if (nodeType === \"svg\") {\n if (typeof result.color === \"string\" && !result.color.startsWith(\"#\")) {\n result.color = `#${result.color}`;\n }\n if (result.svgContent === undefined) {\n errors.push(\"<Svg>: A <svg> child element is required\");\n }\n }\n\n return result;\n}\n\n/**\n * XML 文字列を POMNode 配列に変換する。\n *\n * 最上位は `<Slide>` 要素のみが許容される。各 `<Slide>` が 1 つのスライドに\n * 対応し、その子要素がスライドのルート POMNode となる。子要素が複数ある場合は\n * 暗黙的に VStack でラップされる。\n *\n * XML タグは POM ノードタイプにマッピングされ、属性値は Zod スキーマを参照して\n * 適切な型(number, boolean, array, object)に変換される。\n * 未知のタグ名が指定された場合はエラーがスローされる。\n *\n * @example\n * ```typescript\n * import { parseXml, buildPptx } from \"@hirokisakabe/pom\";\n *\n * const xml = `\n * <Slide>\n * <VStack gap=\"16\" padding=\"32\">\n * <Text fontSize=\"32\" bold=\"true\">売上レポート</Text>\n * </VStack>\n * </Slide>\n * `;\n *\n * const nodes = parseXml(xml);\n * const pptx = await buildPptx(nodes, { w: 1280, h: 720 });\n * ```\n */\nexport function parseXml(xmlString: string): POMNode[] {\n if (!xmlString.trim()) return [];\n\n const parser = new XMLParser({\n preserveOrder: true,\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n parseAttributeValue: false,\n parseTagValue: false,\n trimValues: false,\n });\n\n const wrappedXml = `<__root__>${xmlString}</__root__>`;\n const parsed: XmlElement[] = parser.parse(wrappedXml) as XmlElement[];\n\n if (!parsed || parsed.length === 0) return [];\n\n const rootElement = parsed[0];\n const rootChildren = (rootElement[\"__root__\"] ?? []) as XmlNode[];\n\n const errors: string[] = [];\n const slideElements = rootChildren.filter(\n (child): child is XmlElement => !isTextNode(child),\n );\n\n const nodes: POMNode[] = [];\n for (const slideEl of slideElements) {\n const tagName = getTagName(slideEl);\n if (tagName !== \"Slide\") {\n errors.push(\n `Top-level element must be <Slide>, but got <${tagName}>. Wrap your slide content in <Slide>...</Slide>.`,\n );\n continue;\n }\n if (Object.keys(getAttributes(slideEl)).length > 0) {\n errors.push(`<Slide>: Attributes are not supported`);\n }\n const slideChildren = getChildElements(slideEl);\n if (slideChildren.length === 0) {\n errors.push(`<Slide> must contain at least one child element`);\n continue;\n }\n const converted = slideChildren\n .map((child) => convertElement(child, errors))\n .filter((c): c is Record<string, unknown> => c !== null);\n if (converted.length === 0) continue;\n if (converted.length === 1) {\n nodes.push(converted[0] as POMNode);\n } else {\n nodes.push({\n type: \"vstack\",\n children: converted,\n } as POMNode);\n }\n }\n\n if (errors.length > 0) {\n throw new ParseXmlError(errors);\n }\n\n return nodes;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializeXml.d.ts","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"serializeXml.d.ts","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"mappings":";;;;;AAiKA;;;;AAA6C;;;;;;;;;iBAA7B,YAAA,CAAa,KAAgB,EAAT,OAAO"}
|
|
@@ -42,6 +42,7 @@ function serializeRun(run) {
|
|
|
42
42
|
const spanAttrs = [];
|
|
43
43
|
if (run.color) spanAttrs.push(`color="${escapeAttrValue(run.color)}"`);
|
|
44
44
|
if (run.fontFamily) spanAttrs.push(`fontFamily="${escapeAttrValue(run.fontFamily)}"`);
|
|
45
|
+
if (run.letterSpacing !== void 0) spanAttrs.push(`letterSpacing="${run.letterSpacing}"`);
|
|
45
46
|
if (spanAttrs.length > 0) content = `<Span ${spanAttrs.join(" ")}>${content}</Span>`;
|
|
46
47
|
if (run.strike) content = `<S>${content}</S>`;
|
|
47
48
|
if (run.underline) content = `<U>${content}</U>`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializeXml.js","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"sourcesContent":["import type { POMNode } from \"../types.ts\";\nimport { TAG_TO_TYPE } from \"./parseXml.ts\";\n\nconst TYPE_TO_TAG: Record<string, string> = Object.fromEntries(\n Object.entries(TAG_TO_TYPE).map(([tag, type]) => [type, tag]),\n);\n\n// runs と svgContent は専用の直列化パスで処理する\nconst SKIP_KEYS = new Set([\"type\", \"children\", \"runs\", \"svgContent\"]);\n\n// runs によるインライン装飾を child element として直列化するノードタイプ\nconst INLINE_CONTENT_TYPES = new Set([\"text\", \"shape\"]);\n\nconst CONTAINER_TYPES = new Set([\"vstack\", \"hstack\", \"layer\"]);\n\ninterface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n}\n\nfunction escapeAttrValue(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeXmlContent(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction serializePrimitive(value: string | number | boolean): string {\n if (typeof value === \"string\") return escapeAttrValue(value);\n if (typeof value === \"number\") return String(value);\n return value ? \"true\" : \"false\";\n}\n\nfunction serializeAttrs(node: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n if (SKIP_KEYS.has(key) || value === undefined) continue;\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n for (const [subKey, subValue] of Object.entries(\n value as Record<string, unknown>,\n )) {\n if (subValue !== undefined) {\n parts.push(\n `${key}.${subKey}=\"${serializePrimitive(subValue as string | number | boolean)}\"`,\n );\n }\n }\n } else if (Array.isArray(value)) {\n parts.push(`${key}=\"${escapeAttrValue(JSON.stringify(value))}\"`);\n } else if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n parts.push(`${key}=\"${serializePrimitive(value)}\"`);\n }\n }\n return parts.length > 0 ? \" \" + parts.join(\" \") : \"\";\n}\n\nfunction serializeRun(run: TextRun): string {\n let content = escapeXmlContent(run.text);\n\n if (run.href) {\n content = `<A href=\"${escapeAttrValue(run.href)}\">${content}</A>`;\n }\n if (run.highlight) {\n content = `<Mark color=\"${escapeAttrValue(run.highlight)}\">${content}</Mark>`;\n }\n const spanAttrs: string[] = [];\n if (run.color) spanAttrs.push(`color=\"${escapeAttrValue(run.color)}\"`);\n if (run.fontFamily)\n spanAttrs.push(`fontFamily=\"${escapeAttrValue(run.fontFamily)}\"`);\n if (spanAttrs.length > 0) {\n content = `<Span ${spanAttrs.join(\" \")}>${content}</Span>`;\n }\n if (run.strike) content = `<S>${content}</S>`;\n if (run.underline) content = `<U>${content}</U>`;\n if (run.italic) content = `<I>${content}</I>`;\n if (run.bold) content = `<B>${content}</B>`;\n return content;\n}\n\nfunction serializeRuns(runs: TextRun[]): string {\n return runs.map(serializeRun).join(\"\");\n}\n\nfunction serializeNode(node: POMNode, depth: number): string {\n const indent = \" \".repeat(depth);\n const tag = TYPE_TO_TAG[node.type];\n const nodeRecord = node as Record<string, unknown>;\n\n if (CONTAINER_TYPES.has(node.type)) {\n const children = (nodeRecord.children as POMNode[]) ?? [];\n const attrStr = serializeAttrs(nodeRecord);\n if (children.length === 0) {\n return `${indent}<${tag}${attrStr} />`;\n }\n const childrenStr = children\n .map((c) => serializeNode(c, depth + 1))\n .join(\"\\n\");\n return `${indent}<${tag}${attrStr}>\\n${childrenStr}\\n${indent}</${tag}>`;\n }\n\n if (node.type === \"svg\") {\n const svgContent = (nodeRecord.svgContent as string) ?? \"\";\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr}>\\n${svgContent}\\n${indent}</${tag}>`;\n }\n\n // Text / Shape: runs があればインライン child element として直列化し装飾を保持する\n if (\n INLINE_CONTENT_TYPES.has(node.type) &&\n Array.isArray(nodeRecord.runs) &&\n (nodeRecord.runs as unknown[]).length > 0\n ) {\n const runs = nodeRecord.runs as TextRun[];\n // runs がある場合、text は runs から復元できるため属性からも除外する\n const attrsWithoutText = { ...nodeRecord, text: undefined };\n const attrStr = serializeAttrs(attrsWithoutText);\n const inlineContent = serializeRuns(runs);\n return `${indent}<${tag}${attrStr}>${inlineContent}</${tag}>`;\n }\n\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr} />`;\n}\n\n/**\n * POMNode 配列を XML 文字列に変換する。\n *\n * parseXml の逆操作として機能する。runs(インライン装飾)は B/I/A/U/S/Mark/Span\n * タグとして child element に直列化されるため、テキストの装飾情報も保持される。\n *\n * @example\n * ```typescript\n * import { parseXml, serializeXml } from \"@hirokisakabe/pom\";\n *\n * const nodes = parseXml(xml);\n * // ... ノードの並び替えなど ...\n * const newXml = serializeXml(nodes);\n * ```\n */\nexport function serializeXml(nodes: POMNode[]): string {\n return nodes\n .map((node) => `<Slide>\\n${serializeNode(node, 1)}\\n</Slide>`)\n .join(\"\\n\");\n}\n"],"mappings":";;AAGA,MAAM,cAAsC,OAAO,YACjD,OAAO,QAAQ,WAAW,
|
|
1
|
+
{"version":3,"file":"serializeXml.js","names":[],"sources":["../../src/parseXml/serializeXml.ts"],"sourcesContent":["import type { POMNode } from \"../types.ts\";\nimport { TAG_TO_TYPE } from \"./parseXml.ts\";\n\nconst TYPE_TO_TAG: Record<string, string> = Object.fromEntries(\n Object.entries(TAG_TO_TYPE).map(([tag, type]) => [type, tag]),\n);\n\n// runs と svgContent は専用の直列化パスで処理する\nconst SKIP_KEYS = new Set([\"type\", \"children\", \"runs\", \"svgContent\"]);\n\n// runs によるインライン装飾を child element として直列化するノードタイプ\nconst INLINE_CONTENT_TYPES = new Set([\"text\", \"shape\"]);\n\nconst CONTAINER_TYPES = new Set([\"vstack\", \"hstack\", \"layer\"]);\n\ninterface TextRun {\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strike?: boolean;\n highlight?: string;\n color?: string;\n href?: string;\n fontFamily?: string;\n letterSpacing?: number;\n}\n\nfunction escapeAttrValue(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/\"/g, \""\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction escapeXmlContent(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nfunction serializePrimitive(value: string | number | boolean): string {\n if (typeof value === \"string\") return escapeAttrValue(value);\n if (typeof value === \"number\") return String(value);\n return value ? \"true\" : \"false\";\n}\n\nfunction serializeAttrs(node: Record<string, unknown>): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(node)) {\n if (SKIP_KEYS.has(key) || value === undefined) continue;\n if (typeof value === \"object\" && value !== null && !Array.isArray(value)) {\n for (const [subKey, subValue] of Object.entries(\n value as Record<string, unknown>,\n )) {\n if (subValue !== undefined) {\n parts.push(\n `${key}.${subKey}=\"${serializePrimitive(subValue as string | number | boolean)}\"`,\n );\n }\n }\n } else if (Array.isArray(value)) {\n parts.push(`${key}=\"${escapeAttrValue(JSON.stringify(value))}\"`);\n } else if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n parts.push(`${key}=\"${serializePrimitive(value)}\"`);\n }\n }\n return parts.length > 0 ? \" \" + parts.join(\" \") : \"\";\n}\n\nfunction serializeRun(run: TextRun): string {\n let content = escapeXmlContent(run.text);\n\n if (run.href) {\n content = `<A href=\"${escapeAttrValue(run.href)}\">${content}</A>`;\n }\n if (run.highlight) {\n content = `<Mark color=\"${escapeAttrValue(run.highlight)}\">${content}</Mark>`;\n }\n const spanAttrs: string[] = [];\n if (run.color) spanAttrs.push(`color=\"${escapeAttrValue(run.color)}\"`);\n if (run.fontFamily)\n spanAttrs.push(`fontFamily=\"${escapeAttrValue(run.fontFamily)}\"`);\n if (run.letterSpacing !== undefined)\n spanAttrs.push(`letterSpacing=\"${run.letterSpacing}\"`);\n if (spanAttrs.length > 0) {\n content = `<Span ${spanAttrs.join(\" \")}>${content}</Span>`;\n }\n if (run.strike) content = `<S>${content}</S>`;\n if (run.underline) content = `<U>${content}</U>`;\n if (run.italic) content = `<I>${content}</I>`;\n if (run.bold) content = `<B>${content}</B>`;\n return content;\n}\n\nfunction serializeRuns(runs: TextRun[]): string {\n return runs.map(serializeRun).join(\"\");\n}\n\nfunction serializeNode(node: POMNode, depth: number): string {\n const indent = \" \".repeat(depth);\n const tag = TYPE_TO_TAG[node.type];\n const nodeRecord = node as Record<string, unknown>;\n\n if (CONTAINER_TYPES.has(node.type)) {\n const children = (nodeRecord.children as POMNode[]) ?? [];\n const attrStr = serializeAttrs(nodeRecord);\n if (children.length === 0) {\n return `${indent}<${tag}${attrStr} />`;\n }\n const childrenStr = children\n .map((c) => serializeNode(c, depth + 1))\n .join(\"\\n\");\n return `${indent}<${tag}${attrStr}>\\n${childrenStr}\\n${indent}</${tag}>`;\n }\n\n if (node.type === \"svg\") {\n const svgContent = (nodeRecord.svgContent as string) ?? \"\";\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr}>\\n${svgContent}\\n${indent}</${tag}>`;\n }\n\n // Text / Shape: runs があればインライン child element として直列化し装飾を保持する\n if (\n INLINE_CONTENT_TYPES.has(node.type) &&\n Array.isArray(nodeRecord.runs) &&\n (nodeRecord.runs as unknown[]).length > 0\n ) {\n const runs = nodeRecord.runs as TextRun[];\n // runs がある場合、text は runs から復元できるため属性からも除外する\n const attrsWithoutText = { ...nodeRecord, text: undefined };\n const attrStr = serializeAttrs(attrsWithoutText);\n const inlineContent = serializeRuns(runs);\n return `${indent}<${tag}${attrStr}>${inlineContent}</${tag}>`;\n }\n\n const attrStr = serializeAttrs(nodeRecord);\n return `${indent}<${tag}${attrStr} />`;\n}\n\n/**\n * POMNode 配列を XML 文字列に変換する。\n *\n * parseXml の逆操作として機能する。runs(インライン装飾)は B/I/A/U/S/Mark/Span\n * タグとして child element に直列化されるため、テキストの装飾情報も保持される。\n *\n * @example\n * ```typescript\n * import { parseXml, serializeXml } from \"@hirokisakabe/pom\";\n *\n * const nodes = parseXml(xml);\n * // ... ノードの並び替えなど ...\n * const newXml = serializeXml(nodes);\n * ```\n */\nexport function serializeXml(nodes: POMNode[]): string {\n return nodes\n .map((node) => `<Slide>\\n${serializeNode(node, 1)}\\n</Slide>`)\n .join(\"\\n\");\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","names":[],"sources":["../../../src/registry/definitions/list.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport { measureFontLineHeightRatio } from \"../../calcYogaLayout/fontLoader.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderUlNode, renderOlNode } from \"../../renderPptx/nodes/list.ts\";\n\nfunction applyListYogaStyle(\n node: POMNode,\n yn: YogaNode,\n yoga: Yoga,\n ctx: BuildContext,\n) {\n const n = node as Extract<POMNode, { type: \"ul\" | \"ol\" }>;\n const combinedText = n.items.map((item) => item.text).join(\"\\n\");\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const spacingMultiple = n.lineHeight ?? 1.3;\n\n const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);\n const lineHeight = fontMetricsRatio * spacingMultiple;\n\n // バレット/番号のインデント幅(pptxgenjs DEF_BULLET_MARGIN = 27pt = 36px @96dpi)\n const bulletIndentPx = 36;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);\n\n const { widthPx, heightPx } = measureText(\n combinedText,\n textMaxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return {\n width: widthPx + bulletIndentPx,\n height: heightPx,\n };\n });\n}\n\nexport const ulNodeDef: NodeDefinition = {\n type: \"ul\",\n category: \"leaf\",\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderUlNode(node as Extract<typeof node, { type: \"ul\" }>, ctx);\n },\n};\n\nexport const olNodeDef: NodeDefinition = {\n type: \"ol\",\n category: \"leaf\",\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderOlNode(node as Extract<typeof node, { type: \"ol\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,SAAS,mBACP,MACA,IACA,MACA,KACA;CACA,MAAM,IAAI;CACV,MAAM,eAAe,EAAE,MAAM,KAAK,SAAS,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"list.js","names":[],"sources":["../../../src/registry/definitions/list.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport { measureFontLineHeightRatio } from \"../../calcYogaLayout/fontLoader.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderUlNode, renderOlNode } from \"../../renderPptx/nodes/list.ts\";\n\nfunction applyListYogaStyle(\n node: POMNode,\n yn: YogaNode,\n yoga: Yoga,\n ctx: BuildContext,\n) {\n const n = node as Extract<POMNode, { type: \"ul\" | \"ol\" }>;\n const combinedText = n.items.map((item) => item.text).join(\"\\n\");\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const spacingMultiple = n.lineHeight ?? 1.3;\n\n const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);\n const lineHeight = fontMetricsRatio * spacingMultiple;\n\n // バレット/番号のインデント幅(pptxgenjs DEF_BULLET_MARGIN = 27pt = 36px @96dpi)\n const bulletIndentPx = 36;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);\n\n const { widthPx, heightPx } = measureText(\n combinedText,\n textMaxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return {\n width: widthPx + bulletIndentPx,\n height: heightPx,\n };\n });\n}\n\nexport const ulNodeDef: NodeDefinition = {\n type: \"ul\",\n category: \"leaf\",\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderUlNode(node as Extract<typeof node, { type: \"ul\" }>, ctx);\n },\n};\n\nexport const olNodeDef: NodeDefinition = {\n type: \"ol\",\n category: \"leaf\",\n applyYogaStyle: applyListYogaStyle,\n render(node, ctx) {\n renderOlNode(node as Extract<typeof node, { type: \"ol\" }>, ctx);\n },\n};\n"],"mappings":";;;;AAQA,SAAS,mBACP,MACA,IACA,MACA,KACA;CACA,MAAM,IAAI;CACV,MAAM,eAAe,EAAE,MAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI;CAC/D,MAAM,aAAa,EAAE,YAAY;CACjC,MAAM,aAAa,EAAE,cAAc;CACnC,MAAM,aAAa,EAAE,OAAO,SAAS;CACrC,MAAM,kBAAkB,EAAE,cAAc;CAGxC,MAAM,aADmB,2BAA2B,UAClB,IAAI;CAGtC,MAAM,iBAAiB;CAEvB,GAAG,gBAAgB,OAAO,cAAc;EACtC,MAAM,oBAAoB;GACxB,QAAQ,WAAR;IACE,KAAK,KAAK,wBACR,OAAO,OAAO;IAChB,KAAK,KAAK;IACV,KAAK,KAAK,sBACR,OAAO;IACT,SACE,OAAO,OAAO;GAClB;EACF,EAAA,CAAG;EAIH,MAAM,EAAE,SAAS,aAAa,YAC5B,cAHqB,KAAK,IAAI,GAAG,aAAa,cAIjC,GACb;GACE;GACA;GACA;GACA;EACF,GACA,IAAI,mBACN;EAEA,OAAO;GACL,OAAO,UAAU;GACjB,QAAQ;EACV;CACF,CAAC;AACH;AAEA,MAAa,YAA4B;CACvC,MAAM;CACN,UAAU;CACV,gBAAgB;CAChB,OAAO,MAAM,KAAK;EAChB,aAAa,MAA8C,GAAG;CAChE;AACF;AAEA,MAAa,YAA4B;CACvC,MAAM;CACN,UAAU;CACV,gBAAgB;CAChB,OAAO,MAAM,KAAK;EAChB,aAAa,MAA8C,GAAG;CAChE;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/registry/definitions/shape.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderShapeNode } from \"../../renderPptx/nodes/shape.ts\";\n\nexport const shapeNodeDef: NodeDefinition = {\n type: \"shape\",\n category: \"leaf\",\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"shape\" }>;\n if (n.text) {\n const text = n.text;\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n }\n },\n render(node, ctx) {\n renderShapeNode(node as Extract<typeof node, { type: \"shape\" }>, ctx);\n },\n};\n"],"mappings":";;;AAOA,MAAa,eAA+B;CAC1C,MAAM;CACN,UAAU;CACV,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,IAAI,EAAE,MAAM;GACV,MAAM,OAAO,EAAE;GACf,MAAM,aAAa,EAAE,YAAY;GACjC,MAAM,aAAa,EAAE,cAAc;GACnC,MAAM,aAAa,EAAE,OAAO,SAAS;GACrC,MAAM,aAAa,EAAE,cAAc;GAEnC,GAAG,gBAAgB,OAAO,cAAc;IAatC,MAAM,EAAE,SAAS,aAAa,YAC5B,aAbwB;KACxB,QAAQ,WAAR;MACE,KAAK,KAAK,wBACR,OAAO,OAAO;MAChB,KAAK,KAAK;MACV,KAAK,KAAK,sBACR,OAAO;MACT,SACE,OAAO,OAAO;KAClB;IACF,
|
|
1
|
+
{"version":3,"file":"shape.js","names":[],"sources":["../../../src/registry/definitions/shape.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport type { NodeDefinition, Yoga } from \"../types.ts\";\nimport type { Node as YogaNode } from \"yoga-layout\";\nimport { measureText } from \"../../calcYogaLayout/measureText.ts\";\nimport type { BuildContext } from \"../../buildContext.ts\";\nimport { renderShapeNode } from \"../../renderPptx/nodes/shape.ts\";\n\nexport const shapeNodeDef: NodeDefinition = {\n type: \"shape\",\n category: \"leaf\",\n applyYogaStyle(node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) {\n const n = node as Extract<POMNode, { type: \"shape\" }>;\n if (n.text) {\n const text = n.text;\n const fontSizePx = n.fontSize ?? 24;\n const fontFamily = n.fontFamily ?? \"Noto Sans JP\";\n const fontWeight = n.bold ? \"bold\" : \"normal\";\n const lineHeight = n.lineHeight ?? 1.3;\n\n yn.setMeasureFunc((width, widthMode) => {\n const maxWidthPx = (() => {\n switch (widthMode) {\n case yoga.MEASURE_MODE_UNDEFINED:\n return Number.POSITIVE_INFINITY;\n case yoga.MEASURE_MODE_EXACTLY:\n case yoga.MEASURE_MODE_AT_MOST:\n return width;\n default:\n return Number.POSITIVE_INFINITY;\n }\n })();\n\n const { widthPx, heightPx } = measureText(\n text,\n maxWidthPx,\n {\n fontFamily,\n fontSizePx,\n lineHeight,\n fontWeight,\n },\n ctx.textMeasurementMode,\n );\n\n return { width: widthPx, height: heightPx };\n });\n }\n },\n render(node, ctx) {\n renderShapeNode(node as Extract<typeof node, { type: \"shape\" }>, ctx);\n },\n};\n"],"mappings":";;;AAOA,MAAa,eAA+B;CAC1C,MAAM;CACN,UAAU;CACV,eAAe,MAAe,IAAc,MAAY,KAAmB;EACzE,MAAM,IAAI;EACV,IAAI,EAAE,MAAM;GACV,MAAM,OAAO,EAAE;GACf,MAAM,aAAa,EAAE,YAAY;GACjC,MAAM,aAAa,EAAE,cAAc;GACnC,MAAM,aAAa,EAAE,OAAO,SAAS;GACrC,MAAM,aAAa,EAAE,cAAc;GAEnC,GAAG,gBAAgB,OAAO,cAAc;IAatC,MAAM,EAAE,SAAS,aAAa,YAC5B,aAbwB;KACxB,QAAQ,WAAR;MACE,KAAK,KAAK,wBACR,OAAO,OAAO;MAChB,KAAK,KAAK;MACV,KAAK,KAAK,sBACR,OAAO;MACT,SACE,OAAO,OAAO;KAClB;IACF,EAAA,CAIW,GACT;KACE;KACA;KACA;KACA;IACF,GACA,IAAI,mBACN;IAEA,OAAO;KAAE,OAAO;KAAS,QAAQ;IAAS;GAC5C,CAAC;EACH;CACF;CACA,OAAO,MAAM,KAAK;EAChB,gBAAgB,MAAiD,GAAG;CACtE;AACF"}
|
|
@@ -11,6 +11,7 @@ const textNodeDef = {
|
|
|
11
11
|
const fontFamily = n.fontFamily ?? "Noto Sans JP";
|
|
12
12
|
const fontWeight = n.bold ? "bold" : "normal";
|
|
13
13
|
const lineHeight = 1.3;
|
|
14
|
+
const letterSpacingPx = n.letterSpacing;
|
|
14
15
|
yn.setMeasureFunc((width, widthMode) => {
|
|
15
16
|
const { widthPx, heightPx } = measureText(text, (() => {
|
|
16
17
|
switch (widthMode) {
|
|
@@ -23,7 +24,8 @@ const textNodeDef = {
|
|
|
23
24
|
fontFamily,
|
|
24
25
|
fontSizePx,
|
|
25
26
|
lineHeight,
|
|
26
|
-
fontWeight
|
|
27
|
+
fontWeight,
|
|
28
|
+
letterSpacingPx
|
|
27
29
|
}, ctx.textMeasurementMode);
|
|
28
30
|
return {
|
|
29
31
|
width: widthPx,
|