https://github.com/faulander/md2adf
The repository implements bidirectional conversion between Markdown and Atlassian Document Format (ADF)
https://github.com/faulander/md2adf
adf atlassian confluence jira markdown md
Last synced: about 1 month ago
JSON representation
The repository implements bidirectional conversion between Markdown and Atlassian Document Format (ADF)
- Host: GitHub
- URL: https://github.com/faulander/md2adf
- Owner: faulander
- Created: 2025-12-02T08:27:19.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-12-02T08:56:30.000Z (6 months ago)
- Last Synced: 2025-12-05T03:52:50.589Z (6 months ago)
- Topics: adf, atlassian, confluence, jira, markdown, md
- Language: TypeScript
- Homepage:
- Size: 84 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# @faulander/md2adf
Bidirectional converter between **Markdown** and **Atlassian Document Format (ADF)** with built-in support for mentions, emojis, and smart links.
## Features
- **Bidirectional conversion** - Convert Markdown to ADF and ADF back to Markdown
- **Mentions** - Parse `@username` syntax and convert to/from ADF mention nodes
- **Emojis** - Support for `:shortcode:` emoji syntax with Unicode mapping
- **Smart Links** - Automatic detection of Jira/Confluence URLs as inline/block cards
- **Full Markdown support** - Headings, lists, task lists, tables, code blocks, blockquotes, and more
- **ADF validation** - JSON schema validation with semantic checks
- **TypeScript** - Full type definitions included
- **Dual build** - ESM and CommonJS outputs
## Installation
```bash
npm install @faulander/md2adf
```
## Quick Start
### Markdown to ADF
```typescript
import { markdownToAdf } from '@faulander/md2adf';
const markdown = `
# Hello World
This is a **bold** statement with a :smile: emoji.
- Task 1
- [x] Task 2 (done)
Check out [PROJ-123](https://company.atlassian.net/browse/PROJ-123)
`;
const adf = markdownToAdf(markdown);
console.log(JSON.stringify(adf, null, 2));
```
### ADF to Markdown
```typescript
import { adfToMarkdown } from '@faulander/md2adf';
const adf = {
version: 1,
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{ type: 'text', text: 'Hello ', marks: [{ type: 'strong' }] },
{ type: 'text', text: 'World!' }
]
}
]
};
const markdown = adfToMarkdown(adf);
console.log(markdown); // **Hello** World!
```
## API Reference
### Core Functions
#### `markdownToAdf(markdown, options?)`
Converts a Markdown string to an ADF document.
```typescript
import { markdownToAdf } from '@faulander/md2adf';
const adf = markdownToAdf('# Hello World', {
enableSmartLinks: true,
mentionResolver: (username) => ({ id: `user-${username}`, text: `@${username}` }),
smartLinkResolver: (url) => 'inline' | 'block' | 'link'
});
```
**Options:**
- `enableSmartLinks` - Enable automatic smart link detection (default: `true`)
- `mentionResolver` - Custom function to resolve `@mentions` to user IDs
- `smartLinkResolver` - Custom function to determine link type
#### `adfToMarkdown(adf, options?)`
Converts an ADF document to a Markdown string.
```typescript
import { adfToMarkdown } from '@faulander/md2adf';
const markdown = adfToMarkdown(adfDocument, {
mentionFormatter: (id, text) => `@${text || id}`
});
```
**Options:**
- `mentionFormatter` - Custom function to format mentions in Markdown output
### Smart Links
Smart links automatically convert Atlassian URLs to inline or block cards.
```typescript
import {
detectSmartLinkType,
isAtlassianUrl,
createSmartLinkResolver
} from '@faulander/md2adf';
// Detect link type
detectSmartLinkType('https://company.atlassian.net/browse/PROJ-123'); // 'inline'
detectSmartLinkType('https://company.atlassian.net/wiki/spaces/DOC'); // 'block'
detectSmartLinkType('https://example.com'); // 'link'
// Create custom resolver
const resolver = createSmartLinkResolver({
inlineDomains: ['github.com'],
blockDomains: ['notion.so'],
fallbackToAtlassianDetection: true
});
```
### Mentions
```typescript
import {
createMentionResolver,
createMentionFormatter,
parseMention
} from '@faulander/md2adf';
// Create resolver with user mapping
const resolver = createMentionResolver({
'johndoe': 'user-123',
'janedoe': 'user-456'
});
// Create custom formatter
const formatter = createMentionFormatter('linked'); // @[display](id)
// Parse mention strings
parseMention('@johndoe'); // { username: 'johndoe' }
parseMention('@[John Doe](user-123)'); // { displayName: 'John Doe', id: 'user-123' }
```
### Emojis
```typescript
import {
getEmojiUnicode,
getEmojiShortname,
isValidEmoji,
replaceEmojiShortnames
} from '@faulander/md2adf';
getEmojiUnicode('smile'); // '😄'
getEmojiShortname('😄'); // 'smile'
isValidEmoji('thumbsup'); // true
replaceEmojiShortnames('Hello :wave:!'); // 'Hello 👋!'
```
### Validation
```typescript
import { validateADFDocument, assertValidADF } from '@faulander/md2adf';
// Validate and get errors
const result = validateADFDocument(adf);
if (!result.valid) {
console.error(result.errors);
}
// Assert valid (throws on invalid)
assertValidADF(adf);
```
## Supported Markdown Syntax
| Syntax | Example | ADF Node Type |
|--------|---------|---------------|
| Headings | `# H1` to `###### H6` | `heading` |
| Bold | `**bold**` | `strong` mark |
| Italic | `*italic*` | `em` mark |
| Strikethrough | `~~strike~~` | `strike` mark |
| Inline code | `` `code` `` | `code` mark |
| Links | `[text](url)` | `link` mark |
| Images | `` | `mediaSingle` |
| Bullet lists | `- item` | `bulletList` |
| Ordered lists | `1. item` | `orderedList` |
| Task lists | `- [ ] todo` | `taskList` |
| Blockquotes | `> quote` | `blockquote` |
| Code blocks | ` ```lang ` | `codeBlock` |
| Tables | `\| a \| b \|` | `table` |
| Horizontal rule | `---` | `rule` |
| Mentions | `@username` | `mention` |
| Emojis | `:smile:` | `emoji` |
## Types
The package exports comprehensive TypeScript types:
```typescript
import type {
ADFDocument,
ADFNode,
ADFMark,
MarkdownToADFOptions,
ADFToMarkdownOptions,
MentionResolver,
SmartLinkResolver
} from '@faulander/md2adf';
```
## Error Handling
```typescript
import {
ConversionError,
InvalidMarkdownError,
InvalidADFError,
SchemaValidationError
} from '@faulander/md2adf';
try {
const adf = markdownToAdf(markdown);
} catch (error) {
if (error instanceof InvalidMarkdownError) {
console.error('Invalid Markdown:', error.message);
}
}
```
## Development
```bash
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Lint
npm run lint
# Format
npm run format
```
## License
MIT - Harald Fauland ([@faulander](https://github.com/faulander))