wkhtml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ module WkHtml
2
+ module ToPdf
3
+ class GlobalSettings
4
+ include Settings
5
+
6
+ KEYS = %w(
7
+ size.paperSize
8
+ size.width
9
+ size.height
10
+ orientation
11
+ colorMode
12
+ resolution
13
+ dpi
14
+ pageOffset
15
+ copies
16
+ collate
17
+ outline
18
+ outlineDepth
19
+ dumpOutline
20
+ out
21
+ documentTitle
22
+ useCompression
23
+ margin.top
24
+ margin.bottom
25
+ margin.left
26
+ margin.right
27
+ imageDPI
28
+ imageQuality
29
+ load.cookieJar
30
+ )
31
+ DEFAULTS = {}
32
+
33
+ self.settings = KEYS
34
+ self.default_settings = DEFAULTS
35
+
36
+ def out=(v)
37
+ v = CommonSettings::cleanup_path(v)
38
+ raise ArgumentError.new("#{v} is not writeable") unless CommonSettings::writable?(v)
39
+ self['out'] = v
40
+ end
41
+
42
+ def stdout=(v)
43
+ self.out = v ? CommonSettings::STDOUT : nil
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+
50
+ __END__
51
+ size.paperSize The paper size of the output document, e.g. "A4".
52
+ size.width The with of the output document, e.g. "4cm".
53
+ size.height The height of the output document, e.g. "12in".
54
+ orientation The orientation of the output document, must be either "Landscape" or "Portrait".
55
+ colorMode Should the output be printed in color or gray scale, must be either "Color" or "Grayscale"
56
+ resolution Most likely has no effect.
57
+ dpi What dpi should we use when printing, e.g. "80".
58
+ pageOffset A number that is added to all page numbers when printing headers, footers and table of content.
59
+ copies How many copies should we print?. e.g. "2".
60
+ collate Should the copies be collated? Must be either "true" or "false".
61
+ outline Should a outline (table of content in the sidebar) be generated and put into the PDF? Must be either "true" or false".
62
+ outlineDepth The maximal depth of the outline, e.g. "4".
63
+ dumpOutline If not set to the empty string a XML representation of the outline is dumped to this file.
64
+ out The path of the output file, if "-" output is sent to stdout, if empty the output is stored in a buffer.
65
+ documentTitle The title of the PDF document.
66
+ useCompression Should we use loss less compression when creating the pdf file? Must be either "true" or "false".
67
+ margin.top Size of the top margin, e.g. "2cm"
68
+ margin.bottom Size of the bottom margin, e.g. "2cm"
69
+ margin.left Size of the left margin, e.g. "2cm"
70
+ margin.right Size of the right margin, e.g. "2cm"
71
+ imageDPI The maximal DPI to use for images in the pdf document.
72
+ imageQuality The jpeg compression factor to use when producing the pdf document, e.g. "92".
73
+ load.cookieJar Path of file used to load and store cookies.
@@ -0,0 +1,59 @@
1
+ module WkHtml
2
+ module ToPdf
3
+ class ObjectSettings
4
+ include Settings
5
+
6
+ KEYS = %w(
7
+ toc.useDottedLines
8
+ toc.captionText
9
+ toc.forwardLinks
10
+ toc.backLinks
11
+ toc.indentation
12
+ toc.fontScale
13
+ page
14
+ useExternalLinks
15
+ useLocalLinks
16
+ replacements TODO
17
+ produceForms
18
+ includeInOutline
19
+ pagesCount
20
+ tocXsl
21
+ )
22
+ DEFAULTS = {}
23
+
24
+ self.settings = HeaderSettings::KEYS + WebSettings::KEYS + LoadSettings::KEYS + KEYS
25
+ self.default_settings = DEFAULTS
26
+
27
+ def page=(v)
28
+ v = CommonSettings::cleanup_path(v)
29
+ raise ArgumentError.new("#{v} is missing or not readable") unless CommonSettings::readable?(v)
30
+ self['page'] = v
31
+ end
32
+
33
+ def stdin=(v)
34
+ self.in = v ? CommonSettings::STDIN : ''
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+
41
+ __END__
42
+ toc.useDottedLines Should we use a dotted line when creating a table of content? Must be either "true" or "false".
43
+ toc.captionText The caption to use when creating a table of content.
44
+ toc.forwardLinks Should we create links from the table of content into the actual content? Must be either "true or "false.
45
+ toc.backLinks Should we link back from the content to this table of content.
46
+ toc.indentation The indentation used for every table of content level, e.g. "2em".
47
+ toc.fontScale How much should we scale down the font for every toc level? E.g. "0.8"
48
+ page The URL or path of the web page to convert, if "-" input is read from stdin.
49
+ header.* Header specific settings see Header and footer settings.
50
+ footer.* Footer specific settings see Header and footer settings.
51
+ useExternalLinks Should external links in the HTML document be converted into external pdf links? Must be either "true" or "false.
52
+ useLocalLinks Should internal links in the HTML document be converted into pdf references? Must be either "true" or "false"
53
+ replacements TODO
54
+ produceForms Should we turn HTML forms into PDF forms? Must be either "true" or file".
55
+ load.* Page specific settings related to loading content, see Object Specific loading settings.
56
+ web.* See Web page specific settings.
57
+ includeInOutline Should the sections from this document be included in the outline and table of content?
58
+ pagesCount Should we count the pages of this document, in the counter used for TOC, headers and footers?
59
+ tocXsl If not empty this object is a table of content object, "page" is ignored and this xsl style sheet is used to convert the outline XML into a table of content.
@@ -0,0 +1,3 @@
1
+ module WkHtml
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ module WkHtml
2
+ module WebSettings
3
+ PREFIX = 'web'
4
+ KEYS = %w(
5
+ background
6
+ loadImages
7
+ enableJavascript
8
+ enableIntelligentShrinking
9
+ minimumFontSize
10
+ printMediaType
11
+ defaultEncoding
12
+ userStyleSheet
13
+ enablePlugins
14
+ ).map!{|k| "#{PREFIX}.#{k}" }
15
+ end
16
+ end
17
+
18
+
19
+ __END__
20
+ web.background Should we print the background? Must be either "true" or "false".
21
+ web.loadImages Should we load images? Must be either "true" or "false".
22
+ web.enableJavascript Should we enable javascript? Must be either "true" or "false".
23
+ web.enableIntelligentShrinking Should we enable intelligent shrinkng to fit more content on one page? Must be either "true" or "false". Has no effect for wkhtmltoimage.
24
+ web.minimumFontSize The minimum font size allowed. E.g. "9"
25
+ web.printMediaType Should the content be printed using the print media type instead of the screen media type. Must be either "true" or "false". Has no effect for wkhtmltoimage.
26
+ web.defaultEncoding What encoding should we guess content is using if they do not specify it properly? E.g. "utf-8"
27
+ web.userStyleSheet Url er path to a user specified style sheet.
28
+ web.enablePlugins Should we enable NS plugins, must be either "true" or "false". Enabling this will have limited success.
@@ -0,0 +1,98 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ require 'wkhtml'
20
+
21
+ RSpec.configure do |config|
22
+ # rspec-expectations config goes here. You can use an alternate
23
+ # assertion/expectation library such as wrong or the stdlib/minitest
24
+ # assertions if you prefer.
25
+ config.expect_with :rspec do |expectations|
26
+ # This option will default to `true` in RSpec 4. It makes the `description`
27
+ # and `failure_message` of custom matchers include text for helper methods
28
+ # defined using `chain`, e.g.:
29
+ # be_bigger_than(2).and_smaller_than(4).description
30
+ # # => "be bigger than 2 and smaller than 4"
31
+ # ...rather than:
32
+ # # => "be bigger than 2"
33
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
34
+ end
35
+
36
+ # rspec-mocks config goes here. You can use an alternate test double
37
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
38
+ config.mock_with :rspec do |mocks|
39
+ # Prevents you from mocking or stubbing a method that does not exist on
40
+ # a real object. This is generally recommended, and will default to
41
+ # `true` in RSpec 4.
42
+ mocks.verify_partial_doubles = true
43
+ end
44
+
45
+ # The settings below are suggested to provide a good initial experience
46
+ # with RSpec, but feel free to customize to your heart's content.
47
+ =begin
48
+ # These two settings work together to allow you to limit a spec run
49
+ # to individual examples or groups you care about by tagging them with
50
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
51
+ # get run.
52
+ config.filter_run :focus
53
+ config.run_all_when_everything_filtered = true
54
+
55
+ # Allows RSpec to persist some state between runs in order to support
56
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
57
+ # you configure your source control system to ignore this file.
58
+ config.example_status_persistence_file_path = "spec/examples.txt"
59
+
60
+ # Limits the available syntax to the non-monkey patched syntax that is
61
+ # recommended. For more details, see:
62
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
63
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
64
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
65
+ config.disable_monkey_patching!
66
+
67
+ # This setting enables warnings. It's recommended, but in some cases may
68
+ # be too noisy due to issues in dependencies.
69
+ config.warnings = true
70
+
71
+ # Many RSpec users commonly either run the entire suite or an individual
72
+ # file, and it's useful to allow more verbose output when running an
73
+ # individual spec file.
74
+ if config.files_to_run.one?
75
+ # Use the documentation formatter for detailed output,
76
+ # unless a formatter has already been configured
77
+ # (e.g. via a command-line flag).
78
+ config.default_formatter = 'doc'
79
+ end
80
+
81
+ # Print the 10 slowest examples and example groups at the
82
+ # end of the spec run, to help surface which specs are running
83
+ # particularly slow.
84
+ config.profile_examples = 10
85
+
86
+ # Run specs in random order to surface order dependencies. If you find an
87
+ # order dependency and want to debug it, you can fix the order by providing
88
+ # the seed, which is printed after each run.
89
+ # --seed 1234
90
+ config.order = :random
91
+
92
+ # Seed global randomization in this process using the `--seed` CLI option.
93
+ # Setting this allows you to use `--seed` to deterministically reproduce
94
+ # test failures related to randomization by passing the same `--seed` value
95
+ # as the one that triggered the failure.
96
+ Kernel.srand config.seed
97
+ =end
98
+ end
@@ -0,0 +1,18 @@
1
+ {
2
+ 'jpg' => "\xFF\xD8\xFF\xE0",
3
+ 'pdf' => '%PDF-',
4
+ 'png' => "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A",
5
+ 'svg' => '<?xml',
6
+ 'bmp' => "\x42\x4d"
7
+ }.each do |format,magic|
8
+ magic.force_encoding(Encoding::BINARY)
9
+
10
+ RSpec::Matchers.define :"be_#{format}" do
11
+ match do |output|
12
+ output = output.dup()
13
+ output.force_encoding(Encoding::BINARY)
14
+ output = output[0..magic.size]
15
+ output.start_with?(magic)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_examples 'settings' do |boolean_setting|
4
+ let(:settings){ described_class.new() }
5
+
6
+ describe '#initialize' do
7
+ it 'takes initial settings' do
8
+ obj = described_class.new({boolean_setting => 'true'})
9
+ expect(obj[boolean_setting]).to eql('true')
10
+ end
11
+
12
+ it 'uses defaults' do
13
+ obj = Class.new(described_class) do
14
+ self.default_settings = {boolean_setting => 'true'}
15
+ end.new()
16
+ expect(obj[boolean_setting]).to eql('true')
17
+ end
18
+
19
+ it 'will override defaults' do
20
+ obj = Class.new(described_class) do
21
+ self.default_settings = {boolean_setting => 'true'}
22
+ end.new({
23
+ boolean_setting => 'false'
24
+ })
25
+ expect(obj[boolean_setting]).to eql('false')
26
+ end
27
+ end
28
+
29
+ describe '#to_hash' do
30
+ it 'contains setting' do
31
+ settings[boolean_setting] = 'true'
32
+ expect(settings.to_hash[boolean_setting]).to eql('true')
33
+ end
34
+
35
+ it 'has an alias' do
36
+ expect{settings.to_h}.not_to raise_error
37
+ end
38
+ end
39
+
40
+ describe '#settings=' do
41
+ let(:mock) do
42
+ Class.new(described_class) do
43
+ self.settings = ['blah']
44
+ end
45
+ end
46
+
47
+ it 'defines method getter' do
48
+ expect(mock.instance_methods).to include(:blah)
49
+ end
50
+
51
+ it 'defines method setter' do
52
+ expect(mock.instance_methods).to include(:blah=)
53
+ end
54
+
55
+ it 'defined method can set' do
56
+ settings.__send__(:"#{boolean_setting}=", 'true')
57
+ expect(settings[boolean_setting]).to eql('true')
58
+ end
59
+
60
+ it 'defined method can get' do
61
+ settings[boolean_setting] = 'true'
62
+ expect(settings.__send__(:"#{boolean_setting}")).to eql('true')
63
+ end
64
+ end
65
+ end
@@ -0,0 +1 @@
1
+ <html><bod>My Test</body></html>
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.shared_examples 'to_x_settings' do |boolean_setting|
4
+ let(:settings){ described_class.new() }
5
+
6
+ describe '#initialize' do
7
+ it 'can create' do
8
+ expect(settings).not_to be_nil
9
+ end
10
+ end
11
+
12
+ describe '#[]' do
13
+ it 'can get' do
14
+ expect{ settings[boolean_setting] }.to_not raise_error
15
+ end
16
+
17
+ it 'raises error when unknown' do
18
+ expect{ settings['blah'] }.to raise_error(ArgumentError)
19
+ end
20
+
21
+ it 'can use a symbol' do
22
+ expect{ settings[boolean_setting.to_sym] }.to_not raise_error
23
+ end
24
+ end
25
+
26
+ describe '#[]=' do
27
+ it 'can set' do
28
+ expect(settings[boolean_setting] = 'true').to eq('true')
29
+ end
30
+
31
+ it 'raises error when unknown' do
32
+ expect{ settings['blah'] = '' }.to raise_error(ArgumentError)
33
+ end
34
+
35
+ it 'can use a symbol' do
36
+ expect(settings[boolean_setting.to_sym] = 'true').to eq('true')
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+ require 'support/format'
3
+ require 'tempfile'
4
+
5
+ RSpec.describe WkHtml::Converter do
6
+ let(:html_content) {'<html><bod>My Test</body></html>'}
7
+ let(:html){ WkHtml::Converter.new(html_content) }
8
+ let(:uri){ WkHtml::Converter.new('http://example.com/') }
9
+ let(:file){ WkHtml::Converter.new(File.new(File.join(File.dirname(__FILE__), '..', 'support', 'test.html'))) }
10
+
11
+ #Test a bunch of variations
12
+ ['jpg', 'pdf', 'png', 'bmp', 'svg'].each do |format|
13
+ ['internal', 'external'].each do |location|
14
+ context location do
15
+ describe '#to_image' do
16
+ it "returns a #{format}" do
17
+ convert = location == 'internal' ? html : uri
18
+ expect(convert.to_image(format)).to __send__(:"be_#{format}")
19
+ end
20
+ end
21
+
22
+ describe "#to_#{format}" do
23
+ it "returns a #{format}" do
24
+ convert = location == 'internal' ? html : uri
25
+ expect(convert.to_image(format)).to __send__(:"be_#{format}")
26
+ end
27
+ end
28
+
29
+ describe '#to_file' do
30
+ it "to write a #{format}" do
31
+ Tempfile.open('wkhtml') do |file|
32
+ convert = location == 'internal' ? html : uri
33
+ convert.to_file(file.path, format)
34
+ expect(IO.read(file)).to __send__(:"be_#{format}")
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ describe '#initialize' do
43
+ it 'receives initial options' do
44
+ convert = WkHtml::Converter.new(html_content, {'documentTitle' => 'Here Is My Test'})
45
+ expect(convert.to_pdf().force_encoding(Encoding::BINARY)).to include("/Title (\xFE\xFF\x00H\x00e\x00r\x00e\x00 \x00I\x00s\x00 \x00M\x00y\x00 \x00T\x00e\x00s\x00t)".force_encoding(Encoding::BINARY))
46
+ end
47
+
48
+ it 'can use a file' do
49
+ convert = file
50
+ expect(convert.to_pdf()).to be_pdf
51
+ expect(convert.to_jpg()).to be_jpg
52
+ end
53
+ end
54
+
55
+ describe '#to_image' do
56
+ it 'raises when file is missing' do
57
+ temp = Tempfile.new('wkhtml')
58
+ file = File.new(temp.path)
59
+ temp.close()
60
+ temp.unlink()
61
+ convert = WkHtml::Converter.new(file)
62
+ expect{convert.to_image('pdf')}.to raise_error(ArgumentError)
63
+ expect{convert.to_image('jpg')}.to raise_error(ArgumentError)
64
+ end
65
+ end
66
+
67
+ describe '#to_file' do
68
+ it 'creates when file is missing' do
69
+ temp = Tempfile.new('wkhtml')
70
+ file = File.new(temp.path)
71
+ temp.close()
72
+ temp.unlink()
73
+ convert = html
74
+
75
+ expect(convert.to_file(file, 'pdf')).to eql(file.path)
76
+ expect(convert.to_file(file, 'jpg')).to eql(file.path)
77
+ expect(File.exists?(file.path)).to be true
78
+ end
79
+ end
80
+ end