Add roadmap rendering
This commit is contained in:
@ -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;
|
||||||
|
10
components/md-renderer/mdx-components/code.tsx
Normal file
10
components/md-renderer/mdx-components/code.tsx
Normal file
@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -1,10 +1,7 @@
|
|||||||
The intent of this guide is to give you an idea about the React ecosystem and to help guide your learning if you are confused. We have another [roadmap on the Frontend Development](/frontend) that focuses on the frontend development if you are interested in that.
|
The intent of this guide is to give you an idea about the React ecosystem and to help guide your learning if you are confused. We have another [roadmap on the Frontend Development](/frontend) that focuses on the frontend development if you are interested in that.
|
||||||
|
|
||||||
Also, please note that the list below is exhaustive, and the items are listed in no particular order. You don't need to learn everything listed in the picture, however knowing what you don't know is as important as knowing things.
|
Also, please note that the list below is exhaustive, and the items are listed in no particular order. You don't need to learn everything listed in the picture, however knowing what you don't know is as important as knowing things.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
**→** [All Roadmaps](/roadmaps) • [Programming guides](/guides) • [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
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>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function TextualRoadmap(props: RoadmapProps) {
|
||||||
|
const { roadmap } = props;
|
||||||
|
if (!roadmap.contentPath) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, ol {
|
// Remove trailing slashes
|
||||||
margin: 0 0 20px 40px;
|
const normalizedPath = roadmap.contentPath.replace(/^\//, '');
|
||||||
|
const RoadmapContent = require(`../../content/${normalizedPath}`).default;
|
||||||
|
|
||||||
li + li {
|
return (
|
||||||
margin-top: 7px;
|
<Container maxW={'container.md'} position='relative'>
|
||||||
}
|
<MdRenderer>
|
||||||
}
|
<RoadmapContent />
|
||||||
|
</MdRenderer>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
export default function Roadmap(props: RoadmapProps) {
|
||||||
max-width: 100%;
|
const { roadmap } = props;
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default function Roadmap() {
|
|
||||||
const isImageOnly = true;
|
|
||||||
|
|
||||||
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
|
||||||
|
Reference in New Issue
Block a user