#!/usr/bin/env sh # gitea-link.sh — 解析 Gitea 的 wiki 頁或議題連結(供 jsc-gitea:wiki-to-issue、html-export 使用)。 # # 為什麼要有這支腳本:兩支技能都以「一條連結」為唯一入口,沒有連結就中斷。連結長什麼樣、 # 哪一段是存取庫、哪一段是頁名,是固定的字串規則,交給模型每次自己拆,拆錯就寫到別的存取庫去。 # # 用法: # gitea-link.sh parse 解析連結,印出可直接 eval 的欄位 # # parse 輸出(每行一個 key=value,值已加單引號): # kind='wiki' repo='owner/repo' page='PAGE_NAME' host='https://gitea.example' # kind='issue' repo='owner/repo' index='12' host='https://gitea.example' # # 認得的形式: # https://host/{owner}/{repo}/wiki/{page} (page 可含 %XX 編碼,會還原) # https://host/{owner}/{repo}/wiki/{page}/_edit (尾巴的 _edit、_new 會去掉) # https://host/{owner}/{repo}/issues/{index} # https://host/{owner}/{repo}/issues/{index}#issuecomment-123 # # 結束碼: 0=解析成功 2=用法錯誤 3=不是認得的 wiki 或議題連結 # # 陷阱: # - 結束碼 3 由呼叫端當成「沒有連結」處理,直接中斷流程,不要退回去猜存取庫或頁名。 # - 只解析連結本身,不打網路,也不檢查頁面存不存在;那是 wiki-get 與 issue.sh 的事。 set -eu usage() { echo 'usage: gitea-link.sh parse ' >&2 exit 2 } [ "$#" -eq 2 ] || usage [ "$1" = parse ] || usage url="$2" [ -n "$url" ] || usage python3 - "$url" <<'PY' import re, sys from urllib.parse import urlsplit, unquote url = sys.argv[1].strip() if not re.match(r'^https?://', url): print('[jsc][連結解析][ERR]:連結要以 http:// 或 https:// 開頭。', file=sys.stderr) sys.exit(3) u = urlsplit(url) host = f'{u.scheme}://{u.netloc}' parts = [p for p in u.path.split('/') if p] if len(parts) < 4: print('[jsc][連結解析][ERR]:認不出存取庫與頁面,需要 /{owner}/{repo}/wiki/{page} 或 /{owner}/{repo}/issues/{index}。', file=sys.stderr) sys.exit(3) owner, repo, kind = parts[0], parts[1], parts[2] rest = parts[3:] def out(**kv): for k, v in kv.items(): print(f"{k}='{str(v)}'") if kind == 'wiki': while rest and rest[-1] in ('_edit', '_new', '_pages'): rest.pop() if not rest: print('[jsc][連結解析][ERR]:wiki 連結少了頁名。', file=sys.stderr) sys.exit(3) page = unquote('/'.join(rest)) out(kind='wiki', repo=f'{owner}/{repo}', page=page, host=host) elif kind == 'issues': idx = rest[0].split('#')[0] if not idx.isdigit(): print('[jsc][連結解析][ERR]:議題編號不是數字。', file=sys.stderr) sys.exit(3) out(kind='issue', repo=f'{owner}/{repo}', index=idx, host=host) else: print(f'[jsc][連結解析][ERR]:只認得 wiki 與 issues 連結,收到「{kind}」。', file=sys.stderr) sys.exit(3) PY