Files
mytoolkit/bin/commands/webpage.py
T
Zhengshou Lai 3e4cf618a8 refactor: restructure mytoolkit with new subcommands and md-to-pdf improvements
- Add new subcommands: convert, preflight, server, templates, webpage
- Migrate config from bin/config.json to ~/.config/mytoolkit
- Fix expand_bookmarks to modify writer objects instead of reader
- Improve md_to_pdf with CJK bookmark support
- Update README and project metadata
2026-05-04 17:19:32 +08:00

90 lines
2.9 KiB
Python

"""Webpage project utilities (Docusaurus build / clear / etc.).
Project metadata lives in `server.py` so that adding a new webpage there
automatically wires it up here.
"""
import subprocess
import time
import click
from bin.commands.server import manageable_services, get_service, no_color_env
_PROJECTS = manageable_services()
_NAMES = [s.name for s in _PROJECTS]
def _run_npm(name: str, script: str, label: str) -> None:
"""Run `npm run <script>` in the project's directory, streaming output."""
svc = get_service(name)
assert svc.project_dir is not None # _NAMES is manageable services only
if not svc.project_dir.exists():
click.secho(f"Project directory not found: {svc.project_dir}", fg="red")
raise click.Abort()
click.secho(f"{label} {svc.name} ({svc.description}) ...", fg="cyan")
started = time.time()
proc = subprocess.run(["npm", "run", script], cwd=svc.project_dir, env=no_color_env())
elapsed = time.time() - started
if proc.returncode != 0:
click.secho(f"{script} failed for {svc.name} (exit {proc.returncode})", fg="red")
raise click.Abort()
click.secho(f"{svc.name} {script} done in {elapsed:.1f}s", fg="green")
@click.group(name="webpage")
def webpage_cmd():
"""Manage Docusaurus webpage projects."""
pass
@webpage_cmd.command("list")
def webpage_list():
"""List managed webpage projects and their build status."""
click.echo("")
click.secho(
f"{'Name':<16} {'Build':<12} {'Description':<36} {'Project'}",
fg="bright_blue",
bold=True,
)
click.echo("-" * 100)
for svc in _PROJECTS:
assert svc.project_dir is not None # _PROJECTS is manageable services only
build_dir = svc.project_dir / "build"
if build_dir.exists():
build_status = time.strftime("%m-%d %H:%M", time.localtime(build_dir.stat().st_mtime))
color = "green"
else:
build_status = "missing"
color = "yellow"
click.secho(
f"{svc.name:<16} {build_status:<12} {svc.description:<36} {svc.project_dir}",
fg=color,
)
click.echo("")
@webpage_cmd.command("build")
@click.argument("name", type=click.Choice(_NAMES, case_sensitive=False))
def webpage_build(name):
"""Build a webpage project (`npm run build`)."""
_run_npm(name, "build", "Building")
@webpage_cmd.command("clear")
@click.argument("name", type=click.Choice(_NAMES, case_sensitive=False))
def webpage_clear(name):
"""Clear Docusaurus build artifacts and cache (`npm run clear`)."""
_run_npm(name, "clear", "Clearing")
@webpage_cmd.command("rebuild")
@click.argument("name", type=click.Choice(_NAMES, case_sensitive=False))
def webpage_rebuild(name):
"""Clear cache then build (`npm run clear && npm run build`)."""
_run_npm(name, "clear", "Clearing")
_run_npm(name, "build", "Building")