diff --git a/CHANGELOG.md b/CHANGELOG.md index 7204c55..145314a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,45 @@ ### Unreleased +* Replace controller methods with a Rails renderer + + This provides a much cleaner and better named Rails integration. You can pass options directly into the `render` method which will render the PDF or screenshot and pass it along to `send_data` for you. + + Before: + + ```ruby + class PdfsController < ApplicationController + def show + respond_to do |format| + format.pdf { + pdf = render_pdf() + send_data pdf, disposition: :inline, filename: "example.pdf" + } + format.png { + screenshot = render_screenshot() + send_data screenshot, disposition: :inline, filename: "example.png" + } + end + end + end + ``` + + After: + + ```ruby + class PdfsController < ApplicationController + def show + respond_to do |format| + format.pdf { render ferrum_pdf: {}, disposition: :inline, filename: "example.pdf" } + format.png { render ferrum_screenshot: {}, disposition: :inline, filename: "example.png" } + end + end + end + ``` + + + +* [Breaking] Remove assets helper config option. This will always be included by default. + ### 1.0.0 * No changes diff --git a/README.md b/README.md index bdf0e92..49645d6 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,7 @@ Inspired by [Grover](https://github.com/Studiosity/grover), but without the Node ## Installation -First, make sure Chrome is installed. - -Run the following or add the gem to your Gemfile: +First, make sure Chrome is installed. Then run the following or add the gem to your Gemfile: ```ruby bundle add "ferrum_pdf" @@ -22,21 +20,18 @@ You can use FerrumPdf to render [PDFs](#-pdfs) and [Screenshots](#-screenshots) There are two ways to render PDFs: +* [`render ferrum_pdf: {}` in Rails](#render-pdfs-from-rails-controllers) * [FerrumPdf.render_pdf](#render-pdfs) -* [render_pdf in Rails](#render-pdfs-from-rails-controllers) #### Render PDFs from Rails controllers -Use the `render_pdf` helper in Rails controllers to render a PDF from the current action. +Use the `ferrum_pdf` renderer in Rails controllers to render a PDF from the current action. ```ruby def show respond_to do |format| format.html - format.pdf { - pdf = render_pdf() - send_data pdf, disposition: :inline, filename: "example.pdf" - } + format.pdf { render ferrum_pdf: {}, disposition: :inline, filename: "example.pdf" } end end ``` @@ -44,14 +39,17 @@ end 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: ```ruby -render_pdf( - layout: "pdf, +render ferrum_pdf: { pdf_options: { display_header_footer: true, header_template: FerrumPdf::DEFAULT_HEADER_TEMPLATE, footer_template: FerrumPdf::DEFAULT_FOOTER_TEMPLATE - } -) + }, + layout: "pdf", + template: "pdf", + disposition: :inline, + filename: "example.pdf" +} ``` #### Render PDFs @@ -112,21 +110,18 @@ See [Chrome DevTools Protocol docs](https://chromedevtools.github.io/devtools-pr There are two ways to render Screenshots: +* [`render ferrum_screenshot: {}` in Rails](#render-screenshots-from-rails-controllers) * [FerrumPdf.render_screenshot](#render-screenshots) -* [render_screenshot in Rails](#render-screenshots-from-rails-controllers) #### Render Screenshots from Rails controllers -Use the `render_screenshot` helper in Rails controllers to render a PDF from the current action. +Use the `ferrum_screenshot` renderer in Rails controllers to render a PDF from the current action. ```ruby def show respond_to do |format| format.html - format.png { - screenshot = render_screenshot() - send_data screenshot, disposition: :inline, filename: "example.png" - } + format.png { render ferrum_screenshot: {}, disposition: :inline, filename: "example.png" } end end ``` @@ -134,7 +129,7 @@ end 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. ```ruby -render_screenshot( +render ferrum_screenshot: { screenshot_options: { format: "png" # or "jpeg" quality: nil # Integer 0-100 works for jpeg only @@ -143,8 +138,12 @@ render_screenshot( area: nil # Hash area for screenshot, optional. {x: 0, y: 0, width: 100, height: 100} scale: nil # Float zoom in/out background_color: nil # Ferrum::RGBA.new(0, 0, 0, 0.0) - } -) + }, + layout: "example", + template: "example" + disposition: :inline, + filename: "example.png" +} ``` See [Ferrum screenshot docs](https://github.com/rubycdp/ferrum?tab=readme-ov-file#screenshotoptions--string--integer) for the full set of options. diff --git a/lib/ferrum_pdf.rb b/lib/ferrum_pdf.rb index 35161c7..7cd7d36 100644 --- a/lib/ferrum_pdf.rb +++ b/lib/ferrum_pdf.rb @@ -10,12 +10,9 @@ module FerrumPdf HTML autoload :AssetsHelper, "ferrum_pdf/assets_helper" - autoload :Controller, "ferrum_pdf/controller" autoload :HTMLPreprocessor, "ferrum_pdf/html_preprocessor" mattr_accessor :browser_mutex, default: Mutex.new - mattr_accessor :include_assets_helper_module, default: true - mattr_accessor :include_controller_module, default: true mattr_accessor :config, default: ActiveSupport::OrderedOptions.new.merge( window_size: [ 1920, 1080 ] ) @@ -90,6 +87,7 @@ def render_screenshot(screenshot_options: {}, **load_page_args) # def load_page(url: nil, html: nil, base_url: nil, authorize: nil, wait_for_idle_options: nil, browser: nil, retries: 1) try = 0 + wait_for_idle_options ||= {} with_browser(browser) do |browser| # Closes page automatically after block finishes diff --git a/lib/ferrum_pdf/assets_helper.rb b/lib/ferrum_pdf/assets_helper.rb index 737817a..bb58806 100644 --- a/lib/ferrum_pdf/assets_helper.rb +++ b/lib/ferrum_pdf/assets_helper.rb @@ -1,53 +1,53 @@ module FerrumPdf - module AssetsHelper - class BaseAsset - def initialize(asset) - @asset = asset - end + class BaseAsset + def initialize(asset) + @asset = asset end + end - class PropshaftAsset < BaseAsset - def content_type - @asset.content_type.to_s - end + class PropshaftAsset < BaseAsset + def content_type + @asset.content_type.to_s + end - def content - @asset.content - end + def content + @asset.content end + end - class SprocketsAsset < BaseAsset - def content_type - @asset.content_type - end + class SprocketsAsset < BaseAsset + def content_type + @asset.content_type + end - def content - @asset.source - end + def content + @asset.source end + end - class AssetFinder - class << self - def find(path) - if Rails.application.assets.respond_to?(:load_path) - propshaft_asset(path) - elsif Rails.application.assets.respond_to?(:find_asset) - sprockets_asset(path) - else - nil - end + class AssetFinder + class << self + def find(path) + if Rails.application.assets.respond_to?(:load_path) + propshaft_asset(path) + elsif Rails.application.assets.respond_to?(:find_asset) + sprockets_asset(path) + else + nil end + end - def propshaft_asset(path) - (asset = Rails.application.assets.load_path.find(path)) ? PropshaftAsset.new(asset) : nil - end + def propshaft_asset(path) + (asset = Rails.application.assets.load_path.find(path)) ? PropshaftAsset.new(asset) : nil + end - def sprockets_asset(path) - (asset = Rails.application.assets.find_asset(path)) ? SprocketsAsset.new(asset) : nil - end + def sprockets_asset(path) + (asset = Rails.application.assets.find_asset(path)) ? SprocketsAsset.new(asset) : nil end end + end + module AssetsHelper def ferrum_pdf_inline_stylesheet(path) (asset = AssetFinder.find(path)) ? "".html_safe : nil end diff --git a/lib/ferrum_pdf/controller.rb b/lib/ferrum_pdf/controller.rb deleted file mode 100644 index c17b6e3..0000000 --- a/lib/ferrum_pdf/controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -module FerrumPdf - module Controller - extend ActiveSupport::Concern - - def render_pdf(pdf_options: {}, **rendering, &block) - content = render_to_string(**rendering.with_defaults(formats: [ :html ])) - - FerrumPdf.render_pdf( - html: content, - base_url: request.base_url, - pdf_options: pdf_options, - &block - ) - end - - def render_screenshot(screenshot_options: {}, **rendering, &block) - content = render_to_string(**rendering.with_defaults(formats: [ :html ])) - - FerrumPdf.render_screenshot( - html: content, - base_url: request.base_url, - screenshot_options: screenshot_options, - &block - ) - end - end -end diff --git a/lib/ferrum_pdf/railtie.rb b/lib/ferrum_pdf/railtie.rb index 60ba101..ea23bbd 100644 --- a/lib/ferrum_pdf/railtie.rb +++ b/lib/ferrum_pdf/railtie.rb @@ -2,13 +2,29 @@ module FerrumPdf class Railtie < ::Rails::Railtie initializer "ferrum_pdf.assets_helper" do ActiveSupport.on_load(:action_view) do - include FerrumPdf::AssetsHelper if FerrumPdf.include_assets_helper_module + include FerrumPdf::AssetsHelper end end initializer "ferrum_pdf.controller" do ActiveSupport.on_load(:action_controller) do - include FerrumPdf::Controller if FerrumPdf.include_controller_module + # render ferrum_pdf: { pdf options }, template: "whatever", disposition: :inline, filename: "example.pdf" + ActionController.add_renderer :ferrum_pdf do |pdf_options, options| + send_data_options = options.extract!(:disposition, :filename, :status) + url = pdf_options.delete(:url) + html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank? + pdf = FerrumPdf.render_pdf(html: html, base_url: request.base_url, url: url, pdf_options: pdf_options) + send_data(pdf, **send_data_options.with_defaults(type: :pdf)) + end + + # render ferrum_screenshot: { pdf options }, template: "whatever", disposition: :inline, filename: "example.png" + ActionController.add_renderer :ferrum_screenshot do |screenshot_options, options| + send_data_options = options.extract!(:disposition, :filename, :status) + url = screenshot_options.delete(:url) + html = render_to_string(**options.with_defaults(formats: [ :html ])) if url.blank? + screenshot = FerrumPdf.render_screenshot(url: url, html: html, base_url: request.base_url, screenshot_options: screenshot_options) + send_data(screenshot, **send_data_options.with_defaults(type: screenshot_options.fetch(:format, :png))) + end end end end diff --git a/test/dummy/app/controllers/pdfs_controller.rb b/test/dummy/app/controllers/pdfs_controller.rb index a32359f..b0a308b 100644 --- a/test/dummy/app/controllers/pdfs_controller.rb +++ b/test/dummy/app/controllers/pdfs_controller.rb @@ -6,34 +6,22 @@ def show respond_to do |format| format.html format.pdf { - pdf = render_pdf( - layout: "pdf", - pdf_options: { + render ferrum_pdf: { display_header_footer: true, header_template: FerrumPdf::DEFAULT_HEADER_TEMPLATE, footer_template: FerrumPdf::DEFAULT_FOOTER_TEMPLATE - } - ) do |browser, page| - Rails.logger.debug "FerrumPdf Chrome PID: #{browser.process.pid}" - end - send_data pdf, disposition: :inline, filename: "example.pdf" + }, + disposition: :inline, + filename: "example.pdf" } - format.png { send_data render_screenshot, disposition: :inline, filename: "example.png" } + format.png { render ferrum_screenshot: {}, disposition: :inline, filename: "example.png" } end end def url respond_to do |format| - format.pdf { - pdf = FerrumPdf.render_pdf(url: params[:url]) do |browser, page| - Rails.logger.debug "FerrumPdf Chrome PID: #{browser.process.pid}" - end - send_data pdf, disposition: :inline, filename: "example.pdf" - } - format.png { - screenshot = FerrumPdf.render_screenshot(url: params[:url], screenshot_options: { full: params[:full] }) - send_data screenshot, disposition: :inline, filename: "example.png" - } + format.pdf { render ferrum_pdf: { url: params[:url] }, disposition: :inline, filename: "example.pdf" } + format.png { render ferrum_screenshot: { url: params[:url], full: params[:full] }, disposition: :inline, filename: "example.png" } end end end diff --git a/test/dummy/app/views/layouts/pdf.html.erb b/test/dummy/app/views/layouts/pdf.html.erb index b2dded3..8021b17 100644 --- a/test/dummy/app/views/layouts/pdf.html.erb +++ b/test/dummy/app/views/layouts/pdf.html.erb @@ -3,7 +3,7 @@ - <%= content_for(:title) || "Dummy" %> + <%= content_for(:title) || "Dummy" %> PDF <%= stylesheet_link_tag "print" %>