Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
540064a
move logo auto size into badge-maker
jNullj Mar 15, 2025
395802e
move named logo base64 creation into badge-maker
jNullj Mar 15, 2025
687a443
remove old moved simple-icons helper files into badge-maker
jNullj Mar 15, 2025
b4fd0f0
remove legacy lib/ from dangerfile
jNullj Mar 15, 2025
a269245
remove /lib from test:core
jNullj Mar 15, 2025
9b7ad5a
remove unused logoWidth variable from coalesceBadge
jNullj Mar 15, 2025
6d20ca9
Merge branch 'master' into badge-maker-simple-icons
jNullj Apr 26, 2025
9bad701
move simple-icons as dev dependency
jNullj Apr 26, 2025
b6e26c2
badge-maker: add simple-icons as an optional dependency
jNullj Apr 26, 2025
67b86cc
implement error handling for optional dependencies
jNullj Apr 26, 2025
9335f36
fix: esm modules imports and defs
jNullj Apr 26, 2025
74f868c
dont throw err, only show warn msg
jNullj Apr 26, 2025
cdece06
Merge branch 'master' into badge-maker-simple-icons
jNullj Jun 28, 2025
a059c3c
rename mjs files to js in badge-maker
jNullj Jun 28, 2025
daa9ec6
fix badge-maker util paths
jNullj Jun 28, 2025
72e6c2f
fix simple-icons versions missed at merge
jNullj Jun 28, 2025
b6560ca
update tests for badge-maker simple-icon migration
jNullj Jun 28, 2025
c2d5fc0
remove badge-maker json tests
jNullj Jun 28, 2025
279bbaa
fix dynamic simple-icon optional dependency load
jNullj Jun 28, 2025
cf8f893
restore simple-icons as dependency of shields
jNullj Jun 28, 2025
a232ecc
fix coalesce badge tests
jNullj Jun 28, 2025
0b4719b
fix coalesce named logo tests color veriable name
jNullj Jun 28, 2025
022233e
fix logoSvg override test
jNullj Jun 28, 2025
ae466e9
remove old unrelevant comment
jNullj Jun 28, 2025
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
17 changes: 17 additions & 0 deletions badge-maker/lib/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class MissingOptionalDependencyError extends Error {
constructor(dependencyName) {
super(
`${dependencyName} is not installed. Please install it to use related features.`,
)
this.name = 'MissingOptionalDependencyError'
if (!MissingOptionalDependencyError.warnCreated) {
MissingOptionalDependencyError.warnCreated = {}
}
if (!MissingOptionalDependencyError.warnCreated[dependencyName]) {
console.warn(this.message)
MissingOptionalDependencyError.warnCreated[dependencyName] = true
}
}
}

export { MissingOptionalDependencyError }
54 changes: 53 additions & 1 deletion badge-maker/lib/make-badge.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@ import { normalizeColor, toSvgColor } from './color.js'
import badgeRenderers from './badge-renderers.js'
import { stripXmlWhitespace } from './xml.js'
import { DEFAULT_LOGO_HEIGHT } from './constants.js'
import { MissingOptionalDependencyError } from './errors.js'

let getIconSize
let prepareNamedLogo

try {
getIconSize = (await import('./simple-icons-utils/svg-helpers.js'))
.getIconSize
} catch (e) {
if (!(e instanceof MissingOptionalDependencyError)) {
throw e
}
}

try {
prepareNamedLogo = (await import('./simple-icons-utils/logos.js'))
.prepareNamedLogo
} catch (e) {
if (!(e instanceof MissingOptionalDependencyError)) {
throw e
}
}

/*
note: makeBadge() is fairly thinly wrapped so if we are making changes here
Expand All @@ -15,6 +37,8 @@ export default function makeBadge({
color,
labelColor,
logo,
namedLogo,
namedLogoColor,
logoSize,
logoWidth,
links = ['', ''],
Expand Down Expand Up @@ -46,7 +70,35 @@ export default function makeBadge({
throw new Error(`Unknown badge style: '${style}'`)
}

logoWidth = +logoWidth || (logo ? DEFAULT_LOGO_HEIGHT : 0)
// we assume logo overrides namedLogo
if (logoWidth) {
logoWidth = +logoWidth
} else if (logo) {
logoWidth = DEFAULT_LOGO_HEIGHT
} else if (namedLogo) {
let iconSize
if (getIconSize) {
iconSize = getIconSize(String(namedLogo).toLowerCase())
}
if (iconSize && logoSize === 'auto') {
logoWidth = (iconSize.width / iconSize.height) * DEFAULT_LOGO_HEIGHT
} else {
logoWidth = DEFAULT_LOGO_HEIGHT
}
} else {
logoWidth = 0
}

if (namedLogo && !logo) {
if (prepareNamedLogo) {
logo = prepareNamedLogo({
name: namedLogo,
color: namedLogoColor,
size: logoSize,
style,
})
}
}

return stripXmlWhitespace(
render({
Expand Down
54 changes: 54 additions & 0 deletions badge-maker/lib/make-badge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { expect } from 'chai'
import snapshot from 'snap-shot-it'
import prettier from 'prettier'
import makeBadge from './make-badge.js'
import { getSimpleIcon } from './simple-icons-utils/logos.js'

async function expectBadgeToMatchSnapshot(format) {
snapshot(await prettier.format(makeBadge(format), { parser: 'html' }))
Expand Down Expand Up @@ -759,4 +760,57 @@ describe('The badge generator', function () {
})
})
})

describe('Named logos', function () {
it('applies the named logo', function () {
const svgResult = makeBadge({
label: 'test',
message: 'npm',
namedLogo: 'npm',
format: 'svg',
})
const expectedLogo = getSimpleIcon({ name: 'npm' })
expect(svgResult).to.include(expectedLogo)
})

it('applies the named logo with color', function () {
const svgResult = makeBadge({
label: 'test',
message: 'dependabot',
namedLogo: 'dependabot',
namedLogoColor: 'blue',
format: 'svg',
})
const expectedLogo = getSimpleIcon({ name: 'dependabot', color: 'blue' })
expect(svgResult).to.include(expectedLogo)
})
})

describe('Custom logos', function () {
it('overrides the logo with custom svg', function () {
const logoSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxu'
const svgResult = makeBadge({
label: 'test',
message: 'custom',
logo: logoSvg,
namedLogo: 'appveyor',
format: 'svg',
})
expect(svgResult).to.include(logoSvg)
})
})

describe('Logo size', function () {
it('applies the logo size', function () {
const svgResult = makeBadge({
label: 'test',
message: 'auto-sized',
namedLogo: 'npm',
logoSize: 'auto',
format: 'svg',
})
const expectedLogo = getSimpleIcon({ name: 'npm', size: 'auto' })
expect(svgResult).to.include(expectedLogo)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import * as originalSimpleIcons from 'simple-icons'
import { MissingOptionalDependencyError } from '../errors.js'

let originalSimpleIcons
try {
originalSimpleIcons = await import('simple-icons')
} catch {
// only show warning on first import error
// don't throw an error here as its called from anonymous function
// eslint-disable-next-line no-unused-vars
const e = new MissingOptionalDependencyError('simple-icons')
}

function loadSimpleIcons() {
const simpleIcons = new Map()
Expand Down
12 changes: 6 additions & 6 deletions lib/logos.js → badge-maker/lib/simple-icons-utils/logos.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import Joi from 'joi'
import {
toSvgColor,
brightness,
normalizeColor,
} from '../badge-maker/lib/color.js'
import coalesce from '../core/base-service/coalesce.js'
import { toSvgColor, brightness, normalizeColor } from '../color.js'
import { svg2base64, getIconSize, resetIconPosition } from './svg-helpers.js'
import loadSimpleIcons from './load-simple-icons.js'
const simpleIcons = loadSimpleIcons()
Expand Down Expand Up @@ -123,6 +118,11 @@ function prepareNamedLogo({ name, color, style, size }) {
return getSimpleIcon({ name, color, style, size })
}

// copied from /core/base-service/coalesce.js
function coalesce(...candidates) {
return candidates.find(c => c !== undefined && c !== null)
}

function makeLogo(defaultNamedLogo, overrides) {
const maybeDataUrl = decodeDataUrlFromQueryParam(overrides.logo)
if (maybeDataUrl) {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 3 additions & 0 deletions badge-maker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
"anafanafo": "2.0.0",
"css-color-converter": "^2.0.0"
},
"optionalDependencies": {
"simple-icons": "15.2.0"
},
"scripts": {
"test": "echo 'Run tests from parent dir'; false"
}
Expand Down
26 changes: 4 additions & 22 deletions core/base-service/coalesce-badge.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import {
decodeDataUrlFromQueryParam,
prepareNamedLogo,
} from '../../lib/logos.js'
import { svg2base64, getIconSize } from '../../lib/svg-helpers.js'
import { DEFAULT_LOGO_HEIGHT } from '../../badge-maker/lib/constants.js'
import { decodeDataUrlFromQueryParam } from '../../badge-maker/lib/simple-icons-utils/logos.js'
import { svg2base64 } from '../../badge-maker/lib/simple-icons-utils/svg-helpers.js'
import coalesce from './coalesce.js'
import toArray from './to-array.js'

Expand Down Expand Up @@ -110,7 +106,7 @@ export default function coalesceBadge(
style = 'flat'
}

let namedLogo, namedLogoColor, logoSize, logoWidth, logoSvgBase64
let namedLogo, namedLogoColor, logoSize, logoSvgBase64
if (overrideLogo) {
// `?logo=` could be a named logo or encoded svg.
const overrideLogoSvgBase64 = decodeDataUrlFromQueryParam(overrideLogo)
Expand All @@ -137,20 +133,6 @@ export default function coalesceBadge(
}
logoSize = coalesce(overrideLogoSize, serviceLogoSize)
}
if (namedLogo) {
const iconSize = getIconSize(String(namedLogo).toLowerCase())

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

logoSvgBase64 = prepareNamedLogo({
name: namedLogo,
color: namedLogoColor,
size: logoSize,
style,
})
}

const badgeData = {
// Use `coalesce()` to support empty labels and messages, as in the static
Expand All @@ -172,8 +154,8 @@ export default function coalesceBadge(
),
style,
namedLogo,
namedLogoColor,
logo: logoSvgBase64,
logoWidth,
logoSize,
links: toArray(overrideLink || serviceLink),
cacheLengthSeconds: coalesce(serviceCacheSeconds, defaultCacheSeconds),
Expand Down
66 changes: 25 additions & 41 deletions core/base-service/coalesce-badge.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { expect } from 'chai'
import { getSimpleIcon } from '../../lib/logos.js'
import coalesceBadge from './coalesce-badge.js'

describe('coalesceBadge', function () {
Expand Down Expand Up @@ -165,38 +164,20 @@ describe('coalesceBadge', function () {

describe('Named logos', function () {
it('when not a social badge, ignores the default named logo', function () {
expect(coalesceBadge({}, {}, { namedLogo: 'appveyor' }).logo).to.be
expect(coalesceBadge({}, {}, { namedLogo: 'appveyor' }).namedLogo).to.be
.undefined
})

it('when a social badge, uses the default named logo', function () {
// .not.be.empty for confidence that nothing has changed with `getSimpleIcon()`.
expect(
coalesceBadge({ style: 'social' }, {}, { namedLogo: 'appveyor' }).logo,
).to.equal(getSimpleIcon({ name: 'appveyor' })).and.not.be.empty
})

it('applies the named logo', function () {
expect(coalesceBadge({}, { namedLogo: 'npm' }, {})).to.include({
namedLogo: 'npm',
})
expect(coalesceBadge({}, { namedLogo: 'npm' }, {}).logo).to.equal(
getSimpleIcon({ name: 'npm' }),
).and.not.to.be.empty
})

it('applies the named logo with color', function () {
expect(
coalesceBadge({}, { namedLogo: 'dependabot', logoColor: 'blue' }, {})
.logo,
).to.equal(getSimpleIcon({ name: 'dependabot', color: 'blue' })).and.not
.to.be.empty
coalesceBadge({ style: 'social' }, {}, { namedLogo: 'appveyor' }),
).to.include({ namedLogo: 'appveyor' })
})

it('overrides the logo', function () {
expect(
coalesceBadge({ logo: 'npm' }, { namedLogo: 'appveyor' }, {}).logo,
).to.equal(getSimpleIcon({ name: 'npm' })).and.not.be.empty
coalesceBadge({ logo: 'npm' }, { namedLogo: 'appveyor' }, {}),
).to.include({ namedLogo: 'npm' })
})

it('overrides the logo with a color', function () {
Expand All @@ -205,9 +186,11 @@ describe('coalesceBadge', function () {
{ logo: 'dependabot', logoColor: 'blue' },
{ namedLogo: 'appveyor' },
{},
).logo,
).to.equal(getSimpleIcon({ name: 'dependabot', color: 'blue' })).and.not
.be.empty
),
).to.include({
namedLogo: 'dependabot',
namedLogoColor: 'blue',
})
})

it("when the logo is overridden, it ignores the service's logo color and width", function () {
Expand All @@ -219,8 +202,12 @@ describe('coalesceBadge', function () {
logoColor: 'red',
},
{},
).logo,
).to.equal(getSimpleIcon({ name: 'npm' })).and.not.be.empty
),
)
.to.include({ namedLogo: 'npm' })
.and.not.include({
namedLogoColor: 'red',
})
})

it("overrides the service logo's color", function () {
Expand All @@ -229,17 +216,20 @@ describe('coalesceBadge', function () {
{ logoColor: 'blue' },
{ namedLogo: 'dependabot', logoColor: 'red' },
{},
).logo,
).to.equal(getSimpleIcon({ name: 'dependabot', color: 'blue' })).and.not
.be.empty
),
).to.include({
namedLogo: 'dependabot',
namedLogoColor: 'blue',
})
})

// https://github.com/badges/shields/issues/2998
it('overrides logoSvg', function () {
const logoSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxu'
expect(coalesceBadge({ logo: 'npm' }, { logoSvg }, {}).logo).to.equal(
getSimpleIcon({ name: 'npm' }),
).and.not.be.empty
expect(coalesceBadge({ logo: 'npm' }, { logoSvg }, {})).to.include({
namedLogo: 'npm',
logo: undefined,
})
})
})

Expand Down Expand Up @@ -269,12 +259,6 @@ describe('coalesceBadge', function () {
logoSize: 'auto',
})
})

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

describe('Links', function () {
Expand Down
Loading
Loading