bidi2pdf-rails 0.0.1.alpha.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.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/.gitignore +8 -0
  3. data/.idea/bidi2pdf-rails.iml +449 -0
  4. data/.idea/inspectionProfiles/profiles_settings.xml +5 -0
  5. data/.idea/misc.xml +4 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.rspec +3 -0
  9. data/.rubocop.yml +93 -0
  10. data/.ruby-gemset +1 -0
  11. data/.ruby-version +1 -0
  12. data/MIT-LICENSE +20 -0
  13. data/README.md +102 -0
  14. data/Rakefile +11 -0
  15. data/lib/bidi2pdf-rails.rb +4 -0
  16. data/lib/bidi2pdf_rails/browser_console_log_subscriber.rb +24 -0
  17. data/lib/bidi2pdf_rails/chromedriver_manager_singleton.rb +69 -0
  18. data/lib/bidi2pdf_rails/main_log_subscriber.rb +33 -0
  19. data/lib/bidi2pdf_rails/network_log_subscriber.rb +20 -0
  20. data/lib/bidi2pdf_rails/railtie.rb +44 -0
  21. data/lib/bidi2pdf_rails/services/html_renderer.rb +33 -0
  22. data/lib/bidi2pdf_rails/services/html_to_pdf_converter.rb +28 -0
  23. data/lib/bidi2pdf_rails/services/pdf_browser_session.rb +39 -0
  24. data/lib/bidi2pdf_rails/services/pdf_renderer.rb +81 -0
  25. data/lib/bidi2pdf_rails/services/url_to_pdf_converter.rb +82 -0
  26. data/lib/bidi2pdf_rails/version.rb +3 -0
  27. data/lib/bidi2pdf_rails.rb +141 -0
  28. data/lib/generators/bidi2pdf_rails/USAGE +8 -0
  29. data/lib/generators/bidi2pdf_rails/initializer_generator.rb +74 -0
  30. data/lib/generators/bidi2pdf_rails/templates/bidi2pdf_rails.rb.tt +121 -0
  31. data/spec/bidi2pdf_rails/bidi2pdf_rails_spec.rb +9 -0
  32. data/spec/dummy/Rakefile +6 -0
  33. data/spec/dummy/app/assets/images/img.jpg +0 -0
  34. data/spec/dummy/app/assets/javascripts/paged.polyfill-4.3.js +33251 -0
  35. data/spec/dummy/app/assets/stylesheets/application.css +1 -0
  36. data/spec/dummy/app/assets/stylesheets/pdf.css +121 -0
  37. data/spec/dummy/app/assets/stylesheets/reset.css +449 -0
  38. data/spec/dummy/app/assets/stylesheets/screen.css +281 -0
  39. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  40. data/spec/dummy/app/controllers/reports_controller.rb +12 -0
  41. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  42. data/spec/dummy/app/helpers/reports_helper.rb +2 -0
  43. data/spec/dummy/app/views/layouts/application.html.erb +67 -0
  44. data/spec/dummy/app/views/layouts/pdf.html.erb +67 -0
  45. data/spec/dummy/app/views/pwa/manifest.json.erb +22 -0
  46. data/spec/dummy/app/views/pwa/service-worker.js +26 -0
  47. data/spec/dummy/app/views/reports/show.html.erb +153 -0
  48. data/spec/dummy/bin/rails +4 -0
  49. data/spec/dummy/bin/rake +4 -0
  50. data/spec/dummy/bin/setup +29 -0
  51. data/spec/dummy/config/application.rb +40 -0
  52. data/spec/dummy/config/boot.rb +5 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +57 -0
  55. data/spec/dummy/config/environments/production.rb +73 -0
  56. data/spec/dummy/config/environments/test.rb +51 -0
  57. data/spec/dummy/config/initializers/bidi2pdf_rails.rb +68 -0
  58. data/spec/dummy/config/initializers/content_security_policy.rb +25 -0
  59. data/spec/dummy/config/initializers/cors.rb +9 -0
  60. data/spec/dummy/config/initializers/filter_parameter_logging.rb +8 -0
  61. data/spec/dummy/config/initializers/inflections.rb +16 -0
  62. data/spec/dummy/config/initializers/permissions_policy.rb +13 -0
  63. data/spec/dummy/config/locales/en.yml +31 -0
  64. data/spec/dummy/config/puma.rb +34 -0
  65. data/spec/dummy/config/routes.rb +18 -0
  66. data/spec/dummy/config.ru +6 -0
  67. data/spec/dummy/log/development.log +12781 -0
  68. data/spec/dummy/public/404.html +67 -0
  69. data/spec/dummy/public/406-unsupported-browser.html +66 -0
  70. data/spec/dummy/public/422.html +67 -0
  71. data/spec/dummy/public/500.html +66 -0
  72. data/spec/dummy/public/icon.png +0 -0
  73. data/spec/dummy/public/icon.svg +3 -0
  74. data/spec/dummy/spec/helpers/reports_helper_spec.rb +15 -0
  75. data/spec/dummy/spec/requests/reports_spec.rb +10 -0
  76. data/spec/dummy/spec/views/reports/show.html.erb_spec.rb +5 -0
  77. data/spec/dummy/storage/test.sqlite3 +0 -0
  78. data/spec/dummy/tmp/README.md +69 -0
  79. data/spec/dummy/tmp/local_secret.txt +1 -0
  80. data/spec/dummy/tmp/pids/server.pid +1 -0
  81. data/spec/dummy/tmp/restart.txt +0 -0
  82. data/spec/generator/bidie2pdf_rails_initializer_generator_spec.rb +5 -0
  83. data/spec/generator/initializer_generator_spec.rb +5 -0
  84. data/spec/rails_helper.rb +60 -0
  85. data/spec/requests/reports_spec.rb +17 -0
  86. data/spec/spec_helper.rb +94 -0
  87. data/tasks/bidi2pdf_rails_tasks.rake +4 -0
  88. metadata +310 -0
data/README.md ADDED
@@ -0,0 +1,102 @@
1
+ [![Build Status](https://github.com/dieter-medium/bidi2pdf-rails/actions/workflows/ruby.yml/badge.svg)](https://github.com/dieter-medium/bidi2pdf-rails/blob/main/.github/workflows/ruby.yml)
2
+ [![Maintainability](https://api.codeclimate.com/v1/badges/6425d9893aa3a9ca243e/maintainability)](https://codeclimate.com/github/dieter-medium/bidi2pdf-rails/maintainability)
3
+ [![Gem Version](https://badge.fury.io/rb/bidi2pdf-rails.svg)](https://badge.fury.io/rb/bidi2pdf-rails)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/6425d9893aa3a9ca243e/test_coverage)](https://codeclimate.com/github/dieter-medium/bidi2pdf-rails/test_coverage)
5
+ [![Open Source Helpers](https://www.codetriage.com/dieter-medium/bidi2pdf-rails/badges/users.svg)](https://www.codetriage.com/dieter-medium/bidi2pdf-rails)
6
+
7
+ # 📄 Bidi2pdfRails
8
+
9
+ **Bidi2pdfRails** is the official Rails integration for [Bidi2pdf](https://github.com/dieter-medium/bidi2pdf) – a
10
+ modern, browser-based solution for converting HTML to high-quality PDFs.
11
+ It leverages headless browsing and offers a simple, flexible interface for PDF generation directly from your Rails
12
+ application.
13
+
14
+ > **⚠️ Note:** This project is currently **under development** and **not yet recommended for production use**.
15
+
16
+ ---
17
+
18
+ ## 🚀 Why Bidi2pdfRails?
19
+
20
+ - Utilizes modern browser technologies for accurate rendering (similar to `grover` or `wicked_pdf`)
21
+ - Easy to integrate into existing Rails projects
22
+ - Configurable options: URL, output path, rendering settings
23
+
24
+ ---
25
+
26
+ ## 🔧 Installation
27
+
28
+ Add the following lines to your `Gemfile`:
29
+
30
+ ```ruby
31
+ gem "bidi2pdf-rails"
32
+ # As long as the gem is not published, use:
33
+ gem "bidi2pdf-rails", github: "dieter-medium/bidi2pdf-rails", branch: "main"
34
+ gem "bidi2pdf", github: "dieter-medium/bidi2pdf", branch: "main"
35
+
36
+ # if you want a small performance boost, you can use the following:
37
+ # gem "websocket-native"
38
+ ```
39
+
40
+ Then install the dependencies:
41
+
42
+ ```bash
43
+ bundle
44
+ ```
45
+
46
+ Generate the initializer:
47
+
48
+ ```bash
49
+ bin/rails generate bidi2pdf_rails:initializer
50
+ ```
51
+
52
+ Alternatively, install it manually:
53
+
54
+ ```bash
55
+ gem install bidi2pdf-rails
56
+ ```
57
+
58
+ ---
59
+
60
+ ## 🧪 Example & Getting Started
61
+
62
+ You can find a full example inside the [`spec/dummy`](spec/dummy) directory of this repository.
63
+ This demonstrates how to use `Bidi2pdfRails` in a realistic mini Rails application setup.
64
+
65
+ ### Basic Usage
66
+
67
+ ```ruby
68
+ # Render html via controller action `render_to_string`
69
+ # Any controller action:
70
+ def show
71
+ render pdf: "invoice",
72
+ template: "invoices/show",
73
+ layout: "pdf",
74
+ locals: { invoice: @invoice },
75
+ print_options: { landscape: true },
76
+ wait_for_network_idle: true,
77
+ asset_host: "https://assets.example.com"
78
+ end
79
+
80
+ # Render pdf via direct url call
81
+ def show
82
+ # See: PdfRenderer for all options
83
+ render pdf: 'remote-report', url: "http://example.com", wait_for_page_loaded: false, print_options: { page: { format: :A4 } }
84
+ end
85
+
86
+ ```
87
+
88
+ ---
89
+
90
+ ## 🙌 Contributing
91
+
92
+ Want to contribute?
93
+ Pull requests, bug reports, and ideas are warmly welcome!
94
+
95
+ *Contribution guidelines will be added soon.*
96
+
97
+ ---
98
+
99
+ ## 📄 License
100
+
101
+ This gem is open-source and available under the terms of the [MIT License](https://opensource.org/licenses/MIT).
102
+ Free to use – with responsibility.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/setup"
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ require "rubocop/rake_task"
10
+
11
+ RuboCop::RakeTask.new
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # just to get the nicer gem name
4
+ require_relative "bidi2pdf_rails"
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bidi2pdf/bidi/browser_console_logger"
4
+
5
+ module Bidi2pdfRails
6
+ class BrowserConsoleLogSubscriber < ActiveSupport::LogSubscriber
7
+ def browser_console_log_received(event)
8
+ payload = event.payload
9
+ timestamp = Bidi2pdf::Bidi::BrowserConsoleLogger.format_timestamp(payload[:timestamp])
10
+
11
+ logger.tagged("bidi2pdf_rails", "browser_console", timestamp) do |tagged_logger|
12
+ verbose_logger = Bidi2pdf::VerboseLogger.new(tagged_logger, Bidi2pdfRails.verbosity)
13
+ Bidi2pdf::Bidi::BrowserConsoleLogger.new(verbose_logger)
14
+ .builder
15
+ .with_level(payload[:level])
16
+ .with_prefix("")
17
+ .with_text(payload[:text])
18
+ .with_args(payload[:args])
19
+ .with_stack_trace(payload[:stack_trace])
20
+ .log_event
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module ChromedriverManagerSingleton
5
+ class << self
6
+ attr_reader :manager, :session
7
+
8
+ def initialize_manager
9
+ return unless running_as_server?
10
+
11
+ @mutex ||= Mutex.new
12
+ @mutex.synchronize do
13
+ return if @manager && @session
14
+
15
+ msg = Bidi2pdfRails.remote_browser_url ? "Remote session" : "ChromeDriver manager"
16
+
17
+ Bidi2pdfRails.logger.info "Initializing Bidi2pdf #{msg}"
18
+
19
+ if Bidi2pdfRails.use_remote_browser?
20
+ @session = Bidi::Session.new(
21
+ session_url: Bidi2pdfRails.remote_browser_url,
22
+ headless: Bidi2pdfRails.headless,
23
+ chrome_args: Bidi2pdfRails.chrome_session_args
24
+ )
25
+ else
26
+ @manager = Bidi2pdf::ChromedriverManager.new(
27
+ port: Bidi2pdfRails.chromedriver_port,
28
+ headless: Bidi2pdfRails.headless,
29
+ chrome_args: Bidi2pdfRails.chrome_session_args
30
+ )
31
+ @manager.start
32
+ @session = @manager.session
33
+ end
34
+
35
+ @session.start
36
+ @session.client.on_close { Bidi2pdfRails.logger.info "WebSocket session closed" }
37
+ end
38
+ end
39
+
40
+ def shutdown
41
+ return unless running_as_server?
42
+
43
+ @mutex ||= Mutex.new
44
+ @mutex.synchronize do
45
+ msg = Bidi2pdfRails.remote_browser_url ? "Remote session" : "ChromeDriver manager"
46
+ Bidi2pdfRails.logger.info "Shutting down Bidi2pdf #{msg}"
47
+ @session&.close
48
+ @manager&.stop
49
+ @session = nil
50
+ @manager = nil
51
+ end
52
+ end
53
+
54
+ def running_as_server?
55
+ return false if Rails.const_defined?(:Console)
56
+ return false if defined?(Rails::Generators)
57
+
58
+ return false if File.basename($0) == "rake"
59
+
60
+ # Covers common Rails server entrypoints
61
+ server_commands = %w[server puma unicorn passenger thin webrick rackup]
62
+ cmdline = File.basename($0)
63
+
64
+ server_commands.any? { |s| cmdline.include?(s) } ||
65
+ Rails.const_defined?("Server")
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ class MainLogSubscriber < ActiveSupport::LogSubscriber
5
+ @silenced_events = []
6
+
7
+ class << self
8
+ attr_accessor :silenced_events
9
+
10
+ def silence(event)
11
+ self.silenced_events << event
12
+ end
13
+
14
+ def silenced?(event)
15
+ self.silenced_events.any? { |silenced_event| silenced_event === event }
16
+ end
17
+ end
18
+
19
+ include Bidi2pdf::Notifications::LoggingSubscriberActions
20
+
21
+ def handle_printing(event)
22
+ logger.info "Page rendered and printed: #{event.duration.round(1)}ms"
23
+ end
24
+
25
+ def logger
26
+ Bidi2pdf::VerboseLogger.new(super.tagged("bidi2pdf_rails"), Bidi2pdfRails.verbosity)
27
+ end
28
+
29
+ def silenced?(event)
30
+ MainLogSubscriber.silenced?(event) || super(event)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bidi2pdf/bidi/network_event_formatters/network_event_console_formatter"
4
+
5
+ module Bidi2pdfRails
6
+ class NetworkLogSubscriber < ActiveSupport::LogSubscriber
7
+ def network_event_received(event)
8
+ payload = event.payload
9
+
10
+ return if payload[:method] == "network.responseStarted" || payload[:method] == "network.beforeRequestSent"
11
+
12
+ logger.tagged("bidi2pdf_rails", "network") do |tagged_logger|
13
+ verbose_logger = Bidi2pdf::VerboseLogger.new(tagged_logger, Bidi2pdfRails.verbosity)
14
+ formatter = Bidi2pdf::Bidi::NetworkEventFormatters::NetworkEventConsoleFormatter.new(logger: verbose_logger)
15
+
16
+ formatter.log [payload[:event]]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "services/html_renderer"
4
+ require_relative "services/pdf_renderer"
5
+ require_relative "services/pdf_browser_session"
6
+ require_relative "services/url_to_pdf_converter"
7
+ require_relative "services/html_to_pdf_converter"
8
+
9
+ module Bidi2pdfRails
10
+ class Railtie < ::Rails::Railtie
11
+ initializer "bidi2pdf_rails.add_mime_type" do
12
+ Mime::Type.register "application/pdf", :pdf unless Mime::Type.lookup_by_extension(:pdf)
13
+ end
14
+
15
+ initializer "bidi2pdf_rails.initialize_chromedriver_manager", after: :load_config_initializers do
16
+ Bidi2pdfRails.apply_bidi2pdf_config
17
+
18
+ # defer the initialization of the ChromedriverManager to the ActionController::Base class load event
19
+ ActiveSupport.on_load(:action_controller_base) do
20
+ ChromedriverManagerSingleton.initialize_manager
21
+ end
22
+ end
23
+
24
+ config.after_initialize do
25
+ # Set up shutdown hook for when the application stops
26
+ at_exit do
27
+ ChromedriverManagerSingleton.shutdown
28
+ end
29
+ end
30
+
31
+ initializer "bidi2pdf_rails.add_pdf_renderer" do
32
+ ActionController::Renderers.add :pdf do |filename, options|
33
+ options = options.dup
34
+
35
+ pdf_content = Services::PdfRenderer.new(filename, options, self).render_pdf
36
+
37
+ send_data pdf_content,
38
+ type: Mime[:pdf],
39
+ filename: "#{filename}.pdf",
40
+ disposition: options.fetch(:disposition, "inline")
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module Services
5
+ # app/services/html_renderer.rb
6
+ class HtmlRenderer
7
+ def initialize(controller, options)
8
+ @controller = controller
9
+ @options = options.dup
10
+ end
11
+
12
+ def render
13
+ with_overridden_asset_host { @controller.render_to_string(@options.merge(formats: [:html])) }
14
+ end
15
+
16
+ private
17
+
18
+ def with_overridden_asset_host
19
+ original_asset_host = ActionController::Base.asset_host
20
+
21
+ if @options[:asset_host]
22
+ ActionController::Base.asset_host = @options[:asset_host]
23
+ elsif !Rails.application.config.action_controller.asset_host
24
+ ActionController::Base.asset_host = @controller.request.base_url
25
+ end
26
+
27
+ yield
28
+ ensure
29
+ ActionController::Base.asset_host = original_asset_host
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module Services
5
+ class HtmlToPdfConverter
6
+ include PdfBrowserSession
7
+
8
+ def initialize(html, print_options: {}, wait_for_network_idle: true, wait_for_page_loaded: true, wait_for_page_check_script: nil)
9
+ @html = html
10
+ @print_options = print_options
11
+ @wait_for_network_idle = wait_for_network_idle
12
+ @wait_for_page_loaded = wait_for_page_loaded
13
+ @wait_for_page_check_script = wait_for_page_check_script
14
+ end
15
+
16
+ def generate
17
+ run_browser_session
18
+ end
19
+
20
+ private
21
+
22
+ def prepare_tab(tab)
23
+ tab.render_html_content(@html)
24
+ wait_for_tab(tab)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module Services
5
+ module PdfBrowserSession
6
+ def run_browser_session
7
+ pdf_data = nil
8
+
9
+ thread = Thread.new do
10
+ Rails.application.executor.wrap do
11
+ browser = ChromedriverManagerSingleton.session.browser
12
+ context = browser.create_user_context
13
+ window = context.create_browser_window
14
+ tab = window.create_browser_tab
15
+
16
+ begin
17
+ prepare_tab(tab)
18
+ pdf_data = tab.print(print_options: @print_options)
19
+ ensure
20
+ tab&.close
21
+ window&.close
22
+ context&.close
23
+ end
24
+ end
25
+ end
26
+
27
+ thread.join
28
+ Base64.decode64(pdf_data)
29
+ end
30
+
31
+ private
32
+
33
+ def wait_for_tab(tab)
34
+ tab.wait_until_network_idle if @wait_for_network_idle
35
+ tab.wait_until_page_loaded(check_script: @wait_for_page_check_script) if @wait_for_page_loaded
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module Services
5
+ # PdfRenderer is responsible for rendering a Rails view into a PDF using headless Chrome.
6
+ #
7
+ # It accepts a mix of HTML rendering options (passed to `render_to_string`) and PDF generation options.
8
+ #
9
+ # @example Basic usage
10
+ # renderer = Bidi2pdfRails::Services::PdfRenderer.new("invoice", { template: "invoices/show" }, controller)
11
+ # renderer.render_pdf
12
+ #
13
+ # @param filename [String] the base filename for the generated PDF (used for download naming)
14
+ # @param options [Hash] rendering options including both HTML and PDF-specific options
15
+ # @option options [String] :template The template to render (or other render_to_string keys like :partial, :layout, etc.)
16
+ # @option options [String] :asset_host Optional asset host override
17
+ # @option options [Hash] :print_options Options passed to the Chrome PDF print API
18
+ # @option options [Boolean] :wait_for_network_idle Wait for network to go idle before generating PDF (default: config default)
19
+ # @option options [Boolean] :wait_for_page_loaded Wait for page load event before generating PDF (default: config default)
20
+ # @option options [String] :wait_for_page_check_script JavaScript condition to wait for before generating PDF
21
+ #
22
+ class PdfRenderer
23
+ PDF_OPTIONS = %i[
24
+ print_options
25
+ asset_host
26
+ wait_for_network_idle
27
+ wait_for_page_loaded
28
+ wait_for_page_check_script
29
+ ].freeze
30
+
31
+ PRINT_URL_OPTIONS = %i[
32
+ url
33
+ auth
34
+ headers
35
+ cookies
36
+ ].freeze
37
+
38
+ def initialize(filename, options, controller)
39
+ @filename = filename
40
+ @pdf_options = options.slice(*PDF_OPTIONS)
41
+ @print_url_options = options.slice(*PRINT_URL_OPTIONS)
42
+ @html_options = options.except(*(PDF_OPTIONS + PRINT_URL_OPTIONS))
43
+ @controller = controller
44
+ end
45
+
46
+ def render_pdf
47
+ ActiveSupport::Notifications.instrument("handle_printing.bidi2pdf_rails") do
48
+ print_options = Bidi2pdfRails.print_options(@pdf_options[:print_options] || {})
49
+ wait_for_network_idle = @pdf_options.fetch(:wait_for_network_idle, Bidi2pdfRails.wait_for_network_idle)
50
+ wait_for_page_loaded = @pdf_options.fetch(:wait_for_page_loaded, Bidi2pdfRails.wait_for_page_loaded)
51
+ wait_for_page_check_script = @pdf_options.fetch(:wait_for_page_check_script, Bidi2pdfRails.wait_for_page_check_script)
52
+
53
+ if @print_url_options[:url]
54
+ headers = @print_url_options[:headers] || Bidi2pdfRails.headers
55
+ cookies = @print_url_options[:cookies] || Bidi2pdfRails.cookies
56
+ auth = @print_url_options[:auth] || Bidi2pdfRails.auth
57
+
58
+ UrlToPdfConverter.new(@print_url_options[:url],
59
+ headers: headers,
60
+ cookies: cookies,
61
+ auth: auth,
62
+ print_options: print_options,
63
+ wait_for_network_idle: wait_for_network_idle,
64
+ wait_for_page_loaded: wait_for_page_loaded,
65
+ wait_for_page_check_script: wait_for_page_check_script
66
+ ).generate
67
+ else
68
+ html = HtmlRenderer.new(@controller, @html_options).render
69
+
70
+ HtmlToPdfConverter.new(html,
71
+ print_options: print_options,
72
+ wait_for_network_idle: wait_for_network_idle,
73
+ wait_for_page_loaded: wait_for_page_loaded,
74
+ wait_for_page_check_script: wait_for_page_check_script
75
+ ).generate
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bidi2pdfRails
4
+ module Services
5
+ class UrlToPdfConverter
6
+ include PdfBrowserSession
7
+
8
+ def initialize(url, headers: {}, cookies: {}, auth: {}, print_options: {}, wait_for_network_idle: true, wait_for_page_loaded: true, wait_for_page_check_script: nil)
9
+ @url = url
10
+ @headers = headers || {}
11
+ @cookies = cookies || {}
12
+ @auth = auth || {}
13
+ @print_options = print_options
14
+ @wait_for_network_idle = wait_for_network_idle
15
+ @wait_for_page_loaded = wait_for_page_loaded
16
+ @wait_for_page_check_script = wait_for_page_check_script
17
+ end
18
+
19
+ def generate
20
+ run_browser_session
21
+ end
22
+
23
+ private
24
+
25
+ def prepare_tab(tab)
26
+ add_headers(tab)
27
+ add_basic_auth(tab)
28
+ add_cookies(tab)
29
+
30
+ tab.navigate_to(@url)
31
+ wait_for_tab(tab)
32
+ end
33
+
34
+ def add_cookies(tab)
35
+ @cookies.each do |name, value|
36
+ tab.set_cookie(
37
+ name: name,
38
+ value: value,
39
+ domain: domain,
40
+ secure: uri.scheme == "https"
41
+ )
42
+ end
43
+ end
44
+
45
+ def add_headers(tab)
46
+ @headers.each do |name, value|
47
+ tab.add_headers(
48
+ url_patterns: url_patterns,
49
+ headers: [{ name: name, value: value }]
50
+ )
51
+ end
52
+ end
53
+
54
+ def add_basic_auth(tab)
55
+ return unless @auth[:username] && @auth[:password]
56
+
57
+ tab.basic_auth(
58
+ url_patterns: url_patterns,
59
+ username: @auth[:username],
60
+ password: @auth[:password]
61
+ )
62
+ end
63
+
64
+ def uri
65
+ @uri ||= URI(@url)
66
+ end
67
+
68
+ def domain
69
+ uri.host
70
+ end
71
+
72
+ def url_patterns
73
+ [{
74
+ type: "pattern",
75
+ protocol: uri.scheme,
76
+ hostname: uri.host,
77
+ port: uri.port.to_s
78
+ }]
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ module Bidi2pdfRails
2
+ VERSION = "0.0.1.alpha.1"
3
+ end