Skip to content

Commit

Permalink
Always allow overriding the label (#1108)
Browse files Browse the repository at this point in the history
Audit all the badges with test coverage, looking for badges which assign `badgeData.text[0]`.
  • Loading branch information
paulmelnikow authored Oct 2, 2017
1 parent 0068f31 commit 820b72c
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 32 deletions.
24 changes: 19 additions & 5 deletions lib/text-formatters.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ function starRating(rating) {
while (stars.length < 5) { stars += '☆'; }
return stars;
}
exports.starRating = starRating;

// Convert ISO 4217 code to unicode string.
function currencyFromCode(code) {
Expand All @@ -21,13 +20,11 @@ function currencyFromCode(code) {
USD: '$',
})[code] || code;
}
exports.currencyFromCode = currencyFromCode;

function ordinalNumber(n) {
var s=["ᵗʰ","ˢᵗ","ⁿᵈ","ʳᵈ"], v=n%100;
return n+(s[(v-20)%10]||s[v]||s[0]);
}
exports.ordinalNumber = ordinalNumber;

// Given a number, string with appropriate unit in the metric system, SI.
// Note: numbers beyond the peta- cannot be represented as integers in JS.
Expand All @@ -44,7 +41,6 @@ function metric(n) {
}
return ''+n;
}
exports.metric = metric;

// Remove the starting v in a string.
function omitv(version) {
Expand All @@ -53,4 +49,22 @@ function omitv(version) {
}
return version;
}
exports.omitv = omitv;

function maybePluralize(singular, countable, plural) {
plural = plural || `${singular}s`;

if (countable && countable.length === 1) {
return singular;
} else {
return plural;
}
}

module.exports = {
starRating,
currencyFromCode,
ordinalNumber,
metric,
omitv,
maybePluralize
};
20 changes: 20 additions & 0 deletions lib/text-formatters.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const assert = require('assert');
const {
maybePluralize
} = require('./text-formatters');

describe('text formatters', function() {
it('should pluralize', function() {
assert.equal(maybePluralize('foo', []), 'foos');
assert.equal(maybePluralize('foo', [123]), 'foo');
assert.equal(maybePluralize('foo', [123, 456]), 'foos');
assert.equal(maybePluralize('foo', undefined), 'foos');

assert.equal(maybePluralize('box', [], 'boxes'), 'boxes');
assert.equal(maybePluralize('box', [123], 'boxes'), 'box');
assert.equal(maybePluralize('box', [123, 456], 'boxes'), 'boxes');
assert.equal(maybePluralize('box', undefined, 'boxes'), 'boxes');
});
});
54 changes: 27 additions & 27 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const {
ordinalNumber,
starRating,
omitv,
maybePluralize
} = require('./lib/text-formatters.js');
const {
coveragePercentage: coveragePercentageColor,
Expand Down Expand Up @@ -1844,7 +1845,7 @@ cache(function(data, match, sendBadge, request) {

// Anaconda Cloud / conda package manager integration
camp.route(/^\/conda\/([dvp]n?)\/([^\/]+)\/([^\/]+)\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {
cache(function(queryData, match, sendBadge, request) {
const mode = match[1];
const channel = match[2];
const pkgname = match[3];
Expand Down Expand Up @@ -1877,29 +1878,29 @@ cache(function(data, match, sendBadge, request) {
};
const variants = {
// default use `conda|{channelname}` as label
'': function(data, badgeData) {
badgeData.text[0] = (data && data.label) || 'conda|' + badgeData.text[0];
'': function(queryData, badgeData) {
badgeData.text[0] = (queryData && queryData.label) || 'conda|' + badgeData.text[0];
},
// skip `conda|` prefix
'n': function(data, badgeData) {
'n': function(queryData, badgeData) {
}
};

const update = modes[mode.charAt(0)];
const variant = variants[mode.charAt(1)];

var badgeData = getBadgeData(labels[mode.charAt(0)], data);
var badgeData = getBadgeData(labels[mode.charAt(0)], queryData);
request(url, function(err, res, buffer) {
if (err != null) {
badgeData.text[1] = 'inaccessible';
variant(data, badgeData);
variant(queryData, badgeData);
sendBadge(format, badgeData);
return;
}
try {
var data = JSON.parse(buffer);
update(data, badgeData);
variant(data, badgeData);
variant(queryData, badgeData);
sendBadge(format, badgeData);
} catch(e) {
badgeData.text[1] = 'invalid';
Expand Down Expand Up @@ -2433,22 +2434,22 @@ cache(function(data, match, sendBadge, request) {

// Hex.pm integration.
camp.route(/^\/hexpm\/([^\/]+)\/(.*)\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {
var info = match[1];
var repo = match[2]; // eg, `httpotion`.
var format = match[3];
var apiUrl = 'https://hex.pm/api/packages/' + repo;
var badgeData = getBadgeData('hex', data);
cache(function(queryParams, match, sendBadge, request) {
const info = match[1];
const repo = match[2]; // eg, `httpotion`.
const format = match[3];
const apiUrl = 'https://hex.pm/api/packages/' + repo;
const badgeData = getBadgeData('hex', queryParams);
request(apiUrl, function(err, res, buffer) {
if (err != null) {
badgeData.text[1] = 'inaccessible';
sendBadge(format, badgeData);
return;
}
try {
var data = JSON.parse(buffer);
const data = JSON.parse(buffer);
if (info.charAt(0) === 'd') {
badgeData.text[0] = getLabel('downloads', data);
badgeData.text[0] = getLabel('downloads', queryParams);
var downloads;
switch (info.charAt(1)) {
case 'w':
Expand All @@ -2467,15 +2468,14 @@ cache(function(data, match, sendBadge, request) {
badgeData.colorscheme = downloadCountColor(downloads);
sendBadge(format, badgeData);
} else if (info === 'v') {
var version = data.releases[0].version;
var vdata = versionColor(version);
const version = data.releases[0].version;
const vdata = versionColor(version);
badgeData.text[1] = vdata.version;
badgeData.colorscheme = vdata.color;
sendBadge(format, badgeData);
} else if (info == 'l') {
var license = (data.meta.licenses || []).join(', ');
badgeData.text[0] = 'license';
if ((data.meta.licenses || []).length > 1) badgeData.text[0] += 's';
const license = (data.meta.licenses || []).join(', ');
badgeData.text[0] = getLabel(maybePluralize('license', data.meta.licenses), queryParams);
if (license == '') {
badgeData.text[1] = 'Unknown';
} else {
Expand Down Expand Up @@ -5511,12 +5511,12 @@ cache(function(data, match, sendBadge, request) {

// CRAN/METACRAN integration.
camp.route(/^\/cran\/([vl])\/([^\/]+)\.(svg|png|gif|jpg|json)$/,
cache(function(data, match, sendBadge, request) {
cache(function(queryParams, match, sendBadge, request) {
var info = match[1]; // either `v` or `l`
var pkg = match[2]; // eg, devtools
var format = match[3];
var url = 'http://crandb.r-pkg.org/' + pkg;
var badgeData = getBadgeData('cran', data);
var badgeData = getBadgeData('cran', queryParams);
request(url, function (err, res, buffer) {
if (err != null) {
badgeData.text[1] = 'inaccessible';
Expand All @@ -5538,7 +5538,7 @@ cache(function(data, match, sendBadge, request) {
badgeData.colorscheme = vdata.color;
sendBadge(format, badgeData);
} else if (info === 'l') {
badgeData.text[0] = 'license';
badgeData.text[0] = getLabel('license', queryParams);
var license = data.License;
if (license) {
badgeData.text[1] = license;
Expand Down Expand Up @@ -6453,25 +6453,25 @@ cache(function(query_data, match, sendBadge, request) {
break;
case 'd':
var downloads = parseInt(data.addon.total_downloads[0], 10);
badgeData.text[0] = query_data.label || 'downloads';
badgeData.text[0] = getLabel('downloads', query_data);
badgeData.text[1] = metric(downloads);
badgeData.colorscheme = downloadCountColor(downloads);
break;
case 'rating':
rating = parseInt(data.addon.rating, 10);
badgeData.text[0] = query_data.label || 'rating';
badgeData.text[0] = getLabel('downloads', query_data);
badgeData.text[1] = rating + '/5';
badgeData.colorscheme = floorCountColor(rating, 2, 3, 4);
break;
case 'stars':
rating = parseInt(data.addon.rating, 10);
badgeData.text[0] = query_data.label || 'rating';
badgeData.text[0] = getLabel('downloads', query_data);
badgeData.text[1] = starRating(rating);
badgeData.colorscheme = floorCountColor(rating, 2, 3, 4);
break;
case 'users':
var dailyUsers = parseInt(data.addon.daily_users[0], 10);
badgeData.text[0] = query_data.label || 'users';
badgeData.text[0] = getLabel('downloads', query_data);
badgeData.text[1] = metric(dailyUsers);
badgeData.colorscheme = 'brightgreen';
break;
Expand Down
7 changes: 7 additions & 0 deletions service-tests/conda.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ t.create('version')
value: Joi.string().regex(/^v\d+\.\d+\.\d+$/)
}));

t.create('version (relabel)')
.get('/v/conda-forge/zlib.json?label=123')
.expectJSONTypes(Joi.object().keys({
name: Joi.equal('123'),
value: Joi.string().regex(/^v\d+\.\d+\.\d+$/)
}));

t.create('version (skip prefix)')
.get('/vn/conda-forge/zlib.json')
.expectJSONTypes(Joi.object().keys({
Expand Down

0 comments on commit 820b72c

Please sign in to comment.