Add roadmap rendering

pull/1331/head
Kamran Ahmed 3 years ago
parent 74ef38cdb6
commit 67b8af3f6b
  1. 1
      components/md-renderer/mdx-components/blockquote.tsx
  2. 10
      components/md-renderer/mdx-components/code.tsx
  3. 2
      components/md-renderer/mdx-components/index.tsx
  4. 2
      components/page-header.tsx
  5. 7
      content/roadmaps.json
  6. 3
      content/roadmaps/4-react/landscape.md
  7. 13
      content/roadmaps/7-qa/landscape.md
  8. 8
      lib/roadmap.ts
  9. 5
      package-lock.json
  10. 1
      package.json
  11. 107
      pages/[roadmap]/index.tsx
  12. 1
      pages/_app.tsx
  13. 1
      pages/index.tsx
  14. 1
      scripts/roadmaps-meta.js

@ -5,6 +5,7 @@ const BlockQuote = styled.blockquote`
position: relative; position: relative;
background: #e8e8e8; background: #e8e8e8;
border-radius: 5px; border-radius: 5px;
margin-bottom: 18px;
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin-top: 0; margin-top: 0;

@ -0,0 +1,10 @@
import React from 'react';
import { Code as ChakraCode } from '@chakra-ui/react';
type CodeType = {
children: React.ReactNode;
}
export default function Code(props: CodeType) {
return <ChakraCode bg='blue.500'>{props.children}</ChakraCode>;
}

@ -10,6 +10,7 @@ import { BadgeLink } from './badge-link';
import Ul from './ul'; import Ul from './ul';
import Li from './li'; import Li from './li';
import PremiumBlock from './premium-block'; import PremiumBlock from './premium-block';
import { Code } from '@chakra-ui/react';
const MdxComponents = { const MdxComponents = {
p: P, p: P,
@ -20,6 +21,7 @@ const MdxComponents = {
table: Table, table: Table,
iframe: IFrame, iframe: IFrame,
img: Img, img: Img,
code: Code,
BadgeLink: BadgeLink, BadgeLink: BadgeLink,
PremiumBlock: PremiumBlock, PremiumBlock: PremiumBlock,
ul: Ul, ul: Ul,

@ -16,7 +16,7 @@ export function PageHeader(props: PageHeaderProps) {
<Heading <Heading
as='h1' as='h1'
color='black' color='black'
fontSize={['25px', '25px', '35px']} fontSize={['25px', '25px', '40px']}
fontWeight={700} fontWeight={700}
mb={['2px', '2px', '5px']} mb={['2px', '2px', '5px']}
> >

@ -38,6 +38,7 @@
"featured": true, "featured": true,
"imagePath": "/roadmaps/frontend.png", "imagePath": "/roadmaps/frontend.png",
"resourcesPath": "/roadmaps/1-frontend/resources.md", "resourcesPath": "/roadmaps/1-frontend/resources.md",
"id": "frontend",
"url": "/frontend" "url": "/frontend"
}, },
{ {
@ -79,6 +80,7 @@
"name": "Kamran Ahmed", "name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse" "url": "https://twitter.com/kamranahmedse"
}, },
"id": "backend",
"url": "/backend" "url": "/backend"
}, },
{ {
@ -119,6 +121,7 @@
"name": "Kamran Ahmed", "name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse" "url": "https://twitter.com/kamranahmedse"
}, },
"id": "devops",
"url": "/devops" "url": "/devops"
}, },
{ {
@ -157,6 +160,7 @@
"name": "Kamran Ahmed", "name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse" "url": "https://twitter.com/kamranahmedse"
}, },
"id": "react",
"url": "/react" "url": "/react"
}, },
{ {
@ -199,6 +203,7 @@
"featured": true, "featured": true,
"detailed": false, "detailed": false,
"versions": [], "versions": [],
"id": "postgresql-dba",
"url": "/postgresql-dba" "url": "/postgresql-dba"
}, },
{ {
@ -237,6 +242,7 @@
"name": "Kamran Ahmed", "name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse" "url": "https://twitter.com/kamranahmedse"
}, },
"id": "android",
"url": "/android" "url": "/android"
}, },
{ {
@ -269,6 +275,7 @@
"name": "Anas Fitiani", "name": "Anas Fitiani",
"url": "https://github.com/anas-qa" "url": "https://github.com/anas-qa"
}, },
"id": "qa",
"url": "/qa" "url": "/qa"
} }
] ]

@ -5,6 +5,3 @@ Also, please note that the list below is exhaustive, and the items are listed in
![](/roadmaps/react.png) ![](/roadmaps/react.png)
Please note that the list is opinionated, and you might have different opinions than those of the author. Having said that, [we would love to hear your opinions](https://github.com/kamranahmedse/roadmap.sh/issues/new) and incorporate them in the picture if suitable. Please note that the list is opinionated, and you might have different opinions than those of the author. Having said that, [we would love to hear your opinions](https://github.com/kamranahmedse/roadmap.sh/issues/new) and incorporate them in the picture if suitable.
<!-- @fixme add padding to the container -->
<br /><br /><br />

@ -1,2 +1,11 @@
## QA Roadmap > **Roadmap is not ready yet**. Please check back later or [subscribe to get notified](/signup).
Roadmap to becoming a QA Engineer
While we prepare the roadmap, follow this simple advice to learn anything
> Just **pick a project and start working on it**, you will learn all that you need along the way.
**&rarr;** &nbsp; [All Roadmaps](/roadmaps) &nbsp;&bull;&nbsp; [Programming guides](/guides) &nbsp;&bull;&nbsp; [Subscribe](/signup)

@ -20,14 +20,12 @@ export type RoadmapType = {
contentPath?: string; contentPath?: string;
resourcesPath: string; resourcesPath: string;
isCommunity: boolean; isCommunity: boolean;
id: string;
url: string; url: string;
}; };
export function getRequestedRoadmap(req: NextApiRequest): RoadmapType | undefined { export function getRoadmapById(id: string): RoadmapType | undefined {
// remove trailing slashes return (roadmaps as RoadmapType[]).find(roadmap => roadmap.id === id);
const normalizedUrl = req.url?.replace(/\/$/, '') || '';
return (roadmaps as RoadmapType[]).find(roadmap => normalizedUrl.startsWith(roadmap.url));
} }
export function getAllRoadmaps(): RoadmapType[] { export function getAllRoadmaps(): RoadmapType[] {

5
package-lock.json generated

@ -6100,6 +6100,11 @@
} }
} }
}, },
"prism-themes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/prism-themes/-/prism-themes-1.8.0.tgz",
"integrity": "sha512-pj7A7C9C8juQRFkZHYeApQHdUiak5nkKYlHyWwh7n/b6WjI9KzGtqaGhxUZAIaV1PZ9Z1epJwe41Px3TUGsNJw=="
},
"prismjs": { "prismjs": {
"version": "1.24.1", "version": "1.24.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz",

@ -21,6 +21,7 @@
"date-fns": "^2.23.0", "date-fns": "^2.23.0",
"framer-motion": "^4.1.17", "framer-motion": "^4.1.17",
"next": "^11.1.0", "next": "^11.1.0",
"prism-themes": "^1.8.0",
"react": "17.0.2", "react": "17.0.2",
"react-dom": "17.0.2", "react-dom": "17.0.2",
"styled-components": "^5.3.0" "styled-components": "^5.3.0"

@ -1,50 +1,61 @@
import { Box, Button, Container, SimpleGrid, Stack } from '@chakra-ui/react'; import { Box, Button, Container, Stack } from '@chakra-ui/react';
import { DownloadIcon, EmailIcon } from '@chakra-ui/icons'; import { DownloadIcon, EmailIcon } from '@chakra-ui/icons';
import styled from 'styled-components';
import Image from 'next/image';
import { GlobalHeader } from '../../components/global-header'; import { GlobalHeader } from '../../components/global-header';
import { OpensourceBanner } from '../../components/opensource-banner'; import { OpensourceBanner } from '../../components/opensource-banner';
import { UpdatesBanner } from '../../components/updates-banner'; import { UpdatesBanner } from '../../components/updates-banner';
import { Footer } from '../../components/footer'; import { Footer } from '../../components/footer';
import { PageHeader } from '../../components/page-header'; import { PageHeader } from '../../components/page-header';
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
import MdRenderer from '../../components/md-renderer';
const RoadmapBody = styled.div` type RoadmapProps = {
margin-bottom: 30px; roadmap: RoadmapType;
font-size: 15px; };
h1 { function ImageRoadmap(props: RoadmapProps) {
font-size: 32px; const { roadmap } = props;
font-weight: 700; if (!roadmap.imagePath) {
return null;
} }
p { return (
line-height: 25px; <Container maxW={'900px'} position='relative'>
margin-bottom: 20px <Box mb='30px'>
} <img alt='Frontend Roadmap' src={roadmap.imagePath} />
</Box>
ul, ol { </Container>
margin: 0 0 20px 40px; );
}
li + li { function TextualRoadmap(props: RoadmapProps) {
margin-top: 7px; const { roadmap } = props;
} if (!roadmap.contentPath) {
return null;
} }
img { // Remove trailing slashes
max-width: 100%; const normalizedPath = roadmap.contentPath.replace(/^\//, '');
} const RoadmapContent = require(`../../content/${normalizedPath}`).default;
`;
return (
<Container maxW={'container.md'} position='relative'>
<MdRenderer>
<RoadmapContent />
</MdRenderer>
</Container>
);
}
export default function Roadmap() { export default function Roadmap(props: RoadmapProps) {
const isImageOnly = true; const { roadmap } = props;
return ( return (
<Box bg='white' minH='100vh'> <Box bg='white' minH='100vh'>
<GlobalHeader /> <GlobalHeader />
<Box mb='60px'> <Box mb='60px'>
<PageHeader <PageHeader
title={'Frontend Developer'} title={ roadmap.title }
subtitle={'Step by step guide to becoming a modern frontend developer'} subtitle={ roadmap.description }
> >
<Stack mt='20px' isInline> <Stack mt='20px' isInline>
<Button size='xs' py='14px' px='10px' leftIcon={<DownloadIcon />} colorScheme='yellow' variant='solid'> <Button size='xs' py='14px' px='10px' leftIcon={<DownloadIcon />} colorScheme='yellow' variant='solid'>
@ -55,11 +66,9 @@ export default function Roadmap() {
</Button> </Button>
</Stack> </Stack>
</PageHeader> </PageHeader>
<Container maxW={ isImageOnly ? '900px': 'container.md'} position='relative'>
<RoadmapBody> <ImageRoadmap roadmap={roadmap} />
<img alt='Frontend Roadmap' src='/roadmaps/frontend.png' /> <TextualRoadmap roadmap={roadmap} />
</RoadmapBody>
</Container>
</Box> </Box>
<OpensourceBanner /> <OpensourceBanner />
@ -68,3 +77,37 @@ export default function Roadmap() {
</Box> </Box>
); );
} }
type StaticPathItem = {
params: {
roadmap: string
}
};
export async function getStaticPaths() {
const roadmaps = getAllRoadmaps();
const paramsList: StaticPathItem[] = roadmaps.map(roadmap => ({
params: { 'roadmap': roadmap.id }
}));
return {
paths: paramsList,
fallback: false
};
}
type ContextType = {
params: {
roadmap: string
}
};
export async function getStaticProps(context: ContextType) {
const roadmapId: string = context?.params?.roadmap;
return {
props: {
roadmap: getRoadmapById(roadmapId)
}
};
}

@ -1,6 +1,7 @@
import type { AppProps } from 'next/app'; import type { AppProps } from 'next/app';
import { ChakraProvider } from '@chakra-ui/react'; import { ChakraProvider } from '@chakra-ui/react';
import { roadmapTheme } from './theme'; import { roadmapTheme } from './theme';
import 'prism-themes/themes/prism-shades-of-purple.css';
function MyApp({ Component, pageProps }: AppProps) { function MyApp({ Component, pageProps }: AppProps) {
return ( return (

@ -82,6 +82,7 @@ export default function Home(props: HomeProps) {
{videos.map(video => ( {videos.map(video => (
<LinksListItem <LinksListItem
key={video.url} key={video.url}
badgeText={video.isPro ? 'PRO' : ''}
hideSubtitleOnMobile hideSubtitleOnMobile
title={video.title} title={video.title}
subtitle={video.duration} subtitle={video.duration}

@ -33,6 +33,7 @@ const roadmapsMeta = roadmapDirs.reduce((metaAcc, roadmapDirName) => {
...metaAcc, ...metaAcc,
{ {
...roadmapMeta, ...roadmapMeta,
id: roadmapSlug,
url: `/${roadmapSlug}`, url: `/${roadmapSlug}`,
contentPath: contentPath, contentPath: contentPath,
resourcesPath: resourcesPath resourcesPath: resourcesPath

Loading…
Cancel
Save