@jasy/pdf 1.0.0-alpha.2 → 1.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -14
- 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 +18 -16
- package/dist/api/layout.js +41 -52
- package/dist/api/structure.d.ts +65 -13
- package/dist/api/structure.js +140 -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 +21 -0
- package/dist/assets/font-data.ts +37 -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/crypto/security-handler.d.ts +46 -0
- package/dist/crypto/security-handler.js +129 -0
- package/dist/crypto/webcrypto.d.ts +11 -0
- package/dist/crypto/webcrypto.js +62 -0
- 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 -11
- package/dist/elements/index.js +12 -29
- 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 +17 -4
- package/dist/elements/layout/positioned-element.js +29 -25
- 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 +20 -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 +12 -3
- package/dist/elements/pdf-element.js +10 -19
- package/dist/elements/rectangle-element.d.ts +5 -5
- package/dist/elements/rectangle-element.js +19 -25
- 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 +4 -2
- 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 +21 -19
- 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 +85 -93
- package/dist/renderer/positioned-renderer.d.ts +3 -3
- package/dist/renderer/positioned-renderer.js +8 -23
- package/dist/renderer/rectangle-renderer.d.ts +3 -3
- package/dist/renderer/rectangle-renderer.js +45 -52
- 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 +79 -0
- package/dist/utils/pdf-object-manager.d.ts +18 -6
- package/dist/utils/pdf-object-manager.js +0 -0
- 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 +9 -13
- package/package.json +14 -2
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.layoutPageBands = layoutPageBands;
|
|
6
|
-
const page_sizes_1 = require("../constants/page-sizes");
|
|
7
|
-
const pdf_config_1 = require("../renderer/pdf-config");
|
|
8
|
-
const box_constraints_1 = require("../layout/box-constraints");
|
|
9
|
-
const pdf_element_1 = require("./pdf-element");
|
|
1
|
+
import { pageFormats } from "../constants/page-sizes.js";
|
|
2
|
+
import { Orientation } from "../renderer/pdf-config.js";
|
|
3
|
+
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
4
|
+
import { PDFElement } from "./pdf-element.js";
|
|
10
5
|
/**
|
|
11
6
|
* The content box of a page (inside the margins, orientation applied) for a fully
|
|
12
7
|
* resolved config. Single source of truth, shared by `PageElement` layout and the page
|
|
13
8
|
* driver so they can never drift.
|
|
14
9
|
*/
|
|
15
|
-
function resolvePageContentBox(config) {
|
|
10
|
+
export function resolvePageContentBox(config) {
|
|
16
11
|
const margin = config.margin;
|
|
17
|
-
|
|
18
|
-
let
|
|
19
|
-
|
|
12
|
+
const [pageW, pageH] = config.customSize ?? pageFormats[config.pageSize];
|
|
13
|
+
let width = pageW - margin.left - margin.right;
|
|
14
|
+
let height = pageH - margin.top - margin.bottom;
|
|
15
|
+
if (config.orientation === Orientation.landscape) {
|
|
20
16
|
[width, height] = [height, width];
|
|
21
17
|
}
|
|
22
18
|
return { origin: { x: margin.left, y: margin.top }, width, height };
|
|
@@ -29,17 +25,17 @@ function resolvePageContentBox(config) {
|
|
|
29
25
|
* no header/footer the bands are zero and the body equals the full content box - identical
|
|
30
26
|
* to a page without them.
|
|
31
27
|
*/
|
|
32
|
-
function layoutPageBands(config, header, footer, ctx) {
|
|
28
|
+
export function layoutPageBands(config, header, footer, ctx) {
|
|
33
29
|
const { origin, width, height } = resolvePageContentBox(config);
|
|
34
30
|
let headerHeight = 0;
|
|
35
31
|
if (header) {
|
|
36
|
-
headerHeight = header.calculateLayout(
|
|
32
|
+
headerHeight = header.calculateLayout(BoxConstraints.loose(width, Infinity), origin, ctx).height;
|
|
37
33
|
}
|
|
38
34
|
let footerHeight = 0;
|
|
39
35
|
if (footer) {
|
|
40
36
|
// Measure first to learn its height, then place it flush against the bottom edge.
|
|
41
|
-
footerHeight = footer.calculateLayout(
|
|
42
|
-
footer.calculateLayout(
|
|
37
|
+
footerHeight = footer.calculateLayout(BoxConstraints.loose(width, Infinity), origin, ctx).height;
|
|
38
|
+
footer.calculateLayout(BoxConstraints.loose(width, Infinity), { x: origin.x, y: origin.y + height - footerHeight }, ctx);
|
|
43
39
|
}
|
|
44
40
|
return {
|
|
45
41
|
bodyOrigin: { x: origin.x, y: origin.y + headerHeight },
|
|
@@ -49,11 +45,11 @@ function layoutPageBands(config, header, footer, ctx) {
|
|
|
49
45
|
footerHeight,
|
|
50
46
|
};
|
|
51
47
|
}
|
|
52
|
-
class PageElement extends
|
|
48
|
+
export class PageElement extends PDFElement {
|
|
53
49
|
constructor({ children, config, header, footer }) {
|
|
54
50
|
super();
|
|
55
51
|
this.children = children;
|
|
56
|
-
this.config = config
|
|
52
|
+
this.config = config ?? {};
|
|
57
53
|
this.header = header;
|
|
58
54
|
this.footer = footer;
|
|
59
55
|
}
|
|
@@ -61,15 +57,17 @@ class PageElement extends pdf_element_1.PDFElement {
|
|
|
61
57
|
// Merge the document defaults (carried in the context) with this page's overrides,
|
|
62
58
|
// then hand descendants a context bound to THIS page's geometry. This is what
|
|
63
59
|
// fixes the old last-page-wins global page-config bug.
|
|
64
|
-
this.config =
|
|
60
|
+
this.config = { ...ctx.pageConfig, ...this.config };
|
|
65
61
|
const pageCtx = {
|
|
66
62
|
metrics: ctx.metrics,
|
|
67
63
|
pageConfig: this.config,
|
|
64
|
+
textStyle: ctx.textStyle,
|
|
65
|
+
onOverflow: ctx.onOverflow,
|
|
68
66
|
};
|
|
69
67
|
// Place the header/footer bands; the body gets the region left in between (the whole
|
|
70
68
|
// content box when there is neither - byte-identical to a plain page).
|
|
71
69
|
const bands = layoutPageBands(this.config, this.header, this.footer, pageCtx);
|
|
72
|
-
const childConstraints =
|
|
70
|
+
const childConstraints = BoxConstraints.loose(bands.bodyWidth, bands.bodyHeight);
|
|
73
71
|
// The page body is itself a positioning frame: a `Positioned` with no `relative` ancestor
|
|
74
72
|
// resolves against the content box (a `relative` Box overrides it for its own subtree). Drained
|
|
75
73
|
// after the body is laid out, so a page-level Positioned isn't a silent no-op.
|
|
@@ -78,7 +76,7 @@ class PageElement extends pdf_element_1.PDFElement {
|
|
|
78
76
|
size: { width: bands.bodyWidth, height: bands.bodyHeight },
|
|
79
77
|
place: [],
|
|
80
78
|
};
|
|
81
|
-
const bodyCtx =
|
|
79
|
+
const bodyCtx = { ...pageCtx, frame };
|
|
82
80
|
this.children.forEach((child) => child.calculateLayout(childConstraints, bands.bodyOrigin, bodyCtx));
|
|
83
81
|
for (const place of frame.place)
|
|
84
82
|
place(frame, pageCtx);
|
|
@@ -98,4 +96,3 @@ class PageElement extends pdf_element_1.PDFElement {
|
|
|
98
96
|
return this;
|
|
99
97
|
}
|
|
100
98
|
}
|
|
101
|
-
exports.PageElement = PageElement;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { PageElement } from "./page-element";
|
|
2
|
-
import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
|
|
3
|
-
import { LayoutContext, PDFElement, WithChildren } from "./pdf-element";
|
|
1
|
+
import { PageElement } from "./page-element.js";
|
|
2
|
+
import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
|
|
3
|
+
import { LayoutContext, PDFElement, WithChildren } from "./pdf-element.js";
|
|
4
|
+
import type { ResolvedTextStyle } from "../text/text-style.js";
|
|
4
5
|
interface PDFDocumentParams extends WithChildren {
|
|
5
6
|
children: PageElement[];
|
|
7
|
+
/** Document-level text defaults descendants inherit (seeded into the layout-context root). */
|
|
8
|
+
defaultTextStyle?: Partial<ResolvedTextStyle>;
|
|
6
9
|
}
|
|
7
10
|
export declare class PDFDocumentElement extends PDFElement {
|
|
8
11
|
private children;
|
|
9
|
-
|
|
12
|
+
private defaultTextStyle?;
|
|
13
|
+
constructor({ children, defaultTextStyle }: PDFDocumentParams);
|
|
14
|
+
/** The document-level text defaults; the renderer merges them into the cascade root. */
|
|
15
|
+
getDefaultTextStyle(): Partial<ResolvedTextStyle> | undefined;
|
|
10
16
|
calculateLayout(_constraints: BoxConstraints, _offset: Offset, ctx: LayoutContext): Size;
|
|
11
17
|
getProps(): PDFDocumentParams;
|
|
12
18
|
}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const pdf_element_1 = require("./pdf-element");
|
|
6
|
-
class PDFDocumentElement extends pdf_element_1.PDFElement {
|
|
7
|
-
constructor({ children }) {
|
|
1
|
+
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
2
|
+
import { PDFElement } from "./pdf-element.js";
|
|
3
|
+
export class PDFDocumentElement extends PDFElement {
|
|
4
|
+
constructor({ children, defaultTextStyle }) {
|
|
8
5
|
super();
|
|
9
6
|
this.children = children;
|
|
7
|
+
this.defaultTextStyle = defaultTextStyle;
|
|
8
|
+
}
|
|
9
|
+
/** The document-level text defaults; the renderer merges them into the cascade root. */
|
|
10
|
+
getDefaultTextStyle() {
|
|
11
|
+
return this.defaultTextStyle;
|
|
10
12
|
}
|
|
11
13
|
calculateLayout(_constraints, _offset, ctx) {
|
|
12
14
|
// The document is the root: each page derives its own geometry, so it ignores the
|
|
13
15
|
// incoming constraints/offset. It has no size of its own.
|
|
14
16
|
const origin = { x: 0, y: 0 };
|
|
15
|
-
this.children.forEach((child) => child.calculateLayout(new
|
|
17
|
+
this.children.forEach((child) => child.calculateLayout(new BoxConstraints(), origin, ctx));
|
|
16
18
|
return { width: 0, height: 0 };
|
|
17
19
|
}
|
|
18
20
|
getProps() {
|
|
19
|
-
return { children: this.children };
|
|
21
|
+
return { children: this.children, defaultTextStyle: this.defaultTextStyle };
|
|
20
22
|
}
|
|
21
23
|
}
|
|
22
|
-
exports.PDFDocumentElement = PDFDocumentElement;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import type { FontMetrics } from "../utils/font-metrics";
|
|
2
|
-
import type { PDFPageConfig } from "./page-element";
|
|
3
|
-
import type {
|
|
1
|
+
import type { FontMetrics } from "../utils/font-metrics.js";
|
|
2
|
+
import type { PDFPageConfig } from "./page-element.js";
|
|
3
|
+
import type { ResolvedTextStyle } from "../text/text-style.js";
|
|
4
|
+
import type { OverflowPolicy } from "../layout/fragmentation.js";
|
|
5
|
+
import type { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
|
|
4
6
|
/**
|
|
5
7
|
* Everything the layout pass needs, threaded explicitly (no global singleton):
|
|
6
8
|
* font metrics for measuring, and the geometry of the page currently being laid out.
|
|
@@ -26,6 +28,13 @@ export interface LayoutContext {
|
|
|
26
28
|
pageConfig: PDFPageConfig;
|
|
27
29
|
/** The nearest enclosing positioning frame, if any (set by a `relative` Box). */
|
|
28
30
|
frame?: PositioningFrame;
|
|
31
|
+
/** The cascaded text style descendants inherit (CSS/Flutter-style). Seeded at the document root
|
|
32
|
+
* from the built-in defaults + the `Document` defaults, and carried through page contexts; a
|
|
33
|
+
* `Text` resolves its own unset properties against it. Absent falls back to the built-in defaults. */
|
|
34
|
+
textStyle?: ResolvedTextStyle;
|
|
35
|
+
/** What to do when an element overflows a page region and cannot break (set from the render option;
|
|
36
|
+
* absent = clip silently). Evaluated in `packChildren` where the forced placement happens. */
|
|
37
|
+
onOverflow?: OverflowPolicy;
|
|
29
38
|
}
|
|
30
39
|
export declare abstract class PDFElement {
|
|
31
40
|
abstract getProps(): unknown;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VerticalAlignment = exports.HorizontalAlignment = exports.FlexiblePDFElement = exports.SizedPDFElement = exports.PDFElement = void 0;
|
|
4
|
-
exports.isSizedElement = isSizedElement;
|
|
5
|
-
exports.hasChildrenProp = hasChildrenProp;
|
|
6
|
-
exports.hasChildProp = hasChildProp;
|
|
7
|
-
class PDFElement {
|
|
1
|
+
export class PDFElement {
|
|
8
2
|
}
|
|
9
|
-
|
|
10
|
-
class SizedPDFElement extends PDFElement {
|
|
3
|
+
export class SizedPDFElement extends PDFElement {
|
|
11
4
|
constructor(data) {
|
|
12
5
|
super();
|
|
13
6
|
this.x = data.x;
|
|
@@ -19,8 +12,7 @@ class SizedPDFElement extends PDFElement {
|
|
|
19
12
|
return { x: this.x, y: this.y, width: this.width, height: this.height };
|
|
20
13
|
}
|
|
21
14
|
}
|
|
22
|
-
|
|
23
|
-
class FlexiblePDFElement extends PDFElement {
|
|
15
|
+
export class FlexiblePDFElement extends PDFElement {
|
|
24
16
|
constructor(data) {
|
|
25
17
|
super();
|
|
26
18
|
this.flex = data.flex;
|
|
@@ -30,26 +22,25 @@ class FlexiblePDFElement extends PDFElement {
|
|
|
30
22
|
return this.flex;
|
|
31
23
|
}
|
|
32
24
|
}
|
|
33
|
-
|
|
34
|
-
var HorizontalAlignment;
|
|
25
|
+
export var HorizontalAlignment;
|
|
35
26
|
(function (HorizontalAlignment) {
|
|
36
27
|
HorizontalAlignment["left"] = "LEFT";
|
|
37
28
|
HorizontalAlignment["right"] = "RIGHT";
|
|
38
29
|
HorizontalAlignment["center"] = "CENTER";
|
|
39
30
|
HorizontalAlignment["block"] = "BLOCK";
|
|
40
|
-
})(HorizontalAlignment || (
|
|
41
|
-
var VerticalAlignment;
|
|
31
|
+
})(HorizontalAlignment || (HorizontalAlignment = {}));
|
|
32
|
+
export var VerticalAlignment;
|
|
42
33
|
(function (VerticalAlignment) {
|
|
43
34
|
VerticalAlignment["top"] = "TOP";
|
|
44
35
|
VerticalAlignment["middle"] = "MIDDLE";
|
|
45
36
|
VerticalAlignment["bottom"] = "BOTTOM";
|
|
46
|
-
})(VerticalAlignment || (
|
|
47
|
-
function isSizedElement(obj) {
|
|
37
|
+
})(VerticalAlignment || (VerticalAlignment = {}));
|
|
38
|
+
export function isSizedElement(obj) {
|
|
48
39
|
return typeof obj === "object" && obj !== null && "x" in obj && "y" in obj;
|
|
49
40
|
}
|
|
50
|
-
function hasChildrenProp(obj) {
|
|
41
|
+
export function hasChildrenProp(obj) {
|
|
51
42
|
return "children" in obj;
|
|
52
43
|
}
|
|
53
|
-
function hasChildProp(obj) {
|
|
44
|
+
export function hasChildProp(obj) {
|
|
54
45
|
return "child" in obj;
|
|
55
46
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Color } from "../common/color";
|
|
2
|
-
import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
|
|
3
|
-
import { Fragmentable, FragmentResult } from "../layout/fragmentation";
|
|
4
|
-
import { LayoutContext, PDFElement, SizedElement, SizedPDFElement, WithChildren } from "./pdf-element";
|
|
5
|
-
/** Per-side border
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
2
|
+
import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
|
|
3
|
+
import { Fragmentable, FragmentResult } from "../layout/fragmentation.js";
|
|
4
|
+
import { LayoutContext, PDFElement, SizedElement, SizedPDFElement, WithChildren } from "./pdf-element.js";
|
|
5
|
+
/** Per-side border colors. When set, each present side is stroked individually (sharp
|
|
6
6
|
* corners), instead of the uniform `color` border - this is what enables grid lines. */
|
|
7
7
|
export interface SideBorders {
|
|
8
8
|
top?: Color;
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const pdf_element_1 = require("./pdf-element");
|
|
8
|
-
class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
9
|
-
constructor({ children = [], color = new color_1.Color(0, 0, 0), backgroundColor, borderWidth, width, height, radius, sideBorders, relative, overflow, }) {
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
2
|
+
import { BoxConstraints } from "../layout/box-constraints.js";
|
|
3
|
+
import { packChildren } from "../layout/fragmentation.js";
|
|
4
|
+
import { SizedPDFElement, } from "./pdf-element.js";
|
|
5
|
+
export class RectangleElement extends SizedPDFElement {
|
|
6
|
+
constructor({ children = [], color = new Color(0, 0, 0), backgroundColor, borderWidth, width, height, radius, sideBorders, relative, overflow, }) {
|
|
10
7
|
super({ x: 0, y: 0, width, height });
|
|
11
8
|
this.children = [];
|
|
12
9
|
this.children = children;
|
|
13
10
|
this.color = color;
|
|
14
11
|
this.backgroundColor = backgroundColor;
|
|
15
12
|
// `?? 1` (not `|| 1`) so an explicit `0` means "no border" instead of snapping to 1.
|
|
16
|
-
this.borderWidth = borderWidth
|
|
17
|
-
this.radius = radius
|
|
13
|
+
this.borderWidth = borderWidth ?? 1;
|
|
14
|
+
this.radius = radius ?? 0;
|
|
18
15
|
this.sideBorders = sideBorders;
|
|
19
|
-
this.relative = relative
|
|
20
|
-
this.overflow = overflow
|
|
16
|
+
this.relative = relative ?? false;
|
|
17
|
+
this.overflow = overflow ?? "visible";
|
|
21
18
|
this.sizeMemory = { x: 0, y: 0, width, height };
|
|
22
19
|
}
|
|
23
20
|
/**
|
|
@@ -29,17 +26,16 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
29
26
|
* box is sized by what it actually holds on each page.
|
|
30
27
|
*/
|
|
31
28
|
fragment(maxHeight, width, ctx) {
|
|
32
|
-
|
|
33
|
-
const boxWidth = (_a = this.sizeMemory.width) !== null && _a !== void 0 ? _a : width;
|
|
29
|
+
const boxWidth = this.sizeMemory.width ?? width;
|
|
34
30
|
const innerWidth = Math.max(0, boxWidth - 2 * this.borderWidth);
|
|
35
31
|
// Border-box: the content is inset by the border on top and bottom, so a fragment
|
|
36
32
|
// holding `c` of content is `c + 2*border` tall. (Derived, not a fudge factor.)
|
|
37
33
|
const innerMaxHeight = maxHeight - 2 * this.borderWidth;
|
|
38
|
-
const { fitted, remainder } =
|
|
34
|
+
const { fitted, remainder } = packChildren(this.children, innerMaxHeight, innerWidth, ctx);
|
|
39
35
|
if (remainder.length === 0)
|
|
40
36
|
return { fitted: this, remainder: null };
|
|
41
37
|
const contentHeight = (kids) => kids.reduce((sum, child) => sum +
|
|
42
|
-
child.calculateLayout(
|
|
38
|
+
child.calculateLayout(BoxConstraints.loose(innerWidth, Infinity), { x: 0, y: 0 }, ctx)
|
|
43
39
|
.height, 0);
|
|
44
40
|
return {
|
|
45
41
|
fitted: this.cloneWithChildren(fitted, contentHeight(fitted) + 2 * this.borderWidth),
|
|
@@ -63,7 +59,6 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
63
59
|
});
|
|
64
60
|
}
|
|
65
61
|
calculateLayout(constraints, offset, ctx) {
|
|
66
|
-
var _a, _b, _c, _d, _e;
|
|
67
62
|
// Width: an explicit size wins (clamped), else fill the offered box. (Without this a
|
|
68
63
|
// fixed box would balloon to the parent's size.)
|
|
69
64
|
this.width =
|
|
@@ -93,17 +88,17 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
93
88
|
const frame = this.relative
|
|
94
89
|
? { origin: { x: 0, y: 0 }, size: { width: 0, height: 0 }, place: [] }
|
|
95
90
|
: undefined;
|
|
96
|
-
const childCtx = frame ?
|
|
91
|
+
const childCtx = frame ? { ...ctx, frame } : ctx;
|
|
97
92
|
// Lay out children stacked inside the border (inset by the border width). Width is
|
|
98
93
|
// finalized here; height is left unbounded so each child sizes to its own content.
|
|
99
94
|
const innerWidth = shrinkWrapWidth
|
|
100
95
|
? Infinity
|
|
101
|
-
: Math.max(0, (
|
|
96
|
+
: Math.max(0, (this.width ?? 0) - 2 * this.borderWidth);
|
|
102
97
|
let contentWidth = 0;
|
|
103
98
|
let contentHeight = 0;
|
|
104
99
|
let yCursor = this.y + this.borderWidth;
|
|
105
100
|
for (const child of this.children) {
|
|
106
|
-
const childSize = child.calculateLayout(
|
|
101
|
+
const childSize = child.calculateLayout(BoxConstraints.loose(innerWidth, Infinity), { x: this.x + this.borderWidth, y: yCursor }, childCtx);
|
|
107
102
|
yCursor += childSize.height;
|
|
108
103
|
contentHeight += childSize.height;
|
|
109
104
|
contentWidth = Math.max(contentWidth, childSize.width);
|
|
@@ -117,7 +112,7 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
117
112
|
// The box is sized now: place any out-of-flow `Positioned` descendants against its box.
|
|
118
113
|
if (frame) {
|
|
119
114
|
frame.origin = { x: this.x, y: this.y };
|
|
120
|
-
frame.size = { width:
|
|
115
|
+
frame.size = { width: this.width ?? 0, height: this.height ?? 0 };
|
|
121
116
|
for (const place of frame.place)
|
|
122
117
|
place(frame, ctx);
|
|
123
118
|
}
|
|
@@ -126,8 +121,8 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
126
121
|
// border added on (that asymmetric "+border" was the source of the magic-3 fudge in
|
|
127
122
|
// fragment). Top-left coordinates; the Y-flip happens at the IR -> backend seam.
|
|
128
123
|
return {
|
|
129
|
-
width:
|
|
130
|
-
height:
|
|
124
|
+
width: this.width ?? 0,
|
|
125
|
+
height: this.height ?? 0,
|
|
131
126
|
};
|
|
132
127
|
}
|
|
133
128
|
getProps() {
|
|
@@ -146,4 +141,3 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
146
141
|
};
|
|
147
142
|
}
|
|
148
143
|
}
|
|
149
|
-
exports.RectangleElement = RectangleElement;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
|
|
2
|
-
import { MainAlign, CrossAlign } from "../utils/flex-layout";
|
|
3
|
-
import { LayoutContext, PDFElement, SizedPDFElement, WithChildren } from "./pdf-element";
|
|
1
|
+
import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
|
|
2
|
+
import { MainAlign, CrossAlign } from "../utils/flex-layout.js";
|
|
3
|
+
import { LayoutContext, PDFElement, SizedPDFElement, WithChildren } from "./pdf-element.js";
|
|
4
4
|
interface RowElementParams extends WithChildren {
|
|
5
5
|
/** Space inserted between children, in points. */
|
|
6
6
|
gap?: number;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.RowElement = void 0;
|
|
4
|
-
const flex_layout_1 = require("../utils/flex-layout");
|
|
5
|
-
const pdf_element_1 = require("./pdf-element");
|
|
1
|
+
import { FlexLayoutHelper, HORIZONTAL_AXIS } from "../utils/flex-layout.js";
|
|
2
|
+
import { SizedPDFElement } from "./pdf-element.js";
|
|
6
3
|
/**
|
|
7
4
|
* Horizontal stack: the mirror of `ContainerElement` (Column). Children are laid out
|
|
8
5
|
* left-to-right via the shared `FlexLayoutHelper` on the horizontal axis; fixed children
|
|
@@ -15,13 +12,13 @@ const pdf_element_1 = require("./pdf-element");
|
|
|
15
12
|
* does not fit (handled by the parent's `packChildren`); synchronized cell splitting is a
|
|
16
13
|
* Grid/Table concern.
|
|
17
14
|
*/
|
|
18
|
-
class RowElement extends
|
|
15
|
+
export class RowElement extends SizedPDFElement {
|
|
19
16
|
constructor({ children, gap, main, cross }) {
|
|
20
17
|
super({ x: 0, y: 0 });
|
|
21
18
|
this.children = children;
|
|
22
|
-
this.gap = gap
|
|
23
|
-
this.main = main
|
|
24
|
-
this.cross = cross
|
|
19
|
+
this.gap = gap ?? 0;
|
|
20
|
+
this.main = main ?? "start";
|
|
21
|
+
this.cross = cross ?? "stretch";
|
|
25
22
|
}
|
|
26
23
|
calculateLayout(constraints, offset, ctx) {
|
|
27
24
|
this.x = offset.x;
|
|
@@ -32,7 +29,7 @@ class RowElement extends pdf_element_1.SizedPDFElement {
|
|
|
32
29
|
const crossAvail = constraints.hasBoundedHeight ? constraints.maxHeight : Infinity;
|
|
33
30
|
let result = { mainUsed: 0, crossUsed: 0 };
|
|
34
31
|
if (this.children.length > 0) {
|
|
35
|
-
result =
|
|
32
|
+
result = FlexLayoutHelper.layout(this.children, HORIZONTAL_AXIS, mainAvail, crossAvail, this.x, this.y, { gap: this.gap, main: this.main, cross: this.cross }, ctx);
|
|
36
33
|
}
|
|
37
34
|
this.width = constraints.hasBoundedWidth ? constraints.maxWidth : result.mainUsed;
|
|
38
35
|
this.height = constraints.hasBoundedHeight ? constraints.maxHeight : result.crossUsed;
|
|
@@ -51,4 +48,3 @@ class RowElement extends pdf_element_1.SizedPDFElement {
|
|
|
51
48
|
};
|
|
52
49
|
}
|
|
53
50
|
}
|
|
54
|
-
exports.RowElement = RowElement;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Color } from "../common/color";
|
|
2
|
-
import { FontStyle } from "../utils/pdf-object-manager";
|
|
3
|
-
import { BoxConstraints, Offset, Size } from "../layout/box-constraints";
|
|
4
|
-
import { Fragmentable, FragmentResult } from "../layout/fragmentation";
|
|
5
|
-
import {
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
2
|
+
import { FontStyle } from "../utils/pdf-object-manager.js";
|
|
3
|
+
import { BoxConstraints, Offset, Size } from "../layout/box-constraints.js";
|
|
4
|
+
import { Fragmentable, FragmentResult } from "../layout/fragmentation.js";
|
|
5
|
+
import { TextOverflow } from "../text/line-breaker.js";
|
|
6
|
+
import { HorizontalAlignment, LayoutContext, SizedPDFElement } from "./pdf-element.js";
|
|
6
7
|
export interface TextSegment {
|
|
7
8
|
content: string;
|
|
8
9
|
fontStyle?: FontStyle;
|
|
@@ -12,21 +13,39 @@ export interface TextSegment {
|
|
|
12
13
|
}
|
|
13
14
|
interface TextElementParams {
|
|
14
15
|
id?: string;
|
|
15
|
-
|
|
16
|
+
/** Unset (undefined) inherits the cascaded size; see ResolvedTextStyle. */
|
|
17
|
+
fontSize?: number;
|
|
16
18
|
fontFamily?: string;
|
|
17
19
|
fontStyle?: FontStyle;
|
|
18
20
|
content: string | TextSegment[];
|
|
19
21
|
color?: Color;
|
|
20
22
|
textAlignment?: HorizontalAlignment;
|
|
23
|
+
/** Cap the wrapped lines (default: unlimited / open-end). */
|
|
24
|
+
maxLines?: number;
|
|
25
|
+
/** What to do past `maxLines`: `"clip"` (default) drops them, `"ellipsis"` ends with "…". */
|
|
26
|
+
overflow?: TextOverflow;
|
|
27
|
+
/** Line-height multiplier: each line is `fontSize * lineHeight` tall (default `1`). */
|
|
28
|
+
lineHeight?: number;
|
|
21
29
|
}
|
|
22
30
|
export declare class TextElement extends SizedPDFElement implements Fragmentable {
|
|
31
|
+
private readonly rawFontSize?;
|
|
32
|
+
private readonly rawFontFamily?;
|
|
33
|
+
private readonly rawFontStyle?;
|
|
34
|
+
private readonly rawColor?;
|
|
35
|
+
private readonly rawTextAlignment?;
|
|
36
|
+
private readonly rawLineHeight?;
|
|
23
37
|
private fontSize;
|
|
24
38
|
private fontFamily;
|
|
25
39
|
private fontStyle;
|
|
26
40
|
private color;
|
|
27
|
-
private content;
|
|
28
41
|
private textAlignment;
|
|
29
|
-
|
|
42
|
+
private lineHeight;
|
|
43
|
+
private content;
|
|
44
|
+
private maxLines?;
|
|
45
|
+
private overflow;
|
|
46
|
+
constructor({ fontSize, content, fontFamily, fontStyle, color, textAlignment, maxLines, overflow, lineHeight, }: TextElementParams);
|
|
47
|
+
private resolveStyle;
|
|
48
|
+
private applyStyle;
|
|
30
49
|
/**
|
|
31
50
|
* Splits the paragraph at line boxes (Slice 1). The lines that fit in `maxHeight` stay;
|
|
32
51
|
* the rest become a remainder `TextElement` re-wrapped on the next page. If not even one
|
|
@@ -39,9 +58,13 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
|
|
|
39
58
|
private cloneWithContent;
|
|
40
59
|
calculateLayout(constraints: BoxConstraints, offset: Offset, ctx: LayoutContext): Size;
|
|
41
60
|
/** The unwrapped single-line width of the content (used when width is unbounded, e.g. inside a Row).
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
61
|
+
* Must match the LINE-BREAKER's one-line measure EXACTLY - not just algebraically but BIT-for-bit,
|
|
62
|
+
* so a text laid out at this width never re-wraps inside its own natural-width box. The breaker
|
|
63
|
+
* accumulates `currentWidth += wordWidth + spaceWidth`, grouping the word and its trailing space
|
|
64
|
+
* into one term; we must group the same way. Adding word and space as two separate steps is
|
|
65
|
+
* algebraically equal but, because floating-point addition is not associative, drifts by a sub-ULP
|
|
66
|
+
* - enough to tip a borderline string (e.g. "20 Jun 2026", wider than "04 Jul 2026" only because
|
|
67
|
+
* 'n' beats 'l') one bit over its own width, dropping the last word onto a second line. */
|
|
45
68
|
private naturalWidth;
|
|
46
69
|
getProps(): {
|
|
47
70
|
x: number;
|
|
@@ -54,6 +77,9 @@ export declare class TextElement extends SizedPDFElement implements Fragmentable
|
|
|
54
77
|
color: Color;
|
|
55
78
|
content: string | TextSegment[];
|
|
56
79
|
textAlignment: HorizontalAlignment;
|
|
80
|
+
maxLines: number | undefined;
|
|
81
|
+
overflow: TextOverflow;
|
|
82
|
+
lineHeight: number;
|
|
57
83
|
};
|
|
58
84
|
}
|
|
59
85
|
export {};
|