@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.
- package/README.md +6 -5
- package/dist/autoFit/autoFit.d.ts +2 -1
- package/dist/autoFit/autoFit.d.ts.map +1 -1
- package/dist/autoFit/autoFit.js +33 -17
- package/dist/buildContext.d.ts +2 -0
- package/dist/buildContext.d.ts.map +1 -1
- package/dist/buildContext.js +2 -0
- package/dist/buildPptx.d.ts +7 -1
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +14 -5
- package/dist/calcYogaLayout/calcYogaLayout.d.ts +4 -2
- package/dist/calcYogaLayout/calcYogaLayout.d.ts.map +1 -1
- package/dist/calcYogaLayout/calcYogaLayout.js +29 -15
- package/dist/calcYogaLayout/types.d.ts +16 -0
- package/dist/calcYogaLayout/types.d.ts.map +1 -0
- package/dist/calcYogaLayout/types.js +14 -0
- package/dist/diagnostics.d.ts +14 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +17 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/parseXml/parseXml.d.ts +1 -1
- package/dist/parseXml/parseXml.d.ts.map +1 -1
- package/dist/parseXml/parseXml.js +16 -16
- package/dist/registry/definitions/icon.d.ts.map +1 -1
- package/dist/registry/definitions/icon.js +26 -14
- package/dist/registry/definitions/image.d.ts.map +1 -1
- package/dist/registry/definitions/image.js +2 -3
- package/dist/registry/definitions/layer.d.ts.map +1 -1
- package/dist/registry/definitions/layer.js +9 -6
- package/dist/registry/definitions/line.d.ts.map +1 -1
- package/dist/registry/definitions/line.js +1 -2
- package/dist/registry/types.d.ts +2 -1
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/renderPptx/nodes/chart.d.ts.map +1 -1
- package/dist/renderPptx/nodes/chart.js +6 -4
- package/dist/renderPptx/nodes/flow.d.ts.map +1 -1
- package/dist/renderPptx/nodes/flow.js +14 -4
- package/dist/renderPptx/nodes/image.d.ts.map +1 -1
- package/dist/renderPptx/nodes/image.js +8 -6
- package/dist/renderPptx/nodes/list.d.ts.map +1 -1
- package/dist/renderPptx/nodes/list.js +19 -16
- package/dist/renderPptx/nodes/matrix.d.ts.map +1 -1
- package/dist/renderPptx/nodes/matrix.js +11 -9
- package/dist/renderPptx/nodes/processArrow.d.ts.map +1 -1
- package/dist/renderPptx/nodes/processArrow.js +14 -4
- package/dist/renderPptx/nodes/pyramid.d.ts.map +1 -1
- package/dist/renderPptx/nodes/pyramid.js +6 -4
- package/dist/renderPptx/nodes/shape.d.ts.map +1 -1
- package/dist/renderPptx/nodes/shape.js +6 -4
- package/dist/renderPptx/nodes/table.d.ts.map +1 -1
- package/dist/renderPptx/nodes/table.js +7 -5
- package/dist/renderPptx/nodes/timeline.d.ts.map +1 -1
- package/dist/renderPptx/nodes/timeline.js +14 -4
- package/dist/renderPptx/nodes/tree.d.ts.map +1 -1
- package/dist/renderPptx/nodes/tree.js +6 -4
- package/dist/renderPptx/textOptions.d.ts.map +1 -1
- package/dist/renderPptx/textOptions.js +6 -4
- package/dist/renderPptx/utils/contentArea.d.ts +26 -0
- package/dist/renderPptx/utils/contentArea.d.ts.map +1 -0
- package/dist/renderPptx/utils/contentArea.js +26 -0
- package/dist/renderPptx/utils/scaleToFit.d.ts +3 -2
- package/dist/renderPptx/utils/scaleToFit.d.ts.map +1 -1
- package/dist/renderPptx/utils/scaleToFit.js +3 -3
- package/dist/shared/freeYogaTree.d.ts +3 -3
- package/dist/shared/freeYogaTree.d.ts.map +1 -1
- package/dist/shared/freeYogaTree.js +16 -21
- package/dist/shared/measureImage.d.ts +3 -2
- package/dist/shared/measureImage.d.ts.map +1 -1
- package/dist/shared/measureImage.js +5 -5
- package/dist/toPositioned/toPositioned.d.ts +3 -6
- package/dist/toPositioned/toPositioned.d.ts.map +1 -1
- package/dist/toPositioned/toPositioned.js +11 -19
- package/dist/types.d.ts +12 -445
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +43 -50
- package/package.json +5 -2
- package/dist/parseXml/inputSchema.d.ts +0 -1622
- package/dist/parseXml/inputSchema.d.ts.map +0 -1
- package/dist/parseXml/inputSchema.js +0 -257
package/README.md
CHANGED
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
|
|
36
36
|
## Features
|
|
37
37
|
|
|
38
|
-
- **AI Friendly** — Simple XML structure designed for LLM code generation.
|
|
38
|
+
- **AI Friendly** — Simple XML structure designed for LLM code generation. Include [llm.txt](./website/public/llm.txt) in your system prompt for XML reference. Also available at `https://pom.pptx.app/llm.txt`.
|
|
39
39
|
- **Declarative** — Describe slides as XML. No imperative API calls needed.
|
|
40
40
|
- **Flexible Layout** — Flexbox-style layout with VStack / HStack / Box, powered by yoga-layout.
|
|
41
|
-
- **Rich Nodes** —
|
|
41
|
+
- **Rich Nodes** — 19 built-in node types: charts, flowcharts, tables, timelines, org trees, and more.
|
|
42
42
|
- **Schema-validated** — XML input is validated with Zod schemas at runtime with clear error messages.
|
|
43
43
|
- **PowerPoint Native** — Full access to native PowerPoint shape features (roundRect, ellipse, arrows, etc.).
|
|
44
44
|
- **Pixel Units** — Intuitive pixel-based sizing (internally converted to inches at 96 DPI).
|
|
@@ -63,7 +63,7 @@ const xml = `
|
|
|
63
63
|
</VStack>
|
|
64
64
|
`;
|
|
65
65
|
|
|
66
|
-
const pptx = await buildPptx(xml, { w: 1280, h: 720 });
|
|
66
|
+
const { pptx } = await buildPptx(xml, { w: 1280, h: 720 });
|
|
67
67
|
await pptx.writeFile({ fileName: "presentation.pptx" });
|
|
68
68
|
```
|
|
69
69
|
|
|
@@ -89,6 +89,7 @@ await pptx.writeFile({ fileName: "presentation.pptx" });
|
|
|
89
89
|
| Box | Container for single child with padding |
|
|
90
90
|
| VStack | Vertical stack layout |
|
|
91
91
|
| HStack | Horizontal stack layout |
|
|
92
|
+
| Icon | Lucide icons |
|
|
92
93
|
|
|
93
94
|
For detailed node documentation, see [Nodes](./docs/nodes.md).
|
|
94
95
|
|
|
@@ -209,7 +210,7 @@ Adjustments are applied in the following priority order:
|
|
|
209
210
|
To disable:
|
|
210
211
|
|
|
211
212
|
```typescript
|
|
212
|
-
const pptx = await buildPptx(xml, { w: 1280, h: 720 }, { autoFit: false });
|
|
213
|
+
const { pptx } = await buildPptx(xml, { w: 1280, h: 720 }, { autoFit: false });
|
|
213
214
|
```
|
|
214
215
|
|
|
215
216
|
## Documentation
|
|
@@ -220,7 +221,7 @@ const pptx = await buildPptx(xml, { w: 1280, h: 720 }, { autoFit: false });
|
|
|
220
221
|
| [Nodes](./docs/nodes.md) | Complete reference for all node types |
|
|
221
222
|
| [Master Slide](./docs/master-slide.md) | Headers, footers, and page numbers |
|
|
222
223
|
| [Text Measurement](./docs/text-measurement.md) | Text measurement options and settings |
|
|
223
|
-
| [
|
|
224
|
+
| [llm.txt](./website/public/llm.txt) | Compact XML reference for LLM prompts |
|
|
224
225
|
| [Playground](https://pom.pptx.app/playground) | Try pom XML in the browser |
|
|
225
226
|
|
|
226
227
|
## License
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { POMNode } from "../types.ts";
|
|
2
2
|
import type { BuildContext } from "../buildContext.ts";
|
|
3
|
+
import type { YogaNodeMap } from "../calcYogaLayout/types.ts";
|
|
3
4
|
/**
|
|
4
5
|
* スライドのオーバーフローを検出し、段階的に調整してスライド内に収める。
|
|
5
6
|
*
|
|
@@ -12,5 +13,5 @@ import type { BuildContext } from "../buildContext.ts";
|
|
|
12
13
|
export declare function autoFitSlide(node: POMNode, slideSize: {
|
|
13
14
|
w: number;
|
|
14
15
|
h: number;
|
|
15
|
-
}, ctx: BuildContext): Promise<
|
|
16
|
+
}, ctx: BuildContext): Promise<YogaNodeMap>;
|
|
16
17
|
//# sourceMappingURL=autoFit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autoFit.d.ts","sourceRoot":"","sources":["../../src/autoFit/autoFit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"autoFit.d.ts","sourceRoot":"","sources":["../../src/autoFit/autoFit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AA6E9D;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,WAAW,CAAC,CAkBtB"}
|
package/dist/autoFit/autoFit.js
CHANGED
|
@@ -13,15 +13,27 @@ const strategies = [
|
|
|
13
13
|
uniformScale,
|
|
14
14
|
];
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* レイアウト計算を実行し、コンテンツのオーバーフロー状態を測定する。
|
|
17
|
+
*/
|
|
18
|
+
async function measureOverflow(node, slideSize, ctx) {
|
|
19
|
+
const map = await calcYogaLayout(node, slideSize, ctx);
|
|
20
|
+
const contentHeight = calcContentHeight(map, node);
|
|
21
|
+
const isOverflowing = contentHeight > slideSize.h * OVERFLOW_TOLERANCE;
|
|
22
|
+
const targetRatio = isOverflowing ? slideSize.h / contentHeight : 1;
|
|
23
|
+
return { contentHeight, isOverflowing, targetRatio, map };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Yoga レイアウト結果からコンテンツの占有高さを算出する。
|
|
17
27
|
*
|
|
18
28
|
* ルートの yogaNode の子要素の (top + height) の最大値を計算し、
|
|
19
29
|
* ルートの padding.bottom を加算してコンテンツの占有高さとする。
|
|
20
30
|
* h="max" や flexGrow の影響を受けず、正確なコンテンツ高さを返す。
|
|
21
31
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
32
|
+
function calcContentHeight(map, node) {
|
|
33
|
+
const rootYoga = map.get(node);
|
|
34
|
+
if (!rootYoga) {
|
|
35
|
+
throw new Error("YogaNode not found in map for root node");
|
|
36
|
+
}
|
|
25
37
|
const childCount = rootYoga.getChildCount();
|
|
26
38
|
if (childCount === 0) {
|
|
27
39
|
return rootYoga.getComputedHeight();
|
|
@@ -49,25 +61,29 @@ async function measureContentHeight(node, slideSize, ctx) {
|
|
|
49
61
|
* 4. 全体スケーリング(フォールバック)
|
|
50
62
|
*/
|
|
51
63
|
export async function autoFitSlide(node, slideSize, ctx) {
|
|
64
|
+
// Phase 1: 戦略を順次適用してオーバーフローを解消
|
|
52
65
|
for (const strategy of strategies) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (
|
|
66
|
+
const result = await measureOverflow(node, slideSize, ctx);
|
|
67
|
+
freeYogaTree(result.map);
|
|
68
|
+
if (!result.isOverflowing) {
|
|
56
69
|
break;
|
|
57
70
|
}
|
|
58
|
-
const
|
|
59
|
-
const changed = strategy(node, ratio);
|
|
71
|
+
const changed = strategy(node, result.targetRatio);
|
|
60
72
|
if (!changed) {
|
|
61
73
|
continue;
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
|
-
//
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
// Phase 2: 最終レイアウト計算とオーバーフロー検証
|
|
77
|
+
return finalizeLayout(node, slideSize, ctx);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 最終レイアウトを計算し、オーバーフローが残っていれば警告を出力する。
|
|
81
|
+
*/
|
|
82
|
+
async function finalizeLayout(node, slideSize, ctx) {
|
|
83
|
+
const result = await measureOverflow(node, slideSize, ctx);
|
|
84
|
+
if (result.isOverflowing) {
|
|
85
|
+
ctx.diagnostics.add("AUTOFIT_OVERFLOW", `autoFit: content height (${Math.round(result.contentHeight)}px) exceeds slide height (${slideSize.h}px) after all adjustments.`);
|
|
69
86
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
await calcYogaLayout(node, slideSize, ctx);
|
|
87
|
+
freeYogaTree(result.map);
|
|
88
|
+
return calcYogaLayout(node, slideSize, ctx);
|
|
73
89
|
}
|
package/dist/buildContext.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { TextMeasurementMode } from "./calcYogaLayout/measureText.ts";
|
|
2
|
+
import { DiagnosticCollector } from "./diagnostics.ts";
|
|
2
3
|
export interface BuildContext {
|
|
3
4
|
textMeasurementMode: TextMeasurementMode;
|
|
4
5
|
imageSizeCache: Map<string, {
|
|
@@ -7,6 +8,7 @@ export interface BuildContext {
|
|
|
7
8
|
}>;
|
|
8
9
|
imageDataCache: Map<string, string>;
|
|
9
10
|
iconRasterCache: Map<string, string>;
|
|
11
|
+
diagnostics: DiagnosticCollector;
|
|
10
12
|
}
|
|
11
13
|
export declare function createBuildContext(textMeasurementMode?: TextMeasurementMode): BuildContext;
|
|
12
14
|
//# sourceMappingURL=buildContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildContext.d.ts","sourceRoot":"","sources":["../src/buildContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"buildContext.d.ts","sourceRoot":"","sources":["../src/buildContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,MAAM,WAAW,YAAY;IAC3B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnE,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,WAAW,EAAE,mBAAmB,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAChC,mBAAmB,GAAE,mBAA4B,GAChD,YAAY,CAQd"}
|
package/dist/buildContext.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { DiagnosticCollector } from "./diagnostics.js";
|
|
1
2
|
export function createBuildContext(textMeasurementMode = "auto") {
|
|
2
3
|
return {
|
|
3
4
|
textMeasurementMode,
|
|
4
5
|
imageSizeCache: new Map(),
|
|
5
6
|
imageDataCache: new Map(),
|
|
6
7
|
iconRasterCache: new Map(),
|
|
8
|
+
diagnostics: new DiagnosticCollector(),
|
|
7
9
|
};
|
|
8
10
|
}
|
package/dist/buildPptx.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { TextMeasurementMode } from "./calcYogaLayout/measureText.ts";
|
|
2
|
+
import type { Diagnostic } from "./diagnostics.ts";
|
|
2
3
|
import { SlideMasterOptions } from "./types.ts";
|
|
3
4
|
export type { TextMeasurementMode };
|
|
5
|
+
export interface BuildPptxResult {
|
|
6
|
+
pptx: import("pptxgenjs").default;
|
|
7
|
+
diagnostics: Diagnostic[];
|
|
8
|
+
}
|
|
4
9
|
export declare function buildPptx(xml: string, slideSize: {
|
|
5
10
|
w: number;
|
|
6
11
|
h: number;
|
|
@@ -8,5 +13,6 @@ export declare function buildPptx(xml: string, slideSize: {
|
|
|
8
13
|
master?: SlideMasterOptions;
|
|
9
14
|
textMeasurement?: TextMeasurementMode;
|
|
10
15
|
autoFit?: boolean;
|
|
11
|
-
|
|
16
|
+
strict?: boolean;
|
|
17
|
+
}): Promise<BuildPptxResult>;
|
|
12
18
|
//# sourceMappingURL=buildPptx.d.ts.map
|
package/dist/buildPptx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildPptx.d.ts","sourceRoot":"","sources":["../src/buildPptx.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"buildPptx.d.ts","sourceRoot":"","sources":["../src/buildPptx.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAG3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD,OAAO,EAAkB,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhE,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,WAAW,EAAE,OAAO,CAAC;IAClC,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,eAAe,CAAC,EAAE,mBAAmB,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GACA,OAAO,CAAC,eAAe,CAAC,CA8B1B"}
|
package/dist/buildPptx.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { autoFitSlide } from "./autoFit/autoFit.js";
|
|
2
2
|
import { createBuildContext } from "./buildContext.js";
|
|
3
3
|
import { calcYogaLayout } from "./calcYogaLayout/calcYogaLayout.js";
|
|
4
|
+
import { extractLayoutResults } from "./calcYogaLayout/types.js";
|
|
5
|
+
import { DiagnosticsError } from "./diagnostics.js";
|
|
4
6
|
import { parseXml } from "./parseXml/parseXml.js";
|
|
5
7
|
import { renderPptx } from "./renderPptx/renderPptx.js";
|
|
6
8
|
import { freeYogaTree } from "./shared/freeYogaTree.js";
|
|
@@ -10,20 +12,27 @@ export async function buildPptx(xml, slideSize, options) {
|
|
|
10
12
|
const nodes = parseXml(xml);
|
|
11
13
|
const positionedPages = [];
|
|
12
14
|
for (const node of nodes) {
|
|
15
|
+
let map;
|
|
13
16
|
try {
|
|
14
17
|
if (options?.autoFit !== false) {
|
|
15
|
-
await autoFitSlide(node, slideSize, ctx);
|
|
18
|
+
map = await autoFitSlide(node, slideSize, ctx);
|
|
16
19
|
}
|
|
17
20
|
else {
|
|
18
|
-
await calcYogaLayout(node, slideSize, ctx);
|
|
21
|
+
map = await calcYogaLayout(node, slideSize, ctx);
|
|
19
22
|
}
|
|
20
|
-
const
|
|
23
|
+
const layoutMap = extractLayoutResults(map);
|
|
24
|
+
const positioned = toPositioned(node, ctx, layoutMap);
|
|
21
25
|
positionedPages.push(positioned);
|
|
22
26
|
}
|
|
23
27
|
finally {
|
|
24
|
-
|
|
28
|
+
if (map)
|
|
29
|
+
freeYogaTree(map);
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
const pptx = renderPptx(positionedPages, slideSize, ctx, options?.master);
|
|
28
|
-
|
|
33
|
+
const diagnostics = ctx.diagnostics.items;
|
|
34
|
+
if (options?.strict && diagnostics.length > 0) {
|
|
35
|
+
throw new DiagnosticsError(diagnostics);
|
|
36
|
+
}
|
|
37
|
+
return { pptx, diagnostics };
|
|
29
38
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import type { POMNode } from "../types.ts";
|
|
2
2
|
import type { BuildContext } from "../buildContext.ts";
|
|
3
|
+
import type { YogaNodeMap } from "./types.ts";
|
|
3
4
|
/**
|
|
4
5
|
* POMNode ツリーを Yoga でレイアウト計算する
|
|
5
|
-
* POMNode
|
|
6
|
+
* POMNode と YogaNode の対応を YogaNodeMap として返す
|
|
6
7
|
*
|
|
7
8
|
* @param root 入力 POMNode ツリーのルート
|
|
8
9
|
* @param slideSize スライド全体のサイズ(px)
|
|
9
10
|
* @param ctx BuildContext
|
|
11
|
+
* @returns YogaNodeMap(POMNode → YogaNode のマッピング)
|
|
10
12
|
*/
|
|
11
13
|
export declare function calcYogaLayout(root: POMNode, slideSize: {
|
|
12
14
|
w: number;
|
|
13
15
|
h: number;
|
|
14
|
-
}, ctx: BuildContext): Promise<
|
|
16
|
+
}, ctx: BuildContext): Promise<YogaNodeMap>;
|
|
15
17
|
//# sourceMappingURL=calcYogaLayout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"calcYogaLayout.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/calcYogaLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"calcYogaLayout.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/calcYogaLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAO9C;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EACnC,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,WAAW,CAAC,CA0BtB"}
|
|
@@ -1,32 +1,43 @@
|
|
|
1
1
|
import { loadYoga } from "yoga-layout/load";
|
|
2
2
|
import { prefetchImageSize } from "../shared/measureImage.js";
|
|
3
|
+
import { freeYogaTree } from "../shared/freeYogaTree.js";
|
|
3
4
|
import { getNodeDef } from "../registry/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* POMNode ツリーを Yoga でレイアウト計算する
|
|
6
|
-
* POMNode
|
|
7
|
+
* POMNode と YogaNode の対応を YogaNodeMap として返す
|
|
7
8
|
*
|
|
8
9
|
* @param root 入力 POMNode ツリーのルート
|
|
9
10
|
* @param slideSize スライド全体のサイズ(px)
|
|
10
11
|
* @param ctx BuildContext
|
|
12
|
+
* @returns YogaNodeMap(POMNode → YogaNode のマッピング)
|
|
11
13
|
*/
|
|
12
14
|
export async function calcYogaLayout(root, slideSize, ctx) {
|
|
13
15
|
const Yoga = await getYoga();
|
|
14
16
|
// 事前に全画像のサイズを取得(HTTPS対応のため)
|
|
15
17
|
await prefetchAllImageSizes(root, ctx);
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
const map = new Map();
|
|
19
|
+
try {
|
|
20
|
+
const rootYoga = Yoga.Node.create();
|
|
21
|
+
map.set(root, rootYoga);
|
|
22
|
+
await buildPomWithYogaTree(root, rootYoga, ctx, map);
|
|
23
|
+
// スライド全体サイズを指定
|
|
24
|
+
rootYoga.setWidth(slideSize.w);
|
|
25
|
+
rootYoga.setHeight(slideSize.h);
|
|
26
|
+
rootYoga.calculateLayout(slideSize.w, slideSize.h, Yoga.DIRECTION_LTR);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
// 途中で失敗した場合、作成済みの YogaNode を解放してから再 throw
|
|
30
|
+
freeYogaTree(map);
|
|
31
|
+
throw e;
|
|
32
|
+
}
|
|
33
|
+
return map;
|
|
23
34
|
}
|
|
24
35
|
/**
|
|
25
36
|
* POMNode ツリー内のすべての画像のサイズを事前取得する
|
|
26
37
|
*/
|
|
27
38
|
async function prefetchAllImageSizes(node, ctx) {
|
|
28
39
|
const imageSources = collectImageSources(node);
|
|
29
|
-
await Promise.all(imageSources.map((src) => prefetchImageSize(src, ctx.imageSizeCache, ctx.imageDataCache)));
|
|
40
|
+
await Promise.all(imageSources.map((src) => prefetchImageSize(src, ctx.imageSizeCache, ctx.imageDataCache, ctx.diagnostics)));
|
|
30
41
|
}
|
|
31
42
|
/**
|
|
32
43
|
* POMNode ツリー内のすべての画像のsrcを収集する
|
|
@@ -75,21 +86,24 @@ async function getYoga() {
|
|
|
75
86
|
/**
|
|
76
87
|
* POMNode ツリーを再帰的に走査し、YogaNode ツリーを構築する
|
|
77
88
|
*/
|
|
78
|
-
async function buildPomWithYogaTree(node, parentYoga, ctx, parentNode) {
|
|
89
|
+
async function buildPomWithYogaTree(node, parentYoga, ctx, map, parentNode) {
|
|
79
90
|
const yoga = await getYoga();
|
|
80
91
|
const yn = yoga.Node.create();
|
|
81
|
-
node
|
|
92
|
+
map.set(node, yn); // 対応する YogaNode をマップに登録
|
|
82
93
|
await applyStyleToYogaNode(node, yn, ctx);
|
|
83
94
|
// HStack/VStack の子要素に flexShrink=1 をデフォルト設定(CSS Flexbox と同じ挙動)
|
|
84
95
|
// 主軸方向で %サイズ + gap がある場合の overflow を防ぐ
|
|
96
|
+
// アイコンは固定サイズのコンテンツなので shrink させない
|
|
85
97
|
if (parentNode?.type === "hstack" || parentNode?.type === "vstack") {
|
|
86
|
-
yn.setFlexShrink(1);
|
|
98
|
+
yn.setFlexShrink(node.type === "icon" ? 0 : 1);
|
|
87
99
|
}
|
|
88
100
|
// HStack の子要素で幅が指定されていない場合、デフォルトで均等分割
|
|
89
101
|
// テーブルは setMeasureFunc でカラム幅合計を返すため除外
|
|
102
|
+
// アイコンは固定サイズのコンテンツなので除外
|
|
90
103
|
if (parentNode?.type === "hstack" &&
|
|
91
104
|
node.w === undefined &&
|
|
92
|
-
node.type !== "table"
|
|
105
|
+
node.type !== "table" &&
|
|
106
|
+
node.type !== "icon") {
|
|
93
107
|
yn.setFlexGrow(1);
|
|
94
108
|
yn.setFlexBasis(0);
|
|
95
109
|
}
|
|
@@ -98,14 +112,14 @@ async function buildPomWithYogaTree(node, parentYoga, ctx, parentNode) {
|
|
|
98
112
|
switch (def.category) {
|
|
99
113
|
case "single-child": {
|
|
100
114
|
const boxNode = node;
|
|
101
|
-
await buildPomWithYogaTree(boxNode.children, yn, ctx, node);
|
|
115
|
+
await buildPomWithYogaTree(boxNode.children, yn, ctx, map, node);
|
|
102
116
|
break;
|
|
103
117
|
}
|
|
104
118
|
case "multi-child":
|
|
105
119
|
case "absolute-child": {
|
|
106
120
|
const containerNode = node;
|
|
107
121
|
for (const child of containerNode.children) {
|
|
108
|
-
await buildPomWithYogaTree(child, yn, ctx, node);
|
|
122
|
+
await buildPomWithYogaTree(child, yn, ctx, map, node);
|
|
109
123
|
}
|
|
110
124
|
break;
|
|
111
125
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Node as YogaNode } from "yoga-layout";
|
|
2
|
+
import type { POMNode } from "../types.ts";
|
|
3
|
+
/** POMNode と対応する YogaNode のマッピング。レイアウト計算フェーズでのみ存在する */
|
|
4
|
+
export type YogaNodeMap = Map<POMNode, YogaNode>;
|
|
5
|
+
/** Yoga 計算結果の軽量表現。Yoga ランタイムへの依存なし */
|
|
6
|
+
export interface LayoutResult {
|
|
7
|
+
left: number;
|
|
8
|
+
top: number;
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
}
|
|
12
|
+
/** POMNode と計算済みレイアウト結果のマッピング */
|
|
13
|
+
export type LayoutResultMap = Map<POMNode, LayoutResult>;
|
|
14
|
+
/** YogaNodeMap から計算済みレイアウト結果を抽出する */
|
|
15
|
+
export declare function extractLayoutResults(yogaMap: YogaNodeMap): LayoutResultMap;
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,uDAAuD;AACvD,MAAM,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAEjD,sCAAsC;AACtC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iCAAiC;AACjC,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAEzD,qCAAqC;AACrC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG,eAAe,CAY1E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** YogaNodeMap から計算済みレイアウト結果を抽出する */
|
|
2
|
+
export function extractLayoutResults(yogaMap) {
|
|
3
|
+
const layoutMap = new Map();
|
|
4
|
+
for (const [pomNode, yogaNode] of yogaMap) {
|
|
5
|
+
const computed = yogaNode.getComputedLayout();
|
|
6
|
+
layoutMap.set(pomNode, {
|
|
7
|
+
left: computed.left,
|
|
8
|
+
top: computed.top,
|
|
9
|
+
width: computed.width,
|
|
10
|
+
height: computed.height,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return layoutMap;
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DiagnosticCode = "IMAGE_MEASURE_FAILED" | "IMAGE_NOT_PREFETCHED" | "AUTOFIT_OVERFLOW" | "SCALE_BELOW_THRESHOLD";
|
|
2
|
+
export interface Diagnostic {
|
|
3
|
+
code: DiagnosticCode;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export declare class DiagnosticCollector {
|
|
7
|
+
readonly items: Diagnostic[];
|
|
8
|
+
add(code: DiagnosticCode, message: string): void;
|
|
9
|
+
}
|
|
10
|
+
export declare class DiagnosticsError extends Error {
|
|
11
|
+
readonly diagnostics: Diagnostic[];
|
|
12
|
+
constructor(diagnostics: Diagnostic[]);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB,sBAAsB,GACtB,sBAAsB,GACtB,kBAAkB,GAClB,uBAAuB,CAAC;AAE5B,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,mBAAmB;IAC9B,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,CAAM;IAElC,GAAG,CAAC,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;CAGjD;AAED,qBAAa,gBAAiB,SAAQ,KAAK;aACb,WAAW,EAAE,UAAU,EAAE;gBAAzB,WAAW,EAAE,UAAU,EAAE;CAOtD"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class DiagnosticCollector {
|
|
2
|
+
items = [];
|
|
3
|
+
add(code, message) {
|
|
4
|
+
this.items.push({ code, message });
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class DiagnosticsError extends Error {
|
|
8
|
+
diagnostics;
|
|
9
|
+
constructor(diagnostics) {
|
|
10
|
+
const summary = diagnostics
|
|
11
|
+
.map((d) => `[${d.code}] ${d.message}`)
|
|
12
|
+
.join("\n");
|
|
13
|
+
super(`Build completed with diagnostics:\n${summary}`);
|
|
14
|
+
this.diagnostics = diagnostics;
|
|
15
|
+
this.name = "DiagnosticsError";
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { buildPptx } from "./buildPptx.ts";
|
|
2
|
-
export type { TextMeasurementMode } from "./buildPptx.ts";
|
|
2
|
+
export type { BuildPptxResult, TextMeasurementMode } from "./buildPptx.ts";
|
|
3
|
+
export { DiagnosticsError } from "./diagnostics.ts";
|
|
4
|
+
export type { Diagnostic, DiagnosticCode } from "./diagnostics.ts";
|
|
3
5
|
export { ParseXmlError } from "./parseXml/parseXml.ts";
|
|
4
6
|
export type { SlideMasterOptions, SlideMasterBackground, SlideMasterMargin, MasterObject, MasterTextObject, MasterImageObject, MasterRectObject, MasterLineObject, SlideNumberOptions, } from "./types.ts";
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseXml.d.ts","sourceRoot":"","sources":["../../src/parseXml/parseXml.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"parseXml.d.ts","sourceRoot":"","sources":["../../src/parseXml/parseXml.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,OAAO,EAgBb,MAAM,aAAa,CAAC;AAYrB,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAgB,MAAM,EAAE,MAAM,EAAE,CAAC;gBACrB,MAAM,EAAE,MAAM,EAAE;CAM7B;AAm6BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAiCrD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { XMLParser } from "fast-xml-parser";
|
|
2
|
-
import {
|
|
2
|
+
import { textNodeSchema, ulNodeSchema, olNodeSchema, imageNodeSchema, tableNodeSchema, shapeNodeSchema, chartNodeSchema, timelineNodeSchema, matrixNodeSchema, treeNodeSchema, flowNodeSchema, processArrowNodeSchema, pyramidNodeSchema, lineNodeSchema, iconNodeSchema, } from "../types.js";
|
|
3
3
|
import { NODE_COERCION_MAP, CHILD_ELEMENT_COERCION_MAP, coerceWithRule, coerceFallback, getObjectShapeFromRule, isBooleanObjectUnionRule, } from "./coercionRules.js";
|
|
4
4
|
// ===== ParseXmlError =====
|
|
5
5
|
export class ParseXmlError extends Error {
|
|
@@ -85,21 +85,21 @@ function getKnownChildAttributes(tagName) {
|
|
|
85
85
|
}
|
|
86
86
|
// ===== Leaf node Zod validation schemas =====
|
|
87
87
|
const leafNodeValidationSchemas = {
|
|
88
|
-
text:
|
|
89
|
-
image:
|
|
90
|
-
table:
|
|
91
|
-
shape:
|
|
92
|
-
chart:
|
|
93
|
-
timeline:
|
|
94
|
-
matrix:
|
|
95
|
-
tree:
|
|
96
|
-
flow:
|
|
97
|
-
processArrow:
|
|
98
|
-
pyramid:
|
|
99
|
-
line:
|
|
100
|
-
ul:
|
|
101
|
-
ol:
|
|
102
|
-
icon:
|
|
88
|
+
text: textNodeSchema,
|
|
89
|
+
image: imageNodeSchema,
|
|
90
|
+
table: tableNodeSchema,
|
|
91
|
+
shape: shapeNodeSchema,
|
|
92
|
+
chart: chartNodeSchema,
|
|
93
|
+
timeline: timelineNodeSchema,
|
|
94
|
+
matrix: matrixNodeSchema,
|
|
95
|
+
tree: treeNodeSchema,
|
|
96
|
+
flow: flowNodeSchema,
|
|
97
|
+
processArrow: processArrowNodeSchema,
|
|
98
|
+
pyramid: pyramidNodeSchema,
|
|
99
|
+
line: lineNodeSchema,
|
|
100
|
+
ul: ulNodeSchema,
|
|
101
|
+
ol: olNodeSchema,
|
|
102
|
+
icon: iconNodeSchema,
|
|
103
103
|
};
|
|
104
104
|
function formatZodIssue(issue, tagName) {
|
|
105
105
|
const path = issue.path;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,eAAO,MAAM,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/icon.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,eAAO,MAAM,WAAW,EAAE,cAqEzB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { rasterizeIcon } from "../../icons/index.js";
|
|
2
|
-
import { omitYogaNode } from "../../toPositioned/toPositioned.js";
|
|
3
2
|
import { renderIconNode } from "../../renderPptx/nodes/icon.js";
|
|
3
|
+
import { getContentArea } from "../../renderPptx/utils/contentArea.js";
|
|
4
4
|
export const iconNodeDef = {
|
|
5
5
|
type: "icon",
|
|
6
6
|
category: "leaf",
|
|
@@ -14,11 +14,19 @@ export const iconNodeDef = {
|
|
|
14
14
|
toPositioned(pom, absoluteX, absoluteY, layout, ctx) {
|
|
15
15
|
const n = pom;
|
|
16
16
|
const iconSize = n.size ?? 24;
|
|
17
|
-
|
|
17
|
+
// padding を考慮したコンテンツ領域で bg/icon の座標を計算
|
|
18
|
+
const content = getContentArea({
|
|
19
|
+
x: absoluteX,
|
|
20
|
+
y: absoluteY,
|
|
21
|
+
w: layout.width,
|
|
22
|
+
h: layout.height,
|
|
23
|
+
padding: n.padding,
|
|
24
|
+
});
|
|
25
|
+
// 実描画サイズに合わせてラスタライズ(不要に大きい PNG を防ぐ)
|
|
26
|
+
const rasterSize = Math.max(Math.ceil(n.variant ? iconSize : Math.min(content.w, content.h)), iconSize);
|
|
18
27
|
const iconImageData = rasterizeIcon(n.name, rasterSize, n.color ?? "#000000", ctx.iconRasterCache);
|
|
19
|
-
// variant 指定時はアイコンを中央に配置
|
|
20
28
|
const positioned = {
|
|
21
|
-
...
|
|
29
|
+
...n,
|
|
22
30
|
x: absoluteX,
|
|
23
31
|
y: absoluteY,
|
|
24
32
|
w: layout.width,
|
|
@@ -27,21 +35,25 @@ export const iconNodeDef = {
|
|
|
27
35
|
};
|
|
28
36
|
if (n.variant) {
|
|
29
37
|
const totalSize = Math.ceil(iconSize * 1.75);
|
|
30
|
-
// 背景図形は totalSize
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
positioned.bgX = absoluteX + bgOffsetX;
|
|
34
|
-
positioned.bgY = absoluteY + bgOffsetY;
|
|
38
|
+
// 背景図形は totalSize の正方形として、コンテンツ領域の中央に配置
|
|
39
|
+
positioned.bgX = content.x + (content.w - totalSize) / 2;
|
|
40
|
+
positioned.bgY = content.y + (content.h - totalSize) / 2;
|
|
35
41
|
positioned.bgW = totalSize;
|
|
36
42
|
positioned.bgH = totalSize;
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
positioned.iconX = absoluteX + iconOffsetX;
|
|
41
|
-
positioned.iconY = absoluteY + iconOffsetY;
|
|
43
|
+
// アイコンはコンテンツ領域の中央に配置
|
|
44
|
+
positioned.iconX = content.x + (content.w - iconSize) / 2;
|
|
45
|
+
positioned.iconY = content.y + (content.h - iconSize) / 2;
|
|
42
46
|
positioned.iconW = iconSize;
|
|
43
47
|
positioned.iconH = iconSize;
|
|
44
48
|
}
|
|
49
|
+
else {
|
|
50
|
+
// variant なしの場合もアスペクト比を維持し、コンテンツ領域の中央に配置
|
|
51
|
+
const iconSide = Math.min(content.w, content.h);
|
|
52
|
+
positioned.iconX = content.x + (content.w - iconSide) / 2;
|
|
53
|
+
positioned.iconY = content.y + (content.h - iconSide) / 2;
|
|
54
|
+
positioned.iconW = iconSide;
|
|
55
|
+
positioned.iconH = iconSide;
|
|
56
|
+
}
|
|
45
57
|
return positioned;
|
|
46
58
|
},
|
|
47
59
|
render(node, ctx) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/image.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAQ,MAAM,aAAa,CAAC;AAMxD,eAAO,MAAM,YAAY,EAAE,cAmC1B,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { measureImage, getImageData } from "../../shared/measureImage.js";
|
|
2
2
|
import { renderImageNode } from "../../renderPptx/nodes/image.js";
|
|
3
|
-
import { omitYogaNode } from "../../toPositioned/toPositioned.js";
|
|
4
3
|
export const imageNodeDef = {
|
|
5
4
|
type: "image",
|
|
6
5
|
category: "leaf",
|
|
@@ -8,7 +7,7 @@ export const imageNodeDef = {
|
|
|
8
7
|
const n = node;
|
|
9
8
|
const src = n.src;
|
|
10
9
|
yn.setMeasureFunc(() => {
|
|
11
|
-
const { widthPx, heightPx } = measureImage(src, ctx.imageSizeCache);
|
|
10
|
+
const { widthPx, heightPx } = measureImage(src, ctx.imageSizeCache, ctx.diagnostics);
|
|
12
11
|
return { width: widthPx, height: heightPx };
|
|
13
12
|
});
|
|
14
13
|
},
|
|
@@ -16,7 +15,7 @@ export const imageNodeDef = {
|
|
|
16
15
|
const n = pom;
|
|
17
16
|
const imageData = getImageData(n.src, ctx.imageDataCache);
|
|
18
17
|
return {
|
|
19
|
-
...
|
|
18
|
+
...n,
|
|
20
19
|
x: absoluteX,
|
|
21
20
|
y: absoluteY,
|
|
22
21
|
w: layout.width,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/layer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../../src/registry/definitions/layer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD,eAAO,MAAM,YAAY,EAAE,cA4D1B,CAAC"}
|