@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
|
@@ -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;
|
|
@@ -18,6 +18,11 @@ interface RectangleElementParams extends SizedElement, WithChildren {
|
|
|
18
18
|
radius?: number;
|
|
19
19
|
/** Individual side borders; overrides the uniform `color` border when present. */
|
|
20
20
|
sideBorders?: SideBorders;
|
|
21
|
+
/** When true, this box is a positioning frame for `Positioned` descendants (CSS `relative`). */
|
|
22
|
+
relative?: boolean;
|
|
23
|
+
/** `"hidden"` crops children to the box (CSS `overflow: hidden`); `"visible"` (default) lets a
|
|
24
|
+
* `Positioned` child spill over the edge. */
|
|
25
|
+
overflow?: "hidden" | "visible";
|
|
21
26
|
}
|
|
22
27
|
export declare class RectangleElement extends SizedPDFElement implements Fragmentable {
|
|
23
28
|
private children;
|
|
@@ -26,8 +31,10 @@ export declare class RectangleElement extends SizedPDFElement implements Fragmen
|
|
|
26
31
|
private borderWidth;
|
|
27
32
|
private radius;
|
|
28
33
|
private sideBorders?;
|
|
34
|
+
private relative;
|
|
35
|
+
private overflow;
|
|
29
36
|
private sizeMemory;
|
|
30
|
-
constructor({ children, color, backgroundColor, borderWidth, width, height, radius, sideBorders, }: RectangleElementParams);
|
|
37
|
+
constructor({ children, color, backgroundColor, borderWidth, width, height, radius, sideBorders, relative, overflow, }: RectangleElementParams);
|
|
31
38
|
/**
|
|
32
39
|
* Splits the bordered box across pages (box-decoration-break: clone - every fragment
|
|
33
40
|
* gets its own full border). The children stack is packed into the space left after
|
|
@@ -50,6 +57,7 @@ export declare class RectangleElement extends SizedPDFElement implements Fragmen
|
|
|
50
57
|
borderWidth: number;
|
|
51
58
|
radius: number;
|
|
52
59
|
sideBorders: SideBorders | undefined;
|
|
60
|
+
overflow: "hidden" | "visible";
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
export {};
|
|
@@ -1,21 +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, }) {
|
|
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;
|
|
16
|
+
this.relative = relative ?? false;
|
|
17
|
+
this.overflow = overflow ?? "visible";
|
|
19
18
|
this.sizeMemory = { x: 0, y: 0, width, height };
|
|
20
19
|
}
|
|
21
20
|
/**
|
|
@@ -27,17 +26,16 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
27
26
|
* box is sized by what it actually holds on each page.
|
|
28
27
|
*/
|
|
29
28
|
fragment(maxHeight, width, ctx) {
|
|
30
|
-
|
|
31
|
-
const boxWidth = (_a = this.sizeMemory.width) !== null && _a !== void 0 ? _a : width;
|
|
29
|
+
const boxWidth = this.sizeMemory.width ?? width;
|
|
32
30
|
const innerWidth = Math.max(0, boxWidth - 2 * this.borderWidth);
|
|
33
31
|
// Border-box: the content is inset by the border on top and bottom, so a fragment
|
|
34
32
|
// holding `c` of content is `c + 2*border` tall. (Derived, not a fudge factor.)
|
|
35
33
|
const innerMaxHeight = maxHeight - 2 * this.borderWidth;
|
|
36
|
-
const { fitted, remainder } =
|
|
34
|
+
const { fitted, remainder } = packChildren(this.children, innerMaxHeight, innerWidth, ctx);
|
|
37
35
|
if (remainder.length === 0)
|
|
38
36
|
return { fitted: this, remainder: null };
|
|
39
37
|
const contentHeight = (kids) => kids.reduce((sum, child) => sum +
|
|
40
|
-
child.calculateLayout(
|
|
38
|
+
child.calculateLayout(BoxConstraints.loose(innerWidth, Infinity), { x: 0, y: 0 }, ctx)
|
|
41
39
|
.height, 0);
|
|
42
40
|
return {
|
|
43
41
|
fitted: this.cloneWithChildren(fitted, contentHeight(fitted) + 2 * this.borderWidth),
|
|
@@ -56,10 +54,11 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
56
54
|
borderWidth: this.borderWidth,
|
|
57
55
|
radius: this.radius,
|
|
58
56
|
sideBorders: this.sideBorders,
|
|
57
|
+
relative: this.relative,
|
|
58
|
+
overflow: this.overflow,
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
calculateLayout(constraints, offset, ctx) {
|
|
62
|
-
var _a, _b, _c;
|
|
63
62
|
// Width: an explicit size wins (clamped), else fill the offered box. (Without this a
|
|
64
63
|
// fixed box would balloon to the parent's size.)
|
|
65
64
|
this.width =
|
|
@@ -68,6 +67,9 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
68
67
|
: constraints.hasBoundedWidth
|
|
69
68
|
? constraints.maxWidth
|
|
70
69
|
: this.width;
|
|
70
|
+
// Width shrink-wrap: no explicit width AND an unbounded region (e.g. a `Box` badge inside a
|
|
71
|
+
// `Positioned`). Resolved after the children are measured, just below.
|
|
72
|
+
const shrinkWrapWidth = this.sizeMemory.width === undefined && !constraints.hasBoundedWidth;
|
|
71
73
|
// Height: explicit wins; otherwise FILL a bounded region (e.g. inside an Expanded) but
|
|
72
74
|
// SHRINK-WRAP the content in an unbounded one (a note box in a stack). Shrink-wrap is
|
|
73
75
|
// resolved after the children are measured, just below.
|
|
@@ -80,26 +82,47 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
80
82
|
: this.height;
|
|
81
83
|
this.x = this.sizeMemory.x + offset.x;
|
|
82
84
|
this.y = this.sizeMemory.y + offset.y;
|
|
85
|
+
// A `relative` box is a positioning frame: thread a fresh frame to the subtree so any
|
|
86
|
+
// `Positioned` descendant registers against it (out of flow), then drain it below once the
|
|
87
|
+
// box is sized. A plain box leaves `ctx` untouched -> byte-identical.
|
|
88
|
+
const frame = this.relative
|
|
89
|
+
? { origin: { x: 0, y: 0 }, size: { width: 0, height: 0 }, place: [] }
|
|
90
|
+
: undefined;
|
|
91
|
+
const childCtx = frame ? { ...ctx, frame } : ctx;
|
|
83
92
|
// Lay out children stacked inside the border (inset by the border width). Width is
|
|
84
93
|
// finalized here; height is left unbounded so each child sizes to its own content.
|
|
85
|
-
const innerWidth =
|
|
94
|
+
const innerWidth = shrinkWrapWidth
|
|
95
|
+
? Infinity
|
|
96
|
+
: Math.max(0, (this.width ?? 0) - 2 * this.borderWidth);
|
|
97
|
+
let contentWidth = 0;
|
|
86
98
|
let contentHeight = 0;
|
|
87
99
|
let yCursor = this.y + this.borderWidth;
|
|
88
100
|
for (const child of this.children) {
|
|
89
|
-
const childSize = child.calculateLayout(
|
|
101
|
+
const childSize = child.calculateLayout(BoxConstraints.loose(innerWidth, Infinity), { x: this.x + this.borderWidth, y: yCursor }, childCtx);
|
|
90
102
|
yCursor += childSize.height;
|
|
91
103
|
contentHeight += childSize.height;
|
|
104
|
+
contentWidth = Math.max(contentWidth, childSize.width);
|
|
92
105
|
}
|
|
106
|
+
// No explicit width and no bounded region: shrink-wrap to the widest child.
|
|
107
|
+
if (shrinkWrapWidth)
|
|
108
|
+
this.width = contentWidth + 2 * this.borderWidth;
|
|
93
109
|
// No explicit height and no bounded region: the border hugs its content.
|
|
94
110
|
if (shrinkWrapHeight)
|
|
95
111
|
this.height = contentHeight + 2 * this.borderWidth;
|
|
112
|
+
// The box is sized now: place any out-of-flow `Positioned` descendants against its box.
|
|
113
|
+
if (frame) {
|
|
114
|
+
frame.origin = { x: this.x, y: this.y };
|
|
115
|
+
frame.size = { width: this.width ?? 0, height: this.height ?? 0 };
|
|
116
|
+
for (const place of frame.place)
|
|
117
|
+
place(frame, ctx);
|
|
118
|
+
}
|
|
96
119
|
// Border-box model: width/height ARE the outer box (the rect we draw); the content
|
|
97
120
|
// is inset by the border on every side. Report the honest box size - no phantom
|
|
98
121
|
// border added on (that asymmetric "+border" was the source of the magic-3 fudge in
|
|
99
122
|
// fragment). Top-left coordinates; the Y-flip happens at the IR -> backend seam.
|
|
100
123
|
return {
|
|
101
|
-
width:
|
|
102
|
-
height:
|
|
124
|
+
width: this.width ?? 0,
|
|
125
|
+
height: this.height ?? 0,
|
|
103
126
|
};
|
|
104
127
|
}
|
|
105
128
|
getProps() {
|
|
@@ -114,7 +137,7 @@ class RectangleElement extends pdf_element_1.SizedPDFElement {
|
|
|
114
137
|
borderWidth: this.borderWidth,
|
|
115
138
|
radius: this.radius,
|
|
116
139
|
sideBorders: this.sideBorders,
|
|
140
|
+
overflow: this.overflow,
|
|
117
141
|
};
|
|
118
142
|
}
|
|
119
143
|
}
|
|
120
|
-
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 {};
|
|
@@ -1,24 +1,36 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TextElement = void 0;
|
|
4
|
-
const color_1 = require("../common/color");
|
|
5
1
|
// Import the renderer DIRECTLY, not via the "../renderer" barrel: the barrel pulls in
|
|
6
2
|
// pdf-renderer (and every element) while this element module is still loading, which under
|
|
7
3
|
// ESM (Vite/vitest, and the future framework bindings) duplicates the element classes and
|
|
8
4
|
// breaks the constructor-keyed RendererRegistry. A direct import keeps the graph acyclic.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class TextElement extends
|
|
14
|
-
constructor({ fontSize, content, fontFamily
|
|
5
|
+
import { TextRenderer } from "../renderer/text-renderer.js";
|
|
6
|
+
import { DEFAULT_TEXT_STYLE } from "../text/text-style.js";
|
|
7
|
+
import { wrapStringIntoLines, breakSegmentsIntoLines, segmentLinesToSegments, } from "../text/line-breaker.js";
|
|
8
|
+
import { SizedPDFElement } from "./pdf-element.js";
|
|
9
|
+
export class TextElement extends SizedPDFElement {
|
|
10
|
+
constructor({ fontSize, content, fontFamily, fontStyle, color, textAlignment, maxLines, overflow = "clip", lineHeight, }) {
|
|
15
11
|
super({ x: 0, y: 0 });
|
|
16
|
-
this.
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
12
|
+
this.rawFontSize = fontSize;
|
|
13
|
+
this.rawFontFamily = fontFamily;
|
|
14
|
+
this.rawFontStyle = fontStyle;
|
|
15
|
+
this.rawColor = color;
|
|
16
|
+
this.rawTextAlignment = textAlignment;
|
|
17
|
+
this.rawLineHeight = lineHeight;
|
|
20
18
|
this.content = content;
|
|
21
|
-
this.
|
|
19
|
+
this.maxLines = maxLines;
|
|
20
|
+
this.overflow = overflow;
|
|
21
|
+
this.applyStyle(DEFAULT_TEXT_STYLE);
|
|
22
|
+
}
|
|
23
|
+
// Resolve the author-set values against the cascade: explicit > inherited (ctx) > built-in default.
|
|
24
|
+
resolveStyle(ctx) {
|
|
25
|
+
this.applyStyle(ctx.textStyle ?? DEFAULT_TEXT_STYLE);
|
|
26
|
+
}
|
|
27
|
+
applyStyle(ts) {
|
|
28
|
+
this.fontSize = this.rawFontSize ?? ts.fontSize;
|
|
29
|
+
this.fontFamily = this.rawFontFamily ?? ts.fontFamily;
|
|
30
|
+
this.fontStyle = this.rawFontStyle ?? ts.fontStyle;
|
|
31
|
+
this.color = this.rawColor ?? ts.color;
|
|
32
|
+
this.textAlignment = this.rawTextAlignment ?? ts.textAlignment;
|
|
33
|
+
this.lineHeight = this.rawLineHeight ?? ts.lineHeight;
|
|
22
34
|
}
|
|
23
35
|
/**
|
|
24
36
|
* Splits the paragraph at line boxes (Slice 1). The lines that fit in `maxHeight` stay;
|
|
@@ -27,6 +39,7 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
27
39
|
* the whole element on for progress. Handles both plain strings and styled segments.
|
|
28
40
|
*/
|
|
29
41
|
fragment(maxHeight, width, ctx) {
|
|
42
|
+
this.resolveStyle(ctx);
|
|
30
43
|
return typeof this.content === "string"
|
|
31
44
|
? this.fragmentString(this.content, maxHeight, width, ctx)
|
|
32
45
|
: this.fragmentSegments(this.content, maxHeight, width, ctx);
|
|
@@ -34,8 +47,8 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
34
47
|
// Plain string: every wrapped line is `fontSize` tall (matches calculateTextHeight),
|
|
35
48
|
// so `floor(maxHeight / fontSize)` lines fit.
|
|
36
49
|
fragmentString(content, maxHeight, width, ctx) {
|
|
37
|
-
const lines =
|
|
38
|
-
const fittedLineCount = Math.floor(maxHeight / this.fontSize);
|
|
50
|
+
const lines = wrapStringIntoLines(content, this.fontFamily, this.fontSize, this.fontStyle, width, ctx.metrics, this.maxLines, this.overflow);
|
|
51
|
+
const fittedLineCount = Math.floor(maxHeight / (this.fontSize * this.lineHeight));
|
|
39
52
|
if (fittedLineCount <= 0)
|
|
40
53
|
return { fitted: null, remainder: this };
|
|
41
54
|
if (fittedLineCount >= lines.length)
|
|
@@ -48,17 +61,18 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
48
61
|
// Styled segments: each line's height is its tallest font (maxFontSize), so pack lines
|
|
49
62
|
// by cumulative leading. Rebuild the fitted/remainder halves back into TextSegment[].
|
|
50
63
|
fragmentSegments(content, maxHeight, width, ctx) {
|
|
51
|
-
const lines =
|
|
64
|
+
const lines = breakSegmentsIntoLines(content, {
|
|
52
65
|
fontFamily: this.fontFamily,
|
|
53
66
|
fontSize: this.fontSize,
|
|
54
67
|
fontStyle: this.fontStyle,
|
|
55
|
-
}, width, ctx.metrics);
|
|
68
|
+
}, width, ctx.metrics, this.maxLines, this.overflow);
|
|
56
69
|
let used = 0;
|
|
57
70
|
let fittedLineCount = 0;
|
|
58
71
|
for (const line of lines) {
|
|
59
|
-
|
|
72
|
+
const lineBox = line.maxFontSize * this.lineHeight;
|
|
73
|
+
if (used + lineBox > maxHeight)
|
|
60
74
|
break;
|
|
61
|
-
used +=
|
|
75
|
+
used += lineBox;
|
|
62
76
|
fittedLineCount++;
|
|
63
77
|
}
|
|
64
78
|
if (fittedLineCount <= 0)
|
|
@@ -66,8 +80,8 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
66
80
|
if (fittedLineCount >= lines.length)
|
|
67
81
|
return { fitted: this, remainder: null };
|
|
68
82
|
return {
|
|
69
|
-
fitted: this.cloneWithContent(
|
|
70
|
-
remainder: this.cloneWithContent(
|
|
83
|
+
fitted: this.cloneWithContent(segmentLinesToSegments(lines.slice(0, fittedLineCount))),
|
|
84
|
+
remainder: this.cloneWithContent(segmentLinesToSegments(lines.slice(fittedLineCount))),
|
|
71
85
|
};
|
|
72
86
|
}
|
|
73
87
|
// A copy carrying the same style but different (already-wrapped) content. Re-wrapping at
|
|
@@ -80,10 +94,13 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
80
94
|
fontStyle: this.fontStyle,
|
|
81
95
|
color: this.color,
|
|
82
96
|
textAlignment: this.textAlignment,
|
|
97
|
+
maxLines: this.maxLines,
|
|
98
|
+
overflow: this.overflow,
|
|
99
|
+
lineHeight: this.lineHeight,
|
|
83
100
|
});
|
|
84
101
|
}
|
|
85
102
|
calculateLayout(constraints, offset, ctx) {
|
|
86
|
-
|
|
103
|
+
this.resolveStyle(ctx);
|
|
87
104
|
this.x = offset.x;
|
|
88
105
|
this.y = offset.y;
|
|
89
106
|
// Bounded width (e.g. inside a Column) wraps to that width; an unbounded width
|
|
@@ -92,32 +109,38 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
92
109
|
this.width = constraints.hasBoundedWidth
|
|
93
110
|
? constraints.maxWidth
|
|
94
111
|
: this.naturalWidth(ctx.metrics);
|
|
95
|
-
const wrapWidth =
|
|
96
|
-
this.height =
|
|
112
|
+
const wrapWidth = this.width ?? 0;
|
|
113
|
+
this.height = TextRenderer.calculateTextHeight(this.content, this.fontSize, this.fontFamily, this.fontStyle, ctx.metrics, wrapWidth, this.maxLines, this.overflow, this.lineHeight);
|
|
97
114
|
// Top-left coordinates (y = top of the text box). The baseline offset and the
|
|
98
115
|
// Y-flip are applied downstream (the line-builder positions baselines, the seam
|
|
99
116
|
// flips to PDF), so the element stays coordinate-system-blind.
|
|
100
117
|
return { width: wrapWidth, height: this.height };
|
|
101
118
|
}
|
|
102
119
|
/** The unwrapped single-line width of the content (used when width is unbounded, e.g. inside a Row).
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
120
|
+
* Must match the LINE-BREAKER's one-line measure EXACTLY - not just algebraically but BIT-for-bit,
|
|
121
|
+
* so a text laid out at this width never re-wraps inside its own natural-width box. The breaker
|
|
122
|
+
* accumulates `currentWidth += wordWidth + spaceWidth`, grouping the word and its trailing space
|
|
123
|
+
* into one term; we must group the same way. Adding word and space as two separate steps is
|
|
124
|
+
* algebraically equal but, because floating-point addition is not associative, drifts by a sub-ULP
|
|
125
|
+
* - enough to tip a borderline string (e.g. "20 Jun 2026", wider than "04 Jul 2026" only because
|
|
126
|
+
* 'n' beats 'l') one bit over its own width, dropping the last word onto a second line. */
|
|
106
127
|
naturalWidth(metrics) {
|
|
107
|
-
const
|
|
128
|
+
const oneLine = (text, family, size, style) => {
|
|
129
|
+
const words = text.split(" ");
|
|
130
|
+
const space = metrics.getCharWidth(" ", size, undefined, family, style);
|
|
108
131
|
let width = 0;
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
words.forEach((word, i) => {
|
|
133
|
+
const w = metrics.getStringWidth(word, family, size, style);
|
|
134
|
+
// Group (word + space) as one term, exactly like the breaker - see the note above.
|
|
135
|
+
width += i < words.length - 1 ? w + space : w;
|
|
136
|
+
});
|
|
111
137
|
return width;
|
|
112
138
|
};
|
|
113
139
|
if (typeof this.content === "string") {
|
|
114
|
-
return
|
|
140
|
+
return oneLine(this.content, this.fontFamily, this.fontSize, this.fontStyle);
|
|
115
141
|
}
|
|
116
|
-
return this.content.reduce((sum, seg) =>
|
|
117
|
-
|
|
118
|
-
return sum +
|
|
119
|
-
advance(seg.content, (_a = seg.fontFamily) !== null && _a !== void 0 ? _a : this.fontFamily, (_b = seg.fontSize) !== null && _b !== void 0 ? _b : this.fontSize, (_c = seg.fontStyle) !== null && _c !== void 0 ? _c : this.fontStyle);
|
|
120
|
-
}, 0);
|
|
142
|
+
return this.content.reduce((sum, seg) => sum +
|
|
143
|
+
oneLine(seg.content, seg.fontFamily ?? this.fontFamily, seg.fontSize ?? this.fontSize, seg.fontStyle ?? this.fontStyle), 0);
|
|
121
144
|
}
|
|
122
145
|
getProps() {
|
|
123
146
|
return {
|
|
@@ -131,7 +154,9 @@ class TextElement extends pdf_element_1.SizedPDFElement {
|
|
|
131
154
|
color: this.color,
|
|
132
155
|
content: this.content,
|
|
133
156
|
textAlignment: this.textAlignment,
|
|
157
|
+
maxLines: this.maxLines,
|
|
158
|
+
overflow: this.overflow,
|
|
159
|
+
lineHeight: this.lineHeight,
|
|
134
160
|
};
|
|
135
161
|
}
|
|
136
162
|
}
|
|
137
|
-
exports.TextElement = TextElement;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from "./elements";
|
|
2
|
-
export * from "./renderer";
|
|
3
|
-
export * from "./api";
|
|
1
|
+
export * from "./elements/index.js";
|
|
2
|
+
export * from "./renderer/index.js";
|
|
3
|
+
export * from "./api/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
__exportStar(require("./elements"), exports);
|
|
18
|
-
__exportStar(require("./renderer"), exports);
|
|
19
|
-
__exportStar(require("./api"), exports);
|
|
1
|
+
export * from "./elements/index.js";
|
|
2
|
+
export * from "./renderer/index.js";
|
|
3
|
+
export * from "./api/index.js";
|
|
20
4
|
// export * from './validator';
|
|
21
5
|
// export * from './utils';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Color } from "../common/color";
|
|
2
|
-
import { FontStyle } from "../utils/pdf-object-manager";
|
|
1
|
+
import { Color } from "../common/color.js";
|
|
2
|
+
import { FontStyle } from "../utils/pdf-object-manager.js";
|
|
3
3
|
/**
|
|
4
4
|
* Display list - the seam between layout and the PDF backend.
|
|
5
5
|
*
|
|
@@ -60,6 +60,8 @@ export interface Image {
|
|
|
60
60
|
intrinsicHeight: number;
|
|
61
61
|
data: string;
|
|
62
62
|
imageType: string;
|
|
63
|
+
/** Flate-compressed DeviceGray alpha channel for a transparent PNG, embedded as the XObject's /SMask. */
|
|
64
|
+
smask?: string;
|
|
63
65
|
/** cover/contain fits clip the placement to the element's original frame. */
|
|
64
66
|
clip?: {
|
|
65
67
|
x: number;
|
|
@@ -70,5 +72,22 @@ export interface Image {
|
|
|
70
72
|
/** Corner radius in points for the image box; absent/0 = sharp corners. */
|
|
71
73
|
radius?: number;
|
|
72
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Pushes a clipping region (a rectangle, rounded when `radius` is set). Everything between this and
|
|
77
|
+
* the matching `ClipPop` is clipped to it - what a Box with `overflow: "hidden"` wraps its children
|
|
78
|
+
* in, so a `Positioned` child gets cropped at the box edge instead of spilling over.
|
|
79
|
+
*/
|
|
80
|
+
export interface ClipPush {
|
|
81
|
+
type: "clip-push";
|
|
82
|
+
x: number;
|
|
83
|
+
y: number;
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
radius?: number;
|
|
87
|
+
}
|
|
88
|
+
/** Closes the most recent `ClipPush` (restores the graphics state). */
|
|
89
|
+
export interface ClipPop {
|
|
90
|
+
type: "clip-pop";
|
|
91
|
+
}
|
|
73
92
|
/** The closed set of primitives the PDF backend knows how to draw. */
|
|
74
|
-
export type IRNode = TextRun | Rect | Line | Image;
|
|
93
|
+
export type IRNode = TextRun | Rect | Line | Image | ClipPush | ClipPop;
|
package/dist/ir/display-list.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BoxConstraints = void 0;
|
|
4
1
|
/**
|
|
5
2
|
* The size constraints handed DOWN the tree during layout (Flutter's BoxConstraints
|
|
6
3
|
* model). Pure geometry: a min/max range per axis, no position. An element receives a
|
|
@@ -15,7 +12,7 @@ exports.BoxConstraints = void 0;
|
|
|
15
12
|
* remaining vertical space becomes a `maxHeight`, and "does this fit?" is a constraint
|
|
16
13
|
* check, not a special case.
|
|
17
14
|
*/
|
|
18
|
-
class BoxConstraints {
|
|
15
|
+
export class BoxConstraints {
|
|
19
16
|
constructor(minWidth = 0, maxWidth = Infinity, minHeight = 0, maxHeight = Infinity) {
|
|
20
17
|
this.minWidth = minWidth;
|
|
21
18
|
this.maxWidth = maxWidth;
|
|
@@ -28,7 +25,7 @@ class BoxConstraints {
|
|
|
28
25
|
}
|
|
29
26
|
/** Tight only on the axes given; the others stay unbounded (0..Infinity). */
|
|
30
27
|
static tightFor({ width, height }) {
|
|
31
|
-
return new BoxConstraints(width
|
|
28
|
+
return new BoxConstraints(width ?? 0, width ?? Infinity, height ?? 0, height ?? Infinity);
|
|
32
29
|
}
|
|
33
30
|
/** Caps each axis at `max` but allows anything down to zero (shrink-wrap). */
|
|
34
31
|
static loose(maxWidth, maxHeight) {
|
|
@@ -70,4 +67,3 @@ class BoxConstraints {
|
|
|
70
67
|
return new BoxConstraints(Math.max(parent.minWidth, Math.min(this.minWidth, parent.maxWidth)), Math.max(parent.minWidth, Math.min(this.maxWidth, parent.maxWidth)), Math.max(parent.minHeight, Math.min(this.minHeight, parent.maxHeight)), Math.max(parent.minHeight, Math.min(this.maxHeight, parent.maxHeight)));
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
|
-
exports.BoxConstraints = BoxConstraints;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LayoutContext, PDFElement } from "../elements/pdf-element";
|
|
1
|
+
import { LayoutContext, PDFElement } from "../elements/pdf-element.js";
|
|
2
2
|
/**
|
|
3
3
|
* The result of splitting an element against a fragmentation region (a page, later a
|
|
4
4
|
* column). `fitted` is the part that fits in the region; `remainder` describes what did
|
|
@@ -22,6 +22,13 @@ export interface Fragmentable {
|
|
|
22
22
|
fragment(maxHeight: number, width: number, ctx: LayoutContext): FragmentResult;
|
|
23
23
|
}
|
|
24
24
|
export declare function isFragmentable(element: PDFElement): element is PDFElement & Fragmentable;
|
|
25
|
+
/**
|
|
26
|
+
* What to do when an element is taller than the whole page region and cannot be broken. We always
|
|
27
|
+
* still place it (clipped) so pagination terminates - this only controls how loud we are about it:
|
|
28
|
+
* `"error"` throws (the default; an unbreakable overflow is almost always a layout bug), `"warn"`
|
|
29
|
+
* logs and clips, `"ignore"` clips silently.
|
|
30
|
+
*/
|
|
31
|
+
export type OverflowPolicy = "error" | "warn" | "ignore";
|
|
25
32
|
/**
|
|
26
33
|
* Packs a vertical stack of children into `maxHeight`, in order. Children are measured
|
|
27
34
|
* against `width` (unbounded height) and added until one would overflow; that straddling
|