ferrum_pdf 2.1.0 → 3.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e10a66bff6f06cfd7388c12247ca55e92a79bc48ff741e889e0ac0bfde0286e0
4
- data.tar.gz: 2a92a79c5a7ca34091644fcd5795d1d1c84d49f7d834f02afd6d9ec462ba892b
3
+ metadata.gz: efe120091d2cc3eaaf6ce3e7fc5ccb3c34d3fabe59570986fa5b08d89295b58a
4
+ data.tar.gz: b3923cb2306e1cd27023725ddb088ae9f6ed290aab538db1e0d27bdb032d79cd
5
5
  SHA512:
6
- metadata.gz: c6d4472cb10faebb29ab64634f16063c7aac7927baf76e3e58dc72478d3d21819935138e6595a872f9e0766ff51a17303cad51a1857d62110b2e13fd4877234f
7
- data.tar.gz: 9915cadbed613d26c113a57d5a23268ec3758ef9f566b5f6f387469ed4cce948d5348173a840cf9d36a44d935fda1a3e5f7cb06af5c5f042d73f2fb06707a892
6
+ metadata.gz: 4e44f85006fc98e28298c2e3720b3066bc59611c32b439791df54d5b70e4dae5eaa62fabe1499d75f7f85599ff79e52ffee60485556f3b1167a1082aeb381702
7
+ data.tar.gz: 86ad9105c1a8e2bf3c867a91e0a409d045d5ffdbc6755bdfa5af02a7948271c32ab063a138f3ff09903daa3f100642ef8f328aea154cb4e316add75944d07680
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # 📄 FerrumPdf
2
2
 
3
- PDFs & screentshots for Rails using [Ferrum](https://github.com/rubycdp/ferrum) & headless Chrome.
3
+ PDFs & screenshots for Rails using [Ferrum](https://github.com/rubycdp/ferrum) & headless Chrome.
4
4
 
5
5
  Inspired by [Grover](https://github.com/Studiosity/grover), but without the Node.js and puppeteer dependencies. 🎉
6
6
 
@@ -70,10 +70,11 @@ FerrumPdf.render_pdf(
70
70
  url: "https://example.com/page", # Provide a URL to the content
71
71
 
72
72
  html: content, # or provide HTML
73
- base_url: request.base_url, # Preprocesses `html` to convert relative paths and protocols. Example: "https://example.org"
73
+ display_url: request.original_url, # When supplying content via :html its best to give Chrome a hint of the current url so that it can process relative paths in the document. If you don't provide this, http://example.com will be used instead.
74
74
 
75
75
  authorize: { user: "username", password: "password" }, # Used for authenticating with basic auth
76
76
  wait_for_idle_options: { connections: 0, duration: 0.05, timeout: 5 }, # Used for setting network wait_for_idle options
77
+ timeout_if_open_connections: true,
77
78
 
78
79
  pdf_options: {
79
80
  landscape: false, # paper orientation
@@ -166,7 +167,7 @@ FerrumPdf.render_screenshot(
166
167
  url: "https://example.com/page", # Provide a URL to the content
167
168
 
168
169
  html: content, # or provide HTML
169
- base_url: request.base_url, # Preprocesses `html` to convert relative paths and protocols. Example: "https://example.org"
170
+ display_url: request.original_url, # When supplying content via :html its best to give Chrome a hint of the current url so that it can process relative paths in the document. If you don't provide this, http://example.com will be used instead.
170
171
 
171
172
  screenshot_options: {
172
173
  format: "png" # or "jpeg"
@@ -186,7 +187,6 @@ You can set default values for page loads, PDF renders, and screenshot renders w
186
187
 
187
188
  ```ruby
188
189
  FerrumPdf.configure do |config|
189
- config.page_options.base_url = "https://example.com/"
190
190
  config.page_options.authorize = { user: "username", password: "password" }
191
191
  config.page_options.wait_for_idle_options = { timeout: 90 }
192
192
  config.page_options.retries = 3
@@ -0,0 +1,19 @@
1
+ ActiveSupport.on_load(:action_controller) do
2
+ # render ferrum_pdf: { pdf options }, template: "whatever", disposition: :inline, filename: "example.pdf"
3
+ ActionController.add_renderer :ferrum_pdf do |pdf_options, options|
4
+ send_data_options = options.extract!(:disposition, :filename, :status)
5
+ url = pdf_options.delete(:url)
6
+ html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank?
7
+ pdf = FerrumPdf.render_pdf(html: html, display_url: request.original_url, url: url, pdf_options: pdf_options)
8
+ send_data(pdf, **send_data_options.with_defaults(type: :pdf))
9
+ end
10
+
11
+ # render ferrum_screenshot: { pdf options }, template: "whatever", disposition: :inline, filename: "example.png"
12
+ ActionController.add_renderer :ferrum_screenshot do |screenshot_options, options|
13
+ send_data_options = options.extract!(:disposition, :filename, :status)
14
+ url = screenshot_options.delete(:url)
15
+ html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank?
16
+ screenshot = FerrumPdf.render_screenshot(url: url, html: html, display_url: request.original_url, screenshot_options: screenshot_options)
17
+ send_data(screenshot, **send_data_options.with_defaults(type: screenshot_options.fetch(:format, :png)))
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module FerrumPdf
2
- VERSION = "2.1.0"
2
+ VERSION = "3.0.1"
3
3
  end
data/lib/ferrum_pdf.rb CHANGED
@@ -1,6 +1,8 @@
1
- require "ferrum_pdf/version"
2
- require "ferrum_pdf/railtie"
3
1
  require "ferrum"
2
+ require "action_controller"
3
+
4
+ require "ferrum_pdf/renderers"
5
+ require "ferrum_pdf/version"
4
6
 
5
7
  module FerrumPdf
6
8
  DEFAULT_HEADER_TEMPLATE = "<div class='date text left'></div><div class='title text center'></div>"
@@ -9,9 +11,6 @@ module FerrumPdf
9
11
  <div class='text right'><span class='pageNumber'></span>/<span class='totalPages'></span></div>
10
12
  HTML
11
13
 
12
- autoload :AssetsHelper, "ferrum_pdf/assets_helper"
13
- autoload :HTMLPreprocessor, "ferrum_pdf/html_preprocessor"
14
-
15
14
  mattr_accessor :browser_mutex, default: Mutex.new
16
15
  mattr_accessor :config, default: ActiveSupport::OrderedOptions.new.merge(
17
16
  window_size: [ 1920, 1080 ],
@@ -57,9 +56,9 @@ module FerrumPdf
57
56
  # render_pdf(url: "https://example.org/receipts/example.pdf")
58
57
  # render_pdf(html: "<h1>Hello world</h1>")
59
58
  #
60
- # For rendering HTML, we also need the base_url for preprocessing URLs with relative paths & protocols
59
+ # For rendering HTML, we also need display_url for so that Chrome can interpret URLs with relative paths & protocols
61
60
  #
62
- # render_pdf(html: "<h1>Hello world</h1>", base_url: "https://example.org/")
61
+ # render_pdf(html: "<h1>Hello world</h1>", display_url: "https://example.org/hello_world")
63
62
  #
64
63
  def render_pdf(pdf_options: {}, **load_page_args)
65
64
  load_page(**load_page_args) do |browser, page|
@@ -73,9 +72,9 @@ module FerrumPdf
73
72
  # render_screenshot(url: "https://example.org/receipts/example.pdf")
74
73
  # render_screenshot(html: "<h1>Hello world</h1>")
75
74
  #
76
- # For rendering HTML, we also need the base_url for preprocessing URLs with relative paths & protocols
75
+ # For rendering HTML, we also need display_url for so that Chrome can interpret URLs with relative paths & protocols
77
76
  #
78
- # render_screenshot(html: "<h1>Hello world</h1>", base_url: "https://example.org/")
77
+ # render_screenshot(html: "<h1>Hello world</h1>", display_url: "https://example.org/hello_world")
79
78
  #
80
79
  def render_screenshot(screenshot_options: {}, **load_page_args)
81
80
  load_page(**load_page_args) do |browser, page|
@@ -84,16 +83,16 @@ module FerrumPdf
84
83
  end
85
84
  end
86
85
 
86
+ private
87
+
87
88
  # Loads page into the browser to be used for rendering PDFs or screenshots
88
89
  #
89
- # This automatically applies HTML preprocessing if `html:` is present
90
- #
91
- def load_page(url: nil, html: nil, base_url: nil, authorize: nil, wait_for_idle_options: nil, browser: nil, retries: nil)
90
+ def load_page(url: nil, html: nil, display_url: nil, authorize: nil, wait_for_idle_options: nil, timeout_if_open_connections: nil, browser: nil, retries: nil)
92
91
  try ||= 0
93
92
  authorize ||= config.dig(:page_options, :authorize)
94
- base_url ||= config.dig(:page_options, :base_url)
95
93
  retries ||= config.page_options.fetch(:retries, 1)
96
94
  wait_for_idle_options = config.page_options.fetch(:wait_for_idle_options, {}).merge(wait_for_idle_options || {})
95
+ timeout_if_open_connections = config.page_options.fetch(:timeout_if_open_connections, true) if timeout_if_open_connections.nil?
97
96
 
98
97
  with_browser(browser) do |browser|
99
98
  # Closes page automatically after block finishes
@@ -103,13 +102,24 @@ module FerrumPdf
103
102
 
104
103
  # Load content
105
104
  if html
106
- page.content = FerrumPdf::HTMLPreprocessor.process(html, base_url)
105
+ html_intercepted = false
106
+ page.network.intercept
107
+ page.on(:request) do |request|
108
+ if html_intercepted
109
+ request.continue
110
+ else
111
+ html_intercepted = true
112
+ request.respond(body: html.blank? ? " " : html)
113
+ end
114
+ end
115
+ page.go_to(display_url || "http://example.com")
107
116
  else
108
117
  page.go_to(url)
109
118
  end
110
119
 
111
120
  # Wait for everything to load
112
- page.network.wait_for_idle!(**wait_for_idle_options)
121
+ idle = page.network.wait_for_idle(**wait_for_idle_options)
122
+ raise Ferrum::TimeoutError if timeout_if_open_connections && !idle
113
123
 
114
124
  yield browser, page
115
125
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ferrum_pdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Oliver
@@ -10,7 +10,7 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: rails
13
+ name: actionpack
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
@@ -49,9 +49,7 @@ files:
49
49
  - README.md
50
50
  - Rakefile
51
51
  - lib/ferrum_pdf.rb
52
- - lib/ferrum_pdf/assets_helper.rb
53
- - lib/ferrum_pdf/html_preprocessor.rb
54
- - lib/ferrum_pdf/railtie.rb
52
+ - lib/ferrum_pdf/renderers.rb
55
53
  - lib/ferrum_pdf/version.rb
56
54
  homepage: https://github.com/excid3/ferrum_pdf
57
55
  licenses:
@@ -74,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
74
72
  - !ruby/object:Gem::Version
75
73
  version: '0'
76
74
  requirements: []
77
- rubygems_version: 3.7.1
75
+ rubygems_version: 3.6.9
78
76
  specification_version: 4
79
77
  summary: PDFs & screenshots for Rails using Ferrum & headless Chrome
80
78
  test_files: []
@@ -1,65 +0,0 @@
1
- module FerrumPdf
2
- class BaseAsset
3
- def initialize(asset)
4
- @asset = asset
5
- end
6
- end
7
-
8
- class PropshaftAsset < BaseAsset
9
- def content_type
10
- @asset.content_type.to_s
11
- end
12
-
13
- def content
14
- @asset.content
15
- end
16
- end
17
-
18
- class SprocketsAsset < BaseAsset
19
- def content_type
20
- @asset.content_type
21
- end
22
-
23
- def content
24
- @asset.source
25
- end
26
- end
27
-
28
- class AssetFinder
29
- class << self
30
- def find(path)
31
- if Rails.application.assets.respond_to?(:load_path)
32
- propshaft_asset(path)
33
- elsif Rails.application.assets.respond_to?(:find_asset)
34
- sprockets_asset(path)
35
- else
36
- nil
37
- end
38
- end
39
-
40
- def propshaft_asset(path)
41
- (asset = Rails.application.assets.load_path.find(path)) ? PropshaftAsset.new(asset) : nil
42
- end
43
-
44
- def sprockets_asset(path)
45
- (asset = Rails.application.assets.find_asset(path)) ? SprocketsAsset.new(asset) : nil
46
- end
47
- end
48
- end
49
-
50
- module AssetsHelper
51
- def ferrum_pdf_inline_stylesheet(path)
52
- (asset = AssetFinder.find(path)) ? "<style>#{asset.content}</style>".html_safe : nil
53
- end
54
-
55
- def ferrum_pdf_inline_javascript(path)
56
- (asset = AssetFinder.find(path)) ? "<script>#{asset.content}</script>".html_safe : nil
57
- end
58
-
59
- def ferrum_pdf_base64_asset(path)
60
- return nil unless (asset = AssetFinder.find(path))
61
-
62
- "data:#{asset.content_type};base64,#{Base64.encode64(asset.content).gsub(/\s+/, '')}"
63
- end
64
- end
65
- end
@@ -1,33 +0,0 @@
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
- #
9
- # process("Some HTML", "https://example.org")
10
- #
11
- def self.process(html, base_url)
12
- return html if base_url.blank?
13
-
14
- base_url += "/" unless base_url.end_with? "/"
15
- protocol = base_url.split("://").first
16
- html = translate_relative_paths(html, base_url) if base_url
17
- html = translate_relative_protocols(html, protocol) if protocol
18
- html
19
- end
20
-
21
- def self.translate_relative_paths(html, base_url)
22
- # Try out this regexp using rubular http://rubular.com/r/hiAxBNX7KE
23
- html.gsub(%r{(href|src)=(['"])/([^/"']([^"']*|[^"']*))?['"]}, "\\1=\\2#{base_url}\\3\\2")
24
- end
25
- private_class_method :translate_relative_paths
26
-
27
- def self.translate_relative_protocols(body, protocol)
28
- # Try out this regexp using rubular http://rubular.com/r/0Ohk0wFYxV
29
- body.gsub(%r{(href|src)=(['"])//([^"']*|[^"']*)['"]}, "\\1=\\2#{protocol}://\\3\\2")
30
- end
31
- private_class_method :translate_relative_protocols
32
- end
33
- end
@@ -1,31 +0,0 @@
1
- module FerrumPdf
2
- class Railtie < ::Rails::Railtie
3
- initializer "ferrum_pdf.assets_helper" do
4
- ActiveSupport.on_load(:action_view) do
5
- include FerrumPdf::AssetsHelper
6
- end
7
- end
8
-
9
- initializer "ferrum_pdf.controller" do
10
- ActiveSupport.on_load(:action_controller) do
11
- # render ferrum_pdf: { pdf options }, template: "whatever", disposition: :inline, filename: "example.pdf"
12
- ActionController.add_renderer :ferrum_pdf do |pdf_options, options|
13
- send_data_options = options.extract!(:disposition, :filename, :status)
14
- url = pdf_options.delete(:url)
15
- html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank?
16
- pdf = FerrumPdf.render_pdf(html: html, base_url: request.base_url, url: url, pdf_options: pdf_options)
17
- send_data(pdf, **send_data_options.with_defaults(type: :pdf))
18
- end
19
-
20
- # render ferrum_screenshot: { pdf options }, template: "whatever", disposition: :inline, filename: "example.png"
21
- ActionController.add_renderer :ferrum_screenshot do |screenshot_options, options|
22
- send_data_options = options.extract!(:disposition, :filename, :status)
23
- url = screenshot_options.delete(:url)
24
- html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank?
25
- screenshot = FerrumPdf.render_screenshot(url: url, html: html, base_url: request.base_url, screenshot_options: screenshot_options)
26
- send_data(screenshot, **send_data_options.with_defaults(type: screenshot_options.fetch(:format, :png)))
27
- end
28
- end
29
- end
30
- end
31
- end