@segnavia/render 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/overflow.js CHANGED
@@ -33,15 +33,33 @@ function solveScale(pageWidth, measurements) {
33
33
  }
34
34
  return { scale: pageWidth / (measured.get(high) !== void 0 && measured.get(high) >= pageWidth ? high : lastSatisfied) };
35
35
  }
36
+ /** Returns the visible horizontal part of a box after ancestor clipping. */
37
+ function clippedHorizontalBox(box, clips) {
38
+ const visible = clips.reduce((current, clip) => ({
39
+ left: Math.max(current.left, clip.left),
40
+ right: Math.min(current.right, clip.right)
41
+ }), box);
42
+ return visible.right > visible.left ? visible : void 0;
43
+ }
44
+ function horizontalOverflow(box, clips, pageWidth, rtl) {
45
+ const visible = clippedHorizontalBox(box, clips);
46
+ return {
47
+ clippedStart: Math.max(0, rtl ? box.right - pageWidth : -box.left),
48
+ clippedEnd: Math.max(0, rtl ? -box.left : box.right - pageWidth),
49
+ rightOverflow: visible ? Math.max(0, visible.right - pageWidth) : 0
50
+ };
51
+ }
36
52
  async function measuredOverflow(tab, pageWidth) {
37
- return tab.evaluate((width) => {
53
+ const measured = await tab.evaluate(() => {
38
54
  const root = document.documentElement;
39
55
  const extent = Math.max(root.scrollWidth, document.body?.scrollWidth ?? 0);
40
56
  const endOverflow = Math.max(0, extent - root.clientWidth);
41
57
  const rtl = getComputedStyle(root).direction === "rtl";
42
- const contributions = [];
43
- let clippedStart = 0;
44
- let rightOverflow = rtl ? 0 : endOverflow;
58
+ const clipsContent = (style) => {
59
+ const contain = style.contain.split(/\s+/);
60
+ return style.overflowX !== "visible" || contain.includes("paint") || contain.includes("strict") || contain.includes("content") || style.clipPath !== "none" || style.clip !== "auto";
61
+ };
62
+ const extentClipped = [root, document.body].some((element) => element && clipsContent(getComputedStyle(element)));
45
63
  const locator = (element) => {
46
64
  if (element.id) return `#${CSS.escape(element.id)}`;
47
65
  const parts = [];
@@ -53,29 +71,86 @@ async function measuredOverflow(tab, pageWidth) {
53
71
  }
54
72
  return parts.join(" > ");
55
73
  };
56
- for (const element of document.querySelectorAll("*")) {
74
+ const clipBox = (element, style) => {
57
75
  const box = element.getBoundingClientRect();
58
- const elementStart = Math.max(0, rtl ? box.right - width : -box.left);
59
- const elementEnd = Math.max(0, rtl ? -box.left : box.right - width);
60
- clippedStart = Math.max(clippedStart, elementStart);
61
- rightOverflow = Math.max(rightOverflow, box.right - width);
62
- if ((elementStart > 0 || elementEnd > 0) && contributions.length < 20) contributions.push({
63
- locator: locator(element),
64
- clippedStart: elementStart,
65
- clippedEnd: elementEnd
66
- });
67
- }
76
+ const scale = element instanceof HTMLElement && element.offsetWidth > 0 ? box.width / element.offsetWidth : 1;
77
+ let left = box.left + element.clientLeft * scale;
78
+ let right = left + element.clientWidth * scale;
79
+ if (style.overflowX === "clip") {
80
+ const values = style.overflowClipMargin.split(/\s+/);
81
+ const reference = values.find((value) => value === "content-box" || value === "border-box" || value === "padding-box");
82
+ if (reference === "border-box") {
83
+ left = box.left;
84
+ right = box.right;
85
+ } else if (reference === "content-box") {
86
+ left += Number.parseFloat(style.paddingLeft) * scale;
87
+ right -= Number.parseFloat(style.paddingRight) * scale;
88
+ }
89
+ const margin = values.map(Number.parseFloat).find(Number.isFinite) ?? 0;
90
+ left -= margin * scale;
91
+ right += margin * scale;
92
+ }
93
+ const legacy = style.clip.match(/^rect\((?:([^, ]+)[, ]+)(?:([^, ]+)[, ]+)(?:([^, ]+)[, ]+)([^, )]+)\)$/);
94
+ if (legacy) {
95
+ const length = (value, fallback) => value && value !== "auto" ? Number.parseFloat(value) * scale : fallback;
96
+ left = box.left + length(legacy[4], 0);
97
+ right = box.left + length(legacy[2], box.width);
98
+ }
99
+ return {
100
+ left,
101
+ right
102
+ };
103
+ };
68
104
  return {
69
- overflow: {
70
- pageWidth: width,
71
- extent,
72
- clippedStart,
73
- clippedEnd: endOverflow,
74
- elements: contributions
75
- },
76
- rightOverflow
105
+ extent,
106
+ endOverflow,
107
+ extentClipped,
108
+ rtl,
109
+ elements: [...document.querySelectorAll("*")].map((element) => {
110
+ const box = element.getBoundingClientRect();
111
+ const clips = [];
112
+ let ancestor = element.parentElement;
113
+ while (ancestor) {
114
+ const style = getComputedStyle(ancestor);
115
+ if (clipsContent(style)) clips.push(clipBox(ancestor, style));
116
+ ancestor = ancestor.parentElement;
117
+ }
118
+ return {
119
+ locator: locator(element),
120
+ box: {
121
+ left: box.left,
122
+ right: box.right
123
+ },
124
+ clips
125
+ };
126
+ })
77
127
  };
78
- }, pageWidth);
128
+ });
129
+ const contributions = [];
130
+ let clippedStart = 0;
131
+ let clippedEnd = measured.endOverflow;
132
+ let rightOverflow = measured.rtl || measured.extentClipped ? 0 : measured.endOverflow;
133
+ for (const element of measured.elements) {
134
+ const overflow = horizontalOverflow(element.box, element.clips, pageWidth, measured.rtl);
135
+ clippedStart = Math.max(clippedStart, overflow.clippedStart);
136
+ clippedEnd = Math.max(clippedEnd, overflow.clippedEnd);
137
+ rightOverflow = Math.max(rightOverflow, overflow.rightOverflow);
138
+ if ((overflow.clippedStart > 0 || overflow.clippedEnd > 0) && contributions.length < 20) contributions.push({
139
+ locator: element.locator,
140
+ clippedStart: overflow.clippedStart,
141
+ clippedEnd: overflow.clippedEnd
142
+ });
143
+ }
144
+ return {
145
+ overflow: {
146
+ pageWidth,
147
+ extent: measured.extent,
148
+ clippedStart,
149
+ clippedEnd,
150
+ elements: contributions
151
+ },
152
+ rightOverflow
153
+ };
79
154
  }
80
155
  function overflowEntry(measured, scale, part, inputIndex) {
81
156
  return {
@@ -120,4 +195,4 @@ async function printWithOverflow(tab, pageWidth, part, pdf, inputIndex) {
120
195
  };
121
196
  }
122
197
  //#endregion
123
- export { CHROMIUM_MAX_SHRINK, measureOverflow, printWithOverflow, solveScale };
198
+ export { CHROMIUM_MAX_SHRINK, clippedHorizontalBox, horizontalOverflow, measureOverflow, printWithOverflow, solveScale };
@@ -249,6 +249,7 @@ function replaceType1Function(document, shading, pattern, convert, budget, paint
249
249
  Order: 1,
250
250
  Filter: "FlateDecode"
251
251
  });
252
+ shading.set(PDFName.of("Domain"), document.context.obj(domain));
252
253
  shading.set(PDFName.of("Function"), document.context.register(replacement));
253
254
  return size;
254
255
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@segnavia/render",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,9 +26,9 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
- "@segnavia/format": "0.9.0",
30
- "@segnavia/frame": "0.9.0",
31
- "@segnavia/html": "0.9.0",
29
+ "@segnavia/format": "0.10.0",
30
+ "@segnavia/frame": "0.10.0",
31
+ "@segnavia/html": "0.10.0",
32
32
  "playwright-core": "1.55.1",
33
33
  "pdf-lib": "^1.17.1"
34
34
  }