910d215f0c13b5a22f8e786c0730fbe3.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  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"], 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. function is(token, type) {
  184. return token && token.type.lastIndexOf(type + ".xml") > -1;
  185. }
  186. var XmlBehaviour = function () {
  187. this.add("string_dquotes", "insertion", function (state, action, editor, session, text) {
  188. if (text == '"' || text == "'") {
  189. var quote = text;
  190. var selected = session.doc.getTextRange(editor.getSelectionRange());
  191. if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) {
  192. return {
  193. text: quote + selected + quote,
  194. selection: false
  195. };
  196. }
  197. var cursor = editor.getCursorPosition();
  198. var line = session.doc.getLine(cursor.row);
  199. var rightChar = line.substring(cursor.column, cursor.column + 1);
  200. var iterator = new TokenIterator(session, cursor.row, cursor.column);
  201. var token = iterator.getCurrentToken();
  202. if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) {
  203. return {
  204. text: "",
  205. selection: [1, 1]
  206. };
  207. }
  208. if (!token)
  209. token = iterator.stepBackward();
  210. if (!token)
  211. return;
  212. while (is(token, "tag-whitespace") || is(token, "whitespace")) {
  213. token = iterator.stepBackward();
  214. }
  215. var rightSpace = !rightChar || rightChar.match(/\s/);
  216. if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) {
  217. return {
  218. text: quote + quote,
  219. selection: [1, 1]
  220. };
  221. }
  222. }
  223. });
  224. this.add("string_dquotes", "deletion", function (state, action, editor, session, range) {
  225. var selected = session.doc.getTextRange(range);
  226. if (!range.isMultiLine() && (selected == '"' || selected == "'")) {
  227. var line = session.doc.getLine(range.start.row);
  228. var rightChar = line.substring(range.start.column + 1, range.start.column + 2);
  229. if (rightChar == selected) {
  230. range.end.column++;
  231. return range;
  232. }
  233. }
  234. });
  235. this.add("autoclosing", "insertion", function (state, action, editor, session, text) {
  236. if (text == '>') {
  237. var position = editor.getSelectionRange().start;
  238. var iterator = new TokenIterator(session, position.row, position.column);
  239. var token = iterator.getCurrentToken() || iterator.stepBackward();
  240. if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value")))
  241. return;
  242. if (is(token, "reference.attribute-value"))
  243. return;
  244. if (is(token, "attribute-value")) {
  245. var tokenEndColumn = iterator.getCurrentTokenColumn() + token.value.length;
  246. if (position.column < tokenEndColumn)
  247. return;
  248. if (position.column == tokenEndColumn) {
  249. var nextToken = iterator.stepForward();
  250. if (nextToken && is(nextToken, "attribute-value"))
  251. return;
  252. iterator.stepBackward();
  253. }
  254. }
  255. if (/^\s*>/.test(session.getLine(position.row).slice(position.column)))
  256. return;
  257. while (!is(token, "tag-name")) {
  258. token = iterator.stepBackward();
  259. if (token.value == "<") {
  260. token = iterator.stepForward();
  261. break;
  262. }
  263. }
  264. var tokenRow = iterator.getCurrentTokenRow();
  265. var tokenColumn = iterator.getCurrentTokenColumn();
  266. if (is(iterator.stepBackward(), "end-tag-open"))
  267. return;
  268. var element = token.value;
  269. if (tokenRow == position.row)
  270. element = element.substring(0, position.column - tokenColumn);
  271. if (this.voidElements && this.voidElements.hasOwnProperty(element.toLowerCase()))
  272. return;
  273. return {
  274. text: ">" + "</" + element + ">",
  275. selection: [1, 1]
  276. };
  277. }
  278. });
  279. this.add("autoindent", "insertion", function (state, action, editor, session, text) {
  280. if (text == "\n") {
  281. var cursor = editor.getCursorPosition();
  282. var line = session.getLine(cursor.row);
  283. var iterator = new TokenIterator(session, cursor.row, cursor.column);
  284. var token = iterator.getCurrentToken();
  285. if (is(token, "") && token.type.indexOf("tag-close") !== -1) {
  286. if (token.value == "/>")
  287. return;
  288. while (token && token.type.indexOf("tag-name") === -1) {
  289. token = iterator.stepBackward();
  290. }
  291. if (!token) {
  292. return;
  293. }
  294. var tag = token.value;
  295. var row = iterator.getCurrentTokenRow();
  296. token = iterator.stepBackward();
  297. if (!token || token.type.indexOf("end-tag") !== -1) {
  298. return;
  299. }
  300. if (this.voidElements && !this.voidElements[tag] || !this.voidElements) {
  301. var nextToken = session.getTokenAt(cursor.row, cursor.column + 1);
  302. var line = session.getLine(row);
  303. var nextIndent = this.$getIndent(line);
  304. var indent = nextIndent + session.getTabString();
  305. if (nextToken && nextToken.value === "</") {
  306. return {
  307. text: "\n" + indent + "\n" + nextIndent,
  308. selection: [1, indent.length, 1, indent.length]
  309. };
  310. }
  311. else {
  312. return {
  313. text: "\n" + indent
  314. };
  315. }
  316. }
  317. }
  318. }
  319. });
  320. };
  321. oop.inherits(XmlBehaviour, Behaviour);
  322. exports.XmlBehaviour = XmlBehaviour;
  323. });
  324. 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";
  325. var oop = require("../../lib/oop");
  326. var Range = require("../../range").Range;
  327. var BaseFoldMode = require("./fold_mode").FoldMode;
  328. var FoldMode = exports.FoldMode = function (voidElements, optionalEndTags) {
  329. BaseFoldMode.call(this);
  330. this.voidElements = voidElements || {};
  331. this.optionalEndTags = oop.mixin({}, this.voidElements);
  332. if (optionalEndTags)
  333. oop.mixin(this.optionalEndTags, optionalEndTags);
  334. };
  335. oop.inherits(FoldMode, BaseFoldMode);
  336. var Tag = function () {
  337. this.tagName = "";
  338. this.closing = false;
  339. this.selfClosing = false;
  340. this.start = { row: 0, column: 0 };
  341. this.end = { row: 0, column: 0 };
  342. };
  343. function is(token, type) {
  344. return token && token.type && token.type.lastIndexOf(type + ".xml") > -1;
  345. }
  346. (function () {
  347. this.getFoldWidget = function (session, foldStyle, row) {
  348. var tag = this._getFirstTagInLine(session, row);
  349. if (!tag)
  350. return this.getCommentFoldWidget(session, row);
  351. if (tag.closing || (!tag.tagName && tag.selfClosing))
  352. return foldStyle === "markbeginend" ? "end" : "";
  353. if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase()))
  354. return "";
  355. if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column))
  356. return "";
  357. return "start";
  358. };
  359. this.getCommentFoldWidget = function (session, row) {
  360. if (/comment/.test(session.getState(row)) && /<!-/.test(session.getLine(row)))
  361. return "start";
  362. return "";
  363. };
  364. this._getFirstTagInLine = function (session, row) {
  365. var tokens = session.getTokens(row);
  366. var tag = new Tag();
  367. for (var i = 0; i < tokens.length; i++) {
  368. var token = tokens[i];
  369. if (is(token, "tag-open")) {
  370. tag.end.column = tag.start.column + token.value.length;
  371. tag.closing = is(token, "end-tag-open");
  372. token = tokens[++i];
  373. if (!token)
  374. return null;
  375. tag.tagName = token.value;
  376. if (token.value === "") { //skip empty tag name token for fragment
  377. token = tokens[++i];
  378. if (!token)
  379. return null;
  380. tag.tagName = token.value;
  381. }
  382. tag.end.column += token.value.length;
  383. for (i++; i < tokens.length; i++) {
  384. token = tokens[i];
  385. tag.end.column += token.value.length;
  386. if (is(token, "tag-close")) {
  387. tag.selfClosing = token.value == '/>';
  388. break;
  389. }
  390. }
  391. return tag;
  392. }
  393. else if (is(token, "tag-close")) {
  394. tag.selfClosing = token.value == '/>';
  395. return tag;
  396. }
  397. tag.start.column += token.value.length;
  398. }
  399. return null;
  400. };
  401. this._findEndTagInLine = function (session, row, tagName, startColumn) {
  402. var tokens = session.getTokens(row);
  403. var column = 0;
  404. for (var i = 0; i < tokens.length; i++) {
  405. var token = tokens[i];
  406. column += token.value.length;
  407. if (column < startColumn - 1)
  408. continue;
  409. if (is(token, "end-tag-open")) {
  410. token = tokens[i + 1];
  411. if (is(token, "tag-name") && token.value === "") {
  412. token = tokens[i + 2];
  413. }
  414. if (token && token.value == tagName)
  415. return true;
  416. }
  417. }
  418. return false;
  419. };
  420. this.getFoldWidgetRange = function (session, foldStyle, row) {
  421. var firstTag = this._getFirstTagInLine(session, row);
  422. if (!firstTag) {
  423. return this.getCommentFoldWidget(session, row) && session.getCommentFoldRange(row, session.getLine(row).length);
  424. }
  425. var tags = session.getMatchingTags({ row: row, column: 0 });
  426. if (tags) {
  427. return new Range(tags.openTag.end.row, tags.openTag.end.column, tags.closeTag.start.row, tags.closeTag.start.column);
  428. }
  429. };
  430. }).call(FoldMode.prototype);
  431. });
  432. 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";
  433. var oop = require("../lib/oop");
  434. var lang = require("../lib/lang");
  435. var TextMode = require("./text").Mode;
  436. var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules;
  437. var XmlBehaviour = require("./behaviour/xml").XmlBehaviour;
  438. var XmlFoldMode = require("./folding/xml").FoldMode;
  439. var WorkerClient = require("../worker/worker_client").WorkerClient;
  440. var Mode = function () {
  441. this.HighlightRules = XmlHighlightRules;
  442. this.$behaviour = new XmlBehaviour();
  443. this.foldingRules = new XmlFoldMode();
  444. };
  445. oop.inherits(Mode, TextMode);
  446. (function () {
  447. this.voidElements = lang.arrayToMap([]);
  448. this.blockComment = { start: "<!--", end: "-->" };
  449. this.createWorker = function (session) {
  450. var worker = new WorkerClient(["ace"], "ace/mode/xml_worker", "Worker");
  451. worker.attachToDocument(session.getDocument());
  452. worker.on("error", function (e) {
  453. session.setAnnotations(e.data);
  454. });
  455. worker.on("terminate", function () {
  456. session.clearAnnotations();
  457. });
  458. return worker;
  459. };
  460. this.$id = "ace/mode/xml";
  461. }).call(Mode.prototype);
  462. exports.Mode = Mode;
  463. }); (function() {
  464. ace.require(["ace/mode/xml"], function(m) {
  465. if (typeof module == "object" && typeof exports == "object" && module) {
  466. module.exports = m;
  467. }
  468. });
  469. })();