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