Remove everything

This commit is contained in:
Kamran Ahmed committed 2023-01-05 20:01:04 +04:00
1 parent 631baffb17
commit 3f027cbebb
2536 files changed
-273160

No files matched your search

-9
View File
@@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -e
rm -rf out
next build
next export
echo 'roadmap.sh' > out/CNAME
touch out/.nojekyll
-255
View File
@@ -1,255 +0,0 @@
import fs from 'fs';
import path from 'path';
const CONTENT_DIR = path.join(__dirname, '../content');
// Directory containing the roadmaps
const ROADMAP_CONTENT_DIR = path.join(__dirname, '../content/roadmaps');
const roadmapKey = process.argv[2];
type ControlType = {
ID: string;
typeID: string;
zOrder: string;
w: string;
h: string;
measuredW: string;
measuredH: string;
x: string;
y: string;
properties: {
controlName: string;
};
children: {
controls: {
control: ControlType[];
};
};
};
type RoadmapType = {
mockup: {
controls: {
control: ControlType[];
};
};
};
const roadmaps: Record<string, RoadmapType> = {
frontend: require('../public/project/frontend.json'),
backend: require('../public/project/backend.json'),
devops: require('../public/project/devops.json'),
android: require('../public/project/android.json'),
golang: require('../public/project/golang.json'),
java: require('../public/project/java.json'),
python: require('../public/project/python.json'),
react: require('../public/project/react.json'),
vue: require('../public/project/vue.json'),
angular: require('../public/project/angular.json'),
blockchain: require('../public/project/blockchain.json'),
javascript: require('../public/project/javascript.json'),
nodejs: require('../public/project/nodejs.json'),
qa: require('../public/project/qa.json'),
'design-system': require('../public/project/design-system.json'),
'software-architect': require('../public/project/software-architect.json'),
'aspnet-core': require('../public/project/aspnet-core.json'),
'flutter': require('../public/project/flutter.json'),
'computer-science': require('../public/project/computer-science.json'),
'graphql': require('../public/project/graphql.json'),
};
if (!roadmapKey || !roadmaps[roadmapKey]) {
console.error(`Invalid roadmap key ${roadmapKey}`);
console.error(`Allowed keys are ${Object.keys(roadmaps).join(', ')}`);
process.exit(1);
}
// Directory holding the roadmap content files
const roadmapDirName = fs
.readdirSync(ROADMAP_CONTENT_DIR)
.find((dirName: string) => dirName.replace(/\d+-/, '') === roadmapKey);
if (!roadmapDirName) {
console.error('Roadmap directory not found');
process.exit(1);
}
const roadmapDirPath = path.join(ROADMAP_CONTENT_DIR, roadmapDirName);
const roadmapContentDirPath = path.join(
ROADMAP_CONTENT_DIR,
roadmapDirName,
'content'
);
// If roadmap content already exists do not proceed as it would override the files
if (fs.existsSync(roadmapContentDirPath)) {
console.error(`Roadmap content already exists @ ${roadmapContentDirPath}`);
process.exit(1);
}
// Type representing the nested dir tree
// {
// frontend: {
// internet: {
// dns-how-does-it-work: {}
// what-is-domain-name: {}
// },
// html: {},
// css: {
// making-layouts: {}
// },
// }
// }
type DirTreeType = {
[dirName: string]: DirTreeType;
};
// Hashmap containing the dir key to sort order mapping
// {
// "frontend": 100,
// "frontend:internet": 200,
// "frontend:internet:dns-how-does-it-work": 100
// }
type DirSortOrdersType = Record<string, number>;
function prepareDirTree(
control: ControlType,
dirTree: DirTreeType,
dirSortOrders: DirSortOrdersType
) {
// Directories are only created for groups
if (control.typeID !== '__group__') {
return;
}
// e.g. 104-testing-your-apps:other-options
const controlName = control?.properties?.controlName || '';
// e.g. 104
const sortOrder = controlName.match(/^\d+/)?.[0];
// No directory for a group without control name
if (!controlName || !sortOrder) {
return;
}
// e.g. testing-your-apps:other-options
const controlNameWithoutSortOrder = controlName.replace(/^\d+-/, '');
// e.g. ['testing-your-apps', 'other-options']
const dirParts = controlNameWithoutSortOrder.split(':');
// Nest the dir path in the dirTree
let currDirTree = dirTree;
dirParts.forEach((dirPart) => {
currDirTree[dirPart] = currDirTree[dirPart] || {};
currDirTree = currDirTree[dirPart];
});
dirSortOrders[controlNameWithoutSortOrder] = Number(sortOrder);
const childrenControls = control.children.controls.control;
// No more children
if (childrenControls.length) {
childrenControls.forEach((childControl) => {
prepareDirTree(childControl, dirTree, dirSortOrders);
});
}
return { dirTree, dirSortOrders };
}
const roadmap = roadmaps[roadmapKey];
const controls = roadmap.mockup.controls.control;
// Prepare the dir tree that we will be creating and also calculate the sort orders
const dirTree: DirTreeType = {};
const dirSortOrders: DirSortOrdersType = {};
controls.forEach((control) => {
prepareDirTree(control, dirTree, dirSortOrders);
});
/**
* @param parentDir Parent directory in which directory is to be created
* @param dirTree Nested dir tree to be created
* @param sortOrders Mapping from groupName to sort order
* @param filePaths The mapping from groupName to file path
*/
function createDirTree(
parentDir: string,
dirTree: DirTreeType,
sortOrders: DirSortOrdersType,
filePaths: Record<string, string> = {}
) {
const childrenDirNames = Object.keys(dirTree);
const hasChildren = childrenDirNames.length !== 0;
// @todo write test for this, yolo for now
const groupName = parentDir
.replace(roadmapContentDirPath, '') // Remove base dir path
.replace(/(^\/)|(\/$)/g, '') // Remove trailing slashes
.replace(/(^\d+?-)/g, '') // Remove sorting information
.replaceAll('/', ':') // Replace slashes with `:`
.replace(/:\d+-/, ':');
const humanizedGroupName = groupName
.split(':')
.pop()
?.replaceAll('-', ' ')
.replace(/^\w/, ($0) => $0.toUpperCase());
const sortOrder = sortOrders[groupName] || '';
// Attach sorting information to dirname
// e.g. /roadmaps/100-frontend/content/internet
// ———> /roadmaps/100-frontend/content/103-internet
if (sortOrder) {
parentDir = parentDir.replace(/(.+?)([^\/]+)?$/, `$1${sortOrder}-$2`);
}
// If no children, create a file for this under the parent directory
if (!hasChildren) {
let fileName = `${parentDir}.md`;
fs.writeFileSync(fileName, `# ${humanizedGroupName}`);
filePaths[groupName || 'home'] = fileName.replace(CONTENT_DIR, '');
return filePaths;
}
// There *are* children, so create the parent as a directory
// and create `readme.md` as the content file for this
fs.mkdirSync(parentDir);
let readmeFilePath = path.join(parentDir, 'readme.md');
fs.writeFileSync(readmeFilePath, `# ${humanizedGroupName}`);
filePaths[groupName || 'home'] = readmeFilePath.replace(CONTENT_DIR, '');
// For each of the directory names, create a
// directory inside the given directory
childrenDirNames.forEach((dirName) => {
createDirTree(
path.join(parentDir, dirName),
dirTree[dirName],
dirSortOrders,
filePaths
);
});
return filePaths;
}
// Create directories and get back the paths for created directories
const filePaths = createDirTree(roadmapContentDirPath, dirTree, dirSortOrders);
const contentPathsFilePath = path.join(roadmapDirPath, 'content-paths.json');
fs.writeFileSync(contentPathsFilePath, JSON.stringify(filePaths, null, 2));
const roadmapMetaFilePath = path.join(roadmapDirPath, 'meta.json');
const roadmapMeta = require(roadmapMetaFilePath);
// Put the content paths file path in the roadmap meta
roadmapMeta.contentPathsFilePath = contentPathsFilePath.replace(
roadmapDirPath,
'.'
);
fs.writeFileSync(roadmapMetaFilePath, JSON.stringify(roadmapMeta, null, 2));
-30
View File
@@ -1,30 +0,0 @@
#!/bin/sh
# Checking a pr using hub
set -e
require() {
if [[ -z $(command -v "$1" 2>/dev/null) ]]; then
echo " 🛑 Please install $1 and try again"
exit 1
fi
}
require jq
require gh
require fzf
# get the list of open pull requests
prs=$(gh pr list --json number,title --limit 100 | jq -r '.[] | "\(.number) \(.title)"')
# select a pr
pr=$(echo "$prs" | fzf --prompt="Select a PR: " --height=50% --reverse --preview="gh pr view {1} --json 'files' | jq -r '.files|map(.path)|.[]'")
# get the pr number
pr_number=$(echo "$pr" | awk '{print $1}')
[ -z "$pr_number" ] && echo "🛑 No PR selected" && exit 1
echo "Checkout PR: $pr_number"
gh pr checkout "$pr_number"
-39
View File
@@ -1,39 +0,0 @@
## Scripts
Here is the list of scripts available:
- [Sitemap](#sitemap)
- [Roadmaps Meta](#roadmaps-meta)
- [Content Skeleton](#content-skeleton)
## Sitemap
The below mentioned command generates the sitemap with all the pages and guides
```shell
npm run meta:sitemap
```
## Roadmaps Meta
The below mentioned command generates the `content/roadmaps.json` file by combining the `content/raodmaps/**/meta.json` content in each roadmap
```shell
npm run meta:roadmaps
```
## Content Skeleton
This command is used to create the content folders and files for the interactivity of the roadmap. You can use the below command to generate the roadmap skeletons inside a roadmap directory:
```shell
npm run roadmap-content [frontend|backend|devops|...]
```
For the content skeleton to be generated, we should have proper grouping, and the group names in the project files. You can follow the steps listed below in order to add the meta information to the roadmap.
* Remove all the groups from the roadmaps through the project editor. Select all and press <kbd>cmd</kbd>+<kbd>shift</kbd>+<kbd>g</kbd>
* Identify the boxes that should be clickable and group them together with <kbd>cmd</kbd>+<kbd>shift</kbd>+<kbd>g</kbd>
* Assign the name to the groups.
* Group names have the format of `[sort]-[slug]` e.g. `100-internet`. Each group name should start with a number starting from `100` which helps with sorting of the directories and the files. Groups at the same level have the sequential sorting information.
* Each groups children have a separate group and have the name similar to `[sort]-[parent-slug]:[child-slug]` where `sort` refers to the sorting of the `child-slug` and not the parent. Also `parent-slug` does not need to have the sorting information as a part of slug e.g. if parent was `100-internet` the children would be `100-internet:how-does-the-internet-work`, `101-internet:what-is-http`, `102-internet:browsers`.
-58
View File
@@ -1,58 +0,0 @@
const fs = require('fs');
const path = require('path');
const STORAGE_PATH = path.join(__dirname, '../content');
const ROADMAPS_PATH = path.join(__dirname, '../content/roadmaps');
const META_FILE_PATH = path.join(__dirname, '../content/roadmaps.json');
const roadmapDirs = fs.readdirSync(ROADMAPS_PATH);
console.log(`[x] ${roadmapDirs.length} roadmaps found`);
const roadmapsMeta = roadmapDirs.reduce((metaAcc, roadmapDirName) => {
const roadmapSlug = roadmapDirName.replace(/^\d+-/, '');
const roadmapDir = path.join(ROADMAPS_PATH, roadmapDirName);
const roadmapMeta = require(path.join(roadmapDir, 'meta.json'));
// We can't use the absolute path in the build e.g. ~/Users/user/where-build-is-running/content
// So, we remove it and use the path relative to content directory
let landingPath = roadmapMeta.landingPath;
if (landingPath) {
landingPath = path.join(roadmapDir.replace(STORAGE_PATH, ''), landingPath);
}
let resourcesPath = roadmapMeta.resourcesPath;
if (resourcesPath) {
resourcesPath = path.join(roadmapDir.replace(STORAGE_PATH, ''), resourcesPath);
}
let contentPathsFilePath = roadmapMeta.contentPathsFilePath;
if (contentPathsFilePath) {
contentPathsFilePath = path.join(roadmapDir.replace(STORAGE_PATH, ''), contentPathsFilePath);
}
let metaPath = path.join(roadmapDir.replace(STORAGE_PATH, ''), 'meta.json');
console.log(`----------------------------`);
console.log(`[#] Roadmap: ${roadmapMeta.title}`);
console.log(`[x] Generating sidebar`);
return [
...metaAcc,
{
...roadmapMeta,
id: roadmapSlug,
landingPath: landingPath,
resourcesPath: resourcesPath,
contentPathsFilePath: contentPathsFilePath,
metaPath: metaPath,
isUpcoming: roadmapMeta.isUpcoming || false
}
];
}, []);
console.log(`----------------------------`);
console.log(`[x] Meta generated for ${roadmapsMeta.length} roadmaps`);
console.log(`[x] Writing file ${META_FILE_PATH}`);
fs.writeFileSync(META_FILE_PATH, JSON.stringify(roadmapsMeta, null, 2));
console.log(`[x] Wrote file with content`);
console.log(JSON.stringify(roadmapsMeta, null, 2));
-144
View File
@@ -1,144 +0,0 @@
// This is a development script executed in the build step of pages
const fs = require('fs');
const path = require('path');
const glob = require('glob');
const guides = require('../content/guides.json');
const roadmaps = require('../content/roadmaps.json');
const DOMAIN = 'https://roadmap.sh';
const PAGES_DIR = path.join(__dirname, '../pages');
const SITEMAP_PATH = path.join(__dirname, '../public/sitemap.xml');
const PAGES_PATH = path.join(__dirname, '../pages');
const ROADMAPS_PATH = path.join(__dirname, '../content/roadmaps');
const GUIDES_PATH = path.join(__dirname, '../content/guides');
// 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>`;
function getSlugPriority(pageSlug) {
if (pageSlug === '/') {
return '1.0';
}
const slugPriorities = [
['/roadmaps', '/guides', '/watch', '/podcasts'], // 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 getPageRoutes() {
const files = glob.sync(`${PAGES_PATH}/**/*.tsx`, {
ignore: [
'**/_*.tsx', // private non-page files e.g. _document.js
'**/[[]*[]].tsx', // Ignore dynamic pages i.e. `page/[something].js` files
'**/[[]*[]]/*.tsx', // Ignore files inside dynamic pages i.e. `[something]/abc.js`
'**/components/*.tsx', // Ignore the component files
],
});
const pageRoutes = {};
files.forEach((file) => {
const pageName = file.replace(PAGES_PATH, '').replace('.tsx', '');
const pagePath = pageName.replace('/index', '') || '/';
pageRoutes[pagePath] = { page: `${pageName}` };
});
return pageRoutes;
}
function generateNode(nodeProps) {
const {
slug,
basePath,
fileName,
priority = null,
date = null,
frequency = 'monthly',
} = nodeProps;
if (slug.includes('upcoming') || slug.includes('pdfs')) {
return null;
}
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}.tsx`,
slug: pageSlug,
});
});
const guidesChunk = guides.map((guide) => {
return generateNode({
basePath: GUIDES_PATH,
fileName: `${guide.id}.md`,
slug: `/guides/${guide.id}`,
date: guide.updatedAt,
priority: '1.0',
});
});
const roadmapsChunk = roadmaps.map((roadmap, roadmapCounter) => {
return generateNode({
basePath: ROADMAPS_PATH,
fileName: roadmap.metaPath.replace('/roadmaps', ''),
slug: `/${roadmap.id}`,
date: roadmap.updatedAt,
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();