Remove everything
This commit is contained in:
1 parent
631baffb17
commit
3f027cbebb
2536 files changed
-273160
No files matched your search
@@ -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
|
||||
@@ -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));
|
||||
@@ -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"
|
||||
@@ -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`.
|
||||
@@ -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));
|
||||
@@ -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();
|
||||
Reference in new issue
Block a user