ferrum_pdf 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +136 -12
- data/lib/ferrum_pdf/controller.rb +27 -0
- data/lib/ferrum_pdf/html_preprocessor.rb +26 -0
- data/lib/ferrum_pdf/railtie.rb +1 -1
- data/lib/ferrum_pdf/version.rb +1 -1
- data/lib/ferrum_pdf.rb +32 -47
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad27a3b666b15d934cc1bbf678ac52bfe86fc421723c89a60a123b3599aa2c39
|
4
|
+
data.tar.gz: 0a9bf56518d53ff03f84b9a9143280f97effe45b26edda3695a767d871bb0f73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a2fa255b8d7484952959023ac2ca320ce68259857adbba20fbb0dc9c455e40e6db6a7088daf22b8f70f85da2d31f8fc2c1550a6f6a2ad97cb9920a1841bfd2b
|
7
|
+
data.tar.gz: ed0d20754dee52a621880ef3ffc95894749b8ddfc5796226029d2417c2b6c18e4b29fb94bbae0dd3249d9f7e56e936c6b429f7640ebc7eb33bc5ba72556fb9dc
|
data/README.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
# FerrumPdf
|
2
2
|
|
3
|
-
PDFs for Rails using [Ferrum](https://github.com/rubycdp/ferrum) & headless Chrome
|
3
|
+
PDFs & screentshots for Rails using [Ferrum](https://github.com/rubycdp/ferrum) & headless Chrome.
|
4
|
+
|
5
|
+
Inspired by [Grover](https://github.com/Studiosity/grover).
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
9
|
+
First, make sure Chrome is installed
|
10
|
+
|
7
11
|
Run the following or add the gem to your Gemfile:
|
8
12
|
|
9
13
|
```ruby
|
@@ -12,7 +16,16 @@ bundle add "ferrum_pdf"
|
|
12
16
|
|
13
17
|
## Usage
|
14
18
|
|
15
|
-
|
19
|
+
You can use FerrumPdf to render [PDFs](#pdfs) and [Screenshots](#screenshots)
|
20
|
+
|
21
|
+
### 📄 PDFs
|
22
|
+
|
23
|
+
There are two ways to render PDFs:
|
24
|
+
|
25
|
+
* [FerrumPdf.render_pdf](#render-pdfs)
|
26
|
+
* [render_pdf in Rails](#render-pdfs-from-rails-controllers)
|
27
|
+
|
28
|
+
#### Render PDFs from Rails controllers
|
16
29
|
|
17
30
|
Use the `render_pdf` helper in Rails controllers to render a PDF from the current action.
|
18
31
|
|
@@ -20,34 +33,145 @@ Use the `render_pdf` helper in Rails controllers to render a PDF from the curren
|
|
20
33
|
def show
|
21
34
|
respond_to do |format|
|
22
35
|
format.html
|
23
|
-
format.pdf {
|
36
|
+
format.pdf {
|
37
|
+
pdf = render_pdf()
|
38
|
+
send_data pdf, disposition: :inline, filename: "example.pdf"
|
39
|
+
}
|
24
40
|
end
|
25
41
|
end
|
26
42
|
```
|
27
43
|
|
28
|
-
You can also customize which template is rendered:
|
44
|
+
You can also customize which template is rendered. This will render the template to string with `render_to_string` in Rails, then pass it along to Chrome. For example, you can add headers and footers using `pdf_options` and use a specific layout:
|
29
45
|
|
30
46
|
```ruby
|
31
|
-
render_pdf(
|
47
|
+
render_pdf(
|
48
|
+
layout: "pdf,
|
49
|
+
pdf_options: {
|
50
|
+
display_header_footer: true,
|
51
|
+
header_template: FerrumPdf::DEFAULT_HEADER_TEMPLATE,
|
52
|
+
footer_template: FerrumPdf::DEFAULT_FOOTER_TEMPLATE
|
53
|
+
}
|
54
|
+
)
|
32
55
|
```
|
33
56
|
|
34
|
-
|
35
|
-
|
36
|
-
### Directly with HTML
|
57
|
+
#### Render PDFs
|
37
58
|
|
38
|
-
FerrumPdf can generate a PDF from HTML
|
59
|
+
FerrumPdf can generate a PDF from HTML or a URL:
|
39
60
|
|
40
61
|
```ruby
|
41
62
|
FerrumPdf.render_pdf(html: content)
|
63
|
+
FerrumPdf.render_pdf(url: "https://google.com")
|
42
64
|
```
|
43
65
|
|
44
66
|
You can also pass host and protocol to convert any relative paths to full URLs. This is helpful for converting relative asset paths to full URLs.
|
45
67
|
|
46
68
|
```ruby
|
47
69
|
FerrumPdf.render_pdf(
|
48
|
-
html: content,
|
49
|
-
|
50
|
-
|
70
|
+
html: content, # Provide HTML
|
71
|
+
url: "https://example.com", # or provide a URL to the content
|
72
|
+
host: request.base_url + "/", # Used for setting the host for relative paths
|
73
|
+
protocol: request.protocol, # Used for handling relative protocol paths
|
74
|
+
|
75
|
+
pdf_options: {
|
76
|
+
landscape: false, # paper orientation
|
77
|
+
scale: 1, # Scale of the webpage rendering
|
78
|
+
format: nil,
|
79
|
+
paper_width: 8.5, # Paper width in inches
|
80
|
+
paper_height: 11, # Paper height in inches
|
81
|
+
page_ranges: nil, # Paper ranges to print "1-5, 8 11-13"
|
82
|
+
|
83
|
+
# Margins (in inches, defaults to 1cm)
|
84
|
+
margin_top: 0.4,
|
85
|
+
margin_bottom: 0.4,
|
86
|
+
margin_left: 0.4,
|
87
|
+
margin_right: 0.4,
|
88
|
+
|
89
|
+
# Header, footer, and background options
|
90
|
+
#
|
91
|
+
# Variables can be used with CSS classes. For example <span class="date"></span>
|
92
|
+
# * date: formatted print date
|
93
|
+
# * title: document title
|
94
|
+
# * url: document location
|
95
|
+
# * pageNumber: current page number
|
96
|
+
# *totalPages: total pages in the document
|
97
|
+
|
98
|
+
display_header_footer: false,
|
99
|
+
print_background: false, # Print background graphics
|
100
|
+
header_template: "", # HTML template for the header
|
101
|
+
footer_template: "", # HTML template for the footer
|
102
|
+
}
|
103
|
+
)
|
104
|
+
```
|
105
|
+
|
106
|
+
See [Chrome DevTools Protocol docs](https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF) and [Ferrum's `#pdf` docs](https://github.com/rubycdp/ferrum?tab=readme-ov-file#pdfoptions--string--boolean) for the full set of options.
|
107
|
+
|
108
|
+
### 🎆 Screenshots
|
109
|
+
|
110
|
+
There are two ways to render Screenshots:
|
111
|
+
|
112
|
+
* [FerrumPdf.render_screenshot](#render-screenshot)
|
113
|
+
* [render_screenshot in Rails](#render-screenshots-from-rails-controllers)
|
114
|
+
|
115
|
+
#### Render Screenshot from Rails controller
|
116
|
+
|
117
|
+
Use the `render_screenshot` helper in Rails controllers to render a PDF from the current action.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
def show
|
121
|
+
respond_to do |format|
|
122
|
+
format.html
|
123
|
+
format.png {
|
124
|
+
screenshot = render_screenshot()
|
125
|
+
send_data screenshot, disposition: :inline, filename: "example.png"
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
You can also customize which template is rendered. This will render the template to string with `render_to_string` in Rails, then pass it along to Chrome.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
render_screenshot(
|
135
|
+
screenshot_options: {
|
136
|
+
format: "png" # or "jpeg"
|
137
|
+
quality: nil # Integer 0-100 works for jpeg only
|
138
|
+
full: true # Boolean whether you need full page screenshot or a viewport
|
139
|
+
selector: nil # String css selector for given element, optional
|
140
|
+
area: nil # Hash area for screenshot, optional. {x: 0, y: 0, width: 100, height: 100}
|
141
|
+
scale: nil # Float zoom in/out
|
142
|
+
background_color: nil # Ferrum::RGBA.new(0, 0, 0, 0.0)
|
143
|
+
}
|
144
|
+
)
|
145
|
+
```
|
146
|
+
|
147
|
+
See [Ferrum screenshot docs](https://github.com/rubycdp/ferrum?tab=readme-ov-file#screenshotoptions--string--integer) for the full set of options.
|
148
|
+
|
149
|
+
#### Render Screenshots
|
150
|
+
|
151
|
+
FerrumPdf can generate a screenshot from HTML or a URL:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
FerrumPdf.render_screenshot(html: content)
|
155
|
+
FerrumPdf.render_screenshot(url: "https://google.com")
|
156
|
+
```
|
157
|
+
|
158
|
+
You can also pass host and protocol to convert any relative paths to full URLs. This is helpful for converting relative asset paths to full URLs.
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
FerrumPdf.render_screenshot(
|
162
|
+
html: "",
|
163
|
+
url: "",
|
164
|
+
root_url: "",
|
165
|
+
protocol: "",
|
166
|
+
screenshot_options: {
|
167
|
+
format: "png" # or "jpeg"
|
168
|
+
quality: nil # Integer 0-100 works for jpeg only
|
169
|
+
full: true # Boolean whether you need full page screenshot or a viewport
|
170
|
+
selector: nil # String css selector for given element, optional
|
171
|
+
area: nil # Hash area for screenshot, optional. {x: 0, y: 0, width: 100, height: 100}
|
172
|
+
scale: nil # Float zoom in/out
|
173
|
+
background_color: nil # Ferrum::RGBA.new(0, 0, 0, 0.0)
|
174
|
+
}
|
51
175
|
)
|
52
176
|
```
|
53
177
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module FerrumPdf
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
def render_pdf(pdf_options: {}, **rendering)
|
6
|
+
content = render_to_string(**rendering.with_defaults(formats: [ :html ]))
|
7
|
+
|
8
|
+
FerrumPdf.render_pdf(
|
9
|
+
html: content,
|
10
|
+
host: request.base_url + "/",
|
11
|
+
protocol: request.protocol,
|
12
|
+
pdf_options: pdf_options
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_screenshot(screenshot_options: {}, **rendering)
|
17
|
+
content = render_to_string(**rendering.with_defaults(formats: [ :html ]))
|
18
|
+
|
19
|
+
FerrumPdf.render_screenshot(
|
20
|
+
html: content,
|
21
|
+
host: request.base_url + "/",
|
22
|
+
protocol: request.protocol,
|
23
|
+
screenshot_options: screenshot_options
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module FerrumPdf
|
2
|
+
# Helper module for preparing HTML for conversion
|
3
|
+
#
|
4
|
+
# Sourced from the PDFKit project
|
5
|
+
# @see https://github.com/pdfkit/pdfkit
|
6
|
+
module HTMLPreprocessor
|
7
|
+
# Change relative paths to absolute, and relative protocols to absolute protocols
|
8
|
+
def self.process(html, root_url, protocol)
|
9
|
+
html = translate_relative_paths(html, root_url) if root_url
|
10
|
+
html = translate_relative_protocols(html, protocol) if protocol
|
11
|
+
html
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.translate_relative_paths(html, root_url)
|
15
|
+
# Try out this regexp using rubular http://rubular.com/r/hiAxBNX7KE
|
16
|
+
html.gsub(%r{(href|src)=(['"])/([^/"']([^"']*|[^"']*))?['"]}, "\\1=\\2#{root_url}\\3\\2")
|
17
|
+
end
|
18
|
+
private_class_method :translate_relative_paths
|
19
|
+
|
20
|
+
def self.translate_relative_protocols(body, protocol)
|
21
|
+
# Try out this regexp using rubular http://rubular.com/r/0Ohk0wFYxV
|
22
|
+
body.gsub(%r{(href|src)=(['"])//([^"']*|[^"']*)['"]}, "\\1=\\2#{protocol}://\\3\\2")
|
23
|
+
end
|
24
|
+
private_class_method :translate_relative_protocols
|
25
|
+
end
|
26
|
+
end
|
data/lib/ferrum_pdf/railtie.rb
CHANGED
data/lib/ferrum_pdf/version.rb
CHANGED
data/lib/ferrum_pdf.rb
CHANGED
@@ -1,15 +1,38 @@
|
|
1
1
|
require "ferrum_pdf/version"
|
2
2
|
require "ferrum_pdf/railtie"
|
3
|
-
|
4
3
|
require "ferrum"
|
5
4
|
|
6
5
|
module FerrumPdf
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
DEFAULT_HEADER_TEMPLATE = "<div class='date text left'></div><div class='title text center'></div>"
|
7
|
+
DEFAULT_FOOTER_TEMPLATE = <<~HTML
|
8
|
+
<div class='url text left grow'></div>
|
9
|
+
<div class='text right'><span class='pageNumber'></span>/<span class='totalPages'></span></div>
|
10
|
+
HTML
|
11
|
+
|
12
|
+
autoload :Controller, "ferrum_pdf/controller"
|
13
|
+
autoload :HTMLPreprocessor, "ferrum_pdf/html_preprocessor"
|
14
|
+
|
15
|
+
mattr_accessor :include_controller_module
|
16
|
+
@@include_controller_module = true
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def browser(**options)
|
20
|
+
@browser ||= Ferrum::Browser.new(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render_pdf(html: nil, url: nil, host: nil, protocol: nil, pdf_options: {})
|
24
|
+
render(host: host, protocol: protocol, html: html, url: url) do |page|
|
25
|
+
page.pdf(**pdf_options.with_defaults(encoding: :binary))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_screenshot(html: nil, url: nil, host: nil, protocol: nil, screenshot_options: {})
|
30
|
+
render(host: host, protocol: protocol, html: html, url: url) do |page|
|
31
|
+
page.screenshot(**screenshot_options.with_defaults(encoding: :binary, full: true))
|
32
|
+
end
|
33
|
+
end
|
10
34
|
|
11
|
-
|
12
|
-
Tempfile.create do |file|
|
35
|
+
def render(host:, protocol:, html: nil, url: nil)
|
13
36
|
browser.create_page do |page|
|
14
37
|
if html
|
15
38
|
page.content = FerrumPdf::HTMLPreprocessor.process(html, host, protocol)
|
@@ -17,48 +40,10 @@ module FerrumPdf
|
|
17
40
|
else
|
18
41
|
page.go_to(url)
|
19
42
|
end
|
20
|
-
page
|
21
|
-
file.read
|
43
|
+
yield page
|
22
44
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
# Helper module for preparing HTML for conversion
|
27
|
-
#
|
28
|
-
# Sourced from the PDFKit project
|
29
|
-
# @see https://github.com/pdfkit/pdfkit
|
30
|
-
module HTMLPreprocessor
|
31
|
-
# Change relative paths to absolute, and relative protocols to absolute protocols
|
32
|
-
def self.process(html, root_url, protocol)
|
33
|
-
html = translate_relative_paths(html, root_url) if root_url
|
34
|
-
html = translate_relative_protocols(html, protocol) if protocol
|
35
|
-
html
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.translate_relative_paths(html, root_url)
|
39
|
-
# Try out this regexp using rubular http://rubular.com/r/hiAxBNX7KE
|
40
|
-
html.gsub(%r{(href|src)=(['"])/([^/"']([^"']*|[^"']*))?['"]}, "\\1=\\2#{root_url}\\3\\2")
|
41
|
-
end
|
42
|
-
private_class_method :translate_relative_paths
|
43
|
-
|
44
|
-
def self.translate_relative_protocols(body, protocol)
|
45
|
-
# Try out this regexp using rubular http://rubular.com/r/0Ohk0wFYxV
|
46
|
-
body.gsub(%r{(href|src)=(['"])//([^"']*|[^"']*)['"]}, "\\1=\\2#{protocol}://\\3\\2")
|
47
|
-
end
|
48
|
-
private_class_method :translate_relative_protocols
|
49
|
-
end
|
50
|
-
|
51
|
-
module Controller
|
52
|
-
extend ActiveSupport::Concern
|
53
|
-
|
54
|
-
def render_pdf(name = action_name, formats: [ :html ])
|
55
|
-
content = render_to_string(name, formats: formats)
|
56
|
-
|
57
|
-
FerrumPdf.render_pdf(
|
58
|
-
html: content,
|
59
|
-
host: request.host_with_port,
|
60
|
-
protocol: request.protocol
|
61
|
-
)
|
45
|
+
rescue Ferrum::DeadBrowserError
|
46
|
+
retry
|
62
47
|
end
|
63
48
|
end
|
64
49
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ferrum_pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Oliver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-09-
|
11
|
+
date: 2024-09-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,7 +38,8 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.15'
|
41
|
-
description: Export PDFs from HTML in Rails using Ferrum & headless
|
41
|
+
description: Export PDFs & screenshots from HTML in Rails using Ferrum & headless
|
42
|
+
Chrome
|
42
43
|
email:
|
43
44
|
- excid3@gmail.com
|
44
45
|
executables: []
|
@@ -49,6 +50,8 @@ files:
|
|
49
50
|
- README.md
|
50
51
|
- Rakefile
|
51
52
|
- lib/ferrum_pdf.rb
|
53
|
+
- lib/ferrum_pdf/controller.rb
|
54
|
+
- lib/ferrum_pdf/html_preprocessor.rb
|
52
55
|
- lib/ferrum_pdf/railtie.rb
|
53
56
|
- lib/ferrum_pdf/version.rb
|
54
57
|
- lib/tasks/ferrum_pdf_tasks.rake
|
@@ -74,8 +77,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
77
|
- !ruby/object:Gem::Version
|
75
78
|
version: '0'
|
76
79
|
requirements: []
|
77
|
-
rubygems_version: 3.5.
|
80
|
+
rubygems_version: 3.5.16
|
78
81
|
signing_key:
|
79
82
|
specification_version: 4
|
80
|
-
summary: PDFs for Rails using Ferrum & headless Chrome
|
83
|
+
summary: PDFs & screenshots for Rails using Ferrum & headless Chrome
|
81
84
|
test_files: []
|