developer-roadmap/scripts/editor-roadmap-dirs.ts
Kamran Ahmed 5e50ffbc30
feat: add custom renderer for roadmaps (#5691)
* wip

* fix: update packages

* wip

* wip

* feat: editor content generator

* fix: add dimensions

* feat: add renderer

* feat: add progress modal renderer

* Add API design roadmap

* Update API roadmap rendering

* fix: button click

* fix: link item

* feat: render pdf for editor roadmaps

* Add API roadmap

* Fix broken link of full-stack roadmap

* Update content dir

* Fix typos in api roadmap

* Add assets for pdf and svg

* Add content for api roadmap

* Add todo

* fix: close on editor roadmap select

* Update link not working

* Add api roadmap to get-started and roadmaps page

---------

Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2024-05-17 17:28:24 +01:00

87 lines
2.6 KiB
TypeScript

import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import type { Node } from 'reactflow';
import matter from 'gray-matter';
import type { RoadmapFrontmatter } from '../src/lib/roadmap';
import { slugify } from '../src/lib/slugger';
// ERROR: `__dirname` is not defined in ES module scope
// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');
const roadmapId = process.argv[2];
const allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);
if (!roadmapId) {
console.error('Roadmap Id is required');
process.exit(1);
}
if (!allowedRoadmapIds.includes(roadmapId)) {
console.error(`Invalid roadmap key ${roadmapId}`);
console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);
process.exit(1);
}
const roadmapFrontmatterDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.md`,
);
const roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');
const { data } = matter(roadmapFrontmatterRaw);
const roadmapFrontmatter = data as RoadmapFrontmatter;
if (!roadmapFrontmatter) {
console.error('Invalid roadmap frontmatter');
process.exit(1);
}
if (roadmapFrontmatter.renderer !== 'editor') {
console.error('Only Editor Rendered Roadmaps are allowed');
process.exit(1);
}
const roadmapDir = path.join(
ROADMAP_CONTENT_DIR,
roadmapId,
`${roadmapId}.json`,
);
const roadmapContent = await fs.readFile(roadmapDir, 'utf-8');
let { nodes } = JSON.parse(roadmapContent) as {
nodes: Node[];
};
nodes = nodes.filter(
(node) =>
node?.type && ['topic', 'subtopic'].includes(node.type) && node.data?.label,
);
const roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');
const stats = await fs.stat(roadmapContentDir).catch(() => null);
if (!stats || !stats.isDirectory()) {
await fs.mkdir(roadmapContentDir, { recursive: true });
}
const roadmapContentFiles = await fs.readdir(roadmapContentDir, {
recursive: true,
});
nodes.forEach(async (node, index) => {
const nodeDirPattern = `${slugify(node.data.label)}@${node.id}.md`;
if (roadmapContentFiles.includes(nodeDirPattern)) {
console.log(`Skipping ${nodeDirPattern}`);
return;
}
await fs.writeFile(
path.join(roadmapContentDir, nodeDirPattern),
`# ${node.data.label}`,
);
});