{"id":35145132,"url":"https://github.com/faulander/md2adf","last_synced_at":"2026-04-27T14:31:41.337Z","repository":{"id":327194653,"uuid":"1108257176","full_name":"faulander/md2adf","owner":"faulander","description":"The repository implements bidirectional conversion between Markdown and Atlassian Document Format (ADF)","archived":false,"fork":false,"pushed_at":"2025-12-02T08:56:30.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-05T03:52:50.589Z","etag":null,"topics":["adf","atlassian","confluence","jira","markdown","md"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/faulander.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-02T08:27:19.000Z","updated_at":"2025-12-02T08:57:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/faulander/md2adf","commit_stats":null,"previous_names":["faulander/md2adf"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/faulander/md2adf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faulander%2Fmd2adf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faulander%2Fmd2adf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faulander%2Fmd2adf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faulander%2Fmd2adf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/faulander","download_url":"https://codeload.github.com/faulander/md2adf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/faulander%2Fmd2adf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32341447,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T23:26:28.701Z","status":"online","status_checked_at":"2026-04-27T02:00:06.769Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adf","atlassian","confluence","jira","markdown","md"],"created_at":"2025-12-28T13:39:13.115Z","updated_at":"2026-04-27T14:31:41.326Z","avatar_url":"https://github.com/faulander.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @faulander/md2adf\n\nBidirectional converter between **Markdown** and **Atlassian Document Format (ADF)** with built-in support for mentions, emojis, and smart links.\n\n## Features\n\n- **Bidirectional conversion** - Convert Markdown to ADF and ADF back to Markdown\n- **Mentions** - Parse `@username` syntax and convert to/from ADF mention nodes\n- **Emojis** - Support for `:shortcode:` emoji syntax with Unicode mapping\n- **Smart Links** - Automatic detection of Jira/Confluence URLs as inline/block cards\n- **Full Markdown support** - Headings, lists, task lists, tables, code blocks, blockquotes, and more\n- **ADF validation** - JSON schema validation with semantic checks\n- **TypeScript** - Full type definitions included\n- **Dual build** - ESM and CommonJS outputs\n\n## Installation\n\n```bash\nnpm install @faulander/md2adf\n```\n\n## Quick Start\n\n### Markdown to ADF\n\n```typescript\nimport { markdownToAdf } from '@faulander/md2adf';\n\nconst markdown = `\n# Hello World\n\nThis is a **bold** statement with a :smile: emoji.\n\n- Task 1\n- [x] Task 2 (done)\n\nCheck out [PROJ-123](https://company.atlassian.net/browse/PROJ-123)\n`;\n\nconst adf = markdownToAdf(markdown);\nconsole.log(JSON.stringify(adf, null, 2));\n```\n\n### ADF to Markdown\n\n```typescript\nimport { adfToMarkdown } from '@faulander/md2adf';\n\nconst adf = {\n  version: 1,\n  type: 'doc',\n  content: [\n    {\n      type: 'paragraph',\n      content: [\n        { type: 'text', text: 'Hello ', marks: [{ type: 'strong' }] },\n        { type: 'text', text: 'World!' }\n      ]\n    }\n  ]\n};\n\nconst markdown = adfToMarkdown(adf);\nconsole.log(markdown); // **Hello** World!\n```\n\n## API Reference\n\n### Core Functions\n\n#### `markdownToAdf(markdown, options?)`\n\nConverts a Markdown string to an ADF document.\n\n```typescript\nimport { markdownToAdf } from '@faulander/md2adf';\n\nconst adf = markdownToAdf('# Hello World', {\n  enableSmartLinks: true,\n  mentionResolver: (username) =\u003e ({ id: `user-${username}`, text: `@${username}` }),\n  smartLinkResolver: (url) =\u003e 'inline' | 'block' | 'link'\n});\n```\n\n**Options:**\n- `enableSmartLinks` - Enable automatic smart link detection (default: `true`)\n- `mentionResolver` - Custom function to resolve `@mentions` to user IDs\n- `smartLinkResolver` - Custom function to determine link type\n\n#### `adfToMarkdown(adf, options?)`\n\nConverts an ADF document to a Markdown string.\n\n```typescript\nimport { adfToMarkdown } from '@faulander/md2adf';\n\nconst markdown = adfToMarkdown(adfDocument, {\n  mentionFormatter: (id, text) =\u003e `@${text || id}`\n});\n```\n\n**Options:**\n- `mentionFormatter` - Custom function to format mentions in Markdown output\n\n### Smart Links\n\nSmart links automatically convert Atlassian URLs to inline or block cards.\n\n```typescript\nimport {\n  detectSmartLinkType,\n  isAtlassianUrl,\n  createSmartLinkResolver\n} from '@faulander/md2adf';\n\n// Detect link type\ndetectSmartLinkType('https://company.atlassian.net/browse/PROJ-123'); // 'inline'\ndetectSmartLinkType('https://company.atlassian.net/wiki/spaces/DOC'); // 'block'\ndetectSmartLinkType('https://example.com'); // 'link'\n\n// Create custom resolver\nconst resolver = createSmartLinkResolver({\n  inlineDomains: ['github.com'],\n  blockDomains: ['notion.so'],\n  fallbackToAtlassianDetection: true\n});\n```\n\n### Mentions\n\n```typescript\nimport {\n  createMentionResolver,\n  createMentionFormatter,\n  parseMention\n} from '@faulander/md2adf';\n\n// Create resolver with user mapping\nconst resolver = createMentionResolver({\n  'johndoe': 'user-123',\n  'janedoe': 'user-456'\n});\n\n// Create custom formatter\nconst formatter = createMentionFormatter('linked'); // @[display](id)\n\n// Parse mention strings\nparseMention('@johndoe'); // { username: 'johndoe' }\nparseMention('@[John Doe](user-123)'); // { displayName: 'John Doe', id: 'user-123' }\n```\n\n### Emojis\n\n```typescript\nimport {\n  getEmojiUnicode,\n  getEmojiShortname,\n  isValidEmoji,\n  replaceEmojiShortnames\n} from '@faulander/md2adf';\n\ngetEmojiUnicode('smile'); // '😄'\ngetEmojiShortname('😄'); // 'smile'\nisValidEmoji('thumbsup'); // true\nreplaceEmojiShortnames('Hello :wave:!'); // 'Hello 👋!'\n```\n\n### Validation\n\n```typescript\nimport { validateADFDocument, assertValidADF } from '@faulander/md2adf';\n\n// Validate and get errors\nconst result = validateADFDocument(adf);\nif (!result.valid) {\n  console.error(result.errors);\n}\n\n// Assert valid (throws on invalid)\nassertValidADF(adf);\n```\n\n## Supported Markdown Syntax\n\n| Syntax | Example | ADF Node Type |\n|--------|---------|---------------|\n| Headings | `# H1` to `###### H6` | `heading` |\n| Bold | `**bold**` | `strong` mark |\n| Italic | `*italic*` | `em` mark |\n| Strikethrough | `~~strike~~` | `strike` mark |\n| Inline code | `` `code` `` | `code` mark |\n| Links | `[text](url)` | `link` mark |\n| Images | `![alt](url)` | `mediaSingle` |\n| Bullet lists | `- item` | `bulletList` |\n| Ordered lists | `1. item` | `orderedList` |\n| Task lists | `- [ ] todo` | `taskList` |\n| Blockquotes | `\u003e quote` | `blockquote` |\n| Code blocks | ` ```lang ` | `codeBlock` |\n| Tables | `\\| a \\| b \\|` | `table` |\n| Horizontal rule | `---` | `rule` |\n| Mentions | `@username` | `mention` |\n| Emojis | `:smile:` | `emoji` |\n\n## Types\n\nThe package exports comprehensive TypeScript types:\n\n```typescript\nimport type {\n  ADFDocument,\n  ADFNode,\n  ADFMark,\n  MarkdownToADFOptions,\n  ADFToMarkdownOptions,\n  MentionResolver,\n  SmartLinkResolver\n} from '@faulander/md2adf';\n```\n\n## Error Handling\n\n```typescript\nimport {\n  ConversionError,\n  InvalidMarkdownError,\n  InvalidADFError,\n  SchemaValidationError\n} from '@faulander/md2adf';\n\ntry {\n  const adf = markdownToAdf(markdown);\n} catch (error) {\n  if (error instanceof InvalidMarkdownError) {\n    console.error('Invalid Markdown:', error.message);\n  }\n}\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Run tests\nnpm test\n\n# Lint\nnpm run lint\n\n# Format\nnpm run format\n```\n\n## License\n\nMIT - Harald Fauland ([@faulander](https://github.com/faulander))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaulander%2Fmd2adf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffaulander%2Fmd2adf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffaulander%2Fmd2adf/lists"}