wax_tasks 1.0.2 → 1.1.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.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/lib/tasks/clobber.rake +16 -0
- data/lib/tasks/derivatives_iiif.rake +2 -0
- data/lib/tasks/derivatives_simple.rake +1 -0
- data/lib/tasks/pages.rake +1 -0
- data/lib/tasks/search.rake +1 -0
- data/lib/wax_tasks/asset.rb +8 -3
- data/lib/wax_tasks/collection.rb +42 -10
- data/lib/wax_tasks/collection/images.rb +10 -15
- data/lib/wax_tasks/collection/metadata.rb +1 -1
- data/lib/wax_tasks/config.rb +6 -2
- data/lib/wax_tasks/index.rb +1 -1
- data/lib/wax_tasks/item.rb +1 -1
- data/lib/wax_tasks/record.rb +5 -1
- data/lib/wax_tasks/site.rb +22 -4
- data/lib/wax_tasks/utils.rb +2 -2
- metadata +15 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e51a1e7e4f2b6e4f2a47ea31dafa67a25fa72b4792357fd7e3409f7f604ea40
|
4
|
+
data.tar.gz: 5f91332fb4f9ea78d922252d6d815d67a85738e37d055d8345935aadd0802f7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2392b9846200a684cf022e48071988c41e824d074d848ba686b320f826bb499d50bf3d656d1de6a2789209ccd2ddad057d687013d9d4eff4ddf76a111bc7c593
|
7
|
+
data.tar.gz: dd37457cd55d005ac5ed02a9de0b040a2d34db96e7fb28f40a218808d27e04a5d7299a223407146ae3412fd421e4df2095e976655ff72a4e27c21fd5f9849ebc
|
data/Gemfile
CHANGED
@@ -4,6 +4,8 @@ source 'https://rubygems.org'
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
# dev/test utilities
|
7
|
+
gem 'bundle-audit', require: false
|
8
|
+
gem 'diane', require: false
|
7
9
|
gem 'rubocop', require: false
|
8
|
-
gem 'simplecov', require: false
|
10
|
+
gem 'simplecov', '0.17.1', require: false
|
9
11
|
gem 'yard', require: false
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'wax_tasks'
|
4
|
+
|
5
|
+
namespace :wax do
|
6
|
+
desc 'destroy wax-generated collection files, including pages, derivatives, and search index(es)'
|
7
|
+
task :clobber do
|
8
|
+
args = ARGV.drop(1).each { |a| task a.to_sym }
|
9
|
+
args.reject! { |a| a.start_with? '-' }
|
10
|
+
|
11
|
+
raise WaxTasks::Error::MissingArguments, Rainbow("You must specify a collection after 'wax:clobber'").magenta if args.empty?
|
12
|
+
|
13
|
+
site = WaxTasks::Site.new
|
14
|
+
args.each { |a| site.clobber a }
|
15
|
+
end
|
16
|
+
end
|
@@ -7,6 +7,8 @@ namespace :wax do
|
|
7
7
|
desc 'generate iiif derivatives from local image files'
|
8
8
|
task :iiif do
|
9
9
|
args = ARGV.drop(1).each { |a| task a.to_sym }
|
10
|
+
args.reject! { |a| a.start_with? '-' }
|
11
|
+
|
10
12
|
raise WaxTasks::Error::MissingArguments, Rainbow("You must specify a collection after 'wax:derivatives:iiif'").magenta if args.empty?
|
11
13
|
|
12
14
|
site = WaxTasks::Site.new
|
@@ -7,6 +7,7 @@ namespace :wax do
|
|
7
7
|
desc 'generate iiif derivatives from local image files'
|
8
8
|
task :simple do
|
9
9
|
args = ARGV.drop(1).each { |a| task a.to_sym }
|
10
|
+
args.reject! { |a| a.start_with? '-' }
|
10
11
|
raise WaxTasks::Error::MissingArguments, Rainbow("You must specify a collection after 'wax:derivatives:simple'").magenta if args.empty?
|
11
12
|
|
12
13
|
site = WaxTasks::Site.new
|
data/lib/tasks/pages.rake
CHANGED
@@ -6,6 +6,7 @@ namespace :wax do
|
|
6
6
|
desc 'generate collection md pages from yaml or csv data source'
|
7
7
|
task :pages do
|
8
8
|
args = ARGV.drop(1).each { |a| task a.to_sym }
|
9
|
+
args.reject! { |a| a.start_with? '-' }
|
9
10
|
raise WaxTasks::Error::MissingArguments, Rainbow('You must specify a collection after wax:pages').magenta if args.empty?
|
10
11
|
|
11
12
|
site = WaxTasks::Site.new
|
data/lib/tasks/search.rake
CHANGED
@@ -6,6 +6,7 @@ namespace :wax do
|
|
6
6
|
desc 'build lunr search index (with default UI if UI=true)'
|
7
7
|
task :search do
|
8
8
|
args = ARGV.drop(1).each { |a| task a.to_sym }
|
9
|
+
args.reject! { |a| a.start_with? '-' }
|
9
10
|
raise WaxTasks::Error::MissingArguments, Rainbow('You must specify a collection after wax:search').magenta if args.empty?
|
10
11
|
|
11
12
|
site = WaxTasks::Site.new
|
data/lib/wax_tasks/asset.rb
CHANGED
@@ -3,10 +3,13 @@
|
|
3
3
|
#
|
4
4
|
module WaxTasks
|
5
5
|
Derivative = Struct.new(:path, :label, :img)
|
6
|
-
attr_reader :id, :path
|
7
6
|
|
8
7
|
#
|
9
8
|
class Asset
|
9
|
+
attr_reader :id, :path
|
10
|
+
|
11
|
+
|
12
|
+
|
10
13
|
def initialize(path, pid, variants)
|
11
14
|
@path = path
|
12
15
|
@pid = pid
|
@@ -17,7 +20,7 @@ module WaxTasks
|
|
17
20
|
#
|
18
21
|
#
|
19
22
|
def asset_id
|
20
|
-
id = File.basename
|
23
|
+
id = File.basename @path, '.*'
|
21
24
|
id.prepend "#{@pid}_" unless id == @pid
|
22
25
|
id
|
23
26
|
end
|
@@ -26,7 +29,7 @@ module WaxTasks
|
|
26
29
|
#
|
27
30
|
def simple_derivatives
|
28
31
|
@variants.map do |label, width|
|
29
|
-
img = MiniMagick::Image.open
|
32
|
+
img = MiniMagick::Image.open @path
|
30
33
|
if width > img.width
|
31
34
|
warn Rainbow("Tried to create derivative #{width}px wide, but asset #{@id} for item #{@pid} only has a width of #{img.width}px.").yellow
|
32
35
|
else
|
@@ -42,11 +45,13 @@ module WaxTasks
|
|
42
45
|
#
|
43
46
|
def to_iiif_image_record(is_only, index, base_opts)
|
44
47
|
opts = base_opts.clone
|
48
|
+
|
45
49
|
opts[:is_primary] = index.zero?
|
46
50
|
opts[:section_label] = "Page #{index + 1}" unless is_only
|
47
51
|
opts[:path] = @path
|
48
52
|
opts[:manifest_id] = @pid
|
49
53
|
opts[:id] = @id
|
54
|
+
opts[:variants] = @variants
|
50
55
|
|
51
56
|
WaxIiif::ImageRecord.new(opts)
|
52
57
|
end
|
data/lib/wax_tasks/collection.rb
CHANGED
@@ -7,23 +7,55 @@ module WaxTasks
|
|
7
7
|
#
|
8
8
|
class Collection
|
9
9
|
attr_reader :name, :config, :ext, :search_fields,
|
10
|
-
:page_source, :metadata_source, :imagedata_source
|
10
|
+
:page_source, :metadata_source, :imagedata_source,
|
11
|
+
:iiif_derivative_source, :simple_derivative_source
|
11
12
|
|
12
13
|
include Collection::Metadata
|
13
14
|
include Collection::Images
|
14
15
|
|
16
|
+
IMAGE_DERIVATIVE_DIRECTORY = 'img/derivatives'
|
17
|
+
DEFAULT_VARIANTS = { 'thumbnail' => 250, 'fullwidth' => 1140 }.freeze
|
18
|
+
|
15
19
|
#
|
16
20
|
#
|
17
21
|
def initialize(name, config, source, collections_dir, ext)
|
18
|
-
@name
|
19
|
-
@config
|
20
|
-
@page_extension
|
21
|
-
@site_source
|
22
|
-
@page_source
|
23
|
-
@metadata_source
|
24
|
-
@imagedata_source
|
25
|
-
@
|
26
|
-
@
|
22
|
+
@name = name
|
23
|
+
@config = config
|
24
|
+
@page_extension = ext
|
25
|
+
@site_source = source
|
26
|
+
@page_source = Utils.safe_join source, collections_dir, "_#{@name}"
|
27
|
+
@metadata_source = Utils.safe_join source, '_data', config.dig('metadata', 'source')
|
28
|
+
@imagedata_source = Utils.safe_join source, '_data', config.dig('images', 'source')
|
29
|
+
@iiif_derivative_source = Utils.safe_join source, IMAGE_DERIVATIVE_DIRECTORY, 'iiif'
|
30
|
+
@simple_derivative_source = Utils.safe_join source, IMAGE_DERIVATIVE_DIRECTORY, 'simple'
|
31
|
+
@search_fields = %w[pid label thumbnail permalink collection]
|
32
|
+
@image_variants = image_variants
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
#
|
37
|
+
def image_variants
|
38
|
+
vars = @config.dig('images', 'variants') || {}
|
39
|
+
DEFAULT_VARIANTS.merge vars
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
#
|
44
|
+
def clobber_pages
|
45
|
+
return unless Dir.exist? @page_source
|
46
|
+
puts Rainbow("Removing pages from #{@page_source}").cyan
|
47
|
+
FileUtils.remove_dir @page_source, true
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
#
|
52
|
+
def clobber_derivatives
|
53
|
+
[@iiif_derivative_source, @simple_derivative_source].each do |dir|
|
54
|
+
if Dir.exist? dir
|
55
|
+
puts Rainbow("Removing derivatives from #{dir}").cyan
|
56
|
+
FileUtils.remove_dir dir, true
|
57
|
+
end
|
58
|
+
end
|
27
59
|
end
|
28
60
|
end
|
29
61
|
end
|
@@ -10,14 +10,6 @@ module WaxTasks
|
|
10
10
|
class Collection
|
11
11
|
#
|
12
12
|
module Images
|
13
|
-
#
|
14
|
-
#
|
15
|
-
def image_variants
|
16
|
-
default_variants = { 'thumbnail' => 250, 'full' => 1140 }
|
17
|
-
custom_variants = @config.dig('images', 'variants') || {}
|
18
|
-
default_variants.merge custom_variants
|
19
|
-
end
|
20
|
-
|
21
13
|
#
|
22
14
|
#
|
23
15
|
def items_from_imagedata
|
@@ -46,6 +38,7 @@ module WaxTasks
|
|
46
38
|
next unless Dir.glob("#{target_dir}/*").empty?
|
47
39
|
|
48
40
|
puts Rainbow("\nPreprocessing #{path} into image files. This may take a minute.\n").cyan
|
41
|
+
|
49
42
|
opts = { output_dir: File.dirname(target_dir) }
|
50
43
|
WaxIiif::Utilities::PdfSplitter.split(path, opts)
|
51
44
|
end
|
@@ -53,13 +46,14 @@ module WaxTasks
|
|
53
46
|
|
54
47
|
#
|
55
48
|
#
|
56
|
-
def write_simple_derivatives
|
49
|
+
def write_simple_derivatives
|
57
50
|
puts Rainbow("Generating simple image derivatives for collection '#{@name}'\nThis might take awhile.").cyan
|
58
51
|
|
59
52
|
bar = ProgressBar.new(items_from_imagedata.length)
|
53
|
+
bar.write
|
60
54
|
items_from_imagedata.map do |item|
|
61
55
|
item.simple_derivatives.each do |d|
|
62
|
-
path = "#{
|
56
|
+
path = "#{@simple_derivative_source}/#{d.path}"
|
63
57
|
FileUtils.mkdir_p File.dirname(path)
|
64
58
|
next if File.exist? path
|
65
59
|
|
@@ -78,9 +72,10 @@ module WaxTasks
|
|
78
72
|
build_opts = {
|
79
73
|
base_url: "{{ '/' | absolute_url }}#{dir}",
|
80
74
|
output_dir: dir,
|
81
|
-
collection_label: @name
|
75
|
+
collection_label: @name,
|
76
|
+
variants: @image_variants.dup.tap { |h| h.delete 'full' }
|
82
77
|
}
|
83
|
-
WaxIiif::Builder.new
|
78
|
+
WaxIiif::Builder.new build_opts
|
84
79
|
end
|
85
80
|
|
86
81
|
#
|
@@ -113,10 +108,10 @@ module WaxTasks
|
|
113
108
|
|
114
109
|
#
|
115
110
|
#
|
116
|
-
def write_iiif_derivatives
|
111
|
+
def write_iiif_derivatives
|
117
112
|
items = items_from_imagedata
|
118
113
|
iiif_data = items.map(&:iiif_image_records).flatten
|
119
|
-
builder = iiif_builder
|
114
|
+
builder = iiif_builder @iiif_derivative_source
|
120
115
|
|
121
116
|
builder.load iiif_data
|
122
117
|
|
@@ -124,7 +119,7 @@ module WaxTasks
|
|
124
119
|
builder.process_data
|
125
120
|
records = items.map(&:record).compact
|
126
121
|
|
127
|
-
add_font_matter_to_json_files
|
122
|
+
add_font_matter_to_json_files @iiif_derivative_source
|
128
123
|
add_iiif_results_to_records records, builder.manifests
|
129
124
|
end
|
130
125
|
end
|
data/lib/wax_tasks/config.rb
CHANGED
data/lib/wax_tasks/index.rb
CHANGED
@@ -34,7 +34,7 @@ module WaxTasks
|
|
34
34
|
#
|
35
35
|
#
|
36
36
|
def write_to(dir)
|
37
|
-
file_path = WaxTasks::Utils.safe_join
|
37
|
+
file_path = WaxTasks::Utils.safe_join dir, @path
|
38
38
|
FileUtils.mkdir_p File.dirname(file_path)
|
39
39
|
File.open(file_path, 'w') do |f|
|
40
40
|
f.puts "---\nlayout: none\n---\n"
|
data/lib/wax_tasks/item.rb
CHANGED
@@ -47,7 +47,7 @@ module WaxTasks
|
|
47
47
|
if accepted_image_formats.include? @type
|
48
48
|
[Asset.new(@path, @pid, @variants)]
|
49
49
|
elsif @type == 'dir'
|
50
|
-
paths = Dir.glob("#{@path}/*{#{accepted_image_formats.join(',')}}")
|
50
|
+
paths = Dir.glob("#{@path}/*{#{accepted_image_formats.join(',')}}").sort
|
51
51
|
paths.map { |p| Asset.new(p, @pid, @variants) }
|
52
52
|
else
|
53
53
|
[]
|
data/lib/wax_tasks/record.rb
CHANGED
@@ -23,9 +23,13 @@ module WaxTasks
|
|
23
23
|
@hash.keys
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
26
|
+
# PATCH :: rename 'fullwidth' to 'full' to
|
27
|
+
# (1) avoid breaking wax_iiif with special 'full' variant label
|
28
|
+
# (2) avoid breaking wax_theme which still expects 'full' to provide an image path
|
29
|
+
# this can be deprecated when a new version of wax_theme looks for another fullsize key
|
27
30
|
#
|
28
31
|
def set(key, value)
|
32
|
+
key = 'full' if key == 'fullwidth'
|
29
33
|
@hash[key] = value
|
30
34
|
end
|
31
35
|
|
data/lib/wax_tasks/site.rb
CHANGED
@@ -5,7 +5,6 @@ module WaxTasks
|
|
5
5
|
#
|
6
6
|
class Site
|
7
7
|
attr_reader :config
|
8
|
-
IMAGE_DERIVATIVE_DIRECTORY = 'img/derivatives'
|
9
8
|
|
10
9
|
#
|
11
10
|
#
|
@@ -19,6 +18,26 @@ module WaxTasks
|
|
19
18
|
@config.collections
|
20
19
|
end
|
21
20
|
|
21
|
+
#
|
22
|
+
#
|
23
|
+
def clobber(name)
|
24
|
+
collection = @config.find_collection name
|
25
|
+
raise WaxTasks::Error::InvalidCollection if collection.nil?
|
26
|
+
|
27
|
+
collection.clobber_pages
|
28
|
+
collection.clobber_derivatives
|
29
|
+
|
30
|
+
@config.self.fetch('search', {}).each do |_name, search|
|
31
|
+
next unless search.key? 'index'
|
32
|
+
index = Utils.safe_join @config.source, search['index']
|
33
|
+
next unless File.exist? index
|
34
|
+
puts Rainbow("Removing search index #{index}").cyan
|
35
|
+
FileUtils.rm index
|
36
|
+
end
|
37
|
+
|
38
|
+
puts Rainbow("\nDone ✔").green
|
39
|
+
end
|
40
|
+
|
22
41
|
#
|
23
42
|
#
|
24
43
|
def generate_pages(name)
|
@@ -53,12 +72,11 @@ module WaxTasks
|
|
53
72
|
raise WaxTasks::Error::InvalidCollection if collection.nil?
|
54
73
|
raise WaxTasks::Error::InvalidConfig unless %w[iiif simple].include? type
|
55
74
|
|
56
|
-
output_dir = Utils.safe_join @config.source, IMAGE_DERIVATIVE_DIRECTORY, type
|
57
75
|
records = case type
|
58
76
|
when 'iiif'
|
59
|
-
collection.write_iiif_derivatives
|
77
|
+
collection.write_iiif_derivatives
|
60
78
|
when 'simple'
|
61
|
-
collection.write_simple_derivatives
|
79
|
+
collection.write_simple_derivatives
|
62
80
|
end
|
63
81
|
|
64
82
|
collection.update_metadata records
|
data/lib/wax_tasks/utils.rb
CHANGED
@@ -27,7 +27,7 @@ module WaxTasks
|
|
27
27
|
# @return [Array] same data unless a an item is missing the key `pid`
|
28
28
|
# @raise WaxTasks::Error::MissingPid
|
29
29
|
def self.assert_pids(data)
|
30
|
-
data.each_with_index { |d, i| raise Error::MissingPid, "Collection is missing pid for item #{i}." unless d.key? 'pid' }
|
30
|
+
data.each_with_index { |d, i| raise Error::MissingPid, "Collection is missing pid for item #{i}.\nHint: review common .csv formatting issues (such as hidden characters) in the documentation: https://minicomp.github.io/wiki/wax/preparing-your-collection-data/metadata/" unless d.key? 'pid' }
|
31
31
|
data
|
32
32
|
end
|
33
33
|
|
@@ -114,7 +114,7 @@ module WaxTasks
|
|
114
114
|
#
|
115
115
|
#
|
116
116
|
def self.safe_join(*args)
|
117
|
-
File.join(args.compact)
|
117
|
+
File.join(args.compact).sub %r{^\/}, ''
|
118
118
|
end
|
119
119
|
|
120
120
|
# Constructs the order variable for each page (if the collection
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wax_tasks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marii Nyrop
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: progress_bar
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '13.0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '13.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: safe_yaml
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,20 +70,14 @@ dependencies:
|
|
70
70
|
name: wax_iiif
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 0.1.2
|
76
|
-
- - "<"
|
73
|
+
- - "~>"
|
77
74
|
- !ruby/object:Gem::Version
|
78
75
|
version: '0.2'
|
79
76
|
type: :runtime
|
80
77
|
prerelease: false
|
81
78
|
version_requirements: !ruby/object:Gem::Requirement
|
82
79
|
requirements:
|
83
|
-
- - "
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
version: 0.1.2
|
86
|
-
- - "<"
|
80
|
+
- - "~>"
|
87
81
|
- !ruby/object:Gem::Version
|
88
82
|
version: '0.2'
|
89
83
|
- !ruby/object:Gem::Dependency
|
@@ -100,14 +94,15 @@ dependencies:
|
|
100
94
|
- - "~>"
|
101
95
|
- !ruby/object:Gem::Version
|
102
96
|
version: '3'
|
103
|
-
description: Rake tasks for minimal exhibition sites with
|
97
|
+
description: Rake tasks for minimal exhibition sites with Minicomp/Wax.
|
104
98
|
email:
|
105
|
-
-
|
99
|
+
- marii@nyu.edu
|
106
100
|
executables: []
|
107
101
|
extensions: []
|
108
102
|
extra_rdoc_files: []
|
109
103
|
files:
|
110
104
|
- Gemfile
|
105
|
+
- lib/tasks/clobber.rake
|
111
106
|
- lib/tasks/derivatives_iiif.rake
|
112
107
|
- lib/tasks/derivatives_simple.rake
|
113
108
|
- lib/tasks/pages.rake
|
@@ -131,7 +126,7 @@ licenses:
|
|
131
126
|
- MIT
|
132
127
|
metadata:
|
133
128
|
yard.run: yri
|
134
|
-
post_install_message:
|
129
|
+
post_install_message:
|
135
130
|
rdoc_options: []
|
136
131
|
require_paths:
|
137
132
|
- lib
|
@@ -148,11 +143,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
143
|
requirements:
|
149
144
|
- imagemagick
|
150
145
|
- ghostscript
|
151
|
-
rubyforge_project:
|
152
|
-
rubygems_version: 2.7.6
|
153
|
-
signing_key:
|
146
|
+
rubyforge_project:
|
147
|
+
rubygems_version: 2.7.6.2
|
148
|
+
signing_key:
|
154
149
|
specification_version: 4
|
155
|
-
summary: Rake tasks for minimal exhibition sites with
|
150
|
+
summary: Rake tasks for minimal exhibition sites with Minicomp/Wax.
|
156
151
|
test_files:
|
157
152
|
- spec/spec_helper.rb
|
158
153
|
- spec/setup.rb
|