jekyll-theme-zer0 1.3.0 → 1.4.1
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 +41 -0
- data/README.md +4 -4
- data/_includes/components/cookie-consent.html +2 -3
- data/_includes/components/info-section.html +9 -4
- data/_includes/components/js-cdn.html +8 -1
- data/_includes/content/backlinks.html +4 -0
- data/_includes/core/footer.html +9 -8
- data/_includes/navigation/local-graph.html +55 -20
- data/_includes/navigation/sidebar-left.html +0 -6
- data/_includes/obsidian/full-graph.html +170 -0
- data/_layouts/default.html +104 -100
- data/_plugins/obsidian_links.rb +5 -0
- data/_plugins/preview_image_generator.rb +82 -25
- data/_sass/core/_obsidian.scss +77 -4
- data/_sass/core/_offcanvas-panels.scss +8 -4
- data/assets/data/wiki-index.json +44 -6
- data/assets/js/obsidian-graph.js +0 -1
- data/assets/js/obsidian-local-graph.js +72 -21
- data/assets/js/obsidian-wiki-links.js +21 -4
- data/scripts/README.md +22 -0
- data/scripts/bin/test +62 -0
- data/scripts/bin/validate +596 -0
- data/scripts/lib/README.md +16 -0
- data/scripts/validate +11 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ae8ec5b12734cd267a46b1b5c26ed95f7d55b004e6dd9a52111a477f6bbc395
|
|
4
|
+
data.tar.gz: 84ff1429cdd6504bef5977c44ff88ff9078ffdb2dcd98ea39304c10f939daceb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4c194515ed9cbf3590d46b6c887b9a27c94bbdfb4a5e841417ae759e25b59bd5bf0612846ce20927361daefa42b23459152336db6fb22874ce56b05c87d0203b
|
|
7
|
+
data.tar.gz: d0469bd560f3ddfc264b22e0fd4b7f7ffed2b9c1a7f524f3975b5a574a7a2ae0c5c8bf53c25db53eec1bb4201e21078f95a45de46e3dd742569171ca15d29421
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.4.1] - 2026-04-28
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Version bump: patch release
|
|
7
|
+
|
|
8
|
+
### Commits in this release
|
|
9
|
+
- 9830d3d refactor(obsidian): extract full graph include and sync docs (#82)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## [1.4.0] - 2026-04-25
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Version bump: minor release
|
|
16
|
+
|
|
17
|
+
### Commits in this release
|
|
18
|
+
- d39dfa9 Add standalone Obsidian local graph panel (#77)
|
|
19
|
+
|
|
20
|
+
|
|
3
21
|
## [1.3.0] - 2026-04-24
|
|
4
22
|
|
|
5
23
|
### Changed
|
|
@@ -39,7 +57,16 @@
|
|
|
39
57
|
|
|
40
58
|
## [Unreleased]
|
|
41
59
|
|
|
60
|
+
### Changed
|
|
61
|
+
- **Docker/Jekyll build performance** — Reduced repeated full-page Liquid scans in the footer, settings offcanvas, and cookie consent includes; cached preview image checks during generation; skipped server-side Obsidian rewrites for documents without Obsidian syntax; and changed Docker dev startup to run `bundle install` only when `bundle check` reports missing dependencies. The profiled Docker build improved from 119.2s to 86.8s in local validation.
|
|
62
|
+
|
|
42
63
|
### Added
|
|
64
|
+
- **Development Automation**: Added `scripts/bin/validate` and `scripts/validate`
|
|
65
|
+
as the canonical preflight validation command for repository files, version
|
|
66
|
+
consistency, YAML/data parsing, active configuration contracts, config-file
|
|
67
|
+
classification, navigation data shape, Jekyll build/doctor, compiled assets,
|
|
68
|
+
and optional tests/Obsidian/HTMLProofer checks. CI fast checks now call
|
|
69
|
+
`./scripts/bin/validate --quick`.
|
|
43
70
|
- **Obsidian Integration** — The repo's markdown content is now editable as an [Obsidian](https://obsidian.md) vault and rendered identically on GitHub Pages.
|
|
44
71
|
- Shared vault config (`.obsidian/app.json`, `core-plugins.json`, `community-plugins.json`, `appearance.json`, `hotkeys.json`, `templates.json`) and a Templates-compatible note template at `pages/_notes/_templates/note-template.md`.
|
|
45
72
|
- Liquid-generated `assets/data/wiki-index.json` listing every collection document and standalone page (title, basename, permalink, tags, aliases, excerpt) — works on the default GitHub Pages remote_theme build, no plugin whitelist changes required.
|
|
@@ -76,6 +103,20 @@
|
|
|
76
103
|
`Your Site Title`, `My Awesome Site`, `Welcome`, `Untitled`, or empty).
|
|
77
104
|
|
|
78
105
|
### Fixed
|
|
106
|
+
- **Obsidian Local Graph**: Moved the local graph out of the documentation
|
|
107
|
+
navigation sidebar into its own collapsible side panel with a larger canvas
|
|
108
|
+
and resize-on-open behavior so Cytoscape renders cleanly. Pages with no
|
|
109
|
+
local wiki-link neighbors now keep the graph control visible and render a
|
|
110
|
+
current-page-only graph instead of hiding the panel.
|
|
111
|
+
- **Obsidian Resolver**: The client-side wiki-link resolver now receives
|
|
112
|
+
baseurl-safe index, attachment, and tag URLs from Liquid and derives a safe
|
|
113
|
+
fallback from its script path for GitHub Pages project sites.
|
|
114
|
+
- **Backlinks**: The linked-mentions include now skips draft and unpublished
|
|
115
|
+
candidates unless `site.show_drafts` is enabled.
|
|
116
|
+
- **Validation**: `scripts/bin/validate --quick` now accepts YAML anchors and
|
|
117
|
+
date values used by repository config/data files.
|
|
118
|
+
- **Tests**: `test/test_runner.sh` now includes an `obsidian` suite key/name so
|
|
119
|
+
suite keys, scripts, and labels stay aligned.
|
|
79
120
|
- **Footer Quick Links no longer 404 on bare-minimum sites.**
|
|
80
121
|
`_includes/core/footer.html` previously hard-coded links to
|
|
81
122
|
`/about/`, `/services/`, `/news/`, `/contact/`, `/privacy-policy`, and
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: zer0-mistakes
|
|
3
3
|
sub-title: AI-Native Jekyll Theme
|
|
4
4
|
description: AI-native Jekyll theme for GitHub Pages — Docker-first development, AI-powered installation, multi-agent integration (Copilot, Codex, Cursor, Claude), AI preview-image generation, and AIEO content optimization with Bootstrap 5.3.
|
|
5
|
-
version: 1.
|
|
5
|
+
version: 1.4.1
|
|
6
6
|
layout: landing
|
|
7
7
|
tags:
|
|
8
8
|
- jekyll
|
|
@@ -20,7 +20,7 @@ categories:
|
|
|
20
20
|
- bootstrap
|
|
21
21
|
- ai-tooling
|
|
22
22
|
created: 2024-02-10T23:51:11.480Z
|
|
23
|
-
lastmod: 2026-04-
|
|
23
|
+
lastmod: 2026-04-28T21:04:09.000Z
|
|
24
24
|
draft: false
|
|
25
25
|
permalink: /
|
|
26
26
|
slug: zer0
|
|
@@ -1138,7 +1138,7 @@ git push origin feature/awesome-feature
|
|
|
1138
1138
|
|
|
1139
1139
|
| Metric | Value |
|
|
1140
1140
|
|--------|-------|
|
|
1141
|
-
| **Current Version** | 1.
|
|
1141
|
+
| **Current Version** | 1.4.1 ([RubyGems](https://rubygems.org/gems/jekyll-theme-zer0), [CHANGELOG](/CHANGELOG)) |
|
|
1142
1142
|
| **Documented Features** | 43 ([Feature Registry](https://github.com/bamr87/zer0-mistakes/blob/main/_data/features.yml)) |
|
|
1143
1143
|
| **Setup Time** | 2-5 minutes ([install.sh benchmarks](https://github.com/bamr87/zer0-mistakes/blob/main/install.sh)) |
|
|
1144
1144
|
| **Documentation Pages** | 70+ ([browse docs](/pages/)) |
|
|
@@ -1189,6 +1189,6 @@ And these AI partners that make zer0-mistakes truly AI-native:
|
|
|
1189
1189
|
|
|
1190
1190
|
**Built with ❤️ — and a little help from our AI partners — for the Jekyll community**
|
|
1191
1191
|
|
|
1192
|
-
**v1.
|
|
1192
|
+
**v1.4.1** • [Changelog](CHANGELOG.md) • [License](LICENSE) • [Contributing](CONTRIBUTING.md) • [AI Agent Guide](AGENTS.md)
|
|
1193
1193
|
|
|
1194
1194
|
|
|
@@ -59,9 +59,8 @@ Configuration: Uses site.posthog settings from _config.yml
|
|
|
59
59
|
</p>
|
|
60
60
|
<p class="mb-2 mb-lg-0 small text-white-50">
|
|
61
61
|
This website uses cookies and similar technologies to enhance your browsing experience, analyze traffic, and provide personalized content.
|
|
62
|
-
{% assign
|
|
63
|
-
{%
|
|
64
|
-
{% if _pp or site.privacy_policy_url %}
|
|
62
|
+
{% assign cookie_page_urls = site.html_pages | map: "url" | join: "|" | prepend: "|" | append: "|" %}
|
|
63
|
+
{% if site.privacy_policy_url or cookie_page_urls contains "|/privacy-policy/|" or cookie_page_urls contains "|/privacy-policy|" %}
|
|
65
64
|
<a href="{{ site.privacy_policy_url | default: '/privacy-policy/' | relative_url }}" class="text-white text-decoration-underline">Learn more in our Privacy Policy</a>.
|
|
66
65
|
{% endif %}
|
|
67
66
|
</p>
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
-->
|
|
23
23
|
|
|
24
24
|
{% include components/env-detect.html %}
|
|
25
|
+
{% assign info_section_page_urls = site.html_pages | map: "url" | join: "|" | prepend: "|" | append: "|" %}
|
|
25
26
|
<!-- Settings Offcanvas -->
|
|
26
27
|
<div class="offcanvas offcanvas-end" tabindex="-1" id="info-section" aria-labelledby="infoSectionLabel">
|
|
27
28
|
|
|
@@ -111,9 +112,12 @@
|
|
|
111
112
|
<!-- Admin Quick Links — only render links to pages that actually exist
|
|
112
113
|
in the build (prevents 404s on bare-minimum / remote-theme sites
|
|
113
114
|
that haven't created the admin pages). -->
|
|
114
|
-
{% assign _cfg_page =
|
|
115
|
-
{% assign _theme_page =
|
|
116
|
-
{% assign _nav_page =
|
|
115
|
+
{% assign _cfg_page = false %}
|
|
116
|
+
{% assign _theme_page = false %}
|
|
117
|
+
{% assign _nav_page = false %}
|
|
118
|
+
{% if info_section_page_urls contains "|/about/config/|" %}{% assign _cfg_page = true %}{% endif %}
|
|
119
|
+
{% if info_section_page_urls contains "|/about/settings/theme/|" %}{% assign _theme_page = true %}{% endif %}
|
|
120
|
+
{% if info_section_page_urls contains "|/about/settings/navigation/|" %}{% assign _nav_page = true %}{% endif %}
|
|
117
121
|
{% if _cfg_page or _theme_page or _nav_page %}
|
|
118
122
|
<div class="mb-3">
|
|
119
123
|
<h6 class="text-body-secondary small text-uppercase fw-semibold mb-2">
|
|
@@ -145,7 +149,8 @@
|
|
|
145
149
|
{% include components/env-switcher.html %}
|
|
146
150
|
|
|
147
151
|
<!-- Admin Link — only when target page exists -->
|
|
148
|
-
{% assign _env_page =
|
|
152
|
+
{% assign _env_page = false %}
|
|
153
|
+
{% if info_section_page_urls contains "|/about/settings/environment/|" %}{% assign _env_page = true %}{% endif %}
|
|
149
154
|
{% if _env_page %}
|
|
150
155
|
<div class="mt-4 pt-3 border-top">
|
|
151
156
|
<a href="{{ '/about/settings/environment/' | relative_url }}" class="btn btn-outline-secondary btn-sm w-100">
|
|
@@ -35,4 +35,11 @@
|
|
|
35
35
|
|
|
36
36
|
<!-- Obsidian wiki-link / embed / tag client-side resolver (fallback for the
|
|
37
37
|
remote_theme GH Pages build, where _plugins/obsidian_links.rb cannot run). -->
|
|
38
|
-
|
|
38
|
+
{%- assign obsidian_attachments_path = site.obsidian.attachments_path | default: '/assets/images/notes' -%}
|
|
39
|
+
<script>
|
|
40
|
+
window.OBSIDIAN_CONFIG = window.OBSIDIAN_CONFIG || {};
|
|
41
|
+
window.OBSIDIAN_CONFIG.wikiIndexUrl = {{ '/assets/data/wiki-index.json' | relative_url | jsonify }};
|
|
42
|
+
window.OBSIDIAN_CONFIG.attachmentsPath = {{ obsidian_attachments_path | relative_url | jsonify }};
|
|
43
|
+
window.OBSIDIAN_CONFIG.tagBase = {{ '/tags/' | relative_url | jsonify }};
|
|
44
|
+
</script>
|
|
45
|
+
<script defer src="{{ '/assets/js/obsidian-wiki-links.js' | relative_url }}"></script>
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
{%- assign _backlinks = "" | split: "" -%}
|
|
42
42
|
{%- for _doc in _candidates -%}
|
|
43
43
|
{%- if _doc.url == _self_url -%}{%- continue -%}{%- endif -%}
|
|
44
|
+
{%- comment -%} Hide draft/unpublished references unless this build includes drafts. {%- endcomment -%}
|
|
45
|
+
{%- unless site.show_drafts == true -%}
|
|
46
|
+
{%- if _doc.published == false or _doc.draft == true -%}{%- continue -%}{%- endif -%}
|
|
47
|
+
{%- endunless -%}
|
|
44
48
|
{%- assign _body = _doc.content | default: "" -%}
|
|
45
49
|
{%- assign _body_lower = _body | downcase -%}
|
|
46
50
|
{%- assign _matched = false -%}
|
data/_includes/core/footer.html
CHANGED
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
-->
|
|
32
32
|
|
|
33
33
|
<footer class="bd-footer border-top" role="contentinfo">
|
|
34
|
+
{% assign footer_page_urls = site.html_pages | map: "url" | join: "|" | prepend: "|" | append: "|" %}
|
|
34
35
|
<!-- Powered by Row -->
|
|
35
36
|
<div class="container-xl my-3">
|
|
36
37
|
<ul class="nav justify-content-end list-unstyled d-flex align-items-center flex-wrap" aria-label="Powered by technologies">
|
|
@@ -100,8 +101,8 @@
|
|
|
100
101
|
{% assign _parts = entry | split: "," %}
|
|
101
102
|
{% assign _label = _parts[0] %}
|
|
102
103
|
{% assign _url = _parts[1] %}
|
|
103
|
-
{% assign
|
|
104
|
-
{% if
|
|
104
|
+
{% assign _needle = "|" | append: _url | append: "|" %}
|
|
105
|
+
{% if footer_page_urls contains _needle %}
|
|
105
106
|
<li><a href="{{ _url | relative_url }}" class="text-light text-decoration-none">{{ _label }}</a></li>
|
|
106
107
|
{% endif %}
|
|
107
108
|
{% endfor %}
|
|
@@ -169,14 +170,14 @@
|
|
|
169
170
|
<div class="col-md-4 text-md-end">
|
|
170
171
|
<ul class="list-inline mb-0">
|
|
171
172
|
{% comment %} Only render policy links whose pages exist (or that are explicitly configured). {% endcomment %}
|
|
172
|
-
{% assign
|
|
173
|
-
{%
|
|
174
|
-
{% if
|
|
173
|
+
{% assign _privacy_needle = "|/privacy-policy/|" %}
|
|
174
|
+
{% assign _privacy_alt_needle = "|/privacy-policy|" %}
|
|
175
|
+
{% if site.privacy_policy_url or footer_page_urls contains _privacy_needle or footer_page_urls contains _privacy_alt_needle %}
|
|
175
176
|
<li class="list-inline-item"><a href="{{ site.privacy_policy_url | default: '/privacy-policy' | relative_url }}" class="text-light text-decoration-none">Privacy Policy</a></li>
|
|
176
177
|
{% endif %}
|
|
177
|
-
{% assign
|
|
178
|
-
{%
|
|
179
|
-
{% if
|
|
178
|
+
{% assign _terms_needle = "|/terms-of-service/|" %}
|
|
179
|
+
{% assign _terms_alt_needle = "|/terms-of-service|" %}
|
|
180
|
+
{% if site.terms_of_service_url or footer_page_urls contains _terms_needle or footer_page_urls contains _terms_alt_needle %}
|
|
180
181
|
<li class="list-inline-item"><a href="{{ site.terms_of_service_url | default: '/terms-of-service' | relative_url }}" class="text-light text-decoration-none">Terms of Service</a></li>
|
|
181
182
|
{% endif %}
|
|
182
183
|
<li class="list-inline-item">
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{%- comment -%}
|
|
2
2
|
===================================================================
|
|
3
|
-
LOCAL GRAPH
|
|
3
|
+
LOCAL GRAPH SIDEBAR — collapsible page-scoped graph
|
|
4
4
|
===================================================================
|
|
5
5
|
|
|
6
6
|
File: local-graph.html
|
|
7
7
|
Path: _includes/navigation/local-graph.html
|
|
8
|
-
Purpose: Renders a
|
|
9
|
-
immediate wiki-link neighbors in
|
|
10
|
-
style local graph view).
|
|
8
|
+
Purpose: Renders a collapsible, page-scoped graph of the current page and
|
|
9
|
+
its immediate wiki-link neighbors in a separate side panel.
|
|
11
10
|
|
|
12
11
|
Behavior:
|
|
13
12
|
- Reads /assets/data/wiki-index.json
|
|
14
13
|
- Finds the current page by window.location.pathname (with title/basename
|
|
15
14
|
fallback for permalink quirks)
|
|
16
15
|
- BFS depth=1 by default (current + direct neighbors, in & out)
|
|
17
|
-
-
|
|
18
|
-
|
|
16
|
+
- Renders the current page as a single-node graph when it has no neighbors
|
|
17
|
+
- Hides itself if the current page is not in the wiki-index or the index
|
|
18
|
+
can't be loaded
|
|
19
19
|
- Lazily loads cytoscape.js from CDN with SRI + crossorigin
|
|
20
20
|
|
|
21
21
|
Opt-out: set `local_graph: false` in page front matter.
|
|
@@ -25,20 +25,55 @@
|
|
|
25
25
|
{%- endcomment -%}
|
|
26
26
|
{%- if page.local_graph != false -%}
|
|
27
27
|
{%- assign lg_depth = page.local_graph_depth | default: 1 -%}
|
|
28
|
-
<div class="obsidian-local-graph-
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
data-depth="{{ lg_depth }}"
|
|
39
|
-
data-index-url="{{ '/assets/data/wiki-index.json' | relative_url }}"
|
|
40
|
-
role="img"
|
|
41
|
-
aria-label="Local graph of pages linked to this page"></div>
|
|
28
|
+
<div class="obsidian-local-graph-fab d-print-none" data-obsidian-local-graph-toggle>
|
|
29
|
+
<button class="btn btn-primary rounded-circle shadow-lg obsidian-local-graph-toggle"
|
|
30
|
+
type="button"
|
|
31
|
+
data-bs-toggle="offcanvas"
|
|
32
|
+
data-bs-target="#obsidianLocalGraphPanel"
|
|
33
|
+
aria-controls="obsidianLocalGraphPanel"
|
|
34
|
+
aria-label="Open local graph"
|
|
35
|
+
title="Open local graph">
|
|
36
|
+
<i class="bi bi-diagram-3 fs-5" aria-hidden="true"></i>
|
|
37
|
+
</button>
|
|
42
38
|
</div>
|
|
39
|
+
|
|
40
|
+
<aside class="offcanvas offcanvas-start obsidian-local-graph-panel"
|
|
41
|
+
tabindex="-1"
|
|
42
|
+
id="obsidianLocalGraphPanel"
|
|
43
|
+
aria-labelledby="obsidianLocalGraphLabel"
|
|
44
|
+
data-bs-scroll="true"
|
|
45
|
+
data-bs-backdrop="false"
|
|
46
|
+
data-obsidian-local-graph-panel>
|
|
47
|
+
<div class="offcanvas-header">
|
|
48
|
+
<h2 class="offcanvas-title h5 mb-0" id="obsidianLocalGraphLabel">
|
|
49
|
+
<i class="bi bi-diagram-3 me-2" aria-hidden="true"></i>Local graph
|
|
50
|
+
</h2>
|
|
51
|
+
<button type="button"
|
|
52
|
+
class="btn-close"
|
|
53
|
+
data-bs-dismiss="offcanvas"
|
|
54
|
+
data-bs-target="#obsidianLocalGraphPanel"
|
|
55
|
+
aria-label="Close local graph"></button>
|
|
56
|
+
</div>
|
|
57
|
+
<div class="offcanvas-body">
|
|
58
|
+
<div class="obsidian-local-graph-widget" aria-label="Local graph">
|
|
59
|
+
<div class="obsidian-local-graph-meta d-flex align-items-center justify-content-between gap-2 mb-3">
|
|
60
|
+
<span class="badge text-bg-secondary">Depth {{ lg_depth }}</span>
|
|
61
|
+
<a href="{{ '/docs/obsidian/graph/' | relative_url }}"
|
|
62
|
+
class="btn btn-outline-primary btn-sm"
|
|
63
|
+
title="Open the full site graph">
|
|
64
|
+
<i class="bi bi-arrows-fullscreen me-1" aria-hidden="true"></i>Full graph
|
|
65
|
+
</a>
|
|
66
|
+
</div>
|
|
67
|
+
<div id="obsidian-local-graph"
|
|
68
|
+
data-depth="{{ lg_depth }}"
|
|
69
|
+
data-index-url="{{ '/assets/data/wiki-index.json' | relative_url }}"
|
|
70
|
+
role="img"
|
|
71
|
+
aria-label="Local graph of pages linked to this page"></div>
|
|
72
|
+
<p class="obsidian-local-graph-status small text-secondary mt-2 mb-0"
|
|
73
|
+
data-obsidian-local-graph-status
|
|
74
|
+
role="status">Loading graph...</p>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</aside>
|
|
43
78
|
<script src="{{ '/assets/js/obsidian-local-graph.js' | relative_url }}" defer></script>
|
|
44
79
|
{%- endif -%}
|
|
@@ -48,12 +48,6 @@
|
|
|
48
48
|
<!-- Scrollable content area with dynamic navigation options -->
|
|
49
49
|
<div class="offcanvas-body overflow-auto">
|
|
50
50
|
|
|
51
|
-
<!-- ========================== -->
|
|
52
|
-
<!-- LOCAL GRAPH WIDGET -->
|
|
53
|
-
<!-- ========================== -->
|
|
54
|
-
<!-- Mini Obsidian-style local graph of the current page + neighbors -->
|
|
55
|
-
{% include navigation/local-graph.html %}
|
|
56
|
-
|
|
57
51
|
<!-- ========================== -->
|
|
58
52
|
<!-- AUTO MODE: Collection Docs -->
|
|
59
53
|
<!-- ========================== -->
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
/* Scoped to the graph page so we don't leak into other docs. */
|
|
3
|
+
#obsidian-graph {
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 82vh;
|
|
6
|
+
min-height: 620px;
|
|
7
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
8
|
+
border-radius: var(--bs-border-radius-lg, .5rem);
|
|
9
|
+
background: var(--bs-tertiary-bg, #f8f9fa);
|
|
10
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 4px 12px rgba(0, 0, 0, .04);
|
|
11
|
+
position: relative;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
}
|
|
14
|
+
#obsidian-graph-stats {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-wrap: wrap;
|
|
17
|
+
gap: .375rem;
|
|
18
|
+
}
|
|
19
|
+
#obsidian-graph-stats .badge {
|
|
20
|
+
font-size: .8125rem;
|
|
21
|
+
font-weight: 500;
|
|
22
|
+
padding: .35rem .6rem;
|
|
23
|
+
}
|
|
24
|
+
.obsidian-graph-toolbar {
|
|
25
|
+
display: flex;
|
|
26
|
+
flex-wrap: wrap;
|
|
27
|
+
gap: .5rem .75rem;
|
|
28
|
+
align-items: center;
|
|
29
|
+
margin: .75rem 0;
|
|
30
|
+
padding: .625rem .75rem;
|
|
31
|
+
background: var(--bs-tertiary-bg, #f8f9fa);
|
|
32
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
33
|
+
border-radius: var(--bs-border-radius, .375rem);
|
|
34
|
+
}
|
|
35
|
+
.obsidian-graph-toolbar .form-control {
|
|
36
|
+
max-width: 280px;
|
|
37
|
+
flex: 1 1 200px;
|
|
38
|
+
}
|
|
39
|
+
.obsidian-graph-toolbar .form-check {
|
|
40
|
+
margin-bottom: 0;
|
|
41
|
+
}
|
|
42
|
+
#obsidian-graph-status {
|
|
43
|
+
flex-basis: 100%;
|
|
44
|
+
font-size: .8125rem;
|
|
45
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
46
|
+
min-height: 1.25rem;
|
|
47
|
+
}
|
|
48
|
+
.obsidian-graph-legend {
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-wrap: wrap;
|
|
51
|
+
gap: .5rem;
|
|
52
|
+
margin-top: .75rem;
|
|
53
|
+
font-size: .8125rem;
|
|
54
|
+
}
|
|
55
|
+
.obsidian-graph-legend > span {
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: .375rem;
|
|
59
|
+
padding: .25rem .55rem;
|
|
60
|
+
background: var(--bs-body-bg, #fff);
|
|
61
|
+
border: 1px solid var(--bs-border-color, #dee2e6);
|
|
62
|
+
border-radius: 999px;
|
|
63
|
+
color: var(--bs-body-color, #212529);
|
|
64
|
+
}
|
|
65
|
+
.obsidian-graph-legend .swatch {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
width: .7rem;
|
|
68
|
+
height: .7rem;
|
|
69
|
+
border-radius: 50%;
|
|
70
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, .15);
|
|
71
|
+
}
|
|
72
|
+
.obsidian-graph-legend .swatch-broken {
|
|
73
|
+
border: 1.5px dashed #dc3545;
|
|
74
|
+
background: transparent !important;
|
|
75
|
+
box-shadow: none;
|
|
76
|
+
}
|
|
77
|
+
.obsidian-graph-tips {
|
|
78
|
+
margin-top: .75rem;
|
|
79
|
+
padding: .625rem .75rem;
|
|
80
|
+
font-size: .8125rem;
|
|
81
|
+
color: var(--bs-secondary-color, #6c757d);
|
|
82
|
+
background: var(--bs-tertiary-bg, #f8f9fa);
|
|
83
|
+
border-left: 3px solid var(--bs-primary, #0d6efd);
|
|
84
|
+
border-radius: .25rem;
|
|
85
|
+
}
|
|
86
|
+
.obsidian-graph-tips strong {
|
|
87
|
+
color: var(--bs-body-color, #212529);
|
|
88
|
+
}
|
|
89
|
+
</style>
|
|
90
|
+
|
|
91
|
+
# Obsidian Graph View
|
|
92
|
+
|
|
93
|
+
A live, force-directed map of every page on this site and every
|
|
94
|
+
`[[wiki-link]]` between them. This is the rendered-site equivalent of
|
|
95
|
+
Obsidian's local graph view — built from the same
|
|
96
|
+
[`assets/data/wiki-index.json`]({{ "/assets/data/wiki-index.json" | relative_url }})
|
|
97
|
+
that powers the [client-side resolver]({{ "/docs/obsidian/syntax-reference/" | relative_url }})
|
|
98
|
+
and [backlinks panel]({{ "/docs/obsidian/syntax-reference/#backlinks-panel" | relative_url }}).
|
|
99
|
+
|
|
100
|
+
<div id="obsidian-graph-stats" class="mb-2" aria-live="polite"></div>
|
|
101
|
+
|
|
102
|
+
<div class="obsidian-graph-toolbar">
|
|
103
|
+
<input type="search"
|
|
104
|
+
class="form-control form-control-sm"
|
|
105
|
+
id="obsidian-graph-search"
|
|
106
|
+
placeholder="Filter nodes by title…"
|
|
107
|
+
aria-label="Filter graph nodes by title" />
|
|
108
|
+
<button type="button"
|
|
109
|
+
class="btn btn-outline-secondary btn-sm"
|
|
110
|
+
id="obsidian-graph-fit">
|
|
111
|
+
<i class="bi bi-arrows-fullscreen" aria-hidden="true"></i>
|
|
112
|
+
Reset view
|
|
113
|
+
</button>
|
|
114
|
+
<div class="form-check form-switch">
|
|
115
|
+
<input class="form-check-input"
|
|
116
|
+
type="checkbox"
|
|
117
|
+
role="switch"
|
|
118
|
+
id="obsidian-graph-orphans" />
|
|
119
|
+
<label class="form-check-label" for="obsidian-graph-orphans">
|
|
120
|
+
Show orphans
|
|
121
|
+
</label>
|
|
122
|
+
</div>
|
|
123
|
+
<span id="obsidian-graph-status" role="status"></span>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<div id="obsidian-graph" role="img" aria-label="Site knowledge graph"></div>
|
|
127
|
+
|
|
128
|
+
<div class="obsidian-graph-legend" aria-label="Graph legend">
|
|
129
|
+
<span><span class="swatch" style="background:#0d6efd"></span>Posts</span>
|
|
130
|
+
<span><span class="swatch" style="background:#198754"></span>Docs</span>
|
|
131
|
+
<span><span class="swatch" style="background:#6f42c1"></span>Notes</span>
|
|
132
|
+
<span><span class="swatch" style="background:#d63384"></span>Notebooks</span>
|
|
133
|
+
<span><span class="swatch" style="background:#fd7e14"></span>Quickstart</span>
|
|
134
|
+
<span><span class="swatch" style="background:#6c757d"></span>Pages</span>
|
|
135
|
+
<span><span class="swatch swatch-broken"></span>Broken links</span>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<div class="obsidian-graph-tips">
|
|
139
|
+
<strong>Tips:</strong> click a node to open the page · ⌘/Ctrl-click to
|
|
140
|
+
open in a new tab · drag to reposition · scroll to zoom · hover to
|
|
141
|
+
highlight a node's neighborhood · type in the search box to filter.
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
## How it's built
|
|
145
|
+
|
|
146
|
+
| Piece | File |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| Build-time index (nodes + outgoing edges) | [`assets/data/wiki-index.json`]({{ "/assets/data/wiki-index.json" | relative_url }}) (Liquid template at [`assets/data/wiki-index.json`](https://github.com/bamr87/zer0-mistakes/blob/main/assets/data/wiki-index.json)) |
|
|
149
|
+
| Renderer | `assets/js/obsidian-graph.js` |
|
|
150
|
+
| Layout engine | [cytoscape.js](https://js.cytoscape.org/) (loaded from CDN, only on this page) |
|
|
151
|
+
|
|
152
|
+
Outgoing edges come from the same `[[…]]` syntax the resolver handles —
|
|
153
|
+
unresolved targets show up as dashed red nodes so you can find dangling
|
|
154
|
+
links at a glance. The graph is regenerated every Jekyll build; nothing
|
|
155
|
+
runs client-side except cytoscape's force layout.
|
|
156
|
+
|
|
157
|
+
<!-- Cytoscape.js (only loaded on this page). -->
|
|
158
|
+
<script src="https://cdn.jsdelivr.net/npm/cytoscape@3.30.0/dist/cytoscape.min.js"
|
|
159
|
+
integrity="sha384-kpMsYllYzyaWU69Piok08rPNktpnjqAoDMdB00fjqUkEk3lkuUbSuwJ+oXrjvN6B"
|
|
160
|
+
crossorigin="anonymous"
|
|
161
|
+
defer></script>
|
|
162
|
+
<script src="{{ '/assets/js/obsidian-graph.js' | relative_url }}" defer></script>
|
|
163
|
+
|
|
164
|
+
## See also
|
|
165
|
+
|
|
166
|
+
- [[Obsidian Vault Integration]]
|
|
167
|
+
- [[Obsidian Syntax Reference]]
|
|
168
|
+
- [[Obsidian Authoring Workflow]]
|
|
169
|
+
- [[Getting Started with the Obsidian Vault]]
|
|
170
|
+
- [[Obsidian Integration Troubleshooting]]
|