diff options
Diffstat (limited to 'document_tree/src/elements.rs')
| -rw-r--r-- | document_tree/src/elements.rs | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/document_tree/src/elements.rs b/document_tree/src/elements.rs new file mode 100644 index 0000000..26bccf6 --- /dev/null +++ b/document_tree/src/elements.rs @@ -0,0 +1,288 @@ +use std::path::PathBuf; +use serde_derive::Serialize; + +use crate::attribute_types::{CanBeEmpty,ID,NameToken}; +use crate::extra_attributes::{self,ExtraAttributes}; +use crate::element_categories::*; + + +//-----------------\\ +//Element hierarchy\\ +//-----------------\\ + +pub trait Element { + /// A list containing one or more unique identifier keys + fn ids (& self) -> & Vec<ID>; + fn ids_mut(&mut self) -> &mut Vec<ID>; + /// a list containing the names of an element, typically originating from the element's title or content. + /// Each name in names must be unique; if there are name conflicts (two or more elements want to the same name), + /// the contents will be transferred to the dupnames attribute on the duplicate elements. + /// An element may have at most one of the names or dupnames attributes, but not both. + fn names (& self) -> & Vec<NameToken>; + fn names_mut(&mut self) -> &mut Vec<NameToken>; + fn source (& self) -> & Option<PathBuf>; + fn source_mut(&mut self) -> &mut Option<PathBuf>; + fn classes (& self) -> & Vec<String>; + fn classes_mut(&mut self) -> &mut Vec<String>; +} + +#[derive(Debug,Default,PartialEq,Serialize,Clone)] +pub struct CommonAttributes { + #[serde(skip_serializing_if = "CanBeEmpty::is_empty")] + ids: Vec<ID>, + #[serde(skip_serializing_if = "CanBeEmpty::is_empty")] + names: Vec<NameToken>, + #[serde(skip_serializing_if = "CanBeEmpty::is_empty")] + source: Option<PathBuf>, + #[serde(skip_serializing_if = "CanBeEmpty::is_empty")] + classes: Vec<String>, + //TODO: dupnames +} + +//----\\ +//impl\\ +//----\\ + +macro_rules! impl_element { ($name:ident) => ( + impl Element for $name { + fn ids (& self) -> & Vec<ID> { & self.common.ids } + fn ids_mut(&mut self) -> &mut Vec<ID> { &mut self.common.ids } + fn names (& self) -> & Vec<NameToken> { & self.common.names } + fn names_mut(&mut self) -> &mut Vec<NameToken> { &mut self.common.names } + fn source (& self) -> & Option<PathBuf> { & self.common.source } + fn source_mut(&mut self) -> &mut Option<PathBuf> { &mut self.common.source } + fn classes (& self) -> & Vec<String> { & self.common.classes } + fn classes_mut(&mut self) -> &mut Vec<String> { &mut self.common.classes } + } +)} + +macro_rules! impl_children { ($name:ident, $childtype:ident) => ( + impl HasChildren<$childtype> for $name { + #[allow(clippy::needless_update)] + fn with_children(children: Vec<$childtype>) -> $name { $name { children: children, ..Default::default() } } + fn children (& self) -> & Vec<$childtype> { & self.children } + fn children_mut(&mut self) -> &mut Vec<$childtype> { &mut self.children } + } +)} + +macro_rules! impl_extra { ($name:ident $($more:tt)*) => ( + impl ExtraAttributes<extra_attributes::$name> for $name { + #[allow(clippy::needless_update)] + fn with_extra(extra: extra_attributes::$name) -> $name { $name { common: Default::default(), extra: extra $($more)* } } + fn extra (& self) -> & extra_attributes::$name { & self.extra } + fn extra_mut(&mut self) -> &mut extra_attributes::$name { &mut self.extra } + } +)} + +trait HasExtraAndChildren<C, A> { + fn with_extra_and_children(extra: A, children: Vec<C>) -> Self; +} + +impl<T, C, A> HasExtraAndChildren<C, A> for T where T: HasChildren<C> + ExtraAttributes<A> { + #[allow(clippy::needless_update)] + fn with_extra_and_children(extra: A, mut children: Vec<C>) -> Self { + let mut r = Self::with_extra(extra); + r.children_mut().extend(children.drain(..)); + r + } +} + +macro_rules! impl_new {( + $(#[$attr:meta])* + pub struct $name:ident { $( + $(#[$fattr:meta])* + $field:ident : $typ:path + ),* $(,)* } +) => ( + $(#[$attr])* + #[derive(Debug,PartialEq,Serialize,Clone)] + pub struct $name { $( + $(#[$fattr])* $field: $typ, + )* } + impl $name { + pub fn new( $( $field: $typ, )* ) -> $name { $name { $( $field: $field, )* } } + } +)} + +macro_rules! impl_elem { + ($name:ident) => { + impl_new!(#[derive(Default)] pub struct $name { + #[serde(flatten)] common: CommonAttributes, + }); + impl_element!($name); + }; + ($name:ident; +) => { + impl_new!(#[derive(Default)] pub struct $name { + #[serde(flatten)] common: CommonAttributes, + #[serde(flatten)] extra: extra_attributes::$name, + }); + impl_element!($name); impl_extra!($name, ..Default::default()); + }; + ($name:ident; *) => { //same as above with no default + impl_new!(pub struct $name { + #[serde(flatten)] common: CommonAttributes, + #[serde(flatten)] extra: extra_attributes::$name + }); + impl_element!($name); impl_extra!($name); + }; + ($name:ident, $childtype:ident) => { + impl_new!(#[derive(Default)] pub struct $name { + #[serde(flatten)] common: CommonAttributes, + children: Vec<$childtype>, + }); + impl_element!($name); impl_children!($name, $childtype); + }; + ($name:ident, $childtype:ident; +) => { + impl_new!(#[derive(Default)] pub struct $name { + #[serde(flatten)] common: CommonAttributes, + #[serde(flatten)] extra: extra_attributes::$name, + children: Vec<$childtype>, + }); + impl_element!($name); impl_extra!($name, ..Default::default()); impl_children!($name, $childtype); + }; +} + +macro_rules! impl_elems { ( $( ($($args:tt)*) )* ) => ( + $( impl_elem!($($args)*); )* +)} + + +#[derive(Default,Debug,Serialize)] +pub struct Document { children: Vec<StructuralSubElement> } +impl_children!(Document, StructuralSubElement); + +impl_elems!( + //structual elements + (Section, StructuralSubElement) + (Topic, SubTopic) + (Sidebar, SubSidebar) + + //structural subelements + (Title, TextOrInlineElement) + (Subtitle, TextOrInlineElement) + (Decoration, DecorationElement) + (Docinfo, BibliographicElement) + (Transition) + + //bibliographic elements + (Author, TextOrInlineElement) + (Authors, AuthorInfo) + (Organization, TextOrInlineElement) + (Address, TextOrInlineElement; +) + (Contact, TextOrInlineElement) + (Version, TextOrInlineElement) + (Revision, TextOrInlineElement) + (Status, TextOrInlineElement) + (Date, TextOrInlineElement) + (Copyright, TextOrInlineElement) + (Field, SubField) + + //decoration elements + (Header, BodyElement) + (Footer, BodyElement) + + //simple body elements + (Paragraph, TextOrInlineElement) + (LiteralBlock, TextOrInlineElement; +) + (DoctestBlock, TextOrInlineElement; +) + (MathBlock, String) + (Rubric, TextOrInlineElement) + (SubstitutionDefinition, TextOrInlineElement; +) + (Comment, TextOrInlineElement; +) + (Pending) + (Target; +) + (Raw, String; +) + (Image; *) + + //compound body elements + (Compound, BodyElement) + (Container, BodyElement) + + (BulletList, ListItem; +) + (EnumeratedList, ListItem; +) + (DefinitionList, DefinitionListItem) + (FieldList, Field) + (OptionList, OptionListItem) + + (LineBlock, SubLineBlock) + (BlockQuote, SubBlockQuote) + (Admonition, SubTopic) + (Attention, BodyElement) + (Hint, BodyElement) + (Note, BodyElement) + (Caution, BodyElement) + (Danger, BodyElement) + (Error, BodyElement) + (Important, BodyElement) + (Tip, BodyElement) + (Warning, BodyElement) + (Footnote, SubFootnote; +) + (Citation, SubFootnote; +) + (SystemMessage, BodyElement; +) + (Figure, SubFigure; +) + (Table, SubTable; +) + + //table elements + (TableGroup, SubTableGroup; +) + (TableHead, TableRow; +) + (TableBody, TableRow; +) + (TableRow, TableEntry; +) + (TableEntry, BodyElement; +) + (TableColspec; +) + + //body sub elements + (ListItem, BodyElement) + + (DefinitionListItem, SubDLItem) + (Term, TextOrInlineElement) + (Classifier, TextOrInlineElement) + (Definition, BodyElement) + + (FieldName, TextOrInlineElement) + (FieldBody, BodyElement) + + (OptionListItem, SubOptionListItem) + (OptionGroup, Option_) + (Description, BodyElement) + (Option_, SubOption) + (OptionString, String) + (OptionArgument, String; +) + + (Line, TextOrInlineElement) + (Attribution, TextOrInlineElement) + (Label, TextOrInlineElement) + + (Caption, TextOrInlineElement) + (Legend, BodyElement) + + //inline elements + (Emphasis, TextOrInlineElement) + (Literal, TextOrInlineElement) + (Reference, TextOrInlineElement; +) + (Strong, TextOrInlineElement) + (FootnoteReference, TextOrInlineElement; +) + (CitationReference, TextOrInlineElement; +) + (SubstitutionReference, TextOrInlineElement; +) + (TitleReference, TextOrInlineElement) + (Abbreviation, TextOrInlineElement) + (Acronym, TextOrInlineElement) + (Superscript, TextOrInlineElement) + (Subscript, TextOrInlineElement) + (Inline, TextOrInlineElement) + (Problematic, TextOrInlineElement; +) + (Generated, TextOrInlineElement) + (Math, String) + + //also have non-inline versions. Inline image is no figure child, inline target has content + (TargetInline, String; +) + (RawInline, String; +) + (ImageInline; *) + + //text element = String +); + +impl<'a> From<&'a str> for TextOrInlineElement { + fn from(s: &'a str) -> Self { + s.to_owned().into() + } +} |
