Mercurial Hosting > nabble
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 /* Simple parser for CSS */ | |
2 | |
3 var CSSParser = Editor.Parser = (function() { | |
4 var tokenizeCSS = (function() { | |
5 function normal(source, setState) { | |
6 var ch = source.next(); | |
7 if (ch == "@") { | |
8 source.nextWhileMatches(/\w/); | |
9 return "css-at"; | |
10 } | |
11 else if (ch == "/" && source.equals("*")) { | |
12 setState(inCComment); | |
13 return null; | |
14 } | |
15 else if (ch == "<" && source.equals("!")) { | |
16 setState(inSGMLComment); | |
17 return null; | |
18 } | |
19 else if (ch == "=") { | |
20 return "css-compare"; | |
21 } | |
22 else if (source.equals("=") && (ch == "~" || ch == "|")) { | |
23 source.next(); | |
24 return "css-compare"; | |
25 } | |
26 else if (ch == "\"" || ch == "'") { | |
27 setState(inString(ch)); | |
28 return null; | |
29 } | |
30 else if (ch == "#") { | |
31 source.nextWhileMatches(/\w/); | |
32 return "css-hash"; | |
33 } | |
34 else if (ch == "!") { | |
35 source.nextWhileMatches(/[ \t]/); | |
36 source.nextWhileMatches(/\w/); | |
37 return "css-important"; | |
38 } | |
39 else if (/\d/.test(ch)) { | |
40 source.nextWhileMatches(/[\w.%]/); | |
41 return "css-unit"; | |
42 } | |
43 else if (/[,.+>*\/]/.test(ch)) { | |
44 return "css-select-op"; | |
45 } | |
46 else if (/[;{}:\[\]]/.test(ch)) { | |
47 return "css-punctuation"; | |
48 } | |
49 else { | |
50 source.nextWhileMatches(/[\w\\\-_]/); | |
51 return "css-identifier"; | |
52 } | |
53 } | |
54 | |
55 function inCComment(source, setState) { | |
56 var maybeEnd = false; | |
57 while (!source.endOfLine()) { | |
58 var ch = source.next(); | |
59 if (maybeEnd && ch == "/") { | |
60 setState(normal); | |
61 break; | |
62 } | |
63 maybeEnd = (ch == "*"); | |
64 } | |
65 return "css-comment"; | |
66 } | |
67 | |
68 function inSGMLComment(source, setState) { | |
69 var dashes = 0; | |
70 while (!source.endOfLine()) { | |
71 var ch = source.next(); | |
72 if (dashes >= 2 && ch == ">") { | |
73 setState(normal); | |
74 break; | |
75 } | |
76 dashes = (ch == "-") ? dashes + 1 : 0; | |
77 } | |
78 return "css-comment"; | |
79 } | |
80 | |
81 function inString(quote) { | |
82 return function(source, setState) { | |
83 var escaped = false; | |
84 while (!source.endOfLine()) { | |
85 var ch = source.next(); | |
86 if (ch == quote && !escaped) | |
87 break; | |
88 escaped = !escaped && ch == "\\"; | |
89 } | |
90 if (!escaped) | |
91 setState(normal); | |
92 return "css-string"; | |
93 }; | |
94 } | |
95 | |
96 return function(source, startState) { | |
97 return tokenizer(source, startState || normal); | |
98 }; | |
99 })(); | |
100 | |
101 function indentCSS(inBraces, inRule, base) { | |
102 return function(nextChars) { | |
103 if (!inBraces || /^\}/.test(nextChars)) return base; | |
104 else if (inRule) return base + indentUnit * 2; | |
105 else return base + indentUnit; | |
106 }; | |
107 } | |
108 | |
109 // This is a very simplistic parser -- since CSS does not really | |
110 // nest, it works acceptably well, but some nicer colouroing could | |
111 // be provided with a more complicated parser. | |
112 function parseCSS(source, basecolumn) { | |
113 basecolumn = basecolumn || 0; | |
114 var tokens = tokenizeCSS(source); | |
115 var inBraces = false, inRule = false, inDecl = false;; | |
116 | |
117 var iter = { | |
118 next: function() { | |
119 var token = tokens.next(), style = token.style, content = token.content; | |
120 | |
121 if (style == "css-hash") | |
122 style = token.style = inRule ? "css-colorcode" : "css-identifier"; | |
123 if (style == "css-identifier") { | |
124 if (inRule) token.style = "css-value"; | |
125 else if (!inBraces && !inDecl) token.style = "css-selector"; | |
126 } | |
127 | |
128 if (content == "\n") | |
129 token.indentation = indentCSS(inBraces, inRule, basecolumn); | |
130 | |
131 if (content == "{" && inDecl == "@media") | |
132 inDecl = false; | |
133 else if (content == "{") | |
134 inBraces = true; | |
135 else if (content == "}") | |
136 inBraces = inRule = inDecl = false; | |
137 else if (content == ";") | |
138 inRule = inDecl = false; | |
139 else if (inBraces && style != "css-comment" && style != "whitespace") | |
140 inRule = true; | |
141 else if (!inBraces && style == "css-at") | |
142 inDecl = content; | |
143 | |
144 return token; | |
145 }, | |
146 | |
147 copy: function() { | |
148 var _inBraces = inBraces, _inRule = inRule, _tokenState = tokens.state; | |
149 return function(source) { | |
150 tokens = tokenizeCSS(source, _tokenState); | |
151 inBraces = _inBraces; | |
152 inRule = _inRule; | |
153 return iter; | |
154 }; | |
155 } | |
156 }; | |
157 return iter; | |
158 } | |
159 | |
160 return {make: parseCSS, electricChars: "}"}; | |
161 })(); |