diff --git a/core/badge-urls/make-badge-url.js b/core/badge-urls/make-badge-url.js index 3fd23042e6d56e3e187f1e6ea3ae489cae558314..f6e891ac3fa44b18d7f3c282cf2201abc7c7e13a 100644 --- a/core/badge-urls/make-badge-url.js +++ b/core/badge-urls/make-badge-url.js @@ -71,6 +71,36 @@ function staticBadgeUrl({ return `${baseUrl}/badge/${path}.${format}${suffix}` } +function queryStringStaticBadgeUrl({ + baseUrl = '', + label, + message, + color, + labelColor, + style, + namedLogo, + logoColor, + logoWidth, + logoPosition, + format = 'svg', +}) { + // schemaVersion could be a parameter if we iterate on it, + // for now it's hardcoded to the only supported version. + const schemaVersion = '1' + const suffix = `?${queryString.stringify({ + label, + message, + color, + labelColor, + style, + logo: namedLogo, + logoColor, + logoWidth, + logoPosition, + })}` + return `${baseUrl}/static/v${schemaVersion}.${format}${suffix}` +} + function dynamicBadgeUrl({ baseUrl, datatype, @@ -109,5 +139,6 @@ module.exports = { badgeUrlFromPattern, encodeField, staticBadgeUrl, + queryStringStaticBadgeUrl, dynamicBadgeUrl, } diff --git a/core/badge-urls/make-badge-url.spec.js b/core/badge-urls/make-badge-url.spec.js index 3ca61b9fcccaf73a2ff39eb7a6b763facb23fe6d..55931b9436c92c361bce668f0d40a91b3bcfc893 100644 --- a/core/badge-urls/make-badge-url.spec.js +++ b/core/badge-urls/make-badge-url.spec.js @@ -6,6 +6,7 @@ const { badgeUrlFromPattern, encodeField, staticBadgeUrl, + queryStringStaticBadgeUrl, dynamicBadgeUrl, } = require('./make-badge-url') @@ -81,6 +82,35 @@ describe('Badge URL generation functions', function() { }).expect('/badge/-blue-blue.svg') }) + test(queryStringStaticBadgeUrl, () => { + // the query-string library sorts parameters by name + given({ + label: 'foo', + message: 'bar', + color: 'blue', + style: 'flat-square', + }).expect( + '/static/v1.svg?color=blue&label=foo&message=bar&style=flat-square' + ) + given({ + label: 'foo Bar', + message: 'bar Baz', + color: 'blue', + style: 'flat-square', + format: 'png', + namedLogo: 'github', + }).expect( + '/static/v1.png?color=blue&label=foo%20Bar&logo=github&message=bar%20Baz&style=flat-square' + ) + given({ + label: 'Hello World', + message: 'Привет Мир', + color: '#aabbcc', + }).expect( + '/static/v1.svg?color=%23aabbcc&label=Hello%20World&message=%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%9C%D0%B8%D1%80' + ) + }) + test(dynamicBadgeUrl, () => { const dataUrl = 'http://example.com/foo.json' const query = '$.bar' diff --git a/core/base-service/coalesce-badge.js b/core/base-service/coalesce-badge.js index 30819fb81485f51ebc3912bafb26b2b8d09d210f..68340fe47ac1a39cee038864bb553f8ffb3f6bc4 100644 --- a/core/base-service/coalesce-badge.js +++ b/core/base-service/coalesce-badge.js @@ -62,7 +62,7 @@ module.exports = function coalesceBadge( labelColor: overrideLabelColor, } = overrides - // Only use the legacy properties of the new ones are not provided + // Only use the legacy properties if the new ones are not provided if (typeof overrideColor === 'undefined') { overrideColor = legacyOverrideColor } diff --git a/frontend/components/usage.js b/frontend/components/usage.js index f323bfa2374adc27602386003c733c35a05e2be9..54485d64c4132a36518c4d79243f58a2383ef04e 100644 --- a/frontend/components/usage.js +++ b/frontend/components/usage.js @@ -179,12 +179,17 @@ export default class Usage extends React.PureComponent { <VerticalSpace /> + <p>Using dash "-" separator</p> + <p> + <Snippet snippet={`${baseUrl}/badge/<LABEL>-<MESSAGE>-<COLOR>.svg`} /> + </p> + {this.constructor.renderStaticBadgeEscapingRules()} + <p>Using query string parameters</p> <p> <Snippet - snippet={`${baseUrl}/badge/<SUBJECT>-<STATUS>-<COLOR>.svg`} + snippet={`${baseUrl}/static/v1.svg?label=<LABEL>&message=<MESSAGE>&color=<COLOR>`} /> </p> - {this.constructor.renderStaticBadgeEscapingRules()} <H3 id="colors">Colors</H3> <p> diff --git a/services/static-badge/query-string-static.service.js b/services/static-badge/query-string-static.service.js new file mode 100644 index 0000000000000000000000000000000000000000..1236d505417e5bf05ddde6fb7077e7d901066bc0 --- /dev/null +++ b/services/static-badge/query-string-static.service.js @@ -0,0 +1,32 @@ +'use strict' + +const Joi = require('joi') +const { BaseStaticService, InvalidParameter } = require('..') + +const queryParamSchema = Joi.object({ + message: Joi.string().required(), +}).required() + +module.exports = class QueryStringStaticBadge extends BaseStaticService { + static get category() { + return 'other' + } + + static get route() { + return { + format: 'static/v([0-9])', + capture: ['schemaVersion'], + // All but one of the parameters are parsed via coalesceBadge. This + // reuses what is the override behaviour for other badges. + queryParamSchema, + } + } + + handle(namedParams, queryParams) { + if (namedParams.schemaVersion !== '1') { + throw new InvalidParameter({ prettyMessage: 'Invalid schemaVersion' }) + } + + return { message: queryParams.message } + } +} diff --git a/services/static-badge/query-string-static.tester.js b/services/static-badge/query-string-static.tester.js new file mode 100644 index 0000000000000000000000000000000000000000..6701d703455c1ab0ab290a31bd857702e469f2e8 --- /dev/null +++ b/services/static-badge/query-string-static.tester.js @@ -0,0 +1,39 @@ +'use strict' + +const t = (module.exports = require('../tester').createServiceTester()) + +t.create('Missing message') + .get('/static/v1.json?label=label&message=&color=blue&style=_shields_test') + .expectJSON({ + name: 'label', + value: 'invalid query parameter: message', + color: 'red', + }) + +t.create('Missing label') + .get('/static/v1.json?label=&message=message&color=blue&style=_shields_test') + .expectJSON({ name: '', value: 'message', color: 'blue' }) + +t.create('Case is preserved') + .get( + '/static/v1.json?label=LiCeNsE&message=mIt&color=blue&style=_shields_test' + ) + .expectJSON({ name: 'LiCeNsE', value: 'mIt', color: 'blue' }) + +t.create('Set color') + .get( + '/static/v1.json?label=label&message=message&color=yellow&style=_shields_test' + ) + .expectJSON({ name: 'label', value: 'message', color: 'yellow' }) + +t.create('Set color with a number') + .get( + '/static/v1.json?label=label&message=message&color=123&style=_shields_test' + ) + .expectJSON({ name: 'label', value: 'message', color: '#123' }) + +t.create('Set label') + .get( + '/static/v1.json?label=mylabel&message=message&color=blue&style=_shields_test' + ) + .expectJSON({ name: 'mylabel', value: 'message', color: 'blue' })