forked from CollectionBuilder/collectionbuilder-csv
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Rakefile
191 lines (165 loc) · 6.13 KB
/
Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# frozen_string_literal: true
# CollectionBuilder-CSV helper tasks
require 'csv'
require 'fileutils'
require 'image_optim' unless Gem.win_platform?
require 'mini_magick'
require 'benchmark'
###############################################################################
# TASK: deploy
###############################################################################
desc 'Build site with production env'
task :deploy do
ENV['JEKYLL_ENV'] = 'production'
system('bundle', 'exec', 'jekyll', 'build')
end
###############################################################################
# Helper Functions
###############################################################################
def prompt_user_for_confirmation(message)
response = nil
loop do
print "#{message} (Y/n): "
$stdout.flush
response = case $stdin.gets.chomp.downcase
when '', 'y' then true
when 'n' then false
end
break unless response.nil?
puts 'Please enter "y" or "n"'
end
response
end
def process_and_optimize_image(filename, file_type, output_filename, size, density)
image_optim = ImageOptim.new(svgo: false) unless Gem.win_platform?
if filename == output_filename && file_type == :image && !Gem.win_platform?
puts "Optimizing: #{filename}"
begin
image_optim.optimize_image!(output_filename)
rescue StandardError => e
puts "Error optimizing #{filename}: #{e.message}"
end
elsif filename == output_filename && file_type == :pdf
puts "Skipping: #{filename}"
else
puts "Creating: #{output_filename}"
begin
if file_type == :pdf
inputfile = "#{filename}[0]"
magick = MiniMagick::Tool::Convert.new
magick.density(density)
magick << inputfile
magick.resize(size)
magick.flatten
magick << output_filename
magick.call
else
image = MiniMagick::Image.open(filename)
image.format('jpg')
image.resize(size)
image.flatten
image.write(output_filename)
end
image_optim.optimize_image!(output_filename) unless Gem.win_platform?
rescue StandardError => e
puts "Error creating #{filename}: #{e.message}"
end
end
end
###############################################################################
# TASK: generate_derivatives
###############################################################################
desc 'Generate derivative image files from collection objects'
task :generate_derivatives, [:thumbs_size, :small_size, :density, :missing, :compress_originals] do |_t, args|
# set default arguments
# default image size is based on max pixel width they will appear in the base template features
args.with_defaults(
thumbs_size: '450x',
small_size: '800x800',
density: '300',
missing: 'true',
compress_originals: 'false'
)
# set the folder locations
objects_dir = 'objects'
thumb_image_dir = 'objects/thumbs'
small_image_dir = 'objects/small'
# Ensure that the output directories exist.
[thumb_image_dir, small_image_dir].each do |dir|
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
end
# support these file types
EXTNAME_TYPE_MAP = {
'.jpeg' => :image,
'.jpg' => :image,
'.pdf' => :pdf,
'.png' => :image,
'.tif' => :image,
'.tiff' => :image
}.freeze
# CSV output
list_name = File.join(objects_dir, 'object_list.csv')
field_names = 'filename,object_location,image_small,image_thumb'.split(',')
CSV.open(list_name, 'w') do |csv|
csv << field_names
# Iterate over all files in the objects directory.
Dir.glob(File.join(objects_dir, '*')).each do |filename|
# Skip subdirectories and the README.md file.
if File.directory?(filename) || File.basename(filename) == 'README.md' || File.basename(filename) == 'object_list.csv'
next
end
# Determine the file type and skip if unsupported.
extname = File.extname(filename).downcase
file_type = EXTNAME_TYPE_MAP[extname]
unless file_type
puts "Skipping file with unsupported extension: #{filename}"
csv << ["#{File.basename(filename)}", "/#{filename}", nil, nil]
next
end
# Get the lowercase filename without any leading path and extension.
base_filename = File.basename(filename, '.*').downcase
# Optimize the original image.
if args.compress_originals == 'true'
puts "Optimizing: #{filename}"
process_and_optimize_image(filename, file_type, filename, nil, nil)
end
# Generate the thumb image.
thumb_filename = File.join(thumb_image_dir, "#{base_filename}_th.jpg")
if args.missing == 'false' || !File.exist?(thumb_filename)
process_and_optimize_image(filename, file_type, thumb_filename, args.thumbs_size, args.density)
else
puts "Skipping: #{thumb_filename} already exists"
end
# Generate the small image.
small_filename = File.join([small_image_dir, "#{base_filename}_sm.jpg"])
if (args.missing == 'false') || !File.exist?(small_filename)
process_and_optimize_image(filename, file_type, small_filename, args.small_size, args.density)
else
puts "Skipping: #{small_filename} already exists"
end
csv << ["#{File.basename(filename)}", "/#{filename}", "/#{small_filename}", "/#{thumb_filename}"]
end
end
puts "\e[32mSee '#{list_name}' for list of objects and derivatives created.\e[0m"
end
###############################################################################
# TASK: benchmark
###############################################################################
desc "Benchmark the build process of CollectionBuilder"
task :benchmark_build do
n = 10
total_time = 0
n.times do |i|
puts "Running build ##{i+1}..."
ENV['JEKYLL_ENV'] = 'production'
system('bundle', 'exec', 'jekyll', 'clean')
build_time = Benchmark.realtime do
ENV['JEKYLL_ENV'] = 'production'
system('bundle', 'exec', 'jekyll', 'build')
end
puts "Time for build ##{i+1}: #{build_time.round(2)} seconds"
total_time += build_time
end
average_time = total_time / n
puts "Average build time over #{n} runs: #{average_time.round(2)} seconds"
end