import re from markdown import Markdown from markdown.extensions import Extension from markdown.preprocessors import Preprocessor class GithubAdmonitionPreprocessor(Preprocessor): ADMONITION_PATTERN = re.compile(r'^!(?PNOTE|TIP|IMPORTANT|WARNING|CAUTION)\s*(?P.*?)$', re.MULTILINE) def run(self, lines): new_lines = [] i = 0 while i < len(lines): line = lines[i] match = self.ADMONITION_PATTERN.match(line) if match: admonition_type = match.group('type').lower() title = match.group('title').strip() # Start the div with appropriate classes new_lines.append(f'<div class="markdown-alert markdown-alert-{admonition_type}">') # Add the title if provided, otherwise use the type if title: new_lines.append(f'<p class="markdown-alert-title"><svg class="octicon" viewBox="0 0 16 16" version="1.1" width="16" height="16"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>{admonition_type.capitalize()}</p>') else: new_lines.append(f'<p class="markdown-alert-title"><svg class="octicon" viewBox="0 0 16 16" version="1.1" width="16" height="16"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>{admonition_type.capitalize()}</p>') # Find the content of the admonition i += 1 content_lines = [] while i < len(lines) and lines[i].strip() and not self.ADMONITION_PATTERN.match(lines[i]): content_lines.append(lines[i]) i += 1 # Add content and close the div if content_lines: new_lines.append('<p>' + '<br>'.join(content_lines) + '</p>') new_lines.append('</div>') # If we reached the end of the content or an empty line, don't increment i again if i >= len(lines) or not lines[i].strip(): continue else: new_lines.append(line) i += 1 return new_lines class GithubAdmonitionExtension(Extension): def extendMarkdown(self, md): md.preprocessors.register(GithubAdmonitionPreprocessor(md), 'github_admonition', 175) def convert_markdown_to_html(markdown_text): # Create Markdown instance with GitHub-style admonitions md = Markdown(extensions=[ 'markdown.extensions.fenced_code', 'markdown.extensions.tables', 'markdown.extensions.nl2br', GithubAdmonitionExtension(), # Add other extensions you need ]) # Convert markdown to HTML html = md.convert(markdown_text) return html