wapdown/tests/golden_cases.py

33 lines
1.4 KiB
Python
Raw Normal View History

Extract the WML exporter from md2txt into wapdown md2txt is a suite of minimal text-based markup exporters, and every other renderer in it (text, micron, ama, gemini, nex) is a straight transform of a document into a flat text format. The WML renderer is neither: it emits an XML tree, and it restructures the document rather than transforming it -- splitting one file into many <card>s, inventing navigation between them, building a menu card that exists in no source document, and paginating on a byte budget. That is why it needed levers no sibling renderer needed, and why it alone forced a CARD_BREAK block kind and a {.card} directive into the shared parser that every other renderer ignores. wapdown is that renderer given a repository of its own, where restructuring a document into a navigable deck is the point. Ported: the Markdown parser, block event models, and pipeline core, each trimmed to what a deck compiler actually uses (no FIGlet, no hyphenation, no ASCII-art includes, no text-layout frontmatter), plus the eight inline regexes the renderer had been borrowing from a 1039-line text renderer. The plugin registry comes along so other WAP-era targets can register alongside wml later. Zero runtime dependencies. Config is now first-class: every lever is an argparse flag with validation and a frontmatter equivalent, layered CLI > frontmatter > default, replacing the generic --renderer-option KEY=VALUE passthrough. Five defects found while reading the code, each with a regression test: - Link and image URLs were shredded by the emphasis patterns, which ran before LINK_RE: a path like /v1_2_3/ became /v1<i>2</i>3/ inside the href. Links and images are now resolved and stashed first. - <table> was emitted as a direct child of <card>. The WML 1.3 content model is (onevent*, timer?, (do | p | pre)*), so it must sit in a <p>. - Link labels carried emphasis, but <a> is declared (#PCDATA | br | img)* -- there is nowhere valid for a <b> inside one. Markers are now stripped. - The menu card was built directly and never byte-packed, so the one card most likely to be large was the one card exempt from the budget. - Output was written with CRLF line endings. WML is XML served over HTTP. New, WAP-idiomatic rather than Markdown-idiomatic: - deck-level <template> hoisting nav that would otherwise repeat per card - <select> menus, picked with a keypad digit instead of scrolled to - --deck-per-card, one file per section cross-linked by filename, which is the real answer to per-deck cache limits - <head> metadata: Cache-Control max-age and <access> - a Home options softkey, which <prev/> alone cannot provide - an image policy (keep/alt/drop) for the WBMP-only reality of WAP 1.x browsers -- no conversion is performed 186 tests, where neither repo had any. Golden files pin whole-document output; every deck is validated against the real WML 1.3 DTD, vendored at tests/dtd/wml13.dtd. Rendering examples/trail.md still matches md2txt's committed output byte for byte, modulo the CRLF fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-23 09:27:49 +03:00
"""The set of (source, options) -> golden file cases.
Shared by `test_golden.py` and `regenerate_golden.py` so the suite and the
regeneration script can never disagree about what should exist.
"""
from __future__ import annotations
from typing import Any, Dict, Tuple
# name -> (example filename, renderer options)
CASES: Dict[str, Tuple[str, Dict[str, Any]]] = {
"trail": ("trail.md", {}),
"trail-split": ("trail.md", {"split_level": 2}),
"trail-linear": ("trail.md", {"split_level": 2, "menu": False}),
"trail-manual": ("trail-manual.md", {}),
"trail-select": ("trail-manual.md", {"menu_style": "select"}),
"trail-home": ("trail-manual.md", {"home_label": "Home"}),
"trail-no-template": ("trail-manual.md", {"template_nav": False}),
"trail-paginated": ("trail-manual.md", {"max_card_bytes": 120}),
"trail-images-alt": ("trail-manual.md", {"images": "alt"}),
"trail-head": ("trail-manual.md", {"cache_control": 0, "access_domain": "example.com"}),
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>
2026-09-23 09:27:49 +03:00
"trail-rules": ("trail-rules.md", {}),
"trail-rules-linear": ("trail-rules.md", {"menu": False}),
"trail-rules-kept": ("trail-rules.md", {"split_on_rule": False}),
Extract the WML exporter from md2txt into wapdown md2txt is a suite of minimal text-based markup exporters, and every other renderer in it (text, micron, ama, gemini, nex) is a straight transform of a document into a flat text format. The WML renderer is neither: it emits an XML tree, and it restructures the document rather than transforming it -- splitting one file into many <card>s, inventing navigation between them, building a menu card that exists in no source document, and paginating on a byte budget. That is why it needed levers no sibling renderer needed, and why it alone forced a CARD_BREAK block kind and a {.card} directive into the shared parser that every other renderer ignores. wapdown is that renderer given a repository of its own, where restructuring a document into a navigable deck is the point. Ported: the Markdown parser, block event models, and pipeline core, each trimmed to what a deck compiler actually uses (no FIGlet, no hyphenation, no ASCII-art includes, no text-layout frontmatter), plus the eight inline regexes the renderer had been borrowing from a 1039-line text renderer. The plugin registry comes along so other WAP-era targets can register alongside wml later. Zero runtime dependencies. Config is now first-class: every lever is an argparse flag with validation and a frontmatter equivalent, layered CLI > frontmatter > default, replacing the generic --renderer-option KEY=VALUE passthrough. Five defects found while reading the code, each with a regression test: - Link and image URLs were shredded by the emphasis patterns, which ran before LINK_RE: a path like /v1_2_3/ became /v1<i>2</i>3/ inside the href. Links and images are now resolved and stashed first. - <table> was emitted as a direct child of <card>. The WML 1.3 content model is (onevent*, timer?, (do | p | pre)*), so it must sit in a <p>. - Link labels carried emphasis, but <a> is declared (#PCDATA | br | img)* -- there is nowhere valid for a <b> inside one. Markers are now stripped. - The menu card was built directly and never byte-packed, so the one card most likely to be large was the one card exempt from the budget. - Output was written with CRLF line endings. WML is XML served over HTTP. New, WAP-idiomatic rather than Markdown-idiomatic: - deck-level <template> hoisting nav that would otherwise repeat per card - <select> menus, picked with a keypad digit instead of scrolled to - --deck-per-card, one file per section cross-linked by filename, which is the real answer to per-deck cache limits - <head> metadata: Cache-Control max-age and <access> - a Home options softkey, which <prev/> alone cannot provide - an image policy (keep/alt/drop) for the WBMP-only reality of WAP 1.x browsers -- no conversion is performed 186 tests, where neither repo had any. Golden files pin whole-document output; every deck is validated against the real WML 1.3 DTD, vendored at tests/dtd/wml13.dtd. Rendering examples/trail.md still matches md2txt's committed output byte for byte, modulo the CRLF fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-23 09:27:49 +03:00
"kitchen-sink": ("kitchen-sink.md", {}),
}
# Cases that produce several files; each is written to its own directory.
MULTI_CASES: Dict[str, Tuple[str, Dict[str, Any]]] = {
"trail-decks": ("trail-manual.md", {"deck_per_card": True, "home_label": "Home"}),
}