mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-20 08:02:35 +02:00
Add roadmap rendering
This commit is contained in:
BIN
public/fonts/balsamiq.woff2
Normal file
BIN
public/fonts/balsamiq.woff2
Normal file
Binary file not shown.
@@ -7,9 +7,6 @@ export interface Props {
|
|||||||
|
|
||||||
async function getSVG(name: string) {
|
async function getSVG(name: string) {
|
||||||
const filepath = `/src/icons/${name}.svg`;
|
const filepath = `/src/icons/${name}.svg`;
|
||||||
const iconFiles = await Astro.glob("../icons/**/*.svg");
|
|
||||||
|
|
||||||
console.log(iconFiles[0]);
|
|
||||||
|
|
||||||
const files = import.meta.glob<string>('/src/icons/**/*.svg', {
|
const files = import.meta.glob<string>('/src/icons/**/*.svg', {
|
||||||
eager: true,
|
eager: true,
|
||||||
|
11
src/components/InteractiveRoadmap/InteractiveRoadmap.astro
Normal file
11
src/components/InteractiveRoadmap/InteractiveRoadmap.astro
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
import "./InteractiveRoadmap.css";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
jsonUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { jsonUrl } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<link rel="preload" href="/fonts/balsamiq.woff2" as="font" type="font/woff2" crossorigin slot="after-header" />
|
86
src/components/InteractiveRoadmap/InteractiveRoadmap.css
Normal file
86
src/components/InteractiveRoadmap/InteractiveRoadmap.css
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
svg text tspan {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
text-rendering: optimizeSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
background: #1e1e3f;
|
||||||
|
color: #9efeff;
|
||||||
|
padding: 3px 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(65,53,214)'] {
|
||||||
|
fill: #232381;
|
||||||
|
stroke: #232381;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(255,255,0)'] {
|
||||||
|
fill: #d6d700;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(255,229,153)'] {
|
||||||
|
fill: #f3c950;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(153,153,153)'] {
|
||||||
|
fill: #646464;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(255,255,255)'] {
|
||||||
|
fill: #d7d7d7;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(255,255,221)'] {
|
||||||
|
fill: #e5e5be;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .clickable-group:hover > [fill='rgb(255,217,102)'] {
|
||||||
|
fill: #d9b443;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .done rect {
|
||||||
|
fill: #cbcbcb !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg .done text {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************
|
||||||
|
Aspect ratio implementation
|
||||||
|
*************************************/
|
||||||
|
[style*="--aspect-ratio"] > :first-child {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
[style*="--aspect-ratio"] > img {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (--custom:property) {
|
||||||
|
[style*="--aspect-ratio"] {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
[style*="--aspect-ratio"]::before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
/*noinspection CssUnresolvedCustomProperty*/
|
||||||
|
padding-bottom: calc(100% / (var(--aspect-ratio)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[style*="--aspect-ratio"] > :first-child {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -16,10 +16,14 @@ const { title } = Astro.props;
|
|||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="generator" content={Astro.generator} />
|
<meta name="generator" content={Astro.generator} />
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
|
|
||||||
|
<slot name="after-header" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
|
<slot name="after-footer"/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
<style is:global>
|
<style is:global>
|
38
src/lib/roadmap.ts
Normal file
38
src/lib/roadmap.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
export interface RoadmapFrontmatter {
|
||||||
|
id: string;
|
||||||
|
jsonUrl: string;
|
||||||
|
pdfUrl: string;
|
||||||
|
order: number;
|
||||||
|
featuredTitle: string;
|
||||||
|
featuredDescription: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
hasTopics: boolean;
|
||||||
|
dimensions: {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
seo: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
keywords: string[];
|
||||||
|
};
|
||||||
|
relatedRoadmaps: string[];
|
||||||
|
sitemap: {
|
||||||
|
priority: number;
|
||||||
|
changefreq: string;
|
||||||
|
};
|
||||||
|
tags: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getRoadmapIds() {
|
||||||
|
const roadmapFiles = await import.meta.glob<string>('/src/roadmaps/*/*.md', {
|
||||||
|
eager: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Object.keys(roadmapFiles).map(filePath => {
|
||||||
|
const fileName = filePath.split('/').pop() || '';
|
||||||
|
|
||||||
|
return fileName.replace('.md', '');
|
||||||
|
});
|
||||||
|
}
|
21
src/pages/[roadmapId].astro
Normal file
21
src/pages/[roadmapId].astro
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
import InteractiveRoadamp from "../components/InteractiveRoadmap/InteractiveRoadmap.astro";
|
||||||
|
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||||
|
import { getRoadmapIds, RoadmapFrontmatter } from "../lib/roadmap";
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
const roadmapIds = await getRoadmapIds();
|
||||||
|
|
||||||
|
return roadmapIds.map(roadmapId => ({
|
||||||
|
params: { roadmapId }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { roadmapId } = Astro.params;
|
||||||
|
const file = await import(`../roadmaps/${roadmapId}/${roadmapId}.md`);
|
||||||
|
const frontmatter = file.frontmatter as RoadmapFrontmatter;
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title="">
|
||||||
|
{frontmatter.jsonUrl && <InteractiveRoadamp jsonUrl={frontmatter.jsonUrl} />}
|
||||||
|
</BaseLayout>
|
@@ -1,9 +1,8 @@
|
|||||||
---
|
---
|
||||||
import Layout from "../layouts/Layout.astro";
|
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout title="Developer Roadmaps">
|
<BaseLayout title="Developer Roadmaps">
|
||||||
<div class='bg-gradient-to-b from-slate-900 to-black'>
|
<div class='bg-gradient-to-b from-slate-900 to-black'>
|
||||||
<div class='border-b border-b-slate-900'>
|
<div class='border-b border-b-slate-900'>
|
||||||
<div class='container text-left sm:text-center py-6 sm:py-20 px-6 sm:px-0'>
|
<div class='container text-left sm:text-center py-6 sm:py-20 px-6 sm:px-0'>
|
||||||
@@ -21,4 +20,4 @@ import Layout from "../layouts/Layout.astro";
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</BaseLayout>
|
@@ -1,6 +1,4 @@
|
|||||||
---
|
---
|
||||||
layout: "layouts/svg-roadmap.njk"
|
|
||||||
permalink: "/frontend/"
|
|
||||||
jsonUrl: "/assets/jsons/frontend.json"
|
jsonUrl: "/assets/jsons/frontend.json"
|
||||||
pdfUrl: "/assets/pdfs/frontend.pdf"
|
pdfUrl: "/assets/pdfs/frontend.pdf"
|
||||||
order: 1
|
order: 1
|
||||||
|
Reference in New Issue
Block a user