kopia lustrzana https://github.com/badgen/badgen.net
112 wiersze
2.8 KiB
TypeScript
112 wiersze
2.8 KiB
TypeScript
import { badgen } from 'badgen'
|
|
import icons from 'badgen-icons'
|
|
import originalUrl from 'original-url'
|
|
|
|
import { BadgenParams } from './types'
|
|
|
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
|
|
|
type ServeBadgeOptions = {
|
|
code?: number
|
|
sMaxAge?: number,
|
|
params: BadgenParams
|
|
}
|
|
|
|
export function serveBadgeNext (req: NextApiRequest, res: NextApiResponse, options: ServeBadgeOptions) {
|
|
const { code = 200, sMaxAge = 3600, params } = options
|
|
const { subject, status, color } = params
|
|
|
|
const query = req.query
|
|
const { list, scale, cache } = req.query
|
|
const iconMeta = resolveIcon(query.icon, query.iconWidth)
|
|
|
|
const badgeParams = {
|
|
labelColor: resolveColor(query.labelColor, '555'),
|
|
subject: formatSVGText(typeof query.label === 'string' ? query.label : subject),
|
|
status: formatSVGText(transformStatus(status, { list })),
|
|
color: resolveColor(query.color || color, 'blue'),
|
|
style: resolveBadgeStyle(req),
|
|
icon: iconMeta.src,
|
|
iconWidth: iconMeta.width,
|
|
scale: parseFloat(String(scale)) || 1,
|
|
}
|
|
|
|
const badgeSVGString = badgen(badgeParams)
|
|
|
|
// Minimum s-maxage is set to 300s(5m)
|
|
if (res.getHeader('cache-control') === undefined) {
|
|
const cacheMaxAge = cache ? Math.max(parseInt(String(cache)), 300) : sMaxAge
|
|
res.setHeader('cache-control', `public, max-age=86400, s-maxage=${cacheMaxAge}, stale-while-revalidate=86400`)
|
|
}
|
|
|
|
res.setHeader('Content-Type', 'image/svg+xml;charset=utf-8')
|
|
res.statusCode = code
|
|
res.send(badgeSVGString)
|
|
}
|
|
|
|
function resolveBadgeStyle (req: NextApiRequest, style?: string | string[]): 'flat' | 'classic' {
|
|
if (style === 'flat') {
|
|
return 'flat'
|
|
}
|
|
|
|
if (process.env.BADGE_STYLE === 'flat') {
|
|
return 'flat'
|
|
}
|
|
|
|
if (originalUrl(req).hostname.includes('flat')) {
|
|
return 'flat'
|
|
}
|
|
|
|
return 'classic'
|
|
}
|
|
|
|
function formatSVGText (text: string): string {
|
|
return text
|
|
.replace(/%2F/g, '/') // simple decode
|
|
}
|
|
|
|
function transformStatus (status: any, { list }): string {
|
|
status = String(status)
|
|
|
|
if (list !== undefined) {
|
|
if (list === '1' || list === '') list = '|' // compatible
|
|
status = status.replace(/,/g, ` ${list} `)
|
|
}
|
|
|
|
return status
|
|
}
|
|
|
|
function resolveColor (color: string | string[] | undefined, defaultColor: string): string {
|
|
|
|
if (color !== undefined) {
|
|
return String(color)
|
|
}
|
|
|
|
return defaultColor
|
|
}
|
|
|
|
type ResolvedIcon = {
|
|
src?: string
|
|
width?: number
|
|
}
|
|
|
|
function resolveIcon (icon?: string | string[], width?: string | string[]): ResolvedIcon {
|
|
const iconArg = String(icon) || ''
|
|
const widthNum = parseInt(String(width)) || 10
|
|
|
|
const builtinIcon = icons[icon]
|
|
|
|
if (builtinIcon) {
|
|
return {
|
|
src: builtinIcon.base64,
|
|
width: widthNum || builtinIcon.width
|
|
}
|
|
}
|
|
|
|
if (iconArg.startsWith('data:image/')) {
|
|
return { src: iconArg, width: widthNum }
|
|
}
|
|
|
|
return {}
|
|
}
|