File modules/editor/codemirror/mode/haml/haml.js
Last commit: Sun Dec 17 01:14:09 2017 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://codemirror.net/LICENSE 3 4 (function(mod) { 5 if (typeof exports == "object" && typeof module == "object") // CommonJS 6 mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); 7 else if (typeof define == "function" && define.amd) // AMD 8 define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); 9 else // Plain browser env 10 mod(CodeMirror); 11 })(function(CodeMirror) { 12 "use strict"; 13 14 // full haml mode. This handled embedded ruby and html fragments too 15 CodeMirror.defineMode("haml", function(config) { 16 var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); 17 var rubyMode = CodeMirror.getMode(config, "ruby"); 18 19 function rubyInQuote(endQuote) { 20 return function(stream, state) { 21 var ch = stream.peek(); 22 if (ch == endQuote && state.rubyState.tokenize.length == 1) { 23 // step out of ruby context as it seems to complete processing all the braces 24 stream.next(); 25 state.tokenize = html; 26 return "closeAttributeTag"; 27 } else { 28 return ruby(stream, state); 29 } 30 }; 31 } 32 33 function ruby(stream, state) { 34 if (stream.match("-#")) { 35 stream.skipToEnd(); 36 return "comment"; 37 } 38 return rubyMode.token(stream, state.rubyState); 39 } 40 41 function html(stream, state) { 42 var ch = stream.peek(); 43 44 // handle haml declarations. All declarations that cant be handled here 45 // will be passed to html mode 46 if (state.previousToken.style == "comment" ) { 47 if (state.indented > state.previousToken.indented) { 48 stream.skipToEnd(); 49 return "commentLine"; 50 } 51 } 52 53 if (state.startOfLine) { 54 if (ch == "!" && stream.match("!!")) { 55 stream.skipToEnd(); 56 return "tag"; 57 } else if (stream.match(/^%[\w:#\.]+=/)) { 58 state.tokenize = ruby; 59 return "hamlTag"; 60 } else if (stream.match(/^%[\w:]+/)) { 61 return "hamlTag"; 62 } else if (ch == "/" ) { 63 stream.skipToEnd(); 64 return "comment"; 65 } 66 } 67 68 if (state.startOfLine || state.previousToken.style == "hamlTag") { 69 if ( ch == "#" || ch == ".") { 70 stream.match(/[\w-#\.]*/); 71 return "hamlAttribute"; 72 } 73 } 74 75 // donot handle --> as valid ruby, make it HTML close comment instead 76 if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) { 77 state.tokenize = ruby; 78 return state.tokenize(stream, state); 79 } 80 81 if (state.previousToken.style == "hamlTag" || 82 state.previousToken.style == "closeAttributeTag" || 83 state.previousToken.style == "hamlAttribute") { 84 if (ch == "(") { 85 state.tokenize = rubyInQuote(")"); 86 return state.tokenize(stream, state); 87 } else if (ch == "{") { 88 if (!stream.match(/^\{%.*/)) { 89 state.tokenize = rubyInQuote("}"); 90 return state.tokenize(stream, state); 91 } 92 } 93 } 94 95 return htmlMode.token(stream, state.htmlState); 96 } 97 98 return { 99 // default to html mode 100 startState: function() { 101 var htmlState = CodeMirror.startState(htmlMode); 102 var rubyState = CodeMirror.startState(rubyMode); 103 return { 104 htmlState: htmlState, 105 rubyState: rubyState, 106 indented: 0, 107 previousToken: { style: null, indented: 0}, 108 tokenize: html 109 }; 110 }, 111 112 copyState: function(state) { 113 return { 114 htmlState : CodeMirror.copyState(htmlMode, state.htmlState), 115 rubyState: CodeMirror.copyState(rubyMode, state.rubyState), 116 indented: state.indented, 117 previousToken: state.previousToken, 118 tokenize: state.tokenize 119 }; 120 }, 121 122 token: function(stream, state) { 123 if (stream.sol()) { 124 state.indented = stream.indentation(); 125 state.startOfLine = true; 126 } 127 if (stream.eatSpace()) return null; 128 var style = state.tokenize(stream, state); 129 state.startOfLine = false; 130 // dont record comment line as we only want to measure comment line with 131 // the opening comment block 132 if (style && style != "commentLine") { 133 state.previousToken = { style: style, indented: state.indented }; 134 } 135 // if current state is ruby and the previous token is not `,` reset the 136 // tokenize to html 137 if (stream.eol() && state.tokenize == ruby) { 138 stream.backUp(1); 139 var ch = stream.peek(); 140 stream.next(); 141 if (ch && ch != ",") { 142 state.tokenize = html; 143 } 144 } 145 // reprocess some of the specific style tag when finish setting previousToken 146 if (style == "hamlTag") { 147 style = "tag"; 148 } else if (style == "commentLine") { 149 style = "comment"; 150 } else if (style == "hamlAttribute") { 151 style = "attribute"; 152 } else if (style == "closeAttributeTag") { 153 style = null; 154 } 155 return style; 156 } 157 }; 158 }, "htmlmixed", "ruby"); 159 160 CodeMirror.defineMIME("text/x-haml", "haml"); 161 });
Downloadmodules/editor/codemirror/mode/haml/haml.js
History Sun, 17 Dec 2017 01:14:09 +0100 Jan Dankert Integration eines weiteren Code-Editors: Codemirror. Demnächst müssen wir hier mal aufräumen und andere Editoren rauswerfen.