acdc_parser/model/title.rs
1use std::ops::Deref;
2
3use serde::{Serialize, ser::Serializer};
4
5use super::inlines::InlineNode;
6
7/// A title in a document (section titles, block titles, document title, etc.).
8///
9/// `Title` is a newtype wrapper around `Vec<InlineNode>` that provides convenient
10/// access to inline content. Titles can include formatting, links, and other inline
11/// elements.
12///
13/// # Accessing Content
14///
15/// `Title` implements `Deref<Target=[InlineNode]>`, so you can use slice methods directly:
16///
17/// ```
18/// # use acdc_parser::{Title, InlineNode};
19/// let title = Title::new(vec![/* inline nodes */]);
20///
21/// // Iterate over inline nodes
22/// for node in &title {
23/// // ...
24/// }
25///
26/// // Check if empty
27/// if title.is_empty() {
28/// // ...
29/// }
30///
31/// // Access by index (via deref)
32/// if let Some(first) = title.first() {
33/// // ...
34/// }
35/// ```
36///
37/// # Serialization
38///
39/// Serializes as a plain JSON array of inline nodes for ASG compatibility.
40#[derive(Clone, Debug, Default, PartialEq)]
41#[non_exhaustive]
42pub struct Title(Vec<InlineNode>);
43
44impl Serialize for Title {
45 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46 where
47 S: Serializer,
48 {
49 self.0.serialize(serializer)
50 }
51}
52
53pub type Subtitle = Title;
54
55impl Title {
56 /// Creates a new `Title` with the given inline content.
57 #[must_use]
58 pub fn new(inlines: Vec<InlineNode>) -> Self {
59 Self(inlines)
60 }
61
62 /// Returns `true` if the title has no content.
63 #[must_use]
64 pub fn is_empty(&self) -> bool {
65 self.0.is_empty()
66 }
67
68 /// Returns the number of inline nodes in the title.
69 #[must_use]
70 pub fn len(&self) -> usize {
71 self.0.len()
72 }
73}
74
75impl From<Vec<InlineNode>> for Title {
76 fn from(inlines: Vec<InlineNode>) -> Self {
77 Self(inlines)
78 }
79}
80
81impl AsRef<[InlineNode]> for Title {
82 fn as_ref(&self) -> &[InlineNode] {
83 &self.0
84 }
85}
86
87impl Deref for Title {
88 type Target = [InlineNode];
89
90 fn deref(&self) -> &Self::Target {
91 &self.0
92 }
93}
94
95impl<'a> IntoIterator for &'a Title {
96 type Item = &'a InlineNode;
97 type IntoIter = std::slice::Iter<'a, InlineNode>;
98
99 fn into_iter(self) -> Self::IntoIter {
100 self.0.iter()
101 }
102}