fix: CSS vars perf, scrollbar styles, SVG image inline, nested line-clamp, iframe pseudos & isolation, Tailwind border (#334 #341 #348 #362 #371 #372 #386)#387
Conversation
…horthand for url() when background-image is empty. Closes #343
…lementation for consistent rendering and improved styling. Closes #290
…ylesheets correctly override inline styles in clones. Fixes #328.
…asuring scroll dimensions and using a temporary container for accurate height and width calculations
… avoid text wrapping issues
…memory usage and improve performance
…dress WebKit Bug #219770, enhancing capture reliability
…image decoding for improved capture performance
…t from cache module for improved code organization
…ent argument for cleaner code
…mo files from version control
… support margin collapsing and enhance layout stability
…uding exporters, utils, and modules to improve overall code reliability
…bleshooting, enhancing error visibility during capture processes
…oth English and Chinese versions
…functions into a loop for improved maintainability
…s in Safari to enhance style snapshot accuracy. Closes #340
…s function, verifying correct handling of custom CDN stylesheets. Closes #309
…pplying padding only when necessary based on bounding box transforms. Closes #333
…-elements in cloned styles to prevent double rendering. Closes #359
…d iframe support and consistency across style retrieval. Closes #371
…v does not inherit iframe styles. Closes #372
…ensuring fidelity with CSS variables. Closes #348
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| // Tags that size to text content; grid/flex blockify them but we should not constrain | ||
| // width (causes wrap when font-weight makes text wider than captured width, e.g. "Timestamp demo") | ||
| const INLINE_SIZED_TAGS = new Set(['span', 'small', 'p', 'em', 'strong', 'b', 'i', 'u', 's', 'code', 'cite', 'mark', 'sub', 'sup']) | ||
| const skipWidth = isInline || INLINE_SIZED_TAGS.has(tagName) |
There was a problem hiding this comment.
INLINE_SIZED_TAGS includes block-level p tag, skipping width
Medium Severity
The INLINE_SIZED_TAGS set includes 'p', which is a block-level element by default. The skipWidth condition is isInline || INLINE_SIZED_TAGS.has(tagName), meaning width, min-width, and max-width are unconditionally skipped for all <p> elements regardless of their actual display value. Block-level paragraphs normally fill their container width, and stripping width from their style key can cause layout differences in the captured output.
| ] | ||
| for (const p of BORDER_PROPS) delete out[p] | ||
| out['border'] = 'none' | ||
| } |
There was a problem hiding this comment.
Border normalization deletes border-radius styling unintentionally
Medium Severity
The border normalization for Tailwind's border: 0 solid sets out['border'] = 'none', which in CSS shorthand resets border-radius-related properties too when the browser expands it. More directly, the BORDER_PROPS list doesn't include border-radius, border-image, or border-collapse/border-spacing, so those remain in the snapshot — but the shorthand border: none can conflict with them during rendering. Also, elements using border-image with zero-width borders (valid CSS for decorative purposes) will lose their border-image since the shorthand override takes precedence.


Summary
This PR bundles several bugfixes and small improvements:
shouldIgnorePropahora ignora--*y se agrega la opciónexcludeStyleProps(regex o función) al snapshot de estilos para reducir el costo cuando hay miles de CSS variables en:root.lineClampTree(el)ycapturelo usa para aplicar el clamping también a elementos anidados con-webkit-line-clamp.border: 0 solid: normaliza casos donde todos losborder-*-widthson 0 aborder: noneen el snapshot, evitando bordes “fantasma” en el output.<image href="https://...">: las imágenes dentro de<image>en SVG se inlinéan como data URLs usandosnapFetch, igual que los<img>HTML.::-webkit-scrollbar(incluyendo@import/@media) y se inyectan en el<style>delforeignObjectpara preservar el estilo del scrollbar cuando el elemento no fue scrolleado.iframe) y se aísla el wrapper del iframe usandoall: initialpara que no herede CSS global.Testing
shouldIgnorePropyexcludeStyleProps(A large number of CSS variables will affect snapshot performance #348)border: 0 solidaborder: none(canvas abnormal border style #362)lineClampTree(Line-clamp ellipsis only renders for outermost element, fails for 1-level nested elements (v2.1.0) #386)<image href="https://...">(Unable to capture image inside svg image tag #341)collectScrollbarCSSy captura con estilos de scrollbar (The custom scrollbar style did not take effect, resulting in a native scrollbar style that looks ugly #334)Note
Medium Risk
Touches core DOM capture/clone/style inlining paths (including iframe, font embedding, and sizing heuristics), so regressions could affect output fidelity across browsers despite added test coverage.
Overview
Improves capture fidelity and performance by changing style snapshotting to ignore CSS custom properties by default, adding
excludeStyleProps, and normalizing inline styles to their computed (cascade-resolved) values so stylesheet!importantcan override authored inline styles.Fixes multiple rendering edge cases: inlines SVG
<image href>resources, preserves custom::-webkit-scrollbarstyling by collecting and injecting scrollbar rules, applies line-clamp to nested descendants vialineClampTree, and isolates the<foreignObject>wrapper withall:initialto prevent iframe CSS cascade bleed.Adds Safari/WebKit workarounds (configurable
safariWarmupAttempts, improved warmup + logging) and introduces bounded FIFO caches viaEvictingMapto avoid unbounded memory growth. Also includes targeted fixes for Tailwindborder: 0 solidnormalization, root/body sizing usingscrollHeight, relative background URL resolution, Firefox checkbox/radio replacements, and expanded unit test coverage plus minor docs/demo updates.Written by Cursor Bugbot for commit b49323d. This will update automatically on new commits. Configure here.