PageSourceSearch

https://productos.dev/productos-screenshot.js

js productos.dev collected 2026-10-02 00:09:17 UTC 3,873 bytes, 106 lines download raw bytes

1(function() {
2  if (window.__PRODUCTOS_SCREENSHOT_INIT) return;
3  window.__PRODUCTOS_SCREENSHOT_INIT = true;
4
5  // Pinned version so a sandbox restored from a snapshot always loads the
6  // same engine. Update deliberately, not by floating @latest.
7  var SNAPDOM_URL = "https://cdn.jsdelivr.net/npm/@zumer/snapdom/dist/snapdom.js";
8  var loaderPromise = null;
9
10  function loadSnapdom() {
11    if (window.snapdom) return Promise.resolve(window.snapdom);
12    if (loaderPromise) return loaderPromise;
13    loaderPromise = new Promise(function(resolve, reject) {
14      var s = document.createElement("script");
15      s.src = SNAPDOM_URL;
16      s.crossOrigin = "anonymous";
17      s.onload = function() {
18        if (window.snapdom) resolve(window.snapdom);
19        else reject(new Error("snapdom loaded but global is missing"));
20      };
21      s.onerror = function() {
22        loaderPromise = null;
23        reject(new Error("Failed to load snapdom (CDN unreachable or blocked by CSP)"));
24      };
25      document.head.appendChild(s);
26    });
27    return loaderPromise;
28  }
29
30  function reply(source, payload) {
31    var target = source || window.parent;
32    try { target.postMessage(payload, "*"); }
33    catch (_) { try { window.parent.postMessage(payload, "*"); } catch (__) {} }
34  }
35
36  function shouldSkipForCapture(el) {
37    if (!el) return false;
38    var id = el.id;
39    if (id === "productos-inspector-overlay") return true;
40    if (id === "productos-inspector-highlights") return true;
41    if (el.getAttribute && el.getAttribute("data-productos-skip-shot") === "1") return true;
42    return false;
43  }
44
45  // SnapDOM doesn't have an ignoreElements hook, so we hide our injected UI
46  // for the duration of the capture and restore inline display afterwards.
47  function hideInjectedOverlays() {
48    var nodes = document.querySelectorAll(
49      "#productos-inspector-overlay, #productos-inspector-highlights, [data-productos-skip-shot='1']"
50    );
51    var restorers = [];
52    for (var i = 0; i < nodes.length; i++) {
53      var n = nodes[i];
54      var prev = n.style.display;
55      restorers.push({ node: n, prev: prev });
56      n.style.display = "none";
57    }
58    return function restore() {
59      for (var i = 0; i < restorers.length; i++) {
60        restorers[i].node.style.display = restorers[i].prev;
61      }
62    };
63  }
64
65  window.addEventListener("message", function(e) {
66    var data = e.data;
67    if (!data || data.type !== "productos-screenshot-request") return;
68    var requestId = (data && data.requestId) || "";
69
70    var restoreOverlays = null;
71    loadSnapdom().then(function(snapdom) {
72      restoreOverlays = hideInjectedOverlays();
73      // toCanvas returns a real <canvas> we can call toDataURL on. We pass
74      // documentElement to capture the full viewport-equivalent layout.
75      return snapdom.toCanvas(document.documentElement, {
76        // Snapdom honours device pixel ratio by default; cap it so massive
77        // retina pages don't produce 30MB pngs.
78        scale: 1,
79        // Embed external images / fonts so the canvas isn't tainted.
80        embedFonts: true,
81      });
82    }).then(function(canvas) {
83      if (restoreOverlays) restoreOverlays();
84      var dataUrl = canvas.toDataURL("image/png");
85      reply(e.source, {
86        type: "productos-screenshot-result",
87        requestId: requestId,
88        dataUrl: dataUrl,
89        width: canvas.width,
90        height: canvas.height,
91      });
92    }).catch(function(err) {
93      if (restoreOverlays) restoreOverlays();
94      reply(e.source, {
95        type: "productos-screenshot-error",
96        requestId: requestId,
97        error: String((err && err.message) || err || "screenshot failed"),
98      });
99    });
100  });
101
102  // Announce readiness so parents that want to enable/disable the button can.
103  try {
104    window.parent.postMessage({ type: "productos-screenshot-ready" }, "*");
105  } catch (_) {}
106})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.