syntax_tree-haml 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,306 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SyntaxTree
4
- module Haml
5
- class Tag
6
- LiteralHashValue = Struct.new(:value)
7
-
8
- def self.hash_key(key)
9
- key.match?(/^@|[-:]/) ? "\"#{key}\":" : "#{key}:"
10
- end
11
-
12
- def self.hash_value(value)
13
- case value
14
- when LiteralHashValue
15
- value.value
16
- when String
17
- "\"#{Quotes.normalize(value, "\"")}\""
18
- else
19
- value.to_s
20
- end
21
- end
22
-
23
- class PlainPart < Struct.new(:value)
24
- def format(q, align)
25
- q.text(value)
26
- end
27
-
28
- def length
29
- value.length
30
- end
31
- end
32
-
33
- class PrefixPart < Struct.new(:prefix, :value)
34
- def format(q, align)
35
- q.text("#{prefix}#{value}")
36
- end
37
-
38
- def length
39
- prefix.length + value.length
40
- end
41
- end
42
-
43
- class HTMLAttributesPart
44
- attr_reader :values
45
-
46
- def initialize(raw)
47
- @values =
48
- raw[1...-1].split(",").to_h do |keypair|
49
- keypair[1..-1].split("\" => ")
50
- end
51
- end
52
-
53
- def format(q, align)
54
- q.group do
55
- q.text("(")
56
- q.nest(align) do
57
- q.seplist(values, -> { q.fill_breakable }, :each_pair) do |key, value|
58
- q.text("#{key}=#{value}")
59
- end
60
- end
61
- q.text(")")
62
- end
63
- end
64
-
65
- def length
66
- values.sum { |key, value| key.length + value.length + 3 }
67
- end
68
- end
69
-
70
- class HashAttributesPart < Struct.new(:values)
71
- def format(q, align)
72
- format_value(q, values)
73
- end
74
-
75
- def length
76
- values.sum do |key, value|
77
- key.length + (value.is_a?(String) ? value : value.to_s).length + 3
78
- end
79
- end
80
-
81
- private
82
-
83
- def format_value(q, hash, level = 0)
84
- q.group do
85
- q.text("{")
86
- q.indent do
87
- q.group do
88
- q.breakable(level == 0 ? "" : " ")
89
- q.seplist(hash, nil, :each_pair) do |key, value|
90
- q.text(Tag.hash_key(key))
91
- q.text(" ")
92
-
93
- if value.is_a?(Hash)
94
- format_value(q, value, level + 1)
95
- else
96
- q.text(Tag.hash_value(value))
97
- end
98
- end
99
- end
100
- end
101
-
102
- q.breakable(level == 0 ? "" : " ")
103
- q.text("}")
104
- end
105
- end
106
- end
107
-
108
- attr_reader :node
109
-
110
- def initialize(node)
111
- @node = node
112
- end
113
-
114
- def format(q)
115
- parts = []
116
-
117
- # If we have a tag that isn't a div, then we need to print out that
118
- # name of that tag first. If it is a div, first we'll check if there
119
- # are any other things that would force us to print out the div
120
- # explicitly, and otherwise we'll leave it off.
121
- if node.value[:name] != "div"
122
- parts << PrefixPart.new("%", node.value[:name])
123
- end
124
-
125
- # If we have a class attribute, then we're going to print that here
126
- # using the special class syntax.
127
- if node.value[:attributes].key?("class")
128
- parts << PrefixPart.new(".", node.value[:attributes]["class"].tr(" ", "."))
129
- end
130
-
131
- # If we have an id attribute, then we're going to print that here
132
- # using the special id syntax.
133
- if node.value[:attributes].key?("id")
134
- parts << PrefixPart.new("#", node.value[:attributes]["id"])
135
- end
136
-
137
- # If we're using dynamic attributes on this tag, then they come in as
138
- # a string that looks like the output of Hash#inspect from Ruby. So
139
- # here we're going to split it all up and print it out nicely.
140
- if node.value[:dynamic_attributes].new
141
- parts << HTMLAttributesPart.new(node.value[:dynamic_attributes].new)
142
- end
143
-
144
- # If there are any static attributes that are not class or id (because
145
- # we already took care of those), then we're going to print them out
146
- # here.
147
- static = node.value[:attributes].reject { |key, _| key == "class" || key == "id" }
148
- parts << HashAttributesPart.new(static) if static.any?
149
-
150
- # If there are dynamic attributes that don't use the newer syntax, then
151
- # we're going to print them out here.
152
- if node.value[:dynamic_attributes].old
153
- parts << PlainPart.new("%div") if parts.empty?
154
-
155
- if ::Haml::AttributeParser.available?
156
- dynamic = parse_attributes(node.value[:dynamic_attributes].old)
157
- parts <<
158
- if dynamic.is_a?(LiteralHashValue)
159
- PlainPart.new(dynamic.value)
160
- else
161
- HashAttributesPart.new(dynamic)
162
- end
163
- else
164
- parts << PlainPart.new(node.value[:dynamic_attributes].old)
165
- end
166
- end
167
-
168
- # https://haml.info/docs/yardoc/file.REFERENCE.html#object-reference-
169
- if node.value[:object_ref] != :nil
170
- parts << PlainPart.new("%div") if parts.empty?
171
- parts << PlainPart.new(node.value[:object_ref])
172
- end
173
-
174
- # https://haml.info/docs/yardoc/file.REFERENCE.html#whitespace-removal--and-
175
- parts << PlainPart.new(">") if node.value[:nuke_outer_whitespace]
176
- parts << PlainPart.new("<") if node.value[:nuke_inner_whitespace]
177
-
178
- # https://haml.info/docs/yardoc/file.REFERENCE.html#empty-void-tags-
179
- parts << PlainPart.new("/") if node.value[:self_closing]
180
-
181
- # If there is a value part, then we're going to print slightly
182
- # differently as the value goes after the tag declaration.
183
- if node.value[:value]
184
- return Haml.with_children(node, q) do
185
- q.group do
186
- align = 0
187
-
188
- parts.each do |part|
189
- part.format(q, align)
190
- align += part.length
191
- end
192
- end
193
-
194
- q.indent do
195
- # Split between the declaration of the tag and the contents of the
196
- # tag.
197
- q.breakable("")
198
-
199
- if node.value[:parse] && node.value[:value].match?(/#[{$@]/)
200
- # There's a weird case here where if the value includes
201
- # interpolation and it's marked as { parse: true }, then we
202
- # don't actually want the = prefix, and we want to remove extra
203
- # escaping.
204
- q.if_break { q.text("") }.if_flat { q.text(" ") }
205
- q.text(node.value[:value][1...-1].gsub(/\\"/, "\""))
206
- elsif node.value[:parse]
207
- q.text("= ")
208
- q.text(node.value[:value])
209
- else
210
- q.if_break { q.text("") }.if_flat { q.text(" ") }
211
- q.text(node.value[:value])
212
- end
213
- end
214
- end
215
- end
216
-
217
- # In case none of the other if statements have matched and we're
218
- # printing a div, we need to explicitly add it back into the array.
219
- if parts.empty? && node.value[:name] == "div"
220
- parts << PlainPart.new("%div")
221
- end
222
-
223
- Haml.with_children(node, q) do
224
- align = 0
225
-
226
- parts.each do |part|
227
- part.format(q, align)
228
- align += part.length
229
- end
230
- end
231
- end
232
-
233
- def pretty_print(q)
234
- q.group(2, "(tag", ")") do
235
- q.breakable
236
- q.text("name=")
237
- q.pp(node.value[:name])
238
-
239
- if node.value[:attributes].any?
240
- q.breakable
241
- q.text("attributes=")
242
- q.pp(node.value[:attributes])
243
- end
244
-
245
- if node.value[:dynamic_attributes].new
246
- q.breakable
247
- q.text("dynamic_attributes.new=")
248
- q.pp(node.value[:dynamic_attributes].new)
249
- end
250
-
251
- if node.value[:dynamic_attributes].old
252
- q.breakable
253
- q.text("dynamic_attributes.old=")
254
- q.pp(node.value[:dynamic_attributes].old)
255
- end
256
-
257
- if node.value[:object_ref] != :nil
258
- q.breakable
259
- q.text("object_ref=")
260
- q.pp(node.value[:object_ref])
261
- end
262
-
263
- if node.value[:nuke_outer_whitespace]
264
- q.breakable
265
- q.text("nuke_outer_whitespace")
266
- end
267
-
268
- if node.value[:nuke_inner_whitespace]
269
- q.breakable
270
- q.text("nuke_inner_whitespace")
271
- end
272
-
273
- if node.value[:self_closing]
274
- q.breakable
275
- q.text("self_closing")
276
- end
277
-
278
- if node.value[:value]
279
- q.breakable
280
- q.text("value=")
281
- q.pp(node.value[:value])
282
- end
283
-
284
- if node.children.any?
285
- q.breakable
286
- q.text("children=")
287
- q.pp(node.children)
288
- end
289
- end
290
- end
291
-
292
- private
293
-
294
- def parse_attributes(source)
295
- case Ripper.sexp(source)
296
- in [:program, [[:hash, *], *]] if parsed = ::Haml::AttributeParser.parse(source)
297
- parsed.to_h { |key, value| [key, parse_attributes(value)] }
298
- in [:program, [[:string_literal, *], *]]
299
- source[1...-1]
300
- else
301
- LiteralHashValue.new(source)
302
- end
303
- end
304
- end
305
- end
306
- end