2019-10-04 09:27:30 +00:00
|
|
|
import { badgen } from 'badgen'
|
2019-05-14 01:36:25 +00:00
|
|
|
import icons from 'badgen-icons'
|
2019-11-20 16:35:05 +00:00
|
|
|
import originalUrl from 'original-url'
|
2018-06-29 16:52:17 +00:00
|
|
|
|
2019-11-20 16:35:05 +00:00
|
|
|
import { IncomingMessage, ServerResponse } from 'http'
|
2019-05-14 01:36:25 +00:00
|
|
|
import { BadgenParams } from './types'
|
2018-07-31 13:12:45 +00:00
|
|
|
|
2019-05-14 01:36:25 +00:00
|
|
|
type ServeBadgeOptions = {
|
|
|
|
code?: number
|
|
|
|
sMaxAge?: number,
|
2019-10-28 16:19:11 +00:00
|
|
|
query?: { [key: string]: string | undefined },
|
2019-06-03 14:19:17 +00:00
|
|
|
params: BadgenParams
|
2019-05-14 01:36:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-20 16:35:05 +00:00
|
|
|
export default function (req: IncomingMessage, res: ServerResponse, options: ServeBadgeOptions) {
|
2020-01-18 16:08:00 +00:00
|
|
|
const { code = 200, sMaxAge = 21600, query = {}, params } = options
|
2018-07-17 07:03:38 +00:00
|
|
|
|
2019-06-03 14:19:17 +00:00
|
|
|
const { subject, status, color } = params
|
2020-01-18 16:08:00 +00:00
|
|
|
const { label, labelColor, icon, iconWidth, list, scale, cache } = query
|
2019-06-22 16:30:49 +00:00
|
|
|
const _icon = resolveIcon(icon, iconWidth)
|
2018-07-22 13:00:51 +00:00
|
|
|
|
2019-06-13 11:07:24 +00:00
|
|
|
// TODO: review usage of list
|
2019-06-20 03:42:08 +00:00
|
|
|
list && console.log(`FEAT-LIST ${req.url}`)
|
2019-06-13 11:07:24 +00:00
|
|
|
|
2018-07-31 13:21:04 +00:00
|
|
|
const badge = badgen({
|
2019-07-06 10:12:35 +00:00
|
|
|
labelColor,
|
2018-08-31 02:17:41 +00:00
|
|
|
subject: typeof label !== 'undefined' ? label : subject,
|
2019-06-13 11:07:24 +00:00
|
|
|
status: transformStatus(status, { list }),
|
2019-06-10 16:13:27 +00:00
|
|
|
color: query.color || color,
|
2019-11-20 16:35:05 +00:00
|
|
|
style: autoBadgeStyle(req, query.style),
|
2019-06-12 01:42:07 +00:00
|
|
|
icon: _icon.src,
|
2019-10-04 09:50:20 +00:00
|
|
|
iconWidth: parseInt(iconWidth || _icon.width || '13', 10),
|
2019-11-05 02:51:42 +00:00
|
|
|
scale: parseFloat(scale || '1'),
|
2018-07-31 13:21:04 +00:00
|
|
|
})
|
2018-07-22 13:00:51 +00:00
|
|
|
|
2020-01-18 16:08:00 +00:00
|
|
|
const cacheMaxAge = cache ? Math.max(parseInt(cache as string) || 0, 300) : sMaxAge
|
|
|
|
res.setHeader('Cache-Control', `public, max-age=120, s-maxage=${cacheMaxAge}, stale-while-revalidate=86400`)
|
2018-07-25 05:34:22 +00:00
|
|
|
res.setHeader('Content-Type', 'image/svg+xml;charset=utf-8')
|
2019-05-14 01:36:25 +00:00
|
|
|
res.statusCode = code
|
|
|
|
res.end(badge)
|
2018-06-29 16:52:17 +00:00
|
|
|
}
|
2019-06-12 01:42:07 +00:00
|
|
|
|
2019-11-20 16:35:05 +00:00
|
|
|
type BadgeStyle = 'flat' | undefined
|
|
|
|
|
|
|
|
function autoBadgeStyle (req: IncomingMessage, fallbackValue?: string): BadgeStyle {
|
|
|
|
const isFlat = (fallbackValue || process.env.BADGE_STYLE === 'flat')
|
|
|
|
|| originalUrl(req).hostname.includes('flat')
|
|
|
|
return isFlat ? 'flat' : undefined
|
|
|
|
}
|
|
|
|
|
2019-06-13 11:07:24 +00:00
|
|
|
function transformStatus (status: any, { list }) {
|
|
|
|
status = String(status)
|
|
|
|
|
|
|
|
if (list !== undefined) {
|
2019-06-20 03:17:59 +00:00
|
|
|
if (list === '1' || list === '') list = '|' // compatible
|
2019-06-13 11:07:24 +00:00
|
|
|
status = status.replace(/,/g, ` ${list} `)
|
|
|
|
}
|
|
|
|
|
|
|
|
return status
|
|
|
|
}
|
|
|
|
|
2019-06-12 01:42:07 +00:00
|
|
|
type ResolvedIcon = {
|
|
|
|
src?: string
|
|
|
|
width?: string
|
|
|
|
}
|
|
|
|
|
2019-10-28 16:19:11 +00:00
|
|
|
function resolveIcon (icon: string | undefined, width?: string): ResolvedIcon {
|
2019-06-12 01:42:07 +00:00
|
|
|
const builtinIcon = icons[icon]
|
|
|
|
if (builtinIcon) {
|
|
|
|
return {
|
|
|
|
src: builtinIcon.base64,
|
|
|
|
width: width || builtinIcon.width
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-20 03:33:53 +00:00
|
|
|
if (String(icon).startsWith('data:image/')) {
|
2019-06-12 01:42:07 +00:00
|
|
|
return { src: icon, width }
|
|
|
|
}
|
|
|
|
|
|
|
|
return {}
|
|
|
|
}
|