fix odl patches
[ccsdk/distribution.git] / dgbuilder / public / ace / mode-xml.js
1 define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
2 "use strict";
3
4 var oop = require("../lib/oop");
5 var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
6
7 var XmlHighlightRules = function(normalize) {
8     var tagRegex = "[_:a-zA-Z\xc0-\uffff][-_:.a-zA-Z0-9\xc0-\uffff]*";
9
10     this.$rules = {
11         start : [
12             {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"},
13             {
14                 token : ["punctuation.instruction.xml", "keyword.instruction.xml"],
15                 regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction"
16             },
17             {token : "comment.start.xml", regex : "<\\!--", next : "comment"},
18             {
19                 token : ["xml-pe.doctype.xml", "xml-pe.doctype.xml"],
20                 regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype", caseInsensitive: true
21             },
22             {include : "tag"},
23             {token : "text.end-tag-open.xml", regex: "</"},
24             {token : "text.tag-open.xml", regex: "<"},
25             {include : "reference"},
26             {defaultToken : "text.xml"}
27         ],
28
29         processing_instruction : [{
30             token : "entity.other.attribute-name.decl-attribute-name.xml",
31             regex : tagRegex
32         }, {
33             token : "keyword.operator.decl-attribute-equals.xml",
34             regex : "="
35         }, {
36             include: "whitespace"
37         }, {
38             include: "string"
39         }, {
40             token : "punctuation.xml-decl.xml",
41             regex : "\\?>",
42             next : "start"
43         }],
44
45         doctype : [
46             {include : "whitespace"},
47             {include : "string"},
48             {token : "xml-pe.doctype.xml", regex : ">", next : "start"},
49             {token : "xml-pe.xml", regex : "[-_a-zA-Z0-9:]+"},
50             {token : "punctuation.int-subset", regex : "\\[", push : "int_subset"}
51         ],
52
53         int_subset : [{
54             token : "text.xml",
55             regex : "\\s+"
56         }, {
57             token: "punctuation.int-subset.xml",
58             regex: "]",
59             next: "pop"
60         }, {
61             token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"],
62             regex : "(<\\!)(" + tagRegex + ")",
63             push : [{
64                 token : "text",
65                 regex : "\\s+"
66             },
67             {
68                 token : "punctuation.markup-decl.xml",
69                 regex : ">",
70                 next : "pop"
71             },
72             {include : "string"}]
73         }],
74
75         cdata : [
76             {token : "string.cdata.xml", regex : "\\]\\]>", next : "start"},
77             {token : "text.xml", regex : "\\s+"},
78             {token : "text.xml", regex : "(?:[^\\]]|\\](?!\\]>))+"}
79         ],
80
81         comment : [
82             {token : "comment.end.xml", regex : "-->", next : "start"},
83             {defaultToken : "comment.xml"}
84         ],
85
86         reference : [{
87             token : "constant.language.escape.reference.xml",
88             regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
89         }],
90
91         attr_reference : [{
92             token : "constant.language.escape.reference.attribute-value.xml",
93             regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
94         }],
95
96         tag : [{
97             token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"],
98             regex : "(?:(<)|(</))((?:" + tagRegex + ":)?" + tagRegex + ")",
99             next: [
100                 {include : "attributes"},
101                 {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : "start"}
102             ]
103         }],
104
105         tag_whitespace : [
106             {token : "text.tag-whitespace.xml", regex : "\\s+"}
107         ],
108         whitespace : [
109             {token : "text.whitespace.xml", regex : "\\s+"}
110         ],
111         string: [{
112             token : "string.xml",
113             regex : "'",
114             push : [
115                 {token : "string.xml", regex: "'", next: "pop"},
116                 {defaultToken : "string.xml"}
117             ]
118         }, {
119             token : "string.xml",
120             regex : '"',
121             push : [
122                 {token : "string.xml", regex: '"', next: "pop"},
123                 {defaultToken : "string.xml"}
124             ]
125         }],
126
127         attributes: [{
128             token : "entity.other.attribute-name.xml",
129             regex : tagRegex
130         }, {
131             token : "keyword.operator.attribute-equals.xml",
132             regex : "="
133         }, {
134             include: "tag_whitespace"
135         }, {
136             include: "attribute_value"
137         }],
138
139         attribute_value: [{
140             token : "string.attribute-value.xml",
141             regex : "'",
142             push : [
143                 {token : "string.attribute-value.xml", regex: "'", next: "pop"},
144                 {include : "attr_reference"},
145                 {defaultToken : "string.attribute-value.xml"}
146             ]
147         }, {
148             token : "string.attribute-value.xml",
149             regex : '"',
150             push : [
151                 {token : "string.attribute-value.xml", regex: '"', next: "pop"},
152                 {include : "attr_reference"},
153                 {defaultToken : "string.attribute-value.xml"}
154             ]
155         }]
156     };
157
158     if (this.constructor === XmlHighlightRules)
159         this.normalizeRules();
160 };
161
162
163 (function() {
164
165     this.embedTagRules = function(HighlightRules, prefix, tag){
166         this.$rules.tag.unshift({
167             token : ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
168             regex : "(<)(" + tag + "(?=\\s|>|$))",
169             next: [
170                 {include : "attributes"},
171                 {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : prefix + "start"}
172             ]
173         });
174
175         this.$rules[tag + "-end"] = [
176             {include : "attributes"},
177             {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>",  next: "start",
178                 onMatch : function(value, currentState, stack) {
179                     stack.splice(0);
180                     return this.token;
181             }}
182         ];
183
184         this.embedRules(HighlightRules, prefix, [{
185             token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
186             regex : "(</)(" + tag + "(?=\\s|>|$))",
187             next: tag + "-end"
188         }, {
189             token: "string.cdata.xml",
190             regex : "<\\!\\[CDATA\\["
191         }, {
192             token: "string.cdata.xml",
193             regex : "\\]\\]>"
194         }]);
195     };
196
197 }).call(TextHighlightRules.prototype);
198
199 oop.inherits(XmlHighlightRules, TextHighlightRules);
200
201 exports.XmlHighlightRules = XmlHighlightRules;
202 });
203
204 define("ace/mode/behaviour/xml",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"], function(require, exports, module) {
205 "use strict";
206
207 var oop = require("../../lib/oop");
208 var Behaviour = require("../behaviour").Behaviour;
209 var TokenIterator = require("../../token_iterator").TokenIterator;
210 var lang = require("../../lib/lang");
211
212 function is(token, type) {
213     return token.type.lastIndexOf(type + ".xml") > -1;
214 }
215
216 var XmlBehaviour = function () {
217
218     this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
219         if (text == '"' || text == "'") {
220             var quote = text;
221             var selected = session.doc.getTextRange(editor.getSelectionRange());
222             if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
223                 return {
224                     text: quote + selected + quote,
225                     selection: false
226                 };
227             }
228
229             var cursor = editor.getCursorPosition();
230             var line = session.doc.getLine(cursor.row);
231             var rightChar = line.substring(cursor.column, cursor.column + 1);
232             var iterator = new TokenIterator(session, cursor.row, cursor.column);
233             var token = iterator.getCurrentToken();
234
235             if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
236                 return {
237                     text: "",
238                     selection: [1, 1]
239                 };
240             }
241
242             if (!token)
243                 token = iterator.stepBackward();
244
245             if (!token)
246                 return;
247
248             while (is(token, "tag-whitespace") || is(token, "whitespace")) {
249                 token = iterator.stepBackward();
250             }
251             var rightSpace = !rightChar || rightChar.match(/\s/);
252             if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) {
253                 return {
254                     text: quote + quote,
255                     selection: [1, 1]
256                 };
257             }
258         }
259     });
260
261     this.add("string_dquotes", "deletion", function(state, action, editor, session, range) {
262         var selected = session.doc.getTextRange(range);
263         if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
264             var line = session.doc.getLine(range.start.row);
265             var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
266             if (rightChar == selected) {
267                 range.end.column++;
268                 return range;
269             }
270         }
271     });
272
273     this.add("autoclosing", "insertion", function (state, action, editor, session, text) {
274         if (text == '>') {
275             var position = editor.getSelectionRange().start;
276             var iterator = new TokenIterator(session, position.row, position.column);
277             var token = iterator.getCurrentToken() || iterator.stepBackward();
278             if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value")))
279                 return;
280             if (is(token, "reference.attribute-value"))
281                 return;
282             if (is(token, "attribute-value")) {
283                 var firstChar = token.value.charAt(0);
284                 if (firstChar == '"' || firstChar == "'") {
285                     var lastChar = token.value.charAt(token.value.length - 1);
286                     var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length;
287                     if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar)
288                         return;
289                 }
290             }
291             while (!is(token, "tag-name")) {
292                 token = iterator.stepBackward();
293                 if (token.value == "<") {
294                     token = iterator.stepForward();
295                     break;
296                 }
297             }
298
299             var tokenRow = iterator.getCurrentTokenRow();
300             var tokenColumn = iterator.getCurrentTokenColumn();
301             if (is(iterator.stepBackward(), "end-tag-open"))
302                 return;
303
304             var element = token.value;
305             if (tokenRow == position.row)
306                 element = element.substring(0, position.column - tokenColumn);
307
308             if (this.voidElements.hasOwnProperty(element.toLowerCase()))
309                  return;
310
311             return {
312                text: ">" + "</" + element + ">",
313                selection: [1, 1]
314             };
315         }
316     });
317
318     this.add("autoindent", "insertion", function (state, action, editor, session, text) {
319         if (text == "\n") {
320             var cursor = editor.getCursorPosition();
321             var line = session.getLine(cursor.row);
322             var iterator = new TokenIterator(session, cursor.row, cursor.column);
323             var token = iterator.getCurrentToken();
324
325             if (token && token.type.indexOf("tag-close") !== -1) {
326                 if (token.value == "/>")
327                     return;
328                 while (token && token.type.indexOf("tag-name") === -1) {
329                     token = iterator.stepBackward();
330                 }
331
332                 if (!token) {
333                     return;
334                 }
335
336                 var tag = token.value;
337                 var row = iterator.getCurrentTokenRow();
338                 token = iterator.stepBackward();
339                 if (!token || token.type.indexOf("end-tag") !== -1) {
340                     return;
341                 }
342
343                 if (this.voidElements && !this.voidElements[tag]) {
344                     var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
345                     var line = session.getLine(row);
346                     var nextIndent = this.$getIndent(line);
347                     var indent = nextIndent + session.getTabString();
348
349                     if (nextToken && nextToken.value === "</") {
350                         return {
351                             text: "\n" + indent + "\n" + nextIndent,
352                             selection: [1, indent.length, 1, indent.length]
353                         };
354                     } else {
355                         return {
356                             text: "\n" + indent
357                         };
358                     }
359                 }
360             }
361         }
362     });
363
364 };
365
366 oop.inherits(XmlBehaviour, Behaviour);
367
368 exports.XmlBehaviour = XmlBehaviour;
369 });
370
371 define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/range","ace/mode/folding/fold_mode","ace/token_iterator"], function(require, exports, module) {
372 "use strict";
373
374 var oop = require("../../lib/oop");
375 var lang = require("../../lib/lang");
376 var Range = require("../../range").Range;
377 var BaseFoldMode = require("./fold_mode").FoldMode;
378 var TokenIterator = require("../../token_iterator").TokenIterator;
379
380 var FoldMode = exports.FoldMode = function(voidElements, optionalEndTags) {
381     BaseFoldMode.call(this);
382     this.voidElements = voidElements || {};
383     this.optionalEndTags = oop.mixin({}, this.voidElements);
384     if (optionalEndTags)
385         oop.mixin(this.optionalEndTags, optionalEndTags);
386     
387 };
388 oop.inherits(FoldMode, BaseFoldMode);
389
390 var Tag = function() {
391     this.tagName = "";
392     this.closing = false;
393     this.selfClosing = false;
394     this.start = {row: 0, column: 0};
395     this.end = {row: 0, column: 0};
396 };
397
398 function is(token, type) {
399     return token.type.lastIndexOf(type + ".xml") > -1;
400 }
401
402 (function() {
403
404     this.getFoldWidget = function(session, foldStyle, row) {
405         var tag = this._getFirstTagInLine(session, row);
406
407         if (!tag)
408             return this.getCommentFoldWidget(session, row);
409
410         if (tag.closing || (!tag.tagName && tag.selfClosing))
411             return foldStyle == "markbeginend" ? "end" : "";
412
413         if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase()))
414             return "";
415
416         if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column))
417             return "";
418
419         return "start";
420     };
421     
422     this.getCommentFoldWidget = function(session, row) {
423         if (/comment/.test(session.getState(row)) && /<!-/.test(session.getLine(row)))
424             return "start";
425         return "";
426     };
427     this._getFirstTagInLine = function(session, row) {
428         var tokens = session.getTokens(row);
429         var tag = new Tag();
430
431         for (var i = 0; i < tokens.length; i++) {
432             var token = tokens[i];
433             if (is(token, "tag-open")) {
434                 tag.end.column = tag.start.column + token.value.length;
435                 tag.closing = is(token, "end-tag-open");
436                 token = tokens[++i];
437                 if (!token)
438                     return null;
439                 tag.tagName = token.value;
440                 tag.end.column += token.value.length;
441                 for (i++; i < tokens.length; i++) {
442                     token = tokens[i];
443                     tag.end.column += token.value.length;
444                     if (is(token, "tag-close")) {
445                         tag.selfClosing = token.value == '/>';
446                         break;
447                     }
448                 }
449                 return tag;
450             } else if (is(token, "tag-close")) {
451                 tag.selfClosing = token.value == '/>';
452                 return tag;
453             }
454             tag.start.column += token.value.length;
455         }
456
457         return null;
458     };
459
460     this._findEndTagInLine = function(session, row, tagName, startColumn) {
461         var tokens = session.getTokens(row);
462         var column = 0;
463         for (var i = 0; i < tokens.length; i++) {
464             var token = tokens[i];
465             column += token.value.length;
466             if (column < startColumn)
467                 continue;
468             if (is(token, "end-tag-open")) {
469                 token = tokens[i + 1];
470                 if (token && token.value == tagName)
471                     return true;
472             }
473         }
474         return false;
475     };
476     this._readTagForward = function(iterator) {
477         var token = iterator.getCurrentToken();
478         if (!token)
479             return null;
480
481         var tag = new Tag();
482         do {
483             if (is(token, "tag-open")) {
484                 tag.closing = is(token, "end-tag-open");
485                 tag.start.row = iterator.getCurrentTokenRow();
486                 tag.start.column = iterator.getCurrentTokenColumn();
487             } else if (is(token, "tag-name")) {
488                 tag.tagName = token.value;
489             } else if (is(token, "tag-close")) {
490                 tag.selfClosing = token.value == "/>";
491                 tag.end.row = iterator.getCurrentTokenRow();
492                 tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
493                 iterator.stepForward();
494                 return tag;
495             }
496         } while(token = iterator.stepForward());
497
498         return null;
499     };
500     
501     this._readTagBackward = function(iterator) {
502         var token = iterator.getCurrentToken();
503         if (!token)
504             return null;
505
506         var tag = new Tag();
507         do {
508             if (is(token, "tag-open")) {
509                 tag.closing = is(token, "end-tag-open");
510                 tag.start.row = iterator.getCurrentTokenRow();
511                 tag.start.column = iterator.getCurrentTokenColumn();
512                 iterator.stepBackward();
513                 return tag;
514             } else if (is(token, "tag-name")) {
515                 tag.tagName = token.value;
516             } else if (is(token, "tag-close")) {
517                 tag.selfClosing = token.value == "/>";
518                 tag.end.row = iterator.getCurrentTokenRow();
519                 tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
520             }
521         } while(token = iterator.stepBackward());
522
523         return null;
524     };
525     
526     this._pop = function(stack, tag) {
527         while (stack.length) {
528             
529             var top = stack[stack.length-1];
530             if (!tag || top.tagName == tag.tagName) {
531                 return stack.pop();
532             }
533             else if (this.optionalEndTags.hasOwnProperty(top.tagName)) {
534                 stack.pop();
535                 continue;
536             } else {
537                 return null;
538             }
539         }
540     };
541     
542     this.getFoldWidgetRange = function(session, foldStyle, row) {
543         var firstTag = this._getFirstTagInLine(session, row);
544         
545         if (!firstTag) {
546             return this.getCommentFoldWidget(session, row)
547                 && session.getCommentFoldRange(row, session.getLine(row).length);
548         }
549         
550         var isBackward = firstTag.closing || firstTag.selfClosing;
551         var stack = [];
552         var tag;
553         
554         if (!isBackward) {
555             var iterator = new TokenIterator(session, row, firstTag.start.column);
556             var start = {
557                 row: row,
558                 column: firstTag.start.column + firstTag.tagName.length + 2
559             };
560             if (firstTag.start.row == firstTag.end.row)
561                 start.column = firstTag.end.column;
562             while (tag = this._readTagForward(iterator)) {
563                 if (tag.selfClosing) {
564                     if (!stack.length) {
565                         tag.start.column += tag.tagName.length + 2;
566                         tag.end.column -= 2;
567                         return Range.fromPoints(tag.start, tag.end);
568                     } else
569                         continue;
570                 }
571                 
572                 if (tag.closing) {
573                     this._pop(stack, tag);
574                     if (stack.length == 0)
575                         return Range.fromPoints(start, tag.start);
576                 }
577                 else {
578                     stack.push(tag);
579                 }
580             }
581         }
582         else {
583             var iterator = new TokenIterator(session, row, firstTag.end.column);
584             var end = {
585                 row: row,
586                 column: firstTag.start.column
587             };
588             
589             while (tag = this._readTagBackward(iterator)) {
590                 if (tag.selfClosing) {
591                     if (!stack.length) {
592                         tag.start.column += tag.tagName.length + 2;
593                         tag.end.column -= 2;
594                         return Range.fromPoints(tag.start, tag.end);
595                     } else
596                         continue;
597                 }
598                 
599                 if (!tag.closing) {
600                     this._pop(stack, tag);
601                     if (stack.length == 0) {
602                         tag.start.column += tag.tagName.length + 2;
603                         if (tag.start.row == tag.end.row && tag.start.column < tag.end.column)
604                             tag.start.column = tag.end.column;
605                         return Range.fromPoints(tag.start, end);
606                     }
607                 }
608                 else {
609                     stack.push(tag);
610                 }
611             }
612         }
613         
614     };
615
616 }).call(FoldMode.prototype);
617
618 });
619
620 define("ace/mode/xml",["require","exports","module","ace/lib/oop","ace/lib/lang","ace/mode/text","ace/mode/xml_highlight_rules","ace/mode/behaviour/xml","ace/mode/folding/xml","ace/worker/worker_client"], function(require, exports, module) {
621 "use strict";
622
623 var oop = require("../lib/oop");
624 var lang = require("../lib/lang");
625 var TextMode = require("./text").Mode;
626 var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
627 var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;
628 var XmlFoldMode = require("./folding/xml").FoldMode;
629 var WorkerClient = require("../worker/worker_client").WorkerClient;
630
631 var Mode = function() {
632    this.HighlightRules = XmlHighlightRules;
633    this.$behaviour = new XmlBehaviour();
634    this.foldingRules = new XmlFoldMode();
635 };
636
637 oop.inherits(Mode, TextMode);
638
639 (function() {
640
641     this.voidElements = lang.arrayToMap([]);
642
643     this.blockComment = {start: "<!--", end: "-->"};
644
645     this.createWorker = function(session) {
646         var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
647         worker.attachToDocument(session.getDocument());
648
649         worker.on("error", function(e) {
650             session.setAnnotations(e.data);
651         });
652
653         worker.on("terminate", function() {
654             session.clearAnnotations();
655         });
656
657         return worker;
658     };
659     
660     this.$id = "ace/mode/xml";
661 }).call(Mode.prototype);
662
663 exports.Mode = Mode;
664 });