Mercurial > hg > soundsoftware-site
comparison vendor/gems/coderay-1.0.0/lib/coderay/scanners/css.rb @ 909:cbb26bc654de redmine-1.3
Update to Redmine 1.3-stable branch (Redmine SVN rev 8964)
author | Chris Cannam |
---|---|
date | Fri, 24 Feb 2012 19:09:32 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
908:c6c2cbd0afee | 909:cbb26bc654de |
---|---|
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, :string, | |
13 :error, :important, | |
14 ] # :nodoc: | |
15 | |
16 module RE # :nodoc: | |
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})*"?/ # TODO: buggy regexp | |
24 String2 = /'(?:[^\n\r\f\\']|\\#{NL}|#{Escape})*'?/ # TODO: 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|attr|counters?)\((?:[^)\n\r\f]|\\\))*\)?/ | |
44 | |
45 Id = /##{Name}/ | |
46 Class = /\.#{Name}/ | |
47 PseudoClass = /:#{Name}/ | |
48 AttributeSelector = /\[[^\]]*\]?/ | |
49 end | |
50 | |
51 protected | |
52 | |
53 def scan_tokens encoder, options | |
54 | |
55 value_expected = nil | |
56 states = [:initial] | |
57 | |
58 until eos? | |
59 | |
60 if match = scan(/\s+/) | |
61 encoder.text_token match, :space | |
62 | |
63 elsif case states.last | |
64 when :initial, :media | |
65 if match = scan(/(?>#{RE::Ident})(?!\()|\*/ox) | |
66 encoder.text_token match, :type | |
67 next | |
68 elsif match = scan(RE::Class) | |
69 encoder.text_token match, :class | |
70 next | |
71 elsif match = scan(RE::Id) | |
72 encoder.text_token match, :constant | |
73 next | |
74 elsif match = scan(RE::PseudoClass) | |
75 encoder.text_token match, :pseudo_class | |
76 next | |
77 elsif match = scan(RE::AttributeSelector) | |
78 # TODO: Improve highlighting inside of attribute selectors. | |
79 encoder.text_token match[0,1], :operator | |
80 encoder.text_token match[1..-2], :attribute_name if match.size > 2 | |
81 encoder.text_token match[-1,1], :operator if match[-1] == ?] | |
82 next | |
83 elsif match = scan(/@media/) | |
84 encoder.text_token match, :directive | |
85 states.push :media_before_name | |
86 next | |
87 end | |
88 | |
89 when :block | |
90 if match = scan(/(?>#{RE::Ident})(?!\()/ox) | |
91 if value_expected | |
92 encoder.text_token match, :value | |
93 else | |
94 encoder.text_token match, :key | |
95 end | |
96 next | |
97 end | |
98 | |
99 when :media_before_name | |
100 if match = scan(RE::Ident) | |
101 encoder.text_token match, :type | |
102 states[-1] = :media_after_name | |
103 next | |
104 end | |
105 | |
106 when :media_after_name | |
107 if match = scan(/\{/) | |
108 encoder.text_token match, :operator | |
109 states[-1] = :media | |
110 next | |
111 end | |
112 | |
113 else | |
114 #:nocov: | |
115 raise_inspect 'Unknown state', encoder | |
116 #:nocov: | |
117 | |
118 end | |
119 | |
120 elsif match = scan(/\/\*(?:.*?\*\/|\z)/m) | |
121 encoder.text_token match, :comment | |
122 | |
123 elsif match = scan(/\{/) | |
124 value_expected = false | |
125 encoder.text_token match, :operator | |
126 states.push :block | |
127 | |
128 elsif match = scan(/\}/) | |
129 value_expected = false | |
130 if states.last == :block || states.last == :media | |
131 encoder.text_token match, :operator | |
132 states.pop | |
133 else | |
134 encoder.text_token match, :error | |
135 end | |
136 | |
137 elsif match = scan(/#{RE::String}/o) | |
138 encoder.begin_group :string | |
139 encoder.text_token match[0, 1], :delimiter | |
140 encoder.text_token match[1..-2], :content if match.size > 2 | |
141 encoder.text_token match[-1, 1], :delimiter if match.size >= 2 | |
142 encoder.end_group :string | |
143 | |
144 elsif match = scan(/#{RE::Function}/o) | |
145 encoder.begin_group :string | |
146 start = match[/^\w+\(/] | |
147 encoder.text_token start, :delimiter | |
148 if match[-1] == ?) | |
149 encoder.text_token match[start.size..-2], :content | |
150 encoder.text_token ')', :delimiter | |
151 else | |
152 encoder.text_token match[start.size..-1], :content | |
153 end | |
154 encoder.end_group :string | |
155 | |
156 elsif match = scan(/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/ox) | |
157 encoder.text_token match, :float | |
158 | |
159 elsif match = scan(/#{RE::Color}/o) | |
160 encoder.text_token match, :color | |
161 | |
162 elsif match = scan(/! *important/) | |
163 encoder.text_token match, :important | |
164 | |
165 elsif match = scan(/(?:rgb|hsl)a?\([^()\n]*\)?/) | |
166 encoder.text_token match, :color | |
167 | |
168 elsif match = scan(RE::AtKeyword) | |
169 encoder.text_token match, :directive | |
170 | |
171 elsif match = scan(/ [+>:;,.=()\/] /x) | |
172 if match == ':' | |
173 value_expected = true | |
174 elsif match == ';' | |
175 value_expected = false | |
176 end | |
177 encoder.text_token match, :operator | |
178 | |
179 else | |
180 encoder.text_token getch, :error | |
181 | |
182 end | |
183 | |
184 end | |
185 | |
186 encoder | |
187 end | |
188 | |
189 end | |
190 | |
191 end | |
192 end |