import flask from markupsafe import Markup from pygments import highlight from pygments.lexers import guess_lexer_for_filename, get_lexer_by_name, guess_lexer from pygments.lexers.templates import HtmlDjangoLexer from pygments.lexers.special import TextLexer from pygments.util import ClassNotFound from pymdownx import highlight as hlt from pygments.formatters import HtmlFormatter from src import constants as const FORMATTER = HtmlFormatter(nowrap=True) class TemplateHighlight(hlt.Highlight): @staticmethod def get_linenos(code: str): """ Generate line numbers for code block. """ return Markup("\n".join(map(str, range(1, code.count("\n") + 2)))) @staticmethod def _get_lexer(code: str, language: str | None, filename: str): """ Choose the best suitable lexer depending on present information about code. """ if language: return get_lexer_by_name(language) if filename.endswith((".html", ".j2")): return HtmlDjangoLexer() if filename: return guess_lexer_for_filename(filename, code) return guess_lexer(code) @classmethod def highlight_code(cls, code: str, language: str | None = None, filename: str | None = None): """ Highlight block of code. This function is used in `source/code.html` template. """ try: lexer = cls._get_lexer(code, language, filename or "") except ClassNotFound: lexer = TextLexer() return Markup( highlight(Markup(code.rstrip()).unescape(), lexer, FORMATTER)) def highlight(self, src, language, *_args, **_kwargs): return flask.render_template( "source/code.html", source=src, language=language, ) class TemplateHighlightExtension(hlt.HighlightExtension): def get_pymdownx_highlighter(self): return TemplateHighlight def create_missing_code_style_files(): for style in const.PYGMENTS_BUILTIN_STYLES: style_file = (const.CODE_STYLES_DIR / style).with_suffix(".css") if not style_file.exists(): formatter = HtmlFormatter(style=style) bg_defs = formatter.get_background_style_defs(".highlight") token_defs = formatter.get_token_style_defs(".highlight") with style_file.open("w") as file: file.write("\n".join(bg_defs + token_defs))