npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@complexthings/md-to-adf

v1.0.0

Published

Translate Markdown (Github) into Atlassian Document Format (ADF)

Readme

@complexthings/md-to-adf

Convert GitHub-flavored Markdown to Atlassian Document Format (ADF)

npm latest

ADF is the rich-text format used by Atlassian products (Jira, Confluence) to represent formatted content. This package lets you take any GitHub-flavored Markdown string and get back a fully structured ADF Document object, ready to send to the Atlassian REST API.

Installation

npm install @complexthings/md-to-adf

Usage

Basic Usage

import translateGITHUBMarkdownToADF from '@complexthings/md-to-adf'

const markdown = `# My Heading

This is a paragraph with **bold** and *italic* text.

- First item
- Second item
  - Nested item
`

const adfDocument = translateGITHUBMarkdownToADF(markdown)

// adfDocument is an adf-builder Document object.
// Call .toJSON() to get the plain JSON representation.
console.log(JSON.stringify(adfDocument, null, 2))

The returned object serializes to standard ADF JSON:

{
  "version": 1,
  "type": "doc",
  "content": [
    {
      "type": "heading",
      "attrs": { "level": 1 },
      "content": [{ "type": "text", "text": "My Heading" }]
    },
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "This is a paragraph with " },
        { "type": "text", "text": "bold", "marks": [{ "type": "strong" }] },
        { "type": "text", "text": " and " },
        { "type": "text", "text": "italic", "marks": [{ "type": "em" }] },
        { "type": "text", "text": " text." }
      ]
    },
    {
      "type": "bulletList",
      "content": [
        {
          "type": "listItem",
          "content": [
            { "type": "paragraph", "content": [{ "type": "text", "text": "First item" }] }
          ]
        }
      ]
    }
  ]
}

API

translateGITHUBMarkdownToADF(markdownText)

The single public export of this package. Takes a Markdown string and returns an ADF Document object (from the adf-builder library).

| Parameter | Type | Description | | -------------- | -------- | ------------------------------------ | | markdownText | string | GitHub-flavored Markdown source text |

Returns: Document — an adf-builder Document instance. Pass it directly to the Atlassian REST API or call .toJSON() / JSON.stringify() to obtain plain JSON.

import translateGITHUBMarkdownToADF from '@complexthings/md-to-adf'

const adf = translateGITHUBMarkdownToADF('# Hello\n\nWorld')
// Send to Confluence Page API, Jira issue body, etc.

Internal Modules

The following functions are the building blocks used by translateGITHUBMarkdownToADF. They are exported from their respective source files but are implementation details — prefer using the top-level function unless you need to work with the intermediate representation directly.

buildTreeFromMarkdown(rawTextMarkdown)source/markdownHandling.js

Parses a raw Markdown string into an intermediate representation (IR) tree (IRTreeNode[]). Handles code block collapsing, blockquote merging, paragraph continuation, and list nesting.

parseMarkdownLinetoIR(markdownLineTextWithTabs)source/markdownParsing.js

Parses a single Markdown line into an IRElement object with adfType, textToEmphasis, typeParam, textPosition, and optionally nodeAttached. Used internally by buildTreeFromMarkdown.

fillADFNodesWithMarkdown(currentParentNode, currentArrayOfNodesOfSameIndent)source/adfHandling.js

Recursively walks an IR tree and attaches ADF nodes to a parent Document. Handles list merging, list items, blockquotes, code blocks, paragraphs, and inline content.

attachTextToNodeSliceEmphasis(parentNode, textToEmphasis)source/adfEmphasisParsing.js

Parses a text string character-by-character for emphasis markers (*, _, ~~) and attaches ADF Text nodes with the appropriate marks (em, strong, strike) to the given parent node.

Supported Markdown Features

The following elements are recognized and converted to their ADF equivalents:

| Markdown | ADF Type | Notes | | --------------------------------- | ---------------- | --------------------------------------------------- | | # … ###### | heading | All six heading levels (h1–h6) | | Plain text / continuation lines | paragraph | Consecutive non-blank lines collapse into one block | | * text, - text, + text | bulletList | Nested via indentation (2-space increments) | | 1. text, 1) text | orderedList | Nested; preserves starting number | | `````` | codeBlock | Fenced; optional language tag (```js) | | `code` | inline code | text node with code mark | | *italic* / _italic_ | italic | text node with em mark | | **bold** / __bold__ | bold | text node with strong mark | | ~~strikethrough~~ | strikethrough | text node with strike mark | | [title](url) / [title](url "title") | link | text node with link mark | | :shortname: | emoji | emoji node with shortName attribute | | > text | blockQuote | Consecutive > lines merge into a single block | | ---, ***, ___ (3+ chars) | rule (divider) | Horizontal rule |

Emphasis markers can be combined: ***bold italic*** produces a text node with both strong and em marks. Strikethrough can be layered with bold/italic.

Code blocks inside list items are supported — the code block becomes a child of the list item's paragraph.

Migration from md-to-adf

If you are coming from the original md-to-adf package (unscoped, CommonJS):

| Topic | md-to-adf (original) | @complexthings/md-to-adf (this package) | | --------------- | ----------------------------------- | ----------------------------------------- | | Package name | md-to-adf | @complexthings/md-to-adf | | Module system | CommonJS (require) | ESM only (import) | | Node.js version | unconstrained | >= 22.0.0 | | Function name | translateGITHUBMarkdownToADF | translateGITHUBMarkdownToADF (same) | | Import syntax | const fn = require('md-to-adf') | import fn from '@complexthings/md-to-adf' |

The function signature and return value are identical. Only the import statement needs to change.

Node.js Version

Requires Node.js 22 or later ("engines": { "node": ">=22.0.0" }).

Known Limitations

  • No image rendering. Markdown images (![alt](url)) are parsed as links — the alt text becomes a linked text node rather than an image ADF node.
  • No table support. Markdown tables (| col | col |) are not recognized and will be treated as plain paragraph text.
  • No task list support. GitHub checkboxes (- [ ] item) are not handled — they fall through to plain bullet list items.
  • No HTML pass-through. Inline or block HTML is treated as literal text.
  • No reference-style links. Only inline links ([text](url)) are supported; reference-style links ([text][ref]) are not.
  • No setext-style headings. Only ATX headings (# H1) are recognized; underline-style headings (H1\n===) are not.
  • Strikethrough requires ~~ delimiters. Single-tilde (~text~) is not recognized.

Development

npm test               # Run tests (Vitest)
npm run test:watch     # Run tests in watch mode
npm run test:coverage  # Run tests with coverage report
npm run lint           # Lint source files
npm run lint:fix       # Lint and auto-fix
npm run build          # Build to dist/

Tests are written with Vitest. The original test suite used BDD-style Gherkin feature files (test/feature/*.feature) with step definitions (test/step/*.steps.js) via jest-cucumber-fusion. Fixture inputs and expected ADF outputs live in test/markdown-capture/.

Contributing

  1. Fork the repository and create a feature branch.
  2. Write a failing test that describes the behavior you're adding or fixing.
  3. Implement the change and make the test pass.
  4. Run npm test and npm run lint — both must be clean.
  5. Open a pull request with a clear description of what changed and why.

Please keep pull requests focused: one feature or fix per PR.

License

Apache-2.0