UNPKG

dom-to-image-more

Version:

Generates an image from a DOM node using HTML5 canvas and SVG

93 lines (75 loc) 7 kB
# Fork Analysis — what forks are "ahead" of `main` Generated 2026-06-11. Compared all **124** forks' default branches against `1904labs/dom-to-image-more:main` via the GitHub compare API. **33** were ahead by ≥1 commit; the rest are behind/even (mostly forks created only to file PRs we've already merged). Each ahead-fork's source patch was diffed against the current `src/dom-to-image-more.js`. No rewrites are adopted (per request). The lists below separate **genuinely novel** work from work that is **already superseded** in our current source. --- ## A. Genuine candidates (not in current `main`) ### 1. `ignoreCSSRuleErrors` — suppress the cross-origin cssRules `console.error` ⭐ strongest - **Forks:** daveytran, mgenware (`dom-to-image-more-wc`), nathanfiscus — **three independent forks** hit this. - **Where:** `getCssRules()` (current `src/dom-to-image-more.js:1785-1804`). When a cross-origin stylesheet's `cssRules` throws on access, we unconditionally `console.error(...)`. On font-heavy pages with CDN stylesheets this spams the console on every capture. - **Proposal:** add a boolean option (`ignoreCSSRuleErrors`, default `false`) that gates the `console.error`. Trivial, backwards-compatible. daveytran's exact patch already does this. - **Note:** nathanfiscus instead tries to *pre-filter* sheets by origin (`ownerNode.href.indexOf(hostname)...`) — buggy (throws on `<style>` with null `ownerNode`/`href`); use the option-gated approach, not theirs. ### 2. `requestInterceptor` — intercept any resource fetch (medium) - **Fork:** mgenware (`dom-to-image-more-wc`). - **What:** before the XHR in `getAndEncode`, call `options.requestInterceptor(url)`; if it returns a defined value, resolve with it and skip the network. More general than `corsImg`/`imagePlaceholder` — lets callers supply data from a cache/test harness/custom resolver for *any* URL (fonts + images). - **Trade-off:** overlaps partially with existing `corsImg` + `imagePlaceholder`. Worth it if we want a single general hook; otherwise low priority. ### 3. External stylesheet loading (`skipExternalFileMatch` + fetch fallback) (medium value / medium complexity) - **Forks:** SizlePtyLtd, kbasten (subset) — origin: MichalBryxi/dom-to-image. - **What:** `loadExternalStyleSheets()` `fetch()`es cross-origin stylesheets and re-parses them into a local `<style>` so their `@font-face` rules become readable (working around the same cssRules CORS block as #1, but recovering the fonts instead of just silencing the error). `skipExternalFileMatch` regex skips font files. - **Caveats:** ships company-specific cruft (`eztees-fonts`, `fontStretch='normal'`, `offsetWidth` vs `scrollWidth`) that must NOT be carried over. The stylesheet-fetch core is the valuable part. This is the most substantial real feature found, but also the riskiest to integrate cleanly. Directly addresses our documented "cannot wait for / read a cross-origin stylesheet" limitation. ### 4. `pseudoElementFilter` — choose which `::before`/`::after` get recreated (low–medium) - **Fork:** techvalidate (2019). - **What:** `if (pseudoElementFilter && !pseudoElementFilter(style)) return;` in pseudo-element cloning. We have `filterStyles(node, prop)` but no pseudo-element-level skip. Niche; include only if someone asks. ### 5. `onMakeNodeCopy` / `afterClone` — extra clone hooks (low — overlaps existing) - **Forks:** Heyana (`onMakeNodeCopy`, per-node clone *factory* run before default clone), mgenware (`afterClone`, whole-tree hook between clone and font-embed). - **Assessment:** both overlap our existing `adjustClonedNode(node, clone, after)` and `onclone`. The only gap is a true *factory* (return a replacement element, e.g. hand-rasterize a canvas yourself). Low demand; skip unless requested. --- ## B. Already superseded in current `main` (no action) | Fork(s) | Their change | Why it's already covered | |---|---|---| | daveytran, ITfanheng, lukebrody | guard `readAsDataURL(response)` when response is null/non-Blob | `src:1455-1483` already checks `xhr.response !== null`, `response instanceof Blob`, wraps `readAsDataURL` in try/catch, and routes to `imagePlaceholder` + `onImageError`. lukebrody's baked-in "CORS Error" SVG = our generic `imagePlaceholder`. | | ITfanheng | `url()` regex with matched-quote backreference | Our `URL_REGEX` (`src:1673`) already uses `\1` backreference and is more robust (handles escapes). | | joswhite | sandbox default-style perf optimization (`copyUserComputedStyleFast`, `getDefaultStyle`, 20s sandbox teardown) | This is exactly our `styleCaching` feature (Joseph White already credited). Ours adds strict/relaxed tuning. | | orangeswim | background inlining passed value as priority (bug) | `src:1925-1927` already reads `getPropertyPriority` correctly. | | Printfly | inline SVG `<image>` xlink:href | Done in commit `319d036` "Inline nested SVG `<image>` href". (mask-attr reflection is the only leftover — niche.) | | techvalidate, Hammster | shadowRoot children flattened into clone | Full open-shadow-DOM + slot support already present. | | mfyuce | iframe support via `html2canvas` | We have native same-origin/blob iframe support; pulls an external dep. | | borkdude | force-read `cssRules` (issue #21) | Our `getCssRules` checks the prototype `hasOwnProperty`, which fixes the same case. | | npvn, dmytropidhaiko | `%`/`#`/newline encoding in the SVG data URI | Our `escapeXhtml` already does `%25`/`%23`/`%0A` (dmytropidhaiko's is byte-identical). | | davidburns573 | `disableEmbedFonts` option | Already shipped (he's credited). | | nathanfiscus | origin-check before reading cssRules | Buggy; intent folded into candidate #1. | ## C. Not viable / out of scope (no action) - **Rewrites (explicitly excluded):** Dynaruid (`dom-to-canvas`, Bun/TS monorepo), kufii (`dom-to-image-even-more`, webpack/babel), dmytropidhaiko (`dom-to-image-improved`, Safari-focused rename). - **Rename/CI/publish only:** hriks (`dom-to-image-thor`), Bojagi, wrick17, ecancil ("testing"), Freepik-Labs ("wip"), phanirithvij (test infra), Facil-Espaider (eslint indent), scrpgil (Angular AOT no-op var decls). - **Company-specific hacks:** PlaypowerLabs (`window[url]` global cache, `mathComponentFonts`), scrive (`fontStretch` toggle), Printfly (`eztees-fonts` filter), SizlePtyLtd's non-core bits. - **thinkanymore:** `cloneSvgImgToPngImg` rasterizes an SVG-sourced `<img>` to PNG via canvas — niche and loses vector scalability; Chrome renders SVG `<img>` in foreignObject fine. Skip. --- ## Recommended order 1. **`ignoreCSSRuleErrors`** — ship it; tiny, multi-fork demand, fixes real console spam. 2. **`requestInterceptor`** — consider as a general resource hook if we want one. 3. **External stylesheet fetch** — evaluate seriously (addresses a documented limitation) but integrate only the clean core, drop the company cruft. 4. `pseudoElementFilter`, clone-factory hooks — only on request.