derivative-rodeo 0.2.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +6 -0
  3. data/LICENSE +15 -0
  4. data/README.md +251 -0
  5. data/Rakefile +42 -0
  6. data/derivative_rodeo.gemspec +54 -0
  7. data/lib/derivative/rodeo.rb +3 -0
  8. data/lib/derivative-rodeo.rb +3 -0
  9. data/lib/derivative_rodeo/configuration.rb +95 -0
  10. data/lib/derivative_rodeo/errors.rb +56 -0
  11. data/lib/derivative_rodeo/generators/base_generator.rb +200 -0
  12. data/lib/derivative_rodeo/generators/concerns/copy_file_concern.rb +28 -0
  13. data/lib/derivative_rodeo/generators/copy_generator.rb +14 -0
  14. data/lib/derivative_rodeo/generators/hocr_generator.rb +112 -0
  15. data/lib/derivative_rodeo/generators/monochrome_generator.rb +39 -0
  16. data/lib/derivative_rodeo/generators/pdf_split_generator.rb +61 -0
  17. data/lib/derivative_rodeo/generators/thumbnail_generator.rb +38 -0
  18. data/lib/derivative_rodeo/generators/word_coordinates_generator.rb +39 -0
  19. data/lib/derivative_rodeo/services/base_service.rb +15 -0
  20. data/lib/derivative_rodeo/services/convert_uri_via_template_service.rb +87 -0
  21. data/lib/derivative_rodeo/services/extract_word_coordinates_from_hocr_sgml_service.rb +218 -0
  22. data/lib/derivative_rodeo/services/image_identify_service.rb +89 -0
  23. data/lib/derivative_rodeo/services/image_jp2_service.rb +112 -0
  24. data/lib/derivative_rodeo/services/image_service.rb +73 -0
  25. data/lib/derivative_rodeo/services/pdf_splitter/base.rb +177 -0
  26. data/lib/derivative_rodeo/services/pdf_splitter/jpg_page.rb +14 -0
  27. data/lib/derivative_rodeo/services/pdf_splitter/pages_summary.rb +130 -0
  28. data/lib/derivative_rodeo/services/pdf_splitter/png_page.rb +26 -0
  29. data/lib/derivative_rodeo/services/pdf_splitter/tiff_page.rb +52 -0
  30. data/lib/derivative_rodeo/services/pdf_splitter_service.rb +19 -0
  31. data/lib/derivative_rodeo/services/url_service.rb +42 -0
  32. data/lib/derivative_rodeo/storage_locations/base_location.rb +251 -0
  33. data/lib/derivative_rodeo/storage_locations/concerns/download_concern.rb +67 -0
  34. data/lib/derivative_rodeo/storage_locations/file_location.rb +39 -0
  35. data/lib/derivative_rodeo/storage_locations/http_location.rb +13 -0
  36. data/lib/derivative_rodeo/storage_locations/https_location.rb +13 -0
  37. data/lib/derivative_rodeo/storage_locations/s3_location.rb +103 -0
  38. data/lib/derivative_rodeo/storage_locations/sqs_location.rb +187 -0
  39. data/lib/derivative_rodeo/technical_metadata.rb +23 -0
  40. data/lib/derivative_rodeo/version.rb +5 -0
  41. data/lib/derivative_rodeo.rb +36 -0
  42. metadata +339 -0
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-s3'
4
+
5
+ module DerivativeRodeo
6
+ module StorageLocations
7
+ ##
8
+ # Location to download and upload files to S3
9
+ #
10
+ class S3Location < BaseLocation
11
+ attr_writer :bucket
12
+ ##
13
+ # Create a new uri of the classes type. Parts argument should have a default in
14
+ # implementing classes. Must support a number or the symbol :all
15
+ #
16
+ # @api public
17
+ #
18
+ # @param path [String]
19
+ # @param parts [Integer, :all], defaults to 2 for S3 which is parent_dir/file_name.ext
20
+ # @return [String]
21
+ def self.create_uri(path:, parts: 2)
22
+ file_path = file_path_from_parts(path: path, parts: parts)
23
+ File.join("#{adapter_prefix}/#{file_path}")
24
+ end
25
+
26
+ ##
27
+ # @param config [DerivativeRodeo::Configuration]
28
+ # @return [String]
29
+ def self.adapter_prefix(config: DerivativeRodeo.config)
30
+ "#{scheme}://#{config.aws_s3_bucket}.s3.#{config.aws_s3_region}.amazonaws.com"
31
+ end
32
+
33
+ ##
34
+ # @api public
35
+ # download or copy the file to a tmp path
36
+ # deletes the tmp file after the block is executed
37
+ #
38
+ # @return [String] the path to the tmp file
39
+ def with_existing_tmp_path(&block)
40
+ with_tmp_path(lambda { |file_path, tmp_file_path, exist|
41
+ raise Errors::FileMissingError unless exist
42
+ obj = bucket.object(file_path)
43
+ obj.download_file(tmp_file_path)
44
+ }, &block)
45
+ end
46
+
47
+ ##
48
+ # @api public
49
+ #
50
+ # Existance is futile
51
+ # @return [Boolean]
52
+ def exist?
53
+ bucket.objects(prefix: file_path).count.positive?
54
+ end
55
+
56
+ ##
57
+ # @api public
58
+ # write the tmp file to the file_uri
59
+ #
60
+ # @return [String] the file_uri
61
+ def write
62
+ raise Errors::FileMissingError("Use write within a with__new_tmp_path block and fill the tmp file with data before writing") unless File.exist?(tmp_file_path)
63
+
64
+ obj = bucket.object(file_path)
65
+ obj.upload_file(tmp_file_path)
66
+ file_uri
67
+ end
68
+
69
+ ##
70
+ # @api private
71
+ #
72
+ # @return [Aws::S3::Resource]
73
+ def resource
74
+ @resource ||= if DerivativeRodeo.config.aws_s3_access_key_id
75
+ Aws::S3::Resource.new(region: DerivativeRodeo.config.aws_s3_region,
76
+ credentials: Aws::Credentials.new(
77
+ DerivativeRodeo.config.aws_s3_access_key_id,
78
+ DerivativeRodeo.config.aws_s3_secret_access_key
79
+ ))
80
+ else
81
+ Aws::S3::Resource.new
82
+ end
83
+ end
84
+
85
+ ##
86
+ # @api private
87
+ # https://long-term-video-storage.s3.eu-west-1.amazonaws.com/path1/path2/file.tld
88
+ def bucket_name
89
+ @bucket_name ||= file_uri.match(%r{s3://(.+)\.s3})&.[](1)
90
+ rescue StandardError
91
+ raise Errors::BucketMissingError
92
+ end
93
+
94
+ def bucket
95
+ @bucket ||= resource.bucket(bucket_name)
96
+ end
97
+
98
+ def file_path
99
+ @file_path ||= @file_uri.sub(%r{.+://.+?/}, '')
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'aws-sdk-sqs'
4
+ require 'cgi'
5
+
6
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
7
+ inflect.uncountable 'sqs'
8
+ end
9
+
10
+ module DerivativeRodeo
11
+ module StorageLocations
12
+ ##
13
+ # Location to download and upload files to Sqs
14
+ # It uploads a file_uri to the queue, not the contents of that file
15
+ # reading from the queue is not currently implemented
16
+ class SqsLocation < BaseLocation
17
+ class_attribute :batch_size, default: 10
18
+
19
+ attr_writer :client
20
+
21
+ ##
22
+ # Create a new uri of the classes type. Parts argument should have a default in
23
+ # implementing classes. Must support a number or the symbol :all
24
+ #
25
+ # @api public
26
+ #
27
+ # @param path [String]
28
+ # @param parts [Integer, :all], defaults to 1 for Sqs which is file_name.ext. We use 1 because it helps with tmp files, but the actual sqs queue does not have a file path
29
+ # @return [String]
30
+ def self.create_uri(path:, parts: 1)
31
+ file_path = file_path_from_parts(path: path, parts: parts)
32
+ "#{adapter_prefix}#{file_path}"
33
+ end
34
+
35
+ def self.adapter_prefix(config: DerivativeRodeo.config)
36
+ "#{scheme}://#{config.aws_sqs_region}.amazonaws.com/#{config.aws_sqs_account_id}/#{config.aws_sqs_queue}/"
37
+ end
38
+
39
+ # TODO: implement read
40
+ # ##
41
+ # # @api public
42
+ # # download or copy the file to a tmp path
43
+ # # deletes the tmp file after the block is executed
44
+ # #
45
+ # # @return [String] the path to the tmp file
46
+ # def with_existing_tmp_path(&block)
47
+ # with_tmp_path(lambda { |_file_path, tmp_file_path, exist|
48
+ # raise Errors::FileMissingError unless exist
49
+ # File.open(tmp_file_path, 'w') do |file|
50
+ # read_batch.each do |message|
51
+ # file.write(message)
52
+ # end
53
+ # end
54
+ # }, &block)
55
+ # end
56
+
57
+ ##
58
+ # @api public
59
+ #
60
+ # Existance is futile. And there's not way to check if a specific item is in an sqs queue
61
+ # @return [Boolean]
62
+ def exist?
63
+ false
64
+ end
65
+
66
+ ##
67
+ # @api public
68
+ # write the tmp file to the file_uri
69
+ #
70
+ # @return [String] the file_uri
71
+ def write
72
+ raise Errors::FileMissingError("Use write within a with__new_tmp_path block and fille the mp file with data before writing") unless File.exist?(tmp_file_path)
73
+ raise Errors::MaxQqueueSize(batch_size: batch_size) if batch_size > config.aws_sqs_max_batch_size
74
+ batch = []
75
+ Dir.glob("#{File.dirname(tmp_file_path)}/**/**").each.with_index do |fp, i|
76
+ batch << { id: SecureRandom.uuid, message_body: output_json("file://#{fp}") }
77
+ if (i % batch_size).zero?
78
+ add_batch(messages: batch)
79
+ batch = []
80
+ end
81
+ end
82
+ file_uri
83
+ end
84
+
85
+ def client
86
+ @client ||= if config.aws_sqs_access_key_id && config.aws_sqs_secret_access_key
87
+ Aws::SQS::Client.new(
88
+ region: config.aws_sqs_region,
89
+ credentials: Aws::Credentials.new(
90
+ config.aws_sqs_access_key_id,
91
+ config.aws_sqs_secret_access_key
92
+ )
93
+ )
94
+ else
95
+ Aws::SQS::Client.new(region: config.aws_sqs_region)
96
+ end
97
+ end
98
+
99
+ def add(message:)
100
+ client.send_message({
101
+ queue_url: queue_url,
102
+ message_body: message
103
+ })
104
+ end
105
+
106
+ def add_batch(messages:)
107
+ client.send_message_batch({
108
+ queue_url: queue_url,
109
+ entries: messages
110
+ })
111
+ end
112
+
113
+ # def read_batch
114
+ # raise Errors::MaxQqueueSize(batch_size: batch_size) if batch_size > DerivativeRodeo.config.aws_sqs_max_batch_size
115
+
116
+ # response = client.receive_message({
117
+ # queue_url: queue_url,
118
+ # max_number_of_messages: batch_size
119
+ # })
120
+ # response.messages.map do |message|
121
+ # JSON.parse(message.body)
122
+ # end
123
+ # end
124
+
125
+ def queue_url
126
+ @queue_url ||= client.get_queue_url(queue_name: queue_name).queue_url
127
+ end
128
+
129
+ ##
130
+ # @api private
131
+ def queue_name
132
+ @queue_name ||= file_uri_parts[:queue_name]
133
+ rescue StandardError
134
+ raise Errors::QueueMissingError
135
+ end
136
+
137
+ ##
138
+ # @api private
139
+ def file_path
140
+ @file_path ||= [file_dir, file_name].join('/')
141
+ end
142
+
143
+ def file_dir
144
+ @file_dir ||= file_uri_parts[:file_dir]
145
+ end
146
+
147
+ ##
148
+ # @api private
149
+ def file_name
150
+ @file_name ||= file_uri_parts[:file_name]
151
+ end
152
+
153
+ def template
154
+ params&.[]('template')&.first
155
+ end
156
+
157
+ def scheme
158
+ file_uri_parts&.[](:scheme)
159
+ end
160
+
161
+ def params
162
+ @params ||= CGI.parse(file_uri_parts[:query]) if file_uri_parts[:query]
163
+ end
164
+
165
+ def output_json(uri)
166
+ key = DerivativeRodeo::Services::ConvertUriViaTemplateService.call(from_uri: uri, template: template, adapter: self)
167
+ { key => [template] }.to_json
168
+ end
169
+
170
+ def file_uri_parts
171
+ return @file_uri_parts if @file_uri_parts
172
+ uri = URI.parse(file_uri)
173
+ @file_uri_parts = uri&.component&.inject({}) do |hash, component|
174
+ hash[component] = uri.send(component)
175
+ hash
176
+ end
177
+ @file_uri_parts[:region] = @file_uri_parts[:host]&.split('.')&.[](0)
178
+ path_parts = @file_uri_parts[:path]&.split('/')
179
+ @file_uri_parts[:account_id] = path_parts&.[](1)
180
+ @file_uri_parts[:queue_name] = path_parts&.[](2)
181
+ @file_uri_parts[:file_name] = path_parts&.[](-1)
182
+ @file_uri_parts[:file_dir] = path_parts&.[](3..-2)&.join('/')
183
+ @file_uri_parts
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DerivativeRodeo
4
+ TechnicalMetadata = Struct.new(:color, :num_components, :bits_per_component, :width, :height, :content_type,
5
+ keyword_init: true) do
6
+ alias_method :number_of_components, :num_components
7
+
8
+ def to_hash
9
+ {
10
+ color: color,
11
+ num_components: num_components,
12
+ bits_per_component: bits_per_component,
13
+ width: width,
14
+ height: height,
15
+ content_type: content_type
16
+ }
17
+ end
18
+
19
+ def monochrome?
20
+ color.to_s.casecmp('monochrome').zero?
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DerivativeRodeo
4
+ VERSION = '0.2.0'
5
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+
6
+ require 'byebug' if ENV['DEBUG']
7
+
8
+ require 'derivative_rodeo/errors'
9
+
10
+ require 'derivative_rodeo/configuration'
11
+ require 'derivative_rodeo/technical_metadata'
12
+ require 'derivative_rodeo/version'
13
+ # Base Location loads the other adapters
14
+ require 'derivative_rodeo/storage_locations/base_location'
15
+ require 'derivative_rodeo/generators/base_generator'
16
+ require 'derivative_rodeo/services/base_service'
17
+
18
+ ##
19
+ # DerivativeRodeo is a gem that allows you to generate derivative files from source files
20
+ # It is storage location agnostic, relying on {StorageLocations}. Files can be stored locally or in the cloud.
21
+ # {Generators} are designed to be simple to create and to short circut logic if a
22
+ # pre processed version exists
23
+ module DerivativeRodeo
24
+ ##
25
+ # The {Configuration} that the various processes in your implementation will use.
26
+ #
27
+ # @api public
28
+ #
29
+ # @yieldparam [Derivative::Rodeo::Configuration]
30
+ # @return [Derivative::Rodeo::Configuration]
31
+ def self.config
32
+ @config ||= Configuration.new
33
+ yield(@config) if block_given?
34
+ @config
35
+ end
36
+ end
metadata ADDED
@@ -0,0 +1,339 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: derivative-rodeo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Rob Kaufman
8
+ - Jeremy Friesen
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2023-05-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '5'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '5'
28
+ - !ruby/object:Gem::Dependency
29
+ name: aws-sdk-s3
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: aws-sdk-sqs
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: httparty
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: marcel
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ - !ruby/object:Gem::Dependency
85
+ name: mime-types
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: mini_magick
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: nokogiri
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: bixby
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ - !ruby/object:Gem::Dependency
141
+ name: byebug
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: rspec
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: '3.0'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '3.0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: rake
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: '13.0'
175
+ type: :development
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - "~>"
180
+ - !ruby/object:Gem::Version
181
+ version: '13.0'
182
+ - !ruby/object:Gem::Dependency
183
+ name: simplecov
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ - !ruby/object:Gem::Dependency
197
+ name: yard-activerecord
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ type: :development
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ - !ruby/object:Gem::Dependency
211
+ name: rspec-its
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - ">="
215
+ - !ruby/object:Gem::Version
216
+ version: '0'
217
+ type: :development
218
+ prerelease: false
219
+ version_requirements: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ - !ruby/object:Gem::Dependency
225
+ name: shoulda-matchers
226
+ requirement: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - ">="
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ type: :development
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - ">="
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ - !ruby/object:Gem::Dependency
239
+ name: solargraph
240
+ requirement: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - ">="
243
+ - !ruby/object:Gem::Version
244
+ version: '0'
245
+ type: :development
246
+ prerelease: false
247
+ version_requirements: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - ">="
250
+ - !ruby/object:Gem::Version
251
+ version: '0'
252
+ - !ruby/object:Gem::Dependency
253
+ name: yard
254
+ requirement: !ruby/object:Gem::Requirement
255
+ requirements:
256
+ - - ">="
257
+ - !ruby/object:Gem::Version
258
+ version: '0'
259
+ type: :development
260
+ prerelease: false
261
+ version_requirements: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - ">="
264
+ - !ruby/object:Gem::Version
265
+ version: '0'
266
+ description: An ETL Ecosystem for Derivative Processing.
267
+ email:
268
+ - rob@notch8.com
269
+ - jeremy.n.friesen@gmail.com
270
+ executables: []
271
+ extensions: []
272
+ extra_rdoc_files: []
273
+ files:
274
+ - Gemfile
275
+ - LICENSE
276
+ - README.md
277
+ - Rakefile
278
+ - derivative_rodeo.gemspec
279
+ - lib/derivative-rodeo.rb
280
+ - lib/derivative/rodeo.rb
281
+ - lib/derivative_rodeo.rb
282
+ - lib/derivative_rodeo/configuration.rb
283
+ - lib/derivative_rodeo/errors.rb
284
+ - lib/derivative_rodeo/generators/base_generator.rb
285
+ - lib/derivative_rodeo/generators/concerns/copy_file_concern.rb
286
+ - lib/derivative_rodeo/generators/copy_generator.rb
287
+ - lib/derivative_rodeo/generators/hocr_generator.rb
288
+ - lib/derivative_rodeo/generators/monochrome_generator.rb
289
+ - lib/derivative_rodeo/generators/pdf_split_generator.rb
290
+ - lib/derivative_rodeo/generators/thumbnail_generator.rb
291
+ - lib/derivative_rodeo/generators/word_coordinates_generator.rb
292
+ - lib/derivative_rodeo/services/base_service.rb
293
+ - lib/derivative_rodeo/services/convert_uri_via_template_service.rb
294
+ - lib/derivative_rodeo/services/extract_word_coordinates_from_hocr_sgml_service.rb
295
+ - lib/derivative_rodeo/services/image_identify_service.rb
296
+ - lib/derivative_rodeo/services/image_jp2_service.rb
297
+ - lib/derivative_rodeo/services/image_service.rb
298
+ - lib/derivative_rodeo/services/pdf_splitter/base.rb
299
+ - lib/derivative_rodeo/services/pdf_splitter/jpg_page.rb
300
+ - lib/derivative_rodeo/services/pdf_splitter/pages_summary.rb
301
+ - lib/derivative_rodeo/services/pdf_splitter/png_page.rb
302
+ - lib/derivative_rodeo/services/pdf_splitter/tiff_page.rb
303
+ - lib/derivative_rodeo/services/pdf_splitter_service.rb
304
+ - lib/derivative_rodeo/services/url_service.rb
305
+ - lib/derivative_rodeo/storage_locations/base_location.rb
306
+ - lib/derivative_rodeo/storage_locations/concerns/download_concern.rb
307
+ - lib/derivative_rodeo/storage_locations/file_location.rb
308
+ - lib/derivative_rodeo/storage_locations/http_location.rb
309
+ - lib/derivative_rodeo/storage_locations/https_location.rb
310
+ - lib/derivative_rodeo/storage_locations/s3_location.rb
311
+ - lib/derivative_rodeo/storage_locations/sqs_location.rb
312
+ - lib/derivative_rodeo/technical_metadata.rb
313
+ - lib/derivative_rodeo/version.rb
314
+ homepage: https://github.com/scientist-softserv/derivative_rodeo
315
+ licenses:
316
+ - APACHE-2.0
317
+ metadata:
318
+ homepage_uri: https://github.com/scientist-softserv/derivative_rodeo
319
+ source_code_uri: https://github.com/scientist-softserv/derivative_rodeo
320
+ post_install_message:
321
+ rdoc_options: []
322
+ require_paths:
323
+ - lib
324
+ required_ruby_version: !ruby/object:Gem::Requirement
325
+ requirements:
326
+ - - ">="
327
+ - !ruby/object:Gem::Version
328
+ version: 2.7.0
329
+ required_rubygems_version: !ruby/object:Gem::Requirement
330
+ requirements:
331
+ - - ">="
332
+ - !ruby/object:Gem::Version
333
+ version: '0'
334
+ requirements: []
335
+ rubygems_version: 3.3.7
336
+ signing_key:
337
+ specification_version: 4
338
+ summary: An ETL Ecosystem for Derivative Processing.
339
+ test_files: []