diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 209ecea..67fed45 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -15,10 +15,10 @@ jobs: run: cargo clippy -- -Dwarnings - name: Check all features pulldown - run: cargo check --no-default-features --features pulldown_cmark,better_syntax_highlighting,load-images,svg,fetch + run: cargo check --no-default-features --features pulldown_cmark,better_syntax_highlighting - name: Check all features comrak - run: cargo check --no-default-features --features comrak,better_syntax_highlighting,load-images,svg,fetch + run: cargo check --no-default-features --features comrak,better_syntax_highlighting - name: Cargo fmt run: cargo fmt --check -q diff --git a/CHANGELOG.md b/CHANGELOG.md index 16ef56b..135d96d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- A single table cell split into multiple cells ([#35](https://github.com/lampsitter/egui_commonmark/pull/35)) + ## 0.13.0 - 2024-02-20 ### Added diff --git a/examples/book.rs b/examples/book.rs index 2d05f5b..548e34c 100644 --- a/examples/book.rs +++ b/examples/book.rs @@ -124,6 +124,10 @@ fn main() { name: "Block Quotes ".to_owned(), content: include_str!("markdown/blockquotes.md").to_owned(), }, + Page { + name: "Tables ".to_owned(), + content: include_str!("markdown/tables.md").to_owned(), + }, ], }) }), diff --git a/examples/markdown/tables.md b/examples/markdown/tables.md new file mode 100644 index 0000000..f41bbe5 --- /dev/null +++ b/examples/markdown/tables.md @@ -0,0 +1,9 @@ +# Tables + +Column A | Column B +-----------|---------- +`item` `a1` | item b1 +item a2 | item b2 +item a3 | item b3 +item a4 | item b4 + diff --git a/src/parsers/pulldown.rs b/src/parsers/pulldown.rs index feaf71d..0c12a3e 100644 --- a/src/parsers/pulldown.rs +++ b/src/parsers/pulldown.rs @@ -38,6 +38,56 @@ fn delayed_events<'e>( } } +type Column<'e> = Vec>; +type Row<'e> = Vec>; + +struct Table<'e> { + header: Row<'e>, + rows: Vec>, +} + +fn parse_row<'e>(events: &mut impl Iterator>) -> Vec> { + let mut row = Vec::new(); + let mut column = Vec::new(); + + for e in events.by_ref() { + if let pulldown_cmark::Event::End(pulldown_cmark::TagEnd::TableCell) = e { + row.push(column); + column = Vec::new(); + } + + if let pulldown_cmark::Event::End(pulldown_cmark::TagEnd::TableHead) = e { + break; + } + + if let pulldown_cmark::Event::End(pulldown_cmark::TagEnd::TableRow) = e { + break; + } + + column.push(e); + } + + row +} + +fn parse_table<'e>( + events: &mut impl Iterator)>, +) -> Table<'e> { + let mut all_events = delayed_events(events, pulldown_cmark::TagEnd::Table) + .into_iter() + .peekable(); + + let header = parse_row(&mut all_events); + + let mut rows = Vec::new(); + while all_events.peek().is_some() { + let row = parse_row(&mut all_events); + rows.push(row); + } + + Table { header, rows } +} + /// try to parse events as an alert quote block. This ill modify the events /// to remove the parsed text that should not be rendered. /// Assumes that the first element is a Paragraph @@ -352,21 +402,40 @@ impl CommonMarkViewerInternal { if self.is_table { newline(ui); + let id = self.source_id.with(self.curr_table); + self.curr_table += 1; + egui::Frame::group(ui.style()).show(ui, |ui| { - let id = self.source_id.with(self.curr_table); - self.curr_table += 1; + let Table { header, rows } = parse_table(events); + egui::Grid::new(id).striped(true).show(ui, |ui| { - while self.is_table { - if let Some((_, e)) = events.next() { - self.should_insert_newline = false; - self.event(ui, e, cache, options, max_width); - } else { - break; + for col in header { + ui.horizontal(|ui| { + for e in col { + self.should_insert_newline = false; + self.event(ui, e, cache, options, max_width); + } + }); + } + + ui.end_row(); + + for row in rows { + for col in row { + ui.horizontal(|ui| { + for e in col { + self.should_insert_newline = false; + self.event(ui, e, cache, options, max_width); + } + }); } + + ui.end_row(); } }); }); + self.is_table = false; self.should_insert_newline = true; newline(ui); } @@ -532,15 +601,9 @@ impl CommonMarkViewerInternal { } pulldown_cmark::TagEnd::Item => {} pulldown_cmark::TagEnd::FootnoteDefinition => {} - pulldown_cmark::TagEnd::Table => { - self.is_table = false; - } - pulldown_cmark::TagEnd::TableHead => { - ui.end_row(); - } - pulldown_cmark::TagEnd::TableRow => { - ui.end_row(); - } + pulldown_cmark::TagEnd::Table => {} + pulldown_cmark::TagEnd::TableHead => {} + pulldown_cmark::TagEnd::TableRow => {} pulldown_cmark::TagEnd::TableCell => { // Ensure space between cells ui.label(" ");