Fix: merge conflict
[myslice.git] / to-be-integrated / third-party / codemirror-3.15 / mode / tiki / tiki.js
1 CodeMirror.defineMode('tiki', function(config) {
2   function inBlock(style, terminator, returnTokenizer) {
3     return function(stream, state) {
4       while (!stream.eol()) {
5         if (stream.match(terminator)) {
6           state.tokenize = inText;
7           break;
8         }
9         stream.next();
10       }
11
12       if (returnTokenizer) state.tokenize = returnTokenizer;
13
14       return style;
15     };
16   }
17
18   function inLine(style) {
19     return function(stream, state) {
20       while(!stream.eol()) {
21         stream.next();
22       }
23       state.tokenize = inText;
24       return style;
25     };
26   }
27
28   function inText(stream, state) {
29     function chain(parser) {
30       state.tokenize = parser;
31       return parser(stream, state);
32     }
33
34     var sol = stream.sol();
35     var ch = stream.next();
36
37     //non start of line
38     switch (ch) { //switch is generally much faster than if, so it is used here
39     case "{": //plugin
40       stream.eat("/");
41       stream.eatSpace();
42       var tagName = "";
43       var c;
44       while ((c = stream.eat(/[^\s\u00a0=\"\'\/?(}]/))) tagName += c;
45       state.tokenize = inPlugin;
46       return "tag";
47       break;
48     case "_": //bold
49       if (stream.eat("_")) {
50         return chain(inBlock("strong", "__", inText));
51       }
52       break;
53     case "'": //italics
54       if (stream.eat("'")) {
55         // Italic text
56         return chain(inBlock("em", "''", inText));
57       }
58       break;
59     case "(":// Wiki Link
60       if (stream.eat("(")) {
61         return chain(inBlock("variable-2", "))", inText));
62       }
63       break;
64     case "[":// Weblink
65       return chain(inBlock("variable-3", "]", inText));
66       break;
67     case "|": //table
68       if (stream.eat("|")) {
69         return chain(inBlock("comment", "||"));
70       }
71       break;
72     case "-":
73       if (stream.eat("=")) {//titleBar
74         return chain(inBlock("header string", "=-", inText));
75       } else if (stream.eat("-")) {//deleted
76         return chain(inBlock("error tw-deleted", "--", inText));
77       }
78       break;
79     case "=": //underline
80       if (stream.match("==")) {
81         return chain(inBlock("tw-underline", "===", inText));
82       }
83       break;
84     case ":":
85       if (stream.eat(":")) {
86         return chain(inBlock("comment", "::"));
87       }
88       break;
89     case "^": //box
90       return chain(inBlock("tw-box", "^"));
91       break;
92     case "~": //np
93       if (stream.match("np~")) {
94         return chain(inBlock("meta", "~/np~"));
95       }
96       break;
97     }
98
99     //start of line types
100     if (sol) {
101       switch (ch) {
102       case "!": //header at start of line
103         if (stream.match('!!!!!')) {
104           return chain(inLine("header string"));
105         } else if (stream.match('!!!!')) {
106           return chain(inLine("header string"));
107         } else if (stream.match('!!!')) {
108           return chain(inLine("header string"));
109         } else if (stream.match('!!')) {
110           return chain(inLine("header string"));
111         } else {
112           return chain(inLine("header string"));
113         }
114         break;
115       case "*": //unordered list line item, or <li /> at start of line
116       case "#": //ordered list line item, or <li /> at start of line
117       case "+": //ordered list line item, or <li /> at start of line
118         return chain(inLine("tw-listitem bracket"));
119         break;
120       }
121     }
122
123     //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki
124     return null;
125   }
126
127   var indentUnit = config.indentUnit;
128
129   // Return variables for tokenizers
130   var pluginName, type;
131   function inPlugin(stream, state) {
132     var ch = stream.next();
133     var peek = stream.peek();
134
135     if (ch == "}") {
136       state.tokenize = inText;
137       //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin
138       return "tag";
139     } else if (ch == "(" || ch == ")") {
140       return "bracket";
141     } else if (ch == "=") {
142       type = "equals";
143
144       if (peek == ">") {
145         ch = stream.next();
146         peek = stream.peek();
147       }
148
149       //here we detect values directly after equal character with no quotes
150       if (!/[\'\"]/.test(peek)) {
151         state.tokenize = inAttributeNoQuote();
152       }
153       //end detect values
154
155       return "operator";
156     } else if (/[\'\"]/.test(ch)) {
157       state.tokenize = inAttribute(ch);
158       return state.tokenize(stream, state);
159     } else {
160       stream.eatWhile(/[^\s\u00a0=\"\'\/?]/);
161       return "keyword";
162     }
163   }
164
165   function inAttribute(quote) {
166     return function(stream, state) {
167       while (!stream.eol()) {
168         if (stream.next() == quote) {
169           state.tokenize = inPlugin;
170           break;
171         }
172       }
173       return "string";
174     };
175   }
176
177   function inAttributeNoQuote() {
178     return function(stream, state) {
179       while (!stream.eol()) {
180         var ch = stream.next();
181         var peek = stream.peek();
182         if (ch == " " || ch == "," || /[ )}]/.test(peek)) {
183       state.tokenize = inPlugin;
184       break;
185     }
186   }
187   return "string";
188 };
189                      }
190
191 var curState, setStyle;
192 function pass() {
193   for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]);
194 }
195
196 function cont() {
197   pass.apply(null, arguments);
198   return true;
199 }
200
201 function pushContext(pluginName, startOfLine) {
202   var noIndent = curState.context && curState.context.noIndent;
203   curState.context = {
204     prev: curState.context,
205     pluginName: pluginName,
206     indent: curState.indented,
207     startOfLine: startOfLine,
208     noIndent: noIndent
209   };
210 }
211
212 function popContext() {
213   if (curState.context) curState.context = curState.context.prev;
214 }
215
216 function element(type) {
217   if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));}
218   else if (type == "closePlugin") {
219     var err = false;
220     if (curState.context) {
221       err = curState.context.pluginName != pluginName;
222       popContext();
223     } else {
224       err = true;
225     }
226     if (err) setStyle = "error";
227     return cont(endcloseplugin(err));
228   }
229   else if (type == "string") {
230     if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata");
231     if (curState.tokenize == inText) popContext();
232     return cont();
233   }
234   else return cont();
235 }
236
237 function endplugin(startOfLine) {
238   return function(type) {
239     if (
240       type == "selfclosePlugin" ||
241         type == "endPlugin"
242     )
243       return cont();
244     if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();}
245     return cont();
246   };
247 }
248
249 function endcloseplugin(err) {
250   return function(type) {
251     if (err) setStyle = "error";
252     if (type == "endPlugin") return cont();
253     return pass();
254   };
255 }
256
257 function attributes(type) {
258   if (type == "keyword") {setStyle = "attribute"; return cont(attributes);}
259   if (type == "equals") return cont(attvalue, attributes);
260   return pass();
261 }
262 function attvalue(type) {
263   if (type == "keyword") {setStyle = "string"; return cont();}
264   if (type == "string") return cont(attvaluemaybe);
265   return pass();
266 }
267 function attvaluemaybe(type) {
268   if (type == "string") return cont(attvaluemaybe);
269   else return pass();
270 }
271 return {
272   startState: function() {
273     return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null};
274   },
275   token: function(stream, state) {
276     if (stream.sol()) {
277       state.startOfLine = true;
278       state.indented = stream.indentation();
279     }
280     if (stream.eatSpace()) return null;
281
282     setStyle = type = pluginName = null;
283     var style = state.tokenize(stream, state);
284     if ((style || type) && style != "comment") {
285       curState = state;
286       while (true) {
287         var comb = state.cc.pop() || element;
288         if (comb(type || style)) break;
289       }
290     }
291     state.startOfLine = false;
292     return setStyle || style;
293   },
294   indent: function(state, textAfter) {
295     var context = state.context;
296     if (context && context.noIndent) return 0;
297     if (context && /^{\//.test(textAfter))
298         context = context.prev;
299         while (context && !context.startOfLine)
300           context = context.prev;
301         if (context) return context.indent + indentUnit;
302         else return 0;
303        },
304     electricChars: "/"
305   };
306 });
307
308 CodeMirror.defineMIME("text/tiki", "tiki");