mirror of
https://github.com/typst/typst
synced 2025-07-27 14:27:56 +08:00
feat: always write alt text in marked content sequence for images
This commit is contained in:
parent
0d35ae28ad
commit
5bd9accb9c
@ -4,6 +4,7 @@ use std::sync::{Arc, OnceLock};
|
|||||||
use image::{DynamicImage, EncodableLayout, GenericImageView, Rgba};
|
use image::{DynamicImage, EncodableLayout, GenericImageView, Rgba};
|
||||||
use krilla::image::{BitsPerComponent, CustomImage, ImageColorspace};
|
use krilla::image::{BitsPerComponent, CustomImage, ImageColorspace};
|
||||||
use krilla::surface::Surface;
|
use krilla::surface::Surface;
|
||||||
|
use krilla::tagging::SpanTag;
|
||||||
use krilla_svg::{SurfaceExt, SvgSettings};
|
use krilla_svg::{SurfaceExt, SvgSettings};
|
||||||
use typst_library::diag::{bail, SourceResult};
|
use typst_library::diag::{bail, SourceResult};
|
||||||
use typst_library::foundations::Smart;
|
use typst_library::foundations::Smart;
|
||||||
@ -33,7 +34,8 @@ pub(crate) fn handle_image(
|
|||||||
|
|
||||||
gc.image_spans.insert(span);
|
gc.image_spans.insert(span);
|
||||||
|
|
||||||
let mut handle = tags::start_marked(gc, surface);
|
let mut handle =
|
||||||
|
tags::start_span(gc, surface, SpanTag::empty().with_alt_text(image.alt()));
|
||||||
let surface = handle.surface();
|
let surface = handle.surface();
|
||||||
match image.kind() {
|
match image.kind() {
|
||||||
ImageKind::Raster(raster) => {
|
ImageKind::Raster(raster) => {
|
||||||
|
@ -5,7 +5,7 @@ use ecow::EcoString;
|
|||||||
use krilla::page::Page;
|
use krilla::page::Page;
|
||||||
use krilla::surface::Surface;
|
use krilla::surface::Surface;
|
||||||
use krilla::tagging::{
|
use krilla::tagging::{
|
||||||
ArtifactType, ContentTag, Identifier, Node, TableCellSpan, TableDataCell,
|
ArtifactType, ContentTag, Identifier, Node, SpanTag, TableCellSpan, TableDataCell,
|
||||||
TableHeaderCell, TableHeaderScope, Tag, TagBuilder, TagGroup, TagKind, TagTree,
|
TableHeaderCell, TableHeaderScope, Tag, TagBuilder, TagGroup, TagKind, TagTree,
|
||||||
};
|
};
|
||||||
use typst_library::foundations::{Content, LinkMarker, Packed, StyleChain};
|
use typst_library::foundations::{Content, LinkMarker, Packed, StyleChain};
|
||||||
@ -156,16 +156,16 @@ impl Tags {
|
|||||||
|
|
||||||
/// Returns the current parent's list of children and the structure type ([Tag]).
|
/// Returns the current parent's list of children and the structure type ([Tag]).
|
||||||
/// In case of the document root the structure type will be `None`.
|
/// In case of the document root the structure type will be `None`.
|
||||||
pub(crate) fn parent(&mut self) -> (Option<&mut StackEntryKind>, &mut Vec<TagNode>) {
|
pub(crate) fn parent(&mut self) -> Option<&mut StackEntryKind> {
|
||||||
if let Some(entry) = self.stack.last_mut() {
|
self.stack.last_mut().map(|e| &mut e.kind)
|
||||||
(Some(&mut entry.kind), &mut entry.nodes)
|
|
||||||
} else {
|
|
||||||
(None, &mut self.tree)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push(&mut self, node: TagNode) {
|
pub(crate) fn push(&mut self, node: TagNode) {
|
||||||
self.parent().1.push(node);
|
if let Some(entry) = self.stack.last_mut() {
|
||||||
|
entry.nodes.push(node);
|
||||||
|
} else {
|
||||||
|
self.tree.push(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_tree(&mut self) -> TagTree {
|
pub(crate) fn build_tree(&mut self) -> TagTree {
|
||||||
@ -224,12 +224,30 @@ impl<'a> TagHandle<'a, '_> {
|
|||||||
pub(crate) fn start_marked<'a, 'b>(
|
pub(crate) fn start_marked<'a, 'b>(
|
||||||
gc: &mut GlobalContext,
|
gc: &mut GlobalContext,
|
||||||
surface: &'b mut Surface<'a>,
|
surface: &'b mut Surface<'a>,
|
||||||
|
) -> TagHandle<'a, 'b> {
|
||||||
|
start_content(gc, surface, ContentTag::Other)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`TagHandle`] that automatically calls [`Surface::end_tagged`]
|
||||||
|
/// when dropped.
|
||||||
|
pub(crate) fn start_span<'a, 'b>(
|
||||||
|
gc: &mut GlobalContext,
|
||||||
|
surface: &'b mut Surface<'a>,
|
||||||
|
span: SpanTag,
|
||||||
|
) -> TagHandle<'a, 'b> {
|
||||||
|
start_content(gc, surface, ContentTag::Span(span))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_content<'a, 'b>(
|
||||||
|
gc: &mut GlobalContext,
|
||||||
|
surface: &'b mut Surface<'a>,
|
||||||
|
content: ContentTag,
|
||||||
) -> TagHandle<'a, 'b> {
|
) -> TagHandle<'a, 'b> {
|
||||||
let content = if let Some((_, kind)) = gc.tags.in_artifact {
|
let content = if let Some((_, kind)) = gc.tags.in_artifact {
|
||||||
let ty = artifact_type(kind);
|
let ty = artifact_type(kind);
|
||||||
ContentTag::Artifact(ty)
|
ContentTag::Artifact(ty)
|
||||||
} else {
|
} else {
|
||||||
ContentTag::Other
|
content
|
||||||
};
|
};
|
||||||
let id = surface.start_tagged(content);
|
let id = surface.start_tagged(content);
|
||||||
gc.tags.push(TagNode::Leaf(id));
|
gc.tags.push(TagNode::Leaf(id));
|
||||||
@ -295,13 +313,15 @@ pub(crate) fn handle_start(gc: &mut GlobalContext, elem: &Content) {
|
|||||||
} else if let Some(image) = elem.to_packed::<ImageElem>() {
|
} else if let Some(image) = elem.to_packed::<ImageElem>() {
|
||||||
let alt = image.alt(StyleChain::default()).map(|s| s.to_string());
|
let alt = image.alt(StyleChain::default()).map(|s| s.to_string());
|
||||||
|
|
||||||
let figure_tag = (gc.tags.parent().0)
|
let figure_tag = (gc.tags.parent())
|
||||||
.and_then(|parent| parent.as_standard_mut())
|
.and_then(StackEntryKind::as_standard_mut)
|
||||||
.filter(|tag| tag.kind == TagKind::Figure && tag.alt_text.is_none());
|
.filter(|tag| tag.kind == TagKind::Figure);
|
||||||
if let Some(figure_tag) = figure_tag {
|
if let Some(figure_tag) = figure_tag {
|
||||||
|
if figure_tag.alt_text.is_none() {
|
||||||
// HACK: set alt text of outer figure tag, if the contained image
|
// HACK: set alt text of outer figure tag, if the contained image
|
||||||
// has alt text specified
|
// has alt text specified
|
||||||
figure_tag.alt_text = alt;
|
figure_tag.alt_text = alt;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
TagKind::Figure.with_alt_text(alt)
|
TagKind::Figure.with_alt_text(alt)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user