jekyll-theme-zer0 0.22.0 → 0.22.19
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 +236 -0
- data/README.md +66 -19
- data/_data/navigation/admin.yml +53 -0
- data/_data/theme_backgrounds.yml +121 -0
- data/_includes/components/admin-tabs.html +59 -0
- data/_includes/components/analytics-dashboard.html +232 -0
- data/_includes/components/background-customizer.html +159 -0
- data/_includes/components/background-settings.html +137 -0
- data/_includes/components/collection-manager.html +151 -0
- data/_includes/components/component-showcase.html +452 -0
- data/_includes/components/config-editor.html +207 -0
- data/_includes/components/config-viewer.html +479 -0
- data/_includes/components/env-dashboard.html +154 -0
- data/_includes/components/feature-card.html +94 -0
- data/_includes/components/info-section.html +172 -149
- data/_includes/components/js-cdn.html +4 -1
- data/_includes/components/nav-editor.html +99 -0
- data/_includes/components/setup-banner.html +28 -0
- data/_includes/components/setup-check.html +53 -0
- data/_includes/components/svg-background.html +42 -0
- data/_includes/components/theme-customizer.html +46 -0
- data/_includes/content/seo.html +68 -135
- data/_includes/core/footer.html +1 -1
- data/_includes/core/head.html +3 -2
- data/_includes/core/header.html +14 -7
- data/_includes/landing/landing-install-cards.html +18 -7
- data/_includes/navigation/admin-nav.html +95 -0
- data/_includes/navigation/navbar.html +43 -5
- data/_includes/navigation/sidebar-left.html +1 -1
- data/_includes/setup/wizard.html +330 -0
- data/_layouts/admin.html +166 -0
- data/_layouts/landing.html +23 -9
- data/_layouts/root.html +12 -6
- data/_layouts/setup.html +73 -0
- data/_plugins/preview_image_generator.rb +26 -12
- data/_sass/core/_navbar.scss +2 -2
- data/_sass/custom.scss +28 -6
- data/_sass/theme/_background-mixins.scss +95 -0
- data/_sass/theme/_backgrounds.scss +156 -0
- data/_sass/theme/_color-modes.scss +2 -1
- data/assets/backgrounds/gradients/air.svg +15 -0
- data/assets/backgrounds/gradients/aqua.svg +15 -0
- data/assets/backgrounds/gradients/contrast.svg +15 -0
- data/assets/backgrounds/gradients/dark.svg +15 -0
- data/assets/backgrounds/gradients/dirt.svg +15 -0
- data/assets/backgrounds/gradients/mint.svg +15 -0
- data/assets/backgrounds/gradients/neon.svg +15 -0
- data/assets/backgrounds/gradients/plum.svg +15 -0
- data/assets/backgrounds/gradients/sunrise.svg +15 -0
- data/assets/backgrounds/noise/air.svg +8 -0
- data/assets/backgrounds/noise/aqua.svg +8 -0
- data/assets/backgrounds/noise/contrast.svg +8 -0
- data/assets/backgrounds/noise/dark.svg +8 -0
- data/assets/backgrounds/noise/dirt.svg +8 -0
- data/assets/backgrounds/noise/mint.svg +8 -0
- data/assets/backgrounds/noise/neon.svg +8 -0
- data/assets/backgrounds/noise/plum.svg +8 -0
- data/assets/backgrounds/noise/sunrise.svg +8 -0
- data/assets/backgrounds/patterns/air.svg +7 -0
- data/assets/backgrounds/patterns/aqua.svg +7 -0
- data/assets/backgrounds/patterns/contrast.svg +4 -0
- data/assets/backgrounds/patterns/dark.svg +5 -0
- data/assets/backgrounds/patterns/dirt.svg +5 -0
- data/assets/backgrounds/patterns/mint.svg +6 -0
- data/assets/backgrounds/patterns/neon.svg +6 -0
- data/assets/backgrounds/patterns/plum.svg +6 -0
- data/assets/backgrounds/patterns/sunrise.svg +5 -0
- data/assets/js/background-customizer.js +73 -0
- data/assets/js/code-copy.js +18 -47
- data/assets/js/config-utility.js +307 -0
- data/assets/js/nav-editor.js +39 -0
- data/assets/js/palette-generator.js +415 -0
- data/assets/js/search-modal.js +31 -11
- data/assets/js/setup-wizard.js +306 -0
- data/assets/js/skin-editor.js +645 -0
- data/assets/js/theme-customizer.js +102 -0
- data/assets/js/ui-enhancements.js +15 -24
- data/assets/vendor/bootstrap/css/bootstrap.min.css +1 -0
- data/assets/vendor/bootstrap/js/bootstrap.bundle.min.js +1 -0
- data/scripts/README.md +45 -0
- data/scripts/features/generate-preview-images +297 -7
- data/scripts/features/install-preview-generator +51 -33
- data/scripts/fork-cleanup.sh +92 -19
- data/scripts/github-setup.sh +284 -0
- data/scripts/init_setup.sh +0 -1
- data/scripts/lib/frontmatter.sh +543 -0
- data/scripts/lib/migrate.sh +265 -0
- data/scripts/lib/preview_generator.py +607 -32
- data/scripts/lint-pages +505 -0
- data/scripts/migrate.sh +201 -0
- data/scripts/platform/setup-linux.sh +244 -0
- data/scripts/platform/setup-macos.sh +187 -0
- data/scripts/platform/setup-wsl.sh +196 -0
- metadata +71 -6
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
===================================================================
|
|
3
|
+
SVG-BACKGROUND — Apply fffuel-style SVG background to a zone
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
File: svg-background.html
|
|
7
|
+
Path: _includes/components/svg-background.html
|
|
8
|
+
Purpose: Adds a CSS class for the background zone and injects
|
|
9
|
+
per-skin CSS custom-property overrides from _config.yml.
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
zone — "hero" | "body" | "surface" | "footer" (default: "body")
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
include components/svg-background.html zone="hero"
|
|
16
|
+
<div class="zer0-bg-hero"> ... </div>
|
|
17
|
+
|
|
18
|
+
Dependencies:
|
|
19
|
+
- _sass/theme/_backgrounds.scss (utility classes)
|
|
20
|
+
- _data/theme_backgrounds.yml (asset paths)
|
|
21
|
+
- _config.yml theme_background (opacity / blend settings)
|
|
22
|
+
===================================================================
|
|
23
|
+
-->
|
|
24
|
+
|
|
25
|
+
{% assign zone = include.zone | default: "body" %}
|
|
26
|
+
{% assign skin = site.theme_skin | default: "dark" %}
|
|
27
|
+
{% assign bg = site.theme_background %}
|
|
28
|
+
|
|
29
|
+
{% comment %}
|
|
30
|
+
Inject runtime overrides from _config.yml into inline <style> once per page.
|
|
31
|
+
These override the SCSS defaults so site owners can tune via config alone.
|
|
32
|
+
{% endcomment %}
|
|
33
|
+
{% if bg.enabled != false %}
|
|
34
|
+
<style data-zer0-bg-overrides>
|
|
35
|
+
[data-theme-skin="{{ skin }}"] {
|
|
36
|
+
{% if bg.gradient_opacity %}--zer0-bg-gradient-opacity: {{ bg.gradient_opacity }};{% endif %}
|
|
37
|
+
{% if bg.texture_opacity %}--zer0-bg-texture-opacity: {{ bg.texture_opacity }};{% endif %}
|
|
38
|
+
{% if bg.pattern_opacity %}--zer0-bg-pattern-opacity: {{ bg.pattern_opacity }};{% endif %}
|
|
39
|
+
{% if bg.blend_mode %}--zer0-bg-blend: {{ bg.blend_mode }};{% endif %}
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
42
|
+
{% endif %}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
===================================================================
|
|
3
|
+
THEME CUSTOMIZER — Skin preview grid with live class swapping
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
File: theme-customizer.html
|
|
7
|
+
Path: _includes/components/theme-customizer.html
|
|
8
|
+
Purpose: Displays all available theme skins in a card grid.
|
|
9
|
+
Clicking a card applies the skin class and highlights it.
|
|
10
|
+
Current skin comes from site.theme_skin in _config.yml.
|
|
11
|
+
|
|
12
|
+
Dependencies: Bootstrap 5 grid/card, Bootstrap Icons
|
|
13
|
+
Used by: pages/_about/settings/theme.md (Skin Preview tab)
|
|
14
|
+
===================================================================
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
{% assign current_skin = site.theme_skin | default: "dark" %}
|
|
18
|
+
{% assign skins = "air,aqua,contrast,dark,dirt,neon,mint,plum,sunrise" | split: "," %}
|
|
19
|
+
|
|
20
|
+
<p class="text-body-secondary mb-3">
|
|
21
|
+
Current skin: <strong>{{ current_skin }}</strong>. Click a card to preview (page-level only — does not persist).
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<div class="row g-3" id="skin-grid">
|
|
25
|
+
{% for skin in skins %}
|
|
26
|
+
<div class="col-6 col-md-4 col-lg-3">
|
|
27
|
+
<div class="card h-100 skin-card {% if skin == current_skin %}border-primary{% else %}border-secondary{% endif %}"
|
|
28
|
+
data-skin="{{ skin }}" role="button" tabindex="0" style="cursor:pointer">
|
|
29
|
+
<div class="card-body text-center py-4">
|
|
30
|
+
<i class="bi bi-circle-fill fs-3 mb-2 d-block {% if skin == current_skin %}text-primary{% else %}text-body-secondary{% endif %}"></i>
|
|
31
|
+
<h6 class="card-title mb-1 text-capitalize">{{ skin }}</h6>
|
|
32
|
+
{% if skin == current_skin %}
|
|
33
|
+
<span class="badge bg-primary"><i class="bi bi-check-circle me-1"></i>Active</span>
|
|
34
|
+
{% else %}
|
|
35
|
+
<small class="text-body-tertiary">Click to preview</small>
|
|
36
|
+
{% endif %}
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
{% endfor %}
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div class="alert alert-info mt-3 small" role="alert">
|
|
44
|
+
<i class="bi bi-info-circle me-1"></i>
|
|
45
|
+
To permanently change the skin, update <code>theme_skin</code> in <code>_config.yml</code> or use the <strong>Export YAML</strong> tab.
|
|
46
|
+
</div>
|
data/_includes/content/seo.html
CHANGED
|
@@ -1,142 +1,75 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
<!--
|
|
2
|
+
===================================================================
|
|
3
|
+
SEO SUPPLEMENT - Additional meta tags not covered by jekyll-seo-tag
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
File: seo.html
|
|
7
|
+
Path: _includes/content/seo.html
|
|
8
|
+
Purpose: Outputs ONLY meta tags that the jekyll-seo-tag plugin does
|
|
9
|
+
not generate. The bulk of SEO (title, description, og:*,
|
|
10
|
+
twitter:*, canonical, JSON-LD) is handled by seo tags in
|
|
11
|
+
_layouts/root.html.
|
|
12
|
+
|
|
13
|
+
What this file adds:
|
|
14
|
+
- Custom og:image with preview_images.assets_prefix path normalisation
|
|
15
|
+
for the theme-specific page.preview and page.header.og_image keys.
|
|
16
|
+
When page.image is set, jekyll-seo-tag handles og:image and this
|
|
17
|
+
file skips its own og:image output to avoid duplicate tags.
|
|
18
|
+
- Non-Google site verification tags (Bing, Yandex, Naver, Baidu)
|
|
19
|
+
|
|
20
|
+
Dependencies:
|
|
21
|
+
- jekyll-seo-tag plugin (loaded in _layouts/root.html via seo tags)
|
|
22
|
+
- site.preview_images config in _config.yml
|
|
23
|
+
===================================================================
|
|
7
24
|
-->
|
|
8
25
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
{%-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{%- assign
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
{%-
|
|
24
|
-
{%-
|
|
25
|
-
|
|
26
|
-
{%-
|
|
27
|
-
{%-
|
|
28
|
-
{%-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
{%-
|
|
32
|
-
{%-
|
|
33
|
-
{%-
|
|
34
|
-
{%-
|
|
35
|
-
|
|
36
|
-
{%-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
{%-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
{%- assign og_type = "article" -%}
|
|
45
|
-
{%- else -%}
|
|
46
|
-
{%- assign og_type = "website" -%}
|
|
47
|
-
{%- endif -%}
|
|
48
|
-
|
|
49
|
-
<title>{{ seo_title | default: site.title }} {% if paginator %}{% unless paginator.page == 1 %} {{ site.data.ui-text[site.locale].page | default: "Page" }} {{ paginator.page }}{% endunless %}{% endif %}</title>
|
|
50
|
-
<meta name="description" content="{{ seo_description }}">
|
|
51
|
-
<meta name="author" content="{{ author.name | default: author }}">
|
|
52
|
-
|
|
53
|
-
{% if og_type == "article" %}
|
|
54
|
-
<meta property="article:author" content="{{ author.name | default: author }}">
|
|
55
|
-
{% endif %}
|
|
56
|
-
|
|
57
|
-
<meta property="og:type" content="{{ og_type }}">
|
|
58
|
-
<meta property="og:locale" content="{{ site.locale | replace: "-", "_" | default: "en_US" }}">
|
|
59
|
-
<meta property="og:site_name" content="{{ site.title }}">
|
|
60
|
-
<meta property="og:title" content="{{ page.title | default: site.title | markdownify | strip_html | strip_newlines | escape_once }}">
|
|
61
|
-
<meta property="og:url" content="{{ canonical_url }}">
|
|
62
|
-
|
|
63
|
-
<meta property="og:description" content="{{ seo_description }}">
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{% if page_large_image %}
|
|
67
|
-
<meta property="og:image" content="{{ page_large_image }}">
|
|
68
|
-
{% elsif page_teaser_image %}
|
|
69
|
-
<meta property="og:image" content="{{ page_teaser_image }}">
|
|
70
|
-
{% endif %}
|
|
71
|
-
|
|
72
|
-
{% if site.twitter.username %}
|
|
73
|
-
<meta name="twitter:site" content="@{{ site.twitter.username | replace: "@", "" }}">
|
|
74
|
-
<meta name="twitter:title" content="{{ page.title | default: site.title | markdownify | strip_html | strip_newlines | escape_once }}">
|
|
75
|
-
<meta name="twitter:description" content="{{ seo_description }}">
|
|
76
|
-
<meta name="twitter:url" content="{{ canonical_url }}">
|
|
77
|
-
|
|
78
|
-
{% if page_large_image %}
|
|
79
|
-
<meta name="twitter:card" content="summary_large_image">
|
|
80
|
-
<meta name="twitter:image" content="{{ page_large_image }}">
|
|
81
|
-
{% else %}
|
|
82
|
-
<meta name="twitter:card" content="summary">
|
|
83
|
-
{% if page_teaser_image %}
|
|
84
|
-
<meta name="twitter:image" content="{{ page_teaser_image }}">
|
|
85
|
-
{% endif %}
|
|
86
|
-
{% endif %}
|
|
87
|
-
|
|
88
|
-
{% if author_twitter %}
|
|
89
|
-
<meta name="twitter:creator" content="@{{ author_twitter }}">
|
|
90
|
-
{% endif %}
|
|
91
|
-
{% endif %}
|
|
92
|
-
|
|
93
|
-
<meta property="article:published_time" content="{{ page.date | default: page.lastmod | date_to_xmlschema }}">
|
|
94
|
-
|
|
95
|
-
{% if og_type == "article" and page.last_modified_at %}
|
|
96
|
-
<meta property="article:modified_time" content="{{ page.last_modified_at | date_to_xmlschema }}">
|
|
97
|
-
{% endif %}
|
|
98
|
-
|
|
99
|
-
{% if site.facebook %}
|
|
100
|
-
{% if site.facebook.publisher %}
|
|
101
|
-
<meta property="article:publisher" content="{{ site.facebook.publisher }}">
|
|
102
|
-
{% endif %}
|
|
103
|
-
|
|
104
|
-
{% if site.facebook.app_id %}
|
|
105
|
-
<meta property="fb:app_id" content="{{ site.facebook.app_id }}">
|
|
106
|
-
{% endif %}
|
|
107
|
-
{% endif %}
|
|
108
|
-
|
|
109
|
-
<link rel="canonical" href="{{ canonical_url }}">
|
|
110
|
-
|
|
111
|
-
{% if paginator.previous_page %}
|
|
112
|
-
<link rel="prev" href="{{ paginator.previous_page_path | absolute_url }}">
|
|
113
|
-
{% endif %}
|
|
114
|
-
{% if paginator.next_page %}
|
|
115
|
-
<link rel="next" href="{{ paginator.next_page_path | absolute_url }}">
|
|
116
|
-
{% endif %}
|
|
117
|
-
|
|
118
|
-
<script type="application/ld+json">
|
|
119
|
-
{
|
|
120
|
-
"@context": "https://schema.org",
|
|
121
|
-
{% if site.social.type == "Organization" %}
|
|
122
|
-
"@type": "Organization",
|
|
123
|
-
"url": {{ '/' | absolute_url | jsonify }}{% if site.og_image %},
|
|
124
|
-
"logo": {{ site_og_image | jsonify }}{% endif %}
|
|
125
|
-
{% else %}
|
|
126
|
-
"@type": "Person",
|
|
127
|
-
"name": {{ site.social.name | default: site.name | jsonify }},
|
|
128
|
-
"url": {{ '/' | absolute_url |jsonify }}{% if site.social.links %},
|
|
129
|
-
"sameAs": {{ site.social.links | jsonify }}{% endif %}
|
|
130
|
-
{% endif %}
|
|
131
|
-
}
|
|
132
|
-
</script>
|
|
133
|
-
|
|
134
|
-
<!-- Site verification -->
|
|
135
|
-
|
|
136
|
-
<meta name="google-site-verification" content="{{ site.google_site_verification }}" />
|
|
26
|
+
{%- comment -%}
|
|
27
|
+
Custom og:image handling: supports page.preview and page.header.og_image
|
|
28
|
+
with automatic assets_prefix path normalisation from _config.yml.
|
|
29
|
+
jekyll-seo-tag handles page.image / page.image.path, so we only emit
|
|
30
|
+
our own og:image when those standard keys are absent.
|
|
31
|
+
{%- endcomment -%}
|
|
32
|
+
|
|
33
|
+
{%- unless page.image -%}
|
|
34
|
+
{%- assign page_large_image = page.header.og_image | default: page.header.overlay_image | default: page.header.image -%}
|
|
35
|
+
{%- assign page_teaser_image = page.preview | default: site.og_image -%}
|
|
36
|
+
{%- assign assets_prefix = site.preview_images.assets_prefix | default: '/assets' -%}
|
|
37
|
+
{%- assign auto_prefix = site.preview_images.auto_prefix | default: true -%}
|
|
38
|
+
|
|
39
|
+
{%- if page_teaser_image contains '://' -%}
|
|
40
|
+
{%- comment -%} External URL - use as-is {%- endcomment -%}
|
|
41
|
+
{%- elsif auto_prefix and page_teaser_image != blank -%}
|
|
42
|
+
{%- unless page_teaser_image contains assets_prefix -%}
|
|
43
|
+
{%- assign page_teaser_image = assets_prefix | append: page_teaser_image -%}
|
|
44
|
+
{%- endunless -%}
|
|
45
|
+
{%- endif -%}
|
|
46
|
+
|
|
47
|
+
{%- if page_large_image != blank -%}
|
|
48
|
+
{%- assign seo_image = page_large_image | absolute_url | escape -%}
|
|
49
|
+
{%- elsif page_teaser_image != blank -%}
|
|
50
|
+
{%- assign seo_image = page_teaser_image | absolute_url | escape -%}
|
|
51
|
+
{%- endif -%}
|
|
52
|
+
|
|
53
|
+
{%- if seo_image -%}
|
|
54
|
+
<meta property="og:image" content="{{ seo_image }}">
|
|
55
|
+
<meta name="twitter:image" content="{{ seo_image }}">
|
|
56
|
+
{%- endif -%}
|
|
57
|
+
{%- endunless -%}
|
|
58
|
+
|
|
59
|
+
<!-- Site verification (non-Google; Google is handled by jekyll-seo-tag) -->
|
|
60
|
+
{% if site.bing_site_verification %}
|
|
137
61
|
<meta name="msvalidate.01" content="{{ site.bing_site_verification }}">
|
|
62
|
+
{% endif %}
|
|
63
|
+
{% if site.alexa_site_verification %}
|
|
138
64
|
<meta name="alexaVerifyID" content="{{ site.alexa_site_verification }}">
|
|
65
|
+
{% endif %}
|
|
66
|
+
{% if site.yandex_site_verification %}
|
|
139
67
|
<meta name="yandex-verification" content="{{ site.yandex_site_verification }}">
|
|
68
|
+
{% endif %}
|
|
69
|
+
{% if site.naver_site_verification %}
|
|
140
70
|
<meta name="naver-site-verification" content="{{ site.naver_site_verification }}">
|
|
71
|
+
{% endif %}
|
|
72
|
+
{% if site.baidu_site_verification %}
|
|
141
73
|
<meta name="baidu-site-verification" content="{{ site.baidu_site_verification }}">
|
|
142
|
-
|
|
74
|
+
{% endif %}
|
|
75
|
+
<!-- end _includes/content/seo.html -->
|
data/_includes/core/footer.html
CHANGED
data/_includes/core/head.html
CHANGED
|
@@ -88,9 +88,10 @@
|
|
|
88
88
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
89
89
|
|
|
90
90
|
<!-- ================================ -->
|
|
91
|
-
<!-- SEO
|
|
91
|
+
<!-- SEO SUPPLEMENT -->
|
|
92
92
|
<!-- ================================ -->
|
|
93
|
-
<!--
|
|
93
|
+
<!-- Additional SEO tags not covered by jekyll-seo-tag plugin ( in root.html).
|
|
94
|
+
Outputs custom og:image with assets_prefix normalisation and non-Google site verification. -->
|
|
94
95
|
{% include content/seo.html %}
|
|
95
96
|
|
|
96
97
|
<!-- ========================== -->
|
data/_includes/core/header.html
CHANGED
|
@@ -105,11 +105,18 @@
|
|
|
105
105
|
<div class="navbar-brand-group d-inline-flex align-items-center gap-2">
|
|
106
106
|
<!-- Home Navigation Button (Desktop only) -->
|
|
107
107
|
<div class="navbar-home-links d-none d-lg-inline-flex" role="navigation" aria-label="Quick navigation">
|
|
108
|
-
{%-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
{%- assign nav_home = site.data.navigation.home -%}
|
|
109
|
+
{%- if nav_home and nav_home.size > 0 -%}
|
|
110
|
+
{%- for home in nav_home -%}
|
|
111
|
+
<a class="btn" href="{{ home.url | relative_url }}" aria-label="{{ home.title }}" title="{{ home.title }}" {%- if home.url == page.url %} aria-current="page"{% endif %}>
|
|
112
|
+
<i class="{{ site.default_icon}} {{ home.icon }}"></i>
|
|
113
|
+
</a>
|
|
114
|
+
{%- endfor -%}
|
|
115
|
+
{%- else -%}
|
|
116
|
+
<a class="btn" href="{{ '/' | relative_url }}" aria-label="Home" title="Home — {{ site.title }}">
|
|
117
|
+
<i class="{{ site.default_icon }} bi-house"></i>
|
|
118
|
+
</a>
|
|
119
|
+
{%- endif -%}
|
|
113
120
|
</div>
|
|
114
121
|
|
|
115
122
|
<!-- Brand Logo Link to Root -->
|
|
@@ -151,11 +158,11 @@
|
|
|
151
158
|
<span class="nav-link-text d-none d-xl-inline ms-1">Search</span>
|
|
152
159
|
</button>
|
|
153
160
|
|
|
154
|
-
<!-- Settings
|
|
161
|
+
<!-- Settings Offcanvas Toggle -->
|
|
155
162
|
<button
|
|
156
163
|
class="btn nav-settings-button d-none d-lg-inline-flex"
|
|
157
164
|
type="button"
|
|
158
|
-
data-bs-toggle="
|
|
165
|
+
data-bs-toggle="offcanvas"
|
|
159
166
|
data-bs-target="#info-section"
|
|
160
167
|
aria-label="Open settings"
|
|
161
168
|
aria-haspopup="dialog"
|
|
@@ -30,15 +30,26 @@ docker run -p 4000:4000 {{ site.resources.docker.image | default: '' | join: ''
|
|
|
30
30
|
<div class="col-12 col-sm-10 col-md-6 col-lg-4">
|
|
31
31
|
<div class="card h-100 border-0 shadow-sm">
|
|
32
32
|
<div class="card-header bg-secondary text-white">
|
|
33
|
-
<h5 class="card-title mb-0"><i class="bi bi-git me-2"></i>Fork
|
|
33
|
+
<h5 class="card-title mb-0"><i class="bi bi-git me-2"></i>Fork & Deploy</h5>
|
|
34
34
|
</div>
|
|
35
35
|
<div class="card-body p-4 d-flex flex-column text-center">
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
{% assign github_fork_base = site.resources.github_fork | default: site.github.repository_url | join: '' %}
|
|
37
|
+
{% assign github_fork_suffix = github_fork_base | slice: -5, 5 %}
|
|
38
|
+
{% if github_fork_suffix == '/fork' %}
|
|
39
|
+
{% assign github_fork_url = github_fork_base %}
|
|
40
|
+
{% else %}
|
|
41
|
+
{% assign github_fork_url = github_fork_base | append: '/fork' %}
|
|
42
|
+
{% endif %}
|
|
43
|
+
<p class="card-text mb-3">Fork into <code><username>.github.io</code> for a personal site in minutes.</p>
|
|
44
|
+
<ol class="text-start small mb-3">
|
|
45
|
+
<li>Fork <a href="{{ github_fork_url }}" target="_blank" rel="noopener">bamr87/zer0-mistakes</a></li>
|
|
46
|
+
<li>Name it <code><your-username>.github.io</code></li>
|
|
47
|
+
<li>Enable GitHub Pages in Settings</li>
|
|
48
|
+
</ol>
|
|
49
|
+
<pre class="bg-dark text-light p-3 rounded mb-3 small text-start overflow-auto"><code>git clone https://github.com/<you>/<you>.github.io.git
|
|
50
|
+
cd <you>.github.io
|
|
51
|
+
./scripts/fork-cleanup.sh</code></pre>
|
|
52
|
+
<a class="btn btn-outline-secondary btn-sm mt-auto" href="{{ github_fork_url }}" target="_blank" rel="noopener">Fork on GitHub</a>
|
|
42
53
|
</div>
|
|
43
54
|
</div>
|
|
44
55
|
</div>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
===================================================================
|
|
3
|
+
ADMIN NAV — Data-driven sidebar navigation for admin/settings pages
|
|
4
|
+
===================================================================
|
|
5
|
+
|
|
6
|
+
File: admin-nav.html
|
|
7
|
+
Path: _includes/navigation/admin-nav.html
|
|
8
|
+
Purpose: Renders a vertical nav list for administrative pages.
|
|
9
|
+
Items are read from _data/navigation/admin.yml.
|
|
10
|
+
Highlights the active page based on page.url or
|
|
11
|
+
page.admin_section matching.
|
|
12
|
+
|
|
13
|
+
Dependencies: Bootstrap 5 nav component, Bootstrap Icons,
|
|
14
|
+
_data/navigation/admin.yml
|
|
15
|
+
Used by: _layouts/admin.html
|
|
16
|
+
===================================================================
|
|
17
|
+
-->
|
|
18
|
+
|
|
19
|
+
{% assign current_path = page.url %}
|
|
20
|
+
{% assign admin_items = site.data.navigation.admin %}
|
|
21
|
+
|
|
22
|
+
<ul class="nav nav-pills flex-column">
|
|
23
|
+
|
|
24
|
+
{% assign rendered_separator = false %}
|
|
25
|
+
{% for item in admin_items %}
|
|
26
|
+
|
|
27
|
+
{% if item.external and rendered_separator == false %}
|
|
28
|
+
{% assign rendered_separator = true %}
|
|
29
|
+
<li role="separator"><hr class="my-2"></li>
|
|
30
|
+
{% endif %}
|
|
31
|
+
|
|
32
|
+
{% comment %} Active detection: exact URL match or admin_section match {% endcomment %}
|
|
33
|
+
{% assign is_active = false %}
|
|
34
|
+
{% if current_path == item.url %}
|
|
35
|
+
{% assign is_active = true %}
|
|
36
|
+
{% elsif page.admin_section and page.admin_section == item.title %}
|
|
37
|
+
{% assign is_active = true %}
|
|
38
|
+
{% endif %}
|
|
39
|
+
|
|
40
|
+
{% comment %} Dynamic badges when no static badge is set {% endcomment %}
|
|
41
|
+
{% assign dynamic_badge = nil %}
|
|
42
|
+
{% assign badge_class = "bg-secondary" %}
|
|
43
|
+
{% unless item.badge or item.external %}
|
|
44
|
+
{% if item.url == "/about/settings/collections/" %}
|
|
45
|
+
{% assign dynamic_badge = site.collections | size %}
|
|
46
|
+
{% elsif item.url == "/about/settings/analytics/" %}
|
|
47
|
+
{% if site.posthog.enabled %}
|
|
48
|
+
{% assign dynamic_badge = "On" %}
|
|
49
|
+
{% assign badge_class = "bg-success" %}
|
|
50
|
+
{% else %}
|
|
51
|
+
{% assign dynamic_badge = "Off" %}
|
|
52
|
+
{% assign badge_class = "bg-secondary" %}
|
|
53
|
+
{% endif %}
|
|
54
|
+
{% elsif item.url == "/about/settings/environment/" %}
|
|
55
|
+
{% if jekyll.environment == "production" %}
|
|
56
|
+
{% assign dynamic_badge = "Prod" %}
|
|
57
|
+
{% assign badge_class = "bg-success" %}
|
|
58
|
+
{% else %}
|
|
59
|
+
{% assign dynamic_badge = "Dev" %}
|
|
60
|
+
{% assign badge_class = "bg-warning text-dark" %}
|
|
61
|
+
{% endif %}
|
|
62
|
+
{% endif %}
|
|
63
|
+
{% endunless %}
|
|
64
|
+
|
|
65
|
+
<li class="nav-item">
|
|
66
|
+
{% if item.external %}
|
|
67
|
+
{% comment %} Resolve placeholder tokens for external URLs {% endcomment %}
|
|
68
|
+
{% assign resolved_url = item.url
|
|
69
|
+
| replace: '{github_user}', site.github_user
|
|
70
|
+
| replace: '{repository_name}', site.repository_name %}
|
|
71
|
+
<a class="nav-link d-flex align-items-center text-body-secondary"
|
|
72
|
+
href="{{ resolved_url }}"
|
|
73
|
+
target="_blank" rel="noopener">
|
|
74
|
+
<i class="{{ item.icon }} me-2"></i>
|
|
75
|
+
{{ item.title }}
|
|
76
|
+
<i class="bi bi-box-arrow-up-right ms-auto small"></i>
|
|
77
|
+
</a>
|
|
78
|
+
{% else %}
|
|
79
|
+
<a class="nav-link d-flex align-items-center{% if is_active %} active{% endif %}"
|
|
80
|
+
href="{{ item.url | relative_url }}"
|
|
81
|
+
{% if item.description %}title="{{ item.description }}"{% endif %}>
|
|
82
|
+
<i class="{{ item.icon }} me-2"></i>
|
|
83
|
+
{{ item.title }}
|
|
84
|
+
{% if item.badge %}
|
|
85
|
+
<span class="badge bg-secondary ms-auto">{{ item.badge }}</span>
|
|
86
|
+
{% elsif dynamic_badge %}
|
|
87
|
+
<span class="badge {{ badge_class }} ms-auto">{{ dynamic_badge }}</span>
|
|
88
|
+
{% endif %}
|
|
89
|
+
</a>
|
|
90
|
+
{% endif %}
|
|
91
|
+
</li>
|
|
92
|
+
|
|
93
|
+
{% endfor %}
|
|
94
|
+
|
|
95
|
+
</ul>
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
with hover-activated dropdowns for desktop and accessible interactions
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
|
-
<!-- Navigation Links - Offcanvas -->
|
|
10
|
-
<div class="offcanvas offcanvas-end
|
|
9
|
+
<!-- Navigation Links - Responsive Offcanvas (inline at lg+, offcanvas below) -->
|
|
10
|
+
<div class="offcanvas-lg offcanvas-end" tabindex="-1" id="bdNavbar" aria-labelledby="mainNavOffcanvasLabel">
|
|
11
11
|
|
|
12
12
|
<!-- Main Navigation Header - Offcanvas -->
|
|
13
13
|
<div class="offcanvas-header border-bottom">
|
|
@@ -26,7 +26,17 @@
|
|
|
26
26
|
Home
|
|
27
27
|
</a>
|
|
28
28
|
</li>
|
|
29
|
-
{%-
|
|
29
|
+
{%- comment -%}
|
|
30
|
+
Navigation: data-driven when _data/navigation/main.yml exists;
|
|
31
|
+
otherwise auto-generated from site.collections as a fallback so
|
|
32
|
+
a consumer repo needs only markdown files and _config.yml.
|
|
33
|
+
Exclude a collection from auto-nav by setting nav_exclude: true
|
|
34
|
+
under its entry in _config.yml collections:.
|
|
35
|
+
{%- endcomment -%}
|
|
36
|
+
{%- assign nav_main = site.data.navigation.main -%}
|
|
37
|
+
{%- if nav_main and nav_main.size > 0 -%}
|
|
38
|
+
|
|
39
|
+
{%- for link in nav_main -%}
|
|
30
40
|
{%- assign has_children = link.children and link.children.size > 0 -%}
|
|
31
41
|
|
|
32
42
|
{%- if has_children -%}
|
|
@@ -93,7 +103,35 @@
|
|
|
93
103
|
</a>
|
|
94
104
|
</li>
|
|
95
105
|
{%- endif -%}
|
|
96
|
-
|
|
106
|
+
{%- endfor -%}
|
|
107
|
+
|
|
108
|
+
{%- else -%}
|
|
109
|
+
{%- comment -%}
|
|
110
|
+
Dynamic navigation: one nav item per collection that has output
|
|
111
|
+
documents. The "pages" collection is skipped (structural only).
|
|
112
|
+
Set nav_exclude: true on a collection in _config.yml to hide it.
|
|
113
|
+
{%- endcomment -%}
|
|
114
|
+
{%- for collection in site.collections -%}
|
|
115
|
+
{%- unless collection.label == "pages" or collection.nav_exclude -%}
|
|
116
|
+
{%- if collection.docs.size > 0 -%}
|
|
117
|
+
{%- assign col_title = collection.label | replace: "-", " " | replace: "_", " " | capitalize -%}
|
|
118
|
+
{%- assign col_url = "/" | append: collection.label | append: "/" -%}
|
|
119
|
+
<li class="nav-item" role="none">
|
|
120
|
+
<a
|
|
121
|
+
class="nav-link"
|
|
122
|
+
href="{{ col_url | relative_url }}"
|
|
123
|
+
role="menuitem"
|
|
124
|
+
title="{{ col_title }}"
|
|
125
|
+
{%- if page.collection == collection.label -%} aria-current="page"{%- endif -%}
|
|
126
|
+
>
|
|
127
|
+
<span class="nav-link-text">{{ col_title }}</span>
|
|
128
|
+
</a>
|
|
129
|
+
</li>
|
|
130
|
+
{%- endif -%}
|
|
131
|
+
{%- endunless -%}
|
|
132
|
+
{%- endfor -%}
|
|
133
|
+
|
|
134
|
+
{%- endif -%}
|
|
97
135
|
<li class="nav-item d-lg-none" role="none">
|
|
98
136
|
<button
|
|
99
137
|
class="nav-link btn btn-link text-start w-100"
|
|
@@ -110,7 +148,7 @@
|
|
|
110
148
|
<button
|
|
111
149
|
class="nav-link btn btn-link text-start w-100"
|
|
112
150
|
type="button"
|
|
113
|
-
data-bs-toggle="
|
|
151
|
+
data-bs-toggle="offcanvas"
|
|
114
152
|
data-bs-target="#info-section"
|
|
115
153
|
aria-controls="info-section"
|
|
116
154
|
aria-haspopup="dialog"
|