htmlbeautifier 1.2.1 → 1.4.1

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
- SHA1:
3
- metadata.gz: 657518afa5b160297e6b490855c02526f48ad144
4
- data.tar.gz: bfdfbca49d50e276f2314a893ecc0b70b6392115
2
+ SHA256:
3
+ metadata.gz: 4ad32fe5c137d828c711e50642ff3b00af14e3b8cdf18105506c1149de2c6cde
4
+ data.tar.gz: d42bcce139d8a3e9a96f73735fbb068044f1f43c8d9951c89cd642bf4e996bef
5
5
  SHA512:
6
- metadata.gz: 9a96bc60da54b69d972b80d5faf47a547dc7ab403e19c4ab6685dce4896a71a76bf9b7f49ce3b2c8039d8f0b661fe5c9b21c740116ac49e7e49313a11bd0a903
7
- data.tar.gz: cfe7bb9dceaad5997e65ba6fdc397a0ce5a30ee3012e295c1a1fdc2dedcf3a34661d662b92c83ec28ea4d675f99c82a05c7a2924f8f3f13d32f12db094d82fb8
6
+ metadata.gz: 89dc1309a74d24da1f91ec626e3a0291918c9e0ef64370d10893ee30c961bcb788efa2bc99fbdb89af96d643cf418333b6b5b6eb3ec3e54dfb164398d0cdf0b5
7
+ data.tar.gz: accce8738133c66d40ddcbdc21aee322f7b68e2d9bcca81102fbecc680a5a3b021d8911587e31e0a1963f3cae166e2f436a76800feebde59da411d96cb5fe628
data/bin/htmlbeautifier CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  require "htmlbeautifier"
3
5
  require "optparse"
4
6
  require "fileutils"
7
+ require "stringio"
5
8
 
6
9
  def beautify(name, input, output, options)
7
10
  output.puts HtmlBeautifier.beautify(input, options)
8
- rescue => e
11
+ rescue StandardError => e
9
12
  raise "Error parsing #{name}: #{e}"
10
13
  end
11
14
 
@@ -14,18 +17,18 @@ executable = File.basename(__FILE__)
14
17
  options = { indent: " " }
15
18
  parser = OptionParser.new do |opts|
16
19
  opts.banner = "Usage: #{executable} [options] [file ...]"
17
- opts.separator <<END
20
+ opts.separator <<~STRING
18
21
 
19
- #{executable} has two modes of operation:
22
+ #{executable} has two modes of operation:
20
23
 
21
- 1. If no files are listed, it will read from standard input and write to
22
- standard output.
23
- 2. If files are listed, it will modify each file in place, overwriting it
24
- with the beautified output.
24
+ 1. If no files are listed, it will read from standard input and write to
25
+ standard output.
26
+ 2. If files are listed, it will modify each file in place, overwriting it
27
+ with the beautified output.
25
28
 
26
- The following options are available:
29
+ The following options are available:
27
30
 
28
- END
31
+ STRING
29
32
  opts.on(
30
33
  "-t", "--tab-stops NUMBER", Integer,
31
34
  "Set number of spaces per indent (default #{options[:tab_stops]})"
@@ -50,6 +53,26 @@ END
50
53
  ) do |num|
51
54
  options[:stop_on_errors] = num
52
55
  end
56
+ opts.on(
57
+ "-b", "--keep-blank-lines NUMBER", Integer,
58
+ "Set number of consecutive blank lines"
59
+ ) do |num|
60
+ options[:keep_blank_lines] = num
61
+ end
62
+ opts.on(
63
+ "-l", "--lint-only",
64
+ "Lint only, error on files which would be modified",
65
+ "This is not available when reading from standard input"
66
+ ) do |num|
67
+ options[:lint_only] = num
68
+ end
69
+ opts.on(
70
+ "-v", "--version",
71
+ "Display version and exit"
72
+ ) do
73
+ puts HtmlBeautifier::VERSION::STRING
74
+ exit
75
+ end
53
76
  opts.on(
54
77
  "-h", "--help",
55
78
  "Display this help message and exit"
@@ -58,16 +81,34 @@ END
58
81
  exit
59
82
  end
60
83
  end
84
+
61
85
  parser.parse!
62
86
 
63
87
  if ARGV.any?
88
+ failures = []
64
89
  ARGV.each do |path|
65
90
  input = File.read(path)
66
- temppath = path + ".tmp"
67
- File.open(temppath, "w") do |output|
91
+ if options[:lint_only]
92
+ output = StringIO.new
68
93
  beautify path, input, output, options
94
+ failures << path unless input == output.string
95
+ else
96
+ temppath = "#{path}.tmp"
97
+ File.open(temppath, "w") do |file|
98
+ beautify path, input, file, options
99
+ end
100
+ FileUtils.mv temppath, path
69
101
  end
70
- FileUtils.mv temppath, path
102
+ end
103
+ unless failures.empty?
104
+ relative_paths = failures.map { |path|
105
+ Pathname.new(path).relative_path_from Dir.pwd
106
+ }
107
+ $stderr.puts [
108
+ "Lint failed - files would be modified:",
109
+ *relative_paths
110
+ ].join("\n")
111
+ exit 1
71
112
  end
72
113
  else
73
114
  beautify "standard input", $stdin.read, $stdout, options
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "htmlbeautifier/parser"
2
4
  require "htmlbeautifier/ruby_indenter"
3
5
 
@@ -6,14 +8,16 @@ module HtmlBeautifier
6
8
  DEFAULT_OPTIONS = {
7
9
  indent: " ",
8
10
  initial_level: 0,
9
- stop_on_errors: false
10
- }
11
+ stop_on_errors: false,
12
+ keep_blank_lines: 0
13
+ }.freeze
11
14
 
12
15
  def initialize(output, options = {})
13
16
  options = DEFAULT_OPTIONS.merge(options)
14
17
  @tab = options[:indent]
15
18
  @stop_on_errors = options[:stop_on_errors]
16
19
  @level = options[:initial_level]
20
+ @keep_blank_lines = options[:keep_blank_lines]
17
21
  @new_line = false
18
22
  @empty = true
19
23
  @ie_cc_levels = []
@@ -25,6 +29,7 @@ module HtmlBeautifier
25
29
 
26
30
  def error(text)
27
31
  return unless @stop_on_errors
32
+
28
33
  raise text
29
34
  end
30
35
 
@@ -38,14 +43,15 @@ module HtmlBeautifier
38
43
  end
39
44
 
40
45
  def emit(*strings)
46
+ strings_join = strings.join("")
41
47
  @output << "\n" if @new_line && !@empty
42
- @output << (@tab * @level) if @new_line
43
- @output << strings.join("")
48
+ @output << (@tab * @level) if @new_line && !strings_join.strip.empty?
49
+ @output << strings_join
44
50
  @new_line = false
45
51
  @empty = false
46
52
  end
47
53
 
48
- def new_line(*)
54
+ def new_line
49
55
  @new_line = true
50
56
  end
51
57
 
@@ -64,7 +70,7 @@ module HtmlBeautifier
64
70
 
65
71
  def emit_reindented_block_content(code)
66
72
  lines = code.strip.split(%r{\n})
67
- indentation = lines.first[%r{^\s+}]
73
+ indentation = foreign_block_indentation(code)
68
74
 
69
75
  indent
70
76
  new_line
@@ -75,55 +81,63 @@ module HtmlBeautifier
75
81
  outdent
76
82
  end
77
83
 
84
+ def foreign_block_indentation(code)
85
+ code.split(%r{\n}).find { |ln| !ln.strip.empty? }[%r{^\s+}]
86
+ end
87
+
78
88
  def preformatted_block(opening, content, closing)
79
89
  new_line
80
90
  emit opening, content, closing
81
91
  new_line
82
92
  end
83
93
 
84
- def standalone_element(e)
85
- emit e
86
- new_line if e =~ %r{^<br[^\w]}
94
+ def standalone_element(elem)
95
+ emit elem
96
+ new_line if elem =~ %r{^<br[^\w]}
87
97
  end
88
98
 
89
- def close_element(e)
99
+ def close_element(elem)
90
100
  outdent
91
- emit e
101
+ emit elem
92
102
  end
93
103
 
94
- def close_block_element(e)
95
- close_element e
104
+ def close_block_element(elem)
105
+ close_element elem
96
106
  new_line
97
107
  end
98
108
 
99
- def open_element(e)
100
- emit e
109
+ def open_element(elem)
110
+ emit elem
101
111
  indent
102
112
  end
103
113
 
104
- def open_block_element(e)
114
+ def open_block_element(elem)
105
115
  new_line
106
- open_element e
116
+ open_element elem
107
117
  end
108
118
 
109
- def close_ie_cc(e)
119
+ def close_ie_cc(elem)
110
120
  if @ie_cc_levels.empty?
111
121
  error "Unclosed conditional comment"
112
122
  else
113
123
  @level = @ie_cc_levels.pop
114
124
  end
115
- emit e
125
+ emit elem
116
126
  end
117
127
 
118
- def open_ie_cc(e)
119
- emit e
128
+ def open_ie_cc(elem)
129
+ emit elem
120
130
  @ie_cc_levels.push @level
121
131
  indent
122
132
  end
123
133
 
124
- def text(t)
125
- emit t.chomp
126
- new_line if t.end_with?("\n")
134
+ def new_lines(*content)
135
+ blank_lines = content.first.scan(%r{\n}).count - 1
136
+ blank_lines = [blank_lines, @keep_blank_lines].min
137
+ @output << ("\n" * blank_lines)
138
+ new_line
127
139
  end
140
+
141
+ alias_method :text, :emit
128
142
  end
129
143
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "htmlbeautifier/parser"
2
4
 
3
5
  module HtmlBeautifier
@@ -35,20 +37,21 @@ module HtmlBeautifier
35
37
  :preformatted_block],
36
38
  [%r{<#{HTML_VOID_ELEMENTS}(?: #{ELEMENT_CONTENT})?/?>}om,
37
39
  :standalone_element],
38
- [%r{<\w+(?: #{ELEMENT_CONTENT})?/>}om,
39
- :standalone_element],
40
40
  [%r{</#{HTML_BLOCK_ELEMENTS}>}om,
41
41
  :close_block_element],
42
42
  [%r{<#{HTML_BLOCK_ELEMENTS}(?: #{ELEMENT_CONTENT})?>}om,
43
43
  :open_block_element],
44
44
  [%r{</#{ELEMENT_CONTENT}>}om,
45
45
  :close_element],
46
- [%r{<#{ELEMENT_CONTENT}>}om,
46
+ [%r{<#{ELEMENT_CONTENT}[^/]>}om,
47
47
  :open_element],
48
- [%r{\s*\r?\n\s*}om,
49
- :new_line],
50
- [%r{[^<]+},
51
- :text]]
48
+ [%r{<[\w\-]+(?: #{ELEMENT_CONTENT})?/>}om,
49
+ :standalone_element],
50
+ [%r{(\s*\r?\n\s*)+}om,
51
+ :new_lines],
52
+ [%r{[^<\n]+},
53
+ :text]
54
+ ].freeze
52
55
 
53
56
  def initialize
54
57
  super do |p|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "strscan"
2
4
 
3
5
  module HtmlBeautifier
@@ -29,13 +31,15 @@ module HtmlBeautifier
29
31
  def dispatch(receiver)
30
32
  _, method = @maps.find { |pattern, _| @scanner.scan(pattern) }
31
33
  raise "Unmatched sequence" unless method
34
+
32
35
  receiver.__send__(method, *extract_params(@scanner))
33
- rescue => ex
34
- raise "#{ex.message} on line #{source_line_number}"
36
+ rescue StandardError => e
37
+ raise "#{e.message} on line #{source_line_number}"
35
38
  end
36
39
 
37
40
  def extract_params(scanner)
38
41
  return [scanner[0]] unless scanner[1]
42
+
39
43
  params = []
40
44
  i = 1
41
45
  while scanner[i]
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HtmlBeautifier
2
4
  class RubyIndenter
3
- INDENT_KEYWORDS = %w[ if elsif else unless while until begin for ]
4
- OUTDENT_KEYWORDS = %w[ elsif else end ]
5
- RUBY_INDENT = %r{
5
+ INDENT_KEYWORDS = %w[if elsif else unless while until begin for].freeze
6
+ OUTDENT_KEYWORDS = %w[elsif else end].freeze
7
+ RUBY_INDENT = %r{
6
8
  ^ ( #{INDENT_KEYWORDS.join("|")} )\b
7
- | \b ( do | \{ ) ( \s* \| [^\|]+ \| )? $
9
+ | \b ( do | \{ ) ( \s* \| [^|]+ \| )? $
8
10
  }xo
9
11
  RUBY_OUTDENT = %r{ ^ ( #{OUTDENT_KEYWORDS.join("|")} | \} ) \b }xo
10
12
 
@@ -1,7 +1,9 @@
1
- module HtmlBeautifier #:nodoc:
2
- module VERSION #:nodoc:
1
+ # frozen_string_literal: true
2
+
3
+ module HtmlBeautifier # :nodoc:
4
+ module VERSION # :nodoc:
3
5
  MAJOR = 1
4
- MINOR = 2
6
+ MINOR = 4
5
7
  TINY = 1
6
8
 
7
9
  STRING = [MAJOR, MINOR, TINY].join(".")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "htmlbeautifier/builder"
2
4
  require "htmlbeautifier/html_parser"
3
5
  require "htmlbeautifier/version"
@@ -15,12 +17,14 @@ module HtmlBeautifier
15
17
  # is false, i.e. continue to process the rest of the document.
16
18
  # initial_level - The entire output will be indented by this number of steps.
17
19
  # Default is 0.
20
+ # keep_blank_lines - an integer for the number of consecutive empty lines
21
+ # to keep in output.
18
22
  #
19
23
  def self.beautify(html, options = {})
20
24
  if options[:tab_stops]
21
25
  options[:indent] = " " * options[:tab_stops]
22
26
  end
23
- "".tap { |output|
27
+ String.new.tap { |output|
24
28
  HtmlParser.new.scan html.to_s, Builder.new(output, options)
25
29
  }
26
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: htmlbeautifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Battley
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-22 00:00:00.000000000 Z
11
+ date: 2021-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '13'
20
20
  type: :development
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: '0'
26
+ version: '13'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +44,42 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.30.0
47
+ version: '1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.30.0
54
+ version: '1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.6'
55
83
  description: A normaliser/beautifier for HTML that also understands embedded Ruby.
56
84
  email: pbattley@gmail.com
57
85
  executables:
@@ -80,15 +108,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
108
  requirements:
81
109
  - - ">="
82
110
  - !ruby/object:Gem::Version
83
- version: 1.9.2
111
+ version: 2.6.0
84
112
  required_rubygems_version: !ruby/object:Gem::Requirement
85
113
  requirements:
86
114
  - - ">="
87
115
  - !ruby/object:Gem::Version
88
116
  version: '0'
89
117
  requirements: []
90
- rubyforge_project:
91
- rubygems_version: 2.5.1
118
+ rubygems_version: 3.2.22
92
119
  signing_key:
93
120
  specification_version: 4
94
121
  summary: HTML/ERB beautifier