Created
February 14, 2022 14:59
-
-
Save multipliedtwice/fa90f7ab66d0088ea322d4362cd3a3d8 to your computer and use it in GitHub Desktop.
Sveltekit sitemap xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import dayjs from "dayjs" | |
import { supportedLanguages } from "../config" | |
import fs from "fs" | |
import path from "path" | |
const cwd = process.cwd() | |
import util from "util" | |
import glob from "glob" | |
const stat = util.promisify(fs.stat) | |
const asyncGlob = util.promisify(glob) | |
const BASE_URL = "localhost:3000" // Change this with ur domain | |
const i18nFolder = "[lang]" | |
const notPages = [`/${i18nFolder}`, "/p"] | |
const extraFilter = (file) => !notPages.includes(file) | |
const directory = path.join(cwd, "src/routes") | |
const unixStyleDirectory = directory.replace(/\\/gi, "/") | |
const getRoutes = async (files) => { | |
console.log('files :>> ', files); | |
// get all the routes in the directory and index files stats (last modified) | |
const mapped = await Promise.all( | |
files.map(async (file) => ({ | |
last_modified: dayjs(await stat(file).mtime).format("YYYY-MM-DD"), | |
filepath: file.replace(unixStyleDirectory, "").replace(/\/index.svelte/gi, ""), | |
})) | |
) | |
// remove every route that has ID in it - those will be rendered after API call | |
const filtered = await Promise.all( | |
mapped.filter( | |
({ filepath }) => filepath.length && !filepath?.includes("id") && extraFilter(filepath) | |
) | |
) | |
// replace [lang] with available languages | |
const reduced = await Promise.all( | |
filtered.reduce((acc = [], current) => { | |
if (current.filepath.includes(i18nFolder)) { | |
const i18nRoutes = supportedLanguages.map((lang) => | |
current.filepath.replace("[lang]", lang) | |
) | |
acc.push( | |
i18nRoutes.map((route) => ({ | |
filepath: route, | |
last_modified: current.last_modified, | |
})) | |
) | |
} else { | |
acc.push(current) | |
} | |
return acc | |
}, []) | |
) | |
/* | |
Output will look something like this: | |
[ | |
[ | |
{ filepath: '/ru/shortcuts', last_modified: '2021-11-20' }, | |
{ filepath: '/en/shortcuts', last_modified: '2021-11-20' }, | |
{ filepath: '/th/shortcuts', last_modified: '2021-11-20' } | |
], | |
{ last_modified: '2021-11-20', filepath: '/changelog' }, | |
{ last_modified: '2021-11-20', filepath: '/privacy' }, | |
] | |
*/ | |
return reduced | |
} | |
const render = (svelteRoutes) => `<?xml version="1.0" encoding="UTF-8" ?> | |
<urlset | |
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" | |
xmlns:xhtml="http://www.w3.org/1999/xhtml" | |
> | |
${svelteRoutes | |
.map((route) => { | |
if (Array.isArray(route)) { | |
return `<url> | |
${route | |
.map((r, i) => { | |
if (i === 0) { | |
return `<loc>${BASE_URL}${r.filepath}</loc>` | |
} else { | |
return `<xhtml:link rel="alternate" hreflang="${ | |
r.filepath.split("/")[1] | |
}" href="${BASE_URL}${r.filepath}"/>` | |
} | |
}) | |
.join("\n")} | |
<lastmod>${route[0].last_modified}</lastmod> | |
</url>` | |
} else { | |
return `<url> | |
<loc> | |
${BASE_URL}${route.filepath} | |
</loc> | |
<lastmod>${route.last_modified}</lastmod> | |
</url>` | |
} | |
}) | |
.join("\n")} | |
</urlset> | |
` | |
export async function get(req, res, next) { | |
const headers = { | |
'Cache-Control': 'max-age=0, s-max-age=3600', | |
"Content-Type": "application/xml", | |
} | |
const files = await asyncGlob(directory + "/**/!(_)*.svelte") | |
const svelteRoutes = await getRoutes(files) | |
const sitemap = await render(svelteRoutes) | |
const response = { | |
headers, | |
body: sitemap, | |
} | |
return response | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment