syntax_tree-haml 1.2.0 → 1.2.1
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 +4 -4
- data/.github/workflows/main.yml +3 -1
- data/CHANGELOG.md +8 -1
- data/Gemfile.lock +3 -3
- data/Rakefile +7 -0
- data/lib/syntax_tree/haml/format.rb +425 -0
- data/lib/syntax_tree/haml/pretty_print.rb +158 -0
- data/lib/syntax_tree/haml/version.rb +1 -1
- data/lib/syntax_tree/haml.rb +60 -52
- data/syntax_tree-haml.gemspec +14 -14
- metadata +4 -11
- data/lib/syntax_tree/haml/comment.rb +0 -52
- data/lib/syntax_tree/haml/doctype.rb +0 -64
- data/lib/syntax_tree/haml/filter.rb +0 -42
- data/lib/syntax_tree/haml/haml_comment.rb +0 -38
- data/lib/syntax_tree/haml/plain.rb +0 -40
- data/lib/syntax_tree/haml/root.rb +0 -30
- data/lib/syntax_tree/haml/script.rb +0 -53
- data/lib/syntax_tree/haml/silent_script.rb +0 -62
- data/lib/syntax_tree/haml/tag.rb +0 -306
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ec66452fbab00bf664cbd1d86b9b351a039eb99ac70547dc2defd72003122da
|
4
|
+
data.tar.gz: 5e643711d3d79a8e7c37bc6f17afbb9d855eab2fbf7992f348014cd14ead9490
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a55f022617f25d7898f92ebdcca872cd3920e2177144dc63caa117a8a12bf4c15ee9ec9ad5dedd65312b64191fdf40725b6e83bf1733066e6055901bc374699
|
7
|
+
data.tar.gz: b06d3310d759f3b11fda480172d66253edc1843740f59aef360a7ca5e7d2130d171ee27d272e73a52038ac50b7f1345dcb0a8a4c89a85c3f4a98914a73aee1c9
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.2.1] - 2022-07-22
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- Fix formatting for when empty `%div` or `%div` with no attributes and just children is present.
|
14
|
+
|
9
15
|
## [1.2.0] - 2022-05-13
|
10
16
|
|
11
17
|
### Added
|
@@ -36,7 +42,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
36
42
|
|
37
43
|
- 🎉 Initial release! 🎉
|
38
44
|
|
39
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.2.
|
45
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.2.1...HEAD
|
46
|
+
[1.2.1]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.2.0...v1.2.1
|
40
47
|
[1.2.0]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.1.0...v1.2.0
|
41
48
|
[1.1.0]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.0.1...v1.1.0
|
42
49
|
[1.0.1]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.0.0...v1.0.1
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
syntax_tree-haml (1.2.
|
4
|
+
syntax_tree-haml (1.2.1)
|
5
5
|
haml (>= 5.2)
|
6
6
|
prettier_print
|
7
7
|
syntax_tree (>= 2.0.1)
|
@@ -13,7 +13,7 @@ GEM
|
|
13
13
|
haml (5.2.2)
|
14
14
|
temple (>= 0.8.0)
|
15
15
|
tilt
|
16
|
-
minitest (5.
|
16
|
+
minitest (5.16.2)
|
17
17
|
prettier_print (0.1.0)
|
18
18
|
rake (13.0.6)
|
19
19
|
simplecov (0.21.2)
|
@@ -22,7 +22,7 @@ GEM
|
|
22
22
|
simplecov_json_formatter (~> 0.1)
|
23
23
|
simplecov-html (0.12.3)
|
24
24
|
simplecov_json_formatter (0.1.4)
|
25
|
-
syntax_tree (2.
|
25
|
+
syntax_tree (3.2.0)
|
26
26
|
prettier_print
|
27
27
|
temple (0.8.2)
|
28
28
|
tilt (2.0.10)
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rake/testtask"
|
5
|
+
require "syntax_tree/rake_tasks"
|
5
6
|
|
6
7
|
Rake::TestTask.new(:test) do |t|
|
7
8
|
t.libs << "test"
|
@@ -9,4 +10,10 @@ Rake::TestTask.new(:test) do |t|
|
|
9
10
|
t.test_files = FileList["test/**/*_test.rb"]
|
10
11
|
end
|
11
12
|
|
13
|
+
SOURCE_FILES =
|
14
|
+
FileList[%w[Gemfile Rakefile syntax_tree-haml.gemspec lib/**/*.rb test/*.rb]]
|
15
|
+
|
16
|
+
SyntaxTree::Rake::CheckTask.new { |t| t.source_files = SOURCE_FILES }
|
17
|
+
SyntaxTree::Rake::WriteTask.new { |t| t.source_files = SOURCE_FILES }
|
18
|
+
|
12
19
|
task default: :test
|
@@ -0,0 +1,425 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SyntaxTree
|
4
|
+
module Haml
|
5
|
+
class Format < Visitor
|
6
|
+
attr_reader :q
|
7
|
+
|
8
|
+
def initialize(q)
|
9
|
+
@q = q
|
10
|
+
end
|
11
|
+
|
12
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
|
13
|
+
def visit_comment(node)
|
14
|
+
with_children(node) do
|
15
|
+
q.text("/")
|
16
|
+
q.text("!") if node.value[:revealed]
|
17
|
+
|
18
|
+
if node.value[:conditional]
|
19
|
+
q.text(node.value[:conditional])
|
20
|
+
elsif node.value[:text]
|
21
|
+
q.text(" #{node.value[:text]}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
|
27
|
+
def visit_doctype(node)
|
28
|
+
parts = ["!!!"]
|
29
|
+
|
30
|
+
parts << if DOCTYPE_TYPES.key?(node.value[:type])
|
31
|
+
DOCTYPE_TYPES[node.value[:type]]
|
32
|
+
elsif DOCTYPE_VERSIONS.include?(node.value[:version])
|
33
|
+
node.value[:version]
|
34
|
+
else
|
35
|
+
node.value[:type]
|
36
|
+
end
|
37
|
+
|
38
|
+
parts << node.value[:encoding] if node.value[:encoding]
|
39
|
+
q.text(parts.join(" "))
|
40
|
+
end
|
41
|
+
|
42
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#filter
|
43
|
+
def visit_filter(node)
|
44
|
+
q.group do
|
45
|
+
q.text(":")
|
46
|
+
q.text(node.value[:name])
|
47
|
+
|
48
|
+
q.indent do
|
49
|
+
q.breakable(force: true)
|
50
|
+
|
51
|
+
segments = node.value[:text].strip.split("\n")
|
52
|
+
q.seplist(segments, -> { q.breakable(force: true) }) do |segment|
|
53
|
+
q.text(segment)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
|
60
|
+
def visit_haml_comment(node)
|
61
|
+
q.text("-#")
|
62
|
+
text = node.value[:text].strip
|
63
|
+
|
64
|
+
if text.include?("\n")
|
65
|
+
q.indent do
|
66
|
+
q.breakable(force: true)
|
67
|
+
q.seplist(
|
68
|
+
text.split("\n"),
|
69
|
+
-> { q.breakable(force: true) }
|
70
|
+
) { |segment| q.text(segment) }
|
71
|
+
end
|
72
|
+
else
|
73
|
+
q.text(" #{text}")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
|
78
|
+
def visit_plain(node)
|
79
|
+
text = node.value[:text]
|
80
|
+
q.text("\\") if escaped?(text)
|
81
|
+
q.text(text)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Visit the root node of the AST.
|
85
|
+
def visit_root(node)
|
86
|
+
node.children.each do |child|
|
87
|
+
visit(child)
|
88
|
+
q.breakable(force: true)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
|
93
|
+
def visit_script(node)
|
94
|
+
with_children(node) do
|
95
|
+
q.text("&") if node.value[:escape_html]
|
96
|
+
|
97
|
+
node.value[:preserve] ? q.text("~") : q.text("=")
|
98
|
+
|
99
|
+
q.text(" ")
|
100
|
+
q.text(node.value[:text].strip)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
|
105
|
+
def visit_silent_script(node)
|
106
|
+
q.group do
|
107
|
+
q.text("- ")
|
108
|
+
q.text(node.value[:text].strip)
|
109
|
+
|
110
|
+
node.children.each do |child|
|
111
|
+
if continuation?(node, child)
|
112
|
+
q.breakable(force: true)
|
113
|
+
visit(child)
|
114
|
+
else
|
115
|
+
q.indent do
|
116
|
+
q.breakable(force: true)
|
117
|
+
visit(child)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
LiteralHashValue = Struct.new(:value)
|
125
|
+
|
126
|
+
# When formatting a tag, there are a lot of different kinds of things that
|
127
|
+
# can be printed out. There's the tag name, the attributes, the content,
|
128
|
+
# etc. This object is responsible for housing all of those parts.
|
129
|
+
class PartList
|
130
|
+
attr_reader :node, :parts
|
131
|
+
|
132
|
+
def initialize(node)
|
133
|
+
@node = node
|
134
|
+
@parts = []
|
135
|
+
end
|
136
|
+
|
137
|
+
def <<(part)
|
138
|
+
parts << part
|
139
|
+
end
|
140
|
+
|
141
|
+
def empty?
|
142
|
+
parts.empty?
|
143
|
+
end
|
144
|
+
|
145
|
+
def format(q)
|
146
|
+
if empty? && node.value[:name] == "div"
|
147
|
+
# If we don't have any other parts to print and the tag is a div
|
148
|
+
# then we need to make sure to add that to the beginning. Otherwise
|
149
|
+
# it's implied by the presence of other operators.
|
150
|
+
q.text("%div")
|
151
|
+
else
|
152
|
+
parts.inject(0) do |align, part|
|
153
|
+
part.format(q, align)
|
154
|
+
align + part.length
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class PlainPart < Struct.new(:value)
|
161
|
+
def format(q, align)
|
162
|
+
q.text(value)
|
163
|
+
end
|
164
|
+
|
165
|
+
def length
|
166
|
+
value.length
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class PrefixPart < Struct.new(:prefix, :value)
|
171
|
+
def format(q, align)
|
172
|
+
q.text("#{prefix}#{value}")
|
173
|
+
end
|
174
|
+
|
175
|
+
def length
|
176
|
+
prefix.length + value.length
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class HTMLAttributesPart
|
181
|
+
attr_reader :values
|
182
|
+
|
183
|
+
def initialize(raw)
|
184
|
+
@values =
|
185
|
+
raw[1...-1]
|
186
|
+
.split(",")
|
187
|
+
.to_h { |keypair| keypair[1..-1].split("\" => ") }
|
188
|
+
end
|
189
|
+
|
190
|
+
def format(q, align)
|
191
|
+
q.group do
|
192
|
+
q.text("(")
|
193
|
+
q.nest(align) do
|
194
|
+
q.seplist(
|
195
|
+
values,
|
196
|
+
-> { q.fill_breakable },
|
197
|
+
:each_pair
|
198
|
+
) { |key, value| q.text("#{key}=#{value}") }
|
199
|
+
end
|
200
|
+
q.text(")")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def length
|
205
|
+
values.sum { |key, value| key.length + value.length + 3 }
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class HashAttributesPart < Struct.new(:values)
|
210
|
+
def format(q, align)
|
211
|
+
format_value(q, values)
|
212
|
+
end
|
213
|
+
|
214
|
+
def length
|
215
|
+
values.sum do |key, value|
|
216
|
+
key.length + (value.is_a?(String) ? value : value.to_s).length + 3
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
private
|
221
|
+
|
222
|
+
def format_value(q, hash, level = 0)
|
223
|
+
q.group do
|
224
|
+
q.text("{")
|
225
|
+
q.indent do
|
226
|
+
q.group do
|
227
|
+
q.breakable(level == 0 ? "" : " ")
|
228
|
+
q.seplist(hash, nil, :each_pair) do |key, value|
|
229
|
+
q.text(Format.hash_key(key))
|
230
|
+
q.text(" ")
|
231
|
+
|
232
|
+
if value.is_a?(Hash)
|
233
|
+
format_value(q, value, level + 1)
|
234
|
+
else
|
235
|
+
q.text(Format.hash_value(value))
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
q.breakable(level == 0 ? "" : " ")
|
242
|
+
q.text("}")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def self.hash_key(key)
|
248
|
+
key.match?(/^@|[-:]/) ? "\"#{key}\":" : "#{key}:"
|
249
|
+
end
|
250
|
+
|
251
|
+
def self.hash_value(value)
|
252
|
+
case value
|
253
|
+
when LiteralHashValue
|
254
|
+
value.value
|
255
|
+
when String
|
256
|
+
"\"#{Quotes.normalize(value, "\"")}\""
|
257
|
+
else
|
258
|
+
value.to_s
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Visit a tag node.
|
263
|
+
def visit_tag(node)
|
264
|
+
parts = PartList.new(node)
|
265
|
+
|
266
|
+
# If we have a tag that isn't a div, then we need to print out that
|
267
|
+
# name of that tag first. If it is a div, first we'll check if there
|
268
|
+
# are any other things that would force us to print out the div
|
269
|
+
# explicitly, and otherwise we'll leave it off.
|
270
|
+
if node.value[:name] != "div"
|
271
|
+
parts << PrefixPart.new("%", node.value[:name])
|
272
|
+
end
|
273
|
+
|
274
|
+
# If we have a class attribute, then we're going to print that here
|
275
|
+
# using the special class syntax.
|
276
|
+
if node.value[:attributes].key?("class")
|
277
|
+
parts << PrefixPart.new(
|
278
|
+
".",
|
279
|
+
node.value[:attributes]["class"].tr(" ", ".")
|
280
|
+
)
|
281
|
+
end
|
282
|
+
|
283
|
+
# If we have an id attribute, then we're going to print that here
|
284
|
+
# using the special id syntax.
|
285
|
+
if node.value[:attributes].key?("id")
|
286
|
+
parts << PrefixPart.new("#", node.value[:attributes]["id"])
|
287
|
+
end
|
288
|
+
|
289
|
+
# If we're using dynamic attributes on this tag, then they come in as
|
290
|
+
# a string that looks like the output of Hash#inspect from Ruby. So
|
291
|
+
# here we're going to split it all up and print it out nicely.
|
292
|
+
if node.value[:dynamic_attributes].new
|
293
|
+
parts << HTMLAttributesPart.new(node.value[:dynamic_attributes].new)
|
294
|
+
end
|
295
|
+
|
296
|
+
# If there are any static attributes that are not class or id (because
|
297
|
+
# we already took care of those), then we're going to print them out
|
298
|
+
# here.
|
299
|
+
static =
|
300
|
+
node.value[:attributes].reject do |key, _|
|
301
|
+
key == "class" || key == "id"
|
302
|
+
end
|
303
|
+
|
304
|
+
parts << HashAttributesPart.new(static) if static.any?
|
305
|
+
|
306
|
+
# If there are dynamic attributes that don't use the newer syntax, then
|
307
|
+
# we're going to print them out here.
|
308
|
+
if node.value[:dynamic_attributes].old
|
309
|
+
parts << PlainPart.new("%div") if parts.empty?
|
310
|
+
|
311
|
+
if ::Haml::AttributeParser.available?
|
312
|
+
dynamic = parse_attributes(node.value[:dynamic_attributes].old)
|
313
|
+
parts << if dynamic.is_a?(LiteralHashValue)
|
314
|
+
PlainPart.new(dynamic.value)
|
315
|
+
else
|
316
|
+
HashAttributesPart.new(dynamic)
|
317
|
+
end
|
318
|
+
else
|
319
|
+
parts << PlainPart.new(node.value[:dynamic_attributes].old)
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#object-reference-
|
324
|
+
if node.value[:object_ref] != :nil
|
325
|
+
parts << PlainPart.new("%div") if parts.empty?
|
326
|
+
parts << PlainPart.new(node.value[:object_ref])
|
327
|
+
end
|
328
|
+
|
329
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#whitespace-removal--and-
|
330
|
+
parts << PlainPart.new(">") if node.value[:nuke_outer_whitespace]
|
331
|
+
parts << PlainPart.new("<") if node.value[:nuke_inner_whitespace]
|
332
|
+
|
333
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#empty-void-tags-
|
334
|
+
parts << PlainPart.new("/") if node.value[:self_closing]
|
335
|
+
|
336
|
+
# If there is a value part, then we're going to print slightly
|
337
|
+
# differently as the value goes after the tag declaration.
|
338
|
+
if (value = node.value[:value]) && !value.empty?
|
339
|
+
with_children(node) do
|
340
|
+
q.group { parts.format(q) }
|
341
|
+
q.indent do
|
342
|
+
# Split between the declaration of the tag and the contents of the
|
343
|
+
# tag.
|
344
|
+
q.breakable("")
|
345
|
+
|
346
|
+
if node.value[:parse] && value.match?(/#[{$@]/)
|
347
|
+
# There's a weird case here where if the value includes
|
348
|
+
# interpolation and it's marked as { parse: true }, then we
|
349
|
+
# don't actually want the = prefix, and we want to remove extra
|
350
|
+
# escaping.
|
351
|
+
q.if_break { q.text("") }.if_flat { q.text(" ") }
|
352
|
+
q.text(value[1...-1].gsub(/\\"/, "\""))
|
353
|
+
elsif node.value[:parse]
|
354
|
+
q.text("= ")
|
355
|
+
q.text(value)
|
356
|
+
else
|
357
|
+
q.if_break { q.text("") }.if_flat { q.text(" ") }
|
358
|
+
q.text(value)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
else
|
363
|
+
with_children(node) { parts.format(q) }
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
private
|
368
|
+
|
369
|
+
# When printing out sequences of silent scripts, sometimes subsequent nodes
|
370
|
+
# will be continuations of previous nodes. In that case we want to dedent
|
371
|
+
# them to match.
|
372
|
+
def continuation?(node, child)
|
373
|
+
return false if child.type != :silent_script
|
374
|
+
|
375
|
+
case [node.value[:keyword], child.value[:keyword]]
|
376
|
+
in ["case", "in" | "when" | "else"]
|
377
|
+
true
|
378
|
+
in ["if" | "unless", "elsif" | "else"]
|
379
|
+
true
|
380
|
+
else
|
381
|
+
false
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# If a node comes in as the plain type but starts with one of the special
|
386
|
+
# characters that haml parses, then we need to escape it with a \ when
|
387
|
+
# printing.
|
388
|
+
def escaped?(text)
|
389
|
+
::Haml::Parser::SPECIAL_CHARACTERS.any? do |special|
|
390
|
+
text.start_with?(special)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
# Take a source string and attempt to parse it into a set of attributes that
|
395
|
+
# can be used to format the source.
|
396
|
+
def parse_attributes(source)
|
397
|
+
case Ripper.sexp(source)
|
398
|
+
in [:program, [[:hash, *], *]] if parsed =
|
399
|
+
::Haml::AttributeParser.parse(source)
|
400
|
+
parsed.to_h { |key, value| [key, parse_attributes(value)] }
|
401
|
+
in [:program, [[:string_literal, *], *]]
|
402
|
+
source[1...-1]
|
403
|
+
else
|
404
|
+
LiteralHashValue.new(source)
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def with_children(node)
|
409
|
+
if node.children.empty?
|
410
|
+
q.group { yield }
|
411
|
+
else
|
412
|
+
q.group do
|
413
|
+
q.group { yield }
|
414
|
+
q.indent do
|
415
|
+
node.children.each do |child|
|
416
|
+
q.breakable(force: true)
|
417
|
+
visit(child)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SyntaxTree
|
4
|
+
module Haml
|
5
|
+
class PrettyPrint < Visitor
|
6
|
+
attr_reader :q
|
7
|
+
|
8
|
+
def initialize(q)
|
9
|
+
@q = q
|
10
|
+
end
|
11
|
+
|
12
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
|
13
|
+
def visit_comment(node)
|
14
|
+
group("comment") do
|
15
|
+
if node.value[:conditional]
|
16
|
+
pp_field("conditional", node.value[:conditional])
|
17
|
+
elsif node.value[:text]
|
18
|
+
pp_field("text", node.value[:text])
|
19
|
+
end
|
20
|
+
|
21
|
+
bool_field("revealed") if node.value[:revealed]
|
22
|
+
pp_field("children", node.children) if node.children.any?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
|
27
|
+
def visit_doctype(node)
|
28
|
+
group("doctype") do
|
29
|
+
if DOCTYPE_TYPES.key?(node.value[:type])
|
30
|
+
pp_field("type", node.value[:type])
|
31
|
+
elsif DOCTYPE_VERSIONS.include?(node.value[:version])
|
32
|
+
pp_field("version", node.value[:version])
|
33
|
+
else
|
34
|
+
pp_field("text", node.value[:text])
|
35
|
+
end
|
36
|
+
|
37
|
+
pp_field("encoding", node.value[:encoding]) if node.value[:encoding]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#filter
|
42
|
+
def visit_filter(node)
|
43
|
+
group("filter") do
|
44
|
+
text_field("name", node.value[:name])
|
45
|
+
pp_field("text", node.value[:text])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
|
50
|
+
def visit_haml_comment(node)
|
51
|
+
group("haml_comment") { pp_field("text", node.value[:text]) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
|
55
|
+
def visit_plain(node)
|
56
|
+
group("plain") { pp_field("text", node.value[:text]) }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Visit the root node of the AST.
|
60
|
+
def visit_root(node)
|
61
|
+
group("root") do
|
62
|
+
pp_field("children", node.children) if node.children.any?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
|
67
|
+
def visit_script(node)
|
68
|
+
group("script") do
|
69
|
+
pp_field("text", node.value[:text])
|
70
|
+
bool_field("escape_html") if node.value[:escape_html]
|
71
|
+
bool_field("preserve") if node.value[:preserve]
|
72
|
+
pp_field("children", node.children) if node.children.any?
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# https://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
|
77
|
+
def visit_silent_script(node)
|
78
|
+
group("silent-script") do
|
79
|
+
pp_field("text", node.value[:text])
|
80
|
+
pp_field("children", node.children) if node.children.any?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Visit a tag node.
|
85
|
+
def visit_tag(node)
|
86
|
+
group("tag") do
|
87
|
+
pp_field("name", node.value[:name])
|
88
|
+
|
89
|
+
if node.value[:attributes].any?
|
90
|
+
pp_field("attributes", node.value[:attributes])
|
91
|
+
end
|
92
|
+
|
93
|
+
if node.value[:dynamic_attributes].new
|
94
|
+
pp_field(
|
95
|
+
"dynamic_attributes.new",
|
96
|
+
node.value[:dynamic_attributes].new
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
if node.value[:dynamic_attributes].old
|
101
|
+
pp_field(
|
102
|
+
"dynamic_attributes.old",
|
103
|
+
node.value[:dynamic_attributes].old
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
if node.value[:object_ref] != :nil
|
108
|
+
pp_field("object_ref", node.value[:object_ref])
|
109
|
+
end
|
110
|
+
|
111
|
+
if node.value[:nuke_outer_whitespace]
|
112
|
+
bool_field("nuke_outer_whitespace")
|
113
|
+
end
|
114
|
+
|
115
|
+
if node.value[:nuke_inner_whitespace]
|
116
|
+
bool_field("nuke_inner_whitespace")
|
117
|
+
end
|
118
|
+
|
119
|
+
bool_field("self_closing") if node.value[:self_closing]
|
120
|
+
pp_field("value", node.value[:value]) if node.value[:value]
|
121
|
+
pp_field("children", node.children) if node.children.any?
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def bool_field(name)
|
128
|
+
q.breakable
|
129
|
+
q.text(name)
|
130
|
+
end
|
131
|
+
|
132
|
+
def group(name)
|
133
|
+
q.group do
|
134
|
+
q.text("(")
|
135
|
+
q.text(name)
|
136
|
+
|
137
|
+
q.nest(2) { yield }
|
138
|
+
q.breakable("")
|
139
|
+
q.text(")")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def pp_field(name, value)
|
144
|
+
q.breakable
|
145
|
+
q.text(name)
|
146
|
+
q.text("=")
|
147
|
+
q.pp(value)
|
148
|
+
end
|
149
|
+
|
150
|
+
def text_field(name, value)
|
151
|
+
q.breakable
|
152
|
+
q.text(name)
|
153
|
+
q.text("=")
|
154
|
+
q.text(value)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|