Roadmap to becoming a developer in 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.8 KiB

// This is a development script executed in the build step of pages
const fs = require('fs');
const path = require('path');
const guides = require('../storage/guides');
const roadmaps = require('../storage/roadmaps');
const { getPageRoutes, getGuideRoutes } = require('./path-map');
const DOMAIN = 'https://roadmap.sh';
const PAGES_DIR = path.join(__dirname, '../pages');
const STORAGE_PATH = path.join(__dirname, '../storage');
const SITEMAP_PATH = 'static/sitemap.xml';
const STATIC_PATH = path.join(__dirname, '../static');
// Set the header
const xmlHeader = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">`;
// Wrap all pages in <urlset> tags
const xmlUrlWrapper = nodes => `${xmlHeader}
${nodes}
</urlset>`;
const getSlugPriority = (pageSlug) => {
if (pageSlug === '/') {
return '1.0';
}
const slugPriorities = [
['/roadmaps', '/guides'], // 1.0
['/signup'], // 0.9
['/about'], // 0.8
];
const foundIndex = slugPriorities.findIndex(
routes => routes.some(route => pageSlug.startsWith(route)),
);
if (foundIndex !== -1) {
return parseFloat((10 - foundIndex) / 10)
.toFixed(1);
}
return 0.5;
};
function generateNode({
slug,
basePath,
fileName,
priority = null,
date = null,
frequency = 'monthly',
}) {
const pagePath = path.join(basePath, fileName);
let pageStats = {};
try {
pageStats = fs.lstatSync(pagePath);
} catch (e) {
console.log(`File not found: ${pagePath}`);
pageStats = { mtime: (new Date()) }
}
return `<url>
<loc>${DOMAIN}${slug}</loc>
<changefreq>${ frequency }</changefreq>
<lastmod>${date || pageStats.mtime.toISOString()}</lastmod>
<priority>${ priority || getSlugPriority(slug) }</priority>
</url>`;
}
function generateSiteMap() {
const pageRoutes = getPageRoutes();
const pageSlugs = Object.keys(pageRoutes)
.filter(route => ![
'/privacy',
'/terms',
].includes(route));
const pagesChunk = pageSlugs.map(pageSlug => {
return generateNode({
basePath: PAGES_DIR,
fileName: `${pageRoutes[pageSlug].page}.js`,
slug: pageSlug,
});
});
// Chunks for each of the guides
const guideRoutes = getGuideRoutes();
const guideSlugs = Object.keys(guideRoutes);
const guidesChunk = guideSlugs.map(guideSlug => {
const foundGuide = guides.find(guide => guide.url === guideSlug) || {};
return generateNode({
basePath: STORAGE_PATH,
fileName: `${guideSlug}.md`,
slug: guideSlug,
date: foundGuide.updatedAt,
priority: '1.0',
});
});
// Chunks for each of the roadmaps
const roadmapsChunk = roadmaps.reduce((roadmapsNodes, roadmap) => {
return [
...roadmapsNodes,
generateNode({
basePath: STORAGE_PATH,
fileName: roadmap.path,
slug: roadmap.url,
priority: '1.0',
}),
...Object
.values(roadmap.sidebar || {})
.reduce((pageNodes, menuPages) => {
return [
...pageNodes,
...menuPages.map(menuPage => {
return generateNode({
basePath: STORAGE_PATH,
fileName: menuPage.path,
slug: menuPage.url,
priority: '1.0',
})
})
];
}, [])
]
}, []);
const nodes = [
...roadmapsChunk,
...guidesChunk,
...pagesChunk,
];
const sitemap = `${xmlUrlWrapper(nodes.join('\n'))}`;
fs.writeFileSync(SITEMAP_PATH, sitemap);
console.log(`sitemap.xml with ${nodes.length} entries was written to ${SITEMAP_PATH}`);
}
generateSiteMap();