Skip to content

Commit c804ffd

Browse files
Add Typst image alt text for PDF/UA accessibility
Workaround for Pandoc not passing alt text to Typst image() calls. When an image has alt text (from caption or fig-alt), emits raw Typst with image(..., alt: "...") for accessibility compliance. Temporary fix until pandoc#11394 is merged upstream. Closes #13868 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent a5ed053 commit c804ffd

File tree

16 files changed

+261
-3
lines changed

16 files changed

+261
-3
lines changed

news/changelog-1.9.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ All changes included in 1.9:
4242
- ([#13589](https://github.com/quarto-dev/quarto-cli/issues/13589)): Fix callouts with invalid ID prefixes crashing with "attempt to index a nil value". Callouts with unknown reference types now render as non-crossreferenceable callouts with a warning, ignoring the invalid ID.
4343
- ([#13602](https://github.com/quarto-dev/quarto-cli/issues/13602)): Fix support for multiple files set in `bibliography` field in `biblio.typ` template partial.
4444
- ([#13775](https://github.com/quarto-dev/quarto-cli/issues/13775)): Fix brand fonts not being applied when using `citeproc: true` with Typst format. Format detection now properly handles Pandoc format variants like `typst-citations`.
45+
- ([#13868](https://github.com/quarto-dev/quarto-cli/issues/13868)): Add image alt text support for PDF/UA accessibility. Alt text from markdown captions and explicit `alt` attributes is now passed to Typst's `image()` function. (Temporary workaround until [jgm/pandoc#11394](https://github.com/jgm/pandoc/pull/11394) is merged.)
4546
- ([#13249](https://github.com/quarto-dev/quarto-cli/pull/13249)): Update to Pandoc's Typst template following Pandoc 3.8.3 and Typst 0.14.2 support:
4647
- Code syntax highlighting now uses Skylighting by default.
4748
- New template variables `mathfont`, `codefont`, and `linestretch` for font and line spacing customization.

src/resources/filters/quarto-post/typst.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,48 @@ function render_typst_fixups()
232232
if image.attributes["width"] ~= nil and type(width_as_number) == "number" then
233233
image.attributes["width"] = tostring(image.attributes["width"] / PANDOC_WRITER_OPTIONS.dpi) .. "in"
234234
end
235+
236+
-- Workaround for Pandoc not passing alt text to Typst image() calls
237+
-- See: https://github.com/jgm/pandoc/pull/11394
238+
local alt_text = image.attributes["alt"]
239+
if (alt_text == nil or alt_text == "") and #image.caption > 0 then
240+
alt_text = pandoc.utils.stringify(image.caption)
241+
end
242+
243+
if alt_text and #alt_text > 0 then
244+
-- When returning RawInline instead of Image, Pandoc won't write mediabag
245+
-- entries to disk, so we must do it explicitly
246+
local src = image.src
247+
local mediabagPath = _quarto.modules.mediabag.write_mediabag_entry(src)
248+
if mediabagPath then
249+
src = mediabagPath
250+
end
251+
252+
-- Build image() parameters
253+
local params = {}
254+
255+
-- Source path (escape backslashes for Windows paths)
256+
src = src:gsub('\\', '\\\\')
257+
table.insert(params, '"' .. src .. '"')
258+
259+
-- Alt text second (escape backslashes and quotes)
260+
local escaped_alt = alt_text:gsub('\\', '\\\\'):gsub('"', '\\"')
261+
table.insert(params, 'alt: "' .. escaped_alt .. '"')
262+
263+
-- Height if present
264+
if image.attributes["height"] then
265+
table.insert(params, 'height: ' .. image.attributes["height"])
266+
end
267+
268+
-- Width if present
269+
if image.attributes["width"] then
270+
table.insert(params, 'width: ' .. image.attributes["width"])
271+
end
272+
273+
-- Use #box() wrapper for inline compatibility
274+
return pandoc.RawInline("typst", "#box(image(" .. table.concat(params, ", ") .. "))")
275+
end
276+
235277
return image
236278
end,
237279
Div = function(div)

tests/docs/smoke-all/crossrefs/float/typst/typst-float-4.qmd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ _quarto:
66
tests:
77
typst:
88
ensureTypstFileRegexMatches:
9-
-
9+
-
1010
- "#ref\\(<tbl-foo>, supplement: \\[Table\\]\\)"
1111
- "#ref\\(<fig-foo>, supplement: \\[Figure\\]\\)"
12-
- "#link\\(\"https://www.example.com/\"\\)\\[#.*image\\(\"img/surus.jpg\"\\)\\)"
12+
# Images with captions now include alt text for accessibility
13+
- '#link\("https://www\.example\.com/"\)\[#box\(image\("img/surus\.jpg", alt:'
1314
---
1415

1516
This tests:
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: "Alt text test"
3+
pdf-standard: ua-1
4+
keep-tex: true
5+
---
6+
7+
![This is the alt text](penrose.svg)
8+
Lines changed: 16 additions & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Loading
Lines changed: 16 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)