106 lines
2.2 KiB
Plaintext
106 lines
2.2 KiB
Plaintext
---
|
|
import { getCollection, type CollectionEntry } from "astro:content";
|
|
import Timestamp from "./Timestamp.astro";
|
|
import { sortBy } from "lodash-es";
|
|
import TagList from "./TagList.astro";
|
|
|
|
interface Props {
|
|
className: string;
|
|
basePath: string;
|
|
drafts?: "exclude" | "include" | "only";
|
|
filteredPosts?: Post[];
|
|
}
|
|
|
|
type Post = CollectionEntry<"posts">;
|
|
const { className, basePath, drafts: includeDrafts, filteredPosts } = Astro.props;
|
|
|
|
type FilterFn = (_: Post) => boolean;
|
|
|
|
function unreachable(): never {
|
|
throw new Error("unreachable");
|
|
}
|
|
|
|
function getFilter(): FilterFn {
|
|
switch (includeDrafts) {
|
|
case "exclude":
|
|
case undefined:
|
|
return (post: Post) => !post.data.draft;
|
|
case "include":
|
|
return (_: Post) => true;
|
|
case "only":
|
|
return (post: Post) => post.data.draft === true;
|
|
}
|
|
return unreachable();
|
|
}
|
|
|
|
const filter = getFilter();
|
|
let allPosts;
|
|
if (filteredPosts) allPosts = filteredPosts.filter(filter);
|
|
else allPosts = await getCollection("posts", filter);
|
|
|
|
const sortedPosts = sortBy(allPosts, (post) => -post.data.date);
|
|
---
|
|
|
|
<table class={`postListing ${className}`}>
|
|
{
|
|
sortedPosts.map((post) => {
|
|
return (
|
|
<>
|
|
<tr class="row">
|
|
<td class="info">
|
|
<span class="spacer" />
|
|
<Timestamp timestamp={post.data.date} />
|
|
</td>
|
|
<td>
|
|
<div class="title">
|
|
<a href={`${basePath}/${post.slug}`} class="brand-colorlink">
|
|
{post.data.title}
|
|
</a>
|
|
</div>
|
|
<TagList tags={post.data.tags} />
|
|
</td>
|
|
</tr>
|
|
</>
|
|
);
|
|
})
|
|
}
|
|
</table>
|
|
|
|
<style lang="scss">
|
|
.postListing {
|
|
width: 100%;
|
|
border-spacing: 6px 10px;
|
|
|
|
td {
|
|
// padding-bottom: 10px;
|
|
// line-height: 1;
|
|
|
|
.title {
|
|
font-size: 12pt;
|
|
}
|
|
|
|
.summary {
|
|
padding-top: 4px;
|
|
font-size: 0.64em;
|
|
color: var(--smaller-text-color);
|
|
|
|
p {
|
|
display: inline;
|
|
}
|
|
}
|
|
}
|
|
|
|
td.info {
|
|
color: var(--smaller-text-color);
|
|
font-size: 0.75em;
|
|
white-space: nowrap;
|
|
text-align: right;
|
|
vertical-align: baseline;
|
|
|
|
.spacer {
|
|
font-size: 12pt;
|
|
}
|
|
}
|
|
}
|
|
</style>
|