-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split various utilities into standalone files #952
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can omit the |
||
|
||
// 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, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you make any changes in these implementations?