smooth-screenshot 1.1.1 → 1.1.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 CHANGED
@@ -6,6 +6,8 @@
6
6
  [![types](https://img.shields.io/npm/types/smooth-screenshot)](https://www.npmjs.com/package/smooth-screenshot)
7
7
  [![license](https://img.shields.io/npm/l/smooth-screenshot)](./LICENSE)
8
8
 
9
+ **[Live demo & docs → luccas-carvalho.github.io/smooth-screenshot](https://luccas-carvalho.github.io/smooth-screenshot/)**
10
+
9
11
  **Capture any DOM element to PNG, JPEG, WebP, SVG, or PDF — without ever freezing the UI.**
10
12
 
11
13
  Most DOM-to-image libraries do all their work in one synchronous burst: on a large
package/dist/index.cjs CHANGED
@@ -250,8 +250,25 @@ function createContext(target, options) {
250
250
  return context;
251
251
  }
252
252
 
253
+ // src/util/ns.ts
254
+ var svgNs = null;
255
+ var xhtmlNs = null;
256
+ function svgNamespace(doc) {
257
+ if (svgNs === null) {
258
+ const probe = doc.createElement("div");
259
+ probe.innerHTML = "<svg></svg>";
260
+ svgNs = probe.firstElementChild.namespaceURI ?? "";
261
+ }
262
+ return svgNs;
263
+ }
264
+ function xhtmlNamespace(doc) {
265
+ if (xhtmlNs === null) {
266
+ xhtmlNs = doc.createElement("div").namespaceURI ?? "";
267
+ }
268
+ return xhtmlNs;
269
+ }
270
+
253
271
  // src/clone/default-style.ts
254
- var XHTML_NS = "http://www.w3.org/1999/xhtml";
255
272
  function ensureSandbox(context) {
256
273
  if (context.sandbox?.contentDocument) {
257
274
  return context.sandbox.contentDocument;
@@ -267,7 +284,8 @@ function ensureSandbox(context) {
267
284
  return doc;
268
285
  }
269
286
  function getDefaultStyle(context, source) {
270
- const namespace = source.namespaceURI ?? XHTML_NS;
287
+ const xhtmlNs2 = xhtmlNamespace(context.ownerDocument);
288
+ const namespace = source.namespaceURI ?? xhtmlNs2;
271
289
  const key = `${namespace}|${source.localName}`;
272
290
  const cached = context.defaultStyleCache.get(key);
273
291
  if (cached) return cached;
@@ -278,7 +296,7 @@ function getDefaultStyle(context, source) {
278
296
  context.defaultStyleCache.set(key, empty);
279
297
  return empty;
280
298
  }
281
- const element = namespace === XHTML_NS ? doc.createElement(source.localName) : doc.createElementNS(namespace, source.localName);
299
+ const element = namespace === xhtmlNs2 ? doc.createElement(source.localName) : doc.createElementNS(namespace, source.localName);
282
300
  doc.body.appendChild(element);
283
301
  const computed = sandboxWindow.getComputedStyle(element);
284
302
  const record = {};
@@ -292,15 +310,40 @@ function getDefaultStyle(context, source) {
292
310
  }
293
311
 
294
312
  // src/clone/copy-styles.ts
313
+ var PHYSICAL_BORDER_WIDTHS = [
314
+ "border-top-width",
315
+ "border-right-width",
316
+ "border-bottom-width",
317
+ "border-left-width"
318
+ ];
319
+ function isBorderStyleOrColor(name) {
320
+ if (!name.startsWith("border")) return false;
321
+ if (name.startsWith("border-image") || name.startsWith("border-radius")) {
322
+ return false;
323
+ }
324
+ return name.endsWith("style") || name.endsWith("color");
325
+ }
295
326
  function copyStyle(source, target, context) {
296
327
  const computed = context.ownerWindow.getComputedStyle(source);
297
328
  const defaults = getDefaultStyle(context, source);
298
- const targetStyle = target.style;
329
+ const toCopy = /* @__PURE__ */ new Set();
299
330
  for (let i = 0; i < computed.length; i++) {
300
331
  const name = computed[i];
301
332
  if (!name) continue;
302
333
  const value = computed.getPropertyValue(name);
303
334
  if (value === "" || defaults[name] === value) continue;
335
+ toCopy.add(name);
336
+ }
337
+ if (Array.from(toCopy).some(isBorderStyleOrColor)) {
338
+ for (const width of PHYSICAL_BORDER_WIDTHS) toCopy.add(width);
339
+ }
340
+ if (toCopy.has("outline-style") || toCopy.has("outline-color") || toCopy.has("outline")) {
341
+ toCopy.add("outline-width");
342
+ }
343
+ const targetStyle = target.style;
344
+ for (const name of toCopy) {
345
+ const value = computed.getPropertyValue(name);
346
+ if (value === "") continue;
304
347
  targetStyle.setProperty(name, value, computed.getPropertyPriority(name));
305
348
  }
306
349
  }
@@ -713,8 +756,6 @@ async function embedResources(clone, context) {
713
756
  }
714
757
 
715
758
  // src/serialize/foreign-object-svg.ts
716
- var SVG_NS = "http://www.w3.org/2000/svg";
717
- var XHTML_NS2 = "http://www.w3.org/1999/xhtml";
718
759
  function buildSvgString(params) {
719
760
  const {
720
761
  clone,
@@ -728,25 +769,26 @@ function buildSvgString(params) {
728
769
  } = params;
729
770
  const outW = crop ? crop.width : fullWidth;
730
771
  const outH = crop ? crop.height : fullHeight;
731
- const svg = doc.createElementNS(SVG_NS, "svg");
732
- svg.setAttribute("xmlns", SVG_NS);
772
+ const svgNs2 = svgNamespace(doc);
773
+ const svg = doc.createElementNS(svgNs2, "svg");
774
+ svg.setAttribute("xmlns", svgNs2);
733
775
  svg.setAttribute("width", String(outW));
734
776
  svg.setAttribute("height", String(outH));
735
777
  svg.setAttribute("viewBox", `0 0 ${outW} ${outH}`);
736
778
  if (backgroundColor) {
737
- const rect = doc.createElementNS(SVG_NS, "rect");
779
+ const rect = doc.createElementNS(svgNs2, "rect");
738
780
  rect.setAttribute("width", "100%");
739
781
  rect.setAttribute("height", "100%");
740
782
  rect.setAttribute("fill", backgroundColor);
741
783
  svg.appendChild(rect);
742
784
  }
743
- const foreignObject = doc.createElementNS(SVG_NS, "foreignObject");
785
+ const foreignObject = doc.createElementNS(svgNs2, "foreignObject");
744
786
  foreignObject.setAttribute("x", String(crop ? -crop.x : 0));
745
787
  foreignObject.setAttribute("y", String(crop ? -crop.y : 0));
746
788
  foreignObject.setAttribute("width", String(fullWidth));
747
789
  foreignObject.setAttribute("height", String(fullHeight));
748
790
  const container = doc.createElement("div");
749
- container.setAttribute("xmlns", XHTML_NS2);
791
+ container.setAttribute("xmlns", xhtmlNamespace(doc));
750
792
  if (fontCss || pseudoRules.length > 0) {
751
793
  const style = doc.createElement("style");
752
794
  style.textContent = `${fontCss}