rails-pdf-renderer 0.4.2 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c649a492ecbdff7b6e611300aaf1fa1fe742327e36335fa4d61f37dca76b9dfb
4
- data.tar.gz: 36552f2510d272ae0e01aa795b6f368a59f11f52fa21733113e5d9411957ef42
3
+ metadata.gz: f0faa43dcdd14e5f3c7455270aaca26f5f0089052bbda4112a7aacb42cf30d6f
4
+ data.tar.gz: 9ca877e4310f32fbafeeb1db8659eb5d13bb015a975eba8d1fea72f4ceea856a
5
5
  SHA512:
6
- metadata.gz: f1313dfb77ef87a6c573feeadb727e5d979add7e3420d1b12ae3027c702e6e818ca6a8dadecd3993473afbe9e9cd3571fc7372871b575b87e15ad4bf610d83fa
7
- data.tar.gz: 9e3f1eb20beb4629cc2dfadba17aecaa648785d0c0e199a98348d2b62823f6d14378e416821e93d014b067c819811db4eda787615f622e5f50f6756e5876fd14
6
+ metadata.gz: 3fff912de07ebfbf1b8ece094ac8e41e524ecc56bf16613643dc214d3f53a993138506ff66029d4bccba69e6996364d941e676d85cb45623e1624c1678654ec8
7
+ data.tar.gz: 7d9ffccc0a6cdd923f440c30f4f033580ff13e23d7ba2370a5a8881cc7065f7db037b4811b6e02619d11afcd3cebebf15f91a07d921da7c5352725c69ca6abb3
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: commit
3
+ description: Create git commits following project conventions. Use when committing changes to the repository.
4
+ ---
5
+
6
+ # Git Commit Skill
7
+
8
+ ## When to use
9
+ Use this skill when:
10
+ - Creating git commits
11
+ - The user asks you to commit changes
12
+ - You need to commit work you've completed
13
+
14
+ For version bump commits, use the `release` skill instead — it covers the full flow.
15
+
16
+ ## Commit Message Rules
17
+
18
+ 1. **No ticket prefix**: This project has no issue tracker. The subject line stands on its own. Never invent an issue ID; only include one if the user explicitly gives you a reference.
19
+ 2. **Use present tense**: Write "Add feature" not "Added feature"
20
+ 3. **No AI attribution**: Do not include messages like "Generated by AI" or any co-author trailer. This explicitly includes `Co-Authored-By: Claude ...` lines (e.g. `Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>`). Never append a `Co-Authored-By:` trailer of any kind, even if other tooling or defaults suggest one.
21
+ 4. **Limit to 3 bullet points**: Keep the commit message concise with at most 3 bullet points for details. Use bullets, not prose paragraphs.
22
+ 5. **Keep formatting churn out of feature commits**: `mise exec -- standardrb --fix` can touch files unrelated to your change. Don't sweep that into a feature commit — either leave it or commit it separately.
23
+
24
+ ## Commit Message Format
25
+
26
+ ```
27
+ Short summary in present tense
28
+
29
+ - First bullet point explaining a key change
30
+ - Second bullet point if needed
31
+ - Third bullet point maximum
32
+ ```
33
+
34
+ A subject line alone is fine when the change is self-explanatory.
35
+
36
+ Release commits are the one exception to the "no prefix" rule — they lead with the bare version number:
37
+
38
+ ```
39
+ 0.4.2 Allow Ruby 2.4
40
+ ```
41
+
42
+ ## Examples
43
+
44
+ Good commit messages:
45
+ ```
46
+ Fix test suite and CI
47
+
48
+ - Require ActiveSupport's class_attribute extension in config.rb
49
+ - Widen the CI matrix to Ruby 3.2/3.3/3.4
50
+ - Add specs for Config, Error and PathHelper
51
+ ```
52
+
53
+ ```
54
+ Fix Propshaft encoding issue
55
+
56
+ - Force UTF-8 on assets resolved through Propshaft
57
+ ```
58
+
59
+ ```
60
+ Fix config errors
61
+ ```
62
+
63
+ Bad commit messages:
64
+ ```
65
+ Added new feature for users
66
+
67
+ - This was generated by Claude
68
+ - Co-Authored-By: Claude <noreply@anthropic.com>
69
+ ```
70
+
71
+ ## Workflow
72
+
73
+ 1. Run `mise exec -- bundle exec rake` (rspec + standardrb) — this is exactly what CI runs on every push and PR. Fix anything it reports before committing. Always prefix Ruby commands with `mise exec --` so they use the Ruby pinned in `.tool-versions` instead of the system Ruby.
74
+ 2. Stage the relevant changes with `git add`
75
+ 3. Create a commit with a message following the rules above
76
+ 4. Verify the commit was created successfully with `git log -1`
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: create-pr
3
+ description: Create a GitHub pull request with a well-structured description. Use when creating a PR or when the user asks to open a pull request.
4
+ ---
5
+
6
+ # Create PR Skill
7
+
8
+ ## When to use
9
+ Use this skill when:
10
+ - Creating a GitHub pull request
11
+ - The user asks you to open or create a PR
12
+
13
+ ## Workflow
14
+
15
+ 1. **Gather context**: Run `git log main..HEAD --oneline` and `git diff main...HEAD --stat` to understand all changes
16
+ 2. **Read changed files** if needed to understand the intent behind the changes
17
+ 3. **Write the PR description** following the format below
18
+ 4. **Create the PR** using `gh pr create --base main`
19
+
20
+ PRs target `main` unless the user says otherwise (stacked PRs onto another feature branch happen, but are the exception). Branches are lowercase kebab-case with no namespace prefix — `fix-tests-and-ci`, `allow-ruby-2-4`.
21
+
22
+ ## PR Title Format
23
+
24
+ ```
25
+ Short summary in present tense
26
+ ```
27
+
28
+ No ticket prefix and no conventional-commit prefix. In practice the title matches the branch's commit subject. Keep it under 70 characters.
29
+
30
+ ## PR Description Format
31
+
32
+ ```markdown
33
+ ## Summary
34
+
35
+ Brief description of what this PR does and why. Focus on the intent and approach,
36
+ not a mechanical list of file changes. 2-5 sentences.
37
+
38
+ ## Verification
39
+
40
+ - [ ] `mise exec -- bundle exec rake` passes (rspec + standardrb)
41
+ - [ ] Any extra checks specific to this change
42
+ ```
43
+
44
+ `mise exec -- bundle exec rake` is the project's gate — CI runs it on Ruby 3.3, 3.4 and 4.0. Run Ruby commands through `mise exec --` so they use the Ruby pinned in `.tool-versions` rather than the system Ruby. If you ran it against more than one Ruby version, or deleted `Gemfile.lock` to simulate a clean checkout, say so.
45
+
46
+ Only claim a check you actually ran.
47
+
48
+ ## Bug fix PRs
49
+
50
+ For bug fixes, frame the description around behavior, not code. A reviewer wants to know
51
+ what triggered the bug, what we expected, and what actually happened — not what was wrong with
52
+ the old code. Use this format:
53
+
54
+ ```markdown
55
+ ## Summary
56
+
57
+ One or two sentences describing the problem and the fix.
58
+
59
+ **Steps to reproduce**
60
+ 1. ...
61
+ 2. ...
62
+
63
+ **Expected:** what should happen
64
+ **Actual:** what happened instead (the bug)
65
+
66
+ ## Verification
67
+
68
+ - [ ] ...
69
+ ```
70
+
71
+ Rules for the reproduction steps:
72
+
73
+ - **Minimal**: include only the steps needed to trigger the bug. Eliminate as many
74
+ factors as possible so the cause is isolated.
75
+ - **Reproducible from a clean checkout**: this is a gem, so the repro is code-level — a
76
+ short snippet, a specific config, a Ruby or Rails version, an asset pipeline setup.
77
+ Name the versions involved when they matter.
78
+ - **Start from a known state**: e.g. "in a fresh Rails 8.1 app with Propshaft" rather
79
+ than assuming the reader's local setup.
80
+
81
+ Keep the `## Verification` section in addition — it confirms the fix works, while the
82
+ reproduction steps document the bug.
83
+
84
+ ## Rules
85
+
86
+ 1. **No AI attribution**: Do not include "Generated by Claude Code", co-author lines, or similar
87
+ 2. **Summary should explain why, not just what**: Describe the problem being solved and the approach taken
88
+ 3. **Describe behavior, not code internals**: For bug fixes, give what triggered the bug, what we expected, and what actually happened. Do not explain in detail what was wrong with the old code or what it was before — that's irrelevant to a reviewer
89
+ 4. **Verification is what you actually ran**: Name the commands and their results. Don't list checks you skipped
90
+ 5. **Skip the verification section** if there is nothing meaningful to report (e.g. doc-only changes)
91
+ 6. **Use present tense**: Write "Add feature" not "Added feature"
92
+ 7. **Keep it concise**: The description should be helpful, not exhaustive
93
+
94
+ ## Examples
95
+
96
+ Good PR description:
97
+ ```markdown
98
+ ## Summary
99
+
100
+ The suite never got past loading, both locally and on CI: `config.rb` calls `class_attribute`
101
+ but nothing required ActiveSupport's core extension, so requiring `rails/pdf/renderer`
102
+ standalone (as `spec_helper` does) raised `NoMethodError`. Adding that one require is the
103
+ actual fix. The default `rake` task also chains `standard`, which was reporting 75 offenses
104
+ and aborting the task, so this applies `standard:fix` across the lib and gemspec. CI moves to
105
+ `actions/checkout@v4` and widens the matrix from a single `3.2.2` pin to Ruby 3.2/3.3/3.4.
106
+
107
+ ## Verification
108
+
109
+ - [ ] `mise exec -- bundle exec rake` passes on Ruby 4.0.6 — 19 examples, 0 failures
110
+ - [ ] Passes from scratch with `Gemfile.lock` deleted, simulating a clean CI checkout
111
+ ```
112
+
113
+ Good bug-fix PR description (reproduce / expected / actual):
114
+ ```markdown
115
+ ## Summary
116
+
117
+ Rendering a PDF in a Rails app on Propshaft raised an encoding error when a stylesheet
118
+ contained non-ASCII characters. Assets resolved through Propshaft are now forced to UTF-8.
119
+
120
+ **Steps to reproduce**
121
+ 1. In a Rails 7.1 app using Propshaft, add a stylesheet containing a non-ASCII character
122
+ 2. Render any PDF that includes that stylesheet
123
+
124
+ **Expected:** the PDF renders with the stylesheet applied
125
+ **Actual:** `Encoding::CompatibilityError` is raised during rendering
126
+
127
+ ## Verification
128
+
129
+ - [ ] `mise exec -- bundle exec rake` passes
130
+ - [ ] Rendering a PDF with a non-ASCII stylesheet succeeds in a Propshaft app
131
+ ```
132
+
133
+ Good PR description (no verification section needed):
134
+ ```markdown
135
+ ## Summary
136
+
137
+ Point the gemspec's homepage, source_code_uri and changelog_uri at `gembero/rails-pdf-renderer`.
138
+ They were pointing at a bare `github.com/erikaxel/` URL from before the repo moved to the org.
139
+ ```
140
+
141
+ Bad PR description:
142
+ ```markdown
143
+ ## Summary
144
+
145
+ Updated files to fix the bug.
146
+
147
+ ## Verification
148
+
149
+ - [ ] Run the tests
150
+ - [ ] Check CI passes
151
+
152
+ 🤖 Generated with Claude Code
153
+ ```
154
+
155
+ ## Creating the PR
156
+
157
+ Use `gh pr create` with a HEREDOC for the body:
158
+
159
+ ```bash
160
+ gh pr create --base main --title "Title here" --body "$(cat <<'EOF'
161
+ ## Summary
162
+
163
+ ...
164
+
165
+ ## Verification
166
+
167
+ - [ ] ...
168
+ EOF
169
+ )"
170
+ ```
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: release
3
+ description: Cut a new version of the rails-pdf-renderer gem — bump the version, update the changelog, and publish to rubygems.org. Use when releasing a new version or bumping the gem version.
4
+ ---
5
+
6
+ # Release Skill
7
+
8
+ ## When to use
9
+ Use this skill when:
10
+ - The user asks to cut, ship, or publish a release
11
+ - The user asks to bump the gem version
12
+
13
+ ## Before you start
14
+
15
+ Check that the last release actually shipped:
16
+
17
+ ```bash
18
+ git tag # tags are v-prefixed: v0.4.1
19
+ cat lib/rails/pdf/renderer/version.rb # VERSION = "0.4.2"
20
+ ```
21
+
22
+ If `version.rb` is ahead of the newest tag, a previous version was committed but never
23
+ released. Ask the user whether to release that version as-is or to bump past it — don't
24
+ silently skip it.
25
+
26
+ Also confirm you're releasing from `main` and that it's up to date with `origin/main`.
27
+
28
+ ## Steps
29
+
30
+ 1. **Bump the version** in `lib/rails/pdf/renderer/version.rb`. The gemspec reads
31
+ `RailsPdfRenderer::VERSION` from this file — it's the single source of truth. Follow
32
+ semver: patch for fixes, minor for backwards-compatible features, major for breaking
33
+ changes.
34
+
35
+ 2. **Add a `CHANGELOG.md` entry.** This step is not optional — the changelog was skipped
36
+ for the entire 0.4.x line and is stale as a result. Match the existing format:
37
+
38
+ ```markdown
39
+ ## [0.5.0]
40
+ ### New Features
41
+ - Description of the feature
42
+
43
+ ### Fixes
44
+ - Description of the fix
45
+ ```
46
+
47
+ Newest version goes at the top, directly under the header block. Use `### New Features`
48
+ and `### Fixes` sections with dash bullets; include only the sections that apply.
49
+
50
+ 3. **Run the gate**: `mise exec -- bundle exec rake` (rspec + standardrb). It must be green
51
+ before you release. CI runs this on Ruby 3.3, 3.4 and 4.0.
52
+
53
+ 4. **Commit** the version bump and changelog together, with the version as the subject
54
+ prefix (see the `commit` skill for the general rules — no AI attribution, present tense):
55
+
56
+ ```
57
+ 0.5.0 Add support for custom page sizes
58
+ ```
59
+
60
+ A bare version subject (`0.4.0`) is acceptable when the release has no single headline
61
+ change, but a short description is better.
62
+
63
+ 5. **Publish**: `mise exec -- bundle exec rake release`. This comes from `bundler/gem_tasks` and will:
64
+ - create the `v0.5.0` git tag
65
+ - push the commit and tag to `origin`
66
+ - build the gem and push it to rubygems.org
67
+
68
+ It needs rubygems credentials and it is not reversible — a published version cannot be
69
+ replaced, only yanked. Confirm with the user before running it.
70
+
71
+ ## Notes
72
+
73
+ - The local Ruby version is pinned in `.tool-versions`. Run every Ruby command through
74
+ `mise exec --` so it doesn't fall back to the system Ruby.
75
+ - `Gemfile.lock` is gitignored, so there's no lockfile to update.
76
+ - `mise exec -- bundle exec rake build` produces the gem locally under `pkg/` without
77
+ publishing — useful for a dry run.
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 4.0.6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [0.5.0]
6
+ ### New Features
7
+ - Added the `html:` option for already-rendered HTML. The string is sent to the PDF
8
+ service verbatim and is never compiled as a template, so `<%= %>` in the content
9
+ cannot execute as Ruby on the server. `layout:`, `locals:`, `assigns:`, `formats:`
10
+ and `handlers:` do not apply to `html:`, and passing both `html:` and `inline:`
11
+ raises `ArgumentError`.
12
+ - `type:` is now forwarded to ActionView when rendering `inline:` templates, so a
13
+ non-ERB handler can be used (for example `type: :raw` or `type: :haml`).
14
+ - Documented `inline:` (an ERB template) versus `html:` (finished HTML) in the README.
15
+
16
+ ### Fixes
17
+ - Declare `activesupport` (>= 7.0) as a runtime dependency. It is required at
18
+ load time by `RailsPdfRenderer::Config`, but was previously only pulled in
19
+ through the host application.
20
+ - `status:` is now forwarded to the response for both PDF and `show_as_html:` renders.
21
+ It was previously accepted and silently ignored, so those responses always returned 200.
22
+ - `RailsPdfRenderer::ActionControllerHelper` now requires the standard library and
23
+ ActiveSupport extensions it uses instead of relying on the host application.
24
+
25
+ ### Breaking changes
26
+ - Dropped support for end-of-life Ruby versions. `required_ruby_version` is now
27
+ `>= 3.3.0`. Only Ruby versions still supported by the Ruby core team are
28
+ supported (currently 3.3, 3.4 and 4.0).
29
+
5
30
  ## [0.3.0]
6
31
  ### Fixes
7
32
  Fix Propshaft encoding issue
data/CLAUDE.md ADDED
@@ -0,0 +1,91 @@
1
+ # CLAUDE.md
2
+
3
+ Guidance for Claude Code working in this repository.
4
+
5
+ ## What this gem is
6
+
7
+ `rails-pdf-renderer` is a Rails gem that renders a controller view to HTML and then
8
+ POSTs that HTML to an **external PDF rendering service** (a headless-Chrome-style
9
+ server), which returns the PDF bytes. It does *not* shell out to a local binary.
10
+ This is the main architectural difference from [wicked_pdf](https://github.com/mileszs/wicked_pdf/),
11
+ from which much of the asset-handling code was adapted.
12
+
13
+ Usage in an app looks like `render pdf: "filename", template: "..."` — the gem
14
+ intercepts `render`/`render_to_string` when the options hash contains a `:pdf` key.
15
+
16
+ ## Ruby toolchain
17
+
18
+ The local Ruby version is managed by [mise](https://mise.jdx.dev) and pinned in `.tool-versions`
19
+ (Ruby 4.0). The gem itself supports Ruby 3.3+; CI covers 3.3, 3.4 and 4.0.
20
+
21
+ **Always run Ruby commands through `mise exec --`** so they use the pinned Ruby instead of
22
+ the system Ruby. If `mise install` hasn't been run in a fresh checkout, run it first.
23
+
24
+ ## Commands
25
+
26
+ ```bash
27
+ mise exec -- bin/setup # bundle install
28
+ mise exec -- bundle exec rake # default task: rspec + standardrb (what CI runs)
29
+ mise exec -- bundle exec rake spec # tests only
30
+ mise exec -- bundle exec rspec # tests only
31
+ mise exec -- standardrb # lint only; add --fix to autocorrect
32
+ mise exec -- bin/console # IRB with the gem loaded
33
+ ```
34
+
35
+ CI (`.github/workflows/main.yml`) runs `bundle exec rake` against Ruby 3.3, 3.4 and 4.0,
36
+ matching the gemspec's `required_ruby_version >= 3.3.0`.
37
+
38
+ ## Code layout
39
+
40
+ All code lives under `lib/rails/pdf/renderer/`, namespaced under the top-level
41
+ **class** `RailsPdfRenderer` (a class, not a module — `class RailsPdfRenderer` is
42
+ required when reopening it).
43
+
44
+ - `railtie.rb` — wiring. Prepends `ActionControllerHelper` onto `ActionController::Base`
45
+ and includes `ActionViewHelper` into views via `ActiveSupport.on_load`. Also
46
+ registers the `application/pdf` MIME type. Everything is guarded by
47
+ `if defined?(Rails.env)` so the gem can be required outside Rails.
48
+ - `action_controller_helper.rb` — the `render`/`render_to_string` overrides,
49
+ `make_pdf`, and `pdf_from_server` (the HTTP call to the PDF service).
50
+ - `action_view_helper.rb` — the bulk of the code: `pdf_asset_path`,
51
+ `pdf_stylesheet_link_tag`, `pdf_image_tag`, `pdf_*_base64`, etc. These inline
52
+ assets into the HTML so the remote renderer can resolve them. Supports Sprockets,
53
+ Propshaft, and Webpacker/Shakapacker; each has its own branch in `find_asset`
54
+ and `webpacker_source_url`. Touching one branch usually means checking the others.
55
+ - `config.rb` — configuration, built on `class_attribute`.
56
+ - `error.rb` — `RailsPdfRenderer::Error`, wraps the failed `Net::HTTP` response.
57
+ - `path_helper.rb`, `version.rb`.
58
+
59
+ ## Things that will bite you
60
+
61
+ - **Config is global class state.** `Config` uses `class_attribute`, and
62
+ `RailsPdfRenderer.configuration` memoizes a single instance, so assigning a
63
+ value mutates the class default for the whole process. Tests that change
64
+ configuration must restore it.
65
+ - **`pdf_server_params` unconditionally reads `options[:margin][:top]`** and the
66
+ other margin keys. The default `margin` hash comes from `Config.default_options`,
67
+ which is merged in by `render`. Any code path that builds options without that
68
+ merge will `NoMethodError` on `nil`.
69
+ - **`auth_key` is base64-encoded before being sent** as `Authorization: Bearer <base64>`.
70
+ A missing `auth_key` raises a plain `RuntimeError`, not `RailsPdfRenderer::Error`.
71
+ - The controller helper's `make_pdf` calls `render_to_string` recursively — the
72
+ override checks for the `:pdf` key to avoid infinite recursion, so never leave
73
+ `:pdf` in the options hash passed downward (`make_pdf` deletes it explicitly).
74
+ - Assets read from disk or over HTTP are `force_encoding('UTF-8')`'d — this was a
75
+ deliberate fix for Propshaft (see CHANGELOG 0.3.0), don't remove it.
76
+ - `raise_on_missing_assets` defaults to `true`, so a missing stylesheet or image
77
+ raises rather than silently rendering a blank PDF.
78
+
79
+ ## Style
80
+
81
+ `standard` (standardrb) is the linter and part of the default rake task, but
82
+ existing code in `action_controller_helper.rb` and `action_view_helper.rb` uses
83
+ hashrocket syntax and single quotes inherited from wicked_pdf. Match the
84
+ surrounding file rather than reformatting; run `standardrb` before committing and
85
+ keep unrelated formatting churn out of diffs.
86
+
87
+ ## Releasing
88
+
89
+ 1. Bump `VERSION` in `lib/rails/pdf/renderer/version.rb`.
90
+ 2. Add an entry to `CHANGELOG.md`.
91
+ 3. `mise exec -- bundle exec rake release` (tags, pushes, publishes to rubygems.org).
data/README.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # RailsPdfRenderer
2
2
 
3
+ ## Ruby support
4
+
5
+ This gem only supports Ruby versions that are still supported by the Ruby core
6
+ team. When a Ruby version reaches end-of-life it is dropped from the CI matrix
7
+ and `required_ruby_version` is raised in the next release, which may happen in a
8
+ minor version bump.
9
+
10
+ The currently supported versions are Ruby 3.3, 3.4 and 4.0.
11
+
3
12
  ## Installation
4
13
 
5
14
  Install the gem and add to the application's Gemfile by executing:
@@ -8,17 +17,100 @@ Install the gem and add to the application's Gemfile by executing:
8
17
 
9
18
  ## Usage
10
19
 
20
+ Render the current controller action as a PDF:
21
+
22
+ ```ruby
23
+ class InvoicesController < ApplicationController
24
+ def show
25
+ render pdf: "invoice-#{@invoice.number}"
26
+ end
27
+ end
28
+ ```
29
+
30
+ Or get the PDF back as a string:
31
+
32
+ ```ruby
33
+ pdf = ApplicationController.renderer.render_to_string(pdf: true, template: "invoices/show")
34
+ ```
35
+
36
+ ### `inline:` vs `html:`
37
+
38
+ These two options look similar and are **not** interchangeable:
39
+
40
+ | Option | Content | Processed by |
41
+ | --------- | --------------------------------- | ------------------------------------------ |
42
+ | `inline:` | An **ERB template** source string | ActionView - `<%= %>` is evaluated as Ruby |
43
+ | `html:` | **Finished HTML** | Nothing - sent to the PDF service verbatim |
44
+
45
+ Use `html:` whenever the HTML has already been rendered - ViewComponent output, a
46
+ `render_to_string` from elsewhere, a stored email body, or any content influenced by user
47
+ input:
48
+
49
+ ```ruby
50
+ html = InvoiceComponent.new(invoice: @invoice).render_in(view_context)
51
+ ApplicationController.renderer.render_to_string(pdf: true, html: html)
52
+ ```
11
53
 
54
+ > **Security:** passing already-rendered HTML to `inline:` makes ActionView compile it as an
55
+ > ERB template, so any `<%= ... %>` in the content executes as Ruby on your server. Always use
56
+ > `html:` for content you did not author as a template.
57
+
58
+ `html:` is sent as-is, so `layout:`, `locals:`, `assigns:`, `formats:` and `handlers:` are
59
+ ignored, and passing both `html:` and `inline:` raises `ArgumentError`.
60
+
61
+ If you need a non-ERB *template* language for `inline:`, pass `type:` - it is forwarded to
62
+ ActionView's handler lookup, e.g. `type: :raw` or `type: :haml`.
63
+
64
+ ### Options
65
+
66
+ | Option | Description |
67
+ | ------ | ----------- |
68
+ | `pdf:` | Filename without the `.pdf` extension, when using `render` |
69
+ | `html:` | Finished HTML, sent to the PDF service verbatim |
70
+ | `inline:` | ERB template source |
71
+ | `template:`, `layout:`, `locals:`, `assigns:`, `formats:`, `handlers:`, `file:`, `type:` | Standard ActionView rendering options |
72
+ | `show_as_html:` | Render the HTML in the browser instead of a PDF, for debugging |
73
+ | `status:` | HTTP status for the response |
74
+ | `disposition:` | `"inline"` (default) or `"attachment"` |
75
+ | `save_to_file:` | Also write the PDF to this path |
76
+ | `save_only:` | Write the PDF to `save_to_file:` without sending a response |
77
+ | `orientation:`, `pageSize:`, `zoom:`, `height:`, `width:`, `margin:`, `footerTemplate:` | Forwarded to the PDF service |
78
+
79
+ ### Configuration
80
+
81
+ ```ruby
82
+ RailsPdfRenderer.configure do |config|
83
+ config.url = "https://your-pdf-service.example.com/render"
84
+ config.auth_key = Rails.application.credentials.pdf_service_key
85
+ config.default_options = {margin: {top: "10mm", bottom: "10mm", left: "0mm", right: "0mm"}}
86
+ end
87
+ ```
12
88
 
13
89
  ## Development
14
90
 
15
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
91
+ The local Ruby version is managed with [mise](https://mise.jdx.dev) and pinned in
92
+ `.tool-versions`. Install it once with `mise install`, and run every command through mise so it
93
+ uses the pinned Ruby rather than the system one:
94
+
95
+ $ mise install
96
+ $ mise exec -- bin/setup
97
+
98
+ If you have mise activated in your shell (`mise activate`), the `mise exec --` prefix is
99
+ unnecessary — the pinned Ruby is already on your `PATH`. The examples below spell it out so
100
+ they work either way.
101
+
102
+ Run the tests with `mise exec -- rake spec`, or `mise exec -- bundle exec rake` for the full
103
+ gate (rspec + standardrb) that CI runs. You can also run `mise exec -- bin/console` for an
104
+ interactive prompt that will allow you to experiment.
105
+
106
+ To install this gem onto your local machine, run `mise exec -- bundle exec rake install`.
16
107
 
17
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
108
+ Development happens on Ruby 4.0 even though the gem supports 3.3 and up; CI is what covers
109
+ the rest of the matrix.
18
110
 
19
111
  ## Releasing new gems
20
112
  1. Update version.rb
21
- 2. Run `rake release` to release a new gem
113
+ 2. Run `mise exec -- bundle exec rake release` to release a new gem
22
114
 
23
115
  ## Contributing
24
116
 
@@ -1,11 +1,11 @@
1
+ require "base64"
2
+ require "json"
3
+ require "net/http"
4
+ require "active_support/core_ext/object/blank"
5
+ require "active_support/core_ext/string/output_safety"
6
+
1
7
  class RailsPdfRenderer
2
8
  module ActionControllerHelper
3
- def self.prepended(base)
4
- # Protect from trying to augment modules that appear
5
- # as the result of adding other gems.
6
- return if base != ActionController::Base
7
- end
8
-
9
9
  def render(*args)
10
10
  options = args.first
11
11
  if options.is_a?(Hash) && options.key?(:pdf)
@@ -29,44 +29,62 @@ class RailsPdfRenderer
29
29
  def make_pdf(options = {})
30
30
  options.delete :pdf # We dont use the filename when rendering to string
31
31
 
32
- render_opts = {
33
- :template => options[:template],
34
- :layout => options[:layout],
35
- :formats => options[:formats],
36
- :handlers => options[:handlers],
37
- :assigns => options[:assigns]
38
- }
39
- render_opts[:inline] = options[:inline] if options[:inline]
40
- render_opts[:locals] = options[:locals] if options[:locals]
41
- render_opts[:file] = options[:file] if options[:file]
42
- html_string = render_to_string(render_opts)
43
- pdf_from_server(html_string, options)
32
+ return pdf_from_server(raw_html(options), options) if options.key?(:html)
33
+
34
+ pdf_from_server(render_to_string(view_render_options(options)), options)
44
35
  end
45
36
 
46
37
  def make_and_send_pdf(pdf_name, options = {})
47
38
  options[:layout] ||= false
48
39
  options[:template] ||= File.join(controller_path, action_name)
49
- options[:disposition] ||= 'inline'
40
+ options[:disposition] ||= "inline"
50
41
  if options[:show_as_html]
51
- render_opts = {
52
- :template => options[:template],
53
- :layout => options[:layout],
54
- :formats => options[:formats],
55
- :handlers => options[:handlers],
56
- :assigns => options[:assigns],
57
- :content_type => 'text/html'
58
- }
59
- render_opts[:inline] = options[:inline] if options[:inline]
60
- render_opts[:locals] = options[:locals] if options[:locals]
61
- render_opts[:file] = options[:file] if options[:file]
42
+ render_opts = if options.key?(:html)
43
+ {html: raw_html(options).html_safe, layout: false, content_type: "text/html"}
44
+ else
45
+ view_render_options(options).merge(content_type: "text/html")
46
+ end
47
+ render_opts[:status] = options[:status] if options[:status]
62
48
  render(render_opts)
63
49
  else
64
50
  pdf_content = make_pdf(options)
65
- File.open(options[:save_to_file], 'wb') { |file| file << pdf_content } if options[:save_to_file]
66
- send_data(pdf_content, :filename => pdf_name + '.pdf', :type => 'application/pdf', :disposition => options[:disposition]) unless options[:save_only]
51
+ File.open(options[:save_to_file], "wb") { |file| file << pdf_content } if options[:save_to_file]
52
+ unless options[:save_only]
53
+ send_opts = {filename: pdf_name + ".pdf", type: "application/pdf", disposition: options[:disposition]}
54
+ send_opts[:status] = options[:status] if options[:status]
55
+ send_data(pdf_content, send_opts)
56
+ end
67
57
  end
68
58
  end
69
59
 
60
+ # Already-rendered HTML supplied by the caller through the :html option. Unlike
61
+ # :inline it is never compiled as a template, so `<%= %>` in the content cannot
62
+ # execute as Ruby on the server.
63
+ def raw_html(options)
64
+ if options.key?(:inline)
65
+ raise ArgumentError, "rails-pdf-renderer: :html and :inline are mutually exclusive. " \
66
+ ":html is finished HTML, :inline is an ERB template."
67
+ end
68
+ options[:html].to_s
69
+ end
70
+
71
+ # Options for rendering through ActionView. Everything here goes through a template
72
+ # handler - :inline defaults to ERB unless :type says otherwise.
73
+ def view_render_options(options)
74
+ render_opts = {
75
+ template: options[:template],
76
+ layout: options[:layout],
77
+ formats: options[:formats],
78
+ handlers: options[:handlers],
79
+ assigns: options[:assigns]
80
+ }
81
+ render_opts[:inline] = options[:inline] if options[:inline]
82
+ render_opts[:locals] = options[:locals] if options[:locals]
83
+ render_opts[:file] = options[:file] if options[:file]
84
+ render_opts[:type] = options[:type] if options[:type]
85
+ render_opts
86
+ end
87
+
70
88
  def pdf_from_server(html, options)
71
89
  payload = pdf_server_params(html, options)
72
90
 
@@ -77,10 +95,10 @@ class RailsPdfRenderer
77
95
  raise "auth_key is not set, you need to set it for rails-pdf-renderer to work" if auth_key.blank?
78
96
 
79
97
  uri = URI(url)
80
- headers = { 'Content-Type': 'application/json', "Authorization": "Bearer #{auth_key64}" }
98
+ headers = {"Content-Type": "application/json", Authorization: "Bearer #{auth_key64}"}
81
99
  response = Net::HTTP.post(uri, payload.to_json, headers)
82
100
 
83
- if response.kind_of? Net::HTTPSuccess
101
+ if response.is_a? Net::HTTPSuccess
84
102
  response.body
85
103
  else
86
104
  raise RailsPdfRenderer::Error.new(response)
@@ -1,7 +1,7 @@
1
- require 'net/http'
2
- require 'delegate'
3
- require 'stringio'
4
- require_relative 'path_helper'
1
+ require "net/http"
2
+ require "delegate"
3
+ require "stringio"
4
+ require_relative "path_helper"
5
5
 
6
6
  class RailsPdfRenderer
7
7
  module ActionViewHelper
@@ -60,7 +60,7 @@ class RailsPdfRenderer
60
60
  end
61
61
 
62
62
  def content_type
63
- Mime::Type.lookup_by_extension(File.extname(path).delete('.'))
63
+ Mime::Type.lookup_by_extension(File.extname(path).delete("."))
64
64
  end
65
65
 
66
66
  def to_s
@@ -76,7 +76,7 @@ class RailsPdfRenderer
76
76
  asset = find_asset(path)
77
77
  raise MissingLocalAsset, path if asset.nil?
78
78
 
79
- base64 = Base64.encode64(asset.to_s).gsub(/\s+/, '')
79
+ base64 = Base64.encode64(asset.to_s).gsub(/\s+/, "")
80
80
  "data:#{asset.content_type};base64,#{Rack::Utils.escape(base64)}"
81
81
  end
82
82
 
@@ -86,7 +86,7 @@ class RailsPdfRenderer
86
86
  response = Net::HTTP.get_response(URI(url))
87
87
 
88
88
  if response.is_a?(Net::HTTPSuccess)
89
- base64 = Base64.encode64(response.body).gsub(/\s+/, '')
89
+ base64 = Base64.encode64(response.body).gsub(/\s+/, "")
90
90
  "data:#{response.content_type};base64,#{Rack::Utils.escape(base64)}"
91
91
  else
92
92
  Rails.logger.warn("[pdf] #{response.code} #{response.message}: #{url}")
@@ -96,12 +96,12 @@ class RailsPdfRenderer
96
96
 
97
97
  def pdf_stylesheet_link_tag(*sources)
98
98
  stylesheet_contents = sources.collect do |source|
99
- source = PathHelper.add_extension(source, 'css')
99
+ source = PathHelper.add_extension(source, "css")
100
100
  "<style type='text/css'>#{read_asset(source)}</style>"
101
101
  end.join("\n")
102
102
 
103
103
  stylesheet_contents.gsub(ASSET_URL_REGEX) do
104
- if Regexp.last_match[1].starts_with?('data:')
104
+ if Regexp.last_match[1].starts_with?("data:")
105
105
  "url(#{Regexp.last_match[1]})"
106
106
  else
107
107
  "url(#{pdf_asset_path(Regexp.last_match[1])})"
@@ -116,7 +116,7 @@ class RailsPdfRenderer
116
116
  stylesheet_pack_tag(*sources)
117
117
  else
118
118
  css_text = sources.collect do |source|
119
- source = PathHelper.add_extension(source, 'css')
119
+ source = PathHelper.add_extension(source, "css")
120
120
  pdf_stylesheet_link_tag(webpacker_source_url(source))
121
121
  end.join("\n")
122
122
  css_text.respond_to?(:html_safe) ? css_text.html_safe : css_text
@@ -130,7 +130,7 @@ class RailsPdfRenderer
130
130
  javascript_pack_tag(*sources)
131
131
  else
132
132
  sources.collect do |source|
133
- source = PathHelper.add_extension(source, 'js')
133
+ source = PathHelper.add_extension(source, "js")
134
134
  "<script type='text/javascript'>#{read_asset(webpacker_source_url(source))}</script>"
135
135
  end.join("\n").html_safe
136
136
  end
@@ -141,19 +141,19 @@ class RailsPdfRenderer
141
141
  end
142
142
 
143
143
  def pdf_javascript_src_tag(jsfile, options = {})
144
- jsfile = PathHelper.add_extension(jsfile, 'js')
144
+ jsfile = PathHelper.add_extension(jsfile, "js")
145
145
  javascript_include_tag pdf_asset_path(jsfile), options
146
146
  end
147
147
 
148
148
  def pdf_javascript_include_tag(*sources)
149
149
  sources.collect do |source|
150
- source = PathHelper.add_extension(source, 'js')
150
+ source = PathHelper.add_extension(source, "js")
151
151
  "<script type='text/javascript'>#{read_asset(source)}</script>"
152
152
  end.join("\n").html_safe
153
153
  end
154
154
 
155
155
  def pdf_asset_path(asset)
156
- if (pathname = asset_pathname(asset).to_s) =~ URI_REGEXP
156
+ if URI_REGEXP.match?(pathname = asset_pathname(asset).to_s)
157
157
  pathname
158
158
  else
159
159
  "file:///#{pathname}"
@@ -179,11 +179,11 @@ class RailsPdfRenderer
179
179
  if precompiled_or_absolute_asset?(source)
180
180
  asset = asset_path(source)
181
181
  pathname = prepend_protocol(asset)
182
- if pathname =~ URI_REGEXP
182
+ if URI_REGEXP.match?(pathname)
183
183
  # asset_path returns an absolute URL using asset_host if asset_host is set
184
184
  pathname
185
185
  else
186
- File.join(Rails.public_path, asset.sub(/\A#{Rails.application.config.action_controller.relative_url_root}/, ''))
186
+ File.join(Rails.public_path, asset.sub(/\A#{Rails.application.config.action_controller.relative_url_root}/, ""))
187
187
  end
188
188
  else
189
189
  asset = find_asset(source)
@@ -198,7 +198,7 @@ class RailsPdfRenderer
198
198
 
199
199
  def find_asset(path)
200
200
  if Rails.application.assets.respond_to?(:find_asset)
201
- Rails.application.assets.find_asset(path, :base_path => Rails.application.root.to_s)
201
+ Rails.application.assets.find_asset(path, base_path: Rails.application.root.to_s)
202
202
  elsif defined?(Propshaft::Assembly) && Rails.application.assets.is_a?(Propshaft::Assembly)
203
203
  PropshaftAsset.new(Rails.application.assets.load_path.find(path))
204
204
  elsif Rails.application.respond_to?(:assets_manifest)
@@ -208,7 +208,7 @@ class RailsPdfRenderer
208
208
  asset_path = File.join(Rails.application.assets_manifest.dir, relative_asset_path)
209
209
  LocalAsset.new(asset_path) if File.file?(asset_path)
210
210
  else
211
- SprocketsEnvironment.find_asset(path, :base_path => Rails.application.root.to_s)
211
+ SprocketsEnvironment.find_asset(path, base_path: Rails.application.root.to_s)
212
212
  end
213
213
  end
214
214
 
@@ -219,7 +219,7 @@ class RailsPdfRenderer
219
219
  assets.find do |asset, _v|
220
220
  directory = File.dirname(asset)
221
221
  asset_path = File.basename(asset, File.extname(asset))
222
- asset_path = File.join(directory, asset_path) if directory != '.'
222
+ asset_path = File.join(directory, asset_path) if directory != "."
223
223
 
224
224
  asset_path == path
225
225
  end&.last
@@ -231,11 +231,11 @@ class RailsPdfRenderer
231
231
  # will prepend a http or default_protocol to a protocol relative URL
232
232
  # or when no protcol is set.
233
233
  def prepend_protocol(source)
234
- protocol = RailsPdfRenderer.configuration.default_protocol || 'http'
235
- if source[0, 2] == '//'
236
- source = [protocol, ':', source].join
237
- elsif source[0] != '/' && !source[0, 8].include?('://')
238
- source = [protocol, '://', source].join
234
+ protocol = RailsPdfRenderer.configuration.default_protocol || "http"
235
+ if source[0, 2] == "//"
236
+ source = [protocol, ":", source].join
237
+ elsif source[0] != "/" && !source[0, 8].include?("://")
238
+ source = [protocol, "://", source].join
239
239
  end
240
240
  source
241
241
  end
@@ -243,13 +243,13 @@ class RailsPdfRenderer
243
243
  def precompiled_or_absolute_asset?(source)
244
244
  !Rails.configuration.respond_to?(:assets) ||
245
245
  Rails.configuration.assets.compile == false ||
246
- source.to_s[0] == '/' ||
247
- source.to_s.match(/\Ahttps?\:\/\//)
246
+ source.to_s[0] == "/" ||
247
+ source.to_s.match(/\Ahttps?:\/\//)
248
248
  end
249
249
 
250
250
  def read_asset(source)
251
251
  asset = find_asset(source)
252
- return asset.to_s.force_encoding('UTF-8') if asset
252
+ return asset.to_s.force_encoding("UTF-8") if asset
253
253
 
254
254
  unless precompiled_or_absolute_asset?(source)
255
255
  raise MissingLocalAsset, source if RailsPdfRenderer.configuration.raise_on_missing_assets
@@ -258,7 +258,7 @@ class RailsPdfRenderer
258
258
  end
259
259
 
260
260
  pathname = asset_pathname(source)
261
- if pathname =~ URI_REGEXP
261
+ if URI_REGEXP.match?(pathname)
262
262
  read_from_uri(pathname)
263
263
  elsif File.file?(pathname)
264
264
  IO.read(pathname)
@@ -277,7 +277,7 @@ class RailsPdfRenderer
277
277
  end
278
278
 
279
279
  asset = response.body
280
- asset.force_encoding('UTF-8') if asset
280
+ asset&.force_encoding("UTF-8")
281
281
  asset = gzip(asset) if RailsPdfRenderer.configuration.expect_gzipped_remote_assets
282
282
  asset
283
283
  end
@@ -294,9 +294,9 @@ class RailsPdfRenderer
294
294
  return unless webpacker_version
295
295
 
296
296
  # In Webpacker 3.2.0 asset_pack_url is introduced
297
- if webpacker_version >= '3.2.0'
297
+ if webpacker_version >= "3.2.0"
298
298
  if (host = Rails.application.config.asset_host)
299
- asset_pack_path(source, :host => host)
299
+ asset_pack_path(source, host: host)
300
300
  else
301
301
  asset_pack_url(source)
302
302
  end
@@ -320,12 +320,12 @@ class RailsPdfRenderer
320
320
 
321
321
  def webpacker_version
322
322
  if defined?(Shakapacker)
323
- require 'shakapacker/version'
323
+ require "shakapacker/version"
324
324
  Shakapacker::VERSION
325
325
  elsif defined?(Webpacker)
326
- require 'webpacker/version'
326
+ require "webpacker/version"
327
327
  Webpacker::VERSION
328
328
  end
329
329
  end
330
330
  end
331
- end
331
+ end
@@ -1,3 +1,5 @@
1
+ require "active_support/core_ext/class/attribute"
2
+
1
3
  class RailsPdfRenderer
2
4
  class Config
3
5
  class_attribute :auth_key, instance_accessor: true
@@ -15,4 +17,4 @@ class RailsPdfRenderer
15
17
  }
16
18
  }
17
19
  end
18
- end
20
+ end
@@ -10,4 +10,4 @@ class RailsPdfRenderer
10
10
  "Got error when trying to fetch PDF from server. HTTP error #{@http_response.code} #{@http_response.message}"
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -1,7 +1,7 @@
1
1
  class RailsPdfRenderer
2
2
  module PathHelper
3
3
  def self.add_extension(filename, extension)
4
- filename.to_s.split('.').include?(extension) ? filename : "#{filename}.#{extension}"
4
+ filename.to_s.split(".").include?(extension) ? filename : "#{filename}.#{extension}"
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -1,15 +1,15 @@
1
- require_relative 'action_controller_helper'
2
- require_relative 'action_view_helper'
1
+ require_relative "action_controller_helper"
2
+ require_relative "action_view_helper"
3
3
 
4
4
  class RailsPdfRenderer
5
5
  if defined?(Rails.env)
6
6
  class RailsPdfRendererRailtie < Rails::Railtie
7
- initializer 'rails-pdf-renderer.register' do |_app|
7
+ initializer "rails-pdf-renderer.register" do |_app|
8
8
  ActiveSupport.on_load(:action_controller) { ActionController::Base.send :prepend, RailsPdfRenderer::ActionControllerHelper }
9
9
  ActiveSupport.on_load(:action_view) { include RailsPdfRenderer::ActionViewHelper }
10
10
  end
11
11
  end
12
12
 
13
- Mime::Type.register('application/pdf', :pdf) if Mime::Type.lookup_by_extension(:pdf).nil?
13
+ Mime::Type.register("application/pdf", :pdf) if Mime::Type.lookup_by_extension(:pdf).nil?
14
14
  end
15
15
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class RailsPdfRenderer
4
- VERSION = "0.4.2"
4
+ VERSION = "0.5.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-pdf-renderer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Axel Nielsen
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activesupport
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.0'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: rails
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -86,8 +100,13 @@ executables: []
86
100
  extensions: []
87
101
  extra_rdoc_files: []
88
102
  files:
103
+ - ".claude/skills/commit/SKILL.md"
104
+ - ".claude/skills/create-pr/SKILL.md"
105
+ - ".claude/skills/release/SKILL.md"
89
106
  - ".rspec"
107
+ - ".tool-versions"
90
108
  - CHANGELOG.md
109
+ - CLAUDE.md
91
110
  - LICENSE.txt
92
111
  - README.md
93
112
  - Rakefile
@@ -99,7 +118,6 @@ files:
99
118
  - lib/rails/pdf/renderer/path_helper.rb
100
119
  - lib/rails/pdf/renderer/railtie.rb
101
120
  - lib/rails/pdf/renderer/version.rb
102
- - rails-pdf-renderer.gemspec
103
121
  homepage: https://github.com/erikaxel/
104
122
  licenses:
105
123
  - MIT
@@ -114,14 +132,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
132
  requirements:
115
133
  - - ">="
116
134
  - !ruby/object:Gem::Version
117
- version: 2.4.0
135
+ version: 3.3.0
118
136
  required_rubygems_version: !ruby/object:Gem::Requirement
119
137
  requirements:
120
138
  - - ">="
121
139
  - !ruby/object:Gem::Version
122
140
  version: '0'
123
141
  requirements: []
124
- rubygems_version: 4.0.3
142
+ rubygems_version: 4.0.16
125
143
  specification_version: 4
126
144
  summary: Create PDFs directly from Rails.
127
145
  test_files: []
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/rails/pdf/renderer/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "rails-pdf-renderer"
7
- spec.version = RailsPdfRenderer::VERSION
8
- spec.authors = ["Erik Axel Nielsen"]
9
- spec.email = ["erikaxel.nielsen@gmail.com"]
10
-
11
- spec.summary = "Create PDFs directly from Rails."
12
- spec.description = "Helper library to generate PDFs from Rails."
13
- spec.homepage = "https://github.com/erikaxel/"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.4.0"
16
-
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/erikaxel/"
19
- spec.metadata["changelog_uri"] = "https://github.com/erikaxel/CHANGELOG.md"
20
-
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(__dir__) do
24
- `git ls-files -z`.split("\x0").reject do |f|
25
- (File.expand_path(f) == __FILE__) ||
26
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
27
- end
28
- end
29
- spec.bindir = "exe"
30
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
- spec.require_paths = ["lib"]
32
-
33
- spec.add_development_dependency 'rails'
34
- spec.add_development_dependency 'rake'
35
- spec.add_development_dependency 'rspec'
36
- spec.add_development_dependency "rspec-rails"
37
- spec.add_development_dependency 'standard'
38
- end