shoreditch 1.1.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 +7 -0
- data/CHANGELOG.md +148 -0
- data/Gemfile +5 -0
- data/LICENSE.md +9 -0
- data/README.md +230 -0
- data/bridgetown.automation.rb +277 -0
- data/components/shoreditch/comments.erb +25 -0
- data/components/shoreditch/comments.rb +49 -0
- data/components/shoreditch/details.erb +52 -0
- data/components/shoreditch/details.rb +83 -0
- data/components/shoreditch/head_icons.erb +12 -0
- data/components/shoreditch/head_icons.rb +48 -0
- data/components/shoreditch/post_summary.erb +19 -0
- data/components/shoreditch/post_summary.rb +37 -0
- data/components/shoreditch/sidebar.erb +64 -0
- data/components/shoreditch/sidebar.rb +67 -0
- data/content/shoreditch/shoreditch.css +991 -0
- data/content/shoreditch/shoreditch.js +102 -0
- data/layouts/shoreditch/default.erb +89 -0
- data/layouts/shoreditch/page.erb +27 -0
- data/layouts/shoreditch/post.erb +72 -0
- data/lib/shoreditch/icons.rb +32 -0
- data/lib/shoreditch/version.rb +5 -0
- data/lib/shoreditch.rb +70 -0
- data/shoreditch.gemspec +41 -0
- metadata +112 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<section class="sd-comments">
|
|
2
|
+
<h2>Comments</h2>
|
|
3
|
+
|
|
4
|
+
<%# data-theme follows the OS preference on load; shoreditch.js re-syncs it
|
|
5
|
+
through Giscus's postMessage API when the reader uses the theme toggle,
|
|
6
|
+
so the comment thread does not stay light on a dark page. %>
|
|
7
|
+
<script
|
|
8
|
+
src="https://giscus.app/client.js"
|
|
9
|
+
data-repo="<%= repo %>"
|
|
10
|
+
data-repo-id="<%= repo_id %>"
|
|
11
|
+
data-category="<%= category %>"
|
|
12
|
+
data-category-id="<%= category_id %>"
|
|
13
|
+
data-mapping="pathname"
|
|
14
|
+
data-strict="1"
|
|
15
|
+
data-reactions-enabled="1"
|
|
16
|
+
data-emit-metadata="0"
|
|
17
|
+
data-input-position="bottom"
|
|
18
|
+
data-theme="preferred_color_scheme"
|
|
19
|
+
data-lang="en"
|
|
20
|
+
crossorigin="anonymous"
|
|
21
|
+
async
|
|
22
|
+
></script>
|
|
23
|
+
|
|
24
|
+
<noscript>Comments need JavaScript. They are also readable as GitHub Discussions on the repository.</noscript>
|
|
25
|
+
</section>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The comments slot.
|
|
4
|
+
#
|
|
5
|
+
# The theme ships Giscus (comments stored as GitHub Discussions) as the one
|
|
6
|
+
# provider it knows how to configure, but nothing here is Giscus-specific from
|
|
7
|
+
# a consuming site's point of view: a site that wants something else overrides
|
|
8
|
+
# this component by putting its own `components/shoreditch/comments.erb` in
|
|
9
|
+
# place. Site files take precedence over the gem's source manifest, so no fork
|
|
10
|
+
# and no layout copy is needed.
|
|
11
|
+
#
|
|
12
|
+
# Off unless configured. Set in config/initializers.rb:
|
|
13
|
+
#
|
|
14
|
+
# init :shoreditch do
|
|
15
|
+
# comments({
|
|
16
|
+
# repo: "you/your-repo", repo_id: "R_...",
|
|
17
|
+
# category: "Comments", category_id: "DIC_...",
|
|
18
|
+
# })
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# The four values come from https://giscus.app after enabling Discussions on
|
|
22
|
+
# the repository. A single post opts out with `comments: false` in front matter.
|
|
23
|
+
class Shoreditch::Comments < Bridgetown::Component
|
|
24
|
+
def initialize(site:, resource:)
|
|
25
|
+
@site = site
|
|
26
|
+
@resource = resource
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :site, :resource
|
|
30
|
+
|
|
31
|
+
def render?
|
|
32
|
+
resource.data.comments != false && settings.is_a?(Hash) && required_keys_present?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def settings
|
|
36
|
+
site.config.shoreditch[:comments]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Giscus silently renders nothing if any of these are missing, which is a
|
|
40
|
+
# miserable thing to debug, so treat a partial config as "off".
|
|
41
|
+
def required_keys_present?
|
|
42
|
+
%i[repo repo_id category category_id].all? { |key| settings[key].to_s.strip != "" }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def repo = settings[:repo].to_s
|
|
46
|
+
def repo_id = settings[:repo_id].to_s
|
|
47
|
+
def category = settings[:category].to_s
|
|
48
|
+
def category_id = settings[:category_id].to_s
|
|
49
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<ul class="sd-details">
|
|
2
|
+
<% links.each do |key, icon_name, href, text| %>
|
|
3
|
+
<li data-network="<%= key %>">
|
|
4
|
+
<a href="<%= href %>" rel="me noopener">
|
|
5
|
+
<svg class="sd-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
6
|
+
<path d="<%= icon(icon_name) %>" />
|
|
7
|
+
</svg>
|
|
8
|
+
<%= text %>
|
|
9
|
+
</a>
|
|
10
|
+
</li>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<% if phone != "" %>
|
|
14
|
+
<li data-network="phone">
|
|
15
|
+
<a href="tel:<%= phone.gsub(/[^0-9+]/, "") %>">
|
|
16
|
+
<svg class="sd-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
17
|
+
<path d="<%= icon(:phone) %>" />
|
|
18
|
+
</svg>
|
|
19
|
+
<%= phone %>
|
|
20
|
+
</a>
|
|
21
|
+
</li>
|
|
22
|
+
<% end %>
|
|
23
|
+
|
|
24
|
+
<% if email? %>
|
|
25
|
+
<%# The two halves are only joined in the browser — see shoreditch.js. %>
|
|
26
|
+
<li data-network="email">
|
|
27
|
+
<a
|
|
28
|
+
class="sd-email"
|
|
29
|
+
href="#"
|
|
30
|
+
hidden
|
|
31
|
+
data-sd-email-user="<%= email_parts.first %>"
|
|
32
|
+
data-sd-email-host="<%= email_parts.last %>"
|
|
33
|
+
>
|
|
34
|
+
<svg class="sd-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
35
|
+
<path d="<%= icon(:email) %>" />
|
|
36
|
+
</svg>
|
|
37
|
+
Email
|
|
38
|
+
</a>
|
|
39
|
+
</li>
|
|
40
|
+
<% end %>
|
|
41
|
+
|
|
42
|
+
<% if file_url != "" %>
|
|
43
|
+
<li data-network="file">
|
|
44
|
+
<a href="<%= file_url %>" rel="noopener">
|
|
45
|
+
<svg class="sd-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
46
|
+
<path d="<%= icon(:file) %>" />
|
|
47
|
+
</svg>
|
|
48
|
+
<%= file_link_text %>
|
|
49
|
+
</a>
|
|
50
|
+
</li>
|
|
51
|
+
<% end %>
|
|
52
|
+
</ul>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The contact panel: how to reach the author, and where else they are.
|
|
4
|
+
#
|
|
5
|
+
# Restored from the Jekyll theme's `_includes/details.html`, with two changes.
|
|
6
|
+
# Icons are inlined from the vendored Simple Icons set rather than pulled from
|
|
7
|
+
# a Font Awesome CDN kit on every page load, and the markup is a definition of
|
|
8
|
+
# links rather than a list of hard-coded network blocks, so adding a network is
|
|
9
|
+
# one entry in ENTRIES.
|
|
10
|
+
#
|
|
11
|
+
# Everything is driven by `author` in src/_data/site_metadata.yml. A page opts
|
|
12
|
+
# in with `include_details: true` in its front matter — off elsewhere, since a
|
|
13
|
+
# blog post has no use for a phone number.
|
|
14
|
+
class Shoreditch::Details < Bridgetown::Component
|
|
15
|
+
# network key => [icon, url template, label]. `%s` takes the handle.
|
|
16
|
+
ENTRIES = [
|
|
17
|
+
[:github, :github, "https://github.com/%s", "%s"],
|
|
18
|
+
[:mastodon, :mastodon, "%s", "Mastodon"],
|
|
19
|
+
[:linkedin, :link, "https://linkedin.com/in/%s", "%s"],
|
|
20
|
+
[:twitter, :x, "https://x.com/%s", "@%s"],
|
|
21
|
+
[:instagram, :instagram, "https://instagram.com/%s", "%s"],
|
|
22
|
+
[:reddit, :reddit, "https://reddit.com/user/%s", "%s"],
|
|
23
|
+
[:youtube, :youtube, "%s", "YouTube"],
|
|
24
|
+
[:tiktok, :tiktok, "https://tiktok.com/@%s", "%s"],
|
|
25
|
+
[:lastfm, :lastfm, "https://last.fm/user/%s", "%s"],
|
|
26
|
+
[:deviantart, :deviantart, "https://deviantart.com/%s", "%s"],
|
|
27
|
+
[:artstation, :artstation, "https://artstation.com/%s", "%s"],
|
|
28
|
+
].freeze
|
|
29
|
+
|
|
30
|
+
def initialize(site:, resource:)
|
|
31
|
+
@site = site
|
|
32
|
+
@resource = resource
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
attr_reader :site, :resource
|
|
36
|
+
|
|
37
|
+
# Not `author.present?`: site.metadata is a HashWithDotAccess::Hash, which
|
|
38
|
+
# routes unknown methods to key lookups, so `present?` returns nil for a
|
|
39
|
+
# missing "present" key rather than calling ActiveSupport. Only methods Hash
|
|
40
|
+
# genuinely defines are safe to call on it.
|
|
41
|
+
def render?
|
|
42
|
+
resource.data.include_details == true && author.is_a?(Hash) && !author.empty?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def author
|
|
46
|
+
site.metadata.author
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# [key, icon, href, text] for each network the site actually filled in. The
|
|
50
|
+
# key and the icon are separate because they diverge: LinkedIn is styled as
|
|
51
|
+
# linkedin but drawn with the generic `link` mark.
|
|
52
|
+
def links
|
|
53
|
+
ENTRIES.filter_map do |key, icon, url, label|
|
|
54
|
+
handle = author[key.to_s].to_s.strip
|
|
55
|
+
next if handle.empty?
|
|
56
|
+
|
|
57
|
+
[key, icon, format(url, handle), format(label, handle)]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def phone = author["phone"].to_s.strip
|
|
62
|
+
|
|
63
|
+
def file_url = author["file_url"].to_s.strip
|
|
64
|
+
|
|
65
|
+
def file_link_text
|
|
66
|
+
text = author["file_link_text"].to_s.strip
|
|
67
|
+
text.empty? ? "Download" : text
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Kept split across two metadata keys, as the Jekyll version had it, so the
|
|
71
|
+
# address never appears whole in the HTML for a crawler to lift. Assembled by
|
|
72
|
+
# shoreditch.js. Without JavaScript the address is simply not shown, which is
|
|
73
|
+
# the trade the original made too.
|
|
74
|
+
def email_parts
|
|
75
|
+
[author["email_1"].to_s.strip, author["email_2"].to_s.strip]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def email? = email_parts.none?(&:empty?)
|
|
79
|
+
|
|
80
|
+
def icon(name)
|
|
81
|
+
Shoreditch::ICONS[name]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<% if favicon %>
|
|
2
|
+
<link rel="shortcut icon" href="<%= favicon %>" />
|
|
3
|
+
<% end %>
|
|
4
|
+
<% apple_icons.each do |size, path| %>
|
|
5
|
+
<link rel="apple-touch-icon" sizes="<%= size %>" href="<%= path %>" />
|
|
6
|
+
<% end %>
|
|
7
|
+
<% png_icons.each do |size, path| %>
|
|
8
|
+
<link rel="icon" type="image/png" sizes="<%= size %>" href="<%= path %>" />
|
|
9
|
+
<% end %>
|
|
10
|
+
<% if manifest %>
|
|
11
|
+
<link rel="manifest" href="<%= manifest %>" />
|
|
12
|
+
<% end %>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Favicon and touch-icon links.
|
|
4
|
+
#
|
|
5
|
+
# Only emitted for files the site actually has. The Jekyll theme hard-coded the
|
|
6
|
+
# full apple-touch-icon set, which meant every site using the theme requested a
|
|
7
|
+
# dozen icons whether or not they existed.
|
|
8
|
+
class Shoreditch::HeadIcons < Bridgetown::Component
|
|
9
|
+
APPLE_SIZES = %w[57x57 60x60 72x72 76x76 114x114 120x120 144x144 152x152 180x180].freeze
|
|
10
|
+
PNG_SIZES = %w[16x16 32x32 96x96 192x192].freeze
|
|
11
|
+
|
|
12
|
+
def initialize(site:, prefix: "")
|
|
13
|
+
@site = site
|
|
14
|
+
@prefix = prefix
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def apple_icons
|
|
18
|
+
APPLE_SIZES.filter_map do |size|
|
|
19
|
+
path = "#{@prefix}/apple-icon-#{size}.png"
|
|
20
|
+
[size, path] if exists?(path)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def png_icons
|
|
25
|
+
PNG_SIZES.filter_map do |size|
|
|
26
|
+
# The 192px icon is named for Android; the rest are plain favicons.
|
|
27
|
+
name = size == "192x192" ? "android-icon-192x192" : "favicon-#{size}"
|
|
28
|
+
path = "#{@prefix}/#{name}.png"
|
|
29
|
+
[size, path] if exists?(path)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def favicon
|
|
34
|
+
path = "#{@prefix}/favicon.ico"
|
|
35
|
+
path if exists?(path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def manifest
|
|
39
|
+
path = "#{@prefix}/manifest.json"
|
|
40
|
+
path if exists?(path)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def exists?(path)
|
|
46
|
+
File.exist?(File.join(@site.config.source, path))
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<article class="sd-post-summary">
|
|
2
|
+
<% if thumbnail %>
|
|
3
|
+
<a class="sd-post-thumbnail" href="<%= post.relative_url %>" tabindex="-1" aria-hidden="true">
|
|
4
|
+
<img src="<%= thumbnail %>" alt="" loading="lazy" />
|
|
5
|
+
</a>
|
|
6
|
+
<% end %>
|
|
7
|
+
|
|
8
|
+
<div class="sd-post-detail">
|
|
9
|
+
<p class="sd-post-dates">
|
|
10
|
+
<time datetime="<%= date_attr %>"><%= date_text %></time>
|
|
11
|
+
</p>
|
|
12
|
+
<h2><a href="<%= post.relative_url %>"><%= post.data.title %></a></h2>
|
|
13
|
+
<%# Wrapped so the excerpt can be clamped and flattened as a unit: the
|
|
14
|
+
summary is whatever block the post opens with, which may be a
|
|
15
|
+
blockquote or a {:.message}, and an index preview has to read the same
|
|
16
|
+
whichever it is. %>
|
|
17
|
+
<div class="sd-post-excerpt"><%= summary %></div>
|
|
18
|
+
</div>
|
|
19
|
+
</article>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# One entry in an index listing — used by both the home page and tag pages.
|
|
4
|
+
class Shoreditch::PostSummary < Bridgetown::Component
|
|
5
|
+
def initialize(post:)
|
|
6
|
+
@post = post
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
attr_reader :post
|
|
10
|
+
|
|
11
|
+
def thumbnail
|
|
12
|
+
post.data.thumbnail
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def date_text
|
|
16
|
+
post.date.strftime("%-d %B %Y")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def date_attr
|
|
20
|
+
post.date.strftime("%Y-%m-%d")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Bridgetown's own summary is the first *source line*. The demo's markdown is
|
|
24
|
+
# hard-wrapped at 80 columns, so that cut three of four excerpts off
|
|
25
|
+
# mid-clause and left the paragraph unclosed. An explicit <!--more--> marker
|
|
26
|
+
# wins; otherwise take the first complete paragraph.
|
|
27
|
+
def summary
|
|
28
|
+
html = post.content.to_s
|
|
29
|
+
excerpt =
|
|
30
|
+
if (marker = html.index("<!--more-->"))
|
|
31
|
+
html[0...marker]
|
|
32
|
+
else
|
|
33
|
+
html[%r{\A.*?</p>}m] || html
|
|
34
|
+
end
|
|
35
|
+
excerpt.strip.html_safe
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<aside class="sd-sidebar">
|
|
2
|
+
<div class="sd-logo-area">
|
|
3
|
+
<% if logo_source %>
|
|
4
|
+
<a href="<%= site.metadata.logo_link || "/" %>">
|
|
5
|
+
<img
|
|
6
|
+
class="sd-logo"
|
|
7
|
+
data-shape="<%= logo_shape %>"
|
|
8
|
+
data-flashy="<%= flashy_logo? %>"
|
|
9
|
+
src="<%= logo_source %>"
|
|
10
|
+
alt="<%= site.metadata.title %>"
|
|
11
|
+
/>
|
|
12
|
+
</a>
|
|
13
|
+
<% end %>
|
|
14
|
+
|
|
15
|
+
<% if logo_legend %>
|
|
16
|
+
<span class="sd-logo-legend" data-shape="<%= logo_legend_shape %>"><%= logo_legend %></span>
|
|
17
|
+
<% end %>
|
|
18
|
+
|
|
19
|
+
<%# `include_sticky: false` in front matter drops the site identity and the
|
|
20
|
+
navigation, leaving the logo and badge to introduce a person instead. %>
|
|
21
|
+
<% if sticky? %>
|
|
22
|
+
<div class="sd-site-identity">
|
|
23
|
+
<p class="sd-site-title"><a href="/"><%= site.metadata.title %></a></p>
|
|
24
|
+
<% if site.metadata.tagline %>
|
|
25
|
+
<p class="sd-site-tagline"><%= site.metadata.tagline %></p>
|
|
26
|
+
<% end %>
|
|
27
|
+
</div>
|
|
28
|
+
<% end %>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<%# The contact panel belongs with the identity above it, not with the
|
|
32
|
+
navigation — on a CV the logo, name and contact details read as one block. %>
|
|
33
|
+
<%= render Shoreditch::Details.new(site: site, resource: resource) %>
|
|
34
|
+
|
|
35
|
+
<%# Everything from here sits at the foot of the column: the identity stays
|
|
36
|
+
at the top where the eye starts, the menu and the footer drop to the
|
|
37
|
+
bottom. One auto margin on this wrapper does it, which is why the nav and
|
|
38
|
+
footer are grouped rather than each pushed down separately — two auto
|
|
39
|
+
margins would split the free space and strand the nav in the middle. %>
|
|
40
|
+
<div class="sd-sidebar-bottom">
|
|
41
|
+
<% if sticky? && nav_pages.any? %>
|
|
42
|
+
<nav class="sd-nav" aria-label="Main">
|
|
43
|
+
<% nav_pages.each do |page| %>
|
|
44
|
+
<%# The attribute is always present and only its value varies, because
|
|
45
|
+
ERB escapes interpolated output — injecting the whole attribute
|
|
46
|
+
rendered it as aria-current="page" and the
|
|
47
|
+
a[aria-current="page"] rule never matched. "false" is the value
|
|
48
|
+
ARIA defines for "not the current item". %>
|
|
49
|
+
<a
|
|
50
|
+
href="<%= page.relative_url %>"
|
|
51
|
+
aria-current="<%= current?(page) ? "page" : "false" %>"
|
|
52
|
+
><%= page.data.title %></a>
|
|
53
|
+
<% end %>
|
|
54
|
+
</nav>
|
|
55
|
+
<% end %>
|
|
56
|
+
|
|
57
|
+
<div class="sd-sidebar-footer">
|
|
58
|
+
<button class="sd-theme-toggle" type="button" data-shoreditch-theme-toggle>
|
|
59
|
+
Switch theme
|
|
60
|
+
</button>
|
|
61
|
+
<p>© <%= Time.now.year %> <%= site.metadata.author&.name || site.metadata.title %></p>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</aside>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# The fixed left column: logo, site identity, navigation and footer.
|
|
4
|
+
#
|
|
5
|
+
# Navigation is drawn from pages that opt in with `nav_order` in their front
|
|
6
|
+
# matter, so a site controls the menu from its content rather than from theme
|
|
7
|
+
# configuration. Pages with `exclude: true` never appear.
|
|
8
|
+
class Shoreditch::Sidebar < Bridgetown::Component
|
|
9
|
+
def initialize(site:, resource:)
|
|
10
|
+
@site = site
|
|
11
|
+
@resource = resource
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Components get no implicit access to the site, so it is passed in and
|
|
15
|
+
# exposed for the template.
|
|
16
|
+
attr_reader :site
|
|
17
|
+
|
|
18
|
+
def options
|
|
19
|
+
@site.config.shoreditch
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def nav_pages
|
|
23
|
+
@site.collections.pages.resources
|
|
24
|
+
.reject { |page| page.data.exclude }
|
|
25
|
+
.select { |page| page.data.nav_order }
|
|
26
|
+
.sort_by { |page| [page.data.nav_order, page.data.title.to_s] }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def current?(page)
|
|
30
|
+
page.relative_url == @resource.relative_url
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
attr_reader :resource
|
|
34
|
+
|
|
35
|
+
def logo_source
|
|
36
|
+
return nil if @resource.data.include_logo == false
|
|
37
|
+
|
|
38
|
+
@resource.data.logo_location || @site.metadata.logo
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# `include_sticky: false` drops the site title, tagline and navigation. The
|
|
42
|
+
# CV page used it so its sidebar introduced a person rather than a site.
|
|
43
|
+
def sticky?
|
|
44
|
+
@resource.data.include_sticky != false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# A page can override the logo's shape, as the Jekyll version allowed.
|
|
48
|
+
def logo_shape
|
|
49
|
+
@resource.data.logo_shape || options[:logo_shape]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# "round" or "straight" — the badge under the logo, shaped independently.
|
|
53
|
+
def logo_legend_shape
|
|
54
|
+
@resource.data.logo_legend_shape || options[:logo_legend_shape] || "round"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def flashy_logo?
|
|
58
|
+
@resource.data.flashy_logo == true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def logo_legend
|
|
62
|
+
# A page can override the badge, or suppress it by setting it to false.
|
|
63
|
+
return @resource.data.logo_legend if @resource.data.key?("logo_legend")
|
|
64
|
+
|
|
65
|
+
options[:logo_legend]
|
|
66
|
+
end
|
|
67
|
+
end
|