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}