adamh-html_render 0.0.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.
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
+