1use schemars::JsonSchema;
2use serde_derive::Serialize;
3use std::path::PathBuf;
4
5use crate::attribute_types::{CanBeEmpty, ID, NameToken};
6#[allow(clippy::wildcard_imports)]
7use crate::element_categories::*;
8use crate::extra_attributes::{self, ExtraAttributes};
9
10pub trait Element {
15 fn ids(&self) -> &Vec<ID>;
17 fn ids_mut(&mut self) -> &mut Vec<ID>;
18 fn names(&self) -> &Vec<NameToken>;
23 fn names_mut(&mut self) -> &mut Vec<NameToken>;
24 fn source(&self) -> &Option<PathBuf>;
25 fn source_mut(&mut self) -> &mut Option<PathBuf>;
26 fn classes(&self) -> &Vec<String>;
27 fn classes_mut(&mut self) -> &mut Vec<String>;
28}
29
30#[derive(Clone, Debug, Default, PartialEq, Serialize, JsonSchema)]
31pub struct CommonAttributes {
32 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
33 ids: Vec<ID>,
34 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
35 names: Vec<NameToken>,
36 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
37 source: Option<PathBuf>,
38 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
39 classes: Vec<String>,
40 }
42
43macro_rules! impl_element {
48 ($name:ident) => {
49 impl Element for $name {
50 fn ids(&self) -> &Vec<ID> {
51 &self.common.ids
52 }
53 fn ids_mut(&mut self) -> &mut Vec<ID> {
54 &mut self.common.ids
55 }
56 fn names(&self) -> &Vec<NameToken> {
57 &self.common.names
58 }
59 fn names_mut(&mut self) -> &mut Vec<NameToken> {
60 &mut self.common.names
61 }
62 fn source(&self) -> &Option<PathBuf> {
63 &self.common.source
64 }
65 fn source_mut(&mut self) -> &mut Option<PathBuf> {
66 &mut self.common.source
67 }
68 fn classes(&self) -> &Vec<String> {
69 &self.common.classes
70 }
71 fn classes_mut(&mut self) -> &mut Vec<String> {
72 &mut self.common.classes
73 }
74 }
75 };
76}
77
78macro_rules! impl_children {
79 ($name:ident, $childtype:ident) => {
80 impl HasChildren<$childtype> for $name {
81 #[allow(clippy::needless_update)]
82 fn with_children(children: Vec<$childtype>) -> $name {
83 $name {
84 children,
85 ..Default::default()
86 }
87 }
88 fn children(&self) -> &Vec<$childtype> {
89 &self.children
90 }
91 fn children_mut(&mut self) -> &mut Vec<$childtype> {
92 &mut self.children
93 }
94 }
95 };
96}
97
98macro_rules! impl_extra { ($name:ident $($more:tt)*) => (
99 impl ExtraAttributes<extra_attributes::$name> for $name {
100 #[allow(clippy::needless_update)]
101 fn with_extra(extra: extra_attributes::$name) -> $name { $name { common: Default::default(), extra $($more)* } }
102 fn extra (& self) -> & extra_attributes::$name { & self.extra }
103 fn extra_mut(&mut self) -> &mut extra_attributes::$name { &mut self.extra }
104 }
105)}
106
107#[allow(dead_code)]
108trait HasExtraAndChildren<C, A> {
109 fn with_extra_and_children(extra: A, children: Vec<C>) -> Self;
110}
111
112impl<T, C, A> HasExtraAndChildren<C, A> for T
113where
114 T: HasChildren<C> + ExtraAttributes<A>,
115{
116 #[allow(clippy::needless_update)]
117 fn with_extra_and_children(extra: A, mut children: Vec<C>) -> Self {
118 let mut r = Self::with_extra(extra);
119 r.children_mut().append(&mut children);
120 r
121 }
122}
123
124macro_rules! impl_new {(
125 $(#[$attr:meta])*
126 pub struct $name:ident { $(
127 $(#[$fattr:meta])*
128 $field:ident : $typ:path
129 ),* $(,)* }
130) => (
131 $(#[$attr])*
132 #[derive(Clone, Debug, PartialEq, Serialize, JsonSchema)]
133 pub struct $name { $(
134 $(#[$fattr])* $field: $typ,
135 )* }
136 impl $name {
137 #[must_use]
138 pub fn new( $( $field: $typ, )* ) -> $name { $name { $( $field, )* } }
139 }
140)}
141
142macro_rules! impl_elem {
143 ($name:ident) => {
144 impl_new!(
145 #[derive(Default)]
146 pub struct $name {
147 #[serde(flatten)]
148 common: CommonAttributes,
149 }
150 );
151 impl_element!($name);
152 };
153 ($name:ident; +) => {
154 impl_new!(
155 #[derive(Default)]
156 pub struct $name {
157 #[serde(flatten)]
158 common: CommonAttributes,
159 #[serde(flatten)]
160 extra: extra_attributes::$name,
161 }
162 );
163 impl_element!($name);
164 impl_extra!($name, ..Default::default());
165 };
166 ($name:ident; *) => {
167 impl_new!(
169 pub struct $name {
170 #[serde(flatten)]
171 common: CommonAttributes,
172 #[serde(flatten)]
173 extra: extra_attributes::$name,
174 }
175 );
176 impl_element!($name);
177 impl_extra!($name);
178 };
179 ($name:ident, $childtype:ident) => {
180 impl_new!(
181 #[derive(Default)]
182 pub struct $name {
183 #[serde(flatten)]
184 common: CommonAttributes,
185 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
186 children: Vec<$childtype>,
187 }
188 );
189 impl_element!($name);
190 impl_children!($name, $childtype);
191 };
192 ($name:ident, $childtype:ident; +) => {
193 impl_new!(
194 #[derive(Default)]
195 pub struct $name {
196 #[serde(flatten)]
197 common: CommonAttributes,
198 #[serde(flatten)]
199 extra: extra_attributes::$name,
200 #[serde(default, skip_serializing_if = "CanBeEmpty::is_empty")]
201 children: Vec<$childtype>,
202 }
203 );
204 impl_element!($name);
205 impl_extra!($name, ..Default::default());
206 impl_children!($name, $childtype);
207 };
208}
209
210macro_rules! impl_elems { ( $( ($($args:tt)*) )* ) => (
211 $( impl_elem!($($args)*); )*
212)}
213
214#[derive(Default, Debug, Serialize, JsonSchema)]
215pub struct Document {
216 children: Vec<StructuralSubElement>,
217}
218impl_children!(Document, StructuralSubElement);
219
220impl_elems!(
221 (Section, StructuralSubElement)
223 (Topic, SubTopic)
224 (Sidebar, SubSidebar)
225
226 (Title, TextOrInlineElement)
228 (Subtitle, TextOrInlineElement)
229 (Decoration, DecorationElement)
230 (Docinfo, BibliographicElement)
231 (Transition)
232
233 (Author, TextOrInlineElement)
235 (Authors, AuthorInfo)
236 (Organization, TextOrInlineElement)
237 (Address, TextOrInlineElement; +)
238 (Contact, TextOrInlineElement)
239 (Version, TextOrInlineElement)
240 (Revision, TextOrInlineElement)
241 (Status, TextOrInlineElement)
242 (Date, TextOrInlineElement)
243 (Copyright, TextOrInlineElement)
244 (Field, SubField)
245
246 (Header, BodyElement)
248 (Footer, BodyElement)
249
250 (Paragraph, TextOrInlineElement)
252 (LiteralBlock, TextOrInlineElement; +)
253 (DoctestBlock, TextOrInlineElement; +)
254 (MathBlock, String)
255 (Rubric, TextOrInlineElement)
256 (SubstitutionDefinition, TextOrInlineElement; +)
257 (Comment, TextOrInlineElement; +)
258 (Pending)
259 (Target; +)
260 (Raw, String; +)
261 (Image; *)
262
263 (Compound, BodyElement)
265 (Container, BodyElement)
266
267 (BulletList, ListItem; +)
268 (EnumeratedList, ListItem; +)
269 (DefinitionList, DefinitionListItem)
270 (FieldList, Field)
271 (OptionList, OptionListItem)
272
273 (LineBlock, SubLineBlock)
274 (BlockQuote, SubBlockQuote)
275 (Admonition, SubTopic)
276 (Attention, BodyElement)
277 (Hint, BodyElement)
278 (Note, BodyElement)
279 (Caution, BodyElement)
280 (Danger, BodyElement)
281 (Error, BodyElement)
282 (Important, BodyElement)
283 (Tip, BodyElement)
284 (Warning, BodyElement)
285 (Footnote, SubFootnote; +)
286 (Citation, SubFootnote; +)
287 (SystemMessage, BodyElement; +)
288 (Figure, SubFigure; +)
289 (Table, SubTable; +)
290
291 (TableGroup, SubTableGroup; +)
293 (TableHead, TableRow; +)
294 (TableBody, TableRow; +)
295 (TableRow, TableEntry; +)
296 (TableEntry, BodyElement; +)
297 (TableColspec; +)
298
299 (ListItem, BodyElement)
301
302 (DefinitionListItem, SubDLItem)
303 (Term, TextOrInlineElement)
304 (Classifier, TextOrInlineElement)
305 (Definition, BodyElement)
306
307 (FieldName, TextOrInlineElement)
308 (FieldBody, BodyElement)
309
310 (OptionListItem, SubOptionListItem)
311 (OptionGroup, Option_)
312 (Description, BodyElement)
313 (Option_, SubOption)
314 (OptionString, String)
315 (OptionArgument, String; +)
316
317 (Line, TextOrInlineElement)
318 (Attribution, TextOrInlineElement)
319 (Label, TextOrInlineElement)
320
321 (Caption, TextOrInlineElement)
322 (Legend, BodyElement)
323
324 (Emphasis, TextOrInlineElement)
326 (Literal, String)
327 (Reference, TextOrInlineElement; +)
328 (Strong, TextOrInlineElement)
329 (FootnoteReference, TextOrInlineElement; +)
330 (CitationReference, TextOrInlineElement; +)
331 (SubstitutionReference, TextOrInlineElement; +)
332 (TitleReference, TextOrInlineElement)
333 (Abbreviation, TextOrInlineElement)
334 (Acronym, TextOrInlineElement)
335 (Superscript, TextOrInlineElement)
336 (Subscript, TextOrInlineElement)
337 (Inline, TextOrInlineElement)
338 (Problematic, TextOrInlineElement; +)
339 (Generated, TextOrInlineElement)
340 (Math, String)
341
342 (TargetInline, String; +)
344 (RawInline, String; +)
345 (ImageInline; *)
346
347 );
349
350impl<'a> From<&'a str> for TextOrInlineElement {
351 fn from(s: &'a str) -> Self {
352 s.to_owned().into()
353 }
354}
355
356pub trait LabelledFootnote {
357 fn get_label(&self) -> Result<&str, anyhow::Error>;
362}
363
364impl LabelledFootnote for Footnote {
365 fn get_label(&self) -> Result<&str, anyhow::Error> {
366 use anyhow::{Context, bail};
367
368 let SubFootnote::Label(e) = self
369 .children()
370 .first()
371 .context("Footnote has no children")?
372 else {
373 bail!("Non-auto footnote has no label");
374 };
375 match e
376 .children()
377 .first()
378 .context("Footnote label has no child")?
379 {
380 TextOrInlineElement::String(s) => Ok(s.as_ref()),
381 _ => bail!("Footnote label is not a string"),
382 }
383 }
384}
385
386impl LabelledFootnote for FootnoteReference {
387 fn get_label(&self) -> Result<&str, anyhow::Error> {
388 use anyhow::{Context, bail};
389
390 match self
391 .children()
392 .first()
393 .context("Footnote reference has no child")?
394 {
395 TextOrInlineElement::String(s) => Ok(s.as_ref()),
396 _ => bail!("Footnote reference is not a string"),
397 }
398 }
399}