use serde_derive::Serialize; use crate::target; use super::attribute_types::{CanBeEmpty,FixedSpace,ID,NameToken,AlignHV,AlignH,AlignV,TableAlignH,TableBorder,TableGroupCols,Measure,EnumeratedListType}; pub trait ExtraAttributes { fn with_extra(extra: A) -> Self; fn extra (& self) -> & A; fn extra_mut(&mut self) -> &mut A; } macro_rules! impl_extra { ( $name:ident { $( $(#[$pattr:meta])* $param:ident : $type:ty ),* $(,)* } ) => ( impl_extra!( #[derive(Default,Debug,PartialEq,Serialize,Clone)] $name { $( $(#[$pattr])* $param : $type, )* } ); ); ( $(#[$attr:meta])+ $name:ident { $( $(#[$pattr:meta])* $param:ident : $type:ty ),* $(,)* } ) => ( $(#[$attr])+ pub struct $name { $( $(#[$pattr])* #[serde(skip_serializing_if = "CanBeEmpty::is_empty")] pub $param : $type, )* } ); } impl_extra!(Address { space: FixedSpace }); impl_extra!(LiteralBlock { space: FixedSpace }); impl_extra!(DoctestBlock { space: FixedSpace }); impl_extra!(SubstitutionDefinition { ltrim: bool, rtrim: bool }); impl_extra!(Comment { space: FixedSpace }); impl_extra!(Target { /// External reference to a URI/URL refuri: Option, /// References to ids attributes in other elements refid: Option, /// Internal reference to the names attribute of another element. May resolve to either an internal or external reference. refname: Vec, anonymous: bool, }); impl_extra!(Raw { space: FixedSpace, format: Vec }); impl_extra!(#[derive(Debug,PartialEq,Serialize,Clone)] Image { uri: target::Target, align: Option, alt: Option, height: Option, width: Option, scale: Option, target: Option, // Not part of the DTD but a valid argument }); //bools usually are XML yesorno. “auto” however either exists and is set to something random like “1” or doesn’t exist //does auto actually mean the numbering prefix? impl_extra!(BulletList { bullet: Option }); impl_extra!(EnumeratedList { enumtype: Option, prefix: Option, suffix: Option }); impl_extra!(Footnote { backrefs: Vec, auto: bool }); impl_extra!(Citation { backrefs: Vec }); impl_extra!(SystemMessage { backrefs: Vec, level: Option, line: Option, type_: Option }); impl_extra!(Figure { align: Option, width: Option }); impl_extra!(Table { frame: Option, colsep: Option, rowsep: Option, pgwide: Option }); impl_extra!(TableGroup { cols: TableGroupCols, colsep: Option, rowsep: Option, align: Option }); impl_extra!(TableHead { valign: Option }); impl_extra!(TableBody { valign: Option }); impl_extra!(TableRow { rowsep: Option, valign: Option }); impl_extra!(TableEntry { colname: Option, namest: Option, nameend: Option, morerows: Option, colsep: Option, rowsep: Option, align: Option, r#char: Option, charoff: Option, valign: Option, morecols: Option }); impl_extra!(TableColspec { colnum: Option, colname: Option, colwidth: Option, colsep: Option, rowsep: Option, align: Option, r#char: Option, charoff: Option, stub: Option }); impl_extra!(OptionArgument { delimiter: Option }); impl_extra!(Reference { name: Option, //TODO: is CDATA in the DTD, so maybe no nametoken? /// External reference to a URI/URL refuri: Option, /// References to ids attributes in other elements refid: Option, /// Internal reference to the names attribute of another element refname: Vec, }); impl_extra!(FootnoteReference { refid: Option, refname: Vec, auto: bool }); impl_extra!(CitationReference { refid: Option, refname: Vec }); impl_extra!(SubstitutionReference { refname: Vec }); impl_extra!(Problematic { refid: Option }); //also have non-inline versions. Inline image is no figure child, inline target has content impl_extra!(TargetInline { /// External reference to a URI/URL refuri: Option, /// References to ids attributes in other elements refid: Option, /// Internal reference to the names attribute of another element. May resolve to either an internal or external reference. refname: Vec, anonymous: bool, }); impl_extra!(RawInline { space: FixedSpace, format: Vec }); pub type ImageInline = Image; impl Image { pub fn new(uri: target::Target) -> Image { Image { uri, align: None, alt: None, height: None, width: None, scale: None, target: None, } } }