syntax_tree-haml 1.3.1 → 2.0.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 +4 -4
- data/.github/workflows/auto-merge.yml +22 -0
- data/.github/workflows/main.yml +7 -18
- data/CHANGELOG.md +21 -1
- data/Gemfile.lock +12 -10
- data/README.md +1 -1
- data/lib/syntax_tree/haml/format.rb +76 -38
- data/lib/syntax_tree/haml/version.rb +1 -1
- data/lib/syntax_tree/haml.rb +5 -1
- data/syntax_tree-haml.gemspec +4 -3
- metadata +14 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61fd378df6679c193bda86bdb1f1f78de949b0978c7ec02ec114e1d8fadcd3b5
|
4
|
+
data.tar.gz: 1011cad24c3f91ab3086c14b9dda49c6a0093d20c8d3af8fc86286e8dd8851ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cfb430120300e2fe6a593a7a47e8be22c09d160960b5a6f6d324e117827d752c648d6111c47d664a8d137cff584aa5fb856d93241c5f7edf2be2360e7e8f8c4
|
7
|
+
data.tar.gz: 4e4597ea20a6514cc10ff326db244616ebdd41f11d71095f76ca4aabfb1a1c355e76620e024223ff761e5f9f5bcd0eb868ca62323b2ba669a202da8c0ba13d55
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: Dependabot auto-merge
|
2
|
+
on: pull_request
|
3
|
+
|
4
|
+
permissions:
|
5
|
+
contents: write
|
6
|
+
pull-requests: write
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
dependabot:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
if: ${{ github.actor == 'dependabot[bot]' }}
|
12
|
+
steps:
|
13
|
+
- name: Dependabot metadata
|
14
|
+
id: metadata
|
15
|
+
uses: dependabot/fetch-metadata@v1.3.3
|
16
|
+
with:
|
17
|
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
18
|
+
- name: Enable auto-merge for Dependabot PRs
|
19
|
+
run: gh pr merge --auto --merge "$PR_URL"
|
20
|
+
env:
|
21
|
+
PR_URL: ${{github.event.pull_request.html_url}}
|
22
|
+
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
data/.github/workflows/main.yml
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
name: Main
|
2
2
|
on:
|
3
|
-
|
4
|
-
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- main
|
6
|
+
pull_request: {}
|
5
7
|
jobs:
|
6
8
|
ci:
|
7
9
|
strategy:
|
8
10
|
fail-fast: false
|
9
11
|
matrix:
|
10
12
|
ruby:
|
11
|
-
- '2.7'
|
13
|
+
- '2.7.0'
|
14
|
+
- '2.7.5'
|
12
15
|
- '3.0'
|
13
16
|
- '3.1'
|
14
17
|
name: CI
|
@@ -16,7 +19,7 @@ jobs:
|
|
16
19
|
env:
|
17
20
|
CI: true
|
18
21
|
steps:
|
19
|
-
- uses: actions/checkout@
|
22
|
+
- uses: actions/checkout@v3
|
20
23
|
- uses: ruby/setup-ruby@v1
|
21
24
|
with:
|
22
25
|
bundler-cache: true
|
@@ -25,17 +28,3 @@ jobs:
|
|
25
28
|
run: |
|
26
29
|
bundle exec rake test
|
27
30
|
bundle exec rake stree:check
|
28
|
-
automerge:
|
29
|
-
name: AutoMerge
|
30
|
-
needs: ci
|
31
|
-
runs-on: ubuntu-latest
|
32
|
-
if: github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]'
|
33
|
-
steps:
|
34
|
-
- uses: actions/github-script@v3
|
35
|
-
with:
|
36
|
-
script: |
|
37
|
-
github.pulls.merge({
|
38
|
-
owner: context.payload.repository.owner.login,
|
39
|
-
repo: context.payload.repository.name,
|
40
|
-
pull_number: context.payload.pull_request.number
|
41
|
-
})
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [2.0.0] - 2022-10-18
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Support for Ruby 2.7.0, not just 2.7.3
|
14
|
+
- Require syntax_tree 4.0.1 or higher.
|
15
|
+
- Require prettier_print 1.0.0 or higher.
|
16
|
+
|
17
|
+
### Changed
|
18
|
+
|
19
|
+
- Nodes must now be formatted with a `SyntaxTree::Haml::Formatter`.
|
20
|
+
|
21
|
+
## [1.3.2] - 2022-09-19
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- Properly support unescaping plain and script.
|
26
|
+
|
9
27
|
## [1.3.1] - 2022-08-01
|
10
28
|
|
11
29
|
### Changed
|
@@ -54,7 +72,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
|
|
54
72
|
|
55
73
|
- 🎉 Initial release! 🎉
|
56
74
|
|
57
|
-
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/
|
75
|
+
[unreleased]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v2.0.0...HEAD
|
76
|
+
[2.0.0]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.3.2...v2.0.0
|
77
|
+
[1.3.2]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.3.1...v1.3.2
|
58
78
|
[1.3.1]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.3.0...v1.3.1
|
59
79
|
[1.3.0]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.2.1...v1.3.0
|
60
80
|
[1.2.1]: https://github.com/ruby-syntax-tree/syntax_tree-haml/compare/v1.2.0...v1.2.1
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
syntax_tree-haml (
|
5
|
-
haml (>= 5.2)
|
6
|
-
prettier_print
|
7
|
-
syntax_tree (>=
|
4
|
+
syntax_tree-haml (2.0.0)
|
5
|
+
haml (>= 5.2, != 6.0.0)
|
6
|
+
prettier_print (>= 1.0.0)
|
7
|
+
syntax_tree (>= 4.0.0)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
12
|
docile (1.4.0)
|
13
|
-
haml (
|
14
|
-
temple (>= 0.8.
|
13
|
+
haml (6.0.7)
|
14
|
+
temple (>= 0.8.2)
|
15
|
+
thor
|
15
16
|
tilt
|
16
|
-
minitest (5.16.
|
17
|
-
prettier_print (0.1
|
17
|
+
minitest (5.16.3)
|
18
|
+
prettier_print (1.0.1)
|
18
19
|
rake (13.0.6)
|
19
20
|
simplecov (0.21.2)
|
20
21
|
docile (~> 1.1)
|
@@ -22,9 +23,10 @@ GEM
|
|
22
23
|
simplecov_json_formatter (~> 0.1)
|
23
24
|
simplecov-html (0.12.3)
|
24
25
|
simplecov_json_formatter (0.1.4)
|
25
|
-
syntax_tree (
|
26
|
-
prettier_print
|
26
|
+
syntax_tree (4.0.1)
|
27
|
+
prettier_print (>= 1.0.1)
|
27
28
|
temple (0.8.2)
|
29
|
+
thor (1.2.1)
|
28
30
|
tilt (2.0.11)
|
29
31
|
|
30
32
|
PLATFORMS
|
data/README.md
CHANGED
@@ -55,7 +55,7 @@ template.haml 1ms
|
|
55
55
|
|
56
56
|
## Development
|
57
57
|
|
58
|
-
After checking out the repo, run `
|
58
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests. You can also run `bundle console` for an interactive prompt that will allow you to experiment.
|
59
59
|
|
60
60
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
61
61
|
|
@@ -3,6 +3,22 @@
|
|
3
3
|
module SyntaxTree
|
4
4
|
module Haml
|
5
5
|
class Format < Visitor
|
6
|
+
class Formatter < ::SyntaxTree::Formatter
|
7
|
+
attr_reader :literal_lines, :quote
|
8
|
+
|
9
|
+
def initialize(source, *rest)
|
10
|
+
@literal_lines = {}
|
11
|
+
source
|
12
|
+
.lines
|
13
|
+
.each
|
14
|
+
.with_index(1) do |line, index|
|
15
|
+
@literal_lines[index] = line.rstrip if line.start_with?("!")
|
16
|
+
end
|
17
|
+
|
18
|
+
super(source, *rest)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
6
22
|
attr_reader :q
|
7
23
|
|
8
24
|
def initialize(q)
|
@@ -46,11 +62,17 @@ module SyntaxTree
|
|
46
62
|
q.text(node.value[:name])
|
47
63
|
|
48
64
|
q.indent do
|
49
|
-
q.
|
65
|
+
q.breakable_force
|
66
|
+
first = true
|
67
|
+
|
68
|
+
node.value[:text].each_line(chomp: true) do |line|
|
69
|
+
if first
|
70
|
+
first = false
|
71
|
+
else
|
72
|
+
q.breakable_force
|
73
|
+
end
|
50
74
|
|
51
|
-
|
52
|
-
q.seplist(segments, -> { q.breakable(force: true) }) do |segment|
|
53
|
-
q.text(segment)
|
75
|
+
q.text(line)
|
54
76
|
end
|
55
77
|
end
|
56
78
|
end
|
@@ -63,11 +85,18 @@ module SyntaxTree
|
|
63
85
|
|
64
86
|
if text.include?("\n")
|
65
87
|
q.indent do
|
66
|
-
q.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
88
|
+
q.breakable_force
|
89
|
+
first = true
|
90
|
+
|
91
|
+
text.each_line(chomp: true) do |line|
|
92
|
+
if first
|
93
|
+
first = false
|
94
|
+
else
|
95
|
+
q.breakable_force
|
96
|
+
end
|
97
|
+
|
98
|
+
q.text(line)
|
99
|
+
end
|
71
100
|
end
|
72
101
|
else
|
73
102
|
q.text(" #{text}")
|
@@ -76,28 +105,34 @@ module SyntaxTree
|
|
76
105
|
|
77
106
|
# https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
|
78
107
|
def visit_plain(node)
|
79
|
-
|
80
|
-
|
81
|
-
|
108
|
+
if line = q.literal_lines[node.line]
|
109
|
+
q.text(line)
|
110
|
+
else
|
111
|
+
text = node.value[:text]
|
112
|
+
q.text("\\") if escaped?(text)
|
113
|
+
q.text(text)
|
114
|
+
end
|
82
115
|
end
|
83
116
|
|
84
117
|
# Visit the root node of the AST.
|
85
118
|
def visit_root(node)
|
86
119
|
node.children.each do |child|
|
87
120
|
visit(child)
|
88
|
-
q.
|
121
|
+
q.breakable_force
|
89
122
|
end
|
90
123
|
end
|
91
124
|
|
92
125
|
# https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
|
93
126
|
def visit_script(node)
|
94
127
|
with_children(node) do
|
95
|
-
q.
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
128
|
+
if line = q.literal_lines[node.line]
|
129
|
+
q.text(line)
|
130
|
+
else
|
131
|
+
q.text("&") if node.value[:escape_html]
|
132
|
+
q.text(node.value[:preserve] ? "~" : "=")
|
133
|
+
q.text(" ")
|
134
|
+
q.text(node.value[:text].strip)
|
135
|
+
end
|
101
136
|
end
|
102
137
|
end
|
103
138
|
|
@@ -109,11 +144,11 @@ module SyntaxTree
|
|
109
144
|
|
110
145
|
node.children.each do |child|
|
111
146
|
if continuation?(node, child)
|
112
|
-
q.
|
147
|
+
q.breakable_force
|
113
148
|
visit(child)
|
114
149
|
else
|
115
150
|
q.indent do
|
116
|
-
q.
|
151
|
+
q.breakable_force
|
117
152
|
visit(child)
|
118
153
|
end
|
119
154
|
end
|
@@ -122,7 +157,6 @@ module SyntaxTree
|
|
122
157
|
end
|
123
158
|
|
124
159
|
LiteralHashValue = Struct.new(:value)
|
125
|
-
|
126
160
|
StringHashValue = Struct.new(:value, :quote)
|
127
161
|
|
128
162
|
# When formatting a tag, there are a lot of different kinds of things that
|
@@ -180,6 +214,14 @@ module SyntaxTree
|
|
180
214
|
end
|
181
215
|
|
182
216
|
class HTMLAttributesPart
|
217
|
+
class Separator
|
218
|
+
def call(q)
|
219
|
+
q.fill_breakable
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
SEPARATOR = Separator.new
|
224
|
+
|
183
225
|
attr_reader :values
|
184
226
|
|
185
227
|
def initialize(raw)
|
@@ -193,11 +235,9 @@ module SyntaxTree
|
|
193
235
|
q.group do
|
194
236
|
q.text("(")
|
195
237
|
q.nest(align) do
|
196
|
-
q.seplist(
|
197
|
-
|
198
|
-
|
199
|
-
:each_pair
|
200
|
-
) { |key, value| q.text("#{key}=#{value}") }
|
238
|
+
q.seplist(values, SEPARATOR, :each_pair) do |key, value|
|
239
|
+
q.text("#{key}=#{value}")
|
240
|
+
end
|
201
241
|
end
|
202
242
|
q.text(")")
|
203
243
|
end
|
@@ -222,13 +262,13 @@ module SyntaxTree
|
|
222
262
|
private
|
223
263
|
|
224
264
|
def format_value(q, hash, level = 0)
|
225
|
-
quote =
|
265
|
+
quote = q.quote
|
226
266
|
|
227
267
|
q.group do
|
228
268
|
q.text("{")
|
229
269
|
q.indent do
|
230
270
|
q.group do
|
231
|
-
|
271
|
+
level == 0 ? q.breakable_empty : q.breakable_space
|
232
272
|
q.seplist(hash, nil, :each_pair) do |key, value|
|
233
273
|
if key.match?(/^@|[-:]/)
|
234
274
|
q.text("#{quote}#{Quotes.normalize(key, quote)}#{quote}:")
|
@@ -244,8 +284,7 @@ module SyntaxTree
|
|
244
284
|
when LiteralHashValue
|
245
285
|
q.text(value.value)
|
246
286
|
when StringLiteral
|
247
|
-
|
248
|
-
qq.with_target(q.target) { value.format(qq) }
|
287
|
+
value.format(q)
|
249
288
|
when String
|
250
289
|
q.text("#{quote}#{Quotes.normalize(value, quote)}#{quote}")
|
251
290
|
else
|
@@ -255,7 +294,7 @@ module SyntaxTree
|
|
255
294
|
end
|
256
295
|
end
|
257
296
|
|
258
|
-
|
297
|
+
level == 0 ? q.breakable_empty : q.breakable_space
|
259
298
|
q.text("}")
|
260
299
|
end
|
261
300
|
end
|
@@ -343,7 +382,7 @@ module SyntaxTree
|
|
343
382
|
q.indent do
|
344
383
|
# Split between the declaration of the tag and the contents of the
|
345
384
|
# tag.
|
346
|
-
q.
|
385
|
+
q.breakable_empty
|
347
386
|
|
348
387
|
if node.value[:parse] && value.match?(/#[{$@]/)
|
349
388
|
# There's a weird case here where if the value includes
|
@@ -353,8 +392,7 @@ module SyntaxTree
|
|
353
392
|
q.if_break { q.text("") }.if_flat { q.text(" ") }
|
354
393
|
q.text(value[1...-1].gsub(/\\"/, "\""))
|
355
394
|
elsif node.value[:parse]
|
356
|
-
q.text("= ")
|
357
|
-
q.text(value)
|
395
|
+
q.text("= #{value}")
|
358
396
|
else
|
359
397
|
q.if_break { q.text("") }.if_flat { q.text(" ") }
|
360
398
|
q.text(value)
|
@@ -393,8 +431,8 @@ module SyntaxTree
|
|
393
431
|
end
|
394
432
|
end
|
395
433
|
|
396
|
-
# Take a source string and attempt to parse it into a set of attributes
|
397
|
-
# can be used to format the source.
|
434
|
+
# Take a source string and attempt to parse it into a set of attributes
|
435
|
+
# that can be used to format the source.
|
398
436
|
def parse_attributes(source)
|
399
437
|
case Ripper.sexp(source)
|
400
438
|
in [:program, [[:hash, *], *]] if parsed =
|
@@ -415,7 +453,7 @@ module SyntaxTree
|
|
415
453
|
q.group { yield }
|
416
454
|
q.indent do
|
417
455
|
node.children.each do |child|
|
418
|
-
q.
|
456
|
+
q.breakable_force
|
419
457
|
visit(child)
|
420
458
|
end
|
421
459
|
end
|
data/lib/syntax_tree/haml.rb
CHANGED
@@ -34,7 +34,11 @@ module SyntaxTree
|
|
34
34
|
# This is the main entrypoint for the formatter. It parses the source,
|
35
35
|
# builds a formatter, then pretty prints the result.
|
36
36
|
def self.format(source, maxwidth = 80)
|
37
|
-
|
37
|
+
formatter = Format::Formatter.new(source, +"", maxwidth)
|
38
|
+
parse(source).format(formatter)
|
39
|
+
|
40
|
+
formatter.flush
|
41
|
+
formatter.output
|
38
42
|
end
|
39
43
|
|
40
44
|
# This is a required API for syntax tree which just delegates to File.read.
|
data/syntax_tree-haml.gemspec
CHANGED
@@ -24,9 +24,10 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
25
|
spec.require_paths = %w[lib]
|
26
26
|
|
27
|
-
|
28
|
-
spec.add_dependency "
|
29
|
-
spec.add_dependency "
|
27
|
+
# Can't use 6.0.0 due to https://github.com/haml/haml/issues/1085
|
28
|
+
spec.add_dependency "haml", ">= 5.2", "!= 6.0.0"
|
29
|
+
spec.add_dependency "prettier_print", ">= 1.0.0"
|
30
|
+
spec.add_dependency "syntax_tree", ">= 4.0.0"
|
30
31
|
|
31
32
|
spec.add_development_dependency "bundler"
|
32
33
|
spec.add_development_dependency "minitest"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syntax_tree-haml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Newton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: haml
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '5.2'
|
20
|
+
- - "!="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 6.0.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,34 +27,37 @@ dependencies:
|
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '5.2'
|
30
|
+
- - "!="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 6.0.0
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: prettier_print
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - ">="
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
39
|
+
version: 1.0.0
|
34
40
|
type: :runtime
|
35
41
|
prerelease: false
|
36
42
|
version_requirements: !ruby/object:Gem::Requirement
|
37
43
|
requirements:
|
38
44
|
- - ">="
|
39
45
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
46
|
+
version: 1.0.0
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: syntax_tree
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - ">="
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
53
|
+
version: 4.0.0
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - ">="
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
60
|
+
version: 4.0.0
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: bundler
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -116,6 +122,7 @@ extensions: []
|
|
116
122
|
extra_rdoc_files: []
|
117
123
|
files:
|
118
124
|
- ".github/dependabot.yml"
|
125
|
+
- ".github/workflows/auto-merge.yml"
|
119
126
|
- ".github/workflows/main.yml"
|
120
127
|
- ".gitignore"
|
121
128
|
- CHANGELOG.md
|
@@ -152,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
159
|
- !ruby/object:Gem::Version
|
153
160
|
version: '0'
|
154
161
|
requirements: []
|
155
|
-
rubygems_version: 3.3.
|
162
|
+
rubygems_version: 3.3.21
|
156
163
|
signing_key:
|
157
164
|
specification_version: 4
|
158
165
|
summary: Syntax Tree support for Haml
|