diff options
author | Tim Hatch <tim@timhatch.com> | 2014-06-07 08:04:23 -0700 |
---|---|---|
committer | Tim Hatch <tim@timhatch.com> | 2014-06-07 08:04:23 -0700 |
commit | d85138f7cd0ed4abfd4142f9957ccf7d9c9bfc1d (patch) | |
tree | 9c446d3f213705268800c25316e75ea67d5ecc89 | |
parent | 1725e215f9833d271462ccc7d3bd5fc7c0e41bab (diff) | |
download | pygments-d85138f7cd0ed4abfd4142f9957ccf7d9c9bfc1d.tar.gz |
Import liquid lexer from #977
Resolves #977
-rw-r--r-- | pygments/lexers/_mapping.py | 1 | ||||
-rw-r--r-- | pygments/lexers/templates.py | 173 | ||||
-rw-r--r-- | tests/examplefiles/example.liquid | 42 |
3 files changed, 213 insertions, 3 deletions
diff --git a/pygments/lexers/_mapping.py b/pygments/lexers/_mapping.py index 70159bdb..39439d1c 100644 --- a/pygments/lexers/_mapping.py +++ b/pygments/lexers/_mapping.py @@ -191,6 +191,7 @@ LEXERS = { 'LassoXmlLexer': ('pygments.lexers.templates', 'XML+Lasso', ('xml+lasso',), (), ('application/xml+lasso',)), 'LighttpdConfLexer': ('pygments.lexers.text', 'Lighttpd configuration file', ('lighty', 'lighttpd'), (), ('text/x-lighttpd-conf',)), 'LimboLexer': ('pygments.lexers.inferno', 'Limbo', ('limbo',), ('*.b',), ('text/limbo',)), + 'LiquidLexer': ('pygments.lexers.templates', 'liquid', ('liquid',), ('*.liquid',), ()), 'LiterateAgdaLexer': ('pygments.lexers.functional', 'Literate Agda', ('lagda', 'literate-agda'), ('*.lagda',), ('text/x-literate-agda',)), 'LiterateCryptolLexer': ('pygments.lexers.functional', 'Literate Cryptol', ('lcry', 'literate-cryptol', 'lcryptol'), ('*.lcry',), ('text/x-literate-cryptol',)), 'LiterateHaskellLexer': ('pygments.lexers.functional', 'Literate Haskell', ('lhs', 'literate-haskell', 'lhaskell'), ('*.lhs',), ('text/x-literate-haskell',)), diff --git a/pygments/lexers/templates.py b/pygments/lexers/templates.py index 50579c61..2eae4aa6 100644 --- a/pygments/lexers/templates.py +++ b/pygments/lexers/templates.py @@ -18,9 +18,10 @@ from pygments.lexers.compiled import JavaLexer from pygments.lexers.jvm import TeaLangLexer from pygments.lexers.text import YamlLexer from pygments.lexer import Lexer, DelegatingLexer, RegexLexer, bygroups, \ - include, using, this, default + include, using, this, default, combined from pygments.token import Error, Punctuation, \ - Text, Comment, Operator, Keyword, Name, String, Number, Other, Token + Text, Comment, Operator, Keyword, Name, String, Number, Other, Token, \ + Whitespace from pygments.util import html_doctype_matches, looks_like_xml __all__ = ['HtmlPhpLexer', 'XmlPhpLexer', 'CssPhpLexer', @@ -41,7 +42,7 @@ __all__ = ['HtmlPhpLexer', 'XmlPhpLexer', 'CssPhpLexer', 'VelocityHtmlLexer', 'VelocityXmlLexer', 'SspLexer', 'TeaTemplateLexer', 'LassoHtmlLexer', 'LassoXmlLexer', 'LassoCssLexer', 'LassoJavascriptLexer', 'HandlebarsLexer', - 'HandlebarsHtmlLexer', 'YamlJinjaLexer'] + 'HandlebarsHtmlLexer', 'YamlJinjaLexer', 'LiquidLexer'] class ErbLexer(Lexer): @@ -1851,3 +1852,169 @@ class YamlJinjaLexer(DelegatingLexer): def __init__(self, **options): super(YamlJinjaLexer, self).__init__(YamlLexer, DjangoLexer, **options) + + +class LiquidLexer(RegexLexer): + name = 'liquid' + aliases = ['liquid'] + filenames = ['*.liquid'] + + tokens = { + 'root': [ + (r'[^\{]+', Text), + (r'(\{%)(\s*)', bygroups(Punctuation, Whitespace), 'tag-or-block'), # tags and block tags + (r'(\{\{)(\s*)([^\s(\}\})]+)', bygroups(Punctuation, Whitespace, using(this, state = 'generic')), 'output'), # output tags + (r'\{', Text) + ], + + 'tag-or-block': [ + # builtin logic blocks + (r'(if|unless|elsif|case)(?=\s+)', Keyword.Reserved, 'condition'), + (r'(when)(\s+)', bygroups(Keyword.Reserved, Whitespace), combined('end-of-block', 'whitespace', 'generic')), + (r'(else)(\s*)(%\})', bygroups(Keyword.Reserved, Whitespace, Punctuation), '#pop'), + + # other builtin blocks + (r'(capture)(\s+)([^\s%]+)(\s*)(%\})', bygroups(Name.Tag, Whitespace, using(this, state = 'variable'), Whitespace, Punctuation), '#pop'), + (r'(comment)(\s*)(%\})', bygroups(Name.Tag, Whitespace, Punctuation), 'comment'), + (r'(raw)(\s*)(%\})', bygroups(Name.Tag, Whitespace, Punctuation), 'raw'), + + # end of block + (r'(end(case|unless|if))(\s*)(%\})', bygroups(Keyword.Reserved, None, Whitespace, Punctuation), '#pop'), + (r'(end([^\s%]+))(\s*)(%\})', bygroups(Name.Tag, None, Whitespace, Punctuation), '#pop'), + + # builtin tags (assign and include are handled together with usual tags) + (r'(cycle)(\s+)(([^\s:]*)(:))?(\s*)', bygroups(Name.Tag, Whitespace, None, using(this, state = 'generic'), Punctuation, Whitespace), 'variable-tag-markup'), + + # other tags or blocks + (r'([^\s%]+)(\s*)', bygroups(Name.Tag, Whitespace), 'tag-markup') + ], + + 'output': [ + include('whitespace'), + ('\}\}', Punctuation, '#pop'), # end of output + + (r'\|', Punctuation, 'filters') + ], + + 'filters': [ + include('whitespace'), + (r'\}\}', Punctuation, ('#pop', '#pop')), # end of filters and output + + (r'([^\s\|:]+)(:?)(\s*)', bygroups(Name.Function, Punctuation, Whitespace), 'filter-markup') + ], + + 'filter-markup': [ + (r'\|', Punctuation, '#pop'), + include('end-of-tag'), + include('default-param-markup') + ], + + 'condition': [ + include('end-of-block'), + include('whitespace'), + + (r'([^\s=!><]+)(\s*)([=!><]=?)(\s*)([^\s]+)(\s*)(%\})', bygroups(using(this, state = 'generic'), Whitespace, Operator, Whitespace, using(this, state = 'generic'), Whitespace, Punctuation)), + (r'\b((!)|(not\b))', bygroups(None, Operator, Operator.Word)), + (r'([\w\.\'"]+)(\s+)(contains)(\s+)([\w\.\'"]+)', bygroups(using(this, state = 'generic'), Whitespace, Operator.Word, Whitespace, using(this, state = 'generic'))), + + include('generic'), + include('whitespace') + ], + + 'generic-value': [ + include('generic'), + include('end-at-whitespace') + ], + + 'operator': [ + (r'(\s*)((=|!|>|<)=?)(\s*)', bygroups(Whitespace, Operator, None, Whitespace), '#pop'), + (r'(\s*)(\bcontains\b)(\s*)', bygroups(Whitespace, Operator.Word, Whitespace), '#pop'), + ], + + 'end-of-tag': [ + (r'\}\}', Punctuation, '#pop') + ], + + 'end-of-block': [ + (r'%\}', Punctuation, ('#pop', '#pop')) + ], + + 'end-at-whitespace': [ + (r'\s+', Whitespace, '#pop') + ], + + # states for unknown markup + 'param-markup': [ + include('whitespace'), + (r'([^\s=:]+)(\s*)(=|:)', bygroups(Name.Attribute, Whitespace, Operator)), # params with colons or equals + (r'(\{\{)(\s*)([^\s\}])(\s*)(\}\})', bygroups(Punctuation, Whitespace, using(this, state = 'variable'), Whitespace, Punctuation)), # explicit variables + include('string'), + include('number'), + include('keyword'), + (r',', Punctuation) + ], + + 'default-param-markup': [ + include('param-markup'), + (r'.', Text) # fallback for switches / variables / un-quoted strings / ... + ], + + 'variable-param-markup': [ + include('param-markup'), + include('variable'), + (r'.', Text) # fallback + ], + + 'tag-markup': [ + (r'%\}', Punctuation, ('#pop', '#pop')), # end of tag + include('default-param-markup') + ], + + 'variable-tag-markup': [ + (r'%\}', Punctuation, ('#pop', '#pop')), # end of tag + include('variable-param-markup') + ], + + # states for different values types + 'keyword': [ + (r'\b(false|true)\b', Keyword.Constant) + ], + + 'variable': [ + (r'[a-zA-Z_]\w*', Name.Variable), + (r'(?<=\w)\.(?=\w)', Punctuation) + ], + + 'string': [ + (r"'[^']*'", String.Single), + (r'"[^"]*"', String.Double) + ], + + 'number': [ + (r'\d+\.\d+', Number.Float), + (r'\d+', Number.Integer) + ], + + 'generic': [ # decides for variable, string, keyword or number + include('keyword'), + include('string'), + include('number'), + include('variable') + ], + + 'whitespace': [ + (r'[ \t]+', Whitespace) + ], + + # states for builtin blocks + 'comment': [ + (r'(\{%)(\s*)(endcomment)(\s*)(%\})', bygroups(Punctuation, Whitespace, Name.Tag, Whitespace, Punctuation), ('#pop', '#pop')), + (r'.', Comment) + ], + + 'raw': [ + (r'[^\{]+', Text), + (r'(\{%)(\s*)(endraw)(\s*)(%\})', bygroups(Punctuation, Whitespace, Name.Tag, Whitespace, Punctuation), '#pop'), + (r'\{', Text) + ] + } diff --git a/tests/examplefiles/example.liquid b/tests/examplefiles/example.liquid new file mode 100644 index 00000000..8f3ea9e9 --- /dev/null +++ b/tests/examplefiles/example.liquid @@ -0,0 +1,42 @@ +# This is an example file. Process it with `./pygmentize -O full -f html -o /liquid-example.html example.liquid`. + +{% raw %} +some {{raw}} liquid syntax + +{% raw %} +{% endraw %} + +Just regular text - what happens? + +{% comment %}My lovely {{comment}} {% comment %}{% endcomment %} + +{% custom_tag params: true %} +{% custom_block my="abc" c = false %} + Just usual {{liquid}}. +{% endcustom_block %} + +{% another_tag "my string param" %} + +{{ variable | upcase }} +{{ var.field | textilize | markdownify }} +{{ var.field.property | textilize | markdownify }} +{{ 'string' | truncate: 100 param='df"g' }} + +{% cycle '1', 2, var %} +{% cycle 'group1': '1', var, 2 %} +{% cycle group2: '1', var, 2 %} + +{% if a == 'B' %} +{% elsif a == 'C%}' %} +{% else %} +{% endif %} + +{% unless not a %} +{% else %} +{% endunless %} + +{% case a %} +{% when 'B' %} +{% when 'C' %} +{% else %} +{% endcase %}
\ No newline at end of file |