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