pdfkit 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pdfkit might be problematic. Click here for more details.
- data/Gemfile.lock +1 -1
- data/History.md +11 -1
- data/README.md +19 -16
- data/lib/pdfkit/configuration.rb +2 -2
- data/lib/pdfkit/middleware.rb +3 -1
- data/lib/pdfkit/pdfkit.rb +11 -15
- data/lib/pdfkit/version.rb +1 -1
- data/spec/middleware_spec.rb +40 -0
- data/spec/pdfkit_spec.rb +39 -0
- metadata +11 -5
data/Gemfile.lock
CHANGED
data/History.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
|
1
|
+
2011-06-17
|
2
|
+
==================
|
3
|
+
* Bump to 0.5.1
|
4
|
+
* Fix for response body coming through as an array.
|
5
|
+
* Added root_url configuration for setup where a host my not know its own name.
|
6
|
+
* Awareness of Bundler when looking for the wkhtmltopdf executable.
|
7
|
+
* Fix for file data getting truncated in Ruby 1.8.6
|
8
|
+
* Fix for 0.5.0 release getting stuck rendering all requests as PDFs.
|
9
|
+
* More robust meta tag detection.
|
10
|
+
|
11
|
+
2010-12-27
|
2
12
|
==================
|
3
13
|
* Bump to 0.5.0
|
4
14
|
* Switched to popen - adds support for JRuby and Windows
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# PDFKit
|
2
2
|
|
3
|
-
Create PDFs using plain old HTML+CSS. Uses [wkhtmltopdf](http://github.com/antialize/wkhtmltopdf) on the
|
3
|
+
Create PDFs using plain old HTML+CSS. Uses [wkhtmltopdf](http://github.com/antialize/wkhtmltopdf) on the back-end which renders HTML using Webkit.
|
4
4
|
|
5
5
|
## Install
|
6
6
|
|
@@ -10,11 +10,11 @@ Create PDFs using plain old HTML+CSS. Uses [wkhtmltopdf](http://github.com/antia
|
|
10
10
|
|
11
11
|
### wkhtmltopdf
|
12
12
|
|
13
|
-
1. Install by hand (
|
13
|
+
1. Install by hand (recommended):
|
14
14
|
|
15
|
-
|
15
|
+
<https://github.com/jdpace/PDFKit/wiki/Installing-WKHTMLTOPDF>
|
16
16
|
|
17
|
-
2.
|
17
|
+
2. Try using the wkhtmltopdf-binary gem (mac + linux i386)
|
18
18
|
|
19
19
|
gem install wkhtmltopdf-binary
|
20
20
|
|
@@ -47,11 +47,12 @@ If you're on Windows or you installed wkhtmltopdf by hand to a location other th
|
|
47
47
|
|
48
48
|
# config/initializers/pdfkit.rb
|
49
49
|
PDFKit.configure do |config|
|
50
|
-
config.wkhtmltopdf = '/path/to/wkhtmltopdf'
|
51
|
-
config.default_options = {
|
52
|
-
|
53
|
-
|
54
|
-
}
|
50
|
+
# config.wkhtmltopdf = '/path/to/wkhtmltopdf'
|
51
|
+
# config.default_options = {
|
52
|
+
# :page_size => 'Legal',
|
53
|
+
# :print_media_type => true
|
54
|
+
# }
|
55
|
+
# config.root_url = "http://localhost" # Use only if your external hostname is unavailable on the server.
|
55
56
|
end
|
56
57
|
|
57
58
|
## Middleware
|
@@ -79,7 +80,7 @@ PDFKit comes with a middleware that allows users to get a PDF view of any page o
|
|
79
80
|
|
80
81
|
**With conditions to limit routes that can be generated in pdf**
|
81
82
|
|
82
|
-
# conditions can be
|
83
|
+
# conditions can be regexps (either one or an array)
|
83
84
|
config.middleware.use PDFKit::Middleware, {}, :only => %r[^/public]
|
84
85
|
config.middleware.use PDFKit::Middleware, {}, :only => [%r[^/invoice], %r[^/public]]
|
85
86
|
|
@@ -89,8 +90,8 @@ PDFKit comes with a middleware that allows users to get a PDF view of any page o
|
|
89
90
|
|
90
91
|
## Troubleshooting
|
91
92
|
|
92
|
-
* **Single thread issue:** In development environments it is common to run a
|
93
|
-
single server process. This can cause issues when rendering your pdf
|
93
|
+
* **Single thread issue:** In development environments it is common to run a
|
94
|
+
single server process. This can cause issues when rendering your pdf
|
94
95
|
requires wkhtmltopdf to hit your server again (for images, js, css).
|
95
96
|
This is because the resource requests will get blocked by the initial
|
96
97
|
request and the initial request will be waiting on the resource
|
@@ -101,13 +102,15 @@ PDFKit comes with a middleware that allows users to get a PDF view of any page o
|
|
101
102
|
like Passenger or try to embed your resources within your HTML to
|
102
103
|
avoid extra HTTP requests.
|
103
104
|
|
104
|
-
* **Resources aren't included in the PDF:** Images, CSS, or
|
105
|
+
* **Resources aren't included in the PDF:** Images, CSS, or JavaScript
|
105
106
|
does not seem to be downloading correctly in the PDF. This is due
|
106
107
|
to the fact that wkhtmltopdf does not know where to find those files.
|
107
108
|
Make sure you are using absolute paths (start with forward slash) to
|
108
|
-
your resources. If you are using PDFKit to generate
|
109
|
-
HTML source make sure you use complete paths (either file paths or
|
110
|
-
urls including the domain).
|
109
|
+
your resources. If you are using PDFKit to generate PDFs from a raw
|
110
|
+
HTML source make sure you use complete paths (either file paths or
|
111
|
+
urls including the domain). In restrictive server environments the
|
112
|
+
root_url configuration may be what you are looking for change your
|
113
|
+
asset host.
|
111
114
|
|
112
115
|
## TODO
|
113
116
|
- add amd64 support in --install-wkhtmltopdf
|
data/lib/pdfkit/configuration.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class PDFKit
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :meta_tag_prefix, :default_options
|
3
|
+
attr_accessor :meta_tag_prefix, :default_options, :root_url
|
4
4
|
attr_writer :wkhtmltopdf
|
5
5
|
|
6
6
|
def initialize
|
@@ -17,7 +17,7 @@ class PDFKit
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def wkhtmltopdf
|
20
|
-
@wkhtmltopdf ||= `which wkhtmltopdf
|
20
|
+
@wkhtmltopdf ||= (defined?(Bundler) ? `bundle exec which wkhtmltopdf` : `which wkhtmltopdf`).chomp
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
data/lib/pdfkit/middleware.rb
CHANGED
@@ -10,12 +10,14 @@ class PDFKit
|
|
10
10
|
|
11
11
|
def call(env)
|
12
12
|
@request = Rack::Request.new(env)
|
13
|
+
@render_pdf = false
|
13
14
|
|
14
15
|
set_request_to_render_as_pdf(env) if render_as_pdf?
|
15
16
|
status, headers, response = @app.call(env)
|
16
17
|
|
17
18
|
if rendering_pdf? && headers['Content-Type'] =~ /text\/html|application\/xhtml\+xml/
|
18
19
|
body = response.respond_to?(:body) ? response.body : response.join
|
20
|
+
body = body.join if body.is_a?(Array)
|
19
21
|
body = PDFKit.new(translate_paths(body, env), @options).to_pdf
|
20
22
|
response = [body]
|
21
23
|
|
@@ -35,7 +37,7 @@ class PDFKit
|
|
35
37
|
# Change relative paths to absolute
|
36
38
|
def translate_paths(body, env)
|
37
39
|
# Host with protocol
|
38
|
-
root = "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/"
|
40
|
+
root = PDFKit.configuration.root_url || "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}/"
|
39
41
|
|
40
42
|
body.gsub(/(href|src)=(['"])\/([^\"']*|[^"']*)['"]/, '\1=\2' + root + '\3\2')
|
41
43
|
end
|
data/lib/pdfkit/pdfkit.rb
CHANGED
@@ -61,7 +61,7 @@ class PDFKit
|
|
61
61
|
args = command(path)
|
62
62
|
invoke = args.join(' ')
|
63
63
|
|
64
|
-
result = IO.popen(invoke, "
|
64
|
+
result = IO.popen(invoke, "wb+") do |pdf|
|
65
65
|
pdf.puts(@source.to_s) if @source.html?
|
66
66
|
pdf.close_write
|
67
67
|
pdf.gets(nil)
|
@@ -79,23 +79,19 @@ class PDFKit
|
|
79
79
|
|
80
80
|
protected
|
81
81
|
|
82
|
-
def find_options_in_meta(
|
83
|
-
|
84
|
-
|
85
|
-
found.merge(name => tag.attributes["content"])
|
86
|
-
end
|
87
|
-
end
|
82
|
+
def find_options_in_meta(content)
|
83
|
+
# Read file if content is a File
|
84
|
+
content = content.read if content.is_a?(File)
|
88
85
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
86
|
+
found = {}
|
87
|
+
content.scan(/<meta [^>]*>/) do |meta|
|
88
|
+
if meta.match(/name=["']#{PDFKit.configuration.meta_tag_prefix}/)
|
89
|
+
name = meta.scan(/name=["']#{PDFKit.configuration.meta_tag_prefix}([^"']*)/)[0][0]
|
90
|
+
found[name] = meta.scan(/content=["']([^"']*)/)[0][0]
|
91
|
+
end
|
95
92
|
end
|
93
|
+
|
96
94
|
found
|
97
|
-
rescue # rexml random crash on invalid xml
|
98
|
-
[]
|
99
95
|
end
|
100
96
|
|
101
97
|
def style_tag_for(stylesheet)
|
data/lib/pdfkit/version.rb
CHANGED
data/spec/middleware_spec.rb
CHANGED
@@ -151,5 +151,45 @@ describe PDFKit::Middleware do
|
|
151
151
|
body.should == "NO MATCH"
|
152
152
|
end
|
153
153
|
end
|
154
|
+
|
155
|
+
describe "#translate_paths with root_url configuration" do
|
156
|
+
before do
|
157
|
+
@pdf = PDFKit::Middleware.new({})
|
158
|
+
@env = { 'REQUEST_URI' => 'http://example.com/document.pdf', 'rack.url_scheme' => 'http', 'HTTP_HOST' => 'example.com' }
|
159
|
+
PDFKit.configure do |config|
|
160
|
+
config.root_url = "http://example.net/"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should add the root_url" do
|
165
|
+
@body = %{<html><head><link href='/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src="/test.png" /></body></html>}
|
166
|
+
body = @pdf.send :translate_paths, @body, @env
|
167
|
+
body.should == "<html><head><link href='http://example.net/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src=\"http://example.net/test.png\" /></body></html>"
|
168
|
+
end
|
169
|
+
|
170
|
+
after do
|
171
|
+
PDFKit.configure do |config|
|
172
|
+
config.root_url = nil
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should not get stuck rendering each request as pdf" do
|
178
|
+
mock_app
|
179
|
+
# false by default. No requests.
|
180
|
+
@app.send(:rendering_pdf?).should be_false
|
181
|
+
|
182
|
+
# Remain false on a normal request
|
183
|
+
get 'http://www.example.org/public/file'
|
184
|
+
@app.send(:rendering_pdf?).should be_false
|
185
|
+
|
186
|
+
# Return true on a pdf request.
|
187
|
+
get 'http://www.example.org/public/file.pdf'
|
188
|
+
@app.send(:rendering_pdf?).should be_true
|
189
|
+
|
190
|
+
# Restore to false on any non-pdf request.
|
191
|
+
get 'http://www.example.org/public/file'
|
192
|
+
@app.send(:rendering_pdf?).should be_false
|
193
|
+
end
|
154
194
|
|
155
195
|
end
|
data/spec/pdfkit_spec.rb
CHANGED
@@ -105,6 +105,36 @@ describe PDFKit do
|
|
105
105
|
pdfkit.command[pdfkit.command.index('"--page-size"') + 1].should == '"Legal"'
|
106
106
|
pdfkit.command[pdfkit.command.index('"--orientation"') + 1].should == '"Landscape"'
|
107
107
|
end
|
108
|
+
|
109
|
+
it "should detect special pdfkit meta tags despite bad markup" do
|
110
|
+
body = %{
|
111
|
+
<html>
|
112
|
+
<head>
|
113
|
+
<meta name="pdfkit-page_size" content="Legal"/>
|
114
|
+
<meta name="pdfkit-orientation" content="Landscape"/>
|
115
|
+
</head>
|
116
|
+
<br>
|
117
|
+
</html>
|
118
|
+
}
|
119
|
+
pdfkit = PDFKit.new(body)
|
120
|
+
pdfkit.command[pdfkit.command.index('"--page-size"') + 1].should == '"Legal"'
|
121
|
+
pdfkit.command[pdfkit.command.index('"--orientation"') + 1].should == '"Landscape"'
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should skip non-pdfkit meta tags" do
|
125
|
+
body = %{
|
126
|
+
<html>
|
127
|
+
<head>
|
128
|
+
<meta name="test-page_size" content="Legal"/>
|
129
|
+
<meta name="pdfkit-orientation" content="Landscape"/>
|
130
|
+
</head>
|
131
|
+
<br>
|
132
|
+
</html>
|
133
|
+
}
|
134
|
+
pdfkit = PDFKit.new(body)
|
135
|
+
pdfkit.command[pdfkit.command.index('"--orientation"') + 1].should == '"Landscape"'
|
136
|
+
end
|
137
|
+
|
108
138
|
end
|
109
139
|
|
110
140
|
context "#to_pdf" do
|
@@ -166,6 +196,15 @@ describe PDFKit do
|
|
166
196
|
file.should be_instance_of(File)
|
167
197
|
File.read(file.path)[0...4].should == "%PDF" # PDF Signature at beginning of file
|
168
198
|
end
|
199
|
+
|
200
|
+
it "should not truncate data (in Ruby 1.8.6)" do
|
201
|
+
file_path = File.join(SPEC_ROOT,'fixtures','example.html')
|
202
|
+
pdfkit = PDFKit.new(File.new(file_path))
|
203
|
+
pdf_data = pdfkit.to_pdf
|
204
|
+
file = pdfkit.to_file(@file_path)
|
205
|
+
file_data = open(@file_path, 'rb') {|io| io.read }
|
206
|
+
pdf_data.size.should == file_data.size
|
207
|
+
end
|
169
208
|
end
|
170
209
|
|
171
210
|
context "security" do
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pdfkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 9
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 5
|
8
|
-
-
|
9
|
-
version: 0.5.
|
9
|
+
- 1
|
10
|
+
version: 0.5.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Jared Pace
|
@@ -15,7 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
+
date: 2011-06-17 00:00:00 -06:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -26,6 +27,7 @@ dependencies:
|
|
26
27
|
requirements:
|
27
28
|
- - ~>
|
28
29
|
- !ruby/object:Gem::Version
|
30
|
+
hash: 7
|
29
31
|
segments:
|
30
32
|
- 2
|
31
33
|
- 2
|
@@ -41,6 +43,7 @@ dependencies:
|
|
41
43
|
requirements:
|
42
44
|
- - ">="
|
43
45
|
- !ruby/object:Gem::Version
|
46
|
+
hash: 47
|
44
47
|
segments:
|
45
48
|
- 0
|
46
49
|
- 9
|
@@ -56,6 +59,7 @@ dependencies:
|
|
56
59
|
requirements:
|
57
60
|
- - ">="
|
58
61
|
- !ruby/object:Gem::Version
|
62
|
+
hash: 7
|
59
63
|
segments:
|
60
64
|
- 0
|
61
65
|
- 5
|
@@ -110,6 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
110
114
|
requirements:
|
111
115
|
- - ">="
|
112
116
|
- !ruby/object:Gem::Version
|
117
|
+
hash: 3
|
113
118
|
segments:
|
114
119
|
- 0
|
115
120
|
version: "0"
|
@@ -118,13 +123,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
123
|
requirements:
|
119
124
|
- - ">="
|
120
125
|
- !ruby/object:Gem::Version
|
126
|
+
hash: 3
|
121
127
|
segments:
|
122
128
|
- 0
|
123
129
|
version: "0"
|
124
130
|
requirements: []
|
125
131
|
|
126
132
|
rubyforge_project: pdfkit
|
127
|
-
rubygems_version: 1.
|
133
|
+
rubygems_version: 1.6.2
|
128
134
|
signing_key:
|
129
135
|
specification_version: 3
|
130
136
|
summary: HTML+CSS -> PDF
|