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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddc79db481ece2c7a1a3c3dedbce6f65f176ad045805125cbd997fdaf5f4fb11
4
- data.tar.gz: e27fe52c37feb8fe80386af2fb0083a5b6398a9319189ec0baec5251db4a1a31
3
+ metadata.gz: ba78d2f06a198fd4f9af049e11a4f0ec92fcfa56e16688eaa65b3ea9253320ca
4
+ data.tar.gz: 5d06c40737f856c445cf70fd530639e8876c60dad08d9fdc91acc12e42c9e086
5
5
  SHA512:
6
- metadata.gz: 3e08e5783a5315111f5bbe0acc0f8d819b7e8b80f0a6626ec6283006441005dcba10526282ea6d331b54e7e6fc56c8a24cecb93c235f11b2394448195cf2f264
7
- data.tar.gz: 5ca38f5fd851e57056a87490d5f668a0fa2a9374e6ff46cf0efe7b6cb39af0dc813e0026cee9bf7fc57f99a86833c5385979e1b0bd8c2d03a7d83f969daf494f
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 plugin
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.
@@ -28,5 +28,5 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ["lib"]
30
30
 
31
- spec.add_dependency "syntax_tree", '~> 5.0'
31
+ spec.add_dependency "syntax_tree", '~> 6.0'
32
32
  end
@@ -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)
@@ -3,5 +3,5 @@
3
3
  require 'erb'
4
4
 
5
5
  class ERB::Formatter
6
- VERSION = "0.4.2"
6
+ VERSION = "0.5.0"
7
7
  end
data/lib/erb/formatter.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  require 'pp'
4
- require "erb"
5
- require "ripper"
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
- ERB_OPEN_BLOCK = ->(code) do
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.sub(/\A---\n[\s\S]*?\n---\n/) do |match|
108
- @front_matter = match
109
- match.gsub(/[^\n]/, ' ')
110
- end
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
- value[1...-1].strip.split(/\s+/).each do |value_part|
136
- attr_html << indented(value_part)
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 ERB_OPEN_BLOCK["#{code}\nend"]
262
- code += "\n}" unless ERB_OPEN_BLOCK["#{code}\n}"]
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 /\Aend\z/
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 /\A(else|elsif\b(.*))\z/
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 ERB_OPEN_BLOCK
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.2
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-02-03 00:00:00.000000000 Z
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: '5.0'
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: '5.0'
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.4.5
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.