gotenberg-ruby 1.0.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.
- 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: []
|