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 +4 -4
- data/Gemfile +2 -0
- data/lib/{wax/tasks → tasks}/iiif.rake +3 -1
- data/lib/tasks/jspackage.rake +14 -0
- data/lib/tasks/lunr.rake +9 -0
- data/lib/{wax/tasks → tasks}/pagemaster.rake +3 -2
- data/lib/tasks/push.rake +13 -0
- data/lib/{wax/tasks → tasks}/test.rake +1 -1
- data/lib/wax_tasks/branch.rb +110 -0
- data/lib/wax_tasks/collection.rb +61 -0
- data/lib/wax_tasks/error.rb +71 -0
- data/lib/wax_tasks/iiif_collection.rb +105 -0
- data/lib/wax_tasks/lunr_collection.rb +59 -0
- data/lib/wax_tasks/lunr_index.rb +67 -0
- data/lib/wax_tasks/pagemaster_collection.rb +67 -0
- data/lib/wax_tasks/task_runner.rb +132 -0
- data/lib/wax_tasks/utils.rb +194 -0
- data/lib/wax_tasks.rb +32 -24
- data/spec/setup.rb +38 -0
- data/spec/spec_helper.rb +26 -36
- metadata +21 -51
- data/lib/wax/branch.rb +0 -70
- data/lib/wax/collection.rb +0 -49
- data/lib/wax/iiif_collection.rb +0 -63
- data/lib/wax/index.rb +0 -70
- data/lib/wax/lunr_collection.rb +0 -50
- data/lib/wax/pagemaster_collection.rb +0 -40
- data/lib/wax/tasks/jspackage.rake +0 -26
- data/lib/wax/tasks/lunr.rake +0 -9
- data/lib/wax/tasks/push.rake +0 -18
- data/lib/wax/utilities.rb +0 -99
- data/spec/iiif.rb +0 -42
- data/spec/lunr.rb +0 -24
- data/spec/pagemaster.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a05cb7d5dd4a2218f7c20546a7bb40762ff50c1382457ab5dc8573f5a8131eb9
|
4
|
+
data.tar.gz: d80600e1d481d7aa91c78fc38fb214aa234f86859ff1ae8660310f17586b5ed0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36879c674be8917117b4219e485c987386370c8d8c89d6d8fdc8bc0149a6d05265ede31b4f4720a1aa48d9cca5db1d2e10a8511663f0aaab9ee34a48bbb96edd
|
7
|
+
data.tar.gz: 8b9ba90bd8a415fcacc969bd787862d8d37e1b7f222341bd23a9c9b08c33cd5eb9fd641f31d5a02b0df99707009ffb57969d945d462698df10c45bde58d0e758
|
data/Gemfile
CHANGED
@@ -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
|
-
|
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
|
data/lib/tasks/lunr.rake
ADDED
@@ -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
|
-
|
8
|
-
|
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
|
data/lib/tasks/push.rake
ADDED
@@ -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
|
@@ -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
|