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.
@@ -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