@hirokisakabe/pom 0.1.12 → 0.2.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 +28 -582
- package/dist/calcYogaLayout/calcYogaLayout.js +12 -0
- package/dist/inputSchema.d.ts +268 -2
- package/dist/inputSchema.d.ts.map +1 -1
- package/dist/inputSchema.js +53 -1
- package/dist/renderPptx/renderPptx.d.ts.map +1 -1
- package/dist/renderPptx/renderPptx.js +784 -0
- package/dist/toPositioned/toPositioned.d.ts.map +1 -1
- package/dist/toPositioned/toPositioned.js +45 -0
- package/dist/types.d.ts +399 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +134 -0
- package/package.json +11 -2
- package/dist/parsePptx/convertChart.d.ts +0 -8
- package/dist/parsePptx/convertChart.d.ts.map +0 -1
- package/dist/parsePptx/convertChart.js +0 -78
- package/dist/parsePptx/convertImage.d.ts +0 -8
- package/dist/parsePptx/convertImage.d.ts.map +0 -1
- package/dist/parsePptx/convertImage.js +0 -13
- package/dist/parsePptx/convertShape.d.ts +0 -7
- package/dist/parsePptx/convertShape.d.ts.map +0 -1
- package/dist/parsePptx/convertShape.js +0 -137
- package/dist/parsePptx/convertTable.d.ts +0 -7
- package/dist/parsePptx/convertTable.d.ts.map +0 -1
- package/dist/parsePptx/convertTable.js +0 -46
- package/dist/parsePptx/convertText.d.ts +0 -7
- package/dist/parsePptx/convertText.d.ts.map +0 -1
- package/dist/parsePptx/convertText.js +0 -32
- package/dist/parsePptx/index.d.ts +0 -23
- package/dist/parsePptx/index.d.ts.map +0 -1
- package/dist/parsePptx/index.js +0 -114
- package/dist/parsePptx/parseHtml.d.ts +0 -22
- package/dist/parsePptx/parseHtml.d.ts.map +0 -1
- package/dist/parsePptx/parseHtml.js +0 -53
- package/dist/parsePptx/types.d.ts +0 -15
- package/dist/parsePptx/types.d.ts.map +0 -1
- package/dist/parsePptx/types.js +0 -1
- package/dist/parsePptx/units.d.ts +0 -13
- package/dist/parsePptx/units.d.ts.map +0 -1
- package/dist/parsePptx/units.js +0 -19
package/README.md
CHANGED
|
@@ -9,19 +9,6 @@
|
|
|
9
9
|
> [!NOTE]
|
|
10
10
|
> The PPTX generation feature (`buildPptx`) only works in Node.js environments. However, if you only need the input schema, you can import it from `@hirokisakabe/pom/schema` for use in browser environments.
|
|
11
11
|
|
|
12
|
-
## Table of Contents
|
|
13
|
-
|
|
14
|
-
- [Requirements](#requirements)
|
|
15
|
-
- [Installation](#installation)
|
|
16
|
-
- [Quick Start](#quick-start)
|
|
17
|
-
- [Features](#features)
|
|
18
|
-
- [Nodes](#nodes)
|
|
19
|
-
- [Master Slide](#master-slide)
|
|
20
|
-
- [Serverless Environments](#serverless-environments)
|
|
21
|
-
- [LLM Integration](#llm-integration)
|
|
22
|
-
- [Input Validation in Browser Environments](#input-validation-in-browser-environments)
|
|
23
|
-
- [License](#license)
|
|
24
|
-
|
|
25
12
|
## Installation
|
|
26
13
|
|
|
27
14
|
```bash
|
|
@@ -70,575 +57,34 @@ await pptx.writeFile({ fileName: "presentation.pptx" });
|
|
|
70
57
|
- **Master Slide**: Automatically insert common headers, footers, and page numbers across all pages
|
|
71
58
|
- **AI Friendly**: Simple structure that makes it easy for LLMs to generate code
|
|
72
59
|
|
|
73
|
-
## Nodes
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
### Node List
|
|
103
|
-
|
|
104
|
-
#### 1. Text
|
|
105
|
-
|
|
106
|
-
A node for displaying text.
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
{
|
|
110
|
-
type: "text";
|
|
111
|
-
text: string;
|
|
112
|
-
fontPx?: number;
|
|
113
|
-
color?: string;
|
|
114
|
-
alignText?: "left" | "center" | "right";
|
|
115
|
-
bold?: boolean;
|
|
116
|
-
fontFamily?: string;
|
|
117
|
-
lineSpacingMultiple?: number;
|
|
118
|
-
bullet?: boolean | BulletOptions;
|
|
119
|
-
|
|
120
|
-
// Common properties
|
|
121
|
-
w?: number | "max" | `${number}%`;
|
|
122
|
-
h?: number | "max" | `${number}%`;
|
|
123
|
-
...
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
- `color` specifies the text color as a hex color code (e.g., `"FF0000"`).
|
|
128
|
-
- `bold` enables bold text.
|
|
129
|
-
- `fontFamily` specifies the font family (default: `"Noto Sans JP"`).
|
|
130
|
-
- `lineSpacingMultiple` specifies the line spacing multiplier (default: `1.3`).
|
|
131
|
-
- `bullet` enables bullet points. Use `true` for default bullets, or an object for detailed settings.
|
|
132
|
-
|
|
133
|
-
**BulletOptions:**
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
{
|
|
137
|
-
type?: "bullet" | "number"; // "bullet": symbol, "number": numbered
|
|
138
|
-
indent?: number; // Indent level
|
|
139
|
-
numberType?: "alphaLcParenBoth" | "alphaLcParenR" | "alphaLcPeriod" |
|
|
140
|
-
"alphaUcParenBoth" | "alphaUcParenR" | "alphaUcPeriod" |
|
|
141
|
-
"arabicParenBoth" | "arabicParenR" | "arabicPeriod" | "arabicPlain" |
|
|
142
|
-
"romanLcParenBoth" | "romanLcParenR" | "romanLcPeriod" |
|
|
143
|
-
"romanUcParenBoth" | "romanUcParenR" | "romanUcPeriod";
|
|
144
|
-
numberStartAt?: number; // Starting number
|
|
145
|
-
}
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**Usage Examples:**
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
// Simple bullet list
|
|
152
|
-
{
|
|
153
|
-
type: "text",
|
|
154
|
-
text: "Item 1\nItem 2\nItem 3",
|
|
155
|
-
bullet: true,
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Numbered list
|
|
159
|
-
{
|
|
160
|
-
type: "text",
|
|
161
|
-
text: "Step 1\nStep 2\nStep 3",
|
|
162
|
-
bullet: { type: "number" },
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Lowercase alphabet (a. b. c.)
|
|
166
|
-
{
|
|
167
|
-
type: "text",
|
|
168
|
-
text: "Item A\nItem B\nItem C",
|
|
169
|
-
bullet: { type: "number", numberType: "alphaLcPeriod" },
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Numbered list starting from 5
|
|
173
|
-
{
|
|
174
|
-
type: "text",
|
|
175
|
-
text: "Fifth\nSixth\nSeventh",
|
|
176
|
-
bullet: { type: "number", numberStartAt: 5 },
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
#### 2. Image
|
|
181
|
-
|
|
182
|
-
A node for displaying images.
|
|
183
|
-
|
|
184
|
-
- If `w` and `h` are not specified, the actual image size is automatically used
|
|
185
|
-
- If size is specified, the image is displayed at that size (aspect ratio is not preserved)
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
{
|
|
189
|
-
type: "image";
|
|
190
|
-
src: string; // Image path (local path, URL, or base64 data)
|
|
191
|
-
|
|
192
|
-
// Common properties
|
|
193
|
-
w?: number | "max" | `${number}%`;
|
|
194
|
-
h?: number | "max" | `${number}%`;
|
|
195
|
-
...
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
#### 3. Table
|
|
200
|
-
|
|
201
|
-
A node for drawing tables. Column widths and row heights are declared in px, with fine-grained control over cell decoration.
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
{
|
|
205
|
-
type: "table";
|
|
206
|
-
columns: { width?: number }[];
|
|
207
|
-
rows: {
|
|
208
|
-
height?: number;
|
|
209
|
-
cells: {
|
|
210
|
-
text: string;
|
|
211
|
-
fontPx?: number;
|
|
212
|
-
color?: string;
|
|
213
|
-
bold?: boolean;
|
|
214
|
-
alignText?: "left" | "center" | "right";
|
|
215
|
-
backgroundColor?: string;
|
|
216
|
-
}[];
|
|
217
|
-
}[];
|
|
218
|
-
defaultRowHeight?: number;
|
|
219
|
-
|
|
220
|
-
// Common properties
|
|
221
|
-
w?: number | "max" | `${number}%`;
|
|
222
|
-
h?: number | "max" | `${number}%`;
|
|
223
|
-
...
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
- If `columns[].width` is omitted, columns are evenly distributed across the table width.
|
|
228
|
-
- The sum of `columns` becomes the natural width of the table (can be overridden with `w` if needed).
|
|
229
|
-
- If `rows` `height` is omitted, `defaultRowHeight` is applied (32px if unspecified).
|
|
230
|
-
- Cell background and font decoration can be specified individually for each element in `cells`.
|
|
231
|
-
|
|
232
|
-
#### 4. Shape
|
|
233
|
-
|
|
234
|
-
A node for drawing shapes. Different representations are possible with or without text, supporting complex visual effects.
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
{
|
|
238
|
-
type: "shape";
|
|
239
|
-
shapeType: PptxGenJS.SHAPE_NAME; // e.g., "roundRect", "ellipse", "cloud", "star5"
|
|
240
|
-
text?: string; // Text to display inside the shape (optional)
|
|
241
|
-
fill?: {
|
|
242
|
-
color?: string;
|
|
243
|
-
transparency?: number;
|
|
244
|
-
};
|
|
245
|
-
line?: {
|
|
246
|
-
color?: string;
|
|
247
|
-
width?: number;
|
|
248
|
-
dashType?: "solid" | "dash" | "dashDot" | "lgDash" | "lgDashDot" | "lgDashDotDot" | "sysDash" | "sysDot";
|
|
249
|
-
};
|
|
250
|
-
shadow?: {
|
|
251
|
-
type: "outer" | "inner";
|
|
252
|
-
opacity?: number;
|
|
253
|
-
blur?: number;
|
|
254
|
-
angle?: number;
|
|
255
|
-
offset?: number;
|
|
256
|
-
color?: string;
|
|
257
|
-
};
|
|
258
|
-
fontPx?: number;
|
|
259
|
-
color?: string;
|
|
260
|
-
alignText?: "left" | "center" | "right";
|
|
261
|
-
|
|
262
|
-
// Common properties
|
|
263
|
-
w?: number | "max" | `${number}%`;
|
|
264
|
-
h?: number | "max" | `${number}%`;
|
|
265
|
-
...
|
|
266
|
-
}
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
**Common Shape Types:**
|
|
270
|
-
|
|
271
|
-
- `roundRect`: Rounded rectangle (title boxes, category displays)
|
|
272
|
-
- `ellipse`: Ellipse/circle (step numbers, badges)
|
|
273
|
-
- `cloud`: Cloud shape (comments, key points)
|
|
274
|
-
- `wedgeRectCallout`: Callout with arrow (annotations)
|
|
275
|
-
- `cloudCallout`: Cloud callout (comments)
|
|
276
|
-
- `star5`: 5-pointed star (emphasis, decoration)
|
|
277
|
-
- `downArrow`: Down arrow (flow diagrams)
|
|
278
|
-
|
|
279
|
-
#### 5. Box
|
|
280
|
-
|
|
281
|
-
A generic container that wraps a single child element.
|
|
282
|
-
|
|
283
|
-
- Only **one** child element
|
|
284
|
-
- Used for grouping with padding or fixed size
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
{
|
|
288
|
-
type: "box";
|
|
289
|
-
children: POMNode;
|
|
290
|
-
|
|
291
|
-
// Common properties
|
|
292
|
-
w?: number | "max" | `${number}%`;
|
|
293
|
-
h?: number | "max" | `${number}%`;
|
|
294
|
-
...
|
|
295
|
-
}
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
#### 6. VStack
|
|
299
|
-
|
|
300
|
-
Arranges child elements **vertically**.
|
|
301
|
-
|
|
302
|
-
```typescript
|
|
303
|
-
{
|
|
304
|
-
type: "vstack";
|
|
305
|
-
children: POMNode[];
|
|
306
|
-
alignItems: "start" | "center" | "end" | "stretch";
|
|
307
|
-
justifyContent: "start" | "center" | "end" | "spaceBetween";
|
|
308
|
-
gap?: number;
|
|
309
|
-
|
|
310
|
-
// Common properties
|
|
311
|
-
w?: number | "max" | `${number}%`;
|
|
312
|
-
h?: number | "max" | `${number}%`;
|
|
313
|
-
...
|
|
314
|
-
}
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
#### 7. HStack
|
|
318
|
-
|
|
319
|
-
Arranges child elements **horizontally**.
|
|
320
|
-
|
|
321
|
-
```typescript
|
|
322
|
-
{
|
|
323
|
-
type: "hstack";
|
|
324
|
-
children: POMNode[];
|
|
325
|
-
alignItems: "start" | "center" | "end" | "stretch";
|
|
326
|
-
justifyContent: "start" | "center" | "end" | "spaceBetween";
|
|
327
|
-
gap?: number;
|
|
328
|
-
|
|
329
|
-
// Common properties
|
|
330
|
-
w?: number | "max" | `${number}%`;
|
|
331
|
-
h?: number | "max" | `${number}%`;
|
|
332
|
-
...
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
#### 8. Chart
|
|
337
|
-
|
|
338
|
-
A node for drawing charts. Supports bar charts, line charts, pie charts, area charts, doughnut charts, and radar charts.
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
{
|
|
342
|
-
type: "chart";
|
|
343
|
-
chartType: "bar" | "line" | "pie" | "area" | "doughnut" | "radar";
|
|
344
|
-
data: {
|
|
345
|
-
name?: string; // Series name
|
|
346
|
-
labels: string[]; // Category labels
|
|
347
|
-
values: number[]; // Values
|
|
348
|
-
}[];
|
|
349
|
-
showLegend?: boolean; // Show legend (default: false)
|
|
350
|
-
showTitle?: boolean; // Show title (default: false)
|
|
351
|
-
title?: string; // Title string
|
|
352
|
-
chartColors?: string[]; // Data color array (hex color codes)
|
|
353
|
-
radarStyle?: "standard" | "marker" | "filled"; // Radar-only: chart style
|
|
354
|
-
|
|
355
|
-
// Common properties
|
|
356
|
-
w?: number | "max" | `${number}%`;
|
|
357
|
-
h?: number | "max" | `${number}%`;
|
|
358
|
-
...
|
|
359
|
-
}
|
|
360
|
-
```
|
|
361
|
-
|
|
362
|
-
**Usage Examples:**
|
|
363
|
-
|
|
364
|
-
```typescript
|
|
365
|
-
// Bar chart
|
|
366
|
-
{
|
|
367
|
-
type: "chart",
|
|
368
|
-
chartType: "bar",
|
|
369
|
-
w: 600,
|
|
370
|
-
h: 400,
|
|
371
|
-
data: [
|
|
372
|
-
{
|
|
373
|
-
name: "Sales",
|
|
374
|
-
labels: ["Jan", "Feb", "Mar", "Apr"],
|
|
375
|
-
values: [100, 200, 150, 300],
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
name: "Profit",
|
|
379
|
-
labels: ["Jan", "Feb", "Mar", "Apr"],
|
|
380
|
-
values: [30, 60, 45, 90],
|
|
381
|
-
},
|
|
382
|
-
],
|
|
383
|
-
showLegend: true,
|
|
384
|
-
showTitle: true,
|
|
385
|
-
title: "Monthly Sales & Profit",
|
|
386
|
-
chartColors: ["0088CC", "00AA00"],
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Pie chart
|
|
390
|
-
{
|
|
391
|
-
type: "chart",
|
|
392
|
-
chartType: "pie",
|
|
393
|
-
w: 400,
|
|
394
|
-
h: 300,
|
|
395
|
-
data: [
|
|
396
|
-
{
|
|
397
|
-
name: "Market Share",
|
|
398
|
-
labels: ["Product A", "Product B", "Product C", "Others"],
|
|
399
|
-
values: [40, 30, 20, 10],
|
|
400
|
-
},
|
|
401
|
-
],
|
|
402
|
-
showLegend: true,
|
|
403
|
-
chartColors: ["0088CC", "00AA00", "FF6600", "888888"],
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// Radar chart
|
|
407
|
-
{
|
|
408
|
-
type: "chart",
|
|
409
|
-
chartType: "radar",
|
|
410
|
-
w: 400,
|
|
411
|
-
h: 300,
|
|
412
|
-
data: [
|
|
413
|
-
{
|
|
414
|
-
name: "Skill Assessment",
|
|
415
|
-
labels: ["Technical", "Design", "PM", "Sales", "Support"],
|
|
416
|
-
values: [80, 60, 70, 50, 90],
|
|
417
|
-
},
|
|
418
|
-
],
|
|
419
|
-
showLegend: true,
|
|
420
|
-
radarStyle: "filled",
|
|
421
|
-
chartColors: ["0088CC"],
|
|
422
|
-
}
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
## Master Slide
|
|
426
|
-
|
|
427
|
-
You can automatically insert common headers, footers, and page numbers across all pages.
|
|
428
|
-
|
|
429
|
-
### Basic Usage
|
|
430
|
-
|
|
431
|
-
```typescript
|
|
432
|
-
import { buildPptx } from "@hirokisakabe/pom";
|
|
433
|
-
|
|
434
|
-
const pptx = await buildPptx(
|
|
435
|
-
[page1, page2, page3],
|
|
436
|
-
{ w: 1280, h: 720 },
|
|
437
|
-
{
|
|
438
|
-
master: {
|
|
439
|
-
header: {
|
|
440
|
-
type: "hstack",
|
|
441
|
-
h: 40,
|
|
442
|
-
padding: { left: 48, right: 48, top: 12, bottom: 0 },
|
|
443
|
-
justifyContent: "spaceBetween",
|
|
444
|
-
alignItems: "center",
|
|
445
|
-
backgroundColor: "0F172A",
|
|
446
|
-
children: [
|
|
447
|
-
{
|
|
448
|
-
type: "text",
|
|
449
|
-
text: "Company Name",
|
|
450
|
-
fontPx: 14,
|
|
451
|
-
color: "FFFFFF",
|
|
452
|
-
},
|
|
453
|
-
{
|
|
454
|
-
type: "text",
|
|
455
|
-
text: "{{date}}",
|
|
456
|
-
fontPx: 12,
|
|
457
|
-
color: "E2E8F0",
|
|
458
|
-
},
|
|
459
|
-
],
|
|
460
|
-
},
|
|
461
|
-
footer: {
|
|
462
|
-
type: "hstack",
|
|
463
|
-
h: 30,
|
|
464
|
-
padding: { left: 48, right: 48, top: 0, bottom: 8 },
|
|
465
|
-
justifyContent: "spaceBetween",
|
|
466
|
-
alignItems: "center",
|
|
467
|
-
children: [
|
|
468
|
-
{
|
|
469
|
-
type: "text",
|
|
470
|
-
text: "Confidential",
|
|
471
|
-
fontPx: 10,
|
|
472
|
-
color: "1E293B",
|
|
473
|
-
},
|
|
474
|
-
{
|
|
475
|
-
type: "text",
|
|
476
|
-
text: "Page {{page}} / {{totalPages}}",
|
|
477
|
-
fontPx: 10,
|
|
478
|
-
color: "1E293B",
|
|
479
|
-
alignText: "right",
|
|
480
|
-
},
|
|
481
|
-
],
|
|
482
|
-
},
|
|
483
|
-
date: {
|
|
484
|
-
format: "YYYY/MM/DD", // or "locale"
|
|
485
|
-
},
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
);
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
### Master Slide Options
|
|
492
|
-
|
|
493
|
-
```typescript
|
|
494
|
-
type MasterSlideOptions = {
|
|
495
|
-
header?: POMNode; // Header (any POMNode can be specified)
|
|
496
|
-
footer?: POMNode; // Footer (any POMNode can be specified)
|
|
497
|
-
pageNumber?: {
|
|
498
|
-
position: "left" | "center" | "right"; // Page number position
|
|
499
|
-
};
|
|
500
|
-
date?: {
|
|
501
|
-
format: "YYYY/MM/DD" | "locale"; // Date format
|
|
502
|
-
};
|
|
503
|
-
};
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
### Placeholders
|
|
507
|
-
|
|
508
|
-
The following placeholders can be used in text within headers and footers:
|
|
509
|
-
|
|
510
|
-
- `{{page}}`: Current page number
|
|
511
|
-
- `{{totalPages}}`: Total number of pages
|
|
512
|
-
- `{{date}}`: Date (in the format specified by `date.format`)
|
|
513
|
-
|
|
514
|
-
### Features
|
|
515
|
-
|
|
516
|
-
- **Flexibility**: Headers and footers can use any POMNode (VStack, HStack, Box, etc.)
|
|
517
|
-
- **Automatic Composition**: Headers and footers are automatically added to each page's content
|
|
518
|
-
- **Dynamic Replacement**: Placeholders are automatically replaced per page
|
|
519
|
-
- **Backward Compatibility**: The master option is optional and has no impact on existing code
|
|
520
|
-
|
|
521
|
-
## Serverless Environments
|
|
522
|
-
|
|
523
|
-
pom uses the `canvas` package by default to measure text width and determine line break positions. However, in serverless environments like Vercel or AWS Lambda, Japanese fonts (such as Noto Sans JP) are not installed, which may cause text line breaks to be misaligned.
|
|
524
|
-
|
|
525
|
-
To address this issue, you can specify the text measurement method using the `textMeasurement` option.
|
|
526
|
-
|
|
527
|
-
### textMeasurement Option
|
|
528
|
-
|
|
529
|
-
```typescript
|
|
530
|
-
const pptx = await buildPptx(
|
|
531
|
-
[slide],
|
|
532
|
-
{ w: 1280, h: 720 },
|
|
533
|
-
{
|
|
534
|
-
textMeasurement: "auto", // "canvas" | "fallback" | "auto"
|
|
535
|
-
},
|
|
536
|
-
);
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
| Value | Description |
|
|
540
|
-
| ------------ | -------------------------------------------------------------------------------------- |
|
|
541
|
-
| `"canvas"` | Always use canvas for text width measurement (for environments with fonts installed) |
|
|
542
|
-
| `"fallback"` | Always use fallback calculation (CJK characters = 1em, alphanumeric = 0.5em estimated) |
|
|
543
|
-
| `"auto"` | Auto-detect font availability and fall back if unavailable (default) |
|
|
544
|
-
|
|
545
|
-
### Recommended Settings
|
|
546
|
-
|
|
547
|
-
- **Local development / Docker**: Default (`"auto"`) works fine
|
|
548
|
-
- **Serverless environments**: Default `"auto"` will automatically fall back
|
|
549
|
-
- **Environments with fonts installed**: Explicitly specifying `"canvas"` enables more accurate measurement
|
|
550
|
-
|
|
551
|
-
## LLM Integration
|
|
552
|
-
|
|
553
|
-
pom supports use cases where slides are created from JSON generated by LLMs (GPT-4o, Claude, etc.).
|
|
554
|
-
|
|
555
|
-
### LLM Specification Guide
|
|
556
|
-
|
|
557
|
-
[`llm-guide.md`](./llm-guide.md) is a compact specification document for having LLMs generate JSON in pom format. Include it in your system prompt.
|
|
558
|
-
|
|
559
|
-
**Contents:**
|
|
560
|
-
|
|
561
|
-
- Node list and main properties
|
|
562
|
-
- Standard settings (slide size, padding, gap, font size guidelines)
|
|
563
|
-
- Pattern examples (basic structure, 2-column, table, shapes, charts, etc.)
|
|
564
|
-
- Common mistakes and correct usage
|
|
565
|
-
|
|
566
|
-
### Input Schema
|
|
567
|
-
|
|
568
|
-
Use `inputPomNodeSchema` to validate JSON generated by LLMs.
|
|
569
|
-
|
|
570
|
-
```typescript
|
|
571
|
-
import { inputPomNodeSchema, buildPptx, InputPOMNode } from "@hirokisakabe/pom";
|
|
572
|
-
|
|
573
|
-
// Validate JSON output from LLM
|
|
574
|
-
const jsonFromLLM = `{
|
|
575
|
-
"type": "vstack",
|
|
576
|
-
"padding": 48,
|
|
577
|
-
"gap": 24,
|
|
578
|
-
"children": [
|
|
579
|
-
{ "type": "text", "text": "Title", "fontPx": 32, "bold": true },
|
|
580
|
-
{ "type": "text", "text": "Body text", "fontPx": 16 }
|
|
581
|
-
]
|
|
582
|
-
}`;
|
|
583
|
-
|
|
584
|
-
const parsed = JSON.parse(jsonFromLLM);
|
|
585
|
-
const result = inputPomNodeSchema.safeParse(parsed);
|
|
586
|
-
|
|
587
|
-
if (result.success) {
|
|
588
|
-
// Validation successful - generate PPTX
|
|
589
|
-
const pptx = await buildPptx([result.data], { w: 1280, h: 720 });
|
|
590
|
-
await pptx.writeFile({ fileName: "output.pptx" });
|
|
591
|
-
} else {
|
|
592
|
-
// Validation failed - check error details
|
|
593
|
-
console.error("Validation failed:", result.error.format());
|
|
594
|
-
}
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
### Available Input Schemas
|
|
598
|
-
|
|
599
|
-
| Schema | Description |
|
|
600
|
-
| ------------------------------- | ------------------------------------------ |
|
|
601
|
-
| `inputPomNodeSchema` | Main node schema (includes all node types) |
|
|
602
|
-
| `inputTextNodeSchema` | For text nodes |
|
|
603
|
-
| `inputImageNodeSchema` | For image nodes |
|
|
604
|
-
| `inputTableNodeSchema` | For table nodes |
|
|
605
|
-
| `inputShapeNodeSchema` | For shape nodes |
|
|
606
|
-
| `inputChartNodeSchema` | For chart nodes |
|
|
607
|
-
| `inputBoxNodeSchema` | For Box nodes |
|
|
608
|
-
| `inputVStackNodeSchema` | For VStack nodes |
|
|
609
|
-
| `inputHStackNodeSchema` | For HStack nodes |
|
|
610
|
-
| `inputMasterSlideOptionsSchema` | For master slide settings |
|
|
611
|
-
|
|
612
|
-
### Input Validation in Browser Environments
|
|
613
|
-
|
|
614
|
-
If you want to validate LLM output in browser environments (SPAs like React, Vue, Svelte), you can import schemas from `@hirokisakabe/pom/schema`. This subpath exports only schemas without Node.js dependencies, so it works in browsers.
|
|
615
|
-
|
|
616
|
-
```typescript
|
|
617
|
-
// Available in browser environments
|
|
618
|
-
import { inputPomNodeSchema } from "@hirokisakabe/pom/schema";
|
|
619
|
-
|
|
620
|
-
// Validate response from LLM
|
|
621
|
-
const result = inputPomNodeSchema.safeParse(llmResponse);
|
|
622
|
-
|
|
623
|
-
if (result.success) {
|
|
624
|
-
// Validation successful - send to server for PPTX generation
|
|
625
|
-
await fetch("/api/generate-pptx", {
|
|
626
|
-
method: "POST",
|
|
627
|
-
headers: { "Content-Type": "application/json" },
|
|
628
|
-
body: JSON.stringify(result.data),
|
|
629
|
-
});
|
|
630
|
-
} else {
|
|
631
|
-
// Validation failed - show error to user
|
|
632
|
-
console.error("Validation failed:", result.error.format());
|
|
633
|
-
}
|
|
634
|
-
```
|
|
635
|
-
|
|
636
|
-
**Difference between `@hirokisakabe/pom` and `@hirokisakabe/pom/schema`:**
|
|
637
|
-
|
|
638
|
-
| Import Path | Environment | Included Features |
|
|
639
|
-
| -------------------------- | --------------- | -------------------------------------------- |
|
|
640
|
-
| `@hirokisakabe/pom` | Node.js | Everything (PPTX generation, schemas, types) |
|
|
641
|
-
| `@hirokisakabe/pom/schema` | Browser-capable | Schemas and types only (no PPTX generation) |
|
|
60
|
+
## Available Nodes
|
|
61
|
+
|
|
62
|
+
| Node | Description |
|
|
63
|
+
| ------------ | ---------------------------------------------- |
|
|
64
|
+
| text | Text with font styling and bullet points |
|
|
65
|
+
| image | Images from file path, URL, or base64 |
|
|
66
|
+
| table | Tables with customizable columns and rows |
|
|
67
|
+
| shape | PowerPoint shapes (roundRect, ellipse, etc.) |
|
|
68
|
+
| chart | Charts (bar, line, pie, area, doughnut, radar) |
|
|
69
|
+
| timeline | Timeline/roadmap visualizations |
|
|
70
|
+
| matrix | 2x2 positioning maps |
|
|
71
|
+
| tree | Organization charts and decision trees |
|
|
72
|
+
| flow | Flowcharts with nodes and edges |
|
|
73
|
+
| processArrow | Chevron-style process diagrams |
|
|
74
|
+
| box | Container for single child with padding |
|
|
75
|
+
| vstack | Vertical stack layout |
|
|
76
|
+
| hstack | Horizontal stack layout |
|
|
77
|
+
|
|
78
|
+
For detailed node documentation, see [Nodes Reference](./docs/nodes.md).
|
|
79
|
+
|
|
80
|
+
## Documentation
|
|
81
|
+
|
|
82
|
+
| Document | Description |
|
|
83
|
+
| ----------------------------------------------- | --------------------------------------- |
|
|
84
|
+
| [Nodes Reference](./docs/nodes.md) | Complete reference for all node types |
|
|
85
|
+
| [Master Slide](./docs/master-slide.md) | Headers, footers, and page numbers |
|
|
86
|
+
| [Serverless Environments](./docs/serverless.md) | Text measurement options for serverless |
|
|
87
|
+
| [LLM Integration](./docs/llm-integration.md) | Guide for generating slides with AI/LLM |
|
|
642
88
|
|
|
643
89
|
## License
|
|
644
90
|
|
|
@@ -88,6 +88,11 @@ async function buildPomWithYogaTree(node, parentYoga, parentNode) {
|
|
|
88
88
|
case "image":
|
|
89
89
|
case "table":
|
|
90
90
|
case "shape":
|
|
91
|
+
case "timeline":
|
|
92
|
+
case "matrix":
|
|
93
|
+
case "tree":
|
|
94
|
+
case "flow":
|
|
95
|
+
case "processArrow":
|
|
91
96
|
// 子要素なし
|
|
92
97
|
break;
|
|
93
98
|
}
|
|
@@ -345,5 +350,12 @@ async function applyStyleToYogaNode(node, yn) {
|
|
|
345
350
|
// テキストがない場合は、明示的にサイズが指定されていることを期待
|
|
346
351
|
}
|
|
347
352
|
break;
|
|
353
|
+
case "timeline":
|
|
354
|
+
case "matrix":
|
|
355
|
+
case "tree":
|
|
356
|
+
case "flow":
|
|
357
|
+
case "processArrow":
|
|
358
|
+
// 明示的にサイズが指定されていることを期待
|
|
359
|
+
break;
|
|
348
360
|
}
|
|
349
361
|
}
|