htmlbeautifier 1.1.0 → 1.1.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
2
  SHA1:
3
- metadata.gz: eb927f5efa5cd85b002af5945bd03106b0fc7c31
4
- data.tar.gz: a2dfedd5c2565b7245d1473d77fd729f621e0f0c
3
+ metadata.gz: 3b82dd8d2489286ab4474e1690d0a47ff91ffce8
4
+ data.tar.gz: e20a70c076be7e6eda31e456b0fd56715c1554ce
5
5
  SHA512:
6
- metadata.gz: 2a06c094220e541614b3026403dfe017207d2b09821044720a5bb4093fc580007c638b746022739d1ba75a22b96e6a9a46bb21eeab293bc84c1a313bacd4f0ed
7
- data.tar.gz: 1d29ae0712bed379920a1c1a3e3431d7ffc5404388b1bad04e8b32ae542efdb10f14605fc39e03028a852ddab060ac3e216dcafa5be48fca8c7940736b7ee40a
6
+ metadata.gz: 9da8945658fddb13a0af61e5d61e05b381ffdb8168247d22fe6026043c41822cce4bce45910e844cb8f5183f01a790836a209802531cd4e13a1bbd67b0092877
7
+ data.tar.gz: 224c74e0769b2e208505cd0d1461f4c971ed9a264f2ed78bf27c6311c5fa037e40295b8beb607fed7edf114e354138805cec3e766432b9a3a8e08e0b66a86950
data/README.md CHANGED
@@ -1,11 +1,9 @@
1
- HTML Beautifier
2
- ===============
1
+ # HTML Beautifier
3
2
 
4
3
  A normaliser/beautifier for HTML that also understands embedded Ruby.
5
4
  Ideal for tidying up Rails templates.
6
5
 
7
- What it does
8
- ------------
6
+ ## What it does
9
7
 
10
8
  * Normalises hard tabs to spaces
11
9
  * Removes trailing spaces
@@ -18,8 +16,7 @@ What it does
18
16
  * Indents the left-hand margin of JavaScript and CSS blocks to match the
19
17
  indentation level of the code
20
18
 
21
- Usage
22
- -----
19
+ ## Usage
23
20
 
24
21
  ### From the command line
25
22
 
@@ -35,7 +32,7 @@ or to operate on standard input and output:
35
32
  $ htmlbeautifier < input > output
36
33
  ```
37
34
 
38
- ## In your code
35
+ ### In your code
39
36
 
40
37
  ```ruby
41
38
  require 'htmlbeautifier'
@@ -48,3 +45,27 @@ You can also specify the number of spaces to indent (the default is 2):
48
45
  ```ruby
49
46
  beautiful = HtmlBeautifier.beautify(messy, tab_stops: 4)
50
47
  ```
48
+
49
+ ## Installation
50
+
51
+ This is a Ruby gem.
52
+ To install the command-line tool (you may need `sudo`):
53
+
54
+ ```sh
55
+ $ gem install htmlbeautifier
56
+ ```
57
+
58
+ To use the gem with Bundler, add to your `Gemfile`:
59
+
60
+ ```ruby
61
+ gem 'htmlbeautifier'
62
+ ```
63
+
64
+ ## Contributing
65
+
66
+ 1. Follow [these guidelines][git-commit] when writing commit messages (briefly,
67
+ the first line should begin with a capital letter, use the imperative mood,
68
+ be no more than 50 characters, and not end with a period).
69
+ 2. Include tests.
70
+
71
+ [git-commit]:http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
data/Rakefile CHANGED
@@ -7,3 +7,10 @@ RSpec::Core::RakeTask.new do |t|
7
7
  end
8
8
 
9
9
  task :default => [:spec]
10
+
11
+ if Gem.loaded_specs.key?('rubocop')
12
+ require 'rubocop/rake_task'
13
+ RuboCop::RakeTask.new
14
+
15
+ task(:default).prerequisites << task(:rubocop)
16
+ end
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- require 'htmlbeautifier'
3
- require 'optparse'
4
- require 'fileutils'
2
+ require "htmlbeautifier"
3
+ require "optparse"
4
+ require "fileutils"
5
5
 
6
6
  def beautify(name, input, output, options)
7
7
  output.puts HtmlBeautifier.beautify(input, options)
@@ -11,7 +11,7 @@ end
11
11
 
12
12
  executable = File.basename(__FILE__)
13
13
 
14
- options = {:tab_stops => 2}
14
+ options = { tab_stops: 2 }
15
15
  parser = OptionParser.new do |opts|
16
16
  opts.banner = "Usage: #{executable} [options] [file ...]"
17
17
  opts.separator <<END
@@ -1,9 +1,9 @@
1
- require 'htmlbeautifier/builder'
2
- require 'htmlbeautifier/html_parser'
3
- require 'htmlbeautifier/version'
1
+ require "htmlbeautifier/builder"
2
+ require "htmlbeautifier/html_parser"
3
+ require "htmlbeautifier/version"
4
4
 
5
5
  module HtmlBeautifier
6
-
6
+ #
7
7
  # Returns a beautified HTML/HTML+ERB document as a String.
8
8
  # html must be an object that responds to +#to_s+.
9
9
  #
@@ -13,7 +13,7 @@ module HtmlBeautifier
13
13
  # is false, i.e. continue to process the rest of the document.
14
14
  #
15
15
  def self.beautify(html, options = {})
16
- ''.tap { |output|
16
+ "".tap { |output|
17
17
  HtmlParser.new.scan html.to_s, Builder.new(output, options)
18
18
  }
19
19
  end
@@ -1,17 +1,8 @@
1
- require 'htmlbeautifier/parser'
1
+ require "htmlbeautifier/parser"
2
+ require "htmlbeautifier/ruby_indenter"
2
3
 
3
4
  module HtmlBeautifier
4
5
  class Builder
5
-
6
- RUBY_INDENT =
7
- %r{ ^ ( if | unless | while | begin | elsif | else )\b
8
- | \b ( do | \{ ) ( \s* \| [^\|]+ \| )? $
9
- }x
10
- RUBY_OUTDENT =
11
- %r{ ^ ( end | elsif | else |\} ) \b
12
- }x
13
- ELEMENT_CONTENT = %r{ (?:[^<>]|<%.*?%>)* }mx
14
-
15
6
  DEFAULT_OPTIONS = {
16
7
  tab_stops: 2,
17
8
  stop_on_errors: false
@@ -19,20 +10,21 @@ module HtmlBeautifier
19
10
 
20
11
  def initialize(output, options = {})
21
12
  options = DEFAULT_OPTIONS.merge(options)
13
+ @tab = " " * options[:tab_stops]
14
+ @stop_on_errors = options[:stop_on_errors]
22
15
  @level = 0
23
16
  @new_line = false
24
- @tab = ' ' * options[:tab_stops]
25
- @stop_on_errors = options[:stop_on_errors]
26
- @output = output
27
17
  @empty = true
28
18
  @ie_cc_levels = []
19
+ @output = output
20
+ @embedded_indenter = RubyIndenter.new
29
21
  end
30
22
 
31
23
  private
32
24
 
33
25
  def error(text)
34
26
  return unless @stop_on_errors
35
- raise RuntimeError, text
27
+ raise text
36
28
  end
37
29
 
38
30
  def indent
@@ -44,75 +36,62 @@ module HtmlBeautifier
44
36
  @level = [@level - 1, 0].max
45
37
  end
46
38
 
47
- def emit(s)
48
- if @new_line && !@empty
49
- @output << ("\n" + @tab * @level)
50
- end
51
- @output << s
39
+ def emit(*strings)
40
+ @output << ("\n" + @tab * @level) if @new_line && !@empty
41
+ @output << strings.join("")
52
42
  @new_line = false
53
43
  @empty = false
54
44
  end
55
45
 
56
- def new_line(*_args)
46
+ def new_line(*)
57
47
  @new_line = true
58
48
  end
59
49
 
60
50
  def embed(opening, code, closing)
61
- lines = code.split(/\n/).map{ |l| l.strip }
62
- outdent if lines.first =~ RUBY_OUTDENT
63
- emit opening + code + closing
64
- indent if lines.last =~ RUBY_INDENT
51
+ lines = code.split(%r{\n}).map(&:strip)
52
+ outdent if @embedded_indenter.outdent?(lines)
53
+ emit opening, code, closing
54
+ indent if @embedded_indenter.indent?(lines)
65
55
  end
66
56
 
67
57
  def foreign_block(opening, code, closing)
68
58
  emit opening
69
- unless code.strip.empty?
70
- indent
59
+ emit_reindented_block_content code unless code.strip.empty?
60
+ emit closing
61
+ end
71
62
 
72
- lines = code.split(/\n/)
73
- lines.shift while lines.first.strip.empty?
74
- lines.pop while lines.last.strip.empty?
75
- indentation = lines.first[/^ +/]
63
+ def emit_reindented_block_content(code)
64
+ lines = code.strip.split(%r{\n})
65
+ indentation = lines.first[%r{^\s+}]
76
66
 
67
+ indent
68
+ new_line
69
+ lines.each do |line|
70
+ emit line.rstrip.sub(%r{^#{indentation}}, "")
77
71
  new_line
78
- lines.each do |line|
79
- emit line.rstrip.sub(/^#{indentation}/, '')
80
- new_line
81
- end
82
-
83
- outdent
84
72
  end
85
- emit closing
73
+ outdent
86
74
  end
87
75
 
88
76
  def preformatted_block(opening, content, closing)
89
77
  new_line
90
- emit opening
91
- emit content
92
- emit closing
78
+ emit opening, content, closing
93
79
  new_line
94
80
  end
95
81
 
96
82
  def standalone_element(e)
97
83
  emit e
98
- new_line if e =~ /^<br[^\w]/
84
+ new_line if e =~ %r{^<br[^\w]}
99
85
  end
100
86
 
101
- def close_block_element(e)
87
+ def close_element(e)
102
88
  outdent
103
89
  emit e
104
- new_line
105
90
  end
106
91
 
107
- def open_block_element(e)
92
+ def close_block_element(e)
93
+ close_element e
108
94
  new_line
109
- emit e
110
- indent
111
- end
112
-
113
- def close_element(e)
114
- outdent
115
- emit e
116
95
  end
117
96
 
118
97
  def open_element(e)
@@ -120,6 +99,11 @@ module HtmlBeautifier
120
99
  indent
121
100
  end
122
101
 
102
+ def open_block_element(e)
103
+ new_line
104
+ open_element e
105
+ end
106
+
123
107
  def close_ie_cc(e)
124
108
  if @ie_cc_levels.empty?
125
109
  error "Unclosed conditional comment"
@@ -137,7 +121,7 @@ module HtmlBeautifier
137
121
 
138
122
  def text(t)
139
123
  emit t.chomp
140
- new_line if t.end_with? $/
124
+ new_line if t.end_with?("\n")
141
125
  end
142
126
  end
143
127
  end
@@ -1,4 +1,4 @@
1
- require 'htmlbeautifier/parser'
1
+ require "htmlbeautifier/parser"
2
2
 
3
3
  module HtmlBeautifier
4
4
  class HtmlParser < Parser
@@ -14,38 +14,45 @@ module HtmlBeautifier
14
14
  pre | section | table | tbody | td | tfoot | th | thead | tr | ul | video
15
15
  )}mix
16
16
 
17
+ MAPPINGS = [
18
+ [%r{(<%-?=?)(.*?)(-?%>)}om,
19
+ :embed],
20
+ [%r{<!--\[.*?\]>}om,
21
+ :open_ie_cc],
22
+ [%r{<!\[.*?\]-->}om,
23
+ :close_ie_cc],
24
+ [%r{<!--.*?-->}om,
25
+ :standalone_element],
26
+ [%r{<!.*?>}om,
27
+ :standalone_element],
28
+ [%r{(<script#{ELEMENT_CONTENT}>)(.*?)(</script>)}omi,
29
+ :foreign_block],
30
+ [%r{(<style#{ELEMENT_CONTENT}>)(.*?)(</style>)}omi,
31
+ :foreign_block],
32
+ [%r{(<pre#{ELEMENT_CONTENT}>)(.*?)(</pre>)}omi,
33
+ :preformatted_block],
34
+ [%r{(<textarea#{ELEMENT_CONTENT}>)(.*?)(</textarea>)}omi,
35
+ :preformatted_block],
36
+ [%r{<#{HTML_VOID_ELEMENTS}(?: #{ELEMENT_CONTENT})?/?>}om,
37
+ :standalone_element],
38
+ [%r{</#{HTML_BLOCK_ELEMENTS}>}om,
39
+ :close_block_element],
40
+ [%r{<#{HTML_BLOCK_ELEMENTS}(?: #{ELEMENT_CONTENT})?>}om,
41
+ :open_block_element],
42
+ [%r{</#{ELEMENT_CONTENT}>}om,
43
+ :close_element],
44
+ [%r{<#{ELEMENT_CONTENT}>}om,
45
+ :open_element],
46
+ [%r{\s*\r?\n\s*}om,
47
+ :new_line],
48
+ [%r{[^<]+},
49
+ :text]]
50
+
17
51
  def initialize
18
52
  super do |p|
19
- p.map %r{(<%-?=?)(.*?)(-?%>)}m,
20
- :embed
21
- p.map %r{<!--\[.*?\]>}m,
22
- :open_ie_cc
23
- p.map %r{<!\[.*?\]-->}m,
24
- :close_ie_cc
25
- p.map %r{<!--.*?-->}m,
26
- :standalone_element
27
- p.map %r{<!.*?>}m,
28
- :standalone_element
29
- p.map %r{(<script#{ELEMENT_CONTENT}>)(.*?)(</script>)}mi,
30
- :foreign_block
31
- p.map %r{(<style#{ELEMENT_CONTENT}>)(.*?)(</style>)}mi,
32
- :foreign_block
33
- p.map %r{(<pre#{ELEMENT_CONTENT}>)(.*?)(</pre>)}mi,
34
- :preformatted_block
35
- p.map %r{<#{HTML_VOID_ELEMENTS}(?: #{ELEMENT_CONTENT})?/?>}m,
36
- :standalone_element
37
- p.map %r{</#{HTML_BLOCK_ELEMENTS}>}m,
38
- :close_block_element
39
- p.map %r{<#{HTML_BLOCK_ELEMENTS}(?: #{ELEMENT_CONTENT})?>}m,
40
- :open_block_element
41
- p.map %r{</#{ELEMENT_CONTENT}>}m,
42
- :close_element
43
- p.map %r{<#{ELEMENT_CONTENT}>}m,
44
- :open_element
45
- p.map %r{\s*\r?\n\s*}m,
46
- :new_line
47
- p.map %r{[^<]+},
48
- :text
53
+ MAPPINGS.each do |regexp, method|
54
+ p.map regexp, method
55
+ end
49
56
  end
50
57
  end
51
58
  end
@@ -1,19 +1,8 @@
1
- require 'strscan'
1
+ require "strscan"
2
2
 
3
3
  module HtmlBeautifier
4
4
  class Parser
5
-
6
- def self.debug_block(&blk)
7
- @debug_block = blk
8
- end
9
-
10
- def self.debug(match, method)
11
- if defined? @debug_block
12
- @debug_block.call(match, method)
13
- end
14
- end
15
-
16
- def initialize(&blk)
5
+ def initialize
17
6
  @maps = []
18
7
  yield self if block_given?
19
8
  end
@@ -24,9 +13,7 @@ module HtmlBeautifier
24
13
 
25
14
  def scan(subject, receiver)
26
15
  @scanner = StringScanner.new(subject)
27
- until @scanner.eos?
28
- dispatch(receiver)
29
- end
16
+ dispatch(receiver) until @scanner.eos?
30
17
  end
31
18
 
32
19
  def source_so_far
@@ -34,28 +21,28 @@ module HtmlBeautifier
34
21
  end
35
22
 
36
23
  def source_line_number
37
- [source_so_far.chomp.split(/\n/).count, 1].max
24
+ [source_so_far.chomp.split(%r{\n}).count, 1].max
38
25
  end
39
26
 
40
27
  private
28
+
41
29
  def dispatch(receiver)
42
- @maps.each do |pattern, method|
43
- if @scanner.scan(pattern)
44
- params = []
45
- i = 1
46
- while @scanner[i]
47
- params << @scanner[i]
48
- i += 1
49
- end
50
- params = [@scanner[0]] if params.empty?
51
- self.class.debug(@scanner[0], method)
52
- receiver.__send__(method, *params)
53
- return
54
- end
55
- end
56
- raise "Unmatched sequence"
30
+ _, method = @maps.find { |pattern, _| @scanner.scan(pattern) }
31
+ raise "Unmatched sequence" unless method
32
+ receiver.__send__(method, *extract_params(@scanner))
57
33
  rescue => ex
58
34
  raise "#{ex.message} on line #{source_line_number}"
59
35
  end
36
+
37
+ def extract_params(scanner)
38
+ return [scanner[0]] unless scanner[1]
39
+ params = []
40
+ i = 1
41
+ while scanner[i]
42
+ params << scanner[i]
43
+ i += 1
44
+ end
45
+ params
46
+ end
60
47
  end
61
48
  end
@@ -0,0 +1,19 @@
1
+ module HtmlBeautifier
2
+ 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{
6
+ ^ ( #{INDENT_KEYWORDS.join("|")} )\b
7
+ | \b ( do | \{ ) ( \s* \| [^\|]+ \| )? $
8
+ }xo
9
+ RUBY_OUTDENT = %r{ ^ ( #{OUTDENT_KEYWORDS.join("|")} | \} ) \b }xo
10
+
11
+ def outdent?(lines)
12
+ lines.first =~ RUBY_OUTDENT
13
+ end
14
+
15
+ def indent?(lines)
16
+ lines.last =~ RUBY_INDENT
17
+ end
18
+ end
19
+ end
@@ -2,8 +2,8 @@ module HtmlBeautifier #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 1
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
- STRING = [MAJOR, MINOR, TINY].join('.')
7
+ STRING = [MAJOR, MINOR, TINY].join(".")
8
8
  end
9
9
  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.1.0
4
+ version: 1.1.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: 2015-03-07 00:00:00.000000000 Z
11
+ date: 2015-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.30.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.30.0
41
55
  description: A normaliser/beautifier for HTML that also understands embedded Ruby.
42
56
  email: pbattley@gmail.com
43
57
  executables:
@@ -52,6 +66,7 @@ files:
52
66
  - lib/htmlbeautifier/builder.rb
53
67
  - lib/htmlbeautifier/html_parser.rb
54
68
  - lib/htmlbeautifier/parser.rb
69
+ - lib/htmlbeautifier/ruby_indenter.rb
55
70
  - lib/htmlbeautifier/version.rb
56
71
  homepage: http://github.com/threedaymonk/htmlbeautifier
57
72
  licenses:
@@ -73,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
88
  version: '0'
74
89
  requirements: []
75
90
  rubyforge_project:
76
- rubygems_version: 2.2.2
91
+ rubygems_version: 2.4.5
77
92
  signing_key:
78
93
  specification_version: 4
79
94
  summary: HTML/ERB beautifier