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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ea0c6aba4254ef7d958dec7d9f51048ce82e106ab068a413c1e3b83ec470b01
4
- data.tar.gz: e34df1014f457e4ad42a41a5a29ab9a0d0ab42027cb8d8374aeacf6557a49833
3
+ metadata.gz: ad27a3b666b15d934cc1bbf678ac52bfe86fc421723c89a60a123b3599aa2c39
4
+ data.tar.gz: 0a9bf56518d53ff03f84b9a9143280f97effe45b26edda3695a767d871bb0f73
5
5
  SHA512:
6
- metadata.gz: 68e840f65f0c0821cb8dfe6f3e249e2b5b567f8d3655c1a71a59f143beb25241aedea29fe33d95b18763a32fd5eea88bec9f6a9f4b0b6181df082544cc2453c2
7
- data.tar.gz: 123f094697e37dcee391c157ca5ba379b1b9557e8a4e7c017cb7b45861936bf24e484bec74092793dd3e64e36ffaee0a98bc613f56ed9a5e4e2dfefdbf7f1ac1
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
- ### Rails controllers
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 { send_data render_pdf, disposition: :inline, filename: "example.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(name = action_name, formats: [ :html ])
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
- This will render the template to string, then pass it along to FerrumPdf.
35
-
36
- ### Directly with HTML
57
+ #### Render PDFs
37
58
 
38
- FerrumPdf can generate a PDF from HTML directly:
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
- host: request.host_with_port,
50
- protocol: request.protocol
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
@@ -2,7 +2,7 @@ module FerrumPdf
2
2
  class Railtie < ::Rails::Railtie
3
3
  initializer "ferrum_pdf.controller" do
4
4
  ActiveSupport.on_load(:action_controller) do
5
- include FerrumPdf::Controller
5
+ include FerrumPdf::Controller if FerrumPdf.include_controller_module
6
6
  end
7
7
  end
8
8
  end
@@ -1,3 +1,3 @@
1
1
  module FerrumPdf
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.0"
3
3
  end
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
- def self.browser(**options)
8
- @browser ||= Ferrum::Browser.new(options)
9
- end
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
- def self.render_pdf(host:, protocol:, html: nil, url: nil)
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.pdf(path: file.path)
21
- file.read
43
+ yield page
22
44
  end
23
- end
24
- end
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.1.1
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-20 00:00:00.000000000 Z
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 Chrome
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.18
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: []