gotenberg-ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +20 -0
- data/README.md +1 -0
- data/lib/gotenberg/analyzers/base.rb +52 -0
- data/lib/gotenberg/analyzers/css.rb +17 -0
- data/lib/gotenberg/analyzers/image.rb +41 -0
- data/lib/gotenberg/analyzers/js.rb +17 -0
- data/lib/gotenberg/chromium/files.rb +90 -0
- data/lib/gotenberg/chromium/headers.rb +50 -0
- data/lib/gotenberg/chromium/metadata.rb +24 -0
- data/lib/gotenberg/chromium/properties.rb +142 -0
- data/lib/gotenberg/chromium.rb +64 -0
- data/lib/gotenberg/client.rb +21 -0
- data/lib/gotenberg/compiler.rb +56 -0
- data/lib/gotenberg/exiftools.rb +61 -0
- data/lib/gotenberg/extractors.rb +14 -0
- data/lib/gotenberg/version.rb +3 -0
- data/lib/gotenberg-ruby.rb +5 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3ee579fe775ebbac8cc6eef4e931138f9962b8d0401f1e1bc556bcdf81d1c039
|
4
|
+
data.tar.gz: 8687f9bd12445598334671791e9fbebb50da3f13d4bfabc5be798a9eb89fa3ae
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3333fe62ab25ccbe23c9584af9633fb361576e47d97b13f3b43af9378f76fc7431142bb67b53feaf402ff13a7017495445733a68a3bc3dfec5ea5b5d4a6a2b4d
|
7
|
+
data.tar.gz: ff099effef5eaafe2c1ce89b1a1ca6f935ef44befa19abde53827cd504e5fb6efac7eca43a0e0b906b3a831ee7ed3ade5402b49dcdde4c821f54ad2cfc925190
|
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2022 sanzstez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
TODO
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Gotenberg
|
5
|
+
module Analyzers
|
6
|
+
class Base
|
7
|
+
URI_REGEXP = %r{^[-a-z]+://|^(?:cid|data):|^//}
|
8
|
+
|
9
|
+
attr_accessor :resource
|
10
|
+
|
11
|
+
def initialize resource
|
12
|
+
@resource = resource
|
13
|
+
end
|
14
|
+
|
15
|
+
def assets
|
16
|
+
[binary, filename]
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def binary
|
22
|
+
@binary ||= remote? ? remote_source : local_source
|
23
|
+
end
|
24
|
+
|
25
|
+
def remote_source
|
26
|
+
Faraday.get(src).body
|
27
|
+
rescue StandardError => e
|
28
|
+
raise 'Unable to load remote source. %s' % e.message
|
29
|
+
end
|
30
|
+
|
31
|
+
def local_source
|
32
|
+
IO.binread(src)
|
33
|
+
end
|
34
|
+
|
35
|
+
def extension
|
36
|
+
@extension ||= File.extname(filename).strip.downcase[1..-1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def filename
|
40
|
+
@filename ||= File.basename(src)
|
41
|
+
end
|
42
|
+
|
43
|
+
def remote?
|
44
|
+
src.match?(URI_REGEXP)
|
45
|
+
end
|
46
|
+
|
47
|
+
def src
|
48
|
+
resource[:src]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'base64'
|
3
|
+
require 'gotenberg/analyzers/base'
|
4
|
+
|
5
|
+
module Gotenberg
|
6
|
+
module Analyzers
|
7
|
+
class Css < Base
|
8
|
+
def tag
|
9
|
+
if resource[:inline]
|
10
|
+
'<style type="text/css">%s</style>' % binary
|
11
|
+
else
|
12
|
+
'<link rel="stylesheet" href="%s" />' % filename
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'base64'
|
3
|
+
require 'uri'
|
4
|
+
require 'gotenberg/analyzers/base'
|
5
|
+
|
6
|
+
module Gotenberg
|
7
|
+
module Analyzers
|
8
|
+
class Image < Base
|
9
|
+
MIME_TYPES = {
|
10
|
+
'bmp' => 'image/bmp',
|
11
|
+
'gif' => 'image/gif',
|
12
|
+
'jpe' => 'image/jpeg',
|
13
|
+
'jpeg' => 'image/jpeg',
|
14
|
+
'jpg' => 'image/jpeg',
|
15
|
+
'jfif' => 'image/pipeg',
|
16
|
+
'svg' => 'image/svg+xml',
|
17
|
+
'tif' => 'image/tiff',
|
18
|
+
'tiff' => 'image/tiff',
|
19
|
+
'ico' => 'image/x-icon'
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
def tag
|
23
|
+
'<img src="%s" alt="%s" />' % [src_value, filename]
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def src_value
|
29
|
+
if resource[:inline]
|
30
|
+
'data:%s;base64,%s' % [mimetype, Base64.strict_encode64(binary)]
|
31
|
+
else
|
32
|
+
filename
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def mimetype
|
37
|
+
MIME_TYPES[extension] || 'application/octet-stream'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'base64'
|
3
|
+
require 'gotenberg/analyzers/base'
|
4
|
+
|
5
|
+
module Gotenberg
|
6
|
+
module Analyzers
|
7
|
+
class Js < Base
|
8
|
+
def tag
|
9
|
+
if resource[:inline]
|
10
|
+
'<script type="text/javascript">%s</script>' % binary
|
11
|
+
else
|
12
|
+
'<script src="%s"></script>' % filename
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/multipart'
|
3
|
+
require 'gotenberg/compiler'
|
4
|
+
|
5
|
+
module Gotenberg
|
6
|
+
class Chromium
|
7
|
+
module Files
|
8
|
+
# Adds a header to each page.
|
9
|
+
# Note: it automatically sets the filename to "header.html", as required by Gotenberg.
|
10
|
+
def header header
|
11
|
+
compiler = Compiler.new(header)
|
12
|
+
|
13
|
+
#File.open('header.html', 'w') { |f| f.write(compiler.body) }
|
14
|
+
|
15
|
+
files << multipart_file(compiler.body, 'header.html', 'text/html')
|
16
|
+
end
|
17
|
+
|
18
|
+
# Adds a footer to each page.
|
19
|
+
# Note: it automatically sets the filename to "footer.html", as required by Gotenberg.
|
20
|
+
def footer footer
|
21
|
+
compiler = Compiler.new(footer)
|
22
|
+
|
23
|
+
#File.open('footer.html', 'w') { |f| f.write(compiler.body) }
|
24
|
+
|
25
|
+
files << multipart_file(compiler.body, 'footer.html', 'text/html')
|
26
|
+
end
|
27
|
+
|
28
|
+
# Converts an HTML document to PDF.
|
29
|
+
# Note: it automatically sets the index filename to "index.html", as required by Gotenberg.
|
30
|
+
# See https://gotenberg.dev/docs/modules/chromium#html.
|
31
|
+
def html index
|
32
|
+
compiler = Compiler.new(index)
|
33
|
+
|
34
|
+
meta(extract_metadata_from_body(compiler.body))
|
35
|
+
|
36
|
+
files << multipart_file(compiler.body, 'index.html', 'text/html')
|
37
|
+
|
38
|
+
binary_assets(compiler.assets)
|
39
|
+
|
40
|
+
#File.open('index.html', 'w') { |f| f.write(compiler.body) }
|
41
|
+
|
42
|
+
@endpoint = '/forms/chromium/convert/html'
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
# Converts one or more markdown files to PDF.
|
48
|
+
# Note: it automatically sets the index filename to "index.html", as required by Gotenberg.
|
49
|
+
# See https://gotenberg.dev/docs/modules/chromium#markdown.
|
50
|
+
def markdown index, markdowns = []
|
51
|
+
files << multipart_file(index, 'index.html', 'text/html')
|
52
|
+
|
53
|
+
markdowns.each do |f|
|
54
|
+
files << multipart_file(IO.binread(f), File.basename(f), 'text/markdown')
|
55
|
+
end
|
56
|
+
|
57
|
+
@endpoint = '/forms/chromium/convert/markdown'
|
58
|
+
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets the additional files, like images, fonts, stylesheets, and so on.
|
63
|
+
def binary_assets assets
|
64
|
+
assets.each do |(io, filename)|
|
65
|
+
files << multipart_file(io, filename)
|
66
|
+
end
|
67
|
+
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def assets assets
|
72
|
+
assets.each do |f|
|
73
|
+
files << multipart_file(IO.binread(f), File.basename(f))
|
74
|
+
end
|
75
|
+
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
79
|
+
def files
|
80
|
+
@files ||= []
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def multipart_file body, filename, content_type = 'application/octet-stream'
|
86
|
+
Faraday::Multipart::FilePart.new(StringIO.new(body), content_type, filename)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Gotenberg
|
4
|
+
class Chromium
|
5
|
+
module Headers
|
6
|
+
# Sets the callback and error callback that Gotenberg will use to send
|
7
|
+
# respectively the output file and the error response.
|
8
|
+
def webhook url, error_url
|
9
|
+
headers['Gotenberg-Webhook-Url'] = url
|
10
|
+
headers['Gotenberg-Webhook-Error-Url'] = error_url
|
11
|
+
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
# Overrides the default HTTP method that Gotenberg will use to call the webhook.
|
16
|
+
# Either "POST", "PATCH", or "PUT" - default "POST".
|
17
|
+
def webhook_method method
|
18
|
+
headers['Gotenberg-Webhook-Method'] = method
|
19
|
+
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
# Overrides the default HTTP method that Gotenberg will use to call the error webhook.
|
24
|
+
# Either "POST", "PATCH", or "PUT" - default "POST".
|
25
|
+
def webhook_error_method method
|
26
|
+
headers['Gotenberg-Webhook-Error-Method'] = method
|
27
|
+
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets the extra HTTP headers that Gotenberg will send alongside the request to the webhook and error webhook.
|
32
|
+
def webhook_extra_http_headers headers
|
33
|
+
headers['Gotenberg-Webhook-Extra-Http-Headers'] = headers.to_json
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Overrides the default UUID trace, or request ID, that identifies a request in Gotenberg's logs.
|
39
|
+
def trace trace, header = 'Gotenberg-Trace'
|
40
|
+
headers[header] = trace
|
41
|
+
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def headers
|
46
|
+
@headers = {}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Gotenberg
|
4
|
+
class Chromium
|
5
|
+
module Metadata
|
6
|
+
# set meta headers for PDF file with exiftools (title, creator, etc...)
|
7
|
+
def meta elements
|
8
|
+
metadata.merge!(elements)
|
9
|
+
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def metadata_available?
|
14
|
+
!metadata.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def metadata
|
20
|
+
@metadata ||= {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Gotenberg
|
4
|
+
class Chromium
|
5
|
+
module Properties
|
6
|
+
|
7
|
+
# Overrides the default paper size, in inches. Examples of paper size (width x height):
|
8
|
+
# Letter - 8.5 x 11 (default)
|
9
|
+
# Legal - 8.5 x 14
|
10
|
+
# Tabloid - 11 x 17
|
11
|
+
# Ledger - 17 x 11
|
12
|
+
# A0 - 33.1 x 46.8
|
13
|
+
# A1 - 23.4 x 33.1
|
14
|
+
# A2 - 16.54 x 23.4
|
15
|
+
# A3 - 11.7 x 16.54
|
16
|
+
# A4 - 8.27 x 11.7
|
17
|
+
# A5 - 5.83 x 8.27
|
18
|
+
# A6 - 4.13 x 5.83
|
19
|
+
def paper_size width, height
|
20
|
+
properties['paperWidth'] = width
|
21
|
+
properties['paperHeight'] = height
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
# Overrides the default margins (i.e., 0.39), in inches.
|
27
|
+
def margins top: nil, bottom: nil, left: nil, right: nil
|
28
|
+
properties['marginTop'] = top if top
|
29
|
+
properties['marginBottom'] = bottom if bottom
|
30
|
+
properties['marginLeft'] = left if left
|
31
|
+
properties['marginRight'] = right if right
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
# Forces page size as defined by CSS.
|
37
|
+
def prefer_css_page_size
|
38
|
+
properties['preferCssPageSize'] = true
|
39
|
+
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# Prints the background graphics.
|
44
|
+
def print_background
|
45
|
+
properties['printBackground'] = true
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Sets the paper orientation to landscape.
|
51
|
+
def landscape
|
52
|
+
properties['landscape'] = true
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
# Overrides the default scale of the page rendering (i.e., 1.0).
|
58
|
+
def scale scale
|
59
|
+
properties['scale'] = scale
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Set the page ranges to print, e.g., "1-5, 8, 11-13". Empty means all pages.
|
65
|
+
def native_page_ranges ranges
|
66
|
+
properties['nativePageRanges'] = ranges
|
67
|
+
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Sets the duration (i.e., "1s", "2ms", etc.) to wait when loading an HTML document before converting it to PDF.
|
72
|
+
def wait_delay delay
|
73
|
+
properties['waitDelay'] = delay
|
74
|
+
|
75
|
+
self
|
76
|
+
end
|
77
|
+
|
78
|
+
# Sets the JavaScript expression to wait before converting an HTML document to PDF until it returns true.
|
79
|
+
# For instance: "window.status === 'ready'".
|
80
|
+
def wait_for_expression expression
|
81
|
+
properties['waitForExpression'] = expression
|
82
|
+
|
83
|
+
self
|
84
|
+
end
|
85
|
+
|
86
|
+
# Overrides the default "User-Agent" header.
|
87
|
+
def user_agent user_agent
|
88
|
+
properties['userAgent'] = user_agent
|
89
|
+
|
90
|
+
self
|
91
|
+
end
|
92
|
+
|
93
|
+
# Sets extra HTTP headers that Chromium will send when loading the HTML document.
|
94
|
+
def extra_http_headers headers
|
95
|
+
properties['userAgent'] = headers.to_json
|
96
|
+
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# Forces Gotenberg to return a 409 Conflict response if there are exceptions in the Chromium console
|
101
|
+
def fail_on_console_exceptions
|
102
|
+
properties['failOnConsoleExceptions'] = true
|
103
|
+
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
107
|
+
# Forces Chromium to emulate the media type "print" or "screen".
|
108
|
+
def emulate_media_type type
|
109
|
+
properties['emulatedMediaType'] = type
|
110
|
+
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
# Sets the PDF format of the resulting PDF.
|
115
|
+
# See https://gotenberg.dev/docs/modules/pdf-engines#engines.
|
116
|
+
def pdf_format format
|
117
|
+
properties['pdfFormat'] = format
|
118
|
+
|
119
|
+
self
|
120
|
+
end
|
121
|
+
|
122
|
+
# Converts a target URL to PDF.
|
123
|
+
# See https://gotenberg.dev/docs/modules/chromium#url.
|
124
|
+
def url url, extra_link_tags = [], extra_script_tags = []
|
125
|
+
links = extra_link_tags.flat_map { |url| { 'href' => url } }
|
126
|
+
scripts = extra_script_tags.flat_map { |url| { 'src' => url } }
|
127
|
+
|
128
|
+
properties['url'] = url
|
129
|
+
properties['extraLinkTags'] = links.to_json
|
130
|
+
properties['extraScriptTags'] = scripts.to_json
|
131
|
+
|
132
|
+
endpoint = '/forms/chromium/convert/url'
|
133
|
+
|
134
|
+
self
|
135
|
+
end
|
136
|
+
|
137
|
+
def properties
|
138
|
+
@properties ||= {}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'gotenberg/chromium/properties'
|
2
|
+
require 'gotenberg/chromium/files'
|
3
|
+
require 'gotenberg/chromium/headers'
|
4
|
+
require 'gotenberg/chromium/metadata'
|
5
|
+
require 'gotenberg/client'
|
6
|
+
require 'gotenberg/exiftools'
|
7
|
+
require 'gotenberg/extractors'
|
8
|
+
|
9
|
+
module Gotenberg
|
10
|
+
class Chromium
|
11
|
+
include Properties, Files, Headers, Metadata, Extractors
|
12
|
+
|
13
|
+
attr_accessor :base_path
|
14
|
+
attr_reader :endpoint, :response, :exception
|
15
|
+
|
16
|
+
def self.call(base_path, &block)
|
17
|
+
new(base_path: base_path, &block).call
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize args
|
21
|
+
args.each do |key, value|
|
22
|
+
public_send(('%s=' % key), value)
|
23
|
+
end
|
24
|
+
|
25
|
+
yield self if block_given?
|
26
|
+
end
|
27
|
+
|
28
|
+
def call
|
29
|
+
transform
|
30
|
+
|
31
|
+
if success? && metadata_available?
|
32
|
+
modify_metadata
|
33
|
+
end
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def success?
|
39
|
+
@exception == nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_binary
|
43
|
+
response
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def transform
|
49
|
+
@response = client.adapter.post(endpoint, properties.merge(files: files), headers).body
|
50
|
+
rescue StandardError => e
|
51
|
+
@exception = e
|
52
|
+
end
|
53
|
+
|
54
|
+
def modify_metadata
|
55
|
+
@response = Exiftools.modify(response, metadata)
|
56
|
+
rescue StandardError => e
|
57
|
+
@exception = e
|
58
|
+
end
|
59
|
+
|
60
|
+
def client
|
61
|
+
@client ||= Client.new(base_path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday/multipart'
|
3
|
+
|
4
|
+
module Gotenberg
|
5
|
+
class Client
|
6
|
+
attr_reader :base_path
|
7
|
+
|
8
|
+
def initialize base_path
|
9
|
+
@base_path = base_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def adapter
|
13
|
+
@adapter ||= Faraday.new(base_path) do |c|
|
14
|
+
c.request :multipart
|
15
|
+
c.request :url_encoded
|
16
|
+
c.adapter :net_http
|
17
|
+
c.response :raise_error
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'gotenberg/analyzers/image'
|
3
|
+
require 'gotenberg/analyzers/js'
|
4
|
+
require 'gotenberg/analyzers/css'
|
5
|
+
|
6
|
+
module Gotenberg
|
7
|
+
class Compiler
|
8
|
+
CONTEXT_TAG_REGEX = /(<!-- GOTENBERG-CONTEXT-TAG (.+) -->)/.freeze
|
9
|
+
|
10
|
+
attr_accessor :html
|
11
|
+
|
12
|
+
def initialize html
|
13
|
+
@html = html
|
14
|
+
end
|
15
|
+
|
16
|
+
def body
|
17
|
+
@body ||= compile_body(html)
|
18
|
+
end
|
19
|
+
|
20
|
+
def assets
|
21
|
+
@assets ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def compile_body body
|
27
|
+
body.gsub(CONTEXT_TAG_REGEX) do |context_tag|
|
28
|
+
resource = JSON.parse($2, symbolize_names: true)
|
29
|
+
|
30
|
+
analyzer =
|
31
|
+
case resource[:tag]
|
32
|
+
when 'image'
|
33
|
+
Analyzers::Image.new(resource)
|
34
|
+
when 'js'
|
35
|
+
Analyzers::Js.new(resource)
|
36
|
+
when 'css'
|
37
|
+
Analyzers::Css.new(resource)
|
38
|
+
end
|
39
|
+
|
40
|
+
assets << analyzer.assets
|
41
|
+
|
42
|
+
analyzer.tag
|
43
|
+
|
44
|
+
#css -
|
45
|
+
# 1) read to io (http or file)
|
46
|
+
# 2) scan for url tags -
|
47
|
+
# if data - skip
|
48
|
+
# if relative (read to io http or file )
|
49
|
+
# replace url tags
|
50
|
+
# 3) check if inline then stylesheet tag
|
51
|
+
# 4) if not inline add to assets
|
52
|
+
# 5) replace tag
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'mini_exiftool'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
module Gotenberg
|
5
|
+
class Exiftools
|
6
|
+
attr_reader :io, :metadata
|
7
|
+
|
8
|
+
def self.modify io, metadata
|
9
|
+
new(io, metadata).call
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize io, metadata
|
13
|
+
@io = io
|
14
|
+
@metadata = metadata
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
set_attributes
|
19
|
+
write
|
20
|
+
|
21
|
+
@body
|
22
|
+
end
|
23
|
+
|
24
|
+
def exiftools
|
25
|
+
@exiftools ||= MiniExiftool.new(tempfile.path)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def set_attributes
|
31
|
+
metadata.each do |property, v|
|
32
|
+
exiftools.public_send(('%s=' % property), v)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def write
|
37
|
+
exiftools.save!
|
38
|
+
|
39
|
+
@body = tempfile.read
|
40
|
+
rescue StandardError => e
|
41
|
+
raise e
|
42
|
+
ensure
|
43
|
+
tempfile.close
|
44
|
+
tempfile.unlink
|
45
|
+
end
|
46
|
+
|
47
|
+
def tempfile
|
48
|
+
@tempfile ||= tempfile_builder do |file|
|
49
|
+
file << io
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def tempfile_builder
|
54
|
+
Tempfile.new(['gootenberg', '.pdf']).tap do |tempfile|
|
55
|
+
tempfile.binmode
|
56
|
+
yield tempfile if block_given?
|
57
|
+
tempfile.rewind
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gotenberg-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- sanzstez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-09-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday-multipart
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mini_exiftool
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.0
|
55
|
+
description: A gem that provides a client interface for the Gotenberg PDF generate
|
56
|
+
service
|
57
|
+
email:
|
58
|
+
- sanzstez@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- LICENSE.md
|
64
|
+
- README.md
|
65
|
+
- lib/gotenberg-ruby.rb
|
66
|
+
- lib/gotenberg/analyzers/base.rb
|
67
|
+
- lib/gotenberg/analyzers/css.rb
|
68
|
+
- lib/gotenberg/analyzers/image.rb
|
69
|
+
- lib/gotenberg/analyzers/js.rb
|
70
|
+
- lib/gotenberg/chromium.rb
|
71
|
+
- lib/gotenberg/chromium/files.rb
|
72
|
+
- lib/gotenberg/chromium/headers.rb
|
73
|
+
- lib/gotenberg/chromium/metadata.rb
|
74
|
+
- lib/gotenberg/chromium/properties.rb
|
75
|
+
- lib/gotenberg/client.rb
|
76
|
+
- lib/gotenberg/compiler.rb
|
77
|
+
- lib/gotenberg/exiftools.rb
|
78
|
+
- lib/gotenberg/extractors.rb
|
79
|
+
- lib/gotenberg/version.rb
|
80
|
+
homepage: https://github.com/sanzstez/gotenberg-ruby
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubygems_version: 3.0.9
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: A gem that provides a client interface for the Gotenberg PDF generate service
|
103
|
+
test_files: []
|