Vector graphics inside figure() produce empty structure element in tagged PDF
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 56.1k
- Forks
- 1.7k
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 22
Description
Description
When exporting a tagged PDF (--pdf-standard ua-1), a figure() with alt: that contains only vector graphics (paths, strokes, fills — no text) produces an empty Figure structure element: /K[] with no /Pg reference. Screen readers cannot associate the alt text with the drawing because there are no marked content sequences linking the rendered paths to the Figure tag.
Figures containing text (e.g., axis tick labels in a chart) tag correctly — the text creates marked content items that get linked to the Figure element.
Minimal reproduction
// Works — figure contains text (tick labels from axes)
#figure(
{
import "@preview/lilaq:0.6.0" as lq
import "@preview/tiptoe:0.4.0"
lq.diagram(
width: 200pt, height: 200pt,
xlim: (-5, 5), ylim: (-5, 5),
xaxis: (position: 0, tip: tiptoe.stealth, tick-distance: 1, subticks: none),
yaxis: (position: 0, tip: tiptoe.stealth, tick-distance: 1, subticks: none),
)
},
alt: "Empty coordinate plane with axes from -5 to 5",
)
// Broken — figure contains only vector paths (no text)
#figure(
{
import "@preview/lilaq:0.6.0" as lq
lq.diagram(
width: 200pt, height: 60pt,
xlim: (0, 20), ylim: (-2, 2),
xaxis: none, yaxis: none, grid: none,
lq.plot((0, 4), (0, 0)),
lq.plot((6, 10), (-1, 1)),
)
},
alt: "Two line segments with different slopes",
)
Compile with:
typst compile --pdf-standard ua-1 repro.typ
Observed
Inspecting the PDF structure tree:
Working figure (has text from tick labels):
/Type/StructElem /S/Figure /Alt(...) /K[8 9 10 11 ...] /Pg 3 0 R
Broken figure (only vector paths):
/Type/StructElem /S/Figure /Alt(...) /K[]
The Figure element is created with the correct Alt attribute, but /K is empty — no marked content IDs are linked, and no /Pg page reference exists. VoiceOver and other assistive technology cannot reliably encounter the alt text because the figure has no page location.
Expected
All rendered content inside a figure() — including vector paths, strokes, and fills — should be wrapped in marked content sequences (/BMC.../EMC) and linked to the Figure structure element via /K. This would give the figure a page association and let screen readers present the alt text at the correct reading position.
Environment
- Typst 0.15.1
- macOS, tested with VoiceOver and PDF tag tree inspection via pikepdf
Notes
This affects any drawing library that produces pure vector output (lilaq plots without axes, CeTZ canvas drawings, etc.) when wrapped in figure(alt: ...). The alt text is present in the structure tree but effectively orphaned.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by compiling the two minimal reproductions with typst compile --pdf-standard ua-1 repro.typ and compare their PDF structure trees using pikepdf. Trace how the tagged figure() is associated with rendered content when text is present versus vector-only content. Done means vector-only figures have marked content linked through /K and a page association so assistive technology can locate the alt text.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- accessibility
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100