-
Notifications
You must be signed in to change notification settings - Fork 4
/
[slug].astro
110 lines (91 loc) · 3.34 KB
/
[slug].astro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
---
// The articles (from the "blog" collection) rendered
import Default from "../../components/Default.astro";
import type { Tag } from "../../content/config";
import { entries, entryName, entryPath } from "../../blog";
import { topics } from "../../content/config";
// Generate a new path for each article
export async function getStaticPaths() {
const blogEntries = await entries();
return blogEntries.map((entry) => {
return {
params: { slug: entryName(entry) },
props: { entry },
};
});
}
const { entry } = Astro.props;
const { Content } = await entry.render();
// Returns the date as "January 9, 2012", to be shown in articles
const prettyDate = (d: Date) => {
return d.toLocaleString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
};
const tags: Tag[] = entry.data.tags?.slice(0, 2) ?? [];
// Some machinery to suggest similar articles (by topics)
const suggestedTopics = tags?.map((tag) => topics[tag]).join(" and ");
const allEntries = await entries();
const similarEntries = allEntries.filter(
(e) =>
e.data.pubDate.getTime() < entry.data.pubDate.getTime() &&
tags.some((t) => e.data.tags?.includes(t))
);
const suggestedEntries = similarEntries.slice(0, 2);
---
<Default
title={entry.data.title}
description={entry.data.description}
ogType="article"
og_image={entry.data.og_image}
>
<h1>{entry.data.title}</h1>
<h4>{prettyDate(entry.data.pubDate)}</h4>
<hr />
{
entry.data.og_image ? (
<img
src={entry.data.og_image}
style="margin: auto; display: block; max-height: 630px;"
/>
) : undefined
}
<Content />
<hr style="margin: 5em auto;" />
{
suggestedTopics?.length > 0 && suggestedEntries.length > 0 ? (
<>
<p>Like {suggestedTopics}? Here's more on the topic:</p>
<ul>
{suggestedEntries.map((e) => (
<li>
<a href={entryPath(e)}> {e.data.title}</a>
</li>
))}
</ul>
</>
) : undefined
}
<script>
// Some code for adding a "copy to clipboard" icon to code blocks.
const clipboardIcon = `<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" > <path fill-rule="evenodd" d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"></path><path fill-rule="evenodd" d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0114.25 11h-7.5A1.75 1.75 0 015 9.25v-7.5zm1.75-.25a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-7.5a.25.25 0 00-.25-.25h-7.5z"></path> </svg>`;
// First load all the "pre" elements
const pres = document.querySelectorAll("pre.astro-code");
// For each, look at the "code" element inside, and add an the button/icon as a sibling
pres.forEach((pre) => {
const code = pre.querySelector("code");
if (code) {
const copy = document.createElement("div");
copy.addEventListener("click", async () => {
await navigator.clipboard.writeText(code.innerText);
});
copy.setAttribute("aria-label", "Copy");
copy.innerHTML = clipboardIcon;
copy.classList.add("clipboard-copy");
pre.appendChild(copy);
}
});
</script>
</Default>