Skip to content

Inspector: clear the five ceilings #74 left in addSvg #75

Description

@Jing-yilin

#74 landed the inlining of a same-document <use> and stopped a sprite host from
becoming a blank asset. Five ceilings were accepted knowingly on the way, and two
of them are defects rather than tradeoffs. All of it is latent: no committed board
draws with <use> today (1512 root svgs, 33 with defs/symbol, 0 <use>), so
this is the list to clear before a board actually ships a sprite.

1. seen===1 counts nested resolutions, so a composite symbol loses viewBox adoption.
One top-level <use> into a <symbol> that itself holds a resolvable <use> runs
seen to 2, the root declines the symbol's viewBox, and the size falls back to the
root's width/height attributes. A root sized only by a class or an inline style
has neither — both are stripped from the copy — so the row reads 0x0 and the standalone
copy draws in the browser's default viewport instead of the symbol's coordinate system.
Fix: count top-level resolutions separately from the budget. (Codex P2 on 9beabad.)

2. A sprite-hosted icon never matches its assets/icons file signature, so it never
gets the file's name.
Not a regression — it was true before #74 too, for a different
reason. svgSignature scans every drawing element anywhere in the markup, <symbol>
contents included. Before: the symbol's geometry once, plus a use row the file has
not. After: the symbol's geometry twice, because the original <defs> stays in the copy
beside the inlined result. Either way the key differs from the file's and the inspector
falls back to an inferred label. Fix: after expansion, drop the <symbol>s that were
expanded away and a <defs> left empty — nothing references them once the geometry is
inlined, and the remaining signature is then exactly the icon file's. Gradients,
clipPaths and anything reached by url(#id) must stay. This also shrinks the data:
URI by the duplicated geometry. Keep a dangling <use>'s target if the budget ran out.

3. Wrappers are invisible to the signature, so a nested symbol collides with a flat one.
svgSignature does not sign the inner <svg> wrappers the expansion introduces, so one
glyph reached through two hops and the same glyph inlined flat produce the same key and
share one asset row. Harmless while the geometry really is identical; wrong the moment a
wrapper carries a transform or an offset that changes what is drawn.

4. The regression check is a string canary, not a behaviour test. inspectorAgent.test.ts
asserts substrings of AGENT (document.getElementById(h.slice(1)), :not(defs *,symbol *),
left=64) because the vitest env is node with no DOM. Every real verification for #73 and
its amendment ran out of band, through injectAgent into headless Chrome the way
tools/refkit.py shoots boards. A rename keeps the tests green while the behaviour breaks.
Fix: one headless-Chrome check in the toolkit's test path, driven by the same fixture, so it
runs in CI on a mac runner or is skipped explicitly on Linux.

5. The "defines only" guard names defs and symbol only. Geometry that exists purely
inside a <mask>, <clipPath>, <pattern> or <marker> also draws nothing by itself, so a
root holding only those still becomes an asset row. Nit: extend the :not() list.

Fix order that matches the payoff: 1 and 2 together (both live in addSvg, both decide what
the copy's size and name are), then 4, then 3 and 5 when a board makes them observable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions