syntax_tree-css 0.1.0
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/.github/dependabot.yml +6 -0
- data/.github/workflows/main.yml +34 -0
- data/.gitignore +2 -0
- data/.gitmodules +3 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +36 -0
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/Rakefile +16 -0
- data/lib/syntax_tree/css/basic_visitor.rb +23 -0
- data/lib/syntax_tree/css/format.rb +14 -0
- data/lib/syntax_tree/css/nodes.rb +969 -0
- data/lib/syntax_tree/css/parser.rb +1188 -0
- data/lib/syntax_tree/css/pretty_print.rb +441 -0
- data/lib/syntax_tree/css/selectors.rb +519 -0
- data/lib/syntax_tree/css/version.rb +7 -0
- data/lib/syntax_tree/css/visitor.rb +154 -0
- data/lib/syntax_tree/css.rb +31 -0
- data/syntax_tree-css.gemspec +33 -0
- metadata +147 -0
@@ -0,0 +1,969 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SyntaxTree
|
4
|
+
module CSS
|
5
|
+
# This represents a location in the source file. It maps constructs like
|
6
|
+
# tokens and parse nodes to their original location.
|
7
|
+
class Location
|
8
|
+
attr_reader :start_char, :end_char
|
9
|
+
|
10
|
+
def initialize(start_char:, end_char:)
|
11
|
+
@start_char = start_char
|
12
|
+
@end_char = end_char
|
13
|
+
end
|
14
|
+
|
15
|
+
def to(other)
|
16
|
+
Location.new(start_char: start_char, end_char: other.end_char)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_range
|
20
|
+
start_char...end_char
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from(range)
|
24
|
+
Location.new(start_char: range.begin, end_char: range.end)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# A parent class for all of the various nodes in the tree. Provides common
|
29
|
+
# functionality between them.
|
30
|
+
class Node
|
31
|
+
def format(q)
|
32
|
+
Format.new(q).visit(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def pretty_print(q)
|
36
|
+
PrettyPrint.new(q).visit(self)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# A parsed token that is an identifier that starts with an @ sign.
|
41
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-at-keyword-token
|
42
|
+
class AtKeywordToken < Node
|
43
|
+
attr_reader :value, :location
|
44
|
+
|
45
|
+
def initialize(value:, location:)
|
46
|
+
@value = value
|
47
|
+
@location = Location.from(location)
|
48
|
+
end
|
49
|
+
|
50
|
+
def accept(visitor)
|
51
|
+
visitor.visit_at_keyword_token(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
def child_nodes
|
55
|
+
[]
|
56
|
+
end
|
57
|
+
|
58
|
+
alias deconstruct child_nodes
|
59
|
+
|
60
|
+
def deconstruct_keys(keys)
|
61
|
+
{ value: value, location: location }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# A rule that starts with an at-keyword and then accepts arbitrary tokens.
|
66
|
+
# A common example is an @media rule.
|
67
|
+
# https://www.w3.org/TR/css-syntax-3/#at-rule
|
68
|
+
class AtRule < Node
|
69
|
+
attr_reader :name, :prelude, :block, :location
|
70
|
+
|
71
|
+
def initialize(name:, prelude:, block:, location:)
|
72
|
+
@name = name
|
73
|
+
@prelude = prelude
|
74
|
+
@block = block
|
75
|
+
@location = location
|
76
|
+
end
|
77
|
+
|
78
|
+
def accept(visitor)
|
79
|
+
visitor.visit_at_rule(self)
|
80
|
+
end
|
81
|
+
|
82
|
+
def child_nodes
|
83
|
+
[*prelude, block].compact
|
84
|
+
end
|
85
|
+
|
86
|
+
alias deconstruct child_nodes
|
87
|
+
|
88
|
+
def deconstruct_keys(keys)
|
89
|
+
{ name: name, prelude: prelude, block: block, location: location }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# A parsed token that was a quotes string that had a syntax error. It is
|
94
|
+
# mostly here for error recovery.
|
95
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-bad-string-token
|
96
|
+
class BadStringToken < Node
|
97
|
+
attr_reader :value, :location
|
98
|
+
|
99
|
+
def initialize(value:, location:)
|
100
|
+
@value = value
|
101
|
+
@location = Location.from(location)
|
102
|
+
end
|
103
|
+
|
104
|
+
def accept(visitor)
|
105
|
+
visitor.visit_bad_string_token(self)
|
106
|
+
end
|
107
|
+
|
108
|
+
def child_nodes
|
109
|
+
[]
|
110
|
+
end
|
111
|
+
|
112
|
+
alias deconstruct child_nodes
|
113
|
+
|
114
|
+
def deconstruct_keys(keys)
|
115
|
+
{ value: value, location: location }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# A parsed token that was a call to "url" that had a syntax error. It is
|
120
|
+
# mostly here for error recovery.
|
121
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-bad-url-token
|
122
|
+
class BadURLToken < Node
|
123
|
+
attr_reader :value, :location
|
124
|
+
|
125
|
+
def initialize(value:, location:)
|
126
|
+
@value = value
|
127
|
+
@location = Location.from(location)
|
128
|
+
end
|
129
|
+
|
130
|
+
def accept(visitor)
|
131
|
+
visitor.visit_bad_url_token(self)
|
132
|
+
end
|
133
|
+
|
134
|
+
def child_nodes
|
135
|
+
[]
|
136
|
+
end
|
137
|
+
|
138
|
+
alias deconstruct child_nodes
|
139
|
+
|
140
|
+
def deconstruct_keys(keys)
|
141
|
+
{ value: value, location: location }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# A parsed token containing a CDC (-->).
|
146
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-cdc-token
|
147
|
+
class CDCToken < Node
|
148
|
+
attr_reader :location
|
149
|
+
|
150
|
+
def initialize(location:)
|
151
|
+
@location = Location.from(location)
|
152
|
+
end
|
153
|
+
|
154
|
+
def accept(visitor)
|
155
|
+
visitor.visit_cdc_token(self)
|
156
|
+
end
|
157
|
+
|
158
|
+
def child_nodes
|
159
|
+
[]
|
160
|
+
end
|
161
|
+
|
162
|
+
alias deconstruct child_nodes
|
163
|
+
|
164
|
+
def deconstruct_keys(keys)
|
165
|
+
{ location: location }
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# A parsed token containing a CDO (<!--).
|
170
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-cdo-token
|
171
|
+
class CDOToken < Node
|
172
|
+
attr_reader :location
|
173
|
+
|
174
|
+
def initialize(location:)
|
175
|
+
@location = Location.from(location)
|
176
|
+
end
|
177
|
+
|
178
|
+
def accept(visitor)
|
179
|
+
visitor.visit_cdo_token(self)
|
180
|
+
end
|
181
|
+
|
182
|
+
def child_nodes
|
183
|
+
[]
|
184
|
+
end
|
185
|
+
|
186
|
+
alias deconstruct child_nodes
|
187
|
+
|
188
|
+
def deconstruct_keys(keys)
|
189
|
+
{ location: location }
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# A parsed token that represents the use of a }.
|
194
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-close-curly
|
195
|
+
class CloseCurlyToken < Node
|
196
|
+
attr_reader :location
|
197
|
+
|
198
|
+
def initialize(location:)
|
199
|
+
@location = Location.from(location)
|
200
|
+
end
|
201
|
+
|
202
|
+
def accept(visitor)
|
203
|
+
visitor.visit_close_curly_token(self)
|
204
|
+
end
|
205
|
+
|
206
|
+
def child_nodes
|
207
|
+
[]
|
208
|
+
end
|
209
|
+
|
210
|
+
alias deconstruct child_nodes
|
211
|
+
|
212
|
+
def deconstruct_keys(keys)
|
213
|
+
{ location: location }
|
214
|
+
end
|
215
|
+
|
216
|
+
# Here for convenience for comparing between block types.
|
217
|
+
def value
|
218
|
+
"}"
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# A parsed token that represents the use of a ).
|
223
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-close-paren
|
224
|
+
class CloseParenToken < Node
|
225
|
+
attr_reader :location
|
226
|
+
|
227
|
+
def initialize(location:)
|
228
|
+
@location = Location.from(location)
|
229
|
+
end
|
230
|
+
|
231
|
+
def accept(visitor)
|
232
|
+
visitor.visit_close_paren_token(self)
|
233
|
+
end
|
234
|
+
|
235
|
+
def child_nodes
|
236
|
+
[]
|
237
|
+
end
|
238
|
+
|
239
|
+
alias deconstruct child_nodes
|
240
|
+
|
241
|
+
def deconstruct_keys(keys)
|
242
|
+
{ location: location }
|
243
|
+
end
|
244
|
+
|
245
|
+
# Here for convenience for comparing between block types.
|
246
|
+
def value
|
247
|
+
")"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# A parsed token that represents the use of a ].
|
252
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-close-square
|
253
|
+
class CloseSquareToken < Node
|
254
|
+
attr_reader :location
|
255
|
+
|
256
|
+
def initialize(location:)
|
257
|
+
@location = Location.from(location)
|
258
|
+
end
|
259
|
+
|
260
|
+
def accept(visitor)
|
261
|
+
visitor.visit_close_square_token(self)
|
262
|
+
end
|
263
|
+
|
264
|
+
def child_nodes
|
265
|
+
[]
|
266
|
+
end
|
267
|
+
|
268
|
+
alias deconstruct child_nodes
|
269
|
+
|
270
|
+
def deconstruct_keys(keys)
|
271
|
+
{ location: location }
|
272
|
+
end
|
273
|
+
|
274
|
+
# Here for convenience for comparing between block types.
|
275
|
+
def value
|
276
|
+
"]"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
# A parsed token containing a colon.
|
281
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-colon-token
|
282
|
+
class ColonToken < Node
|
283
|
+
attr_reader :location
|
284
|
+
|
285
|
+
def initialize(location:)
|
286
|
+
@location = Location.from(location)
|
287
|
+
end
|
288
|
+
|
289
|
+
def accept(visitor)
|
290
|
+
visitor.visit_colon_token(self)
|
291
|
+
end
|
292
|
+
|
293
|
+
def child_nodes
|
294
|
+
[]
|
295
|
+
end
|
296
|
+
|
297
|
+
alias deconstruct child_nodes
|
298
|
+
|
299
|
+
def deconstruct_keys(keys)
|
300
|
+
{ location: location }
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# A parsed token that contains a comma.
|
305
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-comma-token
|
306
|
+
class CommaToken < Node
|
307
|
+
attr_reader :location
|
308
|
+
|
309
|
+
def initialize(location:)
|
310
|
+
@location = Location.from(location)
|
311
|
+
end
|
312
|
+
|
313
|
+
def accept(visitor)
|
314
|
+
visitor.visit_comma_token(self)
|
315
|
+
end
|
316
|
+
|
317
|
+
def child_nodes
|
318
|
+
[]
|
319
|
+
end
|
320
|
+
|
321
|
+
alias deconstruct child_nodes
|
322
|
+
|
323
|
+
def deconstruct_keys(keys)
|
324
|
+
{ location: location }
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# A parsed token that contains a comment. These aren't actually declared in
|
329
|
+
# the spec because it assumes you can just drop them. We parse them into
|
330
|
+
# tokens, however, so that we can keep track of their location.
|
331
|
+
class CommentToken < Node
|
332
|
+
attr_reader :value, :location
|
333
|
+
|
334
|
+
def initialize(value:, location:)
|
335
|
+
@value = value
|
336
|
+
@location = Location.from(location)
|
337
|
+
end
|
338
|
+
|
339
|
+
def accept(visitor)
|
340
|
+
visitor.visit_comment_token(self)
|
341
|
+
end
|
342
|
+
|
343
|
+
def child_nodes
|
344
|
+
[]
|
345
|
+
end
|
346
|
+
|
347
|
+
alias deconstruct child_nodes
|
348
|
+
|
349
|
+
def deconstruct_keys(keys)
|
350
|
+
{ value: value, location: location }
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
# This is the top node in the tree if it has been converted into a CSS
|
355
|
+
# stylesheet.
|
356
|
+
class CSSStyleSheet < Node
|
357
|
+
attr_reader :rules, :location
|
358
|
+
|
359
|
+
def initialize(rules:, location:)
|
360
|
+
@rules = rules
|
361
|
+
@location = location
|
362
|
+
end
|
363
|
+
|
364
|
+
def accept(visitor)
|
365
|
+
visitor.visit_css_stylesheet(self)
|
366
|
+
end
|
367
|
+
|
368
|
+
def child_nodes
|
369
|
+
rules
|
370
|
+
end
|
371
|
+
|
372
|
+
alias deconstruct child_nodes
|
373
|
+
|
374
|
+
def deconstruct_keys(keys)
|
375
|
+
{ rules: rules, location: location }
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# Declarations are a particular instance of associating a property or
|
380
|
+
# descriptor name with a value.
|
381
|
+
# https://www.w3.org/TR/css-syntax-3/#declaration
|
382
|
+
class Declaration < Node
|
383
|
+
attr_reader :name, :value, :location
|
384
|
+
|
385
|
+
def initialize(name:, value:, important:, location:)
|
386
|
+
@name = name
|
387
|
+
@value = value
|
388
|
+
@important = important
|
389
|
+
@location = location
|
390
|
+
end
|
391
|
+
|
392
|
+
def accept(visitor)
|
393
|
+
visitor.visit_declaration(self)
|
394
|
+
end
|
395
|
+
|
396
|
+
def child_nodes
|
397
|
+
value
|
398
|
+
end
|
399
|
+
|
400
|
+
alias deconstruct child_nodes
|
401
|
+
|
402
|
+
def deconstruct_keys(keys)
|
403
|
+
{ name: name, value: value, important: important?, location: location }
|
404
|
+
end
|
405
|
+
|
406
|
+
def important?
|
407
|
+
@important
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
# A parsed token that has a value composed of a single code point.
|
412
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-delim-token
|
413
|
+
class DelimToken < Node
|
414
|
+
attr_reader :value, :location
|
415
|
+
|
416
|
+
def initialize(value:, location:)
|
417
|
+
@value = value
|
418
|
+
@location = Location.from(location)
|
419
|
+
end
|
420
|
+
|
421
|
+
def accept(visitor)
|
422
|
+
visitor.visit_delim_token(self)
|
423
|
+
end
|
424
|
+
|
425
|
+
def child_nodes
|
426
|
+
[]
|
427
|
+
end
|
428
|
+
|
429
|
+
alias deconstruct child_nodes
|
430
|
+
|
431
|
+
def deconstruct_keys(keys)
|
432
|
+
{ value: value, location: location }
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
# A parsed token that contains a numeric value with a dimension.
|
437
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-dimension-token
|
438
|
+
class DimensionToken < Node
|
439
|
+
attr_reader :value, :unit, :type, :location
|
440
|
+
|
441
|
+
def initialize(value:, unit:, type:, location:)
|
442
|
+
@value = value
|
443
|
+
@unit = unit
|
444
|
+
@type = type
|
445
|
+
@location = Location.from(location)
|
446
|
+
end
|
447
|
+
|
448
|
+
def accept(visitor)
|
449
|
+
visitor.visit_dimension_token(self)
|
450
|
+
end
|
451
|
+
|
452
|
+
def child_nodes
|
453
|
+
[]
|
454
|
+
end
|
455
|
+
|
456
|
+
alias deconstruct child_nodes
|
457
|
+
|
458
|
+
def deconstruct_keys(keys)
|
459
|
+
{ value: value, type: type, location: location }
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
# A conceptual token representing the end of the list of tokens. Whenever
|
464
|
+
# the list of tokens is empty, the next input token is always an EOFToken.
|
465
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-eof-token
|
466
|
+
class EOFToken < Node
|
467
|
+
attr_reader :location
|
468
|
+
|
469
|
+
def initialize(location:)
|
470
|
+
@location = Location.from(location)
|
471
|
+
end
|
472
|
+
|
473
|
+
def accept(visitor)
|
474
|
+
visitor.visit_eof_token(self)
|
475
|
+
end
|
476
|
+
|
477
|
+
def child_nodes
|
478
|
+
[]
|
479
|
+
end
|
480
|
+
|
481
|
+
alias deconstruct child_nodes
|
482
|
+
|
483
|
+
def deconstruct_keys(keys)
|
484
|
+
{ location: location }
|
485
|
+
end
|
486
|
+
|
487
|
+
# Since we create EOFToken objects a lot with ranges that are empty, it's
|
488
|
+
# nice to have this convenience method.
|
489
|
+
def self.[](index)
|
490
|
+
new(location: index...index)
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
# A function has a name and a value consisting of a list of component
|
495
|
+
# values.
|
496
|
+
# https://www.w3.org/TR/css-syntax-3/#function
|
497
|
+
class Function < Node
|
498
|
+
attr_reader :name, :value, :location
|
499
|
+
|
500
|
+
def initialize(name:, value:, location:)
|
501
|
+
@name = name
|
502
|
+
@value = value
|
503
|
+
@location = location
|
504
|
+
end
|
505
|
+
|
506
|
+
def accept(visitor)
|
507
|
+
visitor.visit_function(self)
|
508
|
+
end
|
509
|
+
|
510
|
+
def child_nodes
|
511
|
+
value
|
512
|
+
end
|
513
|
+
|
514
|
+
alias deconstruct child_nodes
|
515
|
+
|
516
|
+
def deconstruct_keys(keys)
|
517
|
+
{ name: name, value: value, location: location }
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
# A parsed token that contains the beginning of a call to a function, e.g.,
|
522
|
+
# "url(".
|
523
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-function-token
|
524
|
+
class FunctionToken < Node
|
525
|
+
attr_reader :value, :location
|
526
|
+
|
527
|
+
def initialize(value:, location:)
|
528
|
+
@value = value
|
529
|
+
@location = Location.from(location)
|
530
|
+
end
|
531
|
+
|
532
|
+
def accept(visitor)
|
533
|
+
visitor.visit_function_token(self)
|
534
|
+
end
|
535
|
+
|
536
|
+
def child_nodes
|
537
|
+
[]
|
538
|
+
end
|
539
|
+
|
540
|
+
alias deconstruct child_nodes
|
541
|
+
|
542
|
+
def deconstruct_keys(keys)
|
543
|
+
{ value: value, location: location }
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
# A parsed token that contains an identifier that starts with a # sign.
|
548
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-hash-token
|
549
|
+
class HashToken < Node
|
550
|
+
attr_reader :value, :type, :location
|
551
|
+
|
552
|
+
def initialize(value:, type:, location:)
|
553
|
+
@value = value
|
554
|
+
@type = type
|
555
|
+
@location = Location.from(location)
|
556
|
+
end
|
557
|
+
|
558
|
+
def accept(visitor)
|
559
|
+
visitor.visit_hash_token(self)
|
560
|
+
end
|
561
|
+
|
562
|
+
def child_nodes
|
563
|
+
[]
|
564
|
+
end
|
565
|
+
|
566
|
+
alias deconstruct child_nodes
|
567
|
+
|
568
|
+
def deconstruct_keys(keys)
|
569
|
+
{ value: value, type: type, location: location }
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
# A parsed token that contains an plaintext identifier.
|
574
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-ident-token
|
575
|
+
class IdentToken < Node
|
576
|
+
attr_reader :value, :location
|
577
|
+
|
578
|
+
def initialize(value:, location:)
|
579
|
+
@value = value
|
580
|
+
@location = Location.from(location)
|
581
|
+
end
|
582
|
+
|
583
|
+
def accept(visitor)
|
584
|
+
visitor.visit_ident_token(self)
|
585
|
+
end
|
586
|
+
|
587
|
+
def child_nodes
|
588
|
+
[]
|
589
|
+
end
|
590
|
+
|
591
|
+
alias deconstruct child_nodes
|
592
|
+
|
593
|
+
def deconstruct_keys(keys)
|
594
|
+
{ value: value, location: location }
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
# A parsed token that contains a numeric value.
|
599
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-number-token
|
600
|
+
class NumberToken < Node
|
601
|
+
attr_reader :value, :type, :location
|
602
|
+
|
603
|
+
def initialize(value:, type:, location:)
|
604
|
+
@value = value
|
605
|
+
@type = type
|
606
|
+
@location = Location.from(location)
|
607
|
+
end
|
608
|
+
|
609
|
+
def accept(visitor)
|
610
|
+
visitor.visit_number_token(self)
|
611
|
+
end
|
612
|
+
|
613
|
+
def child_nodes
|
614
|
+
[]
|
615
|
+
end
|
616
|
+
|
617
|
+
alias deconstruct child_nodes
|
618
|
+
|
619
|
+
def deconstruct_keys(keys)
|
620
|
+
{ value: value, type: type, location: location }
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
# A parsed token that represents the use of a {.
|
625
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-open-curly
|
626
|
+
class OpenCurlyToken < Node
|
627
|
+
attr_reader :location
|
628
|
+
|
629
|
+
def initialize(location:)
|
630
|
+
@location = Location.from(location)
|
631
|
+
end
|
632
|
+
|
633
|
+
def accept(visitor)
|
634
|
+
visitor.visit_open_curly_token(self)
|
635
|
+
end
|
636
|
+
|
637
|
+
def child_nodes
|
638
|
+
[]
|
639
|
+
end
|
640
|
+
|
641
|
+
alias deconstruct child_nodes
|
642
|
+
|
643
|
+
def deconstruct_keys(keys)
|
644
|
+
{ location: location }
|
645
|
+
end
|
646
|
+
|
647
|
+
# Here for convenience for comparing between block types.
|
648
|
+
def value
|
649
|
+
"{"
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
653
|
+
# A parsed token that represents the use of a (.
|
654
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-open-paren
|
655
|
+
class OpenParenToken < Node
|
656
|
+
attr_reader :location
|
657
|
+
|
658
|
+
def initialize(location:)
|
659
|
+
@location = Location.from(location)
|
660
|
+
end
|
661
|
+
|
662
|
+
def accept(visitor)
|
663
|
+
visitor.visit_open_paren_token(self)
|
664
|
+
end
|
665
|
+
|
666
|
+
def child_nodes
|
667
|
+
[]
|
668
|
+
end
|
669
|
+
|
670
|
+
alias deconstruct child_nodes
|
671
|
+
|
672
|
+
def deconstruct_keys(keys)
|
673
|
+
{ location: location }
|
674
|
+
end
|
675
|
+
|
676
|
+
# Here for convenience for comparing between block types.
|
677
|
+
def value
|
678
|
+
"("
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
# A parsed token that represents the use of a [.
|
683
|
+
# https://www.w3.org/TR/css-syntax-3/#tokendef-open-square
|
684
|
+
class OpenSquareToken < Node
|
685
|
+
attr_reader :location
|
686
|
+
|
687
|
+
def initialize(location:)
|
688
|
+
@location = Location.from(location)
|
689
|
+
end
|
690
|
+
|
691
|
+
def accept(visitor)
|
692
|
+
visitor.visit_open_square_token(self)
|
693
|
+
end
|
694
|
+
|
695
|
+
def child_nodes
|
696
|
+
[]
|
697
|
+
end
|
698
|
+
|
699
|
+
alias deconstruct child_nodes
|
700
|
+
|
701
|
+
def deconstruct_keys(keys)
|
702
|
+
{ location: location }
|
703
|
+
end
|
704
|
+
|
705
|
+
# Here for convenience for comparing between block types.
|
706
|
+
def value
|
707
|
+
"["
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
# A parsed token that contains a numeric value with a percentage sign.
|
712
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-percentage-token
|
713
|
+
class PercentageToken < Node
|
714
|
+
attr_reader :value, :type, :location
|
715
|
+
|
716
|
+
def initialize(value:, type:, location:)
|
717
|
+
@value = value
|
718
|
+
@type = type
|
719
|
+
@location = Location.from(location)
|
720
|
+
end
|
721
|
+
|
722
|
+
def accept(visitor)
|
723
|
+
visitor.visit_percentage_token(self)
|
724
|
+
end
|
725
|
+
|
726
|
+
def child_nodes
|
727
|
+
[]
|
728
|
+
end
|
729
|
+
|
730
|
+
alias deconstruct child_nodes
|
731
|
+
|
732
|
+
def deconstruct_keys(keys)
|
733
|
+
{ value: value, type: type, location: location }
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
# Associates a prelude consisting of a list of component values with a block
|
738
|
+
# consisting of a simple {} block.
|
739
|
+
# https://www.w3.org/TR/css-syntax-3/#qualified-rule
|
740
|
+
class QualifiedRule < Node
|
741
|
+
attr_reader :prelude, :block, :location
|
742
|
+
|
743
|
+
def initialize(prelude:, block:, location:)
|
744
|
+
@prelude = prelude
|
745
|
+
@block = block
|
746
|
+
@location = location
|
747
|
+
end
|
748
|
+
|
749
|
+
def accept(visitor)
|
750
|
+
visitor.visit_qualified_rule(self)
|
751
|
+
end
|
752
|
+
|
753
|
+
def child_nodes
|
754
|
+
[*prelude, block].compact
|
755
|
+
end
|
756
|
+
|
757
|
+
alias deconstruct child_nodes
|
758
|
+
|
759
|
+
def deconstruct_keys(keys)
|
760
|
+
{ prelude: prelude, block: block, location: location }
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
# A parsed token that contains a comma.
|
765
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-semicolon-token
|
766
|
+
class SemicolonToken < Node
|
767
|
+
attr_reader :location
|
768
|
+
|
769
|
+
def initialize(location:)
|
770
|
+
@location = Location.from(location)
|
771
|
+
end
|
772
|
+
|
773
|
+
def accept(visitor)
|
774
|
+
visitor.visit_semicolon_token(self)
|
775
|
+
end
|
776
|
+
|
777
|
+
def child_nodes
|
778
|
+
[]
|
779
|
+
end
|
780
|
+
|
781
|
+
alias deconstruct child_nodes
|
782
|
+
|
783
|
+
def deconstruct_keys(keys)
|
784
|
+
{ location: location }
|
785
|
+
end
|
786
|
+
end
|
787
|
+
|
788
|
+
# A simple block has an associated token (either a <[-token>, <(-token>, or
|
789
|
+
# <{-token>) and a value consisting of a list of component values.
|
790
|
+
# https://www.w3.org/TR/css-syntax-3/#simple-block
|
791
|
+
class SimpleBlock < Node
|
792
|
+
attr_reader :token, :value, :location
|
793
|
+
|
794
|
+
def initialize(token:, value:, location:)
|
795
|
+
@token = token
|
796
|
+
@value = value
|
797
|
+
@location = location
|
798
|
+
end
|
799
|
+
|
800
|
+
def accept(visitor)
|
801
|
+
visitor.visit_simple_block(self)
|
802
|
+
end
|
803
|
+
|
804
|
+
def child_nodes
|
805
|
+
value
|
806
|
+
end
|
807
|
+
|
808
|
+
alias deconstruct child_nodes
|
809
|
+
|
810
|
+
def deconstruct_keys(keys)
|
811
|
+
{ token: token, value: value, location: location }
|
812
|
+
end
|
813
|
+
end
|
814
|
+
|
815
|
+
# A parsed token that contains a quoted string.
|
816
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-string-token
|
817
|
+
class StringToken < Node
|
818
|
+
attr_reader :value, :location
|
819
|
+
|
820
|
+
def initialize(value:, location:)
|
821
|
+
@value = value
|
822
|
+
@location = Location.from(location)
|
823
|
+
end
|
824
|
+
|
825
|
+
def accept(visitor)
|
826
|
+
visitor.visit_string_token(self)
|
827
|
+
end
|
828
|
+
|
829
|
+
def child_nodes
|
830
|
+
[]
|
831
|
+
end
|
832
|
+
|
833
|
+
alias deconstruct child_nodes
|
834
|
+
|
835
|
+
def deconstruct_keys(keys)
|
836
|
+
{ value: value, location: location }
|
837
|
+
end
|
838
|
+
end
|
839
|
+
|
840
|
+
# A style rule is a qualified rule that associates a selector list with a
|
841
|
+
# list of property declarations and possibly a list of nested rules.
|
842
|
+
# https://www.w3.org/TR/css-syntax-3/#style-rule
|
843
|
+
class StyleRule < Node
|
844
|
+
attr_reader :selectors, :declarations, :location
|
845
|
+
|
846
|
+
def initialize(selectors:, declarations:, location:)
|
847
|
+
@selectors = selectors
|
848
|
+
@declarations = declarations
|
849
|
+
@location = location
|
850
|
+
end
|
851
|
+
|
852
|
+
def accept(visitor)
|
853
|
+
visitor.visit_style_rule(self)
|
854
|
+
end
|
855
|
+
|
856
|
+
def child_nodes
|
857
|
+
[*selectors, *declarations]
|
858
|
+
end
|
859
|
+
|
860
|
+
alias deconstruct child_nodes
|
861
|
+
|
862
|
+
def deconstruct_keys(keys)
|
863
|
+
{ selectors: selectors, declarations: declarations, location: location }
|
864
|
+
end
|
865
|
+
end
|
866
|
+
|
867
|
+
# This is the top node in the tree if it hasn't been converted into a CSS
|
868
|
+
# stylesheet.
|
869
|
+
class StyleSheet < Node
|
870
|
+
attr_reader :rules, :location
|
871
|
+
|
872
|
+
def initialize(rules:, location:)
|
873
|
+
@rules = rules
|
874
|
+
@location = location
|
875
|
+
end
|
876
|
+
|
877
|
+
def accept(visitor)
|
878
|
+
visitor.visit_stylesheet(self)
|
879
|
+
end
|
880
|
+
|
881
|
+
def child_nodes
|
882
|
+
rules
|
883
|
+
end
|
884
|
+
|
885
|
+
alias deconstruct child_nodes
|
886
|
+
|
887
|
+
def deconstruct_keys(keys)
|
888
|
+
{ rules: rules, location: location }
|
889
|
+
end
|
890
|
+
end
|
891
|
+
|
892
|
+
# This node represents the use of the urange micro syntax, e.g. U+1F601.
|
893
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-urange
|
894
|
+
class URange < Node
|
895
|
+
attr_reader :start_value, :end_value, :location
|
896
|
+
|
897
|
+
def initialize(start_value:, end_value:, location:)
|
898
|
+
@start_value = start_value
|
899
|
+
@end_value = end_value
|
900
|
+
@location = location
|
901
|
+
end
|
902
|
+
|
903
|
+
def accept(visitor)
|
904
|
+
visitor.visit_urange(self)
|
905
|
+
end
|
906
|
+
|
907
|
+
def child_nodes
|
908
|
+
[]
|
909
|
+
end
|
910
|
+
|
911
|
+
alias deconstruct child_nodes
|
912
|
+
|
913
|
+
def deconstruct_keys(keys)
|
914
|
+
{ start_value: start_value, end_value: end_value, location: location }
|
915
|
+
end
|
916
|
+
end
|
917
|
+
|
918
|
+
# A parsed token that contains a URL. Note that this is different from a
|
919
|
+
# function call to the "url" function only if quotes aren't used.
|
920
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-url-token
|
921
|
+
class URLToken < Node
|
922
|
+
attr_reader :value, :location
|
923
|
+
|
924
|
+
def initialize(value:, location:)
|
925
|
+
@value = value
|
926
|
+
@location = Location.from(location)
|
927
|
+
end
|
928
|
+
|
929
|
+
def accept(visitor)
|
930
|
+
visitor.visit_url_token(self)
|
931
|
+
end
|
932
|
+
|
933
|
+
def child_nodes
|
934
|
+
[]
|
935
|
+
end
|
936
|
+
|
937
|
+
alias deconstruct child_nodes
|
938
|
+
|
939
|
+
def deconstruct_keys(keys)
|
940
|
+
{ value: value, location: location }
|
941
|
+
end
|
942
|
+
end
|
943
|
+
|
944
|
+
# A parsed token that contains only whitespace.
|
945
|
+
# https://www.w3.org/TR/css-syntax-3/#typedef-whitespace-token
|
946
|
+
class WhitespaceToken < Node
|
947
|
+
attr_reader :value, :location
|
948
|
+
|
949
|
+
def initialize(value:, location:)
|
950
|
+
@value = value
|
951
|
+
@location = Location.from(location)
|
952
|
+
end
|
953
|
+
|
954
|
+
def accept(visitor)
|
955
|
+
visitor.visit_whitespace_token(self)
|
956
|
+
end
|
957
|
+
|
958
|
+
def child_nodes
|
959
|
+
[]
|
960
|
+
end
|
961
|
+
|
962
|
+
alias deconstruct child_nodes
|
963
|
+
|
964
|
+
def deconstruct_keys(keys)
|
965
|
+
{ value: value, location: location }
|
966
|
+
end
|
967
|
+
end
|
968
|
+
end
|
969
|
+
end
|