@hirokisakabe/pom 8.5.1 → 8.7.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 +37 -24
- package/dist/autoFit/strategies/reduceFontSize.js +23 -7
- package/dist/autoFit/strategies/reduceFontSize.js.map +1 -1
- package/dist/autoFit/strategies/uniformScale.js +19 -4
- package/dist/autoFit/strategies/uniformScale.js.map +1 -1
- package/dist/parseXml/coercionRules.js +9 -1
- package/dist/parseXml/coercionRules.js.map +1 -1
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js +10 -5
- package/dist/parseXml/parseXml.js.map +1 -1
- package/dist/parseXml/serializeXml.d.ts +3 -2
- package/dist/parseXml/serializeXml.d.ts.map +1 -1
- package/dist/parseXml/serializeXml.js +4 -2
- package/dist/parseXml/serializeXml.js.map +1 -1
- package/dist/registry/definitions/list.js +2 -1
- package/dist/registry/definitions/list.js.map +1 -1
- package/dist/registry/definitions/text.js +2 -1
- package/dist/registry/definitions/text.js.map +1 -1
- package/dist/registry/xmlChildRules.js +11 -1
- package/dist/registry/xmlChildRules.js.map +1 -1
- package/dist/renderPptx/nodes/chart.js +43 -3
- package/dist/renderPptx/nodes/chart.js.map +1 -1
- package/dist/renderPptx/nodes/list.js +15 -2
- package/dist/renderPptx/nodes/list.js.map +1 -1
- package/dist/renderPptx/nodes/shape.js +2 -0
- package/dist/renderPptx/nodes/shape.js.map +1 -1
- package/dist/renderPptx/nodes/table.js +22 -15
- package/dist/renderPptx/nodes/table.js.map +1 -1
- package/dist/renderPptx/nodes/text.js +6 -2
- package/dist/renderPptx/nodes/text.js.map +1 -1
- package/dist/renderPptx/textOptions.js +19 -1
- package/dist/renderPptx/textOptions.js.map +1 -1
- package/dist/types.d.ts +27 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +17 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
## Table of Contents
|
|
28
28
|
|
|
29
29
|
- [Features](#features)
|
|
30
|
+
- [Installation](#installation)
|
|
30
31
|
- [Quick Start](#quick-start)
|
|
31
32
|
- [Available Nodes](#available-nodes)
|
|
32
33
|
- [Node Examples](#node-examples)
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
- **Flexible Layout** — Flexbox-style layout with VStack / HStack, powered by yoga-layout. Ratio-based layouts (e.g., 2:1 columns) via the `grow` attribute (CSS `flex-grow`).
|
|
41
42
|
- **Shorthand + Dot Notation** — Layout/style attributes (e.g. `padding`, `margin`, `border`, `fill`, `shadow`) can mix shorthand and dot notation on the same node. Shorthand sets defaults and dot notation overrides specific keys.
|
|
42
43
|
- **Per-Side Borders** — `borderTop` / `borderRight` / `borderBottom` / `borderLeft` style each edge independently (e.g. `borderLeft.width="6"` for an accent bar, `borderBottom.width="3"` for an underlined heading), merging field-by-field with the uniform `border`. See [Nodes — Common Properties](./docs/nodes.md#common-properties).
|
|
43
|
-
- **Rich Nodes** —
|
|
44
|
+
- **Rich Nodes** — 20 built-in node types: charts, flowcharts, tables, timelines, org trees, and more.
|
|
44
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).
|
|
45
46
|
- **Schema-validated** — XML input is validated with Zod schemas at runtime with clear error messages.
|
|
46
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.
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
- **Master Slide** — Define headers, footers, and page numbers once — applied to all slides automatically.
|
|
50
51
|
- **Accurate Text Measurement** — Text width measured with opentype.js and bundled Noto Sans JP fonts for consistent layout.
|
|
51
52
|
|
|
52
|
-
##
|
|
53
|
+
## Installation
|
|
53
54
|
|
|
54
55
|
> Requires Node.js 18+
|
|
55
56
|
|
|
@@ -57,6 +58,8 @@
|
|
|
57
58
|
npm install @hirokisakabe/pom
|
|
58
59
|
```
|
|
59
60
|
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
60
63
|
```typescript
|
|
61
64
|
import { buildPptx } from "@hirokisakabe/pom";
|
|
62
65
|
|
|
@@ -86,28 +89,28 @@ Each slide must be wrapped in a `<Slide>` element. To produce multiple slides, l
|
|
|
86
89
|
|
|
87
90
|
## Available Nodes
|
|
88
91
|
|
|
89
|
-
| Node | Description
|
|
90
|
-
| ------------ |
|
|
91
|
-
| Text | Text with font styling, decoration, rotation, letter spacing, glow / outline effects, inline bold/italic/underline/strike/highlight/color, and hyperlinks |
|
|
92
|
-
| Ul | Unordered (bullet) list with Li items
|
|
93
|
-
| Ol | Ordered (numbered) list with Li items
|
|
94
|
-
| Image | Images from file path, URL, or base64, with optional rotation
|
|
95
|
-
| Table | Tables with customizable columns and rows
|
|
96
|
-
| Shape | PowerPoint shapes (roundRect, ellipse, etc.) with optional rotation
|
|
97
|
-
| Chart | Charts (bar, line, pie, area, doughnut, radar)
|
|
98
|
-
| Timeline | Timeline / roadmap visualizations
|
|
99
|
-
| Matrix | 2x2 positioning maps
|
|
100
|
-
| Tree | Organization charts and decision trees
|
|
101
|
-
| Flow | Flowcharts with nodes and edges
|
|
102
|
-
| ProcessArrow | Chevron-style process diagrams
|
|
103
|
-
| Pyramid | Pyramid diagrams for hierarchies
|
|
104
|
-
| Line | Horizontal / vertical lines
|
|
105
|
-
| Arrow | Connectors between nodes referenced by ID
|
|
106
|
-
| Layer | Absolute-positioned overlay container
|
|
107
|
-
| VStack | Vertical stack layout
|
|
108
|
-
| HStack | Horizontal stack layout
|
|
109
|
-
| Icon | Lucide icons with optional rotation
|
|
110
|
-
| 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 |
|
|
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 |
|
|
111
114
|
|
|
112
115
|
For detailed node documentation, see [Nodes](./docs/nodes.md).
|
|
113
116
|
|
|
@@ -122,6 +125,16 @@ For detailed node documentation, see [Nodes](./docs/nodes.md).
|
|
|
122
125
|
<ChartDataPoint label="Feb" value="45" />
|
|
123
126
|
</ChartSeries>
|
|
124
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>
|
|
125
138
|
```
|
|
126
139
|
|
|
127
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 =
|
|
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 === "
|
|
26
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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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"}
|
|
@@ -297,6 +297,8 @@ const TEXT_STYLE_RULES = {
|
|
|
297
297
|
italic: "boolean",
|
|
298
298
|
underline: UNDERLINE_RULE,
|
|
299
299
|
strike: "boolean",
|
|
300
|
+
subscript: "boolean",
|
|
301
|
+
superscript: "boolean",
|
|
300
302
|
highlight: "string",
|
|
301
303
|
fontFamily: "string",
|
|
302
304
|
lineHeight: "number"
|
|
@@ -366,7 +368,8 @@ const NODE_COERCION_MAP = {
|
|
|
366
368
|
showTitle: "boolean",
|
|
367
369
|
title: "string",
|
|
368
370
|
chartColors: "json",
|
|
369
|
-
radarStyle: "string"
|
|
371
|
+
radarStyle: "string",
|
|
372
|
+
sparkline: "boolean"
|
|
370
373
|
},
|
|
371
374
|
timeline: {
|
|
372
375
|
...BASE_RULES,
|
|
@@ -527,6 +530,8 @@ const CHILD_ELEMENT_COERCION_MAP = {
|
|
|
527
530
|
italic: "boolean",
|
|
528
531
|
underline: UNDERLINE_RULE,
|
|
529
532
|
strike: "boolean",
|
|
533
|
+
subscript: "boolean",
|
|
534
|
+
superscript: "boolean",
|
|
530
535
|
highlight: "string",
|
|
531
536
|
fontFamily: "string",
|
|
532
537
|
textAlign: "string",
|
|
@@ -540,6 +545,8 @@ const CHILD_ELEMENT_COERCION_MAP = {
|
|
|
540
545
|
italic: "boolean",
|
|
541
546
|
underline: UNDERLINE_RULE,
|
|
542
547
|
strike: "boolean",
|
|
548
|
+
subscript: "boolean",
|
|
549
|
+
superscript: "boolean",
|
|
543
550
|
highlight: "string",
|
|
544
551
|
color: "string",
|
|
545
552
|
fontSize: "number",
|
|
@@ -550,6 +557,7 @@ const CHILD_ELEMENT_COERCION_MAP = {
|
|
|
550
557
|
Span: {
|
|
551
558
|
color: "string",
|
|
552
559
|
fontFamily: "string",
|
|
560
|
+
fontSize: "number",
|
|
553
561
|
letterSpacing: "number"
|
|
554
562
|
}
|
|
555
563
|
};
|
|
@@ -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 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 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":"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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 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 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":"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"}
|
|
@@ -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;
|
|
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;AAitC9B;;;;AAAoD;;;;;;;;;;;;;;;;;;;;;iBAApC,QAAA,CAAS,SAAA,WAAoB,OAAO"}
|
|
@@ -176,11 +176,15 @@ function extractTextRuns(children, inherited = {}) {
|
|
|
176
176
|
const tag = getTagName(child);
|
|
177
177
|
const innerChildren = getRawChildren(child);
|
|
178
178
|
const booleanFormat = INLINE_BOOLEAN_FORMATS.find((format) => format.tag === tag);
|
|
179
|
-
if (booleanFormat)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
if (booleanFormat) {
|
|
180
|
+
const next = {
|
|
181
|
+
...inherited,
|
|
182
|
+
[booleanFormat.property]: true
|
|
183
|
+
};
|
|
184
|
+
if (booleanFormat.property === "subscript") delete next.superscript;
|
|
185
|
+
if (booleanFormat.property === "superscript") delete next.subscript;
|
|
186
|
+
runs.push(...extractTextRuns(innerChildren, next));
|
|
187
|
+
} else if (tag === "A") {
|
|
184
188
|
const next = { ...inherited };
|
|
185
189
|
const href = getAttributes(child).href;
|
|
186
190
|
if (href) next.href = href;
|
|
@@ -198,6 +202,7 @@ function extractTextRuns(children, inherited = {}) {
|
|
|
198
202
|
const next = { ...inherited };
|
|
199
203
|
if (spanAttrs.color && spanAttrs.color.trim()) next.color = spanAttrs.color;
|
|
200
204
|
if (spanAttrs.fontFamily && spanAttrs.fontFamily.trim()) next.fontFamily = spanAttrs.fontFamily;
|
|
205
|
+
if (spanAttrs.fontSize && spanAttrs.fontSize.trim()) next.fontSize = Number(spanAttrs.fontSize);
|
|
201
206
|
if (spanAttrs.letterSpacing && spanAttrs.letterSpacing.trim()) next.letterSpacing = Number(spanAttrs.letterSpacing);
|
|
202
207
|
runs.push(...extractTextRuns(innerChildren, next));
|
|
203
208
|
}
|