1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::{MathIdentifier, MathML};
use std::{
    collections::BTreeMap,
    fmt::{Display, Formatter},
};

mod constructors;
mod display;

/// <https://developer.mozilla.org/en-US/docs/Web/MathML/Element/math>
#[derive(Debug, Clone, PartialEq)]
pub struct MathRoot {
    children: Vec<MathML>,
    attributes: BTreeMap<String, String>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct MathFunction {
    name: String,
    body: Vec<MathML>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct MathRow {
    children: Vec<MathML>,
    has_grouping: bool,
}

/// The [`<mphantom>`](https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mphantom) element is rendered invisibly, but dimensions (such as height, width, and baseline position) are still kept.
#[derive(Debug, Clone, PartialEq)]
pub struct MathPhantom {
    inner: MathML,
}

#[derive(Debug, Clone, PartialEq)]
pub struct MathTable {
    stream: Vec<MathML>,
    attributes: BTreeMap<String, String>,
}

impl MathTable {
    pub fn matrix<I>(stream: I) -> Self
    where
        I: IntoIterator<Item = MathML>,
    {
        Self { stream: stream.into_iter().collect(), attributes: BTreeMap::new() }
    }
    pub fn add_attribute(&mut self, key: &str, value: &str) {
        self.attributes.insert(key.to_string(), value.to_string());
    }
    pub fn get_attributes(&self) -> &BTreeMap<String, String> {
        &self.attributes
    }
    pub fn mut_attributes(&mut self) -> &mut BTreeMap<String, String> {
        &mut self.attributes
    }
}

impl Display for MathTable {
    // let mut mathml = format!("<mtable{}><mtr><mtd>", columnalign);
    // for (i, node) in content.iter().enumerate() {
    //     match node {
    //         MathML::NewLine => {
    //             mathml.push_str("</mtd></mtr>");
    //             if i < content.len() {
    //                 mathml.push_str("<mtr><mtd>")
    //             }
    //         }
    //         MathML::Ampersand => {
    //             mathml.push_str("</mtd>");
    //             if i < content.len() {
    //                 mathml.push_str("<mtd>")
    //             }
    //         }
    //         node => {
    //             mathml = format!("{}{}", mathml, node);
    //         }
    //     }
    // }
    // mathml.push_str("</mtd></mtr></mtable>");
    //
    // write!(f, "{}", mathml)
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("<mtable")?;
        for (key, value) in &self.attributes {
            write!(f, " {}=\"{}\"", key, value)?;
        }
        f.write_str(">")?;
        f.write_str("<mtr><mtd>")?;
        for (i, node) in self.stream.iter().enumerate() {
            match node {
                MathML::NewLine => {
                    f.write_str("</mtd></mtr>")?;
                    if i < self.stream.len() {
                        f.write_str("<mtr><mtd>")?;
                    }
                }
                MathML::Ampersand => {
                    f.write_str("</mtd>")?;
                    if i < self.stream.len() {
                        f.write_str("<mtd>")?;
                    }
                }
                _ => {
                    write!(f, "{}", node)?;
                }
            }
        }
        f.write_str("</mtd></mtr>")?;
        f.write_str("</mtable>")
    }
}