|
1 | 1 | import markdown |
2 | | -import string |
3 | 2 | from markdown.inlinepatterns import InlineProcessor |
4 | 3 | import xml.etree.ElementTree as etree |
5 | 4 | from markdown.preprocessors import Preprocessor |
@@ -116,60 +115,36 @@ def extendMarkdown(self, md): |
116 | 115 | md.postprocessors.register(footnote_postprocessor, "footnote_postprocessor", 25) |
117 | 116 |
|
118 | 117 |
|
119 | | -def strip_not_printable(text): |
120 | | - """Remove non-printable characters from a string.""" |
121 | | - return "".join(filter(lambda x: x in string.printable, text)) |
122 | | - |
123 | | - |
124 | | -# This regex matches the opening line for a mermaid code block in Obsidian's syntax. |
125 | | -MermaidRegex = re.compile(r"^```[\ \t]*[Mm]ermaid[\ \t]*$") |
126 | | - |
127 | | - |
128 | 118 | class MermaidPreprocessor(Preprocessor): |
129 | 119 | def run(self, lines): |
130 | 120 | new_lines = [] |
131 | | - in_mermaid_code = False |
132 | | - is_mermaid = False |
| 121 | + is_mermaid_block = False |
| 122 | + mermaid_lines = [] |
133 | 123 |
|
134 | 124 | for line in lines: |
135 | | - if not in_mermaid_code: |
136 | | - # Match the opening line of the mermaid code block |
137 | | - if MermaidRegex.match(line): |
138 | | - in_mermaid_code = True |
139 | | - new_lines.append('<div class="mermaid">') |
140 | | - is_mermaid = True |
141 | | - else: |
142 | | - new_lines.append(line) |
| 125 | + if line.strip() == "```mermaid": |
| 126 | + is_mermaid_block = True |
| 127 | + mermaid_lines = [] |
| 128 | + elif line.strip() == "```" and is_mermaid_block: |
| 129 | + is_mermaid_block = False |
| 130 | + mermaid_content = "\n".join(mermaid_lines) |
| 131 | + mermaid_html = self.mermaid_to_html(mermaid_content) |
| 132 | + new_lines.append(mermaid_html) |
| 133 | + elif is_mermaid_block: |
| 134 | + mermaid_lines.append(line) |
143 | 135 | else: |
144 | | - # Match the closing line of the mermaid code block |
145 | | - if line.strip() == "```": |
146 | | - in_mermaid_code = False |
147 | | - new_lines.append("</div>") |
148 | | - new_lines.append("") |
149 | | - else: |
150 | | - # Strip non-printable characters and add the mermaid code lines |
151 | | - new_lines.append(strip_not_printable(line).strip()) |
152 | | - |
153 | | - if is_mermaid: |
154 | | - # Add the mermaid.js initialization script to the bottom of the document if any mermaid diagrams were found. |
155 | | - new_lines.append("") |
156 | | - new_lines.append("""<script> |
157 | | - function initializeMermaid() { |
158 | | - mermaid.initialize({startOnLoad: true}); |
159 | | - } |
160 | | - if (document.readyState === "complete" || document.readyState === "interactive") { |
161 | | - setTimeout(initializeMermaid, 1); |
162 | | - } else { |
163 | | - document.addEventListener("DOMContentLoaded", initializeMermaid); |
164 | | - } |
165 | | - </script>""") |
| 136 | + new_lines.append(line) |
166 | 137 |
|
167 | 138 | return new_lines |
168 | 139 |
|
| 140 | + def mermaid_to_html(self, mermaid_content): |
| 141 | + escaped_content = mermaid_content.replace('"', """) |
| 142 | + return f'<div class="mermaid">{escaped_content}</div>' |
| 143 | + |
169 | 144 |
|
170 | 145 | class MermaidExtension(Extension): |
171 | 146 | def extendMarkdown(self, md): |
172 | | - md.preprocessors.register(MermaidPreprocessor(md), "mermaid", 35) |
| 147 | + md.preprocessors.register(MermaidPreprocessor(md), "mermaid", 175) |
173 | 148 |
|
174 | 149 |
|
175 | 150 | # Regular expression to match Obsidian callout syntax |
|
0 commit comments