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,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* theme-customizer.js
|
|
3
|
+
* Powers the Theme Customizer admin page.
|
|
4
|
+
* - Skin preview: clicking a card swaps data-bs-theme for page-level preview
|
|
5
|
+
* - Color editor: syncs color picker ↔ text inputs
|
|
6
|
+
* - YAML export: builds theme_skin + theme_color YAML from current selections
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
/* ── Skin Preview ─────────────────────────────────────────── */
|
|
13
|
+
const skinGrid = document.getElementById('skin-grid');
|
|
14
|
+
let selectedSkin = document.querySelector('.skin-card.border-primary');
|
|
15
|
+
|
|
16
|
+
if (skinGrid) {
|
|
17
|
+
skinGrid.addEventListener('click', function (e) {
|
|
18
|
+
const card = e.target.closest('.skin-card');
|
|
19
|
+
if (!card) return;
|
|
20
|
+
|
|
21
|
+
// Visual: deselect previous, select new
|
|
22
|
+
if (selectedSkin) {
|
|
23
|
+
selectedSkin.classList.replace('border-primary', 'border-secondary');
|
|
24
|
+
const prev = selectedSkin.querySelector('.badge');
|
|
25
|
+
if (prev) prev.outerHTML = '<small class="text-body-tertiary">Click to preview</small>';
|
|
26
|
+
const prevIcon = selectedSkin.querySelector('.bi-circle-fill');
|
|
27
|
+
if (prevIcon) { prevIcon.classList.remove('text-primary'); prevIcon.classList.add('text-body-secondary'); }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
card.classList.replace('border-secondary', 'border-primary');
|
|
31
|
+
const label = card.querySelector('small');
|
|
32
|
+
if (label) label.outerHTML = '<span class="badge bg-primary"><i class="bi bi-check-circle me-1"></i>Selected</span>';
|
|
33
|
+
const icon = card.querySelector('.bi-circle-fill');
|
|
34
|
+
if (icon) { icon.classList.remove('text-body-secondary'); icon.classList.add('text-primary'); }
|
|
35
|
+
|
|
36
|
+
selectedSkin = card;
|
|
37
|
+
rebuildYaml();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* ── Color Editor ─────────────────────────────────────────── */
|
|
42
|
+
document.querySelectorAll('[data-color-key]').forEach(function (picker) {
|
|
43
|
+
picker.addEventListener('input', function () {
|
|
44
|
+
const key = this.dataset.colorKey;
|
|
45
|
+
const textInput = document.querySelector('[data-color-text="' + key + '"]');
|
|
46
|
+
if (textInput) textInput.value = this.value;
|
|
47
|
+
rebuildYaml();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/* ── YAML Export ──────────────────────────────────────────── */
|
|
52
|
+
function rebuildYaml() {
|
|
53
|
+
// If palette-generator.js provides a full YAML builder, use it
|
|
54
|
+
if (typeof rebuildFullYaml === 'function') {
|
|
55
|
+
rebuildFullYaml();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
var lines = [];
|
|
59
|
+
// Skin
|
|
60
|
+
var skin = selectedSkin ? selectedSkin.dataset.skin : 'dark';
|
|
61
|
+
lines.push('theme_skin: "' + skin + '"');
|
|
62
|
+
lines.push('');
|
|
63
|
+
// Colors
|
|
64
|
+
lines.push('theme_color:');
|
|
65
|
+
document.querySelectorAll('[data-color-key]').forEach(function (el) {
|
|
66
|
+
var key = el.dataset.colorKey;
|
|
67
|
+
var val = el.value;
|
|
68
|
+
lines.push(' ' + key + ': ' + val);
|
|
69
|
+
});
|
|
70
|
+
var yaml = lines.join('\n');
|
|
71
|
+
var output = document.getElementById('theme-yaml-output');
|
|
72
|
+
if (output) output.textContent = yaml;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Initial build
|
|
76
|
+
rebuildYaml();
|
|
77
|
+
|
|
78
|
+
/* ── Copy / Download Buttons ──────────────────────────────── */
|
|
79
|
+
var copyBtn = document.getElementById('theme-copy-yaml');
|
|
80
|
+
if (copyBtn) {
|
|
81
|
+
copyBtn.addEventListener('click', function () {
|
|
82
|
+
var text = document.getElementById('theme-yaml-output').textContent;
|
|
83
|
+
navigator.clipboard.writeText(text).then(function () {
|
|
84
|
+
copyBtn.innerHTML = '<i class="bi bi-check me-1"></i> Copied';
|
|
85
|
+
setTimeout(function () { copyBtn.innerHTML = '<i class="bi bi-clipboard me-1"></i> Copy'; }, 2000);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
var dlBtn = document.getElementById('theme-download-yaml');
|
|
91
|
+
if (dlBtn) {
|
|
92
|
+
dlBtn.addEventListener('click', function () {
|
|
93
|
+
var text = document.getElementById('theme-yaml-output').textContent;
|
|
94
|
+
var blob = new Blob([text], { type: 'text/yaml' });
|
|
95
|
+
var a = document.createElement('a');
|
|
96
|
+
a.href = URL.createObjectURL(blob);
|
|
97
|
+
a.download = 'theme-config.yml';
|
|
98
|
+
a.click();
|
|
99
|
+
URL.revokeObjectURL(a.href);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
});
|
|
@@ -12,6 +12,16 @@
|
|
|
12
12
|
/**
|
|
13
13
|
* Initialize scroll animations for elements with animate-on-scroll class
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* True if any part of the element is in the viewport (avoids hiding above-the-fold
|
|
17
|
+
* content until IntersectionObserver runs — that caused layout “jumps” on the landing hero).
|
|
18
|
+
*/
|
|
19
|
+
function isInViewport(el) {
|
|
20
|
+
const rect = el.getBoundingClientRect();
|
|
21
|
+
const vh = window.innerHeight || document.documentElement.clientHeight;
|
|
22
|
+
return rect.bottom > 0 && rect.top < vh;
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
function initScrollAnimations() {
|
|
16
26
|
if (prefersReducedMotion) return;
|
|
17
27
|
|
|
@@ -35,6 +45,9 @@
|
|
|
35
45
|
}, observerOptions);
|
|
36
46
|
|
|
37
47
|
animatedElements.forEach(el => {
|
|
48
|
+
if (isInViewport(el)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
38
51
|
el.style.opacity = '0';
|
|
39
52
|
el.style.transform = 'translateY(30px)';
|
|
40
53
|
el.style.transition = 'opacity 0.6s ease-out, transform 0.6s ease-out';
|
|
@@ -42,29 +55,6 @@
|
|
|
42
55
|
});
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
/**
|
|
46
|
-
* Smooth scroll for anchor links
|
|
47
|
-
*/
|
|
48
|
-
function initSmoothScroll() {
|
|
49
|
-
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
50
|
-
anchor.addEventListener('click', function(e) {
|
|
51
|
-
const href = this.getAttribute('href');
|
|
52
|
-
if (href === '#' || href === '') return;
|
|
53
|
-
|
|
54
|
-
const target = document.querySelector(href);
|
|
55
|
-
if (target) {
|
|
56
|
-
e.preventDefault();
|
|
57
|
-
const offsetTop = target.offsetTop - 80; // Account for fixed navbar
|
|
58
|
-
|
|
59
|
-
window.scrollTo({
|
|
60
|
-
top: offsetTop,
|
|
61
|
-
behavior: prefersReducedMotion ? 'auto' : 'smooth'
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
58
|
/**
|
|
69
59
|
* Add loading state to images
|
|
70
60
|
*/
|
|
@@ -152,7 +142,8 @@
|
|
|
152
142
|
}
|
|
153
143
|
|
|
154
144
|
initScrollAnimations();
|
|
155
|
-
|
|
145
|
+
// Note: Smooth scrolling for anchor links is handled entirely by CSS
|
|
146
|
+
// (scroll-behavior: smooth + scroll-padding-top: 80px in custom.scss)
|
|
156
147
|
initImageLoading();
|
|
157
148
|
initButtonRipples();
|
|
158
149
|
initScrollSpy();
|