1#![doc = include_str!("../README.md")]
2
3use {
4    anyhow::Result,
5    gstring::*,
6    pulldown_cmark::{self as pd, Alignment},
7    std::fmt::Write,
8};
9
10pub fn process(input: &str) -> Result<String> {
12    let mut s = String::new();
13
14    let mut table = vec![];
16    let mut align = None;
17    let mut widths = vec![];
18    let mut column = 0;
19    let mut depth = 0;
20
21    for (event, range) in pd::Parser::new_ext(input, pd::Options::all()).into_offset_iter() {
23        let source = &input[range.clone()];
24
25        match event {
26            pd::Event::Start(pd::Tag::Table(a)) => {
27                table = vec![];
29                align = Some(a);
30                widths = vec![];
31                column = 0;
32                depth += 1;
33            }
34            pd::Event::Start(pd::Tag::TableHead) | pd::Event::Start(pd::Tag::TableRow) => {
35                table.push(vec![]);
37            }
38            pd::Event::Start(pd::Tag::TableCell) => {
39                let row = table.last_mut().unwrap();
41                row.push(GString::new());
42                column += 1;
43                if widths.len() < column {
44                    widths.push(2);
45                }
46            }
47            pd::Event::Start(_) => {
48                depth += 1;
49            }
50            pd::Event::End(pd::TagEnd::TableCell) => {
51                let row = table.last_mut().unwrap();
52                let cell = row.last_mut().unwrap();
53                let source = source.trim();
54                cell.push(source);
55                let i = column - 1;
56                widths[i] = widths[i].max(source.len());
57            }
58            pd::Event::End(pd::TagEnd::TableHead) | pd::Event::End(pd::TagEnd::TableRow) => {
59                column = 0;
61            }
62            pd::Event::End(pd::TagEnd::Table) => {
63                depth -= 1;
65
66                for (r, row) in table.iter().enumerate() {
68                    for (col, cell) in row.iter().enumerate() {
70                        let a = if col == 0 { "|" } else { "" };
72                        match align.as_ref().unwrap()[col] {
73                            Alignment::None => {
74                                write!(&mut s, "{a} {:1$} |", cell.to_string(), widths[col])?;
75                            }
76                            Alignment::Left => {
77                                write!(&mut s, "{a} {:<1$} |", cell.to_string(), widths[col])?;
78                            }
79                            Alignment::Right => {
80                                write!(&mut s, "{a} {:>1$} |", cell.to_string(), widths[col])?;
81                            }
82                            Alignment::Center => {
83                                write!(&mut s, "{a} {:^1$} |", cell.to_string(), widths[col])?;
84                            }
85                        }
86                    }
87
88                    if r == 0 {
89                        writeln!(
91                            &mut s,
92                            "\n|{}|",
93                            widths
94                                .iter()
95                                .enumerate()
96                                .map(|(col, width)| {
97                                    let (a, b) = match align.as_ref().unwrap()[col] {
98                                        Alignment::None => ('-', '-'),
99                                        Alignment::Left => (':', '-'),
100                                        Alignment::Right => ('-', ':'),
101                                        Alignment::Center => (':', ':'),
102                                    };
103                                    format!("{a}{}{b}", "-".repeat(*width))
104                                })
105                                .collect::<Vec<_>>()
106                                .join("|"),
107                        )?;
108                    } else {
109                        writeln!(&mut s)?;
111                    }
112                }
113
114                writeln!(&mut s)?;
115            }
116            pd::Event::End(_) => {
117                depth -= 1;
118
119                if depth == 0 {
120                    write!(&mut s, "{}\n\n", source.trim_end())?;
121                }
122            }
123            _ => {}
124        }
125    }
126
127    Ok(s)
128}