You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sb...@apache.org on 2025/10/06 19:49:58 UTC
(tooling-trusted-release) branch main updated: Add a user manual documentation tree
This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 156b15b Add a user manual documentation tree
156b15b is described below
commit 156b15bd738f5e59581f03b47e27db707fe56990
Author: Sean B. Palmer <se...@miscoranda.com>
AuthorDate: Mon Oct 6 20:49:40 2025 +0100
Add a user manual documentation tree
---
Makefile | 10 ++++--
atr/manual/index.html | 3 ++
atr/manual/index.md | 5 +++
atr/routes/__init__.py | 2 ++
atr/routes/manual.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 116 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index f91368b..daf3138 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
.PHONY: build build-alpine build-playwright build-ts build-ubuntu certs \
check check-extra check-light commit docs generate-version ipython \
- run-playwright run-playwright-slow serve serve-local sync sync-all \
- update-deps
+ manual run-playwright run-playwright-slow serve serve-local sync \
+ sync-all update-deps
BIND ?= 127.0.0.1:8080
IMAGE ?= tooling-trusted-release
@@ -62,6 +62,12 @@ generate-version:
ipython:
uv run --frozen --with ipython ipython
+manual:
+ for fn in atr/manual/*.md; \
+ do \
+ cmark "$$fn" > "$${fn%.md}.html"; \
+ done
+
run-playwright:
docker run --net=host -it atr-playwright python3 test.py --skip-slow
diff --git a/atr/manual/index.html b/atr/manual/index.html
new file mode 100644
index 0000000..1adef07
--- /dev/null
+++ b/atr/manual/index.html
@@ -0,0 +1,3 @@
+<h1>Apache Trusted Releases user manual</h1>
+<p>Welcome to the user manual for the <strong>Apache Trusted Releases</strong> (ATR) platform.</p>
+<p>This user manual is a work in progress.</p>
diff --git a/atr/manual/index.md b/atr/manual/index.md
new file mode 100644
index 0000000..b4039cb
--- /dev/null
+++ b/atr/manual/index.md
@@ -0,0 +1,5 @@
+# Apache Trusted Releases user manual
+
+Welcome to the user manual for the **Apache Trusted Releases** (ATR) platform.
+
+This user manual is a work in progress.
diff --git a/atr/routes/__init__.py b/atr/routes/__init__.py
index 9a04e8b..6fd2717 100644
--- a/atr/routes/__init__.py
+++ b/atr/routes/__init__.py
@@ -26,6 +26,7 @@ import atr.routes.file as file
import atr.routes.finish as finish
import atr.routes.ignores as ignores
import atr.routes.keys as keys
+import atr.routes.manual as manual
import atr.routes.preview as preview
import atr.routes.projects as projects
import atr.routes.published as published
@@ -53,6 +54,7 @@ __all__ = [
"finish",
"ignores",
"keys",
+ "manual",
"preview",
"projects",
"published",
diff --git a/atr/routes/manual.py b/atr/routes/manual.py
new file mode 100644
index 0000000..b55759a
--- /dev/null
+++ b/atr/routes/manual.py
@@ -0,0 +1,98 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import pathlib
+from html.parser import HTMLParser
+
+import aiofiles
+import aiofiles.os
+import markupsafe
+import quart
+
+import atr.config as config
+import atr.route as route
+import atr.template as template
+
+
+class H1Parser(HTMLParser):
+ def __init__(self) -> None:
+ super().__init__()
+ self.h1_content: str | None = None
+ self._in_h1 = False
+
+ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
+ if (tag == "h1") and (self.h1_content is None):
+ self._in_h1 = True
+
+ def handle_endtag(self, tag: str) -> None:
+ if tag == "h1":
+ self._in_h1 = False
+
+ def handle_data(self, data: str) -> None:
+ if self._in_h1 and (self.h1_content is None):
+ self.h1_content = data.strip()
+
+
+@route.public("/manual/")
+async def index(session: route.CommitterSession | None) -> str:
+ return await _serve_manual_page("index")
+
+
+@route.public("/manual/<path:page>")
+async def page(session: route.CommitterSession | None, page: str) -> str:
+ return await _serve_manual_page(page)
+
+
+async def _serve_manual_page(page: str) -> str:
+ manual_dir = pathlib.Path(config.get().PROJECT_ROOT) / "atr" / "manual"
+
+ if not page.endswith(".html"):
+ page = f"{page}.html"
+
+ file_path = manual_dir / page
+
+ manual_root = manual_dir.resolve()
+ try:
+ resolved_file = file_path.resolve()
+ except FileNotFoundError:
+ quart.abort(404)
+ try:
+ resolved_file.relative_to(manual_root)
+ except ValueError:
+ quart.abort(404)
+
+ if not await aiofiles.os.path.exists(resolved_file):
+ quart.abort(404)
+
+ if not await aiofiles.os.path.isfile(resolved_file):
+ quart.abort(404)
+
+ async with aiofiles.open(resolved_file, encoding="utf-8") as handle:
+ html_content = await handle.read()
+
+ safe_content = markupsafe.Markup(html_content)
+
+ filename_title = resolved_file.stem.replace("-", " ").replace("_", " ").title()
+ try:
+ parser = H1Parser()
+ first_lines = "\n".join(html_content.split("\n")[:8])
+ parser.feed(first_lines)
+ title = parser.h1_content or filename_title
+ except Exception:
+ title = filename_title
+
+ return await template.blank(title=title, content=safe_content)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org