dom-to-image-more
repository·main·Indexed 20 days ago
https://github.com/idisposable/dom-to-image-moreA JavaScript library and maintained fork of dom-to-image that converts DOM nodes into SVG, PNG, or JPEG images using HTML5 canvas and SVG. It features improved support for web fonts, images, and cross-origin resources, and provides methods such as toPng, toJpeg, toBlob, toSvg, toCanvas, and toPixelData. The library includes advanced hooks like requestInterceptor for resource handling and onclone for node replacement.
What's inside dom-to-image-more
- dom-to-image-more is a JavaScript library that converts arbitrary DOM nodes—including same-origin and blob iframes—into vector (SVG) or raster (PNG or JPEG) images.
Understand the `domtoimage.impl` internal surface
mainThe
domtoimage.implobject exposes the library's internal implementation surface. It is intended for unit tests and advanced integrations and is not part of the stable public API (toSvg,toPng,toJpeg,toBlob,toCanvas,toPixelData). Because it is internal, it may change between releases without notice.Key components of
implinclude:util: Low-level helpers (type guards, geometry, fetching).fontFaces: Web font discovery and inlining.images: Image and CSS background inlining.inliner: The URL-rewriting engine.urlCache: Per-render resource cache.options: The live, resolved options for the current/last render.copyOptions(options): Normalizes and writes options toimpl.options.resetUrlCache(): Clears theurlCache.
domtoimage.impl;Manage resource caching with `impl.urlCache`
mainimpl.urlCacheis an array used by the resource fetching core to deduplicate and cache fetches within a single render.Each entry follows the shape
{ url: string, promise: Promise | null }. If multiple requests are made for the same URL, they will share the same in-flight or settled promise.The cache is cleared at the start and end of every render. You can manually clear it using
impl.resetUrlCache().Manage external resources with requestInterceptor, corsImg, and imagePlaceholder
mainThe library provides three distinct ways to handle external resources (images, fonts, stylesheets) that may fail due to CORS or network issues. They compose in a specific order:
requestInterceptor(General Primitive): A function that can supply a resource before a fetch (whenstatus === undefined) or recover one after a failure (whenstatusis numeric). Use this for custom caching or complex programmatic logic.corsImg(CORS Proxy Convenience): A declarative way to route cross-origin images through a proxy. It performs an XHR with your configured settings.imagePlaceholder(Failure Convenience): A staticdata:URL substituted when an image fetch fails. This is a shorthand for the failure logic inrequestInterceptor.
Execution Order for a URL:
requestInterceptor(pre-fetch) $\rightarrow$corsImgrewrite $\rightarrow$ fetch $\rightarrow$requestInterceptor(failure) $\rightarrow$imagePlaceholder(images only) $\rightarrow$ drop.Note: A fetch is considered a failure if it results in a network error, timeout, non-2xx status, or if the response cannot be decoded as a usable resource.
How dom-to-image-more works
mainThe library converts DOM nodes to images by leveraging the SVG
<foreignObject>tag, which allows embedding arbitrary HTML inside an SVG.The Rendering Process
- Cloning: The original DOM node is recursively cloned.
- Style Computation: Computed styles for the node and all sub-nodes are copied to the clone. Pseudo-elements (
::before,::after) are recreated as real elements to preserve styles. - Font Embedding:
@font-facedeclarations are parsed, files are downloaded, base64-encoded, and inlined asdata:URLs within a<style>element. - Image Embedding:
<img>sources and CSSbackgroundimages are inlined. - Serialization: The cloned node is serialized to XML, wrapped in a
<foreignObject>inside an SVG, and converted to a data URL. - Canvas Rendering: To produce PNG or raw pixel data, the SVG is rendered onto an off-screen canvas.
Advanced Features
- SVG
<use>Inlining: Resolves same-document<use>references by injecting the target element into a hidden<defs>block in the output. - Style Optimization: Uses
styleCachingto only emit properties that differ from browser defaults, reducing SVG size. - Shadow DOM: Supports open shadow roots and slot-assigned nodes.
- Form State: Captures current values of
<input>and<textarea>elements. - Non-Mutating: All operations occur on a detached clone; no changes are made to your live DOM.
Handle Server-Side Rendering (SSR) constraints
mainThe library requires a browser DOM to function because it reads computed styles and rasterizes via the browser. While it can be imported safely in SSR environments (like Next.js or Angular Universal), calling
toPng,toSvg, or other render methods will reject with ana browser DOM is required (SSR)error.To avoid errors, ensure render calls only execute in the client-side environment using checks like
typeof window !== 'undefined'or framework-specific guards (e.g., Angular'sisPlatformBrowser).Install dom-to-image-more via NPM
mainInstall the package using npm:
npm install dom-to-image-moreThen, import or require it in your project depending on your module system:
/* in ES 6 */ import domtoimage from 'dom-to-image-more'; /* in ES 5 */ var domtoimage = require('dom-to-image-more');Browser and Environment Compatibility
mainSupported Browsers
- Chrome & Firefox: Fully supported. Chrome is recommended for large DOM trees due to better SVG support and
CSSStyleDeclaration.cssTextsupport. - Safari: Not supported due to strict security models on the
<foreignObject>tag and flaky image-decode timing. Workaround: UsetoSvgand render on the server. - Internet Explorer: Not supported (lacks SVG
<foreignObject>support).
Required JavaScript Features
The library requires modern JavaScript features:
globalThis(ES2020)Promise.prototype.finally(ES2018)
Minimum versions:
- Chrome 71+
- Edge 79+
- Firefox 65+
- Opera 58+
- Safari 12.1+
- Node 12+
- Chrome & Firefox: Fully supported. Chrome is recommended for large DOM trees due to better SVG support and
Use TypeScript with dom-to-image-more
mainThe package includes its own type definitions (
dom-to-image-more.d.ts), so you do not need to install separate@typespackages.If using
esModuleInterop: truein yourtsconfig.json, use a standard default import. Otherwise, use therequiresyntax.Note: The
implmember is typed asunknownto discourage dependency on internal implementation details.import domtoimage, { Options } from 'dom-to-image-more'; const node = document.getElementById('my-node')!; const options: Options = { quality: 0.95, styleCaching: 'relaxed' }; domtoimage.toPng(node, options).then((dataUrl: string) => { /* ... */ });Ensure fonts and stylesheets are fully loaded before capturing
mainTo prevent missing glyphs or incorrect metrics, ensure all web fonts and stylesheets are fully loaded before calling a capture method. While the library waits for fonts already being loaded via
document.fonts.ready, it cannot wait for new<link rel="stylesheet">elements added in the same execution tick.Best Practice: Await
document.fonts.readyor listen for theloadevent on your stylesheet<link>elements before initiating the capture.Render hidden elements with ensureShown
mainBy default, nodes with
display: noneoropacity: 0are not rendered. However, a node hidden by an ancestor'svisibility: hiddenis rendered because the library forces the requested root node to be visible.To render elements that have
display: noneoropacity: 0applied directly to them, use theensureShownoption. Note that this does not work if a parent/ancestor is set todisplay: none; in that case, you must move the node or reveal the ancestor manually.Configure high-DPI / Retina output with pixelRatio
mainBy default, the library rasterizes at 1× CSS-pixel resolution, which may appear soft on high-DPI/Retina displays. To achieve a crisp, high-resolution capture, pass
window.devicePixelRatioto thepixelRatiooption.Note: Browsers have canvas size limits. If the resulting dimensions (
width × height × scale × pixelRatio) exceed these limits, the library will clamp the multiplier and log a warning to prevent a blank or partial bitmap.// Example for crisp Retina output domtoimage.toPng(node, { pixelRatio: window.devicePixelRatio });