aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorshu <nvcsadjkojf@outlook.com>2026-08-19 15:56:06 +0800
committershu <nvcsadjkojf@outlook.com>2026-08-19 15:56:06 +0800
commitca1a4a31706d0c03673fe4c414c645ed826b21c6 (patch)
treec412265a19dd4694c39aac65b6e1a8903a513978 /scripts
parent490d41f154615a52734f117d7d7bda5a9331e303 (diff)
精简 Wiki 构建与运行方式
将浏览器端工具整理为 utilities 插件,移除 Docker、Org GTD 和 files API,并补充单文件构建及 Node.js 运行入口。
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/build.sh66
-rwxr-xr-xscripts/dev.sh3
-rwxr-xr-xscripts/init-docker.sh157
-rwxr-xr-xscripts/run.sh16
4 files changed, 80 insertions, 162 deletions
diff --git a/scripts/build.sh b/scripts/build.sh
new file mode 100755
index 0000000..ac7651f
--- /dev/null
+++ b/scripts/build.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+
+set -eu
+
+SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
+PROJECT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
+OUTPUT_DIR="$PROJECT_DIR/dist"
+OUTPUT_FILE="$OUTPUT_DIR/tdwiki.html"
+TIDDLYWIKI_BIN=${TIDDLYWIKI_BIN:-tiddlywiki}
+BUILD_TMP_DIR=
+BUILD_WIKI_DIR=
+
+cleanup() {
+ if [ -n "$BUILD_TMP_DIR" ] && [ -d "$BUILD_TMP_DIR" ]; then
+ rm -rf -- "$BUILD_TMP_DIR"
+ fi
+}
+
+prepare_build_wiki() {
+ BUILD_TMP_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tdwiki-build.XXXXXX")
+ BUILD_WIKI_DIR="$BUILD_TMP_DIR/wiki"
+ mkdir -p "$BUILD_WIKI_DIR"
+ cp -R "$PROJECT_DIR/tiddlers" "$BUILD_WIKI_DIR/tiddlers"
+ cp -R "$PROJECT_DIR/plugins" "$BUILD_WIKI_DIR/plugins"
+
+ node -e '
+const fs = require("fs");
+const source = process.argv[1];
+const destination = process.argv[2];
+const info = JSON.parse(fs.readFileSync(source,"utf8"));
+const serverPlugins = new Set([
+ "tiddlywiki/filesystem",
+ "tiddlywiki/tiddlyweb"
+]);
+info.plugins = (info.plugins || []).filter(name => !serverPlugins.has(name));
+fs.writeFileSync(destination,JSON.stringify(info,null,4) + "\n");
+' "$PROJECT_DIR/tiddlywiki.info" "$BUILD_WIKI_DIR/tiddlywiki.info"
+}
+
+verify_output() {
+ node -e '
+const fs = require("fs");
+const filename = process.argv[1];
+const html = fs.readFileSync(filename,"utf8");
+
+for(const title of ["$:/plugins/local/utilities"]) {
+ if(!html.includes(`"title":"${title}"`)) {
+ throw new Error(`single-file wiki is missing ${title}`);
+ }
+}
+
+' "$OUTPUT_FILE"
+}
+
+trap cleanup EXIT HUP INT TERM
+
+prepare_build_wiki
+mkdir -p "$OUTPUT_DIR"
+
+"$TIDDLYWIKI_BIN" "$BUILD_WIKI_DIR" \
+ --output "$OUTPUT_DIR" \
+ --rendertiddler '$:/core/save/all' \
+ tdwiki.html text/plain
+
+verify_output
+printf 'Built %s\n' "$OUTPUT_FILE"
diff --git a/scripts/dev.sh b/scripts/dev.sh
deleted file mode 100755
index 7d43567..0000000
--- a/scripts/dev.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#/usr/bin/bash
-
-tiddlywiki . --listen port=10000 gzip=yes use-browser-cache=yes \ No newline at end of file
diff --git a/scripts/init-docker.sh b/scripts/init-docker.sh
deleted file mode 100755
index 4bae29b..0000000
--- a/scripts/init-docker.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/bin/sh
-
-set -eu
-
-SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
-PROJECT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
-FORCE_USER=no
-
-if [ "${1:-}" = "--force-user" ]; then
- FORCE_USER=yes
-elif [ "$#" -gt 0 ]; then
- printf 'Usage: %s [--force-user]\n' "$0" >&2
- exit 1
-fi
-
-if [ ! -f "$PROJECT_DIR/.env" ]; then
- cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env"
- printf 'Created .env from .env.example\n'
-fi
-
-set -a
-. "$PROJECT_DIR/.env"
-set +a
-
-BASE_DOMAIN=${BASE_DOMAIN:-tdwiki.home.arpa}
-
-case "$BASE_DOMAIN" in
- *[!a-zA-Z0-9.-]*|.*|*.)
- printf 'Invalid BASE_DOMAIN: %s\n' "$BASE_DOMAIN" >&2
- exit 1
- ;;
-esac
-
-mkdir -p \
- "$PROJECT_DIR/data/authelia" \
- "$PROJECT_DIR/data/caddy/data" \
- "$PROJECT_DIR/data/caddy/config" \
- "$PROJECT_DIR/secrets"
-
-chmod 700 "$PROJECT_DIR/secrets"
-
-generate_secret() {
- file=$1
- bytes=$2
- if [ ! -s "$file" ]; then
- umask 077
- openssl rand -hex "$bytes" > "$file"
- printf 'Generated %s\n' "${file#"$PROJECT_DIR/"}"
- fi
-}
-
-generate_secret "$PROJECT_DIR/secrets/authelia_jwt_secret" 32
-generate_secret "$PROJECT_DIR/secrets/authelia_session_secret" 32
-generate_secret "$PROJECT_DIR/secrets/authelia_storage_encryption_key" 32
-
-sed "s/__BASE_DOMAIN__/$BASE_DOMAIN/g" \
- "$PROJECT_DIR/docker/authelia/configuration.template.yml" \
- > "$PROJECT_DIR/docker/authelia/configuration.yml"
-
-USERS_FILE="$PROJECT_DIR/docker/authelia/users_database.yml"
-
-if [ ! -f "$USERS_FILE" ] || [ "$FORCE_USER" = yes ]; then
- USERNAME=${AUTHELIA_USERNAME:-}
- DISPLAY_NAME=${AUTHELIA_DISPLAY_NAME:-}
- EMAIL=${AUTHELIA_EMAIL:-}
- PASSWORD=${AUTHELIA_PASSWORD:-}
-
- if [ -z "$USERNAME" ]; then
- printf 'Authelia username [admin]: '
- read -r USERNAME
- USERNAME=${USERNAME:-admin}
- fi
-
- case "$USERNAME" in
- *[!a-zA-Z0-9_.-]*)
- printf 'Username may only contain letters, digits, dot, underscore, and hyphen.\n' >&2
- exit 1
- ;;
- esac
-
- if [ -z "$DISPLAY_NAME" ]; then
- printf 'Display name [%s]: ' "$USERNAME"
- read -r DISPLAY_NAME
- DISPLAY_NAME=${DISPLAY_NAME:-$USERNAME}
- fi
-
- if [ -z "$EMAIL" ]; then
- printf 'Email [%s@%s]: ' "$USERNAME" "$BASE_DOMAIN"
- read -r EMAIL
- EMAIL=${EMAIL:-$USERNAME@$BASE_DOMAIN}
- fi
-
- case "$DISPLAY_NAME$EMAIL" in
- *'"'*|*'\'*)
- printf 'Display name and email cannot contain quote or backslash characters.\n' >&2
- exit 1
- ;;
- esac
-
- if [ -z "$PASSWORD" ]; then
- if [ ! -t 0 ]; then
- printf 'Set AUTHELIA_PASSWORD for non-interactive initialization.\n' >&2
- exit 1
- fi
- printf 'Password: '
- stty -echo
- read -r PASSWORD
- stty echo
- printf '\nConfirm password: '
- stty -echo
- read -r PASSWORD_CONFIRM
- stty echo
- printf '\n'
- if [ "$PASSWORD" != "$PASSWORD_CONFIRM" ]; then
- printf 'Passwords do not match.\n' >&2
- exit 1
- fi
- fi
-
- if [ "${#PASSWORD}" -lt 12 ]; then
- printf 'Password must contain at least 12 characters.\n' >&2
- exit 1
- fi
-
- HASH_OUTPUT=$(docker run --rm authelia/authelia:4.39.20 \
- authelia crypto hash generate argon2 \
- --password "$PASSWORD" \
- --no-confirm)
- PASSWORD_HASH=${HASH_OUTPUT#Digest: }
- unset PASSWORD PASSWORD_CONFIRM HASH_OUTPUT
-
- escape_sed() {
- printf '%s' "$1" | sed 's/[|&]/\\&/g'
- }
-
- USERNAME_ESCAPED=$(escape_sed "$USERNAME")
- DISPLAY_NAME_ESCAPED=$(escape_sed "$DISPLAY_NAME")
- EMAIL_ESCAPED=$(escape_sed "$EMAIL")
- PASSWORD_HASH_ESCAPED=$(escape_sed "$PASSWORD_HASH")
-
- sed \
- -e "s|__USERNAME__|$USERNAME_ESCAPED|g" \
- -e "s|__DISPLAY_NAME__|$DISPLAY_NAME_ESCAPED|g" \
- -e "s|__EMAIL__|$EMAIL_ESCAPED|g" \
- -e "s|__PASSWORD_HASH__|$PASSWORD_HASH_ESCAPED|g" \
- "$PROJECT_DIR/docker/authelia/users_database.template.yml" \
- > "$USERS_FILE"
- chmod 600 "$USERS_FILE"
- printf 'Created Authelia user %s\n' "$USERNAME"
-fi
-
-docker compose --project-directory "$PROJECT_DIR" config --quiet
-
-printf '\nInitialization complete.\n'
-printf 'Add wiki.%s, dav.%s, and auth.%s to local DNS, then run:\n' \
- "$BASE_DOMAIN" "$BASE_DOMAIN" "$BASE_DOMAIN"
-printf ' docker compose up -d --build\n'
diff --git a/scripts/run.sh b/scripts/run.sh
index 9164aa6..8843f9f 100755
--- a/scripts/run.sh
+++ b/scripts/run.sh
@@ -1,3 +1,15 @@
-#/usr/bin/bash
+#!/bin/sh
-tiddlywiki . --listen port=10000 use-browser-cache=yes \ No newline at end of file
+set -eu
+
+SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
+PROJECT_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)
+TIDDLYWIKI_BIN=${TIDDLYWIKI_BIN:-tiddlywiki}
+TDWIKI_LISTEN_HOST=${TDWIKI_LISTEN_HOST:-127.0.0.1}
+TDWIKI_LISTEN_PORT=${TDWIKI_LISTEN_PORT:-10000}
+
+exec "$TIDDLYWIKI_BIN" "$PROJECT_DIR" --listen \
+ host="$TDWIKI_LISTEN_HOST" \
+ port="$TDWIKI_LISTEN_PORT" \
+ gzip=yes \
+ use-browser-cache=yes