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.
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ describe WeasyPrint::Source do
4
+
5
+ describe "#url?" do
6
+ it "should return true if passed a url like string" do
7
+ source = WeasyPrint::Source.new('http://google.com')
8
+ expect(source).to be_url
9
+ end
10
+
11
+ it "should return false if passed a file" do
12
+ source = WeasyPrint::Source.new(File.new(__FILE__))
13
+ expect(source).not_to be_url
14
+ end
15
+
16
+ it "should return false if passed HTML" do
17
+ source = WeasyPrint::Source.new('<blink>Oh Hai!</blink>')
18
+ expect(source).not_to be_url
19
+ end
20
+
21
+ it "should return false if passed HTML with embedded urls at the beginning of a line" do
22
+ source = WeasyPrint::Source.new("<blink>Oh Hai!</blink>\nhttp://www.google.com")
23
+ expect(source).not_to be_url
24
+ end
25
+ end
26
+
27
+ describe "#file?" do
28
+ it "should return true if passed a file" do
29
+ source = WeasyPrint::Source.new(File.new(__FILE__))
30
+ expect(source).to be_file
31
+ end
32
+
33
+ it "should return false if passed a url like string" do
34
+ source = WeasyPrint::Source.new('http://google.com')
35
+ expect(source).not_to be_file
36
+ end
37
+
38
+ it "should return false if passed HTML" do
39
+ source = WeasyPrint::Source.new('<blink>Oh Hai!</blink>')
40
+ expect(source).not_to be_file
41
+ end
42
+ end
43
+
44
+ describe "#html?" do
45
+ it "should return true if passed HTML" do
46
+ source = WeasyPrint::Source.new('<blink>Oh Hai!</blink>')
47
+ expect(source).to be_html
48
+ end
49
+
50
+ it "should return false if passed a file" do
51
+ source = WeasyPrint::Source.new(File.new(__FILE__))
52
+ expect(source).not_to be_html
53
+ end
54
+
55
+ it "should return false if passed a url like string" do
56
+ source = WeasyPrint::Source.new('http://google.com')
57
+ expect(source).not_to be_html
58
+ end
59
+ end
60
+
61
+ describe "#to_s" do
62
+ it "should return the HTML if passed HTML" do
63
+ source = WeasyPrint::Source.new('<blink>Oh Hai!</blink>')
64
+ expect(source.to_s).to eq('<blink>Oh Hai!</blink>')
65
+ end
66
+
67
+ it "should return a path if passed a file" do
68
+ source = WeasyPrint::Source.new(File.new(__FILE__))
69
+ expect(source.to_s).to eq(__FILE__)
70
+ end
71
+
72
+ it "should return the url if passed a url like string" do
73
+ source = WeasyPrint::Source.new('http://google.com')
74
+ expect(source.to_s).to eq('http://google.com')
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,15 @@
1
+ SPEC_ROOT = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift(SPEC_ROOT)
3
+ $LOAD_PATH.unshift(File.join(SPEC_ROOT, '..', 'lib'))
4
+ require 'weasyprint'
5
+ require 'rspec'
6
+ require 'rspec/autorun'
7
+ require 'mocha'
8
+ require 'rack'
9
+ require 'rack/test'
10
+ require 'active_support'
11
+ require 'custom_wkhtmltopdf_path' if File.exists?(File.join(SPEC_ROOT, 'custom_wkhtmltopdf_path.rb'))
12
+
13
+ RSpec.configure do |config|
14
+ include Rack::Test::Methods
15
+ end
@@ -0,0 +1,342 @@
1
+ #encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe WeasyPrint do
5
+
6
+ context "initialization" do
7
+ it "should accept HTML as the source" do
8
+ weasyprint = WeasyPrint.new('<h1>Oh Hai</h1>')
9
+ expect(weasyprint.source).to be_html
10
+ expect(weasyprint.source.to_s).to eq('<h1>Oh Hai</h1>')
11
+ end
12
+
13
+ it "should accept a URL as the source" do
14
+ weasyprint = WeasyPrint.new('http://google.com')
15
+ expect(weasyprint.source).to be_url
16
+ expect(weasyprint.source.to_s).to eq('http://google.com')
17
+ end
18
+
19
+ it "should accept a File as the source" do
20
+ file_path = File.join(SPEC_ROOT,'fixtures','example.html')
21
+ weasyprint = WeasyPrint.new(File.new(file_path))
22
+ expect(weasyprint.source).to be_file
23
+ expect(weasyprint.source.to_s).to eq(file_path)
24
+ end
25
+
26
+ it "should parse the options into a cmd line friedly format" do
27
+ weasyprint = WeasyPrint.new('html', :resolution => '300')
28
+ expect(weasyprint.options).to have_key('--resolution')
29
+ end
30
+
31
+ it "should parse complex options into a cmd line friedly format" do
32
+ weasyprint = WeasyPrint.new('html', :replace => {'value' => 'something else'} )
33
+ expect(weasyprint.options).to have_key('--replace')
34
+ end
35
+
36
+ it "should provide default options" do
37
+ weasyprint = WeasyPrint.new('<h1>Oh Hai</h1>')
38
+ ['--format'].each do |option|
39
+ expect(weasyprint.options).to have_key(option)
40
+ end
41
+ end
42
+
43
+ it "should default to 'UTF-8' encoding" do
44
+ weasyprint = WeasyPrint.new('Captación')
45
+ expect(weasyprint.options['--encoding']).to eq('UTF-8')
46
+ end
47
+
48
+ it "should not have any stylesheedt by default" do
49
+ weasyprint = WeasyPrint.new('<h1>Oh Hai</h1>')
50
+ expect(weasyprint.stylesheets).to be_empty
51
+ end
52
+ end
53
+
54
+ context "command" do
55
+ # it "should contstruct the correct command" do
56
+ # weasyprint = WeasyPrint.new('html', :page_size => 'Letter', :toc_l1_font_size => 12, :replace => {'foo' => 'bar'})
57
+ # command = weasyprint.command
58
+ # expect(command).to include "wkhtmltopdf"
59
+ # expect(command).to include "--page-size Letter"
60
+ # expect(command).to include "--toc-l1-font-size 12"
61
+ # expect(command).to include "--replace foo bar"
62
+ # end
63
+
64
+ # it "should setup one cookie only" do
65
+ # weasyprint = WeasyPrint.new('html', cookie: {cookie_name: :cookie_value})
66
+ # command = weasyprint.command
67
+ # expect(command).to include "--cookie cookie_name cookie_value"
68
+ # end
69
+
70
+ # it "should setup multiple cookies when passed a hash" do
71
+ # weasyprint = WeasyPrint.new('html', :cookie => {:cookie_name1 => :cookie_val1, :cookie_name2 => :cookie_val2})
72
+ # command = weasyprint.command
73
+ # expect(command).to include "--cookie cookie_name1 cookie_val1"
74
+ # expect(command).to include "--cookie cookie_name2 cookie_val2"
75
+ # end
76
+
77
+ # it "should setup multiple cookies when passed an array of tuples" do
78
+ # weasyprint = WeasyPrint.new('html', :cookie => [[:cookie_name1, :cookie_val1], [:cookie_name2, :cookie_val2]])
79
+ # command = weasyprint.command
80
+ # expect(command).to include "--cookie cookie_name1 cookie_val1"
81
+ # expect(command).to include "--cookie cookie_name2 cookie_val2"
82
+ # end
83
+
84
+ # it "will not include default options it is told to omit" do
85
+ # WeasyPrint.configure do |config|
86
+ # config.default_options[:disable_smart_shrinking] = true
87
+ # end
88
+
89
+ # weasyprint = WeasyPrint.new('html')
90
+ # expect(weasyprint.command).to include('--disable-smart-shrinking')
91
+ # weasyprint = WeasyPrint.new('html', :disable_smart_shrinking => false)
92
+ # expect(weasyprint.command).not_to include('--disable-smart-shrinking')
93
+ # end
94
+
95
+ it "should encapsulate string arguments in quotes" do
96
+ weasyprint = WeasyPrint.new('html', :header_center => "foo [page]")
97
+ expect(weasyprint.command).to include "--header-center foo\\ \\[page\\]"
98
+ end
99
+
100
+ it "should sanitize string arguments" do
101
+ weasyprint = WeasyPrint.new('html', :header_center => "$(ls)")
102
+ expect(weasyprint.command).to include "--header-center \\$\\(ls\\)"
103
+ end
104
+
105
+ it "read the source from stdin if it is html" do
106
+ weasyprint = WeasyPrint.new('html')
107
+ expect(weasyprint.command).to match /- -$/
108
+ end
109
+
110
+ it "specify the URL to the source if it is a url" do
111
+ weasyprint = WeasyPrint.new('http://google.com')
112
+ expect(weasyprint.command).to match /http:\/\/google.com -$/
113
+ end
114
+
115
+ it "should specify the path to the source if it is a file" do
116
+ file_path = File.join(SPEC_ROOT,'fixtures','example.html')
117
+ weasyprint = WeasyPrint.new(File.new(file_path))
118
+ expect(weasyprint.command).to match /#{file_path} -$/
119
+ end
120
+
121
+ it "should specify the path for the ouput if a path is given" do
122
+ file_path = "/path/to/output.pdf"
123
+ weasyprint = WeasyPrint.new("html")
124
+ expect(weasyprint.command(file_path)).to match /#{file_path}$/
125
+ end
126
+
127
+ # it "should detect special weasyprint meta tags" do
128
+ # body = %{
129
+ # <html>
130
+ # <head>
131
+ # <meta name="weasyprint-page_size" content="Legal"/>
132
+ # <meta name="weasyprint-orientation" content="Landscape"/>
133
+ # </head>
134
+ # </html>
135
+ # }
136
+ # weasyprint = WeasyPrint.new(body)
137
+ # command = weasyprint.command
138
+ # expect(command).to include "--page-size Legal"
139
+ # expect(command).to include "--orientation Landscape"
140
+ # end
141
+
142
+ # it "should detect cookies meta tag" do
143
+ # body = %{
144
+ # <html>
145
+ # <head>
146
+ # <meta name="weasyprint-cookie rails_session" content='rails_session_value' />
147
+ # <meta name="weasyprint-cookie cookie_variable" content='cookie_variable_value' />
148
+ # </head>
149
+ # </html>
150
+ # }
151
+ # weasyprint = WeasyPrint.new(body)
152
+ # command = weasyprint.command
153
+ # expect(command).to include "--cookie rails_session rails_session_value --cookie cookie_variable cookie_variable_value"
154
+ # end
155
+
156
+ # it "should detect disable_smart_shrinking meta tag" do
157
+ # body = %{
158
+ # <html>
159
+ # <head>
160
+ # <meta name="weasyprint-disable_smart_shrinking" content="true"/>
161
+ # </head>
162
+ # </html>
163
+ # }
164
+ # weasyprint = WeasyPrint.new(body)
165
+ # command = weasyprint.command
166
+ # expect(command).to include "--disable-smart-shrinking"
167
+ # expect(command).not_to include "--disable-smart-shrinking true"
168
+ # end
169
+
170
+ # it "should detect names with hyphens instead of underscores" do
171
+ # body = %{
172
+ # <html>
173
+ # <head>
174
+ # <meta content='Portrait' name='weasyprint-orientation'/>
175
+ # <meta content="10mm" name="weasyprint-margin-bottom"/>
176
+ # </head>
177
+ # <br>
178
+ # </html>
179
+ # }
180
+ # weasyprint = WeasyPrint.new(body)
181
+ # expect(weasyprint.command).not_to include 'name\='
182
+ # end
183
+
184
+ # it "should detect special weasyprint meta tags despite bad markup" do
185
+ # body = %{
186
+ # <html>
187
+ # <head>
188
+ # <meta name="weasyprint-page_size" content="Legal"/>
189
+ # <meta name="weasyprint-orientation" content="Landscape"/>
190
+ # </head>
191
+ # <br>
192
+ # </html>
193
+ # }
194
+ # weasyprint = WeasyPrint.new(body)
195
+ # command = weasyprint.command
196
+ # expect(command).to include "--page-size Legal"
197
+ # expect(command).to include "--orientation Landscape"
198
+ # end
199
+
200
+ # it "should skip non-weasyprint meta tags" do
201
+ # body = %{
202
+ # <html>
203
+ # <head>
204
+ # <meta name="test-page_size" content="Legal"/>
205
+ # <meta name="weasyprint-orientation" content="Landscape"/>
206
+ # </head>
207
+ # <br>
208
+ # </html>
209
+ # }
210
+ # weasyprint = WeasyPrint.new(body)
211
+ # command = weasyprint.command
212
+ # expect(command).not_to include "--page-size Legal"
213
+ # expect(command).to include "--orientation Landscape"
214
+ # end
215
+
216
+ # it "should not use quiet" do
217
+ # weasyprint = WeasyPrint.new('html', quiet: false)
218
+ # expect(weasyprint.command).not_to include '--quiet'
219
+ # end
220
+
221
+ # it "should use quiet option by defautl" do
222
+ # weasyprint = WeasyPrint.new('html')
223
+ # expect(weasyprint.command).to include '--quiet'
224
+ # end
225
+
226
+ # it "should not use quiet option in verbose mode" do
227
+ # WeasyPrint.configure do |config|
228
+ # config.verbose = true
229
+ # end
230
+
231
+ # weasyprint = WeasyPrint.new('html')
232
+ # expect(weasyprint.command).not_to include '--quiet'
233
+
234
+ # WeasyPrint.configure do |config|
235
+ # config.verbose = false
236
+ # end
237
+ # end
238
+
239
+ end
240
+
241
+ context "#to_pdf" do
242
+ it "should generate a PDF of the HTML" do
243
+ weasyprint = WeasyPrint.new('html')
244
+ pdf = weasyprint.to_pdf
245
+ expect(pdf[0...4]).to eq("%PDF") # PDF Signature at beginning of file
246
+ end
247
+
248
+ it "should have the stylesheet added to the head if it has one" do
249
+ weasyprint = WeasyPrint.new("<html><head></head><body>Hai!</body></html>")
250
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
251
+ weasyprint.stylesheets << css
252
+ weasyprint.to_pdf
253
+ expect(weasyprint.source.to_s).to include("<style>#{File.read(css)}</style>")
254
+ end
255
+
256
+ it "should prepend style tags if the HTML doesn't have a head tag" do
257
+ weasyprint = WeasyPrint.new("<html><body>Hai!</body></html>")
258
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
259
+ weasyprint.stylesheets << css
260
+ weasyprint.to_pdf
261
+ expect(weasyprint.source.to_s).to include("<style>#{File.read(css)}</style><html>")
262
+ end
263
+
264
+ it "should throw an error if the source is not html and stylesheets have been added" do
265
+ weasyprint = WeasyPrint.new('http://google.com')
266
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
267
+ weasyprint.stylesheets << css
268
+ expect { weasyprint.to_pdf }.to raise_error(WeasyPrint::ImproperSourceError)
269
+ end
270
+
271
+ it "should be able to deal with ActiveSupport::SafeBuffer" do
272
+ weasyprint = WeasyPrint.new(ActiveSupport::SafeBuffer.new "<html><head></head><body>Hai!</body></html>")
273
+ css = File.join(SPEC_ROOT,'fixtures','example.css')
274
+ weasyprint.stylesheets << css
275
+ weasyprint.to_pdf
276
+ expect(weasyprint.source.to_s).to include("<style>#{File.read(css)}</style></head>")
277
+ end
278
+
279
+ it "should escape \\X in stylesheets" do
280
+ weasyprint = WeasyPrint.new("<html><head></head><body>Hai!</body></html>")
281
+ css = File.join(SPEC_ROOT,'fixtures','example_with_hex_symbol.css')
282
+ weasyprint.stylesheets << css
283
+ weasyprint.to_pdf
284
+ expect(weasyprint.source.to_s).to include("<style>#{File.read(css)}</style></head>")
285
+ end
286
+
287
+ it "should throw an error if it is unable to connect" do
288
+ weasyprint = WeasyPrint.new("http://google.com/this-should-not-be-found/404.html")
289
+ expect { weasyprint.to_pdf }.to raise_error /exitstatus=1/
290
+ end
291
+
292
+ it "should generate PDF if there are missing assets" do
293
+ weasyprint = WeasyPrint.new("<html><body><img alt='' src='http://example.com/surely-it-doesnt-exist.gif' /></body></html>")
294
+ pdf = weasyprint.to_pdf
295
+ expect(pdf[0...4]).to eq("%PDF") # PDF Signature at the beginning
296
+ end
297
+ end
298
+
299
+ context "#to_file" do
300
+ before do
301
+ @file_path = File.join(SPEC_ROOT,'fixtures','test.pdf')
302
+ File.delete(@file_path) if File.exist?(@file_path)
303
+ end
304
+
305
+ after do
306
+ File.delete(@file_path)
307
+ end
308
+
309
+ it "should create a file with the PDF as content" do
310
+ weasyprint = WeasyPrint.new('html')
311
+ file = weasyprint.to_file(@file_path)
312
+ expect(file).to be_instance_of(File)
313
+ expect(File.read(file.path)[0...4]).to eq("%PDF") # PDF Signature at beginning of file
314
+ end
315
+
316
+ it "should not truncate data (in Ruby 1.8.6)" do
317
+ file_path = File.join(SPEC_ROOT,'fixtures','example.html')
318
+ weasyprint = WeasyPrint.new(File.new(file_path))
319
+ pdf_data = weasyprint.to_pdf
320
+ file = weasyprint.to_file(@file_path)
321
+ file_data = open(@file_path, 'rb') {|io| io.read }
322
+ expect(pdf_data.size).to eq(file_data.size)
323
+ end
324
+ end
325
+
326
+ context "security" do
327
+ before do
328
+ @test_path = File.join(SPEC_ROOT,'fixtures','security-oops')
329
+ File.delete(@test_path) if File.exist?(@test_path)
330
+ end
331
+
332
+ after do
333
+ File.delete(@test_path) if File.exist?(@test_path)
334
+ end
335
+
336
+ it "should not allow shell injection in options" do
337
+ weasyprint = WeasyPrint.new('html', :encoding => "a title\"; touch #{@test_path} #")
338
+ weasyprint.to_pdf
339
+ expect(File.exist?(@test_path)).to be_false
340
+ end
341
+ end
342
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "weasyprint/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "weasyprint"
7
+ s.version = WeasyPrint::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jared Pace", "Relevance", "Simply Business"]
10
+ s.email = ["jared@codewordstudios.com", "lukas.oberhuber@simplybusiness.co.uk"]
11
+ s.homepage = "https://github.com/simplybusiness/weasyprint"
12
+ s.summary = "HTML+CSS -> PDF"
13
+ s.description = "Uses weasyprint to create PDFs using HTML"
14
+
15
+ # s.rubyforge_project = "weasyprint"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # Developmnet Dependencies
23
+ s.add_development_dependency(%q<activesupport>, [">= 3.0.8"])
24
+ s.add_development_dependency(%q<mocha>, [">= 0.9.10"])
25
+ s.add_development_dependency(%q<rack-test>, [">= 0.5.6"])
26
+ s.add_development_dependency(%q<rake>, ["~>0.9.2"])
27
+ s.add_development_dependency(%q<rdoc>, ["~> 4.0.1"])
28
+ s.add_development_dependency(%q<rspec>, ["~> 2.14.0"])
29
+ end