pretext-pdf 2.0.2 → 2.0.13

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 (100) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/dist/assets/loaders/images.d.ts.map +1 -1
  3. package/dist/assets/loaders/images.js +4 -1
  4. package/dist/assets/loaders/images.js.map +1 -1
  5. package/dist/assets/security/path-allowlist.d.ts.map +1 -1
  6. package/dist/assets/security/path-allowlist.js +10 -1
  7. package/dist/assets/security/path-allowlist.js.map +1 -1
  8. package/dist/assets/svg/resolve-content.d.ts.map +1 -1
  9. package/dist/assets/svg/resolve-content.js +4 -1
  10. package/dist/assets/svg/resolve-content.js.map +1 -1
  11. package/dist/builder.js +1 -1
  12. package/dist/builder.js.map +1 -1
  13. package/dist/compat/normalize.d.ts +13 -0
  14. package/dist/compat/normalize.d.ts.map +1 -0
  15. package/dist/compat/normalize.js +146 -0
  16. package/dist/compat/normalize.js.map +1 -0
  17. package/dist/compat/pdfmake-types.d.ts +91 -0
  18. package/dist/compat/pdfmake-types.d.ts.map +1 -0
  19. package/dist/compat/pdfmake-types.js +8 -0
  20. package/dist/compat/pdfmake-types.js.map +1 -0
  21. package/dist/compat/translate.d.ts +7 -0
  22. package/dist/compat/translate.d.ts.map +1 -0
  23. package/dist/compat/translate.js +205 -0
  24. package/dist/compat/translate.js.map +1 -0
  25. package/dist/compat.d.ts +6 -161
  26. package/dist/compat.d.ts.map +1 -1
  27. package/dist/compat.js +13 -404
  28. package/dist/compat.js.map +1 -1
  29. package/dist/fonts/bundled-paths.d.ts +13 -0
  30. package/dist/fonts/bundled-paths.d.ts.map +1 -0
  31. package/dist/fonts/bundled-paths.js +43 -0
  32. package/dist/fonts/bundled-paths.js.map +1 -0
  33. package/dist/fonts/collect-needed.d.ts +10 -0
  34. package/dist/fonts/collect-needed.d.ts.map +1 -0
  35. package/dist/fonts/collect-needed.js +85 -0
  36. package/dist/fonts/collect-needed.js.map +1 -0
  37. package/dist/fonts/collect-text.d.ts +9 -0
  38. package/dist/fonts/collect-text.d.ts.map +1 -0
  39. package/dist/fonts/collect-text.js +162 -0
  40. package/dist/fonts/collect-text.js.map +1 -0
  41. package/dist/fonts/load-bytes.d.ts +10 -0
  42. package/dist/fonts/load-bytes.d.ts.map +1 -0
  43. package/dist/fonts/load-bytes.js +56 -0
  44. package/dist/fonts/load-bytes.js.map +1 -0
  45. package/dist/fonts.d.ts +11 -10
  46. package/dist/fonts.d.ts.map +1 -1
  47. package/dist/fonts.js +17 -421
  48. package/dist/fonts.js.map +1 -1
  49. package/dist/pipeline-footnotes.d.ts +2 -2
  50. package/dist/pipeline-footnotes.d.ts.map +1 -1
  51. package/dist/pipeline-footnotes.js +5 -2
  52. package/dist/pipeline-footnotes.js.map +1 -1
  53. package/dist/pipeline.d.ts.map +1 -1
  54. package/dist/pipeline.js +9 -5
  55. package/dist/pipeline.js.map +1 -1
  56. package/dist/render-utils.d.ts +1 -7
  57. package/dist/render-utils.d.ts.map +1 -1
  58. package/dist/render-utils.js +9 -30
  59. package/dist/render-utils.js.map +1 -1
  60. package/dist/schema/document.d.ts +2115 -0
  61. package/dist/schema/document.d.ts.map +1 -0
  62. package/dist/schema/document.js +275 -0
  63. package/dist/schema/document.js.map +1 -0
  64. package/dist/schema/elements-block.d.ts +481 -0
  65. package/dist/schema/elements-block.d.ts.map +1 -0
  66. package/dist/schema/elements-block.js +155 -0
  67. package/dist/schema/elements-block.js.map +1 -0
  68. package/dist/schema/elements-media.d.ts +282 -0
  69. package/dist/schema/elements-media.d.ts.map +1 -0
  70. package/dist/schema/elements-media.js +83 -0
  71. package/dist/schema/elements-media.js.map +1 -0
  72. package/dist/schema/elements-table.d.ts +134 -0
  73. package/dist/schema/elements-table.d.ts.map +1 -0
  74. package/dist/schema/elements-table.js +60 -0
  75. package/dist/schema/elements-table.js.map +1 -0
  76. package/dist/schema/elements-text.d.ts +782 -0
  77. package/dist/schema/elements-text.d.ts.map +1 -0
  78. package/dist/schema/elements-text.js +260 -0
  79. package/dist/schema/elements-text.js.map +1 -0
  80. package/dist/schema/shared.d.ts +84 -0
  81. package/dist/schema/shared.d.ts.map +1 -0
  82. package/dist/schema/shared.js +29 -0
  83. package/dist/schema/shared.js.map +1 -0
  84. package/dist/schema.d.ts +10 -2116
  85. package/dist/schema.d.ts.map +1 -1
  86. package/dist/schema.js +10 -852
  87. package/dist/schema.js.map +1 -1
  88. package/dist/types-public/document.d.ts +99 -101
  89. package/dist/types-public/document.d.ts.map +1 -1
  90. package/dist/validate/document.d.ts.map +1 -1
  91. package/dist/validate/document.js +5 -1
  92. package/dist/validate/document.js.map +1 -1
  93. package/dist/validate/elements/media.d.ts.map +1 -1
  94. package/dist/validate/elements/media.js +14 -0
  95. package/dist/validate/elements/media.js.map +1 -1
  96. package/dist/validate/helpers.d.ts +6 -6
  97. package/dist/validate/helpers.d.ts.map +1 -1
  98. package/dist/validate/helpers.js +7 -7
  99. package/dist/validate/helpers.js.map +1 -1
  100. package/package.json +1 -1
package/dist/schema.js CHANGED
@@ -2,860 +2,18 @@
2
2
  * pretext-pdf — Machine-readable JSON Schema for PdfDocument
3
3
  *
4
4
  * Exported via the `pretext-pdf/schema` entry point. Intended for editor
5
- * tooling, MCP clients, and Smithery UI form generation. Not exhaustive —
6
- * covers the most-used fields and all element types.
5
+ * tooling, MCP clients, and Smithery UI form generation.
7
6
  *
8
7
  * Usage:
9
8
  * import { pdfDocumentSchema } from 'pretext-pdf/schema'
9
+ *
10
+ * Implementation is split across src/schema/:
11
+ * shared.ts — atomic sub-schemas (color, align, font-weight, etc.)
12
+ * elements-text.ts — paragraph, heading, list, blockquote, code, callout, rich-paragraph, toc, footnote-def
13
+ * elements-media.ts — image, svg, qr-code, barcode, chart
14
+ * elements-block.ts — spacer, hr, page-break, comment, form-field, float-group
15
+ * elements-table.ts — table
16
+ * document.ts — top-level pdfDocumentSchema (assembles all element schemas)
10
17
  */
11
- // ─── Shared sub-schemas ────────────────────────────────────────────────────────
12
- const alignSchema = { type: 'string', enum: ['left', 'center', 'right', 'justify'] };
13
- const alignNoJustify = { type: 'string', enum: ['left', 'center', 'right'] };
14
- const fontWeightSchema = { type: 'number', enum: [400, 700] };
15
- const colorSchema = { type: 'string', pattern: '^#[0-9A-Fa-f]{6}$', description: '6-digit hex color e.g. #FF0000' };
16
- const dirSchema = { type: 'string', enum: ['ltr', 'rtl', 'auto'] };
17
- const spaceSchema = { type: 'number', description: 'Space in points (pt)' };
18
- const inlineSpanSchema = {
19
- type: 'object',
20
- required: ['text'],
21
- properties: {
22
- text: { type: 'string' },
23
- dir: dirSchema,
24
- fontFamily: { type: 'string' },
25
- fontWeight: fontWeightSchema,
26
- fontStyle: { type: 'string', enum: ['normal', 'italic'] },
27
- color: colorSchema,
28
- fontSize: { type: 'number' },
29
- underline: { type: 'boolean' },
30
- strikethrough: { type: 'boolean' },
31
- url: { type: 'string' },
32
- href: { type: 'string' },
33
- verticalAlign: { type: 'string', enum: ['superscript', 'subscript'] },
34
- smallCaps: { type: 'boolean' },
35
- letterSpacing: { type: 'number' },
36
- footnoteRef: { type: 'string' },
37
- },
38
- };
39
- // ─── Element schemas ──────────────────────────────────────────────────────────
40
- const paragraphSchema = {
41
- type: 'object',
42
- required: ['type', 'text'],
43
- properties: {
44
- type: { type: 'string', const: 'paragraph' },
45
- text: { type: 'string' },
46
- dir: dirSchema,
47
- fontSize: { type: 'number' },
48
- lineHeight: { type: 'number' },
49
- fontFamily: { type: 'string' },
50
- fontWeight: fontWeightSchema,
51
- color: colorSchema,
52
- align: alignSchema,
53
- bgColor: colorSchema,
54
- spaceAfter: spaceSchema,
55
- spaceBefore: spaceSchema,
56
- keepTogether: { type: 'boolean' },
57
- underline: { type: 'boolean' },
58
- strikethrough: { type: 'boolean' },
59
- url: { type: 'string', format: 'uri' },
60
- letterSpacing: { type: 'number' },
61
- smallCaps: { type: 'boolean' },
62
- tabularNumbers: { type: 'boolean', description: 'Render digits at fixed slot width for aligned numeric columns.' },
63
- columns: { type: 'number', description: 'Number of columns for multi-column layout. Default: 1' },
64
- columnGap: { type: 'number', description: 'Gap between columns in pt. Default: 24' },
65
- hyphenate: { type: 'boolean', const: false, description: 'Set to false to disable hyphenation for this element.' },
66
- annotation: {
67
- type: 'object',
68
- required: ['contents'],
69
- properties: {
70
- contents: { type: 'string' },
71
- author: { type: 'string' },
72
- color: colorSchema,
73
- open: { type: 'boolean' },
74
- },
75
- },
76
- },
77
- };
78
- const headingSchema = {
79
- type: 'object',
80
- required: ['type', 'level', 'text'],
81
- properties: {
82
- type: { type: 'string', const: 'heading' },
83
- level: { type: 'number', enum: [1, 2, 3, 4] },
84
- text: { type: 'string' },
85
- dir: dirSchema,
86
- fontFamily: { type: 'string' },
87
- fontWeight: fontWeightSchema,
88
- fontSize: { type: 'number' },
89
- lineHeight: { type: 'number' },
90
- align: alignSchema,
91
- color: colorSchema,
92
- bgColor: colorSchema,
93
- spaceBefore: spaceSchema,
94
- spaceAfter: spaceSchema,
95
- keepTogether: { type: 'boolean' },
96
- underline: { type: 'boolean' },
97
- strikethrough: { type: 'boolean' },
98
- bookmark: { type: 'boolean', const: false },
99
- anchor: { type: 'string' },
100
- url: { type: 'string', format: 'uri' },
101
- letterSpacing: { type: 'number' },
102
- smallCaps: { type: 'boolean' },
103
- tabularNumbers: { type: 'boolean', description: 'Render digits at fixed slot width for aligned numeric columns.' },
104
- hyphenate: { type: 'boolean', const: false, description: 'Set to false to disable hyphenation for this element.' },
105
- annotation: {
106
- type: 'object',
107
- required: ['contents'],
108
- properties: {
109
- contents: { type: 'string' },
110
- author: { type: 'string' },
111
- color: colorSchema,
112
- open: { type: 'boolean' },
113
- },
114
- },
115
- },
116
- };
117
- const spacerSchema = {
118
- type: 'object',
119
- required: ['type', 'height'],
120
- properties: {
121
- type: { type: 'string', const: 'spacer' },
122
- height: { type: 'number', description: 'Height in pt' },
123
- },
124
- };
125
- const hrSchema = {
126
- type: 'object',
127
- required: ['type'],
128
- properties: {
129
- type: { type: 'string', const: 'hr' },
130
- thickness: { type: 'number' },
131
- color: colorSchema,
132
- spaceBefore: { type: 'number', description: 'Space above line in pt. Default: 12.' },
133
- spaceAfter: { type: 'number', description: 'Space below line in pt. Default: 12.' },
134
- },
135
- };
136
- const pageBreakSchema = {
137
- type: 'object',
138
- required: ['type'],
139
- properties: {
140
- type: { type: 'string', const: 'page-break' },
141
- },
142
- };
143
- const imageSchema = {
144
- type: 'object',
145
- required: ['type', 'src'],
146
- properties: {
147
- type: { type: 'string', const: 'image' },
148
- src: { type: 'string', description: 'Absolute file path or URL' },
149
- format: { type: 'string', enum: ['png', 'jpg', 'auto'] },
150
- width: { type: 'number' },
151
- height: { type: 'number' },
152
- align: alignNoJustify,
153
- spaceAfter: spaceSchema,
154
- spaceBefore: spaceSchema,
155
- float: { type: 'string', enum: ['left', 'right'] },
156
- floatText: { type: 'string' },
157
- floatWidth: { type: 'number', description: 'Image column width in pt. Default: 35% of content width.' },
158
- floatGap: { type: 'number', description: 'Gap between image and text columns in pt. Default: 12' },
159
- floatSpans: { type: 'array', items: inlineSpanSchema, description: 'Rich-text spans rendered alongside the image. Alternative to floatText.' },
160
- floatFontSize: { type: 'number', description: 'Font size for floatText in pt.' },
161
- floatFontFamily: { type: 'string', description: 'Font family for floatText.' },
162
- floatColor: colorSchema,
163
- },
164
- };
165
- const svgSchema = {
166
- type: 'object',
167
- required: ['type'],
168
- properties: {
169
- type: { type: 'string', const: 'svg' },
170
- svg: { type: 'string', description: 'Inline SVG markup string' },
171
- src: { type: 'string', description: 'Absolute path or https:// URL to an SVG file' },
172
- width: { type: 'number' },
173
- height: { type: 'number' },
174
- align: alignNoJustify,
175
- spaceBefore: spaceSchema,
176
- spaceAfter: spaceSchema,
177
- },
178
- };
179
- const tableSchema = {
180
- type: 'object',
181
- required: ['type', 'columns', 'rows'],
182
- properties: {
183
- type: { type: 'string', const: 'table' },
184
- columns: {
185
- type: 'array',
186
- items: {
187
- type: 'object',
188
- required: ['width'],
189
- properties: {
190
- width: { oneOf: [{ type: 'number' }, { type: 'string', description: "Fraction e.g. '2*', '*', or 'auto'" }] },
191
- align: alignNoJustify,
192
- },
193
- },
194
- },
195
- rows: {
196
- type: 'array',
197
- items: {
198
- type: 'object',
199
- required: ['cells'],
200
- properties: {
201
- cells: {
202
- type: 'array',
203
- items: {
204
- type: 'object',
205
- required: ['text'],
206
- properties: {
207
- text: { type: 'string' },
208
- align: alignNoJustify,
209
- fontWeight: fontWeightSchema,
210
- fontFamily: { type: 'string' },
211
- fontSize: { type: 'number' },
212
- color: colorSchema,
213
- bgColor: colorSchema,
214
- colspan: { type: 'number' },
215
- rowspan: { type: 'number' },
216
- dir: dirSchema,
217
- tabularNumbers: { type: 'boolean', description: 'Render digits at fixed slot width.' },
218
- },
219
- },
220
- },
221
- isHeader: { type: 'boolean' },
222
- },
223
- },
224
- },
225
- borderColor: colorSchema,
226
- borderWidth: { type: 'number' },
227
- headerBgColor: colorSchema,
228
- fontSize: { type: 'number' },
229
- cellPaddingH: { type: 'number', description: 'Horizontal cell padding in pt. Default: 8' },
230
- cellPaddingV: { type: 'number', description: 'Vertical cell padding in pt. Default: 6' },
231
- spaceAfter: spaceSchema,
232
- spaceBefore: spaceSchema,
233
- dir: dirSchema,
234
- headerRows: { type: 'number', description: 'Number of header rows (repeated on continuation pages).' },
235
- },
236
- };
237
- const listSchema = {
238
- type: 'object',
239
- required: ['type', 'style', 'items'],
240
- properties: {
241
- type: { type: 'string', const: 'list' },
242
- style: { type: 'string', enum: ['ordered', 'unordered'] },
243
- items: {
244
- type: 'array',
245
- items: {
246
- type: 'object',
247
- required: ['text'],
248
- properties: {
249
- text: { type: 'string' },
250
- dir: dirSchema,
251
- fontWeight: fontWeightSchema,
252
- items: {
253
- type: 'array',
254
- description: 'Nested list items (up to 2 levels)',
255
- items: {
256
- type: 'object',
257
- required: ['text'],
258
- properties: {
259
- text: { type: 'string' },
260
- dir: dirSchema,
261
- fontWeight: fontWeightSchema,
262
- },
263
- },
264
- },
265
- },
266
- },
267
- },
268
- marker: { type: 'string' },
269
- indent: { type: 'number' },
270
- markerWidth: { type: 'number', description: 'Width reserved for marker column in pt. Default: 20' },
271
- fontSize: { type: 'number' },
272
- lineHeight: { type: 'number' },
273
- itemSpaceAfter: { type: 'number', description: 'Space between list items in pt. Default: 4' },
274
- nestedNumberingStyle: { type: 'string', enum: ['continue', 'restart'], description: 'How nested ordered counters behave. Default: continue' },
275
- color: colorSchema,
276
- spaceAfter: spaceSchema,
277
- spaceBefore: spaceSchema,
278
- },
279
- };
280
- const blockquoteSchema = {
281
- type: 'object',
282
- required: ['type', 'text'],
283
- properties: {
284
- type: { type: 'string', const: 'blockquote' },
285
- text: { type: 'string' },
286
- dir: dirSchema,
287
- borderColor: colorSchema,
288
- borderWidth: { type: 'number' },
289
- bgColor: colorSchema,
290
- color: colorSchema,
291
- fontFamily: { type: 'string' },
292
- fontWeight: fontWeightSchema,
293
- fontStyle: { type: 'string', enum: ['normal', 'italic'] },
294
- fontSize: { type: 'number' },
295
- lineHeight: { type: 'number' },
296
- padding: { type: 'number', description: 'Shorthand for paddingH and paddingV.' },
297
- paddingH: { type: 'number', description: 'Horizontal padding inside box in pt. Default: 16' },
298
- paddingV: { type: 'number', description: 'Vertical padding inside box in pt. Default: 10' },
299
- align: alignSchema,
300
- spaceBefore: spaceSchema,
301
- spaceAfter: spaceSchema,
302
- keepTogether: { type: 'boolean' },
303
- underline: { type: 'boolean' },
304
- strikethrough: { type: 'boolean' },
305
- },
306
- };
307
- const codeSchema = {
308
- type: 'object',
309
- required: ['type', 'text', 'fontFamily'],
310
- properties: {
311
- type: { type: 'string', const: 'code' },
312
- text: { type: 'string' },
313
- fontFamily: { type: 'string', description: 'Monospace font family (must be loaded in doc.fonts)' },
314
- fontSize: { type: 'number' },
315
- lineHeight: { type: 'number' },
316
- bgColor: colorSchema,
317
- color: colorSchema,
318
- padding: { type: 'number' },
319
- spaceAfter: spaceSchema,
320
- spaceBefore: spaceSchema,
321
- keepTogether: { type: 'boolean' },
322
- language: { type: 'string', description: "e.g. 'javascript', 'typescript', 'python'" },
323
- dir: dirSchema,
324
- highlightTheme: {
325
- type: 'object',
326
- description: 'Custom syntax highlight colors (6-digit hex). Overrides default GitHub-light theme.',
327
- properties: {
328
- keyword: colorSchema,
329
- string: colorSchema,
330
- comment: colorSchema,
331
- number: colorSchema,
332
- function: colorSchema,
333
- punctuation: colorSchema,
334
- type: colorSchema,
335
- built_in: colorSchema,
336
- literal: colorSchema,
337
- },
338
- },
339
- },
340
- };
341
- const calloutSchema = {
342
- type: 'object',
343
- required: ['type', 'content'],
344
- properties: {
345
- type: { type: 'string', const: 'callout' },
346
- content: { type: 'string' },
347
- style: { type: 'string', enum: ['info', 'warning', 'tip', 'note'] },
348
- title: { type: 'string' },
349
- backgroundColor: colorSchema,
350
- borderColor: colorSchema,
351
- color: colorSchema,
352
- titleColor: colorSchema,
353
- fontFamily: { type: 'string' },
354
- fontWeight: fontWeightSchema,
355
- fontSize: { type: 'number' },
356
- lineHeight: { type: 'number' },
357
- padding: { type: 'number', description: 'Shorthand for paddingH and paddingV. Default: 12' },
358
- paddingH: { type: 'number', description: 'Horizontal padding inside box in pt. Default: 16' },
359
- paddingV: { type: 'number', description: 'Vertical padding inside box in pt. Default: 10' },
360
- spaceBefore: spaceSchema,
361
- spaceAfter: spaceSchema,
362
- keepTogether: { type: 'boolean' },
363
- dir: dirSchema,
364
- },
365
- };
366
- const richParagraphSchema = {
367
- type: 'object',
368
- required: ['type', 'spans'],
369
- properties: {
370
- type: { type: 'string', const: 'rich-paragraph' },
371
- spans: { type: 'array', items: inlineSpanSchema },
372
- dir: dirSchema,
373
- fontSize: { type: 'number' },
374
- lineHeight: { type: 'number' },
375
- align: alignSchema,
376
- bgColor: colorSchema,
377
- spaceBefore: spaceSchema,
378
- spaceAfter: spaceSchema,
379
- keepTogether: { type: 'boolean' },
380
- letterSpacing: { type: 'number' },
381
- smallCaps: { type: 'boolean' },
382
- tabularNumbers: { type: 'boolean', description: 'Render digits at fixed slot width for aligned numeric columns.' },
383
- columns: { type: 'number', description: 'Number of columns for multi-column layout. Default: 1' },
384
- columnGap: { type: 'number', description: 'Gap between columns in pt. Default: 24' },
385
- },
386
- };
387
- const tocSchema = {
388
- type: 'object',
389
- required: ['type'],
390
- properties: {
391
- type: { type: 'string', const: 'toc' },
392
- title: { type: 'string' },
393
- showTitle: { type: 'boolean' },
394
- minLevel: { type: 'number', enum: [1, 2, 3, 4] },
395
- maxLevel: { type: 'number', enum: [1, 2, 3, 4] },
396
- fontSize: { type: 'number' },
397
- titleFontSize: { type: 'number', description: 'Font size for TOC title. Default: fontSize + 4' },
398
- levelIndent: { type: 'number', description: 'Indentation per level in pt. Default: 16' },
399
- leader: { type: 'string', description: 'Leader character between entry and page number. Default: .' },
400
- entrySpacing: { type: 'number', description: 'Space after each entry line in pt. Default: 4' },
401
- fontFamily: { type: 'string' },
402
- spaceBefore: spaceSchema,
403
- spaceAfter: spaceSchema,
404
- },
405
- };
406
- const footnoteDefSchema = {
407
- type: 'object',
408
- required: ['type', 'id', 'text'],
409
- properties: {
410
- type: { type: 'string', const: 'footnote-def' },
411
- id: { type: 'string' },
412
- text: { type: 'string' },
413
- fontSize: { type: 'number' },
414
- fontFamily: { type: 'string' },
415
- spaceAfter: spaceSchema,
416
- },
417
- };
418
- const qrCodeSchema = {
419
- type: 'object',
420
- required: ['type', 'data'],
421
- properties: {
422
- type: { type: 'string', const: 'qr-code' },
423
- data: { type: 'string' },
424
- size: { type: 'number' },
425
- errorCorrectionLevel: { type: 'string', enum: ['L', 'M', 'Q', 'H'] },
426
- foreground: colorSchema,
427
- background: colorSchema,
428
- margin: { type: 'number', description: 'Quiet-zone modules around the symbol. Default: 4' },
429
- align: alignNoJustify,
430
- spaceBefore: spaceSchema,
431
- spaceAfter: spaceSchema,
432
- },
433
- };
434
- const barcodeSchema = {
435
- type: 'object',
436
- required: ['type', 'symbology', 'data'],
437
- properties: {
438
- type: { type: 'string', const: 'barcode' },
439
- symbology: { type: 'string', description: "e.g. 'code128', 'ean13', 'qrcode'" },
440
- data: { type: 'string' },
441
- width: { type: 'number' },
442
- height: { type: 'number' },
443
- includeText: { type: 'boolean' },
444
- align: alignNoJustify,
445
- spaceBefore: spaceSchema,
446
- spaceAfter: spaceSchema,
447
- },
448
- };
449
- const commentSchema = {
450
- type: 'object',
451
- required: ['type', 'contents'],
452
- properties: {
453
- type: { type: 'string', const: 'comment' },
454
- contents: { type: 'string' },
455
- author: { type: 'string' },
456
- color: colorSchema,
457
- open: { type: 'boolean' },
458
- spaceAfter: spaceSchema,
459
- },
460
- };
461
- /** Shared base properties present on every FormFieldElement variant. */
462
- const formFieldBaseProperties = {
463
- type: { type: 'string', const: 'form-field' },
464
- name: { type: 'string', description: 'Unique field name used in PDF AcroForm dictionary.' },
465
- label: { type: 'string' },
466
- width: { type: 'number' },
467
- height: { type: 'number' },
468
- fontSize: { type: 'number' },
469
- borderColor: colorSchema,
470
- backgroundColor: colorSchema,
471
- keepTogether: { type: 'boolean', description: 'If true, never break this element across pages. Default: true' },
472
- spaceAfter: spaceSchema,
473
- spaceBefore: spaceSchema,
474
- accessibilityLabel: { type: 'string', description: 'Written to the PDF /TU AcroForm annotation entry for screen-reader announcements.' },
475
- };
476
- /** Shared options array used by radio and dropdown variants. */
477
- const formFieldOptionsSchema = {
478
- type: 'array',
479
- minItems: 1,
480
- items: {
481
- type: 'object',
482
- required: ['value', 'label'],
483
- properties: {
484
- value: { type: 'string', minLength: 1 },
485
- label: { type: 'string', minLength: 1 },
486
- },
487
- additionalProperties: false,
488
- },
489
- };
490
- /**
491
- * Discriminated-union schema for form-field elements.
492
- * The `fieldType` property is the discriminant; each oneOf branch constrains
493
- * the allowed properties to the specific variant so AI agents and schema
494
- * validators get accurate narrowed feedback.
495
- */
496
- const formFieldSchema = {
497
- type: 'object',
498
- required: ['type', 'fieldType', 'name'],
499
- oneOf: [
500
- {
501
- description: 'Single-line or multi-line text input.',
502
- properties: {
503
- ...formFieldBaseProperties,
504
- fieldType: { type: 'string', const: 'text' },
505
- placeholder: { type: 'string' },
506
- defaultValue: { type: 'string' },
507
- multiline: { type: 'boolean' },
508
- maxLength: { type: 'number', minimum: 1 },
509
- },
510
- required: ['type', 'fieldType', 'name'],
511
- },
512
- {
513
- description: 'Boolean on/off checkbox.',
514
- properties: {
515
- ...formFieldBaseProperties,
516
- fieldType: { type: 'string', const: 'checkbox' },
517
- checked: { type: 'boolean', description: 'Initial checked state. Default: false.' },
518
- },
519
- required: ['type', 'fieldType', 'name'],
520
- },
521
- {
522
- description: 'Radio button group — exactly one option is selectable.',
523
- properties: {
524
- ...formFieldBaseProperties,
525
- fieldType: { type: 'string', const: 'radio' },
526
- options: formFieldOptionsSchema,
527
- defaultSelected: { type: 'string', description: 'value of the pre-selected option.' },
528
- },
529
- required: ['type', 'fieldType', 'name', 'options'],
530
- },
531
- {
532
- description: 'Dropdown / select list — exactly one option is selectable.',
533
- properties: {
534
- ...formFieldBaseProperties,
535
- fieldType: { type: 'string', const: 'dropdown' },
536
- options: formFieldOptionsSchema,
537
- defaultSelected: { type: 'string', description: 'value of the pre-selected option.' },
538
- },
539
- required: ['type', 'fieldType', 'name', 'options'],
540
- },
541
- {
542
- description: 'Clickable push-button (no value submitted).',
543
- properties: {
544
- ...formFieldBaseProperties,
545
- fieldType: { type: 'string', const: 'button' },
546
- },
547
- required: ['type', 'fieldType', 'name'],
548
- },
549
- ],
550
- };
551
- const floatGroupSchema = {
552
- type: 'object',
553
- required: ['type', 'image', 'float', 'content'],
554
- properties: {
555
- type: { type: 'string', const: 'float-group' },
556
- image: {
557
- type: 'object',
558
- required: ['src'],
559
- properties: {
560
- src: { type: 'string', description: 'Absolute file path or URL' },
561
- format: { type: 'string', enum: ['png', 'jpg', 'auto'] },
562
- height: { type: 'number' },
563
- },
564
- },
565
- float: { type: 'string', enum: ['left', 'right'] },
566
- floatWidth: { type: 'number', description: 'Image column width in pt. Default: 35% of content width.' },
567
- floatGap: { type: 'number', description: 'Gap between image and text columns in pt. Default: 12' },
568
- content: {
569
- type: 'array',
570
- description: 'Content elements rendered in the text column (paragraph, heading, rich-paragraph).',
571
- items: { type: 'object' },
572
- },
573
- spaceBefore: spaceSchema,
574
- spaceAfter: spaceSchema,
575
- },
576
- };
577
- const chartSchema = {
578
- type: 'object',
579
- required: ['type', 'spec'],
580
- properties: {
581
- type: { type: 'string', const: 'chart' },
582
- spec: { type: 'object', description: 'Vega-Lite JSON specification. Requires vega and vega-lite peer deps.' },
583
- width: { type: 'number' },
584
- height: { type: 'number' },
585
- caption: { type: 'string', description: 'Optional figure caption rendered below the chart.' },
586
- align: alignNoJustify,
587
- spaceBefore: spaceSchema,
588
- spaceAfter: spaceSchema,
589
- },
590
- };
591
- // ─── Top-level document schema ────────────────────────────────────────────────
592
- export const pdfDocumentSchema = {
593
- $schema: 'https://json-schema.org/draft/2020-12/schema',
594
- title: 'PdfDocument',
595
- description: 'Top-level descriptor for a pretext-pdf document.',
596
- type: 'object',
597
- required: ['content'],
598
- properties: {
599
- content: {
600
- type: 'array',
601
- description: 'Document content elements rendered top-to-bottom.',
602
- items: {
603
- oneOf: [
604
- paragraphSchema,
605
- headingSchema,
606
- spacerSchema,
607
- hrSchema,
608
- pageBreakSchema,
609
- imageSchema,
610
- svgSchema,
611
- tableSchema,
612
- listSchema,
613
- blockquoteSchema,
614
- codeSchema,
615
- calloutSchema,
616
- richParagraphSchema,
617
- tocSchema,
618
- footnoteDefSchema,
619
- qrCodeSchema,
620
- barcodeSchema,
621
- commentSchema,
622
- formFieldSchema,
623
- floatGroupSchema,
624
- chartSchema,
625
- ],
626
- },
627
- },
628
- pageSize: {
629
- description: 'Page size. Default: A4 (595×842 pt). Custom: [width, height] in pt.',
630
- oneOf: [
631
- {
632
- type: 'string',
633
- enum: ['A4', 'Letter', 'Legal', 'A3', 'A5', 'Tabloid'],
634
- },
635
- {
636
- type: 'array',
637
- items: { type: 'number' },
638
- minItems: 2,
639
- maxItems: 2,
640
- description: '[width, height] in points',
641
- },
642
- ],
643
- },
644
- margins: {
645
- type: 'object',
646
- description: 'Page margins in pt. Default: all 72pt (1 inch).',
647
- properties: {
648
- top: { type: 'number' },
649
- bottom: { type: 'number' },
650
- left: { type: 'number' },
651
- right: { type: 'number' },
652
- },
653
- },
654
- defaultFont: {
655
- type: 'string',
656
- description: 'Default font family for body text. Default: Inter',
657
- },
658
- defaultFontSize: {
659
- type: 'number',
660
- description: 'Default font size in pt. Default: 12',
661
- },
662
- defaultLineHeight: {
663
- type: 'number',
664
- description: 'Default line height in pt. Default: fontSize * 1.5',
665
- },
666
- fonts: {
667
- type: 'array',
668
- description: 'Custom fonts to load and embed.',
669
- items: {
670
- type: 'object',
671
- required: ['family', 'src'],
672
- properties: {
673
- family: { type: 'string' },
674
- weight: fontWeightSchema,
675
- style: { type: 'string', enum: ['normal', 'italic'] },
676
- src: { type: 'string', description: 'Absolute file path to a TTF/OTF font file' },
677
- },
678
- },
679
- },
680
- header: {
681
- type: 'object',
682
- description: 'Header rendered at top of every page. Supports {{pageNumber}} and {{totalPages}}.',
683
- required: ['text'],
684
- properties: {
685
- text: { type: 'string', description: 'Use {{pageNumber}} and {{totalPages}} as tokens' },
686
- fontSize: { type: 'number' },
687
- align: alignNoJustify,
688
- fontFamily: { type: 'string' },
689
- fontWeight: fontWeightSchema,
690
- color: colorSchema,
691
- },
692
- },
693
- footer: {
694
- type: 'object',
695
- description: 'Footer rendered at bottom of every page. Supports {{pageNumber}} and {{totalPages}}.',
696
- required: ['text'],
697
- properties: {
698
- text: { type: 'string', description: 'Use {{pageNumber}} and {{totalPages}} as tokens' },
699
- fontSize: { type: 'number' },
700
- align: alignNoJustify,
701
- fontFamily: { type: 'string' },
702
- fontWeight: fontWeightSchema,
703
- color: colorSchema,
704
- },
705
- },
706
- sections: {
707
- type: 'array',
708
- description: 'Page-range overrides for header/footer. First matching section wins. Falls back to doc.header/footer.',
709
- items: {
710
- type: 'object',
711
- properties: {
712
- fromPage: { type: 'number', description: 'First page (1-based, inclusive). Default: 1' },
713
- toPage: { type: 'number', description: 'Last page (1-based, inclusive). Default: Infinity' },
714
- header: {
715
- type: 'object',
716
- properties: {
717
- text: { type: 'string' },
718
- fontSize: { type: 'number' },
719
- align: alignNoJustify,
720
- fontFamily: { type: 'string' },
721
- fontWeight: fontWeightSchema,
722
- color: colorSchema,
723
- },
724
- },
725
- footer: {
726
- type: 'object',
727
- properties: {
728
- text: { type: 'string' },
729
- fontSize: { type: 'number' },
730
- align: alignNoJustify,
731
- fontFamily: { type: 'string' },
732
- fontWeight: fontWeightSchema,
733
- color: colorSchema,
734
- },
735
- },
736
- },
737
- },
738
- },
739
- watermark: {
740
- type: 'object',
741
- description: 'Watermark overlay rendered on every page behind content.',
742
- properties: {
743
- text: { type: 'string' },
744
- fontFamily: { type: 'string' },
745
- fontWeight: fontWeightSchema,
746
- fontSize: { type: 'number' },
747
- color: colorSchema,
748
- opacity: { type: 'number', minimum: 0, maximum: 1 },
749
- rotation: { type: 'number', description: 'Rotation in degrees (counter-clockwise). Default: -45' },
750
- },
751
- },
752
- encryption: {
753
- type: 'object',
754
- description: 'Password protection and permission control for the output PDF.',
755
- properties: {
756
- userPassword: { type: 'string', description: 'Password required to open the document.' },
757
- ownerPassword: { type: 'string', description: 'Password for full unrestricted access.' },
758
- permissions: {
759
- type: 'object',
760
- properties: {
761
- printing: { type: 'boolean' },
762
- copying: { type: 'boolean' },
763
- modifying: { type: 'boolean' },
764
- annotating: { type: 'boolean' },
765
- },
766
- },
767
- },
768
- },
769
- metadata: {
770
- type: 'object',
771
- description: 'PDF document metadata written into file properties.',
772
- properties: {
773
- title: { type: 'string' },
774
- author: { type: 'string' },
775
- subject: { type: 'string' },
776
- keywords: { type: 'array', items: { type: 'string' } },
777
- creator: { type: 'string' },
778
- language: { type: 'string', description: "BCP47 language tag e.g. 'en-US', 'hi', 'ar'" },
779
- producer: { type: 'string' },
780
- accessibility: { type: 'object', description: 'Reserved for PDF/UA and WCAG accessibility metadata (v1.8+). No render-time effect in v1.x.' },
781
- semantic: { type: 'object', description: 'Reserved for semantic document structure metadata (v1.8+). No render-time effect in v1.x.' },
782
- },
783
- },
784
- defaultParagraphStyle: {
785
- type: 'object',
786
- description: 'Default style applied to every paragraph and heading that does not set the field explicitly.',
787
- properties: {
788
- fontSize: { type: 'number' },
789
- lineHeight: { type: 'number' },
790
- fontFamily: { type: 'string' },
791
- fontWeight: fontWeightSchema,
792
- color: colorSchema,
793
- align: alignSchema,
794
- letterSpacing: { type: 'number' },
795
- spaceBefore: spaceSchema,
796
- spaceAfter: spaceSchema,
797
- },
798
- },
799
- bookmarks: {
800
- description: 'PDF bookmark outline. Set to false to disable, or provide config object.',
801
- oneOf: [
802
- { type: 'boolean', const: false },
803
- {
804
- type: 'object',
805
- properties: {
806
- minLevel: { type: 'number', enum: [1, 2, 3, 4] },
807
- maxLevel: { type: 'number', enum: [1, 2, 3, 4] },
808
- },
809
- },
810
- ],
811
- },
812
- hyphenation: {
813
- type: 'object',
814
- description: 'Automatic word hyphenation. Requires installing the matching hyphenation.XX npm package.',
815
- required: ['language'],
816
- properties: {
817
- language: { type: 'string', description: "Language code e.g. 'en-us', 'de', 'fr'" },
818
- minWordLength: { type: 'number' },
819
- leftMin: { type: 'number' },
820
- rightMin: { type: 'number' },
821
- },
822
- },
823
- signature: {
824
- type: 'object',
825
- description: 'Signature applied to the rendered PDF. Providing p12 enables PKCS#7 cryptographic signing (requires @signpdf/* peer deps); without p12 a visual-only placeholder box is drawn.',
826
- properties: {
827
- p12: { type: 'string', description: 'Absolute path to a .p12/.pfx certificate file, or base64-encoded cert bytes. Triggers PKCS#7/CMS digital signing. Requires @signpdf/signpdf, @signpdf/placeholder-pdf-lib, @signpdf/signer-p12, and pdf-lib peer deps.' },
828
- passphrase: { type: 'string', description: 'Passphrase to decrypt the P12 certificate. Omit if the certificate has no passphrase.' },
829
- contactInfo: { type: 'string', description: 'Contact info (e.g. email address) embedded in the PDF signature dictionary. Default: empty string.' },
830
- signerName: { type: 'string' },
831
- reason: { type: 'string' },
832
- location: { type: 'string' },
833
- x: { type: 'number' },
834
- y: { type: 'number' },
835
- width: { type: 'number' },
836
- height: { type: 'number' },
837
- page: { type: 'number', description: 'Page index (0-based). Default: last page.' },
838
- borderColor: colorSchema,
839
- fontSize: { type: 'number' },
840
- invisible: { type: 'boolean', description: 'If true, skip the visual signature box — crypto-only invisible signing. Default: false.' },
841
- },
842
- },
843
- flattenForms: {
844
- type: 'boolean',
845
- description: 'If true, flatten all form fields into static content. Default: false',
846
- },
847
- allowedFileDirs: {
848
- type: 'array',
849
- items: { type: 'string' },
850
- description: 'Restrict filesystem access to these absolute directory paths.',
851
- },
852
- },
853
- // additionalProperties: false on the root object catches unknown top-level keys
854
- // in AI-agent and MCP code-generation contexts, where an LLM might hallucinate
855
- // a property that doesn't exist. Element schemas (content items) are intentionally
856
- // not locked down here — they use runtime validation in validate/index.ts which
857
- // produces precise per-property VALIDATION_ERROR messages for better DX than
858
- // JSON Schema's generic "additional property" error.
859
- additionalProperties: false,
860
- };
18
+ export { pdfDocumentSchema } from './schema/document.js';
861
19
  //# sourceMappingURL=schema.js.map