jekyll-theme-zer0 1.21.0 → 1.22.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: 8552bc1992ed59b6f63392207f6a49d12bc9e66ac16cd43b61bb57700f45395e
4
- data.tar.gz: 54304e964cff2dc7fafe3ab03c722dfac994011994be96201d700a67e224ec35
3
+ metadata.gz: 9bb7f0d10a0dcb7cbe5297c6a412db670fc837d5acc43c85b6752baab5acf5a9
4
+ data.tar.gz: '0095e82963f7316a63fecdf355f6fb3e8a126c7528666ab540d274175dda515c'
5
5
  SHA512:
6
- metadata.gz: d656b64ce2440c13047ce0802ca968c767cbcfe20eb8b442973e5cc0a63aafb29263081f2ab5c5737260775643193e9fad9eaa08680fe0151b8442efae15128d
7
- data.tar.gz: a1a9000773b53140084dd986072d1cbfacda99ba66859cfd5cd82965e163b1aa47184ef64e56cb41ed0a6e0ae2950a96a5f4935e637f073c756de757afb36a53
6
+ metadata.gz: 0240ae6516cbc159ae33925ad991e74b958ddbbe19c3806fdf6cde01ba7e625ae6a530184cde8a3e51d5e7748944eba105fec439cde7332910bce2e027f2b5d7
7
+ data.tar.gz: 80283b4cb1950832efac7b7713f660bab1d106adcc0dbeb320c385570a95cc5fd8e6f88614fd09fabdbc44081369300bc6e4e88ade905125edf5caad4ac14c74
data/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.22.0](https://github.com/bamr87/zer0-mistakes/compare/v1.21.0...v1.22.0) (2026-06-26)
9
+
10
+
11
+ ### Features
12
+
13
+ * **ci:** autonomous CI self-repair loop (pipeline Phase 6) ([#237](https://github.com/bamr87/zer0-mistakes/issues/237)) ([a43db45](https://github.com/bamr87/zer0-mistakes/commit/a43db45eae2da2fcf141ac959d0268dd7e6a52bd))
14
+ * **comments:** enable Giscus + wire Claude Code conversation building ([#214](https://github.com/bamr87/zer0-mistakes/issues/214)) ([fef60a5](https://github.com/bamr87/zer0-mistakes/commit/fef60a5cf78697e94c40f098c336112fe5cdd845))
15
+ * **obsidian:** interactive callouts, parity fixes, a11y + vendored graph ([#200](https://github.com/bamr87/zer0-mistakes/issues/200)) ([affbcd6](https://github.com/bamr87/zer0-mistakes/commit/affbcd62b3f7023457195d5137d5ace2a3751367))
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **ci:** enable auto-merge via GraphQL (no git checkout) + graceful no-op ([#232](https://github.com/bamr87/zer0-mistakes/issues/232)) ([4c8c74c](https://github.com/bamr87/zer0-mistakes/commit/4c8c74cfb0775feda9103b379ebcecc4874d517f))
21
+ * **includes:** existence-gate category badge links for remote-theme consumers ([#235](https://github.com/bamr87/zer0-mistakes/issues/235)) ([16ed0a8](https://github.com/bamr87/zer0-mistakes/commit/16ed0a8c77f4cd66b98918a66d00133fa90f4457))
22
+ * **includes:** make component-showcase demo links inert to avoid consumer 404s ([#236](https://github.com/bamr87/zer0-mistakes/issues/236)) ([e96646b](https://github.com/bamr87/zer0-mistakes/commit/e96646b196c2931fc240411ded23184a1e01c8f5))
23
+ * **navigation:** existence-gate the section-sidebar /tags/ links ([#231](https://github.com/bamr87/zer0-mistakes/issues/231)) ([a02b062](https://github.com/bamr87/zer0-mistakes/commit/a02b0622a4f16dfea375629ad347891861283fe3))
24
+ * **search:** degrade search UI gracefully when /search.json is absent ([#234](https://github.com/bamr87/zer0-mistakes/issues/234)) ([f3a718d](https://github.com/bamr87/zer0-mistakes/commit/f3a718d1a9219bee92e2d1a46d2e32c870efb624))
25
+
8
26
  ## [1.21.0](https://github.com/bamr87/zer0-mistakes/compare/v1.20.2...v1.21.0) (2026-06-26)
9
27
 
10
28
 
data/_data/backlog.yml CHANGED
@@ -62,8 +62,8 @@
62
62
 
63
63
  meta:
64
64
  title: "zer0-mistakes Backlog"
65
- updated: 2026-06-15
66
- next_id: 27
65
+ updated: 2026-06-26
66
+ next_id: 32
67
67
 
68
68
  tasks:
69
69
  # --- Housekeeping (seeded so the loop has work on day one) ------------------
@@ -713,3 +713,125 @@ tasks:
713
713
  links: { issue: null, pr: null, roadmap: null }
714
714
  created: 2026-06-15
715
715
  updated: 2026-06-15
716
+
717
+ # --- Issue intake 2026-06-26: remote-theme 404 cluster + docs ----------------
718
+ # Cap: 5 of 7 open issues triaged this run. Deferred (next run): #203 (consumer
719
+ # checklist docs — companion to T-031); #201 (giscus typo — already in-flight in
720
+ # PR #214, so no task, to avoid duplicating live work).
721
+
722
+ - id: T-027
723
+ title: "Theme chrome injects unconditional links (/authors/, /news/, /tags/, /posts/, graph) that 404 for remote-theme consumers"
724
+ status: open
725
+ priority: P2
726
+ area: a11y
727
+ risk: standard
728
+ effort: M
729
+ source: issue
730
+ route: a11y
731
+ summary: >-
732
+ Umbrella for the remote-theme 404 class (#204): the theme chrome itself
733
+ injects internal links to pages whose generators live in `_plugins` (skipped
734
+ by GitHub Pages safe mode), so a built consumer site has broken links on
735
+ every page. Guard each link by existence the way the footer "Quick Links"
736
+ block already does. Specific instances are T-029 (#218 sidebar) and T-030
737
+ (#219 showcase); T-028 (#202) is the search/sitemap variant. Any fix that
738
+ edits `_plugins/` is CODEOWNERS-gated -> human review.
739
+ acceptance:
740
+ - "Theme-injected chrome links render only when their target exists (mirror the footer Quick-Links existence guard)."
741
+ - "A link check over a built remote-theme `_site` reports no theme-injected 404s."
742
+ - "No edit to `lib/jekyll-theme-zer0/version.rb` or release files."
743
+ links: { issue: 204, pr: null, roadmap: null }
744
+ created: 2026-06-26
745
+ updated: 2026-06-26
746
+
747
+ - id: T-028
748
+ title: "remote_theme Pages consumers 404 on /search.json and /sitemap/ (generator is plugin-only)"
749
+ status: open
750
+ priority: P2
751
+ area: feat
752
+ risk: standard
753
+ effort: M
754
+ source: issue
755
+ route: code-fixer
756
+ summary: >-
757
+ On a pure remote-theme Pages consumer, `/search.json` and `/sitemap/` 404
758
+ because `_plugins/search_and_sitemap_generator.rb` never runs under Pages
759
+ safe mode (#202). Provide a Pages-safe fallback (committed stubs the navbar
760
+ search + sitemap link can resolve, or graceful degradation in
761
+ `assets/js/search-modal.js`). NOTE: editing `_plugins/` is CODEOWNERS-gated
762
+ -> human review; prefer the non-plugin path.
763
+ acceptance:
764
+ - "On a remote-theme Pages build, the navbar search resolves (no /search.json 404) or degrades gracefully."
765
+ - "The /sitemap/ link resolves (no 404) for a remote-theme consumer."
766
+ - "No new runtime dependency; no edit to version/release files."
767
+ links: { issue: 202, pr: null, roadmap: null }
768
+ created: 2026-06-26
769
+ updated: 2026-06-26
770
+
771
+ - id: T-029
772
+ title: "Guard the unconditional /tags/ link in section-sidebar.html for remote-theme consumers"
773
+ status: open
774
+ priority: P2
775
+ area: feat
776
+ risk: low
777
+ effort: S
778
+ source: issue
779
+ route: theme-ui
780
+ summary: >-
781
+ `_includes/navigation/section-sidebar.html:69` hardcodes a `/tags/` link;
782
+ remote-theme consumers have no `/tags/` index (plugin-only), so it 404s
783
+ (#218). Guard it the way `_includes/core/footer.html` (~138-147) guards its
784
+ links, or gate on a `site.tags_page` flag. Instance of the T-027 class.
785
+ acceptance:
786
+ - "The sidebar 'View All Tags' link renders only when the tags index exists (or a documented site flag is set)."
787
+ - "Remote-theme consumers no longer 404 from the sidebar link; the Jekyll build stays green."
788
+ - "A `test/visual/*.spec.js` regression asserts the conditional render (theme-ui / visual-evidence)."
789
+ links: { issue: 218, pr: null, roadmap: null }
790
+ created: 2026-06-26
791
+ updated: 2026-06-26
792
+
793
+ - id: T-030
794
+ title: "component-showcase.html hardcodes demo links (/docs/, /pages/, /docs/customization/) that 404 for consumers"
795
+ status: open
796
+ priority: P3
797
+ area: feat
798
+ risk: low
799
+ effort: S
800
+ source: issue
801
+ route: theme-ui
802
+ summary: >-
803
+ `_includes/components/component-showcase.html` hardcodes absolute demo links
804
+ (~323-325, 417/421) that 404 for any consumer without those exact routes
805
+ (#219). Parameterize them (the component already accepts `sections`) or guard
806
+ each by existence. Low priority — demo component — but it makes the showcase
807
+ un-includable as-is. Instance of the T-027 class.
808
+ acceptance:
809
+ - "The showcase's demo links are parameterized or existence-guarded (no hardcoded absolute paths that can 404)."
810
+ - "Including the showcase on a consumer site produces no theme-injected 404s; the Jekyll build stays green."
811
+ - "A `test/visual/*.spec.js` regression covers the parameterized/guarded links (theme-ui / visual-evidence)."
812
+ links: { issue: 219, pr: null, roadmap: null }
813
+ created: 2026-06-26
814
+ updated: 2026-06-26
815
+
816
+ - id: T-031
817
+ title: "Document the safe-mode build-overlay recipe for consumers building outside GitHub Pages"
818
+ status: open
819
+ priority: P3
820
+ area: docs
821
+ risk: low
822
+ effort: S
823
+ source: issue
824
+ route: content
825
+ summary: >-
826
+ Consumers who build the theme outside GitHub Pages (own CI/Actions) must
827
+ reinvent the safe-mode overlay: clone the remote theme, overlay content,
828
+ strip `_plugins`, then `jekyll build --strict_front_matter` (#220). Document
829
+ the recipe in the docs (companion to the #203 consumer checklist). A proven
830
+ reference exists in lifehacker.dev's `scripts/ci/build.sh`.
831
+ acceptance:
832
+ - "A docs page/section under `pages/_docs/` documents the build-overlay recipe (clone -> overlay -> strip _plugins -> strict build)."
833
+ - "It is cross-linked from the remote-theme/deploy docs and passes markdownlint + the content-review deterministic tier."
834
+ - "No code change; docs only."
835
+ links: { issue: 220, pr: null, roadmap: null }
836
+ created: 2026-06-26
837
+ updated: 2026-06-26
@@ -15,13 +15,21 @@
15
15
  tabs,progress,breadcrumbs,table,tooltips,list-group
16
16
  Default: all sections
17
17
 
18
- Usage:
19
- {% include components/component-showcase.html %}
20
- {% include components/component-showcase.html sections="alerts,buttons,cards" %}
18
+ Usage (wrapped in raw so these examples are shown literally and NOT executed —
19
+ un-wrapped, Liquid runs them even inside this HTML comment and the include
20
+ recursively includes itself "stack level too deep"):
21
+ {% raw %}{% include components/component-showcase.html %}
22
+ {% include components/component-showcase.html sections="alerts,buttons,cards" %}{% endraw %}
21
23
 
22
24
  Dependencies:
23
25
  - Bootstrap 5.3 CSS & JS (loaded by theme)
24
26
  - Bootstrap Icons (loaded by theme)
27
+
28
+ Note: The breadcrumb and list-group links are DEMO links only — they are
29
+ intentionally inert (href="#" with onclick="return false;") so the
30
+ showcase never injects site-absolute paths (/docs/, /pages/, ...) that
31
+ would 404 on consumer sites that lack those exact routes (issue #219).
32
+ Do not point them at absolute paths.
25
33
  ===================================================================
26
34
  -->
27
35
  {% assign sections = include.sections | default: "alerts,buttons,badges,cards,accordion,tabs,progress,breadcrumbs,table,tooltips,list-group" %}
@@ -320,9 +328,9 @@ theme: jekyll-theme-zer0</code></pre>
320
328
  <p>Hierarchical navigation trail showing current page position:</p>
321
329
  <nav aria-label="breadcrumb example" class="mb-4">
322
330
  <ol class="breadcrumb">
323
- <li class="breadcrumb-item"><a href="/" class="text-decoration-none"><i class="bi bi-house me-1"></i>Home</a></li>
324
- <li class="breadcrumb-item"><a href="/docs/" class="text-decoration-none">Documentation</a></li>
325
- <li class="breadcrumb-item"><a href="/docs/customization/" class="text-decoration-none">Customization</a></li>
331
+ <li class="breadcrumb-item"><a href="#" class="text-decoration-none" onclick="return false;"><i class="bi bi-house me-1"></i>Home</a></li>
332
+ <li class="breadcrumb-item"><a href="#" class="text-decoration-none" onclick="return false;">Documentation</a></li>
333
+ <li class="breadcrumb-item"><a href="#" class="text-decoration-none" onclick="return false;">Customization</a></li>
326
334
  <li class="breadcrumb-item active" aria-current="page">Theme Colors</li>
327
335
  </ol>
328
336
  </nav>
@@ -414,19 +422,19 @@ document.addEventListener('DOMContentLoaded', () => {
414
422
  <div class="row g-4 mb-4">
415
423
  <div class="col-md-6">
416
424
  <div class="list-group">
417
- <a href="/pages/" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
425
+ <a href="#" onclick="return false;" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
418
426
  <span><i class="bi bi-journal-richtext text-primary me-2"></i>Blog Posts</span>
419
427
  <span class="badge bg-primary rounded-pill">{{ site.posts.size | default: "12" }}</span>
420
428
  </a>
421
- <a href="/docs/" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
429
+ <a href="#" onclick="return false;" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
422
430
  <span><i class="bi bi-book text-success me-2"></i>Documentation</span>
423
431
  <span class="badge bg-success rounded-pill">{{ site.documents.size | default: "8" }}</span>
424
432
  </a>
425
- <a href="/categories/" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
433
+ <a href="#" onclick="return false;" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
426
434
  <span><i class="bi bi-collection text-info me-2"></i>Categories</span>
427
435
  <span class="badge bg-info rounded-pill">{{ site.categories.size | default: "6" }}</span>
428
436
  </a>
429
- <a href="/tags/" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
437
+ <a href="#" onclick="return false;" class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
430
438
  <span><i class="bi bi-tags text-warning me-2"></i>Tags</span>
431
439
  <span class="badge bg-warning text-dark rounded-pill">{{ site.tags.size | default: "24" }}</span>
432
440
  </a>
@@ -44,15 +44,23 @@
44
44
  {% endif %}
45
45
 
46
46
  <!-- Obsidian wiki-link / embed / tag client-side resolver (fallback for the
47
- remote_theme GH Pages build, where _plugins/obsidian_links.rb cannot run). -->
47
+ remote_theme GH Pages build, where _plugins/obsidian_links.rb cannot run).
48
+ Honours `obsidian: { enabled: false }` in _config.yml — when disabled the
49
+ resolver script is not loaded and the flag self-disables any fork that
50
+ loads it another way. Note: `| default: true` would flip `false` back to
51
+ true (Liquid treats false as falsy), so test enabled == false explicitly. -->
48
52
  {%- assign obsidian_attachments_path = site.obsidian.attachments_path | default: '/assets/images/notes' -%}
49
53
  <script>
50
54
  window.OBSIDIAN_CONFIG = window.OBSIDIAN_CONFIG || {};
55
+ window.OBSIDIAN_CONFIG.enabled = {% if site.obsidian.enabled == false %}false{% else %}true{% endif %};
51
56
  window.OBSIDIAN_CONFIG.wikiIndexUrl = {{ '/assets/data/wiki-index.json' | relative_url | jsonify }};
52
57
  window.OBSIDIAN_CONFIG.attachmentsPath = {{ obsidian_attachments_path | relative_url | jsonify }};
53
58
  window.OBSIDIAN_CONFIG.tagBase = {{ '/tags/' | relative_url | jsonify }};
59
+ window.OBSIDIAN_CONFIG.cytoscapeUrl = {{ '/assets/vendor/cytoscape/cytoscape.min.js' | relative_url | jsonify }};
54
60
  </script>
55
- <script defer src="{{ '/assets/js/obsidian-wiki-links.js' | relative_url }}"></script>
61
+ {%- if site.obsidian.enabled != false -%}
62
+ <script defer src="{{ '/assets/js/obsidian-wiki-links.js' | relative_url }}?v={{ site.time | date: '%s' }}"></script>
63
+ {%- endif -%}
56
64
 
57
65
  <!-- Optional fork overrides: opt-in via `site.user_overrides: true` in _config.yml. -->
58
66
  {% if site.user_overrides %}
@@ -108,16 +108,30 @@
108
108
  <div class="card-body d-flex flex-column">
109
109
 
110
110
  <!-- Category Badge -->
111
- {% comment %} Category base is configurable (`category_base`, default `/news`)
112
- to avoid hardcoded 404s for remote-theme consumers. See issue #204. {% endcomment %}
111
+ {% comment %} Category base is configurable (`category_base`, default `/news`).
112
+ Only link the badge when that category index page exists in the build;
113
+ otherwise render a plain badge so remote-theme consumers (whose category
114
+ section is plugin/page-generated and absent) don't get a 404. Mirrors
115
+ the tag-badge / footer Quick-Links existence guard. See issue #204. {% endcomment %}
113
116
  {% if show_category and include.post.categories.size > 0 %}
114
117
  {% assign _category_base = site.category_base | default: '/news' %}
118
+ {% assign primary_category = include.post.categories | first %}
119
+ {% capture _category_url %}{{ _category_base }}/{{ primary_category | slugify }}/{% endcapture %}
120
+ {% comment %} Category index pages can live in site.pages (a regular page) or
121
+ site.posts (a dated section index), so check both. {% endcomment %}
122
+ {% assign _category_page = site.html_pages | where: "url", _category_url | first %}
123
+ {% unless _category_page %}
124
+ {% assign _category_page = site.posts | where: "url", _category_url | first %}
125
+ {% endunless %}
115
126
  <div class="mb-2">
116
- {% assign primary_category = include.post.categories | first %}
117
- <a href="{{ site.baseurl }}{{ _category_base }}/{{ primary_category | slugify }}/"
127
+ {% if _category_page %}
128
+ <a href="{{ site.baseurl }}{{ _category_url }}"
118
129
  class="badge bg-primary text-decoration-none">
119
130
  {{ primary_category }}
120
131
  </a>
132
+ {% else %}
133
+ <span class="badge bg-primary">{{ primary_category }}</span>
134
+ {% endif %}
121
135
  </div>
122
136
  {% endif %}
123
137
 
@@ -21,11 +21,26 @@
21
21
  ===================================================================
22
22
  {%- endcomment -%}
23
23
 
24
- {%- if page.backlinks != false -%}
24
+ {%- if page.backlinks != false and site.obsidian.enabled != false -%}
25
25
  {%- assign _self_url = page.url -%}
26
26
  {%- assign _self_title = page.title | default: "" | downcase | strip -%}
27
27
  {%- assign _self_basename = page.path | split: "/" | last | replace: ".md", "" | replace: ".markdown", "" | downcase -%}
28
28
 
29
+ {%- comment -%}
30
+ Needles = every name another page could wiki-link this page by: title,
31
+ file basename, and any frontmatter aliases. Normalized to lowercase + strip
32
+ to match the resolver. A backlink is a [[needle]] with a terminator
33
+ (]] | # ^) so [[Foobar]] does NOT match the needle "foo".
34
+ {%- endcomment -%}
35
+ {%- assign _needles = "" | split: "" -%}
36
+ {%- if _self_title != "" -%}{%- assign _needles = _needles | push: _self_title -%}{%- endif -%}
37
+ {%- if _self_basename != "" -%}{%- assign _needles = _needles | push: _self_basename -%}{%- endif -%}
38
+ {%- for _alias in page.aliases -%}
39
+ {%- assign _an = _alias | downcase | strip -%}
40
+ {%- if _an != "" -%}{%- assign _needles = _needles | push: _an -%}{%- endif -%}
41
+ {%- endfor -%}
42
+ {%- assign _needles = _needles | uniq -%}
43
+
29
44
  {%- assign _candidates = "" | split: "" -%}
30
45
  {%- for _coll in site.collections -%}
31
46
  {%- for _doc in _coll.docs -%}
@@ -46,31 +61,44 @@
46
61
  {%- if _doc.published == false or _doc.draft == true -%}{%- continue -%}{%- endif -%}
47
62
  {%- endunless -%}
48
63
  {%- assign _body = _doc.content | default: "" -%}
49
- {%- assign _body_lower = _body | downcase -%}
50
64
  {%- assign _matched = false -%}
51
65
 
66
+ {%- comment -%} A markdown link to this page's permalink is a backlink. {%- endcomment -%}
52
67
  {%- if _self_url and _self_url != "" and _self_url != "/" -%}
53
68
  {%- if _body contains _self_url -%}
54
69
  {%- assign _matched = true -%}
55
70
  {%- endif -%}
56
71
  {%- endif -%}
57
72
 
73
+ {%- comment -%}
74
+ Wiki-link match: strip fenced (```) and inline (`) code first so a page
75
+ that merely *documents* [[syntax]] doesn't register as a backlink, then
76
+ require a terminator after the needle.
77
+ {%- endcomment -%}
58
78
  {%- unless _matched -%}
59
- {%- if _self_title != "" -%}
60
- {%- assign _needle = "[[" | append: _self_title -%}
61
- {%- if _body_lower contains _needle -%}
79
+ {%- assign _nb = "" -%}
80
+ {%- assign _fp = _body | split: "```" -%}
81
+ {%- for _p in _fp -%}
82
+ {%- assign _m = forloop.index0 | modulo: 2 -%}
83
+ {%- if _m == 0 -%}{%- assign _nb = _nb | append: _p -%}{%- endif -%}
84
+ {%- endfor -%}
85
+ {%- assign _nb2 = "" -%}
86
+ {%- assign _ip = _nb | split: "`" -%}
87
+ {%- for _p in _ip -%}
88
+ {%- assign _m = forloop.index0 | modulo: 2 -%}
89
+ {%- if _m == 0 -%}{%- assign _nb2 = _nb2 | append: _p -%}{%- endif -%}
90
+ {%- endfor -%}
91
+ {%- assign _body_lower = _nb2 | downcase -%}
92
+ {%- for _n in _needles -%}
93
+ {%- assign _v1 = "[[" | append: _n | append: "]]" -%}
94
+ {%- assign _v2 = "[[" | append: _n | append: "|" -%}
95
+ {%- assign _v3 = "[[" | append: _n | append: "#" -%}
96
+ {%- assign _v4 = "[[" | append: _n | append: "^" -%}
97
+ {%- if _body_lower contains _v1 or _body_lower contains _v2 or _body_lower contains _v3 or _body_lower contains _v4 -%}
62
98
  {%- assign _matched = true -%}
99
+ {%- break -%}
63
100
  {%- endif -%}
64
- {%- endif -%}
65
- {%- endunless -%}
66
-
67
- {%- unless _matched -%}
68
- {%- if _self_basename != "" -%}
69
- {%- assign _needle2 = "[[" | append: _self_basename -%}
70
- {%- if _body_lower contains _needle2 -%}
71
- {%- assign _matched = true -%}
72
- {%- endif -%}
73
- {%- endif -%}
101
+ {%- endfor -%}
74
102
  {%- endunless -%}
75
103
 
76
104
  {%- if _matched -%}
@@ -92,11 +120,12 @@
92
120
  <strong>{{ _ref.title | default: _ref.path | split: "/" | last }}</strong>
93
121
  </a>
94
122
  {%- if _ref.collection -%}
95
- <span class="badge bg-light text-dark ms-1">{{ _ref.collection }}</span>
123
+ <span class="badge rounded-pill border text-body-secondary ms-1">{{ _ref.collection }}</span>
96
124
  {%- endif -%}
97
- {%- if _ref.description -%}
125
+ {%- assign _ref_excerpt = _ref.description | default: _ref.excerpt | strip_html | strip | truncate: 160 -%}
126
+ {%- if _ref_excerpt and _ref_excerpt != "" -%}
98
127
  <div class="obsidian-backlink-excerpt small text-muted">
99
- {{ _ref.description | strip_html | truncate: 160 }}
128
+ {{ _ref_excerpt }}
100
129
  </div>
101
130
  {%- endif -%}
102
131
  </li>
@@ -1,49 +1,35 @@
1
1
  <!--
2
- ╔═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
3
- ║ giscus.html ║
4
- ║ GitHub Discussions Comment System ║
5
- ╠═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
6
- ║ ║
7
- ║ Purpose: Integrates Giscus comment system powered by GitHub Discussions ║
8
- Location: /_includes/content/giscus.html ║
9
- ║ Usage: include content/giscus.html (Liquid tag; braces omitted — Liquid ║
10
- ║ parses include tags even inside HTML comments, which would error)
11
- Dependencies: GitHub repository with Discussions enabled, site.repository, site.giscus configuration ║
12
- ║ ║
13
- Features: ║
14
- ║ • GitHub Discussions-based commenting system ║
15
- ║ • Automatic theme detection (preferred_color_scheme) ║
16
- Pathname-based mapping for unique comment threads ║
17
- Reaction support for enhanced user engagement ║
18
- Top-positioned input for better UX ║
19
- ║ ║
20
- ║ Configuration Options: ║
21
- ║ • data-repo: GitHub repository (site.repository) ║
22
- ║ • data-repo-id: GitHub repository ID (site.giscus.data-repo-id) ║
23
- ║ • data-category-id: Discussions category ID (site.giscus.data-category-id) ║
24
- ║ • data-mapping: "pathname" - maps comments to page URL ║
25
- ║ • data-strict: "1" - enables strict mapping mode ║
26
- ║ ║
27
- ║ Setup Requirements: ║
28
- ║ • GitHub repository with Discussions feature enabled ║
29
- ║ • Giscus app installed on the repository ║
30
- ║ • Correct repo-id and category-id in _config.yml ║
31
- ║ ║
32
- ║ Reference: Feature Request #FR000001 ║
33
- ║ Documentation: https://giscus.app/ ║
34
- ║ ║
35
- ╚═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝
36
- -->
2
+ giscus.html — GitHub Discussions comment system
3
+ ===============================================
4
+
5
+ Purpose: Embeds the Giscus widget so page comments are stored as
6
+ GitHub Discussions (no database, privacy-friendly).
7
+ Location: _includes/content/giscus.html
8
+ Usage: Rendered by the article / note / notebook layouts, gated on
9
+ `page.comments != false and site.giscus.enabled`.
10
+ To include manually elsewhere, use the FULL path:
11
+ include content/giscus.html (wrap in Liquid tags)
12
+ Dependencies: site.repository, site.giscus.* (see _config.yml), a public
13
+ repo with Discussions enabled + the Giscus app installed.
14
+
15
+ Features:
16
+ GitHub Discussions-based commenting
17
+ Automatic light/dark theme (preferred_color_scheme)
18
+ Pathname-based mapping for one thread per page (data-strict)
19
+ • Reactions enabled, input positioned at the top
37
20
 
38
- <!-- ===================================================================================================== -->
39
- <!-- GISCUS COMMENT SYSTEM -->
40
- <!-- ===================================================================================================== -->
41
- <!-- GitHub Discussions-powered comment system integration -->
42
- <!-- Feature Request: #FR000001 -->
43
- <!-- Documentation: https://giscus.app/ -->
44
- <!-- Async loading: Non-blocking comment system initialization -->
21
+ Config-driven attributes (from _config.yml `giscus:` block):
22
+ data-repo ← site.repository
23
+ data-repo-id ← site.giscus.data-repo-id
24
+ data-category-id site.giscus.data-category-id
45
25
 
46
- <!-- giscus app - https://giscus.app/ - Feature # FR000001 -->
26
+ Docs: pages/_docs/features/giscus-comments.md
27
+ Reference: https://giscus.app/ (Feature Request #FR000001)
28
+
29
+ NOTE: do not write a bare `include giscus.html` example with live Liquid
30
+ braces inside this file — Liquid evaluates tags even inside HTML comments,
31
+ which would recursively (and wrongly) try to include "giscus.html".
32
+ -->
47
33
 
48
34
  <script src="https://giscus.app/client.js"
49
35
  data-repo="{{ site.repository }}"
@@ -58,4 +44,4 @@
58
44
  data-lang="en"
59
45
  crossorigin="anonymous"
60
46
  async>
61
- </script>
47
+ </script>
@@ -23,6 +23,9 @@
23
23
  {%- assign _root_only_layouts = "landing,welcome,stats,sitemap-collection,setup,section,news,index,home,admin" | split: "," -%}
24
24
  {%- unless _root_only_layouts contains page.layout -%}
25
25
  {% include navigation/toc-fab.html %}
26
- {% include navigation/local-graph-fab.html %}
27
- {% include navigation/local-graph.html %}
26
+ {%- comment -%} Local-graph FAB/panel are part of the Obsidian feature. {%- endcomment -%}
27
+ {%- if site.obsidian.enabled != false -%}
28
+ {% include navigation/local-graph-fab.html %}
29
+ {% include navigation/local-graph.html %}
30
+ {%- endif -%}
28
31
  {%- endunless -%}
@@ -11,7 +11,7 @@
11
11
  {%- endif -%}
12
12
  {%- endif -%}
13
13
  {%- if page.local_graph != false and _effective_sidebar != false -%}
14
- <div class="obsidian-local-graph-fab d-print-none" data-obsidian-local-graph-toggle>
14
+ <div id="obsidianLocalGraphFab" class="obsidian-local-graph-fab d-print-none" data-obsidian-local-graph-toggle hidden>
15
15
  <button class="btn btn-primary rounded-circle shadow-lg p-0 obsidian-local-graph-toggle"
16
16
  type="button"
17
17
  data-bs-toggle="offcanvas"
@@ -40,7 +40,8 @@
40
40
  aria-labelledby="obsidianLocalGraphLabel"
41
41
  data-bs-scroll="true"
42
42
  data-bs-backdrop="false"
43
- data-obsidian-local-graph-panel>
43
+ data-obsidian-local-graph-panel
44
+ hidden>
44
45
  <div class="offcanvas-header">
45
46
  <h2 class="offcanvas-title h5 mb-0" id="obsidianLocalGraphLabel">
46
47
  <i class="bi bi-diagram-3 me-2" aria-hidden="true"></i>Local graph
@@ -80,7 +81,7 @@
80
81
  <div id="obsidian-local-graph"
81
82
  data-depth="{{ lg_depth }}"
82
83
  data-index-url="{{ '/assets/data/wiki-index.json' | relative_url }}"
83
- role="img"
84
+ role="group"
84
85
  aria-label="Local graph of pages linked to this page"></div>
85
86
  <p class="obsidian-local-graph-status small text-secondary mt-2 mb-0"
86
87
  data-obsidian-local-graph-status
@@ -88,5 +89,5 @@
88
89
  </div>
89
90
  </div>
90
91
  </aside>
91
- <script src="{{ '/assets/js/obsidian-local-graph.js' | relative_url }}" defer></script>
92
+ <script src="{{ '/assets/js/obsidian-local-graph.js' | relative_url }}?v={{ site.time | date: '%s' }}" defer></script>
92
93
  {%- endif -%}
@@ -64,9 +64,14 @@
64
64
  {% endfor %}
65
65
  </nav>
66
66
  </div>
67
- {% if sub_categories.size > 15 %}
67
+ {% comment %} Existence-gate the tags index: a remote-theme consumer without
68
+ the (plugin-generated) /tags/ page must not get a 404 link. Mirrors the
69
+ footer Quick-Links guard and honours the documented site.tags_page. {% endcomment %}
70
+ {% assign _tags_url = site.tags_page | default: "/tags/" %}
71
+ {% assign _tags_page = site.html_pages | where: "url", _tags_url | first %}
72
+ {% if sub_categories.size > 15 and _tags_page %}
68
73
  <div class="card-footer bg-transparent">
69
- <a href="{{ site.baseurl }}/tags/" class="btn btn-sm btn-outline-secondary w-100">
74
+ <a href="{{ _tags_url | relative_url }}" class="btn btn-sm btn-outline-secondary w-100">
70
75
  View All Tags <i class="bi bi-arrow-right ms-1"></i>
71
76
  </a>
72
77
  </div>
@@ -123,11 +128,13 @@
123
128
  {% endif %}
124
129
  {% endfor %}
125
130
  </nav>
131
+ {% if _tags_page %}
126
132
  <div class="p-3">
127
- <a href="{{ site.baseurl }}/tags/" class="btn btn-outline-primary w-100">
133
+ <a href="{{ _tags_url | relative_url }}" class="btn btn-outline-primary w-100">
128
134
  <i class="bi bi-tags me-2"></i>Browse All Tags
129
135
  </a>
130
136
  </div>
137
+ {% endif %}
131
138
  </div>
132
139
  </div>
133
140
 
@@ -136,7 +136,7 @@ and [backlinks panel]({{ "/docs/obsidian/syntax-reference/#backlinks-panel" | re
136
136
  <span id="obsidian-graph-status" role="status"></span>
137
137
  </div>
138
138
 
139
- <div id="obsidian-graph" role="img" aria-label="Site knowledge graph"></div>
139
+ <div id="obsidian-graph" role="group" aria-label="Site knowledge graph"></div>
140
140
 
141
141
  <div class="obsidian-graph-legend" aria-label="Graph legend">
142
142
  <span><span class="swatch" style="background:#0d6efd"></span>Posts</span>
@@ -167,10 +167,12 @@ unresolved targets show up as dashed red nodes so you can find dangling
167
167
  links at a glance. The graph is regenerated every Jekyll build; nothing
168
168
  runs client-side except cytoscape's force layout.
169
169
 
170
- <!-- Cytoscape.js (vendored, only loaded on this page) no CDN so the graph
171
- works under strict CSP and offline. See assets/vendor/cytoscape/. -->
172
- <script src="{{ '/assets/vendor/cytoscape/cytoscape.min.js' | relative_url }}" defer></script>
173
- <script src="{{ '/assets/js/obsidian-graph.js' | relative_url }}" defer></script>
170
+ <!-- Cytoscape.js is vendored (no runtime CDN) and lazy-loaded by
171
+ obsidian-graph.js from window.OBSIDIAN_CONFIG.cytoscapeUrl, only on this
172
+ page, with an in-page recovery message if the fetch fails. -->
173
+ {% if site.obsidian.enabled != false %}
174
+ <script src="{{ '/assets/js/obsidian-graph.js' | relative_url }}?v={{ site.time | date: '%s' }}" defer></script>
175
+ {% endif %}
174
176
 
175
177
  ## See also
176
178