Skip to content

Rich table cells: [[LISTTABLE]] with lists, header rows, merged cells and diagrams - #219

Merged
markbac merged 4 commits into
mainfrom
claude/hopeful-galileo-qo0735
Nov 5, 2026
Merged

markbac merged 4 commits into
mainfrom
claude/hopeful-galileo-qo0735

Conversation

@markbac

@markbac markbac commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Closes #218.

What it does

[[LISTTABLE]] tables hold what a pipe table cannot: several paragraphs, bullet and numbered lists, merged cells and blocks such as diagrams in a cell.

[[LISTTABLE: header, widths=8,52,40]]
| Step | What to do | Check |
| 1 | Fit the batteries.<br>Before you go:<br>- Firmware is current<br>  - and signed | Light flashes green. |
| 2 | Pair the node:<br>1. Hold the button.<br>2. Choose it in the app. | ^ |
| 3 | The first reading:<br>[[BLOCK: reading]] | < |

[[BLOCK: reading]]
```dot
digraph reading { rankdir=LR; Sensor -> Gateway -> Broker; }
```
[[ENDBLOCK]]
  • <br> starts a paragraph, - a bullet, 1. a numbered item, and two spaces nest an item.
  • < merges with the cell on the left, ^ with the cell above.
  • header makes row 1 the header row; widths= sets relative column widths.
  • [[BLOCK: name]] puts a diagram, picture or code from elsewhere in the same file into a cell, without a caption.

How

  • Conversion (listtable.py, driven by directives.py): each table becomes a pandoc grid table, with row and column spans, while each file's directives are expanded. It runs after conditions and variables and before diagrams, so warnings name the right file and line inside includes. A wrapped word that looks like a list marker is escaped.
  • listtable.lua (all formats and sites): moves block contents into their cells, without figure captions. In Word it adds a hidden bookmark so the finishing step knows a rich table.
  • Word finishing (docx_post.py, docx_finish.py):
    • Rich and headerless tables keep pandoc's widths in a fixed layout, and their body rows may split across pages.
    • Only a real header row is formatted and repeated.
    • Pictures are made no wider than their cell.
    • Ordinary tables are unchanged.
  • docxcompose bug, worked around: when merging into the template, docxcompose gave every list in one table the same numbering, so numbered items showed as bullets. Lists are now added one at a time.
  • Import (docx_import.py): a Word table with paragraphs or lists in cells, merged cells or no header row imports as [[LISTTABLE]] with its widths. Other tables still import as pipe tables.
  • Lint and check:
    • Table and block mistakes are directive problems.
    • Lint reads each cell paragraph as separate prose.
    • A caption before the marker counts.
    • Pictures and diagrams in blocks need no caption.
  • Build report: a rich_tables count per source (schema updated).
  • VS Code extension 2.2.0: highlights py-doc directives and {{variables}} in Markdown.
  • CI: the tool-image workflow also runs on pandoc-code changes and checks the example's rich table in a Word build made with the image's pandoc.
  • Docs: user guide (writing, writing documents, import, lint, projects), architecture, requirements FR-029 and FR-064 with traceability, README, and an example guide table that uses every feature.

Testing

  • python -m pytest: 1961 passed, 29 skipped (pandoc 3.1.3 and Graphviz on the host).
  • ruff check ., ruff format --check ., py-doc lint docs --strict, and cd examples && py-doc lint docs poster --strict are clean.
  • cd editors/vscode && npm run lint && npm test: 18 passed.
  • I built the example guide to Word and viewed it through LibreOffice. Merges, nested and numbered lists, and the diagram in its cell all render correctly.

Still to check by hand in Word

  • A tall row splitting across a page (T-09).
  • The highlight character styles, which LibreOffice does not draw.
  • Header-row shading: header rows look blank in LibreOffice for ordinary tables too, so this predates the change.
  • The Word build with pandoc 3.8 runs in the tool-image workflow, not locally.

Generated by Claude Code

[[LISTTABLE]] (optionally with widths=a,b,c) followed by | ... | rows
becomes a headerless pandoc grid table after includes, conditions and
variables, so cells hold several paragraphs (<br>) and bullet lists
(- ). Markers in code are left alone; a row with the wrong number of
cells or a marker with no rows is a warning naming the file and line.

Word table formatting now reads the header row from w:tblLook (or
w:tblHeader). A headerless table keeps its style, centring and width,
but gets a fixed layout on pandoc's column widths, no header
formatting, and rows that may break across pages. Lint reads each cell
paragraph as prose of its own and accepts a caption before the marker.

Documented in the writing guides, requirements (FR-029) and README;
the example guide has a commissioning table, and the example templates
have Highlight Yellow and Highlight Grey character styles.

Refs #218

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHtcxeRPPmXcydfxoEHGJ4
[[LISTTABLE]] now takes `header` for a header row, numbered items
(`1. `) beside bullets, items nested by two spaces, cells merged across
(`<`) and down (`^`), and `[[BLOCK: name]]` cells filled from
[[BLOCK: name]] ... [[ENDBLOCK]] elsewhere in the file: a diagram, a
picture or code. A wrapped word that looks like a list marker is
escaped.

The tables are made while each file's directives are expanded, so
warnings name the right file and line inside includes. listtable.lua
moves the blocks into their cells (without figure captions) and marks
the tables for Word, where a rich table keeps its widths in a fixed
layout, lets its body rows split, formats only a real header row and
fits its pictures to their cells. The Word merge adds numbering one
list at a time, as docxcompose gave every list in one table the same
numbering.

Also: Word tables with paragraphs, lists or merged cells, or without a
header row, import as [[LISTTABLE]]; py-doc check and lint report table
and block mistakes; the build report counts rich tables per source;
the VS Code extension highlights directives and variables; the tool
image workflow checks the example's rich table with the image's pandoc.
Docs, requirements (FR-029, FR-064) and the example guide are updated.

Refs #218

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHtcxeRPPmXcydfxoEHGJ4
Pandoc writes \multirow for a grid table cell that spans rows, which the
example guide's [[LISTTABLE]] now has, and py-doc's LaTeX template (and
the example templates made from it) did not load the package, so the
PDF build stopped with "Undefined control sequence".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHtcxeRPPmXcydfxoEHGJ4
Four sentences added for [[LISTTABLE]] were over Vale's 30 words, which
`py-doc lint docs --strict` fails on in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHtcxeRPPmXcydfxoEHGJ4
@markbac
markbac merged commit 82cdb54 into main Nov 5, 2026
7 checks passed
@markbac
markbac deleted the claude/hopeful-galileo-qo0735 branch November 5, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rich table cells: [[LISTTABLE]] tables with paragraphs, lists, merged cells and diagrams in cells

2 participants