Is there a way to convert from HTML to ADF using TypeScript on NodeJS?

Hey Atlassians,

I don’t want to be rude, but your libraries and documentation are complete mess. How one can convert in October 2025 from HTML to ADF on NodeJS? I still can’t find a way to do it:

  1. There are bunch of libraries on NPM. The most recent seems to be @atlaskit/adf-utils, but it has zero documentation. The links to the repository on BitBucket also don’t have anything. The only thing I was able to find, is this link, which is useless.
  2. The ticket (JRACLOUD-77436) says that there used to be endpoint to convert HTML2ADF, but it is now gone.
  3. The only working example I was able to find is here. However, in doesn’t work in NodeJS. if you switch to the code and try to get only the necessarily code to compile on NodeJS, it doesn’t work - it seems it is designed to work only in a browser. Here it is:
import { JIRATransformer } from '@atlaskit/editor-jira-transformer';
import { defaultSchema } from '@atlaskit/adf-schema/schema-default';
import { JSONTransformer } from '@atlaskit/editor-json-transformer';


const jiraTransformer = new JIRATransformer(defaultSchema);
const adfTransformer = new JSONTransformer();

function getADF(html: string) {
	const pmNode = jiraTransformer.parse(html);
	return adfTransformer.encode(pmNode);
}


const adf = getADF('<p>Hello World</p>');

console.log(adf);

Here is the error:

var parser = new window.DOMParser();
               ^
ReferenceError: window is not defined

All this is a horrible developer experience. Can you help? Is that possible at all?

2 Likes

It’s a real pain. here is one idea for you to test:

import TurndownService from 'turndown';
import { MarkdownTransformer } from '@atlaskit/editor-markdown-transformer';
import { JSONTransformer } from '@atlaskit/editor-json-transformer';
import defaultSchema from '@atlaskit/adf-schema/schema-default';

const turndownService = new TurndownService({ headingStyle: 'atx' });
const markdownTransformer = new MarkdownTransformer(defaultSchema);
const jsonTransformer = new JSONTransformer();


...
    const markdown = turndownService.turndown(String(html || ''));
    const node = markdownTransformer.parse(markdown);
    return adfDoc = jsonTransformer.encode(node);
1 Like

Thank you. I tried this and I’m not sure how it works for you, but here it doesn’t. I hit the problem with these Atlassian libraries which I reported some time ago here (and I heard only crickets so far). They seem to be not ESM ready. If I just use the code as you pasted it, e.g.:

import TurndownService from 'turndown';
import { MarkdownTransformer } from '@atlaskit/editor-markdown-transformer';
import { JSONTransformer } from '@atlaskit/editor-json-transformer';
import defaultSchema from '@atlaskit/adf-schema/schema-default';

const turndownService = new TurndownService({ headingStyle: 'atx' });
const markdownTransformer = new MarkdownTransformer(defaultSchema);
const jsonTransformer = new JSONTransformer();

const html = '<strong>Hello world!</strong>';

const markdown = turndownService.turndown(html);
const node = markdownTransformer.parse(markdown);
const adfDoc = jsonTransformer.encode(node);

console.log(adfDoc);

I get the following error:

node index.js 
node:internal/modules/run_main:105
    triggerUncaughtException(
    ^

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/Users/myu/test/mrkdown2adf-test/node_modules/@atlaskit/adf-schema/schema-default' is not supported resolving ES modules imported from /Users/myu/test/mrkdown2adf-test/index.js
Did you mean to import "@atlaskit/adf-schema/dist/cjs/schema/default-schema.js"?
    at finalizeResolution (node:internal/modules/esm/resolve:262:11)
    at moduleResolve (node:internal/modules/esm/resolve:859:10)
    at defaultResolve (node:internal/modules/esm/resolve:983:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:799:12)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:723:25)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:706:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:307:38)
    at #link (node:internal/modules/esm/module_job:170:49) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///Users/myu/test/mrkdown2adf-test/node_modules/@atlaskit/adf-schema/schema-default'
}

Node.js v24.1.0

If I change it from import defaultSchema from '@atlaskit/adf-schema/schema-default'; to @atlaskit/adf-schema/dist/cjs/schema/default-schema.js, then there is another error:

node index.js
/Users/myu/test/mrkdown2adf-test/node_modules/@atlaskit/editor-markdown-transformer/dist/cjs/index.js:199
        if (schema[key][idx]) {
                       ^

TypeError: Cannot read properties of undefined (reading 'blockquote')
    at /Users/myu/test/mrkdown2adf-test/node_modules/@atlaskit/editor-markdown-transformer/dist/cjs/index.js:199:24
    at Array.forEach (<anonymous>)
    at new MarkdownTransformer (/Users/myu/test/mrkdown2adf-test/node_modules/@atlaskit/editor-markdown-transformer/dist/cjs/index.js:197:24)
    at file:///Users/myu/test/mrkdown2adf-test/index.js:7:29
    at ModuleJob.run (node:internal/modules/esm/module_job:327:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:663:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:99:5)

Node.js v24.1.0

This is my package.json :

{
  "name": "mrkdown2adf-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "module",
  "dependencies": {
    "@atlaskit/adf-schema": "^51.3.2",
    "@atlaskit/editor-json-transformer": "^8.31.0",
    "@atlaskit/editor-markdown-transformer": "^5.20.0",
    "turndown": "^7.2.1"
  }
}

Sorry to not be able to upload the whole project, but this broken forum doesn’t allow me to upload attachments. I got the following error:

Even if it worked, I wouldn’t go with this approach. From HTML to Markdown to ADF seems too risky for me. I thought anyone who dares to invent new formats must also maintain libraries that allow people to convert industry standard formats (HTML) into this ADF, but it seems Atlassian don’t share this opinion.

We use Forge with ESM syntax, however in order to make it work we had to remove ”type”: “module” from package.json, because the Forge bundler did not work with it.