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 +4 -4
- data/CHANGELOG.md +18 -0
- data/_data/backlog.yml +124 -2
- data/_includes/components/component-showcase.html +18 -10
- data/_includes/components/js-cdn.html +10 -2
- data/_includes/components/post-card.html +18 -4
- data/_includes/content/backlinks.html +47 -18
- data/_includes/content/giscus.html +30 -44
- data/_includes/core/footer-fabs.html +5 -2
- data/_includes/navigation/local-graph-fab.html +1 -1
- data/_includes/navigation/local-graph.html +4 -3
- data/_includes/navigation/section-sidebar.html +10 -3
- data/_includes/obsidian/full-graph.html +7 -5
- data/_layouts/article.html +23 -6
- data/_plugins/obsidian_links.rb +84 -15
- data/_sass/core/_obsidian.scss +59 -8
- data/assets/data/wiki-index.json +50 -3
- data/assets/js/obsidian-graph.js +66 -21
- data/assets/js/obsidian-local-graph.js +125 -32
- data/assets/js/obsidian-wiki-links.js +118 -21
- data/assets/js/search-modal.js +45 -9
- data/scripts/bin/giscus-discussions +509 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9bb7f0d10a0dcb7cbe5297c6a412db670fc837d5acc43c85b6752baab5acf5a9
|
|
4
|
+
data.tar.gz: '0095e82963f7316a63fecdf355f6fb3e8a126c7528666ab540d274175dda515c'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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-
|
|
66
|
-
next_id:
|
|
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
|
-
|
|
20
|
-
|
|
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="
|
|
324
|
-
<li class="breadcrumb-item"><a href="
|
|
325
|
-
<li class="breadcrumb-item"><a href="
|
|
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="
|
|
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="
|
|
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="
|
|
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="
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
{%
|
|
117
|
-
<a href="{{ site.baseurl }}{{
|
|
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
|
-
{%-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
{%-
|
|
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
|
|
123
|
+
<span class="badge rounded-pill border text-body-secondary ms-1">{{ _ref.collection }}</span>
|
|
96
124
|
{%- endif -%}
|
|
97
|
-
{%-
|
|
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
|
-
{{
|
|
128
|
+
{{ _ref_excerpt }}
|
|
100
129
|
</div>
|
|
101
130
|
{%- endif -%}
|
|
102
131
|
</li>
|
|
@@ -1,49 +1,35 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
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
|
-
{
|
|
27
|
-
{
|
|
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="
|
|
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
|
-
{%
|
|
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="{{
|
|
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="{{
|
|
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="
|
|
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
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
|