From e5fcc3bf5ec0cb3f3d2bd458fc8854ce528a42a5 Mon Sep 17 00:00:00 2001 From: Tobias Schmitz Date: Mon, 4 Aug 2025 19:53:33 +0200 Subject: [PATCH] feat: disable tags inside hide elem --- crates/typst-pdf/src/tags/context.rs | 3 +- crates/typst-pdf/src/tags/mod.rs | 21 +++++++----- tests/ref/pdftags/disable-tags-hide.yml | 4 +++ .../disable-tags-partially-hidden-list.yml | 34 +++++++++++++++++++ tests/suite/pdftags/disable.typ | 28 +++++++++++++++ 5 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 tests/ref/pdftags/disable-tags-hide.yml create mode 100644 tests/ref/pdftags/disable-tags-partially-hidden-list.yml diff --git a/crates/typst-pdf/src/tags/context.rs b/crates/typst-pdf/src/tags/context.rs index b06afda6e..5b869bd53 100644 --- a/crates/typst-pdf/src/tags/context.rs +++ b/crates/typst-pdf/src/tags/context.rs @@ -189,7 +189,8 @@ impl Tags { #[derive(Clone, Copy, Debug)] pub enum Disable { - ArtifactTag(Location, ArtifactKind), + /// Either an artifact or a hide element. + Elem(Location, ArtifactKind), Tiling, } diff --git a/crates/typst-pdf/src/tags/mod.rs b/crates/typst-pdf/src/tags/mod.rs index 7984999c9..2eb7fb0db 100644 --- a/crates/typst-pdf/src/tags/mod.rs +++ b/crates/typst-pdf/src/tags/mod.rs @@ -11,7 +11,7 @@ use krilla::tagging::{ use typst_library::diag::{SourceResult, bail}; use typst_library::foundations::{Content, LinkMarker, Smart}; use typst_library::introspection::Location; -use typst_library::layout::{Point, Rect, RepeatElem, Size}; +use typst_library::layout::{HideElem, Point, Rect, RepeatElem, Size}; use typst_library::math::EquationElem; use typst_library::model::{ Destination, EnumElem, FigureCaption, FigureElem, FootnoteEntry, HeadingElem, @@ -105,12 +105,15 @@ pub fn handle_start( return Ok(()); } - if let Some(artifact) = elem.to_packed::() { + if let Some(_) = elem.to_packed::() { + push_disable(gc, surface, elem, ArtifactKind::Other); + return Ok(()); + } else if let Some(artifact) = elem.to_packed::() { let kind = artifact.kind.val(); - push_artifact_tag(gc, surface, elem, kind); + push_disable(gc, surface, elem, kind); return Ok(()); } else if let Some(_) = elem.to_packed::() { - push_artifact_tag(gc, surface, elem, ArtifactKind::Other); + push_disable(gc, surface, elem, ArtifactKind::Other); return Ok(()); } @@ -207,7 +210,7 @@ pub fn handle_start( // first page. Maybe it should be the cell on the last page, but that // would require more changes in the layouting code, or a pre-pass // on the frames to figure out if there are other footers following. - push_artifact_tag(gc, surface, elem, ArtifactKind::Other); + push_disable(gc, surface, elem, ArtifactKind::Other); } else { push_stack(gc, elem, StackEntryKind::TableCell(cell.clone()))?; } @@ -312,7 +315,7 @@ fn push_stack( Ok(()) } -fn push_artifact_tag( +fn push_disable( gc: &mut GlobalContext, surface: &mut Surface, elem: &Content, @@ -321,7 +324,7 @@ fn push_artifact_tag( let loc = elem.location().expect("elem to be locatable"); let ty = artifact_type(kind); surface.start_tagged(ContentTag::Artifact(ty)); - gc.tags.disable = Some(Disable::ArtifactTag(loc, kind)); + gc.tags.disable = Some(Disable::Elem(loc, kind)); } pub fn handle_end( @@ -333,7 +336,7 @@ pub fn handle_end( return Ok(()); } - if let Some(Disable::ArtifactTag(l, _)) = gc.tags.disable + if let Some(Disable::Elem(l, _)) = gc.tags.disable && l == loc { surface.end_tagged(); @@ -541,7 +544,7 @@ pub fn page_start(gc: &mut GlobalContext, surface: &mut Surface) { if let Some(disable) = gc.tags.disable { let kind = match disable { - Disable::ArtifactTag(_, kind) => kind, + Disable::Elem(_, kind) => kind, Disable::Tiling => ArtifactKind::Other, }; let ty = artifact_type(kind); diff --git a/tests/ref/pdftags/disable-tags-hide.yml b/tests/ref/pdftags/disable-tags-hide.yml new file mode 100644 index 000000000..8c4b9e4c3 --- /dev/null +++ b/tests/ref/pdftags/disable-tags-hide.yml @@ -0,0 +1,4 @@ +- Tag: H1 + /T: "Hidden" + /K: + - Content: page=0 mcid=0 diff --git a/tests/ref/pdftags/disable-tags-partially-hidden-list.yml b/tests/ref/pdftags/disable-tags-partially-hidden-list.yml new file mode 100644 index 000000000..9986aecaf --- /dev/null +++ b/tests/ref/pdftags/disable-tags-partially-hidden-list.yml @@ -0,0 +1,34 @@ +- Tag: H1 + /T: "Tail hidden" + /K: + - Content: page=0 mcid=0 +- Tag: L + /Numbering: Circle + /K: + - Tag: LI + /K: + - Tag: Lbl + /K: + - Content: page=0 mcid=1 + - Tag: LBody + /K: + - Content: page=0 mcid=2 + - Tag: LI + /K: + - Tag: Lbl + /K: + - Content: page=0 mcid=3 + - Tag: LBody + /K: + - Tag: P + - Tag: L + /Numbering: Circle + /K: + - Tag: LI + /K: + - Tag: Lbl + - Tag: LBody +- Tag: H1 + /T: "Head hidden" + /K: + - Content: page=0 mcid=4 diff --git a/tests/suite/pdftags/disable.typ b/tests/suite/pdftags/disable.typ index 4fa276510..7fc77149d 100644 --- a/tests/suite/pdftags/disable.typ +++ b/tests/suite/pdftags/disable.typ @@ -19,3 +19,31 @@ - c ] #rect(fill: pat) + +--- disable-tags-hide pdftags --- += Hidden + +#hide[ + - a + - b + - c +] + +--- disable-tags-partially-hidden-list pdftags --- +// FIXME(accessibility): In realization, tags inside of list groupings aren't +// handled. Thus if the head of the list is visible, all tags of list items +// will be emitted before (outside) the hide element. And if the head is not +// visible, all tags of list items will be emitted inside the hide element. += Tail hidden +- a +#hide[ +- b + - c +] + += Head hidden +#hide[ +- a +] +- b + - c