wax_tasks 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dcf7d468f41464dd970e43b0f4a22b857b1e412872d9fb1a3467ab63d8482b80
4
- data.tar.gz: 3d8b8640ec00cbf86ed1c06b39935745abf24001ee858d9e9a7dec2ee6d075f9
3
+ metadata.gz: a05cb7d5dd4a2218f7c20546a7bb40762ff50c1382457ab5dc8573f5a8131eb9
4
+ data.tar.gz: d80600e1d481d7aa91c78fc38fb214aa234f86859ff1ae8660310f17586b5ed0
5
5
  SHA512:
6
- metadata.gz: f2315b406a0d970572b617571e140a29e82a09125dfbc5a700059f21da63b4b9f5e5e9bb4195dcdcdcb9d904d33f7319605c9b8c581a70fc1fb233eb41635e03
7
- data.tar.gz: 1742b039101f3f9b7962dbe1685d0900f1da91a5bc50b263c4987bffae0ae5c6532e0ba61b473e90b9c72f687c8a529fa1bf0625df980e51bb3ba975e261b054
6
+ metadata.gz: 36879c674be8917117b4219e485c987386370c8d8c89d6d8fdc8bc0149a6d05265ede31b4f4720a1aa48d9cca5db1d2e10a8511663f0aaab9ee34a48bbb96edd
7
+ data.tar.gz: 8b9ba90bd8a415fcacc969bd787862d8d37e1b7f222341bd23a9c9b08c33cd5eb9fd641f31d5a02b0df99707009ffb57969d945d462698df10c45bde58d0e758
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
+ # dev/test utilities
4
5
  gem 'diane', require: false
5
6
  gem 'rubocop', require: false
6
7
  gem 'simplecov', require: false
8
+ gem 'yard', require: false
@@ -1,9 +1,11 @@
1
1
  require 'wax_tasks'
2
2
 
3
3
  namespace :wax do
4
+ desc 'generate iiif derivatives from local image files'
4
5
  task :iiif do
5
6
  ARGS = ARGV.drop(1).each { |a| task a.to_sym }
6
7
  abort "You must specify a collection after 'wax:iiif'" if ARGS.empty?
7
- ARGS.each { |name| IiifCollection.new(name).process }
8
+ task_runner = WaxTasks::TaskRunner.new
9
+ task_runner.iiif(ARGS)
8
10
  end
9
11
  end
@@ -0,0 +1,14 @@
1
+ require 'wax_tasks'
2
+
3
+ namespace :wax do
4
+ desc 'write a simple package.json for monitoring js dependencies'
5
+ task :jspackage do
6
+ task_runner = WaxTasks::TaskRunner.new
7
+ package = task_runner.js_package
8
+ unless package.empty?
9
+ path = WaxTasks::Utils.make_path(task_runner.site[:source_dir],
10
+ 'package.json')
11
+ File.open(path, 'w') { |f| f.write(package.to_json) }
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ require 'wax_tasks'
2
+
3
+ namespace :wax do
4
+ desc 'build lunr search index (with default UI if UI=true)'
5
+ task :lunr do
6
+ task_runner = WaxTasks::TaskRunner.new
7
+ task_runner.lunr(generate_ui: !!ENV['UI'])
8
+ end
9
+ end
@@ -4,7 +4,8 @@ namespace :wax do
4
4
  desc 'generate collection md pages from yaml or csv data source'
5
5
  task :pagemaster do
6
6
  ARGS = ARGV.drop(1).each { |a| task a.to_sym }
7
- abort "You must specify a collection after 'wax:pagemaster'" if ARGS.empty?
8
- ARGS.each { |name| PagemasterCollection.new(name).generate_pages }
7
+ raise 'You must specify a collection after wax:pagemaster' if ARGS.empty?
8
+ task_runner = WaxTasks::TaskRunner.new
9
+ task_runner.pagemaster(ARGS)
9
10
  end
10
11
  end
@@ -0,0 +1,13 @@
1
+ require 'wax_tasks'
2
+
3
+ namespace :wax do
4
+ desc 'push compiled Jekyll site to git branch BRANCH'
5
+ task :push do
6
+ ARGS = ARGV.drop(1).each { |a| task a.to_sym }
7
+ raise 'You must specify a branch after \'wax:push:branch\'' if ARGS.empty?
8
+
9
+ target = WaxTasks::Utils.slug(ARGS.first)
10
+ task_runner = WaxTasks::TaskRunner.new
11
+ task_runner.push_branch(target)
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
1
  require 'html-proofer'
2
2
 
3
3
  namespace :wax do
4
- desc 'run htmlproofer, rspec if exists'
4
+ desc 'run htmlproofer, rspec if .rspec file exists'
5
5
  task :test do
6
6
  opts = {
7
7
  check_external_hash: true,
@@ -0,0 +1,110 @@
1
+ require 'jekyll'
2
+ require 'logger'
3
+ require 'time'
4
+ require 'tmpdir'
5
+
6
+ module WaxTasks
7
+ # Parent class representing a Git Branch
8
+ # that cannot be created directly. Only child classes
9
+ # (LocalBranch, TravisBranch) can be initialized.
10
+ #
11
+ # @attr target [String] the name of the Git branch to deploy to
12
+ # @attr origin [String] the current repository remote
13
+ # @attr commit_msg [String] the commit message to use on push
14
+ # @attr baseurl [String] the site baseurl to build with (if on gh-pages)
15
+ # @attr success_msg [String] informative message to be output to console
16
+ class Branch
17
+ attr_reader :target, :origin, :commit_msg, :baseurl, :success
18
+ private_class_method :new
19
+
20
+ # This method ensures child classes can be instantiated eventhough
21
+ # Branch.new cannot be.
22
+ def self.inherited(*)
23
+ public_class_method :new
24
+ end
25
+
26
+ # @param site [Hash] the site config from (TaskRunner.site)
27
+ # @param target [String] the name of the Git branch to deploy to
28
+ def initialize(site, target)
29
+ @site = site
30
+ @target = target
31
+ end
32
+
33
+ # Rebuild the Jekyll site with branch @baseurl
34
+ # @return [Nil]
35
+ def rebuild
36
+ if @baseurl.empty?
37
+ msg = 'Building the gh-pages _site without a baseurl is not recommended'
38
+ Logger.new($stdout).warn(msg.orange)
39
+ end
40
+ FileUtils.rm_r(SITE_DIR) if File.directory?(SITE_DIR)
41
+ opts = {
42
+ source: '.',
43
+ destination: SITE_DIR,
44
+ baseurl: @baseurl,
45
+ verbose: true
46
+ }
47
+ Jekyll::Site.new(Jekyll.configuration(opts)).process
48
+ end
49
+
50
+ # Add, commmit, and push compiled Jekyll site to @target branch
51
+ # @return [Nil]
52
+ def push
53
+ if @site[:env] == 'prod'
54
+ rebuild if @target == 'gh-pages'
55
+ raise Error::MissingSite, "Cannot find #{SITE_DIR}" unless Dir.exist? SITE_DIR
56
+ Dir.chdir(SITE_DIR)
57
+ system 'git init && git add .'
58
+ system "git commit -m '#{@commit_msg}'"
59
+ system "git remote add origin #{@origin}"
60
+ puts @success_msg.cyan
61
+ system "git push origin master:refs/heads/#{@target} --force"
62
+ else
63
+ puts "Skipping build for branch '#{@target}' on env='test'".orange
64
+ end
65
+ end
66
+ end
67
+
68
+ # Branch object for `$ wax:push` task when run on Travis-CI VM
69
+ # using encrypted Travis environment vars
70
+ #
71
+ # @attr repo_slug [String] the 'user/repo_name'
72
+ # @attr user [String] the GitHub user making the commit/push
73
+ # @attr token [String] secret git access token
74
+ # @attr commit_msg [String] the commit message to use on push
75
+ # @attr origin [String] the current repository remote
76
+ # @attr baseurl [String] the site baseurl to build with (if on gh-pages)
77
+ # @attr success_msg [String] informative message to be output to console
78
+ class TravisBranch < Branch
79
+ def initialize(site, target)
80
+ super(site, target)
81
+
82
+ @repo_slug = ENV['TRAVIS_REPO_SLUG']
83
+ @user = @repo_slug.split('/').first
84
+ @token = ENV['ACCESS_TOKEN']
85
+
86
+ @commit_msg = "Updated via #{ENV['TRAVIS_COMMIT']} @#{Time.now.utc}"
87
+ @origin = "https://#{@user}:#{@token}@github.com/#{@repo_slug}.git"
88
+ @baseurl = @repo_slug.split('/').last
89
+ @success_msg = "Deploying to #{@target} branch from Travis as #{@user}."
90
+ end
91
+ end
92
+
93
+ # Branch object for `$ wax:push` task when run on local machine
94
+ # using local credentials
95
+ #
96
+ # @attr origin [String] the current repository remote
97
+ # @attr commit_msg [String] the commit message to use on push
98
+ # @attr baseurl [String] the site baseurl to build with (if on gh-pages)
99
+ # @attr success_msg [String] informative message to be output to console
100
+ class LocalBranch < Branch
101
+ def initialize(site, target)
102
+ super(site, target)
103
+
104
+ @origin = `git config --get remote.origin.url`.strip
105
+ @commit_msg = "Updated via local task at #{Time.now.utc}"
106
+ @baseurl = @origin.split('/').last.gsub('.git', '')
107
+ @success_msg = "Deploying to #{@target} branch from local task."
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,61 @@
1
+ module WaxTasks
2
+ # Parent class representing a Jekyll collection
3
+ # that cannot be created directly. Only child classes
4
+ # (IiifCollection, LunrCollection, PagemasterCollection)
5
+ # can be initialized.
6
+ #
7
+ # @attr config [Hash] the collection config within site config
8
+ # @attr name [String] the name of the collection in site:collections
9
+ # @attr page_dir [String] the directory path for generated collection pages
10
+ # @attr site [Hash] the site config
11
+ class Collection
12
+ attr_reader :name, :page_dir
13
+ private_class_method :new
14
+
15
+ # This method ensures child classes can be instantiated though
16
+ # Collection.new cannot be.
17
+ def self.inherited(*)
18
+ public_class_method :new
19
+ end
20
+
21
+ # Creates a new collection with name @name given site config @site
22
+ #
23
+ # @param name [String] the name of the collection in site:collections
24
+ # @param site [Hash] the site config
25
+ def initialize(name, site)
26
+ @name = name
27
+ @site = site
28
+ @config = collection_config
29
+ @page_dir = Utils.make_path(@site[:source_dir],
30
+ @site[:collections_dir],
31
+ @name)
32
+ end
33
+
34
+ # Finds the collection config within the site config
35
+ #
36
+ # @return [Hash] the config for the collection
37
+ def collection_config
38
+ @site[:collections].fetch(@name)
39
+ rescue StandardError => e
40
+ raise Error::InvalidCollection, "Cannot load collection config for #{@name}.\n#{e}"
41
+ end
42
+
43
+ # Ingests the collection source data as an Array of Hashes
44
+ #
45
+ # @param source [String] the path to the CSV, JSON, or YAML source file
46
+ # @return [Array] the collection data
47
+ def ingest_file(source)
48
+ raise Error::MissingSource, "Cannot find #{source}" unless File.exist? source
49
+
50
+ case File.extname(source)
51
+ when '.csv' then data = WaxTasks::Utils.validate_csv(source)
52
+ when '.json' then data = WaxTasks::Utils.validate_json(source)
53
+ when /\.ya?ml/ then data = WaxTasks::Utils.validate_yaml(source)
54
+ else raise Error::InvalidSource, "Cannot load #{File.extname(source)} files. Culprit: #{source}"
55
+ end
56
+
57
+ WaxTasks::Utils.assert_pids(data)
58
+ WaxTasks::Utils.assert_unique(data)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,71 @@
1
+ module WaxTasks
2
+ # Custom WaxTasks Errors module
3
+ module Error
4
+ # Custom WaxTasks Error class with magenta console output
5
+ class WaxTasksError < StandardError
6
+ def initialize(msg = '')
7
+ super(msg.magenta)
8
+ end
9
+ end
10
+
11
+ # Custom Error:
12
+ # Site config cannot be found / parsed
13
+ class InvalidSiteConfig < WaxTasksError; end
14
+
15
+ # Custom Error:
16
+ # Collection specified cannot be found / parsed in site config
17
+ class InvalidCollection < WaxTasksError; end
18
+
19
+ # Custom Error:
20
+ # Collection data source type is not allowed or is an invalid file
21
+ class InvalidSource < WaxTasksError; end
22
+
23
+ # Custom Error:
24
+ # Data source file could not be found
25
+ class MissingSource < WaxTasksError; end
26
+
27
+ # Custom Error:
28
+ # While loading markdown pages to index, one could not be read
29
+ class LunrPageLoad < WaxTasksError; end
30
+
31
+ # Custom Error:
32
+ # Lunr collection does not have fields specified to index
33
+ class MissingFields < WaxTasksError; end
34
+
35
+ # Custom Error:
36
+ # Page layout was not specified for a pagemaster collection
37
+ class MissingLayout < WaxTasksError; end
38
+
39
+ # Custom Error:
40
+ # Collection item does not have a required pid value
41
+ class MissingPid < WaxTasksError; end
42
+
43
+ # Custom Error:
44
+ # Collection item has a non-unique pud value
45
+ class NonUniquePid < WaxTasksError; end
46
+
47
+ # Custom Error:
48
+ # Collection page item could not be generated
49
+ class PageFailure < WaxTasksError; end
50
+
51
+ # Custom Error:
52
+ # CSV file failed to lint + could not be loaded
53
+ class InvalidCSV < WaxTasksError; end
54
+
55
+ # Custom Error:
56
+ # JSON file failed to lint + could not be loaded
57
+ class InvalidJSON < WaxTasksError; end
58
+
59
+ # Custom Error:
60
+ # YAML file failed to lint + could not be loaded
61
+ class InvalidYAML < WaxTasksError; end
62
+
63
+ # Custom Error:
64
+ # No collections in site config have lunr_index parameters
65
+ class NoLunrCollections < WaxTasksError; end
66
+
67
+ # Custom Error:
68
+ # Cannot find _site directory to push to GitHub
69
+ class MissingSite < WaxTasksError; end
70
+ end
71
+ end
@@ -0,0 +1,105 @@
1
+ require 'wax_iiif'
2
+
3
+ module WaxTasks
4
+ # A Jekyll collection with IIIF configuration + data
5
+ #
6
+ # @attr src_data [String] the path to the data source file
7
+ # @attr iiif_config [Hash] the iiif configuration for the collection
8
+ # @attr meta [Array] metadata k,v rules
9
+ # @attr variants [Hash] image variants to generate e.g. { med: 650 }
10
+ # @attr src_dir [String] path to existing iiif source images
11
+ # @attr target_dir [String] target path for iiif derivatives
12
+ class IiifCollection < Collection
13
+ attr_reader :variants, :meta, :target_dir
14
+
15
+ # Creates a new IiifCollection with name @name given site config @site
16
+ def initialize(name, site)
17
+ super(name, site)
18
+
19
+ @src_data = @config.fetch('source', nil)
20
+ @iiif_config = @config.fetch('iiif', {})
21
+ @meta = @iiif_config.fetch('meta', nil)
22
+ @variants = validated_variants
23
+ @src_dir = Utils.make_path(@site[:source_dir],
24
+ '_data/iiif',
25
+ @name)
26
+ @target_dir = Utils.make_path(@site[:source_dir],
27
+ 'iiif',
28
+ @name)
29
+ end
30
+
31
+ # Main method for generating iiif derivatives and json
32
+ # @return [Nil]
33
+ def process
34
+ raise Error::MissingIiifSrc, "Cannot find IIIF source directory #{@src_dir}" unless Dir.exist?(@src_dir)
35
+ FileUtils.mkdir_p(@target_dir, verbose: false)
36
+ builder = iiif_builder
37
+ builder.load(iiif_records)
38
+ builder.process_data(true)
39
+ end
40
+
41
+ # Creates a IiifS3::Builder object from collection config
42
+ # @return [Object]
43
+ def iiif_builder
44
+ build_opts = {
45
+ base_url: "#{@site[:baseurl]}/iiif/#{@name}",
46
+ output_dir: @target_dir,
47
+ verbose: true,
48
+ variants: @variants
49
+ }
50
+ IiifS3::Builder.new(build_opts)
51
+ end
52
+
53
+ # Gets custom image variants from collection config if available
54
+ # Else returns default variants { med: 600, lg: 1140 } to Builder
55
+ #
56
+ # @return [Hash]
57
+ def validated_variants
58
+ vars = @iiif_config.fetch('variants', false)
59
+ if vars.is_a?(Array) && vars.all? { |v| v.is_a?(Integer) }
60
+ variants = {}
61
+ vars.each_with_index do |v, i|
62
+ variants["custom_variant_#{i}".to_sym] = v
63
+ end
64
+ else
65
+ variants = { med: 600, lg: 1140 }
66
+ end
67
+ variants
68
+ end
69
+
70
+ # Creates an array of IIIfS3 ImageRecords from the collection config
71
+ # for the IiifS3 Builder to process
72
+ #
73
+ # @return [Array]
74
+ def iiif_records
75
+ records = []
76
+ source_images = Dir["#{@src_dir}/*"].sort!
77
+ if @meta && @src_data
78
+ src_path = Utils.make_path(@site[:source_dir], '_data', @src_data)
79
+ metadata = ingest_file(src_path)
80
+ else
81
+ metadata = false
82
+ end
83
+ source_images.each { |src_img| records << iiif_record(src_img, metadata) }
84
+ records
85
+ end
86
+
87
+ # Creates an individual IiifS3 ImageRecord
88
+ # with metadata from source data file if available
89
+ #
90
+ # @param src_img [String] path to the original source image
91
+ # @param metadata [Hash] metadata to add to the item if available
92
+ # @return [Object]
93
+ def iiif_record(src_img, metadata)
94
+ basename = File.basename(src_img, '.*').to_s
95
+ record_opts = { id: basename, path: src_img, label: basename }
96
+ if metadata
97
+ src_item = metadata.find { |i| i['pid'].to_s == basename }
98
+ @meta.each do |i|
99
+ record_opts[i.first[0].to_sym] = src_item.fetch(i.first[1], '')
100
+ end
101
+ end
102
+ IiifS3::ImageRecord.new(record_opts)
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,59 @@
1
+ module WaxTasks
2
+ # A Jekyll collection to be Indexed in a Lunr Index / JSON file
3
+ # for client-side search.
4
+ #
5
+ # @attr index_config [Hash] the collection's lunr_index config
6
+ # @attr content [Boolean] whether/not page content should be indexed
7
+ # @attr fields [Array] the fields (i.e., keys) that should be indexed
8
+ # @attr data [Array] hash array of data from the ingested pages
9
+ class LunrCollection < Collection
10
+ attr_accessor :fields, :data
11
+
12
+ # Creates a new LunrCollection with name @name given site config @site
13
+ def initialize(name, site)
14
+ super(name, site)
15
+
16
+ @index_config = @config['lunr_index']
17
+ @content = @index_config.fetch('content', false)
18
+ @fields = @index_config.fetch('fields', [])
19
+ @data = ingest_pages
20
+
21
+ raise Error::MissingFields, "There are no fields for #{@name}.".magenta if @fields.empty?
22
+ end
23
+
24
+ # Finds the @page_dir of markdown pages for the collection and ingests
25
+ # them as an array of hashes
26
+ #
27
+ # @return [Array] array of the loaded markdown pages loaded as hashes
28
+ def ingest_pages
29
+ data = []
30
+ pages = Dir.glob("#{@page_dir}/*.md")
31
+ puts "There are no pages in #{@page_dir} to index.".cyan if pages.empty?
32
+ pages.each do |p|
33
+ begin
34
+ data << load_page(p)
35
+ rescue StandardError => e
36
+ raise Error::LunrPageLoad, "Cannot load page #{p}\n#{e}"
37
+ end
38
+ end
39
+ data
40
+ end
41
+
42
+ # Reads in a markdown file and converts it to a hash
43
+ # with the values from @fields.
44
+ # Adds the content of the file (below the YAML) if @content == true
45
+ #
46
+ # @param page [String] the path to a markdown page to load
47
+ def load_page(page)
48
+ yaml = YAML.load_file(page)
49
+ hash = {
50
+ 'link' => "{{'#{yaml.fetch('permalink')}' | relative_url }}",
51
+ 'collection' => @name
52
+ }
53
+ hash['content'] = File.read(page).html_strip.remove_diacritics if @content
54
+ fields = @fields.push('pid').uniq
55
+ fields.each { |f| hash[f] = yaml[f].normalize }
56
+ hash
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,67 @@
1
+ module WaxTasks
2
+ # A LunrIndex document that combines data from all collections
3
+ # in site config that have `lunr_index` parameters.
4
+ #
5
+ # @attr collections [Array] a list of LunrCollection objects
6
+ # @attr fields [Array] shared list of fields to index among LunrCollections
7
+ class LunrIndex
8
+ attr_accessor :collections, :fields
9
+
10
+ # Creates a new LunrIndex object
11
+ def initialize(collections)
12
+ @collections = collections
13
+ @fields = total_fields
14
+ end
15
+
16
+ # @return [Array] shared list of fields to index among LunrCollections
17
+ def total_fields
18
+ total_fields = @collections.map(&:fields).reduce([], :concat)
19
+ total_fields.uniq
20
+ end
21
+
22
+ # @return [String] writes index data as pretty JSON with YAML front-matter
23
+ def to_s
24
+ data = @collections.map(&:data).flatten
25
+ data.each_with_index.map { |d, id| d['lunr_index'] = id }
26
+ "---\nlayout: none\n---\n#{JSON.pretty_generate(data)}"
27
+ end
28
+
29
+ # Creates a default LunrUI / JS file for displaying the Index
30
+ #
31
+ # @return [String]
32
+ def default_ui
33
+ <<~HEREDOC
34
+ ---
35
+ layout: none
36
+ ---
37
+ $.getJSON({{ site.baseurl }}/js/lunr-index.json, function(index_json) {
38
+ window.index = new elasticlunr.Index;
39
+ window.store = index_json;
40
+ index.saveDocument(false);
41
+ index.setRef('lunr_id');
42
+ #{@fields.map { |f| "index.addField('#{f}');" }.join("\n")}
43
+ // add docs
44
+ for (i in store){
45
+ index.addDoc(store[i]);
46
+ }
47
+ $('input#search').on('keyup', function() {
48
+ var results_div = $('#results');
49
+ var query = $(this).val();
50
+ var results = index.search(query, { boolean: 'AND', expand: true });
51
+ results_div.empty();
52
+ if (results.length > 10) {
53
+ results_div.prepend("<p><small>Displaying 10 of " + results.length + " results.</small></p>");
54
+ }
55
+ for (var r in results.slice(0, 9)) {
56
+ var ref = results[r].ref;
57
+ var item = store[ref];
58
+ #{@fields.map { |f| "var #{f} = item.#{f};" }.join("\n")}
59
+ var result = '<div class="result"><b><a href="' + item.link + '">' + title + '</a></b></p></div>';
60
+ results_div.append(result);
61
+ }
62
+ });
63
+ });
64
+ HEREDOC
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,67 @@
1
+ module WaxTasks
2
+ # A Jekyll collection with a data source file that
3
+ # can generate markdown pages from that data.
4
+ #
5
+ # @attr source [String] the path to the data source file
6
+ # @attr layout [String] the Jekyll layout to be used by the generated pages
7
+ # @attr data [Array] array of hashes representing the ingested data file
8
+ # @attr ordered [Boolean] whether/not the order of items should be preserved
9
+ class PagemasterCollection < Collection
10
+ attr_reader :source, :layout, :data, :ordered
11
+
12
+ # Creates a new PagemasterCollection with name @name given site config @site
13
+ def initialize(name, site)
14
+ super(name, site)
15
+
16
+ @source = source_path
17
+ @layout = assert_layout
18
+ @data = ingest_file(@source)
19
+ @ordered = @config.fetch('keep_order', false)
20
+ end
21
+
22
+ # Constructs the path to the data source file
23
+ #
24
+ # @return [String] the path to the data source file
25
+ def source_path
26
+ raise WaxTasks::Error::MissingSource, "Missing collection source in _config.yml for #{@name}" unless @config.key? 'source'
27
+ WaxTasks::Utils.make_path(@site[:source_dir], '_data', @config['source'])
28
+ end
29
+
30
+ # Confirms + requires `layout` value in the collection @config
31
+ #
32
+ # @return [String] the Jekyll layout to be used by the generated pages
33
+ def assert_layout
34
+ raise WaxTasks::Error::MissingLayout, "Missing collection layout in _config.yml for #{@name}" unless @config.key? 'layout'
35
+ @config['layout']
36
+ end
37
+
38
+ # Writes markdown pages from the ingested data to @page_dir
39
+ # with layout, permalink, and order info added (if applicable)
40
+ #
41
+ # @return [Array] a copy of the pages as hashes, for testing
42
+ def generate_pages
43
+ FileUtils.mkdir_p(@page_dir)
44
+ pages = []
45
+ @data.each_with_index do |item, idx|
46
+ page_slug = item.fetch('pid').to_s.slug
47
+ path = "#{@page_dir}/#{page_slug}.md"
48
+ item['permalink'] = "/#{@name}/#{page_slug}#{@site[:permalink]}"
49
+ item['layout'] = @layout
50
+ item['order'] = padded_int(idx, @data.length) if @ordered
51
+ pages << item
52
+ next "#{page_slug}.md already exits. Skipping." if File.exist?(path)
53
+ File.open(path, 'w') { |f| f.write("#{item.to_yaml}---") }
54
+ end
55
+ puts "#{@data.length} pages were generated to #{@page_dir} directory.".cyan
56
+ pages
57
+ end
58
+
59
+ # Constructs the order variable for each page (if the collection
60
+ # needs to preserve the order of items from the file)
61
+ #
62
+ # @return [Integer] the order if the item padded with '0's for sorting
63
+ def padded_int(idx, max_idx)
64
+ idx.to_s.rjust(Math.log10(max_idx).to_i + 1, '0')
65
+ end
66
+ end
67
+ end