Last active
November 20, 2021 13:49
-
-
Save multipliedtwice/da72201afa07460095cbbfbdd8fa524b to your computer and use it in GitHub Desktop.
Multilingual Sapper sitemap.xml with day.js
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" | |
const fs = require("fs") | |
const path = require("path") | |
const cwd = process.cwd() | |
const matter = require("gray-matter") | |
const util = require("util") | |
const glob = require("glob") | |
const stat = util.promisify(fs.stat) | |
const BASE_URL = "https://rememo.io" // Change this with ur domain | |
const pages = [""] | |
const POSTS_DIR = path.join(cwd, "src/") | |
let svelteRoutes = [] | |
const i18nFolder = "[lang]" | |
const notPages = [`/${i18nFolder}`, "/p"] // Urls to exclude from sitemap | |
const extraFilter = (file) => !notPages.includes(file) | |
const directory = path.join(cwd, "src/routes") | |
const unixStyleDirectory = directory.replace(/\\/gi, "/") | |
const getRoutes = async (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 | |
} | |
glob(directory + "/**/!(_)*.svelte", {}, async (err, files) => { | |
svelteRoutes = await getRoutes(files) | |
}) | |
const render = (pages, posts) => `<?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 function get(req, res, next) { | |
res.setHeader("Cache-Control", `max-age=0, s-max-age=${600}`) // 10 minutes | |
res.setHeader("Content-Type", "application/xml") | |
const sitemap = render(pages, posts) | |
res.end(sitemap) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment