palapala_pdf 0.1.19 → 0.1.22
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/README.md +30 -13
- data/examples/headers_and_footers.pdf +0 -0
- data/examples/js_based_rendering.pdf +0 -0
- data/examples/paged_css.pdf +0 -0
- data/examples/paged_css.rb +1 -1
- data/lib/palapala/chrome_process.rb +2 -2
- data/lib/palapala/helper.rb +7 -6
- data/lib/palapala/pdf.rb +25 -5
- data/lib/palapala/renderer.rb +2 -0
- data/lib/palapala/version.rb +1 -1
- data/palapala_pdf.gemspec +1 -0
- metadata +17 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b471a19225248fbf5121f553fa2f1c8c5556f7e961f9a8e96364c7ba7b7511c3
|
4
|
+
data.tar.gz: 6b340702049072a2ceef8b5f31c6ca326a3522981da740764315611ccdb7182c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5873dac0c8e9609da55a3d370ae3a5963d6817687c7d4df0627c175447ffce7003c9296ea341753130eb67804b8acca1ab19866bed5613537f14ed1272252e99
|
7
|
+
data.tar.gz: 39b09919a14b86dde183af046dedb62e80c69fb639e77065ed17caae1bdaa4d638ef47f531d6f697c7de410c2b747b0782c795a8b0088e3ef99f1d61f6122788
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.4.1
|
data/README.md
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
# PDF Generation for your Rubies
|
1
|
+
# PDF Generation for your Rails and Rubies
|
2
2
|
|
3
3
|
<div align="center"><img src="https://raw.githubusercontent.com/palapala-app/palapala_pdf/main/assets/images/logo.webp" alt="Palapala PDF Logo" width="200"></div>
|
4
4
|
|
5
|
-
This project is a Ruby gem that
|
5
|
+
This project is a Ruby gem that generates PDF files from HTML using the Chrome browser engine, making it convenient for tasks such as generating reports, invoices, or any other printable documents.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
It leverages work from [Puppeteer](https://pptr.dev/browsers-api/) (@puppeteer/browsers) to install a local Chrome-Headless-Shell if no Chrome is running, but that requires node (npx) to be available.
|
7
|
+
On Heroku you just need to install a buildpack for Chrome and the rest is auto-configured.
|
10
8
|
|
11
9
|
This is how easy PDF generation can be in Ruby:
|
12
10
|
|
@@ -14,12 +12,15 @@ This is how easy PDF generation can be in Ruby:
|
|
14
12
|
require "palapala"
|
15
13
|
Palapala::Pdf.new("<h1>Hello, world! #{Time.now}</h1>").save('hello.pdf')
|
16
14
|
```
|
15
|
+
|
17
16
|
And this while having the most modern HTML/CSS/JS availlable to you: flex, grid, canvas, ...
|
18
17
|
|
19
18
|
A core goal of this project is performance, and it is designed to be exceptionally fast. By leveraging **direct communication** with a headless Chrome or Chromium browser via a **raw web socket**, the gem minimizes overhead and dependencies, enabling PDF generation at speeds that significantly outperform other solutions. Whether generating simple or complex documents, this gem ensures that your Ruby applications can handle PDF tasks efficiently and at scale.
|
20
19
|
|
21
20
|
[Example: paged_css.pdf](https://raw.githubusercontent.com/palapala-app/palapala_pdf/main/examples/paged_css.pdf)
|
22
21
|
|
22
|
+
It leverages work from [Puppeteer](https://pptr.dev/browsers-api/) (@puppeteer/browsers) to install a local Chrome-Headless-Shell if no Chrome is running (requires node/npx to be available).
|
23
|
+
|
23
24
|
## Sponsor This Project
|
24
25
|
|
25
26
|
If you find this project useful and would like to support its development, consider sponsoring or buying a coffee to help keep it going:
|
@@ -33,8 +34,8 @@ Your support is greatly appreciated and helps maintain the project!
|
|
33
34
|
|
34
35
|
To install the gem and add it to your application's Gemfile, execute the following command:
|
35
36
|
|
36
|
-
```
|
37
|
-
|
37
|
+
```sh
|
38
|
+
bundle add palapala_pdf
|
38
39
|
```
|
39
40
|
|
40
41
|
## Usage Instructions
|
@@ -179,13 +180,29 @@ Here's an example of how to use `render_to_string` to render a view template to
|
|
179
180
|
```ruby
|
180
181
|
def download_pdf
|
181
182
|
html_string = render_to_string(template: "example/template", layout: "print", locals: { } )
|
182
|
-
pdf_data = Palapala::Pdf.new(html_string).binary_data
|
183
|
+
pdf_data = Palapala::Pdf.new(html_string).binary_data(skip_metadata: true)
|
183
184
|
send_data pdf_data, filename: "document.pdf", type: "application/pdf"
|
184
185
|
end
|
185
186
|
```
|
186
187
|
|
187
188
|
In this example, `pdf_data` is the binary data of the PDF file. The `filename` option specifies the name of the file that will be downloaded by the user, and the `type` option specifies the MIME type of the file.
|
188
189
|
|
190
|
+
In the below example we generate a PDF with metadata:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
def download_pdf
|
194
|
+
html_string = render_to_string(template: "example/template", layout: "print", locals: { } )
|
195
|
+
pdf_data = Palapala::Pdf.new(html_string).binary_data(
|
196
|
+
title: "Hello World from Palapala",
|
197
|
+
author: "Example User",
|
198
|
+
subject: "Sample Document",
|
199
|
+
producer: "Some Company",
|
200
|
+
creator: "PalapalaPDF"
|
201
|
+
)
|
202
|
+
send_data pdf_data, filename: "document.pdf", type: "application/pdf"
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
189
206
|
## Docker
|
190
207
|
|
191
208
|
TODO
|
@@ -229,22 +246,22 @@ TODO
|
|
229
246
|
This buildpack installs chrome and chromedriver (chromedriver is actually not needed, but at least the buildpack is maintained)
|
230
247
|
|
231
248
|
```sh
|
232
|
-
https://
|
249
|
+
https://github.com/heroku/heroku-buildpack-chrome-for-testing
|
233
250
|
```
|
234
251
|
|
235
252
|
### launch as child process
|
236
253
|
|
237
|
-
set `HEADLESS_CHROME_PATH=chrome` as an ENV variable as
|
254
|
+
This is the current default. If HEROKU is detected, then we set `HEADLESS_CHROME_PATH=chrome` as an ENV variable as the above buildpack adds `chrome` to the path. Basically it should run out of the box as long as the buildpack is added.
|
238
255
|
|
239
256
|
### run seperately
|
240
257
|
|
241
|
-
|
258
|
+
If you prefer to run it next to your Rails app, then in your `Procfile` adjust the web worker command to
|
242
259
|
|
243
260
|
```yaml
|
244
261
|
web: bin/start
|
245
262
|
```
|
246
263
|
|
247
|
-
|
264
|
+
And create a bin/start script
|
248
265
|
|
249
266
|
```sh
|
250
267
|
#!/bin/bash
|
@@ -258,7 +275,7 @@ command_to_start_your_background_app &
|
|
258
275
|
wait -n
|
259
276
|
```
|
260
277
|
|
261
|
-
|
278
|
+
Ensure the script is executable
|
262
279
|
|
263
280
|
```sh
|
264
281
|
chmod +x bin/start
|
Binary file
|
Binary file
|
data/examples/paged_css.pdf
CHANGED
Binary file
|
data/examples/paged_css.rb
CHANGED
@@ -82,7 +82,7 @@ module Palapala
|
|
82
82
|
# Display the version
|
83
83
|
system("#{chrome_path} --version") if Palapala.debug
|
84
84
|
# Launch chrome-headless-shell with the --remote-debugging-port parameter
|
85
|
-
params = [ "--disable-gpu", "--remote-debugging-port=9222", "--remote-debugging-address=0.0.0.0" ]
|
85
|
+
params = [ "--disable-gpu", "--disable-software-rasterizer", "--disable-bluetooth", "--disable-dev-shm-usage", "--remote-debugging-port=9222", "--remote-debugging-address=0.0.0.0" ]
|
86
86
|
params.concat(Palapala.chrome_params) if Palapala.chrome_params
|
87
87
|
pid = if Palapala.debug
|
88
88
|
spawn(chrome_path, *params)
|
@@ -97,7 +97,7 @@ module Palapala
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def self.spawn_chrome_from_path
|
100
|
-
params = [ "--headless", "--disable-gpu", "--remote-debugging-port=9222" ]
|
100
|
+
params = [ "--headless", "--disable-gpu", "--disable-software-rasterizer", "--disable-bluetooth", "--disable-dev-shm-usage", "--remote-debugging-port=9222", "--remote-debugging-address=0.0.0.0" ]
|
101
101
|
params.concat(Palapala.chrome_params) if Palapala.chrome_params
|
102
102
|
# Spawn an existing chrome with the path and parameters
|
103
103
|
Process.spawn(chrome_path, *params)
|
data/lib/palapala/helper.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Palapala
|
2
2
|
module Helper
|
3
|
-
def self.header(left: "", center: "", right: "", margin: "1cm")
|
3
|
+
def self.header(left: "", center: "", right: "", margin: "1cm", font_family: "Arial")
|
4
4
|
<<~HTML
|
5
|
-
<div style="display: flex; justify-content: space-between; width: 100%; margin-left: #{margin}; margin-right: #{margin};">
|
5
|
+
<div style="display: flex; justify-content: space-between; width: 100%; margin-left: #{margin}; margin-right: #{margin}; font-family: #{font_family}">
|
6
6
|
<div style="text-align: left; flex: 1;">#{left}</div>
|
7
7
|
<div style="text-align: center; flex: 1;">#{center}</div>
|
8
8
|
<div style="text-align: right; flex: 1;">#{right}</div>
|
@@ -10,13 +10,14 @@ module Palapala
|
|
10
10
|
HTML
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.footer(left: "", center: "", right: "", margin: "1cm")
|
14
|
-
self.header(left:, center:, right:, margin:)
|
13
|
+
def self.footer(left: "", center: "", right: "", margin: "1cm", font_family: "Arial")
|
14
|
+
self.header(left:, center:, right:, margin:, font_family:)
|
15
15
|
end
|
16
16
|
|
17
|
-
def self.page_number
|
17
|
+
def self.page_number(style: nil)
|
18
|
+
style_attr = style.nil? ? "" : "style='#{style}'"
|
18
19
|
<<~HTML
|
19
|
-
<span class="pageNumber"></span>/<span class="totalPages"></span>
|
20
|
+
<span class="pageNumber" #{style_attr}></span>/<span class="totalPages"></span>
|
20
21
|
HTML
|
21
22
|
end
|
22
23
|
|
data/lib/palapala/pdf.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_relative "./renderer"
|
2
2
|
require_relative "./helper"
|
3
|
+
require "combine_pdf"
|
3
4
|
|
4
5
|
module Palapala
|
5
6
|
# Page class to generate PDF from HTML content using Chrome in headless mode in a thread-safe way
|
@@ -80,21 +81,40 @@ module Palapala
|
|
80
81
|
#
|
81
82
|
# @param opts [Hash] the options to pass to the renderer
|
82
83
|
# @return [String] the PDF content as a binary string
|
83
|
-
def binary_data
|
84
|
+
def binary_data(title: "", author: "", subject: "", producer: "PalapalaPDF", creator: "PalapalaPDF", skip_metadata: false)
|
84
85
|
puts "Rendering PDF with params: #{@opts}" if Palapala.debug
|
85
|
-
Renderer.html_to_pdf(@content, params: @opts)
|
86
|
+
binary_data = Renderer.html_to_pdf(@content, params: @opts)
|
87
|
+
|
88
|
+
if skip_metadata
|
89
|
+
binary_data
|
90
|
+
else
|
91
|
+
# Load the PDF from the string
|
92
|
+
pdf = CombinePDF.parse(binary_data)
|
93
|
+
|
94
|
+
# Set metadata manually
|
95
|
+
info_hash = {
|
96
|
+
Title: title,
|
97
|
+
Author: author,
|
98
|
+
Subject: subject,
|
99
|
+
Producer: producer,
|
100
|
+
Creator: creator
|
101
|
+
}
|
102
|
+
|
103
|
+
# Embed metadata into the PDF
|
104
|
+
pdf.info.merge!(info_hash)
|
105
|
+
pdf.to_pdf
|
106
|
+
end
|
86
107
|
rescue StandardError => e
|
87
108
|
puts "Error rendering PDF: #{e.message}"
|
88
109
|
Renderer.reset
|
89
110
|
raise
|
90
111
|
end
|
91
112
|
|
92
|
-
|
93
113
|
# Save the PDF content to a file
|
94
114
|
# @param path [String] the path to save the PDF file
|
95
115
|
# @return [void]
|
96
|
-
def save(path)
|
97
|
-
File.binwrite(path, binary_data)
|
116
|
+
def save(path, **opts)
|
117
|
+
File.binwrite(path, binary_data(**opts))
|
98
118
|
end
|
99
119
|
end
|
100
120
|
end
|
data/lib/palapala/renderer.rb
CHANGED
@@ -88,6 +88,8 @@ module Palapala
|
|
88
88
|
# Method to send a CDP command and wait for a specific method to be called
|
89
89
|
def send_command_and_wait_for_event(method, event_name:, params: {})
|
90
90
|
send_command(method, params:) do
|
91
|
+
# chrome refuses to load pages that are bigger than 2MB and returns a net::ERR_ABORTED error
|
92
|
+
raise "Page cannot be loaded" if @response.dig("result", "errorText") == "net::ERR_ABORTED"
|
91
93
|
@response && @response["method"] == event_name
|
92
94
|
end
|
93
95
|
end
|
data/lib/palapala/version.rb
CHANGED
data/palapala_pdf.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
36
36
|
# Uncomment to register a new dependency of your gem
|
37
37
|
spec.add_dependency 'base64', '~> 0'
|
38
38
|
spec.add_dependency 'websocket-driver', '~> 0'
|
39
|
+
spec.add_dependency 'combine_pdf', '~> 1'
|
39
40
|
|
40
41
|
# For more information and examples about making a new gem, check out our
|
41
42
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: palapala_pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koen Handekyn
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-04-29 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: base64
|
@@ -38,6 +37,20 @@ dependencies:
|
|
38
37
|
- - "~>"
|
39
38
|
- !ruby/object:Gem::Version
|
40
39
|
version: '0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: combine_pdf
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1'
|
47
|
+
type: :runtime
|
48
|
+
prerelease: false
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1'
|
41
54
|
description: This gem uses faw web sockets to render HTML into a PDF using Chrom(e)(ium)
|
42
55
|
with minimal dependencies.
|
43
56
|
email:
|
@@ -84,7 +97,6 @@ metadata:
|
|
84
97
|
homepage_uri: https://github.com/palapala-app/palapala_pdf
|
85
98
|
changelog_uri: https://github.com/palapala-app/palapala_pdf/blob/main/changelog.md
|
86
99
|
rubygems_mfa_required: 'true'
|
87
|
-
post_install_message:
|
88
100
|
rdoc_options: []
|
89
101
|
require_paths:
|
90
102
|
- lib
|
@@ -99,8 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
111
|
- !ruby/object:Gem::Version
|
100
112
|
version: '0'
|
101
113
|
requirements: []
|
102
|
-
rubygems_version: 3.5
|
103
|
-
signing_key:
|
114
|
+
rubygems_version: 3.6.5
|
104
115
|
specification_version: 4
|
105
116
|
summary: Convert HTML into PDF directly from Ruby using Chrome/Chromium.
|
106
117
|
test_files: []
|