diff --git a/.gitignore b/.gitignore index de3849f..2e5c5d0 100644 --- a/.gitignore +++ b/.gitignore @@ -20,15 +20,16 @@ test-results/ # New tool dist files must be force-added: git add -f tool/dist/tool.html dist/ -# Release artifacts — published to Codeberg release assets, not committed. -# website/releases/index.html and website/releases/manifest.json are -# regenerated by build.sh and DO get committed (they're tiny indices). -# Everything else under website/releases/ — versioned HTML tool files, -# zddc-server binaries — lives on Codeberg; the website's Caddy reverse- -# proxies download URLs to Codeberg release-asset URLs. -website/releases/*.html -!website/releases/index.html -website/releases/zddc-server-* +# Release artifacts under website/releases/ ARE committed — per-version HTML +# tool files (_v.html) accumulate as immutable real files; partial +# version pins (_v.html, _v.html) and channels +# (_.html) are checked-in symlinks. The build script +# (shared/build-lib.sh promote_release) maintains the symlink chain on each +# release. Caddy serves these as plain static files; no manifest, no proxy. +# +# zddc-server binaries are NOT committed — they're per-platform multi-MB +# binaries that ship as Codeberg release assets, attached to clean +# zddc-server-vX.Y.Z tags by zddc/release.sh. # IDE and project files .opencode/ diff --git a/bootstrap/level2.html.tmpl b/bootstrap/level2.html.tmpl index ae71f19..0fccfa7 100644 --- a/bootstrap/level2.html.tmpl +++ b/bootstrap/level2.html.tmpl @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // {{CHANNEL}} channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the {{CHANNEL}} default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the {{CHANNEL}} default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = '{{TOOL}}'; const defaultChannel = '{{CHANNEL}}'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/build.sh b/build.sh index 7258616..adf500f 100755 --- a/build.sh +++ b/build.sh @@ -124,71 +124,20 @@ EOF done } -# Regenerate website/releases/index.html and manifest.json from the -# Codeberg release list. Single API call at build time, no runtime -# dependency on Codeberg from the page (it's static HTML when served). +# Regenerate website/releases/index.html from a filesystem scan of +# website/releases/. Lists per-version files (real .html files, immutable +# archives) plus channel mirrors and partial-version pins (symlinks). # -# Page links use /releases// URLs which the website's Caddy -# reverse-proxies to codeberg.org/.../releases/download//. -# Operators see one origin (zddc.varasys.io); Codeberg is the storage -# backend. +# All URLs in the page resolve directly under /releases/ +# — no Codeberg API call, no manifest, no proxy magic. Page is static +# and current as of the last `sh build.sh` run. # -# Skips silently if curl/jq aren't on PATH (offline dev shouldn't blow -# up). Skips with a warning if the API call fails (network down, rate- -# limited, etc.) — the existing index.html stays as-is. +# zddc-server's section links to its Codeberg release pages directly +# (different distribution model — per-platform binaries). build_releases_index() { _out="$RELEASES_DIR/index.html" - _manifest="$RELEASES_DIR/manifest.json" mkdir -p "$RELEASES_DIR" - if ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then - echo " (curl or jq missing — skipping releases index regeneration)" - return 0 - fi - - _api_resp=$(curl -fsSL --max-time 30 \ - 'https://codeberg.org/api/v1/repos/VARASYS/ZDDC/releases?limit=100' \ - 2>/dev/null) || _api_resp="" - - if [ -z "$_api_resp" ]; then - echo " (Codeberg API unreachable — leaving releases/index.html as-is)" - return 0 - fi - - # Build manifest.json: for each tool/channel, find the latest matching - # release and emit "-": "". Channel resolution: - # alpha = latest tag matching -vX.Y.Z-alpha.N - # beta = latest tag matching -vX.Y.Z-beta.N - # stable = latest tag matching -vX.Y.Z (no suffix) - # "Latest" via sort -V on the version part. - _tools="archive transmittal classifier mdedit landing zddc-server" - { - printf '{\n' - _first=1 - for _tool in $_tools; do - for _ch in stable beta alpha; do - if [ "$_ch" = "stable" ]; then - _re="^${_tool}-v[0-9]+\\.[0-9]+\\.[0-9]+\$" - else - _re="^${_tool}-v[0-9]+\\.[0-9]+\\.[0-9]+-${_ch}\\.[0-9]+\$" - fi - _tag=$(printf '%s' "$_api_resp" \ - | jq -r --arg re "$_re" ' - [.[] | select(.tag_name | test($re)) | .tag_name] - | sort - | last // empty - ') - if [ -n "$_tag" ]; then - [ "$_first" = "1" ] || printf ',\n' - printf ' "%s-%s": "%s"' "$_tool" "$_ch" "$_tag" - _first=0 - fi - done - done - printf '\n}\n' - } > "$_manifest" - echo "Wrote $_manifest" - { cat <<'HEAD' @@ -252,109 +201,66 @@ build_releases_index() {
HEAD - # Render one section per tool. The HTML tool releases publish a - # single asset per tag (the inlined HTML); zddc-server publishes - # per-platform binaries. The renderer handles both. + # Render one section per HTML tool, scanning website/releases/ for + # _v*.html real files (per-version archives) and resolving the + # current channel symlinks. for _tool_entry in 'archive|Archive' \ 'transmittal|Transmittal' \ 'classifier|Classifier' \ 'mdedit|Markdown Editor' \ - 'landing|Landing (project picker)' \ - 'zddc-server|zddc-server (Go file server)'; do + 'landing|Landing (project picker)'; do _tool="${_tool_entry%%|*}" _title="${_tool_entry#*|}" - _re_stable="^${_tool}-v[0-9]+\\.[0-9]+\\.[0-9]+\$" - _re_alpha="^${_tool}-v[0-9]+\\.[0-9]+\\.[0-9]+-alpha\\.[0-9]+\$" - _re_beta="^${_tool}-v[0-9]+\\.[0-9]+\\.[0-9]+-beta\\.[0-9]+\$" - _latest_stable=$(printf '%s' "$_api_resp" | jq -r --arg re "$_re_stable" \ - '[.[] | select(.tag_name | test($re)) | .tag_name] | sort | last // empty') - _latest_beta=$(printf '%s' "$_api_resp" | jq -r --arg re "$_re_beta" \ - '[.[] | select(.tag_name | test($re)) | .tag_name] | sort | last // empty') - _latest_alpha=$(printf '%s' "$_api_resp" | jq -r --arg re "$_re_alpha" \ - '[.[] | select(.tag_name | test($re)) | .tag_name] | sort | last // empty') - _all_stables=$(printf '%s' "$_api_resp" | jq -r --arg re "$_re_stable" \ - '[.[] | select(.tag_name | test($re)) | .tag_name] | sort | reverse | .[]') + # All per-version real files for this tool, semver-descending. + # Use find to filter out symlinks; grep + sort -Vr for ordering. + _versioned=$(find "$RELEASES_DIR" -maxdepth 1 -type f -name "${_tool}_v*.html" 2>/dev/null \ + | sed "s|^${RELEASES_DIR}/||" \ + | sort -Vr) - # Skip the section entirely if no releases exist for this tool. - if [ -z "$_latest_stable$_latest_beta$_latest_alpha" ]; then + if [ -z "$_versioned" ]; then continue fi printf '
\n' printf '

%s

\n' "$_title" - # Channel chips. Each link uses /releases// - # which Caddy proxies to the Codeberg release-asset URL. - # Asset name is _v.html for HTML tools; for - # zddc-server we link to the Codeberg release page since - # the asset is per-platform (operator picks one). + # Channel chips — only render if the symlink exists. printf '
\n' - for _row in "stable|$_latest_stable" "beta|$_latest_beta" "alpha|$_latest_alpha"; do - _ch="${_row%%|*}" - _tag="${_row#*|}" - [ -n "$_tag" ] || continue - if [ "$_tool" = "zddc-server" ]; then - printf ' %s\n' \ - "$_ch" "$_tag" "$_ch" - else - _ver="${_tag#${_tool}-v}" - _asset="${_tool}_v${_ver}.html" - printf ' %s\n' \ - "$_ch" "$_tag" "$_asset" "$_ch" + for _ch in stable beta alpha; do + _link="${_tool}_${_ch}.html" + if [ -e "$RELEASES_DIR/$_link" ]; then + printf ' %s\n' "$_ch" "$_link" "$_ch" fi done printf '
\n' - # zddc-server: per-platform binary table, one row per channel. - if [ "$_tool" = "zddc-server" ]; then - _platforms="linux-amd64 darwin-amd64 darwin-arm64 windows-amd64" - printf '

Standalone binaries

\n' - printf ' ' - for _p in $_platforms; do printf '' "$_p"; done - printf '\n' - for _row in "stable|$_latest_stable" "beta|$_latest_beta" "alpha|$_latest_alpha"; do - _ch="${_row%%|*}" - _tag="${_row#*|}" - printf ' ' "$_ch" "$_ch" - if [ -z "$_tag" ]; then - for _p in $_platforms; do printf ''; done - else - for _p in $_platforms; do - _ext=""; case "$_p" in windows-*) _ext=".exe" ;; esac - _asset="zddc-server-${_p}${_ext}" - printf '' "$_tag" "$_asset" - done - fi - printf '\n' - done - printf '
Channel%s
%sdownload
\n' - fi - - # Pin-to-version row. All stables (semver-descending). HTML - # tools link to the asset directly; zddc-server links to the - # Codeberg release page (per-platform asset choice). - if [ -n "$_all_stables" ]; then - printf '
Pin to version:\n' - printf '%s\n' "$_all_stables" | while read -r _t; do - [ -n "$_t" ] || continue - _v="${_t#${_tool}-v}" - if [ "$_tool" = "zddc-server" ]; then - printf ' v%s\n' "$_t" "$_v" - else - printf ' v%s\n' "$_t" "$_tool" "$_v" "$_v" - fi - done - printf '
\n' - fi + # Pin-to-version row: every per-version real file, descending. + printf '
Pin to version:\n' + printf '%s\n' "$_versioned" | while read -r _f; do + [ -n "$_f" ] || continue + # Display as v stripped of _v prefix and .html suffix. + _v="${_f#${_tool}_v}" + _v="${_v%.html}" + printf ' v%s\n' "$_f" "$_v" + done + printf '
\n' printf '
\n' done + # zddc-server section — links to Codeberg release pages directly, + # since binaries don't live under website/releases/. + printf '
\n' + printf '

zddc-server (Go file server)

\n' + printf '

Binaries are published as Codeberg release assets. Pick a platform from the release page; or build from source via the helm charts under helm/.

\n' + printf '

Browse zddc-server releases on Codeberg →

\n' + printf '
\n' + cat <<'TAIL'
-

Append ?v=alpha, ?v=beta, ?v=stable, or ?v=0.0.1 to any deployment URL to switch versions for a single request — see the home page.

+

Append ?v=stable, ?v=beta, ?v=alpha, ?v=0.0 (latest 0.0.x), or ?v=0.0.1 (exact) to any deployment URL to switch versions for a single request — see the home page.

diff --git a/shared/build-lib.sh b/shared/build-lib.sh index 3e3008d..cb29ca2 100755 --- a/shared/build-lib.sh +++ b/shared/build-lib.sh @@ -21,14 +21,17 @@ # — sets globals: build_label, build_version, # is_release, is_red, channel. # See "Channels and release args" below. -# promote_release — for stable / alpha / beta, tag the -# commit and upload the dist HTML as a -# Codeberg release asset. No local mirror -# under website/releases/ — the website -# reverse-proxies download URLs to Codeberg -# release-asset URLs. Stable cuts skip when -# the tool's source is unchanged since the -# latest stable tag. +# promote_release — for stable / alpha / beta, copy the dist +# HTML into website/releases/. Stable cuts +# write the immutable per-version file + +# refresh five symlinks (_v, _v, +# _stable, _beta, _alpha) and tag +# -v. Alpha/beta cuts +# overwrite the channel mirror in place +# and cascade alpha → beta. No git tags +# for alpha/beta cuts; no Codeberg upload +# for HTML tools. See ARCHITECTURE.md +# "Channels" for the full table. # # Channels and release args: # dev build, dist/ only, label @@ -36,13 +39,14 @@ # No website/releases/ side-effect. To publish, re-run # with `--release alpha`. # --release stable, auto-bump patch from latest tag (or 0.0.1). -# Label "vX.Y.Z" (black). Tags + uploads. -# --release X.Y.Z stable, explicit version. Tags + uploads. +# Writes per-version file + symlinks; tags vX.Y.Z. +# --release X.Y.Z stable, explicit version. # --release alpha alpha channel cut at HEAD; # label "v-alpha · · " (red). -# Tags -vX.Y.Z-alpha.N + uploads. +# Overwrites _alpha.html. No tag. # --release beta beta channel; label "v-beta · · ". -# Tags + uploads. +# Overwrites _beta.html. Cascades _alpha.html +# → _beta.html (symlink). No tag. # --release error. # ============================================================================= @@ -52,10 +56,9 @@ if [ -z "${root_dir:-}" ]; then exit 1 fi -# Pull in the Codeberg release-publish helper so promote_release can call -# its publish_codeberg_release function. Sourced unconditionally — the -# helper has no side effects when sourced (only defines functions). -. "$root_dir/../shared/publish-codeberg-release.sh" +# NOTE: shared/publish-codeberg-release.sh is no longer sourced here. +# HTML tools publish to website/releases/ as committed static files; only +# zddc-server/release.sh uploads to Codeberg (it sources the helper directly). # Fail hard on any missing source file ensure_exists() { @@ -101,58 +104,6 @@ escape_js_close_tags() { sed 's# "$2" } -# Echo the next pre-release version for a given channel + tag prefix. -# next_prerelease -# -# Channel must be alpha or beta. Tag prefix is the leading text on this -# tool's stable git tags — e.g. "zddc-server-v" or "archive-v" — so the -# function can be called from either the server release script or any -# HTML tool's build.sh against the same monorepo tag namespace. -# -# Algorithm: -# 1. Walk tags matching X.Y.Z (clean stable, no suffix); pick the -# semver-highest. Default 0.0.0 if no stable tag exists yet. -# 2. Bump the patch component → next_patch. -# 3. Count existing tags of the form -.* -# and emit -.. -# -# The patch-bump assumption: every active pre-release window targets the -# next patch of the latest stable. Cutting a real stable resets the -# counter naturally because next_patch advances. Operators wanting a -# minor or major bump cut stable explicitly with a version arg, then the -# subsequent alphas auto-derive against the new stable. -next_prerelease() { - _channel="$1" - _prefix="$2" - case "$_channel" in - alpha | beta) ;; - *) echo "next_prerelease: channel must be alpha or beta (got '$_channel')" >&2; return 1 ;; - esac - if [ -z "$_prefix" ]; then - echo "next_prerelease: tag prefix is required" >&2 - return 1 - fi - - _latest=$(git -C "$root_dir" tag --list "${_prefix}*" 2>/dev/null \ - | grep -E "^${_prefix}[0-9]+\.[0-9]+\.[0-9]+\$" \ - | sed "s|^${_prefix}||" \ - | sort -V \ - | tail -1) - [ -n "$_latest" ] || _latest="0.0.0" - - _major="${_latest%%.*}" - _rest="${_latest#*.}" - _minor="${_rest%%.*}" - _patch="${_rest#*.}" - _patch=$((_patch + 1)) - _next_patch="${_major}.${_minor}.${_patch}" - - _count=$(git -C "$root_dir" tag --list "${_prefix}${_next_patch}-${_channel}.*" 2>/dev/null | wc -l | tr -d ' ') - _count=$((_count + 1)) - - echo "${_next_patch}-${_channel}.${_count}" -} - # Validate that $1 is a strict X.Y.Z numeric version, where each component # is a non-empty numeric string. Exits with an error if not. _validate_semver() { @@ -264,33 +215,44 @@ _next_stable_for_tool() { echo "${_major}.${_minor}.$((_patch + 1))" } -# Promote a built dist file to a Codeberg release. -# Reads from caller scope: $channel, $build_version, $output_html, $root_dir. +# Promote a built dist file to website/releases/. Reads from caller scope: +# $channel ("stable" / "alpha" / "beta"), $build_version (stable only), +# $output_html, $root_dir. # -# All three channels (alpha, beta, stable) follow the same shape now: -# 1. Compute the version (already done by compute_build_label for stable; -# for alpha/beta we compute next_prerelease here). -# 2. Tag the commit -v (or -v-CHANNEL.N). -# 3. Upload the built dist HTML as a release asset to Codeberg. +# Stable cuts: +# 1. Skip if source unchanged since latest stable tag. +# 2. Copy dist HTML → website/releases/_v.html (immutable). +# 3. Refresh symlinks: _v, _v, _stable, _beta, _alpha all → the +# new versioned file. Cascade rule: stable cut means beta and alpha +# reset to stable (no active dev on either downstream channel). +# 4. Tag the commit -v. # -# Idempotent: the publish helper replaces a same-named asset on re-upload, -# and the tag step is a no-op if the tag already points at HEAD. +# Alpha/beta cuts: +# 1. Overwrite website/releases/_.html with dist HTML +# (replaces a symlink with real bytes if one was there). +# 2. For beta: cascade _alpha.html → _beta.html (symlink), +# since alpha defaults to beta when no active alpha. +# 3. No tag — channel URLs are stable URLs by design; counters defeat +# that. The on-page label encodes · for traceability. # -# For stable: the original "skip if no source change since latest stable -# tag" guard still applies — pointless re-releases are silently no-op'd. -# For alpha/beta: the auto-incrementing counter already differentiates -# successive cuts, so no skip check. +# Plain dev builds (no --release): never call promote_release. # -# Requires $CODEBERG_TOKEN exported. publish_codeberg_release surfaces a -# clear error if it isn't. +# No Codeberg upload — HTML tools live in git. zddc-server's release.sh +# handles binary uploads to Codeberg directly (different distribution model). promote_release() { _tool="$1" + _releases_dir="$root_dir/../website/releases" + + if [ ! -d "$_releases_dir" ]; then + echo "promote_release: $_releases_dir not found" >&2 + return 1 + fi case "$channel" in stable) if [ -z "$build_version" ]; then echo "promote_release: stable channel but no build_version" >&2 - exit 1 + return 1 fi _latest=$(git -C "$root_dir" tag --list "${_tool}-v*" 2>/dev/null \ | grep -E "^${_tool}-v[0-9]+\.[0-9]+\.[0-9]+\$" \ @@ -299,25 +261,49 @@ promote_release() { echo "${_tool}: no source changes since $_latest — skipping" return 0 fi - _version="$build_version" + _promote_stable "$_tool" "$build_version" "$_releases_dir" ;; alpha | beta) - _version=$(next_prerelease "$channel" "${_tool}-v") + _promote_channel "$_tool" "$channel" "$_releases_dir" ;; *) echo "promote_release: unknown channel '$channel'" >&2 - exit 1 + return 1 ;; esac +} - _tag="${_tool}-v${_version}" +# Stable cut: per-version file + 5 symlinks + git tag. +_promote_stable() { + _t="$1" + _ver="$2" + _rdir="$3" - # Tag the commit (idempotent: skip if already at HEAD). + _major="${_ver%%.*}" + _rest="${_ver#*.}" + _minor="${_rest%%.*}" + _versioned="${_t}_v${_ver}.html" + + cp "$output_html" "$_rdir/$_versioned" + echo "Wrote $_rdir/$_versioned" + + # Refresh the 5 symlinks. Cascade: stable cut → beta + alpha both + # reset to stable (no active dev on either downstream channel). + for _sym in "${_t}_v${_major}.${_minor}.html" \ + "${_t}_v${_major}.html" \ + "${_t}_stable.html" \ + "${_t}_beta.html" \ + "${_t}_alpha.html"; do + ln -sfn "$_versioned" "$_rdir/$_sym" + echo " $_sym → $_versioned" + done + + _tag="${_t}-v${_ver}" if git -C "$root_dir" rev-parse -q --verify "refs/tags/$_tag" >/dev/null; then _existing=$(git -C "$root_dir" rev-list -n 1 "$_tag") _head=$(git -C "$root_dir" rev-parse HEAD) if [ "$_existing" != "$_head" ]; then - echo "promote_release: tag $_tag already exists at $_existing, but HEAD is $_head" >&2 + echo "promote_release: tag $_tag exists at $_existing but HEAD is $_head" >&2 return 1 fi echo "(tag $_tag already at HEAD)" @@ -326,21 +312,28 @@ promote_release() { echo "tagged $_tag" fi - # Upload to Codeberg. The asset name embeds the version so consumers - # can pin to a specific build (e.g. _v0.0.3-alpha.1.html). - _asset="${_tool}_v${_version}.html" - _staged="$root_dir/$_tool/dist/$_asset" - cp "$output_html" "$_staged" - if ! command -v publish_codeberg_release >/dev/null 2>&1; then - # build-lib.sh is sourced before publish-codeberg-release.sh in the - # canonical wrapper scripts; if the helper isn't loaded yet, bail - # with a clear pointer. - echo "promote_release: publish_codeberg_release not available; source shared/publish-codeberg-release.sh first" >&2 - return 1 - fi - publish_codeberg_release "VARASYS/ZDDC" "$_tag" "$_staged" - rm -f "$_staged" - - echo "Released $_tag (channel: $channel, version: $_version)" + echo "Released ${_t} v${_ver} (stable)" echo " publish git tag with: git push origin $_tag" } + +# Alpha/beta cut: overwrite mutable channel mirror; cascade alpha → beta +# on a beta cut (alpha defaults to beta when no active alpha). +_promote_channel() { + _t="$1" + _ch="$2" + _rdir="$3" + + _file="${_t}_${_ch}.html" + # Replace symlink (if present) with real bytes by removing first; + # cp -f follows symlinks and would overwrite the symlink target. + rm -f "$_rdir/$_file" + cp "$output_html" "$_rdir/$_file" + echo "Wrote $_rdir/$_file" + + if [ "$_ch" = "beta" ]; then + ln -sfn "$_file" "$_rdir/${_t}_alpha.html" + echo " ${_t}_alpha.html → $_file" + fi + + echo "Released ${_t} ${_ch}" +} diff --git a/tests/build-label.spec.js b/tests/build-label.spec.js index 651498b..1389510 100644 --- a/tests/build-label.spec.js +++ b/tests/build-label.spec.js @@ -44,11 +44,12 @@ for (const tool of tools) { const match = html.match(/class="build-timestamp">(?:]*>)?([^<]+?)(?:<\/span>)?-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'archive'; const defaultChannel = 'alpha'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-alpha/classifier.html b/website/bootstrap/track-alpha/classifier.html index 8149ff3..b4d6b76 100644 --- a/website/bootstrap/track-alpha/classifier.html +++ b/website/bootstrap/track-alpha/classifier.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // alpha channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the alpha default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the alpha default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'classifier'; const defaultChannel = 'alpha'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-alpha/index.html b/website/bootstrap/track-alpha/index.html index b8a9115..919d4fe 100644 --- a/website/bootstrap/track-alpha/index.html +++ b/website/bootstrap/track-alpha/index.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // alpha channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the alpha default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the alpha default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'landing'; const defaultChannel = 'alpha'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-alpha/mdedit.html b/website/bootstrap/track-alpha/mdedit.html index 899b29e..f4329d2 100644 --- a/website/bootstrap/track-alpha/mdedit.html +++ b/website/bootstrap/track-alpha/mdedit.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // alpha channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the alpha default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the alpha default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'mdedit'; const defaultChannel = 'alpha'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-alpha/transmittal.html b/website/bootstrap/track-alpha/transmittal.html index 72115ba..6a542f5 100644 --- a/website/bootstrap/track-alpha/transmittal.html +++ b/website/bootstrap/track-alpha/transmittal.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // alpha channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the alpha default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the alpha default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'transmittal'; const defaultChannel = 'alpha'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-beta/archive.html b/website/bootstrap/track-beta/archive.html index c15ae95..850faf8 100644 --- a/website/bootstrap/track-beta/archive.html +++ b/website/bootstrap/track-beta/archive.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // beta channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the beta default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the beta default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'archive'; const defaultChannel = 'beta'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-beta/classifier.html b/website/bootstrap/track-beta/classifier.html index 7311ba6..b6c8753 100644 --- a/website/bootstrap/track-beta/classifier.html +++ b/website/bootstrap/track-beta/classifier.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // beta channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the beta default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the beta default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'classifier'; const defaultChannel = 'beta'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-beta/index.html b/website/bootstrap/track-beta/index.html index e2f3b58..b1801bf 100644 --- a/website/bootstrap/track-beta/index.html +++ b/website/bootstrap/track-beta/index.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // beta channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the beta default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the beta default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'landing'; const defaultChannel = 'beta'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-beta/mdedit.html b/website/bootstrap/track-beta/mdedit.html index 8ca27bd..87a8873 100644 --- a/website/bootstrap/track-beta/mdedit.html +++ b/website/bootstrap/track-beta/mdedit.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // beta channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the beta default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the beta default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'mdedit'; const defaultChannel = 'beta'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-beta/transmittal.html b/website/bootstrap/track-beta/transmittal.html index f6bed9f..1f2fd93 100644 --- a/website/bootstrap/track-beta/transmittal.html +++ b/website/bootstrap/track-beta/transmittal.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // beta channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the beta default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the beta default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'transmittal'; const defaultChannel = 'beta'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-stable/archive.html b/website/bootstrap/track-stable/archive.html index 250eee5..fdcb74a 100644 --- a/website/bootstrap/track-stable/archive.html +++ b/website/bootstrap/track-stable/archive.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // stable channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the stable default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the stable default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'archive'; const defaultChannel = 'stable'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-stable/classifier.html b/website/bootstrap/track-stable/classifier.html index 9d4a09b..526b482 100644 --- a/website/bootstrap/track-stable/classifier.html +++ b/website/bootstrap/track-stable/classifier.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // stable channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the stable default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the stable default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'classifier'; const defaultChannel = 'stable'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-stable/index.html b/website/bootstrap/track-stable/index.html index c91b48f..69498af 100644 --- a/website/bootstrap/track-stable/index.html +++ b/website/bootstrap/track-stable/index.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // stable channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the stable default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the stable default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'landing'; const defaultChannel = 'stable'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-stable/mdedit.html b/website/bootstrap/track-stable/mdedit.html index ebe2136..a56643e 100644 --- a/website/bootstrap/track-stable/mdedit.html +++ b/website/bootstrap/track-stable/mdedit.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // stable channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the stable default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the stable default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'mdedit'; const defaultChannel = 'stable'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/bootstrap/track-stable/transmittal.html b/website/bootstrap/track-stable/transmittal.html index 405ed39..bbca1e1 100644 --- a/website/bootstrap/track-stable/transmittal.html +++ b/website/bootstrap/track-stable/transmittal.html @@ -14,47 +14,33 @@ // document.write()s it in place. The default upstream is the // stable channel; the URL parameter ?v= overrides it: // - // ?v=alpha|beta|stable switches to that channel - // ?v=0.0.4 (or v0.0.4) pins to that exact stable version - // (none) uses the stable default + // ?v=stable | beta | alpha switch to that channel + // ?v=0.0.4 (or v0.0.4) pin to that exact stable version + // ?v=0.0 (or v0.0) pin to latest patch within 0.0.x (symlink) + // ?v=0 (or v0) pin to latest within 0.x (symlink) + // (none) use the stable default // - // Resolution path: - // 1. Channel mode (no ?v= or ?v={alpha,beta,stable}): fetch - // manifest.json from the same origin, look up - // "-" → tag, then fetch the asset. - // 2. Version pin: build the URL directly (skip manifest). - // - // The asset URL is /releases//_v.html. Caddy on - // zddc.varasys.io reverse-proxies that to the Codeberg release-asset - // URL — neither this stub nor the user's browser hits codeberg.org - // directly. + // Resolution is purely static — every URL maps to a real file or a + // checked-in symlink under /releases/. No manifest lookup, + // no JS indirection, no client-side version arithmetic. (async function () { const params = new URLSearchParams(location.search); const v = params.get('v'); const tool = 'transmittal'; const defaultChannel = 'stable'; - const channels = ['alpha', 'beta', 'stable']; + const channels = ['stable', 'beta', 'alpha']; const base = 'https://zddc.varasys.io/releases/'; - function isChannel(s) { return channels.indexOf(s) >= 0; } + function suffixFor(value) { + if (!value) return '_' + defaultChannel; + if (channels.indexOf(value) >= 0) return '_' + value; + // Strip optional leading 'v', accept "0.0.4" / "0.0" / "0". + const ver = value.startsWith('v') ? value.slice(1) : value; + return '_v' + ver; + } try { - let assetUrl; - if (v && !isChannel(v)) { - // Explicit version pin (e.g. ?v=0.0.4 or ?v=v0.0.4). - const ver = v.replace(/^v/, ''); - const tag = tool + '-v' + ver; - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } else { - // Channel mode: resolve via manifest. - const channel = (v && isChannel(v)) ? v : defaultChannel; - const manifest = await (await fetch(base + 'manifest.json', { cache: 'no-cache', credentials: 'omit' })).json(); - const tag = manifest[tool + '-' + channel]; - if (!tag) throw new Error('manifest has no entry for ' + tool + '-' + channel); - const ver = tag.replace(tool + '-v', ''); - assetUrl = base + tag + '/' + tool + '_v' + ver + '.html'; - } - + const assetUrl = base + tool + suffixFor(v) + '.html'; const resp = await fetch(assetUrl, { cache: 'no-cache', credentials: 'omit' }); if (!resp.ok) throw new Error(resp.status + ' ' + resp.statusText); const html = await resp.text(); diff --git a/website/releases/archive_alpha.html b/website/releases/archive_alpha.html new file mode 120000 index 0000000..1e746ff --- /dev/null +++ b/website/releases/archive_alpha.html @@ -0,0 +1 @@ +archive_v0.0.2.html \ No newline at end of file diff --git a/website/releases/archive_beta.html b/website/releases/archive_beta.html new file mode 120000 index 0000000..1e746ff --- /dev/null +++ b/website/releases/archive_beta.html @@ -0,0 +1 @@ +archive_v0.0.2.html \ No newline at end of file diff --git a/website/releases/archive_stable.html b/website/releases/archive_stable.html new file mode 120000 index 0000000..1e746ff --- /dev/null +++ b/website/releases/archive_stable.html @@ -0,0 +1 @@ +archive_v0.0.2.html \ No newline at end of file diff --git a/website/releases/archive_v0.0.1.html b/website/releases/archive_v0.0.1.html new file mode 100644 index 0000000..753b624 --- /dev/null +++ b/website/releases/archive_v0.0.1.html @@ -0,0 +1,7800 @@ + + + + + + ZDDC Archive + + + +
+ + + + +
+
+
+ ZDDC Archive + v0.0.1 +
+ + +
+
+ + +
+
+ + +
+ + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +
+ + + +
+
+ + +
+ + + + + + + + + + + +
+
+ Tracking Number + +
+ +
+
+
+ Title + +
+ +
+
+
+ + Revisions +
+ +
+
+
+ + +
+ 0 files + 0 selected + +
+
+
+ + + + + +
+
+

Welcome to ZDDC Archive

+

Click Add Local Directory to select an archive folder to browse.

+

This browser provides a convenient interface for searching and retrieving files from ZDDC-compliant archives.

+

How to navigate:

+
    +
  • Select a party to see their transmittal folders; toggle folder types (Issued, Received, MDL, Incoming) above the list
  • +
  • Select transmittal folders to see their files
  • +
  • Use Ctrl+Click to select multiple folders
  • +
  • Use Shift+Click to select a range
  • +
  • Ctrl+Click chevrons to recursively expand/collapse
  • +
+ +
+ ⚠️ Windows Path Length Deficiency +
+

Microsoft Windows has a legacy 260-character path limit that affects most applications. If you see "files skipped" warnings, use Microsoft's own workaround:

+
    +
  1. Open Command Prompt as Administrator
  2. +
  3. Map your archive to a short drive letter:
    + subst Z: "C:\Your\Long\Path\To\Archive" +
  4. +
  5. Use the Z: drive in Archive Browser
  6. +
  7. To remove later: subst Z: /d
  8. +
+

This limitation dates back to Windows 95. The mapping persists until reboot.

+
+
+ +

Note: This application works entirely in your browser and does not transmit any data.

+
+
+ + + + + +
+ + + + diff --git a/website/releases/archive_v0.0.2.html b/website/releases/archive_v0.0.2.html new file mode 100644 index 0000000..05b3e7b --- /dev/null +++ b/website/releases/archive_v0.0.2.html @@ -0,0 +1,7833 @@ + + + + + + ZDDC Archive + + + + +
+ + + + +
+
+
+ ZDDC Archive + v0.0.2 +
+ + +
+
+ + +
+
+ + +
+ + + + +
+ +
+ + + + + + + +
+ + +
+ +
+ +
+ + + +
+
+ + +
+ + + + + + + + + + + +
+
+ Tracking Number + +
+ +
+
+
+ Title + +
+ +
+
+
+ + Revisions +
+ +
+
+
+ + +
+ 0 files + 0 selected + +
+
+
+ + + + + +
+
+

Welcome to ZDDC Archive

+

Click Add Local Directory to select an archive folder to browse.

+

This browser provides a convenient interface for searching and retrieving files from ZDDC-compliant archives.

+

How to navigate:

+
    +
  • Select a party to see their transmittal folders; toggle folder types (Issued, Received, MDL, Incoming) above the list
  • +
  • Select transmittal folders to see their files
  • +
  • Use Ctrl+Click to select multiple folders
  • +
  • Use Shift+Click to select a range
  • +
  • Ctrl+Click chevrons to recursively expand/collapse
  • +
+ +
+ ⚠️ Windows Path Length Deficiency +
+

Microsoft Windows has a legacy 260-character path limit that affects most applications. If you see "files skipped" warnings, use Microsoft's own workaround:

+
    +
  1. Open Command Prompt as Administrator
  2. +
  3. Map your archive to a short drive letter:
    + subst Z: "C:\Your\Long\Path\To\Archive" +
  4. +
  5. Use the Z: drive in Archive Browser
  6. +
  7. To remove later: subst Z: /d
  8. +
+

This limitation dates back to Windows 95. The mapping persists until reboot.

+
+
+ +

Note: This application works entirely in your browser and does not transmit any data.

+
+
+ + + + + +
+ + + + diff --git a/website/releases/archive_v0.0.html b/website/releases/archive_v0.0.html new file mode 120000 index 0000000..1e746ff --- /dev/null +++ b/website/releases/archive_v0.0.html @@ -0,0 +1 @@ +archive_v0.0.2.html \ No newline at end of file diff --git a/website/releases/archive_v0.html b/website/releases/archive_v0.html new file mode 120000 index 0000000..1e746ff --- /dev/null +++ b/website/releases/archive_v0.html @@ -0,0 +1 @@ +archive_v0.0.2.html \ No newline at end of file diff --git a/website/releases/classifier_alpha.html b/website/releases/classifier_alpha.html new file mode 120000 index 0000000..040a480 --- /dev/null +++ b/website/releases/classifier_alpha.html @@ -0,0 +1 @@ +classifier_v0.0.2.html \ No newline at end of file diff --git a/website/releases/classifier_beta.html b/website/releases/classifier_beta.html new file mode 120000 index 0000000..040a480 --- /dev/null +++ b/website/releases/classifier_beta.html @@ -0,0 +1 @@ +classifier_v0.0.2.html \ No newline at end of file diff --git a/website/releases/classifier_stable.html b/website/releases/classifier_stable.html new file mode 120000 index 0000000..040a480 --- /dev/null +++ b/website/releases/classifier_stable.html @@ -0,0 +1 @@ +classifier_v0.0.2.html \ No newline at end of file diff --git a/website/releases/classifier_v0.0.1.html b/website/releases/classifier_v0.0.1.html new file mode 100644 index 0000000..b02ed36 --- /dev/null +++ b/website/releases/classifier_v0.0.1.html @@ -0,0 +1,6971 @@ + + + + + + ZDDC Classifier + + + +
+ +
+ +
+
+
+ ZDDC Classifier + v0.0.1 +
+ + +
+
+ + +
+
+ + +
+ + + + +
+
+
+

Files

+
+ 0 files + 0 modified + +
+
+
+ + + | + + + | + +
+
+
+ + + + + + + + + + + + + + + + + +
#Original Filename + + Ext + + New Filename + + Tracking + + Rev + + Status + + Title + +
+
+
+ +
+ + +
+
+

ZDDC Classifier

+

Rename a folder of files to ZDDC format using a spreadsheet interface.

+

Open a directory, fill in tracking number, revision, status, and title for each file, then save — the files are renamed on disk.

+ + + + +
    +
  • Files already named to ZDDC format are parsed automatically
  • +
  • Edit cells directly, or copy columns to and from Excel
  • +
  • Real-time validation highlights non-compliant names
  • +
  • Rename one file or all modified files at once
  • +
+ +

Click Select Directory to begin.

+ +

This application works entirely in your browser. No data is transmitted to any server.

+
+
+
+ + + +
+ + + + diff --git a/website/releases/classifier_v0.0.2.html b/website/releases/classifier_v0.0.2.html new file mode 100644 index 0000000..54d7c50 --- /dev/null +++ b/website/releases/classifier_v0.0.2.html @@ -0,0 +1,6972 @@ + + + + + + ZDDC Classifier + + + + +
+ +
+ +
+
+
+ ZDDC Classifier + v0.0.2 +
+ + +
+
+ + +
+
+ + +
+ + + + +
+
+
+

Files

+
+ 0 files + 0 modified + +
+
+
+ + + | + + + | + +
+
+
+ + + + + + + + + + + + + + + + + +
#Original Filename + + Ext + + New Filename + + Tracking + + Rev + + Status + + Title + +
+
+
+ +
+ + +
+
+

ZDDC Classifier

+

Rename a folder of files to ZDDC format using a spreadsheet interface.

+

Open a directory, fill in tracking number, revision, status, and title for each file, then save — the files are renamed on disk.

+ + + + +
    +
  • Files already named to ZDDC format are parsed automatically
  • +
  • Edit cells directly, or copy columns to and from Excel
  • +
  • Real-time validation highlights non-compliant names
  • +
  • Rename one file or all modified files at once
  • +
+ +

Click Select Directory to begin.

+ +

This application works entirely in your browser. No data is transmitted to any server.

+
+
+
+ + + +
+ + + + diff --git a/website/releases/classifier_v0.0.html b/website/releases/classifier_v0.0.html new file mode 120000 index 0000000..040a480 --- /dev/null +++ b/website/releases/classifier_v0.0.html @@ -0,0 +1 @@ +classifier_v0.0.2.html \ No newline at end of file diff --git a/website/releases/classifier_v0.html b/website/releases/classifier_v0.html new file mode 120000 index 0000000..040a480 --- /dev/null +++ b/website/releases/classifier_v0.html @@ -0,0 +1 @@ +classifier_v0.0.2.html \ No newline at end of file diff --git a/website/releases/index.html b/website/releases/index.html index fa8f3ff..135e1da 100644 --- a/website/releases/index.html +++ b/website/releases/index.html @@ -61,68 +61,71 @@

Archive

Pin to version: - v0.0.2 - v0.0.1 + v0.0.2 + v0.0.1

Transmittal

Pin to version: - v0.0.2 - v0.0.1 + v0.0.2 + v0.0.1

Classifier

Pin to version: - v0.0.2 - v0.0.1 + v0.0.2 + v0.0.1

Markdown Editor

Pin to version: - v0.0.2 - v0.0.1 + v0.0.2 + v0.0.1

Landing (project picker)

Pin to version: - v0.0.2 - v0.0.1 + v0.0.2 + v0.0.1

zddc-server (Go file server)

-
- alpha -
-

Standalone binaries

- - - - -
Channellinux-amd64darwin-amd64darwin-arm64windows-amd64
stable
beta
alphadownloaddownloaddownloaddownload
+

Binaries are published as Codeberg release assets. Pick a platform from the release page; or build from source via the helm charts under helm/.

+

Browse zddc-server releases on Codeberg →

-

Append ?v=alpha, ?v=beta, ?v=stable, or ?v=0.0.1 to any deployment URL to switch versions for a single request — see the home page.

+

Append ?v=stable, ?v=beta, ?v=alpha, ?v=0.0 (latest 0.0.x), or ?v=0.0.1 (exact) to any deployment URL to switch versions for a single request — see the home page.

diff --git a/website/releases/landing_alpha.html b/website/releases/landing_alpha.html new file mode 120000 index 0000000..6c365e6 --- /dev/null +++ b/website/releases/landing_alpha.html @@ -0,0 +1 @@ +landing_v0.0.2.html \ No newline at end of file diff --git a/website/releases/landing_beta.html b/website/releases/landing_beta.html new file mode 120000 index 0000000..6c365e6 --- /dev/null +++ b/website/releases/landing_beta.html @@ -0,0 +1 @@ +landing_v0.0.2.html \ No newline at end of file diff --git a/website/releases/landing_stable.html b/website/releases/landing_stable.html new file mode 120000 index 0000000..6c365e6 --- /dev/null +++ b/website/releases/landing_stable.html @@ -0,0 +1 @@ +landing_v0.0.2.html \ No newline at end of file diff --git a/website/releases/landing_v0.0.1.html b/website/releases/landing_v0.0.1.html new file mode 100644 index 0000000..e7c0831 --- /dev/null +++ b/website/releases/landing_v0.0.1.html @@ -0,0 +1,1029 @@ + + + + + + ZDDC Archive — Projects + + + +
+
+ ZDDC Archive + v0.0.1 +
+
+ +
+
+ +
+ + + +
+
+

Select Projects

+
+ +
+ + +
+ + +
+
+ +
+ +
+ + +
+
+ + + + diff --git a/website/releases/landing_v0.0.2.html b/website/releases/landing_v0.0.2.html new file mode 100644 index 0000000..0d44c75 --- /dev/null +++ b/website/releases/landing_v0.0.2.html @@ -0,0 +1,2199 @@ + + + + + + ZDDC Archive — Projects + + + + +
+
+ ZDDC Archive + v0.0.2 +
+
+ +
+
+ +
+ +
+

Welcome to the ZDDC Archive

+

+ Pick the projects you want to view, then open the archive. Filter by + project number or title, and save your selection as a preset to + share or come back to later. +

+
+ + + + + +
+
+
+

Projects

+ +
+
+ +
+ +
Loading projects…
+
+ + +
+
+ + + + diff --git a/website/releases/landing_v0.0.html b/website/releases/landing_v0.0.html new file mode 120000 index 0000000..6c365e6 --- /dev/null +++ b/website/releases/landing_v0.0.html @@ -0,0 +1 @@ +landing_v0.0.2.html \ No newline at end of file diff --git a/website/releases/landing_v0.html b/website/releases/landing_v0.html new file mode 120000 index 0000000..6c365e6 --- /dev/null +++ b/website/releases/landing_v0.html @@ -0,0 +1 @@ +landing_v0.0.2.html \ No newline at end of file diff --git a/website/releases/manifest.json b/website/releases/manifest.json deleted file mode 100644 index d6c4b06..0000000 --- a/website/releases/manifest.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "archive-stable": "archive-v0.0.2", - "transmittal-stable": "transmittal-v0.0.2", - "classifier-stable": "classifier-v0.0.2", - "mdedit-stable": "mdedit-v0.0.2", - "landing-stable": "landing-v0.0.2", - "zddc-server-alpha": "zddc-server-v0.0.8-alpha.2" -} diff --git a/website/releases/mdedit_alpha.html b/website/releases/mdedit_alpha.html new file mode 120000 index 0000000..639e6e8 --- /dev/null +++ b/website/releases/mdedit_alpha.html @@ -0,0 +1 @@ +mdedit_v0.0.2.html \ No newline at end of file diff --git a/website/releases/mdedit_beta.html b/website/releases/mdedit_beta.html new file mode 120000 index 0000000..639e6e8 --- /dev/null +++ b/website/releases/mdedit_beta.html @@ -0,0 +1 @@ +mdedit_v0.0.2.html \ No newline at end of file diff --git a/website/releases/mdedit_stable.html b/website/releases/mdedit_stable.html new file mode 120000 index 0000000..639e6e8 --- /dev/null +++ b/website/releases/mdedit_stable.html @@ -0,0 +1 @@ +mdedit_v0.0.2.html \ No newline at end of file diff --git a/website/releases/mdedit_v0.0.1.html b/website/releases/mdedit_v0.0.1.html new file mode 100644 index 0000000..274ae67 --- /dev/null +++ b/website/releases/mdedit_v0.0.1.html @@ -0,0 +1,5064 @@ + + + + + + ZDDC Markdown + + + + + + +
+
+
+
+ ZDDC Markdown + v0.0.1 +
+ +
+
+ + +
+
+ +
+
+ + +
+ +
+
+

Welcome to ZDDC Markdown

+

All files are edited on your local computer.

+

Click Scratchpad to start editing,
or Select Directory to work with files.

+ +
+ + +
+
+
+ +
+
+ + 0 folders + 0 files + 0 unsaved +
+ +
+ + + + + + +
+ + + + diff --git a/website/releases/mdedit_v0.0.2.html b/website/releases/mdedit_v0.0.2.html new file mode 100644 index 0000000..ca8e264 --- /dev/null +++ b/website/releases/mdedit_v0.0.2.html @@ -0,0 +1,5416 @@ + + + + + + ZDDC Markdown + + + + + + + +
+
+
+
+ ZDDC Markdown + v0.0.2 +
+ +
+
+ + +
+
+ +
+
+ + +
+ +
+ + + +
+
+
+ +
+
+ + 0 folders + 0 files + 0 unsaved +
+ +
+ + + + + + +
+ + + + diff --git a/website/releases/mdedit_v0.0.html b/website/releases/mdedit_v0.0.html new file mode 120000 index 0000000..639e6e8 --- /dev/null +++ b/website/releases/mdedit_v0.0.html @@ -0,0 +1 @@ +mdedit_v0.0.2.html \ No newline at end of file diff --git a/website/releases/mdedit_v0.html b/website/releases/mdedit_v0.html new file mode 120000 index 0000000..639e6e8 --- /dev/null +++ b/website/releases/mdedit_v0.html @@ -0,0 +1 @@ +mdedit_v0.0.2.html \ No newline at end of file diff --git a/website/releases/transmittal_alpha.html b/website/releases/transmittal_alpha.html new file mode 120000 index 0000000..eda1ce8 --- /dev/null +++ b/website/releases/transmittal_alpha.html @@ -0,0 +1 @@ +transmittal_v0.0.2.html \ No newline at end of file diff --git a/website/releases/transmittal_beta.html b/website/releases/transmittal_beta.html new file mode 120000 index 0000000..eda1ce8 --- /dev/null +++ b/website/releases/transmittal_beta.html @@ -0,0 +1 @@ +transmittal_v0.0.2.html \ No newline at end of file diff --git a/website/releases/transmittal_stable.html b/website/releases/transmittal_stable.html new file mode 120000 index 0000000..eda1ce8 --- /dev/null +++ b/website/releases/transmittal_stable.html @@ -0,0 +1 @@ +transmittal_v0.0.2.html \ No newline at end of file diff --git a/website/releases/transmittal_v0.0.1.html b/website/releases/transmittal_v0.0.1.html new file mode 100644 index 0000000..93f91a6 --- /dev/null +++ b/website/releases/transmittal_v0.0.1.html @@ -0,0 +1,10998 @@ + + + + + + + + + ZDDC Transmittal + + + +
+ + JavaScript not available +
+ ZDDC Transmittal + v0.0.1 +
+
+
+ + +
+
+
+
+ + + + +
+ + +
+

+ Integrity + Not Validated (requires JavaScript) +

+
+
+
+ +
+
+ + +
+
Drop folder to scan / verify Drop HTML or JSON to import
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
# + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/releases/transmittal_v0.0.2.html b/website/releases/transmittal_v0.0.2.html new file mode 100644 index 0000000..c52de1d --- /dev/null +++ b/website/releases/transmittal_v0.0.2.html @@ -0,0 +1,10999 @@ + + + + + + + + + ZDDC Transmittal + + + + +
+ + JavaScript not available +
+ ZDDC Transmittal + v0.0.2 +
+
+
+ + +
+
+
+
+ + + + +
+ + +
+

+ Integrity + Not Validated (requires JavaScript) +

+
+
+
+ +
+
+ + +
+
Drop folder to scan / verify Drop HTML or JSON to import
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
# + + + + + + + + + + + + + +
+
+
+ +
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/website/releases/transmittal_v0.0.html b/website/releases/transmittal_v0.0.html new file mode 120000 index 0000000..eda1ce8 --- /dev/null +++ b/website/releases/transmittal_v0.0.html @@ -0,0 +1 @@ +transmittal_v0.0.2.html \ No newline at end of file diff --git a/website/releases/transmittal_v0.html b/website/releases/transmittal_v0.html new file mode 120000 index 0000000..eda1ce8 --- /dev/null +++ b/website/releases/transmittal_v0.html @@ -0,0 +1 @@ +transmittal_v0.0.2.html \ No newline at end of file diff --git a/zddc/release.sh b/zddc/release.sh index 7725675..c6491fe 100755 --- a/zddc/release.sh +++ b/zddc/release.sh @@ -1,19 +1,17 @@ #!/bin/sh -# release.sh — cut a zddc-server release: tag, compile binaries, -# publish them as assets to a Codeberg release. +# release.sh — cut a zddc-server stable release: tag, cross-compile +# binaries, publish them as assets to a Codeberg release. # # Usage: -# sh zddc/release.sh # alpha cut (default), version auto-derived -# sh zddc/release.sh alpha # same -# sh zddc/release.sh beta # beta cut, version auto-derived -# sh zddc/release.sh stable # stable cut, patch++ from latest stable -# sh zddc/release.sh stable 0.1.0 # stable cut, explicit version +# sh zddc/release.sh # patch++ from latest stable tag +# sh zddc/release.sh 0.1.0 # explicit version (X.Y.Z) # -# What this is NOT: there's no container image build, no registry push. -# Those went away when the upstream codeberg.org/varasys/zddc-server -# image lost its only consumers (tnd-zddc-chart's two Dockerfiles now -# compile from source directly, fetching this Codeberg release tarball -# / binary). See AGENTS.md "Releasing" for the full flow. +# Why stable-only: zddc-server publishes binaries only on stable cuts. +# Beta/alpha channels of zddc-server have no binary distribution — the +# helm/zddc-server-{prod,dev} charts in this repo build from source at +# deploy time, so any commit on main is buildable. There's no +# cascade/symlink layer for binaries; if you need a specific build, +# pin the chart's commit ref. # # Prerequisites: # - Go 1.24+ on PATH. @@ -21,13 +19,12 @@ # - curl, jq, git. # # What it does: -# 1. Determine version per the pre-release semver scheme: -# alpha/beta → next_prerelease (vX.Y.Z-CHANNEL.N from latest stable) -# stable → operator-supplied or patch-bumped from latest stable +# 1. Derive version: explicit arg, or patch-bumped from latest clean +# zddc-server-vX.Y.Z tag. # 2. Tag the current commit zddc-server-v. -# 3. Cross-compile binaries (linux/darwin/windows × amd64/arm64) -# into zddc/dist/zddc-server--[.exe]. Native Go preferred. -# 4. Upload each binary as an asset to the new Codeberg release. +# 3. Cross-compile binaries (linux/darwin/windows × amd64/arm64) into +# zddc/dist/zddc-server--[.exe]. Native Go. +# 4. Upload each binary as a release asset on Codeberg. # 5. Print the operator's next steps (push the tag). # # The script does NOT push the tag itself — that's a deliberate `git push` @@ -37,31 +34,19 @@ set -eu usage() { cat >&2 <<'EOF' -usage: release.sh [alpha|beta|stable] [] +usage: release.sh [] - alpha (default) cut alpha. Auto-derive version from the latest clean - zddc-server-vX.Y.Z tag plus next-patch + -alpha.N. - beta cut beta. Auto-derive version (vX.Y.Z + -beta.N). - stable cut stable. Without , patch-bump from the - latest clean stable tag. With , use it - verbatim (must be a clean X.Y.Z). + No args patch-bump from the latest clean zddc-server-vX.Y.Z tag. + explicit X.Y.Z (e.g. 0.1.0). EOF exit 1 } -CHANNEL="${1:-alpha}" -case "$CHANNEL" in - alpha | beta | stable) ;; +case "${1:-}" in -h | --help) usage ;; - *) echo "error: unknown channel '$CHANNEL'" >&2; usage ;; esac -EXPLICIT_VERSION="${2:-}" -if [ -n "$EXPLICIT_VERSION" ] && [ "$CHANNEL" != "stable" ]; then - echo "error: an explicit is only valid with the 'stable' channel" >&2 - echo " alpha and beta versions are auto-derived." >&2 - exit 1 -fi +EXPLICIT_VERSION="${1:-}" if [ -z "${CODEBERG_TOKEN:-}" ]; then echo "error: CODEBERG_TOKEN must be exported in the environment" >&2 @@ -74,41 +59,33 @@ SCRIPT_DIR=$(cd "$(dirname "$0")/.." && pwd) TAG_PREFIX="zddc-server-v" REPO="VARASYS/ZDDC" -# Source build-lib.sh for next_prerelease + _validate_semver. It -# requires root_dir set; pointing at the repo root works. +# Source build-lib.sh for _validate_semver. It requires root_dir set; +# pointing at the repo root works. root_dir="$SCRIPT_DIR" . "$SCRIPT_DIR/shared/build-lib.sh" . "$SCRIPT_DIR/shared/publish-codeberg-release.sh" # --- Determine version ----------------------------------------------------- -case "$CHANNEL" in - alpha | beta) - VERSION=$(next_prerelease "$CHANNEL" "$TAG_PREFIX") - ;; - stable) - if [ -n "$EXPLICIT_VERSION" ]; then - _validate_semver "$EXPLICIT_VERSION" - VERSION="$EXPLICIT_VERSION" - else - _latest=$(git -C "$SCRIPT_DIR" tag --list "${TAG_PREFIX}*" 2>/dev/null \ - | grep -E "^${TAG_PREFIX}[0-9]+\.[0-9]+\.[0-9]+\$" \ - | sed "s|^${TAG_PREFIX}||" \ - | sort -V \ - | tail -1) - [ -n "$_latest" ] || _latest="0.0.0" - _major="${_latest%%.*}" - _rest="${_latest#*.}" - _minor="${_rest%%.*}" - _patch="${_rest#*.}" - VERSION="${_major}.${_minor}.$((_patch + 1))" - fi - ;; -esac +if [ -n "$EXPLICIT_VERSION" ]; then + _validate_semver "$EXPLICIT_VERSION" + VERSION="$EXPLICIT_VERSION" +else + _latest=$(git -C "$SCRIPT_DIR" tag --list "${TAG_PREFIX}*" 2>/dev/null \ + | grep -E "^${TAG_PREFIX}[0-9]+\.[0-9]+\.[0-9]+\$" \ + | sed "s|^${TAG_PREFIX}||" \ + | sort -V \ + | tail -1) + [ -n "$_latest" ] || _latest="0.0.0" + _major="${_latest%%.*}" + _rest="${_latest#*.}" + _minor="${_rest%%.*}" + _patch="${_rest#*.}" + VERSION="${_major}.${_minor}.$((_patch + 1))" +fi GIT_TAG="${TAG_PREFIX}${VERSION}" -echo "=== zddc-server release ===" -echo "Channel: $CHANNEL" +echo "=== zddc-server stable release ===" echo "Version: $VERSION" echo "Git tag: $GIT_TAG" echo @@ -167,20 +144,3 @@ echo echo "=== Done ===" echo "Release: https://codeberg.org/$REPO/releases/tag/$GIT_TAG" echo "Git tag: $GIT_TAG (publish with: git push origin $GIT_TAG)" -echo -case "$CHANNEL" in - stable) - echo "Reminder (channel discipline rule 4): freshen alpha + beta now" - echo "so the floating channels resolve to at-least-current code:" - echo " ./freshen-channel zddc-server alpha" - echo " ./freshen-channel zddc-server beta" - ;; - beta) - echo "Beta cut. Soak before promoting to stable." - ;; -esac -echo -echo "Don't forget to also regenerate the website releases page:" -echo " sh build.sh" -echo " git add website/releases/index.html website/releases/manifest.json" -echo " git commit && git push"