Files
zulip/zerver/lib/markdown/include.py
Eeshan Garg bfbd77ca5c markdown: Organize preprocessor priorities in one place.
All of our custom Markdown extensions have priorities that govern
the order in which the preprocessors will be run. It is more
convenient to have these all in one file so that you can easily
discern the order at first glance.

Thanks to Alya Abbott for reporting the bug that led to this
refactoring!
2021-09-20 16:57:43 -07:00

71 lines
2.5 KiB
Python

import os
import re
from typing import Any, List
import markdown
from markdown_include.include import IncludePreprocessor, MarkdownInclude
from zerver.lib.exceptions import InvalidMarkdownIncludeStatement
from zerver.lib.markdown.preprocessor_priorities import PREPROCESSOR_PRIORITES
INC_SYNTAX = re.compile(r"\{!\s*(.+?)\s*!\}")
class MarkdownIncludeCustom(MarkdownInclude):
def extendMarkdown(self, md: markdown.Markdown) -> None:
md.preprocessors.register(
IncludeCustomPreprocessor(md, self.getConfigs()),
"include_wrapper",
PREPROCESSOR_PRIORITES["include"],
)
class IncludeCustomPreprocessor(IncludePreprocessor):
"""
This is a custom implementation of the markdown_include
extension that checks for include statements and if the included
macro file does not exist or can't be opened, raises a custom
JsonableError exception. The rest of the functionality is identical
to the original markdown_include extension.
"""
def run(self, lines: List[str]) -> List[str]:
done = False
while not done:
for line in lines:
loc = lines.index(line)
m = INC_SYNTAX.search(line)
if m:
filename = m.group(1)
filename = os.path.expanduser(filename)
if not os.path.isabs(filename):
filename = os.path.normpath(
os.path.join(self.base_path, filename),
)
try:
with open(filename, encoding=self.encoding) as r:
text = r.readlines()
except Exception as e:
print(f"Warning: could not find file {filename}. Error: {e}")
lines[loc] = INC_SYNTAX.sub("", line)
raise InvalidMarkdownIncludeStatement(m.group(0).strip())
line_split = INC_SYNTAX.split(line)
if len(text) == 0:
text.append("")
for i in range(len(text)):
text[i] = text[i].rstrip("\r\n")
text[0] = line_split[0] + text[0]
text[-1] = text[-1] + line_split[2]
lines = lines[:loc] + text + lines[loc + 1 :]
break
else:
done = True
return lines
def makeExtension(*args: Any, **kwargs: str) -> MarkdownIncludeCustom:
return MarkdownIncludeCustom(kwargs)