Skip to content

Commit

Permalink
feat(logos): support auto-sizing mode
Browse files Browse the repository at this point in the history
  • Loading branch information
LitoMore committed Apr 3, 2024
1 parent 10b2f88 commit d4fafe3
Show file tree
Hide file tree
Showing 15 changed files with 154 additions and 38 deletions.
5 changes: 5 additions & 0 deletions badge-maker/lib/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const DEFAULT_LOGO_HEIGHT = 14

module.exports = {
DEFAULT_LOGO_HEIGHT,
}
5 changes: 4 additions & 1 deletion badge-maker/lib/make-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { normalizeColor, toSvgColor } = require('./color')
const badgeRenderers = require('./badge-renderers')
const { stripXmlWhitespace } = require('./xml')
const { DEFAULT_LOGO_HEIGHT } = require('./constants')

/*
note: makeBadge() is fairly thinly wrapped so if we are making changes here
Expand All @@ -17,6 +18,7 @@ module.exports = function makeBadge({
labelColor,
logo,
logoPosition,
logoSize,
logoWidth,
links = ['', ''],
}) {
Expand Down Expand Up @@ -45,7 +47,7 @@ module.exports = function makeBadge({
throw new Error(`Unknown badge style: '${style}'`)
}

logoWidth = +logoWidth || (logo ? 14 : 0)
logoWidth = +logoWidth || (logo ? DEFAULT_LOGO_HEIGHT : 0)

return stripXmlWhitespace(
render({
Expand All @@ -55,6 +57,7 @@ module.exports = function makeBadge({
logo,
logoPosition,
logoWidth,
logoSize,
logoPadding: logo && label.length ? 3 : 0,
color: toSvgColor(color),
labelColor: toSvgColor(labelColor),
Expand Down
1 change: 1 addition & 0 deletions core/base-service/base.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ describe('BaseService', function () {
namedLogo: undefined,
logo: undefined,
logoWidth: undefined,
logoSize: undefined,
logoPosition: undefined,
links: [],
labelColor: undefined,
Expand Down
22 changes: 20 additions & 2 deletions core/base-service/coalesce-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
decodeDataUrlFromQueryParam,
prepareNamedLogo,
} from '../../lib/logos.js'
import { svg2base64 } from '../../lib/svg-helpers.js'
import { svg2base64, getIconSize } from '../../lib/svg-helpers.js'
import { DEFAULT_LOGO_HEIGHT } from '../../badge-maker/lib/constants.js'
import coalesce from './coalesce.js'
import toArray from './to-array.js'

Expand Down Expand Up @@ -56,6 +57,7 @@ export default function coalesceBadge(
let {
logoWidth: overrideLogoWidth,
logoPosition: overrideLogoPosition,
logoSize: overrideLogoSize,
color: overrideColor,
labelColor: overrideLabelColor,
} = overrides
Expand Down Expand Up @@ -87,6 +89,7 @@ export default function coalesceBadge(
logoSvg: serviceLogoSvg,
namedLogo: serviceNamedLogo,
logoColor: serviceLogoColor,
logoSize: serviceLogoSize,
logoWidth: serviceLogoWidth,
logoPosition: serviceLogoPosition,
link: serviceLink,
Expand Down Expand Up @@ -119,7 +122,12 @@ export default function coalesceBadge(
style = 'flat'
}

let namedLogo, namedLogoColor, logoWidth, logoPosition, logoSvgBase64
let namedLogo,
namedLogoColor,
logoSize,
logoWidth,
logoPosition,
logoSvgBase64
if (overrideLogo) {
// `?logo=` could be a named logo or encoded svg.
const overrideLogoSvgBase64 = decodeDataUrlFromQueryParam(overrideLogo)
Expand All @@ -133,6 +141,7 @@ export default function coalesceBadge(
}
// If the logo has been overridden it does not make sense to inherit the
// original width or position.
logoSize = overrideLogoSize
logoWidth = overrideLogoWidth
logoPosition = overrideLogoPosition
} else {
Expand All @@ -145,13 +154,21 @@ export default function coalesceBadge(
)
namedLogoColor = coalesce(overrideLogoColor, serviceLogoColor)
}
logoSize = coalesce(overrideLogoSize, serviceLogoSize)
logoWidth = coalesce(overrideLogoWidth, serviceLogoWidth)
logoPosition = coalesce(overrideLogoPosition, serviceLogoPosition)
}
if (namedLogo) {
const iconSize = getIconSize(String(namedLogo).toLowerCase())

if (!logoWidth && iconSize && logoSize === 'auto') {
logoWidth = (iconSize.width / iconSize.height) * DEFAULT_LOGO_HEIGHT
}

logoSvgBase64 = prepareNamedLogo({
name: namedLogo,
color: namedLogoColor,
size: logoSize,
style,
})
}
Expand Down Expand Up @@ -179,6 +196,7 @@ export default function coalesceBadge(
logo: logoSvgBase64,
logoWidth,
logoPosition,
logoSize,
links: toArray(overrideLink || serviceLink),
cacheLengthSeconds: coalesce(serviceCacheSeconds, defaultCacheSeconds),
}
Expand Down
14 changes: 14 additions & 0 deletions core/base-service/coalesce-badge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,20 @@ describe('coalesceBadge', function () {
})
})

describe('Logo size', function () {
it('overrides the logoSize', function () {
expect(coalesceBadge({ logoSize: 'auto' }, {}, {})).to.include({
logoSize: 'auto',
})
})

it('applies the logo size', function () {
expect(
coalesceBadge({}, { namedLogo: 'npm', logoSize: 'auto' }, {}),
).to.include({ logoSize: 'auto' })
})
})

describe('Logo width', function () {
it('overrides the logoWidth', function () {
expect(coalesceBadge({ logoWidth: 20 }, {}, {})).to.include({
Expand Down
12 changes: 12 additions & 0 deletions core/base-service/openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const globalParamRefs = [
{ $ref: '#/components/parameters/style' },
{ $ref: '#/components/parameters/logo' },
{ $ref: '#/components/parameters/logoColor' },
{ $ref: '#/components/parameters/logoSize' },
{ $ref: '#/components/parameters/label' },
{ $ref: '#/components/parameters/labelColor' },
{ $ref: '#/components/parameters/color' },
Expand Down Expand Up @@ -140,6 +141,17 @@ function category2openapi({ category, services, sort = false }) {
},
example: 'violet',
},
logoSize: {
name: 'logoSize',
in: 'query',
required: false,
description:
"Make icons adaptively resize by setting `auto`. It's useful for some wider logos like `amd` and `amg`.",
schema: {
type: 'string',
},
example: 'auto',
},
label: {
name: 'label',
in: 'query',
Expand Down
13 changes: 13 additions & 0 deletions core/base-service/openapi.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ const expected = {
schema: { type: 'string' },
example: 'violet',
},
logoSize: {
name: 'logoSize',
in: 'query',
required: false,
description:
"Make icons adaptively resize by setting `auto`. It's useful for some wider logos like `amd` and `amg`.",
schema: {
type: 'string',
},
example: 'auto',
},
label: {
name: 'label',
in: 'query',
Expand Down Expand Up @@ -158,6 +169,7 @@ const expected = {
{ $ref: '#/components/parameters/style' },
{ $ref: '#/components/parameters/logo' },
{ $ref: '#/components/parameters/logoColor' },
{ $ref: '#/components/parameters/logoSize' },
{ $ref: '#/components/parameters/label' },
{ $ref: '#/components/parameters/labelColor' },
{ $ref: '#/components/parameters/color' },
Expand Down Expand Up @@ -213,6 +225,7 @@ const expected = {
{ $ref: '#/components/parameters/style' },
{ $ref: '#/components/parameters/logo' },
{ $ref: '#/components/parameters/logoColor' },
{ $ref: '#/components/parameters/logoSize' },
{ $ref: '#/components/parameters/label' },
{ $ref: '#/components/parameters/labelColor' },
{ $ref: '#/components/parameters/color' },
Expand Down
9 changes: 4 additions & 5 deletions lib/load-simple-icons.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as originalSimpleIcons from 'simple-icons/icons'
import { svg2base64 } from './svg-helpers.js'

function loadSimpleIcons() {
const simpleIcons = {}
Expand All @@ -16,10 +15,10 @@ function loadSimpleIcons() {
const icon = originalSimpleIcons[key]
const { title, slug, hex } = icon

icon.base64 = {
default: svg2base64(icon.svg.replace('<svg', `<svg fill="#${hex}"`)),
light: svg2base64(icon.svg.replace('<svg', '<svg fill="whitesmoke"')),
dark: svg2base64(icon.svg.replace('<svg', '<svg fill="#333"')),
icon.styles = {
default: icon.svg.replace('<svg', `<svg fill="#${hex}"`),
light: icon.svg.replace('<svg', '<svg fill="whitesmoke"'),
dark: icon.svg.replace('<svg', '<svg fill="#333"'),
}

// There are a few instances where multiple icons have the same title
Expand Down
2 changes: 1 addition & 1 deletion lib/load-simple-icons.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe('loadSimpleIcons', function () {
})

it('prepares three color themes', function () {
expect(simpleIcons.sentry.base64).to.have.all.keys(
expect(simpleIcons.sentry.styles).to.have.all.keys(
'default',
'light',
'dark',
Expand Down
31 changes: 23 additions & 8 deletions lib/logos.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
normalizeColor,
} from '../badge-maker/lib/color.js'
import coalesce from '../core/base-service/coalesce.js'
import { svg2base64 } from './svg-helpers.js'
import { svg2base64, getIconSize, resetIconPosition } from './svg-helpers.js'
import loadLogos from './load-logos.js'
import loadSimpleIcons from './load-simple-icons.js'
const logos = loadLogos()
Expand Down Expand Up @@ -88,25 +88,38 @@ function getSimpleIconStyle({ icon, style }) {
return 'default'
}

function getSimpleIcon({ name, color, style }) {
function getSimpleIcon({ name, color, style, size }) {
const key = name === 'travis' ? 'travis-ci' : name.replace(/ /g, '-')

if (!(key in simpleIcons)) {
return undefined
}

let iconSvg

const svgColor = toSvgColor(color)
if (svgColor) {
return svg2base64(
simpleIcons[key].svg.replace('<svg', `<svg fill="${svgColor}"`),
)
iconSvg = simpleIcons[key].svg.replace('<svg', `<svg fill="${svgColor}"`)
} else {
const iconStyle = getSimpleIconStyle({ icon: simpleIcons[key], style })
return simpleIcons[key].base64[iconStyle]
iconSvg = simpleIcons[key].styles[iconStyle]
}

if (size === 'auto') {
const { width: iconWidth, height: iconHeight } = getIconSize(key)

if (iconWidth > iconHeight) {
const path = resetIconPosition(simpleIcons[key].path)
iconSvg = iconSvg
.replace('viewBox="0 0 24 24"', `viewBox="0 0 24 ${iconHeight}"`)
.replace(/<path d=".*"\/>/, `<path d="${path}"/>`)
}
}

return svg2base64(iconSvg)
}

function prepareNamedLogo({ name, color, style }) {
function prepareNamedLogo({ name, color, style, size }) {
if (typeof name !== 'string') {
return undefined
}
Expand All @@ -118,7 +131,8 @@ function prepareNamedLogo({ name, color, style }) {
}

return (
getShieldsIcon({ name, color }) || getSimpleIcon({ name, color, style })
getShieldsIcon({ name, color }) ||
getSimpleIcon({ name, color, style, size })
)
}

Expand All @@ -131,6 +145,7 @@ function makeLogo(defaultNamedLogo, overrides) {
name: coalesce(overrides.logo, defaultNamedLogo),
color: overrides.logoColor,
style: overrides.style,
size: overrides.logoSize,
})
}
}
Expand Down
33 changes: 32 additions & 1 deletion lib/svg-helpers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
import SVGPathCommander from 'svg-path-commander'
import loadSimpleIcons from './load-simple-icons.js'

function svg2base64(svg) {
return `data:image/svg+xml;base64,${Buffer.from(svg.trim()).toString(
'base64',
)}`
}

export { svg2base64 }
function getIconSize(iconKey) {
const simpleIcons = loadSimpleIcons()

if (!(iconKey in simpleIcons)) {
return undefined
}

const {
width,
height,
x: x0,
y: y0,
x2: x1,
y2: y1,
} = SVGPathCommander.getPathBBox(simpleIcons[iconKey].path)

return { width, height, x0, y0, x1, y1 }
}

function resetIconPosition(path) {
const { x: offsetX, y: offsetY } = SVGPathCommander.getPathBBox(path)
const pathReset = new SVGPathCommander(path)
.transform({ translate: [-offsetX, -offsetY] })
.toString()

return pathReset
}

export { svg2base64, getIconSize, resetIconPosition }
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"semver": "~7.6.0",
"simple-icons": "11.10.0",
"smol-toml": "1.1.4",
"svg-path-commander": "^2.0.9",
"webextension-store-meta": "^1.1.0",
"xpath": "~0.0.34"
},
Expand Down
Loading

0 comments on commit d4fafe3

Please sign in to comment.