@hirokisakabe/pom 5.2.0 → 5.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 (106) 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 +479 -0
  27. package/dist/parseXml/inputSchema.d.ts +22 -105
  28. package/dist/parseXml/inputSchema.d.ts.map +1 -1
  29. package/dist/parseXml/inputSchema.js +5 -3
  30. package/dist/parseXml/parseXml.d.ts.map +1 -1
  31. package/dist/parseXml/parseXml.js +48 -277
  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 +50 -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/nodes/icon.d.ts.map +1 -1
  78. package/dist/renderPptx/nodes/icon.js +22 -4
  79. package/dist/renderPptx/renderPptx.d.ts +2 -1
  80. package/dist/renderPptx/renderPptx.d.ts.map +1 -1
  81. package/dist/renderPptx/renderPptx.js +19 -60
  82. package/dist/renderPptx/types.d.ts +2 -0
  83. package/dist/renderPptx/types.d.ts.map +1 -1
  84. package/dist/renderPptx/utils/backgroundBorder.d.ts.map +1 -1
  85. package/dist/renderPptx/utils/backgroundBorder.js +1 -1
  86. package/dist/shared/freeYogaTree.d.ts.map +1 -0
  87. package/dist/shared/measureImage.d.ts +13 -3
  88. package/dist/shared/measureImage.d.ts.map +1 -1
  89. package/dist/shared/measureImage.js +14 -19
  90. package/dist/shared/walkTree.d.ts.map +1 -0
  91. package/dist/toPositioned/toPositioned.d.ts +8 -1
  92. package/dist/toPositioned/toPositioned.d.ts.map +1 -1
  93. package/dist/toPositioned/toPositioned.js +32 -189
  94. package/dist/types.d.ts +38 -54
  95. package/dist/types.d.ts.map +1 -1
  96. package/dist/types.js +11 -1
  97. package/package.json +3 -3
  98. package/dist/autoFit/freeYogaTree.d.ts.map +0 -1
  99. package/dist/autoFit/walkTree.d.ts.map +0 -1
  100. package/dist/renderPptx/nodes/index.d.ts +0 -15
  101. package/dist/renderPptx/nodes/index.d.ts.map +0 -1
  102. package/dist/renderPptx/nodes/index.js +0 -14
  103. /package/dist/{autoFit → shared}/freeYogaTree.d.ts +0 -0
  104. /package/dist/{autoFit → shared}/freeYogaTree.js +0 -0
  105. /package/dist/{autoFit → shared}/walkTree.d.ts +0 -0
  106. /package/dist/{autoFit → shared}/walkTree.js +0 -0
@@ -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"}
@@ -1,16 +1,24 @@
1
+ type ImageSizeCache = Map<string, {
2
+ widthPx: number;
3
+ heightPx: number;
4
+ }>;
5
+ type ImageDataCache = Map<string, string>;
1
6
  /**
2
7
  * キャッシュされた画像データ(Base64)を取得する
3
8
  * @param src 画像のパス
9
+ * @param cache 画像データキャッシュ
4
10
  * @returns Base64形式の画像データ、またはキャッシュがない場合はundefined
5
11
  */
6
- export declare function getImageData(src: string): string | undefined;
12
+ export declare function getImageData(src: string, cache: ImageDataCache): string | undefined;
7
13
  /**
8
14
  * 画像サイズを事前取得してキャッシュする(非同期)
9
15
  * HTTPS URLの画像を処理する際に使用
10
16
  * @param src 画像のパス(ローカルパス、base64データ、またはHTTPS URL)
17
+ * @param sizeCache 画像サイズキャッシュ
18
+ * @param dataCache 画像データキャッシュ
11
19
  * @returns 画像の幅と高さ(px)
12
20
  */
13
- export declare function prefetchImageSize(src: string): Promise<{
21
+ export declare function prefetchImageSize(src: string, sizeCache: ImageSizeCache, dataCache: ImageDataCache): Promise<{
14
22
  widthPx: number;
15
23
  heightPx: number;
16
24
  }>;
@@ -18,10 +26,12 @@ export declare function prefetchImageSize(src: string): Promise<{
18
26
  * 画像ファイルのサイズを取得する(同期)
19
27
  * 事前にprefetchImageSizeでキャッシュしておくこと
20
28
  * @param src 画像のパス(ローカルパス、base64データ、またはHTTPS URL)
29
+ * @param sizeCache 画像サイズキャッシュ
21
30
  * @returns 画像の幅と高さ(px)
22
31
  */
23
- export declare function measureImage(src: string): {
32
+ export declare function measureImage(src: string, sizeCache: ImageSizeCache): {
24
33
  widthPx: number;
25
34
  heightPx: number;
26
35
  };
36
+ export {};
27
37
  //# sourceMappingURL=measureImage.d.ts.map
@@ -1 +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
+ {"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"}
@@ -6,32 +6,26 @@ const imageSizeModule = require("image-size");
6
6
  // CommonJS モジュールは .default または直接エクスポートされる場合がある
7
7
  /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
8
8
  const imageSize = imageSizeModule.default ?? imageSizeModule;
9
- /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
10
- /**
11
- * 画像サイズのキャッシュ(事前取得した画像サイズを保持)
12
- */
13
- const imageSizeCache = new Map();
14
- /**
15
- * 画像データのキャッシュ(Base64形式、リモート画像用)
16
- */
17
- const imageDataCache = new Map();
18
9
  /**
19
10
  * キャッシュされた画像データ(Base64)を取得する
20
11
  * @param src 画像のパス
12
+ * @param cache 画像データキャッシュ
21
13
  * @returns Base64形式の画像データ、またはキャッシュがない場合はundefined
22
14
  */
23
- export function getImageData(src) {
24
- return imageDataCache.get(src);
15
+ export function getImageData(src, cache) {
16
+ return cache.get(src);
25
17
  }
26
18
  /**
27
19
  * 画像サイズを事前取得してキャッシュする(非同期)
28
20
  * HTTPS URLの画像を処理する際に使用
29
21
  * @param src 画像のパス(ローカルパス、base64データ、またはHTTPS URL)
22
+ * @param sizeCache 画像サイズキャッシュ
23
+ * @param dataCache 画像データキャッシュ
30
24
  * @returns 画像の幅と高さ(px)
31
25
  */
32
- export async function prefetchImageSize(src) {
26
+ export async function prefetchImageSize(src, sizeCache, dataCache) {
33
27
  // キャッシュにあればそれを返す
34
- const cached = imageSizeCache.get(src);
28
+ const cached = sizeCache.get(src);
35
29
  if (cached) {
36
30
  return cached;
37
31
  }
@@ -53,7 +47,7 @@ export async function prefetchImageSize(src) {
53
47
  // 画像データをBase64形式でキャッシュ(pptxgenjs用)
54
48
  const contentType = response.headers.get("content-type") || "image/png";
55
49
  const base64 = Buffer.from(arrayBuffer).toString("base64");
56
- imageDataCache.set(src, `${contentType};base64,${base64}`);
50
+ dataCache.set(src, `${contentType};base64,${base64}`);
57
51
  }
58
52
  // ローカルファイルパスの場合
59
53
  else {
@@ -67,7 +61,7 @@ export async function prefetchImageSize(src) {
67
61
  heightPx: height,
68
62
  };
69
63
  // キャッシュに保存
70
- imageSizeCache.set(src, result);
64
+ sizeCache.set(src, result);
71
65
  return result;
72
66
  }
73
67
  catch (error) {
@@ -77,7 +71,7 @@ export async function prefetchImageSize(src) {
77
71
  widthPx: 100,
78
72
  heightPx: 100,
79
73
  };
80
- imageSizeCache.set(src, result);
74
+ sizeCache.set(src, result);
81
75
  return result;
82
76
  }
83
77
  }
@@ -85,11 +79,12 @@ export async function prefetchImageSize(src) {
85
79
  * 画像ファイルのサイズを取得する(同期)
86
80
  * 事前にprefetchImageSizeでキャッシュしておくこと
87
81
  * @param src 画像のパス(ローカルパス、base64データ、またはHTTPS URL)
82
+ * @param sizeCache 画像サイズキャッシュ
88
83
  * @returns 画像の幅と高さ(px)
89
84
  */
90
- export function measureImage(src) {
85
+ export function measureImage(src, sizeCache) {
91
86
  // キャッシュにあればそれを返す
92
- const cached = imageSizeCache.get(src);
87
+ const cached = sizeCache.get(src);
93
88
  if (cached) {
94
89
  return cached;
95
90
  }
@@ -121,7 +116,7 @@ export function measureImage(src) {
121
116
  heightPx: height,
122
117
  };
123
118
  // キャッシュに保存
124
- imageSizeCache.set(src, result);
119
+ sizeCache.set(src, result);
125
120
  return result;
126
121
  }
127
122
  catch (error) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"walkTree.d.ts","sourceRoot":"","sources":["../../src/shared/walkTree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAC/B,IAAI,CAeN"}
@@ -1,10 +1,17 @@
1
1
  import type { POMNode, PositionedNode } from "../types.ts";
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">;
2
8
  /**
3
9
  * POMNode ツリーを絶対座標付きの PositionedNode ツリーに変換する
4
10
  * @param pom 入力 POMNode
11
+ * @param ctx BuildContext
5
12
  * @param parentX 親ノードの絶対X座標
6
13
  * @param parentY 親ノードの絶対Y座標
7
14
  * @returns PositionedNode ツリー
8
15
  */
9
- export declare function toPositioned(pom: POMNode, parentX?: number, parentY?: number): PositionedNode;
16
+ export declare function toPositioned(pom: POMNode, ctx: BuildContext, parentX?: number, parentY?: number): PositionedNode;
10
17
  //# 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;AAI3D;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,OAAO,EACZ,OAAO,SAAI,EACX,OAAO,SAAI,GACV,cAAc,CAwOhB"}
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,224 +1,67 @@
1
- import { getImageData } from "../shared/measureImage.js";
2
- import { rasterizeIcon } from "../icons/index.js";
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
+ }
3
11
  /**
4
12
  * POMNode ツリーを絶対座標付きの PositionedNode ツリーに変換する
5
13
  * @param pom 入力 POMNode
14
+ * @param ctx BuildContext
6
15
  * @param parentX 親ノードの絶対X座標
7
16
  * @param parentY 親ノードの絶対Y座標
8
17
  * @returns PositionedNode ツリー
9
18
  */
10
- export function toPositioned(pom, parentX = 0, parentY = 0) {
19
+ export function toPositioned(pom, ctx, parentX = 0, parentY = 0) {
11
20
  if (!pom.yogaNode) {
12
21
  throw new Error("yogaNode not set on POMNode");
13
22
  }
14
23
  const layout = pom.yogaNode.getComputedLayout();
15
24
  const absoluteX = parentX + layout.left;
16
25
  const absoluteY = parentY + layout.top;
17
- switch (pom.type) {
18
- case "text":
19
- case "ul":
20
- case "ol": {
21
- return {
22
- ...pom,
23
- x: absoluteX,
24
- y: absoluteY,
25
- w: layout.width,
26
- h: layout.height,
27
- };
28
- }
29
- case "image": {
30
- const imageData = getImageData(pom.src);
31
- return {
32
- ...pom,
33
- x: absoluteX,
34
- y: absoluteY,
35
- w: layout.width,
36
- h: layout.height,
37
- imageData,
38
- };
39
- }
40
- case "table": {
41
- return {
42
- ...pom,
43
- x: absoluteX,
44
- y: absoluteY,
45
- w: layout.width,
46
- h: layout.height,
47
- };
48
- }
49
- case "shape": {
50
- return {
51
- ...pom,
52
- x: absoluteX,
53
- y: absoluteY,
54
- w: layout.width,
55
- h: layout.height,
56
- };
57
- }
58
- case "chart": {
59
- return {
60
- ...pom,
61
- x: absoluteX,
62
- y: absoluteY,
63
- w: layout.width,
64
- h: layout.height,
65
- };
66
- }
67
- case "timeline": {
68
- return {
69
- ...pom,
70
- x: absoluteX,
71
- y: absoluteY,
72
- w: layout.width,
73
- h: layout.height,
74
- };
75
- }
76
- case "matrix": {
77
- return {
78
- ...pom,
79
- x: absoluteX,
80
- y: absoluteY,
81
- w: layout.width,
82
- h: layout.height,
83
- };
84
- }
85
- case "tree": {
86
- return {
87
- ...pom,
88
- x: absoluteX,
89
- y: absoluteY,
90
- w: layout.width,
91
- h: layout.height,
92
- };
93
- }
94
- case "flow": {
95
- return {
96
- ...pom,
97
- x: absoluteX,
98
- y: absoluteY,
99
- w: layout.width,
100
- h: layout.height,
101
- };
102
- }
103
- case "processArrow": {
104
- return {
105
- ...pom,
106
- x: absoluteX,
107
- y: absoluteY,
108
- w: layout.width,
109
- h: layout.height,
110
- };
111
- }
112
- case "pyramid": {
113
- return {
114
- ...pom,
115
- x: absoluteX,
116
- y: absoluteY,
117
- w: layout.width,
118
- h: layout.height,
119
- };
120
- }
121
- case "box": {
122
- return {
123
- ...pom,
124
- x: absoluteX,
125
- y: absoluteY,
126
- w: layout.width,
127
- h: layout.height,
128
- children: toPositioned(pom.children, absoluteX, absoluteY),
129
- };
130
- }
131
- case "vstack": {
132
- return {
133
- ...pom,
134
- x: absoluteX,
135
- y: absoluteY,
136
- w: layout.width,
137
- h: layout.height,
138
- children: pom.children.map((child) => toPositioned(child, absoluteX, absoluteY)),
139
- };
140
- }
141
- case "hstack": {
26
+ const def = getNodeDef(pom.type);
27
+ // ノード固有のカスタム変換がある場合はそれを使用
28
+ if (def.toPositioned) {
29
+ return def.toPositioned(pom, absoluteX, absoluteY, layout, ctx);
30
+ }
31
+ // category ベースのデフォルト処理
32
+ switch (def.category) {
33
+ case "leaf":
142
34
  return {
143
- ...pom,
35
+ ...omitYogaNode(pom),
144
36
  x: absoluteX,
145
37
  y: absoluteY,
146
38
  w: layout.width,
147
39
  h: layout.height,
148
- children: pom.children.map((child) => toPositioned(child, absoluteX, absoluteY)),
149
40
  };
150
- }
151
- case "icon": {
152
- const rasterSize = Math.max(Math.ceil(layout.width), Math.ceil(layout.height), pom.size ?? 24);
153
- const iconImageData = rasterizeIcon(pom.name, rasterSize, pom.color ?? "#000000");
41
+ case "single-child": {
42
+ const boxNode = pom;
154
43
  return {
155
- ...pom,
44
+ ...omitYogaNode(boxNode),
156
45
  x: absoluteX,
157
46
  y: absoluteY,
158
47
  w: layout.width,
159
48
  h: layout.height,
160
- iconImageData,
161
- };
162
- }
163
- case "line": {
164
- // line ノードは絶対座標(x1, y1, x2, y2)を持つため、
165
- // yogaNode の座標ではなく自身の座標からバウンディングボックスを計算
166
- return {
167
- ...pom,
168
- x: Math.min(pom.x1, pom.x2),
169
- y: Math.min(pom.y1, pom.y2),
170
- w: Math.abs(pom.x2 - pom.x1),
171
- h: Math.abs(pom.y2 - pom.y1),
49
+ children: toPositioned(boxNode.children, ctx, absoluteX, absoluteY),
172
50
  };
173
51
  }
174
- case "layer": {
175
- // layer の子要素は layer 内の相対座標(child.x, child.y)を持つ
176
- // layer の絶対座標に加算してスライド上の絶対座標に変換
52
+ case "multi-child": {
53
+ const containerNode = pom;
177
54
  return {
178
- ...pom,
55
+ ...omitYogaNode(containerNode),
179
56
  x: absoluteX,
180
57
  y: absoluteY,
181
58
  w: layout.width,
182
59
  h: layout.height,
183
- children: pom.children.map((child) => {
184
- // layer 内での子要素の絶対座標(child.x, child.y がない場合は 0)
185
- const childX = child.x ?? 0;
186
- const childY = child.y ?? 0;
187
- // line ノードは特別な処理が必要
188
- // x1, y1, x2, y2 は layer 内の相対座標として扱い、layer の座標を加算
189
- if (child.type === "line") {
190
- const lineAbsoluteX = absoluteX + childX;
191
- const lineAbsoluteY = absoluteY + childY;
192
- const adjustedX1 = child.x1 + lineAbsoluteX;
193
- const adjustedY1 = child.y1 + lineAbsoluteY;
194
- const adjustedX2 = child.x2 + lineAbsoluteX;
195
- const adjustedY2 = child.y2 + lineAbsoluteY;
196
- return {
197
- ...child,
198
- x1: adjustedX1,
199
- y1: adjustedY1,
200
- x2: adjustedX2,
201
- y2: adjustedY2,
202
- x: Math.min(adjustedX1, adjustedX2),
203
- y: Math.min(adjustedY1, adjustedY2),
204
- w: Math.abs(adjustedX2 - adjustedX1),
205
- h: Math.abs(adjustedY2 - adjustedY1),
206
- };
207
- }
208
- // その他のノードは通常の処理
209
- // Yoga で計算された子要素の相対座標を取得
210
- const childLayout = child.yogaNode.getComputedLayout();
211
- // 正しい親座標を計算: layer の座標 + child.x - Yoga の相対座標
212
- // こうすることで toPositioned 内で:
213
- // absoluteX = adjustedParentX + childLayout.left
214
- // = (absoluteX + child.x - childLayout.left) + childLayout.left
215
- // = absoluteX + child.x
216
- // となり、子要素とその内部の子要素が正しい座標で配置される
217
- const adjustedParentX = absoluteX + childX - childLayout.left;
218
- const adjustedParentY = absoluteY + childY - childLayout.top;
219
- return toPositioned(child, adjustedParentX, adjustedParentY);
220
- }),
60
+ children: containerNode.children.map((child) => toPositioned(child, ctx, absoluteX, absoluteY)),
221
61
  };
222
62
  }
63
+ case "absolute-child":
64
+ // absolute-child (layer) は必ずカスタム toPositioned を持つべき
65
+ throw new Error(`Node type "${pom.type}" with category "absolute-child" must have a custom toPositioned`);
223
66
  }
224
67
  }