1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# -*- coding: utf-8 -*- #
# frozen_string_literal: true
module Rouge
module Lexers
class Jinja < TemplateLexer
title "Jinja"
desc "Django/Jinja template engine (jinja.pocoo.org)"
tag 'jinja'
aliases 'django'
mimetypes 'application/x-django-templating', 'application/x-jinja',
'text/html+django', 'text/html+jinja'
def self.keywords
@keywords ||= %w(as context do else extends from ignore missing
import include reversed recursive scoped
autoescape endautoescape block endblock call endcall
filter endfilter for endfor if endif macro endmacro
set endset trans endtrans with endwith without)
end
def self.tests
@tests ||= %w(callable defined divisibleby equalto escaped even iterable
lower mapping none number odd sameas sequence string
undefined upper)
end
def self.pseudo_keywords
@pseudo_keywords ||= %w(true false none True False None)
end
def self.word_operators
@word_operators ||= %w(is in and or not)
end
state :root do
# Comments
rule %r/{#/, Comment, :comment
rule %r/##.*/, Comment
# Raw and verbatim
rule %r/({%-?)(\s*)(raw|verbatim)(\s*)(-?%})/ do |m|
groups Comment::Preproc, Text, Keyword, Text, Comment::Preproc
case m[3]
when "raw"
push :raw
when "verbatim"
push :verbatim
end
end
# Statements
rule %r/\{\%/ do
token Comment::Preproc
push :statement
end
# Expressions
rule %r/\{\{/ do
token Comment::Preproc
push :expression
end
rule(/(.+?)(?=\\|{{|{%|{#|##)/m) { delegate parent }
rule(/.+/m) { delegate parent }
end
state :filter do
# Filters are called like variable|foo(arg1, ...)
rule %r/(\|\s*)(\w+)/ do
groups Operator, Name::Function
end
end
state :function do
rule %r/(\w+)(\()/ do
groups Name::Function, Punctuation
end
end
state :text do
rule %r/\s+/m, Text
end
state :literal do
# Strings
rule %r/"(\\.|.)*?"/, Str::Double
rule %r/'(\\.|.)*?'/, Str::Single
# Numbers
rule %r/\d+(?=}\s)/, Num
# Arithmetic operators (+, -, *, **, //, /)
# TODO : implement modulo (%)
rule %r/(\+|\-|\*|\/\/?|\*\*?|=)/, Operator
# Comparisons operators (<=, <, >=, >, ==, ===, !=)
rule %r/(<=?|>=?|===?|!=)/, Operator
# Punctuation (the comma, [], ())
rule %r/,/, Punctuation
rule %r/\[/, Punctuation
rule %r/\]/, Punctuation
rule %r/\(/, Punctuation
rule %r/\)/, Punctuation
end
state :comment do
rule %r/[^#]+/m, Comment
rule(/#}/) { token Comment; pop! }
rule %r/#/, Comment
end
state :expression do
rule %r/\w+\.?/m, Name::Variable
mixin :filter
mixin :function
mixin :literal
mixin :text
rule %r/%}|}}/, Comment::Preproc, :pop!
end
state :statement do
rule %r/(\w+\.?)/ do |m|
if self.class.keywords.include?(m[0])
groups Keyword
elsif self.class.pseudo_keywords.include?(m[0])
groups Keyword::Pseudo
elsif self.class.word_operators.include?(m[0])
groups Operator::Word
elsif self.class.tests.include?(m[0])
groups Name::Builtin
else
groups Name::Variable
end
end
mixin :filter
mixin :function
mixin :literal
mixin :text
rule %r/\%\}/, Comment::Preproc, :pop!
end
state :raw do
rule %r/({%-?)(\s*)(endraw)(\s*)(-?%})/ do
groups Comment::Preproc, Text, Keyword, Text, Comment::Preproc
pop!
end
rule %r/[^{]+/, Text
rule %r/{/, Text
end
state :verbatim do
rule %r/({%-?)(\s*)(endverbatim)(\s*)(-?%})/ do
groups Comment::Preproc, Text, Keyword, Text, Comment::Preproc
pop!
end
rule %r/[^{]+/, Text
rule %r/{/, Text
end
end
end
end
|