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

prompt-export

Adds a toPrompt() export method that returns an LLM-ready package: a structured element map with bounding boxes, a pre-formatted prompt text, and (optionally) an annotated screenshot. Tuned for vision-language models, browser-agent pipelines, visual QA, and any workflow that pairs a capture with structured metadata.

import { promptExport } from '@zumer/snapdom-plugins/prompt-export';

const result = await snapdom(el, { plugins: [promptExport()] });
// Default: no image, just the structured map + prompt text (cheapest)
const { elements, prompt, dimensions } = await result.toPrompt();

To also include the annotated image (for tasks that truly depend on vision):

const result = await snapdom(el, {
  plugins: [promptExport({ include: ['image', 'elements', 'prompt'] })]
});
const { image, elements, prompt, dimensions } = await result.toPrompt();

The returned object (fields present only if requested via include):

FieldTypeDescription
elementsArrayOne entry per detected element: { id, tag, type, name, text, bbox, attributes, state?, styles?, covered? }
promptstringPre-formatted text describing interactive + semantic elements
imagestringData URL of the (optionally annotated) screenshot — only when include contains 'image'
dimensions{width, height}Scaled dimensions (always present)

elements is split into two types:

  • 'interactive' — buttons, links, inputs, [role]/[tabindex] targets. These get numbered badges overlaid on the screenshot when annotate is on.
  • 'semantic' — headings, paragraphs, <nav>, <main>, images with alt, table cells, etc. Structural context, not overlaid.

Each bbox is in pixel coordinates of the returned image (scaled against maxImageWidth).

Each interactive entry also carries:

  • name — the computed accessible name (aria-label → labelledby → alt → title → labels[0] → textContent)
  • state — runtime state: { checked, disabled, focus, open, value, selectedText } (only keys that apply)
  • styles — visually-meaningful computed props filtered to drop defaults
  • covered: true when another element is painted on top of the bbox center (an agent won't click through a modal)
// Example — feed a vision-capable LLM
const { image, elements } = await result.toPrompt({
  include: ['image', 'elements', 'prompt']
});

// image is a data URL → pass as image input
// elements is JSON → pass as structured context alongside the image
// "Click element [3]" → look up elements[3].bbox for real coordinates
OptionTypeDefaultDescription
includestring[]['elements', 'prompt']Fields to return. Add 'image' for tasks that need vision (chart content, layout QA, canvas). Use ['prompt'] for the cheapest text-only mode.
annotatebooleantrueOverlay numbered badges on interactive elements (only affects the image when included)
promptMode'compact' | 'verbose''compact'Prompt text verbosity. Compact omits coords when badges are on the image.
includeCoordsbooleantrueInclude bbox in the prompt text
imageFormat'png' | 'jpg' | 'webp''png'Output image format (only used when image is included)
imageQualitynumber0.8Quality for lossy formats (0–1)
maxImageWidthnumber1024Max width in px; downscales and rescales bboxes if larger
interactiveSelectorstringsee belowCSS selector for the interactive element set
semanticSelectorstringsee belowCSS selector for the semantic element set
labelStyleobject{}Override styles for the numbered badges (position, color, backgroundColor, etc.)

Defaults:

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

Both per-call options (opts.include, opts.imageFormat, etc.) and constructor options are supported; per-call wins.

The image is the most expensive part of toPrompt() to produce (canvas draw + data-URL serialization), so the default skips it. Add 'image' to include when the task actually uses vision:

// Vision-dependent task (chart content, layout QA, visual diff)
await result.toPrompt({ include: ['image', 'elements', 'prompt'] });

// Pure structured agent loop (cheapest)
await result.toPrompt({ include: ['prompt'] });

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 24 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