Class: Palapala::Pdf

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

Overview

Page class to generate PDF from HTML content using Chrome in headless mode in a thread-safe way

Instance Method Summary collapse

Constructor Details

#initialize(content, footer_template: nil, footer: nil, generate_tagged_pdf: nil, header_template: nil, header: nil, landscape: nil, margin_bottom: nil, margin_left: nil, margin_right: nil, margin_top: nil, page_ranges: nil, paper_height: nil, paper_width: nil, prefer_css_page_size: nil, print_background: nil, scale: nil, watermark: nil) ⇒ Pdf

Initialize the PDF object with the HTML content and optional parameters.

The options are passed to the renderer when generating the PDF. The options are the snakified version of the options from the Chrome DevTools Protocol to respect the Ruby conventions. (see chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF)

Parameters:

  • content (String)

    the HTML content to convert to PDF

  • footer_html (String)

    the HTML content for the footer

  • footer (String) (defaults to: nil)

    the footer content that is centered

  • generate_tagged_pdf (Boolean) (defaults to: nil)

    whether to generate a tagged PDF

  • header_html (String)

    the HTML content for the header

  • header (String) (defaults to: nil)

    the header content that is centered

  • landscape (Boolean) (defaults to: nil)

    whether to use landscape orientation

  • margin_bottom (Integer) (defaults to: nil)

    the bottom margin in inches

  • margin_left (Integer) (defaults to: nil)

    the left margin in inches

  • margin_right (Integer) (defaults to: nil)

    the right margin in inches

  • margin_top (Integer) (defaults to: nil)

    the top margin in inches

  • page_ranges (String) (defaults to: nil)

    the page ranges to print, e.g., “1-3, 5, 7-9”

  • paper_height (Integer) (defaults to: nil)

    the paper height in inches

  • paper_width (Integer) (defaults to: nil)

    the paper width in inches

  • prefer_css_page_size (Boolean) (defaults to: nil)

    whether to prefer CSS page size (advised)

  • print_background (Boolean) (defaults to: nil)

    whether to print background graphics

  • scale (Float) (defaults to: nil)

    the scale of the PDF rendering

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/palapala/pdf.rb', line 32

def initialize(content,
               footer_template: nil,
               footer: nil,
               generate_tagged_pdf: nil,
               header_template: nil,
               header: nil,
               landscape: nil,
               margin_bottom: nil,
               margin_left: nil,
               margin_right: nil,
               margin_top: nil,
               page_ranges: nil,
               paper_height: nil,
               paper_width: nil,
               prefer_css_page_size: nil,
               print_background: nil,
               scale: nil,
               watermark: nil)
  @content = content || raise(ArgumentError, "Content is required and can't be nil")
  @opts = {}
  raise(ArgumentError, "Either footer or footer_template is expected") if !footer_template.nil? && !footer.nil?
  raise(ArgumentError, "Either header or header_template is expected") if !header_template.nil? && !header.nil?
  @opts[:headerTemplate]      = header_template      || Helper.hf_template(from: header) || Palapala.defaults[:header_template]
  @opts[:footerTemplate]      = footer_template      || Helper.hf_template(from: footer) || Palapala.defaults[:footer_template]
  @opts[:pageRanges]          = page_ranges          || Palapala.defaults[:page_ranges]
  @opts[:generateTaggedPDF]   = generate_tagged_pdf  || Palapala.defaults[:generate_tagged_pdf]
  @opts[:paperWidth]          = paper_width          || Palapala.defaults[:paper_width]
  @opts[:paperHeight]         = paper_height         || Palapala.defaults[:paper_height]
  @opts[:landscape]           = landscape            || Palapala.defaults[:landscape]
  @opts[:marginTop]           = margin_top           || Palapala.defaults[:margin_top]
  @opts[:marginLeft]          = margin_left          || Palapala.defaults[:margin_left]
  @opts[:marginBottom]        = margin_bottom        || Palapala.defaults[:margin_bottom]
  @opts[:marginRight]         = margin_right         || Palapala.defaults[:margin_right]
  @opts[:preferCSSPageSize]   = prefer_css_page_size || Palapala.defaults[:prefer_css_page_size]
  @opts[:printBackground]     = print_background     || Palapala.defaults[:print_background]
  @opts[:scale]               = scale                || Palapala.defaults[:scale]
  @opts[:headerTemplate]      = (@opts[:headerTemplate].to_s + Helper.watermark(watermark)) if watermark
  @opts[:displayHeaderFooter] = (@opts[:headerTemplate] || @opts[:footerTemplate]) ? true : false
  @opts[:headerTemplate]    ||= " " if @opts[:displayHeaderFooter]
  @opts[:footerTemplate]    ||= " " if @opts[:displayHeaderFooter]
  @opts[:encoding]            = :binary
  @opts.compact!
end

Instance Method Details

#binary_data(title: "", author: "", subject: "", producer: "PalapalaPDF", creator: "PalapalaPDF", skip_metadata: false) ⇒ String

Render the PDF content to a binary string.

The params from the initializer are converted to the expected casing and merged with the options passed to this method. The options passed here are passed unchanged to the renderer and get priority over the options from the initializer. Chrome DevTools Protocol expects the options to be camelCase, see chromedevtools.github.io/devtools-protocol/tot/Page/#method-printToPDF.

Parameters:

  • opts (Hash)

    the options to pass to the renderer

Returns:

  • (String)

    the PDF content as a binary string



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/palapala/pdf.rb', line 84

def binary_data(title: "", author: "", subject: "", producer: "PalapalaPDF", creator: "PalapalaPDF", skip_metadata: false)
  puts "Rendering PDF with params: #{@opts}" if Palapala.debug
  binary_data = Renderer.html_to_pdf(@content, params: @opts)

  if 
    binary_data
  else
    # Load the PDF from the string
    pdf = CombinePDF.parse(binary_data)

    # Set metadata manually
    info_hash = {
      Title: title,
      Author: author,
      Subject: subject,
      Producer: producer,
      Creator: creator
    }

    # Embed metadata into the PDF
    pdf.info.merge!(info_hash)
    pdf.to_pdf
  end
rescue StandardError => e
  puts "Error rendering PDF: #{e.message}"
  Renderer.reset
  raise
end

#save(path, **opts) ⇒ void

This method returns an undefined value.

Save the PDF content to a file

Parameters:

  • path (String)

    the path to save the PDF file



116
117
118
# File 'lib/palapala/pdf.rb', line 116

def save(path, **opts)
  File.binwrite(path, binary_data(**opts))
end