captureDOM function in snapDOM codebase - part 1
In this article, we review captureDOM function in snapDOM codebase. This review is split into 2 parts. We will look at:
-
captureDOM overview
-
options
-
prepareClone function
-
inlineImages function
-
inlineBackgroundImages function

captureDOM overview
capture.js has 129 LOC at the time of writing this article. captureDOM is a core function in snapDOM.
This function gets called when you call snapdom.capture function as shown below:
snapdom.capture = async (el, options = {}) => { const url = await captureDOM(el, options);
This above code snippet is picked from snapdom.js.
options
The following are the available options passed as a parameter to the captureDOM function
const { compress = true, embedFonts = false, fast = true, scale = 1, useProxy = ''} = options;
For a comprehensive list of supported options, check out the docs.
prepareClone function
The following code is picked from snapdom/src/core/prepare.js:
/** * Prepares a clone of an element for capture, inlining pseudo-elements and generating CSS classes. * * @param {Element} element - Element to clone * @param {boolean} [compress=false] - Whether to compress style keys * @param {boolean} [embedFonts=false] - Whether to embed custom fonts * @param {Object} [options={}] - Capture options * @param {string[]} [options.exclude] - CSS selectors for elements to exclude * @param {Function} [options.filter] - Custom filter function * @returns {Promise<Object>} Object containing the clone, generated CSS, and style cache */ export async function prepareClone(element, compress = false, embedFonts = false, options = {}) { ... }
This function has a comment explaining what it does, along with the parameters description.
inlineImages function
The following code is picked from images.js
/** * Converts all <img> elements in the clone to data URLs or replaces them with placeholders if loading fails. * * @param {Element} clone - Clone of the original element * @param {Object} [options={}] - Options for image processing * @returns {Promise<void>} Promise that resolves when all images are processed */ export async function inlineImages(clone, options = {}) { const imgs = Array.from(clone.querySelectorAll("img")); const processImg = async (img) => { const src = img.src; try { const dataUrl = await fetchImage(src, { useProxy: options.useProxy }); img.src = dataUrl; if (!img.width) img.width = img.naturalWidth || 100; if (!img.height) img.height = img.naturalHeight || 100; } catch { const fallback = document.createElement("div"); fallback.style = `width: ${img.width || 100}px; height: ${img.height || 100}px; background: #ccc; display: inline-block; text-align: center; line-height: ${img.height || 100}px; color: #666; font-size: 12px;`; fallback.innerText = "img"; img.replaceWith(fallback); } }; for (let i = 0; i < imgs.length; i += 4) { const group = imgs.slice(i, i + 4).map(processImg); await Promise.allSettled(group); } }
This function converts an image to data URL and if the image loading fails, it shows a placeholder in the image captured as a fallback.
inlineBackgroundImages function
The following code is picked from modules/background.js
/** * Recursively inlines background-related images and masks from the source element to its clone. * * This function walks through the source DOM tree and its clone, copying inline styles for * background images, masks, and border images to ensure the clone retains all visual image * resources inline (e.g., data URLs), avoiding external dependencies. * * It also preserves the `background-color` property if it is not transparent. * * Special handling is done for `border-image` related properties: the * `border-image-slice`, `border-image-width`, `border-image-outset`, and `border-image-repeat` * are only copied if `border-image` or `border-image-source` are present and active. * * @param {HTMLElement} source The original source element from which styles are read. * @param {HTMLElement} clone The cloned element to which inline styles are applied. * @param {Object} [options={}] Optional parameters passed to image inlining functions. * @returns {Promise<void>} Resolves when all inlining operations (including async image fetches) complete. */ export async function inlineBackgroundImages(source, clone, options = {}) { ... }
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.
References:
-
https://github.com/zumerlab/snapdom/blob/main/src/core/capture.js#L28
-
https://github.com/zumerlab/snapdom/blob/main/src/api/snapdom.js#L261
-
https://github.com/zumerlab/snapdom?tab=readme-ov-file#options
-
https://github.com/zumerlab/snapdom/blob/main/src/core/prepare.js#L25
-
https://github.com/zumerlab/snapdom/blob/main/src/modules/images.js#L15
-
https://github.com/zumerlab/snapdom/blob/main/src/modules/background.js#L26