wax_tasks 1.0.0.pre.beta → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ module WaxTasks
5
+ #
6
+ class Collection
7
+ #
8
+ module Metadata
9
+ #
10
+ #
11
+ def search_fields=(fields)
12
+ @search_fields.concat(fields).flatten.compact.uniq
13
+ end
14
+
15
+ #
16
+ #
17
+ def records_from_pages
18
+ paths = Dir.glob("#{@page_source}/*.{md, markdown}")
19
+ warn Rainbow("There are no pages in #{@page_source} to index.").orange if paths.empty?
20
+
21
+ paths.map do |path|
22
+ begin
23
+ content = WaxTasks::Utils.content_clean File.read(path)
24
+ Record.new(SafeYAML.load_file(path)).tap do |r|
25
+ r.set 'content', content
26
+ r.set 'permalink', "/#{@name}/#{r.pid}#{@ext}" unless r.permalink?
27
+ end
28
+ rescue StandardError => e
29
+ raise Error::PageLoad, "Cannot load page #{path}\n#{e}"
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ #
36
+ def records_from_metadata
37
+ raise Error::MissingSource, "Cannot find metadata source '#{@metadata_source}'" unless File.exist? @metadata_source
38
+
39
+ metadata = Utils.ingest @metadata_source
40
+ metadata.each_with_index.map do |meta, i|
41
+ Record.new(meta).tap do |r|
42
+ r.set 'order', Utils.padded_int(i, metadata.length) unless r.order?
43
+ r.set 'layout', @config['layout'] if @config.key? 'layout'
44
+ r.set 'collection', @name
45
+ end
46
+ end
47
+ end
48
+
49
+ #
50
+ #
51
+ def update_metadata(update)
52
+ records = consolidate_records records_from_metadata, update
53
+ reformatted = case File.extname @metadata_source
54
+ when '.csv'
55
+ csv_string records
56
+ when '.json'
57
+ json_string records
58
+ when /\.ya?ml/
59
+ yaml_string records
60
+ end
61
+ File.open(@metadata_source, 'w') { |f| f.puts reformatted }
62
+ end
63
+
64
+ #
65
+ #
66
+ def consolidate_records(original, new)
67
+ lost_record_pids = original.map(&:pid) - new.map(&:pid)
68
+ lost_record_pids.each do |pid|
69
+ new << original.find { |r| r.pid == pid }
70
+ end
71
+ new.sort_by(&:order)
72
+ end
73
+
74
+ #
75
+ #
76
+ def csv_string(records)
77
+ keys = records.flat_map(&:keys).uniq
78
+ CSV.generate do |csv|
79
+ csv << keys
80
+ records.each do |r|
81
+ csv << keys.map { |k| r.hash.fetch(k, '') }
82
+ end
83
+ end
84
+ end
85
+
86
+ #
87
+ #
88
+ def json_string(records)
89
+ hashes = records.map(&:hash)
90
+ JSON.pretty_generate hashes
91
+ end
92
+
93
+ #
94
+ #
95
+ def yaml_string(records)
96
+ hashes = records.map(&:hash)
97
+ hashes.to_yaml
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaxTasks
4
+ #
5
+ class Config
6
+ attr_reader :collections
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ @collections = process_collections
11
+ end
12
+
13
+ #
14
+ #
15
+ def source
16
+ @config.dig 'source'
17
+ end
18
+
19
+ #
20
+ #
21
+ def collections_dir
22
+ @config.dig 'collections_dir'
23
+ end
24
+
25
+ #
26
+ # Contructs permalink extension from site `permalink` variable
27
+ #
28
+ # @return [String] the end of the permalink, either '/' or '.html'
29
+ def ext
30
+ case @config.dig 'permalink'
31
+ when 'pretty' || '/'
32
+ '/'
33
+ else
34
+ '.html'
35
+ end
36
+ end
37
+
38
+ #
39
+ #
40
+ def process_collections
41
+ if @config.key? 'collections'
42
+ @config['collections'].map do |k, v|
43
+ WaxTasks::Collection.new(k, v, source, collections_dir, ext)
44
+ end
45
+ else
46
+ []
47
+ end
48
+ end
49
+
50
+ #
51
+ #
52
+ def search(name)
53
+ search_config = @config.dig 'search', name
54
+ raise WaxTasks::Error::InvalidConfig if search_config.nil?
55
+ raise WaxTasks::Error::InvalidConfig unless search_config.dig('collections').is_a? Hash
56
+
57
+ search_config['collections'] = search_config['collections'].map do |k, v|
58
+ fields = v.fetch('fields', [])
59
+ fields << 'content' if v.fetch('content', false)
60
+ find_collection(k).tap { |c| c.search_fields = fields }
61
+ end
62
+
63
+ search_config
64
+ end
65
+
66
+ #
67
+ #
68
+ def find_collection(name)
69
+ collection = @collections.find { |c| c.name == name }
70
+ raise WaxTasks::Error::InvalidCollection, "Cannot find requested collection '#{name}'" if collection.nil?
71
+
72
+ collection
73
+ end
74
+ end
75
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WaxTasks
2
4
  # Custom WaxTasks Errors module
3
5
  module Error
4
6
  # Custom WaxTasks Error class with magenta console output
5
7
  class WaxTasksError < StandardError
6
8
  def initialize(msg = '')
7
- super(msg.magenta)
9
+ super(Rainbow(msg).magenta)
8
10
  end
9
11
  end
10
12
 
@@ -13,8 +15,8 @@ module WaxTasks
13
15
  class MissingArguments < WaxTasksError; end
14
16
 
15
17
  # Custom Error:
16
- # Site config cannot be found / parsed
17
- class InvalidSiteConfig < WaxTasksError; end
18
+ # Site config cannot be found / parsed for the task at hand
19
+ class InvalidConfig < WaxTasksError; end
18
20
 
19
21
  # Custom Error:
20
22
  # Collection specified cannot be found / parsed in site config
@@ -22,58 +24,42 @@ module WaxTasks
22
24
 
23
25
  # Custom Error:
24
26
  # Collection data source type is not allowed or is an invalid file
25
- class InvalidSource < WaxTasksError; end
27
+ class InvalidSource < WaxTasksError; end
26
28
 
27
29
  # Custom Error:
28
30
  # Data source file could not be found
29
- class MissingSource < WaxTasksError; end
30
-
31
- # Custom Error:
32
- # While loading markdown pages to index, one could not be read
33
- class LunrPageLoad < WaxTasksError; end
34
-
35
- # Custom Error:
36
- # Lunr collection does not have fields specified to index
37
- class MissingFields < WaxTasksError; end
31
+ class MissingSource < WaxTasksError; end
38
32
 
39
33
  # Custom Error:
40
- # Page layout was not specified for a pagemaster collection
41
- class MissingLayout < WaxTasksError; end
34
+ # Could not load collection page(s)
35
+ class PageLoad < WaxTasksError; end
42
36
 
43
37
  # Custom Error:
44
38
  # Collection item does not have a required pid value
45
- class MissingPid < WaxTasksError; end
39
+ class MissingPid < WaxTasksError; end
46
40
 
47
41
  # Custom Error:
48
42
  # Collection item has a non-unique pud value
49
- class NonUniquePid < WaxTasksError; end
43
+ class NonUniquePid < WaxTasksError; end
50
44
 
51
45
  # Custom Error:
52
46
  # Collection page item could not be generated
53
- class PageFailure < WaxTasksError; end
47
+ class PageFailure < WaxTasksError; end
54
48
 
55
49
  # Custom Error:
56
50
  # CSV file failed to lint + could not be loaded
57
- class InvalidCSV < WaxTasksError; end
51
+ class InvalidCSV < WaxTasksError; end
58
52
 
59
53
  # Custom Error:
60
54
  # JSON file failed to lint + could not be loaded
61
- class InvalidJSON < WaxTasksError; end
55
+ class InvalidJSON < WaxTasksError; end
62
56
 
63
57
  # Custom Error:
64
58
  # YAML file failed to lint + could not be loaded
65
- class InvalidYAML < WaxTasksError; end
66
-
67
- # Custom Error:
68
- # No collections in site config have lunr_index parameters
69
- class NoLunrCollections < WaxTasksError; end
70
-
71
- # Custom Error:
72
- # Cannot find _site directory to push to GitHub
73
- class MissingSite < WaxTasksError; end
59
+ class InvalidYAML < WaxTasksError; end
74
60
 
75
61
  # Custom Error:
76
- # Cannot find IIIF source image files
77
- class MissingIiifSrc < WaxTasksError; end
62
+ # Search index in site config has no valid collections to index
63
+ class NoSearchCollections < WaxTasksError; end
78
64
  end
79
65
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaxTasks
4
+ #
5
+ class Index
6
+ attr_reader :path, :collections
7
+
8
+ def initialize(config)
9
+ @config = config
10
+ @collections = config.dig 'collections'
11
+ @path = config.dig 'index'
12
+
13
+ raise WaxTasks::Error::NoSearchCollections if @collections.nil?
14
+ raise WaxTasks::Error::InvalidConfig if @path.nil?
15
+
16
+ @records = records
17
+ end
18
+
19
+ #
20
+ #
21
+ def records
22
+ lunr_id = 0
23
+ @collections.flat_map do |collection|
24
+ collection.records_from_pages.each.flat_map do |r|
25
+ r.keep_only collection.search_fields
26
+ r.set 'lunr_id', lunr_id
27
+ r.lunr_normalize_values
28
+ lunr_id += 1
29
+ r
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ #
36
+ def write_to(dir)
37
+ file_path = WaxTasks::Utils.safe_join Dir.pwd, dir, path
38
+ FileUtils.mkdir_p File.dirname(file_path)
39
+ File.open(file_path, 'w') do |f|
40
+ f.puts "---\nlayout: none\n---\n"
41
+ f.puts JSON.pretty_generate(@records.map(&:hash))
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaxTasks
4
+ #
5
+ class Item
6
+ attr_accessor :record, :iiif_config
7
+ attr_reader :pid
8
+
9
+ #
10
+ #
11
+ #
12
+ def initialize(path, variants)
13
+ @path = path
14
+ @variants = variants
15
+ @type = type
16
+ @pid = File.basename @path, '.*'
17
+ @assets = assets
18
+ end
19
+
20
+ #
21
+ #
22
+ def accepted_image_formats
23
+ %w[.png .jpg .jpeg .tiff]
24
+ end
25
+
26
+ #
27
+ #
28
+ def type
29
+ Dir.exist?(@path) ? 'dir' : File.extname(@path)
30
+ end
31
+
32
+ #
33
+ #
34
+ def valid?
35
+ accepted_image_formats.include?(@type) || @type == 'dir'
36
+ end
37
+
38
+ #
39
+ #
40
+ def record?
41
+ @record.is_a? Record
42
+ end
43
+
44
+ #
45
+ #
46
+ def assets
47
+ if accepted_image_formats.include? @type
48
+ [Asset.new(@path, @pid, @variants)]
49
+ elsif @type == 'dir'
50
+ paths = Dir.glob("#{@path}/*{#{accepted_image_formats.join(',')}}")
51
+ paths.map { |p| Asset.new(p, @pid, @variants) }
52
+ else
53
+ []
54
+ end
55
+ end
56
+
57
+ #
58
+ #
59
+ def simple_derivatives
60
+ @assets.map(&:simple_derivatives).flatten
61
+ end
62
+
63
+ #
64
+ #
65
+ def logo
66
+ logo_uri = @iiif_config&.dig 'logo'
67
+ "{{ '#{logo_uri}' | absolute_url }}" if logo_uri
68
+ end
69
+
70
+ def label
71
+ label_key = @iiif_config&.dig 'label'
72
+ if @record && label_key
73
+ @record.hash.dig label_key
74
+ else
75
+ @pid
76
+ end
77
+ end
78
+
79
+ #
80
+ #
81
+ def description
82
+ description_key = @iiif_config&.dig 'description'
83
+ @record.hash.dig description_key if description_key && @record
84
+ end
85
+
86
+ #
87
+ #
88
+ def attribution
89
+ attribution_key = @iiif_config.dig 'attribution'
90
+ @record.hash.dig attribution_key if attribution_key && @record
91
+ end
92
+
93
+ #
94
+ #
95
+ def iiif_image_records
96
+ opts = base_opts.clone
97
+ is_only = @assets.length == 1
98
+
99
+ @assets.map.with_index do |asset, i|
100
+ asset.to_iiif_image_record(is_only, i, opts)
101
+ end
102
+ end
103
+
104
+ #
105
+ #
106
+ def base_opts
107
+ opts = { label: label }
108
+ return opts unless @iiif_config
109
+
110
+ opts[:logo] = logo if logo
111
+ opts[:description] = description.to_s if description
112
+ opts[:attribution] = attribution.to_s if attribution
113
+ opts
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WaxTasks
4
+ #
5
+ class Record
6
+ attr_reader :pid, :hash, :order
7
+
8
+ def initialize(hash)
9
+ @hash = hash
10
+ @pid = @hash.dig 'pid'
11
+ @order = @hash.dig 'order'
12
+ end
13
+
14
+ #
15
+ #
16
+ def lunr_normalize_values
17
+ @hash.transform_values { |v| Utils.lunr_normalize v }
18
+ end
19
+
20
+ #
21
+ #
22
+ def keys
23
+ @hash.keys
24
+ end
25
+
26
+ #
27
+ #
28
+ def set(key, value)
29
+ @hash[key] = value
30
+ end
31
+
32
+ #
33
+ #
34
+ def permalink?
35
+ @hash.key? 'permalink'
36
+ end
37
+
38
+ #
39
+ #
40
+ def order?
41
+ @order.is_a? String
42
+ end
43
+
44
+ #
45
+ #
46
+ def keep_only(fields)
47
+ @hash.select! { |k, _v| fields.include? k }
48
+ end
49
+
50
+ #
51
+ #
52
+ def write_to_page(dir)
53
+ raise Error::MissingPid if @pid.nil?
54
+
55
+ path = "#{dir}/#{Utils.slug(@pid)}.md"
56
+ if File.exist? path
57
+ 0
58
+ else
59
+ FileUtils.mkdir_p File.dirname(path)
60
+ File.open(path, 'w') { |f| f.puts "#{@hash.to_yaml}---" }
61
+ 1
62
+ end
63
+ end
64
+ end
65
+ end