@@ -8,67 +8,208 @@ Category: template
8
8
*/
9
9
10
10
export default function ( hljs ) {
11
- var PARAMS = {
12
- className : 'params' ,
13
- begin : '\\(' , end : '\\)'
11
+ const regex = hljs . regex ;
12
+ const FUNCTION_NAMES = [
13
+ "attribute" ,
14
+ "block" ,
15
+ "constant" ,
16
+ "country_timezones" ,
17
+ "cycle" ,
18
+ "date" ,
19
+ "dump" ,
20
+ "html_classes" ,
21
+ "include" ,
22
+ "max" ,
23
+ "min" ,
24
+ "parent" ,
25
+ "random" ,
26
+ "range" ,
27
+ "source" ,
28
+ "template_from_string"
29
+ ] ;
30
+
31
+ const FILTERS = [
32
+ "abs" ,
33
+ "batch" ,
34
+ "capitalize" ,
35
+ "column" ,
36
+ "convert_encoding" ,
37
+ "country_name" ,
38
+ "currency_name" ,
39
+ "currency_symbol" ,
40
+ "data_uri" ,
41
+ "date" ,
42
+ "date_modify" ,
43
+ "default" ,
44
+ "escape" ,
45
+ "filter" ,
46
+ "first" ,
47
+ "format" ,
48
+ "format_currency" ,
49
+ "format_date" ,
50
+ "format_datetime" ,
51
+ "format_number" ,
52
+ "format_time" ,
53
+ "html_to_markdown" ,
54
+ "inky_to_html" ,
55
+ "inline_css" ,
56
+ "join" ,
57
+ "json_encode" ,
58
+ "keys" ,
59
+ "language_name" ,
60
+ "last" ,
61
+ "length" ,
62
+ "locale_name" ,
63
+ "lower" ,
64
+ "map" ,
65
+ "markdown" ,
66
+ "markdown_to_html" ,
67
+ "merge" ,
68
+ "nl2br" ,
69
+ "number_format" ,
70
+ "raw" ,
71
+ "reduce" ,
72
+ "replace" ,
73
+ "reverse" ,
74
+ "round" ,
75
+ "slice" ,
76
+ "slug" ,
77
+ "sort" ,
78
+ "spaceless" ,
79
+ "split" ,
80
+ "striptags" ,
81
+ "timezone_name" ,
82
+ "title" ,
83
+ "trim" ,
84
+ "u|0" ,
85
+ "upper" ,
86
+ "url_encode"
87
+ ] ;
88
+
89
+ let TAG_NAMES = [
90
+ "apply" ,
91
+ "autoescape" ,
92
+ "block" ,
93
+ "cache" ,
94
+ "deprecated" ,
95
+ "do" ,
96
+ "embed" ,
97
+ "extends" ,
98
+ "filter" ,
99
+ "flush" ,
100
+ "for" ,
101
+ "from" ,
102
+ "if" ,
103
+ "import" ,
104
+ "include" ,
105
+ "macro" ,
106
+ "sandbox" ,
107
+ "set" ,
108
+ "use" ,
109
+ "verbatim" ,
110
+ "with"
111
+ ] ;
112
+
113
+ TAG_NAMES = TAG_NAMES . concat ( TAG_NAMES . map ( t => `end${ t } ` ) ) ;
114
+
115
+ const STRING = {
116
+ scope : 'string' ,
117
+ variants : [
118
+ {
119
+ begin : / ' / ,
120
+ end : / ' /
121
+ } ,
122
+ {
123
+ begin : / " / ,
124
+ end : / " /
125
+ } ,
126
+ ]
14
127
} ;
15
128
16
- var FUNCTION_NAMES = 'attribute block constant cycle date dump include ' +
17
- 'max min parent random range source template_from_string' ;
129
+ const NUMBER = {
130
+ scope : "number" ,
131
+ match : / \d + /
132
+ } ;
18
133
19
- var FUNCTIONS = {
20
- beginKeywords : FUNCTION_NAMES ,
21
- keywords : { name : FUNCTION_NAMES } ,
22
- relevance : 0 ,
134
+ const PARAMS = {
135
+ begin : / \( / ,
136
+ end : / \) / ,
137
+ excludeBegin : true ,
138
+ excludeEnd : true ,
23
139
contains : [
24
- PARAMS
140
+ STRING ,
141
+ NUMBER
25
142
]
26
143
} ;
27
144
28
- var FILTER = {
29
- begin : / \| [ A - Z a - z _ ] + : ? / ,
30
- keywords :
31
- 'abs batch capitalize column convert_encoding date date_modify default ' +
32
- 'escape filter first format inky_to_html inline_css join json_encode keys last ' +
33
- 'length lower map markdown merge nl2br number_format raw reduce replace ' +
34
- 'reverse round slice sort spaceless split striptags title trim upper url_encode' ,
145
+
146
+ const FUNCTIONS = {
147
+ beginKeywords : FUNCTION_NAMES . join ( " " ) ,
148
+ keywords : { name : FUNCTION_NAMES } ,
149
+ relevance : 0 ,
150
+ contains : [ PARAMS ]
151
+ } ;
152
+
153
+ const FILTER = {
154
+ match : / \| (? = [ A - Z a - z _ ] + : ? ) / ,
155
+ beginScope : "punctuation" ,
156
+ relevance : 0 ,
35
157
contains : [
36
- FUNCTIONS
158
+ {
159
+ match : / [ A - Z a - z _ ] + : ? / ,
160
+ keywords : FILTERS
161
+ } ,
37
162
]
38
163
} ;
39
164
40
- var TAGS = 'apply autoescape block deprecated do embed extends filter flush for from ' +
41
- 'if import include macro sandbox set use verbatim with' ;
165
+ const tagNamed = ( tagnames , { relevance} ) => {
166
+ return {
167
+ beginScope : {
168
+ 1 : 'template-tag' ,
169
+ 3 : 'name'
170
+ } ,
171
+ relevance : relevance || 2 ,
172
+ endScope : 'template-tag' ,
173
+ begin : [
174
+ / \{ % / ,
175
+ / \s * / ,
176
+ regex . either ( ...tagnames )
177
+ ] ,
178
+ end : / % \} / ,
179
+ keywords : "in" ,
180
+ contains : [
181
+ FILTER ,
182
+ FUNCTIONS ,
183
+ STRING ,
184
+ NUMBER
185
+ ]
186
+ } ;
187
+ } ;
42
188
43
- TAGS = TAGS + ' ' + TAGS . split ( ' ' ) . map ( function ( t ) { return 'end' + t } ) . join ( ' ' ) ;
189
+ const CUSTOM_TAG_RE = / [ a - z _ ] + / ;
190
+ const TAG = tagNamed ( TAG_NAMES , { relevance : 2 } ) ;
191
+ const CUSTOM_TAG = tagNamed ( [ CUSTOM_TAG_RE ] , { relevance : 1 } ) ;
44
192
45
193
return {
46
194
name : 'Twig' ,
47
- aliases : [ 'craftcms' ] ,
195
+ aliases : [ 'craftcms' ] ,
48
196
case_insensitive : true ,
49
197
subLanguage : 'xml' ,
50
198
contains : [
51
199
hljs . COMMENT ( / \{ # / , / # \} / ) ,
200
+ TAG ,
201
+ CUSTOM_TAG ,
52
202
{
53
- className : 'template-tag' ,
54
- begin : / \{ % / , end : / % \} / ,
203
+ className : 'template-variable' ,
204
+ begin : / \{ \{ / ,
205
+ end : / \} \} / ,
55
206
contains : [
56
- {
57
- className : 'name' ,
58
- begin : / \w + / ,
59
- keywords : TAGS ,
60
- starts : {
61
- endsWithParent : true ,
62
- contains : [ FILTER , FUNCTIONS ] ,
63
- relevance : 0
64
- }
65
- }
207
+ 'self' ,
208
+ FILTER ,
209
+ FUNCTIONS ,
210
+ STRING ,
211
+ NUMBER
66
212
]
67
- } ,
68
- {
69
- className : 'template-variable' ,
70
- begin : / \{ \{ / , end : / \} \} / ,
71
- contains : [ 'self' , FILTER , FUNCTIONS ]
72
213
}
73
214
]
74
215
} ;
0 commit comments