Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ jobs:
- kind: ja-JP
tag: latest
base: "/docs/"
- kind: no-config
tag: v0.14.1
base: "/docs/"
name: |
Build for ${{ matrix.kind }} ${{ matrix.tag }} (base: ${{ matrix.base }})
steps:
Expand All @@ -89,11 +92,14 @@ jobs:
if: ${{ matrix.kind == 'ja-JP' }}
run: bun run fetch-docs-ja-jp
- name: Fetch docs assets
if: ${{ matrix.kind == 'official' }}
if: ${{ matrix.kind == 'official' || matrix.kind == 'no-config' }}
shell: bash
run: |
set -euxo pipefail
bash scripts/fetch-docs-assets.sh --tag "${{ matrix.tag }}" --base "${{ matrix.base }}" --dest public
bash scripts/fetch-docs-assets.sh \
--tag "${{ matrix.tag }}" \
--base "${{ matrix.base }}" \
--dest public ${{ matrix.kind == 'no-config' && '--skip metadata --skip favicon' || '' }}

- name: Run Vite build
run: bun run build
Expand Down
110 changes: 71 additions & 39 deletions scripts/fetch-docs-assets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@ set -euo pipefail

print_usage() {
cat <<'EOF'
Usage: fetch-docs-assets.sh [--tag TAG] [--base BASE] [--dest DEST] [--origin ORIGIN]
Usage: fetch-docs-assets.sh [--tag TAG] [--base BASE] [options...]

Environment/args:
--tag TAG (required) Release tag to download, e.g. v0.14.0 or latest
--base BASE (required) Base path used by docs, e.g. / or /docs/
--dest DEST (optional) Destination directory to write files (default: public)
--origin ORIGIN (optional) Origin URL for the deployed site, without base path (default: https://example.com/)
--skip FILE (optional) Skip one of the files (docs.json, docs-assets, favicon, metadata), can be specified multiple times

This script performs the following:
- Downloads docs.json from the release tag
- Replaces '/DOCS-BASE/' placeholder in docs.json with the provided base
- Downloads docs-assets.zip and extracts it to destination/assets
- Downloads favicon and writes to destination/favicon.png
- Generates destination/metadata.json with basic deployment metadata
- docs.json:
- Downloads docs.json from the release tag
- Replaces '/DOCS-BASE/' placeholder in docs.json with the provided base
- docs-assets: Downloads docs-assets.zip and extracts it to destination/assets
- favicon: Downloads favicon and writes to destination/favicon.png
- metadata: Generates destination/metadata.json with basic deployment metadata
EOF
}

Expand All @@ -30,6 +32,7 @@ DEST="public"
ORIGIN="https://example.com/"
TAG=""
BASE=""
SKIP=()

# Parse args
while [[ $# -gt 0 ]]; do
Expand All @@ -50,6 +53,19 @@ while [[ $# -gt 0 ]]; do
ORIGIN="$2"
shift 2
;;
--skip)
case "$2" in
docs.json | docs-assets | favicon | metadata)
SKIP+=("$2")
shift 2
;;
*)
echo "Invalid --skip option: $2" >&2
print_usage
exit 2
;;
esac
;;
--help | -h)
print_usage
exit 0
Expand Down Expand Up @@ -80,52 +96,67 @@ fi
RELEASE_BASE_URL="https://github.com/${ORG}/dev-builds/releases/download/docs-${TAG}"

# Download docs.json
DOCS_URL="${RELEASE_BASE_URL}/docs.json"
echo "Fetching docs from ${DOCS_URL}"
if ! curl -sSfL "$DOCS_URL" -o "${DEST}/docs.json"; then
echo "Failed to download docs.json from ${DOCS_URL}" >&2
exit 3
fi

# Replace placeholder '/DOCS-BASE/' with provided base in docs.json
# Use `sd` if available, else fallback to sed
if command -v sd >/dev/null 2>&1; then
sd '/DOCS-BASE/' "$BASE" "${DEST}/docs.json"
if printf '%s\n' "${SKIP[@]}" | grep -qx "docs.json"; then
echo "Skipping docs.json download as per --skip option"
else
# Use portable sed: escape slashes
ESCAPED_BASE=$(printf '%s' "$BASE" | sed 's|/|\\/|g')
sed -i "s/\/DOCS-BASE\//${ESCAPED_BASE}/g" "${DEST}/docs.json"
DOCS_URL="${RELEASE_BASE_URL}/docs.json"
echo "Fetching docs from ${DOCS_URL}"
if ! curl -sSfL "$DOCS_URL" -o "${DEST}/docs.json"; then
echo "Failed to download docs.json from ${DOCS_URL}" >&2
exit 3
fi

# Replace placeholder '/DOCS-BASE/' with provided base in docs.json
# Use `sd` if available, else fallback to sed
if command -v sd >/dev/null 2>&1; then
sd '/DOCS-BASE/' "$BASE" "${DEST}/docs.json"
else
# Use portable sed: escape slashes
ESCAPED_BASE=$(printf '%s' "$BASE" | sed 's|/|\\/|g')
sed -i "s/\/DOCS-BASE\//${ESCAPED_BASE}/g" "${DEST}/docs.json"
fi
fi

# Download assets and extract
ASSETS_URL="${RELEASE_BASE_URL}/docs-assets.zip"
ASSETS_ZIP="docs-assets.zip"
if curl -sSfL "$ASSETS_URL" -o "$ASSETS_ZIP"; then
echo "Extracting ${ASSETS_ZIP} to ${DEST}/assets"
# Clean up existing assets if present
rm -rf "${DEST}/assets"
unzip -q "$ASSETS_ZIP"
if [[ -d assets ]]; then
mv assets "${DEST}/assets"
if printf '%s\n' "${SKIP[@]}" | grep -qx "docs-assets"; then
echo "Skipping docs-assets download as per --skip option"
else
ASSETS_URL="${RELEASE_BASE_URL}/docs-assets.zip"
ASSETS_ZIP="docs-assets.zip"
if curl -sSfL "$ASSETS_URL" -o "$ASSETS_ZIP"; then
echo "Extracting ${ASSETS_ZIP} to ${DEST}/assets"
# Clean up existing assets if present
rm -rf "${DEST}/assets"
unzip -q "$ASSETS_ZIP"
if [[ -d assets ]]; then
mv assets "${DEST}/assets"
else
echo "Downloaded zip did not contain assets/ folder" >&2
# keep build going; not necessarily fatal
fi
rm -f "$ASSETS_ZIP"
else
echo "Downloaded zip did not contain assets/ folder" >&2
# keep build going; not necessarily fatal
echo "No assets ZIP was found at ${ASSETS_URL} (continuing without error)" >&2
fi
rm -f "$ASSETS_ZIP"
else
echo "No assets ZIP was found at ${ASSETS_URL} (continuing without error)" >&2
fi

# Download favicon
FAVICON_URL="https://github.com/${ORG}/org/raw/main/design/typst-community.icon.png"
if curl -sSfL "$FAVICON_URL" -o "${DEST}/favicon.png"; then
echo "Wrote favicon to ${DEST}/favicon.png"
if printf '%s\n' "${SKIP[@]}" | grep -qx "favicon"; then
echo "Skipping favicon download as per --skip option"
else
echo "Failed to download favicon from ${FAVICON_URL} (continuing without error)" >&2
FAVICON_URL="https://github.com/${ORG}/org/raw/main/design/typst-community.icon.png"
if curl -sSfL "$FAVICON_URL" -o "${DEST}/favicon.png"; then
echo "Wrote favicon to ${DEST}/favicon.png"
else
echo "Failed to download favicon from ${FAVICON_URL} (continuing without error)" >&2
fi
fi

# Write metadata.json
cat >"${DEST}/metadata.json" <<EOF
if printf '%s\n' "${SKIP[@]}" | grep -qx "metadata"; then
echo "Skipping metadata generation as per --skip option"
else
cat >"${DEST}/metadata.json" <<EOF
{
"\$schema": "../metadata.schema.json",
"language": "en-US",
Expand All @@ -145,6 +176,7 @@ cat >"${DEST}/metadata.json" <<EOF
"displayTranslationStatus": false
}
EOF
fi

# Done
printf '\nFetch docs assets script done.\n'
Expand Down
7 changes: 5 additions & 2 deletions scripts/netlify-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,11 @@ build_en_US v0.13.1
# At present, typst-jp do not translate comments within example code.
# And there is no simple way to download assets from GitHub Actions or the gh-pages branch.
# Therefore, we reuse the assets from the official version.
bash scripts/fetch-docs-assets.sh --tag "v0.13.1" --base "/irrelevant/"
rm public/{docs,metadata}.json
bash scripts/fetch-docs-assets.sh \
--tag "v0.13.1" \
--base "/irrelevant/" \
--skip docs.json \
--skip metadata

# Prepare JSON files
mise exec -- bun run fetch-docs-ja-jp
Expand Down
8 changes: 1 addition & 7 deletions src/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,7 @@ const metadata: Metadata = (() => {
typstOfficialUrl: "https://typst.app/",
typstOfficialDocsUrl: "https://typst.app/docs/",
githubOrganizationUrl: "https://github.com/typst",
socialLinks: [
{ url: "https://github.com/typst/typst" },
{
title: "Discord (dummy)",
url: "https://discord.gg/dummy",
},
],
socialLinks: [{ url: "https://github.com/typst/typst" }],
originUrl: "https://example.com/",
basePath: "/docs/",
displayTranslationStatus: true,
Expand Down
19 changes: 7 additions & 12 deletions src/translation/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import type { FC } from "hono/jsx";
import type { TooltipProps } from "../components/ui/Tooltip";
import { language } from "../metadata";
import {
Translation as EnUSTranslation,
translation as enUSTranslation,
} from "./en-US";
import {
Translation as JaJPTranslation,
translation as jaJPTranslation,
} from "./ja-JP";

/**
* Translation dictionary for UI attributes and aria labels.
Expand Down Expand Up @@ -105,12 +97,15 @@ export type TranslationComponentProps =
export type TranslationComponent = FC<TranslationComponentProps>;

// Switch translation language.
const { Translation, translation } = (() => {
const { Translation, translation } = await (() => {
// These imports should be lazy and static.
// - Lazy: A translation may use special metadata (e.g., Discord/QQ URL), so not all translations can be safely imported in every build. Therefore, we have to use the import function, not the import statement.
// - Static: The argument of the import function has to be a plain string, not a variable. Dynamic import has limitations even with rollup and vite properly configured.
switch (language) {
case "ja-JP":
return { Translation: JaJPTranslation, translation: jaJPTranslation };
case "en-US":
return { Translation: EnUSTranslation, translation: enUSTranslation };
return import("./en-US");
case "ja-JP":
return import("./ja-JP");
default:
throw new Error(`Unsupported language: ${language}`);
}
Expand Down