@qvac/harness 0.7.3 → 0.8.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 (106) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/NOTICE.md +16 -0
  3. package/dist-lib/lib/capabilities/completion.d.ts +1 -0
  4. package/dist-lib/lib/capabilities/completion.js +28 -8
  5. package/dist-lib/lib/capabilities/tool-turns.d.ts +3 -0
  6. package/dist-lib/lib/capabilities/tool-turns.js +7 -0
  7. package/dist-lib/lib/context-window.js +2 -2
  8. package/dist-lib/lib/helpers/run-outcome.d.ts +4 -1
  9. package/dist-lib/lib/helpers/run-outcome.js +14 -8
  10. package/dist-lib/lib/helpers/tool-call-markup.js +4 -4
  11. package/dist-lib/lib/hooks/built-in/arg-repair.js +7 -0
  12. package/dist-lib/lib/office/engine/codes.d.ts +62 -0
  13. package/dist-lib/lib/office/engine/codes.js +61 -0
  14. package/dist-lib/lib/office/engine/docx/document.d.ts +216 -0
  15. package/dist-lib/lib/office/engine/docx/document.js +1152 -0
  16. package/dist-lib/lib/office/engine/docx/index.d.ts +7 -0
  17. package/dist-lib/lib/office/engine/docx/index.js +8 -0
  18. package/dist-lib/lib/office/engine/docx/styles.d.ts +31 -0
  19. package/dist-lib/lib/office/engine/docx/styles.js +173 -0
  20. package/dist-lib/lib/office/engine/docx/template.d.ts +18 -0
  21. package/dist-lib/lib/office/engine/docx/template.js +133 -0
  22. package/dist-lib/lib/office/engine/docx/text.d.ts +55 -0
  23. package/dist-lib/lib/office/engine/docx/text.js +538 -0
  24. package/dist-lib/lib/office/engine/drawingml/chart.d.ts +63 -0
  25. package/dist-lib/lib/office/engine/drawingml/chart.js +539 -0
  26. package/dist-lib/lib/office/engine/drawingml/text.d.ts +35 -0
  27. package/dist-lib/lib/office/engine/drawingml/text.js +352 -0
  28. package/dist-lib/lib/office/engine/errors.d.ts +6 -0
  29. package/dist-lib/lib/office/engine/errors.js +12 -0
  30. package/dist-lib/lib/office/engine/image.d.ts +8 -0
  31. package/dist-lib/lib/office/engine/image.js +48 -0
  32. package/dist-lib/lib/office/engine/index.d.ts +12 -0
  33. package/dist-lib/lib/office/engine/index.js +7 -0
  34. package/dist-lib/lib/office/engine/opc/content-types.d.ts +17 -0
  35. package/dist-lib/lib/office/engine/opc/content-types.js +74 -0
  36. package/dist-lib/lib/office/engine/opc/media.d.ts +13 -0
  37. package/dist-lib/lib/office/engine/opc/media.js +11 -0
  38. package/dist-lib/lib/office/engine/opc/package.d.ts +51 -0
  39. package/dist-lib/lib/office/engine/opc/package.js +324 -0
  40. package/dist-lib/lib/office/engine/opc/paths.d.ts +7 -0
  41. package/dist-lib/lib/office/engine/opc/paths.js +46 -0
  42. package/dist-lib/lib/office/engine/opc/properties.d.ts +7 -0
  43. package/dist-lib/lib/office/engine/opc/properties.js +75 -0
  44. package/dist-lib/lib/office/engine/opc/relationships.d.ts +23 -0
  45. package/dist-lib/lib/office/engine/opc/relationships.js +65 -0
  46. package/dist-lib/lib/office/engine/opc/zip.d.ts +15 -0
  47. package/dist-lib/lib/office/engine/opc/zip.js +264 -0
  48. package/dist-lib/lib/office/engine/pptx/fit.d.ts +12 -0
  49. package/dist-lib/lib/office/engine/pptx/fit.js +37 -0
  50. package/dist-lib/lib/office/engine/pptx/index.d.ts +8 -0
  51. package/dist-lib/lib/office/engine/pptx/index.js +8 -0
  52. package/dist-lib/lib/office/engine/pptx/inherit.d.ts +29 -0
  53. package/dist-lib/lib/office/engine/pptx/inherit.js +155 -0
  54. package/dist-lib/lib/office/engine/pptx/notes.d.ts +5 -0
  55. package/dist-lib/lib/office/engine/pptx/notes.js +85 -0
  56. package/dist-lib/lib/office/engine/pptx/presentation.d.ts +54 -0
  57. package/dist-lib/lib/office/engine/pptx/presentation.js +749 -0
  58. package/dist-lib/lib/office/engine/pptx/read.d.ts +9 -0
  59. package/dist-lib/lib/office/engine/pptx/read.js +66 -0
  60. package/dist-lib/lib/office/engine/pptx/shapes.d.ts +52 -0
  61. package/dist-lib/lib/office/engine/pptx/shapes.js +276 -0
  62. package/dist-lib/lib/office/engine/pptx/slides.d.ts +27 -0
  63. package/dist-lib/lib/office/engine/pptx/slides.js +123 -0
  64. package/dist-lib/lib/office/engine/pptx/template.d.ts +20 -0
  65. package/dist-lib/lib/office/engine/pptx/template.js +391 -0
  66. package/dist-lib/lib/office/engine/pptx/types.d.ts +120 -0
  67. package/dist-lib/lib/office/engine/pptx/types.js +1 -0
  68. package/dist-lib/lib/office/engine/units.d.ts +3 -0
  69. package/dist-lib/lib/office/engine/units.js +12 -0
  70. package/dist-lib/lib/office/engine/utf8.d.ts +2 -0
  71. package/dist-lib/lib/office/engine/utf8.js +103 -0
  72. package/dist-lib/lib/office/engine/xlsx/formula.d.ts +49 -0
  73. package/dist-lib/lib/office/engine/xlsx/formula.js +381 -0
  74. package/dist-lib/lib/office/engine/xlsx/index.d.ts +8 -0
  75. package/dist-lib/lib/office/engine/xlsx/index.js +8 -0
  76. package/dist-lib/lib/office/engine/xlsx/refs.d.ts +22 -0
  77. package/dist-lib/lib/office/engine/xlsx/refs.js +82 -0
  78. package/dist-lib/lib/office/engine/xlsx/reshape.d.ts +21 -0
  79. package/dist-lib/lib/office/engine/xlsx/reshape.js +424 -0
  80. package/dist-lib/lib/office/engine/xlsx/sheet.d.ts +108 -0
  81. package/dist-lib/lib/office/engine/xlsx/sheet.js +662 -0
  82. package/dist-lib/lib/office/engine/xlsx/strings.d.ts +15 -0
  83. package/dist-lib/lib/office/engine/xlsx/strings.js +93 -0
  84. package/dist-lib/lib/office/engine/xlsx/styles.d.ts +38 -0
  85. package/dist-lib/lib/office/engine/xlsx/styles.js +369 -0
  86. package/dist-lib/lib/office/engine/xlsx/template.d.ts +7 -0
  87. package/dist-lib/lib/office/engine/xlsx/template.js +54 -0
  88. package/dist-lib/lib/office/engine/xlsx/workbook.d.ts +161 -0
  89. package/dist-lib/lib/office/engine/xlsx/workbook.js +850 -0
  90. package/dist-lib/lib/office/engine/xlsx/write.d.ts +2 -0
  91. package/dist-lib/lib/office/engine/xlsx/write.js +42 -0
  92. package/dist-lib/lib/office/engine/xml.d.ts +45 -0
  93. package/dist-lib/lib/office/engine/xml.js +258 -0
  94. package/dist-lib/lib/tools/exec/scope.d.ts +2 -0
  95. package/dist-lib/lib/tools/exec/scope.js +33 -2
  96. package/dist-lib/lib/tools/pdf/build.d.ts +43 -0
  97. package/dist-lib/lib/tools/pdf/build.js +150 -0
  98. package/dist-lib/lib/tools/pdf/images.d.ts +7 -0
  99. package/dist-lib/lib/tools/pdf/images.js +82 -0
  100. package/dist-lib/lib/tools/pdf/request.d.ts +63 -0
  101. package/dist-lib/lib/tools/pdf/request.js +335 -0
  102. package/dist-lib/lib/tools/pdf.d.ts +6 -0
  103. package/dist-lib/lib/tools/pdf.js +302 -0
  104. package/dist-lib/lib/tools/skill.js +14 -0
  105. package/package.json +25 -1
  106. package/worker/harness-sidecar.mjs +3 -1
@@ -0,0 +1,391 @@
1
+ import * as xml from '../xml.js';
2
+ import { DocsError } from '../errors.js';
3
+ import { isRecord } from '../../../guards.js';
4
+ const { a: A, p: P, r: R } = xml.ns;
5
+ const REL_BASE = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/';
6
+ const PML = 'application/vnd.openxmlformats-officedocument.presentationml.';
7
+ const TYPES = {
8
+ presentation: PML + 'presentation.main+xml',
9
+ master: PML + 'slideMaster+xml',
10
+ layout: PML + 'slideLayout+xml',
11
+ presProps: PML + 'presProps+xml',
12
+ viewProps: PML + 'viewProps+xml',
13
+ tableStyles: PML + 'tableStyles+xml',
14
+ theme: 'application/vnd.openxmlformats-officedocument.theme+xml',
15
+ core: 'application/vnd.openxmlformats-package.core-properties+xml',
16
+ app: 'application/vnd.openxmlformats-officedocument.extended-properties+xml'
17
+ };
18
+ export const SIZES = {
19
+ '16:9': { width: 12192000, height: 6858000 },
20
+ '4:3': { width: 9144000, height: 6858000 }
21
+ };
22
+ const DEFAULT_COLORS = {
23
+ dark1: '000000',
24
+ light1: 'FFFFFF',
25
+ dark2: '44546A',
26
+ light2: 'E7E6E6',
27
+ accent1: '4472C4',
28
+ accent2: 'ED7D31',
29
+ accent3: 'A5A5A5',
30
+ accent4: 'FFC000',
31
+ accent5: '5B9BD5',
32
+ accent6: '70AD47',
33
+ hyperlink: '0563C1',
34
+ followedHyperlink: '954F72'
35
+ };
36
+ const DEFAULT_FONTS = { heading: 'Calibri Light', body: 'Calibri' };
37
+ const SCHEME_NAMES = {
38
+ dark1: 'dk1',
39
+ light1: 'lt1',
40
+ dark2: 'dk2',
41
+ light2: 'lt2',
42
+ accent1: 'accent1',
43
+ accent2: 'accent2',
44
+ accent3: 'accent3',
45
+ accent4: 'accent4',
46
+ accent5: 'accent5',
47
+ accent6: 'accent6',
48
+ hyperlink: 'hlink',
49
+ followedHyperlink: 'folHlink'
50
+ };
51
+ export const TABLE_STYLE = '{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}';
52
+ const FOOTER_BODY_PR = '<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0" anchor="ctr"/>';
53
+ function isThemeColor(key) {
54
+ return key in DEFAULT_COLORS;
55
+ }
56
+ function isFontKey(key) {
57
+ return key in DEFAULT_FONTS;
58
+ }
59
+ function isSizeName(value) {
60
+ return value === '16:9' || value === '4:3';
61
+ }
62
+ function sizeSource(value) {
63
+ if (value === undefined || value === '') {
64
+ return SIZES['16:9'];
65
+ }
66
+ if (isSizeName(value)) {
67
+ return SIZES[value];
68
+ }
69
+ return isRecord(value) ? value : null;
70
+ }
71
+ function inRange(n) {
72
+ return typeof n === 'number' && Number.isInteger(n) && n >= 914400 && n <= 51206400;
73
+ }
74
+ function resolveSize(value) {
75
+ const raw = sizeSource(value);
76
+ const width = raw?.width;
77
+ const height = raw?.height;
78
+ if (!inRange(width) || !inRange(height)) {
79
+ throw new DocsError('INVALID_OPTIONS', 'size must be "16:9", "4:3" or { width, height } in EMU between 1 and 56 inches');
80
+ }
81
+ return { width, height };
82
+ }
83
+ function resolveColors(value) {
84
+ const colors = { ...DEFAULT_COLORS };
85
+ for (const [key, color] of Object.entries(isRecord(value) ? value : {})) {
86
+ if (!isThemeColor(key)) {
87
+ throw new DocsError('INVALID_OPTIONS', `unknown theme color "${key}"; use ${Object.keys(DEFAULT_COLORS).join(', ')}`);
88
+ }
89
+ if (typeof color !== 'string' || !/^#?[0-9a-fA-F]{6}$/.test(color)) {
90
+ throw new DocsError('INVALID_OPTIONS', `theme color ${key} must be hex RGB, got ${String(color)}`);
91
+ }
92
+ colors[key] = color.replace('#', '').toUpperCase();
93
+ }
94
+ return colors;
95
+ }
96
+ function resolveFonts(value) {
97
+ const fonts = { ...DEFAULT_FONTS };
98
+ for (const [key, face] of Object.entries(isRecord(value) ? value : {})) {
99
+ if (!isFontKey(key)) {
100
+ throw new DocsError('INVALID_OPTIONS', `unknown theme font "${key}"; use heading or body`);
101
+ }
102
+ if (typeof face !== 'string' || !face.trim()) {
103
+ throw new DocsError('INVALID_OPTIONS', `theme font ${key} must be a typeface name`);
104
+ }
105
+ fonts[key] = face;
106
+ }
107
+ return fonts;
108
+ }
109
+ function options(opts) {
110
+ const input = isRecord(opts) ? opts : {};
111
+ return {
112
+ size: resolveSize(input.size),
113
+ colors: resolveColors(input.colors),
114
+ fonts: resolveFonts(input.fonts),
115
+ title: typeof input.title === 'string' ? input.title : undefined
116
+ };
117
+ }
118
+ function escape(value) {
119
+ return value
120
+ .replace(/&/g, '&amp;')
121
+ .replace(/</g, '&lt;')
122
+ .replace(/>/g, '&gt;')
123
+ .replace(/"/g, '&quot;');
124
+ }
125
+ function geometry(size) {
126
+ const sx = (n) => Math.round((n * size.width) / 12192000);
127
+ const sy = (n) => Math.round((n * size.height) / 6858000);
128
+ const rect = (at) => ({ x: sx(at.x), y: sy(at.y), cx: sx(at.cx), cy: sy(at.cy) });
129
+ return {
130
+ title: rect({ x: 838200, y: 365125, cx: 10515600, cy: 1325563 }),
131
+ body: rect({ x: 838200, y: 1825625, cx: 10515600, cy: 4351338 }),
132
+ date: rect({ x: 838200, y: 6356350, cx: 2743200, cy: 365125 }),
133
+ footer: rect({ x: 4038600, y: 6356350, cx: 4114800, cy: 365125 }),
134
+ number: rect({ x: 8610600, y: 6356350, cx: 2743200, cy: 365125 }),
135
+ coverTitle: rect({ x: 1524000, y: 1122363, cx: 9144000, cy: 2387600 }),
136
+ coverSubtitle: rect({ x: 1524000, y: 3602038, cx: 9144000, cy: 1655762 }),
137
+ sectionTitle: rect({ x: 831850, y: 1709738, cx: 10515600, cy: 2852737 }),
138
+ sectionBody: rect({ x: 831850, y: 4589463, cx: 10515600, cy: 1500187 }),
139
+ left: rect({ x: 838200, y: 1825625, cx: 5181600, cy: 4351338 }),
140
+ right: rect({ x: 6172200, y: 1825625, cx: 5181600, cy: 4351338 })
141
+ };
142
+ }
143
+ function xfrm(b) {
144
+ return `<a:xfrm><a:off x="${b.x}" y="${b.y}"/><a:ext cx="${b.cx}" cy="${b.cy}"/></a:xfrm>`;
145
+ }
146
+ function run(text) {
147
+ return `<a:p><a:r><a:rPr lang="en-US"/><a:t>${escape(text)}</a:t></a:r></a:p>`;
148
+ }
149
+ function placeholder(spec) {
150
+ const attrs = Object.entries(spec.ph)
151
+ .map(([k, v]) => ` ${k}="${v}"`)
152
+ .join('');
153
+ const box = spec.box ? xfrm(spec.box) : '';
154
+ const bodyPr = spec.bodyPr ?? '<a:bodyPr/>';
155
+ const lstStyle = spec.lstStyle ?? '<a:lstStyle/>';
156
+ return `<p:sp><p:nvSpPr><p:cNvPr id="${spec.id}" name="${escape(spec.name)}"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph${attrs}/></p:nvPr></p:nvSpPr><p:spPr>${box}</p:spPr><p:txBody>${bodyPr}${lstStyle}${run(spec.prompt)}</p:txBody></p:sp>`;
157
+ }
158
+ function tree(shapes) {
159
+ return `<p:spTree><p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr><a:xfrm><a:off x="0" y="0"/><a:ext cx="0" cy="0"/><a:chOff x="0" y="0"/><a:chExt cx="0" cy="0"/></a:xfrm></p:grpSpPr>${shapes.join('')}</p:spTree>`;
160
+ }
161
+ function footerStyle(align) {
162
+ return `<a:lstStyle><a:lvl1pPr algn="${align}"><a:defRPr sz="1200"><a:solidFill><a:schemeClr val="tx1"><a:tint val="75000"/></a:schemeClr></a:solidFill></a:defRPr></a:lvl1pPr></a:lstStyle>`;
163
+ }
164
+ function footers(g, spec) {
165
+ const { start, boxed } = spec;
166
+ const parts = [
167
+ { name: 'Date Placeholder', ph: { type: 'dt', sz: 'half', idx: 10 }, box: g.date, align: 'l' },
168
+ {
169
+ name: 'Footer Placeholder',
170
+ ph: { type: 'ftr', sz: 'quarter', idx: 11 },
171
+ box: g.footer,
172
+ align: 'ctr'
173
+ },
174
+ {
175
+ name: 'Slide Number Placeholder',
176
+ ph: { type: 'sldNum', sz: 'quarter', idx: 12 },
177
+ box: g.number,
178
+ align: 'r'
179
+ }
180
+ ];
181
+ return parts.map((part, i) => placeholder({
182
+ id: start + i,
183
+ name: part.name,
184
+ ph: part.ph,
185
+ box: boxed ? part.box : undefined,
186
+ bodyPr: boxed ? FOOTER_BODY_PR : undefined,
187
+ lstStyle: boxed ? footerStyle(part.align) : undefined,
188
+ prompt: ''
189
+ }));
190
+ }
191
+ function rootXml(spec) {
192
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<p:${spec.local} xmlns:a="${A}" xmlns:r="${R}" xmlns:p="${P}"${spec.attrs}>${spec.body}</p:${spec.local}>`;
193
+ }
194
+ function titlePlaceholder(prompt = 'Click to edit Master title style') {
195
+ return placeholder({ id: 2, name: 'Title 1', ph: { type: 'title' }, prompt });
196
+ }
197
+ function coverLayout(g) {
198
+ const noBullets = '<a:lstStyle><a:lvl1pPr marL="0" indent="0" algn="ctr"><a:buNone/><a:defRPr sz="2400"/></a:lvl1pPr></a:lstStyle>';
199
+ return {
200
+ name: 'Title Slide',
201
+ type: 'title',
202
+ shapes: [
203
+ placeholder({
204
+ id: 2,
205
+ name: 'Title 1',
206
+ ph: { type: 'ctrTitle' },
207
+ box: g.coverTitle,
208
+ bodyPr: '<a:bodyPr anchor="b"/>',
209
+ lstStyle: '<a:lstStyle><a:lvl1pPr algn="ctr"><a:defRPr sz="6000"/></a:lvl1pPr></a:lstStyle>',
210
+ prompt: 'Click to edit Master title style'
211
+ }),
212
+ placeholder({
213
+ id: 3,
214
+ name: 'Subtitle 2',
215
+ ph: { type: 'subTitle', idx: 1 },
216
+ box: g.coverSubtitle,
217
+ lstStyle: noBullets,
218
+ prompt: 'Click to edit Master subtitle style'
219
+ }),
220
+ ...footers(g, { start: 4, boxed: false })
221
+ ]
222
+ };
223
+ }
224
+ function sectionLayout(g) {
225
+ return {
226
+ name: 'Section Header',
227
+ type: 'secHead',
228
+ shapes: [
229
+ placeholder({
230
+ id: 2,
231
+ name: 'Title 1',
232
+ ph: { type: 'title' },
233
+ box: g.sectionTitle,
234
+ bodyPr: '<a:bodyPr anchor="b"/>',
235
+ lstStyle: '<a:lstStyle><a:lvl1pPr><a:defRPr sz="6000"/></a:lvl1pPr></a:lstStyle>',
236
+ prompt: 'Click to edit Master title style'
237
+ }),
238
+ placeholder({
239
+ id: 3,
240
+ name: 'Text Placeholder 2',
241
+ ph: { type: 'body', idx: 1 },
242
+ box: g.sectionBody,
243
+ lstStyle: '<a:lstStyle><a:lvl1pPr marL="0" indent="0"><a:buNone/><a:defRPr sz="2400"><a:solidFill><a:schemeClr val="tx1"><a:tint val="75000"/></a:schemeClr></a:solidFill></a:defRPr></a:lvl1pPr></a:lstStyle>',
244
+ prompt: 'Click to edit Master text styles'
245
+ }),
246
+ ...footers(g, { start: 4, boxed: false })
247
+ ]
248
+ };
249
+ }
250
+ function twoContentLayout(g) {
251
+ const content = (id, box) => placeholder({
252
+ id,
253
+ name: `Content Placeholder ${id - 1}`,
254
+ ph: { sz: 'half', idx: id - 2 },
255
+ box,
256
+ prompt: 'Click to edit Master text styles'
257
+ });
258
+ return {
259
+ name: 'Two Content',
260
+ type: 'twoObj',
261
+ shapes: [
262
+ titlePlaceholder(),
263
+ content(3, g.left),
264
+ content(4, g.right),
265
+ ...footers(g, { start: 5, boxed: false })
266
+ ]
267
+ };
268
+ }
269
+ function layouts(g) {
270
+ const body = placeholder({
271
+ id: 3,
272
+ name: 'Content Placeholder 2',
273
+ ph: { idx: 1 },
274
+ prompt: 'Click to edit Master text styles'
275
+ });
276
+ return [
277
+ coverLayout(g),
278
+ {
279
+ name: 'Title and Content',
280
+ type: 'obj',
281
+ shapes: [titlePlaceholder(), body, ...footers(g, { start: 4, boxed: false })]
282
+ },
283
+ sectionLayout(g),
284
+ twoContentLayout(g),
285
+ {
286
+ name: 'Title Only',
287
+ type: 'titleOnly',
288
+ shapes: [titlePlaceholder(), ...footers(g, { start: 3, boxed: false })]
289
+ },
290
+ { name: 'Blank', type: 'blank', shapes: footers(g, { start: 2, boxed: false }) }
291
+ ];
292
+ }
293
+ function font(major) {
294
+ return `<a:latin typeface="+${major}-lt"/><a:ea typeface="+${major}-ea"/><a:cs typeface="+${major}-cs"/>`;
295
+ }
296
+ function bodyLevel(sz, i) {
297
+ const lvl = i + 1;
298
+ return `<a:lvl${lvl}pPr marL="${228600 + 457200 * i}" indent="-228600" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:lnSpc><a:spcPct val="90000"/></a:lnSpc><a:spcBef><a:spcPts val="${i === 0 ? 1000 : 500}"/></a:spcBef><a:buFont typeface="Arial"/><a:buChar char="&#8226;"/><a:defRPr sz="${sz}" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill>${font('mn')}</a:defRPr></a:lvl${lvl}pPr>`;
299
+ }
300
+ function otherLevel(lvl) {
301
+ return `<a:lvl${lvl}pPr marL="${457200 * (lvl - 1)}" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:defRPr sz="1800" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill>${font('mn')}</a:defRPr></a:lvl${lvl}pPr>`;
302
+ }
303
+ function textStyles() {
304
+ const body = [2800, 2400, 2000, 1800, 1800, 1800, 1800, 1800, 1800].map(bodyLevel).join('');
305
+ const other = [1, 2, 3, 4, 5, 6, 7, 8, 9].map(otherLevel).join('');
306
+ return `<p:txStyles><p:titleStyle><a:lvl1pPr algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1"><a:lnSpc><a:spcPct val="90000"/></a:lnSpc><a:spcBef><a:spcPct val="0"/></a:spcBef><a:buNone/><a:defRPr sz="4400" kern="1200"><a:solidFill><a:schemeClr val="tx1"/></a:solidFill>${font('mj')}</a:defRPr></a:lvl1pPr></p:titleStyle><p:bodyStyle>${body}</p:bodyStyle><p:otherStyle><a:defPPr><a:defRPr lang="en-US"/></a:defPPr>${other}</p:otherStyle></p:txStyles>`;
307
+ }
308
+ function master(g, layoutCount) {
309
+ const shapes = [
310
+ placeholder({
311
+ id: 2,
312
+ name: 'Title Placeholder 1',
313
+ ph: { type: 'title' },
314
+ box: g.title,
315
+ bodyPr: '<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0" anchor="ctr"><a:normAutofit/></a:bodyPr>',
316
+ prompt: 'Click to edit Master title style'
317
+ }),
318
+ placeholder({
319
+ id: 3,
320
+ name: 'Text Placeholder 2',
321
+ ph: { type: 'body', idx: 1 },
322
+ box: g.body,
323
+ bodyPr: '<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0"><a:normAutofit/></a:bodyPr>',
324
+ prompt: 'Click to edit Master text styles'
325
+ }),
326
+ ...footers(g, { start: 4, boxed: true })
327
+ ];
328
+ const ids = Array.from({ length: layoutCount }, (_, i) => `<p:sldLayoutId id="${2147483649 + i}" r:id="rId${i + 1}"/>`).join('');
329
+ return rootXml({
330
+ local: 'sldMaster',
331
+ attrs: '',
332
+ body: `<p:cSld><p:bg><p:bgRef idx="1001"><a:schemeClr val="bg1"/></p:bgRef></p:bg>${tree(shapes)}</p:cSld><p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/><p:sldLayoutIdLst>${ids}</p:sldLayoutIdLst>${textStyles()}`
333
+ });
334
+ }
335
+ function theme(colors, fonts) {
336
+ const scheme = Object.entries(SCHEME_NAMES)
337
+ .map(([key, tag]) => `<a:${tag}><a:srgbClr val="${isThemeColor(key) ? colors[key] : ''}"/></a:${tag}>`)
338
+ .join('');
339
+ const face = (name) => `<a:latin typeface="${escape(name)}"/><a:ea typeface=""/><a:cs typeface=""/>`;
340
+ const solid = '<a:solidFill><a:schemeClr val="phClr"/></a:solidFill>';
341
+ const line = (w) => `<a:ln w="${w}" cap="flat" cmpd="sng" algn="ctr"><a:solidFill><a:schemeClr val="phClr"/></a:solidFill><a:prstDash val="solid"/><a:miter lim="800000"/></a:ln>`;
342
+ return `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
343
+ <a:theme xmlns:a="${A}" name="QVAC"><a:themeElements><a:clrScheme name="QVAC">${scheme}</a:clrScheme><a:fontScheme name="QVAC"><a:majorFont>${face(fonts.heading)}</a:majorFont><a:minorFont>${face(fonts.body)}</a:minorFont></a:fontScheme><a:fmtScheme name="QVAC"><a:fillStyleLst>${solid}${solid}${solid}</a:fillStyleLst><a:lnStyleLst>${line(6350)}${line(12700)}${line(19050)}</a:lnStyleLst><a:effectStyleLst><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle><a:effectStyle><a:effectLst/></a:effectStyle></a:effectStyleLst><a:bgFillStyleLst>${solid}${solid}${solid}</a:bgFillStyleLst></a:fmtScheme></a:themeElements><a:objectDefaults/><a:extraClrSchemeLst/></a:theme>`;
344
+ }
345
+ function addLayouts(pkg, g) {
346
+ const all = layouts(g);
347
+ all.forEach((layout, i) => {
348
+ const name = `/ppt/slideLayouts/slideLayout${i + 1}.xml`;
349
+ const body = `<p:cSld name="${escape(layout.name)}">${tree(layout.shapes)}</p:cSld><p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>`;
350
+ pkg.add(name, xml.parse(rootXml({ local: 'sldLayout', attrs: ` type="${layout.type}" preserve="1"`, body })), TYPES.layout);
351
+ pkg.rels(name).add(REL_BASE + 'slideMaster', '/ppt/slideMasters/slideMaster1.xml');
352
+ pkg.rels('/ppt/slideMasters/slideMaster1.xml').add(REL_BASE + 'slideLayout', name);
353
+ });
354
+ return all.length;
355
+ }
356
+ function addProps(pkg, title) {
357
+ pkg.add('/ppt/presProps.xml', xml.parse(rootXml({ local: 'presentationPr', attrs: '', body: '' })), TYPES.presProps);
358
+ pkg.add('/ppt/viewProps.xml', xml.parse(rootXml({ local: 'viewPr', attrs: '', body: '<p:gridSpacing cx="76200" cy="76200"/>' })), TYPES.viewProps);
359
+ pkg.add('/ppt/tableStyles.xml', xml.parse(`<a:tblStyleLst xmlns:a="${A}" def="${TABLE_STYLE}"/>`), TYPES.tableStyles);
360
+ const dcTitle = title ? `<dc:title>${escape(title)}</dc:title>` : '';
361
+ pkg.add('/docProps/core.xml', xml.parse(`<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/">${dcTitle}</cp:coreProperties>`), TYPES.core);
362
+ pkg.add('/docProps/app.xml', xml.parse('<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"><Application>QVAC</Application></Properties>'), TYPES.app);
363
+ }
364
+ function addRelationships(pkg) {
365
+ const main = pkg.rels('/ppt/presentation.xml');
366
+ main.add(REL_BASE + 'slideMaster', '/ppt/slideMasters/slideMaster1.xml');
367
+ main.add(REL_BASE + 'theme', '/ppt/theme/theme1.xml');
368
+ main.add(REL_BASE + 'presProps', '/ppt/presProps.xml');
369
+ main.add(REL_BASE + 'viewProps', '/ppt/viewProps.xml');
370
+ main.add(REL_BASE + 'tableStyles', '/ppt/tableStyles.xml');
371
+ pkg.rels('/').add(REL_BASE + 'officeDocument', '/ppt/presentation.xml');
372
+ pkg
373
+ .rels('/')
374
+ .add('http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', '/docProps/core.xml');
375
+ pkg.rels('/').add(REL_BASE + 'extended-properties', '/docProps/app.xml');
376
+ }
377
+ export function build(pkg, opts = {}) {
378
+ const { size, colors, fonts, title } = options(opts);
379
+ const g = geometry(size);
380
+ const presentation = `<p:sldMasterIdLst><p:sldMasterId id="2147483648" r:id="rId1"/></p:sldMasterIdLst><p:sldSz cx="${size.width}" cy="${size.height}"/><p:notesSz cx="6858000" cy="9144000"/>`;
381
+ pkg.add('/ppt/presentation.xml', xml.parse(rootXml({ local: 'presentation', attrs: ' saveSubsetFonts="1"', body: presentation })), TYPES.presentation);
382
+ pkg.add('/ppt/slideMasters/slideMaster1.xml', xml.parse(master(g, layouts(g).length)), TYPES.master);
383
+ addLayouts(pkg, g);
384
+ pkg.add('/ppt/theme/theme1.xml', xml.parse(theme(colors, fonts)), TYPES.theme);
385
+ pkg.rels('/ppt/slideMasters/slideMaster1.xml').add(REL_BASE + 'theme', '/ppt/theme/theme1.xml');
386
+ addProps(pkg, title);
387
+ addRelationships(pkg);
388
+ }
389
+ export function notesTheme() {
390
+ return xml.serialize(xml.parse(theme(DEFAULT_COLORS, DEFAULT_FONTS)));
391
+ }
@@ -0,0 +1,120 @@
1
+ import type { Box } from './inherit.ts';
2
+ import type { ShapeKind } from './shapes.ts';
3
+ import type { ReadParagraph, Losses, TextInput, Style } from '../drawingml/text.ts';
4
+ import type { ChartInfo, ChartSpec } from '../drawingml/chart.ts';
5
+ export type { Box } from './inherit.ts';
6
+ export type { ShapeKind } from './shapes.ts';
7
+ export type ShapeId = number | 'title' | 'subtitle' | 'body';
8
+ export interface ShapeRef {
9
+ slide: number;
10
+ shape: ShapeId;
11
+ }
12
+ export interface CellRef extends ShapeRef {
13
+ row: number;
14
+ column: number;
15
+ }
16
+ export interface ReadOptions {
17
+ from?: number;
18
+ count?: number;
19
+ slides?: number[];
20
+ }
21
+ export interface ShapeInfo {
22
+ id: number | null;
23
+ name: string;
24
+ kind: ShapeKind;
25
+ placeholder?: string;
26
+ group?: number;
27
+ paragraphs?: ReadParagraph[];
28
+ rows?: string[][];
29
+ box?: Box;
30
+ chart?: ChartInfo;
31
+ }
32
+ export interface SlideInfo {
33
+ index: number;
34
+ layout: string | null;
35
+ shapes: ShapeInfo[];
36
+ notes?: string;
37
+ }
38
+ export interface LayoutInfo {
39
+ name: string;
40
+ type: string;
41
+ }
42
+ export interface TextResult {
43
+ paragraphs: number;
44
+ changed: boolean;
45
+ removed?: Losses;
46
+ overflow?: boolean;
47
+ fontScale?: number;
48
+ }
49
+ export interface FitOptions {
50
+ fit?: 'shrink';
51
+ }
52
+ export interface StyleOptions {
53
+ paragraph?: number;
54
+ }
55
+ export interface RunCount {
56
+ runs: number;
57
+ }
58
+ export interface AddSlideOptions {
59
+ like?: number;
60
+ layout?: string;
61
+ at?: number;
62
+ title?: TextInput;
63
+ body?: TextInput;
64
+ }
65
+ export interface AddedSlide {
66
+ index: number;
67
+ layout: string;
68
+ shapes: ShapeInfo[];
69
+ }
70
+ export interface Placement {
71
+ x?: number;
72
+ y?: number;
73
+ width?: number;
74
+ height?: number;
75
+ }
76
+ export interface PictureOptions extends Placement {
77
+ name?: string;
78
+ description?: string;
79
+ }
80
+ export interface TextBoxOptions extends Placement {
81
+ text?: TextInput;
82
+ style?: Style;
83
+ fill?: string;
84
+ name?: string;
85
+ }
86
+ export interface TableOptions extends Placement {
87
+ rows: (string | number | null)[][];
88
+ header?: boolean;
89
+ name?: string;
90
+ }
91
+ export interface ChartOptions extends Partial<ChartSpec>, Placement {
92
+ name?: string;
93
+ }
94
+ export interface PlacedShape extends Box {
95
+ id: number;
96
+ }
97
+ export interface ReplaceOptions {
98
+ stretch?: boolean;
99
+ }
100
+ export interface ReplacedPicture extends Partial<Box> {
101
+ id: number | null;
102
+ }
103
+ export interface MoveOptions {
104
+ to: number;
105
+ }
106
+ export interface Moved {
107
+ moved: boolean;
108
+ }
109
+ export interface Deleted {
110
+ deleted: number | null;
111
+ removed?: {
112
+ animations: true;
113
+ };
114
+ }
115
+ export interface Remaining {
116
+ slides: number;
117
+ }
118
+ export interface Changed {
119
+ changed: boolean;
120
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ export declare function inches(n: number): number;
2
+ export declare function points(n: number): number;
3
+ export declare function cm(n: number): number;
@@ -0,0 +1,12 @@
1
+ const EMU_PER_INCH = 914400;
2
+ const EMU_PER_POINT = 12700;
3
+ const EMU_PER_CM = 360000;
4
+ export function inches(n) {
5
+ return Math.round(n * EMU_PER_INCH);
6
+ }
7
+ export function points(n) {
8
+ return Math.round(n * EMU_PER_POINT);
9
+ }
10
+ export function cm(n) {
11
+ return Math.round(n * EMU_PER_CM);
12
+ }
@@ -0,0 +1,2 @@
1
+ export declare function encode(text: string): Uint8Array;
2
+ export declare function decode(bytes: Uint8Array): string;
@@ -0,0 +1,103 @@
1
+ const encoder = typeof TextEncoder === 'function' ? new TextEncoder() : null;
2
+ const decoder = typeof TextDecoder === 'function' ? new TextDecoder('utf-8', { ignoreBOM: true }) : null;
3
+ function codePointAt(text, i) {
4
+ const c = text.charCodeAt(i);
5
+ if (c < 0xd800 || c > 0xdfff) {
6
+ return { code: c, width: 1 };
7
+ }
8
+ const next = text.charCodeAt(i + 1);
9
+ if (c <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) {
10
+ return { code: 0x10000 + ((c - 0xd800) << 10) + (next - 0xdc00), width: 2 };
11
+ }
12
+ return { code: 0xfffd, width: 1 };
13
+ }
14
+ function writeCodePoint(out, at, c) {
15
+ if (c < 0x80) {
16
+ out[at] = c;
17
+ return 1;
18
+ }
19
+ if (c < 0x800) {
20
+ out[at] = 0xc0 | (c >> 6);
21
+ out[at + 1] = 0x80 | (c & 0x3f);
22
+ return 2;
23
+ }
24
+ if (c < 0x10000) {
25
+ out[at] = 0xe0 | (c >> 12);
26
+ out[at + 1] = 0x80 | ((c >> 6) & 0x3f);
27
+ out[at + 2] = 0x80 | (c & 0x3f);
28
+ return 3;
29
+ }
30
+ out[at] = 0xf0 | (c >> 18);
31
+ out[at + 1] = 0x80 | ((c >> 12) & 0x3f);
32
+ out[at + 2] = 0x80 | ((c >> 6) & 0x3f);
33
+ out[at + 3] = 0x80 | (c & 0x3f);
34
+ return 4;
35
+ }
36
+ export function encode(text) {
37
+ if (encoder) {
38
+ return encoder.encode(text);
39
+ }
40
+ const out = new Uint8Array(text.length * 3);
41
+ let n = 0;
42
+ for (let i = 0; i < text.length;) {
43
+ const { code, width } = codePointAt(text, i);
44
+ n += writeCodePoint(out, n, code);
45
+ i += width;
46
+ }
47
+ return out.slice(0, n);
48
+ }
49
+ function sequence(bytes, at) {
50
+ const b = bytes[at];
51
+ if (b < 0x80) {
52
+ return { code: b, next: at + 1 };
53
+ }
54
+ let need = 0;
55
+ let code = 0;
56
+ if (b >= 0xc2 && b < 0xe0) {
57
+ need = 1;
58
+ code = b & 0x1f;
59
+ }
60
+ else if (b >= 0xe0 && b < 0xf0) {
61
+ need = 2;
62
+ code = b & 0x0f;
63
+ }
64
+ else if (b >= 0xf0 && b < 0xf5) {
65
+ need = 3;
66
+ code = b & 0x07;
67
+ }
68
+ else {
69
+ return { code: 0xfffd, next: at + 1 };
70
+ }
71
+ for (let k = 1; k <= need; k++) {
72
+ const cont = bytes[at + k];
73
+ if (cont === undefined || (cont & 0xc0) !== 0x80) {
74
+ return { code: 0xfffd, next: at + k };
75
+ }
76
+ code = (code << 6) | (cont & 0x3f);
77
+ }
78
+ const overlong = (need === 2 && code < 0x800) || (need === 3 && code < 0x10000);
79
+ const invalid = (code >= 0xd800 && code <= 0xdfff) || code > 0x10ffff;
80
+ return { code: overlong || invalid ? 0xfffd : code, next: at + need + 1 };
81
+ }
82
+ export function decode(bytes) {
83
+ if (decoder) {
84
+ return decoder.decode(bytes);
85
+ }
86
+ let out = '';
87
+ let chunk = [];
88
+ for (let i = 0; i < bytes.length;) {
89
+ const { code, next } = sequence(bytes, i);
90
+ if (code >= 0x10000) {
91
+ chunk.push(0xd800 + ((code - 0x10000) >> 10), 0xdc00 + ((code - 0x10000) & 0x3ff));
92
+ }
93
+ else {
94
+ chunk.push(code);
95
+ }
96
+ if (chunk.length > 8192) {
97
+ out += String.fromCharCode(...chunk);
98
+ chunk = [];
99
+ }
100
+ i = next;
101
+ }
102
+ return out + String.fromCharCode(...chunk);
103
+ }