mode-xml-6468964d.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. ace.define("ace/mode/xml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(require, exports, module){"use strict";
  2. var oop = require("../lib/oop");
  3. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  4. var XmlHighlightRules = function (normalize) {
  5. var tagRegex = "[_:a-zA-Z\xc0-\uffff][-_:.a-zA-Z0-9\xc0-\uffff]*";
  6. this.$rules = {
  7. start: [
  8. { token: "string.cdata.xml", regex: "<\\!\\[CDATA\\[", next: "cdata" },
  9. {
  10. token: ["punctuation.instruction.xml", "keyword.instruction.xml"],
  11. regex: "(<\\?)(" + tagRegex + ")", next: "processing_instruction"
  12. },
  13. { token: "comment.start.xml", regex: "<\\!--", next: "comment" },
  14. {
  15. token: ["xml-pe.doctype.xml", "xml-pe.doctype.xml"],
  16. regex: "(<\\!)(DOCTYPE)(?=[\\s])", next: "doctype", caseInsensitive: true
  17. },
  18. { include: "tag" },
  19. { token: "text.end-tag-open.xml", regex: "</" },
  20. { token: "text.tag-open.xml", regex: "<" },
  21. { include: "reference" },
  22. { defaultToken: "text.xml" }
  23. ],
  24. processing_instruction: [{
  25. token: "entity.other.attribute-name.decl-attribute-name.xml",
  26. regex: tagRegex
  27. }, {
  28. token: "keyword.operator.decl-attribute-equals.xml",
  29. regex: "="
  30. }, {
  31. include: "whitespace"
  32. }, {
  33. include: "string"
  34. }, {
  35. token: "punctuation.xml-decl.xml",
  36. regex: "\\?>",
  37. next: "start"
  38. }],
  39. doctype: [
  40. { include: "whitespace" },
  41. { include: "string" },
  42. { token: "xml-pe.doctype.xml", regex: ">", next: "start" },
  43. { token: "xml-pe.xml", regex: "[-_a-zA-Z0-9:]+" },
  44. { token: "punctuation.int-subset", regex: "\\[", push: "int_subset" }
  45. ],
  46. int_subset: [{
  47. token: "text.xml",
  48. regex: "\\s+"
  49. }, {
  50. token: "punctuation.int-subset.xml",
  51. regex: "]",
  52. next: "pop"
  53. }, {
  54. token: ["punctuation.markup-decl.xml", "keyword.markup-decl.xml"],
  55. regex: "(<\\!)(" + tagRegex + ")",
  56. push: [{
  57. token: "text",
  58. regex: "\\s+"
  59. },
  60. {
  61. token: "punctuation.markup-decl.xml",
  62. regex: ">",
  63. next: "pop"
  64. },
  65. { include: "string" }]
  66. }],
  67. cdata: [
  68. { token: "string.cdata.xml", regex: "\\]\\]>", next: "start" },
  69. { token: "text.xml", regex: "\\s+" },
  70. { token: "text.xml", regex: "(?:[^\\]]|\\](?!\\]>))+" }
  71. ],
  72. comment: [
  73. { token: "comment.end.xml", regex: "-->", next: "start" },
  74. { defaultToken: "comment.xml" }
  75. ],
  76. reference: [{
  77. token: "constant.language.escape.reference.xml",
  78. regex: "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
  79. }],
  80. attr_reference: [{
  81. token: "constant.language.escape.reference.attribute-value.xml",
  82. regex: "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)"
  83. }],
  84. tag: [{
  85. token: ["meta.tag.punctuation.tag-open.xml", "meta.tag.punctuation.end-tag-open.xml", "meta.tag.tag-name.xml"],
  86. regex: "(?:(<)|(</))((?:" + tagRegex + ":)?" + tagRegex + ")",
  87. next: [
  88. { include: "attributes" },
  89. { token: "meta.tag.punctuation.tag-close.xml", regex: "/?>", next: "start" }
  90. ]
  91. }],
  92. tag_whitespace: [
  93. { token: "text.tag-whitespace.xml", regex: "\\s+" }
  94. ],
  95. whitespace: [
  96. { token: "text.whitespace.xml", regex: "\\s+" }
  97. ],
  98. string: [{
  99. token: "string.xml",
  100. regex: "'",
  101. push: [
  102. { token: "string.xml", regex: "'", next: "pop" },
  103. { defaultToken: "string.xml" }
  104. ]
  105. }, {
  106. token: "string.xml",
  107. regex: '"',
  108. push: [
  109. { token: "string.xml", regex: '"', next: "pop" },
  110. { defaultToken: "string.xml" }
  111. ]
  112. }],
  113. attributes: [{
  114. token: "entity.other.attribute-name.xml",
  115. regex: tagRegex
  116. }, {
  117. token: "keyword.operator.attribute-equals.xml",
  118. regex: "="
  119. }, {
  120. include: "tag_whitespace"
  121. }, {
  122. include: "attribute_value"
  123. }],
  124. attribute_value: [{
  125. token: "string.attribute-value.xml",
  126. regex: "'",
  127. push: [
  128. { token: "string.attribute-value.xml", regex: "'", next: "pop" },
  129. { include: "attr_reference" },
  130. { defaultToken: "string.attribute-value.xml" }
  131. ]
  132. }, {
  133. token: "string.attribute-value.xml",
  134. regex: '"',
  135. push: [
  136. { token: "string.attribute-value.xml", regex: '"', next: "pop" },
  137. { include: "attr_reference" },
  138. { defaultToken: "string.attribute-value.xml" }
  139. ]
  140. }]
  141. };
  142. if (this.constructor === XmlHighlightRules)
  143. this.normalizeRules();
  144. };
  145. (function () {
  146. this.embedTagRules = function (HighlightRules, prefix, tag) {
  147. this.$rules.tag.unshift({
  148. token: ["meta.tag.punctuation.tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
  149. regex: "(<)(" + tag + "(?=\\s|>|$))",
  150. next: [
  151. { include: "attributes" },
  152. { token: "meta.tag.punctuation.tag-close.xml", regex: "/?>", next: prefix + "start" }
  153. ]
  154. });
  155. this.$rules[tag + "-end"] = [
  156. { include: "attributes" },
  157. { token: "meta.tag.punctuation.tag-close.xml", regex: "/?>", next: "start",
  158. onMatch: function (value, currentState, stack) {
  159. stack.splice(0);
  160. return this.token;
  161. } }
  162. ];
  163. this.embedRules(HighlightRules, prefix, [{
  164. token: ["meta.tag.punctuation.end-tag-open.xml", "meta.tag." + tag + ".tag-name.xml"],
  165. regex: "(</)(" + tag + "(?=\\s|>|$))",
  166. next: tag + "-end"
  167. }, {
  168. token: "string.cdata.xml",
  169. regex: "<\\!\\[CDATA\\["
  170. }, {
  171. token: "string.cdata.xml",
  172. regex: "\\]\\]>"
  173. }]);
  174. };
  175. }).call(TextHighlightRules.prototype);
  176. oop.inherits(XmlHighlightRules, TextHighlightRules);
  177. exports.XmlHighlightRules = XmlHighlightRules;
  178. });
  179. 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";
  180. var oop = require("../../lib/oop");
  181. var Behaviour = require("../behaviour").Behaviour;
  182. var TokenIterator = require("../../token_iterator").TokenIterator;
  183. var lang = require("../../lib/lang");
  184. function is(token, type) {
  185. return token && token.type.lastIndexOf(type + ".xml") > -1;
  186. }
  187. var XmlBehaviour = function () {
  188. this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
  189. if (text == '"' || text == "'") {
  190. var quote = text;
  191. var selected = session.doc.getTextRange(editor.getSelectionRange());
  192. if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
  193. return {
  194. text: quote + selected + quote,
  195. selection: false
  196. };
  197. }
  198. var cursor = editor.getCursorPosition();
  199. var line = session.doc.getLine(cursor.row);
  200. var rightChar = line.substring(cursor.column, cursor.column + 1);
  201. var iterator = new TokenIterator(session, cursor.row, cursor.column);
  202. var token = iterator.getCurrentToken();
  203. if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
  204. return {
  205. text: "",
  206. selection: [1, 1]
  207. };
  208. }
  209. if (!token)
  210. token = iterator.stepBackward();
  211. if (!token)
  212. return;
  213. while (is(token, "tag-whitespace") || is(token, "whitespace")) {
  214. token = iterator.stepBackward();
  215. }
  216. var rightSpace = !rightChar || rightChar.match(/\s/);
  217. if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) {
  218. return {
  219. text: quote + quote,
  220. selection: [1, 1]
  221. };
  222. }
  223. }
  224. });
  225. this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
  226. var selected = session.doc.getTextRange(range);
  227. if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
  228. var line = session.doc.getLine(range.start.row);
  229. var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
  230. if (rightChar == selected) {
  231. range.end.column++;
  232. return range;
  233. }
  234. }
  235. });
  236. this.add("autoclosing", "insertion", function (state, action, editor, session, text) {
  237. if (text == '>') {
  238. var position = editor.getSelectionRange().start;
  239. var iterator = new TokenIterator(session, position.row, position.column);
  240. var token = iterator.getCurrentToken() || iterator.stepBackward();
  241. if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value")))
  242. return;
  243. if (is(token, "reference.attribute-value"))
  244. return;
  245. if (is(token, "attribute-value")) {
  246. var tokenEndColumn = iterator.getCurrentTokenColumn() + token.value.length;
  247. if (position.column < tokenEndColumn)
  248. return;
  249. if (position.column == tokenEndColumn) {
  250. var nextToken = iterator.stepForward();
  251. if (nextToken && is(nextToken, "attribute-value"))
  252. return;
  253. iterator.stepBackward();
  254. }
  255. }
  256. if (/^\s*>/.test(session.getLine(position.row).slice(position.column)))
  257. return;
  258. while (!is(token, "tag-name")) {
  259. token = iterator.stepBackward();
  260. if (token.value == "<") {
  261. token = iterator.stepForward();
  262. break;
  263. }
  264. }
  265. var tokenRow = iterator.getCurrentTokenRow();
  266. var tokenColumn = iterator.getCurrentTokenColumn();
  267. if (is(iterator.stepBackward(), "end-tag-open"))
  268. return;
  269. var element = token.value;
  270. if (tokenRow == position.row)
  271. element = element.substring(0, position.column - tokenColumn);
  272. if (this.voidElements.hasOwnProperty(element.toLowerCase()))
  273. return;
  274. return {
  275. text: ">" + "</" + element + ">",
  276. selection: [1, 1]
  277. };
  278. }
  279. });
  280. this.add("autoindent", "insertion", function (state, action, editor, session, text) {
  281. if (text == "\n") {
  282. var cursor = editor.getCursorPosition();
  283. var line = session.getLine(cursor.row);
  284. var iterator = new TokenIterator(session, cursor.row, cursor.column);
  285. var token = iterator.getCurrentToken();
  286. if (token && token.type.indexOf("tag-close") !== -1) {
  287. if (token.value == "/>")
  288. return;
  289. while (token && token.type.indexOf("tag-name") === -1) {
  290. token = iterator.stepBackward();
  291. }
  292. if (!token) {
  293. return;
  294. }
  295. var tag = token.value;
  296. var row = iterator.getCurrentTokenRow();
  297. token = iterator.stepBackward();
  298. if (!token || token.type.indexOf("end-tag") !== -1) {
  299. return;
  300. }
  301. if (this.voidElements && !this.voidElements[tag]) {
  302. var nextToken = session.getTokenAt(cursor.row, cursor.column + 1);
  303. var line = session.getLine(row);
  304. var nextIndent = this.$getIndent(line);
  305. var indent = nextIndent + session.getTabString();
  306. if (nextToken && nextToken.value === "</") {
  307. return {
  308. text: "\n" + indent + "\n" + nextIndent,
  309. selection: [1, indent.length, 1, indent.length]
  310. };
  311. }
  312. else {
  313. return {
  314. text: "\n" + indent
  315. };
  316. }
  317. }
  318. }
  319. }
  320. });
  321. };
  322. oop.inherits(XmlBehaviour, Behaviour);
  323. exports.XmlBehaviour = XmlBehaviour;
  324. });
  325. ace.define("ace/mode/folding/xml",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"], function(require, exports, module){"use strict";
  326. var oop = require("../../lib/oop");
  327. var Range = require("../../range").Range;
  328. var BaseFoldMode = require("./fold_mode").FoldMode;
  329. var FoldMode = exports.FoldMode = function (voidElements, optionalEndTags) {
  330. BaseFoldMode.call(this);
  331. this.voidElements = voidElements || {};
  332. this.optionalEndTags = oop.mixin({}, this.voidElements);
  333. if (optionalEndTags)
  334. oop.mixin(this.optionalEndTags, optionalEndTags);
  335. };
  336. oop.inherits(FoldMode, BaseFoldMode);
  337. var Tag = function () {
  338. this.tagName = "";
  339. this.closing = false;
  340. this.selfClosing = false;
  341. this.start = { row: 0, column: 0 };
  342. this.end = { row: 0, column: 0 };
  343. };
  344. function is(token, type) {
  345. return token.type.lastIndexOf(type + ".xml") > -1;
  346. }
  347. (function () {
  348. this.getFoldWidget = function (session, foldStyle, row) {
  349. var tag = this._getFirstTagInLine(session, row);
  350. if (!tag)
  351. return this.getCommentFoldWidget(session, row);
  352. if (tag.closing || (!tag.tagName && tag.selfClosing))
  353. return foldStyle === "markbeginend" ? "end" : "";
  354. if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase()))
  355. return "";
  356. if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column))
  357. return "";
  358. return "start";
  359. };
  360. this.getCommentFoldWidget = function (session, row) {
  361. if (/comment/.test(session.getState(row)) && /<!-/.test(session.getLine(row)))
  362. return "start";
  363. return "";
  364. };
  365. this._getFirstTagInLine = function (session, row) {
  366. var tokens = session.getTokens(row);
  367. var tag = new Tag();
  368. for (var i = 0; i < tokens.length; i++) {
  369. var token = tokens[i];
  370. if (is(token, "tag-open")) {
  371. tag.end.column = tag.start.column + token.value.length;
  372. tag.closing = is(token, "end-tag-open");
  373. token = tokens[++i];
  374. if (!token)
  375. return null;
  376. tag.tagName = token.value;
  377. tag.end.column += token.value.length;
  378. for (i++; i < tokens.length; i++) {
  379. token = tokens[i];
  380. tag.end.column += token.value.length;
  381. if (is(token, "tag-close")) {
  382. tag.selfClosing = token.value == '/>';
  383. break;
  384. }
  385. }
  386. return tag;
  387. }
  388. else if (is(token, "tag-close")) {
  389. tag.selfClosing = token.value == '/>';
  390. return tag;
  391. }
  392. tag.start.column += token.value.length;
  393. }
  394. return null;
  395. };
  396. this._findEndTagInLine = function (session, row, tagName, startColumn) {
  397. var tokens = session.getTokens(row);
  398. var column = 0;
  399. for (var i = 0; i < tokens.length; i++) {
  400. var token = tokens[i];
  401. column += token.value.length;
  402. if (column < startColumn)
  403. continue;
  404. if (is(token, "end-tag-open")) {
  405. token = tokens[i + 1];
  406. if (token && token.value == tagName)
  407. return true;
  408. }
  409. }
  410. return false;
  411. };
  412. this.getFoldWidgetRange = function (session, foldStyle, row) {
  413. var tags = session.getMatchingTags({ row: row, column: 0 });
  414. if (tags) {
  415. return new Range(tags.openTag.end.row, tags.openTag.end.column, tags.closeTag.start.row, tags.closeTag.start.column);
  416. }
  417. else {
  418. return this.getCommentFoldWidget(session, row)
  419. && session.getCommentFoldRange(row, session.getLine(row).length);
  420. }
  421. };
  422. }).call(FoldMode.prototype);
  423. });
  424. 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";
  425. var oop = require("../lib/oop");
  426. var lang = require("../lib/lang");
  427. var TextMode = require("./text").Mode;
  428. var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
  429. var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;
  430. var XmlFoldMode = require("./folding/xml").FoldMode;
  431. var WorkerClient = require("../worker/worker_client").WorkerClient;
  432. var Mode = function () {
  433. this.HighlightRules = XmlHighlightRules;
  434. this.$behaviour = new XmlBehaviour();
  435. this.foldingRules = new XmlFoldMode();
  436. };
  437. oop.inherits(Mode, TextMode);
  438. (function () {
  439. this.voidElements = lang.arrayToMap([]);
  440. this.blockComment = { start: "<!--", end: "-->" };
  441. this.createWorker = function (session) {
  442. var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
  443. worker.attachToDocument(session.getDocument());
  444. worker.on("error", function (e) {
  445. session.setAnnotations(e.data);
  446. });
  447. worker.on("terminate", function () {
  448. session.clearAnnotations();
  449. });
  450. return worker;
  451. };
  452. this.$id = "ace/mode/xml";
  453. }).call(Mode.prototype);
  454. exports.Mode = Mode;
  455. }); (function() {
  456. ace.require(["ace/mode/xml"], function(m) {
  457. if (typeof module == "object" && typeof exports == "object" && module) {
  458. module.exports = m;
  459. }
  460. });
  461. })();