]> luflow.net public git repositories - flow-web.git/blob - static/highlight/es/languages/handlebars.js
Initial commit.
[flow-web.git] / static / highlight / es / languages / handlebars.js
1 /*! `handlebars` grammar compiled for Highlight.js 11.11.1 */
2 var hljsGrammar = (function () {
3 'use strict';
4
5 /*
6 Language: Handlebars
7 Requires: xml.js
8 Author: Robin Ward <robin.ward@gmail.com>
9 Description: Matcher for Handlebars as well as EmberJS additions.
10 Website: https://handlebarsjs.com
11 Category: template
12 */
13
14 function handlebars(hljs) {
15 const regex = hljs.regex;
16 const BUILT_INS = {
17 $pattern: /[\w.\/]+/,
18 built_in: [
19 'action',
20 'bindattr',
21 'collection',
22 'component',
23 'concat',
24 'debugger',
25 'each',
26 'each-in',
27 'get',
28 'hash',
29 'if',
30 'in',
31 'input',
32 'link-to',
33 'loc',
34 'log',
35 'lookup',
36 'mut',
37 'outlet',
38 'partial',
39 'query-params',
40 'render',
41 'template',
42 'textarea',
43 'unbound',
44 'unless',
45 'view',
46 'with',
47 'yield'
48 ]
49 };
50
51 const LITERALS = {
52 $pattern: /[\w.\/]+/,
53 literal: [
54 'true',
55 'false',
56 'undefined',
57 'null'
58 ]
59 };
60
61 // as defined in https://handlebarsjs.com/guide/expressions.html#literal-segments
62 // this regex matches literal segments like ' abc ' or [ abc ] as well as helpers and paths
63 // like a/b, ./abc/cde, and abc.bcd
64
65 const DOUBLE_QUOTED_ID_REGEX = /""|"[^"]+"/;
66 const SINGLE_QUOTED_ID_REGEX = /''|'[^']+'/;
67 const BRACKET_QUOTED_ID_REGEX = /\[\]|\[[^\]]+\]/;
68 const PLAIN_ID_REGEX = /[^\s!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]+/;
69 const PATH_DELIMITER_REGEX = /(\.|\/)/;
70 const ANY_ID = regex.either(
71 DOUBLE_QUOTED_ID_REGEX,
72 SINGLE_QUOTED_ID_REGEX,
73 BRACKET_QUOTED_ID_REGEX,
74 PLAIN_ID_REGEX
75 );
76
77 const IDENTIFIER_REGEX = regex.concat(
78 regex.optional(/\.|\.\/|\//), // relative or absolute path
79 ANY_ID,
80 regex.anyNumberOfTimes(regex.concat(
81 PATH_DELIMITER_REGEX,
82 ANY_ID
83 ))
84 );
85
86 // identifier followed by a equal-sign (without the equal sign)
87 const HASH_PARAM_REGEX = regex.concat(
88 '(',
89 BRACKET_QUOTED_ID_REGEX, '|',
90 PLAIN_ID_REGEX,
91 ')(?==)'
92 );
93
94 const HELPER_NAME_OR_PATH_EXPRESSION = { begin: IDENTIFIER_REGEX };
95
96 const HELPER_PARAMETER = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, { keywords: LITERALS });
97
98 const SUB_EXPRESSION = {
99 begin: /\(/,
100 end: /\)/
101 // the "contains" is added below when all necessary sub-modes are defined
102 };
103
104 const HASH = {
105 // fka "attribute-assignment", parameters of the form 'key=value'
106 className: 'attr',
107 begin: HASH_PARAM_REGEX,
108 relevance: 0,
109 starts: {
110 begin: /=/,
111 end: /=/,
112 starts: { contains: [
113 hljs.NUMBER_MODE,
114 hljs.QUOTE_STRING_MODE,
115 hljs.APOS_STRING_MODE,
116 HELPER_PARAMETER,
117 SUB_EXPRESSION
118 ] }
119 }
120 };
121
122 const BLOCK_PARAMS = {
123 // parameters of the form '{{#with x as | y |}}...{{/with}}'
124 begin: /as\s+\|/,
125 keywords: { keyword: 'as' },
126 end: /\|/,
127 contains: [
128 {
129 // define sub-mode in order to prevent highlighting of block-parameter named "as"
130 begin: /\w+/ }
131 ]
132 };
133
134 const HELPER_PARAMETERS = {
135 contains: [
136 hljs.NUMBER_MODE,
137 hljs.QUOTE_STRING_MODE,
138 hljs.APOS_STRING_MODE,
139 BLOCK_PARAMS,
140 HASH,
141 HELPER_PARAMETER,
142 SUB_EXPRESSION
143 ],
144 returnEnd: true
145 // the property "end" is defined through inheritance when the mode is used. If depends
146 // on the surrounding mode, but "endsWithParent" does not work here (i.e. it includes the
147 // end-token of the surrounding mode)
148 };
149
150 const SUB_EXPRESSION_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
151 className: 'name',
152 keywords: BUILT_INS,
153 starts: hljs.inherit(HELPER_PARAMETERS, { end: /\)/ })
154 });
155
156 SUB_EXPRESSION.contains = [ SUB_EXPRESSION_CONTENTS ];
157
158 const OPENING_BLOCK_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
159 keywords: BUILT_INS,
160 className: 'name',
161 starts: hljs.inherit(HELPER_PARAMETERS, { end: /\}\}/ })
162 });
163
164 const CLOSING_BLOCK_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
165 keywords: BUILT_INS,
166 className: 'name'
167 });
168
169 const BASIC_MUSTACHE_CONTENTS = hljs.inherit(HELPER_NAME_OR_PATH_EXPRESSION, {
170 className: 'name',
171 keywords: BUILT_INS,
172 starts: hljs.inherit(HELPER_PARAMETERS, { end: /\}\}/ })
173 });
174
175 const ESCAPE_MUSTACHE_WITH_PRECEEDING_BACKSLASH = {
176 begin: /\\\{\{/,
177 skip: true
178 };
179 const PREVENT_ESCAPE_WITH_ANOTHER_PRECEEDING_BACKSLASH = {
180 begin: /\\\\(?=\{\{)/,
181 skip: true
182 };
183
184 return {
185 name: 'Handlebars',
186 aliases: [
187 'hbs',
188 'html.hbs',
189 'html.handlebars',
190 'htmlbars'
191 ],
192 case_insensitive: true,
193 subLanguage: 'xml',
194 contains: [
195 ESCAPE_MUSTACHE_WITH_PRECEEDING_BACKSLASH,
196 PREVENT_ESCAPE_WITH_ANOTHER_PRECEEDING_BACKSLASH,
197 hljs.COMMENT(/\{\{!--/, /--\}\}/),
198 hljs.COMMENT(/\{\{!/, /\}\}/),
199 {
200 // open raw block "{{{{raw}}}} content not evaluated {{{{/raw}}}}"
201 className: 'template-tag',
202 begin: /\{\{\{\{(?!\/)/,
203 end: /\}\}\}\}/,
204 contains: [ OPENING_BLOCK_MUSTACHE_CONTENTS ],
205 starts: {
206 end: /\{\{\{\{\//,
207 returnEnd: true,
208 subLanguage: 'xml'
209 }
210 },
211 {
212 // close raw block
213 className: 'template-tag',
214 begin: /\{\{\{\{\//,
215 end: /\}\}\}\}/,
216 contains: [ CLOSING_BLOCK_MUSTACHE_CONTENTS ]
217 },
218 {
219 // open block statement
220 className: 'template-tag',
221 begin: /\{\{#/,
222 end: /\}\}/,
223 contains: [ OPENING_BLOCK_MUSTACHE_CONTENTS ]
224 },
225 {
226 className: 'template-tag',
227 begin: /\{\{(?=else\}\})/,
228 end: /\}\}/,
229 keywords: 'else'
230 },
231 {
232 className: 'template-tag',
233 begin: /\{\{(?=else if)/,
234 end: /\}\}/,
235 keywords: 'else if'
236 },
237 {
238 // closing block statement
239 className: 'template-tag',
240 begin: /\{\{\//,
241 end: /\}\}/,
242 contains: [ CLOSING_BLOCK_MUSTACHE_CONTENTS ]
243 },
244 {
245 // template variable or helper-call that is NOT html-escaped
246 className: 'template-variable',
247 begin: /\{\{\{/,
248 end: /\}\}\}/,
249 contains: [ BASIC_MUSTACHE_CONTENTS ]
250 },
251 {
252 // template variable or helper-call that is html-escaped
253 className: 'template-variable',
254 begin: /\{\{/,
255 end: /\}\}/,
256 contains: [ BASIC_MUSTACHE_CONTENTS ]
257 }
258 ]
259 };
260 }
261
262 return handlebars;
263
264 })();
265 ;
266 export default hljsGrammar;