diff --git a/badge-maker/README.md b/badge-maker/README.md index bb6ec1378c94d..5a8c50631ebb0 100644 --- a/badge-maker/README.md +++ b/badge-maker/README.md @@ -67,6 +67,8 @@ The format is the following: message: 'passed', // (Required) Badge message labelColor: '#555', // (Optional) Label color color: '#4c1', // (Optional) Message color + logoBase64: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2NCIgaGVpZ2h0PSI2NCI+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iOCIgZmlsbD0iI2IxY2U1NiIvPjxwYXRoIGQ9Ik04IDBoMjR2NjRIOGMtNC40MzIgMC04LTMuNTY4LTgtOFY4YzAtNC40MzIgMy41NjgtOCA4LTh6IiBmaWxsPSIjNWQ1ZDVkIi8+PC9zdmc+' // (Optional) Any custom logo can be passed in a URL parameter by base64 encoding + links: ['https://example.com', 'https://example.com'], // (Optional) Links array of maximum two links // (Optional) One of: 'plastic', 'flat', 'flat-square', 'for-the-badge' or 'social' // Each offers a different visual design. diff --git a/badge-maker/index.d.ts b/badge-maker/index.d.ts index 38d71e22b8344..5a1b6872ebe81 100644 --- a/badge-maker/index.d.ts +++ b/badge-maker/index.d.ts @@ -4,6 +4,8 @@ interface Format { labelColor?: string color?: string style?: 'plastic' | 'flat' | 'flat-square' | 'for-the-badge' | 'social' + logoBase64?: string + links?: Array } export declare class ValidationError extends Error {} diff --git a/badge-maker/lib/badge-renderers.js b/badge-maker/lib/badge-renderers.js index af726101e0819..8c76899e6a438 100644 --- a/badge-maker/lib/badge-renderers.js +++ b/badge-maker/lib/badge-renderers.js @@ -3,6 +3,7 @@ const anafanafo = require('anafanafo') const { brightness } = require('./color') const { XmlElement, ElementList } = require('./xml') +const { DEFAULT_LOGO_HEIGHT } = require('./constants') // https://github.com/badges/shields/pull/1132 const FONT_SCALE_UP_FACTOR = 10 @@ -53,7 +54,7 @@ function shouldWrapBodyWithLink({ links }) { } function getLogoElement({ logo, horizPadding, badgeHeight, logoWidth }) { - const logoHeight = 14 + const logoHeight = DEFAULT_LOGO_HEIGHT if (!logo) return '' return new XmlElement({ name: 'image', diff --git a/badge-maker/lib/index.js b/badge-maker/lib/index.js index 051c3d84e9c7b..eb38c01a999a6 100644 --- a/badge-maker/lib/index.js +++ b/badge-maker/lib/index.js @@ -16,13 +16,30 @@ function _validate(format) { throw new ValidationError('Field `message` is required') } - const stringFields = ['labelColor', 'color', 'message', 'label'] + const stringFields = ['labelColor', 'color', 'message', 'label', 'logoBase64'] stringFields.forEach(function (field) { if (field in format && typeof format[field] !== 'string') { throw new ValidationError(`Field \`${field}\` must be of type string`) } }) + if ('links' in format) { + if (!Array.isArray(format.links)) { + throw new ValidationError('Field `links` must be an array of strings') + } else { + if (format.links.length > 2) { + throw new ValidationError( + 'Field `links` must not have more than 2 elements', + ) + } + format.links.forEach(function (field) { + if (typeof field !== 'string') { + throw new ValidationError('Field `links` must be an array of strings') + } + }) + } + } + const styleValues = [ 'plastic', 'flat', @@ -38,7 +55,15 @@ function _validate(format) { } function _clean(format) { - const expectedKeys = ['label', 'message', 'labelColor', 'color', 'style'] + const expectedKeys = [ + 'label', + 'message', + 'labelColor', + 'color', + 'style', + 'logoBase64', + 'links', + ] const cleaned = {} Object.keys(format).forEach(key => { @@ -65,7 +90,9 @@ function _clean(format) { * @param {string} format.message (Required) Badge message (e.g: 'passing') * @param {string} format.labelColor (Optional) Label color * @param {string} format.color (Optional) Message color - * @param {string} format.style (Optional) Visual style e.g: 'flat' + * @param {string} format.style (Optional) Visual style (e.g: 'flat') + * @param {string} format.logoBase64 (Optional) Logo data URL + * @param {Array} format.links (Optional) Links array (e.g: ['https://example.com', 'https://example.com']) * @returns {string} Badge in SVG format * @see https://github.com/badges/shields/tree/master/badge-maker/README.md */ diff --git a/badge-maker/lib/index.spec.js b/badge-maker/lib/index.spec.js index 839aa061e4ff1..2f1ab6862a9c1 100644 --- a/badge-maker/lib/index.spec.js +++ b/badge-maker/lib/index.spec.js @@ -25,6 +25,17 @@ describe('makeBadge function', function () { style: 'flat', }), ).to.satisfy(isSvg) + expect( + makeBadge({ + label: 'build', + message: 'passed', + color: 'green', + style: 'flat', + labelColor: 'blue', + logoBase64: 'data:image/svg+xml;base64,PHN2ZyB4bWxu', + links: ['https://example.com', 'https://example.com'], + }), + ).to.satisfy(isSvg) }) it('should throw a ValidationError with invalid inputs', function () { @@ -46,6 +57,21 @@ describe('makeBadge function', function () { expect(() => makeBadge({ label: 'build', message: 'passed', labelColor: 7 }), ).to.throw(ValidationError, 'Field `labelColor` must be of type string') + expect(() => + makeBadge({ label: 'build', message: 'passed', logoBase64: 7 }), + ).to.throw(ValidationError, 'Field `logoBase64` must be of type string') + expect(() => + makeBadge({ label: 'build', message: 'passed', links: 'test' }), + ).to.throw(ValidationError, 'Field `links` must be an array of strings') + expect(() => + makeBadge({ label: 'build', message: 'passed', links: [1] }), + ).to.throw(ValidationError, 'Field `links` must be an array of strings') + expect(() => + makeBadge({ label: 'build', message: 'passed', links: ['1', '2', '3'] }), + ).to.throw( + ValidationError, + 'Field `links` must not have more than 2 elements', + ) expect(() => makeBadge({ label: 'build', message: 'passed', format: 'png' }), ).to.throw(ValidationError, "Unexpected field 'format'") diff --git a/badge-maker/lib/make-badge.js b/badge-maker/lib/make-badge.js index bb96c62867c9c..e1bb54bfcbca8 100644 --- a/badge-maker/lib/make-badge.js +++ b/badge-maker/lib/make-badge.js @@ -17,9 +17,7 @@ module.exports = function makeBadge({ color, labelColor, logo, - logoPosition, logoSize, - logoWidth, links = ['', ''], }) { // String coercion and whitespace removal. @@ -31,7 +29,6 @@ module.exports = function makeBadge({ return JSON.stringify({ label, message, - logoWidth, // Only call normalizeColor for the JSON case: this is handled // internally by toSvgColor in the SVG case. color: normalizeColor(color), @@ -47,16 +44,13 @@ module.exports = function makeBadge({ throw new Error(`Unknown badge style: '${style}'`) } - logoWidth = +logoWidth || (logo ? DEFAULT_LOGO_HEIGHT : 0) - return stripXmlWhitespace( render({ label, message, links, logo, - logoPosition, - logoWidth, + logoWidth: logo ? DEFAULT_LOGO_HEIGHT : 0, logoSize, logoPadding: logo && label.length ? 3 : 0, color: toSvgColor(color),