html5small 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # HTML5small
2
2
 
3
3
  HTML5small is a general-purpose minifier for HTML5 documents.
4
+ <br>
5
+ It is faster than [html_compressor](https://github.com/completelynovel/html_compressor)
6
+ and at the same time compresses much better,
7
+ while still generating valid HTML5.
8
+
9
+ ## Usage
10
+ ```sh
11
+ $ gem install html5small
12
+ ```
13
+
14
+ ```ruby
15
+ require 'html5small'
16
+ ::HTML5.minify '<html>...</html>'
17
+ ```
4
18
 
5
19
  ## Origin
6
20
  HTML5small is based on [h5-min](https://github.com/runpaint/h5-min),
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.1.0
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p><a href=foo&amp;bar>a</a>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p><a href=foo&amp;bar>a</a>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p><a href=a&quot;b>a</a>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p><a href=a&quot;b>a</a>
data/fixtures/dl.html.min CHANGED
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><dl><dt>Term<dd>Desc<dt>Term<dt>Term<dd>Desc</dl>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><dl><dt>Term<dd>Desc<dt>Term<dt>Term<dd>Desc</dl>
@@ -0,0 +1,5 @@
1
+ <!DOCTYPE html>
2
+ <meta charset=utf-8>
3
+ <title>Untitled</title>
4
+ <div itemscope hidden="">
5
+ </div>
@@ -0,0 +1 @@
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><div hidden itemscope></div>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>⋔ Ь
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>⋔ Ь
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>1 &amp; 2 &gt; ?
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>1 &amp; 2 &gt; ?
data/fixtures/ie.html.min CHANGED
@@ -1,3 +1,3 @@
1
1
  <!doctype html><meta charset=utf-8><title>Untitled</title><!--[if lt IE 9]>
2
2
  <script src=//html5shiv.googlecode.com/svn/trunk/html5.js></script>
3
- <![endif]--><h1>I.E!?!</h1>
3
+ <![endif]--><body><h1>I.E!?!</h1>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><ul><li><i>one</i><li><i>two</i></ul>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><ul><li><i>one</i><li><i>two</i></ul>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>Two lines
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>Two lines
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p><dfn title="a b">d</dfn>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p><dfn title="a b">d</dfn>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>p<p>p
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>p<p>p
@@ -1,4 +1,4 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><pre>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><pre>
2
2
  &lt; - &gt;
3
3
  &amp;
4
4
  </pre>
@@ -1,4 +1,4 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><pre>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><pre>
2
2
  This
3
3
  <b>is</b>
4
4
  pre-formatted .
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>"q'<pre>&amp;"'</pre>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>"q'<pre>&amp;"'</pre>
@@ -0,0 +1,8 @@
1
+ <!DOCTYPE html>
2
+ <meta charset=utf-8>
3
+ <title>Untitled</title>
4
+ <script>
5
+ console.log(1 < 2);
6
+ console.log(1 > 2);
7
+ console.log(1 && 2);
8
+ </script>
@@ -0,0 +1,5 @@
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><script>
2
+ console.log(1 < 2);
3
+ console.log(1 > 2);
4
+ console.log(1 && 2);
5
+ </script>
@@ -1 +1 @@
1
- <!doctype html><title>Untitled</title><meta charset=utf-8><link href=//creativecommons.org/licenses/by-sa/3.0/ rel=license><h1>Title</h1><p>Test
1
+ <!doctype html><title>Untitled</title><meta charset=utf-8><link href=//creativecommons.org/licenses/by-sa/3.0/ rel=license><body><h1>Title</h1><p>Test
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p><a class=c href=/ hreflang=az-Latn-x-latn style=s title=t>a</a>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p><a class=c href=/ hreflang=az-Latn-x-latn style=s title=t>a</a>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><table class=c><thead class=h><tr><th>H<th>H<tbody class=b><tr><td>D<td>D<tr><td>D<td>D</table>
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><table class=c><thead class=h><tr><th>H<th>H<tbody class=b><tr><td>D<td>D<tr><td>D<td>D</table>
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>Tab tab
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>Tab tab
@@ -1 +1 @@
1
- <!doctype html><meta charset=utf-8><title>Untitled</title><p>This is a<code>string</code>.
1
+ <!doctype html><meta charset=utf-8><title>Untitled</title><body><p>This is a<code>string</code>.
@@ -0,0 +1,103 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "html5small"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Run Paint Run Run", "Ruben Verborgh"]
12
+ s.date = "2012-11-04"
13
+ s.description = "Minifier for HTML5 documents"
14
+ s.email = "ruben.verborgh@gmail.com"
15
+ s.executables = ["html5small", "html5small"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/html5small",
27
+ "fixtures/attribute-value-ampersand.html",
28
+ "fixtures/attribute-value-ampersand.html.min",
29
+ "fixtures/attribute-value-quot.html",
30
+ "fixtures/attribute-value-quot.html.min",
31
+ "fixtures/dl.html",
32
+ "fixtures/dl.html.min",
33
+ "fixtures/empty-attributes.html",
34
+ "fixtures/empty-attributes.html.min",
35
+ "fixtures/entities-expand.html",
36
+ "fixtures/entities-expand.html.min",
37
+ "fixtures/entities-no-expand.html",
38
+ "fixtures/entities-no-expand.html.min",
39
+ "fixtures/ie.html",
40
+ "fixtures/ie.html.min",
41
+ "fixtures/lists.html",
42
+ "fixtures/lists.html.min",
43
+ "fixtures/newlines.html",
44
+ "fixtures/newlines.html.min",
45
+ "fixtures/normalise-attribute-name.html",
46
+ "fixtures/normalise-attribute-name.html.min",
47
+ "fixtures/normalise-tag-name.html",
48
+ "fixtures/normalise-tag-name.html.min",
49
+ "fixtures/pre-entities.html",
50
+ "fixtures/pre-entities.html.min",
51
+ "fixtures/pre.html",
52
+ "fixtures/pre.html.min",
53
+ "fixtures/quot-entity.html",
54
+ "fixtures/quot-entity.html.min",
55
+ "fixtures/scripts.html",
56
+ "fixtures/scripts.html.min",
57
+ "fixtures/skeleton.html",
58
+ "fixtures/skeleton.html.min",
59
+ "fixtures/sort-attributes.html",
60
+ "fixtures/sort-attributes.html.min",
61
+ "fixtures/table.html",
62
+ "fixtures/table.html.min",
63
+ "fixtures/tabs.html",
64
+ "fixtures/tabs.html.min",
65
+ "fixtures/whitespace-complex.html",
66
+ "fixtures/whitespace-complex.html.min",
67
+ "fixtures/whitespace-p.html",
68
+ "fixtures/whitespace-p.html.min",
69
+ "html5small.gemspec",
70
+ "lib/html5small.rb",
71
+ "lib/html5small/Minifier.rb",
72
+ "lib/html5small/OptionalTags.rb",
73
+ "spec/htmlsmall_spec.rb",
74
+ "spec/spec.opts",
75
+ "spec/spec_helper.rb"
76
+ ]
77
+ s.homepage = "http://github.com/RubenVerborgh/HTML5small"
78
+ s.require_paths = ["lib"]
79
+ s.rubygems_version = "1.8.23"
80
+ s.summary = "HTML5small"
81
+
82
+ if s.respond_to? :specification_version then
83
+ s.specification_version = 3
84
+
85
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
86
+ s.add_runtime_dependency(%q<htmlentities>, [">= 4.1.0"])
87
+ s.add_runtime_dependency(%q<nokogiri>, [">= 1.5.0"])
88
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
89
+ s.add_development_dependency(%q<yard>, [">= 0"])
90
+ else
91
+ s.add_dependency(%q<htmlentities>, [">= 4.1.0"])
92
+ s.add_dependency(%q<nokogiri>, [">= 1.5.0"])
93
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
94
+ s.add_dependency(%q<yard>, [">= 0"])
95
+ end
96
+ else
97
+ s.add_dependency(%q<htmlentities>, [">= 4.1.0"])
98
+ s.add_dependency(%q<nokogiri>, [">= 1.5.0"])
99
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
100
+ s.add_dependency(%q<yard>, [">= 0"])
101
+ end
102
+ end
103
+
@@ -16,31 +16,6 @@ module HTML5
16
16
  strong style sub sup svg table textarea time ul var video wbr
17
17
  }.map(&:to_sym)
18
18
 
19
- BOOL_ATTR = {
20
- _: [:itemscope, :hidden],
21
- audio: [:loop, :autoplay, :controls],
22
- button: [:formnovalidate, :disabled, :autofocus],
23
- command: [:disabled, :checked],
24
- details: [:open],
25
- fieldset: [:disabled],
26
- form: [:novalidate],
27
- iframe: [:seamless],
28
- img: [:ismap],
29
- input: [:autocomplete, :autofocus, :defaultchecked,
30
- :checked, :disabled, :formnovalidate, :indeterminate,
31
- :multiple, :readonly, :required],
32
- keygen: [:disabled, :autofocus],
33
- optgroup: [:disabled],
34
- option: [:disabled, :defaultselected, :selected],
35
- ol: [:reversed],
36
- select: [:autofocus, :disabled, :multiple],
37
- script: [:async, :defer],
38
- style: [:scoped],
39
- textarea: [:autofocus, :disabled, :readonly, :required],
40
- time: [:pubdate],
41
- video: [:loop, :autoplay, :controls],
42
- }
43
-
44
19
  attr_accessor :buf, :text_node, :entities
45
20
 
46
21
  def initialize
@@ -101,11 +76,8 @@ module HTML5
101
76
  end.sort_by do |name, value|
102
77
  name
103
78
  end.map do |name, value|
104
- if boolean_attribute?(element, name)
105
- name.to_s
106
- else
107
- "#{name}=#{value}"
108
- end
79
+ # Empty values can use the empty attribute syntax
80
+ value.empty? ? name.to_s : "#{name}=#{value}"
109
81
  end.join(' ').insert(0, ' ')
110
82
  end
111
83
 
@@ -114,13 +86,7 @@ module HTML5
114
86
  # ?
115
87
  def value_needs_quoting? value
116
88
  # must not contain any " ", """, "'", ">", or "=", characters
117
- value =~ /[[:space:]"'><=`]/ or value.empty?
118
- end
119
-
120
- def boolean_attribute? element, attribute
121
- e, a = [element, attribute].map(&:to_sym)
122
- BOOL_ATTR[:_].include?(a) or
123
- (BOOL_ATTR.key?(e) and BOOL_ATTR[e].include?(a))
89
+ value =~ /[[:space:]"'><=`]/
124
90
  end
125
91
 
126
92
  def format_entities html, except={}
@@ -130,13 +96,19 @@ module HTML5
130
96
  end
131
97
 
132
98
  def format_text_node
99
+ # Don't escape script contents
100
+ return text_node if in_script_element?
101
+ # Escape entities inside the text node
133
102
  text = format_entities text_node, {quot: ?", apos: ?'}
103
+ # Don't remove white space in elements with non-HTML content
134
104
  return text if in_pre_element?
135
- text.gsub!(/[\n\t]/,' ')
105
+ # Treat all whitespace as spaces
106
+ text.gsub!(/[\n\t]/, ' ')
136
107
  # Don't strip inter-element white space for flow elements
137
108
  unless buf =~ %r{</\w+>\s*\Z} and in_flow_element?
138
109
  text.lstrip!
139
110
  end
111
+ # Normalize spaces
140
112
  text.squeeze(' ')
141
113
  end
142
114
 
@@ -148,6 +120,10 @@ module HTML5
148
120
  not (PRE_TAGS & @stack).empty?
149
121
  end
150
122
 
123
+ def in_script_element?
124
+ @stack.include? :script
125
+ end
126
+
151
127
  def dump_text_node
152
128
  buf << format_text_node
153
129
  text_node.clear
@@ -20,7 +20,8 @@ module HTML5
20
20
  # if the first thing inside the body element is not a space character or
21
21
  # a comment, except if the first thing inside the body element is a
22
22
  # script or style element.
23
- %r{<body>\s?(?!<(script|style))},
23
+ # Unfortunately, this can confuse older IE browsers.
24
+ # %r{<body>\s?(?!<(script|style))},
24
25
  # A body element's end tag may be omitted if the body element is not
25
26
  # immediately followed by a comment.
26
27
  %r{</body>},
data/lib/html5small.rb CHANGED
@@ -1,5 +1,5 @@
1
- require_relative 'html5small/minifier'
2
- require_relative 'html5small/optional'
1
+ require_relative 'html5small/Minifier'
2
+ require_relative 'html5small/OptionalTags'
3
3
 
4
4
  module HTML5
5
5
  def self.minify html
@@ -25,6 +25,8 @@ end
25
25
  quot_entity: "expands &quot; entity in text nodes",
26
26
  newlines: "should treat newlines in text as a space",
27
27
  tabs: "should treat tabs in text as a space",
28
+ empty_attributes: "should use the empty attribute syntax when appropriate",
29
+ scripts: "should not escape entities inside scripts",
28
30
  }
29
31
 
30
32
  describe HTML5, '.minify' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html5small
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -97,6 +97,8 @@ files:
97
97
  - fixtures/attribute-value-quot.html.min
98
98
  - fixtures/dl.html
99
99
  - fixtures/dl.html.min
100
+ - fixtures/empty-attributes.html
101
+ - fixtures/empty-attributes.html.min
100
102
  - fixtures/entities-expand.html
101
103
  - fixtures/entities-expand.html.min
102
104
  - fixtures/entities-no-expand.html
@@ -117,6 +119,8 @@ files:
117
119
  - fixtures/pre.html.min
118
120
  - fixtures/quot-entity.html
119
121
  - fixtures/quot-entity.html.min
122
+ - fixtures/scripts.html
123
+ - fixtures/scripts.html.min
120
124
  - fixtures/skeleton.html
121
125
  - fixtures/skeleton.html.min
122
126
  - fixtures/sort-attributes.html
@@ -129,10 +133,11 @@ files:
129
133
  - fixtures/whitespace-complex.html.min
130
134
  - fixtures/whitespace-p.html
131
135
  - fixtures/whitespace-p.html.min
136
+ - html5small.gemspec
132
137
  - lib/html5small.rb
133
138
  - lib/html5small/Minifier.rb
134
- - lib/html5small/optional.rb
135
- - spec/h5-min_spec.rb
139
+ - lib/html5small/OptionalTags.rb
140
+ - spec/htmlsmall_spec.rb
136
141
  - spec/spec.opts
137
142
  - spec/spec_helper.rb
138
143
  homepage: http://github.com/RubenVerborgh/HTML5small