erb-formatter 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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.