Overview
dsh-web-icon-indicator
README / EN
Package documentation
Registry summary
dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
The favicon is a plain image, so browsers never run the SVG's own CSS/JS animation inside the tab UI — every frame is rendered here in JavaScript. How well a *changing* favicon is displayed differs by browser: | Browser | SVG favicon | Live per-state color/effect | Why | | --- | --- | --- | --- | | Chrome / Edge | ✅ | ✅ smooth | Re-reads `<link rel=icon>` live; `data:`-URI SVGs are fine. | | Firefox | ✅ | ✅ smooth | Renders SVG favicons well (and honors their `prefers-color-scheme`, unused here). | | Safari (macOS) | ✅ rendered static | ⚠️ best-effort | Ignores in-SVG CSS; aggressive icon caching. | | Safari (iOS) | ✅ rendered static | ⚠️ rarely | Unlikely to refresh without revisiting the tab. | Known limitations (current as of Safari 26.3): - **Favicons have their own cache.** Chrome keeps a favicon database, Firefox a `favicons.sqlite`, and **Safari a system-level icon cache** — none of which a normal *clear cache* touches, and WebKit even caches the "no icon" case. That is why a changed icon can linger for an existing tab. The plugin already mitigates this: it serves `base.svg` and the status endpoint with `Cache-Control: no-store`, bundles a freshness query (`?t=Date.now()`) on its fetches, and replaces the `<link rel=icon>` node on each state change. - **A theme-scoped favicon pair must be collapsed first (DSH ≥ 0.1.7).** The shell's `index.html` ships *two* `rel=icon` links — `favicon-dark.svg` for `prefers-color-scheme: dark` and `favicon.svg` for light — because up to `0.1.6-alpha.2` there was exactly one. A browser resolves the favicon to the **last connected link whose `media` matches**, so repainting only the first one left the tab showing the shell's icon no matter what the session did. The plugin now normalizes the set to a single always-matching link at startup (keeping the variant your scheme selects) before painting. If you are on a version before 0.5.2 and the tab icon simply never changes, this is why. - **Safari renders SVG favicons but ignores their internal CSS** — no `@media`, no `prefers-color-scheme`, no CSS animation. So all recoloring must be baked into each frame's markup (which the plugin does) rather than driven by CSS variables. - **`data:`-URI SVG favicons are unreliable in Safari** (WebKit bug 236616, still open; reproduced on Safari 17.6). The plugin currently builds each frame as a `data:image/svg+xml` URI, so on Safari the tab icon may not render at all — the biggest known gap. - **Dynamic JS updates in Safari are hit-or-miss;** they may require a reload, and Safari "locks onto" the first icon it sees. There is no guaranteed, spec-supported way to swap a favicon live in Safari today. - **Pinned-tab icon (`<link rel="mask-icon">`) uses its own cache**, separate from the regular favicon, and is a single-colour silhouette tinted by the `color` attribute — macOS + pinned-tab only, read at page load, not live. Full mechanics with sources (WebKit bugs, Stack Overflow, browser-engineering blogs) and a recommended path toward smoother Safari colour changes live in [`docs/safari-favicon-research.md`](./docs/safari-favicon-research.md).
