|
1 | 1 | from mistune.core import BaseRenderer |
2 | 2 | from mistune.util import escape as escape_text, striptags, safe_entity |
| 3 | +import re |
3 | 4 | from urllib.parse import urljoin, urlparse |
4 | 5 |
|
| 6 | +from md2bbcode.image_rewrite import rewrite_svg_url |
| 7 | + |
5 | 8 |
|
6 | 9 | class BBCodeRenderer(BaseRenderer): |
7 | 10 | """A renderer for converting Markdown to BBCode.""" |
@@ -56,7 +59,12 @@ def link(self, text: str, url: str, title=None) -> str: |
56 | 59 |
|
57 | 60 | def image(self, text: str, url: str, title=None) -> str: |
58 | 61 | alt_text = f' alt="{text}"' if text else '' |
59 | | - img_tag = f'[img{alt_text}]' + self.safe_url(url) + '[/img]' |
| 62 | + safe_url = self.safe_url(url) |
| 63 | + rewritten_url = rewrite_svg_url(safe_url) |
| 64 | + if rewritten_url is None: |
| 65 | + link_text = text or safe_url |
| 66 | + return f"[url={safe_url}]{link_text}[/url]" |
| 67 | + img_tag = f'[img{alt_text}]' + rewritten_url + '[/img]' |
60 | 68 | # Check if alt text starts with 'pixel' and treat it as pixel art |
61 | 69 | if text and text.lower().startswith('pixel'): |
62 | 70 | return f'[pixelate]{img_tag}[/pixelate]' |
@@ -115,6 +123,16 @@ def block_code(self, code: str, **attrs) -> str: |
115 | 123 | return f"[CODE]{escape_text(code)}[/CODE]\n" |
116 | 124 |
|
117 | 125 | def block_quote(self, text: str) -> str: |
| 126 | + # GFMD "alerts"/admonitions are expressed as a blockquote |
| 127 | + # Render these into a dedicated XenForo custom BBCode, rather than a normal QUOTE. |
| 128 | + m = re.match(r"^\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*", text, flags=re.IGNORECASE) |
| 129 | + if m: |
| 130 | + kind = m.group(1).lower() |
| 131 | + body = text[m.end():].strip() |
| 132 | + if body: |
| 133 | + return f"[admonition={kind}]{body}[/admonition]\n" |
| 134 | + return f"[admonition={kind}][/admonition]\n" |
| 135 | + |
118 | 136 | return '[QUOTE]\n' + text + '[/QUOTE]\n' |
119 | 137 |
|
120 | 138 | def block_html(self, html: str) -> str: |
|
0 commit comments