Repository navigation
Markdown tables: preserve sizing hints and support richer grid-table layout #5738
Description
Problem
The Markdig audit in #5737 found table features that parse correctly upstream but cannot be represented faithfully by Terminal.Gui's current TableData / MarkdownTable layout model.
- Markdig's
PipeTableOptions.InferColumnWidthsFromSeparator(available since 0.41.0) computes percentage widths inTableColumnDefinition.Width. Terminal.Gui drops those hints and chooses widths from content alone. - Grid tables can have no header, multiple header rows, column spans, row spans, and block content inside a cell. Terminal.Gui currently promotes the first row to a header and represents each cell as inline text.
- The current height, border, hit-testing, and selection calculations assume one header row and one independent rectangular cell per column.
The changes in #5737 address inline fidelity and alert labels. They deliberately leave sizing policy and richer table geometry for this issue.
Goal
Render Markdig table structure faithfully while keeping ordinary pipe tables and standalone MarkdownTable use compatible. Define predictable behavior when requested proportions or cell contents cannot fit a narrow terminal.
Examples
Optional inferred widths
MarkdownPipeline pipeline = new MarkdownPipelineBuilder ()
.UsePipeTables (new PipeTableOptions { InferColumnWidthsFromSeparator = true })
.Build ();| Short | Description |
| ----- | -------------------- |
| A | B |The separator expresses a 1:4 width preference. Currently those hints never reach table layout. Decide how preferences interact with available content width, cell padding, borders, minimum widths, rounding, and overflow. Keep the existing content-driven behavior when no widths are specified.
Grid table with an explicit header and multiline cells
+-----------+-------------------+
| Name | Description |
+===========+===================+
| Markdig | A fast, powerful |
| | Markdown parser. |
+-----------+-------------------+Grid table with a spanning cell
+-------+-------+
| A | B |
+=======+=======+
| Cell spanning |
+-------+-------+Headerless grid table
+-------+-------+
| A | B |
+-------+-------+
| C | D |
+-------+-------+Markdig identifies the header status; the first row must not automatically become a styled header.
Scope
- Preserve optional column width hints, row header status, cell coordinates,
ColumnSpan,RowSpan, and cell block content when lowering the Markdig AST. - Design the table data model. Preserve existing
TableDataconstructors and standaloneMarkdownTablebehavior where practical. Avoid exposing Markdig-specific AST types in Terminal.Gui's public API without an explicit compatibility decision. - Specify natural widths, preferred proportions, minimum/maximum widths, border/padding accounting, deterministic rounding, narrow-terminal overflow, and resizing behavior.
- Lay out headerless and multiple-header-row tables, row/column spans, and multiline cells containing paragraphs, hard breaks, lists, and code blocks.
- Draw borders without internal separators through spanning cells; preserve correct intersections at mixed spans and header boundaries.
- Keep link navigation, keyboard activation, mouse hit testing, selection, scrolling, clipboard output, and ANSI rendering aligned with the actual cell rectangles.
- Apply the same geometry and width calculations during measurement, rendering, and hit testing. Support Unicode graphemes, combining sequences, CJK, and emoji display widths.
Acceptance criteria
- With inferred widths enabled, a 1:4 separator preference affects rendered column widths according to a documented allocation rule, within deterministic integer-cell rounding.
- Without width hints, existing ordinary pipe-table layout tests continue to pass.
- Zero/unspecified width hints, partial hints, widths that cannot satisfy minimums, and terminal widths below the normal minimum have documented, tested outcomes without negative sizes, exceptions, or infinite loops.
- Resizing narrow → wide → narrow recomputes widths, row heights, borders, content size, and link regions consistently.
- Headerless grid tables retain every data row without synthetic header styling or a synthetic header separator.
- Explicit header boundaries and multiple header rows follow the AST rather than row position assumptions.
- Representative row spans, column spans, and mixed spans render correct borders and preserve every cell's content.
- Paragraphs, explicit line breaks, lists, and code inside grid cells retain their structure and have correct row heights.
- Links in wrapped, aligned, and spanning cells activate the original URL with both keyboard and mouse input.
- Selection/copy over partial cells, spans, headers, and complete tables has a documented representation and does not duplicate or drop content.
- ANSI output and on-screen rendering agree on cell positions and text. Grapheme-aware width tests cover CJK, combining sequences, and ZWJ emoji.
- Existing constructors and standalone table use remain covered; intentional compatibility changes are documented.
- Native AOT smoke coverage exercises representative proportional, headerless, and spanning tables without new unsuppressed trim/AOT warnings.
- Add UICatalog examples plus a
tuirecrecording; inspect the cast and rendered output at more than one terminal width.
Implementation pointers
Terminal.Gui/Views/Markdown/MarkdownView.Parsing.cs:HandleTableBlock, AST lowering and header/row classification.Terminal.Gui/Views/Markdown/TableData.cs: current public table model.Terminal.Gui/Views/Markdown/MarkdownTable.cs:ComputeColumnWidths,Recalculate, row heights,DrawBorders,DrawWrappedRow,HitTestLinkRegion, andBuildLinkRegions.Terminal.Gui/Views/Markdown/MarkdownView.Layout.cs: table SubView placement and placeholder rows.Terminal.Gui/Views/Markdown/MarkdownView.Selection.cs: table reconstruction and selection mapping.- Existing Markdown table, selection, ANSI rendering, and dependency regression tests;
Tests/NativeAotSmoke/MarkdownSmokeTests.cs.
Reuse the structured inline-cell lowering added by #5737. Preserve parsed display content through measurement and rendering rather than serializing and reparsing it.
References and dependencies
- Update Markdig to 1.4.2, fix Markdown rendering, and test Native AOT #5737: dependency update, inline fidelity, alerts, AOT tests, and audit.
- Markdig table documentation.
- Markdig column width option.
- Markdig table cell model.
Deferred decisions
Choose the public representation and exact sizing/overflow policy before implementing the larger geometry change. Source-to-preview navigation, general Markdown editing, default pipeline changes, and HTML/KaTeX/Mermaid rendering are outside this issue.
This is follow-up work; #5737 can land without it.
Activity