Skip to content

Instantly share code, notes, and snippets.

@maul-esel
Last active December 23, 2015 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maul-esel/6652045 to your computer and use it in GitHub Desktop.
Save maul-esel/6652045 to your computer and use it in GitHub Desktop.
a WIP pygments lexer for the liquid templating language
# 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 %}
# This is a non-completed pygments lexer for the liquid templating language.
#
# To use this, you must:
# 1. download the pygments-main source code
# 2. include the code below in the pygments/lexers/template.py file
# 3. modify __all__ in the same file to include 'LiquidLexer'
# 4. execute 'make mapfiles'
from pygments.lexers import combined
from pygments.token import Whitespace
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)
]
}
@parkr
Copy link

parkr commented Apr 23, 2014

NICE!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment