##// END OF EJS Templates
codemirror: update from 5.4.0 to 5.11.0, fixes #3154
marcink -
r346:1a48416d default
parent child Browse files
Show More
@@ -165,7 +165,7 b' div.CodeMirror span.CodeMirror-nonmatchi'
165 165 }
166 166
167 167 /* The fake, visible scrollbars. Used to force redraw during scrolling
168 before actuall scrolling happens, thus preventing shaking and
168 before actual scrolling happens, thus preventing shaking and
169 169 flickering artifacts. */
170 170 .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
171 171 position: absolute;
@@ -207,6 +207,11 b' div.CodeMirror span.CodeMirror-nonmatchi'
207 207 z-index: 4;
208 208 height: 100%;
209 209 }
210 .CodeMirror-gutter-background {
211 position: absolute;
212 top: 0; bottom: 0;
213 z-index: 4;
214 }
210 215 .CodeMirror-gutter-elt {
211 216 position: absolute;
212 217 cursor: default;
@@ -280,7 +285,7 b' div.CodeMirror span.CodeMirror-nonmatchi'
280 285 overflow: hidden;
281 286 visibility: hidden;
282 287 }
283 .CodeMirror-measure pre { position: static; }
288
284 289
285 290 .CodeMirror div.CodeMirror-cursor {
286 291 position: absolute;
@@ -288,11 +293,17 b' div.CodeMirror span.CodeMirror-nonmatchi'
288 293 width: 0;
289 294 }
290 295
296 .CodeMirror-measure pre { position: static; }
297
291 298 div.CodeMirror-cursors {
292 299 visibility: hidden;
293 300 position: relative;
294 301 z-index: 3;
295 302 }
303 div.CodeMirror-dragcursors {
304 visibility: visible;
305 }
306
296 307 .CodeMirror-focused div.CodeMirror-cursors {
297 308 visibility: visible;
298 309 }
@@ -300,8 +311,8 b' div.CodeMirror-cursors {'
300 311 .CodeMirror-selected { background: #d9d9d9; }
301 312 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
302 313 .CodeMirror-crosshair { cursor: crosshair; }
303 .CodeMirror ::selection { background: #d7d4f0; }
304 .CodeMirror ::-moz-selection { background: #d7d4f0; }
314 .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
315 .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
305 316
306 317 .cm-searching {
307 318 background: #ffa;
@@ -25,8 +25,12 b' CodeMirror.defineMode("clike", function('
25 25 multiLineStrings = parserConfig.multiLineStrings,
26 26 indentStatements = parserConfig.indentStatements !== false,
27 27 indentSwitch = parserConfig.indentSwitch !== false,
28 namespaceSeparator = parserConfig.namespaceSeparator;
29 var isOperatorChar = /[+\-*&%=<>!?|\/]/;
28 namespaceSeparator = parserConfig.namespaceSeparator,
29 isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
30 numberStart = parserConfig.numberStart || /[\d\.]/,
31 number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
32 isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
33 endStatement = parserConfig.endStatement || /^[;:,]$/;
30 34
31 35 var curPunc, isDefKeyword;
32 36
@@ -40,13 +44,14 b' CodeMirror.defineMode("clike", function('
40 44 state.tokenize = tokenString(ch);
41 45 return state.tokenize(stream, state);
42 46 }
43 if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
47 if (isPunctuationChar.test(ch)) {
44 48 curPunc = ch;
45 49 return null;
46 50 }
47 if (/\d/.test(ch)) {
48 stream.eatWhile(/[\w\.]/);
49 return "number";
51 if (numberStart.test(ch)) {
52 stream.backUp(1)
53 if (stream.match(number)) return "number"
54 stream.next()
50 55 }
51 56 if (ch == "/") {
52 57 if (stream.eat("*")) {
@@ -67,17 +72,17 b' CodeMirror.defineMode("clike", function('
67 72 stream.eatWhile(/[\w\$_\xa1-\uffff]/);
68 73
69 74 var cur = stream.current();
70 if (keywords.propertyIsEnumerable(cur)) {
71 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
72 if (defKeywords.propertyIsEnumerable(cur)) isDefKeyword = true;
75 if (contains(keywords, cur)) {
76 if (contains(blockKeywords, cur)) curPunc = "newstatement";
77 if (contains(defKeywords, cur)) isDefKeyword = true;
73 78 return "keyword";
74 79 }
75 if (types.propertyIsEnumerable(cur)) return "variable-3";
76 if (builtin.propertyIsEnumerable(cur)) {
77 if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
80 if (contains(types, cur)) return "variable-3";
81 if (contains(builtin, cur)) {
82 if (contains(blockKeywords, cur)) curPunc = "newstatement";
78 83 return "builtin";
79 84 }
80 if (atoms.propertyIsEnumerable(cur)) return "atom";
85 if (contains(atoms, cur)) return "atom";
81 86 return "variable";
82 87 }
83 88
@@ -168,8 +173,7 b' CodeMirror.defineMode("clike", function('
168 173 if (style == "comment" || style == "meta") return style;
169 174 if (ctx.align == null) ctx.align = true;
170 175
171 if ((curPunc == ";" || curPunc == ":" || curPunc == ","))
172 while (isStatement(state.context.type)) popContext(state);
176 if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state);
173 177 else if (curPunc == "{") pushContext(state, stream.column(), "}");
174 178 else if (curPunc == "[") pushContext(state, stream.column(), "]");
175 179 else if (curPunc == "(") pushContext(state, stream.column(), ")");
@@ -212,8 +216,16 b' CodeMirror.defineMode("clike", function('
212 216 if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
213 217 var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
214 218 if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev;
219 if (hooks.indent) {
220 var hook = hooks.indent(state, ctx, textAfter);
221 if (typeof hook == "number") return hook
222 }
215 223 var closing = firstChar == ctx.type;
216 224 var switchBlock = ctx.prev && ctx.prev.type == "switchstatement";
225 if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
226 while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
227 return ctx.indented
228 }
217 229 if (isStatement(ctx.type))
218 230 return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
219 231 if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
@@ -238,27 +250,30 b' CodeMirror.defineMode("clike", function('
238 250 for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
239 251 return obj;
240 252 }
253 function contains(words, word) {
254 if (typeof words === "function") {
255 return words(word);
256 } else {
257 return words.propertyIsEnumerable(word);
258 }
259 }
241 260 var cKeywords = "auto if break case register continue return default do sizeof " +
242 "static else struct switch extern typedef float union for " +
243 "goto while enum const volatile";
261 "static else struct switch extern typedef union for goto while enum const volatile";
244 262 var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
245 263
246 264 function cppHook(stream, state) {
247 if (!state.startOfLine) return false;
248 for (;;) {
249 if (stream.skipTo("\\")) {
250 stream.next();
251 if (stream.eol()) {
252 state.tokenize = cppHook;
253 break;
254 }
255 } else {
256 stream.skipToEnd();
257 state.tokenize = null;
258 break;
265 if (!state.startOfLine) return false
266 for (var ch, next = null; ch = stream.peek();) {
267 if (ch == "\\" && stream.match(/^.$/)) {
268 next = cppHook
269 break
270 } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
271 break
259 272 }
273 stream.next()
260 274 }
261 return "meta";
275 state.tokenize = next
276 return "meta"
262 277 }
263 278
264 279 function pointerHook(_stream, state) {
@@ -266,6 +281,11 b' CodeMirror.defineMode("clike", function('
266 281 return false;
267 282 }
268 283
284 function cpp14Literal(stream) {
285 stream.eatWhile(/[\w\.']/);
286 return "number";
287 }
288
269 289 function cpp11StringHook(stream, state) {
270 290 stream.backUp(1);
271 291 // Raw strings.
@@ -373,6 +393,16 b' CodeMirror.defineMode("clike", function('
373 393 "U": cpp11StringHook,
374 394 "L": cpp11StringHook,
375 395 "R": cpp11StringHook,
396 "0": cpp14Literal,
397 "1": cpp14Literal,
398 "2": cpp14Literal,
399 "3": cpp14Literal,
400 "4": cpp14Literal,
401 "5": cpp14Literal,
402 "6": cpp14Literal,
403 "7": cpp14Literal,
404 "8": cpp14Literal,
405 "9": cpp14Literal,
376 406 token: function(stream, state, style) {
377 407 if (style == "variable" && stream.peek() == "(" &&
378 408 (state.prevToken == ";" || state.prevToken == null ||
@@ -398,6 +428,7 b' CodeMirror.defineMode("clike", function('
398 428 defKeywords: words("class interface package enum"),
399 429 typeFirstDefinitions: true,
400 430 atoms: words("true false null"),
431 endStatement: /^[;:]$/,
401 432 hooks: {
402 433 "@": function(stream) {
403 434 stream.eatWhile(/[\w\$_]/);
@@ -453,7 +484,7 b' CodeMirror.defineMode("clike", function('
453 484 keywords: words(
454 485
455 486 /* scala */
456 "abstract case catch class def do else extends false final finally for forSome if " +
487 "abstract case catch class def do else extends final finally for forSome if " +
457 488 "implicit import lazy match new null object override package private protected return " +
458 489 "sealed super this throw trait try type val var while with yield _ : = => <- <: " +
459 490 "<% >: # @ " +
@@ -501,6 +532,59 b' CodeMirror.defineMode("clike", function('
501 532 modeProps: {closeBrackets: {triples: '"'}}
502 533 });
503 534
535 function tokenKotlinString(tripleString){
536 return function (stream, state) {
537 var escaped = false, next, end = false;
538 while (!stream.eol()) {
539 if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
540 if (tripleString && stream.match('"""')) {end = true; break;}
541 next = stream.next();
542 if(!escaped && next == "$" && stream.match('{'))
543 stream.skipTo("}");
544 escaped = !escaped && next == "\\" && !tripleString;
545 }
546 if (end || !tripleString)
547 state.tokenize = null;
548 return "string";
549 }
550 }
551
552 def("text/x-kotlin", {
553 name: "clike",
554 keywords: words(
555 /*keywords*/
556 "package as typealias class interface this super val " +
557 "var fun for is in This throw return " +
558 "break continue object if else while do try when !in !is as? " +
559
560 /*soft keywords*/
561 "file import where by get set abstract enum open inner override private public internal " +
562 "protected catch finally out final vararg reified dynamic companion constructor init " +
563 "sealed field property receiver param sparam lateinit data inline noinline tailrec " +
564 "external annotation crossinline const operator infix"
565 ),
566 types: words(
567 /* package java.lang */
568 "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
569 "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
570 "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
571 "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
572 ),
573 intendSwitch: false,
574 indentStatements: false,
575 multiLineStrings: true,
576 blockKeywords: words("catch class do else finally for if where try while enum"),
577 defKeywords: words("class val var object package interface fun"),
578 atoms: words("true false null this"),
579 hooks: {
580 '"': function(stream, state) {
581 state.tokenize = tokenKotlinString(stream.match('""'));
582 return state.tokenize(stream, state);
583 }
584 },
585 modeProps: {closeBrackets: {triples: '"'}}
586 });
587
504 588 def(["x-shader/x-vertex", "x-shader/x-fragment"], {
505 589 name: "clike",
506 590 keywords: words("sampler1D sampler2D sampler3D samplerCube " +
@@ -583,9 +667,106 b' CodeMirror.defineMode("clike", function('
583 667 stream.eatWhile(/[\w\$]/);
584 668 return "keyword";
585 669 },
586 "#": cppHook
670 "#": cppHook,
671 indent: function(_state, ctx, textAfter) {
672 if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
673 }
587 674 },
588 675 modeProps: {fold: "brace"}
589 676 });
590 677
678 def("text/x-squirrel", {
679 name: "clike",
680 keywords: words("base break clone continue const default delete enum extends function in class" +
681 " foreach local resume return this throw typeof yield constructor instanceof static"),
682 types: words(cTypes),
683 blockKeywords: words("case catch class else for foreach if switch try while"),
684 defKeywords: words("function local class"),
685 typeFirstDefinitions: true,
686 atoms: words("true false null"),
687 hooks: {"#": cppHook},
688 modeProps: {fold: ["brace", "include"]}
689 });
690
691 // Ceylon Strings need to deal with interpolation
692 var stringTokenizer = null;
693 function tokenCeylonString(type) {
694 return function(stream, state) {
695 var escaped = false, next, end = false;
696 while (!stream.eol()) {
697 if (!escaped && stream.match('"') &&
698 (type == "single" || stream.match('""'))) {
699 end = true;
700 break;
701 }
702 if (!escaped && stream.match('``')) {
703 stringTokenizer = tokenCeylonString(type);
704 end = true;
705 break;
706 }
707 next = stream.next();
708 escaped = type == "single" && !escaped && next == "\\";
709 }
710 if (end)
711 state.tokenize = null;
712 return "string";
713 }
714 }
715
716 def("text/x-ceylon", {
717 name: "clike",
718 keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
719 " exists extends finally for function given if import in interface is let module new" +
720 " nonempty object of out outer package return satisfies super switch then this throw" +
721 " try value void while"),
722 types: function(word) {
723 // In Ceylon all identifiers that start with an uppercase are types
724 var first = word.charAt(0);
725 return (first === first.toUpperCase() && first !== first.toLowerCase());
726 },
727 blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
728 defKeywords: words("class dynamic function interface module object package value"),
729 builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
730 " native optional sealed see serializable shared suppressWarnings tagged throws variable"),
731 isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
732 isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
733 numberStart: /[\d#$]/,
734 number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
735 multiLineStrings: true,
736 typeFirstDefinitions: true,
737 atoms: words("true false null larger smaller equal empty finished"),
738 indentSwitch: false,
739 styleDefs: false,
740 hooks: {
741 "@": function(stream) {
742 stream.eatWhile(/[\w\$_]/);
743 return "meta";
744 },
745 '"': function(stream, state) {
746 state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
747 return state.tokenize(stream, state);
748 },
749 '`': function(stream, state) {
750 if (!stringTokenizer || !stream.match('`')) return false;
751 state.tokenize = stringTokenizer;
752 stringTokenizer = null;
753 return state.tokenize(stream, state);
754 },
755 "'": function(stream) {
756 stream.eatWhile(/[\w\$_\xa1-\uffff]/);
757 return "atom";
758 },
759 token: function(_stream, state, style) {
760 if ((style == "variable" || style == "variable-3") &&
761 state.prevToken == ".") {
762 return "variable-2";
763 }
764 }
765 },
766 modeProps: {
767 fold: ["brace", "import"],
768 closeBrackets: {triples: '"'}
769 }
770 });
771
591 772 });
@@ -59,7 +59,8 b' CodeMirror.defineMode("clojure", functio'
59 59 sign: /[+-]/,
60 60 exponent: /e/i,
61 61 keyword_char: /[^\s\(\[\;\)\]]/,
62 symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/
62 symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/,
63 block_indent: /^(?:def|with)[^\/]+$|\/(?:def|with)/
63 64 };
64 65
65 66 function stateStack(indent, type, prev) { // represents a state stack object
@@ -96,6 +97,9 b' CodeMirror.defineMode("clojure", functio'
96 97 if ( '.' == stream.peek() ) {
97 98 stream.eat('.');
98 99 stream.eatWhile(tests.digit);
100 } else if ('/' == stream.peek() ) {
101 stream.eat('/');
102 stream.eatWhile(tests.digit);
99 103 }
100 104
101 105 if ( stream.eat(tests.exponent) ) {
@@ -139,7 +143,7 b' CodeMirror.defineMode("clojure", functio'
139 143 }
140 144
141 145 // skip spaces
142 if (stream.eatSpace()) {
146 if (state.mode != "string" && stream.eatSpace()) {
143 147 return null;
144 148 }
145 149 var returnType = null;
@@ -187,7 +191,7 b' CodeMirror.defineMode("clojure", functio'
187 191 }
188 192
189 193 if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
190 /^(?:def|with)/.test(keyWord))) { // indent-word
194 tests.block_indent.test(keyWord))) { // indent-word
191 195 pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
192 196 } else { // non-indent word
193 197 // we continue eating the spaces
@@ -240,5 +244,6 b' CodeMirror.defineMode("clojure", functio'
240 244 });
241 245
242 246 CodeMirror.defineMIME("text/x-clojure", "clojure");
247 CodeMirror.defineMIME("text/x-clojurescript", "clojure");
243 248
244 249 });
@@ -25,7 +25,7 b' CodeMirror.defineMode("coffeescript", fu'
25 25 var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
26 26 var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
27 27 var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
28 var properties = /^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/;
28 var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;
29 29
30 30 var wordOperators = wordRegexp(["and", "or", "not",
31 31 "is", "isnt", "in",
@@ -145,6 +145,8 b' CodeMirror.defineMode("coffeescript", fu'
145 145 }
146 146 }
147 147
148
149
148 150 // Handle operators and delimiters
149 151 if (stream.match(operators) || stream.match(wordOperators)) {
150 152 return "operator";
@@ -157,6 +159,10 b' CodeMirror.defineMode("coffeescript", fu'
157 159 return "atom";
158 160 }
159 161
162 if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
163 return "property";
164 }
165
160 166 if (stream.match(keywords)) {
161 167 return "keyword";
162 168 }
@@ -165,10 +171,6 b' CodeMirror.defineMode("coffeescript", fu'
165 171 return "variable";
166 172 }
167 173
168 if (stream.match(properties)) {
169 return "property";
170 }
171
172 174 // Handle non-detected items
173 175 stream.next();
174 176 return ERRORCLASS;
@@ -265,24 +267,11 b' CodeMirror.defineMode("coffeescript", fu'
265 267 var style = state.tokenize(stream, state);
266 268 var current = stream.current();
267 269
268 // Handle "." connected identifiers
269 if (current === ".") {
270 style = state.tokenize(stream, state);
271 current = stream.current();
272 if (/^\.[\w$]+$/.test(current)) {
273 return "variable";
274 } else {
275 return ERRORCLASS;
276 }
277 }
278
279 270 // Handle scope changes.
280 271 if (current === "return") {
281 272 state.dedent = true;
282 273 }
283 if (((current === "->" || current === "=>") &&
284 !state.lambda &&
285 !stream.peek())
274 if (((current === "->" || current === "=>") && stream.eol())
286 275 || style === "indent") {
287 276 indent(stream, state);
288 277 }
@@ -324,8 +313,7 b' CodeMirror.defineMode("coffeescript", fu'
324 313 return {
325 314 tokenize: tokenBase,
326 315 scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
327 lastToken: null,
328 lambda: false,
316 prop: false,
329 317 dedent: 0
330 318 };
331 319 },
@@ -335,12 +323,9 b' CodeMirror.defineMode("coffeescript", fu'
335 323 if (fillAlign && stream.sol()) fillAlign.align = false;
336 324
337 325 var style = tokenLexer(stream, state);
338 if (fillAlign && style && style != "comment") fillAlign.align = true;
339
340 state.lastToken = {style:style, content: stream.current()};
341
342 if (stream.eol() && stream.lambda) {
343 state.lambda = false;
326 if (style && style != "comment") {
327 if (fillAlign) fillAlign.align = true;
328 state.prop = style == "punctuation" && stream.current() == "."
344 329 }
345 330
346 331 return style;
@@ -365,5 +350,6 b' CodeMirror.defineMode("coffeescript", fu'
365 350 });
366 351
367 352 CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
353 CodeMirror.defineMIME("text/coffeescript", "coffeescript");
368 354
369 355 });
@@ -12,6 +12,7 b''
12 12 "use strict";
13 13
14 14 CodeMirror.defineMode("css", function(config, parserConfig) {
15 var inline = parserConfig.inline
15 16 if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
16 17
17 18 var indentUnit = config.indentUnit,
@@ -19,13 +20,15 b' CodeMirror.defineMode("css", function(co'
19 20 documentTypes = parserConfig.documentTypes || {},
20 21 mediaTypes = parserConfig.mediaTypes || {},
21 22 mediaFeatures = parserConfig.mediaFeatures || {},
23 mediaValueKeywords = parserConfig.mediaValueKeywords || {},
22 24 propertyKeywords = parserConfig.propertyKeywords || {},
23 25 nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
24 26 fontProperties = parserConfig.fontProperties || {},
25 27 counterDescriptors = parserConfig.counterDescriptors || {},
26 28 colorKeywords = parserConfig.colorKeywords || {},
27 29 valueKeywords = parserConfig.valueKeywords || {},
28 allowNested = parserConfig.allowNested;
30 allowNested = parserConfig.allowNested,
31 supportsAtComponent = parserConfig.supportsAtComponent === true;
29 32
30 33 var type, override;
31 34 function ret(style, tp) { type = tp; return style; }
@@ -119,13 +122,14 b' CodeMirror.defineMode("css", function(co'
119 122 this.prev = prev;
120 123 }
121 124
122 function pushContext(state, stream, type) {
123 state.context = new Context(type, stream.indentation() + indentUnit, state.context);
125 function pushContext(state, stream, type, indent) {
126 state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
124 127 return type;
125 128 }
126 129
127 130 function popContext(state) {
128 state.context = state.context.prev;
131 if (state.context.prev)
132 state.context = state.context.prev;
129 133 return state.context.type;
130 134 }
131 135
@@ -157,9 +161,13 b' CodeMirror.defineMode("css", function(co'
157 161 return pushContext(state, stream, "block");
158 162 } else if (type == "}" && state.context.prev) {
159 163 return popContext(state);
160 } else if (/@(media|supports|(-moz-)?document)/.test(type)) {
164 } else if (supportsAtComponent && /@component/.test(type)) {
165 return pushContext(state, stream, "atComponentBlock");
166 } else if (/^@(-moz-)?document$/.test(type)) {
167 return pushContext(state, stream, "documentTypes");
168 } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
161 169 return pushContext(state, stream, "atBlock");
162 } else if (/@(font-face|counter-style)/.test(type)) {
170 } else if (/^@(font-face|counter-style)/.test(type)) {
163 171 state.stateArg = type;
164 172 return "restricted_atBlock_before";
165 173 } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
@@ -219,7 +227,7 b' CodeMirror.defineMode("css", function(co'
219 227 if (type == "}" || type == "{") return popAndPass(type, stream, state);
220 228 if (type == "(") return pushContext(state, stream, "parens");
221 229
222 if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
230 if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
223 231 override += " error";
224 232 } else if (type == "word") {
225 233 wordAsValue(stream);
@@ -252,33 +260,56 b' CodeMirror.defineMode("css", function(co'
252 260 return pass(type, stream, state);
253 261 };
254 262
263 states.documentTypes = function(type, stream, state) {
264 if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
265 override = "tag";
266 return state.context.type;
267 } else {
268 return states.atBlock(type, stream, state);
269 }
270 };
271
255 272 states.atBlock = function(type, stream, state) {
256 273 if (type == "(") return pushContext(state, stream, "atBlock_parens");
257 if (type == "}") return popAndPass(type, stream, state);
274 if (type == "}" || type == ";") return popAndPass(type, stream, state);
258 275 if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
259 276
277 if (type == "interpolation") return pushContext(state, stream, "interpolation");
278
260 279 if (type == "word") {
261 280 var word = stream.current().toLowerCase();
262 281 if (word == "only" || word == "not" || word == "and" || word == "or")
263 282 override = "keyword";
264 else if (documentTypes.hasOwnProperty(word))
265 override = "tag";
266 283 else if (mediaTypes.hasOwnProperty(word))
267 284 override = "attribute";
268 285 else if (mediaFeatures.hasOwnProperty(word))
269 286 override = "property";
287 else if (mediaValueKeywords.hasOwnProperty(word))
288 override = "keyword";
270 289 else if (propertyKeywords.hasOwnProperty(word))
271 290 override = "property";
272 291 else if (nonStandardPropertyKeywords.hasOwnProperty(word))
273 292 override = "string-2";
274 293 else if (valueKeywords.hasOwnProperty(word))
275 294 override = "atom";
295 else if (colorKeywords.hasOwnProperty(word))
296 override = "keyword";
276 297 else
277 298 override = "error";
278 299 }
279 300 return state.context.type;
280 301 };
281 302
303 states.atComponentBlock = function(type, stream, state) {
304 if (type == "}")
305 return popAndPass(type, stream, state);
306 if (type == "{")
307 return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
308 if (type == "word")
309 override = "error";
310 return state.context.type;
311 };
312
282 313 states.atBlock_parens = function(type, stream, state) {
283 314 if (type == ")") return popContext(state);
284 315 if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
@@ -336,9 +367,9 b' CodeMirror.defineMode("css", function(co'
336 367 return {
337 368 startState: function(base) {
338 369 return {tokenize: null,
339 state: "top",
370 state: inline ? "block" : "top",
340 371 stateArg: null,
341 context: new Context("top", base || 0, null)};
372 context: new Context(inline ? "block" : "top", base || 0, null)};
342 373 },
343 374
344 375 token: function(stream, state) {
@@ -357,12 +388,18 b' CodeMirror.defineMode("css", function(co'
357 388 var cx = state.context, ch = textAfter && textAfter.charAt(0);
358 389 var indent = cx.indent;
359 390 if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
360 if (cx.prev &&
361 (ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "restricted_atBlock") ||
362 ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
363 ch == "{" && (cx.type == "at" || cx.type == "atBlock"))) {
364 indent = cx.indent - indentUnit;
365 cx = cx.prev;
391 if (cx.prev) {
392 if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
393 cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
394 // Resume indentation from parent context.
395 cx = cx.prev;
396 indent = cx.indent;
397 } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
398 ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
399 // Dedent relative to current context.
400 indent = Math.max(0, cx.indent - indentUnit);
401 cx = cx.prev;
402 }
366 403 }
367 404 return indent;
368 405 },
@@ -399,17 +436,24 b' CodeMirror.defineMode("css", function(co'
399 436 "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
400 437 "max-color", "color-index", "min-color-index", "max-color-index",
401 438 "monochrome", "min-monochrome", "max-monochrome", "resolution",
402 "min-resolution", "max-resolution", "scan", "grid"
439 "min-resolution", "max-resolution", "scan", "grid", "orientation",
440 "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
441 "pointer", "any-pointer", "hover", "any-hover"
403 442 ], mediaFeatures = keySet(mediaFeatures_);
404 443
444 var mediaValueKeywords_ = [
445 "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
446 "interlace", "progressive"
447 ], mediaValueKeywords = keySet(mediaValueKeywords_);
448
405 449 var propertyKeywords_ = [
406 450 "align-content", "align-items", "align-self", "alignment-adjust",
407 451 "alignment-baseline", "anchor-point", "animation", "animation-delay",
408 452 "animation-direction", "animation-duration", "animation-fill-mode",
409 453 "animation-iteration-count", "animation-name", "animation-play-state",
410 454 "animation-timing-function", "appearance", "azimuth", "backface-visibility",
411 "background", "background-attachment", "background-clip", "background-color",
412 "background-image", "background-origin", "background-position",
455 "background", "background-attachment", "background-blend-mode", "background-clip",
456 "background-color", "background-image", "background-origin", "background-position",
413 457 "background-repeat", "background-size", "baseline-shift", "binding",
414 458 "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
415 459 "bookmark-target", "border", "border-bottom", "border-bottom-color",
@@ -553,11 +597,12 b' CodeMirror.defineMode("css", function(co'
553 597 "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
554 598 "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
555 599 "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
556 "col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
600 "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
601 "compact", "condensed", "contain", "content",
557 602 "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
558 "cross", "crosshair", "currentcolor", "cursive", "cyclic", "dashed", "decimal",
603 "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
559 604 "decimal-leading-zero", "default", "default-button", "destination-atop",
560 "destination-in", "destination-out", "destination-over", "devanagari",
605 "destination-in", "destination-out", "destination-over", "devanagari", "difference",
561 606 "disc", "discard", "disclosure-closed", "disclosure-open", "document",
562 607 "dot-dash", "dot-dot-dash",
563 608 "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
@@ -568,23 +613,23 b' CodeMirror.defineMode("css", function(co'
568 613 "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
569 614 "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
570 615 "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
571 "ethiopic-numeric", "ew-resize", "expanded", "extends", "extra-condensed",
572 "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "footnotes",
616 "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
617 "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
573 618 "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
574 "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
619 "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
575 620 "help", "hidden", "hide", "higher", "highlight", "highlighttext",
576 "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
621 "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
577 622 "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
578 623 "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
579 624 "inline-block", "inline-flex", "inline-table", "inset", "inside", "intrinsic", "invert",
580 625 "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
581 626 "katakana", "katakana-iroha", "keep-all", "khmer",
582 627 "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
583 "landscape", "lao", "large", "larger", "left", "level", "lighter",
628 "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
584 629 "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
585 630 "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
586 631 "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
587 "lower-roman", "lowercase", "ltr", "malayalam", "match", "matrix", "matrix3d",
632 "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
588 633 "media-controls-background", "media-current-time-display",
589 634 "media-fullscreen-button", "media-mute-button", "media-play-button",
590 635 "media-return-to-realtime-button", "media-rewind-button",
@@ -593,7 +638,7 b' CodeMirror.defineMode("css", function(co'
593 638 "media-volume-slider-container", "media-volume-sliderthumb", "medium",
594 639 "menu", "menulist", "menulist-button", "menulist-text",
595 640 "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
596 "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize",
641 "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
597 642 "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
598 643 "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
599 644 "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
@@ -606,8 +651,8 b' CodeMirror.defineMode("css", function(co'
606 651 "relative", "repeat", "repeating-linear-gradient",
607 652 "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
608 653 "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
609 "rotateZ", "round", "row-resize", "rtl", "run-in", "running",
610 "s-resize", "sans-serif", "scale", "scale3d", "scaleX", "scaleY", "scaleZ",
654 "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
655 "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
611 656 "scroll", "scrollbar", "se-resize", "searchfield",
612 657 "searchfield-cancel-button", "searchfield-decoration",
613 658 "searchfield-results-button", "searchfield-results-decoration",
@@ -615,8 +660,8 b' CodeMirror.defineMode("css", function(co'
615 660 "simp-chinese-formal", "simp-chinese-informal", "single",
616 661 "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
617 662 "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
618 "small", "small-caps", "small-caption", "smaller", "solid", "somali",
619 "source-atop", "source-in", "source-out", "source-over", "space", "spell-out", "square",
663 "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
664 "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
620 665 "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
621 666 "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
622 667 "table-caption", "table-cell", "table-column", "table-column-group",
@@ -633,12 +678,13 b' CodeMirror.defineMode("css", function(co'
633 678 "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
634 679 "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
635 680 "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
636 "window", "windowframe", "windowtext", "words", "x-large", "x-small", "xor",
681 "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
637 682 "xx-large", "xx-small"
638 683 ], valueKeywords = keySet(valueKeywords_);
639 684
640 var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(propertyKeywords_)
641 .concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
685 var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
686 .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
687 .concat(valueKeywords_);
642 688 CodeMirror.registerHelper("hintWords", "css", allWords);
643 689
644 690 function tokenCComment(stream, state) {
@@ -657,6 +703,7 b' CodeMirror.defineMode("css", function(co'
657 703 documentTypes: documentTypes,
658 704 mediaTypes: mediaTypes,
659 705 mediaFeatures: mediaFeatures,
706 mediaValueKeywords: mediaValueKeywords,
660 707 propertyKeywords: propertyKeywords,
661 708 nonStandardPropertyKeywords: nonStandardPropertyKeywords,
662 709 fontProperties: fontProperties,
@@ -676,6 +723,7 b' CodeMirror.defineMode("css", function(co'
676 723 CodeMirror.defineMIME("text/x-scss", {
677 724 mediaTypes: mediaTypes,
678 725 mediaFeatures: mediaFeatures,
726 mediaValueKeywords: mediaValueKeywords,
679 727 propertyKeywords: propertyKeywords,
680 728 nonStandardPropertyKeywords: nonStandardPropertyKeywords,
681 729 colorKeywords: colorKeywords,
@@ -717,6 +765,7 b' CodeMirror.defineMode("css", function(co'
717 765 CodeMirror.defineMIME("text/x-less", {
718 766 mediaTypes: mediaTypes,
719 767 mediaFeatures: mediaFeatures,
768 mediaValueKeywords: mediaValueKeywords,
720 769 propertyKeywords: propertyKeywords,
721 770 nonStandardPropertyKeywords: nonStandardPropertyKeywords,
722 771 colorKeywords: colorKeywords,
@@ -751,4 +800,26 b' CodeMirror.defineMode("css", function(co'
751 800 helperType: "less"
752 801 });
753 802
803 CodeMirror.defineMIME("text/x-gss", {
804 documentTypes: documentTypes,
805 mediaTypes: mediaTypes,
806 mediaFeatures: mediaFeatures,
807 propertyKeywords: propertyKeywords,
808 nonStandardPropertyKeywords: nonStandardPropertyKeywords,
809 fontProperties: fontProperties,
810 counterDescriptors: counterDescriptors,
811 colorKeywords: colorKeywords,
812 valueKeywords: valueKeywords,
813 supportsAtComponent: true,
814 tokenHooks: {
815 "/": function(stream, state) {
816 if (!stream.eat("*")) return false;
817 state.tokenize = tokenCComment;
818 return tokenCComment(stream, state);
819 }
820 },
821 name: "css",
822 helperType: "gss"
823 });
824
754 825 });
@@ -60,9 +60,9 b''
60 60 };
61 61 var indentUnit = config.indentUnit;
62 62 var curPunc;
63 var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "right", "round", "rtrim", "shortestPath", "sign", "sin", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "trim", "type", "upper"]);
64 var preds = wordRegexp(["all", "and", "any", "has", "in", "none", "not", "or", "single", "xor"]);
65 var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "distinct", "drop", "else", "end", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
63 var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]);
64 var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]);
65 var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with"]);
66 66 var operatorChars = /[*+\-<>=&|~%^]/;
67 67
68 68 return {
@@ -15,7 +15,7 b''
15 15 "implements get native operator set typedef with enum throw rethrow " +
16 16 "assert break case continue default in return new deferred async await " +
17 17 "try catch finally do else for if switch while import library export " +
18 "part of show hide is").split(" ");
18 "part of show hide is as").split(" ");
19 19 var blockKeywords = "try catch finally do else for if switch while".split(" ");
20 20 var atoms = "true false null".split(" ");
21 21 var builtins = "void bool num int double dynamic var String".split(" ");
@@ -26,21 +26,101 b''
26 26 return obj;
27 27 }
28 28
29 function pushInterpolationStack(state) {
30 (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize);
31 }
32
33 function popInterpolationStack(state) {
34 return (state.interpolationStack || (state.interpolationStack = [])).pop();
35 }
36
37 function sizeInterpolationStack(state) {
38 return state.interpolationStack ? state.interpolationStack.length : 0;
39 }
40
29 41 CodeMirror.defineMIME("application/dart", {
30 42 name: "clike",
31 43 keywords: set(keywords),
32 multiLineStrings: true,
33 44 blockKeywords: set(blockKeywords),
34 45 builtin: set(builtins),
35 46 atoms: set(atoms),
36 47 hooks: {
37 48 "@": function(stream) {
38 stream.eatWhile(/[\w\$_]/);
49 stream.eatWhile(/[\w\$_\.]/);
39 50 return "meta";
51 },
52
53 // custom string handling to deal with triple-quoted strings and string interpolation
54 "'": function(stream, state) {
55 return tokenString("'", stream, state, false);
56 },
57 "\"": function(stream, state) {
58 return tokenString("\"", stream, state, false);
59 },
60 "r": function(stream, state) {
61 var peek = stream.peek();
62 if (peek == "'" || peek == "\"") {
63 return tokenString(stream.next(), stream, state, true);
64 }
65 return false;
66 },
67
68 "}": function(_stream, state) {
69 // "}" is end of interpolation, if interpolation stack is non-empty
70 if (sizeInterpolationStack(state) > 0) {
71 state.tokenize = popInterpolationStack(state);
72 return null;
73 }
74 return false;
40 75 }
41 76 }
42 77 });
43 78
79 function tokenString(quote, stream, state, raw) {
80 var tripleQuoted = false;
81 if (stream.eat(quote)) {
82 if (stream.eat(quote)) tripleQuoted = true;
83 else return "string"; //empty string
84 }
85 function tokenStringHelper(stream, state) {
86 var escaped = false;
87 while (!stream.eol()) {
88 if (!raw && !escaped && stream.peek() == "$") {
89 pushInterpolationStack(state);
90 state.tokenize = tokenInterpolation;
91 return "string";
92 }
93 var next = stream.next();
94 if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
95 state.tokenize = null;
96 break;
97 }
98 escaped = !raw && !escaped && next == "\\";
99 }
100 return "string";
101 }
102 state.tokenize = tokenStringHelper;
103 return tokenStringHelper(stream, state);
104 }
105
106 function tokenInterpolation(stream, state) {
107 stream.eat("$");
108 if (stream.eat("{")) {
109 // let clike handle the content of ${...},
110 // we take over again when "}" appears (see hooks).
111 state.tokenize = null;
112 } else {
113 state.tokenize = tokenInterpolationIdentifier;
114 }
115 return null;
116 }
117
118 function tokenInterpolationIdentifier(stream, state) {
119 stream.eatWhile(/[\w_]/);
120 state.tokenize = popInterpolationStack(state);
121 return "variable";
122 }
123
44 124 CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins));
45 125
46 126 // This is needed to make loading through meta.js work.
@@ -14,14 +14,14 b''
14 14 "use strict";
15 15
16 16 CodeMirror.defineMode("django:inner", function() {
17 var keywords = ["block", "endblock", "for", "endfor", "true", "false",
18 "loop", "none", "self", "super", "if", "endif", "as",
19 "else", "import", "with", "endwith", "without", "context", "ifequal", "endifequal",
20 "ifnotequal", "endifnotequal", "extends", "include", "load", "comment",
21 "endcomment", "empty", "url", "static", "trans", "blocktrans", "now", "regroup",
22 "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle", "csrf_token",
23 "autoescape", "endautoescape", "spaceless", "ssi", "templatetag",
24 "verbatim", "endverbatim", "widthratio"],
17 var keywords = ["block", "endblock", "for", "endfor", "true", "false", "filter", "endfilter",
18 "loop", "none", "self", "super", "if", "elif", "endif", "as", "else", "import",
19 "with", "endwith", "without", "context", "ifequal", "endifequal", "ifnotequal",
20 "endifnotequal", "extends", "include", "load", "comment", "endcomment",
21 "empty", "url", "static", "trans", "blocktrans", "endblocktrans", "now",
22 "regroup", "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle",
23 "csrf_token", "autoescape", "endautoescape", "spaceless", "endspaceless",
24 "ssi", "templatetag", "verbatim", "endverbatim", "widthratio"],
25 25 filters = ["add", "addslashes", "capfirst", "center", "cut", "date",
26 26 "default", "default_if_none", "dictsort",
27 27 "dictsortreversed", "divisibleby", "escape", "escapejs",
@@ -35,11 +35,13 b''
35 35 "truncatechars_html", "truncatewords", "truncatewords_html",
36 36 "unordered_list", "upper", "urlencode", "urlize",
37 37 "urlizetrunc", "wordcount", "wordwrap", "yesno"],
38 operators = ["==", "!=", "<", ">", "<=", ">=", "in", "not", "or", "and"];
38 operators = ["==", "!=", "<", ">", "<=", ">="],
39 wordOperators = ["in", "not", "or", "and"];
39 40
40 41 keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b");
41 42 filters = new RegExp("^\\b(" + filters.join("|") + ")\\b");
42 43 operators = new RegExp("^\\b(" + operators.join("|") + ")\\b");
44 wordOperators = new RegExp("^\\b(" + wordOperators.join("|") + ")\\b");
43 45
44 46 // We have to return "null" instead of null, in order to avoid string
45 47 // styling as the default, when using Django templates inside HTML
@@ -59,7 +61,7 b''
59 61
60 62 // Ignore completely any stream series that do not match the
61 63 // Django template opening tags.
62 while (stream.next() != null && !stream.match("{{", false) && !stream.match("{%", false)) {}
64 while (stream.next() != null && !stream.match(/\{[{%#]/, false)) {}
63 65 return null;
64 66 }
65 67
@@ -270,6 +272,11 b''
270 272 return "operator";
271 273 }
272 274
275 // Attempt to match a word operator
276 if (stream.match(wordOperators)) {
277 return "keyword";
278 }
279
273 280 // Attempt to match a keyword
274 281 var keywordMatch = stream.match(keywords);
275 282 if (keywordMatch) {
@@ -310,9 +317,8 b''
310 317
311 318 // Mark everything as comment inside the tag and the tag itself.
312 319 function inComment (stream, state) {
313 if (stream.match("#}")) {
314 state.tokenize = tokenBase;
315 }
320 if (stream.match(/^.*?#\}/)) state.tokenize = tokenBase
321 else stream.skipToEnd()
316 322 return "comment";
317 323 }
318 324
@@ -69,7 +69,10 b''
69 69 token: null,
70 70 next: "start"
71 71 }
72 ]
72 ],
73 meta: {
74 lineComment: "#"
75 }
73 76 });
74 77
75 78 CodeMirror.defineMIME("text/x-dockerfile", "dockerfile");
@@ -202,4 +202,4 b''
202 202 });
203 203
204 204 CodeMirror.defineMIME("text/x-elm", "elm");
205 })();
205 });
@@ -220,8 +220,6 b' CodeMirror.defineMode("erlang", function'
220 220 }else{
221 221 return rval(state,stream,"function");
222 222 }
223 }else if (is_member(w,operatorAtomWords)) {
224 return rval(state,stream,"operator");
225 223 }else if (lookahead(stream) == ":") {
226 224 if (w == "erlang") {
227 225 return rval(state,stream,"builtin");
@@ -230,8 +228,6 b' CodeMirror.defineMode("erlang", function'
230 228 }
231 229 }else if (is_member(w,["true","false"])) {
232 230 return rval(state,stream,"boolean");
233 }else if (is_member(w,["true","false"])) {
234 return rval(state,stream,"boolean");
235 231 }else{
236 232 return rval(state,stream,"atom");
237 233 }
@@ -11,6 +11,8 b''
11 11 })(function(CodeMirror) {
12 12 "use strict";
13 13
14 var urlRE = /^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i
15
14 16 CodeMirror.defineMode("gfm", function(config, modeConfig) {
15 17 var codeDepth = 0;
16 18 function blankLine(state) {
@@ -37,7 +39,7 b' CodeMirror.defineMode("gfm", function(co'
37 39
38 40 // Hack to prevent formatting override inside code blocks (block and inline)
39 41 if (state.codeBlock) {
40 if (stream.match(/^```/)) {
42 if (stream.match(/^```+/)) {
41 43 state.codeBlock = false;
42 44 return null;
43 45 }
@@ -47,7 +49,7 b' CodeMirror.defineMode("gfm", function(co'
47 49 if (stream.sol()) {
48 50 state.code = false;
49 51 }
50 if (stream.sol() && stream.match(/^```/)) {
52 if (stream.sol() && stream.match(/^```+/)) {
51 53 stream.skipToEnd();
52 54 state.codeBlock = true;
53 55 return null;
@@ -78,25 +80,29 b' CodeMirror.defineMode("gfm", function(co'
78 80 }
79 81 if (stream.sol() || state.ateSpace) {
80 82 state.ateSpace = false;
81 if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
82 // User/Project@SHA
83 // User@SHA
84 // SHA
85 state.combineTokens = true;
86 return "link";
87 } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
88 // User/Project#Num
89 // User#Num
90 // #Num
91 state.combineTokens = true;
92 return "link";
83 if (modeConfig.gitHubSpice !== false) {
84 if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
85 // User/Project@SHA
86 // User@SHA
87 // SHA
88 state.combineTokens = true;
89 return "link";
90 } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
91 // User/Project#Num
92 // User#Num
93 // #Num
94 state.combineTokens = true;
95 return "link";
96 }
93 97 }
94 98 }
95 if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i) &&
96 stream.string.slice(stream.start - 2, stream.start) != "](") {
99 if (stream.match(urlRE) &&
100 stream.string.slice(stream.start - 2, stream.start) != "](" &&
101 (stream.start == 0 || /\W/.test(stream.string.charAt(stream.start - 1)))) {
97 102 // URLs
98 103 // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
99 104 // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
105 // And then limited url schemes to the CommonMark list, so foo:bar isn't matched as a URL
100 106 state.combineTokens = true;
101 107 return "link";
102 108 }
@@ -109,15 +115,16 b' CodeMirror.defineMode("gfm", function(co'
109 115 var markdownConfig = {
110 116 underscoresBreakWords: false,
111 117 taskLists: true,
112 fencedCodeBlocks: true,
118 fencedCodeBlocks: '```',
113 119 strikethrough: true
114 120 };
115 121 for (var attr in modeConfig) {
116 122 markdownConfig[attr] = modeConfig[attr];
117 123 }
118 124 markdownConfig.name = "markdown";
119 CodeMirror.defineMIME("gfmBase", markdownConfig);
120 return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
125 return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay);
126
121 127 }, "markdown");
122 128
129 CodeMirror.defineMIME("text/x-gfm", "gfm");
123 130 });
@@ -86,7 +86,7 b' CodeMirror.defineMode("go", function(con'
86 86 var escaped = false, next, end = false;
87 87 while ((next = stream.next()) != null) {
88 88 if (next == quote && !escaped) {end = true; break;}
89 escaped = !escaped && next == "\\";
89 escaped = !escaped && quote != "`" && next == "\\";
90 90 }
91 91 if (end || !(escaped || quote == "`"))
92 92 state.tokenize = tokenBase;
@@ -85,8 +85,10 b''
85 85 state.tokenize = rubyInQuote(")");
86 86 return state.tokenize(stream, state);
87 87 } else if (ch == "{") {
88 state.tokenize = rubyInQuote("}");
89 return state.tokenize(stream, state);
88 if (!stream.match(/^\{%.*/)) {
89 state.tokenize = rubyInQuote("}");
90 return state.tokenize(stream, state);
91 }
90 92 }
91 93 }
92 94
@@ -3,15 +3,15 b''
3 3
4 4 (function(mod) {
5 5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
6 mod(require("../../lib/codemirror"), require("../../addon/mode/simple"), require("../../addon/mode/multiplex"));
7 7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
8 define(["../../lib/codemirror", "../../addon/mode/simple", "../../addon/mode/multiplex"], mod);
9 9 else // Plain browser env
10 10 mod(CodeMirror);
11 11 })(function(CodeMirror) {
12 12 "use strict";
13 13
14 CodeMirror.defineSimpleMode("handlebars", {
14 CodeMirror.defineSimpleMode("handlebars-tags", {
15 15 start: [
16 16 { regex: /\{\{!--/, push: "dash_comment", token: "comment" },
17 17 { regex: /\{\{!/, push: "comment", token: "comment" },
@@ -21,8 +21,8 b''
21 21 { regex: /\}\}/, pop: true, token: "tag" },
22 22
23 23 // Double and single quotes
24 { regex: /"(?:[^\\]|\\.)*?"/, token: "string" },
25 { regex: /'(?:[^\\]|\\.)*?'/, token: "string" },
24 { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" },
25 { regex: /'(?:[^\\']|\\.)*'?/, token: "string" },
26 26
27 27 // Handlebars keywords
28 28 { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
@@ -49,5 +49,14 b''
49 49 ]
50 50 });
51 51
52 CodeMirror.defineMode("handlebars", function(config, parserConfig) {
53 var handlebars = CodeMirror.getMode(config, "handlebars-tags");
54 if (!parserConfig || !parserConfig.base) return handlebars;
55 return CodeMirror.multiplexingMode(
56 CodeMirror.getMode(config, parserConfig.base),
57 {open: "{{", close: "}}", mode: handlebars, parseDelimiters: true}
58 );
59 });
60
52 61 CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
53 62 });
@@ -16,23 +16,21 b' CodeMirror.defineMode("haxe", function(c'
16 16
17 17 // Tokenizer
18 18
19 var keywords = function(){
20 function kw(type) {return {type: type, style: "keyword"};}
21 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
22 var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"};
19 function kw(type) {return {type: type, style: "keyword"};}
20 var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
21 var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"};
23 22 var type = kw("typedef");
24 return {
25 "if": A, "while": A, "else": B, "do": B, "try": B,
26 "return": C, "break": C, "continue": C, "new": C, "throw": C,
27 "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
23 var keywords = {
24 "if": A, "while": A, "else": B, "do": B, "try": B,
25 "return": C, "break": C, "continue": C, "new": C, "throw": C,
26 "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"),
28 27 "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"),
29 "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
30 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
31 "in": operator, "never": kw("property_access"), "trace":kw("trace"),
28 "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"),
29 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
30 "in": operator, "never": kw("property_access"), "trace":kw("trace"),
32 31 "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type,
33 "true": atom, "false": atom, "null": atom
34 };
35 }();
32 "true": atom, "false": atom, "null": atom
33 };
36 34
37 35 var isOperatorChar = /[+\-*&%=<>!?|]/;
38 36
@@ -41,14 +39,13 b' CodeMirror.defineMode("haxe", function(c'
41 39 return f(stream, state);
42 40 }
43 41
44 function nextUntilUnescaped(stream, end) {
42 function toUnescaped(stream, end) {
45 43 var escaped = false, next;
46 44 while ((next = stream.next()) != null) {
47 45 if (next == end && !escaped)
48 return false;
46 return true;
49 47 escaped = !escaped && next == "\\";
50 48 }
51 return escaped;
52 49 }
53 50
54 51 // Used as scratch variables to communicate multiple values without
@@ -61,70 +58,58 b' CodeMirror.defineMode("haxe", function(c'
61 58
62 59 function haxeTokenBase(stream, state) {
63 60 var ch = stream.next();
64 if (ch == '"' || ch == "'")
61 if (ch == '"' || ch == "'") {
65 62 return chain(stream, state, haxeTokenString(ch));
66 else if (/[\[\]{}\(\),;\:\.]/.test(ch))
63 } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
67 64 return ret(ch);
68 else if (ch == "0" && stream.eat(/x/i)) {
65 } else if (ch == "0" && stream.eat(/x/i)) {
69 66 stream.eatWhile(/[\da-f]/i);
70 67 return ret("number", "number");
71 }
72 else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
73 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
68 } else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
69 stream.match(/^\d*(?:\.\d*(?!\.))?(?:[eE][+\-]?\d+)?/);
74 70 return ret("number", "number");
75 }
76 else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
77 nextUntilUnescaped(stream, "/");
71 } else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) {
72 toUnescaped(stream, "/");
78 73 stream.eatWhile(/[gimsu]/);
79 74 return ret("regexp", "string-2");
80 }
81 else if (ch == "/") {
75 } else if (ch == "/") {
82 76 if (stream.eat("*")) {
83 77 return chain(stream, state, haxeTokenComment);
84 }
85 else if (stream.eat("/")) {
78 } else if (stream.eat("/")) {
86 79 stream.skipToEnd();
87 80 return ret("comment", "comment");
88 }
89 else {
81 } else {
90 82 stream.eatWhile(isOperatorChar);
91 83 return ret("operator", null, stream.current());
92 84 }
93 }
94 else if (ch == "#") {
85 } else if (ch == "#") {
95 86 stream.skipToEnd();
96 87 return ret("conditional", "meta");
97 }
98 else if (ch == "@") {
88 } else if (ch == "@") {
99 89 stream.eat(/:/);
100 90 stream.eatWhile(/[\w_]/);
101 91 return ret ("metadata", "meta");
102 }
103 else if (isOperatorChar.test(ch)) {
92 } else if (isOperatorChar.test(ch)) {
104 93 stream.eatWhile(isOperatorChar);
105 94 return ret("operator", null, stream.current());
106 }
107 else {
108 var word;
109 if(/[A-Z]/.test(ch))
110 {
111 stream.eatWhile(/[\w_<>]/);
112 word = stream.current();
113 return ret("type", "variable-3", word);
114 }
115 else
116 {
95 } else {
96 var word;
97 if(/[A-Z]/.test(ch)) {
98 stream.eatWhile(/[\w_<>]/);
99 word = stream.current();
100 return ret("type", "variable-3", word);
101 } else {
117 102 stream.eatWhile(/[\w_]/);
118 103 var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
119 104 return (known && state.kwAllowed) ? ret(known.type, known.style, word) :
120 105 ret("variable", "variable", word);
121 }
106 }
122 107 }
123 108 }
124 109
125 110 function haxeTokenString(quote) {
126 111 return function(stream, state) {
127 if (!nextUntilUnescaped(stream, quote))
112 if (toUnescaped(stream, quote))
128 113 state.tokenize = haxeTokenBase;
129 114 return ret("string", "string");
130 115 };
@@ -176,27 +161,25 b' CodeMirror.defineMode("haxe", function(c'
176 161 cc.pop()();
177 162 if (cx.marked) return cx.marked;
178 163 if (type == "variable" && inScope(state, content)) return "variable-2";
179 if (type == "variable" && imported(state, content)) return "variable-3";
164 if (type == "variable" && imported(state, content)) return "variable-3";
180 165 return style;
181 166 }
182 167 }
183 168 }
184 169
185 function imported(state, typename)
186 {
187 if (/[a-z]/.test(typename.charAt(0)))
188 return false;
189 var len = state.importedtypes.length;
190 for (var i = 0; i<len; i++)
191 if(state.importedtypes[i]==typename) return true;
170 function imported(state, typename) {
171 if (/[a-z]/.test(typename.charAt(0)))
172 return false;
173 var len = state.importedtypes.length;
174 for (var i = 0; i<len; i++)
175 if(state.importedtypes[i]==typename) return true;
192 176 }
193 177
194
195 178 function registerimport(importname) {
196 var state = cx.state;
197 for (var t = state.importedtypes; t; t = t.next)
198 if(t.name == importname) return;
199 state.importedtypes = { name: importname, next: state.importedtypes };
179 var state = cx.state;
180 for (var t = state.importedtypes; t; t = t.next)
181 if(t.name == importname) return;
182 state.importedtypes = { name: importname, next: state.importedtypes };
200 183 }
201 184 // Combinator utils
202 185
@@ -208,13 +191,20 b' CodeMirror.defineMode("haxe", function(c'
208 191 pass.apply(null, arguments);
209 192 return true;
210 193 }
194 function inList(name, list) {
195 for (var v = list; v; v = v.next)
196 if (v.name == name) return true;
197 return false;
198 }
211 199 function register(varname) {
212 200 var state = cx.state;
213 201 if (state.context) {
214 202 cx.marked = "def";
215 for (var v = state.localVars; v; v = v.next)
216 if (v.name == varname) return;
203 if (inList(varname, state.localVars)) return;
217 204 state.localVars = {name: varname, next: state.localVars};
205 } else if (state.globalVars) {
206 if (inList(varname, state.globalVars)) return;
207 state.globalVars = {name: varname, next: state.globalVars};
218 208 }
219 209 }
220 210
@@ -229,6 +219,7 b' CodeMirror.defineMode("haxe", function(c'
229 219 cx.state.localVars = cx.state.context.vars;
230 220 cx.state.context = cx.state.context.prev;
231 221 }
222 popcontext.lex = true;
232 223 function pushlex(type, info) {
233 224 var result = function() {
234 225 var state = cx.state;
@@ -252,7 +243,7 b' CodeMirror.defineMode("haxe", function(c'
252 243 if (type == wanted) return cont();
253 244 else if (wanted == ";") return pass();
254 245 else return cont(f);
255 };
246 }
256 247 return f;
257 248 }
258 249
@@ -266,25 +257,26 b' CodeMirror.defineMode("haxe", function(c'
266 257 if (type == "attribute") return cont(maybeattribute);
267 258 if (type == "function") return cont(functiondef);
268 259 if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
269 poplex, statement, poplex);
260 poplex, statement, poplex);
270 261 if (type == "variable") return cont(pushlex("stat"), maybelabel);
271 262 if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
272 block, poplex, poplex);
263 block, poplex, poplex);
273 264 if (type == "case") return cont(expression, expect(":"));
274 265 if (type == "default") return cont(expect(":"));
275 266 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
276 statement, poplex, popcontext);
267 statement, poplex, popcontext);
277 268 if (type == "import") return cont(importdef, expect(";"));
278 269 if (type == "typedef") return cont(typedef);
279 270 return pass(pushlex("stat"), expression, expect(";"), poplex);
280 271 }
281 272 function expression(type) {
282 273 if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator);
274 if (type == "type" ) return cont(maybeoperator);
283 275 if (type == "function") return cont(functiondef);
284 276 if (type == "keyword c") return cont(maybeexpression);
285 277 if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator);
286 278 if (type == "operator") return cont(expression);
287 if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator);
279 if (type == "[") return cont(pushlex("]"), commasep(maybeexpression, "]"), poplex, maybeoperator);
288 280 if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator);
289 281 return cont();
290 282 }
@@ -318,14 +310,14 b' CodeMirror.defineMode("haxe", function(c'
318 310 }
319 311
320 312 function importdef (type, value) {
321 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
322 else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);
313 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
314 else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef);
323 315 }
324 316
325 317 function typedef (type, value)
326 318 {
327 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
328 else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }
319 if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); }
320 else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); }
329 321 }
330 322
331 323 function maybelabel(type) {
@@ -363,16 +355,19 b' CodeMirror.defineMode("haxe", function(c'
363 355 if (type == ",") return cont(vardef1);
364 356 }
365 357 function forspec1(type, value) {
366 if (type == "variable") {
367 register(value);
368 }
369 return cont(pushlex(")"), pushcontext, forin, expression, poplex, statement, popcontext);
358 if (type == "variable") {
359 register(value);
360 return cont(forin, expression)
361 } else {
362 return pass()
363 }
370 364 }
371 365 function forin(_type, value) {
372 366 if (value == "in") return cont();
373 367 }
374 368 function functiondef(type, value) {
375 if (type == "variable") {register(value); return cont(functiondef);}
369 //function names starting with upper-case letters are recognised as types, so cludging them together here.
370 if (type == "variable" || type == "type") {register(value); return cont(functiondef);}
376 371 if (value == "new") return cont(functiondef);
377 372 if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
378 373 }
@@ -392,21 +387,23 b' CodeMirror.defineMode("haxe", function(c'
392 387 }
393 388
394 389 // Interface
395
396 390 return {
397 391 startState: function(basecolumn) {
398 var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
399 return {
392 var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"];
393 var state = {
400 394 tokenize: haxeTokenBase,
401 395 reAllowed: true,
402 396 kwAllowed: true,
403 397 cc: [],
404 398 lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false),
405 399 localVars: parserConfig.localVars,
406 importedtypes: defaulttypes,
400 importedtypes: defaulttypes,
407 401 context: parserConfig.localVars && {vars: parserConfig.localVars},
408 402 indented: 0
409 403 };
404 if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
405 state.globalVars = parserConfig.globalVars;
406 return state;
410 407 },
411 408
412 409 token: function(stream, state) {
@@ -9,113 +9,142 b''
9 9 else // Plain browser env
10 10 mod(CodeMirror);
11 11 })(function(CodeMirror) {
12 "use strict";
13
14 CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
15 var htmlMode = CodeMirror.getMode(config, {name: "xml",
16 htmlMode: true,
17 multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
18 multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
19 var cssMode = CodeMirror.getMode(config, "css");
20
21 var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
22 scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
23 mode: CodeMirror.getMode(config, "javascript")});
24 if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
25 var conf = scriptTypesConf[i];
26 scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
27 }
28 scriptTypes.push({matches: /./,
29 mode: CodeMirror.getMode(config, "text/plain")});
12 "use strict";
30 13
31 function html(stream, state) {
32 var tagName = state.htmlState.tagName;
33 if (tagName) tagName = tagName.toLowerCase();
34 var style = htmlMode.token(stream, state.htmlState);
35 if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
36 // Script block: mode to change to depends on type attribute
37 var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
38 scriptType = scriptType ? scriptType[1] : "";
39 if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
40 for (var i = 0; i < scriptTypes.length; ++i) {
41 var tp = scriptTypes[i];
42 if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
43 if (tp.mode) {
44 state.token = script;
45 state.localMode = tp.mode;
46 state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
47 }
48 break;
49 }
50 }
51 } else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
52 state.token = css;
53 state.localMode = cssMode;
54 state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
55 }
56 return style;
57 }
14 var defaultTags = {
15 script: [
16 ["lang", /(javascript|babel)/i, "javascript"],
17 ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
18 ["type", /./, "text/plain"],
19 [null, null, "javascript"]
20 ],
21 style: [
22 ["lang", /^css$/i, "css"],
23 ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
24 ["type", /./, "text/plain"],
25 [null, null, "css"]
26 ]
27 };
28
58 29 function maybeBackup(stream, pat, style) {
59 var cur = stream.current();
60 var close = cur.search(pat);
61 if (close > -1) stream.backUp(cur.length - close);
62 else if (cur.match(/<\/?$/)) {
30 var cur = stream.current(), close = cur.search(pat);
31 if (close > -1) {
32 stream.backUp(cur.length - close);
33 } else if (cur.match(/<\/?$/)) {
63 34 stream.backUp(cur.length);
64 35 if (!stream.match(pat, false)) stream.match(cur);
65 36 }
66 37 return style;
67 38 }
68 function script(stream, state) {
69 if (stream.match(/^<\/\s*script\s*>/i, false)) {
70 state.token = html;
71 state.localState = state.localMode = null;
72 return null;
73 }
74 return maybeBackup(stream, /<\/\s*script\s*>/,
75 state.localMode.token(stream, state.localState));
39
40 var attrRegexpCache = {};
41 function getAttrRegexp(attr) {
42 var regexp = attrRegexpCache[attr];
43 if (regexp) return regexp;
44 return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
45 }
46
47 function getAttrValue(stream, attr) {
48 var pos = stream.pos, match;
49 while (pos >= 0 && stream.string.charAt(pos) !== "<") pos--;
50 if (pos < 0) return pos;
51 if (match = stream.string.slice(pos, stream.pos).match(getAttrRegexp(attr)))
52 return match[2];
53 return "";
76 54 }
77 function css(stream, state) {
78 if (stream.match(/^<\/\s*style\s*>/i, false)) {
79 state.token = html;
80 state.localState = state.localMode = null;
81 return null;
55
56 function getTagRegexp(tagName, anchored) {
57 return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
58 }
59
60 function addTags(from, to) {
61 for (var tag in from) {
62 var dest = to[tag] || (to[tag] = []);
63 var source = from[tag];
64 for (var i = source.length - 1; i >= 0; i--)
65 dest.unshift(source[i])
82 66 }
83 return maybeBackup(stream, /<\/\s*style\s*>/,
84 cssMode.token(stream, state.localState));
67 }
68
69 function findMatchingMode(tagInfo, stream) {
70 for (var i = 0; i < tagInfo.length; i++) {
71 var spec = tagInfo[i];
72 if (!spec[0] || spec[1].test(getAttrValue(stream, spec[0]))) return spec[2];
73 }
85 74 }
86 75
87 return {
88 startState: function() {
89 var state = htmlMode.startState();
90 return {token: html, localMode: null, localState: null, htmlState: state};
91 },
76 CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
77 var htmlMode = CodeMirror.getMode(config, {
78 name: "xml",
79 htmlMode: true,
80 multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
81 multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
82 });
92 83
93 copyState: function(state) {
94 if (state.localState)
95 var local = CodeMirror.copyState(state.localMode, state.localState);
96 return {token: state.token, localMode: state.localMode, localState: local,
97 htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
98 },
84 var tags = {};
85 var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
86 addTags(defaultTags, tags);
87 if (configTags) addTags(configTags, tags);
88 if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
89 tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
99 90
100 token: function(stream, state) {
101 return state.token(stream, state);
102 },
91 function html(stream, state) {
92 var tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase();
93 var tagInfo = tagName && tags.hasOwnProperty(tagName) && tags[tagName];
94
95 var style = htmlMode.token(stream, state.htmlState), modeSpec;
103 96
104 indent: function(state, textAfter) {
105 if (!state.localMode || /^\s*<\//.test(textAfter))
106 return htmlMode.indent(state.htmlState, textAfter);
107 else if (state.localMode.indent)
108 return state.localMode.indent(state.localState, textAfter);
109 else
110 return CodeMirror.Pass;
111 },
97 if (tagInfo && /\btag\b/.test(style) && stream.current() === ">" &&
98 (modeSpec = findMatchingMode(tagInfo, stream))) {
99 var mode = CodeMirror.getMode(config, modeSpec);
100 var endTagA = getTagRegexp(tagName, true), endTag = getTagRegexp(tagName, false);
101 state.token = function (stream, state) {
102 if (stream.match(endTagA, false)) {
103 state.token = html;
104 state.localState = state.localMode = null;
105 return null;
106 }
107 return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
108 };
109 state.localMode = mode;
110 state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
111 }
112 return style;
113 };
114
115 return {
116 startState: function () {
117 var state = htmlMode.startState();
118 return {token: html, localMode: null, localState: null, htmlState: state};
119 },
112 120
113 innerMode: function(state) {
114 return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
115 }
116 };
117 }, "xml", "javascript", "css");
121 copyState: function (state) {
122 var local;
123 if (state.localState) {
124 local = CodeMirror.copyState(state.localMode, state.localState);
125 }
126 return {token: state.token, localMode: state.localMode, localState: local,
127 htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
128 },
129
130 token: function (stream, state) {
131 return state.token(stream, state);
132 },
118 133
119 CodeMirror.defineMIME("text/html", "htmlmixed");
134 indent: function (state, textAfter) {
135 if (!state.localMode || /^\s*<\//.test(textAfter))
136 return htmlMode.indent(state.htmlState, textAfter);
137 else if (state.localMode.indent)
138 return state.localMode.indent(state.localState, textAfter);
139 else
140 return CodeMirror.Pass;
141 },
120 142
143 innerMode: function (state) {
144 return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
145 }
146 };
147 }, "xml", "javascript", "css");
148
149 CodeMirror.defineMIME("text/html", "htmlmixed");
121 150 });
@@ -74,7 +74,7 b" CodeMirror.defineMode('jade', function ("
74 74 res.javaScriptArguments = this.javaScriptArguments;
75 75 res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth;
76 76 res.isInterpolating = this.isInterpolating;
77 res.interpolationNesting = this.intpolationNesting;
77 res.interpolationNesting = this.interpolationNesting;
78 78
79 79 res.jsState = CodeMirror.copyState(jsMode, this.jsState);
80 80
@@ -167,7 +167,7 b" CodeMirror.defineMode('jade', function ("
167 167 if (state.interpolationNesting < 0) {
168 168 stream.next();
169 169 state.isInterpolating = false;
170 return 'puncutation';
170 return 'punctuation';
171 171 }
172 172 } else if (stream.peek() === '{') {
173 173 state.interpolationNesting++;
@@ -583,7 +583,7 b" CodeMirror.defineMode('jade', function ("
583 583 copyState: copyState,
584 584 token: nextToken
585 585 };
586 });
586 }, 'javascript', 'css', 'htmlmixed');
587 587
588 588 CodeMirror.defineMIME('text/x-jade', 'jade');
589 589
@@ -13,6 +13,11 b''
13 13 })(function(CodeMirror) {
14 14 "use strict";
15 15
16 function expressionAllowed(stream, state, backUp) {
17 return /^(?:operator|sof|keyword c|case|new|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
18 (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
19 }
20
16 21 CodeMirror.defineMode("javascript", function(config, parserConfig) {
17 22 var indentUnit = config.indentUnit;
18 23 var statementIndent = parserConfig.statementIndent;
@@ -30,13 +35,13 b' CodeMirror.defineMode("javascript", func'
30 35
31 36 var jsKeywords = {
32 37 "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
33 "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
38 "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
34 39 "var": kw("var"), "const": kw("var"), "let": kw("var"),
35 40 "function": kw("function"), "catch": kw("catch"),
36 41 "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
37 42 "in": operator, "typeof": operator, "instanceof": operator,
38 43 "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
39 "this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
44 "this": kw("this"), "class": kw("class"), "super": kw("atom"),
40 45 "yield": C, "export": kw("export"), "import": kw("import"), "extends": C
41 46 };
42 47
@@ -45,18 +50,23 b' CodeMirror.defineMode("javascript", func'
45 50 var type = {type: "variable", style: "variable-3"};
46 51 var tsKeywords = {
47 52 // object-like things
48 "interface": kw("interface"),
49 "extends": kw("extends"),
50 "constructor": kw("constructor"),
53 "interface": kw("class"),
54 "implements": C,
55 "namespace": C,
56 "module": kw("module"),
57 "enum": kw("module"),
51 58
52 59 // scope modifiers
53 "public": kw("public"),
54 "private": kw("private"),
55 "protected": kw("protected"),
56 "static": kw("static"),
60 "public": kw("modifier"),
61 "private": kw("modifier"),
62 "protected": kw("modifier"),
63 "abstract": kw("modifier"),
64
65 // operators
66 "as": operator,
57 67
58 68 // types
59 "string": type, "number": type, "bool": type, "any": type
69 "string": type, "number": type, "boolean": type, "any": type
60 70 };
61 71
62 72 for (var attr in tsKeywords) {
@@ -105,6 +115,12 b' CodeMirror.defineMode("javascript", func'
105 115 } else if (ch == "0" && stream.eat(/x/i)) {
106 116 stream.eatWhile(/[\da-f]/i);
107 117 return ret("number", "number");
118 } else if (ch == "0" && stream.eat(/o/i)) {
119 stream.eatWhile(/[0-7]/i);
120 return ret("number", "number");
121 } else if (ch == "0" && stream.eat(/b/i)) {
122 stream.eatWhile(/[01]/i);
123 return ret("number", "number");
108 124 } else if (/\d/.test(ch)) {
109 125 stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
110 126 return ret("number", "number");
@@ -115,8 +131,7 b' CodeMirror.defineMode("javascript", func'
115 131 } else if (stream.eat("/")) {
116 132 stream.skipToEnd();
117 133 return ret("comment", "comment");
118 } else if (state.lastType == "operator" || state.lastType == "keyword c" ||
119 state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
134 } else if (expressionAllowed(stream, state, 1)) {
120 135 readRegexp(stream);
121 136 stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
122 137 return ret("regexp", "string-2");
@@ -275,8 +290,8 b' CodeMirror.defineMode("javascript", func'
275 290 return false;
276 291 }
277 292 var state = cx.state;
293 cx.marked = "def";
278 294 if (state.context) {
279 cx.marked = "def";
280 295 if (inList(state.localVars)) return;
281 296 state.localVars = {name: varname, next: state.localVars};
282 297 } else {
@@ -347,10 +362,10 b' CodeMirror.defineMode("javascript", func'
347 362 if (type == "default") return cont(expect(":"));
348 363 if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
349 364 statement, poplex, popcontext);
350 if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
351 365 if (type == "class") return cont(pushlex("form"), className, poplex);
352 if (type == "export") return cont(pushlex("form"), afterExport, poplex);
353 if (type == "import") return cont(pushlex("form"), afterImport, poplex);
366 if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
367 if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
368 if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
354 369 return pass(pushlex("stat"), expression, expect(";"), poplex);
355 370 }
356 371 function expression(type) {
@@ -374,7 +389,8 b' CodeMirror.defineMode("javascript", func'
374 389 if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
375 390 if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
376 391 if (type == "{") return contCommasep(objprop, "}", null, maybeop);
377 if (type == "quasi") { return pass(quasi, maybeop); }
392 if (type == "quasi") return pass(quasi, maybeop);
393 if (type == "new") return cont(maybeTarget(noComma));
378 394 return cont();
379 395 }
380 396 function maybeexpression(type) {
@@ -425,6 +441,18 b' CodeMirror.defineMode("javascript", func'
425 441 findFatArrow(cx.stream, cx.state);
426 442 return pass(type == "{" ? statement : expressionNoComma);
427 443 }
444 function maybeTarget(noComma) {
445 return function(type) {
446 if (type == ".") return cont(noComma ? targetNoComma : target);
447 else return pass(noComma ? expressionNoComma : expression);
448 };
449 }
450 function target(_, value) {
451 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
452 }
453 function targetNoComma(_, value) {
454 if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
455 }
428 456 function maybelabel(type) {
429 457 if (type == ":") return cont(poplex, statement);
430 458 return pass(maybeoperatorComma, expect(";"), poplex);
@@ -442,8 +470,12 b' CodeMirror.defineMode("javascript", func'
442 470 return cont(afterprop);
443 471 } else if (type == "jsonld-keyword") {
444 472 return cont(afterprop);
473 } else if (type == "modifier") {
474 return cont(objprop)
445 475 } else if (type == "[") {
446 476 return cont(expression, expect("]"), afterprop);
477 } else if (type == "spread") {
478 return cont(expression);
447 479 }
448 480 }
449 481 function getterSetter(type) {
@@ -492,7 +524,9 b' CodeMirror.defineMode("javascript", func'
492 524 return pass(pattern, maybetype, maybeAssign, vardefCont);
493 525 }
494 526 function pattern(type, value) {
527 if (type == "modifier") return cont(pattern)
495 528 if (type == "variable") { register(value); return cont(); }
529 if (type == "spread") return cont(pattern);
496 530 if (type == "[") return contCommasep(pattern, "]");
497 531 if (type == "{") return contCommasep(proppattern, "}");
498 532 }
@@ -502,6 +536,8 b' CodeMirror.defineMode("javascript", func'
502 536 return cont(maybeAssign);
503 537 }
504 538 if (type == "variable") cx.marked = "property";
539 if (type == "spread") return cont(pattern);
540 if (type == "}") return pass();
505 541 return cont(expect(":"), pattern, maybeAssign);
506 542 }
507 543 function maybeAssign(_type, value) {
@@ -572,10 +608,6 b' CodeMirror.defineMode("javascript", func'
572 608 cx.marked = "property";
573 609 return cont();
574 610 }
575 function afterModule(type, value) {
576 if (type == "string") return cont(statement);
577 if (type == "variable") { register(value); return cont(maybeFrom); }
578 }
579 611 function afterExport(_type, value) {
580 612 if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
581 613 if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
@@ -628,7 +660,7 b' CodeMirror.defineMode("javascript", func'
628 660 lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
629 661 localVars: parserConfig.localVars,
630 662 context: parserConfig.localVars && {vars: parserConfig.localVars},
631 indented: 0
663 indented: basecolumn || 0
632 664 };
633 665 if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
634 666 state.globalVars = parserConfig.globalVars;
@@ -684,7 +716,13 b' CodeMirror.defineMode("javascript", func'
684 716
685 717 helperType: jsonMode ? "json" : "javascript",
686 718 jsonldMode: jsonldMode,
687 jsonMode: jsonMode
719 jsonMode: jsonMode,
720
721 expressionAllowed: expressionAllowed,
722 skipExpression: function(state) {
723 var top = state.cc[state.cc.length - 1]
724 if (top == expression || top == expressionNoComma) state.cc.pop()
725 }
688 726 };
689 727 });
690 728
@@ -18,35 +18,34 b' CodeMirror.defineMode("julia", function('
18 18 return new RegExp("^((" + words.join(")|(") + "))\\b");
19 19 }
20 20
21 var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b/;
21 var operators = parserConf.operators || /^\.?[|&^\\%*+\-<>!=\/]=?|\?|~|:|\$|\.[<>]|<<=?|>>>?=?|\.[<>=]=|->?|\/\/|\bin\b(?!\()|[\u2208\u2209](?!\()/;
22 22 var delimiters = parserConf.delimiters || /^[;,()[\]{}]/;
23 var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
23 var identifiers = parserConf.identifiers || /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
24 24 var blockOpeners = ["begin", "function", "type", "immutable", "let", "macro", "for", "while", "quote", "if", "else", "elseif", "try", "finally", "catch", "do"];
25 25 var blockClosers = ["end", "else", "elseif", "catch", "finally"];
26 var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype', 'ccall'];
27 var builtinList = ['true', 'false', 'enumerate', 'open', 'close', 'nothing', 'NaN', 'Inf', 'print', 'println', 'Int', 'Int8', 'Uint8', 'Int16', 'Uint16', 'Int32', 'Uint32', 'Int64', 'Uint64', 'Int128', 'Uint128', 'Bool', 'Char', 'Float16', 'Float32', 'Float64', 'Array', 'Vector', 'Matrix', 'String', 'UTF8String', 'ASCIIString', 'error', 'warn', 'info', '@printf'];
26 var keywordList = ['if', 'else', 'elseif', 'while', 'for', 'begin', 'let', 'end', 'do', 'try', 'catch', 'finally', 'return', 'break', 'continue', 'global', 'local', 'const', 'export', 'import', 'importall', 'using', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable', 'quote', 'typealias', 'abstract', 'bitstype'];
27 var builtinList = ['true', 'false', 'nothing', 'NaN', 'Inf'];
28 28
29 29 //var stringPrefixes = new RegExp("^[br]?('|\")")
30 var stringPrefixes = /^(`|'|"{3}|([br]?"))/;
30 var stringPrefixes = /^(`|'|"{3}|([brv]?"))/;
31 31 var keywords = wordRegexp(keywordList);
32 32 var builtins = wordRegexp(builtinList);
33 33 var openers = wordRegexp(blockOpeners);
34 34 var closers = wordRegexp(blockClosers);
35 35 var macro = /^@[_A-Za-z][_A-Za-z0-9]*/;
36 var symbol = /^:[_A-Za-z][_A-Za-z0-9]*/;
36 var symbol = /^:[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*!*/;
37 var typeAnnotation = /^::[^.,;"{()=$\s]+({[^}]*}+)*/;
37 38
38 function in_array(state) {
39 var ch = cur_scope(state);
40 if(ch=="[" || ch=="{") {
39 function inArray(state) {
40 var ch = currentScope(state);
41 if (ch == '[') {
41 42 return true;
42 43 }
43 else {
44 return false;
45 }
44 return false;
46 45 }
47 46
48 function cur_scope(state) {
49 if(state.scopes.length==0) {
47 function currentScope(state) {
48 if (state.scopes.length == 0) {
50 49 return null;
51 50 }
52 51 return state.scopes[state.scopes.length - 1];
@@ -54,20 +53,34 b' CodeMirror.defineMode("julia", function('
54 53
55 54 // tokenizers
56 55 function tokenBase(stream, state) {
56 //Handle multiline comments
57 if (stream.match(/^#=\s*/)) {
58 state.scopes.push('#=');
59 }
60 if (currentScope(state) == '#=' && stream.match(/^=#/)) {
61 state.scopes.pop();
62 return 'comment';
63 }
64 if (state.scopes.indexOf('#=') >= 0) {
65 if (!stream.match(/.*?(?=(#=|=#))/)) {
66 stream.skipToEnd();
67 }
68 return 'comment';
69 }
70
57 71 // Handle scope changes
58 var leaving_expr = state.leaving_expr;
59 if(stream.sol()) {
60 leaving_expr = false;
72 var leavingExpr = state.leavingExpr;
73 if (stream.sol()) {
74 leavingExpr = false;
61 75 }
62 state.leaving_expr = false;
63 if(leaving_expr) {
64 if(stream.match(/^'+/)) {
76 state.leavingExpr = false;
77 if (leavingExpr) {
78 if (stream.match(/^'+/)) {
65 79 return 'operator';
66 80 }
67
68 81 }
69 82
70 if(stream.match(/^\.{2,3}/)) {
83 if (stream.match(/^\.{2,3}/)) {
71 84 return 'operator';
72 85 }
73 86
@@ -76,56 +89,51 b' CodeMirror.defineMode("julia", function('
76 89 }
77 90
78 91 var ch = stream.peek();
79 // Handle Comments
92
93 // Handle single line comments
80 94 if (ch === '#') {
81 stream.skipToEnd();
82 return 'comment';
83 }
84 if(ch==='[') {
85 state.scopes.push("[");
95 stream.skipToEnd();
96 return 'comment';
86 97 }
87 98
88 if(ch==='{') {
89 state.scopes.push("{");
99 if (ch === '[') {
100 state.scopes.push('[');
90 101 }
91 102
92 var scope=cur_scope(state);
103 var scope = currentScope(state);
93 104
94 if(scope==='[' && ch===']') {
105 if (scope == '[' && ch === ']') {
95 106 state.scopes.pop();
96 state.leaving_expr=true;
107 state.leavingExpr = true;
97 108 }
98 109
99 if(scope==='{' && ch==='}') {
110 if (scope == '(' && ch === ')') {
100 111 state.scopes.pop();
101 state.leaving_expr=true;
102 }
103
104 if(ch===')') {
105 state.leaving_expr = true;
112 state.leavingExpr = true;
106 113 }
107 114
108 115 var match;
109 if(!in_array(state) && (match=stream.match(openers, false))) {
116 if (!inArray(state) && (match=stream.match(openers, false))) {
110 117 state.scopes.push(match);
111 118 }
112 119
113 if(!in_array(state) && stream.match(closers, false)) {
120 if (!inArray(state) && stream.match(closers, false)) {
114 121 state.scopes.pop();
115 122 }
116 123
117 if(in_array(state)) {
118 if(stream.match(/^end/)) {
124 if (inArray(state)) {
125 if (state.lastToken == 'end' && stream.match(/^:/)) {
126 return 'operator';
127 }
128 if (stream.match(/^end/)) {
119 129 return 'number';
120 130 }
121
122 131 }
123 132
124 if(stream.match(/^=>/)) {
133 if (stream.match(/^=>/)) {
125 134 return 'operator';
126 135 }
127 136
128
129 137 // Handle Number Literals
130 138 if (stream.match(/^[0-9\.]/, false)) {
131 139 var imMatcher = RegExp(/^im\b/);
@@ -134,10 +142,11 b' CodeMirror.defineMode("julia", function('
134 142 if (stream.match(/^\d*\.(?!\.)\d+([ef][\+\-]?\d+)?/i)) { floatLiteral = true; }
135 143 if (stream.match(/^\d+\.(?!\.)\d*/)) { floatLiteral = true; }
136 144 if (stream.match(/^\.\d+/)) { floatLiteral = true; }
145 if (stream.match(/^0x\.[0-9a-f]+p[\+\-]?\d+/i)) { floatLiteral = true; }
137 146 if (floatLiteral) {
138 147 // Float literals may be "imaginary"
139 148 stream.match(imMatcher);
140 state.leaving_expr = true;
149 state.leavingExpr = true;
141 150 return 'number';
142 151 }
143 152 // Integers
@@ -157,18 +166,27 b' CodeMirror.defineMode("julia", function('
157 166 if (intLiteral) {
158 167 // Integer literals may be "long"
159 168 stream.match(imMatcher);
160 state.leaving_expr = true;
169 state.leavingExpr = true;
161 170 return 'number';
162 171 }
163 172 }
164 173
165 if(stream.match(/^(::)|(<:)/)) {
174 if (stream.match(/^<:/)) {
166 175 return 'operator';
167 176 }
168 177
178 if (stream.match(typeAnnotation)) {
179 return 'builtin';
180 }
181
169 182 // Handle symbols
170 if(!leaving_expr && stream.match(symbol)) {
171 return 'string';
183 if (!leavingExpr && stream.match(symbol) || stream.match(/:\./)) {
184 return 'builtin';
185 }
186
187 // Handle parametric types
188 if (stream.match(/^{[^}]*}(?=\()/)) {
189 return 'builtin';
172 190 }
173 191
174 192 // Handle operators and Delimiters
@@ -176,7 +194,6 b' CodeMirror.defineMode("julia", function('
176 194 return 'operator';
177 195 }
178 196
179
180 197 // Handle Strings
181 198 if (stream.match(stringPrefixes)) {
182 199 state.tokenize = tokenStringFactory(stream.current());
@@ -187,7 +204,6 b' CodeMirror.defineMode("julia", function('
187 204 return 'meta';
188 205 }
189 206
190
191 207 if (stream.match(delimiters)) {
192 208 return null;
193 209 }
@@ -200,21 +216,74 b' CodeMirror.defineMode("julia", function('
200 216 return 'builtin';
201 217 }
202 218
219 var isDefinition = state.isDefinition ||
220 state.lastToken == 'function' ||
221 state.lastToken == 'macro' ||
222 state.lastToken == 'type' ||
223 state.lastToken == 'immutable';
203 224
204 225 if (stream.match(identifiers)) {
205 state.leaving_expr=true;
226 if (isDefinition) {
227 if (stream.peek() === '.') {
228 state.isDefinition = true;
229 return 'variable';
230 }
231 state.isDefinition = false;
232 return 'def';
233 }
234 if (stream.match(/^({[^}]*})*\(/, false)) {
235 return callOrDef(stream, state);
236 }
237 state.leavingExpr = true;
206 238 return 'variable';
207 239 }
240
208 241 // Handle non-detected items
209 242 stream.next();
210 243 return ERRORCLASS;
211 244 }
212 245
246 function callOrDef(stream, state) {
247 var match = stream.match(/^(\(\s*)/);
248 if (match) {
249 if (state.firstParenPos < 0)
250 state.firstParenPos = state.scopes.length;
251 state.scopes.push('(');
252 state.charsAdvanced += match[1].length;
253 }
254 if (currentScope(state) == '(' && stream.match(/^\)/)) {
255 state.scopes.pop();
256 state.charsAdvanced += 1;
257 if (state.scopes.length <= state.firstParenPos) {
258 var isDefinition = stream.match(/^\s*?=(?!=)/, false);
259 stream.backUp(state.charsAdvanced);
260 state.firstParenPos = -1;
261 state.charsAdvanced = 0;
262 if (isDefinition)
263 return 'def';
264 return 'builtin';
265 }
266 }
267 // Unfortunately javascript does not support multiline strings, so we have
268 // to undo anything done upto here if a function call or definition splits
269 // over two or more lines.
270 if (stream.match(/^$/g, false)) {
271 stream.backUp(state.charsAdvanced);
272 while (state.scopes.length > state.firstParenPos + 1)
273 state.scopes.pop();
274 state.firstParenPos = -1;
275 state.charsAdvanced = 0;
276 return 'builtin';
277 }
278 state.charsAdvanced += stream.match(/^([^()]*)/)[1].length;
279 return callOrDef(stream, state);
280 }
281
213 282 function tokenStringFactory(delimiter) {
214 while ('rub'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
283 while ('bruv'.indexOf(delimiter.charAt(0).toLowerCase()) >= 0) {
215 284 delimiter = delimiter.substr(1);
216 285 }
217 var singleline = delimiter.length == 1;
286 var singleline = delimiter == "'";
218 287 var OUTCLASS = 'string';
219 288
220 289 function tokenString(stream, state) {
@@ -245,45 +314,41 b' CodeMirror.defineMode("julia", function('
245 314 return tokenString;
246 315 }
247 316
248 function tokenLexer(stream, state) {
249 var style = state.tokenize(stream, state);
250 var current = stream.current();
251
252 // Handle '.' connected identifiers
253 if (current === '.') {
254 style = stream.match(identifiers, false) ? null : ERRORCLASS;
255 if (style === null && state.lastStyle === 'meta') {
256 // Apply 'meta' style to '.' connected identifiers when
257 // appropriate.
258 style = 'meta';
259 }
260 return style;
261 }
262
263 return style;
264 }
265
266 317 var external = {
267 318 startState: function() {
268 319 return {
269 320 tokenize: tokenBase,
270 321 scopes: [],
271 leaving_expr: false
322 lastToken: null,
323 leavingExpr: false,
324 isDefinition: false,
325 charsAdvanced: 0,
326 firstParenPos: -1
272 327 };
273 328 },
274 329
275 330 token: function(stream, state) {
276 var style = tokenLexer(stream, state);
277 state.lastStyle = style;
331 var style = state.tokenize(stream, state);
332 var current = stream.current();
333
334 if (current && style) {
335 state.lastToken = current;
336 }
337
338 // Handle '.' connected identifiers
339 if (current === '.') {
340 style = stream.match(identifiers, false) || stream.match(macro, false) ||
341 stream.match(/\(/, false) ? 'operator' : ERRORCLASS;
342 }
278 343 return style;
279 344 },
280 345
281 346 indent: function(state, textAfter) {
282 347 var delta = 0;
283 if(textAfter=="end" || textAfter=="]" || textAfter=="}" || textAfter=="else" || textAfter=="elseif" || textAfter=="catch" || textAfter=="finally") {
348 if (textAfter == "end" || textAfter == "]" || textAfter == "}" || textAfter == "else" || textAfter == "elseif" || textAfter == "catch" || textAfter == "finally") {
284 349 delta = -1;
285 350 }
286 return (state.scopes.length + delta) * 4;
351 return (state.scopes.length + delta) * _conf.indentUnit;
287 352 },
288 353
289 354 lineComment: "#",
@@ -39,8 +39,10 b' CodeMirror.defineMode("markdown", functi'
39 39 if (modeCfg.underscoresBreakWords === undefined)
40 40 modeCfg.underscoresBreakWords = true;
41 41
42 // Turn on fenced code blocks? ("```" to start/end)
43 if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
42 // Use `fencedCodeBlocks` to configure fenced code blocks. false to
43 // disable, string to specify a precise regexp that the fence should
44 // match, and true to allow three or more backticks or tildes (as
45 // per CommonMark).
44 46
45 47 // Turn on task lists? ("- [ ] " and "- [x] ")
46 48 if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
@@ -49,32 +51,46 b' CodeMirror.defineMode("markdown", functi'
49 51 if (modeCfg.strikethrough === undefined)
50 52 modeCfg.strikethrough = false;
51 53
54 // Allow token types to be overridden by user-provided token types.
55 if (modeCfg.tokenTypeOverrides === undefined)
56 modeCfg.tokenTypeOverrides = {};
57
52 58 var codeDepth = 0;
53 59
54 var header = 'header'
55 , code = 'comment'
56 , quote = 'quote'
57 , list1 = 'variable-2'
58 , list2 = 'variable-3'
59 , list3 = 'keyword'
60 , hr = 'hr'
61 , image = 'tag'
62 , formatting = 'formatting'
63 , linkinline = 'link'
64 , linkemail = 'link'
65 , linktext = 'link'
66 , linkhref = 'string'
67 , em = 'em'
68 , strong = 'strong'
69 , strikethrough = 'strikethrough';
60 var tokenTypes = {
61 header: "header",
62 code: "comment",
63 quote: "quote",
64 list1: "variable-2",
65 list2: "variable-3",
66 list3: "keyword",
67 hr: "hr",
68 image: "tag",
69 formatting: "formatting",
70 linkInline: "link",
71 linkEmail: "link",
72 linkText: "link",
73 linkHref: "string",
74 em: "em",
75 strong: "strong",
76 strikethrough: "strikethrough"
77 };
78
79 for (var tokenType in tokenTypes) {
80 if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
81 tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
82 }
83 }
70 84
71 85 var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
72 86 , ulRE = /^[*\-+]\s+/
73 87 , olRE = /^[0-9]+([.)])\s+/
74 88 , taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
75 , atxHeaderRE = /^(#+)(?: |$)/
89 , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
76 90 , setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/
77 , textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
91 , textRE = /^[^#!\[\]*_\\<>` "'(~]+/
92 , fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) +
93 ")[ \\t]*([\\w+#]*)");
78 94
79 95 function switchInline(stream, state, f) {
80 96 state.f = state.inline = f;
@@ -86,6 +102,9 b' CodeMirror.defineMode("markdown", functi'
86 102 return f(stream, state);
87 103 }
88 104
105 function lineIsEmpty(line) {
106 return !line || !/\S/.test(line.string)
107 }
89 108
90 109 // Blocks
91 110
@@ -110,7 +129,8 b' CodeMirror.defineMode("markdown", functi'
110 129 state.trailingSpace = 0;
111 130 state.trailingSpaceNewLine = false;
112 131 // Mark this line as blank
113 state.thisLineHasContent = false;
132 state.prevLine = state.thisLine
133 state.thisLine = null
114 134 return null;
115 135 }
116 136
@@ -141,10 +161,10 b' CodeMirror.defineMode("markdown", functi'
141 161 var match = null;
142 162 if (state.indentationDiff >= 4) {
143 163 stream.skipToEnd();
144 if (prevLineIsIndentedCode || !state.prevLineHasContent) {
164 if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) {
145 165 state.indentation -= 4;
146 166 state.indentedCode = true;
147 return code;
167 return tokenTypes.code;
148 168 } else {
149 169 return null;
150 170 }
@@ -155,7 +175,8 b' CodeMirror.defineMode("markdown", functi'
155 175 if (modeCfg.highlightFormatting) state.formatting = "header";
156 176 state.f = state.inline;
157 177 return getType(state);
158 } else if (state.prevLineHasContent && !state.quote && !prevLineIsList && !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
178 } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList &&
179 !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) {
159 180 state.header = match[0].charAt(0) == '=' ? 1 : 2;
160 181 if (modeCfg.highlightFormatting) state.formatting = "header";
161 182 state.f = state.inline;
@@ -169,8 +190,8 b' CodeMirror.defineMode("markdown", functi'
169 190 return switchInline(stream, state, footnoteLink);
170 191 } else if (stream.match(hrRE, true)) {
171 192 state.hr = true;
172 return hr;
173 } else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
193 return tokenTypes.hr;
194 } else if ((lineIsEmpty(state.prevLine) || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
174 195 var listType = null;
175 196 if (stream.match(ulRE, true)) {
176 197 listType = 'ul';
@@ -178,7 +199,7 b' CodeMirror.defineMode("markdown", functi'
178 199 stream.match(olRE, true);
179 200 listType = 'ol';
180 201 }
181 state.indentation += 4;
202 state.indentation = stream.column() + stream.current().length;
182 203 state.list = true;
183 204 state.listDepth++;
184 205 if (modeCfg.taskLists && stream.match(taskListRE, false)) {
@@ -187,9 +208,10 b' CodeMirror.defineMode("markdown", functi'
187 208 state.f = state.inline;
188 209 if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
189 210 return getType(state);
190 } else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
211 } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) {
212 state.fencedChars = match[1]
191 213 // try switching mode
192 state.localMode = getMode(RegExp.$1);
214 state.localMode = getMode(match[2]);
193 215 if (state.localMode) state.localState = state.localMode.startState();
194 216 state.f = state.block = local;
195 217 if (modeCfg.highlightFormatting) state.formatting = "code-block";
@@ -202,7 +224,8 b' CodeMirror.defineMode("markdown", functi'
202 224
203 225 function htmlBlock(stream, state) {
204 226 var style = htmlMode.token(stream, state.htmlState);
205 if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
227 if ((htmlFound && state.htmlState.tagStart === null &&
228 (!state.htmlState.context && state.htmlState.tokenize.isInText)) ||
206 229 (state.md_inside && stream.current().indexOf(">") > -1)) {
207 230 state.f = inlineNormal;
208 231 state.block = blockNormal;
@@ -212,7 +235,7 b' CodeMirror.defineMode("markdown", functi'
212 235 }
213 236
214 237 function local(stream, state) {
215 if (stream.sol() && stream.match("```", false)) {
238 if (state.fencedChars && stream.match(state.fencedChars, false)) {
216 239 state.localMode = state.localState = null;
217 240 state.f = state.block = leavingLocal;
218 241 return null;
@@ -220,14 +243,15 b' CodeMirror.defineMode("markdown", functi'
220 243 return state.localMode.token(stream, state.localState);
221 244 } else {
222 245 stream.skipToEnd();
223 return code;
246 return tokenTypes.code;
224 247 }
225 248 }
226 249
227 250 function leavingLocal(stream, state) {
228 stream.match("```");
251 stream.match(state.fencedChars);
229 252 state.block = blockNormal;
230 253 state.f = inlineNormal;
254 state.fencedChars = null;
231 255 if (modeCfg.highlightFormatting) state.formatting = "code-block";
232 256 state.code = true;
233 257 var returnType = getType(state);
@@ -240,22 +264,22 b' CodeMirror.defineMode("markdown", functi'
240 264 var styles = [];
241 265
242 266 if (state.formatting) {
243 styles.push(formatting);
267 styles.push(tokenTypes.formatting);
244 268
245 269 if (typeof state.formatting === "string") state.formatting = [state.formatting];
246 270
247 271 for (var i = 0; i < state.formatting.length; i++) {
248 styles.push(formatting + "-" + state.formatting[i]);
272 styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
249 273
250 274 if (state.formatting[i] === "header") {
251 styles.push(formatting + "-" + state.formatting[i] + "-" + state.header);
275 styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
252 276 }
253 277
254 278 // Add `formatting-quote` and `formatting-quote-#` for blockquotes
255 279 // Add `error` instead if the maximum blockquote nesting depth is passed
256 280 if (state.formatting[i] === "quote") {
257 281 if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
258 styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
282 styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
259 283 } else {
260 284 styles.push("error");
261 285 }
@@ -273,38 +297,36 b' CodeMirror.defineMode("markdown", functi'
273 297 }
274 298
275 299 if (state.linkHref) {
276 styles.push(linkhref, "url");
300 styles.push(tokenTypes.linkHref, "url");
277 301 } else { // Only apply inline styles to non-url text
278 if (state.strong) { styles.push(strong); }
279 if (state.em) { styles.push(em); }
280 if (state.strikethrough) { styles.push(strikethrough); }
281
282 if (state.linkText) { styles.push(linktext); }
283
284 if (state.code) { styles.push(code); }
302 if (state.strong) { styles.push(tokenTypes.strong); }
303 if (state.em) { styles.push(tokenTypes.em); }
304 if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
305 if (state.linkText) { styles.push(tokenTypes.linkText); }
306 if (state.code) { styles.push(tokenTypes.code); }
285 307 }
286 308
287 if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
309 if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
288 310
289 311 if (state.quote) {
290 styles.push(quote);
312 styles.push(tokenTypes.quote);
291 313
292 314 // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
293 315 if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
294 styles.push(quote + "-" + state.quote);
316 styles.push(tokenTypes.quote + "-" + state.quote);
295 317 } else {
296 styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
318 styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
297 319 }
298 320 }
299 321
300 322 if (state.list !== false) {
301 323 var listMod = (state.listDepth - 1) % 3;
302 324 if (!listMod) {
303 styles.push(list1);
325 styles.push(tokenTypes.list1);
304 326 } else if (listMod === 1) {
305 styles.push(list2);
327 styles.push(tokenTypes.list2);
306 328 } else {
307 styles.push(list3);
329 styles.push(tokenTypes.list3);
308 330 }
309 331 }
310 332
@@ -360,7 +382,8 b' CodeMirror.defineMode("markdown", functi'
360 382 stream.next();
361 383 if (modeCfg.highlightFormatting) {
362 384 var type = getType(state);
363 return type ? type + " formatting-escape" : "formatting-escape";
385 var formattingEscape = tokenTypes.formatting + "-escape";
386 return type ? type + " " + formattingEscape : formattingEscape;
364 387 }
365 388 }
366 389
@@ -374,7 +397,7 b' CodeMirror.defineMode("markdown", functi'
374 397 matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
375 398 var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
376 399 if (stream.match(new RegExp(regex), true)) {
377 return linkhref;
400 return tokenTypes.linkHref;
378 401 }
379 402 }
380 403
@@ -405,7 +428,7 b' CodeMirror.defineMode("markdown", functi'
405 428 if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
406 429 stream.match(/\[[^\]]*\]/);
407 430 state.inline = state.f = linkHref;
408 return image;
431 return tokenTypes.image;
409 432 }
410 433
411 434 if (ch === '[' && stream.match(/.*\](\(.*\)| ?\[.*\])/, false)) {
@@ -431,7 +454,7 b' CodeMirror.defineMode("markdown", functi'
431 454 } else {
432 455 type = "";
433 456 }
434 return type + linkinline;
457 return type + tokenTypes.linkInline;
435 458 }
436 459
437 460 if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
@@ -443,15 +466,14 b' CodeMirror.defineMode("markdown", functi'
443 466 } else {
444 467 type = "";
445 468 }
446 return type + linkemail;
469 return type + tokenTypes.linkEmail;
447 470 }
448 471
449 if (ch === '<' && stream.match(/^\w/, false)) {
450 if (stream.string.indexOf(">") != -1) {
451 var atts = stream.string.substring(1,stream.string.indexOf(">"));
452 if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
453 state.md_inside = true;
454 }
472 if (ch === '<' && stream.match(/^(!--|\w)/, false)) {
473 var end = stream.string.indexOf(">", stream.pos);
474 if (end != -1) {
475 var atts = stream.string.substring(stream.start, end);
476 if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
455 477 }
456 478 stream.backUp(1);
457 479 state.htmlState = CodeMirror.startState(htmlMode);
@@ -553,12 +575,12 b' CodeMirror.defineMode("markdown", functi'
553 575 } else {
554 576 type = "";
555 577 }
556 return type + linkinline;
578 return type + tokenTypes.linkInline;
557 579 }
558 580
559 581 stream.match(/^[^>]+/, true);
560 582
561 return linkinline;
583 return tokenTypes.linkInline;
562 584 }
563 585
564 586 function linkHref(stream, state) {
@@ -598,7 +620,7 b' CodeMirror.defineMode("markdown", functi'
598 620 }
599 621
600 622 function footnoteLink(stream, state) {
601 if (stream.match(/^[^\]]*\]:/, false)) {
623 if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
602 624 state.f = footnoteLinkInside;
603 625 stream.next(); // Consume [
604 626 if (modeCfg.highlightFormatting) state.formatting = "link";
@@ -617,9 +639,9 b' CodeMirror.defineMode("markdown", functi'
617 639 return returnType;
618 640 }
619 641
620 stream.match(/^[^\]]+/, true);
642 stream.match(/^([^\]\\]|\\.)+/, true);
621 643
622 return linktext;
644 return tokenTypes.linkText;
623 645 }
624 646
625 647 function footnoteUrl(stream, state) {
@@ -636,7 +658,7 b' CodeMirror.defineMode("markdown", functi'
636 658 stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
637 659 }
638 660 state.f = state.inline = inlineNormal;
639 return linkhref + " url";
661 return tokenTypes.linkHref + " url";
640 662 }
641 663
642 664 var savedInlineRE = [];
@@ -656,8 +678,8 b' CodeMirror.defineMode("markdown", functi'
656 678 return {
657 679 f: blockNormal,
658 680
659 prevLineHasContent: false,
660 thisLineHasContent: false,
681 prevLine: null,
682 thisLine: null,
661 683
662 684 block: blockNormal,
663 685 htmlState: null,
@@ -680,7 +702,8 b' CodeMirror.defineMode("markdown", functi'
680 702 quote: 0,
681 703 trailingSpace: 0,
682 704 trailingSpaceNewLine: false,
683 strikethrough: false
705 strikethrough: false,
706 fencedChars: null
684 707 };
685 708 },
686 709
@@ -688,8 +711,8 b' CodeMirror.defineMode("markdown", functi'
688 711 return {
689 712 f: s.f,
690 713
691 prevLineHasContent: s.prevLineHasContent,
692 thisLineHasContent: s.thisLineHasContent,
714 prevLine: s.prevLine,
715 thisLine: s.thisLine,
693 716
694 717 block: s.block,
695 718 htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
@@ -702,6 +725,7 b' CodeMirror.defineMode("markdown", functi'
702 725 text: s.text,
703 726 formatting: false,
704 727 linkTitle: s.linkTitle,
728 code: s.code,
705 729 em: s.em,
706 730 strong: s.strong,
707 731 strikethrough: s.strikethrough,
@@ -714,7 +738,8 b' CodeMirror.defineMode("markdown", functi'
714 738 indentedCode: s.indentedCode,
715 739 trailingSpace: s.trailingSpace,
716 740 trailingSpaceNewLine: s.trailingSpaceNewLine,
717 md_inside: s.md_inside
741 md_inside: s.md_inside,
742 fencedChars: s.fencedChars
718 743 };
719 744 },
720 745
@@ -723,28 +748,25 b' CodeMirror.defineMode("markdown", functi'
723 748 // Reset state.formatting
724 749 state.formatting = false;
725 750
726 if (stream.sol()) {
727 var forceBlankLine = !!state.header || state.hr;
751 if (stream != state.thisLine) {
752 var forceBlankLine = state.header || state.hr;
728 753
729 754 // Reset state.header and state.hr
730 755 state.header = 0;
731 756 state.hr = false;
732 757
733 758 if (stream.match(/^\s*$/, true) || forceBlankLine) {
734 state.prevLineHasContent = false;
735 759 blankLine(state);
736 return forceBlankLine ? this.token(stream, state) : null;
737 } else {
738 state.prevLineHasContent = state.thisLineHasContent;
739 state.thisLineHasContent = true;
760 if (!forceBlankLine) return null
761 state.prevLine = null
740 762 }
741 763
764 state.prevLine = state.thisLine
765 state.thisLine = stream
766
742 767 // Reset state.taskList
743 768 state.taskList = false;
744 769
745 // Reset state.code
746 state.code = false;
747
748 770 // Reset state.trailingSpace
749 771 state.trailingSpace = 0;
750 772 state.trailingSpaceNewLine = false;
@@ -14,18 +14,22 b''
14 14 CodeMirror.modeInfo = [
15 15 {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
16 16 {name: "PGP", mimes: ["application/pgp", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["pgp"]},
17 {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn, asn1"]},
17 {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
18 18 {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
19 {name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
19 20 {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},
20 21 {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
21 22 {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
22 23 {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
23 24 {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj"]},
25 {name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
26 {name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
24 27 {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
25 28 {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
26 29 {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
27 30 {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
28 31 {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
32 {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
29 33 {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
30 34 {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
31 35 {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
@@ -53,6 +57,7 b''
53 57 {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy"]},
54 58 {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
55 59 {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
60 {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
56 61 {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
57 62 {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
58 63 {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
@@ -66,9 +71,10 b''
66 71 mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
67 72 {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
68 73 {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
74 {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
69 75 {name: "Jinja2", mime: "null", mode: "jinja2"},
70 76 {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
71 {name: "Kotlin", mime: "text/x-kotlin", mode: "kotlin", ext: ["kt"]},
77 {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
72 78 {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
73 79 {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
74 80 {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
@@ -81,10 +87,12 b''
81 87 {name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
82 88 {name: "MySQL", mime: "text/x-mysql", mode: "sql"},
83 89 {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
90 {name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
84 91 {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
85 92 {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"]},
86 93 {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
87 94 {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
95 {name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
88 96 {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
89 97 {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
90 98 {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
@@ -106,7 +114,7 b''
106 114 {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
107 115 {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
108 116 {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
109 {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"]},
117 {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
110 118 {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
111 119 {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
112 120 {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
@@ -116,6 +124,7 b''
116 124 {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
117 125 {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
118 126 {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
127 {name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
119 128 {name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
120 129 {name: "MariaDB", mime: "text/x-mariadb", mode: "sql"},
121 130 {name: "sTeX", mime: "text/x-stex", mode: "stex"},
@@ -137,10 +146,14 b''
137 146 {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
138 147 {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
139 148 {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
149 {name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
140 150 {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd"], alias: ["rss", "wsdl", "xsd"]},
141 151 {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
142 152 {name: "YAML", mime: "text/x-yaml", mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
143 {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]}
153 {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
154 {name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
155 {name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
156 {name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]}
144 157 ];
145 158 // Ensure all modes have a mime property for backwards compatibility
146 159 for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
@@ -113,7 +113,7 b' MIME_TO_EXT = {'
113 113 "text/x-fortran": {"exts": ["*.f","*.f90","*.F","*.F90","*.for","*.f77"], "mode": "fortran"},
114 114 "text/x-fsharp": {"exts": ["*.fs","*.fsi"], "mode": "mllike"},
115 115 "text/x-gas": {"exts": ["*.s","*.S"], "mode": "gas"},
116 "text/x-gfm": {"exts": ["*.md","*.MD"], "mode": "markdown"},
116 "text/x-gfm": {"exts": ["*.md","*.MD"], "mode": "gfm"},
117 117 "text/x-gherkin": {"exts": ["*.feature"], "mode": ""},
118 118 "text/x-glslsrc": {"exts": ["*.vert","*.frag","*.geo"], "mode": ""},
119 119 "text/x-gnuplot": {"exts": ["*.plot","*.plt"], "mode": ""},
@@ -137,11 +137,11 b' MIME_TO_EXT = {'
137 137 "text/x-julia": {"exts": ["*.jl"], "mode": "julia"},
138 138 "text/x-kconfig": {"exts": ["Kconfig","*Config.in*","external.in*","standard-modules.in"], "mode": ""},
139 139 "text/x-koka": {"exts": ["*.kk","*.kki"], "mode": ""},
140 "text/x-kotlin": {"exts": ["*.kt"], "mode": "kotlin"},
140 "text/x-kotlin": {"exts": ["*.kt"], "mode": "clike"},
141 141 "text/x-lasso": {"exts": ["*.lasso","*.lasso[89]"], "mode": ""},
142 142 "text/x-latex": {"exts": ["*.ltx","*.text"], "mode": "stex"},
143 143 "text/x-less": {"exts": ["*.less"], "mode": "css"},
144 "text/x-literate-haskell": {"exts": ["*.lhs"], "mode": ""},
144 "text/x-literate-haskell": {"exts": ["*.lhs"], "mode": "haskell-literate"},
145 145 "text/x-livescript": {"exts": ["*.ls"], "mode": "livescript"},
146 146 "text/x-llvm": {"exts": ["*.ll"], "mode": ""},
147 147 "text/x-logos": {"exts": ["*.x","*.xi","*.xm","*.xmi"], "mode": ""},
@@ -162,7 +162,7 b' MIME_TO_EXT = {'
162 162 "text/x-newspeak": {"exts": ["*.ns2"], "mode": ""},
163 163 "text/x-nginx-conf": {"exts": ["*.conf"], "mode": "nginx"},
164 164 "text/x-nimrod": {"exts": ["*.nim","*.nimrod"], "mode": ""},
165 "text/x-nsis": {"exts": ["*.nsi","*.nsh"], "mode": ""},
165 "text/x-nsis": {"exts": ["*.nsi","*.nsh"], "mode": "nsis"},
166 166 "text/x-objdump": {"exts": ["*.objdump"], "mode": ""},
167 167 "text/x-objective-c": {"exts": ["*.m","*.h"], "mode": ""},
168 168 "text/x-objective-c++": {"exts": ["*.mm","*.hh"], "mode": ""},
@@ -217,7 +217,7 b' MIME_TO_EXT = {'
217 217 "text/x-vb": {"exts": ["*.vb"], "mode": "vb"},
218 218 "text/x-vbnet": {"exts": ["*.vb","*.bas"], "mode": ""},
219 219 "text/x-verilog": {"exts": ["*.v"], "mode": "verilog"},
220 "text/x-vhdl": {"exts": ["*.vhdl","*.vhd"], "mode": ""},
220 "text/x-vhdl": {"exts": ["*.vhdl","*.vhd"], "mode": "vhdl"},
221 221 "text/x-vim": {"exts": ["*.vim",".vimrc",".exrc",".gvimrc","_vimrc","_exrc","_gvimrc","vimrc","gvimrc"], "mode": ""},
222 222 "text/x-windows-registry": {"exts": ["*.reg"], "mode": ""},
223 223 "text/x-xtend": {"exts": ["*.xtend"], "mode": ""},
@@ -173,6 +173,6 b' CodeMirror.defineMode("nginx", function('
173 173 };
174 174 });
175 175
176 CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");
176 CodeMirror.defineMIME("text/x-nginx-conf", "nginx");
177 177
178 178 });
@@ -86,7 +86,7 b''
86 86 "die echo empty exit eval include include_once isset list require require_once return " +
87 87 "print unset __halt_compiler self static parent yield insteadof finally";
88 88 var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__";
89 var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
89 var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count";
90 90 CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" "));
91 91 CodeMirror.registerHelper("wordChars", "php", /[\w$]/);
92 92
@@ -105,14 +105,15 b''
105 105 return "variable-2";
106 106 },
107 107 "<": function(stream, state) {
108 if (stream.match(/<</)) {
109 var nowDoc = stream.eat("'");
108 var before;
109 if (before = stream.match(/<<\s*/)) {
110 var quoted = stream.eat(/['"]/);
110 111 stream.eatWhile(/[\w\.]/);
111 var delim = stream.current().slice(3 + (nowDoc ? 1 : 0));
112 if (nowDoc) stream.eat("'");
112 var delim = stream.current().slice(before[0].length + (quoted ? 2 : 1));
113 if (quoted) stream.eat(quoted);
113 114 if (delim) {
114 115 (state.tokStack || (state.tokStack = [])).push(delim, 0);
115 state.tokenize = phpString(delim, nowDoc ? false : true);
116 state.tokenize = phpString(delim, quoted != "'");
116 117 return "string";
117 118 }
118 119 }
@@ -159,6 +160,7 b''
159 160 if (!isPHP) {
160 161 if (stream.match(/^<\?\w*/)) {
161 162 state.curMode = phpMode;
163 if (!state.php) state.php = CodeMirror.startState(phpMode, htmlMode.indent(state.html, ""))
162 164 state.curState = state.php;
163 165 return "meta";
164 166 }
@@ -182,6 +184,7 b''
182 184 } else if (isPHP && state.php.tokenize == null && stream.match("?>")) {
183 185 state.curMode = htmlMode;
184 186 state.curState = state.html;
187 if (!state.php.context.prev) state.php = null;
185 188 return "meta";
186 189 } else {
187 190 return phpMode.token(stream, state.curState);
@@ -190,7 +193,8 b''
190 193
191 194 return {
192 195 startState: function() {
193 var html = CodeMirror.startState(htmlMode), php = CodeMirror.startState(phpMode);
196 var html = CodeMirror.startState(htmlMode)
197 var php = parserConfig.startOpen ? CodeMirror.startState(phpMode) : null
194 198 return {html: html,
195 199 php: php,
196 200 curMode: parserConfig.startOpen ? phpMode : htmlMode,
@@ -200,7 +204,7 b''
200 204
201 205 copyState: function(state) {
202 206 var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html),
203 php = state.php, phpNew = CodeMirror.copyState(phpMode, php), cur;
207 php = state.php, phpNew = php && CodeMirror.copyState(phpMode, php), cur;
204 208 if (state.curMode == htmlMode) cur = htmlNew;
205 209 else cur = phpNew;
206 210 return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur,
@@ -48,18 +48,18 b''
48 48 CodeMirror.defineMode("python", function(conf, parserConf) {
49 49 var ERRORCLASS = "error";
50 50
51 var singleDelimiters = parserConf.singleDelimiters || new RegExp("^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]");
52 var doubleOperators = parserConf.doubleOperators || new RegExp("^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))");
53 var doubleDelimiters = parserConf.doubleDelimiters || new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))");
54 var tripleDelimiters = parserConf.tripleDelimiters || new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))");
51 var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/;
52 var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/;
53 var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/;
54 var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/;
55 55
56 56 if (parserConf.version && parseInt(parserConf.version, 10) == 3){
57 57 // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
58 var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!@]");
59 var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*");
58 var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/;
59 var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
60 60 } else {
61 var singleOperators = parserConf.singleOperators || new RegExp("^[\\+\\-\\*/%&|\\^~<>!]");
62 var identifiers = parserConf.identifiers|| new RegExp("^[_A-Za-z][_A-Za-z0-9]*");
61 var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/;
62 var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
63 63 }
64 64
65 65 var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
@@ -160,13 +160,16 b''
160 160
161 161 // Handle operators and Delimiters
162 162 if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters))
163 return null;
163 return "punctuation";
164 164
165 165 if (stream.match(doubleOperators) || stream.match(singleOperators))
166 166 return "operator";
167 167
168 168 if (stream.match(singleDelimiters))
169 return null;
169 return "punctuation";
170
171 if (state.lastToken == "." && stream.match(identifiers))
172 return "property";
170 173
171 174 if (stream.match(keywords) || stream.match(wordOperators))
172 175 return "keyword";
@@ -246,17 +249,6 b''
246 249 var style = state.tokenize(stream, state);
247 250 var current = stream.current();
248 251
249 // Handle '.' connected identifiers
250 if (current == ".") {
251 style = stream.match(identifiers, false) ? null : ERRORCLASS;
252 if (style == null && state.lastStyle == "meta") {
253 // Apply 'meta' style to '.' connected identifiers when
254 // appropriate.
255 style = "meta";
256 }
257 return style;
258 }
259
260 252 // Handle decorators
261 253 if (current == "@"){
262 254 if(parserConf.version && parseInt(parserConf.version, 10) == 3){
@@ -267,7 +259,7 b''
267 259 }
268 260
269 261 if ((style == "variable" || style == "builtin")
270 && state.lastStyle == "meta")
262 && state.lastToken == "meta")
271 263 style = "meta";
272 264
273 265 // Handle scope changes.
@@ -300,7 +292,6 b''
300 292 return {
301 293 tokenize: tokenBase,
302 294 scopes: [{offset: basecolumn || 0, type: "py", align: null}],
303 lastStyle: null,
304 295 lastToken: null,
305 296 lambda: false,
306 297 dedent: 0
@@ -312,11 +303,9 b''
312 303 if (addErr) state.errorToken = false;
313 304 var style = tokenLexer(stream, state);
314 305
315 state.lastStyle = style;
316
317 var current = stream.current();
318 if (current && style)
319 state.lastToken = current;
306 if (style && style != "comment")
307 state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style;
308 if (style == "punctuation") style = null;
320 309
321 310 if (stream.eol() && state.lambda)
322 311 state.lambda = false;
@@ -34,10 +34,10 b' CodeMirror.defineMIME("text/x-rpm-change'
34 34 // Quick and dirty spec file highlighting
35 35
36 36 CodeMirror.defineMode("rpm-spec", function() {
37 var arch = /^(i386|i586|i686|x86_64|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
37 var arch = /^(i386|i586|i686|x86_64|ppc64le|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/;
38 38
39 var preamble = /^(Name|Version|Release|License|Summary|Url|Group|Source|BuildArch|BuildRequires|BuildRoot|AutoReqProv|Provides|Requires(\(\w+\))?|Obsoletes|Conflicts|Recommends|Source\d*|Patch\d*|ExclusiveArch|NoSource|Supplements):/;
40 var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pre|post|triggerin|triggerun|pretrans|posttrans|verifyscript|check|triggerpostun|triggerprein|trigger)/;
39 var preamble = /^[a-zA-Z0-9()]+:/;
40 var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pretrans|posttrans|pre|post|triggerin|triggerun|verifyscript|check|triggerpostun|triggerprein|trigger)/;
41 41 var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros
42 42 var control_flow_simple = /^%(else|endif)/; // rpm control flow macros
43 43 var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros
@@ -55,8 +55,8 b' CodeMirror.defineMode("rpm-spec", functi'
55 55 if (ch == "#") { stream.skipToEnd(); return "comment"; }
56 56
57 57 if (stream.sol()) {
58 if (stream.match(preamble)) { return "preamble"; }
59 if (stream.match(section)) { return "section"; }
58 if (stream.match(preamble)) { return "header"; }
59 if (stream.match(section)) { return "atom"; }
60 60 }
61 61
62 62 if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT'
@@ -73,21 +73,29 b' CodeMirror.defineMode("rpm-spec", functi'
73 73 if (stream.eol()) { state.controlFlow = false; }
74 74 }
75 75
76 if (stream.match(arch)) { return "number"; }
76 if (stream.match(arch)) {
77 if (stream.eol()) { state.controlFlow = false; }
78 return "number";
79 }
77 80
78 81 // Macros like '%make_install' or '%attr(0775,root,root)'
79 82 if (stream.match(/^%[\w]+/)) {
80 83 if (stream.match(/^\(/)) { state.macroParameters = true; }
81 return "macro";
84 return "keyword";
82 85 }
83 86 if (state.macroParameters) {
84 87 if (stream.match(/^\d+/)) { return "number";}
85 88 if (stream.match(/^\)/)) {
86 89 state.macroParameters = false;
87 return "macro";
90 return "keyword";
88 91 }
89 92 }
90 if (stream.match(/^%\{\??[\w \-]+\}/)) { return "macro"; } // Macros like '%{defined fedora}'
93
94 // Macros like '%{defined fedora}'
95 if (stream.match(/^%\{\??[\w \-\:\!]+\}/)) {
96 if (stream.eol()) { state.controlFlow = false; }
97 return "def";
98 }
91 99
92 100 //TODO: Include bash script sub-parser (CodeMirror supports that)
93 101 stream.next();
@@ -25,7 +25,7 b' CodeMirror.defineMode("ruby", function(c'
25 25 "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
26 26 "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__"
27 27 ]);
28 var indentWords = wordObj(["def", "class", "case", "for", "while", "module", "then",
28 var indentWords = wordObj(["def", "class", "case", "for", "while", "until", "module", "then",
29 29 "catch", "loop", "proc", "begin"]);
30 30 var dedentWords = wordObj(["end", "until"]);
31 31 var matching = {"[": "]", "{": "}", "(": ")"};
@@ -37,7 +37,6 b' CodeMirror.defineMode("ruby", function(c'
37 37 }
38 38
39 39 function tokenBase(stream, state) {
40 curPunc = null;
41 40 if (stream.sol() && stream.match("=begin") && stream.eol()) {
42 41 state.tokenize.push(readBlockComment);
43 42 return "comment";
@@ -232,6 +231,7 b' CodeMirror.defineMode("ruby", function(c'
232 231 },
233 232
234 233 token: function(stream, state) {
234 curPunc = null;
235 235 if (stream.sol()) state.indented = stream.indentation();
236 236 var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
237 237 var thisTok = curPunc;
@@ -275,7 +275,7 b' CodeMirror.defineMode("ruby", function(c'
275 275 (state.continuedLine ? config.indentUnit : 0);
276 276 },
277 277
278 electricChars: "}de", // enD and rescuE
278 electricInput: /^\s*(?:end|rescue|\})$/,
279 279 lineComment: "#"
280 280 };
281 281 });
@@ -3,449 +3,69 b''
3 3
4 4 (function(mod) {
5 5 if (typeof exports == "object" && typeof module == "object") // CommonJS
6 mod(require("../../lib/codemirror"));
6 mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
7 7 else if (typeof define == "function" && define.amd) // AMD
8 define(["../../lib/codemirror"], mod);
8 define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
9 9 else // Plain browser env
10 10 mod(CodeMirror);
11 11 })(function(CodeMirror) {
12 12 "use strict";
13 13
14 CodeMirror.defineMode("rust", function() {
15 var indentUnit = 4, altIndentUnit = 2;
16 var valKeywords = {
17 "if": "if-style", "while": "if-style", "loop": "else-style", "else": "else-style",
18 "do": "else-style", "ret": "else-style", "fail": "else-style",
19 "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
20 "let": "let", "fn": "fn", "for": "for", "alt": "alt", "iface": "iface",
21 "impl": "impl", "type": "type", "enum": "enum", "mod": "mod",
22 "as": "op", "true": "atom", "false": "atom", "assert": "op", "check": "op",
23 "claim": "op", "native": "ignore", "unsafe": "ignore", "import": "else-style",
24 "export": "else-style", "copy": "op", "log": "op", "log_err": "op",
25 "use": "op", "bind": "op", "self": "atom", "struct": "enum"
26 };
27 var typeKeywords = function() {
28 var keywords = {"fn": "fn", "block": "fn", "obj": "obj"};
29 var atoms = "bool uint int i8 i16 i32 i64 u8 u16 u32 u64 float f32 f64 str char".split(" ");
30 for (var i = 0, e = atoms.length; i < e; ++i) keywords[atoms[i]] = "atom";
31 return keywords;
32 }();
33 var operatorChar = /[+\-*&%=<>!?|\.@]/;
34
35 // Tokenizer
36
37 // Used as scratch variable to communicate multiple values without
38 // consing up tons of objects.
39 var tcat, content;
40 function r(tc, style) {
41 tcat = tc;
42 return style;
43 }
44
45 function tokenBase(stream, state) {
46 var ch = stream.next();
47 if (ch == '"') {
48 state.tokenize = tokenString;
49 return state.tokenize(stream, state);
50 }
51 if (ch == "'") {
52 tcat = "atom";
53 if (stream.eat("\\")) {
54 if (stream.skipTo("'")) { stream.next(); return "string"; }
55 else { return "error"; }
56 } else {
57 stream.next();
58 return stream.eat("'") ? "string" : "error";
59 }
60 }
61 if (ch == "/") {
62 if (stream.eat("/")) { stream.skipToEnd(); return "comment"; }
63 if (stream.eat("*")) {
64 state.tokenize = tokenComment(1);
65 return state.tokenize(stream, state);
66 }
67 }
68 if (ch == "#") {
69 if (stream.eat("[")) { tcat = "open-attr"; return null; }
70 stream.eatWhile(/\w/);
71 return r("macro", "meta");
72 }
73 if (ch == ":" && stream.match(":<")) {
74 return r("op", null);
75 }
76 if (ch.match(/\d/) || (ch == "." && stream.eat(/\d/))) {
77 var flp = false;
78 if (!stream.match(/^x[\da-f]+/i) && !stream.match(/^b[01]+/)) {
79 stream.eatWhile(/\d/);
80 if (stream.eat(".")) { flp = true; stream.eatWhile(/\d/); }
81 if (stream.match(/^e[+\-]?\d+/i)) { flp = true; }
82 }
83 if (flp) stream.match(/^f(?:32|64)/);
84 else stream.match(/^[ui](?:8|16|32|64)/);
85 return r("atom", "number");
86 }
87 if (ch.match(/[()\[\]{}:;,]/)) return r(ch, null);
88 if (ch == "-" && stream.eat(">")) return r("->", null);
89 if (ch.match(operatorChar)) {
90 stream.eatWhile(operatorChar);
91 return r("op", null);
92 }
93 stream.eatWhile(/\w/);
94 content = stream.current();
95 if (stream.match(/^::\w/)) {
96 stream.backUp(1);
97 return r("prefix", "variable-2");
98 }
99 if (state.keywords.propertyIsEnumerable(content))
100 return r(state.keywords[content], content.match(/true|false/) ? "atom" : "keyword");
101 return r("name", "variable");
102 }
103
104 function tokenString(stream, state) {
105 var ch, escaped = false;
106 while (ch = stream.next()) {
107 if (ch == '"' && !escaped) {
108 state.tokenize = tokenBase;
109 return r("atom", "string");
110 }
111 escaped = !escaped && ch == "\\";
112 }
113 // Hack to not confuse the parser when a string is split in
114 // pieces.
115 return r("op", "string");
116 }
117
118 function tokenComment(depth) {
119 return function(stream, state) {
120 var lastCh = null, ch;
121 while (ch = stream.next()) {
122 if (ch == "/" && lastCh == "*") {
123 if (depth == 1) {
124 state.tokenize = tokenBase;
125 break;
126 } else {
127 state.tokenize = tokenComment(depth - 1);
128 return state.tokenize(stream, state);
129 }
130 }
131 if (ch == "*" && lastCh == "/") {
132 state.tokenize = tokenComment(depth + 1);
133 return state.tokenize(stream, state);
134 }
135 lastCh = ch;
136 }
137 return "comment";
138 };
139 }
140
141 // Parser
142
143 var cx = {state: null, stream: null, marked: null, cc: null};
144 function pass() {
145 for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
146 }
147 function cont() {
148 pass.apply(null, arguments);
149 return true;
150 }
151
152 function pushlex(type, info) {
153 var result = function() {
154 var state = cx.state;
155 state.lexical = {indented: state.indented, column: cx.stream.column(),
156 type: type, prev: state.lexical, info: info};
157 };
158 result.lex = true;
159 return result;
160 }
161 function poplex() {
162 var state = cx.state;
163 if (state.lexical.prev) {
164 if (state.lexical.type == ")")
165 state.indented = state.lexical.indented;
166 state.lexical = state.lexical.prev;
167 }
168 }
169 function typecx() { cx.state.keywords = typeKeywords; }
170 function valcx() { cx.state.keywords = valKeywords; }
171 poplex.lex = typecx.lex = valcx.lex = true;
172
173 function commasep(comb, end) {
174 function more(type) {
175 if (type == ",") return cont(comb, more);
176 if (type == end) return cont();
177 return cont(more);
178 }
179 return function(type) {
180 if (type == end) return cont();
181 return pass(comb, more);
182 };
183 }
14 CodeMirror.defineSimpleMode("rust",{
15 start: [
16 // string and byte string
17 {regex: /b?"/, token: "string", next: "string"},
18 // raw string and raw byte string
19 {regex: /b?r"/, token: "string", next: "string_raw"},
20 {regex: /b?r#+"/, token: "string", next: "string_raw_hash"},
21 // character
22 {regex: /'(?:[^'\\]|\\(?:[nrt0'"]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\}))'/, token: "string-2"},
23 // byte
24 {regex: /b'(?:[^']|\\(?:['\\nrt0]|x[\da-fA-F]{2}))'/, token: "string-2"},
184 25
185 function stat_of(comb, tag) {
186 return cont(pushlex("stat", tag), comb, poplex, block);
187 }
188 function block(type) {
189 if (type == "}") return cont();
190 if (type == "let") return stat_of(letdef1, "let");
191 if (type == "fn") return stat_of(fndef);
192 if (type == "type") return cont(pushlex("stat"), tydef, endstatement, poplex, block);
193 if (type == "enum") return stat_of(enumdef);
194 if (type == "mod") return stat_of(mod);
195 if (type == "iface") return stat_of(iface);
196 if (type == "impl") return stat_of(impl);
197 if (type == "open-attr") return cont(pushlex("]"), commasep(expression, "]"), poplex);
198 if (type == "ignore" || type.match(/[\]\);,]/)) return cont(block);
199 return pass(pushlex("stat"), expression, poplex, endstatement, block);
200 }
201 function endstatement(type) {
202 if (type == ";") return cont();
203 return pass();
204 }
205 function expression(type) {
206 if (type == "atom" || type == "name") return cont(maybeop);
207 if (type == "{") return cont(pushlex("}"), exprbrace, poplex);
208 if (type.match(/[\[\(]/)) return matchBrackets(type, expression);
209 if (type.match(/[\]\)\};,]/)) return pass();
210 if (type == "if-style") return cont(expression, expression);
211 if (type == "else-style" || type == "op") return cont(expression);
212 if (type == "for") return cont(pattern, maybetype, inop, expression, expression);
213 if (type == "alt") return cont(expression, altbody);
214 if (type == "fn") return cont(fndef);
215 if (type == "macro") return cont(macro);
216 return cont();
217 }
218 function maybeop(type) {
219 if (content == ".") return cont(maybeprop);
220 if (content == "::<"){return cont(typarams, maybeop);}
221 if (type == "op" || content == ":") return cont(expression);
222 if (type == "(" || type == "[") return matchBrackets(type, expression);
223 return pass();
224 }
225 function maybeprop() {
226 if (content.match(/^\w+$/)) {cx.marked = "variable"; return cont(maybeop);}
227 return pass(expression);
228 }
229 function exprbrace(type) {
230 if (type == "op") {
231 if (content == "|") return cont(blockvars, poplex, pushlex("}", "block"), block);
232 if (content == "||") return cont(poplex, pushlex("}", "block"), block);
233 }
234 if (content == "mutable" || (content.match(/^\w+$/) && cx.stream.peek() == ":"
235 && !cx.stream.match("::", false)))
236 return pass(record_of(expression));
237 return pass(block);
238 }
239 function record_of(comb) {
240 function ro(type) {
241 if (content == "mutable" || content == "with") {cx.marked = "keyword"; return cont(ro);}
242 if (content.match(/^\w*$/)) {cx.marked = "variable"; return cont(ro);}
243 if (type == ":") return cont(comb, ro);
244 if (type == "}") return cont();
245 return cont(ro);
246 }
247 return ro;
248 }
249 function blockvars(type) {
250 if (type == "name") {cx.marked = "def"; return cont(blockvars);}
251 if (type == "op" && content == "|") return cont();
252 return cont(blockvars);
253 }
254
255 function letdef1(type) {
256 if (type.match(/[\]\)\};]/)) return cont();
257 if (content == "=") return cont(expression, letdef2);
258 if (type == ",") return cont(letdef1);
259 return pass(pattern, maybetype, letdef1);
260 }
261 function letdef2(type) {
262 if (type.match(/[\]\)\};,]/)) return pass(letdef1);
263 else return pass(expression, letdef2);
264 }
265 function maybetype(type) {
266 if (type == ":") return cont(typecx, rtype, valcx);
267 return pass();
268 }
269 function inop(type) {
270 if (type == "name" && content == "in") {cx.marked = "keyword"; return cont();}
271 return pass();
272 }
273 function fndef(type) {
274 if (content == "@" || content == "~") {cx.marked = "keyword"; return cont(fndef);}
275 if (type == "name") {cx.marked = "def"; return cont(fndef);}
276 if (content == "<") return cont(typarams, fndef);
277 if (type == "{") return pass(expression);
278 if (type == "(") return cont(pushlex(")"), commasep(argdef, ")"), poplex, fndef);
279 if (type == "->") return cont(typecx, rtype, valcx, fndef);
280 if (type == ";") return cont();
281 return cont(fndef);
282 }
283 function tydef(type) {
284 if (type == "name") {cx.marked = "def"; return cont(tydef);}
285 if (content == "<") return cont(typarams, tydef);
286 if (content == "=") return cont(typecx, rtype, valcx);
287 return cont(tydef);
288 }
289 function enumdef(type) {
290 if (type == "name") {cx.marked = "def"; return cont(enumdef);}
291 if (content == "<") return cont(typarams, enumdef);
292 if (content == "=") return cont(typecx, rtype, valcx, endstatement);
293 if (type == "{") return cont(pushlex("}"), typecx, enumblock, valcx, poplex);
294 return cont(enumdef);
295 }
296 function enumblock(type) {
297 if (type == "}") return cont();
298 if (type == "(") return cont(pushlex(")"), commasep(rtype, ")"), poplex, enumblock);
299 if (content.match(/^\w+$/)) cx.marked = "def";
300 return cont(enumblock);
301 }
302 function mod(type) {
303 if (type == "name") {cx.marked = "def"; return cont(mod);}
304 if (type == "{") return cont(pushlex("}"), block, poplex);
305 return pass();
306 }
307 function iface(type) {
308 if (type == "name") {cx.marked = "def"; return cont(iface);}
309 if (content == "<") return cont(typarams, iface);
310 if (type == "{") return cont(pushlex("}"), block, poplex);
311 return pass();
312 }
313 function impl(type) {
314 if (content == "<") return cont(typarams, impl);
315 if (content == "of" || content == "for") {cx.marked = "keyword"; return cont(rtype, impl);}
316 if (type == "name") {cx.marked = "def"; return cont(impl);}
317 if (type == "{") return cont(pushlex("}"), block, poplex);
318 return pass();
319 }
320 function typarams() {
321 if (content == ">") return cont();
322 if (content == ",") return cont(typarams);
323 if (content == ":") return cont(rtype, typarams);
324 return pass(rtype, typarams);
325 }
326 function argdef(type) {
327 if (type == "name") {cx.marked = "def"; return cont(argdef);}
328 if (type == ":") return cont(typecx, rtype, valcx);
329 return pass();
330 }
331 function rtype(type) {
332 if (type == "name") {cx.marked = "variable-3"; return cont(rtypemaybeparam); }
333 if (content == "mutable") {cx.marked = "keyword"; return cont(rtype);}
334 if (type == "atom") return cont(rtypemaybeparam);
335 if (type == "op" || type == "obj") return cont(rtype);
336 if (type == "fn") return cont(fntype);
337 if (type == "{") return cont(pushlex("{"), record_of(rtype), poplex);
338 return matchBrackets(type, rtype);
339 }
340 function rtypemaybeparam() {
341 if (content == "<") return cont(typarams);
342 return pass();
343 }
344 function fntype(type) {
345 if (type == "(") return cont(pushlex("("), commasep(rtype, ")"), poplex, fntype);
346 if (type == "->") return cont(rtype);
347 return pass();
348 }
349 function pattern(type) {
350 if (type == "name") {cx.marked = "def"; return cont(patternmaybeop);}
351 if (type == "atom") return cont(patternmaybeop);
352 if (type == "op") return cont(pattern);
353 if (type.match(/[\]\)\};,]/)) return pass();
354 return matchBrackets(type, pattern);
355 }
356 function patternmaybeop(type) {
357 if (type == "op" && content == ".") return cont();
358 if (content == "to") {cx.marked = "keyword"; return cont(pattern);}
359 else return pass();
360 }
361 function altbody(type) {
362 if (type == "{") return cont(pushlex("}", "alt"), altblock1, poplex);
363 return pass();
364 }
365 function altblock1(type) {
366 if (type == "}") return cont();
367 if (type == "|") return cont(altblock1);
368 if (content == "when") {cx.marked = "keyword"; return cont(expression, altblock2);}
369 if (type.match(/[\]\);,]/)) return cont(altblock1);
370 return pass(pattern, altblock2);
371 }
372 function altblock2(type) {
373 if (type == "{") return cont(pushlex("}", "alt"), block, poplex, altblock1);
374 else return pass(altblock1);
375 }
376
377 function macro(type) {
378 if (type.match(/[\[\(\{]/)) return matchBrackets(type, expression);
379 return pass();
380 }
381 function matchBrackets(type, comb) {
382 if (type == "[") return cont(pushlex("]"), commasep(comb, "]"), poplex);
383 if (type == "(") return cont(pushlex(")"), commasep(comb, ")"), poplex);
384 if (type == "{") return cont(pushlex("}"), commasep(comb, "}"), poplex);
385 return cont();
386 }
387
388 function parse(state, stream, style) {
389 var cc = state.cc;
390 // Communicate our context to the combinators.
391 // (Less wasteful than consing up a hundred closures on every call.)
392 cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
393
394 while (true) {
395 var combinator = cc.length ? cc.pop() : block;
396 if (combinator(tcat)) {
397 while(cc.length && cc[cc.length - 1].lex)
398 cc.pop()();
399 return cx.marked || style;
400 }
401 }
402 }
403
404 return {
405 startState: function() {
406 return {
407 tokenize: tokenBase,
408 cc: [],
409 lexical: {indented: -indentUnit, column: 0, type: "top", align: false},
410 keywords: valKeywords,
411 indented: 0
412 };
413 },
414
415 token: function(stream, state) {
416 if (stream.sol()) {
417 if (!state.lexical.hasOwnProperty("align"))
418 state.lexical.align = false;
419 state.indented = stream.indentation();
420 }
421 if (stream.eatSpace()) return null;
422 tcat = content = null;
423 var style = state.tokenize(stream, state);
424 if (style == "comment") return style;
425 if (!state.lexical.hasOwnProperty("align"))
426 state.lexical.align = true;
427 if (tcat == "prefix") return style;
428 if (!content) content = stream.current();
429 return parse(state, stream, style);
430 },
431
432 indent: function(state, textAfter) {
433 if (state.tokenize != tokenBase) return 0;
434 var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical,
435 type = lexical.type, closing = firstChar == type;
436 if (type == "stat") return lexical.indented + indentUnit;
437 if (lexical.align) return lexical.column + (closing ? 0 : 1);
438 return lexical.indented + (closing ? 0 : (lexical.info == "alt" ? altIndentUnit : indentUnit));
439 },
440
441 electricChars: "{}",
26 {regex: /(?:(?:[0-9][0-9_]*)(?:(?:[Ee][+-]?[0-9_]+)|\.[0-9_]+(?:[Ee][+-]?[0-9_]+)?)(?:f32|f64)?)|(?:0(?:b[01_]+|(?:o[0-7_]+)|(?:x[0-9a-fA-F_]+))|(?:[0-9][0-9_]*))(?:u8|u16|u32|u64|i8|i16|i32|i64|isize|usize)?/,
27 token: "number"},
28 {regex: /(let(?:\s+mut)?|fn|enum|mod|struct|type)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, token: ["keyword", null, "def"]},
29 {regex: /(?:abstract|alignof|as|box|break|continue|const|crate|do|else|enum|extern|fn|for|final|if|impl|in|loop|macro|match|mod|move|offsetof|override|priv|proc|pub|pure|ref|return|self|sizeof|static|struct|super|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\b/, token: "keyword"},
30 {regex: /\b(?:Self|isize|usize|char|bool|u8|u16|u32|u64|f16|f32|f64|i8|i16|i32|i64|str|Option)\b/, token: "atom"},
31 {regex: /\b(?:true|false|Some|None|Ok|Err)\b/, token: "builtin"},
32 {regex: /\b(fn)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/,
33 token: ["keyword", null ,"def"]},
34 {regex: /#!?\[.*\]/, token: "meta"},
35 {regex: /\/\/.*/, token: "comment"},
36 {regex: /\/\*/, token: "comment", next: "comment"},
37 {regex: /[-+\/*=<>!]+/, token: "operator"},
38 {regex: /[a-zA-Z_]\w*!/,token: "variable-3"},
39 {regex: /[a-zA-Z_]\w*/, token: "variable"},
40 {regex: /[\{\[\(]/, indent: true},
41 {regex: /[\}\]\)]/, dedent: true}
42 ],
43 string: [
44 {regex: /"/, token: "string", next: "start"},
45 {regex: /(?:[^\\"]|\\(?:.|$))*/, token: "string"}
46 ],
47 string_raw: [
48 {regex: /"/, token: "string", next: "start"},
49 {regex: /[^"]*/, token: "string"}
50 ],
51 string_raw_hash: [
52 {regex: /"#+/, token: "string", next: "start"},
53 {regex: /(?:[^"]|"(?!#))*/, token: "string"}
54 ],
55 comment: [
56 {regex: /.*?\*\//, token: "comment", next: "start"},
57 {regex: /.*/, token: "comment"}
58 ],
59 meta: {
60 dontIndentStates: ["comment"],
61 electricInput: /^\s*\}$/,
442 62 blockCommentStart: "/*",
443 63 blockCommentEnd: "*/",
444 64 lineComment: "//",
445 65 fold: "brace"
446 };
66 }
447 67 });
448 68
69
449 70 CodeMirror.defineMIME("text/x-rustsrc", "rust");
450
451 71 });
@@ -165,7 +165,9 b' CodeMirror.defineMode("sparql", function'
165 165 return context.col + (closing ? 0 : 1);
166 166 else
167 167 return context.indent + (closing ? 0 : indentUnit);
168 }
168 },
169
170 lineComment: "#"
169 171 };
170 172 });
171 173
@@ -257,7 +257,7 b' CodeMirror.defineMode("sql", function(co'
257 257 }
258 258
259 259 // these keywords are used by all SQL dialects (however, a mode can still overwrite it)
260 var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where ";
260 var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit";
261 261
262 262 // turn a space-separated list into an array
263 263 function set(str) {
@@ -126,19 +126,16 b''
126 126 if (stream.match(/^&{1}\s*$/)) {
127 127 return ["variable-3", "reference"];
128 128 }
129 // Variable
130 if (ch == "$" && stream.match(/^\$[\w-]+/i)) {
131 return ["variable-2", "variable-name"];
132 }
133 129 // Word operator
134 130 if (stream.match(wordOperatorKeywordsRegexp)) {
135 131 return ["operator", "operator"];
136 132 }
137 133 // Word
138 if (stream.match(/^[-_]*[a-z0-9]+[\w-]*/i)) {
134 if (stream.match(/^\$?[-_]*[a-z0-9]+[\w-]*/i)) {
135 // Variable
139 136 if (stream.match(/^(\.|\[)[\w-\'\"\]]+/i, false)) {
140 137 if (!wordIsTag(stream.current())) {
141 stream.match(/[\w-]+/);
138 stream.match(/\./);
142 139 return ["variable-2", "variable-name"];
143 140 }
144 141 }
@@ -323,7 +320,7 b''
323 320 return pushContext(state, stream, "block", 0);
324 321 }
325 322 if (type == "variable-name") {
326 if ((stream.indentation() == 0 && startOfLine(stream)) || wordIsBlock(firstWordOfLine(stream))) {
323 if (stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/) || wordIsBlock(firstWordOfLine(stream))) {
327 324 return pushContext(state, stream, "variableName");
328 325 }
329 326 else {
@@ -429,6 +426,11 b''
429 426 return pushContext(state, stream, "block");
430 427 }
431 428 if (word == "return") return pushContext(state, stream, "block", 0);
429
430 // Placeholder selector
431 if (override == "variable-2" && stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/)) {
432 return pushContext(state, stream, "block");
433 }
432 434 }
433 435 return state.context.type;
434 436 };
@@ -639,7 +641,6 b''
639 641 states.variableName = function(type, stream, state) {
640 642 if (type == "string" || type == "[" || type == "]" || stream.current().match(/^(\.|\$)/)) {
641 643 if (stream.current().match(/^\.[\w-]+/i)) override = "variable-2";
642 if (endOfLine(stream)) return popContext(state);
643 644 return "variableName";
644 645 }
645 646 return popAndPass(type, stream, state);
@@ -735,7 +736,7 b''
735 736 var nonStandardPropertyKeywords_ = ["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"];
736 737 var fontProperties_ = ["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"];
737 738 var colorKeywords_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"];
738 var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale"];
739 var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale","row","row-reverse","wrap","wrap-reverse","column-reverse","flex-start","flex-end","space-between","space-around"];
739 740
740 741 var wordOperatorKeywords_ = ["in","and","or","not","is not","is a","is","isnt","defined","if unless"],
741 742 blockKeywords_ = ["for","if","else","unless", "from", "to"],
@@ -13,189 +13,188 b''
13 13 })(function(CodeMirror) {
14 14 "use strict"
15 15
16 function trim(str) { return /^\s*(.*?)\s*$/.exec(str)[1] }
17
18 var separators = [" ","\\\+","\\\-","\\\(","\\\)","\\\*","/",":","\\\?","\\\<","\\\>"," ","\\\."]
19 var tokens = new RegExp(separators.join("|"),"g")
20
21 function getWord(string, pos) {
22 var index = -1, count = 1
23 var words = string.split(tokens)
24 for (var i = 0; i < words.length; i++) {
25 for(var j = 1; j <= words[i].length; j++) {
26 if (count==pos) index = i
27 count++
28 }
29 count++
30 }
31 var ret = ["", ""]
32 if (pos == 0) {
33 ret[1] = words[0]
34 ret[0] = null
35 } else {
36 ret[1] = words[index]
37 ret[0] = words[index-1]
38 }
39 return ret
16 function wordSet(words) {
17 var set = {}
18 for (var i = 0; i < words.length; i++) set[words[i]] = true
19 return set
40 20 }
41 21
42 CodeMirror.defineMode("swift", function() {
43 var keywords=["var","let","class","deinit","enum","extension","func","import","init","let","protocol","static","struct","subscript","typealias","var","as","dynamicType","is","new","super","self","Self","Type","__COLUMN__","__FILE__","__FUNCTION__","__LINE__","break","case","continue","default","do","else","fallthrough","if","in","for","return","switch","where","while","associativity","didSet","get","infix","inout","left","mutating","none","nonmutating","operator","override","postfix","precedence","prefix","right","set","unowned","unowned(safe)","unowned(unsafe)","weak","willSet"]
44 var commonConstants=["Infinity","NaN","undefined","null","true","false","on","off","yes","no","nil","null","this","super"]
45 var types=["String","bool","int","string","double","Double","Int","Float","float","public","private","extension"]
46 var numbers=["0","1","2","3","4","5","6","7","8","9"]
47 var operators=["+","-","/","*","%","=","|","&","<",">"]
48 var punc=[";",",",".","(",")","{","}","[","]"]
49 var delimiters=/^(?:[()\[\]{},:`=;]|\.\.?\.?)/
50 var identifiers=/^[_A-Za-z$][_A-Za-z$0-9]*/
51 var properties=/^(@|this\.)[_A-Za-z$][_A-Za-z$0-9]*/
52 var regexPrefixes=/^(\/{3}|\/)/
22 var keywords = wordSet(["var","let","class","deinit","enum","extension","func","import","init","protocol",
23 "static","struct","subscript","typealias","as","dynamicType","is","new","super",
24 "self","Self","Type","__COLUMN__","__FILE__","__FUNCTION__","__LINE__","break","case",
25 "continue","default","do","else","fallthrough","if","in","for","return","switch",
26 "where","while","associativity","didSet","get","infix","inout","left","mutating",
27 "none","nonmutating","operator","override","postfix","precedence","prefix","right",
28 "set","unowned","weak","willSet"])
29 var definingKeywords = wordSet(["var","let","class","enum","extension","func","import","protocol","struct",
30 "typealias","dynamicType","for"])
31 var atoms = wordSet(["Infinity","NaN","undefined","null","true","false","on","off","yes","no","nil","null",
32 "this","super"])
33 var types = wordSet(["String","bool","int","string","double","Double","Int","Float","float","public",
34 "private","extension"])
35 var operators = "+-/*%=|&<>#"
36 var punc = ";,.(){}[]"
37 var number = /^-?(?:(?:[\d_]+\.[_\d]*|\.[_\d]+|0o[0-7_\.]+|0b[01_\.]+)(?:e-?[\d_]+)?|0x[\d_a-f\.]+(?:p-?[\d_]+)?)/i
38 var identifier = /^[_A-Za-z$][_A-Za-z$0-9]*/
39 var property = /^[@\.][_A-Za-z$][_A-Za-z$0-9]*/
40 var regexp = /^\/(?!\s)(?:\/\/)?(?:\\.|[^\/])+\//
41
42 function tokenBase(stream, state, prev) {
43 if (stream.sol()) state.indented = stream.indentation()
44 if (stream.eatSpace()) return null
45
46 var ch = stream.peek()
47 if (ch == "/") {
48 if (stream.match("//")) {
49 stream.skipToEnd()
50 return "comment"
51 }
52 if (stream.match("/*")) {
53 state.tokenize.push(tokenComment)
54 return tokenComment(stream, state)
55 }
56 if (stream.match(regexp)) return "string-2"
57 }
58 if (operators.indexOf(ch) > -1) {
59 stream.next()
60 return "operator"
61 }
62 if (punc.indexOf(ch) > -1) {
63 stream.next()
64 stream.match("..")
65 return "punctuation"
66 }
67 if (ch == '"' || ch == "'") {
68 stream.next()
69 var tokenize = tokenString(ch)
70 state.tokenize.push(tokenize)
71 return tokenize(stream, state)
72 }
73
74 if (stream.match(number)) return "number"
75 if (stream.match(property)) return "property"
76
77 if (stream.match(identifier)) {
78 var ident = stream.current()
79 if (keywords.hasOwnProperty(ident)) {
80 if (definingKeywords.hasOwnProperty(ident))
81 state.prev = "define"
82 return "keyword"
83 }
84 if (types.hasOwnProperty(ident)) return "variable-2"
85 if (atoms.hasOwnProperty(ident)) return "atom"
86 if (prev == "define") return "def"
87 return "variable"
88 }
53 89
90 stream.next()
91 return null
92 }
93
94 function tokenUntilClosingParen() {
95 var depth = 0
96 return function(stream, state, prev) {
97 var inner = tokenBase(stream, state, prev)
98 if (inner == "punctuation") {
99 if (stream.current() == "(") ++depth
100 else if (stream.current() == ")") {
101 if (depth == 0) {
102 stream.backUp(1)
103 state.tokenize.pop()
104 return state.tokenize[state.tokenize.length - 1](stream, state)
105 }
106 else --depth
107 }
108 }
109 return inner
110 }
111 }
112
113 function tokenString(quote) {
114 return function(stream, state) {
115 var ch, escaped = false
116 while (ch = stream.next()) {
117 if (escaped) {
118 if (ch == "(") {
119 state.tokenize.push(tokenUntilClosingParen())
120 return "string"
121 }
122 escaped = false
123 } else if (ch == quote) {
124 break
125 } else {
126 escaped = ch == "\\"
127 }
128 }
129 state.tokenize.pop()
130 return "string"
131 }
132 }
133
134 function tokenComment(stream, state) {
135 stream.match(/^(?:[^*]|\*(?!\/))*/)
136 if (stream.match("*/")) state.tokenize.pop()
137 return "comment"
138 }
139
140 function Context(prev, align, indented) {
141 this.prev = prev
142 this.align = align
143 this.indented = indented
144 }
145
146 function pushContext(state, stream) {
147 var align = stream.match(/^\s*($|\/[\/\*])/, false) ? null : stream.column() + 1
148 state.context = new Context(state.context, align, state.indented)
149 }
150
151 function popContext(state) {
152 if (state.context) {
153 state.indented = state.context.indented
154 state.context = state.context.prev
155 }
156 }
157
158 CodeMirror.defineMode("swift", function(config) {
54 159 return {
55 160 startState: function() {
56 161 return {
57 prev: false,
58 string: false,
59 escape: false,
60 inner: false,
61 comment: false,
62 num_left: 0,
63 num_right: 0,
64 doubleString: false,
65 singleString: false
162 prev: null,
163 context: null,
164 indented: 0,
165 tokenize: []
66 166 }
67 167 },
68 token: function(stream, state) {
69 if (stream.eatSpace()) return null
70 168
71 var ch = stream.next()
72 if (state.string) {
73 if (state.escape) {
74 state.escape = false
75 return "string"
76 } else {
77 if ((ch == "\"" && (state.doubleString && !state.singleString) ||
78 (ch == "'" && (!state.doubleString && state.singleString))) &&
79 !state.escape) {
80 state.string = false
81 state.doubleString = false
82 state.singleString = false
83 return "string"
84 } else if (ch == "\\" && stream.peek() == "(") {
85 state.inner = true
86 state.string = false
87 return "keyword"
88 } else if (ch == "\\" && stream.peek() != "(") {
89 state.escape = true
90 state.string = true
91 return "string"
92 } else {
93 return "string"
94 }
95 }
96 } else if (state.comment) {
97 if (ch == "*" && stream.peek() == "/") {
98 state.prev = "*"
99 return "comment"
100 } else if (ch == "/" && state.prev == "*") {
101 state.prev = false
102 state.comment = false
103 return "comment"
104 }
105 return "comment"
106 } else {
107 if (ch == "/") {
108 if (stream.peek() == "/") {
109 stream.skipToEnd()
110 return "comment"
111 }
112 if (stream.peek() == "*") {
113 state.comment = true
114 return "comment"
115 }
116 }
117 if (ch == "(" && state.inner) {
118 state.num_left++
119 return null
120 }
121 if (ch == ")" && state.inner) {
122 state.num_right++
123 if (state.num_left == state.num_right) {
124 state.inner=false
125 state.string=true
126 }
127 return null
128 }
169 token: function(stream, state) {
170 var prev = state.prev
171 state.prev = null
172 var tokenize = state.tokenize[state.tokenize.length - 1] || tokenBase
173 var style = tokenize(stream, state, prev)
174 if (!style || style == "comment") state.prev = prev
175 else if (!state.prev) state.prev = style
129 176
130 var ret = getWord(stream.string, stream.pos)
131 var the_word = ret[1]
132 var prev_word = ret[0]
177 if (style == "punctuation") {
178 var bracket = /[\(\[\{]|([\]\)\}])/.exec(stream.current())
179 if (bracket) (bracket[1] ? popContext : pushContext)(state, stream)
180 }
133 181
134 if (operators.indexOf(ch + "") > -1) return "operator"
135 if (punc.indexOf(ch) > -1) return "punctuation"
136
137 if (typeof the_word != "undefined") {
138 the_word = trim(the_word)
139 if (typeof prev_word != "undefined") prev_word = trim(prev_word)
140 if (the_word.charAt(0) == "#") return null
141
142 if (types.indexOf(the_word) > -1) return "def"
143 if (commonConstants.indexOf(the_word) > -1) return "atom"
144 if (numbers.indexOf(the_word) > -1) return "number"
145
146 if ((numbers.indexOf(the_word.charAt(0) + "") > -1 ||
147 operators.indexOf(the_word.charAt(0) + "") > -1) &&
148 numbers.indexOf(ch) > -1) {
149 return "number"
150 }
182 return style
183 },
151 184
152 if (keywords.indexOf(the_word) > -1 ||
153 keywords.indexOf(the_word.split(tokens)[0]) > -1)
154 return "keyword"
155 if (keywords.indexOf(prev_word) > -1) return "def"
156 }
157 if (ch == '"' && !state.doubleString) {
158 state.string = true
159 state.doubleString = true
160 return "string"
161 }
162 if (ch == "'" && !state.singleString) {
163 state.string = true
164 state.singleString = true
165 return "string"
166 }
167 if (ch == "(" && state.inner)
168 state.num_left++
169 if (ch == ")" && state.inner) {
170 state.num_right++
171 if (state.num_left == state.num_right) {
172 state.inner = false
173 state.string = true
174 }
175 return null
176 }
177 if (stream.match(/^-?[0-9\.]/, false)) {
178 if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i) ||
179 stream.match(/^-?\d+\.\d*/) ||
180 stream.match(/^-?\.\d+/)) {
181 if (stream.peek() == ".") stream.backUp(1)
182 return "number"
183 }
184 if (stream.match(/^-?0x[0-9a-f]+/i) ||
185 stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/) ||
186 stream.match(/^-?0(?![\dx])/i))
187 return "number"
188 }
189 if (stream.match(regexPrefixes)) {
190 if (stream.current()!="/" || stream.match(/^.*\//,false)) return "string"
191 else stream.backUp(1)
192 }
193 if (stream.match(delimiters)) return "punctuation"
194 if (stream.match(identifiers)) return "variable"
195 if (stream.match(properties)) return "property"
196 return "variable"
197 }
198 }
185 indent: function(state, textAfter) {
186 var cx = state.context
187 if (!cx) return 0
188 var closing = /^[\]\}\)]/.test(textAfter)
189 if (cx.align != null) return cx.align - (closing ? 1 : 0)
190 return cx.indented + (closing ? 0 : config.indentUnit)
191 },
192
193 electricInput: /^\s*[\)\}\]]$/,
194
195 lineComment: "//",
196 blockCommentStart: "/*",
197 blockCommentEnd: "*/"
199 198 }
200 199 })
201 200
@@ -11,54 +11,56 b''
11 11 })(function(CodeMirror) {
12 12 "use strict";
13 13
14 CodeMirror.defineMode("xml", function(config, parserConfig) {
15 var indentUnit = config.indentUnit;
16 var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
17 var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
18 if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
14 var htmlConfig = {
15 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
16 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
17 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
18 'track': true, 'wbr': true, 'menuitem': true},
19 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
20 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
21 'th': true, 'tr': true},
22 contextGrabbers: {
23 'dd': {'dd': true, 'dt': true},
24 'dt': {'dd': true, 'dt': true},
25 'li': {'li': true},
26 'option': {'option': true, 'optgroup': true},
27 'optgroup': {'optgroup': true},
28 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
29 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
30 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
31 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
32 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
33 'rp': {'rp': true, 'rt': true},
34 'rt': {'rp': true, 'rt': true},
35 'tbody': {'tbody': true, 'tfoot': true},
36 'td': {'td': true, 'th': true},
37 'tfoot': {'tbody': true},
38 'th': {'td': true, 'th': true},
39 'thead': {'tbody': true, 'tfoot': true},
40 'tr': {'tr': true}
41 },
42 doNotIndent: {"pre": true},
43 allowUnquoted: true,
44 allowMissing: true,
45 caseFold: true
46 }
19 47
20 var Kludges = parserConfig.htmlMode ? {
21 autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
22 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
23 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
24 'track': true, 'wbr': true, 'menuitem': true},
25 implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
26 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
27 'th': true, 'tr': true},
28 contextGrabbers: {
29 'dd': {'dd': true, 'dt': true},
30 'dt': {'dd': true, 'dt': true},
31 'li': {'li': true},
32 'option': {'option': true, 'optgroup': true},
33 'optgroup': {'optgroup': true},
34 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
35 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
36 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
37 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
38 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
39 'rp': {'rp': true, 'rt': true},
40 'rt': {'rp': true, 'rt': true},
41 'tbody': {'tbody': true, 'tfoot': true},
42 'td': {'td': true, 'th': true},
43 'tfoot': {'tbody': true},
44 'th': {'td': true, 'th': true},
45 'thead': {'tbody': true, 'tfoot': true},
46 'tr': {'tr': true}
47 },
48 doNotIndent: {"pre": true},
49 allowUnquoted: true,
50 allowMissing: true,
51 caseFold: true
52 } : {
53 autoSelfClosers: {},
54 implicitlyClosed: {},
55 contextGrabbers: {},
56 doNotIndent: {},
57 allowUnquoted: false,
58 allowMissing: false,
59 caseFold: false
60 };
61 var alignCDATA = parserConfig.alignCDATA;
48 var xmlConfig = {
49 autoSelfClosers: {},
50 implicitlyClosed: {},
51 contextGrabbers: {},
52 doNotIndent: {},
53 allowUnquoted: false,
54 allowMissing: false,
55 caseFold: false
56 }
57
58 CodeMirror.defineMode("xml", function(editorConf, config_) {
59 var indentUnit = editorConf.indentUnit
60 var config = {}
61 var defaults = config_.htmlMode ? htmlConfig : xmlConfig
62 for (var prop in defaults) config[prop] = defaults[prop]
63 for (var prop in config_) config[prop] = config_[prop]
62 64
63 65 // Return variables for tokenizers
64 66 var type, setStyle;
@@ -109,6 +111,7 b' CodeMirror.defineMode("xml", function(co'
109 111 return null;
110 112 }
111 113 }
114 inText.isInText = true;
112 115
113 116 function inTag(stream, state) {
114 117 var ch = stream.next();
@@ -187,7 +190,7 b' CodeMirror.defineMode("xml", function(co'
187 190 this.tagName = tagName;
188 191 this.indent = state.indented;
189 192 this.startOfLine = startOfLine;
190 if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
193 if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
191 194 this.noIndent = true;
192 195 }
193 196 function popContext(state) {
@@ -200,8 +203,8 b' CodeMirror.defineMode("xml", function(co'
200 203 return;
201 204 }
202 205 parentTagName = state.context.tagName;
203 if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
204 !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
206 if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
207 !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
205 208 return;
206 209 }
207 210 popContext(state);
@@ -232,7 +235,7 b' CodeMirror.defineMode("xml", function(co'
232 235 if (type == "word") {
233 236 var tagName = stream.current();
234 237 if (state.context && state.context.tagName != tagName &&
235 Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
238 config.implicitlyClosed.hasOwnProperty(state.context.tagName))
236 239 popContext(state);
237 240 if (state.context && state.context.tagName == tagName) {
238 241 setStyle = "tag";
@@ -268,7 +271,7 b' CodeMirror.defineMode("xml", function(co'
268 271 var tagName = state.tagName, tagStart = state.tagStart;
269 272 state.tagName = state.tagStart = null;
270 273 if (type == "selfcloseTag" ||
271 Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
274 config.autoSelfClosers.hasOwnProperty(tagName)) {
272 275 maybePopContext(state, tagName);
273 276 } else {
274 277 maybePopContext(state, tagName);
@@ -281,12 +284,12 b' CodeMirror.defineMode("xml", function(co'
281 284 }
282 285 function attrEqState(type, stream, state) {
283 286 if (type == "equals") return attrValueState;
284 if (!Kludges.allowMissing) setStyle = "error";
287 if (!config.allowMissing) setStyle = "error";
285 288 return attrState(type, stream, state);
286 289 }
287 290 function attrValueState(type, stream, state) {
288 291 if (type == "string") return attrContinuedState;
289 if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
292 if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
290 293 setStyle = "error";
291 294 return attrState(type, stream, state);
292 295 }
@@ -296,12 +299,14 b' CodeMirror.defineMode("xml", function(co'
296 299 }
297 300
298 301 return {
299 startState: function() {
300 return {tokenize: inText,
301 state: baseState,
302 indented: 0,
303 tagName: null, tagStart: null,
304 context: null};
302 startState: function(baseIndent) {
303 var state = {tokenize: inText,
304 state: baseState,
305 indented: baseIndent || 0,
306 tagName: null, tagStart: null,
307 context: null}
308 if (baseIndent != null) state.baseIndent = baseIndent
309 return state
305 310 },
306 311
307 312 token: function(stream, state) {
@@ -334,19 +339,19 b' CodeMirror.defineMode("xml", function(co'
334 339 return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
335 340 // Indent the starts of attribute names.
336 341 if (state.tagName) {
337 if (multilineTagIndentPastTag)
342 if (config.multilineTagIndentPastTag !== false)
338 343 return state.tagStart + state.tagName.length + 2;
339 344 else
340 return state.tagStart + indentUnit * multilineTagIndentFactor;
345 return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
341 346 }
342 if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
347 if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
343 348 var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
344 349 if (tagAfter && tagAfter[1]) { // Closing tag spotted
345 350 while (context) {
346 351 if (context.tagName == tagAfter[2]) {
347 352 context = context.prev;
348 353 break;
349 } else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
354 } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
350 355 context = context.prev;
351 356 } else {
352 357 break;
@@ -354,25 +359,30 b' CodeMirror.defineMode("xml", function(co'
354 359 }
355 360 } else if (tagAfter) { // Opening tag spotted
356 361 while (context) {
357 var grabbers = Kludges.contextGrabbers[context.tagName];
362 var grabbers = config.contextGrabbers[context.tagName];
358 363 if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
359 364 context = context.prev;
360 365 else
361 366 break;
362 367 }
363 368 }
364 while (context && !context.startOfLine)
369 while (context && context.prev && !context.startOfLine)
365 370 context = context.prev;
366 371 if (context) return context.indent + indentUnit;
367 else return 0;
372 else return state.baseIndent || 0;
368 373 },
369 374
370 375 electricInput: /<\/[\s\w:]+>$/,
371 376 blockCommentStart: "<!--",
372 377 blockCommentEnd: "-->",
373 378
374 configuration: parserConfig.htmlMode ? "html" : "xml",
375 helperType: parserConfig.htmlMode ? "html" : "xml"
379 configuration: config.htmlMode ? "html" : "xml",
380 helperType: config.htmlMode ? "html" : "xml",
381
382 skipAttribute: function(state) {
383 if (state.state == attrValueState)
384 state.state = attrState
385 }
376 386 };
377 387 });
378 388
This diff has been collapsed as it changes many lines, (573 lines changed) Show them Hide them
@@ -13,7 +13,7 b''
13 13 else if (typeof define == "function" && define.amd) // AMD
14 14 return define([], mod);
15 15 else // Plain browser env
16 this.CodeMirror = mod();
16 (this || window).CodeMirror = mod();
17 17 })(function() {
18 18 "use strict";
19 19
@@ -21,27 +21,29 b''
21 21
22 22 // Kludges for bugs and behavior differences that can't be feature
23 23 // detected are enabled based on userAgent etc sniffing.
24
25 var gecko = /gecko\/\d/i.test(navigator.userAgent);
26 var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
27 var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
24 var userAgent = navigator.userAgent;
25 var platform = navigator.platform;
26
27 var gecko = /gecko\/\d/i.test(userAgent);
28 var ie_upto10 = /MSIE \d/.test(userAgent);
29 var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
28 30 var ie = ie_upto10 || ie_11up;
29 31 var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]);
30 var webkit = /WebKit\//.test(navigator.userAgent);
31 var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent);
32 var chrome = /Chrome\//.test(navigator.userAgent);
33 var presto = /Opera\//.test(navigator.userAgent);
32 var webkit = /WebKit\//.test(userAgent);
33 var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
34 var chrome = /Chrome\//.test(userAgent);
35 var presto = /Opera\//.test(userAgent);
34 36 var safari = /Apple Computer/.test(navigator.vendor);
35 var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(navigator.userAgent);
36 var phantom = /PhantomJS/.test(navigator.userAgent);
37
38 var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent);
37 var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
38 var phantom = /PhantomJS/.test(userAgent);
39
40 var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
39 41 // This is woefully incomplete. Suggestions for alternative methods welcome.
40 var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(navigator.userAgent);
41 var mac = ios || /Mac/.test(navigator.platform);
42 var windows = /win/i.test(navigator.platform);
43
44 var presto_version = presto && navigator.userAgent.match(/Version\/(\d*\.\d*)/);
42 var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
43 var mac = ios || /Mac/.test(platform);
44 var windows = /win/i.test(platform);
45
46 var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
45 47 if (presto_version) presto_version = Number(presto_version[1]);
46 48 if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
47 49 // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
@@ -65,7 +67,7 b''
65 67 setGuttersForLineNumbers(options);
66 68
67 69 var doc = options.value;
68 if (typeof doc == "string") doc = new Doc(doc, options.mode);
70 if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator);
69 71 this.doc = doc;
70 72
71 73 var input = new CodeMirror.inputStyles[options.inputStyle](this);
@@ -87,6 +89,7 b''
87 89 focused: false,
88 90 suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
89 91 pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
92 selectingText: false,
90 93 draggingText: false,
91 94 highlight: new Delayed(), // stores highlight worker timeout
92 95 keySeq: null, // Unfinished key sequence
@@ -407,7 +410,7 b''
407 410 if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal");
408 411 });
409 412
410 this.checkedOverlay = false;
413 this.checkedZeroWidth = false;
411 414 // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
412 415 if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px";
413 416 }
@@ -442,29 +445,43 b''
442 445 this.horiz.firstChild.style.width = "0";
443 446 }
444 447
445 if (!this.checkedOverlay && measure.clientHeight > 0) {
446 if (sWidth == 0) this.overlayHack();
447 this.checkedOverlay = true;
448 if (!this.checkedZeroWidth && measure.clientHeight > 0) {
449 if (sWidth == 0) this.zeroWidthHack();
450 this.checkedZeroWidth = true;
448 451 }
449 452
450 453 return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0};
451 454 },
452 455 setScrollLeft: function(pos) {
453 456 if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos;
457 if (this.disableHoriz) this.enableZeroWidthBar(this.horiz, this.disableHoriz);
454 458 },
455 459 setScrollTop: function(pos) {
456 460 if (this.vert.scrollTop != pos) this.vert.scrollTop = pos;
457 },
458 overlayHack: function() {
461 if (this.disableVert) this.enableZeroWidthBar(this.vert, this.disableVert);
462 },
463 zeroWidthHack: function() {
459 464 var w = mac && !mac_geMountainLion ? "12px" : "18px";
460 this.horiz.style.minHeight = this.vert.style.minWidth = w;
461 var self = this;
462 var barMouseDown = function(e) {
463 if (e_target(e) != self.vert && e_target(e) != self.horiz)
464 operation(self.cm, onMouseDown)(e);
465 };
466 on(this.vert, "mousedown", barMouseDown);
467 on(this.horiz, "mousedown", barMouseDown);
465 this.horiz.style.height = this.vert.style.width = w;
466 this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
467 this.disableHoriz = new Delayed;
468 this.disableVert = new Delayed;
469 },
470 enableZeroWidthBar: function(bar, delay) {
471 bar.style.pointerEvents = "auto";
472 function maybeDisable() {
473 // To find out whether the scrollbar is still visible, we
474 // check whether the element under the pixel in the bottom
475 // left corner of the scrollbar box is the scrollbar box
476 // itself (when the bar is still visible) or its filler child
477 // (when the bar is hidden). If it is still visible, we keep
478 // it enabled, if it's hidden, we disable pointer events.
479 var box = bar.getBoundingClientRect();
480 var elt = document.elementFromPoint(box.left + 1, box.bottom - 1);
481 if (elt != bar) bar.style.pointerEvents = "none";
482 else delay.set(1000, maybeDisable);
483 }
484 delay.set(1000, maybeDisable);
468 485 },
469 486 clear: function() {
470 487 var parent = this.horiz.parentNode;
@@ -714,7 +731,7 b''
714 731 // width and height.
715 732 removeChildren(display.cursorDiv);
716 733 removeChildren(display.selectionDiv);
717 display.gutters.style.height = 0;
734 display.gutters.style.height = display.sizer.style.minHeight = 0;
718 735
719 736 if (different) {
720 737 display.lastWrapHeight = update.wrapperHeight;
@@ -806,7 +823,7 b''
806 823 // given line.
807 824 function updateWidgetHeight(line) {
808 825 if (line.widgets) for (var i = 0; i < line.widgets.length; ++i)
809 line.widgets[i].height = line.widgets[i].node.offsetHeight;
826 line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight;
810 827 }
811 828
812 829 // Do a bulk-read of the DOM positions and sizes needed to draw the
@@ -955,12 +972,22 b''
955 972 lineView.node.removeChild(lineView.gutter);
956 973 lineView.gutter = null;
957 974 }
975 if (lineView.gutterBackground) {
976 lineView.node.removeChild(lineView.gutterBackground);
977 lineView.gutterBackground = null;
978 }
979 if (lineView.line.gutterClass) {
980 var wrap = ensureLineWrapped(lineView);
981 lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
982 "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
983 "px; width: " + dims.gutterTotalWidth + "px");
984 wrap.insertBefore(lineView.gutterBackground, lineView.text);
985 }
958 986 var markers = lineView.line.gutterMarkers;
959 987 if (cm.options.lineNumbers || markers) {
960 988 var wrap = ensureLineWrapped(lineView);
961 989 var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " +
962 (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) +
963 "px; width: " + dims.gutterTotalWidth + "px");
990 (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px");
964 991 cm.display.input.setUneditable(gutterWrap);
965 992 wrap.insertBefore(gutterWrap, lineView.text);
966 993 if (lineView.line.gutterClass)
@@ -1067,10 +1094,6 b''
1067 1094 if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
1068 1095 }
1069 1096
1070 function isReadOnly(cm) {
1071 return cm.options.readOnly || cm.doc.cantEdit;
1072 }
1073
1074 1097 // This will be set to an array of strings when copying, so that,
1075 1098 // when pasting, we know what kind of selections the copied text
1076 1099 // was made out of.
@@ -1082,13 +1105,18 b''
1082 1105 if (!sel) sel = doc.sel;
1083 1106
1084 1107 var paste = cm.state.pasteIncoming || origin == "paste";
1085 var textLines = splitLines(inserted), multiPaste = null;
1108 var textLines = doc.splitLines(inserted), multiPaste = null;
1086 1109 // When pasing N lines into N selections, insert one line per selection
1087 1110 if (paste && sel.ranges.length > 1) {
1088 if (lastCopied && lastCopied.join("\n") == inserted)
1089 multiPaste = sel.ranges.length % lastCopied.length == 0 && map(lastCopied, splitLines);
1090 else if (textLines.length == sel.ranges.length)
1111 if (lastCopied && lastCopied.join("\n") == inserted) {
1112 if (sel.ranges.length % lastCopied.length == 0) {
1113 multiPaste = [];
1114 for (var i = 0; i < lastCopied.length; i++)
1115 multiPaste.push(doc.splitLines(lastCopied[i]));
1116 }
1117 } else if (textLines.length == sel.ranges.length) {
1091 1118 multiPaste = map(textLines, function(l) { return [l]; });
1119 }
1092 1120 }
1093 1121
1094 1122 // Normal behavior is to insert the new text into every selection
@@ -1120,7 +1148,8 b''
1120 1148 var pasted = e.clipboardData && e.clipboardData.getData("text/plain");
1121 1149 if (pasted) {
1122 1150 e.preventDefault();
1123 runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
1151 if (!cm.isReadOnly() && !cm.options.disableInput)
1152 runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); });
1124 1153 return true;
1125 1154 }
1126 1155 }
@@ -1222,13 +1251,14 b''
1222 1251 });
1223 1252
1224 1253 on(te, "paste", function(e) {
1225 if (handlePaste(e, cm)) return true;
1254 if (signalDOMEvent(cm, e) || handlePaste(e, cm)) return
1226 1255
1227 1256 cm.state.pasteIncoming = true;
1228 1257 input.fastPoll();
1229 1258 });
1230 1259
1231 1260 function prepareCopyCut(e) {
1261 if (signalDOMEvent(cm, e)) return
1232 1262 if (cm.somethingSelected()) {
1233 1263 lastCopied = cm.getSelections();
1234 1264 if (input.inaccurateSelection) {
@@ -1256,7 +1286,7 b''
1256 1286 on(te, "copy", prepareCopyCut);
1257 1287
1258 1288 on(display.scroller, "paste", function(e) {
1259 if (eventInWidget(display, e)) return;
1289 if (eventInWidget(display, e) || signalDOMEvent(cm, e)) return;
1260 1290 cm.state.pasteIncoming = true;
1261 1291 input.focus();
1262 1292 });
@@ -1268,6 +1298,7 b''
1268 1298
1269 1299 on(te, "compositionstart", function() {
1270 1300 var start = cm.getCursor("from");
1301 if (input.composing) input.composing.range.clear()
1271 1302 input.composing = {
1272 1303 start: start,
1273 1304 range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
@@ -1388,8 +1419,8 b''
1388 1419 // will be the case when there is a lot of text in the textarea,
1389 1420 // in which case reading its value would be expensive.
1390 1421 if (this.contextMenuPending || !cm.state.focused ||
1391 (hasSelection(input) && !prevInput) ||
1392 isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq)
1422 (hasSelection(input) && !prevInput && !this.composing) ||
1423 cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
1393 1424 return false;
1394 1425
1395 1426 var text = input.value;
@@ -1516,6 +1547,10 b''
1516 1547 }
1517 1548 },
1518 1549
1550 readOnlyChanged: function(val) {
1551 if (!val) this.reset();
1552 },
1553
1519 1554 setUneditable: nothing,
1520 1555
1521 1556 needsContentAttribute: false
@@ -1534,10 +1569,11 b''
1534 1569 init: function(display) {
1535 1570 var input = this, cm = input.cm;
1536 1571 var div = input.div = display.lineDiv;
1537 div.contentEditable = "true";
1538 1572 disableBrowserMagic(div);
1539 1573
1540 on(div, "paste", function(e) { handlePaste(e, cm); })
1574 on(div, "paste", function(e) {
1575 if (!signalDOMEvent(cm, e)) handlePaste(e, cm);
1576 })
1541 1577
1542 1578 on(div, "compositionstart", function(e) {
1543 1579 var data = e.data;
@@ -1575,11 +1611,12 b''
1575 1611
1576 1612 on(div, "input", function() {
1577 1613 if (input.composing) return;
1578 if (!input.pollContent())
1614 if (cm.isReadOnly() || !input.pollContent())
1579 1615 runInOp(input.cm, function() {regChange(cm);});
1580 1616 });
1581 1617
1582 1618 function onCopyCut(e) {
1619 if (signalDOMEvent(cm, e)) return
1583 1620 if (cm.somethingSelected()) {
1584 1621 lastCopied = cm.getSelections();
1585 1622 if (e.type == "cut") cm.replaceSelection("", null, "cut");
@@ -1655,8 +1692,13 b''
1655 1692 try { var rng = range(start.node, start.offset, end.offset, end.node); }
1656 1693 catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
1657 1694 if (rng) {
1658 sel.removeAllRanges();
1659 sel.addRange(rng);
1695 if (!gecko && this.cm.state.focused) {
1696 sel.collapse(start.node, start.offset);
1697 if (!rng.collapsed) sel.addRange(rng);
1698 } else {
1699 sel.removeAllRanges();
1700 sel.addRange(rng);
1701 }
1660 1702 if (old && sel.anchorNode == null) sel.addRange(old);
1661 1703 else if (gecko) this.startGracePeriod();
1662 1704 }
@@ -1756,7 +1798,7 b''
1756 1798 var toNode = display.view[toIndex + 1].node.previousSibling;
1757 1799 }
1758 1800
1759 var newText = splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
1801 var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
1760 1802 var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
1761 1803 while (newText.length > 1 && oldText.length > 1) {
1762 1804 if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
@@ -1800,17 +1842,24 b''
1800 1842 this.div.focus();
1801 1843 },
1802 1844 applyComposition: function(composing) {
1803 if (composing.data && composing.data != composing.startData)
1845 if (this.cm.isReadOnly())
1846 operation(this.cm, regChange)(this.cm)
1847 else if (composing.data && composing.data != composing.startData)
1804 1848 operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel);
1805 1849 },
1806 1850
1807 1851 setUneditable: function(node) {
1808 node.setAttribute("contenteditable", "false");
1852 node.contentEditable = "false"
1809 1853 },
1810 1854
1811 1855 onKeyPress: function(e) {
1812 1856 e.preventDefault();
1813 operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
1857 if (!this.cm.isReadOnly())
1858 operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0);
1859 },
1860
1861 readOnlyChanged: function(val) {
1862 this.div.contentEditable = String(val != "nocursor")
1814 1863 },
1815 1864
1816 1865 onContextMenu: nothing,
@@ -1912,7 +1961,7 b''
1912 1961 }
1913 1962
1914 1963 function domTextBetween(cm, from, to, fromLine, toLine) {
1915 var text = "", closing = false;
1964 var text = "", closing = false, lineSep = cm.doc.lineSeparator();
1916 1965 function recognizeMarker(id) { return function(marker) { return marker.id == id; }; }
1917 1966 function walk(node) {
1918 1967 if (node.nodeType == 1) {
@@ -1926,7 +1975,7 b''
1926 1975 if (markerID) {
1927 1976 var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
1928 1977 if (found.length && (range = found[0].find()))
1929 text += getBetween(cm.doc, range.from, range.to).join("\n");
1978 text += getBetween(cm.doc, range.from, range.to).join(lineSep);
1930 1979 return;
1931 1980 }
1932 1981 if (node.getAttribute("contenteditable") == "false") return;
@@ -1938,7 +1987,7 b''
1938 1987 var val = node.nodeValue;
1939 1988 if (!val) return;
1940 1989 if (closing) {
1941 text += "\n";
1990 text += lineSep;
1942 1991 closing = false;
1943 1992 }
1944 1993 text += val;
@@ -2110,7 +2159,7 b''
2110 2159
2111 2160 // Give beforeSelectionChange handlers a change to influence a
2112 2161 // selection update.
2113 function filterSelectionChange(doc, sel) {
2162 function filterSelectionChange(doc, sel, options) {
2114 2163 var obj = {
2115 2164 ranges: sel.ranges,
2116 2165 update: function(ranges) {
@@ -2118,7 +2167,8 b''
2118 2167 for (var i = 0; i < ranges.length; i++)
2119 2168 this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
2120 2169 clipPos(doc, ranges[i].head));
2121 }
2170 },
2171 origin: options && options.origin
2122 2172 };
2123 2173 signal(doc, "beforeSelectionChange", doc, obj);
2124 2174 if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj);
@@ -2144,7 +2194,7 b''
2144 2194
2145 2195 function setSelectionNoUndo(doc, sel, options) {
2146 2196 if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
2147 sel = filterSelectionChange(doc, sel);
2197 sel = filterSelectionChange(doc, sel, options);
2148 2198
2149 2199 var bias = options && options.bias ||
2150 2200 (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
@@ -2178,8 +2228,9 b''
2178 2228 var out;
2179 2229 for (var i = 0; i < sel.ranges.length; i++) {
2180 2230 var range = sel.ranges[i];
2181 var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear);
2182 var newHead = skipAtomic(doc, range.head, bias, mayClear);
2231 var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
2232 var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
2233 var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
2183 2234 if (out || newAnchor != range.anchor || newHead != range.head) {
2184 2235 if (!out) out = sel.ranges.slice(0, i);
2185 2236 out[i] = new Range(newAnchor, newHead);
@@ -2188,54 +2239,59 b''
2188 2239 return out ? normalizeSelection(out, sel.primIndex) : sel;
2189 2240 }
2190 2241
2191 // Ensure a given position is not inside an atomic range.
2192 function skipAtomic(doc, pos, bias, mayClear) {
2193 var flipped = false, curPos = pos;
2194 var dir = bias || 1;
2195 doc.cantEdit = false;
2196 search: for (;;) {
2197 var line = getLine(doc, curPos.line);
2198 if (line.markedSpans) {
2199 for (var i = 0; i < line.markedSpans.length; ++i) {
2200 var sp = line.markedSpans[i], m = sp.marker;
2201 if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) &&
2202 (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) {
2203 if (mayClear) {
2204 signal(m, "beforeCursorEnter");
2205 if (m.explicitlyCleared) {
2206 if (!line.markedSpans) break;
2207 else {--i; continue;}
2208 }
2209 }
2210 if (!m.atomic) continue;
2211 var newPos = m.find(dir < 0 ? -1 : 1);
2212 if (cmp(newPos, curPos) == 0) {
2213 newPos.ch += dir;
2214 if (newPos.ch < 0) {
2215 if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1));
2216 else newPos = null;
2217 } else if (newPos.ch > line.text.length) {
2218 if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0);
2219 else newPos = null;
2220 }
2221 if (!newPos) {
2222 if (flipped) {
2223 // Driven in a corner -- no valid cursor position found at all
2224 // -- try again *with* clearing, if we didn't already
2225 if (!mayClear) return skipAtomic(doc, pos, bias, true);
2226 // Otherwise, turn off editing until further notice, and return the start of the doc
2227 doc.cantEdit = true;
2228 return Pos(doc.first, 0);
2229 }
2230 flipped = true; newPos = pos; dir = -dir;
2231 }
2232 }
2233 curPos = newPos;
2234 continue search;
2242 function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
2243 var line = getLine(doc, pos.line);
2244 if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) {
2245 var sp = line.markedSpans[i], m = sp.marker;
2246 if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
2247 (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
2248 if (mayClear) {
2249 signal(m, "beforeCursorEnter");
2250 if (m.explicitlyCleared) {
2251 if (!line.markedSpans) break;
2252 else {--i; continue;}
2235 2253 }
2236 2254 }
2237 }
2238 return curPos;
2255 if (!m.atomic) continue;
2256
2257 if (oldPos) {
2258 var near = m.find(dir < 0 ? 1 : -1), diff;
2259 if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) near = movePos(doc, near, -dir, line);
2260 if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
2261 return skipAtomicInner(doc, near, pos, dir, mayClear);
2262 }
2263
2264 var far = m.find(dir < 0 ? -1 : 1);
2265 if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) far = movePos(doc, far, dir, line);
2266 return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null;
2267 }
2268 }
2269 return pos;
2270 }
2271
2272 // Ensure a given position is not inside an atomic range.
2273 function skipAtomic(doc, pos, oldPos, bias, mayClear) {
2274 var dir = bias || 1;
2275 var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
2276 (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
2277 skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
2278 (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
2279 if (!found) {
2280 doc.cantEdit = true;
2281 return Pos(doc.first, 0);
2282 }
2283 return found;
2284 }
2285
2286 function movePos(doc, pos, dir, line) {
2287 if (dir < 0 && pos.ch == 0) {
2288 if (pos.line > doc.first) return clipPos(doc, Pos(pos.line - 1));
2289 else return null;
2290 } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
2291 if (pos.line < doc.first + doc.size - 1) return Pos(pos.line + 1, 0);
2292 else return null;
2293 } else {
2294 return new Pos(pos.line, pos.ch + dir);
2239 2295 }
2240 2296 }
2241 2297
@@ -2255,7 +2311,7 b''
2255 2311 var range = doc.sel.ranges[i];
2256 2312 var collapsed = range.empty();
2257 2313 if (collapsed || cm.options.showCursorWhenSelecting)
2258 drawSelectionCursor(cm, range, curFragment);
2314 drawSelectionCursor(cm, range.head, curFragment);
2259 2315 if (!collapsed)
2260 2316 drawSelectionRange(cm, range, selFragment);
2261 2317 }
@@ -2263,8 +2319,8 b''
2263 2319 }
2264 2320
2265 2321 // Draws a cursor for the given range
2266 function drawSelectionCursor(cm, range, output) {
2267 var pos = cursorCoords(cm, range.head, "div", null, null, !cm.options.singleCursorHeightPerLine);
2322 function drawSelectionCursor(cm, head, output) {
2323 var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
2268 2324
2269 2325 var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
2270 2326 cursor.style.left = pos.left + "px";
@@ -2388,8 +2444,8 b''
2388 2444
2389 2445 doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) {
2390 2446 if (doc.frontier >= cm.display.viewFrom) { // Visible
2391 var oldStyles = line.styles;
2392 var highlighted = highlightLine(cm, line, state, true);
2447 var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength;
2448 var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true);
2393 2449 line.styles = highlighted.styles;
2394 2450 var oldCls = line.styleClasses, newCls = highlighted.classes;
2395 2451 if (newCls) line.styleClasses = newCls;
@@ -2398,9 +2454,10 b''
2398 2454 oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
2399 2455 for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i];
2400 2456 if (ischange) changedLines.push(doc.frontier);
2401 line.stateAfter = copyState(doc.mode, state);
2457 line.stateAfter = tooLong ? state : copyState(doc.mode, state);
2402 2458 } else {
2403 processLine(cm, line.text, state);
2459 if (line.text.length <= cm.options.maxHighlightLength)
2460 processLine(cm, line.text, state);
2404 2461 line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null;
2405 2462 }
2406 2463 ++doc.frontier;
@@ -2545,10 +2602,12 b''
2545 2602 function prepareMeasureForLine(cm, line) {
2546 2603 var lineN = lineNo(line);
2547 2604 var view = findViewForLine(cm, lineN);
2548 if (view && !view.text)
2605 if (view && !view.text) {
2549 2606 view = null;
2550 else if (view && view.changes)
2607 } else if (view && view.changes) {
2551 2608 updateLineForChanges(cm, view, lineN, getDimensions(cm));
2609 cm.curOp.forceUpdate = true;
2610 }
2552 2611 if (!view)
2553 2612 view = updateExternalMeasurement(cm, line);
2554 2613
@@ -2961,12 +3020,12 b''
2961 3020 var callbacks = group.delayedCallbacks, i = 0;
2962 3021 do {
2963 3022 for (; i < callbacks.length; i++)
2964 callbacks[i]();
3023 callbacks[i].call(null);
2965 3024 for (var j = 0; j < group.ops.length; j++) {
2966 3025 var op = group.ops[j];
2967 3026 if (op.cursorActivityHandlers)
2968 3027 while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
2969 op.cursorActivityHandlers[op.cursorActivityCalled++](op.cm);
3028 op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm);
2970 3029 }
2971 3030 } while (i < callbacks.length);
2972 3031 }
@@ -3060,7 +3119,8 b''
3060 3119
3061 3120 if (cm.state.focused && op.updateInput)
3062 3121 cm.display.input.reset(op.typing);
3063 if (op.focus && op.focus == activeElt()) ensureFocus(op.cm);
3122 if (op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()))
3123 ensureFocus(op.cm);
3064 3124 }
3065 3125
3066 3126 function endOperation_finish(op) {
@@ -3375,7 +3435,7 b''
3375 3435 return dx * dx + dy * dy > 20 * 20;
3376 3436 }
3377 3437 on(d.scroller, "touchstart", function(e) {
3378 if (!isMouseLikeTouchEvent(e)) {
3438 if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
3379 3439 clearTimeout(touchFinished);
3380 3440 var now = +new Date;
3381 3441 d.activeTouch = {start: now, moved: false,
@@ -3426,9 +3486,11 b''
3426 3486 on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
3427 3487
3428 3488 d.dragFunctions = {
3429 simple: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
3489 enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);},
3490 over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
3430 3491 start: function(e){onDragStart(cm, e);},
3431 drop: operation(cm, onDrop)
3492 drop: operation(cm, onDrop),
3493 leave: function() {clearDragCursor(cm);}
3432 3494 };
3433 3495
3434 3496 var inp = d.input.getField();
@@ -3445,8 +3507,9 b''
3445 3507 var funcs = cm.display.dragFunctions;
3446 3508 var toggle = value ? on : off;
3447 3509 toggle(cm.display.scroller, "dragstart", funcs.start);
3448 toggle(cm.display.scroller, "dragenter", funcs.simple);
3449 toggle(cm.display.scroller, "dragover", funcs.simple);
3510 toggle(cm.display.scroller, "dragenter", funcs.enter);
3511 toggle(cm.display.scroller, "dragover", funcs.over);
3512 toggle(cm.display.scroller, "dragleave", funcs.leave);
3450 3513 toggle(cm.display.scroller, "drop", funcs.drop);
3451 3514 }
3452 3515 }
@@ -3501,7 +3564,7 b''
3501 3564 // not interfere with, such as a scrollbar or widget.
3502 3565 function onMouseDown(e) {
3503 3566 var cm = this, display = cm.display;
3504 if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return;
3567 if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) return;
3505 3568 display.shift = e.shiftKey;
3506 3569
3507 3570 if (eventInWidget(display, e)) {
@@ -3519,7 +3582,10 b''
3519 3582
3520 3583 switch (e_button(e)) {
3521 3584 case 1:
3522 if (start)
3585 // #3261: make sure, that we're not starting a second selection
3586 if (cm.state.selectingText)
3587 cm.state.selectingText(e);
3588 else if (start)
3523 3589 leftButtonDown(cm, e, start);
3524 3590 else if (e_target(e) == display.scroller)
3525 3591 e_preventDefault(e);
@@ -3554,7 +3620,7 b''
3554 3620 }
3555 3621
3556 3622 var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained;
3557 if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) &&
3623 if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
3558 3624 type == "single" && (contained = sel.contains(start)) > -1 &&
3559 3625 (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
3560 3626 (cmp(contained.to(), start) > 0 || start.xRel < 0))
@@ -3639,7 +3705,8 b''
3639 3705 setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
3640 3706 {scroll: false, origin: "*mouse"});
3641 3707 } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
3642 setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0));
3708 setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
3709 {scroll: false, origin: "*mouse"});
3643 3710 startSel = doc.sel;
3644 3711 } else {
3645 3712 replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
@@ -3717,6 +3784,7 b''
3717 3784 }
3718 3785
3719 3786 function done(e) {
3787 cm.state.selectingText = false;
3720 3788 counter = Infinity;
3721 3789 e_preventDefault(e);
3722 3790 display.input.focus();
@@ -3730,13 +3798,14 b''
3730 3798 else extend(e);
3731 3799 });
3732 3800 var up = operation(cm, done);
3801 cm.state.selectingText = up;
3733 3802 on(document, "mousemove", move);
3734 3803 on(document, "mouseup", up);
3735 3804 }
3736 3805
3737 3806 // Determines whether an event happened in the gutter, and fires the
3738 3807 // handlers for the corresponding event.
3739 function gutterEvent(cm, e, type, prevent, signalfn) {
3808 function gutterEvent(cm, e, type, prevent) {
3740 3809 try { var mX = e.clientX, mY = e.clientY; }
3741 3810 catch(e) { return false; }
3742 3811 if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false;
@@ -3753,14 +3822,14 b''
3753 3822 if (g && g.getBoundingClientRect().right >= mX) {
3754 3823 var line = lineAtHeight(cm.doc, mY);
3755 3824 var gutter = cm.options.gutters[i];
3756 signalfn(cm, type, cm, line, gutter, e);
3825 signal(cm, type, cm, line, gutter, e);
3757 3826 return e_defaultPrevented(e);
3758 3827 }
3759 3828 }
3760 3829 }
3761 3830
3762 3831 function clickInGutter(cm, e) {
3763 return gutterEvent(cm, e, "gutterClick", true, signalLater);
3832 return gutterEvent(cm, e, "gutterClick", true);
3764 3833 }
3765 3834
3766 3835 // Kludge to work around strange IE behavior where it'll sometimes
@@ -3769,23 +3838,32 b''
3769 3838
3770 3839 function onDrop(e) {
3771 3840 var cm = this;
3841 clearDragCursor(cm);
3772 3842 if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
3773 3843 return;
3774 3844 e_preventDefault(e);
3775 3845 if (ie) lastDrop = +new Date;
3776 3846 var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
3777 if (!pos || isReadOnly(cm)) return;
3847 if (!pos || cm.isReadOnly()) return;
3778 3848 // Might be a file drop, in which case we simply extract the text
3779 3849 // and insert it.
3780 3850 if (files && files.length && window.FileReader && window.File) {
3781 3851 var n = files.length, text = Array(n), read = 0;
3782 3852 var loadFile = function(file, i) {
3853 if (cm.options.allowDropFileTypes &&
3854 indexOf(cm.options.allowDropFileTypes, file.type) == -1)
3855 return;
3856
3783 3857 var reader = new FileReader;
3784 3858 reader.onload = operation(cm, function() {
3785 text[i] = reader.result;
3859 var content = reader.result;
3860 if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = "";
3861 text[i] = content;
3786 3862 if (++read == n) {
3787 3863 pos = clipPos(cm.doc, pos);
3788 var change = {from: pos, to: pos, text: splitLines(text.join("\n")), origin: "paste"};
3864 var change = {from: pos, to: pos,
3865 text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
3866 origin: "paste"};
3789 3867 makeChange(cm.doc, change);
3790 3868 setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)));
3791 3869 }
@@ -3839,6 +3917,25 b''
3839 3917 }
3840 3918 }
3841 3919
3920 function onDragOver(cm, e) {
3921 var pos = posFromMouse(cm, e);
3922 if (!pos) return;
3923 var frag = document.createDocumentFragment();
3924 drawSelectionCursor(cm, pos, frag);
3925 if (!cm.display.dragCursor) {
3926 cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
3927 cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
3928 }
3929 removeChildrenAndAdd(cm.display.dragCursor, frag);
3930 }
3931
3932 function clearDragCursor(cm) {
3933 if (cm.display.dragCursor) {
3934 cm.display.lineSpace.removeChild(cm.display.dragCursor);
3935 cm.display.dragCursor = null;
3936 }
3937 }
3938
3842 3939 // SCROLL EVENTS
3843 3940
3844 3941 // Sync the scrollable area and scrollbars, ensure the viewport
@@ -3903,8 +4000,9 b''
3903 4000
3904 4001 var display = cm.display, scroll = display.scroller;
3905 4002 // Quit if there's nothing to scroll here
3906 if (!(dx && scroll.scrollWidth > scroll.clientWidth ||
3907 dy && scroll.scrollHeight > scroll.clientHeight)) return;
4003 var canScrollX = scroll.scrollWidth > scroll.clientWidth;
4004 var canScrollY = scroll.scrollHeight > scroll.clientHeight;
4005 if (!(dx && canScrollX || dy && canScrollY)) return;
3908 4006
3909 4007 // Webkit browsers on OS X abort momentum scrolls when the target
3910 4008 // of the scroll event is removed from the scrollable element.
@@ -3928,10 +4026,15 b''
3928 4026 // scrolling entirely here. It'll be slightly off from native, but
3929 4027 // better than glitching out.
3930 4028 if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
3931 if (dy)
4029 if (dy && canScrollY)
3932 4030 setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight)));
3933 4031 setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)));
3934 e_preventDefault(e);
4032 // Only prevent default scrolling if vertical scrolling is
4033 // actually possible. Otherwise, it causes vertical scroll
4034 // jitter on OSX trackpads when deltaX is small and deltaY
4035 // is large (issue #3579)
4036 if (!dy || (dy && canScrollY))
4037 e_preventDefault(e);
3935 4038 display.wheelStartX = null; // Abort measurement, if in progress
3936 4039 return;
3937 4040 }
@@ -3980,7 +4083,7 b''
3980 4083 cm.display.input.ensurePolled();
3981 4084 var prevShift = cm.display.shift, done = false;
3982 4085 try {
3983 if (isReadOnly(cm)) cm.state.suppressEdits = true;
4086 if (cm.isReadOnly()) cm.state.suppressEdits = true;
3984 4087 if (dropShift) cm.display.shift = false;
3985 4088 done = bound(cm) != Pass;
3986 4089 } finally {
@@ -4159,12 +4262,13 b''
4159 4262 // right-click take effect on it.
4160 4263 function onContextMenu(cm, e) {
4161 4264 if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return;
4265 if (signalDOMEvent(cm, e, "contextmenu")) return;
4162 4266 cm.display.input.onContextMenu(e);
4163 4267 }
4164 4268
4165 4269 function contextMenuInGutter(cm, e) {
4166 4270 if (!hasHandler(cm, "gutterContextMenu")) return false;
4167 return gutterEvent(cm, e, "gutterContextMenu", false, signal);
4271 return gutterEvent(cm, e, "gutterContextMenu", false);
4168 4272 }
4169 4273
4170 4274 // UPDATING
@@ -4468,7 +4572,7 b''
4468 4572 function replaceRange(doc, code, from, to, origin) {
4469 4573 if (!to) to = from;
4470 4574 if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; }
4471 if (typeof code == "string") code = splitLines(code);
4575 if (typeof code == "string") code = doc.splitLines(code);
4472 4576 makeChange(doc, {from: from, to: to, text: code, origin: origin});
4473 4577 }
4474 4578
@@ -4712,10 +4816,9 b''
4712 4816 function findPosH(doc, pos, dir, unit, visually) {
4713 4817 var line = pos.line, ch = pos.ch, origDir = dir;
4714 4818 var lineObj = getLine(doc, line);
4715 var possible = true;
4716 4819 function findNextLine() {
4717 4820 var l = line + dir;
4718 if (l < doc.first || l >= doc.first + doc.size) return (possible = false);
4821 if (l < doc.first || l >= doc.first + doc.size) return false
4719 4822 line = l;
4720 4823 return lineObj = getLine(doc, l);
4721 4824 }
@@ -4725,14 +4828,16 b''
4725 4828 if (!boundToLine && findNextLine()) {
4726 4829 if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj);
4727 4830 else ch = dir < 0 ? lineObj.text.length : 0;
4728 } else return (possible = false);
4831 } else return false
4729 4832 } else ch = next;
4730 4833 return true;
4731 4834 }
4732 4835
4733 if (unit == "char") moveOnce();
4734 else if (unit == "column") moveOnce(true);
4735 else if (unit == "word" || unit == "group") {
4836 if (unit == "char") {
4837 moveOnce()
4838 } else if (unit == "column") {
4839 moveOnce(true)
4840 } else if (unit == "word" || unit == "group") {
4736 4841 var sawType = null, group = unit == "group";
4737 4842 var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
4738 4843 for (var first = true;; first = false) {
@@ -4752,8 +4857,8 b''
4752 4857 if (dir > 0 && !moveOnce(!first)) break;
4753 4858 }
4754 4859 }
4755 var result = skipAtomic(doc, Pos(line, ch), origDir, true);
4756 if (!possible) result.hitSide = true;
4860 var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true);
4861 if (!cmp(pos, result)) result.hitSide = true;
4757 4862 return result;
4758 4863 }
4759 4864
@@ -5045,7 +5150,7 b''
5045 5150
5046 5151 execCommand: function(cmd) {
5047 5152 if (commands.hasOwnProperty(cmd))
5048 return commands[cmd](this);
5153 return commands[cmd].call(null, this);
5049 5154 },
5050 5155
5051 5156 triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
@@ -5140,6 +5245,7 b''
5140 5245 signal(this, "overwriteToggle", this, this.state.overwrite);
5141 5246 },
5142 5247 hasFocus: function() { return this.display.input.getField() == activeElt(); },
5248 isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit); },
5143 5249
5144 5250 scrollTo: methodOp(function(x, y) {
5145 5251 if (x != null || y != null) resolveScrollToPos(this);
@@ -5263,6 +5369,22 b''
5263 5369 clearCaches(cm);
5264 5370 regChange(cm);
5265 5371 }, true);
5372 option("lineSeparator", null, function(cm, val) {
5373 cm.doc.lineSep = val;
5374 if (!val) return;
5375 var newBreaks = [], lineNo = cm.doc.first;
5376 cm.doc.iter(function(line) {
5377 for (var pos = 0;;) {
5378 var found = line.text.indexOf(val, pos);
5379 if (found == -1) break;
5380 pos = found + val.length;
5381 newBreaks.push(Pos(lineNo, found));
5382 }
5383 lineNo++;
5384 });
5385 for (var i = newBreaks.length - 1; i >= 0; i--)
5386 replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
5387 });
5266 5388 option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) {
5267 5389 cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
5268 5390 if (old != CodeMirror.Init) cm.refresh();
@@ -5321,11 +5443,12 b''
5321 5443 cm.display.disabled = true;
5322 5444 } else {
5323 5445 cm.display.disabled = false;
5324 if (!val) cm.display.input.reset();
5325 }
5446 }
5447 cm.display.input.readOnlyChanged(val)
5326 5448 });
5327 5449 option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true);
5328 5450 option("dragDrop", true, dragDropChanged);
5451 option("allowDropFileTypes", null);
5329 5452
5330 5453 option("cursorBlinkRate", 530);
5331 5454 option("cursorScrollMargin", 0);
@@ -5613,7 +5736,8 b''
5613 5736 } else if (cur.line > cm.doc.first) {
5614 5737 var prev = getLine(cm.doc, cur.line - 1).text;
5615 5738 if (prev)
5616 cm.replaceRange(line.charAt(0) + "\n" + prev.charAt(prev.length - 1),
5739 cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
5740 prev.charAt(prev.length - 1),
5617 5741 Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose");
5618 5742 }
5619 5743 }
@@ -5627,10 +5751,10 b''
5627 5751 var len = cm.listSelections().length;
5628 5752 for (var i = 0; i < len; i++) {
5629 5753 var range = cm.listSelections()[i];
5630 cm.replaceRange("\n", range.anchor, range.head, "+input");
5754 cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input");
5631 5755 cm.indentLine(range.from().line + 1, null, true);
5632 ensureCursorVisible(cm);
5633 5756 }
5757 ensureCursorVisible(cm);
5634 5758 });
5635 5759 },
5636 5760 toggleOverwrite: function(cm) {cm.toggleOverwrite();}
@@ -6558,7 +6682,7 b''
6558 6682 parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;";
6559 6683 removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
6560 6684 }
6561 return widget.height = widget.node.offsetHeight;
6685 return widget.height = widget.node.parentNode.offsetHeight;
6562 6686 }
6563 6687
6564 6688 function addLineWidget(doc, handle, node, options) {
@@ -6747,7 +6871,9 b''
6747 6871
6748 6872 function getLineStyles(cm, line, updateFrontier) {
6749 6873 if (!line.styles || line.styles[0] != cm.state.modeGen) {
6750 var result = highlightLine(cm, line, line.stateAfter = getStateBefore(cm, lineNo(line)));
6874 var state = getStateBefore(cm, lineNo(line));
6875 var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state);
6876 line.stateAfter = state;
6751 6877 line.styles = result.styles;
6752 6878 if (result.classes) line.styleClasses = result.classes;
6753 6879 else if (line.styleClasses) line.styleClasses = null;
@@ -6764,7 +6890,7 b''
6764 6890 var stream = new StringStream(text, cm.options.tabSize);
6765 6891 stream.start = stream.pos = startAt || 0;
6766 6892 if (text == "") callBlankLine(mode, state);
6767 while (!stream.eol() && stream.pos <= cm.options.maxHighlightLength) {
6893 while (!stream.eol()) {
6768 6894 readToken(mode, stream, state);
6769 6895 stream.start = stream.pos;
6770 6896 }
@@ -6791,7 +6917,7 b''
6791 6917 // is needed on Webkit to be able to get line-level bounding
6792 6918 // rectangles for it (in measureChar).
6793 6919 var content = elt("span", null, null, webkit ? "padding-right: .1px" : null);
6794 var builder = {pre: elt("pre", [content]), content: content,
6920 var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
6795 6921 col: 0, pos: 0, cm: cm,
6796 6922 splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")};
6797 6923 lineView.measure = {};
@@ -6881,6 +7007,10 b''
6881 7007 txt.setAttribute("role", "presentation");
6882 7008 txt.setAttribute("cm-text", "\t");
6883 7009 builder.col += tabWidth;
7010 } else if (m[0] == "\r" || m[0] == "\n") {
7011 var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
7012 txt.setAttribute("cm-text", m[0]);
7013 builder.col += 1;
6884 7014 } else {
6885 7015 var txt = builder.cm.options.specialCharPlaceholder(m[0]);
6886 7016 txt.setAttribute("cm-text", m[0]);
@@ -6962,7 +7092,7 b''
6962 7092 if (nextChange == pos) { // Update current marker set
6963 7093 spanStyle = spanEndStyle = spanStartStyle = title = css = "";
6964 7094 collapsed = null; nextChange = Infinity;
6965 var foundBookmarks = [];
7095 var foundBookmarks = [], endStyles
6966 7096 for (var j = 0; j < spans.length; ++j) {
6967 7097 var sp = spans[j], m = sp.marker;
6968 7098 if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
@@ -6973,9 +7103,9 b''
6973 7103 spanEndStyle = "";
6974 7104 }
6975 7105 if (m.className) spanStyle += " " + m.className;
6976 if (m.css) css = m.css;
7106 if (m.css) css = (css ? css + ";" : "") + m.css;
6977 7107 if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle;
6978 if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle;
7108 if (m.endStyle && sp.to == nextChange) (endStyles || (endStyles = [])).push(m.endStyle, sp.to)
6979 7109 if (m.title && !title) title = m.title;
6980 7110 if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
6981 7111 collapsed = sp;
@@ -6983,14 +7113,17 b''
6983 7113 nextChange = sp.from;
6984 7114 }
6985 7115 }
7116 if (endStyles) for (var j = 0; j < endStyles.length; j += 2)
7117 if (endStyles[j + 1] == nextChange) spanEndStyle += " " + endStyles[j]
7118
7119 if (!collapsed || collapsed.from == pos) for (var j = 0; j < foundBookmarks.length; ++j)
7120 buildCollapsedSpan(builder, 0, foundBookmarks[j]);
6986 7121 if (collapsed && (collapsed.from || 0) == pos) {
6987 7122 buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
6988 7123 collapsed.marker, collapsed.from == null);
6989 7124 if (collapsed.to == null) return;
6990 7125 if (collapsed.to == pos) collapsed = false;
6991 7126 }
6992 if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j)
6993 buildCollapsedSpan(builder, 0, foundBookmarks[j]);
6994 7127 }
6995 7128 if (pos >= len) break;
6996 7129
@@ -7226,8 +7359,8 b''
7226 7359 };
7227 7360
7228 7361 var nextDocId = 0;
7229 var Doc = CodeMirror.Doc = function(text, mode, firstLine) {
7230 if (!(this instanceof Doc)) return new Doc(text, mode, firstLine);
7362 var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) {
7363 if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep);
7231 7364 if (firstLine == null) firstLine = 0;
7232 7365
7233 7366 BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
@@ -7241,8 +7374,10 b''
7241 7374 this.history = new History(null);
7242 7375 this.id = ++nextDocId;
7243 7376 this.modeOption = mode;
7244
7245 if (typeof text == "string") text = splitLines(text);
7377 this.lineSep = lineSep;
7378 this.extend = false;
7379
7380 if (typeof text == "string") text = this.splitLines(text);
7246 7381 updateDoc(this, {from: start, to: start, text: text});
7247 7382 setSelection(this, simpleSelection(start), sel_dontScroll);
7248 7383 };
@@ -7272,12 +7407,12 b''
7272 7407 getValue: function(lineSep) {
7273 7408 var lines = getLines(this, this.first, this.first + this.size);
7274 7409 if (lineSep === false) return lines;
7275 return lines.join(lineSep || "\n");
7410 return lines.join(lineSep || this.lineSeparator());
7276 7411 },
7277 7412 setValue: docMethodOp(function(code) {
7278 7413 var top = Pos(this.first, 0), last = this.first + this.size - 1;
7279 7414 makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
7280 text: splitLines(code), origin: "setValue", full: true}, true);
7415 text: this.splitLines(code), origin: "setValue", full: true}, true);
7281 7416 setSelection(this, simpleSelection(top));
7282 7417 }),
7283 7418 replaceRange: function(code, from, to, origin) {
@@ -7288,7 +7423,7 b''
7288 7423 getRange: function(from, to, lineSep) {
7289 7424 var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
7290 7425 if (lineSep === false) return lines;
7291 return lines.join(lineSep || "\n");
7426 return lines.join(lineSep || this.lineSeparator());
7292 7427 },
7293 7428
7294 7429 getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;},
@@ -7328,10 +7463,11 b''
7328 7463 extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
7329 7464 }),
7330 7465 extendSelections: docMethodOp(function(heads, options) {
7331 extendSelections(this, clipPosArray(this, heads, options));
7466 extendSelections(this, clipPosArray(this, heads), options);
7332 7467 }),
7333 7468 extendSelectionsBy: docMethodOp(function(f, options) {
7334 extendSelections(this, map(this.sel.ranges, f), options);
7469 var heads = map(this.sel.ranges, f);
7470 extendSelections(this, clipPosArray(this, heads), options);
7335 7471 }),
7336 7472 setSelections: docMethodOp(function(ranges, primary, options) {
7337 7473 if (!ranges.length) return;
@@ -7354,13 +7490,13 b''
7354 7490 lines = lines ? lines.concat(sel) : sel;
7355 7491 }
7356 7492 if (lineSep === false) return lines;
7357 else return lines.join(lineSep || "\n");
7493 else return lines.join(lineSep || this.lineSeparator());
7358 7494 },
7359 7495 getSelections: function(lineSep) {
7360 7496 var parts = [], ranges = this.sel.ranges;
7361 7497 for (var i = 0; i < ranges.length; i++) {
7362 7498 var sel = getBetween(this, ranges[i].from(), ranges[i].to());
7363 if (lineSep !== false) sel = sel.join(lineSep || "\n");
7499 if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator());
7364 7500 parts[i] = sel;
7365 7501 }
7366 7502 return parts;
@@ -7375,7 +7511,7 b''
7375 7511 var changes = [], sel = this.sel;
7376 7512 for (var i = 0; i < sel.ranges.length; i++) {
7377 7513 var range = sel.ranges[i];
7378 changes[i] = {from: range.from(), to: range.to(), text: splitLines(code[i]), origin: origin};
7514 changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
7379 7515 }
7380 7516 var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
7381 7517 for (var i = changes.length - 1; i >= 0; i--)
@@ -7456,7 +7592,7 b''
7456 7592 removeLineWidget: function(widget) { widget.clear(); },
7457 7593
7458 7594 markText: function(from, to, options) {
7459 return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
7595 return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range");
7460 7596 },
7461 7597 setBookmark: function(pos, options) {
7462 7598 var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
@@ -7525,7 +7661,8 b''
7525 7661 },
7526 7662
7527 7663 copy: function(copyHistory) {
7528 var doc = new Doc(getLines(this, this.first, this.first + this.size), this.modeOption, this.first);
7664 var doc = new Doc(getLines(this, this.first, this.first + this.size),
7665 this.modeOption, this.first, this.lineSep);
7529 7666 doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
7530 7667 doc.sel = this.sel;
7531 7668 doc.extend = false;
@@ -7541,7 +7678,7 b''
7541 7678 var from = this.first, to = this.first + this.size;
7542 7679 if (options.from != null && options.from > from) from = options.from;
7543 7680 if (options.to != null && options.to < to) to = options.to;
7544 var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from);
7681 var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep);
7545 7682 if (options.sharedHist) copy.history = this.history;
7546 7683 (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
7547 7684 copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
@@ -7570,7 +7707,13 b''
7570 7707 iterLinkedDocs: function(f) {linkedDocs(this, f);},
7571 7708
7572 7709 getMode: function() {return this.mode;},
7573 getEditor: function() {return this.cm;}
7710 getEditor: function() {return this.cm;},
7711
7712 splitLines: function(str) {
7713 if (this.lineSep) return str.split(this.lineSep);
7714 return splitLinesAuto(str);
7715 },
7716 lineSeparator: function() { return this.lineSep || "\n"; }
7574 7717 });
7575 7718
7576 7719 // Public alias.
@@ -8010,24 +8153,30 b''
8010 8153 }
8011 8154 };
8012 8155
8156 var noHandlers = []
8157 function getHandlers(emitter, type, copy) {
8158 var arr = emitter._handlers && emitter._handlers[type]
8159 if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers
8160 else return arr || noHandlers
8161 }
8162
8013 8163 var off = CodeMirror.off = function(emitter, type, f) {
8014 8164 if (emitter.removeEventListener)
8015 8165 emitter.removeEventListener(type, f, false);
8016 8166 else if (emitter.detachEvent)
8017 8167 emitter.detachEvent("on" + type, f);
8018 8168 else {
8019 var arr = emitter._handlers && emitter._handlers[type];
8020 if (!arr) return;
8021 for (var i = 0; i < arr.length; ++i)
8022 if (arr[i] == f) { arr.splice(i, 1); break; }
8169 var handlers = getHandlers(emitter, type, false)
8170 for (var i = 0; i < handlers.length; ++i)
8171 if (handlers[i] == f) { handlers.splice(i, 1); break; }
8023 8172 }
8024 8173 };
8025 8174
8026 8175 var signal = CodeMirror.signal = function(emitter, type /*, values...*/) {
8027 var arr = emitter._handlers && emitter._handlers[type];
8028 if (!arr) return;
8176 var handlers = getHandlers(emitter, type, true)
8177 if (!handlers.length) return;
8029 8178 var args = Array.prototype.slice.call(arguments, 2);
8030 for (var i = 0; i < arr.length; ++i) arr[i].apply(null, args);
8179 for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args);
8031 8180 };
8032 8181
8033 8182 var orphanDelayedCallbacks = null;
@@ -8040,8 +8189,8 b''
8040 8189 // them to be executed when the last operation ends, or, if no
8041 8190 // operation is active, when a timeout fires.
8042 8191 function signalLater(emitter, type /*, values...*/) {
8043 var arr = emitter._handlers && emitter._handlers[type];
8044 if (!arr) return;
8192 var arr = getHandlers(emitter, type, false)
8193 if (!arr.length) return;
8045 8194 var args = Array.prototype.slice.call(arguments, 2), list;
8046 8195 if (operationGroup) {
8047 8196 list = operationGroup.delayedCallbacks;
@@ -8081,8 +8230,7 b''
8081 8230 }
8082 8231
8083 8232 function hasHandler(emitter, type) {
8084 var arr = emitter._handlers && emitter._handlers[type];
8085 return arr && arr.length > 0;
8233 return getHandlers(emitter, type).length > 0
8086 8234 }
8087 8235
8088 8236 // Add on and off methods to a constructor's prototype, to make
@@ -8129,7 +8277,7 b''
8129 8277
8130 8278 // The inverse of countColumn -- find the offset that corresponds to
8131 8279 // a particular column.
8132 function findColumn(string, goal, tabSize) {
8280 var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) {
8133 8281 for (var pos = 0, col = 0;;) {
8134 8282 var nextTab = string.indexOf("\t", pos);
8135 8283 if (nextTab == -1) nextTab = string.length;
@@ -8269,7 +8417,12 b''
8269 8417 } while (child = child.parentNode);
8270 8418 };
8271 8419
8272 function activeElt() { return document.activeElement; }
8420 function activeElt() {
8421 var activeElement = document.activeElement;
8422 while (activeElement && activeElement.root && activeElement.root.activeElement)
8423 activeElement = activeElement.root.activeElement;
8424 return activeElement;
8425 }
8273 8426 // Older versions of IE throws unspecified error when touching
8274 8427 // document.activeElement in some cases (during loading, in iframe)
8275 8428 if (ie && ie_version < 11) activeElt = function() {
@@ -8371,7 +8524,7 b''
8371 8524
8372 8525 // See if "".split is the broken IE version, if so, provide an
8373 8526 // alternative way to split lines.
8374 var splitLines = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
8527 var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) {
8375 8528 var pos = 0, result = [], l = string.length;
8376 8529 while (pos <= l) {
8377 8530 var nl = string.indexOf("\n", pos);
@@ -8417,14 +8570,16 b''
8417 8570
8418 8571 // KEY NAMES
8419 8572
8420 var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
8421 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
8422 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
8423 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", 107: "=", 109: "-", 127: "Delete",
8424 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
8425 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
8426 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"};
8427 CodeMirror.keyNames = keyNames;
8573 var keyNames = CodeMirror.keyNames = {
8574 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
8575 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
8576 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
8577 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
8578 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
8579 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
8580 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
8581 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
8582 };
8428 8583 (function() {
8429 8584 // Number keys
8430 8585 for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i);
@@ -8729,7 +8884,7 b''
8729 8884
8730 8885 // THE END
8731 8886
8732 CodeMirror.version = "5.4.0";
8887 CodeMirror.version = "5.11.0";
8733 8888
8734 8889 return CodeMirror;
8735 8890 });
@@ -25,8 +25,18 b''
25 25 };
26 26
27 27 CodeMirror.defineExtension("showHint", function(options) {
28 // We want a single cursor position.
29 if (this.listSelections().length > 1 || this.somethingSelected()) return;
28 options = parseOptions(this, this.getCursor("start"), options);
29 var selections = this.listSelections()
30 if (selections.length > 1) return;
31 // By default, don't allow completion when something is selected.
32 // A hint function can have a `supportsSelection` property to
33 // indicate that it can handle selections.
34 if (this.somethingSelected()) {
35 if (!options.hint.supportsSelection) return;
36 // Don't try with cross-line selections
37 for (var i = 0; i < selections.length; i++)
38 if (selections[i].head.line != selections[i].anchor.line) return;
39 }
30 40
31 41 if (this.state.completionActive) this.state.completionActive.close();
32 42 var completion = this.state.completionActive = new Completion(this, options);
@@ -38,12 +48,12 b''
38 48
39 49 function Completion(cm, options) {
40 50 this.cm = cm;
41 this.options = this.buildOptions(options);
51 this.options = options;
42 52 this.widget = null;
43 53 this.debounce = 0;
44 54 this.tick = 0;
45 this.startPos = this.cm.getCursor();
46 this.startLen = this.cm.getLine(this.startPos.line).length;
55 this.startPos = this.cm.getCursor("start");
56 this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
47 57
48 58 var self = this;
49 59 cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
@@ -99,7 +109,6 b''
99 109
100 110 update: function(first) {
101 111 if (this.tick == null) return;
102 if (this.data) CodeMirror.signal(this.data, "update");
103 112 if (!this.options.hint.async) {
104 113 this.finishUpdate(this.options.hint(this.cm, this.options), first);
105 114 } else {
@@ -111,6 +120,8 b''
111 120 },
112 121
113 122 finishUpdate: function(data, first) {
123 if (this.data) CodeMirror.signal(this.data, "update");
124 if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null;
114 125 this.data = data;
115 126
116 127 var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
@@ -123,20 +134,21 b''
123 134 CodeMirror.signal(data, "shown");
124 135 }
125 136 }
126 },
127
128 buildOptions: function(options) {
129 var editor = this.cm.options.hintOptions;
130 var out = {};
131 for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
132 if (editor) for (var prop in editor)
133 if (editor[prop] !== undefined) out[prop] = editor[prop];
134 if (options) for (var prop in options)
135 if (options[prop] !== undefined) out[prop] = options[prop];
136 return out;
137 137 }
138 138 };
139 139
140 function parseOptions(cm, pos, options) {
141 var editor = cm.options.hintOptions;
142 var out = {};
143 for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
144 if (editor) for (var prop in editor)
145 if (editor[prop] !== undefined) out[prop] = editor[prop];
146 if (options) for (var prop in options)
147 if (options[prop] !== undefined) out[prop] = options[prop];
148 if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
149 return out;
150 }
151
140 152 function getText(completion) {
141 153 if (typeof completion == "string") return completion;
142 154 else return completion.text;
@@ -335,34 +347,79 b''
335 347 }
336 348 };
337 349
338 CodeMirror.registerHelper("hint", "auto", function(cm, options) {
339 var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
350 function applicableHelpers(cm, helpers) {
351 if (!cm.somethingSelected()) return helpers
352 var result = []
353 for (var i = 0; i < helpers.length; i++)
354 if (helpers[i].supportsSelection) result.push(helpers[i])
355 return result
356 }
357
358 function resolveAutoHints(cm, pos) {
359 var helpers = cm.getHelpers(pos, "hint"), words
340 360 if (helpers.length) {
341 for (var i = 0; i < helpers.length; i++) {
342 var cur = helpers[i](cm, options);
343 if (cur && cur.list.length) return cur;
361 var async = false, resolved
362 for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true
363 if (async) {
364 resolved = function(cm, callback, options) {
365 var app = applicableHelpers(cm, helpers)
366 function run(i, result) {
367 if (i == app.length) return callback(null)
368 var helper = app[i]
369 if (helper.async) {
370 helper(cm, function(result) {
371 if (result) callback(result)
372 else run(i + 1)
373 }, options)
374 } else {
375 var result = helper(cm, options)
376 if (result) callback(result)
377 else run(i + 1)
378 }
379 }
380 run(0)
381 }
382 resolved.async = true
383 } else {
384 resolved = function(cm, options) {
385 var app = applicableHelpers(cm, helpers)
386 for (var i = 0; i < app.length; i++) {
387 var cur = app[i](cm, options)
388 if (cur && cur.list.length) return cur
389 }
390 }
344 391 }
392 resolved.supportsSelection = true
393 return resolved
345 394 } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
346 if (words) return CodeMirror.hint.fromList(cm, {words: words});
395 return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
347 396 } else if (CodeMirror.hint.anyword) {
348 return CodeMirror.hint.anyword(cm, options);
397 return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
398 } else {
399 return function() {}
349 400 }
401 }
402
403 CodeMirror.registerHelper("hint", "auto", {
404 resolve: resolveAutoHints
350 405 });
351 406
352 407 CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
353 408 var cur = cm.getCursor(), token = cm.getTokenAt(cur);
409 var to = CodeMirror.Pos(cur.line, token.end);
410 if (token.string && /\w/.test(token.string[token.string.length - 1])) {
411 var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
412 } else {
413 var term = "", from = to;
414 }
354 415 var found = [];
355 416 for (var i = 0; i < options.words.length; i++) {
356 417 var word = options.words[i];
357 if (word.slice(0, token.string.length) == token.string)
418 if (word.slice(0, term.length) == term)
358 419 found.push(word);
359 420 }
360 421
361 if (found.length) return {
362 list: found,
363 from: CodeMirror.Pos(cur.line, token.start),
364 to: CodeMirror.Pos(cur.line, token.end)
365 };
422 if (found.length) return {list: found, from: from, to: to};
366 423 });
367 424
368 425 CodeMirror.commands.autocomplete = CodeMirror.showHint;
@@ -373,7 +430,7 b''
373 430 alignWithWord: true,
374 431 closeCharacters: /[\s()\[\]{};:>,]/,
375 432 closeOnUnfocus: true,
376 completeOnSingleClick: false,
433 completeOnSingleClick: true,
377 434 container: null,
378 435 customKeys: null,
379 436 extraKeys: null
@@ -37,7 +37,9 b''
37 37 var elt = cm.state.placeholder = document.createElement("pre");
38 38 elt.style.cssText = "height: 0; overflow: visible";
39 39 elt.className = "CodeMirror-placeholder";
40 elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
40 var placeHolder = cm.getOption("placeholder")
41 if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
42 elt.appendChild(placeHolder)
41 43 cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
42 44 }
43 45
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now