diff --git a/astro.config.ts b/astro.config.ts
index b150148..59d561f 100644
--- a/astro.config.ts
+++ b/astro.config.ts
@@ -1,7 +1,6 @@
import mdx from '@astrojs/mdx';
import node from '@astrojs/node';
import { defineConfig, envField } from 'astro/config';
-import arraybuffer from 'vite-plugin-arraybuffer';
import { astroImage } from './remark-plugins/images';
// Dynamic switch the site. This is hard coded.
@@ -51,7 +50,6 @@ export default defineConfig({
enabled: false,
},
vite: {
- plugins: [arraybuffer()],
// Add this for avoiding the needless import optimize in Vite.
optimizeDeps: { exclude: ['@napi-rs/canvas'] },
},
diff --git a/package-lock.json b/package-lock.json
index 0d047e5..a8acc90 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28,7 +28,7 @@
"@napi-rs/canvas": "^0.1.53",
"@types/lodash": "^4.17.5",
"@types/luxon": "^3.4.2",
- "@types/node": "^20.14.2",
+ "@types/node": "^20.14.5",
"@types/pg": "^8.11.6",
"@types/qrcode-svg": "^1.1.4",
"@types/unist": "^3.0.2",
@@ -42,8 +42,7 @@
"rimraf": "^5.0.7",
"sharp": "^0.33.4",
"typescript": "^5.4.5",
- "unist-util-visit": "^5.0.0",
- "vite-plugin-arraybuffer": "^0.0.7"
+ "unist-util-visit": "^5.0.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -2741,9 +2740,9 @@
}
},
"node_modules/@types/node": {
- "version": "20.14.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.2.tgz",
- "integrity": "sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==",
+ "version": "20.14.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.5.tgz",
+ "integrity": "sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==",
"devOptional": true,
"license": "MIT",
"dependencies": {
@@ -3993,9 +3992,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
- "version": "1.4.803",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.803.tgz",
- "integrity": "sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==",
+ "version": "1.4.805",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.805.tgz",
+ "integrity": "sha512-8W4UJwX/w9T0QSzINJckTKG6CYpAUTqsaWcWIsdud3I1FYJcMgW9QqT1/4CBff/pP/TihWh13OmiyY8neto6vw==",
"license": "ISC"
},
"node_modules/emmet": {
@@ -8708,13 +8707,6 @@
}
}
},
- "node_modules/vite-plugin-arraybuffer": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/vite-plugin-arraybuffer/-/vite-plugin-arraybuffer-0.0.7.tgz",
- "integrity": "sha512-c4Egxj7NUGco2Ggw9KUBToOxuc7Ws7mWm0hz/QnaT5Ph8ycC7ypMBOD31NuhPSx+wdUvgIbS1XpMvJLSdHakPA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/vitefu": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.5.tgz",
diff --git a/package.json b/package.json
index 0ad3328..080a773 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
"@napi-rs/canvas": "^0.1.53",
"@types/lodash": "^4.17.5",
"@types/luxon": "^3.4.2",
- "@types/node": "^20.14.2",
+ "@types/node": "^20.14.5",
"@types/pg": "^8.11.6",
"@types/qrcode-svg": "^1.1.4",
"@types/unist": "^3.0.2",
@@ -74,7 +74,6 @@
"rimraf": "^5.0.7",
"sharp": "^0.33.4",
"typescript": "^5.4.5",
- "unist-util-visit": "^5.0.0",
- "vite-plugin-arraybuffer": "^0.0.7"
+ "unist-util-visit": "^5.0.0"
}
}
diff --git a/src/assets/og/logo-dark.png b/src/assets/og/logo-dark.png
deleted file mode 100644
index cff93b5..0000000
Binary files a/src/assets/og/logo-dark.png and /dev/null differ
diff --git a/src/assets/og/open-graph.png b/src/assets/og/open-graph.png
deleted file mode 100644
index 1a1ee64..0000000
Binary files a/src/assets/og/open-graph.png and /dev/null differ
diff --git a/src/env.d.ts b/src/env.d.ts
index 204abbc..338ba9e 100644
--- a/src/env.d.ts
+++ b/src/env.d.ts
@@ -1,4 +1,3 @@
///
///
///
-///
diff --git a/src/helpers/images.ts b/src/helpers/images.ts
index dde65d2..bf3a4d7 100644
--- a/src/helpers/images.ts
+++ b/src/helpers/images.ts
@@ -52,7 +52,6 @@ export const blurStyle = (image: Image) => ({
// Copied and modified https://github.com/zce/velite/blob/main/src/assets.ts
export const imageMetadata = async (publicPath: string): Promise => {
- // Load for sharp on demand for avoiding the resolver issues in production.
const { default: sharp } = await import('sharp');
if (!publicPath.startsWith('/')) {
diff --git a/src/helpers/og.ts b/src/helpers/og.ts
index 8ed39ee..9a4a359 100644
--- a/src/helpers/og.ts
+++ b/src/helpers/og.ts
@@ -9,8 +9,19 @@ import { options } from '@/helpers/schema';
import { Canvas, GlobalFonts, Image, type SKRSContext2D } from '@napi-rs/canvas';
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
-import font from '../assets/og/NotoSansSC-Bold.ttf?arraybuffer';
-import logoDark from '../assets/og/logo-dark.png?arraybuffer';
+
+const darkLogo = ``;
const getStringWidth = (text: string, fontSize: number) => {
let result = 0;
@@ -114,18 +125,20 @@ const fetchCover = async (cover: string): Promise => {
return await readFile(coverPath);
};
-export { default as defaultOpenGraph } from '../assets/og/open-graph.png?arraybuffer';
-
export interface OpenGraphProps {
title: string;
summary: string;
cover: string;
}
-export const drawOpenGraph = async ({ title, summary, cover }: OpenGraphProps) => {
+export const defaultOpenGraph = async (): Promise => {
+ return await fetchCover('/images/default-cover.jpg');
+};
+
+export const drawOpenGraph = async ({ title, summary, cover }: OpenGraphProps): Promise => {
// Register the font if it doesn't exist
if (!GlobalFonts.has('NotoSansSC-Bold')) {
- const fontBuffer = Buffer.from(font);
+ const fontBuffer = await readFile(join(process.cwd(), 'src/assets/og/NotoSansSC-Bold.ttf'));
GlobalFonts.register(fontBuffer, 'NotoSansSC-Bold');
}
@@ -135,7 +148,7 @@ export const drawOpenGraph = async ({ title, summary, cover }: OpenGraphProps) =
// Generate the logo image
const logoImage = new Image();
- logoImage.src = Buffer.from(logoDark);
+ logoImage.src = Buffer.from(darkLogo, 'utf-8');
// Mark sure the summary length is small enough to fit in
const description = `${summary
@@ -171,5 +184,20 @@ export const drawOpenGraph = async ({ title, summary, cover }: OpenGraphProps) =
ctx.restore();
- return await canvas.encode('png');
+ const encodedImage = await canvas.encode('png');
+ return await compressImage(encodedImage);
+};
+
+const compressImage = async (buf: Buffer): Promise => {
+ const { default: sharp } = await import('sharp');
+ return await sharp(buf)
+ .png({
+ compressionLevel: 9,
+ adaptiveFiltering: true,
+ force: true,
+ palette: true,
+ quality: 75,
+ progressive: true,
+ })
+ .toBuffer();
};
diff --git a/src/pages/og/[slug].png.ts b/src/pages/og/[slug].png.ts
index 40f04d2..3829d87 100644
--- a/src/pages/og/[slug].png.ts
+++ b/src/pages/og/[slug].png.ts
@@ -2,8 +2,8 @@ import { defaultOpenGraph, drawOpenGraph } from '@/helpers/og';
import { getPage, getPost, pages, posts } from '@/helpers/schema';
import type { APIRoute } from 'astro';
-const fallback = () =>
- new Response(defaultOpenGraph, {
+const fallback = async () =>
+ new Response(await defaultOpenGraph(), {
headers: { 'Content-Type': 'image/png' },
});
@@ -12,7 +12,7 @@ export const prerender = true;
export const GET: APIRoute = async ({ params }) => {
const slug = params.slug;
if (!slug) {
- return fallback();
+ return await fallback();
}
let title: string;
@@ -25,7 +25,7 @@ export const GET: APIRoute = async ({ params }) => {
// Fallback to query from pages
const page = getPage(slug);
if (!page) {
- return fallback();
+ return await fallback();
}
title = page.title;