1 define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module) {
4 var oop = require("../lib/oop");
5 var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
7 var XmlHighlightRules = function(normalize) {
8 var tagRegex = "[_:a-zA-Z\xc0-\uffff][-_:.a-zA-Z0-9\xc0-\uffff]*";
12 {token : "string.cdata.xml", regex : "<\\!\\[CDATA\\[", next : "cdata"},
14 token : ["punctuation.instruction.xml", "keyword.instruction.xml"],
15 regex : "(<\\?)(" + tagRegex + ")", next : "processing_instruction"
17 {token : "comment.start.xml", regex : "<\\!--", next : "comment"},
19 token : ["xml-pe.doctype.xml", "xml-pe.doctype.xml"],
20 regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype", caseInsensitive: true
23 {token : "text.end-tag-open.xml", regex: "</"},
24 {token : "text.tag-open.xml", regex: "<"},
25 {include : "reference"},
26 {defaultToken : "text.xml"}
29 processing_instruction : [{
30 token : "entity.other.attribute-name.decl-attribute-name.xml",
33 token : "keyword.operator.decl-attribute-equals.xml",
40 token : "punctuation.xml-decl.xml",
46 {include : "whitespace"},
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"}
57 token: "punctuation.int-subset.xml",
61 token : ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"],
62 regex : "(<\\!)(" + tagRegex + ")",
68 token : "punctuation.markup-decl.xml",
76 {token : "string.cdata.xml", regex : "\\]\\]>", next : "start"},
77 {token : "text.xml", regex : "\\s+"},
78 {token : "text.xml", regex : "(?:[^\\]]|\\](?!\\]>))+"}
82 {token : "comment.end.xml", regex : "-->", next : "start"},
83 {defaultToken : "comment.xml"}
87 token : "constant.language.escape.reference.xml",
88 regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
92 token : "constant.language.escape.reference.attribute-value.xml",
93 regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
97 token : ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"],
98 regex : "(?:(<)|(</))((?:" + tagRegex + ":)?" + tagRegex + ")",
100 {include : "attributes"},
101 {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : "start"}
106 {token : "text.tag-whitespace.xml", regex : "\\s+"}
109 {token : "text.whitespace.xml", regex : "\\s+"}
112 token : "string.xml",
115 {token : "string.xml", regex: "'", next: "pop"},
116 {defaultToken : "string.xml"}
119 token : "string.xml",
122 {token : "string.xml", regex: '"', next: "pop"},
123 {defaultToken : "string.xml"}
128 token : "entity.other.attribute-name.xml",
131 token : "keyword.operator.attribute-equals.xml",
134 include: "tag_whitespace"
136 include: "attribute_value"
140 token : "string.attribute-value.xml",
143 {token : "string.attribute-value.xml", regex: "'", next: "pop"},
144 {include : "attr_reference"},
145 {defaultToken : "string.attribute-value.xml"}
148 token : "string.attribute-value.xml",
151 {token : "string.attribute-value.xml", regex: '"', next: "pop"},
152 {include : "attr_reference"},
153 {defaultToken : "string.attribute-value.xml"}
158 if (this.constructor === XmlHighlightRules)
159 this.normalizeRules();
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|>|$))",
170 {include : "attributes"},
171 {token : "meta.tag.punctuation.tag-close.xml", regex : "/?>", next : prefix + "start"}
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) {
184 this.embedRules(HighlightRules, prefix, [{
185 token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
186 regex : "(</)(" + tag + "(?=\\s|>|$))",
189 token: "string.cdata.xml",
190 regex : "<\\!\\[CDATA\\["
192 token: "string.cdata.xml",
197 }).call(TextHighlightRules.prototype);
199 oop.inherits(XmlHighlightRules, TextHighlightRules);
201 exports.XmlHighlightRules = XmlHighlightRules;
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) {
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");
212 function is(token, type) {
213 return token.type.lastIndexOf(type + ".xml") > -1;
216 var XmlBehaviour = function () {
218 this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
219 if (text == '"' || text == "'") {
221 var selected = session.doc.getTextRange(editor.getSelectionRange());
222 if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
224 text: quote + selected + quote,
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();
235 if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
243 token = iterator.stepBackward();
248 while (is(token, "tag-whitespace") || is(token, "whitespace")) {
249 token = iterator.stepBackward();
251 var rightSpace = !rightChar || rightChar.match(/\s/);
252 if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) {
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) {
273 this.add("autoclosing", "insertion", function (state, action, editor, session, 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")))
280 if (is(token, "reference.attribute-value"))
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)
291 while (!is(token, "tag-name")) {
292 token = iterator.stepBackward();
293 if (token.value == "<") {
294 token = iterator.stepForward();
299 var tokenRow = iterator.getCurrentTokenRow();
300 var tokenColumn = iterator.getCurrentTokenColumn();
301 if (is(iterator.stepBackward(), "end-tag-open"))
304 var element = token.value;
305 if (tokenRow == position.row)
306 element = element.substring(0, position.column - tokenColumn);
308 if (this.voidElements.hasOwnProperty(element.toLowerCase()))
312 text: ">" + "</" + element + ">",
318 this.add("autoindent", "insertion", function (state, action, editor, session, text) {
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();
325 if (token && token.type.indexOf("tag-close") !== -1) {
326 if (token.value == "/>")
328 while (token && token.type.indexOf("tag-name") === -1) {
329 token = iterator.stepBackward();
336 var tag = token.value;
337 var row = iterator.getCurrentTokenRow();
338 token = iterator.stepBackward();
339 if (!token || token.type.indexOf("end-tag") !== -1) {
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();
349 if (nextToken && nextToken.value === "</") {
351 text: "\n" + indent + "\n" + nextIndent,
352 selection: [1, indent.length, 1, indent.length]
366 oop.inherits(XmlBehaviour, Behaviour);
368 exports.XmlBehaviour = XmlBehaviour;
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) {
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;
380 var FoldMode = exports.FoldMode = function(voidElements, optionalEndTags) {
381 BaseFoldMode.call(this);
382 this.voidElements = voidElements || {};
383 this.optionalEndTags = oop.mixin({}, this.voidElements);
385 oop.mixin(this.optionalEndTags, optionalEndTags);
388 oop.inherits(FoldMode, BaseFoldMode);
390 var Tag = function() {
392 this.closing = false;
393 this.selfClosing = false;
394 this.start = {row: 0, column: 0};
395 this.end = {row: 0, column: 0};
398 function is(token, type) {
399 return token.type.lastIndexOf(type + ".xml") > -1;
404 this.getFoldWidget = function(session, foldStyle, row) {
405 var tag = this._getFirstTagInLine(session, row);
408 return this.getCommentFoldWidget(session, row);
410 if (tag.closing || (!tag.tagName && tag.selfClosing))
411 return foldStyle == "markbeginend" ? "end" : "";
413 if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase()))
416 if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column))
422 this.getCommentFoldWidget = function(session, row) {
423 if (/comment/.test(session.getState(row)) && /<!-/.test(session.getLine(row)))
427 this._getFirstTagInLine = function(session, row) {
428 var tokens = session.getTokens(row);
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");
439 tag.tagName = token.value;
440 tag.end.column += token.value.length;
441 for (i++; i < tokens.length; i++) {
443 tag.end.column += token.value.length;
444 if (is(token, "tag-close")) {
445 tag.selfClosing = token.value == '/>';
450 } else if (is(token, "tag-close")) {
451 tag.selfClosing = token.value == '/>';
454 tag.start.column += token.value.length;
460 this._findEndTagInLine = function(session, row, tagName, startColumn) {
461 var tokens = session.getTokens(row);
463 for (var i = 0; i < tokens.length; i++) {
464 var token = tokens[i];
465 column += token.value.length;
466 if (column < startColumn)
468 if (is(token, "end-tag-open")) {
469 token = tokens[i + 1];
470 if (token && token.value == tagName)
476 this._readTagForward = function(iterator) {
477 var token = iterator.getCurrentToken();
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();
496 } while(token = iterator.stepForward());
501 this._readTagBackward = function(iterator) {
502 var token = iterator.getCurrentToken();
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();
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;
521 } while(token = iterator.stepBackward());
526 this._pop = function(stack, tag) {
527 while (stack.length) {
529 var top = stack[stack.length-1];
530 if (!tag || top.tagName == tag.tagName) {
533 else if (this.optionalEndTags.hasOwnProperty(top.tagName)) {
542 this.getFoldWidgetRange = function(session, foldStyle, row) {
543 var firstTag = this._getFirstTagInLine(session, row);
546 return this.getCommentFoldWidget(session, row)
547 && session.getCommentFoldRange(row, session.getLine(row).length);
550 var isBackward = firstTag.closing || firstTag.selfClosing;
555 var iterator = new TokenIterator(session, row, firstTag.start.column);
558 column: firstTag.start.column + firstTag.tagName.length + 2
560 if (firstTag.start.row == firstTag.end.row)
561 start.column = firstTag.end.column;
562 while (tag = this._readTagForward(iterator)) {
563 if (tag.selfClosing) {
565 tag.start.column += tag.tagName.length + 2;
567 return Range.fromPoints(tag.start, tag.end);
573 this._pop(stack, tag);
574 if (stack.length == 0)
575 return Range.fromPoints(start, tag.start);
583 var iterator = new TokenIterator(session, row, firstTag.end.column);
586 column: firstTag.start.column
589 while (tag = this._readTagBackward(iterator)) {
590 if (tag.selfClosing) {
592 tag.start.column += tag.tagName.length + 2;
594 return Range.fromPoints(tag.start, tag.end);
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);
616 }).call(FoldMode.prototype);
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) {
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;
631 var Mode = function() {
632 this.HighlightRules = XmlHighlightRules;
633 this.$behaviour = new XmlBehaviour();
634 this.foldingRules = new XmlFoldMode();
637 oop.inherits(Mode, TextMode);
641 this.voidElements = lang.arrayToMap([]);
643 this.blockComment = {start: "<!--", end: "-->"};
645 this.createWorker = function(session) {
646 var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
647 worker.attachToDocument(session.getDocument());
649 worker.on("error", function(e) {
650 session.setAnnotations(e.data);
653 worker.on("terminate", function() {
654 session.clearAnnotations();
660 this.$id = "ace/mode/xml";
661 }).call(Mode.prototype);