forme-ruby 0.1.0-x86_64-linux-gnu → 0.2.0-x86_64-linux-gnu
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/CHANGELOG.md +46 -2
- data/CONTRIBUTING.md +1 -1
- data/NOTICE +1 -1
- data/README.md +20 -20
- data/SECURITY.md +4 -5
- data/THIRD_PARTY_LICENSES.txt +238 -17
- data/docs/github-setup.md +13 -11
- data/docs/installation.md +16 -32
- data/docs/releasing.md +54 -40
- data/docs/rendering.md +26 -7
- data/docs/security-exceptions.md +7 -4
- data/lib/forme_pdf/native/libforme_pdf_native.so +0 -0
- data/lib/forme_pdf/rails.rb +2 -0
- data/lib/forme_pdf/renderer.rb +30 -10
- data/lib/forme_pdf/version.rb +2 -2
- metadata +7 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bcec7b760319b11c375b2fb12c145efd061f193b914e1912b778a0e50434c896
|
|
4
|
+
data.tar.gz: 34952294dc0cc9c45b64bd3b79684a998ed765c2414973d22aa471cb830fc178
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b002ce2f7900ea162b58d920213df60e63be6446c0982a44692d3c136179feb356501d6cc9164dc01f09fa0c8752b223f498e75801f7145d20c0fe3fc901290
|
|
7
|
+
data.tar.gz: ec4ba56567607425342bd80043ca18fcf505407663bdb46e36cb68cf44b6f35541302624f6272daada4f32b87b71e0fd83e9d93149f9c715f3333af34b448860
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,48 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.2.0 (2026-10-20)
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- File image sources (`/`, `./`, `../`) are omitted with a warning unless the new
|
|
8
|
+
`image_root:` option names a directory containing them. Allowed files are
|
|
9
|
+
inlined after checking they are regular files of at most 64 MiB.
|
|
10
|
+
- Font `weight` must be an Integer from 1 to 1000 and `italic` true or false;
|
|
11
|
+
invalid values and non-UTF-8 `css:` or font families raise `ArgumentError`.
|
|
12
|
+
- `FormePDF::Rails#render_forme_pdf` is private, so Rails does not expose it as
|
|
13
|
+
a controller action. Call it from your own actions as before.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Rendering deeply nested HTML on a non-main Ruby thread no longer overflows the
|
|
18
|
+
thread's stack and hangs the process. Renders run on a native thread with a
|
|
19
|
+
64 MiB stack, and documents nested deeper than 512 elements raise
|
|
20
|
+
`FormePDF::RenderError`.
|
|
21
|
+
- Failed source builds show Cargo's diagnostics instead of only
|
|
22
|
+
"Forme native build failed".
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Require Ruby 3.3 or later. The Ubuntu 24.04 package job installs a pinned
|
|
27
|
+
Ruby 3.3 build in its clean container.
|
|
28
|
+
- State only platform requirements in the README and installation guide.
|
|
29
|
+
- Update the native engine to Forme HTML 0.28.0 at
|
|
30
|
+
`b97dc101b705ea5d7fea6fb1b20fabfb5bd2d63d`; running headers and footers
|
|
31
|
+
no longer inherit `<body>` color and font.
|
|
32
|
+
- Allow the `json` 3.x runtime dependency.
|
|
33
|
+
- Refresh locked Rust and development dependencies and regenerate third-party notices.
|
|
34
|
+
- Publish on a `v*` tag push instead of a manual dispatch. The release promotes
|
|
35
|
+
the tagged commit's CI packages unchanged, attaches them with `SHA256SUMS` to
|
|
36
|
+
the GitHub release, and pushes each to RubyGems with a Sigstore attestation.
|
|
37
|
+
- Re-review native audit exceptions against the new engine revision.
|
|
38
|
+
- CI installs the source gem on macOS as well as Linux, verifies the rustup
|
|
39
|
+
installer checksum and pins the Ubuntu test images by digest.
|
|
40
|
+
|
|
41
|
+
## 0.1.0 (2026-09-18)
|
|
42
|
+
|
|
43
|
+
Released on [GitHub](https://github.com/clearstackio/forme-ruby/releases/tag/v0.1.0)
|
|
44
|
+
and [RubyGems](https://rubygems.org/gems/forme-ruby/versions/0.1.0)
|
|
45
|
+
with identical source and native gems.
|
|
4
46
|
|
|
5
47
|
### Added
|
|
6
48
|
|
|
@@ -23,7 +65,9 @@
|
|
|
23
65
|
|
|
24
66
|
- Forme HTML 0.24.0 at `f408920e632c59da0651b5b6d32f8c1397477673`.
|
|
25
67
|
- Build toolchain: Rust 1.94.0; target minimums macOS 15 and glibc 2.28.
|
|
26
|
-
-
|
|
68
|
+
- Release commit `266628a` passed the full hosted platform matrix and CodeQL.
|
|
69
|
+
- Published all three packages through trusted publishing; registry downloads
|
|
70
|
+
match the qualified CI and GitHub release artifacts byte-for-byte.
|
|
27
71
|
|
|
28
72
|
### Release preparation
|
|
29
73
|
|
data/CONTRIBUTING.md
CHANGED
|
@@ -5,7 +5,7 @@ Use synthetic documents and assets that can be redistributed.
|
|
|
5
5
|
|
|
6
6
|
## Set up a checkout
|
|
7
7
|
|
|
8
|
-
Use CRuby 3.
|
|
8
|
+
Use CRuby 3.3+ and Rust/Cargo 1.94.0, a native linker and make. From the repository:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
11
|
bundle install
|
data/NOTICE
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
forme-ruby is an independent binding, not an official Forme project.
|
|
2
2
|
Forme: https://github.com/danmolitor/forme
|
|
3
|
-
Pinned revision:
|
|
3
|
+
Pinned revision: b97dc101b705ea5d7fea6fb1b20fabfb5bd2d63d
|
|
4
4
|
Forme is MIT licensed. Native distributions must include upstream and dependency
|
|
5
5
|
license notices generated during their build (see third-party notices).
|
data/README.md
CHANGED
|
@@ -9,18 +9,25 @@ WebAssembly or separate rendering service is needed.
|
|
|
9
9
|
|
|
10
10
|
This is an independent MIT-licensed binding maintained by
|
|
11
11
|
[ClearStack](https://github.com/clearstackio), not an official upstream project.
|
|
12
|
-
**0.
|
|
12
|
+
**[0.2.0 is available on RubyGems](https://rubygems.org/gems/forme-ruby/versions/0.2.0).**
|
|
13
13
|
|
|
14
14
|
## Getting started
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
lockfile. Git installation compiles the native extension and requires Rust/Cargo
|
|
18
|
-
1.94.0, a linker and make:
|
|
16
|
+
Add to your Gemfile and run `bundle install`:
|
|
19
17
|
|
|
20
18
|
```ruby
|
|
21
|
-
gem "forme-ruby",
|
|
19
|
+
gem "forme-ruby", "~> 0.2.0", require: "forme_pdf"
|
|
22
20
|
```
|
|
23
21
|
|
|
22
|
+
Or install directly:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
gem install forme-ruby -v 0.2.0
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
RubyGems selects a matching native package where available. The same packages
|
|
29
|
+
and checksums are available in the [GitHub release](https://github.com/clearstackio/forme-ruby/releases/tag/v0.2.0).
|
|
30
|
+
|
|
24
31
|
```ruby
|
|
25
32
|
require "forme_pdf"
|
|
26
33
|
|
|
@@ -28,21 +35,14 @@ pdf = FormePDF.render_html("<h1>Hello from Ruby</h1>")
|
|
|
28
35
|
File.binwrite("hello.pdf", pdf)
|
|
29
36
|
```
|
|
30
37
|
|
|
31
|
-
|
|
32
|
-
15+ and Linux AMD64 glibc 2.28+ and need no compiler. Source installs require
|
|
33
|
-
network access to locked upstream dependencies. See [installation](docs/installation.md).
|
|
34
|
-
|
|
35
|
-
## Native platform targets
|
|
38
|
+
## Requirements
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
- Ruby 3.3 or later.
|
|
41
|
+
- Native gems: macOS 15+ on Apple Silicon, or Linux AMD64 with glibc 2.28+.
|
|
42
|
+
- Source gem: Rust/Cargo 1.94.0, a C linker, make and network access to the
|
|
43
|
+
locked upstream dependencies.
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
pending. Red Hat testing uses official UBI images, not RHEL certification.
|
|
44
|
-
Linux ARM64, Windows and Alpine/musl binaries are not provided. See the
|
|
45
|
-
[installation guide](docs/installation.md) for Ruby and source-build requirements.
|
|
45
|
+
See the [installation guide](docs/installation.md).
|
|
46
46
|
|
|
47
47
|
## Using Rails
|
|
48
48
|
|
|
@@ -65,7 +65,7 @@ Rails is optional. The [Rails guide](docs/rails.md) also covers the opt-in
|
|
|
65
65
|
- [Release guide](docs/releasing.md): package qualification and future publication.
|
|
66
66
|
- [Changelog](CHANGELOG.md), [license](LICENSE) and [third-party notices](THIRD_PARTY_LICENSES.txt).
|
|
67
67
|
|
|
68
|
-
Use trusted HTML and assets.
|
|
69
|
-
sandbox for untrusted documents. See [security](SECURITY.md). Report reproducible
|
|
68
|
+
Use trusted HTML and assets. Local image files are read only inside an explicit
|
|
69
|
+
`image_root:`, and the engine is not a sandbox for untrusted documents. See [security](SECURITY.md). Report reproducible
|
|
70
70
|
bugs through [GitHub issues](https://github.com/clearstackio/forme-ruby/issues)
|
|
71
71
|
with synthetic input, Ruby/platform versions and renderer diagnostics.
|
data/SECURITY.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
Render trusted HTML and caller-selected assets only.
|
|
4
|
-
|
|
3
|
+
Render trusted HTML and caller-selected assets only. Local image files are read
|
|
4
|
+
only inside a caller-supplied `image_root:`, at most 64 MiB each. Rendering
|
|
5
|
+
consumes CPU/memory in the host process, and some layouts, such as deeply nested
|
|
6
|
+
tables, can take far longer than their size suggests. It is not an HTML sandbox;
|
|
5
7
|
thread cancellation is not a reliable rendering timeout.
|
|
6
8
|
|
|
7
9
|
Keep confidential documents out of logs and public issue attachments. Use a
|
|
@@ -9,9 +11,6 @@ minimal synthetic reproduction when reporting a problem. Send potential
|
|
|
9
11
|
security vulnerabilities privately to ajaya@clearstack.io rather than posting
|
|
10
12
|
sensitive details publicly. No response-time guarantee is offered.
|
|
11
13
|
|
|
12
|
-
The initial 0.1.0 release is still in preparation. Before deployment, qualify the
|
|
13
|
-
exact package and pinned native dependencies on your application's target.
|
|
14
|
-
|
|
15
14
|
Dependency audit exceptions and their call-path evidence are recorded in
|
|
16
15
|
[the security review](docs/security-exceptions.md). They must be re-reviewed
|
|
17
16
|
when the pinned engine or public native interface changes.
|
data/THIRD_PARTY_LICENSES.txt
CHANGED
|
@@ -3236,7 +3236,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
3236
3236
|
|
|
3237
3237
|
|
|
3238
3238
|
|
|
3239
|
-
crc32fast 1.5.
|
|
3239
|
+
crc32fast 1.5.3 — MIT OR Apache-2.0
|
|
3240
3240
|
https://github.com/srijs/rust-crc32fast
|
|
3241
3241
|
|
|
3242
3242
|
Apache License
|
|
@@ -6631,7 +6631,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
6631
6631
|
|
|
6632
6632
|
|
|
6633
6633
|
|
|
6634
|
-
forme-pdf 0.
|
|
6634
|
+
forme-pdf 0.28.0 — MIT
|
|
6635
6635
|
https://github.com/formepdf/forme
|
|
6636
6636
|
|
|
6637
6637
|
MIT License
|
|
@@ -6658,7 +6658,7 @@ SOFTWARE.
|
|
|
6658
6658
|
|
|
6659
6659
|
|
|
6660
6660
|
|
|
6661
|
-
forme-pdf-html 0.
|
|
6661
|
+
forme-pdf-html 0.28.0 — MIT
|
|
6662
6662
|
https://github.com/formepdf/forme
|
|
6663
6663
|
|
|
6664
6664
|
MIT License
|
|
@@ -8240,7 +8240,7 @@ SOFTWARE.
|
|
|
8240
8240
|
|
|
8241
8241
|
|
|
8242
8242
|
|
|
8243
|
-
lazy_static 1.5.
|
|
8243
|
+
lazy_static 1.5.1 — MIT OR Apache-2.0
|
|
8244
8244
|
https://github.com/rust-lang-nursery/lazy-static.rs
|
|
8245
8245
|
|
|
8246
8246
|
Apache License
|
|
@@ -8446,8 +8446,6 @@ See the License for the specific language governing permissions and
|
|
|
8446
8446
|
limitations under the License.
|
|
8447
8447
|
|
|
8448
8448
|
|
|
8449
|
-
Copyright (c) 2010 The Rust Project Developers
|
|
8450
|
-
|
|
8451
8449
|
Permission is hereby granted, free of charge, to any
|
|
8452
8450
|
person obtaining a copy of this software and associated
|
|
8453
8451
|
documentation files (the "Software"), to deal in the
|
|
@@ -8474,7 +8472,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
8474
8472
|
|
|
8475
8473
|
|
|
8476
8474
|
|
|
8477
|
-
libc 0.2.
|
|
8475
|
+
libc 0.2.191 — MIT OR Apache-2.0
|
|
8478
8476
|
https://github.com/rust-lang/libc
|
|
8479
8477
|
|
|
8480
8478
|
Apache License
|
|
@@ -16370,7 +16368,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
16370
16368
|
|
|
16371
16369
|
|
|
16372
16370
|
|
|
16373
|
-
serde_json 1.0.
|
|
16371
|
+
serde_json 1.0.154 — MIT OR Apache-2.0
|
|
16374
16372
|
https://github.com/serde-rs/json
|
|
16375
16373
|
|
|
16376
16374
|
Apache License
|
|
@@ -17074,7 +17072,7 @@ SOFTWARE.
|
|
|
17074
17072
|
|
|
17075
17073
|
|
|
17076
17074
|
|
|
17077
|
-
siphasher 1.0.
|
|
17075
|
+
siphasher 1.0.4 — MIT OR Apache-2.0
|
|
17078
17076
|
https://github.com/jedisct1/rust-siphash
|
|
17079
17077
|
|
|
17080
17078
|
Copyright 2012-2016 The Rust Project Developers.
|
|
@@ -17087,7 +17085,230 @@ option.
|
|
|
17087
17085
|
|
|
17088
17086
|
|
|
17089
17087
|
|
|
17090
|
-
|
|
17088
|
+
Apache License
|
|
17089
|
+
Version 2.0, January 2004
|
|
17090
|
+
http://www.apache.org/licenses/
|
|
17091
|
+
|
|
17092
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
17093
|
+
|
|
17094
|
+
1. Definitions.
|
|
17095
|
+
|
|
17096
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
17097
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
17098
|
+
|
|
17099
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
17100
|
+
the copyright owner that is granting the License.
|
|
17101
|
+
|
|
17102
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17103
|
+
other entities that control, are controlled by, or are under common
|
|
17104
|
+
control with that entity. For the purposes of this definition,
|
|
17105
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
17106
|
+
direction or management of such entity, whether by contract or
|
|
17107
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
17108
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
17109
|
+
|
|
17110
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
17111
|
+
exercising permissions granted by this License.
|
|
17112
|
+
|
|
17113
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
17114
|
+
including but not limited to software source code, documentation
|
|
17115
|
+
source, and configuration files.
|
|
17116
|
+
|
|
17117
|
+
"Object" form shall mean any form resulting from mechanical
|
|
17118
|
+
transformation or translation of a Source form, including but
|
|
17119
|
+
not limited to compiled object code, generated documentation,
|
|
17120
|
+
and conversions to other media types.
|
|
17121
|
+
|
|
17122
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
17123
|
+
Object form, made available under the License, as indicated by a
|
|
17124
|
+
copyright notice that is included in or attached to the work
|
|
17125
|
+
(an example is provided in the Appendix below).
|
|
17126
|
+
|
|
17127
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
17128
|
+
form, that is based on (or derived from) the Work and for which the
|
|
17129
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
17130
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
17131
|
+
of this License, Derivative Works shall not include works that remain
|
|
17132
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
17133
|
+
the Work and Derivative Works thereof.
|
|
17134
|
+
|
|
17135
|
+
"Contribution" shall mean any work of authorship, including
|
|
17136
|
+
the original version of the Work and any modifications or additions
|
|
17137
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
17138
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
17139
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
17140
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
17141
|
+
means any form of electronic, verbal, or written communication sent
|
|
17142
|
+
to the Licensor or its representatives, including but not limited to
|
|
17143
|
+
communication on electronic mailing lists, source code control systems,
|
|
17144
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
17145
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
17146
|
+
excluding communication that is conspicuously marked or otherwise
|
|
17147
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
17148
|
+
|
|
17149
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
17150
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
17151
|
+
subsequently incorporated within the Work.
|
|
17152
|
+
|
|
17153
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
17154
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
17155
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
17156
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
17157
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
17158
|
+
Work and such Derivative Works in Source or Object form.
|
|
17159
|
+
|
|
17160
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
17161
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
17162
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
17163
|
+
(except as stated in this section) patent license to make, have made,
|
|
17164
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
17165
|
+
where such license applies only to those patent claims licensable
|
|
17166
|
+
by such Contributor that are necessarily infringed by their
|
|
17167
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
17168
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
17169
|
+
institute patent litigation against any entity (including a
|
|
17170
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
17171
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
17172
|
+
or contributory patent infringement, then any patent licenses
|
|
17173
|
+
granted to You under this License for that Work shall terminate
|
|
17174
|
+
as of the date such litigation is filed.
|
|
17175
|
+
|
|
17176
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
17177
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
17178
|
+
modifications, and in Source or Object form, provided that You
|
|
17179
|
+
meet the following conditions:
|
|
17180
|
+
|
|
17181
|
+
(a) You must give any other recipients of the Work or
|
|
17182
|
+
Derivative Works a copy of this License; and
|
|
17183
|
+
|
|
17184
|
+
(b) You must cause any modified files to carry prominent notices
|
|
17185
|
+
stating that You changed the files; and
|
|
17186
|
+
|
|
17187
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
17188
|
+
that You distribute, all copyright, patent, trademark, and
|
|
17189
|
+
attribution notices from the Source form of the Work,
|
|
17190
|
+
excluding those notices that do not pertain to any part of
|
|
17191
|
+
the Derivative Works; and
|
|
17192
|
+
|
|
17193
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
17194
|
+
distribution, then any Derivative Works that You distribute must
|
|
17195
|
+
include a readable copy of the attribution notices contained
|
|
17196
|
+
within such NOTICE file, excluding those notices that do not
|
|
17197
|
+
pertain to any part of the Derivative Works, in at least one
|
|
17198
|
+
of the following places: within a NOTICE text file distributed
|
|
17199
|
+
as part of the Derivative Works; within the Source form or
|
|
17200
|
+
documentation, if provided along with the Derivative Works; or,
|
|
17201
|
+
within a display generated by the Derivative Works, if and
|
|
17202
|
+
wherever such third-party notices normally appear. The contents
|
|
17203
|
+
of the NOTICE file are for informational purposes only and
|
|
17204
|
+
do not modify the License. You may add Your own attribution
|
|
17205
|
+
notices within Derivative Works that You distribute, alongside
|
|
17206
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
17207
|
+
that such additional attribution notices cannot be construed
|
|
17208
|
+
as modifying the License.
|
|
17209
|
+
|
|
17210
|
+
You may add Your own copyright statement to Your modifications and
|
|
17211
|
+
may provide additional or different license terms and conditions
|
|
17212
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
17213
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
17214
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
17215
|
+
the conditions stated in this License.
|
|
17216
|
+
|
|
17217
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
17218
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
17219
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
17220
|
+
this License, without any additional terms or conditions.
|
|
17221
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
17222
|
+
the terms of any separate license agreement you may have executed
|
|
17223
|
+
with Licensor regarding such Contributions.
|
|
17224
|
+
|
|
17225
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
17226
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
17227
|
+
except as required for reasonable and customary use in describing the
|
|
17228
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
17229
|
+
|
|
17230
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
17231
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
17232
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
17233
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
17234
|
+
implied, including, without limitation, any warranties or conditions
|
|
17235
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
17236
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
17237
|
+
appropriateness of using or redistributing the Work and assume any
|
|
17238
|
+
risks associated with Your exercise of permissions under this License.
|
|
17239
|
+
|
|
17240
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
17241
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
17242
|
+
unless required by applicable law (such as deliberate and grossly
|
|
17243
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
17244
|
+
liable to You for damages, including any direct, indirect, special,
|
|
17245
|
+
incidental, or consequential damages of any character arising as a
|
|
17246
|
+
result of this License or out of the use or inability to use the
|
|
17247
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
17248
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
17249
|
+
other commercial damages or losses), even if such Contributor
|
|
17250
|
+
has been advised of the possibility of such damages.
|
|
17251
|
+
|
|
17252
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
17253
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
17254
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
17255
|
+
or other liability obligations and/or rights consistent with this
|
|
17256
|
+
License. However, in accepting such obligations, You may act only
|
|
17257
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
17258
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
17259
|
+
defend, and hold each Contributor harmless for any liability
|
|
17260
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
17261
|
+
of your accepting any such warranty or additional liability.
|
|
17262
|
+
|
|
17263
|
+
END OF TERMS AND CONDITIONS
|
|
17264
|
+
|
|
17265
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
17266
|
+
|
|
17267
|
+
To apply the Apache License to your work, attach the following
|
|
17268
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
17269
|
+
replaced with your own identifying information. (Don't include
|
|
17270
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
17271
|
+
comment syntax for the file format. We also recommend that a
|
|
17272
|
+
file or class name and description of purpose be included on the
|
|
17273
|
+
same "printed page" as the copyright notice for easier
|
|
17274
|
+
identification within third-party archives.
|
|
17275
|
+
|
|
17276
|
+
Copyright [yyyy] [name of copyright owner]
|
|
17277
|
+
|
|
17278
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
17279
|
+
you may not use this file except in compliance with the License.
|
|
17280
|
+
You may obtain a copy of the License at
|
|
17281
|
+
|
|
17282
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
17283
|
+
|
|
17284
|
+
Unless required by applicable law or agreed to in writing, software
|
|
17285
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
17286
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17287
|
+
See the License for the specific language governing permissions and
|
|
17288
|
+
limitations under the License.
|
|
17289
|
+
|
|
17290
|
+
|
|
17291
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17292
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
17293
|
+
in the Software without restriction, including without limitation the rights
|
|
17294
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17295
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17296
|
+
furnished to do so, subject to the following conditions:
|
|
17297
|
+
|
|
17298
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17299
|
+
copies or substantial portions of the Software.
|
|
17300
|
+
|
|
17301
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17302
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17303
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17304
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17305
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
17306
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
17307
|
+
SOFTWARE.
|
|
17308
|
+
|
|
17309
|
+
|
|
17310
|
+
|
|
17311
|
+
smallvec 1.16.3 — MIT OR Apache-2.0
|
|
17091
17312
|
https://github.com/servo/rust-smallvec
|
|
17092
17313
|
|
|
17093
17314
|
Apache License
|
|
@@ -18291,7 +18512,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
18291
18512
|
|
|
18292
18513
|
|
|
18293
18514
|
|
|
18294
|
-
syn 3.0.
|
|
18515
|
+
syn 3.0.9 — MIT OR Apache-2.0
|
|
18295
18516
|
https://github.com/dtolnay/syn
|
|
18296
18517
|
|
|
18297
18518
|
Apache License
|
|
@@ -18732,7 +18953,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
18732
18953
|
|
|
18733
18954
|
|
|
18734
18955
|
|
|
18735
|
-
thiserror 2.0.
|
|
18956
|
+
thiserror 2.0.21 — MIT OR Apache-2.0
|
|
18736
18957
|
https://github.com/dtolnay/thiserror
|
|
18737
18958
|
|
|
18738
18959
|
Apache License
|
|
@@ -18939,7 +19160,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
18939
19160
|
|
|
18940
19161
|
|
|
18941
19162
|
|
|
18942
|
-
thiserror-impl 2.0.
|
|
19163
|
+
thiserror-impl 2.0.21 — MIT OR Apache-2.0
|
|
18943
19164
|
https://github.com/dtolnay/thiserror
|
|
18944
19165
|
|
|
18945
19166
|
Apache License
|
|
@@ -20768,7 +20989,7 @@ SOFTWARE.
|
|
|
20768
20989
|
|
|
20769
20990
|
|
|
20770
20991
|
|
|
20771
|
-
unicode-ident 1.0.
|
|
20992
|
+
unicode-ident 1.0.27 — (MIT OR Apache-2.0) AND Unicode-3.0
|
|
20772
20993
|
https://github.com/dtolnay/unicode-ident
|
|
20773
20994
|
|
|
20774
20995
|
Apache License
|
|
@@ -23307,7 +23528,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
23307
23528
|
|
|
23308
23529
|
|
|
23309
23530
|
|
|
23310
|
-
zerocopy 0.8.
|
|
23531
|
+
zerocopy 0.8.63 — BSD-2-Clause OR Apache-2.0 OR MIT
|
|
23311
23532
|
https://github.com/google/zerocopy
|
|
23312
23533
|
|
|
23313
23534
|
Apache License
|
|
@@ -23569,7 +23790,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
23569
23790
|
|
|
23570
23791
|
|
|
23571
23792
|
|
|
23572
|
-
zerocopy-derive 0.8.
|
|
23793
|
+
zerocopy-derive 0.8.63 — BSD-2-Clause OR Apache-2.0 OR MIT
|
|
23573
23794
|
https://github.com/google/zerocopy
|
|
23574
23795
|
|
|
23575
23796
|
Apache License
|
|
@@ -23831,7 +24052,7 @@ DEALINGS IN THE SOFTWARE.
|
|
|
23831
24052
|
|
|
23832
24053
|
|
|
23833
24054
|
|
|
23834
|
-
zeroize 1.9.
|
|
24055
|
+
zeroize 1.9.1 — Apache-2.0 OR MIT
|
|
23835
24056
|
https://github.com/RustCrypto/utils
|
|
23836
24057
|
|
|
23837
24058
|
|
data/docs/github-setup.md
CHANGED
|
@@ -9,7 +9,7 @@ RubyGems settings a maintainer must enable. These instructions prepare
|
|
|
9
9
|
The repository includes an MIT license, contributor and security guides, issue
|
|
10
10
|
forms, a pull-request template, CODEOWNERS, Dependabot, CodeQL, dependency review,
|
|
11
11
|
and build/release workflows. Actions are pinned to full commit SHAs; Dependabot
|
|
12
|
-
proposes updates. CI runs on pull requests,
|
|
12
|
+
proposes updates. CI runs on pull requests, master pushes and a weekly schedule.
|
|
13
13
|
PR jobs do not receive publishing credentials. Checkout does not persist tokens.
|
|
14
14
|
|
|
15
15
|
## Configure GitHub after an authorized push
|
|
@@ -20,7 +20,7 @@ PR jobs do not receive publishing credentials. Checkout does not persist tokens.
|
|
|
20
20
|
graph, Dependabot alerts, secret scanning and push protection where available.
|
|
21
21
|
CodeQL is provided as an advanced workflow for Ruby, Rust and GitHub Actions; do not also enable
|
|
22
22
|
CodeQL default setup.
|
|
23
|
-
3. After the first successful run, protect `
|
|
23
|
+
3. After the first successful run, protect `master` with a ruleset requiring pull
|
|
24
24
|
requests, one approving review, resolved conversations, current branches and
|
|
25
25
|
the `CI required`, CodeQL matrix and dependency-review checks. Select the
|
|
26
26
|
actual check names from GitHub. Block deletion and force pushes. Require code
|
|
@@ -28,26 +28,28 @@ PR jobs do not receive publishing credentials. Checkout does not persist tokens.
|
|
|
28
28
|
pull requests can be reviewed. Do not silently bypass review to unblock them.
|
|
29
29
|
4. Allow only reviewed Actions, keep the default workflow token read-only, and
|
|
30
30
|
disable Actions creating or approving pull requests. Keep fork approval on.
|
|
31
|
-
5. Create environment `rubygems`, restrict deployment to `
|
|
31
|
+
5. Create environment `rubygems`, restrict deployment to `v*` tags, and configure a
|
|
32
32
|
trusted maintainer as required reviewer with self-review prevented. Confirm
|
|
33
33
|
an eligible second reviewer exists before enabling this requirement.
|
|
34
34
|
6. Configure RubyGems trusted publishing exactly as [releasing](releasing.md)
|
|
35
35
|
specifies. Do not store a long-lived publishing key in repository secrets.
|
|
36
36
|
|
|
37
|
-
The
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
The authorized initial history consolidation is complete. Remote branch
|
|
38
|
+
`archive/pre-0.1.0-squash` preserves the old consumer pin. The `rubygems`
|
|
39
|
+
environment deploys only from `v*` tags (it allowed the default branch for the manual 0.1.0
|
|
40
|
+
release). RubyGems trusted publishing successfully published 0.1.0. A second reviewer remains a
|
|
41
|
+
separate repository setup task.
|
|
42
|
+
Never force-push just to make CI pass.
|
|
41
43
|
|
|
42
44
|
## Release evidence
|
|
43
45
|
|
|
44
|
-
`CI required` fails if any Ruby test, package build,
|
|
46
|
+
`CI required` fails if any Ruby test, package build, package installation or
|
|
45
47
|
audit fails or is skipped. Linux packages are built against glibc 2.28 and checked
|
|
46
48
|
for newer symbol requirements. Compatibility jobs install the same artifact,
|
|
47
|
-
not a newly rebuilt library.
|
|
49
|
+
not a newly rebuilt library.
|
|
48
50
|
|
|
49
|
-
The
|
|
50
|
-
for the exact
|
|
51
|
+
The tag-triggered release workflow accepts only a successful CI run from this
|
|
52
|
+
repository, for the exact master commit the tag points to. It validates package names, versions, platforms and
|
|
51
53
|
license files before trusted publication, and records an attestation for the
|
|
52
54
|
promotion workflow. Keep the successful CI URL with release notes. GitHub
|
|
53
55
|
settings, hosted matrix success and RubyGems setup must be confirmed separately;
|
data/docs/installation.md
CHANGED
|
@@ -5,49 +5,33 @@ source and native packages, and how to check the installed renderer.
|
|
|
5
5
|
|
|
6
6
|
## Requirements
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
macOS ARM64. The core has no Rails dependency. JRuby, Windows, musl and other
|
|
10
|
-
architectures are not qualified release targets.
|
|
8
|
+
CRuby 3.3 or later. Rails is optional.
|
|
11
9
|
|
|
12
|
-
| Package |
|
|
10
|
+
| Package | Needs |
|
|
13
11
|
| --- | --- |
|
|
14
|
-
|
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
12
|
+
| `arm64-darwin` | macOS 15 or later on Apple Silicon. |
|
|
13
|
+
| `x86_64-linux-gnu` | Linux AMD64 with glibc 2.28 or later. |
|
|
14
|
+
| `ruby` source gem or Git checkout | Rust/Cargo 1.94.0, a C linker, make and network access to the pinned Git and crates.io dependencies. |
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
Native gems need no compiler and no system Forme library.
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
CPU target. CI rejects symbols requiring glibc newer than 2.28. The same gem
|
|
22
|
-
is installed and renders a PDF in UBI 8, 9 and 10, Ubuntu 24.04 and 26.04,
|
|
23
|
-
and current Arch Linux, without Rust installed. UBI testing exercises the
|
|
24
|
-
RHEL userspace baseline; it is not a certification of every RHEL deployment.
|
|
25
|
-
Use a Ruby 3.2+ installation even when a distribution defaults to older Ruby.
|
|
18
|
+
## Install from GitHub
|
|
26
19
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
identical pagination for every font and document.
|
|
20
|
+
Download the matching native gem and `SHA256SUMS` from the
|
|
21
|
+
[0.2.0 release](https://github.com/clearstackio/forme-ruby/releases/tag/v0.2.0).
|
|
22
|
+
Check its digest with `shasum -a 256 <filename>` against the checksum file, then
|
|
23
|
+
run `gem install ./<filename>`.
|
|
32
24
|
|
|
33
|
-
## Install
|
|
25
|
+
## Install from RubyGems
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
[README](../README.md) and run `bundle install`. Commit `Gemfile.lock` so builds
|
|
37
|
-
use a reviewed revision. Compilation happens during installation; no compiler
|
|
38
|
-
or dependency download runs during `require` or rendering.
|
|
39
|
-
|
|
40
|
-
## Install a released version later
|
|
41
|
-
|
|
42
|
-
After publication is confirmed, use:
|
|
27
|
+
Add to your Gemfile and run `bundle install`:
|
|
43
28
|
|
|
44
29
|
```ruby
|
|
45
|
-
gem "forme-ruby", "~> 0.
|
|
30
|
+
gem "forme-ruby", "~> 0.2.0", require: "forme_pdf"
|
|
46
31
|
```
|
|
47
32
|
|
|
48
|
-
Bundler selects a matching native package where available
|
|
49
|
-
|
|
50
|
-
Native packages load their own shared library without a system Forme install.
|
|
33
|
+
Bundler selects a matching native package where available and otherwise
|
|
34
|
+
installs the source gem, which needs the build tools above.
|
|
51
35
|
|
|
52
36
|
## Verify the installation
|
|
53
37
|
|
data/docs/releasing.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Preparing and Releasing Forme Ruby
|
|
2
2
|
|
|
3
3
|
After reading this guide, you will know how to qualify source/native artifacts
|
|
4
|
-
and which steps publish externally. **
|
|
4
|
+
and which steps publish externally. **Published versions are listed in the [changelog](../CHANGELOG.md).**
|
|
5
5
|
Local preparation does not authorize a push, tag or RubyGems publication.
|
|
6
6
|
|
|
7
7
|
## Prepare locally
|
|
@@ -18,22 +18,20 @@ Local preparation does not authorize a push, tag or RubyGems publication.
|
|
|
18
18
|
Previously successful CI does not qualify the new commit. Consumers must not
|
|
19
19
|
lock to an unpublished SHA. Do not change remote history during local preparation.
|
|
20
20
|
|
|
21
|
-
## Qualify the release commit
|
|
21
|
+
## Qualify the release commit
|
|
22
22
|
|
|
23
23
|
After a separately authorized GitHub push, require successful `ci.yml` for that
|
|
24
|
-
exact `
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
artifact renders on macOS 15/26. See [installation](installation.md). Review the three intended artifacts: `ruby`,
|
|
28
|
-
`arm64-darwin`, and `x86_64-linux-gnu`. No Windows or musl binary is claimed.
|
|
24
|
+
exact `master` commit, including every package installation job. Review the three
|
|
25
|
+
intended artifacts: `ruby`, `arm64-darwin` and `x86_64-linux-gnu`. The
|
|
26
|
+
[installation requirements](installation.md) must match what CI qualifies.
|
|
29
27
|
|
|
30
|
-
The
|
|
31
|
-
|
|
32
|
-
|
|
28
|
+
The initial history consolidation is complete. Branch `archive/pre-0.1.0-squash`
|
|
29
|
+
preserves the earlier history and existing consumer pin. Future releases should
|
|
30
|
+
use normal commits without rewriting published history.
|
|
33
31
|
|
|
34
32
|
Review [GitHub repository setup](github-setup.md) before enabling releases.
|
|
35
33
|
|
|
36
|
-
## Configure trusted publishing
|
|
34
|
+
## Configure trusted publishing
|
|
37
35
|
|
|
38
36
|
Under the `ajaya` RubyGems account, configure a pending publisher for the new gem:
|
|
39
37
|
|
|
@@ -52,32 +50,48 @@ for setup. No long-lived RubyGems API key is required by this workflow.
|
|
|
52
50
|
|
|
53
51
|
## Publish only with explicit authorization
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
53
|
+
Pushing a `v*` tag publishes. `release.yml` runs on the tag and:
|
|
54
|
+
|
|
55
|
+
1. checks the tag equals `v` plus `FormePDF::VERSION`;
|
|
56
|
+
2. finds the successful `ci.yml` run on `master` for the tagged commit and
|
|
57
|
+
downloads its three packages, rebuilding nothing;
|
|
58
|
+
3. validates names, versions, platforms, license files and build hooks;
|
|
59
|
+
4. records a GitHub build-provenance attestation for those packages;
|
|
60
|
+
5. creates the GitHub release with the packages and `SHA256SUMS`, or, when the
|
|
61
|
+
release already exists, requires its packages to match byte-for-byte;
|
|
62
|
+
6. signs each package with Sigstore and pushes it to RubyGems through trusted
|
|
63
|
+
publishing with that attestation, then waits until RubyGems serves it.
|
|
64
|
+
|
|
65
|
+
This follows the RubyGems [trusted publishing release guide](https://guides.rubygems.org/trusted-publishing/releasing-gems/)
|
|
66
|
+
and our other gems:
|
|
67
|
+
|
|
68
|
+
1. Update `VERSION` in `lib/forme_pdf/version.rb`.
|
|
69
|
+
2. Move the Unreleased CHANGELOG entries under the new version and date.
|
|
70
|
+
3. Commit to `master` and wait for CI to pass on that commit.
|
|
71
|
+
4. Tag and push: `git tag vX.Y.Z && git push origin master vX.Y.Z`.
|
|
72
|
+
|
|
73
|
+
Treat the tag push as publication, not a dry run. Afterward, verify all three
|
|
74
|
+
platforms and their attestations on RubyGems and install from RubyGems in a clean
|
|
75
|
+
environment. Partial publication cannot be overwritten: inspect which platforms
|
|
76
|
+
succeeded before deciding how to recover. Update consumer Gemfiles only after
|
|
77
|
+
the version is available and qualified.
|
|
78
|
+
|
|
79
|
+
## Release evidence
|
|
80
|
+
|
|
81
|
+
[GitHub release 0.1.0](https://github.com/clearstackio/forme-ruby/releases/tag/v0.1.0)
|
|
82
|
+
contains the source gem, both native gems and SHA-256 checksums from
|
|
83
|
+
[CI run 35415089757](https://github.com/clearstackio/forme-ruby/actions/runs/35415089757).
|
|
84
|
+
Every job passed on commit `266628a20a0a52bad222c8f8e6d2277b08122896`, including
|
|
85
|
+
every package installation job. CodeQL also
|
|
86
|
+
passed. Packages were downloaded and validated before release; the macOS native
|
|
87
|
+
gem was additionally installed and rendered locally outside the checkout.
|
|
88
|
+
|
|
89
|
+
The GitHub `rubygems` environment exists.
|
|
90
|
+
[Registry publication run 35415885728](https://github.com/clearstackio/forme-ruby/actions/runs/35415885728)
|
|
91
|
+
succeeded through trusted publishing for all three platforms. Downloads from
|
|
92
|
+
RubyGems matched the CI and GitHub release artifacts byte-for-byte. A fresh
|
|
93
|
+
macOS ARM registry installation loaded the native library and rendered a PDF.
|
|
94
|
+
|
|
95
|
+
The publisher is configured; do not recreate it for subsequent versions.
|
|
96
|
+
A published version must never be pushed again. Use a new
|
|
97
|
+
version for future releases and qualify its packages before publication.
|
data/docs/rendering.md
CHANGED
|
@@ -20,8 +20,22 @@ ASCII-8BIT String. Always write with `File.binwrite`.
|
|
|
20
20
|
|
|
21
21
|
Forme supports a subset of HTML and print CSS, not browser layout or JavaScript.
|
|
22
22
|
Use dedicated print styles and inspect the resulting pages. Inline CSS or pass
|
|
23
|
-
`css:`; embed images as data URIs. The binding does not fetch remote stylesheets
|
|
24
|
-
|
|
23
|
+
`css:`; embed images as data URIs. The binding does not fetch remote stylesheets,
|
|
24
|
+
fonts or images.
|
|
25
|
+
|
|
26
|
+
Image sources starting with `/`, `./` or `../` are files. They are omitted with a
|
|
27
|
+
warning unless you pass `image_root:`, a directory that must contain them:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
pdf = FormePDF.render_html(
|
|
31
|
+
'<img src="./logo.png" width="120">',
|
|
32
|
+
image_root: Rails.root.join("app/assets/images")
|
|
33
|
+
)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Relative paths resolve against `image_root`; absolute paths and symlinks must
|
|
37
|
+
resolve inside it. Each file must be a regular PNG, JPEG or WebP file of at most
|
|
38
|
+
64 MiB. Warnings name the reason, never the path.
|
|
25
39
|
|
|
26
40
|
Supply TTF font bytes explicitly:
|
|
27
41
|
|
|
@@ -32,9 +46,10 @@ pdf = FormePDF.render_html(
|
|
|
32
46
|
)
|
|
33
47
|
```
|
|
34
48
|
|
|
35
|
-
`css:` and `
|
|
36
|
-
`family`, `data`, `weight` (
|
|
37
|
-
|
|
49
|
+
`css:`, `fonts:` and `image_root:` are the supported rendering keywords. Font
|
|
50
|
+
entries accept `family`, `data`, `weight` (an Integer from 1 to 1000, default
|
|
51
|
+
400) and `italic` (true or false, default false). Unknown or invalid options
|
|
52
|
+
raise `ArgumentError`. Register the weights/styles your document needs and check the PDF.
|
|
38
53
|
|
|
39
54
|
## Inspect diagnostics
|
|
40
55
|
|
|
@@ -52,12 +67,16 @@ send sensitive document content or diagnostics to public logs.
|
|
|
52
67
|
## Handle errors and concurrency
|
|
53
68
|
|
|
54
69
|
`FormePDF::LoadError` and `FormePDF::RenderError` inherit `FormePDF::Error`.
|
|
55
|
-
Invalid caller arguments
|
|
70
|
+
Invalid caller arguments, including text that is not valid UTF-8, raise
|
|
71
|
+
`ArgumentError`. Documents nested more than 512 elements deep raise
|
|
72
|
+
`FormePDF::RenderError` instead of rendering. Avoid
|
|
56
73
|
rescuing everything and returning an HTML success response as if it were a PDF.
|
|
57
74
|
|
|
58
75
|
Each render owns independent native result storage. Ruby copies the bytes and
|
|
59
76
|
frees that result even when copying or decoding fails. Native calls release the
|
|
60
|
-
Ruby lock
|
|
77
|
+
Ruby lock and render on a native thread with its own 64 MiB stack, so deep
|
|
78
|
+
documents behave the same on Puma, Sidekiq and `Thread.new` threads as on the
|
|
79
|
+
main thread. Concurrent callers do not share output buffers. Ruby interruption is
|
|
61
80
|
masked during native ownership, so thread cancellation is not a render deadline.
|
|
62
81
|
Use process-level resource limits for large or hostile inputs. The API is not a
|
|
63
82
|
sandbox and exposes no per-render timeout.
|
data/docs/security-exceptions.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Reviewing Native Dependency Advisories
|
|
2
2
|
|
|
3
3
|
After reading this guide, you will understand the current audit exceptions and
|
|
4
|
-
when they must be reconsidered. Review date: 2026-
|
|
4
|
+
when they must be reconsidered. Review date: 2026-10-20.
|
|
5
5
|
|
|
6
6
|
## Scope
|
|
7
7
|
|
|
8
8
|
These exceptions acknowledge vulnerable dependencies; they do not patch them.
|
|
9
|
-
They apply only to Forme revision `
|
|
9
|
+
They apply only to Forme 0.28.0 revision `b97dc101b705ea5d7fea6fb1b20fabfb5bd2d63d`,
|
|
10
10
|
the locked dependency graph and the HTML-only Ruby API. Rendering is not a
|
|
11
11
|
sandbox for arbitrary HTML. See [SECURITY](../SECURITY.md).
|
|
12
12
|
|
|
@@ -18,8 +18,11 @@ sandbox for arbitrary HTML. See [SECURITY](../SECURITY.md).
|
|
|
18
18
|
|
|
19
19
|
## Verify the boundaries
|
|
20
20
|
|
|
21
|
-
`ext/forme_pdf/src/lib.rs` accepts only CSS and
|
|
22
|
-
and
|
|
21
|
+
`ext/forme_pdf/src/lib.rs` accepts only CSS, fonts and an image root, rejects
|
|
22
|
+
unknown options, and reproduces `forme_pdf_html::render_html` with default HTML
|
|
23
|
+
options: `html_to_document`, then `forme::render_with_options`. Between the two
|
|
24
|
+
it replaces file image sources with data URIs or empties them, so the engine
|
|
25
|
+
never reads files itself; image bytes still reach only the image loader. In the pinned
|
|
23
26
|
upstream tree, `html/src/dom.rs` parses with html5ever. `html/src/map.rs` has no
|
|
24
27
|
`NodeKind::Svg` construction and initializes `certification: None`.
|
|
25
28
|
`engine/src/image_loader.rs` accepts JPEG, PNG and WebP, so an SVG image cannot
|
|
Binary file
|
data/lib/forme_pdf/rails.rb
CHANGED
|
@@ -5,6 +5,8 @@ require "forme_pdf"
|
|
|
5
5
|
module FormePDF
|
|
6
6
|
# Explicitly include this module in an ActionController; no Railtie or middleware.
|
|
7
7
|
module Rails
|
|
8
|
+
private
|
|
9
|
+
|
|
8
10
|
# Render a caller-selected Rails template into binary PDF bytes.
|
|
9
11
|
# The controller retains responsibility for authorization and send_data.
|
|
10
12
|
def render_forme_pdf(template:, layout:, locals: {}, **options)
|
data/lib/forme_pdf/renderer.rb
CHANGED
|
@@ -6,19 +6,12 @@ module FormePDF
|
|
|
6
6
|
# One native render call with caller-owned input and independently owned output.
|
|
7
7
|
class Renderer
|
|
8
8
|
# Return PDF bytes, renderer warnings and layout pass count.
|
|
9
|
-
def self.call(html, css: nil, fonts: [])
|
|
9
|
+
def self.call(html, css: nil, fonts: [], image_root: nil)
|
|
10
10
|
fail ArgumentError, "HTML must be a String" unless html.is_a?(String)
|
|
11
|
-
html = html
|
|
12
|
-
html.force_encoding(Encoding::UTF_8) if html.encoding == Encoding::BINARY
|
|
13
|
-
fail ArgumentError, "HTML must be valid UTF-8" unless html.valid_encoding?
|
|
14
|
-
html = html.encode(Encoding::UTF_8)
|
|
11
|
+
html = utf8(html, "HTML")
|
|
15
12
|
fail ArgumentError, "CSS must be a String or nil" unless css.nil? || css.is_a?(String)
|
|
16
13
|
fail ArgumentError, "fonts must be an Array" unless fonts.is_a?(Array)
|
|
17
|
-
options = JSON.generate(css: css, fonts: fonts.map { |font|
|
|
18
|
-
fail ArgumentError, "font must contain family and data" unless font.is_a?(Hash) && font[:family].is_a?(String) && font[:data].is_a?(String)
|
|
19
|
-
fail ArgumentError, "unknown font option" unless (font.keys - %i[family data weight italic]).empty?
|
|
20
|
-
{family: font.fetch(:family), data: Base64.strict_encode64(font.fetch(:data)), weight: font.fetch(:weight, 400), italic: font.fetch(:italic, false)}
|
|
21
|
-
})
|
|
14
|
+
options = JSON.generate(css: css && utf8(css, "CSS"), fonts: fonts.map { |font| font_option(font) }, image_root: image_root_option(image_root))
|
|
22
15
|
Native.load!
|
|
23
16
|
input = FFI::MemoryPointer.from_string(html)
|
|
24
17
|
opts = FFI::MemoryPointer.from_string(options)
|
|
@@ -36,5 +29,32 @@ module FormePDF
|
|
|
36
29
|
Native.forme_result_destroy(result) if result && !result.null?
|
|
37
30
|
end
|
|
38
31
|
end
|
|
32
|
+
|
|
33
|
+
# Binary text is read as UTF-8; other valid encodings are transcoded.
|
|
34
|
+
def self.utf8(text, name)
|
|
35
|
+
text = text.dup
|
|
36
|
+
text.force_encoding(Encoding::UTF_8) if text.encoding == Encoding::BINARY
|
|
37
|
+
fail ArgumentError, "#{name} must be valid UTF-8" unless text.valid_encoding?
|
|
38
|
+
text.encode(Encoding::UTF_8)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.font_option(font)
|
|
42
|
+
fail ArgumentError, "font must contain family and data" unless font.is_a?(Hash) && font[:family].is_a?(String) && font[:data].is_a?(String)
|
|
43
|
+
fail ArgumentError, "unknown font option" unless (font.keys - %i[family data weight italic]).empty?
|
|
44
|
+
weight = font.fetch(:weight, 400)
|
|
45
|
+
italic = font.fetch(:italic, false)
|
|
46
|
+
fail ArgumentError, "font weight must be an Integer from 1 to 1000" unless weight.is_a?(Integer) && weight.between?(1, 1000)
|
|
47
|
+
fail ArgumentError, "font italic must be true or false" unless [true, false].include?(italic)
|
|
48
|
+
{family: utf8(font[:family], "font family"), data: Base64.strict_encode64(font[:data]), weight: weight, italic: italic}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.image_root_option(root)
|
|
52
|
+
return if root.nil?
|
|
53
|
+
fail ArgumentError, "image_root must be a String or Pathname" unless root.is_a?(String) || root.respond_to?(:to_path)
|
|
54
|
+
root = File.expand_path(root.respond_to?(:to_path) ? root.to_path : root)
|
|
55
|
+
fail ArgumentError, "image_root must be an existing directory" unless File.directory?(root)
|
|
56
|
+
utf8(root, "image_root")
|
|
57
|
+
end
|
|
58
|
+
private_class_method :utf8, :font_option, :image_root_option
|
|
39
59
|
end
|
|
40
60
|
end
|
data/lib/forme_pdf/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: forme-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: x86_64-linux-gnu
|
|
6
6
|
authors:
|
|
7
7
|
- Ajaya Agrawalla
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-10-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|
|
@@ -47,7 +47,7 @@ dependencies:
|
|
|
47
47
|
version: '2.0'
|
|
48
48
|
- - "<"
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
|
-
version: '
|
|
50
|
+
version: '4'
|
|
51
51
|
type: :runtime
|
|
52
52
|
prerelease: false
|
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -57,7 +57,7 @@ dependencies:
|
|
|
57
57
|
version: '2.0'
|
|
58
58
|
- - "<"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '4'
|
|
61
61
|
description: Independent Ruby bindings for the Rust Forme HTML renderer. No browser,
|
|
62
62
|
Node.js, WebAssembly or separate rendering service.
|
|
63
63
|
email:
|
|
@@ -95,9 +95,9 @@ licenses:
|
|
|
95
95
|
- MIT
|
|
96
96
|
metadata:
|
|
97
97
|
source_code_uri: https://github.com/clearstackio/forme-ruby
|
|
98
|
-
documentation_uri: https://github.com/clearstackio/forme-ruby/blob/
|
|
98
|
+
documentation_uri: https://github.com/clearstackio/forme-ruby/blob/master/docs/README.md
|
|
99
99
|
bug_tracker_uri: https://github.com/clearstackio/forme-ruby/issues
|
|
100
|
-
changelog_uri: https://github.com/clearstackio/forme-ruby/blob/
|
|
100
|
+
changelog_uri: https://github.com/clearstackio/forme-ruby/blob/master/CHANGELOG.md
|
|
101
101
|
rubygems_mfa_required: 'true'
|
|
102
102
|
allowed_push_host: https://rubygems.org
|
|
103
103
|
post_install_message:
|
|
@@ -108,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
108
108
|
requirements:
|
|
109
109
|
- - ">="
|
|
110
110
|
- !ruby/object:Gem::Version
|
|
111
|
-
version: '3.
|
|
111
|
+
version: '3.3'
|
|
112
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
113
|
requirements:
|
|
114
114
|
- - ">="
|