mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
feat: best effort link alt text generation
This commit is contained in:
parent
79423f3033
commit
99815f449c
@ -222,9 +222,10 @@ const LINK_MARKER_RULE: ShowFn<LinkMarker> = |elem, _, _| Ok(elem.body.clone());
|
||||
const LINK_RULE: ShowFn<LinkElem> = |elem, engine, styles| {
|
||||
let body = elem.body.clone();
|
||||
let dest = elem.dest.resolve(engine.introspector).at(elem.span())?;
|
||||
let url = || dest.as_url().map(|url| url.clone().into_inner());
|
||||
// TODO(accessibility): remove custom alt field and generate alt text
|
||||
let alt = elem.alt.get_cloned(styles).or_else(url);
|
||||
let alt = match elem.alt.get_cloned(styles) {
|
||||
Some(alt) => Some(alt),
|
||||
None => dest.alt_text(engine, styles)?,
|
||||
};
|
||||
Ok(body.linked(dest, alt))
|
||||
};
|
||||
|
||||
|
@ -795,8 +795,8 @@ 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(accessibility): generate alt text
|
||||
content = content.linked(dest, None);
|
||||
let alt = content.plain_text();
|
||||
content = content.linked(dest, Some(alt));
|
||||
}
|
||||
StrResult::Ok(content)
|
||||
})
|
||||
@ -931,8 +931,8 @@ impl ElemRenderer<'_> {
|
||||
if let Some(hayagriva::ElemMeta::Entry(i)) = elem.meta {
|
||||
if let Some(location) = (self.link)(i) {
|
||||
let dest = Destination::Location(location);
|
||||
// TODO(accessibility): generate alt text
|
||||
content = content.linked(dest, None);
|
||||
let alt = content.plain_text();
|
||||
content = content.linked(dest, Some(alt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,18 @@
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
|
||||
use comemo::Tracked;
|
||||
use ecow::{eco_format, EcoString};
|
||||
|
||||
use crate::diag::{bail, StrResult};
|
||||
use crate::diag::{bail, SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
cast, elem, Content, Label, Packed, Repr, ShowSet, Smart, StyleChain, Styles,
|
||||
};
|
||||
use crate::introspection::{Introspector, Locatable, Location};
|
||||
use crate::layout::Position;
|
||||
use crate::text::TextElem;
|
||||
use crate::introspection::{Counter, CounterKey, Introspector, Locatable, Location};
|
||||
use crate::layout::{PageElem, Position};
|
||||
use crate::model::NumberingPattern;
|
||||
use crate::text::{LocalName, TextElem};
|
||||
|
||||
/// Links to a URL or a location in the document.
|
||||
///
|
||||
@ -216,12 +219,26 @@ pub enum Destination {
|
||||
}
|
||||
|
||||
impl Destination {
|
||||
pub fn as_url(&self) -> Option<&Url> {
|
||||
if let Self::Url(v) = self {
|
||||
Some(v)
|
||||
} else {
|
||||
None
|
||||
pub fn alt_text(
|
||||
&self,
|
||||
engine: &mut Engine,
|
||||
styles: StyleChain,
|
||||
) -> SourceResult<Option<EcoString>> {
|
||||
let alt = match self {
|
||||
Destination::Url(url) => Some(url.clone().into_inner()),
|
||||
Destination::Position(_) => None,
|
||||
&Destination::Location(loc) => {
|
||||
let numbering = loc
|
||||
.page_numbering(engine)
|
||||
.unwrap_or_else(|| NumberingPattern::from_str("1").unwrap().into());
|
||||
let content = Counter::new(CounterKey::Page)
|
||||
.display_at_loc(engine, loc, styles, &numbering)?;
|
||||
let page_nr = content.plain_text();
|
||||
let page_str = PageElem::local_name_in(styles);
|
||||
Some(eco_format!("{page_str} {page_nr}"))
|
||||
}
|
||||
};
|
||||
Ok(alt)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user