1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
module CodeRay
module Scanners
class CSS2 < RuleBasedScanner
register_for :css2
KINDS_NOT_LOC = [
:comment,
:class, :pseudo_class, :tag,
:id, :directive,
:key, :value, :operator, :color, :float, :string,
:error, :important, :type,
] # :nodoc:
module RE # :nodoc:
Hex = /[0-9a-fA-F]/
Unicode = /\\#{Hex}{1,6}\b/ # differs from standard because it allows uppercase hex too
Escape = /#{Unicode}|\\[^\n0-9a-fA-F]/
NMChar = /[-_a-zA-Z0-9]/
NMStart = /[_a-zA-Z]/
String1 = /(")((?:[^\n\\"]+|\\\n|#{Escape})+)?(")?/ # TODO: buggy regexp
String2 = /(')((?:[^\n\\']+|\\\n|#{Escape})+)?(')?/ # TODO: buggy regexp
String = /#{String1}|#{String2}/
HexColor = /#(?:#{Hex}{6}|#{Hex}{3})/
Num = /-?(?:[0-9]*\.[0-9]+|[0-9]+)n?/
Name = /#{NMChar}+/
Ident = /-?#{NMStart}#{NMChar}*/
AtKeyword = /@#{Ident}/
Percentage = /#{Num}%/
reldimensions = %w[em ex px]
absdimensions = %w[in cm mm pt pc]
Unit = Regexp.union(*(reldimensions + absdimensions + %w[s dpi dppx deg]))
Dimension = /#{Num}#{Unit}/
Function = /((?:url|alpha|attr|counters?)\()((?:[^)\n]|\\\))+)?(\))?/
Id = /(?!#{HexColor}\b(?!-))##{Name}/
Class = /\.#{Name}/
PseudoClass = /::?#{Ident}/
AttributeSelector = /(\[)([^\]]+)?(\])?/
end
state :initial do
on %r/\s+/, :space
on check_if(:block), check_if(:value_expected), %r/(?>#{RE::Ident})(?!\()/x, :value
on check_if(:block), %r/(?>#{RE::Ident})(?!\()/x, :key
on check_unless(:block), %r/(?>#{RE::Ident})(?!\()|\*/x, :tag
on check_unless(:block), RE::Class, :class
on check_unless(:block), RE::Id, :id
on check_unless(:block), RE::PseudoClass, :pseudo_class
# TODO: Improve highlighting inside of attribute selectors.
on check_unless(:block), RE::AttributeSelector, groups(:operator, :attribute_name, :operator)
on check_unless(:block), %r/(@media)(\s+)?(#{RE::Ident})?(\s+)?(\{)?/, groups(:directive, :space, :type, :space, :operator)
on %r/\/\*(?:.*?\*\/|\z)/m, :comment
on %r/\{/, :operator, flag_off(:value_expected), flag_on(:block)
on %r/\}/, :operator, flag_off(:value_expected), flag_off(:block)
on RE::String1, push(:string), groups(:delimiter, :content, :delimiter), pop
on RE::String2, push(:string), groups(:delimiter, :content, :delimiter), pop
on RE::Function, push(:function), groups(:delimiter, :content, :delimiter), pop
on %r/(?: #{RE::Dimension} | #{RE::Percentage} | #{RE::Num} )/x, :float
on RE::HexColor, :color
on %r/! *important/, :important
on %r/(?:rgb|hsl)a?\([^()\n]*\)?/, :color
on RE::AtKeyword, :directive
on %r/:/, :operator, flag_on(:value_expected)
on %r/;/, :operator, flag_off(:value_expected)
on %r/ [+>~,.=()\/] /x, :operator
end
protected
def setup
super
@value_expected = false
@block = false
end
end
end
end
|