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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 76b40b8ac598c39b7d6ea9b1235a4089893bd73e52d8722e8a2c4af8115aa468
4
- data.tar.gz: d4109676b6da69d8f40d623b55d40087d57c45f46c718fa349116a9080807bf9
3
+ metadata.gz: 033420eec75b6786d092924ce18408a536c7ec67c9987924506538186a4cc561
4
+ data.tar.gz: f7bcf2906a41f300ed37c921c45f18b2fc764edcec95c9b69c1d3efeb4aa8386
5
5
  SHA512:
6
- metadata.gz: 89bb231311898453666edc086e0a54d6593d6c2644749e4f8a021253b0d272bb56f9bb0c522b9eac17314ea94ccd33e0d2289bd01dde5b69fc9f5f95b2b61ec9
7
- data.tar.gz: 7c05e014b8ad8ae8d6fc31f3382af750f10bde1d481f1ad1e19def058645c85e6a4db8b95514a674736da12170e2a49d30898a248ed8c4296d526f967257823c
6
+ metadata.gz: 58e508a035a0993b79f9511c10d1d7104df50c04c7d5a4ec6304e9f51a8677f93d05bb1aafaec98238ad0a2e5b46dd594722518fbc435a011b58855870658c75
7
+ data.tar.gz: d9ab55d7518df3cb520ef0c566d2a78b27eb269d4e744988895d7c0d1710f0e3c9c672b768cb1c78c80262dc8d06572cf3a79caf2806d993a76eebdd4e78c500
@@ -1,5 +1,5 @@
1
1
  # Changes here will be overwritten by Copier; NEVER EDIT MANUALLY
2
- _commit: 618054b
2
+ _commit: 97c7f4b
3
3
  _src_path: gh:athackst/ci
4
4
  automerge_mode: poll
5
5
  bump_script_path: ''
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 derived from the final tree
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.serialized_tree)
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(serialized_tree, page_url)
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 do |item|
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
- title = page.data["nav_title"] || page.data["title"] || Utils.titleize(Utils.last_segment(@root_dir))
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" => resolved_root_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" => resolved_root_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
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Jekyll
4
4
  module AwesomeNav
5
- VERSION = "0.1.3"
5
+ VERSION = "0.2.0"
6
6
 
7
7
  def self.warn_if_unstamped_version(output = $stderr)
8
8
  return unless VERSION == "0.0.0"
@@ -3,7 +3,7 @@
3
3
  {% if item.url %}
4
4
  <a
5
5
  href="{{ item.url | relative_url }}"
6
- {% if item.url == page.url %}aria-current="page"{% endif %}
6
+ {% if item.current %}aria-current="page"{% endif %}
7
7
  >
8
8
  {{ item.title }}
9
9
  </a>
@@ -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 %}
@@ -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` | Breadcrumb entries for the current page. |
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 optional children:
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:
@@ -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.1.3
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-19 00:00:00.000000000 Z
11
+ date: 2026-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jekyll