weasyprint 0.1.0
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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +24 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +50 -0
- data/LICENSE +20 -0
- data/POST_INSTALL +9 -0
- data/README.md +131 -0
- data/Rakefile +24 -0
- data/lib/weasyprint.rb +4 -0
- data/lib/weasyprint/configuration.rb +47 -0
- data/lib/weasyprint/middleware.rb +102 -0
- data/lib/weasyprint/source.rb +23 -0
- data/lib/weasyprint/version.rb +3 -0
- data/lib/weasyprint/weasyprint.rb +154 -0
- data/spec/fixtures/example.css +1 -0
- data/spec/fixtures/example.html +5 -0
- data/spec/fixtures/example_with_hex_symbol.css +3 -0
- data/spec/middleware_spec.rb +384 -0
- data/spec/source_spec.rb +78 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/weasyprint_spec.rb +342 -0
- data/weasyprint.gemspec +29 -0
- metadata +164 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
class WeasyPrint
|
2
|
+
class Source
|
3
|
+
def initialize(url_file_or_html)
|
4
|
+
@source = url_file_or_html
|
5
|
+
end
|
6
|
+
|
7
|
+
def url?
|
8
|
+
@source.is_a?(String) && @source.match(/\Ahttp/)
|
9
|
+
end
|
10
|
+
|
11
|
+
def file?
|
12
|
+
@source.kind_of?(File)
|
13
|
+
end
|
14
|
+
|
15
|
+
def html?
|
16
|
+
!(url? || file?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
file? ? @source.path : @source
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
class WeasyPrint
|
4
|
+
|
5
|
+
class NoExecutableError < StandardError
|
6
|
+
def initialize
|
7
|
+
msg = "No weasyprint executable found at #{WeasyPrint.configuration.weasyprint}\n"
|
8
|
+
msg << ">> Please install weasyprint - http://weasyprint.org/docs/install/"
|
9
|
+
super(msg)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ImproperSourceError < StandardError
|
14
|
+
def initialize(msg)
|
15
|
+
super("Improper Source: #{msg}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :source, :stylesheets
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
def initialize(url_file_or_html, options = {})
|
23
|
+
@source = Source.new(url_file_or_html)
|
24
|
+
|
25
|
+
@stylesheets = []
|
26
|
+
|
27
|
+
@options = WeasyPrint.configuration.default_options.merge(options)
|
28
|
+
@options = normalize_options(@options)
|
29
|
+
|
30
|
+
raise NoExecutableError.new unless File.exists?(WeasyPrint.configuration.weasyprint)
|
31
|
+
end
|
32
|
+
|
33
|
+
def command(path = nil)
|
34
|
+
args = [executable]
|
35
|
+
args += @options.to_a.flatten.compact
|
36
|
+
|
37
|
+
if @source.html?
|
38
|
+
args << '-' # Get HTML from stdin
|
39
|
+
else
|
40
|
+
args << @source.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
args << (path || '-') # Write to file or stdout
|
44
|
+
|
45
|
+
args.shelljoin
|
46
|
+
end
|
47
|
+
|
48
|
+
def executable
|
49
|
+
default = WeasyPrint.configuration.weasyprint
|
50
|
+
return default if default !~ /^\// # its not a path, so nothing we can do
|
51
|
+
if File.exist?(default)
|
52
|
+
default
|
53
|
+
else
|
54
|
+
default.split('/').last
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_pdf(path=nil)
|
59
|
+
append_stylesheets
|
60
|
+
|
61
|
+
invoke = command(path)
|
62
|
+
|
63
|
+
result = IO.popen(invoke, "wb+") do |pdf|
|
64
|
+
pdf.puts(@source.to_s) if @source.html?
|
65
|
+
pdf.close_write
|
66
|
+
pdf.gets(nil)
|
67
|
+
end
|
68
|
+
result = File.read(path) if path
|
69
|
+
|
70
|
+
# $? is thread safe per http://stackoverflow.com/questions/2164887/thread-safe-external-process-in-ruby-plus-checking-exitstatus
|
71
|
+
raise "command failed (exitstatus=#{$?.exitstatus}): #{invoke}" if result.to_s.strip.empty? or !successful?($?)
|
72
|
+
return result
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_file(path)
|
76
|
+
self.to_pdf(path)
|
77
|
+
File.new(path)
|
78
|
+
end
|
79
|
+
|
80
|
+
protected
|
81
|
+
|
82
|
+
REPEATABLE_OPTIONS = %w[]
|
83
|
+
|
84
|
+
def style_tag_for(stylesheet)
|
85
|
+
"<style>#{File.read(stylesheet)}</style>"
|
86
|
+
end
|
87
|
+
|
88
|
+
def append_stylesheets
|
89
|
+
raise ImproperSourceError.new('Stylesheets may only be added to an HTML source') if stylesheets.any? && !@source.html?
|
90
|
+
|
91
|
+
stylesheets.each do |stylesheet|
|
92
|
+
if @source.to_s.match(/<\/head>/)
|
93
|
+
@source = Source.new(@source.to_s.gsub(/(<\/head>)/) {|s| style_tag_for(stylesheet) + s })
|
94
|
+
else
|
95
|
+
@source.to_s.insert(0, style_tag_for(stylesheet))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def normalize_options(options)
|
101
|
+
normalized_options = {}
|
102
|
+
|
103
|
+
options.each do |key, value|
|
104
|
+
next if !value
|
105
|
+
|
106
|
+
# The actual option for weasyprint
|
107
|
+
normalized_key = "--#{normalize_arg key}"
|
108
|
+
|
109
|
+
# If the option is repeatable, attempt to normalize all values
|
110
|
+
if REPEATABLE_OPTIONS.include? normalized_key
|
111
|
+
normalize_repeatable_value(value) do |normalized_key_piece, normalized_value|
|
112
|
+
normalized_options[[normalized_key, normalized_key_piece]] = normalized_value
|
113
|
+
end
|
114
|
+
else # Otherwise, just normalize it like usual
|
115
|
+
normalized_options[normalized_key] = normalize_value(value)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
normalized_options
|
120
|
+
end
|
121
|
+
|
122
|
+
def normalize_arg(arg)
|
123
|
+
arg.to_s.downcase.gsub(/[^a-z0-9]/,'-')
|
124
|
+
end
|
125
|
+
|
126
|
+
def normalize_value(value)
|
127
|
+
case value
|
128
|
+
when TrueClass, 'true' #ie, ==true, see http://www.ruby-doc.org/core-1.9.3/TrueClass.html
|
129
|
+
nil
|
130
|
+
when Hash
|
131
|
+
value.to_a.flatten.collect{|x| normalize_value(x)}.compact
|
132
|
+
when Array
|
133
|
+
value.flatten.collect{|x| x.to_s}
|
134
|
+
else
|
135
|
+
value.to_s
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def normalize_repeatable_value(value)
|
140
|
+
case value
|
141
|
+
when Hash, Array
|
142
|
+
value.each do |(key, value)|
|
143
|
+
yield [normalize_value(key), normalize_value(value)]
|
144
|
+
end
|
145
|
+
else
|
146
|
+
[normalize_value(value), '']
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def successful?(status)
|
151
|
+
status.success?
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
body { font-size: 20px; }
|
@@ -0,0 +1,384 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def app; Rack::Lint.new(@app); end
|
4
|
+
|
5
|
+
def mock_app(options = {}, conditions = {}, custom_headers = {})
|
6
|
+
main_app = lambda { |env|
|
7
|
+
@env = env
|
8
|
+
full_headers = headers.merge custom_headers
|
9
|
+
[200, full_headers, @body || ['Hello world!']]
|
10
|
+
}
|
11
|
+
|
12
|
+
builder = Rack::Builder.new
|
13
|
+
builder.use WeasyPrint::Middleware, options, conditions
|
14
|
+
builder.run main_app
|
15
|
+
@app = builder.to_app
|
16
|
+
end
|
17
|
+
|
18
|
+
describe WeasyPrint::Middleware do
|
19
|
+
let(:headers) { {'Content-Type' => "text/html"} }
|
20
|
+
|
21
|
+
describe "#call" do
|
22
|
+
describe "caching" do
|
23
|
+
let(:headers) { {'Content-Type' => "text/html", 'ETag' => 'foo', 'Cache-Control' => 'max-age=2592000, public'} }
|
24
|
+
|
25
|
+
context "by default" do
|
26
|
+
before { mock_app }
|
27
|
+
|
28
|
+
it "deletes ETag" do
|
29
|
+
get 'http://www.example.org/public/test.pdf'
|
30
|
+
expect(last_response.headers["ETag"]).to be_nil
|
31
|
+
end
|
32
|
+
it "deletes Cache-Control" do
|
33
|
+
get 'http://www.example.org/public/test.pdf'
|
34
|
+
expect(last_response.headers["Cache-Control"]).to be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when on" do
|
39
|
+
before { mock_app({}, :caching => true) }
|
40
|
+
|
41
|
+
it "preserves ETag" do
|
42
|
+
get 'http://www.example.org/public/test.pdf'
|
43
|
+
expect(last_response.headers["ETag"]).not_to be_nil
|
44
|
+
end
|
45
|
+
it "preserves Cache-Control" do
|
46
|
+
get 'http://www.example.org/public/test.pdf'
|
47
|
+
expect(last_response.headers["Cache-Control"]).not_to be_nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "conditions" do
|
53
|
+
describe ":only" do
|
54
|
+
|
55
|
+
describe "regex" do
|
56
|
+
describe "one" do
|
57
|
+
before { mock_app({}, :only => %r[^/public]) }
|
58
|
+
|
59
|
+
context "matching" do
|
60
|
+
specify do
|
61
|
+
get 'http://www.example.org/public/test.pdf'
|
62
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
63
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "not matching" do
|
68
|
+
specify do
|
69
|
+
get 'http://www.example.org/secret/test.pdf'
|
70
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
71
|
+
expect(last_response.body).to eq("Hello world!")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end # one regex
|
75
|
+
|
76
|
+
describe "multiple" do
|
77
|
+
before { mock_app({}, :only => [%r[^/invoice], %r[^/public]]) }
|
78
|
+
|
79
|
+
context "matching" do
|
80
|
+
specify do
|
81
|
+
get 'http://www.example.org/public/test.pdf'
|
82
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
83
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "not matching" do
|
88
|
+
specify do
|
89
|
+
get 'http://www.example.org/secret/test.pdf'
|
90
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
91
|
+
expect(last_response.body).to eq("Hello world!")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end # multiple regex
|
95
|
+
end # regex
|
96
|
+
|
97
|
+
describe "string" do
|
98
|
+
describe "one" do
|
99
|
+
before { mock_app({}, :only => '/public') }
|
100
|
+
|
101
|
+
context "matching" do
|
102
|
+
specify do
|
103
|
+
get 'http://www.example.org/public/test.pdf'
|
104
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
105
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context "not matching" do
|
110
|
+
specify do
|
111
|
+
get 'http://www.example.org/secret/test.pdf'
|
112
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
113
|
+
expect(last_response.body).to eq("Hello world!")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end # one string
|
117
|
+
|
118
|
+
describe "multiple" do
|
119
|
+
before { mock_app({}, :only => ['/invoice', '/public']) }
|
120
|
+
|
121
|
+
context "matching" do
|
122
|
+
specify do
|
123
|
+
get 'http://www.example.org/public/test.pdf'
|
124
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
125
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "not matching" do
|
130
|
+
specify do
|
131
|
+
get 'http://www.example.org/secret/test.pdf'
|
132
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
133
|
+
expect(last_response.body).to eq("Hello world!")
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end # multiple string
|
137
|
+
end # string
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
describe ":except" do
|
142
|
+
|
143
|
+
describe "regex" do
|
144
|
+
describe "one" do
|
145
|
+
before { mock_app({}, :except => %r[^/secret]) }
|
146
|
+
|
147
|
+
context "matching" do
|
148
|
+
specify do
|
149
|
+
get 'http://www.example.org/public/test.pdf'
|
150
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
151
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "not matching" do
|
156
|
+
specify do
|
157
|
+
get 'http://www.example.org/secret/test.pdf'
|
158
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
159
|
+
expect(last_response.body).to eq("Hello world!")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end # one regex
|
163
|
+
|
164
|
+
describe "multiple" do
|
165
|
+
before { mock_app({}, :except => [%r[^/prawn], %r[^/secret]]) }
|
166
|
+
|
167
|
+
context "matching" do
|
168
|
+
specify do
|
169
|
+
get 'http://www.example.org/public/test.pdf'
|
170
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
171
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "not matching" do
|
176
|
+
specify do
|
177
|
+
get 'http://www.example.org/secret/test.pdf'
|
178
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
179
|
+
expect(last_response.body).to eq("Hello world!")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end # multiple regex
|
183
|
+
end # regex
|
184
|
+
|
185
|
+
describe "string" do
|
186
|
+
describe "one" do
|
187
|
+
before { mock_app({}, :except => '/secret') }
|
188
|
+
|
189
|
+
context "matching" do
|
190
|
+
specify do
|
191
|
+
get 'http://www.example.org/public/test.pdf'
|
192
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
193
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "not matching" do
|
198
|
+
specify do
|
199
|
+
get 'http://www.example.org/secret/test.pdf'
|
200
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
201
|
+
expect(last_response.body).to eq("Hello world!")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end # one string
|
205
|
+
|
206
|
+
describe "multiple" do
|
207
|
+
before { mock_app({}, :except => ['/prawn', '/secret']) }
|
208
|
+
|
209
|
+
context "matching" do
|
210
|
+
specify do
|
211
|
+
get 'http://www.example.org/public/test.pdf'
|
212
|
+
expect(last_response.headers["Content-Type"]).to eq("application/pdf")
|
213
|
+
expect(last_response.body.bytesize).to eq(WeasyPrint.new("Hello world!").to_pdf.bytesize)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
context "not matching" do
|
218
|
+
specify do
|
219
|
+
get 'http://www.example.org/secret/test.pdf'
|
220
|
+
expect(last_response.headers["Content-Type"]).to eq("text/html")
|
221
|
+
expect(last_response.body).to eq("Hello world!")
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end # multiple string
|
225
|
+
end # string
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "saving generated pdf to disk" do
|
230
|
+
before do
|
231
|
+
#make sure tests don't find an old test_save.pdf
|
232
|
+
File.delete('spec/test_save.pdf') if File.exists?('spec/test_save.pdf')
|
233
|
+
expect(File.exists?('spec/test_save.pdf')).to be_false
|
234
|
+
end
|
235
|
+
|
236
|
+
context "when header WeasyPrint-save-pdf is present" do
|
237
|
+
it "should saved the .pdf to disk" do
|
238
|
+
headers = { 'WeasyPrint-save-pdf' => 'spec/test_save.pdf' }
|
239
|
+
mock_app({}, {only: '/public'}, headers)
|
240
|
+
get 'http://www.example.org/public/test_save.pdf'
|
241
|
+
expect(File.exists?('spec/test_save.pdf')).to be_true
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should not raise when target directory does not exist" do
|
245
|
+
headers = { 'WeasyPrint-save-pdf' => '/this/dir/does/not/exist/spec/test_save.pdf' }
|
246
|
+
mock_app({}, {only: '/public'}, headers)
|
247
|
+
expect {
|
248
|
+
get 'http://www.example.com/public/test_save.pdf'
|
249
|
+
}.not_to raise_error
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
context "when header WeasyPrint-save-pdf is not present" do
|
254
|
+
it "should not saved the .pdf to disk" do
|
255
|
+
mock_app({}, {only: '/public'}, {} )
|
256
|
+
get 'http://www.example.org/public/test_save.pdf'
|
257
|
+
expect(File.exists?('spec/test_save.pdf')).to be_false
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "remove .pdf from PATH_INFO and REQUEST_URI" do
|
264
|
+
before { mock_app }
|
265
|
+
|
266
|
+
context "matching" do
|
267
|
+
|
268
|
+
specify do
|
269
|
+
get 'http://www.example.org/public/file.pdf'
|
270
|
+
expect(@env["PATH_INFO"]).to eq("/public/file")
|
271
|
+
expect(@env["REQUEST_URI"]).to eq("/public/file")
|
272
|
+
expect(@env["SCRIPT_NAME"]).to be_empty
|
273
|
+
end
|
274
|
+
specify do
|
275
|
+
get 'http://www.example.org/public/file.txt'
|
276
|
+
expect(@env["PATH_INFO"]).to eq("/public/file.txt")
|
277
|
+
expect(@env["REQUEST_URI"]).to be_nil
|
278
|
+
expect(@env["SCRIPT_NAME"]).to be_empty
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "subdomain matching" do
|
283
|
+
before do
|
284
|
+
main_app = lambda { |env|
|
285
|
+
@env = env
|
286
|
+
@env['SCRIPT_NAME'] = '/example.org'
|
287
|
+
headers = {'Content-Type' => "text/html"}
|
288
|
+
[200, headers, @body || ['Hello world!']]
|
289
|
+
}
|
290
|
+
|
291
|
+
builder = Rack::Builder.new
|
292
|
+
builder.use WeasyPrint::Middleware
|
293
|
+
builder.run main_app
|
294
|
+
@app = builder.to_app
|
295
|
+
end
|
296
|
+
specify do
|
297
|
+
get 'http://example.org/sub/public/file.pdf'
|
298
|
+
expect(@env["PATH_INFO"]).to eq("/sub/public/file")
|
299
|
+
expect(@env["REQUEST_URI"]).to eq("/sub/public/file")
|
300
|
+
expect(@env["SCRIPT_NAME"]).to eq("/example.org")
|
301
|
+
end
|
302
|
+
specify do
|
303
|
+
get 'http://example.org/sub/public/file.txt'
|
304
|
+
expect(@env["PATH_INFO"]).to eq("/sub/public/file.txt")
|
305
|
+
expect(@env["REQUEST_URI"]).to be_nil
|
306
|
+
expect(@env["SCRIPT_NAME"]).to eq("/example.org")
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "#translate_paths" do
|
314
|
+
before do
|
315
|
+
@pdf = WeasyPrint::Middleware.new({})
|
316
|
+
@env = { 'REQUEST_URI' => 'http://example.com/document.pdf', 'rack.url_scheme' => 'http', 'HTTP_HOST' => 'example.com' }
|
317
|
+
end
|
318
|
+
|
319
|
+
it "should correctly parse relative url with single quotes" do
|
320
|
+
@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>}
|
321
|
+
body = @pdf.send :translate_paths, @body, @env
|
322
|
+
expect(body).to eq("<html><head><link href='http://example.com/stylesheets/application.css' media='screen' rel='stylesheet' type='text/css' /></head><body><img alt='test' src=\"http://example.com/test.png\" /></body></html>")
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should correctly parse relative url with double quotes" do
|
326
|
+
@body = %{<link href="/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />}
|
327
|
+
body = @pdf.send :translate_paths, @body, @env
|
328
|
+
expect(body).to eq("<link href=\"http://example.com/stylesheets/application.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />")
|
329
|
+
end
|
330
|
+
|
331
|
+
it "should correctly parse relative url with double quotes" do
|
332
|
+
@body = %{<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>}
|
333
|
+
body = @pdf.send :translate_paths, @body, @env
|
334
|
+
expect(body).to eq("<link href='//fonts.googleapis.com/css?family=Open+Sans:400,600' rel='stylesheet' type='text/css'>")
|
335
|
+
end
|
336
|
+
|
337
|
+
it "should return the body even if there are no valid substitutions found" do
|
338
|
+
@body = "NO MATCH"
|
339
|
+
body = @pdf.send :translate_paths, @body, @env
|
340
|
+
expect(body).to eq("NO MATCH")
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "#translate_paths with root_url configuration" do
|
345
|
+
before do
|
346
|
+
@pdf = WeasyPrint::Middleware.new({})
|
347
|
+
@env = { 'REQUEST_URI' => 'http://example.com/document.pdf', 'rack.url_scheme' => 'http', 'HTTP_HOST' => 'example.com' }
|
348
|
+
WeasyPrint.configure do |config|
|
349
|
+
config.root_url = "http://example.net/"
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
it "should add the root_url" do
|
354
|
+
@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>}
|
355
|
+
body = @pdf.send :translate_paths, @body, @env
|
356
|
+
expect(body).to eq("<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>")
|
357
|
+
end
|
358
|
+
|
359
|
+
after do
|
360
|
+
WeasyPrint.configure do |config|
|
361
|
+
config.root_url = nil
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
it "should not get stuck rendering each request as pdf" do
|
367
|
+
mock_app
|
368
|
+
# false by default. No requests.
|
369
|
+
expect(@app.send(:rendering_pdf?)).to be_false
|
370
|
+
|
371
|
+
# Remain false on a normal request
|
372
|
+
get 'http://www.example.org/public/file'
|
373
|
+
expect(@app.send(:rendering_pdf?)).to be_false
|
374
|
+
|
375
|
+
# Return true on a pdf request.
|
376
|
+
get 'http://www.example.org/public/file.pdf'
|
377
|
+
expect(@app.send(:rendering_pdf?)).to be_true
|
378
|
+
|
379
|
+
# Restore to false on any non-pdf request.
|
380
|
+
get 'http://www.example.org/public/file'
|
381
|
+
expect(@app.send(:rendering_pdf?)).to be_false
|
382
|
+
end
|
383
|
+
|
384
|
+
end
|