wkhtml 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,52 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include <wkhtmltox/pdf.h>
4
+ #include <wkhtmltox/image.h>
5
+
6
+ static ID idReady;
7
+ static VALUE mWkHtml = Qnil;
8
+ static VALUE mWkHtmlToPdf = Qnil;
9
+ static VALUE cWkHtmlToPdfGlobalSettings = Qnil;
10
+ static VALUE cWkHtmlToPdfObjectSettings = Qnil;
11
+ static VALUE cWkHtmlToPdfConverter = Qnil;
12
+ static VALUE mWkHtmlToImage = Qnil;
13
+ static VALUE cWkHtmlToImageGlobalSettings = Qnil;
14
+ static VALUE cWkHtmlToImageConverter = Qnil;
15
+
16
+ void Init_wkhtml();
17
+ void Deinit_wkhtml_native(VALUE data);
18
+
19
+ //WkHtml::ToPdf
20
+
21
+ //WkHtml::ToPdf::GlobalSettings
22
+ VALUE wkhtml_topdf_globalsettings_alloc(VALUE self);
23
+ VALUE wkhtml_topdf_globalsettings_aset(VALUE self, VALUE key, VALUE val);
24
+ VALUE wkhtml_topdf_globalsettings_aref(VALUE self, VALUE key);
25
+
26
+ //WkHtml::ToPdf::ObjectSettings
27
+ VALUE wkhtml_topdf_objectsettings_alloc(VALUE self);
28
+ VALUE wkhtml_topdf_objectsettings_aset(VALUE self, VALUE key, VALUE val);
29
+ VALUE wkhtml_topdf_objectsettings_aref(VALUE self, VALUE key);
30
+
31
+ //WkHtml::ToPdf::Converter
32
+ void wkhtml_topdf_converter_free(wkhtmltopdf_converter* converter);
33
+ VALUE wkhtml_topdf_converter_create(VALUE self, VALUE settings);
34
+ VALUE wkhtml_topdf_converter_add_object(VALUE self, VALUE settings, VALUE data);
35
+ VALUE wkhtml_topdf_converter_convert(VALUE self);
36
+ VALUE wkhtml_topdf_converter_http_error_code(VALUE self);
37
+ VALUE wkhtml_topdf_converter_get_output(VALUE self);
38
+
39
+ //WkHtml::ToImage
40
+
41
+ //WkHtml::ToImage::GlobalSettings
42
+ void wkhtml_toimage_globalsettings_free(wkhtmltoimage_global_settings* settings);
43
+ VALUE wkhtml_toimage_globalsettings_alloc(VALUE self);
44
+ VALUE wkhtml_toimage_globalsettings_aset(VALUE self, VALUE key, VALUE val);
45
+ VALUE wkhtml_toimage_globalsettings_aref(VALUE self, VALUE key);
46
+
47
+ //WkHtml::ToImage::Converter
48
+ void wkhtml_toimage_converter_free(wkhtmltoimage_converter* converter);
49
+ VALUE wkhtml_toimage_converter_create(VALUE self, VALUE settings, VALUE data);
50
+ VALUE wkhtml_toimage_converter_convert(VALUE self);
51
+ VALUE wkhtml_toimage_converter_http_error_code(VALUE self);
52
+ VALUE wkhtml_toimage_converter_get_output(VALUE self);
@@ -0,0 +1,14 @@
1
+ require 'wkhtml/wkhtml_native'
2
+ require 'wkhtml/version'
3
+ require 'wkhtml/settings'
4
+ require 'wkhtml/common_settings'
5
+ require 'wkhtml/header_settings'
6
+ require 'wkhtml/load_settings'
7
+ require 'wkhtml/web_settings'
8
+ require 'wkhtml/to_image/global_settings'
9
+ require 'wkhtml/to_pdf/global_settings'
10
+ require 'wkhtml/to_pdf/object_settings'
11
+ require 'wkhtml/converter'
12
+
13
+ module WkHtml
14
+ end
@@ -0,0 +1,52 @@
1
+ require 'uri'
2
+ require 'fileutils'
3
+ require 'tempfile'
4
+
5
+ module WkHtml
6
+ module CommonSettings
7
+ TRUE = 'true'
8
+ FALSE = 'false'
9
+ STDIN = STDOUT = '-'
10
+ PDF = 'pdf'
11
+ JPG = 'jpg'
12
+ PNG = 'png'
13
+ BMP = 'bmp'
14
+ SVG = 'svg'
15
+ REGEXP_URI = /\A#{URI.regexp(['http', 'https'])}/
16
+
17
+ class << self
18
+ def cleanup_path(path)
19
+ path = path.path if path.is_a?(File) || path.is_a?(Tempfile)
20
+
21
+ if path == STDIN || path == STDOUT
22
+ path
23
+ elsif path =~ REGEXP_URI
24
+ URI.parse(path).to_s()
25
+ else
26
+ File.expand_path(path)
27
+ end
28
+ end
29
+
30
+ def readable?(path)
31
+ unless path =~ REGEXP_URI
32
+ File.exists?(path) && File.readable?(path)
33
+ else
34
+ true
35
+ end
36
+ end
37
+
38
+ def writable?(path)
39
+ unless File.writable?(path)
40
+ begin
41
+ FileUtils.touch(path)
42
+ true
43
+ rescue
44
+ false
45
+ end
46
+ else
47
+ true
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,125 @@
1
+ require 'tempfile'
2
+
3
+ module WkHtml
4
+ class Converter
5
+ #
6
+ class Failed < StandardError
7
+ attr_reader :http_error_code
8
+
9
+ def initialize(http_error_code)
10
+ @http_error_code = http_error_code
11
+ super(@http_error_code.nil?() ? "Conversion failed" : "Conversion failed with HTTP status #{@http_error_code}")
12
+ end
13
+ end
14
+
15
+ def initialize(data, options = {})
16
+ @data = data
17
+ #Thanks http://stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash
18
+ @options = options.inject({}){|memo,(k,v)| memo[k.to_s()] = v; memo} #Force string for easy comparison with allowed settings
19
+
20
+ #Handle multiple inbound types
21
+ @use_data = case @data
22
+ when String
23
+ !(@data =~ CommonSettings::REGEXP_URI)
24
+ when File, Tempfile
25
+ @data = @data.path
26
+ false
27
+ when URI
28
+ @data = @data.to_s()
29
+ false
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ #
36
+ #
37
+ #
38
+ def to_file(path, format = nil)
39
+ path = CommonSettings::cleanup_path(path)
40
+
41
+ unless format
42
+ #Use file extension if available
43
+ format = File.extname(path)
44
+ format.sub!(/^\./, '')
45
+ format = nil if format.empty?()
46
+ end
47
+ format ||= CommonSettings::JPG
48
+ format = format.to_s()
49
+
50
+ native_converter = if format == CommonSettings::PDF
51
+ create_pdf_converter do |s|
52
+ s.out = path
53
+ end
54
+ else
55
+ create_image_converter do |s|
56
+ s.fmt = format
57
+ s.out = path
58
+ end
59
+ end
60
+
61
+ unless native_converter.convert()
62
+ raise Failed.new(native_converter.http_error_code())
63
+ end
64
+
65
+ path
66
+ end
67
+
68
+ #
69
+ #
70
+ #
71
+ def to_image(format = CommonSettings::JPG)
72
+ native_converter = if format == CommonSettings::PDF
73
+ create_pdf_converter()
74
+ else
75
+ create_image_converter do |s|
76
+ s.fmt = format
77
+ end
78
+ end
79
+
80
+ unless native_converter.convert()
81
+ raise Failed.new(native_converter.http_error_code())
82
+ end
83
+ native_converter.get_output()
84
+ end
85
+
86
+ def to_pdf(); self.to_image(CommonSettings::PDF); end
87
+ def to_jpg(); self.to_image(CommonSettings::JPG); end
88
+ def to_png(); self.to_image(CommonSettings::PNG); end
89
+ def to_bmp(); self.to_image(CommonSettings::BMP); end
90
+ def to_svg(); self.to_image(CommonSettings::SVG); end
91
+
92
+
93
+ protected
94
+ def create_pdf_converter(&block)
95
+ global_settings = build_settings(WkHtml::ToPdf::GlobalSettings)
96
+ object_settings = build_settings(WkHtml::ToPdf::ObjectSettings)
97
+ object_settings.page = @data unless @use_data
98
+ yield global_settings, object_settings if block_given?()
99
+ native_converter = WkHtml::ToPdf::Converter.create(global_settings)
100
+ native_converter.add_object(object_settings, @use_data ? @data : nil)
101
+ native_converter
102
+ end
103
+
104
+ def create_image_converter(&block)
105
+ global_settings = build_settings(WkHtml::ToImage::GlobalSettings)
106
+ global_settings.in = @data unless @use_data
107
+ yield global_settings if block_given?()
108
+ native_converter = WkHtml::ToImage::Converter.create(global_settings, @use_data ? @data : nil)
109
+ native_converter
110
+ end
111
+
112
+ def build_settings(klass)
113
+ settings = klass.new()
114
+ (@options.keys & settings.class.settings).each do |key|
115
+ local_key = key.tr('.', '_')
116
+ if settings.class.public_method_defined?(local_key) #Use the instance method instead
117
+ settings.__send__(:"#{local_key}=", @options[key])
118
+ else #Does not exist, just go for raw []=
119
+ settings[key] = @options[key]
120
+ end
121
+ end
122
+ settings
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,27 @@
1
+ module WkHtml
2
+ module HeaderSettings
3
+ HEADER_PREFIX = 'header'
4
+ FOOTER_PREFIX = 'footer'
5
+ KEYS = %w(
6
+ fontSize
7
+ fontName
8
+ left
9
+ center
10
+ right
11
+ line
12
+ spacing
13
+ htmlUrl
14
+ ).map!{|k| ["#{HEADER_PREFIX}.#{k}", "#{FOOTER_PREFIX}.#{k}"] }.flatten()
15
+ end
16
+ end
17
+
18
+
19
+ __END__
20
+ header.fontSize The font size to use for the header, e.g. "13"
21
+ header.fontName The name of the font to use for the header. e.g. "times"
22
+ header.left The string to print in the left part of the header, note that some sequences are replaced in this string, see the wkhtmltopdf manual.
23
+ header.center The text to print in the center part of the header.
24
+ header.right The text to print in the right part of the header.
25
+ header.line Whether a line should be printed under the header (either "true" or "false").
26
+ header.spacing The amount of space to put between the header and the content, e.g. "1.8". Be aware that if this is too large the header will be printed outside the pdf document. This can be corrected with the margin.top setting.
27
+ header.htmlUrl Url for a HTML document to use for the header.
@@ -0,0 +1,41 @@
1
+ module WkHtml
2
+ module LoadSettings
3
+ PREFIX = 'load'
4
+ KEYS = %w(
5
+ username
6
+ password
7
+ jsdelay
8
+ zoomFactor
9
+ customHeaders
10
+ repertCustomHeaders
11
+ cookies
12
+ post
13
+ blockLocalFileAccess
14
+ stopSlowScript
15
+ debugJavascript
16
+ loadErrorHandling
17
+ proxy
18
+ runScript
19
+ ).map!{|k| "#{PREFIX}.#{k}" }
20
+ end
21
+ end
22
+
23
+
24
+ __END__
25
+ load.username The user name to use when loging into a website, E.g. "bart"
26
+ load.password The password to used when logging into a website, E.g. "elbarto"
27
+ load.jsdelay The mount of time in milliseconds to wait after a page has done loading until it is actually printed. E.g. "1200". We will wait this amount of time or until, javascript calls window.print().
28
+ load.zoomFactor How much should we zoom in on the content? E.g. "2.2".
29
+ load.customHeaders TODO
30
+ load.repertCustomHeaders Should the custom headers be sent all elements loaded instead of only the main page? Must be either "true" or "false".
31
+ load.cookies TODO
32
+ load.post TODO
33
+ load.blockLocalFileAccess Disallow local and piped files to access other local files. Must be either "true" or "false".
34
+ load.stopSlowScript Stop slow running javascript. Must be either "true" or "false".
35
+ load.debugJavascript Forward javascript warnings and errors to the warning callback. Must be either "true" or "false".
36
+ load.loadErrorHandling How should we handle obejcts that fail to load. Must be one of:
37
+ "abort" Abort the convertion process
38
+ "skip" Do not add the object to the final output
39
+ "ignore" Try to add the object to the final output.
40
+ load.proxy String describing what proxy to use when loading the object.
41
+ load.runScript TODO
@@ -0,0 +1,77 @@
1
+ module WkHtml
2
+ module Settings
3
+ TRUE = 'true'
4
+ FALSE = 'false'
5
+
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+
10
+ def initialize(initial = {})
11
+ initial = self.class.default_settings.merge(initial)
12
+ initial.each{|key,value| self[key] = value}
13
+ end
14
+
15
+ #
16
+ # Convert all attributes to Hash. This will ignore errors from retrieving
17
+ # the setting.
18
+ #
19
+ def to_hash()
20
+ Hash[
21
+ self.class.settings.map do |key|
22
+ begin
23
+ [key, self[key]]
24
+ rescue ArgumentError
25
+ nil
26
+ end
27
+ end.compact()
28
+ ]
29
+ end
30
+ alias_method :to_h, :to_hash
31
+
32
+
33
+ module ClassMethods
34
+ #
35
+ # List of settings defined
36
+ #
37
+ def settings()
38
+ @settings ||= []
39
+ end
40
+
41
+ #
42
+ # Assign the attributes and define instance methods
43
+ #
44
+ def settings=(keys)
45
+ @settings = keys
46
+ keys.each do |key|
47
+ #Change key to local method
48
+ local_key = key.tr('.', '_')
49
+
50
+ #Getter
51
+ define_method(local_key.to_sym()) do
52
+ self[key]
53
+ end unless method_defined?(local_key.to_sym())
54
+
55
+ #Setter
56
+ define_method(:"#{local_key}=") do |value|
57
+ self[key] = value
58
+ end unless method_defined?(:"#{local_key}=")
59
+ end
60
+ end
61
+
62
+ #
63
+ # List of default attibute values
64
+ #
65
+ def default_settings()
66
+ @default_settings ||= {}
67
+ end
68
+
69
+ #
70
+ # Assign default attributes that will be set when created
71
+ #
72
+ def default_settings=(hash)
73
+ @default_settings = hash
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,65 @@
1
+ module WkHtml
2
+ module ToImage
3
+ class GlobalSettings
4
+ include Settings
5
+
6
+ KEYS = %w(
7
+ crop.left
8
+ crop.top
9
+ crop.width
10
+ crop.height
11
+ load.cookieJar
12
+ transparent
13
+ in
14
+ out
15
+ fmt
16
+ screenWidth
17
+ smartWidth
18
+ quality
19
+ )
20
+ DEFAULTS = {
21
+ 'fmt' => CommonSettings::JPG
22
+ }
23
+
24
+ self.settings = WebSettings::KEYS + LoadSettings::KEYS + KEYS
25
+ self.default_settings = DEFAULTS
26
+
27
+ def in=(v)
28
+ v = CommonSettings::cleanup_path(v)
29
+ raise ArgumentError.new("#{v} is missing or not readable") unless CommonSettings::readable?(v)
30
+ self['in'] = v
31
+ end
32
+
33
+ def out=(v)
34
+ v = CommonSettings::cleanup_path(v)
35
+ raise ArgumentError.new("#{v} is not writeable") unless CommonSettings::writable?(v)
36
+ self['out'] = v
37
+ end
38
+
39
+ def stdin=(v)
40
+ self.in = v ? CommonSettings::STDIN : nil
41
+ end
42
+
43
+ def stdout=(v)
44
+ self.out = v ? CommonSettings::STDOUT : nil
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ __END__
52
+ crop.left left/x coordinate of the window to capture in pixels. E.g. "200"
53
+ crop.top top/y coordinate of the window to capture in pixels. E.g. "200"
54
+ crop.width Width of the window to capture in pixels. E.g. "200"
55
+ crop.height Height of the window to capture in pixels. E.g. "200"
56
+ load.cookieJar Path of file used to load and store cookies.
57
+ load.* Page specific settings related to loading content, see Object Specific loading settings.
58
+ web.* See Web page specific settings.
59
+ transparent When outputting a PNG or SVG, make the white background transparent. Must be either "true" or "false"
60
+ in The URL or path of the input file, if "-" stdin is used. E.g. "http://google.com"
61
+ out The path of the output file, if "-" stdout is used, if empty the content is stored to a internalBuffer.
62
+ fmt The output format to use, must be either "", "jpg", "png", "bmp" or "svg".
63
+ screenWidth The with of the screen used to render is pixels, e.g "800".
64
+ smartWidth Should we expand the screenWidth if the content does not fit? must be either "true" or "false".
65
+ quality The compression factor to use when outputting a JPEG image. E.g. "94".