dom-to-image-more

repository·main·Indexed 20 days ago

https://github.com/idisposable/dom-to-image-more

A 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.

Tokens
10.4K
Snippets
17
Records
52
Agent score
70%

What's inside dom-to-image-more

  1. Understand the `domtoimage.impl` internal surface

    main

    The domtoimage.impl object 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 impl include:

    • 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 to impl.options.
    • resetUrlCache(): Clears the urlCache.
    domtoimage.impl;
  2. Manage resource caching with `impl.urlCache`

    main

    impl.urlCache is 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().

  3. Manage external resources with requestInterceptor, corsImg, and imagePlaceholder

    main

    The 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:

    1. requestInterceptor (General Primitive): A function that can supply a resource before a fetch (when status === undefined) or recover one after a failure (when status is numeric). Use this for custom caching or complex programmatic logic.
    2. corsImg (CORS Proxy Convenience): A declarative way to route cross-origin images through a proxy. It performs an XHR with your configured settings.
    3. imagePlaceholder (Failure Convenience): A static data: URL substituted when an image fetch fails. This is a shorthand for the failure logic in requestInterceptor.

    Execution Order for a URL: requestInterceptor (pre-fetch) $\rightarrow$ corsImg rewrite $\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.

  4. How dom-to-image-more works

    main

    The library converts DOM nodes to images by leveraging the SVG <foreignObject> tag, which allows embedding arbitrary HTML inside an SVG.

    The Rendering Process

    1. Cloning: The original DOM node is recursively cloned.
    2. 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.
    3. Font Embedding: @font-face declarations are parsed, files are downloaded, base64-encoded, and inlined as data: URLs within a <style> element.
    4. Image Embedding: <img> sources and CSS background images are inlined.
    5. Serialization: The cloned node is serialized to XML, wrapped in a <foreignObject> inside an SVG, and converted to a data URL.
    6. 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 styleCaching to 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.
  5. Handle Server-Side Rendering (SSR) constraints

    main

    The 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 an a 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's isPlatformBrowser).

  6. Install dom-to-image-more via NPM

    main

    Install the package using npm:

    npm install dom-to-image-more

    Then, 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');
  7. Browser and Environment Compatibility

    main

    Supported Browsers

    • Chrome & Firefox: Fully supported. Chrome is recommended for large DOM trees due to better SVG support and CSSStyleDeclaration.cssText support.
    • Safari: Not supported due to strict security models on the <foreignObject> tag and flaky image-decode timing. Workaround: Use toSvg and 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+
  8. Use TypeScript with dom-to-image-more

    main

    The package includes its own type definitions (dom-to-image-more.d.ts), so you do not need to install separate @types packages.

    If using esModuleInterop: true in your tsconfig.json, use a standard default import. Otherwise, use the require syntax.

    Note: The impl member is typed as unknown to 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) => {
        /* ... */
    });
  9. Ensure fonts and stylesheets are fully loaded before capturing

    main

    To 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.ready or listen for the load event on your stylesheet <link> elements before initiating the capture.

  10. Render hidden elements with ensureShown

    main

    By default, nodes with display: none or opacity: 0 are not rendered. However, a node hidden by an ancestor's visibility: hidden is rendered because the library forces the requested root node to be visible.

    To render elements that have display: none or opacity: 0 applied directly to them, use the ensureShown option. Note that this does not work if a parent/ancestor is set to display: none; in that case, you must move the node or reveal the ancestor manually.

  11. Configure high-DPI / Retina output with pixelRatio

    main

    By 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.devicePixelRatio to the pixelRatio option.

    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 });