@@ -24,7 +24,7 @@
| ID | Release | Exempt | Item | R | S | A | G | Goals | Score |
| ID | Release | Exempt | Item | R | S | A | G | Goals | Score |
|---|---|---|---|---|---|---|---|---|---|
|---|---|---|---|---|---|---|---|---|---|
| 40 | 0.2.0 | decision | **Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document it takes. ** | 6 | 7 | 8 | 9 | 1 | 26.2 |
| 40 | 0.2.0 | decision | **Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document `adfToMarkdown` takes. ** | 6 | 7 | 8 | 9 | 1 | 26.2 |
| 7 | 0.2.0 | | **Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF. ** | 6 | 9 | 9 | 9 | 2, 3 | 25.8 |
| 7 | 0.2.0 | | **Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF. ** | 6 | 9 | 9 | 9 | 2, 3 | 25.8 |
| 45 | 0.2.0 | | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`. ** | 2 | 3 | 6 | 8 | 1 | 25.2 |
| 45 | 0.2.0 | | **Replace `isAdfDocument` with a reader returning `Result<AdfDocument>`. ** | 2 | 3 | 6 | 8 | 1 | 25.2 |
| 6 | 0.2.0 | decision | **Specify the HTML dialect. ** | 2 | 6 | 7 | 8 | 2, 3 | 24.7 |
| 6 | 0.2.0 | decision | **Specify the HTML dialect. ** | 2 | 6 | 7 | 8 | 2, 3 | 24.7 |
@@ -34,25 +34,25 @@
| 34 | 0.3.0 | | **Read emphasis flanking by the whole character beside an astral symbol. ** | 2 | 3 | 3 | 6 | 3, 4 | 12.6 |
| 34 | 0.3.0 | | **Read emphasis flanking by the whole character beside an astral symbol. ** | 2 | 3 | 3 | 6 | 3, 4 | 12.6 |
| 42 | 0.3.0 | | **Trim a text leaf's trailing blanks in linear time. ** | 1 | 2 | 5 | 9 | 8 | 12.5 |
| 42 | 0.3.0 | | **Trim a text leaf's trailing blanks in linear time. ** | 1 | 2 | 5 | 9 | 8 | 12.5 |
| 48 | 0.3.0 | question | **Keep the release path publishing past npm's bypass-2FA token retirement. ** | 4 | 4 | 8 | 3 | 9 | 11.7 |
| 48 | 0.3.0 | question | **Keep the release path publishing past npm's bypass-2FA token retirement. ** | 4 | 4 | 8 | 3 | 9 | 11.7 |
| 31 | 0.3.0 | | **Make the branch figure the coverage floor is read against repeatabl e. ** | 2 | 3 | 3 | 4 | 1 | 11.2 |
| 31 | 0.3.0 | | **Make the branch-coverage figure repeat across runs of an unchanged tre e. ** | 2 | 3 | 3 | 4 | 1 | 11.2 |
| 33 | 0.3.0 | | **Make a carried mark run cost the line one re-emit . ** | 4 | 5 | 6 | 9 | 8 | 10.7 |
| 33 | 0.3.0 | | **Emit a line in time linear in its mark runs, in `adfToMarkdown` and the plain reduction . ** | 4 | 5 | 6 | 9 | 8 | 10.7 |
| 46 | 0.3.0 | | **Publish the bundle size in the README, failing the release pipeline when it drifts. ** | 2 | 4 | 5 | 5 | 7, 9 | 10.3 |
| 46 | 0.3.0 | | **Publish the bundle size in the README, failing the release pipeline when it drifts. ** | 2 | 4 | 5 | 5 | 7, 9 | 10.3 |
| 9 | 0.3.0 | | **Ship an online sandbox: a web page with two textboxes converting between ADF and markdown on the library's browser build. ** | 2 | 6 | 6 | 8 | 9 | 10.3 |
| 9 | 0.3.0 | | **Ship an online sandbox: a web page with two textboxes converting between ADF and markdown on the library's browser build. ** | 2 | 6 | 6 | 8 | 9 | 10.3 |
| 8 | 0.4.0 | question | **Ship a CLI. ** | 4 | 7 | 5 | 5 | 9 | 5.3 |
| 8 | 0.4.0 | question | **Ship a CLI. ** | 4 | 7 | 5 | 5 | 9 | 5.3 |
## Details
## Details
### 40. Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document it takes.
### 40. Make `markdownToAdf(adfToMarkdown(doc))` deep-equal `doc` for every document `adfToMarkdown` takes.
Today it holds for editor-normal documents only: two adjacent text nodes with the same marks merge,
Today it holds for editor-normal documents only: two adjacent text nodes with the same marks merge,
an empty `attrs` , `marks` or `content` drops, and `-0` reads back `0` — shapes pipelines and bots
an empty `attrs` , `marks` or `content` drops, and `-0` reads back `0` — shapes pipelines and bots
build. Spell each so it reads back as written, CommonMark's spelling kept wherever none occurs; the
build. Spell each so it reads back as written; CommonMark's spelling stays wherever the document
spellings are part of the chunk. `docs/decisions.md` §Equality is editor-normal, `spec/flavour.md`
holds none of these shapes. The spellings are part of the chunk. `docs/decisions.md` §Equality is editor-normal, `spec/flavour.md`
and `corpus/README.md` follow, and the tests drop `toEditorNormal` .
and `corpus/README.md` follow, and the tests drop `toEditorNormal` .
### 7. Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF.
### 7. Ship HTML: `adfToHtml`, `htmlToAdf`, and `markdownToHtml` / `htmlToMarkdown` composed through ADF.
Builds on item 6. T he CommonMark spec suite runs against `markdownToHtml` from here . The README
Builds on item 6. Once it lands, t he CommonMark spec suite runs against `markdownToHtml` . The README
documents HTML as it documents markdown, and its tagline and `package.json` 's `description` regain
documents HTML as it documents markdown, and its tagline and `package.json` 's `description` regain
HTML.
HTML.
@@ -83,14 +83,11 @@ already escape it.
### 47. Open the README with what the package is, what it does and for whom.
### 47. Open the README with what the package is, what it does and for whom.
It opens with the pre-launch rationale — Atlassian's REST APIs, `pf-editor-service/convert` being
It opens with the pre-launch rationale — Atlassian's REST APIs, `pf-editor-service/convert` being
decommissioned, a link to JRACLOUD-77436 — where a shipped package sh oul d answer what it is, what it
decommissioned, a link to JRACLOUD-77436. The backgr oun d goes entirely, no endpoint, ticket or
does and for whom first, then the shortest runnable example. The background goes entirely, no
"why" note left. The badges are npm's version and the Gitea Actions status. The README names the
endpoint, ticket or "why" note left. The top follows the package-README order: an npm version badge
lossy pair, `adfToPlainMarkdown` and `plainMarkdownToAdf` , and the flavours it writes and reads —
and the Gitea Actions badge, a tagline that is also `package.json` 's `description` , a feature list
GitHub Flavored Markdown's alerts and task lists, Obsidian Flavored Markdown's callouts — so a
and a one-line table of contents, then install and the shortest runnable example; a table of
search for either finds the package.
everything exported sits near the bottom. The README names the lossy pair and the flavours it
writes and reads — GitHub Flavored Markdown's alerts and task lists, Obsidian Flavored Markdown's
callouts — so a search for either finds the package.
### 34. Read emphasis flanking by the whole character beside an astral symbol.
### 34. Read emphasis flanking by the whole character beside an astral symbol.
@@ -111,13 +108,13 @@ writes was not enough, and npm answered `EOTP` until the token itself bypassed.
bypass-2FA tokens for direct publishing around January 2027, leaving them `npm stage publish` , which
bypass-2FA tokens for direct publishing around January 2027, leaving them `npm stage publish` , which
a maintainer approves with 2FA; its replacement — trusted publishing over OIDC — supports
a maintainer approves with 2FA; its replacement — trusted publishing over OIDC — supports
GitHub-hosted Actions, GitLab.com's shared runners and CircleCI's cloud, self-hosted runners planned
GitHub-hosted Actions, GitLab.com's shared runners and CircleCI's cloud, self-hosted runners planned
without a date. So the release path has an expiry date and no drop-in successor yet. Revisit:
without a date. Revisit:
whether npm has added Gitea or self-hosted OIDC, and otherwise whether the release moves to the
whether npm has added Gitea or self-hosted OIDC, and otherwise whether the release moves to the
staged publish — which fits badly with publish-on-merge, and is the maintainer's trade to weigh
staged publish — which fits badly with publish-on-merge, and is the maintainer's trade to weigh.
rather than discover on a red release run . It stays out of `0.2.0` knowing the cutoff may land
The Goals and G cells are provisional: no README goal covers the release path . It stays out of `0.2.0` knowing the cutoff may land
first.
first.
### 31. Make the branch figure the coverage floor is read against repeatabl e.
### 31. Make the branch-coverage figure repeat across runs of an unchanged tre e.
Three Node test legs over one unchanged tree reported `emit/inline-line.ts` at 95.83%, 96.23% and
Three Node test legs over one unchanged tree reported `emit/inline-line.ts` at 95.83%, 96.23% and
96.23%, and the total at 98.80%, 98.84% and 98.84% (2026-09-21). `--experimental-test-coverage`
96.23%, and the total at 98.80%, 98.84% and 98.84% (2026-09-21). `--experimental-test-coverage`
@@ -128,7 +125,7 @@ moves upward, so the first raise to the measured figure reddens a run that chang
measurement repeatable, or state the number the floor may be raised to and why it is not the
measurement repeatable, or state the number the floor may be raised to and why it is not the
measured one.
measured one.
### 33. Make a carried mark run cost the line one re-emit .
### 33. Emit a line in time linear in its mark runs, in `adfToMarkdown` and the plain reduction .
`adfToMarkdown` spends 23 s on one paragraph of 2000 × `un` plus `**-r**` : each run its flanking
`adfToMarkdown` spends 23 s on one paragraph of 2000 × `un` plus `**-r**` : each run its flanking
cannot spell re-emits the whole line before riding the carry, quadratic in the runs, and the plain
cannot spell re-emits the whole line before riding the carry, quadratic in the runs, and the plain
@@ -138,7 +135,7 @@ reduction's `spellableLine` drops one mark per re-emit the same way. Make both l
Lands after item 7, which changes it. The quantity is what a consumer downloads and loads: the
Lands after item 7, which changes it. The quantity is what a consumer downloads and loads: the
tarball `npm pack` produces, its unpacked `dist` , and the built JavaScript minified + gzipped — the
tarball `npm pack` produces, its unpacked `dist` , and the built JavaScript minified + gzipped — the
figure the competitors advertise (marklassian's "12kb") and the only apple-to-apple one, since ours
figure the competitors advertise (marklassian's "12kb") and the only apples -to-apples one, since ours
ships tsc's unminified output and no minifier yet (decide here whether to minify for the build or
ships tsc's unminified output and no minifier yet (decide here whether to minify for the build or
report the unminified gzip). The figure lands in README §The package beside the "no runtime
report the unminified gzip). The figure lands in README §The package beside the "no runtime
dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5 kB, JS gzipped
dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5 kB, JS gzipped
@@ -146,5 +143,6 @@ dependencies" claim. Measured today, unminified: tarball 60.4 kB, unpacked 221.5
### 8. Ship a CLI.
### 8. Ship a CLI.
No goal or persona in the README covers it yet; the maintainer names both before it is built, and
The Goals and G cells are provisional: no goal or persona in the README covers a CLI yet. The
they land in the README's `## Goals` and `## Audience` with it.
maintainer names both before it is built, and they land in the README's `## Goals` and `## Audience`
with it.