@office-kit/pptx-dsl 0.4.0 → 0.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 +98 -4
- package/dist/index.d.ts +26 -3
- package/dist/index.js +70 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -61,8 +61,8 @@ Layout is explicit: CSS and automatic UI layout are not implemented.
|
|
|
61
61
|
| `Image` | Bytes in `data`, optional format and fit |
|
|
62
62
|
| `Media` | `kind` `video` / `audio` with bytes in `data`, or `online` with a `url` |
|
|
63
63
|
| `Chart` | Complete core `ChartSpec` via `spec` |
|
|
64
|
-
| `Table` |
|
|
65
|
-
| `Fill` | Existing shape target, replacement text, optional format
|
|
64
|
+
| `Table` | Rows of strings, rich cells or merges; sizes; cell styles and `styleCell` |
|
|
65
|
+
| `Fill` | Existing shape target, replacement text, optional format and `autoFit` |
|
|
66
66
|
| `Remove` | Existing shape target |
|
|
67
67
|
| `Raw` | Deferred callback receiving the presentation and enclosing slide/shape |
|
|
68
68
|
|
|
@@ -72,6 +72,26 @@ accepts the core `TextFormat` properties directly, plus alignment, anchor,
|
|
|
72
72
|
text auto-fit, `bullets` and `paragraphSpacing` (both apply to every paragraph; a
|
|
73
73
|
newline in the text starts one). A `Shape` with `text` takes `align` and `anchor`.
|
|
74
74
|
|
|
75
|
+
Each entry of `paragraphs` is a core `ParagraphSpec` that also takes its own `bullet`
|
|
76
|
+
and `level`. The paragraph's `bullet` wins over `bullets`, so `bullet: 'none'` keeps a
|
|
77
|
+
heading line out of the list. `level` is the `TextLevel` type, `0` to `8`, and nests
|
|
78
|
+
the list; `tsc` rejects any other number.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<Text
|
|
82
|
+
x={1}
|
|
83
|
+
y={1}
|
|
84
|
+
width={8}
|
|
85
|
+
height={3}
|
|
86
|
+
bullets="bullet"
|
|
87
|
+
paragraphs={[
|
|
88
|
+
{ runs: [{ text: 'What changed' }], bullet: 'none' },
|
|
89
|
+
{ runs: [{ text: 'Churn fell to 4.2%' }] },
|
|
90
|
+
{ runs: [{ text: 'Driver: simpler setup' }], level: 1, bullet: { char: '–' } },
|
|
91
|
+
]}
|
|
92
|
+
/>
|
|
93
|
+
```
|
|
94
|
+
|
|
75
95
|
A `Line` runs from (`x1`, `y1`) to (`x2`, `y2`) instead of taking bounds. A
|
|
76
96
|
`Group` holds two or more visual elements and may contain other groups; the
|
|
77
97
|
result moves and resizes as one object in PowerPoint.
|
|
@@ -95,6 +115,39 @@ field: `cellStyle`, `headerStyle` (row 0), `stripeFill` (even body rows), then
|
|
|
95
115
|
/>
|
|
96
116
|
```
|
|
97
117
|
|
|
118
|
+
A cell in `rows` is a string or a cell object, `{ text }` or `{ paragraphs }`, never
|
|
119
|
+
both or neither. `paragraphs` takes core `ParagraphSpec[]` for more than one run or
|
|
120
|
+
paragraph in a cell. The merged cell style is the base of every run, so a run states
|
|
121
|
+
only what differs, and the style's `align` applies unless a paragraph has its own.
|
|
122
|
+
`styleCell` receives a rich cell's `value` as its run texts joined, one line per
|
|
123
|
+
paragraph.
|
|
124
|
+
|
|
125
|
+
`colSpan` and `rowSpan` on a cell object make it the top-left of a merge. `rows` stays
|
|
126
|
+
a full rectangular grid, so a column index means the same in every row: each position
|
|
127
|
+
the merge covers is written as `''`, and anything else there is an error because
|
|
128
|
+
a covered cell's text is never shown. The merged block takes its fill and borders from
|
|
129
|
+
its top-left cell (this is how the preview renders it), so covered positions get no
|
|
130
|
+
style and `styleCell` is not called for them. Spans that leave the grid or overlap throw the core error.
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
<Table
|
|
134
|
+
x={1}
|
|
135
|
+
y={1}
|
|
136
|
+
width={8}
|
|
137
|
+
height={3}
|
|
138
|
+
rows={[
|
|
139
|
+
[{ text: 'Plan', rowSpan: 2 }, { text: 'Effect', colSpan: 2 }, ''],
|
|
140
|
+
['', 'Count', 'Change'],
|
|
141
|
+
[
|
|
142
|
+
'FAQ',
|
|
143
|
+
'372',
|
|
144
|
+
{ paragraphs: [{ runs: [{ text: '+26% ' }, { text: 'QoQ', format: { bold: true } }] }] },
|
|
145
|
+
],
|
|
146
|
+
]}
|
|
147
|
+
cellStyle={{ format: { size: 14 } }}
|
|
148
|
+
/>
|
|
149
|
+
```
|
|
150
|
+
|
|
98
151
|
`Media` embeds a video or audio clip from bytes, or links an online video by
|
|
99
152
|
URL (YouTube page URLs are rewritten to the embed form). `poster` supplies the
|
|
100
153
|
image shown before playback; a neutral play-button poster is used otherwise.
|
|
@@ -128,6 +181,8 @@ slides; use `<Slide from={{index: 0}}>` to duplicate an original slide. Referenc
|
|
|
128
181
|
always refer to the source sequence, and each compilation loads the source fresh.
|
|
129
182
|
A source deck is not reconstructed from DSL-understood fields: the core package
|
|
130
183
|
retains existing parts. Editing text intentionally replaces that shape's text.
|
|
184
|
+
`Fill` takes the same `autoFit` values as `Text` (`"normal"` shrinks text that is
|
|
185
|
+
longer than the placeholder); omitted, the shape keeps the template's setting.
|
|
131
186
|
`size` applies only to new decks; source decks retain their original dimensions.
|
|
132
187
|
`theme` accepts the core theme overrides and follows its first-theme semantics.
|
|
133
188
|
|
|
@@ -162,11 +217,50 @@ context-specific handles and a nesting check. Without scope, contextual handles
|
|
|
162
217
|
are optional. Text also
|
|
163
218
|
accepts Raw children. An enclosing shape does not accept new Slide-level objects.
|
|
164
219
|
|
|
220
|
+
## Embedding `compile()` in your own build
|
|
221
|
+
|
|
222
|
+
An `office-pptx init` project comes with a build that records source locations and
|
|
223
|
+
a `check` script that runs `tsc --noEmit`. A host that calls `compile()` from its own
|
|
224
|
+
build (a server compiling generated TSX, a bundler plugin) has to arrange both.
|
|
225
|
+
|
|
226
|
+
**Build with the dev JSX transform to get source locations.** `compile()` prefixes
|
|
227
|
+
an error with `file:line:col <Element>:` for each enclosing element, but only when the
|
|
228
|
+
module was built with the dev runtime, which records where each element was written.
|
|
229
|
+
`office-pptx` always builds that way.
|
|
230
|
+
|
|
231
|
+
| Tool | Setting |
|
|
232
|
+
| ---------- | ---------------------------------------------- |
|
|
233
|
+
| TypeScript | `"jsx": "react-jsxdev"` instead of `react-jsx` |
|
|
234
|
+
| esbuild | `jsx: 'automatic', jsxDev: true` |
|
|
235
|
+
|
|
236
|
+
```text
|
|
237
|
+
react-jsx Shape reference matched 0 shapes: {"name":"Titel 1"}
|
|
238
|
+
react-jsxdev deck.tsx:6:7 <Slide>: deck.tsx:7:9 <Fill>: Shape reference matched 0 shapes: {"name":"Titel 1"}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Type-check authored modules with `tsc` in strict mode.** The runtime does not
|
|
242
|
+
validate prop names, so `<Table cellFills={...}>` compiles and the unknown prop is
|
|
243
|
+
ignored. Type checking is what rejects it, along with a misspelt literal such as
|
|
244
|
+
`anchor="ctr"`. A transpile-only build (esbuild, swc) skips that check, and a prop
|
|
245
|
+
passed through an object spread escapes it even in `tsc`.
|
|
246
|
+
|
|
247
|
+
**Compile and save.** `compile(root)` takes the root `Presentation` element (a
|
|
248
|
+
module's default export) and resolves to the core presentation; `savePresentation`
|
|
249
|
+
from `@office-kit/pptx` turns that into `.pptx` bytes. Template bytes go in through
|
|
250
|
+
`<Presentation source={bytes}>`, from wherever the host holds them.
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { savePresentation } from '@office-kit/pptx';
|
|
254
|
+
import { compile } from '@office-kit/pptx-dsl';
|
|
255
|
+
|
|
256
|
+
const { default: root } = await import(builtModuleUrl);
|
|
257
|
+
const bytes = await savePresentation(await compile(root));
|
|
258
|
+
```
|
|
259
|
+
|
|
165
260
|
## Current coverage
|
|
166
261
|
|
|
167
262
|
This is an initial DSL, not complete OOXML coverage. Typed master/layout creation,
|
|
168
|
-
animations, transitions, connectors, groups
|
|
169
|
-
cells still require additional declarative elements or core work. Raw can invoke
|
|
263
|
+
animations, transitions, connectors, groups and media playback still require additional declarative elements or core work. Raw can invoke
|
|
170
264
|
available core capabilities but does not count as typed declarative support.
|
|
171
265
|
Cross-presentation imports are not exposed because the current core import API
|
|
172
266
|
can discard unsupported relationships. Do not use it as a lossless import path.
|
package/dist/index.d.ts
CHANGED
|
@@ -84,8 +84,15 @@ interface ShapeStyle {
|
|
|
84
84
|
glow?: api.GlowOptions;
|
|
85
85
|
click?: api.ShapeClickAction;
|
|
86
86
|
}
|
|
87
|
+
/** A paragraph's indent level: 0 is the top, 8 the deepest PowerPoint has. */
|
|
88
|
+
type TextLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
89
|
+
interface TextParagraph extends api.ParagraphSpec {
|
|
90
|
+
/** This paragraph's own bullet; wins over `bullets`. */
|
|
91
|
+
bullet?: api.BulletStyle;
|
|
92
|
+
level?: TextLevel;
|
|
93
|
+
}
|
|
87
94
|
interface TextProps extends Bounds, ShapeStyle, api.TextFormat, Children {
|
|
88
|
-
paragraphs?: readonly
|
|
95
|
+
paragraphs?: readonly TextParagraph[];
|
|
89
96
|
align?: api.ParagraphAlignment;
|
|
90
97
|
anchor?: api.TextAnchor;
|
|
91
98
|
autoFit?: api.TextAutoFit;
|
|
@@ -139,10 +146,24 @@ interface TableCellInfo {
|
|
|
139
146
|
/** Zero-based; row 0 is the header. */
|
|
140
147
|
row: number;
|
|
141
148
|
column: number;
|
|
149
|
+
/** A cell's text; for `paragraphs`, the run texts joined, one line per paragraph. */
|
|
142
150
|
value: string;
|
|
143
151
|
}
|
|
152
|
+
/** Exactly one of `text` and `paragraphs`. An empty cell is the string `''`. */
|
|
153
|
+
type TableCellContent = {
|
|
154
|
+
text: string;
|
|
155
|
+
paragraphs?: never;
|
|
156
|
+
} | {
|
|
157
|
+
text?: never;
|
|
158
|
+
paragraphs: readonly api.ParagraphSpec[];
|
|
159
|
+
};
|
|
160
|
+
type TableCellSpec = TableCellContent & {
|
|
161
|
+
/** This cell is the top-left of a merge. The positions it covers stay in `rows` as `''`. */colSpan?: number;
|
|
162
|
+
rowSpan?: number;
|
|
163
|
+
};
|
|
164
|
+
type TableCell = string | TableCellSpec;
|
|
144
165
|
interface TableProps extends Bounds, Children {
|
|
145
|
-
rows: readonly (readonly
|
|
166
|
+
rows: readonly (readonly TableCell[])[];
|
|
146
167
|
columnWidths?: readonly number[];
|
|
147
168
|
rowHeights?: readonly number[];
|
|
148
169
|
cellStyle?: CellStyle;
|
|
@@ -175,11 +196,13 @@ interface FillProps extends Children {
|
|
|
175
196
|
target: Target;
|
|
176
197
|
text?: string;
|
|
177
198
|
format?: api.TextFormat;
|
|
199
|
+
/** Omitted keeps whatever the template's `<a:bodyPr>` says. */
|
|
200
|
+
autoFit?: api.TextAutoFit;
|
|
178
201
|
}
|
|
179
202
|
declare function Fill(props: FillProps): Node;
|
|
180
203
|
declare function Remove(props: {
|
|
181
204
|
target: Target;
|
|
182
205
|
}): Node;
|
|
183
206
|
//#endregion
|
|
184
|
-
export { Bounds, CellBorderSide, CellStyle, Chart, ChartProps, type Child, type Children, Fill, FillProps, Fragment, Group, GroupProps, Image, ImageProps, LayoutRef, Line, LineProps, Media, MediaProps, type Node, Presentation, type PresentationNode, PresentationProps, Raw, type RawContext, RawProps, Remove, Shape, ShapeProps, ShapeStyle, Slide, SlideProps, SlideRef, Table, TableCellInfo, TableProps, Target, Text, TextProps, compile };
|
|
207
|
+
export { Bounds, CellBorderSide, CellStyle, Chart, ChartProps, type Child, type Children, Fill, FillProps, Fragment, Group, GroupProps, Image, ImageProps, LayoutRef, Line, LineProps, Media, MediaProps, type Node, Presentation, type PresentationNode, PresentationProps, Raw, type RawContext, RawProps, Remove, Shape, ShapeProps, ShapeStyle, Slide, SlideProps, SlideRef, Table, TableCell, TableCellInfo, TableCellSpec, TableProps, Target, Text, TextLevel, TextParagraph, TextProps, compile };
|
|
185
208
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -116,7 +116,13 @@ function Text(props) {
|
|
|
116
116
|
if (props.align) api.setShapeAlignment(shape, props.align);
|
|
117
117
|
if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);
|
|
118
118
|
if (props.autoFit) api.setShapeTextAutoFit(shape, props.autoFit);
|
|
119
|
+
props.paragraphs?.forEach((paragraph, index) => {
|
|
120
|
+
if (paragraph.level !== void 0) api.setParagraphLevel(shape, index, paragraph.level);
|
|
121
|
+
});
|
|
119
122
|
if (props.bullets !== void 0) api.setShapeBullets(shape, props.bullets);
|
|
123
|
+
props.paragraphs?.forEach((paragraph, index) => {
|
|
124
|
+
if (paragraph.bullet !== void 0) api.setParagraphBullet(shape, index, paragraph.bullet);
|
|
125
|
+
});
|
|
120
126
|
if (props.paragraphSpacing) {
|
|
121
127
|
const { before, after } = props.paragraphSpacing;
|
|
122
128
|
const spacing = {
|
|
@@ -216,21 +222,50 @@ function cellBorders(borders) {
|
|
|
216
222
|
}
|
|
217
223
|
return sides;
|
|
218
224
|
}
|
|
225
|
+
const positionKey = (row, col) => `${row}:${col}`;
|
|
226
|
+
const cellSpec = (cell) => typeof cell === "string" ? { text: cell } : cell;
|
|
227
|
+
const cellValue = (spec) => spec.paragraphs ? spec.paragraphs.map((paragraph) => paragraph.runs.map((run) => run.text).join("")).join("\n") : spec.text;
|
|
228
|
+
/** Maps every position a merge covers to that merge's top-left cell. */
|
|
229
|
+
function coveredPositions(rows) {
|
|
230
|
+
const covered = /* @__PURE__ */ new Map();
|
|
231
|
+
rows.forEach((cells, row) => cells.forEach((cell, col) => {
|
|
232
|
+
const { rowSpan = 1, colSpan = 1 } = cellSpec(cell);
|
|
233
|
+
const lastRow = Math.min(row + rowSpan, rows.length);
|
|
234
|
+
const lastCol = Math.min(col + colSpan, cells.length);
|
|
235
|
+
for (let r = row; r < lastRow; r++) for (let c = col; c < lastCol; c++) if (r !== row || c !== col) covered.set(positionKey(r, c), {
|
|
236
|
+
row,
|
|
237
|
+
col
|
|
238
|
+
});
|
|
239
|
+
}));
|
|
240
|
+
return covered;
|
|
241
|
+
}
|
|
242
|
+
function checkCells(rows, covered) {
|
|
243
|
+
rows.forEach((cells, row) => cells.forEach((cell, col) => {
|
|
244
|
+
const spec = cellSpec(cell);
|
|
245
|
+
if (spec.text === void 0 === (spec.paragraphs === void 0)) throw new Error(`Table cell (${row}, ${col}) accepts either text or paragraphs.`);
|
|
246
|
+
const anchor = covered.get(positionKey(row, col));
|
|
247
|
+
if (anchor && cell !== "") throw new Error(`Table cell (${row}, ${col}) is covered by the merge at (${anchor.row}, ${anchor.col}); write it as ''.`);
|
|
248
|
+
}));
|
|
249
|
+
}
|
|
219
250
|
function Table(props) {
|
|
220
251
|
return node("Table", async (context) => {
|
|
252
|
+
const covered = coveredPositions(props.rows);
|
|
253
|
+
checkCells(props.rows, covered);
|
|
221
254
|
const shape = created(context, api.addSlideTable(requireSlide(context), {
|
|
222
255
|
...bounds(props),
|
|
223
|
-
rows: props.rows,
|
|
256
|
+
rows: props.rows.map((cells) => cells.map((cell) => cellSpec(cell).text ?? "")),
|
|
224
257
|
...props.columnWidths ? { colWidths: props.columnWidths.map(api.inches) } : {},
|
|
225
258
|
...props.rowHeights ? { rowHeights: props.rowHeights.map(api.inches) } : {}
|
|
226
259
|
}));
|
|
227
|
-
props.rows.forEach((row, r) => row.forEach((
|
|
260
|
+
props.rows.forEach((row, r) => row.forEach((entry, c) => {
|
|
261
|
+
if (covered.has(positionKey(r, c))) return;
|
|
262
|
+
const spec = cellSpec(entry);
|
|
228
263
|
const cell = api.getTableCell(shape, r, c);
|
|
229
264
|
const header = r === 0 ? props.headerStyle : void 0;
|
|
230
265
|
const own = props.styleCell?.({
|
|
231
266
|
row: r,
|
|
232
267
|
column: c,
|
|
233
|
-
value
|
|
268
|
+
value: cellValue(spec)
|
|
234
269
|
});
|
|
235
270
|
const striped = r > 0 && r % 2 === 0 ? props.stripeFill : void 0;
|
|
236
271
|
const appearance = {
|
|
@@ -245,9 +280,29 @@ function Table(props) {
|
|
|
245
280
|
}
|
|
246
281
|
};
|
|
247
282
|
if (appearance.fill) api.setTableCellFill(cell, appearance.fill);
|
|
248
|
-
if (
|
|
283
|
+
if (spec.paragraphs) {
|
|
284
|
+
const built = api.getTableCellParagraphs(cell)[0]?.elements[0];
|
|
285
|
+
const base = {
|
|
286
|
+
...built?.kind === "r" ? built.format : {},
|
|
287
|
+
...appearance.format
|
|
288
|
+
};
|
|
289
|
+
const { align } = appearance;
|
|
290
|
+
api.setTableCellParagraphs(cell, spec.paragraphs.map((paragraph) => ({
|
|
291
|
+
...paragraph,
|
|
292
|
+
...paragraph.align === void 0 && align ? { align } : {},
|
|
293
|
+
runs: paragraph.runs.map((run) => ({
|
|
294
|
+
...run,
|
|
295
|
+
format: {
|
|
296
|
+
...base,
|
|
297
|
+
...run.format
|
|
298
|
+
}
|
|
299
|
+
}))
|
|
300
|
+
})));
|
|
301
|
+
} else {
|
|
302
|
+
if (appearance.format) api.setTableCellTextFormat(cell, appearance.format);
|
|
303
|
+
if (appearance.align) api.setTableCellAlignment(cell, appearance.align);
|
|
304
|
+
}
|
|
249
305
|
if (appearance.anchor) api.setTableCellAnchor(cell, appearance.anchor);
|
|
250
|
-
if (appearance.align) api.setTableCellAlignment(cell, appearance.align);
|
|
251
306
|
const borders = cellBorders({
|
|
252
307
|
...props.cellStyle?.borders,
|
|
253
308
|
...header?.borders,
|
|
@@ -255,6 +310,15 @@ function Table(props) {
|
|
|
255
310
|
});
|
|
256
311
|
if (Object.keys(borders).length > 0) api.setTableCellBorders(cell, borders);
|
|
257
312
|
}));
|
|
313
|
+
props.rows.forEach((row, r) => row.forEach((entry, c) => {
|
|
314
|
+
const { rowSpan = 1, colSpan = 1 } = cellSpec(entry);
|
|
315
|
+
if (rowSpan !== 1 || colSpan !== 1) api.mergeTableCells(shape, {
|
|
316
|
+
row: r,
|
|
317
|
+
col: c,
|
|
318
|
+
rowSpan,
|
|
319
|
+
colSpan
|
|
320
|
+
});
|
|
321
|
+
}));
|
|
258
322
|
await visit(props.children, {
|
|
259
323
|
...context,
|
|
260
324
|
shape,
|
|
@@ -306,6 +370,7 @@ function Fill(props) {
|
|
|
306
370
|
const shape = selectShape(requireSlide(context), props.target);
|
|
307
371
|
api.setShapeText(shape, props.text ?? literal(props.children));
|
|
308
372
|
if (props.format) api.setShapeTextFormat(shape, props.format);
|
|
373
|
+
if (props.autoFit) api.setShapeTextAutoFit(shape, props.autoFit);
|
|
309
374
|
});
|
|
310
375
|
}
|
|
311
376
|
function Remove(props) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import * as api from '@office-kit/pptx';\nimport {\n created,\n textContent,\n literal,\n node,\n requireSlide,\n visit,\n type Children,\n type Context,\n type Node,\n type PresentationNode,\n type RawContext,\n} from './model.ts';\nexport type { Child, Children, Node, PresentationNode, RawContext } from './model.ts';\nexport { Fragment } from './jsx-runtime.ts';\n\nexport type PresentationProps = Children &\n (\n | { source: api.PresentationInput; size?: never }\n | { source?: never; size?: api.PresentationSize }\n ) & {\n theme?: Parameters<typeof api.setPresentationTheme>[1];\n /** Compose replaces the slide sequence; edit retains the original sequence. */\n mode?: 'compose' | 'edit';\n };\nexport function Presentation(props: PresentationProps): PresentationNode {\n return {\n kind: 'Presentation',\n evaluate: () => {\n throw new Error('Presentation must be the root.');\n },\n async compile() {\n if (props.source !== undefined && props.size !== undefined)\n throw new Error('Presentation source retains its original size; do not specify size.');\n const presentation =\n props.source === undefined\n ? api.createPresentation(props.size === undefined ? {} : { size: props.size })\n : await api.loadPresentation(props.source);\n if (props.theme) api.setPresentationTheme(presentation, props.theme);\n const originals = [...api.getSlides(presentation)];\n const context: Context = {\n presentation,\n originals,\n mode: props.mode ?? (props.source === undefined ? 'compose' : 'edit'),\n scope: 'presentation',\n deferred: [],\n };\n await visit(props.children, context);\n for (const apply of context.deferred) await apply();\n if (context.mode === 'compose') {\n for (const slide of originals) api.removeSlide(presentation, slide);\n }\n return presentation;\n },\n };\n}\nexport async function compile(root: Node): Promise<api.PresentationData> {\n if (!('compile' in root) || typeof root.compile !== 'function')\n throw new Error('Export a Presentation as the root.');\n return root.compile();\n}\n\nexport type LayoutRef = { name: string } | { part: string } | { type: string };\nexport type SlideRef = { index: number } | { part: string } | { title: string };\nexport type Target =\n | { name: string }\n | { id: number }\n | { placeholder: { type?: string; idx?: number } };\nexport type SlideProps = Children &\n ({ from?: SlideRef; target?: never } | { from?: never; target: SlideRef }) & {\n layout?: LayoutRef;\n background?: string;\n notes?: string;\n };\nfunction selectSlide(context: Context, ref: SlideRef): api.SlideData {\n const matches = context.originals.filter((slide, index) =>\n 'index' in ref\n ? index === ref.index\n : 'part' in ref\n ? api.getSlidePartName(slide) === ref.part\n : api.getSlideTitle(slide) === ref.title,\n );\n if (matches.length !== 1)\n throw new Error(`Slide reference matched ${matches.length} slides: ${JSON.stringify(ref)}`);\n return matches[0]!;\n}\nfunction selectLayout(presentation: api.PresentationData, ref: LayoutRef): api.SlideLayoutData {\n const matches = api\n .getSlideLayouts(presentation)\n .filter((layout) =>\n 'name' in ref\n ? api.getSlideLayoutName(layout) === ref.name\n : 'part' in ref\n ? api.getSlideLayoutPartName(layout) === ref.part\n : api.getSlideLayoutType(layout) === ref.type,\n );\n if (matches.length !== 1)\n throw new Error(`Layout reference matched ${matches.length} layouts: ${JSON.stringify(ref)}`);\n return matches[0]!;\n}\nexport function Slide(props: SlideProps): Node {\n return node('Slide', async (context) => {\n if (context.scope !== 'presentation') throw new Error('Slide must be inside Presentation.');\n if (props.target && context.mode !== 'edit')\n throw new Error('Slide target requires Presentation mode=\"edit\".');\n if (props.from && props.target) throw new Error('Slide cannot specify both from and target.');\n const layout = props.layout ? selectLayout(context.presentation, props.layout) : undefined;\n const slide = props.target\n ? selectSlide(context, props.target)\n : props.from\n ? api.duplicateSlide(context.presentation, selectSlide(context, props.from))\n : layout\n ? api.addSlide(context.presentation, { layout })\n : api.addBlankSlide(context.presentation);\n if (layout && (props.from || props.target)) api.setSlideLayout(slide, layout);\n if (props.background !== undefined) api.setSlideBackground(slide, props.background);\n if (props.notes !== undefined) api.setSlideNotes(slide, props.notes);\n await visit(props.children, { ...context, slide, scope: 'slide' });\n });\n}\nexport type RawProps =\n | { scope?: undefined; apply: (context: RawContext) => void | Promise<void> }\n | {\n scope: 'presentation';\n apply: (context: Pick<RawContext, 'presentation'>) => void | Promise<void>;\n }\n | {\n scope: 'slide';\n apply: (context: RawContext & { slide: api.SlideData }) => void | Promise<void>;\n }\n | { scope: 'shape'; apply: (context: Required<RawContext>) => void | Promise<void> };\n\nexport function Raw(props: RawProps): Node {\n return node('Raw', (context) => {\n if (props.scope !== undefined && props.scope !== context.scope) {\n throw new Error(`Raw scope=\"${props.scope}\" cannot run inside ${context.scope}.`);\n }\n context.deferred.push(() => {\n if (props.scope === 'shape') {\n if (!context.shape || !context.slide) throw new Error('Raw requires a shape context.');\n return props.apply({\n presentation: context.presentation,\n slide: context.slide,\n shape: context.shape,\n });\n }\n if (props.scope === 'slide') {\n if (!context.slide) throw new Error('Raw requires a slide context.');\n return props.apply({ ...context, slide: context.slide });\n }\n return props.apply(context);\n });\n });\n}\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\nexport interface ShapeStyle {\n name?: string;\n fill?: string | api.GradientFillOptions;\n stroke?: { color: string; width?: number } | false;\n rotation?: number;\n shadow?: api.ShadowOptions;\n glow?: api.GlowOptions;\n click?: api.ShapeClickAction;\n}\nfunction bounds(props: Bounds) {\n return {\n x: api.inches(props.x),\n y: api.inches(props.y),\n w: api.inches(props.width),\n h: api.inches(props.height),\n };\n}\nfunction style(shape: api.SlideShapeData, props: ShapeStyle) {\n if (props.fill !== undefined) {\n if (typeof props.fill === 'string') api.setShapeFill(shape, props.fill);\n else api.setShapeGradientFill(shape, props.fill);\n }\n if (props.stroke === false) api.setShapeNoStroke(shape);\n else if (props.stroke)\n api.setShapeStroke(shape, {\n color: props.stroke.color,\n widthEmu: api.pt(props.stroke.width ?? 1),\n });\n if (props.rotation !== undefined) api.setShapeRotation(shape, props.rotation);\n if (props.shadow) api.setShapeShadow(shape, props.shadow);\n if (props.glow) api.setShapeGlow(shape, props.glow);\n if (props.click) api.setShapeClickAction(shape, props.click);\n}\nexport interface TextProps extends Bounds, ShapeStyle, api.TextFormat, Children {\n paragraphs?: readonly api.ParagraphSpec[];\n align?: api.ParagraphAlignment;\n anchor?: api.TextAnchor;\n autoFit?: api.TextAutoFit;\n /** Bullet or numbering for every paragraph; a newline in the text starts a paragraph. */\n bullets?: api.BulletStyle;\n /** Space before / after every paragraph, in points. */\n paragraphSpacing?: { before?: number; after?: number };\n}\nexport function Text(props: TextProps): Node {\n return node('Text', async (context) => {\n const slide = requireSlide(context);\n const content = textContent(props.children);\n if (props.paragraphs && content.text.trim())\n throw new Error('Text accepts either text children or paragraphs.');\n const shape = created(\n context,\n api.addSlideTextBox(slide, {\n ...bounds(props),\n ...(props.name ? { name: props.name } : {}),\n text: content.text,\n }),\n );\n if (props.paragraphs) api.setShapeParagraphs(shape, props.paragraphs);\n api.setShapeTextFormat(shape, props);\n if (props.align) api.setShapeAlignment(shape, props.align);\n if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);\n if (props.autoFit) api.setShapeTextAutoFit(shape, props.autoFit);\n if (props.bullets !== undefined) api.setShapeBullets(shape, props.bullets);\n if (props.paragraphSpacing) {\n const { before, after } = props.paragraphSpacing;\n const spacing = {\n ...(before !== undefined ? { beforePts: before } : {}),\n ...(after !== undefined ? { afterPts: after } : {}),\n };\n for (let i = 0; i < api.getShapeParagraphCount(shape); i++) {\n api.setParagraphSpacing(shape, i, spacing);\n }\n }\n style(shape, props);\n await visit(content.elements, { ...context, slide, shape, scope: 'shape' });\n });\n}\nexport interface ShapeProps extends Bounds, ShapeStyle, Children {\n preset: Parameters<typeof api.addSlideShape>[1]['preset'];\n text?: string;\n format?: api.TextFormat;\n /** Alignment and anchor of `text` inside the shape. */\n align?: api.ParagraphAlignment;\n anchor?: api.TextAnchor;\n}\nexport function Shape(props: ShapeProps): Node {\n return node('Shape', async (context) => {\n if ((props.align || props.anchor) && props.text === undefined)\n throw new Error('Shape align and anchor position its text; set text as well.');\n const shape = created(\n context,\n api.addSlideShape(requireSlide(context), {\n ...bounds(props),\n preset: props.preset,\n ...(props.name ? { name: props.name } : {}),\n ...(props.text !== undefined ? { text: props.text } : {}),\n }),\n );\n style(shape, props);\n if (props.format) api.setShapeTextFormat(shape, props.format);\n if (props.align) api.setShapeAlignment(shape, props.align);\n if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface ImageProps extends Bounds, ShapeStyle, Children {\n data: Uint8Array;\n format?: api.ImageFormat;\n fit?: api.ImageFit;\n}\nexport function Image(props: ImageProps): Node {\n return node('Image', async (context) => {\n const shape = created(\n context,\n api.addSlideImage(requireSlide(context), props.data, {\n ...bounds(props),\n ...(props.format ? { format: props.format } : {}),\n ...(props.fit ? { fit: props.fit } : {}),\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n style(shape, props);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\n// No ShapeStyle: a clip's picture already carries the `ppaction://media` click\n// action that makes it playable, which `click` would replace.\nexport type MediaProps = Bounds &\n Children &\n api.SlideMediaSource & {\n name?: string;\n poster?: Uint8Array;\n posterFormat?: api.ImageFormat;\n };\nexport function Media(props: MediaProps): Node {\n return node('Media', async (context) => {\n const { x: _x, y: _y, width: _width, height: _height, children, ...media } = props;\n const shape = created(\n context,\n api.addSlideMedia(requireSlide(context), { ...media, ...bounds(props) }),\n );\n await visit(children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface ChartProps extends Bounds, ShapeStyle, Children {\n spec: api.ChartSpec;\n}\nexport function Chart(props: ChartProps): Node {\n return node('Chart', async (context) => {\n const shape = created(\n context,\n api.addSlideChart(requireSlide(context), {\n ...bounds(props),\n spec: props.spec,\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n style(shape, props);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport type CellBorderSide = 'left' | 'right' | 'top' | 'bottom';\nexport interface CellStyle {\n fill?: string;\n format?: api.TextFormat;\n anchor?: api.TextAnchor;\n align?: api.ParagraphAlignment;\n /** Border per side. `width` is in points; without it the line has no explicit width. */\n borders?: Partial<Record<CellBorderSide, { color: string; width?: number }>>;\n}\nexport interface TableCellInfo {\n /** Zero-based; row 0 is the header. */\n row: number;\n column: number;\n value: string;\n}\nexport interface TableProps extends Bounds, Children {\n rows: readonly (readonly string[])[];\n columnWidths?: readonly number[];\n rowHeights?: readonly number[];\n cellStyle?: CellStyle;\n headerStyle?: CellStyle;\n stripeFill?: string;\n /**\n * Style for one cell, merged over `cellStyle`, `headerStyle` and\n * `stripeFill` — for a status column, a total row, a highlighted figure.\n */\n styleCell?: (cell: TableCellInfo) => CellStyle | undefined;\n}\nfunction cellBorders(borders: NonNullable<CellStyle['borders']>) {\n const sides: Partial<Record<CellBorderSide, { color: string; widthEmu?: number }>> = {};\n for (const side of ['left', 'right', 'top', 'bottom'] as const) {\n const border = borders[side];\n if (!border) continue;\n sides[side] = {\n color: border.color,\n ...(border.width !== undefined ? { widthEmu: api.pt(border.width) } : {}),\n };\n }\n return sides;\n}\nexport function Table(props: TableProps): Node {\n return node('Table', async (context) => {\n const shape = created(\n context,\n api.addSlideTable(requireSlide(context), {\n ...bounds(props),\n rows: props.rows,\n ...(props.columnWidths ? { colWidths: props.columnWidths.map(api.inches) } : {}),\n ...(props.rowHeights ? { rowHeights: props.rowHeights.map(api.inches) } : {}),\n }),\n );\n props.rows.forEach((row, r) =>\n row.forEach((value, c) => {\n const cell = api.getTableCell(shape, r, c);\n const header = r === 0 ? props.headerStyle : undefined;\n const own = props.styleCell?.({ row: r, column: c, value });\n const striped = r > 0 && r % 2 === 0 ? props.stripeFill : undefined;\n const appearance: CellStyle = {\n ...props.cellStyle,\n ...header,\n ...(striped !== undefined ? { fill: striped } : {}),\n ...own,\n format: { ...props.cellStyle?.format, ...header?.format, ...own?.format },\n };\n if (appearance.fill) api.setTableCellFill(cell, appearance.fill);\n if (appearance.format) api.setTableCellTextFormat(cell, appearance.format);\n if (appearance.anchor) api.setTableCellAnchor(cell, appearance.anchor);\n if (appearance.align) api.setTableCellAlignment(cell, appearance.align);\n // Only when a side is set: an empty call would still give every cell a <a:tcPr>.\n const borders = cellBorders({\n ...props.cellStyle?.borders,\n ...header?.borders,\n ...own?.borders,\n });\n if (Object.keys(borders).length > 0) api.setTableCellBorders(cell, borders);\n }),\n );\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface LineProps {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n color?: string;\n /** Stroke width in points. */\n width?: number;\n name?: string;\n}\nexport function Line(props: LineProps): Node {\n return node('Line', (context) => {\n created(\n context,\n api.addSlideLine(requireSlide(context), {\n from: { x: api.inches(props.x1), y: api.inches(props.y1) },\n to: { x: api.inches(props.x2), y: api.inches(props.y2) },\n ...(props.color !== undefined ? { color: props.color } : {}),\n ...(props.width !== undefined ? { widthEmu: api.pt(props.width) } : {}),\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n });\n}\nexport interface GroupProps extends Children {\n name?: string;\n}\n/** Groups the shapes its children create, so they move and resize as one object. */\nexport function Group(props: GroupProps): Node {\n return node('Group', async (context) => {\n requireSlide(context);\n const members: api.SlideShapeData[] = [];\n await visit(props.children, { ...context, members });\n created(context, api.groupShapes(members, props.name ? { name: props.name } : {}));\n });\n}\nfunction selectShape(slide: api.SlideData, target: Target): api.SlideShapeData {\n const matches = api.getSlideShapes(slide).filter((shape) => {\n if ('name' in target) return api.getShapeName(shape) === target.name;\n if ('id' in target) return api.getShapeId(shape) === target.id;\n const ph = target.placeholder;\n return (\n (ph.type !== undefined || ph.idx !== undefined) &&\n (ph.type === undefined || api.getShapePlaceholderType(shape) === ph.type) &&\n (ph.idx === undefined || api.getShapePlaceholderIdx(shape) === ph.idx)\n );\n });\n if (matches.length !== 1)\n throw new Error(`Shape reference matched ${matches.length} shapes: ${JSON.stringify(target)}`);\n return matches[0]!;\n}\nexport interface FillProps extends Children {\n target: Target;\n text?: string;\n format?: api.TextFormat;\n}\nexport function Fill(props: FillProps): Node {\n return node('Fill', (context) => {\n const shape = selectShape(requireSlide(context), props.target);\n api.setShapeText(shape, props.text ?? literal(props.children));\n if (props.format) api.setShapeTextFormat(shape, props.format);\n });\n}\nexport function Remove(props: { target: Target }): Node {\n return node('Remove', (context) => {\n const slide = requireSlide(context);\n api.removeShape(selectShape(slide, props.target));\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import * as api from '@office-kit/pptx';\nimport {\n created,\n textContent,\n literal,\n node,\n requireSlide,\n visit,\n type Children,\n type Context,\n type Node,\n type PresentationNode,\n type RawContext,\n} from './model.ts';\nexport type { Child, Children, Node, PresentationNode, RawContext } from './model.ts';\nexport { Fragment } from './jsx-runtime.ts';\n\nexport type PresentationProps = Children &\n (\n | { source: api.PresentationInput; size?: never }\n | { source?: never; size?: api.PresentationSize }\n ) & {\n theme?: Parameters<typeof api.setPresentationTheme>[1];\n /** Compose replaces the slide sequence; edit retains the original sequence. */\n mode?: 'compose' | 'edit';\n };\nexport function Presentation(props: PresentationProps): PresentationNode {\n return {\n kind: 'Presentation',\n evaluate: () => {\n throw new Error('Presentation must be the root.');\n },\n async compile() {\n if (props.source !== undefined && props.size !== undefined)\n throw new Error('Presentation source retains its original size; do not specify size.');\n const presentation =\n props.source === undefined\n ? api.createPresentation(props.size === undefined ? {} : { size: props.size })\n : await api.loadPresentation(props.source);\n if (props.theme) api.setPresentationTheme(presentation, props.theme);\n const originals = [...api.getSlides(presentation)];\n const context: Context = {\n presentation,\n originals,\n mode: props.mode ?? (props.source === undefined ? 'compose' : 'edit'),\n scope: 'presentation',\n deferred: [],\n };\n await visit(props.children, context);\n for (const apply of context.deferred) await apply();\n if (context.mode === 'compose') {\n for (const slide of originals) api.removeSlide(presentation, slide);\n }\n return presentation;\n },\n };\n}\nexport async function compile(root: Node): Promise<api.PresentationData> {\n if (!('compile' in root) || typeof root.compile !== 'function')\n throw new Error('Export a Presentation as the root.');\n return root.compile();\n}\n\nexport type LayoutRef = { name: string } | { part: string } | { type: string };\nexport type SlideRef = { index: number } | { part: string } | { title: string };\nexport type Target =\n | { name: string }\n | { id: number }\n | { placeholder: { type?: string; idx?: number } };\nexport type SlideProps = Children &\n ({ from?: SlideRef; target?: never } | { from?: never; target: SlideRef }) & {\n layout?: LayoutRef;\n background?: string;\n notes?: string;\n };\nfunction selectSlide(context: Context, ref: SlideRef): api.SlideData {\n const matches = context.originals.filter((slide, index) =>\n 'index' in ref\n ? index === ref.index\n : 'part' in ref\n ? api.getSlidePartName(slide) === ref.part\n : api.getSlideTitle(slide) === ref.title,\n );\n if (matches.length !== 1)\n throw new Error(`Slide reference matched ${matches.length} slides: ${JSON.stringify(ref)}`);\n return matches[0]!;\n}\nfunction selectLayout(presentation: api.PresentationData, ref: LayoutRef): api.SlideLayoutData {\n const matches = api\n .getSlideLayouts(presentation)\n .filter((layout) =>\n 'name' in ref\n ? api.getSlideLayoutName(layout) === ref.name\n : 'part' in ref\n ? api.getSlideLayoutPartName(layout) === ref.part\n : api.getSlideLayoutType(layout) === ref.type,\n );\n if (matches.length !== 1)\n throw new Error(`Layout reference matched ${matches.length} layouts: ${JSON.stringify(ref)}`);\n return matches[0]!;\n}\nexport function Slide(props: SlideProps): Node {\n return node('Slide', async (context) => {\n if (context.scope !== 'presentation') throw new Error('Slide must be inside Presentation.');\n if (props.target && context.mode !== 'edit')\n throw new Error('Slide target requires Presentation mode=\"edit\".');\n if (props.from && props.target) throw new Error('Slide cannot specify both from and target.');\n const layout = props.layout ? selectLayout(context.presentation, props.layout) : undefined;\n const slide = props.target\n ? selectSlide(context, props.target)\n : props.from\n ? api.duplicateSlide(context.presentation, selectSlide(context, props.from))\n : layout\n ? api.addSlide(context.presentation, { layout })\n : api.addBlankSlide(context.presentation);\n if (layout && (props.from || props.target)) api.setSlideLayout(slide, layout);\n if (props.background !== undefined) api.setSlideBackground(slide, props.background);\n if (props.notes !== undefined) api.setSlideNotes(slide, props.notes);\n await visit(props.children, { ...context, slide, scope: 'slide' });\n });\n}\nexport type RawProps =\n | { scope?: undefined; apply: (context: RawContext) => void | Promise<void> }\n | {\n scope: 'presentation';\n apply: (context: Pick<RawContext, 'presentation'>) => void | Promise<void>;\n }\n | {\n scope: 'slide';\n apply: (context: RawContext & { slide: api.SlideData }) => void | Promise<void>;\n }\n | { scope: 'shape'; apply: (context: Required<RawContext>) => void | Promise<void> };\n\nexport function Raw(props: RawProps): Node {\n return node('Raw', (context) => {\n if (props.scope !== undefined && props.scope !== context.scope) {\n throw new Error(`Raw scope=\"${props.scope}\" cannot run inside ${context.scope}.`);\n }\n context.deferred.push(() => {\n if (props.scope === 'shape') {\n if (!context.shape || !context.slide) throw new Error('Raw requires a shape context.');\n return props.apply({\n presentation: context.presentation,\n slide: context.slide,\n shape: context.shape,\n });\n }\n if (props.scope === 'slide') {\n if (!context.slide) throw new Error('Raw requires a slide context.');\n return props.apply({ ...context, slide: context.slide });\n }\n return props.apply(context);\n });\n });\n}\nexport interface Bounds {\n x: number;\n y: number;\n width: number;\n height: number;\n}\nexport interface ShapeStyle {\n name?: string;\n fill?: string | api.GradientFillOptions;\n stroke?: { color: string; width?: number } | false;\n rotation?: number;\n shadow?: api.ShadowOptions;\n glow?: api.GlowOptions;\n click?: api.ShapeClickAction;\n}\nfunction bounds(props: Bounds) {\n return {\n x: api.inches(props.x),\n y: api.inches(props.y),\n w: api.inches(props.width),\n h: api.inches(props.height),\n };\n}\nfunction style(shape: api.SlideShapeData, props: ShapeStyle) {\n if (props.fill !== undefined) {\n if (typeof props.fill === 'string') api.setShapeFill(shape, props.fill);\n else api.setShapeGradientFill(shape, props.fill);\n }\n if (props.stroke === false) api.setShapeNoStroke(shape);\n else if (props.stroke)\n api.setShapeStroke(shape, {\n color: props.stroke.color,\n widthEmu: api.pt(props.stroke.width ?? 1),\n });\n if (props.rotation !== undefined) api.setShapeRotation(shape, props.rotation);\n if (props.shadow) api.setShapeShadow(shape, props.shadow);\n if (props.glow) api.setShapeGlow(shape, props.glow);\n if (props.click) api.setShapeClickAction(shape, props.click);\n}\n/** A paragraph's indent level: 0 is the top, 8 the deepest PowerPoint has. */\nexport type TextLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;\nexport interface TextParagraph extends api.ParagraphSpec {\n /** This paragraph's own bullet; wins over `bullets`. */\n bullet?: api.BulletStyle;\n level?: TextLevel;\n}\nexport interface TextProps extends Bounds, ShapeStyle, api.TextFormat, Children {\n paragraphs?: readonly TextParagraph[];\n align?: api.ParagraphAlignment;\n anchor?: api.TextAnchor;\n autoFit?: api.TextAutoFit;\n /** Bullet or numbering for every paragraph; a newline in the text starts a paragraph. */\n bullets?: api.BulletStyle;\n /** Space before / after every paragraph, in points. */\n paragraphSpacing?: { before?: number; after?: number };\n}\nexport function Text(props: TextProps): Node {\n return node('Text', async (context) => {\n const slide = requireSlide(context);\n const content = textContent(props.children);\n if (props.paragraphs && content.text.trim())\n throw new Error('Text accepts either text children or paragraphs.');\n const shape = created(\n context,\n api.addSlideTextBox(slide, {\n ...bounds(props),\n ...(props.name ? { name: props.name } : {}),\n text: content.text,\n }),\n );\n if (props.paragraphs) api.setShapeParagraphs(shape, props.paragraphs);\n api.setShapeTextFormat(shape, props);\n if (props.align) api.setShapeAlignment(shape, props.align);\n if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);\n if (props.autoFit) api.setShapeTextAutoFit(shape, props.autoFit);\n // Before any bullet: core 0.17.0, still in the peer range, sizes a bullet's hanging\n // indent from the level at that moment and never moves it afterwards.\n props.paragraphs?.forEach((paragraph, index) => {\n if (paragraph.level !== undefined) api.setParagraphLevel(shape, index, paragraph.level);\n });\n if (props.bullets !== undefined) api.setShapeBullets(shape, props.bullets);\n props.paragraphs?.forEach((paragraph, index) => {\n if (paragraph.bullet !== undefined) api.setParagraphBullet(shape, index, paragraph.bullet);\n });\n if (props.paragraphSpacing) {\n const { before, after } = props.paragraphSpacing;\n const spacing = {\n ...(before !== undefined ? { beforePts: before } : {}),\n ...(after !== undefined ? { afterPts: after } : {}),\n };\n for (let i = 0; i < api.getShapeParagraphCount(shape); i++) {\n api.setParagraphSpacing(shape, i, spacing);\n }\n }\n style(shape, props);\n await visit(content.elements, { ...context, slide, shape, scope: 'shape' });\n });\n}\nexport interface ShapeProps extends Bounds, ShapeStyle, Children {\n preset: Parameters<typeof api.addSlideShape>[1]['preset'];\n text?: string;\n format?: api.TextFormat;\n /** Alignment and anchor of `text` inside the shape. */\n align?: api.ParagraphAlignment;\n anchor?: api.TextAnchor;\n}\nexport function Shape(props: ShapeProps): Node {\n return node('Shape', async (context) => {\n if ((props.align || props.anchor) && props.text === undefined)\n throw new Error('Shape align and anchor position its text; set text as well.');\n const shape = created(\n context,\n api.addSlideShape(requireSlide(context), {\n ...bounds(props),\n preset: props.preset,\n ...(props.name ? { name: props.name } : {}),\n ...(props.text !== undefined ? { text: props.text } : {}),\n }),\n );\n style(shape, props);\n if (props.format) api.setShapeTextFormat(shape, props.format);\n if (props.align) api.setShapeAlignment(shape, props.align);\n if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface ImageProps extends Bounds, ShapeStyle, Children {\n data: Uint8Array;\n format?: api.ImageFormat;\n fit?: api.ImageFit;\n}\nexport function Image(props: ImageProps): Node {\n return node('Image', async (context) => {\n const shape = created(\n context,\n api.addSlideImage(requireSlide(context), props.data, {\n ...bounds(props),\n ...(props.format ? { format: props.format } : {}),\n ...(props.fit ? { fit: props.fit } : {}),\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n style(shape, props);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\n// No ShapeStyle: a clip's picture already carries the `ppaction://media` click\n// action that makes it playable, which `click` would replace.\nexport type MediaProps = Bounds &\n Children &\n api.SlideMediaSource & {\n name?: string;\n poster?: Uint8Array;\n posterFormat?: api.ImageFormat;\n };\nexport function Media(props: MediaProps): Node {\n return node('Media', async (context) => {\n const { x: _x, y: _y, width: _width, height: _height, children, ...media } = props;\n const shape = created(\n context,\n api.addSlideMedia(requireSlide(context), { ...media, ...bounds(props) }),\n );\n await visit(children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface ChartProps extends Bounds, ShapeStyle, Children {\n spec: api.ChartSpec;\n}\nexport function Chart(props: ChartProps): Node {\n return node('Chart', async (context) => {\n const shape = created(\n context,\n api.addSlideChart(requireSlide(context), {\n ...bounds(props),\n spec: props.spec,\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n style(shape, props);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport type CellBorderSide = 'left' | 'right' | 'top' | 'bottom';\nexport interface CellStyle {\n fill?: string;\n format?: api.TextFormat;\n anchor?: api.TextAnchor;\n align?: api.ParagraphAlignment;\n /** Border per side. `width` is in points; without it the line has no explicit width. */\n borders?: Partial<Record<CellBorderSide, { color: string; width?: number }>>;\n}\nexport interface TableCellInfo {\n /** Zero-based; row 0 is the header. */\n row: number;\n column: number;\n /** A cell's text; for `paragraphs`, the run texts joined, one line per paragraph. */\n value: string;\n}\n/** Exactly one of `text` and `paragraphs`. An empty cell is the string `''`. */\ntype TableCellContent =\n | { text: string; paragraphs?: never }\n | { text?: never; paragraphs: readonly api.ParagraphSpec[] };\nexport type TableCellSpec = TableCellContent & {\n /** This cell is the top-left of a merge. The positions it covers stay in `rows` as `''`. */\n colSpan?: number;\n rowSpan?: number;\n};\nexport type TableCell = string | TableCellSpec;\nexport interface TableProps extends Bounds, Children {\n rows: readonly (readonly TableCell[])[];\n columnWidths?: readonly number[];\n rowHeights?: readonly number[];\n cellStyle?: CellStyle;\n headerStyle?: CellStyle;\n stripeFill?: string;\n /**\n * Style for one cell, merged over `cellStyle`, `headerStyle` and\n * `stripeFill` — for a status column, a total row, a highlighted figure.\n */\n styleCell?: (cell: TableCellInfo) => CellStyle | undefined;\n}\nfunction cellBorders(borders: NonNullable<CellStyle['borders']>) {\n const sides: Partial<Record<CellBorderSide, { color: string; widthEmu?: number }>> = {};\n for (const side of ['left', 'right', 'top', 'bottom'] as const) {\n const border = borders[side];\n if (!border) continue;\n sides[side] = {\n color: border.color,\n ...(border.width !== undefined ? { widthEmu: api.pt(border.width) } : {}),\n };\n }\n return sides;\n}\ntype CellPosition = { row: number; col: number };\nconst positionKey = (row: number, col: number) => `${row}:${col}`;\nconst cellSpec = (cell: TableCell): TableCellSpec =>\n typeof cell === 'string' ? { text: cell } : cell;\nconst cellValue = (spec: TableCellSpec): string =>\n spec.paragraphs\n ? spec.paragraphs.map((paragraph) => paragraph.runs.map((run) => run.text).join('')).join('\\n')\n : spec.text;\n\n/** Maps every position a merge covers to that merge's top-left cell. */\nfunction coveredPositions(rows: TableProps['rows']): Map<string, CellPosition> {\n const covered = new Map<string, CellPosition>();\n rows.forEach((cells, row) =>\n cells.forEach((cell, col) => {\n const { rowSpan = 1, colSpan = 1 } = cellSpec(cell);\n // Clamped to the grid: the core rejects an oversized span later, and an\n // unbounded loop must not run first.\n const lastRow = Math.min(row + rowSpan, rows.length);\n const lastCol = Math.min(col + colSpan, cells.length);\n for (let r = row; r < lastRow; r++)\n for (let c = col; c < lastCol; c++)\n if (r !== row || c !== col) covered.set(positionKey(r, c), { row, col });\n }),\n );\n return covered;\n}\nfunction checkCells(rows: TableProps['rows'], covered: Map<string, CellPosition>) {\n rows.forEach((cells, row) =>\n cells.forEach((cell, col) => {\n const spec = cellSpec(cell);\n if ((spec.text === undefined) === (spec.paragraphs === undefined))\n throw new Error(`Table cell (${row}, ${col}) accepts either text or paragraphs.`);\n const anchor = covered.get(positionKey(row, col));\n // PowerPoint paints only the merge's top-left cell, so anything written\n // here would vanish from the slide without a trace.\n if (anchor && cell !== '')\n throw new Error(\n `Table cell (${row}, ${col}) is covered by the merge at (${anchor.row}, ${anchor.col}); write it as ''.`,\n );\n }),\n );\n}\nexport function Table(props: TableProps): Node {\n return node('Table', async (context) => {\n const covered = coveredPositions(props.rows);\n checkCells(props.rows, covered);\n const shape = created(\n context,\n api.addSlideTable(requireSlide(context), {\n ...bounds(props),\n rows: props.rows.map((cells) => cells.map((cell) => cellSpec(cell).text ?? '')),\n ...(props.columnWidths ? { colWidths: props.columnWidths.map(api.inches) } : {}),\n ...(props.rowHeights ? { rowHeights: props.rowHeights.map(api.inches) } : {}),\n }),\n );\n props.rows.forEach((row, r) =>\n row.forEach((entry, c) => {\n // A merged block is painted from its top-left cell alone, fill and all\n // four borders, so a covered position gets no style and no styleCell call.\n if (covered.has(positionKey(r, c))) return;\n const spec = cellSpec(entry);\n const cell = api.getTableCell(shape, r, c);\n const header = r === 0 ? props.headerStyle : undefined;\n const own = props.styleCell?.({ row: r, column: c, value: cellValue(spec) });\n const striped = r > 0 && r % 2 === 0 ? props.stripeFill : undefined;\n const appearance: CellStyle = {\n ...props.cellStyle,\n ...header,\n ...(striped !== undefined ? { fill: striped } : {}),\n ...own,\n format: { ...props.cellStyle?.format, ...header?.format, ...own?.format },\n };\n if (appearance.fill) api.setTableCellFill(cell, appearance.fill);\n if (spec.paragraphs) {\n // addSlideTable bakes the deck's body-text color into each run so text\n // stays readable on an inverted color map; new runs must keep it.\n const built = api.getTableCellParagraphs(cell)[0]?.elements[0];\n const base = { ...(built?.kind === 'r' ? built.format : {}), ...appearance.format };\n const { align } = appearance;\n api.setTableCellParagraphs(\n cell,\n spec.paragraphs.map((paragraph) => ({\n ...paragraph,\n ...(paragraph.align === undefined && align ? { align } : {}),\n runs: paragraph.runs.map((run) => ({ ...run, format: { ...base, ...run.format } })),\n })),\n );\n } else {\n if (appearance.format) api.setTableCellTextFormat(cell, appearance.format);\n if (appearance.align) api.setTableCellAlignment(cell, appearance.align);\n }\n if (appearance.anchor) api.setTableCellAnchor(cell, appearance.anchor);\n // Only when a side is set: an empty call would still give every cell a <a:tcPr>.\n const borders = cellBorders({\n ...props.cellStyle?.borders,\n ...header?.borders,\n ...own?.borders,\n });\n if (Object.keys(borders).length > 0) api.setTableCellBorders(cell, borders);\n }),\n );\n props.rows.forEach((row, r) =>\n row.forEach((entry, c) => {\n const { rowSpan = 1, colSpan = 1 } = cellSpec(entry);\n if (rowSpan !== 1 || colSpan !== 1)\n api.mergeTableCells(shape, { row: r, col: c, rowSpan, colSpan });\n }),\n );\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface LineProps {\n x1: number;\n y1: number;\n x2: number;\n y2: number;\n color?: string;\n /** Stroke width in points. */\n width?: number;\n name?: string;\n}\nexport function Line(props: LineProps): Node {\n return node('Line', (context) => {\n created(\n context,\n api.addSlideLine(requireSlide(context), {\n from: { x: api.inches(props.x1), y: api.inches(props.y1) },\n to: { x: api.inches(props.x2), y: api.inches(props.y2) },\n ...(props.color !== undefined ? { color: props.color } : {}),\n ...(props.width !== undefined ? { widthEmu: api.pt(props.width) } : {}),\n ...(props.name ? { name: props.name } : {}),\n }),\n );\n });\n}\nexport interface GroupProps extends Children {\n name?: string;\n}\n/** Groups the shapes its children create, so they move and resize as one object. */\nexport function Group(props: GroupProps): Node {\n return node('Group', async (context) => {\n requireSlide(context);\n const members: api.SlideShapeData[] = [];\n await visit(props.children, { ...context, members });\n created(context, api.groupShapes(members, props.name ? { name: props.name } : {}));\n });\n}\nfunction selectShape(slide: api.SlideData, target: Target): api.SlideShapeData {\n const matches = api.getSlideShapes(slide).filter((shape) => {\n if ('name' in target) return api.getShapeName(shape) === target.name;\n if ('id' in target) return api.getShapeId(shape) === target.id;\n const ph = target.placeholder;\n return (\n (ph.type !== undefined || ph.idx !== undefined) &&\n (ph.type === undefined || api.getShapePlaceholderType(shape) === ph.type) &&\n (ph.idx === undefined || api.getShapePlaceholderIdx(shape) === ph.idx)\n );\n });\n if (matches.length !== 1)\n throw new Error(`Shape reference matched ${matches.length} shapes: ${JSON.stringify(target)}`);\n return matches[0]!;\n}\nexport interface FillProps extends Children {\n target: Target;\n text?: string;\n format?: api.TextFormat;\n /** Omitted keeps whatever the template's `<a:bodyPr>` says. */\n autoFit?: api.TextAutoFit;\n}\nexport function Fill(props: FillProps): Node {\n return node('Fill', (context) => {\n const shape = selectShape(requireSlide(context), props.target);\n api.setShapeText(shape, props.text ?? literal(props.children));\n if (props.format) api.setShapeTextFormat(shape, props.format);\n if (props.autoFit) api.setShapeTextAutoFit(shape, props.autoFit);\n });\n}\nexport function Remove(props: { target: Target }): Node {\n return node('Remove', (context) => {\n const slide = requireSlide(context);\n api.removeShape(selectShape(slide, props.target));\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@office-kit/pptx-dsl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Typed TSX authoring for editable PowerPoint presentations",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"tsdown": "^0.22.2",
|
|
38
38
|
"typescript": "^6.0.3",
|
|
39
|
-
"@office-kit/pptx": "0.
|
|
39
|
+
"@office-kit/pptx": "0.18.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@office-kit/pptx": ">=0.17.0"
|