diff --git a/ConsoleMarkdownRenderer.Tests/RendererTests.cs b/ConsoleMarkdownRenderer.Tests/RendererTests.cs index c32f14c..e6eade8 100644 --- a/ConsoleMarkdownRenderer.Tests/RendererTests.cs +++ b/ConsoleMarkdownRenderer.Tests/RendererTests.cs @@ -375,6 +375,49 @@ public void RendererTests_AutolinkTest(int index, string expectedContent, string Assert.IsFalse(link.IsImage, $"IsImage should be false at index {index}"); } + [TestMethod] + public void RendererTests_TableColumnAlignment_HonorsMarkdownAlignment() + { + // Pipe-table column alignment specified in Markdown (`:---`, `:---:`, `---:`) should + // be reflected in the Spectre.Console TableColumn.Alignment of the rendered table. + const string markdown = "| left | center | right |\n| :--- | :----: | ----: |\n| a | b | c |\n"; + + var document = Markdown.Parse(markdown, MarkdownDisplayer.DefaultPipeline); + var renderer = new ConsoleRenderer(new DisplayOptions()); + renderer.Render(document); + + Assert.IsNotNull(renderer.Root); + // Root is an outer wrapper Table whose single cell holds the rendered table. + var outer = (Table)renderer.Root; + var inner = (Table)outer.Rows.First().First(); + + Assert.AreEqual(3, inner.Columns.Count, "Expected three table columns"); + Assert.AreEqual(Justify.Left, inner.Columns[0].Alignment, "First column should be left-aligned"); + Assert.AreEqual(Justify.Center, inner.Columns[1].Alignment, "Second column should be center-aligned"); + Assert.AreEqual(Justify.Right, inner.Columns[2].Alignment, "Third column should be right-aligned"); + } + + [TestMethod] + public void RendererTests_TableColumnAlignment_DefaultsToLeftWhenUnspecified() + { + // When no alignment is specified (`---`), columns should default to left-aligned. + const string markdown = "| a | b | c |\n| - | - | - |\n| 1 | 2 | 3 |\n"; + + var document = Markdown.Parse(markdown, MarkdownDisplayer.DefaultPipeline); + var renderer = new ConsoleRenderer(new DisplayOptions()); + renderer.Render(document); + + Assert.IsNotNull(renderer.Root); + var outer = (Table)renderer.Root; + var inner = (Table)outer.Rows.First().First(); + + Assert.AreEqual(3, inner.Columns.Count); + foreach (var column in inner.Columns) + { + Assert.AreEqual(Justify.Left, column.Alignment, "Unspecified alignment should default to left"); + } + } + [TestMethod] public void RendererTests_TerminalHyperlinks_DefaultEnabled() { diff --git a/ConsoleMarkdownRenderer.Tests/resources/table.txt b/ConsoleMarkdownRenderer.Tests/resources/table.txt index 144bbff..04c7ad0 100644 --- a/ConsoleMarkdownRenderer.Tests/resources/table.txt +++ b/ConsoleMarkdownRenderer.Tests/resources/table.txt @@ -4,14 +4,14 @@ │ │ │ header 1 │ │ │ header 2 │ │ │ header 3 │ │ │ │ │ └──────────┘ │ └──────────┘ │ └──────────┘ │ │ │ ├──────────────┼──────────────┼──────────────┤ │ -│ │ ┌───┐ │ ┌───┐ │ ┌───┐ │ │ -│ │ │ 1 │ │ │ 2 │ │ │ 3 │ │ │ -│ │ └───┘ │ └───┘ │ └───┘ │ │ -│ │ ┌───┐ │ ┌───┐ │ ┌───┐ │ │ -│ │ │ 4 │ │ │ 5 │ │ │ 6 │ │ │ -│ │ └───┘ │ └───┘ │ └───┘ │ │ -│ │ ┌───┐ │ ┌───┐ │ ┌───┐ │ │ -│ │ │ 7 │ │ │ 8 │ │ │ 9 │ │ │ -│ │ └───┘ │ └───┘ │ └───┘ │ │ +│ │ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │ │ +│ │ │ 1 │ │ │ 2 │ │ │ 3 │ │ │ +│ │ └──────────┘ │ └──────────┘ │ └──────────┘ │ │ +│ │ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │ │ +│ │ │ 4 │ │ │ 5 │ │ │ 6 │ │ │ +│ │ └──────────┘ │ └──────────┘ │ └──────────┘ │ │ +│ │ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │ │ +│ │ │ 7 │ │ │ 8 │ │ │ 9 │ │ │ +│ │ └──────────┘ │ └──────────┘ │ └──────────┘ │ │ │ └──────────────┴──────────────┴──────────────┘ │ └────────────────────────────────────────────────┘ diff --git a/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.md b/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.md new file mode 100644 index 0000000..f677c3d --- /dev/null +++ b/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.md @@ -0,0 +1,4 @@ +| left | center | right | +| :--- | :----: | ----: | +| a | b | c | +| dd | ee | ff | diff --git a/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.txt b/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.txt new file mode 100644 index 0000000..fe73f01 --- /dev/null +++ b/ConsoleMarkdownRenderer.Tests/resources/tableAlignment.txt @@ -0,0 +1,14 @@ +┌───────────────────────────────────────┐ +│ ┌──────────┬────────────┬───────────┐ │ +│ │ ┌──────┐ │ ┌────────┐ │ ┌───────┐ │ │ +│ │ │ left │ │ │ center │ │ │ right │ │ │ +│ │ └──────┘ │ └────────┘ │ └───────┘ │ │ +│ ├──────────┼────────────┼───────────┤ │ +│ │ ┌──────┐ │ ┌────────┐ │ ┌───────┐ │ │ +│ │ │ a │ │ │ b │ │ │ c │ │ │ +│ │ └──────┘ │ └────────┘ │ └───────┘ │ │ +│ │ ┌──────┐ │ ┌────────┐ │ ┌───────┐ │ │ +│ │ │ dd │ │ │ ee │ │ │ ff │ │ │ +│ │ └──────┘ │ └────────┘ │ └───────┘ │ │ +│ └──────────┴────────────┴───────────┘ │ +└───────────────────────────────────────┘ diff --git a/ObjectRenderers/Frames/ConsoleRendererBase.TableFrame.cs b/ObjectRenderers/Frames/ConsoleRendererBase.TableFrame.cs index 914e14c..6192ea7 100644 --- a/ObjectRenderers/Frames/ConsoleRendererBase.TableFrame.cs +++ b/ObjectRenderers/Frames/ConsoleRendererBase.TableFrame.cs @@ -2,6 +2,8 @@ using Spectre.Console; using Spectre.Console.Rendering; +using Markdig.Extensions.Tables; + using MDTable = Markdig.Extensions.Tables.Table; using MDTableRow = Markdig.Extensions.Tables.TableRow; @@ -29,6 +31,20 @@ public TableFrame(MDTable mdTable) public void AddCell(IRenderable data) { + // The data is the cell's frame Table (created by NewFrameImplementation in + // StartTableCellImplementation). To make the parent column's alignment + // visible we expand the inner frame Table to fill the parent column and + // apply the matching Justify to its single column — Spectre.Console only + // honors TableColumn.Alignment on Markup-like cell content and ignores it + // for nested Table renderables. + if (data is Spectre.Console.Table cellTable + && m_pos < MDTable.ColumnDefinitions.Count + && cellTable.Columns.Count > 0) + { + cellTable.Expand = true; + cellTable.Columns[0].Alignment = ToJustify(MDTable.ColumnDefinitions[m_pos].Alignment); + } + m_columnData[m_pos] = data; m_pos++; } @@ -39,7 +55,12 @@ public override void AddRow(IRenderable data) { for (int i = 0; i < m_columnData.Length; i++) { - Table.AddColumn(new TableColumn(m_columnData[i])); + var column = new TableColumn(m_columnData[i]); + if (i < MDTable.ColumnDefinitions.Count) + { + column.Alignment = ToJustify(MDTable.ColumnDefinitions[i].Alignment); + } + Table.AddColumn(column); } m_addedColumns = true; } @@ -54,6 +75,13 @@ public override void AddRow(IRenderable data) m_pos = 0; } + private static Justify ToJustify(TableColumnAlign? alignment) => alignment switch + { + TableColumnAlign.Center => Justify.Center, + TableColumnAlign.Right => Justify.Right, + _ => Justify.Left, + }; + private bool m_addedColumns; private readonly IRenderable[] m_columnData; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 2a6f9d8..be2df9a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -3,6 +3,22 @@ ## Upcoming Changes ### :art: Renderers :art: +- [#143](https://github.com/boxofyellow/ConsoleMarkdownRenderer/pull/143): Honor Markdown pipe-table column alignment in ConsoleTableRenderer + - ``` markdown + | left | center | right | + | :--- | :----: | ----: | + | a | b | c | + | dd | ee | ff | + ``` + - Render + | left | center | right | + | :--- | :----: | ----: | + | a | b | c | + | dd | ee | ff | + - Before + Image + - After + Image - [#132](https://github.com/boxofyellow/ConsoleMarkdownRenderer/pull/132): Render Markdig CustomContainer admonition blocks - ```markdown :::note