{"_id":"@dynaruid/dom-to-canvas","name":"@dynaruid/dom-to-canvas","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@dynaruid/dom-to-canvas","version":"0.2.0","description":"Generates an image from a DOM node using HTML5 canvas and SVG","license":"MIT","author":{"name":"Dynaruid"},"repository":{"type":"git","url":"git+https://github.com/Dynaruid/dom-to-canvas.git","directory":"packages/dom-to-canvas"},"homepage":"https://github.com/Dynaruid/dom-to-canvas/tree/main/packages/dom-to-canvas","bugs":{"url":"https://github.com/Dynaruid/dom-to-canvas/issues"},"contributors":[{"name":"Marc Brooks","url":"https://about.me/IDisposable"},{"name":"Anatolii Saienko","url":"https://github.com/tsayen"},{"name":"Paul Bakaus","url":"http://paulbakaus.com/"}],"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","type":"module","scripts":{"build":"tsc -p tsconfig.build.json","prepack":"npm run build","test":"bun test","typecheck":"tsc --noEmit"},"exports":{".":{"types":"./dist/index.d.ts","deno":"./index.ts","import":"./dist/index.js","default":"./dist/index.js"}},"publishConfig":{"access":"public"},"keywords":["dom","image","raster","render","html","canvas","svg","png"],"devDependencies":{"@types/bun":"latest","@types/jsdom":"^28.0.1","jsdom":"^29.0.2","typescript":"^5.9.3"},"_id":"@dynaruid/dom-to-canvas@0.2.0","gitHead":"c684f2ff9efb34d7b6147bb000767f495eda9a17","_nodeVersion":"22.14.0","_npmVersion":"11.4.2","dist":{"integrity":"sha512-LQo6//H36IqsNEkr3vcMwMF7w4ZarECpc9XJLWTg5siDMNcUAjFMfgw5XD4Xq5fTfgNdyqfoc3ubqvTfW/N3Gg==","shasum":"bf8d55a24204eec4745f1b77c4c3eb6571d4d49e","tarball":"https://registry.npmjs.org/@dynaruid/dom-to-canvas/-/dom-to-canvas-0.2.0.tgz","fileCount":63,"unpackedSize":191890,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDgifkxUCHWA3yFN3hySTs6c9ZDfgBXCGjHsy9L7z9cmQIgH3FF2s+x6auNZdQrI8ROwVuhFSmuBadMFytCNUdTZUo="}]},"_npmUser":{"name":"dynaruid","email":"dynaruid@gmail.com"},"directories":{},"maintainers":[{"name":"dynaruid","email":"dynaruid@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dom-to-canvas_0.2.0_1777430650387_0.11884847332318005"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-29T02:44:10.303Z","0.2.0":"2026-04-29T02:44:10.514Z","modified":"2026-04-29T02:44:10.726Z"},"maintainers":[{"name":"dynaruid","email":"dynaruid@gmail.com"}],"description":"Generates an image from a DOM node using HTML5 canvas and SVG","homepage":"https://github.com/Dynaruid/dom-to-canvas/tree/main/packages/dom-to-canvas","keywords":["dom","image","raster","render","html","canvas","svg","png"],"repository":{"type":"git","url":"git+https://github.com/Dynaruid/dom-to-canvas.git","directory":"packages/dom-to-canvas"},"contributors":[{"name":"Marc Brooks","url":"https://about.me/IDisposable"},{"name":"Anatolii Saienko","url":"https://github.com/tsayen"},{"name":"Paul Bakaus","url":"http://paulbakaus.com/"}],"author":{"name":"Dynaruid"},"bugs":{"url":"https://github.com/Dynaruid/dom-to-canvas/issues"},"license":"MIT","readme":"# dom-to-canvas\n\n[![JSR](https://jsr.io/badges/@dynaruid/dom-to-canvas)](https://jsr.io/@dynaruid/dom-to-canvas)\n[![JSR Score](https://jsr.io/badges/@dynaruid/dom-to-canvas/score)](https://jsr.io/@dynaruid/dom-to-canvas)\n[![JSR Weekly Downloads](https://jsr.io/badges/@dynaruid/dom-to-canvas/weekly-downloads)](https://jsr.io/@dynaruid/dom-to-canvas)\n\nGenerate an image from a DOM node with HTML5 canvas and SVG.\nTypeScript rewrite of [dom-to-image-more](https://github.com/1904labs/dom-to-image-more), published on JSR.\n\nThis package renders browser DOM nodes. Use it in a browser or a browser-like DOM environment.\n\n## Why\n\n- Export any DOM subtree as PNG, JPEG, SVG, Blob, canvas, or raw pixel data.\n- Keep a live canvas handle when you need repeated or continuous rendering.\n- Keep computed styles, form values, fonts, and images in the rendered output.\n- Use one API across browser apps, tests, and browser-like DOM environments.\n\n## Install\n\n### Deno / JSR\n\n```bash\ndeno add jsr:@dynaruid/dom-to-canvas\n```\n\n### npm / Node / Bun\n\n```bash\nnpm install @dynaruid/dom-to-canvas\n```\n\n```bash\npnpm add @dynaruid/dom-to-canvas\n```\n\n```bash\nyarn add @dynaruid/dom-to-canvas\n```\n\n```bash\nbun add @dynaruid/dom-to-canvas\n```\n\n### Deno via npm\n\n```bash\ndeno add npm:@dynaruid/dom-to-canvas\n```\n\nJSR is the recommended path for Deno. The npm package ships ESM output in `dist/`, while Deno consumers can keep using the source TypeScript entry.\n\n## Quick Start\n\n### One-shot export\n\n```ts\nimport {\n  copyPixelData,\n  getCanvas,\n  toPng,\n  toSvg,\n  toJpeg,\n  toBlob,\n  toCanvas,\n  toPixelData\n} from \"@dynaruid/dom-to-canvas\";\n\n// PNG data URL\nconst dataUrl = await toPng(\n  document.getElementById(\"my-node\")!\n);\n\n// SVG data URL\nconst svgDataUrl = await toSvg(node, {\n  bgcolor: \"#fff\",\n  width: 800,\n  height: 600\n});\n\n// JPEG with quality\nconst jpegUrl = await toJpeg(node, { quality: 0.8 });\n\n// Blob\nconst blob = await toBlob(node);\n\n// Canvas element\nconst canvas = await toCanvas(node, { scale: 2 });\n\n// Raw pixel data\nconst pixels = await toPixelData(node);\n\n// Write into an existing buffer\nconst target = new Uint8Array(4 * 800 * 600);\nconst result = await copyPixelData(node, target);\nconsole.log(result.width, result.height);\n```\n\n### Live canvas\n\n```ts\nimport { getCanvas } from \"@dynaruid/dom-to-canvas\";\n\nconst handle = getCanvas(node, {\n  scale: 2,\n  mode: \"continuous\"\n});\n\ndocument.body.append(handle.canvas);\n\nawait handle.render();\nhandle.start();\n\n// Later\nhandle.stop();\nhandle.update({ bgcolor: \"#111\" });\nawait handle.render();\nhandle.dispose();\n```\n\n## One-shot vs Live\n\n| API                                     | Result                       | Notes                                     |\n| --------------------------------------- | ---------------------------- | ----------------------------------------- |\n| `getCanvas(node, options?)`             | `CanvasHandle`               | Live canvas owner with lifecycle controls |\n| `toSvg(node, options?)`                 | `Promise<string>`            | SVG data URL                              |\n| `toPng(node, options?)`                 | `Promise<string>`            | PNG data URL                              |\n| `toJpeg(node, options?)`                | `Promise<string>`            | JPEG data URL                             |\n| `toBlob(node, options?)`                | `Promise<Blob>`              | PNG `Blob`                                |\n| `toPixelData(node, options?)`           | `Promise<Uint8ClampedArray>` | Copies fresh pixel data                   |\n| `copyPixelData(node, target, options?)` | `Promise<PixelCopyResult>`   | Writes into a caller-owned buffer         |\n| `toCanvas(node, options?)`              | `Promise<HTMLCanvasElement>` | Deprecated one-shot alias                 |\n\n## CanvasHandle\n\n`getCanvas` returns a handle with these members:\n\n```ts\ninterface CanvasHandle {\n  readonly canvas: HTMLCanvasElement;\n  readonly node: Node;\n  readonly options: Options;\n  readonly isRendering: boolean;\n  readonly isRunning: boolean;\n  readonly frame: number;\n\n  render(options?: Options): Promise<HTMLCanvasElement>;\n  start(): void;\n  stop(): void;\n  update(options: Options): void;\n  resize(options?: Options): void;\n  dispose(): void;\n}\n```\n\n## API\n\n### `getCanvas(node, options?): CanvasHandle`\n\n### `toSvg(node, options?): Promise<string>`\n\n### `toPng(node, options?): Promise<string>`\n\n### `toJpeg(node, options?): Promise<string>`\n\n### `toBlob(node, options?): Promise<Blob>`\n\n### `copyPixelData(node, target, options?): Promise<PixelCopyResult>`\n\n### `toCanvas(node, options?): Promise<HTMLCanvasElement>`\n\nDeprecated compatibility alias for one-shot canvas export.\n\n### `toPixelData(node, options?): Promise<Uint8ClampedArray>`\n\n### `Renderer`\n\nReusable low-level canvas owner for advanced scenarios.\n\n### `RenderSession`\n\nLow-level per-render resource session used internally by one-shot and live paths.\n\n## Options\n\n| Option                  | Type                           | Default    | Description                         |\n| ----------------------- | ------------------------------ | ---------- | ----------------------------------- |\n| `filter`                | `(node: Node) => boolean`      | —          | Filter out nodes                    |\n| `bgcolor`               | `string`                       | —          | Background color                    |\n| `width`                 | `number`                       | —          | Output width                        |\n| `height`                | `number`                       | —          | Output height                       |\n| `style`                 | `Record<string, string>`       | —          | Inline styles to apply              |\n| `quality`               | `number`                       | `1.0`      | JPEG quality (0–1)                  |\n| `scale`                 | `number`                       | `1`        | Scale multiplier                    |\n| `mode`                  | `\"dirty\" \\| \"continuous\"`      | `\"dirty\"`  | Live handle invalidation mode       |\n| `imagePlaceholder`      | `string`                       | —          | Data URL fallback for failed images |\n| `cacheBust`             | `boolean`                      | `false`    | Bypass cache for resources          |\n| `useCredentials`        | `boolean`                      | `false`    | Send credentials while fetching     |\n| `useCredentialsFilters` | `(string \\| RegExp)[]`         | `[]`       | Restrict credentialed fetches       |\n| `httpTimeout`           | `number`                       | `30000`    | Resource fetch timeout in ms        |\n| `copyDefaultStyles`     | `boolean`                      | `true`     | Copy default element styles         |\n| `styleCaching`          | `\"strict\" \\| \"relaxed\"`        | `\"strict\"` | Style computation cache strategy    |\n| `disableEmbedFonts`     | `boolean`                      | `false`    | Skip font embedding                 |\n| `disableInlineImages`   | `boolean`                      | `false`    | Skip image inlining                 |\n| `corsImg`               | `CorsImgConfig`                | —          | Proxy cross-origin image fetches    |\n| `onclone`               | `(clone: HTMLElement) => void` | —          | Callback on cloned DOM              |\n| `adjustClonedNode`      | `(orig, clone, after) => void` | —          | Adjust cloned nodes                 |\n| `filterStyles`          | `(el, prop) => boolean`        | —          | Filter style properties             |\n\n## CSS Animation Policy\n\n- `mode: \"dirty\"` is the default for live handles. It re-renders on DOM mutation, text changes, attribute changes, observed element resize, and explicit `update()` or `resize()` calls.\n- CSS keyframe animations and transitions often change computed styles without mutating the DOM. If the canvas must track those frames, use `mode: \"continuous\"`.\n- One-shot exports ignore `mode` entirely.\n\n## Notes\n\n- The package needs `window`, `document`, canvas, and image APIs.\n- Cross-origin images and fonts still depend on the browser's security model.\n- For Node-based tests, use a browser-like DOM such as `jsdom`.\n\n## React\n\nIf you need React bindings, see [`@dynaruid/dom-to-canvas-react`](https://jsr.io/@dynaruid/dom-to-canvas-react).\n\n## Links\n\n- [JSR package](https://jsr.io/@dynaruid/dom-to-canvas)\n- [API docs](https://jsr.io/@dynaruid/dom-to-canvas/doc)\n- [GitHub repository](https://github.com/Dynaruid/dom-to-canvas)\n\n## Development\n\n```bash\nbun test\nbun run typecheck\n```\n\n## License\n\nMIT.\n\nThis project is derived from dom-to-image-more. The upstream author credits are preserved in LICENSE and package metadata.\n","readmeFilename":"README.md","_rev":"1-832822bd6e059be8c499defc72fffe49"}