diff --git a/website/.gitignore b/website/.gitignore new file mode 100644 index 000000000..ffd492d01 --- /dev/null +++ b/website/.gitignore @@ -0,0 +1 @@ +public/sitemap.xml diff --git a/website/adapters/netlify-edge/vite.config.ts b/website/adapters/netlify-edge/vite.config.ts index 67fdae2f5..d9e85ef35 100644 --- a/website/adapters/netlify-edge/vite.config.ts +++ b/website/adapters/netlify-edge/vite.config.ts @@ -11,6 +11,13 @@ export default extendConfig(baseConfig, () => { }, outDir: '.netlify/edge-functions/entry.netlify-edge', }, - plugins: [netlifyEdgeAdapter()], + plugins: [ + netlifyEdgeAdapter({ + ssg: { + include: [], + sitemapOutFile: null, + }, + }), + ], }; }); diff --git a/website/netlify.toml b/website/netlify.toml index d1edf8c94..63cdece29 100644 --- a/website/netlify.toml +++ b/website/netlify.toml @@ -1,3 +1,3 @@ [build] publish = "dist" -command = "npm run build" +command = "npm run sitemap && npm run build" diff --git a/website/package.json b/website/package.json index 12a9c7990..b393d22d7 100644 --- a/website/package.json +++ b/website/package.json @@ -17,6 +17,7 @@ "build.server": "vite build -c adapters/netlify-edge/vite.config.ts", "build.types": "tsc --incremental --noEmit", "contributors": "tsm ./scripts/contributors.ts", + "sitemap": "tsm ./scripts/sitemap.ts", "deploy": "netlify deploy --build", "dev": "vite --mode ssr", "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", diff --git a/website/scripts/contributors.ts b/website/scripts/contributors.ts index c119945da..a15b64dfa 100644 --- a/website/scripts/contributors.ts +++ b/website/scripts/contributors.ts @@ -17,11 +17,11 @@ const GITHUB_PERSONAL_ACCESS_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN; const EXCLUDED_COMMITS = ['2cc351f6db7798cf60276225abcbacbc1ea491db']; /** - * Finds all index files in the given directory. + * Finds all index files in the given directories. * * @param directories The directories to search in. */ -async function findIndexFiles(directories: string[]) { +function findIndexFiles(directories: string[]) { // Create file paths list const filePaths: string[] = []; @@ -40,7 +40,7 @@ async function findIndexFiles(directories: string[]) { const itemPath = path.join(directory, itemName); const itemStat = fs.statSync(itemPath); if (itemStat.isDirectory()) { - filePaths.push(...(await findIndexFiles([itemPath]))); + filePaths.push(...findIndexFiles([itemPath])); } } } @@ -60,7 +60,7 @@ async function updateContributors() { } // Find all MDX files of guides and API reference - const filePaths = await findIndexFiles([ + const filePaths = findIndexFiles([ path.join('src', 'routes', 'guides'), path.join('src', 'routes', 'api'), ]); diff --git a/website/scripts/sitemap.ts b/website/scripts/sitemap.ts new file mode 100644 index 000000000..a10a95b90 --- /dev/null +++ b/website/scripts/sitemap.ts @@ -0,0 +1,71 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const ORIGIN = 'https://valibot.dev/'; + +/** + * Finds all index files in the given directory. + * + * @param directory The directory to search in. + */ +function findIndexFiles(directory: string) { + // Create file paths list + const filePaths: string[] = []; + + // Get items of directory + const items = fs.readdirSync(directory); + + for (const itemName of items) { + // If item is a index file, add it to list + if (itemName === 'index.tsx' || itemName === 'index.mdx') { + filePaths.push(path.join(directory, itemName)); + + // Otherwise, search for nested index files + } else { + const itemPath = path.join(directory, itemName); + const itemStat = fs.statSync(itemPath); + if (itemStat.isDirectory()) { + filePaths.push(...findIndexFiles(itemPath)); + } + } + } + + // Return file paths list + return filePaths; +} + +/** + * Generates the sitemap of the website. + */ +async function generateSitemap() { + // Find all route index files + const filePaths = findIndexFiles(path.join('src', 'routes')); + + // Create URL paths and sort them + const urlSet = filePaths + // Transform file paths to URL paths + .map((filePath) => + filePath + .replace(/\\/g, '/') + .replace(/src\/routes\//, '') + .replace(/\(.+\)\//, '') + .replace(/index\.(tsx|mdx)/, '') + ) + // Sort URL paths alphabetically + .sort() + // Reduce URL paths to URL set + .reduce( + (urlPaths, urlPath) => + `${urlPaths}${ORIGIN}${urlPath}`, + '' + ); + + // Write sitemap.xml to public directory + fs.writeFileSync( + path.join('public', 'sitemap.xml'), + `${urlSet}` + ); +} + +// Start generation of sitemap +generateSitemap();