@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 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` | String rows, column and row sizes, cell/header/stripe styles, `styleCell` |
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, media playback, and structured table
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 api.ParagraphSpec[];
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 string[])[];
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((value, c) => {
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 (appearance.format) api.setTableCellTextFormat(cell, appearance.format);
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.4.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.17.0"
39
+ "@office-kit/pptx": "0.18.0"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@office-kit/pptx": ">=0.17.0"