acdc_parser/model/inlines/
macros.rs1use std::collections::HashSet;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{ElementAttributes, InlineNode, Location, Source, StemNotation, Substitution};
6
7pub const ICON_SIZES: &[&str] = &["1x", "2x", "3x", "4x", "5x", "lg", "fw"];
8
9#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
11#[non_exhaustive]
12pub struct Pass {
13 #[serde(default, skip_serializing_if = "Option::is_none")]
14 pub text: Option<String>,
15 #[serde(default, skip_serializing_if = "HashSet::is_empty")]
16 pub substitutions: HashSet<Substitution>,
17 pub location: Location,
18 #[serde(skip)]
19 pub kind: PassthroughKind,
20}
21
22#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)]
23pub enum PassthroughKind {
24 #[default]
25 Single,
26 Double,
27 Triple,
28 Macro,
29}
30
31#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
33#[non_exhaustive]
34pub struct Footnote {
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub id: Option<String>,
37 #[serde(default, skip_serializing_if = "Vec::is_empty")]
38 pub content: Vec<InlineNode>,
39 #[serde(skip)]
40 pub number: u32,
41 pub location: Location,
42}
43
44#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
46#[non_exhaustive]
47pub struct Icon {
48 pub target: Source,
49 pub attributes: ElementAttributes,
50 pub location: Location,
51}
52
53#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
55#[non_exhaustive]
56pub struct Link {
57 #[serde(skip_serializing)]
60 pub text: Option<String>,
61 pub target: Source,
62 pub attributes: ElementAttributes,
63 pub location: Location,
64}
65
66impl Link {
67 #[must_use]
69 pub fn new(target: Source, location: Location) -> Self {
70 Self {
71 text: None,
72 target,
73 attributes: ElementAttributes::default(),
74 location,
75 }
76 }
77
78 #[must_use]
80 pub fn with_text(mut self, text: Option<String>) -> Self {
81 self.text = text;
82 self
83 }
84
85 #[must_use]
87 pub fn with_attributes(mut self, attributes: ElementAttributes) -> Self {
88 self.attributes = attributes;
89 self
90 }
91}
92
93#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
95#[non_exhaustive]
96pub struct Url {
97 #[serde(skip_serializing)]
100 pub text: Vec<InlineNode>,
101 pub target: Source,
102 pub attributes: ElementAttributes,
103 pub location: Location,
104}
105
106#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
108#[non_exhaustive]
109pub struct Mailto {
110 #[serde(skip_serializing)]
113 pub text: Vec<InlineNode>,
114 pub target: Source,
115 pub attributes: ElementAttributes,
116 pub location: Location,
117}
118
119#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
121#[non_exhaustive]
122pub struct Button {
123 pub label: String,
124 pub location: Location,
125}
126
127#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
129#[non_exhaustive]
130pub struct Menu {
131 pub target: String,
132 #[serde(default, skip_serializing_if = "Vec::is_empty")]
133 pub items: Vec<String>,
134 pub location: Location,
135}
136
137#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
139#[non_exhaustive]
140pub struct Keyboard {
141 pub keys: Vec<Key>,
142 pub location: Location,
143}
144
145impl Keyboard {
146 #[must_use]
148 pub fn new(keys: Vec<Key>, location: Location) -> Self {
149 Self { keys, location }
150 }
151}
152
153pub type Key = String;
155
156#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
158#[non_exhaustive]
159pub struct CrossReference {
160 pub target: String,
161 #[serde(default, skip_serializing_if = "Option::is_none")]
162 pub text: Option<String>,
163 pub location: Location,
164}
165
166impl CrossReference {
167 #[must_use]
169 pub fn new(target: impl Into<String>, location: Location) -> Self {
170 Self {
171 target: target.into(),
172 text: None,
173 location,
174 }
175 }
176
177 #[must_use]
179 pub fn with_text(mut self, text: Option<String>) -> Self {
180 self.text = text;
181 self
182 }
183}
184
185#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
187#[non_exhaustive]
188pub struct Autolink {
189 pub url: Source,
190 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
193 pub bracketed: bool,
194 pub location: Location,
195}
196
197#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
199#[non_exhaustive]
200pub struct Stem {
201 pub content: String,
202 pub notation: StemNotation,
203 pub location: Location,
204}
205
206#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
212#[non_exhaustive]
213pub enum IndexTermKind {
214 Flow(String),
218 Concealed {
222 term: String,
223 #[serde(default, skip_serializing_if = "Option::is_none")]
224 secondary: Option<String>,
225 #[serde(default, skip_serializing_if = "Option::is_none")]
226 tertiary: Option<String>,
227 },
228}
229
230#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
239#[non_exhaustive]
240pub struct IndexTerm {
241 pub kind: IndexTermKind,
243 pub location: Location,
244}
245
246impl IndexTerm {
247 #[must_use]
249 pub fn term(&self) -> &str {
250 match &self.kind {
251 IndexTermKind::Flow(term) | IndexTermKind::Concealed { term, .. } => term,
252 }
253 }
254
255 #[must_use]
257 pub fn secondary(&self) -> Option<&str> {
258 match &self.kind {
259 IndexTermKind::Flow(_) => None,
260 IndexTermKind::Concealed { secondary, .. } => secondary.as_deref(),
261 }
262 }
263
264 #[must_use]
266 pub fn tertiary(&self) -> Option<&str> {
267 match &self.kind {
268 IndexTermKind::Flow(_) => None,
269 IndexTermKind::Concealed { tertiary, .. } => tertiary.as_deref(),
270 }
271 }
272
273 #[must_use]
275 pub fn is_visible(&self) -> bool {
276 matches!(self.kind, IndexTermKind::Flow(_))
277 }
278}