adamh-html_render 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest ADDED
@@ -0,0 +1,8 @@
1
+ README.rdoc
2
+ Rakefile
3
+ html_render.gemspec
4
+ lib/html_render.rb
5
+ lib/html_render/render_batches.rb
6
+ lib/html_render/renderers.rb
7
+ lib/html_render/images.rb
8
+ Manifest
data/README.rdoc ADDED
@@ -0,0 +1,55 @@
1
+ = html_render
2
+
3
+ html_render translates strings of HTML into PNG images.
4
+
5
+ The procedure is anything but magical. The process amounts to:
6
+
7
+ 0. POST the HTML to a URL which translates HTML into PNG.
8
+ 0. Read in the response.
9
+
10
+ The benefit comes when different URLs translate HTML into PNG differently.
11
+ With logic spanning many operating systems and web browser libraries, it is
12
+ possible to render several different PNGs for the same HTML. We can compare
13
+ the different PNGs to determine if our HTML is exposing a browser bug.
14
+
15
+ == Install
16
+
17
+ gem install adamh-html_render --source http://gems.github.com
18
+
19
+ == Example code
20
+
21
+ require 'rubygems'
22
+ require 'html_render'
23
+
24
+ ff3_renderer = HTMLRender::Renderers::HTTPRenderer.new('http://localhost:20558/ff3-linux')
25
+ ie6_renderer = HTMLRender::Renderers::HTTPRenderer.new('http://winxp-ie6.local:20558/ie')
26
+
27
+ html = '<html><body>Here is my HTML!</body></html>'
28
+
29
+ ff3_image = ff3_renderer.render(html)
30
+ ie6_image = ie6_renderer.render(html)
31
+
32
+ if ff3_image != ie6_image
33
+ puts 'Images differ! Differences recorded in diff.png'
34
+ diff = ff3_image.difference(ie6_image)
35
+ File.open('diff.png', 'w') { |f| f.write(diff.to_blob) }
36
+ end
37
+
38
+ == Usefulness
39
+
40
+ Because of different text-rendering engines, different browsers and operating
41
+ systems will almost always produce differing PNG files. The
42
+ +HTMLRender::Images::PNGImage.difference+ method produces a graphic with which
43
+ a person can quickly determine whether the changes are significant or not.
44
+
45
+ The intent behind this design--producing comparison images rather than using
46
+ fuzzy image matching--is for a manual verification process: presenting a user
47
+ with a list of rendered images so the user can quickly determine which images
48
+ are acceptable and which indicate a bug in the HTML (or, more commonly, a bug
49
+ in the browser which the HTML must work around). The engineering of such a
50
+ workflow is beyond the scope of this project.
51
+
52
+ == Dependencies
53
+
54
+ - httpclient >=2.1.4
55
+ - RMagick >= 2.9.1
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('html_render', '0.0.1') do |p|
6
+ p.description = 'Make images from HTML strings'
7
+ p.url = 'http://adamhooper.com/eng'
8
+ p.author = 'Adam Hooper'
9
+ p.email = 'adam@adamhooper.com'
10
+ p.runtime_dependencies = [ 'httpclient >=2.1.4', 'rmagick >=2.9.1' ]
11
+ end
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{html_render}
3
+ s.version = "0.0.1"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Adam Hooper"]
7
+ s.date = %q{2009-03-06}
8
+ s.description = %q{Make images from HTML strings}
9
+ s.email = %q{adam@adamhooper.com}
10
+ s.extra_rdoc_files = ["README.rdoc", "lib/html_render.rb", "lib/html_render/render_batches.rb", "lib/html_render/renderers.rb", "lib/html_render/images.rb"]
11
+ s.files = ["README.rdoc", "Rakefile", "html_render.gemspec", "lib/html_render.rb", "lib/html_render/render_batches.rb", "lib/html_render/renderers.rb", "lib/html_render/images.rb", "Manifest"]
12
+ s.has_rdoc = true
13
+ s.homepage = %q{http://adamhooper.com/eng}
14
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Html_render", "--main", "README.rdoc"]
15
+ s.require_paths = ["lib"]
16
+ s.rubyforge_project = %q{html_render}
17
+ s.rubygems_version = %q{1.2.0}
18
+ s.summary = %q{Make images from HTML strings}
19
+
20
+ if s.respond_to? :specification_version then
21
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
22
+ s.specification_version = 2
23
+
24
+ if current_version >= 3 then
25
+ s.add_runtime_dependency(%q<httpclient>, [">= 2.1.4"])
26
+ s.add_runtime_dependency(%q<rmagick>, [">= 2.9.1"])
27
+ s.add_development_dependency(%q<echoe>, [">= 0"])
28
+ else
29
+ s.add_dependency(%q<httpclient>, [">= 2.1.4"])
30
+ s.add_dependency(%q<rmagick>, [">= 2.9.1"])
31
+ s.add_dependency(%q<echoe>, [">= 0"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<httpclient>, [">= 2.1.4"])
35
+ s.add_dependency(%q<rmagick>, [">= 2.9.1"])
36
+ s.add_dependency(%q<echoe>, [">= 0"])
37
+ end
38
+ end
@@ -0,0 +1,47 @@
1
+ require 'RMagick'
2
+ require 'tempfile'
3
+
4
+ module HTMLRender; end
5
+
6
+ module HTMLRender::Images
7
+ class Base
8
+ def ==(other)
9
+ return false unless self.class === other
10
+ (self <=> other) == 0
11
+ end
12
+
13
+ def difference(other)
14
+ raise NotImplementedError
15
+ end
16
+ end
17
+
18
+ class PNGImage < Base
19
+ attr_reader :png
20
+
21
+ def initialize(data)
22
+ @png = Magick::Image.from_blob(data)[0]
23
+ end
24
+
25
+ def <=>(other)
26
+ (png <=> other.png) == 0
27
+ end
28
+
29
+ def difference(other)
30
+ raise NotImplementedError unless PNGImage === other
31
+
32
+ rows = [ png.rows, other.png.rows ].max
33
+ columns = [ png.columns, other.png.columns ].max
34
+
35
+ image = Magick::Image.new(columns, rows) do |info|
36
+ info.format = 'png'
37
+ end
38
+ image.background_color = 'black'
39
+ image.composite!(png, 0, 0, Magick::OverCompositeOp)
40
+ image.composite!(other.png, 0, 0, Magick::DifferenceCompositeOp)
41
+ end
42
+
43
+ def to_blob
44
+ png.to_blob
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,43 @@
1
+ require 'html_render/renderers'
2
+
3
+ module HTMLRender; end
4
+ module HTMLRender::RenderBatches
5
+ class HTTPRenderBatch
6
+ attr_reader :servers
7
+
8
+ # +servers+: Hash of (String) key to (String) URL to pass to
9
+ # HTTPRenderer
10
+ def initialize(servers)
11
+ @servers = servers
12
+ end
13
+
14
+ # +html+: HTML to render
15
+ # +directory+: Directory in which to dump PNG files (one per server)
16
+ def render_html_to_directory(html, directory)
17
+ threads = create_threads(html, directory)
18
+ threads.each { |t| t.join }
19
+ end
20
+
21
+ private
22
+
23
+ def create_threads(html, dir)
24
+ threads = []
25
+
26
+ servers.each do |key, url|
27
+ threads << create_thread(html, url, File.join(dir, "#{key}.png"))
28
+ end
29
+
30
+ threads
31
+ end
32
+
33
+ def create_thread(html, url, filename)
34
+ Thread.new(html, url, filename) do |html, url, filename|
35
+ renderer = HTMLRender::Renderers::HTTPRenderer.new(url)
36
+ image = renderer.render(html)
37
+ File.open(filename, 'w') do |f|
38
+ f.write(image.to_blob)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,35 @@
1
+ require 'httpclient'
2
+
3
+ require 'html_render/images'
4
+
5
+ module HTMLRender; end
6
+ module HTMLRender::Renderers
7
+ class Base
8
+ def render(html)
9
+ raise NotImplementedError
10
+ end
11
+ end
12
+
13
+ # Renders using an HTTP server built for the very purpose.
14
+ #
15
+ # One should POST the HTML to the given URL, and the server should
16
+ # respond with a PNG image.
17
+ class HTTPRenderer < Base
18
+ attr_accessor :url
19
+
20
+ def initialize(url)
21
+ @url = url
22
+ end
23
+
24
+ def render(html)
25
+ client = HTTPClient.new
26
+
27
+ response = client.post(url, html)
28
+ if response.status != 200
29
+ raise Exception.new("Unexpected HTTP server response from #{url}: #{response.inspect}")
30
+ end
31
+
32
+ HTMLRender::Images::PNGImage.new(response.content)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ require 'html_render/images'
2
+ require 'html_render/renderers'
3
+ require 'html_render/render_batches'
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: adamh-html_render
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Adam Hooper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-06 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: httpclient
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.4
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rmagick
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.9.1
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: echoe
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Make images from HTML strings
46
+ email: adam@adamhooper.com
47
+ executables: []
48
+
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README.rdoc
53
+ - lib/html_render.rb
54
+ - lib/html_render/render_batches.rb
55
+ - lib/html_render/renderers.rb
56
+ - lib/html_render/images.rb
57
+ files:
58
+ - README.rdoc
59
+ - Rakefile
60
+ - html_render.gemspec
61
+ - lib/html_render.rb
62
+ - lib/html_render/render_batches.rb
63
+ - lib/html_render/renderers.rb
64
+ - lib/html_render/images.rb
65
+ - Manifest
66
+ has_rdoc: true
67
+ homepage: http://adamhooper.com/eng
68
+ post_install_message:
69
+ rdoc_options:
70
+ - --line-numbers
71
+ - --inline-source
72
+ - --title
73
+ - Html_render
74
+ - --main
75
+ - README.rdoc
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ version:
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: "1.2"
89
+ version:
90
+ requirements: []
91
+
92
+ rubyforge_project: html_render
93
+ rubygems_version: 1.2.0
94
+ signing_key:
95
+ specification_version: 2
96
+ summary: Make images from HTML strings
97
+ test_files: []
98
+