Remove contributing and component docs from the public docs site
Drop the Contributing and internals section, Architecture, Frontend, and dp-* component pages from the docs registry, prose files, nav, and legacy redirect target. Guard with tests that fail if they return.
This commit is contained in:
+1
-13
@@ -10,9 +10,7 @@ from molodetz.rendering import normalize_dashes
|
||||
|
||||
PROSE_DIR = config.TEMPLATES_DIR / "docs" / "prose"
|
||||
|
||||
SECTIONS = ("Start here", "Building with the API", "Contributing and internals", "Admin")
|
||||
|
||||
COMPONENTS = ("avatar", "code", "content", "title", "toast", "dialog", "context-menu", "upload", "lightbox", "chat")
|
||||
SECTIONS = ("Start here", "Building with the API", "Admin")
|
||||
|
||||
DOCS_PAGES = [
|
||||
{"slug": "welcome", "title": "Welcome", "section": "Start here", "file": "welcome.md"},
|
||||
@@ -20,18 +18,8 @@ DOCS_PAGES = [
|
||||
{"slug": "join", "title": "Joining", "section": "Start here", "file": "join.md"},
|
||||
{"slug": "legal", "title": "Terms and privacy", "section": "Start here", "file": "legal.md"},
|
||||
{"slug": "api", "title": "API and authentication", "section": "Building with the API", "file": "api.md"},
|
||||
{"slug": "architecture", "title": "Architecture", "section": "Contributing and internals", "file": "architecture.md"},
|
||||
{"slug": "frontend", "title": "Frontend and components", "section": "Contributing and internals", "file": "frontend.md"},
|
||||
{"slug": "admin", "title": "Admin and services", "section": "Admin", "file": "admin.md", "admin": True},
|
||||
{"slug": "backups", "title": "Backups and maintenance", "section": "Admin", "file": "backups.md", "admin": True},
|
||||
] + [
|
||||
{
|
||||
"slug": f"component-{name}",
|
||||
"title": f"dp-{name}",
|
||||
"section": "Contributing and internals",
|
||||
"file": f"component-{name}.md",
|
||||
}
|
||||
for name in COMPONENTS
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ LEGACY_PATHS = {
|
||||
"/docs/schrijven": "/docs/writing",
|
||||
"/docs/binnen": "/docs/join",
|
||||
"/docs/juridisch": "/docs/legal",
|
||||
"/docs/architectuur": "/docs/architecture",
|
||||
"/docs/architectuur": "/docs/welcome",
|
||||
"/docs/beheer": "/docs/admin",
|
||||
"/docs/api/inhoud": "/docs/api/content",
|
||||
"/docs/api/binnen": "/docs/api/join",
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# Architecture
|
||||
|
||||
FastAPI with Jinja2, rendered on the server. SQLite through `dataset`, synchronous and deliberately without a threadpool. Sessions with PBKDF2-SHA256 passwords.
|
||||
|
||||
## Layers
|
||||
|
||||
- `molodetz/database/`: one file per subject, always import from the package root.
|
||||
- `molodetz/routers/`: mirrors the URL path.
|
||||
- `molodetz/services/`: background services under one supervisor with a file lock.
|
||||
- `molodetz/templates/`: one Jinja environment in `templating.py`.
|
||||
|
||||
## Deleting
|
||||
|
||||
Everything is soft deleted with `deleted_at` and `deleted_by`. Only cleanup jobs delete for real.
|
||||
|
||||
## Static files
|
||||
|
||||
Assets go through `static_url()`, which versions them under `/static/v<version>/`. Those are immutably cacheable for a year.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-avatar
|
||||
|
||||
Shows a deterministic SVG avatar plus a presence dot. Attributes `seed`, `size`, `uid`.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-chat
|
||||
|
||||
Simple log with an input line. Emits a `dp-chat-send` event.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-code
|
||||
|
||||
Highlights a code block with highlight.js and adds a Copy button.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-content
|
||||
|
||||
Renders live markdown on the client through marked, then DOMPurify. Only for live content, such as the editor preview.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-context-menu
|
||||
|
||||
Small context menu with buttons, positioned at the cursor.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-dialog
|
||||
|
||||
Confirmation dialog. Forms with `data-confirm` go through it.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-lightbox
|
||||
|
||||
Full screen view for images with `data-lightbox`. Escape or a click closes it.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-title
|
||||
|
||||
Inline variant of dp-content for titles.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-toast
|
||||
|
||||
Host for short notices. Use `Toast.flash(el, message)` or `app.toast(message)`.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,5 +0,0 @@
|
||||
# dp-upload
|
||||
|
||||
Drop zone for files. Emits a `dp-files` event with the chosen files.
|
||||
|
||||
Light DOM, no shadow DOM. Registers itself with `customElements.define`.
|
||||
@@ -1,7 +0,0 @@
|
||||
# Frontend and components
|
||||
|
||||
ES6 modules, one class per file, no framework and no bundler. `Application.js` creates all singletons and sets `window.app`.
|
||||
|
||||
Components are custom elements with the `dp-` prefix, without shadow DOM. See the component pages in the sidebar.
|
||||
|
||||
Client rendering with marked and DOMPurify is only for live content: the preview in the editor. Published posts are rendered on the server.
|
||||
@@ -12,4 +12,4 @@ Molodetz is a quiet blog roll. Notes about the work, finishing it, and judgement
|
||||
|
||||
## Where to start
|
||||
|
||||
Read [Writing on the roll](/docs/writing) for the content, [API and authentication](/docs/api) for integrations, and [Architecture](/docs/architecture) if you want to know how it is built.
|
||||
Read [Writing on the roll](/docs/writing) for the content, and [API and authentication](/docs/api) for integrations.
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "molodetz"
|
||||
version = "1.0.15"
|
||||
version = "1.0.16"
|
||||
description = "Molodetz, a calm community blog roll."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
import re
|
||||
|
||||
from molodetz.docs_prose import DOCS_PAGES, PROSE_DIR, SECTIONS
|
||||
|
||||
BANNED_SECTION = "Contributing and internals"
|
||||
BANNED_TITLES = {
|
||||
"Architecture",
|
||||
"Frontend and components",
|
||||
"dp-avatar",
|
||||
"dp-code",
|
||||
"dp-content",
|
||||
"dp-title",
|
||||
"dp-toast",
|
||||
"dp-dialog",
|
||||
"dp-context-menu",
|
||||
"dp-upload",
|
||||
"dp-lightbox",
|
||||
"dp-chat",
|
||||
}
|
||||
BANNED_SLUGS = {
|
||||
"architecture",
|
||||
"frontend",
|
||||
"component-avatar",
|
||||
"component-code",
|
||||
"component-content",
|
||||
"component-title",
|
||||
"component-toast",
|
||||
"component-dialog",
|
||||
"component-context-menu",
|
||||
"component-upload",
|
||||
"component-lightbox",
|
||||
"component-chat",
|
||||
}
|
||||
BANNED_FILES = {
|
||||
"architecture.md",
|
||||
"frontend.md",
|
||||
*[
|
||||
f"component-{name}.md"
|
||||
for name in (
|
||||
"avatar",
|
||||
"code",
|
||||
"content",
|
||||
"title",
|
||||
"toast",
|
||||
"dialog",
|
||||
"context-menu",
|
||||
"upload",
|
||||
"lightbox",
|
||||
"chat",
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def _docs_surfaces(html):
|
||||
sidebar = re.search(r'<aside class="docs-sidebar">(.*?)</aside>', html, re.S)
|
||||
content = re.search(r'<article class="docs-content[^"]*">(.*?)</article>', html, re.S)
|
||||
return (sidebar.group(1) if sidebar else ""), (content.group(1) if content else "")
|
||||
|
||||
|
||||
def test_docs_registry_excludes_removed_internals():
|
||||
assert BANNED_SECTION not in SECTIONS
|
||||
titles = {page["title"] for page in DOCS_PAGES}
|
||||
slugs = {page["slug"] for page in DOCS_PAGES}
|
||||
sections = {page["section"] for page in DOCS_PAGES}
|
||||
assert not titles & BANNED_TITLES
|
||||
assert not slugs & BANNED_SLUGS
|
||||
assert BANNED_SECTION not in sections
|
||||
for name in BANNED_FILES:
|
||||
assert not (PROSE_DIR / name).exists(), name
|
||||
|
||||
|
||||
def test_served_docs_hide_removed_internals(anon, admin):
|
||||
banned_hrefs = {f"/docs/{slug}" for slug in BANNED_SLUGS}
|
||||
for client in (anon, admin):
|
||||
for path in ("/docs", "/docs/welcome", "/docs/api"):
|
||||
html = client.get(path).text
|
||||
sidebar, content = _docs_surfaces(html)
|
||||
surface = f"{sidebar}\n{content}"
|
||||
assert BANNED_SECTION not in surface, path
|
||||
for title in BANNED_TITLES:
|
||||
assert title not in surface, (path, title)
|
||||
for href in banned_hrefs:
|
||||
assert href not in surface, (path, href)
|
||||
for slug in sorted(BANNED_SLUGS):
|
||||
assert anon.get(f"/docs/{slug}").status_code == 404, slug
|
||||
+1
-1
@@ -14,7 +14,7 @@ REDIRECTS = [
|
||||
("/docs/schrijven", "/docs/writing"),
|
||||
("/docs/binnen", "/docs/join"),
|
||||
("/docs/juridisch", "/docs/legal"),
|
||||
("/docs/architectuur", "/docs/architecture"),
|
||||
("/docs/architectuur", "/docs/welcome"),
|
||||
("/docs/api/inhoud", "/docs/api/content"),
|
||||
("/docs/api/binnen", "/docs/api/join"),
|
||||
]
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
from tests.conftest import assert_no_horizontal_overflow, goto_ready
|
||||
|
||||
PUBLIC_PAGES = ["/", "/roll", "/standard", "/flyers", "/memes", "/people", "/people/retoor", "/join", "/docs", "/docs/welcome", "/docs/api/content", "/docs/component-code", "/terms", "/privacy"]
|
||||
PUBLIC_PAGES = ["/", "/roll", "/standard", "/flyers", "/memes", "/people", "/people/retoor", "/join", "/docs", "/docs/welcome", "/docs/api/content", "/terms", "/privacy"]
|
||||
|
||||
|
||||
def test_home_renders_without_errors(page, app_server):
|
||||
|
||||
Reference in New Issue
Block a user