What:新增 wiki-to-issue 技能,把一頁 wiki 轉成同一個存取庫的議題;配套新增 tools/gitea-link.sh 解析連結、tools/issue.sh 讀寫議題。 Why:wiki 頁要變成可追蹤的工作時,原本得自己拼 API:組 JSON、查標籤 id、挑回應欄位,跳脫一錯就把對外的議題內容寫壞。 How:連結是唯一入口,gitea-link.sh 解不出 wiki 頁就中止,不猜存取庫也不猜頁名;標籤只從既有的挑;站台沒有專案看板 API 時據實回報請使用者手動拖,不假裝關聯成功。 Who:使用 jsc 技能組、需要把 wiki 內容交辦出去的人。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
78 lines
2.9 KiB
Bash
Executable File
78 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env sh
|
||
# gitea-link.sh — 解析 Gitea 的 wiki 頁或議題連結(供 jsc-gitea:wiki-to-issue、html-export 使用)。
|
||
#
|
||
# 為什麼要有這支腳本:兩支技能都以「一條連結」為唯一入口,沒有連結就中斷。連結長什麼樣、
|
||
# 哪一段是存取庫、哪一段是頁名,是固定的字串規則,交給模型每次自己拆,拆錯就寫到別的存取庫去。
|
||
#
|
||
# 用法:
|
||
# gitea-link.sh parse <url> 解析連結,印出可直接 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 <url>' >&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
|