File modules/editor/codemirror/mode/velocity/velocity.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")); 7 else if (typeof define == "function" && define.amd) // AMD 8 define(["../../lib/codemirror"], mod); 9 else // Plain browser env 10 mod(CodeMirror); 11 })(function(CodeMirror) { 12 "use strict"; 13 14 CodeMirror.defineMode("velocity", function() { 15 function parseWords(str) { 16 var obj = {}, words = str.split(" "); 17 for (var i = 0; i < words.length; ++i) obj[words[i]] = true; 18 return obj; 19 } 20 21 var keywords = parseWords("#end #else #break #stop #[[ #]] " + 22 "#{end} #{else} #{break} #{stop}"); 23 var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " + 24 "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}"); 25 var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent"); 26 var isOperatorChar = /[+\-*&%=<>!?:\/|]/; 27 28 function chain(stream, state, f) { 29 state.tokenize = f; 30 return f(stream, state); 31 } 32 function tokenBase(stream, state) { 33 var beforeParams = state.beforeParams; 34 state.beforeParams = false; 35 var ch = stream.next(); 36 // start of unparsed string? 37 if ((ch == "'") && !state.inString && state.inParams) { 38 state.lastTokenWasBuiltin = false; 39 return chain(stream, state, tokenString(ch)); 40 } 41 // start of parsed string? 42 else if ((ch == '"')) { 43 state.lastTokenWasBuiltin = false; 44 if (state.inString) { 45 state.inString = false; 46 return "string"; 47 } 48 else if (state.inParams) 49 return chain(stream, state, tokenString(ch)); 50 } 51 // is it one of the special signs []{}().,;? Seperator? 52 else if (/[\[\]{}\(\),;\.]/.test(ch)) { 53 if (ch == "(" && beforeParams) 54 state.inParams = true; 55 else if (ch == ")") { 56 state.inParams = false; 57 state.lastTokenWasBuiltin = true; 58 } 59 return null; 60 } 61 // start of a number value? 62 else if (/\d/.test(ch)) { 63 state.lastTokenWasBuiltin = false; 64 stream.eatWhile(/[\w\.]/); 65 return "number"; 66 } 67 // multi line comment? 68 else if (ch == "#" && stream.eat("*")) { 69 state.lastTokenWasBuiltin = false; 70 return chain(stream, state, tokenComment); 71 } 72 // unparsed content? 73 else if (ch == "#" && stream.match(/ *\[ *\[/)) { 74 state.lastTokenWasBuiltin = false; 75 return chain(stream, state, tokenUnparsed); 76 } 77 // single line comment? 78 else if (ch == "#" && stream.eat("#")) { 79 state.lastTokenWasBuiltin = false; 80 stream.skipToEnd(); 81 return "comment"; 82 } 83 // variable? 84 else if (ch == "$") { 85 stream.eatWhile(/[\w\d\$_\.{}]/); 86 // is it one of the specials? 87 if (specials && specials.propertyIsEnumerable(stream.current())) { 88 return "keyword"; 89 } 90 else { 91 state.lastTokenWasBuiltin = true; 92 state.beforeParams = true; 93 return "builtin"; 94 } 95 } 96 // is it a operator? 97 else if (isOperatorChar.test(ch)) { 98 state.lastTokenWasBuiltin = false; 99 stream.eatWhile(isOperatorChar); 100 return "operator"; 101 } 102 else { 103 // get the whole word 104 stream.eatWhile(/[\w\$_{}@]/); 105 var word = stream.current(); 106 // is it one of the listed keywords? 107 if (keywords && keywords.propertyIsEnumerable(word)) 108 return "keyword"; 109 // is it one of the listed functions? 110 if (functions && functions.propertyIsEnumerable(word) || 111 (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") && 112 !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) { 113 state.beforeParams = true; 114 state.lastTokenWasBuiltin = false; 115 return "keyword"; 116 } 117 if (state.inString) { 118 state.lastTokenWasBuiltin = false; 119 return "string"; 120 } 121 if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin) 122 return "builtin"; 123 // default: just a "word" 124 state.lastTokenWasBuiltin = false; 125 return null; 126 } 127 } 128 129 function tokenString(quote) { 130 return function(stream, state) { 131 var escaped = false, next, end = false; 132 while ((next = stream.next()) != null) { 133 if ((next == quote) && !escaped) { 134 end = true; 135 break; 136 } 137 if (quote=='"' && stream.peek() == '$' && !escaped) { 138 state.inString = true; 139 end = true; 140 break; 141 } 142 escaped = !escaped && next == "\\"; 143 } 144 if (end) state.tokenize = tokenBase; 145 return "string"; 146 }; 147 } 148 149 function tokenComment(stream, state) { 150 var maybeEnd = false, ch; 151 while (ch = stream.next()) { 152 if (ch == "#" && maybeEnd) { 153 state.tokenize = tokenBase; 154 break; 155 } 156 maybeEnd = (ch == "*"); 157 } 158 return "comment"; 159 } 160 161 function tokenUnparsed(stream, state) { 162 var maybeEnd = 0, ch; 163 while (ch = stream.next()) { 164 if (ch == "#" && maybeEnd == 2) { 165 state.tokenize = tokenBase; 166 break; 167 } 168 if (ch == "]") 169 maybeEnd++; 170 else if (ch != " ") 171 maybeEnd = 0; 172 } 173 return "meta"; 174 } 175 // Interface 176 177 return { 178 startState: function() { 179 return { 180 tokenize: tokenBase, 181 beforeParams: false, 182 inParams: false, 183 inString: false, 184 lastTokenWasBuiltin: false 185 }; 186 }, 187 188 token: function(stream, state) { 189 if (stream.eatSpace()) return null; 190 return state.tokenize(stream, state); 191 }, 192 blockCommentStart: "#*", 193 blockCommentEnd: "*#", 194 lineComment: "##", 195 fold: "velocity" 196 }; 197 }); 198 199 CodeMirror.defineMIME("text/velocity", "velocity"); 200 201 });
Downloadmodules/editor/codemirror/mode/velocity/velocity.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.