jekyll-awesome-nav 0.1.3 → 0.2.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/.copier-answers.ci.yml +1 -1
- data/README.md +2 -2
- data/lib/jekyll/awesome_nav/generator.rb +1 -1
- data/lib/jekyll/awesome_nav/navigation_result.rb +49 -29
- data/lib/jekyll/awesome_nav/serializer.rb +1 -1
- data/lib/jekyll/awesome_nav/version.rb +1 -1
- data/site/_includes/awesome-nav-tree.html +1 -1
- data/site/_layouts/awesome_nav_demo.html +98 -0
- data/site/docs/guides/data.md +12 -3
- data/site/docs/guides/layouts.md +5 -2
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 033420eec75b6786d092924ce18408a536c7ec67c9987924506538186a4cc561
|
|
4
|
+
data.tar.gz: f7bcf2906a41f300ed37c921c45f18b2fc764edcec95c9b69c1d3efeb4aa8386
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 58e508a035a0993b79f9511c10d1d7104df50c04c7d5a4ec6304e9f51a8677f93d05bb1aafaec98238ad0a2e5b46dd594722518fbc435a011b58855870658c75
|
|
7
|
+
data.tar.gz: d9ab55d7518df3cb520ef0c566d2a78b27eb269d4e744988895d7c0d1710f0e3c9c672b768cb1c78c80262dc8d06572cf3a79caf2806d993a76eebdd4e78c500
|
data/.copier-answers.ci.yml
CHANGED
data/README.md
CHANGED
|
@@ -65,10 +65,10 @@ awesome_nav:
|
|
|
65
65
|
|
|
66
66
|
Each page under the configured root receives:
|
|
67
67
|
|
|
68
|
-
- `page.awesome_nav`: the full navigation tree rooted at `awesome_nav.root`
|
|
68
|
+
- `page.awesome_nav`: the full navigation tree rooted at `awesome_nav.root`, annotated with `current` and `contains_current`
|
|
69
69
|
- `page.awesome_nav_local`: the local subtree for the page's directory
|
|
70
70
|
- `page.awesome_nav_dir`: the directory supplying the active nav context
|
|
71
|
-
- `page.breadcrumbs`: breadcrumb items
|
|
71
|
+
- `page.breadcrumbs`: lightweight breadcrumb items with `title` and `url`
|
|
72
72
|
- `page.awesome_nav_previous`: the previous linked nav item, when one exists
|
|
73
73
|
- `page.awesome_nav_next`: the next linked nav item, when one exists
|
|
74
74
|
|
|
@@ -46,7 +46,7 @@ module Jekyll
|
|
|
46
46
|
page_url = Utils.normalize_url(page.url)
|
|
47
47
|
page_entry = result.nav_entry_for(page_url)
|
|
48
48
|
|
|
49
|
-
page.data["awesome_nav"] = deep_copy(result.
|
|
49
|
+
page.data["awesome_nav"] = deep_copy(result.annotated_tree_for(page_url))
|
|
50
50
|
page.data["awesome_nav_local"] = deep_copy(result.local_nav_for(nav_dir))
|
|
51
51
|
page.data["awesome_nav_dir"] = nav_dir
|
|
52
52
|
page.data["breadcrumbs"] = result.breadcrumbs_for(page)
|
|
@@ -14,6 +14,10 @@ module Jekyll
|
|
|
14
14
|
@serialized_tree ||= Serializer.serialize_tree(@tree)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def annotated_tree_for(page_url)
|
|
18
|
+
annotate_current(serialized_tree, Utils.normalize_url(page_url)).first
|
|
19
|
+
end
|
|
20
|
+
|
|
17
21
|
def serialized_local_nav_map
|
|
18
22
|
@serialized_local_nav_map ||= Serializer.serialize_map(local_nav_nodes)
|
|
19
23
|
end
|
|
@@ -42,20 +46,11 @@ module Jekyll
|
|
|
42
46
|
|
|
43
47
|
def breadcrumbs_for(page)
|
|
44
48
|
page_url = Utils.normalize_url(page.url)
|
|
45
|
-
trail = find_trail(
|
|
49
|
+
trail = find_trail(internal_serialized_tree, page_url)
|
|
46
50
|
return root_breadcrumb(page) if trail.nil? && Utils.source_dir_for(page) == @root_dir && Utils.index_page?(page)
|
|
47
51
|
return [] unless trail
|
|
48
52
|
|
|
49
|
-
breadcrumbs = trail.filter_map
|
|
50
|
-
next if item["title"].to_s.empty?
|
|
51
|
-
|
|
52
|
-
crumb = { "title" => item["title"] }
|
|
53
|
-
crumb["url"] = item["url"] if item["url"]
|
|
54
|
-
crumb
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
breadcrumbs = trim_root_breadcrumb(breadcrumbs)
|
|
58
|
-
return breadcrumbs if @root_dir.empty?
|
|
53
|
+
breadcrumbs = trail.filter_map { |item| breadcrumb_item_for(item) }
|
|
59
54
|
|
|
60
55
|
prepend_root_breadcrumb(breadcrumbs)
|
|
61
56
|
end
|
|
@@ -66,6 +61,10 @@ module Jekyll
|
|
|
66
61
|
|
|
67
62
|
private
|
|
68
63
|
|
|
64
|
+
def internal_serialized_tree
|
|
65
|
+
@internal_serialized_tree ||= Serializer.serialize_tree(@tree, include_internal: true)
|
|
66
|
+
end
|
|
67
|
+
|
|
69
68
|
def local_nav_nodes
|
|
70
69
|
@local_nav_nodes ||= begin
|
|
71
70
|
map = { @root_dir => @tree.map(&:deep_dup) }
|
|
@@ -87,14 +86,12 @@ module Jekyll
|
|
|
87
86
|
end
|
|
88
87
|
|
|
89
88
|
def root_breadcrumb(page)
|
|
90
|
-
|
|
91
|
-
title = resolved_root_title if title.to_s.empty?
|
|
92
|
-
[{ "title" => title, "url" => Utils.normalize_url(page.url) }]
|
|
89
|
+
[{ "title" => root_breadcrumb_title, "url" => Utils.normalize_url(page.url) }]
|
|
93
90
|
end
|
|
94
91
|
|
|
95
92
|
def prepend_root_breadcrumb(breadcrumbs)
|
|
96
93
|
root_crumb = {
|
|
97
|
-
"title" =>
|
|
94
|
+
"title" => root_breadcrumb_title,
|
|
98
95
|
"url" => Utils.normalize_url(@root_page&.url || "/#{@root_dir}/")
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -103,25 +100,12 @@ module Jekyll
|
|
|
103
100
|
[root_crumb] + breadcrumbs
|
|
104
101
|
end
|
|
105
102
|
|
|
106
|
-
def trim_root_breadcrumb(breadcrumbs)
|
|
107
|
-
return breadcrumbs if breadcrumbs.empty?
|
|
108
|
-
|
|
109
|
-
root_crumb = {
|
|
110
|
-
"title" => resolved_root_title,
|
|
111
|
-
"url" => Utils.normalize_url(@root_page&.url || "/#{@root_dir}/")
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return breadcrumbs unless same_breadcrumb_url?(breadcrumbs.first, root_crumb)
|
|
115
|
-
|
|
116
|
-
breadcrumbs[1..] || []
|
|
117
|
-
end
|
|
118
|
-
|
|
119
103
|
def neighbor_map
|
|
120
104
|
@neighbor_map ||= begin
|
|
121
105
|
items = []
|
|
122
106
|
if @root_page
|
|
123
107
|
items << {
|
|
124
|
-
"title" =>
|
|
108
|
+
"title" => root_breadcrumb_title,
|
|
125
109
|
"url" => Utils.normalize_url(@root_page.url)
|
|
126
110
|
}
|
|
127
111
|
end
|
|
@@ -158,6 +142,36 @@ module Jekyll
|
|
|
158
142
|
nil
|
|
159
143
|
end
|
|
160
144
|
|
|
145
|
+
def annotate_current(items, target_url)
|
|
146
|
+
annotated_items = Array(items).map do |item|
|
|
147
|
+
annotated_children, child_contains_current = annotate_current(item["children"], target_url)
|
|
148
|
+
current = current_item?(item, target_url)
|
|
149
|
+
contains_current = child_contains_current || current
|
|
150
|
+
|
|
151
|
+
annotated_item = deep_copy(item)
|
|
152
|
+
annotated_item["current"] = current
|
|
153
|
+
annotated_item["contains_current"] = contains_current
|
|
154
|
+
annotated_item["children"] = annotated_children if annotated_item["children"].is_a?(Array)
|
|
155
|
+
annotated_item
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
[annotated_items, annotated_items.any? { |item| item["contains_current"] }]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def breadcrumb_item_for(item)
|
|
162
|
+
return if item["title"].to_s.empty?
|
|
163
|
+
|
|
164
|
+
crumb = { "title" => item["title"] }
|
|
165
|
+
crumb["url"] = item["url"] if item["url"]
|
|
166
|
+
crumb
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def current_item?(item, target_url)
|
|
170
|
+
return false unless item["url"]
|
|
171
|
+
|
|
172
|
+
Utils.normalize_url(item["url"]) == target_url
|
|
173
|
+
end
|
|
174
|
+
|
|
161
175
|
def deep_copy(value)
|
|
162
176
|
Marshal.load(Marshal.dump(value))
|
|
163
177
|
end
|
|
@@ -168,6 +182,12 @@ module Jekyll
|
|
|
168
182
|
Utils.normalize_url(left["url"]) == Utils.normalize_url(right["url"])
|
|
169
183
|
end
|
|
170
184
|
|
|
185
|
+
def root_breadcrumb_title
|
|
186
|
+
return "home" if @root_dir.empty?
|
|
187
|
+
|
|
188
|
+
resolved_root_title
|
|
189
|
+
end
|
|
190
|
+
|
|
171
191
|
def resolved_root_title
|
|
172
192
|
title = @root_page&.data&.fetch("nav_title", nil) ||
|
|
173
193
|
@root_page&.data&.fetch("title", nil) ||
|
|
@@ -18,7 +18,7 @@ module Jekyll
|
|
|
18
18
|
item = { "title" => node.title }
|
|
19
19
|
item["url"] = node.url if node.url
|
|
20
20
|
item["children"] = serialize_tree(node.children, include_internal: include_internal) if node.section? && node.children.any?
|
|
21
|
-
item["__dir"] = node.dir if include_internal && node.dir
|
|
21
|
+
item["__dir"] = node.dir if include_internal && !node.dir.nil?
|
|
22
22
|
item
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -239,6 +239,63 @@ layout: default
|
|
|
239
239
|
margin-top: 1.25rem;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
.awesome-nav-demo__debug {
|
|
243
|
+
margin-top: 1.5rem;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.awesome-nav-demo__debug details {
|
|
247
|
+
border-radius: 1.25rem;
|
|
248
|
+
overflow: hidden;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.awesome-nav-demo__debug summary {
|
|
252
|
+
align-items: center;
|
|
253
|
+
cursor: pointer;
|
|
254
|
+
display: flex;
|
|
255
|
+
font-weight: 800;
|
|
256
|
+
gap: 0.75rem;
|
|
257
|
+
justify-content: space-between;
|
|
258
|
+
list-style: none;
|
|
259
|
+
padding: 1rem 1.15rem;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.awesome-nav-demo__debug summary::-webkit-details-marker {
|
|
263
|
+
display: none;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.awesome-nav-demo__debug-summary-copy {
|
|
267
|
+
font-size: 0.82rem;
|
|
268
|
+
font-weight: 600;
|
|
269
|
+
opacity: 0.82;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.awesome-nav-demo__debug-grid {
|
|
273
|
+
display: grid;
|
|
274
|
+
gap: 1rem;
|
|
275
|
+
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
|
|
276
|
+
padding: 0 1rem 1rem;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.awesome-nav-demo__debug-card {
|
|
280
|
+
border-radius: 1rem;
|
|
281
|
+
min-width: 0;
|
|
282
|
+
padding: 0.9rem;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.awesome-nav-demo__debug-card h2 {
|
|
286
|
+
font-size: 0.95rem;
|
|
287
|
+
margin: 0 0 0.65rem;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.awesome-nav-demo__debug-card pre {
|
|
291
|
+
font-size: 0.78rem;
|
|
292
|
+
line-height: 1.5;
|
|
293
|
+
margin: 0;
|
|
294
|
+
overflow: auto;
|
|
295
|
+
white-space: pre-wrap;
|
|
296
|
+
word-break: break-word;
|
|
297
|
+
}
|
|
298
|
+
|
|
242
299
|
.awesome-nav-demo__pager a {
|
|
243
300
|
border-radius: 1.25rem;
|
|
244
301
|
display: flex;
|
|
@@ -365,6 +422,47 @@ layout: default
|
|
|
365
422
|
{{ content | inject_anchors }}
|
|
366
423
|
</article>
|
|
367
424
|
|
|
425
|
+
<section class="awesome-nav-demo__debug" aria-label="Plugin debug data">
|
|
426
|
+
<details>
|
|
427
|
+
<summary>
|
|
428
|
+
<span>Plugin data</span>
|
|
429
|
+
<span class="awesome-nav-demo__debug-summary-copy">Resolved page variables for this page</span>
|
|
430
|
+
</summary>
|
|
431
|
+
|
|
432
|
+
<div class="awesome-nav-demo__debug-grid">
|
|
433
|
+
<section class="awesome-nav-demo__debug-card">
|
|
434
|
+
<h2><code>page.breadcrumbs</code></h2>
|
|
435
|
+
<pre>{{ page.breadcrumbs | jsonify }}</pre>
|
|
436
|
+
</section>
|
|
437
|
+
|
|
438
|
+
<section class="awesome-nav-demo__debug-card">
|
|
439
|
+
<h2><code>page.awesome_nav</code></h2>
|
|
440
|
+
<pre>{{ page.awesome_nav | jsonify }}</pre>
|
|
441
|
+
</section>
|
|
442
|
+
|
|
443
|
+
<section class="awesome-nav-demo__debug-card">
|
|
444
|
+
<h2><code>page.awesome_nav_local</code></h2>
|
|
445
|
+
<pre>{{ page.awesome_nav_local | jsonify }}</pre>
|
|
446
|
+
</section>
|
|
447
|
+
|
|
448
|
+
<section class="awesome-nav-demo__debug-card">
|
|
449
|
+
<h2><code>page.awesome_nav_dir</code></h2>
|
|
450
|
+
<pre>{{ page.awesome_nav_dir | jsonify }}</pre>
|
|
451
|
+
</section>
|
|
452
|
+
|
|
453
|
+
<section class="awesome-nav-demo__debug-card">
|
|
454
|
+
<h2><code>page.awesome_nav_previous</code></h2>
|
|
455
|
+
<pre>{{ page.awesome_nav_previous | jsonify }}</pre>
|
|
456
|
+
</section>
|
|
457
|
+
|
|
458
|
+
<section class="awesome-nav-demo__debug-card">
|
|
459
|
+
<h2><code>page.awesome_nav_next</code></h2>
|
|
460
|
+
<pre>{{ page.awesome_nav_next | jsonify }}</pre>
|
|
461
|
+
</section>
|
|
462
|
+
</div>
|
|
463
|
+
</details>
|
|
464
|
+
</section>
|
|
465
|
+
|
|
368
466
|
{% if previous_item or next_item %}
|
|
369
467
|
<nav class="awesome-nav-demo__pager" aria-label="Pagination">
|
|
370
468
|
{% if previous_item %}
|
data/site/docs/guides/data.md
CHANGED
|
@@ -8,10 +8,10 @@ The plugin writes navigation data onto each page under the configured docs root.
|
|
|
8
8
|
|
|
9
9
|
| Variable | Description |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| `page.awesome_nav` | Full resolved docs tree. |
|
|
11
|
+
| `page.awesome_nav` | Full resolved docs tree with `current` and `contains_current` state for rendering. |
|
|
12
12
|
| `page.awesome_nav_local` | Navigation items for the current directory context. |
|
|
13
13
|
| `page.awesome_nav_dir` | Directory that supplied the current local nav context. |
|
|
14
|
-
| `page.breadcrumbs` |
|
|
14
|
+
| `page.breadcrumbs` | Lightweight breadcrumb entries for the current page. |
|
|
15
15
|
| `page.awesome_nav_previous` | Previous page in the resolved navigation order. |
|
|
16
16
|
| `page.awesome_nav_next` | Next page in the resolved navigation order. |
|
|
17
17
|
|
|
@@ -19,16 +19,25 @@ For README-indexed directories, these values are computed using the directory in
|
|
|
19
19
|
|
|
20
20
|
## Tree item shape
|
|
21
21
|
|
|
22
|
-
Navigation entries are hashes with a title, URL, and
|
|
22
|
+
Navigation entries are hashes with a title, URL, optional children, and current-state flags:
|
|
23
23
|
|
|
24
24
|
```yaml
|
|
25
25
|
title: Install Guide
|
|
26
26
|
url: /docs/guides/install/
|
|
27
|
+
current: true
|
|
28
|
+
contains_current: true
|
|
27
29
|
children: []
|
|
28
30
|
```
|
|
29
31
|
|
|
30
32
|
Layouts should treat `children` as optional because leaf pages do not need nested items.
|
|
31
33
|
|
|
34
|
+
Breadcrumb items stay lightweight and only expose:
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
title: Install Guide
|
|
38
|
+
url: /docs/guides/install/
|
|
39
|
+
```
|
|
40
|
+
|
|
32
41
|
## Site variables
|
|
33
42
|
|
|
34
43
|
The plugin also writes resolved data into `site.config` for advanced theme use:
|
data/site/docs/guides/layouts.md
CHANGED
|
@@ -46,14 +46,17 @@ The plugin writes breadcrumbs to `page.breadcrumbs`.
|
|
|
46
46
|
|
|
47
47
|
## Render a sidebar
|
|
48
48
|
|
|
49
|
-
Use `page.awesome_nav` for the full docs tree:
|
|
49
|
+
Use `page.awesome_nav` for the full docs tree. Each item includes `current` for the exact page match and `contains_current` for the active branch:
|
|
50
50
|
|
|
51
51
|
```liquid
|
|
52
52
|
{% raw %}<nav aria-label="Documentation">
|
|
53
53
|
<ul>
|
|
54
54
|
{% for item in page.awesome_nav %}
|
|
55
55
|
<li>
|
|
56
|
-
<a href="{{ item.url | relative_url }}">{{ item.title }}</a>
|
|
56
|
+
<a href="{{ item.url | relative_url }}"{% if item.current %} aria-current="page"{% endif %}>{{ item.title }}</a>
|
|
57
|
+
{% if item.contains_current %}
|
|
58
|
+
<span class="visually-hidden">(current section)</span>
|
|
59
|
+
{% endif %}
|
|
57
60
|
{% if item.children %}
|
|
58
61
|
<ul>
|
|
59
62
|
{% for child in item.children %}
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-awesome-nav
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Allison Thackston
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|