mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-27 18:22:45 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			162 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // CodeMirror, copyright (c) by Marijn Haverbeke and others
 | |
| // Distributed under an MIT license: https://codemirror.net/LICENSE
 | |
| 
 | |
| (function(mod) {
 | |
|   if (typeof exports == "object" && typeof module == "object") // CommonJS
 | |
|     mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby"));
 | |
|   else if (typeof define == "function" && define.amd) // AMD
 | |
|     define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod);
 | |
|   else // Plain browser env
 | |
|     mod(CodeMirror);
 | |
| })(function(CodeMirror) {
 | |
| "use strict";
 | |
| 
 | |
|   // full haml mode. This handled embedded ruby and html fragments too
 | |
|   CodeMirror.defineMode("haml", function(config) {
 | |
|     var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"});
 | |
|     var rubyMode = CodeMirror.getMode(config, "ruby");
 | |
| 
 | |
|     function rubyInQuote(endQuote) {
 | |
|       return function(stream, state) {
 | |
|         var ch = stream.peek();
 | |
|         if (ch == endQuote && state.rubyState.tokenize.length == 1) {
 | |
|           // step out of ruby context as it seems to complete processing all the braces
 | |
|           stream.next();
 | |
|           state.tokenize = html;
 | |
|           return "closeAttributeTag";
 | |
|         } else {
 | |
|           return ruby(stream, state);
 | |
|         }
 | |
|       };
 | |
|     }
 | |
| 
 | |
|     function ruby(stream, state) {
 | |
|       if (stream.match("-#")) {
 | |
|         stream.skipToEnd();
 | |
|         return "comment";
 | |
|       }
 | |
|       return rubyMode.token(stream, state.rubyState);
 | |
|     }
 | |
| 
 | |
|     function html(stream, state) {
 | |
|       var ch = stream.peek();
 | |
| 
 | |
|       // handle haml declarations. All declarations that cant be handled here
 | |
|       // will be passed to html mode
 | |
|       if (state.previousToken.style == "comment" ) {
 | |
|         if (state.indented > state.previousToken.indented) {
 | |
|           stream.skipToEnd();
 | |
|           return "commentLine";
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (state.startOfLine) {
 | |
|         if (ch == "!" && stream.match("!!")) {
 | |
|           stream.skipToEnd();
 | |
|           return "tag";
 | |
|         } else if (stream.match(/^%[\w:#\.]+=/)) {
 | |
|           state.tokenize = ruby;
 | |
|           return "hamlTag";
 | |
|         } else if (stream.match(/^%[\w:]+/)) {
 | |
|           return "hamlTag";
 | |
|         } else if (ch == "/" ) {
 | |
|           stream.skipToEnd();
 | |
|           return "comment";
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (state.startOfLine || state.previousToken.style == "hamlTag") {
 | |
|         if ( ch == "#" || ch == ".") {
 | |
|           stream.match(/[\w-#\.]*/);
 | |
|           return "hamlAttribute";
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       // donot handle --> as valid ruby, make it HTML close comment instead
 | |
|       if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) {
 | |
|         state.tokenize = ruby;
 | |
|         return state.tokenize(stream, state);
 | |
|       }
 | |
| 
 | |
|       if (state.previousToken.style == "hamlTag" ||
 | |
|           state.previousToken.style == "closeAttributeTag" ||
 | |
|           state.previousToken.style == "hamlAttribute") {
 | |
|         if (ch == "(") {
 | |
|           state.tokenize = rubyInQuote(")");
 | |
|           return state.tokenize(stream, state);
 | |
|         } else if (ch == "{") {
 | |
|           if (!stream.match(/^\{%.*/)) {
 | |
|             state.tokenize = rubyInQuote("}");
 | |
|             return state.tokenize(stream, state);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       return htmlMode.token(stream, state.htmlState);
 | |
|     }
 | |
| 
 | |
|     return {
 | |
|       // default to html mode
 | |
|       startState: function() {
 | |
|         var htmlState = CodeMirror.startState(htmlMode);
 | |
|         var rubyState = CodeMirror.startState(rubyMode);
 | |
|         return {
 | |
|           htmlState: htmlState,
 | |
|           rubyState: rubyState,
 | |
|           indented: 0,
 | |
|           previousToken: { style: null, indented: 0},
 | |
|           tokenize: html
 | |
|         };
 | |
|       },
 | |
| 
 | |
|       copyState: function(state) {
 | |
|         return {
 | |
|           htmlState : CodeMirror.copyState(htmlMode, state.htmlState),
 | |
|           rubyState: CodeMirror.copyState(rubyMode, state.rubyState),
 | |
|           indented: state.indented,
 | |
|           previousToken: state.previousToken,
 | |
|           tokenize: state.tokenize
 | |
|         };
 | |
|       },
 | |
| 
 | |
|       token: function(stream, state) {
 | |
|         if (stream.sol()) {
 | |
|           state.indented = stream.indentation();
 | |
|           state.startOfLine = true;
 | |
|         }
 | |
|         if (stream.eatSpace()) return null;
 | |
|         var style = state.tokenize(stream, state);
 | |
|         state.startOfLine = false;
 | |
|         // dont record comment line as we only want to measure comment line with
 | |
|         // the opening comment block
 | |
|         if (style && style != "commentLine") {
 | |
|           state.previousToken = { style: style, indented: state.indented };
 | |
|         }
 | |
|         // if current state is ruby and the previous token is not `,` reset the
 | |
|         // tokenize to html
 | |
|         if (stream.eol() && state.tokenize == ruby) {
 | |
|           stream.backUp(1);
 | |
|           var ch = stream.peek();
 | |
|           stream.next();
 | |
|           if (ch && ch != ",") {
 | |
|             state.tokenize = html;
 | |
|           }
 | |
|         }
 | |
|         // reprocess some of the specific style tag when finish setting previousToken
 | |
|         if (style == "hamlTag") {
 | |
|           style = "tag";
 | |
|         } else if (style == "commentLine") {
 | |
|           style = "comment";
 | |
|         } else if (style == "hamlAttribute") {
 | |
|           style = "attribute";
 | |
|         } else if (style == "closeAttributeTag") {
 | |
|           style = null;
 | |
|         }
 | |
|         return style;
 | |
|       }
 | |
|     };
 | |
|   }, "htmlmixed", "ruby");
 | |
| 
 | |
|   CodeMirror.defineMIME("text/x-haml", "haml");
 | |
| });
 | 
