@hirokisakabe/pom 5.2.0 → 5.2.1

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 (104) hide show
  1. package/README.md +10 -11
  2. package/dist/autoFit/autoFit.d.ts +2 -1
  3. package/dist/autoFit/autoFit.d.ts.map +1 -1
  4. package/dist/autoFit/autoFit.js +7 -7
  5. package/dist/autoFit/strategies/reduceFontSize.js +1 -1
  6. package/dist/autoFit/strategies/reduceGapAndPadding.js +1 -1
  7. package/dist/autoFit/strategies/reduceTableRowHeight.js +1 -1
  8. package/dist/autoFit/strategies/uniformScale.js +1 -1
  9. package/dist/buildContext.d.ts +12 -0
  10. package/dist/buildContext.d.ts.map +1 -0
  11. package/dist/buildContext.js +8 -0
  12. package/dist/buildPptx.d.ts +1 -1
  13. package/dist/buildPptx.d.ts.map +1 -1
  14. package/dist/buildPptx.js +15 -15
  15. package/dist/calcYogaLayout/calcYogaLayout.d.ts +3 -1
  16. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  17. package/dist/calcYogaLayout/calcYogaLayout.js +43 -371
  18. package/dist/calcYogaLayout/measureText.d.ts +1 -5
  19. package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
  20. package/dist/calcYogaLayout/measureText.js +2 -10
  21. package/dist/icons/renderIcon.d.ts +1 -1
  22. package/dist/icons/renderIcon.d.ts.map +1 -1
  23. package/dist/icons/renderIcon.js +3 -4
  24. package/dist/parseXml/coercionRules.d.ts +35 -0
  25. package/dist/parseXml/coercionRules.d.ts.map +1 -0
  26. package/dist/parseXml/coercionRules.js +477 -0
  27. package/dist/parseXml/inputSchema.d.ts +15 -105
  28. package/dist/parseXml/inputSchema.d.ts.map +1 -1
  29. package/dist/parseXml/inputSchema.js +2 -2
  30. package/dist/parseXml/parseXml.d.ts.map +1 -1
  31. package/dist/parseXml/parseXml.js +40 -272
  32. package/dist/registry/definitions/box.d.ts +3 -0
  33. package/dist/registry/definitions/box.d.ts.map +1 -0
  34. package/dist/registry/definitions/box.js +6 -0
  35. package/dist/registry/definitions/chart.d.ts +3 -0
  36. package/dist/registry/definitions/chart.d.ts.map +1 -0
  37. package/dist/registry/definitions/chart.js +8 -0
  38. package/dist/registry/definitions/compositeNodes.d.ts +8 -0
  39. package/dist/registry/definitions/compositeNodes.d.ts.map +1 -0
  40. package/dist/registry/definitions/compositeNodes.js +81 -0
  41. package/dist/registry/definitions/icon.d.ts +3 -0
  42. package/dist/registry/definitions/icon.d.ts.map +1 -0
  43. package/dist/registry/definitions/icon.js +28 -0
  44. package/dist/registry/definitions/image.d.ts +3 -0
  45. package/dist/registry/definitions/image.d.ts.map +1 -0
  46. package/dist/registry/definitions/image.js +34 -0
  47. package/dist/registry/definitions/layer.d.ts +3 -0
  48. package/dist/registry/definitions/layer.d.ts.map +1 -0
  49. package/dist/registry/definitions/layer.js +49 -0
  50. package/dist/registry/definitions/line.d.ts +3 -0
  51. package/dist/registry/definitions/line.d.ts.map +1 -0
  52. package/dist/registry/definitions/line.js +26 -0
  53. package/dist/registry/definitions/list.d.ts +4 -0
  54. package/dist/registry/definitions/list.d.ts.map +1 -0
  55. package/dist/registry/definitions/list.js +53 -0
  56. package/dist/registry/definitions/shape.d.ts +3 -0
  57. package/dist/registry/definitions/shape.d.ts.map +1 -0
  58. package/dist/registry/definitions/shape.js +37 -0
  59. package/dist/registry/definitions/stack.d.ts +4 -0
  60. package/dist/registry/definitions/stack.d.ts.map +1 -0
  61. package/dist/registry/definitions/stack.js +78 -0
  62. package/dist/registry/definitions/table.d.ts +3 -0
  63. package/dist/registry/definitions/table.d.ts.map +1 -0
  64. package/dist/registry/definitions/table.js +16 -0
  65. package/dist/registry/definitions/text.d.ts +3 -0
  66. package/dist/registry/definitions/text.d.ts.map +1 -0
  67. package/dist/registry/definitions/text.js +35 -0
  68. package/dist/registry/index.d.ts +2 -0
  69. package/dist/registry/index.d.ts.map +1 -0
  70. package/dist/registry/index.js +34 -0
  71. package/dist/registry/nodeRegistry.d.ts +7 -0
  72. package/dist/registry/nodeRegistry.d.ts.map +1 -0
  73. package/dist/registry/nodeRegistry.js +13 -0
  74. package/dist/registry/types.d.ts +26 -0
  75. package/dist/registry/types.d.ts.map +1 -0
  76. package/dist/registry/types.js +1 -0
  77. package/dist/renderPptx/renderPptx.d.ts +2 -1
  78. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  79. package/dist/renderPptx/renderPptx.js +19 -60
  80. package/dist/renderPptx/types.d.ts +2 -0
  81. package/dist/renderPptx/types.d.ts.map +1 -1
  82. package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -1
  83. package/dist/renderPptx/utils/backgroundBorder.js +1 -1
  84. package/dist/shared/freeYogaTree.d.ts.map +1 -0
  85. package/dist/shared/measureImage.d.ts +13 -3
  86. package/dist/shared/measureImage.d.ts.map +1 -1
  87. package/dist/shared/measureImage.js +14 -19
  88. package/dist/shared/walkTree.d.ts.map +1 -0
  89. package/dist/toPositioned/toPositioned.d.ts +8 -1
  90. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  91. package/dist/toPositioned/toPositioned.js +32 -189
  92. package/dist/types.d.ts +17 -54
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js +1 -1
  95. package/package.json +3 -3
  96. package/dist/autoFit/freeYogaTree.d.ts.map +0 -1
  97. package/dist/autoFit/walkTree.d.ts.map +0 -1
  98. package/dist/renderPptx/nodes/index.d.ts +0 -15
  99. package/dist/renderPptx/nodes/index.d.ts.map +0 -1
  100. package/dist/renderPptx/nodes/index.js +0 -14
  101. /package/dist/{autoFit → shared}/freeYogaTree.d.ts +0 -0
  102. /package/dist/{autoFit → shared}/freeYogaTree.js +0 -0
  103. /package/dist/{autoFit → shared}/walkTree.d.ts +0 -0
  104. /package/dist/{autoFit → shared}/walkTree.js +0 -0
@@ -0,0 +1,49 @@
1
+ import { toPositioned, omitYogaNode } from "../../toPositioned/toPositioned.js";
2
+ export const layerNodeDef = {
3
+ type: "layer",
4
+ category: "absolute-child",
5
+ // applyYogaStyle: layer は子を絶対配置するコンテナ。サイズは明示的に指定されることを期待
6
+ toPositioned(pom, absoluteX, absoluteY, layout, ctx) {
7
+ const n = pom;
8
+ // layer の子要素は layer 内の相対座標(child.x, child.y)を持つ
9
+ // layer の絶対座標に加算してスライド上の絶対座標に変換
10
+ return {
11
+ ...omitYogaNode(n),
12
+ x: absoluteX,
13
+ y: absoluteY,
14
+ w: layout.width,
15
+ h: layout.height,
16
+ children: n.children.map((child) => {
17
+ const childX = child.x ?? 0;
18
+ const childY = child.y ?? 0;
19
+ // line ノードは特別な処理が必要
20
+ // x1, y1, x2, y2 は layer 内の相対座標として扱い、layer の座標を加算
21
+ if (child.type === "line") {
22
+ const lineAbsoluteX = absoluteX + childX;
23
+ const lineAbsoluteY = absoluteY + childY;
24
+ const adjustedX1 = child.x1 + lineAbsoluteX;
25
+ const adjustedY1 = child.y1 + lineAbsoluteY;
26
+ const adjustedX2 = child.x2 + lineAbsoluteX;
27
+ const adjustedY2 = child.y2 + lineAbsoluteY;
28
+ return {
29
+ ...omitYogaNode(child),
30
+ x1: adjustedX1,
31
+ y1: adjustedY1,
32
+ x2: adjustedX2,
33
+ y2: adjustedY2,
34
+ x: Math.min(adjustedX1, adjustedX2),
35
+ y: Math.min(adjustedY1, adjustedY2),
36
+ w: Math.abs(adjustedX2 - adjustedX1),
37
+ h: Math.abs(adjustedY2 - adjustedY1),
38
+ };
39
+ }
40
+ // その他のノードは通常の処理
41
+ const childLayout = child.yogaNode.getComputedLayout();
42
+ const adjustedParentX = absoluteX + childX - childLayout.left;
43
+ const adjustedParentY = absoluteY + childY - childLayout.top;
44
+ return toPositioned(child, ctx, adjustedParentX, adjustedParentY);
45
+ }),
46
+ };
47
+ },
48
+ // render: category ベースの子要素再帰で対応
49
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const lineNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/line.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,eAAO,MAAM,WAAW,EAAE,cAuBzB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { renderLineNode } from "../../renderPptx/nodes/line.js";
2
+ import { omitYogaNode } from "../../toPositioned/toPositioned.js";
3
+ export const lineNodeDef = {
4
+ type: "line",
5
+ category: "leaf",
6
+ applyYogaStyle(_node, yn) {
7
+ // line ノードは絶対座標を使用するため、Yoga レイアウトではサイズ 0 として扱う
8
+ yn.setWidth(0);
9
+ yn.setHeight(0);
10
+ },
11
+ toPositioned(pom, _absoluteX, _absoluteY, _layout) {
12
+ const n = pom;
13
+ // line ノードは絶対座標(x1, y1, x2, y2)を持つため、
14
+ // yogaNode の座標ではなく自身の座標からバウンディングボックスを計算
15
+ return {
16
+ ...omitYogaNode(n),
17
+ x: Math.min(n.x1, n.x2),
18
+ y: Math.min(n.y1, n.y2),
19
+ w: Math.abs(n.x2 - n.x1),
20
+ h: Math.abs(n.y2 - n.y1),
21
+ };
22
+ },
23
+ render(node, ctx) {
24
+ renderLineNode(node, ctx);
25
+ },
26
+ };
@@ -0,0 +1,4 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const ulNodeDef: NodeDefinition;
3
+ export declare const olNodeDef: NodeDefinition;
4
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/list.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AA0DxD,eAAO,MAAM,SAAS,EAAE,cAOvB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,cAOvB,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { measureText } from "../../calcYogaLayout/measureText.js";
2
+ import { measureFontLineHeightRatio } from "../../calcYogaLayout/fontLoader.js";
3
+ import { renderUlNode, renderOlNode } from "../../renderPptx/nodes/list.js";
4
+ function applyListYogaStyle(node, yn, yoga, ctx) {
5
+ const n = node;
6
+ const combinedText = n.items.map((item) => item.text).join("\n");
7
+ const fontSizePx = n.fontSize ?? 24;
8
+ const fontFamily = "Noto Sans JP";
9
+ const fontWeight = n.bold ? "bold" : "normal";
10
+ const spacingMultiple = n.lineHeight ?? 1.3;
11
+ const fontMetricsRatio = measureFontLineHeightRatio(fontWeight);
12
+ const lineHeight = fontMetricsRatio * spacingMultiple;
13
+ // バレット/番号のインデント幅(pptxgenjs DEF_BULLET_MARGIN = 27pt = 36px @96dpi)
14
+ const bulletIndentPx = 36;
15
+ yn.setMeasureFunc((width, widthMode) => {
16
+ const maxWidthPx = (() => {
17
+ switch (widthMode) {
18
+ case yoga.MEASURE_MODE_UNDEFINED:
19
+ return Number.POSITIVE_INFINITY;
20
+ case yoga.MEASURE_MODE_EXACTLY:
21
+ case yoga.MEASURE_MODE_AT_MOST:
22
+ return width;
23
+ }
24
+ })();
25
+ const textMaxWidthPx = Math.max(0, maxWidthPx - bulletIndentPx);
26
+ const { widthPx, heightPx } = measureText(combinedText, textMaxWidthPx, {
27
+ fontFamily,
28
+ fontSizePx,
29
+ lineHeight,
30
+ fontWeight,
31
+ }, ctx.textMeasurementMode);
32
+ return {
33
+ width: widthPx + bulletIndentPx,
34
+ height: heightPx,
35
+ };
36
+ });
37
+ }
38
+ export const ulNodeDef = {
39
+ type: "ul",
40
+ category: "leaf",
41
+ applyYogaStyle: applyListYogaStyle,
42
+ render(node, ctx) {
43
+ renderUlNode(node, ctx);
44
+ },
45
+ };
46
+ export const olNodeDef = {
47
+ type: "ol",
48
+ category: "leaf",
49
+ applyYogaStyle: applyListYogaStyle,
50
+ render(node, ctx) {
51
+ renderOlNode(node, ctx);
52
+ },
53
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const shapeNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shape.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/shape.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAMxD,eAAO,MAAM,YAAY,EAAE,cA0C1B,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { measureText } from "../../calcYogaLayout/measureText.js";
2
+ import { renderShapeNode } from "../../renderPptx/nodes/shape.js";
3
+ export const shapeNodeDef = {
4
+ type: "shape",
5
+ category: "leaf",
6
+ applyYogaStyle(node, yn, yoga, ctx) {
7
+ const n = node;
8
+ if (n.text) {
9
+ const text = n.text;
10
+ const fontSizePx = n.fontSize ?? 24;
11
+ const fontFamily = n.fontFamily ?? "Noto Sans JP";
12
+ const fontWeight = n.bold ? "bold" : "normal";
13
+ const lineHeight = n.lineHeight ?? 1.3;
14
+ yn.setMeasureFunc((width, widthMode) => {
15
+ const maxWidthPx = (() => {
16
+ switch (widthMode) {
17
+ case yoga.MEASURE_MODE_UNDEFINED:
18
+ return Number.POSITIVE_INFINITY;
19
+ case yoga.MEASURE_MODE_EXACTLY:
20
+ case yoga.MEASURE_MODE_AT_MOST:
21
+ return width;
22
+ }
23
+ })();
24
+ const { widthPx, heightPx } = measureText(text, maxWidthPx, {
25
+ fontFamily,
26
+ fontSizePx,
27
+ lineHeight,
28
+ fontWeight,
29
+ }, ctx.textMeasurementMode);
30
+ return { width: widthPx, height: heightPx };
31
+ });
32
+ }
33
+ },
34
+ render(node, ctx) {
35
+ renderShapeNode(node, ctx);
36
+ },
37
+ };
@@ -0,0 +1,4 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const vstackNodeDef: NodeDefinition;
3
+ export declare const hstackNodeDef: NodeDefinition;
4
+ //# sourceMappingURL=stack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/stack.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAuExD,eAAO,MAAM,aAAa,EAAE,cAQ3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,cAQ3B,CAAC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * vstack/hstack 共通の Flex プロパティを適用する
3
+ */
4
+ function applyFlexProperties(node, yn, yoga) {
5
+ if (node.gap !== undefined) {
6
+ yn.setGap(yoga.GUTTER_ROW, node.gap);
7
+ yn.setGap(yoga.GUTTER_COLUMN, node.gap);
8
+ }
9
+ if (node.alignItems !== undefined) {
10
+ switch (node.alignItems) {
11
+ case "start":
12
+ yn.setAlignItems(yoga.ALIGN_FLEX_START);
13
+ break;
14
+ case "center":
15
+ yn.setAlignItems(yoga.ALIGN_CENTER);
16
+ break;
17
+ case "end":
18
+ yn.setAlignItems(yoga.ALIGN_FLEX_END);
19
+ break;
20
+ case "stretch":
21
+ yn.setAlignItems(yoga.ALIGN_STRETCH);
22
+ break;
23
+ }
24
+ }
25
+ if (node.justifyContent !== undefined) {
26
+ switch (node.justifyContent) {
27
+ case "start":
28
+ yn.setJustifyContent(yoga.JUSTIFY_FLEX_START);
29
+ break;
30
+ case "center":
31
+ yn.setJustifyContent(yoga.JUSTIFY_CENTER);
32
+ break;
33
+ case "end":
34
+ yn.setJustifyContent(yoga.JUSTIFY_FLEX_END);
35
+ break;
36
+ case "spaceBetween":
37
+ yn.setJustifyContent(yoga.JUSTIFY_SPACE_BETWEEN);
38
+ break;
39
+ case "spaceAround":
40
+ yn.setJustifyContent(yoga.JUSTIFY_SPACE_AROUND);
41
+ break;
42
+ case "spaceEvenly":
43
+ yn.setJustifyContent(yoga.JUSTIFY_SPACE_EVENLY);
44
+ break;
45
+ }
46
+ }
47
+ if (node.flexWrap !== undefined) {
48
+ switch (node.flexWrap) {
49
+ case "nowrap":
50
+ yn.setFlexWrap(yoga.WRAP_NO_WRAP);
51
+ break;
52
+ case "wrap":
53
+ yn.setFlexWrap(yoga.WRAP_WRAP);
54
+ break;
55
+ case "wrapReverse":
56
+ yn.setFlexWrap(yoga.WRAP_WRAP_REVERSE);
57
+ break;
58
+ }
59
+ }
60
+ }
61
+ export const vstackNodeDef = {
62
+ type: "vstack",
63
+ category: "multi-child",
64
+ applyYogaStyle(node, yn, yoga) {
65
+ yn.setFlexDirection(yoga.FLEX_DIRECTION_COLUMN);
66
+ applyFlexProperties(node, yn, yoga);
67
+ },
68
+ // render: category ベースの子要素再帰で対応
69
+ };
70
+ export const hstackNodeDef = {
71
+ type: "hstack",
72
+ category: "multi-child",
73
+ applyYogaStyle(node, yn, yoga) {
74
+ yn.setFlexDirection(yoga.FLEX_DIRECTION_ROW);
75
+ applyFlexProperties(node, yn, yoga);
76
+ },
77
+ // render: category ベースの子要素再帰で対応
78
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const tableNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=table.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/table.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIlD,eAAO,MAAM,YAAY,EAAE,cAa1B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { calcTableIntrinsicSize } from "../../shared/tableUtils.js";
2
+ import { renderTableNode } from "../../renderPptx/nodes/table.js";
3
+ export const tableNodeDef = {
4
+ type: "table",
5
+ category: "leaf",
6
+ applyYogaStyle(node, yn) {
7
+ const n = node;
8
+ yn.setMeasureFunc(() => {
9
+ const { width, height } = calcTableIntrinsicSize(n);
10
+ return { width, height };
11
+ });
12
+ },
13
+ render(node, ctx) {
14
+ renderTableNode(node, ctx);
15
+ },
16
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodeDefinition } from "../types.ts";
2
+ export declare const textNodeDef: NodeDefinition;
3
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/text.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAMxD,eAAO,MAAM,WAAW,EAAE,cAwCzB,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { measureText } from "../../calcYogaLayout/measureText.js";
2
+ import { renderTextNode } from "../../renderPptx/nodes/text.js";
3
+ export const textNodeDef = {
4
+ type: "text",
5
+ category: "leaf",
6
+ applyYogaStyle(node, yn, yoga, ctx) {
7
+ const n = node;
8
+ const text = n.text;
9
+ const fontSizePx = n.fontSize ?? 24;
10
+ const fontFamily = "Noto Sans JP";
11
+ const fontWeight = n.bold ? "bold" : "normal";
12
+ const lineHeight = 1.3;
13
+ yn.setMeasureFunc((width, widthMode) => {
14
+ const maxWidthPx = (() => {
15
+ switch (widthMode) {
16
+ case yoga.MEASURE_MODE_UNDEFINED:
17
+ return Number.POSITIVE_INFINITY;
18
+ case yoga.MEASURE_MODE_EXACTLY:
19
+ case yoga.MEASURE_MODE_AT_MOST:
20
+ return width;
21
+ }
22
+ })();
23
+ const { widthPx, heightPx } = measureText(text, maxWidthPx, {
24
+ fontFamily,
25
+ fontSizePx,
26
+ lineHeight,
27
+ fontWeight,
28
+ }, ctx.textMeasurementMode);
29
+ return { width: widthPx, height: heightPx };
30
+ });
31
+ },
32
+ render(node, ctx) {
33
+ renderTextNode(node, ctx);
34
+ },
35
+ };
@@ -0,0 +1,2 @@
1
+ export { getNodeDef } from "./nodeRegistry.ts";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AA0CA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { registerNode } from "./nodeRegistry.js";
2
+ import { textNodeDef } from "./definitions/text.js";
3
+ import { ulNodeDef, olNodeDef } from "./definitions/list.js";
4
+ import { imageNodeDef } from "./definitions/image.js";
5
+ import { tableNodeDef } from "./definitions/table.js";
6
+ import { shapeNodeDef } from "./definitions/shape.js";
7
+ import { chartNodeDef } from "./definitions/chart.js";
8
+ import { iconNodeDef } from "./definitions/icon.js";
9
+ import { lineNodeDef } from "./definitions/line.js";
10
+ import { timelineNodeDef, matrixNodeDef, treeNodeDef, flowNodeDef, processArrowNodeDef, pyramidNodeDef, } from "./definitions/compositeNodes.js";
11
+ import { boxNodeDef } from "./definitions/box.js";
12
+ import { vstackNodeDef, hstackNodeDef } from "./definitions/stack.js";
13
+ import { layerNodeDef } from "./definitions/layer.js";
14
+ // 全ノード定義を登録
15
+ registerNode(textNodeDef);
16
+ registerNode(ulNodeDef);
17
+ registerNode(olNodeDef);
18
+ registerNode(imageNodeDef);
19
+ registerNode(tableNodeDef);
20
+ registerNode(shapeNodeDef);
21
+ registerNode(chartNodeDef);
22
+ registerNode(iconNodeDef);
23
+ registerNode(lineNodeDef);
24
+ registerNode(timelineNodeDef);
25
+ registerNode(matrixNodeDef);
26
+ registerNode(treeNodeDef);
27
+ registerNode(flowNodeDef);
28
+ registerNode(processArrowNodeDef);
29
+ registerNode(pyramidNodeDef);
30
+ registerNode(boxNodeDef);
31
+ registerNode(vstackNodeDef);
32
+ registerNode(hstackNodeDef);
33
+ registerNode(layerNodeDef);
34
+ export { getNodeDef } from "./nodeRegistry.js";
@@ -0,0 +1,7 @@
1
+ import type { POMNode } from "../types.ts";
2
+ import type { NodeDefinition } from "./types.ts";
3
+ type NodeType = POMNode["type"];
4
+ export declare function registerNode(def: NodeDefinition): void;
5
+ export declare function getNodeDef(type: NodeType): NodeDefinition;
6
+ export {};
7
+ //# sourceMappingURL=nodeRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeRegistry.d.ts","sourceRoot":"","sources":["../../src/registry/nodeRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAIhC,wBAAgB,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAKtD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,cAAc,CAIzD"}
@@ -0,0 +1,13 @@
1
+ const registry = new Map();
2
+ export function registerNode(def) {
3
+ if (registry.has(def.type)) {
4
+ throw new Error(`Duplicate node registration: ${def.type}`);
5
+ }
6
+ registry.set(def.type, def);
7
+ }
8
+ export function getNodeDef(type) {
9
+ const def = registry.get(type);
10
+ if (!def)
11
+ throw new Error(`Unknown node type: ${type}`);
12
+ return def;
13
+ }
@@ -0,0 +1,26 @@
1
+ import type { POMNode, PositionedNode } from "../types.ts";
2
+ import type { Node as YogaNode } from "yoga-layout";
3
+ import type { RenderContext } from "../renderPptx/types.ts";
4
+ import type { loadYoga } from "yoga-layout/load";
5
+ import type { BuildContext } from "../buildContext.ts";
6
+ export type Yoga = Awaited<ReturnType<typeof loadYoga>>;
7
+ /** ノードのカテゴリ。子要素の扱い方を決定する */
8
+ export type NodeCategory = "leaf" | "single-child" | "multi-child" | "absolute-child";
9
+ export interface NodeDefinition {
10
+ /** ノードタイプ名 */
11
+ type: POMNode["type"];
12
+ /** ノードカテゴリ */
13
+ category: NodeCategory;
14
+ /** YogaNode にノード固有のスタイル/measureFunc を適用する */
15
+ applyYogaStyle?: (node: POMNode, yn: YogaNode, yoga: Yoga, ctx: BuildContext) => void | Promise<void>;
16
+ /** POMNode → PositionedNode へのカスタム変換(未定義なら category ベースのデフォルト) */
17
+ toPositioned?: (pom: POMNode, absoluteX: number, absoluteY: number, layout: {
18
+ width: number;
19
+ height: number;
20
+ }, ctx: BuildContext) => PositionedNode;
21
+ /** PositionedNode をスライドにレンダリングする(リーフノード用) */
22
+ render?: (node: PositionedNode, ctx: RenderContext) => void;
23
+ /** 画像ソース収集(prefetch 用) */
24
+ collectImageSources?: (node: POMNode) => string[];
25
+ }
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC;AAExD,4BAA4B;AAC5B,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,cAAc,GACd,aAAa,GACb,gBAAgB,CAAC;AAErB,MAAM,WAAW,cAAc;IAC7B,cAAc;IACd,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAEtB,cAAc;IACd,QAAQ,EAAE,YAAY,CAAC;IAEvB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,CACf,IAAI,EAAE,OAAO,EACb,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,YAAY,KACd,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,kEAAkE;IAClE,YAAY,CAAC,EAAE,CACb,GAAG,EAAE,OAAO,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EACzC,GAAG,EAAE,YAAY,KACd,cAAc,CAAC;IAEpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,KAAK,IAAI,CAAC;IAE5D,0BAA0B;IAC1B,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM,EAAE,CAAC;CACnD"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,5 @@
1
1
  import type { PositionedNode, SlideMasterOptions } from "../types.ts";
2
+ import type { BuildContext } from "../buildContext.ts";
2
3
  type SlidePx = {
3
4
  w: number;
4
5
  h: number;
@@ -10,6 +11,6 @@ type SlidePx = {
10
11
  * @param master スライドマスターオプション(省略可能)
11
12
  * @returns PptxGenJS インスタンス
12
13
  */
13
- export declare function renderPptx(pages: PositionedNode[], slidePx: SlidePx, master?: SlideMasterOptions): import("pptxgenjs").default;
14
+ export declare function renderPptx(pages: PositionedNode[], slidePx: SlidePx, buildContext: BuildContext, master?: SlideMasterOptions): import("pptxgenjs").default;
14
15
  export {};
15
16
  //# 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;AAwBrB,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA+JxC;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,kBAAkB,+BAqL5B"}
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;AACrB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQvD,KAAK,OAAO,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA+JxC;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,YAAY,EAC1B,MAAM,CAAC,EAAE,kBAAkB,+BAsI5B"}
@@ -9,7 +9,7 @@ import { pxToIn, pxToPt } from "./units.js";
9
9
  import { convertUnderline, convertStrike } from "./textOptions.js";
10
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, renderPyramidNode, renderLineNode, renderUlNode, renderOlNode, renderIconNode, } from "./nodes/index.js";
12
+ import { getNodeDef } from "../registry/index.js";
13
13
  const DEFAULT_MASTER_NAME = "POM_MASTER";
14
14
  /**
15
15
  * zIndex でソートして描画順を制御する(安定ソート)
@@ -165,7 +165,7 @@ function defineSlideMasterFromOptions(pptx, master) {
165
165
  * @param master スライドマスターオプション(省略可能)
166
166
  * @returns PptxGenJS インスタンス
167
167
  */
168
- export function renderPptx(pages, slidePx, master) {
168
+ export function renderPptx(pages, slidePx, buildContext, master) {
169
169
  const slideIn = { w: pxToIn(slidePx.w), h: pxToIn(slidePx.h) }; // layout(=px) → PptxGenJS(=inch) への最終変換
170
170
  const pptx = new PptxGenJS();
171
171
  pptx.defineLayout({ name: "custom", width: slideIn.w, height: slideIn.h });
@@ -177,7 +177,7 @@ export function renderPptx(pages, slidePx, master) {
177
177
  for (const data of pages) {
178
178
  // マスターが指定されている場合は masterName を使用
179
179
  const slide = masterName ? pptx.addSlide({ masterName }) : pptx.addSlide();
180
- const ctx = { slide, pptx };
180
+ const ctx = { slide, pptx, buildContext };
181
181
  // ルートノードの backgroundColor はスライドの background プロパティとして適用
182
182
  // これにより、マスタースライドのオブジェクトを覆い隠さない
183
183
  // line ノードは backgroundColor を持たないためスキップ
@@ -192,7 +192,7 @@ export function renderPptx(pages, slidePx, master) {
192
192
  // backgroundColor と backgroundImage の両方がある場合、backgroundImage が優先
193
193
  const rootBackgroundImage = data.type !== "line" ? data.backgroundImage : undefined;
194
194
  if (rootBackgroundImage) {
195
- const cachedData = getImageData(rootBackgroundImage.src);
195
+ const cachedData = getImageData(rootBackgroundImage.src, buildContext.imageDataCache);
196
196
  if (cachedData) {
197
197
  slide.background = { data: cachedData };
198
198
  }
@@ -244,69 +244,28 @@ export function renderPptx(pages, slidePx, master) {
244
244
  renderBackgroundAndBorder(node, ctx);
245
245
  }
246
246
  }
247
- switch (node.type) {
248
- case "text":
249
- renderTextNode(node, ctx);
250
- break;
251
- case "ul":
252
- renderUlNode(node, ctx);
253
- break;
254
- case "ol":
255
- renderOlNode(node, ctx);
256
- break;
257
- case "image":
258
- renderImageNode(node, ctx);
259
- break;
260
- case "icon":
261
- renderIconNode(node, ctx);
262
- break;
263
- case "box":
264
- // 子要素を再帰的に処理
265
- renderNode(node.children);
266
- break;
267
- case "vstack":
268
- case "hstack":
269
- // zIndex でソートして描画順を制御(値が小さいものが先に描画される)
270
- for (const child of sortByZIndex(node.children)) {
271
- renderNode(child);
247
+ const def = getNodeDef(node.type);
248
+ switch (def.category) {
249
+ case "leaf":
250
+ if (!def.render) {
251
+ throw new Error(`No render function registered for leaf node: ${node.type}`);
272
252
  }
253
+ def.render(node, ctx);
273
254
  break;
274
- case "table":
275
- renderTableNode(node, ctx);
276
- break;
277
- case "shape":
278
- renderShapeNode(node, ctx);
279
- break;
280
- case "chart":
281
- renderChartNode(node, ctx);
255
+ case "single-child": {
256
+ const boxNode = node;
257
+ renderNode(boxNode.children);
282
258
  break;
283
- case "timeline":
284
- renderTimelineNode(node, ctx);
285
- break;
286
- case "matrix":
287
- renderMatrixNode(node, ctx);
288
- break;
289
- case "tree":
290
- renderTreeNode(node, ctx);
291
- break;
292
- case "flow":
293
- renderFlowNode(node, ctx);
294
- break;
295
- case "processArrow":
296
- renderProcessArrowNode(node, ctx);
297
- break;
298
- case "pyramid":
299
- renderPyramidNode(node, ctx);
300
- break;
301
- case "line":
302
- renderLineNode(node, ctx);
303
- break;
304
- case "layer":
259
+ }
260
+ case "multi-child":
261
+ case "absolute-child": {
262
+ const containerNode = node;
305
263
  // zIndex でソートして描画順を制御(値が小さいものが先に描画される)
306
- for (const child of sortByZIndex(node.children)) {
264
+ for (const child of sortByZIndex(containerNode.children)) {
307
265
  renderNode(child);
308
266
  }
309
267
  break;
268
+ }
310
269
  }
311
270
  }
312
271
  renderNode(data, true); // ルートノードとして処理
@@ -1,9 +1,11 @@
1
+ import type { BuildContext } from "../buildContext.ts";
1
2
  type PptxGenJSClass = import("pptxgenjs").default;
2
3
  export type SlideInstance = ReturnType<PptxGenJSClass["addSlide"]>;
3
4
  export type PptxInstance = PptxGenJSClass;
4
5
  export type RenderContext = {
5
6
  slide: SlideInstance;
6
7
  pptx: PptxInstance;
8
+ buildContext: BuildContext;
7
9
  };
8
10
  export {};
9
11
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
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
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderPptx/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,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;IACnB,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"backgroundBorder.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/backgroundBorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,aAAa,GACjB,IAAI,CAyHN"}
1
+ {"version":3,"file":"backgroundBorder.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/backgroundBorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,cAAc,EACpB,GAAG,EAAE,aAAa,GACjB,IAAI,CA4HN"}
@@ -94,7 +94,7 @@ export function renderBackgroundAndBorder(node, ctx) {
94
94
  h: pxToIn(node.h),
95
95
  },
96
96
  };
97
- const cachedData = getImageData(backgroundImage.src);
97
+ const cachedData = getImageData(backgroundImage.src, ctx.buildContext.imageDataCache);
98
98
  if (cachedData) {
99
99
  ctx.slide.addImage({ ...imageOptions, data: cachedData });
100
100
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freeYogaTree.d.ts","sourceRoot":"","sources":["../../src/shared/freeYogaTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAwBhD"}