@lpdfio/lpdf 0.29.0 → 0.30.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/dist/browser.js CHANGED
@@ -45,6 +45,20 @@ var LpdfEngine = class {
45
45
  const len1 = WASM_VECTOR_LEN;
46
46
  wasm.lpdfengine_load_image(this.__wbg_ptr, ptr0, len0, ptr1, len1);
47
47
  }
48
+ /**
49
+ * Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the
50
+ * `src` that names it. The engine reads no files: call this once for every `<markdown-styles src="…">`
51
+ * of the document before `render_pdf`, as `load_font` is called for a font.
52
+ * @param {string} src
53
+ * @param {string} xml
54
+ */
55
+ load_markdown_styles(src, xml) {
56
+ const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
57
+ const len0 = WASM_VECTOR_LEN;
58
+ const ptr1 = passStringToWasm0(xml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
59
+ const len1 = WASM_VECTOR_LEN;
60
+ wasm.lpdfengine_load_markdown_styles(this.__wbg_ptr, ptr0, len0, ptr1, len1);
61
+ }
48
62
  /**
49
63
  * @param {string} license_key
50
64
  */
@@ -151,26 +165,40 @@ var LpdfEngine = class {
151
165
  wasm.lpdfengine_set_created_on(this.__wbg_ptr, ptr0, len0);
152
166
  }
153
167
  /**
154
- * Configure RC4-128 encryption applied to every subsequent `render_pdf` call.
168
+ * Configure encryption applied to every subsequent `render_pdf` call.
155
169
  *
156
170
  * `permissions_json` is a JSON object with boolean fields matching the
157
171
  * `Permissions` struct (`print`, `modify`, `copy`, `annotate`, `fill_forms`,
158
172
  * `accessibility`, `assemble`, `print_hq`). Omitted fields default to `true`.
159
173
  *
174
+ * `algorithm` is `"aes-256"` or `"rc4-128"`. AES-256 needs `entropy`: at least 32
175
+ * random bytes from the host's secure generator, from which the core cuts the file
176
+ * key, salts and IVs. RC4-128 ignores it. Fails when the algorithm is unknown or
177
+ * AES-256 gets too little entropy.
178
+ *
160
179
  * To apply permissions without an open password, pass an empty `user_password`
161
180
  * and a non-empty `owner_password`.
162
181
  * @param {string} user_password
163
182
  * @param {string} owner_password
164
183
  * @param {string} permissions_json
184
+ * @param {string} algorithm
185
+ * @param {Uint8Array} entropy
165
186
  */
166
- set_encryption(user_password, owner_password, permissions_json) {
187
+ set_encryption(user_password, owner_password, permissions_json, algorithm, entropy) {
167
188
  const ptr0 = passStringToWasm0(user_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
168
189
  const len0 = WASM_VECTOR_LEN;
169
190
  const ptr1 = passStringToWasm0(owner_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
170
191
  const len1 = WASM_VECTOR_LEN;
171
192
  const ptr2 = passStringToWasm0(permissions_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
172
193
  const len2 = WASM_VECTOR_LEN;
173
- wasm.lpdfengine_set_encryption(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2);
194
+ const ptr3 = passStringToWasm0(algorithm, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
195
+ const len3 = WASM_VECTOR_LEN;
196
+ const ptr4 = passArray8ToWasm0(entropy, wasm.__wbindgen_malloc);
197
+ const len4 = WASM_VECTOR_LEN;
198
+ const ret = wasm.lpdfengine_set_encryption(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4);
199
+ if (ret[1]) {
200
+ throw takeFromExternrefTable0(ret[0]);
201
+ }
174
202
  }
175
203
  /**
176
204
  * Inject glyph advance-width tables for custom fonts.
@@ -451,6 +479,7 @@ async function initLpdf(wasmSource, licenseKey = "") {
451
479
  await __wbg_init(wasmSource);
452
480
  const fontMap = /* @__PURE__ */ new Map();
453
481
  const imageMap = /* @__PURE__ */ new Map();
482
+ const markdownStyles = /* @__PURE__ */ new Map();
454
483
  return {
455
484
  loadFont(name, bytes) {
456
485
  fontMap.set(name, bytes);
@@ -458,6 +487,9 @@ async function initLpdf(wasmSource, licenseKey = "") {
458
487
  loadImage(name, bytes) {
459
488
  imageMap.set(name, bytes);
460
489
  },
490
+ loadMarkdownStyles(src, text) {
491
+ markdownStyles.set(src, text);
492
+ },
461
493
  checkLicenseKey(key) {
462
494
  return JSON.parse(check_license(key ?? licenseKey, nowUnix()));
463
495
  },
@@ -470,6 +502,9 @@ async function initLpdf(wasmSource, licenseKey = "") {
470
502
  for (const [name, bytes] of imageMap) {
471
503
  engine.load_image(name, bytes);
472
504
  }
505
+ for (const [src, text] of markdownStyles) {
506
+ engine.load_markdown_styles(src, text);
507
+ }
473
508
  if (callOptions.createdOn) {
474
509
  engine.set_created_on(callOptions.createdOn);
475
510
  }
package/dist/canvas.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, TextAtAttr, ImgAtAttr, BarcodeAtAttr, LayerAttr } from './attrs';
2
- import type { LpdfSpanNode } from './layout';
2
+ import type { LpdfSpanNode, LpdfCodeSpanNode } from './layout';
3
3
  /**
4
4
  * Builds the `transform` string of a layer. `String(CanvasTransform.rotate(45))` is
5
5
  * `matrix(...)`, which a layer's `transform` attribute accepts like `rotate(45)`.
@@ -44,7 +44,7 @@ export interface LpdfCanvasPathNode {
44
44
  export interface LpdfCanvasTextAtNode {
45
45
  type: 'text-at';
46
46
  attrs: Record<string, string>;
47
- nodes: (string | LpdfSpanNode)[];
47
+ nodes: (string | LpdfSpanNode | LpdfCodeSpanNode)[];
48
48
  }
49
49
  export interface LpdfCanvasImgAtNode {
50
50
  type: 'img-at';
@@ -65,7 +65,7 @@ declare function line(attrs: LineAttr): LpdfCanvasLineNode;
65
65
  declare function ellipse(attrs: EllipseAttr): LpdfCanvasEllipseNode;
66
66
  declare function circle(attrs: CircleAttr): LpdfCanvasCircleNode;
67
67
  declare function path(attrs: PathAttr): LpdfCanvasPathNode;
68
- declare function textAt(attrs: TextAtAttr, nodes?: (string | LpdfSpanNode)[]): LpdfCanvasTextAtNode;
68
+ declare function textAt(attrs: TextAtAttr, nodes?: (string | LpdfSpanNode | LpdfCodeSpanNode)[]): LpdfCanvasTextAtNode;
69
69
  declare function imgAt(attrs: ImgAtAttr): LpdfCanvasImgAtNode;
70
70
  declare function barcodeAt(attrs: BarcodeAtAttr): LpdfCanvasBarcodeAtNode;
71
71
  declare function layer(attrs: LayerAttr | null, nodes?: LpdfCanvasPrimitiveNode[]): LpdfCanvasLayerNode;
package/dist/engine.d.ts CHANGED
@@ -26,7 +26,7 @@ export interface LicenseCheck {
26
26
  export declare class LpdfRenderError extends Error {
27
27
  constructor(message: string);
28
28
  }
29
- /** PDF permission flags for RC4-128 encryption. All flags default to `true` (allowed). */
29
+ /** PDF permission flags. All flags default to `true` (allowed). */
30
30
  export interface EncryptPermissions {
31
31
  print?: boolean;
32
32
  modify?: boolean;
@@ -37,7 +37,12 @@ export interface EncryptPermissions {
37
37
  assemble?: boolean;
38
38
  print_hq?: boolean;
39
39
  }
40
- /** RC4-128 encryption options passed to {@link PdfEngine.setEncryption}. */
40
+ /**
41
+ * The cipher a PDF is encrypted with. `'aes-256'` is the default. `'rc4-128'` is deprecated by
42
+ * PDF 2.0; use it only for readers that cannot open AES-256.
43
+ */
44
+ export type EncryptAlgorithm = 'aes-256' | 'rc4-128';
45
+ /** Encryption options passed to {@link PdfEngine.setEncryption}. */
41
46
  export interface EncryptOptions {
42
47
  /** Open password shown to readers. Empty string = no open password required. */
43
48
  userPassword: string;
@@ -45,11 +50,17 @@ export interface EncryptOptions {
45
50
  ownerPassword: string;
46
51
  /** Permission flags applied to the document. Omitted flags default to `true`. */
47
52
  permissions?: EncryptPermissions;
53
+ /**
54
+ * The cipher. Defaults to `'aes-256'`, which makes every render of the same document differ
55
+ * in its bytes, since each one gets a fresh random key.
56
+ */
57
+ algorithm?: EncryptAlgorithm;
48
58
  }
49
59
  export declare class PdfEngine {
50
60
  private _licenseKey;
51
61
  private readonly _fonts;
52
62
  private readonly _images;
63
+ private readonly _markdownStyles;
53
64
  private _disposed;
54
65
  private _encrypt;
55
66
  constructor();
@@ -80,8 +91,13 @@ export declare class PdfEngine {
80
91
  */
81
92
  loadImage(name: string, bytes: Uint8Array): this;
82
93
  /**
83
- * Configure RC4-128 encryption for all subsequent `render` calls.
84
- * Returns `this` for chaining.
94
+ * Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the `src` that
95
+ * names it, as `<markdown-styles src="…">` does. Call before `render`. Returns `this` for chaining.
96
+ */
97
+ loadMarkdownStyles(src: string, text: string): this;
98
+ /**
99
+ * Configure encryption for all subsequent `render` calls: AES-256 unless
100
+ * `options.algorithm` says `'rc4-128'`. Returns `this` for chaining.
85
101
  */
86
102
  setEncryption(options: EncryptOptions): this;
87
103
  /**
@@ -95,6 +111,11 @@ export declare class PdfEngine {
95
111
  */
96
112
  dispose(): void;
97
113
  [Symbol.dispose](): void;
114
+ /**
115
+ * Hand the engine the files of Markdown rules that a document names: the ones loaded here, and the ones read from
116
+ * their `src`. A file that can't be read is left for the engine to report, naming the `src`.
117
+ */
118
+ private _loadMarkdownStyles;
98
119
  private _throwIfDisposed;
99
120
  /**
100
121
  * Render an lpdf XML string to PDF bytes (Node.js).
package/dist/engine.js CHANGED
@@ -1,6 +1,7 @@
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");
5
6
  // require() path is relative to the compiled output at dist/engine.js.
6
7
  // In the published package, wasm-pack artifacts live in dist/wasm/.
@@ -28,11 +29,22 @@ class LpdfRenderError extends Error {
28
29
  }
29
30
  }
30
31
  exports.LpdfRenderError = LpdfRenderError;
32
+ /**
33
+ * Hands the engine the encryption options. AES-256 needs random bytes, which the engine does not
34
+ * make: they come from Node's secure generator, 32 bytes for each render.
35
+ */
36
+ function configureEncryption(engine, options) {
37
+ const algorithm = options.algorithm ?? 'aes-256';
38
+ const entropy = algorithm === 'aes-256' ? new Uint8Array((0, node_crypto_1.randomBytes)(32)) : new Uint8Array(0);
39
+ const permsJson = JSON.stringify(options.permissions ?? {});
40
+ engine.set_encryption(options.userPassword, options.ownerPassword, permsJson, algorithm, entropy);
41
+ }
31
42
  class PdfEngine {
32
43
  constructor() {
33
44
  this._licenseKey = '';
34
45
  this._fonts = new Map();
35
46
  this._images = new Map();
47
+ this._markdownStyles = new Map();
36
48
  this._disposed = false;
37
49
  this._encrypt = null;
38
50
  }
@@ -78,8 +90,17 @@ class PdfEngine {
78
90
  return this;
79
91
  }
80
92
  /**
81
- * Configure RC4-128 encryption for all subsequent `render` calls.
82
- * Returns `this` for chaining.
93
+ * Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the `src` that
94
+ * names it, as `<markdown-styles src="…">` does. Call before `render`. Returns `this` for chaining.
95
+ */
96
+ loadMarkdownStyles(src, text) {
97
+ this._throwIfDisposed();
98
+ this._markdownStyles.set(src, text);
99
+ return this;
100
+ }
101
+ /**
102
+ * Configure encryption for all subsequent `render` calls: AES-256 unless
103
+ * `options.algorithm` says `'rc4-128'`. Returns `this` for chaining.
83
104
  */
84
105
  setEncryption(options) {
85
106
  this._throwIfDisposed();
@@ -103,6 +124,24 @@ class PdfEngine {
103
124
  this._disposed = true;
104
125
  }
105
126
  [Symbol.dispose]() { this.dispose(); }
127
+ /**
128
+ * Hand the engine the files of Markdown rules that a document names: the ones loaded here, and the ones read from
129
+ * their `src`. A file that can't be read is left for the engine to report, naming the `src`.
130
+ */
131
+ _loadMarkdownStyles(engine, srcs) {
132
+ const files = new Map(this._markdownStyles);
133
+ for (const src of srcs) {
134
+ if (!files.has(src)) {
135
+ try {
136
+ files.set(src, (0, node_fs_1.readFileSync)(src, 'utf8'));
137
+ }
138
+ catch { /* not found; the engine says so */ }
139
+ }
140
+ }
141
+ for (const [src, text] of files) {
142
+ engine.load_markdown_styles(src, text);
143
+ }
144
+ }
106
145
  _throwIfDisposed() {
107
146
  if (this._disposed)
108
147
  throw new Error('PdfEngine has been disposed.');
@@ -136,6 +175,7 @@ class PdfEngine {
136
175
  for (const [name, bytes] of this._images) {
137
176
  engine.load_image(name, bytes);
138
177
  }
178
+ this._loadMarkdownStyles(engine, markdownStylesSrcs(xml));
139
179
  // Auto-load images declared via <image src="…"> that weren't pre-loaded.
140
180
  for (const [key, src] of extractAssetSrcs(xml, 'image')) {
141
181
  if (!this._images.has(key)) {
@@ -146,8 +186,7 @@ class PdfEngine {
146
186
  }
147
187
  }
148
188
  if (this._encrypt) {
149
- const permsJson = JSON.stringify(this._encrypt.permissions ?? {});
150
- engine.set_encryption(this._encrypt.userPassword, this._encrypt.ownerPassword, permsJson);
189
+ configureEncryption(engine, this._encrypt);
151
190
  }
152
191
  const dataJson = callOptions.data != null ? JSON.stringify(callOptions.data) : null;
153
192
  pdf = engine.render_pdf(xml, dataJson);
@@ -180,9 +219,9 @@ class PdfEngine {
180
219
  for (const [name, bytes] of allImages) {
181
220
  engine.load_image(name, bytes);
182
221
  }
222
+ this._loadMarkdownStyles(engine, markdownStylesSrcsOfDocument(input));
183
223
  if (this._encrypt) {
184
- const permsJson = JSON.stringify(this._encrypt.permissions ?? {});
185
- engine.set_encryption(this._encrypt.userPassword, this._encrypt.ownerPassword, permsJson);
224
+ configureEncryption(engine, this._encrypt);
186
225
  }
187
226
  pdf = engine.render_tree_pdf(json);
188
227
  }
@@ -213,6 +252,31 @@ function extractAssetSrcs(xml, tag) {
213
252
  }
214
253
  return result;
215
254
  }
255
+ /** The `src` of each `<markdown-styles>` in XML. */
256
+ function markdownStylesSrcs(xml) {
257
+ const srcs = [];
258
+ for (const match of xml.matchAll(/<markdown-styles\s[^>]*>/g)) {
259
+ const src = /\bsrc="([^"]*)"/.exec(match[0])?.[1];
260
+ if (src)
261
+ srcs.push(src);
262
+ }
263
+ return srcs;
264
+ }
265
+ /** The `src` of each `markdown-styles` a document holds, in the markdown of any of its sections. */
266
+ function markdownStylesSrcsOfDocument(document) {
267
+ const srcs = [];
268
+ for (const section of document.nodes) {
269
+ for (const child of section.nodes) {
270
+ if (child.type !== 'markdown')
271
+ continue;
272
+ for (const part of child.nodes) {
273
+ if (part.type === 'markdown-styles' && part.attrs['src'])
274
+ srcs.push(part.attrs['src']);
275
+ }
276
+ }
277
+ }
278
+ return srcs;
279
+ }
216
280
  /** The `ref ?? name → src` pairs of the fonts or images a document declares in `attrs.assets`. */
217
281
  function assetSrcsOfDocument(document, kind) {
218
282
  const result = new Map();
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  export { PdfEngine, LpdfRenderError } from './engine';
2
- export type { EncryptPermissions, EncryptOptions } from './engine';
2
+ export type { EncryptAlgorithm, EncryptPermissions, EncryptOptions } from './engine';
3
3
  export type { RenderOptions, EngineOptions } from './_shared';
4
4
  export { FieldType, Pin, Orientation, SectionType, FootnoteCounter, BuiltinFont, PageScope } from './constants';
5
5
  export type { PdfDocument, LpdfSectionNode, LpdfSectionChild, LpdfLayoutBlock, DocumentTokens, GradientToken, GradientStop, DocumentAssets, DocumentMeta, SectionAttr, DocumentAttr, } from './kit';
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';
6
+ 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, LayoutAttr, MarkdownAttr, MarkdownStylesAttr, MarkdownH1Attr, MarkdownH2Attr, MarkdownH3Attr, MarkdownH4Attr, MarkdownH5Attr, MarkdownH6Attr, MarkdownPAttr, MarkdownCodeAttr, MarkdownQuoteAttr, MarkdownLiAttr, MarkdownAAttr, MarkdownStrongAttr, MarkdownEmAttr, MarkdownDelAttr, MarkdownTableAttr, MarkdownThAttr, MarkdownTdAttr, } from './attrs';
7
+ export type { LpdfNode, LpdfContainerNode, LpdfListNode, LpdfLiNode, LpdfTextNode, LpdfCodeNode, LpdfSpanNode, LpdfCodeSpanNode, LpdfFnNode, LpdfDividerNode, LpdfImgNode, LpdfShapeNode, LpdfBarcodeNode, LpdfTableNode, LpdfTheadNode, LpdfTrNode, LpdfTdNode, LpdfRegionNode, LpdfFieldNode, LpdfBookmarkNode, } from './layout';
8
+ export { LMarkdown } from './markdown';
9
+ export type { LpdfMarkdownNode, LpdfMarkdownStylesNode, LpdfMarkdownContentNode, LpdfMarkdownRuleNode, } from './markdown';
8
10
  export { CanvasTransform } from './canvas';
9
11
  export type { LpdfCanvasLayerNode, LpdfCanvasPrimitiveNode, LpdfCanvasRectNode, LpdfCanvasLineNode, LpdfCanvasEllipseNode, LpdfCanvasCircleNode, LpdfCanvasPathNode, LpdfCanvasTextAtNode, LpdfCanvasImgAtNode, LpdfCanvasBarcodeAtNode, } from './canvas';
10
12
  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.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; } });
@@ -14,6 +14,9 @@ Object.defineProperty(exports, "SectionType", { enumerable: true, get: function
14
14
  Object.defineProperty(exports, "FootnoteCounter", { enumerable: true, get: function () { return constants_1.FootnoteCounter; } });
15
15
  Object.defineProperty(exports, "BuiltinFont", { enumerable: true, get: function () { return constants_1.BuiltinFont; } });
16
16
  Object.defineProperty(exports, "PageScope", { enumerable: true, get: function () { return constants_1.PageScope; } });
17
+ // ── Markdown ──────────────────────────────────────────────────────────────────
18
+ var markdown_1 = require("./markdown");
19
+ Object.defineProperty(exports, "LMarkdown", { enumerable: true, get: function () { return markdown_1.LMarkdown; } });
17
20
  // ── Layer types ───────────────────────────────────────────────────────────────
18
21
  var canvas_1 = require("./canvas");
19
22
  Object.defineProperty(exports, "CanvasTransform", { enumerable: true, get: function () { return canvas_1.CanvasTransform; } });
package/dist/kit.d.ts CHANGED
@@ -21,6 +21,7 @@
21
21
  */
22
22
  import type { LpdfBookmarkNode, LpdfNode } from './layout';
23
23
  import type { LpdfCanvasLayerNode } from './canvas';
24
+ import type { LpdfMarkdownNode } from './markdown';
24
25
  import type { FontAttr, ImageAttr, LayoutAttr } from './attrs';
25
26
  /** One color of a gradient: `color` is hex or a color token, at an `offset` from `'0%'` to `'100%'`. */
26
27
  export interface GradientStop {
@@ -106,10 +107,10 @@ export interface LpdfSectionNode {
106
107
  nodes: LpdfSectionChild[];
107
108
  }
108
109
  /**
109
- * What a section holds: a bookmark first, then layers, then at most one layout, then layers. Layers before
110
- * the layout paint under it, and layers after it paint over it.
110
+ * What a section holds: a bookmark first, then layers, then at most one layout or one markdown, then layers.
111
+ * Layers before the layout paint under it, and layers after it paint over it.
111
112
  */
112
- export type LpdfSectionChild = LpdfBookmarkNode | LpdfCanvasLayerNode | LpdfLayoutBlock;
113
+ export type LpdfSectionChild = LpdfBookmarkNode | LpdfCanvasLayerNode | LpdfLayoutBlock | LpdfMarkdownNode;
113
114
  export interface PdfDocument {
114
115
  version: 1;
115
116
  type: 'document';
package/dist/layout.d.ts CHANGED
@@ -1,9 +1,15 @@
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
2
  export interface LpdfSpanNode {
3
3
  type: 'span';
4
4
  attrs: Record<string, string>;
5
5
  nodes: string[];
6
6
  }
7
+ /** A run of code inside a text: its words in the code font on a tint. */
8
+ export interface LpdfCodeSpanNode {
9
+ type: 'code-span';
10
+ attrs: Record<string, string>;
11
+ nodes: string[];
12
+ }
7
13
  /** A footnote: its words go at the bottom of the page where its number lands. */
8
14
  export interface LpdfFnNode {
9
15
  type: 'fn';
@@ -15,10 +21,28 @@ export interface LpdfContainerNode {
15
21
  attrs: Record<string, string>;
16
22
  nodes: LpdfNode[];
17
23
  }
24
+ /** A list of items, each marked with a bullet or a number the engine gives. */
25
+ export interface LpdfListNode {
26
+ type: 'list';
27
+ attrs: Record<string, string>;
28
+ nodes: LpdfLiNode[];
29
+ }
30
+ /** One item of a list: what a layout holds, beside the item's marker. */
31
+ export interface LpdfLiNode {
32
+ type: 'li';
33
+ attrs: Record<string, string>;
34
+ nodes: LpdfNode[];
35
+ }
18
36
  export interface LpdfTextNode {
19
37
  type: 'text';
20
38
  attrs: Record<string, string>;
21
- nodes: (string | LpdfSpanNode | LpdfFnNode)[];
39
+ nodes: (string | LpdfSpanNode | LpdfCodeSpanNode | LpdfFnNode)[];
40
+ }
41
+ /** Code in a box. Its strings keep their spaces and lines; its spans color parts of it. */
42
+ export interface LpdfCodeNode {
43
+ type: 'code';
44
+ attrs: Record<string, string>;
45
+ nodes: (string | LpdfSpanNode)[];
22
46
  }
23
47
  export interface LpdfDividerNode {
24
48
  type: 'divider';
@@ -70,18 +94,32 @@ export interface LpdfBookmarkNode {
70
94
  type: 'bookmark';
71
95
  attrs: Record<string, string>;
72
96
  }
73
- export type LpdfNode = LpdfContainerNode | LpdfTextNode | LpdfDividerNode | LpdfTableNode | LpdfImgNode | LpdfShapeNode | LpdfBarcodeNode | LpdfRegionNode | LpdfFieldNode | LpdfBookmarkNode;
97
+ export type LpdfNode = LpdfContainerNode | LpdfListNode | LpdfTextNode | LpdfCodeNode | LpdfDividerNode | LpdfTableNode | LpdfImgNode | LpdfShapeNode | LpdfBarcodeNode | LpdfRegionNode | LpdfFieldNode | LpdfBookmarkNode;
74
98
  declare function column(attrs: ColumnAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
75
99
  declare function row(attrs: RowAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
76
100
  declare function grid(attrs: GridAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
77
101
  declare function frame(attrs: FrameAttr | null, nodes?: LpdfNode[]): LpdfContainerNode;
78
102
  declare function link(attrs: LinkAttr, nodes?: LpdfNode[]): LpdfContainerNode;
103
+ /**
104
+ * A list of items, which are `li` nodes. A bullet list marks each item with a shape; with `type: 'number'` the
105
+ * engine numbers them, in the `format` given, and the numbers follow the items that `data-source` makes.
106
+ */
107
+ declare function list(attrs: ListAttr | null, nodes?: LpdfLiNode[]): LpdfListNode;
108
+ /** An item of a list. Its words go in a `text`; a `list` inside it is a list under the item. */
109
+ declare function li(attrs: LiAttr | null, nodes?: LpdfNode[]): LpdfLiNode;
79
110
  declare function table(attrs: TableAttr, nodes?: (LpdfTheadNode | LpdfTrNode)[]): LpdfTableNode;
80
111
  declare function thead(attrs: TheadAttr | null, nodes?: LpdfTdNode[]): LpdfTheadNode;
81
112
  declare function tr(attrs: TrAttr | null, nodes?: LpdfTdNode[]): LpdfTrNode;
82
113
  declare function td(attrs: TdAttr | null, nodes?: LpdfNode[]): LpdfTdNode;
83
- declare function text(attrs: TextAttr | null, nodes?: (string | LpdfSpanNode | LpdfFnNode)[]): LpdfTextNode;
114
+ declare function text(attrs: TextAttr | null, nodes?: (string | LpdfSpanNode | LpdfCodeSpanNode | LpdfFnNode)[]): LpdfTextNode;
115
+ /**
116
+ * Code in a box that fills the width and grows with its lines. The strings are kept as they are written: every
117
+ * space, and a new line wherever a `\n` is. A line longer than the box wraps. The spans color parts of it.
118
+ */
119
+ declare function code(attrs: CodeAttr | null, nodes?: (string | LpdfSpanNode)[]): LpdfCodeNode;
84
120
  declare function span(attrs: SpanAttr | null, nodes?: string[]): LpdfSpanNode;
121
+ /** A run of code in the nodes of a text: its words in the code font on a tint. */
122
+ declare function codeSpan(attrs: CodeSpanAttr | null, nodes?: string[]): LpdfCodeSpanNode;
85
123
  /**
86
124
  * A footnote, in the nodes of a text. The engine numbers it and puts a small raised number at its place in the
87
125
  * text; its words go at the bottom of the page where that number lands. It has no attributes: pass `NoAttr`.
@@ -104,10 +142,14 @@ export declare const LpdfLayout: Readonly<{
104
142
  column: typeof column;
105
143
  row: typeof row;
106
144
  grid: typeof grid;
145
+ list: typeof list;
146
+ li: typeof li;
107
147
  frame: typeof frame;
108
148
  link: typeof link;
109
149
  text: typeof text;
150
+ code: typeof code;
110
151
  span: typeof span;
152
+ codeSpan: typeof codeSpan;
111
153
  fn: typeof fn;
112
154
  divider: typeof divider;
113
155
  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,
@@ -0,0 +1,75 @@
1
+ import type { MarkdownAttr, MarkdownStylesAttr, MarkdownH1Attr, MarkdownH2Attr, MarkdownH3Attr, MarkdownH4Attr, MarkdownH5Attr, MarkdownH6Attr, MarkdownPAttr, MarkdownCodeAttr, MarkdownQuoteAttr, MarkdownLiAttr, MarkdownAAttr, MarkdownStrongAttr, MarkdownEmAttr, MarkdownDelAttr, MarkdownTableAttr, MarkdownThAttr, MarkdownTdAttr } from './attrs';
2
+ /** A rule of a markdown's styles: the element it is named after, with the attributes it sets. */
3
+ export interface LpdfMarkdownRuleNode {
4
+ type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'code' | 'quote' | 'li' | 'a' | 'strong' | 'em' | 'del' | 'table' | 'th' | 'td';
5
+ attrs: Record<string, string>;
6
+ }
7
+ /** The rules that say how the parts of a markdown look, with a file of them in `src` when it has one. */
8
+ export interface LpdfMarkdownStylesNode {
9
+ type: 'markdown-styles';
10
+ attrs: Record<string, string>;
11
+ nodes: LpdfMarkdownRuleNode[];
12
+ }
13
+ /** The Markdown itself, as strings. */
14
+ export interface LpdfMarkdownContentNode {
15
+ type: 'markdown-content';
16
+ attrs: Record<string, string>;
17
+ nodes: string[];
18
+ }
19
+ /** A markdown, which takes the place of a layout in a section and holds only Markdown. */
20
+ export interface LpdfMarkdownNode {
21
+ type: 'markdown';
22
+ attrs: Record<string, string>;
23
+ nodes: (LpdfMarkdownStylesNode | LpdfMarkdownContentNode)[];
24
+ }
25
+ /**
26
+ * Markdown as the content of a section, where a layout would go. It holds only Markdown: the `LMarkdown.styles`
27
+ * that say how each part looks, which are optional, and one `LMarkdown.content` with the text. What Markdown
28
+ * can't say, such as the page, a header, a footer or a cover, stays in the section around it: layers paint a
29
+ * header and a footer in the margin it leaves.
30
+ *
31
+ * ```ts
32
+ * L.markdown({ margin: '54pt', gap: 'm' }, [
33
+ * LMarkdown.styles(NoAttr, [LMarkdown.h1({ color: 'muted' })]),
34
+ * LMarkdown.content(NoAttr, [body]),
35
+ * ])
36
+ * ```
37
+ */
38
+ declare function markdown(attrs: MarkdownAttr | null, nodes?: (LpdfMarkdownStylesNode | LpdfMarkdownContentNode)[]): LpdfMarkdownNode;
39
+ /**
40
+ * The rules that say how the parts of a markdown look. A rule is named after the Markdown it styles and takes the
41
+ * attributes of the element it becomes. A rule here overrides the same rule of the file `src` names, which
42
+ * overrides the defaults.
43
+ */
44
+ declare function styles(attrs: MarkdownStylesAttr | null, nodes?: LpdfMarkdownRuleNode[]): LpdfMarkdownStylesNode;
45
+ /**
46
+ * The Markdown, as strings that make one text. The common indent of its lines is removed, so that indenting the
47
+ * code does not make a code block of it. It has no attributes: pass `NoAttr`.
48
+ */
49
+ declare function content(attrs: null, nodes?: string[]): LpdfMarkdownContentNode;
50
+ /** The parts of a markdown: its styles, its content and the rules of its styles. */
51
+ export declare const LMarkdown: Readonly<{
52
+ styles: typeof styles;
53
+ content: typeof content;
54
+ h1: (attrs?: MarkdownH1Attr | null) => LpdfMarkdownRuleNode;
55
+ h2: (attrs?: MarkdownH2Attr | null) => LpdfMarkdownRuleNode;
56
+ h3: (attrs?: MarkdownH3Attr | null) => LpdfMarkdownRuleNode;
57
+ h4: (attrs?: MarkdownH4Attr | null) => LpdfMarkdownRuleNode;
58
+ h5: (attrs?: MarkdownH5Attr | null) => LpdfMarkdownRuleNode;
59
+ h6: (attrs?: MarkdownH6Attr | null) => LpdfMarkdownRuleNode;
60
+ p: (attrs?: MarkdownPAttr | null) => LpdfMarkdownRuleNode;
61
+ code: (attrs?: MarkdownCodeAttr | null) => LpdfMarkdownRuleNode;
62
+ quote: (attrs?: MarkdownQuoteAttr | null) => LpdfMarkdownRuleNode;
63
+ li: (attrs?: MarkdownLiAttr | null) => LpdfMarkdownRuleNode;
64
+ a: (attrs?: MarkdownAAttr | null) => LpdfMarkdownRuleNode;
65
+ strong: (attrs?: MarkdownStrongAttr | null) => LpdfMarkdownRuleNode;
66
+ em: (attrs?: MarkdownEmAttr | null) => LpdfMarkdownRuleNode;
67
+ del: (attrs?: MarkdownDelAttr | null) => LpdfMarkdownRuleNode;
68
+ table: (attrs?: MarkdownTableAttr | null) => LpdfMarkdownRuleNode;
69
+ th: (attrs?: MarkdownThAttr | null) => LpdfMarkdownRuleNode;
70
+ td: (attrs?: MarkdownTdAttr | null) => LpdfMarkdownRuleNode;
71
+ }>;
72
+ export declare const LpdfMarkdown: Readonly<{
73
+ markdown: typeof markdown;
74
+ }>;
75
+ export {};