Mercurial > hg > soundsoftware-site
comparison vendor/gems/coderay-0.9.7/lib/coderay/scanners/.svn/text-base/css.rb.svn-base @ 210:0579821a129a
Update to Redmine trunk rev 4802
author | Chris Cannam |
---|---|
date | Tue, 08 Feb 2011 13:51:46 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
128:07fa8a8b56a8 | 210:0579821a129a |
---|---|
1 module CodeRay | |
2 module Scanners | |
3 | |
4 class CSS < Scanner | |
5 | |
6 register_for :css | |
7 | |
8 KINDS_NOT_LOC = [ | |
9 :comment, | |
10 :class, :pseudo_class, :type, | |
11 :constant, :directive, | |
12 :key, :value, :operator, :color, :float, | |
13 :error, :important, | |
14 ] | |
15 | |
16 module RE | |
17 Hex = /[0-9a-fA-F]/ | |
18 Unicode = /\\#{Hex}{1,6}(?:\r\n|\s)?/ # differs from standard because it allows uppercase hex too | |
19 Escape = /#{Unicode}|\\[^\r\n\f0-9a-fA-F]/ | |
20 NMChar = /[-_a-zA-Z0-9]|#{Escape}/ | |
21 NMStart = /[_a-zA-Z]|#{Escape}/ | |
22 NL = /\r\n|\r|\n|\f/ | |
23 String1 = /"(?:[^\n\r\f\\"]|\\#{NL}|#{Escape})*"?/ # FIXME: buggy regexp | |
24 String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # FIXME: buggy regexp | |
25 String = /#{String1}|#{String2}/ | |
26 | |
27 HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/ | |
28 Color = /#{HexColor}/ | |
29 | |
30 Num = /-?(?:[0-9]+|[0-9]*\.[0-9]+)/ | |
31 Name = /#{NMChar}+/ | |
32 Ident = /-?#{NMStart}#{NMChar}*/ | |
33 AtKeyword = /@#{Ident}/ | |
34 Percentage = /#{Num}%/ | |
35 | |
36 reldimensions = %w[em ex px] | |
37 absdimensions = %w[in cm mm pt pc] | |
38 Unit = Regexp.union(*(reldimensions + absdimensions)) | |
39 | |
40 Dimension = /#{Num}#{Unit}/ | |
41 | |
42 Comment = %r! /\* (?: .*? \*/ | .* ) !mx | |
43 Function = /(?:url|alpha)\((?:[^)\n\r\f]|\\\))*\)?/ | |
44 | |
45 Id = /##{Name}/ | |
46 Class = /\.#{Name}/ | |
47 PseudoClass = /:#{Name}/ | |
48 AttributeSelector = /\[[^\]]*\]?/ | |
49 | |
50 end | |
51 | |
52 def scan_tokens tokens, options | |
53 | |
54 value_expected = nil | |
55 states = [:initial] | |
56 | |
57 until eos? | |
58 | |
59 kind = nil | |
60 match = nil | |
61 | |
62 if scan(/\s+/) | |
63 kind = :space | |
64 | |
65 elsif case states.last | |
66 when :initial, :media | |
67 if scan(/(?>#{RE::Ident})(?!\()|\*/ox) | |
68 kind = :type | |
69 elsif scan RE::Class | |
70 kind = :class | |
71 elsif scan RE::Id | |
72 kind = :constant | |
73 elsif scan RE::PseudoClass | |
74 kind = :pseudo_class | |
75 elsif match = scan(RE::AttributeSelector) | |
76 # TODO: Improve highlighting inside of attribute selectors. | |
77 tokens << [:open, :string] | |
78 tokens << [match[0,1], :delimiter] | |
79 tokens << [match[1..-2], :content] if match.size > 2 | |
80 tokens << [match[-1,1], :delimiter] if match[-1] == ?] | |
81 tokens << [:close, :string] | |
82 next | |
83 elsif match = scan(/@media/) | |
84 kind = :directive | |
85 states.push :media_before_name | |
86 end | |
87 | |
88 when :block | |
89 if scan(/(?>#{RE::Ident})(?!\()/ox) | |
90 if value_expected | |
91 kind = :value | |
92 else | |
93 kind = :key | |
94 end | |
95 end | |
96 | |
97 when :media_before_name | |
98 if scan RE::Ident | |
99 kind = :type | |
100 states[-1] = :media_after_name | |
101 end | |
102 | |
103 when :media_after_name | |
104 if scan(/\{/) | |
105 kind = :operator | |
106 states[-1] = :media | |
107 end | |
108 | |
109 when :comment | |
110 if scan(/(?:[^*\s]|\*(?!\/))+/) | |
111 kind = :comment | |
112 elsif scan(/\*\//) | |
113 kind = :comment | |
114 states.pop | |
115 elsif scan(/\s+/) | |
116 kind = :space | |
117 end | |
118 | |
119 else | |
120 raise_inspect 'Unknown state', tokens | |
121 | |
122 end | |
123 | |
124 elsif scan(/\/\*/) | |
125 kind = :comment | |
126 states.push :comment | |
127 | |
128 elsif scan(/\{/) | |
129 value_expected = false | |
130 kind = :operator | |
131 states.push :block | |
132 | |
133 elsif scan(/\}/) | |
134 value_expected = false | |
135 if states.last == :block || states.last == :media | |
136 kind = :operator | |
137 states.pop | |
138 else | |
139 kind = :error | |
140 end | |
141 | |
142 elsif match = scan(/#{RE::String}/o) | |
143 tokens << [:open, :string] | |
144 tokens << [match[0, 1], :delimiter] | |
145 tokens << [match[1..-2], :content] if match.size > 2 | |
146 tokens << [match[-1, 1], :delimiter] if match.size >= 2 | |
147 tokens << [:close, :string] | |
148 next | |
149 | |
150 elsif match = scan(/#{RE::Function}/o) | |
151 tokens << [:open, :string] | |
152 start = match[/^\w+\(/] | |
153 tokens << [start, :delimiter] | |
154 if match[-1] == ?) | |
155 tokens << [match[start.size..-2], :content] | |
156 tokens << [')', :delimiter] | |
157 else | |
158 tokens << [match[start.size..-1], :content] | |
159 end | |
160 tokens << [:close, :string] | |
161 next | |
162 | |
163 elsif scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) | |
164 kind = :float | |
165 | |
166 elsif scan(/#{RE::Color}/o) | |
167 kind = :color | |
168 | |
169 elsif scan(/! *important/) | |
170 kind = :important | |
171 | |
172 elsif scan(/rgb\([^()\n]*\)?/) | |
173 kind = :color | |
174 | |
175 elsif scan(/#{RE::AtKeyword}/o) | |
176 kind = :directive | |
177 | |
178 elsif match = scan(/ [+>:;,.=()\/] /x) | |
179 if match == ':' | |
180 value_expected = true | |
181 elsif match == ';' | |
182 value_expected = false | |
183 end | |
184 kind = :operator | |
185 | |
186 else | |
187 getch | |
188 kind = :error | |
189 | |
190 end | |
191 | |
192 match ||= matched | |
193 if $CODERAY_DEBUG and not kind | |
194 raise_inspect 'Error token %p in line %d' % | |
195 [[match, kind], line], tokens | |
196 end | |
197 raise_inspect 'Empty token', tokens unless match | |
198 | |
199 tokens << [match, kind] | |
200 | |
201 end | |
202 | |
203 tokens | |
204 end | |
205 | |
206 end | |
207 | |
208 end | |
209 end |