mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-31 00:34:05 -06:00
feat: add basic satori og image generation
This commit is contained in:
parent
6a2e0b3ad3
commit
715446272a
@ -77,6 +77,7 @@
|
|||||||
"remark-rehype": "^10.1.0",
|
"remark-rehype": "^10.1.0",
|
||||||
"remark-smartypants": "^2.0.0",
|
"remark-smartypants": "^2.0.0",
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
|
"satori": "^0.10.6",
|
||||||
"serve-handler": "^6.1.5",
|
"serve-handler": "^6.1.5",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"to-vfile": "^7.2.4",
|
"to-vfile": "^7.2.4",
|
||||||
|
|||||||
@ -1,9 +1,65 @@
|
|||||||
import { FullSlug, _stripSlashes, joinSegments, pathToRoot } from "../util/path"
|
import { FullSlug, _stripSlashes, joinSegments, pathToRoot } from "../util/path"
|
||||||
import { JSResourceToScriptElement } from "../util/resources"
|
import { JSResourceToScriptElement } from "../util/resources"
|
||||||
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
import { QuartzComponentConstructor, QuartzComponentProps } from "./types"
|
||||||
|
import satori from "satori"
|
||||||
|
import * as fs from "fs"
|
||||||
|
|
||||||
|
const robotoData = await (
|
||||||
|
await fetch("https://fonts.gstatic.com/s/roboto/v30/KFOmCnqEu92Fr1Me5Q.ttf")
|
||||||
|
).arrayBuffer()
|
||||||
|
|
||||||
|
async function generateSvg(title: string, filePath: string) {
|
||||||
|
const svg = await satori(
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
color: "black",
|
||||||
|
backgroundColor: "green",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
fontSize: 64,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>,
|
||||||
|
{
|
||||||
|
width: 1200,
|
||||||
|
height: 675,
|
||||||
|
fonts: [
|
||||||
|
{
|
||||||
|
name: "Roboto",
|
||||||
|
// Use `fs` (Node.js only) or `fetch` to read the font as Buffer/ArrayBuffer and provide `data` here.
|
||||||
|
data: robotoData,
|
||||||
|
weight: 400,
|
||||||
|
style: "normal",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
fs.writeFileSync(`public/static/${filePath}.svg`, svg)
|
||||||
|
}
|
||||||
|
|
||||||
export default (() => {
|
export default (() => {
|
||||||
function Head({ cfg, fileData, externalResources }: QuartzComponentProps) {
|
function Head({ cfg, fileData, externalResources }: QuartzComponentProps) {
|
||||||
|
const dir = "public/static"
|
||||||
|
const slug = fileData.filePath
|
||||||
|
const filePath = slug?.replaceAll("/", "-")
|
||||||
|
const ogArr = slug?.split("/")
|
||||||
|
const ogTitle = fileData.frontmatter?.title ?? "Untitled"
|
||||||
|
|
||||||
|
// const title = fileData?.fron
|
||||||
|
// console.log("filePath: ", filePath)
|
||||||
|
// if (ogTitle && filePath) {
|
||||||
|
console.log("OG title: ", ogTitle)
|
||||||
|
generateSvg(ogTitle as string, filePath as string)
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
fs.mkdirSync(dir)
|
||||||
|
}
|
||||||
const title = fileData.frontmatter?.title ?? "Untitled"
|
const title = fileData.frontmatter?.title ?? "Untitled"
|
||||||
const description = fileData.description?.trim() ?? "No description provided"
|
const description = fileData.description?.trim() ?? "No description provided"
|
||||||
const { css, js } = externalResources
|
const { css, js } = externalResources
|
||||||
@ -14,6 +70,7 @@ export default (() => {
|
|||||||
|
|
||||||
const iconPath = joinSegments(baseDir, "static/icon.png")
|
const iconPath = joinSegments(baseDir, "static/icon.png")
|
||||||
const ogImagePath = `https://${cfg.baseUrl}/static/og-image.png`
|
const ogImagePath = `https://${cfg.baseUrl}/static/og-image.png`
|
||||||
|
const ogImagePathNew = `https://${cfg.baseUrl}/static/${filePath}.svg`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<head>
|
<head>
|
||||||
@ -22,7 +79,7 @@ export default (() => {
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
{cfg.baseUrl && <meta property="og:image" content={ogImagePath} />}
|
{cfg.baseUrl && <meta property="og:image" content={ogImagePathNew} />}
|
||||||
<meta property="og:width" content="1200" />
|
<meta property="og:width" content="1200" />
|
||||||
<meta property="og:height" content="675" />
|
<meta property="og:height" content="675" />
|
||||||
<link rel="icon" href={iconPath} />
|
<link rel="icon" href={iconPath} />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user