@lpdfio/lpdf 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/dist/L.d.ts +7 -2
- package/dist/L.js +6 -0
- package/dist/_shared.d.ts +42 -3
- package/dist/_shared.js +52 -3
- package/dist/attrs.d.ts +733 -65
- package/dist/browser.js +126 -47
- package/dist/canvas.d.ts +13 -12
- package/dist/constants.d.ts +27 -0
- package/dist/constants.js +25 -1
- package/dist/engine.d.ts +19 -28
- package/dist/engine.js +129 -27
- package/dist/index.d.ts +6 -5
- package/dist/index.js +7 -1
- package/dist/kit.d.ts +49 -33
- package/dist/kit.js +7 -1
- package/dist/layout.d.ts +62 -19
- package/dist/layout.js +26 -0
- package/dist/markdown.d.ts +76 -0
- package/dist/markdown.js +63 -0
- package/dist/wasm/lpdf-web.js +191 -36
- package/dist/wasm/lpdf.js +197 -36
- package/dist/wasm/lpdf_bg.wasm +0 -0
- package/package.json +4 -1
package/dist/engine.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PdfEngine = exports.LpdfRenderError = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
4
5
|
const node_fs_1 = require("node:fs");
|
|
6
|
+
const _shared_1 = require("./_shared");
|
|
5
7
|
// require() path is relative to the compiled output at dist/engine.js.
|
|
6
8
|
// In the published package, wasm-pack artifacts live in dist/wasm/.
|
|
7
9
|
// In the monorepo, `npm run build` copies them there from <root>/dist/node/.
|
|
@@ -28,13 +30,18 @@ class LpdfRenderError extends Error {
|
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
exports.LpdfRenderError = LpdfRenderError;
|
|
33
|
+
/** Node's secure generator, for the entropy of AES-256. */
|
|
34
|
+
function secureRandomBytes(count) {
|
|
35
|
+
return new Uint8Array((0, node_crypto_1.randomBytes)(count));
|
|
36
|
+
}
|
|
31
37
|
class PdfEngine {
|
|
32
38
|
constructor() {
|
|
33
39
|
this._licenseKey = '';
|
|
34
40
|
this._fonts = new Map();
|
|
35
41
|
this._images = new Map();
|
|
42
|
+
this._files = new Map();
|
|
43
|
+
this._markdownStyles = new Map();
|
|
36
44
|
this._disposed = false;
|
|
37
|
-
this._encrypt = null;
|
|
38
45
|
}
|
|
39
46
|
/**
|
|
40
47
|
* Set the license key. Returns `this` for chaining.
|
|
@@ -78,21 +85,21 @@ class PdfEngine {
|
|
|
78
85
|
return this;
|
|
79
86
|
}
|
|
80
87
|
/**
|
|
81
|
-
*
|
|
82
|
-
* Returns `this` for chaining.
|
|
88
|
+
* Register the bytes of a file the document carries, for the `<file>` of its `<attachments>` whose `ref`, or with
|
|
89
|
+
* no ref whose name, is `name`. The PDF carries them as they are. Call before `render`. Returns `this` for chaining.
|
|
83
90
|
*/
|
|
84
|
-
|
|
91
|
+
loadFile(name, bytes) {
|
|
85
92
|
this._throwIfDisposed();
|
|
86
|
-
this.
|
|
93
|
+
this._files.set(name, bytes);
|
|
87
94
|
return this;
|
|
88
95
|
}
|
|
89
96
|
/**
|
|
90
|
-
*
|
|
91
|
-
* Returns `this` for chaining.
|
|
97
|
+
* Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the `src` that
|
|
98
|
+
* names it, as `<markdown-styles src="…">` does. Call before `render`. Returns `this` for chaining.
|
|
92
99
|
*/
|
|
93
|
-
|
|
100
|
+
loadMarkdownStyles(src, text) {
|
|
94
101
|
this._throwIfDisposed();
|
|
95
|
-
this.
|
|
102
|
+
this._markdownStyles.set(src, text);
|
|
96
103
|
return this;
|
|
97
104
|
}
|
|
98
105
|
/**
|
|
@@ -103,6 +110,44 @@ class PdfEngine {
|
|
|
103
110
|
this._disposed = true;
|
|
104
111
|
}
|
|
105
112
|
[Symbol.dispose]() { this.dispose(); }
|
|
113
|
+
/**
|
|
114
|
+
* Hand the engine the files of Markdown rules that a document names: the ones loaded here, and the ones read from
|
|
115
|
+
* their `src`. A file that can't be read is left for the engine to report, naming the `src`.
|
|
116
|
+
*/
|
|
117
|
+
_loadMarkdownStyles(engine, srcs) {
|
|
118
|
+
const files = new Map(this._markdownStyles);
|
|
119
|
+
for (const src of srcs) {
|
|
120
|
+
if (!files.has(src)) {
|
|
121
|
+
try {
|
|
122
|
+
files.set(src, (0, node_fs_1.readFileSync)(src, 'utf8'));
|
|
123
|
+
}
|
|
124
|
+
catch { /* not found; the engine says so */ }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
for (const [src, text] of files) {
|
|
128
|
+
engine.load_markdown_styles(src, text);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Hand the engine the files the document carries: the ones loaded here, and the ones read from the `src` of a file
|
|
133
|
+
* that wasn't. A `src` that can't be read is an error that names the file and the path.
|
|
134
|
+
*/
|
|
135
|
+
_loadFiles(engine, srcs) {
|
|
136
|
+
const files = new Map(this._files);
|
|
137
|
+
for (const [key, src] of srcs) {
|
|
138
|
+
if (files.has(key))
|
|
139
|
+
continue;
|
|
140
|
+
try {
|
|
141
|
+
files.set(key, (0, node_fs_1.readFileSync)(src));
|
|
142
|
+
}
|
|
143
|
+
catch (e) {
|
|
144
|
+
throw new LpdfRenderError(`file '${key}' of <attachments>: cannot read its src '${src}': ${e instanceof Error ? e.message : String(e)}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (const [key, bytes] of files) {
|
|
148
|
+
engine.load_file(key, bytes);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
106
151
|
_throwIfDisposed() {
|
|
107
152
|
if (this._disposed)
|
|
108
153
|
throw new Error('PdfEngine has been disposed.');
|
|
@@ -136,6 +181,8 @@ class PdfEngine {
|
|
|
136
181
|
for (const [name, bytes] of this._images) {
|
|
137
182
|
engine.load_image(name, bytes);
|
|
138
183
|
}
|
|
184
|
+
this._loadMarkdownStyles(engine, markdownStylesSrcs(xml));
|
|
185
|
+
this._loadFiles(engine, extractAssetSrcs(xml, 'file'));
|
|
139
186
|
// Auto-load images declared via <image src="…"> that weren't pre-loaded.
|
|
140
187
|
for (const [key, src] of extractAssetSrcs(xml, 'image')) {
|
|
141
188
|
if (!this._images.has(key)) {
|
|
@@ -145,12 +192,8 @@ class PdfEngine {
|
|
|
145
192
|
catch { /* skip unresolvable image */ }
|
|
146
193
|
}
|
|
147
194
|
}
|
|
148
|
-
if (this._encrypt) {
|
|
149
|
-
const permsJson = JSON.stringify(this._encrypt.permissions ?? {});
|
|
150
|
-
engine.set_encryption(this._encrypt.userPassword, this._encrypt.ownerPassword, permsJson);
|
|
151
|
-
}
|
|
152
195
|
const dataJson = callOptions.data != null ? JSON.stringify(callOptions.data) : null;
|
|
153
|
-
pdf = engine.render_pdf(xml, dataJson);
|
|
196
|
+
pdf = engine.render_pdf(xml, dataJson, ...(0, _shared_1.encryptionArguments)(callOptions, secureRandomBytes));
|
|
154
197
|
}
|
|
155
198
|
else {
|
|
156
199
|
// JSON (Kit tree) path — pass JSON directly to render_tree_pdf. Fonts and images the
|
|
@@ -180,15 +223,15 @@ class PdfEngine {
|
|
|
180
223
|
for (const [name, bytes] of allImages) {
|
|
181
224
|
engine.load_image(name, bytes);
|
|
182
225
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
pdf = engine.render_tree_pdf(json);
|
|
226
|
+
this._loadMarkdownStyles(engine, markdownStylesSrcsOfDocument(input));
|
|
227
|
+
this._loadFiles(engine, fileSrcsOfDocument(input));
|
|
228
|
+
pdf = engine.render_tree_pdf(json, ...(0, _shared_1.encryptionArguments)(callOptions, secureRandomBytes));
|
|
188
229
|
}
|
|
189
230
|
}
|
|
190
231
|
catch (e) {
|
|
191
232
|
engine.free();
|
|
233
|
+
if (e instanceof LpdfRenderError)
|
|
234
|
+
throw e;
|
|
192
235
|
const msg = e instanceof Error ? e.message : String(e);
|
|
193
236
|
throw new LpdfRenderError(msg);
|
|
194
237
|
}
|
|
@@ -198,21 +241,80 @@ class PdfEngine {
|
|
|
198
241
|
}
|
|
199
242
|
exports.PdfEngine = PdfEngine;
|
|
200
243
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
201
|
-
|
|
244
|
+
// Comments and CDATA sections, whose text is not markup: a <file> shown in a Markdown block is text, not a file.
|
|
245
|
+
const XML_NOT_MARKUP_RE = /<!--[\s\S]*?-->|<!\[CDATA\[[\s\S]*?\]\]>/g;
|
|
246
|
+
const XML_ATTRIBUTE_RE = /([\w:.-]+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
|
|
247
|
+
const XML_ENTITY_RE = /&(?:(amp|lt|gt|quot|apos)|#(\d+)|#x([0-9a-fA-F]+));/g;
|
|
248
|
+
const XML_ENTITIES = { amp: '&', lt: '<', gt: '>', quot: '"', apos: "'" };
|
|
249
|
+
/** An attribute value as the XML means it, with its entities and character references decoded. */
|
|
250
|
+
function decodeXml(value) {
|
|
251
|
+
return value.replace(XML_ENTITY_RE, (_, name, decimal, hex) =>
|
|
252
|
+
// XML_ENTITY_RE matches exactly one of its three groups, so without a name or a decimal there is a hex.
|
|
253
|
+
name ? XML_ENTITIES[name] : String.fromCodePoint(parseInt(decimal ?? hex, decimal ? 10 : 16)));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* The attributes of each `<tag>` element in XML, read as the engine reads them: comments and CDATA sections are left
|
|
257
|
+
* out, a quoted value may hold a `>`, either quote may be used, and the values are decoded.
|
|
258
|
+
*/
|
|
259
|
+
function xmlElements(xml, tag) {
|
|
260
|
+
const elements = [];
|
|
261
|
+
// Attribute values may contain '>', so quoted runs are matched whole.
|
|
262
|
+
const re = new RegExp(`<${tag}\\b((?:[^>"']|"[^"]*"|'[^']*')*)>`, 'g');
|
|
263
|
+
for (const match of xml.replace(XML_NOT_MARKUP_RE, '').matchAll(re)) {
|
|
264
|
+
const attributes = new Map();
|
|
265
|
+
for (const attribute of match[1].matchAll(XML_ATTRIBUTE_RE)) {
|
|
266
|
+
attributes.set(attribute[1], decodeXml(attribute[2] ?? attribute[3]));
|
|
267
|
+
}
|
|
268
|
+
elements.push(attributes);
|
|
269
|
+
}
|
|
270
|
+
return elements;
|
|
271
|
+
}
|
|
272
|
+
/** The `ref ?? name → src` pairs of the `<font>`, `<image>` or `<file>` elements in XML. */
|
|
202
273
|
function extractAssetSrcs(xml, tag) {
|
|
203
274
|
const result = new Map();
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
const name = /\bname="([^"]*)"/.exec(t)?.[1];
|
|
208
|
-
const ref = /\bref="([^"]*)"/.exec(t)?.[1];
|
|
209
|
-
const src = /\bsrc="([^"]*)"/.exec(t)?.[1];
|
|
210
|
-
const key = ref ?? name;
|
|
275
|
+
for (const attributes of xmlElements(xml, tag)) {
|
|
276
|
+
const key = attributes.get('ref') ?? attributes.get('name');
|
|
277
|
+
const src = attributes.get('src');
|
|
211
278
|
if (key && src)
|
|
212
279
|
result.set(key, src);
|
|
213
280
|
}
|
|
214
281
|
return result;
|
|
215
282
|
}
|
|
283
|
+
/** The `src` of each `<markdown-styles>` in XML. */
|
|
284
|
+
function markdownStylesSrcs(xml) {
|
|
285
|
+
const srcs = [];
|
|
286
|
+
for (const attributes of xmlElements(xml, 'markdown-styles')) {
|
|
287
|
+
const src = attributes.get('src');
|
|
288
|
+
if (src)
|
|
289
|
+
srcs.push(src);
|
|
290
|
+
}
|
|
291
|
+
return srcs;
|
|
292
|
+
}
|
|
293
|
+
/** The `src` of each `markdown-styles` a document holds, in the markdown of any of its sections. */
|
|
294
|
+
function markdownStylesSrcsOfDocument(document) {
|
|
295
|
+
const srcs = [];
|
|
296
|
+
for (const section of document.nodes) {
|
|
297
|
+
for (const child of section.nodes) {
|
|
298
|
+
if (child.type !== 'markdown')
|
|
299
|
+
continue;
|
|
300
|
+
for (const part of child.nodes) {
|
|
301
|
+
const src = part.type === 'markdown-styles' ? part.attrs['src'] : undefined;
|
|
302
|
+
if (typeof src === 'string' && src)
|
|
303
|
+
srcs.push(src);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return srcs;
|
|
308
|
+
}
|
|
309
|
+
/** The `ref ?? name → src` pairs of the files a document carries in `attrs.attachments`. */
|
|
310
|
+
function fileSrcsOfDocument(document) {
|
|
311
|
+
const result = new Map();
|
|
312
|
+
for (const { name, ref, src } of document.attrs['attachments'] ?? []) {
|
|
313
|
+
if (src)
|
|
314
|
+
result.set(ref ?? name, src);
|
|
315
|
+
}
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
216
318
|
/** The `ref ?? name → src` pairs of the fonts or images a document declares in `attrs.assets`. */
|
|
217
319
|
function assetSrcsOfDocument(document, kind) {
|
|
218
320
|
const result = new Map();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { PdfEngine, LpdfRenderError } from './engine';
|
|
2
|
-
export type { EncryptPermissions, EncryptOptions } from './engine';
|
|
3
2
|
export type { RenderOptions, EngineOptions } from './_shared';
|
|
4
|
-
export { FieldType, Pin, Orientation, SectionType, FootnoteCounter, BuiltinFont, PageScope } from './constants';
|
|
5
|
-
export type { PdfDocument, LpdfSectionNode, LpdfSectionChild, LpdfLayoutBlock, DocumentTokens,
|
|
6
|
-
export type { ColumnAttr, RowAttr, GridAttr, FrameAttr, LinkAttr, TableAttr, TheadAttr, TrAttr, TdAttr, TextAttr, SpanAttr, DividerAttr, ImgAttr, ShapeAttr, BarcodeAttr, RegionAttr, FieldAttr, BookmarkAttr, LayerAttr, RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, TextAtAttr, ImgAtAttr, BarcodeAtAttr, FontAttr, ImageAttr, LayoutAttr, } from './attrs';
|
|
7
|
-
export type { LpdfNode, LpdfContainerNode, LpdfTextNode, LpdfSpanNode, LpdfFnNode, LpdfDividerNode, LpdfImgNode, LpdfShapeNode, LpdfBarcodeNode, LpdfTableNode, LpdfTheadNode, LpdfTrNode, LpdfTdNode, LpdfRegionNode, LpdfFieldNode, LpdfBookmarkNode, } from './layout';
|
|
3
|
+
export { FieldType, Pin, Orientation, SectionType, FootnoteCounter, Cipher, Permission, FileRelationship, BuiltinFont, PageScope, } from './constants';
|
|
4
|
+
export type { PdfDocument, LpdfSectionNode, LpdfSectionChild, LpdfLayoutBlock, DocumentTokens, TokenSlot, TokenRow, DocumentAssets, DocumentMeta, DocumentOutput, SectionAttr, DocumentAttr, } from './kit';
|
|
5
|
+
export type { ColumnAttr, RowAttr, GridAttr, ListAttr, LiAttr, FrameAttr, LinkAttr, TableAttr, TheadAttr, TrAttr, TdAttr, TextAttr, CodeAttr, SpanAttr, CodeSpanAttr, DividerAttr, ImgAttr, ShapeAttr, BarcodeAttr, RegionAttr, FieldAttr, BookmarkAttr, LayerAttr, RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, TextAtAttr, ImgAtAttr, BarcodeAtAttr, FontAttr, ImageAttr, FileAttr, LayoutAttr, GradientToken, GradientStop, MarkdownAttr, MarkdownStylesAttr, MarkdownH1Attr, MarkdownH2Attr, MarkdownH3Attr, MarkdownH4Attr, MarkdownH5Attr, MarkdownH6Attr, MarkdownPAttr, MarkdownCodeAttr, MarkdownQuoteAttr, MarkdownLiAttr, MarkdownAAttr, MarkdownStrongAttr, MarkdownEmAttr, MarkdownDelAttr, MarkdownTableAttr, MarkdownThAttr, MarkdownTdAttr, } from './attrs';
|
|
6
|
+
export type { LpdfNode, LpdfContainerNode, LpdfListNode, LpdfLiNode, LpdfTextNode, LpdfCodeNode, LpdfSpanNode, LpdfCodeSpanNode, LpdfFnNode, LpdfDividerNode, LpdfImgNode, LpdfShapeNode, LpdfBarcodeNode, LpdfTableNode, LpdfTheadNode, LpdfTrNode, LpdfTdNode, LpdfRegionNode, LpdfFieldNode, LpdfBookmarkNode, } from './layout';
|
|
7
|
+
export { LMarkdown } from './markdown';
|
|
8
|
+
export type { LpdfMarkdownNode, LpdfMarkdownStylesNode, LpdfMarkdownContentNode, LpdfMarkdownRuleNode, } from './markdown';
|
|
8
9
|
export { CanvasTransform } from './canvas';
|
|
9
10
|
export type { LpdfCanvasLayerNode, LpdfCanvasPrimitiveNode, LpdfCanvasRectNode, LpdfCanvasLineNode, LpdfCanvasEllipseNode, LpdfCanvasCircleNode, LpdfCanvasPathNode, LpdfCanvasTextAtNode, LpdfCanvasImgAtNode, LpdfCanvasBarcodeAtNode, } from './canvas';
|
|
10
11
|
export { L, NoAttr } from './L';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NoAttr = exports.L = exports.CanvasTransform = exports.PageScope = exports.BuiltinFont = exports.FootnoteCounter = exports.SectionType = exports.Orientation = exports.Pin = exports.FieldType = exports.LpdfRenderError = exports.PdfEngine = void 0;
|
|
3
|
+
exports.NoAttr = exports.L = exports.CanvasTransform = exports.LMarkdown = exports.PageScope = exports.BuiltinFont = exports.FileRelationship = exports.Permission = exports.Cipher = exports.FootnoteCounter = exports.SectionType = exports.Orientation = exports.Pin = exports.FieldType = exports.LpdfRenderError = exports.PdfEngine = void 0;
|
|
4
4
|
// ── Engine ────────────────────────────────────────────────────────────────────
|
|
5
5
|
var engine_1 = require("./engine");
|
|
6
6
|
Object.defineProperty(exports, "PdfEngine", { enumerable: true, get: function () { return engine_1.PdfEngine; } });
|
|
@@ -12,8 +12,14 @@ Object.defineProperty(exports, "Pin", { enumerable: true, get: function () { ret
|
|
|
12
12
|
Object.defineProperty(exports, "Orientation", { enumerable: true, get: function () { return constants_1.Orientation; } });
|
|
13
13
|
Object.defineProperty(exports, "SectionType", { enumerable: true, get: function () { return constants_1.SectionType; } });
|
|
14
14
|
Object.defineProperty(exports, "FootnoteCounter", { enumerable: true, get: function () { return constants_1.FootnoteCounter; } });
|
|
15
|
+
Object.defineProperty(exports, "Cipher", { enumerable: true, get: function () { return constants_1.Cipher; } });
|
|
16
|
+
Object.defineProperty(exports, "Permission", { enumerable: true, get: function () { return constants_1.Permission; } });
|
|
17
|
+
Object.defineProperty(exports, "FileRelationship", { enumerable: true, get: function () { return constants_1.FileRelationship; } });
|
|
15
18
|
Object.defineProperty(exports, "BuiltinFont", { enumerable: true, get: function () { return constants_1.BuiltinFont; } });
|
|
16
19
|
Object.defineProperty(exports, "PageScope", { enumerable: true, get: function () { return constants_1.PageScope; } });
|
|
20
|
+
// ── Markdown ──────────────────────────────────────────────────────────────────
|
|
21
|
+
var markdown_1 = require("./markdown");
|
|
22
|
+
Object.defineProperty(exports, "LMarkdown", { enumerable: true, get: function () { return markdown_1.LMarkdown; } });
|
|
17
23
|
// ── Layer types ───────────────────────────────────────────────────────────────
|
|
18
24
|
var canvas_1 = require("./canvas");
|
|
19
25
|
Object.defineProperty(exports, "CanvasTransform", { enumerable: true, get: function () { return canvas_1.CanvasTransform; } });
|
package/dist/kit.d.ts
CHANGED
|
@@ -21,24 +21,13 @@
|
|
|
21
21
|
*/
|
|
22
22
|
import type { LpdfBookmarkNode, LpdfNode } from './layout';
|
|
23
23
|
import type { LpdfCanvasLayerNode } from './canvas';
|
|
24
|
-
import type {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
* A gradient of the tokens, which a background or a fill uses as `gradient:name`. Give `from` and `to` for two
|
|
32
|
-
* colors, or `stops` for more. `angle` is the direction of a linear gradient in degrees: 0 runs top to bottom
|
|
33
|
-
* and 90 left to right. A radial gradient runs from the center of the box out to its farthest corner.
|
|
34
|
-
*/
|
|
35
|
-
export interface GradientToken {
|
|
36
|
-
type: 'linear' | 'radial';
|
|
37
|
-
from?: string;
|
|
38
|
-
to?: string;
|
|
39
|
-
angle?: number | string;
|
|
40
|
-
stops?: GradientStop[];
|
|
41
|
-
}
|
|
24
|
+
import type { LpdfMarkdownNode } from './markdown';
|
|
25
|
+
import type { FileAttr, FontAttr, GradientToken, ImageAttr, LayoutAttr } from './attrs';
|
|
26
|
+
import { type AttrValue } from './_shared';
|
|
27
|
+
/** A slot of a token row, from the smallest to the largest. */
|
|
28
|
+
export type TokenSlot = 'xs' | 's' | 'm' | 'l' | 'xl' | 'xxl';
|
|
29
|
+
/** A token row: a value for each slot it sets. */
|
|
30
|
+
export type TokenRow<T> = Partial<Record<TokenSlot, T>>;
|
|
42
31
|
export interface DocumentTokens {
|
|
43
32
|
colors?: Record<string, string>;
|
|
44
33
|
gradients?: Record<string, GradientToken>;
|
|
@@ -48,15 +37,16 @@ export interface DocumentTokens {
|
|
|
48
37
|
* starting with a letter, and is neither a slot nor `fill` or `full`.
|
|
49
38
|
*/
|
|
50
39
|
aliases?: Record<string, string>;
|
|
51
|
-
space?:
|
|
52
|
-
grid?:
|
|
53
|
-
border?:
|
|
54
|
-
radius?:
|
|
55
|
-
width?:
|
|
40
|
+
space?: TokenRow<string>;
|
|
41
|
+
grid?: TokenRow<string>;
|
|
42
|
+
border?: TokenRow<string>;
|
|
43
|
+
radius?: TokenRow<string>;
|
|
44
|
+
width?: TokenRow<string>;
|
|
56
45
|
/** The heights `height` names: `{ xs: '16pt', s: '24pt', m: '32pt', l: '48pt', xl: '64pt', xxl: '96pt' }` by default. */
|
|
57
|
-
height?:
|
|
58
|
-
textSize?:
|
|
59
|
-
lineHeight
|
|
46
|
+
height?: TokenRow<string>;
|
|
47
|
+
textSize?: TokenRow<string>;
|
|
48
|
+
/** The factors `lineHeight` names, each a number above 0: `{ xs: 1, s: 1.1, m: 1.2, l: 1.4, xl: 1.6, xxl: 2 }` by default. */
|
|
49
|
+
lineHeight?: TokenRow<number>;
|
|
60
50
|
}
|
|
61
51
|
/**
|
|
62
52
|
* The fonts and images the document declares, as the `assets` element of the XML does. A font or image
|
|
@@ -73,12 +63,32 @@ export interface DocumentMeta {
|
|
|
73
63
|
keywords?: string;
|
|
74
64
|
creator?: string;
|
|
75
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* How the PDF file is written, as the `output` element of the XML is: whether it is encrypted, and what a reader
|
|
68
|
+
* may do with it, and the standard it meets. The passwords are not here: they come with the render call.
|
|
69
|
+
*/
|
|
70
|
+
export interface DocumentOutput {
|
|
71
|
+
/** The cipher the PDF is encrypted with, `aes-256` or `rc4-128` (`Cipher`). Without it the PDF is not encrypted. */
|
|
72
|
+
encrypt?: string;
|
|
73
|
+
/**
|
|
74
|
+
* What a reader may do without the owner password, separated by spaces (`Permission`): `all`, or any of
|
|
75
|
+
* `print`, `modify`, `copy`, `annotate`, `fill-forms`, `accessibility`, `assemble`. A permission comes only from
|
|
76
|
+
* naming it: without `allow`, or with `''`, nothing is allowed, and `all` allows everything. It needs `encrypt`.
|
|
77
|
+
*/
|
|
78
|
+
allow?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Writes the PDF as PDF/A, the standard for files kept for the long term: `2b`, or `2u` when its text must also
|
|
81
|
+
* be searchable. The render needs `createdOn`, and every text a font of `assets`. What PDF/A cannot hold is an
|
|
82
|
+
* error that says what to change: a built-in font, a CMYK color, a form field, a barcode's digits, `encrypt`.
|
|
83
|
+
*/
|
|
84
|
+
pdfa?: string;
|
|
85
|
+
}
|
|
76
86
|
export interface SectionAttr {
|
|
77
87
|
size?: string;
|
|
78
88
|
orientation?: string;
|
|
79
89
|
background?: string;
|
|
80
90
|
title?: string;
|
|
81
|
-
debug?:
|
|
91
|
+
debug?: boolean;
|
|
82
92
|
type?: string;
|
|
83
93
|
tocIndentStep?: string;
|
|
84
94
|
footnoteCounter?: string;
|
|
@@ -91,25 +101,31 @@ export interface DocumentAttr {
|
|
|
91
101
|
assets?: DocumentAssets;
|
|
92
102
|
tokens?: DocumentTokens;
|
|
93
103
|
meta?: DocumentMeta;
|
|
94
|
-
|
|
104
|
+
output?: DocumentOutput;
|
|
105
|
+
/**
|
|
106
|
+
* Files the PDF carries inside it, as the `attachments` element of the XML does: a reader lists them in its
|
|
107
|
+
* attachments panel. Each file's bytes are read from its `src`, or loaded with `loadFile` under its `ref` or name.
|
|
108
|
+
*/
|
|
109
|
+
attachments?: FileAttr[];
|
|
110
|
+
debug?: boolean;
|
|
95
111
|
footnoteCounter?: string;
|
|
96
112
|
}
|
|
97
113
|
/** A layout block — wraps an ordered list of layout nodes. */
|
|
98
114
|
export interface LpdfLayoutBlock {
|
|
99
115
|
type: 'layout';
|
|
100
|
-
attrs: Record<string,
|
|
116
|
+
attrs: Record<string, AttrValue>;
|
|
101
117
|
nodes: LpdfNode[];
|
|
102
118
|
}
|
|
103
119
|
export interface LpdfSectionNode {
|
|
104
120
|
type: 'section';
|
|
105
|
-
attrs: Record<string,
|
|
121
|
+
attrs: Record<string, AttrValue>;
|
|
106
122
|
nodes: LpdfSectionChild[];
|
|
107
123
|
}
|
|
108
124
|
/**
|
|
109
|
-
* What a section holds: a bookmark first, then layers, then at most one layout, then layers.
|
|
110
|
-
* the layout paint under it, and layers after it paint over it.
|
|
125
|
+
* What a section holds: a bookmark first, then layers, then at most one layout or one markdown, then layers.
|
|
126
|
+
* Layers before the layout paint under it, and layers after it paint over it.
|
|
111
127
|
*/
|
|
112
|
-
export type LpdfSectionChild = LpdfBookmarkNode | LpdfCanvasLayerNode | LpdfLayoutBlock;
|
|
128
|
+
export type LpdfSectionChild = LpdfBookmarkNode | LpdfCanvasLayerNode | LpdfLayoutBlock | LpdfMarkdownNode;
|
|
113
129
|
export interface PdfDocument {
|
|
114
130
|
version: 1;
|
|
115
131
|
type: 'document';
|
package/dist/kit.js
CHANGED
|
@@ -35,13 +35,15 @@ function section(attrs, nodes = []) {
|
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
function document(attrs, nodes = []) {
|
|
38
|
-
const { assets, tokens, meta, ...restOpts } = attrs ?? {};
|
|
38
|
+
const { assets, tokens, meta, output, attachments, ...restOpts } = attrs ?? {};
|
|
39
39
|
const attrsObj = {
|
|
40
40
|
...(0, _shared_1.buildAttrs)(restOpts),
|
|
41
41
|
};
|
|
42
42
|
if (assets !== undefined)
|
|
43
43
|
attrsObj['assets'] = assets;
|
|
44
44
|
if (tokens !== undefined) {
|
|
45
|
+
// A factor of the line-height row and a gradient's angle are numbers, which JSON can't hold as NaN or infinity.
|
|
46
|
+
(0, _shared_1.assertFiniteIn)('tokens', tokens);
|
|
45
47
|
const { textSize, lineHeight, ...rest } = tokens;
|
|
46
48
|
attrsObj['tokens'] = {
|
|
47
49
|
...rest,
|
|
@@ -51,6 +53,10 @@ function document(attrs, nodes = []) {
|
|
|
51
53
|
}
|
|
52
54
|
if (meta !== undefined)
|
|
53
55
|
attrsObj['meta'] = meta;
|
|
56
|
+
if (output !== undefined)
|
|
57
|
+
attrsObj['output'] = output;
|
|
58
|
+
if (attachments !== undefined)
|
|
59
|
+
attrsObj['attachments'] = attachments;
|
|
54
60
|
return {
|
|
55
61
|
version: 1,
|
|
56
62
|
type: 'document',
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,87 +1,126 @@
|
|
|
1
|
-
import type { ColumnAttr, RowAttr, GridAttr, FrameAttr, LinkAttr, TableAttr, TheadAttr, TrAttr, TdAttr, TextAttr, SpanAttr, DividerAttr, ImgAttr, ShapeAttr, BarcodeAttr, FieldAttr, RegionAttr, BookmarkAttr } from './attrs';
|
|
1
|
+
import type { ColumnAttr, RowAttr, GridAttr, ListAttr, LiAttr, FrameAttr, LinkAttr, TableAttr, TheadAttr, TrAttr, TdAttr, TextAttr, CodeAttr, SpanAttr, CodeSpanAttr, DividerAttr, ImgAttr, ShapeAttr, BarcodeAttr, FieldAttr, RegionAttr, BookmarkAttr } from './attrs';
|
|
2
|
+
import { type AttrValue } from './_shared';
|
|
2
3
|
export interface LpdfSpanNode {
|
|
3
4
|
type: 'span';
|
|
4
|
-
attrs: Record<string,
|
|
5
|
+
attrs: Record<string, AttrValue>;
|
|
6
|
+
nodes: string[];
|
|
7
|
+
}
|
|
8
|
+
/** A run of code inside a text: its words in the code font on a tint. */
|
|
9
|
+
export interface LpdfCodeSpanNode {
|
|
10
|
+
type: 'code-span';
|
|
11
|
+
attrs: Record<string, AttrValue>;
|
|
5
12
|
nodes: string[];
|
|
6
13
|
}
|
|
7
14
|
/** A footnote: its words go at the bottom of the page where its number lands. */
|
|
8
15
|
export interface LpdfFnNode {
|
|
9
16
|
type: 'fn';
|
|
10
|
-
attrs: Record<string,
|
|
17
|
+
attrs: Record<string, AttrValue>;
|
|
11
18
|
nodes: (string | LpdfSpanNode)[];
|
|
12
19
|
}
|
|
13
20
|
export interface LpdfContainerNode {
|
|
14
21
|
type: 'column' | 'row' | 'grid' | 'frame' | 'link';
|
|
15
|
-
attrs: Record<string,
|
|
22
|
+
attrs: Record<string, AttrValue>;
|
|
23
|
+
nodes: LpdfNode[];
|
|
24
|
+
}
|
|
25
|
+
/** A list of items, each marked with a bullet or a number the engine gives. */
|
|
26
|
+
export interface LpdfListNode {
|
|
27
|
+
type: 'list';
|
|
28
|
+
attrs: Record<string, AttrValue>;
|
|
29
|
+
nodes: LpdfLiNode[];
|
|
30
|
+
}
|
|
31
|
+
/** One item of a list: what a layout holds, beside the item's marker. */
|
|
32
|
+
export interface LpdfLiNode {
|
|
33
|
+
type: 'li';
|
|
34
|
+
attrs: Record<string, AttrValue>;
|
|
16
35
|
nodes: LpdfNode[];
|
|
17
36
|
}
|
|
18
37
|
export interface LpdfTextNode {
|
|
19
38
|
type: 'text';
|
|
20
|
-
attrs: Record<string,
|
|
21
|
-
nodes: (string | LpdfSpanNode | LpdfFnNode)[];
|
|
39
|
+
attrs: Record<string, AttrValue>;
|
|
40
|
+
nodes: (string | LpdfSpanNode | LpdfCodeSpanNode | LpdfFnNode)[];
|
|
41
|
+
}
|
|
42
|
+
/** Code in a box. Its strings keep their spaces and lines; its spans color parts of it. */
|
|
43
|
+
export interface LpdfCodeNode {
|
|
44
|
+
type: 'code';
|
|
45
|
+
attrs: Record<string, AttrValue>;
|
|
46
|
+
nodes: (string | LpdfSpanNode)[];
|
|
22
47
|
}
|
|
23
48
|
export interface LpdfDividerNode {
|
|
24
49
|
type: 'divider';
|
|
25
|
-
attrs: Record<string,
|
|
50
|
+
attrs: Record<string, AttrValue>;
|
|
26
51
|
}
|
|
27
52
|
export interface LpdfImgNode {
|
|
28
53
|
type: 'img';
|
|
29
|
-
attrs: Record<string,
|
|
54
|
+
attrs: Record<string, AttrValue>;
|
|
30
55
|
}
|
|
31
56
|
export interface LpdfShapeNode {
|
|
32
57
|
type: 'shape';
|
|
33
|
-
attrs: Record<string,
|
|
58
|
+
attrs: Record<string, AttrValue>;
|
|
34
59
|
}
|
|
35
60
|
export interface LpdfBarcodeNode {
|
|
36
61
|
type: 'barcode';
|
|
37
|
-
attrs: Record<string,
|
|
62
|
+
attrs: Record<string, AttrValue>;
|
|
38
63
|
}
|
|
39
64
|
export interface LpdfTheadNode {
|
|
40
65
|
type: 'thead';
|
|
41
|
-
attrs: Record<string,
|
|
66
|
+
attrs: Record<string, AttrValue>;
|
|
42
67
|
nodes: LpdfTdNode[];
|
|
43
68
|
}
|
|
44
69
|
export interface LpdfTrNode {
|
|
45
70
|
type: 'tr';
|
|
46
|
-
attrs: Record<string,
|
|
71
|
+
attrs: Record<string, AttrValue>;
|
|
47
72
|
nodes: LpdfTdNode[];
|
|
48
73
|
}
|
|
49
74
|
export interface LpdfTdNode {
|
|
50
75
|
type: 'td';
|
|
51
|
-
attrs: Record<string,
|
|
76
|
+
attrs: Record<string, AttrValue>;
|
|
52
77
|
nodes: LpdfNode[];
|
|
53
78
|
}
|
|
54
79
|
export interface LpdfTableNode {
|
|
55
80
|
type: 'table';
|
|
56
|
-
attrs: Record<string,
|
|
81
|
+
attrs: Record<string, AttrValue>;
|
|
57
82
|
nodes: (LpdfTheadNode | LpdfTrNode)[];
|
|
58
83
|
}
|
|
59
84
|
export interface LpdfRegionNode {
|
|
60
85
|
type: 'region';
|
|
61
|
-
attrs: Record<string,
|
|
86
|
+
attrs: Record<string, AttrValue>;
|
|
62
87
|
nodes: LpdfNode[];
|
|
63
88
|
}
|
|
64
89
|
export interface LpdfFieldNode {
|
|
65
90
|
type: 'field';
|
|
66
|
-
attrs: Record<string,
|
|
91
|
+
attrs: Record<string, AttrValue>;
|
|
67
92
|
}
|
|
68
93
|
/** An outline entry and link target that marks the node after it; it draws nothing. */
|
|
69
94
|
export interface LpdfBookmarkNode {
|
|
70
95
|
type: 'bookmark';
|
|
71
|
-
attrs: Record<string,
|
|
96
|
+
attrs: Record<string, AttrValue>;
|
|
72
97
|
}
|
|
73
|
-
export type LpdfNode = LpdfContainerNode | LpdfTextNode | LpdfDividerNode | LpdfTableNode | LpdfImgNode | LpdfShapeNode | LpdfBarcodeNode | LpdfRegionNode | LpdfFieldNode | LpdfBookmarkNode;
|
|
98
|
+
export type LpdfNode = LpdfContainerNode | LpdfListNode | LpdfTextNode | LpdfCodeNode | LpdfDividerNode | LpdfTableNode | LpdfImgNode | LpdfShapeNode | LpdfBarcodeNode | LpdfRegionNode | LpdfFieldNode | LpdfBookmarkNode;
|
|
74
99
|
declare function column(attrs: ColumnAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
|
|
75
100
|
declare function row(attrs: RowAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
|
|
76
101
|
declare function grid(attrs: GridAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
|
|
77
102
|
declare function frame(attrs: FrameAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
|
|
78
103
|
declare function link(attrs: LinkAttr, nodes?: LpdfNode[]): LpdfContainerNode;
|
|
104
|
+
/**
|
|
105
|
+
* A list of items, which are `li` nodes. A bullet list marks each item with a shape; with `type: 'number'` the
|
|
106
|
+
* engine numbers them, in the `format` given, and the numbers follow the items that `data-source` makes.
|
|
107
|
+
*/
|
|
108
|
+
declare function list(attrs: ListAttr | null, nodes?: LpdfLiNode[]): LpdfListNode;
|
|
109
|
+
/** An item of a list. Its words go in a `text`; a `list` inside it is a list under the item. */
|
|
110
|
+
declare function li(attrs: LiAttr | null, nodes?: LpdfNode[]): LpdfLiNode;
|
|
79
111
|
declare function table(attrs: TableAttr, nodes?: (LpdfTheadNode | LpdfTrNode)[]): LpdfTableNode;
|
|
80
112
|
declare function thead(attrs: TheadAttr | null, nodes?: LpdfTdNode[]): LpdfTheadNode;
|
|
81
113
|
declare function tr(attrs: TrAttr | null, nodes?: LpdfTdNode[]): LpdfTrNode;
|
|
82
114
|
declare function td(attrs: TdAttr | null, nodes?: LpdfNode[]): LpdfTdNode;
|
|
83
|
-
declare function text(attrs: TextAttr | null, nodes?: (string | LpdfSpanNode | LpdfFnNode)[]): LpdfTextNode;
|
|
115
|
+
declare function text(attrs: TextAttr | null, nodes?: (string | LpdfSpanNode | LpdfCodeSpanNode | LpdfFnNode)[]): LpdfTextNode;
|
|
116
|
+
/**
|
|
117
|
+
* Code in a box that fills the width and grows with its lines. The strings are kept as they are written: every
|
|
118
|
+
* space, and a new line wherever a `\n` is. A line longer than the box wraps. The spans color parts of it.
|
|
119
|
+
*/
|
|
120
|
+
declare function code(attrs: CodeAttr | null, nodes?: (string | LpdfSpanNode)[]): LpdfCodeNode;
|
|
84
121
|
declare function span(attrs: SpanAttr | null, nodes?: string[]): LpdfSpanNode;
|
|
122
|
+
/** A run of code in the nodes of a text: its words in the code font on a tint. */
|
|
123
|
+
declare function codeSpan(attrs: CodeSpanAttr | null, nodes?: string[]): LpdfCodeSpanNode;
|
|
85
124
|
/**
|
|
86
125
|
* A footnote, in the nodes of a text. The engine numbers it and puts a small raised number at its place in the
|
|
87
126
|
* text; its words go at the bottom of the page where that number lands. It has no attributes: pass `NoAttr`.
|
|
@@ -104,10 +143,14 @@ export declare const LpdfLayout: Readonly<{
|
|
|
104
143
|
column: typeof column;
|
|
105
144
|
row: typeof row;
|
|
106
145
|
grid: typeof grid;
|
|
146
|
+
list: typeof list;
|
|
147
|
+
li: typeof li;
|
|
107
148
|
frame: typeof frame;
|
|
108
149
|
link: typeof link;
|
|
109
150
|
text: typeof text;
|
|
151
|
+
code: typeof code;
|
|
110
152
|
span: typeof span;
|
|
153
|
+
codeSpan: typeof codeSpan;
|
|
111
154
|
fn: typeof fn;
|
|
112
155
|
divider: typeof divider;
|
|
113
156
|
img: typeof img;
|
package/dist/layout.js
CHANGED
|
@@ -22,6 +22,17 @@ function frame(attrs, nodes = []) {
|
|
|
22
22
|
function link(attrs, nodes = []) {
|
|
23
23
|
return makeContainer('link', attrs, nodes);
|
|
24
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* A list of items, which are `li` nodes. A bullet list marks each item with a shape; with `type: 'number'` the
|
|
27
|
+
* engine numbers them, in the `format` given, and the numbers follow the items that `data-source` makes.
|
|
28
|
+
*/
|
|
29
|
+
function list(attrs, nodes = []) {
|
|
30
|
+
return { type: 'list', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
31
|
+
}
|
|
32
|
+
/** An item of a list. Its words go in a `text`; a `list` inside it is a list under the item. */
|
|
33
|
+
function li(attrs, nodes = []) {
|
|
34
|
+
return { type: 'li', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
35
|
+
}
|
|
25
36
|
function table(attrs, nodes = []) {
|
|
26
37
|
return { type: 'table', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
27
38
|
}
|
|
@@ -37,9 +48,20 @@ function td(attrs, nodes = []) {
|
|
|
37
48
|
function text(attrs, nodes = []) {
|
|
38
49
|
return { type: 'text', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
39
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Code in a box that fills the width and grows with its lines. The strings are kept as they are written: every
|
|
53
|
+
* space, and a new line wherever a `\n` is. A line longer than the box wraps. The spans color parts of it.
|
|
54
|
+
*/
|
|
55
|
+
function code(attrs, nodes = []) {
|
|
56
|
+
return { type: 'code', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
57
|
+
}
|
|
40
58
|
function span(attrs, nodes = []) {
|
|
41
59
|
return { type: 'span', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
42
60
|
}
|
|
61
|
+
/** A run of code in the nodes of a text: its words in the code font on a tint. */
|
|
62
|
+
function codeSpan(attrs, nodes = []) {
|
|
63
|
+
return { type: 'code-span', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
|
|
64
|
+
}
|
|
43
65
|
/**
|
|
44
66
|
* A footnote, in the nodes of a text. The engine numbers it and puts a small raised number at its place in the
|
|
45
67
|
* text; its words go at the bottom of the page where that number lands. It has no attributes: pass `NoAttr`.
|
|
@@ -78,10 +100,14 @@ exports.LpdfLayout = Object.freeze({
|
|
|
78
100
|
column,
|
|
79
101
|
row,
|
|
80
102
|
grid,
|
|
103
|
+
list,
|
|
104
|
+
li,
|
|
81
105
|
frame,
|
|
82
106
|
link,
|
|
83
107
|
text,
|
|
108
|
+
code,
|
|
84
109
|
span,
|
|
110
|
+
codeSpan,
|
|
85
111
|
fn,
|
|
86
112
|
divider,
|
|
87
113
|
img,
|