Make --- divide cards, and stop drawing ASCII rules

WML has no horizontal rule element -- its entire %layout entity is
`<br>` -- so a thematic break was being rendered as `<p>------------</p>`,
a hardcoded twelve-dash guess at screen width that wraps into nonsense on
a narrow device and is short on a wide one. It was the one construct
where the renderer invented a width out of nothing.

A `---` already looks like a divider and reads as one in every Markdown
document ever written, so it now is one: it starts a new card, by
default. Rules are never drawn, whether or not they divide.

Thematic breaks and `{.card Title}` markers are now a single mechanism --
an explicit divider, optionally carrying a title -- and compose freely in
one document. Both still win over --split-level. A section takes its
title from its own first heading when the divider does not supply one, so
the common shape needs no titles at all:

    Intro on the menu.

    ---

    ## Weather

    Cold and clear.

`--no-split-on-rule` / `split_on_rule: false` opts out of the splitting;
it does not bring the dashes back.

Three edges this opened, each fixed here rather than left to bite:

- Setext headings. `Heading` over `---` is an H2 in Markdown, but the
  parser was ATX-only, so it produced a paragraph plus a rule. Once a
  rule divides cards, a setext document would have split at every heading
  and stranded each heading as body copy on the card before it. Setext
  headings are now parsed, so such a document keeps its structure.
- Empty sections. A trailing `---`, or two in a row, produced an empty
  "Untitled" card and a menu entry leading to it. Sections with no
  renderable content are dropped.
- The multi-card threshold was two sections, so a document with a single
  divider collapsed back into one card. Any explicit divider now makes a
  multi-card deck: `A --- B` asks for two screens.

Also fixes a latent frontmatter bug this made far more likely: a document
opening with `---` and no `key: value` lines had its opening swallowed as
if the break were a frontmatter fence. A fenced block with no keys in it
is not frontmatter.

222 tests. Rendering examples/trail.md still matches md2txt's committed
output byte for byte; no golden file contains an ASCII rule any more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
randogoth 2026-09-23 09:27:49 +03:00
parent b83e24e2f7
commit 3b728d9d74
17 changed files with 383 additions and 36 deletions

View file

@ -26,27 +26,46 @@ Zero runtime dependencies, Python 3.13+.
## Cards
A document with no options becomes a single card. Splitting is always opt-in, and there are two ways to ask for it.
A document with no dividers becomes a single card. There are three ways to ask for more.
**Manual dividers** — put a `{.card}` or `{.card Title}` line wherever a new card should start:
**Thematic breaks** — a plain `---` starts a new card. WML has no rule element to draw (its entire layout vocabulary is `<br>`), and a row of ASCII dashes is noise on a small screen, so the glyph is put to better use as the divider it already looks like:
```markdown
Intro shown on the menu card...
{.card Weather}
---
## Weather
Cold and clear.
---
## Trail Status
- North Loop: open
```
Each card takes its title from its own first heading. `***` and `___` work identically — any Markdown thematic break divides. A trailing `---`, or two in a row, adds no empty card. `--no-split-on-rule` turns this off; breaks are then ignored rather than drawn, because there is still nothing to draw them with.
`---` under a line of text is a setext heading, not a break, and is parsed as one — so a document written in that style keeps its headings instead of shattering into cards.
**Named dividers** — `{.card Title}` is the same mechanism with an explicit title, for when a section has no heading to borrow one from:
```markdown
{.card Trail Status}
- North Loop: open
```
**Heading-level splitting** — `--split-level 2` starts a new card at every `##`, which fits the common one-H1-title-plus-H2-sections document:
The two compose freely in one document.
**Heading-level splitting** — `--split-level 2` starts a new card at every `##`, which fits a document that is already structured by headings and has no dividers in it:
```bash
wapdown trail.md --split-level 2
```
If a document contains any `{.card}` markers, they win and `--split-level` is ignored: an explicit boundary in the document is a stronger statement of intent than a rule passed on the command line.
Explicit dividers win over `--split-level` when both are present: a boundary written into the document is a stronger statement of intent than a rule passed on the command line.
## Navigation
@ -112,6 +131,7 @@ cache_control: 0
| `--max-card-bytes` | `max_card_bytes` | `1400` | Per-card byte safety net; `0` disables. |
| `--menu` / `--no-menu` | `menu` | `true` | Hub-and-spoke menu vs. linear More/Back chaining. |
| `--menu-style` | `menu_style` | `links` | `links` or `select` for the menu's choices. |
| `--split-on-rule` / `--no-split-on-rule` | `split_on_rule` | `true` | Start a new card at every thematic break. |
| `--deck-per-card` | `deck_per_card` | `false` | Write one file per section into the output directory. |
| `--nav-next-label` | `nav_next_label` | `More` | Forward label. |
| `--nav-prev-label` | `nav_prev_label` | `Prev` | Label between pagination parts. |
@ -128,7 +148,9 @@ cache_control: 0
| Markdown | WML |
| --- | --- |
| Headings | `<p><b><big>` for the first on a card, `<p><b>` after |
| Paragraphs, lists, rules | `<p>` — WML has no list element, so bullets and numbers become literal text |
| Paragraphs, lists | `<p>` — WML has no list element, so bullets and numbers become literal text |
| `---` / `***` / `___` | a card divider; never drawn, as WML has no rule element |
| Setext headings (`===` / `---` underlines) | same as `#` / `##` |
| `**bold**`, `*italic*` | `<b>`, `<i>` |
| `~~strike~~`, `` `code` `` | markers stripped; WML has no equivalent |
| Links | `<a href>` |
@ -136,6 +158,7 @@ cache_control: 0
| Fenced/indented code | `<p>` with `<br/>` between lines |
| Blockquotes | `<p><i>` |
| Pipe tables | `<p><table columns="N">` with a bold header row |
| `{.card Title}` | a card divider carrying a title |
| `{.include file.md}` | inlined before conversion |
Two consequences of WML's own grammar are worth knowing: