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