Split various utilities into standalone files (#952)
This commit is contained in:
parent
108533e08e
commit
ccbdad69ba
45
lib/color-formatters.js
Normal file
45
lib/color-formatters.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Commonly-used functions for determining the colour to use for a badge,
|
||||
* including colours based off download count, version number, etc.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function versionFormatter(version) {
|
||||
var first = version[0];
|
||||
if (first === 'v') {
|
||||
first = version[1];
|
||||
} else if (/^[0-9]/.test(version)) {
|
||||
version = 'v' + version;
|
||||
}
|
||||
if (first === '0' || (version.indexOf('-') !== -1)) {
|
||||
return { version: version, color: 'orange' };
|
||||
} else {
|
||||
return { version: version, color: 'blue' };
|
||||
}
|
||||
}
|
||||
exports.version = versionFormatter;
|
||||
|
||||
function downloadCount(downloads) {
|
||||
return floorCount(downloads, 10, 100, 1000);
|
||||
}
|
||||
exports.downloadCount = downloadCount;
|
||||
|
||||
function coveragePercentage(percentage) {
|
||||
return floorCount(percentage, 80, 90, 100);
|
||||
}
|
||||
exports.coveragePercentage = coveragePercentage;
|
||||
|
||||
function floorCount(value, yellow, yellowgreen, green) {
|
||||
if (value === 0) {
|
||||
return 'red';
|
||||
} else if (value < yellow) {
|
||||
return 'yellow';
|
||||
} else if (value < yellowgreen) {
|
||||
return 'yellowgreen';
|
||||
} else if (value < green) {
|
||||
return 'green';
|
||||
} else {
|
||||
return 'brightgreen';
|
||||
}
|
||||
}
|
||||
exports.floorCount = floorCount;
|
181
lib/php-version.js
Normal file
181
lib/php-version.js
Normal file
|
@ -0,0 +1,181 @@
|
|||
/**
|
||||
* Utilities relating to PHP version numbers. This compares version numbers
|
||||
* using the algorithm followed by Composer (see
|
||||
* https://getcomposer.org/doc/04-schema.md#version).
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const {listCompare} = require('./version.js');
|
||||
|
||||
// Return a negative value if v1 < v2,
|
||||
// zero if v1 = v2,
|
||||
// a positive value otherwise.
|
||||
//
|
||||
// See https://getcomposer.org/doc/04-schema.md#version
|
||||
// and https://github.com/badges/shields/issues/319#issuecomment-74411045
|
||||
function compare(v1, v2) {
|
||||
// Omit the starting `v`.
|
||||
var rawv1 = omitv(v1);
|
||||
var rawv2 = omitv(v2);
|
||||
try {
|
||||
var v1data = numberedVersionData(rawv1);
|
||||
var v2data = numberedVersionData(rawv2);
|
||||
} catch(e) {
|
||||
return asciiVersionCompare(rawv1, rawv2);
|
||||
}
|
||||
|
||||
// Compare the numbered part (eg, 1.0.0 < 2.0.0).
|
||||
var numbersCompare = listCompare(v1data.numbers, v2data.numbers);
|
||||
if (numbersCompare !== 0) {
|
||||
return numbersCompare;
|
||||
}
|
||||
|
||||
// Compare the modifiers (eg, alpha < beta).
|
||||
if (v1data.modifier < v2data.modifier) {
|
||||
return -1;
|
||||
} else if (v1data.modifier > v2data.modifier) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compare the modifier counts (eg, alpha1 < alpha3).
|
||||
if (v1data.modifierCount < v2data.modifierCount) {
|
||||
return -1;
|
||||
} else if (v1data.modifierCount > v2data.modifierCount) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
exports.compare = compare;
|
||||
|
||||
function latest(versions) {
|
||||
var latest = versions[0];
|
||||
for (var i = 1; i < versions.length; i++) {
|
||||
if (compare(latest, versions[i]) < 0) {
|
||||
latest = versions[i];
|
||||
}
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
exports.latest = latest;
|
||||
|
||||
// Whether a version is stable.
|
||||
function isStable(version) {
|
||||
var rawVersion = omitv(version);
|
||||
try {
|
||||
var versionData = numberedVersionData(rawVersion);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
// normal or patch
|
||||
return (versionData.modifier === 3) || (versionData.modifier === 4);
|
||||
}
|
||||
exports.isStable = isStable;
|
||||
|
||||
// === Private helper functions ===
|
||||
|
||||
// Remove the starting v in a string.
|
||||
function omitv(version) {
|
||||
if (version.charCodeAt(0) === 118) { // v
|
||||
return version.slice(1);
|
||||
} else {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a negative value if v1 < v2,
|
||||
// zero if v1 = v2, a positive value otherwise.
|
||||
function asciiVersionCompare(v1, v2) {
|
||||
if (v1 < v2) {
|
||||
return -1;
|
||||
} else if (v1 > v2) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Take a version without the starting v.
|
||||
// eg, '1.0.x-beta'
|
||||
// Return { numbers: [1,0,something big], modifier: 2, modifierCount: 1 }
|
||||
function numberedVersionData(version) {
|
||||
// A version has a numbered part and a modifier part
|
||||
// (eg, 1.0.0-patch, 2.0.x-dev).
|
||||
var parts = version.split('-');
|
||||
var numbered = parts[0];
|
||||
|
||||
// Aliases that get caught here.
|
||||
if (numbered === 'dev') {
|
||||
return {
|
||||
numbers: parts[1],
|
||||
modifier: 5,
|
||||
modifierCount: 1,
|
||||
};
|
||||
}
|
||||
|
||||
var modifierLevel = 3;
|
||||
var modifierLevelCount = 0;
|
||||
|
||||
if (parts.length > 1) {
|
||||
var modifier = parts[parts.length - 1];
|
||||
var firstLetter = modifier.charCodeAt(0);
|
||||
var modifierLevelCountString;
|
||||
|
||||
// Modifiers: alpha < beta < RC < normal < patch < dev
|
||||
if (firstLetter === 97) { // a
|
||||
modifierLevel = 0;
|
||||
if (/^alpha/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(5));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 98) { // b
|
||||
modifierLevel = 1;
|
||||
if (/^beta/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(4));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 82) { // R
|
||||
modifierLevel = 2;
|
||||
modifierLevelCountString = + (modifier.slice(2));
|
||||
} else if (firstLetter === 112) { // p
|
||||
modifierLevel = 4;
|
||||
if (/^patch/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(5));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 100) { // d
|
||||
modifierLevel = 5;
|
||||
if (/^dev/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(3));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
// If we got the empty string, it defaults to a modifier count of 1.
|
||||
if (!modifierLevelCountString) {
|
||||
modifierLevelCount = 1;
|
||||
} else {
|
||||
modifierLevelCount = + modifierLevelCountString;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to convert to a list of numbers.
|
||||
var toNum = function(s) {
|
||||
var n = +s;
|
||||
if (n !== n) { // If n is NaN…
|
||||
n = 0xffffffff;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
var numberList = numbered.split('.').map(toNum);
|
||||
|
||||
return {
|
||||
numbers: numberList,
|
||||
modifier: modifierLevel,
|
||||
modifierCount: modifierLevelCount,
|
||||
};
|
||||
}
|
47
lib/text-formatters.js
Normal file
47
lib/text-formatters.js
Normal file
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Commonly-used functions for formatting text in badge labels. Includes
|
||||
* ordinal numbers, currency codes, star ratings, etc.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
function starRating(rating) {
|
||||
var stars = '';
|
||||
while (stars.length < rating) { stars += '★'; }
|
||||
while (stars.length < 5) { stars += '☆'; }
|
||||
return stars;
|
||||
}
|
||||
exports.starRating = starRating;
|
||||
|
||||
// Convert ISO 4217 code to unicode string.
|
||||
function currencyFromCode(code) {
|
||||
return ({
|
||||
CNY: '¥',
|
||||
EUR: '€',
|
||||
GBP: '₤',
|
||||
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.
|
||||
var metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
||||
var metricPower = metricPrefix
|
||||
.map(function(a, i) { return Math.pow(1000, i + 1); });
|
||||
function metric(n) {
|
||||
for (var i = metricPrefix.length - 1; i >= 0; i--) {
|
||||
var limit = metricPower[i];
|
||||
if (n >= limit) {
|
||||
n = Math.round(n / limit);
|
||||
return ''+n + metricPrefix[i];
|
||||
}
|
||||
}
|
||||
return ''+n;
|
||||
}
|
||||
exports.metric = metric;
|
80
lib/version.js
Normal file
80
lib/version.js
Normal file
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Utilities relating to generating badges relating to version numbers. Includes
|
||||
* comparing versions to determine the latest, and determining the color to use
|
||||
* for the badge based on whether the version is a stable release.
|
||||
*
|
||||
* For utilities specific to PHP version ranges, see php-version.js.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const semver = require('semver');
|
||||
|
||||
// Given a list of versions (as strings), return the latest version.
|
||||
// Return undefined if no version could be found.
|
||||
function latest(versions) {
|
||||
var version = '';
|
||||
var origVersions = versions;
|
||||
versions = versions.filter(function(version) {
|
||||
return (/^v?[0-9]/).test(version);
|
||||
});
|
||||
try {
|
||||
version = semver.maxSatisfying(versions, '');
|
||||
} catch(e) {
|
||||
version = latestDottedVersion(versions);
|
||||
}
|
||||
if (version === undefined) {
|
||||
origVersions = origVersions.sort();
|
||||
version = origVersions[origVersions.length - 1];
|
||||
}
|
||||
return version;
|
||||
}
|
||||
exports.latest = latest;
|
||||
|
||||
function listCompare(a, b) {
|
||||
var alen = a.length, blen = b.length;
|
||||
for (var i = 0; i < alen; i++) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return alen - blen;
|
||||
}
|
||||
exports.listCompare = listCompare;
|
||||
|
||||
// === Private helper functions ===
|
||||
|
||||
// Take a list of string versions.
|
||||
// Return the latest, or undefined, if there are none.
|
||||
function latestDottedVersion(versions) {
|
||||
var len = versions.length;
|
||||
if (len === 0) { return; }
|
||||
var version = versions[0];
|
||||
for (var i = 1; i < len; i++) {
|
||||
if (compareDottedVersion(version, versions[i]) < 0) {
|
||||
version = versions[i];
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
// Take string versions.
|
||||
// -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
|
||||
function compareDottedVersion(v1, v2) {
|
||||
var parts1 = /([0-9\.]+)(.*)$/.exec(v1);
|
||||
var parts2 = /([0-9\.]+)(.*)$/.exec(v2);
|
||||
if (parts1 != null && parts2 != null) {
|
||||
var numbers1 = parts1[1];
|
||||
var numbers2 = parts2[1];
|
||||
var distinguisher1 = parts1[2];
|
||||
var distinguisher2 = parts2[2];
|
||||
var numlist1 = numbers1.split('.').map(function(e) { return +e; });
|
||||
var numlist2 = numbers2.split('.').map(function(e) { return +e; });
|
||||
var cmp = listCompare(numlist1, numlist2);
|
||||
if (cmp !== 0) { return cmp; }
|
||||
else { return distinguisher1 < distinguisher2? -1:
|
||||
distinguisher1 > distinguisher2? 1: 0; }
|
||||
}
|
||||
return v1 < v2? -1: v1 > v2? 1: 0;
|
||||
}
|
328
server.js
328
server.js
|
@ -38,6 +38,25 @@ if (serverSecrets && serverSecrets.gh_client_id) {
|
|||
githubAuth.setRoutes(camp);
|
||||
}
|
||||
|
||||
const {latest: latestVersion} = require('./lib/version.js');
|
||||
const {
|
||||
compare: phpVersionCompare,
|
||||
latest: phpLatestVersion,
|
||||
isStable: phpStableVersion,
|
||||
} = require('./lib/php-version.js');
|
||||
const {
|
||||
currencyFromCode,
|
||||
metric,
|
||||
ordinalNumber,
|
||||
starRating,
|
||||
} = require('./lib/text-formatters.js');
|
||||
const {
|
||||
coveragePercentage: coveragePercentageColor,
|
||||
downloadCount: downloadCountColor,
|
||||
floorCount: floorCountColor,
|
||||
version: versionColor,
|
||||
} = require('./lib/color-formatters.js');
|
||||
|
||||
var semver = require('semver');
|
||||
var serverStartTime = new Date((new Date()).toGMTString());
|
||||
|
||||
|
@ -6466,23 +6485,6 @@ function regularUpdate(url, interval, scraper, cb) {
|
|||
});
|
||||
}
|
||||
|
||||
// Given a number, string with appropriate unit in the metric system, SI.
|
||||
// Note: numbers beyond the peta- cannot be represented as integers in JS.
|
||||
var metricPrefix = ['k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'];
|
||||
var metricPower = metricPrefix
|
||||
.map(function(a, i) { return Math.pow(1000, i + 1); });
|
||||
function metric(n) {
|
||||
for (var i = metricPrefix.length - 1; i >= 0; i--) {
|
||||
var limit = metricPower[i];
|
||||
if (n >= limit) {
|
||||
n = Math.round(n / limit);
|
||||
return ''+n + metricPrefix[i];
|
||||
}
|
||||
}
|
||||
return ''+n;
|
||||
}
|
||||
|
||||
|
||||
// Get data from a svg-style badge.
|
||||
// cb: function(err, string)
|
||||
function fetchFromSvg(request, url, cb) {
|
||||
|
@ -6498,295 +6500,3 @@ function fetchFromSvg(request, url, cb) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function ordinalNumber(n) {
|
||||
var s=["ᵗʰ","ˢᵗ","ⁿᵈ","ʳᵈ"], v=n%100;
|
||||
return n+(s[(v-20)%10]||s[v]||s[0]);
|
||||
}
|
||||
|
||||
// Convert ISO 4217 code to unicode string.
|
||||
function currencyFromCode(code) {
|
||||
return ({
|
||||
CNY: '¥',
|
||||
EUR: '€',
|
||||
GBP: '₤',
|
||||
USD: '$',
|
||||
})[code] || code;
|
||||
}
|
||||
|
||||
function starRating(rating) {
|
||||
var stars = '';
|
||||
while (stars.length < rating) { stars += '★'; }
|
||||
while (stars.length < 5) { stars += '☆'; }
|
||||
return stars;
|
||||
}
|
||||
|
||||
function coveragePercentageColor(percentage) {
|
||||
return floorCountColor(percentage, 80, 90, 100);
|
||||
}
|
||||
|
||||
function downloadCountColor(downloads) {
|
||||
return floorCountColor(downloads, 10, 100, 1000);
|
||||
}
|
||||
|
||||
function floorCountColor(value, yellow, yellowgreen, green) {
|
||||
if (value === 0) {
|
||||
return 'red';
|
||||
} else if (value < yellow) {
|
||||
return 'yellow';
|
||||
} else if (value < yellowgreen) {
|
||||
return 'yellowgreen';
|
||||
} else if (value < green) {
|
||||
return 'green';
|
||||
} else {
|
||||
return 'brightgreen';
|
||||
}
|
||||
}
|
||||
|
||||
function versionColor(version) {
|
||||
var first = version[0];
|
||||
if (first === 'v') {
|
||||
first = version[1];
|
||||
} else if (/^[0-9]/.test(version)) {
|
||||
version = 'v' + version;
|
||||
}
|
||||
if (first === '0' || (version.indexOf('-') !== -1)) {
|
||||
return { version: version, color: 'orange' };
|
||||
} else {
|
||||
return { version: version, color: 'blue' };
|
||||
}
|
||||
}
|
||||
|
||||
// Take string versions.
|
||||
// -1 if v1 < v2, 1 if v1 > v2, 0 otherwise.
|
||||
function compareDottedVersion(v1, v2) {
|
||||
var parts1 = /([0-9\.]+)(.*)$/.exec(v1);
|
||||
var parts2 = /([0-9\.]+)(.*)$/.exec(v2);
|
||||
if (parts1 != null && parts2 != null) {
|
||||
var numbers1 = parts1[1];
|
||||
var numbers2 = parts2[1];
|
||||
var distinguisher1 = parts1[2];
|
||||
var distinguisher2 = parts2[2];
|
||||
var numlist1 = numbers1.split('.').map(function(e) { return +e; });
|
||||
var numlist2 = numbers2.split('.').map(function(e) { return +e; });
|
||||
var cmp = listCompare(numlist1, numlist2);
|
||||
if (cmp !== 0) { return cmp; }
|
||||
else { return distinguisher1 < distinguisher2? -1:
|
||||
distinguisher1 > distinguisher2? 1: 0; }
|
||||
}
|
||||
return v1 < v2? -1: v1 > v2? 1: 0;
|
||||
}
|
||||
|
||||
// Take a list of string versions.
|
||||
// Return the latest, or undefined, if there are none.
|
||||
function latestDottedVersion(versions) {
|
||||
var len = versions.length;
|
||||
if (len === 0) { return; }
|
||||
var version = versions[0];
|
||||
for (var i = 1; i < len; i++) {
|
||||
if (compareDottedVersion(version, versions[i]) < 0) {
|
||||
version = versions[i];
|
||||
}
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
// Given a list of versions (as strings), return the latest version.
|
||||
// Return undefined if no version could be found.
|
||||
function latestVersion(versions) {
|
||||
var version = '';
|
||||
var origVersions = versions;
|
||||
versions = versions.filter(function(version) {
|
||||
return (/^v?[0-9]/).test(version);
|
||||
});
|
||||
try {
|
||||
version = semver.maxSatisfying(versions, '');
|
||||
} catch(e) {
|
||||
version = latestDottedVersion(versions);
|
||||
}
|
||||
if (version === undefined) {
|
||||
origVersions = origVersions.sort();
|
||||
version = origVersions[origVersions.length - 1];
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
// Return a negative value if v1 < v2,
|
||||
// zero if v1 = v2, a positive value otherwise.
|
||||
function asciiVersionCompare(v1, v2) {
|
||||
if (v1 < v2) {
|
||||
return -1;
|
||||
} else if (v1 > v2) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the starting v in a string.
|
||||
function omitv(version) {
|
||||
if (version.charCodeAt(0) === 118) { // v
|
||||
return version.slice(1);
|
||||
} else {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
// Take a version without the starting v.
|
||||
// eg, '1.0.x-beta'
|
||||
// Return { numbers: [1,0,something big], modifier: 2, modifierCount: 1 }
|
||||
function phpNumberedVersionData(version) {
|
||||
// A version has a numbered part and a modifier part
|
||||
// (eg, 1.0.0-patch, 2.0.x-dev).
|
||||
var parts = version.split('-');
|
||||
var numbered = parts[0];
|
||||
|
||||
// Aliases that get caught here.
|
||||
if (numbered === 'dev') {
|
||||
return {
|
||||
numbers: parts[1],
|
||||
modifier: 5,
|
||||
modifierCount: 1,
|
||||
};
|
||||
}
|
||||
|
||||
var modifierLevel = 3;
|
||||
var modifierLevelCount = 0;
|
||||
|
||||
if (parts.length > 1) {
|
||||
var modifier = parts[parts.length - 1];
|
||||
var firstLetter = modifier.charCodeAt(0);
|
||||
var modifierLevelCountString;
|
||||
|
||||
// Modifiers: alpha < beta < RC < normal < patch < dev
|
||||
if (firstLetter === 97) { // a
|
||||
modifierLevel = 0;
|
||||
if (/^alpha/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(5));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 98) { // b
|
||||
modifierLevel = 1;
|
||||
if (/^beta/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(4));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 82) { // R
|
||||
modifierLevel = 2;
|
||||
modifierLevelCountString = + (modifier.slice(2));
|
||||
} else if (firstLetter === 112) { // p
|
||||
modifierLevel = 4;
|
||||
if (/^patch/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(5));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
} else if (firstLetter === 100) { // d
|
||||
modifierLevel = 5;
|
||||
if (/^dev/.test(modifier)) {
|
||||
modifierLevelCountString = + (modifier.slice(3));
|
||||
} else {
|
||||
modifierLevelCountString = + (modifier.slice(1));
|
||||
}
|
||||
}
|
||||
|
||||
// If we got the empty string, it defaults to a modifier count of 1.
|
||||
if (!modifierLevelCountString) {
|
||||
modifierLevelCount = 1;
|
||||
} else {
|
||||
modifierLevelCount = + modifierLevelCountString;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to convert to a list of numbers.
|
||||
var toNum = function(s) {
|
||||
var n = +s;
|
||||
if (n !== n) { // If n is NaN…
|
||||
n = 0xffffffff;
|
||||
}
|
||||
return n;
|
||||
};
|
||||
var numberList = numbered.split('.').map(toNum);
|
||||
|
||||
return {
|
||||
numbers: numberList,
|
||||
modifier: modifierLevel,
|
||||
modifierCount: modifierLevelCount,
|
||||
};
|
||||
}
|
||||
|
||||
function listCompare(a, b) {
|
||||
var alen = a.length, blen = b.length;
|
||||
for (var i = 0; i < alen; i++) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return alen - blen;
|
||||
}
|
||||
|
||||
// Return a negative value if v1 < v2,
|
||||
// zero if v1 = v2,
|
||||
// a positive value otherwise.
|
||||
//
|
||||
// See https://getcomposer.org/doc/04-schema.md#version
|
||||
// and https://github.com/badges/shields/issues/319#issuecomment-74411045
|
||||
function phpVersionCompare(v1, v2) {
|
||||
// Omit the starting `v`.
|
||||
var rawv1 = omitv(v1);
|
||||
var rawv2 = omitv(v2);
|
||||
try {
|
||||
var v1data = phpNumberedVersionData(rawv1);
|
||||
var v2data = phpNumberedVersionData(rawv2);
|
||||
} catch(e) {
|
||||
return asciiVersionCompare(rawv1, rawv2);
|
||||
}
|
||||
|
||||
// Compare the numbered part (eg, 1.0.0 < 2.0.0).
|
||||
var numbersCompare = listCompare(v1data.numbers, v2data.numbers);
|
||||
if (numbersCompare !== 0) {
|
||||
return numbersCompare;
|
||||
}
|
||||
|
||||
// Compare the modifiers (eg, alpha < beta).
|
||||
if (v1data.modifier < v2data.modifier) {
|
||||
return -1;
|
||||
} else if (v1data.modifier > v2data.modifier) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Compare the modifier counts (eg, alpha1 < alpha3).
|
||||
if (v1data.modifierCount < v2data.modifierCount) {
|
||||
return -1;
|
||||
} else if (v1data.modifierCount > v2data.modifierCount) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function phpLatestVersion(versions) {
|
||||
var latest = versions[0];
|
||||
for (var i = 1; i < versions.length; i++) {
|
||||
if (phpVersionCompare(latest, versions[i]) < 0) {
|
||||
latest = versions[i];
|
||||
}
|
||||
}
|
||||
return latest;
|
||||
}
|
||||
|
||||
// Whether a version is stable.
|
||||
function phpStableVersion(version) {
|
||||
var rawVersion = omitv(version);
|
||||
try {
|
||||
var versionData = phpNumberedVersionData(rawVersion);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
// normal or patch
|
||||
return (versionData.modifier === 3) || (versionData.modifier === 4);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user