Add [npm] type definitions badge (#1541)

Let a package show off its type definitions based on devDependency data in the published npm package.

Close #1252
This commit is contained in:
Paul Melnikow
2018-03-11 18:00:41 -07:00
committed by GitHub
parent 2d651533aa
commit 6750115b79
7 changed files with 185 additions and 30 deletions

View File

@@ -840,6 +840,15 @@ const allBadgeExamples = [
'node'
]
},
{
title: 'npm type definitions',
previewUri: '/npm/types/chalk.svg',
keywords: [
'node',
'typescript',
'flow'
]
},
{
title: 'PyPI',
previewUri: '/pypi/v/nine.svg',

View File

@@ -1,7 +1,46 @@
'use strict';
const { rangeStart, minor } = require('./version');
const defaultNpmRegistryUri = 'https://registry.npmjs.org';
function makePackageDataUrl({ registryUrl, scope, packageName }) {
registryUrl = registryUrl || defaultNpmRegistryUri;
if (scope === undefined) {
// e.g. https://registry.npmjs.org/express/latest
// Use this endpoint as an optimization. It covers the vast majority of
// these badges, and the response is smaller.
return `${registryUrl}/${packageName}/latest`;
} else {
// e.g. https://registry.npmjs.org/@cedx%2Fgulp-david
// because https://registry.npmjs.org/@cedx%2Fgulp-david/latest does not work
const path = encodeURIComponent(`${scope}/${packageName}`);
return `${registryUrl}/@${path}`;
}
}
function typeDefinitions(packageData) {
const { devDependencies } = packageData;
const supportedLanguages = [
{ name: 'TypeScript', range: devDependencies.typescript },
{ name: 'Flow', range: devDependencies['flow-bin'] },
]
.filter(lang => lang.range !== undefined)
.map(({ name, range }) => {
const version = minor(rangeStart(range));
return `${name} v${version}`;
});
if (supportedLanguages.length > 0) {
return supportedLanguages.join(' | ');
} else {
return 'none';
}
}
module.exports = {
defaultNpmRegistryUri,
makePackageDataUrl,
typeDefinitions,
};

View File

@@ -0,0 +1,10 @@
'use strict';
const { test, given } = require('sazerac');
const { typeDefinitions } = require('./npm-badge-helpers');
describe('NPM badge helpers', function () {
test(typeDefinitions, () => {
given({ devDependencies: { typescript: '^2.4.7' } }).expect('TypeScript v2.4');
});
});

View File

@@ -28,7 +28,6 @@ function latest(versions) {
}
return version;
}
exports.latest = latest;
function listCompare(a, b) {
const alen = a.length, blen = b.length;
@@ -41,7 +40,6 @@ function listCompare(a, b) {
}
return alen - blen;
}
exports.listCompare = listCompare;
// === Private helper functions ===
@@ -81,3 +79,50 @@ function compareDottedVersion(v1, v2) {
}
return v1 < v2? -1: v1 > v2? 1: 0;
}
// Slice the specified number of dotted parts from the given semver version.
// e.g. slice('2.4.7', 'minor') -> '2.4'
function slice(v, releaseType) {
if (! semver.valid(v)) {
return null;
}
const major = semver.major(v);
const minor = semver.minor(v);
const patch = semver.patch(v);
const prerelease = semver.prerelease(v);
const dottedParts = {
major: [major],
minor: [major, minor],
patch: [major, minor, patch],
}[releaseType];
if (dottedParts === undefined) {
throw Error(`Unknown releaseType: ${releaseType}`);
}
const dotted = dottedParts.join('.');
if (prerelease) {
return `${dotted}-${prerelease.join('.')}`;
} else {
return dotted;
}
}
function minor(v) {
return slice(v, 'minor');
}
function rangeStart(v) {
const range = new semver.Range(v);
return range.set[0][0].semver.version;
}
module.exports = {
latest,
listCompare,
slice,
minor,
rangeStart,
};

View File

@@ -1,7 +1,7 @@
'use strict';
const { test, given } = require('sazerac');
const {latest} = require('./version');
const { latest, slice, rangeStart } = require('./version');
describe('Version helpers', function () {
test(latest, () => {
@@ -31,4 +31,17 @@ describe('Version helpers', function () {
// Simple (one-number) versions
given(['2', '10', '1']).expect('10');
});
test(slice, () => {
given('2.4.7', 'major').expect('2');
given('2.4.7', 'minor').expect('2.4');
given('2.4.7', 'patch').expect('2.4.7');
given('2.4.7-alpha.1', 'major').expect('2-alpha.1');
given('2.4.7-alpha.1', 'minor').expect('2.4-alpha.1');
given('2.4.7-alpha.1', 'patch').expect('2.4.7-alpha.1');
});
test(rangeStart, () => {
given('^2.4.7').expect('2.4.7');
});
});