12d - The README speaks !adf: and MIGRATION.md converts 0.1.0's stored markdown #88
@@ -0,0 +1,56 @@
|
|||||||
|
# Migrating
|
||||||
|
|
||||||
|
## From `0.1.0` to `0.2.0`
|
||||||
|
|
||||||
|
Directives moved under the `!adf:` prefix. `0.2.0` reads `0.1.0`'s spelling without an error,
|
||||||
|
turning each directive into text and each carried node into an `adf` code block. Before `0.2.0`
|
||||||
|
reads any `0.1.0` markdown, convert what is stored or in flight (an open editor, a queue) with the
|
||||||
|
recipe below, and rewrite markdown your code writes or matches (templates, prompts, patterns) by
|
||||||
|
the spelling table. Stored ADF needs no change.
|
||||||
|
|
||||||
|
### Convert 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Convert each document once: a second pass can return ok while turning the directives into text.
|
||||||
|
Stop `0.1.0` writing first, and record which documents are converted.
|
||||||
|
- A refusal carrying `position` is `0.1.0`'s parse, which refused that markdown before too. One
|
||||||
|
without is `0.2.0`'s emit: store the document `markdownToAdf010` read as ADF rather than keeping
|
||||||
|
the unconverted markdown.
|
||||||
|
|
||||||
|
### 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}` |
|
||||||
|
| `::taskItem TODO {localId=i}`: an empty `caption`, `decisionItem`, `paragraph` or `taskItem`, or an empty `heading` carrying `localId` | `!adf:taskItem TODO {localId=i}` then `!adf:/taskItem` |
|
||||||
|
| `: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` an ordinary code block language; text
|
||||||
|
holding an unescaped `!adf:` and a `carry` fence are claimed instead.
|
||||||
|
|
||||||
|
### Error codes
|
||||||
|
|
||||||
|
| Input | `0.1.0` | `0.2.0` |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| a leaf node given a body (`media`, `listBreak`) | `unsupported-node-shape` | `malformed-directive` |
|
||||||
|
| a node with a block body written as a leaf (`panel`) | `unsupported-node-shape` | `malformed-directive` |
|
||||||
|
| an empty node the `::taskItem` spelling row names, written as a leaf | parses | `malformed-directive` |
|
||||||
|
| an empty node the `::taskItem` spelling row names, written with a closer | `unsupported-node-shape` | parses |
|
||||||
@@ -6,7 +6,8 @@ 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`](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/spec/flavour.md).
|
||||||
|
Upgrading from `0.1.0`: [convert your markdown first](https://gitea.larvit.se/larvit/adf-codec/src/branch/main/MIGRATION.md).
|
||||||
|
|
||||||
## What it is for
|
## What it is for
|
||||||
|
|
||||||
@@ -27,7 +28,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 +79,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, `[content]` or `{attrs}`, 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 |
|
||||||
|
|
||||||
|
|||||||
@@ -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`,
|
||||||
|
|||||||
Reference in New Issue
Block a user