Search: compactness in metric spaces
Heine-Borel Theorem
A theorem page links definitions, prerequisites, proofs, and nearby ideas into one navigable object.
1Find a page or theorem
2Follow the prerequisite trail
3Save it to study
4Discuss or contribute
Symptom
On pages with multiple illustrations (e.g. page 1274, "The Rose with Two Petals"), point labels and other text glyphs rendered incorrectly in the browser — letters from one illustration appeared inside a different illustration, or labels went missing entirely.
Root cause
TikZ/dvisvgm emits glyph path definitions with IDs like
glyph-0-0,glyph-1-0,clip-0. These IDs are only unique within a single SVG document. When two illustrations are inlined into the same HTML page, both declareid="glyph-0-0"in their defs, and everyxlink:href="#glyph-0-0"resolves to whichever definition the browser found first. Result: one illustration's letters are drawn from another's font table, and references to IDs that do not exist in the winning defs render as blank.The pipeline fix was to namespace every emitted ID with the illustration's slug —
glyph-0-0becomesglyph-rose-two-petals-0-0,clip-0becomesclip-rose-two-petals-0, and everyxlink:hrefrewritten to match. This was applied in the TikZ compile step and the DB content was updated.Investigation (and the MCP detour)
I confirmed the server is serving the correct, namespaced SVG:
/api/illustrations/rose-two-petalsreturns IDsglyph-rose-two-petals-0-0throughglyph-rose-two-petals-2-1and matching use refs./api/illustrations/batch?slugs=rose-two-petalsreturns the same namespaced content.I then wanted to verify what the browser actually renders on the authenticated wiki page, since the user was still seeing broken labels. I ran into:
/pages/1274returns the Demo Mode landing page to anonymous visitors, so a plain Playwright run (via the repo's node_modules) could not reach the rendered illustration./chromecommand,/reload-plugins, and asking for a session cookie — believing a dedicated browser MCP was necessary to inspect the rendered DOM./api/illustrations/*endpoints are public (per the demo-mode middleware), so I could fetch the SVG anonymously and render it into a DOM directly.Verification
With the browser MCP connected (but unauthenticated), I fetched the SVG from the public API and injected it into
document.bodyon a demo-mode page, then queried the rendered DOM:glyph-rose-two-petals-{0-0, 1-0, 2-0, 2-1},clip-rose-two-petals-{0, 1}.useelements withxlink:href="#glyph-rose-two-petals-..."— every one resolves to a real definition.use.getBBox()returns non-zero width/height for every label (e.g.{x: 62.27, y: 63.12, w: 4.95, h: 4.52}), confirming the browser is actually rasterising each glyph.So end-to-end: pipeline, DB, HTTP response, SVG DOM, and rasterised glyphs all check out.
Why the user was still seeing breakage
Since the freshly-fetched SVG renders correctly, the broken labels the user was seeing in their own browser are almost certainly served from a stale cache — either:
Suggested follow-ups
?v=<content_hash>) or ETag / Last-Modified based on the SVG content when the inline image / fetch path is rendered, so republishing an illustration invalidates stale client caches automatically.id="glyph-<digits>-<digits>"remains in any stored SVG — catches regressions of this class cheaply.Cache-Control: no-storefor debugging.