`. |
-## Markdown support
+## Serving
-| Markdown | WML |
-| --- | --- |
-| Headings | `` for the first on a card, `
` after |
-| Paragraphs, lists | `
` — 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*` | ``, `` |
-| `~~strike~~`, `` `code` `` | markers stripped; WML has no equivalent |
-| Links | `` |
-| Images | `
`, subject to `--images` |
-| Fenced/indented code | `` with `
` between lines |
-| Blockquotes | `
` |
-| Pipe tables | `
` 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:
-
-- **A literal `$` is written `$$`.** WML uses `$` to introduce a variable substitution, so wapdown doubles it for you. `Permit fee: $5` comes out as `Permit fee: $$5`, which the device renders as `$5`.
-- **Link labels cannot carry emphasis.** WML declares `` as `(#PCDATA | br | img)*`, so there is nowhere valid to put a `` inside one. `[**go** now](url)` becomes `go now`, with the markers stripped rather than translated.
-
-WML 1.3 is the only supported DTD, by design rather than by flag.
-
-## Serving a deck
-
-Serve `.wml` as `text/vnd.wap.wml` — a browser that receives `text/html` will usually refuse to render it. `--cache-control 0` is worth setting for content that changes, since WAP gateways cache aggressively.
+Serve `.wml` as `text/vnd.wap.wml` — a browser given `text/html` will usually refuse to render it. Set `--cache-control 0` for content that changes; WAP gateways cache aggressively.
## Development
```bash
uv sync
-uv run pytest # unit, golden, and well-formedness tests
+uv run pytest # unit, golden, well-formedness
uv run --extra dtd pytest # ...plus validation against the real WML 1.3 DTD
```
-The DTD is vendored at `tests/dtd/wml13.dtd` so the suite never depends on fetching a twenty-year-old URL. DTD validation needs `lxml` and is skipped when it is absent.
-
-Golden files under `tests/golden/` pin whole-document output. After an intentional renderer change:
+The DTD is vendored at `tests/dtd/wml13.dtd`; validation needs `lxml` and is skipped without it. Golden files pin whole-document output — after an intentional change, regenerate and read the diff:
```bash
-uv run python tests/regenerate_golden.py
-jj diff tests/golden # the diff is the change, stated in output
+uv run python tests/regenerate_golden.py && jj diff tests/golden
```
-## Architecture
-
-Markdown is parsed into a stream of block events, which a renderer turns into output. The pieces are registered as plugins (`src/wapdown/plugins/`), so another WAP-era target — HDML, i-mode cHTML — can be added alongside `wml` without restructuring anything.
-
-- `parsers/markdown.py` — Markdown to `BlockEvent`s
-- `renderers/wml/inline.py` — inline markup and WML's escaping rules
-- `renderers/wml/deck.py` — sectioning, byte packing, navigation topology
-- `renderers/wml/renderer.py` — element emission
-- `config.py` — defaults, frontmatter, and CLI layering
-
-Unlike a streaming text renderer, the WML renderer buffers the whole event stream: card boundaries, menu choices, and nav targets all depend on knowing the document's full structure up front.
-
-## Credit
-
-The WML renderer began life inside [md2txt](https://codeberg.org/randogoth/md2txt), a suite of plain-text Markdown exporters, and was extracted here because a deck compiler is a different kind of thing from a text exporter.
+Parsers and renderers are registered as plugins (`src/wapdown/plugins/`), so another WAP-era target such as HDML or i-mode cHTML can be added without restructuring. The renderer is split into `inline.py` (markup and escaping), `deck.py` (sectioning, packing, nav topology) and `renderer.py` (element emission).
## License