[badge/dynamic/json] User defined JSON source badge (#820)
* Add User Defined URL support * Add test * eslint fixes * 100% coverage * use JSONpath * update try.html * Update tests, restore prefix & suffix * order dependencies alphabetically * update jsonpath version dependency * update url structure & move to query strings * update error handling & remove xml refrences * fix eslint errors * update tests * update dynamic badge generator * url -> uri & decode uri Allow an encoded url to be used. needed for any uri that requires params in the address * resolve conflicts * update for new page generation * check uri is defined * add query params to `request-handler.js` * eslint fixes * add test for no uri specified * move query params to be local to dynamic badge * update tests * dynamic badge gen use same base url as static badge
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
|
||||
<h2 id="your-badge"> Your Badge </h2>
|
||||
|
||||
<h3 id="static-badge"> Static </h3>
|
||||
|
||||
<form action='javascript:makeImage()' id='imageMaker'>
|
||||
<input class='short' name='subject' placeholder='subject'/>
|
||||
<input class='short' name='status' placeholder='status'/>
|
||||
@@ -49,6 +51,27 @@
|
||||
<img src="/badge/color-ff69b4-ff69b4.svg" alt='ff69b4'/>
|
||||
</p>
|
||||
|
||||
<h3 id="dynamic-badge"> Dynamic </h3>
|
||||
|
||||
<form action='javascript:generateDynamicImage()' id='dynamicImageMaker'>
|
||||
<input class='short' name='type' list='dynamic-type' placeholder='type'/>
|
||||
<datalist id='dynamic-type'>
|
||||
<option value='json'>
|
||||
</datalist>
|
||||
<input class='short' name='label' placeholder='label'/>
|
||||
<input class='short' name='uri' placeholder='uri'/>
|
||||
<input class='short' name='query' placeholder='$.data.subdata'/>
|
||||
<input class='short' name='color' placeholder='hex color'/>
|
||||
<input class='short' name='prefix' placeholder='prefix'/>
|
||||
<input class='short' name='suffix' placeholder='suffix'/>
|
||||
<button>Generate</button>
|
||||
</form>
|
||||
|
||||
<p>
|
||||
<code>/badge/dynamic/<TYPE>.svg?uri=<URI>&label=<LABEL>&query=<<a href="https://www.npmjs.com/package/jsonpath" target="_BLANK" title="JSONdata syntax">$.DATA.SUBDATA</a>>&colorB=<COLOR>&prefix=<PREFIX>&suffix=<SUFFIX></code>
|
||||
</p>
|
||||
<hr class='spacing'/>
|
||||
|
||||
<h2 id="styles"> Styles </h2>
|
||||
<p>
|
||||
The following styles are available (flat is the default as of Feb 1st 2015):
|
||||
@@ -448,6 +471,18 @@ function makeImage() {
|
||||
document.location = url;
|
||||
}
|
||||
|
||||
function generateDynamicImage() {
|
||||
var url = document.getElementById('imgUrlPrefix').textContent;
|
||||
url += 'dynamic/' + escapeField(dynamicImageMaker.type.value);
|
||||
url += '.svg?label=' + escapeField(dynamicImageMaker.label.value);
|
||||
url += '&colorB=' + escapeField(dynamicImageMaker.color.value);
|
||||
url += '&prefix=' + escapeField(dynamicImageMaker.prefix.value);
|
||||
url += '&suffix=' + escapeField(dynamicImageMaker.suffix.value);
|
||||
url += '&query=' + dynamicImageMaker.query.value;
|
||||
url += '&uri=' + escapeField(dynamicImageMaker.uri.value);
|
||||
document.location = url;
|
||||
}
|
||||
|
||||
function escapeField(s) {
|
||||
return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"dot": "~1.1.2",
|
||||
"gm": "^1.23.0",
|
||||
"json-autosave": "~1.1.2",
|
||||
"jsonpath": "~0.2.12",
|
||||
"lodash.countby": "^4.6.0",
|
||||
"moment": "^2.18.1",
|
||||
"pdfkit": "~0.8.0",
|
||||
|
||||
45
server.js
45
server.js
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const countBy = require('lodash.countby');
|
||||
const jp = require('jsonpath');
|
||||
const path = require('path');
|
||||
const prettyBytes = require('pretty-bytes');
|
||||
const queryString = require('query-string');
|
||||
@@ -7139,6 +7140,50 @@ camp.route(/^\/maven-metadata\/v\/(https?)\/(.+\.xml)\.(svg|png|gif|jpg|json)$/,
|
||||
});
|
||||
}));
|
||||
|
||||
// User defined sources - JSON response
|
||||
camp.route(/^\/badge\/dynamic\/(json)\.(svg|png|gif|jpg|json)$/,
|
||||
cache({
|
||||
queryParams: ['uri', 'query', 'prefix', 'suffix'],
|
||||
handler: function(query, match, sendBadge, request) {
|
||||
var type = match[1];
|
||||
var format = match[2];
|
||||
var prefix = query.prefix || '';
|
||||
var suffix = query.suffix || '';
|
||||
var pathExpression = query.query;
|
||||
|
||||
var badgeData = getBadgeData('custom badge', query);
|
||||
|
||||
if (!query.uri){
|
||||
badgeData.text[1] = 'no uri specified';
|
||||
sendBadge(format, badgeData);
|
||||
return;
|
||||
}
|
||||
var uri = encodeURI(decodeURIComponent(query.uri));
|
||||
|
||||
request(uri, (err, res, data) => {
|
||||
try {
|
||||
if (res && res.statusCode === 404)
|
||||
throw 'invalid resource';
|
||||
|
||||
if (err != null || !res || res.statusCode !== 200)
|
||||
throw 'inaccessible';
|
||||
|
||||
switch (type){
|
||||
case 'json':
|
||||
data = (typeof data == 'object' ? data : JSON.parse(data));
|
||||
badgeData.text[1] = (prefix || '') + jp.query(data, pathExpression).join(', ') + (suffix || '');
|
||||
break;
|
||||
}
|
||||
} catch(e) {
|
||||
badgeData.colorB = 'lightgrey';
|
||||
badgeData.text[1] = e;
|
||||
} finally {
|
||||
sendBadge(format, badgeData);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
// nsp for npm packages
|
||||
camp.route(/^\/nsp\/npm\/(?:@([^/]+)?\/)?([^/]+)?(?:\/([^/]+)?)?\.(svg|png|gif|jpg|json)?$/, cache((data, match, sendBadge, request) => {
|
||||
// A: /nsp/npm/:package.:format
|
||||
|
||||
42
service-tests/json.js
Normal file
42
service-tests/json.js
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
const Joi = require('joi');
|
||||
const ServiceTester = require('./runner/service-tester');
|
||||
|
||||
const t = new ServiceTester({ id: 'badge/dynamic/json', title: 'User Defined JSON Source Data' });
|
||||
module.exports = t;
|
||||
|
||||
t.create('Connection error')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.name&label=Package Name')
|
||||
.networkOff()
|
||||
.expectJSON({ name: 'Package Name', value: 'inaccessible' });
|
||||
|
||||
t.create('No URI specified')
|
||||
.get('.json?query=$.name&label=Package Name')
|
||||
.expectJSON({ name: 'Package Name', value: 'no uri specified' });
|
||||
|
||||
t.create('JSON from uri')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.name')
|
||||
.expectJSON({ name: 'custom badge', value: 'gh-badges'});
|
||||
|
||||
t.create('JSON from uri | caching with new query params')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.version')
|
||||
.expectJSONTypes(Joi.object().keys({
|
||||
name: 'custom badge',
|
||||
value: Joi.string().regex(/^\d+(\.\d+)?(\.\d+)?$/)
|
||||
}));
|
||||
|
||||
t.create('JSON from uri | with prefix & suffix & label')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.version&prefix=v&suffix= dev&label=Shields')
|
||||
.expectJSONTypes(Joi.object().keys({
|
||||
name: 'Shields',
|
||||
value: Joi.string().regex(/^v\d+(\.\d+)?(\.\d+)?\sdev$/)
|
||||
}));
|
||||
|
||||
t.create('JSON from uri | object doesnt exist')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/package.json&query=$.does_not_exist')
|
||||
.expectJSON({ name: 'custom badge', value: '' });
|
||||
|
||||
t.create('JSON from uri | invalid uri')
|
||||
.get('.json?uri=https://github.com/badges/shields/raw/master/notafile.json&query=$.version')
|
||||
.expectJSON({ name: 'custom badge', value: 'invalid resource' });
|
||||
Reference in New Issue
Block a user