Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@zumer/snapdom-plugins

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@zumer/snapdom-plugins

Official plugins for SnapDOM

Source
npmnpm
Version
2.1.0
Version published
Weekly downloads
257
307.94%
Maintainers
1
Weekly downloads
 
Created
Source

@zumer/snapdom-plugins

Official plugins for SnapDOM — extend and transform DOM captures with zero core changes.

Install

npm install @zumer/snapdom-plugins

Usage

Import plugins individually (recommended for tree-shaking):

import { snapdom } from '@zumer/snapdom';
import { filter } from '@zumer/snapdom-plugins/filter';
import { timestampOverlay } from '@zumer/snapdom-plugins/timestamp-overlay';

const result = await snapdom(element, {
  plugins: [filter({ preset: 'grayscale' }), timestampOverlay()]
});
const png = await result.toPng();

Or import everything at once:

import { filter, timestampOverlay, replaceText } from '@zumer/snapdom-plugins';

CDN (no install):

import { snapdom } from 'https://esm.sh/@zumer/snapdom';
import { filter } from 'https://esm.sh/@zumer/snapdom-plugins/filter';

Plugins

filter

Applies CSS filter effects to the captured clone.

import { filter } from '@zumer/snapdom-plugins/filter';

snapdom(el, { plugins: [filter({ preset: 'grayscale' })] });
OptionTypeDefaultDescription
presetstring'grayscale' | 'sepia' | 'blur' | 'invert' | 'vintage' | 'dramatic'
filterstring''Raw CSS filter string, e.g. 'blur(2px) contrast(1.2)'

timestamp-overlay

Adds a translucent timestamp label to the captured clone.

import { timestampOverlay } from '@zumer/snapdom-plugins/timestamp-overlay';

snapdom(el, { plugins: [timestampOverlay({ position: 'top-right', format: 'date' })] });
OptionTypeDefaultDescription
formatstring | function'datetime''datetime' | 'date' | 'time' | 'iso' | custom (Date) => string
positionstring'bottom-right''top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
backgroundstring'rgba(0,0,0,0.6)'Label background color
colorstring'#fff'Label text color
fontSizenumber11Font size in px

replace-text

Find-and-replace text in the captured clone. Supports strings and regex.

import { replaceText } from '@zumer/snapdom-plugins/replace-text';

snapdom(el, {
  plugins: [replaceText({
    replacements: [
      { find: 'DRAFT', replace: 'APPROVED' },
      { find: /\d{4}-\d{2}-\d{2}/, replace: '[REDACTED]' }
    ]
  })]
});
OptionTypeDefaultDescription
replacementsArray<{ find: string|RegExp, replace: string }>[]List of find/replace pairs

color-tint

Tints the entire capture to a specified color using a mix-blend-mode overlay.

import { colorTint } from '@zumer/snapdom-plugins/color-tint';

snapdom(el, { plugins: [colorTint({ color: 'royalblue', opacity: 0.4 })] });
OptionTypeDefaultDescription
colorstring'red'Any CSS color value
opacitynumber1Overlay opacity (0–1)

ascii-export

Adds a toAscii() export method that converts captures to ASCII art.

import { asciiExport } from '@zumer/snapdom-plugins/ascii-export';

const result = await snapdom(el, { plugins: [asciiExport({ width: 100 })] });
const art = await result.toAscii();
console.log(art);
OptionTypeDefaultDescription
widthnumber80Character width of output
charsetstring' .:-=+*#%@'Characters from lightest to darkest
invertbooleanfalseInvert luminance mapping

pdf-image

Exports the capture as a PNG embedded in a downloadable PDF (A4). Adds a toPdfImage() method.

import { pdfImage } from '@zumer/snapdom-plugins/pdf-image';

const result = await snapdom(el, { plugins: [pdfImage({ orientation: 'landscape' })] });
await result.toPdfImage(); // triggers download
OptionTypeDefaultDescription
orientationstring'portrait''portrait' | 'landscape'
qualitynumber0.92JPEG quality (0–1)
filenamestring'capture.pdf'Download filename

html-in-canvas

Uses the experimental WICG drawElementImage API for direct DOM-to-canvas rendering where supported. Falls back gracefully.

import { htmlInCanvas } from '@zumer/snapdom-plugins/html-in-canvas';

snapdom(el, { plugins: [htmlInCanvas()] });

This plugin uses an experimental browser API and may not work in all environments.

agent-map

Produces a Set-of-Mark package for visual agents: an annotated screenshot with numbered badges on interactive elements, plus a compact JSON map from badge index → role / accessible name / bbox / state. One call, fully client-side.

import { agentMap } from '@zumer/snapdom-plugins/agent-map';

const result = await snapdom(el, { plugins: [agentMap()] });
const { image, map, dimensions } = await result.toAgentMap();

// image: data URL of the screenshot with numbered red badges overlaid
// map:   [{ i, n, r, b, s? }, …] — index, name, role, bbox, state
// Agent says "click element 2" → map[2].b gives [x, y, w, h]

Map entry shape (default fields: 'minimal'):

KeyTypeDescription
inumberIndex matching the badge drawn on the image
nstringAccessible name (aria-label → labelledby → alt → title → labels → textContent, truncated to 60 chars)
rstringARIA-style role (button, link, checkbox, radio, textbox, combobox, slider, heading, …) — derived from role attribute or implicit role of the element
b[x, y, w, h]Bounding box in pixels, scaled against maxImageWidth
sobject?State: included only when at least one key is meaningful — checked, disabled, focus, expanded, pressed, selected, value, open, selectedText, covered

Example map for a checkout form:

[
  { i: 0, n: 'Email',         r: 'textbox',  b: [28,  80, 280, 34], s: { value: 'ada@example.com' } },
  { i: 1, n: 'Send product updates', r: 'checkbox', b: [28, 134,  13, 13], s: { checked: true } },
  { i: 2, n: 'Apply coupon',  r: 'button',   b: [28, 176, 114, 38], s: { expanded: false } },
  { i: 3, n: 'Remove coupon', r: 'button',   b: [150, 176, 140, 38], s: { disabled: true } },
  { i: 4, n: 'Pay $53.90',    r: 'button',   b: [28, 220,  97, 38] }
]

Options

OptionTypeDefaultDescription
image'annotated' | 'raw' | false'annotated''annotated' overlays numbered badges; 'raw' skips badges; false skips image generation entirely (no canvas draw, no toDataURL — cheapest path).
fields'minimal' | 'full''minimal''full' adds t (raw text content) and a (meaningful attributes) per entry.
semanticbooleanfalseInclude non-interactive structural elements (headings, paragraphs, landmarks). Off by default — agents act on interactive.
maxImageWidthnumber1024Downscale target for the image; bboxes rescale to match.
imageFormat'png' | 'jpg' | 'webp''png'Image format (only used when image is rendered).
imageQualitynumber0.8Quality for lossy formats.
interactiveSelectorstringsee belowCSS selector for interactive elements.
semanticSelectorstringsee belowCSS selector for semantic elements (used when semantic: true).
labelStyleobject{}Override badge styles.

Defaults:

  • interactive: a[href], button, input, select, textarea, [role="button"|"link"|"tab"|"menuitem"|"checkbox"|"radio"|"switch"|"slider"|"combobox"|"textbox"], [tabindex]:not([tabindex="-1"]), summary, [contenteditable="true"]
  • semantic: h1–h6, nav, main, article, section, header, footer, figcaption, blockquote, legend, p

Per-call options override constructor options (e.g. result.toAgentMap({ image: false })).

When to use

  • Visual agents using Set-of-Mark prompting — one call gives you both the labelled image and the coordinate lookup table.
  • Computer-use / browser-agent harnesses that need click coordinates for a vision model's output.
  • Visual QA with an LLM judge — compare before/after captures with structured element identity.
  • Dataset generation for vision-LLM fine-tuning — (image, map) pairs.

Because it runs entirely in the browser, it works in contexts where Playwright / Puppeteer can't: Chrome extensions, SaaS web apps capturing the user's own page, Electron apps capturing their own window.

Plugin registration

Global (applies to all captures):

import { snapdom } from '@zumer/snapdom';
import { filter } from '@zumer/snapdom-plugins/filter';

snapdom.plugins(filter({ preset: 'sepia' }));

Per-capture (overrides global for that call):

const result = await snapdom(element, {
  plugins: [filter({ preset: 'dramatic' })]
});

Per-capture plugins run before global ones. Duplicate plugin names are skipped automatically.

Build your own plugin

Use the template to scaffold a new plugin in seconds:

npx degit zumerlab/snapdom/packages/plugin-template my-plugin

See PLUGIN_SPEC.md for the full hook specification and CONTRIBUTING_PLUGINS.md to get your plugin listed on the community page.

License

MIT

Keywords

snapdom

FAQs

Package last updated on 26 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts