Files
shields/lib/npm-provider.js
Paul Melnikow cc9a6db853 Speed up font-width computation in most cases (#1390)
Ref: #1379

This takes a naive approach to font-width computation, the most compute-intensive part of rendering badges.

1. Add the widths of the individual characters.
    - These widths are measured on startup using PDFKit.
2. For each character pair, add a kerning adjustment
    - The difference between the width of each character pair, and the sum of the characters' separate widths.
    - These are computed for each character pair on startup using PDFKit.
3. For a string with characters outside the printable ASCII character set, fall back to PDFKit.

This branch averaged 0.041 ms in `makeBadge`, compared to 0.144 ms on master, a speedup of 73%. That was on a test of 10,000 consecutive requests (using the `benchmark-performance.sh` script, now checked in).

The speedup applies to badges containing exclusively printable ASCII characters. It wouldn't be as dramatic on non-ASCII text. Though, we could add some frequently used non-ASCII characters to the cached set.
2017-12-26 23:57:46 -05:00

41 lines
1.3 KiB
JavaScript

'use strict';
const { makeBadgeData: getBadgeData } = require('./badge-data');
const { metric } = require('./text-formatters');
// npm downloads count
function mapNpmDownloads({ camp, cache }, urlComponent, apiUriComponent) {
camp.route(new RegExp('^/npm/' + urlComponent + '/(.*)\\.(svg|png|gif|jpg|json)$'),
cache(function(data, match, sendBadge, request) {
const pkg = encodeURIComponent(match[1]); // eg, "express" or "@user/express"
const format = match[2];
const apiUrl = 'https://api.npmjs.org/downloads/point/' + apiUriComponent + '/' + pkg;
const badgeData = getBadgeData('downloads', data);
request(apiUrl, function(err, res, buffer) {
if (err != null) {
badgeData.text[1] = 'inaccessible';
sendBadge(format, badgeData);
return;
}
try {
const totalDownloads = JSON.parse(buffer).downloads || 0;
const badgeSuffix = apiUriComponent.replace('last-', '/');
badgeData.text[1] = metric(totalDownloads) + badgeSuffix;
if (totalDownloads === 0) {
badgeData.colorscheme = 'red';
} else {
badgeData.colorscheme = 'brightgreen';
}
sendBadge(format, badgeData);
} catch(e) {
badgeData.text[1] = 'invalid';
sendBadge(format, badgeData);
}
});
}));
}
module.exports = {
mapNpmDownloads
};