Path: blob/master/web-gui/buildyourownbotnet/assets/js/codemirror/mode/haml/haml.js
1293 views
(function() {1"use strict";23// full haml mode. This handled embeded ruby and html fragments too4CodeMirror.defineMode("haml", function(config) {5var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});6var rubyMode = CodeMirror.getMode(config, "ruby");78function rubyInQuote(endQuote) {9return function(stream, state) {10var ch = stream.peek();11if (ch == endQuote && state.rubyState.tokenize.length == 1) {12// step out of ruby context as it seems to complete processing all the braces13stream.next();14state.tokenize = html;15return "closeAttributeTag";16} else {17return ruby(stream, state);18}19};20}2122function ruby(stream, state) {23if (stream.match("-#")) {24stream.skipToEnd();25return "comment";26}27return rubyMode.token(stream, state.rubyState);28}2930function html(stream, state) {31var ch = stream.peek();3233// handle haml declarations. All declarations that cant be handled here34// will be passed to html mode35if (state.previousToken.style == "comment" ) {36if (state.indented > state.previousToken.indented) {37stream.skipToEnd();38return "commentLine";39}40}4142if (state.startOfLine) {43if (ch == "!" && stream.match("!!")) {44stream.skipToEnd();45return "tag";46} else if (stream.match(/^%[\w:#\.]+=/)) {47state.tokenize = ruby;48return "hamlTag";49} else if (stream.match(/^%[\w:]+/)) {50return "hamlTag";51} else if (ch == "/" ) {52stream.skipToEnd();53return "comment";54}55}5657if (state.startOfLine || state.previousToken.style == "hamlTag") {58if ( ch == "#" || ch == ".") {59stream.match(/[\w-#\.]*/);60return "hamlAttribute";61}62}6364// donot handle --> as valid ruby, make it HTML close comment instead65if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {66state.tokenize = ruby;67return null;68}6970if (state.previousToken.style == "hamlTag" ||71state.previousToken.style == "closeAttributeTag" ||72state.previousToken.style == "hamlAttribute") {73if (ch == "(") {74state.tokenize = rubyInQuote(")");75return null;76} else if (ch == "{") {77state.tokenize = rubyInQuote("}");78return null;79}80}8182return htmlMode.token(stream, state.htmlState);83}8485return {86// default to html mode87startState: function() {88var htmlState = htmlMode.startState();89var rubyState = rubyMode.startState();90return {91htmlState: htmlState,92rubyState: rubyState,93indented: 0,94previousToken: { style: null, indented: 0},95tokenize: html96};97},9899copyState: function(state) {100return {101htmlState : CodeMirror.copyState(htmlMode, state.htmlState),102rubyState: CodeMirror.copyState(rubyMode, state.rubyState),103indented: state.indented,104previousToken: state.previousToken,105tokenize: state.tokenize106};107},108109token: function(stream, state) {110if (stream.sol()) {111state.indented = stream.indentation();112state.startOfLine = true;113}114if (stream.eatSpace()) return null;115var style = state.tokenize(stream, state);116state.startOfLine = false;117// dont record comment line as we only want to measure comment line with118// the opening comment block119if (style && style != "commentLine") {120state.previousToken = { style: style, indented: state.indented };121}122// if current state is ruby and the previous token is not `,` reset the123// tokenize to html124if (stream.eol() && state.tokenize == ruby) {125stream.backUp(1);126var ch = stream.peek();127stream.next();128if (ch && ch != ",") {129state.tokenize = html;130}131}132// reprocess some of the specific style tag when finish setting previousToken133if (style == "hamlTag") {134style = "tag";135} else if (style == "commentLine") {136style = "comment";137} else if (style == "hamlAttribute") {138style = "attribute";139} else if (style == "closeAttributeTag") {140style = null;141}142return style;143}144};145}, "htmlmixed", "ruby");146147CodeMirror.defineMIME("text/x-haml", "haml");148})();149150151