Files
shields/core/base-service/coalesce-badge.js
chris48s 3ba05cb184 📦 version 3 (#4756)
* Validate input to BadgeFactory.create() (#3875)

* validate input to create()

* remove deprecated properties (#3881)

* remove BadgeFactory class (#3884)

* Template literal templates (#4459)

- Remove use of the doT template library and move to generating SVG output using javascript template literals.
- Drop SVGO and mostly manually implement the optimisations.
- Add a bunch more tests

Co-authored-by: Paul Melnikow <github@paulmelnikow.com>

* drop raster support in package CLI (#4523)

* drop raster support in package CLI
* update docs

* rename gh-badges package to badge-maker

* rename gh-badges dir to badge-maker

* update relative imports and other refs to in parent dir

'gh-badges' --> 'badge-maker'

* update snyk service tests

This change is only tangentially related

We've used the shields repo as an example for these tests so
moving files around in our repo has a knock-on effect on them

* add missing type hints to dev style page

* write the changelog/migration guide for v3

* use extension in README CLI example

* update CLI help

whoops - missed this in #4523

* bump version

* update for self-hosting users

* README updates

* drop .format param from CLI, always output SVG

* Change text[] to label and message, Remove JSON output

- Change text[] to label and message
- Fix message only badge
- Remove JSON output format
- Update the docs

* update package-lock

* rename 'template' to 'style'

* handle invalid styles in coalesceBadge

* ensure makeBadge is passed a string for template in coalesceBadge()

issue #4925

* fix (logo/no label text/label color specified) case

issue #4926

* add example of (logo/no label text/label color specified) to style debug page

* update type defs

* padding fix for FTB style

Co-authored-by: Paul Melnikow <github@paulmelnikow.com>
2020-04-23 20:05:48 +01:00

191 lines
6.3 KiB
JavaScript

'use strict'
const {
decodeDataUrlFromQueryParam,
prepareNamedLogo,
} = require('../../lib/logos')
const { svg2base64 } = require('../../lib/svg-helpers')
const coalesce = require('./coalesce')
const toArray = require('./to-array')
// Translate modern badge data to the legacy schema understood by the badge
// maker. Allow the user to override the label, color, logo, etc. through the
// query string. Provide support for most badge options via `serviceData` so
// the Endpoint badge can specify logos and colors, though allow that the
// user's logo or color to take precedence. A notable exception is the case of
// errors. When the service specifies that an error has occurred, the user's
// requested color does not override the error color.
//
// Logos are resolved in this manner:
//
// 1. When `?logo=` contains the name of one of the Shields logos, or contains
// base64-encoded SVG, that logo is used. In the case of a named logo, when
// a `&logoColor=` is specified, that color is used. Otherwise the default
// color is used. `logoColor` will not be applied to a custom
// (base64-encoded) logo; if a custom color is desired the logo should be
// recolored prior to making the request. The appearance of the logo can be
// customized using `logoWidth`, and in the case of the popout badge,
// `logoPosition`. When `?logo=` is specified, any logo-related parameters
// specified dynamically by the service, or by default in the service, are
// ignored.
// 2. The second precedence is the dynamic logo returned by a service. This is
// used only by the Endpoint badge. The `logoColor` can be overridden by the
// query string.
// 3. In the case of the `social` style only, the last precedence is the
// service's default logo. The `logoColor` can be overridden by the query
// string.
module.exports = function coalesceBadge(
overrides,
serviceData,
// These two parameters were kept separate to make tests clearer.
defaultBadgeData,
{ category, _cacheLength: defaultCacheSeconds } = {}
) {
// The "overrideX" naming is based on services that provide badge
// parameters themselves, which can be overridden by a query string
// parameter. (For a couple services, the dynamic badge and the
// query-string-based static badge, the service never sets a value
// so the query string overrides are the _only_ way to configure
// these badge parameters.
const {
style: overrideStyle,
label: overrideLabel,
logo: overrideLogo,
logoColor: overrideLogoColor,
link: overrideLink,
colorB: legacyOverrideColor,
colorA: legacyOverrideLabelColor,
} = overrides
let {
logoWidth: overrideLogoWidth,
logoPosition: overrideLogoPosition,
color: overrideColor,
labelColor: overrideLabelColor,
} = overrides
// Only use the legacy properties if the new ones are not provided
if (typeof overrideColor === 'undefined') {
overrideColor = legacyOverrideColor
}
if (typeof overrideLabelColor === 'undefined') {
overrideLabelColor = legacyOverrideLabelColor
}
// Scoutcamp converts numeric query params to numbers. Convert them back.
if (typeof overrideColor === 'number') {
overrideColor = `${overrideColor}`
}
if (typeof overrideLabelColor === 'number') {
overrideLabelColor = `${overrideLabelColor}`
}
overrideLogoWidth = +overrideLogoWidth || undefined
overrideLogoPosition = +overrideLogoPosition || undefined
const {
isError,
label: serviceLabel,
message: serviceMessage,
color: serviceColor,
labelColor: serviceLabelColor,
logoSvg: serviceLogoSvg,
namedLogo: serviceNamedLogo,
logoColor: serviceLogoColor,
logoWidth: serviceLogoWidth,
logoPosition: serviceLogoPosition,
link: serviceLink,
cacheSeconds: serviceCacheSeconds,
style: serviceStyle,
} = serviceData
const {
color: defaultColor,
namedLogo: defaultNamedLogo,
label: defaultLabel,
labelColor: defaultLabelColor,
} = defaultBadgeData
let style = coalesce(overrideStyle, serviceStyle)
if (typeof style !== 'string') {
style = 'flat'
}
if (style.startsWith('popout')) {
style = style.replace('popout', 'flat')
}
const styleValues = [
'plastic',
'flat',
'flat-square',
'for-the-badge',
'social',
]
if (!styleValues.includes(style)) {
style = 'flat'
}
let namedLogo, namedLogoColor, logoWidth, logoPosition, logoSvgBase64
if (overrideLogo) {
// `?logo=` could be a named logo or encoded svg.
const overrideLogoSvgBase64 = decodeDataUrlFromQueryParam(overrideLogo)
if (overrideLogoSvgBase64) {
logoSvgBase64 = overrideLogoSvgBase64
} else {
namedLogo = overrideLogo
// If the logo has been overridden it does not make sense to inherit the
// original color.
namedLogoColor = overrideLogoColor
}
// If the logo has been overridden it does not make sense to inherit the
// original width or position.
logoWidth = overrideLogoWidth
logoPosition = overrideLogoPosition
} else {
if (serviceLogoSvg) {
logoSvgBase64 = svg2base64(serviceLogoSvg)
} else {
namedLogo = coalesce(
serviceNamedLogo,
style === 'social' ? defaultNamedLogo : undefined
)
namedLogoColor = coalesce(overrideLogoColor, serviceLogoColor)
}
logoWidth = coalesce(overrideLogoWidth, serviceLogoWidth)
logoPosition = coalesce(overrideLogoPosition, serviceLogoPosition)
}
if (namedLogo) {
logoSvgBase64 = prepareNamedLogo({
name: namedLogo,
color: namedLogoColor,
style,
})
}
return {
text: [
// Use `coalesce()` to support empty labels and messages, as in the
// static badge.
coalesce(overrideLabel, serviceLabel, defaultLabel, category),
coalesce(serviceMessage, 'n/a'),
],
color: coalesce(
// In case of an error, disregard user's color override.
isError ? undefined : overrideColor,
serviceColor,
defaultColor,
'lightgrey'
),
labelColor: coalesce(
// In case of an error, disregard user's color override.
isError ? undefined : overrideLabelColor,
serviceLabelColor,
defaultLabelColor
),
template: style,
namedLogo,
logo: logoSvgBase64,
logoWidth,
logoPosition,
links: toArray(overrideLink || serviceLink),
cacheLengthSeconds: coalesce(serviceCacheSeconds, defaultCacheSeconds),
}
}