p_css 0.2.0.beta1-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +282 -0
- data/Cargo.toml +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +357 -0
- data/ext/css_native/Cargo.toml +12 -0
- data/ext/css_native/extconf.rb +4 -0
- data/ext/css_native/src/lib.rs +117 -0
- data/ext/css_native/src/matcher.rs +356 -0
- data/ext/css_native/src/selectors.rs +411 -0
- data/ext/css_native/src/snapshot.rs +370 -0
- data/ext/css_native/src/state.rs +174 -0
- data/ext/css_native/src/tokenizer.rs +596 -0
- data/lib/css/3.3/css_native.so +0 -0
- data/lib/css/3.4/css_native.so +0 -0
- data/lib/css/4.0/css_native.so +0 -0
- data/lib/css/cascade.rb +277 -0
- data/lib/css/code_points.rb +59 -0
- data/lib/css/escape.rb +82 -0
- data/lib/css/media_queries/context.rb +60 -0
- data/lib/css/media_queries/evaluator.rb +157 -0
- data/lib/css/media_queries/nodes.rb +41 -0
- data/lib/css/media_queries/parser.rb +374 -0
- data/lib/css/media_queries.rb +9 -0
- data/lib/css/native.rb +179 -0
- data/lib/css/nesting.rb +229 -0
- data/lib/css/nodes.rb +42 -0
- data/lib/css/parser.rb +429 -0
- data/lib/css/selectors/anb_parser.rb +174 -0
- data/lib/css/selectors/matcher.rb +545 -0
- data/lib/css/selectors/nodes.rb +61 -0
- data/lib/css/selectors/parser.rb +395 -0
- data/lib/css/selectors/serializer.rb +102 -0
- data/lib/css/selectors/specificity.rb +81 -0
- data/lib/css/selectors.rb +11 -0
- data/lib/css/serializer.rb +167 -0
- data/lib/css/token.rb +107 -0
- data/lib/css/token_cursor.rb +49 -0
- data/lib/css/tokenizer.rb +447 -0
- data/lib/css/urange.rb +45 -0
- data/lib/css/version.rb +3 -0
- data/lib/css.rb +73 -0
- data/lib/p_css.rb +1 -0
- data/sig/css/cascade.rbs +22 -0
- data/sig/css/media_queries.rbs +107 -0
- data/sig/css/nodes.rbs +76 -0
- data/sig/css/selectors.rbs +164 -0
- data/sig/css/token.rbs +33 -0
- data/sig/css.rbs +99 -0
- metadata +113 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
module CSS
|
|
2
|
+
module Selectors
|
|
3
|
+
# Parser for the An+B microsyntax used by `:nth-child(...)` and friends.
|
|
4
|
+
# https://drafts.csswg.org/css-syntax/#anb-microsyntax
|
|
5
|
+
module AnBParser
|
|
6
|
+
TRAILING_DASH_INT = /\A-(\d+)\z/.freeze
|
|
7
|
+
N_TRAILING_INT = /\An(-\d+)?\z/i.freeze
|
|
8
|
+
DASH_N_TRAILING = /\A-n(-\d+)?\z/i.freeze
|
|
9
|
+
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
def parse(input)
|
|
13
|
+
tokens = input.is_a?(String) ? Tokenizer.new(input).tokenize : input.to_a
|
|
14
|
+
Impl.new(tokens).parse
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class Impl
|
|
18
|
+
include CSS::TokenCursor
|
|
19
|
+
|
|
20
|
+
def initialize(tokens)
|
|
21
|
+
init_cursor(tokens)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def parse
|
|
25
|
+
skip_whitespace
|
|
26
|
+
|
|
27
|
+
result = parse_value
|
|
28
|
+
|
|
29
|
+
skip_whitespace
|
|
30
|
+
|
|
31
|
+
unless peek.type == :eof
|
|
32
|
+
raise ParseError, "trailing tokens in AnB: #{peek.type}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def parse_value
|
|
41
|
+
t = peek
|
|
42
|
+
|
|
43
|
+
case t.type
|
|
44
|
+
when :ident then parse_ident_form(t)
|
|
45
|
+
when :number then parse_pure_number(t)
|
|
46
|
+
when :dimension then parse_dimension_form(t)
|
|
47
|
+
when :delim then parse_signed_form(t)
|
|
48
|
+
else
|
|
49
|
+
raise ParseError, "expected An+B, got #{t.type}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parse_ident_form(t)
|
|
54
|
+
consume
|
|
55
|
+
|
|
56
|
+
case t.value.downcase
|
|
57
|
+
when 'even'
|
|
58
|
+
AnB.new(step: 2, offset: 0)
|
|
59
|
+
when 'odd'
|
|
60
|
+
AnB.new(step: 2, offset: 1)
|
|
61
|
+
when 'n'
|
|
62
|
+
parse_offset(step: 1)
|
|
63
|
+
when '-n'
|
|
64
|
+
parse_offset(step: -1)
|
|
65
|
+
when N_TRAILING_INT
|
|
66
|
+
AnB.new(step: 1, offset: -extract_dash_int(t.value, prefix: 'n'))
|
|
67
|
+
when DASH_N_TRAILING
|
|
68
|
+
AnB.new(step: -1, offset: -extract_dash_int(t.value, prefix: '-n'))
|
|
69
|
+
else
|
|
70
|
+
raise ParseError, "invalid AnB identifier: #{t.value}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def parse_pure_number(t)
|
|
75
|
+
consume
|
|
76
|
+
|
|
77
|
+
raise ParseError, 'AnB integer must be an integer' unless t.flag == :integer
|
|
78
|
+
|
|
79
|
+
AnB.new(step: 0, offset: t.value)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def parse_dimension_form(t)
|
|
83
|
+
consume
|
|
84
|
+
|
|
85
|
+
raise ParseError, 'AnB step coefficient must be an integer' unless t.flag == :integer
|
|
86
|
+
|
|
87
|
+
unit = t.unit.downcase
|
|
88
|
+
|
|
89
|
+
if unit == 'n'
|
|
90
|
+
parse_offset(step: t.value)
|
|
91
|
+
elsif unit.start_with?('n') && (m = TRAILING_DASH_INT.match(unit[1..]))
|
|
92
|
+
AnB.new(step: t.value, offset: -m[1].to_i)
|
|
93
|
+
else
|
|
94
|
+
raise ParseError, "invalid AnB dimension unit: #{unit}"
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# `+n`, `+n+1`, `+n-1`, `+n-3` (where `+n-3` lexes as delim '+' then
|
|
99
|
+
# ident "n-3"): consume the leading `+` and re-enter the ident path.
|
|
100
|
+
def parse_signed_form(t)
|
|
101
|
+
raise ParseError, "unexpected delim #{t.value}" unless t.value == '+'
|
|
102
|
+
|
|
103
|
+
consume
|
|
104
|
+
|
|
105
|
+
ident = peek
|
|
106
|
+
|
|
107
|
+
unless ident.type == :ident
|
|
108
|
+
raise ParseError, "expected ident after '+', got #{ident.type}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
consume
|
|
112
|
+
|
|
113
|
+
case ident.value.downcase
|
|
114
|
+
when 'n'
|
|
115
|
+
parse_offset(step: 1)
|
|
116
|
+
when N_TRAILING_INT
|
|
117
|
+
AnB.new(step: 1, offset: -extract_dash_int(ident.value, prefix: 'n'))
|
|
118
|
+
else
|
|
119
|
+
raise ParseError, "invalid AnB after '+': #{ident.value}"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def parse_offset(step:)
|
|
124
|
+
skip_whitespace
|
|
125
|
+
|
|
126
|
+
t = peek
|
|
127
|
+
|
|
128
|
+
case t.type
|
|
129
|
+
when :eof
|
|
130
|
+
AnB.new(step:, offset: 0)
|
|
131
|
+
when :number
|
|
132
|
+
consume
|
|
133
|
+
|
|
134
|
+
raise ParseError, 'AnB offset must be an integer' unless t.flag == :integer
|
|
135
|
+
|
|
136
|
+
AnB.new(step:, offset: t.value)
|
|
137
|
+
when :delim
|
|
138
|
+
unless t.value == '+' || t.value == '-'
|
|
139
|
+
raise ParseError, "expected +/- in AnB offset, got delim #{t.value}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
sign = t.value
|
|
143
|
+
consume
|
|
144
|
+
|
|
145
|
+
skip_whitespace
|
|
146
|
+
|
|
147
|
+
n = peek
|
|
148
|
+
|
|
149
|
+
unless n.type == :number && n.flag == :integer
|
|
150
|
+
raise ParseError, "expected integer after #{sign}"
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
consume
|
|
154
|
+
|
|
155
|
+
AnB.new(step:, offset: sign == '-' ? -n.value.abs : n.value.abs)
|
|
156
|
+
else
|
|
157
|
+
AnB.new(step:, offset: 0)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def extract_dash_int(s, prefix:)
|
|
162
|
+
rest = s.sub(/\A#{prefix}/i, '')
|
|
163
|
+
return 0 if rest.empty?
|
|
164
|
+
|
|
165
|
+
m = TRAILING_DASH_INT.match(rest)
|
|
166
|
+
|
|
167
|
+
raise ParseError, "invalid AnB suffix: #{s}" unless m
|
|
168
|
+
|
|
169
|
+
m[1].to_i
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|