// This file is automatically generated!
//
// To update it:
// 1. Edit the `generate.toml` file inside of this directory
// 2. Run `cargo run --bin=codegen` from the repository root

/// A tag for group nodes.
#[derive(Clone, Debug, PartialEq)]
pub enum TagKind {
    /// A part of a document that may contain multiple articles or sections.
    Part(Tag<kind::Part>),
    /// An article with largely self-contained content.
    Article(Tag<kind::Article>),
    /// Section of a larger document.
    Section(Tag<kind::Section>),
    /// A generic block-level grouping element.
    Div(Tag<kind::Div>),
    /// A paragraph-level quote.
    BlockQuote(Tag<kind::BlockQuote>),
    /// An image or figure caption.
    ///
    /// **Best Practice**: In the tag tree, this should appear
    /// as a sibling after the image (or other) content it describes.
    Caption(Tag<kind::Caption>),
    /// Table of contents.
    ///
    /// **Best Practice**: Should consist of TOCIs or other nested TOCs.
    TOC(Tag<kind::TOC>),
    /// Item in the table of contents.
    ///
    /// **Best Practice**: Should only appear within a TOC. Should only consist of
    /// labels, references, paragraphs and TOCs.
    TOCI(Tag<kind::TOCI>),
    /// Index of the key terms in the document.
    ///
    /// **Best Practice**: Should contain a sequence of text accompanied by
    /// reference elements pointing to their occurrence in the text.
    Index(Tag<kind::Index>),
    /// A paragraph.
    P(Tag<kind::P>),
    /// Heading level `n`, including an optional title of the heading.
    ///
    /// The title is required for some export modes, like for example PDF/UA.
    Hn(Tag<kind::Hn>),
    /// A list.
    ///
    /// **Best practice**: Should consist of an optional caption followed by
    /// list items.
    /// List numbering is only required for PDF/UA, but we just enforce it for always.
    L(Tag<kind::L>),
    /// A list item.
    ///
    /// **Best practice**: Should consist of one or more list labels and/or list bodies.
    LI(Tag<kind::LI>),
    /// Label for a list item.
    Lbl(Tag<kind::Lbl>),
    /// Description of the list item.
    LBody(Tag<kind::LBody>),
    /// A table, with an optional summary describing the purpose and structure.
    ///
    /// **Best practice**: Should consist of an optional table header row,
    /// one or more table body elements and an optional table footer. Can have
    /// caption as the first or last child.
    Table(Tag<kind::Table>),
    /// A table row.
    ///
    /// **Best practice**: May contain table headers cells and table data cells.
    TR(Tag<kind::TR>),
    /// A table header cell.
    TH(Tag<kind::TH>),
    /// A table data cell.
    TD(Tag<kind::TD>),
    /// A table header row group.
    THead(Tag<kind::THead>),
    /// A table data row group.
    TBody(Tag<kind::TBody>),
    /// A table footer row group.
    TFoot(Tag<kind::TFoot>),
    /// An inline-level element that does not have a specific meaning.
    Span(Tag<kind::Span>),
    /// An inline quotation.
    InlineQuote(Tag<kind::InlineQuote>),
    /// A foot- or endnote, potentially referred to from within the text.
    ///
    /// **Best practice**: It may have a label as a child.
    Note(Tag<kind::Note>),
    /// A reference to elsewhere in the document.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to a destination in the document, and the second child should consist of
    /// the children that should be associated with that reference.
    Reference(Tag<kind::Reference>),
    /// A reference to the external source of some cited document.
    ///
    /// **Best practice**: It may have a label as a child.
    BibEntry(Tag<kind::BibEntry>),
    /// Computer code.
    Code(Tag<kind::Code>),
    /// A link.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to an URL, and the second child should consist of the children that should
    /// be associated with that link.
    Link(Tag<kind::Link>),
    /// An association between an annotation and the content it belongs to. PDF
    ///
    /// **Best practice**: Should be used for all annotations, except for link annotations and
    /// widget annotations. The first child should be the identifier of a non-link annotation,
    /// and all other subsequent children should be content identifiers associated with that
    /// annotation.
    Annot(Tag<kind::Annot>),
    /// Item of graphical content.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    Figure(Tag<kind::Figure>),
    /// A mathematical formula.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    Formula(Tag<kind::Formula>),
    /// Non-structural element. A grouping element having no inherent structural significance;
    /// it serves solely for grouping purposes.
    NonStruct(Tag<kind::NonStruct>),
    /// A date or time.
    Datetime(Tag<kind::Datetime>),
    /// A list of terms.
    Terms(Tag<kind::Terms>),
    /// A title.
    Title(Tag<kind::Title>),
    /// Encloses content with strong importance, most commonly **bold** text.
    Strong(Tag<kind::Strong>),
    /// Encloses content that is emphasized, most commonly *italic* text.
    Em(Tag<kind::Em>),
}

impl TagKind {
    /// A type erased tag, which allows reading all attributes.
    pub fn as_any(&self) -> &AnyTag {
        match self {
            Self::Part(tag) => tag.as_any(),
            Self::Article(tag) => tag.as_any(),
            Self::Section(tag) => tag.as_any(),
            Self::Div(tag) => tag.as_any(),
            Self::BlockQuote(tag) => tag.as_any(),
            Self::Caption(tag) => tag.as_any(),
            Self::TOC(tag) => tag.as_any(),
            Self::TOCI(tag) => tag.as_any(),
            Self::Index(tag) => tag.as_any(),
            Self::P(tag) => tag.as_any(),
            Self::Hn(tag) => tag.as_any(),
            Self::L(tag) => tag.as_any(),
            Self::LI(tag) => tag.as_any(),
            Self::Lbl(tag) => tag.as_any(),
            Self::LBody(tag) => tag.as_any(),
            Self::Table(tag) => tag.as_any(),
            Self::TR(tag) => tag.as_any(),
            Self::TH(tag) => tag.as_any(),
            Self::TD(tag) => tag.as_any(),
            Self::THead(tag) => tag.as_any(),
            Self::TBody(tag) => tag.as_any(),
            Self::TFoot(tag) => tag.as_any(),
            Self::Span(tag) => tag.as_any(),
            Self::InlineQuote(tag) => tag.as_any(),
            Self::Note(tag) => tag.as_any(),
            Self::Reference(tag) => tag.as_any(),
            Self::BibEntry(tag) => tag.as_any(),
            Self::Code(tag) => tag.as_any(),
            Self::Link(tag) => tag.as_any(),
            Self::Annot(tag) => tag.as_any(),
            Self::Figure(tag) => tag.as_any(),
            Self::Formula(tag) => tag.as_any(),
            Self::NonStruct(tag) => tag.as_any(),
            Self::Datetime(tag) => tag.as_any(),
            Self::Terms(tag) => tag.as_any(),
            Self::Title(tag) => tag.as_any(),
            Self::Strong(tag) => tag.as_any(),
            Self::Em(tag) => tag.as_any(),
        }
    }

    /// A type erased tag, which allows reading all attributes and additionally
    /// writing all global attributes.
    pub fn as_any_mut(&mut self) -> &mut AnyTag {
        match self {
            Self::Part(tag) => tag.as_any_mut(),
            Self::Article(tag) => tag.as_any_mut(),
            Self::Section(tag) => tag.as_any_mut(),
            Self::Div(tag) => tag.as_any_mut(),
            Self::BlockQuote(tag) => tag.as_any_mut(),
            Self::Caption(tag) => tag.as_any_mut(),
            Self::TOC(tag) => tag.as_any_mut(),
            Self::TOCI(tag) => tag.as_any_mut(),
            Self::Index(tag) => tag.as_any_mut(),
            Self::P(tag) => tag.as_any_mut(),
            Self::Hn(tag) => tag.as_any_mut(),
            Self::L(tag) => tag.as_any_mut(),
            Self::LI(tag) => tag.as_any_mut(),
            Self::Lbl(tag) => tag.as_any_mut(),
            Self::LBody(tag) => tag.as_any_mut(),
            Self::Table(tag) => tag.as_any_mut(),
            Self::TR(tag) => tag.as_any_mut(),
            Self::TH(tag) => tag.as_any_mut(),
            Self::TD(tag) => tag.as_any_mut(),
            Self::THead(tag) => tag.as_any_mut(),
            Self::TBody(tag) => tag.as_any_mut(),
            Self::TFoot(tag) => tag.as_any_mut(),
            Self::Span(tag) => tag.as_any_mut(),
            Self::InlineQuote(tag) => tag.as_any_mut(),
            Self::Note(tag) => tag.as_any_mut(),
            Self::Reference(tag) => tag.as_any_mut(),
            Self::BibEntry(tag) => tag.as_any_mut(),
            Self::Code(tag) => tag.as_any_mut(),
            Self::Link(tag) => tag.as_any_mut(),
            Self::Annot(tag) => tag.as_any_mut(),
            Self::Figure(tag) => tag.as_any_mut(),
            Self::Formula(tag) => tag.as_any_mut(),
            Self::NonStruct(tag) => tag.as_any_mut(),
            Self::Datetime(tag) => tag.as_any_mut(),
            Self::Terms(tag) => tag.as_any_mut(),
            Self::Title(tag) => tag.as_any_mut(),
            Self::Strong(tag) => tag.as_any_mut(),
            Self::Em(tag) => tag.as_any_mut(),
        }
    }

    /// The tag id.
    pub fn id(&self) -> Option<&TagId> {
        self.as_any().id()
    }

    /// Set the tag id.
    pub fn set_id(&mut self, id: Option<TagId>) {
        self.as_any_mut().set_id(id);
    }

    /// Set the tag id.
    pub fn with_id(mut self, id: Option<TagId>) -> Self {
        self.set_id(id);
        self
    }

    /// The language of this tag.
    pub fn lang(&self) -> Option<&str> {
        self.as_any().lang()
    }

    /// Set the language of this tag.
    pub fn set_lang(&mut self, lang: Option<String>) {
        self.as_any_mut().set_lang(lang);
    }

    /// Set the language of this tag.
    pub fn with_lang(mut self, lang: Option<String>) -> Self {
        self.set_lang(lang);
        self
    }

    /// The optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn alt_text(&self) -> Option<&str> {
        self.as_any().alt_text()
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn set_alt_text(&mut self, alt_text: Option<String>) {
        self.as_any_mut().set_alt_text(alt_text);
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn with_alt_text(mut self, alt_text: Option<String>) -> Self {
        self.set_alt_text(alt_text);
        self
    }

    /// The expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn expanded(&self) -> Option<&str> {
        self.as_any().expanded()
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn set_expanded(&mut self, expanded: Option<String>) {
        self.as_any_mut().set_expanded(expanded);
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn with_expanded(mut self, expanded: Option<String>) -> Self {
        self.set_expanded(expanded);
        self
    }

    /// The actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn actual_text(&self) -> Option<&str> {
        self.as_any().actual_text()
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn set_actual_text(&mut self, actual_text: Option<String>) {
        self.as_any_mut().set_actual_text(actual_text);
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn with_actual_text(mut self, actual_text: Option<String>) -> Self {
        self.set_actual_text(actual_text);
        self
    }

    /// The title, characterizing a specific tag such as `"Chapter 1"`.
    pub fn title(&self) -> Option<&str> {
        self.as_any().title()
    }

    /// The heading level
    pub fn level(&self) -> Option<NonZeroU16> {
        self.as_any().level()
    }

    /// The list numbering.
    pub fn numbering(&self) -> Option<ListNumbering> {
        self.as_any().numbering()
    }

    /// The table summary.
    pub fn summary(&self) -> Option<&str> {
        self.as_any().summary()
    }

    /// The table header scope.
    pub fn scope(&self) -> Option<TableHeaderScope> {
        self.as_any().scope()
    }

    /// The list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn headers(&self) -> Option<&[TagId]> {
        self.as_any().headers()
    }

    /// The row span of this table cell.
    pub fn row_span(&self) -> Option<NonZeroU32> {
        self.as_any().row_span()
    }

    /// The column span of this table cell.
    pub fn col_span(&self) -> Option<NonZeroU32> {
        self.as_any().col_span()
    }

    /// The placement.
    pub fn placement(&self) -> Option<Placement> {
        self.as_any().placement()
    }

    /// Set the placement.
    pub fn set_placement(&mut self, placement: Option<Placement>) {
        self.as_any_mut().set_placement(placement);
    }

    /// Set the placement.
    pub fn with_placement(mut self, placement: Option<Placement>) -> Self {
        self.set_placement(placement);
        self
    }

    /// The writing mode.
    pub fn writing_mode(&self) -> Option<WritingMode> {
        self.as_any().writing_mode()
    }

    /// Set the writing mode.
    pub fn set_writing_mode(&mut self, writing_mode: Option<WritingMode>) {
        self.as_any_mut().set_writing_mode(writing_mode);
    }

    /// Set the writing mode.
    pub fn with_writing_mode(mut self, writing_mode: Option<WritingMode>) -> Self {
        self.set_writing_mode(writing_mode);
        self
    }

    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn bbox(&self) -> Option<BBox> {
        self.as_any().bbox()
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.as_any().width()
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.as_any().height()
    }

    /// The background color.
    pub fn background_color(&self) -> Option<NaiveRgbColor> {
        self.as_any().background_color()
    }

    /// Set the background color.
    pub fn set_background_color(&mut self, background_color: Option<NaiveRgbColor>) {
        self.as_any_mut().set_background_color(background_color);
    }

    /// Set the background color.
    pub fn with_background_color(mut self, background_color: Option<NaiveRgbColor>) -> Self {
        self.set_background_color(background_color);
        self
    }

    /// The border color.
    pub fn border_color(&self) -> Option<Sides<NaiveRgbColor>> {
        self.as_any().border_color()
    }

    /// Set the border color.
    pub fn set_border_color(&mut self, border_color: Option<Sides<NaiveRgbColor>>) {
        self.as_any_mut().set_border_color(border_color);
    }

    /// Set the border color.
    pub fn with_border_color(mut self, border_color: Option<Sides<NaiveRgbColor>>) -> Self {
        self.set_border_color(border_color);
        self
    }

    /// The way the border is drawn.
    pub fn border_style(&self) -> Option<Sides<BorderStyle>> {
        self.as_any().border_style()
    }

    /// Set the way the border is drawn.
    pub fn set_border_style(&mut self, border_style: Option<Sides<BorderStyle>>) {
        self.as_any_mut().set_border_style(border_style);
    }

    /// Set the way the border is drawn.
    pub fn with_border_style(mut self, border_style: Option<Sides<BorderStyle>>) -> Self {
        self.set_border_style(border_style);
        self
    }

    /// The border width.
    pub fn border_thickness(&self) -> Option<Sides<f32>> {
        self.as_any().border_thickness()
    }

    /// Set the border width.
    pub fn set_border_thickness(&mut self, border_thickness: Option<Sides<f32>>) {
        self.as_any_mut().set_border_thickness(border_thickness);
    }

    /// Set the border width.
    pub fn with_border_thickness(mut self, border_thickness: Option<Sides<f32>>) -> Self {
        self.set_border_thickness(border_thickness);
        self
    }

    /// The padding inside of an element.
    pub fn padding(&self) -> Option<Sides<f32>> {
        self.as_any().padding()
    }

    /// Set the padding inside of an element.
    pub fn set_padding(&mut self, padding: Option<Sides<f32>>) {
        self.as_any_mut().set_padding(padding);
    }

    /// Set the padding inside of an element.
    pub fn with_padding(mut self, padding: Option<Sides<f32>>) -> Self {
        self.set_padding(padding);
        self
    }

    /// The color of text, borders, and text decorations.
    pub fn color(&self) -> Option<NaiveRgbColor> {
        self.as_any().color()
    }

    /// Set the color of text, borders, and text decorations.
    pub fn set_color(&mut self, color: Option<NaiveRgbColor>) {
        self.as_any_mut().set_color(color);
    }

    /// Set the color of text, borders, and text decorations.
    pub fn with_color(mut self, color: Option<NaiveRgbColor>) -> Self {
        self.set_color(color);
        self
    }

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.as_any().space_before()
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.as_any().space_after()
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.as_any().start_indent()
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.as_any().end_indent()
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.as_any().text_indent()
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.as_any().text_align()
    }

    /// The alignment of block-level elements inside of this block-level element.
    pub fn block_align(&self) -> Option<BlockAlign> {
        self.as_any().block_align()
    }

    /// The alignment of inline-level elements inside of this block-level element.
    pub fn inline_align(&self) -> Option<InlineAlign> {
        self.as_any().inline_align()
    }

    /// The border style of table cells, overriding `BorderStyle`.
    pub fn table_border_style(&self) -> Option<Sides<BorderStyle>> {
        self.as_any().table_border_style()
    }

    /// The padding inside of table cells, overriding `Padding`.
    pub fn table_padding(&self) -> Option<Sides<f32>> {
        self.as_any().table_padding()
    }

    /// The distance by which the baseline shall be shifted from the default position.
    pub fn baseline_shift(&self) -> Option<f32> {
        self.as_any().baseline_shift()
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn set_baseline_shift(&mut self, baseline_shift: Option<f32>) {
        self.as_any_mut().set_baseline_shift(baseline_shift);
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn with_baseline_shift(mut self, baseline_shift: Option<f32>) -> Self {
        self.set_baseline_shift(baseline_shift);
        self
    }

    /// The height of each line in an element on the block axis.
    pub fn line_height(&self) -> Option<LineHeight> {
        self.as_any().line_height()
    }

    /// Set the height of each line in an element on the block axis.
    pub fn set_line_height(&mut self, line_height: Option<LineHeight>) {
        self.as_any_mut().set_line_height(line_height);
    }

    /// Set the height of each line in an element on the block axis.
    pub fn with_line_height(mut self, line_height: Option<LineHeight>) -> Self {
        self.set_line_height(line_height);
        self
    }

    /// The color of the text decoration, overriding the fill color.
    pub fn text_decoration_color(&self) -> Option<NaiveRgbColor> {
        self.as_any().text_decoration_color()
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn set_text_decoration_color(&mut self, text_decoration_color: Option<NaiveRgbColor>) {
        self.as_any_mut().set_text_decoration_color(text_decoration_color);
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn with_text_decoration_color(mut self, text_decoration_color: Option<NaiveRgbColor>) -> Self {
        self.set_text_decoration_color(text_decoration_color);
        self
    }

    /// The width of the text decoration line.
    pub fn text_decoration_thickness(&self) -> Option<f32> {
        self.as_any().text_decoration_thickness()
    }

    /// Set the width of the text decoration line.
    pub fn set_text_decoration_thickness(&mut self, text_decoration_thickness: Option<f32>) {
        self.as_any_mut().set_text_decoration_thickness(text_decoration_thickness);
    }

    /// Set the width of the text decoration line.
    pub fn with_text_decoration_thickness(mut self, text_decoration_thickness: Option<f32>) -> Self {
        self.set_text_decoration_thickness(text_decoration_thickness);
        self
    }

    /// The kind of text decoration.
    pub fn text_decoration_type(&self) -> Option<TextDecorationType> {
        self.as_any().text_decoration_type()
    }

    /// Set the kind of text decoration.
    pub fn set_text_decoration_type(&mut self, text_decoration_type: Option<TextDecorationType>) {
        self.as_any_mut().set_text_decoration_type(text_decoration_type);
    }

    /// Set the kind of text decoration.
    pub fn with_text_decoration_type(mut self, text_decoration_type: Option<TextDecorationType>) -> Self {
        self.set_text_decoration_type(text_decoration_type);
        self
    }

    /// How the glyphs are rotated in a vertical writing mode.
    pub fn glyph_orientation_vertical(&self) -> Option<GlyphOrientationVertical> {
        self.as_any().glyph_orientation_vertical()
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn set_glyph_orientation_vertical(&mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) {
        self.as_any_mut().set_glyph_orientation_vertical(glyph_orientation_vertical);
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn with_glyph_orientation_vertical(mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) -> Self {
        self.set_glyph_orientation_vertical(glyph_orientation_vertical);
        self
    }

    /// The number of columns in the grouping element.
    pub fn column_count(&self) -> Option<NonZeroU32> {
        self.as_any().column_count()
    }

    /// The width of the gaps between columns in the grouping element.
    pub fn column_gap(&self) -> Option<&ColumnDimensions> {
        self.as_any().column_gap()
    }

    /// The width of the columns in the grouping element.
    pub fn column_widths(&self) -> Option<&ColumnDimensions> {
        self.as_any().column_widths()
    }
}

// Read accessors for all attributes and write accessors for global ones.
impl AnyTag {
    #[inline(always)]
    fn get_struct(&self, ordinal: usize) -> Option<&StructAttr> {
        self.attrs.get(ordinal).map(Attr::unwrap_struct)
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_struct(&mut self, attr: StructAttr) {
        self.attrs.set(Attr::Struct(attr));
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_or_remove_struct(&mut self, ordinal: usize, attr: Option<StructAttr>) {
        self.attrs.set_or_remove(ordinal, attr.map(Attr::Struct));
    }

    #[inline(always)]
    fn get_list(&self, ordinal: usize) -> Option<&ListAttr> {
        self.attrs.get(ordinal).map(Attr::unwrap_list)
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_list(&mut self, attr: ListAttr) {
        self.attrs.set(Attr::List(attr));
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_or_remove_list(&mut self, ordinal: usize, attr: Option<ListAttr>) {
        self.attrs.set_or_remove(ordinal, attr.map(Attr::List));
    }

    #[inline(always)]
    fn get_table(&self, ordinal: usize) -> Option<&TableAttr> {
        self.attrs.get(ordinal).map(Attr::unwrap_table)
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_table(&mut self, attr: TableAttr) {
        self.attrs.set(Attr::Table(attr));
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_or_remove_table(&mut self, ordinal: usize, attr: Option<TableAttr>) {
        self.attrs.set_or_remove(ordinal, attr.map(Attr::Table));
    }

    #[inline(always)]
    fn get_layout(&self, ordinal: usize) -> Option<&LayoutAttr> {
        self.attrs.get(ordinal).map(Attr::unwrap_layout)
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_layout(&mut self, attr: LayoutAttr) {
        self.attrs.set(Attr::Layout(attr));
    }

    #[allow(unused)]
    #[inline(always)]
    fn set_or_remove_layout(&mut self, ordinal: usize, attr: Option<LayoutAttr>) {
        self.attrs.set_or_remove(ordinal, attr.map(Attr::Layout));
    }


    /// The tag id.
    pub fn id(&self) -> Option<&TagId> {
        self.get_struct(StructAttr::ID).map(StructAttr::unwrap_id)
    }

    /// Set the tag id.
    pub fn set_id(&mut self, id: Option<TagId>) {
        self.set_or_remove_struct(StructAttr::ID, id.map(StructAttr::Id));
    }

    /// Set the tag id.
    pub fn with_id(mut self, id: Option<TagId>) -> Self {
        self.set_id(id);
        self
    }

    /// The language of this tag.
    pub fn lang(&self) -> Option<&str> {
        self.get_struct(StructAttr::LANG).map(StructAttr::unwrap_lang)
    }

    /// Set the language of this tag.
    pub fn set_lang(&mut self, lang: Option<String>) {
        self.set_or_remove_struct(StructAttr::LANG, lang.map(StructAttr::Lang));
    }

    /// Set the language of this tag.
    pub fn with_lang(mut self, lang: Option<String>) -> Self {
        self.set_lang(lang);
        self
    }

    /// The optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn alt_text(&self) -> Option<&str> {
        self.get_struct(StructAttr::ALT_TEXT).map(StructAttr::unwrap_alt_text)
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn set_alt_text(&mut self, alt_text: Option<String>) {
        self.set_or_remove_struct(StructAttr::ALT_TEXT, alt_text.map(StructAttr::AltText));
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn with_alt_text(mut self, alt_text: Option<String>) -> Self {
        self.set_alt_text(alt_text);
        self
    }

    /// The expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn expanded(&self) -> Option<&str> {
        self.get_struct(StructAttr::EXPANDED).map(StructAttr::unwrap_expanded)
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn set_expanded(&mut self, expanded: Option<String>) {
        self.set_or_remove_struct(StructAttr::EXPANDED, expanded.map(StructAttr::Expanded));
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn with_expanded(mut self, expanded: Option<String>) -> Self {
        self.set_expanded(expanded);
        self
    }

    /// The actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn actual_text(&self) -> Option<&str> {
        self.get_struct(StructAttr::ACTUAL_TEXT).map(StructAttr::unwrap_actual_text)
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn set_actual_text(&mut self, actual_text: Option<String>) {
        self.set_or_remove_struct(StructAttr::ACTUAL_TEXT, actual_text.map(StructAttr::ActualText));
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn with_actual_text(mut self, actual_text: Option<String>) -> Self {
        self.set_actual_text(actual_text);
        self
    }

    /// The title, characterizing a specific tag such as `"Chapter 1"`.
    pub fn title(&self) -> Option<&str> {
        self.get_struct(StructAttr::TITLE).map(StructAttr::unwrap_title)
    }

    /// The heading level
    pub fn level(&self) -> Option<NonZeroU16> {
        self.get_struct(StructAttr::HEADING_LEVEL).map(StructAttr::unwrap_level)
    }

    /// The list numbering.
    pub fn numbering(&self) -> Option<ListNumbering> {
        self.get_list(ListAttr::NUMBERING).map(ListAttr::unwrap_numbering)
    }

    /// The table summary.
    pub fn summary(&self) -> Option<&str> {
        self.get_table(TableAttr::SUMMARY).map(TableAttr::unwrap_summary)
    }

    /// The table header scope.
    pub fn scope(&self) -> Option<TableHeaderScope> {
        self.get_table(TableAttr::HEADER_SCOPE).map(TableAttr::unwrap_scope)
    }

    /// The list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn headers(&self) -> Option<&[TagId]> {
        self.get_table(TableAttr::CELL_HEADERS).map(TableAttr::unwrap_headers)
    }

    /// The row span of this table cell.
    pub fn row_span(&self) -> Option<NonZeroU32> {
        self.get_table(TableAttr::ROW_SPAN).map(TableAttr::unwrap_row_span)
    }

    /// The column span of this table cell.
    pub fn col_span(&self) -> Option<NonZeroU32> {
        self.get_table(TableAttr::COL_SPAN).map(TableAttr::unwrap_col_span)
    }

    /// The placement.
    pub fn placement(&self) -> Option<Placement> {
        self.get_layout(LayoutAttr::PLACEMENT).map(LayoutAttr::unwrap_placement)
    }

    /// Set the placement.
    pub fn set_placement(&mut self, placement: Option<Placement>) {
        self.set_or_remove_layout(LayoutAttr::PLACEMENT, placement.map(LayoutAttr::Placement));
    }

    /// Set the placement.
    pub fn with_placement(mut self, placement: Option<Placement>) -> Self {
        self.set_placement(placement);
        self
    }

    /// The writing mode.
    pub fn writing_mode(&self) -> Option<WritingMode> {
        self.get_layout(LayoutAttr::WRITING_MODE).map(LayoutAttr::unwrap_writing_mode)
    }

    /// Set the writing mode.
    pub fn set_writing_mode(&mut self, writing_mode: Option<WritingMode>) {
        self.set_or_remove_layout(LayoutAttr::WRITING_MODE, writing_mode.map(LayoutAttr::WritingMode));
    }

    /// Set the writing mode.
    pub fn with_writing_mode(mut self, writing_mode: Option<WritingMode>) -> Self {
        self.set_writing_mode(writing_mode);
        self
    }

    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn bbox(&self) -> Option<BBox> {
        self.get_layout(LayoutAttr::B_BOX).map(LayoutAttr::unwrap_bbox)
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// The background color.
    pub fn background_color(&self) -> Option<NaiveRgbColor> {
        self.get_layout(LayoutAttr::BACKGROUND_COLOR).map(LayoutAttr::unwrap_background_color)
    }

    /// Set the background color.
    pub fn set_background_color(&mut self, background_color: Option<NaiveRgbColor>) {
        self.set_or_remove_layout(LayoutAttr::BACKGROUND_COLOR, background_color.map(LayoutAttr::BackgroundColor));
    }

    /// Set the background color.
    pub fn with_background_color(mut self, background_color: Option<NaiveRgbColor>) -> Self {
        self.set_background_color(background_color);
        self
    }

    /// The border color.
    pub fn border_color(&self) -> Option<Sides<NaiveRgbColor>> {
        self.get_layout(LayoutAttr::BORDER_COLOR).map(LayoutAttr::unwrap_border_color)
    }

    /// Set the border color.
    pub fn set_border_color(&mut self, border_color: Option<Sides<NaiveRgbColor>>) {
        self.set_or_remove_layout(LayoutAttr::BORDER_COLOR, border_color.map(LayoutAttr::BorderColor));
    }

    /// Set the border color.
    pub fn with_border_color(mut self, border_color: Option<Sides<NaiveRgbColor>>) -> Self {
        self.set_border_color(border_color);
        self
    }

    /// The way the border is drawn.
    pub fn border_style(&self) -> Option<Sides<BorderStyle>> {
        self.get_layout(LayoutAttr::BORDER_STYLE).map(LayoutAttr::unwrap_border_style)
    }

    /// Set the way the border is drawn.
    pub fn set_border_style(&mut self, border_style: Option<Sides<BorderStyle>>) {
        self.set_or_remove_layout(LayoutAttr::BORDER_STYLE, border_style.map(LayoutAttr::BorderStyle));
    }

    /// Set the way the border is drawn.
    pub fn with_border_style(mut self, border_style: Option<Sides<BorderStyle>>) -> Self {
        self.set_border_style(border_style);
        self
    }

    /// The border width.
    pub fn border_thickness(&self) -> Option<Sides<f32>> {
        self.get_layout(LayoutAttr::BORDER_THICKNESS).map(LayoutAttr::unwrap_border_thickness)
    }

    /// Set the border width.
    pub fn set_border_thickness(&mut self, border_thickness: Option<Sides<f32>>) {
        self.set_or_remove_layout(LayoutAttr::BORDER_THICKNESS, border_thickness.map(LayoutAttr::BorderThickness));
    }

    /// Set the border width.
    pub fn with_border_thickness(mut self, border_thickness: Option<Sides<f32>>) -> Self {
        self.set_border_thickness(border_thickness);
        self
    }

    /// The padding inside of an element.
    pub fn padding(&self) -> Option<Sides<f32>> {
        self.get_layout(LayoutAttr::PADDING).map(LayoutAttr::unwrap_padding)
    }

    /// Set the padding inside of an element.
    pub fn set_padding(&mut self, padding: Option<Sides<f32>>) {
        self.set_or_remove_layout(LayoutAttr::PADDING, padding.map(LayoutAttr::Padding));
    }

    /// Set the padding inside of an element.
    pub fn with_padding(mut self, padding: Option<Sides<f32>>) -> Self {
        self.set_padding(padding);
        self
    }

    /// The color of text, borders, and text decorations.
    pub fn color(&self) -> Option<NaiveRgbColor> {
        self.get_layout(LayoutAttr::COLOR).map(LayoutAttr::unwrap_color)
    }

    /// Set the color of text, borders, and text decorations.
    pub fn set_color(&mut self, color: Option<NaiveRgbColor>) {
        self.set_or_remove_layout(LayoutAttr::COLOR, color.map(LayoutAttr::Color));
    }

    /// Set the color of text, borders, and text decorations.
    pub fn with_color(mut self, color: Option<NaiveRgbColor>) -> Self {
        self.set_color(color);
        self
    }

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// The alignment of block-level elements inside of this block-level element.
    pub fn block_align(&self) -> Option<BlockAlign> {
        self.get_layout(LayoutAttr::BLOCK_ALIGN).map(LayoutAttr::unwrap_block_align)
    }

    /// The alignment of inline-level elements inside of this block-level element.
    pub fn inline_align(&self) -> Option<InlineAlign> {
        self.get_layout(LayoutAttr::INLINE_ALIGN).map(LayoutAttr::unwrap_inline_align)
    }

    /// The border style of table cells, overriding `BorderStyle`.
    pub fn table_border_style(&self) -> Option<Sides<BorderStyle>> {
        self.get_layout(LayoutAttr::TABLE_BORDER_STYLE).map(LayoutAttr::unwrap_table_border_style)
    }

    /// The padding inside of table cells, overriding `Padding`.
    pub fn table_padding(&self) -> Option<Sides<f32>> {
        self.get_layout(LayoutAttr::TABLE_PADDING).map(LayoutAttr::unwrap_table_padding)
    }

    /// The distance by which the baseline shall be shifted from the default position.
    pub fn baseline_shift(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::BASELINE_SHIFT).map(LayoutAttr::unwrap_baseline_shift)
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn set_baseline_shift(&mut self, baseline_shift: Option<f32>) {
        self.set_or_remove_layout(LayoutAttr::BASELINE_SHIFT, baseline_shift.map(LayoutAttr::BaselineShift));
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn with_baseline_shift(mut self, baseline_shift: Option<f32>) -> Self {
        self.set_baseline_shift(baseline_shift);
        self
    }

    /// The height of each line in an element on the block axis.
    pub fn line_height(&self) -> Option<LineHeight> {
        self.get_layout(LayoutAttr::LINE_HEIGHT).map(LayoutAttr::unwrap_line_height)
    }

    /// Set the height of each line in an element on the block axis.
    pub fn set_line_height(&mut self, line_height: Option<LineHeight>) {
        self.set_or_remove_layout(LayoutAttr::LINE_HEIGHT, line_height.map(LayoutAttr::LineHeight));
    }

    /// Set the height of each line in an element on the block axis.
    pub fn with_line_height(mut self, line_height: Option<LineHeight>) -> Self {
        self.set_line_height(line_height);
        self
    }

    /// The color of the text decoration, overriding the fill color.
    pub fn text_decoration_color(&self) -> Option<NaiveRgbColor> {
        self.get_layout(LayoutAttr::TEXT_DECORATION_COLOR).map(LayoutAttr::unwrap_text_decoration_color)
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn set_text_decoration_color(&mut self, text_decoration_color: Option<NaiveRgbColor>) {
        self.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_COLOR, text_decoration_color.map(LayoutAttr::TextDecorationColor));
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn with_text_decoration_color(mut self, text_decoration_color: Option<NaiveRgbColor>) -> Self {
        self.set_text_decoration_color(text_decoration_color);
        self
    }

    /// The width of the text decoration line.
    pub fn text_decoration_thickness(&self) -> Option<f32> {
        self.get_layout(LayoutAttr::TEXT_DECORATION_THICKNESS).map(LayoutAttr::unwrap_text_decoration_thickness)
    }

    /// Set the width of the text decoration line.
    pub fn set_text_decoration_thickness(&mut self, text_decoration_thickness: Option<f32>) {
        self.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_THICKNESS, text_decoration_thickness.map(LayoutAttr::TextDecorationThickness));
    }

    /// Set the width of the text decoration line.
    pub fn with_text_decoration_thickness(mut self, text_decoration_thickness: Option<f32>) -> Self {
        self.set_text_decoration_thickness(text_decoration_thickness);
        self
    }

    /// The kind of text decoration.
    pub fn text_decoration_type(&self) -> Option<TextDecorationType> {
        self.get_layout(LayoutAttr::TEXT_DECORATION_TYPE).map(LayoutAttr::unwrap_text_decoration_type)
    }

    /// Set the kind of text decoration.
    pub fn set_text_decoration_type(&mut self, text_decoration_type: Option<TextDecorationType>) {
        self.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_TYPE, text_decoration_type.map(LayoutAttr::TextDecorationType));
    }

    /// Set the kind of text decoration.
    pub fn with_text_decoration_type(mut self, text_decoration_type: Option<TextDecorationType>) -> Self {
        self.set_text_decoration_type(text_decoration_type);
        self
    }

    /// How the glyphs are rotated in a vertical writing mode.
    pub fn glyph_orientation_vertical(&self) -> Option<GlyphOrientationVertical> {
        self.get_layout(LayoutAttr::GLYPH_ORIENTATION_VERTICAL).map(LayoutAttr::unwrap_glyph_orientation_vertical)
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn set_glyph_orientation_vertical(&mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) {
        self.set_or_remove_layout(LayoutAttr::GLYPH_ORIENTATION_VERTICAL, glyph_orientation_vertical.map(LayoutAttr::GlyphOrientationVertical));
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn with_glyph_orientation_vertical(mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) -> Self {
        self.set_glyph_orientation_vertical(glyph_orientation_vertical);
        self
    }

    /// The number of columns in the grouping element.
    pub fn column_count(&self) -> Option<NonZeroU32> {
        self.get_layout(LayoutAttr::COLUMN_COUNT).map(LayoutAttr::unwrap_column_count)
    }

    /// The width of the gaps between columns in the grouping element.
    pub fn column_gap(&self) -> Option<&ColumnDimensions> {
        self.get_layout(LayoutAttr::COLUMN_GAP).map(LayoutAttr::unwrap_column_gap)
    }

    /// The width of the columns in the grouping element.
    pub fn column_widths(&self) -> Option<&ColumnDimensions> {
        self.get_layout(LayoutAttr::COLUMN_WIDTHS).map(LayoutAttr::unwrap_column_widths)
    }
}

impl<T> Tag<T> {

    /// The tag id.
    pub fn id(&self) -> Option<&TagId> {
        self.inner.get_struct(StructAttr::ID).map(StructAttr::unwrap_id)
    }

    /// Set the tag id.
    pub fn set_id(&mut self, id: Option<TagId>) {
        self.inner.set_or_remove_struct(StructAttr::ID, id.map(StructAttr::Id));
    }

    /// Set the tag id.
    pub fn with_id(mut self, id: Option<TagId>) -> Self {
        self.set_id(id);
        self
    }

    /// The language of this tag.
    pub fn lang(&self) -> Option<&str> {
        self.inner.get_struct(StructAttr::LANG).map(StructAttr::unwrap_lang)
    }

    /// Set the language of this tag.
    pub fn set_lang(&mut self, lang: Option<String>) {
        self.inner.set_or_remove_struct(StructAttr::LANG, lang.map(StructAttr::Lang));
    }

    /// Set the language of this tag.
    pub fn with_lang(mut self, lang: Option<String>) -> Self {
        self.set_lang(lang);
        self
    }

    /// The optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn alt_text(&self) -> Option<&str> {
        self.inner.get_struct(StructAttr::ALT_TEXT).map(StructAttr::unwrap_alt_text)
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn set_alt_text(&mut self, alt_text: Option<String>) {
        self.inner.set_or_remove_struct(StructAttr::ALT_TEXT, alt_text.map(StructAttr::AltText));
    }

    /// Set the optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    pub fn with_alt_text(mut self, alt_text: Option<String>) -> Self {
        self.set_alt_text(alt_text);
        self
    }

    /// The expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn expanded(&self) -> Option<&str> {
        self.inner.get_struct(StructAttr::EXPANDED).map(StructAttr::unwrap_expanded)
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn set_expanded(&mut self, expanded: Option<String>) {
        self.inner.set_or_remove_struct(StructAttr::EXPANDED, expanded.map(StructAttr::Expanded));
    }

    /// Set the expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    pub fn with_expanded(mut self, expanded: Option<String>) -> Self {
        self.set_expanded(expanded);
        self
    }

    /// The actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn actual_text(&self) -> Option<&str> {
        self.inner.get_struct(StructAttr::ACTUAL_TEXT).map(StructAttr::unwrap_actual_text)
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn set_actual_text(&mut self, actual_text: Option<String>) {
        self.inner.set_or_remove_struct(StructAttr::ACTUAL_TEXT, actual_text.map(StructAttr::ActualText));
    }

    /// Set the actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    pub fn with_actual_text(mut self, actual_text: Option<String>) -> Self {
        self.set_actual_text(actual_text);
        self
    }

    /// The placement.
    pub fn placement(&self) -> Option<Placement> {
        self.inner.get_layout(LayoutAttr::PLACEMENT).map(LayoutAttr::unwrap_placement)
    }

    /// Set the placement.
    pub fn set_placement(&mut self, placement: Option<Placement>) {
        self.inner.set_or_remove_layout(LayoutAttr::PLACEMENT, placement.map(LayoutAttr::Placement));
    }

    /// Set the placement.
    pub fn with_placement(mut self, placement: Option<Placement>) -> Self {
        self.set_placement(placement);
        self
    }

    /// The writing mode.
    pub fn writing_mode(&self) -> Option<WritingMode> {
        self.inner.get_layout(LayoutAttr::WRITING_MODE).map(LayoutAttr::unwrap_writing_mode)
    }

    /// Set the writing mode.
    pub fn set_writing_mode(&mut self, writing_mode: Option<WritingMode>) {
        self.inner.set_or_remove_layout(LayoutAttr::WRITING_MODE, writing_mode.map(LayoutAttr::WritingMode));
    }

    /// Set the writing mode.
    pub fn with_writing_mode(mut self, writing_mode: Option<WritingMode>) -> Self {
        self.set_writing_mode(writing_mode);
        self
    }

    /// The background color.
    pub fn background_color(&self) -> Option<NaiveRgbColor> {
        self.inner.get_layout(LayoutAttr::BACKGROUND_COLOR).map(LayoutAttr::unwrap_background_color)
    }

    /// Set the background color.
    pub fn set_background_color(&mut self, background_color: Option<NaiveRgbColor>) {
        self.inner.set_or_remove_layout(LayoutAttr::BACKGROUND_COLOR, background_color.map(LayoutAttr::BackgroundColor));
    }

    /// Set the background color.
    pub fn with_background_color(mut self, background_color: Option<NaiveRgbColor>) -> Self {
        self.set_background_color(background_color);
        self
    }

    /// The border color.
    pub fn border_color(&self) -> Option<Sides<NaiveRgbColor>> {
        self.inner.get_layout(LayoutAttr::BORDER_COLOR).map(LayoutAttr::unwrap_border_color)
    }

    /// Set the border color.
    pub fn set_border_color(&mut self, border_color: Option<Sides<NaiveRgbColor>>) {
        self.inner.set_or_remove_layout(LayoutAttr::BORDER_COLOR, border_color.map(LayoutAttr::BorderColor));
    }

    /// Set the border color.
    pub fn with_border_color(mut self, border_color: Option<Sides<NaiveRgbColor>>) -> Self {
        self.set_border_color(border_color);
        self
    }

    /// The way the border is drawn.
    pub fn border_style(&self) -> Option<Sides<BorderStyle>> {
        self.inner.get_layout(LayoutAttr::BORDER_STYLE).map(LayoutAttr::unwrap_border_style)
    }

    /// Set the way the border is drawn.
    pub fn set_border_style(&mut self, border_style: Option<Sides<BorderStyle>>) {
        self.inner.set_or_remove_layout(LayoutAttr::BORDER_STYLE, border_style.map(LayoutAttr::BorderStyle));
    }

    /// Set the way the border is drawn.
    pub fn with_border_style(mut self, border_style: Option<Sides<BorderStyle>>) -> Self {
        self.set_border_style(border_style);
        self
    }

    /// The border width.
    pub fn border_thickness(&self) -> Option<Sides<f32>> {
        self.inner.get_layout(LayoutAttr::BORDER_THICKNESS).map(LayoutAttr::unwrap_border_thickness)
    }

    /// Set the border width.
    pub fn set_border_thickness(&mut self, border_thickness: Option<Sides<f32>>) {
        self.inner.set_or_remove_layout(LayoutAttr::BORDER_THICKNESS, border_thickness.map(LayoutAttr::BorderThickness));
    }

    /// Set the border width.
    pub fn with_border_thickness(mut self, border_thickness: Option<Sides<f32>>) -> Self {
        self.set_border_thickness(border_thickness);
        self
    }

    /// The padding inside of an element.
    pub fn padding(&self) -> Option<Sides<f32>> {
        self.inner.get_layout(LayoutAttr::PADDING).map(LayoutAttr::unwrap_padding)
    }

    /// Set the padding inside of an element.
    pub fn set_padding(&mut self, padding: Option<Sides<f32>>) {
        self.inner.set_or_remove_layout(LayoutAttr::PADDING, padding.map(LayoutAttr::Padding));
    }

    /// Set the padding inside of an element.
    pub fn with_padding(mut self, padding: Option<Sides<f32>>) -> Self {
        self.set_padding(padding);
        self
    }

    /// The color of text, borders, and text decorations.
    pub fn color(&self) -> Option<NaiveRgbColor> {
        self.inner.get_layout(LayoutAttr::COLOR).map(LayoutAttr::unwrap_color)
    }

    /// Set the color of text, borders, and text decorations.
    pub fn set_color(&mut self, color: Option<NaiveRgbColor>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLOR, color.map(LayoutAttr::Color));
    }

    /// Set the color of text, borders, and text decorations.
    pub fn with_color(mut self, color: Option<NaiveRgbColor>) -> Self {
        self.set_color(color);
        self
    }

    /// The distance by which the baseline shall be shifted from the default position.
    pub fn baseline_shift(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::BASELINE_SHIFT).map(LayoutAttr::unwrap_baseline_shift)
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn set_baseline_shift(&mut self, baseline_shift: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::BASELINE_SHIFT, baseline_shift.map(LayoutAttr::BaselineShift));
    }

    /// Set the distance by which the baseline shall be shifted from the default position.
    pub fn with_baseline_shift(mut self, baseline_shift: Option<f32>) -> Self {
        self.set_baseline_shift(baseline_shift);
        self
    }

    /// The height of each line in an element on the block axis.
    pub fn line_height(&self) -> Option<LineHeight> {
        self.inner.get_layout(LayoutAttr::LINE_HEIGHT).map(LayoutAttr::unwrap_line_height)
    }

    /// Set the height of each line in an element on the block axis.
    pub fn set_line_height(&mut self, line_height: Option<LineHeight>) {
        self.inner.set_or_remove_layout(LayoutAttr::LINE_HEIGHT, line_height.map(LayoutAttr::LineHeight));
    }

    /// Set the height of each line in an element on the block axis.
    pub fn with_line_height(mut self, line_height: Option<LineHeight>) -> Self {
        self.set_line_height(line_height);
        self
    }

    /// The color of the text decoration, overriding the fill color.
    pub fn text_decoration_color(&self) -> Option<NaiveRgbColor> {
        self.inner.get_layout(LayoutAttr::TEXT_DECORATION_COLOR).map(LayoutAttr::unwrap_text_decoration_color)
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn set_text_decoration_color(&mut self, text_decoration_color: Option<NaiveRgbColor>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_COLOR, text_decoration_color.map(LayoutAttr::TextDecorationColor));
    }

    /// Set the color of the text decoration, overriding the fill color.
    pub fn with_text_decoration_color(mut self, text_decoration_color: Option<NaiveRgbColor>) -> Self {
        self.set_text_decoration_color(text_decoration_color);
        self
    }

    /// The width of the text decoration line.
    pub fn text_decoration_thickness(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_DECORATION_THICKNESS).map(LayoutAttr::unwrap_text_decoration_thickness)
    }

    /// Set the width of the text decoration line.
    pub fn set_text_decoration_thickness(&mut self, text_decoration_thickness: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_THICKNESS, text_decoration_thickness.map(LayoutAttr::TextDecorationThickness));
    }

    /// Set the width of the text decoration line.
    pub fn with_text_decoration_thickness(mut self, text_decoration_thickness: Option<f32>) -> Self {
        self.set_text_decoration_thickness(text_decoration_thickness);
        self
    }

    /// The kind of text decoration.
    pub fn text_decoration_type(&self) -> Option<TextDecorationType> {
        self.inner.get_layout(LayoutAttr::TEXT_DECORATION_TYPE).map(LayoutAttr::unwrap_text_decoration_type)
    }

    /// Set the kind of text decoration.
    pub fn set_text_decoration_type(&mut self, text_decoration_type: Option<TextDecorationType>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_DECORATION_TYPE, text_decoration_type.map(LayoutAttr::TextDecorationType));
    }

    /// Set the kind of text decoration.
    pub fn with_text_decoration_type(mut self, text_decoration_type: Option<TextDecorationType>) -> Self {
        self.set_text_decoration_type(text_decoration_type);
        self
    }

    /// How the glyphs are rotated in a vertical writing mode.
    pub fn glyph_orientation_vertical(&self) -> Option<GlyphOrientationVertical> {
        self.inner.get_layout(LayoutAttr::GLYPH_ORIENTATION_VERTICAL).map(LayoutAttr::unwrap_glyph_orientation_vertical)
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn set_glyph_orientation_vertical(&mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) {
        self.inner.set_or_remove_layout(LayoutAttr::GLYPH_ORIENTATION_VERTICAL, glyph_orientation_vertical.map(LayoutAttr::GlyphOrientationVertical));
    }

    /// Set how the glyphs are rotated in a vertical writing mode.
    pub fn with_glyph_orientation_vertical(mut self, glyph_orientation_vertical: Option<GlyphOrientationVertical>) -> Self {
        self.set_glyph_orientation_vertical(glyph_orientation_vertical);
        self
    }
}

/// Tag kind structs.
pub mod kind {
    /// A part of a document that may contain multiple articles or sections.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Part;

    /// An article with largely self-contained content.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Article;

    /// Section of a larger document.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Section;

    /// A generic block-level grouping element.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Div;

    /// A paragraph-level quote.
    #[derive(Clone, Debug, PartialEq)]
    pub struct BlockQuote;

    /// An image or figure caption.
    ///
    /// **Best Practice**: In the tag tree, this should appear
    /// as a sibling after the image (or other) content it describes.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Caption;

    /// Table of contents.
    ///
    /// **Best Practice**: Should consist of TOCIs or other nested TOCs.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TOC;

    /// Item in the table of contents.
    ///
    /// **Best Practice**: Should only appear within a TOC. Should only consist of
    /// labels, references, paragraphs and TOCs.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TOCI;

    /// Index of the key terms in the document.
    ///
    /// **Best Practice**: Should contain a sequence of text accompanied by
    /// reference elements pointing to their occurrence in the text.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Index;

    /// A paragraph.
    #[derive(Clone, Debug, PartialEq)]
    pub struct P;

    /// Heading level `n`, including an optional title of the heading.
    ///
    /// The title is required for some export modes, like for example PDF/UA.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Hn;

    /// A list.
    ///
    /// **Best practice**: Should consist of an optional caption followed by
    /// list items.
    /// List numbering is only required for PDF/UA, but we just enforce it for always.
    #[derive(Clone, Debug, PartialEq)]
    pub struct L;

    /// A list item.
    ///
    /// **Best practice**: Should consist of one or more list labels and/or list bodies.
    #[derive(Clone, Debug, PartialEq)]
    pub struct LI;

    /// Label for a list item.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Lbl;

    /// Description of the list item.
    #[derive(Clone, Debug, PartialEq)]
    pub struct LBody;

    /// A table, with an optional summary describing the purpose and structure.
    ///
    /// **Best practice**: Should consist of an optional table header row,
    /// one or more table body elements and an optional table footer. Can have
    /// caption as the first or last child.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Table;

    /// A table row.
    ///
    /// **Best practice**: May contain table headers cells and table data cells.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TR;

    /// A table header cell.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TH;

    /// A table data cell.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TD;

    /// A table header row group.
    #[derive(Clone, Debug, PartialEq)]
    pub struct THead;

    /// A table data row group.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TBody;

    /// A table footer row group.
    #[derive(Clone, Debug, PartialEq)]
    pub struct TFoot;

    /// An inline-level element that does not have a specific meaning.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Span;

    /// An inline quotation.
    #[derive(Clone, Debug, PartialEq)]
    pub struct InlineQuote;

    /// A foot- or endnote, potentially referred to from within the text.
    ///
    /// **Best practice**: It may have a label as a child.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Note;

    /// A reference to elsewhere in the document.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to a destination in the document, and the second child should consist of
    /// the children that should be associated with that reference.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Reference;

    /// A reference to the external source of some cited document.
    ///
    /// **Best practice**: It may have a label as a child.
    #[derive(Clone, Debug, PartialEq)]
    pub struct BibEntry;

    /// Computer code.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Code;

    /// A link.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to an URL, and the second child should consist of the children that should
    /// be associated with that link.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Link;

    /// An association between an annotation and the content it belongs to. PDF
    ///
    /// **Best practice**: Should be used for all annotations, except for link annotations and
    /// widget annotations. The first child should be the identifier of a non-link annotation,
    /// and all other subsequent children should be content identifiers associated with that
    /// annotation.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Annot;

    /// Item of graphical content.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Figure;

    /// A mathematical formula.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Formula;

    /// Non-structural element. A grouping element having no inherent structural significance;
    /// it serves solely for grouping purposes.
    #[derive(Clone, Debug, PartialEq)]
    pub struct NonStruct;

    /// A date or time.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Datetime;

    /// A list of terms.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Terms;

    /// A title.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Title;

    /// Encloses content with strong importance, most commonly **bold** text.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Strong;

    /// Encloses content that is emphasized, most commonly *italic* text.
    #[derive(Clone, Debug, PartialEq)]
    pub struct Em;

}

impl From<Tag<kind::Part>> for TagKind {
    fn from(value: Tag<kind::Part>) -> Self {
        Self::Part(value)
    }
}
impl Tag<kind::Part> {
    /// A part of a document that may contain multiple articles or sections.
    #[allow(non_upper_case_globals)]
    pub const Part: Tag<kind::Part> = Tag::new();
}

impl From<Tag<kind::Article>> for TagKind {
    fn from(value: Tag<kind::Article>) -> Self {
        Self::Article(value)
    }
}
impl Tag<kind::Article> {
    /// An article with largely self-contained content.
    #[allow(non_upper_case_globals)]
    pub const Article: Tag<kind::Article> = Tag::new();

    /// The number of columns in the grouping element.
    pub fn column_count(&self) -> Option<NonZeroU32> {
        self.inner.get_layout(LayoutAttr::COLUMN_COUNT).map(LayoutAttr::unwrap_column_count)
    }

    /// Set the number of columns in the grouping element.
    pub fn set_column_count(&mut self, column_count: Option<NonZeroU32>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_COUNT, column_count.map(LayoutAttr::ColumnCount));
    }

    /// Set the number of columns in the grouping element.
    pub fn with_column_count(mut self, column_count: Option<NonZeroU32>) -> Self {
        self.set_column_count(column_count);
        self
    }

    /// The width of the gaps between columns in the grouping element.
    pub fn column_gap(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_GAP).map(LayoutAttr::unwrap_column_gap)
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn set_column_gap(&mut self, column_gap: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_GAP, column_gap.map(LayoutAttr::ColumnGap));
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn with_column_gap(mut self, column_gap: Option<ColumnDimensions>) -> Self {
        self.set_column_gap(column_gap);
        self
    }

    /// The width of the columns in the grouping element.
    pub fn column_widths(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_WIDTHS).map(LayoutAttr::unwrap_column_widths)
    }

    /// Set the width of the columns in the grouping element.
    pub fn set_column_widths(&mut self, column_widths: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_WIDTHS, column_widths.map(LayoutAttr::ColumnWidths));
    }

    /// Set the width of the columns in the grouping element.
    pub fn with_column_widths(mut self, column_widths: Option<ColumnDimensions>) -> Self {
        self.set_column_widths(column_widths);
        self
    }
}

impl From<Tag<kind::Section>> for TagKind {
    fn from(value: Tag<kind::Section>) -> Self {
        Self::Section(value)
    }
}
impl Tag<kind::Section> {
    /// Section of a larger document.
    #[allow(non_upper_case_globals)]
    pub const Section: Tag<kind::Section> = Tag::new();

    /// The number of columns in the grouping element.
    pub fn column_count(&self) -> Option<NonZeroU32> {
        self.inner.get_layout(LayoutAttr::COLUMN_COUNT).map(LayoutAttr::unwrap_column_count)
    }

    /// Set the number of columns in the grouping element.
    pub fn set_column_count(&mut self, column_count: Option<NonZeroU32>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_COUNT, column_count.map(LayoutAttr::ColumnCount));
    }

    /// Set the number of columns in the grouping element.
    pub fn with_column_count(mut self, column_count: Option<NonZeroU32>) -> Self {
        self.set_column_count(column_count);
        self
    }

    /// The width of the gaps between columns in the grouping element.
    pub fn column_gap(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_GAP).map(LayoutAttr::unwrap_column_gap)
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn set_column_gap(&mut self, column_gap: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_GAP, column_gap.map(LayoutAttr::ColumnGap));
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn with_column_gap(mut self, column_gap: Option<ColumnDimensions>) -> Self {
        self.set_column_gap(column_gap);
        self
    }

    /// The width of the columns in the grouping element.
    pub fn column_widths(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_WIDTHS).map(LayoutAttr::unwrap_column_widths)
    }

    /// Set the width of the columns in the grouping element.
    pub fn set_column_widths(&mut self, column_widths: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_WIDTHS, column_widths.map(LayoutAttr::ColumnWidths));
    }

    /// Set the width of the columns in the grouping element.
    pub fn with_column_widths(mut self, column_widths: Option<ColumnDimensions>) -> Self {
        self.set_column_widths(column_widths);
        self
    }
}

impl From<Tag<kind::Div>> for TagKind {
    fn from(value: Tag<kind::Div>) -> Self {
        Self::Div(value)
    }
}
impl Tag<kind::Div> {
    /// A generic block-level grouping element.
    #[allow(non_upper_case_globals)]
    pub const Div: Tag<kind::Div> = Tag::new();

    /// The number of columns in the grouping element.
    pub fn column_count(&self) -> Option<NonZeroU32> {
        self.inner.get_layout(LayoutAttr::COLUMN_COUNT).map(LayoutAttr::unwrap_column_count)
    }

    /// Set the number of columns in the grouping element.
    pub fn set_column_count(&mut self, column_count: Option<NonZeroU32>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_COUNT, column_count.map(LayoutAttr::ColumnCount));
    }

    /// Set the number of columns in the grouping element.
    pub fn with_column_count(mut self, column_count: Option<NonZeroU32>) -> Self {
        self.set_column_count(column_count);
        self
    }

    /// The width of the gaps between columns in the grouping element.
    pub fn column_gap(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_GAP).map(LayoutAttr::unwrap_column_gap)
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn set_column_gap(&mut self, column_gap: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_GAP, column_gap.map(LayoutAttr::ColumnGap));
    }

    /// Set the width of the gaps between columns in the grouping element.
    pub fn with_column_gap(mut self, column_gap: Option<ColumnDimensions>) -> Self {
        self.set_column_gap(column_gap);
        self
    }

    /// The width of the columns in the grouping element.
    pub fn column_widths(&self) -> Option<&ColumnDimensions> {
        self.inner.get_layout(LayoutAttr::COLUMN_WIDTHS).map(LayoutAttr::unwrap_column_widths)
    }

    /// Set the width of the columns in the grouping element.
    pub fn set_column_widths(&mut self, column_widths: Option<ColumnDimensions>) {
        self.inner.set_or_remove_layout(LayoutAttr::COLUMN_WIDTHS, column_widths.map(LayoutAttr::ColumnWidths));
    }

    /// Set the width of the columns in the grouping element.
    pub fn with_column_widths(mut self, column_widths: Option<ColumnDimensions>) -> Self {
        self.set_column_widths(column_widths);
        self
    }
}

impl From<Tag<kind::BlockQuote>> for TagKind {
    fn from(value: Tag<kind::BlockQuote>) -> Self {
        Self::BlockQuote(value)
    }
}
impl Tag<kind::BlockQuote> {
    /// A paragraph-level quote.
    #[allow(non_upper_case_globals)]
    pub const BlockQuote: Tag<kind::BlockQuote> = Tag::new();
}

impl From<Tag<kind::Caption>> for TagKind {
    fn from(value: Tag<kind::Caption>) -> Self {
        Self::Caption(value)
    }
}
impl Tag<kind::Caption> {
    /// An image or figure caption.
    ///
    /// **Best Practice**: In the tag tree, this should appear
    /// as a sibling after the image (or other) content it describes.
    #[allow(non_upper_case_globals)]
    pub const Caption: Tag<kind::Caption> = Tag::new();
}

impl From<Tag<kind::TOC>> for TagKind {
    fn from(value: Tag<kind::TOC>) -> Self {
        Self::TOC(value)
    }
}
impl Tag<kind::TOC> {
    /// Table of contents.
    ///
    /// **Best Practice**: Should consist of TOCIs or other nested TOCs.
    #[allow(non_upper_case_globals)]
    pub const TOC: Tag<kind::TOC> = Tag::new();
}

impl From<Tag<kind::TOCI>> for TagKind {
    fn from(value: Tag<kind::TOCI>) -> Self {
        Self::TOCI(value)
    }
}
impl Tag<kind::TOCI> {
    /// Item in the table of contents.
    ///
    /// **Best Practice**: Should only appear within a TOC. Should only consist of
    /// labels, references, paragraphs and TOCs.
    #[allow(non_upper_case_globals)]
    pub const TOCI: Tag<kind::TOCI> = Tag::new();
}

impl From<Tag<kind::Index>> for TagKind {
    fn from(value: Tag<kind::Index>) -> Self {
        Self::Index(value)
    }
}
impl Tag<kind::Index> {
    /// Index of the key terms in the document.
    ///
    /// **Best Practice**: Should contain a sequence of text accompanied by
    /// reference elements pointing to their occurrence in the text.
    #[allow(non_upper_case_globals)]
    pub const Index: Tag<kind::Index> = Tag::new();
}

impl From<Tag<kind::P>> for TagKind {
    fn from(value: Tag<kind::P>) -> Self {
        Self::P(value)
    }
}
impl Tag<kind::P> {
    /// A paragraph.
    #[allow(non_upper_case_globals)]
    pub const P: Tag<kind::P> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::Hn>> for TagKind {
    fn from(value: Tag<kind::Hn>) -> Self {
        Self::Hn(value)
    }
}
impl Tag<kind::Hn> {
    /// Heading level `n`, including an optional title of the heading.
    ///
    /// The title is required for some export modes, like for example PDF/UA.
    #[allow(non_snake_case)]
    pub fn Hn(level: NonZeroU16, title: Option<String>) -> Tag<kind::Hn> {
        let mut tag = Tag::new();
        tag.set_level(level);
        tag.set_title(title);
        tag
    }

    /// The heading level
    pub fn level(&self) -> NonZeroU16 {
        self.inner.get_struct(StructAttr::HEADING_LEVEL).unwrap().unwrap_level()
    }

    /// Set the heading level
    pub fn set_level(&mut self, level: NonZeroU16) {
        self.inner.set_struct(StructAttr::HeadingLevel(level));
    }

    /// Set the heading level
    pub fn with_level(mut self, level: NonZeroU16) -> Self {
        self.set_level(level);
        self
    }

    /// The title, characterizing a specific tag such as `"Chapter 1"`.
    pub fn title(&self) -> Option<&str> {
        self.inner.get_struct(StructAttr::TITLE).map(StructAttr::unwrap_title)
    }

    /// Set the title, characterizing a specific tag such as `"Chapter 1"`.
    pub fn set_title(&mut self, title: Option<String>) {
        self.inner.set_or_remove_struct(StructAttr::TITLE, title.map(StructAttr::Title));
    }

    /// Set the title, characterizing a specific tag such as `"Chapter 1"`.
    pub fn with_title(mut self, title: Option<String>) -> Self {
        self.set_title(title);
        self
    }

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::L>> for TagKind {
    fn from(value: Tag<kind::L>) -> Self {
        Self::L(value)
    }
}
impl Tag<kind::L> {
    /// A list.
    ///
    /// **Best practice**: Should consist of an optional caption followed by
    /// list items.
    /// List numbering is only required for PDF/UA, but we just enforce it for always.
    #[allow(non_snake_case)]
    pub fn L(numbering: ListNumbering) -> Tag<kind::L> {
        let mut tag = Tag::new();
        tag.set_numbering(numbering);
        tag
    }

    /// The list numbering.
    pub fn numbering(&self) -> ListNumbering {
        self.inner.get_list(ListAttr::NUMBERING).unwrap().unwrap_numbering()
    }

    /// Set the list numbering.
    pub fn set_numbering(&mut self, numbering: ListNumbering) {
        self.inner.set_list(ListAttr::Numbering(numbering));
    }

    /// Set the list numbering.
    pub fn with_numbering(mut self, numbering: ListNumbering) -> Self {
        self.set_numbering(numbering);
        self
    }

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::LI>> for TagKind {
    fn from(value: Tag<kind::LI>) -> Self {
        Self::LI(value)
    }
}
impl Tag<kind::LI> {
    /// A list item.
    ///
    /// **Best practice**: Should consist of one or more list labels and/or list bodies.
    #[allow(non_upper_case_globals)]
    pub const LI: Tag<kind::LI> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::Lbl>> for TagKind {
    fn from(value: Tag<kind::Lbl>) -> Self {
        Self::Lbl(value)
    }
}
impl Tag<kind::Lbl> {
    /// Label for a list item.
    #[allow(non_upper_case_globals)]
    pub const Lbl: Tag<kind::Lbl> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::LBody>> for TagKind {
    fn from(value: Tag<kind::LBody>) -> Self {
        Self::LBody(value)
    }
}
impl Tag<kind::LBody> {
    /// Description of the list item.
    #[allow(non_upper_case_globals)]
    pub const LBody: Tag<kind::LBody> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::Table>> for TagKind {
    fn from(value: Tag<kind::Table>) -> Self {
        Self::Table(value)
    }
}
impl Tag<kind::Table> {
    /// A table, with an optional summary describing the purpose and structure.
    ///
    /// **Best practice**: Should consist of an optional table header row,
    /// one or more table body elements and an optional table footer. Can have
    /// caption as the first or last child.
    #[allow(non_upper_case_globals)]
    pub const Table: Tag<kind::Table> = Tag::new();

    /// The table summary.
    pub fn summary(&self) -> Option<&str> {
        self.inner.get_table(TableAttr::SUMMARY).map(TableAttr::unwrap_summary)
    }

    /// Set the table summary.
    pub fn set_summary(&mut self, summary: Option<String>) {
        self.inner.set_or_remove_table(TableAttr::SUMMARY, summary.map(TableAttr::Summary));
    }

    /// Set the table summary.
    pub fn with_summary(mut self, summary: Option<String>) -> Self {
        self.set_summary(summary);
        self
    }

    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn bbox(&self) -> Option<BBox> {
        self.inner.get_layout(LayoutAttr::B_BOX).map(LayoutAttr::unwrap_bbox)
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn set_bbox(&mut self, bbox: Option<BBox>) {
        self.inner.set_or_remove_layout(LayoutAttr::B_BOX, bbox.map(LayoutAttr::BBox));
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn with_bbox(mut self, bbox: Option<BBox>) -> Self {
        self.set_bbox(bbox);
        self
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// Set the width.
    pub fn set_width(&mut self, width: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::WIDTH, width.map(LayoutAttr::Width));
    }

    /// Set the width.
    pub fn with_width(mut self, width: Option<f32>) -> Self {
        self.set_width(width);
        self
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// Set the height.
    pub fn set_height(&mut self, height: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::HEIGHT, height.map(LayoutAttr::Height));
    }

    /// Set the height.
    pub fn with_height(mut self, height: Option<f32>) -> Self {
        self.set_height(height);
        self
    }

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }

    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn text_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::TEXT_INDENT).map(LayoutAttr::unwrap_text_indent)
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn set_text_indent(&mut self, text_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_INDENT, text_indent.map(LayoutAttr::TextIndent));
    }

    /// Set the amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    pub fn with_text_indent(mut self, text_indent: Option<f32>) -> Self {
        self.set_text_indent(text_indent);
        self
    }

    /// The text alignment.
    pub fn text_align(&self) -> Option<TextAlign> {
        self.inner.get_layout(LayoutAttr::TEXT_ALIGN).map(LayoutAttr::unwrap_text_align)
    }

    /// Set the text alignment.
    pub fn set_text_align(&mut self, text_align: Option<TextAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::TEXT_ALIGN, text_align.map(LayoutAttr::TextAlign));
    }

    /// Set the text alignment.
    pub fn with_text_align(mut self, text_align: Option<TextAlign>) -> Self {
        self.set_text_align(text_align);
        self
    }
}

impl From<Tag<kind::TR>> for TagKind {
    fn from(value: Tag<kind::TR>) -> Self {
        Self::TR(value)
    }
}
impl Tag<kind::TR> {
    /// A table row.
    ///
    /// **Best practice**: May contain table headers cells and table data cells.
    #[allow(non_upper_case_globals)]
    pub const TR: Tag<kind::TR> = Tag::new();
}

impl From<Tag<kind::TH>> for TagKind {
    fn from(value: Tag<kind::TH>) -> Self {
        Self::TH(value)
    }
}
impl Tag<kind::TH> {
    /// A table header cell.
    #[allow(non_snake_case)]
    pub fn TH(scope: TableHeaderScope) -> Tag<kind::TH> {
        let mut tag = Tag::new();
        tag.set_scope(scope);
        tag
    }

    /// The table header scope.
    pub fn scope(&self) -> TableHeaderScope {
        self.inner.get_table(TableAttr::HEADER_SCOPE).unwrap().unwrap_scope()
    }

    /// Set the table header scope.
    pub fn set_scope(&mut self, scope: TableHeaderScope) {
        self.inner.set_table(TableAttr::HeaderScope(scope));
    }

    /// Set the table header scope.
    pub fn with_scope(mut self, scope: TableHeaderScope) -> Self {
        self.set_scope(scope);
        self
    }

    /// The list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn headers(&self) -> Option<&[TagId]> {
        self.inner.get_table(TableAttr::CELL_HEADERS).map(TableAttr::unwrap_headers)
    }

    /// Set the list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn set_headers(&mut self, headers: Option<impl IntoIterator<Item = TagId>>) {
        self.inner.set_or_remove_table(TableAttr::CELL_HEADERS, headers.map(|ids| ids.into_iter().collect()).map(TableAttr::CellHeaders));
    }

    /// Set the list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn with_headers(mut self, headers: Option<impl IntoIterator<Item = TagId>>) -> Self {
        self.set_headers(headers);
        self
    }

    /// The row span of this table cell.
    pub fn row_span(&self) -> Option<NonZeroU32> {
        self.inner.get_table(TableAttr::ROW_SPAN).map(TableAttr::unwrap_row_span)
    }

    /// Set the row span of this table cell.
    pub fn set_row_span(&mut self, row_span: Option<NonZeroU32>) {
        self.inner.set_or_remove_table(TableAttr::ROW_SPAN, row_span.map(TableAttr::RowSpan));
    }

    /// Set the row span of this table cell.
    pub fn with_row_span(mut self, row_span: Option<NonZeroU32>) -> Self {
        self.set_row_span(row_span);
        self
    }

    /// The column span of this table cell.
    pub fn col_span(&self) -> Option<NonZeroU32> {
        self.inner.get_table(TableAttr::COL_SPAN).map(TableAttr::unwrap_col_span)
    }

    /// Set the column span of this table cell.
    pub fn set_col_span(&mut self, col_span: Option<NonZeroU32>) {
        self.inner.set_or_remove_table(TableAttr::COL_SPAN, col_span.map(TableAttr::ColSpan));
    }

    /// Set the column span of this table cell.
    pub fn with_col_span(mut self, col_span: Option<NonZeroU32>) -> Self {
        self.set_col_span(col_span);
        self
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// Set the width.
    pub fn set_width(&mut self, width: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::WIDTH, width.map(LayoutAttr::Width));
    }

    /// Set the width.
    pub fn with_width(mut self, width: Option<f32>) -> Self {
        self.set_width(width);
        self
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// Set the height.
    pub fn set_height(&mut self, height: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::HEIGHT, height.map(LayoutAttr::Height));
    }

    /// Set the height.
    pub fn with_height(mut self, height: Option<f32>) -> Self {
        self.set_height(height);
        self
    }

    /// The border style of table cells, overriding `BorderStyle`.
    pub fn table_border_style(&self) -> Option<Sides<BorderStyle>> {
        self.inner.get_layout(LayoutAttr::TABLE_BORDER_STYLE).map(LayoutAttr::unwrap_table_border_style)
    }

    /// Set the border style of table cells, overriding `BorderStyle`.
    pub fn set_table_border_style(&mut self, table_border_style: Option<Sides<BorderStyle>>) {
        self.inner.set_or_remove_layout(LayoutAttr::TABLE_BORDER_STYLE, table_border_style.map(LayoutAttr::TableBorderStyle));
    }

    /// Set the border style of table cells, overriding `BorderStyle`.
    pub fn with_table_border_style(mut self, table_border_style: Option<Sides<BorderStyle>>) -> Self {
        self.set_table_border_style(table_border_style);
        self
    }

    /// The padding inside of table cells, overriding `Padding`.
    pub fn table_padding(&self) -> Option<Sides<f32>> {
        self.inner.get_layout(LayoutAttr::TABLE_PADDING).map(LayoutAttr::unwrap_table_padding)
    }

    /// Set the padding inside of table cells, overriding `Padding`.
    pub fn set_table_padding(&mut self, table_padding: Option<Sides<f32>>) {
        self.inner.set_or_remove_layout(LayoutAttr::TABLE_PADDING, table_padding.map(LayoutAttr::TablePadding));
    }

    /// Set the padding inside of table cells, overriding `Padding`.
    pub fn with_table_padding(mut self, table_padding: Option<Sides<f32>>) -> Self {
        self.set_table_padding(table_padding);
        self
    }

    /// The alignment of block-level elements inside of this block-level element.
    pub fn block_align(&self) -> Option<BlockAlign> {
        self.inner.get_layout(LayoutAttr::BLOCK_ALIGN).map(LayoutAttr::unwrap_block_align)
    }

    /// Set the alignment of block-level elements inside of this block-level element.
    pub fn set_block_align(&mut self, block_align: Option<BlockAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::BLOCK_ALIGN, block_align.map(LayoutAttr::BlockAlign));
    }

    /// Set the alignment of block-level elements inside of this block-level element.
    pub fn with_block_align(mut self, block_align: Option<BlockAlign>) -> Self {
        self.set_block_align(block_align);
        self
    }

    /// The alignment of inline-level elements inside of this block-level element.
    pub fn inline_align(&self) -> Option<InlineAlign> {
        self.inner.get_layout(LayoutAttr::INLINE_ALIGN).map(LayoutAttr::unwrap_inline_align)
    }

    /// Set the alignment of inline-level elements inside of this block-level element.
    pub fn set_inline_align(&mut self, inline_align: Option<InlineAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::INLINE_ALIGN, inline_align.map(LayoutAttr::InlineAlign));
    }

    /// Set the alignment of inline-level elements inside of this block-level element.
    pub fn with_inline_align(mut self, inline_align: Option<InlineAlign>) -> Self {
        self.set_inline_align(inline_align);
        self
    }
}

impl From<Tag<kind::TD>> for TagKind {
    fn from(value: Tag<kind::TD>) -> Self {
        Self::TD(value)
    }
}
impl Tag<kind::TD> {
    /// A table data cell.
    #[allow(non_upper_case_globals)]
    pub const TD: Tag<kind::TD> = Tag::new();

    /// The list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn headers(&self) -> Option<&[TagId]> {
        self.inner.get_table(TableAttr::CELL_HEADERS).map(TableAttr::unwrap_headers)
    }

    /// Set the list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn set_headers(&mut self, headers: Option<impl IntoIterator<Item = TagId>>) {
        self.inner.set_or_remove_table(TableAttr::CELL_HEADERS, headers.map(|ids| ids.into_iter().collect()).map(TableAttr::CellHeaders));
    }

    /// Set the list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    pub fn with_headers(mut self, headers: Option<impl IntoIterator<Item = TagId>>) -> Self {
        self.set_headers(headers);
        self
    }

    /// The row span of this table cell.
    pub fn row_span(&self) -> Option<NonZeroU32> {
        self.inner.get_table(TableAttr::ROW_SPAN).map(TableAttr::unwrap_row_span)
    }

    /// Set the row span of this table cell.
    pub fn set_row_span(&mut self, row_span: Option<NonZeroU32>) {
        self.inner.set_or_remove_table(TableAttr::ROW_SPAN, row_span.map(TableAttr::RowSpan));
    }

    /// Set the row span of this table cell.
    pub fn with_row_span(mut self, row_span: Option<NonZeroU32>) -> Self {
        self.set_row_span(row_span);
        self
    }

    /// The column span of this table cell.
    pub fn col_span(&self) -> Option<NonZeroU32> {
        self.inner.get_table(TableAttr::COL_SPAN).map(TableAttr::unwrap_col_span)
    }

    /// Set the column span of this table cell.
    pub fn set_col_span(&mut self, col_span: Option<NonZeroU32>) {
        self.inner.set_or_remove_table(TableAttr::COL_SPAN, col_span.map(TableAttr::ColSpan));
    }

    /// Set the column span of this table cell.
    pub fn with_col_span(mut self, col_span: Option<NonZeroU32>) -> Self {
        self.set_col_span(col_span);
        self
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// Set the width.
    pub fn set_width(&mut self, width: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::WIDTH, width.map(LayoutAttr::Width));
    }

    /// Set the width.
    pub fn with_width(mut self, width: Option<f32>) -> Self {
        self.set_width(width);
        self
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// Set the height.
    pub fn set_height(&mut self, height: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::HEIGHT, height.map(LayoutAttr::Height));
    }

    /// Set the height.
    pub fn with_height(mut self, height: Option<f32>) -> Self {
        self.set_height(height);
        self
    }

    /// The border style of table cells, overriding `BorderStyle`.
    pub fn table_border_style(&self) -> Option<Sides<BorderStyle>> {
        self.inner.get_layout(LayoutAttr::TABLE_BORDER_STYLE).map(LayoutAttr::unwrap_table_border_style)
    }

    /// Set the border style of table cells, overriding `BorderStyle`.
    pub fn set_table_border_style(&mut self, table_border_style: Option<Sides<BorderStyle>>) {
        self.inner.set_or_remove_layout(LayoutAttr::TABLE_BORDER_STYLE, table_border_style.map(LayoutAttr::TableBorderStyle));
    }

    /// Set the border style of table cells, overriding `BorderStyle`.
    pub fn with_table_border_style(mut self, table_border_style: Option<Sides<BorderStyle>>) -> Self {
        self.set_table_border_style(table_border_style);
        self
    }

    /// The padding inside of table cells, overriding `Padding`.
    pub fn table_padding(&self) -> Option<Sides<f32>> {
        self.inner.get_layout(LayoutAttr::TABLE_PADDING).map(LayoutAttr::unwrap_table_padding)
    }

    /// Set the padding inside of table cells, overriding `Padding`.
    pub fn set_table_padding(&mut self, table_padding: Option<Sides<f32>>) {
        self.inner.set_or_remove_layout(LayoutAttr::TABLE_PADDING, table_padding.map(LayoutAttr::TablePadding));
    }

    /// Set the padding inside of table cells, overriding `Padding`.
    pub fn with_table_padding(mut self, table_padding: Option<Sides<f32>>) -> Self {
        self.set_table_padding(table_padding);
        self
    }

    /// The alignment of block-level elements inside of this block-level element.
    pub fn block_align(&self) -> Option<BlockAlign> {
        self.inner.get_layout(LayoutAttr::BLOCK_ALIGN).map(LayoutAttr::unwrap_block_align)
    }

    /// Set the alignment of block-level elements inside of this block-level element.
    pub fn set_block_align(&mut self, block_align: Option<BlockAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::BLOCK_ALIGN, block_align.map(LayoutAttr::BlockAlign));
    }

    /// Set the alignment of block-level elements inside of this block-level element.
    pub fn with_block_align(mut self, block_align: Option<BlockAlign>) -> Self {
        self.set_block_align(block_align);
        self
    }

    /// The alignment of inline-level elements inside of this block-level element.
    pub fn inline_align(&self) -> Option<InlineAlign> {
        self.inner.get_layout(LayoutAttr::INLINE_ALIGN).map(LayoutAttr::unwrap_inline_align)
    }

    /// Set the alignment of inline-level elements inside of this block-level element.
    pub fn set_inline_align(&mut self, inline_align: Option<InlineAlign>) {
        self.inner.set_or_remove_layout(LayoutAttr::INLINE_ALIGN, inline_align.map(LayoutAttr::InlineAlign));
    }

    /// Set the alignment of inline-level elements inside of this block-level element.
    pub fn with_inline_align(mut self, inline_align: Option<InlineAlign>) -> Self {
        self.set_inline_align(inline_align);
        self
    }
}

impl From<Tag<kind::THead>> for TagKind {
    fn from(value: Tag<kind::THead>) -> Self {
        Self::THead(value)
    }
}
impl Tag<kind::THead> {
    /// A table header row group.
    #[allow(non_upper_case_globals)]
    pub const THead: Tag<kind::THead> = Tag::new();
}

impl From<Tag<kind::TBody>> for TagKind {
    fn from(value: Tag<kind::TBody>) -> Self {
        Self::TBody(value)
    }
}
impl Tag<kind::TBody> {
    /// A table data row group.
    #[allow(non_upper_case_globals)]
    pub const TBody: Tag<kind::TBody> = Tag::new();
}

impl From<Tag<kind::TFoot>> for TagKind {
    fn from(value: Tag<kind::TFoot>) -> Self {
        Self::TFoot(value)
    }
}
impl Tag<kind::TFoot> {
    /// A table footer row group.
    #[allow(non_upper_case_globals)]
    pub const TFoot: Tag<kind::TFoot> = Tag::new();
}

impl From<Tag<kind::Span>> for TagKind {
    fn from(value: Tag<kind::Span>) -> Self {
        Self::Span(value)
    }
}
impl Tag<kind::Span> {
    /// An inline-level element that does not have a specific meaning.
    #[allow(non_upper_case_globals)]
    pub const Span: Tag<kind::Span> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::InlineQuote>> for TagKind {
    fn from(value: Tag<kind::InlineQuote>) -> Self {
        Self::InlineQuote(value)
    }
}
impl Tag<kind::InlineQuote> {
    /// An inline quotation.
    #[allow(non_upper_case_globals)]
    pub const InlineQuote: Tag<kind::InlineQuote> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Note>> for TagKind {
    fn from(value: Tag<kind::Note>) -> Self {
        Self::Note(value)
    }
}
impl Tag<kind::Note> {
    /// A foot- or endnote, potentially referred to from within the text.
    ///
    /// **Best practice**: It may have a label as a child.
    #[allow(non_upper_case_globals)]
    pub const Note: Tag<kind::Note> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Reference>> for TagKind {
    fn from(value: Tag<kind::Reference>) -> Self {
        Self::Reference(value)
    }
}
impl Tag<kind::Reference> {
    /// A reference to elsewhere in the document.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to a destination in the document, and the second child should consist of
    /// the children that should be associated with that reference.
    #[allow(non_upper_case_globals)]
    pub const Reference: Tag<kind::Reference> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::BibEntry>> for TagKind {
    fn from(value: Tag<kind::BibEntry>) -> Self {
        Self::BibEntry(value)
    }
}
impl Tag<kind::BibEntry> {
    /// A reference to the external source of some cited document.
    ///
    /// **Best practice**: It may have a label as a child.
    #[allow(non_upper_case_globals)]
    pub const BibEntry: Tag<kind::BibEntry> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Code>> for TagKind {
    fn from(value: Tag<kind::Code>) -> Self {
        Self::Code(value)
    }
}
impl Tag<kind::Code> {
    /// Computer code.
    #[allow(non_upper_case_globals)]
    pub const Code: Tag<kind::Code> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Link>> for TagKind {
    fn from(value: Tag<kind::Link>) -> Self {
        Self::Link(value)
    }
}
impl Tag<kind::Link> {
    /// A link.
    ///
    /// **Best practice**: The first child of a tag group with this tag should be a link annotation
    /// linking to an URL, and the second child should consist of the children that should
    /// be associated with that link.
    #[allow(non_upper_case_globals)]
    pub const Link: Tag<kind::Link> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Annot>> for TagKind {
    fn from(value: Tag<kind::Annot>) -> Self {
        Self::Annot(value)
    }
}
impl Tag<kind::Annot> {
    /// An association between an annotation and the content it belongs to. PDF
    ///
    /// **Best practice**: Should be used for all annotations, except for link annotations and
    /// widget annotations. The first child should be the identifier of a non-link annotation,
    /// and all other subsequent children should be content identifiers associated with that
    /// annotation.
    #[allow(non_upper_case_globals)]
    pub const Annot: Tag<kind::Annot> = Tag::new();

    /// The spacing before the block-level element.
    pub fn space_before(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_BEFORE).map(LayoutAttr::unwrap_space_before)
    }

    /// Set the spacing before the block-level element.
    pub fn set_space_before(&mut self, space_before: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_BEFORE, space_before.map(LayoutAttr::SpaceBefore));
    }

    /// Set the spacing before the block-level element.
    pub fn with_space_before(mut self, space_before: Option<f32>) -> Self {
        self.set_space_before(space_before);
        self
    }

    /// The spacing after the block-level element.
    pub fn space_after(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::SPACE_AFTER).map(LayoutAttr::unwrap_space_after)
    }

    /// Set the spacing after the block-level element.
    pub fn set_space_after(&mut self, space_after: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::SPACE_AFTER, space_after.map(LayoutAttr::SpaceAfter));
    }

    /// Set the spacing after the block-level element.
    pub fn with_space_after(mut self, space_after: Option<f32>) -> Self {
        self.set_space_after(space_after);
        self
    }

    /// The spacing between the start inline edge of the element and the parent.
    pub fn start_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::START_INDENT).map(LayoutAttr::unwrap_start_indent)
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn set_start_indent(&mut self, start_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::START_INDENT, start_indent.map(LayoutAttr::StartIndent));
    }

    /// Set the spacing between the start inline edge of the element and the parent.
    pub fn with_start_indent(mut self, start_indent: Option<f32>) -> Self {
        self.set_start_indent(start_indent);
        self
    }

    /// The spacing between the end inline edge of the element and the parent.
    pub fn end_indent(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::END_INDENT).map(LayoutAttr::unwrap_end_indent)
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn set_end_indent(&mut self, end_indent: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::END_INDENT, end_indent.map(LayoutAttr::EndIndent));
    }

    /// Set the spacing between the end inline edge of the element and the parent.
    pub fn with_end_indent(mut self, end_indent: Option<f32>) -> Self {
        self.set_end_indent(end_indent);
        self
    }
}

impl From<Tag<kind::Figure>> for TagKind {
    fn from(value: Tag<kind::Figure>) -> Self {
        Self::Figure(value)
    }
}
impl Tag<kind::Figure> {
    /// Item of graphical content.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    #[allow(non_snake_case)]
    pub fn Figure(alt_text: Option<String>) -> Tag<kind::Figure> {
        let mut tag = Tag::new();
        tag.set_alt_text(alt_text);
        tag
    }

    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn bbox(&self) -> Option<BBox> {
        self.inner.get_layout(LayoutAttr::B_BOX).map(LayoutAttr::unwrap_bbox)
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn set_bbox(&mut self, bbox: Option<BBox>) {
        self.inner.set_or_remove_layout(LayoutAttr::B_BOX, bbox.map(LayoutAttr::BBox));
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn with_bbox(mut self, bbox: Option<BBox>) -> Self {
        self.set_bbox(bbox);
        self
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// Set the width.
    pub fn set_width(&mut self, width: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::WIDTH, width.map(LayoutAttr::Width));
    }

    /// Set the width.
    pub fn with_width(mut self, width: Option<f32>) -> Self {
        self.set_width(width);
        self
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// Set the height.
    pub fn set_height(&mut self, height: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::HEIGHT, height.map(LayoutAttr::Height));
    }

    /// Set the height.
    pub fn with_height(mut self, height: Option<f32>) -> Self {
        self.set_height(height);
        self
    }
}

impl From<Tag<kind::Formula>> for TagKind {
    fn from(value: Tag<kind::Formula>) -> Self {
        Self::Formula(value)
    }
}
impl Tag<kind::Formula> {
    /// A mathematical formula.
    ///
    /// Providing `alt_text` is required in some export modes, like for example PDF/UA-1.
    #[allow(non_snake_case)]
    pub fn Formula(alt_text: Option<String>) -> Tag<kind::Formula> {
        let mut tag = Tag::new();
        tag.set_alt_text(alt_text);
        tag
    }

    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn bbox(&self) -> Option<BBox> {
        self.inner.get_layout(LayoutAttr::B_BOX).map(LayoutAttr::unwrap_bbox)
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn set_bbox(&mut self, bbox: Option<BBox>) {
        self.inner.set_or_remove_layout(LayoutAttr::B_BOX, bbox.map(LayoutAttr::BBox));
    }

    /// Set the bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    pub fn with_bbox(mut self, bbox: Option<BBox>) -> Self {
        self.set_bbox(bbox);
        self
    }

    /// The width.
    pub fn width(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::WIDTH).map(LayoutAttr::unwrap_width)
    }

    /// Set the width.
    pub fn set_width(&mut self, width: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::WIDTH, width.map(LayoutAttr::Width));
    }

    /// Set the width.
    pub fn with_width(mut self, width: Option<f32>) -> Self {
        self.set_width(width);
        self
    }

    /// The height.
    pub fn height(&self) -> Option<f32> {
        self.inner.get_layout(LayoutAttr::HEIGHT).map(LayoutAttr::unwrap_height)
    }

    /// Set the height.
    pub fn set_height(&mut self, height: Option<f32>) {
        self.inner.set_or_remove_layout(LayoutAttr::HEIGHT, height.map(LayoutAttr::Height));
    }

    /// Set the height.
    pub fn with_height(mut self, height: Option<f32>) -> Self {
        self.set_height(height);
        self
    }
}

impl From<Tag<kind::NonStruct>> for TagKind {
    fn from(value: Tag<kind::NonStruct>) -> Self {
        Self::NonStruct(value)
    }
}
impl Tag<kind::NonStruct> {
    /// Non-structural element. A grouping element having no inherent structural significance;
    /// it serves solely for grouping purposes.
    #[allow(non_upper_case_globals)]
    pub const NonStruct: Tag<kind::NonStruct> = Tag::new();
}

impl From<Tag<kind::Datetime>> for TagKind {
    fn from(value: Tag<kind::Datetime>) -> Self {
        Self::Datetime(value)
    }
}
impl Tag<kind::Datetime> {
    /// A date or time.
    #[allow(non_upper_case_globals)]
    pub const Datetime: Tag<kind::Datetime> = Tag::new();
}

impl From<Tag<kind::Terms>> for TagKind {
    fn from(value: Tag<kind::Terms>) -> Self {
        Self::Terms(value)
    }
}
impl Tag<kind::Terms> {
    /// A list of terms.
    #[allow(non_upper_case_globals)]
    pub const Terms: Tag<kind::Terms> = Tag::new();
}

impl From<Tag<kind::Title>> for TagKind {
    fn from(value: Tag<kind::Title>) -> Self {
        Self::Title(value)
    }
}
impl Tag<kind::Title> {
    /// A title.
    #[allow(non_upper_case_globals)]
    pub const Title: Tag<kind::Title> = Tag::new();
}

impl From<Tag<kind::Strong>> for TagKind {
    fn from(value: Tag<kind::Strong>) -> Self {
        Self::Strong(value)
    }
}
impl Tag<kind::Strong> {
    /// Encloses content with strong importance, most commonly **bold** text.
    #[allow(non_upper_case_globals)]
    pub const Strong: Tag<kind::Strong> = Tag::new();
}

impl From<Tag<kind::Em>> for TagKind {
    fn from(value: Tag<kind::Em>) -> Self {
        Self::Em(value)
    }
}
impl Tag<kind::Em> {
    /// Encloses content that is emphasized, most commonly *italic* text.
    #[allow(non_upper_case_globals)]
    pub const Em: Tag<kind::Em> = Tag::new();
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum Attr {
    Struct(StructAttr),
    List(ListAttr),
    Table(TableAttr),
    Layout(LayoutAttr),
}

impl Attr {

        #[inline(always)]
        fn unwrap_struct(&self) -> &StructAttr {
            match self {
                Self::Struct(attr) => attr,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_list(&self) -> &ListAttr {
            match self {
                Self::List(attr) => attr,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_table(&self) -> &TableAttr {
            match self {
                Self::Table(attr) => attr,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_layout(&self) -> &LayoutAttr {
            match self {
                Self::Layout(attr) => attr,
                _ => unreachable!(),
            }
        }
}
impl Ordinal for Attr {
    fn ordinal(&self) -> usize {
        match self {
            Self::Struct(a) => a.ordinal(),
            Self::List(a) => a.ordinal(),
            Self::Table(a) => a.ordinal(),
            Self::Layout(a) => a.ordinal(),
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum StructAttr {
    /// The tag id.
    Id(TagId),
    /// The language of this tag.
    Lang(String),
    /// The optional alternate text that describes the text (for example, if the text
    /// consists of a star symbol, the alt text should describe that in natural language).
    AltText(String),
    /// The expanded form of an abbreviation.
    /// Only applicable if the content of the tag is an abbreviation.
    Expanded(String),
    /// The actual text represented by the content of this tag, i.e. if it contained
    /// some curves that artistically represent some word. This should be the exact
    /// replacement text of the word.
    ActualText(String),
    /// The title, characterizing a specific tag such as `"Chapter 1"`.
    Title(String),
    /// The heading level
    HeadingLevel(NonZeroU16),
}

impl StructAttr {
    pub(crate) const ID: usize = 0;
    pub(crate) const LANG: usize = 1;
    pub(crate) const ALT_TEXT: usize = 2;
    pub(crate) const EXPANDED: usize = 3;
    pub(crate) const ACTUAL_TEXT: usize = 4;
    pub(crate) const TITLE: usize = 5;
    pub(crate) const HEADING_LEVEL: usize = 6;

        #[inline(always)]
        fn unwrap_id(&self) -> &TagId {
            match self {
                Self::Id(val) => val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_lang(&self) -> &str {
            match self {
                Self::Lang(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_alt_text(&self) -> &str {
            match self {
                Self::AltText(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_expanded(&self) -> &str {
            match self {
                Self::Expanded(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_actual_text(&self) -> &str {
            match self {
                Self::ActualText(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_title(&self) -> &str {
            match self {
                Self::Title(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_level(&self) -> NonZeroU16 {
            match self {
                Self::HeadingLevel(val) => *val,
                _ => unreachable!(),
            }
        }
}

impl Ordinal for StructAttr {
    fn ordinal(&self) -> usize {
        match self {
            Self::Id(_) => Self::ID,
            Self::Lang(_) => Self::LANG,
            Self::AltText(_) => Self::ALT_TEXT,
            Self::Expanded(_) => Self::EXPANDED,
            Self::ActualText(_) => Self::ACTUAL_TEXT,
            Self::Title(_) => Self::TITLE,
            Self::HeadingLevel(_) => Self::HEADING_LEVEL,
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum ListAttr {
    /// The list numbering.
    Numbering(ListNumbering),
}

impl ListAttr {
    pub(crate) const NUMBERING: usize = 7;

        #[inline(always)]
        fn unwrap_numbering(&self) -> ListNumbering {
            match self {
                Self::Numbering(val) => *val,
            }
        }
}

impl Ordinal for ListAttr {
    fn ordinal(&self) -> usize {
        match self {
            Self::Numbering(_) => Self::NUMBERING,
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum TableAttr {
    /// The table summary.
    Summary(String),
    /// The table header scope.
    HeaderScope(TableHeaderScope),
    /// The list of headers associated with a table cell.
    /// Table data cells (`TD`) may specify a list of table headers (`TH`),
    /// which can also specify a list of parent header cells (`TH`), and so on.
    /// To determine the list of associated headers this list is recursively
    /// evaluated.
    ///
    /// This allows specifying header hierarchies inside tables.
    CellHeaders(SmallVec<[TagId; 1]>),
    /// The row span of this table cell.
    RowSpan(NonZeroU32),
    /// The column span of this table cell.
    ColSpan(NonZeroU32),
}

impl TableAttr {
    pub(crate) const SUMMARY: usize = 8;
    pub(crate) const HEADER_SCOPE: usize = 9;
    pub(crate) const CELL_HEADERS: usize = 10;
    pub(crate) const ROW_SPAN: usize = 11;
    pub(crate) const COL_SPAN: usize = 12;

        #[inline(always)]
        fn unwrap_summary(&self) -> &str {
            match self {
                Self::Summary(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_scope(&self) -> TableHeaderScope {
            match self {
                Self::HeaderScope(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_headers(&self) -> &[TagId] {
            match self {
                Self::CellHeaders(val) => val.as_ref(),
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_row_span(&self) -> NonZeroU32 {
            match self {
                Self::RowSpan(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_col_span(&self) -> NonZeroU32 {
            match self {
                Self::ColSpan(val) => *val,
                _ => unreachable!(),
            }
        }
}

impl Ordinal for TableAttr {
    fn ordinal(&self) -> usize {
        match self {
            Self::Summary(_) => Self::SUMMARY,
            Self::HeaderScope(_) => Self::HEADER_SCOPE,
            Self::CellHeaders(_) => Self::CELL_HEADERS,
            Self::RowSpan(_) => Self::ROW_SPAN,
            Self::ColSpan(_) => Self::COL_SPAN,
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub(crate) enum LayoutAttr {
    /// The placement.
    Placement(Placement),
    /// The writing mode.
    WritingMode(WritingMode),
    /// The bounding box of a tag that encloses its visible content.
    /// If the content spans multiple pages, this should be omitted.
    BBox(BBox),
    /// The width.
    Width(f32),
    /// The height.
    Height(f32),
    /// The background color.
    BackgroundColor(NaiveRgbColor),
    /// The border color.
    BorderColor(Sides<NaiveRgbColor>),
    /// The way the border is drawn.
    BorderStyle(Sides<BorderStyle>),
    /// The border width.
    BorderThickness(Sides<f32>),
    /// The padding inside of an element.
    Padding(Sides<f32>),
    /// The color of text, borders, and text decorations.
    Color(NaiveRgbColor),
    /// The spacing before the block-level element.
    SpaceBefore(f32),
    /// The spacing after the block-level element.
    SpaceAfter(f32),
    /// The spacing between the start inline edge of the element and the parent.
    StartIndent(f32),
    /// The spacing between the end inline edge of the element and the parent.
    EndIndent(f32),
    /// The amount the first line of text in a block-level element is indented. Only
    /// applicable to paragraph-like elements with non-block-level elements.
    TextIndent(f32),
    /// The text alignment.
    TextAlign(TextAlign),
    /// The alignment of block-level elements inside of this block-level element.
    BlockAlign(BlockAlign),
    /// The alignment of inline-level elements inside of this block-level element.
    InlineAlign(InlineAlign),
    /// The border style of table cells, overriding `BorderStyle`.
    TableBorderStyle(Sides<BorderStyle>),
    /// The padding inside of table cells, overriding `Padding`.
    TablePadding(Sides<f32>),
    /// The distance by which the baseline shall be shifted from the default position.
    BaselineShift(f32),
    /// The height of each line in an element on the block axis.
    LineHeight(LineHeight),
    /// The color of the text decoration, overriding the fill color.
    TextDecorationColor(NaiveRgbColor),
    /// The width of the text decoration line.
    TextDecorationThickness(f32),
    /// The kind of text decoration.
    TextDecorationType(TextDecorationType),
    /// How the glyphs are rotated in a vertical writing mode.
    GlyphOrientationVertical(GlyphOrientationVertical),
    /// The number of columns in the grouping element.
    ColumnCount(NonZeroU32),
    /// The width of the gaps between columns in the grouping element.
    ColumnGap(ColumnDimensions),
    /// The width of the columns in the grouping element.
    ColumnWidths(ColumnDimensions),
}

impl LayoutAttr {
    pub(crate) const PLACEMENT: usize = 13;
    pub(crate) const WRITING_MODE: usize = 14;
    pub(crate) const B_BOX: usize = 15;
    pub(crate) const WIDTH: usize = 16;
    pub(crate) const HEIGHT: usize = 17;
    pub(crate) const BACKGROUND_COLOR: usize = 18;
    pub(crate) const BORDER_COLOR: usize = 19;
    pub(crate) const BORDER_STYLE: usize = 20;
    pub(crate) const BORDER_THICKNESS: usize = 21;
    pub(crate) const PADDING: usize = 22;
    pub(crate) const COLOR: usize = 23;
    pub(crate) const SPACE_BEFORE: usize = 24;
    pub(crate) const SPACE_AFTER: usize = 25;
    pub(crate) const START_INDENT: usize = 26;
    pub(crate) const END_INDENT: usize = 27;
    pub(crate) const TEXT_INDENT: usize = 28;
    pub(crate) const TEXT_ALIGN: usize = 29;
    pub(crate) const BLOCK_ALIGN: usize = 30;
    pub(crate) const INLINE_ALIGN: usize = 31;
    pub(crate) const TABLE_BORDER_STYLE: usize = 32;
    pub(crate) const TABLE_PADDING: usize = 33;
    pub(crate) const BASELINE_SHIFT: usize = 34;
    pub(crate) const LINE_HEIGHT: usize = 35;
    pub(crate) const TEXT_DECORATION_COLOR: usize = 36;
    pub(crate) const TEXT_DECORATION_THICKNESS: usize = 37;
    pub(crate) const TEXT_DECORATION_TYPE: usize = 38;
    pub(crate) const GLYPH_ORIENTATION_VERTICAL: usize = 39;
    pub(crate) const COLUMN_COUNT: usize = 40;
    pub(crate) const COLUMN_GAP: usize = 41;
    pub(crate) const COLUMN_WIDTHS: usize = 42;

        #[inline(always)]
        fn unwrap_placement(&self) -> Placement {
            match self {
                Self::Placement(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_writing_mode(&self) -> WritingMode {
            match self {
                Self::WritingMode(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_bbox(&self) -> BBox {
            match self {
                Self::BBox(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_width(&self) -> f32 {
            match self {
                Self::Width(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_height(&self) -> f32 {
            match self {
                Self::Height(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_background_color(&self) -> NaiveRgbColor {
            match self {
                Self::BackgroundColor(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_border_color(&self) -> Sides<NaiveRgbColor> {
            match self {
                Self::BorderColor(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_border_style(&self) -> Sides<BorderStyle> {
            match self {
                Self::BorderStyle(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_border_thickness(&self) -> Sides<f32> {
            match self {
                Self::BorderThickness(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_padding(&self) -> Sides<f32> {
            match self {
                Self::Padding(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_color(&self) -> NaiveRgbColor {
            match self {
                Self::Color(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_space_before(&self) -> f32 {
            match self {
                Self::SpaceBefore(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_space_after(&self) -> f32 {
            match self {
                Self::SpaceAfter(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_start_indent(&self) -> f32 {
            match self {
                Self::StartIndent(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_end_indent(&self) -> f32 {
            match self {
                Self::EndIndent(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_text_indent(&self) -> f32 {
            match self {
                Self::TextIndent(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_text_align(&self) -> TextAlign {
            match self {
                Self::TextAlign(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_block_align(&self) -> BlockAlign {
            match self {
                Self::BlockAlign(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_inline_align(&self) -> InlineAlign {
            match self {
                Self::InlineAlign(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_table_border_style(&self) -> Sides<BorderStyle> {
            match self {
                Self::TableBorderStyle(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_table_padding(&self) -> Sides<f32> {
            match self {
                Self::TablePadding(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_baseline_shift(&self) -> f32 {
            match self {
                Self::BaselineShift(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_line_height(&self) -> LineHeight {
            match self {
                Self::LineHeight(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_text_decoration_color(&self) -> NaiveRgbColor {
            match self {
                Self::TextDecorationColor(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_text_decoration_thickness(&self) -> f32 {
            match self {
                Self::TextDecorationThickness(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_text_decoration_type(&self) -> TextDecorationType {
            match self {
                Self::TextDecorationType(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_glyph_orientation_vertical(&self) -> GlyphOrientationVertical {
            match self {
                Self::GlyphOrientationVertical(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_column_count(&self) -> NonZeroU32 {
            match self {
                Self::ColumnCount(val) => *val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_column_gap(&self) -> &ColumnDimensions {
            match self {
                Self::ColumnGap(val) => val,
                _ => unreachable!(),
            }
        }

        #[inline(always)]
        fn unwrap_column_widths(&self) -> &ColumnDimensions {
            match self {
                Self::ColumnWidths(val) => val,
                _ => unreachable!(),
            }
        }
}

impl Ordinal for LayoutAttr {
    fn ordinal(&self) -> usize {
        match self {
            Self::Placement(_) => Self::PLACEMENT,
            Self::WritingMode(_) => Self::WRITING_MODE,
            Self::BBox(_) => Self::B_BOX,
            Self::Width(_) => Self::WIDTH,
            Self::Height(_) => Self::HEIGHT,
            Self::BackgroundColor(_) => Self::BACKGROUND_COLOR,
            Self::BorderColor(_) => Self::BORDER_COLOR,
            Self::BorderStyle(_) => Self::BORDER_STYLE,
            Self::BorderThickness(_) => Self::BORDER_THICKNESS,
            Self::Padding(_) => Self::PADDING,
            Self::Color(_) => Self::COLOR,
            Self::SpaceBefore(_) => Self::SPACE_BEFORE,
            Self::SpaceAfter(_) => Self::SPACE_AFTER,
            Self::StartIndent(_) => Self::START_INDENT,
            Self::EndIndent(_) => Self::END_INDENT,
            Self::TextIndent(_) => Self::TEXT_INDENT,
            Self::TextAlign(_) => Self::TEXT_ALIGN,
            Self::BlockAlign(_) => Self::BLOCK_ALIGN,
            Self::InlineAlign(_) => Self::INLINE_ALIGN,
            Self::TableBorderStyle(_) => Self::TABLE_BORDER_STYLE,
            Self::TablePadding(_) => Self::TABLE_PADDING,
            Self::BaselineShift(_) => Self::BASELINE_SHIFT,
            Self::LineHeight(_) => Self::LINE_HEIGHT,
            Self::TextDecorationColor(_) => Self::TEXT_DECORATION_COLOR,
            Self::TextDecorationThickness(_) => Self::TEXT_DECORATION_THICKNESS,
            Self::TextDecorationType(_) => Self::TEXT_DECORATION_TYPE,
            Self::GlyphOrientationVertical(_) => Self::GLYPH_ORIENTATION_VERTICAL,
            Self::ColumnCount(_) => Self::COLUMN_COUNT,
            Self::ColumnGap(_) => Self::COLUMN_GAP,
            Self::ColumnWidths(_) => Self::COLUMN_WIDTHS,
        }
    }
}

