mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
feat: [WIP] generate alt text for ref elements
This commit is contained in:
parent
254aadccfc
commit
3d4d548934
@ -877,7 +877,7 @@ impl<'a> Generator<'a> {
|
|||||||
renderer.display_elem_child(elem, &mut None, false)?;
|
renderer.display_elem_child(elem, &mut None, false)?;
|
||||||
if let Some(location) = first_occurrences.get(item.key.as_str()) {
|
if let Some(location) = first_occurrences.get(item.key.as_str()) {
|
||||||
let dest = Destination::Location(*location);
|
let dest = Destination::Location(*location);
|
||||||
// TODO: accept user supplied alt text
|
// TODO(accessibility): generate alt text
|
||||||
content = content.linked(dest, None);
|
content = content.linked(dest, None);
|
||||||
}
|
}
|
||||||
StrResult::Ok(content)
|
StrResult::Ok(content)
|
||||||
@ -1013,7 +1013,7 @@ impl ElemRenderer<'_> {
|
|||||||
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta {
|
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta {
|
||||||
if let Some(location) = (self.link)(i) {
|
if let Some(location) = (self.link)(i) {
|
||||||
let dest = Destination::Location(location);
|
let dest = Destination::Location(location);
|
||||||
// TODO: accept user supplied alt text
|
// TODO(accessibility): generate alt text
|
||||||
content = content.linked(dest, None);
|
content = content.linked(dest, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ impl Show for Packed<FootnoteElem> {
|
|||||||
let sup = SuperElem::new(num).pack().spanned(span);
|
let sup = SuperElem::new(num).pack().spanned(span);
|
||||||
let loc = loc.variant(1);
|
let loc = loc.variant(1);
|
||||||
// Add zero-width weak spacing to make the footnote "sticky".
|
// 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))
|
Ok(HElem::hole().pack() + sup.linked(Destination::Location(loc), None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ impl Show for Packed<FootnoteEntry> {
|
|||||||
let sup = SuperElem::new(num)
|
let sup = SuperElem::new(num)
|
||||||
.pack()
|
.pack()
|
||||||
.spanned(span)
|
.spanned(span)
|
||||||
// TODO: accept user supplied alt text
|
// TODO(accessibility): generate alt text
|
||||||
.linked(Destination::Location(loc), None)
|
.linked(Destination::Location(loc), None)
|
||||||
.located(loc.variant(1));
|
.located(loc.variant(1));
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use std::num::NonZeroUsize;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use comemo::{Track, Tracked};
|
use comemo::{Track, Tracked};
|
||||||
use ecow::eco_format;
|
use ecow::{eco_format, EcoString};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use typst_syntax::Span;
|
use typst_syntax::Span;
|
||||||
use typst_utils::{Get, NonZeroExt};
|
use typst_utils::{Get, NonZeroExt};
|
||||||
@ -23,7 +23,7 @@ use crate::layout::{
|
|||||||
};
|
};
|
||||||
use crate::math::EquationElem;
|
use crate::math::EquationElem;
|
||||||
use crate::model::{Destination, HeadingElem, NumberingPattern, ParElem, Refable};
|
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.
|
/// 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::new(None, Some(styles));
|
||||||
let context = context.track();
|
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 prefix = self.prefix(engine, context, span)?;
|
||||||
let body = self.body().at(span)?;
|
let body = self.body().at(span)?;
|
||||||
let page = self.page(engine, context, span)?;
|
let page = self.page(engine, context, span)?;
|
||||||
let alt = {
|
let alt = alt_text(styles, &prefix, &body, &page);
|
||||||
// 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 inner = self.inner(context, span, body, page)?;
|
let inner = self.inner(context, span, body, page)?;
|
||||||
let block = if self.element.is::<EquationElem>() {
|
let block = if self.element.is::<EquationElem>() {
|
||||||
let body = prefix.unwrap_or_default() + inner;
|
let body = prefix.unwrap_or_default() + inner;
|
||||||
@ -704,6 +697,27 @@ cast! {
|
|||||||
v: Content => v.unpack::<Self>().map_err(|_| "expected outline entry")?
|
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.
|
/// Measures the width of a prefix.
|
||||||
fn measure_prefix(
|
fn measure_prefix(
|
||||||
engine: &mut Engine,
|
engine: &mut Engine,
|
||||||
|
@ -338,13 +338,18 @@ fn show_reference(
|
|||||||
Smart::Custom(Some(supplement)) => supplement.resolve(engine, styles, [elem])?,
|
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;
|
let mut content = numbers;
|
||||||
if !supplement.is_empty() {
|
if !supplement.is_empty() {
|
||||||
content = supplement + TextElem::packed("\u{a0}") + content;
|
content = supplement + TextElem::packed("\u{a0}") + content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: accept user supplied alt text
|
Ok(content.linked(Destination::Location(loc), Some(alt)))
|
||||||
Ok(content.linked(Destination::Location(loc), None))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turn a reference into a citation.
|
/// Turn a reference into a citation.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user