Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor badge color functions #2742

Merged
merged 16 commits into from
Jan 15, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions doc/service-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,6 @@ static render({ status, result }) {
We can also use nock to intercept API calls to return a known response body.

```js
const { colorScheme } = require('../test-helpers')

t.create('Build passed (mocked)')
.get('/build/wercker/go-wercker-api.json?style=_shields_test')
.intercept(nock =>
Expand All @@ -241,7 +239,7 @@ t.create('Build passed (mocked)')
.expectJSON({
name: 'build',
value: 'passing',
colorB: colorScheme.brightgreen,
color: 'brightgreen',
})

t.create('Build failed (mocked)')
Expand Down
80 changes: 53 additions & 27 deletions gh-badges/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const bf = new BadgeFactory()

const format = {
text: ['build', 'passed'],
colorscheme: 'green',
color: 'green',
template: 'flat',
}

Expand All @@ -44,41 +44,67 @@ The format is the following:

format: 'svg', // Also supports json

colorscheme: 'green',
// or ...
colorA: '#555',
colorB: '#4c1',
color: '#4c1',
labelColor: '#555',

// See templates/ for a list of available templates.
// Each offers a different visual design.
template: 'flat',

// Deprecated attributes:
colorscheme: 'green', // Now an alias for `color`.
colorB: '#4c1', // Now an alias for `color`.
colorA: '#555', // Now an alias for `labelColor`.
}
```

### See also

- [colorscheme.json](./lib/colorscheme.json) for the `colorscheme` option
- [templates/](./templates) for the `template` option

## Defaults

If you want to use a colorscheme, head to `lib/colorscheme.json`. Each scheme
has a name and a [CSS/SVG color][] for the color used in the first box (for the
first piece of text, field `colorA`) and for the one used in the second box
(field `colorB`).

## Colors

There are three ways to specify `color` and `labelColor`:

1. One of the [Shields named colors](./lib/color.js):

- ![][brightgreen]
- ![][green]
- ![][yellow]
- ![][yellowgreen]
- ![][orange]
- ![][red]
- ![][blue]
- ![][grey] ![][gray] – the default `labelColor`
- ![][lightgrey] ![][lightgray] – the default `color`

2. A three- or six-character hex color, optionally prefixed with `#`:

- ![][4c1]
- ![][#007fff]
- etc.

3. [Any valid CSS color][css color], e.g.

- `rgb(...)`, `rgba(...)`
- `hsl(...)`, `hsla(...)`
- ![][aqua] ![][fuchsia] ![][lightslategray] etc.

[brightgreen]: https://img.shields.io/badge/brightgreen-brightgreen.svg
[green]: https://img.shields.io/badge/green-green.svg
[yellow]: https://img.shields.io/badge/yellow-yellow.svg
[yellowgreen]: https://img.shields.io/badge/yellowgreen-yellowgreen.svg
[orange]: https://img.shields.io/badge/orange-orange.svg
[red]: https://img.shields.io/badge/red-red.svg
[blue]: https://img.shields.io/badge/blue-blue.svg
[grey]: https://img.shields.io/badge/grey-grey.svg
[gray]: https://img.shields.io/badge/gray-gray.svg
[lightgrey]: https://img.shields.io/badge/lightgrey-lightgrey.svg
[lightgray]: https://img.shields.io/badge/lightgray-lightgray.svg
[4c1]: https://img.shields.io/badge/4c1-4c1.svg
[#007fff]: https://img.shields.io/badge/%23007fff-007fff.svg
[aqua]: https://img.shields.io/badge/aqua-aqua.svg
[fuchsia]: https://img.shields.io/badge/fuchsia-fuchsia.svg
[lightslategray]: https://img.shields.io/badge/lightslategray-lightslategray.svg
[css color]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
[css/svg color]: http://www.w3.org/TR/SVG/types.html#DataTypeColor

```js
"green": {
"colorB": "#4c1"
}
```

Both `colorA` and `colorB` have default values. Usually, the first box uses the
same dark grey, so you can rely on that default value by not providing a
`"colorA"` field (such as above).

You can also use the `"colorA"` and `"colorB"` fields directly in the badges if
you don't want to make a color scheme for it. In that case, remove the
`"colorscheme"` field altogether.
6 changes: 3 additions & 3 deletions gh-badges/lib/badge-cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

const makeBadge = require('./make-badge')
const svg2img = require('./svg-to-img')
const colorscheme = require('./colorscheme.json')
const { namedColors } = require('./color')

if (process.argv.length < 4) {
console.log('Usage: badge subject status [:colorscheme] [.output] [@style]')
paulmelnikow marked this conversation as resolved.
Show resolved Hide resolved
console.log(
'Or: badge subject status right-color [left-color] [.output] [@style]'
)
console.log()
console.log(` colorscheme: one of ${Object.keys(colorscheme).join(', ')}.`)
console.log(` colorscheme: one of ${Object.keys(namedColors).join(', ')}.`)
console.log(' left-color, right-color:')
console.log(' #xxx (three hex digits)')
console.log(' #xxxxxx (six hex digits)')
Expand Down Expand Up @@ -53,7 +53,7 @@ if (style) {

if (color[0] === ':') {
color = color.slice(1)
if (colorscheme[color] == null) {
if (namedColors[color] == null) {
// Colorscheme not found.
console.error('Invalid color scheme.')
process.exit(1)
Expand Down
49 changes: 49 additions & 0 deletions gh-badges/lib/color.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict'

const isCSSColor = require('is-css-color')

// When updating these, be sure also to update the list in `gh-badges/README.md`.
const namedColors = {
brightgreen: '#4c1',
green: '#97CA00',
yellow: '#dfb317',
yellowgreen: '#a4a61d',
orange: '#fe7d37',
red: '#e05d44',
blue: '#007ec6',
grey: '#555',
gray: '#555',
lightgrey: '#9f9f9f',
lightgray: '#9f9f9f',
}

const hexColorRegex = /^([\da-f]{3}){1,2}$/i
calebcartwright marked this conversation as resolved.
Show resolved Hide resolved
function isHexColor(s = '') {
return hexColorRegex.test(s.toLowerCase())
}

function normalizeColor(color) {
if (color === undefined) {
return undefined
} else if (color in namedColors) {
return color
} else if (isHexColor(color)) {
return `#${color.toLowerCase()}`
} else if (isCSSColor(color)) {
return color.toLowerCase()
} else {
return undefined
}
}

function toSvgColor(color) {
const normalized = normalizeColor(color)
return normalized in namedColors ? namedColors[color] : normalized
}

module.exports = {
namedColors,
isHexColor,
normalizeColor,
toSvgColor,
}
37 changes: 37 additions & 0 deletions gh-badges/lib/color.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict'

const { test, given, forCases } = require('sazerac')
const { isHexColor, normalizeColor, toSvgColor } = require('./color')

test(isHexColor, () => {
forCases([given('f00bae'), given('4c1'), given('ABC123')]).expect(true)
forCases([given('f00bar'), given(''), given(undefined)]).expect(false)
})

test(normalizeColor, () => {
given('red').expect('red')
given('blue').expect('blue')
given('4c1').expect('#4c1')
given('f00f00').expect('#f00f00')
given('ABC123').expect('#abc123')
given('#ABC123').expect('#abc123')
given('papayawhip').expect('papayawhip')
given('purple').expect('purple')
forCases([given(''), given(undefined), given('not-a-color')]).expect(
undefined
)
})

test(toSvgColor, () => {
given('red').expect('#e05d44')
given('blue').expect('#007ec6')
given('4c1').expect('#4c1')
given('f00f00').expect('#f00f00')
given('ABC123').expect('#abc123')
given('#ABC123').expect('#abc123')
given('papayawhip').expect('papayawhip')
given('purple').expect('purple')
forCases([given(''), given(undefined), given('not-a-color')]).expect(
undefined
)
})
13 changes: 0 additions & 13 deletions gh-badges/lib/colorscheme.json

This file was deleted.

33 changes: 11 additions & 22 deletions gh-badges/lib/make-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const path = require('path')
const SVGO = require('svgo')
const dot = require('dot')
const anafanafo = require('anafanafo')
const isCSSColor = require('is-css-color')
const { normalizeColor, toSvgColor } = require('./color')

// cache templates.
const templates = {}
Expand Down Expand Up @@ -92,26 +92,15 @@ function capitalize(s) {
return s.charAt(0).toUpperCase() + s.slice(1)
}

// check if colorA/B is a colorscheme else check if it's a valid css3 color else return undefined and let the badge assign the default color
function assignColor(color = '', colorschemeType = 'colorB') {
if (definedColorschemes[color] !== undefined) {
return definedColorschemes[color][colorschemeType] || undefined
} else if (isCSSColor(color)) {
return color
} else {
return undefined
}
}

const definedColorschemes = require(path.join(__dirname, 'colorscheme.json'))

function makeBadge({
format,
template,
text,
colorscheme,
color,
colorA,
colorB,
labelColor,
logo,
logoPosition,
logoWidth,
Expand Down Expand Up @@ -142,12 +131,6 @@ function makeBadge({
text = text.map(value => value.toUpperCase())
}

// colorA/B have a higher priority than colorscheme
colorA = colorA || colorscheme || undefined
colorB = colorB || colorscheme || undefined
colorA = assignColor(colorA, 'colorA')
colorB = assignColor(colorB, 'colorB')

const [left, right] = text
let leftWidth = (anafanafo(left) / 10) | 0
// Increase chances of pixel grid alignment.
Expand All @@ -169,6 +152,9 @@ function makeBadge({
logoPadding = logo ? 3 : 0
}

color = color || colorB || colorscheme
labelColor = labelColor || colorA

const context = {
text: [left, right],
escapedText: text.map(escapeXml),
Expand All @@ -178,8 +164,11 @@ function makeBadge({
logoPosition,
logoWidth,
logoPadding,
colorA,
colorB,
// `color` and `labelColor` are included for the `_shields_test` template.
color: normalizeColor(color),
labelColor: normalizeColor(labelColor),
colorA: toSvgColor(labelColor),
colorB: toSvgColor(color),
escapeXml,
}

Expand Down
Loading