The Trans Directory
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: parse parallelization chunk arg, inline b64 for og image

+49 -35
+22 -2
quartz/plugins/emitters/ogImage.tsx
··· 1 1 import { QuartzEmitterPlugin } from "../types" 2 2 import { i18n } from "../../i18n" 3 3 import { unescapeHTML } from "../../util/escape" 4 - import { FullSlug, getFileExtension } from "../../util/path" 4 + import { FullSlug, getFileExtension, joinSegments, QUARTZ } from "../../util/path" 5 5 import { ImageOptions, SocialImageOptions, defaultImage, getSatoriFonts } from "../../util/og" 6 6 import sharp from "sharp" 7 7 import satori, { SatoriOptions } from "satori" ··· 10 10 import { write } from "./helpers" 11 11 import { BuildCtx } from "../../util/ctx" 12 12 import { QuartzPluginData } from "../vfile" 13 + import fs from "node:fs/promises" 14 + import chalk from "chalk" 13 15 14 16 const defaultOptions: SocialImageOptions = { 15 17 colorScheme: "lightMode", ··· 28 30 userOpts: SocialImageOptions, 29 31 ): Promise<Readable> { 30 32 const { width, height } = userOpts 31 - const imageComponent = userOpts.imageStructure(cfg, userOpts, title, description, fonts, fileData) 33 + const iconPath = joinSegments(QUARTZ, "static", "icon.png") 34 + let iconBase64: string | undefined = undefined 35 + try { 36 + const iconData = await fs.readFile(iconPath) 37 + iconBase64 = `data:image/png;base64,${iconData.toString("base64")}` 38 + } catch (err) { 39 + console.warn(chalk.yellow(`Warning: Could not find icon at ${iconPath}`)) 40 + } 41 + 42 + const imageComponent = userOpts.imageStructure({ 43 + cfg, 44 + userOpts, 45 + title, 46 + description, 47 + fonts, 48 + fileData, 49 + iconBase64, 50 + }) 51 + 32 52 const svg = await satori(imageComponent, { 33 53 width, 34 54 height,
+2 -2
quartz/processors/parse.ts
··· 172 172 workerType: "thread", 173 173 }) 174 174 const errorHandler = (err: any) => { 175 - console.error(`${err}`.replace(/^error:\s*/i, "")) 175 + console.error(err) 176 176 process.exit(1) 177 177 } 178 178 ··· 201 201 202 202 const markdownToHtmlPromises: WorkerPromise<ProcessedContent[]>[] = [] 203 203 processedFiles = 0 204 - for (const [mdChunk, _] of mdResults) { 204 + for (const mdChunk of mdResults) { 205 205 markdownToHtmlPromises.push(pool.exec("processHtml", [serializableCtx, mdChunk])) 206 206 } 207 207 const results: ProcessedContent[][] = await Promise.all(
+1 -1
quartz/util/log.ts
··· 35 35 const truncated = truncate(output, columns) 36 36 process.stdout.write(truncated) 37 37 this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerChars.length 38 - }, 20) 38 + }, 50) 39 39 } 40 40 } 41 41
+24 -30
quartz/util/og.tsx
··· 13 13 14 14 const defaultHeaderWeight = [700] 15 15 const defaultBodyWeight = [400] 16 + 16 17 export async function getSatoriFonts(headerFont: FontSpecification, bodyFont: FontSpecification) { 17 18 // Get all weights for header and body fonts 18 19 const headerWeights: FontWeight[] = ( ··· 134 135 excludeRoot: boolean 135 136 /** 136 137 * JSX to use for generating image. See satori docs for more info (https://github.com/vercel/satori) 137 - * @param cfg global quartz config 138 - * @param userOpts options that can be set by user 139 - * @param title title of current page 140 - * @param description description of current page 141 - * @param fonts global font that can be used for styling 142 - * @param fileData full fileData of current page 143 - * @returns prepared jsx to be used for generating image 144 138 */ 145 139 imageStructure: ( 146 - cfg: GlobalConfiguration, 147 - userOpts: UserOpts, 148 - title: string, 149 - description: string, 150 - fonts: SatoriOptions["fonts"], 151 - fileData: QuartzPluginData, 140 + options: ImageOptions & { 141 + userOpts: UserOpts 142 + iconBase64?: string 143 + }, 152 144 ) => JSXInternal.Element 153 145 } 154 146 ··· 178 170 } 179 171 180 172 // This is the default template for generated social image. 181 - export const defaultImage: SocialImageOptions["imageStructure"] = ( 182 - cfg: GlobalConfiguration, 183 - { colorScheme }: UserOpts, 184 - title: string, 185 - description: string, 186 - _fonts: SatoriOptions["fonts"], 187 - fileData: QuartzPluginData, 188 - ) => { 173 + export const defaultImage: SocialImageOptions["imageStructure"] = ({ 174 + cfg, 175 + userOpts, 176 + title, 177 + description, 178 + fileData, 179 + iconBase64, 180 + }) => { 181 + const { colorScheme } = userOpts 189 182 const fontBreakPoint = 32 190 183 const useSmallerFont = title.length > fontBreakPoint 191 - const iconPath = `https://${cfg.baseUrl}/static/icon.png` 192 184 193 185 // Format date if available 194 186 const rawDate = getDate(cfg, fileData) ··· 226 218 marginBottom: "0.5rem", 227 219 }} 228 220 > 229 - <img 230 - src={iconPath} 231 - width={56} 232 - height={56} 233 - style={{ 234 - borderRadius: "50%", 235 - }} 236 - /> 221 + {iconBase64 && ( 222 + <img 223 + src={iconBase64} 224 + width={56} 225 + height={56} 226 + style={{ 227 + borderRadius: "50%", 228 + }} 229 + /> 230 + )} 237 231 <div 238 232 style={{ 239 233 display: "flex",