You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							222 lines
						
					
					
						
							6.5 KiB
						
					
					
				
			
		
		
	
	
							222 lines
						
					
					
						
							6.5 KiB
						
					
					
				| // CodeMirror, copyright (c) by Marijn Haverbeke and others
 | |
| // Distributed under an MIT license: http://codemirror.net/LICENSE
 | |
| 
 | |
| /**
 | |
|  * Smarty 2 and 3 mode.
 | |
|  */
 | |
| 
 | |
| (function(mod) {
 | |
|   if (typeof exports == "object" && typeof module == "object") // CommonJS
 | |
|     mod(require("../../lib/codemirror"));
 | |
|   else if (typeof define == "function" && define.amd) // AMD
 | |
|     define(["../../lib/codemirror"], mod);
 | |
|   else // Plain browser env
 | |
|     mod(CodeMirror);
 | |
| })(function(CodeMirror) {
 | |
| "use strict";
 | |
| 
 | |
| CodeMirror.defineMode("smarty", function(config) {
 | |
|   "use strict";
 | |
| 
 | |
|   // our default settings; check to see if they're overridden
 | |
|   var settings = {
 | |
|     rightDelimiter: '}',
 | |
|     leftDelimiter: '{',
 | |
|     smartyVersion: 2 // for backward compatibility
 | |
|   };
 | |
|   if (config.hasOwnProperty("leftDelimiter")) {
 | |
|     settings.leftDelimiter = config.leftDelimiter;
 | |
|   }
 | |
|   if (config.hasOwnProperty("rightDelimiter")) {
 | |
|     settings.rightDelimiter = config.rightDelimiter;
 | |
|   }
 | |
|   if (config.hasOwnProperty("smartyVersion") && config.smartyVersion === 3) {
 | |
|     settings.smartyVersion = 3;
 | |
|   }
 | |
| 
 | |
|   var keyFunctions = ["debug", "extends", "function", "include", "literal"];
 | |
|   var last;
 | |
|   var regs = {
 | |
|     operatorChars: /[+\-*&%=<>!?]/,
 | |
|     validIdentifier: /[a-zA-Z0-9_]/,
 | |
|     stringChar: /['"]/
 | |
|   };
 | |
| 
 | |
|   var helpers = {
 | |
|     cont: function(style, lastType) {
 | |
|       last = lastType;
 | |
|       return style;
 | |
|     },
 | |
|     chain: function(stream, state, parser) {
 | |
|       state.tokenize = parser;
 | |
|       return parser(stream, state);
 | |
|     }
 | |
|   };
 | |
| 
 | |
| 
 | |
|   // our various parsers
 | |
|   var parsers = {
 | |
| 
 | |
|     // the main tokenizer
 | |
|     tokenizer: function(stream, state) {
 | |
|       if (stream.match(settings.leftDelimiter, true)) {
 | |
|         if (stream.eat("*")) {
 | |
|           return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
 | |
|         } else {
 | |
|           // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode
 | |
|           state.depth++;
 | |
|           var isEol = stream.eol();
 | |
|           var isFollowedByWhitespace = /\s/.test(stream.peek());
 | |
|           if (settings.smartyVersion === 3 && settings.leftDelimiter === "{" && (isEol || isFollowedByWhitespace)) {
 | |
|             state.depth--;
 | |
|             return null;
 | |
|           } else {
 | |
|             state.tokenize = parsers.smarty;
 | |
|             last = "startTag";
 | |
|             return "tag";
 | |
|           }
 | |
|         }
 | |
|       } else {
 | |
|         stream.next();
 | |
|         return null;
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     // parsing Smarty content
 | |
|     smarty: function(stream, state) {
 | |
|       if (stream.match(settings.rightDelimiter, true)) {
 | |
|         if (settings.smartyVersion === 3) {
 | |
|           state.depth--;
 | |
|           if (state.depth <= 0) {
 | |
|             state.tokenize = parsers.tokenizer;
 | |
|           }
 | |
|         } else {
 | |
|           state.tokenize = parsers.tokenizer;
 | |
|         }
 | |
|         return helpers.cont("tag", null);
 | |
|       }
 | |
| 
 | |
|       if (stream.match(settings.leftDelimiter, true)) {
 | |
|         state.depth++;
 | |
|         return helpers.cont("tag", "startTag");
 | |
|       }
 | |
| 
 | |
|       var ch = stream.next();
 | |
|       if (ch == "$") {
 | |
|         stream.eatWhile(regs.validIdentifier);
 | |
|         return helpers.cont("variable-2", "variable");
 | |
|       } else if (ch == "|") {
 | |
|         return helpers.cont("operator", "pipe");
 | |
|       } else if (ch == ".") {
 | |
|         return helpers.cont("operator", "property");
 | |
|       } else if (regs.stringChar.test(ch)) {
 | |
|         state.tokenize = parsers.inAttribute(ch);
 | |
|         return helpers.cont("string", "string");
 | |
|       } else if (regs.operatorChars.test(ch)) {
 | |
|         stream.eatWhile(regs.operatorChars);
 | |
|         return helpers.cont("operator", "operator");
 | |
|       } else if (ch == "[" || ch == "]") {
 | |
|         return helpers.cont("bracket", "bracket");
 | |
|       } else if (ch == "(" || ch == ")") {
 | |
|         return helpers.cont("bracket", "operator");
 | |
|       } else if (/\d/.test(ch)) {
 | |
|         stream.eatWhile(/\d/);
 | |
|         return helpers.cont("number", "number");
 | |
|       } else {
 | |
| 
 | |
|         if (state.last == "variable") {
 | |
|           if (ch == "@") {
 | |
|             stream.eatWhile(regs.validIdentifier);
 | |
|             return helpers.cont("property", "property");
 | |
|           } else if (ch == "|") {
 | |
|             stream.eatWhile(regs.validIdentifier);
 | |
|             return helpers.cont("qualifier", "modifier");
 | |
|           }
 | |
|         } else if (state.last == "pipe") {
 | |
|           stream.eatWhile(regs.validIdentifier);
 | |
|           return helpers.cont("qualifier", "modifier");
 | |
|         } else if (state.last == "whitespace") {
 | |
|           stream.eatWhile(regs.validIdentifier);
 | |
|           return helpers.cont("attribute", "modifier");
 | |
|         } if (state.last == "property") {
 | |
|           stream.eatWhile(regs.validIdentifier);
 | |
|           return helpers.cont("property", null);
 | |
|         } else if (/\s/.test(ch)) {
 | |
|           last = "whitespace";
 | |
|           return null;
 | |
|         }
 | |
| 
 | |
|         var str = "";
 | |
|         if (ch != "/") {
 | |
|           str += ch;
 | |
|         }
 | |
|         var c = null;
 | |
|         while (c = stream.eat(regs.validIdentifier)) {
 | |
|           str += c;
 | |
|         }
 | |
|         for (var i=0, j=keyFunctions.length; i<j; i++) {
 | |
|           if (keyFunctions[i] == str) {
 | |
|             return helpers.cont("keyword", "keyword");
 | |
|           }
 | |
|         }
 | |
|         if (/\s/.test(ch)) {
 | |
|           return null;
 | |
|         }
 | |
|         return helpers.cont("tag", "tag");
 | |
|       }
 | |
|     },
 | |
| 
 | |
|     inAttribute: function(quote) {
 | |
|       return function(stream, state) {
 | |
|         var prevChar = null;
 | |
|         var currChar = null;
 | |
|         while (!stream.eol()) {
 | |
|           currChar = stream.peek();
 | |
|           if (stream.next() == quote && prevChar !== '\\') {
 | |
|             state.tokenize = parsers.smarty;
 | |
|             break;
 | |
|           }
 | |
|           prevChar = currChar;
 | |
|         }
 | |
|         return "string";
 | |
|       };
 | |
|     },
 | |
| 
 | |
|     inBlock: function(style, terminator) {
 | |
|       return function(stream, state) {
 | |
|         while (!stream.eol()) {
 | |
|           if (stream.match(terminator)) {
 | |
|             state.tokenize = parsers.tokenizer;
 | |
|             break;
 | |
|           }
 | |
|           stream.next();
 | |
|         }
 | |
|         return style;
 | |
|       };
 | |
|     }
 | |
|   };
 | |
| 
 | |
| 
 | |
|   // the public API for CodeMirror
 | |
|   return {
 | |
|     startState: function() {
 | |
|       return {
 | |
|         tokenize: parsers.tokenizer,
 | |
|         mode: "smarty",
 | |
|         last: null,
 | |
|         depth: 0
 | |
|       };
 | |
|     },
 | |
|     token: function(stream, state) {
 | |
|       var style = state.tokenize(stream, state);
 | |
|       state.last = last;
 | |
|       return style;
 | |
|     },
 | |
|     electricChars: ""
 | |
|   };
 | |
| });
 | |
| 
 | |
| CodeMirror.defineMIME("text/x-smarty", "smarty");
 | |
| 
 | |
| });
 |