12d - The README speaks !adf: and MIGRATION.md converts 0.1.0's stored markdown #88

Merged
lilleman merged 3 commits from 12d into main 2026-09-16 22:20:39 +02:00
3 changed files with 57 additions and 10 deletions
Showing only changes of commit 6358a2263c - Show all commits
+46
View File
@@ -0,0 +1,46 @@
# Migrating
## From `0.1.0` to `0.2.0`
Directives moved under the `!adf:` prefix. `0.2.0` reads markdown `0.1.0` wrote without an error
and turns every directive in it into plain text, so convert stored markdown before `0.2.0` reads
it. Stored ADF needs no change.
### Convert stored markdown
Read it with `0.1.0` and write it with `0.2.0`, installed side by side:
```sh
npm install @larvit/adf-codec@0.2.0 adf-codec-0.1@npm:@larvit/adf-codec@0.1.0
```
```ts
import { adfToMarkdown } from '@larvit/adf-codec'
import { markdownToAdf as markdownToAdf010 } from 'adf-codec-0.1'
function migrateMarkdown(stored: string) {
const parsed = markdownToAdf010(stored)
return parsed.ok ? adfToMarkdown(parsed.value) : parsed
}
```
### Spellings
| `0.1.0` | `0.2.0` |
| --- | --- |
| `:::panel info` … `:::`, the fence longer per nesting level | `!adf:panel info` … `!adf:/panel` at any depth |
| `::media {id=a type=file}` | `!adf:media {id=a type=file}` |
| `::paragraph`, the empty paragraph | `!adf:paragraph` then `!adf:/paragraph` |
| `:mention[@Mikael]{id=5b10a2}` | `!adf:mention[@Mikael]{id=5b10a2}` |
| the `adf` code fence and `:adf{json="…"}` | the `carry` code fence and `!adf:carry{json="…"}` |
| `\:` keeps a directive literal | `\!adf:` keeps a directive literal |
A colon run and `:name[` are plain text now, and `adf` is an ordinary code block language.
### Error codes
| Input | `0.1.0` | `0.2.0` |
| --- | --- | --- |
| a leaf node given a body, `listBreak` included: `:::media {…}` … `:::`, `!adf:media {…}` … `!adf:/media` | `unsupported-node-shape` | `malformed-directive` |
| a container node with no closer: `::panel info`, `!adf:panel info` | `unsupported-node-shape` | `malformed-directive` |
| an empty paragraph with a closer: `:::paragraph` … `:::`, `!adf:paragraph` … `!adf:/paragraph` | `unsupported-node-shape` | parses |
+4 -4
View File
@@ -6,7 +6,7 @@ an HTML dialect.
**Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at **Status: published — the markdown round-trip (`adfToMarkdown`, `markdownToAdf`); HTML at
`0.3.0`.** `0.3.0`.**
Plan: `todo.md`. Decisions: `AGENTS.md`. The flavour's grammar: Plan: `todo.md`. Decisions: `AGENTS.md`. The flavour's grammar:
[`spec/flavour.md`](spec/flavour.md). [`spec/flavour.md`](spec/flavour.md). Upgrading from `0.1.0`: [`MIGRATION.md`](MIGRATION.md).
## What it is for ## What it is for
@@ -27,7 +27,7 @@ npm install @larvit/adf-codec
```ts ```ts
import { markdownToAdf } from '@larvit/adf-codec' import { markdownToAdf } from '@larvit/adf-codec'
const result = markdownToAdf('# Release notes\n\n:::panel info\nShipped on Tuesday.\n:::\n') const result = markdownToAdf('# Release notes\n\n!adf:panel info\nShipped on Tuesday.\n!adf:/panel\n')
if (result.ok) { if (result.ok) {
send(result.value) send(result.value)
} else { } else {
@@ -78,9 +78,9 @@ Parsing — `markdownToAdf`, and `htmlToAdf` at `0.3.0`:
| Code | Fires when | What you can do | | Code | Fires when | What you can do |
| --- | --- | --- | | --- | --- | --- |
| `malformed-directive` | a `:::` block or `:name[…]` inline directive the grammar cannot read — an unclosed fence or `[content]`, `{attrs}` out of order or duplicated, invalid JSON in an `adf` carry | write the spelling the message names, or escape the line — `\:::` for a block, `\:` for an inline one — to keep it literal text | | `malformed-directive` | an `!adf:` the grammar cannot read — a prefix completing no directive, an unclosed container or `[content]`, a closer with no container of its name open, a leaf given a body, `{attrs}` out of order or duplicated, invalid JSON in a `carry` | write the spelling the message names, or escape the prefix — `\!adf:`, block and inline alike — to keep it literal text |
| `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way | | `malformed-pipe-table` | a pipe row that is no pipe table — a missing or ragged `---` delimiter row, an alignment colon in it, or a row not opening with a pipe | open every row with a pipe and give the delimiter row the header's cell count; to keep the lines literal text instead, escape the leading pipe of every one — escaping a single row leaves the next to open a fresh table and fail the same way |
| `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the colon; the spelling itself is well formed, so a later minor may give the name meaning | | `unknown-directive-name` | a directive whose name is no node or mark this version spells | check the name in `spec/flavour.md`, or escape the prefix as `\!adf:`; the spelling itself is well formed, so a later minor may give the name meaning |
| `unmappable-html` | the markdown holds a raw HTML tag, comment or processing instruction | remove it or write it in the flavour — ADF holds no raw-HTML node, and the element mapping lands at `0.3.0` | | `unmappable-html` | the markdown holds a raw HTML tag, comment or processing instruction | remove it or write it in the flavour — ADF holds no raw-HTML node, and the element mapping lands at `0.3.0` |
| `unmappable-image` | an image sits inside other content, or carries a title | give the image a paragraph of its own and drop the title | | `unmappable-image` | an image sits inside other content, or carries a title | give the image a paragraph of its own and drop the title |
+7 -6
View File
@@ -275,12 +275,13 @@ proves 12, 13 spells 11's gaps in 12's grammar, and 12 rewrites code 4b and 4c c
- [ ] **13b — The directive link.** `link` spelled as above in both directions, with a round-trip - [ ] **13b — The directive link.** `link` spelled as above in both directions, with a round-trip
fixture per trigger, `spec/flavour.md`'s Marks section following; `unspellable-link` removed fixture per trigger, `spec/flavour.md`'s Marks section following; `unspellable-link` removed
from the code list, its `errors/` fixtures and the CommonMark suite's `unspellable` from the code list, its `errors/` fixtures and the CommonMark suite's `unspellable`
exceptions it cures re-derived, and the README's code table and its "not every document exceptions it cures re-derived, the README's code table and its "not every document
converts back" guarantee following; the gap list is empty. A round-trip fixture holds the converts back" guarantee following, and `MIGRATION.md` naming the removed code; the gap
shape 4.2's review left refused until then: an autolink-shaped link under a directive mark list is empty. A round-trip fixture holds the shape 4.2's review left refused until then:
whose href holds `\:name{`. A link opening a paragraph whose opening reads as a link an autolink-shaped link under a directive mark whose href holds `\!adf:name{`. A link
reference definition, which 4.3 leaves riding the carry, takes the directive link too, with opening a paragraph whose opening reads as a link reference definition, which 4.3 leaves
its round-trip fixture (the maintainer, 2026-09-15). riding the carry, takes the directive link too, with its round-trip fixture (the
maintainer, 2026-09-15).
- [ ] **14 — The CommonMark subset's directory (`0.2.0`).** `src/markdown/` holds 16 source - [ ] **14 — The CommonMark subset's directory (`0.2.0`).** `src/markdown/` holds 16 source
files at its root and 10 adds more there. The CommonMark subset moves under files at its root and 10 adds more there. The CommonMark subset moves under
`src/markdown/commonmark/` — `backtick-runs.ts`, `commonmark-grammar.ts` as `grammar.ts`, `src/markdown/commonmark/` — `backtick-runs.ts`, `commonmark-grammar.ts` as `grammar.ts`,