1# ext/pygmentplugin.py 2# Copyright 2006-2023 the Mako authors and contributors <see AUTHORS file> 3# 4# This module is part of Mako and is released under 5# the MIT License: http://www.opensource.org/licenses/mit-license.php 6 7from pygments import highlight 8from pygments.formatters.html import HtmlFormatter 9from pygments.lexer import bygroups 10from pygments.lexer import DelegatingLexer 11from pygments.lexer import include 12from pygments.lexer import RegexLexer 13from pygments.lexer import using 14from pygments.lexers.agile import Python3Lexer 15from pygments.lexers.agile import PythonLexer 16from pygments.lexers.web import CssLexer 17from pygments.lexers.web import HtmlLexer 18from pygments.lexers.web import JavascriptLexer 19from pygments.lexers.web import XmlLexer 20from pygments.token import Comment 21from pygments.token import Keyword 22from pygments.token import Name 23from pygments.token import Operator 24from pygments.token import Other 25from pygments.token import String 26from pygments.token import Text 27 28 29class MakoLexer(RegexLexer): 30 name = "Mako" 31 aliases = ["mako"] 32 filenames = ["*.mao"] 33 34 tokens = { 35 "root": [ 36 ( 37 r"(\s*)(\%)(\s*end(?:\w+))(\n|\Z)", 38 bygroups(Text, Comment.Preproc, Keyword, Other), 39 ), 40 ( 41 r"(\s*)(\%(?!%))([^\n]*)(\n|\Z)", 42 bygroups(Text, Comment.Preproc, using(PythonLexer), Other), 43 ), 44 ( 45 r"(\s*)(##[^\n]*)(\n|\Z)", 46 bygroups(Text, Comment.Preproc, Other), 47 ), 48 (r"""(?s)<%doc>.*?</%doc>""", Comment.Preproc), 49 ( 50 r"(<%)([\w\.\:]+)", 51 bygroups(Comment.Preproc, Name.Builtin), 52 "tag", 53 ), 54 ( 55 r"(</%)([\w\.\:]+)(>)", 56 bygroups(Comment.Preproc, Name.Builtin, Comment.Preproc), 57 ), 58 (r"<%(?=([\w\.\:]+))", Comment.Preproc, "ondeftags"), 59 ( 60 r"(?s)(<%(?:!?))(.*?)(%>)", 61 bygroups(Comment.Preproc, using(PythonLexer), Comment.Preproc), 62 ), 63 ( 64 r"(\$\{)(.*?)(\})", 65 bygroups(Comment.Preproc, using(PythonLexer), Comment.Preproc), 66 ), 67 ( 68 r"""(?sx) 69 (.+?) # anything, followed by: 70 (?: 71 (?<=\n)(?=%(?!%)|\#\#) | # an eval or comment line 72 (?=\#\*) | # multiline comment 73 (?=</?%) | # a python block 74 # call start or end 75 (?=\$\{) | # a substitution 76 (?<=\n)(?=\s*%) | 77 # - don't consume 78 (\\\n) | # an escaped newline 79 \Z # end of string 80 ) 81 """, 82 bygroups(Other, Operator), 83 ), 84 (r"\s+", Text), 85 ], 86 "ondeftags": [ 87 (r"<%", Comment.Preproc), 88 (r"(?<=<%)(include|inherit|namespace|page)", Name.Builtin), 89 include("tag"), 90 ], 91 "tag": [ 92 (r'((?:\w+)\s*=)\s*(".*?")', bygroups(Name.Attribute, String)), 93 (r"/?\s*>", Comment.Preproc, "#pop"), 94 (r"\s+", Text), 95 ], 96 "attr": [ 97 ('".*?"', String, "#pop"), 98 ("'.*?'", String, "#pop"), 99 (r"[^\s>]+", String, "#pop"), 100 ], 101 } 102 103 104class MakoHtmlLexer(DelegatingLexer): 105 name = "HTML+Mako" 106 aliases = ["html+mako"] 107 108 def __init__(self, **options): 109 super().__init__(HtmlLexer, MakoLexer, **options) 110 111 112class MakoXmlLexer(DelegatingLexer): 113 name = "XML+Mako" 114 aliases = ["xml+mako"] 115 116 def __init__(self, **options): 117 super().__init__(XmlLexer, MakoLexer, **options) 118 119 120class MakoJavascriptLexer(DelegatingLexer): 121 name = "JavaScript+Mako" 122 aliases = ["js+mako", "javascript+mako"] 123 124 def __init__(self, **options): 125 super().__init__(JavascriptLexer, MakoLexer, **options) 126 127 128class MakoCssLexer(DelegatingLexer): 129 name = "CSS+Mako" 130 aliases = ["css+mako"] 131 132 def __init__(self, **options): 133 super().__init__(CssLexer, MakoLexer, **options) 134 135 136pygments_html_formatter = HtmlFormatter( 137 cssclass="syntax-highlighted", linenos=True 138) 139 140 141def syntax_highlight(filename="", language=None): 142 mako_lexer = MakoLexer() 143 python_lexer = Python3Lexer() 144 if filename.startswith("memory:") or language == "mako": 145 return lambda string: highlight( 146 string, mako_lexer, pygments_html_formatter 147 ) 148 return lambda string: highlight( 149 string, python_lexer, pygments_html_formatter 150 ) 151