mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-29 20:21:50 +02:00
Guides listing page
This commit is contained in:
40
src/components/GuideListItem.astro
Normal file
40
src/components/GuideListItem.astro
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
import type { GuideFileType } from "../lib/guide";
|
||||
|
||||
export interface Props {
|
||||
guide: GuideFileType;
|
||||
}
|
||||
|
||||
const { guide } = Astro.props;
|
||||
const { frontmatter, id } = guide;
|
||||
---
|
||||
|
||||
<a
|
||||
class:list={[
|
||||
"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b",
|
||||
]}
|
||||
href={`/guides/${id}`}
|
||||
>
|
||||
<span class="group-hover:translate-x-2 transition-transform">
|
||||
{frontmatter.title}
|
||||
|
||||
{
|
||||
frontmatter.isNew && (
|
||||
<span class="bg-green-300 text-green-900 text-xs font-medium px-1.5 py-0.5 rounded-sm uppercase ml-1.5">
|
||||
New
|
||||
<span class="hidden sm:inline">
|
||||
·
|
||||
{new Date(frontmatter.date).toLocaleString("default", {
|
||||
month: "long",
|
||||
})}
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<span class="capitalize text-gray-500 text-xs hidden sm:block">
|
||||
{frontmatter.type}
|
||||
</span>
|
||||
|
||||
<span class="text-gray-400 text-xs block sm:hidden"> »</span>
|
||||
</a>
|
59
src/lib/guide.ts
Normal file
59
src/lib/guide.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import type { MarkdownFileType } from "./file";
|
||||
|
||||
export interface GuideFrontmatter {
|
||||
title: string;
|
||||
description: string;
|
||||
author: {
|
||||
name: string;
|
||||
url: string;
|
||||
imageUrl: string;
|
||||
};
|
||||
seo: {
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
isNew: boolean;
|
||||
type: "visual" | "textual";
|
||||
date: string;
|
||||
sitemap: {
|
||||
priority: number;
|
||||
changefreq: "daily" | "weekly" | "monthly" | "yealry";
|
||||
};
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export type GuideFileType = MarkdownFileType<GuideFrontmatter> & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates id from the given guide file
|
||||
* @param filePath Markdown file path
|
||||
*
|
||||
* @returns unique guide identifier
|
||||
*/
|
||||
function guidePathToId(filePath: string): string {
|
||||
return filePath.replace("/src/guides/", "").replace(".md", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the guides sorted by the publishing date
|
||||
* @returns Promisifed guide files
|
||||
*/
|
||||
export async function getAllGuides(): Promise<GuideFileType[]> {
|
||||
const guides = await import.meta.glob<GuideFileType>("/src/guides/*.md", {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
const guideFiles = Object.values(guides);
|
||||
const enrichedGuides = guideFiles.map((guideFile) => ({
|
||||
...guideFile,
|
||||
id: guidePathToId(guideFile.file),
|
||||
}));
|
||||
|
||||
return enrichedGuides.sort(
|
||||
(a, b) =>
|
||||
new Date(b.frontmatter.date).valueOf() -
|
||||
new Date(a.frontmatter.date).valueOf()
|
||||
);
|
||||
}
|
@@ -1,8 +1,5 @@
|
||||
import type { MarkdownFileType } from "./File";
|
||||
import type { MarkdownFileType } from "./file";
|
||||
|
||||
export type RoadmapFileType = MarkdownFileType<RoadmapFrontmatter> & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export interface RoadmapFrontmatter {
|
||||
jsonUrl: string;
|
||||
@@ -32,6 +29,10 @@ export interface RoadmapFrontmatter {
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
export type RoadmapFileType = MarkdownFileType<RoadmapFrontmatter> & {
|
||||
id: string;
|
||||
};
|
||||
|
||||
function roadmapPathToId(filePath: string):string {
|
||||
const fileName = filePath.split("/").pop() || "";
|
||||
|
||||
@@ -44,7 +45,7 @@ function roadmapPathToId(filePath: string):string {
|
||||
* @returns string[] Array of roadmap IDs
|
||||
*/
|
||||
export async function getRoadmapIds() {
|
||||
const roadmapFiles = await import.meta.glob<string>("/src/roadmaps/*/*.md", {
|
||||
const roadmapFiles = await import.meta.glob<RoadmapFileType>("/src/roadmaps/*/*.md", {
|
||||
eager: true,
|
||||
});
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { MarkdownFileType } from './File';
|
||||
import type { MarkdownFileType } from './file';
|
||||
import type { RoadmapFrontmatter } from './roadmap';
|
||||
|
||||
// Generates URL from the topic file path e.g.
|
||||
|
23
src/pages/guides.astro
Normal file
23
src/pages/guides.astro
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
import GuideListItem from "../components/GuideListItem.astro";
|
||||
import SimplePageHeader from "../components/SimplePageHeader.astro";
|
||||
import BaseLayout from "../layouts/BaseLayout.astro";
|
||||
import { getAllGuides } from "../lib/guide";
|
||||
|
||||
const guides = await getAllGuides();
|
||||
---
|
||||
|
||||
<BaseLayout title="Guides">
|
||||
<SimplePageHeader
|
||||
title="Guides"
|
||||
description="Succinct graphical explanations to engineering topics."
|
||||
/>
|
||||
|
||||
<div class="pb-20 pt-2 bg-gray-50">
|
||||
<div class="container">
|
||||
<div class="mt-3 sm:my-5">
|
||||
{guides.map((guide) => <GuideListItem guide={guide} />)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BaseLayout>
|
Reference in New Issue
Block a user