@jasy/pdf 1.0.0-alpha.1 → 1.0.0-alpha.3
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 +3 -3
- package/dist/api/args.d.ts +1 -1
- package/dist/api/args.js +2 -5
- package/dist/api/color.d.ts +4 -4
- package/dist/api/color.js +11 -17
- package/dist/api/content.d.ts +8 -8
- package/dist/api/content.js +23 -24
- package/dist/api/descriptor.d.ts +2 -2
- package/dist/api/descriptor.js +75 -31
- package/dist/api/index.d.ts +8 -8
- package/dist/api/index.js +8 -24
- package/dist/api/insets.js +4 -8
- package/dist/api/layout.d.ts +27 -12
- package/dist/api/layout.js +46 -45
- package/dist/api/structure.d.ts +60 -13
- package/dist/api/structure.js +132 -88
- package/dist/api/table.d.ts +5 -5
- package/dist/api/table.js +28 -24
- package/dist/api/text.d.ts +27 -2
- package/dist/api/text.js +45 -27
- package/dist/assets/font-data.d.ts +2 -0
- package/dist/assets/font-data.js +6 -0
- package/dist/assets/font-data.ts +7 -0
- package/dist/common/color.js +1 -5
- package/dist/constants/page-sizes.js +3 -6
- package/dist/constants/pdf-parts.js +1 -4
- package/dist/elements/container-element.d.ts +4 -4
- package/dist/elements/container-element.js +9 -13
- package/dist/elements/image-element.d.ts +18 -2
- package/dist/elements/image-element.js +81 -105
- package/dist/elements/index.d.ts +12 -10
- package/dist/elements/index.js +12 -28
- package/dist/elements/layout/default-text-style-element.d.ts +30 -0
- package/dist/elements/layout/default-text-style-element.js +47 -0
- package/dist/elements/layout/deferred-element.d.ts +3 -3
- package/dist/elements/layout/deferred-element.js +4 -8
- package/dist/elements/layout/expanded-element.d.ts +3 -3
- package/dist/elements/layout/expanded-element.js +10 -14
- package/dist/elements/layout/padding-element.d.ts +3 -3
- package/dist/elements/layout/padding-element.js +9 -14
- package/dist/elements/layout/positioned-element.d.ts +44 -0
- package/dist/elements/layout/positioned-element.js +61 -0
- package/dist/elements/layout/repeating-header-element.d.ts +3 -3
- package/dist/elements/layout/repeating-header-element.js +8 -12
- package/dist/elements/layout/sized-container-element.d.ts +2 -2
- package/dist/elements/layout/sized-container-element.js +6 -11
- package/dist/elements/line-element.d.ts +3 -3
- package/dist/elements/line-element.js +5 -10
- package/dist/elements/page-element.d.ts +8 -6
- package/dist/elements/page-element.js +31 -23
- package/dist/elements/pdf-document-element.d.ts +10 -4
- package/dist/elements/pdf-document-element.js +11 -10
- package/dist/elements/pdf-element.d.ts +28 -3
- package/dist/elements/pdf-element.js +10 -19
- package/dist/elements/rectangle-element.d.ts +14 -6
- package/dist/elements/rectangle-element.js +44 -21
- package/dist/elements/row-element.d.ts +3 -3
- package/dist/elements/row-element.js +7 -11
- package/dist/elements/text-element.d.ts +37 -11
- package/dist/elements/text-element.js +64 -39
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -19
- package/dist/ir/display-list.d.ts +22 -3
- package/dist/ir/display-list.js +1 -2
- package/dist/layout/box-constraints.js +2 -6
- package/dist/layout/fragmentation.d.ts +8 -1
- package/dist/layout/fragmentation.js +22 -10
- package/dist/platform/browser-fs.d.ts +2 -0
- package/dist/platform/browser-fs.js +9 -0
- package/dist/platform/browser-image.d.ts +5 -0
- package/dist/platform/browser-image.js +13 -0
- package/dist/platform/node-fs.d.ts +2 -0
- package/dist/platform/node-fs.js +10 -0
- package/dist/platform/node-image.d.ts +5 -0
- package/dist/platform/node-image.js +9 -0
- package/dist/renderer/container-renderer.d.ts +3 -3
- package/dist/renderer/container-renderer.js +12 -27
- package/dist/renderer/default-text-style-renderer.d.ts +6 -0
- package/dist/renderer/default-text-style-renderer.js +10 -0
- package/dist/renderer/deferred-renderer.d.ts +3 -3
- package/dist/renderer/deferred-renderer.js +8 -23
- package/dist/renderer/expanded-renderer.d.ts +3 -3
- package/dist/renderer/expanded-renderer.js +6 -21
- package/dist/renderer/image-renderer.d.ts +3 -3
- package/dist/renderer/image-renderer.js +77 -75
- package/dist/renderer/index.d.ts +10 -10
- package/dist/renderer/index.js +10 -26
- package/dist/renderer/line-renderer.d.ts +3 -3
- package/dist/renderer/line-renderer.js +13 -28
- package/dist/renderer/padding-renderer.d.ts +3 -3
- package/dist/renderer/padding-renderer.js +6 -21
- package/dist/renderer/page-renderer.d.ts +2 -2
- package/dist/renderer/page-renderer.js +61 -77
- package/dist/renderer/pdf-backend.d.ts +2 -2
- package/dist/renderer/pdf-backend.js +34 -17
- package/dist/renderer/pdf-config.js +4 -7
- package/dist/renderer/pdf-document-class.d.ts +5 -5
- package/dist/renderer/pdf-document-class.js +24 -41
- package/dist/renderer/pdf-document-renderer.d.ts +3 -3
- package/dist/renderer/pdf-document-renderer.js +71 -85
- package/dist/renderer/pdf-renderer.d.ts +2 -2
- package/dist/renderer/pdf-renderer.js +83 -90
- package/dist/renderer/positioned-renderer.d.ts +6 -0
- package/dist/renderer/positioned-renderer.js +10 -0
- package/dist/renderer/rectangle-renderer.d.ts +3 -3
- package/dist/renderer/rectangle-renderer.js +45 -44
- package/dist/renderer/repeating-header-renderer.d.ts +3 -3
- package/dist/renderer/repeating-header-renderer.js +11 -26
- package/dist/renderer/row-renderer.d.ts +3 -3
- package/dist/renderer/row-renderer.js +12 -27
- package/dist/renderer/text-renderer.d.ts +6 -5
- package/dist/renderer/text-renderer.js +33 -42
- package/dist/text/line-breaker.d.ts +8 -5
- package/dist/text/line-breaker.js +67 -16
- package/dist/text/text-style.d.ts +25 -0
- package/dist/text/text-style.js +29 -0
- package/dist/utils/afm-parser.js +3 -13
- package/dist/utils/bytes.d.ts +24 -0
- package/dist/utils/bytes.js +76 -0
- package/dist/utils/flex-layout.d.ts +2 -2
- package/dist/utils/flex-layout.js +15 -20
- package/dist/utils/font-metrics.d.ts +1 -1
- package/dist/utils/font-metrics.js +1 -2
- package/dist/utils/font-path.js +3 -6
- package/dist/utils/image-helper.d.ts +6 -5
- package/dist/utils/image-helper.js +101 -111
- package/dist/utils/md5.d.ts +4 -0
- package/dist/utils/md5.js +80 -0
- package/dist/utils/pdf-object-manager.d.ts +10 -6
- package/dist/utils/pdf-object-manager.js +89 -94
- package/dist/utils/renderer-registry.js +1 -5
- package/dist/utils/ttf-parser.d.ts +2 -2
- package/dist/utils/ttf-parser.js +32 -36
- package/dist/utils/ttf-subsetter.d.ts +1 -1
- package/dist/utils/ttf-subsetter.js +40 -42
- package/dist/utils/utf8-to-windows1252-encoder.js +1 -4
- package/dist/validators/element-validator.d.ts +2 -2
- package/dist/validators/element-validator.js +17 -23
- package/package.json +14 -2
package/README.md
CHANGED
|
@@ -137,9 +137,9 @@ verify all of it:
|
|
|
137
137
|
|
|
138
138
|
| Package | What it is |
|
|
139
139
|
| --- | --- |
|
|
140
|
-
| **[@jasy/zugferd](https://
|
|
141
|
-
| **[@jasy/cli](https://
|
|
142
|
-
| **[@jasy/pdf](https://
|
|
140
|
+
| **[@jasy/zugferd](https://npmx.dev/@jasy/zugferd)** | ZUGFeRD / XRechnung: your data → PDF/A-3 + EN-16931 XML, with local validation. **The prize.** |
|
|
141
|
+
| **[@jasy/cli](https://npmx.dev/@jasy/cli)** | the `jasy` terminal: read · validate · export, headless **and** interactive |
|
|
142
|
+
| **[@jasy/pdf](https://npmx.dev/@jasy/pdf)** | the declarative, Flutter-style PDF layout engine that powers them |
|
|
143
143
|
|
|
144
144
|
---
|
|
145
145
|
|
package/dist/api/args.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PDFElement } from "../elements/pdf-element";
|
|
1
|
+
import { PDFElement } from "../elements/pdf-element.js";
|
|
2
2
|
/**
|
|
3
3
|
* Lets a container factory be called either `F(children)` or `F(opts, children)` - the
|
|
4
4
|
* same ergonomic shape across Document/Page/Column/Row/Box. When the first argument is the
|
package/dist/api/args.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.splitArgs = splitArgs;
|
|
4
1
|
/**
|
|
5
2
|
* Lets a container factory be called either `F(children)` or `F(opts, children)` - the
|
|
6
3
|
* same ergonomic shape across Document/Page/Column/Row/Box. When the first argument is the
|
|
7
4
|
* child array, options default to empty.
|
|
8
5
|
*/
|
|
9
|
-
function splitArgs(a, b) {
|
|
6
|
+
export function splitArgs(a, b) {
|
|
10
7
|
if (Array.isArray(a))
|
|
11
8
|
return { opts: {}, children: a };
|
|
12
|
-
return { opts: a, children: b
|
|
9
|
+
return { opts: a, children: b ?? [] };
|
|
13
10
|
}
|
package/dist/api/color.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { Color } from "../common/color";
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
2
2
|
/**
|
|
3
|
-
* Every way to name a
|
|
3
|
+
* Every way to name a color. The FORM picks the convention, so there is never a guess
|
|
4
4
|
* (locked design §2):
|
|
5
5
|
*
|
|
6
6
|
* | form | example | meaning |
|
|
7
7
|
* |---------------------------|--------------------------|--------------------------------|
|
|
8
|
-
* | named (full CSS set) | `"steelblue"`, `"transparent"` | the ~148 CSS
|
|
8
|
+
* | named (full CSS set) | `"steelblue"`, `"transparent"` | the ~148 CSS color names |
|
|
9
9
|
* | hex 6 / 3 | `"#1450aa"` / `"#14a"` | CSS RGB |
|
|
10
10
|
* | hex 8 / 4 | `"#1450aacc"` / `"#14ac"`| CSS RGBA (alpha LAST) |
|
|
11
11
|
* | number | `0xff1450aa` | Flutter ARGB (alpha FIRST) |
|
|
@@ -19,6 +19,6 @@ export declare function rgb(r: number, g: number, b: number): Color;
|
|
|
19
19
|
export declare function rgba(r: number, g: number, b: number, a: number): Color;
|
|
20
20
|
/**
|
|
21
21
|
* Normalizes any `ColorInput` to an engine `Color`. The single funnel every factory uses,
|
|
22
|
-
* so a
|
|
22
|
+
* so a color means the same thing no matter how it was written.
|
|
23
23
|
*/
|
|
24
24
|
export declare function toColor(input: ColorInput): Color;
|
package/dist/api/color.js
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rgb = rgb;
|
|
4
|
-
exports.rgba = rgba;
|
|
5
|
-
exports.toColor = toColor;
|
|
6
|
-
const color_1 = require("../common/color");
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
7
2
|
/** Channels 0–255, fully opaque. */
|
|
8
|
-
function rgb(r, g, b) {
|
|
9
|
-
return new
|
|
3
|
+
export function rgb(r, g, b) {
|
|
4
|
+
return new Color(r, g, b, 1);
|
|
10
5
|
}
|
|
11
6
|
/** Channels 0–255, alpha 0–1. */
|
|
12
|
-
function rgba(r, g, b, a) {
|
|
13
|
-
return new
|
|
7
|
+
export function rgba(r, g, b, a) {
|
|
8
|
+
return new Color(r, g, b, a);
|
|
14
9
|
}
|
|
15
10
|
/**
|
|
16
11
|
* Normalizes any `ColorInput` to an engine `Color`. The single funnel every factory uses,
|
|
17
|
-
* so a
|
|
12
|
+
* so a color means the same thing no matter how it was written.
|
|
18
13
|
*/
|
|
19
|
-
function toColor(input) {
|
|
20
|
-
|
|
21
|
-
if (input instanceof color_1.Color)
|
|
14
|
+
export function toColor(input) {
|
|
15
|
+
if (input instanceof Color)
|
|
22
16
|
return input;
|
|
23
17
|
if (typeof input === "number")
|
|
24
18
|
return fromArgbNumber(input);
|
|
@@ -27,7 +21,7 @@ function toColor(input) {
|
|
|
27
21
|
return fromHex(s);
|
|
28
22
|
const named = CSS_COLORS[s];
|
|
29
23
|
if (named)
|
|
30
|
-
return new
|
|
24
|
+
return new Color(named[0], named[1], named[2], named[3] ?? 1);
|
|
31
25
|
throw new Error(`Unknown color: "${input}"`);
|
|
32
26
|
}
|
|
33
27
|
/** Flutter ARGB: 0xAARRGGBB, alpha FIRST. A 6-digit number has alpha 0x00 = transparent. */
|
|
@@ -36,7 +30,7 @@ function fromArgbNumber(n) {
|
|
|
36
30
|
const r = (n >>> 16) & 0xff;
|
|
37
31
|
const g = (n >>> 8) & 0xff;
|
|
38
32
|
const b = n & 0xff;
|
|
39
|
-
return new
|
|
33
|
+
return new Color(r, g, b, a / 255);
|
|
40
34
|
}
|
|
41
35
|
/** CSS hex: #RGB, #RGBA, #RRGGBB, #RRGGBBAA. Alpha is LAST. */
|
|
42
36
|
function fromHex(s) {
|
|
@@ -58,7 +52,7 @@ function fromHex(s) {
|
|
|
58
52
|
const a = full.length === 8 ? parseInt(full.slice(6, 8), 16) / 255 : 1;
|
|
59
53
|
if ([r, g, b].some(Number.isNaN))
|
|
60
54
|
throw new Error(`Invalid hex color: "${s}"`);
|
|
61
|
-
return new
|
|
55
|
+
return new Color(r, g, b, a);
|
|
62
56
|
}
|
|
63
57
|
// The full CSS named-color set (~148, incl. the synonyms grey/gray and `transparent`).
|
|
64
58
|
// [r, g, b] or [r, g, b, alpha]. Lower-cased keys; `toColor` lower-cases the input.
|
package/dist/api/content.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ImageElement, CustomImage } from "../elements/image-element";
|
|
2
|
-
import { PDFElement } from "../elements/pdf-element";
|
|
3
|
-
import { ColorInput } from "./color";
|
|
4
|
-
import { Insets } from "./insets";
|
|
1
|
+
import { ImageElement, CustomImage } from "../elements/image-element.js";
|
|
2
|
+
import { PDFElement } from "../elements/pdf-element.js";
|
|
3
|
+
import { ColorInput } from "./color.js";
|
|
4
|
+
import { Insets } from "./insets.js";
|
|
5
5
|
/** A horizontal rule (locked §4). */
|
|
6
6
|
export interface DividerOptions {
|
|
7
|
-
/** Line
|
|
7
|
+
/** Line color (default a light gray). */
|
|
8
8
|
color?: ColorInput;
|
|
9
9
|
/** Line thickness in points (default 1). */
|
|
10
10
|
thickness?: number;
|
|
@@ -14,11 +14,11 @@ export interface DividerOptions {
|
|
|
14
14
|
/**
|
|
15
15
|
* A horizontal rule that spans the parent's width. Maps to a `LineElement` (hiding its
|
|
16
16
|
* `xEnd`/`yEnd` mechanics) wrapped in a `PaddingElement` - the line has no height of its
|
|
17
|
-
* own, so the padding gives it vertical room and
|
|
17
|
+
* own, so the padding gives it vertical room and centers the rule. Use inside a Column.
|
|
18
18
|
*/
|
|
19
19
|
export declare function Divider(opts?: DividerOptions): PDFElement;
|
|
20
|
-
/** An image source: a local file path,
|
|
21
|
-
export type ImageSource = string | CustomImage;
|
|
20
|
+
/** An image source: a local file path (Node), raw bytes (e.g. a browser fetch/upload), or a `CustomImage`. */
|
|
21
|
+
export type ImageSource = string | Uint8Array | CustomImage;
|
|
22
22
|
/** How the image fills its box (locked §4). Mirrors CSS `object-fit`. */
|
|
23
23
|
export type ImageFit = "none" | "contain" | "cover" | "fill";
|
|
24
24
|
export interface ImageOptions {
|
package/dist/api/content.js
CHANGED
|
@@ -1,47 +1,46 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const padding_element_1 = require("../elements/layout/padding-element");
|
|
7
|
-
const image_element_1 = require("../elements/image-element");
|
|
8
|
-
const color_1 = require("./color");
|
|
9
|
-
const insets_1 = require("./insets");
|
|
1
|
+
import { LineElement } from "../elements/line-element.js";
|
|
2
|
+
import { PaddingElement } from "../elements/layout/padding-element.js";
|
|
3
|
+
import { ImageElement, CustomLocalImage, CustomBytesImage, BoxFit, } from "../elements/image-element.js";
|
|
4
|
+
import { toColor } from "./color.js";
|
|
5
|
+
import { toEdges } from "./insets.js";
|
|
10
6
|
const DEFAULT_DIVIDER_COLOR = "lightgray";
|
|
11
7
|
const DEFAULT_DIVIDER_MARGIN = { y: 6 };
|
|
12
8
|
/**
|
|
13
9
|
* A horizontal rule that spans the parent's width. Maps to a `LineElement` (hiding its
|
|
14
10
|
* `xEnd`/`yEnd` mechanics) wrapped in a `PaddingElement` - the line has no height of its
|
|
15
|
-
* own, so the padding gives it vertical room and
|
|
11
|
+
* own, so the padding gives it vertical room and centers the rule. Use inside a Column.
|
|
16
12
|
*/
|
|
17
|
-
function Divider(opts = {}) {
|
|
18
|
-
|
|
19
|
-
const line = new line_element_1.LineElement({
|
|
13
|
+
export function Divider(opts = {}) {
|
|
14
|
+
const line = new LineElement({
|
|
20
15
|
x: 0,
|
|
21
16
|
y: 0,
|
|
22
17
|
xEnd: 0, // resolved to the parent's width at layout time
|
|
23
18
|
yEnd: 0, // horizontal: no vertical span
|
|
24
|
-
color:
|
|
25
|
-
strokeWidth:
|
|
19
|
+
color: toColor(opts.color ?? DEFAULT_DIVIDER_COLOR),
|
|
20
|
+
strokeWidth: opts.thickness ?? 1,
|
|
26
21
|
});
|
|
27
|
-
return new
|
|
28
|
-
margin:
|
|
22
|
+
return new PaddingElement({
|
|
23
|
+
margin: toEdges(opts.margin ?? DEFAULT_DIVIDER_MARGIN),
|
|
29
24
|
child: line,
|
|
30
25
|
});
|
|
31
26
|
}
|
|
32
27
|
const FIT = {
|
|
33
|
-
none:
|
|
34
|
-
contain:
|
|
35
|
-
cover:
|
|
36
|
-
fill:
|
|
28
|
+
none: BoxFit.none,
|
|
29
|
+
contain: BoxFit.contain,
|
|
30
|
+
cover: BoxFit.cover,
|
|
31
|
+
fill: BoxFit.fill,
|
|
37
32
|
};
|
|
38
33
|
/**
|
|
39
34
|
* An image. `src` is a local file path (wrapped in a `CustomLocalImage`) or a ready
|
|
40
35
|
* `CustomImage` for non-filesystem sources. Maps to an `ImageElement`.
|
|
41
36
|
*/
|
|
42
|
-
function Image(src, opts = {}) {
|
|
43
|
-
return new
|
|
44
|
-
image: typeof src === "string"
|
|
37
|
+
export function Image(src, opts = {}) {
|
|
38
|
+
return new ImageElement({
|
|
39
|
+
image: typeof src === "string"
|
|
40
|
+
? new CustomLocalImage(src)
|
|
41
|
+
: src instanceof Uint8Array
|
|
42
|
+
? new CustomBytesImage(src)
|
|
43
|
+
: src,
|
|
45
44
|
width: opts.width,
|
|
46
45
|
height: opts.height,
|
|
47
46
|
fit: opts.fit ? FIT[opts.fit] : undefined,
|
package/dist/api/descriptor.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PDFElement } from "../elements/pdf-element";
|
|
2
|
-
import { PDFDocumentElement } from "../elements/pdf-document-element";
|
|
1
|
+
import { PDFElement } from "../elements/pdf-element.js";
|
|
2
|
+
import { PDFDocumentElement } from "../elements/pdf-document-element.js";
|
|
3
3
|
/**
|
|
4
4
|
* The framework-agnostic contract (the firewall). A binding (Vue/React, or any tree-builder)
|
|
5
5
|
* produces a tree of these plain descriptors; `build` turns each node into an engine element
|
package/dist/api/descriptor.js
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const text_1 = require("./text");
|
|
7
|
-
const layout_1 = require("./layout");
|
|
8
|
-
const content_1 = require("./content");
|
|
9
|
-
const structure_1 = require("./structure");
|
|
1
|
+
import { Text, Paragraph, span } from "./text.js";
|
|
2
|
+
import { Column, Row, Box, Padding, Spacer, Expanded, Positioned } from "./layout.js";
|
|
3
|
+
import { Divider, Image } from "./content.js";
|
|
4
|
+
import { Page, Document, DefaultTextStyle } from "./structure.js";
|
|
5
|
+
import { Table } from "./table.js";
|
|
10
6
|
// Element children (Column/Row/Box/Page/…) → built recursively. Text/Paragraph children are
|
|
11
7
|
// strings or `span` descriptors and become content instead.
|
|
12
8
|
function elementChildren(children) {
|
|
13
9
|
return children.map(build);
|
|
14
10
|
}
|
|
15
11
|
function textOf(node) {
|
|
16
|
-
var _a;
|
|
17
12
|
if (typeof node === "string")
|
|
18
13
|
return node;
|
|
19
|
-
const first =
|
|
14
|
+
const first = node.children?.[0];
|
|
20
15
|
return typeof first === "string" ? first : "";
|
|
21
16
|
}
|
|
22
17
|
function toSegment(c) {
|
|
23
18
|
if (typeof c === "string")
|
|
24
|
-
return
|
|
19
|
+
return span(c);
|
|
25
20
|
if (c.type === "span")
|
|
26
|
-
return
|
|
21
|
+
return span(textOf(c), c.props);
|
|
27
22
|
throw new Error(`A Text child must be a string or a span, got "${c.type}"`);
|
|
28
23
|
}
|
|
29
24
|
function textContent(children) {
|
|
@@ -31,40 +26,89 @@ function textContent(children) {
|
|
|
31
26
|
return children[0];
|
|
32
27
|
return children.map(toSegment);
|
|
33
28
|
}
|
|
29
|
+
// A `<TableCell>`'s content → a `Cell`: a lone string stays a string (the table wraps it in Text);
|
|
30
|
+
// otherwise its children are built (a single element, or a Column of several).
|
|
31
|
+
function buildCell(cell) {
|
|
32
|
+
if (typeof cell === "string")
|
|
33
|
+
return cell;
|
|
34
|
+
const kids = cell.children ?? [];
|
|
35
|
+
if (kids.length === 1 && typeof kids[0] === "string")
|
|
36
|
+
return kids[0];
|
|
37
|
+
if (kids.length === 0)
|
|
38
|
+
return "";
|
|
39
|
+
const els = kids.map(build);
|
|
40
|
+
return els.length === 1 ? els[0] : Column(els);
|
|
41
|
+
}
|
|
42
|
+
// A `<TableRow>`'s `<TableCell>` children → one row of `Cell`s.
|
|
43
|
+
function rowCells(row) {
|
|
44
|
+
return (row.children ?? [])
|
|
45
|
+
.filter((c) => typeof c !== "string" && c.type === "table-cell")
|
|
46
|
+
.map(buildCell);
|
|
47
|
+
}
|
|
48
|
+
// A `#header` / `#footer` slot's content → one element (a Column if it holds several; strings → Text).
|
|
49
|
+
function slotElement(node) {
|
|
50
|
+
const els = (node.children ?? []).map((c) => (typeof c === "string" ? Text(c) : build(c)));
|
|
51
|
+
return els.length === 1 ? els[0] : Column(els);
|
|
52
|
+
}
|
|
34
53
|
const REGISTRY = {
|
|
35
|
-
document: (props, children) =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
document: (props, children) => {
|
|
55
|
+
const doc = Document(props, elementChildren(children));
|
|
56
|
+
// A binding can register fonts declaratively: `fonts: { Name: bytes | path | family }`.
|
|
57
|
+
if (props.fonts) {
|
|
58
|
+
for (const [name, src] of Object.entries(props.fonts))
|
|
59
|
+
doc.addFont(name, src);
|
|
60
|
+
}
|
|
61
|
+
return doc;
|
|
62
|
+
},
|
|
63
|
+
page: (props, children) => {
|
|
64
|
+
// `#header` / `#footer` arrive as `page-header` / `page-footer` marker children (read raw); the rest
|
|
65
|
+
// is the body. Both repeat on every physical page the body paginates onto.
|
|
66
|
+
const slot = (type) => {
|
|
67
|
+
const m = children.find((c) => typeof c !== "string" && c.type === type);
|
|
68
|
+
return m ? slotElement(m) : undefined;
|
|
69
|
+
};
|
|
70
|
+
const body = children.filter((c) => typeof c === "string" || (c.type !== "page-header" && c.type !== "page-footer"));
|
|
71
|
+
return Page({ ...props, header: slot("page-header"), footer: slot("page-footer") }, elementChildren(body));
|
|
72
|
+
},
|
|
73
|
+
column: (props, children) => Column(props, elementChildren(children)),
|
|
74
|
+
row: (props, children) => Row(props, elementChildren(children)),
|
|
75
|
+
box: (props, children) => Box(props, elementChildren(children)),
|
|
76
|
+
padding: (props, children) => Padding(props.insets ?? 0, elementChildren(children)[0]),
|
|
77
|
+
expanded: (props, children) => Expanded(props, elementChildren(children)[0]),
|
|
78
|
+
spacer: (props) => Spacer(props?.flex),
|
|
79
|
+
divider: (props) => Divider(props),
|
|
80
|
+
image: (props) => Image(props.src, props),
|
|
81
|
+
text: (props, children) => Text(textContent(children), props),
|
|
82
|
+
paragraph: (props, children) => Paragraph(textContent(children), props),
|
|
83
|
+
// `<Table>` reads its `<TableRow>`/`<TableCell>` structure raw; one row may be marked `header`.
|
|
84
|
+
table: (props, children) => {
|
|
85
|
+
const rows = children.filter((c) => typeof c !== "string" && c.type === "table-row");
|
|
86
|
+
const header = rows.find((r) => r.props?.header);
|
|
87
|
+
const body = rows.filter((r) => !r.props?.header);
|
|
88
|
+
return Table({ ...props, header: header ? rowCells(header) : undefined }, body.map(rowCells));
|
|
89
|
+
},
|
|
90
|
+
positioned: (props, children) => Positioned(props, elementChildren(children)[0]),
|
|
91
|
+
"default-text-style": (props, children) => DefaultTextStyle(props, elementChildren(children)),
|
|
47
92
|
};
|
|
48
93
|
/**
|
|
49
94
|
* Registers a custom element type, so a binding (or a user-defined component) can introduce
|
|
50
95
|
* its own tag that resolves to an engine element through this same seam. Overwrites an
|
|
51
96
|
* existing type of the same name.
|
|
52
97
|
*/
|
|
53
|
-
function registerElement(type, factory) {
|
|
98
|
+
export function registerElement(type, factory) {
|
|
54
99
|
REGISTRY[type] = factory;
|
|
55
100
|
}
|
|
56
101
|
/** Turns one descriptor node (or bare string → `Text`) into an engine element. */
|
|
57
|
-
function build(node) {
|
|
58
|
-
var _a, _b;
|
|
102
|
+
export function build(node) {
|
|
59
103
|
if (typeof node === "string")
|
|
60
|
-
return
|
|
104
|
+
return Text(node);
|
|
61
105
|
const factory = REGISTRY[node.type];
|
|
62
106
|
if (!factory)
|
|
63
107
|
throw new Error(`Unknown element type: "${node.type}"`);
|
|
64
|
-
return factory(
|
|
108
|
+
return factory(node.props ?? {}, node.children ?? []);
|
|
65
109
|
}
|
|
66
110
|
/** Builds a descriptor tree whose root is a `document` into the renderable root element. */
|
|
67
|
-
function buildDocument(root) {
|
|
111
|
+
export function buildDocument(root) {
|
|
68
112
|
if (root.type !== "document")
|
|
69
113
|
throw new Error(`Expected a "document" root, got "${root.type}"`);
|
|
70
114
|
return build(root);
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from "./color";
|
|
2
|
-
export * from "./insets";
|
|
3
|
-
export * from "./text";
|
|
4
|
-
export * from "./layout";
|
|
5
|
-
export * from "./content";
|
|
6
|
-
export * from "./structure";
|
|
7
|
-
export * from "./table";
|
|
8
|
-
export * from "./descriptor";
|
|
1
|
+
export * from "./color.js";
|
|
2
|
+
export * from "./insets.js";
|
|
3
|
+
export * from "./text.js";
|
|
4
|
+
export * from "./layout.js";
|
|
5
|
+
export * from "./content.js";
|
|
6
|
+
export * from "./structure.js";
|
|
7
|
+
export * from "./table.js";
|
|
8
|
+
export * from "./descriptor.js";
|
package/dist/api/index.js
CHANGED
|
@@ -1,27 +1,11 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
1
|
// The intuitive API layer: declarative factory functions + input normalizers that compile
|
|
18
2
|
// down to the core engine elements. A thin, curated surface ON TOP of the engine - the
|
|
19
3
|
// core classes stay untouched and remain exported for power users.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
4
|
+
export * from "./color.js";
|
|
5
|
+
export * from "./insets.js";
|
|
6
|
+
export * from "./text.js";
|
|
7
|
+
export * from "./layout.js";
|
|
8
|
+
export * from "./content.js";
|
|
9
|
+
export * from "./structure.js";
|
|
10
|
+
export * from "./table.js";
|
|
11
|
+
export * from "./descriptor.js";
|
package/dist/api/insets.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toEdges = toEdges;
|
|
4
1
|
/** Normalizes any `Insets` to the engine's `[top, right, bottom, left]`. */
|
|
5
|
-
function toEdges(i) {
|
|
6
|
-
var _a, _b, _c, _d, _e, _f;
|
|
2
|
+
export function toEdges(i) {
|
|
7
3
|
if (typeof i === "number")
|
|
8
4
|
return [i, i, i, i];
|
|
9
5
|
if (Array.isArray(i))
|
|
@@ -13,9 +9,9 @@ function toEdges(i) {
|
|
|
13
9
|
// axis interpretation (an empty object is all-zero either way).
|
|
14
10
|
const o = i;
|
|
15
11
|
if (o.x !== undefined || o.y !== undefined) {
|
|
16
|
-
const x =
|
|
17
|
-
const y =
|
|
12
|
+
const x = o.x ?? 0;
|
|
13
|
+
const y = o.y ?? 0;
|
|
18
14
|
return [y, x, y, x];
|
|
19
15
|
}
|
|
20
|
-
return [
|
|
16
|
+
return [o.top ?? 0, o.right ?? 0, o.bottom ?? 0, o.left ?? 0];
|
|
21
17
|
}
|
package/dist/api/layout.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { ContainerElement } from "../elements/container-element";
|
|
2
|
-
import { RowElement } from "../elements/row-element";
|
|
3
|
-
import { RectangleElement } from "../elements/rectangle-element";
|
|
4
|
-
import { ExpandedElement } from "../elements/layout/expanded-element";
|
|
5
|
-
import { PaddingElement } from "../elements/layout/padding-element";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { ContainerElement } from "../elements/container-element.js";
|
|
2
|
+
import { RowElement } from "../elements/row-element.js";
|
|
3
|
+
import { RectangleElement } from "../elements/rectangle-element.js";
|
|
4
|
+
import { ExpandedElement } from "../elements/layout/expanded-element.js";
|
|
5
|
+
import { PaddingElement } from "../elements/layout/padding-element.js";
|
|
6
|
+
import { PositionedElement, PositionedInsets } from "../elements/layout/positioned-element.js";
|
|
7
|
+
import { PDFElement } from "../elements/pdf-element.js";
|
|
8
|
+
import { MainAlign, CrossAlign } from "../utils/flex-layout.js";
|
|
9
|
+
import { ColorInput } from "./color.js";
|
|
10
|
+
import { Insets } from "./insets.js";
|
|
10
11
|
/** Options shared by the `Column` and `Row` stacks (locked §4). */
|
|
11
12
|
export interface StackOptions {
|
|
12
13
|
/** Space inserted between children, in points. */
|
|
@@ -25,9 +26,9 @@ export declare function Row(children: PDFElement[]): RowElement;
|
|
|
25
26
|
export declare function Row(opts: StackOptions, children: PDFElement[]): RowElement;
|
|
26
27
|
/** A bordered / filled box that wraps its children (locked §4). */
|
|
27
28
|
export interface BoxOptions {
|
|
28
|
-
/** Border (stroke)
|
|
29
|
+
/** Border (stroke) color. A box has a border only when `border` or `borderWidth` is set. */
|
|
29
30
|
border?: ColorInput;
|
|
30
|
-
/** Per-side border
|
|
31
|
+
/** Per-side border colors - override/add to `border`. Any of these makes the box draw
|
|
31
32
|
* individual side lines (sharp corners) instead of a uniform frame - this is how you get
|
|
32
33
|
* grid lines (e.g. a cell with only `borderBottom` + `borderRight`). */
|
|
33
34
|
borderTop?: ColorInput;
|
|
@@ -36,7 +37,7 @@ export interface BoxOptions {
|
|
|
36
37
|
borderLeft?: ColorInput;
|
|
37
38
|
/** Border thickness in points (default 1 when a border is present). */
|
|
38
39
|
borderWidth?: number;
|
|
39
|
-
/** Background fill
|
|
40
|
+
/** Background fill color. */
|
|
40
41
|
bg?: ColorInput;
|
|
41
42
|
/** Inner padding between the border and the children. */
|
|
42
43
|
padding?: Insets;
|
|
@@ -45,6 +46,12 @@ export interface BoxOptions {
|
|
|
45
46
|
height?: number;
|
|
46
47
|
/** Corner radius in points. */
|
|
47
48
|
radius?: number;
|
|
49
|
+
/** Make this box a positioning frame: `Positioned` children placed inside it resolve their
|
|
50
|
+
* offsets against this box (CSS `position: relative`). */
|
|
51
|
+
relative?: boolean;
|
|
52
|
+
/** `"hidden"` crops children to the box (rounded corners included); `"visible"` (default) lets a
|
|
53
|
+
* `Positioned` child spill over the edge. */
|
|
54
|
+
overflow?: "hidden" | "visible";
|
|
48
55
|
}
|
|
49
56
|
/**
|
|
50
57
|
* A box: maps to a `RectangleElement` (fill + border + radius) whose children are stacked
|
|
@@ -55,6 +62,14 @@ export declare function Box(children: PDFElement[]): RectangleElement;
|
|
|
55
62
|
export declare function Box(opts: BoxOptions, children: PDFElement[]): RectangleElement;
|
|
56
63
|
/** Insets a single child by `padding` (a number / `{x,y}` / `{top,…}` / 4-tuple). */
|
|
57
64
|
export declare function Padding(padding: Insets, child: PDFElement): PaddingElement;
|
|
65
|
+
/**
|
|
66
|
+
* Places a child OUT OF FLOW, relative to the nearest enclosing `relative` Box. Two ways, pick per
|
|
67
|
+
* axis: pin to EDGES - `Positioned({ top, left, right, bottom }, child)`, where a negative value
|
|
68
|
+
* pokes into / out of the corner (a badge, a tab, a ribbon) and pinning both sides stretches; or
|
|
69
|
+
* ANCHOR + nudge - `Positioned({ h: "center", v: "end", x: -10, y: -8 }, child)`, i.e. centered /
|
|
70
|
+
* end-aligned with a pixel offset. An edge wins over an anchor on the same axis.
|
|
71
|
+
*/
|
|
72
|
+
export declare function Positioned(opts: PositionedInsets, child: PDFElement): PositionedElement;
|
|
58
73
|
/**
|
|
59
74
|
* A flexible empty gap that pushes its siblings apart - `Row([a, Spacer(), b])` sends `a`
|
|
60
75
|
* and `b` to the edges. `flex` weights it against other flex children (default 1).
|