html2pdf-rails 0.5.0 → 0.7.0
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/.github/workflows/ci.yml +30 -0
- data/README.md +60 -0
- data/lib/html2pdf/rails/helper.rb +58 -5
- data/lib/html2pdf/rails/mailer_rendering.rb +16 -0
- data/lib/html2pdf/rails/railtie.rb +6 -0
- data/lib/html2pdf/rails/rendering.rb +13 -19
- data/lib/html2pdf/rails/version.rb +1 -1
- data/lib/html2pdf/rails.rb +23 -4
- metadata +5 -7
- data/.travis.yml +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3651940b4f5e82b4b9016f5ee19bb796445247b2f7f6b47e4f7e61b9bb77c57d
|
|
4
|
+
data.tar.gz: 51f9ab1f57f30e455053a06f37aac4599ea30ff1dcb36b8deff32ee283411456
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44b1e70af04a620a235a53091b3ab6b6b6b02d556da30e3dccabe6001cdd32566820c72671d14843720cfebf1ab9cc41757cfc090158519a1ad99d4ca5e8d8ba
|
|
7
|
+
data.tar.gz: 1148efd75a6d2ca35bd16259082d9dc301f12bd9bc2979c7b0566d419e74179403af2c7c1742f4d58ac84d15dfa09728d379ad4ce828fe6de6548e5948a5b496
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
ruby-version: ['3.2', '3.3', '3.4', '4.0']
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
24
|
+
uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
27
|
+
bundler-cache: true
|
|
28
|
+
|
|
29
|
+
- name: Run tests
|
|
30
|
+
run: bundle exec rspec -fp
|
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
1
3
|
# html2pdf-rails
|
|
2
4
|
|
|
3
5
|
PDF generator (from HTML) gem for Ruby on Rails.
|
|
@@ -59,6 +61,40 @@ You can get signed url of Cloud Storage if your Cloud Funciton code support it.
|
|
|
59
61
|
redirect_to pdf_url
|
|
60
62
|
```
|
|
61
63
|
|
|
64
|
+
### Attach PDF to an email (ActionMailer)
|
|
65
|
+
|
|
66
|
+
`render_to_pdf_string` is available in all mailers. It renders a template, converts it to PDF, and returns the PDF binary.
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
class OrderMailer < ApplicationMailer
|
|
70
|
+
def receipt(order)
|
|
71
|
+
@order = order
|
|
72
|
+
attachments['receipt.pdf'] = render_to_pdf_string
|
|
73
|
+
mail(to: order.user.email)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
By default, the template is inferred from `<mailer_name>/<action_name>` and `formats: [:pdf]` is used. So the example above renders `order_mailer/receipt.pdf.erb`. You can override these defaults:
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
attachments['receipt.pdf'] = render_to_pdf_string(
|
|
82
|
+
template: 'order_mailer/receipt_pdf',
|
|
83
|
+
layout: 'pdf',
|
|
84
|
+
pdf_options: { margin: { top: '30px' } }
|
|
85
|
+
)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Generate PDF from arbitrary HTML
|
|
89
|
+
|
|
90
|
+
If you already have an HTML string (for example, in a background job or PORO), use the low-level API:
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
html = ApplicationController.render(template: 'invoices/show', assigns: { invoice: invoice })
|
|
94
|
+
pdf = Html2Pdf::Rails.generate(html: html, pdf_options: { margin: { top: '30px' } })
|
|
95
|
+
File.binwrite('invoice.pdf', pdf)
|
|
96
|
+
```
|
|
97
|
+
|
|
62
98
|
### Advanced Usage with all available options
|
|
63
99
|
|
|
64
100
|
```ruby
|
|
@@ -130,6 +166,30 @@ Html2Pdf.configure do |config|
|
|
|
130
166
|
end
|
|
131
167
|
```
|
|
132
168
|
|
|
169
|
+
### `html2pdf_base_tag` in mailers / jobs
|
|
170
|
+
|
|
171
|
+
`html2pdf_base_tag` resolves the base URL in this order (matches Rails `url_for`):
|
|
172
|
+
|
|
173
|
+
1. Explicit `host:` / `protocol:` argument
|
|
174
|
+
2. `HTTP_X_ORIGINAL_HOST` request header (host only, for Ngrok-style proxying)
|
|
175
|
+
3. View-context `url_options[:host]` / `[:protocol]`:
|
|
176
|
+
- In a controller view: `config.action_controller.default_url_options` merged over `request.host` / `request.protocol` (config wins, request as fallback — same behavior as Rails `url_for`)
|
|
177
|
+
- In a mailer view: `config.action_mailer.default_url_options`
|
|
178
|
+
4. `Rails.application.routes.default_url_options[:host]` / `[:protocol]` (final fallback)
|
|
179
|
+
|
|
180
|
+
Most Rails apps already configure `config.action_mailer.default_url_options` for mailer URL helpers, so no extra setup is usually required:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
# config/environments/production.rb
|
|
184
|
+
config.action_mailer.default_url_options = { host: 'example.com', protocol: 'https' }
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
If you want to override per-call (e.g. multi-tenant), pass arguments:
|
|
188
|
+
|
|
189
|
+
```erb
|
|
190
|
+
<%= html2pdf_base_tag host: 'tenant.example.com', protocol: 'https' %>
|
|
191
|
+
```
|
|
192
|
+
|
|
133
193
|
## Contributing
|
|
134
194
|
|
|
135
195
|
Bug reports and pull requests are welcome on GitHub at https://github.com/SonicGarden/html2pdf-rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
|
@@ -3,11 +3,64 @@
|
|
|
3
3
|
module Html2Pdf
|
|
4
4
|
module Rails
|
|
5
5
|
module Helper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
# Resolves the base URL in the same order as Rails' `url_for`, with one
|
|
7
|
+
# gem-specific addition (HTTP_X_ORIGINAL_HOST). See `_html2pdf_default_url_options`
|
|
8
|
+
# for the source of `options`.
|
|
9
|
+
def html2pdf_base_tag(host: nil, protocol: nil)
|
|
10
|
+
req = _html2pdf_request
|
|
11
|
+
options = _html2pdf_default_url_options
|
|
12
|
+
|
|
13
|
+
# HTTP_X_ORIGINAL_HOST overrides options because dev tunneling (Ngrok) sets
|
|
14
|
+
# this header to the externally-visible host that puppeteer must reach,
|
|
15
|
+
# which doesn't match request.host or any configured default.
|
|
16
|
+
host ||= req && req.headers['HTTP_X_ORIGINAL_HOST']
|
|
17
|
+
host ||= options[:host]
|
|
18
|
+
if host.blank?
|
|
19
|
+
raise ArgumentError,
|
|
20
|
+
'html2pdf_base_tag: host is not available. Pass `host:` or configure default_url_options (e.g. config.action_mailer.default_url_options).'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# options[:protocol] from controller's url_options is "https://" (with trailing
|
|
24
|
+
# "://" — request.protocol convention), while config and mailer values are
|
|
25
|
+
# bare "https". Normalize.
|
|
26
|
+
protocol ||= options[:protocol]&.to_s&.delete_suffix('://')
|
|
27
|
+
protocol ||= 'https'
|
|
28
|
+
|
|
29
|
+
tag.base href: "#{protocol}://#{host}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def _html2pdf_request
|
|
35
|
+
respond_to?(:request) ? request : nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Mirrors how Rails' `url_for` resolves URL options, so this helper produces
|
|
39
|
+
# the same host/protocol as `url_for` would in the same context.
|
|
40
|
+
#
|
|
41
|
+
# `view.url_options` delegates to `controller.url_options`:
|
|
42
|
+
# https://github.com/rails/rails/blob/v8.1.2/actionview/lib/action_view/routing_url_for.rb#L124
|
|
43
|
+
#
|
|
44
|
+
# In a controller this returns
|
|
45
|
+
# `{ host: request.host, protocol: request.protocol, ... }.merge!(super)`:
|
|
46
|
+
# https://github.com/rails/rails/blob/v8.1.2/actionpack/lib/action_controller/metal/url_for.rb#L37
|
|
47
|
+
# `merge!` lets class-level `default_url_options` win over request info.
|
|
48
|
+
# In a mailer it returns the class-level `default_url_options` directly
|
|
49
|
+
# (no request to merge in).
|
|
50
|
+
#
|
|
51
|
+
# `RouteSet#url_for` then does `default_url_options.merge(options)`, so
|
|
52
|
+
# routes' default is the base under everything else. We replicate that here:
|
|
53
|
+
# https://github.com/rails/rails/blob/v8.1.2/actionpack/lib/action_dispatch/routing/route_set.rb#L856
|
|
54
|
+
#
|
|
55
|
+
# Note: `config.action_mailer.default_url_options` and
|
|
56
|
+
# `config.action_controller.default_url_options` populate the *class*
|
|
57
|
+
# `default_url_options`, NOT `Rails.application.routes.default_url_options` —
|
|
58
|
+
# they are three separate hashes. Reading only the routes hash would miss the
|
|
59
|
+
# typical mailer setup.
|
|
60
|
+
def _html2pdf_default_url_options
|
|
61
|
+
routes_options = ::Rails.application&.routes&.default_url_options || {}
|
|
62
|
+
context_options = respond_to?(:url_options) ? url_options : {}
|
|
63
|
+
routes_options.merge(context_options)
|
|
11
64
|
end
|
|
12
65
|
end
|
|
13
66
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Html2Pdf
|
|
4
|
+
module Rails
|
|
5
|
+
module MailerRendering
|
|
6
|
+
def render_to_pdf_string(template: nil, layout: false, formats: [:pdf], handlers: nil, pdf_options: {})
|
|
7
|
+
# When :template is omitted, Rails resolves the template from `_prefixes`
|
|
8
|
+
# (= [mailer_name]) and `action_name` via `_process_render_template_options`:
|
|
9
|
+
# https://github.com/rails/rails/blob/v8.1.2/actionview/lib/action_view/rendering.rb#L177
|
|
10
|
+
render_opts = { template: template, layout: layout, formats: formats, handlers: handlers }.compact
|
|
11
|
+
html = render_to_string(**render_opts)
|
|
12
|
+
Html2Pdf::Rails.generate(html: html, pdf_options: pdf_options)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'rails'
|
|
3
4
|
require 'html2pdf/rails/rendering'
|
|
5
|
+
require 'html2pdf/rails/mailer_rendering'
|
|
4
6
|
require 'html2pdf/rails/helper'
|
|
5
7
|
|
|
6
8
|
module Html2Pdf
|
|
@@ -10,6 +12,10 @@ module Html2Pdf
|
|
|
10
12
|
ActionController::Base.prepend Rendering
|
|
11
13
|
end
|
|
12
14
|
|
|
15
|
+
ActiveSupport.on_load(:action_mailer) do
|
|
16
|
+
ActionMailer::Base.include MailerRendering
|
|
17
|
+
end
|
|
18
|
+
|
|
13
19
|
ActiveSupport.on_load(:action_view) do
|
|
14
20
|
ActionView::Base.include Helper
|
|
15
21
|
end
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'retryable'
|
|
4
|
-
require 'html2pdf/rails/client'
|
|
5
|
-
|
|
6
3
|
module Html2Pdf
|
|
7
4
|
module Rails
|
|
8
5
|
module Rendering
|
|
@@ -28,9 +25,15 @@ module Html2Pdf
|
|
|
28
25
|
|
|
29
26
|
def _html2_pdf_render_pdf_and_get_url(pdf_name, options = {})
|
|
30
27
|
options = _html2pdf_default_options(pdf_name, options)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
html = _html2pdf_render_html(options)
|
|
29
|
+
response = Html2Pdf::Rails.generate(
|
|
30
|
+
html: html,
|
|
31
|
+
pdf_options: options[:pdf_options],
|
|
32
|
+
put_to_storage: true,
|
|
33
|
+
file_name: options[:file_name],
|
|
34
|
+
disposition: options[:disposition]
|
|
35
|
+
)
|
|
36
|
+
JSON.parse(response)['url']
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
def _html2pdf_make_and_send_pdf(pdf_name, options = {})
|
|
@@ -40,24 +43,15 @@ module Html2Pdf
|
|
|
40
43
|
render_opts = options.slice(:template, :layout, :formats, :handlers)
|
|
41
44
|
render(render_opts.merge({ content_type: 'text/html' }))
|
|
42
45
|
else
|
|
43
|
-
|
|
46
|
+
html = _html2pdf_render_html(options)
|
|
47
|
+
pdf_content = Html2Pdf::Rails.generate(html: html, pdf_options: options[:pdf_options])
|
|
44
48
|
send_data(pdf_content, filename: options[:file_name], type: 'application/pdf', disposition: options[:disposition])
|
|
45
49
|
end
|
|
46
50
|
end
|
|
47
51
|
|
|
48
|
-
def
|
|
52
|
+
def _html2pdf_render_html(options)
|
|
49
53
|
render_opts = options.slice(:template, :layout, :formats, :handlers)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Retryable.retryable(tries: 3, on: Html2Pdf::Rails::ServiceUnavailableError) do
|
|
53
|
-
Client.post(
|
|
54
|
-
html: html,
|
|
55
|
-
put_to_storage: options[:put_to_storage],
|
|
56
|
-
file_name: options[:file_name],
|
|
57
|
-
disposition: options[:disposition],
|
|
58
|
-
pdf_options: options[:pdf_options]
|
|
59
|
-
)
|
|
60
|
-
end
|
|
54
|
+
render_to_string(**render_opts)
|
|
61
55
|
end
|
|
62
56
|
end
|
|
63
57
|
end
|
data/lib/html2pdf/rails.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'retryable'
|
|
2
2
|
require 'html2pdf/rails/version'
|
|
3
|
+
require 'html2pdf/rails/errors'
|
|
4
|
+
require 'html2pdf/rails/client'
|
|
3
5
|
require 'html2pdf/rails/railtie'
|
|
4
6
|
|
|
5
7
|
module Html2Pdf
|
|
6
8
|
class Config
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
attr_accessor :endpoint, :app
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
@endpoint = nil
|
|
13
|
+
@app = nil
|
|
14
|
+
end
|
|
10
15
|
end
|
|
11
16
|
|
|
12
17
|
class << self
|
|
@@ -18,4 +23,18 @@ module Html2Pdf
|
|
|
18
23
|
@config ||= Config.new
|
|
19
24
|
end
|
|
20
25
|
end
|
|
26
|
+
|
|
27
|
+
module Rails
|
|
28
|
+
def self.generate(html:, pdf_options: {}, put_to_storage: false, file_name: nil, disposition: nil)
|
|
29
|
+
Retryable.retryable(tries: 3, on: ServiceUnavailableError) do
|
|
30
|
+
Client.post(
|
|
31
|
+
html: html,
|
|
32
|
+
pdf_options: pdf_options,
|
|
33
|
+
put_to_storage: put_to_storage,
|
|
34
|
+
file_name: file_name,
|
|
35
|
+
disposition: disposition
|
|
36
|
+
)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
21
40
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: html2pdf-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- aki77
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -87,10 +86,10 @@ executables: []
|
|
|
87
86
|
extensions: []
|
|
88
87
|
extra_rdoc_files: []
|
|
89
88
|
files:
|
|
89
|
+
- ".github/workflows/ci.yml"
|
|
90
90
|
- ".gitignore"
|
|
91
91
|
- ".rspec"
|
|
92
92
|
- ".rubocop.yml"
|
|
93
|
-
- ".travis.yml"
|
|
94
93
|
- CODE_OF_CONDUCT.md
|
|
95
94
|
- Gemfile
|
|
96
95
|
- LICENSE.txt
|
|
@@ -103,6 +102,7 @@ files:
|
|
|
103
102
|
- lib/html2pdf/rails/client.rb
|
|
104
103
|
- lib/html2pdf/rails/errors.rb
|
|
105
104
|
- lib/html2pdf/rails/helper.rb
|
|
105
|
+
- lib/html2pdf/rails/mailer_rendering.rb
|
|
106
106
|
- lib/html2pdf/rails/railtie.rb
|
|
107
107
|
- lib/html2pdf/rails/rendering.rb
|
|
108
108
|
- lib/html2pdf/rails/version.rb
|
|
@@ -110,7 +110,6 @@ homepage: https://github.com/SonicGarden/html2pdf-rails
|
|
|
110
110
|
licenses:
|
|
111
111
|
- MIT
|
|
112
112
|
metadata: {}
|
|
113
|
-
post_install_message:
|
|
114
113
|
rdoc_options: []
|
|
115
114
|
require_paths:
|
|
116
115
|
- lib
|
|
@@ -125,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
125
124
|
- !ruby/object:Gem::Version
|
|
126
125
|
version: '0'
|
|
127
126
|
requirements: []
|
|
128
|
-
rubygems_version:
|
|
129
|
-
signing_key:
|
|
127
|
+
rubygems_version: 4.0.3
|
|
130
128
|
specification_version: 4
|
|
131
129
|
summary: PDF generator (from HTML) gem for Ruby on Rails
|
|
132
130
|
test_files: []
|