mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-08 00:00:42 +02:00
Roadmap filtering by tags
This commit is contained in:
26
src/components/SimplePageHeader.astro
Normal file
26
src/components/SimplePageHeader.astro
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
import YouTubeAlert from './YouTubeAlert.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
showYouTubeAlert?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, description, showYouTubeAlert = false } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="bg-white border-b pt-6 pb-5 sm:pt-12 sm:pb-10">
|
||||||
|
<div class="container">
|
||||||
|
{
|
||||||
|
showYouTubeAlert && (
|
||||||
|
<div class="mb-4 hidden sm:block">
|
||||||
|
<YouTubeAlert />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1 class="text-3xl sm:text-5xl mb-1 sm:mb-2 font-bold">{title}</h1>
|
||||||
|
<p class="text-gray-500 text-sm sm:text-lg">{description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
11
src/lib/File.ts
Normal file
11
src/lib/File.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
export interface MarkdownFileType<T = Record<string, string>> {
|
||||||
|
frontmatter: T;
|
||||||
|
file: string;
|
||||||
|
url: string;
|
||||||
|
Content: any;
|
||||||
|
getHeadings: () => {
|
||||||
|
depth: number;
|
||||||
|
slug: string;
|
||||||
|
text: string;
|
||||||
|
}[];
|
||||||
|
}
|
@@ -1,3 +1,7 @@
|
|||||||
|
import type { MarkdownFileType } from "./File";
|
||||||
|
|
||||||
|
type RoadmapFileType = MarkdownFileType<RoadmapFrontmatter>;
|
||||||
|
|
||||||
export interface RoadmapFrontmatter {
|
export interface RoadmapFrontmatter {
|
||||||
id: string;
|
id: string;
|
||||||
jsonUrl: string;
|
jsonUrl: string;
|
||||||
@@ -25,6 +29,11 @@ export interface RoadmapFrontmatter {
|
|||||||
tags: string[];
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the IDs of all the roadmaps available on the website
|
||||||
|
*
|
||||||
|
* @returns string[] Array of roadmap IDs
|
||||||
|
*/
|
||||||
export async function getRoadmapIds() {
|
export async function getRoadmapIds() {
|
||||||
const roadmapFiles = await import.meta.glob<string>("/src/roadmaps/*/*.md", {
|
const roadmapFiles = await import.meta.glob<string>("/src/roadmaps/*/*.md", {
|
||||||
eager: true,
|
eager: true,
|
||||||
@@ -36,3 +45,23 @@ export async function getRoadmapIds() {
|
|||||||
return fileName.replace(".md", "");
|
return fileName.replace(".md", "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the roadmap files which have the given tag assigned
|
||||||
|
*
|
||||||
|
* @param tag Tag assigned to roadmap
|
||||||
|
* @returns Promisified RoadmapFileType[]
|
||||||
|
*/
|
||||||
|
export async function getRoadmapsByTag(tag: string): Promise<RoadmapFileType[]> {
|
||||||
|
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
|
||||||
|
'/src/roadmaps/*/*.md',
|
||||||
|
{
|
||||||
|
eager: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const roadmapFiles: MarkdownFileType<RoadmapFrontmatter>[] = Object.values(roadmapFilesMap);
|
||||||
|
const filteredRoadmaps = roadmapFiles.filter(roadmapFile => roadmapFile.frontmatter.tags.includes(tag));
|
||||||
|
|
||||||
|
return filteredRoadmaps;
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { joinPath } from './path';
|
import type { MarkdownFileType } from './File';
|
||||||
import type { RoadmapFrontmatter } from './roadmap';
|
import type { RoadmapFrontmatter } from './roadmap';
|
||||||
|
|
||||||
// Generates URL from the topic file path e.g.
|
// Generates URL from the topic file path e.g.
|
||||||
@@ -64,24 +64,10 @@ export type BreadcrumbItem = {
|
|||||||
url: string;
|
url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FileHeadingType = {
|
|
||||||
depth: number;
|
|
||||||
slug: string;
|
|
||||||
text: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface TopicFileContentType {
|
|
||||||
frontMatter: Record<string, string>;
|
|
||||||
file: string;
|
|
||||||
url: string;
|
|
||||||
Content: any;
|
|
||||||
getHeadings: () => FileHeadingType[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TopicFileType {
|
export interface TopicFileType {
|
||||||
url: string;
|
url: string;
|
||||||
text: string;
|
text: string;
|
||||||
file: TopicFileContentType;
|
file: MarkdownFileType;
|
||||||
roadmap: RoadmapFrontmatter;
|
roadmap: RoadmapFrontmatter;
|
||||||
roadmapId: string;
|
roadmapId: string;
|
||||||
breadcrumbs: BreadcrumbItem[];
|
breadcrumbs: BreadcrumbItem[];
|
||||||
@@ -102,7 +88,7 @@ export async function getTopicFiles(): Promise<Record<string, TopicFileType>> {
|
|||||||
const mapping: Record<string, TopicFileType> = {};
|
const mapping: Record<string, TopicFileType> = {};
|
||||||
|
|
||||||
for (let filePath of Object.keys(contentFiles)) {
|
for (let filePath of Object.keys(contentFiles)) {
|
||||||
const fileContent: TopicFileContentType = contentFiles[filePath] as any;
|
const fileContent: MarkdownFileType = contentFiles[filePath] as any;
|
||||||
const fileHeadings = fileContent.getHeadings();
|
const fileHeadings = fileContent.getHeadings();
|
||||||
const firstHeading = fileHeadings[0];
|
const firstHeading = fileHeadings[0];
|
||||||
|
|
||||||
|
25
src/pages/roadmaps.astro
Normal file
25
src/pages/roadmaps.astro
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
import SimplePageHeader from '../components/SimplePageHeader.astro';
|
||||||
|
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||||
|
import { getRoadmapsByTag } from '../lib/roadmap';
|
||||||
|
|
||||||
|
const roleRoadmaps = await getRoadmapsByTag('role-roadmap');
|
||||||
|
const skillRoadmaps = await getRoadmapsByTag('skill-roadmap');
|
||||||
|
---
|
||||||
|
|
||||||
|
<BaseLayout title="Roadmap">
|
||||||
|
<SimplePageHeader
|
||||||
|
title="Developer Roadmaps"
|
||||||
|
description="Step by step guides and paths to learn different tools or technologies"
|
||||||
|
showYouTubeAlert={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="bg-gray-100 pt-4 pb-14 sm:pt-8 sm:pb-16">
|
||||||
|
<div class="container">
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-0.5 sm:gap-3">
|
||||||
|
<h1>{ roleRoadmaps.length }</h1>
|
||||||
|
<h1>{ skillRoadmaps.length }</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</BaseLayout>
|
Reference in New Issue
Block a user