diff --git a/sanic/handlers/directory.py b/sanic/handlers/directory.py index b5422be1..1a787689 100644 --- a/sanic/handlers/directory.py +++ b/sanic/handlers/directory.py @@ -15,11 +15,12 @@ from sanic.response.types import HTTPResponse class DirectoryHandler: def __init__( - self, directory: Path, autoindex: bool, index_name: str + self, directory: Path, autoindex: bool, index_name: str, url: str ) -> None: self.directory = directory self.autoindex = autoindex self.index_name = index_name + self.url = url def handle(self): index_file = self.directory / self.index_name @@ -30,7 +31,7 @@ class DirectoryHandler: return file(index_file) def index(self): - page = AutoIndex(self._iter_files()) + page = AutoIndex(self._iter_files(), self.url) return html(page.render()) def _prepare_file(self, path: Path) -> Dict[str, Union[int, str]]: @@ -61,7 +62,7 @@ class DirectoryHandler: ) -> Optional[Coroutine[Any, Any, HTTPResponse]]: if exception.autoindex or exception.index_name: maybe_response = DirectoryHandler( - exception.location, exception.autoindex, exception.index_name + exception.location, exception.autoindex, exception.index_name, request.path ).handle() if maybe_response: return maybe_response diff --git a/sanic/pages/autoindex.py b/sanic/pages/autoindex.py index f79b4989..33bccb33 100644 --- a/sanic/pages/autoindex.py +++ b/sanic/pages/autoindex.py @@ -16,6 +16,11 @@ class FileInfo(TypedDict): class AutoIndex(BasePage): EXTRA_STYLE = dedent( """ + #breadcrumbs .path-0 a::before { content: "🏠"; } + a { text-decoration: none; } + a:hover { text-decoration: underline; } + #breadcrumbs span { display: inline-block; } + #breadcrumbs span:has(> a:hover) * { color: #ff0d61; text-shadow: 0 0 0.3rem; } table.autoindex tr { display: flex; } table.autoindex td { margin: 0 0.5rem; } table.autoindex td:first-child { flex: 1; } @@ -25,9 +30,10 @@ class AutoIndex(BasePage): ) TITLE = "📁 File browser" - def __init__(self, files: Iterable[FileInfo]) -> None: + def __init__(self, files: Iterable[FileInfo], url: str) -> None: super().__init__() self.files = files + self.url = url def _body(self) -> None: with self.doc.main: @@ -35,7 +41,15 @@ class AutoIndex(BasePage): self._file_table(self.files) def _headline(self): - self.doc.h1(self.TITLE) + # Implement a heading with the current path, combined with breadcrumb links + with self.doc.h1(id="breadcrumbs"): + p = self.url.split("/")[:-1] + for i in reversed(range(len(p))): + self.doc.span(class_=f"path-{i}").__enter__() + for i, part in enumerate(p): + path = "/".join(p[: i + 1]) + "/" + self.doc.a(f"{part}/", href=path) + self.doc.__exit__(None, None, None) def _file_table(self, files: Iterable[FileInfo]): with self.doc.table(class_="autoindex"):