pdf_editor 0.0.1

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.
@@ -0,0 +1,69 @@
1
+ require_relative 'resource'
2
+ require_relative 'mixins/service'
3
+ require_relative 'mixins/pdf_runner'
4
+ require_relative 'mixins/errors'
5
+
6
+ module PdfEditor
7
+ class RotatePage
8
+ include PdfEditor::Service
9
+ include PdfEditor::PdfRunner
10
+ include PdfEditor::Errors
11
+
12
+ ROTATIONS = {
13
+ left: 'left',
14
+ right: 'right',
15
+ flip: 'down'
16
+ }
17
+
18
+ attr_reader :resource, :page, :rotate
19
+
20
+ def post_init
21
+ @resource = args.fetch(:resource, nil)
22
+ @page = args.fetch(:page, nil)
23
+ @rotate = ROTATIONS[args.fetch(:rotate, '')]
24
+ end
25
+
26
+ def call
27
+ if resource.nil? || page.nil? || rotate.nil?
28
+ raise Errors::ArgumentMissingError,
29
+ "resource: #{resource} \n page: #{page} \n rotate: #{rotate}"
30
+ end
31
+ PdfEditor::Resource.new(
32
+ create_tempfile {run_command}
33
+ )
34
+ end
35
+
36
+ private
37
+
38
+ def run_command
39
+ read_from_io do
40
+ pdf_runner.cat(format_command)
41
+ end
42
+ end
43
+
44
+ def get_page_count
45
+ page_count = resource.page_count
46
+ if page_count == 0 || page > page_count
47
+ raise Errors::PageRangeError, "Page #{page} does not exist. There are #{page_count} pages "
48
+ end
49
+ page_count
50
+ end
51
+
52
+ def format_command
53
+ page_count = get_page_count
54
+ page_nums = Array(1..page_count)
55
+
56
+ before_page = page_nums[0, page_nums.index(page)]
57
+
58
+ first_page_after = page_nums.index(page+1) || page_nums.length
59
+ after_page = page_nums[first_page_after, page_nums.length]
60
+
61
+ result = []
62
+ result << {:pdf => resource.path, :start => before_page.first, :end => before_page.last} unless before_page.empty?
63
+ result << {:pdf => resource.path, :start => page, :end => page, :orientation => rotate}
64
+ result << {:pdf => resource.path, :start => after_page.first, :end => after_page.last} unless after_page.empty?
65
+ result
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'resource'
2
+ require_relative 'mixins/service'
3
+ require_relative 'mixins/pdf_runner'
4
+ require_relative 'mixins/errors'
5
+
6
+ module PdfEditor
7
+ class Shuffle
8
+ include PdfEditor::Service
9
+ include PdfEditor::PdfRunner
10
+ include PdfEditor::Errors
11
+
12
+ #
13
+ # Page order does not require unique members and
14
+ # is not sorted. This is the base class for other
15
+ # shuffle operations.
16
+ #
17
+
18
+ attr_reader :resource, :page_order
19
+
20
+ def post_init
21
+ @resource = args[:resource]
22
+ @page_order = args.fetch(:page_order, [])
23
+ end
24
+
25
+ def call
26
+ if resource.nil?
27
+ raise Errors::ResourcesEmptyError, 'Must have a resource to shuffle'
28
+ end
29
+ if page_order.empty?
30
+ raise Errors::PageOrderInvalidError, 'Page order was invalid'
31
+ end
32
+ PdfEditor::Resource.new(
33
+ create_tempfile {run_command}
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def run_command
40
+ read_from_io do
41
+ pdf_runner.cat(format_command)
42
+ end
43
+ rescue ::ActivePdftk::CommandError => e
44
+ raise InvalidInputError, e.message
45
+ end
46
+
47
+ def format_command
48
+ page_order.map do |page_num|
49
+ {
50
+ :pdf => resource.path,
51
+ :start => page_num,
52
+ :end => page_num
53
+ }
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,52 @@
1
+ require_relative 'resource'
2
+ require_relative 'mixins/service'
3
+ require_relative 'mixins/prawn_dsl'
4
+
5
+ module PdfEditor
6
+ class TableOfContents
7
+ include PdfEditor::Service
8
+ include PdfEditor::PrawnDSL
9
+
10
+ attr_reader :resources
11
+
12
+ def post_init
13
+ @resources = args.fetch(:resources, [])
14
+ end
15
+
16
+ def call
17
+ if resources.empty?
18
+ raise PdfEditor::Errors::ResourcesEmptyError,
19
+ 'You must have at least one resource to create a table of contents'
20
+ end
21
+ PdfEditor::Resource.new(
22
+ create_tempfile {create_pdf}
23
+ )
24
+ end
25
+
26
+ def create_pdf
27
+ update_pdf do
28
+ header
29
+ body
30
+ end
31
+ to_pdf
32
+ end
33
+
34
+ def header
35
+ move_down 20
36
+ text 'applicant_name', size: 40, align: :center
37
+ move_down 50
38
+ end
39
+
40
+ def body
41
+ begin_page_count = 1 # TOC normally doesn't count itself as a page
42
+
43
+ resources.inject(begin_page_count) do |page_location, resource|
44
+ text "#{resource.name}........................#{page_location}"
45
+ move_down 10
46
+
47
+ page_location + resource.page_count
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,38 @@
1
+ require_relative 'resource'
2
+ require_relative 'mixins/service'
3
+ require_relative 'mixins/prawn_dsl'
4
+
5
+ module PdfEditor
6
+ class TitlePage
7
+ include PdfEditor::Service
8
+ include PdfEditor::PrawnDSL
9
+ include PdfEditor::Errors
10
+
11
+ attr_reader :title
12
+
13
+ def post_init
14
+ @title = args[:title]
15
+ end
16
+
17
+ def call
18
+ unless title
19
+ raise Errors::TitlePageTitleError, 'Title page requires a title to operate'
20
+ end
21
+ PdfEditor::Resource.new(
22
+ create_tempfile {create_pdf},
23
+ title
24
+ )
25
+ end
26
+
27
+ private
28
+
29
+ def create_pdf
30
+ update_pdf do
31
+ move_down 30
32
+ text title, size: 40, align: :center
33
+ end
34
+ to_pdf
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module PdfEditor
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'pdf_editor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "pdf_editor"
8
+ spec.version = PdfEditor::VERSION
9
+ spec.authors = ["bradwheel"]
10
+ spec.email = ["bradley.m.wheel@gmail.com"]
11
+ spec.summary = %q{Edits Pdf's}
12
+ spec.description = %q{Edits Pdf's}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'prawn', '1.2.1'
22
+ spec.add_dependency 'pdf-reader', '1.3.3'
23
+ spec.add_dependency 'docsplit', '0.7.5'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.6'
26
+ spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'rspec'
28
+ spec.add_development_dependency 'pdf-inspector'
29
+ spec.add_development_dependency 'pry'
30
+ end
@@ -0,0 +1,158 @@
1
+ require 'support/spec_helper'
2
+
3
+ module PdfEditor
4
+ describe Bundle do
5
+
6
+ before do
7
+ @resource_1 = get_resource('five_page.pdf', 'Five Page Pdf')
8
+ @resource_2 = get_resource('two_page.pdf', 'Two Page Pdf')
9
+ @service = PdfEditor::Bundle.new(
10
+ resources: [@resource_1, @resource_2],
11
+ title: 'TOC',
12
+ with_toc: true,
13
+ with_title_pages: true
14
+ )
15
+ end
16
+
17
+ describe '#create_title_page' do
18
+
19
+ it 'returns a resource' do
20
+ ret = @service.send(:create_title_page, @resource_1)
21
+ expect(ret).to be_instance_of PdfEditor::Resource
22
+ end
23
+
24
+ end
25
+
26
+ describe '#merge_resource_with_title_page' do
27
+
28
+ it 'creates a single resource with title page and original content' do
29
+ ret = @service.send(:merge_resource_with_title_page, @resource_1)
30
+ contents = []
31
+ ret.open_file do |f|
32
+ reader = ::PDF::Reader.new(f)
33
+ reader.pages.each {|page| contents << page.text}
34
+ end
35
+ expect(ret.page_count).to eq 6
36
+ expect(contents).to eq ['Five Page Pdf', 'Page 1', 'Page 2', 'Page 3', 'Page 4', 'Page 5']
37
+ end
38
+
39
+ end
40
+
41
+ describe '#call' do
42
+
43
+ before do
44
+ @service.stub(:create_title_pages) { nil }
45
+ @service.stub(:create_table_of_contents) { nil }
46
+ @service.stub(:bundle_documents) { nil }
47
+ end
48
+
49
+ it 'calls #create_title_pages' do
50
+ expect(@service).to receive(:create_title_pages)
51
+ @service.call
52
+ end
53
+
54
+ it 'calls #create_table_of_contents' do
55
+ expect(@service).to receive(:create_table_of_contents)
56
+ @service.call
57
+ end
58
+
59
+ it 'calls #bundle_documents' do
60
+ expect(@service).to receive(:bundle_documents)
61
+ @service.call
62
+ end
63
+
64
+ end
65
+
66
+ describe '#create_title_pages' do
67
+
68
+ context 'when with_title_pages' do
69
+
70
+ it 'creates title pages' do
71
+ service = PdfEditor::Bundle.new(
72
+ resources: [@resource_1, @resource_2],
73
+ title: 'TOC',
74
+ with_toc: true,
75
+ with_title_pages: true
76
+ )
77
+ service.send(:create_title_pages)
78
+ ready_for_toc = service.send(:ready_for_toc)
79
+ page_count = ready_for_toc.inject(0) {|sum, resource| sum + resource.page_count}
80
+ expect(page_count).to eq 9
81
+ end
82
+
83
+ end
84
+
85
+ context 'when not with_title_pages' do
86
+
87
+ it 'does not create title pages' do
88
+ service = PdfEditor::Bundle.new(
89
+ resources: [@resource_1, @resource_2],
90
+ title: 'TOC',
91
+ with_toc: true,
92
+ with_title_pages: false
93
+ )
94
+ service.send(:create_title_pages)
95
+ ready_for_toc = service.send(:ready_for_toc)
96
+ page_count = ready_for_toc.inject(0) {|sum, resource| sum + resource.page_count}
97
+ expect(page_count).to eq 7
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+
104
+ describe '#create_table_of_contents' do
105
+
106
+ it 'does nothing if ready_for_toc is empty' do
107
+ service = PdfEditor::Bundle.new(
108
+ resources: [],
109
+ title: 'TOC',
110
+ with_toc: true,
111
+ with_title_pages: false
112
+ )
113
+ service.send(:create_table_of_contents)
114
+ expect(service.send(:table_of_contents)).to be_nil
115
+ end
116
+
117
+ it 'does nothing if not with_toc' do
118
+ service = PdfEditor::Bundle.new(
119
+ resources: [@resource_1, @resource_2],
120
+ title: 'TOC',
121
+ with_toc: false,
122
+ with_title_pages: false
123
+ )
124
+ service.send(:create_table_of_contents)
125
+ expect(service.send(:table_of_contents)).to be_nil
126
+ end
127
+
128
+ it 'sets table_of_contents to generated table_of_contents' do
129
+ service = PdfEditor::Bundle.new(
130
+ resources: [@resource_1, @resource_2],
131
+ title: 'TOC',
132
+ with_toc: true,
133
+ with_title_pages: true
134
+ )
135
+ service.stub(:ready_for_toc) {[@resource_1, @resource_2]}
136
+ service.send(:create_table_of_contents)
137
+ expect(service.send(:table_of_contents)).to be_instance_of PdfEditor::Resource
138
+ end
139
+
140
+ end
141
+
142
+ describe '#bundle_documents' do
143
+
144
+ it 'merges the table_of_contents with the contents' do
145
+ service = PdfEditor::Bundle.new(
146
+ resources: [@resource_1, @resource_2],
147
+ title: 'TOC',
148
+ with_toc: true,
149
+ with_title_pages: true
150
+ )
151
+ ret = service.call
152
+ expect(ret.page_count).to eq 10
153
+ end
154
+
155
+ end
156
+
157
+ end
158
+ end
@@ -0,0 +1,63 @@
1
+ require 'support/spec_helper'
2
+
3
+ module PdfEditor
4
+ describe Merge do
5
+
6
+ before do
7
+ support_dir = ::File.join(::File.dirname(__FILE__), 'support', 'docs')
8
+
9
+ ['merge_1.pdf', 'merge_2.pdf'].each_with_index do |file, i|
10
+
11
+ ::File.open(::File.join(support_dir, file), 'r') do |f|
12
+
13
+ ::Tempfile.open(['', '.pdf']) do |tf|
14
+ tf.write f.read
15
+ instance_variable_set(:"@resource_#{i+1}", PdfEditor::Resource.new(tf))
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+
23
+ describe '#call' do
24
+
25
+ before do
26
+ @ret = PdfEditor::Merge.call(resources: [@resource_1, @resource_2], merged_name: 'Merged Name')
27
+ end
28
+
29
+ it 'returns a resource' do
30
+ expect(@ret).to be_instance_of PdfEditor::Resource
31
+ end
32
+
33
+ it 'returns a merged document' do
34
+ contents = ''
35
+ @ret.open_file do |f|
36
+ PDF::Reader.new(f).pages.each {|page| contents << page.text}
37
+ end
38
+ expect(contents).to eq 'merge 1merge 2'
39
+ expect(@ret.page_count).to eq 2
40
+ end
41
+
42
+ it 'raises an error if no resources are present' do
43
+ expect{PdfEditor::Merge.call}.to raise_error PdfEditor::Errors::ResourcesEmptyError
44
+ end
45
+
46
+ it 'returned resource has merged_name if supplied' do
47
+ expect(@ret.name).to eq 'Merged Name'
48
+ end
49
+
50
+ end
51
+
52
+ describe '#format_command' do
53
+
54
+ it 'creates the proper format for merge' do
55
+ expected_format = [{:pdf => @resource_1.path}, {:pdf => @resource_2.path}]
56
+ service = PdfEditor::Merge.new(resources: [@resource_1, @resource_2])
57
+ expect(service.send(:format_command)).to eq expected_format
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end