@office-kit/pptx-dsl 0.2.0 → 0.4.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 +57 -16
- package/dist/index.d.ts +52 -2
- package/dist/index.js +104 -16
- package/dist/index.js.map +1 -1
- package/dist/{jsx-runtime-C-Ggfem1.d.ts → jsx-runtime-D7IpzvWG.d.ts} +3 -1
- package/dist/{jsx-runtime-BgfNl42k.js → jsx-runtime-DoUxctgW.js} +7 -2
- package/dist/jsx-runtime-DoUxctgW.js.map +1 -0
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/package.json +3 -3
- package/dist/jsx-runtime-BgfNl42k.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
# @office-kit/pptx-dsl
|
|
2
2
|
|
|
3
|
-
Start with [Create slides with AI
|
|
3
|
+
Start with [Create slides with AI](https://office-kit.github.io/pptx/docs/authoring)
|
|
4
4
|
for installation and preview, then see the
|
|
5
5
|
[TSX reference](https://office-kit.github.io/pptx/docs/tsx).
|
|
6
|
-
|
|
6
|
+
Install the Claude Code skill to let the agent handle project setup, or run
|
|
7
|
+
`npx --yes @office-kit/pptx-dev@latest init my-slides` to create a project yourself.
|
|
8
|
+
For an existing TypeScript project, install `@office-kit/pptx-dsl` and
|
|
9
|
+
`@office-kit/pptx` from npm.
|
|
7
10
|
|
|
8
11
|
Typed, declarative PowerPoint authoring in TSX. This package uses its own JSX
|
|
9
12
|
runtime; React and Vue are not dependencies. It creates native editable PPTX
|
|
@@ -47,23 +50,61 @@ Layout is explicit: CSS and automatic UI layout are not implemented.
|
|
|
47
50
|
|
|
48
51
|
## Elements
|
|
49
52
|
|
|
50
|
-
| Element | Input
|
|
51
|
-
| -------------- |
|
|
52
|
-
| `Presentation` | Optional source PPTX bytes or `size`, theme, `mode`
|
|
53
|
-
| `Slide` | Source `from` or edit `target`, layout, background, notes
|
|
54
|
-
| `Text` | Literal children or core `ParagraphSpec[]` via `paragraphs`, text format
|
|
55
|
-
| `Shape` | Core preset geometry, fill, stroke, effects, optional text
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
53
|
+
| Element | Input |
|
|
54
|
+
| -------------- | ------------------------------------------------------------------------- |
|
|
55
|
+
| `Presentation` | Optional source PPTX bytes or `size`, theme, `mode` |
|
|
56
|
+
| `Slide` | Source `from` or edit `target`, layout, background, notes |
|
|
57
|
+
| `Text` | Literal children or core `ParagraphSpec[]` via `paragraphs`, text format |
|
|
58
|
+
| `Shape` | Core preset geometry, fill, stroke, effects, optional text |
|
|
59
|
+
| `Line` | End points `x1` `y1` `x2` `y2`, `color`, `width` |
|
|
60
|
+
| `Group` | Groups the shapes its children create; optional `name` |
|
|
61
|
+
| `Image` | Bytes in `data`, optional format and fit |
|
|
62
|
+
| `Media` | `kind` `video` / `audio` with bytes in `data`, or `online` with a `url` |
|
|
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 |
|
|
66
|
+
| `Remove` | Existing shape target |
|
|
67
|
+
| `Raw` | Deferred callback receiving the presentation and enclosing slide/shape |
|
|
62
68
|
|
|
63
69
|
Bounds are required for newly created visual objects. Shape styles support solid
|
|
64
70
|
and gradient fills, stroke, rotation, shadow, glow and click actions. `Text`
|
|
65
|
-
accepts the core `TextFormat` properties directly, plus alignment, anchor
|
|
66
|
-
text auto-fit
|
|
71
|
+
accepts the core `TextFormat` properties directly, plus alignment, anchor,
|
|
72
|
+
text auto-fit, `bullets` and `paragraphSpacing` (both apply to every paragraph; a
|
|
73
|
+
newline in the text starts one). A `Shape` with `text` takes `align` and `anchor`.
|
|
74
|
+
|
|
75
|
+
A `Line` runs from (`x1`, `y1`) to (`x2`, `y2`) instead of taking bounds. A
|
|
76
|
+
`Group` holds two or more visual elements and may contain other groups; the
|
|
77
|
+
result moves and resizes as one object in PowerPoint.
|
|
78
|
+
|
|
79
|
+
A table cell style sets `fill`, `format`, `anchor`, `align` and `borders` (per
|
|
80
|
+
side, `width` in points). Styles merge in this order, later ones winning per
|
|
81
|
+
field: `cellStyle`, `headerStyle` (row 0), `stripeFill` (even body rows), then
|
|
82
|
+
`styleCell`, a callback that receives `{ row, column, value }`:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
<Table
|
|
86
|
+
x={1}
|
|
87
|
+
y={1}
|
|
88
|
+
width={8}
|
|
89
|
+
height={3}
|
|
90
|
+
rows={rows}
|
|
91
|
+
cellStyle={{ borders: { bottom: { color: '#D5D9E0', width: 0.75 } } }}
|
|
92
|
+
styleCell={({ row, value }) =>
|
|
93
|
+
row > 0 && value === 'At risk' ? { fill: '#D64545', format: { color: '#FFFFFF' } } : undefined
|
|
94
|
+
}
|
|
95
|
+
/>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`Media` embeds a video or audio clip from bytes, or links an online video by
|
|
99
|
+
URL (YouTube page URLs are rewritten to the embed form). `poster` supplies the
|
|
100
|
+
image shown before playback; a neutral play-button poster is used otherwise.
|
|
101
|
+
It takes bounds and `name` but no shape styles: the clip's picture already owns
|
|
102
|
+
its click action.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<Media kind="video" data={clipBytes} poster={posterBytes} x={1} y={1.5} width={8} height={4.5} />
|
|
106
|
+
<Media kind="online" url="https://youtu.be/dQw4w9WgXcQ" x={1} y={1.5} width={8} height={4.5} />
|
|
107
|
+
```
|
|
67
108
|
|
|
68
109
|
## Existing presentations
|
|
69
110
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as Node, l as PresentationNode, o as Child, s as Children, t as Fragment, u as RawContext } from "./jsx-runtime-
|
|
1
|
+
import { c as Node, l as PresentationNode, o as Child, s as Children, t as Fragment, u as RawContext } from "./jsx-runtime-D7IpzvWG.js";
|
|
2
2
|
import * as api from "@office-kit/pptx";
|
|
3
3
|
|
|
4
4
|
//#region src/index.d.ts
|
|
@@ -89,12 +89,22 @@ interface TextProps extends Bounds, ShapeStyle, api.TextFormat, Children {
|
|
|
89
89
|
align?: api.ParagraphAlignment;
|
|
90
90
|
anchor?: api.TextAnchor;
|
|
91
91
|
autoFit?: api.TextAutoFit;
|
|
92
|
+
/** Bullet or numbering for every paragraph; a newline in the text starts a paragraph. */
|
|
93
|
+
bullets?: api.BulletStyle;
|
|
94
|
+
/** Space before / after every paragraph, in points. */
|
|
95
|
+
paragraphSpacing?: {
|
|
96
|
+
before?: number;
|
|
97
|
+
after?: number;
|
|
98
|
+
};
|
|
92
99
|
}
|
|
93
100
|
declare function Text(props: TextProps): Node;
|
|
94
101
|
interface ShapeProps extends Bounds, ShapeStyle, Children {
|
|
95
102
|
preset: Parameters<typeof api.addSlideShape>[1]['preset'];
|
|
96
103
|
text?: string;
|
|
97
104
|
format?: api.TextFormat;
|
|
105
|
+
/** Alignment and anchor of `text` inside the shape. */
|
|
106
|
+
align?: api.ParagraphAlignment;
|
|
107
|
+
anchor?: api.TextAnchor;
|
|
98
108
|
}
|
|
99
109
|
declare function Shape(props: ShapeProps): Node;
|
|
100
110
|
interface ImageProps extends Bounds, ShapeStyle, Children {
|
|
@@ -103,14 +113,33 @@ interface ImageProps extends Bounds, ShapeStyle, Children {
|
|
|
103
113
|
fit?: api.ImageFit;
|
|
104
114
|
}
|
|
105
115
|
declare function Image(props: ImageProps): Node;
|
|
116
|
+
type MediaProps = Bounds & Children & api.SlideMediaSource & {
|
|
117
|
+
name?: string;
|
|
118
|
+
poster?: Uint8Array;
|
|
119
|
+
posterFormat?: api.ImageFormat;
|
|
120
|
+
};
|
|
121
|
+
declare function Media(props: MediaProps): Node;
|
|
106
122
|
interface ChartProps extends Bounds, ShapeStyle, Children {
|
|
107
123
|
spec: api.ChartSpec;
|
|
108
124
|
}
|
|
109
125
|
declare function Chart(props: ChartProps): Node;
|
|
126
|
+
type CellBorderSide = 'left' | 'right' | 'top' | 'bottom';
|
|
110
127
|
interface CellStyle {
|
|
111
128
|
fill?: string;
|
|
112
129
|
format?: api.TextFormat;
|
|
113
130
|
anchor?: api.TextAnchor;
|
|
131
|
+
align?: api.ParagraphAlignment;
|
|
132
|
+
/** Border per side. `width` is in points; without it the line has no explicit width. */
|
|
133
|
+
borders?: Partial<Record<CellBorderSide, {
|
|
134
|
+
color: string;
|
|
135
|
+
width?: number;
|
|
136
|
+
}>>;
|
|
137
|
+
}
|
|
138
|
+
interface TableCellInfo {
|
|
139
|
+
/** Zero-based; row 0 is the header. */
|
|
140
|
+
row: number;
|
|
141
|
+
column: number;
|
|
142
|
+
value: string;
|
|
114
143
|
}
|
|
115
144
|
interface TableProps extends Bounds, Children {
|
|
116
145
|
rows: readonly (readonly string[])[];
|
|
@@ -119,8 +148,29 @@ interface TableProps extends Bounds, Children {
|
|
|
119
148
|
cellStyle?: CellStyle;
|
|
120
149
|
headerStyle?: CellStyle;
|
|
121
150
|
stripeFill?: string;
|
|
151
|
+
/**
|
|
152
|
+
* Style for one cell, merged over `cellStyle`, `headerStyle` and
|
|
153
|
+
* `stripeFill` — for a status column, a total row, a highlighted figure.
|
|
154
|
+
*/
|
|
155
|
+
styleCell?: (cell: TableCellInfo) => CellStyle | undefined;
|
|
122
156
|
}
|
|
123
157
|
declare function Table(props: TableProps): Node;
|
|
158
|
+
interface LineProps {
|
|
159
|
+
x1: number;
|
|
160
|
+
y1: number;
|
|
161
|
+
x2: number;
|
|
162
|
+
y2: number;
|
|
163
|
+
color?: string;
|
|
164
|
+
/** Stroke width in points. */
|
|
165
|
+
width?: number;
|
|
166
|
+
name?: string;
|
|
167
|
+
}
|
|
168
|
+
declare function Line(props: LineProps): Node;
|
|
169
|
+
interface GroupProps extends Children {
|
|
170
|
+
name?: string;
|
|
171
|
+
}
|
|
172
|
+
/** Groups the shapes its children create, so they move and resize as one object. */
|
|
173
|
+
declare function Group(props: GroupProps): Node;
|
|
124
174
|
interface FillProps extends Children {
|
|
125
175
|
target: Target;
|
|
126
176
|
text?: string;
|
|
@@ -131,5 +181,5 @@ declare function Remove(props: {
|
|
|
131
181
|
target: Target;
|
|
132
182
|
}): Node;
|
|
133
183
|
//#endregion
|
|
134
|
-
export { Bounds, CellStyle, Chart, ChartProps, type Child, type Children, Fill, FillProps, Fragment, Image, ImageProps, LayoutRef, type Node, Presentation, type PresentationNode, PresentationProps, Raw, type RawContext, RawProps, Remove, Shape, ShapeProps, ShapeStyle, Slide, SlideProps, SlideRef, Table, TableProps, Target, Text, TextProps, compile };
|
|
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 };
|
|
135
185
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as created, c as requireSlide, l as textContent, o as literal, s as node, t as Fragment, u as visit } from "./jsx-runtime-DoUxctgW.js";
|
|
2
2
|
import * as api from "@office-kit/pptx";
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
function Presentation(props) {
|
|
@@ -106,16 +106,25 @@ function Text(props) {
|
|
|
106
106
|
const slide = requireSlide(context);
|
|
107
107
|
const content = textContent(props.children);
|
|
108
108
|
if (props.paragraphs && content.text.trim()) throw new Error("Text accepts either text children or paragraphs.");
|
|
109
|
-
const shape = api.addSlideTextBox(slide, {
|
|
109
|
+
const shape = created(context, api.addSlideTextBox(slide, {
|
|
110
110
|
...bounds(props),
|
|
111
111
|
...props.name ? { name: props.name } : {},
|
|
112
112
|
text: content.text
|
|
113
|
-
});
|
|
113
|
+
}));
|
|
114
114
|
if (props.paragraphs) api.setShapeParagraphs(shape, props.paragraphs);
|
|
115
115
|
api.setShapeTextFormat(shape, 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
|
+
if (props.bullets !== void 0) api.setShapeBullets(shape, props.bullets);
|
|
120
|
+
if (props.paragraphSpacing) {
|
|
121
|
+
const { before, after } = props.paragraphSpacing;
|
|
122
|
+
const spacing = {
|
|
123
|
+
...before !== void 0 ? { beforePts: before } : {},
|
|
124
|
+
...after !== void 0 ? { afterPts: after } : {}
|
|
125
|
+
};
|
|
126
|
+
for (let i = 0; i < api.getShapeParagraphCount(shape); i++) api.setParagraphSpacing(shape, i, spacing);
|
|
127
|
+
}
|
|
119
128
|
style(shape, props);
|
|
120
129
|
await visit(content.elements, {
|
|
121
130
|
...context,
|
|
@@ -127,14 +136,17 @@ function Text(props) {
|
|
|
127
136
|
}
|
|
128
137
|
function Shape(props) {
|
|
129
138
|
return node("Shape", async (context) => {
|
|
130
|
-
|
|
139
|
+
if ((props.align || props.anchor) && props.text === void 0) throw new Error("Shape align and anchor position its text; set text as well.");
|
|
140
|
+
const shape = created(context, api.addSlideShape(requireSlide(context), {
|
|
131
141
|
...bounds(props),
|
|
132
142
|
preset: props.preset,
|
|
133
143
|
...props.name ? { name: props.name } : {},
|
|
134
144
|
...props.text !== void 0 ? { text: props.text } : {}
|
|
135
|
-
});
|
|
145
|
+
}));
|
|
136
146
|
style(shape, props);
|
|
137
147
|
if (props.format) api.setShapeTextFormat(shape, props.format);
|
|
148
|
+
if (props.align) api.setShapeAlignment(shape, props.align);
|
|
149
|
+
if (props.anchor) api.setShapeTextAnchor(shape, props.anchor);
|
|
138
150
|
await visit(props.children, {
|
|
139
151
|
...context,
|
|
140
152
|
shape,
|
|
@@ -144,12 +156,12 @@ function Shape(props) {
|
|
|
144
156
|
}
|
|
145
157
|
function Image(props) {
|
|
146
158
|
return node("Image", async (context) => {
|
|
147
|
-
const shape = api.addSlideImage(requireSlide(context), props.data, {
|
|
159
|
+
const shape = created(context, api.addSlideImage(requireSlide(context), props.data, {
|
|
148
160
|
...bounds(props),
|
|
149
161
|
...props.format ? { format: props.format } : {},
|
|
150
162
|
...props.fit ? { fit: props.fit } : {},
|
|
151
163
|
...props.name ? { name: props.name } : {}
|
|
152
|
-
});
|
|
164
|
+
}));
|
|
153
165
|
style(shape, props);
|
|
154
166
|
await visit(props.children, {
|
|
155
167
|
...context,
|
|
@@ -158,13 +170,27 @@ function Image(props) {
|
|
|
158
170
|
});
|
|
159
171
|
});
|
|
160
172
|
}
|
|
173
|
+
function Media(props) {
|
|
174
|
+
return node("Media", async (context) => {
|
|
175
|
+
const { x: _x, y: _y, width: _width, height: _height, children, ...media } = props;
|
|
176
|
+
const shape = created(context, api.addSlideMedia(requireSlide(context), {
|
|
177
|
+
...media,
|
|
178
|
+
...bounds(props)
|
|
179
|
+
}));
|
|
180
|
+
await visit(children, {
|
|
181
|
+
...context,
|
|
182
|
+
shape,
|
|
183
|
+
scope: "shape"
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
161
187
|
function Chart(props) {
|
|
162
188
|
return node("Chart", async (context) => {
|
|
163
|
-
const shape = api.addSlideChart(requireSlide(context), {
|
|
189
|
+
const shape = created(context, api.addSlideChart(requireSlide(context), {
|
|
164
190
|
...bounds(props),
|
|
165
191
|
spec: props.spec,
|
|
166
192
|
...props.name ? { name: props.name } : {}
|
|
167
|
-
});
|
|
193
|
+
}));
|
|
168
194
|
style(shape, props);
|
|
169
195
|
await visit(props.children, {
|
|
170
196
|
...context,
|
|
@@ -173,28 +199,61 @@ function Chart(props) {
|
|
|
173
199
|
});
|
|
174
200
|
});
|
|
175
201
|
}
|
|
202
|
+
function cellBorders(borders) {
|
|
203
|
+
const sides = {};
|
|
204
|
+
for (const side of [
|
|
205
|
+
"left",
|
|
206
|
+
"right",
|
|
207
|
+
"top",
|
|
208
|
+
"bottom"
|
|
209
|
+
]) {
|
|
210
|
+
const border = borders[side];
|
|
211
|
+
if (!border) continue;
|
|
212
|
+
sides[side] = {
|
|
213
|
+
color: border.color,
|
|
214
|
+
...border.width !== void 0 ? { widthEmu: api.pt(border.width) } : {}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
return sides;
|
|
218
|
+
}
|
|
176
219
|
function Table(props) {
|
|
177
220
|
return node("Table", async (context) => {
|
|
178
|
-
const shape = api.addSlideTable(requireSlide(context), {
|
|
221
|
+
const shape = created(context, api.addSlideTable(requireSlide(context), {
|
|
179
222
|
...bounds(props),
|
|
180
223
|
rows: props.rows,
|
|
181
224
|
...props.columnWidths ? { colWidths: props.columnWidths.map(api.inches) } : {},
|
|
182
225
|
...props.rowHeights ? { rowHeights: props.rowHeights.map(api.inches) } : {}
|
|
183
|
-
});
|
|
184
|
-
props.rows.forEach((row, r) => row.forEach((
|
|
226
|
+
}));
|
|
227
|
+
props.rows.forEach((row, r) => row.forEach((value, c) => {
|
|
185
228
|
const cell = api.getTableCell(shape, r, c);
|
|
229
|
+
const header = r === 0 ? props.headerStyle : void 0;
|
|
230
|
+
const own = props.styleCell?.({
|
|
231
|
+
row: r,
|
|
232
|
+
column: c,
|
|
233
|
+
value
|
|
234
|
+
});
|
|
235
|
+
const striped = r > 0 && r % 2 === 0 ? props.stripeFill : void 0;
|
|
186
236
|
const appearance = {
|
|
187
237
|
...props.cellStyle,
|
|
188
|
-
...
|
|
238
|
+
...header,
|
|
239
|
+
...striped !== void 0 ? { fill: striped } : {},
|
|
240
|
+
...own,
|
|
189
241
|
format: {
|
|
190
242
|
...props.cellStyle?.format,
|
|
191
|
-
...
|
|
243
|
+
...header?.format,
|
|
244
|
+
...own?.format
|
|
192
245
|
}
|
|
193
246
|
};
|
|
194
247
|
if (appearance.fill) api.setTableCellFill(cell, appearance.fill);
|
|
195
|
-
if (r > 0 && r % 2 === 0 && props.stripeFill) api.setTableCellFill(cell, props.stripeFill);
|
|
196
248
|
if (appearance.format) api.setTableCellTextFormat(cell, appearance.format);
|
|
197
249
|
if (appearance.anchor) api.setTableCellAnchor(cell, appearance.anchor);
|
|
250
|
+
if (appearance.align) api.setTableCellAlignment(cell, appearance.align);
|
|
251
|
+
const borders = cellBorders({
|
|
252
|
+
...props.cellStyle?.borders,
|
|
253
|
+
...header?.borders,
|
|
254
|
+
...own?.borders
|
|
255
|
+
});
|
|
256
|
+
if (Object.keys(borders).length > 0) api.setTableCellBorders(cell, borders);
|
|
198
257
|
}));
|
|
199
258
|
await visit(props.children, {
|
|
200
259
|
...context,
|
|
@@ -203,6 +262,35 @@ function Table(props) {
|
|
|
203
262
|
});
|
|
204
263
|
});
|
|
205
264
|
}
|
|
265
|
+
function Line(props) {
|
|
266
|
+
return node("Line", (context) => {
|
|
267
|
+
created(context, api.addSlideLine(requireSlide(context), {
|
|
268
|
+
from: {
|
|
269
|
+
x: api.inches(props.x1),
|
|
270
|
+
y: api.inches(props.y1)
|
|
271
|
+
},
|
|
272
|
+
to: {
|
|
273
|
+
x: api.inches(props.x2),
|
|
274
|
+
y: api.inches(props.y2)
|
|
275
|
+
},
|
|
276
|
+
...props.color !== void 0 ? { color: props.color } : {},
|
|
277
|
+
...props.width !== void 0 ? { widthEmu: api.pt(props.width) } : {},
|
|
278
|
+
...props.name ? { name: props.name } : {}
|
|
279
|
+
}));
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/** Groups the shapes its children create, so they move and resize as one object. */
|
|
283
|
+
function Group(props) {
|
|
284
|
+
return node("Group", async (context) => {
|
|
285
|
+
requireSlide(context);
|
|
286
|
+
const members = [];
|
|
287
|
+
await visit(props.children, {
|
|
288
|
+
...context,
|
|
289
|
+
members
|
|
290
|
+
});
|
|
291
|
+
created(context, api.groupShapes(members, props.name ? { name: props.name } : {}));
|
|
292
|
+
});
|
|
293
|
+
}
|
|
206
294
|
function selectShape(slide, target) {
|
|
207
295
|
const matches = api.getSlideShapes(slide).filter((shape) => {
|
|
208
296
|
if ("name" in target) return api.getShapeName(shape) === target.name;
|
|
@@ -227,6 +315,6 @@ function Remove(props) {
|
|
|
227
315
|
});
|
|
228
316
|
}
|
|
229
317
|
//#endregion
|
|
230
|
-
export { Chart, Fill, Fragment, Image, Presentation, Raw, Remove, Shape, Slide, Table, Text, compile };
|
|
318
|
+
export { Chart, Fill, Fragment, Group, Image, Line, Media, Presentation, Raw, Remove, Shape, Slide, Table, Text, compile };
|
|
231
319
|
|
|
232
320
|
//# sourceMappingURL=index.js.map
|
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 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}\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 = api.addSlideTextBox(slide, {\n ...bounds(props),\n ...(props.name ? { name: props.name } : {}),\n text: content.text,\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 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}\nexport function Shape(props: ShapeProps): Node {\n return node('Shape', async (context) => {\n const shape = 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 style(shape, props);\n if (props.format) api.setShapeTextFormat(shape, props.format);\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 = 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 style(shape, props);\n await visit(props.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 = api.addSlideChart(requireSlide(context), {\n ...bounds(props),\n spec: props.spec,\n ...(props.name ? { name: props.name } : {}),\n });\n style(shape, props);\n await visit(props.children, { ...context, shape, scope: 'shape' });\n });\n}\nexport interface CellStyle {\n fill?: string;\n format?: api.TextFormat;\n anchor?: api.TextAnchor;\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}\nexport function Table(props: TableProps): Node {\n return node('Table', async (context) => {\n const shape = 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 props.rows.forEach((row, r) =>\n row.forEach((_, c) => {\n const cell = api.getTableCell(shape, r, c);\n const appearance = {\n ...props.cellStyle,\n ...(r === 0 ? props.headerStyle : {}),\n format: { ...props.cellStyle?.format, ...(r === 0 ? props.headerStyle?.format : {}) },\n };\n if (appearance.fill) api.setTableCellFill(cell, appearance.fill);\n if (r > 0 && r % 2 === 0 && props.stripeFill) api.setTableCellFill(cell, props.stripeFill);\n if (appearance.format) api.setTableCellTextFormat(cell, appearance.format);\n if (appearance.anchor) api.setTableCellAnchor(cell, appearance.anchor);\n }),\n );\n await visit(props.children, { ...context, shape, scope: 'shape' });\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}\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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"}
|
|
@@ -15,6 +15,8 @@ interface Context extends RawContext {
|
|
|
15
15
|
scope: 'presentation' | 'slide' | 'shape';
|
|
16
16
|
originals: readonly api.SlideData[];
|
|
17
17
|
deferred: Array<() => void | Promise<void>>;
|
|
18
|
+
/** Set inside a `Group`: every shape created there, in drawing order. */
|
|
19
|
+
members?: api.SlideShapeData[];
|
|
18
20
|
}
|
|
19
21
|
interface Node {
|
|
20
22
|
readonly kind: string;
|
|
@@ -47,4 +49,4 @@ declare namespace JSX {
|
|
|
47
49
|
}
|
|
48
50
|
//#endregion
|
|
49
51
|
export { jsxs as a, Node as c, jsxDEV as i, PresentationNode as l, JSX as n, Child as o, jsx as r, Children as s, Fragment as t, RawContext as u };
|
|
50
|
-
//# sourceMappingURL=jsx-runtime-
|
|
52
|
+
//# sourceMappingURL=jsx-runtime-D7IpzvWG.d.ts.map
|
|
@@ -24,6 +24,11 @@ function requireSlide(context) {
|
|
|
24
24
|
if (!context.slide || context.scope !== "slide") throw new Error("This element must be a child of Slide.");
|
|
25
25
|
return context.slide;
|
|
26
26
|
}
|
|
27
|
+
/** Reports a new shape to the enclosing `Group`, if there is one. */
|
|
28
|
+
function created(context, shape) {
|
|
29
|
+
context.members?.push(shape);
|
|
30
|
+
return shape;
|
|
31
|
+
}
|
|
27
32
|
function literal(children) {
|
|
28
33
|
if (children == null || typeof children === "boolean") return "";
|
|
29
34
|
if (typeof children === "string" || typeof children === "number") return String(children);
|
|
@@ -65,6 +70,6 @@ function Fragment({ children }) {
|
|
|
65
70
|
return node("Fragment", (context) => visit(children, context));
|
|
66
71
|
}
|
|
67
72
|
//#endregion
|
|
68
|
-
export {
|
|
73
|
+
export { created as a, requireSlide as c, jsxs as i, textContent as l, jsx as n, literal as o, jsxDEV as r, node as s, Fragment as t, visit as u };
|
|
69
74
|
|
|
70
|
-
//# sourceMappingURL=jsx-runtime-
|
|
75
|
+
//# sourceMappingURL=jsx-runtime-DoUxctgW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx-runtime-DoUxctgW.js","names":[],"sources":["../src/model.ts","../src/jsx-runtime.ts"],"sourcesContent":["import type * as api from '@office-kit/pptx';\n\nexport type Child = Node | string | number | boolean | null | undefined | readonly Child[];\nexport interface Children {\n children?: Child;\n}\nexport interface RawContext {\n presentation: api.PresentationData;\n slide?: api.SlideData;\n shape?: api.SlideShapeData;\n}\nexport interface Context extends RawContext {\n mode: 'compose' | 'edit';\n scope: 'presentation' | 'slide' | 'shape';\n originals: readonly api.SlideData[];\n deferred: Array<() => void | Promise<void>>;\n /** Set inside a `Group`: every shape created there, in drawing order. */\n members?: api.SlideShapeData[];\n}\nexport interface Node {\n readonly kind: string;\n readonly source?: { fileName: string; lineNumber: number; columnNumber: number };\n readonly evaluate: (context: Context) => void | Promise<void>;\n}\nexport interface PresentationNode extends Node {\n readonly compile: () => Promise<api.PresentationData>;\n}\nexport function node(kind: string, evaluate: Node['evaluate']): Node {\n return { kind, evaluate };\n}\nexport async function visit(children: Child, context: Context): Promise<void> {\n if (children == null || typeof children === 'boolean') return;\n if (typeof children === 'string' || typeof children === 'number') {\n if (String(children).trim()) throw new Error('Text content must be inside Text or Fill.');\n return;\n }\n if ('evaluate' in children) {\n try {\n await children.evaluate(context);\n } catch (cause) {\n if (!children.source) throw cause;\n const { fileName, lineNumber, columnNumber } = children.source;\n throw new Error(\n `${fileName}:${lineNumber}:${columnNumber} <${children.kind}>: ${cause instanceof Error ? cause.message : String(cause)}`,\n { cause },\n );\n }\n } else {\n for (const child of children) await visit(child, context);\n }\n}\nexport function requireSlide(context: Context): api.SlideData {\n if (!context.slide || context.scope !== 'slide')\n throw new Error('This element must be a child of Slide.');\n return context.slide;\n}\n/** Reports a new shape to the enclosing `Group`, if there is one. */\nexport function created(context: Context, shape: api.SlideShapeData): api.SlideShapeData {\n context.members?.push(shape);\n return shape;\n}\nexport function literal(children: Child): string {\n if (children == null || typeof children === 'boolean') return '';\n if (typeof children === 'string' || typeof children === 'number') return String(children);\n if ('evaluate' in children)\n throw new Error('Use paragraphs for rich text; element children are not text.');\n return children.map(literal).join('');\n}\n\n/** Separate inline text from shape-scoped escape hatches without evaluating them. */\nexport function textContent(children: Child): { text: string; elements: Node[] } {\n const elements: Node[] = [];\n function collect(child: Child): string {\n if (child == null || typeof child === 'boolean') return '';\n if (typeof child === 'string' || typeof child === 'number') return String(child);\n if ('evaluate' in child) {\n elements.push(child);\n return '';\n }\n return child.map(collect).join('');\n }\n return { text: collect(children), elements };\n}\n","import { node, visit, type Child, type Children, type Node } from './model.ts';\n\nexport function jsx<P>(component: (props: P) => Node, props: P, _key?: string | number): Node {\n if (typeof component !== 'function')\n throw new Error('Use imported PPTX components, not HTML tags.');\n return component(props);\n}\nexport const jsxs = jsx;\nexport function jsxDEV<P>(\n component: (props: P) => Node,\n props: P,\n key?: string | number,\n _isStaticChildren?: boolean,\n source?: Node['source'],\n): Node {\n const result = jsx(component, props, key);\n return source ? { ...result, source } : result;\n}\nexport function Fragment({ children }: Children): Node {\n return node('Fragment', (context) => visit(children, context));\n}\nexport namespace JSX {\n export type Element = Node;\n export interface ElementChildrenAttribute {\n children: Child;\n }\n export interface IntrinsicAttributes {\n key?: string | number;\n }\n}\n"],"mappings":";AA2BA,SAAgB,KAAK,MAAc,UAAkC;CACnE,OAAO;EAAE;EAAM;CAAS;AAC1B;AACA,eAAsB,MAAM,UAAiB,SAAiC;CAC5E,IAAI,YAAY,QAAQ,OAAO,aAAa,WAAW;CACvD,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;EAChE,IAAI,OAAO,QAAQ,CAAC,CAAC,KAAK,GAAG,MAAM,IAAI,MAAM,2CAA2C;EACxF;CACF;CACA,IAAI,cAAc,UAChB,IAAI;EACF,MAAM,SAAS,SAAS,OAAO;CACjC,SAAS,OAAO;EACd,IAAI,CAAC,SAAS,QAAQ,MAAM;EAC5B,MAAM,EAAE,UAAU,YAAY,iBAAiB,SAAS;EACxD,MAAM,IAAI,MACR,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,IAAI,SAAS,KAAK,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACtH,EAAE,MAAM,CACV;CACF;MAEA,KAAK,MAAM,SAAS,UAAU,MAAM,MAAM,OAAO,OAAO;AAE5D;AACA,SAAgB,aAAa,SAAiC;CAC5D,IAAI,CAAC,QAAQ,SAAS,QAAQ,UAAU,SACtC,MAAM,IAAI,MAAM,wCAAwC;CAC1D,OAAO,QAAQ;AACjB;;AAEA,SAAgB,QAAQ,SAAkB,OAA+C;CACvF,QAAQ,SAAS,KAAK,KAAK;CAC3B,OAAO;AACT;AACA,SAAgB,QAAQ,UAAyB;CAC/C,IAAI,YAAY,QAAQ,OAAO,aAAa,WAAW,OAAO;CAC9D,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU,OAAO,OAAO,QAAQ;CACxF,IAAI,cAAc,UAChB,MAAM,IAAI,MAAM,8DAA8D;CAChF,OAAO,SAAS,IAAI,OAAO,CAAC,CAAC,KAAK,EAAE;AACtC;;AAGA,SAAgB,YAAY,UAAqD;CAC/E,MAAM,WAAmB,CAAC;CAC1B,SAAS,QAAQ,OAAsB;EACrC,IAAI,SAAS,QAAQ,OAAO,UAAU,WAAW,OAAO;EACxD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;EAC/E,IAAI,cAAc,OAAO;GACvB,SAAS,KAAK,KAAK;GACnB,OAAO;EACT;EACA,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,KAAK,EAAE;CACnC;CACA,OAAO;EAAE,MAAM,QAAQ,QAAQ;EAAG;CAAS;AAC7C;;;AChFA,SAAgB,IAAO,WAA+B,OAAU,MAA8B;CAC5F,IAAI,OAAO,cAAc,YACvB,MAAM,IAAI,MAAM,8CAA8C;CAChE,OAAO,UAAU,KAAK;AACxB;AACA,MAAa,OAAO;AACpB,SAAgB,OACd,WACA,OACA,KACA,mBACA,QACM;CACN,MAAM,SAAS,IAAI,WAAW,OAAO,GAAG;CACxC,OAAO,SAAS;EAAE,GAAG;EAAQ;CAAO,IAAI;AAC1C;AACA,SAAgB,SAAS,EAAE,YAA4B;CACrD,OAAO,KAAK,aAAa,YAAY,MAAM,UAAU,OAAO,CAAC;AAC/D"}
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./jsx-runtime-
|
|
1
|
+
import { a as jsxs, i as jsxDEV, n as JSX, r as jsx, t as Fragment } from "./jsx-runtime-D7IpzvWG.js";
|
|
2
2
|
export { Fragment, JSX, jsx, jsxDEV, jsxs };
|
package/dist/jsx-runtime.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-
|
|
1
|
+
import { i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-DoUxctgW.js";
|
|
2
2
|
export { Fragment, jsx, jsxDEV, jsxs };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@office-kit/pptx-dsl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Typed TSX authoring for editable PowerPoint presentations",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
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.17.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@office-kit/pptx": ">=0.
|
|
42
|
+
"@office-kit/pptx": ">=0.17.0"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=22.18.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-runtime-BgfNl42k.js","names":[],"sources":["../src/model.ts","../src/jsx-runtime.ts"],"sourcesContent":["import type * as api from '@office-kit/pptx';\n\nexport type Child = Node | string | number | boolean | null | undefined | readonly Child[];\nexport interface Children {\n children?: Child;\n}\nexport interface RawContext {\n presentation: api.PresentationData;\n slide?: api.SlideData;\n shape?: api.SlideShapeData;\n}\nexport interface Context extends RawContext {\n mode: 'compose' | 'edit';\n scope: 'presentation' | 'slide' | 'shape';\n originals: readonly api.SlideData[];\n deferred: Array<() => void | Promise<void>>;\n}\nexport interface Node {\n readonly kind: string;\n readonly source?: { fileName: string; lineNumber: number; columnNumber: number };\n readonly evaluate: (context: Context) => void | Promise<void>;\n}\nexport interface PresentationNode extends Node {\n readonly compile: () => Promise<api.PresentationData>;\n}\nexport function node(kind: string, evaluate: Node['evaluate']): Node {\n return { kind, evaluate };\n}\nexport async function visit(children: Child, context: Context): Promise<void> {\n if (children == null || typeof children === 'boolean') return;\n if (typeof children === 'string' || typeof children === 'number') {\n if (String(children).trim()) throw new Error('Text content must be inside Text or Fill.');\n return;\n }\n if ('evaluate' in children) {\n try {\n await children.evaluate(context);\n } catch (cause) {\n if (!children.source) throw cause;\n const { fileName, lineNumber, columnNumber } = children.source;\n throw new Error(\n `${fileName}:${lineNumber}:${columnNumber} <${children.kind}>: ${cause instanceof Error ? cause.message : String(cause)}`,\n { cause },\n );\n }\n } else {\n for (const child of children) await visit(child, context);\n }\n}\nexport function requireSlide(context: Context): api.SlideData {\n if (!context.slide || context.scope !== 'slide')\n throw new Error('This element must be a child of Slide.');\n return context.slide;\n}\nexport function literal(children: Child): string {\n if (children == null || typeof children === 'boolean') return '';\n if (typeof children === 'string' || typeof children === 'number') return String(children);\n if ('evaluate' in children)\n throw new Error('Use paragraphs for rich text; element children are not text.');\n return children.map(literal).join('');\n}\n\n/** Separate inline text from shape-scoped escape hatches without evaluating them. */\nexport function textContent(children: Child): { text: string; elements: Node[] } {\n const elements: Node[] = [];\n function collect(child: Child): string {\n if (child == null || typeof child === 'boolean') return '';\n if (typeof child === 'string' || typeof child === 'number') return String(child);\n if ('evaluate' in child) {\n elements.push(child);\n return '';\n }\n return child.map(collect).join('');\n }\n return { text: collect(children), elements };\n}\n","import { node, visit, type Child, type Children, type Node } from './model.ts';\n\nexport function jsx<P>(component: (props: P) => Node, props: P, _key?: string | number): Node {\n if (typeof component !== 'function')\n throw new Error('Use imported PPTX components, not HTML tags.');\n return component(props);\n}\nexport const jsxs = jsx;\nexport function jsxDEV<P>(\n component: (props: P) => Node,\n props: P,\n key?: string | number,\n _isStaticChildren?: boolean,\n source?: Node['source'],\n): Node {\n const result = jsx(component, props, key);\n return source ? { ...result, source } : result;\n}\nexport function Fragment({ children }: Children): Node {\n return node('Fragment', (context) => visit(children, context));\n}\nexport namespace JSX {\n export type Element = Node;\n export interface ElementChildrenAttribute {\n children: Child;\n }\n export interface IntrinsicAttributes {\n key?: string | number;\n }\n}\n"],"mappings":";AAyBA,SAAgB,KAAK,MAAc,UAAkC;CACnE,OAAO;EAAE;EAAM;CAAS;AAC1B;AACA,eAAsB,MAAM,UAAiB,SAAiC;CAC5E,IAAI,YAAY,QAAQ,OAAO,aAAa,WAAW;CACvD,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU;EAChE,IAAI,OAAO,QAAQ,CAAC,CAAC,KAAK,GAAG,MAAM,IAAI,MAAM,2CAA2C;EACxF;CACF;CACA,IAAI,cAAc,UAChB,IAAI;EACF,MAAM,SAAS,SAAS,OAAO;CACjC,SAAS,OAAO;EACd,IAAI,CAAC,SAAS,QAAQ,MAAM;EAC5B,MAAM,EAAE,UAAU,YAAY,iBAAiB,SAAS;EACxD,MAAM,IAAI,MACR,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,IAAI,SAAS,KAAK,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,KACtH,EAAE,MAAM,CACV;CACF;MAEA,KAAK,MAAM,SAAS,UAAU,MAAM,MAAM,OAAO,OAAO;AAE5D;AACA,SAAgB,aAAa,SAAiC;CAC5D,IAAI,CAAC,QAAQ,SAAS,QAAQ,UAAU,SACtC,MAAM,IAAI,MAAM,wCAAwC;CAC1D,OAAO,QAAQ;AACjB;AACA,SAAgB,QAAQ,UAAyB;CAC/C,IAAI,YAAY,QAAQ,OAAO,aAAa,WAAW,OAAO;CAC9D,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,UAAU,OAAO,OAAO,QAAQ;CACxF,IAAI,cAAc,UAChB,MAAM,IAAI,MAAM,8DAA8D;CAChF,OAAO,SAAS,IAAI,OAAO,CAAC,CAAC,KAAK,EAAE;AACtC;;AAGA,SAAgB,YAAY,UAAqD;CAC/E,MAAM,WAAmB,CAAC;CAC1B,SAAS,QAAQ,OAAsB;EACrC,IAAI,SAAS,QAAQ,OAAO,UAAU,WAAW,OAAO;EACxD,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;EAC/E,IAAI,cAAc,OAAO;GACvB,SAAS,KAAK,KAAK;GACnB,OAAO;EACT;EACA,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,KAAK,EAAE;CACnC;CACA,OAAO;EAAE,MAAM,QAAQ,QAAQ;EAAG;CAAS;AAC7C;;;ACzEA,SAAgB,IAAO,WAA+B,OAAU,MAA8B;CAC5F,IAAI,OAAO,cAAc,YACvB,MAAM,IAAI,MAAM,8CAA8C;CAChE,OAAO,UAAU,KAAK;AACxB;AACA,MAAa,OAAO;AACpB,SAAgB,OACd,WACA,OACA,KACA,mBACA,QACM;CACN,MAAM,SAAS,IAAI,WAAW,OAAO,GAAG;CACxC,OAAO,SAAS;EAAE,GAAG;EAAQ;CAAO,IAAI;AAC1C;AACA,SAAgB,SAAS,EAAE,YAA4B;CACrD,OAAO,KAAK,aAAa,YAAY,MAAM,UAAU,OAAO,CAAC;AAC/D"}
|