#!/usr/bin/env sh set -eu ROOT_DIR="$(CDPATH= cd -- "$(dirname "$0")/../.." && pwd)" CALENDAR_DIR="$ROOT_DIR/calendar" DIST_DIR="$CALENDAR_DIR/dist" PORT=${PORT:-4173} SWIFT_SCRIPT="$CALENDAR_DIR/scripts/export-kindle-background.swift" THEMES_SOURCE="$CALENDAR_DIR/config/themes.json" THEME_FILTER="" ORIENTATION_FILTER="" print_usage() { cat <<'EOF' 用法: sh scripts/export-theme-backgrounds.sh [选项] 选项: --theme 只导出指定主题 --orientation 只导出指定方向;必须和 --theme 一起使用 -h, --help 查看帮助 示例: sh scripts/export-theme-backgrounds.sh sh scripts/export-theme-backgrounds.sh --theme simple sh scripts/export-theme-backgrounds.sh --theme simple --orientation portrait EOF } while [ "$#" -gt 0 ]; do case "$1" in --theme) shift THEME_FILTER=${1:?"missing theme id"} ;; --orientation) shift ORIENTATION_FILTER=${1:?"missing orientation"} ;; -h|--help) print_usage exit 0 ;; *) echo "未知参数: $1" >&2 echo >&2 print_usage >&2 exit 1 ;; esac shift done if [ -n "$ORIENTATION_FILTER" ] && [ -z "$THEME_FILTER" ]; then echo "--orientation 必须和 --theme 一起使用。" >&2 exit 1 fi selection_output=$( node --input-type=module -e " import fs from 'node:fs'; const data = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); const requestedTheme = process.argv[2]; const requestedOrientation = process.argv[3]; const themes = data.themes ?? []; const themeMap = new Map(themes.map((theme) => [theme.id, theme])); if (requestedTheme && !themeMap.has(requestedTheme)) { console.error(\`未知主题: \${requestedTheme}\`); process.exit(1); } if (requestedOrientation && !requestedTheme) { console.error('--orientation 必须和 --theme 一起使用。'); process.exit(1); } const filteredThemes = requestedTheme ? themes.filter((theme) => theme.id === requestedTheme) : themes; const items = []; for (const theme of filteredThemes) { const orientations = Object.keys(theme.variants ?? {}); if (requestedOrientation) { if (!orientations.includes(requestedOrientation)) { console.error( \`主题 \${theme.id} 不支持方向 \${requestedOrientation},可用方向: \${orientations.join(', ')}\`, ); process.exit(1); } } const filteredOrientations = requestedOrientation ? [requestedOrientation] : orientations; for (const orientation of filteredOrientations) { const variant = theme.variants[orientation]; items.push([theme.id, orientation, variant.backgroundPath].join('\t')); } } if (items.length === 0) { console.error('没有可导出的主题背景。'); process.exit(1); } console.log(\`DEFAULT_THEME_ID=\${data.defaultThemeId}\`); console.log(\`DEFAULT_ORIENTATION=\${data.defaultOrientation}\`); for (const item of items) { console.log(\`ITEM=\${item}\`); } " "$THEMES_SOURCE" "$THEME_FILTER" "$ORIENTATION_FILTER" ) DEFAULT_THEME_ID="" DEFAULT_ORIENTATION="" EXPORT_ITEMS="" while IFS= read -r line; do case "$line" in DEFAULT_THEME_ID=*) DEFAULT_THEME_ID=${line#DEFAULT_THEME_ID=} ;; DEFAULT_ORIENTATION=*) DEFAULT_ORIENTATION=${line#DEFAULT_ORIENTATION=} ;; ITEM=*) if [ -n "$EXPORT_ITEMS" ]; then EXPORT_ITEMS="${EXPORT_ITEMS} ${line#ITEM=}" else EXPORT_ITEMS=${line#ITEM=} fi ;; esac done <&2 exit 1 fi cd "$CALENDAR_DIR" npm run build >/dev/null python3 -m http.server "$PORT" -d "$DIST_DIR" >/tmp/kindle-calendar-http.log 2>&1 & SERVER_PID=$! trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT INT TERM sleep 1 printf '%s\n' "$EXPORT_ITEMS" | while IFS="$(printf '\t')" read -r theme_id orientation background_path; do out_png="$DIST_DIR/$background_path" out_region="${out_png%.png}.clock-region.json" url="http://127.0.0.1:$PORT/?mode=background&theme=$theme_id&orientation=$orientation" /usr/bin/swift "$SWIFT_SCRIPT" "$url" "$out_png" "$out_region" >/dev/null # 根目录的 kindlebg.png / clock-region.json 只给默认主题兜底使用。 # 定向导出其它主题时不覆盖它,避免把默认主题的运行时入口意外改掉。 if [ "$theme_id" = "$DEFAULT_THEME_ID" ] && [ "$orientation" = "$DEFAULT_ORIENTATION" ]; then cp "$out_png" "$DIST_DIR/kindlebg.png" cp "$out_region" "$DIST_DIR/clock-region.json" fi printf 'Exported %s %s -> %s\n' "$theme_id" "$orientation" "$out_png" done node "$CALENDAR_DIR/scripts/generate-dashboard-manifest.mjs" >/dev/null if [ -f "$DIST_DIR/clock-region.json" ]; then printf 'Default region saved to %s\n' "$DIST_DIR/clock-region.json" else printf 'Skipped default region update (default theme not exported this run)\n' fi