Skip to content

Commit 43d34f0

Browse files
feat: Add markdown to ADF (Atlassian Document Format) adapter module
- Created comprehensive markdown to ADF converter in src/codegen/shared/markdown_adf/ - Supports all common markdown elements: headings, paragraphs, lists, code blocks, inline formatting - Includes type definitions for ADF document structure - Added comprehensive test suite with 20+ test cases - Added detailed documentation and usage examples - Added markdown>=3.4.0 dependency to pyproject.toml The adapter converts markdown text to Atlassian Document Format (ADF) JSON structure, which is used by Jira, Confluence, and other Atlassian products.
1 parent 3761b6c commit 43d34f0

7 files changed

Lines changed: 1069 additions & 0 deletions

File tree

=3.4.0

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Collecting markdown
2+
Downloading markdown-3.8-py3-none-any.whl.metadata (5.1 kB)
3+
Downloading markdown-3.8-py3-none-any.whl (106 kB)
4+
Installing collected packages: markdown
5+
Successfully installed markdown-3.8

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ dependencies = [
6363
"numpy>=2.2.2",
6464
"mcp[cli]",
6565
"neo4j",
66+
"markdown>=3.4.0",
6667
"modal>=0.73.45",
6768
"slack-sdk",
6869
"lox>=0.12.0",
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# Markdown to ADF Adapter
2+
3+
This module provides utilities to convert Markdown text to Atlassian Document Format (ADF), which is used by Atlassian products like Jira and Confluence.
4+
5+
## Overview
6+
7+
The Atlassian Document Format (ADF) is a JSON-based format that represents rich text content in Atlassian products. This adapter converts standard Markdown syntax to the corresponding ADF structure.
8+
9+
## Usage
10+
11+
### Basic Usage
12+
13+
```python
14+
from codegen.shared.markdown_adf import MarkdownToADFAdapter
15+
16+
# Create an adapter instance
17+
adapter = MarkdownToADFAdapter()
18+
19+
# Convert markdown to ADF
20+
markdown_text = """
21+
# Hello World
22+
23+
This is a paragraph with **bold** and *italic* text.
24+
25+
## Code Example
26+
27+
Here's some Python code:
28+
29+
```python
30+
def greet(name):
31+
print(f"Hello, {name}!")
32+
```
33+
34+
## Lists
35+
36+
- Item 1
37+
- Item 2 with `inline code`
38+
- Item 3
39+
40+
> This is a blockquote with important information.
41+
"""
42+
43+
adf_document = adapter.convert(markdown_text)
44+
print(json.dumps(adf_document, indent=2))
45+
```
46+
47+
### Output Structure
48+
49+
The adapter returns an `ADFDocument` which is a dictionary with the following structure:
50+
51+
```python
52+
{
53+
"version": 1,
54+
"type": "doc",
55+
"content": [
56+
# Array of ADF nodes
57+
]
58+
}
59+
```
60+
61+
## Supported Markdown Elements
62+
63+
### Text Formatting
64+
65+
| Markdown | ADF Mark Type | Description |
66+
|----------|---------------|-------------|
67+
| `**bold**` | `strong` | Bold text |
68+
| `*italic*` | `em` | Italic text |
69+
| `` `code` `` | `code` | Inline code |
70+
| `[link](url)` | `link` | Hyperlinks |
71+
| `~~strikethrough~~` | `strike` | Strikethrough text |
72+
73+
### Block Elements
74+
75+
| Markdown | ADF Node Type | Description |
76+
|----------|---------------|-------------|
77+
| `# Heading` | `heading` | Headings (H1-H6) |
78+
| Paragraphs | `paragraph` | Regular paragraphs |
79+
| ``` code ``` | `codeBlock` | Code blocks with optional language |
80+
| `- item` | `bulletList` | Bullet lists |
81+
| `1. item` | `orderedList` | Numbered lists |
82+
| `> quote` | `blockquote` | Block quotes |
83+
| `---` | `rule` | Horizontal rules |
84+
85+
### Advanced Features
86+
87+
- **Code blocks with syntax highlighting**: Language detection from fenced code blocks
88+
- **Nested lists**: Support for multi-level lists
89+
- **Mixed formatting**: Combination of multiple inline formats
90+
- **Link handling**: Automatic conversion of markdown links to ADF link marks
91+
92+
## Examples
93+
94+
### Simple Text with Formatting
95+
96+
```python
97+
markdown = "This is **bold** and *italic* text with `inline code`."
98+
adf = adapter.convert(markdown)
99+
```
100+
101+
Results in:
102+
```json
103+
{
104+
"version": 1,
105+
"type": "doc",
106+
"content": [
107+
{
108+
"type": "paragraph",
109+
"content": [
110+
{"type": "text", "text": "This is "},
111+
{"type": "text", "text": "bold", "marks": [{"type": "strong"}]},
112+
{"type": "text", "text": " and "},
113+
{"type": "text", "text": "italic", "marks": [{"type": "em"}]},
114+
{"type": "text", "text": " text with "},
115+
{"type": "text", "text": "inline code", "marks": [{"type": "code"}]},
116+
{"type": "text", "text": "."}
117+
]
118+
}
119+
]
120+
}
121+
```
122+
123+
### Code Block with Language
124+
125+
```python
126+
markdown = '''```python
127+
def hello():
128+
print("Hello, world!")
129+
```'''
130+
adf = adapter.convert(markdown)
131+
```
132+
133+
Results in:
134+
```json
135+
{
136+
"version": 1,
137+
"type": "doc",
138+
"content": [
139+
{
140+
"type": "codeBlock",
141+
"attrs": {"language": "python"},
142+
"content": [
143+
{"type": "text", "text": "def hello():\n print(\"Hello, world!\")"}
144+
]
145+
}
146+
]
147+
}
148+
```
149+
150+
### Lists
151+
152+
```python
153+
markdown = '''
154+
- First item
155+
- Second item with **bold** text
156+
- Third item
157+
'''
158+
adf = adapter.convert(markdown)
159+
```
160+
161+
Results in a bullet list with properly formatted list items.
162+
163+
## Error Handling
164+
165+
The adapter is designed to be robust and handle malformed markdown gracefully:
166+
167+
- **Invalid HTML**: Falls back to creating a simple paragraph with the original text
168+
- **Empty input**: Creates an empty paragraph
169+
- **Unsupported elements**: Extracts text content and wraps in paragraphs
170+
- **Malformed markdown**: Processes what it can and creates valid ADF structure
171+
172+
## Type Safety
173+
174+
The module includes comprehensive TypeScript-style type definitions:
175+
176+
- `ADFDocument`: The root document structure
177+
- `ADFNode`: Base node type with all possible properties
178+
- `ADFMark`: Inline formatting marks
179+
- Specific node types: `ADFTextNode`, `ADFParagraphNode`, `ADFHeadingNode`, etc.
180+
181+
## Dependencies
182+
183+
- `markdown`: Python markdown parser
184+
- `typing`: Type hints support
185+
186+
## Testing
187+
188+
The module includes comprehensive tests covering:
189+
190+
- Basic text conversion
191+
- All supported markdown elements
192+
- Complex nested structures
193+
- Error handling scenarios
194+
- Edge cases and malformed input
195+
196+
Run tests with:
197+
```bash
198+
pytest tests/shared/test_markdown_adf_adapter.py
199+
```
200+
201+
## Limitations
202+
203+
- **Tables**: Not yet implemented (markdown tables are complex to convert to ADF)
204+
- **Images**: Not implemented (requires media handling)
205+
- **Custom HTML**: Raw HTML in markdown is not processed
206+
- **Advanced ADF features**: Some ADF-specific features like panels, mentions, etc. are not supported
207+
208+
## Future Enhancements
209+
210+
- Table support
211+
- Image and media handling
212+
- Custom ADF node types (panels, mentions, etc.)
213+
- Configuration options for conversion behavior
214+
- Performance optimizations for large documents
215+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""
2+
Markdown to ADF (Atlassian Document Format) Adapter
3+
4+
This module provides utilities to convert Markdown text to Atlassian Document Format (ADF),
5+
which is used by Atlassian products like Jira and Confluence.
6+
"""
7+
8+
from .adapter import MarkdownToADFAdapter
9+
from .adf_types import ADFDocument, ADFNode, ADFMark
10+
11+
__all__ = ["MarkdownToADFAdapter", "ADFDocument", "ADFNode", "ADFMark"]

0 commit comments

Comments
 (0)