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

@ -141,3 +141,36 @@ class TestExamples:
)
def test_every_example_converts(self, name, tmp_path, capsys):
assert main([str(EXAMPLES / name), "-o", str(tmp_path / "out.wml")]) == 0
class TestRuleDividers:
RULES = "Intro.\n\n---\n\n## Alpha\n\nBody.\n"
def test_rules_divide_by_default(self, source, capsys):
main([str(source(self.RULES))])
assert '<card id="menu"' in capsys.readouterr().out
def test_no_split_on_rule_flag(self, source, capsys):
main([str(source(self.RULES)), "--no-split-on-rule"])
out = capsys.readouterr().out
assert '<card id="menu"' not in out
assert "------" not in out
def test_frontmatter_can_disable(self, source, capsys):
path = source("---\nsplit_on_rule: false\n---\n" + self.RULES)
main([str(path)])
assert '<card id="menu"' not in capsys.readouterr().out
def test_leading_rule_without_frontmatter_keeps_content(self, source, capsys):
# Regression: a document opening with `---` and no key: value pairs
# had its opening swallowed as if it were a frontmatter fence.
main([str(source("---\n\nKept text.\n\n---\n\nAlso kept.\n"))])
out = capsys.readouterr().out
assert "Kept text." in out
assert "Also kept." in out
def test_real_frontmatter_is_still_consumed(self, source, capsys):
main([str(source("---\ntitle: Deck\n---\n\nBody.\n"))])
out = capsys.readouterr().out
assert "title: Deck" not in out
assert 'title="Deck"' not in out or "Body." in out