pretext-pdf 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +57 -0
- package/README.md +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fonts.js.map +1 -1
- package/dist/schema.d.ts +1597 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +723 -0
- package/dist/schema.js.map +1 -0
- package/dist/types-public.d.ts +2 -1
- package/dist/types-public.d.ts.map +1 -1
- package/dist/validate.d.ts +3 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +13 -8
- package/dist/validate.js.map +1 -1
- package/package.json +7 -3
package/dist/schema.js
ADDED
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pretext-pdf — Machine-readable JSON Schema for PdfDocument
|
|
3
|
+
*
|
|
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.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* import { pdfDocumentSchema } from 'pretext-pdf/schema'
|
|
10
|
+
*/
|
|
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
|
+
fontFamily: { type: 'string' },
|
|
24
|
+
fontWeight: fontWeightSchema,
|
|
25
|
+
fontStyle: { type: 'string', enum: ['normal', 'italic'] },
|
|
26
|
+
color: colorSchema,
|
|
27
|
+
fontSize: { type: 'number' },
|
|
28
|
+
underline: { type: 'boolean' },
|
|
29
|
+
strikethrough: { type: 'boolean' },
|
|
30
|
+
url: { type: 'string' },
|
|
31
|
+
href: { type: 'string' },
|
|
32
|
+
verticalAlign: { type: 'string', enum: ['superscript', 'subscript'] },
|
|
33
|
+
smallCaps: { type: 'boolean' },
|
|
34
|
+
letterSpacing: { type: 'number' },
|
|
35
|
+
footnoteRef: { type: 'string' },
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
// ─── Element schemas ──────────────────────────────────────────────────────────
|
|
39
|
+
const paragraphSchema = {
|
|
40
|
+
type: 'object',
|
|
41
|
+
required: ['type', 'text'],
|
|
42
|
+
properties: {
|
|
43
|
+
type: { type: 'string', const: 'paragraph' },
|
|
44
|
+
text: { type: 'string' },
|
|
45
|
+
dir: dirSchema,
|
|
46
|
+
fontSize: { type: 'number' },
|
|
47
|
+
lineHeight: { type: 'number' },
|
|
48
|
+
fontFamily: { type: 'string' },
|
|
49
|
+
fontWeight: fontWeightSchema,
|
|
50
|
+
color: colorSchema,
|
|
51
|
+
align: alignSchema,
|
|
52
|
+
bgColor: colorSchema,
|
|
53
|
+
spaceAfter: spaceSchema,
|
|
54
|
+
spaceBefore: spaceSchema,
|
|
55
|
+
keepTogether: { type: 'boolean' },
|
|
56
|
+
underline: { type: 'boolean' },
|
|
57
|
+
strikethrough: { type: 'boolean' },
|
|
58
|
+
url: { type: 'string', format: 'uri' },
|
|
59
|
+
letterSpacing: { type: 'number' },
|
|
60
|
+
smallCaps: { type: 'boolean' },
|
|
61
|
+
annotation: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
required: ['contents'],
|
|
64
|
+
properties: {
|
|
65
|
+
contents: { type: 'string' },
|
|
66
|
+
author: { type: 'string' },
|
|
67
|
+
color: colorSchema,
|
|
68
|
+
open: { type: 'boolean' },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
const headingSchema = {
|
|
74
|
+
type: 'object',
|
|
75
|
+
required: ['type', 'level', 'text'],
|
|
76
|
+
properties: {
|
|
77
|
+
type: { type: 'string', const: 'heading' },
|
|
78
|
+
level: { type: 'number', enum: [1, 2, 3, 4] },
|
|
79
|
+
text: { type: 'string' },
|
|
80
|
+
dir: dirSchema,
|
|
81
|
+
fontFamily: { type: 'string' },
|
|
82
|
+
fontWeight: fontWeightSchema,
|
|
83
|
+
fontSize: { type: 'number' },
|
|
84
|
+
lineHeight: { type: 'number' },
|
|
85
|
+
align: alignSchema,
|
|
86
|
+
color: colorSchema,
|
|
87
|
+
bgColor: colorSchema,
|
|
88
|
+
spaceBefore: spaceSchema,
|
|
89
|
+
spaceAfter: spaceSchema,
|
|
90
|
+
keepTogether: { type: 'boolean' },
|
|
91
|
+
underline: { type: 'boolean' },
|
|
92
|
+
strikethrough: { type: 'boolean' },
|
|
93
|
+
bookmark: { type: 'boolean', const: false },
|
|
94
|
+
anchor: { type: 'string' },
|
|
95
|
+
url: { type: 'string', format: 'uri' },
|
|
96
|
+
letterSpacing: { type: 'number' },
|
|
97
|
+
smallCaps: { type: 'boolean' },
|
|
98
|
+
annotation: {
|
|
99
|
+
type: 'object',
|
|
100
|
+
required: ['contents'],
|
|
101
|
+
properties: {
|
|
102
|
+
contents: { type: 'string' },
|
|
103
|
+
author: { type: 'string' },
|
|
104
|
+
color: colorSchema,
|
|
105
|
+
open: { type: 'boolean' },
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
const spacerSchema = {
|
|
111
|
+
type: 'object',
|
|
112
|
+
required: ['type', 'height'],
|
|
113
|
+
properties: {
|
|
114
|
+
type: { type: 'string', const: 'spacer' },
|
|
115
|
+
height: { type: 'number', description: 'Height in pt' },
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
const hrSchema = {
|
|
119
|
+
type: 'object',
|
|
120
|
+
required: ['type'],
|
|
121
|
+
properties: {
|
|
122
|
+
type: { type: 'string', const: 'hr' },
|
|
123
|
+
thickness: { type: 'number' },
|
|
124
|
+
color: colorSchema,
|
|
125
|
+
spaceAbove: { type: 'number', description: 'Space above line in pt. Default: 12. Primary field.' },
|
|
126
|
+
spaceBelow: { type: 'number', description: 'Space below line in pt. Default: 12. Primary field.' },
|
|
127
|
+
spaceBefore: { type: 'number', description: 'Alias for spaceAbove (primary).' },
|
|
128
|
+
spaceAfter: { type: 'number', description: 'Alias for spaceBelow (primary).' },
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
const pageBreakSchema = {
|
|
132
|
+
type: 'object',
|
|
133
|
+
required: ['type'],
|
|
134
|
+
properties: {
|
|
135
|
+
type: { type: 'string', const: 'page-break' },
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
const imageSchema = {
|
|
139
|
+
type: 'object',
|
|
140
|
+
required: ['type', 'src'],
|
|
141
|
+
properties: {
|
|
142
|
+
type: { type: 'string', const: 'image' },
|
|
143
|
+
src: { type: 'string', description: 'Absolute file path or URL' },
|
|
144
|
+
format: { type: 'string', enum: ['png', 'jpg', 'auto'] },
|
|
145
|
+
width: { type: 'number' },
|
|
146
|
+
height: { type: 'number' },
|
|
147
|
+
align: alignNoJustify,
|
|
148
|
+
spaceAfter: spaceSchema,
|
|
149
|
+
spaceBefore: spaceSchema,
|
|
150
|
+
float: { type: 'string', enum: ['left', 'right'] },
|
|
151
|
+
floatText: { type: 'string' },
|
|
152
|
+
floatWidth: { type: 'number', description: 'Image column width in pt. Default: 35% of content width.' },
|
|
153
|
+
floatGap: { type: 'number', description: 'Gap between image and text columns in pt. Default: 12' },
|
|
154
|
+
floatSpans: { type: 'array', items: inlineSpanSchema, description: 'Rich-text spans rendered alongside the image. Alternative to floatText.' },
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
const svgSchema = {
|
|
158
|
+
type: 'object',
|
|
159
|
+
required: ['type'],
|
|
160
|
+
properties: {
|
|
161
|
+
type: { type: 'string', const: 'svg' },
|
|
162
|
+
svg: { type: 'string', description: 'Inline SVG markup string' },
|
|
163
|
+
src: { type: 'string', description: 'Absolute path or https:// URL to an SVG file' },
|
|
164
|
+
width: { type: 'number' },
|
|
165
|
+
height: { type: 'number' },
|
|
166
|
+
align: alignNoJustify,
|
|
167
|
+
spaceBefore: spaceSchema,
|
|
168
|
+
spaceAfter: spaceSchema,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
const tableSchema = {
|
|
172
|
+
type: 'object',
|
|
173
|
+
required: ['type', 'columns', 'rows'],
|
|
174
|
+
properties: {
|
|
175
|
+
type: { type: 'string', const: 'table' },
|
|
176
|
+
columns: {
|
|
177
|
+
type: 'array',
|
|
178
|
+
items: {
|
|
179
|
+
type: 'object',
|
|
180
|
+
required: ['width'],
|
|
181
|
+
properties: {
|
|
182
|
+
width: { oneOf: [{ type: 'number' }, { type: 'string', description: "Fraction e.g. '2*', '*', or 'auto'" }] },
|
|
183
|
+
align: alignNoJustify,
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
rows: {
|
|
188
|
+
type: 'array',
|
|
189
|
+
items: {
|
|
190
|
+
type: 'object',
|
|
191
|
+
required: ['cells'],
|
|
192
|
+
properties: {
|
|
193
|
+
cells: {
|
|
194
|
+
type: 'array',
|
|
195
|
+
items: {
|
|
196
|
+
type: 'object',
|
|
197
|
+
required: ['text'],
|
|
198
|
+
properties: {
|
|
199
|
+
text: { type: 'string' },
|
|
200
|
+
align: alignNoJustify,
|
|
201
|
+
fontWeight: fontWeightSchema,
|
|
202
|
+
color: colorSchema,
|
|
203
|
+
bgColor: colorSchema,
|
|
204
|
+
colspan: { type: 'number' },
|
|
205
|
+
rowspan: { type: 'number' },
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
isHeader: { type: 'boolean' },
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
borderColor: colorSchema,
|
|
214
|
+
borderWidth: { type: 'number' },
|
|
215
|
+
headerBgColor: colorSchema,
|
|
216
|
+
fontSize: { type: 'number' },
|
|
217
|
+
cellPaddingH: { type: 'number', description: 'Horizontal cell padding in pt. Default: 8' },
|
|
218
|
+
cellPaddingV: { type: 'number', description: 'Vertical cell padding in pt. Default: 6' },
|
|
219
|
+
spaceAfter: spaceSchema,
|
|
220
|
+
spaceBefore: spaceSchema,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
const listSchema = {
|
|
224
|
+
type: 'object',
|
|
225
|
+
required: ['type', 'style', 'items'],
|
|
226
|
+
properties: {
|
|
227
|
+
type: { type: 'string', const: 'list' },
|
|
228
|
+
style: { type: 'string', enum: ['ordered', 'unordered'] },
|
|
229
|
+
items: {
|
|
230
|
+
type: 'array',
|
|
231
|
+
items: {
|
|
232
|
+
type: 'object',
|
|
233
|
+
required: ['text'],
|
|
234
|
+
properties: {
|
|
235
|
+
text: { type: 'string' },
|
|
236
|
+
fontWeight: fontWeightSchema,
|
|
237
|
+
items: { type: 'array', description: 'Nested list items (up to 2 levels)' },
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
marker: { type: 'string' },
|
|
242
|
+
indent: { type: 'number' },
|
|
243
|
+
fontSize: { type: 'number' },
|
|
244
|
+
color: colorSchema,
|
|
245
|
+
spaceAfter: spaceSchema,
|
|
246
|
+
spaceBefore: spaceSchema,
|
|
247
|
+
},
|
|
248
|
+
};
|
|
249
|
+
const blockquoteSchema = {
|
|
250
|
+
type: 'object',
|
|
251
|
+
required: ['type', 'text'],
|
|
252
|
+
properties: {
|
|
253
|
+
type: { type: 'string', const: 'blockquote' },
|
|
254
|
+
text: { type: 'string' },
|
|
255
|
+
dir: dirSchema,
|
|
256
|
+
borderColor: colorSchema,
|
|
257
|
+
borderWidth: { type: 'number' },
|
|
258
|
+
bgColor: colorSchema,
|
|
259
|
+
color: colorSchema,
|
|
260
|
+
fontFamily: { type: 'string' },
|
|
261
|
+
fontWeight: fontWeightSchema,
|
|
262
|
+
fontStyle: { type: 'string', enum: ['normal', 'italic'] },
|
|
263
|
+
fontSize: { type: 'number' },
|
|
264
|
+
align: alignSchema,
|
|
265
|
+
spaceBefore: spaceSchema,
|
|
266
|
+
spaceAfter: spaceSchema,
|
|
267
|
+
keepTogether: { type: 'boolean' },
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
const codeSchema = {
|
|
271
|
+
type: 'object',
|
|
272
|
+
required: ['type', 'text', 'fontFamily'],
|
|
273
|
+
properties: {
|
|
274
|
+
type: { type: 'string', const: 'code' },
|
|
275
|
+
text: { type: 'string' },
|
|
276
|
+
fontFamily: { type: 'string', description: 'Monospace font family (must be loaded in doc.fonts)' },
|
|
277
|
+
fontSize: { type: 'number' },
|
|
278
|
+
lineHeight: { type: 'number' },
|
|
279
|
+
bgColor: colorSchema,
|
|
280
|
+
color: colorSchema,
|
|
281
|
+
padding: { type: 'number' },
|
|
282
|
+
spaceAfter: spaceSchema,
|
|
283
|
+
spaceBefore: spaceSchema,
|
|
284
|
+
keepTogether: { type: 'boolean' },
|
|
285
|
+
language: { type: 'string', description: "e.g. 'javascript', 'typescript', 'python'" },
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
const calloutSchema = {
|
|
289
|
+
type: 'object',
|
|
290
|
+
required: ['type', 'content'],
|
|
291
|
+
properties: {
|
|
292
|
+
type: { type: 'string', const: 'callout' },
|
|
293
|
+
content: { type: 'string' },
|
|
294
|
+
style: { type: 'string', enum: ['info', 'warning', 'tip', 'note'] },
|
|
295
|
+
title: { type: 'string' },
|
|
296
|
+
backgroundColor: colorSchema,
|
|
297
|
+
borderColor: colorSchema,
|
|
298
|
+
color: colorSchema,
|
|
299
|
+
fontFamily: { type: 'string' },
|
|
300
|
+
fontSize: { type: 'number' },
|
|
301
|
+
spaceBefore: spaceSchema,
|
|
302
|
+
spaceAfter: spaceSchema,
|
|
303
|
+
keepTogether: { type: 'boolean' },
|
|
304
|
+
dir: dirSchema,
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
const richParagraphSchema = {
|
|
308
|
+
type: 'object',
|
|
309
|
+
required: ['type', 'spans'],
|
|
310
|
+
properties: {
|
|
311
|
+
type: { type: 'string', const: 'rich-paragraph' },
|
|
312
|
+
spans: { type: 'array', items: inlineSpanSchema },
|
|
313
|
+
dir: dirSchema,
|
|
314
|
+
fontSize: { type: 'number' },
|
|
315
|
+
lineHeight: { type: 'number' },
|
|
316
|
+
align: alignSchema,
|
|
317
|
+
bgColor: colorSchema,
|
|
318
|
+
spaceBefore: spaceSchema,
|
|
319
|
+
spaceAfter: spaceSchema,
|
|
320
|
+
keepTogether: { type: 'boolean' },
|
|
321
|
+
letterSpacing: { type: 'number' },
|
|
322
|
+
smallCaps: { type: 'boolean' },
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
const tocSchema = {
|
|
326
|
+
type: 'object',
|
|
327
|
+
required: ['type'],
|
|
328
|
+
properties: {
|
|
329
|
+
type: { type: 'string', const: 'toc' },
|
|
330
|
+
title: { type: 'string' },
|
|
331
|
+
showTitle: { type: 'boolean' },
|
|
332
|
+
minLevel: { type: 'number', enum: [1, 2, 3, 4] },
|
|
333
|
+
maxLevel: { type: 'number', enum: [1, 2, 3, 4] },
|
|
334
|
+
fontSize: { type: 'number' },
|
|
335
|
+
fontFamily: { type: 'string' },
|
|
336
|
+
spaceBefore: spaceSchema,
|
|
337
|
+
spaceAfter: spaceSchema,
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
const footnoteDefSchema = {
|
|
341
|
+
type: 'object',
|
|
342
|
+
required: ['type', 'id', 'text'],
|
|
343
|
+
properties: {
|
|
344
|
+
type: { type: 'string', const: 'footnote-def' },
|
|
345
|
+
id: { type: 'string' },
|
|
346
|
+
text: { type: 'string' },
|
|
347
|
+
fontSize: { type: 'number' },
|
|
348
|
+
fontFamily: { type: 'string' },
|
|
349
|
+
spaceAfter: spaceSchema,
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
const qrCodeSchema = {
|
|
353
|
+
type: 'object',
|
|
354
|
+
required: ['type', 'data'],
|
|
355
|
+
properties: {
|
|
356
|
+
type: { type: 'string', const: 'qr-code' },
|
|
357
|
+
data: { type: 'string' },
|
|
358
|
+
size: { type: 'number' },
|
|
359
|
+
errorCorrectionLevel: { type: 'string', enum: ['L', 'M', 'Q', 'H'] },
|
|
360
|
+
foreground: colorSchema,
|
|
361
|
+
background: colorSchema,
|
|
362
|
+
align: alignNoJustify,
|
|
363
|
+
spaceBefore: spaceSchema,
|
|
364
|
+
spaceAfter: spaceSchema,
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
const barcodeSchema = {
|
|
368
|
+
type: 'object',
|
|
369
|
+
required: ['type', 'symbology', 'data'],
|
|
370
|
+
properties: {
|
|
371
|
+
type: { type: 'string', const: 'barcode' },
|
|
372
|
+
symbology: { type: 'string', description: "e.g. 'code128', 'ean13', 'qrcode'" },
|
|
373
|
+
data: { type: 'string' },
|
|
374
|
+
width: { type: 'number' },
|
|
375
|
+
height: { type: 'number' },
|
|
376
|
+
includeText: { type: 'boolean' },
|
|
377
|
+
align: alignNoJustify,
|
|
378
|
+
spaceBefore: spaceSchema,
|
|
379
|
+
spaceAfter: spaceSchema,
|
|
380
|
+
},
|
|
381
|
+
};
|
|
382
|
+
const commentSchema = {
|
|
383
|
+
type: 'object',
|
|
384
|
+
required: ['type', 'contents'],
|
|
385
|
+
properties: {
|
|
386
|
+
type: { type: 'string', const: 'comment' },
|
|
387
|
+
contents: { type: 'string' },
|
|
388
|
+
author: { type: 'string' },
|
|
389
|
+
color: colorSchema,
|
|
390
|
+
open: { type: 'boolean' },
|
|
391
|
+
spaceAfter: spaceSchema,
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
const formFieldSchema = {
|
|
395
|
+
type: 'object',
|
|
396
|
+
required: ['type', 'fieldType', 'name'],
|
|
397
|
+
properties: {
|
|
398
|
+
type: { type: 'string', const: 'form-field' },
|
|
399
|
+
fieldType: { type: 'string', enum: ['text', 'checkbox', 'radio', 'dropdown', 'button'] },
|
|
400
|
+
name: { type: 'string' },
|
|
401
|
+
label: { type: 'string' },
|
|
402
|
+
placeholder: { type: 'string' },
|
|
403
|
+
defaultValue: { type: 'string' },
|
|
404
|
+
multiline: { type: 'boolean' },
|
|
405
|
+
maxLength: { type: 'number' },
|
|
406
|
+
checked: { type: 'boolean' },
|
|
407
|
+
options: {
|
|
408
|
+
type: 'array',
|
|
409
|
+
items: {
|
|
410
|
+
type: 'object',
|
|
411
|
+
required: ['value', 'label'],
|
|
412
|
+
properties: {
|
|
413
|
+
value: { type: 'string' },
|
|
414
|
+
label: { type: 'string' },
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
width: { type: 'number' },
|
|
419
|
+
height: { type: 'number' },
|
|
420
|
+
fontSize: { type: 'number' },
|
|
421
|
+
spaceAfter: spaceSchema,
|
|
422
|
+
spaceBefore: spaceSchema,
|
|
423
|
+
},
|
|
424
|
+
};
|
|
425
|
+
const floatGroupSchema = {
|
|
426
|
+
type: 'object',
|
|
427
|
+
required: ['type', 'image', 'float', 'content'],
|
|
428
|
+
properties: {
|
|
429
|
+
type: { type: 'string', const: 'float-group' },
|
|
430
|
+
image: {
|
|
431
|
+
type: 'object',
|
|
432
|
+
required: ['src'],
|
|
433
|
+
properties: {
|
|
434
|
+
src: { type: 'string', description: 'Absolute file path or URL' },
|
|
435
|
+
format: { type: 'string', enum: ['png', 'jpg', 'auto'] },
|
|
436
|
+
height: { type: 'number' },
|
|
437
|
+
},
|
|
438
|
+
},
|
|
439
|
+
float: { type: 'string', enum: ['left', 'right'] },
|
|
440
|
+
floatWidth: { type: 'number', description: 'Image column width in pt. Default: 35% of content width.' },
|
|
441
|
+
floatGap: { type: 'number', description: 'Gap between image and text columns in pt. Default: 12' },
|
|
442
|
+
content: {
|
|
443
|
+
type: 'array',
|
|
444
|
+
description: 'Content elements rendered in the text column (paragraph, heading, rich-paragraph).',
|
|
445
|
+
items: { type: 'object' },
|
|
446
|
+
},
|
|
447
|
+
spaceBefore: spaceSchema,
|
|
448
|
+
spaceAfter: spaceSchema,
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
const chartSchema = {
|
|
452
|
+
type: 'object',
|
|
453
|
+
required: ['type', 'spec'],
|
|
454
|
+
properties: {
|
|
455
|
+
type: { type: 'string', const: 'chart' },
|
|
456
|
+
spec: { type: 'object', description: 'Vega-Lite JSON specification. Requires vega and vega-lite peer deps.' },
|
|
457
|
+
width: { type: 'number' },
|
|
458
|
+
height: { type: 'number' },
|
|
459
|
+
caption: { type: 'string', description: 'Optional figure caption rendered below the chart.' },
|
|
460
|
+
align: alignNoJustify,
|
|
461
|
+
spaceBefore: spaceSchema,
|
|
462
|
+
spaceAfter: spaceSchema,
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
// ─── Top-level document schema ────────────────────────────────────────────────
|
|
466
|
+
export const pdfDocumentSchema = {
|
|
467
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
468
|
+
title: 'PdfDocument',
|
|
469
|
+
description: 'Top-level descriptor for a pretext-pdf document.',
|
|
470
|
+
type: 'object',
|
|
471
|
+
required: ['content'],
|
|
472
|
+
properties: {
|
|
473
|
+
content: {
|
|
474
|
+
type: 'array',
|
|
475
|
+
description: 'Document content elements rendered top-to-bottom.',
|
|
476
|
+
items: {
|
|
477
|
+
anyOf: [
|
|
478
|
+
paragraphSchema,
|
|
479
|
+
headingSchema,
|
|
480
|
+
spacerSchema,
|
|
481
|
+
hrSchema,
|
|
482
|
+
pageBreakSchema,
|
|
483
|
+
imageSchema,
|
|
484
|
+
svgSchema,
|
|
485
|
+
tableSchema,
|
|
486
|
+
listSchema,
|
|
487
|
+
blockquoteSchema,
|
|
488
|
+
codeSchema,
|
|
489
|
+
calloutSchema,
|
|
490
|
+
richParagraphSchema,
|
|
491
|
+
tocSchema,
|
|
492
|
+
footnoteDefSchema,
|
|
493
|
+
qrCodeSchema,
|
|
494
|
+
barcodeSchema,
|
|
495
|
+
commentSchema,
|
|
496
|
+
formFieldSchema,
|
|
497
|
+
floatGroupSchema,
|
|
498
|
+
chartSchema,
|
|
499
|
+
],
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
pageSize: {
|
|
503
|
+
description: 'Page size. Default: A4 (595×842 pt). Custom: [width, height] in pt.',
|
|
504
|
+
oneOf: [
|
|
505
|
+
{
|
|
506
|
+
type: 'string',
|
|
507
|
+
enum: ['A4', 'Letter', 'Legal', 'A3', 'A5', 'Tabloid'],
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
type: 'array',
|
|
511
|
+
items: { type: 'number' },
|
|
512
|
+
minItems: 2,
|
|
513
|
+
maxItems: 2,
|
|
514
|
+
description: '[width, height] in points',
|
|
515
|
+
},
|
|
516
|
+
],
|
|
517
|
+
},
|
|
518
|
+
margins: {
|
|
519
|
+
type: 'object',
|
|
520
|
+
description: 'Page margins in pt. Default: all 72pt (1 inch).',
|
|
521
|
+
properties: {
|
|
522
|
+
top: { type: 'number' },
|
|
523
|
+
bottom: { type: 'number' },
|
|
524
|
+
left: { type: 'number' },
|
|
525
|
+
right: { type: 'number' },
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
defaultFont: {
|
|
529
|
+
type: 'string',
|
|
530
|
+
description: 'Default font family for body text. Default: Inter',
|
|
531
|
+
},
|
|
532
|
+
defaultFontSize: {
|
|
533
|
+
type: 'number',
|
|
534
|
+
description: 'Default font size in pt. Default: 12',
|
|
535
|
+
},
|
|
536
|
+
defaultLineHeight: {
|
|
537
|
+
type: 'number',
|
|
538
|
+
description: 'Default line height in pt. Default: fontSize * 1.5',
|
|
539
|
+
},
|
|
540
|
+
fonts: {
|
|
541
|
+
type: 'array',
|
|
542
|
+
description: 'Custom fonts to load and embed.',
|
|
543
|
+
items: {
|
|
544
|
+
type: 'object',
|
|
545
|
+
required: ['family', 'src'],
|
|
546
|
+
properties: {
|
|
547
|
+
family: { type: 'string' },
|
|
548
|
+
weight: fontWeightSchema,
|
|
549
|
+
style: { type: 'string', enum: ['normal', 'italic'] },
|
|
550
|
+
src: { type: 'string', description: 'Absolute file path to a TTF/OTF font file' },
|
|
551
|
+
},
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
header: {
|
|
555
|
+
type: 'object',
|
|
556
|
+
description: 'Header rendered at top of every page. Supports {{pageNumber}} and {{totalPages}}.',
|
|
557
|
+
required: ['text'],
|
|
558
|
+
properties: {
|
|
559
|
+
text: { type: 'string', description: 'Use {{pageNumber}} and {{totalPages}} as tokens' },
|
|
560
|
+
fontSize: { type: 'number' },
|
|
561
|
+
align: alignNoJustify,
|
|
562
|
+
fontFamily: { type: 'string' },
|
|
563
|
+
fontWeight: fontWeightSchema,
|
|
564
|
+
color: colorSchema,
|
|
565
|
+
},
|
|
566
|
+
},
|
|
567
|
+
footer: {
|
|
568
|
+
type: 'object',
|
|
569
|
+
description: 'Footer rendered at bottom of every page. Supports {{pageNumber}} and {{totalPages}}.',
|
|
570
|
+
required: ['text'],
|
|
571
|
+
properties: {
|
|
572
|
+
text: { type: 'string', description: 'Use {{pageNumber}} and {{totalPages}} as tokens' },
|
|
573
|
+
fontSize: { type: 'number' },
|
|
574
|
+
align: alignNoJustify,
|
|
575
|
+
fontFamily: { type: 'string' },
|
|
576
|
+
fontWeight: fontWeightSchema,
|
|
577
|
+
color: colorSchema,
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
sections: {
|
|
581
|
+
type: 'array',
|
|
582
|
+
description: 'Page-range overrides for header/footer. First matching section wins. Falls back to doc.header/footer.',
|
|
583
|
+
items: {
|
|
584
|
+
type: 'object',
|
|
585
|
+
properties: {
|
|
586
|
+
fromPage: { type: 'number', description: 'First page (1-based, inclusive). Default: 1' },
|
|
587
|
+
toPage: { type: 'number', description: 'Last page (1-based, inclusive). Default: Infinity' },
|
|
588
|
+
header: {
|
|
589
|
+
type: 'object',
|
|
590
|
+
properties: {
|
|
591
|
+
text: { type: 'string' },
|
|
592
|
+
fontSize: { type: 'number' },
|
|
593
|
+
align: alignNoJustify,
|
|
594
|
+
fontFamily: { type: 'string' },
|
|
595
|
+
fontWeight: fontWeightSchema,
|
|
596
|
+
color: colorSchema,
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
footer: {
|
|
600
|
+
type: 'object',
|
|
601
|
+
properties: {
|
|
602
|
+
text: { type: 'string' },
|
|
603
|
+
fontSize: { type: 'number' },
|
|
604
|
+
align: alignNoJustify,
|
|
605
|
+
fontFamily: { type: 'string' },
|
|
606
|
+
fontWeight: fontWeightSchema,
|
|
607
|
+
color: colorSchema,
|
|
608
|
+
},
|
|
609
|
+
},
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
},
|
|
613
|
+
watermark: {
|
|
614
|
+
type: 'object',
|
|
615
|
+
description: 'Watermark overlay rendered on every page behind content.',
|
|
616
|
+
properties: {
|
|
617
|
+
text: { type: 'string' },
|
|
618
|
+
fontFamily: { type: 'string' },
|
|
619
|
+
fontWeight: fontWeightSchema,
|
|
620
|
+
fontSize: { type: 'number' },
|
|
621
|
+
color: colorSchema,
|
|
622
|
+
opacity: { type: 'number', minimum: 0, maximum: 1 },
|
|
623
|
+
rotation: { type: 'number', description: 'Rotation in degrees (counter-clockwise). Default: -45' },
|
|
624
|
+
},
|
|
625
|
+
},
|
|
626
|
+
encryption: {
|
|
627
|
+
type: 'object',
|
|
628
|
+
description: 'Password protection and permission control for the output PDF.',
|
|
629
|
+
properties: {
|
|
630
|
+
userPassword: { type: 'string', description: 'Password required to open the document.' },
|
|
631
|
+
ownerPassword: { type: 'string', description: 'Password for full unrestricted access.' },
|
|
632
|
+
permissions: {
|
|
633
|
+
type: 'object',
|
|
634
|
+
properties: {
|
|
635
|
+
printing: { type: 'boolean' },
|
|
636
|
+
copying: { type: 'boolean' },
|
|
637
|
+
modifying: { type: 'boolean' },
|
|
638
|
+
annotating: { type: 'boolean' },
|
|
639
|
+
},
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
},
|
|
643
|
+
metadata: {
|
|
644
|
+
type: 'object',
|
|
645
|
+
description: 'PDF document metadata written into file properties.',
|
|
646
|
+
properties: {
|
|
647
|
+
title: { type: 'string' },
|
|
648
|
+
author: { type: 'string' },
|
|
649
|
+
subject: { type: 'string' },
|
|
650
|
+
keywords: { type: 'array', items: { type: 'string' } },
|
|
651
|
+
creator: { type: 'string' },
|
|
652
|
+
language: { type: 'string', description: "BCP47 language tag e.g. 'en-US', 'hi', 'ar'" },
|
|
653
|
+
producer: { type: 'string' },
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
defaultParagraphStyle: {
|
|
657
|
+
type: 'object',
|
|
658
|
+
description: 'Default style applied to every paragraph and heading that does not set the field explicitly.',
|
|
659
|
+
properties: {
|
|
660
|
+
fontSize: { type: 'number' },
|
|
661
|
+
lineHeight: { type: 'number' },
|
|
662
|
+
fontFamily: { type: 'string' },
|
|
663
|
+
fontWeight: fontWeightSchema,
|
|
664
|
+
color: colorSchema,
|
|
665
|
+
align: alignSchema,
|
|
666
|
+
letterSpacing: { type: 'number' },
|
|
667
|
+
spaceBefore: spaceSchema,
|
|
668
|
+
spaceAfter: spaceSchema,
|
|
669
|
+
},
|
|
670
|
+
},
|
|
671
|
+
bookmarks: {
|
|
672
|
+
description: 'PDF bookmark outline. Set to false to disable, or provide config object.',
|
|
673
|
+
oneOf: [
|
|
674
|
+
{ type: 'boolean', const: false },
|
|
675
|
+
{
|
|
676
|
+
type: 'object',
|
|
677
|
+
properties: {
|
|
678
|
+
minLevel: { type: 'number', enum: [1, 2, 3, 4] },
|
|
679
|
+
maxLevel: { type: 'number', enum: [1, 2, 3, 4] },
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
],
|
|
683
|
+
},
|
|
684
|
+
hyphenation: {
|
|
685
|
+
type: 'object',
|
|
686
|
+
description: 'Automatic word hyphenation. Requires installing the matching hyphenation.XX npm package.',
|
|
687
|
+
required: ['language'],
|
|
688
|
+
properties: {
|
|
689
|
+
language: { type: 'string', description: "Language code e.g. 'en-us', 'de', 'fr'" },
|
|
690
|
+
minWordLength: { type: 'number' },
|
|
691
|
+
leftMin: { type: 'number' },
|
|
692
|
+
rightMin: { type: 'number' },
|
|
693
|
+
},
|
|
694
|
+
},
|
|
695
|
+
signature: {
|
|
696
|
+
type: 'object',
|
|
697
|
+
description: 'Visual signature placeholder drawn on a specified page.',
|
|
698
|
+
properties: {
|
|
699
|
+
signerName: { type: 'string' },
|
|
700
|
+
reason: { type: 'string' },
|
|
701
|
+
location: { type: 'string' },
|
|
702
|
+
x: { type: 'number' },
|
|
703
|
+
y: { type: 'number' },
|
|
704
|
+
width: { type: 'number' },
|
|
705
|
+
height: { type: 'number' },
|
|
706
|
+
page: { type: 'number', description: 'Page index (0-based). Default: last page.' },
|
|
707
|
+
borderColor: colorSchema,
|
|
708
|
+
fontSize: { type: 'number' },
|
|
709
|
+
invisible: { type: 'boolean' },
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
flattenForms: {
|
|
713
|
+
type: 'boolean',
|
|
714
|
+
description: 'If true, flatten all form fields into static content. Default: false',
|
|
715
|
+
},
|
|
716
|
+
allowedFileDirs: {
|
|
717
|
+
type: 'array',
|
|
718
|
+
items: { type: 'string' },
|
|
719
|
+
description: 'Restrict filesystem access to these absolute directory paths.',
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
};
|
|
723
|
+
//# sourceMappingURL=schema.js.map
|