jekyll-theme-zer0 0.22.21 → 0.22.22
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 +55 -0
- data/README.md +294 -23
- data/scripts/bin/install +717 -0
- data/scripts/bin/test +45 -2
- data/scripts/lib/install/README.md +63 -0
- data/scripts/lib/install/agents.sh +166 -0
- data/scripts/lib/install/ai/diagnose.sh +199 -0
- data/scripts/lib/install/ai/openai.sh +233 -0
- data/scripts/lib/install/ai/suggest.sh +182 -0
- data/scripts/lib/install/ai/wizard.sh +160 -0
- data/scripts/lib/install/config.sh +56 -0
- data/scripts/lib/install/deploy/README.md +52 -0
- data/scripts/lib/install/deploy/azure-swa.sh +50 -0
- data/scripts/lib/install/deploy/docker-prod.sh +71 -0
- data/scripts/lib/install/deploy/github-pages.sh +44 -0
- data/scripts/lib/install/deploy/registry.sh +190 -0
- data/scripts/lib/install/doctor.sh +301 -0
- data/scripts/lib/install/fs.sh +52 -0
- data/scripts/lib/install/logging.sh +33 -0
- data/scripts/lib/install/pages.sh +255 -0
- data/scripts/lib/install/platform.sh +71 -0
- data/scripts/lib/install/profile.sh +113 -0
- data/scripts/lib/install/template.sh +137 -0
- data/scripts/lib/install/upgrade.sh +184 -0
- data/scripts/lib/install/wizard_interactive.sh +189 -0
- metadata +24 -2
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =========================================================================
|
|
3
|
+
# scripts/lib/install/fs.sh
|
|
4
|
+
# =========================================================================
|
|
5
|
+
# Filesystem helpers for install.sh: idempotent file/directory copy with
|
|
6
|
+
# automatic timestamped backups when destination already exists.
|
|
7
|
+
#
|
|
8
|
+
# Required globals (set by install.sh before sourcing/use):
|
|
9
|
+
# $TARGET_DIR — used to compute relative paths in log messages
|
|
10
|
+
#
|
|
11
|
+
# Functions exported:
|
|
12
|
+
# copy_file_with_backup SRC DEST
|
|
13
|
+
# copy_directory_with_backup SRC DEST
|
|
14
|
+
# =========================================================================
|
|
15
|
+
|
|
16
|
+
# Copy a file, backing up the destination if it already exists.
|
|
17
|
+
copy_file_with_backup() {
|
|
18
|
+
local src="$1"
|
|
19
|
+
local dest="$2"
|
|
20
|
+
local relative_path="${dest#${TARGET_DIR:-}/}"
|
|
21
|
+
|
|
22
|
+
# Create destination directory if it doesn't exist
|
|
23
|
+
mkdir -p "$(dirname "$dest")"
|
|
24
|
+
|
|
25
|
+
# Backup existing file if it exists
|
|
26
|
+
if [[ -f "$dest" ]]; then
|
|
27
|
+
local backup_file="${dest}.backup.$(date +%Y%m%d_%H%M%S)"
|
|
28
|
+
log_warning "File exists, creating backup: $relative_path -> ${backup_file##*/}"
|
|
29
|
+
cp "$dest" "$backup_file"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Copy the file
|
|
33
|
+
cp "$src" "$dest"
|
|
34
|
+
log_info "Copied: $relative_path"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Copy a directory, backing up the destination if it already exists.
|
|
38
|
+
copy_directory_with_backup() {
|
|
39
|
+
local src="$1"
|
|
40
|
+
local dest="$2"
|
|
41
|
+
local relative_path="${dest#${TARGET_DIR:-}/}"
|
|
42
|
+
|
|
43
|
+
if [[ -d "$dest" ]]; then
|
|
44
|
+
local backup_dir="${dest}.backup.$(date +%Y%m%d_%H%M%S)"
|
|
45
|
+
log_warning "Directory exists, creating backup: $relative_path -> ${backup_dir##*/}"
|
|
46
|
+
cp -r "$dest" "$backup_dir"
|
|
47
|
+
rm -rf "$dest"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
cp -r "$src" "$dest"
|
|
51
|
+
log_info "Copied directory: $relative_path"
|
|
52
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =========================================================================
|
|
3
|
+
# scripts/lib/install/logging.sh
|
|
4
|
+
# =========================================================================
|
|
5
|
+
# Logging shim for install.sh. Provides log_info / log_success /
|
|
6
|
+
# log_warning / log_error names used throughout install.sh while
|
|
7
|
+
# delegating to scripts/lib/common.sh primitives where available.
|
|
8
|
+
#
|
|
9
|
+
# WHY a shim instead of a direct sed-rename?
|
|
10
|
+
# - install.sh has ~300+ call sites to log_info/log_success/log_warning/log_error
|
|
11
|
+
# - Common.sh uses different verbs (info/success/warn/error) and `error` exits
|
|
12
|
+
# - A thin shim preserves behavior exactly while letting future code use
|
|
13
|
+
# either vocabulary.
|
|
14
|
+
#
|
|
15
|
+
# Source order requirement:
|
|
16
|
+
# This file must be sourced AFTER scripts/lib/common.sh so the
|
|
17
|
+
# colour variables (RED/GREEN/YELLOW/BLUE/NC) are defined.
|
|
18
|
+
#
|
|
19
|
+
# Compatibility: bash 3.2+ (macOS default)
|
|
20
|
+
# =========================================================================
|
|
21
|
+
|
|
22
|
+
# Define colours if common.sh wasn't sourced (safe defaults).
|
|
23
|
+
RED="${RED:-\033[0;31m}"
|
|
24
|
+
GREEN="${GREEN:-\033[0;32m}"
|
|
25
|
+
YELLOW="${YELLOW:-\033[1;33m}"
|
|
26
|
+
BLUE="${BLUE:-\033[0;34m}"
|
|
27
|
+
NC="${NC:-\033[0m}"
|
|
28
|
+
|
|
29
|
+
# install.sh-style logging — identical output to the original block.
|
|
30
|
+
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
|
|
31
|
+
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
|
|
32
|
+
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
|
|
33
|
+
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/lib/install/pages.sh
|
|
3
|
+
#
|
|
4
|
+
# Starter-page generator for jekyll-theme-zer0 installations.
|
|
5
|
+
# Replaces 8 near-identical create_*_page heredoc functions with a single
|
|
6
|
+
# manifest-driven renderer.
|
|
7
|
+
#
|
|
8
|
+
# Required env (from install.conf via config.sh):
|
|
9
|
+
# TARGET_DIR, THEME_NAME, THEME_DISPLAY_NAME, DEFAULT_URL, GITHUB_URL
|
|
10
|
+
#
|
|
11
|
+
# Required functions (from template.sh):
|
|
12
|
+
# create_from_template <template_relpath> <dest_abspath> <fallback_content>
|
|
13
|
+
#
|
|
14
|
+
# Public API:
|
|
15
|
+
# render_starter_pages - generate all default pages + admin
|
|
16
|
+
# render_admin_settings_pages - generate just the _about/settings/* pages
|
|
17
|
+
|
|
18
|
+
# ---------- Manifest --------------------------------------------------------
|
|
19
|
+
# Format (pipe-separated, no spaces around |):
|
|
20
|
+
# <template_relpath>|<dest_relpath>|<mkdir_relpath>|<fallback_func>
|
|
21
|
+
# Empty <mkdir_relpath> = no mkdir; empty <fallback_func> = no fallback.
|
|
22
|
+
_starter_pages_manifest() {
|
|
23
|
+
cat <<'MANIFEST'
|
|
24
|
+
pages/quickstart.md.template|pages/quickstart/index.md|pages/quickstart|_fallback_quickstart
|
|
25
|
+
pages/docs-index.md.template|pages/_docs/index.md|pages/_docs|_fallback_docs_index
|
|
26
|
+
pages/configuration.md.template|pages/_docs/configuration/index.md|pages/_docs/configuration|
|
|
27
|
+
pages/troubleshooting.md.template|pages/_docs/troubleshooting.md|pages/_docs|
|
|
28
|
+
pages/about.md.template|pages/_about/index.md|pages/_about|_fallback_about
|
|
29
|
+
pages/blog.md.template|pages/blog.md||_fallback_blog
|
|
30
|
+
MANIFEST
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_admin_settings_pages() {
|
|
34
|
+
echo "theme config navigation collections analytics environment"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# ---------- Fallback content (only used when template missing) --------------
|
|
38
|
+
_fallback_quickstart() {
|
|
39
|
+
cat <<EOF
|
|
40
|
+
---
|
|
41
|
+
layout: default
|
|
42
|
+
title: Quick Start
|
|
43
|
+
permalink: /quickstart/
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# Quick Start Guide
|
|
47
|
+
|
|
48
|
+
Get your site up and running in just a few minutes!
|
|
49
|
+
|
|
50
|
+
## Prerequisites
|
|
51
|
+
|
|
52
|
+
Before you begin, make sure you have:
|
|
53
|
+
|
|
54
|
+
- **Docker Desktop** installed ([download](https://www.docker.com/products/docker-desktop))
|
|
55
|
+
- **Git** installed ([download](https://git-scm.com/))
|
|
56
|
+
|
|
57
|
+
## 1. Start Development Server
|
|
58
|
+
|
|
59
|
+
### Using Docker (Recommended)
|
|
60
|
+
|
|
61
|
+
\`\`\`bash
|
|
62
|
+
docker-compose up
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
Your site will be available at **${DEFAULT_URL}**
|
|
66
|
+
|
|
67
|
+
### Using Local Ruby
|
|
68
|
+
|
|
69
|
+
\`\`\`bash
|
|
70
|
+
bundle install
|
|
71
|
+
bundle exec jekyll serve
|
|
72
|
+
\`\`\`
|
|
73
|
+
|
|
74
|
+
## 2. Customize Your Site
|
|
75
|
+
|
|
76
|
+
Edit \`_config.yml\` to personalize your site:
|
|
77
|
+
|
|
78
|
+
\`\`\`yaml
|
|
79
|
+
title: Your Site Title
|
|
80
|
+
description: Your site description
|
|
81
|
+
author: Your Name
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
## 3. Add Content
|
|
85
|
+
|
|
86
|
+
- Create posts in \`pages/_posts/\`
|
|
87
|
+
- Create documentation in \`pages/_docs/\`
|
|
88
|
+
- Add static pages in \`pages/\`
|
|
89
|
+
|
|
90
|
+
## Next Steps
|
|
91
|
+
|
|
92
|
+
- [Read the Documentation](/docs/) - Learn about all features
|
|
93
|
+
- [Explore Configuration](/docs/configuration/) - Customize your site
|
|
94
|
+
- [Learn about Layouts](/docs/layouts/) - Understand page layouts
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
Need help? Check the [troubleshooting guide](/docs/troubleshooting/) or [open an issue](${GITHUB_URL}/issues).
|
|
99
|
+
EOF
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
_fallback_docs_index() {
|
|
103
|
+
cat <<EOF
|
|
104
|
+
---
|
|
105
|
+
layout: default
|
|
106
|
+
title: Documentation
|
|
107
|
+
permalink: /docs/
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
# Documentation
|
|
111
|
+
|
|
112
|
+
Welcome to the ${THEME_NAME} theme documentation. Here you'll find everything you need to build and customize your Jekyll site.
|
|
113
|
+
|
|
114
|
+
## Getting Started
|
|
115
|
+
|
|
116
|
+
<div class="row">
|
|
117
|
+
<div class="col-md-6 mb-3">
|
|
118
|
+
|
|
119
|
+
### Installation
|
|
120
|
+
|
|
121
|
+
The theme supports multiple installation methods:
|
|
122
|
+
|
|
123
|
+
- **Docker** (Recommended) - Zero dependencies
|
|
124
|
+
- **Remote Theme** - For GitHub Pages
|
|
125
|
+
- **Gem** - Traditional Ruby installation
|
|
126
|
+
|
|
127
|
+
[View Installation Guide →](/quickstart/)
|
|
128
|
+
|
|
129
|
+
</div>
|
|
130
|
+
<div class="col-md-6 mb-3">
|
|
131
|
+
|
|
132
|
+
### Configuration
|
|
133
|
+
|
|
134
|
+
Customize your site with \`_config.yml\`:
|
|
135
|
+
|
|
136
|
+
- Site title and description
|
|
137
|
+
- Navigation menus
|
|
138
|
+
- Social links
|
|
139
|
+
- Analytics integration
|
|
140
|
+
|
|
141
|
+
[View Configuration Guide →](/docs/configuration/)
|
|
142
|
+
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
## Need Help?
|
|
147
|
+
|
|
148
|
+
- [Troubleshooting Guide](/docs/troubleshooting/)
|
|
149
|
+
- [GitHub Issues](${GITHUB_URL}/issues)
|
|
150
|
+
- [GitHub Discussions](${GITHUB_URL}/discussions)
|
|
151
|
+
EOF
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_fallback_about() {
|
|
155
|
+
cat <<EOF
|
|
156
|
+
---
|
|
157
|
+
layout: default
|
|
158
|
+
title: About
|
|
159
|
+
permalink: /about/
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
# About This Site
|
|
163
|
+
|
|
164
|
+
This site is built with the **${THEME_DISPLAY_NAME}** - a professional Jekyll theme designed for GitHub Pages with Bootstrap 5.3.
|
|
165
|
+
|
|
166
|
+
## Theme Features
|
|
167
|
+
|
|
168
|
+
- ✅ Bootstrap 5.3 integration
|
|
169
|
+
- ✅ Dark/Light mode toggle
|
|
170
|
+
- ✅ Docker support
|
|
171
|
+
- ✅ GitHub Pages compatible
|
|
172
|
+
- ✅ SEO optimized
|
|
173
|
+
|
|
174
|
+
## Learn More
|
|
175
|
+
|
|
176
|
+
- [Theme Documentation](/docs/)
|
|
177
|
+
- [GitHub Repository](${GITHUB_URL})
|
|
178
|
+
- [Report an Issue](${GITHUB_URL}/issues)
|
|
179
|
+
|
|
180
|
+
## Customizing This Page
|
|
181
|
+
|
|
182
|
+
Edit \`pages/_about/index.md\` to customize this page with your own content.
|
|
183
|
+
EOF
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
_fallback_blog() {
|
|
187
|
+
cat <<'EOF'
|
|
188
|
+
---
|
|
189
|
+
layout: default
|
|
190
|
+
title: Blog
|
|
191
|
+
permalink: /blog/
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
# Blog
|
|
195
|
+
|
|
196
|
+
Welcome to the blog. Create your first post to get started!
|
|
197
|
+
|
|
198
|
+
## Creating Posts
|
|
199
|
+
|
|
200
|
+
Create markdown files in `pages/_posts/` with the format:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
YYYY-MM-DD-your-post-title.md
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Recent Posts
|
|
207
|
+
|
|
208
|
+
{% for post in site.posts limit:5 %}
|
|
209
|
+
- [{{ post.title }}]({{ post.url }}) - {{ post.date | date: "%B %d, %Y" }}
|
|
210
|
+
{% endfor %}
|
|
211
|
+
|
|
212
|
+
{% if site.posts.size == 0 %}
|
|
213
|
+
*No posts yet. Create your first post to see it here!*
|
|
214
|
+
{% endif %}
|
|
215
|
+
EOF
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
# ---------- Public renderers ------------------------------------------------
|
|
219
|
+
render_admin_settings_pages() {
|
|
220
|
+
local admin_dir="$TARGET_DIR/pages/_about/settings"
|
|
221
|
+
mkdir -p "$admin_dir"
|
|
222
|
+
|
|
223
|
+
log_info "Creating admin settings pages..."
|
|
224
|
+
local page
|
|
225
|
+
for page in $(_admin_settings_pages); do
|
|
226
|
+
create_from_template "pages/admin/${page}.md.template" "$admin_dir/${page}.md" ""
|
|
227
|
+
done
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
render_starter_pages() {
|
|
231
|
+
log_info "Creating essential starter pages..."
|
|
232
|
+
mkdir -p "$TARGET_DIR/pages"
|
|
233
|
+
|
|
234
|
+
local tmpl dest mkdir_rel fb_func fallback
|
|
235
|
+
while IFS='|' read -r tmpl dest mkdir_rel fb_func; do
|
|
236
|
+
[ -z "$tmpl" ] && continue
|
|
237
|
+
[ -n "$mkdir_rel" ] && mkdir -p "$TARGET_DIR/$mkdir_rel"
|
|
238
|
+
if [ -n "$fb_func" ] && declare -f "$fb_func" >/dev/null 2>&1; then
|
|
239
|
+
fallback="$("$fb_func")"
|
|
240
|
+
else
|
|
241
|
+
fallback=""
|
|
242
|
+
fi
|
|
243
|
+
create_from_template "$tmpl" "$TARGET_DIR/$dest" "$fallback"
|
|
244
|
+
done <<MANIFEST_EOF
|
|
245
|
+
$(_starter_pages_manifest)
|
|
246
|
+
MANIFEST_EOF
|
|
247
|
+
|
|
248
|
+
render_admin_settings_pages
|
|
249
|
+
|
|
250
|
+
log_success "Starter pages created"
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
# Backward-compatible aliases (legacy install.sh call sites)
|
|
254
|
+
create_starter_pages() { render_starter_pages "$@"; }
|
|
255
|
+
create_admin_pages() { render_admin_settings_pages "$@"; }
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =========================================================================
|
|
3
|
+
# scripts/lib/install/platform.sh
|
|
4
|
+
# =========================================================================
|
|
5
|
+
# Platform / Ruby detection helpers used by install.sh.
|
|
6
|
+
#
|
|
7
|
+
# Bash 3.2-compatible — no `declare -A`, no `=~` capture groups.
|
|
8
|
+
#
|
|
9
|
+
# Functions exported:
|
|
10
|
+
# detect_os -> Darwin | Linux | CYGWIN | MINGW | unknown
|
|
11
|
+
# detect_ruby_version -> e.g. "2.6.8" or "none"
|
|
12
|
+
# ruby_version_lt_27 -> exit 0 when ruby < 2.7
|
|
13
|
+
# needs_macos_gemfile -> exit 0 when macOS + ruby < 2.7
|
|
14
|
+
# detect_platform -> auto | wsl | macos | linux | unknown
|
|
15
|
+
# =========================================================================
|
|
16
|
+
|
|
17
|
+
# Returns: Darwin | Linux | CYGWIN | MINGW | unknown
|
|
18
|
+
detect_os() {
|
|
19
|
+
uname -s 2>/dev/null || echo "unknown"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# Returns the ruby version string (e.g. "2.6.8"), or "none" if ruby is absent.
|
|
23
|
+
detect_ruby_version() {
|
|
24
|
+
if ! command -v ruby >/dev/null 2>&1; then
|
|
25
|
+
echo "none"
|
|
26
|
+
return
|
|
27
|
+
fi
|
|
28
|
+
# ruby --version prints: ruby 2.6.8p205 (2021-07-07 ...) [platform]
|
|
29
|
+
# We want "2.6.8" — strip the trailing pNNN patch indicator via sed.
|
|
30
|
+
ruby --version 2>/dev/null | awk '{print $2}' | sed 's/p[0-9]*//' | sed 's/-.*//' | tr -d '\r'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
# Returns 0 (true) if the current Ruby version is < 2.7.0, 1 (false) otherwise.
|
|
34
|
+
# Uses awk so arithmetic is safe even with partial version strings.
|
|
35
|
+
ruby_version_lt_27() {
|
|
36
|
+
local ver
|
|
37
|
+
ver=$(detect_ruby_version)
|
|
38
|
+
[ "$ver" = "none" ] && return 1 # no ruby → don't apply macOS caps
|
|
39
|
+
awk -v ver="$ver" 'BEGIN {
|
|
40
|
+
n = split(ver, a, ".")
|
|
41
|
+
if (a[1]+0 == 2 && a[2]+0 < 7) exit 0
|
|
42
|
+
exit 1
|
|
43
|
+
}'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Returns 0 (true) when running on macOS with system Ruby < 2.7.
|
|
47
|
+
# This is the condition that triggers use of Gemfile.macos.template.
|
|
48
|
+
needs_macos_gemfile() {
|
|
49
|
+
local os
|
|
50
|
+
os=$(detect_os)
|
|
51
|
+
[ "$os" = "Darwin" ] && ruby_version_lt_27
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Detect runtime platform. Honours $PLATFORM if explicitly set.
|
|
55
|
+
# Returns: macos | linux | wsl | unknown
|
|
56
|
+
detect_platform() {
|
|
57
|
+
if [[ "${PLATFORM:-auto}" != "auto" ]]; then
|
|
58
|
+
echo "$PLATFORM"
|
|
59
|
+
return
|
|
60
|
+
fi
|
|
61
|
+
# WSL detection (check before generic Linux)
|
|
62
|
+
if grep -qiE '(microsoft|wsl)' /proc/version 2>/dev/null; then
|
|
63
|
+
echo "wsl"
|
|
64
|
+
elif [[ "$(uname -s)" == "Darwin" ]]; then
|
|
65
|
+
echo "macos"
|
|
66
|
+
elif [[ "$(uname -s)" == "Linux" ]]; then
|
|
67
|
+
echo "linux"
|
|
68
|
+
else
|
|
69
|
+
echo "unknown"
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# scripts/lib/install/profile.sh
|
|
3
|
+
#
|
|
4
|
+
# Minimal pure-bash YAML reader for templates/profiles/*.yml.
|
|
5
|
+
# Bash 3.2 compatible. Schema is intentionally simple (scalar key/value
|
|
6
|
+
# + flat string lists) so we don't need yq/python.
|
|
7
|
+
#
|
|
8
|
+
# Public API:
|
|
9
|
+
# profiles_dir <REPO_ROOT> — absolute path to profiles dir
|
|
10
|
+
# list_profile_names <REPO_ROOT> — newline-separated profile slugs
|
|
11
|
+
# profile_path <REPO_ROOT> <name> — absolute path to a profile yml
|
|
12
|
+
# profile_get_scalar <file> <key> — print a scalar value or empty
|
|
13
|
+
# profile_get_list <file> <key> — print list items, one per line
|
|
14
|
+
# profile_print_summary <file> — pretty-print full profile
|
|
15
|
+
|
|
16
|
+
profiles_dir() {
|
|
17
|
+
local repo_root="$1"
|
|
18
|
+
echo "$repo_root/templates/profiles"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
list_profile_names() {
|
|
22
|
+
local repo_root="$1"
|
|
23
|
+
local dir
|
|
24
|
+
dir="$(profiles_dir "$repo_root")"
|
|
25
|
+
[ -d "$dir" ] || return 1
|
|
26
|
+
# List *.yml stems, sorted, excluding any leading-dot files
|
|
27
|
+
( cd "$dir" && for f in *.yml; do
|
|
28
|
+
[ -e "$f" ] || continue
|
|
29
|
+
echo "${f%.yml}"
|
|
30
|
+
done ) | sort
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
profile_path() {
|
|
34
|
+
local repo_root="$1" name="$2"
|
|
35
|
+
local p
|
|
36
|
+
p="$(profiles_dir "$repo_root")/${name}.yml"
|
|
37
|
+
[ -f "$p" ] || return 1
|
|
38
|
+
echo "$p"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Extract a scalar value: lines like `key: value`. Strips surrounding
|
|
42
|
+
# whitespace and quotes. Ignores list lines (starting with `-`).
|
|
43
|
+
profile_get_scalar() {
|
|
44
|
+
local file="$1" key="$2"
|
|
45
|
+
[ -f "$file" ] || return 1
|
|
46
|
+
awk -v k="$key" '
|
|
47
|
+
# match " key: value" or "key: value" at top level (no leading dash)
|
|
48
|
+
$0 ~ "^[[:space:]]*" k "[[:space:]]*:" {
|
|
49
|
+
sub("^[[:space:]]*" k "[[:space:]]*:[[:space:]]*", "")
|
|
50
|
+
# strip trailing comments
|
|
51
|
+
sub(/[[:space:]]+#.*$/, "")
|
|
52
|
+
# strip surrounding quotes
|
|
53
|
+
gsub(/^["'\'']|["'\'']$/, "")
|
|
54
|
+
print
|
|
55
|
+
exit
|
|
56
|
+
}
|
|
57
|
+
' "$file"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Extract a flat list under a key. Returns nothing for `key: []` or missing.
|
|
61
|
+
profile_get_list() {
|
|
62
|
+
local file="$1" key="$2"
|
|
63
|
+
[ -f "$file" ] || return 1
|
|
64
|
+
awk -v k="$key" '
|
|
65
|
+
BEGIN { inblock = 0 }
|
|
66
|
+
# Start: "key:" line with nothing (or just a comment) after it
|
|
67
|
+
$0 ~ "^[[:space:]]*" k "[[:space:]]*:[[:space:]]*(#.*)?$" {
|
|
68
|
+
inblock = 1
|
|
69
|
+
next
|
|
70
|
+
}
|
|
71
|
+
inblock {
|
|
72
|
+
# End block on next non-list, non-blank, non-indented line
|
|
73
|
+
if ($0 ~ /^[[:space:]]*-[[:space:]]+/) {
|
|
74
|
+
line = $0
|
|
75
|
+
sub(/^[[:space:]]*-[[:space:]]+/, "", line)
|
|
76
|
+
sub(/[[:space:]]+#.*$/, "", line)
|
|
77
|
+
gsub(/^["'\'']|["'\'']$/, "", line)
|
|
78
|
+
print line
|
|
79
|
+
next
|
|
80
|
+
}
|
|
81
|
+
if ($0 ~ /^[[:space:]]*#/) next
|
|
82
|
+
if ($0 ~ /^[[:space:]]*$/) next
|
|
83
|
+
inblock = 0
|
|
84
|
+
}
|
|
85
|
+
' "$file"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
profile_print_summary() {
|
|
89
|
+
local file="$1"
|
|
90
|
+
[ -f "$file" ] || { echo "(profile file not found: $file)" >&2; return 1; }
|
|
91
|
+
local name display desc legacy rec
|
|
92
|
+
name="$(profile_get_scalar "$file" name)"
|
|
93
|
+
display="$(profile_get_scalar "$file" display_name)"
|
|
94
|
+
desc="$(profile_get_scalar "$file" description)"
|
|
95
|
+
legacy="$(profile_get_scalar "$file" legacy_flag)"
|
|
96
|
+
rec="$(profile_get_scalar "$file" recommended_for)"
|
|
97
|
+
printf ' %-9s %s\n' "$name" "$display"
|
|
98
|
+
[ -n "$desc" ] && printf ' %s\n' "$desc"
|
|
99
|
+
[ -n "$legacy" ] && printf ' → install.sh %s\n' "$legacy"
|
|
100
|
+
[ -n "$rec" ] && printf ' For: %s\n' "$rec"
|
|
101
|
+
local includes excludes
|
|
102
|
+
includes="$(profile_get_list "$file" includes)"
|
|
103
|
+
excludes="$(profile_get_list "$file" excludes)"
|
|
104
|
+
if [ -n "$includes" ]; then
|
|
105
|
+
printf ' Includes:\n'
|
|
106
|
+
echo "$includes" | sed 's/^/ - /'
|
|
107
|
+
fi
|
|
108
|
+
if [ -n "$excludes" ]; then
|
|
109
|
+
printf ' Excludes:\n'
|
|
110
|
+
echo "$excludes" | sed 's/^/ - /'
|
|
111
|
+
fi
|
|
112
|
+
echo
|
|
113
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =========================================================================
|
|
3
|
+
# scripts/lib/install/template.sh
|
|
4
|
+
# =========================================================================
|
|
5
|
+
# Template rendering for install.sh.
|
|
6
|
+
#
|
|
7
|
+
# Functions exported:
|
|
8
|
+
# render_template TEMPLATE_FILE [OUTPUT_FILE]
|
|
9
|
+
# Replace {{VAR_NAME}} placeholders. If OUTPUT_FILE omitted, writes
|
|
10
|
+
# to stdout.
|
|
11
|
+
#
|
|
12
|
+
# create_from_template TEMPLATE_REL OUTPUT_FILE [FALLBACK_CONTENT]
|
|
13
|
+
# Resolution order:
|
|
14
|
+
# 1. Local templates ($TEMPLATES_DIR/$TEMPLATE_REL)
|
|
15
|
+
# 2. Remote fetch from $GITHUB_RAW_URL/templates/$TEMPLATE_REL
|
|
16
|
+
# (only when REMOTE_INSTALL=true)
|
|
17
|
+
# 3. FALLBACK_CONTENT (literal string)
|
|
18
|
+
# Existing OUTPUT_FILE is preserved (skipped with a warning).
|
|
19
|
+
#
|
|
20
|
+
# templates_available
|
|
21
|
+
# Returns 0 when $TEMPLATES_DIR is set and points to an existing dir.
|
|
22
|
+
#
|
|
23
|
+
# Required globals (provided by install.sh / install.conf):
|
|
24
|
+
# THEME_NAME, THEME_GEM_NAME, THEME_DISPLAY_NAME,
|
|
25
|
+
# GITHUB_USER, GITHUB_REPO, GITHUB_URL, GITHUB_RAW_URL,
|
|
26
|
+
# DEFAULT_PORT, DEFAULT_URL,
|
|
27
|
+
# JEKYLL_VERSION, FFI_VERSION, WEBRICK_VERSION, COMMONMARKER_VERSION,
|
|
28
|
+
# GITHUB_PAGES_MAX_VERSION, COMMONMARKER_MACOS_VERSION,
|
|
29
|
+
# RUBY_MIN_VERSION_MACOS, INSTALL_MODE, REMOTE_INSTALL, TEMPLATES_DIR
|
|
30
|
+
#
|
|
31
|
+
# Optional globals (used when set):
|
|
32
|
+
# FORK_GITHUB_USER, FORK_SITE_NAME, FORK_AUTHOR, FORK_EMAIL,
|
|
33
|
+
# SITE_TITLE, SITE_DESCRIPTION, SITE_AUTHOR, SITE_EMAIL,
|
|
34
|
+
# REPOSITORY_NAME
|
|
35
|
+
# =========================================================================
|
|
36
|
+
|
|
37
|
+
# Render a template file, replacing {{VAR_NAME}} placeholders.
|
|
38
|
+
render_template() {
|
|
39
|
+
local template_file="$1"
|
|
40
|
+
local output_file="${2:-}"
|
|
41
|
+
|
|
42
|
+
if [[ ! -f "$template_file" ]]; then
|
|
43
|
+
return 1
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
local content
|
|
47
|
+
content=$(cat "$template_file")
|
|
48
|
+
|
|
49
|
+
# Replace all known placeholders. Order matches the original install.sh
|
|
50
|
+
# implementation to guarantee identical output.
|
|
51
|
+
content=$(echo "$content" | sed \
|
|
52
|
+
-e "s|{{THEME_NAME}}|${THEME_NAME}|g" \
|
|
53
|
+
-e "s|{{THEME_GEM_NAME}}|${THEME_GEM_NAME}|g" \
|
|
54
|
+
-e "s|{{THEME_DISPLAY_NAME}}|${THEME_DISPLAY_NAME}|g" \
|
|
55
|
+
-e "s|{{GITHUB_USER}}|${FORK_GITHUB_USER:-$GITHUB_USER}|g" \
|
|
56
|
+
-e "s|{{GITHUB_REPO}}|${GITHUB_REPO}|g" \
|
|
57
|
+
-e "s|{{GITHUB_URL}}|${GITHUB_URL}|g" \
|
|
58
|
+
-e "s|{{GITHUB_RAW_URL}}|${GITHUB_RAW_URL}|g" \
|
|
59
|
+
-e "s|{{DEFAULT_PORT}}|${DEFAULT_PORT}|g" \
|
|
60
|
+
-e "s|{{DEFAULT_URL}}|${DEFAULT_URL}|g" \
|
|
61
|
+
-e "s|{{JEKYLL_VERSION}}|${JEKYLL_VERSION}|g" \
|
|
62
|
+
-e "s|{{FFI_VERSION}}|${FFI_VERSION}|g" \
|
|
63
|
+
-e "s|{{WEBRICK_VERSION}}|${WEBRICK_VERSION}|g" \
|
|
64
|
+
-e "s|{{COMMONMARKER_VERSION}}|${COMMONMARKER_VERSION}|g" \
|
|
65
|
+
-e "s|{{GITHUB_PAGES_MAX_VERSION}}|${GITHUB_PAGES_MAX_VERSION:-232}|g" \
|
|
66
|
+
-e "s|{{COMMONMARKER_MACOS_VERSION}}|${COMMONMARKER_MACOS_VERSION:-~> 0.23}|g" \
|
|
67
|
+
-e "s|{{RUBY_MIN_VERSION_MACOS}}|${RUBY_MIN_VERSION_MACOS:-2.6.0}|g" \
|
|
68
|
+
-e "s|{{SITE_TITLE}}|${FORK_SITE_NAME:-${SITE_TITLE:-My Jekyll Site}}|g" \
|
|
69
|
+
-e "s|{{SITE_DESCRIPTION}}|${SITE_DESCRIPTION:-A Jekyll site built with ${THEME_NAME}}|g" \
|
|
70
|
+
-e "s|{{SITE_AUTHOR}}|${FORK_AUTHOR:-${SITE_AUTHOR:-Site Author}}|g" \
|
|
71
|
+
-e "s|{{SITE_EMAIL}}|${FORK_EMAIL:-${SITE_EMAIL:-your@email.com}}|g" \
|
|
72
|
+
-e "s|{{CURRENT_DATE}}|$(date +%Y-%m-%d)|g" \
|
|
73
|
+
-e "s|{{CURRENT_YEAR}}|$(date +%Y)|g" \
|
|
74
|
+
-e "s|{{REPOSITORY_NAME}}|${REPOSITORY_NAME:-$THEME_NAME}|g" \
|
|
75
|
+
-e "s|{{RAW_GITHUB_URL}}|${GITHUB_RAW_URL}|g" \
|
|
76
|
+
-e "s|{{FORK_GITHUB_USER}}|${FORK_GITHUB_USER:-${GITHUB_USER}}|g" \
|
|
77
|
+
-e "s|{{INSTALL_MODE}}|${INSTALL_MODE:-full}|g" \
|
|
78
|
+
-e "s|{{GITHUB_PAGES_URL}}|https://${FORK_GITHUB_USER:-${GITHUB_USER}}.github.io/${REPOSITORY_NAME:-$THEME_NAME}|g")
|
|
79
|
+
|
|
80
|
+
if [[ -n "$output_file" ]]; then
|
|
81
|
+
mkdir -p "$(dirname "$output_file")"
|
|
82
|
+
echo "$content" > "$output_file"
|
|
83
|
+
else
|
|
84
|
+
echo "$content"
|
|
85
|
+
fi
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# Create a file from template with automatic fallback to embedded content.
|
|
89
|
+
create_from_template() {
|
|
90
|
+
local template_path="$1"
|
|
91
|
+
local output_file="$2"
|
|
92
|
+
local fallback_content="${3:-}"
|
|
93
|
+
|
|
94
|
+
# Skip if output already exists
|
|
95
|
+
if [[ -f "$output_file" ]]; then
|
|
96
|
+
log_warning "$(basename "$output_file") already exists, skipping to preserve content"
|
|
97
|
+
return 0
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Try local template first
|
|
101
|
+
if [[ -n "${TEMPLATES_DIR:-}" ]] && [[ -f "$TEMPLATES_DIR/$template_path" ]]; then
|
|
102
|
+
render_template "$TEMPLATES_DIR/$template_path" "$output_file"
|
|
103
|
+
log_info "Created $(basename "$output_file") from template"
|
|
104
|
+
return 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Try to fetch from GitHub for remote installs
|
|
108
|
+
if [[ "${REMOTE_INSTALL:-false}" == "true" ]]; then
|
|
109
|
+
local remote_url="${GITHUB_RAW_URL}/templates/$template_path"
|
|
110
|
+
local remote_content
|
|
111
|
+
if remote_content=$(curl -fsSL "$remote_url" 2>/dev/null); then
|
|
112
|
+
local temp_file
|
|
113
|
+
temp_file=$(mktemp)
|
|
114
|
+
echo "$remote_content" > "$temp_file"
|
|
115
|
+
render_template "$temp_file" "$output_file"
|
|
116
|
+
rm -f "$temp_file"
|
|
117
|
+
log_info "Created $(basename "$output_file") from remote template"
|
|
118
|
+
return 0
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Use fallback content if provided
|
|
123
|
+
if [[ -n "$fallback_content" ]]; then
|
|
124
|
+
mkdir -p "$(dirname "$output_file")"
|
|
125
|
+
echo "$fallback_content" > "$output_file"
|
|
126
|
+
log_info "Created $(basename "$output_file") from fallback"
|
|
127
|
+
return 0
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
log_warning "Could not create $(basename "$output_file") (no template or fallback)"
|
|
131
|
+
return 1
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Check if templates are available (TEMPLATES_DIR set + directory exists).
|
|
135
|
+
templates_available() {
|
|
136
|
+
[[ -n "${TEMPLATES_DIR:-}" ]] && [[ -d "$TEMPLATES_DIR" ]]
|
|
137
|
+
}
|