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 +5 -5
- data/bin/htmlbeautifier +53 -12
- data/lib/htmlbeautifier/builder.rb +38 -24
- data/lib/htmlbeautifier/html_parser.rb +10 -7
- data/lib/htmlbeautifier/parser.rb +6 -2
- data/lib/htmlbeautifier/ruby_indenter.rb +6 -4
- data/lib/htmlbeautifier/version.rb +5 -3
- data/lib/htmlbeautifier.rb +5 -1
- metadata +36 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4ad32fe5c137d828c711e50642ff3b00af14e3b8cdf18105506c1149de2c6cde
|
4
|
+
data.tar.gz: d42bcce139d8a3e9a96f73735fbb068044f1f43c8d9951c89cd642bf4e996bef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
23
|
-
2. If files are listed, it will modify each file in place, overwriting it
|
24
|
-
|
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
|
-
|
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
|
-
|
67
|
-
|
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
|
-
|
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 <<
|
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 =
|
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(
|
85
|
-
emit
|
86
|
-
new_line if
|
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(
|
99
|
+
def close_element(elem)
|
90
100
|
outdent
|
91
|
-
emit
|
101
|
+
emit elem
|
92
102
|
end
|
93
103
|
|
94
|
-
def close_block_element(
|
95
|
-
close_element
|
104
|
+
def close_block_element(elem)
|
105
|
+
close_element elem
|
96
106
|
new_line
|
97
107
|
end
|
98
108
|
|
99
|
-
def open_element(
|
100
|
-
emit
|
109
|
+
def open_element(elem)
|
110
|
+
emit elem
|
101
111
|
indent
|
102
112
|
end
|
103
113
|
|
104
|
-
def open_block_element(
|
114
|
+
def open_block_element(elem)
|
105
115
|
new_line
|
106
|
-
open_element
|
116
|
+
open_element elem
|
107
117
|
end
|
108
118
|
|
109
|
-
def close_ie_cc(
|
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
|
125
|
+
emit elem
|
116
126
|
end
|
117
127
|
|
118
|
-
def open_ie_cc(
|
119
|
-
emit
|
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
|
125
|
-
|
126
|
-
|
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{\
|
49
|
-
:
|
50
|
-
[%r{
|
51
|
-
:
|
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 =>
|
34
|
-
raise "#{
|
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[
|
4
|
-
OUTDENT_KEYWORDS = %w[
|
5
|
-
RUBY_INDENT
|
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
|
|
data/lib/htmlbeautifier.rb
CHANGED
@@ -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
|
-
|
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.
|
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:
|
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: '
|
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: '
|
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:
|
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:
|
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:
|
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
|
-
|
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
|