Fix fonts

This commit is contained in:
Eric Bailey
2025-06-16 17:13:21 -05:00
parent 9fcd10be32
commit 0956a40f7a
6 changed files with 88 additions and 37 deletions
+29 -23
View File
@@ -2,36 +2,42 @@ import {writeFile} from 'node:fs/promises'
import * as path from 'node:path'
import {fileURLToPath} from 'node:url'
const __DIRNAME = path.dirname(fileURLToPath(import.meta.url))
import {
ADDITIONAL_FONTS,
ADDITIONAL_FONTS_POSTSCRIPT_NAMES,
} from '../src/util/fonts.js'
const FONTS = [
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-jp@5.0/japanese-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-tc@5.0/chinese-traditional-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-sc@5.0/chinese-simplified-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-hk@5.0/chinese-hongkong-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-kr@5.0/korean-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-thai@5.0/thai-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-arabic@5.0/arabic-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-hebrew@5.0/hebrew-700-normal.ttf',
]
const __DIRNAME = path.dirname(fileURLToPath(import.meta.url))
const outDir = path.join(__DIRNAME, '..', 'src', 'assets', 'fonts')
async function main() {
await Promise.all(
FONTS.map(async urlStr => {
const url = new URL(urlStr)
const res = await fetch(url)
const font = await res.arrayBuffer()
const filename = url.pathname
.split('/')
.slice(-2)
.join('/')
.replace(/@[\d.]+\//, '-')
ADDITIONAL_FONTS.map(async urlStr => {
// get last part of the URL
const raw = urlStr.split('/').slice(-1).join('')
// style and weight are known parts of the path, rest is the font family
const [styleWithExtension, weight, ...fontFamilyParts] = raw
.split('-')
.reverse()
const style = styleWithExtension.split('.')[0]
// re-reverse the font family parts to get the original order
const rawFontFamily = fontFamilyParts.reverse().join('-')
// get the postscript name from the map
const postScriptName = ADDITIONAL_FONTS_POSTSCRIPT_NAMES[rawFontFamily]
// our filename format: `weight-postScriptName-style.ttf`
const filename = `${weight}-${postScriptName}-${style}.ttf`
// fetch the file
const res = await fetch(urlStr)
if (!res.ok) {
throw new Error(`HTTP ${res.status}: fetching failed for ${filename}`)
throw new Error(`HTTP ${res.status}: fetching failed for ${urlStr}`)
}
console.log(`Writing font ${filename}...`)
await writeFile(
path.join(__DIRNAME, '..', 'src', 'assets', 'fonts', filename),
Buffer.from(font),
path.join(outDir, filename),
Buffer.from(await res.arrayBuffer()),
)
}),
)
+2 -1
View File
@@ -1,4 +1,5 @@
import {atoms as a, style as s, theme as t} from '../theme/index.js'
import {FONT_FAMILY_DEF} from '../util/fonts.js'
const SCALE_MULTIPLIER = 1 - 0.0625
@@ -20,7 +21,7 @@ export function Text({
a.tracking_wide,
t.atoms.text,
{
fontFamily: 'Inter',
fontFamily: FONT_FAMILY_DEF,
fontWeight: 400,
},
...(cx ?? []),
+3 -3
View File
@@ -1,7 +1,7 @@
import {AtpAgent} from '@atproto/api'
import {Config} from './config.js'
import {getFontFiles, readFonts} from './util/fonts.js'
import {getFontDefinitions} from './util/fonts.js'
export type AppContextOptions = {
cfg: Config
@@ -23,8 +23,8 @@ export class AppContext {
static async fromConfig(cfg: Config, overrides?: Partial<AppContextOptions>) {
const appviewAgent = new AtpAgent({service: cfg.service.appviewUrl})
const fontFiles = getFontFiles()
const fonts = readFonts(fontFiles)
const fonts = getFontDefinitions()
return new AppContext({
cfg,
appviewAgent,
+1 -6
View File
@@ -10,7 +10,6 @@ import {getPost} from '../data/getPost.js'
import {getPostData} from '../data/getPostData.js'
import {httpLogger} from '../logger.js'
import {loadEmojiAsSvg} from '../util.js'
import {getFontFiles} from '../util/fonts.js'
import {
getRenderOptions,
parseDisplayOptionsFromQuery,
@@ -72,15 +71,11 @@ export default function (ctx: AppContext, app: Express) {
},
)
const output = await resvg.renderAsync(svg, {
font: {
fontFiles: getFontFiles(),
defaultFontFamily: 'Inter',
},
fitTo: {
mode: 'width',
value: width * 2,
},
logLevel: 'trace',
// logLevel: 'trace',
})
res.statusCode = 200
+45 -4
View File
@@ -3,6 +3,43 @@ import * as path from 'node:path'
const __DIRNAME = path.join(process.cwd(), 'src')
export const ADDITIONAL_FONTS = [
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-jp@5.0/japanese-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-tc@5.0/chinese-traditional-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-sc@5.0/chinese-simplified-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-hk@5.0/chinese-hongkong-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-kr@5.0/korean-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-thai@5.0/thai-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-arabic@5.0/arabic-700-normal.ttf',
'https://cdn.jsdelivr.net/fontsource/fonts/noto-sans-hebrew@5.0/hebrew-700-normal.ttf',
]
/**
* CSS `fontFamily` defs must use the PostScript names of the fonts. When
* adding additional fonts above, you'll need to figure out the PostScript name
* and add it to the map below.
*/
export const ADDITIONAL_FONTS_POSTSCRIPT_NAMES: Record<string, string> = {
arabic: 'Noto Sans Arabic',
hebrew: 'Noto Sans Arabic',
japanese: 'Noto Sans JP Thin',
korean: 'Noto Sans KR',
thai: 'Noto Sans Thai',
'chinese-hongkong': 'Noto Sans HK',
'chinese-simplified': 'Noto Sans SC',
'chinese-traditional': 'Noto Sans TC',
}
/**
* Precomputed, for use in the runtime CSS defs
*/
export const FONT_FAMILY_DEF = `Inter, ${Object.values(
ADDITIONAL_FONTS_POSTSCRIPT_NAMES,
).join(', ')}, sans-serif`
/**
* Get all TTF files from our fonts dir
*/
export function getFontFiles() {
const fontDirectory = path.join(__DIRNAME, 'assets', 'fonts')
return readdirSync(fontDirectory)
@@ -10,13 +47,17 @@ export function getFontFiles() {
.map(file => path.join(fontDirectory, file))
}
export function readFonts(fontFiles: string[]) {
return fontFiles.map(file => {
/**
* Get all font files and format for use by Satori
*/
export function getFontDefinitions() {
return getFontFiles().map(file => {
const basename = path.basename(file, path.extname(file))
const italic = basename.includes('Italic')
const [weight, name] = basename.split('-')
const [weight, postScriptName] = basename.split('-')
return {
name,
name: postScriptName,
data: readFileSync(file),
weight: parseInt(weight),
style: italic ? 'italic' : 'normal',
+8
View File
@@ -107,6 +107,14 @@
</div>
</section>
<!-- Other languages -->
<section>
<h1>Other languages</h1>
<div class="grid">
<div class="item"><img src="http://localhost:3000/profile/miyanushi.bsky.social/post/3lrqt3xxmuk2a?mat=1"><div>Japanese</div></div>
</div>
</section>
<!-- Misc -->
<section>
<h1>Misc</h1>