Class: Palapala::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/palapala/renderer.rb

Overview

Render HTML content to PDF using Chrome in headless mode with minimal dependencies

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRenderer

Returns a new instance of Renderer.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/palapala/renderer.rb', line 10

def initialize
  puts "Initializing a renderer" if Palapala.debug
  # Create an instance of WebSocketClient with the WebSocket URL
  @client = Palapala::WebSocketClient.new(websocket_url)
  # Create the WebSocket driver
  @driver = WebSocket::Driver.client(@client)
  # Register the on_message callback
  @driver.on(:message, &method(:on_message))
  @driver.on(:close) { Thread.current[:renderer] = nil } # Reset the renderer on close
  # Start the WebSocket handshake
  @driver.start
  # Initialize the protocol to get the page events
  send_command_and_wait_for_result("Page.enable")
end

Class Method Details

.html_to_pdf(html, params: {}) ⇒ Object



96
97
98
# File 'lib/palapala/renderer.rb', line 96

def self.html_to_pdf(html, params: {})
  thread_local_instance.html_to_pdf(html, params: params)
end

.resetObject

Reset the thread-local instance of the renderer



31
32
33
34
# File 'lib/palapala/renderer.rb', line 31

def self.reset
  puts "Clearing the thread local renderer" if Palapala.debug
  Thread.current[:renderer] = nil
end

.thread_local_instanceObject

Create a thread-local instance of the renderer



26
27
28
# File 'lib/palapala/renderer.rb', line 26

def self.thread_local_instance
  Thread.current[:renderer] ||= Renderer.new
end

Instance Method Details

#closeObject



100
101
102
103
# File 'lib/palapala/renderer.rb', line 100

def close
  @driver.close
  @client.close
end

#current_idObject

Get the current ID



46
# File 'lib/palapala/renderer.rb', line 46

def current_id = @id

#html_to_pdf(html, params: {}) ⇒ Object

Parameters:

  • html (String)

    The HTML content to convert to PDF

  • params (Hash) (defaults to: {})

    Additional parameters to pass to the CDP command



89
90
91
92
93
94
# File 'lib/palapala/renderer.rb', line 89

def html_to_pdf(html, params: {})
  send_command_and_wait_for_event("Page.navigate", params: { url: data_url_for_html(html) },
                                                   event_name: "Page.frameStoppedLoading")
  result = send_command_and_wait_for_result("Page.printToPDF", params:)
  Base64.decode64(result["data"])
end

#next_idObject

Update the current ID to the next ID (increment by 1)



43
# File 'lib/palapala/renderer.rb', line 43

def next_id = @id = (@id || 0) + 1

#on_message(e) ⇒ Object

Callback to handle the incomming WebSocket messages



37
38
39
40
# File 'lib/palapala/renderer.rb', line 37

def on_message(e)
  puts "Received: #{e.data[0..64]}" if Palapala.debug
  @response = JSON.parse(e.data) # Parse the JSON response
end

#process_until(&block) ⇒ Object

Process the WebSocket messages until some state is true



49
50
51
52
53
54
55
# File 'lib/palapala/renderer.rb', line 49

def process_until(&block)
  loop do
    @driver.parse(@client.read)
    return if block.call
    return if @driver.state == :closed
  end
end

#send_and_wait(message) ⇒ Object

Method to send a message (text) and wait for a response



58
59
60
61
62
# File 'lib/palapala/renderer.rb', line 58

def send_and_wait(message, &)
  puts "\nSending: #{message}" if Palapala.debug
  @driver.text(message)
  process_until(&)
end

#send_command(method, params: {}, &block) ⇒ Object

Method to send a CDP command and wait for some state to be true



65
66
67
# File 'lib/palapala/renderer.rb', line 65

def send_command(method, params: {}, &block)
  send_and_wait(JSON.generate({ id: next_id, method:, params: }), &block)
end

#send_command_and_wait_for_event(method, event_name:, params: {}) ⇒ Object

Method to send a CDP command and wait for a specific method to be called



79
80
81
82
83
# File 'lib/palapala/renderer.rb', line 79

def send_command_and_wait_for_event(method, event_name:, params: {})
  send_command(method, params:) do
    @response && @response["method"] == event_name
  end
end

#send_command_and_wait_for_result(method, params: {}) ⇒ Hash

Method to send a CDP command and wait for the matching event to get the result

Returns:

  • (Hash)

    The result of the command



71
72
73
74
75
76
# File 'lib/palapala/renderer.rb', line 71

def send_command_and_wait_for_result(method, params: {})
  send_command(method, params:) do
    @response && @response["id"] == current_id
  end
  @response["result"]
end