Source code for httk.serve.web.publishing.static
import shutil
from pathlib import Path
from httk.serve.web.engine.site_engine import SiteEngine
from httk.serve.web.model.page import PageResult, PublishReport
from httk.serve.web.widgets import WidgetAsset
[docs]
CONTENT_EXTENSIONS: set[str] = {".md", ".rst", ".html", ".httkweb"}
[docs]
def publish_site(*, engine: SiteEngine, outdir: str | Path) -> PublishReport:
output_root = Path(outdir).resolve()
warnings: list[str] = []
static_files: list[tuple[Path, Path]] = []
static_file_paths: set[Path] = set()
static_directory_paths: set[Path] = set()
pages: list[tuple[Path, PageResult]] = []
assets: dict[str, WidgetAsset] = {}
static_dir = engine.config.static_dir
if static_dir.exists():
for static_path in sorted(static_dir.rglob("*")):
rel = static_path.relative_to(static_dir)
if static_path.is_dir():
static_directory_paths.add(rel)
elif static_path.is_file():
static_files.append((static_path, rel))
static_file_paths.add(rel)
static_directory_paths.update(parent for parent in rel.parents if parent != Path("."))
content_dir = engine.config.content_dir
if content_dir.exists():
for content_file in sorted(content_dir.rglob("*")):
if not content_file.is_file() or content_file.suffix.lower() not in CONTENT_EXTENSIONS:
continue
rel = content_file.relative_to(content_dir)
route = str(rel.with_suffix(""))
result = engine.render(route)
warnings.extend(result.warnings)
pages.append((rel.with_suffix(".html"), result))
for asset in result.assets:
assets[asset.path] = asset
asset_root = Path("_httk") / "serve" / "assets"
for asset in assets.values():
asset_rel = asset_root / asset.path
if (
asset_rel in static_file_paths
or asset_rel in static_directory_paths
or any(parent in static_file_paths for parent in asset_rel.parents if parent != Path("."))
):
raise ValueError(f"widget asset collides with site static output: {asset.path}")
output_root.mkdir(parents=True, exist_ok=True)
written_files: list[Path] = []
for source, rel in static_files:
target = output_root / rel
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, target)
written_files.append(target)
for rel, result in pages:
target = output_root / rel
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(result.body)
written_files.append(target)
for asset in assets.values():
target = output_root / asset_root / asset.path
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(asset.content)
written_files.append(target)
return PublishReport(written_files=written_files, warnings=warnings)