@lpdfio/lpdf 0.26.0 → 0.28.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/README.md CHANGED
@@ -19,9 +19,9 @@ const { L, NoAttr } = require('@lpdfio/lpdf')
19
19
 
20
20
  const engine = L.engine()
21
21
 
22
- const doc = L.document({ size: 'letter', margin: '48pt' }, [
22
+ const doc = L.document({ size: 'letter' }, [
23
23
  L.section(NoAttr, [
24
- L.layout(NoAttr, [
24
+ L.layout({ margin: '48pt' }, [
25
25
  L.column({ gap: '24pt' }, [
26
26
  L.row({ justify: 'between' }, [
27
27
  L.text({ fontSize: '8pt', color: '#888888' }, ['ACME CORP']),
package/dist/L.d.ts CHANGED
@@ -5,7 +5,7 @@ export declare const NoAttr: null;
5
5
  /**
6
6
  * Unified lpdf facade.
7
7
  *
8
- * All document, layout, and canvas factory methods are available as flat
8
+ * All document, layout, and layer factory methods are available as flat
9
9
  * properties on this object. Construction-time configuration is handled via
10
10
  * `L.engine()`.
11
11
  *
@@ -30,9 +30,8 @@ export declare const L: Readonly<{
30
30
  /** Convert a `PdfDocument` tree to an lpdf XML string. */
31
31
  toXml: (doc: PdfDocument) => string;
32
32
  document: (attrs: import("./kit").DocumentAttr | null, nodes?: import("./kit").LpdfSectionNode[]) => PdfDocument;
33
- section: (attrs: import("./kit").SectionAttr | null, nodes?: (import("./layout").LpdfBookmarkNode | import("./kit").LpdfLayoutBlock | import("./kit").LpdfCanvasBlock)[]) => import("./kit").LpdfSectionNode;
34
- layout: (_attrs: null, nodes?: import("./layout").LpdfNode[]) => import("./kit").LpdfLayoutBlock;
35
- canvas: (_attrs: null, layers?: import("./canvas").LpdfCanvasLayerNode[]) => import("./kit").LpdfCanvasBlock;
33
+ section: (attrs: import("./kit").SectionAttr | null, nodes?: import("./kit").LpdfSectionChild[]) => import("./kit").LpdfSectionNode;
34
+ layout: (attrs: import("./attrs").LayoutAttr | null, nodes?: import("./layout").LpdfNode[]) => import("./kit").LpdfLayoutBlock;
36
35
  assets: (attrs: DocumentAssets) => DocumentAssets;
37
36
  tokens: (attrs: DocumentTokens) => DocumentTokens;
38
37
  column: (attrs: import("./attrs").ColumnAttr | null, nodes?: import("./layout").LpdfNode[]) => import("./layout").LpdfContainerNode;
@@ -58,6 +57,7 @@ export declare const L: Readonly<{
58
57
  ellipse: (attrs: import("./attrs").EllipseAttr) => import("./canvas").LpdfCanvasEllipseNode;
59
58
  circle: (attrs: import("./attrs").CircleAttr) => import("./canvas").LpdfCanvasCircleNode;
60
59
  path: (attrs: import("./attrs").PathAttr) => import("./canvas").LpdfCanvasPathNode;
61
- textAt: (attrs: import("./attrs").CanvasTextAttr, nodes?: (string | import("./layout").LpdfSpanNode)[]) => import("./canvas").LpdfCanvasTextNode;
62
- imgAt: (attrs: import("./attrs").CanvasImgAttr) => import("./canvas").LpdfCanvasImgNode;
60
+ textAt: (attrs: import("./attrs").TextAtAttr, nodes?: (string | import("./layout").LpdfSpanNode)[]) => import("./canvas").LpdfCanvasTextAtNode;
61
+ imgAt: (attrs: import("./attrs").ImgAtAttr) => import("./canvas").LpdfCanvasImgAtNode;
62
+ barcodeAt: (attrs: import("./attrs").BarcodeAtAttr) => import("./canvas").LpdfCanvasBarcodeAtNode;
63
63
  }>;
package/dist/L.js CHANGED
@@ -11,7 +11,7 @@ exports.NoAttr = null;
11
11
  /**
12
12
  * Unified lpdf facade.
13
13
  *
14
- * All document, layout, and canvas factory methods are available as flat
14
+ * All document, layout, and layer factory methods are available as flat
15
15
  * properties on this object. Construction-time configuration is handled via
16
16
  * `L.engine()`.
17
17
  *
@@ -39,7 +39,6 @@ exports.L = Object.freeze({
39
39
  document: kit_1.LpdfKit.document,
40
40
  section: kit_1.LpdfKit.section,
41
41
  layout: kit_1.LpdfKit.layout,
42
- canvas: kit_1.LpdfKit.canvas,
43
42
  assets: (attrs) => attrs,
44
43
  tokens: (attrs) => attrs,
45
44
  // ── Layout ────────────────────────────────────────────────────────────────
@@ -60,7 +59,7 @@ exports.L = Object.freeze({
60
59
  region: layout_1.LpdfLayout.region,
61
60
  field: layout_1.LpdfLayout.field,
62
61
  bookmark: layout_1.LpdfLayout.bookmark,
63
- // ── Canvas ────────────────────────────────────────────────────────────────
62
+ // ── Layers ────────────────────────────────────────────────────────────────
64
63
  layer: canvas_1.LpdfCanvas.layer,
65
64
  rect: canvas_1.LpdfCanvas.rect,
66
65
  line: canvas_1.LpdfCanvas.line,
@@ -69,4 +68,5 @@ exports.L = Object.freeze({
69
68
  path: canvas_1.LpdfCanvas.path,
70
69
  textAt: canvas_1.LpdfCanvas.textAt,
71
70
  imgAt: canvas_1.LpdfCanvas.imgAt,
71
+ barcodeAt: canvas_1.LpdfCanvas.barcodeAt,
72
72
  });
package/dist/attrs.d.ts CHANGED
@@ -5,6 +5,12 @@
5
5
  export interface ColumnAttr {
6
6
  font?: string;
7
7
  fontSize?: string;
8
+ /**
9
+ * The color of the text inside the box. A text that sets no color of its own takes the nearest
10
+ * box's, and the text token when no box sets one. A divider or a barcode in the box keeps its own
11
+ * color.
12
+ */
13
+ color?: string;
8
14
  gap?: string;
9
15
  /**
10
16
  * Space between the edge of the box and its content, written like CSS: one value for all sides,
@@ -21,6 +27,21 @@ export interface ColumnAttr {
21
27
  background?: string;
22
28
  border?: string;
23
29
  radius?: string;
30
+ /**
31
+ * How opaque the box and everything in it is, from 0 to 1. The box is faded as one, so children
32
+ * that overlap do not show through each other, and a box inside a faded box is faded further: 0.5
33
+ * inside 0.5 is drawn at 0.25. A form field in the box is not faded. Default 1.
34
+ */
35
+ opacity?: string;
36
+ /**
37
+ * A hard-edged shadow: a copy of the box, moved right and down by the first two lengths (negative
38
+ * is left and up) and filled with the color, drawn under the box with the same radius. An opacity
39
+ * from 0 to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur.
40
+ * The shadow takes no room in the layout, so it can run into the margin or a neighbor, and the
41
+ * siblings after the box are drawn over it. A box with no background shows the shadow only
42
+ * outside it. The box's own opacity fades the box and its shadow together.
43
+ */
44
+ shadow?: string;
24
45
  /**
25
46
  * Where the box falls in the page flow. no: never split the box, and move it whole to the next
26
47
  * page when it does not fit. break-before: start it on a new page. break-after: start the next
@@ -49,6 +70,12 @@ export interface ColumnAttr {
49
70
  export interface RowAttr {
50
71
  font?: string;
51
72
  fontSize?: string;
73
+ /**
74
+ * The color of the text inside the box. A text that sets no color of its own takes the nearest
75
+ * box's, and the text token when no box sets one. A divider or a barcode in the box keeps its own
76
+ * color.
77
+ */
78
+ color?: string;
52
79
  gap?: string;
53
80
  /**
54
81
  * Space between the edge of the box and its content, written like CSS: one value for all sides,
@@ -65,6 +92,21 @@ export interface RowAttr {
65
92
  background?: string;
66
93
  border?: string;
67
94
  radius?: string;
95
+ /**
96
+ * How opaque the box and everything in it is, from 0 to 1. The box is faded as one, so children
97
+ * that overlap do not show through each other, and a box inside a faded box is faded further: 0.5
98
+ * inside 0.5 is drawn at 0.25. A form field in the box is not faded. Default 1.
99
+ */
100
+ opacity?: string;
101
+ /**
102
+ * A hard-edged shadow: a copy of the box, moved right and down by the first two lengths (negative
103
+ * is left and up) and filled with the color, drawn under the box with the same radius. An opacity
104
+ * from 0 to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur.
105
+ * The shadow takes no room in the layout, so it can run into the margin or a neighbor, and the
106
+ * siblings after the box are drawn over it. A box with no background shows the shadow only
107
+ * outside it. The box's own opacity fades the box and its shadow together.
108
+ */
109
+ shadow?: string;
68
110
  /**
69
111
  * Where the box falls in the page flow. no: never split the box, and move it whole to the next
70
112
  * page when it does not fit. break-before: start it on a new page. break-after: start the next
@@ -91,6 +133,12 @@ export interface RowAttr {
91
133
  export interface GridAttr {
92
134
  font?: string;
93
135
  fontSize?: string;
136
+ /**
137
+ * The color of the text inside the box. A text that sets no color of its own takes the nearest
138
+ * box's, and the text token when no box sets one. A divider or a barcode in the box keeps its own
139
+ * color.
140
+ */
141
+ color?: string;
94
142
  gap?: string;
95
143
  /**
96
144
  * Space between the edge of the box and its content, written like CSS: one value for all sides,
@@ -107,6 +155,21 @@ export interface GridAttr {
107
155
  background?: string;
108
156
  border?: string;
109
157
  radius?: string;
158
+ /**
159
+ * How opaque the box and everything in it is, from 0 to 1. The box is faded as one, so children
160
+ * that overlap do not show through each other, and a box inside a faded box is faded further: 0.5
161
+ * inside 0.5 is drawn at 0.25. A form field in the box is not faded. Default 1.
162
+ */
163
+ opacity?: string;
164
+ /**
165
+ * A hard-edged shadow: a copy of the box, moved right and down by the first two lengths (negative
166
+ * is left and up) and filled with the color, drawn under the box with the same radius. An opacity
167
+ * from 0 to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur.
168
+ * The shadow takes no room in the layout, so it can run into the margin or a neighbor, and the
169
+ * siblings after the box are drawn over it. A box with no background shows the shadow only
170
+ * outside it. The box's own opacity fades the box and its shadow together.
171
+ */
172
+ shadow?: string;
110
173
  /**
111
174
  * Where the box falls in the page flow. no: never split the box, and move it whole to the next
112
175
  * page when it does not fit. break-before: start it on a new page. break-after: start the next
@@ -133,6 +196,12 @@ export interface GridAttr {
133
196
  export interface FrameAttr {
134
197
  font?: string;
135
198
  fontSize?: string;
199
+ /**
200
+ * The color of the text inside the box. A text that sets no color of its own takes the nearest
201
+ * box's, and the text token when no box sets one. A divider or a barcode in the box keeps its own
202
+ * color.
203
+ */
204
+ color?: string;
136
205
  /**
137
206
  * Space between the edge of the box and its content, written like CSS: one value for all sides,
138
207
  * two for top-bottom and left-right, three for top, left-right and bottom, four for top, right,
@@ -148,6 +217,21 @@ export interface FrameAttr {
148
217
  background?: string;
149
218
  border?: string;
150
219
  radius?: string;
220
+ /**
221
+ * How opaque the box and everything in it is, from 0 to 1. The box is faded as one, so children
222
+ * that overlap do not show through each other, and a box inside a faded box is faded further: 0.5
223
+ * inside 0.5 is drawn at 0.25. A form field in the box is not faded. Default 1.
224
+ */
225
+ opacity?: string;
226
+ /**
227
+ * A hard-edged shadow: a copy of the box, moved right and down by the first two lengths (negative
228
+ * is left and up) and filled with the color, drawn under the box with the same radius. An opacity
229
+ * from 0 to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur.
230
+ * The shadow takes no room in the layout, so it can run into the margin or a neighbor, and the
231
+ * siblings after the box are drawn over it. A box with no background shows the shadow only
232
+ * outside it. The box's own opacity fades the box and its shadow together.
233
+ */
234
+ shadow?: string;
151
235
  /**
152
236
  * Where the box falls in the page flow. no: never split the box, and move it whole to the next
153
237
  * page when it does not fit. break-before: start it on a new page. break-after: start the next
@@ -215,7 +299,11 @@ export interface SpanAttr {
215
299
  strike?: string;
216
300
  }
217
301
  /**
218
- * Attributes of the `img` element.
302
+ * An image. It is never stretched. With only a width or a height, the other follows the image's
303
+ * proportions. With both, they are a maximum: the image takes the largest size that fits in them,
304
+ * and its box becomes that size, which the parent's align places. To put images of different shapes
305
+ * in slots of one size, wrap each in a frame of that size. With neither, the image has its natural
306
+ * size.
219
307
  */
220
308
  export interface ImgAttr {
221
309
  name: string;
@@ -237,23 +325,34 @@ export interface ImgAttr {
237
325
  debug?: string;
238
326
  }
239
327
  /**
240
- * Attributes of the `barcode` element.
328
+ * A QR code, a Code 128 or an EAN-13. It is never stretched. With only a width or a height, the
329
+ * other follows the barcode's proportions. With both, they are a maximum: the barcode takes the
330
+ * largest size that fits in them, and its box becomes that size, which the parent's align places.
331
+ * To put barcodes in slots of one size, wrap each in a frame of that size.
241
332
  */
242
333
  export interface BarcodeAttr {
243
334
  type: string;
244
335
  data: string;
245
- size?: string;
246
336
  /**
247
- * Width of the element. A length fixes it. fill, in a row, takes the width its line leaves after
248
- * the other children, shared equally if several on the line use fill, and never moves to the next
249
- * line; in a column it takes the full width.
337
+ * Height of the whole barcode, with the digits of hrt inside it: they take the bottom 12pt and
338
+ * the bars the rest. A barcode is never stretched. With only a height, the width follows the
339
+ * barcode's proportions. With both width and height, they are a maximum: the barcode takes the
340
+ * largest size that fits in them, and its box becomes that size. A QR code is square, so it takes
341
+ * the smaller of the two. Without a size, a code128 is as wide as its bars at 1pt per module and
342
+ * its bars are 40pt high, and an ean13 is the standard symbol, 0.33mm per module and bars 22.85mm
343
+ * high. The digits of hrt add 12pt to either.
250
344
  */
251
- width?: string;
252
345
  height?: string;
253
346
  ec?: string;
254
347
  hrt?: string;
255
348
  color?: string;
256
349
  background?: string;
350
+ /**
351
+ * Width of the element. A length fixes it. fill, in a row, takes the width its line leaves after
352
+ * the other children, shared equally if several on the line use fill, and never moves to the next
353
+ * line; in a column it takes the full width.
354
+ */
355
+ width?: string;
257
356
  paginate?: string;
258
357
  debug?: string;
259
358
  }
@@ -272,6 +371,25 @@ export interface TextAttr {
272
371
  bold?: string;
273
372
  color?: string;
274
373
  align?: string;
374
+ /**
375
+ * The distance between lines, as a factor of the font size: a number above 0, such as 1.5, or a
376
+ * name from the line-height row of the tokens. Default 1.2, which is the token m.
377
+ */
378
+ lineHeight?: string;
379
+ /**
380
+ * The most lines drawn. Only whole lines are drawn, and the rest of the text is dropped. A text
381
+ * in the layout has no cap by default and wraps at the width it has; the lines it drops take no
382
+ * room, and a text that splits across pages keeps the cap across them. A text-at is one line by
383
+ * default, and above 1 needs a width to wrap within.
384
+ */
385
+ maxLines?: string;
386
+ /**
387
+ * End the last line drawn in an ellipsis when max-lines drops text, shortened to fit the width.
388
+ * Off by default: the text stops at the end of a line. A text-at also ends a line in one when it
389
+ * is cut off at its width. A text in the layout without max-lines is never cut, so there it has
390
+ * no effect.
391
+ */
392
+ ellipsis?: string;
275
393
  /**
276
394
  * Width of the element. A length fixes it. fill, in a row, takes the width its line leaves after
277
395
  * the other children, shared equally if several on the line use fill, and never moves to the next
@@ -291,6 +409,31 @@ export interface TextAttr {
291
409
  * where the lines fit.
292
410
  */
293
411
  orphans?: string;
412
+ /**
413
+ * Records the words of this text under a name as the pages are filled, so a text with capture-ref
414
+ * in a header or a footer can show them. Put it on a heading in the flow. The page that holds the
415
+ * text counts it, the words above it on that page included, and a text that splits across pages
416
+ * is recorded on the page where it starts. A text cannot have both capture and capture-ref.
417
+ */
418
+ capture?: string;
419
+ /**
420
+ * Shows what was captured under this name, as of the page the text is drawn on, in place of words
421
+ * of its own. Put it in a region. It takes the lines it may use, one unless max-lines says more,
422
+ * whatever it shows, so a header or a footer does not grow with its value; a longer value is cut,
423
+ * and ends in dots with ellipsis. On a page where nothing was captured it shows the latest value
424
+ * of an earlier page of the section, and capture-fallback before any.
425
+ */
426
+ captureRef?: string;
427
+ /**
428
+ * Which of the texts captured under the name on this page the text shows: the first or the last.
429
+ * Default last. Only for a text with capture-ref.
430
+ */
431
+ captureMode?: string;
432
+ /**
433
+ * What the text shows until something has been captured in the section. Default: nothing. Only
434
+ * for a text with capture-ref.
435
+ */
436
+ captureFallback?: string;
294
437
  paginate?: string;
295
438
  debug?: string;
296
439
  }
@@ -300,6 +443,12 @@ export interface TextAttr {
300
443
  export interface TdAttr {
301
444
  font?: string;
302
445
  fontSize?: string;
446
+ /**
447
+ * The color of the text inside the box. A text that sets no color of its own takes the nearest
448
+ * box's, and the text token when no box sets one. A divider or a barcode in the box keeps its own
449
+ * color.
450
+ */
451
+ color?: string;
303
452
  gap?: string;
304
453
  /**
305
454
  * Space between the edge of the box and its content, written like CSS: one value for all sides,
@@ -316,6 +465,21 @@ export interface TdAttr {
316
465
  background?: string;
317
466
  border?: string;
318
467
  radius?: string;
468
+ /**
469
+ * How opaque the box and everything in it is, from 0 to 1. The box is faded as one, so children
470
+ * that overlap do not show through each other, and a box inside a faded box is faded further: 0.5
471
+ * inside 0.5 is drawn at 0.25. A form field in the box is not faded. Default 1.
472
+ */
473
+ opacity?: string;
474
+ /**
475
+ * A hard-edged shadow: a copy of the box, moved right and down by the first two lengths (negative
476
+ * is left and up) and filled with the color, drawn under the box with the same radius. An opacity
477
+ * from 0 to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur.
478
+ * The shadow takes no room in the layout, so it can run into the margin or a neighbor, and the
479
+ * siblings after the box are drawn over it. A box with no background shows the shadow only
480
+ * outside it. The box's own opacity fades the box and its shadow together.
481
+ */
482
+ shadow?: string;
319
483
  /**
320
484
  * Where the box falls in the page flow. no: never split the box, and move it whole to the next
321
485
  * page when it does not fit. break-before: start it on a new page. break-after: start the next
@@ -414,8 +578,9 @@ export interface BookmarkAttr {
414
578
  }
415
579
  /**
416
580
  * Pins content to the top or bottom edge of pages, outside the normal flow, for headers and
417
- * footers. It reserves that space on every page it appears on. Only allowed directly inside layout,
418
- * and one per pin on a page.
581
+ * footers. It reserves that space on every page it appears on. Only allowed directly inside layout.
582
+ * Where it is written among the flow does not matter: pin chooses the edge, and regions on one edge
583
+ * stack in the order written.
419
584
  */
420
585
  export interface RegionAttr {
421
586
  /**
@@ -432,21 +597,46 @@ export interface RegionAttr {
432
597
  debug?: string;
433
598
  }
434
599
  /**
435
- * Groups canvas shapes and sets what applies to all of them: which pages they appear on, opacity,
436
- * transform and clip. Layers cannot be nested.
600
+ * Draws shapes, text, images and barcodes at exact positions on the page, independent of the
601
+ * flowing layout: watermarks, stamps, page furniture. Coordinates start at the top left corner of
602
+ * the whole page, not inside the layout's margin, and y grows downward. A layer before the
603
+ * section's layout paints under it, and one after paints over it. It sets what applies to all of
604
+ * its content: which pages it appears on, opacity, transform and clip, and the font, size and color
605
+ * of its text. Layers cannot be nested.
437
606
  */
438
607
  export interface LayerAttr {
439
608
  page?: string;
609
+ /**
610
+ * How opaque everything in the layer is, from 0 to 1. To fade one element, put it in a layer of
611
+ * its own.
612
+ */
440
613
  opacity?: string;
441
614
  transform?: string;
615
+ /**
616
+ * A rectangle that cuts off what the layer draws outside it: x y w h, in points from the top left
617
+ * corner of the page.
618
+ */
442
619
  clip?: string;
620
+ /**
621
+ * The font of the text-at in the layer that sets none of its own. Defaults to the font of the
622
+ * document.
623
+ */
624
+ font?: string;
625
+ /**
626
+ * The size of the text-at in the layer that sets none of its own. Defaults to 11pt.
627
+ */
628
+ fontSize?: string;
629
+ /**
630
+ * The color of the text-at in the layer that sets none of its own. Defaults to the text token.
631
+ */
632
+ color?: string;
443
633
  }
444
634
  /**
445
- * Attributes of the `rect` element on the canvas.
635
+ * Attributes of the `rect` element in a layer.
446
636
  */
447
637
  export interface RectAttr {
448
- w: string;
449
- h: string;
638
+ width: string;
639
+ height: string;
450
640
  x?: string;
451
641
  y?: string;
452
642
  anchor?: string;
@@ -455,39 +645,77 @@ export interface RectAttr {
455
645
  stroke?: string;
456
646
  strokeWidth?: string;
457
647
  strokeDash?: string;
458
- opacity?: string;
648
+ /**
649
+ * A hard-edged shadow: a copy of the shape, moved right and down by the first two lengths
650
+ * (negative is left and up) and filled with the color, drawn under the shape. An opacity from 0
651
+ * to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur. A shape
652
+ * with no fill shows the shadow only outside it.
653
+ */
654
+ shadow?: string;
459
655
  }
460
656
  /**
461
- * Attributes of the `circle` element on the canvas.
657
+ * Attributes of the `circle` element in a layer.
462
658
  */
463
659
  export interface CircleAttr {
464
660
  r: string;
465
- cx?: string;
466
- cy?: string;
661
+ /**
662
+ * Where the circle's box goes, the square of side 2r around it: its left edge, or with anchor, an
663
+ * offset from that point of the page, where the box's matching point goes. The centre is r
664
+ * further in.
665
+ */
666
+ x?: string;
667
+ /**
668
+ * Where the circle's box goes, the square of side 2r around it: its top edge, or with anchor, an
669
+ * offset from that point of the page, where the box's matching point goes. The centre is r
670
+ * further in.
671
+ */
672
+ y?: string;
467
673
  anchor?: string;
468
674
  fill?: string;
469
675
  stroke?: string;
470
676
  strokeWidth?: string;
471
677
  strokeDash?: string;
472
- opacity?: string;
678
+ /**
679
+ * A hard-edged shadow: a copy of the shape, moved right and down by the first two lengths
680
+ * (negative is left and up) and filled with the color, drawn under the shape. An opacity from 0
681
+ * to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur. A shape
682
+ * with no fill shows the shadow only outside it.
683
+ */
684
+ shadow?: string;
473
685
  }
474
686
  /**
475
- * Attributes of the `ellipse` element on the canvas.
687
+ * Attributes of the `ellipse` element in a layer.
476
688
  */
477
689
  export interface EllipseAttr {
478
690
  rx: string;
479
691
  ry: string;
480
- cx?: string;
481
- cy?: string;
692
+ /**
693
+ * Where the ellipse's box goes, 2rx wide and 2ry high around it: its left edge, or with anchor,
694
+ * an offset from that point of the page, where the box's matching point goes. The centre is rx
695
+ * further in.
696
+ */
697
+ x?: string;
698
+ /**
699
+ * Where the ellipse's box goes, 2rx wide and 2ry high around it: its top edge, or with anchor, an
700
+ * offset from that point of the page, where the box's matching point goes. The centre is ry
701
+ * further in.
702
+ */
703
+ y?: string;
482
704
  anchor?: string;
483
705
  fill?: string;
484
706
  stroke?: string;
485
707
  strokeWidth?: string;
486
708
  strokeDash?: string;
487
- opacity?: string;
709
+ /**
710
+ * A hard-edged shadow: a copy of the shape, moved right and down by the first two lengths
711
+ * (negative is left and up) and filled with the color, drawn under the shape. An opacity from 0
712
+ * to 1 after the color fades the shadow alone: "2pt 3pt #000000 0.2". There is no blur. A shape
713
+ * with no fill shows the shadow only outside it.
714
+ */
715
+ shadow?: string;
488
716
  }
489
717
  /**
490
- * Attributes of the `line` element on the canvas.
718
+ * Attributes of the `line` element in a layer.
491
719
  */
492
720
  export interface LineAttr {
493
721
  x1: string;
@@ -500,7 +728,7 @@ export interface LineAttr {
500
728
  lineCap?: string;
501
729
  }
502
730
  /**
503
- * Attributes of the `path` element on the canvas.
731
+ * Attributes of the `path` element in a layer.
504
732
  */
505
733
  export interface PathAttr {
506
734
  d: string;
@@ -510,33 +738,111 @@ export interface PathAttr {
510
738
  strokeWidth?: string;
511
739
  strokeDash?: string;
512
740
  lineCap?: string;
513
- opacity?: string;
514
741
  }
515
742
  /**
516
- * Text at an exact position on the page: either x and y, or an anchor with optional offsets.
743
+ * Text at a fixed place on the page. It is the text of the layout, with the same defaults: the
744
+ * document's font or Helvetica, 11pt and the text colour. It is one line unless told otherwise;
745
+ * give width to cut it off at a width or to wrap it with max-lines. x and y place its box: the
746
+ * top-left corner, or with anchor, an offset from that point of the page, where the box's matching
747
+ * point goes. {page} and {pages} in it count within the section, and a text that comes from data
748
+ * belongs in the layout, since a longer text loses its end here without a warning.
517
749
  */
518
- export interface CanvasTextAttr {
750
+ export interface TextAtAttr {
519
751
  x?: string;
520
752
  y?: string;
521
753
  anchor?: string;
522
- font?: string;
523
754
  fontSize?: string;
755
+ font?: string;
756
+ /**
757
+ * Use the bold face of the font. It applies to the 14 built-in fonts: Helvetica becomes
758
+ * Helvetica-Bold, Times-Roman becomes Times-Bold, Courier becomes Courier-Bold, and the oblique
759
+ * and italic faces their bold forms. A custom font has no bold face to pick, so name one in font.
760
+ */
761
+ bold?: string;
524
762
  color?: string;
525
763
  align?: string;
526
- w?: string;
764
+ /**
765
+ * The distance between lines, as a factor of the font size: a number above 0, such as 1.5, or a
766
+ * name from the line-height row of the tokens. Default 1.2, which is the token m.
767
+ */
527
768
  lineHeight?: string;
528
- opacity?: string;
769
+ /**
770
+ * The most lines drawn. Only whole lines are drawn, and the rest of the text is dropped. A text
771
+ * in the layout has no cap by default and wraps at the width it has; the lines it drops take no
772
+ * room, and a text that splits across pages keeps the cap across them. A text-at is one line by
773
+ * default, and above 1 needs a width to wrap within.
774
+ */
775
+ maxLines?: string;
776
+ /**
777
+ * End the last line drawn in an ellipsis when max-lines drops text, shortened to fit the width.
778
+ * Off by default: the text stops at the end of a line. A text-at also ends a line in one when it
779
+ * is cut off at its width. A text in the layout without max-lines is never cut, so there it has
780
+ * no effect.
781
+ */
782
+ ellipsis?: string;
783
+ /**
784
+ * Width of the box. Without it the text is one line of the width its characters need, and align
785
+ * has no effect; a long text runs on past the edge of the page, which cuts it off, but stays in
786
+ * the PDF. With it, a line past the width is cut off at it, or ends in an ellipsis with ellipsis,
787
+ * and max-lines above 1 wraps the text within it.
788
+ */
789
+ width?: string;
529
790
  }
530
791
  /**
531
- * Attributes of the `img` element on the canvas.
792
+ * An image at a fixed place on the page. It needs width or height, and the other follows the
793
+ * image's proportions. With both, they are a maximum: the image takes the largest size that fits in
794
+ * them, and its box becomes that size, so an anchor places the image itself. x and y place its box:
795
+ * the top-left corner, or with anchor, an offset from that point of the page, where the box's
796
+ * matching point goes.
532
797
  */
533
- export interface CanvasImgAttr {
798
+ export interface ImgAtAttr {
534
799
  name: string;
535
- w: string;
536
- h: string;
537
800
  x?: string;
538
801
  y?: string;
539
802
  anchor?: string;
803
+ width?: string;
804
+ height?: string;
805
+ }
806
+ /**
807
+ * A barcode at a fixed place on the page. It needs width or height, and the other follows the
808
+ * barcode's proportions. With both, they are a maximum: the barcode takes the largest size that
809
+ * fits in them, and its box becomes that size, so an anchor places the barcode itself. x and y
810
+ * place its box: the top-left corner, or with anchor, an offset from that point of the page, where
811
+ * the box's matching point goes.
812
+ */
813
+ export interface BarcodeAtAttr {
814
+ type: string;
815
+ data: string;
816
+ /**
817
+ * Height of the whole barcode, with the digits of hrt inside it: they take the bottom 12pt and
818
+ * the bars the rest. A barcode is never stretched. With only a height, the width follows the
819
+ * barcode's proportions. With both width and height, they are a maximum: the barcode takes the
820
+ * largest size that fits in them, and its box becomes that size. A QR code is square, so it takes
821
+ * the smaller of the two. Without a size, a code128 is as wide as its bars at 1pt per module and
822
+ * its bars are 40pt high, and an ean13 is the standard symbol, 0.33mm per module and bars 22.85mm
823
+ * high. The digits of hrt add 12pt to either.
824
+ */
825
+ height?: string;
826
+ ec?: string;
827
+ hrt?: string;
828
+ color?: string;
829
+ background?: string;
830
+ x?: string;
831
+ y?: string;
832
+ anchor?: string;
833
+ width?: string;
834
+ }
835
+ /**
836
+ * The flowing content of a section. Elements stack down the page, and a new page starts when one
837
+ * runs out of room. Put headers and footers in a region, which sits outside the flow.
838
+ */
839
+ export interface LayoutAttr {
840
+ /**
841
+ * The space between the page edges and the flowing content and its regions: one value for all
842
+ * four sides, or two to four in the order top, right, bottom, left. Defaults to 36pt. Layers
843
+ * ignore it and measure from the page edges.
844
+ */
845
+ margin?: string;
540
846
  }
541
847
  /**
542
848
  * Declares a font that text can be set in by name, with the font attribute. A built-in PDF font is
package/dist/browser.js CHANGED
@@ -119,7 +119,7 @@ var LpdfEngine = class {
119
119
  }
120
120
  }
121
121
  /**
122
- * Render a JSON kit-tree or canvas-tree document to PDF bytes.
122
+ * Render a JSON kit-tree document to PDF bytes.
123
123
  *
124
124
  * This is the JSON counterpart of `render_pdf`. The Node adapter uses it
125
125
  * when an `LpdfDocument` Kit tree is passed to `renderPdf()`, avoiding an
package/dist/canvas.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, CanvasTextAttr, CanvasImgAttr, LayerAttr } from './attrs';
1
+ import type { RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, TextAtAttr, ImgAtAttr, BarcodeAtAttr, LayerAttr } from './attrs';
2
2
  import type { LpdfSpanNode } from './layout';
3
3
  /**
4
4
  * Builds the `transform` string of a layer. `String(CanvasTransform.rotate(45))` is
@@ -41,16 +41,20 @@ export interface LpdfCanvasPathNode {
41
41
  type: 'path';
42
42
  attrs: Record<string, string>;
43
43
  }
44
- export interface LpdfCanvasTextNode {
45
- type: 'text';
44
+ export interface LpdfCanvasTextAtNode {
45
+ type: 'text-at';
46
46
  attrs: Record<string, string>;
47
47
  nodes: (string | LpdfSpanNode)[];
48
48
  }
49
- export interface LpdfCanvasImgNode {
50
- type: 'img';
49
+ export interface LpdfCanvasImgAtNode {
50
+ type: 'img-at';
51
51
  attrs: Record<string, string>;
52
52
  }
53
- export type LpdfCanvasPrimitiveNode = LpdfCanvasRectNode | LpdfCanvasLineNode | LpdfCanvasEllipseNode | LpdfCanvasCircleNode | LpdfCanvasPathNode | LpdfCanvasTextNode | LpdfCanvasImgNode;
53
+ export interface LpdfCanvasBarcodeAtNode {
54
+ type: 'barcode-at';
55
+ attrs: Record<string, string>;
56
+ }
57
+ export type LpdfCanvasPrimitiveNode = LpdfCanvasRectNode | LpdfCanvasLineNode | LpdfCanvasEllipseNode | LpdfCanvasCircleNode | LpdfCanvasPathNode | LpdfCanvasTextAtNode | LpdfCanvasImgAtNode | LpdfCanvasBarcodeAtNode;
54
58
  export interface LpdfCanvasLayerNode {
55
59
  type: 'layer';
56
60
  attrs: Record<string, string>;
@@ -61,8 +65,9 @@ declare function line(attrs: LineAttr): LpdfCanvasLineNode;
61
65
  declare function ellipse(attrs: EllipseAttr): LpdfCanvasEllipseNode;
62
66
  declare function circle(attrs: CircleAttr): LpdfCanvasCircleNode;
63
67
  declare function path(attrs: PathAttr): LpdfCanvasPathNode;
64
- declare function textAt(attrs: CanvasTextAttr, nodes?: (string | LpdfSpanNode)[]): LpdfCanvasTextNode;
65
- declare function imgAt(attrs: CanvasImgAttr): LpdfCanvasImgNode;
68
+ declare function textAt(attrs: TextAtAttr, nodes?: (string | LpdfSpanNode)[]): LpdfCanvasTextAtNode;
69
+ declare function imgAt(attrs: ImgAtAttr): LpdfCanvasImgAtNode;
70
+ declare function barcodeAt(attrs: BarcodeAtAttr): LpdfCanvasBarcodeAtNode;
66
71
  declare function layer(attrs: LayerAttr | null, nodes?: LpdfCanvasPrimitiveNode[]): LpdfCanvasLayerNode;
67
72
  export declare const LpdfCanvas: Readonly<{
68
73
  rect: typeof rect;
@@ -72,6 +77,7 @@ export declare const LpdfCanvas: Readonly<{
72
77
  path: typeof path;
73
78
  textAt: typeof textAt;
74
79
  imgAt: typeof imgAt;
80
+ barcodeAt: typeof barcodeAt;
75
81
  layer: typeof layer;
76
82
  }>;
77
83
  export {};
package/dist/canvas.js CHANGED
@@ -67,10 +67,13 @@ function path(attrs) {
67
67
  return { type: 'path', attrs: (0, _shared_1.buildAttrs)(attrs) };
68
68
  }
69
69
  function textAt(attrs, nodes = []) {
70
- return { type: 'text', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
70
+ return { type: 'text-at', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
71
71
  }
72
72
  function imgAt(attrs) {
73
- return { type: 'img', attrs: (0, _shared_1.buildAttrs)(attrs) };
73
+ return { type: 'img-at', attrs: (0, _shared_1.buildAttrs)(attrs) };
74
+ }
75
+ function barcodeAt(attrs) {
76
+ return { type: 'barcode-at', attrs: (0, _shared_1.buildAttrs)(attrs) };
74
77
  }
75
78
  function layer(attrs, nodes = []) {
76
79
  return { type: 'layer', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
@@ -83,5 +86,6 @@ exports.LpdfCanvas = Object.freeze({
83
86
  path,
84
87
  textAt,
85
88
  imgAt,
89
+ barcodeAt,
86
90
  layer,
87
91
  });
package/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ export { PdfEngine, LpdfRenderError } from './engine';
2
2
  export type { EncryptPermissions, EncryptOptions } from './engine';
3
3
  export type { RenderOptions, EngineOptions } from './_shared';
4
4
  export { FieldType, Pin, Orientation, SectionType, BuiltinFont, PageScope } from './constants';
5
- export type { PdfDocument, LpdfSectionNode, LpdfLayoutBlock, LpdfCanvasBlock, DocumentTokens, DocumentAssets, DocumentMeta, SectionAttr, DocumentAttr, } from './kit';
6
- export type { ColumnAttr, RowAttr, GridAttr, FrameAttr, LinkAttr, TableAttr, TheadAttr, TrAttr, TdAttr, TextAttr, SpanAttr, DividerAttr, ImgAttr, BarcodeAttr, RegionAttr, FieldAttr, BookmarkAttr, LayerAttr, RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, CanvasTextAttr, CanvasImgAttr, FontAttr, ImageAttr, } from './attrs';
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, BarcodeAttr, RegionAttr, FieldAttr, BookmarkAttr, LayerAttr, RectAttr, CircleAttr, EllipseAttr, LineAttr, PathAttr, TextAtAttr, ImgAtAttr, BarcodeAtAttr, FontAttr, ImageAttr, LayoutAttr, } from './attrs';
7
7
  export type { LpdfNode, LpdfContainerNode, LpdfTextNode, LpdfSpanNode, LpdfDividerNode, LpdfImgNode, LpdfBarcodeNode, LpdfTableNode, LpdfTheadNode, LpdfTrNode, LpdfTdNode, LpdfRegionNode, LpdfFieldNode, LpdfBookmarkNode, } from './layout';
8
8
  export { CanvasTransform } from './canvas';
9
- export type { LpdfCanvasLayerNode, LpdfCanvasPrimitiveNode, LpdfCanvasRectNode, LpdfCanvasLineNode, LpdfCanvasEllipseNode, LpdfCanvasCircleNode, LpdfCanvasPathNode, LpdfCanvasTextNode, LpdfCanvasImgNode, } from './canvas';
9
+ export type { LpdfCanvasLayerNode, LpdfCanvasPrimitiveNode, LpdfCanvasRectNode, LpdfCanvasLineNode, LpdfCanvasEllipseNode, LpdfCanvasCircleNode, LpdfCanvasPathNode, LpdfCanvasTextAtNode, LpdfCanvasImgAtNode, LpdfCanvasBarcodeAtNode, } from './canvas';
10
10
  export { L, NoAttr } from './L';
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ Object.defineProperty(exports, "Orientation", { enumerable: true, get: function
13
13
  Object.defineProperty(exports, "SectionType", { enumerable: true, get: function () { return constants_1.SectionType; } });
14
14
  Object.defineProperty(exports, "BuiltinFont", { enumerable: true, get: function () { return constants_1.BuiltinFont; } });
15
15
  Object.defineProperty(exports, "PageScope", { enumerable: true, get: function () { return constants_1.PageScope; } });
16
- // ── Canvas types ──────────────────────────────────────────────────────────────
16
+ // ── Layer types ───────────────────────────────────────────────────────────────
17
17
  var canvas_1 = require("./canvas");
18
18
  Object.defineProperty(exports, "CanvasTransform", { enumerable: true, get: function () { return canvas_1.CanvasTransform; } });
19
19
  // ── Facade ────────────────────────────────────────────────────────────────────
package/dist/kit.d.ts CHANGED
@@ -1,39 +1,54 @@
1
1
  /**
2
2
  * LpdfKit — document skeleton assembly.
3
3
  *
4
- * Assembles sections (containing layout and canvas blocks) into a document
5
- * tree ready for `LpdfEngine.renderPdf()` or `kitToXml()`.
4
+ * Assembles sections (layers and a layout) into a document tree ready for
5
+ * `PdfEngine.render()` or `L.toXml()`. A section holds layers, then at most
6
+ * one layout, then layers: the layers before the layout paint under it, and
7
+ * the layers after it paint over it.
6
8
  *
7
9
  * @example
8
10
  * ```ts
9
- * import { LpdfEngine, LpdfKit, LpdfLayout, LpdfCanvas } from 'lpdf';
11
+ * import { L, NoAttr } from '@lpdfio/lpdf';
10
12
  *
11
- * const doc = LpdfKit.document({
12
- * sections: [
13
- * LpdfKit.section({
14
- * nodes: [
15
- * LpdfKit.canvas([ LpdfCanvas.layer([ LpdfCanvas.rect(0, 0, 595, 842) ]) ]),
16
- * LpdfKit.layout([ LpdfLayout.text(['Hello']) ]),
17
- * ],
18
- * options: { size: 'a4', margin: '28pt' },
19
- * }),
20
- * ],
21
- * options: { meta: { title: 'My Doc' } },
22
- * });
23
- * const bytes = await new LpdfEngine(key).renderPdf(doc);
13
+ * const doc = L.document({ meta: { title: 'My Doc' } }, [
14
+ * L.section({ size: 'a4' }, [
15
+ * L.layer(NoAttr, [ L.rect({ x: '0pt', y: '0pt', width: '595pt', height: '842pt', fill: '#f5f5f5' }) ]),
16
+ * L.layout({ margin: '28pt' }, [ L.text(NoAttr, ['Hello']) ]),
17
+ * ]),
18
+ * ]);
19
+ * const bytes = await L.engine().setLicenseKey(key).render(doc);
24
20
  * ```
25
21
  */
26
22
  import type { LpdfBookmarkNode, LpdfNode } from './layout';
27
23
  import type { LpdfCanvasLayerNode } from './canvas';
28
- import type { FontAttr, ImageAttr } from './attrs';
24
+ import type { FontAttr, ImageAttr, LayoutAttr } from './attrs';
25
+ /** One color of a gradient: `color` is hex or a color token, at an `offset` from `'0%'` to `'100%'`. */
26
+ export interface GradientStop {
27
+ offset: string;
28
+ color: string;
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
+ }
29
42
  export interface DocumentTokens {
30
43
  colors?: Record<string, string>;
44
+ gradients?: Record<string, GradientToken>;
31
45
  space?: Record<string, string>;
32
46
  grid?: Record<string, string>;
33
47
  border?: Record<string, string>;
34
48
  radius?: Record<string, string>;
35
49
  width?: Record<string, string>;
36
50
  textSize?: Record<string, string>;
51
+ lineHeight?: Record<string, string>;
37
52
  }
38
53
  /**
39
54
  * The fonts and images the document declares, as the `assets` element of the XML does. A font or image
@@ -53,7 +68,6 @@ export interface DocumentMeta {
53
68
  export interface SectionAttr {
54
69
  size?: string;
55
70
  orientation?: string;
56
- margin?: string;
57
71
  background?: string;
58
72
  title?: string;
59
73
  debug?: string;
@@ -63,7 +77,6 @@ export interface SectionAttr {
63
77
  export interface DocumentAttr {
64
78
  size?: string;
65
79
  orientation?: string;
66
- margin?: string;
67
80
  background?: string;
68
81
  font?: string;
69
82
  assets?: DocumentAssets;
@@ -74,31 +87,30 @@ export interface DocumentAttr {
74
87
  /** A layout block — wraps an ordered list of layout nodes. */
75
88
  export interface LpdfLayoutBlock {
76
89
  type: 'layout';
90
+ attrs: Record<string, string>;
77
91
  nodes: LpdfNode[];
78
92
  }
79
- /** A canvas block — wraps an ordered list of canvas layers. */
80
- export interface LpdfCanvasBlock {
81
- type: 'canvas';
82
- nodes: LpdfCanvasLayerNode[];
83
- }
84
93
  export interface LpdfSectionNode {
85
94
  type: 'section';
86
95
  attrs: Record<string, string>;
87
- nodes: (LpdfBookmarkNode | LpdfLayoutBlock | LpdfCanvasBlock)[];
96
+ nodes: LpdfSectionChild[];
88
97
  }
98
+ /**
99
+ * What a section holds: a bookmark first, then layers, then at most one layout, then layers. Layers before
100
+ * the layout paint under it, and layers after it paint over it.
101
+ */
102
+ export type LpdfSectionChild = LpdfBookmarkNode | LpdfCanvasLayerNode | LpdfLayoutBlock;
89
103
  export interface PdfDocument {
90
104
  version: 1;
91
105
  type: 'document';
92
106
  attrs: Record<string, unknown>;
93
107
  nodes: LpdfSectionNode[];
94
108
  }
95
- declare function layout(_attrs: null, nodes?: LpdfNode[]): LpdfLayoutBlock;
96
- declare function canvas(_attrs: null, layers?: LpdfCanvasLayerNode[]): LpdfCanvasBlock;
97
- declare function section(attrs: SectionAttr | null, nodes?: (LpdfBookmarkNode | LpdfLayoutBlock | LpdfCanvasBlock)[]): LpdfSectionNode;
109
+ declare function layout(attrs: LayoutAttr | null, nodes?: LpdfNode[]): LpdfLayoutBlock;
110
+ declare function section(attrs: SectionAttr | null, nodes?: LpdfSectionChild[]): LpdfSectionNode;
98
111
  declare function document(attrs: DocumentAttr | null, nodes?: LpdfSectionNode[]): PdfDocument;
99
112
  export declare const LpdfKit: Readonly<{
100
113
  layout: typeof layout;
101
- canvas: typeof canvas;
102
114
  section: typeof section;
103
115
  document: typeof document;
104
116
  }>;
package/dist/kit.js CHANGED
@@ -2,37 +2,30 @@
2
2
  /**
3
3
  * LpdfKit — document skeleton assembly.
4
4
  *
5
- * Assembles sections (containing layout and canvas blocks) into a document
6
- * tree ready for `LpdfEngine.renderPdf()` or `kitToXml()`.
5
+ * Assembles sections (layers and a layout) into a document tree ready for
6
+ * `PdfEngine.render()` or `L.toXml()`. A section holds layers, then at most
7
+ * one layout, then layers: the layers before the layout paint under it, and
8
+ * the layers after it paint over it.
7
9
  *
8
10
  * @example
9
11
  * ```ts
10
- * import { LpdfEngine, LpdfKit, LpdfLayout, LpdfCanvas } from 'lpdf';
12
+ * import { L, NoAttr } from '@lpdfio/lpdf';
11
13
  *
12
- * const doc = LpdfKit.document({
13
- * sections: [
14
- * LpdfKit.section({
15
- * nodes: [
16
- * LpdfKit.canvas([ LpdfCanvas.layer([ LpdfCanvas.rect(0, 0, 595, 842) ]) ]),
17
- * LpdfKit.layout([ LpdfLayout.text(['Hello']) ]),
18
- * ],
19
- * options: { size: 'a4', margin: '28pt' },
20
- * }),
21
- * ],
22
- * options: { meta: { title: 'My Doc' } },
23
- * });
24
- * const bytes = await new LpdfEngine(key).renderPdf(doc);
14
+ * const doc = L.document({ meta: { title: 'My Doc' } }, [
15
+ * L.section({ size: 'a4' }, [
16
+ * L.layer(NoAttr, [ L.rect({ x: '0pt', y: '0pt', width: '595pt', height: '842pt', fill: '#f5f5f5' }) ]),
17
+ * L.layout({ margin: '28pt' }, [ L.text(NoAttr, ['Hello']) ]),
18
+ * ]),
19
+ * ]);
20
+ * const bytes = await L.engine().setLicenseKey(key).render(doc);
25
21
  * ```
26
22
  */
27
23
  Object.defineProperty(exports, "__esModule", { value: true });
28
24
  exports.LpdfKit = void 0;
29
25
  const _shared_1 = require("./_shared");
30
26
  // ── Factory functions ─────────────────────────────────────────────────────────
31
- function layout(_attrs, nodes = []) {
32
- return { type: 'layout', nodes };
33
- }
34
- function canvas(_attrs, layers = []) {
35
- return { type: 'canvas', nodes: layers };
27
+ function layout(attrs, nodes = []) {
28
+ return { type: 'layout', attrs: (0, _shared_1.buildAttrs)(attrs), nodes };
36
29
  }
37
30
  function section(attrs, nodes = []) {
38
31
  return {
@@ -49,8 +42,12 @@ function document(attrs, nodes = []) {
49
42
  if (assets !== undefined)
50
43
  attrsObj['assets'] = assets;
51
44
  if (tokens !== undefined) {
52
- const { textSize, ...rest } = tokens;
53
- attrsObj['tokens'] = textSize !== undefined ? { 'text-size': textSize, ...rest } : rest;
45
+ const { textSize, lineHeight, ...rest } = tokens;
46
+ attrsObj['tokens'] = {
47
+ ...rest,
48
+ ...(textSize !== undefined ? { 'text-size': textSize } : {}),
49
+ ...(lineHeight !== undefined ? { 'line-height': lineHeight } : {}),
50
+ };
54
51
  }
55
52
  if (meta !== undefined)
56
53
  attrsObj['meta'] = meta;
@@ -64,7 +61,6 @@ function document(attrs, nodes = []) {
64
61
  // ── LpdfKit export ────────────────────────────────────────────────────────────
65
62
  exports.LpdfKit = Object.freeze({
66
63
  layout,
67
- canvas,
68
64
  section,
69
65
  document,
70
66
  });
@@ -120,7 +120,7 @@ export class LpdfEngine {
120
120
  }
121
121
  }
122
122
  /**
123
- * Render a JSON kit-tree or canvas-tree document to PDF bytes.
123
+ * Render a JSON kit-tree document to PDF bytes.
124
124
  *
125
125
  * This is the JSON counterpart of `render_pdf`. The Node adapter uses it
126
126
  * when an `LpdfDocument` Kit tree is passed to `renderPdf()`, avoiding an
package/dist/wasm/lpdf.js CHANGED
@@ -120,7 +120,7 @@ class LpdfEngine {
120
120
  }
121
121
  }
122
122
  /**
123
- * Render a JSON kit-tree or canvas-tree document to PDF bytes.
123
+ * Render a JSON kit-tree document to PDF bytes.
124
124
  *
125
125
  * This is the JSON counterpart of `render_pdf`. The Node adapter uses it
126
126
  * when an `LpdfDocument` Kit tree is passed to `renderPdf()`, avoiding an
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lpdfio/lpdf",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "Node.js SDK for Lpdf — PDF as Code on every platform. You describe a document as code or XML. Lpdf renders a compact, pixel-perfect PDF — identical across platforms.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",