jekyll-theme-zer0 1.27.0 → 1.28.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 +386 -4
- data/_data/consumers.yml +147 -0
- data/_data/features.yml +77 -5
- data/_data/i18n/fr.yml +98 -0
- data/_data/i18n/manifest.yml +1502 -0
- data/_data/navigation/docs.yml +2 -0
- data/_data/navigation/main.yml +6 -0
- data/_data/series.yml +19 -0
- data/_data/theme-manifest.yml +348 -266
- data/_includes/README.md +21 -2
- data/_includes/analytics/google-tag-manager-body.html +11 -2
- data/_includes/analytics/google-tag-manager-head.html +16 -6
- data/_includes/analytics/posthog.html +33 -4
- data/_includes/components/abc-letter.html +43 -0
- data/_includes/components/book-card.html +42 -0
- data/_includes/components/book-nav.html +80 -0
- data/_includes/components/book-plate.html +31 -0
- data/_includes/components/book-toc.html +47 -0
- data/_includes/components/bookshelf.html +68 -0
- data/_includes/components/card-grid.html +60 -0
- data/_includes/components/data-card.html +95 -0
- data/_includes/components/halfmoon.html +5 -1
- data/_includes/components/page-feedback.html +65 -2
- data/_includes/components/theme-controls-bar.html +10 -2
- data/_includes/components/theme-customizer.html +8 -2
- data/_includes/content/seo.html +9 -3
- data/_includes/core/color-mode-init.html +13 -4
- data/_includes/core/favicon.html +46 -0
- data/_includes/core/head.html +9 -0
- data/_includes/custom/body-end.html +18 -0
- data/_includes/custom/body-start.html +17 -0
- data/_includes/custom/footer.html +18 -0
- data/_includes/custom/head.html +18 -0
- data/_includes/navigation/local-graph.html +28 -2
- data/_includes/navigation/nav-tree.html +3 -3
- data/_includes/navigation/sidebar-config.html +21 -0
- data/_includes/navigation/sidebar-nav.html +4 -0
- data/_includes/navigation/sidebar-pagetree.html +150 -0
- data/_includes/navigation/unified-drawer.html +8 -2
- data/_includes/obsidian/full-graph.html +165 -136
- data/_layouts/404.html +260 -0
- data/_layouts/README.md +2 -0
- data/_layouts/book-abc.html +106 -0
- data/_layouts/book-story.html +91 -0
- data/_layouts/book.html +113 -0
- data/_layouts/collection.html +17 -5
- data/_layouts/home.html +5 -2
- data/_layouts/landing.html +9 -0
- data/_layouts/news.html +155 -31
- data/_layouts/root.html +16 -2
- data/_layouts/section.html +57 -15
- data/_sass/components/_book.scss +423 -0
- data/_sass/core/_navbar.scss +13 -0
- data/_sass/core/_obsidian.scss +286 -6
- data/_sass/theme/_backgrounds.scss +21 -8
- data/assets/css/main.scss +1 -0
- data/assets/js/auto-hide-nav.js +5 -1
- data/assets/js/halfmoon.js +26 -0
- data/assets/js/obsidian-graph.js +702 -264
- data/assets/js/obsidian-local-graph.js +161 -54
- data/assets/js/search-modal.js +4 -1
- data/scripts/bin/manifest +31 -4
- data/scripts/bin/validate +5 -1
- data/scripts/install/README.md +47 -6
- data/scripts/install/ai/client.sh +302 -93
- data/scripts/install/ai/prompts/spec.schema.json +1 -1
- data/scripts/install/ai/wizard.sh +10 -5
- data/scripts/install/apply.sh +7 -3
- data/scripts/install/cli.sh +54 -4
- data/scripts/install/config.sh +167 -0
- data/scripts/install/doctor.sh +38 -0
- data/scripts/install/plan.sh +10 -0
- data/scripts/install/spec.sh +15 -7
- data/scripts/install/template.sh +4 -0
- data/scripts/propagate.rb +277 -0
- data/scripts/translate.rb +90 -0
- metadata +27 -2
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
page (settings offcanvas + theme-controls-bar).
|
|
10
10
|
params: class (string, optional, default "") — extra btn-group classes,
|
|
11
11
|
e.g. "w-100" to fill the parent.
|
|
12
|
+
config: site.color_mode_lock: true removes the control entirely — the
|
|
13
|
+
site pins one mode and visitor switching is disabled
|
|
14
|
+
(halfmoon.js + core/color-mode-init.html enforce the same).
|
|
12
15
|
-->
|
|
13
|
-
|
|
16
|
+
{% unless site.color_mode_lock %}
|
|
14
17
|
<div class="btn-group bd-theme-switch {{ include.class | default: '' }}" role="group" aria-label="Color mode">
|
|
15
18
|
<button type="button" class="btn btn-outline-secondary btn-sm d-flex align-items-center justify-content-center gap-1" data-bs-theme-value="light" aria-pressed="false">
|
|
16
19
|
<svg class="bi flex-shrink-0" width="1em" height="1em" fill="currentColor" aria-hidden="true"><use href="#sun-fill"></use></svg>
|
|
@@ -25,3 +28,4 @@
|
|
|
25
28
|
<span>Auto</span>
|
|
26
29
|
</button>
|
|
27
30
|
</div>
|
|
31
|
+
{% endunless %}
|
|
@@ -103,6 +103,14 @@
|
|
|
103
103
|
<!-- Step 1 — request type -->
|
|
104
104
|
<fieldset class="pf-field pf-types">
|
|
105
105
|
<legend class="pf-legend">What kind of feedback?</legend>
|
|
106
|
+
{%- comment -%}
|
|
107
|
+
_data/feedback_types.yml is optional for consumers (remote_theme
|
|
108
|
+
cannot ship _data). Without it the widget falls back to a minimal
|
|
109
|
+
generic taxonomy (see pf_fallback_types below) instead of rendering
|
|
110
|
+
an empty selector. The fallback entries carry no GitHub labels and
|
|
111
|
+
no agent directive — labels must exist in the target repo or GitHub
|
|
112
|
+
silently drops them from prefilled issue URLs.
|
|
113
|
+
{%- endcomment -%}
|
|
106
114
|
{%- assign pf_group = "" -%}
|
|
107
115
|
{%- for t in site.data.feedback_types -%}
|
|
108
116
|
{%- if t.group != pf_group -%}
|
|
@@ -124,6 +132,54 @@
|
|
|
124
132
|
</span>
|
|
125
133
|
</button>
|
|
126
134
|
{%- if forloop.last -%}</div>{%- endif -%}
|
|
135
|
+
{%- else -%}
|
|
136
|
+
{%- comment -%}
|
|
137
|
+
_data/feedback_types.yml is optional for consumers (remote_theme
|
|
138
|
+
cannot ship _data). Without it, render this minimal generic
|
|
139
|
+
taxonomy instead of an empty selector. Ids/markup must stay in
|
|
140
|
+
sync with the fallback JSON in the #pageFeedbackTypes script
|
|
141
|
+
below. Fallback entries carry no GitHub labels (labels must exist
|
|
142
|
+
in the target repo or GitHub silently drops them) and no agent
|
|
143
|
+
directive.
|
|
144
|
+
{%- endcomment -%}
|
|
145
|
+
<p class="pf-types-group">This page</p>
|
|
146
|
+
<div class="pf-types-grid" role="radiogroup" aria-label="This page">
|
|
147
|
+
<button type="button" class="pf-type" role="radio" aria-checked="false"
|
|
148
|
+
data-pf-type-id="fix-page" tabindex="0">
|
|
149
|
+
<i class="bi bi-bug pf-type-icon" aria-hidden="true"></i>
|
|
150
|
+
<span class="pf-type-text">
|
|
151
|
+
<span class="pf-type-label">Report a problem</span>
|
|
152
|
+
<span class="pf-type-desc">A typo, broken link, wrong information, or something rendering badly</span>
|
|
153
|
+
</span>
|
|
154
|
+
</button>
|
|
155
|
+
<button type="button" class="pf-type" role="radio" aria-checked="false"
|
|
156
|
+
data-pf-type-id="improve-page" tabindex="-1">
|
|
157
|
+
<i class="bi bi-stars pf-type-icon" aria-hidden="true"></i>
|
|
158
|
+
<span class="pf-type-text">
|
|
159
|
+
<span class="pf-type-label">Improve this page</span>
|
|
160
|
+
<span class="pf-type-desc">Polish the copy, structure, or presentation</span>
|
|
161
|
+
</span>
|
|
162
|
+
</button>
|
|
163
|
+
</div>
|
|
164
|
+
<p class="pf-types-group">The site</p>
|
|
165
|
+
<div class="pf-types-grid" role="radiogroup" aria-label="The site">
|
|
166
|
+
<button type="button" class="pf-type" role="radio" aria-checked="false"
|
|
167
|
+
data-pf-type-id="feature" tabindex="-1">
|
|
168
|
+
<i class="bi bi-lightbulb pf-type-icon" aria-hidden="true"></i>
|
|
169
|
+
<span class="pf-type-text">
|
|
170
|
+
<span class="pf-type-label">Suggest a feature</span>
|
|
171
|
+
<span class="pf-type-desc">An idea that would make the site more useful</span>
|
|
172
|
+
</span>
|
|
173
|
+
</button>
|
|
174
|
+
<button type="button" class="pf-type" role="radio" aria-checked="false"
|
|
175
|
+
data-pf-type-id="question" tabindex="-1">
|
|
176
|
+
<i class="bi bi-question-circle pf-type-icon" aria-hidden="true"></i>
|
|
177
|
+
<span class="pf-type-text">
|
|
178
|
+
<span class="pf-type-label">Ask a question</span>
|
|
179
|
+
<span class="pf-type-desc">Something unclear that is not exactly a bug</span>
|
|
180
|
+
</span>
|
|
181
|
+
</button>
|
|
182
|
+
</div>
|
|
127
183
|
{%- endfor -%}
|
|
128
184
|
</fieldset>
|
|
129
185
|
|
|
@@ -219,9 +275,16 @@
|
|
|
219
275
|
}
|
|
220
276
|
</script>
|
|
221
277
|
|
|
222
|
-
<!-- Request-type taxonomy (from _data/feedback_types.yml
|
|
278
|
+
<!-- Request-type taxonomy (from _data/feedback_types.yml; generic fallback
|
|
279
|
+
when the site ships no data file — keep in sync with the fallback markup
|
|
280
|
+
in the pf-types fieldset above) -->
|
|
223
281
|
<script id="pageFeedbackTypes" type="application/json">
|
|
224
|
-
{{ site.data.feedback_types | jsonify }}
|
|
282
|
+
{% if site.data.feedback_types %}{{ site.data.feedback_types | jsonify }}{% else %}[
|
|
283
|
+
{"id":"fix-page","label":"Report a problem","icon":"bi-bug","group":"This page","scope":"page","description":"A typo, broken link, wrong information, or something rendering badly","labels":[],"agent":false,"placeholder":"What is wrong, where on the page, and what did you expect instead?"},
|
|
284
|
+
{"id":"improve-page","label":"Improve this page","icon":"bi-stars","group":"This page","scope":"page","description":"Polish the copy, structure, or presentation","labels":[],"agent":false,"placeholder":"What would make this page clearer, tighter, or more useful?"},
|
|
285
|
+
{"id":"feature","label":"Suggest a feature","icon":"bi-lightbulb","group":"The site","scope":"site","description":"An idea that would make the site more useful","labels":[],"agent":false,"placeholder":"Describe the feature and the problem it would solve."},
|
|
286
|
+
{"id":"question","label":"Ask a question","icon":"bi-question-circle","group":"The site","scope":"site","description":"Something unclear that is not exactly a bug","labels":[],"agent":false,"placeholder":"What would you like to know?"}
|
|
287
|
+
]{% endif %}
|
|
225
288
|
</script>
|
|
226
289
|
|
|
227
290
|
<!-- Live page context (build-time front matter; runtime detail added by JS) -->
|
|
@@ -13,16 +13,24 @@
|
|
|
13
13
|
Used by theme settings and theme preview pages.
|
|
14
14
|
===================================================================
|
|
15
15
|
{%- endcomment -%}
|
|
16
|
-
{
|
|
17
|
-
|
|
16
|
+
{%- comment -%}
|
|
17
|
+
_data/theme_skins.yml is optional for consumers (remote_theme cannot ship
|
|
18
|
+
_data), so fall back to the compiled skin registry. Keep this list in sync
|
|
19
|
+
with the [data-theme-skin] blocks in _sass/theme/_skins.scss.
|
|
20
|
+
{%- endcomment -%}
|
|
21
|
+
{% assign _skin_fallback = "air|aqua|dirt|neon|mint|plum|sunrise" | split: "|" %}
|
|
22
|
+
{% assign active_skin = site.theme_skin | default: site.data.theme_skins.default | default: "air" %}
|
|
23
|
+
{% assign skin_order = site.data.theme_skins.order | default: _skin_fallback %}
|
|
18
24
|
|
|
19
25
|
<div class="theme-controls-bar d-flex flex-wrap align-items-center gap-3 mb-4 p-3 bg-body-tertiary rounded-3 border">
|
|
26
|
+
{% unless site.color_mode_lock %}
|
|
20
27
|
<div class="d-flex align-items-center gap-2">
|
|
21
28
|
<i class="bi bi-moon-stars" aria-hidden="true"></i>
|
|
22
29
|
<span class="fw-semibold small">Mode:</span>
|
|
23
30
|
{% include components/halfmoon.html %}
|
|
24
31
|
</div>
|
|
25
32
|
<div class="vr d-none d-sm-block" aria-hidden="true"></div>
|
|
33
|
+
{% endunless %}
|
|
26
34
|
<div class="d-flex align-items-center gap-2 flex-grow-1">
|
|
27
35
|
<i class="bi bi-palette2" aria-hidden="true"></i>
|
|
28
36
|
<span class="fw-semibold small">Skin:</span>
|
|
@@ -14,8 +14,14 @@
|
|
|
14
14
|
===================================================================
|
|
15
15
|
-->
|
|
16
16
|
|
|
17
|
-
{
|
|
18
|
-
|
|
17
|
+
{%- comment -%}
|
|
18
|
+
_data/theme_skins.yml is optional for consumers (remote_theme cannot ship
|
|
19
|
+
_data), so fall back to the compiled skin registry. Keep this list in sync
|
|
20
|
+
with the [data-theme-skin] blocks in _sass/theme/_skins.scss.
|
|
21
|
+
{%- endcomment -%}
|
|
22
|
+
{% assign _skin_fallback = "air|aqua|dirt|neon|mint|plum|sunrise" | split: "|" %}
|
|
23
|
+
{% assign current_skin = site.theme_skin | default: site.data.theme_skins.default | default: "air" %}
|
|
24
|
+
{% assign skins = site.data.theme_skins.order | default: _skin_fallback %}
|
|
19
25
|
|
|
20
26
|
<p class="text-body-secondary mb-3">
|
|
21
27
|
Current skin: <strong>{{ current_skin }}</strong>. Click a card to preview (page-level only — does not persist).
|
data/_includes/content/seo.html
CHANGED
|
@@ -37,17 +37,23 @@
|
|
|
37
37
|
{%- assign assets_prefix = site.preview_images.assets_prefix | default: '/assets' -%}
|
|
38
38
|
{%- assign auto_prefix = site.preview_images.auto_prefix | default: true -%}
|
|
39
39
|
|
|
40
|
+
{%- comment -%}
|
|
41
|
+
Guard with truthiness AND blank: in Liquid 4 `nil != blank` is TRUE, so a
|
|
42
|
+
bare `!= blank` check on an unset variable takes the branch and assigns a
|
|
43
|
+
nil seo_image — og:image was silently dropped on every page without a
|
|
44
|
+
page.header image, defeating the site.og_image fallback entirely.
|
|
45
|
+
{%- endcomment -%}
|
|
40
46
|
{%- if page_teaser_image contains '://' -%}
|
|
41
47
|
{%- comment -%} External URL - use as-is {%- endcomment -%}
|
|
42
|
-
{%- elsif auto_prefix and page_teaser_image != blank -%}
|
|
48
|
+
{%- elsif auto_prefix and page_teaser_image and page_teaser_image != blank -%}
|
|
43
49
|
{%- unless page_teaser_image contains assets_prefix -%}
|
|
44
50
|
{%- assign page_teaser_image = assets_prefix | append: page_teaser_image -%}
|
|
45
51
|
{%- endunless -%}
|
|
46
52
|
{%- endif -%}
|
|
47
53
|
|
|
48
|
-
{%- if page_large_image != blank -%}
|
|
54
|
+
{%- if page_large_image and page_large_image != blank -%}
|
|
49
55
|
{%- assign seo_image = page_large_image | absolute_url | escape -%}
|
|
50
|
-
{%- elsif page_teaser_image != blank -%}
|
|
56
|
+
{%- elsif page_teaser_image and page_teaser_image != blank -%}
|
|
51
57
|
{%- assign seo_image = page_teaser_image | absolute_url | escape -%}
|
|
52
58
|
{%- endif -%}
|
|
53
59
|
|
|
@@ -13,9 +13,12 @@
|
|
|
13
13
|
when Bootstrap's [data-bs-theme] selectors are first evaluated.
|
|
14
14
|
|
|
15
15
|
Priority order (highest → lowest):
|
|
16
|
-
1.
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
1. site.color_mode_lock — when true, config wins unconditionally:
|
|
17
|
+
visitor preference and OS scheme are ignored
|
|
18
|
+
(data-color-mode-lock attribute, set by root.html)
|
|
19
|
+
2. localStorage["theme"] — user's explicit override via Appearance panel
|
|
20
|
+
3. data-color-mode-default — site.color_mode_default config value
|
|
21
|
+
4. "auto" fallback — resolves via prefers-color-scheme
|
|
19
22
|
{%- endcomment -%}
|
|
20
23
|
<script>
|
|
21
24
|
(function () {
|
|
@@ -23,8 +26,14 @@
|
|
|
23
26
|
try {
|
|
24
27
|
var root = document.documentElement;
|
|
25
28
|
var configDefault = root.getAttribute('data-color-mode-default') || 'auto';
|
|
26
|
-
var
|
|
29
|
+
var locked = root.getAttribute('data-color-mode-lock') === 'true';
|
|
30
|
+
var stored = locked ? null : window.localStorage.getItem('theme');
|
|
27
31
|
var mode = stored || configDefault;
|
|
32
|
+
if (mode === 'auto' && locked) {
|
|
33
|
+
{%- comment -%} A locked "auto" is contradictory; treat it as dark so
|
|
34
|
+
the brand-pinned mode never flips with the OS. {%- endcomment %}
|
|
35
|
+
mode = 'dark';
|
|
36
|
+
}
|
|
28
37
|
if (mode === 'auto') {
|
|
29
38
|
root.setAttribute('data-bs-theme',
|
|
30
39
|
window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% comment %} Feature: ZER0-079 {% endcomment %}
|
|
2
|
+
{%- comment -%}
|
|
3
|
+
Component: favicon
|
|
4
|
+
Path: _includes/core/favicon.html
|
|
5
|
+
Purpose: Emit the browser-identity tags (favicon, SVG icon, Apple touch
|
|
6
|
+
icon, web manifest, theme-color) for every page. Before this
|
|
7
|
+
include existed, sites relied on the browser's implicit
|
|
8
|
+
/favicon.ico probe — which silently 404s on sites without the
|
|
9
|
+
file and never works for baseurl (project-page) deployments.
|
|
10
|
+
Params: none — reads the optional `favicon:` block in _config.yml:
|
|
11
|
+
|
|
12
|
+
favicon:
|
|
13
|
+
ico : /favicon.ico # legacy .ico (default)
|
|
14
|
+
svg : /assets/images/favicon.svg # scalable icon (optional)
|
|
15
|
+
png : /assets/images/favicon-32.png # PNG icon (optional)
|
|
16
|
+
png_size : 32x32 # sizes attr for png (optional)
|
|
17
|
+
apple_touch : /assets/images/apple-touch.png # iOS home-screen icon (optional)
|
|
18
|
+
manifest : /site.webmanifest # PWA manifest (optional)
|
|
19
|
+
theme_color : "#0d1117" # browser chrome color (optional)
|
|
20
|
+
|
|
21
|
+
With NO config at all this still emits the explicit
|
|
22
|
+
/favicon.ico link (every consumer site carries one at root),
|
|
23
|
+
and theme_color falls back to site.theme_color.main so the
|
|
24
|
+
mobile address bar matches the site's design tokens.
|
|
25
|
+
Notes: Page-invariant — safe to render via include_cached. All paths
|
|
26
|
+
run through relative_url so baseurl deployments resolve.
|
|
27
|
+
{%- endcomment -%}
|
|
28
|
+
{%- assign _fav = site.favicon -%}
|
|
29
|
+
{%- assign _fav_ico = _fav.ico | default: '/favicon.ico' -%}
|
|
30
|
+
<link rel="icon" href="{{ _fav_ico | relative_url }}" sizes="32x32">
|
|
31
|
+
{%- if _fav.svg %}
|
|
32
|
+
<link rel="icon" type="image/svg+xml" href="{{ _fav.svg | relative_url }}">
|
|
33
|
+
{%- endif %}
|
|
34
|
+
{%- if _fav.png %}
|
|
35
|
+
<link rel="icon" type="image/png" href="{{ _fav.png | relative_url }}"{% if _fav.png_size %} sizes="{{ _fav.png_size }}"{% endif %}>
|
|
36
|
+
{%- endif %}
|
|
37
|
+
{%- if _fav.apple_touch %}
|
|
38
|
+
<link rel="apple-touch-icon" href="{{ _fav.apple_touch | relative_url }}">
|
|
39
|
+
{%- endif %}
|
|
40
|
+
{%- if _fav.manifest %}
|
|
41
|
+
<link rel="manifest" href="{{ _fav.manifest | relative_url }}">
|
|
42
|
+
{%- endif %}
|
|
43
|
+
{%- assign _fav_theme_color = _fav.theme_color | default: site.theme_color.main -%}
|
|
44
|
+
{%- if _fav_theme_color %}
|
|
45
|
+
<meta name="theme-color" content="{{ _fav_theme_color }}">
|
|
46
|
+
{%- endif %}
|
data/_includes/core/head.html
CHANGED
|
@@ -87,6 +87,10 @@ window.MathJax = {
|
|
|
87
87
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
88
88
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
89
89
|
|
|
90
|
+
<!-- Favicon + browser identity (config-driven via `favicon:`; explicit
|
|
91
|
+
/favicon.ico fallback so baseurl deployments resolve) — page-invariant, cached. -->
|
|
92
|
+
{% include_cached core/favicon.html %}
|
|
93
|
+
|
|
90
94
|
<!-- ================================ -->
|
|
91
95
|
<!-- SEO SUPPLEMENT -->
|
|
92
96
|
<!-- ================================ -->
|
|
@@ -186,6 +190,11 @@ window.MathJax = {
|
|
|
186
190
|
<link rel="stylesheet" href="{{ '/assets/css/stats.css' | relative_url }}">
|
|
187
191
|
{% endif %}
|
|
188
192
|
|
|
193
|
+
<!-- Consumer hook: end of <head>. Inject JSON-LD, font preloads, verification
|
|
194
|
+
tags, or extra meta by shadowing _includes/custom/head.html in your site —
|
|
195
|
+
no fork of this file needed. The theme ships the stub empty. -->
|
|
196
|
+
{% include custom/head.html %}
|
|
197
|
+
|
|
189
198
|
<!-- ========================== -->
|
|
190
199
|
<!-- EXPERIMENTAL FRAMEWORKS -->
|
|
191
200
|
<!-- ========================== -->
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
===================================================================
|
|
3
|
+
CUSTOM HOOK — body-end
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
Path: _includes/custom/body-end.html
|
|
7
|
+
Purpose: Consumer extension point rendered as the LAST thing before
|
|
8
|
+
</body> — after the theme's JS bundle and analytics. Use it
|
|
9
|
+
for site-specific scripts, third-party widgets, or anything
|
|
10
|
+
that must load after the theme's JavaScript.
|
|
11
|
+
|
|
12
|
+
The theme ships this file EMPTY. Create _includes/custom/body-end.html
|
|
13
|
+
in YOUR site to shadow this stub. No theme layout needs forking.
|
|
14
|
+
|
|
15
|
+
Companion hooks: custom/head.html, custom/body-start.html,
|
|
16
|
+
custom/footer.html. See _includes/README.md § Custom hooks.
|
|
17
|
+
===================================================================
|
|
18
|
+
{%- endcomment -%}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
===================================================================
|
|
3
|
+
CUSTOM HOOK — body-start
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
Path: _includes/custom/body-start.html
|
|
7
|
+
Purpose: Consumer extension point rendered immediately AFTER the
|
|
8
|
+
opening <body> tag — the required position for snippets like
|
|
9
|
+
Google Tag Manager's <noscript> iframe.
|
|
10
|
+
|
|
11
|
+
The theme ships this file EMPTY. Create _includes/custom/body-start.html
|
|
12
|
+
in YOUR site to shadow this stub. No theme layout needs forking.
|
|
13
|
+
|
|
14
|
+
Companion hooks: custom/head.html, custom/footer.html,
|
|
15
|
+
custom/body-end.html. See _includes/README.md § Custom hooks.
|
|
16
|
+
===================================================================
|
|
17
|
+
{%- endcomment -%}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
===================================================================
|
|
3
|
+
CUSTOM HOOK — footer
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
Path: _includes/custom/footer.html
|
|
7
|
+
Purpose: Consumer extension point rendered directly AFTER the theme
|
|
8
|
+
footer (and its FAB tail), before the cookie-consent banner.
|
|
9
|
+
Use it for an extra footer strip, badges, or legal links the
|
|
10
|
+
theme footer doesn't model.
|
|
11
|
+
|
|
12
|
+
The theme ships this file EMPTY. Create _includes/custom/footer.html
|
|
13
|
+
in YOUR site to shadow this stub. No theme layout needs forking.
|
|
14
|
+
|
|
15
|
+
Companion hooks: custom/head.html, custom/body-start.html,
|
|
16
|
+
custom/body-end.html. See _includes/README.md § Custom hooks.
|
|
17
|
+
===================================================================
|
|
18
|
+
{%- endcomment -%}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
===================================================================
|
|
3
|
+
CUSTOM HOOK — head
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
Path: _includes/custom/head.html
|
|
7
|
+
Purpose: Consumer extension point rendered at the END of the theme's
|
|
8
|
+
<head> (after main.css, tokens-inline, and user-overrides).
|
|
9
|
+
|
|
10
|
+
The theme ships this file EMPTY. To inject site-specific markup —
|
|
11
|
+
structured data (JSON-LD), font preloads, verification tags, extra
|
|
12
|
+
meta — create _includes/custom/head.html in YOUR site and it will
|
|
13
|
+
shadow this stub. No theme layout or core include needs forking.
|
|
14
|
+
|
|
15
|
+
Companion hooks: custom/body-start.html, custom/footer.html,
|
|
16
|
+
custom/body-end.html. See _includes/README.md § Custom hooks.
|
|
17
|
+
===================================================================
|
|
18
|
+
{%- endcomment -%}
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
Opt-out: set `local_graph: false` in page front matter.
|
|
24
24
|
|
|
25
25
|
Configurable depth: `local_graph_depth: 2` in page front matter (default 1).
|
|
26
|
+
The panel's depth selector (1–3) and incoming/outgoing switches override it
|
|
27
|
+
per-browser via localStorage (zer0.obsidianLocalGraph.v1).
|
|
26
28
|
===================================================================
|
|
27
29
|
{%- endcomment -%}
|
|
28
30
|
{%- comment -%} Shared visibility resolver — sets sidebar_enabled {%- endcomment -%}
|
|
@@ -63,8 +65,18 @@
|
|
|
63
65
|
{%- if _graph_page -%}{%- break -%}{%- endif -%}
|
|
64
66
|
{%- endfor -%}
|
|
65
67
|
{%- endunless -%}
|
|
66
|
-
<div class="obsidian-local-graph-meta d-flex align-items-center justify-content-between gap-2 mb-
|
|
67
|
-
<
|
|
68
|
+
<div class="obsidian-local-graph-meta d-flex flex-wrap align-items-center justify-content-between gap-2 mb-2">
|
|
69
|
+
<div class="d-flex align-items-center gap-2">
|
|
70
|
+
<span class="small text-secondary">Depth</span>
|
|
71
|
+
<div class="btn-group btn-group-sm" role="group" aria-label="Graph depth">
|
|
72
|
+
{%- for d in (1..3) -%}
|
|
73
|
+
<input type="radio" class="btn-check" name="obsidianLgDepth"
|
|
74
|
+
id="obsidian-lg-depth-{{ d }}" autocomplete="off"
|
|
75
|
+
{% if d == lg_depth %}checked{% endif %} />
|
|
76
|
+
<label class="btn btn-outline-secondary" for="obsidian-lg-depth-{{ d }}">{{ d }}</label>
|
|
77
|
+
{%- endfor -%}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
68
80
|
{%- if _graph_page -%}
|
|
69
81
|
<a href="{{ _graph_url | relative_url }}"
|
|
70
82
|
class="btn btn-outline-primary btn-sm"
|
|
@@ -73,6 +85,20 @@
|
|
|
73
85
|
</a>
|
|
74
86
|
{%- endif -%}
|
|
75
87
|
</div>
|
|
88
|
+
<div class="d-flex flex-wrap column-gap-3 mb-2"
|
|
89
|
+
role="group"
|
|
90
|
+
aria-label="Link directions shown in the local graph">
|
|
91
|
+
<div class="form-check form-switch mb-0">
|
|
92
|
+
<input class="form-check-input" type="checkbox" role="switch"
|
|
93
|
+
id="obsidian-lg-outgoing" checked />
|
|
94
|
+
<label class="form-check-label small" for="obsidian-lg-outgoing">Outgoing</label>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="form-check form-switch mb-0">
|
|
97
|
+
<input class="form-check-input" type="checkbox" role="switch"
|
|
98
|
+
id="obsidian-lg-incoming" checked />
|
|
99
|
+
<label class="form-check-label small" for="obsidian-lg-incoming">Incoming</label>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
76
102
|
<div id="obsidian-local-graph"
|
|
77
103
|
data-depth="{{ lg_depth }}"
|
|
78
104
|
data-index-url="{{ '/assets/data/wiki-index.json' | relative_url }}"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<ul class="list-unstyled fw-normal pb-2 small nav-tree-root">
|
|
37
37
|
{% for item in navigation %}
|
|
38
38
|
{% assign item_id = item.title | slugify | prepend: "nav-" %}
|
|
39
|
-
{% assign is_active = page.url == item.url %}
|
|
39
|
+
{% assign is_active = false %}{% if page.url == item.url %}{% assign is_active = true %}{% endif %}
|
|
40
40
|
{% assign is_expanded = item.expanded | default: false %}
|
|
41
41
|
{% assign has_children = item.children and item.children.size > 0 %}
|
|
42
42
|
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
<ul class="list-unstyled fw-normal ps-3 nav-tree-children">
|
|
79
79
|
{% for child in item.children %}
|
|
80
80
|
{% assign child_id = child.title | slugify | prepend: "nav-" %}
|
|
81
|
-
{% assign child_active = page.url == child.url %}
|
|
81
|
+
{% assign child_active = false %}{% if page.url == child.url %}{% assign child_active = true %}{% endif %}
|
|
82
82
|
{% assign child_expanded = child.expanded | default: false %}
|
|
83
83
|
{% assign child_has_children = child.children and child.children.size > 0 %}
|
|
84
84
|
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
<div class="collapse{% if child_expanded %} show{% endif %}" id="{{ child_id }}">
|
|
119
119
|
<ul class="list-unstyled fw-normal ps-3 nav-tree-children">
|
|
120
120
|
{% for grandchild in child.children %}
|
|
121
|
-
{% assign gc_active = page.url == grandchild.url %}
|
|
121
|
+
{% assign gc_active = false %}{% if page.url == grandchild.url %}{% assign gc_active = true %}{% endif %}
|
|
122
122
|
<li class="mb-1 nav-tree-item" data-depth="2">
|
|
123
123
|
{% if grandchild.url %}
|
|
124
124
|
<a href="{{ grandchild.url | relative_url }}"
|
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
Notes: `nav: auto` picks the best mode for the page's collection —
|
|
29
29
|
a curated _data/navigation/<collection>.yml wins, then the
|
|
30
30
|
live "collection" folder tree, then post "categories".
|
|
31
|
+
Legacy mode names ("tree", "dynamic", "searchCats") from
|
|
32
|
+
pre-1.x sidebars are aliased to "auto" for backward compat.
|
|
31
33
|
{%- endcomment -%}
|
|
32
34
|
|
|
33
35
|
{%- comment -%} 1. Visibility: page.sidebar wins; featured/breaking posts default off {%- endcomment -%}
|
|
@@ -61,6 +63,14 @@
|
|
|
61
63
|
{%- endif -%}
|
|
62
64
|
{%- endif -%}
|
|
63
65
|
|
|
66
|
+
{%- comment -%} 3b. Legacy mode names from pre-1.x sidebars ("tree", "dynamic",
|
|
67
|
+
"searchCats") no longer exist; consumer configs still carry them, which
|
|
68
|
+
used to silently disable the sidebar (no data file matches those names).
|
|
69
|
+
Treat them as "auto" so those sites get the best available mode. {%- endcomment -%}
|
|
70
|
+
{%- if sidebar_nav == "tree" or sidebar_nav == "dynamic" or sidebar_nav == "searchCats" -%}
|
|
71
|
+
{%- assign sidebar_nav = "auto" -%}
|
|
72
|
+
{%- endif -%}
|
|
73
|
+
|
|
64
74
|
{%- comment -%} 4. "auto" → concrete mode based on the page's collection {%- endcomment -%}
|
|
65
75
|
{%- if sidebar_nav == "auto" -%}
|
|
66
76
|
{%- assign sidebar_nav = nil -%}
|
|
@@ -91,6 +101,17 @@
|
|
|
91
101
|
{%- if site.tags.size > 0 -%}
|
|
92
102
|
{%- assign sidebar_has_content = true -%}
|
|
93
103
|
{%- endif -%}
|
|
104
|
+
{%- when "pages" -%}
|
|
105
|
+
{%- comment -%} URL-hierarchy page tree — content exists when the base
|
|
106
|
+
prefix matches at least one page (see sidebar-pagetree.html). {%- endcomment -%}
|
|
107
|
+
{%- assign _pt_base = page.sidebar.base -%}
|
|
108
|
+
{%- if _pt_base -%}
|
|
109
|
+
{%- assign _pt_pool = site.html_pages | concat: site.documents -%}
|
|
110
|
+
{%- assign _pt_hits = _pt_pool | where_exp: "p", "p.url contains _pt_base" -%}
|
|
111
|
+
{%- if _pt_hits.size > 0 -%}
|
|
112
|
+
{%- assign sidebar_has_content = true -%}
|
|
113
|
+
{%- endif -%}
|
|
114
|
+
{%- endif -%}
|
|
94
115
|
{%- else -%}
|
|
95
116
|
{%- if site.data.navigation[sidebar_nav] -%}
|
|
96
117
|
{%- assign sidebar_has_content = true -%}
|
|
@@ -23,6 +23,10 @@
|
|
|
23
23
|
<div class="nav-tree nav-tree--categories"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree>
|
|
24
24
|
{% include navigation/sidebar-categories.html taxonomy=sidebar_nav %}
|
|
25
25
|
</div>
|
|
26
|
+
{%- elsif sidebar_nav == "pages" -%}
|
|
27
|
+
<nav class="w-100 nav-tree"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree aria-label="Section navigation">
|
|
28
|
+
{% include navigation/sidebar-pagetree.html %}
|
|
29
|
+
</nav>
|
|
26
30
|
{%- elsif sidebar_nav -%}
|
|
27
31
|
<nav class="w-100 nav-tree"{% if include.id %} id="{{ include.id }}"{% endif %} data-nav-tree aria-label="Section navigation">
|
|
28
32
|
{% include navigation/nav-tree.html nav=sidebar_nav %}
|