Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Separate classes for configuration and node script invocation logic #54

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/Dhalang.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module Dhalang
require_relative 'Dhalang/url_utils'
require_relative 'Dhalang/file_utils'
require_relative 'Dhalang/error'
require_relative 'Dhalang/puppeteer'
require_relative 'Dhalang/configuration'
require_relative 'Dhalang/node_script_invoker'
require 'uri'
require 'tempfile'
require 'shellwords'
Expand Down
87 changes: 87 additions & 0 deletions lib/Dhalang/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
module Dhalang
# Groups Puppeteer and Dhalang configuration.
class Configuration
NODE_MODULES_PATH = Dir.pwd + '/node_modules/'.freeze
USER_OPTIONS = {
navigationTimeout: 10000,
printToPDFTimeout: 0, # unlimited
navigationWaitUntil: 'load',
navigationWaitForSelector: '',
navigationWaitForXPath: '',
userAgent: '',
isHeadless: true,
viewPort: '',
httpAuthenticationCredentials: '',
isAutoHeight: false,
chromeOptions: []
}.freeze
DEFAULT_PDF_OPTIONS = {
scale: 1,
displayHeaderFooter: false,
headerTemplate: '',
footerTemplate: '',
headerTemplateFile: '',
footerTemplateFile: '',
printBackground: true,
landscape: false,
pageRanges: '',
format: 'A4',
width: '',
height: '',
margin: { top: 36, right: 36, bottom: 20, left: 36 },
preferCSSPageSize: true,
omitBackground: false
}.freeze
DEFAULT_SCREENSHOT_OPTIONS = {
fullPage: true,
clip: nil,
omitBackground: false
}.freeze
DEFAULT_JPEG_OPTIONS = {
quality: 100
}.freeze

private_constant :NODE_MODULES_PATH
private_constant :USER_OPTIONS
private_constant :DEFAULT_PDF_OPTIONS
private_constant :DEFAULT_SCREENSHOT_OPTIONS
private_constant :DEFAULT_JPEG_OPTIONS

private attr_accessor :page_url
private attr_accessor :temp_file_path
private attr_accessor :temp_file_extension
private attr_accessor :user_options
private attr_accessor :pdf_options
private attr_accessor :screenshot_options
private attr_accessor :jpeg_options

# @param [Hash] custom_options Changes that override default.
# @param [String] page_url Url for Puppeteer to visit.
# @param [String] temp_file_path Absolute path of temp file to use for writing script results.
# Can be nil for scripts using stdout.
# @param [String] temp_file_extension Extension of temp file. Can be nil for scripts using stdout.
def initialize(custom_options, page_url, temp_file_path = nil, temp_file_extension = nil)
self.page_url = page_url
self.temp_file_path = temp_file_path
self.temp_file_extension = temp_file_extension
self.user_options = USER_OPTIONS.map { |key, default_value| [key, custom_options.fetch(key, default_value)] }
self.pdf_options = DEFAULT_PDF_OPTIONS.map { |key, default_value| [key, custom_options.fetch(key, default_value)] }
self.screenshot_options = DEFAULT_SCREENSHOT_OPTIONS.map { |key, default_value| [key, custom_options.fetch(key, default_value)] }
self.jpeg_options = DEFAULT_JPEG_OPTIONS.map { |key, default_value| [key, custom_options.fetch(key, default_value)] }
end

# Returns configuration as JSON string.
def json
return {
webPageUrl: page_url,
tempFilePath: temp_file_path,
puppeteerPath: NODE_MODULES_PATH,
imageType: temp_file_extension,
userOptions: user_options.to_h,
pdfOptions: pdf_options.to_h,
screenshotOptions: screenshot_options.to_h,
jpegOptions: jpeg_options.to_h
}.to_json
end
end
end
28 changes: 28 additions & 0 deletions lib/Dhalang/node_script_invoker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Dhalang
class NodeScriptInvoker

# Executes JS script under given script_path by launching a new Node process.
#
# @param [String] script_path Absolute path of JS script to execute.
# @param [Configuration] configuration Configuration to use.
def self.execute_script(script_path, configuration)
command = create_node_command(script_path, configuration)
Open3.popen2e(command) do |_stdin, stdouterr, wait|
return nil if wait.value.success?

output = stdouterr.read.strip
output = nil if output == ''
message = output || "Exited with status #{wait.value.exitstatus}"
raise DhalangError, message
end
end

# Returns a [String] with node command that invokes the provided script with the configuration.
#
# @param [String] script_path Absolute path of JS script to invoke.
# @param [Configuration] configuration Configuration to use.
private_class_method def self.create_node_command(script_path, configuration)
"node #{script_path} #{Shellwords.escape(configuration.json)}"
end
end
end
97 changes: 0 additions & 97 deletions lib/Dhalang/puppeteer.rb

This file was deleted.

7 changes: 4 additions & 3 deletions lib/PDF.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module Dhalang
# Allows consumers of this library to create PDFs with Puppeteer.
class PDF
PUPPETEER_SCRIPT_PATH = File.expand_path('../js/pdf-generator.js', __FILE__).freeze
private_constant :PUPPETEER_SCRIPT_PATH
SCRIPT_PATH = File.expand_path('../js/pdf-generator.js', __FILE__).freeze
private_constant :SCRIPT_PATH

# Captures the full webpage under the given url as PDF.
#
Expand Down Expand Up @@ -43,7 +43,8 @@ def self.get_from_html(html, options = {})
private_class_method def self.get(url, options)
temp_file = FileUtils.create_temp_file("pdf")
begin
Puppeteer.visit(url, PUPPETEER_SCRIPT_PATH, temp_file.path, "pdf", options)
configuration = Configuration.new(options, url, temp_file.path, "pdf")
NodeScriptInvoker.execute_script(SCRIPT_PATH, configuration)
binary_pdf_content = FileUtils.read_binary(temp_file.path)
ensure
FileUtils.delete(temp_file)
Expand Down
7 changes: 4 additions & 3 deletions lib/Screenshot.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
module Dhalang
# Allows consumers of this library to take screenshots with Puppeteer.
class Screenshot
PUPPETEER_SCRIPT_PATH = File.expand_path('../js/screenshot-generator.js', __FILE__).freeze
SCRIPT_PATH = File.expand_path('../js/screenshot-generator.js', __FILE__).freeze
IMAGE_TYPES = [:jpeg, :png, :webp].freeze
private_constant :PUPPETEER_SCRIPT_PATH
private_constant :SCRIPT_PATH
private_constant :IMAGE_TYPES

# <b>DEPRECATED:</b> Please use `get_from_url(url, :jpeg)` instead.
Expand Down Expand Up @@ -44,7 +44,8 @@ def self.get_from_url(url, image_type, options = {})

temp_file = FileUtils.create_temp_file(image_type)
begin
Puppeteer.visit(url, PUPPETEER_SCRIPT_PATH, temp_file.path, image_type, options)
configuration = Configuration.new(options, url, temp_file.path, image_type)
NodeScriptInvoker.execute_script(SCRIPT_PATH, configuration)
binary_image_content = FileUtils.read_binary(temp_file.path)
ensure
FileUtils.delete(temp_file)
Expand Down