aboutsummaryrefslogtreecommitdiff
path: root/website/scripts
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-02 21:48:02 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-02 21:48:02 +0300
commitb751d102f158968aab681cb663d27b4c32197f62 (patch)
tree85d03609314559df7705c2cb0ab4e37ab6d9715f /website/scripts
parent295b09ca25edbccac65401ee84fa420dd3888aad (diff)
feat: add preview update channel
Diffstat (limited to 'website/scripts')
-rw-r--r--website/scripts/prepare-docs.mjs80
1 files changed, 76 insertions, 4 deletions
diff --git a/website/scripts/prepare-docs.mjs b/website/scripts/prepare-docs.mjs
index c6fefaf7..19201a18 100644
--- a/website/scripts/prepare-docs.mjs
+++ b/website/scripts/prepare-docs.mjs
@@ -1,12 +1,23 @@
-import { cp, mkdir, rm } from 'node:fs/promises';
-import { dirname, resolve } from 'node:path';
+import { cp, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
+import { dirname, join, relative, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
+import process from 'node:process';
const websiteDir = dirname(fileURLToPath(import.meta.url));
const repoRoot = resolve(websiteDir, '../..');
const publicDir = resolve(repoRoot, 'website/public');
+const stableDocsDir = resolve(repoRoot, 'website/src/content/docs');
+const previewDocsSourceDir = resolve(repoRoot, 'docs/next/website/src/content/docs');
+const previewDocsDir = resolve(stableDocsDir, 'preview');
-await preparePublicAssets();
+if (process.argv[2] === '--rewrite-preview-doc-fixture') {
+ const chunks = [];
+ for await (const chunk of process.stdin) chunks.push(chunk);
+ process.stdout.write(rewritePreviewDocContent(Buffer.concat(chunks).toString('utf8')));
+} else {
+ await preparePublicAssets();
+ await preparePreviewDocs();
+}
async function preparePublicAssets() {
await rm(publicDir, { recursive: true, force: true });
@@ -15,11 +26,17 @@ async function preparePublicAssets() {
for (const file of [
'install.sh',
'latest.json',
+ 'preview.json',
'robots.txt',
'_headers',
'_redirects',
]) {
- await cp(resolve(repoRoot, 'website', file), resolve(publicDir, file));
+ const source = resolve(repoRoot, 'website', file);
+ try {
+ await cp(source, resolve(publicDir, file));
+ } catch (error) {
+ if (file !== 'preview.json' || error.code !== 'ENOENT') throw error;
+ }
}
for (const directory of ['assets', 'css']) {
@@ -28,3 +45,58 @@ async function preparePublicAssets() {
});
}
}
+
+async function preparePreviewDocs() {
+ await rm(previewDocsDir, { recursive: true, force: true });
+ await copyPreviewDocs(previewDocsSourceDir, previewDocsDir);
+}
+
+async function copyPreviewDocs(sourceDir, destinationDir) {
+ await mkdir(destinationDir, { recursive: true });
+ for (const entry of await readdir(sourceDir, { withFileTypes: true })) {
+ const source = join(sourceDir, entry.name);
+ const destination = join(destinationDir, entry.name);
+ if (entry.isDirectory()) {
+ await copyPreviewDocs(source, destination);
+ continue;
+ }
+ if (!entry.isFile()) continue;
+
+ const content = await readFile(source, 'utf8');
+ const relativePath = relative(previewDocsSourceDir, source);
+ await writeFile(destination, rewritePreviewDocContent(content, relativePath), 'utf8');
+ }
+}
+
+export function rewritePreviewDocContent(content, relativePath = '') {
+ const rewritten = content
+ .replaceAll('/docs/', '/docs/preview/')
+ .replaceAll('../../../public/', '../../../../public/');
+ return insertPreviewNotice(rewritten, relativePath);
+}
+
+function insertPreviewNotice(content, relativePath) {
+ const notice = [
+ '> Preview docs describe unreleased preview builds. Stable docs remain at [/docs/](/docs/).',
+ '',
+ '',
+ ].join('\n');
+ const indexPrefix =
+ relativePath === 'index.mdx'
+ ? content.replace('title: Herdr documentation', 'title: Herdr preview documentation')
+ : content;
+ const frontmatter = indexPrefix.match(/^---\n[\s\S]*?\n---\n/);
+ if (!frontmatter) {
+ return insertNoticeAfterImports(indexPrefix, notice);
+ }
+ const body = indexPrefix.slice(frontmatter[0].length);
+ return `${frontmatter[0]}\n${insertNoticeAfterImports(body, notice)}`;
+}
+
+function insertNoticeAfterImports(content, notice) {
+ const imports = content.match(/^(\s*import .+?;\n)+\s*/);
+ if (!imports) {
+ return `${notice}${content}`;
+ }
+ return `${imports[0]}${notice}${content.slice(imports[0].length)}`;
+}