wkhtml 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.
@@ -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