site(com): Downloads and Documents, built from a release; the nav links; the release's SHA256SUMS covers every file (#126, #157) [skip ci]

The design canvas (v17) gains the Documents artboard -- the Book of Fabric and
the Dictionary of v4 first, then the book, the three volumes and the API
reference, each with its SHA-256, and the SSRN paper -- and Downloads and
Documents in every .com nav; Downloads' reading list becomes a pointer to
Documents. site/com/canvas/ copied from it.

site/com/build.py --release TAG --sums SHA256SUMS builds Downloads and
Documents from the release ([TAG], [RELEASE]/<file>, [SHA:<file>]; a file the
release's SHA256SUMS lacks fails the build). Without a release it builds Home,
Try it and Inquiries exactly as before -- byte for byte -- with no link to the
two pages, so they go live only with alpha.4. install.sh installs them when
built.

scripts/nightly.sh gitea-release: the release's SHA256SUMS now covers every
file it attaches -- the images' sums, then the PDFs and the Root CA's
certificate -- so `sha256sum -c SHA256SUMS` checks all of it and Documents
finds each sum. The Nexus artifacts keep their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
This commit is contained in:
Claude
2026-11-10 11:38:50 +00:00
parent 1a9b142d80
commit be2c204d56
9 changed files with 337 additions and 14 deletions
+47 -6
View File
@@ -3,7 +3,9 @@
# Copyright (c) 2023-2026 Robert A. James
"""build.py -- the starshipos-f18.com XWiki pages, made from the "StarshipOS.com" design canvas.
site/com/build.py canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki
site/com/build.py [--release TAG --sums SHA256SUMS]
canvas/{Main,Inquiries,TryIt}.dc.html -> {Main,Inquiries,TryIt}.WebHome.xwiki,
and with a release, canvas/{Downloads,Documents}.dc.html too
The canvas is the source: its artboards are copied into canvas/ as they are, and this turns each into
one {{html}} block (which needs a page author with script rights). What changes on the way:
@@ -15,6 +17,10 @@ one {{html}} block (which needs a page author with script rights). What changes
- Try it: the drawn console becomes the real one, an iframe of try.starshipos-f18.com;
- the inquiry form posts to the .org's PublicInquiry, which files it under Inquiries there
(admin-only, site/org/inquiries); the announcements form, which has no server, sends by e-mail;
- Downloads and Documents (#126, #157) are built from a release: --release TAG and the release's
SHA256SUMS fill in [TAG], [RELEASE]/<file> (the file on the Gitea release) and [SHA:<file>].
Without a release they are not built, and the other pages' links to them are taken out, so
nothing on the site points at a page that is not there (they go live with alpha.4);
install.sh puts the pages and the images on the wiki.
"""
@@ -31,6 +37,8 @@ FONTS = ('<link rel="preconnect" href="https://fonts.googleapis.com">\n'
'&amp;family=Exo+2:wght@600;700&amp;display=swap" rel="stylesheet">')
ORG = "https://starshipos-f18.org/"
PAGES = ["Main", "Inquiries", "TryIt"]
RELEASE_PAGES = ["Downloads", "Documents"]
RELEASES = "https://gitea.starshipos-f18.org/rajames/LithosAnanke/releases/download/"
IMAGES = {"/_blob/5b564d54d98e02ad600c913a9a1888f2": "badge.jpg",
"/_blob/5483451f292782a8b366e437181c4bcf": "captain-bob.jpg"}
@@ -44,11 +52,15 @@ CONSOLE = '''<div style="background: #050A14; border: 1px solid #34486A; border-
<p style="margin: 12px 0 0; font-size: 13px; color: #A3AEC2">If the console does not connect, every machine is in use: try again in a few minutes.</p>'''
def body(src):
def body(src, pages):
m = re.search(r"<x-dc>(.*)</x-dc>", src, re.S)
html = re.sub(r"<helmet>.*?</helmet>", "", m.group(1), flags=re.S).strip()
html = html.replace("{{accent}}", ACCENT)
for p in PAGES:
# a page not built this time is not linked to: its <a> taken out (the nav, the footers)
for p in RELEASE_PAGES:
if p not in pages:
html = re.sub(r'<a href="%s\.dc\.html"[^>]*>[^<]*</a>\n?' % p, "", html)
for p in pages:
html = html.replace('href="%s.dc.html"' % p, 'href="/bin/view/%s/"' % p)
html = html.replace('href="https://starshipos.org"', 'href="%s"' % ORG)
html = html.replace(">starshipos.org</a>", ">starshipos-f18.org</a>")
@@ -90,14 +102,43 @@ def forms(html, page):
return html
def release(html, tag, sums):
"""[TAG], [RELEASE]/<file> and [SHA:<file>] from the release; a file it has not is an error."""
html = html.replace("[TAG]", tag)
html = html.replace("[RELEASE]/", RELEASES + tag + "/")
def sha(m):
if m.group(1) not in sums:
sys.exit("build: %s is not in the release's SHA256SUMS" % m.group(1))
return sums[m.group(1)]
return re.sub(r"\[SHA:([^\]]+)\]", sha, html)
if __name__ == "__main__":
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("--release", help="the release's tag, e.g. v4.0.0-alpha.4")
ap.add_argument("--sums", help="the release's SHA256SUMS")
a = ap.parse_args()
if bool(a.release) != bool(a.sums):
sys.exit("build: --release and --sums go together")
sums = {}
if a.sums:
for l in open(a.sums).read().split("\n"):
f = l.split()
if len(f) == 2:
sums[f[1].lstrip("*").lstrip("./")] = f[0]
os.chdir(os.path.dirname(os.path.abspath(__file__)))
for p in PAGES:
html = forms(body(open("canvas/%s.dc.html" % p).read()), p)
pages = PAGES + (RELEASE_PAGES if a.release else [])
for p in pages:
html = forms(body(open("canvas/%s.dc.html" % p).read(), pages), p)
if p in RELEASE_PAGES:
html = release(html, a.release, sums)
if p == "TryIt":
html = try_it(html)
html = colorlock.lock(html, '<div style="background: #0A1222')
assert "{{" not in html.replace(colorlock.STYLE, "") and "[SSRN" not in html and ".dc.html" not in html and "_blob" not in html, p
assert "[TAG]" not in html and "[RELEASE]" not in html and "[SHA:" not in html, p
with open("%s.WebHome.xwiki" % p, "w") as f:
f.write(colorlock.GUEST_CHROME + '{{html clean="false"}}\n%s\n%s\n{{/html}}\n' % (FONTS, html))
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in PAGES))
print("wrote", ", ".join("%s.WebHome.xwiki" % p for p in pages))