pagyra-js 0.0.21 → 0.0.23

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.
Files changed (92) hide show
  1. package/README.md +283 -264
  2. package/dist/browser/pagyra.min.js +30 -30
  3. package/dist/browser/pagyra.min.js.map +4 -4
  4. package/dist/src/css/apply-declarations.js +2 -1
  5. package/dist/src/css/clip-path-types.d.ts +9 -1
  6. package/dist/src/css/compute-style/overrides.js +10 -1
  7. package/dist/src/css/parsers/clip-path-parser.js +51 -0
  8. package/dist/src/css/parsers/register-parsers.js +21 -0
  9. package/dist/src/css/properties/visual.d.ts +2 -0
  10. package/dist/src/css/style.d.ts +5 -0
  11. package/dist/src/css/style.js +3 -0
  12. package/dist/src/css/ua-defaults/element-defaults.js +13 -0
  13. package/dist/src/dom/node.d.ts +2 -0
  14. package/dist/src/dom/node.js +1 -0
  15. package/dist/src/fonts/woff2/decoder.d.ts +1 -9
  16. package/dist/src/fonts/woff2/decoder.js +6 -565
  17. package/dist/src/fonts/woff2/glyf-reconstructor.d.ts +54 -0
  18. package/dist/src/fonts/woff2/glyf-reconstructor.js +357 -0
  19. package/dist/src/fonts/woff2/hmtx-reconstructor.d.ts +5 -0
  20. package/dist/src/fonts/woff2/hmtx-reconstructor.js +42 -0
  21. package/dist/src/fonts/woff2/sfnt-builder.d.ts +7 -0
  22. package/dist/src/fonts/woff2/sfnt-builder.js +55 -0
  23. package/dist/src/fonts/woff2/utils.d.ts +12 -0
  24. package/dist/src/fonts/woff2/utils.js +111 -0
  25. package/dist/src/html-to-pdf/render-finalize.js +5 -1
  26. package/dist/src/layout/inline/run-placer.js +1 -1
  27. package/dist/src/layout/strategies/flex/alignment.d.ts +10 -0
  28. package/dist/src/layout/strategies/flex/alignment.js +91 -0
  29. package/dist/src/layout/strategies/flex/distributor.d.ts +5 -0
  30. package/dist/src/layout/strategies/flex/distributor.js +56 -0
  31. package/dist/src/layout/strategies/flex/line-builder.d.ts +5 -0
  32. package/dist/src/layout/strategies/flex/line-builder.js +55 -0
  33. package/dist/src/layout/strategies/flex/types.d.ts +27 -0
  34. package/dist/src/layout/strategies/flex/types.js +2 -0
  35. package/dist/src/layout/strategies/flex/utils.d.ts +12 -0
  36. package/dist/src/layout/strategies/flex/utils.js +113 -0
  37. package/dist/src/layout/strategies/flex.js +4 -308
  38. package/dist/src/layout/strategies/grid.js +0 -3
  39. package/dist/src/layout/strategies/table.js +85 -58
  40. package/dist/src/layout/utils/text-metrics.js +16 -8
  41. package/dist/src/pdf/font/embedder.js +3 -3
  42. package/dist/src/pdf/font/font-subset.js +1 -3
  43. package/dist/src/pdf/font/to-unicode.js +16 -16
  44. package/dist/src/pdf/layout-tree-builder.js +15 -9
  45. package/dist/src/pdf/renderer/box-painter.js +74 -9
  46. package/dist/src/pdf/renderers/text-renderer.d.ts +4 -2
  47. package/dist/src/pdf/renderers/text-renderer.js +52 -2
  48. package/dist/src/pdf/types.d.ts +16 -1
  49. package/dist/src/pdf/utils/clip-path-resolver.js +28 -12
  50. package/dist/src/pdf/utils/mask-resolver.d.ts +7 -0
  51. package/dist/src/pdf/utils/mask-resolver.js +25 -0
  52. package/dist/src/pdf/utils/node-text-run-factory.d.ts +2 -1
  53. package/dist/src/pdf/utils/node-text-run-factory.js +5 -26
  54. package/dist/src/pdf/utils/rounded-rect-to-path.d.ts +7 -0
  55. package/dist/src/pdf/utils/rounded-rect-to-path.js +86 -0
  56. package/dist/src/render/offset.d.ts +5 -0
  57. package/dist/src/render/offset.js +93 -9
  58. package/dist/src/text/line-breaker.js +31 -0
  59. package/dist/tests/css/clip-path-parser.spec.js +15 -8
  60. package/dist/tests/environment/path-resolution.spec.js +2 -1
  61. package/dist/tests/helpers/ai-layout-diagnostics.js +6 -6
  62. package/dist/tests/layout/container-query-units.spec.js +0 -7
  63. package/dist/tests/layout/inline-background-alignment.spec.js +6 -6
  64. package/dist/tests/layout/table-image-cell.spec.js +95 -0
  65. package/dist/tests/pdf/alignments.spec.js +12 -12
  66. package/dist/tests/pdf/clip-path.spec.js +3 -1
  67. package/dist/tests/pdf/form-text-encoding.spec.js +1 -1
  68. package/dist/tests/pdf/svg-stroke-dash.spec.js +8 -8
  69. package/dist/tests/pdf/text-transform-matrix.spec.js +1 -1
  70. package/dist/tests/pdf/xref-integrity.spec.js +1 -1
  71. package/dist/tests/verify-subset-multi.spec.js +14 -14
  72. package/dist/tests/verify-subset.spec.js +12 -12
  73. package/package.json +89 -71
  74. package/dist/src/image/js-png-backend.d.ts +0 -7
  75. package/dist/src/image/js-png-backend.js +0 -9
  76. package/dist/src/image/png-backend.d.ts +0 -5
  77. package/dist/src/image/png-wasm-loader.d.ts +0 -5
  78. package/dist/src/image/png-wasm-loader.js +0 -59
  79. package/dist/src/image/wasm/png_decoder_wasm.d.ts +0 -8
  80. package/dist/src/image/wasm/png_decoder_wasm.js +0 -24
  81. package/dist/src/image/wasm/png_decoder_wasm_bg.js +0 -16
  82. package/dist/src/image/wasm-png-backend.d.ts +0 -6
  83. package/dist/src/image/wasm-png-backend.js +0 -17
  84. package/dist/src/layout/table/cell_layout.d.ts +0 -2
  85. package/dist/src/layout/table/cell_layout.js +0 -26
  86. package/dist/tests/image/png-backend.spec.d.ts +0 -1
  87. package/dist/tests/image/png-backend.spec.js +0 -34
  88. package/dist/tests/pdf/font-subset-registry-key.spec.d.ts +0 -1
  89. package/dist/tests/pdf/font-subset-registry-key.spec.js +0 -66
  90. package/dist/tests/pdf/header-footer.spec.d.ts +0 -1
  91. package/dist/tests/pdf/header-footer.spec.js +0 -46
  92. /package/dist/{src/image/png-backend.js → tests/layout/table-image-cell.spec.d.ts} +0 -0
@@ -19,7 +19,8 @@ const SHORTHAND_PROPERTIES = new Set([
19
19
  "font",
20
20
  "text-decoration",
21
21
  "flex",
22
- "gap"
22
+ "gap",
23
+ "grid-column"
23
24
  ]);
24
25
  // Cache for frequently used parsers to reduce Map lookups
25
26
  const parserCache = new Map();
@@ -14,4 +14,12 @@ export interface ClipPathPolygon {
14
14
  }>;
15
15
  referenceBox?: ClipPathReferenceBox;
16
16
  }
17
- export type ClipPath = ClipPathPolygon;
17
+ export interface ClipPathEllipse {
18
+ type: "ellipse";
19
+ rx: ClipPathLength;
20
+ ry: ClipPathLength;
21
+ cx: ClipPathLength;
22
+ cy: ClipPathLength;
23
+ referenceBox?: ClipPathReferenceBox;
24
+ }
25
+ export type ClipPath = ClipPathPolygon | ClipPathEllipse;
@@ -1,4 +1,4 @@
1
- import { BoxSizing } from "../enums.js";
1
+ import { BoxSizing, OverflowMode } from "../enums.js";
2
2
  import { normalizeFontWeight } from "../font-weight.js";
3
3
  import { CssUnitResolver } from "../css-unit-resolver.js";
4
4
  import { LayoutPropertyResolver } from "../layout-property-resolver.js";
@@ -174,6 +174,15 @@ export function applyStyleInitOverrides(styleInit, styleOptions, mergedDefaults,
174
174
  if (styleInit.gridColumnSpan !== undefined) {
175
175
  styleOptions.gridColumnSpan = styleInit.gridColumnSpan;
176
176
  }
177
+ if (styleInit.breakInside !== undefined) {
178
+ styleOptions.breakInside = styleInit.breakInside;
179
+ }
180
+ if (styleInit.overflowX !== undefined) {
181
+ styleOptions.overflowX = styleInit.overflowX;
182
+ }
183
+ if (styleInit.overflowY !== undefined) {
184
+ styleOptions.overflowY = styleInit.overflowY;
185
+ }
177
186
  if (styleInit.justifyContent !== undefined)
178
187
  styleOptions.justifyContent = styleInit.justifyContent;
179
188
  if (styleInit.alignItems !== undefined)
@@ -18,6 +18,10 @@ function parseClipPathValue(value) {
18
18
  if (polygon) {
19
19
  return polygon;
20
20
  }
21
+ const ellipse = parseEllipse(normalized);
22
+ if (ellipse) {
23
+ return ellipse;
24
+ }
21
25
  return undefined;
22
26
  }
23
27
  function parsePolygon(input) {
@@ -66,6 +70,53 @@ function splitEvenTokens(tokens) {
66
70
  }
67
71
  return result;
68
72
  }
73
+ function parseEllipse(input) {
74
+ const match = /^ellipse\s*\((.+)\)$/i.exec(input);
75
+ if (!match) {
76
+ return undefined;
77
+ }
78
+ const body = match[1].trim();
79
+ // ellipse(rx ry at cx cy)
80
+ const atMatch = /^(.+?)\s+at\s+(.+)$/i.exec(body);
81
+ let rxToken;
82
+ let ryToken;
83
+ let cxToken = "50%";
84
+ let cyToken = "50%";
85
+ if (atMatch) {
86
+ const radii = atMatch[1].trim().split(/\s+/).filter(Boolean);
87
+ const center = atMatch[2].trim().split(/\s+/).filter(Boolean);
88
+ if (radii.length < 2 || center.length < 2) {
89
+ return undefined;
90
+ }
91
+ rxToken = radii[0];
92
+ ryToken = radii[1];
93
+ cxToken = center[0];
94
+ cyToken = center[1];
95
+ }
96
+ else {
97
+ const tokens = body.split(/\s+/).filter(Boolean);
98
+ if (tokens.length < 2) {
99
+ return undefined;
100
+ }
101
+ rxToken = tokens[0];
102
+ ryToken = tokens[1];
103
+ }
104
+ const rx = parseClipLength(rxToken);
105
+ const ry = parseClipLength(ryToken);
106
+ const cx = parseClipLength(cxToken);
107
+ const cy = parseClipLength(cyToken);
108
+ if (!rx || !ry || !cx || !cy) {
109
+ return undefined;
110
+ }
111
+ return {
112
+ type: "ellipse",
113
+ rx,
114
+ ry,
115
+ cx,
116
+ cy,
117
+ referenceBox: "border-box",
118
+ };
119
+ }
69
120
  function parseClipLength(token) {
70
121
  const parsed = parseLengthOrPercent(token);
71
122
  if (parsed === undefined) {
@@ -155,6 +155,17 @@ export function registerAllPropertyParsers() {
155
155
  registerPropertyParser("float", parseFloat);
156
156
  registerPropertyParser("overflow-wrap", parseOverflowWrap);
157
157
  registerPropertyParser("word-wrap", parseWordWrap);
158
+ registerPropertyParser("overflow", (value, target) => {
159
+ const val = value.trim().toLowerCase();
160
+ target.overflowX = val;
161
+ target.overflowY = val;
162
+ });
163
+ registerPropertyParser("overflow-x", (value, target) => {
164
+ target.overflowX = value.trim().toLowerCase();
165
+ });
166
+ registerPropertyParser("overflow-y", (value, target) => {
167
+ target.overflowY = value.trim().toLowerCase();
168
+ });
158
169
  registerPropertyParser("word-break", parseWordBreak);
159
170
  registerPropertyParser("text-shadow", parseTextShadow);
160
171
  registerPropertyParser("list-style-type", parseListStyleType);
@@ -165,6 +176,9 @@ export function registerAllPropertyParsers() {
165
176
  registerPropertyParser("counter-increment", (value, target) => {
166
177
  target.counterIncrement = parseCounterIncrement(value);
167
178
  });
179
+ registerPropertyParser("break-inside", (value, target) => {
180
+ target.breakInside = value.trim().toLowerCase();
181
+ });
168
182
  // Transform (store as raw string for limited later use)
169
183
  registerPropertyParser("transform", (value, target) => {
170
184
  // store raw transform string
@@ -176,7 +190,14 @@ export function registerAllPropertyParsers() {
176
190
  registerPropertyParser("background-origin", applyBackgroundOriginDecl);
177
191
  registerPropertyParser("background-repeat", applyBackgroundRepeatDecl);
178
192
  registerPropertyParser("background-clip", applyBackgroundClipDecl);
193
+ registerPropertyParser("-webkit-background-clip", applyBackgroundClipDecl);
179
194
  registerPropertyParser("background-image", parseBackgroundImage);
195
+ registerPropertyParser("mask", (value, target) => {
196
+ target.mask = value;
197
+ });
198
+ registerPropertyParser("-webkit-mask", (value, target) => {
199
+ target.mask = value;
200
+ });
180
201
  registerPropertyParser("background", parseBackground);
181
202
  registerPropertyParser("object-fit", parseObjectFit);
182
203
  registerPropertyParser("clip-path", parseClipPath);
@@ -83,6 +83,8 @@ export interface VisualProperties {
83
83
  overflowY: OverflowMode;
84
84
  /** Clipping path applied to the element */
85
85
  clipPath?: ClipPath;
86
+ /** CSS masking */
87
+ mask?: string;
86
88
  /** CSS filter — lista ordenada de funções (aplicadas da esquerda para direita) */
87
89
  filter?: FilterFunction[];
88
90
  /** CSS backdrop-filter — mesma estrutura, render diferente */
@@ -33,6 +33,7 @@ export interface StyleAccumulator {
33
33
  textShadows?: TextShadowInput[];
34
34
  transform?: string;
35
35
  clipPath?: ClipPath;
36
+ mask?: string;
36
37
  borderTop?: LengthInput;
37
38
  borderRight?: LengthInput;
38
39
  borderBottom?: LengthInput;
@@ -96,10 +97,13 @@ export interface StyleAccumulator {
96
97
  wordBreak?: WordBreak;
97
98
  trackListColumns?: TrackDefinitionInput[];
98
99
  trackListRows?: TrackDefinitionInput[];
100
+ overflowX?: string;
101
+ overflowY?: string;
99
102
  autoFlow?: GridAutoFlow;
100
103
  rowGap?: NumericLength | ClampNumericLength;
101
104
  columnGap?: NumericLength | ClampNumericLength;
102
105
  gridColumnSpan?: number;
106
+ breakInside?: string;
103
107
  zIndex?: number | "auto";
104
108
  top?: LengthInput;
105
109
  right?: LengthInput;
@@ -216,6 +220,7 @@ export declare class ComputedStyle implements StyleProperties {
216
220
  breakBefore: string;
217
221
  breakAfter: string;
218
222
  breakInside: string;
223
+ mask?: string;
219
224
  widows: number;
220
225
  orphans: number;
221
226
  opacity: number;
@@ -97,6 +97,8 @@ export class ComputedStyle {
97
97
  this.flexWrap = data.flexWrap;
98
98
  this.trackListColumns = data.trackListColumns;
99
99
  this.trackListRows = data.trackListRows;
100
+ this.overflowX = data.overflowX;
101
+ this.overflowY = data.overflowY;
100
102
  this.autoFlow = data.autoFlow;
101
103
  this.rowGap = data.rowGap;
102
104
  this.columnGap = data.columnGap;
@@ -106,6 +108,7 @@ export class ComputedStyle {
106
108
  this.breakBefore = data.breakBefore;
107
109
  this.breakAfter = data.breakAfter;
108
110
  this.breakInside = data.breakInside;
111
+ this.mask = data.mask;
109
112
  this.widows = data.widows;
110
113
  this.orphans = data.orphans;
111
114
  this.textIndent = data.textIndent;
@@ -110,6 +110,19 @@ class ElementSpecificDefaultsImpl {
110
110
  fontFamily: TypographyDefaults.getFontFamily(),
111
111
  color: TypographyDefaults.getColor(),
112
112
  },
113
+ // Horizontal rule — UA default renders a thin line via its border. Without this,
114
+ // an <hr> with no explicit border (relying on browser defaults) is invisible.
115
+ hr: {
116
+ display: Display.Block,
117
+ marginTop: relativeLength("em", 0.5),
118
+ marginBottom: relativeLength("em", 0.5),
119
+ borderTop: 1,
120
+ borderColor: "#a0a0a0",
121
+ fontSize: relativeLength("em", 1),
122
+ lineHeight: createNormalLineHeight(),
123
+ fontFamily: TypographyDefaults.getFontFamily(),
124
+ color: TypographyDefaults.getColor(),
125
+ },
113
126
  // Lists
114
127
  ul: {
115
128
  display: Display.Block,
@@ -17,6 +17,7 @@ export interface NodeVisitor {
17
17
  }
18
18
  export interface LayoutNodeOptions {
19
19
  intrinsicInlineSize?: number;
20
+ minIntrinsicInlineSize?: number;
20
21
  intrinsicBlockSize?: number;
21
22
  textContent?: string;
22
23
  tagName?: string;
@@ -41,6 +42,7 @@ export declare class LayoutNode {
41
42
  establishesGFC: boolean;
42
43
  establishesTFC: boolean;
43
44
  intrinsicInlineSize?: number;
45
+ minIntrinsicInlineSize?: number;
44
46
  intrinsicBlockSize?: number;
45
47
  textContent?: string;
46
48
  tagName?: string;
@@ -12,6 +12,7 @@ export class LayoutNode {
12
12
  this.establishesGFC = false;
13
13
  this.establishesTFC = false;
14
14
  this.intrinsicInlineSize = options?.intrinsicInlineSize;
15
+ this.minIntrinsicInlineSize = options?.minIntrinsicInlineSize;
15
16
  this.intrinsicBlockSize = options?.intrinsicBlockSize;
16
17
  this.textContent = options?.textContent;
17
18
  this.tagName = options?.tagName;
@@ -1,5 +1,6 @@
1
1
  import type { ParsedFont } from "../types.js";
2
2
  import { type AsyncDecompressFn } from "../../compression/decompress.js";
3
+ import { type GlyfReconstruction } from "./glyf-reconstructor.js";
3
4
  export interface Woff2Dependencies {
4
5
  decompress?: AsyncDecompressFn;
5
6
  transformers?: Map<number, Woff2Transform>;
@@ -20,15 +21,6 @@ interface Woff2Header {
20
21
  uncompressedSize: number;
21
22
  tables: Woff2Table[];
22
23
  }
23
- interface GlyfReconstruction {
24
- glyfData: Uint8Array;
25
- locaData: Uint8Array;
26
- glyfChecksum: number;
27
- locaChecksum: number;
28
- numGlyphs: number;
29
- indexFormat: number;
30
- xMins: Int16Array;
31
- }
32
24
  interface TransformState {
33
25
  glyfInfo: GlyfReconstruction | null;
34
26
  numHMetrics: number;