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

Answer principles round 1: 0 🔴, 3 🟡 (0 misread); the README names the carry element and the bar, the table gains five npm converters, compare.mjs sorts

This commit is contained in:
2026-10-28 21:12:41 +01:00
committed by Lillem4n
parent 11529ac165
commit 3014f302c1
3 changed files with 41 additions and 19 deletions
+13 -6
View File
@@ -15,7 +15,7 @@ shows, edits, exports or generates the rich text Atlassian products store as ADF
| Markdown from a bot, a model or a person | ADF | `portableMarkdownToAdf` | reads CommonMark plus GFM's tables, task lists and alerts, `~~`, and Obsidian's callouts and `==`; `commonMarkToAdf` reads strict CommonMark alone |
| ADF | markdown to edit, then ADF again | `adfToLosslessMarkdown`, then `losslessMarkdownToAdf` | gives back the document it started from, panels, mentions, statuses and node types this version does not know included |
| ADF | markdown that GitHub, GitLab and Obsidian render | `adfToPortableMarkdown` | keeps the text, images by URL and link targets and drops the rest |
| ADF | HTML | `adfToHtml` | writes the elements a browser shows; `htmlToAdf` reads that HTML back to the same document, and refuses any other HTML |
| ADF | HTML | `adfToHtml` | writes paragraphs, headings, lists, quotes, code blocks, links and marks as HTML elements, and every other node as an element holding its JSON; `htmlToAdf` reads that HTML back to the same document, and refuses any other HTML |
Every call returns a result, never a throw. A refusal carries a code from a closed list, and every
refusal but `engine-limit` repeats on the same input ([The guarantees](#the-guarantees)).
@@ -244,8 +244,9 @@ place, and on CI failing a change that breaks a guarantee.
## Other ADF converters
Serves [Goals](#goals) 3. The first table lists every npm package that converts ADF to or from
markdown, whatever its downloads, unless its own documentation calls it experimental or incomplete.
Serves [Goals](#goals) 3. The first table lists every npm package that runs in Node and converts
ADF to or from markdown, whatever its downloads; a package that fails ordinary nodes stays, with how it fails. A
wrapper or fork of a listed package is left out.
On 2026-10-28, [`converter-comparison/`](https://github.com/larvit/adf-codec/tree/main/converter-comparison)
ran each package's published code, at the version the table names, with its default options. A
package writing markdown got a document holding marks, a link, a mention, a status, a panel and a
@@ -256,8 +257,11 @@ holding the same marks and link.
| --- | --- | --- | --- | --- | --- |
| `@larvit/adf-codec` | both ways | the same document | kept | markdown: lossless, portable; CommonMark in; HTML out; its own HTML in | 0 |
| `@atlaskit/editor-markdown-transformer` 6.3.1 | markdown to ADF, through `@atlaskit/editor-json-transformer` 10.0.0; ADF to markdown throws "This is not implemented yet" | – | – | markdown | 5 |
| `@complexthings/md-to-adf` 1.0.0 | markdown to ADF; writes each list item as a list of its own | – | – | markdown | 1 |
| `@faulander/md2adf` 1.0.0 | both ways | a different document: the status is gone, the mention's `id` becomes its text and the panel a quote | dropped with its text | markdown | 2 |
| `@nthings.dev/adf4j-wasm` 1.0.2 | ADF to markdown | – | replaced by the text `[Unsupported: futureThing]` | GitHub Flavored Markdown, from WebAssembly | 0 |
| `@wrtnlabs/markdown-to-adf` 1.0.2 | markdown to a list of blocks, not a document; `***bold italic***` comes out as italic text holding asterisks | – | – | markdown | 2 |
| `adf-converter` 0.1.0 | ADF to markdown | – | its text kept, with a console message | markdown | 0 |
| `adf-md` 0.2.0 | both ways | a different document: the status without its `localId`, the marks in the other order | dropped with its text | markdown with MDX tags for panels, mentions and statuses | 6 |
| `adf-to-markdown` 1.0.1 | ADF to markdown | – | dropped with its text | markdown | 0 |
| `adf-to-md` 1.2.1 | ADF to markdown | – | dropped with its text, as are mentions, statuses and panels | markdown | 1 |
@@ -266,14 +270,17 @@ holding the same marks and link.
| `github-markdown-adf` 1.3.0 | both ways | a different document: the mention comes back as text, the status as inline code, the marks in the other order | dropped with its text | markdown | 3 |
| `markdown-to-adf` 0.2.20 | markdown to ADF; writes a quote as the node type `blockQuote`, which ADF spells `blockquote` | – | – | markdown | 3 |
| `marklassian` 1.2.1 | markdown to ADF | – | – | markdown | 1 |
| `md-adf` 0.2.2 | both ways | a different document: the mention and the status come back as text, the marks in the other order, the panel as a quote | dropped with its text | markdown | 5 |
| `md-to-adf` 0.6.4 | markdown to ADF | – | – | markdown | 2 |
| `mdast-util-from-adf` 2.3.0 | ADF to an mdast tree, which `mdast-util-to-markdown` writes as markdown; throws on a status | – | throws | markdown | 3 |
| `mdast-util-from-adf` 2.3.0 | ADF to an mdast tree, which `mdast-util-to-markdown` 2.2.1 writes as markdown; throws on a status | – | throws | markdown | 3 |
The next table lists converters in other ecosystems and Atlassian's own paths. They are not run
here; each row is what the project's documentation says, on 2026-10-28.
The next table lists converters this comparison does not run: other ecosystems' libraries,
Atlassian's own paths, and one npm package that needs a browser. Each row is what the project's
documentation says, on 2026-10-28.
| Converter | Converts | Source |
| --- | --- | --- |
| `adf2md` 2.0.0, JavaScript for browsers | ADF to and from GitHub Flavored Markdown with MDX-style tags for Atlassian nodes; ships a browser bundle that needs a page, not Node | [npm](https://www.npmjs.com/package/adf2md) |
| `marklas` 0.8.6, Python | GitHub Flavored Markdown to and from ADF | [PyPI](https://pypi.org/project/marklas/) |
| `pyadf` 0.5.2, Python | ADF to markdown; a node it cannot render becomes an HTML element holding its attributes | [README](https://github.com/YoungseokCh/pyadf) |
| `jc-adf` 0.2.0, Rust | markdown to and from ADF; a node type it does not know goes through an `adf:<type>` fenced block | [crates.io](https://crates.io/crates/jc-adf) |
+24 -13
View File
@@ -1,22 +1,26 @@
import * as adf2markdown from "adf2markdown";
import * as adfCodec from "@larvit/adf-codec";
import * as adfConverter from "adf-converter";
import * as adfMd from "adf-md";
import * as adfToMarkdown from "adf-to-markdown";
import adfToMd from "adf-to-md";
import { loadAdf4j } from "@nthings.dev/adf4j-wasm";
import * as atlaskitJson from "@atlaskit/editor-json-transformer";
import * as atlaskitMarkdown from "@atlaskit/editor-markdown-transformer";
import { createRequire } from "node:module";
import * as extendedParser from "extended-markdown-adf-parser";
import * as faulander from "@faulander/md2adf";
import { fromADF } from "mdast-util-from-adf";
import * as githubMarkdownAdf from "github-markdown-adf";
import { isDeepStrictEqual } from "node:util";
import * as marklassian from "marklassian";
import { loadAdf4j } from "@nthings.dev/adf4j-wasm";
import * as markdownToAdf from "markdown-to-adf";
import { fromADF } from "mdast-util-from-adf";
import { markdownToJiraBlock } from "@wrtnlabs/markdown-to-adf";
import * as marklassian from "marklassian";
import * as mdAdf from "md-adf";
import mdToAdf from "md-to-adf";
import { readFileSync } from "node:fs";
import { toMarkdown as mdastToMarkdown } from "mdast-util-to-markdown";
import { readFileSync } from "node:fs";
import translateGithubMarkdown from "@complexthings/md-to-adf";
const { defaultSchema } = createRequire(import.meta.url)("@atlaskit/adf-schema/schema-default");
@@ -60,15 +64,18 @@ const converters = {
toAdf: (md) => json.encode(atlaskit.parse(md)),
toMarkdown: (doc) => atlaskit.encode(json.parse(doc)),
},
"@larvit/adf-codec": {
toAdf: (md) => adfCodec.losslessMarkdownToAdf(md).value,
toMarkdown: (doc) => adfCodec.adfToLosslessMarkdown(doc).value,
},
"@complexthings/md-to-adf": { toAdf: (md) => translateGithubMarkdown(md) },
"@faulander/md2adf": {
toAdf: (md) => faulander.markdownToAdf(md),
toMarkdown: (doc) => faulander.adfToMarkdown(doc),
},
"@larvit/adf-codec": {
toAdf: (md) => adfCodec.losslessMarkdownToAdf(md).value,
toMarkdown: (doc) => adfCodec.adfToLosslessMarkdown(doc).value,
},
"@nthings.dev/adf4j-wasm": { toMarkdown: (doc) => adf4j.convert(JSON.stringify(doc)) },
"@wrtnlabs/markdown-to-adf": { toAdf: (md) => markdownToJiraBlock(md) },
"adf-converter": { toMarkdown: (doc) => adfConverter.processADF(doc, adfConverter.markdownFormatter) },
"adf-md": {
toAdf: (md) => succeeded(adfMd.markdownToAdf(md)),
toMarkdown: (doc) => succeeded(adfMd.adfToMarkdown(doc)),
@@ -76,18 +83,22 @@ const converters = {
"adf-to-markdown": { toMarkdown: (doc) => adfToMarkdown.convertADFToMarkdown(doc) },
"adf-to-md": { toMarkdown: (doc) => adfToMd.convert(doc).result },
adf2markdown: { toMarkdown: (doc) => adf2markdown.adf2markdown(doc) },
"extended-markdown-adf-parser": {
toAdf: (md) => extended.markdownToAdf(md),
toMarkdown: (doc) => extended.adfToMarkdown(doc),
},
"github-markdown-adf": {
toAdf: (md) => githubMarkdownAdf.mdToAdf(md),
toMarkdown: (doc) => githubMarkdownAdf.adfToMd(doc),
},
"markdown-to-adf": { toAdf: (md) => markdownToAdf.markdownToAdf(md) },
"mdast-util-from-adf": { toMarkdown: (doc) => mdastToMarkdown(fromADF(doc)) },
"extended-markdown-adf-parser": {
toAdf: (md) => extended.markdownToAdf(md),
toMarkdown: (doc) => extended.adfToMarkdown(doc),
},
marklassian: { toAdf: (md) => marklassian.markdownToAdf(md) },
"md-adf": {
toAdf: (md) => mdAdf.markdownToAdf(md).value,
toMarkdown: (doc) => mdAdf.adfToMarkdown(doc).value,
},
"md-to-adf": { toAdf: (md) => mdToAdf(md) },
"mdast-util-from-adf": { toMarkdown: (doc) => mdastToMarkdown(fromADF(doc)) },
};
const show = (label, call) => {
+4
View File
@@ -8,9 +8,12 @@ docker run --rm --memory 2g --memory-swap 2g --ulimit core=0 -u "$(id -u):$(id -
npm install --before=2026-10-29 --ignore-scripts --no-audit --no-fund --silent \
@atlaskit/editor-json-transformer@10.0.0 \
@atlaskit/editor-markdown-transformer@6.3.1 \
@complexthings/md-to-adf@1.0.0 \
@faulander/md2adf@1.0.0 \
@larvit/adf-codec@0.2.0 \
@nthings.dev/adf4j-wasm@1.0.2 \
@wrtnlabs/markdown-to-adf@1.0.2 \
adf-converter@0.1.0 \
adf-md@0.2.0 \
adf-to-markdown@1.0.1 \
adf-to-md@1.2.1 \
@@ -19,6 +22,7 @@ docker run --rm --memory 2g --memory-swap 2g --ulimit core=0 -u "$(id -u):$(id -
github-markdown-adf@1.3.0 \
markdown-to-adf@0.2.20 \
marklassian@1.2.1 \
md-adf@0.2.2 \
md-to-adf@0.6.4 \
mdast-util-from-adf@2.3.0 \
mdast-util-to-markdown@2.2.1 &&