sigh
This commit is contained in:
1 parent
8f368b0dc3
commit
2a895e42d6
3 files changed
+106
-4
No files matched your search
@@ -60,6 +60,8 @@ jobs:
|
||||
- name: Build Quartz
|
||||
working-directory: site
|
||||
run: npx quartz build -d ..
|
||||
- name: Patch sidebar title link
|
||||
run: python ../publish/quartz-patches/patch-title-link.py
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
"""Patch all built HTML files so the sidebar title link goes to /Threadwell/.
|
||||
|
||||
The `<h2 class="page-title">` link is generated by the
|
||||
`@quartz-community/page-title` plugin from a relative href that breaks
|
||||
when the URL bar lacks a trailing slash. We rewrite the href to the
|
||||
absolute site base path so it never lands on the bare domain.
|
||||
|
||||
Idempotent. Safe to re-run.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT = Path(__file__).resolve()
|
||||
VAULT = SCRIPT.parents[2]
|
||||
|
||||
# Detect base path from the publish overlay if present, else default to /Threadwell/
|
||||
overlay = VAULT / "publish" / "quartz.config.yaml"
|
||||
site_base = "/Threadwell/"
|
||||
if overlay.is_file():
|
||||
for line in overlay.read_text(encoding="utf-8").splitlines():
|
||||
if line.startswith("baseUrl:"):
|
||||
host = line.split(":", 1)[1].strip()
|
||||
if "/" in host:
|
||||
site_base = "/" + host.split("/", 1)[1].rstrip("/") + "/"
|
||||
else:
|
||||
site_base = "/"
|
||||
break
|
||||
|
||||
PUBLIC = VAULT / "site" / "public"
|
||||
|
||||
PATTERN = re.compile(
|
||||
r'(<h2\s+class="page-title"><a\s+href=")[^"]*(">)'
|
||||
)
|
||||
REPLACEMENT = rf"\1{site_base}\2"
|
||||
|
||||
|
||||
def patch_html(path: Path) -> bool:
|
||||
text = path.read_text(encoding="utf-8", errors="ignore")
|
||||
new = PATTERN.sub(REPLACEMENT, text)
|
||||
if new != text:
|
||||
path.write_text(new, encoding="utf-8")
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not PUBLIC.is_dir():
|
||||
print(f"missing {PUBLIC}")
|
||||
return 1
|
||||
changed = 0
|
||||
total = 0
|
||||
for path in PUBLIC.rglob("*.html"):
|
||||
total += 1
|
||||
if patch_html(path):
|
||||
changed += 1
|
||||
print(f"site base: {site_base}")
|
||||
print(f"total {total}, changed {changed}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -9,6 +9,9 @@ Default without --orig: only rows already publish=true.
|
||||
|
||||
After upload, any note token that is the local filename (backticked or
|
||||
bare) or a previous url for that row becomes .
|
||||
|
||||
Per-upload curl: --max-time 120, --retry 3, --retry-delay 2, --retry-all-errors.
|
||||
Errors are sanitized to redact the userhash before printing.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -17,12 +20,28 @@ import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
from paths import VAULT as VAULT_ROOT
|
||||
|
||||
API = "https://catbox.moe/user/api.php"
|
||||
MAX_TIME = 120
|
||||
RETRIES = 3
|
||||
RETRY_DELAY = 5
|
||||
THROTTLE_SECS = 5.0
|
||||
LIMIT_RATE = "500k"
|
||||
|
||||
|
||||
def _redact_cmd(cmd: list[str]) -> str:
|
||||
out: list[str] = []
|
||||
for tok in cmd:
|
||||
if tok.startswith("userhash="):
|
||||
out.append("userhash=<redacted>")
|
||||
else:
|
||||
out.append(tok)
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
def load_userhash(vault: Path) -> str:
|
||||
@@ -54,6 +73,15 @@ def upload(path: Path, userhash: str) -> str:
|
||||
cmd = [
|
||||
"curl.exe",
|
||||
"-sS",
|
||||
"--max-time",
|
||||
str(MAX_TIME),
|
||||
"--retry",
|
||||
str(RETRIES),
|
||||
"--retry-delay",
|
||||
str(RETRY_DELAY),
|
||||
"--retry-all-errors",
|
||||
"--limit-rate",
|
||||
LIMIT_RATE,
|
||||
"-F",
|
||||
"reqtype=fileupload",
|
||||
"-F",
|
||||
@@ -62,7 +90,13 @@ def upload(path: Path, userhash: str) -> str:
|
||||
f"fileToUpload=@{path}",
|
||||
API,
|
||||
]
|
||||
raw = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT)
|
||||
try:
|
||||
raw = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
raise SystemExit(
|
||||
f"catbox upload failed for {path.name} "
|
||||
f"(curl exit {exc.returncode}): {_redact_cmd(cmd)}"
|
||||
) from None
|
||||
url = raw.strip()
|
||||
if not url.startswith("https://"):
|
||||
raise SystemExit(f"catbox refused {path.name}: {url[:200]}")
|
||||
@@ -122,9 +156,10 @@ def main(argv: list[str] | None = None) -> int:
|
||||
|
||||
userhash = None if args.dry_run else load_userhash(args.vault)
|
||||
uploaded = 0
|
||||
for item in items:
|
||||
if not item.get("publish"):
|
||||
continue
|
||||
publishable = [it for it in items if it.get("publish")]
|
||||
for i, item in enumerate(publishable):
|
||||
if i > 0 and not args.dry_run:
|
||||
time.sleep(THROTTLE_SECS)
|
||||
name = str(item.get("filename") or "")
|
||||
src = args.thread / name
|
||||
if not src.is_file():
|
||||
|
||||
Reference in new issue
Block a user