AtlatestRepositorysigil-site

sigil-site / treepublish.sh

1#!/usr/bin/env bash
2set -euo pipefail
3
4# Publish the Sigil website to Codeberg Pages
5#
6# Usage: ./publish.sh [OPTIONS]
7#
8# Options:
9# --local Build only, don't commit/push
10# --serve After building, serve locally (implies --local)
11# --port PORT Port for local server (default: 8000)
12# --skip-build Skip building libraries (use existing build artifacts)
13# --with-repl Force-build the WASM web REPL (on by default for a production
14# publish; use this to also build it under --local)
15# --skip-repl Skip the WASM web REPL build (explicit opt-out; NOT recommended
16# for a production publish — it ships a possibly-stale REPL)
18# The REPL build needs zig (auto-detected from ~/.sigil/toolchain/zig) and
19# wasm-opt/Binaryen (on Guix: run under `guix shell binaryen`). A production
20# publish builds it by default so the live REPL never silently goes stale.
22# Environment:
23# SIGIL Path to sigil binary (default: ~/.sigil/bin/sigil)
24# PARENT_DIR Parent directory where sibling repos live (default: ..)
25# CODEBERG_USER Codeberg username for HTTPS push auth (default: daviwil)
26# CODEBERG_TOKEN When set, uses HTTPS for git operations instead of SSH
28# This script:
29# 1. Ensures the sigil monorepo is present and built
30# 2. Clones/fetches all extracted core library repos
31# 3. Builds each library so API doc JSON is generated
32# 4. Builds the WASM web REPL (default for a production publish; --skip-repl to opt out)
33# 5. Assembles a combined lib directory for with-api-docs
34# 6. Builds the site
35# 7. Optionally deploys to Codeberg Pages
37LOCAL_ONLY=false
38SERVE=false
39PORT=8000
40SKIP_BUILD=false
41WITH_REPL="" # empty = decide after parsing: a production publish builds the REPL, --local skips it
43while [[ $# -gt 0 ]]; do
44 case $1 in
45 --local)
46 LOCAL_ONLY=true
47 shift
48 ;;
49 --serve)
50 LOCAL_ONLY=true
51 SERVE=true
52 shift
53 ;;
54 --port)
55 PORT="$2"
56 shift 2
57 ;;
58 --skip-build)
59 SKIP_BUILD=true
60 shift
61 ;;
62 --with-repl)
63 WITH_REPL=true
64 shift
65 ;;
66 --skip-repl)
67 WITH_REPL=false
68 shift
69 ;;
70 *)
71 echo "Unknown option: $1"
72 echo "Usage: $0 [--local] [--serve] [--port PORT] [--skip-build] [--with-repl] [--skip-repl]"
73 exit 1
74 ;;
75 esac
76done
78# The web REPL is part of a PRODUCTION publish by default, so a real deploy can
79# never silently ship a stale REPL wasm. (It did: usesigil.org sat at 0.17.3
80# while the rest of the site read 0.17.6, because --with-repl was an easy-to-
81# forget opt-in.) A production publish now BUILDS the REPL unless --skip-repl is
82# passed explicitly; local dev previews (--local) skip it by default for fast
83# iteration (opt in with --with-repl). Either way the choice is explicit.
84if [[ -z "$WITH_REPL" ]]; then
85 if [[ "$LOCAL_ONLY" == "true" ]]; then WITH_REPL=false; else WITH_REPL=true; fi
86fi
88SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
89cd "$SCRIPT_DIR"
91SIGIL="${SIGIL:-$HOME/.sigil/bin/sigil}"
92PARENT_DIR="${PARENT_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
93PUBLIC_DIR="$SCRIPT_DIR/public"
94COMBINED_LIB="$SCRIPT_DIR/build/combined-lib"
96# Pages deployment target (usesigil.org is hosted from sigil monorepo pages branch)
97# Use HTTPS with token auth when CODEBERG_TOKEN is set (e.g. in CI),
98# otherwise use SSH (local development)
99if [[ -n "${CODEBERG_TOKEN:-}" ]]; then
100 CODEBERG_USER="${CODEBERG_USER:-daviwil}"
101 PAGES_REPO_URL="https://${CODEBERG_USER}:${CODEBERG_TOKEN}@codeberg.org/sigil/sigil.git"
102else
103 PAGES_REPO_URL="[email protected]:sigil/sigil.git"
104fi
105PAGES_BRANCH="pages"
106DOMAIN="usesigil.org"
108# ---------------------------------------------------------------------------
109# Core libraries whose API docs appear on usesigil.org
110# ---------------------------------------------------------------------------
112# Monorepo packages (built from ../sigil) that need a _pkg manifest
113# generated when their custom tasks: skip the default copy-package-docs
114# step. The browser/WASM bridge packages all stage JS assets through
115# custom tasks, so without this list their package pages never render
116# on the site even though their module .json docs generate fine.
117MONOREPO_PACKAGES=(
118 # P2-reabsorbed packages. Keep these explicit so their package manifests
119 # and any package-local docs/ trees come from the monorepo build rather
120 # than a retired standalone checkout.
121 sigil-args
122 sigil-format
123 sigil-git
124 sigil-help
125 sigil-repl
126 sigil-stdlib
127 sigil-cli
128 sigil-run
129 sigil-browser
130 sigil-wasm-runtime
131 sigil-wasm-dom
132 sigil-wasm-net
133 sigil-wasm-canvas2d
134 sigil-wasm-gl
137# Extracted repos (cloned as peer directories and built individually).
138# Multi-package repos: sigil-lang (sigil-lib + sigil-stdlib),
139# sigil-build (sigil-package + sigil-deps + sigil-build),
140# sigil-test (sigil-test + sigil-test-runner).
141EXTRACTED_REPOS=(
142 # sigil-lang, sigil-build, sigil-store and sigil-test were re-integrated into the
143 # monorepo (packages/); their standalone repos are archived. Building the stale
144 # clones let their modules override the monorepo's (2026-09-18: unbound
145 # reset-compiler-input-proofs! from a May sigil-build). Keep them out.
147 sigil-log sigil-json sigil-http sigil-crypto sigil-tls sigil-sqlite
148 sigil-lsp sigil-mcp sigil-nrepl sigil-ffi
149 sigil-peg sigil-sxml sigil-markdown sigil-css
150 sigil-r7rs sigil-transducers sigil-web sigil-web-client sigil-yaml sigil-later
151 # Core, general-purpose libraries added by the 2026-07 completeness audit.
152 # These are published sigil/* library packages that were missing from the
153 # docs site. (SaaS/API-client packages: forgejo, caldav, jmap, discourse,
154 # postmark, ses, lemonsqueezy, telegram, twitch, youtube, wise, plus the
155 # graphics/audio/game stack, are intentionally excluded; see the audit note.)
156 # sigil-rss was also identified but is NOT release-ready (no tags, its
157 # package.sgl lacks the required `sigil:` field and fails to build), so it
158 # is held back until it is fixed and released. sigil-ledger was evaluated
159 # and intentionally left out as too specialized.
160 sigil-websocket sigil-oauth sigil-jwt sigil-irc sigil-xmpp
161 sigil-org sigil-tui
164# ---------------------------------------------------------------------------
165# Helper functions
166# ---------------------------------------------------------------------------
168info() { echo "=== $* ==="; }
169warn() { echo "WARNING: $*"; }
170die() { echo "ERROR: $*" >&2; exit 1; }
172repo_url() {
173 local name="$1"
174 if [[ -n "${CODEBERG_TOKEN:-}" ]]; then
175 echo "https://codeberg.org/sigil/${name}.git"
176 else
177 echo "[email protected]:sigil/${name}.git"
178 fi
181ensure_repo() {
182 local name="$1"
183 local dir="$PARENT_DIR/$name"
185 if [[ -d "$dir" ]]; then
186 echo " Fetching $name..."
187 git -C "$dir" fetch --quiet --tags 2>/dev/null || true
188 else
189 echo " Cloning $name..."
190 git clone --quiet "$(repo_url "$name")" "$dir"
191 fi
194build_extracted_repo() {
195 local name="$1"
196 local dir="$PARENT_DIR/$name"
198 if [[ ! -d "$dir" ]]; then
199 warn "$name directory not found, skipping"
200 return
201 fi
203 echo " Building $name..."
204 cd "$dir"
206 # Ensure deps are installed
207 if [[ ! -d ".sigil/deps" ]]; then
208 $SIGIL deps install > /dev/null 2>&1 || true
209 fi
211 # Build with --force to ensure JSON docs are generated.
212 # The build may error after compilation due to sigil-lib resolution;
213 # that's OK since compilation (and JSON generation) still succeeds.
214 $SIGIL build --force > /dev/null 2>&1 || true
216 cd "$SCRIPT_DIR"
219# Merge a lib directory into the combined lib.
220# Copies .sgb, .json, and _pkg files. First source wins on conflicts.
221merge_lib() {
222 local src="$1"
223 local label="$2"
225 if [[ ! -d "$src" ]]; then
226 warn "$label lib dir not found: $src"
227 return
228 fi
230 # Copy .sgb and .json files, preserving directory structure
231 find "$src" -type f \( -name "*.sgb" -o -name "*.json" \) | while read -r file; do
232 local rel="${file#$src/}"
233 local dest="$COMBINED_LIB/$rel"
234 if [[ ! -f "$dest" ]]; then
235 mkdir -p "$(dirname "$dest")"
236 cp "$file" "$dest"
237 fi
238 done
240 # Copy _pkg directories (package metadata + docs)
241 if [[ -d "$src/_pkg" ]]; then
242 find "$src/_pkg" -type f | while read -r file; do
243 local rel="${file#$src/}"
244 local dest="$COMBINED_LIB/$rel"
245 if [[ ! -f "$dest" ]]; then
246 mkdir -p "$(dirname "$dest")"
247 cp "$file" "$dest"
248 fi
249 done
250 fi
253# Fix package attribution for extracted repos.
254# When a module exists in both the monorepo (as part of sigil-stdlib) and an
255# extracted repo (as its own package), the monorepo .json says package: "sigil-stdlib"
256# but the extracted repo .json says package: "<repo-name>". We want the extracted
257# repo's attribution so the module appears under the correct package on the site.
258fix_extracted_json() {
259 local name="$1"
260 local src="$PARENT_DIR/$name/build/dev/lib"
262 if [[ ! -d "$src" ]]; then
263 return
264 fi
266 # Overwrite .json files in combined-lib where the extracted repo's version
267 # has the correct package attribution (package matches the repo name)
268 find "$src" -name "*.json" ! -path "*/_pkg/*" | while read -r file; do
269 if grep -q "\"package\": \"$name\"" "$file"; then
270 local rel="${file#$src/}"
271 local dest="$COMBINED_LIB/$rel"
272 mkdir -p "$(dirname "$dest")"
273 cp "$file" "$dest"
274 fi
275 done
278# Ensure a _pkg manifest exists for a monorepo package.
279# Some packages have custom tasks: that skip the default copy-package-docs step,
280# so their _pkg manifest is never created. We generate one from package.sgl.
281ensure_pkg_manifest() {
282 local name="$1"
283 local pkg_dir="$PARENT_DIR/sigil/packages/$name"
284 local manifest_dir="$COMBINED_LIB/_pkg/$name"
285 local manifest_path="$manifest_dir/manifest.json"
287 # Skip if manifest already exists
288 if [[ -f "$manifest_path" ]]; then
289 return
290 fi
292 if [[ ! -f "$pkg_dir/package.sgl" ]]; then
293 warn "No package.sgl for $name, cannot generate manifest"
294 return
295 fi
297 # Extract version and description from package.sgl
298 # Packages may omit version: (inherited from workspace), fall back to workspace version
299 local version description
300 version=$(grep 'version:' "$pkg_dir/package.sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)
301 if [[ -z "$version" ]]; then
302 version=$(grep 'version:' "$PARENT_DIR/sigil/package.sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)
303 fi
304 description=$(grep 'description:' "$pkg_dir/package.sgl" | head -1 | sed 's/.*description: *"\(.*\)".*/\1/' || true)
306 mkdir -p "$manifest_dir"
307 cat > "$manifest_path" <<MANIFEST
309 "name": "$name",
310 "version": "$version",
311 "description": "$description"
313MANIFEST
314 echo " Generated manifest for $name"
317# Ensure a _pkg manifest exists for an EXTRACTED repo package.
318# Extracted repos whose package.sgl defines a custom tasks: build task override
319# the default build (which runs copy-package-docs), and if they also ship no
320# docs/ dir they never emit their own _pkg/<name>/manifest.json. Without that
321# manifest, Press's scan-library-docs skips the package entirely: no Libraries
322# sidebar entry and the /docs/lib/<name>/ page 404s (as happened to
323# sigil-crypto, sigil-tls, and sigil-nrepl). This is the same failure mode
324# ensure_pkg_manifest handles for MONOREPO_PACKAGES; generate the manifest from
325# the repo's own package.sgl. The package name is the repo name (matches the
326# convention fix_extracted_json relies on for single-package repos).
327ensure_extracted_pkg_manifest() {
328 local name="$1"
329 local repo_dir="$PARENT_DIR/$name"
330 local pkg_sgl="$repo_dir/package.sgl"
331 local build_lib="$repo_dir/build/dev/lib"
333 if [[ ! -f "$pkg_sgl" ]]; then
334 return
335 fi
337 local manifest_dir="$COMBINED_LIB/_pkg/$name"
338 local manifest_path="$manifest_dir/manifest.json"
340 # Skip if a manifest was already merged from the repo's own build output
341 if [[ -f "$manifest_path" ]]; then
342 return
343 fi
345 # Only synthesize a manifest when the repo actually built modules attributed
346 # to this package. This guards against workspace/multi-package repos (e.g.
347 # sigil-lang, whose package.sgl name is the workspace name "sigil-lang" but
348 # which ships sigil-stdlib/sigil-lib) and against unbuilt/empty repos --
349 # either would otherwise produce a bogus empty package in the sidebar.
350 if [[ ! -d "$build_lib" ]]; then
351 return
352 fi
353 if ! grep -rls "\"package\": \"$name\"" "$build_lib" --include='*.json' >/dev/null 2>&1; then
354 return
355 fi
357 local version description
358 version=$(grep 'version:' "$pkg_sgl" | head -1 | sed 's/.*version: *"\(.*\)".*/\1/' || true)
359 description=$(grep 'description:' "$pkg_sgl" | head -1 | sed 's/.*description: *"\(.*\)".*/\1/' || true)
361 mkdir -p "$manifest_dir"
362 cat > "$manifest_path" <<MANIFEST
364 "name": "$name",
365 "version": "$version",
366 "description": "$description"
368MANIFEST
369 echo " Generated manifest for extracted package $name"
372# ---------------------------------------------------------------------------
373# Step 1: Ensure sigil monorepo is present and built
374# ---------------------------------------------------------------------------
376info "Checking sigil monorepo"
378if [[ ! -d "$PARENT_DIR/sigil" ]]; then
379 die "../sigil not found. Clone the sigil monorepo as a peer directory."
380fi
382if [[ "$SKIP_BUILD" != "true" ]]; then
383 if [[ ! -d "$PARENT_DIR/sigil/build/dev/lib" ]]; then
384 echo " Building monorepo..."
385 cd "$PARENT_DIR/sigil"
386 $SIGIL build
387 cd "$SCRIPT_DIR"
388 else
389 echo " Monorepo build found."
390 fi
391fi
393# ---------------------------------------------------------------------------
394# Step 2: Clone/fetch extracted library repos
395# ---------------------------------------------------------------------------
397info "Ensuring extracted library repos"
399for repo in "${EXTRACTED_REPOS[@]}"; do
400 ensure_repo "$repo"
401done
403# ---------------------------------------------------------------------------
404# Step 3: Build extracted libraries
405# ---------------------------------------------------------------------------
407if [[ "$SKIP_BUILD" != "true" ]]; then
408 info "Building extracted libraries"
410 for repo in "${EXTRACTED_REPOS[@]}"; do
411 build_extracted_repo "$repo"
412 done
413fi
415# ---------------------------------------------------------------------------
416# Step 3.5: Build web REPL WASM (default for production publishes; --skip-repl to opt out)
417# ---------------------------------------------------------------------------
419if [[ "$WITH_REPL" == "true" ]]; then
420 # Auto-detect the sigil-bundled zig so the REPL build works without a manual
421 # PATH setup. sigil's pinned zig is cached under the monorepo's tools/zig
422 # (populated by scripts/with-zig) and symlinked at ~/.sigil/toolchain/zig —
423 # the same toolchain the release build uses. Only look if zig isn't already
424 # on PATH.
425 if ! command -v zig >/dev/null 2>&1; then
426 for zdir in "$HOME/.sigil/toolchain/zig" "${PARENT_DIR:-}/sigil/tools/zig"; do
427 if [[ -n "$zdir" && -x "$zdir/zig" ]]; then
428 info "Using bundled zig at $zdir"
429 export PATH="$zdir:$PATH"
430 break
431 fi
432 done
433 fi
434 if ! command -v zig >/dev/null 2>&1; then
435 die "REPL build requires zig: not on PATH and no bundled zig found at ~/.sigil/toolchain/zig or \$PARENT_DIR/sigil/tools/zig. Install zig, or run the monorepo's scripts/with-zig once to populate the bundled toolchain."
436 fi
438 # wasm-opt (Binaryen) is required for the --asyncify post-link pass that the
439 # monorepo's --config web build runs. Without it that pass is silently
440 # skipped and the REPL wasm ships unresolved asyncify.* imports, so it fails
441 # to instantiate in the browser ("Import asyncify: module is not an object
442 # or function") and the REPL hangs. Fail loudly instead of shipping a broken
443 # REPL. On Guix, wasm-opt is not on PATH by default: re-run inside a guix
444 # shell (zig is auto-detected, so binaryen is the only thing to add):
445 # guix shell binaryen -- ./publish.sh
446 if ! command -v wasm-opt >/dev/null 2>&1; then
447 die "REPL build requires wasm-opt (Binaryen) for the --asyncify pass, not on PATH. On Guix: guix shell binaryen -- ./publish.sh (zig is auto-detected). To publish WITHOUT the REPL, pass --skip-repl explicitly — but that ships whatever REPL wasm is currently staged, which may be stale."
448 fi
450 info "Building web REPL (WASM)"
452 ensure_repo "sigil-web-repl"
453 REPL_SRC="$PARENT_DIR/sigil-web-repl"
454 cd "$REPL_SRC"
456 # Clean build: the bundle step globs everything under build/web/lib,
457 # so orphaned modules from older builds survive incremental rebuilds
458 # and ship stale bytecode (March-era v7 match/sxml modules rode along
459 # this way and broke those REPL examples on the live site).
460 rm -rf build/web
462 # Install deps or use redirects to local monorepo
463 if [[ -d "$PARENT_DIR/sigil" ]]; then
464 REDIR_FILE=$(mktemp)
465 cat > "$REDIR_FILE" << 'REDIR_EOF'
466(redirects
467 repos: (list
468 (for-repo
469 url: "codeberg:sigil/sigil"
470 use: (from-path dir: "../sigil"))))
471REDIR_EOF
472 $SIGIL build --redirects "$REDIR_FILE" --config web
473 rm -f "$REDIR_FILE"
474 else
475 $SIGIL deps install
476 $SIGIL build --config web
477 fi
478 cd "$SCRIPT_DIR"
480 # Copy WASM artifacts into site assets
481 REPL_BUILD="$REPL_SRC/build/web"
482 if [[ -f "$REPL_BUILD/sigil-web-repl.wasm" ]]; then
483 echo " Copying WASM artifacts..."
484 cp "$REPL_BUILD/sigil-web-repl.wasm" "$SCRIPT_DIR/assets/repl/"
485 # The page JS and the wasm are a matched pair: a stale page driving
486 # a fresh wasm hung evaluation on the live site (the eval/input ABI
487 # plumbing had moved on). Always ship the page from the same build.
488 cp "$REPL_BUILD/index.html" "$SCRIPT_DIR/assets/repl/index.html"
490 # Generate merged lib.bundle (web-repl modules + extras for REPL examples).
491 # generate-web-bundle lets LATER dirs override earlier ones, so the
492 # REPL's own lib goes last: it is the coherent, freshly built set,
493 # and a stale peer build must never override its core/stdlib
494 # bytecode (a v7 sigil/core.sgb from an old sigil-sxml build once
495 # shipped over the fresh v9 one and broke the live REPL).
496 BUNDLE_DIRS=""
497 for peer in sigil-sxml sigil-match; do
498 if [[ -d "$PARENT_DIR/$peer/build/dev/lib" ]]; then
499 echo " Adding modules from $peer..."
500 BUNDLE_DIRS="$BUNDLE_DIRS \"$PARENT_DIR/$peer/build/dev/lib\""
501 fi
502 done
503 BUNDLE_DIRS="$BUNDLE_DIRS \"$REPL_BUILD/lib\""
505 echo " Generating lib.bundle..."
506 $SIGIL eval "(import (sigil build))
507 (let ((n (generate-web-bundle
508 output: \"assets/repl/lib.bundle\"
509 dirs: (list $BUNDLE_DIRS))))
510 (display n)
511 (display \" files bundled\n\"))"
512 else
513 warn "WASM build did not produce sigil-web-repl.wasm"
514 fi
515fi
517# ---------------------------------------------------------------------------
518# Step 4: Assemble combined lib directory
519# ---------------------------------------------------------------------------
521info "Assembling combined API docs"
523rm -rf "$COMBINED_LIB"
524mkdir -p "$COMBINED_LIB"
526# Monorepo libs first (primary source)
527merge_lib "$PARENT_DIR/sigil/build/dev/lib" "monorepo"
529# Then extracted repos (only adds modules not already present)
530for repo in "${EXTRACTED_REPOS[@]}"; do
531 merge_lib "$PARENT_DIR/$repo/build/dev/lib" "$repo"
532done
534# Fix package attribution for extracted repos whose modules overlap with monorepo
535for repo in "${EXTRACTED_REPOS[@]}"; do
536 fix_extracted_json "$repo"
537done
539# Generate _pkg manifests for monorepo packages that lack them
540for pkg in "${MONOREPO_PACKAGES[@]}"; do
541 ensure_pkg_manifest "$pkg"
542done
544# Generate _pkg manifests for extracted repos whose custom build tasks skip
545# copy-package-docs (e.g. sigil-crypto, sigil-tls, sigil-nrepl). Without this
546# they never appear in the Libraries sidebar and their pages 404.
547for repo in "${EXTRACTED_REPOS[@]}"; do
548 ensure_extracted_pkg_manifest "$repo"
549done
551echo " Combined lib ready."
553# ---------------------------------------------------------------------------
554# Step 5: Build the site
555# ---------------------------------------------------------------------------
557info "Building site"
559# Ensure press and other deps are installed
560if [[ ! -d ".sigil/deps" ]]; then
561 echo " Installing site dependencies..."
562 $SIGIL deps install
563fi
565# Compile the site explicitly before run. `sigil run`'s auto-compile-hook
566# can produce sub-threshold .sgb stubs in some cases (see sigil-papercut t-2fa9);
567# an explicit `sigil build` produces real bytecode and avoids the failure mode
568# where `(import (sigil-site main))` finds the module but its exports are empty.
569echo " Compiling site sources..."
570$SIGIL build
572# Clear stale output before regenerating. The site build writes pages into
573# public/ but never removes ones that no longer exist, so pages for packages
574# dropped from the arrays (or any renamed/removed content) linger as stale
575# files. Because the deploy step copies public/ verbatim into the fresh pages
576# branch, those stale pages would ship to production on every republish, not
577# just locally. Starting from an empty output tree guarantees public/ reflects
578# exactly the current build.
579rm -rf "$PUBLIC_DIR"
581# Build and run the site
582# -L adds combined-lib to module search paths so Press's load-module-details
583# can find .json doc files for packages not in the site's dependency tree
584$SIGIL -L "$COMBINED_LIB" run -- build
586# Verify
587if [[ ! -d "$PUBLIC_DIR" ]] || [[ ! -f "$PUBLIC_DIR/index.html" ]]; then
588 die "Site build failed - public directory missing or incomplete"
589fi
591# ---------------------------------------------------------------------------
592# Step 6: Deploy or serve
593# ---------------------------------------------------------------------------
595if [[ "$LOCAL_ONLY" == "true" ]]; then
596 echo ""
597 echo "Local build complete! Site is in: $PUBLIC_DIR"
599 if [[ "$SERVE" == "true" ]]; then
600 echo "Starting local server at http://localhost:$PORT"
601 echo "Press Ctrl+C to stop."
602 cd "$PUBLIC_DIR"
603 python3 -m http.server "$PORT"
604 fi
605else
606 info "Publishing site to $DOMAIN"
608 TEMP_DIR=$(mktemp -d)
610 # Initialize a fresh repo with orphan branch
611 cd "$TEMP_DIR"
612 git init --quiet
613 git config user.email "[email protected]"
614 git config user.name "Sigil Pages"
615 git checkout --orphan "$PAGES_BRANCH"
617 # Copy public content
618 cp -r "$PUBLIC_DIR"/* "$TEMP_DIR/"
620 # Create .domains file for Codeberg Pages
621 echo "$DOMAIN" > "$TEMP_DIR/.domains"
623 # Commit and force push
624 git add -A
625 git commit --quiet -m "Update site"
626 git remote add origin "$PAGES_REPO_URL"
627 echo " Force pushing to $PAGES_BRANCH branch..."
628 git push --force origin "$PAGES_BRANCH"
630 echo ""
631 echo "Done! Site will be available at:"
632 echo " https://$DOMAIN/"
633 echo " https://$DOMAIN/docs/"
635 # Cleanup
636 cd "$SCRIPT_DIR"
637 rm -rf "$TEMP_DIR"
638fi