combine_pdf 1.0.23 → 1.0.26
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +28 -0
- data/CHANGELOG.md +15 -1
- data/README.md +10 -10
- data/combine_pdf.gemspec +1 -1
- data/lib/combine_pdf/parser.rb +2 -2
- data/lib/combine_pdf/pdf_public.rb +8 -4
- data/lib/combine_pdf/version.rb +1 -1
- data/test/automated +26 -25
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc482ee9da31ce7fc01e92da3936e44407e4879c7058817bb4a57ba0fc0a4165
|
4
|
+
data.tar.gz: 1dd52423ee639783510a9ad9aa347e9597e2e14d38a11914d05a03b5116006f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6ac66c289762c5f2b6473f450e8808e79d9ca9f927b68f083204a93b7f213a433a6fc4076cd3241ff1a17ac7c08297087ab1bf76e58b0dad12e7a0eebc34628
|
7
|
+
data.tar.gz: a39c619af345d61d7d40ba0d0b0a32438caace2b05512273afe1f21b737de6324dcc483f34234c5123c9ed0508a0db481b4bf90ffc06fce2484922f2c6c7abe0
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: Main
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
tests:
|
7
|
+
name: Tests
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby: ["2.7", "3.0", "3.1", "3.2"]
|
13
|
+
|
14
|
+
steps:
|
15
|
+
- name: Checkout code
|
16
|
+
uses: actions/checkout@v3
|
17
|
+
|
18
|
+
- name: Setup Ruby
|
19
|
+
uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
bundler-cache: true
|
23
|
+
|
24
|
+
- name: Generate lockfile
|
25
|
+
run: bundle lock
|
26
|
+
|
27
|
+
- name: Run tests
|
28
|
+
run: bundle exec rake test
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
#### Change log v.1.0.
|
3
|
+
#### Change log v.1.0.26 (2023-12-22)
|
4
|
+
|
5
|
+
**Performance**: possible performance bump. Credit to @denislavski (Denislav Naydenov) for opening PR #235.
|
6
|
+
|
7
|
+
#### Change log v.1.0.25 (2023-12-19)
|
8
|
+
|
9
|
+
**Fix**: possible improve memory usage. Credit to @denislavski (Denislav Naydenov) for opening PR #233 and suggesting this change.
|
10
|
+
|
11
|
+
#### Change log v.1.0.24 (2023-10-19)
|
12
|
+
|
13
|
+
**Fix**: possible `nil` in loop. Credit to @jkowens for PR #231 and adding a quick fix using a simple guard.
|
14
|
+
|
15
|
+
**Fix**: preserve file creation date metadata where relevant.
|
16
|
+
|
17
|
+
#### Change log v.1.0.23 (2023-04-04)
|
4
18
|
|
5
19
|
**Feature**: merged PR #177 for the `raise_on_encrypted: true` option support. Credit to @leviwilson and @kimyu92 for the PR.
|
6
20
|
|
data/README.md
CHANGED
@@ -7,23 +7,23 @@
|
|
7
7
|
|
8
8
|
CombinePDF is a nifty model, written in pure Ruby, to parse PDF files and combine (merge) them with other PDF files, watermark them or stamp them (all using the PDF file format and pure Ruby code).
|
9
9
|
|
10
|
-
##
|
10
|
+
## Unmaintained - Help Wanted(!)
|
11
11
|
|
12
|
-
|
12
|
+
I decided to stop maintaining this gem and hope someone could take over the PR reviews and maintenance of this gem (or simply open a successful fork).
|
13
13
|
|
14
|
-
|
15
|
-
gem install combine_pdf
|
16
|
-
```
|
14
|
+
I wrote this gem because I needed to solve an issue with bates-numbering existing PDF documents.
|
17
15
|
|
18
|
-
|
16
|
+
However, since 2014 I have been maintaining the gem for free and for no reason at all, except that I enjoyed sharing it with the community.
|
19
17
|
|
20
|
-
I
|
18
|
+
I love this gem, but I cannot keep maintaining it as I have my own projects to focus own and I need both the time and (more importantly) the mindspace.
|
21
19
|
|
22
|
-
|
20
|
+
## Install
|
23
21
|
|
24
|
-
|
22
|
+
Install with ruby gems:
|
25
23
|
|
26
|
-
|
24
|
+
```ruby
|
25
|
+
gem install combine_pdf
|
26
|
+
```
|
27
27
|
|
28
28
|
## Known Limitations
|
29
29
|
|
data/combine_pdf.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "combine_pdf"
|
8
8
|
spec.version = CombinePDF::VERSION
|
9
9
|
spec.authors = ["Boaz Segev"]
|
10
|
-
spec.email = ["
|
10
|
+
spec.email = ["bo@bowild.com"]
|
11
11
|
spec.summary = %q{Combine, stamp and watermark PDF files in pure Ruby.}
|
12
12
|
spec.description = %q{A nifty gem, in pure Ruby, to parse PDF files and combine (merge) them with other PDF files, number the pages, watermark them or stamp them, create tables, add basic text objects etc` (all using the PDF file format).}
|
13
13
|
spec.homepage = "https://github.com/boazsegev/combine_pdf"
|
data/lib/combine_pdf/parser.rb
CHANGED
@@ -323,8 +323,8 @@ module CombinePDF
|
|
323
323
|
str << 12
|
324
324
|
when 48..57 # octal notation for byte?
|
325
325
|
rep -= 48
|
326
|
-
rep = (rep << 3) + (str_bytes.shift-48) if str_bytes[0]
|
327
|
-
rep = (rep << 3) + (str_bytes.shift-48) if str_bytes[0]
|
326
|
+
rep = (rep << 3) + (str_bytes.shift-48) if str_bytes[0]&.between?(48, 57)
|
327
|
+
rep = (rep << 3) + (str_bytes.shift-48) if str_bytes[0]&.between?(48, 57) && (((rep << 3) + (str_bytes[0] - 48)) <= 255)
|
328
328
|
str << rep
|
329
329
|
when 10 # new line, ignore
|
330
330
|
str_bytes.shift if str_bytes[0] == 13
|
@@ -175,8 +175,12 @@ module CombinePDF
|
|
175
175
|
def to_pdf(options = {})
|
176
176
|
# reset version if not specified
|
177
177
|
@version = 1.5 if @version.to_f == 0.0
|
178
|
+
|
178
179
|
# set info for merged file
|
179
|
-
@info[:
|
180
|
+
unless(@info[:CreationDate].is_a?(String))
|
181
|
+
@info[:CreationDate] = Time.now unless @info[:CreationDate].is_a?(Time)
|
182
|
+
@info[:CreationDate] = @info[:CreationDate].getgm.strftime("D:%Y%m%d%H%M%S%:::z'00")
|
183
|
+
end
|
180
184
|
@info[:Subject] = options[:subject] if options[:subject]
|
181
185
|
@info[:Producer] = options[:producer] if options[:producer]
|
182
186
|
# rebuild_catalog
|
@@ -202,9 +206,9 @@ module CombinePDF
|
|
202
206
|
xref_location = loc
|
203
207
|
# xref_location = 0
|
204
208
|
# out.each { |line| xref_location += line.bytesize + 1}
|
205
|
-
out << "xref\n0 #{indirect_object_count}\n0000000000 65535 f
|
206
|
-
xref.each { |offset| out << (
|
207
|
-
out <<
|
209
|
+
out << "xref\n0 #{indirect_object_count}\n0000000000 65535 f "
|
210
|
+
xref.each { |offset| out << ("%010d 00000 n ".freeze % offset) }
|
211
|
+
out << 'trailer'.freeze
|
208
212
|
out << "<<\n/Root #{false || "#{catalog[:indirect_reference_id]} #{catalog[:indirect_generation_number]} R"}"
|
209
213
|
out << "/Size #{indirect_object_count}"
|
210
214
|
out << "/Info #{@info[:indirect_reference_id]} #{@info[:indirect_generation_number]} R"
|
data/lib/combine_pdf/version.rb
CHANGED
data/test/automated
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
$VERBOSE = true
|
4
4
|
|
5
5
|
require 'benchmark'
|
6
|
-
|
6
|
+
Dir.chdir File.expand_path(File.join('..', '..', 'lib'), __FILE__)
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
7
8
|
require 'combine_pdf'
|
8
9
|
# require 'bundler/setup'
|
9
10
|
|
@@ -15,51 +16,51 @@ require 'combine_pdf'
|
|
15
16
|
# Pry.start
|
16
17
|
|
17
18
|
pdf = CombinePDF.load "../../test\ pdfs/filled_form.pdf"
|
18
|
-
pdf.save '01_check_radio_buttuns.pdf'
|
19
|
+
pdf.save '../tmp/01_check_radio_buttuns.pdf'
|
19
20
|
pdf = CombinePDF.load "../../test\ pdfs/filled_form.pdf"
|
20
21
|
pdf << CombinePDF.load("../../test\ pdfs/empty_form.pdf")
|
21
22
|
pdf << CombinePDF.load("../../test\ pdfs/filled_form.pdf")
|
22
|
-
pdf.save '02_check_form_unification_middle_is_empty.pdf'
|
23
|
+
pdf.save '../tmp/02_check_form_unification_middle_is_empty.pdf'
|
23
24
|
|
24
25
|
pdf = CombinePDF.load "../../test\ pdfs/check_form_data__objstreams_w_versions.pdf"
|
25
|
-
pdf.save '02_01_check_form_data_ordering_issue.pdf'
|
26
|
+
pdf.save '../tmp/02_01_check_form_data_ordering_issue.pdf'
|
26
27
|
|
27
28
|
|
28
29
|
pdf = CombinePDF.load '../../test pdfs/share-font-background.pdf'
|
29
30
|
pdf2 = CombinePDF.load '../../test pdfs/share-font-foreground.pdf'
|
30
31
|
i = 0
|
31
32
|
pdf.pages.each { |pg| pg << pdf2.pages[i] }
|
32
|
-
pdf.save '03_check_font_conflict.pdf'
|
33
|
+
pdf.save '../tmp/03_check_font_conflict.pdf'
|
33
34
|
|
34
35
|
pdf = CombinePDF.load '../../test pdfs/nil_1.pdf'
|
35
36
|
pdf2 = CombinePDF.load '../../test pdfs/nil_2.pdf'
|
36
37
|
pdf << pdf2
|
37
|
-
pdf.save '03_01_nil_value_conflict.pdf'
|
38
|
+
pdf.save '../tmp/03_01_nil_value_conflict.pdf'
|
38
39
|
|
39
40
|
pdf = CombinePDF.load '../../test pdfs/space_after_streram_keyword.pdf'
|
40
|
-
pdf.save '03_02_extra_space_after_stream_keyword.pdf'
|
41
|
+
pdf.save '../tmp/03_02_extra_space_after_stream_keyword.pdf'
|
41
42
|
|
42
43
|
pdf = CombinePDF.load '../../test pdfs/nested_difference.pdf'
|
43
|
-
pdf.save '03_03_nested_difference.pdf'
|
44
|
+
pdf.save '../tmp/03_03_nested_difference.pdf'
|
44
45
|
|
45
46
|
pdf = CombinePDF.load '../../test pdfs/names_go_haywire_0.pdf'
|
46
47
|
pdf << CombinePDF.load('../../test pdfs/names_go_haywire_1.pdf')
|
47
|
-
pdf.save '04_check_view_and_names_reference.pdf'
|
48
|
+
pdf.save '../tmp/04_check_view_and_names_reference.pdf'
|
48
49
|
|
49
50
|
pdf = CombinePDF.load('../../test pdfs/outlines/self_merge_err.pdf')
|
50
|
-
pdf.save '05_x1_scribus_test.pdf'
|
51
|
+
pdf.save '../tmp/05_x1_scribus_test.pdf'
|
51
52
|
pdf = CombinePDF.load('../../test pdfs/outlines/self_merge_err.pdf')
|
52
53
|
pdf << CombinePDF.load('../../test pdfs/outlines/self_merge_err.pdf')
|
53
|
-
pdf.save '05_x2_scribus_test.pdf'
|
54
|
+
pdf.save '../tmp/05_x2_scribus_test.pdf'
|
54
55
|
pdf = CombinePDF.load "../../test pdfs/outlines/named_dest.pdf";nil
|
55
|
-
pdf.save '05_check_named_dest_links.pdf' # this will take a while
|
56
|
+
pdf.save '../tmp/05_check_named_dest_links.pdf' # this will take a while
|
56
57
|
pdf = CombinePDF.load "../../test pdfs/outlines/named_dest.pdf";nil
|
57
58
|
pdf << CombinePDF.load('../../test pdfs/outlines/named_dest.pdf'); nil
|
58
|
-
pdf.save '05_1_timeless_check_named_dest_links.pdf' # never ends... :-(
|
59
|
+
pdf.save '../tmp/05_1_timeless_check_named_dest_links.pdf' # never ends... :-(
|
59
60
|
|
60
61
|
pdf = CombinePDF.load '../../test pdfs/outline_small.pdf'
|
61
62
|
pdf << CombinePDF.load('../../test pdfs/outline_small.pdf')
|
62
|
-
pdf.save '06_check_links_to_second_copy.pdf'
|
63
|
+
pdf.save '../tmp/06_check_links_to_second_copy.pdf'
|
63
64
|
|
64
65
|
lists = %w(../../test\ pdfs/outlines/self_merge_err.pdf ../../test\ pdfs/outlines/big_toc.pdf ../../test\ pdfs/outlines/bigger_toc.pdf ../../test\ pdfs/outlines/named_dest_no_toc.pdf ../../test\ pdfs/outlines/named_dest_no_toc2.pdf ../../test\ pdfs/outlines/named_dest.pdf ../../test\ pdfs/outlines/named_dest2.pdf)
|
65
66
|
|
@@ -76,7 +77,7 @@ lists.each do |n|
|
|
76
77
|
end
|
77
78
|
pdf = CombinePDF.new
|
78
79
|
lists.each { |n| pdf << CombinePDF.load(n) }
|
79
|
-
pdf.save('07_named destinations.pdf')
|
80
|
+
pdf.save('../tmp/07_named destinations.pdf')
|
80
81
|
|
81
82
|
pdf = CombinePDF.new
|
82
83
|
lists.each { |n| pdf << CombinePDF.load(n) }
|
@@ -90,15 +91,15 @@ pdf.number_pages(start_at: 1,
|
|
90
91
|
number_location: [:top, :bottom],
|
91
92
|
opacity: 0.75)
|
92
93
|
|
93
|
-
pdf.save('07_named destinations_numbered.pdf')
|
94
|
+
pdf.save('../tmp/07_named destinations_numbered.pdf')
|
94
95
|
|
95
|
-
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err.pdf").save '08_1-unknown-err-empty-str.pdf'
|
96
|
-
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err2.pdf").save '08_2-unknown-err-empty-str.pdf'
|
97
|
-
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err3.pdf").save '08_3-unknown-err-empty-str.pdf'
|
98
|
-
CombinePDF.load("../../test\ pdfs/xref_in_middle.pdf").save '08_4-xref-in-middle.pdf'
|
99
|
-
CombinePDF.load("../../test\ pdfs/xref_split.pdf").save '08_5-xref-fragmented.pdf'
|
96
|
+
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err.pdf").save '../tmp/08_1-unknown-err-empty-str.pdf'
|
97
|
+
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err2.pdf").save '../tmp/08_2-unknown-err-empty-str.pdf'
|
98
|
+
CombinePDF.load("../../test\ pdfs/Scribus-unknown_err3.pdf").save '../tmp/08_3-unknown-err-empty-str.pdf'
|
99
|
+
CombinePDF.load("../../test\ pdfs/xref_in_middle.pdf").save '../tmp/08_4-xref-in-middle.pdf'
|
100
|
+
CombinePDF.load("../../test\ pdfs/xref_split.pdf").save '../tmp/08_5-xref-fragmented.pdf'
|
100
101
|
|
101
|
-
CombinePDF.load("../../test\ pdfs/nil_object.pdf").save('09_nil_in_parsed_array.pdf')
|
102
|
+
CombinePDF.load("../../test\ pdfs/nil_object.pdf").save('../tmp/09_nil_in_parsed_array.pdf')
|
102
103
|
|
103
104
|
encrypted = [ "../../test\ pdfs/pdf-reader/encrypted_version4_revision4_128bit_aes_user_pass_apples_enc_metadata.pdf",
|
104
105
|
"../../test\ pdfs/AESv2\ encrypted.pdf",
|
@@ -109,7 +110,7 @@ encrypted = [ "../../test\ pdfs/pdf-reader/encrypted_version4_revision4_128bit_a
|
|
109
110
|
encrypted.length.times do |i|
|
110
111
|
fname = File.basename encrypted[i]
|
111
112
|
begin
|
112
|
-
CombinePDF.load(encrypted[i]).save "10_#{i}_#{fname}"
|
113
|
+
CombinePDF.load(encrypted[i]).save "../tmp/10_#{i}_#{fname}"
|
113
114
|
rescue => e
|
114
115
|
puts e.class.name, e.message
|
115
116
|
if(i == 0)
|
@@ -125,10 +126,10 @@ IO.binwrite '11_prawn.pdf', (Prawn::Document.new { text 'Hello World!' }).render
|
|
125
126
|
page = CombinePDF.parse((Prawn::Document.new { text 'Hello World!' }).render)
|
126
127
|
pdf = CombinePDF.new
|
127
128
|
pdf << page
|
128
|
-
pdf.save '11_parsed_from_prawn.pdf'
|
129
|
+
pdf.save '../tmp/11_parsed_from_prawn.pdf'
|
129
130
|
pdf = CombinePDF.new
|
130
131
|
pdf << page << page
|
131
|
-
pdf.save('11_AcrobatReader_is_unique_page.pdf')
|
132
|
+
pdf.save('../tmp/11_AcrobatReader_is_unique_page.pdf')
|
132
133
|
|
133
134
|
puts GC.stat.inspect
|
134
135
|
# unify = [
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: combine_pdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.26
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-rc4
|
@@ -84,11 +84,12 @@ description: A nifty gem, in pure Ruby, to parse PDF files and combine (merge) t
|
|
84
84
|
with other PDF files, number the pages, watermark them or stamp them, create tables,
|
85
85
|
add basic text objects etc` (all using the PDF file format).
|
86
86
|
email:
|
87
|
-
-
|
87
|
+
- bo@bowild.com
|
88
88
|
executables: []
|
89
89
|
extensions: []
|
90
90
|
extra_rdoc_files: []
|
91
91
|
files:
|
92
|
+
- ".github/workflows/main.yml"
|
92
93
|
- ".gitignore"
|
93
94
|
- ".travis.yml"
|
94
95
|
- CHANGELOG.md
|