feat: article tags link to articles with the same tag
This commit is contained in:
parent
1b1bbae3ce
commit
aa26e7cd55
10 changed files with 309 additions and 363 deletions
|
@ -197,9 +197,13 @@ const sortedEducation = [...education].sort((a, b) => a.id - b.id);
|
|||
<h3
|
||||
class="inline-flex items-center justify-center gap-x-1 leading-none font-semibold"
|
||||
>
|
||||
<Link class="hover:underline" href="/projects/camouflage-store"
|
||||
>Camouflage Store</Link
|
||||
<Link
|
||||
href="/projects/camouflage-store"
|
||||
class="text-secondary inline-flex items-center gap-1 hover:underline"
|
||||
>
|
||||
<span class="mr-1 h-1 w-1 rounded-full bg-green-500"></span>
|
||||
Camouflage Store
|
||||
</Link>
|
||||
</h3><div class="text-tertiary text-sm tabular-nums">
|
||||
2020 - Current
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,8 @@ import type { APIRoute } from "astro";
|
|||
const getRobotsTxt = (sitemapURL: URL) => `
|
||||
User-agent: *
|
||||
Disallow: /cv
|
||||
Disallow: /tags
|
||||
Disallow: /tags/*
|
||||
Allow: /
|
||||
|
||||
Sitemap: ${sitemapURL.href}
|
||||
|
|
70
src/pages/tags/[tag].astro
Normal file
70
src/pages/tags/[tag].astro
Normal file
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { SITE } from "@consts";
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import ShowcasePost from "@components/ShowcasePost.astro";
|
||||
import { createSlug } from "@lib/utils";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allBlogPosts = (await getCollection("posts")).filter(
|
||||
(post) => !post.data.draft,
|
||||
);
|
||||
const allProjects = (await getCollection("projects")).filter(
|
||||
(post) => !post.data.draft,
|
||||
);
|
||||
|
||||
const blogTags = allBlogPosts.flatMap((post) => post.data.tags);
|
||||
const projectTags = allProjects.flatMap((project) => project.data.tags);
|
||||
|
||||
const allTags = new Set([...blogTags, ...projectTags]);
|
||||
|
||||
return Array.from(allTags).map((tag) => {
|
||||
const slug = createSlug(tag);
|
||||
return {
|
||||
params: { tag: slug },
|
||||
props: { originalTag: tag },
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { originalTag } = Astro.props;
|
||||
|
||||
const allBlogPosts = await getCollection("posts");
|
||||
const allProjects = await getCollection("projects");
|
||||
|
||||
const blogPostsWithTag = allBlogPosts.filter((post) =>
|
||||
post.data.tags.includes(originalTag),
|
||||
);
|
||||
const projectsWithTag = allProjects.filter((project) =>
|
||||
project.data.tags.includes(originalTag),
|
||||
);
|
||||
|
||||
const allArticlesWithTag = [...blogPostsWithTag, ...projectsWithTag]
|
||||
.filter((post) => !post.data.draft)
|
||||
.sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
|
||||
---
|
||||
|
||||
<Layout title={SITE.TITLE} description={`Articles tagged with ${originalTag}.`}>
|
||||
<h1 class="animate-reveal text-3xl font-semibold break-words opacity-0">
|
||||
<span class="capitalize">{originalTag}</span> is tagged on {
|
||||
allArticlesWithTag.length
|
||||
}
|
||||
{
|
||||
allArticlesWithTag.length > 1 ? (
|
||||
<span>articles</span>
|
||||
) : (
|
||||
<span>article</span>
|
||||
)
|
||||
}
|
||||
</h1>
|
||||
<ul
|
||||
class="animate-reveal grid grid-cols-1 gap-6 opacity-0 [animation-delay:0.1s]"
|
||||
>
|
||||
{allArticlesWithTag.map((article) => <ShowcasePost collection={article} />)}
|
||||
</ul>
|
||||
<a
|
||||
href="/tags"
|
||||
class="animate-reveal w-fit underline opacity-0 [animation-delay:0.2s] hover:no-underline"
|
||||
>See all tags</a
|
||||
>
|
||||
</Layout>
|
50
src/pages/tags/index.astro
Normal file
50
src/pages/tags/index.astro
Normal file
|
@ -0,0 +1,50 @@
|
|||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import { SITE } from "@consts";
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import { createSlug } from "@lib/utils";
|
||||
|
||||
function freqSort(items: Array<string>) {
|
||||
var cnts = items.reduce(function (obj: any, val) {
|
||||
obj[val] = (obj[val] || 0) + 1;
|
||||
return obj;
|
||||
}, {});
|
||||
var sorted = Object.keys(cnts).sort(function (a, b) {
|
||||
return cnts[b] - cnts[a];
|
||||
});
|
||||
return sorted;
|
||||
}
|
||||
|
||||
const allBlogPosts = (await getCollection("posts")).filter(
|
||||
(post) => !post.data.draft,
|
||||
);
|
||||
const allProjects = (await getCollection("projects")).filter(
|
||||
(post) => !post.data.draft,
|
||||
);
|
||||
|
||||
const blogTags = allBlogPosts.flatMap((post) => post.data.tags);
|
||||
const projectTags = allProjects.flatMap((project) => project.data.tags);
|
||||
|
||||
const allTags = blogTags.concat(projectTags);
|
||||
const allTagsSorted = freqSort(allTags);
|
||||
---
|
||||
|
||||
<Layout title={SITE.TITLE} description="All tags found on articles.">
|
||||
<h1 class="animate-reveal text-3xl font-semibold break-words opacity-0">
|
||||
Tags
|
||||
</h1>
|
||||
<ol
|
||||
class="text-tertiary animate-reveal flex flex-wrap items-center gap-2 opacity-0 [animation-delay:0.1s]"
|
||||
>
|
||||
{
|
||||
allTagsSorted.map((tag: any) => (
|
||||
<a
|
||||
href={`/tags/${createSlug(tag)}`}
|
||||
class="underline hover:no-underline"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</ol>
|
||||
</Layout>
|
Loading…
Add table
Add a link
Reference in a new issue