parent
274060a08f
commit
9b74a5fa62
5 changed files with 129 additions and 6 deletions
@ -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> |
@ -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() |
||||
); |
||||
} |
@ -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> |
Loading…
Reference in new issue