jekyll-theme-open-project-helpers 1.0.0.rc4 → 1.0.0.rc5
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/jekyll-theme-open-project-helpers.gemspec +1 -1
- data/lib/jekyll-theme-open-project-helpers/blog_index.rb +62 -0
- data/lib/jekyll-theme-open-project-helpers/filterable_index.rb +104 -0
- data/lib/jekyll-theme-open-project-helpers/project_data_reader.rb +181 -0
- data/lib/jekyll-theme-open-project-helpers/site_type.rb +20 -0
- data/lib/jekyll-theme-open-project-helpers.rb +7 -352
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 905882f12a5d505fb7535d96b7f1c8b52a174200
|
4
|
+
data.tar.gz: 8c6f12cd854586c181b74a9a469d3812ba958e68
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cc3e706e19a520699df1f965bcd863c48bde072e8a899eb2ef11f307c10a0748d836a8e2c2b347c4095968c8206e7efe8ed1c50c0b83c827273e096af5bdbef
|
7
|
+
data.tar.gz: cae265cbaf51cb2b398fa845afe0fbcd24ca331678acbbc5c5fcd0b38bdd06b06631ddf1dfb5507bc9341478c67bf41a0486e226ae174afb108b573e77f043f2
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module OpenProjectHelpers
|
3
|
+
|
4
|
+
# Below passes an array of posts of open hub blog
|
5
|
+
# and from each individual project blog, combined and sorted by date,
|
6
|
+
# to open hub blog index page.
|
7
|
+
#
|
8
|
+
# (It also does some processing on the posts.)
|
9
|
+
|
10
|
+
class BlogIndexGenerator < Jekyll::Generator
|
11
|
+
safe true
|
12
|
+
|
13
|
+
def generate(site)
|
14
|
+
site_posts = site.posts.docs
|
15
|
+
|
16
|
+
if Jekyll::OpenProjectHelpers::is_hub(site)
|
17
|
+
# Get documents representing projects
|
18
|
+
projects = site.collections['projects'].docs.select do |item|
|
19
|
+
pieces = item.url.split('/')
|
20
|
+
pieces.length == 4 && pieces[-1] == 'index' && pieces[1] == 'projects'
|
21
|
+
end
|
22
|
+
# Add project name (matches directory name, may differ from title)
|
23
|
+
projects = projects.map do |project|
|
24
|
+
project.data['name'] = project.url.split('/')[2]
|
25
|
+
project
|
26
|
+
end
|
27
|
+
|
28
|
+
# Get documents representnig posts from each project’s blog
|
29
|
+
project_posts = site.collections['projects'].docs.select { |item| item.url.include? '_posts' }
|
30
|
+
|
31
|
+
# Add parent project’s data hash onto each
|
32
|
+
project_posts = project_posts.map do |post|
|
33
|
+
project_name = post.url.split('/')[2]
|
34
|
+
post.data['parent_project'] = projects.detect { |p| p.data['name'] == project_name }
|
35
|
+
post
|
36
|
+
end
|
37
|
+
|
38
|
+
posts_combined = (project_posts + site_posts).sort_by(&:date).reverse
|
39
|
+
|
40
|
+
else
|
41
|
+
posts_combined = site_posts
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# On each post, replace authors’ emails with corresponding md5 hashes
|
46
|
+
# suitable for hotlinking authors’ Gravatar profile pictures.
|
47
|
+
posts_combined = posts_combined.map do |post|
|
48
|
+
if post.data.key? 'author'
|
49
|
+
email = post.data['author']['email']
|
50
|
+
hash = Digest::MD5.hexdigest(email)
|
51
|
+
post.data['author']['email'] = hash
|
52
|
+
end
|
53
|
+
post
|
54
|
+
end
|
55
|
+
|
56
|
+
blog_index = site.site_payload["site"]["pages"].detect { |page| page.url == '/blog/' }
|
57
|
+
blog_index.data['posts_combined'] = posts_combined
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module OpenProjectHelpers
|
3
|
+
|
4
|
+
# On an open hub site, Jekyll Open Project theme assumes the existence of two types
|
5
|
+
# of item indexes: software and specs, where items are gathered
|
6
|
+
# from across open projects in the hub.
|
7
|
+
#
|
8
|
+
# The need for :item_test arises from our data structure (see Jekyll Open Project theme docs)
|
9
|
+
# and the fact that Jekyll doesn’t intuitively handle nested collections.
|
10
|
+
INDEXES = {
|
11
|
+
"software" => {
|
12
|
+
:item_test => lambda { |item| item.path.include? '/_software' and not item.path.include? '/docs' },
|
13
|
+
},
|
14
|
+
"specs" => {
|
15
|
+
:item_test => lambda { |item| item.path.include? '/_specs' and not item.path.include? '/docs' },
|
16
|
+
},
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
# Each software or spec item can have its tags,
|
21
|
+
# and the theme allows to filter each index by a tag.
|
22
|
+
# The below generates an additional index page
|
23
|
+
# for each tag in an index, like software/Ruby.
|
24
|
+
#
|
25
|
+
# Note: this expects "_pages/<index page>.html" to be present in site source,
|
26
|
+
# so it would fail if theme setup instructions were not followed fully.
|
27
|
+
|
28
|
+
class FilteredIndexPage < Jekyll::Page
|
29
|
+
def initialize(site, base, dir, tag, items, index_page)
|
30
|
+
@site = site
|
31
|
+
@base = base
|
32
|
+
@dir = dir
|
33
|
+
@name = 'index.html'
|
34
|
+
|
35
|
+
self.process(@name)
|
36
|
+
self.read_yaml(File.join(base, '_pages'), "#{index_page}.html")
|
37
|
+
self.data['tag'] = tag
|
38
|
+
self.data['items'] = items
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class FilteredIndexPageGenerator < Jekyll::Generator
|
43
|
+
safe true
|
44
|
+
|
45
|
+
def generate(site)
|
46
|
+
if Jekyll::OpenProjectHelpers::is_hub(site)
|
47
|
+
INDEXES.each do |index_name, params|
|
48
|
+
items = site.collections['projects'].docs.select { |item| params[:item_test].call(item) }
|
49
|
+
|
50
|
+
# Creates a data structure like { tag1: [item1, item2], tag2: [item2, item3] }
|
51
|
+
tags = {}
|
52
|
+
items.each do |item|
|
53
|
+
item.data['tags'].each do |tag|
|
54
|
+
unless tags.key? tag
|
55
|
+
tags[tag] = []
|
56
|
+
end
|
57
|
+
tags[tag].push(item)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Creates a filtered index page for each tag
|
62
|
+
tags.each do |tag, tagged_items|
|
63
|
+
site.pages << FilteredIndexPage.new(
|
64
|
+
site,
|
65
|
+
site.source,
|
66
|
+
|
67
|
+
# The filtered page will be nested under /<index page>/<tag>.html
|
68
|
+
File.join(index_name, tag),
|
69
|
+
|
70
|
+
tag,
|
71
|
+
tagged_items,
|
72
|
+
index_name)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Below passes the `items` variable to normal (unfiltered)
|
82
|
+
# index page layout.
|
83
|
+
|
84
|
+
class IndexPageGenerator < Jekyll::Generator
|
85
|
+
safe true
|
86
|
+
|
87
|
+
def generate(site)
|
88
|
+
|
89
|
+
INDEXES.each do |index_name, params|
|
90
|
+
if Jekyll::OpenProjectHelpers::is_hub(site)
|
91
|
+
items = site.collections['projects'].docs.select { |item| params[:item_test].call(item) }
|
92
|
+
else
|
93
|
+
items = site.collections[index_name].docs.select { |item| params[:item_test].call(item) }
|
94
|
+
end
|
95
|
+
|
96
|
+
page = site.site_payload["site"]["pages"].detect { |p| p.url == "/#{index_name}/" }
|
97
|
+
page.data['items'] = items
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module OpenProjectHelpers
|
3
|
+
|
4
|
+
class CollectionDocReader < Jekyll::DataReader
|
5
|
+
|
6
|
+
def read(dir, collection)
|
7
|
+
read_project_subdir(dir, collection)
|
8
|
+
end
|
9
|
+
|
10
|
+
def read_project_subdir(dir, collection, nested=false)
|
11
|
+
return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
|
12
|
+
|
13
|
+
entries = Dir.chdir(dir) do
|
14
|
+
Dir["*.{md,markdown,html,svg,png}"] + Dir["*"].select { |fn| File.directory?(fn) }
|
15
|
+
end
|
16
|
+
|
17
|
+
entries.each do |entry|
|
18
|
+
path = File.join(dir, entry)
|
19
|
+
|
20
|
+
if File.directory?(path)
|
21
|
+
read_project_subdir(path, collection, nested=true)
|
22
|
+
|
23
|
+
elsif nested or (File.basename(entry, '.*') != 'index')
|
24
|
+
ext = File.extname(path)
|
25
|
+
if ['.md', '.markdown', '.html'].include? ext
|
26
|
+
doc = Jekyll::Document.new(path, :site => @site, :collection => collection)
|
27
|
+
doc.read
|
28
|
+
collection.docs << doc
|
29
|
+
else
|
30
|
+
collection.files << Jekyll::StaticFile.new(
|
31
|
+
@site,
|
32
|
+
@site.source,
|
33
|
+
Pathname.new(File.dirname(path)).relative_path_from(Pathname.new(@site.source)).to_s,
|
34
|
+
File.basename(path),
|
35
|
+
collection)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
#
|
44
|
+
# Below deals with fetching each open project’s data from its site’s repo
|
45
|
+
# (such as posts, template includes, software and specs)
|
46
|
+
# and reading it into 'projects' collection docs.
|
47
|
+
#
|
48
|
+
|
49
|
+
class OpenProjectReader < JekyllData::Reader
|
50
|
+
|
51
|
+
def read
|
52
|
+
super
|
53
|
+
if Jekyll::OpenProjectHelpers::is_hub(@site)
|
54
|
+
fetch_and_read_projects
|
55
|
+
else
|
56
|
+
fetch_and_read_docs_for_items('software')
|
57
|
+
fetch_and_read_docs_for_items('specs')
|
58
|
+
fetch_hub_logo
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def fetch_hub_logo
|
65
|
+
if @site.config.key? 'parent_hub' and @site.config['parent_hub'].key? 'git_repo_url'
|
66
|
+
git_sparse_checkout(
|
67
|
+
File.join(@site.source, 'parent-hub'),
|
68
|
+
@site.config['parent_hub']['git_repo_url'],
|
69
|
+
['assets/', 'title.html'])
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def fetch_and_read_projects
|
74
|
+
project_indexes = @site.collections['projects'].docs.select do |doc|
|
75
|
+
pieces = doc.id.split('/')
|
76
|
+
pieces.length == 4 and pieces[1] == 'projects' and pieces[3] == 'index'
|
77
|
+
end
|
78
|
+
project_indexes.each do |project|
|
79
|
+
project_path = project.path.split('/')[0..-2].join('/')
|
80
|
+
|
81
|
+
result = git_sparse_checkout(
|
82
|
+
project_path,
|
83
|
+
project['site']['git_repo_url'],
|
84
|
+
['assets/', '_posts/', '_software/', '_specs/'])
|
85
|
+
|
86
|
+
if result[:newly_initialized]
|
87
|
+
CollectionDocReader.new(site).read(
|
88
|
+
project_path,
|
89
|
+
@site.collections['projects'])
|
90
|
+
end
|
91
|
+
|
92
|
+
fetch_and_read_docs_for_items('projects', 'software')
|
93
|
+
fetch_and_read_docs_for_items('projects', 'specs')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def fetch_docs_for_item(item_doc)
|
98
|
+
item_name = item_doc.id.split('/')[-1]
|
99
|
+
docs_path = "#{item_doc.path.split('/')[0..-2].join('/')}/#{item_name}"
|
100
|
+
|
101
|
+
return {
|
102
|
+
:checkout_result => git_sparse_checkout(
|
103
|
+
docs_path,
|
104
|
+
item_doc['docs']['git_repo_url'],
|
105
|
+
[item_doc['docs']['git_repo_subtree']]),
|
106
|
+
:docs_path => docs_path,
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
def fetch_and_read_docs_for_items(collection_name, index_collection_name=nil)
|
111
|
+
# collection_name would be either software, specs, or (for hub site) projects
|
112
|
+
# index_collection_name would be either software or specs
|
113
|
+
|
114
|
+
index_collection_name = index_collection_name or collection_name
|
115
|
+
|
116
|
+
entry_points = @site.collections[collection_name].docs.select do |doc|
|
117
|
+
doc.data.key?('docs') and
|
118
|
+
doc.data['docs']['git_repo_url']
|
119
|
+
end
|
120
|
+
entry_points.each do |index_doc|
|
121
|
+
result = fetch_docs_for_item(index_doc)
|
122
|
+
index_doc.merge_data!({ 'last_update' => result[:checkout_result][:modified_at] })
|
123
|
+
if result[:checkout_result][:newly_initialized]
|
124
|
+
CollectionDocReader.new(site).read(
|
125
|
+
result[:docs_path],
|
126
|
+
@site.collections[collection_name])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def git_sparse_checkout(repo_path, remote_url, subtrees)
|
132
|
+
# Returns boolean indicating whether the checkout happened
|
133
|
+
|
134
|
+
newly_initialized = false
|
135
|
+
repo = nil
|
136
|
+
|
137
|
+
git_dir = File.join(repo_path, '.git')
|
138
|
+
unless File.exists? git_dir
|
139
|
+
newly_initialized = true
|
140
|
+
|
141
|
+
repo = Git.init(repo_path)
|
142
|
+
|
143
|
+
repo.config(
|
144
|
+
'core.sshCommand',
|
145
|
+
'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no')
|
146
|
+
|
147
|
+
repo.add_remote('origin', remote_url)
|
148
|
+
|
149
|
+
repo.config('core.sparseCheckout', true)
|
150
|
+
open(File.join(git_dir, 'info', 'sparse-checkout'), 'a') { |f|
|
151
|
+
subtrees.each { |path| f << "#{path}\n" }
|
152
|
+
}
|
153
|
+
|
154
|
+
else
|
155
|
+
repo = Git.open(repo_path)
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
repo.fetch
|
160
|
+
repo.reset_hard
|
161
|
+
repo.checkout('origin/master', { :f => true })
|
162
|
+
|
163
|
+
latest_commit = repo.gcommit('HEAD')
|
164
|
+
|
165
|
+
latest_commit.date
|
166
|
+
|
167
|
+
return {
|
168
|
+
:newly_initialized => newly_initialized,
|
169
|
+
:modified_at => latest_commit.date,
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
Jekyll::Hooks.register :site, :after_init do |site|
|
178
|
+
if site.theme # TODO: Check theme name
|
179
|
+
site.reader = Jekyll::OpenProjectHelpers::OpenProjectReader::new(site)
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module OpenProjectHelpers
|
3
|
+
|
4
|
+
def self.is_hub(site)
|
5
|
+
|
6
|
+
# If there’re projects defined, we assume it is indeed
|
7
|
+
# a Jekyll Open Project hub site.
|
8
|
+
if site.collections.key? 'projects'
|
9
|
+
if site.collections['projects'] != nil
|
10
|
+
if site.collections['projects'].docs.length > 0
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
return false
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -1,360 +1,15 @@
|
|
1
1
|
require 'digest/md5'
|
2
|
+
|
2
3
|
require 'jekyll-data/reader'
|
3
4
|
require 'git'
|
4
5
|
|
6
|
+
require 'jekyll-theme-open-project-helpers/site_type'
|
7
|
+
require 'jekyll-theme-open-project-helpers/project_data_reader'
|
8
|
+
require 'jekyll-theme-open-project-helpers/filterable_index'
|
9
|
+
require 'jekyll-theme-open-project-helpers/blog_index'
|
5
10
|
|
6
|
-
def is_hub(site)
|
7
|
-
# If there’re projects defined, we assume it is indeed
|
8
|
-
# a Jekyll Open Project hub site.
|
9
|
-
if site.collections.key? 'projects'
|
10
|
-
if site.collections['projects'] != nil
|
11
|
-
if site.collections['projects'].docs.length > 0
|
12
|
-
return true
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
return false
|
18
|
-
end
|
19
|
-
|
20
|
-
class CollectionDocReader < Jekyll::DataReader
|
21
|
-
|
22
|
-
def read(dir, collection)
|
23
|
-
read_project_subdir(dir, collection)
|
24
|
-
end
|
25
|
-
|
26
|
-
def read_project_subdir(dir, collection, nested=false)
|
27
|
-
return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
|
28
|
-
|
29
|
-
entries = Dir.chdir(dir) do
|
30
|
-
Dir["*.{md,markdown,html,svg,png}"] + Dir["*"].select { |fn| File.directory?(fn) }
|
31
|
-
end
|
32
|
-
|
33
|
-
entries.each do |entry|
|
34
|
-
path = File.join(dir, entry)
|
35
|
-
|
36
|
-
if File.directory?(path)
|
37
|
-
read_project_subdir(path, collection, nested=true)
|
38
|
-
|
39
|
-
elsif nested or (File.basename(entry, '.*') != 'index')
|
40
|
-
ext = File.extname(path)
|
41
|
-
if ['.md', '.markdown', '.html'].include? ext
|
42
|
-
doc = Jekyll::Document.new(path, :site => @site, :collection => collection)
|
43
|
-
doc.read
|
44
|
-
collection.docs << doc
|
45
|
-
else
|
46
|
-
collection.files << Jekyll::StaticFile.new(
|
47
|
-
@site,
|
48
|
-
@site.source,
|
49
|
-
Pathname.new(File.dirname(path)).relative_path_from(Pathname.new(@site.source)).to_s,
|
50
|
-
File.basename(path),
|
51
|
-
collection)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
|
-
#
|
60
|
-
# Below deals with fetching each open project’s data from its site’s repo
|
61
|
-
# (such as posts, template includes, software and specs)
|
62
|
-
# and reading it into 'projects' collection docs.
|
63
|
-
#
|
64
|
-
|
65
|
-
class OpenProjectReader < JekyllData::Reader
|
66
|
-
|
67
|
-
def read
|
68
|
-
super
|
69
|
-
if is_hub(@site)
|
70
|
-
fetch_and_read_projects
|
71
|
-
else
|
72
|
-
fetch_and_read_docs_for_items('software')
|
73
|
-
fetch_and_read_docs_for_items('specs')
|
74
|
-
fetch_hub_logo
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def fetch_hub_logo
|
81
|
-
if @site.config.key? 'parent_hub' and @site.config['parent_hub'].key? 'git_repo_url'
|
82
|
-
git_sparse_checkout(
|
83
|
-
File.join(@site.source, 'parent-hub'),
|
84
|
-
@site.config['parent_hub']['git_repo_url'],
|
85
|
-
['assets/', 'title.html'])
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def fetch_and_read_projects
|
90
|
-
project_indexes = @site.collections['projects'].docs.select do |doc|
|
91
|
-
pieces = doc.id.split('/')
|
92
|
-
pieces.length == 4 and pieces[1] == 'projects' and pieces[3] == 'index'
|
93
|
-
end
|
94
|
-
project_indexes.each do |project|
|
95
|
-
project_path = project.path.split('/')[0..-2].join('/')
|
96
|
-
|
97
|
-
result = git_sparse_checkout(
|
98
|
-
project_path,
|
99
|
-
project['site']['git_repo_url'],
|
100
|
-
['assets/', '_posts/', '_software/', '_specs/'])
|
101
|
-
|
102
|
-
if result[:newly_initialized]
|
103
|
-
CollectionDocReader.new(site).read(
|
104
|
-
project_path,
|
105
|
-
@site.collections['projects'])
|
106
|
-
end
|
107
|
-
|
108
|
-
fetch_and_read_docs_for_items('projects', 'software')
|
109
|
-
fetch_and_read_docs_for_items('projects', 'specs')
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def fetch_docs_for_item(item_doc)
|
114
|
-
item_name = item_doc.id.split('/')[-1]
|
115
|
-
docs_path = "#{item_doc.path.split('/')[0..-2].join('/')}/#{item_name}"
|
116
|
-
|
117
|
-
return {
|
118
|
-
:checkout_result => git_sparse_checkout(
|
119
|
-
docs_path,
|
120
|
-
item_doc['docs']['git_repo_url'],
|
121
|
-
[item_doc['docs']['git_repo_subtree']]),
|
122
|
-
:docs_path => docs_path,
|
123
|
-
}
|
124
|
-
end
|
125
|
-
|
126
|
-
def fetch_and_read_docs_for_items(collection_name, index_collection_name=nil)
|
127
|
-
# collection_name would be either software, specs, or (for hub site) projects
|
128
|
-
# index_collection_name would be either software or specs
|
129
|
-
|
130
|
-
index_collection_name = index_collection_name or collection_name
|
131
|
-
|
132
|
-
entry_points = @site.collections[collection_name].docs.select do |doc|
|
133
|
-
doc.data.key?('docs') and
|
134
|
-
doc.data['docs']['git_repo_url']
|
135
|
-
end
|
136
|
-
entry_points.each do |index_doc|
|
137
|
-
result = fetch_docs_for_item(index_doc)
|
138
|
-
index_doc.merge_data!({ 'last_update' => result[:checkout_result][:modified_at] })
|
139
|
-
if result[:checkout_result][:newly_initialized]
|
140
|
-
CollectionDocReader.new(site).read(
|
141
|
-
result[:docs_path],
|
142
|
-
@site.collections[collection_name])
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def git_sparse_checkout(repo_path, remote_url, subtrees)
|
148
|
-
# Returns boolean indicating whether the checkout happened
|
149
|
-
|
150
|
-
newly_initialized = false
|
151
|
-
repo = nil
|
152
|
-
|
153
|
-
git_dir = File.join(repo_path, '.git')
|
154
|
-
unless File.exists? git_dir
|
155
|
-
newly_initialized = true
|
156
|
-
|
157
|
-
repo = Git.init(repo_path)
|
158
|
-
|
159
|
-
repo.config(
|
160
|
-
'core.sshCommand',
|
161
|
-
'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no')
|
162
|
-
|
163
|
-
repo.add_remote('origin', remote_url)
|
164
|
-
|
165
|
-
repo.config('core.sparseCheckout', true)
|
166
|
-
open(File.join(git_dir, 'info', 'sparse-checkout'), 'a') { |f|
|
167
|
-
subtrees.each { |path| f << "#{path}\n" }
|
168
|
-
}
|
169
|
-
|
170
|
-
else
|
171
|
-
repo = Git.open(repo_path)
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
repo.fetch
|
176
|
-
repo.reset_hard
|
177
|
-
repo.checkout('origin/master', { :f => true })
|
178
|
-
|
179
|
-
latest_commit = repo.gcommit('HEAD')
|
180
|
-
|
181
|
-
latest_commit.date
|
182
|
-
|
183
|
-
return {
|
184
|
-
:newly_initialized => newly_initialized,
|
185
|
-
:modified_at => latest_commit.date,
|
186
|
-
}
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
|
191
|
-
Jekyll::Hooks.register :site, :after_init do |site|
|
192
|
-
if site.theme # TODO: Check theme name
|
193
|
-
site.reader = OpenProjectReader::new(site)
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
|
198
|
-
#
|
199
|
-
# Below deals with blog and other indexes
|
200
|
-
#
|
201
|
-
|
202
|
-
module OpenProjectHelpers
|
203
|
-
|
204
|
-
# On an open hub site, Jekyll Open Project theme assumes the existence of two types
|
205
|
-
# of item indexes: software and specs, where items are gathered
|
206
|
-
# from across open projects in the hub.
|
207
|
-
#
|
208
|
-
# The need for :item_test arises from our data structure (see Jekyll Open Project theme docs)
|
209
|
-
# and the fact that Jekyll doesn’t intuitively handle nested collections.
|
210
|
-
INDEXES = {
|
211
|
-
"software" => {
|
212
|
-
:item_test => lambda { |item| item.path.include? '/_software' and not item.path.include? '/docs' },
|
213
|
-
},
|
214
|
-
"specs" => {
|
215
|
-
:item_test => lambda { |item| item.path.include? '/_specs' and not item.path.include? '/docs' },
|
216
|
-
},
|
217
|
-
}
|
218
|
-
|
219
|
-
|
220
|
-
# Each software or spec item can have its tags,
|
221
|
-
# and the theme allows to filter each index by a tag.
|
222
|
-
# The below generates an additional index page
|
223
|
-
# for each tag in an index, like software/Ruby.
|
224
|
-
#
|
225
|
-
# Note: this expects "_pages/<index page>.html" to be present in site source,
|
226
|
-
# so it would fail if theme setup instructions were not followed fully.
|
227
|
-
|
228
|
-
class FilteredIndexPage < Jekyll::Page
|
229
|
-
def initialize(site, base, dir, tag, items, index_page)
|
230
|
-
@site = site
|
231
|
-
@base = base
|
232
|
-
@dir = dir
|
233
|
-
@name = 'index.html'
|
234
|
-
|
235
|
-
self.process(@name)
|
236
|
-
self.read_yaml(File.join(base, '_pages'), "#{index_page}.html")
|
237
|
-
self.data['tag'] = tag
|
238
|
-
self.data['items'] = items
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
class FilteredIndexPageGenerator < Jekyll::Generator
|
243
|
-
safe true
|
244
|
-
|
245
|
-
def generate(site)
|
246
|
-
if is_hub(site)
|
247
|
-
INDEXES.each do |index_name, params|
|
248
|
-
items = site.collections['projects'].docs.select { |item| params[:item_test].call(item) }
|
249
|
-
|
250
|
-
# Creates a data structure like { tag1: [item1, item2], tag2: [item2, item3] }
|
251
|
-
tags = {}
|
252
|
-
items.each do |item|
|
253
|
-
item.data['tags'].each do |tag|
|
254
|
-
unless tags.key? tag
|
255
|
-
tags[tag] = []
|
256
|
-
end
|
257
|
-
tags[tag].push(item)
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
# Creates a filtered index page for each tag
|
262
|
-
tags.each do |tag, tagged_items|
|
263
|
-
site.pages << FilteredIndexPage.new(
|
264
|
-
site,
|
265
|
-
site.source,
|
266
|
-
|
267
|
-
# The filtered page will be nested under /<index page>/<tag>.html
|
268
|
-
File.join(index_name, tag),
|
269
|
-
|
270
|
-
tag,
|
271
|
-
tagged_items,
|
272
|
-
index_name)
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
|
281
|
-
# Below passes the `items` variable to normal (unfiltered)
|
282
|
-
# index page layout.
|
283
|
-
|
284
|
-
class IndexPageGenerator < Jekyll::Generator
|
285
|
-
safe true
|
286
|
-
|
287
|
-
def generate(site)
|
288
|
-
|
289
|
-
INDEXES.each do |index_name, params|
|
290
|
-
if is_hub(site)
|
291
|
-
items = site.collections['projects'].docs.select { |item| params[:item_test].call(item) }
|
292
|
-
else
|
293
|
-
items = site.collections[index_name].docs.select { |item| params[:item_test].call(item) }
|
294
|
-
end
|
295
|
-
|
296
|
-
page = site.site_payload["site"]["pages"].detect { |p| p.url == "/#{index_name}/" }
|
297
|
-
page.data['items'] = items
|
298
|
-
end
|
299
|
-
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
|
304
|
-
# Below passes an array of posts of open hub blog
|
305
|
-
# and from each individual project blog, combined and sorted by date,
|
306
|
-
# to open hub blog index page.
|
307
|
-
#
|
308
|
-
# (It also does some processing on the posts.)
|
309
|
-
|
310
|
-
class BlogIndexGenerator < Jekyll::Generator
|
311
|
-
safe true
|
312
|
-
|
313
|
-
def generate(site)
|
314
|
-
site_posts = site.posts.docs
|
315
|
-
|
316
|
-
if is_hub(site)
|
317
|
-
# Get documents representing projects
|
318
|
-
projects = site.collections['projects'].docs.select do |item|
|
319
|
-
pieces = item.url.split('/')
|
320
|
-
pieces.length == 4 && pieces[-1] == 'index' && pieces[1] == 'projects'
|
321
|
-
end
|
322
|
-
# Add project name (matches directory name, may differ from title)
|
323
|
-
projects = projects.map do |project|
|
324
|
-
project.data['name'] = project.url.split('/')[2]
|
325
|
-
project
|
326
|
-
end
|
327
|
-
|
328
|
-
# Get documents representnig posts from each project’s blog
|
329
|
-
project_posts = site.collections['projects'].docs.select { |item| item.url.include? '_posts' }
|
330
|
-
|
331
|
-
# Add parent project’s data hash onto each
|
332
|
-
project_posts = project_posts.map do |post|
|
333
|
-
project_name = post.url.split('/')[2]
|
334
|
-
post.data['parent_project'] = projects.detect { |p| p.data['name'] == project_name }
|
335
|
-
post
|
336
|
-
end
|
337
|
-
|
338
|
-
posts_combined = (project_posts + site_posts).sort_by(&:date).reverse
|
339
|
-
|
340
|
-
else
|
341
|
-
posts_combined = site_posts
|
342
|
-
|
343
|
-
end
|
344
|
-
|
345
|
-
# On each post, replace authors’ emails with corresponding md5 hashes
|
346
|
-
# suitable for hotlinking authors’ Gravatar profile pictures.
|
347
|
-
posts_combined = posts_combined.map do |post|
|
348
|
-
if post.data.key? 'author'
|
349
|
-
email = post.data['author']['email']
|
350
|
-
hash = Digest::MD5.hexdigest(email)
|
351
|
-
post.data['author']['email'] = hash
|
352
|
-
end
|
353
|
-
post
|
354
|
-
end
|
355
11
|
|
356
|
-
|
357
|
-
|
358
|
-
end
|
12
|
+
module Jekyll
|
13
|
+
module OpenProjectHelpers
|
359
14
|
end
|
360
15
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-theme-open-project-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -78,6 +78,10 @@ files:
|
|
78
78
|
- develop/release
|
79
79
|
- jekyll-theme-open-project-helpers.gemspec
|
80
80
|
- lib/jekyll-theme-open-project-helpers.rb
|
81
|
+
- lib/jekyll-theme-open-project-helpers/blog_index.rb
|
82
|
+
- lib/jekyll-theme-open-project-helpers/filterable_index.rb
|
83
|
+
- lib/jekyll-theme-open-project-helpers/project_data_reader.rb
|
84
|
+
- lib/jekyll-theme-open-project-helpers/site_type.rb
|
81
85
|
homepage: https://github.com/riboseinc/jekyll-theme-open-project-helpers/
|
82
86
|
licenses:
|
83
87
|
- MIT
|