# D33. A figure's SVG in the page, rebuilt from an allowlist (13 Oct 2026)

The « Nietzsche » session generated engraved plates as SVG (`generators/`) and wanted them to draw themselves as the voice spoke; the `draw` effect (D28) traces the strokes of a block's inline drawing, but an image block renders an `<img>`, so it wiped them instead, and the session animated the plates in the files themselves, which captures and reduced motion cannot reach.
- **`inline: true` on an image block** (and its forks) whose asset is an SVG: the build reads the file and writes it in place of the `<img>` (`@elabora/core` `render/svg-inline.ts`, called by the compiler, so packages, the canvas and captures agree). Opt-in: an inline drawing is part of the course data and of every page that shows it, and a theme's rules on `.t-figure img` do not reach it.
- **Sanitized by rewriting, not by filtering.** The file is the course's own, but it lands in a learner's LMS page: it is read as XML and written again from an allowlist of SVG elements that draw (shapes, text, gradients, patterns, clips, masks, markers, filters, SMIL animations other than of links), without event handlers, links (kept as their content), scripts, foreignObject, DOCTYPE and entities, comments, references out of the drawing (`#fragments` and `data:` images only, in attributes, styles and `<style>`); a root that is not `<svg>` keeps the `<img>`. Its ids are prefixed with the block's (`t-svg-<block>-<id>`) with every reference to them (`href`, `url(#…)`, ARIA lists, SMIL timing), so two drawings never share an id; its `<style>` is scoped to it (`svg[data-t-svg="t-svg-<block>"]`), its `@keyframes` renamed, `@import` and `@font-face` dropped. The validator says what was removed (`W_SVG_INLINE_SANITIZED`). Rejected: DOMPurify-like sanitizing in the player (a dependency, and the page would hold the raw file), an `<object>` or `<use href="file.svg#…">` (the page's CSS and the timeline still cannot reach inside a separate document).
- **Accessible as the `<img>` was**: `role="img"` and `aria-label` from the block's `alt`, the file's own root `<title>` dropped (the alt is its name); `aria-hidden` when decorative; `focusable="false"`.
- **`draw` draws each subpath.** A dash pattern starts again at every subpath of a path, so an engraving's hatching (one path, hundreds of short lines) drawn with its total length showed every line at once; each shape is now drawn with the length of its longest subpath (`subpaths` in `@elabora/player` `timed-blocks.ts` splits path data, each subpath from an absolute point), so every line grows from its start at the same pace. Captures without a moment show the drawing whole (an effect that ended leaves no animation).
*Revisit if:* authors need inline drawings in component props of kind asset (a component's template binds an `<img>` today), or heavy drawings make course data too large (lazy inlining per screen).
