css.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. CodeMirror.defineMode("css", function(config) {
  2. var indentUnit = config.indentUnit, type;
  3. function ret(style, tp) {type = tp; return style;}
  4. function tokenBase(stream, state) {
  5. var ch = stream.next();
  6. if (ch == "@") {stream.eatWhile(/\w/); return ret("meta", stream.current());}
  7. else if (ch == "/" && stream.eat("*")) {
  8. state.tokenize = tokenCComment;
  9. return tokenCComment(stream, state);
  10. }
  11. else if (ch == "<" && stream.eat("!")) {
  12. state.tokenize = tokenSGMLComment;
  13. return tokenSGMLComment(stream, state);
  14. }
  15. else if (ch == "=") ret(null, "compare");
  16. else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
  17. else if (ch == "\"" || ch == "'") {
  18. state.tokenize = tokenString(ch);
  19. return state.tokenize(stream, state);
  20. }
  21. else if (ch == "#") {
  22. stream.eatWhile(/\w/);
  23. return ret("atom", "hash");
  24. }
  25. else if (ch == "!") {
  26. stream.match(/^\s*\w*/);
  27. return ret("keyword", "important");
  28. }
  29. else if (/\d/.test(ch)) {
  30. stream.eatWhile(/[\w.%]/);
  31. return ret("number", "unit");
  32. }
  33. else if (/[,.+>*\/]/.test(ch)) {
  34. return ret(null, "select-op");
  35. }
  36. else if (/[;{}:\[\]]/.test(ch)) {
  37. return ret(null, ch);
  38. }
  39. else {
  40. stream.eatWhile(/[\w\\\-_]/);
  41. return ret("variable", "variable");
  42. }
  43. }
  44. function tokenCComment(stream, state) {
  45. var maybeEnd = false, ch;
  46. while ((ch = stream.next()) != null) {
  47. if (maybeEnd && ch == "/") {
  48. state.tokenize = tokenBase;
  49. break;
  50. }
  51. maybeEnd = (ch == "*");
  52. }
  53. return ret("comment", "comment");
  54. }
  55. function tokenSGMLComment(stream, state) {
  56. var dashes = 0, ch;
  57. while ((ch = stream.next()) != null) {
  58. if (dashes >= 2 && ch == ">") {
  59. state.tokenize = tokenBase;
  60. break;
  61. }
  62. dashes = (ch == "-") ? dashes + 1 : 0;
  63. }
  64. return ret("comment", "comment");
  65. }
  66. function tokenString(quote) {
  67. return function(stream, state) {
  68. var escaped = false, ch;
  69. while ((ch = stream.next()) != null) {
  70. if (ch == quote && !escaped)
  71. break;
  72. escaped = !escaped && ch == "\\";
  73. }
  74. if (!escaped) state.tokenize = tokenBase;
  75. return ret("string", "string");
  76. };
  77. }
  78. return {
  79. startState: function(base) {
  80. return {tokenize: tokenBase,
  81. baseIndent: base || 0,
  82. stack: []};
  83. },
  84. token: function(stream, state) {
  85. if (stream.eatSpace()) return null;
  86. var style = state.tokenize(stream, state);
  87. var context = state.stack[state.stack.length-1];
  88. if (type == "hash" && context == "rule") style = "atom";
  89. else if (style == "variable") {
  90. if (context == "rule") style = "number";
  91. else if (!context || context == "@media{") style = "tag";
  92. }
  93. if (context == "rule" && /^[\{\};]$/.test(type))
  94. state.stack.pop();
  95. if (type == "{") {
  96. if (context == "@media") state.stack[state.stack.length-1] = "@media{";
  97. else state.stack.push("{");
  98. }
  99. else if (type == "}") state.stack.pop();
  100. else if (type == "@media") state.stack.push("@media");
  101. else if (context == "{" && type != "comment") state.stack.push("rule");
  102. return style;
  103. },
  104. indent: function(state, textAfter) {
  105. var n = state.stack.length;
  106. if (/^\}/.test(textAfter))
  107. n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
  108. return state.baseIndent + n * indentUnit;
  109. },
  110. electricChars: "}"
  111. };
  112. });
  113. CodeMirror.defineMIME("text/css", "css");