slotdeck 0.0.0-stage → 0.1.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.
Files changed (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +486 -2
  3. package/dist/deck/numbers.d.ts +14 -0
  4. package/dist/deck/numbers.js +48 -0
  5. package/dist/deck/numbers.js.map +1 -0
  6. package/dist/deck/spec.d.ts +73 -0
  7. package/dist/deck/spec.js +21 -0
  8. package/dist/deck/spec.js.map +1 -0
  9. package/dist/deck/validate.d.ts +49 -0
  10. package/dist/deck/validate.js +189 -0
  11. package/dist/deck/validate.js.map +1 -0
  12. package/dist/generate.d.ts +53 -0
  13. package/dist/generate.js +44 -0
  14. package/dist/generate.js.map +1 -0
  15. package/dist/index.d.ts +42 -0
  16. package/dist/index.js +27 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/llm/gemini.d.ts +39 -0
  19. package/dist/llm/gemini.js +147 -0
  20. package/dist/llm/gemini.js.map +1 -0
  21. package/dist/llm/provider.d.ts +38 -0
  22. package/dist/llm/provider.js +2 -0
  23. package/dist/llm/provider.js.map +1 -0
  24. package/dist/node.d.ts +3 -0
  25. package/dist/node.js +31 -0
  26. package/dist/node.js.map +1 -0
  27. package/dist/plan/assets.d.ts +28 -0
  28. package/dist/plan/assets.js +80 -0
  29. package/dist/plan/assets.js.map +1 -0
  30. package/dist/plan/catalog.d.ts +106 -0
  31. package/dist/plan/catalog.js +302 -0
  32. package/dist/plan/catalog.js.map +1 -0
  33. package/dist/plan/edit.d.ts +31 -0
  34. package/dist/plan/edit.js +364 -0
  35. package/dist/plan/edit.js.map +1 -0
  36. package/dist/plan/plan.d.ts +106 -0
  37. package/dist/plan/plan.js +243 -0
  38. package/dist/plan/plan.js.map +1 -0
  39. package/dist/plan/write.d.ts +39 -0
  40. package/dist/plan/write.js +179 -0
  41. package/dist/plan/write.js.map +1 -0
  42. package/dist/pptx/package.d.ts +48 -0
  43. package/dist/pptx/package.js +202 -0
  44. package/dist/pptx/package.js.map +1 -0
  45. package/dist/pptx/presentation.d.ts +20 -0
  46. package/dist/pptx/presentation.js +31 -0
  47. package/dist/pptx/presentation.js.map +1 -0
  48. package/dist/pptx/xml.d.ts +23 -0
  49. package/dist/pptx/xml.js +67 -0
  50. package/dist/pptx/xml.js.map +1 -0
  51. package/dist/render/chart.d.ts +18 -0
  52. package/dist/render/chart.js +158 -0
  53. package/dist/render/chart.js.map +1 -0
  54. package/dist/render/extract.d.ts +11 -0
  55. package/dist/render/extract.js +65 -0
  56. package/dist/render/extract.js.map +1 -0
  57. package/dist/render/picture.d.ts +20 -0
  58. package/dist/render/picture.js +114 -0
  59. package/dist/render/picture.js.map +1 -0
  60. package/dist/render/render.d.ts +32 -0
  61. package/dist/render/render.js +247 -0
  62. package/dist/render/render.js.map +1 -0
  63. package/dist/render/repeat.d.ts +15 -0
  64. package/dist/render/repeat.js +118 -0
  65. package/dist/render/repeat.js.map +1 -0
  66. package/dist/render/table.d.ts +12 -0
  67. package/dist/render/table.js +84 -0
  68. package/dist/render/table.js.map +1 -0
  69. package/dist/render/text.d.ts +31 -0
  70. package/dist/render/text.js +210 -0
  71. package/dist/render/text.js.map +1 -0
  72. package/dist/store.d.ts +18 -0
  73. package/dist/store.js +23 -0
  74. package/dist/store.js.map +1 -0
  75. package/dist/template/change.d.ts +138 -0
  76. package/dist/template/change.js +406 -0
  77. package/dist/template/change.js.map +1 -0
  78. package/dist/template/check.d.ts +15 -0
  79. package/dist/template/check.js +97 -0
  80. package/dist/template/check.js.map +1 -0
  81. package/dist/template/draft.d.ts +47 -0
  82. package/dist/template/draft.js +276 -0
  83. package/dist/template/draft.js.map +1 -0
  84. package/dist/template/inspect.d.ts +53 -0
  85. package/dist/template/inspect.js +157 -0
  86. package/dist/template/inspect.js.map +1 -0
  87. package/dist/template/instruct.d.ts +26 -0
  88. package/dist/template/instruct.js +278 -0
  89. package/dist/template/instruct.js.map +1 -0
  90. package/dist/template/manifest.d.ts +226 -0
  91. package/dist/template/manifest.js +116 -0
  92. package/dist/template/manifest.js.map +1 -0
  93. package/dist/template/measure.d.ts +80 -0
  94. package/dist/template/measure.js +212 -0
  95. package/dist/template/measure.js.map +1 -0
  96. package/dist/template/sample.d.ts +17 -0
  97. package/dist/template/sample.js +96 -0
  98. package/dist/template/sample.js.map +1 -0
  99. package/dist/template/view.d.ts +46 -0
  100. package/dist/template/view.js +38 -0
  101. package/dist/template/view.js.map +1 -0
  102. package/dist/tools.d.ts +68 -0
  103. package/dist/tools.js +266 -0
  104. package/dist/tools.js.map +1 -0
  105. package/dist/util/image.d.ts +11 -0
  106. package/dist/util/image.js +58 -0
  107. package/dist/util/image.js.map +1 -0
  108. package/dist/util/png.d.ts +2 -0
  109. package/dist/util/png.js +50 -0
  110. package/dist/util/png.js.map +1 -0
  111. package/package.json +63 -4
@@ -0,0 +1,118 @@
1
+ import { NS, childElement, descendants, path, removeNode } from '../pptx/xml.js';
2
+ import { COPY_ID_STEP, rowLayout } from '../template/manifest.js';
3
+ /** The transform element that positions a shape within its parent. */
4
+ export function shapeTransform(shape) {
5
+ if (shape.localName === 'grpSp')
6
+ return path(shape, [NS.p, 'grpSpPr'], [NS.a, 'xfrm']);
7
+ if (shape.localName === 'graphicFrame')
8
+ return childElement(shape, NS.p, 'xfrm');
9
+ return path(shape, [NS.p, 'spPr'], [NS.a, 'xfrm']);
10
+ }
11
+ function extent(shape) {
12
+ const xfrm = shapeTransform(shape);
13
+ const off = xfrm && childElement(xfrm, NS.a, 'off');
14
+ const ext = xfrm && childElement(xfrm, NS.a, 'ext');
15
+ const x = Number(off?.getAttribute('x')) || 0;
16
+ const y = Number(off?.getAttribute('y')) || 0;
17
+ return { x, y, right: x + (Number(ext?.getAttribute('cx')) || 0), bottom: y + (Number(ext?.getAttribute('cy')) || 0) };
18
+ }
19
+ function union(extents) {
20
+ return {
21
+ x: Math.min(...extents.map((e) => e.x)),
22
+ y: Math.min(...extents.map((e) => e.y)),
23
+ right: Math.max(...extents.map((e) => e.right)),
24
+ bottom: Math.max(...extents.map((e) => e.bottom)),
25
+ };
26
+ }
27
+ function moveBy(shape, dx, dy) {
28
+ const off = childElement(shapeTransform(shape), NS.a, 'off');
29
+ if (!off)
30
+ return;
31
+ off.setAttribute('x', String(Math.round(Number(off.getAttribute('x') ?? 0) + dx)));
32
+ off.setAttribute('y', String(Math.round(Number(off.getAttribute('y') ?? 0) + dy)));
33
+ }
34
+ /** Places a shape that is not inside a group at a given area of the slide. Sizes are in EMU. */
35
+ export function placeShape(shape, box, slideWidth, slideHeight) {
36
+ const parent = shape.parentNode;
37
+ const xfrm = shapeTransform(shape);
38
+ const off = xfrm && childElement(xfrm, NS.a, 'off');
39
+ const ext = xfrm && childElement(xfrm, NS.a, 'ext');
40
+ if (!parent || parent.localName !== 'spTree' || !off || !ext)
41
+ throw new Error('a box can only be set for a shape that is not inside a group');
42
+ off.setAttribute('x', String(Math.round(box.x * slideWidth)));
43
+ off.setAttribute('y', String(Math.round(box.y * slideHeight)));
44
+ ext.setAttribute('cx', String(Math.round(box.w * slideWidth)));
45
+ ext.setAttribute('cy', String(Math.round(box.h * slideHeight)));
46
+ }
47
+ /**
48
+ * Gives a row or grid of items the requested number: removes the surplus or copies the last
49
+ * item, then lays the items out again around the centre of the area they occupied. Rows keep
50
+ * the template's spacing when there is room and tighten when there is not; a grid uses as few
51
+ * rows as the count needs, each row centred.
52
+ *
53
+ * Copied shapes get the id of their original plus a multiple of {@link COPY_ID_STEP}.
54
+ */
55
+ export function applyRepeat(shapes, repeat, count, slideWidth) {
56
+ const items = repeat.shapes.map((ids) => ids.map((id) => {
57
+ const shape = shapes.get(id);
58
+ if (!shape)
59
+ throw new Error(`repeat item points at shape #${id}, which is not on the template slide`);
60
+ return shape;
61
+ }));
62
+ const drawn = items.length;
63
+ const first = items[0]?.[0];
64
+ if (!first)
65
+ throw new Error('a repeat needs at least one item with a shape');
66
+ const boxes = items.map((item) => union(item.map(extent)));
67
+ const width = Math.max(...boxes.map((box) => box.right - box.x));
68
+ const height = Math.max(...boxes.map((box) => box.bottom - box.y));
69
+ const area = union(boxes);
70
+ // Spacing and direction are read off the template slide: the first two items of the first
71
+ // row give the column pitch and the reading direction; the first items of two rows the row pitch.
72
+ const drawnRows = rowLayout(repeat, drawn);
73
+ const second = (drawnRows[0] ?? 0) > 1 ? boxes[1] : undefined;
74
+ const pitch = second ? Math.abs(second.x - boxes[0].x) : width * 1.5;
75
+ const rightToLeft = second ? second.x < boxes[0].x : true;
76
+ const nextRow = drawnRows.length > 1 ? boxes[drawnRows[0]] : undefined;
77
+ const rowPitch = nextRow ? Math.abs(nextRow.y - boxes[0].y) : height * 1.2;
78
+ // A span in slide fractions only makes sense for shapes placed directly on the slide.
79
+ const onSlide = first.parentNode?.localName === 'spTree';
80
+ const span = repeat.span && onSlide ? { left: repeat.span.left * slideWidth, right: repeat.span.right * slideWidth } : { left: area.x, right: area.right };
81
+ for (const item of items.slice(count))
82
+ for (const shape of item)
83
+ removeNode(shape);
84
+ items.length = Math.min(drawn, count);
85
+ boxes.length = items.length;
86
+ const original = items[drawn - 1];
87
+ for (let copy = 1; original && items.length < count; copy++) {
88
+ let after = items[items.length - 1].at(-1);
89
+ const clones = original.map((shape) => {
90
+ const clone = shape.cloneNode(true);
91
+ for (const props of descendants(clone, NS.p, 'cNvPr'))
92
+ props.setAttribute('id', String(Number(props.getAttribute('id')) + copy * COPY_ID_STEP));
93
+ after.parentNode?.insertBefore(clone, after.nextSibling);
94
+ after = clone;
95
+ return clone;
96
+ });
97
+ items.push(clones);
98
+ boxes.push(boxes[drawn - 1]);
99
+ }
100
+ const rows = rowLayout(repeat, count);
101
+ const totalHeight = (rows.length - 1) * rowPitch + height;
102
+ const top = (area.y + area.bottom) / 2 - totalHeight / 2;
103
+ const centre = (area.x + area.right) / 2;
104
+ let index = 0;
105
+ rows.forEach((size, row) => {
106
+ const step = size > 1 ? Math.min(pitch, (span.right - span.left - width) / (size - 1)) : 0;
107
+ const total = (size - 1) * step + width;
108
+ const start = Math.min(Math.max(centre - total / 2, span.left), Math.max(span.left, span.right - total));
109
+ for (let position = 0; position < size; position++, index++) {
110
+ const box = boxes[index];
111
+ const x = start + (rightToLeft ? size - 1 - position : position) * step;
112
+ const y = top + row * rowPitch;
113
+ for (const shape of items[index])
114
+ moveBy(shape, x - box.x, y - box.y);
115
+ }
116
+ });
117
+ }
118
+ //# sourceMappingURL=repeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repeat.js","sourceRoot":"","sources":["../../src/render/repeat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { TableValue } from '../deck/spec.ts';
2
+ import type { Element } from '../pptx/xml.ts';
3
+ import type { Direction, TableSlotDef } from '../template/manifest.ts';
4
+ /**
5
+ * Rebuilds a table from the sample table's own rows and cells, so borders, fills and banding
6
+ * stay as designed while the number of rows and columns follows the content.
7
+ *
8
+ * - The first sample row is the header; the body rows that follow are reused in turn.
9
+ * - Columns share the table's width equally.
10
+ * - The table runs in the deck's reading direction, with text aligned to its start.
11
+ */
12
+ export declare function setTable(frame: Element, table: TableValue, slot: TableSlotDef, direction: Direction): void;
@@ -0,0 +1,84 @@
1
+ import { NS, childElement, childElements, descendants, removeNode } from '../pptx/xml.js';
2
+ import { setBodyText } from './text.js';
3
+ /**
4
+ * Rebuilds a table from the sample table's own rows and cells, so borders, fills and banding
5
+ * stay as designed while the number of rows and columns follows the content.
6
+ *
7
+ * - The first sample row is the header; the body rows that follow are reused in turn.
8
+ * - Columns share the table's width equally.
9
+ * - The table runs in the deck's reading direction, with text aligned to its start.
10
+ */
11
+ export function setTable(frame, table, slot, direction) {
12
+ const tbl = descendants(frame, NS.a, 'tbl')[0];
13
+ if (frame.localName !== 'graphicFrame' || !tbl)
14
+ throw new Error('table slots must point at a table');
15
+ const grid = childElement(tbl, NS.a, 'tblGrid');
16
+ const sampleRows = childElements(tbl, NS.a, 'tr');
17
+ const sampleColumns = grid ? childElements(grid, NS.a, 'gridCol') : [];
18
+ const headerSample = sampleRows[0];
19
+ if (!grid || !headerSample || sampleColumns.length === 0)
20
+ throw new Error('the sample table has no rows or columns to copy');
21
+ if (descendants(tbl, NS.a, 'tc').some((cell) => ['gridSpan', 'rowSpan', 'hMerge', 'vMerge'].some((name) => cell.hasAttribute(name)))) {
22
+ throw new Error('sample tables with merged cells are not supported');
23
+ }
24
+ // With two or more body rows the first two carry the banding; a single one is simply repeated.
25
+ const bodySamples = sampleRows.slice(1, 3);
26
+ if (bodySamples.length === 0)
27
+ bodySamples.push(headerSample);
28
+ const doc = tbl.ownerDocument;
29
+ if (!doc)
30
+ throw new Error('table is detached from its document');
31
+ const prefix = tbl.prefix ? `${tbl.prefix}:` : '';
32
+ const columns = table.header.length;
33
+ const align = direction === 'rtl' ? 'r' : 'l';
34
+ // Columns: equal shares of the original width.
35
+ const width = sampleColumns.reduce((sum, column) => sum + Number(column.getAttribute('w') ?? 0), 0);
36
+ const share = Math.floor(width / columns);
37
+ for (const column of sampleColumns)
38
+ removeNode(column);
39
+ for (let index = 0; index < columns; index++) {
40
+ const column = doc.createElementNS(NS.a, `${prefix}gridCol`);
41
+ column.setAttribute('w', String(index === columns - 1 ? width - share * (columns - 1) : share));
42
+ grid.appendChild(column);
43
+ }
44
+ const buildRow = (sample, cells, style) => {
45
+ const row = sample.cloneNode(true);
46
+ // Row ids must be unique, and a copied row would repeat its sample's.
47
+ for (const extension of childElements(row, NS.a, 'extLst'))
48
+ removeNode(extension);
49
+ const sampleCells = childElements(row, NS.a, 'tc');
50
+ const lastSample = sampleCells[sampleCells.length - 1];
51
+ if (!lastSample)
52
+ throw new Error('a sample table row has no cells');
53
+ for (const cell of sampleCells)
54
+ removeNode(cell);
55
+ cells.forEach((text, index) => {
56
+ const cell = (sampleCells[index] ?? lastSample).cloneNode(true);
57
+ const body = childElement(cell, NS.a, 'txBody');
58
+ if (body)
59
+ setBodyText(body, [text], style ? { flipAlign: false, align, style } : { flipAlign: false, align });
60
+ row.insertBefore(cell, childElement(row, NS.a, 'extLst') ?? null);
61
+ });
62
+ return row;
63
+ };
64
+ const rows = [
65
+ buildRow(headerSample, table.header, slot.headerText),
66
+ ...table.rows.map((cells, index) => buildRow(bodySamples[index % bodySamples.length], cells, slot.bodyText)),
67
+ ];
68
+ for (const row of sampleRows)
69
+ removeNode(row);
70
+ for (const row of rows)
71
+ tbl.appendChild(row);
72
+ let props = childElement(tbl, NS.a, 'tblPr');
73
+ if (!props) {
74
+ props = doc.createElementNS(NS.a, `${prefix}tblPr`);
75
+ tbl.insertBefore(props, tbl.firstChild);
76
+ }
77
+ props.setAttribute('rtl', direction === 'rtl' ? '1' : '0');
78
+ // PowerPoint recomputes the frame height from the rows; other viewers use the stored value.
79
+ const extent = descendants(frame, NS.a, 'ext').find((el) => el.parentNode && el.parentNode.localName === 'xfrm');
80
+ const height = rows.reduce((sum, row) => sum + Number(row.getAttribute('h') ?? 0), 0);
81
+ if (extent && height > 0)
82
+ extent.setAttribute('cy', String(height));
83
+ }
84
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/render/table.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Element } from '../pptx/xml.ts';
2
+ import type { Direction, TableTextStyle } from '../template/manifest.ts';
3
+ export interface TextOptions {
4
+ /** Swap left and right alignment (the deck reads the other way from the template). */
5
+ flipAlign: boolean;
6
+ /** Which run of the template paragraph supplies the formatting. Defaults to the first. */
7
+ styleRun?: 'first' | 'last';
8
+ /** Set the paragraph alignment outright, whatever the template has. */
9
+ align?: 'l' | 'r' | 'ctr';
10
+ /** Formatting to put on the text, for places where the template defines none. */
11
+ style?: TableTextStyle;
12
+ }
13
+ /** Base direction of a piece of text from its first letter; `undefined` when it has none (e.g. "78%"). */
14
+ export declare function detectDirection(text: string): Direction | undefined;
15
+ /**
16
+ * Replaces the text of a shape. Each new paragraph takes its formatting from the
17
+ * template paragraph in the same position (the last one is reused when there are more).
18
+ */
19
+ export declare function setShapeText(shape: Element, paragraphs: string[], options: TextOptions): void;
20
+ /** Replaces the paragraphs of a text body (`p:txBody` of a shape, `a:txBody` of a table cell). */
21
+ export declare function setBodyText(body: Element, paragraphs: string[], options: TextOptions): void;
22
+ /**
23
+ * Resizes the text of a shape after it was filled. `scale` multiplies each run's own size;
24
+ * `size` sets every run to that size first (points). Runs that state no size are left alone
25
+ * unless `size` is given. `paragraphGap` sets the space after each paragraph (points).
26
+ */
27
+ export declare function adjustText(shape: Element, change: {
28
+ scale?: number;
29
+ size?: number;
30
+ paragraphGap?: number;
31
+ }): void;
@@ -0,0 +1,210 @@
1
+ import { NS, childElement, childElements, removeNode } from '../pptx/xml.js';
2
+ const RTL_LETTER = /[\p{Script=Hebrew}\p{Script=Arabic}\p{Script=Syriac}\p{Script=Thaana}]/u;
3
+ /** Base direction of a piece of text from its first letter; `undefined` when it has none (e.g. "78%"). */
4
+ export function detectDirection(text) {
5
+ const firstLetter = /\p{L}/u.exec(text)?.[0];
6
+ if (!firstLetter)
7
+ return undefined;
8
+ return RTL_LETTER.test(firstLetter) ? 'rtl' : 'ltr';
9
+ }
10
+ /**
11
+ * Replaces the text of a shape. Each new paragraph takes its formatting from the
12
+ * template paragraph in the same position (the last one is reused when there are more).
13
+ */
14
+ export function setShapeText(shape, paragraphs, options) {
15
+ const body = childElement(shape, NS.p, 'txBody');
16
+ if (!body)
17
+ throw new Error('shape has no text body to fill');
18
+ setBodyText(body, paragraphs, options);
19
+ }
20
+ /** Replaces the paragraphs of a text body (`p:txBody` of a shape, `a:txBody` of a table cell). */
21
+ export function setBodyText(body, paragraphs, options) {
22
+ const existing = childElements(body, NS.a, 'p');
23
+ if (existing.length === 0)
24
+ throw new Error('text body has no paragraph to take formatting from');
25
+ const fresh = paragraphs.map((text, index) => {
26
+ const proto = existing[Math.min(index, existing.length - 1)];
27
+ return buildParagraph(proto, text, options);
28
+ });
29
+ for (const paragraph of existing)
30
+ removeNode(paragraph);
31
+ for (const paragraph of fresh)
32
+ body.appendChild(paragraph);
33
+ }
34
+ /**
35
+ * Resizes the text of a shape after it was filled. `scale` multiplies each run's own size;
36
+ * `size` sets every run to that size first (points). Runs that state no size are left alone
37
+ * unless `size` is given. `paragraphGap` sets the space after each paragraph (points).
38
+ */
39
+ export function adjustText(shape, change) {
40
+ const body = childElement(shape, NS.p, 'txBody');
41
+ if (!body)
42
+ return;
43
+ const scale = change.scale ?? 1;
44
+ for (const paragraph of childElements(body, NS.a, 'p')) {
45
+ const props = [...childElements(paragraph, NS.a, 'r').map((run) => childElement(run, NS.a, 'rPr')), childElement(paragraph, NS.a, 'endParaRPr')];
46
+ for (const runProps of props) {
47
+ if (!runProps)
48
+ continue;
49
+ const base = change.size !== undefined ? change.size * 100 : Number(runProps.getAttribute('sz') ?? 0);
50
+ if (base > 0 && (change.size !== undefined || scale !== 1))
51
+ runProps.setAttribute('sz', String(Math.round((base * scale) / 50) * 50));
52
+ }
53
+ if (change.paragraphGap !== undefined)
54
+ setParagraphGap(paragraph, change.paragraphGap);
55
+ }
56
+ }
57
+ function setParagraphGap(paragraph, points) {
58
+ const doc = paragraph.ownerDocument;
59
+ if (!doc)
60
+ return;
61
+ const prefix = paragraph.prefix ? `${paragraph.prefix}:` : '';
62
+ let props = childElement(paragraph, NS.a, 'pPr');
63
+ if (!props) {
64
+ props = doc.createElementNS(NS.a, `${prefix}pPr`);
65
+ paragraph.insertBefore(props, paragraph.firstChild);
66
+ }
67
+ const old = childElement(props, NS.a, 'spcAft');
68
+ if (old)
69
+ removeNode(old);
70
+ const gap = doc.createElementNS(NS.a, `${prefix}spcAft`);
71
+ const value = doc.createElementNS(NS.a, `${prefix}spcPts`);
72
+ value.setAttribute('val', String(Math.round(points * 100)));
73
+ gap.appendChild(value);
74
+ // Paragraph properties keep a fixed order: line spacing, space before, space after, then the rest.
75
+ const before = childElement(props, NS.a, 'spcBef') ?? childElement(props, NS.a, 'lnSpc');
76
+ props.insertBefore(gap, before ? before.nextSibling : props.firstChild);
77
+ }
78
+ function buildParagraph(proto, text, options) {
79
+ const doc = proto.ownerDocument;
80
+ if (!doc)
81
+ throw new Error('paragraph is detached from its document');
82
+ const prefix = proto.prefix ? `${proto.prefix}:` : '';
83
+ const paragraph = proto.cloneNode(true);
84
+ // One run of the template paragraph carries the formatting we keep. A paragraph that was
85
+ // empty in the template has no run, so its formatting comes from the end-of-paragraph properties.
86
+ const runs = childElements(paragraph, NS.a, 'r');
87
+ let run = options.styleRun === 'last' ? runs[runs.length - 1] : runs[0];
88
+ const endProps = childElement(paragraph, NS.a, 'endParaRPr');
89
+ if (!run) {
90
+ run = doc.createElementNS(NS.a, `${prefix}r`);
91
+ if (endProps) {
92
+ const runProps = doc.createElementNS(NS.a, `${prefix}rPr`);
93
+ for (let i = 0; i < endProps.attributes.length; i++) {
94
+ const attr = endProps.attributes.item(i);
95
+ if (attr)
96
+ runProps.setAttribute(attr.name, attr.value);
97
+ }
98
+ for (const child of childElements(endProps))
99
+ runProps.appendChild(child.cloneNode(true));
100
+ run.appendChild(runProps);
101
+ }
102
+ }
103
+ let textNode = childElement(run, NS.a, 't');
104
+ if (!textNode) {
105
+ textNode = doc.createElementNS(NS.a, `${prefix}t`);
106
+ run.appendChild(textNode);
107
+ }
108
+ textNode.textContent = text;
109
+ if (options.style)
110
+ applyStyle(run, options.style, prefix);
111
+ // Drop every run, line break and field of the template paragraph, then put ours back.
112
+ for (const child of childElements(paragraph)) {
113
+ if (child.localName !== 'pPr' && child.localName !== 'endParaRPr')
114
+ removeNode(child);
115
+ }
116
+ paragraph.insertBefore(run, endProps ?? null);
117
+ applyDirection(paragraph, text, options, prefix);
118
+ return paragraph;
119
+ }
120
+ function applyStyle(run, style, prefix) {
121
+ const doc = run.ownerDocument;
122
+ if (!doc)
123
+ return;
124
+ let props = childElement(run, NS.a, 'rPr');
125
+ if (!props) {
126
+ props = doc.createElementNS(NS.a, `${prefix}rPr`);
127
+ run.insertBefore(props, run.firstChild);
128
+ }
129
+ if (style.size !== undefined)
130
+ props.setAttribute('sz', String(Math.round(style.size * 100)));
131
+ if (style.bold !== undefined)
132
+ props.setAttribute('b', style.bold ? '1' : '0');
133
+ // Run properties keep a fixed child order: line, fill, effects, then the typefaces.
134
+ if (style.color) {
135
+ for (const fill of ['noFill', 'solidFill', 'gradFill', 'blipFill', 'pattFill', 'grpFill']) {
136
+ const old = childElement(props, NS.a, fill);
137
+ if (old)
138
+ removeNode(old);
139
+ }
140
+ const fill = doc.createElementNS(NS.a, `${prefix}solidFill`);
141
+ const color = doc.createElementNS(NS.a, `${prefix}srgbClr`);
142
+ color.setAttribute('val', style.color.replace(/^#/, '').toUpperCase());
143
+ fill.appendChild(color);
144
+ const line = childElement(props, NS.a, 'ln');
145
+ props.insertBefore(fill, line ? line.nextSibling : props.firstChild);
146
+ }
147
+ if (style.font) {
148
+ const after = ['hlinkClick', 'hlinkMouseOver', 'rtl', 'extLst'].map((name) => childElement(props, NS.a, name)).find(Boolean) ?? null;
149
+ for (const script of ['latin', 'ea', 'cs', 'sym']) {
150
+ const old = childElement(props, NS.a, script);
151
+ if (old)
152
+ removeNode(old);
153
+ const face = doc.createElementNS(NS.a, `${prefix}${script}`);
154
+ face.setAttribute('typeface', style.font);
155
+ props.insertBefore(face, after);
156
+ }
157
+ }
158
+ }
159
+ function applyDirection(paragraph, text, options, prefix) {
160
+ const direction = detectDirection(text);
161
+ let props = childElement(paragraph, NS.a, 'pPr');
162
+ if (!props) {
163
+ if (!direction && !options.flipAlign && !options.align)
164
+ return;
165
+ const doc = paragraph.ownerDocument;
166
+ if (!doc)
167
+ return;
168
+ props = doc.createElementNS(NS.a, `${prefix}pPr`);
169
+ paragraph.insertBefore(props, paragraph.firstChild);
170
+ }
171
+ if (direction)
172
+ props.setAttribute('rtl', direction === 'rtl' ? '1' : '0');
173
+ if (options.align) {
174
+ props.setAttribute('algn', options.align);
175
+ }
176
+ else if (options.flipAlign) {
177
+ // A paragraph that states no alignment is left-aligned.
178
+ const align = props.getAttribute('algn') ?? 'l';
179
+ if (align === 'r')
180
+ props.setAttribute('algn', 'l');
181
+ else if (align === 'l')
182
+ props.setAttribute('algn', 'r');
183
+ }
184
+ if (direction === 'rtl')
185
+ markRightToLeftLanguage(paragraph, text, prefix);
186
+ }
187
+ const RTL_LANGUAGE = /^(he|iw|yi|ar|fa|ur|ps|ug|sd|ckb|syr|dv)\b/i;
188
+ /**
189
+ * PowerPoint places punctuation and spaces by the language of their run, not only by the
190
+ * paragraph's direction: in a run marked English, "contact: name@example.org" after Hebrew words
191
+ * puts the colon on the far side of the address. A right-to-left text therefore gets a
192
+ * right-to-left language on its run, unless the template already gave it one.
193
+ */
194
+ function markRightToLeftLanguage(paragraph, text, prefix) {
195
+ const doc = paragraph.ownerDocument;
196
+ if (!doc)
197
+ return;
198
+ const letter = RTL_LETTER.exec(text)?.[0] ?? '';
199
+ const language = /\p{Script=Hebrew}/u.test(letter) ? 'he-IL' : /\p{Script=Arabic}/u.test(letter) ? 'ar-SA' : /\p{Script=Syriac}/u.test(letter) ? 'syr-SY' : 'dv-MV';
200
+ for (const run of childElements(paragraph, NS.a, 'r')) {
201
+ let runProps = childElement(run, NS.a, 'rPr');
202
+ if (!runProps) {
203
+ runProps = doc.createElementNS(NS.a, `${prefix}rPr`);
204
+ run.insertBefore(runProps, run.firstChild);
205
+ }
206
+ if (!RTL_LANGUAGE.test(runProps.getAttribute('lang') ?? ''))
207
+ runProps.setAttribute('lang', language);
208
+ }
209
+ }
210
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/render/text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Where plans, decks, pictures and rendered files are kept between calls. Keys look like paths
3
+ * (`deck/ab12.json`, `asset/gen-1f2e`), so a folder on a volume, a bucket or a table all fit.
4
+ *
5
+ * Pictures are stored on their own, apart from the deck JSON and the pptx. The JSON stays a
6
+ * few kilobytes of text, which is all a language model ever sees; a pptx can be rebuilt from
7
+ * the JSON and the pictures whenever it is wanted.
8
+ */
9
+ export interface BlobStore {
10
+ get(key: string): Promise<Uint8Array | undefined>;
11
+ set(key: string, data: Uint8Array): Promise<void>;
12
+ }
13
+ /** A store that lives in memory, for tests and short-lived processes. */
14
+ export declare function memoryStore(): BlobStore & {
15
+ keys(): string[];
16
+ };
17
+ export declare function readJson<T>(store: BlobStore, key: string): Promise<T | undefined>;
18
+ export declare function writeJson(store: BlobStore, key: string, value: unknown): Promise<void>;
package/dist/store.js ADDED
@@ -0,0 +1,23 @@
1
+ /** A store that lives in memory, for tests and short-lived processes. */
2
+ export function memoryStore() {
3
+ const blobs = new Map();
4
+ return {
5
+ async get(key) {
6
+ return blobs.get(key);
7
+ },
8
+ async set(key, data) {
9
+ blobs.set(key, data);
10
+ },
11
+ keys: () => [...blobs.keys()],
12
+ };
13
+ }
14
+ const encoder = new TextEncoder();
15
+ const decoder = new TextDecoder();
16
+ export async function readJson(store, key) {
17
+ const data = await store.get(key);
18
+ return data ? JSON.parse(decoder.decode(data)) : undefined;
19
+ }
20
+ export async function writeJson(store, key, value) {
21
+ await store.set(key, encoder.encode(JSON.stringify(value)));
22
+ }
23
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAaA,yEAAyE;AACzE,MAAM,UAAU,WAAW;IACzB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC5C,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAG;YACX,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI;YACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC;QACD,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,KAAgB,EAAE,GAAW;IAC7D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAgB,EAAE,GAAW,EAAE,KAAc;IAC3E,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC"}