@hirokisakabe/pom 5.4.0 → 5.5.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 (81) hide show
  1. package/README.md +6 -5
  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 +33 -17
  5. package/dist/buildContext.d.ts +2 -0
  6. package/dist/buildContext.d.ts.map +1 -1
  7. package/dist/buildContext.js +2 -0
  8. package/dist/buildPptx.d.ts +7 -1
  9. package/dist/buildPptx.d.ts.map +1 -1
  10. package/dist/buildPptx.js +14 -5
  11. package/dist/calcYogaLayout/calcYogaLayout.d.ts +4 -2
  12. package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
  13. package/dist/calcYogaLayout/calcYogaLayout.js +29 -15
  14. package/dist/calcYogaLayout/types.d.ts +16 -0
  15. package/dist/calcYogaLayout/types.d.ts.map +1 -0
  16. package/dist/calcYogaLayout/types.js +14 -0
  17. package/dist/diagnostics.d.ts +14 -0
  18. package/dist/diagnostics.d.ts.map +1 -0
  19. package/dist/diagnostics.js +17 -0
  20. package/dist/index.d.ts +3 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -0
  23. package/dist/parseXml/parseXml.d.ts +1 -1
  24. package/dist/parseXml/parseXml.d.ts.map +1 -1
  25. package/dist/parseXml/parseXml.js +16 -16
  26. package/dist/registry/definitions/icon.d.ts.map +1 -1
  27. package/dist/registry/definitions/icon.js +26 -14
  28. package/dist/registry/definitions/image.d.ts.map +1 -1
  29. package/dist/registry/definitions/image.js +2 -3
  30. package/dist/registry/definitions/layer.d.ts.map +1 -1
  31. package/dist/registry/definitions/layer.js +9 -6
  32. package/dist/registry/definitions/line.d.ts.map +1 -1
  33. package/dist/registry/definitions/line.js +1 -2
  34. package/dist/registry/types.d.ts +2 -1
  35. package/dist/registry/types.d.ts.map +1 -1
  36. package/dist/renderPptx/nodes/chart.d.ts.map +1 -1
  37. package/dist/renderPptx/nodes/chart.js +6 -4
  38. package/dist/renderPptx/nodes/flow.d.ts.map +1 -1
  39. package/dist/renderPptx/nodes/flow.js +14 -4
  40. package/dist/renderPptx/nodes/image.d.ts.map +1 -1
  41. package/dist/renderPptx/nodes/image.js +8 -6
  42. package/dist/renderPptx/nodes/list.d.ts.map +1 -1
  43. package/dist/renderPptx/nodes/list.js +19 -16
  44. package/dist/renderPptx/nodes/matrix.d.ts.map +1 -1
  45. package/dist/renderPptx/nodes/matrix.js +11 -9
  46. package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -1
  47. package/dist/renderPptx/nodes/processArrow.js +14 -4
  48. package/dist/renderPptx/nodes/pyramid.d.ts.map +1 -1
  49. package/dist/renderPptx/nodes/pyramid.js +6 -4
  50. package/dist/renderPptx/nodes/shape.d.ts.map +1 -1
  51. package/dist/renderPptx/nodes/shape.js +6 -4
  52. package/dist/renderPptx/nodes/table.d.ts.map +1 -1
  53. package/dist/renderPptx/nodes/table.js +7 -5
  54. package/dist/renderPptx/nodes/timeline.d.ts.map +1 -1
  55. package/dist/renderPptx/nodes/timeline.js +14 -4
  56. package/dist/renderPptx/nodes/tree.d.ts.map +1 -1
  57. package/dist/renderPptx/nodes/tree.js +6 -4
  58. package/dist/renderPptx/textOptions.d.ts.map +1 -1
  59. package/dist/renderPptx/textOptions.js +6 -4
  60. package/dist/renderPptx/utils/contentArea.d.ts +26 -0
  61. package/dist/renderPptx/utils/contentArea.d.ts.map +1 -0
  62. package/dist/renderPptx/utils/contentArea.js +26 -0
  63. package/dist/renderPptx/utils/scaleToFit.d.ts +3 -2
  64. package/dist/renderPptx/utils/scaleToFit.d.ts.map +1 -1
  65. package/dist/renderPptx/utils/scaleToFit.js +3 -3
  66. package/dist/shared/freeYogaTree.d.ts +3 -3
  67. package/dist/shared/freeYogaTree.d.ts.map +1 -1
  68. package/dist/shared/freeYogaTree.js +16 -21
  69. package/dist/shared/measureImage.d.ts +3 -2
  70. package/dist/shared/measureImage.d.ts.map +1 -1
  71. package/dist/shared/measureImage.js +5 -5
  72. package/dist/toPositioned/toPositioned.d.ts +3 -6
  73. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  74. package/dist/toPositioned/toPositioned.js +11 -19
  75. package/dist/types.d.ts +12 -445
  76. package/dist/types.d.ts.map +1 -1
  77. package/dist/types.js +43 -50
  78. package/package.json +5 -2
  79. package/dist/parseXml/inputSchema.d.ts +0 -1622
  80. package/dist/parseXml/inputSchema.d.ts.map +0 -1
  81. package/dist/parseXml/inputSchema.js +0 -257
@@ -0,0 +1,26 @@
1
+ /**
2
+ * ノードの padding を考慮したコンテンツ描画領域を計算する。
3
+ * background/border はノード全体の領域 (node.x/y/w/h) に描画し、
4
+ * コンテンツはこの関数で返される領域に描画する。
5
+ */
6
+ export function getContentArea(node) {
7
+ if (node.padding === undefined) {
8
+ return { x: node.x, y: node.y, w: node.w, h: node.h };
9
+ }
10
+ let top, right, bottom, left;
11
+ if (typeof node.padding === "number") {
12
+ top = right = bottom = left = node.padding;
13
+ }
14
+ else {
15
+ top = node.padding.top ?? 0;
16
+ right = node.padding.right ?? 0;
17
+ bottom = node.padding.bottom ?? 0;
18
+ left = node.padding.left ?? 0;
19
+ }
20
+ return {
21
+ x: node.x + left,
22
+ y: node.y + top,
23
+ w: Math.max(0, node.w - left - right),
24
+ h: Math.max(0, node.h - top - bottom),
25
+ };
26
+ }
@@ -1,8 +1,9 @@
1
+ import type { DiagnosticCollector } from "../../diagnostics.ts";
1
2
  /**
2
3
  * 割り当てサイズと固有サイズからスケール係数を計算する。
3
4
  *
4
5
  * - scaleFactor = min(allocatedW / intrinsicW, allocatedH / intrinsicH, 1.0)
5
- * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして console.warn
6
+ * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして diagnostics に記録
6
7
  */
7
- export declare function calcScaleFactor(allocatedW: number, allocatedH: number, intrinsicW: number, intrinsicH: number, nodeType: string): number;
8
+ export declare function calcScaleFactor(allocatedW: number, allocatedH: number, intrinsicW: number, intrinsicH: number, nodeType: string, diagnostics: DiagnosticCollector): number;
8
9
  //# sourceMappingURL=scaleToFit.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"scaleToFit.d.ts","sourceRoot":"","sources":["../../../src/renderPptx/utils/scaleToFit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAIhE;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,mBAAmB,GAC/B,MAAM,CAgBR"}
@@ -3,16 +3,16 @@ const MIN_SCALE_THRESHOLD = 0.5;
3
3
  * 割り当てサイズと固有サイズからスケール係数を計算する。
4
4
  *
5
5
  * - scaleFactor = min(allocatedW / intrinsicW, allocatedH / intrinsicH, 1.0)
6
- * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして console.warn
6
+ * - scaleFactor < MIN_SCALE_THRESHOLD の場合、閾値でクランプして diagnostics に記録
7
7
  */
8
- export function calcScaleFactor(allocatedW, allocatedH, intrinsicW, intrinsicH, nodeType) {
8
+ export function calcScaleFactor(allocatedW, allocatedH, intrinsicW, intrinsicH, nodeType, diagnostics) {
9
9
  if (intrinsicW <= 0 || intrinsicH <= 0)
10
10
  return 1.0;
11
11
  const scaleX = allocatedW / intrinsicW;
12
12
  const scaleY = allocatedH / intrinsicH;
13
13
  let scaleFactor = Math.min(scaleX, scaleY, 1.0);
14
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.`);
15
+ diagnostics.add("SCALE_BELOW_THRESHOLD", `${nodeType} node: scale factor ${scaleFactor.toFixed(2)} is below threshold ${MIN_SCALE_THRESHOLD}. Content may overflow.`);
16
16
  scaleFactor = MIN_SCALE_THRESHOLD;
17
17
  }
18
18
  return scaleFactor;
@@ -1,7 +1,7 @@
1
- import type { POMNode } from "../types.ts";
1
+ import type { YogaNodeMap } from "../calcYogaLayout/types.ts";
2
2
  /**
3
- * POMNode ツリー内の全 yogaNode を解放し、参照をクリアする。
3
+ * YogaNodeMap 内の全 YogaNode を解放する。
4
4
  * calcYogaLayout を再実行する前に呼び出すこと。
5
5
  */
6
- export declare function freeYogaTree(node: POMNode): void;
6
+ export declare function freeYogaTree(map: YogaNodeMap): void;
7
7
  //# sourceMappingURL=freeYogaTree.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"freeYogaTree.d.ts","sourceRoot":"","sources":["../../src/shared/freeYogaTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAqBnD"}
@@ -1,29 +1,24 @@
1
- import { walkPOMTree } from "./walkTree.js";
2
1
  /**
3
- * POMNode ツリー内の全 yogaNode を解放し、参照をクリアする。
2
+ * YogaNodeMap 内の全 YogaNode を解放する。
4
3
  * calcYogaLayout を再実行する前に呼び出すこと。
5
4
  */
6
- export function freeYogaTree(node) {
7
- // 子から先に解放する(yoga-layout は親が子を参照しているため)
8
- const nodes = [];
9
- walkPOMTree(node, (n) => nodes.push(n));
10
- // 逆順(リーフから)で解放
11
- for (let i = nodes.length - 1; i >= 0; i--) {
12
- const n = nodes[i];
13
- if (n.yogaNode) {
14
- // 親から切り離してから解放
15
- const owner = n.yogaNode.getParent();
16
- if (owner) {
17
- const childCount = owner.getChildCount();
18
- for (let j = 0; j < childCount; j++) {
19
- if (owner.getChild(j) === n.yogaNode) {
20
- owner.removeChild(n.yogaNode);
21
- break;
22
- }
5
+ export function freeYogaTree(map) {
6
+ // Map の insertion order は親→子なので、逆順(リーフから)で解放する
7
+ const yogaNodes = Array.from(map.values());
8
+ for (let i = yogaNodes.length - 1; i >= 0; i--) {
9
+ const yn = yogaNodes[i];
10
+ // 親から切り離してから解放
11
+ const owner = yn.getParent();
12
+ if (owner) {
13
+ const childCount = owner.getChildCount();
14
+ for (let j = 0; j < childCount; j++) {
15
+ if (owner.getChild(j) === yn) {
16
+ owner.removeChild(yn);
17
+ break;
23
18
  }
24
19
  }
25
- n.yogaNode.free();
26
- n.yogaNode = undefined;
27
20
  }
21
+ yn.free();
28
22
  }
23
+ map.clear();
29
24
  }
@@ -1,3 +1,4 @@
1
+ import type { DiagnosticCollector } from "../diagnostics.ts";
1
2
  type ImageSizeCache = Map<string, {
2
3
  widthPx: number;
3
4
  heightPx: number;
@@ -18,7 +19,7 @@ export declare function getImageData(src: string, cache: ImageDataCache): string
18
19
  * @param dataCache 画像データキャッシュ
19
20
  * @returns 画像の幅と高さ(px)
20
21
  */
21
- export declare function prefetchImageSize(src: string, sizeCache: ImageSizeCache, dataCache: ImageDataCache): Promise<{
22
+ export declare function prefetchImageSize(src: string, sizeCache: ImageSizeCache, dataCache: ImageDataCache, diagnostics: DiagnosticCollector): Promise<{
22
23
  widthPx: number;
23
24
  heightPx: number;
24
25
  }>;
@@ -29,7 +30,7 @@ export declare function prefetchImageSize(src: string, sizeCache: ImageSizeCache
29
30
  * @param sizeCache 画像サイズキャッシュ
30
31
  * @returns 画像の幅と高さ(px)
31
32
  */
32
- export declare function measureImage(src: string, sizeCache: ImageSizeCache): {
33
+ export declare function measureImage(src: string, sizeCache: ImageSizeCache, diagnostics: DiagnosticCollector): {
33
34
  widthPx: number;
34
35
  heightPx: number;
35
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"measureImage.d.ts","sourceRoot":"","sources":["../../src/shared/measureImage.ts"],"names":[],"mappings":"AAYA,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzE,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,GACpB,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,cAAc,GACxB,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CA0DD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,GACxB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAqDA"}
1
+ {"version":3,"file":"measureImage.d.ts","sourceRoot":"","sources":["../../src/shared/measureImage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAW7D,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACzE,KAAK,cAAc,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE1C;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,cAAc,GACpB,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,EACzB,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,mBAAmB,GAC/B,OAAO,CAAC;IACT,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CA6DD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,mBAAmB,GAC/B;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAyDA"}
@@ -23,7 +23,7 @@ export function getImageData(src, cache) {
23
23
  * @param dataCache 画像データキャッシュ
24
24
  * @returns 画像の幅と高さ(px)
25
25
  */
26
- export async function prefetchImageSize(src, sizeCache, dataCache) {
26
+ export async function prefetchImageSize(src, sizeCache, dataCache, diagnostics) {
27
27
  // キャッシュにあればそれを返す
28
28
  const cached = sizeCache.get(src);
29
29
  if (cached) {
@@ -66,7 +66,7 @@ export async function prefetchImageSize(src, sizeCache, dataCache) {
66
66
  }
67
67
  catch (error) {
68
68
  // エラーが発生した場合はデフォルトサイズを返す
69
- console.warn(`Failed to measure image size for ${src}:`, error);
69
+ diagnostics.add("IMAGE_MEASURE_FAILED", `Failed to measure image size for ${src}: ${String(error)}`);
70
70
  const result = {
71
71
  widthPx: 100,
72
72
  heightPx: 100,
@@ -82,7 +82,7 @@ export async function prefetchImageSize(src, sizeCache, dataCache) {
82
82
  * @param sizeCache 画像サイズキャッシュ
83
83
  * @returns 画像の幅と高さ(px)
84
84
  */
85
- export function measureImage(src, sizeCache) {
85
+ export function measureImage(src, sizeCache, diagnostics) {
86
86
  // キャッシュにあればそれを返す
87
87
  const cached = sizeCache.get(src);
88
88
  if (cached) {
@@ -98,7 +98,7 @@ export function measureImage(src, sizeCache) {
98
98
  }
99
99
  // HTTPS/HTTP URLの場合はキャッシュがないとデフォルト値を返す
100
100
  else if (src.startsWith("https://") || src.startsWith("http://")) {
101
- console.warn(`Image size for URL ${src} was not prefetched. Using default size.`);
101
+ diagnostics.add("IMAGE_NOT_PREFETCHED", `Image size for URL ${src} was not prefetched. Using default size.`);
102
102
  return {
103
103
  widthPx: 100,
104
104
  heightPx: 100,
@@ -121,7 +121,7 @@ export function measureImage(src, sizeCache) {
121
121
  }
122
122
  catch (error) {
123
123
  // エラーが発生した場合はデフォルトサイズを返す
124
- console.warn(`Failed to measure image size for ${src}:`, error);
124
+ diagnostics.add("IMAGE_MEASURE_FAILED", `Failed to measure image size for ${src}: ${String(error)}`);
125
125
  return {
126
126
  widthPx: 100,
127
127
  heightPx: 100,
@@ -1,17 +1,14 @@
1
1
  import type { POMNode, PositionedNode } from "../types.ts";
2
2
  import type { BuildContext } from "../buildContext.ts";
3
- /**
4
- * POMNode から yogaNode を除外したオブジェクトを返す。
5
- * PositionedNode に yogaNode 参照が残らないようにするため。
6
- */
7
- export declare function omitYogaNode<T extends POMNode>(pom: T): Omit<T, "yogaNode">;
3
+ import type { LayoutResultMap } from "../calcYogaLayout/types.ts";
8
4
  /**
9
5
  * POMNode ツリーを絶対座標付きの PositionedNode ツリーに変換する
10
6
  * @param pom 入力 POMNode
11
7
  * @param ctx BuildContext
8
+ * @param map LayoutResultMap(POMNode → 計算済みレイアウト結果のマッピング)
12
9
  * @param parentX 親ノードの絶対X座標
13
10
  * @param parentY 親ノードの絶対Y座標
14
11
  * @returns PositionedNode ツリー
15
12
  */
16
- export declare function toPositioned(pom: POMNode, ctx: BuildContext, parentX?: number, parentY?: number): PositionedNode;
13
+ export declare function toPositioned(pom: POMNode, ctx: BuildContext, map: LayoutResultMap, parentX?: number, parentY?: number): PositionedNode;
17
14
  //# sourceMappingURL=toPositioned.d.ts.map
@@ -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;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,UAAU,CAAC,CAI3E;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,YAAY,EACjB,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CA8DhB"}
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;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAGlE;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE,eAAe,EACpB,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CAmEhB"}
@@ -1,38 +1,30 @@
1
1
  import { getNodeDef } from "../registry/index.js";
2
- /**
3
- * POMNode から yogaNode を除外したオブジェクトを返す。
4
- * PositionedNode に yogaNode 参照が残らないようにするため。
5
- */
6
- export function omitYogaNode(pom) {
7
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
8
- const { yogaNode, ...rest } = pom;
9
- return rest;
10
- }
11
2
  /**
12
3
  * POMNode ツリーを絶対座標付きの PositionedNode ツリーに変換する
13
4
  * @param pom 入力 POMNode
14
5
  * @param ctx BuildContext
6
+ * @param map LayoutResultMap(POMNode → 計算済みレイアウト結果のマッピング)
15
7
  * @param parentX 親ノードの絶対X座標
16
8
  * @param parentY 親ノードの絶対Y座標
17
9
  * @returns PositionedNode ツリー
18
10
  */
19
- export function toPositioned(pom, ctx, parentX = 0, parentY = 0) {
20
- if (!pom.yogaNode) {
21
- throw new Error("yogaNode not set on POMNode");
11
+ export function toPositioned(pom, ctx, map, parentX = 0, parentY = 0) {
12
+ const layout = map.get(pom);
13
+ if (!layout) {
14
+ throw new Error("Layout result not found in map for POMNode");
22
15
  }
23
- const layout = pom.yogaNode.getComputedLayout();
24
16
  const absoluteX = parentX + layout.left;
25
17
  const absoluteY = parentY + layout.top;
26
18
  const def = getNodeDef(pom.type);
27
19
  // ノード固有のカスタム変換がある場合はそれを使用
28
20
  if (def.toPositioned) {
29
- return def.toPositioned(pom, absoluteX, absoluteY, layout, ctx);
21
+ return def.toPositioned(pom, absoluteX, absoluteY, layout, ctx, map);
30
22
  }
31
23
  // category ベースのデフォルト処理
32
24
  switch (def.category) {
33
25
  case "leaf":
34
26
  return {
35
- ...omitYogaNode(pom),
27
+ ...pom,
36
28
  x: absoluteX,
37
29
  y: absoluteY,
38
30
  w: layout.width,
@@ -41,23 +33,23 @@ export function toPositioned(pom, ctx, parentX = 0, parentY = 0) {
41
33
  case "single-child": {
42
34
  const boxNode = pom;
43
35
  return {
44
- ...omitYogaNode(boxNode),
36
+ ...boxNode,
45
37
  x: absoluteX,
46
38
  y: absoluteY,
47
39
  w: layout.width,
48
40
  h: layout.height,
49
- children: toPositioned(boxNode.children, ctx, absoluteX, absoluteY),
41
+ children: toPositioned(boxNode.children, ctx, map, absoluteX, absoluteY),
50
42
  };
51
43
  }
52
44
  case "multi-child": {
53
45
  const containerNode = pom;
54
46
  return {
55
- ...omitYogaNode(containerNode),
47
+ ...containerNode,
56
48
  x: absoluteX,
57
49
  y: absoluteY,
58
50
  w: layout.width,
59
51
  h: layout.height,
60
- children: containerNode.children.map((child) => toPositioned(child, ctx, absoluteX, absoluteY)),
52
+ children: containerNode.children.map((child) => toPositioned(child, ctx, map, absoluteX, absoluteY)),
61
53
  };
62
54
  }
63
55
  case "absolute-child":