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 +23 -6
- package/lib/css-resolver.d.ts +10 -0
- package/lib/css-resolver.d.ts.map +1 -0
- package/lib/css-resolver.js +1231 -0
- package/lib/css-resolver.js.map +1 -0
- package/lib/index.d.ts +2 -6
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -29
- package/lib/index.js.map +1 -1
- package/lib/layout.d.ts +5 -5
- package/lib/layout.d.ts.map +1 -1
- package/lib/layout.js +364 -292
- package/lib/layout.js.map +1 -1
- package/lib/render-tag.umd.js +10 -0
- package/lib/render-tag.umd.js.map +1 -0
- package/lib/render.d.ts.map +1 -1
- package/lib/render.js +32 -67
- package/lib/render.js.map +1 -1
- package/lib/style-resolver.d.ts.map +1 -1
- package/lib/style-resolver.js +22 -3
- package/lib/style-resolver.js.map +1 -1
- package/lib/types.d.ts +9 -19
- package/lib/types.d.ts.map +1 -1
- package/package.json +10 -3
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
|
-
|
|
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
|
-
##
|
|
179
|
+
## Recommended CSS reset
|
|
180
180
|
|
|
181
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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"}
|