@hirokisakabe/pom 8.6.0 → 8.8.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.
Files changed (49) hide show
  1. package/README.md +33 -23
  2. package/dist/autoFit/strategies/reduceFontSize.js +23 -7
  3. package/dist/autoFit/strategies/reduceFontSize.js.map +1 -1
  4. package/dist/autoFit/strategies/uniformScale.js +19 -4
  5. package/dist/autoFit/strategies/uniformScale.js.map +1 -1
  6. package/dist/buildContext.js +4 -2
  7. package/dist/buildContext.js.map +1 -1
  8. package/dist/buildPptx.d.ts.map +1 -1
  9. package/dist/buildPptx.js +3 -1
  10. package/dist/buildPptx.js.map +1 -1
  11. package/dist/parseXml/coercionRules.js +8 -1
  12. package/dist/parseXml/coercionRules.js.map +1 -1
  13. package/dist/parseXml/parseXml.d.ts.map +1 -1
  14. package/dist/parseXml/parseXml.js +4 -3
  15. package/dist/parseXml/parseXml.js.map +1 -1
  16. package/dist/parseXml/serializeXml.d.ts.map +1 -1
  17. package/dist/parseXml/serializeXml.js +1 -0
  18. package/dist/parseXml/serializeXml.js.map +1 -1
  19. package/dist/registry/definitions/list.js +2 -1
  20. package/dist/registry/definitions/list.js.map +1 -1
  21. package/dist/registry/definitions/text.js +2 -1
  22. package/dist/registry/definitions/text.js.map +1 -1
  23. package/dist/registry/xmlChildRules.js +1 -1
  24. package/dist/registry/xmlChildRules.js.map +1 -1
  25. package/dist/renderPptx/glowEffects.js +147 -0
  26. package/dist/renderPptx/glowEffects.js.map +1 -0
  27. package/dist/renderPptx/gradientFills.js +14 -1
  28. package/dist/renderPptx/gradientFills.js.map +1 -1
  29. package/dist/renderPptx/nodes/chart.js +43 -3
  30. package/dist/renderPptx/nodes/chart.js.map +1 -1
  31. package/dist/renderPptx/nodes/icon.js +13 -6
  32. package/dist/renderPptx/nodes/icon.js.map +1 -1
  33. package/dist/renderPptx/nodes/list.js +1 -0
  34. package/dist/renderPptx/nodes/list.js.map +1 -1
  35. package/dist/renderPptx/nodes/shape.js +24 -2
  36. package/dist/renderPptx/nodes/shape.js.map +1 -1
  37. package/dist/renderPptx/nodes/table.js +1 -1
  38. package/dist/renderPptx/nodes/table.js.map +1 -1
  39. package/dist/renderPptx/nodes/text.js +9 -3
  40. package/dist/renderPptx/nodes/text.js.map +1 -1
  41. package/dist/renderPptx/renderPptx.js +1 -1
  42. package/dist/renderPptx/units.js +8 -1
  43. package/dist/renderPptx/units.js.map +1 -1
  44. package/dist/renderPptx/utils/backgroundBorder.js +1 -1
  45. package/dist/types.d.ts +24 -0
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/types.js +9 -2
  48. package/dist/types.js.map +1 -1
  49. package/package.json +5 -5
package/README.md CHANGED
@@ -44,7 +44,7 @@
44
44
  - **Rich Nodes** — 20 built-in node types: charts, flowcharts, tables, timelines, org trees, and more.
45
45
  - **Design Tokens** — Declare a color palette once with a top-level `<Theme>` element and reference tokens as `$name` from any color attribute. See [Nodes — Top-Level `<Theme>`](./docs/nodes.md#top-level-theme-design-tokens).
46
46
  - **Schema-validated** — XML input is validated with Zod schemas at runtime with clear error messages.
47
- - **PowerPoint Native** — Generates real editable PowerPoint shapes — not images. Recipients can modify everything. Linear gradient backgrounds (`backgroundGradient="linear-gradient(135deg, #667EEA 0%, #764BA2 100%)"`) are exported as native gradient fills.
47
+ - **PowerPoint Native** — Generates real editable PowerPoint shapes — not images. Recipients can modify everything. Linear gradient backgrounds (`backgroundGradient="linear-gradient(135deg, #667EEA 0%, #764BA2 100%)"`) and text fills (`textGradient="linear-gradient(90deg, #38BDF8 0%, #A78BFA 100%)"` on `<Text>`) are exported as native gradient fills.
48
48
  - **Leaf Rotation** — `Text`, `Shape`, `Image`, and `Icon` support `rotate` in clockwise degrees at render time without affecting flex layout.
49
49
  - **Pixel Units** — Intuitive pixel-based sizing (internally converted to inches at 96 DPI).
50
50
  - **Master Slide** — Define headers, footers, and page numbers once — applied to all slides automatically.
@@ -89,28 +89,28 @@ Each slide must be wrapped in a `<Slide>` element. To produce multiple slides, l
89
89
 
90
90
  ## Available Nodes
91
91
 
92
- | Node | Description |
93
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
- | Text | Text with font styling, decoration (incl. subscript / superscript), rotation, letter spacing, glow / outline effects, inline bold/italic/underline/strike/sub/sup/highlight/color, and hyperlinks |
95
- | Ul | Unordered (bullet) list with Li items |
96
- | Ol | Ordered (numbered) list with Li items |
97
- | Image | Images from file path, URL, or base64, with optional rotation |
98
- | Table | Tables with customizable columns and rows |
99
- | Shape | PowerPoint shapes (roundRect, ellipse, etc.) with optional rotation |
100
- | Chart | Charts (bar, line, pie, area, doughnut, radar) |
101
- | Timeline | Timeline / roadmap visualizations |
102
- | Matrix | 2x2 positioning maps |
103
- | Tree | Organization charts and decision trees |
104
- | Flow | Flowcharts with nodes and edges |
105
- | ProcessArrow | Chevron-style process diagrams |
106
- | Pyramid | Pyramid diagrams for hierarchies |
107
- | Line | Horizontal / vertical lines |
108
- | Arrow | Connectors between nodes referenced by ID |
109
- | Layer | Absolute-positioned overlay container |
110
- | VStack | Vertical stack layout |
111
- | HStack | Horizontal stack layout |
112
- | Icon | Lucide icons with optional rotation |
113
- | Svg | Inline SVG graphics |
92
+ | Node | Description |
93
+ | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | Text | Text with font styling, decoration (incl. subscript / superscript), rotation, letter spacing, glow / outline effects, inline bold/italic/underline/strike/sub/sup/highlight/color/fontSize, and hyperlinks |
95
+ | Ul | Unordered (bullet) list with Li items |
96
+ | Ol | Ordered (numbered) list with Li items |
97
+ | Image | Images from file path, URL, or base64, with optional rotation |
98
+ | Table | Tables with customizable columns and rows |
99
+ | Shape | PowerPoint shapes (roundRect, ellipse, etc.) with optional rotation, native glow, and outline effects |
100
+ | Chart | Charts (bar, line, pie, area, doughnut, radar) |
101
+ | Timeline | Timeline / roadmap visualizations |
102
+ | Matrix | 2x2 positioning maps |
103
+ | Tree | Organization charts and decision trees |
104
+ | Flow | Flowcharts with nodes and edges |
105
+ | ProcessArrow | Chevron-style process diagrams |
106
+ | Pyramid | Pyramid diagrams for hierarchies |
107
+ | Line | Horizontal / vertical lines |
108
+ | Arrow | Connectors between nodes referenced by ID |
109
+ | Layer | Absolute-positioned overlay container |
110
+ | VStack | Vertical stack layout |
111
+ | HStack | Horizontal stack layout |
112
+ | Icon | Lucide icons with optional rotation; variant background supports native glow / outline effects |
113
+ | Svg | Inline SVG graphics |
114
114
 
115
115
  For detailed node documentation, see [Nodes](./docs/nodes.md).
116
116
 
@@ -125,6 +125,16 @@ For detailed node documentation, see [Nodes](./docs/nodes.md).
125
125
  <ChartDataPoint label="Feb" value="45" />
126
126
  </ChartSeries>
127
127
  </Chart>
128
+
129
+ <!-- Sparkline mode: hides legend / axes / margins for compact h=40 inline charts (bar / line / area) -->
130
+ <Chart chartType="bar" w="200" h="40" sparkline="true" chartColors='["0088CC"]'>
131
+ <ChartSeries name="Sales">
132
+ <ChartDataPoint label="Q1" value="100" />
133
+ <ChartDataPoint label="Q2" value="200" />
134
+ <ChartDataPoint label="Q3" value="150" />
135
+ <ChartDataPoint label="Q4" value="300" />
136
+ </ChartSeries>
137
+ </Chart>
128
138
  ```
129
139
 
130
140
  <img src="./docs/images/chart.png" alt="Chart example" width="600">
@@ -11,36 +11,52 @@ function reduceFontSize(node, targetRatio) {
11
11
  const ratio = Math.max(targetRatio, MIN_SCALE);
12
12
  let changed = false;
13
13
  let sawTarget = false;
14
+ const scale = (current) => Math.max(MIN_FONT_SIZE, Math.round(current * ratio));
15
+ const scaleRuns = (runs) => {
16
+ if (!runs) return;
17
+ for (const run of runs) {
18
+ if (run.fontSize === void 0) continue;
19
+ sawTarget = true;
20
+ const newSize = scale(run.fontSize);
21
+ if (newSize !== run.fontSize) {
22
+ run.fontSize = newSize;
23
+ changed = true;
24
+ }
25
+ }
26
+ };
14
27
  walkPOMTree(node, (n) => {
15
28
  if (n.type === "text" || n.type === "shape" || n.type === "ul" || n.type === "ol") {
16
29
  if (n.fontSize !== void 0) {
17
30
  sawTarget = true;
18
- const newSize = Math.max(MIN_FONT_SIZE, Math.round(n.fontSize * ratio));
31
+ const newSize = scale(n.fontSize);
19
32
  if (newSize !== n.fontSize) {
20
33
  n.fontSize = newSize;
21
34
  changed = true;
22
35
  }
23
36
  }
24
37
  }
25
- if (n.type === "ul" || n.type === "ol") {
26
- for (const item of n.items) if (item.fontSize !== void 0) {
38
+ if (n.type === "text") scaleRuns(n.runs);
39
+ if (n.type === "ul" || n.type === "ol") for (const item of n.items) {
40
+ if (item.fontSize !== void 0) {
27
41
  sawTarget = true;
28
- const newSize = Math.max(MIN_FONT_SIZE, Math.round(item.fontSize * ratio));
42
+ const newSize = scale(item.fontSize);
29
43
  if (newSize !== item.fontSize) {
30
44
  item.fontSize = newSize;
31
45
  changed = true;
32
46
  }
33
47
  }
48
+ scaleRuns(item.runs);
34
49
  }
35
- if (n.type === "table") {
36
- for (const row of n.rows) for (const cell of row.cells) if (cell.fontSize !== void 0) {
50
+ if (n.type === "table") for (const row of n.rows) for (const cell of row.cells) {
51
+ if (cell.fontSize !== void 0) {
37
52
  sawTarget = true;
38
- const newSize = Math.max(MIN_FONT_SIZE, Math.round(cell.fontSize * ratio));
53
+ const newSize = scale(cell.fontSize);
39
54
  if (newSize !== cell.fontSize) {
40
55
  cell.fontSize = newSize;
41
56
  changed = true;
42
57
  }
43
58
  }
59
+ scaleRuns(cell.runs);
44
60
  }
45
61
  });
46
62
  return toStrategyResult({
@@ -1 +1 @@
1
- {"version":3,"file":"reduceFontSize.js","names":[],"sources":["../../../src/autoFit/strategies/reduceFontSize.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport { walkPOMTree } from \"../../shared/walkTree.ts\";\nimport type { AutoFitStrategyResult } from \"../strategyResult.ts\";\nimport { toStrategyResult } from \"../strategyResult.ts\";\n\nconst MIN_FONT_SIZE = 10;\nconst MIN_SCALE = 0.6;\n\n/**\n * テキスト系ノードの fontSize を縮小する。\n * 対象: text, ul, ol, shape\n */\nexport function reduceFontSize(\n node: POMNode,\n targetRatio: number,\n): AutoFitStrategyResult {\n const ratio = Math.max(targetRatio, MIN_SCALE);\n let changed = false;\n let sawTarget = false;\n\n walkPOMTree(node, (n) => {\n if (\n n.type === \"text\" ||\n n.type === \"shape\" ||\n n.type === \"ul\" ||\n n.type === \"ol\"\n ) {\n if (n.fontSize !== undefined) {\n sawTarget = true;\n const newSize = Math.max(MIN_FONT_SIZE, Math.round(n.fontSize * ratio));\n if (newSize !== n.fontSize) {\n n.fontSize = newSize;\n changed = true;\n }\n }\n }\n\n // ul/ol の li 要素の fontSize も縮小\n if (n.type === \"ul\" || n.type === \"ol\") {\n for (const item of n.items) {\n if (item.fontSize !== undefined) {\n sawTarget = true;\n const newSize = Math.max(\n MIN_FONT_SIZE,\n Math.round(item.fontSize * ratio),\n );\n if (newSize !== item.fontSize) {\n item.fontSize = newSize;\n changed = true;\n }\n }\n }\n }\n\n // table セルの fontSize も縮小\n if (n.type === \"table\") {\n for (const row of n.rows) {\n for (const cell of row.cells) {\n if (cell.fontSize !== undefined) {\n sawTarget = true;\n const newSize = Math.max(\n MIN_FONT_SIZE,\n Math.round(cell.fontSize * ratio),\n );\n if (newSize !== cell.fontSize) {\n cell.fontSize = newSize;\n changed = true;\n }\n }\n }\n }\n }\n });\n\n return toStrategyResult({ changed, sawTarget });\n}\n"],"mappings":";;;AAKA,MAAM,gBAAgB;AACtB,MAAM,YAAY;;;;;AAMlB,SAAgB,eACd,MACA,aACuB;CACvB,MAAM,QAAQ,KAAK,IAAI,aAAa,SAAS;CAC7C,IAAI,UAAU;CACd,IAAI,YAAY;CAEhB,YAAY,OAAO,MAAM;EACvB,IACE,EAAE,SAAS,UACX,EAAE,SAAS,WACX,EAAE,SAAS,QACX,EAAE,SAAS;OAEP,EAAE,aAAa,KAAA,GAAW;IAC5B,YAAY;IACZ,MAAM,UAAU,KAAK,IAAI,eAAe,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;IACtE,IAAI,YAAY,EAAE,UAAU;KAC1B,EAAE,WAAW;KACb,UAAU;IACZ;GACF;;EAIF,IAAI,EAAE,SAAS,QAAQ,EAAE,SAAS;QAC3B,MAAM,QAAQ,EAAE,OACnB,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,UAAU,KAAK,IACnB,eACA,KAAK,MAAM,KAAK,WAAW,KAAK,CAClC;IACA,IAAI,YAAY,KAAK,UAAU;KAC7B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;;EAKJ,IAAI,EAAE,SAAS;QACR,MAAM,OAAO,EAAE,MAClB,KAAK,MAAM,QAAQ,IAAI,OACrB,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,UAAU,KAAK,IACnB,eACA,KAAK,MAAM,KAAK,WAAW,KAAK,CAClC;IACA,IAAI,YAAY,KAAK,UAAU;KAC7B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;;CAIR,CAAC;CAED,OAAO,iBAAiB;EAAE;EAAS;CAAU,CAAC;AAChD"}
1
+ {"version":3,"file":"reduceFontSize.js","names":[],"sources":["../../../src/autoFit/strategies/reduceFontSize.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport { walkPOMTree } from \"../../shared/walkTree.ts\";\nimport type { AutoFitStrategyResult } from \"../strategyResult.ts\";\nimport { toStrategyResult } from \"../strategyResult.ts\";\n\nconst MIN_FONT_SIZE = 10;\nconst MIN_SCALE = 0.6;\n\n/**\n * テキスト系ノードの fontSize を縮小する。\n * 対象: text, ul, ol, shape\n */\nexport function reduceFontSize(\n node: POMNode,\n targetRatio: number,\n): AutoFitStrategyResult {\n const ratio = Math.max(targetRatio, MIN_SCALE);\n let changed = false;\n let sawTarget = false;\n\n const scale = (current: number) =>\n Math.max(MIN_FONT_SIZE, Math.round(current * ratio));\n\n const scaleRuns = (runs: { fontSize?: number }[] | undefined) => {\n if (!runs) return;\n for (const run of runs) {\n if (run.fontSize === undefined) continue;\n sawTarget = true;\n const newSize = scale(run.fontSize);\n if (newSize !== run.fontSize) {\n run.fontSize = newSize;\n changed = true;\n }\n }\n };\n\n walkPOMTree(node, (n) => {\n if (\n n.type === \"text\" ||\n n.type === \"shape\" ||\n n.type === \"ul\" ||\n n.type === \"ol\"\n ) {\n if (n.fontSize !== undefined) {\n sawTarget = true;\n const newSize = scale(n.fontSize);\n if (newSize !== n.fontSize) {\n n.fontSize = newSize;\n changed = true;\n }\n }\n }\n\n // text の <Span fontSize> による run 単位上書きも一緒に縮小する\n // (shape は runs フィールドを持たない)\n if (n.type === \"text\") {\n scaleRuns(n.runs);\n }\n\n // ul/ol の li 要素の fontSize と <Span fontSize> による run 単位上書きも縮小\n if (n.type === \"ul\" || n.type === \"ol\") {\n for (const item of n.items) {\n if (item.fontSize !== undefined) {\n sawTarget = true;\n const newSize = scale(item.fontSize);\n if (newSize !== item.fontSize) {\n item.fontSize = newSize;\n changed = true;\n }\n }\n scaleRuns(item.runs);\n }\n }\n\n // table セルの fontSize と <Span fontSize> による run 単位上書きも縮小\n if (n.type === \"table\") {\n for (const row of n.rows) {\n for (const cell of row.cells) {\n if (cell.fontSize !== undefined) {\n sawTarget = true;\n const newSize = scale(cell.fontSize);\n if (newSize !== cell.fontSize) {\n cell.fontSize = newSize;\n changed = true;\n }\n }\n scaleRuns(cell.runs);\n }\n }\n }\n });\n\n return toStrategyResult({ changed, sawTarget });\n}\n"],"mappings":";;;AAKA,MAAM,gBAAgB;AACtB,MAAM,YAAY;;;;;AAMlB,SAAgB,eACd,MACA,aACuB;CACvB,MAAM,QAAQ,KAAK,IAAI,aAAa,SAAS;CAC7C,IAAI,UAAU;CACd,IAAI,YAAY;CAEhB,MAAM,SAAS,YACb,KAAK,IAAI,eAAe,KAAK,MAAM,UAAU,KAAK,CAAC;CAErD,MAAM,aAAa,SAA8C;EAC/D,IAAI,CAAC,MAAM;EACX,KAAK,MAAM,OAAO,MAAM;GACtB,IAAI,IAAI,aAAa,KAAA,GAAW;GAChC,YAAY;GACZ,MAAM,UAAU,MAAM,IAAI,QAAQ;GAClC,IAAI,YAAY,IAAI,UAAU;IAC5B,IAAI,WAAW;IACf,UAAU;GACZ;EACF;CACF;CAEA,YAAY,OAAO,MAAM;EACvB,IACE,EAAE,SAAS,UACX,EAAE,SAAS,WACX,EAAE,SAAS,QACX,EAAE,SAAS;OAEP,EAAE,aAAa,KAAA,GAAW;IAC5B,YAAY;IACZ,MAAM,UAAU,MAAM,EAAE,QAAQ;IAChC,IAAI,YAAY,EAAE,UAAU;KAC1B,EAAE,WAAW;KACb,UAAU;IACZ;GACF;;EAKF,IAAI,EAAE,SAAS,QACb,UAAU,EAAE,IAAI;EAIlB,IAAI,EAAE,SAAS,QAAQ,EAAE,SAAS,MAChC,KAAK,MAAM,QAAQ,EAAE,OAAO;GAC1B,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,UAAU,MAAM,KAAK,QAAQ;IACnC,IAAI,YAAY,KAAK,UAAU;KAC7B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;GACA,UAAU,KAAK,IAAI;EACrB;EAIF,IAAI,EAAE,SAAS,SACb,KAAK,MAAM,OAAO,EAAE,MAClB,KAAK,MAAM,QAAQ,IAAI,OAAO;GAC5B,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,UAAU,MAAM,KAAK,QAAQ;IACnC,IAAI,YAAY,KAAK,UAAU;KAC7B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;GACA,UAAU,KAAK,IAAI;EACrB;CAGN,CAAC;CAED,OAAO,iBAAiB;EAAE;EAAS;CAAU,CAAC;AAChD"}
@@ -13,6 +13,18 @@ function uniformScale(node, targetRatio) {
13
13
  const ratio = Math.max(targetRatio, MIN_SCALE);
14
14
  let changed = false;
15
15
  let sawTarget = false;
16
+ const scaleRunFontSizes = (runs) => {
17
+ if (!runs) return;
18
+ for (const run of runs) {
19
+ if (run.fontSize === void 0) continue;
20
+ sawTarget = true;
21
+ const newVal = scaleNumber(run.fontSize, ratio, 8);
22
+ if (newVal !== run.fontSize) {
23
+ run.fontSize = newVal;
24
+ changed = true;
25
+ }
26
+ }
27
+ };
16
28
  walkPOMTree(node, (n) => {
17
29
  if ("fontSize" in n && typeof n.fontSize === "number") {
18
30
  sawTarget = true;
@@ -22,6 +34,7 @@ function uniformScale(node, targetRatio) {
22
34
  changed = true;
23
35
  }
24
36
  }
37
+ if (n.type === "text") scaleRunFontSizes(n.runs);
25
38
  if ((n.type === "vstack" || n.type === "hstack") && n.gap !== void 0) {
26
39
  sawTarget = true;
27
40
  const newVal = scaleNumber(n.gap, ratio, 1);
@@ -56,8 +69,8 @@ function uniformScale(node, targetRatio) {
56
69
  }
57
70
  }
58
71
  }
59
- if (n.type === "ul" || n.type === "ol") {
60
- for (const item of n.items) if (item.fontSize !== void 0) {
72
+ if (n.type === "ul" || n.type === "ol") for (const item of n.items) {
73
+ if (item.fontSize !== void 0) {
61
74
  sawTarget = true;
62
75
  const newVal = scaleNumber(item.fontSize, ratio, 8);
63
76
  if (newVal !== item.fontSize) {
@@ -65,6 +78,7 @@ function uniformScale(node, targetRatio) {
65
78
  changed = true;
66
79
  }
67
80
  }
81
+ scaleRunFontSizes(item.runs);
68
82
  }
69
83
  if (n.type === "icon" && n.size !== void 0) {
70
84
  sawTarget = true;
@@ -74,8 +88,8 @@ function uniformScale(node, targetRatio) {
74
88
  changed = true;
75
89
  }
76
90
  }
77
- if (n.type === "table") {
78
- for (const row of n.rows) for (const cell of row.cells) if (cell.fontSize !== void 0) {
91
+ if (n.type === "table") for (const row of n.rows) for (const cell of row.cells) {
92
+ if (cell.fontSize !== void 0) {
79
93
  sawTarget = true;
80
94
  const newVal = scaleNumber(cell.fontSize, ratio, 8);
81
95
  if (newVal !== cell.fontSize) {
@@ -83,6 +97,7 @@ function uniformScale(node, targetRatio) {
83
97
  changed = true;
84
98
  }
85
99
  }
100
+ scaleRunFontSizes(cell.runs);
86
101
  }
87
102
  });
88
103
  return toStrategyResult({
@@ -1 +1 @@
1
- {"version":3,"file":"uniformScale.js","names":[],"sources":["../../../src/autoFit/strategies/uniformScale.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport { walkPOMTree } from \"../../shared/walkTree.ts\";\nimport { mapBoxSpacing } from \"../../shared/boxSpacing.ts\";\nimport type { AutoFitStrategyResult } from \"../strategyResult.ts\";\nimport { toStrategyResult } from \"../strategyResult.ts\";\n\nconst MIN_SCALE = 0.5;\n\nfunction scaleNumber(value: number, ratio: number, min: number): number {\n return Math.max(min, Math.round(value * ratio));\n}\n\n/**\n * 全サイズ関連プロパティを一律スケーリングする(フォールバック)。\n */\nexport function uniformScale(\n node: POMNode,\n targetRatio: number,\n): AutoFitStrategyResult {\n const ratio = Math.max(targetRatio, MIN_SCALE);\n let changed = false;\n let sawTarget = false;\n\n walkPOMTree(node, (n) => {\n // fontSize\n if (\"fontSize\" in n && typeof n.fontSize === \"number\") {\n sawTarget = true;\n const newVal = scaleNumber(n.fontSize, ratio, 8);\n if (newVal !== n.fontSize) {\n (n as { fontSize: number }).fontSize = newVal;\n changed = true;\n }\n }\n\n // gap (vstack/hstack)\n if ((n.type === \"vstack\" || n.type === \"hstack\") && n.gap !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.gap, ratio, 1);\n if (newVal !== n.gap) {\n n.gap = newVal;\n changed = true;\n }\n }\n\n // padding\n if (n.padding !== undefined) {\n sawTarget = true;\n const result = mapBoxSpacing(n.padding, (v) => scaleNumber(v, ratio, 1));\n if (result.changed) {\n n.padding = result.value;\n changed = true;\n }\n }\n\n // table: defaultRowHeight, row.height\n if (n.type === \"table\") {\n if (n.defaultRowHeight !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.defaultRowHeight, ratio, 16);\n if (newVal !== n.defaultRowHeight) {\n n.defaultRowHeight = newVal;\n changed = true;\n }\n }\n for (const row of n.rows) {\n if (row.height !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(row.height, ratio, 16);\n if (newVal !== row.height) {\n row.height = newVal;\n changed = true;\n }\n }\n }\n }\n\n // ul/ol items fontSize\n if (n.type === \"ul\" || n.type === \"ol\") {\n for (const item of n.items) {\n if (item.fontSize !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(item.fontSize, ratio, 8);\n if (newVal !== item.fontSize) {\n item.fontSize = newVal;\n changed = true;\n }\n }\n }\n }\n\n // icon size\n if (n.type === \"icon\" && n.size !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.size, ratio, 8);\n if (newVal !== n.size) {\n n.size = newVal;\n changed = true;\n }\n }\n\n // table cells fontSize\n if (n.type === \"table\") {\n for (const row of n.rows) {\n for (const cell of row.cells) {\n if (cell.fontSize !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(cell.fontSize, ratio, 8);\n if (newVal !== cell.fontSize) {\n cell.fontSize = newVal;\n changed = true;\n }\n }\n }\n }\n }\n });\n\n return toStrategyResult({ changed, sawTarget });\n}\n"],"mappings":";;;;AAMA,MAAM,YAAY;AAElB,SAAS,YAAY,OAAe,OAAe,KAAqB;CACtE,OAAO,KAAK,IAAI,KAAK,KAAK,MAAM,QAAQ,KAAK,CAAC;AAChD;;;;AAKA,SAAgB,aACd,MACA,aACuB;CACvB,MAAM,QAAQ,KAAK,IAAI,aAAa,SAAS;CAC7C,IAAI,UAAU;CACd,IAAI,YAAY;CAEhB,YAAY,OAAO,MAAM;EAEvB,IAAI,cAAc,KAAK,OAAO,EAAE,aAAa,UAAU;GACrD,YAAY;GACZ,MAAM,SAAS,YAAY,EAAE,UAAU,OAAO,CAAC;GAC/C,IAAI,WAAW,EAAE,UAAU;IACzB,EAA4B,WAAW;IACvC,UAAU;GACZ;EACF;EAGA,KAAK,EAAE,SAAS,YAAY,EAAE,SAAS,aAAa,EAAE,QAAQ,KAAA,GAAW;GACvE,YAAY;GACZ,MAAM,SAAS,YAAY,EAAE,KAAK,OAAO,CAAC;GAC1C,IAAI,WAAW,EAAE,KAAK;IACpB,EAAE,MAAM;IACR,UAAU;GACZ;EACF;EAGA,IAAI,EAAE,YAAY,KAAA,GAAW;GAC3B,YAAY;GACZ,MAAM,SAAS,cAAc,EAAE,UAAU,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC;GACvE,IAAI,OAAO,SAAS;IAClB,EAAE,UAAU,OAAO;IACnB,UAAU;GACZ;EACF;EAGA,IAAI,EAAE,SAAS,SAAS;GACtB,IAAI,EAAE,qBAAqB,KAAA,GAAW;IACpC,YAAY;IACZ,MAAM,SAAS,YAAY,EAAE,kBAAkB,OAAO,EAAE;IACxD,IAAI,WAAW,EAAE,kBAAkB;KACjC,EAAE,mBAAmB;KACrB,UAAU;IACZ;GACF;GACA,KAAK,MAAM,OAAO,EAAE,MAClB,IAAI,IAAI,WAAW,KAAA,GAAW;IAC5B,YAAY;IACZ,MAAM,SAAS,YAAY,IAAI,QAAQ,OAAO,EAAE;IAChD,IAAI,WAAW,IAAI,QAAQ;KACzB,IAAI,SAAS;KACb,UAAU;IACZ;GACF;EAEJ;EAGA,IAAI,EAAE,SAAS,QAAQ,EAAE,SAAS;QAC3B,MAAM,QAAQ,EAAE,OACnB,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,SAAS,YAAY,KAAK,UAAU,OAAO,CAAC;IAClD,IAAI,WAAW,KAAK,UAAU;KAC5B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;;EAKJ,IAAI,EAAE,SAAS,UAAU,EAAE,SAAS,KAAA,GAAW;GAC7C,YAAY;GACZ,MAAM,SAAS,YAAY,EAAE,MAAM,OAAO,CAAC;GAC3C,IAAI,WAAW,EAAE,MAAM;IACrB,EAAE,OAAO;IACT,UAAU;GACZ;EACF;EAGA,IAAI,EAAE,SAAS;QACR,MAAM,OAAO,EAAE,MAClB,KAAK,MAAM,QAAQ,IAAI,OACrB,IAAI,KAAK,aAAa,KAAA,GAAW;IAC/B,YAAY;IACZ,MAAM,SAAS,YAAY,KAAK,UAAU,OAAO,CAAC;IAClD,IAAI,WAAW,KAAK,UAAU;KAC5B,KAAK,WAAW;KAChB,UAAU;IACZ;GACF;;CAIR,CAAC;CAED,OAAO,iBAAiB;EAAE;EAAS;CAAU,CAAC;AAChD"}
1
+ {"version":3,"file":"uniformScale.js","names":[],"sources":["../../../src/autoFit/strategies/uniformScale.ts"],"sourcesContent":["import type { POMNode } from \"../../types.ts\";\nimport { walkPOMTree } from \"../../shared/walkTree.ts\";\nimport { mapBoxSpacing } from \"../../shared/boxSpacing.ts\";\nimport type { AutoFitStrategyResult } from \"../strategyResult.ts\";\nimport { toStrategyResult } from \"../strategyResult.ts\";\n\nconst MIN_SCALE = 0.5;\n\nfunction scaleNumber(value: number, ratio: number, min: number): number {\n return Math.max(min, Math.round(value * ratio));\n}\n\n/**\n * 全サイズ関連プロパティを一律スケーリングする(フォールバック)。\n */\nexport function uniformScale(\n node: POMNode,\n targetRatio: number,\n): AutoFitStrategyResult {\n const ratio = Math.max(targetRatio, MIN_SCALE);\n let changed = false;\n let sawTarget = false;\n\n const scaleRunFontSizes = (runs: { fontSize?: number }[] | undefined) => {\n if (!runs) return;\n for (const run of runs) {\n if (run.fontSize === undefined) continue;\n sawTarget = true;\n const newVal = scaleNumber(run.fontSize, ratio, 8);\n if (newVal !== run.fontSize) {\n run.fontSize = newVal;\n changed = true;\n }\n }\n };\n\n walkPOMTree(node, (n) => {\n // fontSize\n if (\"fontSize\" in n && typeof n.fontSize === \"number\") {\n sawTarget = true;\n const newVal = scaleNumber(n.fontSize, ratio, 8);\n if (newVal !== n.fontSize) {\n (n as { fontSize: number }).fontSize = newVal;\n changed = true;\n }\n }\n\n // text の <Span fontSize> による run 単位上書きも一緒にスケーリング\n // (shape は runs フィールドを持たない)\n if (n.type === \"text\") {\n scaleRunFontSizes(n.runs);\n }\n\n // gap (vstack/hstack)\n if ((n.type === \"vstack\" || n.type === \"hstack\") && n.gap !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.gap, ratio, 1);\n if (newVal !== n.gap) {\n n.gap = newVal;\n changed = true;\n }\n }\n\n // padding\n if (n.padding !== undefined) {\n sawTarget = true;\n const result = mapBoxSpacing(n.padding, (v) => scaleNumber(v, ratio, 1));\n if (result.changed) {\n n.padding = result.value;\n changed = true;\n }\n }\n\n // table: defaultRowHeight, row.height\n if (n.type === \"table\") {\n if (n.defaultRowHeight !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.defaultRowHeight, ratio, 16);\n if (newVal !== n.defaultRowHeight) {\n n.defaultRowHeight = newVal;\n changed = true;\n }\n }\n for (const row of n.rows) {\n if (row.height !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(row.height, ratio, 16);\n if (newVal !== row.height) {\n row.height = newVal;\n changed = true;\n }\n }\n }\n }\n\n // ul/ol items fontSize と Li 内 <Span fontSize> も一緒にスケーリング\n if (n.type === \"ul\" || n.type === \"ol\") {\n for (const item of n.items) {\n if (item.fontSize !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(item.fontSize, ratio, 8);\n if (newVal !== item.fontSize) {\n item.fontSize = newVal;\n changed = true;\n }\n }\n scaleRunFontSizes(item.runs);\n }\n }\n\n // icon size\n if (n.type === \"icon\" && n.size !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(n.size, ratio, 8);\n if (newVal !== n.size) {\n n.size = newVal;\n changed = true;\n }\n }\n\n // table cells fontSize と Td 内 <Span fontSize> も一緒にスケーリング\n if (n.type === \"table\") {\n for (const row of n.rows) {\n for (const cell of row.cells) {\n if (cell.fontSize !== undefined) {\n sawTarget = true;\n const newVal = scaleNumber(cell.fontSize, ratio, 8);\n if (newVal !== cell.fontSize) {\n cell.fontSize = newVal;\n changed = true;\n }\n }\n scaleRunFontSizes(cell.runs);\n }\n }\n }\n });\n\n return toStrategyResult({ changed, sawTarget });\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
- import { DiagnosticCollector } from "./diagnostics.js";
2
1
  import { GradientFillRegistry } from "./renderPptx/gradientFills.js";
2
+ import { DiagnosticCollector } from "./diagnostics.js";
3
+ import { GlowEffectRegistry } from "./renderPptx/glowEffects.js";
3
4
  //#region src/buildContext.ts
4
5
  function createBuildContext(textMeasurementMode = "auto") {
5
6
  return {
@@ -8,7 +9,8 @@ function createBuildContext(textMeasurementMode = "auto") {
8
9
  imageDataCache: /* @__PURE__ */ new Map(),
9
10
  iconRasterCache: /* @__PURE__ */ new Map(),
10
11
  diagnostics: new DiagnosticCollector(),
11
- gradientFills: new GradientFillRegistry()
12
+ gradientFills: new GradientFillRegistry(),
13
+ glowEffects: new GlowEffectRegistry()
12
14
  };
13
15
  }
14
16
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"buildContext.js","names":[],"sources":["../src/buildContext.ts"],"sourcesContent":["import type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport { DiagnosticCollector } from \"./diagnostics.ts\";\nimport { GradientFillRegistry } from \"./renderPptx/gradientFills.ts\";\n\nexport interface BuildContext {\n textMeasurementMode: TextMeasurementMode;\n imageSizeCache: Map<string, { widthPx: number; heightPx: number }>;\n imageDataCache: Map<string, string>;\n iconRasterCache: Map<string, string>;\n diagnostics: DiagnosticCollector;\n gradientFills: GradientFillRegistry;\n}\n\nexport function createBuildContext(\n textMeasurementMode: TextMeasurementMode = \"auto\",\n): BuildContext {\n return {\n textMeasurementMode,\n imageSizeCache: new Map(),\n imageDataCache: new Map(),\n iconRasterCache: new Map(),\n diagnostics: new DiagnosticCollector(),\n gradientFills: new GradientFillRegistry(),\n };\n}\n"],"mappings":";;;AAaA,SAAgB,mBACd,sBAA2C,QAC7B;CACd,OAAO;EACL;EACA,gCAAgB,IAAI,IAAI;EACxB,gCAAgB,IAAI,IAAI;EACxB,iCAAiB,IAAI,IAAI;EACzB,aAAa,IAAI,oBAAoB;EACrC,eAAe,IAAI,qBAAqB;CAC1C;AACF"}
1
+ {"version":3,"file":"buildContext.js","names":[],"sources":["../src/buildContext.ts"],"sourcesContent":["import type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport { DiagnosticCollector } from \"./diagnostics.ts\";\nimport { GlowEffectRegistry } from \"./renderPptx/glowEffects.ts\";\nimport { GradientFillRegistry } from \"./renderPptx/gradientFills.ts\";\n\nexport interface BuildContext {\n textMeasurementMode: TextMeasurementMode;\n imageSizeCache: Map<string, { widthPx: number; heightPx: number }>;\n imageDataCache: Map<string, string>;\n iconRasterCache: Map<string, string>;\n diagnostics: DiagnosticCollector;\n gradientFills: GradientFillRegistry;\n glowEffects: GlowEffectRegistry;\n}\n\nexport function createBuildContext(\n textMeasurementMode: TextMeasurementMode = \"auto\",\n): BuildContext {\n return {\n textMeasurementMode,\n imageSizeCache: new Map(),\n imageDataCache: new Map(),\n iconRasterCache: new Map(),\n diagnostics: new DiagnosticCollector(),\n gradientFills: new GradientFillRegistry(),\n glowEffects: new GlowEffectRegistry(),\n };\n}\n"],"mappings":";;;;AAeA,SAAgB,mBACd,sBAA2C,QAC7B;CACd,OAAO;EACL;EACA,gCAAgB,IAAI,IAAI;EACxB,gCAAgB,IAAI,IAAI;EACxB,iCAAiB,IAAI,IAAI;EACzB,aAAa,IAAI,oBAAoB;EACrC,eAAe,IAAI,qBAAqB;EACxC,aAAa,IAAI,mBAAmB;CACtC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"buildPptx.d.ts","names":[],"sources":["../src/buildPptx.ts"],"mappings":";;;;;UAmBiB,eAAA;EACf,IAAA,sBAA0B,OAAA;EAC1B,WAAA,EAAa,UAAU;AAAA;AAAA,iBAGH,SAAA,CACpB,GAAA,UACA,SAAA;EAAa,CAAA;EAAW,CAAA;AAAA,GACxB,OAAA;EACE,MAAA,GAAS,kBAAA;EACT,UAAA,GAAa,WAAA,GAAc,UAAA;EAC3B,eAAA,GAAkB,mBAAA;EAClB,OAAA;EACA,MAAA;AAAA,IAED,OAAA,CAAQ,eAAA"}
1
+ {"version":3,"file":"buildPptx.d.ts","names":[],"sources":["../src/buildPptx.ts"],"mappings":";;;;;UAoBiB,eAAA;EACf,IAAA,sBAA0B,OAAA;EAC1B,WAAA,EAAa,UAAU;AAAA;AAAA,iBAGH,SAAA,CACpB,GAAA,UACA,SAAA;EAAa,CAAA;EAAW,CAAA;AAAA,GACxB,OAAA;EACE,MAAA,GAAS,kBAAA;EACT,UAAA,GAAa,WAAA,GAAc,UAAA;EAC3B,eAAA,GAAkB,mBAAA;EAClB,OAAA;EACA,MAAA;AAAA,IAED,OAAA,CAAQ,eAAA"}
package/dist/buildPptx.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { freeYogaTree } from "./shared/freeYogaTree.js";
2
+ import { patchPptxWriteForGradientFills } from "./renderPptx/gradientFills.js";
2
3
  import { calcYogaLayout } from "./calcYogaLayout/calcYogaLayout.js";
3
4
  import { autoFitSlide } from "./autoFit/autoFit.js";
4
5
  import { DiagnosticsError } from "./diagnostics.js";
5
- import { patchPptxWriteForGradientFills } from "./renderPptx/gradientFills.js";
6
+ import { patchPptxWriteForGlowEffects } from "./renderPptx/glowEffects.js";
6
7
  import { createBuildContext } from "./buildContext.js";
7
8
  import { extractLayoutResults } from "./calcYogaLayout/types.js";
8
9
  import { parseMasterPptx } from "./parseMasterPptx.js";
@@ -44,6 +45,7 @@ async function buildPptx(xml, slideSize, options) {
44
45
  }
45
46
  const pptx = await renderPptx(positionedPages, slideSize, ctx, master);
46
47
  patchPptxWriteForGradientFills(pptx, ctx.gradientFills);
48
+ patchPptxWriteForGlowEffects(pptx, ctx.glowEffects);
47
49
  const diagnostics = ctx.diagnostics.items;
48
50
  if (options?.strict && diagnostics.length > 0) throw new DiagnosticsError(diagnostics);
49
51
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"buildPptx.js","names":[],"sources":["../src/buildPptx.ts"],"sourcesContent":["import { autoFitSlide } from \"./autoFit/autoFit.ts\";\nimport { createBuildContext } from \"./buildContext.ts\";\nimport { calcYogaLayout } from \"./calcYogaLayout/calcYogaLayout.ts\";\nimport type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport type { YogaNodeMap } from \"./calcYogaLayout/types.ts\";\nimport { extractLayoutResults } from \"./calcYogaLayout/types.ts\";\nimport type { Diagnostic } from \"./diagnostics.ts\";\nimport { DiagnosticsError } from \"./diagnostics.ts\";\nimport { parseMasterPptx } from \"./parseMasterPptx.ts\";\nimport { parseXml } from \"./parseXml/parseXml.ts\";\nimport { patchPptxWriteForGradientFills } from \"./renderPptx/gradientFills.ts\";\nimport { renderPptx } from \"./renderPptx/renderPptx.ts\";\nimport { freeYogaTree } from \"./shared/freeYogaTree.ts\";\nimport { toPositioned } from \"./toPositioned/toPositioned.ts\";\nimport { PositionedNode, SlideMasterOptions } from \"./types.ts\";\nimport { validatePositioned } from \"./validatePositioned/validatePositioned.ts\";\n\nexport type { TextMeasurementMode };\n\nexport interface BuildPptxResult {\n pptx: import(\"pptxgenjs\").default;\n diagnostics: Diagnostic[];\n}\n\nexport async function buildPptx(\n xml: string,\n slideSize: { w: number; h: number },\n options?: {\n master?: SlideMasterOptions;\n masterPptx?: ArrayBuffer | Uint8Array;\n textMeasurement?: TextMeasurementMode;\n autoFit?: boolean;\n strict?: boolean;\n },\n): Promise<BuildPptxResult> {\n const ctx = createBuildContext(options?.textMeasurement ?? \"auto\");\n\n // グラデーション後処理のマーカー色がユーザー指定色と衝突しないよう、\n // 入力 XML / master オプション中に現れる色を予約しておく\n ctx.gradientFills.reserveColors(xml);\n if (options?.master) {\n ctx.gradientFills.reserveColors(JSON.stringify(options.master));\n }\n\n const nodes = parseXml(xml);\n const positionedPages: PositionedNode[] = [];\n\n for (const [slideIndex, node] of nodes.entries()) {\n let map: YogaNodeMap | undefined;\n try {\n if (options?.autoFit !== false) {\n map = await autoFitSlide(node, slideSize, ctx);\n } else {\n map = await calcYogaLayout(node, slideSize, ctx);\n }\n const layoutMap = extractLayoutResults(map);\n const positioned = await toPositioned(node, ctx, layoutMap);\n validatePositioned(positioned, slideSize, ctx, slideIndex);\n positionedPages.push(positioned);\n } finally {\n if (map) freeYogaTree(map);\n }\n }\n\n // masterPptx から背景を抽出し、master オプションにマージ\n let master = options?.master;\n if (options?.masterPptx) {\n try {\n const bg = await parseMasterPptx(options.masterPptx);\n if (bg) {\n if (master) {\n // 明示的に background が指定されていない場合のみ、masterPptx の背景を使用\n if (!master.background) {\n master = { ...master, background: bg };\n }\n } else {\n master = { background: bg };\n }\n }\n } catch (e) {\n const message =\n e instanceof Error ? e.message : \"Unknown error parsing masterPptx\";\n ctx.diagnostics.add(\"MASTER_PPTX_PARSE_FAILED\", message);\n }\n }\n\n const pptx = await renderPptx(positionedPages, slideSize, ctx, master);\n\n // backgroundGradient 使用時は write/writeFile に gradFill 置換の後処理を仕込む\n patchPptxWriteForGradientFills(pptx, ctx.gradientFills);\n\n const diagnostics = ctx.diagnostics.items;\n\n if (options?.strict && diagnostics.length > 0) {\n throw new DiagnosticsError(diagnostics);\n }\n\n return { pptx, diagnostics };\n}\n"],"mappings":";;;;;;;;;;;;;AAwBA,eAAsB,UACpB,KACA,WACA,SAO0B;CAC1B,MAAM,MAAM,mBAAmB,SAAS,mBAAmB,MAAM;CAIjE,IAAI,cAAc,cAAc,GAAG;CACnC,IAAI,SAAS,QACX,IAAI,cAAc,cAAc,KAAK,UAAU,QAAQ,MAAM,CAAC;CAGhE,MAAM,QAAQ,SAAS,GAAG;CAC1B,MAAM,kBAAoC,CAAC;CAE3C,KAAK,MAAM,CAAC,YAAY,SAAS,MAAM,QAAQ,GAAG;EAChD,IAAI;EACJ,IAAI;GACF,IAAI,SAAS,YAAY,OACvB,MAAM,MAAM,aAAa,MAAM,WAAW,GAAG;QAE7C,MAAM,MAAM,eAAe,MAAM,WAAW,GAAG;GAGjD,MAAM,aAAa,MAAM,aAAa,MAAM,KAD1B,qBAAqB,GACkB,CAAC;GAC1D,mBAAmB,YAAY,WAAW,KAAK,UAAU;GACzD,gBAAgB,KAAK,UAAU;EACjC,UAAU;GACR,IAAI,KAAK,aAAa,GAAG;EAC3B;CACF;CAGA,IAAI,SAAS,SAAS;CACtB,IAAI,SAAS,YACX,IAAI;EACF,MAAM,KAAK,MAAM,gBAAgB,QAAQ,UAAU;EACnD,IAAI,IACF,IAAI;OAEE,CAAC,OAAO,YACV,SAAS;IAAE,GAAG;IAAQ,YAAY;GAAG;EAAA,OAGvC,SAAS,EAAE,YAAY,GAAG;CAGhC,SAAS,GAAG;EACV,MAAM,UACJ,aAAa,QAAQ,EAAE,UAAU;EACnC,IAAI,YAAY,IAAI,4BAA4B,OAAO;CACzD;CAGF,MAAM,OAAO,MAAM,WAAW,iBAAiB,WAAW,KAAK,MAAM;CAGrE,+BAA+B,MAAM,IAAI,aAAa;CAEtD,MAAM,cAAc,IAAI,YAAY;CAEpC,IAAI,SAAS,UAAU,YAAY,SAAS,GAC1C,MAAM,IAAI,iBAAiB,WAAW;CAGxC,OAAO;EAAE;EAAM;CAAY;AAC7B"}
1
+ {"version":3,"file":"buildPptx.js","names":[],"sources":["../src/buildPptx.ts"],"sourcesContent":["import { autoFitSlide } from \"./autoFit/autoFit.ts\";\nimport { createBuildContext } from \"./buildContext.ts\";\nimport { calcYogaLayout } from \"./calcYogaLayout/calcYogaLayout.ts\";\nimport type { TextMeasurementMode } from \"./calcYogaLayout/measureText.ts\";\nimport type { YogaNodeMap } from \"./calcYogaLayout/types.ts\";\nimport { extractLayoutResults } from \"./calcYogaLayout/types.ts\";\nimport type { Diagnostic } from \"./diagnostics.ts\";\nimport { DiagnosticsError } from \"./diagnostics.ts\";\nimport { parseMasterPptx } from \"./parseMasterPptx.ts\";\nimport { parseXml } from \"./parseXml/parseXml.ts\";\nimport { patchPptxWriteForGlowEffects } from \"./renderPptx/glowEffects.ts\";\nimport { patchPptxWriteForGradientFills } from \"./renderPptx/gradientFills.ts\";\nimport { renderPptx } from \"./renderPptx/renderPptx.ts\";\nimport { freeYogaTree } from \"./shared/freeYogaTree.ts\";\nimport { toPositioned } from \"./toPositioned/toPositioned.ts\";\nimport { PositionedNode, SlideMasterOptions } from \"./types.ts\";\nimport { validatePositioned } from \"./validatePositioned/validatePositioned.ts\";\n\nexport type { TextMeasurementMode };\n\nexport interface BuildPptxResult {\n pptx: import(\"pptxgenjs\").default;\n diagnostics: Diagnostic[];\n}\n\nexport async function buildPptx(\n xml: string,\n slideSize: { w: number; h: number },\n options?: {\n master?: SlideMasterOptions;\n masterPptx?: ArrayBuffer | Uint8Array;\n textMeasurement?: TextMeasurementMode;\n autoFit?: boolean;\n strict?: boolean;\n },\n): Promise<BuildPptxResult> {\n const ctx = createBuildContext(options?.textMeasurement ?? \"auto\");\n\n // グラデーション後処理のマーカー色がユーザー指定色と衝突しないよう、\n // 入力 XML / master オプション中に現れる色を予約しておく\n ctx.gradientFills.reserveColors(xml);\n if (options?.master) {\n ctx.gradientFills.reserveColors(JSON.stringify(options.master));\n }\n\n const nodes = parseXml(xml);\n const positionedPages: PositionedNode[] = [];\n\n for (const [slideIndex, node] of nodes.entries()) {\n let map: YogaNodeMap | undefined;\n try {\n if (options?.autoFit !== false) {\n map = await autoFitSlide(node, slideSize, ctx);\n } else {\n map = await calcYogaLayout(node, slideSize, ctx);\n }\n const layoutMap = extractLayoutResults(map);\n const positioned = await toPositioned(node, ctx, layoutMap);\n validatePositioned(positioned, slideSize, ctx, slideIndex);\n positionedPages.push(positioned);\n } finally {\n if (map) freeYogaTree(map);\n }\n }\n\n // masterPptx から背景を抽出し、master オプションにマージ\n let master = options?.master;\n if (options?.masterPptx) {\n try {\n const bg = await parseMasterPptx(options.masterPptx);\n if (bg) {\n if (master) {\n // 明示的に background が指定されていない場合のみ、masterPptx の背景を使用\n if (!master.background) {\n master = { ...master, background: bg };\n }\n } else {\n master = { background: bg };\n }\n }\n } catch (e) {\n const message =\n e instanceof Error ? e.message : \"Unknown error parsing masterPptx\";\n ctx.diagnostics.add(\"MASTER_PPTX_PARSE_FAILED\", message);\n }\n }\n\n const pptx = await renderPptx(positionedPages, slideSize, ctx, master);\n\n // backgroundGradient / textGradient 使用時は write/writeFile に gradFill 置換の後処理を仕込む\n patchPptxWriteForGradientFills(pptx, ctx.gradientFills);\n\n // Shape / Icon の glow 指定がある場合は write/writeFile に effectLst 挿入の\n // 後処理を仕込む (gradientFills の patch 後にチェーンする)\n patchPptxWriteForGlowEffects(pptx, ctx.glowEffects);\n\n const diagnostics = ctx.diagnostics.items;\n\n if (options?.strict && diagnostics.length > 0) {\n throw new DiagnosticsError(diagnostics);\n }\n\n return { pptx, diagnostics };\n}\n"],"mappings":";;;;;;;;;;;;;;AAyBA,eAAsB,UACpB,KACA,WACA,SAO0B;CAC1B,MAAM,MAAM,mBAAmB,SAAS,mBAAmB,MAAM;CAIjE,IAAI,cAAc,cAAc,GAAG;CACnC,IAAI,SAAS,QACX,IAAI,cAAc,cAAc,KAAK,UAAU,QAAQ,MAAM,CAAC;CAGhE,MAAM,QAAQ,SAAS,GAAG;CAC1B,MAAM,kBAAoC,CAAC;CAE3C,KAAK,MAAM,CAAC,YAAY,SAAS,MAAM,QAAQ,GAAG;EAChD,IAAI;EACJ,IAAI;GACF,IAAI,SAAS,YAAY,OACvB,MAAM,MAAM,aAAa,MAAM,WAAW,GAAG;QAE7C,MAAM,MAAM,eAAe,MAAM,WAAW,GAAG;GAGjD,MAAM,aAAa,MAAM,aAAa,MAAM,KAD1B,qBAAqB,GACkB,CAAC;GAC1D,mBAAmB,YAAY,WAAW,KAAK,UAAU;GACzD,gBAAgB,KAAK,UAAU;EACjC,UAAU;GACR,IAAI,KAAK,aAAa,GAAG;EAC3B;CACF;CAGA,IAAI,SAAS,SAAS;CACtB,IAAI,SAAS,YACX,IAAI;EACF,MAAM,KAAK,MAAM,gBAAgB,QAAQ,UAAU;EACnD,IAAI,IACF,IAAI;OAEE,CAAC,OAAO,YACV,SAAS;IAAE,GAAG;IAAQ,YAAY;GAAG;EAAA,OAGvC,SAAS,EAAE,YAAY,GAAG;CAGhC,SAAS,GAAG;EACV,MAAM,UACJ,aAAa,QAAQ,EAAE,UAAU;EACnC,IAAI,YAAY,IAAI,4BAA4B,OAAO;CACzD;CAGF,MAAM,OAAO,MAAM,WAAW,iBAAiB,WAAW,KAAK,MAAM;CAGrE,+BAA+B,MAAM,IAAI,aAAa;CAItD,6BAA6B,MAAM,IAAI,WAAW;CAElD,MAAM,cAAc,IAAI,YAAY;CAEpC,IAAI,SAAS,UAAU,YAAY,SAAS,GAC1C,MAAM,IAAI,iBAAiB,WAAW;CAGxC,OAAO;EAAE;EAAM;CAAY;AAC7B"}
@@ -309,6 +309,7 @@ const NODE_COERCION_MAP = {
309
309
  text: "string",
310
310
  rotate: "number",
311
311
  ...TEXT_STYLE_RULES,
312
+ textGradient: "string",
312
313
  letterSpacing: "number",
313
314
  glow: TEXT_GLOW_RULE,
314
315
  outline: TEXT_OUTLINE_RULE
@@ -338,6 +339,8 @@ const NODE_COERCION_MAP = {
338
339
  color: "string",
339
340
  variant: "string",
340
341
  bgColor: "string",
342
+ glow: TEXT_GLOW_RULE,
343
+ outline: TEXT_OUTLINE_RULE,
341
344
  rotate: "number"
342
345
  },
343
346
  svg: {
@@ -358,6 +361,8 @@ const NODE_COERCION_MAP = {
358
361
  rotate: "number",
359
362
  fill: FILL_STYLE_RULE,
360
363
  line: BORDER_STYLE_RULE,
364
+ glow: TEXT_GLOW_RULE,
365
+ outline: TEXT_OUTLINE_RULE,
361
366
  ...TEXT_STYLE_RULES
362
367
  },
363
368
  chart: {
@@ -368,7 +373,8 @@ const NODE_COERCION_MAP = {
368
373
  showTitle: "boolean",
369
374
  title: "string",
370
375
  chartColors: "json",
371
- radarStyle: "string"
376
+ radarStyle: "string",
377
+ sparkline: "boolean"
372
378
  },
373
379
  timeline: {
374
380
  ...BASE_RULES,
@@ -556,6 +562,7 @@ const CHILD_ELEMENT_COERCION_MAP = {
556
562
  Span: {
557
563
  color: "string",
558
564
  fontFamily: "string",
565
+ fontSize: "number",
559
566
  letterSpacing: "number"
560
567
  }
561
568
  };
@@ -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 TEXT_GLOW_RULE: CoercionRule = {\n type: \"object\",\n shape: { size: \"number\", opacity: \"number\", color: \"string\" },\n};\n\nconst TEXT_OUTLINE_RULE: CoercionRule = {\n type: \"object\",\n shape: { size: \"number\", color: \"string\" },\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: {\n color: \"string\",\n width: \"number\",\n arrowType: \"string\",\n labelColor: \"string\",\n },\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 borderTop: BORDER_STYLE_RULE,\n borderRight: BORDER_STYLE_RULE,\n borderBottom: BORDER_STYLE_RULE,\n borderLeft: 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 subscript: \"boolean\",\n superscript: \"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 rotate: \"number\",\n ...TEXT_STYLE_RULES,\n letterSpacing: \"number\",\n glow: TEXT_GLOW_RULE,\n outline: TEXT_OUTLINE_RULE,\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 rotate: \"number\",\n },\n icon: {\n ...BASE_RULES,\n name: \"string\",\n size: \"number\",\n color: \"string\",\n variant: \"string\",\n bgColor: \"string\",\n rotate: \"number\",\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 rotate: \"number\",\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 dateColor: \"string\",\n titleColor: \"string\",\n descriptionColor: \"string\",\n },\n matrix: {\n ...BASE_RULES,\n axes: \"json\",\n quadrants: \"json\",\n items: \"json\",\n axisLabelColor: \"string\",\n quadrantLabelColor: \"string\",\n itemLabelColor: \"string\",\n },\n tree: {\n ...BASE_RULES,\n layout: \"string\",\n nodeShape: \"string\",\n data: \"json\",\n textColor: \"string\",\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 textColor: \"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 labelColor: \"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 subscript: \"boolean\",\n superscript: \"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 subscript: \"boolean\",\n superscript: \"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,iBAA+B;CACnC,MAAM;CACN,OAAO;EAAE,MAAM;EAAU,SAAS;EAAU,OAAO;CAAS;AAC9D;AAEA,MAAM,oBAAkC;CACtC,MAAM;CACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAS;AAC3C;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;EACL,OAAO;EACP,OAAO;EACP,WAAW;EACX,YAAY;CACd;AACF;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,WAAW;CACX,aAAa;CACb,cAAc;CACd,YAAY;CACZ,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,aAAa;CACb,WAAW;CACX,YAAY;CACZ,YAAY;AACd;AAGA,MAAa,oBAAkE;CAC7E,MAAM;EACJ,GAAG;EACH,MAAM;EACN,QAAQ;EACR,GAAG;EACH,eAAe;EACf,MAAM;EACN,SAAS;CACX;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;EACR,QAAQ;CACV;CACA,MAAM;EACJ,GAAG;EACH,MAAM;EACN,MAAM;EACN,OAAO;EACP,SAAS;EACT,SAAS;EACT,QAAQ;CACV;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,QAAQ;EACR,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;EACP,WAAW;EACX,YAAY;EACZ,kBAAkB;CACpB;CACA,QAAQ;EACN,GAAG;EACH,MAAM;EACN,WAAW;EACX,OAAO;EACP,gBAAgB;EAChB,oBAAoB;EACpB,gBAAgB;CAClB;CACA,MAAM;EACJ,GAAG;EACH,QAAQ;EACR,WAAW;EACX,MAAM;EACN,WAAW;EACX,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;EACP,WAAW;CACb;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;EACP,YAAY;CACd;CACA,KAAK,EACH,OAAO,SACT;CACA,IAAI;EACF,MAAM;EACN,UAAU;EACV,OAAO;EACP,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,WAAW;EACX,aAAa;EACb,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,aAAa;EACb,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
+ {"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 TEXT_GLOW_RULE: CoercionRule = {\n type: \"object\",\n shape: { size: \"number\", opacity: \"number\", color: \"string\" },\n};\n\nconst TEXT_OUTLINE_RULE: CoercionRule = {\n type: \"object\",\n shape: { size: \"number\", color: \"string\" },\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: {\n color: \"string\",\n width: \"number\",\n arrowType: \"string\",\n labelColor: \"string\",\n },\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 borderTop: BORDER_STYLE_RULE,\n borderRight: BORDER_STYLE_RULE,\n borderBottom: BORDER_STYLE_RULE,\n borderLeft: 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 subscript: \"boolean\",\n superscript: \"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 rotate: \"number\",\n ...TEXT_STYLE_RULES,\n textGradient: \"string\",\n letterSpacing: \"number\",\n glow: TEXT_GLOW_RULE,\n outline: TEXT_OUTLINE_RULE,\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 rotate: \"number\",\n },\n icon: {\n ...BASE_RULES,\n name: \"string\",\n size: \"number\",\n color: \"string\",\n variant: \"string\",\n bgColor: \"string\",\n glow: TEXT_GLOW_RULE,\n outline: TEXT_OUTLINE_RULE,\n rotate: \"number\",\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 rotate: \"number\",\n fill: FILL_STYLE_RULE,\n line: BORDER_STYLE_RULE,\n glow: TEXT_GLOW_RULE,\n outline: TEXT_OUTLINE_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 sparkline: \"boolean\",\n },\n timeline: {\n ...BASE_RULES,\n direction: \"string\",\n items: \"json\",\n dateColor: \"string\",\n titleColor: \"string\",\n descriptionColor: \"string\",\n },\n matrix: {\n ...BASE_RULES,\n axes: \"json\",\n quadrants: \"json\",\n items: \"json\",\n axisLabelColor: \"string\",\n quadrantLabelColor: \"string\",\n itemLabelColor: \"string\",\n },\n tree: {\n ...BASE_RULES,\n layout: \"string\",\n nodeShape: \"string\",\n data: \"json\",\n textColor: \"string\",\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 textColor: \"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 labelColor: \"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 subscript: \"boolean\",\n superscript: \"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 subscript: \"boolean\",\n superscript: \"boolean\",\n highlight: \"string\",\n color: \"string\",\n fontSize: \"number\",\n fontFamily: \"string\",\n },\n B: {},\n I: {},\n Span: {\n color: \"string\",\n fontFamily: \"string\",\n fontSize: \"number\",\n letterSpacing: \"number\",\n },\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,iBAA+B;CACnC,MAAM;CACN,OAAO;EAAE,MAAM;EAAU,SAAS;EAAU,OAAO;CAAS;AAC9D;AAEA,MAAM,oBAAkC;CACtC,MAAM;CACN,OAAO;EAAE,MAAM;EAAU,OAAO;CAAS;AAC3C;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;EACL,OAAO;EACP,OAAO;EACP,WAAW;EACX,YAAY;CACd;AACF;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,WAAW;CACX,aAAa;CACb,cAAc;CACd,YAAY;CACZ,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,aAAa;CACb,WAAW;CACX,YAAY;CACZ,YAAY;AACd;AAGA,MAAa,oBAAkE;CAC7E,MAAM;EACJ,GAAG;EACH,MAAM;EACN,QAAQ;EACR,GAAG;EACH,cAAc;EACd,eAAe;EACf,MAAM;EACN,SAAS;CACX;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;EACR,QAAQ;CACV;CACA,MAAM;EACJ,GAAG;EACH,MAAM;EACN,MAAM;EACN,OAAO;EACP,SAAS;EACT,SAAS;EACT,MAAM;EACN,SAAS;EACT,QAAQ;CACV;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,QAAQ;EACR,MAAM;EACN,MAAM;EACN,MAAM;EACN,SAAS;EACT,GAAG;CACL;CACA,OAAO;EACL,GAAG;EACH,WAAW;EACX,MAAM;EACN,YAAY;EACZ,WAAW;EACX,OAAO;EACP,aAAa;EACb,YAAY;EACZ,WAAW;CACb;CACA,UAAU;EACR,GAAG;EACH,WAAW;EACX,OAAO;EACP,WAAW;EACX,YAAY;EACZ,kBAAkB;CACpB;CACA,QAAQ;EACN,GAAG;EACH,MAAM;EACN,WAAW;EACX,OAAO;EACP,gBAAgB;EAChB,oBAAoB;EACpB,gBAAgB;CAClB;CACA,MAAM;EACJ,GAAG;EACH,QAAQ;EACR,WAAW;EACX,MAAM;EACN,WAAW;EACX,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;EACP,WAAW;CACb;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;EACP,YAAY;CACd;CACA,KAAK,EACH,OAAO,SACT;CACA,IAAI;EACF,MAAM;EACN,UAAU;EACV,OAAO;EACP,MAAM;EACN,QAAQ;EACR,WAAW;EACX,QAAQ;EACR,WAAW;EACX,aAAa;EACb,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,aAAa;EACb,WAAW;EACX,OAAO;EACP,UAAU;EACV,YAAY;CACd;CACA,GAAG,CAAC;CACJ,GAAG,CAAC;CACJ,MAAM;EACJ,OAAO;EACP,YAAY;EACZ,UAAU;EACV,eAAe;CACjB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseXml.d.ts","names":[],"sources":["../../src/parseXml/parseXml.ts"],"mappings":";;;cAiCa,aAAA,SAAsB,KAAK;EAAA,SACtB,MAAA;cACJ,MAAA;AAAA;;;;;;;AAAgB;AA8sC9B;;;;AAAoD;;;;;;;;;;;;;;;;;;;;;iBAApC,QAAA,CAAS,SAAA,WAAoB,OAAO"}
1
+ {"version":3,"file":"parseXml.d.ts","names":[],"sources":["../../src/parseXml/parseXml.ts"],"mappings":";;;cAiCa,aAAA,SAAsB,KAAK;EAAA,SACtB,MAAA;cACJ,MAAA;AAAA;;;;;;;AAAgB;AA0sC9B;;;;AAAoD;;;;;;;;;;;;;;;;;;;;;iBAApC,QAAA,CAAS,SAAA,WAAoB,OAAO"}
@@ -202,6 +202,7 @@ function extractTextRuns(children, inherited = {}) {
202
202
  const next = { ...inherited };
203
203
  if (spanAttrs.color && spanAttrs.color.trim()) next.color = spanAttrs.color;
204
204
  if (spanAttrs.fontFamily && spanAttrs.fontFamily.trim()) next.fontFamily = spanAttrs.fontFamily;
205
+ if (spanAttrs.fontSize && spanAttrs.fontSize.trim()) next.fontSize = Number(spanAttrs.fontSize);
205
206
  if (spanAttrs.letterSpacing && spanAttrs.letterSpacing.trim()) next.letterSpacing = Number(spanAttrs.letterSpacing);
206
207
  runs.push(...extractTextRuns(innerChildren, next));
207
208
  }
@@ -524,7 +525,7 @@ function resolveThemeToken(name, hashPrefix, tokens, themeDeclared, errors) {
524
525
  }
525
526
  function resolveThemeTokensDeep(value, key, tokens, themeDeclared, errors) {
526
527
  if (typeof value === "string") {
527
- if (key === "backgroundGradient") return value.replace(TOKEN_REF_IN_GRADIENT_PATTERN, (matched, name) => {
528
+ if (key === "backgroundGradient" || key === "textGradient") return value.replace(TOKEN_REF_IN_GRADIENT_PATTERN, (matched, name) => {
528
529
  return resolveThemeToken(name, "#", tokens, themeDeclared, errors) ?? matched;
529
530
  });
530
531
  if (key !== null && isColorKey(key)) {
@@ -602,8 +603,8 @@ function convertPomNode(nodeType, tagName, attrs, childElements, textContent, er
602
603
  }
603
604
  const childRule = def.xmlChildRule;
604
605
  if (childRule && childElements.length > 0) applyXmlChildRule(childRule, nodeType, tagName, childElements, result, errors, xmlNode);
605
- else if (def.childPolicy.kind === "pom-children" && childElements.length > 0) result.children = childElements.map((child) => convertElement(child, errors, theme)).filter((child) => child !== null);
606
- else if (def.childPolicy.kind !== "pom-children" && !childRule && childElements.length > 0) errors.push(`<${tagName}>: Unexpected child elements. <${tagName}> does not accept child elements`);
606
+ else if (def.childPolicy.kind === "pom-children") result.children = childElements.map((child) => convertElement(child, errors, theme)).filter((child) => child !== null);
607
+ else if (!childRule && childElements.length > 0) errors.push(`<${tagName}>: Unexpected child elements. <${tagName}> does not accept child elements`);
607
608
  for (const [key, value] of Object.entries(result)) {
608
609
  if (key === "type" || key === "children") continue;
609
610
  result[key] = resolveThemeTokensDeep(value, key, theme.tokens, theme.declared, errors);