From 6ebe85d67877254683e8038ad7fbf262fd495636 Mon Sep 17 00:00:00 2001 From: Tobias Schmitz Date: Thu, 26 Jun 2025 18:50:43 +0200 Subject: [PATCH] fix: don't include outline title in TOC hierarchy --- crates/typst-library/src/model/outline.rs | 19 ++++++++++++++++++- crates/typst-pdf/src/tags.rs | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/crates/typst-library/src/model/outline.rs b/crates/typst-library/src/model/outline.rs index 9db263be1..1e177130d 100644 --- a/crates/typst-library/src/model/outline.rs +++ b/crates/typst-library/src/model/outline.rs @@ -273,6 +273,7 @@ impl Show for Packed { let depth = self.depth(styles).unwrap_or(NonZeroUsize::MAX); // Build the outline entries. + let mut entries = vec![]; for elem in elems { let Some(outlinable) = elem.with::() else { bail!(span, "cannot outline {}", elem.func().name()); @@ -281,10 +282,13 @@ impl Show for Packed { let level = outlinable.level(); if outlinable.outlined() && level <= depth { let entry = OutlineEntry::new(level, elem); - seq.push(entry.pack().spanned(span)); + entries.push(entry.pack().spanned(span)); } } + // Wrap the entries into a marker for pdf tagging. + seq.push(OutlineBody::new(Content::sequence(entries)).pack()); + Ok(Content::sequence(seq)) } } @@ -307,6 +311,19 @@ impl LocalName for Packed { const KEY: &'static str = "outline"; } +/// Only used to mark +#[elem(Locatable, Show)] +pub struct OutlineBody { + #[required] + body: Content, +} + +impl Show for Packed { + fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult { + Ok(self.body.clone()) + } +} + /// Defines how an outline is indented. #[derive(Debug, Clone, PartialEq, Hash)] pub enum OutlineIndent { diff --git a/crates/typst-pdf/src/tags.rs b/crates/typst-pdf/src/tags.rs index d65e898c8..8e41ea2ff 100644 --- a/crates/typst-pdf/src/tags.rs +++ b/crates/typst-pdf/src/tags.rs @@ -11,7 +11,7 @@ use typst_library::foundations::{Content, LinkMarker, Packed, StyleChain}; use typst_library::introspection::Location; use typst_library::layout::RepeatElem; use typst_library::model::{ - Destination, FigureCaption, FigureElem, HeadingElem, Outlinable, OutlineElem, + Destination, FigureCaption, FigureElem, HeadingElem, Outlinable, OutlineBody, OutlineEntry, TableCell, TableElem, }; use typst_library::pdf::{ArtifactElem, ArtifactKind, PdfTagElem, PdfTagKind}; @@ -383,7 +383,7 @@ pub(crate) fn handle_start(gc: &mut GlobalContext, elem: &Content) { // TODO: when targeting PDF 2.0 headings `> 6` are supported _ => TagKind::H6(Some(name)).into(), } - } else if let Some(_) = elem.to_packed::() { + } else if let Some(_) = elem.to_packed::() { push_stack(gc, loc, StackEntryKind::Outline(OutlineCtx::new())); return; } else if let Some(entry) = elem.to_packed::() {