@mionita1980/adf-converter
v0.1.0
Published
Convert between Markdown and Atlassian Document Format (ADF), in both directions
Maintainers
Readme
ADF Converter
Convert between Markdown and Atlassian Document Format (ADF) — the JSON body format used by Jira, Confluence, and other Atlassian Cloud REST APIs.
Install
npm install -g adf-converterOr from source:
npm install
npm linkRequires Node 18.3+ (uses the built-in util.parseArgs).
Usage
convert [options] [file]
Arguments:
file File to convert. Use "-" or omit to read stdin.
Options:
-t, --to <format> Force output format: "adf" or "md". Overrides detection.
-o, --output <file> Write to this file instead of stdout.
-c, --compact Minify JSON output (ADF only; default is pretty-printed).
-i, --indent <n> Indent width for pretty JSON. Default: 2.
--loose-lists Put blank lines between list items (Markdown output only).
-h, --help Show this help.
-v, --version Show version.Direction is detected automatically
Input that parses as JSON with "type": "doc" is treated as ADF and converted to Markdown. Anything else is treated as Markdown and converted to ADF.
convert notes.md # Markdown -> ADF
convert notes.adf.json # ADF -> Markdown
cat doc.json | convert # ADF -> Markdown from stdin
convert notes.md -o notes.json # write to a fileUse --to when you want to override that — for example to normalise a Markdown file by round-tripping it through ADF:
convert notes.md --to md # Markdown -> ADF -> Markdown
convert doc.json | convert --to adf # full round tripWorking with the Jira API
Post a Markdown file as a Jira comment:
curl -X POST "$JIRA_URL/rest/api/3/issue/PROJ-1/comment" \
-H 'Content-Type: application/json' \
-u "$JIRA_USER:$JIRA_TOKEN" \
-d "$(convert comment.md --compact | jq '{body: .}')"Read an existing comment back as Markdown:
curl -s "$JIRA_URL/rest/api/3/issue/PROJ-1/comment" -u "$JIRA_USER:$JIRA_TOKEN" \
| jq '.comments[0].body' | convertUse as a library
const { markdownToAdf, adfToMarkdown, detectFormat } = require('adf-converter');
const adf = markdownToAdf('# Hello **world**');
// { version: 1, type: 'doc', content: [ ... ] }
const md = adfToMarkdown(adf);
// '# Hello **world**'
detectFormat(someString); // 'adf' | 'markdown'adfToMarkdown accepts either an ADF object or a JSON string, and takes an options object: { tightLists: false } puts blank lines between list items.
How the two directions work
Markdown → ADF uses Atlaskit directly: MarkdownTransformer.parse() then JSONTransformer.encode().
ADF → Markdown is implemented here. Atlaskit ships no reverse path — MarkdownTransformer.encode() is a stub that throws "This is not implemented yet". So src/adf2md.js parses the ADF into a ProseMirror node via JSONTransformer.parse(), then runs it through a custom prosemirror-markdown serializer. That serializer had to be written from scratch because ADF's node names differ from prosemirror-markdown's defaults (bulletList vs bullet_list) and because prosemirror-markdown has no table support at all.
Round-trip fidelity
Markdown that uses only standard constructs round-trips byte-for-byte (covered by tests): headings, emphasis, inline code, strikethrough, links, lists, blockquotes, fenced code with language, tables, and rules.
ADF → Markdown is lossy where Markdown has no equivalent. These degrade gracefully rather than failing:
| ADF node | Rendered as | Round-trips? |
|---|---|---|
| panel | Blockquote with a **TYPE:** label | No |
| taskList / taskItem | - [x] / - [ ] checkboxes | No |
| expand | <details><summary> HTML | No |
| mention | Its display text (@Alice) | No |
| status | Its display text | No |
| date | ISO date (2025-03-01) | No |
| media / mediaSingle |  image | Partially |
| inlineCard / blockCard | Autolink (<https://…>) | Partially |
| underline mark | <u> HTML | No |
| subsup mark | <sub> / <sup> HTML | No |
| textColor, backgroundColor | Dropped | No |
| Table colspan / rowspan | Flattened (GFM has no spans) | No |
If a table has no header row, an empty one is emitted, since GFM pipe tables require it.
Tests
npm test # 34 tests, both directions plus round trips