@hirokisakabe/pom 1.4.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +158 -193
  2. package/dist/buildPptx.d.ts +2 -2
  3. package/dist/buildPptx.d.ts.map +1 -1
  4. package/dist/buildPptx.js +3 -1
  5. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  6. package/dist/calcYogaLayout/calcYogaLayout.js +95 -19
  7. package/dist/calcYogaLayout/fontLoader.d.ts +0 -7
  8. package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -1
  9. package/dist/calcYogaLayout/fontLoader.js +1 -1
  10. package/dist/calcYogaLayout/measureText.d.ts +0 -4
  11. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  12. package/dist/calcYogaLayout/measureText.js +0 -6
  13. package/dist/index.d.ts +2 -5
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -4
  16. package/dist/{inputSchema.d.ts → parseXml/inputSchema.d.ts} +254 -460
  17. package/dist/parseXml/inputSchema.d.ts.map +1 -0
  18. package/dist/{inputSchema.js → parseXml/inputSchema.js} +42 -140
  19. package/dist/{parseXml.d.ts → parseXml/parseXml.d.ts} +6 -2
  20. package/dist/parseXml/parseXml.d.ts.map +1 -0
  21. package/dist/parseXml/parseXml.js +823 -0
  22. package/dist/renderPptx/nodes/flow.d.ts.map +1 -1
  23. package/dist/renderPptx/nodes/flow.js +26 -16
  24. package/dist/renderPptx/nodes/index.d.ts +1 -0
  25. package/dist/renderPptx/nodes/index.d.ts.map +1 -1
  26. package/dist/renderPptx/nodes/index.js +1 -0
  27. package/dist/renderPptx/nodes/list.d.ts +12 -0
  28. package/dist/renderPptx/nodes/list.d.ts.map +1 -0
  29. package/dist/renderPptx/nodes/list.js +145 -0
  30. package/dist/renderPptx/nodes/matrix.d.ts.map +1 -1
  31. package/dist/renderPptx/nodes/matrix.js +43 -31
  32. package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -1
  33. package/dist/renderPptx/nodes/processArrow.js +14 -6
  34. package/dist/renderPptx/nodes/shape.js +2 -2
  35. package/dist/renderPptx/nodes/table.d.ts.map +1 -1
  36. package/dist/renderPptx/nodes/table.js +1 -1
  37. package/dist/renderPptx/nodes/timeline.d.ts.map +1 -1
  38. package/dist/renderPptx/nodes/timeline.js +58 -37
  39. package/dist/renderPptx/nodes/tree.d.ts.map +1 -1
  40. package/dist/renderPptx/nodes/tree.js +49 -40
  41. package/dist/renderPptx/renderPptx.d.ts +1 -2
  42. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  43. package/dist/renderPptx/renderPptx.js +8 -4
  44. package/dist/renderPptx/textOptions.d.ts +1 -29
  45. package/dist/renderPptx/textOptions.d.ts.map +1 -1
  46. package/dist/renderPptx/textOptions.js +1 -27
  47. package/dist/renderPptx/types.d.ts +0 -2
  48. package/dist/renderPptx/types.d.ts.map +1 -1
  49. package/dist/renderPptx/utils/backgroundBorder.js +1 -1
  50. package/dist/renderPptx/utils/scaleToFit.d.ts +8 -0
  51. package/dist/renderPptx/utils/scaleToFit.d.ts.map +1 -0
  52. package/dist/renderPptx/utils/scaleToFit.js +19 -0
  53. package/dist/shared/measureImage.d.ts.map +1 -0
  54. package/dist/{table/utils.d.ts → shared/tableUtils.d.ts} +1 -3
  55. package/dist/shared/tableUtils.d.ts.map +1 -0
  56. package/dist/{table/utils.js → shared/tableUtils.js} +2 -2
  57. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  58. package/dist/toPositioned/toPositioned.js +4 -2
  59. package/dist/types.d.ts +271 -154
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/types.js +67 -33
  62. package/package.json +3 -6
  63. package/dist/calcYogaLayout/measureImage.d.ts.map +0 -1
  64. package/dist/component.d.ts +0 -90
  65. package/dist/component.d.ts.map +0 -1
  66. package/dist/component.js +0 -123
  67. package/dist/inputSchema.d.ts.map +0 -1
  68. package/dist/parseXml.d.ts.map +0 -1
  69. package/dist/parseXml.js +0 -332
  70. package/dist/renderPptx/nodes/box.d.ts +0 -2
  71. package/dist/renderPptx/nodes/box.d.ts.map +0 -1
  72. package/dist/renderPptx/nodes/box.js +0 -3
  73. package/dist/renderPptx/utils/index.d.ts +0 -6
  74. package/dist/renderPptx/utils/index.d.ts.map +0 -1
  75. package/dist/renderPptx/utils/index.js +0 -3
  76. package/dist/renderPptx/utils/shapeDrawing.d.ts +0 -27
  77. package/dist/renderPptx/utils/shapeDrawing.d.ts.map +0 -1
  78. package/dist/renderPptx/utils/shapeDrawing.js +0 -36
  79. package/dist/renderPptx/utils/textDrawing.d.ts +0 -25
  80. package/dist/renderPptx/utils/textDrawing.d.ts.map +0 -1
  81. package/dist/renderPptx/utils/textDrawing.js +0 -25
  82. package/dist/schema.d.ts +0 -23
  83. package/dist/schema.d.ts.map +0 -1
  84. package/dist/schema.js +0 -24
  85. package/dist/table/utils.d.ts.map +0 -1
  86. /package/dist/{calcYogaLayout → shared}/measureImage.d.ts +0 -0
  87. /package/dist/{calcYogaLayout → shared}/measureImage.js +0 -0
@@ -1,4 +1,6 @@
1
1
  import { pxToIn, pxToPt } from "../units.js";
2
+ import { measureTimeline } from "../../calcYogaLayout/measureCompositeNodes.js";
3
+ import { calcScaleFactor } from "../utils/scaleToFit.js";
2
4
  export function renderTimelineNode(node, ctx) {
3
5
  const direction = node.direction ?? "horizontal";
4
6
  const items = node.items;
@@ -6,16 +8,21 @@ export function renderTimelineNode(node, ctx) {
6
8
  if (itemCount === 0)
7
9
  return;
8
10
  const defaultColor = "1D4ED8"; // blue
9
- const nodeRadius = 12; // px
10
- const lineWidth = 4; // px
11
+ const baseNodeRadius = 12; // px
12
+ const baseLineWidth = 4; // px
13
+ // スケール係数を計算
14
+ const intrinsic = measureTimeline(node);
15
+ const scaleFactor = calcScaleFactor(node.w, node.h, intrinsic.width, intrinsic.height, "timeline");
16
+ const nodeRadius = baseNodeRadius * scaleFactor;
17
+ const lineWidth = baseLineWidth * scaleFactor;
11
18
  if (direction === "horizontal") {
12
- renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth);
19
+ renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth, scaleFactor);
13
20
  }
14
21
  else {
15
- renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth);
22
+ renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth, scaleFactor);
16
23
  }
17
24
  }
18
- function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth) {
25
+ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth, scaleFactor) {
19
26
  const itemCount = items.length;
20
27
  const lineY = node.y + node.h / 2;
21
28
  const startX = node.x + nodeRadius;
@@ -29,6 +36,13 @@ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, li
29
36
  h: 0,
30
37
  line: { color: "E2E8F0", width: pxToPt(lineWidth) },
31
38
  });
39
+ const labelW = 120 * scaleFactor;
40
+ const dateLabelH = 24 * scaleFactor;
41
+ const titleLabelH = 24 * scaleFactor;
42
+ const descLabelH = 32 * scaleFactor;
43
+ const dateOffset = 40 * scaleFactor;
44
+ const titleGap = 8 * scaleFactor;
45
+ const descOffset = 32 * scaleFactor;
32
46
  // 各アイテムを描画
33
47
  items.forEach((item, index) => {
34
48
  const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);
@@ -46,11 +60,11 @@ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, li
46
60
  });
47
61
  // 日付を上に表示
48
62
  ctx.slide.addText(item.date, {
49
- x: pxToIn(cx - 60),
50
- y: pxToIn(cy - nodeRadius - 40),
51
- w: pxToIn(120),
52
- h: pxToIn(24),
53
- fontSize: pxToPt(12),
63
+ x: pxToIn(cx - labelW / 2),
64
+ y: pxToIn(cy - nodeRadius - dateOffset),
65
+ w: pxToIn(labelW),
66
+ h: pxToIn(dateLabelH),
67
+ fontSize: pxToPt(12 * scaleFactor),
54
68
  fontFace: "Noto Sans JP",
55
69
  color: "64748B",
56
70
  align: "center",
@@ -58,11 +72,11 @@ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, li
58
72
  });
59
73
  // タイトルを下に表示
60
74
  ctx.slide.addText(item.title, {
61
- x: pxToIn(cx - 60),
62
- y: pxToIn(cy + nodeRadius + 8),
63
- w: pxToIn(120),
64
- h: pxToIn(24),
65
- fontSize: pxToPt(14),
75
+ x: pxToIn(cx - labelW / 2),
76
+ y: pxToIn(cy + nodeRadius + titleGap),
77
+ w: pxToIn(labelW),
78
+ h: pxToIn(titleLabelH),
79
+ fontSize: pxToPt(14 * scaleFactor),
66
80
  fontFace: "Noto Sans JP",
67
81
  color: "1E293B",
68
82
  bold: true,
@@ -72,11 +86,11 @@ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, li
72
86
  // 説明を表示
73
87
  if (item.description) {
74
88
  ctx.slide.addText(item.description, {
75
- x: pxToIn(cx - 60),
76
- y: pxToIn(cy + nodeRadius + 32),
77
- w: pxToIn(120),
78
- h: pxToIn(32),
79
- fontSize: pxToPt(11),
89
+ x: pxToIn(cx - labelW / 2),
90
+ y: pxToIn(cy + nodeRadius + descOffset),
91
+ w: pxToIn(labelW),
92
+ h: pxToIn(descLabelH),
93
+ fontSize: pxToPt(11 * scaleFactor),
80
94
  fontFace: "Noto Sans JP",
81
95
  color: "64748B",
82
96
  align: "center",
@@ -85,9 +99,9 @@ function renderHorizontalTimeline(node, ctx, items, defaultColor, nodeRadius, li
85
99
  }
86
100
  });
87
101
  }
88
- function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth) {
102
+ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, lineWidth, scaleFactor) {
89
103
  const itemCount = items.length;
90
- const lineX = node.x + 40;
104
+ const lineX = node.x + 40 * scaleFactor;
91
105
  const startY = node.y + nodeRadius;
92
106
  const endY = node.y + node.h - nodeRadius;
93
107
  const lineLength = endY - startY;
@@ -99,6 +113,13 @@ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, line
99
113
  h: pxToIn(lineLength),
100
114
  line: { color: "E2E8F0", width: pxToPt(lineWidth) },
101
115
  });
116
+ const labelGap = 16 * scaleFactor;
117
+ const dateLabelW = 100 * scaleFactor;
118
+ const dateLabelH = 20 * scaleFactor;
119
+ const titleLabelH = 24 * scaleFactor;
120
+ const descLabelH = 32 * scaleFactor;
121
+ const titleLabelW = node.w - 80 * scaleFactor;
122
+ const descLabelW = node.w - 80 * scaleFactor;
102
123
  // 各アイテムを描画
103
124
  items.forEach((item, index) => {
104
125
  const progress = itemCount === 1 ? 0.5 : index / (itemCount - 1);
@@ -116,11 +137,11 @@ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, line
116
137
  });
117
138
  // 日付を左上に表示
118
139
  ctx.slide.addText(item.date, {
119
- x: pxToIn(cx + nodeRadius + 16),
120
- y: pxToIn(cy - nodeRadius - 4),
121
- w: pxToIn(100),
122
- h: pxToIn(20),
123
- fontSize: pxToPt(12),
140
+ x: pxToIn(cx + nodeRadius + labelGap),
141
+ y: pxToIn(cy - nodeRadius - 4 * scaleFactor),
142
+ w: pxToIn(dateLabelW),
143
+ h: pxToIn(dateLabelH),
144
+ fontSize: pxToPt(12 * scaleFactor),
124
145
  fontFace: "Noto Sans JP",
125
146
  color: "64748B",
126
147
  align: "left",
@@ -128,11 +149,11 @@ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, line
128
149
  });
129
150
  // タイトルを右に表示
130
151
  ctx.slide.addText(item.title, {
131
- x: pxToIn(cx + nodeRadius + 16),
132
- y: pxToIn(cy - 4),
133
- w: pxToIn(node.w - 80),
134
- h: pxToIn(24),
135
- fontSize: pxToPt(14),
152
+ x: pxToIn(cx + nodeRadius + labelGap),
153
+ y: pxToIn(cy - 4 * scaleFactor),
154
+ w: pxToIn(titleLabelW),
155
+ h: pxToIn(titleLabelH),
156
+ fontSize: pxToPt(14 * scaleFactor),
136
157
  fontFace: "Noto Sans JP",
137
158
  color: "1E293B",
138
159
  bold: true,
@@ -142,11 +163,11 @@ function renderVerticalTimeline(node, ctx, items, defaultColor, nodeRadius, line
142
163
  // 説明を表示
143
164
  if (item.description) {
144
165
  ctx.slide.addText(item.description, {
145
- x: pxToIn(cx + nodeRadius + 16),
146
- y: pxToIn(cy + 20),
147
- w: pxToIn(node.w - 80),
148
- h: pxToIn(32),
149
- fontSize: pxToPt(11),
166
+ x: pxToIn(cx + nodeRadius + labelGap),
167
+ y: pxToIn(cy + 20 * scaleFactor),
168
+ w: pxToIn(descLabelW),
169
+ h: pxToIn(descLabelH),
170
+ fontSize: pxToPt(11 * scaleFactor),
150
171
  fontFace: "Noto Sans JP",
151
172
  color: "64748B",
152
173
  align: "left",
@@ -1 +1 @@
1
- {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,KAAK,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAWpE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,aAAa,GACjB,IAAI,CAwQN"}
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,KAAK,kBAAkB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAWpE,wBAAgB,cAAc,CAC5B,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE,aAAa,GACjB,IAAI,CAwSN"}
@@ -1,4 +1,5 @@
1
1
  import { pxToIn, pxToPt } from "../units.js";
2
+ import { calcScaleFactor } from "../utils/scaleToFit.js";
2
3
  export function renderTreeNode(node, ctx) {
3
4
  const layout = node.layout ?? "vertical";
4
5
  const nodeShape = node.nodeShape ?? "rect";
@@ -33,7 +34,7 @@ export function renderTreeNode(node, ctx) {
33
34
  };
34
35
  }
35
36
  }
36
- // ツリーレイアウトを計算
37
+ // ツリーレイアウトを計算(原点(0,0)からの相対座標)
37
38
  function calculateTreeLayout(item, x, y) {
38
39
  const subtreeSize = calculateSubtreeSize(item);
39
40
  const layoutNode = {
@@ -85,15 +86,15 @@ export function renderTreeNode(node, ctx) {
85
86
  return layoutNode;
86
87
  }
87
88
  // 接続線を描画
88
- function drawConnector(parent, child, style) {
89
+ function drawConnector(parent, child, style, sf, ox, oy) {
89
90
  const lineColor = style.color ?? "333333";
90
91
  const lineWidth = style.width ?? 2;
91
92
  if (layout === "vertical") {
92
93
  // 親の下端中央から子の上端中央へ
93
- const parentCenterX = parent.x + parent.width / 2;
94
- const parentBottomY = parent.y + parent.height;
95
- const childCenterX = child.x + child.width / 2;
96
- const childTopY = child.y;
94
+ const parentCenterX = ox + (parent.x + parent.width / 2) * sf;
95
+ const parentBottomY = oy + (parent.y + parent.height) * sf;
96
+ const childCenterX = ox + (child.x + child.width / 2) * sf;
97
+ const childTopY = oy + child.y * sf;
97
98
  const midY = (parentBottomY + childTopY) / 2;
98
99
  // 垂直線(親から中間点まで)
99
100
  ctx.slide.addShape(ctx.pptx.ShapeType.line, {
@@ -101,7 +102,7 @@ export function renderTreeNode(node, ctx) {
101
102
  y: pxToIn(parentBottomY),
102
103
  w: 0,
103
104
  h: pxToIn(midY - parentBottomY),
104
- line: { color: lineColor, width: pxToPt(lineWidth) },
105
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
105
106
  });
106
107
  // 水平線(中間点で)
107
108
  const minX = Math.min(parentCenterX, childCenterX);
@@ -112,7 +113,7 @@ export function renderTreeNode(node, ctx) {
112
113
  y: pxToIn(midY),
113
114
  w: pxToIn(maxX - minX),
114
115
  h: 0,
115
- line: { color: lineColor, width: pxToPt(lineWidth) },
116
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
116
117
  });
117
118
  }
118
119
  // 垂直線(中間点から子まで)
@@ -121,15 +122,15 @@ export function renderTreeNode(node, ctx) {
121
122
  y: pxToIn(midY),
122
123
  w: 0,
123
124
  h: pxToIn(childTopY - midY),
124
- line: { color: lineColor, width: pxToPt(lineWidth) },
125
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
125
126
  });
126
127
  }
127
128
  else {
128
129
  // 親の右端中央から子の左端中央へ
129
- const parentRightX = parent.x + parent.width;
130
- const parentCenterY = parent.y + parent.height / 2;
131
- const childLeftX = child.x;
132
- const childCenterY = child.y + child.height / 2;
130
+ const parentRightX = ox + (parent.x + parent.width) * sf;
131
+ const parentCenterY = oy + (parent.y + parent.height / 2) * sf;
132
+ const childLeftX = ox + child.x * sf;
133
+ const childCenterY = oy + (child.y + child.height / 2) * sf;
133
134
  const midX = (parentRightX + childLeftX) / 2;
134
135
  // 水平線(親から中間点まで)
135
136
  ctx.slide.addShape(ctx.pptx.ShapeType.line, {
@@ -137,7 +138,7 @@ export function renderTreeNode(node, ctx) {
137
138
  y: pxToIn(parentCenterY),
138
139
  w: pxToIn(midX - parentRightX),
139
140
  h: 0,
140
- line: { color: lineColor, width: pxToPt(lineWidth) },
141
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
141
142
  });
142
143
  // 垂直線(中間点で)
143
144
  const minY = Math.min(parentCenterY, childCenterY);
@@ -148,7 +149,7 @@ export function renderTreeNode(node, ctx) {
148
149
  y: pxToIn(minY),
149
150
  w: 0,
150
151
  h: pxToIn(maxY - minY),
151
- line: { color: lineColor, width: pxToPt(lineWidth) },
152
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
152
153
  });
153
154
  }
154
155
  // 水平線(中間点から子まで)
@@ -157,12 +158,12 @@ export function renderTreeNode(node, ctx) {
157
158
  y: pxToIn(childCenterY),
158
159
  w: pxToIn(childLeftX - midX),
159
160
  h: 0,
160
- line: { color: lineColor, width: pxToPt(lineWidth) },
161
+ line: { color: lineColor, width: pxToPt(lineWidth * sf) },
161
162
  });
162
163
  }
163
164
  }
164
165
  // ノードを描画
165
- function drawTreeNode(layoutNode, shape, defaultNodeColor) {
166
+ function drawTreeNode(layoutNode, shape, defaultNodeColor, sf, ox, oy) {
166
167
  const color = layoutNode.item.color ?? defaultNodeColor;
167
168
  const shapeType = (() => {
168
169
  switch (shape) {
@@ -174,22 +175,26 @@ export function renderTreeNode(node, ctx) {
174
175
  return ctx.pptx.ShapeType.ellipse;
175
176
  }
176
177
  })();
178
+ const drawX = ox + layoutNode.x * sf;
179
+ const drawY = oy + layoutNode.y * sf;
180
+ const drawW = layoutNode.width * sf;
181
+ const drawH = layoutNode.height * sf;
177
182
  // ノードの背景
178
183
  ctx.slide.addShape(shapeType, {
179
- x: pxToIn(layoutNode.x),
180
- y: pxToIn(layoutNode.y),
181
- w: pxToIn(layoutNode.width),
182
- h: pxToIn(layoutNode.height),
184
+ x: pxToIn(drawX),
185
+ y: pxToIn(drawY),
186
+ w: pxToIn(drawW),
187
+ h: pxToIn(drawH),
183
188
  fill: { color },
184
- line: { color: "333333", width: pxToPt(1) },
189
+ line: { color: "333333", width: pxToPt(1 * sf) },
185
190
  });
186
191
  // ノードのラベル
187
192
  ctx.slide.addText(layoutNode.item.label, {
188
- x: pxToIn(layoutNode.x),
189
- y: pxToIn(layoutNode.y),
190
- w: pxToIn(layoutNode.width),
191
- h: pxToIn(layoutNode.height),
192
- fontSize: pxToPt(12),
193
+ x: pxToIn(drawX),
194
+ y: pxToIn(drawY),
195
+ w: pxToIn(drawW),
196
+ h: pxToIn(drawH),
197
+ fontSize: pxToPt(12 * sf),
193
198
  fontFace: "Noto Sans JP",
194
199
  color: "FFFFFF",
195
200
  align: "center",
@@ -197,27 +202,31 @@ export function renderTreeNode(node, ctx) {
197
202
  });
198
203
  }
199
204
  // すべての接続線を再帰的に描画
200
- function drawAllConnectors(layoutNode) {
205
+ function drawAllConnectors(layoutNode, sf, ox, oy) {
201
206
  for (const child of layoutNode.children) {
202
- drawConnector(layoutNode, child, connectorStyle);
203
- drawAllConnectors(child);
207
+ drawConnector(layoutNode, child, connectorStyle, sf, ox, oy);
208
+ drawAllConnectors(child, sf, ox, oy);
204
209
  }
205
210
  }
206
211
  // すべてのノードを再帰的に描画
207
- function drawAllNodes(layoutNode) {
208
- drawTreeNode(layoutNode, nodeShape, defaultColor);
212
+ function drawAllNodes(layoutNode, sf, ox, oy) {
213
+ drawTreeNode(layoutNode, nodeShape, defaultColor, sf, ox, oy);
209
214
  for (const child of layoutNode.children) {
210
- drawAllNodes(child);
215
+ drawAllNodes(child, sf, ox, oy);
211
216
  }
212
217
  }
213
218
  // ツリーのサイズを計算
214
219
  const treeSize = calculateSubtreeSize(node.data);
215
- // 描画領域内の中央に配置
216
- const offsetX = node.x + (node.w - treeSize.width) / 2;
217
- const offsetY = node.y + (node.h - treeSize.height) / 2;
218
- // レイアウト計算
219
- const rootLayout = calculateTreeLayout(node.data, offsetX, offsetY);
220
+ // スケール係数を計算
221
+ const scaleFactor = calcScaleFactor(node.w, node.h, treeSize.width, treeSize.height, "tree");
222
+ // スケール後のサイズで中央配置オフセットを計算
223
+ const scaledW = treeSize.width * scaleFactor;
224
+ const scaledH = treeSize.height * scaleFactor;
225
+ const offsetX = node.x + (node.w - scaledW) / 2;
226
+ const offsetY = node.y + (node.h - scaledH) / 2;
227
+ // レイアウト計算(原点(0,0)からの相対座標)
228
+ const rootLayout = calculateTreeLayout(node.data, 0, 0);
220
229
  // 描画(接続線を先に、ノードを後に描画)
221
- drawAllConnectors(rootLayout);
222
- drawAllNodes(rootLayout);
230
+ drawAllConnectors(rootLayout, scaleFactor, offsetX, offsetY);
231
+ drawAllNodes(rootLayout, scaleFactor, offsetX, offsetY);
223
232
  }
@@ -3,8 +3,6 @@ type SlidePx = {
3
3
  w: number;
4
4
  h: number;
5
5
  };
6
- export { createTextOptions, convertUnderline, convertStrike, } from "./textOptions.ts";
7
- export { PX_PER_IN, pxToIn, pxToPt } from "./units.ts";
8
6
  /**
9
7
  * PositionedNode ツリーを PptxGenJS スライドに変換する
10
8
  * @param pages PositionedNode ツリーの配列(各要素が1ページ)
@@ -13,4 +11,5 @@ export { PX_PER_IN, pxToIn, pxToPt } from "./units.ts";
13
11
  * @returns PptxGenJS インスタンス
14
12
  */
15
13
  export declare function renderPptx(pages: PositionedNode[], slidePx: SlidePx, master?: SlideMasterOptions): import("pptxgenjs").default;
14
+ export {};
16
15
  //# sourceMappingURL=renderPptx.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAoBrB,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACxC,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAqJvD;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,kBAAkB,+BAqK5B"}
1
+ {"version":3,"file":"renderPptx.d.ts","sourceRoot":"","sources":["../../src/renderPptx/renderPptx.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EACV,cAAc,EACd,kBAAkB,EAEnB,MAAM,aAAa,CAAC;AAsBrB,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAqJxC;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,kBAAkB,+BA6K5B"}
@@ -7,11 +7,9 @@ const pptxModule = require("pptxgenjs");
7
7
  const PptxGenJS = pptxModule.default ?? pptxModule;
8
8
  import { pxToIn, pxToPt } from "./units.js";
9
9
  import { convertUnderline, convertStrike } from "./textOptions.js";
10
- import { getImageData } from "../calcYogaLayout/measureImage.js";
10
+ import { getImageData } from "../shared/measureImage.js";
11
11
  import { renderBackgroundAndBorder } from "./utils/backgroundBorder.js";
12
- import { renderTextNode, renderImageNode, renderTableNode, renderShapeNode, renderChartNode, renderTimelineNode, renderMatrixNode, renderTreeNode, renderFlowNode, renderProcessArrowNode, renderLineNode, } from "./nodes/index.js";
13
- export { createTextOptions, convertUnderline, convertStrike, } from "./textOptions.js";
14
- export { PX_PER_IN, pxToIn, pxToPt } from "./units.js";
12
+ import { renderTextNode, renderImageNode, renderTableNode, renderShapeNode, renderChartNode, renderTimelineNode, renderMatrixNode, renderTreeNode, renderFlowNode, renderProcessArrowNode, renderLineNode, renderUlNode, renderOlNode, } from "./nodes/index.js";
15
13
  const DEFAULT_MASTER_NAME = "POM_MASTER";
16
14
  /**
17
15
  * MasterObject を pptxgenjs の objects 形式に変換する
@@ -240,6 +238,12 @@ export function renderPptx(pages, slidePx, master) {
240
238
  case "text":
241
239
  renderTextNode(node, ctx);
242
240
  break;
241
+ case "ul":
242
+ renderUlNode(node, ctx);
243
+ break;
244
+ case "ol":
245
+ renderOlNode(node, ctx);
246
+ break;
243
247
  case "image":
244
248
  renderImageNode(node, ctx);
245
249
  break;
@@ -1,4 +1,4 @@
1
- import type { PositionedNode, BulletOptions, Underline, UnderlineStyle } from "../types.ts";
1
+ import type { PositionedNode, Underline, UnderlineStyle } from "../types.ts";
2
2
  type TextNode = Extract<PositionedNode, {
3
3
  type: "text";
4
4
  }>;
@@ -13,13 +13,6 @@ export declare function convertUnderline(underline: Underline | undefined): {
13
13
  * strike プロパティを pptxgenjs 形式に変換する
14
14
  */
15
15
  export declare function convertStrike(strike: boolean | undefined): "sngStrike" | undefined;
16
- type PptxBulletOptions = {
17
- type?: "bullet" | "number";
18
- indent?: number;
19
- numberType?: BulletOptions["numberType"];
20
- numberStartAt?: number;
21
- };
22
- export declare function createBulletOptions(bullet: boolean | BulletOptions): PptxBulletOptions | boolean;
23
16
  export declare function createTextOptions(node: TextNode): {
24
17
  x: number;
25
18
  y: number;
@@ -40,27 +33,6 @@ export declare function createTextOptions(node: TextNode): {
40
33
  };
41
34
  strike: "sngStrike";
42
35
  highlight: string;
43
- } | {
44
- bullet: boolean | PptxBulletOptions;
45
- x: number;
46
- y: number;
47
- w: number;
48
- h: number;
49
- fontSize: number;
50
- fontFace: string;
51
- align: "right" | "left" | "center";
52
- valign: "top";
53
- margin: number;
54
- lineSpacingMultiple: number;
55
- color: string;
56
- bold: boolean;
57
- italic: boolean;
58
- underline: {
59
- style?: UnderlineStyle;
60
- color?: string;
61
- };
62
- strike: "sngStrike";
63
- highlight: string;
64
36
  };
65
37
  export {};
66
38
  //# sourceMappingURL=textOptions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"textOptions.d.ts","sourceRoot":"","sources":["../../src/renderPptx/textOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,SAAS,EACT,cAAc,EACf,MAAM,aAAa,CAAC;AAGrB,KAAK,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B;IAAE,KAAK,CAAC,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQxD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,GAC1B,WAAW,GAAG,SAAS,CAGzB;AAED,KAAK,iBAAiB,GAAG;IACvB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,OAAO,GAAG,aAAa,GAC9B,iBAAiB,GAAG,OAAO,CAqB7B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ;;;;;;;;;;;;;;;gBApDnC,cAAc;gBAAU,MAAM;;;;;;;;;;;;;;;;;;;;gBAA9B,cAAc;gBAAU,MAAM;;;;EAoF1C"}
1
+ {"version":3,"file":"textOptions.d.ts","sourceRoot":"","sources":["../../src/renderPptx/textOptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7E,KAAK,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1D;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,SAAS,GAAG,SAAS,GAC/B;IAAE,KAAK,CAAC,EAAE,cAAc,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAQxD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,GAAG,SAAS,GAC1B,WAAW,GAAG,SAAS,CAGzB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,QAAQ;;;;;;;;;;;;;;;gBApBnC,cAAc;gBAAU,MAAM;;;;EA2C1C"}
@@ -22,30 +22,11 @@ export function convertStrike(strike) {
22
22
  return "sngStrike";
23
23
  return undefined;
24
24
  }
25
- export function createBulletOptions(bullet) {
26
- if (typeof bullet === "boolean") {
27
- return bullet;
28
- }
29
- const options = {};
30
- if (bullet.type !== undefined) {
31
- options.type = bullet.type;
32
- }
33
- if (bullet.indent !== undefined) {
34
- options.indent = bullet.indent;
35
- }
36
- if (bullet.numberType !== undefined) {
37
- options.numberType = bullet.numberType;
38
- }
39
- if (bullet.numberStartAt !== undefined) {
40
- options.numberStartAt = bullet.numberStartAt;
41
- }
42
- return options;
43
- }
44
25
  export function createTextOptions(node) {
45
26
  const fontSizePx = node.fontPx ?? 24;
46
27
  const fontFamily = node.fontFamily ?? "Noto Sans JP";
47
28
  const lineSpacingMultiple = node.lineSpacingMultiple ?? 1.3;
48
- const baseOptions = {
29
+ return {
49
30
  x: pxToIn(node.x),
50
31
  y: pxToIn(node.y),
51
32
  w: pxToIn(node.w),
@@ -63,11 +44,4 @@ export function createTextOptions(node) {
63
44
  strike: convertStrike(node.strike),
64
45
  highlight: node.highlight,
65
46
  };
66
- if (node.bullet !== undefined) {
67
- return {
68
- ...baseOptions,
69
- bullet: createBulletOptions(node.bullet),
70
- };
71
- }
72
- return baseOptions;
73
47
  }
@@ -1,4 +1,3 @@
1
- import type { PositionedNode } from "../types.ts";
2
1
  type PptxGenJSClass = import("pptxgenjs").default;
3
2
  export type SlideInstance = ReturnType<PptxGenJSClass["addSlide"]>;
4
3
  export type PptxInstance = PptxGenJSClass;
@@ -6,6 +5,5 @@ export type RenderContext = {
6
5
  slide: SlideInstance;
7
6
  pptx: PptxInstance;
8
7
  };
9
- export type NodeRenderer<T extends PositionedNode> = (node: T, ctx: RenderContext) => void;
10
8
  export {};
11
9
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderPptx/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,KAAK,cAAc,GAAG,OAAO,WAAW,EAAE,OAAO,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,cAAc,IAAI,CACnD,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,aAAa,KACf,IAAI,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderPptx/types.ts"],"names":[],"mappings":"AAAA,KAAK,cAAc,GAAG,OAAO,WAAW,EAAE,OAAO,CAAC;AAClD,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;AACnE,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,IAAI,EAAE,YAAY,CAAC;CACpB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { getImageData } from "../../calcYogaLayout/measureImage.js";
1
+ import { getImageData } from "../../shared/measureImage.js";
2
2
  import { pxToIn, pxToPt } from "../units.js";
3
3
  function convertShadow(shadow) {
4
4
  return {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * 割り当てサイズと固有サイズからスケール係数を計算する。
3
+ *
4
+ * - scaleFactor = min(allocatedW / intrinsicW, allocatedH / intrinsicH, 1.0)
5
+ * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして console.warn
6
+ */
7
+ export declare function calcScaleFactor(allocatedW: number, allocatedH: number, intrinsicW: number, intrinsicH: number, nodeType: string): number;
8
+ //# sourceMappingURL=scaleToFit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaleToFit.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/scaleToFit.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,MAAM,CAeR"}
@@ -0,0 +1,19 @@
1
+ const MIN_SCALE_THRESHOLD = 0.5;
2
+ /**
3
+ * 割り当てサイズと固有サイズからスケール係数を計算する。
4
+ *
5
+ * - scaleFactor = min(allocatedW / intrinsicW, allocatedH / intrinsicH, 1.0)
6
+ * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして console.warn
7
+ */
8
+ export function calcScaleFactor(allocatedW, allocatedH, intrinsicW, intrinsicH, nodeType) {
9
+ if (intrinsicW <= 0 || intrinsicH <= 0)
10
+ return 1.0;
11
+ const scaleX = allocatedW / intrinsicW;
12
+ const scaleY = allocatedH / intrinsicH;
13
+ let scaleFactor = Math.min(scaleX, scaleY, 1.0);
14
+ if (scaleFactor < MIN_SCALE_THRESHOLD) {
15
+ console.warn(`[pom] ${nodeType} node: scale factor ${scaleFactor.toFixed(2)} is below threshold ${MIN_SCALE_THRESHOLD}. Content may overflow.`);
16
+ scaleFactor = MIN_SCALE_THRESHOLD;
17
+ }
18
+ return scaleFactor;
19
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measureImage.d.ts","sourceRoot":"","sources":["../../src/shared/measureImage.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE5D;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CA0DD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqDA"}
@@ -1,6 +1,4 @@
1
1
  import type { TableNode } from "../types.ts";
2
- export declare const DEFAULT_TABLE_ROW_HEIGHT = 32;
3
- export declare const DEFAULT_TABLE_COLUMN_WIDTH = 100;
4
2
  export declare function calcTableIntrinsicSize(node: TableNode): {
5
3
  width: number;
6
4
  height: number;
@@ -15,4 +13,4 @@ export declare function resolveRowHeights(node: TableNode): number[];
15
13
  * @param tableWidth テーブル全体の幅(レイアウト計算後の確定値)
16
14
  */
17
15
  export declare function resolveColumnWidths(node: TableNode, tableWidth: number): number[];
18
- //# sourceMappingURL=utils.d.ts.map
16
+ //# sourceMappingURL=tableUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableUtils.d.ts","sourceRoot":"","sources":["../../src/shared/tableUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,SAAS;;;EAQrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,YAGhD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAeV"}
@@ -1,5 +1,5 @@
1
- export const DEFAULT_TABLE_ROW_HEIGHT = 32;
2
- export const DEFAULT_TABLE_COLUMN_WIDTH = 100;
1
+ const DEFAULT_TABLE_ROW_HEIGHT = 32;
2
+ const DEFAULT_TABLE_COLUMN_WIDTH = 100;
3
3
  export function calcTableIntrinsicSize(node) {
4
4
  const width = node.columns.reduce((sum, column) => sum + (column.width ?? DEFAULT_TABLE_COLUMN_WIDTH), 0);
5
5
  const height = resolveRowHeights(node).reduce((sum, h) => sum + h, 0);
@@ -1 +1 @@
1
- {"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG3D;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CAyMhB"}
1
+ {"version":3,"file":"toPositioned.d.ts","sourceRoot":"","sources":["../../src/toPositioned/toPositioned.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG3D;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CA2MhB"}
@@ -1,4 +1,4 @@
1
- import { getImageData } from "../calcYogaLayout/measureImage.js";
1
+ import { getImageData } from "../shared/measureImage.js";
2
2
  /**
3
3
  * POMNode ツリーを絶対座標付きの PositionedNode ツリーに変換する
4
4
  * @param pom 入力 POMNode
@@ -14,7 +14,9 @@ export function toPositioned(pom, parentX = 0, parentY = 0) {
14
14
  const absoluteX = parentX + layout.left;
15
15
  const absoluteY = parentY + layout.top;
16
16
  switch (pom.type) {
17
- case "text": {
17
+ case "text":
18
+ case "ul":
19
+ case "ol": {
18
20
  return {
19
21
  ...pom,
20
22
  x: absoluteX,