From 4deb2d6117b07ecbae03e6e47a995d26b222999a Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:06:50 +0200 Subject: [PATCH 1/6] fetch docs without git submodules --- .gitignore | 4 ++++ .gitmodules | 4 ---- README.md | 9 ++++++++ justfile | 6 +++--- package.json | 4 ++++ scripts/fetch-docs.mjs | 49 ++++++++++++++++++++++++++++++++++++++++++ src/content/docs | 1 - 7 files changed, 69 insertions(+), 8 deletions(-) delete mode 100644 .gitmodules create mode 100644 scripts/fetch-docs.mjs delete mode 160000 src/content/docs diff --git a/.gitignore b/.gitignore index 49ceb21..ef02775 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,7 @@ pnpm-debug.log* # macOS-specific files .DS_Store .vercel + +# downloaded documentation +src/content/docs/ +src/content/.docs-*/ diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 5575b6a..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "src/content/docs"] - path = src/content/docs - url = https://github.com/zane-lang/docs - branch = main diff --git a/README.md b/README.md index 36e84f3..ea5b86d 100644 --- a/README.md +++ b/README.md @@ -1 +1,10 @@ # The Zane Website + +The documentation is downloaded from [`zane-lang/docs`](https://github.com/zane-lang/docs) +before starting the development server or building the site. To refresh it manually, run: + +```sh +npm run sync:docs +``` + +Set `ZANE_DOCS_REF` to fetch a branch, tag, or commit other than `main`. diff --git a/justfile b/justfile index d9fd74d..67441d9 100644 --- a/justfile +++ b/justfile @@ -1,5 +1,5 @@ -submodules: - git submodule update --remote --recursive --force +docs: + npm run sync:docs dev: npm run dev @@ -8,7 +8,7 @@ ship: #!/usr/bin/env bash read -p "Are you sure you want to deploy to production? [y/N] " confirm if [[ "$confirm" =~ ^[Yy]$ ]]; then - just submodules && vercel --prod + vercel --prod else echo "Deployment cancelled." fi diff --git a/package.json b/package.json index a777fd3..7eb0c0e 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,12 @@ "type": "module", "version": "0.0.1", "scripts": { + "sync:docs": "node scripts/fetch-docs.mjs", + "predev": "npm run sync:docs", "dev": "astro dev", + "prestart": "npm run sync:docs", "start": "astro dev", + "prebuild": "npm run sync:docs", "build": "astro build", "preview": "astro preview", "astro": "astro" diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs new file mode 100644 index 0000000..4a8e7e2 --- /dev/null +++ b/scripts/fetch-docs.mjs @@ -0,0 +1,49 @@ +import { spawnSync } from 'node:child_process'; +import { mkdtemp, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repository = 'zane-lang/docs'; +const ref = process.env.ZANE_DOCS_REF || 'main'; +const root = join(dirname(fileURLToPath(import.meta.url)), '..'); +const destination = join(root, 'src/content/docs'); +const workDirectory = await mkdtemp(join(root, 'src/content/.docs-')); +const archive = join(workDirectory, 'docs.tar.gz'); +const extracted = join(workDirectory, 'extracted'); + +try { + const response = await fetch( + `https://api.github.com/repos/${repository}/tarball/${encodeURIComponent(ref)}`, + { + headers: { + Accept: 'application/vnd.github+json', + 'User-Agent': 'zane-lang-website', + }, + }, + ); + + if (!response.ok) { + throw new Error(`GitHub returned ${response.status} ${response.statusText}`); + } + + await writeFile(archive, Buffer.from(await response.arrayBuffer())); + await mkdir(extracted); + + const result = spawnSync( + 'tar', + ['-xzf', archive, '--strip-components=1', '-C', extracted], + { encoding: 'utf8' }, + ); + + if (result.error) throw result.error; + if (result.status !== 0) { + throw new Error(result.stderr.trim() || `tar exited with status ${result.status}`); + } + + await readFile(join(extracted, 'README.md')); + await rm(destination, { recursive: true, force: true }); + await rename(extracted, destination); + console.log(`Downloaded ${repository}@${ref} to src/content/docs`); +} finally { + await rm(workDirectory, { recursive: true, force: true }); +} diff --git a/src/content/docs b/src/content/docs deleted file mode 160000 index 3074f50..0000000 --- a/src/content/docs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3074f5023e45b3db411bb0fddcdb427094916181 From d4ce9c2f50980a0996ac67d0a6e7402b917db0ce Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:23:33 +0200 Subject: [PATCH 2/6] avoid redundant docs downloads in development --- package.json | 4 ++-- scripts/fetch-docs.mjs | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7eb0c0e..145f143 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "version": "0.0.1", "scripts": { "sync:docs": "node scripts/fetch-docs.mjs", - "predev": "npm run sync:docs", + "predev": "npm run sync:docs -- --skip-if-exists", "dev": "astro dev", - "prestart": "npm run sync:docs", + "prestart": "npm run sync:docs -- --skip-if-exists", "start": "astro dev", "prebuild": "npm run sync:docs", "build": "astro build", diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs index 4a8e7e2..118554e 100644 --- a/scripts/fetch-docs.mjs +++ b/scripts/fetch-docs.mjs @@ -1,5 +1,5 @@ import { spawnSync } from 'node:child_process'; -import { mkdtemp, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises'; +import { access, mkdtemp, mkdir, rename, rm, writeFile } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -7,6 +7,15 @@ const repository = 'zane-lang/docs'; const ref = process.env.ZANE_DOCS_REF || 'main'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const destination = join(root, 'src/content/docs'); + +if (process.argv.includes('--skip-if-exists')) { + try { + await access(join(destination, 'README.md')); + console.log('Docs already exist, skipping download.'); + process.exit(0); + } catch {} +} + const workDirectory = await mkdtemp(join(root, 'src/content/.docs-')); const archive = join(workDirectory, 'docs.tar.gz'); const extracted = join(workDirectory, 'extracted'); @@ -40,7 +49,7 @@ try { throw new Error(result.stderr.trim() || `tar exited with status ${result.status}`); } - await readFile(join(extracted, 'README.md')); + await access(join(extracted, 'README.md')); await rm(destination, { recursive: true, force: true }); await rename(extracted, destination); console.log(`Downloaded ${repository}@${ref} to src/content/docs`); From 53c7d5d8478f41797f477c4ba08c12e97f2db22d Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:32:02 +0200 Subject: [PATCH 3/6] make docs fetch robust on fresh clones --- scripts/fetch-docs.mjs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs index 118554e..c8fc4ac 100644 --- a/scripts/fetch-docs.mjs +++ b/scripts/fetch-docs.mjs @@ -6,7 +6,8 @@ import { fileURLToPath } from 'node:url'; const repository = 'zane-lang/docs'; const ref = process.env.ZANE_DOCS_REF || 'main'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); -const destination = join(root, 'src/content/docs'); +const contentDirectory = join(root, 'src/content'); +const destination = join(contentDirectory, 'docs'); if (process.argv.includes('--skip-if-exists')) { try { @@ -16,18 +17,19 @@ if (process.argv.includes('--skip-if-exists')) { } catch {} } -const workDirectory = await mkdtemp(join(root, 'src/content/.docs-')); +await mkdir(contentDirectory, { recursive: true }); +const workDirectory = await mkdtemp(join(contentDirectory, '.docs-')); const archive = join(workDirectory, 'docs.tar.gz'); const extracted = join(workDirectory, 'extracted'); try { const response = await fetch( - `https://api.github.com/repos/${repository}/tarball/${encodeURIComponent(ref)}`, + `https://github.com/${repository}/archive/${encodeURIComponent(ref)}.tar.gz`, { headers: { - Accept: 'application/vnd.github+json', 'User-Agent': 'zane-lang-website', }, + signal: AbortSignal.timeout(30_000), }, ); From 4c2b11c015d92e5f46bed2b260ee3524cb2b0a18 Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:42:16 +0200 Subject: [PATCH 4/6] decouple docs sync from repository files --- scripts/fetch-docs.mjs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs index c8fc4ac..e2ea278 100644 --- a/scripts/fetch-docs.mjs +++ b/scripts/fetch-docs.mjs @@ -11,7 +11,7 @@ const destination = join(contentDirectory, 'docs'); if (process.argv.includes('--skip-if-exists')) { try { - await access(join(destination, 'README.md')); + await access(destination); console.log('Docs already exist, skipping download.'); process.exit(0); } catch {} @@ -51,7 +51,6 @@ try { throw new Error(result.stderr.trim() || `tar exited with status ${result.status}`); } - await access(join(extracted, 'README.md')); await rm(destination, { recursive: true, force: true }); await rename(extracted, destination); console.log(`Downloaded ${repository}@${ref} to src/content/docs`); From f543f5e5af5697dad8a5a9db5f8845970d4a509c Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:51:31 +0200 Subject: [PATCH 5/6] fetch docs with a shallow clone --- README.md | 5 +++-- scripts/fetch-docs.mjs | 37 ++++++++++--------------------------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index ea5b86d..eb34683 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # The Zane Website -The documentation is downloaded from [`zane-lang/docs`](https://github.com/zane-lang/docs) +The documentation is shallow-cloned from [`zane-lang/docs`](https://github.com/zane-lang/docs) before starting the development server or building the site. To refresh it manually, run: ```sh npm run sync:docs ``` -Set `ZANE_DOCS_REF` to fetch a branch, tag, or commit other than `main`. +Set `ZANE_DOCS_REF` to clone a branch or tag other than `main`. The clone's `.git` +directory is removed after fetching, and the downloaded documentation is ignored by Git. diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs index e2ea278..cf18ef5 100644 --- a/scripts/fetch-docs.mjs +++ b/scripts/fetch-docs.mjs @@ -1,9 +1,9 @@ import { spawnSync } from 'node:child_process'; -import { access, mkdtemp, mkdir, rename, rm, writeFile } from 'node:fs/promises'; +import { access, mkdtemp, mkdir, rename, rm } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; -const repository = 'zane-lang/docs'; +const repository = 'https://github.com/zane-lang/docs.git'; const ref = process.env.ZANE_DOCS_REF || 'main'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const contentDirectory = join(root, 'src/content'); @@ -19,41 +19,24 @@ if (process.argv.includes('--skip-if-exists')) { await mkdir(contentDirectory, { recursive: true }); const workDirectory = await mkdtemp(join(contentDirectory, '.docs-')); -const archive = join(workDirectory, 'docs.tar.gz'); -const extracted = join(workDirectory, 'extracted'); +const checkout = join(workDirectory, 'checkout'); try { - const response = await fetch( - `https://github.com/${repository}/archive/${encodeURIComponent(ref)}.tar.gz`, - { - headers: { - 'User-Agent': 'zane-lang-website', - }, - signal: AbortSignal.timeout(30_000), - }, - ); - - if (!response.ok) { - throw new Error(`GitHub returned ${response.status} ${response.statusText}`); - } - - await writeFile(archive, Buffer.from(await response.arrayBuffer())); - await mkdir(extracted); - const result = spawnSync( - 'tar', - ['-xzf', archive, '--strip-components=1', '-C', extracted], - { encoding: 'utf8' }, + 'git', + ['clone', '--depth=1', '--branch', ref, '--single-branch', repository, checkout], + { encoding: 'utf8', timeout: 30_000 }, ); if (result.error) throw result.error; if (result.status !== 0) { - throw new Error(result.stderr.trim() || `tar exited with status ${result.status}`); + throw new Error(result.stderr.trim() || `git clone exited with status ${result.status}`); } + await rm(join(checkout, '.git'), { recursive: true, force: true }); await rm(destination, { recursive: true, force: true }); - await rename(extracted, destination); - console.log(`Downloaded ${repository}@${ref} to src/content/docs`); + await rename(checkout, destination); + console.log(`Cloned zane-lang/docs@${ref} to src/content/docs`); } finally { await rm(workDirectory, { recursive: true, force: true }); } From ee5404e872c4324d00d8b17d844428feed6ee2ca Mon Sep 17 00:00:00 2001 From: Manuel Stieger <149385373+TheLazyCat00@users.noreply.github.com> Date: Mon, 20 Jul 2026 14:57:42 +0200 Subject: [PATCH 6/6] run docs sync without package-manager recursion --- package.json | 6 +++--- scripts/fetch-docs.mjs | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 145f143..590eeca 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,11 @@ "version": "0.0.1", "scripts": { "sync:docs": "node scripts/fetch-docs.mjs", - "predev": "npm run sync:docs -- --skip-if-exists", + "predev": "node scripts/fetch-docs.mjs --skip-if-exists", "dev": "astro dev", - "prestart": "npm run sync:docs -- --skip-if-exists", + "prestart": "node scripts/fetch-docs.mjs --skip-if-exists", "start": "astro dev", - "prebuild": "npm run sync:docs", + "prebuild": "node scripts/fetch-docs.mjs", "build": "astro build", "preview": "astro preview", "astro": "astro" diff --git a/scripts/fetch-docs.mjs b/scripts/fetch-docs.mjs index cf18ef5..b3ef866 100644 --- a/scripts/fetch-docs.mjs +++ b/scripts/fetch-docs.mjs @@ -1,7 +1,10 @@ -import { spawnSync } from 'node:child_process'; +import { execFile } from 'node:child_process'; import { access, mkdtemp, mkdir, rename, rm } from 'node:fs/promises'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { promisify } from 'node:util'; + +const execFileAsync = promisify(execFile); const repository = 'https://github.com/zane-lang/docs.git'; const ref = process.env.ZANE_DOCS_REF || 'main'; @@ -22,21 +25,19 @@ const workDirectory = await mkdtemp(join(contentDirectory, '.docs-')); const checkout = join(workDirectory, 'checkout'); try { - const result = spawnSync( + await execFileAsync( 'git', ['clone', '--depth=1', '--branch', ref, '--single-branch', repository, checkout], - { encoding: 'utf8', timeout: 30_000 }, + { timeout: 30_000 }, ); - if (result.error) throw result.error; - if (result.status !== 0) { - throw new Error(result.stderr.trim() || `git clone exited with status ${result.status}`); - } - await rm(join(checkout, '.git'), { recursive: true, force: true }); await rm(destination, { recursive: true, force: true }); await rename(checkout, destination); console.log(`Cloned zane-lang/docs@${ref} to src/content/docs`); +} catch (error) { + const stderr = typeof error?.stderr === 'string' ? error.stderr.trim() : ''; + throw new Error(stderr || error?.message || 'Failed to clone documentation', { cause: error }); } finally { await rm(workDirectory, { recursive: true, force: true }); }