codemirror-rails 2.22 → 2.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/lib/codemirror/rails/version.rb +2 -2
  2. data/vendor/assets/javascripts/codemirror.js +164 -83
  3. data/vendor/assets/javascripts/codemirror/modes/clojure.js +13 -13
  4. data/vendor/assets/javascripts/codemirror/modes/css.js +1 -1
  5. data/vendor/assets/javascripts/codemirror/modes/htmlmixed.js +1 -1
  6. data/vendor/assets/javascripts/codemirror/modes/javascript.js +3 -3
  7. data/vendor/assets/javascripts/codemirror/modes/less.js +86 -57
  8. data/vendor/assets/javascripts/codemirror/modes/markdown.js +29 -60
  9. data/vendor/assets/javascripts/codemirror/modes/properties.js +17 -11
  10. data/vendor/assets/javascripts/codemirror/modes/smarty.js +148 -0
  11. data/vendor/assets/javascripts/codemirror/modes/stex.js +15 -2
  12. data/vendor/assets/javascripts/codemirror/modes/tiddlywiki.js +41 -31
  13. data/vendor/assets/javascripts/codemirror/modes/vbscript.js +26 -0
  14. data/vendor/assets/javascripts/codemirror/modes/xml.js +2 -1
  15. data/vendor/assets/javascripts/codemirror/modes/xquery.js +448 -0
  16. data/vendor/assets/javascripts/codemirror/utils/closetag.js +174 -0
  17. data/vendor/assets/javascripts/codemirror/utils/foldcode.js +1 -1
  18. data/vendor/assets/javascripts/codemirror/utils/formatting.js +1 -1
  19. data/vendor/assets/javascripts/codemirror/utils/javascript-hint.js +4 -2
  20. data/vendor/assets/javascripts/codemirror/utils/simple-hint.js +6 -0
  21. data/vendor/assets/stylesheets/codemirror.css +2 -0
  22. data/vendor/assets/stylesheets/codemirror/modes/tiddlywiki.css +1 -1
  23. data/vendor/assets/stylesheets/codemirror/themes/eclipse.css +1 -1
  24. data/vendor/assets/stylesheets/codemirror/themes/elegant.css +2 -2
  25. data/vendor/assets/stylesheets/codemirror/themes/lesser-dark.css +45 -0
  26. data/vendor/assets/stylesheets/codemirror/themes/neat.css +3 -3
  27. data/vendor/assets/stylesheets/codemirror/themes/rubyblue.css +1 -1
  28. data/vendor/assets/stylesheets/codemirror/themes/xq-dark.css +46 -0
  29. metadata +10 -6
  30. data/vendor/assets/javascripts/codemirror/modes/rpm-spec.css +0 -5
  31. data/vendor/assets/stylesheets/codemirror/modes/properties.css +0 -3
@@ -1,21 +1,23 @@
1
1
  CodeMirror.defineMode("properties", function() {
2
2
  return {
3
3
  token: function(stream, state) {
4
- var sol = stream.sol();
4
+ var sol = stream.sol() || state.afterSection;
5
5
  var eol = stream.eol();
6
6
 
7
+ state.afterSection = false;
8
+
7
9
  if (sol) {
8
10
  if (state.nextMultiline) {
9
11
  state.inMultiline = true;
10
12
  state.nextMultiline = false;
11
13
  } else {
12
- state.position = "key";
14
+ state.position = "def";
13
15
  }
14
16
  }
15
17
 
16
18
  if (eol && ! state.nextMultiline) {
17
19
  state.inMultiline = false;
18
- state.position = "key";
20
+ state.position = "def";
19
21
  }
20
22
 
21
23
  if (sol) {
@@ -24,16 +26,18 @@ CodeMirror.defineMode("properties", function() {
24
26
 
25
27
  var ch = stream.next();
26
28
 
27
- if (sol && (ch === "#" || ch === "!")) {
29
+ if (sol && (ch === "#" || ch === "!" || ch === ";")) {
28
30
  state.position = "comment";
29
31
  stream.skipToEnd();
30
32
  return "comment";
31
-
33
+ } else if (sol && ch === "[") {
34
+ state.afterSection = true;
35
+ stream.skipTo("]"); stream.eat("]");
36
+ return "header";
32
37
  } else if (ch === "=" || ch === ":") {
33
- state.position = "value";
34
- return "equals";
35
-
36
- } else if (ch === "\\" && state.position === "value") {
38
+ state.position = "quote";
39
+ return null;
40
+ } else if (ch === "\\" && state.position === "quote") {
37
41
  if (stream.next() !== "u") { // u = Unicode sequence \u1234
38
42
  // Multiline value
39
43
  state.nextMultiline = true;
@@ -45,9 +49,10 @@ CodeMirror.defineMode("properties", function() {
45
49
 
46
50
  startState: function() {
47
51
  return {
48
- position : "key", // Current position, "key", "value" or "comment"
52
+ position : "def", // Current position, "def", "quote" or "comment"
49
53
  nextMultiline : false, // Is the next line multiline value
50
- inMultiline : false // Is the current line a multiline value
54
+ inMultiline : false, // Is the current line a multiline value
55
+ afterSection : false // Did we just open a section
51
56
  };
52
57
  }
53
58
 
@@ -55,3 +60,4 @@ CodeMirror.defineMode("properties", function() {
55
60
  });
56
61
 
57
62
  CodeMirror.defineMIME("text/x-properties", "properties");
63
+ CodeMirror.defineMIME("text/x-ini", "properties");
@@ -0,0 +1,148 @@
1
+ CodeMirror.defineMode("smarty", function(config, parserConfig) {
2
+ var keyFuncs = ["debug", "extends", "function", "include", "literal"];
3
+ var last;
4
+ var regs = {
5
+ operatorChars: /[+\-*&%=<>!?]/,
6
+ validIdentifier: /[a-zA-Z0-9\_]/,
7
+ stringChar: /[\'\"]/
8
+ }
9
+ var leftDelim = (typeof config.mode.leftDelimiter != 'undefined') ? config.mode.leftDelimiter : "{";
10
+ var rightDelim = (typeof config.mode.rightDelimiter != 'undefined') ? config.mode.rightDelimiter : "}";
11
+ function ret(style, lst) { last = lst; return style; }
12
+
13
+
14
+ function tokenizer(stream, state) {
15
+ function chain(parser) {
16
+ state.tokenize = parser;
17
+ return parser(stream, state);
18
+ }
19
+
20
+ if (stream.match(leftDelim, true)) {
21
+ if (stream.eat("*")) {
22
+ return chain(inBlock("comment", "*" + rightDelim));
23
+ }
24
+ else {
25
+ state.tokenize = inSmarty;
26
+ return "tag";
27
+ }
28
+ }
29
+ else {
30
+ // I'd like to do an eatWhile() here, but I can't get it to eat only up to the rightDelim string/char
31
+ stream.next();
32
+ return null;
33
+ }
34
+ }
35
+
36
+ function inSmarty(stream, state) {
37
+ if (stream.match(rightDelim, true)) {
38
+ state.tokenize = tokenizer;
39
+ return ret("tag", null);
40
+ }
41
+
42
+ var ch = stream.next();
43
+ if (ch == "$") {
44
+ stream.eatWhile(regs.validIdentifier);
45
+ return ret("variable-2", "variable");
46
+ }
47
+ else if (ch == ".") {
48
+ return ret("operator", "property");
49
+ }
50
+ else if (regs.stringChar.test(ch)) {
51
+ state.tokenize = inAttribute(ch);
52
+ return ret("string", "string");
53
+ }
54
+ else if (regs.operatorChars.test(ch)) {
55
+ stream.eatWhile(regs.operatorChars);
56
+ return ret("operator", "operator");
57
+ }
58
+ else if (ch == "[" || ch == "]") {
59
+ return ret("bracket", "bracket");
60
+ }
61
+ else if (/\d/.test(ch)) {
62
+ stream.eatWhile(/\d/);
63
+ return ret("number", "number");
64
+ }
65
+ else {
66
+ if (state.last == "variable") {
67
+ if (ch == "@") {
68
+ stream.eatWhile(regs.validIdentifier);
69
+ return ret("property", "property");
70
+ }
71
+ else if (ch == "|") {
72
+ stream.eatWhile(regs.validIdentifier);
73
+ return ret("qualifier", "modifier");
74
+ }
75
+ }
76
+ else if (state.last == "whitespace") {
77
+ stream.eatWhile(regs.validIdentifier);
78
+ return ret("attribute", "modifier");
79
+ }
80
+ else if (state.last == "property") {
81
+ stream.eatWhile(regs.validIdentifier);
82
+ return ret("property", null);
83
+ }
84
+ else if (/\s/.test(ch)) {
85
+ last = "whitespace";
86
+ return null;
87
+ }
88
+
89
+ var str = "";
90
+ if (ch != "/") {
91
+ str += ch;
92
+ }
93
+ var c = "";
94
+ while ((c = stream.eat(regs.validIdentifier))) {
95
+ str += c;
96
+ }
97
+ var i, j;
98
+ for (i=0, j=keyFuncs.length; i<j; i++) {
99
+ if (keyFuncs[i] == str) {
100
+ return ret("keyword", "keyword");
101
+ }
102
+ }
103
+ if (/\s/.test(ch)) {
104
+ return null;
105
+ }
106
+ return ret("tag", "tag");
107
+ }
108
+ }
109
+
110
+ function inAttribute(quote) {
111
+ return function(stream, state) {
112
+ while (!stream.eol()) {
113
+ if (stream.next() == quote) {
114
+ state.tokenize = inSmarty;
115
+ break;
116
+ }
117
+ }
118
+ return "string";
119
+ };
120
+ }
121
+
122
+ function inBlock(style, terminator) {
123
+ return function(stream, state) {
124
+ while (!stream.eol()) {
125
+ if (stream.match(terminator)) {
126
+ state.tokenize = tokenizer;
127
+ break;
128
+ }
129
+ stream.next();
130
+ }
131
+ return style;
132
+ };
133
+ }
134
+
135
+ return {
136
+ startState: function() {
137
+ return { tokenize: tokenizer, mode: "smarty", last: null };
138
+ },
139
+ token: function(stream, state) {
140
+ var style = state.tokenize(stream, state);
141
+ state.last = last;
142
+ return style;
143
+ },
144
+ electricChars: ""
145
+ }
146
+ });
147
+
148
+ CodeMirror.defineMIME("text/x-smarty", "smarty");
@@ -82,7 +82,7 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
82
82
  }
83
83
 
84
84
  function normal(source, state) {
85
- if (source.match(/^\\[a-z]+/)) {
85
+ if (source.match(/^\\[a-zA-Z@]+/)) {
86
86
  var cmdName = source.current();
87
87
  cmdName = cmdName.substr(1, cmdName.length-1);
88
88
  var plug = plugins[cmdName];
@@ -95,9 +95,22 @@ CodeMirror.defineMode("stex", function(cmCfg, modeCfg)
95
95
  return plug.style;
96
96
  }
97
97
 
98
+ // escape characters
99
+ if (source.match(/^\\[$&%#{}_]/)) {
100
+ return "tag";
101
+ }
102
+
103
+ // white space control characters
104
+ if (source.match(/^\\[,;!\/]/)) {
105
+ return "tag";
106
+ }
107
+
98
108
  var ch = source.next();
99
109
  if (ch == "%") {
100
- setState(state, inCComment);
110
+ // special case: % at end of its own line; stay in same state
111
+ if (!source.eol()) {
112
+ setState(state, inCComment);
113
+ }
101
114
  return "comment";
102
115
  }
103
116
  else if (ch=='}' || ch==']') {
@@ -1,18 +1,18 @@
1
1
  /***
2
- |''Name''|tiddlywiki.js|
3
- |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror2|
4
- |''Author''|PMario|
5
- |''Version''|0.1.6|
6
- |''Status''|''beta''|
7
- |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8
- |''Documentation''|http://codemirror.tiddlyspace.com/|
9
- |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10
- |''CoreVersion''|2.5.0|
11
- |''Requires''|codemirror.js|
12
- |''Keywords''|syntax highlighting color code mirror codemirror|
13
- ! Info
14
- CoreVersion parameter is needed for TiddlyWiki only!
15
- ***/
2
+ |''Name''|tiddlywiki.js|
3
+ |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror|
4
+ |''Author''|PMario|
5
+ |''Version''|0.1.7|
6
+ |''Status''|''stable''|
7
+ |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]|
8
+ |''Documentation''|http://codemirror.tiddlyspace.com/|
9
+ |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]|
10
+ |''CoreVersion''|2.5.0|
11
+ |''Requires''|codemirror.js|
12
+ |''Keywords''|syntax highlighting color code mirror codemirror|
13
+ ! Info
14
+ CoreVersion parameter is needed for TiddlyWiki only!
15
+ ***/
16
16
  //{{{
17
17
  CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
18
18
  var indentUnit = config.indentUnit;
@@ -47,20 +47,20 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
47
47
  }();
48
48
 
49
49
  var isSpaceName = /[\w_\-]/i,
50
- reHR = /^\-\-\-\-+$/,
50
+ reHR = /^\-\-\-\-+$/, // <hr>
51
51
  reWikiCommentStart = /^\/\*\*\*$/, // /***
52
52
  reWikiCommentStop = /^\*\*\*\/$/, // ***/
53
53
  reBlockQuote = /^<<<$/,
54
54
 
55
- reJsCodeStart = /^\/\/\{\{\{$/, // //{{{
56
- reJsCodeStop = /^\/\/\}\}\}$/, // //}}}
57
- reXmlCodeStart = /^<!--\{\{\{-->$/,
58
- reXmlCodeStop = /^<!--\}\}\}-->$/,
55
+ reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start
56
+ reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop
57
+ reXmlCodeStart = /^<!--\{\{\{-->$/, // xml block start
58
+ reXmlCodeStop = /^<!--\}\}\}-->$/, // xml stop
59
59
 
60
- reCodeBlockStart = /^\{\{\{$/,
61
- reCodeBlockStop = /^\}\}\}$/,
60
+ reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start
61
+ reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop
62
62
 
63
- reCodeStart = /\{\{\{/,
63
+ reCodeStart = /\{\{\{/, // {{{ code span start
64
64
  reUntilCodeStop = /.*?\}\}\}/;
65
65
 
66
66
  function chain(stream, state, f) {
@@ -95,9 +95,9 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
95
95
 
96
96
  state.block = false; // indicates the start of a code block.
97
97
 
98
- ch = stream.peek(); // don't eat, to make match simpler
98
+ ch = stream.peek(); // don't eat, to make matching simpler
99
99
 
100
- // check start of blocks
100
+ // check start of blocks
101
101
  if (sol && /[<\/\*{}\-]/.test(ch)) {
102
102
  if (stream.match(reCodeBlockStart)) {
103
103
  state.block = true;
@@ -116,7 +116,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
116
116
  return ret('hr', 'hr');
117
117
  }
118
118
  } // sol
119
- var ch = stream.next();
119
+ ch = stream.next();
120
120
 
121
121
  if (sol && /[\/\*!#;:>|]/.test(ch)) {
122
122
  if (ch == "!") { // tw header
@@ -131,11 +131,11 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
131
131
  stream.eatWhile('#');
132
132
  return ret("list", "list");
133
133
  }
134
- if (ch == ";") { // tw list
134
+ if (ch == ";") { // definition list, term
135
135
  stream.eatWhile(';');
136
136
  return ret("list", "list");
137
137
  }
138
- if (ch == ":") { // tw list
138
+ if (ch == ":") { // definition list, description
139
139
  stream.eatWhile(':');
140
140
  return ret("list", "list");
141
141
  }
@@ -162,6 +162,9 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
162
162
  if (ch == '"') {
163
163
  return ret('string', 'string');
164
164
  }
165
+ if (ch == '~') { // _no_ CamelCase indicator should be bold
166
+ return ret('text', 'brace');
167
+ }
165
168
  if (/[\[\]]/.test(ch)) { // check for [[..]]
166
169
  if (stream.peek() == ch) {
167
170
  stream.next();
@@ -189,9 +192,15 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
189
192
  return chain(stream, state, twTokenUnderline);
190
193
  }
191
194
  }
192
- if (ch == "-") { // tw strikethrough TODO looks ugly .. different handling see below;
195
+ // strikethrough and mdash handling
196
+ if (ch == "-") {
193
197
  if (stream.eat("-")) {
194
- return chain(stream, state, twTokenStrike);
198
+ // if strikethrough looks ugly, change CSS.
199
+ if (stream.peek() != ' ')
200
+ return chain(stream, state, twTokenStrike);
201
+ // mdash
202
+ if (stream.peek() == ' ')
203
+ return ret('text', 'brace');
195
204
  }
196
205
  }
197
206
  if (ch == "'") { // tw bold
@@ -208,6 +217,7 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
208
217
  return ret(ch);
209
218
  }
210
219
 
220
+ // core macro handling
211
221
  stream.eatWhile(/[\w\$_]/);
212
222
  var word = stream.current(),
213
223
  known = textwords.propertyIsEnumerable(word) && textwords[word];
@@ -301,8 +311,8 @@ CodeMirror.defineMode("tiddlywiki", function (config, parserConfig) {
301
311
  return ret("text", "underlined");
302
312
  }
303
313
 
304
- // tw strike through text looks ugly
305
- // TODO just strike through the first and last 2 chars if possible.
314
+ // tw strike through text looks ugly
315
+ // change CSS if needed
306
316
  function twTokenStrike(stream, state) {
307
317
  var maybeEnd = false,
308
318
  ch, nr;
@@ -0,0 +1,26 @@
1
+ CodeMirror.defineMode("vbscript", function() {
2
+ var regexVBScriptKeyword = /^(?:Call|Case|CDate|Clear|CInt|CLng|Const|CStr|Description|Dim|Do|Each|Else|ElseIf|End|Err|Error|Exit|False|For|Function|If|LCase|Loop|LTrim|Next|Nothing|Now|Number|On|Preserve|Quit|ReDim|Resume|RTrim|Select|Set|Sub|Then|To|Trim|True|UBound|UCase|Until|VbCr|VbCrLf|VbLf|VbTab)$/im;
3
+
4
+ return {
5
+ token: function(stream) {
6
+ if (stream.eatSpace()) return null;
7
+ var ch = stream.next();
8
+ if (ch == "'") {
9
+ stream.skipToEnd();
10
+ return "comment";
11
+ }
12
+ if (ch == '"') {
13
+ stream.skipTo('"');
14
+ return "string";
15
+ }
16
+
17
+ if (/\w/.test(ch)) {
18
+ stream.eatWhile(/\w/);
19
+ if (regexVBScriptKeyword.test(stream.current())) return "keyword";
20
+ }
21
+ return null;
22
+ }
23
+ };
24
+ });
25
+
26
+ CodeMirror.defineMIME("text/vbscript", "vbscript");
@@ -264,4 +264,5 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
264
264
  });
265
265
 
266
266
  CodeMirror.defineMIME("application/xml", "xml");
267
- CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
267
+ if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
268
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
@@ -0,0 +1,448 @@
1
+ /*
2
+ Copyright (C) 2011 by MarkLogic Corporation
3
+ Author: Mike Brevoort <mike@brevoort.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ */
23
+ CodeMirror.defineMode("xquery", function(config, parserConfig) {
24
+
25
+ // The keywords object is set to the result of this self executing
26
+ // function. Each keyword is a property of the keywords object whose
27
+ // value is {type: atype, style: astyle}
28
+ var keywords = function(){
29
+ // conveinence functions used to build keywords object
30
+ function kw(type) {return {type: type, style: "keyword"};}
31
+ var A = kw("keyword a")
32
+ , B = kw("keyword b")
33
+ , C = kw("keyword c")
34
+ , operator = kw("operator")
35
+ , atom = {type: "atom", style: "atom"}
36
+ , punctuation = {type: "punctuation", style: ""}
37
+ , qualifier = {type: "axis_specifier", style: "qualifier"};
38
+
39
+ // kwObj is what is return from this function at the end
40
+ var kwObj = {
41
+ 'if': A, 'switch': A, 'while': A, 'for': A,
42
+ 'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B,
43
+ 'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C,
44
+ 'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C,
45
+ ',': punctuation,
46
+ 'null': atom, 'fn:false()': atom, 'fn:true()': atom
47
+ };
48
+
49
+ // a list of 'basic' keywords. For each add a property to kwObj with the value of
50
+ // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"}
51
+ var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before',
52
+ 'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self',
53
+ 'descending','document','document-node','element','else','eq','every','except','external','following',
54
+ 'following-sibling','follows','for','function','if','import','in','instance','intersect','item',
55
+ 'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding',
56
+ 'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element',
57
+ 'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where',
58
+ 'xquery', 'empty-sequence'];
59
+ for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i])};
60
+
61
+ // a list of types. For each add a property to kwObj with the value of
62
+ // {type: "atom", style: "atom"}
63
+ var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime',
64
+ 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary',
65
+ 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration'];
66
+ for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;};
67
+
68
+ // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"}
69
+ var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-'];
70
+ for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;};
71
+
72
+ // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"}
73
+ var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::",
74
+ "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"];
75
+ for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; };
76
+
77
+ return kwObj;
78
+ }();
79
+
80
+ // Used as scratch variables to communicate multiple values without
81
+ // consing up tons of objects.
82
+ var type, content;
83
+
84
+ function ret(tp, style, cont) {
85
+ type = tp; content = cont;
86
+ return style;
87
+ }
88
+
89
+ function chain(stream, state, f) {
90
+ state.tokenize = f;
91
+ return f(stream, state);
92
+ }
93
+
94
+ // the primary mode tokenizer
95
+ function tokenBase(stream, state) {
96
+ var ch = stream.next(),
97
+ mightBeFunction = false,
98
+ isEQName = isEQNameAhead(stream);
99
+
100
+ // an XML tag (if not in some sub, chained tokenizer)
101
+ if (ch == "<") {
102
+ if(stream.match("!--", true))
103
+ return chain(stream, state, tokenXMLComment);
104
+
105
+ if(stream.match("![CDATA", false)) {
106
+ state.tokenize = tokenCDATA;
107
+ return ret("tag", "tag");
108
+ }
109
+
110
+ if(stream.match("?", false)) {
111
+ return chain(stream, state, tokenPreProcessing);
112
+ }
113
+
114
+ var isclose = stream.eat("/");
115
+ stream.eatSpace();
116
+ var tagName = "", c;
117
+ while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c;
118
+
119
+ return chain(stream, state, tokenTag(tagName, isclose));
120
+ }
121
+ // start code block
122
+ else if(ch == "{") {
123
+ pushStateStack(state,{ type: "codeblock"});
124
+ return ret("", "");
125
+ }
126
+ // end code block
127
+ else if(ch == "}") {
128
+ popStateStack(state);
129
+ return ret("", "");
130
+ }
131
+ // if we're in an XML block
132
+ else if(isInXmlBlock(state)) {
133
+ if(ch == ">")
134
+ return ret("tag", "tag");
135
+ else if(ch == "/" && stream.eat(">")) {
136
+ popStateStack(state);
137
+ return ret("tag", "tag");
138
+ }
139
+ else
140
+ return ret("word", "word");
141
+ }
142
+ // if a number
143
+ else if (/\d/.test(ch)) {
144
+ stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/);
145
+ return ret("number", "atom");
146
+ }
147
+ // comment start
148
+ else if (ch === "(" && stream.eat(":")) {
149
+ pushStateStack(state, { type: "comment"});
150
+ return chain(stream, state, tokenComment);
151
+ }
152
+ // quoted string
153
+ else if ( !isEQName && (ch === '"' || ch === "'"))
154
+ return chain(stream, state, tokenString(ch));
155
+ // variable
156
+ else if(ch === "$") {
157
+ return chain(stream, state, tokenVariable);
158
+ }
159
+ // assignment
160
+ else if(ch ===":" && stream.eat("=")) {
161
+ return ret("operator", "keyword");
162
+ }
163
+ // open paren
164
+ else if(ch === "(") {
165
+ pushStateStack(state, { type: "paren"});
166
+ return ret("", "");
167
+ }
168
+ // close paren
169
+ else if(ch === ")") {
170
+ popStateStack(state);
171
+ return ret("", "");
172
+ }
173
+ // open paren
174
+ else if(ch === "[") {
175
+ pushStateStack(state, { type: "bracket"});
176
+ return ret("", "");
177
+ }
178
+ // close paren
179
+ else if(ch === "]") {
180
+ popStateStack(state);
181
+ return ret("", "");
182
+ }
183
+ else {
184
+ var known = keywords.propertyIsEnumerable(ch) && keywords[ch];
185
+
186
+ // if there's a EQName ahead, consume the rest of the string portion, it's likely a function
187
+ if(isEQName && ch === '\"') while(stream.next() !== '"'){}
188
+ if(isEQName && ch === '\'') while(stream.next() !== '\''){}
189
+
190
+ // gobble up a word if the character is not known
191
+ if(!known) stream.eatWhile(/[\w\$_-]/);
192
+
193
+ // gobble a colon in the case that is a lib func type call fn:doc
194
+ var foundColon = stream.eat(":")
195
+
196
+ // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier
197
+ // which should get matched as a keyword
198
+ if(!stream.eat(":") && foundColon) {
199
+ stream.eatWhile(/[\w\$_-]/);
200
+ }
201
+ // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort)
202
+ if(stream.match(/^[ \t]*\(/, false)) {
203
+ mightBeFunction = true;
204
+ }
205
+ // is the word a keyword?
206
+ var word = stream.current();
207
+ known = keywords.propertyIsEnumerable(word) && keywords[word];
208
+
209
+ // if we think it's a function call but not yet known,
210
+ // set style to variable for now for lack of something better
211
+ if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"};
212
+
213
+ // if the previous word was element, attribute, axis specifier, this word should be the name of that
214
+ if(isInXmlConstructor(state)) {
215
+ popStateStack(state);
216
+ return ret("word", "word", word);
217
+ }
218
+ // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and
219
+ // push the stack so we know to look for it on the next word
220
+ if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"});
221
+
222
+ // if the word is known, return the details of that else just call this a generic 'word'
223
+ return known ? ret(known.type, known.style, word) :
224
+ ret("word", "word", word);
225
+ }
226
+ }
227
+
228
+ // handle comments, including nested
229
+ function tokenComment(stream, state) {
230
+ var maybeEnd = false, maybeNested = false, nestedCount = 0, ch;
231
+ while (ch = stream.next()) {
232
+ if (ch == ")" && maybeEnd) {
233
+ if(nestedCount > 0)
234
+ nestedCount--;
235
+ else {
236
+ popStateStack(state);
237
+ break;
238
+ }
239
+ }
240
+ else if(ch == ":" && maybeNested) {
241
+ nestedCount++;
242
+ }
243
+ maybeEnd = (ch == ":");
244
+ maybeNested = (ch == "(");
245
+ }
246
+
247
+ return ret("comment", "comment");
248
+ }
249
+
250
+ // tokenizer for string literals
251
+ // optionally pass a tokenizer function to set state.tokenize back to when finished
252
+ function tokenString(quote, f) {
253
+ return function(stream, state) {
254
+ var ch;
255
+
256
+ if(isInString(state) && stream.current() == quote) {
257
+ popStateStack(state);
258
+ if(f) state.tokenize = f;
259
+ return ret("string", "string");
260
+ }
261
+
262
+ pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) });
263
+
264
+ // if we're in a string and in an XML block, allow an embedded code block
265
+ if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
266
+ state.tokenize = tokenBase;
267
+ return ret("string", "string");
268
+ }
269
+
270
+
271
+ while (ch = stream.next()) {
272
+ if (ch == quote) {
273
+ popStateStack(state);
274
+ if(f) state.tokenize = f;
275
+ break;
276
+ }
277
+ else {
278
+ // if we're in a string and in an XML block, allow an embedded code block in an attribute
279
+ if(stream.match("{", false) && isInXmlAttributeBlock(state)) {
280
+ state.tokenize = tokenBase;
281
+ return ret("string", "string");
282
+ }
283
+
284
+ }
285
+ }
286
+
287
+ return ret("string", "string");
288
+ };
289
+ }
290
+
291
+ // tokenizer for variables
292
+ function tokenVariable(stream, state) {
293
+ var isVariableChar = /[\w\$_-]/;
294
+
295
+ // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote
296
+ if(stream.eat("\"")) {
297
+ while(stream.next() !== '\"'){};
298
+ stream.eat(":");
299
+ } else {
300
+ stream.eatWhile(isVariableChar);
301
+ if(!stream.match(":=", false)) stream.eat(":");
302
+ }
303
+ stream.eatWhile(isVariableChar);
304
+ state.tokenize = tokenBase;
305
+ return ret("variable", "variable");
306
+ }
307
+
308
+ // tokenizer for XML tags
309
+ function tokenTag(name, isclose) {
310
+ return function(stream, state) {
311
+ stream.eatSpace();
312
+ if(isclose && stream.eat(">")) {
313
+ popStateStack(state);
314
+ state.tokenize = tokenBase;
315
+ return ret("tag", "tag");
316
+ }
317
+ // self closing tag without attributes?
318
+ if(!stream.eat("/"))
319
+ pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase});
320
+ if(!stream.eat(">")) {
321
+ state.tokenize = tokenAttribute;
322
+ return ret("tag", "tag");
323
+ }
324
+ else {
325
+ state.tokenize = tokenBase;
326
+ }
327
+ return ret("tag", "tag");
328
+ }
329
+ }
330
+
331
+ // tokenizer for XML attributes
332
+ function tokenAttribute(stream, state) {
333
+ var ch = stream.next();
334
+
335
+ if(ch == "/" && stream.eat(">")) {
336
+ if(isInXmlAttributeBlock(state)) popStateStack(state);
337
+ if(isInXmlBlock(state)) popStateStack(state);
338
+ return ret("tag", "tag");
339
+ }
340
+ if(ch == ">") {
341
+ if(isInXmlAttributeBlock(state)) popStateStack(state);
342
+ return ret("tag", "tag");
343
+ }
344
+ if(ch == "=")
345
+ return ret("", "");
346
+ // quoted string
347
+ if (ch == '"' || ch == "'")
348
+ return chain(stream, state, tokenString(ch, tokenAttribute));
349
+
350
+ if(!isInXmlAttributeBlock(state))
351
+ pushStateStack(state, { type: "attribute", name: name, tokenize: tokenAttribute});
352
+
353
+ stream.eat(/[a-zA-Z_:]/);
354
+ stream.eatWhile(/[-a-zA-Z0-9_:.]/);
355
+ stream.eatSpace();
356
+
357
+ // the case where the attribute has not value and the tag was closed
358
+ if(stream.match(">", false) || stream.match("/", false)) {
359
+ popStateStack(state);
360
+ state.tokenize = tokenBase;
361
+ }
362
+
363
+ return ret("attribute", "attribute");
364
+ }
365
+
366
+ // handle comments, including nested
367
+ function tokenXMLComment(stream, state) {
368
+ while (ch = stream.next()) {
369
+ if (ch == "-" && stream.match("->", true)) {
370
+ state.tokenize = tokenBase;
371
+ return ret("comment", "comment");
372
+ }
373
+ }
374
+ }
375
+
376
+
377
+ // handle CDATA
378
+ function tokenCDATA(stream, state) {
379
+ while (ch = stream.next()) {
380
+ if (ch == "]" && stream.match("]", true)) {
381
+ state.tokenize = tokenBase;
382
+ return ret("comment", "comment");
383
+ }
384
+ }
385
+ }
386
+
387
+ // handle preprocessing instructions
388
+ function tokenPreProcessing(stream, state) {
389
+ while (ch = stream.next()) {
390
+ if (ch == "?" && stream.match(">", true)) {
391
+ state.tokenize = tokenBase;
392
+ return ret("comment", "comment meta");
393
+ }
394
+ }
395
+ }
396
+
397
+
398
+ // functions to test the current context of the state
399
+ function isInXmlBlock(state) { return isIn(state, "tag"); }
400
+ function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); }
401
+ function isInCodeBlock(state) { return isIn(state, "codeblock"); }
402
+ function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); }
403
+ function isInString(state) { return isIn(state, "string"); }
404
+
405
+ function isEQNameAhead(stream) {
406
+ // assume we've already eaten a quote (")
407
+ if(stream.current() === '"')
408
+ return stream.match(/^[^\"]+\"\:/, false);
409
+ else if(stream.current() === '\'')
410
+ return stream.match(/^[^\"]+\'\:/, false);
411
+ else
412
+ return false;
413
+ }
414
+
415
+ function isIn(state, type) {
416
+ return (state.stack.length && state.stack[state.stack.length - 1].type == type);
417
+ }
418
+
419
+ function pushStateStack(state, newState) {
420
+ state.stack.push(newState);
421
+ }
422
+
423
+ function popStateStack(state) {
424
+ var popped = state.stack.pop();
425
+ var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize
426
+ state.tokenize = reinstateTokenize || tokenBase;
427
+ }
428
+
429
+ // the interface for the mode API
430
+ return {
431
+ startState: function(basecolumn) {
432
+ return {
433
+ tokenize: tokenBase,
434
+ cc: [],
435
+ stack: []
436
+ };
437
+ },
438
+
439
+ token: function(stream, state) {
440
+ if (stream.eatSpace()) return null;
441
+ var style = state.tokenize(stream, state);
442
+ return style;
443
+ }
444
+ };
445
+
446
+ });
447
+
448
+ CodeMirror.defineMIME("application/xquery", "xquery");