The render layer had no CSS Grid support, so Vector 2022's page layout
(three nested grids) collapsed to a vertical stack with the article
landing tens of thousands of pixels down the page. Wikipedia rendered
as a near-blank page and Hacker News only worked through per-site
hardcoded CSS overrides.
Removed the HN-specific hardcoding and fixed the general engine instead:
- CSS Grid layout (grid-template-areas/columns/rows via taffy's grid mode)
- Indexed, specificity-correct cascade in a new css.rs, replacing the
old test-every-selector-against-every-node scan. Cascade time on
Wikipedia went from 9.5s to under 200ms.
- Ancestor bloom-filter fast-rejection for selector matching in
obscura-dom, needed to make the indexed cascade actually fast on
descendant combinators.
- :link/:visited pseudo-classes were previously unparseable, so any
rule using them (a:link{color:...}, extremely common) silently
dropped the whole rule from the cascade.
- overflow:hidden clipping, fixing the pervasive visually-hidden-but-
accessible pattern used for skip links and screen-reader-only labels.
- @media parser robustness: it did a literal substring search for
max-width: and silently dropped the constraint on max-width : 750px
(space before colon) or max-width:calc(750px - 1px), treating
mobile-only or narrow-viewport rules as always active. The calc()
case was hiding Wikipedia's TOC sidebar via a rule meant only for
narrow screens.
- Table auto-layout approximation: the trailing auto-width td in a row
absorbs leftover space, so a width:100% table's unsized last column
reaches the right edge instead of shrinking to content.
- Inline formatting context approximation: a block holding inline-level
children (a paragraph or list item with links) is promoted to a
wrapping flex row so text and links read as continuous prose instead
of one fragment per line.
- Whitespace-only text nodes no longer get a full line-height box. They
used to stack up as blank rows, turning Wikipedia's collapsed TOC
subsections and the page header into hundreds of pixels of dead space.
- SVG rendering via resvg/usvg, plus resolving relative image URLs
against the page's base URL.
- background-image support including background-size/background-position
for correctly sized and positioned icons.
- Per-screenshot image fetch cache.
- Fixed the layout-only (no paint feature) build, which didn't compile
due to an unconditional call into paint-gated code.
37 lines
1.6 KiB
TOML
37 lines
1.6 KiB
TOML
[package]
|
|
name = "obscura-render"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
repository.workspace = true
|
|
description = "Optional scoped render layer for Obscura: layout (taffy) and, with the paint feature, text and raster output for screenshots."
|
|
|
|
[features]
|
|
default = []
|
|
# Rasterize the laid-out tree to a pixmap (tiny-skia) with text (ab_glyph) and images.
|
|
# Off by default; the layout core (getBoundingClientRect etc.) works without it.
|
|
paint = ["dep:tiny-skia", "dep:ab_glyph", "dep:image", "dep:ureq", "dep:base64", "dep:resvg", "dep:usvg", "dep:url"]
|
|
|
|
[dependencies]
|
|
taffy = { workspace = true }
|
|
obscura-dom = { workspace = true }
|
|
tiny-skia = { workspace = true, optional = true }
|
|
ab_glyph = { workspace = true, optional = true }
|
|
image = { version = "0.24", default-features = false, features = ["jpeg", "png", "webp"], optional = true }
|
|
ureq = { version = "2.9", default-features = false, features = ["tls"], optional = true }
|
|
base64 = { workspace = true, optional = true }
|
|
# SVG rasterization for <img src="*.svg">, inline <svg>, and background-image
|
|
# SVGs, all extremely common for logos/icons. Pure Rust, CPU, no system deps,
|
|
# same deterministic-rendering guarantee as the rest of this crate.
|
|
resvg = { version = "0.47", default-features = false, features = ["text", "raster-images"], optional = true }
|
|
usvg = { version = "0.47", default-features = false, optional = true }
|
|
url = { workspace = true, optional = true }
|
|
cssparser = "0.34"
|
|
[lib]
|
|
path = "src/lib.rs"
|
|
|
|
[[bin]]
|
|
name = "paint_file"
|
|
path = "src/bin/paint_file.rs"
|
|
required-features = ["paint"]
|