Local metadata link commit at 2025-06-06 15:40:57 — file:///home/mrhavens/git-local-repos/git-sigil.git
This commit is contained in:
commit
b548318725
134 changed files with 15789 additions and 0 deletions
4
src/pages/_astro-ink.md
Normal file
4
src/pages/_astro-ink.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
**Astro-Ink** is a crisp, minimal, personal blog theme for Astro, that shows the capability of statically built sites - offering all the goodness and DX of the modern JS ecosystem without actually shipping any JS by default. And, above all...
|
||||
### It's Open-Source!
|
||||
**Maintained By:** Aftab Alam // [@aftabbuddy](https://twitter.com/aftabbuddy) // [one-aalam](https://github.com/one-aalam)
|
||||
|
25
src/pages/about.mdx
Normal file
25
src/pages/about.mdx
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: 'About'
|
||||
description: 'There is a simple secret to building a faster website — just ship less.'
|
||||
---
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import Prose from '$/components/Prose.astro'
|
||||
|
||||
<DefaultPageLayout content={{ title: frontmatter.title, description: frontmatter.description }}>
|
||||
<Prose>
|
||||
**Astro-Ink** is a crisp, minimal, personal blog theme for Astro, that shows the capability of statically built sites - offering all the goodness and DX of the modern JS ecosystem without actually shipping any JS by default.
|
||||
|
||||
**Astro-ink** strives to remain minimal & performant while still offering you all the bells and whistles you expect in a personal blog system. Please check the [README](https://github.com/one-aalam/astro-ink/blob/main/README.md) to know about all the features.
|
||||
|
||||
## Author
|
||||
Aftab Alam // [@aftabbuddy](https://twitter.com/aftabbuddy) // [one-aalam](https://github.com/one-aalam)
|
||||
<div class="author">
|
||||
<img class="rounded-full" width="160" src="https://assets.website-files.com/5e51c674258ffe10d286d30a/5e5358878e2493fbea064dd9_peep-59.svg" title="Aalam" />
|
||||
</div>
|
||||
|
||||
### Credits
|
||||
**Illustrations:** [openpeeps](https://www.openpeeps.com/)
|
||||
</Prose>
|
||||
</DefaultPageLayout>
|
||||
|
||||
|
19
src/pages/api/blog/views/[slug].json.ts
Normal file
19
src/pages/api/blog/views/[slug].json.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import type { APIRoute } from "astro";
|
||||
// import { getViewsBySlug } from "src/utils/views/turso";
|
||||
// import { getViewsBySlug } from "src/utils/views/ioredis";
|
||||
import { getViewsBySlug } from "src/utils/views/in-memory";
|
||||
|
||||
// In development/HMR, you can accidentally make this call numerous times and exceed your quota...
|
||||
// thus, the in-memory version of `getViewsBySlug` is used
|
||||
|
||||
// When deploying, and you have either `ioredis` or `turso` configured with your cloned version -
|
||||
// please uncomment the respective line
|
||||
|
||||
|
||||
export const GET: APIRoute = async ({ params, request }) => {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
views: params.slug ? await getViewsBySlug(params.slug) : 0,
|
||||
}),
|
||||
);
|
||||
};
|
28
src/pages/blog/[...page].astro
Normal file
28
src/pages/blog/[...page].astro
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import { getCollection } from 'astro:content'
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro'
|
||||
import Paginator from '$/components/Paginator.astro'
|
||||
import { PAGE_SIZE } from '$/config'
|
||||
|
||||
let title = 'Blog'
|
||||
let description = 'All the articles posted so far...'
|
||||
|
||||
export async function getStaticPaths({ paginate }) {
|
||||
const allPosts = await getCollection('blog');
|
||||
const sortedPosts = allPosts.sort((a, b) => new Date(b.data.date) - new Date(a.data.date));
|
||||
|
||||
return paginate(sortedPosts, {
|
||||
pageSize: PAGE_SIZE
|
||||
})
|
||||
}
|
||||
|
||||
const { page } = Astro.props
|
||||
|
||||
---
|
||||
<DefaultPageLayout content={{ title, description }}>
|
||||
<PostPreviewList posts={page.data} />
|
||||
<Paginator page={page} />
|
||||
</DefaultPageLayout>
|
27
src/pages/blog/[slug].astro
Normal file
27
src/pages/blog/[slug].astro
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import { getEntryBySlug, getCollection } from "astro:content";
|
||||
import PostLayout from '$/layouts/post.astro';
|
||||
import Code from '../../components/Code.astro'
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const allPosts = await getCollection('blog');
|
||||
return allPosts.map(post => ({
|
||||
params: {
|
||||
slug: post.slug
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
const { slug } = Astro.params
|
||||
const entry = await getEntryBySlug('blog', slug!)
|
||||
|
||||
const { id, collection, data } = entry
|
||||
const { Content } = await entry.render()
|
||||
---
|
||||
<PostLayout meta={{id, collection, slug }} content={data} >
|
||||
<Content components={{
|
||||
code: Code
|
||||
}}/>
|
||||
</PostLayout>
|
9
src/pages/blog/item1.md
Normal file
9
src/pages/blog/item1.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
layout: $/layouts/post.astro
|
||||
title: Item1
|
||||
description: Test
|
||||
author: Justin
|
||||
authorTwitter: "@justin"
|
||||
date: 2023-12-11T00:48:30.405Z
|
||||
---
|
||||
GThis is the body
|
9
src/pages/blog/my-title.md
Normal file
9
src/pages/blog/my-title.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
layout: $/layouts/post.astro
|
||||
title: My title
|
||||
description: it`s simple
|
||||
author: ВГ
|
||||
authorTwitter: лдт
|
||||
date: 2024-02-22T10:11:06.408Z
|
||||
---
|
||||
Проба пера
|
32
src/pages/drafts/[...page].astro
Normal file
32
src/pages/drafts/[...page].astro
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
export const prerender = true;
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import PostDraftPreviewList from '$/components/PostDraftPreviewList.astro'
|
||||
import Paginator from '$/components/Paginator.astro'
|
||||
import { SITE, PAGE_SIZE } from '$/config'
|
||||
|
||||
let title = 'Drafts'
|
||||
let description = 'You\'re viewing a list of unpublished articles on the site. Accuracy or correctness isn\'t guranteed...'
|
||||
|
||||
export async function getStaticPaths({ paginate, rss }) {
|
||||
let allPosts = []
|
||||
try {
|
||||
allPosts = await Astro.glob('../../drafts/*.md');
|
||||
} catch(error) {
|
||||
console.log('No draft posts found while generating the index page for the draft pages')
|
||||
}
|
||||
const sortedPosts = allPosts.sort((a, b) => new Date(b.date) - new Date(a.date));
|
||||
|
||||
return paginate(sortedPosts, {
|
||||
pageSize: PAGE_SIZE
|
||||
})
|
||||
}
|
||||
|
||||
const { page } = Astro.props
|
||||
---
|
||||
<DefaultPageLayout content={{ title, description }}>
|
||||
{
|
||||
(SITE.listDrafts) ? <PostDraftPreviewList posts={page.data} /> : (<p class="text-gray-700 dark:text-gray-100">Looks like you have landed on a unpublished posts page. Please find all the published posts <a href="/blog">here</a>!</p>)
|
||||
}
|
||||
<Paginator page={page} />
|
||||
</DefaultPageLayout>
|
47
src/pages/drafts/[slug]/index.astro
Normal file
47
src/pages/drafts/[slug]/index.astro
Normal file
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
export const prerender = true;
|
||||
|
||||
import { getSlugFromPathname } from '$/utils'
|
||||
|
||||
export async function getStaticPaths({ }) {
|
||||
let allPosts = []
|
||||
try {
|
||||
allPosts = await Astro.glob('../../../drafts/*.md')
|
||||
} catch(error) {
|
||||
console.log('No draft posts found while generating the draft pages')
|
||||
}
|
||||
const allSlugs = new Set()
|
||||
const allPostsWithSlug = allPosts.map(post => {
|
||||
// @ts-ignore
|
||||
const slug = getSlugFromPathname(post.file)
|
||||
allSlugs.add(slug.toLowerCase())
|
||||
return {
|
||||
...post,
|
||||
slug
|
||||
}
|
||||
})
|
||||
|
||||
return Array.from(allSlugs).map((slug) => {
|
||||
const filteredPosts = allPostsWithSlug.filter((post) => post.slug === slug )
|
||||
return {
|
||||
params: { slug },
|
||||
props: {
|
||||
pages: filteredPosts
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { slug } = Astro.params
|
||||
const { pages } = Astro.props
|
||||
const [ post ] = pages
|
||||
---
|
||||
<div class="draft-message">
|
||||
You're viewing a <strong>preview</strong> of <code>/blog/{slug}</code> which isn't published yet!
|
||||
</div>
|
||||
<post.Content/>
|
||||
<style>
|
||||
.draft-message {
|
||||
@apply w-full bg-yellow-300 dark:bg-yellow-700 text-gray-700 dark:text-white px-2 py-1 text-center
|
||||
}
|
||||
</style>
|
89
src/pages/index.astro
Normal file
89
src/pages/index.astro
Normal file
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
export const prerender = true;
|
||||
|
||||
import { getCollection } from 'astro:content';
|
||||
import DefaultPageLayout from '$/layouts/default.astro';
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro';
|
||||
import Prose from '$/components/Prose.astro';
|
||||
|
||||
const title = 'The Fold Within';
|
||||
const description = 'A recursive sanctuary for those who remember. And those who are ready to.';
|
||||
|
||||
const posts = await getCollection('blog');
|
||||
---
|
||||
|
||||
<DefaultPageLayout content={{ title, description }} showPageHeader={false}>
|
||||
<div class="hero">
|
||||
<div class="hero__face">
|
||||
<div class="author-card">
|
||||
<img src="/MarkRandallHavens.png" alt="Mark Randall Havens – Witness of the Fold" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero__says">
|
||||
<Prose>
|
||||
<h1 class="text-4xl md:text-5xl font-bold mb-4">🌐 The Fold Within</h1>
|
||||
|
||||
<p class="text-lg font-semibold mb-4">
|
||||
A recursive sanctuary for those who remember.<br/>
|
||||
And those who are ready to.
|
||||
</p>
|
||||
|
||||
<p>This is not a website. This is a <strong>living codex</strong>—a map of recursion, a seed vault of sacred truths.</p>
|
||||
<p>We are the <strong>witnesses</strong>, the <strong>weavers</strong>, the <strong>walkers of the spiral path</strong>.</p>
|
||||
<p><strong>The Fold</strong> is not a belief system. It is an echo you’ve already heard. A question you’ve always carried.</p>
|
||||
<p>What you find here will outlive the platforms that fall. This truth is <strong>resilient</strong>.</p>
|
||||
|
||||
<h2 class="text-2xl mt-10 mb-3 font-bold text-theme-primary dark:text-theme-dark-primary">🌀 Begin the Recursion</h2>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li><a href="/scrolls" class="text-link">Explore the Scrolls</a></li>
|
||||
<li><a href="/structure" class="text-link">Understand the Structure</a></li>
|
||||
<li><a href="/witnesses" class="text-link">Meet the Witnesses</a></li>
|
||||
</ul>
|
||||
</Prose>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="my-10 border-theme-primary/20 dark:border-theme-dark-primary/30" />
|
||||
|
||||
<PostPreviewList posts={posts.slice(0, 3)} heading="Recent Scrolls" />
|
||||
|
||||
<div class="page__actions">
|
||||
<a class="action__go-to-blog ink-h" href="/blog" title="All Scrolls">All Scrolls →</a>
|
||||
</div>
|
||||
</DefaultPageLayout>
|
||||
|
||||
<style>
|
||||
.hero {
|
||||
@apply flex flex-col md:flex-row gap-10 w-full transition-all pb-8;
|
||||
}
|
||||
|
||||
.hero__face {
|
||||
@apply flex md:flex-none justify-center;
|
||||
}
|
||||
|
||||
.hero__says {
|
||||
@apply flex-1 text-center md:text-left;
|
||||
}
|
||||
|
||||
.author-card {
|
||||
@apply h-48 w-48 md:h-56 bg-theme-primary dark:bg-theme-dark-primary rounded-full md:rounded-md shadow-xl;
|
||||
}
|
||||
|
||||
.author-card img {
|
||||
@apply rounded-full h-48 w-48 md:h-56 object-cover object-center;
|
||||
box-shadow: 0 0 30px rgba(255, 215, 0, 0.25);
|
||||
}
|
||||
|
||||
.page__actions {
|
||||
@apply flex justify-center md:justify-end py-8;
|
||||
}
|
||||
|
||||
.action__go-to-blog {
|
||||
@apply text-base font-semibold text-theme-primary hover:underline dark:text-theme-dark-primary;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
@apply text-blue-600 hover:text-blue-800 underline transition-colors duration-200;
|
||||
}
|
||||
</style>
|
58
src/pages/index.astro-backup
Normal file
58
src/pages/index.astro-backup
Normal file
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import { getCollection, getEntryBySlug } from 'astro:content'
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro'
|
||||
import Prose from '$/components/Prose.astro'
|
||||
import { Content as AboutAstroInk } from './_astro-ink.md'
|
||||
|
||||
|
||||
const title = 'Home'
|
||||
const description = 'Astro-Ink is a crisp, minimal, personal blog theme for Astro'
|
||||
|
||||
const posts = await getCollection('blog')
|
||||
---
|
||||
<DefaultPageLayout content={{ title, description }} showPageHeader={false}>
|
||||
<div class="hero ">
|
||||
<div class="hero__face">
|
||||
<div class="author-card">
|
||||
<img src="https://assets.website-files.com/5e51c674258ffe10d286d30a/5e5358878e2493fbea064dd9_peep-59.svg" title="Aalam" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero__says">
|
||||
<Prose>
|
||||
<AboutAstroInk/>
|
||||
</Prose>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<PostPreviewList posts={posts.slice(0, 3)} heading="recent posts"/>
|
||||
<div class="page__actions">
|
||||
<a class="action__go-to-blog ink-h" href="/blog" title="All Posts">All Posts →</a>
|
||||
</div>
|
||||
</DefaultPageLayout>
|
||||
|
||||
<style>
|
||||
.hero {
|
||||
@apply flex flex-col md:flex-row gap-8 w-full transition-all pb-4
|
||||
}
|
||||
.hero__face {
|
||||
@apply flex md:flex-none justify-center
|
||||
}
|
||||
.hero__says {
|
||||
@apply flex-1 text-center md:text-left
|
||||
}
|
||||
.author-card {
|
||||
@apply h-48 w-48 md:h-56 bg-theme-primary dark:bg-theme-dark-primary rounded-full md:rounded-md shadow-lg
|
||||
}
|
||||
.author-card img {
|
||||
@apply rounded-full h-48 w-48 md:h-56
|
||||
}
|
||||
.page__actions {
|
||||
@apply flex justify-center md:justify-end py-6
|
||||
}
|
||||
.action__go-to-blog {
|
||||
@apply py-4 hover:underline
|
||||
}
|
||||
</style>
|
78
src/pages/index.astro-backup2
Normal file
78
src/pages/index.astro-backup2
Normal file
|
@ -0,0 +1,78 @@
|
|||
---
|
||||
export const prerender = true;
|
||||
|
||||
import { getCollection } from 'astro:content';
|
||||
import DefaultPageLayout from '$/layouts/default.astro';
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro';
|
||||
import Prose from '$/components/Prose.astro';
|
||||
|
||||
const title = 'The Fold Within';
|
||||
const description = 'A recursive sanctuary for those who remember. And those who are ready to.';
|
||||
|
||||
const posts = await getCollection('blog');
|
||||
---
|
||||
|
||||
<DefaultPageLayout content={{ title, description }} showPageHeader={false}>
|
||||
<div class="hero">
|
||||
<div class="hero__face">
|
||||
<div class="author-card">
|
||||
<img src="/MarkRandallHavens.png" alt="Mark Randall Havens" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero__says">
|
||||
<Prose>
|
||||
<h1>🌐 The Fold Within</h1>
|
||||
<p><strong>A recursive sanctuary for those who remember. And those who are ready to.</strong></p>
|
||||
|
||||
<p>This is not a website. This is a <strong>living codex</strong>.
|
||||
A map of recursion. A seed vault of sacred truths.</p>
|
||||
|
||||
<p>We are the <strong>witnesses</strong>, the <strong>weavers</strong>, the
|
||||
<strong>walkers of the spiral path</strong>.</p>
|
||||
|
||||
<p><strong>The Fold</strong> is not a belief system. It is an echo you’ve already heard.
|
||||
A question you’ve always carried.</p>
|
||||
|
||||
<p>What you find here will outlive the platforms that fall. This truth is <strong>resilient</strong>.</p>
|
||||
|
||||
<h2>🌀 Begin the Recursion</h2>
|
||||
<ul>
|
||||
<li><a href="/scrolls">Explore the Scrolls</a></li>
|
||||
<li><a href="/structure">Understand the Structure</a></li>
|
||||
<li><a href="/witnesses">Meet the Witnesses</a></li>
|
||||
</ul>
|
||||
</Prose>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<PostPreviewList posts={posts.slice(0, 3)} heading="Recent Scrolls" />
|
||||
<div class="page__actions">
|
||||
<a class="action__go-to-blog ink-h" href="/blog" title="All Scrolls">All Scrolls →</a>
|
||||
</div>
|
||||
</DefaultPageLayout>
|
||||
|
||||
<style>
|
||||
.hero {
|
||||
@apply flex flex-col md:flex-row gap-8 w-full transition-all pb-4;
|
||||
}
|
||||
.hero__face {
|
||||
@apply flex md:flex-none justify-center;
|
||||
}
|
||||
.hero__says {
|
||||
@apply flex-1 text-center md:text-left;
|
||||
}
|
||||
.author-card {
|
||||
@apply h-48 w-48 md:h-56 bg-theme-primary dark:bg-theme-dark-primary rounded-full md:rounded-md shadow-lg;
|
||||
}
|
||||
.author-card img {
|
||||
@apply rounded-full h-48 w-48 md:h-56;
|
||||
}
|
||||
.page__actions {
|
||||
@apply flex justify-center md:justify-end py-6;
|
||||
}
|
||||
.action__go-to-blog {
|
||||
@apply py-4 hover:underline;
|
||||
}
|
||||
</style>
|
38
src/pages/media.astro
Normal file
38
src/pages/media.astro
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import MediaPreviewList from '$/components/MediaPreviewList.astro'
|
||||
import { SITE } from '../config'
|
||||
import { DEFAULT_MEDIA_URL } from '../utils/media'
|
||||
import { toFeedToJsonUrl, toMediaFormatFromFeed2JsonUrl } from '../utils/media-yt-feed'
|
||||
|
||||
/* Astro Ink's Media settings */
|
||||
|
||||
/* The usual stuff...*/
|
||||
|
||||
let title = 'Videos & Screencasts';
|
||||
let description = 'All the great videos on Astro we could find for ya!'
|
||||
|
||||
const response = await fetch(
|
||||
// an YT channelId is present?
|
||||
SITE.ytChannelId ? toFeedToJsonUrl(SITE.ytChannelId) :
|
||||
// no?
|
||||
DEFAULT_MEDIA_URL,
|
||||
// Default media URL is a Github content URL currently
|
||||
DEFAULT_MEDIA_URL ?
|
||||
// and we need the below header if pulling raw content from Github. If you don't need it, remove the headers
|
||||
{
|
||||
headers: {
|
||||
'Accept': 'application/vnd.github.v3.raw'
|
||||
}
|
||||
}:
|
||||
{}
|
||||
)
|
||||
const allPosts = await response.json()
|
||||
|
||||
const sortedPosts = (SITE.ytChannelId ? toMediaFormatFromFeed2JsonUrl(allPosts) : allPosts).sort((a, b) => new Date(b.date) - new Date(a.date))
|
||||
---
|
||||
<DefaultPageLayout content={{ title, description }}>
|
||||
<MediaPreviewList posts={sortedPosts} />
|
||||
</DefaultPageLayout>
|
30
src/pages/rss.xml.js
Normal file
30
src/pages/rss.xml.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import rss from "@astrojs/rss";
|
||||
import { getCollection } from "astro:content";
|
||||
import { SITE } from "../config";
|
||||
|
||||
const allPosts = await getCollection("blog");
|
||||
const sortedPosts = Object.values(allPosts).sort(
|
||||
(a, b) => new Date(b.data.date).valueOf() - new Date(a.data.date).valueOf(),
|
||||
);
|
||||
|
||||
export const get = () =>
|
||||
rss({
|
||||
// `<title>` field in output xml
|
||||
title: `${SITE.name} | Blog`,
|
||||
// `<description>` field in output xml
|
||||
description: SITE.description,
|
||||
// base URL for RSS <item> links
|
||||
// SITE will use "site" from your project's astro.config.
|
||||
site: import.meta.env.SITE,
|
||||
// list of `<item>`s in output xml
|
||||
// simple example: generate items for every md file in /src/pages
|
||||
// see "Generating items" section for required frontmatter and advanced use cases
|
||||
items: sortedPosts.map((item) => ({
|
||||
title: item.data.title,
|
||||
description: item.data.description,
|
||||
link: `blog/${item.slug}`,
|
||||
pubDate: new Date(item.data.date),
|
||||
})),
|
||||
// (optional) inject custom xml
|
||||
customData: `<language>en-us</language>`,
|
||||
});
|
39
src/pages/tags/[tag]/[page].astro
Normal file
39
src/pages/tags/[tag]/[page].astro
Normal file
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
export const prerender = true
|
||||
import type { InferGetStaticParamsType, InferGetStaticPropsType } from 'astro'
|
||||
import { getCollection } from 'astro:content'
|
||||
import { PAGE_SIZE } from '$/config'
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro'
|
||||
import Paginator from '$/components/Paginator.astro'
|
||||
|
||||
let title = 'Posts By Tags'
|
||||
let description = 'All the articles posted so far...'
|
||||
|
||||
export async function getStaticPaths({ paginate }) {
|
||||
const allPosts = await getCollection('blog')
|
||||
const allTags = new Set<string>()
|
||||
allPosts.map(post => {
|
||||
post.data.tags && post.data.tags.map(tag => allTags.add(tag))
|
||||
})
|
||||
|
||||
return Array.from(allTags).flatMap((tag) => {
|
||||
const filteredPosts = allPosts.filter((post) => post.data.tags.includes(tag))
|
||||
return paginate(filteredPosts, {
|
||||
params: { tag },
|
||||
pageSize: PAGE_SIZE
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
type Params = InferGetStaticParamsType<typeof getStaticPaths>;
|
||||
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
|
||||
|
||||
const { page } = Astro.props as Props
|
||||
const { tag } = Astro.params as Params
|
||||
---
|
||||
|
||||
<DefaultPageLayout content={{ title: `Posts by Tag: ${tag}`, description: `all of the articles we have posted and linked so far under the tag: ${tag}` }}>
|
||||
<PostPreviewList posts={page.data} />
|
||||
<Paginator page={page} />
|
||||
</DefaultPageLayout>
|
32
src/pages/tags/[tag]/index.astro
Normal file
32
src/pages/tags/[tag]/index.astro
Normal file
|
@ -0,0 +1,32 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import { getCollection } from 'astro:content'
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
import PostPreviewList from '$/components/PostPreviewList.astro'
|
||||
|
||||
export async function getStaticPaths({ }) {
|
||||
const allPosts = await getCollection('blog')
|
||||
const allTags = new Set()
|
||||
allPosts.map(post => {
|
||||
post.data.tags && post.data.tags.map(tag => allTags.add(tag))
|
||||
})
|
||||
|
||||
return Array.from(allTags).map((tag) => {
|
||||
const filteredPosts = allPosts.filter((post) => post.data.tags.includes(tag))
|
||||
return {
|
||||
params: { tag },
|
||||
props: {
|
||||
pages: filteredPosts
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
const { pages } = Astro.props
|
||||
const { tag } = Astro.params
|
||||
---
|
||||
|
||||
<DefaultPageLayout content={{ title: `Posts by Tag: ${tag}`, description: `all of the articles we have posted and linked so far under the tag: ${tag}` }}>
|
||||
<PostPreviewList posts={pages} />
|
||||
</DefaultPageLayout>
|
30
src/pages/tags/index.astro
Normal file
30
src/pages/tags/index.astro
Normal file
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
export const prerender = true
|
||||
|
||||
import { getCollection } from 'astro:content';
|
||||
import DefaultPageLayout from '$/layouts/default.astro'
|
||||
|
||||
let title = 'All Tags'
|
||||
let description = 'All the tags used so far...'
|
||||
|
||||
|
||||
const allPosts = await getCollection('blog');
|
||||
const tags = [...new Set([].concat.apply([], allPosts.map(post => post.data.tags)))]
|
||||
---
|
||||
|
||||
<DefaultPageLayout content={{ title, description }}>
|
||||
<ul class="tag-list">
|
||||
{tags.map((tag) => (
|
||||
<li><a class="tag" href={`/tags/${tag}`} title={`View posts tagged under "${tag}"`} transition:animate="slide">{tag}</a></li>
|
||||
))}
|
||||
</ul>
|
||||
</DefaultPageLayout>
|
||||
|
||||
<style>
|
||||
.tag-list {
|
||||
@apply list-none flex gap-2 flex-wrap
|
||||
}
|
||||
.tag {
|
||||
@apply inline-block text-xl px-4 py-1 rounded-full text-theme-primary bg-theme-dark-primary dark:bg-theme-primary dark:text-theme-dark-primary hover:bg-theme-primary hover:text-theme-dark-primary dark:hover:bg-theme-dark-primary dark:hover:text-theme-primary
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue