86 lines
3.5 KiB
Bash
Executable File
86 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Erzeugt die Skill-Tabelle in README.md zwischen <!-- skills:start --> und <!-- skills:end -->
|
||
# neu. Mit --check wird nur geprüft, ob die Tabelle aktuell ist (Exit-Code 1, wenn nicht).
|
||
# Aufruf: scripts/update-index.sh [--check]
|
||
set -euo pipefail
|
||
source "$(dirname "$0")/lib.sh"
|
||
|
||
REPO_WEB="https://git.gundel.dev/dg/claude-skills"
|
||
readme="$ROOT/README.md"
|
||
check=0
|
||
[[ "${1:-}" == "--check" ]] && check=1
|
||
|
||
if ! grep -q '<!-- skills:start -->' "$readme" || ! grep -q '<!-- skills:end -->' "$readme"; then
|
||
echo "README.md enthält die Marker <!-- skills:start --> / <!-- skills:end --> nicht." >&2
|
||
exit 1
|
||
fi
|
||
|
||
table="$(mktemp)"
|
||
trap 'rm -f "$table"' EXIT
|
||
{
|
||
echo '| Skill | Kurzbeschreibung | Version | Doku | Download | Erweiterung (.mcpb) | Cursor-Plugin | Cursor 1-Klick |'
|
||
echo '|---|---|---|---|---|---|---|---|'
|
||
while IFS= read -r name; do
|
||
[[ -z "$name" ]] && continue
|
||
desc=""
|
||
ver="$(skill_version "$SKILLS_DIR/$name")"
|
||
if fm="$(frontmatter "$SKILLS_DIR/$name/SKILL.md" 2>/dev/null)"; then
|
||
desc="$(fm_value "$fm" description || true)"
|
||
fi
|
||
desc="${desc//|/\\|}"
|
||
tag_enc="$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=""))' "$name/v$ver")"
|
||
zip_link="[${name}-v${ver}.zip](${REPO_WEB}/releases/download/${tag_enc}/${name}-v${ver}.zip)"
|
||
mcpb=""
|
||
cursor_zip=""
|
||
deeplink=""
|
||
if [[ -f "$SKILLS_DIR/$name/extension/manifest.json" ]]; then
|
||
mcpb="[${name}-v${ver}.mcpb](${REPO_WEB}/releases/download/${tag_enc}/${name}-v${ver}.mcpb)"
|
||
cursor_zip="[${name}-cursor-v${ver}.zip](${REPO_WEB}/releases/download/${tag_enc}/${name}-cursor-v${ver}.zip)"
|
||
deeplink="$(python3 - "$SKILLS_DIR/$name/extension/manifest.json" "$name" <<'PY'
|
||
import json, base64, sys, urllib.parse, re
|
||
man = json.load(open(sys.argv[1], encoding="utf-8"))
|
||
name = sys.argv[2]
|
||
sk = {"wordcraft-mcp":"wordcraft","gridcraft-mcp":"gridcraft"}.get(name)
|
||
if not sk:
|
||
m = re.match(r"^(.+)-mcp$", name)
|
||
sk = m.group(1) if m else name
|
||
cmd = man["server"]["mcp_config"]["command"]
|
||
args = []
|
||
for a in man["server"]["mcp_config"].get("args") or []:
|
||
s = str(a)
|
||
if s == "${user_config.author}":
|
||
args.append("Claude")
|
||
elif s == "${user_config.read_root}":
|
||
args.append("${userHome}/Documents")
|
||
elif s == "${user_config.write_root}":
|
||
args.append("${userHome}/Documents/Claude")
|
||
else:
|
||
args.append(s)
|
||
payload = {sk: {"command": cmd, "args": args}}
|
||
b64 = base64.urlsafe_b64encode(json.dumps(payload, separators=(",", ":")).encode()).decode().rstrip("=")
|
||
link = f"cursor://anysphere.cursor-deeplink/mcp/install?name={urllib.parse.quote(sk)}&config={b64}"
|
||
print(f"[Add to Cursor]({link})")
|
||
PY
|
||
)"
|
||
fi
|
||
printf '| [%s](skills/%s/) | %s | %s | [README](skills/%s/README.md) | %s | %s | %s | %s |\n' \
|
||
"$name" "$name" "$desc" "$ver" "$name" "$zip_link" "$mcpb" "$cursor_zip" "$deeplink"
|
||
done < <(skill_names)
|
||
} > "$table"
|
||
|
||
new="$(tr -d '\r' < "$readme" | awk -v t="$table" '
|
||
/<!-- skills:start -->/ { print; while ((getline l < t) > 0) print l; skip = 1; next }
|
||
/<!-- skills:end -->/ { skip = 0 }
|
||
!skip { print }')"
|
||
|
||
if [[ $check -eq 1 ]]; then
|
||
if [[ "$new" != "$(tr -d '\r' < "$readme")" ]]; then
|
||
echo "README.md ist nicht aktuell – scripts/update-index.sh ausführen und committen." >&2
|
||
exit 1
|
||
fi
|
||
echo "README.md ist aktuell."
|
||
else
|
||
python3 -c 'import sys; open(sys.argv[1],"w",encoding="utf-8",newline="\n").write(sys.stdin.read())' "$readme" <<< "$new"
|
||
echo "README.md aktualisiert."
|
||
fi
|