@skrillex1224/playwright-toolkit 2.1.229 → 2.1.231

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 CHANGED
@@ -219,6 +219,7 @@ await page.context().addCookies(cookies);
219
219
 
220
220
  // 全页面滚动截图 (自动检测所有滚动元素,强制展开后截图,默认会执行 watermarkify)
221
221
  // 默认会将返回的 base64 压缩到 5MiB 以内,避免 Apify/Crawlee dataset 单条 item 超限
222
+ // 默认会额外保留一小段安全 buffer;如需精确贴边可传 { buffer: 0 }
222
223
  const base64Image = await Share.captureScreen(page);
223
224
 
224
225
  // 截图只使用当前页面运行时 viewport;移动端请通过 ActorInfo.device 切换,不再通过截图参数覆盖
package/dist/index.cjs CHANGED
@@ -505,6 +505,9 @@ var SUPPORTED_TYPES = /* @__PURE__ */ new Set(["png", "jpeg", "webp"]);
505
505
  var EXPANDED_SCROLLABLE_CLASS = "__pk_expanded__";
506
506
  var DEFAULT_MAX_HEIGHT = 8e3;
507
507
  var DEFAULT_SETTLE_MS = 1e3;
508
+ var DEFAULT_BUFFER_RATIO = 0.25;
509
+ var DEFAULT_BUFFER_MIN = 120;
510
+ var DEFAULT_BUFFER_MAX = 320;
508
511
  var toPositiveNumber = (value, fallback = 0) => {
509
512
  const n = Number(value);
510
513
  if (!Number.isFinite(n) || n <= 0) return fallback;
@@ -514,6 +517,10 @@ var toPositiveInteger = (value, fallback = 0) => {
514
517
  const number = Math.round(Number(value) || 0);
515
518
  return number > 0 ? number : fallback;
516
519
  };
520
+ var resolveDefaultBuffer = (viewport = {}) => {
521
+ const height = Math.max(1, Number(viewport.height) || 0);
522
+ return Math.round(Math.min(DEFAULT_BUFFER_MAX, Math.max(DEFAULT_BUFFER_MIN, height * DEFAULT_BUFFER_RATIO)));
523
+ };
517
524
  var normalizeType = (value) => {
518
525
  const raw = String(value || "png").trim().toLowerCase();
519
526
  if (!SUPPORTED_TYPES.has(raw)) return "png";
@@ -568,7 +575,21 @@ var expandScrollableContent = async (page, options = {}) => {
568
575
  if (Number(style.opacity) === 0) return false;
569
576
  return rect.width > 0 && rect.height > 0;
570
577
  };
571
- const isScrollableY = (el, style) => {
578
+ const rememberOriginalBoxStyles = (el) => {
579
+ if (!el || isDocumentElement(el) || el.classList.contains(className)) {
580
+ return;
581
+ }
582
+ el.dataset.pkOrigOverflow = el.style.overflow;
583
+ el.dataset.pkOrigOverflowPriority = el.style.getPropertyPriority("overflow") || "";
584
+ el.dataset.pkOrigHeight = el.style.height;
585
+ el.dataset.pkOrigHeightPriority = el.style.getPropertyPriority("height") || "";
586
+ el.dataset.pkOrigMinHeight = el.style.minHeight;
587
+ el.dataset.pkOrigMinHeightPriority = el.style.getPropertyPriority("min-height") || "";
588
+ el.dataset.pkOrigMaxHeight = el.style.maxHeight;
589
+ el.dataset.pkOrigMaxHeightPriority = el.style.getPropertyPriority("max-height") || "";
590
+ el.classList.add(className);
591
+ };
592
+ const isScrollableY = (el, style, rect) => {
572
593
  if (!el || el.scrollHeight <= el.clientHeight + 1) {
573
594
  return false;
574
595
  }
@@ -578,7 +599,60 @@ var expandScrollableContent = async (page, options = {}) => {
578
599
  const overflowY = String(style.overflowY || "").toLowerCase();
579
600
  const overflow = String(style.overflow || "").toLowerCase();
580
601
  const scrollableOverflow = /* @__PURE__ */ new Set(["auto", "scroll", "overlay"]);
581
- return scrollableOverflow.has(overflowY) || scrollableOverflow.has(overflow);
602
+ if (scrollableOverflow.has(overflowY) || scrollableOverflow.has(overflow)) {
603
+ return true;
604
+ }
605
+ const clippingOverflow = /* @__PURE__ */ new Set(["hidden", "clip"]);
606
+ const clipsY = clippingOverflow.has(overflowY) || clippingOverflow.has(overflow);
607
+ if (!clipsY || !rect) {
608
+ return false;
609
+ }
610
+ const viewportHeight = window.innerHeight || 0;
611
+ return rect.height >= viewportHeight * 0.25 || el.scrollHeight >= viewportHeight * 0.75;
612
+ };
613
+ const measureNeededHeight = (el) => {
614
+ if (!el) return 0;
615
+ const scrollHeight = Math.ceil(el.scrollHeight || 0);
616
+ if (scrollHeight <= 0) return 0;
617
+ if (isDocumentElement(el)) {
618
+ return scrollHeight;
619
+ }
620
+ const rect = el.getBoundingClientRect();
621
+ if (!rect || rect.width <= 0 || rect.height <= 0) {
622
+ return 0;
623
+ }
624
+ const documentTop = Math.max(0, Math.ceil(rect.top + (window.scrollY || window.pageYOffset || 0)));
625
+ return documentTop + scrollHeight;
626
+ };
627
+ const scrollableElements = [];
628
+ const expandElementToScrollHeight = (el) => {
629
+ if (!el || isDocumentElement(el)) return;
630
+ const scrollHeight = Math.ceil(el.scrollHeight || 0);
631
+ if (scrollHeight <= 0) return;
632
+ rememberOriginalBoxStyles(el);
633
+ el.style.setProperty("overflow", "visible", "important");
634
+ el.style.setProperty("height", `${scrollHeight}px`, "important");
635
+ el.style.setProperty("min-height", `${scrollHeight}px`, "important");
636
+ el.style.setProperty("max-height", "none", "important");
637
+ };
638
+ const expandClippingAncestors = (el) => {
639
+ for (let node = el?.parentElement; node && !isDocumentElement(node); node = node.parentElement) {
640
+ const style = window.getComputedStyle(node);
641
+ const rect = node.getBoundingClientRect();
642
+ if (!isVisible(node, style, rect)) continue;
643
+ const overflowY = String(style.overflowY || "").toLowerCase();
644
+ const overflow = String(style.overflow || "").toLowerCase();
645
+ const clipsContent = ["hidden", "clip", "auto", "scroll", "overlay"].includes(overflowY) || ["hidden", "clip", "auto", "scroll", "overlay"].includes(overflow);
646
+ if (!clipsContent) continue;
647
+ rememberOriginalBoxStyles(node);
648
+ node.style.setProperty("overflow", "visible", "important");
649
+ node.style.setProperty("max-height", "none", "important");
650
+ if (node.scrollHeight > node.clientHeight + 1) {
651
+ const scrollHeight = Math.ceil(node.scrollHeight || 0);
652
+ node.style.setProperty("height", `${scrollHeight}px`, "important");
653
+ node.style.setProperty("min-height", `${scrollHeight}px`, "important");
654
+ }
655
+ }
582
656
  };
583
657
  candidates.forEach((el) => {
584
658
  const style = window.getComputedStyle(el);
@@ -586,51 +660,46 @@ var expandScrollableContent = async (page, options = {}) => {
586
660
  if (visibleOnly && !isVisible(el, style, rect)) {
587
661
  return;
588
662
  }
589
- if (!isScrollableY(el, style)) {
663
+ if (!isScrollableY(el, style, rect)) {
590
664
  return;
591
665
  }
592
- const scrollHeight = Math.ceil(el.scrollHeight || 0);
593
- if (scrollHeight <= 0) {
666
+ const neededHeight = measureNeededHeight(el);
667
+ if (neededHeight <= 0) {
594
668
  return;
595
669
  }
596
- if (scrollHeight > maxHeight) {
597
- maxHeight = scrollHeight;
670
+ if (neededHeight > maxHeight) {
671
+ maxHeight = neededHeight;
598
672
  }
673
+ scrollableElements.push(el);
599
674
  if (isDocumentElement(el)) {
600
675
  return;
601
676
  }
602
- if (!el.classList.contains(className)) {
603
- el.dataset.pkOrigOverflow = el.style.overflow;
604
- el.dataset.pkOrigOverflowPriority = el.style.getPropertyPriority("overflow") || "";
605
- el.dataset.pkOrigHeight = el.style.height;
606
- el.dataset.pkOrigHeightPriority = el.style.getPropertyPriority("height") || "";
607
- el.dataset.pkOrigMinHeight = el.style.minHeight;
608
- el.dataset.pkOrigMinHeightPriority = el.style.getPropertyPriority("min-height") || "";
609
- el.dataset.pkOrigMaxHeight = el.style.maxHeight;
610
- el.dataset.pkOrigMaxHeightPriority = el.style.getPropertyPriority("max-height") || "";
611
- el.classList.add(className);
612
- }
677
+ expandClippingAncestors(el);
613
678
  if (forceScrollableHeight) {
614
- el.style.setProperty("overflow", "visible", "important");
615
- el.style.setProperty("height", `${scrollHeight}px`, "important");
616
- el.style.setProperty("min-height", `${scrollHeight}px`, "important");
617
- el.style.setProperty("max-height", "none", "important");
679
+ expandElementToScrollHeight(el);
618
680
  return;
619
681
  }
682
+ rememberOriginalBoxStyles(el);
620
683
  el.style.overflow = "visible";
621
684
  el.style.height = "auto";
622
685
  el.style.maxHeight = "none";
623
686
  });
687
+ scrollableElements.forEach((el) => {
688
+ const neededHeight = measureNeededHeight(el);
689
+ if (neededHeight > maxHeight) {
690
+ maxHeight = neededHeight;
691
+ }
692
+ });
624
693
  return maxHeight;
625
694
  }, {
626
695
  className: EXPANDED_SCROLLABLE_CLASS,
627
- forceScrollableHeight: Boolean(options.forceScrollableHeight),
696
+ forceScrollableHeight: options.forceScrollableHeight !== false,
628
697
  visibleOnly: options.visibleOnly !== false
629
698
  });
630
699
  };
631
700
  var prepareExpandedFullPageScreenshot = async (page, options = {}) => {
632
701
  const originalViewport = await resolveCurrentViewportSize(page);
633
- const defaultBuffer = Math.round((originalViewport.height || 1080) / 2);
702
+ const defaultBuffer = resolveDefaultBuffer(originalViewport);
634
703
  const buffer = options.buffer ?? defaultBuffer;
635
704
  const maxHeight = toPositiveInteger(options.maxHeight, DEFAULT_MAX_HEIGHT);
636
705
  const settleMs = Math.max(0, Number(options.settleMs ?? DEFAULT_SETTLE_MS) || 0);
@@ -8302,7 +8371,7 @@ var Share = {
8302
8371
  *
8303
8372
  * @param {import('playwright').Page} page
8304
8373
  * @param {Object} [options]
8305
- * @param {number} [options.buffer]
8374
+ * @param {number} [options.buffer] 额外缓冲高度;默认按视口高度自动计算,传 0 可关闭
8306
8375
  * @param {boolean} [options.restore]
8307
8376
  * @param {number} [options.maxHeight]
8308
8377
  * @param {number} [options.maxBytes] 默认 5MiB,返回 base64 超过后会压缩
@@ -8315,7 +8384,7 @@ var Share = {
8315
8384
  const screenshotWatermarkify = resolveCaptureScreenWatermarkify(page, options.watermarkify);
8316
8385
  const compression = resolveImageCompression(options);
8317
8386
  const captureOptions = {
8318
- buffer: options.buffer ?? 0,
8387
+ ...Object.prototype.hasOwnProperty.call(options, "buffer") ? { buffer: options.buffer } : {},
8319
8388
  restore,
8320
8389
  maxHeight: options.maxHeight,
8321
8390
  type: "png",