Skip to content

Commit de6fe6d

Browse files
author
cemacar
committed
first commit
0 parents  commit de6fe6d

File tree

9 files changed

+818
-0
lines changed

9 files changed

+818
-0
lines changed

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Composer
2+
/vendor/
3+
/composer.lock
4+
5+
# IDE
6+
/.idea/
7+
/.vscode/
8+
9+
# OS /
10+
.DS_Store
11+
Thumbs.db
12+
13+
# Log
14+
*.log
15+
.cache/
16+
.phpunit.result.cache
17+
18+
# Test
19+
/tmp/
20+
/tests/output/
21+
22+
# Other
23+
*.swp
24+
*.bak
25+
*.tmp
26+
*.orig

README.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# html-to-adf
2+
3+
A PHP library to convert **HTML**, **Markdown**, and **Plain Text** into Atlassian Document Format (ADF) — compatible with Jira & Confluence.
4+
5+
---
6+
7+
## Features
8+
9+
- Recursive HTML parsing via DOM
10+
- Headings, Paragraphs, Emphasis, Strong, Links, Lists, Code Blocks, Tables, Images
11+
- Markdown-to-ADF using `league/commonmark`
12+
- Plain text support
13+
- Pluggable converter architecture
14+
- Composer-based install
15+
- Testable, extensible & PSR-compliant
16+
17+
---
18+
19+
## Installation
20+
21+
```bash
22+
composer require your-vendor/html-to-adf
23+
```
24+
25+
---
26+
27+
## Usage
28+
29+
### Initialize `ConverterManager` and register converters
30+
31+
```php
32+
use HtmlToAdf\ConverterManager;
33+
use HtmlToAdf\Converters\HtmlConverter;
34+
use HtmlToAdf\Converters\MarkdownConverter;
35+
use HtmlToAdf\Converters\PlainTextConverter;
36+
37+
$manager = new ConverterManager();
38+
$manager->registerConverter(new HtmlConverter());
39+
$manager->registerConverter(new MarkdownConverter());
40+
$manager->registerConverter(new PlainTextConverter());
41+
```
42+
43+
---
44+
45+
### Convert HTML
46+
47+
```php
48+
$html = '<h2>Hello</h2><p>This is a <strong>test</strong>.</p>';
49+
$adf = $manager->convert('html', $html);
50+
51+
print_r($adf);
52+
```
53+
54+
---
55+
56+
### Convert Markdown
57+
58+
```php
59+
$markdown = "## Hello\nThis is a **test**.";
60+
$adf = $manager->convert('markdown', $markdown);
61+
62+
print_r($adf);
63+
```
64+
65+
---
66+
67+
### Convert Plain Text
68+
69+
```php
70+
$text = "Just a simple paragraph.";
71+
$adf = $manager->convert('text', $text);
72+
73+
print_r($adf);
74+
```
75+
76+
---
77+
78+
## ADF Output Example
79+
80+
**Input:**
81+
82+
```html
83+
<p>Hello <strong>world</strong>!</p>
84+
```
85+
86+
**Output:**
87+
88+
```json
89+
{
90+
"version": 1,
91+
"type": "doc",
92+
"content": [
93+
{
94+
"type": "paragraph",
95+
"content": [
96+
{ "type": "text", "text": "Hello " },
97+
{
98+
"type": "text",
99+
"text": "world",
100+
"marks": [{ "type": "strong" }]
101+
},
102+
{ "type": "text", "text": "!" }
103+
]
104+
}
105+
]
106+
}
107+
```
108+
109+
---
110+
111+
## Architecture
112+
113+
| Component | Description |
114+
|----------------------|------------------------------------------------|
115+
| `ConverterManager` | Manages format dispatching to converters |
116+
| `ConverterInterface` | Interface for pluggable format converters |
117+
| `HtmlConverter` | Parses DOM and builds ADF recursively |
118+
| `MarkdownConverter` | Uses CommonMark, then delegates to HTML |
119+
| `PlainTextConverter` | Wraps text in paragraph ADF structure |
120+
| `AdfNodeBuilder` | (Optional) Helps build consistent ADF output |
121+
122+
123+
124+
---
125+
126+
## Author
127+
128+
**Cem Açar**
129+
cemacar03@gmail.com
130+
131+
---
132+
133+
## License
134+
135+
Licensed under the [MIT License](LICENSE).

composer.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "jira-adf/html-to-adf",
3+
"description": "Convert HTML, Markdown, and Plain Text to Atlassian Document Format (ADF)",
4+
"autoload": {
5+
"psr-4": {
6+
"HtmlToAdf\\": "src/"
7+
}
8+
},
9+
"require": {
10+
"ext-dom": "*",
11+
"league/commonmark": "^2.0"
12+
},
13+
"require-dev": {
14+
"phpunit/phpunit": "^10"
15+
},
16+
"license": "MIT"
17+
}

example.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
use HtmlToAdf\ConverterManager;
6+
use HtmlToAdf\Converters\HtmlConverter;
7+
use HtmlToAdf\Converters\MarkdownConverter;
8+
use HtmlToAdf\Converters\PlainTextConverter;
9+
10+
// Initialize the ADF Converter Manager
11+
$manager = new ConverterManager();
12+
13+
// Register available converters
14+
$manager->registerConverter(new HtmlConverter());
15+
$manager->registerConverter(new MarkdownConverter());
16+
$manager->registerConverter(new PlainTextConverter());
17+
18+
/**
19+
* ---------------------------
20+
* EXAMPLE 1 — HTML Conversion
21+
* ---------------------------
22+
*/
23+
$html = <<<HTML
24+
<h1>Project Documentation</h1>
25+
<p><strong>Important details</strong>, <em>notes</em>, <del>invalid info</del>, and <code>code snippets</code>.</p>
26+
<ul>
27+
<li>Real-time data processing</li>
28+
<li>API integration
29+
<ul>
30+
<li>GET /api/items</li>
31+
<li>POST /api/items</li>
32+
</ul>
33+
</li>
34+
<li>Automated testing support</li>
35+
</ul>
36+
<ol>
37+
<li>Installation
38+
<ol>
39+
<li>Run <code>composer install</code></li>
40+
<li>Copy and configure <code>.env</code></li>
41+
</ol>
42+
</li>
43+
</ol>
44+
<blockquote><strong>Note:</strong> PHP 8.1 or above is required.</blockquote>
45+
<pre><code class="language-js">fetch("https://api.example.com/data")
46+
.then(response => response.json())
47+
.then(data => console.log(data));</code></pre>
48+
<img src="https://example.com/image.jpg" alt="Diagram" />
49+
<table>
50+
<thead>
51+
<tr><th>Name</th><th>Role</th><th>Active</th></tr>
52+
</thead>
53+
<tbody>
54+
<tr><td>Cem</td><td>Admin</td><td>✅</td></tr>
55+
<tr><td>Ece</td><td>Editor</td><td>❌</td></tr>
56+
</tbody>
57+
</table>
58+
HTML;
59+
60+
echo "===== HTML to ADF =====\n";
61+
$htmlAdf = $manager->convert('html', $html);
62+
echo json_encode($htmlAdf, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
63+
echo "\n\n";
64+
65+
/**
66+
* ------------------------------
67+
* EXAMPLE 2 — Markdown Conversion
68+
* ------------------------------
69+
*/
70+
$markdown = <<<MD
71+
# Markdown Example
72+
73+
**Bold**, _italic_, ~~strikethrough~~, and \`inline code\`
74+
75+
- List item 1
76+
- List item 2
77+
- Nested list
78+
79+
> This is a blockquote
80+
81+
\`\`\`php
82+
echo "Hello World!";
83+
\`\`\`
84+
MD;
85+
86+
echo "===== Markdown to ADF =====\n";
87+
$markdownAdf = $manager->convert('markdown', $markdown);
88+
echo json_encode($markdownAdf, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
89+
echo "\n\n";
90+
91+
92+
$text = "This is a simple plain text. It will be wrapped in a paragraph node.";
93+
94+
echo "===== Plain Text to ADF =====\n";
95+
$textAdf = $manager->convert('text', $text);
96+
echo json_encode($textAdf, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
97+
echo "\n";
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
namespace HtmlToAdf\Contracts;
3+
4+
/**
5+
* Interface ConverterInterface
6+
*
7+
* Defines the contract for a converter that checks if a specific input format is supported
8+
* and converts the given content into Atlassian Document Format (ADF).
9+
*
10+
* @package HtmlToAdf\Contracts
11+
* @author Cem Açar <cemacar03@gmail.com>
12+
*/
13+
interface ConverterInterface
14+
{
15+
/**
16+
* Determines whether the given input format is supported by the converter.
17+
*
18+
* @param string $inputFormat The input format to check (e.g., 'html', 'markdown')
19+
* @return bool True if the format is supported, false otherwise
20+
*/
21+
public function supports(string $inputFormat): bool;
22+
23+
/**
24+
* Converts the given content into Atlassian Document Format (ADF).
25+
*
26+
* @param string $content The content to convert
27+
* @return array The content converted into ADF structure
28+
*/
29+
public function convert(string $content): array;
30+
}

src/ConverterManager.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
namespace HtmlToAdf;
3+
4+
use HtmlToAdf\Contracts\ConverterInterface;
5+
6+
/**
7+
* Class ConverterManager
8+
*
9+
* Manages and delegates conversion requests to registered converters
10+
* based on supported input formats.
11+
*
12+
* @package HtmlToAdf
13+
* @author Cem Açar <cemacar03@gmail.com>
14+
*/
15+
class ConverterManager
16+
{
17+
/**
18+
* @var ConverterInterface[] List of registered converters
19+
*/
20+
protected array $converters = [];
21+
22+
/**
23+
* Registers a converter to the manager.
24+
*
25+
* @param ConverterInterface $converter The converter instance to register
26+
* @return void
27+
*/
28+
public function registerConverter(ConverterInterface $converter): void
29+
{
30+
$this->converters[] = $converter;
31+
}
32+
33+
/**
34+
* Converts the given content using a matching converter for the specified format.
35+
*
36+
* @param string $inputFormat The format of the input content (e.g., 'html', 'markdown')
37+
* @param string $content The raw content to be converted
38+
* @return array Converted content in ADF format
39+
*
40+
* @throws \Exception If no suitable converter is found for the given format
41+
*/
42+
public function convert(string $inputFormat, string $content): array
43+
{
44+
foreach ($this->converters as $converter) {
45+
if ($converter->supports($inputFormat)) {
46+
return $converter->convert($content);
47+
}
48+
}
49+
50+
throw new \Exception("No converter found for format: $inputFormat");
51+
}
52+
}

0 commit comments

Comments
 (0)