cdx_core/extensions/semantic/
citation.rs1use serde::{Deserialize, Serialize};
4
5use crate::content::Block;
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Citation {
11 #[serde(rename = "ref")]
13 pub reference: String,
14
15 #[serde(default, skip_serializing_if = "Option::is_none")]
17 pub locator: Option<String>,
18
19 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub locator_type: Option<LocatorType>,
22
23 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub prefix: Option<String>,
26
27 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub suffix: Option<String>,
30
31 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
33 pub suppress_author: bool,
34}
35
36impl Citation {
37 #[must_use]
39 pub fn new(reference: impl Into<String>) -> Self {
40 Self {
41 reference: reference.into(),
42 locator: None,
43 locator_type: None,
44 prefix: None,
45 suffix: None,
46 suppress_author: false,
47 }
48 }
49
50 #[must_use]
52 pub fn with_page(mut self, page: impl Into<String>) -> Self {
53 self.locator = Some(page.into());
54 self.locator_type = Some(LocatorType::Page);
55 self
56 }
57
58 #[must_use]
60 pub fn with_locator(mut self, locator: impl Into<String>, locator_type: LocatorType) -> Self {
61 self.locator = Some(locator.into());
62 self.locator_type = Some(locator_type);
63 self
64 }
65
66 #[must_use]
68 pub fn with_prefix(mut self, prefix: impl Into<String>) -> Self {
69 self.prefix = Some(prefix.into());
70 self
71 }
72
73 #[must_use]
75 pub fn with_suffix(mut self, suffix: impl Into<String>) -> Self {
76 self.suffix = Some(suffix.into());
77 self
78 }
79
80 #[must_use]
82 pub const fn suppress_author(mut self) -> Self {
83 self.suppress_author = true;
84 self
85 }
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
90#[serde(rename_all = "lowercase")]
91pub enum LocatorType {
92 Page,
94 Chapter,
96 Section,
98 Paragraph,
100 Verse,
102 Line,
104 Figure,
106 Table,
108 Equation,
110 Timestamp,
112}
113
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub struct Footnote {
121 pub number: u32,
123
124 #[serde(default, skip_serializing_if = "Option::is_none")]
126 pub id: Option<String>,
127
128 #[serde(default, skip_serializing_if = "Option::is_none")]
131 pub content: Option<String>,
132
133 #[serde(default, skip_serializing_if = "Vec::is_empty")]
136 pub children: Vec<Block>,
137}
138
139impl Footnote {
140 #[must_use]
142 pub fn new(number: u32) -> Self {
143 Self {
144 number,
145 id: None,
146 content: None,
147 children: Vec::new(),
148 }
149 }
150
151 #[must_use]
153 pub fn with_id(mut self, id: impl Into<String>) -> Self {
154 self.id = Some(id.into());
155 self
156 }
157
158 #[must_use]
163 pub fn with_content(mut self, content: impl Into<String>) -> Self {
164 self.content = Some(content.into());
165 self
166 }
167
168 #[must_use]
173 pub fn with_children(mut self, children: Vec<Block>) -> Self {
174 self.children = children;
175 self
176 }
177
178 #[must_use]
180 pub fn has_children(&self) -> bool {
181 !self.children.is_empty()
182 }
183
184 #[must_use]
186 pub fn has_content(&self) -> bool {
187 self.content.is_some()
188 }
189}