11module . exports = grammar ( {
22 name : "htmldjango" ,
33
4- // Handle whitespace explicitly
5- extras : $ => [ ] ,
4+ word : $ => $ . _identifier ,
65
76 rules : {
87 template : $ => repeat (
@@ -13,16 +12,39 @@ module.exports = grammar({
1312 $ . _expression ,
1413 $ . _statement ,
1514 $ . _comment ,
16- $ . content ,
17- / \s + /
15+ $ . content
1816 ) ,
1917
2018 // General rules
21- keyword : $ => choice ( "on" , "off" , "with" , "as" , "silent" , "only" , "from" , "random" , "by" ) ,
19+ keyword : $ => token ( seq (
20+ choice (
21+ "on" ,
22+ "off" ,
23+ "with" ,
24+ "as" ,
25+ "silent" ,
26+ "only" ,
27+ "from" ,
28+ "random" ,
29+ "by"
30+ ) ,
31+ / \s /
32+ ) ) ,
33+ keyword_operator : $ => token ( seq (
34+ choice (
35+ "and" ,
36+ "or" ,
37+ "not" ,
38+ "in" ,
39+ "not in" ,
40+ "is" ,
41+ "is not"
42+ ) ,
43+ / \s /
44+ ) ) ,
2245 operator : $ => choice ( "==" , "!=" , "<" , ">" , "<=" , ">=" ) ,
23- keyword_operator : $ => choice ( "and" , "or" , "not" , "in" , "not in" , "is" , "is not" ) ,
24- number : $ => repeat1 ( / [ 0 - 9 ] / ) ,
25- boolean : $ => choice ( "True" , "False" ) ,
46+ number : $ => / [ 0 - 9 ] + / ,
47+ boolean : $ => token ( seq ( choice ( "True" , "False" ) , / \s / ) ) ,
2648 string : $ => seq (
2749 choice (
2850 seq ( "'" , repeat ( / [ ^ ' ] / ) , "'" ) ,
@@ -31,24 +53,23 @@ module.exports = grammar({
3153 repeat ( seq ( "|" , $ . filter ) )
3254 ) ,
3355
34- _word : $ => repeat1 ( / [ A - Z a - z 0 - 9 _ ] / ) ,
35- _ws : $ => repeat1 ( " " ) ,
56+ _identifier : $ => / \w + / ,
3657
3758 // Expressions
38- _expression : $ => seq ( "{{" , optional ( $ . _ws ) , $ . variable , optional ( $ . _ws ) , "}}" ) ,
59+ _expression : $ => seq ( "{{" , $ . variable , "}}" ) ,
3960
4061 variable : $ => seq ( $ . variable_name , repeat ( seq ( "|" , $ . filter ) ) ) ,
4162 // Django variables cannot start with an "_", can contain one or more words separated by a "."
42- variable_name : $ => seq ( repeat1 ( / [ A - Z a - z ] / ) , optional ( $ . _word ) , repeat ( seq ( "." , $ . _word ) ) ) ,
43-
63+ variable_name : $ => / [ a - z A - Z ] ( \w + ) ? ( ( \. ? \w ) + ) ? / ,
64+
4465 filter : $ => seq ( $ . filter_name , optional ( seq ( ":" , choice ( $ . filter_argument , $ . _quoted_filter_argument ) ) ) ) ,
45- filter_name : $ => $ . _word ,
46- filter_argument : $ => seq ( $ . _word , repeat ( seq ( "." , $ . _word ) ) ) ,
66+ filter_name : $ => $ . _identifier ,
67+ filter_argument : $ => seq ( $ . _identifier , repeat ( seq ( "." , $ . _identifier ) ) ) ,
4768 _quoted_filter_argument : $ => choice (
4869 seq ( "'" , alias ( repeat ( / [ ^ ' ] / ) , $ . filter_argument ) , "'" ) ,
4970 seq ( '"' , alias ( repeat ( / [ ^ " ] / ) , $ . filter_argument ) , '"' )
5071 ) ,
51-
72+
5273 // Statements
5374 // unpaired type {% tag %}
5475 // paired type {% tag %}..{% endtag %}
@@ -57,8 +78,7 @@ module.exports = grammar({
5778 alias ( $ . if_statement , $ . paired_statement ) ,
5879 alias ( $ . for_statement , $ . paired_statement ) ,
5980 alias ( $ . filter_statement , $ . paired_statement ) ,
60- $ . unpaired_statement ,
61- $ . detatched_end_statement
81+ $ . unpaired_statement
6282 ) ,
6383
6484 paired_statement : $ => {
@@ -73,13 +93,13 @@ module.exports = grammar({
7393 ] ;
7494
7595 return choice ( ...tag_names . map ( ( tag_name ) => seq (
76- "{%" , $ . _ws , alias ( tag_name + " " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , "%}" ,
96+ "{%" , alias ( tag_name , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ,
7797 repeat ( $ . _node ) ,
78- "{%" , $ . _ws , "end" , alias ( tag_name + " " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , alias ( "%}" , $ . end_paired_statement ) ) ) ) ;
98+ "{%" , alias ( "end" + tag_name , $ . tag_name ) , repeat ( $ . _attribute ) , alias ( "%}" , $ . end_paired_statement ) ) ) ) ;
7999 } ,
80100
81101 if_statement : $ => seq (
82- "{%" , $ . _ws , alias ( "if " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , "%}" ,
102+ "{%" , alias ( "if" , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ,
83103 repeat ( $ . _node ) ,
84104 repeat ( prec . left ( seq (
85105 alias ( $ . elif_statement , $ . branch_statement ) ,
@@ -89,30 +109,28 @@ module.exports = grammar({
89109 alias ( $ . else_statement , $ . branch_statement ) ,
90110 repeat ( $ . _node ) ,
91111 ) ) ,
92- "{%" , $ . _ws , "end" , alias ( "if " , $ . tag_name ) , optional ( $ . _ws ) , alias ( "%}" , $ . end_paired_statement )
112+ "{%" , alias ( "endif " , $ . tag_name ) , alias ( "%}" , $ . end_paired_statement )
93113 ) ,
94- elif_statement : $ => seq ( "{%" , $ . _ws , alias ( "elif " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , "%}" ) ,
95- else_statement : $ => seq ( "{%" , $ . _ws , alias ( "else " , $ . tag_name ) , optional ( $ . _ws ) , "%}" ) ,
114+ elif_statement : $ => seq ( "{%" , alias ( "elif" , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ) ,
115+ else_statement : $ => seq ( "{%" , alias ( "else" , $ . tag_name ) , "%}" ) ,
96116
97117 for_statement : $ => seq (
98- "{%" , $ . _ws , alias ( "for " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , "%}" ,
118+ "{%" , alias ( "for" , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ,
99119 repeat ( $ . _node ) ,
100120 optional ( seq (
101121 alias ( $ . empty_statement , $ . branch_statement ) ,
102122 repeat ( $ . _node ) ,
103123 ) ) ,
104- "{%" , $ . _ws , "end" , alias ( "for " , $ . tag_name ) , optional ( $ . _ws ) , alias ( "%}" , $ . end_paired_statement )
124+ "{%" , alias ( "endfor " , $ . tag_name ) , alias ( "%}" , $ . end_paired_statement )
105125 ) ,
106- empty_statement : $ => seq ( "{%" , $ . _ws , alias ( "empty " , $ . tag_name ) , optional ( $ . _ws ) , repeat ( $ . _attribute ) , "%}" ) ,
126+ empty_statement : $ => seq ( "{%" , alias ( "empty" , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ) ,
107127
108128 filter_statement : $ => seq (
109- "{%" , $ . _ws , alias ( "filter " , $ . tag_name ) , optional ( $ . _ws ) , $ . filter , repeat ( seq ( "|" , $ . filter ) ) , $ . _ws , "%}" ,
129+ "{%" , alias ( "filter" , $ . tag_name ) , $ . filter , repeat ( seq ( "|" , $ . filter ) ) , "%}" ,
110130 repeat ( $ . _node ) ,
111- "{%" , $ . _ws , "end" , alias ( "filter " , $ . tag_name ) , optional ( $ . _ws ) , alias ( "%}" , $ . end_paired_statement )
131+ "{%" , alias ( "endfilter " , $ . tag_name ) , alias ( "%}" , $ . end_paired_statement )
112132 ) ,
113-
114- unpaired_statement : $ => seq ( "{%" , $ . _ws , alias ( $ . _word , $ . tag_name ) , $ . _ws , repeat ( $ . _attribute ) , "%}" ) ,
115- detatched_end_statement : $ => seq ( "{%" , $ . _ws , "end" , alias ( $ . _word , $ . tag_name ) , $ . _ws , repeat ( $ . _attribute ) , "%}" ) ,
133+ unpaired_statement : $ => seq ( "{%" , alias ( $ . _identifier , $ . tag_name ) , repeat ( $ . _attribute ) , "%}" ) ,
116134
117135 _attribute : $ => seq (
118136 choice (
@@ -124,11 +142,7 @@ module.exports = grammar({
124142 $ . string ,
125143 $ . variable
126144 ) ,
127- choice (
128- $ . _ws ,
129- seq ( optional ( $ . _ws ) , "," , optional ( $ . _ws ) ) ,
130- seq ( optional ( $ . _ws ) , "=" , optional ( $ . _ws ) )
131- )
145+ optional ( choice ( "," , "=" ) )
132146 ) ,
133147
134148 // Comments
@@ -140,10 +154,10 @@ module.exports = grammar({
140154 ) ,
141155 unpaired_comment : $ => seq ( "{#" , repeat ( / .| \s / ) , repeat ( seq ( alias ( $ . unpaired_comment , "" ) , repeat ( / .| \s / ) ) ) , "#}" ) ,
142156 paired_comment : $ => seq (
143- alias ( "{%" , "" ) , $ . _ws , "comment" , optional ( seq ( $ . _ws , $ . _word ) ) , $ . _ws , alias ( "%}" , "" ) ,
157+ alias ( "{%" , "" ) , "comment" , optional ( $ . _identifier ) , alias ( "%}" , "" ) ,
144158 repeat ( / .| \s / ) ,
145159 repeat ( seq ( alias ( $ . paired_comment , "" ) , repeat ( / .| \s / ) ) ) ,
146- alias ( "{%" , "" ) , $ . _ws , "endcomment" , $ . _ws , alias ( "%}" , "" )
160+ alias ( "{%" , "" ) , "endcomment" , alias ( "%}" , "" )
147161 ) ,
148162
149163 // All other content
0 commit comments