jekyll-theme-guides-mbland 0.2.0 → 0.2.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/lib/jekyll-theme-guides-mbland.rb +10 -0
- data/lib/jekyll-theme-guides-mbland/breadcrumbs.rb +28 -0
- data/lib/jekyll-theme-guides-mbland/generated_nodes.rb +64 -0
- data/lib/jekyll-theme-guides-mbland/generated_pages.rb +36 -0
- data/lib/jekyll-theme-guides-mbland/generator.rb +17 -0
- data/lib/jekyll-theme-guides-mbland/namespace_flattener.rb +39 -0
- data/lib/jekyll-theme-guides-mbland/navigation.rb +257 -0
- data/lib/jekyll-theme-guides-mbland/repository.rb +73 -0
- data/lib/jekyll-theme-guides-mbland/tags.rb +51 -0
- data/lib/jekyll-theme-guides-mbland/update.rb +6 -0
- data/lib/jekyll-theme-guides-mbland/version.rb +3 -0
- metadata +12 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29934a58f4e2a89479b2df4e2d399ad911a8e854
|
4
|
+
data.tar.gz: 47be69db1434d7b7b57ac129f30d2f8354a4dd7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c226a22e83ede73c78f45e96e395ad21143e80483e3e52649f9237fa1391448fc7d987e0e9383660be884ca910c999b0900863f56a5d5ff958d6376cc6c2127f
|
7
|
+
data.tar.gz: 63363244938c0a3d5d5a5cc032dd22230062909cc11a3e898e159b2d86e5c1c2966369c77b1e7b64cd9ea6ee932eb92c35cf4133ae5d261cb716ded568a843f4
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'jekyll-theme-guides-mbland/breadcrumbs'
|
2
|
+
require 'jekyll-theme-guides-mbland/generator'
|
3
|
+
require 'jekyll-theme-guides-mbland/navigation'
|
4
|
+
require 'jekyll-theme-guides-mbland/repository'
|
5
|
+
require 'jekyll-theme-guides-mbland/tags'
|
6
|
+
require 'jekyll-theme-guides-mbland/update'
|
7
|
+
require 'jekyll-theme-guides-mbland/version'
|
8
|
+
|
9
|
+
require 'jekyll_pages_api'
|
10
|
+
require 'jekyll_pages_api_search'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'jekyll'
|
2
|
+
require 'safe_yaml'
|
3
|
+
|
4
|
+
module JekyllThemeGuidesMbland
|
5
|
+
class Breadcrumbs
|
6
|
+
def self.generate(site, docs)
|
7
|
+
breadcrumbs = create_breadcrumbs(site)
|
8
|
+
docs.each do |page|
|
9
|
+
page.data['breadcrumbs'] = breadcrumbs[page.permalink || page.url]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.create_breadcrumbs(site)
|
14
|
+
(site.config['navigation'] || []).flat_map do |nav|
|
15
|
+
Breadcrumbs.generate_breadcrumbs(nav, '/', [])
|
16
|
+
end.to_h
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.generate_breadcrumbs(nav, parent_url, parents)
|
20
|
+
url = parent_url + (nav['url'] || '')
|
21
|
+
crumbs = parents + [{ 'url' => url, 'text' => nav['text'] }]
|
22
|
+
child_crumbs = (nav['children'] || []).flat_map do |child|
|
23
|
+
generate_breadcrumbs(child, url, crumbs)
|
24
|
+
end
|
25
|
+
[[url, crumbs]] + child_crumbs
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module JekyllThemeGuidesMbland
|
2
|
+
class GeneratedNodes
|
3
|
+
# Params:
|
4
|
+
# url_to_nav: Mapping from original document URL to "nav item" objects,
|
5
|
+
# i.e. { 'text' => '...', 'url' => '...', 'internal' => true }
|
6
|
+
# nav_data: Array of nav item objects contained in `url_to_nav` after
|
7
|
+
# applying updates, possibly containing "orphan" items marked with an
|
8
|
+
# `:orphan_url` property
|
9
|
+
#
|
10
|
+
# Returns:
|
11
|
+
# nav_data with orphans properly nested within automatically-generated
|
12
|
+
# parent nodes marked with `'generated' => true`
|
13
|
+
def self.create_homes_for_orphans(url_to_nav, nav_data)
|
14
|
+
orphans = nav_data.select { |nav| nav[:orphan_url] }
|
15
|
+
orphans.each { |nav| create_home_for_orphan(nav, nav_data, url_to_nav) }
|
16
|
+
nav_data.reject! { |nav| nav[:orphan_url] }
|
17
|
+
prune_childless_parents(nav_data)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create_home_for_orphan(nav, nav_data, url_to_nav)
|
21
|
+
parents = nav[:orphan_url].split('/')[1..-1]
|
22
|
+
nav['url'] = parents.pop + '/'
|
23
|
+
child_url = '/'
|
24
|
+
immediate_parent = parents.reduce(nil) do |parent, child|
|
25
|
+
child_url = child_url + child + '/'
|
26
|
+
find_or_create_node(nav_data, child_url, parent, child, url_to_nav)
|
27
|
+
end
|
28
|
+
assign_orphan_to_home(nav, immediate_parent, url_to_nav)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.find_or_create_node(nav_data, child_url, parent, child, url_to_nav)
|
32
|
+
child_nav = url_to_nav[child_url]
|
33
|
+
if child_nav.nil?
|
34
|
+
child_nav = generated_node(child)
|
35
|
+
url_to_nav[child_url] = child_nav
|
36
|
+
(parent.nil? ? nav_data : (parent['children'] ||= [])) << child_nav
|
37
|
+
end
|
38
|
+
child_nav
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.generated_node(parent_slug)
|
42
|
+
{
|
43
|
+
'text' => parent_slug.split('-').join(' ').capitalize,
|
44
|
+
'url' => parent_slug + '/',
|
45
|
+
'internal' => true,
|
46
|
+
'generated' => true,
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.assign_orphan_to_home(nav, immediate_parent, url_to_nav)
|
51
|
+
nav_copy = {}.merge(nav)
|
52
|
+
url_to_nav[nav_copy.delete(:orphan_url)] = nav_copy
|
53
|
+
(immediate_parent['children'] ||= []) << nav_copy
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.prune_childless_parents(nav_data)
|
57
|
+
(nav_data || []).reject! do |nav|
|
58
|
+
children = (nav['children'] || [])
|
59
|
+
prune_childless_parents(children)
|
60
|
+
nav['generated'] && children.empty?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module JekyllThemeGuidesMbland
|
2
|
+
class GeneratedPages
|
3
|
+
DEFAULT_LAYOUT = 'jekyll_theme_guides_mbland_generated_home_redirect'.freeze
|
4
|
+
|
5
|
+
def self.generate_pages_from_navigation_data(site)
|
6
|
+
layout = site.config['generate_nodes']
|
7
|
+
return if layout.nil? || layout == false
|
8
|
+
layout = DEFAULT_LAYOUT if layout == true
|
9
|
+
nav_data = site.config['navigation']
|
10
|
+
generate_pages_from_generated_nodes(site, layout, nav_data, '/')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.generate_pages_from_generated_nodes(site, layout, nav_data,
|
14
|
+
parent_url)
|
15
|
+
(nav_data || []).select { |nav| nav['generated'] }.each do |nav|
|
16
|
+
site.pages << GeneratedPage.new(site, layout, nav, parent_url)
|
17
|
+
children = nav['children']
|
18
|
+
next_url = parent_url + nav['url']
|
19
|
+
generate_pages_from_generated_nodes(site, layout, children, next_url)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class GeneratedPage < ::Jekyll::Page
|
25
|
+
def initialize(site, layout, nav, parent_url)
|
26
|
+
@site = site
|
27
|
+
@name = 'index.html'
|
28
|
+
|
29
|
+
process(@name)
|
30
|
+
@data = {}
|
31
|
+
data['title'] = nav['text']
|
32
|
+
data['permalink'] = parent_url + nav['url']
|
33
|
+
data['layout'] = layout
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative './breadcrumbs'
|
2
|
+
require_relative './generated_pages'
|
3
|
+
require_relative './namespace_flattener'
|
4
|
+
|
5
|
+
require 'jekyll'
|
6
|
+
|
7
|
+
module JekyllThemeGuidesMbland
|
8
|
+
class Generator < ::Jekyll::Generator
|
9
|
+
def generate(site)
|
10
|
+
GeneratedPages.generate_pages_from_navigation_data(site)
|
11
|
+
pages = site.collections['pages']
|
12
|
+
docs = (pages.nil? ? [] : pages.docs) + site.pages
|
13
|
+
Breadcrumbs.generate(site, docs)
|
14
|
+
NamespaceFlattener.flatten_url_namespace(site, docs)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module JekyllThemeGuidesMbland
|
2
|
+
class NamespaceFlattener
|
3
|
+
def self.flatten_url_namespace(site, docs)
|
4
|
+
flatten_urls(docs) if site.config['flat_namespace']
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.flatten_urls(docs)
|
8
|
+
flat_to_orig = {}
|
9
|
+
docs.each { |page| flatten_page_urls(page, flat_to_orig) }
|
10
|
+
check_for_collisions(flat_to_orig)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.flatten_page_urls(page, flat_to_orig)
|
14
|
+
orig_url = page.permalink || page.url
|
15
|
+
flattened_url = flat_url(orig_url)
|
16
|
+
(flat_to_orig[flattened_url] ||= []) << orig_url
|
17
|
+
page.data['permalink'] = flattened_url
|
18
|
+
(page.data['breadcrumbs'] || []).each do |crumb|
|
19
|
+
crumb['url'] = flat_url(crumb['url'])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.flat_url(url)
|
24
|
+
url == '/' ? url : "/#{url.split('/')[1..-1].last}/"
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.check_for_collisions(flat_to_orig)
|
28
|
+
collisions = flat_to_orig.map do |flattened, orig|
|
29
|
+
[flattened, orig] if orig.size != 1
|
30
|
+
end.compact
|
31
|
+
|
32
|
+
return if collisions.empty?
|
33
|
+
|
34
|
+
messages = collisions.map { |flat, orig| "#{flat}: #{orig.join(', ')}" }
|
35
|
+
raise StandardError, "collisions in flattened namespace between\n " +
|
36
|
+
messages.join("\n ")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require_relative './generated_nodes'
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require 'safe_yaml'
|
5
|
+
|
6
|
+
module JekyllThemeGuidesMbland
|
7
|
+
module FrontMatter
|
8
|
+
EXTNAMES = %w[.md .html].freeze
|
9
|
+
|
10
|
+
def self.load(basedir)
|
11
|
+
# init_file_to_front_matter_map is initializing the map with a nil value
|
12
|
+
# for every file that _should_ contain front matter as far as the
|
13
|
+
# navigation menu is concerned. Any nil values that remain after merging
|
14
|
+
# with the site_file_to_front_matter map will result in a validation
|
15
|
+
# error.
|
16
|
+
init_file_to_front_matter_map(basedir)
|
17
|
+
.merge(site_file_to_front_matter(init_site(basedir)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.validate_with_message_upon_error(front_matter)
|
21
|
+
files_with_errors = validate front_matter
|
22
|
+
return if files_with_errors.empty?
|
23
|
+
message = ['The following files have errors in their front matter:']
|
24
|
+
files_with_errors.each do |file, errors|
|
25
|
+
message << " #{file}:"
|
26
|
+
message.concat(errors.map { |error| " #{error}" })
|
27
|
+
end
|
28
|
+
message.join "\n" unless message.size == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.validate(front_matter)
|
32
|
+
front_matter.map do |file, data|
|
33
|
+
next [file, ['no front matter defined']] if data.nil?
|
34
|
+
errors = missing_property_errors(data) + permalink_errors(data)
|
35
|
+
[file, errors] unless errors.empty?
|
36
|
+
end.compact.to_h
|
37
|
+
end
|
38
|
+
|
39
|
+
class << self
|
40
|
+
private
|
41
|
+
|
42
|
+
def init_site(basedir)
|
43
|
+
Dir.chdir(basedir) do
|
44
|
+
config = SafeYAML.load_file('_config.yml', safe: true)
|
45
|
+
adjust_config_paths(basedir, config)
|
46
|
+
site = Jekyll::Site.new(Jekyll.configuration(config))
|
47
|
+
site.reset
|
48
|
+
site.read
|
49
|
+
site
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def adjust_config_paths(basedir, config)
|
54
|
+
source = config['source']
|
55
|
+
config['source'] = source.nil? ? basedir : File.join(basedir, source)
|
56
|
+
destination = config['destination']
|
57
|
+
destination = '_site' if destination.nil?
|
58
|
+
config['destination'] = File.join(basedir, destination)
|
59
|
+
end
|
60
|
+
|
61
|
+
def site_file_to_front_matter(site)
|
62
|
+
site_pages(site).map do |page|
|
63
|
+
[page.relative_path, page.data]
|
64
|
+
end.to_h
|
65
|
+
end
|
66
|
+
|
67
|
+
# We're supporting two possible configurations:
|
68
|
+
#
|
69
|
+
# - a `pages/` directory in which documents appear as part of the regular
|
70
|
+
# site.pages collection; we have to filter by page.relative_path, and we
|
71
|
+
# do not assign a permalink so that validation (in a later step) will
|
72
|
+
# ensure that each page has a permalink assigned
|
73
|
+
#
|
74
|
+
# - an actual `pages` collection, stored in a `_pages` directory; no
|
75
|
+
# filtering is necessary, and we can reliably set the permalink to
|
76
|
+
# page.url as a default
|
77
|
+
def site_pages(site)
|
78
|
+
pages = site.collections['pages']
|
79
|
+
if pages.nil?
|
80
|
+
site.pages.select do |page|
|
81
|
+
# Handle both with and without leading slash, as leading slash was
|
82
|
+
# removed in v3.2.0.pre.beta2:
|
83
|
+
# jekyll/jekyll/commit/4fbbeddae20fa52732f30ef001bb1f80258bc5d7
|
84
|
+
page.relative_path.start_with?('/pages/', 'pages/') ||
|
85
|
+
page.url == '/'
|
86
|
+
end
|
87
|
+
else
|
88
|
+
pages.docs.each { |page| page.data['permalink'] ||= page.url }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def init_file_to_front_matter_map(basedir)
|
93
|
+
file_to_front_matter = {}
|
94
|
+
Dir.chdir(basedir) do
|
95
|
+
pages_dir = Dir.exist?('_pages') ? '_pages' : 'pages'
|
96
|
+
Dir[File.join(pages_dir, '**', '*')].each do |file_name|
|
97
|
+
extname = File.extname(file_name)
|
98
|
+
next unless File.file?(file_name) && EXTNAMES.include?(extname)
|
99
|
+
file_to_front_matter[file_name] = nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
file_to_front_matter
|
103
|
+
end
|
104
|
+
|
105
|
+
def missing_property_errors(data)
|
106
|
+
properties = %w[title permalink]
|
107
|
+
properties.map { |p| "no `#{p}:` property" if data[p].nil? }.compact
|
108
|
+
end
|
109
|
+
|
110
|
+
def permalink_errors(data)
|
111
|
+
pl = data['permalink']
|
112
|
+
return [] if pl.nil?
|
113
|
+
errors = []
|
114
|
+
errors << "`permalink:` does not begin with '/'" \
|
115
|
+
unless pl.start_with? '/'
|
116
|
+
errors << "`permalink:` does not end with '/'" unless pl.end_with? '/'
|
117
|
+
errors
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Automatically updates the `navigation:` field in _config.yml.
|
123
|
+
#
|
124
|
+
# Does this by parsing the front matter from files in `pages/`. Preserves the
|
125
|
+
# existing order of items in `navigation:`, but new items may need to be
|
126
|
+
# reordered manually.
|
127
|
+
def self.update_navigation_configuration(basedir)
|
128
|
+
config_path = File.join basedir, '_config.yml'
|
129
|
+
config_data = SafeYAML.load_file config_path, safe: true
|
130
|
+
return unless config_data
|
131
|
+
nav_data = config_data['navigation'] || []
|
132
|
+
NavigationMenu.update_navigation_data(nav_data, basedir, config_data)
|
133
|
+
NavigationMenuWriter.write_navigation_data_to_config_file(config_path,
|
134
|
+
nav_data)
|
135
|
+
end
|
136
|
+
|
137
|
+
module NavigationMenu
|
138
|
+
def self.update_navigation_data(nav_data, basedir, config_data)
|
139
|
+
original = map_nav_items_by_url('/', nav_data).to_h
|
140
|
+
updated = updated_nav_data(basedir)
|
141
|
+
remove_stale_nav_entries(nav_data, original, updated)
|
142
|
+
updated.map { |url, nav| apply_nav_update(url, nav, nav_data, original) }
|
143
|
+
if config_data['generate_nodes']
|
144
|
+
GeneratedNodes.create_homes_for_orphans(original, nav_data)
|
145
|
+
else
|
146
|
+
check_for_orphaned_items(nav_data)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.map_nav_items_by_url(parent_url, nav_data)
|
151
|
+
nav_data.flat_map do |nav|
|
152
|
+
url = File.join('', parent_url, nav['url'] || '')
|
153
|
+
[[url, nav]].concat(map_nav_items_by_url(url, nav['children'] || []))
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.updated_nav_data(basedir)
|
158
|
+
front_matter = FrontMatter.load basedir
|
159
|
+
errors = FrontMatter.validate_with_message_upon_error front_matter
|
160
|
+
abort errors + "\n_config.yml not updated" if errors
|
161
|
+
front_matter
|
162
|
+
.values.sort_by { |fm| fm['permalink'] }
|
163
|
+
.map { |fm| [fm['permalink'], page_nav(fm)] }.to_h
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.page_nav(front_matter)
|
167
|
+
url_components = front_matter['permalink'].split('/')[1..-1]
|
168
|
+
result = {
|
169
|
+
'text' => front_matter['navtitle'] || front_matter['title'],
|
170
|
+
'url' => "#{url_components.nil? ? '' : url_components.last}/",
|
171
|
+
'internal' => true,
|
172
|
+
}
|
173
|
+
# Delete the root URL so we don't have an empty `url:` property laying
|
174
|
+
# around.
|
175
|
+
result.delete 'url' if result['url'] == '/'
|
176
|
+
result
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.remove_stale_nav_entries(nav_data, original, updated)
|
180
|
+
# Remove old entries whose pages have been deleted
|
181
|
+
original.each do |url, nav|
|
182
|
+
if !updated.member?(url) && nav['internal'] && !nav['generated']
|
183
|
+
nav['delete'] = true
|
184
|
+
end
|
185
|
+
end
|
186
|
+
original.delete_if { |_url, nav| nav['delete'] }
|
187
|
+
nav_data.delete_if { |nav| nav['delete'] }
|
188
|
+
nav_data.each { |nav| remove_stale_children(nav) }
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.remove_stale_children(parent)
|
192
|
+
children = (parent['children'] || [])
|
193
|
+
children.delete_if { |nav| nav['delete'] }
|
194
|
+
parent.delete 'children' if children.empty?
|
195
|
+
children.each { |child| remove_stale_children(child) }
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.apply_nav_update(url, nav, nav_data, original)
|
199
|
+
orig = original[url]
|
200
|
+
if orig.nil?
|
201
|
+
apply_new_nav_item(url, nav, nav_data, original)
|
202
|
+
else
|
203
|
+
orig['text'] = nav['text']
|
204
|
+
orig.delete('generated')
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def self.apply_new_nav_item(url, nav, nav_data, original)
|
209
|
+
parent_url = File.dirname(url || '/')
|
210
|
+
parent = original["#{parent_url}/"]
|
211
|
+
if parent_url == '/'
|
212
|
+
nav_data << (original[url] = nav)
|
213
|
+
elsif parent.nil?
|
214
|
+
nav_data << nav.merge(orphan_url: url)
|
215
|
+
else
|
216
|
+
(parent['children'] ||= []) << nav
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def self.check_for_orphaned_items(nav_data)
|
221
|
+
orphan_urls = nav_data.map { |nav| nav[:orphan_url] }.compact
|
222
|
+
return if orphan_urls.empty?
|
223
|
+
raise StandardError, "Parent pages missing for the following:\n " +
|
224
|
+
orphan_urls.join("\n ")
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class NavigationMenuWriter
|
229
|
+
def self.write_navigation_data_to_config_file(config_path, nav_data)
|
230
|
+
lines = []
|
231
|
+
in_navigation = false
|
232
|
+
open(config_path).each_line do |line|
|
233
|
+
in_navigation = process_line line, lines, nav_data, in_navigation
|
234
|
+
end
|
235
|
+
File.write config_path, lines.join
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.process_line(line, lines, nav_data, in_navigation = false)
|
239
|
+
if !in_navigation && line.start_with?('navigation:')
|
240
|
+
lines << line << format_navigation_section(nav_data)
|
241
|
+
in_navigation = true
|
242
|
+
elsif in_navigation
|
243
|
+
in_navigation = line.start_with?(' ', '-')
|
244
|
+
lines << line unless in_navigation
|
245
|
+
else
|
246
|
+
lines << line
|
247
|
+
end
|
248
|
+
in_navigation
|
249
|
+
end
|
250
|
+
|
251
|
+
YAML_PREFIX = "---\n".freeze
|
252
|
+
|
253
|
+
def self.format_navigation_section(nav_data)
|
254
|
+
nav_data.empty? ? '' : nav_data.to_yaml[YAML_PREFIX.size..-1]
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'English'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module JekyllThemeGuidesMbland
|
5
|
+
TEMPLATE_FILES = %w[
|
6
|
+
_pages/add-a-new-page/make-a-child-page.md
|
7
|
+
_pages/add-a-new-page.md
|
8
|
+
_pages/add-images.md
|
9
|
+
_pages/advanced-features.md
|
10
|
+
_pages/github-setup.md
|
11
|
+
_pages/images.png
|
12
|
+
_pages/post-your-guide.md
|
13
|
+
_pages/update-the-config-file/understanding-baseurl.md
|
14
|
+
_pages/update-the-config-file.md
|
15
|
+
images/description.png
|
16
|
+
images/gh-add-guide.png
|
17
|
+
images/gh-branches-link.png
|
18
|
+
images/gh-default-branch.png
|
19
|
+
images/gh-settings-button.png
|
20
|
+
images/gh-webhook.png
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
def self.clear_template_files_and_create_new_repository(basedir,
|
24
|
+
outstream = $stdout)
|
25
|
+
remove_template_files basedir, outstream
|
26
|
+
delete_create_repo_command_from_go_script basedir, outstream
|
27
|
+
create_new_git_repository basedir, outstream
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.remove_template_files(basedir, outstream)
|
31
|
+
Dir.chdir basedir do
|
32
|
+
outstream.puts 'Clearing Guides Template files.'
|
33
|
+
files = TEMPLATE_FILES.map { |f| File.join basedir, f }
|
34
|
+
.select { |f| File.exist? f }
|
35
|
+
File.delete(*files)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.delete_create_repo_command_from_go_script(basedir, outstream)
|
40
|
+
Dir.chdir basedir do
|
41
|
+
outstream.puts 'Removing `:create_repo` command from the `./go` script.'
|
42
|
+
go_script = File.join basedir, 'go'
|
43
|
+
content = File.read go_script
|
44
|
+
match = /\ndef_command\(\n :create_repo,.*?end\n/m.match content
|
45
|
+
content = "#{match.pre_match}#{match.post_match}" unless match.nil?
|
46
|
+
File.write go_script, content
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
GIT_COMMANDS = {
|
51
|
+
'Creating a new git repository.' => 'git init',
|
52
|
+
'Creating mbland-pages branch.' => 'git checkout -b mbland-pages',
|
53
|
+
'Adding files for initial commit.' => 'git add .',
|
54
|
+
}.freeze
|
55
|
+
|
56
|
+
def self.create_new_git_repository(basedir, outstream)
|
57
|
+
Dir.chdir basedir do
|
58
|
+
outstream.puts 'Removing old git repository.'
|
59
|
+
FileUtils.rm_rf '.git'
|
60
|
+
GIT_COMMANDS.each do |description, command|
|
61
|
+
outstream.puts description
|
62
|
+
exec_cmd_capture_output command, outstream
|
63
|
+
end
|
64
|
+
outstream.puts "All done! Run \'git commit\' to create your first commit."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
private_class_method :create_new_git_repository
|
68
|
+
|
69
|
+
def self.exec_cmd_capture_output(command, outstream)
|
70
|
+
opts = { out: outstream, err: outstream }
|
71
|
+
exit $CHILD_STATUS.exitstatus unless system command, opts
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'jekyll/tags/include'
|
2
|
+
require 'liquid'
|
3
|
+
|
4
|
+
module JekyllThemeGuidesMbland
|
5
|
+
class ShouldExpandNavTag < ::Liquid::Tag
|
6
|
+
NAME = 'jekyll_theme_guides_mbland_should_expand_nav'.freeze
|
7
|
+
::Liquid::Template.register_tag(NAME, self)
|
8
|
+
|
9
|
+
attr_reader :parent_reference, :url_reference
|
10
|
+
|
11
|
+
def initialize(_tag_name, markup, _)
|
12
|
+
references = markup.split(',').map(&:strip)
|
13
|
+
@parent_reference = references.shift
|
14
|
+
@url_reference = references.shift
|
15
|
+
end
|
16
|
+
|
17
|
+
def render(context)
|
18
|
+
scope = context.scopes.detect { |s| s.member?(url_reference) }
|
19
|
+
parent_url = scope[url_reference]
|
20
|
+
page_url = context['page']['url']
|
21
|
+
page_url == parent_url || page_url.start_with?(parent_url) ||
|
22
|
+
expand_nav_default(scope, context)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def expand_nav_default(scope, context)
|
28
|
+
default = scope[parent_reference]['expand_nav']
|
29
|
+
default = context['site']['expand_nav'] if default.nil?
|
30
|
+
default.nil? ? false : default
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class PopLastUrlComponent < ::Liquid::Tag
|
35
|
+
NAME = 'jekyll_theme_guides_mbland_pop_last_url_component'.freeze
|
36
|
+
::Liquid::Template.register_tag(NAME, self)
|
37
|
+
|
38
|
+
attr_reader :reference
|
39
|
+
|
40
|
+
def initialize(_tag_name, markup, _)
|
41
|
+
@reference = markup.strip
|
42
|
+
end
|
43
|
+
|
44
|
+
def render(context)
|
45
|
+
scope = context.scopes.detect { |s| s.member?(reference) }
|
46
|
+
parent_url = scope[reference]
|
47
|
+
result = File.dirname(parent_url)
|
48
|
+
result == '/' ? result : "#{result}/"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-theme-guides-mbland
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Bland
|
@@ -180,6 +180,17 @@ files:
|
|
180
180
|
- assets/js/guide.js
|
181
181
|
- assets/js/vendor/anchor.min.js
|
182
182
|
- assets/js/vendor/jquery-1.11.2.min.js
|
183
|
+
- lib/jekyll-theme-guides-mbland.rb
|
184
|
+
- lib/jekyll-theme-guides-mbland/breadcrumbs.rb
|
185
|
+
- lib/jekyll-theme-guides-mbland/generated_nodes.rb
|
186
|
+
- lib/jekyll-theme-guides-mbland/generated_pages.rb
|
187
|
+
- lib/jekyll-theme-guides-mbland/generator.rb
|
188
|
+
- lib/jekyll-theme-guides-mbland/namespace_flattener.rb
|
189
|
+
- lib/jekyll-theme-guides-mbland/navigation.rb
|
190
|
+
- lib/jekyll-theme-guides-mbland/repository.rb
|
191
|
+
- lib/jekyll-theme-guides-mbland/tags.rb
|
192
|
+
- lib/jekyll-theme-guides-mbland/update.rb
|
193
|
+
- lib/jekyll-theme-guides-mbland/version.rb
|
183
194
|
homepage: https://github.com/mbland/jekyll-theme-guides-mbland
|
184
195
|
licenses:
|
185
196
|
- ISC
|