gotenberg-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,14 @@
1
+ module Gotenberg
2
+ module Extractors
3
+
4
+ private
5
+
6
+ def extract_metadata_from_body body, variables = {}
7
+ body.match('<title.*?>(.*?)<\/title>') do
8
+ variables.merge!(title: $1)
9
+ end
10
+
11
+ variables
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Gotenberg
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,5 @@
1
+ require 'gotenberg/version'
2
+
3
+ module Gotenberg
4
+ autoload :Chromium, 'gotenberg/chromium'
5
+ 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: []