Skip to main content

acdc_parser/model/
anchor.rs

1//! Anchor and reference types for `AsciiDoc` documents.
2
3use serde::{
4    Serialize,
5    ser::{SerializeMap, Serializer},
6};
7
8use super::location::Location;
9use super::title::Title;
10
11/// Section styles that should not receive automatic numbering.
12///
13/// When `sectnums` is enabled, sections with these styles are excluded from
14/// the numbering scheme. Appendix uses letter numbering (A, B, C) which is
15/// handled separately.
16pub const UNNUMBERED_SECTION_STYLES: &[&str] = &[
17    "preface",
18    "abstract",
19    "dedication",
20    "colophon",
21    "bibliography",
22    "glossary",
23    "index",
24    "appendix",
25];
26
27/// An `Anchor` represents an anchor in a document.
28///
29/// An anchor is a reference point in a document that can be linked to.
30#[derive(Clone, Debug, Default, PartialEq, Serialize)]
31#[non_exhaustive]
32pub struct Anchor {
33    pub id: String,
34    #[serde(default, skip_serializing_if = "Option::is_none")]
35    pub xreflabel: Option<String>,
36    pub location: Location,
37}
38
39impl Anchor {
40    /// Create a new anchor with the given ID and location.
41    #[must_use]
42    pub fn new(id: String, location: Location) -> Self {
43        Self {
44            id,
45            xreflabel: None,
46            location,
47        }
48    }
49
50    /// Set the cross-reference label.
51    #[must_use]
52    pub fn with_xreflabel(mut self, xreflabel: Option<String>) -> Self {
53        self.xreflabel = xreflabel;
54        self
55    }
56}
57
58/// A `TocEntry` represents a table of contents entry.
59///
60/// This is collected during parsing from Section.
61#[derive(Clone, Debug, PartialEq)]
62#[non_exhaustive]
63pub struct TocEntry {
64    /// Unique identifier for this section (used for anchor links)
65    pub id: String,
66    /// Title of the section
67    pub title: Title,
68    /// Section level (1 for top-level, 2 for subsection, etc.)
69    pub level: u8,
70    /// Optional cross-reference label (from `[[id,xreflabel]]` syntax)
71    pub xreflabel: Option<String>,
72    /// Whether this section should be numbered when `sectnums` is enabled.
73    ///
74    /// False for special section styles like `[bibliography]`, `[glossary]`, etc.
75    pub numbered: bool,
76}
77
78impl Serialize for TocEntry {
79    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80    where
81        S: Serializer,
82    {
83        let mut state = serializer.serialize_map(None)?;
84        state.serialize_entry("id", &self.id)?;
85        state.serialize_entry("title", &self.title)?;
86        state.serialize_entry("level", &self.level)?;
87        if self.xreflabel.is_some() {
88            state.serialize_entry("xreflabel", &self.xreflabel)?;
89        }
90        state.end()
91    }
92}