CLAUDE.md -> AGENTS.md and docs-preview
This commit is contained in:
parent
3208f11b18
commit
b2b97ab8b3
2 changed files with 83 additions and 0 deletions
83
mise-tasks/docs-preview
Executable file
83
mise-tasks/docs-preview
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = ["rich>=13.0.0", "typer>=0.24.0"]
|
||||
# ///
|
||||
#MISE description="Serve a docs release tarball locally in a browser"
|
||||
#USAGE arg "<tarball>" help="Path to docs tarball (e.g. ~/Downloads/docs-v0.0.2.tar.gz)"
|
||||
#USAGE flag "--port <port>" default="8484" help="Port for preview server (default 8484)"
|
||||
"""Extract a docs release tarball and serve it locally.
|
||||
|
||||
Downloads the docs tarball from a Forgejo release page manually, then
|
||||
point this task at it to preview the site in your browser.
|
||||
|
||||
Usage:
|
||||
mise run docs-preview ~/Downloads/docs-v0.0.2.tar.gz
|
||||
mise run docs-preview ~/Downloads/docs-v0.0.2.tar.gz --port 9090
|
||||
"""
|
||||
|
||||
import http.server
|
||||
import tarfile
|
||||
import tempfile
|
||||
import threading
|
||||
import webbrowser
|
||||
from pathlib import Path
|
||||
from typing import Annotated
|
||||
|
||||
import typer
|
||||
from rich.console import Console
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def main(
|
||||
tarball: Annotated[Path, typer.Argument(help="Path to docs tarball")],
|
||||
port: Annotated[int, typer.Option(help="Port for preview server")] = 8484,
|
||||
) -> None:
|
||||
tarball = tarball.expanduser().resolve()
|
||||
if not tarball.exists():
|
||||
console.print(f"[bold red]File not found:[/bold red] {tarball}")
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
docroot = Path(tempfile.mkdtemp(prefix="docs-preview-"))
|
||||
console.print(f"[dim]Extracting {tarball.name} to {docroot}...[/dim]")
|
||||
with tarfile.open(tarball, "r:gz") as tf:
|
||||
tf.extractall(docroot, filter="data")
|
||||
|
||||
url = f"http://localhost:{port}"
|
||||
console.print(f"\n[bold green]Serving docs at {url}[/bold green]")
|
||||
console.print(f"[yellow]Press Ctrl+C to stop.[/yellow]\n")
|
||||
|
||||
threading.Timer(0.5, lambda: webbrowser.open(url)).start()
|
||||
|
||||
class QuartzHandler(http.server.SimpleHTTPRequestHandler):
|
||||
"""Handler that resolves clean URLs to index.html files."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, directory=str(docroot), **kwargs)
|
||||
|
||||
def do_GET(self):
|
||||
# Quartz outputs foo.html, not foo/index.html, so clean URLs
|
||||
# like /tutorials/tutorials need to resolve to tutorials.html
|
||||
path = self.path.split("?")[0].split("#")[0]
|
||||
file = docroot / path.lstrip("/")
|
||||
if not file.suffix and not file.is_file():
|
||||
html_candidate = file.with_suffix(".html")
|
||||
if html_candidate.is_file():
|
||||
self.path = path + ".html"
|
||||
elif (file / "index.html").is_file():
|
||||
self.path = path.rstrip("/") + "/index.html"
|
||||
super().do_GET()
|
||||
|
||||
handler = QuartzHandler
|
||||
server = http.server.HTTPServer(("localhost", port), handler)
|
||||
try:
|
||||
server.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
finally:
|
||||
console.print("\n[dim]Stopped.[/dim]")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
typer.run(main)
|
||||
Loading…
Add table
Add a link
Reference in a new issue