Class CodeRay::Scanners::CSS
In: lib/coderay/scanners/css.rb
Parent: Scanner

Methods

Classes and Modules

Module CodeRay::Scanners::CSS::RE

Constants

KINDS_NOT_LOC = [ :comment, :class, :pseudo_class, :type, :constant, :directive, :key, :value, :operator, :color, :float, :content, :delimiter, :error, :important, ]

Public Instance methods

[Source]

     # File lib/coderay/scanners/css.rb, line 52
 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

[Validate]