From 1587b96b3c03394386b6c08e7e2165af7639a8ce Mon Sep 17 00:00:00 2001 From: Alex Kit Date: Thu, 13 Nov 2014 17:54:56 +0100 Subject: [PATCH] Add Mask Highlighter --- demo/kitchen-sink/docs/mask.mask | 52 +++++ lib/ace/ext/modelist.js | 1 + lib/ace/mode/_test/tokens_mask.json | 302 ++++++++++++++++++++++++++ lib/ace/mode/mask.js | 84 ++++++++ lib/ace/mode/mask_highlight_rules.js | 309 +++++++++++++++++++++++++++ 5 files changed, 748 insertions(+) create mode 100644 demo/kitchen-sink/docs/mask.mask create mode 100644 lib/ace/mode/_test/tokens_mask.json create mode 100644 lib/ace/mode/mask.js create mode 100644 lib/ace/mode/mask_highlight_rules.js diff --git a/demo/kitchen-sink/docs/mask.mask b/demo/kitchen-sink/docs/mask.mask new file mode 100644 index 00000000..85a9e6c2 --- /dev/null +++ b/demo/kitchen-sink/docs/mask.mask @@ -0,0 +1,52 @@ +/* Mask Syntax Demo */ + +div > ' Test ~[name]'; + +define :userProfile { + header { + h4 > @title; + button.close; + } +} + +:userProfile { + @title > ' Hello ~[: username.toUpperCase()]' +} + +style { + html, body { + background: url('name.png') 0 0 no-repeat; + } +} + +button { + event click (e) { + this.textContent = `name ${e.clientX} !`; + } +} + +md > """ + +- div +- span + +Hello + +[one](http://google.com) + +"""; + + +header .foo > 'Heading' + +button .baz x-signal='click: test' disabled > " + Hello, + world + \"Buddy\" +" + +var a = { + name: `name ${window.innerWidth}` +}; + +span .foo > "~[bind: a.name]" \ No newline at end of file diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 9e012f51..3245d8a7 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -109,6 +109,7 @@ var supportedModes = { Lucene: ["lucene"], Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"], Markdown: ["md|markdown"], + Mask: ["mask"], MATLAB: ["matlab"], MEL: ["mel"], MUSHCode: ["mc|mush"], diff --git a/lib/ace/mode/_test/tokens_mask.json b/lib/ace/mode/_test/tokens_mask.json new file mode 100644 index 00000000..5f2b9762 --- /dev/null +++ b/lib/ace/mode/_test/tokens_mask.json @@ -0,0 +1,302 @@ +[[ + "start", + ["comment","/* Mask Syntax Demo */"] +],[ + "start" +],[ + "start", + ["keyword.support.constant.language","div"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["string.start","'"], + ["string"," Test "], + ["paren.lparen.markup.italic","~["], + ["identifier","name"], + ["paren.rparen.markup.italic","]"], + ["string.end","'"], + ["paren.rparen",";"] +],[ + "start" +],[ + "start", + ["keyword","define"], + ["text"," :"], + ["support.variable.class","userProfile"], + ["text"," "], + ["paren.lparen","{"] +],[ + "start", + ["text","\t"], + ["keyword.support.constant.language","header"], + ["text"," "], + ["paren.lparen","{"] +],[ + "start", + ["text","\t\t"], + ["keyword.support.constant.language","h4"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["support.function.markup.bold","@title"], + ["paren.lparen",";"] +],[ + "start", + ["text","\t\t"], + ["keyword.support.constant.language","button"], + ["support.variable.class",".close"], + ["paren.lparen",";"] +],[ + "start", + ["text","\t"], + ["paren.rparen","}"] +],[ + "start", + ["paren.rparen","}"] +],[ + "start" +],[ + "start", + ["support.function.markup.bold",":userProfile"], + ["text"," "], + ["paren.lparen","{"] +],[ + "start", + ["text","\t"], + ["support.function.markup.bold","@title"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["string.start","'"], + ["string"," Hello "], + ["paren.lparen.markup.italic","~["], + ["keyword.control.markup.italic",":"], + ["text"," "], + ["identifier","username"], + ["punctuation.operator","."], + ["support.function","toUpperCase"], + ["paren.lparen","("], + ["paren.rparen",")"], + ["paren.rparen.markup.italic","]"], + ["string.end","'"] +],[ + "start", + ["paren.rparen","}"] +],[ + "start" +],[ + ["paren.lparen52","constant.language40"], + ["constant.language","style"], + ["text"," "], + ["paren.lparen","{"] +],[ + ["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"], + ["text"," "], + ["constant","html"], + ["text",", "], + ["constant","body"], + ["text"," "], + ["paren.lparen","{"] +],[ + ["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"], + ["text"," "], + ["support.type","background"], + ["text",": "], + ["support.function","url("], + ["string","'name.png'"], + ["support.function",")"], + ["text"," "], + ["constant.numeric","0"], + ["text"," "], + ["constant.numeric","0"], + ["text"," "], + ["support.constant","no-repeat"], + ["text",";"] +],[ + ["paren.lparen52","constant.language40"], + ["text"," "], + ["paren.rparen","}"] +],[ + ["#tmp","css-block-end","paren.lparen52","constant.language40"], + ["paren.rparen","}"] +],[ + ["#tmp","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","start","paren.lparen52","constant.language40"], + ["keyword.support.constant.language","button"], + ["text"," "], + ["paren.lparen","{"] +],[ + ["paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["text","\t"], + ["constant.language","event"], + ["text"," "], + ["support.variable.class","click"], + ["text"," "], + ["paren.lparen","("], + ["identifier","e"], + ["paren.rparen",")"], + ["text"," "], + ["paren.lparen","{"] +],[ + ["#tmp","js-block-start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["text","\t "], + ["variable.language","this"], + ["punctuation.operator","."], + ["identifier","textContent"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["string.quasi.start","`"], + ["string.quasi","name "], + ["paren.quasi.start","${"], + ["identifier","e"], + ["punctuation.operator","."], + ["identifier","clientX"], + ["paren.quasi.end","}"], + ["string.quasi"," !"], + ["string.quasi.end","`"], + ["punctuation.operator",";"] +],[ + ["#tmp","js-block-end","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["text","\t"], + ["paren.rparen","}"] +],[ + ["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["paren.rparen","}"] +],[ + ["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["constant.language","md"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["paren.lparen","\"\"\""] +],[ + ["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["markup.list","- "], + ["list","div"] +],[ + ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["markup.list","- "], + ["list","span"] +],[ + ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["list"," "] +],[ + ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["list","Hello"] +],[ + ["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["text","["], + ["string","one"], + ["text","]("], + ["markup.underline","http://google.com"], + ["text",")"] +],[ + ["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["paren.rparen","\"\"\";"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["keyword.support.constant.language","header"], + ["text"," "], + ["support.variable.class",".foo"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["string.start","'"], + ["string","Heading"], + ["string.end","'"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["keyword.support.constant.language","button"], + ["text"," "], + ["support.variable.class",".baz"], + ["text"," "], + ["support.variable.class.markup.bold","x-signal"], + ["keyword.operator","="], + ["string.start","'"], + ["string","click: test"], + ["string.end","'"], + ["text"," "], + ["support.variable.class","disabled"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["string.start","\""] +],[ + ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["string","\tHello,"] +],[ + ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["string","\tworld "] +],[ + ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["string","\t"], + ["string.escape","\\\""], + ["string","Buddy"], + ["string.escape","\\\""] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["string.end","\""] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","js-statement-start","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["constant.language","var"], + ["text"," "], + ["identifier","a"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["paren","{"] +],[ + ["#tmp","js-statement-no_regex","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["text"," "], + ["identifier","name"], + ["punctuation.operator",":"], + ["text"," "], + ["string.quasi.start","`"], + ["string.quasi","name "], + ["paren.quasi.start","${"], + ["variable.language","window"], + ["punctuation.operator","."], + ["support.constant","innerWidth"], + ["paren.rparen","}"], + ["string.quasi.end","`"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["paren.rparen","};"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] +],[ + ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], + ["keyword.support.constant.language","span"], + ["text"," "], + ["support.variable.class",".foo"], + ["text"," "], + ["paren.lparen",">"], + ["text"," "], + ["string.start","\""], + ["paren.lparen.markup.italic","~["], + ["keyword.control.markup.italic","bind:"], + ["text"," "], + ["identifier","a"], + ["punctuation.operator","."], + ["identifier","name"], + ["paren.rparen.markup.italic","]"], + ["string.end","\""] +]] \ No newline at end of file diff --git a/lib/ace/mode/mask.js b/lib/ace/mode/mask.js new file mode 100644 index 00000000..ee94c82f --- /dev/null +++ b/lib/ace/mode/mask.js @@ -0,0 +1,84 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2014, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var MaskHighlightRules = require("./mask_highlight_rules").MaskHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var CssBehaviour = require("./behaviour/css").CssBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = MaskHighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CssBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + // ignore braces in comments + var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + var match = line.match(/^.*\{\s*$/); + if (match) { + indent += tab; + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.$id = "ace/mode/mask"; +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); diff --git a/lib/ace/mode/mask_highlight_rules.js b/lib/ace/mode/mask_highlight_rules.js new file mode 100644 index 00000000..8142ebe0 --- /dev/null +++ b/lib/ace/mode/mask_highlight_rules.js @@ -0,0 +1,309 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2014, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { +"use strict"; + +exports.MaskHighlightRules = MaskHighlightRules; + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextRules = require("./text_highlight_rules").TextHighlightRules; +var JSRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var CssRules = require("./css_highlight_rules").CssHighlightRules; +var MDRules = require("./markdown_highlight_rules").MarkdownHighlightRules; +var HTMLRules = require("./html_highlight_rules").HtmlHighlightRules; + +var token_TAG = "keyword.support.constant.language", + token_COMPO = "support.function.markup.bold", + token_KEYWORD = "keyword", + token_LANG = "constant.language", + token_UTIL = "keyword.control.markup.italic", + token_ATTR = "support.variable.class", + token_PUNKT = "keyword.operator", + token_ITALIC = "markup.italic", + token_BOLD = "markup.bold", + token_LPARE = "paren.lparen", + token_RPARE = "paren.rparen"; + +var const_FUNCTIONS, + const_KEYWORDS, + const_CONST, + const_TAGS; +(function(){ + const_FUNCTIONS = lang.arrayToMap( + ("log").split("|") + ); + const_CONST = lang.arrayToMap( + (":dualbind|:bind|:import|slot|event|style|html|markdown|md").split("|") + ); + const_KEYWORDS = lang.arrayToMap( + ("debugger|define|var|if|each|for|of|else|switch|case|with|visible|+if|+each|+for|+switch|+with|+visible|include|import").split("|") + ); + const_TAGS = lang.arrayToMap( + ("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|" + + "big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|" + + "command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|" + + "figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|" + + "header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|" + + "link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|" + + "option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|" + + "small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|" + + "textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp").split("|") + ); +}()); + +function MaskHighlightRules () { + + this.$rules = { + "start" : [ + Token("comment", "\\/\\/.*$"), + Token("comment", "\\/\\*", [ + Token("comment", ".*?\\*\\/", "start"), + Token("comment", ".+") + ]), + + Blocks.string("'''"), + Blocks.string('"""'), + Blocks.string('"'), + Blocks.string("'"), + + Blocks.syntax(/(markdown|md)\b/, "md-multiline", "multiline"), + Blocks.syntax(/html\b/, "html-multiline", "multiline"), + Blocks.syntax(/(slot|event)\b/, "js-block", "block"), + Blocks.syntax(/style\b/, "css-block", "block"), + Blocks.syntax(/var\b/, "js-statement", "attr"), + + Blocks.tag(), + + Token(token_LPARE, "[[({>]"), + Token(token_RPARE, "[\\])};]", "start"), + { + caseInsensitive: true + } + ] + }; + var rules = this; + + addJavaScript("interpolation", /\]/, token_RPARE + "." + token_ITALIC); + addJavaScript("statement", /\)|}|;/); + addJavaScript("block", /\}/); + addCss(); + addMarkdown(); + addHtml(); + + function addJavaScript(name, escape, closeType) { + var prfx = "js-" + name + "-", + rootTokens = name === "block" ? ["start"] : ["start", "no_regex"]; + add( + JSRules + , prfx + , escape + , rootTokens + , closeType + ); + } + function addCss() { + add(CssRules, "css-block-", /\}/); + } + function addMarkdown() { + add(MDRules, "md-multiline-", /("""|''')/, []); + } + function addHtml() { + add(HTMLRules, "html-multiline-", /("""|''')/); + } + function add(Rules, strPrfx, rgxEnd, rootTokens, closeType) { + var next = "pop"; + var tokens = rootTokens || [ "start" ]; + if (tokens.length === 0) { + tokens = null; + } + if (/block|multiline/.test(strPrfx)) { + next = strPrfx + "end"; + rules.$rules[next] = [ + Token("empty", "", "start") + ]; + } + rules.embedRules( + Rules + , strPrfx + , [ Token(closeType || token_RPARE, rgxEnd, next) ] + , tokens + , tokens == null ? true : false + ); + } + + this.normalizeRules(); +} +oop.inherits(MaskHighlightRules, TextRules); + +var Blocks = { + string: function(str, next){ + var token = Token( + "string.start" + , str + , [ + Token(token_LPARE + "." + token_ITALIC, /~\[/, Blocks.interpolation()), + Token("string.end", str, "pop"), + { + defaultToken: "string" + } + ] + , next + ); + if (str.length === 1){ + var escaped = Token("string.escape", "\\\\" + str); + token.push.unshift(escaped); + } + return token; + }, + interpolation: function(){ + return [ + Token(token_UTIL, /\s*\w*\s*:/), + "js-interpolation-start" + ]; + }, + tagHead: function (rgx) { + return Token(token_ATTR, rgx, [ + Token(token_ATTR, /[\w\-_]+/), + Token(token_LPARE + "." + token_ITALIC, /~\[/, Blocks.interpolation()), + Blocks.goUp() + ]); + }, + tag: function () { + return { + token: 'tag', + onMatch : function(value) { + if (void 0 !== const_KEYWORDS[value]) + return token_KEYWORD; + if (void 0 !== const_CONST[value]) + return token_LANG; + if (void 0 !== const_FUNCTIONS[value]) + return "support.function"; + if (void 0 !== const_TAGS[value.toLowerCase()]) + return token_TAG; + + return token_COMPO; + }, + regex : /([@\w\-_:+]+)|((^|\s)(?=\s*(\.|#)))/, + push: [ + Blocks.tagHead(/\./) , + Blocks.tagHead(/\#/) , + Blocks.expression(), + Blocks.attribute(), + + Token(token_LPARE, /[;>{]/, "pop") + ] + }; + }, + syntax: function(rgx, next, type){ + return { + token: token_LANG, + regex : rgx, + push: ({ + "attr": [ + next + "-start", + Token(token_PUNKT, /;/, "start") + ], + "multiline": [ + Blocks.tagHead(/\./) , + Blocks.tagHead(/\#/) , + Blocks.attribute(), + Blocks.expression(), + Token(token_LPARE, /[>\{]/), + Token(token_PUNKT, /;/, "start"), + Token(token_LPARE, /'''|"""/, [ next + "-start" ]) + ], + "block": [ + Blocks.tagHead(/\./) , + Blocks.tagHead(/\#/) , + Blocks.attribute(), + Blocks.expression(), + Token(token_LPARE, /\{/, [ next + "-start" ]) + ] + })[type] + }; + }, + attribute: function(){ + return Token(function(value){ + return /^x\-/.test(value) + ? token_ATTR + "." + token_BOLD + : token_ATTR; + }, /[\w_-]+/, [ + Token(token_PUNKT, /\s*=\s*/, [ + Blocks.string('"'), + Blocks.string("'"), + Blocks.word(), + Blocks.goUp() + ]), + Blocks.goUp() + ]); + }, + expression: function(){ + return Token(token_LPARE, /\(/, [ "js-statement-start" ]); + }, + word: function(){ + return Token("string", /[\w-_]+/); + }, + goUp: function(){ + return Token("text", "", "pop"); + }, + goStart: function(){ + return Token("text", "", "start"); + } +}; + + +function Token(token, rgx, mix) { + var push, next, onMatch; + if (arguments.length === 4) { + push = mix; + next = arguments[3]; + } + else if (typeof mix === "string") { + next = mix; + } + else { + push = mix; + } + if (typeof token === "function") { + onMatch = token; + token = "empty"; + } + return { + token: token, + regex: rgx, + push: push, + next: next, + onMatch: onMatch + }; +} + +});