feat: initial commit

This commit is contained in:
2023-09-02 22:58:42 +02:00
commit bb0950208e
70 changed files with 22649 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
import satori, { SatoriOptions } from "satori";
import { SITE } from "@config";
import { writeFile } from "node:fs/promises";
import { Resvg } from "@resvg/resvg-js";
const fetchFonts = async () => {
// Regular Font
const fontFileRegular = await fetch(
"https://www.1001fonts.com/download/font/ibm-plex-mono.regular.ttf"
);
const fontRegular: ArrayBuffer = await fontFileRegular.arrayBuffer();
// Bold Font
const fontFileBold = await fetch(
"https://www.1001fonts.com/download/font/ibm-plex-mono.bold.ttf"
);
const fontBold: ArrayBuffer = await fontFileBold.arrayBuffer();
return { fontRegular, fontBold };
};
const { fontRegular, fontBold } = await fetchFonts();
const ogImage = (text: string) => {
return (
<div
style={{
background: "#fefbfb",
width: "100%",
height: "100%",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<div
style={{
position: "absolute",
top: "-1px",
right: "-1px",
border: "4px solid #000",
background: "#ecebeb",
opacity: "0.9",
borderRadius: "4px",
display: "flex",
justifyContent: "center",
margin: "2.5rem",
width: "88%",
height: "80%",
}}
/>
<div
style={{
border: "4px solid #000",
background: "#fefbfb",
borderRadius: "4px",
display: "flex",
justifyContent: "center",
margin: "2rem",
width: "88%",
height: "80%",
}}
>
<div
style={{
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
margin: "20px",
width: "90%",
height: "90%",
}}
>
<p
style={{
fontSize: 72,
fontWeight: "bold",
maxHeight: "84%",
overflow: "hidden",
}}
>
{text}
</p>
<div
style={{
display: "flex",
justifyContent: "space-between",
width: "100%",
marginBottom: "8px",
fontSize: 28,
}}
>
<span>
by{" "}
<span
style={{
color: "transparent",
}}
>
"
</span>
<span style={{ overflow: "hidden", fontWeight: "bold" }}>
{SITE.author}
</span>
</span>
<span style={{ overflow: "hidden", fontWeight: "bold" }}>
{SITE.title}
</span>
</div>
</div>
</div>
</div>
);
};
const options: SatoriOptions = {
width: 1200,
height: 630,
embedFont: true,
fonts: [
{
name: "IBM Plex Mono",
data: fontRegular,
weight: 400,
style: "normal",
},
{
name: "IBM Plex Mono",
data: fontBold,
weight: 600,
style: "normal",
},
],
};
const generateOgImage = async (mytext = SITE.title) => {
const svg = await satori(ogImage(mytext), options);
// render png in production mode
if (import.meta.env.MODE === "production") {
const resvg = new Resvg(svg);
const pngData = resvg.render();
const pngBuffer = pngData.asPng();
console.info("Output PNG Image :", `${mytext}.png`);
await writeFile(`./dist/${mytext}.png`, pngBuffer);
}
return svg;
};
export default generateOgImage;

View File

@@ -0,0 +1,14 @@
import { SITE } from "@config";
const getPageNumbers = (numberOfPosts: number) => {
const numberOfPages = numberOfPosts / Number(SITE.postPerPage);
let pageNumbers: number[] = [];
for (let i = 1; i <= Math.ceil(numberOfPages); i++) {
pageNumbers = [...pageNumbers, i];
}
return pageNumbers;
};
export default getPageNumbers;

View File

@@ -0,0 +1,7 @@
import { slugifyAll } from "./slugify";
import type { CollectionEntry } from "astro:content";
const getPostsByTag = (posts: CollectionEntry<"blog">[], tag: string) =>
posts.filter(post => slugifyAll(post.data.tags).includes(tag));
export default getPostsByTag;

View File

@@ -0,0 +1,12 @@
import type { CollectionEntry } from "astro:content";
const getSortedPosts = (posts: CollectionEntry<"blog">[]) =>
posts
.filter(({ data }) => !data.draft)
.sort(
(a, b) =>
Math.floor(new Date(b.data.pubDatetime).getTime() / 1000) -
Math.floor(new Date(a.data.pubDatetime).getTime() / 1000)
);
export default getSortedPosts;

View File

@@ -0,0 +1,17 @@
import { slugifyStr } from "./slugify";
import type { CollectionEntry } from "astro:content";
const getUniqueTags = (posts: CollectionEntry<"blog">[]) => {
const filteredPosts = posts.filter(({ data }) => !data.draft);
const tags: string[] = filteredPosts
.flatMap(post => post.data.tags)
.map(tag => slugifyStr(tag))
.filter(
(value: string, index: number, self: string[]) =>
self.indexOf(value) === index
)
.sort((tagA: string, tagB: string) => tagA.localeCompare(tagB));
return tags;
};
export default getUniqueTags;

11
src/utils/slugify.ts Normal file
View File

@@ -0,0 +1,11 @@
import { slug as slugger } from "github-slugger";
import type { BlogFrontmatter } from "@content/_schemas";
export const slugifyStr = (str: string) => slugger(str);
const slugify = (post: BlogFrontmatter) =>
post.postSlug ? slugger(post.postSlug) : slugger(post.title);
export const slugifyAll = (arr: string[]) => arr.map(str => slugifyStr(str));
export default slugify;