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,441 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SyntaxTree
|
4
|
+
module CSS
|
5
|
+
# A pretty-print visitor.
|
6
|
+
class PrettyPrint < BasicVisitor
|
7
|
+
attr_reader :q
|
8
|
+
|
9
|
+
def initialize(q)
|
10
|
+
@q = q
|
11
|
+
end
|
12
|
+
|
13
|
+
#-------------------------------------------------------------------------
|
14
|
+
# CSS3 nodes
|
15
|
+
#-------------------------------------------------------------------------
|
16
|
+
|
17
|
+
# Visit an AtKeywordToken node.
|
18
|
+
def visit_at_keyword_token(node)
|
19
|
+
token("at-keyword-token") do
|
20
|
+
q.breakable
|
21
|
+
q.pp(node.value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Visit an AtRule node.
|
26
|
+
def visit_at_rule(node)
|
27
|
+
token("at-rule") do
|
28
|
+
q.breakable
|
29
|
+
q.pp(node.name)
|
30
|
+
|
31
|
+
q.breakable
|
32
|
+
q.text("(prelude")
|
33
|
+
q.nest(2) do
|
34
|
+
q.breakable("")
|
35
|
+
q.seplist(node.prelude) { |token| q.pp(token) }
|
36
|
+
end
|
37
|
+
|
38
|
+
q.breakable("")
|
39
|
+
q.text(")")
|
40
|
+
|
41
|
+
q.breakable
|
42
|
+
q.pp(node.block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Visit a BadStringToken node.
|
47
|
+
def visit_bad_string_token(node)
|
48
|
+
token("bad-string-token") do
|
49
|
+
q.breakable
|
50
|
+
q.pp(node.value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Visit a BadURLToken node.
|
55
|
+
def visit_bad_url_token(node)
|
56
|
+
token("bad-url-token") do
|
57
|
+
q.breakable
|
58
|
+
q.pp(node.value)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Visit a CDCToken node.
|
63
|
+
def visit_cdc_token(node)
|
64
|
+
token("cdc-token")
|
65
|
+
end
|
66
|
+
|
67
|
+
# Visit a CDOToken node.
|
68
|
+
def visit_cdo_token(node)
|
69
|
+
token("cdo-token")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Visit a CloseCurlyToken node.
|
73
|
+
def visit_close_curly_token(node)
|
74
|
+
token("close-curly-token")
|
75
|
+
end
|
76
|
+
|
77
|
+
# Visit a CloseParenToken node.
|
78
|
+
def visit_close_paren_token(node)
|
79
|
+
token("close-paren-token")
|
80
|
+
end
|
81
|
+
|
82
|
+
# Visit a CloseSquareToken node.
|
83
|
+
def visit_close_square_token(node)
|
84
|
+
token("close-square-token")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Visit a ColonToken node.
|
88
|
+
def visit_colon_token(node)
|
89
|
+
token("colon-token")
|
90
|
+
end
|
91
|
+
|
92
|
+
# Visit a CommentToken node.
|
93
|
+
def visit_comment_token(node)
|
94
|
+
token("comment-token") do
|
95
|
+
q.breakable
|
96
|
+
q.pp(node.value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Visit a CommaToken node.
|
101
|
+
def visit_comma_token(node)
|
102
|
+
token("comma-token")
|
103
|
+
end
|
104
|
+
|
105
|
+
# Visit a CSSStyleSheet node.
|
106
|
+
def visit_css_stylesheet(node)
|
107
|
+
token("css-stylesheet") do
|
108
|
+
if node.rules.any?
|
109
|
+
q.breakable
|
110
|
+
q.seplist(node.rules) { |rule| q.pp(rule) }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Visit a Declaration node.
|
116
|
+
def visit_declaration(node)
|
117
|
+
token("declaration") do
|
118
|
+
q.breakable
|
119
|
+
q.text(node.name)
|
120
|
+
|
121
|
+
if node.important?
|
122
|
+
q.breakable
|
123
|
+
q.text("!important")
|
124
|
+
end
|
125
|
+
|
126
|
+
q.breakable
|
127
|
+
q.seplist(node.value) { |token| q.pp(token) }
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Visit a DelimToken node.
|
132
|
+
def visit_delim_token(node)
|
133
|
+
token("delim-token") do
|
134
|
+
q.breakable
|
135
|
+
q.pp(node.value)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Visit a DimensionToken node.
|
140
|
+
def visit_dimension_token(node)
|
141
|
+
token("dimension-token") do
|
142
|
+
q.breakable
|
143
|
+
q.text(node.type)
|
144
|
+
|
145
|
+
q.breakable
|
146
|
+
q.pp(node.value)
|
147
|
+
|
148
|
+
q.breakable
|
149
|
+
q.text(node.unit)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Visit an EOFToken node.
|
154
|
+
def visit_eof_token(node)
|
155
|
+
token("eof-token")
|
156
|
+
end
|
157
|
+
|
158
|
+
# Visit a Function node.
|
159
|
+
def visit_function(node)
|
160
|
+
token("function") do
|
161
|
+
q.breakable
|
162
|
+
q.text(node.name)
|
163
|
+
|
164
|
+
q.breakable
|
165
|
+
q.text("(value")
|
166
|
+
q.nest(2) do
|
167
|
+
q.breakable
|
168
|
+
q.seplist(node.value) { |token| q.pp(token) }
|
169
|
+
end
|
170
|
+
|
171
|
+
q.breakable("")
|
172
|
+
q.text(")")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Visit a FunctionToken node.
|
177
|
+
def visit_function_token(node)
|
178
|
+
token("function-token") do
|
179
|
+
q.breakable
|
180
|
+
q.pp(node.value)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Visit an IdentToken node.
|
185
|
+
def visit_ident_token(node)
|
186
|
+
token("ident-token") do
|
187
|
+
q.breakable
|
188
|
+
q.pp(node.value)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# Visit a HashToken node.
|
193
|
+
def visit_hash_token(node)
|
194
|
+
token("hash-token") do
|
195
|
+
q.breakable
|
196
|
+
q.pp(node.value)
|
197
|
+
|
198
|
+
q.breakable
|
199
|
+
q.text(node.type)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Visit a NumberToken node.
|
204
|
+
def visit_number_token(node)
|
205
|
+
token("number-token") do
|
206
|
+
q.breakable
|
207
|
+
q.text(node.type)
|
208
|
+
|
209
|
+
q.breakable
|
210
|
+
q.pp(node.value)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Visit an OpenCurlyToken node.
|
215
|
+
def visit_open_curly_token(node)
|
216
|
+
token("open-curly-token")
|
217
|
+
end
|
218
|
+
|
219
|
+
# Visit an OpenParenToken node.
|
220
|
+
def visit_open_paren_token(node)
|
221
|
+
token("open-paren-token")
|
222
|
+
end
|
223
|
+
|
224
|
+
# Visit an OpenSquareToken node.
|
225
|
+
def visit_open_square_token(node)
|
226
|
+
token("open-square-token")
|
227
|
+
end
|
228
|
+
|
229
|
+
# Visit a PercentageToken node.
|
230
|
+
def visit_percentage_token(node)
|
231
|
+
token("percentage-token") do
|
232
|
+
q.breakable
|
233
|
+
q.text(node.type)
|
234
|
+
|
235
|
+
q.breakable
|
236
|
+
q.pp(node.value)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
# Visit a QualifiedRule node.
|
241
|
+
def visit_qualified_rule(node)
|
242
|
+
token("qualified-rule") do
|
243
|
+
q.breakable
|
244
|
+
q.text("(prelude")
|
245
|
+
q.nest(2) do
|
246
|
+
q.breakable("")
|
247
|
+
q.seplist(node.prelude) { |token| q.pp(token) }
|
248
|
+
end
|
249
|
+
|
250
|
+
q.breakable("")
|
251
|
+
q.text(")")
|
252
|
+
|
253
|
+
q.breakable
|
254
|
+
q.pp(node.block)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# Visit a SemicolonToken node.
|
259
|
+
def visit_semicolon_token(node)
|
260
|
+
token("semicolon-token")
|
261
|
+
end
|
262
|
+
|
263
|
+
# Visit a SimpleBlock node.
|
264
|
+
def visit_simple_block(node)
|
265
|
+
token("simple-block") do
|
266
|
+
q.breakable
|
267
|
+
q.pp(node.token)
|
268
|
+
|
269
|
+
if node.value.any?
|
270
|
+
q.breakable
|
271
|
+
q.seplist(node.value) { |val| q.pp(val) }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
# Visit a StringToken node.
|
277
|
+
def visit_string_token(node)
|
278
|
+
token("string-token") do
|
279
|
+
q.breakable
|
280
|
+
q.pp(node.value)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
# Visit a StyleRule node.
|
285
|
+
def visit_style_rule(node)
|
286
|
+
token("style-rule") do
|
287
|
+
q.breakable
|
288
|
+
q.text("(selectors")
|
289
|
+
q.nest(2) do
|
290
|
+
q.breakable
|
291
|
+
q.seplist(node.selectors) { |token| q.pp(token) }
|
292
|
+
end
|
293
|
+
|
294
|
+
q.breakable("")
|
295
|
+
q.text(")")
|
296
|
+
|
297
|
+
q.breakable
|
298
|
+
q.text("(declarations")
|
299
|
+
|
300
|
+
if node.declarations.any?
|
301
|
+
q.nest(2) do
|
302
|
+
q.breakable
|
303
|
+
q.seplist(node.declarations) { |token| q.pp(token) }
|
304
|
+
end
|
305
|
+
|
306
|
+
q.breakable("")
|
307
|
+
end
|
308
|
+
|
309
|
+
q.text(")")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Visit a StyleSheet node.
|
314
|
+
def visit_stylesheet(node)
|
315
|
+
token("stylesheet") do
|
316
|
+
if node.rules.any?
|
317
|
+
q.breakable
|
318
|
+
q.seplist(node.rules) { |rule| q.pp(rule) }
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Visit a URange node.
|
324
|
+
def visit_urange(node)
|
325
|
+
token("urange") do
|
326
|
+
q.breakable
|
327
|
+
q.pp(node.start_value)
|
328
|
+
q.text("-")
|
329
|
+
q.pp(node.end_value)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
# Visit a URLToken node.
|
334
|
+
def visit_url_token(node)
|
335
|
+
token("url-token") do
|
336
|
+
q.breakable
|
337
|
+
q.pp(node.value)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# Visit a WhitespaceToken node.
|
342
|
+
def visit_whitespace_token(node)
|
343
|
+
token("whitespace-token") do
|
344
|
+
q.breakable
|
345
|
+
q.pp(node.value)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
#-------------------------------------------------------------------------
|
350
|
+
# Selector nodes
|
351
|
+
#-------------------------------------------------------------------------
|
352
|
+
|
353
|
+
# Visit a Selectors::ClassSelector node.
|
354
|
+
def visit_class_selector(node)
|
355
|
+
token("class-selector") do
|
356
|
+
q.breakable
|
357
|
+
q.pp(node.value)
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
# Visit a Selectors::IdSelector node.
|
362
|
+
def visit_id_selector(node)
|
363
|
+
token("id-selector") do
|
364
|
+
q.breakable
|
365
|
+
q.pp(node.value)
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# Visit a Selectors::PseudoClassSelector node.
|
370
|
+
def visit_pseudo_class_selector(node)
|
371
|
+
token("pseudo-class-selector") do
|
372
|
+
q.breakable
|
373
|
+
q.pp(node.value)
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
# Visit a Selectors::PseudoClassFunction node.
|
378
|
+
def visit_pseudo_class_function(node)
|
379
|
+
token("pseudo-class-function") do
|
380
|
+
q.breakable
|
381
|
+
q.pp(node.name)
|
382
|
+
|
383
|
+
if node.arguments.any?
|
384
|
+
q.breakable
|
385
|
+
q.seplist(node.arguments) { |argument| q.pp(argument) }
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
# Visit a Selectors::PseudoElementSelector node.
|
391
|
+
def visit_pseudo_element_selector(node)
|
392
|
+
token("pseudo-element-selector") do
|
393
|
+
q.breakable
|
394
|
+
q.pp(node.value)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
# Visit a Selectors::TypeSelector node.
|
399
|
+
def visit_type_selector(node)
|
400
|
+
token("type-selector") do
|
401
|
+
if node.prefix
|
402
|
+
q.breakable
|
403
|
+
q.pp(node.prefix)
|
404
|
+
end
|
405
|
+
|
406
|
+
q.breakable
|
407
|
+
q.pp(node.value)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
# Visit a Selectors::WqName node.
|
412
|
+
def visit_wqname(node)
|
413
|
+
token("wqname") do
|
414
|
+
if node.prefix
|
415
|
+
q.breakable
|
416
|
+
q.pp(node.prefix)
|
417
|
+
end
|
418
|
+
|
419
|
+
q.breakable
|
420
|
+
q.pp(node.name)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
private
|
425
|
+
|
426
|
+
def token(name)
|
427
|
+
q.group do
|
428
|
+
q.text("(")
|
429
|
+
q.text(name)
|
430
|
+
|
431
|
+
if block_given?
|
432
|
+
q.nest(2) { yield }
|
433
|
+
q.breakable("")
|
434
|
+
end
|
435
|
+
|
436
|
+
q.text(")")
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
end
|