diff --git a/build-archived-version.sh b/build-archived-version.sh new file mode 100755 index 00000000..68ec7bed --- /dev/null +++ b/build-archived-version.sh @@ -0,0 +1,128 @@ +#!/bin/bash +set -euo pipefail + +# build-archived-version.sh - Build a standalone static Docusaurus site for an archived version +# +# Usage: ./build-archived-version.sh [--llama-stack-dir ] +# +# Examples: +# ./build-archived-version.sh v0.5.0 +# ./build-archived-version.sh v0.6.0 --llama-stack-dir /tmp/llama-stack +# +# Output: docs// containing the full static site + +VERSION="${1:?Usage: $0 [--llama-stack-dir ]}" +REPO_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Parse optional arguments +LLAMA_STACK_DIR="" +shift +while [[ $# -gt 0 ]]; do + case $1 in + --llama-stack-dir) LLAMA_STACK_DIR="$2"; shift 2 ;; + *) echo "Unknown option: $1"; exit 1 ;; + esac +done + +# Setup temp directory for the build +TEMP_DIR=$(mktemp -d) +BUILD_DIR="$TEMP_DIR/llama-stack/docs" +trap 'rm -rf "$TEMP_DIR"' EXIT + +echo "=== Building archived version $VERSION ===" + +# Step 1: Get llama-stack at the specified version +if [ -n "$LLAMA_STACK_DIR" ] && [ -d "$LLAMA_STACK_DIR" ]; then + echo "--- Cloning from local repo ---" + git clone --local --no-checkout "$LLAMA_STACK_DIR" "$TEMP_DIR/llama-stack" + cd "$TEMP_DIR/llama-stack" + git checkout "$VERSION" 2>/dev/null || git checkout "tags/$VERSION" +else + echo "--- Cloning from GitHub ---" + git clone --depth 1 --branch "$VERSION" https://github.com/llamastack/llama-stack.git "$TEMP_DIR/llama-stack" +fi + +cd "$BUILD_DIR" + +# Step 2: Install dependencies +echo "--- Installing dependencies ---" +npm ci 2>&1 | tail -5 + +# Step 3: Generate API docs +echo "--- Generating API docs ---" + +if [ -f "static/llama-stack-spec.yaml" ]; then + npm run gen-api-docs stable 2>&1 | grep -E "^Successfully" || true +fi + +if [ -f "static/experimental-llama-stack-spec.yaml" ]; then + npm run gen-api-docs experimental 2>&1 | grep -E "^Successfully" || true +fi + +if [ -f "static/deprecated-llama-stack-spec.yaml" ]; then + npm run gen-api-docs deprecated 2>&1 | grep -E "^Successfully" || true +fi + +# Step 4: Inline raw-loader imports +echo "--- Inlining raw-loader imports ---" +python3 "$REPO_DIR/inline-raw-loader.py" docs "$TEMP_DIR/llama-stack" + +# Step 5: Fix MDX compatibility issues +echo "--- Fixing MDX compatibility ---" +python3 "$REPO_DIR/fix-mdx-compat.py" docs + +# Step 6: Patch config for standalone archived build +echo "--- Patching config for baseUrl: /$VERSION/ ---" +export VERSION +node << 'CONFIGEOF' +const fs = require('fs'); +const version = process.env.VERSION; + +let config = fs.readFileSync('docusaurus.config.ts', 'utf8'); + +// Set baseUrl to /vX.Y.Z/ +config = config.replace( + /baseUrl:\s*["'][^"']*["']/, + `baseUrl: '/${version}/'` +); + +// Add announcement banner for archived version inside themeConfig +const bannerEntry = ` + announcementBar: { + id: 'archived_version', + content: 'This is documentation for ${version}. For the latest version, visit the main site.', + backgroundColor: '#2b3137', + textColor: '#ffffff', + isCloseable: false, + },`; + +// Insert after "themeConfig: {" +config = config.replace( + /themeConfig:\s*\{/, + `themeConfig: {${bannerEntry}` +); + +// Fix blog include pattern to support both .md and .mdx +config = config.replace( + /include:\s*\['?\*\.md'?\]/g, + "include: ['*.{md,mdx}']" +); + +fs.writeFileSync('docusaurus.config.ts', config); +console.log('Config patched'); +CONFIGEOF + +# Step 7: Build +echo "--- Building ---" +NODE_OPTIONS="--max-old-space-size=8192" npm run build 2>&1 | tail -50 + +# Step 8: Copy build output to docs// +echo "--- Copying to docs/$VERSION/ ---" +OUTPUT_DIR="$REPO_DIR/docs/$VERSION" +rm -rf "$OUTPUT_DIR" +mkdir -p "$OUTPUT_DIR" +cp -r build/* "$OUTPUT_DIR/" + +echo "=== Done building $VERSION ===" +echo "Output: docs/$VERSION/" +du -sh "$OUTPUT_DIR" diff --git a/docs/versions.html b/docs/versions.html new file mode 100644 index 00000000..252ffd02 --- /dev/null +++ b/docs/versions.html @@ -0,0 +1,51 @@ + + + + + + Llama Stack Documentation Versions + + + +
+

Documentation Versions

+

All published versions of the Llama Stack documentation.

+
+ Latest (main) + current +
+
    +

    Back to latest docs

    +
    + + + diff --git a/docs/versionsArchived.json b/docs/versionsArchived.json new file mode 100644 index 00000000..295a056a --- /dev/null +++ b/docs/versionsArchived.json @@ -0,0 +1,14 @@ +{ + "v0.2.22": "https://llamastack.github.io/v0.2.22/", + "v0.2.21": "https://llamastack.github.io/v0.2.21/", + "v0.2.20": "https://llamastack.github.io/v0.2.20/", + "v0.2.19": "https://llamastack.github.io/v0.2.19/", + "v0.2.18": "https://llamastack.github.io/v0.2.18/", + "v0.2.17": "https://llamastack.github.io/v0.2.17/", + "v0.2.16": "https://llamastack.github.io/v0.2.16/", + "v0.2.15": "https://llamastack.github.io/v0.2.15/", + "v0.2.14": "https://llamastack.github.io/v0.2.14/", + "v0.2.13": "https://llamastack.github.io/v0.2.13/", + "v0.2.12": "https://llamastack.github.io/v0.2.12/", + "v0.2.11": "https://llamastack.github.io/v0.2.11/" +} diff --git a/fix-mdx-compat.py b/fix-mdx-compat.py new file mode 100755 index 00000000..2bc21494 --- /dev/null +++ b/fix-mdx-compat.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +"""Fix MDX-incompatible syntax in markdown/mdx files. + +Usage: python3 fix-mdx-compat.py + +Fixes patterns that break Docusaurus MDX v3 parser: + - <|...|> (LLM special tokens) -> <|...|> + - < <<EOF + - { and } outside code fences/inline code -> \{ and \} + +Only processes files that have <| or <). +""" + +import re +import os +import sys +import glob + + +def needs_fixing(content): + """Check if file has patterns that need fixing.""" + in_code_fence = False + for line in content.split("\n"): + stripped = line.strip() + if stripped.startswith("```") or stripped.startswith("~~~"): + in_code_fence = not in_code_fence + continue + if in_code_fence: + continue + if "<|" in line or "<]", stripped): + return True + return False + + +def fix_line(line): + """Fix a single line outside code fences.""" + # Escape <| and << + line = line.replace("<|", "<|") + line = re.sub(r"<<(\w+)", r"<<\1", line) + + # Escape { and } outside inline code spans + parts = re.split(r"(`[^`]+`)", line) + escaped_parts = [] + for part in parts: + if part.startswith("`") and part.endswith("`"): + escaped_parts.append(part) + else: + part = re.sub(r"(? + +Example: python3 inline-raw-loader.py versioned_docs/version-v0.4.1 /tmp/llama-stack +""" + +import re +import os +import sys +import glob + + +def escape_for_mdx(text): + """Escape MDX-incompatible syntax in imported content.""" + lines = text.split("\n") + result = [] + in_code_fence = False + + for line in lines: + stripped = line.strip() + + # Track code fences + if stripped.startswith("```") or stripped.startswith("~~~"): + in_code_fence = not in_code_fence + result.append(line) + continue + + if in_code_fence: + result.append(line) + continue + + # Convert autolinks to [URL](URL) format + line = re.sub(r"<(https?://[^>]+)>", r"[\1](\1)", line) + + # Escape { and } outside inline code spans + parts = re.split(r"(`[^`]+`)", line) + escaped_parts = [] + for part in parts: + if part.startswith("`") and part.endswith("`"): + escaped_parts.append(part) + else: + part = re.sub(r"(? {candidate}") + break + + if imported_content is None: + print(f" WARNING: Could not resolve {file_ref}") + continue + + # Remove the raw-loader import line + content = re.sub( + r"import\s+" + var_name + r"\s+from\s+'!!raw-loader![^']+';[ \t]*\n", + "", + content, + ) + + # Remove ReactMarkdown import + content = re.sub( + r"import\s+ReactMarkdown\s+from\s+'react-markdown';[ \t]*\n", + "", + content, + ) + + # Convert RST-style admonitions to Docusaurus format + imported_content = re.sub(r"```\{note\}", ":::note", imported_content) + imported_content = re.sub(r"```\{caution\}", ":::caution", imported_content) + imported_content = re.sub(r"```\{tip\}", ":::tip", imported_content) + imported_content = re.sub(r"```\{warning\}", ":::warning", imported_content) + imported_content = re.sub( + r"(:::(?:note|caution|tip|warning)\n(?:(?!```).)*?\n)```", + r"\1:::", + imported_content, + flags=re.DOTALL, + ) + + # Fix relative links that point to repo files + imported_content = imported_content.replace( + "](tests/README.md)", + "](https://github.com/llamastack/llama-stack/blob/main/tests/README.md)", + ) + imported_content = imported_content.replace( + "](./RELEASE_PROCESS.md)", + "](https://github.com/llamastack/llama-stack/blob/main/RELEASE_PROCESS.md)", + ) + imported_content = imported_content.replace( + "](README.md)", "](https://github.com/llamastack/llama-stack#community)" + ) + imported_content = imported_content.replace( + "](llama_stack/", + "](https://github.com/llamastack/llama-stack/blob/main/llama_stack/", + ) + + # Escape MDX-incompatible syntax in imported content + imported_content = escape_for_mdx(imported_content) + + # Replace {VarName} with inlined content + content = re.sub( + r"\{" + var_name + r"\}", + imported_content, + content, + ) + + with open(mdx_path, "w") as f: + f.write(content) + print(" Inlined successfully") + + +if __name__ == "__main__": + if len(sys.argv) != 3: + print(__doc__) + sys.exit(1) + inline_raw_loader(sys.argv[1], sys.argv[2])