| docs/plugins/CustomOgImages.md | ●●●●● patch | view | raw | blame | history | |
| quartz/plugins/emitters/ogImage.tsx | ●●●●● patch | view | raw | blame | history | |
| quartz/util/path.test.ts | ●●●●● patch | view | raw | blame | history | |
| quartz/util/path.ts | ●●●●● patch | view | raw | blame | history |
docs/plugins/CustomOgImages.md
@@ -62,7 +62,7 @@ | `socialDescription` | `description` | Description to be used for preview. | | `socialImage` | `image`, `cover` | Link to preview image. | The `socialImage` property should contain a link to an image relative to `quartz/static`. If you have a folder for all your images in `quartz/static/my-images`, an example for `socialImage` could be `"my-images/cover.png"`. The `socialImage` property should contain a link to an image either relative to `quartz/static`, or a full URL. If you have a folder for all your images in `quartz/static/my-images`, an example for `socialImage` could be `"my-images/cover.png"`. Alternatively, you can use a fully qualified URL like `"https://example.com/cover.png"`. > [!info] Info > quartz/plugins/emitters/ogImage.tsx
@@ -1,7 +1,7 @@ import { QuartzEmitterPlugin } from "../types" import { i18n } from "../../i18n" import { unescapeHTML } from "../../util/escape" import { FullSlug, getFileExtension, joinSegments, QUARTZ } from "../../util/path" import { FullSlug, getFileExtension, isAbsoluteURL, joinSegments, QUARTZ } from "../../util/path" import { ImageOptions, SocialImageOptions, defaultImage, getSatoriFonts } from "../../util/og" import sharp from "sharp" import satori, { SatoriOptions } from "satori" @@ -144,13 +144,19 @@ additionalHead: [ (pageData) => { const isRealFile = pageData.filePath !== undefined const userDefinedOgImagePath = pageData.frontmatter?.socialImage let userDefinedOgImagePath = pageData.frontmatter?.socialImage if (userDefinedOgImagePath) { userDefinedOgImagePath = isAbsoluteURL(userDefinedOgImagePath) ? userDefinedOgImagePath : `https://${baseUrl}/static/${userDefinedOgImagePath}` } const generatedOgImagePath = isRealFile ? `https://${baseUrl}/${pageData.slug!}-og-image.webp` : undefined const defaultOgImagePath = `https://${baseUrl}/static/og-image.png` const ogImagePath = userDefinedOgImagePath ?? generatedOgImagePath ?? defaultOgImagePath const ogImageMimeType = `image/${getFileExtension(ogImagePath) ?? "png"}` return ( <> quartz/util/path.test.ts
@@ -38,6 +38,17 @@ assert(!path.isRelativeURL("./abc/def.md")) }) test("isAbsoluteURL", () => { assert(path.isAbsoluteURL("https://example.com")) assert(path.isAbsoluteURL("http://example.com")) assert(path.isAbsoluteURL("ftp://example.com/a/b/c")) assert(path.isAbsoluteURL("http://host/%25")) assert(path.isAbsoluteURL("file://host/twoslashes?more//slashes")) assert(!path.isAbsoluteURL("example.com/abc/def")) assert(!path.isAbsoluteURL("abc")) }) test("isFullSlug", () => { assert(path.isFullSlug("index")) assert(path.isFullSlug("abc/def")) quartz/util/path.ts
@@ -1,6 +1,7 @@ import { slug as slugAnchor } from "github-slugger" import type { Element as HastElement } from "hast" import { clone } from "./clone" // this file must be isomorphic so it can't use node libs (e.g. path) export const QUARTZ = "quartz" @@ -39,6 +40,15 @@ return validStart && validEnding && ![".md", ".html"].includes(getFileExtension(s) ?? "") } export function isAbsoluteURL(s: string): boolean { try { new URL(s) } catch { return false } return true } export function getFullSlug(window: Window): FullSlug { const res = window.document.body.dataset.slug! as FullSlug return res