File modules/editor/codemirror/mode/smarty/smarty.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 /** 5 * Smarty 2 and 3 mode. 6 */ 7 8 (function(mod) { 9 if (typeof exports == "object" && typeof module == "object") // CommonJS 10 mod(require("../../lib/codemirror")); 11 else if (typeof define == "function" && define.amd) // AMD 12 define(["../../lib/codemirror"], mod); 13 else // Plain browser env 14 mod(CodeMirror); 15 })(function(CodeMirror) { 16 "use strict"; 17 18 CodeMirror.defineMode("smarty", function(config, parserConf) { 19 var rightDelimiter = parserConf.rightDelimiter || "}"; 20 var leftDelimiter = parserConf.leftDelimiter || "{"; 21 var version = parserConf.version || 2; 22 var baseMode = CodeMirror.getMode(config, parserConf.baseMode || "null"); 23 24 var keyFunctions = ["debug", "extends", "function", "include", "literal"]; 25 var regs = { 26 operatorChars: /[+\-*&%=<>!?]/, 27 validIdentifier: /[a-zA-Z0-9_]/, 28 stringChar: /['"]/ 29 }; 30 31 var last; 32 function cont(style, lastType) { 33 last = lastType; 34 return style; 35 } 36 37 function chain(stream, state, parser) { 38 state.tokenize = parser; 39 return parser(stream, state); 40 } 41 42 // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode 43 function doesNotCount(stream, pos) { 44 if (pos == null) pos = stream.pos; 45 return version === 3 && leftDelimiter == "{" && 46 (pos == stream.string.length || /\s/.test(stream.string.charAt(pos))); 47 } 48 49 function tokenTop(stream, state) { 50 var string = stream.string; 51 for (var scan = stream.pos;;) { 52 var nextMatch = string.indexOf(leftDelimiter, scan); 53 scan = nextMatch + leftDelimiter.length; 54 if (nextMatch == -1 || !doesNotCount(stream, nextMatch + leftDelimiter.length)) break; 55 } 56 if (nextMatch == stream.pos) { 57 stream.match(leftDelimiter); 58 if (stream.eat("*")) { 59 return chain(stream, state, tokenBlock("comment", "*" + rightDelimiter)); 60 } else { 61 state.depth++; 62 state.tokenize = tokenSmarty; 63 last = "startTag"; 64 return "tag"; 65 } 66 } 67 68 if (nextMatch > -1) stream.string = string.slice(0, nextMatch); 69 var token = baseMode.token(stream, state.base); 70 if (nextMatch > -1) stream.string = string; 71 return token; 72 } 73 74 // parsing Smarty content 75 function tokenSmarty(stream, state) { 76 if (stream.match(rightDelimiter, true)) { 77 if (version === 3) { 78 state.depth--; 79 if (state.depth <= 0) { 80 state.tokenize = tokenTop; 81 } 82 } else { 83 state.tokenize = tokenTop; 84 } 85 return cont("tag", null); 86 } 87 88 if (stream.match(leftDelimiter, true)) { 89 state.depth++; 90 return cont("tag", "startTag"); 91 } 92 93 var ch = stream.next(); 94 if (ch == "$") { 95 stream.eatWhile(regs.validIdentifier); 96 return cont("variable-2", "variable"); 97 } else if (ch == "|") { 98 return cont("operator", "pipe"); 99 } else if (ch == ".") { 100 return cont("operator", "property"); 101 } else if (regs.stringChar.test(ch)) { 102 state.tokenize = tokenAttribute(ch); 103 return cont("string", "string"); 104 } else if (regs.operatorChars.test(ch)) { 105 stream.eatWhile(regs.operatorChars); 106 return cont("operator", "operator"); 107 } else if (ch == "[" || ch == "]") { 108 return cont("bracket", "bracket"); 109 } else if (ch == "(" || ch == ")") { 110 return cont("bracket", "operator"); 111 } else if (/\d/.test(ch)) { 112 stream.eatWhile(/\d/); 113 return cont("number", "number"); 114 } else { 115 116 if (state.last == "variable") { 117 if (ch == "@") { 118 stream.eatWhile(regs.validIdentifier); 119 return cont("property", "property"); 120 } else if (ch == "|") { 121 stream.eatWhile(regs.validIdentifier); 122 return cont("qualifier", "modifier"); 123 } 124 } else if (state.last == "pipe") { 125 stream.eatWhile(regs.validIdentifier); 126 return cont("qualifier", "modifier"); 127 } else if (state.last == "whitespace") { 128 stream.eatWhile(regs.validIdentifier); 129 return cont("attribute", "modifier"); 130 } if (state.last == "property") { 131 stream.eatWhile(regs.validIdentifier); 132 return cont("property", null); 133 } else if (/\s/.test(ch)) { 134 last = "whitespace"; 135 return null; 136 } 137 138 var str = ""; 139 if (ch != "/") { 140 str += ch; 141 } 142 var c = null; 143 while (c = stream.eat(regs.validIdentifier)) { 144 str += c; 145 } 146 for (var i=0, j=keyFunctions.length; i<j; i++) { 147 if (keyFunctions[i] == str) { 148 return cont("keyword", "keyword"); 149 } 150 } 151 if (/\s/.test(ch)) { 152 return null; 153 } 154 return cont("tag", "tag"); 155 } 156 } 157 158 function tokenAttribute(quote) { 159 return function(stream, state) { 160 var prevChar = null; 161 var currChar = null; 162 while (!stream.eol()) { 163 currChar = stream.peek(); 164 if (stream.next() == quote && prevChar !== '\\') { 165 state.tokenize = tokenSmarty; 166 break; 167 } 168 prevChar = currChar; 169 } 170 return "string"; 171 }; 172 } 173 174 function tokenBlock(style, terminator) { 175 return function(stream, state) { 176 while (!stream.eol()) { 177 if (stream.match(terminator)) { 178 state.tokenize = tokenTop; 179 break; 180 } 181 stream.next(); 182 } 183 return style; 184 }; 185 } 186 187 return { 188 startState: function() { 189 return { 190 base: CodeMirror.startState(baseMode), 191 tokenize: tokenTop, 192 last: null, 193 depth: 0 194 }; 195 }, 196 copyState: function(state) { 197 return { 198 base: CodeMirror.copyState(baseMode, state.base), 199 tokenize: state.tokenize, 200 last: state.last, 201 depth: state.depth 202 }; 203 }, 204 innerMode: function(state) { 205 if (state.tokenize == tokenTop) 206 return {mode: baseMode, state: state.base}; 207 }, 208 token: function(stream, state) { 209 var style = state.tokenize(stream, state); 210 state.last = last; 211 return style; 212 }, 213 indent: function(state, text) { 214 if (state.tokenize == tokenTop && baseMode.indent) 215 return baseMode.indent(state.base, text); 216 else 217 return CodeMirror.Pass; 218 }, 219 blockCommentStart: leftDelimiter + "*", 220 blockCommentEnd: "*" + rightDelimiter 221 }; 222 }); 223 224 CodeMirror.defineMIME("text/x-smarty", "smarty"); 225 });
Download modules/editor/codemirror/mode/smarty/smarty.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.