w_syntax_tree-erb 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4b1234ed5afef9a96ebefb415733354ac530ffa9bb35b718195d36be9f9fed7c
4
+ data.tar.gz: 03c589bb628753e874f05aa6ea504f0d3d14e2057a7843d919abfd31f9fc66e9
5
+ SHA512:
6
+ metadata.gz: cb5dd5cad343aabf4eaa8bd8cb177eeabb673cf68b8a016f36c13ee5ff2fbbb277a313800849cee940013355e430edca26d5d8541d566588f7902c41816d20a9
7
+ data.tar.gz: 3a147354e9fbef1bf89b604033c57f3746f1e17e69d050e7b4b41ffc409005000f4a7e5a12085e2704da71c4de4e16691795f6fe4600ba04de1106f5179c15b6
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Formatting report
3
+ about: Create a report to help us improve
4
+ title: "[Formatting] "
5
+ labels: bug
6
+ assignees: davidwessman
7
+
8
+ ---
9
+
10
+ <details>
11
+ <summary>ERB-snippet</summary
12
+
13
+ ```html
14
+ <% code %>
15
+ ```
16
+ </details>
17
+
18
+ <details>
19
+ <summary>Expected formatting</summary
20
+
21
+ ```html
22
+ <% code %>
23
+ ```
24
+ </details>
25
+ <details>
26
+ <summary>Actual formatting</summary
27
+
28
+ ```html
29
+ <% code %>
30
+ ```
31
+ </details>
32
+
33
+ ## Comment
34
+
35
+ ## Versions
36
+ syntax_tree:
37
+ syntax_tree-erb:
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: General
3
+ about: General issues
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "bundler"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
@@ -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}}
@@ -0,0 +1,32 @@
1
+ name: Main
2
+ on:
3
+ workflow_dispatch:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ pull_request:
9
+ types: [opened, synchronize, reopened]
10
+ jobs:
11
+ ci:
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ ruby:
16
+ - "3.0"
17
+ - "3.1"
18
+ - "3.2"
19
+ name: CI
20
+ runs-on: ubuntu-latest
21
+ env:
22
+ CI: true
23
+ steps:
24
+ - uses: actions/checkout@master
25
+ - uses: ruby/setup-ruby@v1
26
+ with:
27
+ bundler-cache: true
28
+ ruby-version: ${{ matrix.ruby }}
29
+ - name: Test
30
+ run: |
31
+ bundle exec rake test
32
+ bundle exec rake stree:check
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ test.erb
data/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.0.1] - 2023-05-25
10
+
11
+ ### Added
12
+
13
+ - 🎉 First version based on syntax_tree-xml 🎉
14
+
15
+ [unreleased]: https://github.com/davidwessman/syntax_tree-erb/compare/v0.1.0...HEAD
16
+ [0.0.1]: https://github.com/davidwessman/syntax_tree-erb/compare/b280a...v0.1.0
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ syntax_tree-erb (0.0.1)
5
+ prettier_print (>= 1.2.0)
6
+ syntax_tree (>= 6.1.1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ docile (1.4.0)
12
+ minitest (5.18.0)
13
+ prettier_print (1.2.1)
14
+ rake (13.0.6)
15
+ simplecov (0.22.0)
16
+ docile (~> 1.1)
17
+ simplecov-html (~> 0.11)
18
+ simplecov_json_formatter (~> 0.1)
19
+ simplecov-html (0.12.3)
20
+ simplecov_json_formatter (0.1.4)
21
+ syntax_tree (6.1.1)
22
+ prettier_print (>= 1.2.0)
23
+
24
+ PLATFORMS
25
+ arm64-darwin-21
26
+ x86_64-darwin-21
27
+ x86_64-darwin-22
28
+ x86_64-linux
29
+
30
+ DEPENDENCIES
31
+ bundler
32
+ minitest
33
+ rake
34
+ simplecov
35
+ syntax_tree-erb!
36
+
37
+ BUNDLED WITH
38
+ 2.4.1
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022-present Kevin Newton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # SyntaxTree::ERB
2
+
3
+ [![Build Status](https://github.com/davidwessman/syntax_tree-erb/actions/workflows/main.yml/badge.svg)](https://github.com/davidwessman/syntax_tree-erb/actions/workflows/main.yml)
4
+
5
+ [Syntax Tree](https://github.com/ruby-syntax-tree/syntax_tree) support for ERB.
6
+
7
+ Currently handles
8
+
9
+ - ERB
10
+ - Tags with and without output
11
+ - Tags inside strings
12
+ - `if`, `elsif`, `else` and `unless` statements
13
+ - blocks
14
+ - comments
15
+ - Formatting of the ruby-code is done by `syntax_tree`
16
+ - HTML
17
+ - Tags with attributes
18
+ - Tags with and without closing tags
19
+ - Comments
20
+ - Vue
21
+ - Attributes, events and slots using `:`, `@` and `#` respectively
22
+ - Text output
23
+
24
+ ## Unhandled cases
25
+
26
+ - Please add to this pinned issue (https://github.com/davidwessman/syntax_tree-erb/issues/28) or create a separate issue if you encounter formatting or parsing errors.
27
+
28
+ ## Installation
29
+
30
+ Add this line to your application's Gemfile:
31
+
32
+ ```ruby
33
+ gem "w_syntax_tree-erb", "~> 0.9", require: false
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ```sh
39
+ bundle exec stree --plugins=erb "./**/*.html.erb"
40
+ ```
41
+
42
+ From code:
43
+
44
+ ```ruby
45
+ require "syntax_tree/erb"
46
+
47
+ pp SyntaxTree::ERB.parse(source) # print out the AST
48
+ puts SyntaxTree::ERB.format(source) # format the AST
49
+ ```
50
+
51
+ ## List all parsing errors
52
+
53
+ In order to get a list of all parsing errors (which needs to be fixed before the formatting works), this script can be used:
54
+
55
+ ```ruby
56
+ #!/bin/ruby
57
+
58
+ require "syntax_tree/erb"
59
+
60
+ failures = []
61
+
62
+ Dir
63
+ .glob("./app/**/*.html.erb")
64
+ .each do |file|
65
+ puts("Processing #{file}")
66
+ begin
67
+ source = SyntaxTree::ERB.read(file)
68
+ SyntaxTree::ERB.parse(source)
69
+ SyntaxTree::ERB.format(source)
70
+ rescue => exception
71
+ failures << { file: file, message: exception.message }
72
+ end
73
+ end
74
+
75
+ puts failures
76
+ ```
77
+
78
+ ## Contributing
79
+
80
+ Bug reports and pull requests are welcome on GitHub at https://github.com/davidwessman/syntax_tree-erb.
81
+
82
+ ## License
83
+
84
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+ require "syntax_tree/rake_tasks"
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << "test"
9
+ t.libs << "lib"
10
+ t.test_files = FileList["test/**/*_test.rb"]
11
+ end
12
+
13
+ SyntaxTree::Rake::CheckTask.new
14
+ SyntaxTree::Rake::WriteTask.new
15
+
16
+ task default: :test
@@ -0,0 +1,20 @@
1
+ #!/bin/ruby
2
+
3
+ require "syntax_tree/erb"
4
+
5
+ failures = []
6
+
7
+ Dir
8
+ .glob("./app/**/*.html.erb")
9
+ .each do |file|
10
+ puts("Processing #{file}")
11
+ begin
12
+ source = SyntaxTree::ERB.read(file)
13
+ SyntaxTree::ERB.parse(source)
14
+ SyntaxTree::ERB.format(source)
15
+ rescue => exception
16
+ failures << { file: file, message: exception.message }
17
+ end
18
+ end
19
+
20
+ puts failures
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SyntaxTree
4
+ module ERB
5
+ class Format < Visitor
6
+ attr_reader :q
7
+
8
+ def initialize(q)
9
+ @q = q
10
+ end
11
+
12
+ # Visit a Token node.
13
+ def visit_token(node)
14
+ q.text(node.value.strip)
15
+ end
16
+
17
+ # Visit a Document node.
18
+ def visit_document(node)
19
+ child_nodes = node.child_nodes.sort_by(&:location)
20
+
21
+ q.seplist(child_nodes, -> { q.breakable(force: true) }) do |child_node|
22
+ visit(child_node)
23
+ end
24
+
25
+ q.breakable(force: true)
26
+ end
27
+
28
+ def visit_block(node)
29
+ visit(node.opening)
30
+
31
+ if node.elements.any?
32
+ q.indent do
33
+ q.breakable("")
34
+ q.seplist(
35
+ node.elements,
36
+ -> { q.breakable(force: true) }
37
+ ) { |child_node| visit(child_node) }
38
+ end
39
+ end
40
+
41
+ if node.closing
42
+ q.breakable("")
43
+ visit(node.closing)
44
+ end
45
+ end
46
+
47
+ def visit_html(node)
48
+ visit_block(node)
49
+ end
50
+
51
+ def visit_erb_block(node)
52
+ visit_block(node)
53
+ end
54
+
55
+ def visit_erb_if(node)
56
+ visit_block(node)
57
+ end
58
+
59
+ def visit_erb_elsif(node)
60
+ visit_block(node)
61
+ end
62
+
63
+ def visit_erb_else(node)
64
+ visit_block(node)
65
+ end
66
+
67
+ def visit_erb_case(node)
68
+ visit_block(node)
69
+ end
70
+
71
+ def visit_erb_case_when(node)
72
+ visit_block(node)
73
+ end
74
+
75
+ # Visit an ErbNode node.
76
+ def visit_erb(node)
77
+ visit(node.opening_tag)
78
+
79
+ if node.keyword
80
+ q.text(" ")
81
+ visit(node.keyword)
82
+ end
83
+
84
+ visit(node.content)
85
+
86
+ visit(node.closing_tag)
87
+ end
88
+
89
+ def visit_erb_do_close(node)
90
+ visit(node.closing)
91
+ end
92
+
93
+ def visit_erb_close(node)
94
+ visit(node.closing)
95
+ end
96
+
97
+ # Visit an ErbEnd node.
98
+ def visit_erb_end(node)
99
+ visit(node.opening_tag)
100
+ q.text(" ")
101
+ visit(node.keyword)
102
+ q.text(" ")
103
+ visit(node.closing_tag)
104
+ end
105
+
106
+ def visit_erb_content(node)
107
+ rows =
108
+ if node.value.is_a?(String)
109
+ node.value.split("\n")
110
+ else
111
+ formatter =
112
+ SyntaxTree::Formatter.new("", [], erb_print_width(node.value))
113
+ formatter.format(node.value.statements)
114
+ formatter.flush
115
+ formatter.output.join.split("\n")
116
+ end
117
+
118
+ if rows.size > 1
119
+ q.group do
120
+ q.text(" ")
121
+ q.seplist(rows, -> { q.breakable(" ") }) { |row| q.text(row) }
122
+ q.text(" ")
123
+ end
124
+ elsif rows.size == 1
125
+ q.text(" ")
126
+ q.text(rows.first)
127
+ q.text(" ")
128
+ else
129
+ q.text(" ")
130
+ end
131
+ end
132
+
133
+ # Visit an HtmlNode::OpeningTag node.
134
+ def visit_opening_tag(node)
135
+ q.group do
136
+ visit(node.opening)
137
+ visit(node.name)
138
+
139
+ if node.attributes.any?
140
+ q.indent do
141
+ q.breakable
142
+ q.seplist(node.attributes, -> { q.breakable }) do |child_node|
143
+ visit(child_node)
144
+ end
145
+ end
146
+ end
147
+
148
+ q.breakable(node.closing.value == "/>" ? " " : "")
149
+ visit(node.closing)
150
+ end
151
+ end
152
+
153
+ # Visit an HtmlNode::ClosingTag node.
154
+ def visit_closing_tag(node)
155
+ q.group do
156
+ visit(node.opening)
157
+ visit(node.name)
158
+ visit(node.closing)
159
+ end
160
+ end
161
+
162
+ # Visit an Attribute node.
163
+ def visit_attribute(node)
164
+ q.group do
165
+ visit(node.key)
166
+ visit(node.equals)
167
+ visit(node.value)
168
+ end
169
+ end
170
+
171
+ # Visit a HtmlString node.
172
+ def visit_html_string(node)
173
+ q.group do
174
+ q.text("\"")
175
+ q.seplist(node.contents, -> { "" }) { |child_node| visit(child_node) }
176
+ q.text("\"")
177
+ end
178
+ end
179
+
180
+ def visit_html_comment(node)
181
+ visit(node.token)
182
+ end
183
+
184
+ # Visit a CharData node.
185
+ def visit_char_data(node)
186
+ lines = node.value.value.strip.split("\n")
187
+
188
+ if lines.size > 0
189
+ q.seplist(lines, -> { q.breakable(indent: false) }) do |line|
190
+ q.text(line)
191
+ end
192
+ end
193
+ end
194
+
195
+ # Visit a Doctype node.
196
+ def visit_doctype(node)
197
+ q.group do
198
+ visit(node.opening)
199
+ q.text(" ")
200
+ visit(node.name)
201
+
202
+ visit(node.closing)
203
+ end
204
+ end
205
+
206
+ def erb_print_width(syntax_tree)
207
+ statements = syntax_tree.statements.body
208
+ # Set the width to maximum if we have an IfNode or IfOp,
209
+ # we cannot format them purely with SyntaxTree because the ERB-syntax will be unparseable.
210
+ if statements.any? { |node| check_for_if_statement(node) }
211
+ 999_999
212
+ else
213
+ SyntaxTree::ERB::MAX_WIDTH
214
+ end
215
+ end
216
+
217
+ def check_for_if_statement(node)
218
+ return false if node.nil?
219
+
220
+ if node.is_a?(SyntaxTree::IfNode) || node.is_a?(SyntaxTree::IfOp)
221
+ return true
222
+ end
223
+
224
+ node.child_nodes.any? do |child_node|
225
+ check_for_if_statement(child_node)
226
+ end
227
+ end
228
+ end
229
+ end
230
+ end