Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add HTML to Markdown conversion for Discord embeds #16

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add HTML to Markdown conversion for Discord embeds
### Description

Add the `convertHtmlToMarkdown` function to convert HTML content into Markdown format to increase the quality of the Discord Webhook feature.

1. **Anchor Tags (`<a>`)**: Converts links to Markdown links
   - Example: `<a href="https://www.example.com">Example</a>` becomes `[Example](https://www.example.com)`

2. **Headings (`<h1>` to `<h6>`)**: Converts HTML headings to Markdown headings, with a maximum of three `#` characters
   - Example: `<h1>Title</h1>` becomes `# Title`

3. **Unordered Lists (`<ul>` and `<li>`)**: Converts unorderd lists to Markdown lists with dashes
   - Example: 
     ```html
     <ul>
       <li>Item 1</li>
       <li>Item 2</li>
     </ul>
     ```
     becomes
     ```
     - Item 1
     - Item 2
     ```

4. **Ordered Lists (`<ol>` and `<li>`)**: Converts ordered lists to numbered Markdown lists
   - Example:
     ```html
     <ol>
       <li>First item</li>
       <li>Second item</li>
     </ol>
     ```
     becomes
     ```
     1. First item
     2. Second item
     ```

5. **Bold Text (`<strong>`)**: Converts bold/strong text to markdown bold text
   - Example: `<strong>bold</strong>` becomes `**bold**`

6. **Italic Text (`<i>`)**: Converts italic text to Markdown italic text
   - Example: `<i>italic</i>` becomes `*italic*`

7. **Blockquotes (`<blockquote>`)**: Converts blockquotes to Markdown blockquotes
   - Example: `<blockquote>text</blockquote>` becomes `> text`

8. **Code (`<code>`)**: Converts code tags to Markdown code
   - Example: `<code>code</code>` becomes `` `code` ``

9. **Horizontal Rules (`<hr>`)**: Converts horizontal rules to Markdown horizontal rules
   - Example: `<hr>` becomes `---` (Discord does not yet support horizontal rules, but I think it's likely that they will be added in the future)

Screenshots of my tests:
![Screenshot 1](https://www.skydinse.net/storage/img/changelog-plugin-update-1.png)
![Screenshot 2](https://www.skydinse.net/storage/img/changelog-plugin-update-2.png)
![Screenshot 3](https://www.skydinse.net/storage/img/changelog-plugin-update-3.png)
Lunanuuu authored Jul 30, 2024
commit 653a354decddd528707c8c533ec400307a8970f8
51 changes: 50 additions & 1 deletion src/Models/Update.php
Original file line number Diff line number Diff line change
@@ -45,12 +45,61 @@ public function category()
return $this->belongsTo(Category::class);
}

public function convertHtmlToMarkdown($text)
{
// Convert <a> tags to Markdown links
$text = preg_replace_callback('/<a href="([^"]+)"[^>]*>(.*?)<\/a>/i', function ($matches) {
return '[' . $matches[2] . '](' . $matches[1] . ')';
}, $text);

// Convert <strong> to Markdown bold
$text = preg_replace('/<strong>(.*?)<\/strong>/i', '**$1**', $text);

// Convert <i> to Markdown italic
$text = preg_replace('/<i>(.*?)<\/i>/i', '*$1*', $text);

// Convert <h1> to <h6> into Markdown headings with a limit of 3 #
for ($i = 1; $i <= 6; $i++) {
$text = preg_replace('/<h' . $i . '[^>]*>(.*?)<\/h' . $i . '>/i', str_repeat('#', min($i, 3)) . ' $1', $text);
}

// Convert <ul> and <li> to Markdown lists
$text = preg_replace_callback('/<ul[^>]*>(.*?)<\/ul>/is', function ($matches) {
return preg_replace('/<li[^>]*>(.*?)<\/li>/is', '- $1', $matches[1]);
}, $text);

// Convert <ol> and <li> to numbered Markdown lists
$text = preg_replace_callback('/<ol[^>]*>(.*?)<\/ol>/is', function ($matches) {
$markdownList = '';
$items = preg_match_all('/<li[^>]*>(.*?)<\/li>/is', $matches[1], $liMatches);
foreach ($liMatches[1] as $index => $item) {
$markdownList .= ($index + 1) . '. ' . strip_tags($item) . PHP_EOL;
}
return $markdownList;
}, $text);

// Convert <blockquote> to Markdown blockquotes
$text = preg_replace('/<blockquote[^>]*>(.*?)<\/blockquote>/is', '> $1', $text);

// Convert <code> to Markdown inline code
$text = preg_replace('/<code>(.*?)<\/code>/is', '`$1`', $text);

// Convert <hr> to Markdown horizontal rule
$text = preg_replace('/<hr[^>]*>/i', '---', $text);

// Remove all remaining HTML tags
$text = strip_tags($text);

return $text;
}

public function createDiscordWebhook(User $author): DiscordWebhook
{

$embed = Embed::create()
->title($this->name)
->author($author->name, null, $author->getAvatar())
->description(Str::limit(strip_tags($this->description), 1995))
->description(Str::limit($this->convertHtmlToMarkdown($this->description), 1995))
->url(route('changelog.categories.show', $this->category))
->footer($this->category->name)
->timestamp(now());