bskyogcard: support emoji, more languages, long starter pack names (#4668)
This commit is contained in:
parent
f6b138f709
commit
49396451ec
12 changed files with 413 additions and 163 deletions
|
@ -43,6 +43,7 @@ export function StarterPack(props: {
|
|||
} else {
|
||||
imagesAcross.push(...imagesExceptCreator.slice(0, 7))
|
||||
}
|
||||
const isLongTitle = record ? record.name.length > 30 : false
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
|
@ -130,7 +131,9 @@ export function StarterPack(props: {
|
|||
<div
|
||||
style={{
|
||||
padding: '75px 30px 0px',
|
||||
fontSize: 65,
|
||||
fontSize: isLongTitle ? 55 : 65,
|
||||
display: 'flex',
|
||||
textAlign: 'center',
|
||||
}}>
|
||||
{record?.name || 'Starter Pack'}
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {readFileSync} from 'node:fs'
|
||||
import {readdirSync, readFileSync} from 'node:fs'
|
||||
import * as path from 'node:path'
|
||||
import {fileURLToPath} from 'node:url'
|
||||
|
||||
import {AtpAgent} from '@atproto/api'
|
||||
import * as path from 'path'
|
||||
import {fileURLToPath} from 'url'
|
||||
|
||||
import {Config} from './config.js'
|
||||
|
||||
|
@ -28,12 +28,14 @@ export class AppContext {
|
|||
|
||||
static async fromConfig(cfg: Config, overrides?: Partial<AppContextOptions>) {
|
||||
const appviewAgent = new AtpAgent({service: cfg.service.appviewUrl})
|
||||
const fonts = [
|
||||
{
|
||||
name: 'Inter',
|
||||
data: readFileSync(path.join(__DIRNAME, 'assets', 'Inter-Bold.ttf')),
|
||||
},
|
||||
]
|
||||
const fontDirectory = path.join(__DIRNAME, 'assets', 'fonts')
|
||||
const fontFiles = readdirSync(fontDirectory)
|
||||
const fonts = fontFiles.map(file => {
|
||||
return {
|
||||
name: path.basename(file, path.extname(file)),
|
||||
data: readFileSync(path.join(fontDirectory, file)),
|
||||
}
|
||||
})
|
||||
return new AppContext({
|
||||
cfg,
|
||||
appviewAgent,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {subsystemLogger} from '@atproto/common'
|
||||
|
||||
export const httpLogger = subsystemLogger('bskyogcard')
|
||||
export const renderLogger = subsystemLogger('bskyogcard:render')
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
} from '../components/StarterPack.js'
|
||||
import {AppContext} from '../context.js'
|
||||
import {httpLogger} from '../logger.js'
|
||||
import {loadEmojiAsSvg} from '../util.js'
|
||||
import {handler, originVerifyMiddleware} from './util.js'
|
||||
|
||||
export default function (ctx: AppContext, app: Express) {
|
||||
|
@ -65,6 +66,11 @@ export default function (ctx: AppContext, app: Express) {
|
|||
fonts: ctx.fonts,
|
||||
height: STARTERPACK_HEIGHT,
|
||||
width: STARTERPACK_WIDTH,
|
||||
loadAdditionalAsset: async (code, text) => {
|
||||
if (code === 'emoji') {
|
||||
return await loadEmojiAsSvg(text)
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
const output = await resvg.renderAsync(svg)
|
||||
|
|
37
bskyogcard/src/util.ts
Normal file
37
bskyogcard/src/util.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import twemoji from 'twemoji'
|
||||
|
||||
import {renderLogger} from './logger.js'
|
||||
|
||||
const U200D = String.fromCharCode(0x200d)
|
||||
const UFE0F_REGEXP = /\uFE0F/g
|
||||
|
||||
export async function loadEmojiAsSvg(chars: string) {
|
||||
const cached = emojiCache.get(chars)
|
||||
if (cached) return cached
|
||||
const iconCode = twemoji.convert.toCodePoint(
|
||||
chars.indexOf(U200D) < 0 ? chars.replace(UFE0F_REGEXP, '') : chars,
|
||||
)
|
||||
const res = await fetch(getEmojiUrl(iconCode))
|
||||
const body = await res.arrayBuffer()
|
||||
if (!res.ok) {
|
||||
renderLogger.warn(
|
||||
{status: res.status, err: Buffer.from(body).toString()},
|
||||
'could not fetch emoji',
|
||||
)
|
||||
return
|
||||
}
|
||||
const svg =
|
||||
'data:image/svg+xml;base64,' + Buffer.from(body).toString('base64')
|
||||
emojiCache.set(chars, svg)
|
||||
return svg
|
||||
}
|
||||
|
||||
const emojiCache = new Map<string, string>()
|
||||
|
||||
function getEmojiUrl(code: string) {
|
||||
return (
|
||||
'https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/svg/' +
|
||||
code.toLowerCase() +
|
||||
'.svg'
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue