gatchaman 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 83669db5ec638c57ccfd8f56068d4db631a061d4
4
+ data.tar.gz: 4f143d83b8e109c79b6d463dac40806433e991ad
5
+ SHA512:
6
+ metadata.gz: e3c44f552269b19291486c5aec3d00e4035f4f66bcee93e42f516fe8b55a96219fe395ec709d707175c8de9c76aed7dd8b92961b1d91bfb525870a32421058e0
7
+ data.tar.gz: f4471f7a121ae95344d9f155e6fdb9c1752ce8a8853b575442657bdfd7119333aaf93043219c4aeb12a1d2b91b5394d4b252ff5460891b748b87ee9619a05fcb
data/ChangeLog CHANGED
@@ -10,3 +10,14 @@
10
10
 
11
11
  * RADME.md add usage of Gatchaman class
12
12
  * relaese version 0.1.1
13
+
14
+ 2013-02-20 maruyama shinepi <shinpeim@gmail.com>
15
+
16
+ * release version 0.2.0
17
+ * now gatchan expand js and css(thanks to wneko)
18
+
19
+ 2013-03-18 maruyama shinpei <shinpeim@gmail.com>
20
+
21
+ * release version 0.2.1
22
+ * some bug fixes
23
+ * refactor (thanks to wneko)
data/README.md CHANGED
@@ -25,6 +25,6 @@ or
25
25
  4. Push to the branch (`git push origin my-new-feature`)
26
26
  5. Create new Pull Request
27
27
 
28
- ## Contributers
28
+ ## Contributors
29
29
 
30
30
  wneko [js and css expand options]
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = 'spec/**/*_spec.rb'
7
+ spec.rspec_opts = ['-cfs']
8
+ end
9
+ rescue LoadError => e
10
+ end
@@ -24,8 +24,8 @@ options = parse_options
24
24
  input_file = ARGV.shift or help
25
25
 
26
26
  begin
27
- print Gatchaman.new(options[:document_root], options[:current_directory] || File.dirname(input_file)).
28
- data_uri_schemize(IO.read(input_file))
27
+ options[:current_directory] ||= File.dirname(input_file)
28
+ print Gatchaman.new(options).data_uri_schemize(IO.read(input_file))
29
29
  rescue => e
30
30
  warn e.message
31
31
  exit 2
@@ -20,4 +20,5 @@ Gem::Specification.new do |gem|
20
20
  gem.add_runtime_dependency "nokogiri", "~> 1.5.6"
21
21
  gem.add_runtime_dependency "mime-types", "~> 1.19"
22
22
  gem.add_development_dependency "rspec", "~> 2.12.0"
23
+ gem.add_development_dependency "rake", "~> 10.0.3"
23
24
  end
@@ -1,91 +1,41 @@
1
1
  require "gatchaman/version"
2
- require "nokogiri"
3
- require "mime/types"
4
- require "open-uri"
5
- require "base64"
2
+ require "gatchaman/embedder"
3
+
6
4
  class Gatchaman
7
- SCHEMIZE_TARGET_ELEMENTS = [
8
- :img,
9
- :audio,
10
- :video
5
+ EMBED_OPTION_KEYS = [
6
+ :document_root,
7
+ :current_dir,
11
8
  ].freeze
12
-
9
+
13
10
  def initialize(options = {})
14
- @document_root = chomp_last_slash(options[:document_root])
15
- @current_dir = chomp_last_slash(options[:current_dir])
11
+ @options = options
12
+ @embed_options = {}
13
+ EMBED_OPTION_KEYS.each do |key|
14
+ @embed_options[key] = @options[key] if @options[key]
15
+ end
16
+ end
16
17
 
17
- @expand_js = options[:expand_js] || false
18
- @expand_css = options[:expand_css] || false
18
+ def embedders
19
+ if @embedders.nil?
20
+ @embedders = []
21
+ @embedders << Gatchaman::Embedder::Media.new(@embed_options)
22
+ @embedders << Gatchaman::Embedder::JS.new(@embed_options) if @options[:expand_js]
23
+ @embedders << Gatchaman::Embedder::CSS.new(@embed_options) if @options[:expand_css]
24
+ end
25
+ @embedders
19
26
  end
20
27
 
21
28
  def data_uri_schemize(html_string)
22
- doc = Nokogiri::HTML::DocumentFragment.parse(html_string)
29
+ doc = if Nokogiri.XML(html_string).root.name == "html"
30
+ Nokogiri::HTML::Document.parse(html_string)
31
+ else
32
+ Nokogiri::HTML::DocumentFragment.parse(html_string)
33
+ end
23
34
 
24
- doc.css(SCHEMIZE_TARGET_ELEMENTS.join(',')).each do |element|
25
- element[:src] = to_data_scheme(extract_path(element[:src]))
35
+ embedders.each do |embedder|
36
+ embedder.embed(doc)
26
37
  end
27
38
 
28
- expand_js(doc) if @expand_js
29
- expand_css(doc) if @expand_css
30
-
31
39
  doc.to_s
32
40
  end
33
-
34
- private
35
- def chomp_last_slash(str)
36
- str.gsub(/\/$/,"")
37
- end
38
- def extract_path(path)
39
- if path =~ /^http/
40
- return path
41
- elsif path =~ /^\//
42
- return @document_root + path
43
- else
44
- return @current_dir + "/" + path
45
- end
46
- end
47
- def to_data_scheme(path)
48
- mime = MIME::Types.type_for(path).first
49
- image_binary = open(path, "r:ASCII-8BIT"){|f|
50
- f.read(nil)
51
- }
52
- base64 = Base64.encode64(image_binary).gsub(/\s/,'')
53
- "data:#{mime.to_s};base64,#{base64}"
54
- end
55
- def inner_html_from_file(filename)
56
- ["", open(extract_path(filename)).read.chomp, ""].join("\n")
57
- end
58
- def expand_js(doc)
59
- doc.css('script').each do |element|
60
- expand_js_element(element)
61
- end
62
- doc
63
- end
64
- def expand_css(doc)
65
- doc.css('link[rel=stylesheet]').each do |element|
66
- expand_css_element(element)
67
- end
68
- doc
69
- end
70
- def expand_js_element(element)
71
- return if element[:src].nil? or element[:src].size == 0
72
- element.inner_html += inner_html_from_file(element[:src])
73
- [:src, :charset].each {|attr| element.delete(attr.to_s)}
74
- end
75
- def expand_css_element(element)
76
- element.name = "style"
77
- content = inner_html_from_file(element[:href])
78
- content = expand_css_url(content)
79
- element.inner_html = content
80
- element.attributes.keys.each do |attr_name|
81
- next if [:media, :type].include? attr_name.to_sym
82
- element.delete(attr_name)
83
- end
84
- end
85
- def expand_css_url(css_content)
86
- css_content.gsub(/\burl\b\(([^)]+)\)/) do
87
- data_scheme = to_data_scheme(extract_path($1))
88
- "url(#{data_scheme})"
89
- end
90
- end
91
41
  end
@@ -0,0 +1,28 @@
1
+ require "mime/types"
2
+ require "open-uri"
3
+ require "base64"
4
+
5
+ class Gatchaman
6
+ class DataScheme < String
7
+ def initialize(path)
8
+ @path = path
9
+ super(to_s)
10
+ end
11
+
12
+ def mime_type
13
+ @mime_type ||= MIME::Types.type_for(@path).first.to_s
14
+ end
15
+
16
+ def binary
17
+ @binary ||= open(@path, "r:ASCII-8BIT") {|f| f.read(nil) }
18
+ end
19
+
20
+ def base64
21
+ @base64 ||= Base64.encode64(binary).gsub(/\s/, '')
22
+ end
23
+
24
+ def to_s
25
+ "data:#{mime_type};base64,#{base64}"
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'open-uri'
2
+ require "nokogiri"
3
+ require "gatchaman/data_scheme"
4
+ require "gatchaman/path"
5
+ require "gatchaman/embedder/media"
6
+ require "gatchaman/embedder/css"
7
+ require "gatchaman/embedder/js"
8
+
9
+ class Gatchaman
10
+ module Embedder
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ require 'gatchaman/embedder/generic'
2
+
3
+ class Gatchaman::Embedder::CSS < Gatchaman::Embedder::Generic
4
+ def embed(doc)
5
+ doc.css('link[rel=stylesheet]').each do |element|
6
+ embed_element(element)
7
+ end
8
+ doc.css('style').each do |element|
9
+ element.content = embed_all_url_in_css(element.content)
10
+ end
11
+ doc
12
+ end
13
+
14
+ private
15
+ def embed_element(element)
16
+ element.name = "style"
17
+ content = inner_html_from_file(element[:href])
18
+ element.inner_html = content
19
+ element.attributes.keys.each do |attr_name|
20
+ next if [:media, :type].include? attr_name.to_sym
21
+ element.delete(attr_name)
22
+ end
23
+ end
24
+
25
+ def embed_all_url_in_css(css_content)
26
+ css_content.gsub(/\burl\b\(([^)]+)\)/) do
27
+ data_scheme = Gatchaman::DataScheme.new(path($1))
28
+ "url(#{data_scheme})"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ class Gatchaman
2
+ module Embedder
3
+ class Generic
4
+ def initialize(options)
5
+ @options = options
6
+ end
7
+
8
+ def expand(doc)
9
+ doc
10
+ end
11
+
12
+ private
13
+ def path(path)
14
+ Path.new(path, @options)
15
+ end
16
+
17
+ def inner_html_from_file(filename)
18
+ ["", open(path(filename)).read.chomp, ""].join("\n")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ require 'gatchaman/embedder/generic'
2
+
3
+ class Gatchaman::Embedder::JS < Gatchaman::Embedder::Generic
4
+ def embed(doc)
5
+ doc.css('script').each do |element|
6
+ embed_element(element)
7
+ end
8
+ doc
9
+ end
10
+
11
+ private
12
+ def embed_element(element)
13
+ return if element[:src].nil? or element[:src].size == 0
14
+ element.inner_html += html_comment_out(inner_html_from_file(element[:src]))
15
+ [:src, :charset].each {|attr| element.delete(attr.to_s)}
16
+ end
17
+
18
+ def html_comment_out(content)
19
+ ["<!--", content, "-->"].join("\n")
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'gatchaman/embedder/generic'
2
+
3
+ class Gatchaman::Embedder::Media < Gatchaman::Embedder::Generic
4
+ TARGET_ELEMENTS = [
5
+ :img,
6
+ :audio,
7
+ :video
8
+ ].freeze
9
+
10
+ def embed(doc)
11
+ doc.css(TARGET_ELEMENTS.join(',')).each do |element|
12
+ element[:src] = Gatchaman::DataScheme.new(path(element[:src]))
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ require 'uri'
2
+ require 'pathname'
3
+
4
+ class Gatchaman
5
+ class Path < String
6
+ HTTP_REGEX = /^(?:shttp|http|https):/
7
+
8
+ def initialize(path, options = {})
9
+ @path = path
10
+ @document_root = options[:document_root]
11
+ @current_dir = options[:current_dir]
12
+ super(normalized)
13
+ end
14
+
15
+ def normalized
16
+ if @path =~ HTTP_REGEX
17
+ @path
18
+ else
19
+ path = Pathname.new(@path)
20
+ if path.relative?
21
+ Pathname.new(@current_dir).join(@path).to_s
22
+ else
23
+ Pathname.new(@document_root).join(path.relative_path_from(root)).to_s
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+ def root
30
+ Pathname.new("/")
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,3 @@
1
1
  class Gatchaman
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -7,7 +7,7 @@ describe Gatchaman do
7
7
  let(:document_root) {File.dirname(File.dirname(__FILE__))}
8
8
  let(:current_dir) {File.dirname(__FILE__)}
9
9
  let(:gatchaman){Gatchaman.new(document_root: document_root, current_dir: current_dir, expand_js: true, expand_css: true)}
10
- let(:base64_encoded_resouce){
10
+ let(:base64_encoded_resource){
11
11
  "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAGCAIAAABrW6giAAAACXBIWXMAA
12
12
  BYlAAAWJQFJUiTwAAABy2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPH
13
13
  g6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0
@@ -23,39 +23,54 @@ describe Gatchaman do
23
23
  bXBtZXRhPgrjpclbAAAAFUlEQVQIHWOUlJRkgAEmGANEk8MBABhmAFcTc
24
24
  YlpAAAAAElFTkSuQmCC".gsub(/[\s\n]/,'')
25
25
  }
26
- let(:test_css_content) { open("#{current_dir}/resouces/test.css").read.chomp }
27
- let(:test_js_content) { open("#{current_dir}/resouces/test.js").read.chomp }
26
+ let(:test_css_content) { open("#{current_dir}/resources/test.css").read.chomp }
27
+ let(:test_js_content) { open("#{current_dir}/resources/test.js").read.chomp }
28
28
 
29
29
  it "絶対urlのsrcをdata schemeで置き換えてくれること" do
30
- gatchaman.should_receive(:open).with("http://example.com/img/test.png", "r:ASCII-8BIT").
31
- and_return(Base64.decode64(base64_encoded_resouce))
30
+ Gatchaman::DataScheme.any_instance.should_receive(:open).with("http://example.com/img/test.png", "r:ASCII-8BIT").
31
+ and_return(Base64.decode64(base64_encoded_resource))
32
32
  gatchaman.data_uri_schemize("<img src='http://example.com/img/test.png'>").
33
- should == "<img src=\"data:image/png;base64,#{base64_encoded_resouce}\">"
33
+ should == "<img src=\"data:image/png;base64,#{base64_encoded_resource}\">"
34
34
  end
35
35
 
36
36
  it "相対urlの相対パスsrcをdata schemeで置き換えてくれること" do
37
- gatchaman.data_uri_schemize('<img src="resouces/test.png">').
38
- should == "<img src=\"data:image/png;base64,#{base64_encoded_resouce}\">"
37
+ gatchaman.data_uri_schemize('<img src="resources/test.png">').
38
+ should == "<img src=\"data:image/png;base64,#{base64_encoded_resource}\">"
39
39
  end
40
40
 
41
41
  it "相対urlの絶対パスsrcをdata schemeで置き換えてくれること" do
42
- gatchaman.data_uri_schemize('<img src="/spec/resouces/test.png">').
43
- should == "<img src=\"data:image/png;base64,#{base64_encoded_resouce}\">"
42
+ gatchaman.data_uri_schemize('<img src="/spec/resources/test.png">').
43
+ should == "<img src=\"data:image/png;base64,#{base64_encoded_resource}\">"
44
+ end
45
+
46
+ it "ルートにhtmlタグを含む場合、htmlページとして出力すること" do
47
+ gatchaman.data_uri_schemize('<html><body><h1>nyan!</h1></body></html>').
48
+ should match /^<html>/
49
+ end
50
+
51
+ it "ルートにhtmlタグを含まない場合、htmlの断片として出力すること" do
52
+ gatchaman.data_uri_schemize('<body><h1>nyan!</h1></body>').
53
+ should_not match /^<html>/
44
54
  end
45
55
 
46
56
  it "cssを展開してくれること" do
47
- gatchaman.data_uri_schemize('<link rel="stylesheet" type="text/css" media="screen" href="resouces/test.css">').
57
+ gatchaman.data_uri_schemize('<link rel="stylesheet" type="text/css" media="screen" href="resources/test.css">').
48
58
  should == %[<style type="text/css" media="screen">\n#{test_css_content}\n</style>]
49
59
  end
50
60
 
51
61
  it "css内部のurl参照を展開してくれること" do
52
- gatchaman.data_uri_schemize('<link rel="stylesheet" type="text/css" media="screen" href="resouces/test_2.css">').
53
- include?(base64_encoded_resouce).should be_true
62
+ gatchaman.data_uri_schemize('<link rel="stylesheet" type="text/css" media="screen" href="resources/test_2.css">').
63
+ include?(base64_encoded_resource).should be_true
64
+ end
65
+
66
+ it "styleタグ内部のURLを展開してくれること" do
67
+ gatchaman.data_uri_schemize('<style> * { background: url(/spec/resources/test.png); } </style>').
68
+ include?(base64_encoded_resource).should be_true
54
69
  end
55
70
 
56
71
  it "jsを展開してくれること" do
57
- gatchaman.data_uri_schemize('<script src="resouces/test.js" type="text/javascript" charset="utf-8"></script>').
58
- should == %[<script type="text/javascript">\n#{test_js_content}\n</script>]
72
+ gatchaman.data_uri_schemize('<script src="resources/test.js" type="text/javascript" charset="utf-8"></script>').
73
+ should == %[<script type="text/javascript"><!--\n\n#{test_js_content}\n\n--></script>]
59
74
  end
60
75
  end
61
76
  end
@@ -3,3 +3,15 @@
3
3
  body {
4
4
  background: url(resouces/test.png);
5
5
  }
6
+
7
+ .a {
8
+ background: url(resouces/test.png);
9
+ }
10
+
11
+ .b {
12
+ background: url(resouces/test.png);
13
+ }
14
+
15
+ .c {
16
+ background: url(resouces/test.png);
17
+ }
File without changes
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ /* Here is Comment */
2
+
3
+ body {
4
+ background: url(resources/test.png);
5
+ }
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gatchaman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Shinpei Maruyama
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-20 00:00:00.000000000 Z
11
+ date: 2013-03-18 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: nokogiri
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,7 +27,6 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: mime-types
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
31
  - - ~>
36
32
  - !ruby/object:Gem::Version
@@ -38,7 +34,6 @@ dependencies:
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
38
  - - ~>
44
39
  - !ruby/object:Gem::Version
@@ -46,7 +41,6 @@ dependencies:
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
45
  - - ~>
52
46
  - !ruby/object:Gem::Version
@@ -54,11 +48,24 @@ dependencies:
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
52
  - - ~>
60
53
  - !ruby/object:Gem::Version
61
54
  version: 2.12.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 10.0.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 10.0.3
62
69
  description: Gatchaman is a gem to replace src values in HTML documents with data
63
70
  URI scheme
64
71
  email:
@@ -77,42 +84,50 @@ files:
77
84
  - bin/gatchan
78
85
  - gatchaman.gemspec
79
86
  - lib/gatchaman.rb
87
+ - lib/gatchaman/data_scheme.rb
88
+ - lib/gatchaman/embedder.rb
89
+ - lib/gatchaman/embedder/css.rb
90
+ - lib/gatchaman/embedder/generic.rb
91
+ - lib/gatchaman/embedder/js.rb
92
+ - lib/gatchaman/embedder/media.rb
93
+ - lib/gatchaman/path.rb
80
94
  - lib/gatchaman/version.rb
81
95
  - spec/gatchaman_spec.rb
82
- - spec/resouces/test.css
83
- - spec/resouces/test.js
84
- - spec/resouces/test.png
85
96
  - spec/resouces/test_2.css
97
+ - spec/resources/test.css
98
+ - spec/resources/test.js
99
+ - spec/resources/test.png
100
+ - spec/resources/test_2.css
86
101
  - spec/spec_helper.rb
87
102
  homepage: https://github.com/Shinpeim/Gatchaman
88
103
  licenses: []
104
+ metadata: {}
89
105
  post_install_message:
90
106
  rdoc_options: []
91
107
  require_paths:
92
108
  - lib
93
109
  required_ruby_version: !ruby/object:Gem::Requirement
94
- none: false
95
110
  requirements:
96
- - - ! '>='
111
+ - - '>='
97
112
  - !ruby/object:Gem::Version
98
113
  version: '0'
99
114
  required_rubygems_version: !ruby/object:Gem::Requirement
100
- none: false
101
115
  requirements:
102
- - - ! '>='
116
+ - - '>='
103
117
  - !ruby/object:Gem::Version
104
118
  version: '0'
105
119
  requirements: []
106
120
  rubyforge_project:
107
- rubygems_version: 1.8.24
121
+ rubygems_version: 2.0.0
108
122
  signing_key:
109
- specification_version: 3
123
+ specification_version: 4
110
124
  summary: Gatchaman is a gem to replace src values in HTML documents with data URI
111
125
  scheme
112
126
  test_files:
113
127
  - spec/gatchaman_spec.rb
114
- - spec/resouces/test.css
115
- - spec/resouces/test.js
116
- - spec/resouces/test.png
117
128
  - spec/resouces/test_2.css
129
+ - spec/resources/test.css
130
+ - spec/resources/test.js
131
+ - spec/resources/test.png
132
+ - spec/resources/test_2.css
118
133
  - spec/spec_helper.rb