@hirokisakabe/pom 1.3.0 → 2.0.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 +22 -150
- package/dist/buildPptx.d.ts +2 -2
- package/dist/buildPptx.d.ts.map +1 -1
- package/dist/buildPptx.js +3 -1
- package/dist/calcYogaLayout/fontLoader.d.ts +0 -7
- package/dist/calcYogaLayout/fontLoader.d.ts.map +1 -1
- package/dist/calcYogaLayout/fontLoader.js +1 -1
- package/dist/calcYogaLayout/measureText.d.ts +0 -4
- package/dist/calcYogaLayout/measureText.d.ts.map +1 -1
- package/dist/calcYogaLayout/measureText.js +0 -6
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/inputSchema.d.ts +3 -438
- package/dist/inputSchema.d.ts.map +1 -1
- package/dist/inputSchema.js +6 -138
- package/dist/parseXml.d.ts +28 -0
- package/dist/parseXml.d.ts.map +1 -0
- package/dist/parseXml.js +795 -0
- package/dist/renderPptx/renderPptx.d.ts +1 -2
- package/dist/renderPptx/renderPptx.d.ts.map +1 -1
- package/dist/renderPptx/renderPptx.js +0 -2
- package/dist/renderPptx/textOptions.d.ts +0 -1
- package/dist/renderPptx/textOptions.d.ts.map +1 -1
- package/dist/renderPptx/textOptions.js +1 -1
- package/dist/renderPptx/types.d.ts +0 -2
- package/dist/renderPptx/types.d.ts.map +1 -1
- package/dist/table/utils.d.ts +0 -2
- package/dist/table/utils.d.ts.map +1 -1
- package/dist/table/utils.js +2 -2
- package/dist/types.d.ts +13 -121
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +21 -27
- package/package.json +4 -6
- package/dist/component.d.ts +0 -90
- package/dist/component.d.ts.map +0 -1
- package/dist/component.js +0 -123
- package/dist/renderPptx/nodes/box.d.ts +0 -2
- package/dist/renderPptx/nodes/box.d.ts.map +0 -1
- package/dist/renderPptx/nodes/box.js +0 -3
- package/dist/renderPptx/utils/index.d.ts +0 -6
- package/dist/renderPptx/utils/index.d.ts.map +0 -1
- package/dist/renderPptx/utils/index.js +0 -3
- package/dist/renderPptx/utils/shapeDrawing.d.ts +0 -27
- package/dist/renderPptx/utils/shapeDrawing.d.ts.map +0 -1
- package/dist/renderPptx/utils/shapeDrawing.js +0 -36
- package/dist/renderPptx/utils/textDrawing.d.ts +0 -25
- package/dist/renderPptx/utils/textDrawing.d.ts.map +0 -1
- package/dist/renderPptx/utils/textDrawing.js +0 -25
- package/dist/schema.d.ts +0 -23
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js +0 -24
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# pom
|
|
2
2
|
|
|
3
|
-
**pom (PowerPoint Object Model)** is a library for declaratively describing PowerPoint presentations (pptx) in TypeScript. It is designed for use cases where
|
|
3
|
+
**pom (PowerPoint Object Model)** is a library for declaratively describing PowerPoint presentations (pptx) in TypeScript. It is designed for use cases where XML in POM format generated by AI is converted into PowerPoint files.
|
|
4
|
+
|
|
5
|
+
> **[Try it online](https://pom-playground.vercel.app/)** — XML Playground
|
|
4
6
|
|
|
5
7
|
## Requirements
|
|
6
8
|
|
|
@@ -19,39 +21,23 @@ npm install @hirokisakabe/pom
|
|
|
19
21
|
## Quick Start
|
|
20
22
|
|
|
21
23
|
```typescript
|
|
22
|
-
import { buildPptx
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
{
|
|
33
|
-
type: "text",
|
|
34
|
-
text: "Presentation Title",
|
|
35
|
-
fontPx: 48,
|
|
36
|
-
bold: true,
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
type: "text",
|
|
40
|
-
text: "Subtitle",
|
|
41
|
-
fontPx: 24,
|
|
42
|
-
color: "666666",
|
|
43
|
-
},
|
|
44
|
-
],
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const pptx = await buildPptx([slide], { w: 1280, h: 720 });
|
|
24
|
+
import { buildPptx } from "@hirokisakabe/pom";
|
|
25
|
+
|
|
26
|
+
const xml = `
|
|
27
|
+
<VStack w="100%" h="max" padding="48" gap="24" alignItems="start">
|
|
28
|
+
<Text fontPx="48" bold="true">Presentation Title</Text>
|
|
29
|
+
<Text fontPx="24" color="666666">Subtitle</Text>
|
|
30
|
+
</VStack>
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const pptx = await buildPptx(xml, { w: 1280, h: 720 });
|
|
48
34
|
await pptx.writeFile({ fileName: "presentation.pptx" });
|
|
49
35
|
```
|
|
50
36
|
|
|
51
37
|
## Features
|
|
52
38
|
|
|
53
|
-
- **
|
|
54
|
-
- **Declarative**: Describe slides with
|
|
39
|
+
- **Schema-validated**: XML input validated with Zod schemas at runtime
|
|
40
|
+
- **Declarative**: Describe slides with XML
|
|
55
41
|
- **PowerPoint First**: Native support for Shape features
|
|
56
42
|
- **Flexible Layout**: Automatic layout with VStack/HStack/Box
|
|
57
43
|
- **Pixel Units**: Intuitive pixel-based sizing (internally converted to inches)
|
|
@@ -78,129 +64,15 @@ await pptx.writeFile({ fileName: "presentation.pptx" });
|
|
|
78
64
|
|
|
79
65
|
For detailed node documentation, see [Nodes Reference](./docs/nodes.md).
|
|
80
66
|
|
|
81
|
-
## Components
|
|
82
|
-
|
|
83
|
-
pom provides a `defineComponent` helper for creating reusable component templates. Components are simple functions that take props and return a `POMNode` — no runtime magic, no new node types.
|
|
84
|
-
|
|
85
|
-
```typescript
|
|
86
|
-
import { defineComponent, mergeTheme, POMNode, Theme } from "@hirokisakabe/pom";
|
|
87
|
-
|
|
88
|
-
// Define a reusable card component
|
|
89
|
-
const SectionCard = defineComponent<{
|
|
90
|
-
title: string;
|
|
91
|
-
content: POMNode; // Slot: any POMNode
|
|
92
|
-
theme?: Partial<Theme>; // Theme override
|
|
93
|
-
}>((props) => {
|
|
94
|
-
const t = mergeTheme(props.theme);
|
|
95
|
-
return {
|
|
96
|
-
type: "box",
|
|
97
|
-
padding: t.spacing.md,
|
|
98
|
-
backgroundColor: "FFFFFF",
|
|
99
|
-
border: { color: t.colors.border, width: 1 },
|
|
100
|
-
borderRadius: 8,
|
|
101
|
-
children: {
|
|
102
|
-
type: "vstack",
|
|
103
|
-
gap: t.spacing.sm,
|
|
104
|
-
children: [
|
|
105
|
-
{
|
|
106
|
-
type: "text",
|
|
107
|
-
text: props.title,
|
|
108
|
-
fontPx: t.fontPx.heading,
|
|
109
|
-
bold: true,
|
|
110
|
-
},
|
|
111
|
-
props.content,
|
|
112
|
-
],
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
// Use the component
|
|
118
|
-
const slide: POMNode = {
|
|
119
|
-
type: "vstack",
|
|
120
|
-
w: 1280,
|
|
121
|
-
h: 720,
|
|
122
|
-
padding: 48,
|
|
123
|
-
gap: 24,
|
|
124
|
-
children: [
|
|
125
|
-
SectionCard({
|
|
126
|
-
title: "Revenue",
|
|
127
|
-
content: { type: "text", text: "$1,000,000" },
|
|
128
|
-
}),
|
|
129
|
-
SectionCard({
|
|
130
|
-
title: "Custom Theme",
|
|
131
|
-
content: { type: "text", text: "Styled card" },
|
|
132
|
-
theme: { colors: { border: "CBD5E1" } },
|
|
133
|
-
}),
|
|
134
|
-
],
|
|
135
|
-
};
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Components support:
|
|
139
|
-
|
|
140
|
-
- **Slots**: Pass `POMNode` or `POMNode[]` as props for content injection
|
|
141
|
-
- **Theme**: Use `mergeTheme()` for colors, spacing, and font size overrides
|
|
142
|
-
- **Nesting**: Components can call other components
|
|
143
|
-
- **JSON / LLM**: Use `expandComponents()` to resolve component references in JSON
|
|
144
|
-
|
|
145
|
-
### Using Components with LLM-generated JSON
|
|
146
|
-
|
|
147
|
-
When an LLM outputs JSON containing `{ type: "component", name: "...", props: {...} }`, use `expandComponentSlides()` to resolve them before building:
|
|
148
|
-
|
|
149
|
-
```typescript
|
|
150
|
-
import {
|
|
151
|
-
buildPptx,
|
|
152
|
-
defineComponent,
|
|
153
|
-
expandComponentSlides,
|
|
154
|
-
} from "@hirokisakabe/pom";
|
|
155
|
-
|
|
156
|
-
// Register components
|
|
157
|
-
const SectionCard = defineComponent<{ title: string; content: unknown }>(
|
|
158
|
-
(props) => ({
|
|
159
|
-
type: "box",
|
|
160
|
-
padding: 16,
|
|
161
|
-
children: {
|
|
162
|
-
type: "vstack",
|
|
163
|
-
gap: 8,
|
|
164
|
-
children: [
|
|
165
|
-
{ type: "text", text: props.title, bold: true },
|
|
166
|
-
props.content,
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
}),
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
const registry = { SectionCard };
|
|
173
|
-
|
|
174
|
-
// LLM output (JSON with component references)
|
|
175
|
-
const llmOutput = [
|
|
176
|
-
{
|
|
177
|
-
type: "vstack",
|
|
178
|
-
w: 1280,
|
|
179
|
-
h: 720,
|
|
180
|
-
children: [
|
|
181
|
-
{
|
|
182
|
-
type: "component",
|
|
183
|
-
name: "SectionCard",
|
|
184
|
-
props: { title: "KPI", content: { type: "text", text: "$1M" } },
|
|
185
|
-
},
|
|
186
|
-
],
|
|
187
|
-
},
|
|
188
|
-
];
|
|
189
|
-
|
|
190
|
-
// Expand → Build
|
|
191
|
-
const slides = expandComponentSlides(llmOutput, registry);
|
|
192
|
-
const pptx = await buildPptx(slides, { w: 1280, h: 720 });
|
|
193
|
-
```
|
|
194
|
-
|
|
195
67
|
## Documentation
|
|
196
68
|
|
|
197
|
-
| Document
|
|
198
|
-
|
|
|
199
|
-
| [Nodes Reference](./docs/nodes.md)
|
|
200
|
-
| [Master Slide](./docs/master-slide.md)
|
|
201
|
-
| [Serverless Environments](./docs/serverless.md)
|
|
202
|
-
| [LLM Integration](./docs/llm-integration.md)
|
|
203
|
-
| [
|
|
69
|
+
| Document | Description |
|
|
70
|
+
| ------------------------------------------------ | --------------------------------------- |
|
|
71
|
+
| [Nodes Reference](./docs/nodes.md) | Complete reference for all node types |
|
|
72
|
+
| [Master Slide](./docs/master-slide.md) | Headers, footers, and page numbers |
|
|
73
|
+
| [Serverless Environments](./docs/serverless.md) | Text measurement options for serverless |
|
|
74
|
+
| [LLM Integration](./docs/llm-integration.md) | Compact XML reference for LLM prompts |
|
|
75
|
+
| [Playground](https://pom-playground.vercel.app/) | Try pom XML in the browser |
|
|
204
76
|
|
|
205
77
|
## License
|
|
206
78
|
|
package/dist/buildPptx.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TextMeasurementMode } from "./calcYogaLayout/measureText.ts";
|
|
2
|
-
import {
|
|
2
|
+
import { SlideMasterOptions } from "./types.ts";
|
|
3
3
|
export type { TextMeasurementMode };
|
|
4
|
-
export declare function buildPptx(
|
|
4
|
+
export declare function buildPptx(xml: string, slideSize: {
|
|
5
5
|
w: number;
|
|
6
6
|
h: number;
|
|
7
7
|
}, options?: {
|
package/dist/buildPptx.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildPptx.d.ts","sourceRoot":"","sources":["../src/buildPptx.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,mBAAmB,EACpB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"buildPptx.d.ts","sourceRoot":"","sources":["../src/buildPptx.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,mBAAmB,EACpB,MAAM,iCAAiC,CAAC;AAIzC,OAAO,EAAkB,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhE,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,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;CACvC,wCAqBF"}
|
package/dist/buildPptx.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { calcYogaLayout } from "./calcYogaLayout/calcYogaLayout.js";
|
|
2
2
|
import { setTextMeasurementMode, } from "./calcYogaLayout/measureText.js";
|
|
3
|
+
import { parseXml } from "./parseXml.js";
|
|
3
4
|
import { renderPptx } from "./renderPptx/renderPptx.js";
|
|
4
5
|
import { toPositioned } from "./toPositioned/toPositioned.js";
|
|
5
|
-
export async function buildPptx(
|
|
6
|
+
export async function buildPptx(xml, slideSize, options) {
|
|
6
7
|
// テキスト計測モードを設定(デフォルトは auto)
|
|
7
8
|
if (options?.textMeasurement) {
|
|
8
9
|
setTextMeasurementMode(options.textMeasurement);
|
|
@@ -10,6 +11,7 @@ export async function buildPptx(nodes, slideSize, options) {
|
|
|
10
11
|
else {
|
|
11
12
|
setTextMeasurementMode("auto");
|
|
12
13
|
}
|
|
14
|
+
const nodes = parseXml(xml);
|
|
13
15
|
const positionedPages = [];
|
|
14
16
|
for (const node of nodes) {
|
|
15
17
|
await calcYogaLayout(node, slideSize);
|
|
@@ -2,13 +2,6 @@
|
|
|
2
2
|
* opentype.js を使用したフォント読み込みモジュール
|
|
3
3
|
* Node.js とブラウザ両方で動作する
|
|
4
4
|
*/
|
|
5
|
-
import { Font } from "opentype.js";
|
|
6
|
-
/**
|
|
7
|
-
* フォントを取得する(キャッシュ付き)
|
|
8
|
-
* @param weight フォントウェイト ("normal" or "bold")
|
|
9
|
-
* @returns opentype.js の Font オブジェクト
|
|
10
|
-
*/
|
|
11
|
-
export declare function getFont(weight: "normal" | "bold"): Font;
|
|
12
5
|
/**
|
|
13
6
|
* 指定したテキストの幅を計測する
|
|
14
7
|
* @param text 計測するテキスト
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontLoader.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/fontLoader.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"fontLoader.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/fontLoader.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA2DH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,QAAQ,GAAG,MAAM,GACxB,MAAM,CAGR"}
|
|
@@ -30,7 +30,7 @@ function base64ToArrayBuffer(base64) {
|
|
|
30
30
|
* @param weight フォントウェイト ("normal" or "bold")
|
|
31
31
|
* @returns opentype.js の Font オブジェクト
|
|
32
32
|
*/
|
|
33
|
-
|
|
33
|
+
function getFont(weight) {
|
|
34
34
|
const cacheKey = weight;
|
|
35
35
|
// キャッシュがあればそれを返す
|
|
36
36
|
const cached = fontCache.get(cacheKey);
|
|
@@ -9,10 +9,6 @@ export type TextMeasurementMode = "opentype" | "fallback" | "auto";
|
|
|
9
9
|
* テキスト計測モードを設定する
|
|
10
10
|
*/
|
|
11
11
|
export declare function setTextMeasurementMode(mode: TextMeasurementMode): void;
|
|
12
|
-
/**
|
|
13
|
-
* 現在のテキスト計測モードを取得する
|
|
14
|
-
*/
|
|
15
|
-
export declare function getTextMeasurementMode(): TextMeasurementMode;
|
|
16
12
|
/**
|
|
17
13
|
* テキストを折り返し付きでレイアウトし、そのサイズを測定する
|
|
18
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"measureText.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/measureText.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAoHnE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAEtE;
|
|
1
|
+
{"version":3,"file":"measureText.d.ts","sourceRoot":"","sources":["../../src/calcYogaLayout/measureText.ts"],"names":[],"mappings":"AAEA,KAAK,cAAc,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;AAoHnE;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAEtE;AAcD;;GAEG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,cAAc,GACnB;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAmBA"}
|
|
@@ -102,12 +102,6 @@ let currentMode = "auto";
|
|
|
102
102
|
export function setTextMeasurementMode(mode) {
|
|
103
103
|
currentMode = mode;
|
|
104
104
|
}
|
|
105
|
-
/**
|
|
106
|
-
* 現在のテキスト計測モードを取得する
|
|
107
|
-
*/
|
|
108
|
-
export function getTextMeasurementMode() {
|
|
109
|
-
return currentMode;
|
|
110
|
-
}
|
|
111
105
|
/**
|
|
112
106
|
* fontWeight を "normal" | "bold" に正規化する
|
|
113
107
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export * from "./types.ts";
|
|
2
|
-
export * from "./inputSchema.ts";
|
|
3
1
|
export { buildPptx } from "./buildPptx.ts";
|
|
4
2
|
export type { TextMeasurementMode } from "./buildPptx.ts";
|
|
5
|
-
export {
|
|
6
|
-
export type {
|
|
3
|
+
export { ParseXmlError } from "./parseXml.ts";
|
|
4
|
+
export type { SlideMasterOptions, SlideMasterBackground, SlideMasterMargin, MasterObject, MasterTextObject, MasterImageObject, MasterRectObject, MasterLineObject, SlideNumberOptions, } from "./types.ts";
|
|
7
5
|
//# 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,
|
|
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;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,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,4 +1,2 @@
|
|
|
1
|
-
export * from "./types.js";
|
|
2
|
-
export * from "./inputSchema.js";
|
|
3
1
|
export { buildPptx } from "./buildPptx.js";
|
|
4
|
-
export {
|
|
2
|
+
export { ParseXmlError } from "./parseXml.js";
|