ace.define("ace/mode/xml_highlight_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], function (require, exports, module) {
  "use strict";

  var oop = require("../lib/oop");

  var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

  var XmlHighlightRules = function XmlHighlightRules(normalize) {
    var tagRegex = "[_:a-zA-Z\xC0-\uFFFF][-_:.a-zA-Z0-9\xC0-\uFFFF]*";
    this.$rules = {
      start: [{
        token: "string.cdata.xml",
        regex: "<\\!\\[CDATA\\[",
        next: "cdata"
      }, {
        token: ["punctuation.instruction.xml", "keyword.instruction.xml"],
        regex: "(<\\?)(" + tagRegex + ")",
        next: "processing_instruction"
      }, {
        token: "comment.start.xml",
        regex: "<\\!--",
        next: "comment"
      }, {
        token: ["xml-pe.doctype.xml", "xml-pe.doctype.xml"],
        regex: "(<\\!)(DOCTYPE)(?=[\\s])",
        next: "doctype",
        caseInsensitive: true
      }, {
        include: "tag"
      }, {
        token: "text.end-tag-open.xml",
        regex: "</"
      }, {
        token: "text.tag-open.xml",
        regex: "<"
      }, {
        include: "reference"
      }, {
        defaultToken: "text.xml"
      }],
      processing_instruction: [{
        token: "entity.other.attribute-name.decl-attribute-name.xml",
        regex: tagRegex
      }, {
        token: "keyword.operator.decl-attribute-equals.xml",
        regex: "="
      }, {
        include: "whitespace"
      }, {
        include: "string"
      }, {
        token: "punctuation.xml-decl.xml",
        regex: "\\?>",
        next: "start"
      }],
      doctype: [{
        include: "whitespace"
      }, {
        include: "string"
      }, {
        token: "xml-pe.doctype.xml",
        regex: ">",
        next: "start"
      }, {
        token: "xml-pe.xml",
        regex: "[-_a-zA-Z0-9:]+"
      }, {
        token: "punctuation.int-subset",
        regex: "\\[",
        push: "int_subset"
      }],
      int_subset: [{
        token: "text.xml",
        regex: "\\s+"
      }, {
        token: "punctuation.int-subset.xml",
        regex: "]",
        next: "pop"
      }, {
        token: ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"],
        regex: "(<\\!)(" + tagRegex + ")",
        push: [{
          token: "text",
          regex: "\\s+"
        }, {
          token: "punctuation.markup-decl.xml",
          regex: ">",
          next: "pop"
        }, {
          include: "string"
        }]
      }],
      cdata: [{
        token: "string.cdata.xml",
        regex: "\\]\\]>",
        next: "start"
      }, {
        token: "text.xml",
        regex: "\\s+"
      }, {
        token: "text.xml",
        regex: "(?:[^\\]]|\\](?!\\]>))+"
      }],
      comment: [{
        token: "comment.end.xml",
        regex: "-->",
        next: "start"
      }, {
        defaultToken: "comment.xml"
      }],
      reference: [{
        token: "constant.language.escape.reference.xml",
        regex: "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
      }],
      attr_reference: [{
        token: "constant.language.escape.reference.attribute-value.xml",
        regex: "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
      }],
      tag: [{
        token: ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"],
        regex: "(?:(<)|(</))((?:" + tagRegex + ":)?" + tagRegex + ")",
        next: [{
          include: "attributes"
        }, {
          token: "meta.tag.punctuation.tag-close.xml",
          regex: "/?>",
          next: "start"
        }]
      }],
      tag_whitespace: [{
        token: "text.tag-whitespace.xml",
        regex: "\\s+"
      }],
      whitespace: [{
        token: "text.whitespace.xml",
        regex: "\\s+"
      }],
      string: [{
        token: "string.xml",
        regex: "'",
        push: [{
          token: "string.xml",
          regex: "'",
          next: "pop"
        }, {
          defaultToken: "string.xml"
        }]
      }, {
        token: "string.xml",
        regex: '"',
        push: [{
          token: "string.xml",
          regex: '"',
          next: "pop"
        }, {
          defaultToken: "string.xml"
        }]
      }],
      attributes: [{
        token: "entity.other.attribute-name.xml",
        regex: tagRegex
      }, {
        token: "keyword.operator.attribute-equals.xml",
        regex: "="
      }, {
        include: "tag_whitespace"
      }, {
        include: "attribute_value"
      }],
      attribute_value: [{
        token: "string.attribute-value.xml",
        regex: "'",
        push: [{
          token: "string.attribute-value.xml",
          regex: "'",
          next: "pop"
        }, {
          include: "attr_reference"
        }, {
          defaultToken: "string.attribute-value.xml"
        }]
      }, {
        token: "string.attribute-value.xml",
        regex: '"',
        push: [{
          token: "string.attribute-value.xml",
          regex: '"',
          next: "pop"
        }, {
          include: "attr_reference"
        }, {
          defaultToken: "string.attribute-value.xml"
        }]
      }]
    };
    if (this.constructor === XmlHighlightRules) this.normalizeRules();
  };

  (function () {
    this.embedTagRules = function (HighlightRules, prefix, tag) {
      this.$rules.tag.unshift({
        token: ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
        regex: "(<)(" + tag + "(?=\\s|>|$))",
        next: [{
          include: "attributes"
        }, {
          token: "meta.tag.punctuation.tag-close.xml",
          regex: "/?>",
          next: prefix + "start"
        }]
      });
      this.$rules[tag + "-end"] = [{
        include: "attributes"
      }, {
        token: "meta.tag.punctuation.tag-close.xml",
        regex: "/?>",
        next: "start",
        onMatch: function onMatch(value, currentState, stack) {
          stack.splice(0);
          return this.token;
        }
      }];
      this.embedRules(HighlightRules, prefix, [{
        token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
        regex: "(</)(" + tag + "(?=\\s|>|$))",
        next: tag + "-end"
      }, {
        token: "string.cdata.xml",
        regex: "<\\!\\[CDATA\\["
      }, {
        token: "string.cdata.xml",
        regex: "\\]\\]>"
      }]);
    };
  }).call(TextHighlightRules.prototype);
  oop.inherits(XmlHighlightRules, TextHighlightRules);
  exports.XmlHighlightRules = XmlHighlightRules;
});
ace.define("ace/mode/behaviour/xml", ["require", "exports", "module", "ace/lib/oop", "ace/mode/behaviour", "ace/token_iterator", "ace/lib/lang"], function (require, exports, module) {
  "use strict";

  var oop = require("../../lib/oop");

  var Behaviour = require("../behaviour").Behaviour;

  var TokenIterator = require("../../token_iterator").TokenIterator;

  var lang = require("../../lib/lang");

  function is(token, type) {
    return token && token.type.lastIndexOf(type + ".xml") > -1;
  }

  var XmlBehaviour = function XmlBehaviour() {
    this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
      if (text == '"' || text == "'") {
        var quote = text;
        var selected = session.doc.getTextRange(editor.getSelectionRange());

        if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
          return {
            text: quote + selected + quote,
            selection: false
          };
        }

        var cursor = editor.getCursorPosition();
        var line = session.doc.getLine(cursor.row);
        var rightChar = line.substring(cursor.column, cursor.column + 1);
        var iterator = new TokenIterator(session, cursor.row, cursor.column);
        var token = iterator.getCurrentToken();

        if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
          return {
            text: "",
            selection: [1, 1]
          };
        }

        if (!token) token = iterator.stepBackward();
        if (!token) return;

        while (is(token, "tag-whitespace") || is(token, "whitespace")) {
          token = iterator.stepBackward();
        }

        var rightSpace = !rightChar || rightChar.match(/\s/);

        if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?')) {
          return {
            text: quote + quote,
            selection: [1, 1]
          };
        }
      }
    });
    this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
      var selected = session.doc.getTextRange(range);

      if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
        var line = session.doc.getLine(range.start.row);
        var rightChar = line.substring(range.start.column + 1, range.start.column + 2);

        if (rightChar == selected) {
          range.end.column++;
          return range;
        }
      }
    });
    this.add("autoclosing", "insertion", function (state, action, editor, session, text) {
      if (text == '>') {
        var position = editor.getSelectionRange().start;
        var iterator = new TokenIterator(session, position.row, position.column);
        var token = iterator.getCurrentToken() || iterator.stepBackward();
        if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value"))) return;
        if (is(token, "reference.attribute-value")) return;

        if (is(token, "attribute-value")) {
          var tokenEndColumn = iterator.getCurrentTokenColumn() + token.value.length;
          if (position.column < tokenEndColumn) return;

          if (position.column == tokenEndColumn) {
            var nextToken = iterator.stepForward();
            if (nextToken && is(nextToken, "attribute-value")) return;
            iterator.stepBackward();
          }
        }

        if (/^\s*>/.test(session.getLine(position.row).slice(position.column))) return;

        while (!is(token, "tag-name")) {
          token = iterator.stepBackward();

          if (token.value == "<") {
            token = iterator.stepForward();
            break;
          }
        }

        var tokenRow = iterator.getCurrentTokenRow();
        var tokenColumn = iterator.getCurrentTokenColumn();
        if (is(iterator.stepBackward(), "end-tag-open")) return;
        var element = token.value;
        if (tokenRow == position.row) element = element.substring(0, position.column - tokenColumn);
        if (this.voidElements.hasOwnProperty(element.toLowerCase())) return;
        return {
          text: ">" + "</" + element + ">",
          selection: [1, 1]
        };
      }
    });
    this.add("autoindent", "insertion", function (state, action, editor, session, text) {
      if (text == "\n") {
        var cursor = editor.getCursorPosition();
        var line = session.getLine(cursor.row);
        var iterator = new TokenIterator(session, cursor.row, cursor.column);
        var token = iterator.getCurrentToken();

        if (token && token.type.indexOf("tag-close") !== -1) {
          if (token.value == "/>") return;

          while (token && token.type.indexOf("tag-name") === -1) {
            token = iterator.stepBackward();
          }

          if (!token) {
            return;
          }

          var tag = token.value;
          var row = iterator.getCurrentTokenRow();
          token = iterator.stepBackward();

          if (!token || token.type.indexOf("end-tag") !== -1) {
            return;
          }

          if (this.voidElements && !this.voidElements[tag]) {
            var nextToken = session.getTokenAt(cursor.row, cursor.column + 1);
            var line = session.getLine(row);
            var nextIndent = this.$getIndent(line);
            var indent = nextIndent + session.getTabString();

            if (nextToken && nextToken.value === "</") {
              return {
                text: "\n" + indent + "\n" + nextIndent,
                selection: [1, indent.length, 1, indent.length]
              };
            } else {
              return {
                text: "\n" + indent
              };
            }
          }
        }
      }
    });
  };

  oop.inherits(XmlBehaviour, Behaviour);
  exports.XmlBehaviour = XmlBehaviour;
});
ace.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) {
  "use strict";

  var oop = require("../../lib/oop");

  var lang = require("../../lib/lang");

  var Range = require("../../range").Range;

  var BaseFoldMode = require("./fold_mode").FoldMode;

  var TokenIterator = require("../../token_iterator").TokenIterator;

  var FoldMode = exports.FoldMode = function (voidElements, optionalEndTags) {
    BaseFoldMode.call(this);
    this.voidElements = voidElements || {};
    this.optionalEndTags = oop.mixin({}, this.voidElements);
    if (optionalEndTags) oop.mixin(this.optionalEndTags, optionalEndTags);
  };

  oop.inherits(FoldMode, BaseFoldMode);

  var Tag = function Tag() {
    this.tagName = "";
    this.closing = false;
    this.selfClosing = false;
    this.start = {
      row: 0,
      column: 0
    };
    this.end = {
      row: 0,
      column: 0
    };
  };

  function is(token, type) {
    return token.type.lastIndexOf(type + ".xml") > -1;
  }

  (function () {
    this.getFoldWidget = function (session, foldStyle, row) {
      var tag = this._getFirstTagInLine(session, row);

      if (!tag) return this.getCommentFoldWidget(session, row);
      if (tag.closing || !tag.tagName && tag.selfClosing) return foldStyle == "markbeginend" ? "end" : "";
      if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase())) return "";
      if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column)) return "";
      return "start";
    };

    this.getCommentFoldWidget = function (session, row) {
      if (/comment/.test(session.getState(row)) && /<!-/.test(session.getLine(row))) return "start";
      return "";
    };

    this._getFirstTagInLine = function (session, row) {
      var tokens = session.getTokens(row);
      var tag = new Tag();

      for (var i = 0; i < tokens.length; i++) {
        var token = tokens[i];

        if (is(token, "tag-open")) {
          tag.end.column = tag.start.column + token.value.length;
          tag.closing = is(token, "end-tag-open");
          token = tokens[++i];
          if (!token) return null;
          tag.tagName = token.value;
          tag.end.column += token.value.length;

          for (i++; i < tokens.length; i++) {
            token = tokens[i];
            tag.end.column += token.value.length;

            if (is(token, "tag-close")) {
              tag.selfClosing = token.value == '/>';
              break;
            }
          }

          return tag;
        } else if (is(token, "tag-close")) {
          tag.selfClosing = token.value == '/>';
          return tag;
        }

        tag.start.column += token.value.length;
      }

      return null;
    };

    this._findEndTagInLine = function (session, row, tagName, startColumn) {
      var tokens = session.getTokens(row);
      var column = 0;

      for (var i = 0; i < tokens.length; i++) {
        var token = tokens[i];
        column += token.value.length;
        if (column < startColumn) continue;

        if (is(token, "end-tag-open")) {
          token = tokens[i + 1];
          if (token && token.value == tagName) return true;
        }
      }

      return false;
    };

    this._readTagForward = function (iterator) {
      var token = iterator.getCurrentToken();
      if (!token) return null;
      var tag = new Tag();

      do {
        if (is(token, "tag-open")) {
          tag.closing = is(token, "end-tag-open");
          tag.start.row = iterator.getCurrentTokenRow();
          tag.start.column = iterator.getCurrentTokenColumn();
        } else if (is(token, "tag-name")) {
          tag.tagName = token.value;
        } else if (is(token, "tag-close")) {
          tag.selfClosing = token.value == "/>";
          tag.end.row = iterator.getCurrentTokenRow();
          tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
          iterator.stepForward();
          return tag;
        }
      } while (token = iterator.stepForward());

      return null;
    };

    this._readTagBackward = function (iterator) {
      var token = iterator.getCurrentToken();
      if (!token) return null;
      var tag = new Tag();

      do {
        if (is(token, "tag-open")) {
          tag.closing = is(token, "end-tag-open");
          tag.start.row = iterator.getCurrentTokenRow();
          tag.start.column = iterator.getCurrentTokenColumn();
          iterator.stepBackward();
          return tag;
        } else if (is(token, "tag-name")) {
          tag.tagName = token.value;
        } else if (is(token, "tag-close")) {
          tag.selfClosing = token.value == "/>";
          tag.end.row = iterator.getCurrentTokenRow();
          tag.end.column = iterator.getCurrentTokenColumn() + token.value.length;
        }
      } while (token = iterator.stepBackward());

      return null;
    };

    this._pop = function (stack, tag) {
      while (stack.length) {
        var top = stack[stack.length - 1];

        if (!tag || top.tagName == tag.tagName) {
          return stack.pop();
        } else if (this.optionalEndTags.hasOwnProperty(top.tagName)) {
          stack.pop();
          continue;
        } else {
          return null;
        }
      }
    };

    this.getFoldWidgetRange = function (session, foldStyle, row) {
      var firstTag = this._getFirstTagInLine(session, row);

      if (!firstTag) {
        return this.getCommentFoldWidget(session, row) && session.getCommentFoldRange(row, session.getLine(row).length);
      }

      var isBackward = firstTag.closing || firstTag.selfClosing;
      var stack = [];
      var tag;

      if (!isBackward) {
        var iterator = new TokenIterator(session, row, firstTag.start.column);
        var start = {
          row: row,
          column: firstTag.start.column + firstTag.tagName.length + 2
        };
        if (firstTag.start.row == firstTag.end.row) start.column = firstTag.end.column;

        while (tag = this._readTagForward(iterator)) {
          if (tag.selfClosing) {
            if (!stack.length) {
              tag.start.column += tag.tagName.length + 2;
              tag.end.column -= 2;
              return Range.fromPoints(tag.start, tag.end);
            } else continue;
          }

          if (tag.closing) {
            this._pop(stack, tag);

            if (stack.length == 0) return Range.fromPoints(start, tag.start);
          } else {
            stack.push(tag);
          }
        }
      } else {
        var iterator = new TokenIterator(session, row, firstTag.end.column);
        var end = {
          row: row,
          column: firstTag.start.column
        };

        while (tag = this._readTagBackward(iterator)) {
          if (tag.selfClosing) {
            if (!stack.length) {
              tag.start.column += tag.tagName.length + 2;
              tag.end.column -= 2;
              return Range.fromPoints(tag.start, tag.end);
            } else continue;
          }

          if (!tag.closing) {
            this._pop(stack, tag);

            if (stack.length == 0) {
              tag.start.column += tag.tagName.length + 2;
              if (tag.start.row == tag.end.row && tag.start.column < tag.end.column) tag.start.column = tag.end.column;
              return Range.fromPoints(tag.start, end);
            }
          } else {
            stack.push(tag);
          }
        }
      }
    };
  }).call(FoldMode.prototype);
});
ace.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) {
  "use strict";

  var oop = require("../lib/oop");

  var lang = require("../lib/lang");

  var TextMode = require("./text").Mode;

  var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;

  var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;

  var XmlFoldMode = require("./folding/xml").FoldMode;

  var WorkerClient = require("../worker/worker_client").WorkerClient;

  var Mode = function Mode() {
    this.HighlightRules = XmlHighlightRules;
    this.$behaviour = new XmlBehaviour();
    this.foldingRules = new XmlFoldMode();
  };

  oop.inherits(Mode, TextMode);
  (function () {
    this.voidElements = lang.arrayToMap([]);
    this.blockComment = {
      start: "<!--",
      end: "-->"
    };

    this.createWorker = function (session) {
      var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
      worker.attachToDocument(session.getDocument());
      worker.on("error", function (e) {
        session.setAnnotations(e.data);
      });
      worker.on("terminate", function () {
        session.clearAnnotations();
      });
      return worker;
    };

    this.$id = "ace/mode/xml";
  }).call(Mode.prototype);
  exports.Mode = Mode;
});

(function () {
  ace.require(["ace/mode/xml"], function (m) {
    if (typeof module == "object" && typeof exports == "object" && module) {
      module.exports = m;
    }
  });
})();