mask_highlight_rules.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2014, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. define(function(require, exports, module) {
  31. "use strict";
  32. exports.MaskHighlightRules = MaskHighlightRules;
  33. var oop = require("../lib/oop");
  34. var lang = require("../lib/lang");
  35. var TextRules = require("./text_highlight_rules").TextHighlightRules;
  36. var JSRules = require("./javascript_highlight_rules").JavaScriptHighlightRules;
  37. var CssRules = require("./css_highlight_rules").CssHighlightRules;
  38. var MDRules = require("./markdown_highlight_rules").MarkdownHighlightRules;
  39. var HTMLRules = require("./html_highlight_rules").HtmlHighlightRules;
  40. var token_TAG = "keyword.support.constant.language",
  41. token_COMPO = "support.function.markup.bold",
  42. token_KEYWORD = "keyword",
  43. token_LANG = "constant.language",
  44. token_UTIL = "keyword.control.markup.italic",
  45. token_ATTR = "support.variable.class",
  46. token_PUNKT = "keyword.operator",
  47. token_ITALIC = "markup.italic",
  48. token_BOLD = "markup.bold",
  49. token_LPARE = "paren.lparen",
  50. token_RPARE = "paren.rparen";
  51. var const_FUNCTIONS,
  52. const_KEYWORDS,
  53. const_CONST,
  54. const_TAGS;
  55. (function(){
  56. const_FUNCTIONS = lang.arrayToMap(
  57. ("log").split("|")
  58. );
  59. const_CONST = lang.arrayToMap(
  60. (":dualbind|:bind|:import|slot|event|style|html|markdown|md").split("|")
  61. );
  62. const_KEYWORDS = lang.arrayToMap(
  63. ("debugger|define|var|if|each|for|of|else|switch|case|with|visible|+if|+each|+for|+switch|+with|+visible|include|import").split("|")
  64. );
  65. const_TAGS = lang.arrayToMap(
  66. ("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|" +
  67. "big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|" +
  68. "command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|" +
  69. "figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" +
  70. "header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|" +
  71. "link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|" +
  72. "option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|" +
  73. "small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|" +
  74. "textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp").split("|")
  75. );
  76. }());
  77. function MaskHighlightRules () {
  78. this.$rules = {
  79. "start" : [
  80. Token("comment", "\\/\\/.*$"),
  81. Token("comment", "\\/\\*", [
  82. Token("comment", ".*?\\*\\/", "start"),
  83. Token("comment", ".+")
  84. ]),
  85. Blocks.string("'''"),
  86. Blocks.string('"""'),
  87. Blocks.string('"'),
  88. Blocks.string("'"),
  89. Blocks.syntax(/(markdown|md)\b/, "md-multiline", "multiline"),
  90. Blocks.syntax(/html\b/, "html-multiline", "multiline"),
  91. Blocks.syntax(/(slot|event)\b/, "js-block", "block"),
  92. Blocks.syntax(/style\b/, "css-block", "block"),
  93. Blocks.syntax(/var\b/, "js-statement", "attr"),
  94. Blocks.tag(),
  95. Token(token_LPARE, "[[({>]"),
  96. Token(token_RPARE, "[\\])};]", "start"),
  97. {
  98. caseInsensitive: true
  99. }
  100. ]
  101. };
  102. var rules = this;
  103. addJavaScript("interpolation", /\]/, token_RPARE + "." + token_ITALIC);
  104. addJavaScript("statement", /\)|}|;/);
  105. addJavaScript("block", /\}/);
  106. addCss();
  107. addMarkdown();
  108. addHtml();
  109. function addJavaScript(name, escape, closeType) {
  110. var prfx = "js-" + name + "-",
  111. rootTokens = name === "block" ? ["start"] : ["start", "no_regex"];
  112. add(
  113. JSRules
  114. , prfx
  115. , escape
  116. , rootTokens
  117. , closeType
  118. );
  119. }
  120. function addCss() {
  121. add(CssRules, "css-block-", /\}/);
  122. }
  123. function addMarkdown() {
  124. add(MDRules, "md-multiline-", /("""|''')/, []);
  125. }
  126. function addHtml() {
  127. add(HTMLRules, "html-multiline-", /("""|''')/);
  128. }
  129. function add(Rules, strPrfx, rgxEnd, rootTokens, closeType) {
  130. var next = "pop";
  131. var tokens = rootTokens || [ "start" ];
  132. if (tokens.length === 0) {
  133. tokens = null;
  134. }
  135. if (/block|multiline/.test(strPrfx)) {
  136. next = strPrfx + "end";
  137. rules.$rules[next] = [
  138. Token("empty", "", "start")
  139. ];
  140. }
  141. rules.embedRules(
  142. Rules
  143. , strPrfx
  144. , [ Token(closeType || token_RPARE, rgxEnd, next) ]
  145. , tokens
  146. , tokens == null ? true : false
  147. );
  148. }
  149. this.normalizeRules();
  150. }
  151. oop.inherits(MaskHighlightRules, TextRules);
  152. var Blocks = {
  153. string: function(str, next){
  154. var token = Token(
  155. "string.start"
  156. , str
  157. , [
  158. Token(token_LPARE + "." + token_ITALIC, /~\[/, Blocks.interpolation()),
  159. Token("string.end", str, "pop"),
  160. {
  161. defaultToken: "string"
  162. }
  163. ]
  164. , next
  165. );
  166. if (str.length === 1){
  167. var escaped = Token("string.escape", "\\\\" + str);
  168. token.push.unshift(escaped);
  169. }
  170. return token;
  171. },
  172. interpolation: function(){
  173. return [
  174. Token(token_UTIL, /\s*\w*\s*:/),
  175. "js-interpolation-start"
  176. ];
  177. },
  178. tagHead: function (rgx) {
  179. return Token(token_ATTR, rgx, [
  180. Token(token_ATTR, /[\w\-_]+/),
  181. Token(token_LPARE + "." + token_ITALIC, /~\[/, Blocks.interpolation()),
  182. Blocks.goUp()
  183. ]);
  184. },
  185. tag: function () {
  186. return {
  187. token: 'tag',
  188. onMatch : function(value) {
  189. if (void 0 !== const_KEYWORDS[value])
  190. return token_KEYWORD;
  191. if (void 0 !== const_CONST[value])
  192. return token_LANG;
  193. if (void 0 !== const_FUNCTIONS[value])
  194. return "support.function";
  195. if (void 0 !== const_TAGS[value.toLowerCase()])
  196. return token_TAG;
  197. return token_COMPO;
  198. },
  199. regex : /([@\w\-_:+]+)|((^|\s)(?=\s*(\.|#)))/,
  200. push: [
  201. Blocks.tagHead(/\./) ,
  202. Blocks.tagHead(/\#/) ,
  203. Blocks.expression(),
  204. Blocks.attribute(),
  205. Token(token_LPARE, /[;>{]/, "pop")
  206. ]
  207. };
  208. },
  209. syntax: function(rgx, next, type){
  210. return {
  211. token: token_LANG,
  212. regex : rgx,
  213. push: ({
  214. "attr": [
  215. next + "-start",
  216. Token(token_PUNKT, /;/, "start")
  217. ],
  218. "multiline": [
  219. Blocks.tagHead(/\./) ,
  220. Blocks.tagHead(/\#/) ,
  221. Blocks.attribute(),
  222. Blocks.expression(),
  223. Token(token_LPARE, /[>\{]/),
  224. Token(token_PUNKT, /;/, "start"),
  225. Token(token_LPARE, /'''|"""/, [ next + "-start" ])
  226. ],
  227. "block": [
  228. Blocks.tagHead(/\./) ,
  229. Blocks.tagHead(/\#/) ,
  230. Blocks.attribute(),
  231. Blocks.expression(),
  232. Token(token_LPARE, /\{/, [ next + "-start" ])
  233. ]
  234. })[type]
  235. };
  236. },
  237. attribute: function(){
  238. return Token(function(value){
  239. return /^x\-/.test(value)
  240. ? token_ATTR + "." + token_BOLD
  241. : token_ATTR;
  242. }, /[\w_-]+/, [
  243. Token(token_PUNKT, /\s*=\s*/, [
  244. Blocks.string('"'),
  245. Blocks.string("'"),
  246. Blocks.word(),
  247. Blocks.goUp()
  248. ]),
  249. Blocks.goUp()
  250. ]);
  251. },
  252. expression: function(){
  253. return Token(token_LPARE, /\(/, [ "js-statement-start" ]);
  254. },
  255. word: function(){
  256. return Token("string", /[\w-_]+/);
  257. },
  258. goUp: function(){
  259. return Token("text", "", "pop");
  260. },
  261. goStart: function(){
  262. return Token("text", "", "start");
  263. }
  264. };
  265. function Token(token, rgx, mix) {
  266. var push, next, onMatch;
  267. if (arguments.length === 4) {
  268. push = mix;
  269. next = arguments[3];
  270. }
  271. else if (typeof mix === "string") {
  272. next = mix;
  273. }
  274. else {
  275. push = mix;
  276. }
  277. if (typeof token === "function") {
  278. onMatch = token;
  279. token = "empty";
  280. }
  281. return {
  282. token: token,
  283. regex: rgx,
  284. push: push,
  285. next: next,
  286. onMatch: onMatch
  287. };
  288. }
  289. });