jekyll-theme-zer0 0.15.2 → 0.17.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 +138 -10
- data/README.md +7 -7
- data/_data/authors.yml +2 -2
- data/_data/features.yml +676 -0
- data/_data/navigation/README.md +54 -0
- data/_data/navigation/about.yml +7 -5
- data/_data/navigation/docs.yml +77 -31
- data/_data/navigation/home.yml +4 -3
- data/_data/navigation/main.yml +16 -7
- data/_data/navigation/quickstart.yml +4 -2
- data/_includes/components/js-cdn.html +2 -2
- data/_includes/components/preview-image.html +20 -3
- data/_includes/content/intro.html +11 -2
- data/_includes/content/seo.html +12 -1
- data/_includes/landing/landing-install-cards.html +8 -8
- data/_includes/landing/landing-quick-links.html +4 -4
- data/_includes/navigation/breadcrumbs.html +29 -6
- data/_includes/navigation/nav-tree.html +181 -0
- data/_includes/navigation/navbar.html +262 -9
- data/_includes/navigation/sidebar-left.html +22 -23
- data/_layouts/default.html +1 -1
- data/_layouts/landing.html +1 -1
- data/_layouts/notebook.html +4 -4
- data/_layouts/root.html +2 -2
- data/_plugins/preview_image_generator.rb +29 -8
- data/_sass/core/_nav-tree.scss +145 -0
- data/_sass/custom.scss +3 -0
- data/assets/images/previews/site-personalization-configuration.png +0 -0
- data/assets/js/modules/navigation/config.js +149 -0
- data/assets/js/modules/navigation/focus.js +189 -0
- data/assets/js/modules/navigation/gestures.js +179 -0
- data/assets/js/modules/navigation/index.js +227 -0
- data/assets/js/modules/navigation/keyboard.js +237 -0
- data/assets/js/modules/navigation/scroll-spy.js +219 -0
- data/assets/js/modules/navigation/sidebar-state.js +267 -0
- data/assets/js/modules/navigation/smooth-scroll.js +153 -0
- data/scripts/README.md +8 -1
- data/scripts/lib/preview_generator.py +164 -8
- data/scripts/migrate-nav-modes.sh +146 -0
- data/scripts/update-preview-paths.sh +145 -0
- metadata +17 -3
- data/assets/js/sidebar.js +0 -511
|
@@ -101,6 +101,8 @@ class PreviewGenerator:
|
|
|
101
101
|
output_dir: str = "assets/images/previews",
|
|
102
102
|
image_style: str = "digital art, professional blog illustration",
|
|
103
103
|
image_size: str = "1024x1024",
|
|
104
|
+
assets_prefix: str = "/assets",
|
|
105
|
+
auto_prefix: bool = True,
|
|
104
106
|
dry_run: bool = False,
|
|
105
107
|
verbose: bool = False,
|
|
106
108
|
force: bool = False,
|
|
@@ -110,6 +112,8 @@ class PreviewGenerator:
|
|
|
110
112
|
self.output_dir = project_root / output_dir
|
|
111
113
|
self.image_style = image_style
|
|
112
114
|
self.image_size = image_size
|
|
115
|
+
self.assets_prefix = assets_prefix
|
|
116
|
+
self.auto_prefix = auto_prefix
|
|
113
117
|
self.dry_run = dry_run
|
|
114
118
|
self.verbose = verbose
|
|
115
119
|
self.force = force
|
|
@@ -129,6 +133,27 @@ class PreviewGenerator:
|
|
|
129
133
|
if self.verbose:
|
|
130
134
|
log(msg, "debug")
|
|
131
135
|
|
|
136
|
+
def normalize_preview_path(self, preview_path: Optional[str]) -> Optional[str]:
|
|
137
|
+
"""Normalize a preview path by adding assets_prefix if needed.
|
|
138
|
+
|
|
139
|
+
This allows users to omit the /assets/ prefix in frontmatter:
|
|
140
|
+
- /images/previews/my-image.png -> /assets/images/previews/my-image.png
|
|
141
|
+
- /assets/images/previews/my-image.png -> unchanged
|
|
142
|
+
- https://example.com/image.png -> unchanged (external URL)
|
|
143
|
+
"""
|
|
144
|
+
if not preview_path:
|
|
145
|
+
return preview_path
|
|
146
|
+
|
|
147
|
+
# External URLs pass through unchanged
|
|
148
|
+
if preview_path.startswith('http://') or preview_path.startswith('https://'):
|
|
149
|
+
return preview_path
|
|
150
|
+
|
|
151
|
+
# If auto_prefix is enabled and path doesn't contain assets_prefix
|
|
152
|
+
if self.auto_prefix and self.assets_prefix not in preview_path:
|
|
153
|
+
return f"{self.assets_prefix}{preview_path}"
|
|
154
|
+
|
|
155
|
+
return preview_path
|
|
156
|
+
|
|
132
157
|
def parse_front_matter(self, file_path: Path) -> Optional[ContentFile]:
|
|
133
158
|
"""Parse front matter and content from a markdown file."""
|
|
134
159
|
try:
|
|
@@ -178,19 +203,19 @@ class PreviewGenerator:
|
|
|
178
203
|
if not preview_path:
|
|
179
204
|
return False
|
|
180
205
|
|
|
206
|
+
# Normalize the path first (adds assets_prefix if needed)
|
|
207
|
+
normalized_path = self.normalize_preview_path(preview_path)
|
|
208
|
+
if not normalized_path:
|
|
209
|
+
return False
|
|
210
|
+
|
|
181
211
|
# Handle absolute and relative paths
|
|
182
|
-
clean_path =
|
|
212
|
+
clean_path = normalized_path.lstrip('/')
|
|
183
213
|
|
|
184
214
|
# Check direct path
|
|
185
215
|
full_path = self.project_root / clean_path
|
|
186
216
|
if full_path.exists():
|
|
187
217
|
return True
|
|
188
218
|
|
|
189
|
-
# Check in assets directory
|
|
190
|
-
assets_path = self.project_root / 'assets' / clean_path
|
|
191
|
-
if assets_path.exists():
|
|
192
|
-
return True
|
|
193
|
-
|
|
194
219
|
return False
|
|
195
220
|
|
|
196
221
|
def generate_prompt(self, content: ContentFile) -> str:
|
|
@@ -395,12 +420,131 @@ class PreviewGenerator:
|
|
|
395
420
|
prompt_used=prompt,
|
|
396
421
|
)
|
|
397
422
|
|
|
423
|
+
def generate_image_xai(self, prompt: str, output_path: Path) -> GenerationResult:
|
|
424
|
+
"""Generate image using xAI Grok API."""
|
|
425
|
+
if not HAS_REQUESTS:
|
|
426
|
+
return GenerationResult(
|
|
427
|
+
success=False,
|
|
428
|
+
image_path=None,
|
|
429
|
+
preview_url=None,
|
|
430
|
+
error="requests package not installed. Run: pip install requests",
|
|
431
|
+
prompt_used=prompt,
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
api_key = os.environ.get('XAI_API_KEY')
|
|
435
|
+
if not api_key:
|
|
436
|
+
return GenerationResult(
|
|
437
|
+
success=False,
|
|
438
|
+
image_path=None,
|
|
439
|
+
preview_url=None,
|
|
440
|
+
error="XAI_API_KEY environment variable not set",
|
|
441
|
+
prompt_used=prompt,
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
try:
|
|
445
|
+
# xAI has a max prompt length of 1024 characters
|
|
446
|
+
truncated_prompt = prompt[:1000] if len(prompt) > 1000 else prompt
|
|
447
|
+
self.debug(f"Generating with xAI Grok, prompt: {truncated_prompt[:200]}...")
|
|
448
|
+
|
|
449
|
+
# xAI uses OpenAI-compatible API format
|
|
450
|
+
response = requests.post(
|
|
451
|
+
"https://api.x.ai/v1/images/generations",
|
|
452
|
+
headers={
|
|
453
|
+
"Authorization": f"Bearer {api_key}",
|
|
454
|
+
"Content-Type": "application/json",
|
|
455
|
+
},
|
|
456
|
+
json={
|
|
457
|
+
"model": "grok-2-image",
|
|
458
|
+
"prompt": truncated_prompt,
|
|
459
|
+
"n": 1,
|
|
460
|
+
},
|
|
461
|
+
timeout=120, # 2 minute timeout for image generation
|
|
462
|
+
)
|
|
463
|
+
response.raise_for_status()
|
|
464
|
+
|
|
465
|
+
data = response.json()
|
|
466
|
+
|
|
467
|
+
# xAI returns base64-encoded images
|
|
468
|
+
if 'data' not in data or not data['data']:
|
|
469
|
+
return GenerationResult(
|
|
470
|
+
success=False,
|
|
471
|
+
image_path=None,
|
|
472
|
+
preview_url=None,
|
|
473
|
+
error="No image data in response",
|
|
474
|
+
prompt_used=prompt,
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
image_data = data['data'][0]
|
|
478
|
+
|
|
479
|
+
# Check if it's a URL or base64
|
|
480
|
+
if 'url' in image_data:
|
|
481
|
+
# Download from URL
|
|
482
|
+
img_response = requests.get(image_data['url'], timeout=60)
|
|
483
|
+
img_response.raise_for_status()
|
|
484
|
+
output_path.write_bytes(img_response.content)
|
|
485
|
+
elif 'b64_json' in image_data:
|
|
486
|
+
# Decode base64
|
|
487
|
+
import base64
|
|
488
|
+
image_bytes = base64.b64decode(image_data['b64_json'])
|
|
489
|
+
output_path.write_bytes(image_bytes)
|
|
490
|
+
else:
|
|
491
|
+
return GenerationResult(
|
|
492
|
+
success=False,
|
|
493
|
+
image_path=None,
|
|
494
|
+
preview_url=None,
|
|
495
|
+
error="Unexpected response format from xAI",
|
|
496
|
+
prompt_used=prompt,
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
return GenerationResult(
|
|
500
|
+
success=True,
|
|
501
|
+
image_path=str(output_path),
|
|
502
|
+
preview_url=str(output_path.relative_to(self.project_root)),
|
|
503
|
+
error=None,
|
|
504
|
+
prompt_used=prompt,
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
except requests.exceptions.HTTPError as e:
|
|
508
|
+
error_msg = str(e)
|
|
509
|
+
try:
|
|
510
|
+
error_data = e.response.json()
|
|
511
|
+
self.debug(f"xAI error response: {error_data}")
|
|
512
|
+
if 'error' in error_data:
|
|
513
|
+
error_msg = error_data['error'].get('message', str(error_data['error']))
|
|
514
|
+
elif 'detail' in error_data:
|
|
515
|
+
error_msg = str(error_data['detail'])
|
|
516
|
+
else:
|
|
517
|
+
error_msg = str(error_data)
|
|
518
|
+
except:
|
|
519
|
+
# Try to get raw text
|
|
520
|
+
try:
|
|
521
|
+
error_msg = e.response.text[:500]
|
|
522
|
+
except:
|
|
523
|
+
pass
|
|
524
|
+
return GenerationResult(
|
|
525
|
+
success=False,
|
|
526
|
+
image_path=None,
|
|
527
|
+
preview_url=None,
|
|
528
|
+
error=f"xAI API error: {error_msg}",
|
|
529
|
+
prompt_used=prompt,
|
|
530
|
+
)
|
|
531
|
+
except Exception as e:
|
|
532
|
+
return GenerationResult(
|
|
533
|
+
success=False,
|
|
534
|
+
image_path=None,
|
|
535
|
+
preview_url=None,
|
|
536
|
+
error=str(e),
|
|
537
|
+
prompt_used=prompt,
|
|
538
|
+
)
|
|
539
|
+
|
|
398
540
|
def generate_image(self, prompt: str, output_path: Path) -> GenerationResult:
|
|
399
541
|
"""Generate image using configured provider."""
|
|
400
542
|
if self.provider == "openai":
|
|
401
543
|
return self.generate_image_openai(prompt, output_path)
|
|
402
544
|
elif self.provider == "stability":
|
|
403
545
|
return self.generate_image_stability(prompt, output_path)
|
|
546
|
+
elif self.provider == "xai":
|
|
547
|
+
return self.generate_image_xai(prompt, output_path)
|
|
404
548
|
else:
|
|
405
549
|
return GenerationResult(
|
|
406
550
|
success=False,
|
|
@@ -559,9 +703,9 @@ def main():
|
|
|
559
703
|
)
|
|
560
704
|
parser.add_argument(
|
|
561
705
|
'-p', '--provider',
|
|
562
|
-
choices=['openai', 'stability'],
|
|
706
|
+
choices=['openai', 'stability', 'xai'],
|
|
563
707
|
default='openai',
|
|
564
|
-
help="AI provider for image generation"
|
|
708
|
+
help="AI provider for image generation (openai, stability, xai)"
|
|
565
709
|
)
|
|
566
710
|
parser.add_argument(
|
|
567
711
|
'-d', '--dry-run',
|
|
@@ -593,6 +737,16 @@ def main():
|
|
|
593
737
|
default='digital art, professional blog illustration, clean design',
|
|
594
738
|
help="Image style prompt"
|
|
595
739
|
)
|
|
740
|
+
parser.add_argument(
|
|
741
|
+
'--assets-prefix',
|
|
742
|
+
default='/assets',
|
|
743
|
+
help="Prefix to prepend to relative preview paths (default: /assets)"
|
|
744
|
+
)
|
|
745
|
+
parser.add_argument(
|
|
746
|
+
'--no-auto-prefix',
|
|
747
|
+
action='store_true',
|
|
748
|
+
help="Disable automatic assets prefix prepending"
|
|
749
|
+
)
|
|
596
750
|
|
|
597
751
|
args = parser.parse_args()
|
|
598
752
|
|
|
@@ -606,6 +760,8 @@ def main():
|
|
|
606
760
|
provider=args.provider,
|
|
607
761
|
output_dir=args.output_dir,
|
|
608
762
|
image_style=args.style,
|
|
763
|
+
assets_prefix=args.assets_prefix,
|
|
764
|
+
auto_prefix=not args.no_auto_prefix,
|
|
609
765
|
dry_run=args.dry_run,
|
|
610
766
|
verbose=args.verbose,
|
|
611
767
|
force=args.force,
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ===================================================================
|
|
3
|
+
# MIGRATE NAV MODES - Update Front Matter Navigation Values
|
|
4
|
+
# ===================================================================
|
|
5
|
+
#
|
|
6
|
+
# File: migrate-nav-modes.sh
|
|
7
|
+
# Path: scripts/migrate-nav-modes.sh
|
|
8
|
+
# Purpose: Update front matter nav values from old to new modes
|
|
9
|
+
#
|
|
10
|
+
# Migration Map:
|
|
11
|
+
# dynamic → auto
|
|
12
|
+
# searchCats → categories
|
|
13
|
+
# docs → tree
|
|
14
|
+
# about → tree
|
|
15
|
+
# quickstart → tree
|
|
16
|
+
# main → tree
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# ./scripts/migrate-nav-modes.sh # Dry run (preview changes)
|
|
20
|
+
# ./scripts/migrate-nav-modes.sh --apply # Apply changes
|
|
21
|
+
#
|
|
22
|
+
# ===================================================================
|
|
23
|
+
|
|
24
|
+
set -eo pipefail
|
|
25
|
+
|
|
26
|
+
# Colors for output
|
|
27
|
+
RED='\033[0;31m'
|
|
28
|
+
GREEN='\033[0;32m'
|
|
29
|
+
YELLOW='\033[1;33m'
|
|
30
|
+
BLUE='\033[0;34m'
|
|
31
|
+
NC='\033[0m' # No Color
|
|
32
|
+
|
|
33
|
+
# Script configuration
|
|
34
|
+
PAGES_DIR="pages"
|
|
35
|
+
DRY_RUN=true
|
|
36
|
+
|
|
37
|
+
# Parse arguments
|
|
38
|
+
if [[ "${1:-}" == "--apply" ]]; then
|
|
39
|
+
DRY_RUN=false
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
43
|
+
echo -e "${BLUE} Navigation Mode Migration Script${NC}"
|
|
44
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
45
|
+
echo ""
|
|
46
|
+
|
|
47
|
+
if $DRY_RUN; then
|
|
48
|
+
echo -e "${YELLOW}Running in DRY RUN mode. No files will be modified.${NC}"
|
|
49
|
+
echo -e "${YELLOW}Use --apply to make actual changes.${NC}"
|
|
50
|
+
else
|
|
51
|
+
echo -e "${RED}Running in APPLY mode. Files will be modified.${NC}"
|
|
52
|
+
fi
|
|
53
|
+
echo ""
|
|
54
|
+
|
|
55
|
+
# Migration patterns (old → new)
|
|
56
|
+
# Using simple arrays instead of associative arrays for compatibility
|
|
57
|
+
OLD_PATTERNS=("nav: dynamic" "nav: searchCats")
|
|
58
|
+
NEW_PATTERNS=("nav: auto" "nav: categories")
|
|
59
|
+
|
|
60
|
+
# Files that explicitly set nav values (not inherited from _config.yml)
|
|
61
|
+
EXPLICIT_NAV_PATTERNS=(
|
|
62
|
+
"nav: dynamic"
|
|
63
|
+
"nav: searchCats"
|
|
64
|
+
"nav: docs"
|
|
65
|
+
"nav: about"
|
|
66
|
+
"nav: quickstart"
|
|
67
|
+
"nav: main"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Count changes
|
|
71
|
+
TOTAL_FILES=0
|
|
72
|
+
TOTAL_CHANGES=0
|
|
73
|
+
|
|
74
|
+
echo -e "${BLUE}Scanning for files with explicit nav values...${NC}"
|
|
75
|
+
echo ""
|
|
76
|
+
|
|
77
|
+
# Find all markdown files
|
|
78
|
+
while IFS= read -r -d '' file; do
|
|
79
|
+
file_changes=0
|
|
80
|
+
|
|
81
|
+
# Check if file has any nav patterns
|
|
82
|
+
for pattern in "${EXPLICIT_NAV_PATTERNS[@]}"; do
|
|
83
|
+
if grep -q "$pattern" "$file" 2>/dev/null; then
|
|
84
|
+
((file_changes++)) || true
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
if [[ $file_changes -gt 0 ]]; then
|
|
89
|
+
((TOTAL_FILES++)) || true
|
|
90
|
+
echo -e "${GREEN}Found:${NC} $file"
|
|
91
|
+
|
|
92
|
+
# Show what would change
|
|
93
|
+
for i in "${!OLD_PATTERNS[@]}"; do
|
|
94
|
+
old_pattern="${OLD_PATTERNS[$i]}"
|
|
95
|
+
new_pattern="${NEW_PATTERNS[$i]}"
|
|
96
|
+
if grep -q "$old_pattern" "$file" 2>/dev/null; then
|
|
97
|
+
echo -e " ${YELLOW}Change:${NC} '$old_pattern' → '$new_pattern'"
|
|
98
|
+
((TOTAL_CHANGES++)) || true
|
|
99
|
+
|
|
100
|
+
if ! $DRY_RUN; then
|
|
101
|
+
# Apply the change using sed
|
|
102
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
103
|
+
sed -i '' "s/$old_pattern/$new_pattern/g" "$file"
|
|
104
|
+
else
|
|
105
|
+
sed -i "s/$old_pattern/$new_pattern/g" "$file"
|
|
106
|
+
fi
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
# Check for named nav files that should use tree mode
|
|
112
|
+
# Note: These are trickier because we want to keep the YAML file reference
|
|
113
|
+
# but change how the template interprets them
|
|
114
|
+
for named_nav in "docs" "about" "quickstart" "main"; do
|
|
115
|
+
if grep -q "nav: $named_nav" "$file" 2>/dev/null; then
|
|
116
|
+
echo -e " ${BLUE}Note:${NC} 'nav: $named_nav' - YAML file will be used with tree mode"
|
|
117
|
+
# No automatic migration - sidebar-left.html handles this via fallthrough
|
|
118
|
+
fi
|
|
119
|
+
done
|
|
120
|
+
|
|
121
|
+
echo ""
|
|
122
|
+
fi
|
|
123
|
+
done < <(find "$PAGES_DIR" -name "*.md" -print0 2>/dev/null)
|
|
124
|
+
|
|
125
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
126
|
+
echo -e "${BLUE} Summary${NC}"
|
|
127
|
+
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
|
128
|
+
echo ""
|
|
129
|
+
echo -e "Files scanned: ${GREEN}$(find "$PAGES_DIR" -name "*.md" 2>/dev/null | wc -l | tr -d ' ')${NC}"
|
|
130
|
+
echo -e "Files affected: ${GREEN}$TOTAL_FILES${NC}"
|
|
131
|
+
echo -e "Changes made: ${GREEN}$TOTAL_CHANGES${NC}"
|
|
132
|
+
echo ""
|
|
133
|
+
|
|
134
|
+
if $DRY_RUN; then
|
|
135
|
+
echo -e "${YELLOW}This was a dry run. To apply changes, run:${NC}"
|
|
136
|
+
echo -e " ${GREEN}./scripts/migrate-nav-modes.sh --apply${NC}"
|
|
137
|
+
else
|
|
138
|
+
echo -e "${GREEN}Migration complete!${NC}"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
echo ""
|
|
142
|
+
echo -e "${BLUE}Navigation Mode Reference:${NC}"
|
|
143
|
+
echo " auto - Auto-generated from collection documents"
|
|
144
|
+
echo " tree - YAML-defined hierarchical navigation"
|
|
145
|
+
echo " categories - Category-based grouping"
|
|
146
|
+
echo ""
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# update-preview-paths.sh
|
|
4
|
+
#
|
|
5
|
+
# Updates all preview paths in markdown frontmatter to remove the /assets/ prefix.
|
|
6
|
+
# This aligns with the new auto_prefix feature that automatically prepends /assets/.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./scripts/update-preview-paths.sh # Dry run (preview changes)
|
|
10
|
+
# ./scripts/update-preview-paths.sh --apply # Apply changes
|
|
11
|
+
#
|
|
12
|
+
# Example transformation:
|
|
13
|
+
# preview: /assets/images/previews/my-image.png
|
|
14
|
+
# becomes:
|
|
15
|
+
# preview: /images/previews/my-image.png
|
|
16
|
+
#
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# Colors for output
|
|
21
|
+
RED='\033[0;31m'
|
|
22
|
+
GREEN='\033[0;32m'
|
|
23
|
+
YELLOW='\033[1;33m'
|
|
24
|
+
BLUE='\033[0;34m'
|
|
25
|
+
CYAN='\033[0;36m'
|
|
26
|
+
NC='\033[0m' # No Color
|
|
27
|
+
|
|
28
|
+
# Script directory
|
|
29
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
30
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
31
|
+
|
|
32
|
+
# Counters
|
|
33
|
+
TOTAL_FILES=0
|
|
34
|
+
MODIFIED_FILES=0
|
|
35
|
+
SKIPPED_FILES=0
|
|
36
|
+
|
|
37
|
+
# Mode
|
|
38
|
+
DRY_RUN=true
|
|
39
|
+
|
|
40
|
+
# Parse arguments
|
|
41
|
+
for arg in "$@"; do
|
|
42
|
+
case $arg in
|
|
43
|
+
--apply)
|
|
44
|
+
DRY_RUN=false
|
|
45
|
+
shift
|
|
46
|
+
;;
|
|
47
|
+
--help|-h)
|
|
48
|
+
echo "Usage: $0 [--apply]"
|
|
49
|
+
echo ""
|
|
50
|
+
echo "Updates preview paths in markdown frontmatter to remove /assets/ prefix."
|
|
51
|
+
echo ""
|
|
52
|
+
echo "Options:"
|
|
53
|
+
echo " --apply Apply changes (default is dry run)"
|
|
54
|
+
echo " --help Show this help message"
|
|
55
|
+
exit 0
|
|
56
|
+
;;
|
|
57
|
+
esac
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
log_info() {
|
|
61
|
+
echo -e "${BLUE}[INFO]${NC} $1"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
log_success() {
|
|
65
|
+
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
log_warning() {
|
|
69
|
+
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
log_change() {
|
|
73
|
+
echo -e "${CYAN}[CHANGE]${NC} $1"
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
echo ""
|
|
77
|
+
echo -e "${BLUE}========================================${NC}"
|
|
78
|
+
echo -e "${BLUE}🔄 Preview Path Updater${NC}"
|
|
79
|
+
echo -e "${BLUE}========================================${NC}"
|
|
80
|
+
echo ""
|
|
81
|
+
|
|
82
|
+
if [ "$DRY_RUN" = true ]; then
|
|
83
|
+
log_warning "DRY RUN MODE - No files will be modified"
|
|
84
|
+
log_info "Run with --apply to make changes"
|
|
85
|
+
else
|
|
86
|
+
log_warning "APPLY MODE - Files will be modified"
|
|
87
|
+
fi
|
|
88
|
+
echo ""
|
|
89
|
+
|
|
90
|
+
# Find all markdown files in pages directory
|
|
91
|
+
find "$PROJECT_ROOT/pages" -name "*.md" -type f | while read -r file; do
|
|
92
|
+
TOTAL_FILES=$((TOTAL_FILES + 1))
|
|
93
|
+
|
|
94
|
+
# Check if file has a preview field with /assets/ prefix
|
|
95
|
+
if grep -q "^preview: /assets/" "$file" 2>/dev/null; then
|
|
96
|
+
# Extract current preview path
|
|
97
|
+
current_path=$(grep "^preview:" "$file" | head -1 | sed 's/^preview: //')
|
|
98
|
+
|
|
99
|
+
# Remove /assets/ prefix
|
|
100
|
+
new_path=$(echo "$current_path" | sed 's|^/assets/|/|')
|
|
101
|
+
|
|
102
|
+
log_change "$file"
|
|
103
|
+
echo " Old: $current_path"
|
|
104
|
+
echo " New: $new_path"
|
|
105
|
+
|
|
106
|
+
if [ "$DRY_RUN" = false ]; then
|
|
107
|
+
# Use sed to replace the preview line
|
|
108
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
109
|
+
# macOS sed requires empty string for -i
|
|
110
|
+
sed -i '' "s|^preview: /assets/|preview: /|" "$file"
|
|
111
|
+
else
|
|
112
|
+
# Linux sed
|
|
113
|
+
sed -i "s|^preview: /assets/|preview: /|" "$file"
|
|
114
|
+
fi
|
|
115
|
+
log_success "Updated: $file"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
MODIFIED_FILES=$((MODIFIED_FILES + 1))
|
|
119
|
+
else
|
|
120
|
+
SKIPPED_FILES=$((SKIPPED_FILES + 1))
|
|
121
|
+
fi
|
|
122
|
+
done
|
|
123
|
+
|
|
124
|
+
echo ""
|
|
125
|
+
echo -e "${CYAN}========================================${NC}"
|
|
126
|
+
echo -e "${CYAN}📊 Summary${NC}"
|
|
127
|
+
echo -e "${CYAN}========================================${NC}"
|
|
128
|
+
|
|
129
|
+
# Re-count since subshell doesn't persist variables
|
|
130
|
+
MODIFIED_COUNT=$(find "$PROJECT_ROOT/pages" -name "*.md" -type f -exec grep -l "^preview: /assets/" {} \; 2>/dev/null | wc -l | tr -d ' ')
|
|
131
|
+
TOTAL_COUNT=$(find "$PROJECT_ROOT/pages" -name "*.md" -type f | wc -l | tr -d ' ')
|
|
132
|
+
|
|
133
|
+
if [ "$DRY_RUN" = true ]; then
|
|
134
|
+
echo " Files to update: $MODIFIED_COUNT"
|
|
135
|
+
echo " Total markdown files: $TOTAL_COUNT"
|
|
136
|
+
echo ""
|
|
137
|
+
log_info "Run with --apply to make these changes"
|
|
138
|
+
else
|
|
139
|
+
# After applying, count should be 0
|
|
140
|
+
REMAINING=$(find "$PROJECT_ROOT/pages" -name "*.md" -type f -exec grep -l "^preview: /assets/" {} \; 2>/dev/null | wc -l | tr -d ' ')
|
|
141
|
+
echo " Files updated: $MODIFIED_COUNT"
|
|
142
|
+
echo " Files remaining: $REMAINING"
|
|
143
|
+
echo " Total markdown files: $TOTAL_COUNT"
|
|
144
|
+
fi
|
|
145
|
+
echo ""
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-theme-zer0
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.17.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Amr Abdel
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-12-
|
|
11
|
+
date: 2025-12-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: jekyll
|
|
@@ -80,9 +80,11 @@ files:
|
|
|
80
80
|
- _data/README.md
|
|
81
81
|
- _data/authors.yml
|
|
82
82
|
- _data/content_statistics.yml
|
|
83
|
+
- _data/features.yml
|
|
83
84
|
- _data/generate_statistics.rb
|
|
84
85
|
- _data/generate_statistics.sh
|
|
85
86
|
- _data/github-actions-example.yml
|
|
87
|
+
- _data/navigation/README.md
|
|
86
88
|
- _data/navigation/about.yml
|
|
87
89
|
- _data/navigation/docs.yml
|
|
88
90
|
- _data/navigation/home.yml
|
|
@@ -127,6 +129,7 @@ files:
|
|
|
127
129
|
- _includes/landing/landing-install-cards.html
|
|
128
130
|
- _includes/landing/landing-quick-links.html
|
|
129
131
|
- _includes/navigation/breadcrumbs.html
|
|
132
|
+
- _includes/navigation/nav-tree.html
|
|
130
133
|
- _includes/navigation/nav_list.html
|
|
131
134
|
- _includes/navigation/navbar.html
|
|
132
135
|
- _includes/navigation/sidebar-categories.html
|
|
@@ -157,6 +160,7 @@ files:
|
|
|
157
160
|
- _plugins/preview_image_generator.rb
|
|
158
161
|
- _plugins/theme_version.rb
|
|
159
162
|
- _sass/core/_docs.scss
|
|
163
|
+
- _sass/core/_nav-tree.scss
|
|
160
164
|
- _sass/core/_syntax.scss
|
|
161
165
|
- _sass/core/_theme.scss
|
|
162
166
|
- _sass/core/_variables.scss
|
|
@@ -183,6 +187,7 @@ files:
|
|
|
183
187
|
- assets/images/previews/published-documentation-library.png
|
|
184
188
|
- assets/images/previews/quantum-computing-explained-from-qubits-to-quantum.png
|
|
185
189
|
- assets/images/previews/science.png
|
|
190
|
+
- assets/images/previews/site-personalization-configuration.png
|
|
186
191
|
- assets/images/previews/technology.png
|
|
187
192
|
- assets/images/previews/the-complete-guide-to-startup-funding-in-2025.png
|
|
188
193
|
- assets/images/previews/the-remote-work-revolution-how-global-teams-are-re.png
|
|
@@ -201,12 +206,19 @@ files:
|
|
|
201
206
|
- assets/js/color-modes.js
|
|
202
207
|
- assets/js/docs.min.js
|
|
203
208
|
- assets/js/halfmoon.js
|
|
209
|
+
- assets/js/modules/navigation/config.js
|
|
210
|
+
- assets/js/modules/navigation/focus.js
|
|
211
|
+
- assets/js/modules/navigation/gestures.js
|
|
212
|
+
- assets/js/modules/navigation/index.js
|
|
213
|
+
- assets/js/modules/navigation/keyboard.js
|
|
214
|
+
- assets/js/modules/navigation/scroll-spy.js
|
|
215
|
+
- assets/js/modules/navigation/sidebar-state.js
|
|
216
|
+
- assets/js/modules/navigation/smooth-scroll.js
|
|
204
217
|
- assets/js/myScript.js
|
|
205
218
|
- assets/js/nanobar.min.js
|
|
206
219
|
- assets/js/particles-source.js
|
|
207
220
|
- assets/js/particles.js
|
|
208
221
|
- assets/js/side-bar-folders.js
|
|
209
|
-
- assets/js/sidebar.js
|
|
210
222
|
- assets/particles.json
|
|
211
223
|
- scripts/README.md
|
|
212
224
|
- scripts/analyze-commits.sh
|
|
@@ -230,6 +242,7 @@ files:
|
|
|
230
242
|
- scripts/lib/preview_generator.py
|
|
231
243
|
- scripts/lib/validation.sh
|
|
232
244
|
- scripts/lib/version.sh
|
|
245
|
+
- scripts/migrate-nav-modes.sh
|
|
233
246
|
- scripts/release
|
|
234
247
|
- scripts/setup.sh
|
|
235
248
|
- scripts/test-auto-version.sh
|
|
@@ -244,6 +257,7 @@ files:
|
|
|
244
257
|
- scripts/test/lib/test_validation.sh
|
|
245
258
|
- scripts/test/lib/test_version.sh
|
|
246
259
|
- scripts/test/theme/validate
|
|
260
|
+
- scripts/update-preview-paths.sh
|
|
247
261
|
- scripts/utils/analyze-commits
|
|
248
262
|
- scripts/utils/fix-markdown
|
|
249
263
|
- scripts/utils/setup
|