PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 3.16.6
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v3.16.6
4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 All 340 releases
profile-builder / assets / lib / codemirror / mode / javascript / javascript.js

javascript.js in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 3.16.6, at assets/lib/codemirror/mode/javascript/javascript.js

481 lines 17.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 // TODO actually recognize syntax of TypeScript constructs
2
3 CodeMirror.defineMode("javascript", function(config, parserConfig) {
4 var indentUnit = config.indentUnit;
5 var statementIndent = parserConfig.statementIndent;
6 var jsonMode = parserConfig.json;
7 var isTS = parserConfig.typescript;
8
9 // Tokenizer
10
11 var keywords = function(){
12 function kw(type) {return {type: type, style: "keyword"};}
13 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
14 var operator = kw("operator"), atom = {type: "atom", style: "atom"};
15
16 var jsKeywords = {
17 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
18 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
19 "var": kw("var"), "const": kw("var"), "let": kw("var"),
20 "function": kw("function"), "catch": kw("catch"),
21 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
22 "in": operator, "typeof": operator, "instanceof": operator,
23 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
24 "this": kw("this")
25 };
26
27 // Extend the 'normal' keywords with the TypeScript language extensions
28 if (isTS) {
29 var type = {type: "variable", style: "variable-3"};
30 var tsKeywords = {
31 // object-like things
32 "interface": kw("interface"),
33 "class": kw("class"),
34 "extends": kw("extends"),
35 "constructor": kw("constructor"),
36
37 // scope modifiers
38 "public": kw("public"),
39 "private": kw("private"),
40 "protected": kw("protected"),
41 "static": kw("static"),
42
43 "super": kw("super"),
44
45 // types
46 "string": type, "number": type, "bool": type, "any": type
47 };
48
49 for (var attr in tsKeywords) {
50 jsKeywords[attr] = tsKeywords[attr];
51 }
52 }
53
54 return jsKeywords;
55 }();
56
57 var isOperatorChar = /[+\-*&%=<>!?|~^]/;
58
59 function chain(stream, state, f) {
60 state.tokenize = f;
61 return f(stream, state);
62 }
63
64 function nextUntilUnescaped(stream, end) {
65 var escaped = false, next;
66 while ((next = stream.next()) != null) {
67 if (next == end && !escaped)
68 return false;
69 escaped = !escaped && next == "\\";
70 }
71 return escaped;
72 }
73
74 // Used as scratch variables to communicate multiple values without
75 // consing up tons of objects.
76 var type, content;
77 function ret(tp, style, cont) {
78 type = tp; content = cont;
79 return style;
80 }
81 function jsTokenBase(stream, state) {
82 var ch = stream.next();
83 if (ch == '"' || ch == "'")
84 return chain(stream, state, jsTokenString(ch));
85 else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/))
86 return ret("number", "number");
87 else if (/[\[\]{}\(\),;\:\.]/.test(ch))
88 return ret(ch);
89 else if (ch == "0" && stream.eat(/x/i)) {
90 stream.eatWhile(/[\da-f]/i);
91 return ret("number", "number");
92 }
93 else if (/\d/.test(ch)) {
94 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
95 return ret("number", "number");
96 }
97 else if (ch == "/") {
98 if (stream.eat("*")) {
99 return chain(stream, state, jsTokenComment);
100 }
101 else if (stream.eat("/")) {
102 stream.skipToEnd();
103 return ret("comment", "comment");
104 }
105 else if (state.lastType == "operator" || state.lastType == "keyword c" ||
106 /^[\[{}\(,;:]$/.test(state.lastType)) {
107 nextUntilUnescaped(stream, "/");
108 stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
109 return ret("regexp", "string-2");
110 }
111 else {
112 stream.eatWhile(isOperatorChar);
113 return ret("operator", null, stream.current());
114 }
115 }
116 else if (ch == "#") {
117 stream.skipToEnd();
118 return ret("error", "error");
119 }
120 else if (isOperatorChar.test(ch)) {
121 stream.eatWhile(isOperatorChar);
122 return ret("operator", null, stream.current());
123 }
124 else {
125 stream.eatWhile(/[\w\$_]/);
126 var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
127 return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
128 ret("variable", "variable", word);
129 }
130 }
131
132 function jsTokenString(quote) {
133 return function(stream, state) {
134 if (!nextUntilUnescaped(stream, quote))
135 state.tokenize = jsTokenBase;
136 return ret("string", "string");
137 };
138 }
139
140 function jsTokenComment(stream, state) {
141 var maybeEnd = false, ch;
142 while (ch = stream.next()) {
143 if (ch == "/" && maybeEnd) {
144 state.tokenize = jsTokenBase;
145 break;
146 }
147 maybeEnd = (ch == "*");
148 }
149 return ret("comment", "comment");
150 }
151
152 // Parser
153
154 var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
155
156 function JSLexical(indented, column, type, align, prev, info) {
157 this.indented = indented;
158 this.column = column;
159 this.type = type;
160 this.prev = prev;
161 this.info = info;
162 if (align != null) this.align = align;
163 }
164
165 function inScope(state, varname) {
166 for (var v = state.localVars; v; v = v.next)
167 if (v.name == varname) return true;
168 }
169
170 function parseJS(state, style, type, content, stream) {
171 var cc = state.cc;
172 // Communicate our context to the combinators.
173 // (Less wasteful than consing up a hundred closures on every call.)
174 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
175
176 if (!state.lexical.hasOwnProperty("align"))
177 state.lexical.align = true;
178
179 while(true) {
180 var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
181 if (combinator(type, content)) {
182 while(cc.length && cc[cc.length - 1].lex)
183 cc.pop()();
184 if (cx.marked) return cx.marked;
185 if (type == "variable" && inScope(state, content)) return "variable-2";
186 return style;
187 }
188 }
189 }
190
191 // Combinator utils
192
193 var cx = {state: null, column: null, marked: null, cc: null};
194 function pass() {
195 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
196 }
197 function cont() {
198 pass.apply(null, arguments);
199 return true;
200 }
201 function register(varname) {
202 function inList(list) {
203 for (var v = list; v; v = v.next)
204 if (v.name == varname) return true;
205 return false;
206 }
207 var state = cx.state;
208 if (state.context) {
209 cx.marked = "def";
210 if (inList(state.localVars)) return;
211 state.localVars = {name: varname, next: state.localVars};
212 } else {
213 if (inList(state.globalVars)) return;
214 state.globalVars = {name: varname, next: state.globalVars};
215 }
216 }
217
218 // Combinators
219
220 var defaultVars = {name: "this", next: {name: "arguments"}};
221 function pushcontext() {
222 cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
223 cx.state.localVars = defaultVars;
224 }
225 function popcontext() {
226 cx.state.localVars = cx.state.context.vars;
227 cx.state.context = cx.state.context.prev;
228 }
229 function pushlex(type, info) {
230 var result = function() {
231 var state = cx.state, indent = state.indented;
232 if (state.lexical.type == "stat") indent = state.lexical.indented;
233 state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
234 };
235 result.lex = true;
236 return result;
237 }
238 function poplex() {
239 var state = cx.state;
240 if (state.lexical.prev) {
241 if (state.lexical.type == ")")
242 state.indented = state.lexical.indented;
243 state.lexical = state.lexical.prev;
244 }
245 }
246 poplex.lex = true;
247
248 function expect(wanted) {
249 return function(type) {
250 if (type == wanted) return cont();
251 else if (wanted == ";") return pass();
252 else return cont(arguments.callee);
253 };
254 }
255
256 function statement(type) {
257 if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
258 if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
259 if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
260 if (type == "{") return cont(pushlex("}"), block, poplex);
261 if (type == ";") return cont();
262 if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse);
263 if (type == "function") return cont(functiondef);
264 if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
265 poplex, statement, poplex);
266 if (type == "variable") return cont(pushlex("stat"), maybelabel);
267 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
268 block, poplex, poplex);
269 if (type == "case") return cont(expression, expect(":"));
270 if (type == "default") return cont(expect(":"));
271 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
272 statement, poplex, popcontext);
273 return pass(pushlex("stat"), expression, expect(";"), poplex);
274 }
275 function expression(type) {
276 return expressionInner(type, false);
277 }
278 function expressionNoComma(type) {
279 return expressionInner(type, true);
280 }
281 function expressionInner(type, noComma) {
282 var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
283 if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
284 if (type == "function") return cont(functiondef);
285 if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
286 if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
287 if (type == "operator") return cont(noComma ? expressionNoComma : expression);
288 if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop);
289 if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop);
290 return cont();
291 }
292 function maybeexpression(type) {
293 if (type.match(/[;\}\)\],]/)) return pass();
294 return pass(expression);
295 }
296 function maybeexpressionNoComma(type) {
297 if (type.match(/[;\}\)\],]/)) return pass();
298 return pass(expressionNoComma);
299 }
300
301 function maybeoperatorComma(type, value) {
302 if (type == ",") return cont(expression);
303 return maybeoperatorNoComma(type, value, false);
304 }
305 function maybeoperatorNoComma(type, value, noComma) {
306 var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
307 var expr = noComma == false ? expression : expressionNoComma;
308 if (type == "operator") {
309 if (/\+\+|--/.test(value)) return cont(me);
310 if (value == "?") return cont(expression, expect(":"), expr);
311 return cont(expr);
312 }
313 if (type == ";") return;
314 if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me);
315 if (type == ".") return cont(property, me);
316 if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
317 }
318 function maybelabel(type) {
319 if (type == ":") return cont(poplex, statement);
320 return pass(maybeoperatorComma, expect(";"), poplex);
321 }
322 function property(type) {
323 if (type == "variable") {cx.marked = "property"; return cont();}
324 }
325 function objprop(type, value) {
326 if (type == "variable") {
327 cx.marked = "property";
328 if (value == "get" || value == "set") return cont(getterSetter);
329 } else if (type == "number" || type == "string") {
330 cx.marked = type + " property";
331 }
332 if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma);
333 }
334 function getterSetter(type) {
335 if (type == ":") return cont(expression);
336 if (type != "variable") return cont(expect(":"), expression);
337 cx.marked = "property";
338 return cont(functiondef);
339 }
340 function commasep(what, end) {
341 function proceed(type) {
342 if (type == ",") {
343 var lex = cx.state.lexical;
344 if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
345 return cont(what, proceed);
346 }
347 if (type == end) return cont();
348 return cont(expect(end));
349 }
350 return function(type) {
351 if (type == end) return cont();
352 else return pass(what, proceed);
353 };
354 }
355 function block(type) {
356 if (type == "}") return cont();
357 return pass(statement, block);
358 }
359 function maybetype(type) {
360 if (type == ":") return cont(typedef);
361 return pass();
362 }
363 function typedef(type) {
364 if (type == "variable"){cx.marked = "variable-3"; return cont();}
365 return pass();
366 }
367 function vardef1(type, value) {
368 if (type == "variable") {
369 register(value);
370 return isTS ? cont(maybetype, vardef2) : cont(vardef2);
371 }
372 return pass();
373 }
374 function vardef2(type, value) {
375 if (value == "=") return cont(expressionNoComma, vardef2);
376 if (type == ",") return cont(vardef1);
377 }
378 function maybeelse(type, value) {
379 if (type == "keyword b" && value == "else") return cont(pushlex("form"), statement, poplex);
380 }
381 function forspec1(type) {
382 if (type == "var") return cont(vardef1, expect(";"), forspec2);
383 if (type == ";") return cont(forspec2);
384 if (type == "variable") return cont(formaybein);
385 return pass(expression, expect(";"), forspec2);
386 }
387 function formaybein(_type, value) {
388 if (value == "in") return cont(expression);
389 return cont(maybeoperatorComma, forspec2);
390 }
391 function forspec2(type, value) {
392 if (type == ";") return cont(forspec3);
393 if (value == "in") return cont(expression);
394 return pass(expression, expect(";"), forspec3);
395 }
396 function forspec3(type) {
397 if (type != ")") cont(expression);
398 }
399 function functiondef(type, value) {
400 if (type == "variable") {register(value); return cont(functiondef);}
401 if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
402 }
403 function funarg(type, value) {
404 if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
405 }
406
407 // Interface
408
409 return {
410 startState: function(basecolumn) {
411 return {
412 tokenize: jsTokenBase,
413 lastType: null,
414 cc: [],
415 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
416 localVars: parserConfig.localVars,
417 globalVars: parserConfig.globalVars,
418 context: parserConfig.localVars && {vars: parserConfig.localVars},
419 indented: 0
420 };
421 },
422
423 token: function(stream, state) {
424 if (stream.sol()) {
425 if (!state.lexical.hasOwnProperty("align"))
426 state.lexical.align = false;
427 state.indented = stream.indentation();
428 }
429 if (state.tokenize != jsTokenComment && stream.eatSpace()) return null;
430 var style = state.tokenize(stream, state);
431 if (type == "comment") return style;
432 state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
433 return parseJS(state, style, type, content, stream);
434 },
435
436 indent: function(state, textAfter) {
437 if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
438 if (state.tokenize != jsTokenBase) return 0;
439 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
440 // Kludge to prevent 'maybelse' from blocking lexical scope pops
441 for (var i = state.cc.length - 1; i >= 0; --i) {
442 var c = state.cc[i];
443 if (c == poplex) lexical = lexical.prev;
444 else if (c != maybeelse || /^else\b/.test(textAfter)) break;
445 }
446 if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
447 if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
448 lexical = lexical.prev;
449 var type = lexical.type, closing = firstChar == type;
450
451 if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
452 else if (type == "form" && firstChar == "{") return lexical.indented;
453 else if (type == "form") return lexical.indented + indentUnit;
454 else if (type == "stat")
455 return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
456 else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
457 return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
458 else if (lexical.align) return lexical.column + (closing ? 0 : 1);
459 else return lexical.indented + (closing ? 0 : indentUnit);
460 },
461
462 electricChars: ":{}",
463 blockCommentStart: jsonMode ? null : "/*",
464 blockCommentEnd: jsonMode ? null : "*/",
465 lineComment: jsonMode ? null : "//",
466 fold: "brace",
467
468 helperType: jsonMode ? "json" : "javascript",
469 jsonMode: jsonMode
470 };
471 });
472
473 CodeMirror.defineMIME("text/javascript", "javascript");
474 CodeMirror.defineMIME("text/ecmascript", "javascript");
475 CodeMirror.defineMIME("application/javascript", "javascript");
476 CodeMirror.defineMIME("application/ecmascript", "javascript");
477 CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
478 CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
479 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
480 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
481