@polotno/html-export
v0.10.1
Published
Convert plain Polotno JSON into rendered HTML in browsers or Node.js with a DOM implementation
Readme
@polotno/html-export — Polotno JSON to HTML
Convert Polotno design JSON into HTML markup without loading the editor.
Works without the editor. Pass plain Polotno design JSON from any source.
Runtime: Browser first. Node.js requires a DOM implementation such as jsdom.
License: Non-production use is free, with no time limit. Production use requires a valid Polotno subscription. Read the license.
Install
npm install @polotno/html-exportUsage
import { jsonToHTML } from '@polotno/html-export';
const html = await jsonToHTML(store.toJSON());jsonToHTML accepts plain design JSON — no editor or store required.
Options:
elementHook({ dom, element })— post-process each element's virtual node.textOverflow—'change-font-size'(default) |'resize'|'ellipsis'|'fit'; the global flag for text without its owntextOverflow. The default shrinks the font to fit — the same default polotno-node exports use. An element's owntextOverflow,maxLinesand size bounds apply either way. The fit is measured through render-tag: under jsdom with the fonts node-canvas sees.store.toHTML()forwards the live editor flag ('resize'by default) instead.textSplitAllowed—boolean, defaultfalse; whether shrink-to-fit measurement may wrap a long word mid-word. By default a word wider than the box shrinks the font instead of splitting. Mirrors the editor'ssetTextSplitAllowedflag (forwarded automatically bystore.toHTML()).fetchGuard—(url) => boolean | Promise<boolean>; returnfalseto reject a download. See Untrusted designs on a server.
Node
The exporter is browser-first and needs a DOM. In Node, run it under
jsdom — the same setup this package's own
test suite uses. Per-line text backgrounds need real Range.getClientRects
measurement and fall back to a legacy overlay under jsdom; for full-fidelity
rendering in Node use
polotno-node.
Untrusted designs on a server
By default the export refuses only cloud-metadata endpoints (such as
169.254.169.254), named by literal IP or known hostname, including as a
redirect target. When it runs on a server on designs you do not trust, pass
fetchGuard; it replaces the default check. It gets every URL the export
downloads to inline (SVG sources and clip masks), including each redirect hop. Return false to reject the URL. The
export then makes no request to it. Image sizes are read through your DOM's own image
loader (under jsdom, node-canvas), which the guard does not cover. For example, use the guard that
polotno-node exports:
import { assertUrlAllowed } from 'polotno-node/ssrf-guard';
const fetchGuard = (url) =>
assertUrlAllowed(url, { blockPrivateNetwork: true }).then(
() => true,
() => false,
);
await jsonToHTML(json, { fetchGuard });In a browser the request runs as the user, so a guard is not necessary there. A browser hides each redirect target, so there the guard sees only the first URL and the final one.
