erb-formatter 0.4.2 → 0.5.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/README.md +19 -4
- data/erb-formatter.gemspec +1 -1
- data/lib/erb/formatter/command_line.rb +6 -2
- data/lib/erb/formatter/version.rb +1 -1
- data/lib/erb/formatter.rb +41 -64
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ba78d2f06a198fd4f9af049e11a4f0ec92fcfa56e16688eaa65b3ea9253320ca
|
4
|
+
data.tar.gz: 5d06c40737f856c445cf70fd530639e8876c60dad08d9fdc91acc12e42c9e086
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4997b2e942b1fe2ed3a0bf0b0e828ba7565090bf781508accd4d64540e90b986d7d0414534e066cd149d56d8d208342dd20c6ac1ba749498e03b080d4e799a10
|
7
|
+
data.tar.gz: 59901e642196b0538e88379384d655a8f6a174007ba30fa7829b25db829cedbc8bcb94ef80e58b026e6223cc166fa442db798c84a18d38baecf5c36d63cee3cf
|
data/README.md
CHANGED
@@ -33,13 +33,18 @@ Or install it yourself as:
|
|
33
33
|
|
34
34
|
## Usage
|
35
35
|
|
36
|
+
### From [Visual Studio Code](https://code.visualstudio.com)
|
37
|
+
|
38
|
+
Just install the [Ruby ERB::Formatter 🪜](https://marketplace.visualstudio.com/items?itemName=elia.erb-formatter) extension
|
39
|
+
and follow the setup instructions there.
|
40
|
+
|
36
41
|
### From the command line
|
37
42
|
|
38
43
|
Update files in-place:
|
39
44
|
|
40
45
|
$ erb-format app/views/**/*.html.erb --write
|
41
46
|
|
42
|
-
or use stdin/stdout (useful for editor integrations):
|
47
|
+
or use stdin/stdout (useful for editor integrations):
|
43
48
|
|
44
49
|
$ echo "<div > asdf <% if 123%> <%='foobar'%> <%end-%> </div>" | erb-format --stdin
|
45
50
|
<div>
|
@@ -51,7 +56,7 @@ or use stdin/stdout (useful for editor integrations):
|
|
51
56
|
|
52
57
|
Check out `erb-format --help` for more options.
|
53
58
|
|
54
|
-
### From Ruby
|
59
|
+
### From [Ruby](https://www.ruby-lang.org/en/)
|
55
60
|
|
56
61
|
```ruby
|
57
62
|
require 'erb/formatter'
|
@@ -76,7 +81,7 @@ ERB
|
|
76
81
|
# </div>
|
77
82
|
```
|
78
83
|
|
79
|
-
### With `lint-staged`
|
84
|
+
### With [`lint-staged`](https://github.com/okonet/lint-staged#readme)
|
80
85
|
|
81
86
|
Add the gem to your gemfile and the following to your `package.json`:
|
82
87
|
|
@@ -87,7 +92,7 @@ Add the gem to your gemfile and the following to your `package.json`:
|
|
87
92
|
}
|
88
93
|
```
|
89
94
|
|
90
|
-
### As a TextMate
|
95
|
+
### As a [TextMate](http://macromates.com) command
|
91
96
|
|
92
97
|
Create a command with the following settings:
|
93
98
|
|
@@ -104,6 +109,16 @@ cd "$TM_PROJECT_DIRECTORY"
|
|
104
109
|
bundle exec erb-format --stdin-filename "$TM_FILEPATH" < /dev/stdin 2> /dev/stdout
|
105
110
|
```
|
106
111
|
|
112
|
+
### With [(Neo)VIM ALE](https://github.com/dense-analysis/ale)
|
113
|
+
|
114
|
+
Enable `erb-formatter` as a fixer in the ALE config:
|
115
|
+
|
116
|
+
```vim
|
117
|
+
let g:ale_fixers = {
|
118
|
+
\ 'eruby': ['erb-formatter'],
|
119
|
+
\}
|
120
|
+
```
|
121
|
+
|
107
122
|
## Development
|
108
123
|
|
109
124
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/erb-formatter.gemspec
CHANGED
@@ -10,7 +10,7 @@ class ERB::Formatter::CommandLine
|
|
10
10
|
@argv = argv.dup
|
11
11
|
@stdin = stdin
|
12
12
|
|
13
|
-
@write, @filename, @read_stdin, @code = nil
|
13
|
+
@write, @filename, @read_stdin, @code, @single_class_per_line = nil
|
14
14
|
|
15
15
|
OptionParser.new do |parser|
|
16
16
|
parser.banner = "Usage: #{$0} FILENAME... --write"
|
@@ -37,6 +37,10 @@ class ERB::Formatter::CommandLine
|
|
37
37
|
@width = value
|
38
38
|
end
|
39
39
|
|
40
|
+
parser.on("--single-class-per-line", "Print each class on a separate line") do |value|
|
41
|
+
@single_class_per_line = value
|
42
|
+
end
|
43
|
+
|
40
44
|
parser.on("--[no-]debug", "Enable debug mode") do |value|
|
41
45
|
$DEBUG = value
|
42
46
|
end
|
@@ -77,7 +81,7 @@ class ERB::Formatter::CommandLine
|
|
77
81
|
if ignore_list.should_ignore_file? filename
|
78
82
|
print code unless write
|
79
83
|
else
|
80
|
-
html = ERB::Formatter.new(code, filename: filename, line_width: @width || 80)
|
84
|
+
html = ERB::Formatter.new(code, filename: filename, line_width: @width || 80, single_class_per_line: @single_class_per_line)
|
81
85
|
|
82
86
|
if write
|
83
87
|
File.write(filename, html)
|
data/lib/erb/formatter.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
|
3
3
|
require 'pp'
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'securerandom'
|
4
|
+
require 'erb'
|
5
|
+
require 'yaml'
|
7
6
|
require 'strscan'
|
8
7
|
require 'stringio'
|
8
|
+
require 'securerandom'
|
9
9
|
require 'erb/formatter/version'
|
10
10
|
|
11
11
|
require 'syntax_tree'
|
@@ -38,8 +38,6 @@ class ERB::Formatter
|
|
38
38
|
|
39
39
|
ERB_TAG = %r{(<%(?:==|=|-|))\s*(.*?)\s*(-?%>)}m
|
40
40
|
ERB_PLACEHOLDER = %r{erb[a-z0-9]+tag}
|
41
|
-
ERB_END = %r{(<%-?)\s*(end)\s*(-?%>)}
|
42
|
-
ERB_ELSE = %r{(<%-?)\s*(else|elsif\b.*)\s*(-?%>)}
|
43
41
|
|
44
42
|
TAG_NAME = /[a-z0-9_:-]+/
|
45
43
|
TAG_NAME_ONLY = /\A#{TAG_NAME}\z/
|
@@ -49,20 +47,15 @@ class ERB::Formatter
|
|
49
47
|
|
50
48
|
SELF_CLOSING_TAG = /\A(area|base|br|col|command|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)\z/i
|
51
49
|
|
52
|
-
|
50
|
+
RUBY_OPEN_BLOCK = ->(code) do
|
53
51
|
# is nil when the parsing is broken, meaning it's an open expression
|
54
52
|
Ripper.sexp(code).nil?
|
55
53
|
end.freeze
|
54
|
+
RUBY_CLOSE_BLOCK = /\Aend\z/
|
55
|
+
RUBY_REOPEN_BLOCK = /\A(else|elsif\b(.*)|when\b(.*))\z/
|
56
56
|
|
57
57
|
RUBOCOP_STDIN_MARKER = "===================="
|
58
58
|
|
59
|
-
# Override the max line length to account from already indented ERB
|
60
|
-
module RubocopForcedMaxLineLength
|
61
|
-
def max
|
62
|
-
Thread.current['RuboCop::Cop::Layout::LineLength#max'] || super
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
59
|
module DebugShovel
|
67
60
|
def <<(string)
|
68
61
|
puts "ADDING: #{string.inspect} FROM:\n #{caller(1, 5).join("\n ")}"
|
@@ -74,13 +67,14 @@ class ERB::Formatter
|
|
74
67
|
new(source, filename: filename).html
|
75
68
|
end
|
76
69
|
|
77
|
-
def initialize(source, line_width: 80, filename: nil, debug: $DEBUG)
|
70
|
+
def initialize(source, line_width: 80, single_class_per_line: false, filename: nil, debug: $DEBUG)
|
78
71
|
@original_source = source
|
79
72
|
@filename = filename || '(erb)'
|
80
73
|
@line_width = line_width
|
81
74
|
@source = remove_front_matter source.dup
|
82
75
|
@html = +""
|
83
76
|
@debug = debug
|
77
|
+
@single_class_per_line = single_class_per_line
|
84
78
|
|
85
79
|
html.extend DebugShovel if @debug
|
86
80
|
|
@@ -104,10 +98,13 @@ class ERB::Formatter
|
|
104
98
|
end
|
105
99
|
|
106
100
|
def remove_front_matter(source)
|
107
|
-
source.
|
108
|
-
|
109
|
-
|
110
|
-
|
101
|
+
return source unless source.start_with?("---\n")
|
102
|
+
|
103
|
+
first_body_line = YAML.parse(source).children.first.end_line + 1
|
104
|
+
lines = source.lines
|
105
|
+
|
106
|
+
@front_matter = lines[0...first_body_line].join
|
107
|
+
lines[first_body_line..].join
|
111
108
|
end
|
112
109
|
|
113
110
|
attr_accessor \
|
@@ -124,6 +121,7 @@ class ERB::Formatter
|
|
124
121
|
|
125
122
|
attr_html = ""
|
126
123
|
tag_stack_push(['attr='], attrs)
|
124
|
+
|
127
125
|
attrs.scan(ATTR).flatten.each do |attr|
|
128
126
|
attr.strip!
|
129
127
|
full_attr = indented(attr)
|
@@ -132,59 +130,38 @@ class ERB::Formatter
|
|
132
130
|
if full_attr.size > line_width && MULTILINE_ATTR_NAMES.include?(name) && attr.match?(QUOTED_ATTR)
|
133
131
|
attr_html << indented("#{name}=#{value[0]}")
|
134
132
|
tag_stack_push('attr"', value)
|
135
|
-
|
136
|
-
|
133
|
+
|
134
|
+
value_parts = value[1...-1].strip.split(/\s+/)
|
135
|
+
|
136
|
+
if !@single_class_per_line && name == 'class'
|
137
|
+
line = value_parts.shift
|
138
|
+
value_parts.each do |value_part|
|
139
|
+
if (line.size + value_part.size + 1) <= line_width
|
140
|
+
line << " #{value_part}"
|
141
|
+
else
|
142
|
+
attr_html << indented(line)
|
143
|
+
line = value_part
|
144
|
+
end
|
145
|
+
end
|
146
|
+
attr_html << indented(line) if line
|
147
|
+
else
|
148
|
+
value_parts.each do |value_part|
|
149
|
+
attr_html << indented(value_part)
|
150
|
+
end
|
137
151
|
end
|
152
|
+
|
138
153
|
tag_stack_pop('attr"', value)
|
139
154
|
attr_html << indented(value[-1])
|
140
155
|
else
|
141
156
|
attr_html << full_attr
|
142
157
|
end
|
143
158
|
end
|
159
|
+
|
144
160
|
tag_stack_pop(['attr='], attrs)
|
145
161
|
attr_html << indented("")
|
146
162
|
attr_html
|
147
163
|
end
|
148
164
|
|
149
|
-
def format_erb_attributes(string)
|
150
|
-
erb_scanner = StringScanner.new(string.to_s)
|
151
|
-
erb_pre_pos = 0
|
152
|
-
until erb_scanner.eos?
|
153
|
-
if erb_scanner.scan_until(erb_tags_regexp)
|
154
|
-
erb_pre_match = erb_scanner.pre_match
|
155
|
-
erb_pre_match = erb_pre_match[erb_pre_pos..]
|
156
|
-
erb_pre_pos = erb_scanner.pos
|
157
|
-
|
158
|
-
erb_code = erb_tags[erb_scanner.captures.first]
|
159
|
-
|
160
|
-
format_attributes(erb_pre_match)
|
161
|
-
|
162
|
-
erb_open, ruby_code, erb_close = ERB_TAG.match(erb_code).captures
|
163
|
-
full_erb_tag = "#{erb_open} #{ruby_code} #{erb_close}"
|
164
|
-
|
165
|
-
case ruby_code
|
166
|
-
when /\Aend\z/
|
167
|
-
tag_stack_pop('%erb%', ruby_code)
|
168
|
-
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
169
|
-
when /\A(else|elsif\b(.*))\z/
|
170
|
-
tag_stack_pop('%erb%', ruby_code)
|
171
|
-
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
172
|
-
tag_stack_push('%erb%', ruby_code)
|
173
|
-
when ERB_OPEN_BLOCK
|
174
|
-
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
175
|
-
tag_stack_push('%erb%', ruby_code)
|
176
|
-
else
|
177
|
-
ruby_code = format_ruby(ruby_code, autoclose: false)
|
178
|
-
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
179
|
-
end
|
180
|
-
else
|
181
|
-
rest = erb_scanner.rest.to_s
|
182
|
-
format_erb_attributes(rest)
|
183
|
-
erb_scanner.terminate
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
165
|
def tag_stack_push(tag_name, code)
|
189
166
|
tag_stack << [tag_name, code]
|
190
167
|
p PUSH: tag_stack if @debug
|
@@ -258,8 +235,8 @@ class ERB::Formatter
|
|
258
235
|
|
259
236
|
def format_ruby(code, autoclose: false)
|
260
237
|
if autoclose
|
261
|
-
code += "\nend" unless
|
262
|
-
code += "\n}" unless
|
238
|
+
code += "\nend" unless RUBY_OPEN_BLOCK["#{code}\nend"]
|
239
|
+
code += "\n}" unless RUBY_OPEN_BLOCK["#{code}\n}"]
|
263
240
|
end
|
264
241
|
p RUBY_IN_: code if @debug
|
265
242
|
|
@@ -303,16 +280,16 @@ class ERB::Formatter
|
|
303
280
|
erb_open << ' ' unless ruby_code.start_with?('#')
|
304
281
|
|
305
282
|
case ruby_code
|
306
|
-
when
|
283
|
+
when RUBY_CLOSE_BLOCK
|
307
284
|
full_erb_tag = "#{erb_open}#{ruby_code} #{erb_close}"
|
308
285
|
tag_stack_pop('%erb%', ruby_code)
|
309
286
|
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
310
|
-
when
|
287
|
+
when RUBY_REOPEN_BLOCK
|
311
288
|
full_erb_tag = "#{erb_open}#{ruby_code} #{erb_close}"
|
312
289
|
tag_stack_pop('%erb%', ruby_code)
|
313
290
|
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
314
291
|
tag_stack_push('%erb%', ruby_code)
|
315
|
-
when
|
292
|
+
when RUBY_OPEN_BLOCK
|
316
293
|
full_erb_tag = "#{erb_open}#{ruby_code} #{erb_close}"
|
317
294
|
html << (erb_pre_match.match?(/\s+\z/) ? indented(full_erb_tag) : full_erb_tag)
|
318
295
|
tag_stack_push('%erb%', ruby_code)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erb-formatter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elia Schito
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: syntax_tree
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6.0'
|
27
27
|
description:
|
28
28
|
email:
|
29
29
|
- elia@schito.me
|
@@ -68,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
requirements: []
|
71
|
-
rubygems_version: 3.
|
71
|
+
rubygems_version: 3.3.23
|
72
72
|
signing_key:
|
73
73
|
specification_version: 4
|
74
74
|
summary: Format ERB files with speed and precision.
|