summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Schmitz <tobiasschmitz2001@gmail.com>2025-07-03 18:38:54 +0200
committerTobias Schmitz <tobiasschmitz2001@gmail.com>2025-07-03 18:43:30 +0200
commit3d4d5489349f0d13707903462d0f245e19b54298 (patch)
treef953e3cbedb47ea9b07768eae750fe570cfd340c
parent254aadccfc67f207b46d3865bd9805fc9924b1c0 (diff)
feat: [WIP] generate alt text for ref elements
-rw-r--r--crates/typst-library/src/model/bibliography.rs4
-rw-r--r--crates/typst-library/src/model/footnote.rs4
-rw-r--r--crates/typst-library/src/model/outline.rs36
-rw-r--r--crates/typst-library/src/model/reference.rs9
4 files changed, 36 insertions, 17 deletions
diff --git a/crates/typst-library/src/model/bibliography.rs b/crates/typst-library/src/model/bibliography.rs
index 3b14c8cb..ec9d6677 100644
--- a/crates/typst-library/src/model/bibliography.rs
+++ b/crates/typst-library/src/model/bibliography.rs
@@ -877,7 +877,7 @@ impl<'a> Generator<'a> {
renderer.display_elem_child(elem, &mut None, false)?;
if let Some(location) = first_occurrences.get(item.key.as_str()) {
let dest = Destination::Location(*location);
- // TODO: accept user supplied alt text
+ // TODO(accessibility): generate alt text
content = content.linked(dest, None);
}
StrResult::Ok(content)
@@ -1013,7 +1013,7 @@ impl ElemRenderer<'_> {
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta {
if let Some(location) = (self.link)(i) {
let dest = Destination::Location(location);
- // TODO: accept user supplied alt text
+ // TODO(accessibility): generate alt text
content = content.linked(dest, None);
}
}
diff --git a/crates/typst-library/src/model/footnote.rs b/crates/typst-library/src/model/footnote.rs
index 872827d9..f1eeb0c3 100644
--- a/crates/typst-library/src/model/footnote.rs
+++ b/crates/typst-library/src/model/footnote.rs
@@ -147,7 +147,7 @@ impl Show for Packed<FootnoteElem> {
let sup = SuperElem::new(num).pack().spanned(span);
let loc = loc.variant(1);
// Add zero-width weak spacing to make the footnote "sticky".
- // TODO: accept user supplied alt text
+ // TODO(accessibility): generate alt text
Ok(HElem::hole().pack() + sup.linked(Destination::Location(loc), None))
}
}
@@ -297,7 +297,7 @@ impl Show for Packed<FootnoteEntry> {
let sup = SuperElem::new(num)
.pack()
.spanned(span)
- // TODO: accept user supplied alt text
+ // TODO(accessibility): generate alt text
.linked(Destination::Location(loc), None)
.located(loc.variant(1));
diff --git a/crates/typst-library/src/model/outline.rs b/crates/typst-library/src/model/outline.rs
index adca5783..8e2f18da 100644
--- a/crates/typst-library/src/model/outline.rs
+++ b/crates/typst-library/src/model/outline.rs
@@ -2,7 +2,7 @@ use std::num::NonZeroUsize;
use std::str::FromStr;
use comemo::{Track, Tracked};
-use ecow::eco_format;
+use ecow::{eco_format, EcoString};
use smallvec::SmallVec;
use typst_syntax::Span;
use typst_utils::{Get, NonZeroExt};
@@ -23,7 +23,7 @@ use crate::layout::{
};
use crate::math::EquationElem;
use crate::model::{Destination, HeadingElem, NumberingPattern, ParElem, Refable};
-use crate::text::{LocalName, SpaceElem, TextElem};
+use crate::text::{LocalName, SmartQuoteElem, SmartQuotes, SpaceElem, TextElem};
/// A table of contents, figures, or other elements.
///
@@ -435,18 +435,11 @@ impl Show for Packed<OutlineEntry> {
let context = Context::new(None, Some(styles));
let context = context.track();
- // TODO: prefix should be wrapped in a `Lbl` structure element
+ // TODO(accessibility): prefix should be wrapped in a `Lbl` structure element
let prefix = self.prefix(engine, context, span)?;
let body = self.body().at(span)?;
let page = self.page(engine, context, span)?;
- let alt = {
- // TODO: accept user supplied alt text
- let prefix = prefix.as_ref().map(|p| p.plain_text()).unwrap_or_default();
- let body = body.plain_text();
- let page_str = PageElem::local_name_in(styles);
- let page_nr = page.plain_text();
- eco_format!("{prefix} \"{body}\", {page_str} {page_nr}")
- };
+ let alt = alt_text(styles, &prefix, &body, &page);
let inner = self.inner(context, span, body, page)?;
let block = if self.element.is::<EquationElem>() {
let body = prefix.unwrap_or_default() + inner;
@@ -704,6 +697,27 @@ cast! {
v: Content => v.unpack::<Self>().map_err(|_| "expected outline entry")?
}
+fn alt_text(
+ styles: StyleChain,
+ prefix: &Option<Content>,
+ body: &Content,
+ page: &Content,
+) -> EcoString {
+ let prefix = prefix.as_ref().map(|p| p.plain_text()).unwrap_or_default();
+ let body = body.plain_text();
+ let page_str = PageElem::local_name_in(styles);
+ let page_nr = page.plain_text();
+ let quotes = SmartQuotes::get(
+ SmartQuoteElem::quotes_in(styles),
+ TextElem::lang_in(styles),
+ TextElem::region_in(styles),
+ SmartQuoteElem::alternative_in(styles),
+ );
+ let open = quotes.double_open;
+ let close = quotes.double_close;
+ eco_format!("{prefix} {open}{body}{close} {page_str} {page_nr}",)
+}
+
/// Measures the width of a prefix.
fn measure_prefix(
engine: &mut Engine,
diff --git a/crates/typst-library/src/model/reference.rs b/crates/typst-library/src/model/reference.rs
index b04c57c4..2b35a826 100644
--- a/crates/typst-library/src/model/reference.rs
+++ b/crates/typst-library/src/model/reference.rs
@@ -338,13 +338,18 @@ fn show_reference(
Smart::Custom(Some(supplement)) => supplement.resolve(engine, styles, [elem])?,
};
+ let alt = {
+ let supplement = supplement.plain_text();
+ let numbering = numbers.plain_text();
+ eco_format!("{supplement} {numbering}",)
+ };
+
let mut content = numbers;
if !supplement.is_empty() {
content = supplement + TextElem::packed("\u{a0}") + content;
}
- // TODO: accept user supplied alt text
- Ok(content.linked(Destination::Location(loc), None))
+ Ok(content.linked(Destination::Location(loc), Some(alt)))
}
/// Turn a reference into a citation.