multi_html 0.0.2

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.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - rbx-18mode
4
+ - rbx-19mode
5
+ - jruby-18mode
6
+ - jruby-19mode
7
+ - 1.8.7
8
+ - 1.9.2
9
+ - 1.9.3
10
+ - ruby-head
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'html_press', :require => nil
4
+ gem 'html_minifier', ">= 0.0.4", :require => nil
5
+ # gem 'html_compressor', :require => nil
6
+ # gem 'html_min', :require => nil
7
+ # gem 'htmlmin', :require => nil
8
+ # gem 'htmlcompressor', :require => nil
9
+
10
+ # gem 'html-pipeline', :require => nil
11
+
12
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 sterebooster
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # MultiHtml [![Build Status](https://secure.travis-ci.org/stereobooster/multi_html.png?branch=master)](https://secure.travis-ci.org/#!/stereobooster/multi_html) [![Dependency Status](https://gemnasium.com/stereobooster/multi_html.png?travis)](https://gemnasium.com/stereobooster/multi_html) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/stereobooster/multi_html)
2
+
3
+ There are lot of Ruby libraries to minify HTML.
4
+ Instead of choosing a single implementation and forcing users of your library to be
5
+ stuck with it, you can use MultiHtml instead, which will simply choose the
6
+ best available HTML minifier. Here's how to use it:
7
+
8
+ ```ruby
9
+ require 'multi_html'
10
+
11
+ MultiHtml.min('<div> <p>test</p> </div>') #=> '<div><p>test</p></div>'
12
+ ```
13
+
14
+ The `use` method, which sets the MultiHtml adapter, takes either a symbol or a
15
+ class (to allow for custom HTML minifier) that responds to `.min` at the class level.
16
+
17
+ MultiHtml tries to have intelligent defaulting. That is, if you have any of the
18
+ supported engines already loaded, it will utilize them before attempting to
19
+ load any.
20
+ It will load libraries in following order:
21
+
22
+ - [html_minifier](https://github.com/stereobooster/html_minifier)
23
+ - TODO: [html_compressor](https://github.com/completelynovel/html_compressor)
24
+ - TODO: [html_min](http://rubygems.org/gems/html_min)
25
+ - TODO: [htmlmin](https://github.com/aishek/htmlmin)
26
+ - TODO: [htmlcompressor](https://github.com/paolochiodi/htmlcompressor)
27
+
28
+ If no other library is available, MultiHtml falls back to [html_press](https://github.com/stereobooster/html_press).
29
+
30
+ ## HTML::Pipeline
31
+
32
+ ```ruby
33
+ pipeline = HTML::Pipeline.new [
34
+ MultiHtml::Filter
35
+ ]
36
+ pipeline.call('<div> <p>test</p> </div>') #=> '<div><p>test</p></div>'
37
+ ```
38
+
39
+ ## TODO
40
+
41
+ - benchmark against most popular css frameworks (speed, size)
42
+ - generate benchmark report (html or md)
43
+ - write test suite
44
+ - generate comparison table (html or md) with the help of test suite
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it
49
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
50
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
51
+ 4. Push to the branch (`git push origin my-new-feature`)
52
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ desc "Run all examples"
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :default => :spec
data/lib/multi_html.rb ADDED
@@ -0,0 +1,116 @@
1
+ require "multi_html/version"
2
+ require "multi_html/filter"
3
+
4
+ module MultiHtml
5
+ class ParseError < StandardError
6
+ def initialize(message="", backtrace=[])
7
+ super(message)
8
+ self.set_backtrace(backtrace)
9
+ end
10
+ end
11
+
12
+ @adapter = nil
13
+
14
+ REQUIREMENT_MAP = [
15
+ ["html_minifier", :html_minifier],
16
+ # ["html_compressor", :html_compressor],
17
+ # ["html_min", :html_min],
18
+ # ["htmlmin", :htmlmin],
19
+ # ["htmlcompressor", :htmlcompressor],
20
+ ["html_press", :html_press]
21
+ ]
22
+
23
+ class << self
24
+
25
+ # The default adapter based on what you currently
26
+ # have loaded and installed. First checks to see
27
+ # if any adapters are already loaded, then checks
28
+ # to see which are installed if none are loaded.
29
+ def default_adapter
30
+ return :html_minifier if defined?(::HtmlMinifier)
31
+ # return :html_compressor if defined?(::HtmlCompressor)
32
+ # return :html_min if defined?(::HTMLMin)
33
+ # return :htmlmin if defined?(::HTMLMin)
34
+ # return :htmlcompressor if defined?(::HtmlCompressor)
35
+ return :html_press if defined?(::HtmlPress)
36
+
37
+ REQUIREMENT_MAP.each do |(library, adapter)|
38
+ begin
39
+ require library
40
+ return adapter
41
+ rescue LoadError
42
+ next
43
+ end
44
+ end
45
+
46
+ :html_press
47
+ end
48
+ # :nodoc:
49
+ alias :default_engine :default_adapter
50
+
51
+ # Get the current adapter class.
52
+ def adapter
53
+ return @adapter if @adapter
54
+ self.use self.default_adapter
55
+ @adapter
56
+ end
57
+ # :nodoc:
58
+ alias :engine :adapter
59
+
60
+ # Set the adapter utilizing a symbol, string, or class.
61
+ # Supported by default are:
62
+ #
63
+ # * <tt>:html_press</tt>
64
+ # * <tt>:cssminify</tt>
65
+ # * <tt>:yuicssmin</tt>
66
+ # * <tt>:yui_compressor</tt>
67
+ # * <tt>:rainpress</tt>
68
+ def use(new_adapter)
69
+ @adapter = load_adapter(new_adapter)
70
+ end
71
+ alias :adapter= :use
72
+ # :nodoc:
73
+ alias :engine= :use
74
+
75
+ def load_adapter(new_adapter)
76
+ case new_adapter
77
+ when String, Symbol
78
+ require "multi_html/adapters/#{new_adapter}"
79
+ self::Adapters.const_get(:"#{new_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}")
80
+ when NilClass, FalseClass
81
+ default_adapter = self.default_adapter
82
+ require "multi_html/adapters/#{default_adapter}"
83
+ self::Adapters.const_get(:"#{default_adapter.to_s.split('_').map{|s| s.capitalize}.join('')}")
84
+ when Class
85
+ new_adapter
86
+ else
87
+ raise "Did not recognize your adapter specification. Please specify either a symbol or a class."
88
+ end
89
+ end
90
+
91
+ def current_adapter(options)
92
+ if new_adapter = (options || {}).delete(:adapter)
93
+ load_adapter(new_adapter)
94
+ else
95
+ adapter
96
+ end
97
+ end
98
+
99
+ # Minify HTML
100
+ def min(string, options={})
101
+ string = string.read if string.respond_to?(:read)
102
+
103
+ adapter = current_adapter(options)
104
+ if defined?(adapter::ParseError)
105
+ begin
106
+ adapter.min(string, options)
107
+ rescue adapter::ParseError => exception
108
+ raise ::MultiHtml::ParseError.new(exception.message, exception.backtrace)
109
+ end
110
+ else
111
+ adapter.min(string, options)
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,11 @@
1
+ require 'html_compressor' unless defined?(::HtmlCompressor)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class HtmlCompressor
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::HtmlCompressor.new(options).compress(text)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'html_min' unless defined?(::HTMLMin)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class HtmlMin
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::HTMLMin.new.minimize(text)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'html_minifier' unless defined?(::HtmlMinifier)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class HtmlMinifier
6
+ def self.min(text, options=nil) #:nodoc:
7
+ ::HtmlMinifier.minify(text, options)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'html_press' unless defined?(::HtmlPress)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class HtmlPress
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::HtmlPress.press(text, options)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'htmlcompressor' unless defined?(::HtmlCompressor)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class Htmlcompressor
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::HtmlCompressor.Compressor.new(options).compile(text)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'htmlmin' unless defined?(::HTMLMin)
2
+
3
+ module MultiHtml
4
+ module Adapters
5
+ class Htmlmin
6
+ def self.min(text, options={}) #:nodoc:
7
+ ::HTMLMin.minify(text, options)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ begin
2
+ require 'html/pipeline'
3
+
4
+ module MultiHtml
5
+ class Filter < ::HTML::Pipeline::TextFilter
6
+ def call
7
+ MultiHtml.min(@text, context[:multi_html])
8
+ end
9
+ end
10
+ end
11
+ rescue LoadError
12
+ end
@@ -0,0 +1,3 @@
1
+ module MultiHtml
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multi_html/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "multi_html"
8
+ gem.version = MultiHtml::VERSION
9
+ gem.authors = ["sterebooster"]
10
+ gem.email = ["stereobooster@gmail.com"]
11
+ gem.description = %q{A generic swappable back-end for HTML minifiers}
12
+ gem.summary = %q{A generic swappable back-end for HTML minifiers}
13
+ gem.homepage = "https://github.com/stereobooster/multi_html"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency 'html_press'
22
+
23
+ gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'simplecov'
26
+ end
@@ -0,0 +1,19 @@
1
+ shared_examples_for "an adapter" do |adapter|
2
+
3
+ before do
4
+ begin
5
+ MultiHtml.use adapter
6
+ rescue LoadError
7
+ pending "Adapter #{adapter} couldn't be loaded (not installed?)"
8
+ end
9
+ end
10
+
11
+ describe '.min' do
12
+ it 'minify' do
13
+ MultiHtml.min(" <p>some text</p>").should eq '<p>some text</p>'
14
+ end
15
+
16
+ it 'support options'
17
+
18
+ end
19
+ end
data/spec/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ def macruby?
2
+ defined?(RUBY_ENGINE) && RUBY_ENGINE == 'macruby'
3
+ end
4
+
5
+ unless ENV['CI'] || macruby?
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ add_filter 'spec'
9
+ end
10
+ end
11
+
12
+ require 'multi_html'
13
+ require 'rspec'
14
+
15
+ class MockDecoder
16
+ def self.min(string, options={})
17
+ ''
18
+ end
19
+ end
@@ -0,0 +1,79 @@
1
+ require 'helper'
2
+ require 'adapter_shared_example'
3
+ require 'stringio'
4
+
5
+ describe MultiHtml do
6
+ context 'adapters' do
7
+ before do
8
+ MultiHtml.use nil
9
+ end
10
+ context 'when no other implementations are available' do
11
+
12
+ # :HtmlCompressor, :HTMLMin
13
+ CONSTS = [:HtmlPress, :HtmlMinifier]
14
+
15
+ before do
16
+ @old_map = MultiHtml::REQUIREMENT_MAP
17
+ @old_consts = {}
18
+ CONSTS.each do |c|
19
+ @old_consts[c] = Object.const_get c if Object.const_defined?(c)
20
+ end
21
+
22
+ MultiHtml::REQUIREMENT_MAP.each_with_index do |(library, adapter), index|
23
+ MultiHtml::REQUIREMENT_MAP[index] = ["foo/#{library}", adapter]
24
+ end
25
+
26
+ CONSTS.each do |c|
27
+ Object.send :remove_const, c if @old_consts[c]
28
+ end
29
+ end
30
+
31
+ after do
32
+ @old_map.each_with_index do |(library, adapter), index|
33
+ MultiHtml::REQUIREMENT_MAP[index] = [library, adapter]
34
+ end
35
+
36
+ CONSTS.each do |c|
37
+ Object.const_set c, @old_consts[c] if @old_consts[c]
38
+ end
39
+ end
40
+
41
+ it 'defaults to vendored implemention if no other implementions are available' do
42
+ MultiHtml.default_adapter.should eq :html_press
43
+ end
44
+ end
45
+
46
+ it 'defaults to the best not vendored lib if any other lib available' do
47
+ require 'html_minifier'
48
+ MultiHtml.adapter.name.should eq 'MultiHtml::Adapters::HtmlMinifier'
49
+ end
50
+
51
+ it 'is settable via a symbol' do
52
+ MultiHtml.use :html_minifier
53
+ MultiHtml.adapter.name.should eq 'MultiHtml::Adapters::HtmlMinifier'
54
+ end
55
+
56
+ it 'is settable via a class' do
57
+ MultiHtml.use MockDecoder
58
+ MultiHtml.adapter.name.should eq 'MockDecoder'
59
+ end
60
+ end
61
+
62
+ # html_compressor html_min htmlmin htmlcompressor
63
+ %w(html_press html_minifier).each do |adapter|
64
+ context adapter do
65
+ it_behaves_like "an adapter", adapter
66
+ end
67
+ end
68
+ end
69
+
70
+ if defined?(MultiHtml::Filter)
71
+ describe MultiHtml::Filter do
72
+ it "filter works" do
73
+ pipeline = HTML::Pipeline.new [
74
+ MultiHtml::Filter
75
+ ]
76
+ pipeline.call(" <p>some text</p>").should eq '<p>some text</p>'
77
+ end
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: multi_html
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - sterebooster
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: html_press
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: simplecov
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: A generic swappable back-end for HTML minifiers
79
+ email:
80
+ - stereobooster@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - .travis.yml
87
+ - Gemfile
88
+ - LICENSE.txt
89
+ - README.md
90
+ - Rakefile
91
+ - lib/multi_html.rb
92
+ - lib/multi_html/adapters/html_compressor.rb
93
+ - lib/multi_html/adapters/html_min.rb
94
+ - lib/multi_html/adapters/html_minifier.rb
95
+ - lib/multi_html/adapters/html_press.rb
96
+ - lib/multi_html/adapters/htmlcompressor.rb
97
+ - lib/multi_html/adapters/htmlmin.rb
98
+ - lib/multi_html/filter.rb
99
+ - lib/multi_html/version.rb
100
+ - multi_html.gemspec
101
+ - spec/adapter_shared_example.rb
102
+ - spec/helper.rb
103
+ - spec/multi_html_spec.rb
104
+ homepage: https://github.com/stereobooster/multi_html
105
+ licenses:
106
+ - MIT
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ segments:
118
+ - 0
119
+ hash: -404139121
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ segments:
127
+ - 0
128
+ hash: -404139121
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 1.8.24
132
+ signing_key:
133
+ specification_version: 3
134
+ summary: A generic swappable back-end for HTML minifiers
135
+ test_files:
136
+ - spec/adapter_shared_example.rb
137
+ - spec/helper.rb
138
+ - spec/multi_html_spec.rb