@hirokisakabe/pom 0.1.12 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +31 -584
  2. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  3. package/dist/calcYogaLayout/calcYogaLayout.js +61 -84
  4. package/dist/calcYogaLayout/fontLoader.d.ts +20 -0
  5. package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -0
  6. package/dist/calcYogaLayout/fontLoader.js +59 -0
  7. package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts +7 -0
  8. package/dist/calcYogaLayout/fonts/notoSansJPBold.d.ts.map +1 -0
  9. package/dist/calcYogaLayout/fonts/notoSansJPBold.js +6 -0
  10. package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts +7 -0
  11. package/dist/calcYogaLayout/fonts/notoSansJPRegular.d.ts.map +1 -0
  12. package/dist/calcYogaLayout/fonts/notoSansJPRegular.js +6 -0
  13. package/dist/calcYogaLayout/measureText.d.ts +1 -1
  14. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  15. package/dist/calcYogaLayout/measureText.js +65 -114
  16. package/dist/inputSchema.d.ts +268 -2
  17. package/dist/inputSchema.d.ts.map +1 -1
  18. package/dist/inputSchema.js +53 -1
  19. package/dist/renderPptx/nodes/box.d.ts +1 -0
  20. package/dist/renderPptx/nodes/box.d.ts.map +1 -0
  21. package/dist/renderPptx/nodes/box.js +2 -0
  22. package/dist/renderPptx/nodes/chart.d.ts +8 -0
  23. package/dist/renderPptx/nodes/chart.d.ts.map +1 -0
  24. package/dist/renderPptx/nodes/chart.js +23 -0
  25. package/dist/renderPptx/nodes/flow.d.ts +8 -0
  26. package/dist/renderPptx/nodes/flow.d.ts.map +1 -0
  27. package/dist/renderPptx/nodes/flow.js +208 -0
  28. package/dist/renderPptx/nodes/image.d.ts +8 -0
  29. package/dist/renderPptx/nodes/image.d.ts.map +1 -0
  30. package/dist/renderPptx/nodes/image.js +17 -0
  31. package/dist/renderPptx/nodes/index.d.ts +11 -0
  32. package/dist/renderPptx/nodes/index.d.ts.map +1 -0
  33. package/dist/renderPptx/nodes/index.js +10 -0
  34. package/dist/renderPptx/nodes/matrix.d.ts +8 -0
  35. package/dist/renderPptx/nodes/matrix.d.ts.map +1 -0
  36. package/dist/renderPptx/nodes/matrix.js +150 -0
  37. package/dist/renderPptx/nodes/processArrow.d.ts +8 -0
  38. package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -0
  39. package/dist/renderPptx/nodes/processArrow.js +75 -0
  40. package/dist/renderPptx/nodes/shape.d.ts +8 -0
  41. package/dist/renderPptx/nodes/shape.d.ts.map +1 -0
  42. package/dist/renderPptx/nodes/shape.js +49 -0
  43. package/dist/renderPptx/nodes/table.d.ts +8 -0
  44. package/dist/renderPptx/nodes/table.d.ts.map +1 -0
  45. package/dist/renderPptx/nodes/table.js +29 -0
  46. package/dist/renderPptx/nodes/text.d.ts +8 -0
  47. package/dist/renderPptx/nodes/text.d.ts.map +1 -0
  48. package/dist/renderPptx/nodes/text.js +5 -0
  49. package/dist/renderPptx/nodes/timeline.d.ts +8 -0
  50. package/dist/renderPptx/nodes/timeline.d.ts.map +1 -0
  51. package/dist/renderPptx/nodes/timeline.js +157 -0
  52. package/dist/renderPptx/nodes/tree.d.ts +8 -0
  53. package/dist/renderPptx/nodes/tree.d.ts.map +1 -0
  54. package/dist/renderPptx/nodes/tree.js +223 -0
  55. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  56. package/dist/renderPptx/renderPptx.js +32 -166
  57. package/dist/renderPptx/types.d.ts +10 -0
  58. package/dist/renderPptx/types.d.ts.map +1 -0
  59. package/dist/renderPptx/utils/backgroundBorder.d.ts +8 -0
  60. package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -0
  61. package/dist/renderPptx/utils/backgroundBorder.js +44 -0
  62. package/dist/renderPptx/utils/index.d.ts +6 -0
  63. package/dist/renderPptx/utils/index.d.ts.map +1 -0
  64. package/dist/renderPptx/utils/index.js +3 -0
  65. package/dist/renderPptx/utils/shapeDrawing.d.ts +27 -0
  66. package/dist/renderPptx/utils/shapeDrawing.d.ts.map +1 -0
  67. package/dist/renderPptx/utils/shapeDrawing.js +36 -0
  68. package/dist/renderPptx/utils/textDrawing.d.ts +20 -0
  69. package/dist/renderPptx/utils/textDrawing.d.ts.map +1 -0
  70. package/dist/renderPptx/utils/textDrawing.js +20 -0
  71. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  72. package/dist/toPositioned/toPositioned.js +45 -0
  73. package/dist/types.d.ts +399 -2
  74. package/dist/types.d.ts.map +1 -1
  75. package/dist/types.js +134 -0
  76. package/package.json +13 -3
  77. package/dist/parsePptx/convertChart.d.ts +0 -8
  78. package/dist/parsePptx/convertChart.d.ts.map +0 -1
  79. package/dist/parsePptx/convertChart.js +0 -78
  80. package/dist/parsePptx/convertImage.d.ts +0 -8
  81. package/dist/parsePptx/convertImage.d.ts.map +0 -1
  82. package/dist/parsePptx/convertImage.js +0 -13
  83. package/dist/parsePptx/convertShape.d.ts +0 -7
  84. package/dist/parsePptx/convertShape.d.ts.map +0 -1
  85. package/dist/parsePptx/convertShape.js +0 -137
  86. package/dist/parsePptx/convertTable.d.ts +0 -7
  87. package/dist/parsePptx/convertTable.d.ts.map +0 -1
  88. package/dist/parsePptx/convertTable.js +0 -46
  89. package/dist/parsePptx/convertText.d.ts +0 -7
  90. package/dist/parsePptx/convertText.d.ts.map +0 -1
  91. package/dist/parsePptx/convertText.js +0 -32
  92. package/dist/parsePptx/index.d.ts +0 -23
  93. package/dist/parsePptx/index.d.ts.map +0 -1
  94. package/dist/parsePptx/index.js +0 -114
  95. package/dist/parsePptx/parseHtml.d.ts +0 -22
  96. package/dist/parsePptx/parseHtml.d.ts.map +0 -1
  97. package/dist/parsePptx/parseHtml.js +0 -53
  98. package/dist/parsePptx/types.d.ts +0 -15
  99. package/dist/parsePptx/types.d.ts.map +0 -1
  100. package/dist/parsePptx/units.d.ts +0 -13
  101. package/dist/parsePptx/units.d.ts.map +0 -1
  102. package/dist/parsePptx/units.js +0 -19
  103. /package/dist/{parsePptx → renderPptx}/types.js +0 -0
@@ -0,0 +1,23 @@
1
+ import { pxToIn } from "../units";
2
+ export function renderChartNode(node, ctx) {
3
+ const chartData = node.data.map((d) => ({
4
+ name: d.name,
5
+ labels: d.labels,
6
+ values: d.values,
7
+ }));
8
+ const chartOptions = {
9
+ x: pxToIn(node.x),
10
+ y: pxToIn(node.y),
11
+ w: pxToIn(node.w),
12
+ h: pxToIn(node.h),
13
+ showLegend: node.showLegend ?? false,
14
+ showTitle: node.showTitle ?? false,
15
+ title: node.title,
16
+ chartColors: node.chartColors,
17
+ };
18
+ // radar専用オプション
19
+ if (node.chartType === "radar" && node.radarStyle) {
20
+ chartOptions.radarStyle = node.radarStyle;
21
+ }
22
+ ctx.slide.addChart(node.chartType, chartData, chartOptions);
23
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type FlowPositionedNode = Extract<PositionedNode, {
4
+ type: "flow";
5
+ }>;
6
+ export declare function renderFlowNode(node: FlowPositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/flow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,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,CA0GN"}
@@ -0,0 +1,208 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderFlowNode(node, ctx) {
3
+ const direction = node.direction ?? "horizontal";
4
+ const nodeWidth = node.nodeWidth ?? 120;
5
+ const nodeHeight = node.nodeHeight ?? 60;
6
+ const nodeGap = node.nodeGap ?? 80;
7
+ const connectorStyle = node.connectorStyle ?? {};
8
+ const defaultColor = "1D4ED8";
9
+ const layouts = new Map();
10
+ const nodeCount = node.nodes.length;
11
+ // ノードのレイアウトを計算
12
+ if (direction === "horizontal") {
13
+ calculateHorizontalLayout(node, layouts, nodeCount, nodeWidth, nodeHeight, nodeGap);
14
+ }
15
+ else {
16
+ calculateVerticalLayout(node, layouts, nodeCount, nodeWidth, nodeHeight, nodeGap);
17
+ }
18
+ // 接続線を描画(ノードより先に描画して背面に配置)
19
+ for (const conn of node.connections) {
20
+ const fromLayout = layouts.get(conn.from);
21
+ const toLayout = layouts.get(conn.to);
22
+ if (!fromLayout || !toLayout)
23
+ continue;
24
+ const lineColor = conn.color ?? connectorStyle.color ?? "333333";
25
+ const lineWidth = connectorStyle.width ?? 2;
26
+ const arrowType = connectorStyle.arrowType ?? "triangle";
27
+ drawConnection(ctx, direction, fromLayout, toLayout, lineColor, lineWidth, arrowType);
28
+ // ラベルを描画
29
+ if (conn.label) {
30
+ const labelX = (fromLayout.x +
31
+ fromLayout.width / 2 +
32
+ toLayout.x +
33
+ toLayout.width / 2) /
34
+ 2;
35
+ const labelY = (fromLayout.y +
36
+ fromLayout.height / 2 +
37
+ toLayout.y +
38
+ toLayout.height / 2) /
39
+ 2;
40
+ ctx.slide.addText(conn.label, {
41
+ x: pxToIn(labelX - 30),
42
+ y: pxToIn(labelY - 10),
43
+ w: pxToIn(60),
44
+ h: pxToIn(20),
45
+ fontSize: pxToPt(10),
46
+ fontFace: "Noto Sans JP",
47
+ color: "64748B",
48
+ align: "center",
49
+ valign: "middle",
50
+ });
51
+ }
52
+ }
53
+ // ノードを描画
54
+ for (const item of node.nodes) {
55
+ const layout = layouts.get(item.id);
56
+ if (!layout)
57
+ continue;
58
+ const fillColor = item.color ?? defaultColor;
59
+ const textColor = item.textColor ?? "FFFFFF";
60
+ // 図形を描画
61
+ ctx.slide.addText(item.text, {
62
+ x: pxToIn(layout.x),
63
+ y: pxToIn(layout.y),
64
+ w: pxToIn(layout.width),
65
+ h: pxToIn(layout.height),
66
+ shape: item.shape,
67
+ fill: { color: fillColor },
68
+ line: { color: "333333", width: pxToPt(1) },
69
+ fontSize: pxToPt(14),
70
+ fontFace: "Noto Sans JP",
71
+ color: textColor,
72
+ align: "center",
73
+ valign: "middle",
74
+ });
75
+ }
76
+ }
77
+ function calculateHorizontalLayout(node, layouts, nodeCount, nodeWidth, nodeHeight, nodeGap) {
78
+ const totalWidth = nodeCount * nodeWidth + (nodeCount - 1) * nodeGap;
79
+ const startX = node.x + (node.w - totalWidth) / 2;
80
+ const centerY = node.y + node.h / 2;
81
+ node.nodes.forEach((item, index) => {
82
+ const w = item.width ?? nodeWidth;
83
+ const h = item.height ?? nodeHeight;
84
+ layouts.set(item.id, {
85
+ id: item.id,
86
+ x: startX + index * (nodeWidth + nodeGap) + (nodeWidth - w) / 2,
87
+ y: centerY - h / 2,
88
+ width: w,
89
+ height: h,
90
+ item,
91
+ });
92
+ });
93
+ }
94
+ function calculateVerticalLayout(node, layouts, nodeCount, nodeWidth, nodeHeight, nodeGap) {
95
+ const totalHeight = nodeCount * nodeHeight + (nodeCount - 1) * nodeGap;
96
+ const startY = node.y + (node.h - totalHeight) / 2;
97
+ const centerX = node.x + node.w / 2;
98
+ node.nodes.forEach((item, index) => {
99
+ const w = item.width ?? nodeWidth;
100
+ const h = item.height ?? nodeHeight;
101
+ layouts.set(item.id, {
102
+ id: item.id,
103
+ x: centerX - w / 2,
104
+ y: startY + index * (nodeHeight + nodeGap) + (nodeHeight - h) / 2,
105
+ width: w,
106
+ height: h,
107
+ item,
108
+ });
109
+ });
110
+ }
111
+ function drawConnection(ctx, direction, fromLayout, toLayout, lineColor, lineWidth, arrowType) {
112
+ let startX, startY, endX, endY;
113
+ if (direction === "horizontal") {
114
+ // 水平: 右端から左端へ
115
+ startX = fromLayout.x + fromLayout.width;
116
+ startY = fromLayout.y + fromLayout.height / 2;
117
+ endX = toLayout.x;
118
+ endY = toLayout.y + toLayout.height / 2;
119
+ }
120
+ else {
121
+ // 垂直: 下端から上端へ
122
+ startX = fromLayout.x + fromLayout.width / 2;
123
+ startY = fromLayout.y + fromLayout.height;
124
+ endX = toLayout.x + toLayout.width / 2;
125
+ endY = toLayout.y;
126
+ }
127
+ // 直線接続(シンプルなケース)
128
+ const isHorizontalLine = Math.abs(startY - endY) < 1;
129
+ const isVerticalLine = Math.abs(startX - endX) < 1;
130
+ if (isHorizontalLine || isVerticalLine) {
131
+ // 直線で描画
132
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
133
+ x: pxToIn(Math.min(startX, endX)),
134
+ y: pxToIn(Math.min(startY, endY)),
135
+ w: pxToIn(Math.abs(endX - startX)),
136
+ h: pxToIn(Math.abs(endY - startY)),
137
+ line: {
138
+ color: lineColor,
139
+ width: pxToPt(lineWidth),
140
+ endArrowType: arrowType,
141
+ },
142
+ });
143
+ }
144
+ else {
145
+ // L字型接続
146
+ drawLShapedConnection(ctx, direction, startX, startY, endX, endY, lineColor, lineWidth, arrowType);
147
+ }
148
+ }
149
+ function drawLShapedConnection(ctx, direction, startX, startY, endX, endY, lineColor, lineWidth, arrowType) {
150
+ const midX = (startX + endX) / 2;
151
+ const midY = (startY + endY) / 2;
152
+ if (direction === "horizontal") {
153
+ // 水平→垂直→水平
154
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
155
+ x: pxToIn(startX),
156
+ y: pxToIn(startY),
157
+ w: pxToIn(midX - startX),
158
+ h: 0,
159
+ line: { color: lineColor, width: pxToPt(lineWidth) },
160
+ });
161
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
162
+ x: pxToIn(midX),
163
+ y: pxToIn(Math.min(startY, endY)),
164
+ w: 0,
165
+ h: pxToIn(Math.abs(endY - startY)),
166
+ line: { color: lineColor, width: pxToPt(lineWidth) },
167
+ });
168
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
169
+ x: pxToIn(midX),
170
+ y: pxToIn(endY),
171
+ w: pxToIn(endX - midX),
172
+ h: 0,
173
+ line: {
174
+ color: lineColor,
175
+ width: pxToPt(lineWidth),
176
+ endArrowType: arrowType,
177
+ },
178
+ });
179
+ }
180
+ else {
181
+ // 垂直→水平→垂直
182
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
183
+ x: pxToIn(startX),
184
+ y: pxToIn(startY),
185
+ w: 0,
186
+ h: pxToIn(midY - startY),
187
+ line: { color: lineColor, width: pxToPt(lineWidth) },
188
+ });
189
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
190
+ x: pxToIn(Math.min(startX, endX)),
191
+ y: pxToIn(midY),
192
+ w: pxToIn(Math.abs(endX - startX)),
193
+ h: 0,
194
+ line: { color: lineColor, width: pxToPt(lineWidth) },
195
+ });
196
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
197
+ x: pxToIn(endX),
198
+ y: pxToIn(midY),
199
+ w: 0,
200
+ h: pxToIn(endY - midY),
201
+ line: {
202
+ color: lineColor,
203
+ width: pxToPt(lineWidth),
204
+ endArrowType: arrowType,
205
+ },
206
+ });
207
+ }
208
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type ImagePositionedNode = Extract<PositionedNode, {
4
+ type: "image";
5
+ }>;
6
+ export declare function renderImageNode(node: ImagePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/image.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,aAAa,GACjB,IAAI,CAeN"}
@@ -0,0 +1,17 @@
1
+ import { pxToIn } from "../units";
2
+ export function renderImageNode(node, ctx) {
3
+ const imageOptions = {
4
+ x: pxToIn(node.x),
5
+ y: pxToIn(node.y),
6
+ w: pxToIn(node.w),
7
+ h: pxToIn(node.h),
8
+ };
9
+ if (node.imageData) {
10
+ // Base64 データがある場合は data プロパティを使用(リモート画像)
11
+ ctx.slide.addImage({ ...imageOptions, data: node.imageData });
12
+ }
13
+ else {
14
+ // ローカルパスの場合は path プロパティを使用
15
+ ctx.slide.addImage({ ...imageOptions, path: node.src });
16
+ }
17
+ }
@@ -0,0 +1,11 @@
1
+ export { renderTextNode } from "./text";
2
+ export { renderImageNode } from "./image";
3
+ export { renderTableNode } from "./table";
4
+ export { renderShapeNode } from "./shape";
5
+ export { renderChartNode } from "./chart";
6
+ export { renderTimelineNode } from "./timeline";
7
+ export { renderMatrixNode } from "./matrix";
8
+ export { renderTreeNode } from "./tree";
9
+ export { renderFlowNode } from "./flow";
10
+ export { renderProcessArrowNode } from "./processArrow";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { renderTextNode } from "./text";
2
+ export { renderImageNode } from "./image";
3
+ export { renderTableNode } from "./table";
4
+ export { renderShapeNode } from "./shape";
5
+ export { renderChartNode } from "./chart";
6
+ export { renderTimelineNode } from "./timeline";
7
+ export { renderMatrixNode } from "./matrix";
8
+ export { renderTreeNode } from "./tree";
9
+ export { renderFlowNode } from "./flow";
10
+ export { renderProcessArrowNode } from "./processArrow";
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type MatrixPositionedNode = Extract<PositionedNode, {
4
+ type: "matrix";
5
+ }>;
6
+ export declare function renderMatrixNode(node: MatrixPositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=matrix.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/matrix.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,oBAAoB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AAExE,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,oBAAoB,EAC1B,GAAG,EAAE,aAAa,GACjB,IAAI,CAkHN"}
@@ -0,0 +1,150 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderMatrixNode(node, ctx) {
3
+ const items = node.items;
4
+ const axes = node.axes;
5
+ const quadrants = node.quadrants;
6
+ const defaultItemColor = "1D4ED8"; // blue
7
+ const itemSize = 24; // px
8
+ const lineWidth = 2; // px
9
+ const axisColor = "E2E8F0";
10
+ // マトリクスの描画領域(パディングを考慮)
11
+ const padding = 60; // 軸ラベル用の余白
12
+ const areaX = node.x + padding;
13
+ const areaY = node.y + padding;
14
+ const areaW = node.w - padding * 2;
15
+ const areaH = node.h - padding * 2;
16
+ // 中心座標
17
+ const centerX = areaX + areaW / 2;
18
+ const centerY = areaY + areaH / 2;
19
+ // === 1. 十字線(軸線)を描画 ===
20
+ // 横線(X軸)
21
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
22
+ x: pxToIn(areaX),
23
+ y: pxToIn(centerY),
24
+ w: pxToIn(areaW),
25
+ h: 0,
26
+ line: { color: axisColor, width: pxToPt(lineWidth) },
27
+ });
28
+ // 縦線(Y軸)
29
+ ctx.slide.addShape(ctx.pptx.ShapeType.line, {
30
+ x: pxToIn(centerX),
31
+ y: pxToIn(areaY),
32
+ w: 0,
33
+ h: pxToIn(areaH),
34
+ line: { color: axisColor, width: pxToPt(lineWidth) },
35
+ });
36
+ // === 2. 軸ラベルを描画 ===
37
+ // X軸ラベル(下部中央)
38
+ ctx.slide.addText(axes.x, {
39
+ x: pxToIn(centerX - 60),
40
+ y: pxToIn(areaY + areaH + 8),
41
+ w: pxToIn(120),
42
+ h: pxToIn(24),
43
+ fontSize: pxToPt(12),
44
+ fontFace: "Noto Sans JP",
45
+ color: "64748B",
46
+ align: "center",
47
+ valign: "top",
48
+ });
49
+ // Y軸ラベル(左部中央)
50
+ ctx.slide.addText(axes.y, {
51
+ x: pxToIn(node.x + 4),
52
+ y: pxToIn(centerY - 12),
53
+ w: pxToIn(48),
54
+ h: pxToIn(24),
55
+ fontSize: pxToPt(12),
56
+ fontFace: "Noto Sans JP",
57
+ color: "64748B",
58
+ align: "center",
59
+ valign: "middle",
60
+ });
61
+ // === 3. 象限ラベルを描画 ===
62
+ if (quadrants) {
63
+ renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY);
64
+ }
65
+ // === 4. アイテムをプロット ===
66
+ for (const item of items) {
67
+ // 座標変換: (0,0)=左下, (1,1)=右上
68
+ // x: 0 -> areaX, 1 -> areaX + areaW
69
+ // y: 0 -> areaY + areaH, 1 -> areaY (反転)
70
+ const itemX = areaX + item.x * areaW;
71
+ const itemY = areaY + (1 - item.y) * areaH; // Y軸反転
72
+ const itemColor = item.color ?? defaultItemColor;
73
+ // 円を描画
74
+ ctx.slide.addShape(ctx.pptx.ShapeType.ellipse, {
75
+ x: pxToIn(itemX - itemSize / 2),
76
+ y: pxToIn(itemY - itemSize / 2),
77
+ w: pxToIn(itemSize),
78
+ h: pxToIn(itemSize),
79
+ fill: { color: itemColor },
80
+ line: { type: "none" },
81
+ });
82
+ // ラベルを描画(円の上)
83
+ ctx.slide.addText(item.label, {
84
+ x: pxToIn(itemX - 50),
85
+ y: pxToIn(itemY - itemSize / 2 - 20),
86
+ w: pxToIn(100),
87
+ h: pxToIn(18),
88
+ fontSize: pxToPt(11),
89
+ fontFace: "Noto Sans JP",
90
+ color: "1E293B",
91
+ bold: true,
92
+ align: "center",
93
+ valign: "bottom",
94
+ });
95
+ }
96
+ }
97
+ function renderQuadrantLabels(ctx, quadrants, areaX, areaY, areaW, areaH, centerX, centerY) {
98
+ const quadrantFontSize = 11;
99
+ const quadrantColor = "94A3B8"; // slate-400
100
+ const quadrantW = areaW / 2 - 20;
101
+ const quadrantH = 48;
102
+ // 左上
103
+ ctx.slide.addText(quadrants.topLeft, {
104
+ x: pxToIn(areaX + 10),
105
+ y: pxToIn(areaY + 10),
106
+ w: pxToIn(quadrantW),
107
+ h: pxToIn(quadrantH),
108
+ fontSize: pxToPt(quadrantFontSize),
109
+ fontFace: "Noto Sans JP",
110
+ color: quadrantColor,
111
+ align: "left",
112
+ valign: "top",
113
+ });
114
+ // 右上
115
+ ctx.slide.addText(quadrants.topRight, {
116
+ x: pxToIn(centerX + 10),
117
+ y: pxToIn(areaY + 10),
118
+ w: pxToIn(quadrantW),
119
+ h: pxToIn(quadrantH),
120
+ fontSize: pxToPt(quadrantFontSize),
121
+ fontFace: "Noto Sans JP",
122
+ color: quadrantColor,
123
+ align: "right",
124
+ valign: "top",
125
+ });
126
+ // 左下
127
+ ctx.slide.addText(quadrants.bottomLeft, {
128
+ x: pxToIn(areaX + 10),
129
+ y: pxToIn(centerY + areaH / 2 - quadrantH - 10),
130
+ w: pxToIn(quadrantW),
131
+ h: pxToIn(quadrantH),
132
+ fontSize: pxToPt(quadrantFontSize),
133
+ fontFace: "Noto Sans JP",
134
+ color: quadrantColor,
135
+ align: "left",
136
+ valign: "bottom",
137
+ });
138
+ // 右下
139
+ ctx.slide.addText(quadrants.bottomRight, {
140
+ x: pxToIn(centerX + 10),
141
+ y: pxToIn(centerY + areaH / 2 - quadrantH - 10),
142
+ w: pxToIn(quadrantW),
143
+ h: pxToIn(quadrantH),
144
+ fontSize: pxToPt(quadrantFontSize),
145
+ fontFace: "Noto Sans JP",
146
+ color: quadrantColor,
147
+ align: "right",
148
+ valign: "bottom",
149
+ });
150
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type ProcessArrowPositionedNode = Extract<PositionedNode, {
4
+ type: "processArrow";
5
+ }>;
6
+ export declare function renderProcessArrowNode(node: ProcessArrowPositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=processArrow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processArrow.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/processArrow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,0BAA0B,GAAG,OAAO,CACvC,cAAc,EACd;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CACzB,CAAC;AAEF,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,0BAA0B,EAChC,GAAG,EAAE,aAAa,GACjB,IAAI,CAsCN"}
@@ -0,0 +1,75 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderProcessArrowNode(node, ctx) {
3
+ const direction = node.direction ?? "horizontal";
4
+ const steps = node.steps;
5
+ const stepCount = steps.length;
6
+ if (stepCount === 0)
7
+ return;
8
+ const defaultColor = "4472C4"; // PowerPoint標準の青
9
+ const defaultTextColor = "FFFFFF";
10
+ const itemWidth = node.itemWidth ?? 150;
11
+ const itemHeight = node.itemHeight ?? 60;
12
+ const gap = node.gap ?? -15; // 負の値でシェブロンを重ねる
13
+ if (direction === "horizontal") {
14
+ renderHorizontalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor);
15
+ }
16
+ else {
17
+ renderVerticalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor);
18
+ }
19
+ }
20
+ function renderHorizontalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor) {
21
+ const totalWidth = stepCount * itemWidth + (stepCount - 1) * gap;
22
+ const startX = node.x + (node.w - totalWidth) / 2;
23
+ const centerY = node.y + node.h / 2;
24
+ steps.forEach((step, index) => {
25
+ const stepX = startX + index * (itemWidth + gap);
26
+ const stepY = centerY - itemHeight / 2;
27
+ const fillColor = step.color?.replace("#", "") ?? defaultColor;
28
+ const textColor = step.textColor?.replace("#", "") ?? defaultTextColor;
29
+ // 最初のステップは homePlate、以降は chevron
30
+ const shapeType = index === 0 ? ctx.pptx.ShapeType.homePlate : ctx.pptx.ShapeType.chevron;
31
+ ctx.slide.addText(step.label, {
32
+ x: pxToIn(stepX),
33
+ y: pxToIn(stepY),
34
+ w: pxToIn(itemWidth),
35
+ h: pxToIn(itemHeight),
36
+ shape: shapeType,
37
+ fill: { color: fillColor },
38
+ line: { type: "none" },
39
+ fontSize: pxToPt(node.fontPx ?? 14),
40
+ fontFace: "Noto Sans JP",
41
+ color: textColor,
42
+ bold: node.bold ?? false,
43
+ align: "center",
44
+ valign: "middle",
45
+ });
46
+ });
47
+ }
48
+ function renderVerticalProcessArrow(node, ctx, steps, stepCount, itemWidth, itemHeight, gap, defaultColor, defaultTextColor) {
49
+ const totalHeight = stepCount * itemHeight + (stepCount - 1) * gap;
50
+ const startY = node.y + (node.h - totalHeight) / 2;
51
+ const centerX = node.x + node.w / 2;
52
+ steps.forEach((step, index) => {
53
+ const stepX = centerX - itemWidth / 2;
54
+ const stepY = startY + index * (itemHeight + gap);
55
+ const fillColor = step.color?.replace("#", "") ?? defaultColor;
56
+ const textColor = step.textColor?.replace("#", "") ?? defaultTextColor;
57
+ // 垂直方向では pentagon を使用(下向き矢印風)
58
+ const shapeType = index === 0 ? ctx.pptx.ShapeType.rect : ctx.pptx.ShapeType.pentagon;
59
+ ctx.slide.addText(step.label, {
60
+ x: pxToIn(stepX),
61
+ y: pxToIn(stepY),
62
+ w: pxToIn(itemWidth),
63
+ h: pxToIn(itemHeight),
64
+ shape: shapeType,
65
+ fill: { color: fillColor },
66
+ line: { type: "none" },
67
+ fontSize: pxToPt(node.fontPx ?? 14),
68
+ fontFace: "Noto Sans JP",
69
+ color: textColor,
70
+ bold: node.bold ?? false,
71
+ align: "center",
72
+ valign: "middle",
73
+ });
74
+ });
75
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type ShapePositionedNode = Extract<PositionedNode, {
4
+ type: "shape";
5
+ }>;
6
+ export declare function renderShapeNode(node: ShapePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/shape.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,aAAa,GACjB,IAAI,CAgDN"}
@@ -0,0 +1,49 @@
1
+ import { pxToIn, pxToPt } from "../units";
2
+ export function renderShapeNode(node, ctx) {
3
+ const shapeOptions = {
4
+ x: pxToIn(node.x),
5
+ y: pxToIn(node.y),
6
+ w: pxToIn(node.w),
7
+ h: pxToIn(node.h),
8
+ fill: node.fill
9
+ ? {
10
+ color: node.fill.color,
11
+ transparency: node.fill.transparency,
12
+ }
13
+ : undefined,
14
+ line: node.line
15
+ ? {
16
+ color: node.line.color,
17
+ width: node.line.width !== undefined ? pxToPt(node.line.width) : undefined,
18
+ dashType: node.line.dashType,
19
+ }
20
+ : undefined,
21
+ shadow: node.shadow
22
+ ? {
23
+ type: node.shadow.type,
24
+ opacity: node.shadow.opacity,
25
+ blur: node.shadow.blur,
26
+ angle: node.shadow.angle,
27
+ offset: node.shadow.offset,
28
+ color: node.shadow.color,
29
+ }
30
+ : undefined,
31
+ };
32
+ if (node.text) {
33
+ // テキストがある場合:addTextでshapeを指定
34
+ ctx.slide.addText(node.text, {
35
+ ...shapeOptions,
36
+ shape: node.shapeType,
37
+ fontSize: pxToPt(node.fontPx ?? 24),
38
+ fontFace: "Noto Sans JP",
39
+ color: node.color,
40
+ align: node.alignText ?? "center",
41
+ valign: "middle",
42
+ lineSpacingMultiple: 1.3,
43
+ });
44
+ }
45
+ else {
46
+ // テキストがない場合:addShapeを使用
47
+ ctx.slide.addShape(node.shapeType, shapeOptions);
48
+ }
49
+ }
@@ -0,0 +1,8 @@
1
+ import type { PositionedNode } from "../../types";
2
+ import type { RenderContext } from "../types";
3
+ type TablePositionedNode = Extract<PositionedNode, {
4
+ type: "table";
5
+ }>;
6
+ export declare function renderTableNode(node: TablePositionedNode, ctx: RenderContext): void;
7
+ export {};
8
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/nodes/table.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI9C,KAAK,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAEtE,wBAAgB,eAAe,CAC7B,IAAI,EAAE,mBAAmB,EACzB,GAAG,EAAE,aAAa,GACjB,IAAI,CA+BN"}
@@ -0,0 +1,29 @@
1
+ import { resolveColumnWidths, resolveRowHeights } from "../../table/utils";
2
+ import { pxToIn, pxToPt } from "../units";
3
+ export function renderTableNode(node, ctx) {
4
+ const tableRows = node.rows.map((row) => row.cells.map((cell) => {
5
+ const cellOptions = {
6
+ fontSize: pxToPt(cell.fontPx ?? 18),
7
+ color: cell.color,
8
+ bold: cell.bold,
9
+ align: cell.alignText ?? "left",
10
+ fill: cell.backgroundColor
11
+ ? { color: cell.backgroundColor }
12
+ : undefined,
13
+ };
14
+ return {
15
+ text: cell.text,
16
+ options: cellOptions,
17
+ };
18
+ }));
19
+ const tableOptions = {
20
+ x: pxToIn(node.x),
21
+ y: pxToIn(node.y),
22
+ w: pxToIn(node.w),
23
+ h: pxToIn(node.h),
24
+ colW: resolveColumnWidths(node, node.w).map((width) => pxToIn(width)),
25
+ rowH: resolveRowHeights(node).map((height) => pxToIn(height)),
26
+ margin: 0,
27
+ };
28
+ ctx.slide.addTable(tableRows, tableOptions);
29
+ }