feat: write tags for raw text

This commit is contained in:
Tobias Schmitz 2025-07-30 18:35:22 +02:00
parent 95e0e76e9d
commit 0e7d1f10ba
No known key found for this signature in database

View File

@ -23,6 +23,7 @@ use typst_library::model::{
TermsElem, TermsElem,
}; };
use typst_library::pdf::{ArtifactElem, ArtifactKind, PdfMarkerTag, PdfMarkerTagKind}; use typst_library::pdf::{ArtifactElem, ArtifactKind, PdfMarkerTag, PdfMarkerTagKind};
use typst_library::text::RawElem;
use typst_library::visualize::ImageElem; use typst_library::visualize::ImageElem;
use typst_syntax::Span; use typst_syntax::Span;
@ -177,6 +178,22 @@ pub(crate) fn handle_start(
} else if let Some(quote) = elem.to_packed::<QuoteElem>() { } else if let Some(quote) = elem.to_packed::<QuoteElem>() {
// TODO: should the attribution be handled somehow? // TODO: should the attribution be handled somehow?
if quote.block.val() { Tag::BlockQuote.into() } else { Tag::InlineQuote.into() } if quote.block.val() { Tag::BlockQuote.into() } else { Tag::InlineQuote.into() }
} else if let Some(raw) = elem.to_packed::<RawElem>() {
let desc = raw.lang.opt_ref().and_then(|lang_token| {
let lower = lang_token.to_lowercase();
let (lang, _) = RawElem::languages()
.into_iter()
.find(|(_, tokens)| tokens.contains(&lower.as_str()))?;
// TODO: localization
Some(if raw.block.val() {
format!("code block {lang}")
} else {
format!("inline code {lang}")
})
});
push_stack(gc, elem, StackEntryKind::Code(desc))?;
return Ok(());
} else { } else {
return Ok(()); return Ok(());
}; };
@ -399,6 +416,15 @@ fn pop_stack(gc: &mut GlobalContext, entry: StackEntry) {
ctx.entry = Some(tag); ctx.entry = Some(tag);
return; return;
} }
StackEntryKind::Code(desc) => {
let code = TagNode::group(Tag::Code, entry.nodes);
if desc.is_some() {
let desc = TagNode::group(Tag::Span.with_alt_text(desc), Vec::new());
TagNode::group(Tag::NonStruct, vec![desc, code])
} else {
code
}
}
}; };
gc.tags.push(node); gc.tags.push(node);
@ -749,6 +775,7 @@ pub(crate) enum StackEntryKind {
/// The footnote entry at the end of the page. Contains the [`Location`] of /// The footnote entry at the end of the page. Contains the [`Location`] of
/// the [`FootnoteElem`](typst_library::model::FootnoteElem). /// the [`FootnoteElem`](typst_library::model::FootnoteElem).
FootnoteEntry(Location), FootnoteEntry(Location),
Code(Option<String>),
} }
impl StackEntryKind { impl StackEntryKind {
@ -844,6 +871,7 @@ impl StackEntryKind {
StackEntryKind::Link(..) => !is_pdf_ua, StackEntryKind::Link(..) => !is_pdf_ua,
StackEntryKind::FootnoteRef(_) => false, StackEntryKind::FootnoteRef(_) => false,
StackEntryKind::FootnoteEntry(_) => false, StackEntryKind::FootnoteEntry(_) => false,
StackEntryKind::Code(_) => false,
} }
} }
} }
@ -965,6 +993,12 @@ pub(crate) enum TagNode {
FootnoteEntry(Location), FootnoteEntry(Location),
} }
impl TagNode {
pub fn group(tag: impl Into<TagKind>, children: Vec<TagNode>) -> Self {
TagNode::Group(tag.into(), children)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct Placeholder(usize); pub(crate) struct Placeholder(usize);