render-tag 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Render HTML rich text onto canvas with the 2D API. No SVG, no `foreignObject`
6
6
 
7
7
  ## Why
8
8
 
9
- Browsers can render HTML into canvas via SVG `foreignObject`, but it's slow (~100ms) and inconsistent across browsers. `render-tag` parses your HTML, resolves styles via `getComputedStyle`, then lays out and draws everything with canvas 2D calls. It's **10-60x faster** than SVG-based approaches.
9
+ When you need rich text as part of a canvas design editors, image export, canvas-based apps — the standard SVG `foreignObject` approach is slow (~100ms per render). `render-tag` parses your HTML, resolves styles via `getComputedStyle`, then lays out and draws everything with pure canvas 2D calls. It's **10-60x faster** than SVG-based approaches.
10
10
 
11
11
  By design, render-tag focuses on **rich text only** — paragraphs, headings, lists, tables, inline formatting. It is not designed for interactive elements (buttons, inputs, iframes) or complex HTML layouts. This focus is what makes it fast.
12
12
 
@@ -176,11 +176,16 @@ drawLayout({ layout: result, width: 400, ctx: offscreenCtx });
176
176
  - `overflow-wrap: break-word`
177
177
  - Soft hyphens (`­`)
178
178
 
179
- ## Cross-browser consistency
179
+ ## Recommended CSS reset
180
180
 
181
- The library targets Chrome as the primary browser. For consistent rendering across Chrome and Firefox, add these CSS rules to your input:
181
+ For best consistency between DOM and canvas rendering, add these CSS rules to your input HTML:
182
182
 
183
183
  ```css
184
+ /* Normalize monospace font size.
185
+ Chrome reduces <code>/<pre> font-size via a UA quirk that canvas can't replicate.
186
+ This makes DOM and canvas render code at the same size. */
187
+ code, pre, kbd, samp { font-size: inherit; }
188
+
184
189
  /* Suppress Firefox's ::marker extra line height (~1.5px per list item).
185
190
  render-tag draws list markers itself, so this loses nothing visually. */
186
191
  li::marker { content: none; font-size: 0; line-height: 0; }
@@ -192,16 +197,28 @@ li::marker { content: none; font-size: 0; line-height: 0; }
192
197
  .has-emoji { font-kerning: none; }
193
198
  ```
194
199
 
195
- With `accuracy: 'balanced'` (the default), the library uses hidden DOM probes to match Firefox's actual line box heights. With `accuracy: 'performance'`, the CSS above becomes especially important for Firefox consistency.
200
+ The default `accuracy: 'performance'` uses pure canvas API measurements with no DOM touches, producing consistent canvas output across browsers. Use `accuracy: 'balanced'` if you need each browser's canvas output to match its own native DOM rendering more closely (at the cost of cross-browser canvas consistency).
201
+
202
+ ## Design decisions
203
+
204
+ ### Chrome-first rendering
205
+
206
+ Chrome is the primary target browser. When a rendering choice must favor one browser over another, Chrome wins. All development and CI testing defaults to Chromium.
207
+
208
+ ### Cross-browser consistency over per-browser accuracy
209
+
210
+ The library prioritizes producing **the same canvas output in every browser** over matching each browser's native DOM rendering pixel-for-pixel. If Chrome and Firefox render a `<p>` slightly differently in DOM, our canvas output should match Chrome's version in both browsers — not adapt to each browser's quirks.
211
+
212
+ In other words: identical canvas output everywhere > perfect DOM fidelity per browser. Users expect the same visual result regardless of which browser their audience uses.
196
213
 
197
214
  ## How it works
198
215
 
199
216
  1. **Parse** HTML with `DOMParser`
200
- 2. **Resolve styles** via hidden DOM + `getComputedStyle` (CSS cascade for free)
217
+ 2. **Resolve styles** via built-in CSS resolver (selector matching, cascade, inheritance — no DOM insertion)
201
218
  3. **Layout** with canvas `measureText` (block flow, inline wrapping, margin collapsing)
202
219
  4. **Render** with canvas 2D API (`fillText`, `fillRect`, `strokeText`, etc.)
203
220
 
204
- Style resolution uses a hidden DOM element with `getComputedStyle` to get the full CSS cascade. Layout and rendering are done entirely with the canvas 2D API. Optional DOM probes (`accuracy: 'balanced'`) improve cross-browser accuracy for line heights and mixed-font wrapping.
221
+ Style resolution uses a built-in CSS parser and resolver that handles selectors, specificity, cascade, and inheritance without inserting HTML into the document. Layout and rendering are done entirely with the canvas 2D API.
205
222
 
206
223
  ## Development
207
224
 
@@ -0,0 +1,10 @@
1
+ import type { StyledNode } from './types.js';
2
+ /**
3
+ * Resolve styles for a DOM tree without inserting into the document.
4
+ * Parses CSS rules, matches selectors, resolves cascade + inheritance.
5
+ */
6
+ export declare function resolveStylesFromCSS(fragment: DocumentFragment, css: string, containerWidth: number): {
7
+ tree: StyledNode;
8
+ cleanup: () => void;
9
+ };
10
+ //# sourceMappingURL=css-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css-resolver.d.ts","sourceRoot":"","sources":["../src/css-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,UAAU,EAAE,MAAM,YAAY,CAAC;AAy2B5D;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,MAAM,GACrB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAmV3C"}