pdfrb 0.7.21 → 0.7.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fede6fc181df1691732c051b8339ee2bded64c7f393691fd9dd5b0f151082e9
4
- data.tar.gz: a602406104c68a47a6d5ddca09fedaa12831528c9cb603a9dab0a123f171004f
3
+ metadata.gz: 06bcf184cd873b50571015f1848d43e3692c041d98bd278237b86d06f79d14c0
4
+ data.tar.gz: 768be65b94d3a987e83278429a765563974ee95cd7125ca05d9a0b9a303074c8
5
5
  SHA512:
6
- metadata.gz: 7822801383bb40e5d381f4b10801de93b3271304ff2b748ca6a2e1182de9620c5694920c1ddfa4d4bfceb15033fa6b6e069addb76fcdc1721c3ccde104da226d
7
- data.tar.gz: 94a2bbcb98addcb843be49ffdce5a75e693f34f7384106c8036f6247b66751c760176a55b55b6e407d24935ff26f1700512da96a827ef2d0e02ca70e8a9e48e2
6
+ metadata.gz: 912a23d9b0d4e2b122ea255214dc4d443ee0233d592ed483cea6a12c5ff60ec52db59a183edb8790b8b4acc50badfef728da2de56028fef8df5c58fd507e0d04
7
+ data.tar.gz: ec728839ee2d5db65428b681aa0bc41dd7613569e3baca4adea7e197e5388f64440342547ef2e538b2568a3bab3bce12f0ec584a6165b867f36bf20c676941b6
data/docs/SEMVER.md ADDED
@@ -0,0 +1,60 @@
1
+ # Pdfrb Semver Policy
2
+
3
+ ## Version Scheme
4
+
5
+ Pdfrb follows [Semantic Versioning 2.0.0](https://semver.org/).
6
+
7
+ - **MAJOR** (X.0.0): Breaking API changes. Existing code that depends
8
+ on pdfrb may need updates.
9
+ - **MINOR** (0.X.0): New features, backward-compatible. Existing code
10
+ continues to work.
11
+ - **PATCH** (0.0.X): Bug fixes, performance improvements, doc updates.
12
+ No new features, no breaking changes.
13
+
14
+ ## Current Phase: 0.x (pre-1.0)
15
+
16
+ During 0.x development, the API is not yet frozen. Minor version bumps
17
+ MAY include breaking changes, but they will be documented in
18
+ CHANGELOG.md with migration notes.
19
+
20
+ The goal is to reach 1.0 once:
21
+ - The public API is stable (Document, Writer, Canvas, Conformance).
22
+ - Round-trip is proven against a broad fixture corpus.
23
+ - All P0 TODOs are complete.
24
+ - veraPDF cross-check passes on PDF/A output.
25
+
26
+ ## Deprecation Policy
27
+
28
+ 1. A deprecated API is marked with YARD `@deprecated` tags and emits a
29
+ `Warning.warn` on first use.
30
+ 2. The deprecation period lasts at least one minor version.
31
+ 3. Removal happens in the next major version bump.
32
+
33
+ ## Release Checklist
34
+
35
+ - [ ] All specs pass: `bundle exec rake`
36
+ - [ ] Rubocop clean: `bundle exec rubocop`
37
+ - [ ] Coverage maintained or improved: `COVERAGE=1 bundle exec rspec`
38
+ - [ ] CHANGELOG.md updated with all changes
39
+ - [ ] Version bumped in `lib/pdfrb/version.rb`
40
+ - [ ] Git tag created: `vX.Y.Z`
41
+ - [ ] Gem pushed: `gem build && gem push`
42
+
43
+ ## Public API Stability Contract
44
+
45
+ The following are considered **stable** (subject to semver guarantees):
46
+
47
+ - `Pdfrb::Document` — top-level facade (new, open, write, pages, fonts, etc.)
48
+ - `Pdfrb::Writer` — serialization
49
+ - `Pdfrb::Serializer` — COS-to-bytes
50
+ - `Pdfrb::Canvas` — content-stream drawing
51
+ - `Pdfrb::Compare` — semantic diff
52
+ - `Pdfrb::Conformance` — PDF/A and PDF/UA validators
53
+ - `Pdfrb::DigitalSignature` — signing and verification
54
+ - `Pdfrb::Error` hierarchy
55
+
56
+ The following are **internal** (may change without notice):
57
+
58
+ - `Pdfrb::Source::*` — tokenizer/parser internals
59
+ - `Pdfrb::Model::Cos::*` — COS implementation details
60
+ - `Pdfrb::Arlington::*` — predicate evaluation internals
data/docs/USAGE.md ADDED
@@ -0,0 +1,173 @@
1
+ # Pdfrb Usage Guide
2
+
3
+ A cookbook of common PDF tasks using pdfrb.
4
+
5
+ ## Creating a PDF
6
+
7
+ ```ruby
8
+ require "pdfrb"
9
+
10
+ doc = Pdfrb::Document.new
11
+ font = doc.fonts.add("Helvetica")
12
+ page = doc.pages.add
13
+ page.canvas.text("Hello, World!", at: [72, 720], font: font, size: 24)
14
+
15
+ doc.write("hello.pdf")
16
+ ```
17
+
18
+ ## Reading a PDF
19
+
20
+ ```ruby
21
+ doc = Pdfrb.open("input.pdf")
22
+ puts "Pages: #{doc.pages.count}"
23
+ doc.pages.each do |page|
24
+ text = Pdfrb::Task::ExtractText.call_single_page(page)
25
+ puts text
26
+ end
27
+ ```
28
+
29
+ ## Drawing on a Canvas
30
+
31
+ ```ruby
32
+ doc = Pdfrb::Document.new
33
+ page = doc.pages.add
34
+ font = doc.fonts.add("Helvetica")
35
+
36
+ page.canvas.tap do |c|
37
+ c.text("Title", at: [72, 720], font: font, size: 18)
38
+ c.rectangle(point: [72, 700], width: 200, height: 50)
39
+ c.stroke
40
+ c.line(from: [72, 600], to: [300, 600])
41
+ c.stroke
42
+ end
43
+
44
+ doc.write("drawing.pdf")
45
+ ```
46
+
47
+ ## Embedding an ICC Profile
48
+
49
+ ```ruby
50
+ icc_bytes = File.binread("sRGB.icc")
51
+ cs = doc.colors.embed_icc_profile(icc_bytes)
52
+ page = doc.pages.first
53
+ cs_name = doc.colors.register(page, cs)
54
+ # Use cs_name in content stream: "/CS1 cs 0.5 0.3 0.2 scn"
55
+ ```
56
+
57
+ ## Tagged PDF (Accessibility)
58
+
59
+ ```ruby
60
+ doc.structure.enable!
61
+ doc.catalog.value[:Lang] = "en-US"
62
+
63
+ doc_elem = doc.structure.add_element(:Document)
64
+ doc.structure.add_child(doc_elem, :H1, title: "Introduction")
65
+ doc.structure.add_child(doc_elem, :P)
66
+ ```
67
+
68
+ ## Optional Content Groups (Layers)
69
+
70
+ ```ruby
71
+ doc.layers.add("Background Art", default_on: false)
72
+ doc.layers.add("Annotations")
73
+ doc.layers.sync!
74
+ ```
75
+
76
+ ## Interactive Forms (AcroForm)
77
+
78
+ ```ruby
79
+ page = doc.pages.add
80
+ doc.form.add_text_field("username", page: page, rect: [50, 700, 250, 720])
81
+ doc.form.add_checkbox("agree", page: page, rect: [50, 650, 65, 665], checked: true)
82
+ doc.form.add_combo("country", page: page, rect: [50, 600, 200, 620],
83
+ options: ["US", "UK", "JP"], value: "US")
84
+ ```
85
+
86
+ ## Digital Signatures
87
+
88
+ ```ruby
89
+ cert = OpenSSL::X509::Certificate.new(File.read("cert.pem"))
90
+ key = OpenSSL::PKey::RSA.new(File.read("key.pem"))
91
+
92
+ signed = Pdfrb::DigitalSignature::Signing.sign(doc, cert: cert, key: key,
93
+ reason: "Approval")
94
+ File.binwrite("signed.pdf", signed)
95
+
96
+ # Verify
97
+ results = Pdfrb::DigitalSignature::Verification.verify(signed, trusted_certs: [cert])
98
+ puts "Valid: #{results.first.valid?}"
99
+ ```
100
+
101
+ ## Semantic Comparison (Diff)
102
+
103
+ ```ruby
104
+ left = File.binread("v1.pdf")
105
+ right = File.binread("v2.pdf")
106
+ report = Pdfrb::Compare.compare(left, right)
107
+
108
+ puts "Pages: #{report.page_count_delta}"
109
+ puts "Fonts added: #{report.font_diff[:added]}"
110
+ puts "Equivalent: #{report.equivalent?}"
111
+ ```
112
+
113
+ ## Conformance Validation
114
+
115
+ ```ruby
116
+ doc = Pdfrb.open("archival.pdf")
117
+
118
+ # PDF/A
119
+ result = Pdfrb::Conformance::PdfA.validate(doc, level: :a2b)
120
+ puts "PDF/A-2b: #{result.passed? ? 'PASS' : 'FAIL'}"
121
+ result.errors.each { |e| puts " ERROR: #{e.message}" }
122
+
123
+ # PDF/UA
124
+ result = Pdfrb::Conformance::PdfUA.validate(doc)
125
+ puts "PDF/UA: #{result.passed? ? 'PASS' : 'FAIL'}"
126
+ ```
127
+
128
+ ## Linearization (Fast Web View)
129
+
130
+ ```ruby
131
+ doc = Pdfrb.open("large.pdf")
132
+ io = StringIO.new
133
+ Pdfrb::Linearization::Writer.new(doc).write(io)
134
+ File.binwrite("linearized.pdf", io.string)
135
+ ```
136
+
137
+ ## Encryption
138
+
139
+ ```ruby
140
+ doc = Pdfrb.open("input.pdf")
141
+ doc.write("encrypted.pdf")
142
+ # Encryption configuration via document.config
143
+ ```
144
+
145
+ ## Merging PDFs
146
+
147
+ ```ruby
148
+ target = Pdfrb.open("base.pdf")
149
+ source = Pdfrb.open("appendix.pdf")
150
+ Pdfrb::Task::Merge.call(target, source)
151
+ target.write("merged.pdf")
152
+ ```
153
+
154
+ ## Extracting Images
155
+
156
+ ```ruby
157
+ doc = Pdfrb.open("input.pdf")
158
+ images = Pdfrb::Task::ExtractImages.call(doc)
159
+ images.each_with_index do |img, i|
160
+ File.binwrite("image_#{i}.#{img[:format]}", img[:data])
161
+ end
162
+ ```
163
+
164
+ ## CLI
165
+
166
+ ```sh
167
+ pdfrb info input.pdf
168
+ pdfrb extract-text input.pdf
169
+ pdfrb merge a.pdf b.pdf -o merged.pdf
170
+ pdfrb diff v1.pdf v2.pdf
171
+ pdfrb encrypt input.pdf -o encrypted.pdf
172
+ pdfrb optimize input.pdf -o optimized.pdf
173
+ ```
data/lib/pdfrb/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pdfrb
4
- VERSION = "0.7.21"
4
+ VERSION = "0.7.22"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdfrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.21
4
+ version: 0.7.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-08-17 00:00:00.000000000 Z
11
+ date: 2026-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -701,6 +701,8 @@ files:
701
701
  - data/pdfrb/glyphlist.txt
702
702
  - data/pdfrb/layout/hyphenation_en.txt
703
703
  - data/pdfrb/zapfdingbats.txt
704
+ - docs/SEMVER.md
705
+ - docs/USAGE.md
704
706
  - exe/pdfrb
705
707
  - lib/pdfrb.rb
706
708
  - lib/pdfrb/action.rb
@@ -1218,7 +1220,6 @@ files:
1218
1220
  - lib/pdfrb/xmp/packet.rb
1219
1221
  - lib/pdfrb/xmp/schemas.rb
1220
1222
  - lib/pdfrb/xref_section.rb
1221
- - pdfrb.gemspec
1222
1223
  - script/apply_fixes.sh
1223
1224
  - script/make_jpeg_fixture.rb
1224
1225
  - script/make_png_fixture.rb
data/pdfrb.gemspec DELETED
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/pdfrb/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "pdfrb"
7
- spec.version = Pdfrb::VERSION
8
- spec.authors = ["Ribose Inc."]
9
- spec.email = ["open.source@ribose.com"]
10
-
11
- spec.summary = "Pure-Ruby PDF parser, Arlington-model-driven domain model, and serializer"
12
- spec.description = <<~HEREDOC
13
- Pdfrb is a pure-Ruby PDF library: a byte-level reader, an
14
- Arlington-model-driven typed domain model, and a serializer. The
15
- PDF object model is sourced directly from the vendored Arlington
16
- PDF Model TSVs (machine-readable ISO 32000-2:2020), so field
17
- metadata, version predicates, and validators stay aligned with
18
- the spec by data, not by hand-coded mimicry.
19
-
20
- Two-direction contract: "PDF file <=> Model" and "API Builder
21
- Input => Model". Mirrors the layered design of the sibling
22
- postscript gem.
23
- HEREDOC
24
-
25
- spec.homepage = "https://github.com/claricle/pdfrb"
26
- spec.license = "BSD-2-Clause"
27
- spec.required_ruby_version = ">= 3.2.0"
28
-
29
- spec.metadata["homepage_uri"] = spec.homepage
30
- spec.metadata["source_code_uri"] = "https://github.com/claricle/pdfrb"
31
- spec.metadata["changelog_uri"] = "https://github.com/claricle/pdfrb/blob/main/CHANGELOG.md"
32
- spec.metadata["bug_tracker_uri"] = "https://github.com/claricle/pdfrb/issues"
33
- spec.metadata["rubygems_mfa_required"] = "true"
34
-
35
- spec.files = Dir.chdir(__dir__) do
36
- `git ls-files -z`.split("\x0").reject do |f|
37
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
38
- end
39
- end
40
- spec.bindir = "exe"
41
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
42
- spec.require_paths = ["lib"]
43
-
44
- spec.add_dependency "thor"
45
- end