diff --git a/frontend/fragments/try-footer.html b/frontend/fragments/try-footer.html
index 0982cfea4f3f2..5684d355ac636 100644
--- a/frontend/fragments/try-footer.html
+++ b/frontend/fragments/try-footer.html
@@ -1,6 +1,8 @@
Your Badge
+ Static
+
+
+
+/badge/dynamic/<TYPE>.svg?uri=<URI>&label=<LABEL>&query=<$.DATA.SUBDATA>&colorB=<COLOR>&prefix=<PREFIX>&suffix=<SUFFIX>
+
+
+
Styles
The following styles are available (flat is the default as of Feb 1st 2015):
@@ -448,6 +471,18 @@
Like This?
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, '__'));
}
diff --git a/package.json b/package.json
index 190498055cf5c..12328e6c4456f 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/server.js b/server.js
index 1a8982d820975..407f1a319ce46 100644
--- a/server.js
+++ b/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
diff --git a/service-tests/json.js b/service-tests/json.js
new file mode 100644
index 0000000000000..0861b0c78308e
--- /dev/null
+++ b/service-tests/json.js
@@ -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' });