3
0
mirror of https://github.com/larvit/adf-codec.git synced 2026-11-13 04:08:29 +01:00

Answer stability round 1: every reader names unsupported-nesting-depth, Flavour stays file-local; product-owner round 1: model markdown reads in portableMarkdownToAdf, the migration rows say what each reader builds, each code names its readers, item 84 filed

This commit is contained in:
2026-10-09 02:49:10 +02:00
parent 6e2ac6040a
commit ba531e13bf
5 changed files with 26 additions and 14 deletions
+4 -3
View File
@@ -3,9 +3,10 @@
## Unreleased
- **Breaking:** each call names the markdown it reads or writes. `adfToMarkdown` and `markdownToAdf`
are now `adfToLosslessMarkdown` and `losslessMarkdownToAdf`, and the new `commonMarkToAdf` reads
markdown a person or a model wrote as the CommonMark spec says: a directive, a pipe table, `~~`
and an `adf:` fence read as text and code. `MIGRATION.md` says which call to take.
are now `adfToLosslessMarkdown` and `losslessMarkdownToAdf`. A bot's or a model's markdown reads
in `portableMarkdownToAdf`, and markdown known to be strict CommonMark in the new
`commonMarkToAdf`, where a directive, a pipe table, `~~` and an `adf:` fence read as text and
code. `MIGRATION.md` says which call to take.
- **Breaking:** the markdown readers refuse a value that is not a string with the new code
`not-a-string`; `MIGRATION.md` lists what each value did before.
- **Breaking:** an attribute value that is not a plain object, array or JSON primitive, such as a
+2 -2
View File
@@ -7,8 +7,8 @@ Each call names the markdown it reads or writes:
| `0.1.0` | `0.2.0` |
| --- | --- |
| `adfToMarkdown` | `adfToLosslessMarkdown` |
| `markdownToAdf`, for markdown `adfToMarkdown` wrote | `losslessMarkdownToAdf` |
| `markdownToAdf`, for markdown a person or a model wrote | `portableMarkdownToAdf`, which keeps GFM's pipe tables and `~~`; or `commonMarkToAdf`, which reads them, a directive and an `adf:` fence as CommonMark does, as text and code |
| `markdownToAdf`, for markdown `adfToMarkdown` wrote, edited since or not | `losslessMarkdownToAdf` |
| `markdownToAdf`, for markdown no `adfToMarkdown` output went into | `portableMarkdownToAdf`, which keeps GFM's pipe tables and `~~` and reads alerts, callouts, task markers and `==` as nodes (README §Portable markdown); or `commonMarkToAdf`, which reads all of them, a directive and an `adf:` fence as CommonMark does, as text and code |
Directives moved under the `!adf:` prefix. `losslessMarkdownToAdf` reads `0.1.0`'s spelling without
an error, turning each directive into text and each carried node into an `adf` code block. Before
+10 -7
View File
@@ -10,9 +10,10 @@ products store as ADF.
- **Lossless:** `adfToLosslessMarkdown` and `losslessMarkdownToAdf` give back the document they
started from — panels, mentions, statuses and node types this version does not know included.
- **CommonMark in:** `commonMarkToAdf` reads a bot's or a model's markdown as the CommonMark spec
says, apart from raw HTML and the exceptions [The guarantees](#the-guarantees) lists; markdown
holding GFM's pipe tables or `~~` reads in `portableMarkdownToAdf`.
- **Markdown in:** `portableMarkdownToAdf` reads a bot's or a model's markdown, GFM's pipe tables
and `~~` included; `commonMarkToAdf` reads markdown known to be strict CommonMark as its spec
says, nothing in it becoming a table, task or panel. Both apart from raw HTML and the exceptions
[The guarantees](#the-guarantees) lists.
- **Portable markdown, lossy:** `adfToPortableMarkdown` and `portableMarkdownToAdf` convert to and
from the markdown that GitHub, GitLab and Obsidian render — GitHub Flavored Markdown's alerts,
task lists and pipe tables, Obsidian Flavored Markdown's callouts and highlights.
@@ -183,9 +184,11 @@ UTF-16 code unit, a JavaScript string index rather than a codepoint or a byte of
or before the refusal — currently the start of the line the enclosing block begins on; a later
minor may narrow that, never widen it. For `not-a-string` it is `{ line: 1, offset: 0 }`.
Parsing — `losslessMarkdownToAdf` raises every row, `portableMarkdownToAdf` the rows naming no
directive, and `commonMarkToAdf` `not-a-string`, `unmappable-html` and `unmappable-image`;
`htmlToAdf` at `0.3.0`:
Parsing — `commonMarkToAdf` raises `not-a-string`, `unmappable-html` and `unmappable-image`;
`portableMarkdownToAdf` those and `malformed-pipe-table`; `losslessMarkdownToAdf` every row; and
`htmlToAdf`, at `0.3.0`, the rows its dialect reaches. Every reader also raises
`unsupported-nesting-depth`, and `losslessMarkdownToAdf` `unsupported-node-shape`, from the table
after next:
| Code | Fires when | What you can do |
| --- | --- | --- |
@@ -193,7 +196,7 @@ directive, and `commonMarkToAdf` `not-a-string`, `unmappable-html` and `unmappab
| `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 |
| `not-a-string` | the value handed in is not a string, such as `null`, a number or a `String` object | pass the input as a string, `String(value)` for a `String` object; the message names the value's type |
| `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 input holds an HTML construct the documented element set does not map, a comment and a processing instruction among them — at this version that is every raw HTML construct in markdown, the element set landing at `0.3.0` | remove the construct, or write what it holds in the lossless flavour |
| `unmappable-html` | the input holds an HTML construct the documented element set does not map, a comment and a processing instruction among them — at this version that is every raw HTML construct in markdown, the element set landing at `0.3.0` | remove the construct, or write what it holds as markdown |
| `unmappable-image` | an image sits inside other content that is not another image's description, or carries a title | give the image a paragraph of its own and drop the title |
| `unspellable-whitespace` | an `emoji`, `mention` or `status` directive's content slot spells a newline or a carriage return — `
`, `
`, `!adf:text{text="\n"}` | replace it with a space, or write the node as `!adf:carry` — an inline directive never spans lines |
+1 -1
View File
@@ -1,6 +1,6 @@
import { isWordCharacter } from '../commonmark/emphasis-matching.ts'
export type Flavour = 'commonmark' | 'lossless' | 'portable'
type Flavour = 'commonmark' | 'lossless' | 'portable'
export type WrittenFlavour = Exclude<Flavour, 'commonmark'>
+9 -1
View File
@@ -6,7 +6,7 @@
`Bar = 9`
`Next ID = 84`
`Next ID = 85`
| Goal | W |
|---|---|
@@ -38,6 +38,7 @@
| 77 | 0.3.0 | decision | **Read the input once into a plain copy, so an accessor property or a throwing Proxy yields `not-an-adf-document` and every call returns a result.** | 4 | 4 | 5 | 9 | 1 | 23.0 |
| 83 | 0.3.0 | defect | **Refuse a document whose markdown would pass the engine's string limit with a result, never a `RangeError`.** | 3 | 4 | 5 | 8 | 1, 9 | 22.0 |
| 71 | 0.3.0 | | **Add a README table comparing the package with the other ADF converters, each cell checked against that package's own docs or behaviour.** | 1 | 3 | 6 | 7 | 3 | 21.2 |
| 84 | 0.3.0 | | **Read GFM's pipe table without leading pipes, and with alignment colons, in `portableMarkdownToAdf`, dropping the alignment.** | 3 | 4 | 7 | 7 | 4, 7 | 19.4 |
| 80 | 0.3.0 | | **Name the node's path and the attribute key when `not-an-adf-document` refuses a node inside the document.** | 2 | 3 | 5 | 6 | 1 | 19.2 |
| 68 | 0.3.0 | | **Carry a non-text inline node holding `content` or `text`, a block holding `text`, and a leaf block holding `content`.** | 3 | 3 | 4 | 7 | 1 | 18.2 |
| 75 | 0.3.0 | | **Make the generated-markdown property write block carries as `adf:` fences, canonical and hostile.** | 2 | 2 | 3 | 7 | 1 | 17.5 |
@@ -183,6 +184,13 @@ the table names each version and the date it was checked. Found while planning d
candidates are `@atlaskit/editor-markdown-transformer`, `adf-to-markdown`, `adf-to-md`,
`adf2markdown`, `extended-markdown-adf-parser`, `marklassian` and `md-to-adf`.
### 84. Read GFM's pipe table without leading pipes, and with alignment colons, in `portableMarkdownToAdf`, dropping the alignment.
Models write `|:---|` delimiter rows and tables without a leading pipe; both are
`malformed-pipe-table` today, and `portableMarkdownToAdf` is the bot's reader. ADF holds no column
alignment, so the portable reader drops it (Goal 7: form, never content). The lossless reader keeps
§Tables' narrowing. Found by the product-owner review of item 43, 2026-10-09.
### 80. Name the node's path and the attribute key when `not-an-adf-document` refuses a node inside the document.
Lands with items 45 and 77, whose reader walks every node. Today every refused node, such as one