diff src/nabble/view/web/util/codemirror/js/parsecss.js @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nabble/view/web/util/codemirror/js/parsecss.js	Thu Mar 21 19:15:52 2019 -0600
@@ -0,0 +1,161 @@
+/* Simple parser for CSS */
+
+var CSSParser = Editor.Parser = (function() {
+  var tokenizeCSS = (function() {
+    function normal(source, setState) {
+      var ch = source.next();
+      if (ch == "@") {
+        source.nextWhileMatches(/\w/);
+        return "css-at";
+      }
+      else if (ch == "/" && source.equals("*")) {
+        setState(inCComment);
+        return null;
+      }
+      else if (ch == "<" && source.equals("!")) {
+        setState(inSGMLComment);
+        return null;
+      }
+      else if (ch == "=") {
+        return "css-compare";
+      }
+      else if (source.equals("=") && (ch == "~" || ch == "|")) {
+        source.next();
+        return "css-compare";
+      }
+      else if (ch == "\"" || ch == "'") {
+        setState(inString(ch));
+        return null;
+      }
+      else if (ch == "#") {
+        source.nextWhileMatches(/\w/);
+        return "css-hash";
+      }
+      else if (ch == "!") {
+        source.nextWhileMatches(/[ \t]/);
+        source.nextWhileMatches(/\w/);
+        return "css-important";
+      }
+      else if (/\d/.test(ch)) {
+        source.nextWhileMatches(/[\w.%]/);
+        return "css-unit";
+      }
+      else if (/[,.+>*\/]/.test(ch)) {
+        return "css-select-op";
+      }
+      else if (/[;{}:\[\]]/.test(ch)) {
+        return "css-punctuation";
+      }
+      else {
+        source.nextWhileMatches(/[\w\\\-_]/);
+        return "css-identifier";
+      }
+    }
+
+    function inCComment(source, setState) {
+      var maybeEnd = false;
+      while (!source.endOfLine()) {
+        var ch = source.next();
+        if (maybeEnd && ch == "/") {
+          setState(normal);
+          break;
+        }
+        maybeEnd = (ch == "*");
+      }
+      return "css-comment";
+    }
+
+    function inSGMLComment(source, setState) {
+      var dashes = 0;
+      while (!source.endOfLine()) {
+        var ch = source.next();
+        if (dashes >= 2 && ch == ">") {
+          setState(normal);
+          break;
+        }
+        dashes = (ch == "-") ? dashes + 1 : 0;
+      }
+      return "css-comment";
+    }
+
+    function inString(quote) {
+      return function(source, setState) {
+        var escaped = false;
+        while (!source.endOfLine()) {
+          var ch = source.next();
+          if (ch == quote && !escaped)
+            break;
+          escaped = !escaped && ch == "\\";
+        }
+        if (!escaped)
+          setState(normal);
+        return "css-string";
+      };
+    }
+
+    return function(source, startState) {
+      return tokenizer(source, startState || normal);
+    };
+  })();
+
+  function indentCSS(inBraces, inRule, base) {
+    return function(nextChars) {
+      if (!inBraces || /^\}/.test(nextChars)) return base;
+      else if (inRule) return base + indentUnit * 2;
+      else return base + indentUnit;
+    };
+  }
+
+  // This is a very simplistic parser -- since CSS does not really
+  // nest, it works acceptably well, but some nicer colouroing could
+  // be provided with a more complicated parser.
+  function parseCSS(source, basecolumn) {
+    basecolumn = basecolumn || 0;
+    var tokens = tokenizeCSS(source);
+    var inBraces = false, inRule = false, inDecl = false;;
+
+    var iter = {
+      next: function() {
+        var token = tokens.next(), style = token.style, content = token.content;
+
+        if (style == "css-hash")
+          style = token.style =  inRule ? "css-colorcode" : "css-identifier";
+        if (style == "css-identifier") {
+          if (inRule) token.style = "css-value";
+          else if (!inBraces && !inDecl) token.style = "css-selector";
+        }
+
+        if (content == "\n")
+          token.indentation = indentCSS(inBraces, inRule, basecolumn);
+
+        if (content == "{" && inDecl == "@media")
+          inDecl = false;
+        else if (content == "{")
+          inBraces = true;
+        else if (content == "}")
+          inBraces = inRule = inDecl = false;
+        else if (content == ";")
+          inRule = inDecl = false;
+        else if (inBraces && style != "css-comment" && style != "whitespace")
+          inRule = true;
+        else if (!inBraces && style == "css-at")
+          inDecl = content;
+
+        return token;
+      },
+
+      copy: function() {
+        var _inBraces = inBraces, _inRule = inRule, _tokenState = tokens.state;
+        return function(source) {
+          tokens = tokenizeCSS(source, _tokenState);
+          inBraces = _inBraces;
+          inRule = _inRule;
+          return iter;
+        };
+      }
+    };
+    return iter;
+  }
+
+  return {make: parseCSS, electricChars: "}"};
+})();