| Index: lib/src/prism/plugins/jsonp-highlight/prism-jsonp-highlight.js
 | 
| diff --git a/lib/src/prism/plugins/jsonp-highlight/prism-jsonp-highlight.js b/lib/src/prism/plugins/jsonp-highlight/prism-jsonp-highlight.js
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..06a9e68c09f1174f533fab0ab7ea830e3db21e54
 | 
| --- /dev/null
 | 
| +++ b/lib/src/prism/plugins/jsonp-highlight/prism-jsonp-highlight.js
 | 
| @@ -0,0 +1,151 @@
 | 
| +(function() {
 | 
| +	if ( !self.Prism || !self.document || !document.querySelectorAll ) return;
 | 
| +
 | 
| +	var adapters = [];
 | 
| +	function registerAdapter(adapter) {
 | 
| +		if (typeof adapter === "function" && !getAdapter(adapter)) {
 | 
| +			adapters.push(adapter);
 | 
| +		}
 | 
| +	}
 | 
| +	function getAdapter(adapter) {
 | 
| +		if (typeof adapter === "function") {
 | 
| +			return adapters.filter(function(fn) { return fn.valueOf() === adapter.valueOf()})[0];
 | 
| +		}
 | 
| +		else if (typeof adapter === "string" && adapter.length > 0) {
 | 
| +			return adapters.filter(function(fn) { return fn.name === adapter})[0];
 | 
| +		}
 | 
| +		return null;
 | 
| +	}
 | 
| +	function removeAdapter(adapter) {
 | 
| +		if (typeof adapter === "string")
 | 
| +			adapter = getAdapter(adapter);
 | 
| +		if (typeof adapter === "function") {
 | 
| +			var index = adapters.indexOf(adapter);
 | 
| +			if (index >=0) {
 | 
| +				adapters.splice(index,1);
 | 
| +			}
 | 
| +		}
 | 
| +	}
 | 
| +
 | 
| +	Prism.plugins.jsonphighlight = {
 | 
| +		registerAdapter: registerAdapter,
 | 
| +		removeAdapter: removeAdapter,
 | 
| +		highlight: highlight
 | 
| +	};
 | 
| +	registerAdapter(function github(rsp, el) {
 | 
| +		if ( rsp && rsp.meta && rsp.data ) {
 | 
| +			if ( rsp.meta.status && rsp.meta.status >= 400 ) {
 | 
| +				return "Error: " + ( rsp.data.message || rsp.meta.status );
 | 
| +			}
 | 
| +			else if ( typeof(rsp.data.content) === "string" ) {
 | 
| +				return typeof(atob) === "function"
 | 
| +					? atob(rsp.data.content.replace(/\s/g, ""))
 | 
| +					: "Your browser cannot decode base64";
 | 
| +			}
 | 
| +		}
 | 
| +		return null;
 | 
| +	});
 | 
| +	registerAdapter(function gist(rsp, el) {
 | 
| +		if ( rsp && rsp.meta && rsp.data && rsp.data.files ) {
 | 
| +			if ( rsp.meta.status && rsp.meta.status >= 400 ) {
 | 
| +				return "Error: " + ( rsp.data.message || rsp.meta.status );
 | 
| +			}
 | 
| +			else {
 | 
| +				var filename = el.getAttribute("data-filename");
 | 
| +				if (filename == null) {
 | 
| +					// Maybe in the future we can somehow render all files
 | 
| +					// But the standard <script> include for gists does that nicely already,
 | 
| +					// so that might be getting beyond the scope of this plugin
 | 
| +					for (var key in rsp.data.files) {
 | 
| +						if (rsp.data.files.hasOwnProperty(key)) {
 | 
| +							filename = key;
 | 
| +							break;
 | 
| +						}
 | 
| +					}
 | 
| +				}
 | 
| +				if (rsp.data.files[filename] !== undefined) {
 | 
| +					return rsp.data.files[filename].content;
 | 
| +				}
 | 
| +				else {
 | 
| +					return "Error: unknown or missing gist file " + filename;
 | 
| +				}
 | 
| +			}
 | 
| +		}
 | 
| +		return null;
 | 
| +	});
 | 
| +	registerAdapter(function bitbucket(rsp, el) {
 | 
| +		return rsp && rsp.node && typeof(rsp.data) === "string"
 | 
| +			? rsp.data
 | 
| +			: null;
 | 
| +	});
 | 
| +
 | 
| +	var jsonpcb = 0,
 | 
| +	    loadstr = "Loading…";
 | 
| +
 | 
| +	function highlight() {
 | 
| +		Array.prototype.slice.call(document.querySelectorAll("pre[data-jsonp]")).forEach(function(pre) {
 | 
| +			pre.textContent = "";
 | 
| +
 | 
| +			var code = document.createElement("code");
 | 
| +			code.textContent = loadstr;
 | 
| +			pre.appendChild(code);
 | 
| +
 | 
| +			var adapterfn = pre.getAttribute("data-adapter");
 | 
| +			var adapter = null;
 | 
| +			if ( adapterfn ) {
 | 
| +				if ( typeof(window[adapterfn]) === "function" ) {
 | 
| +					adapter = window[adapterfn];
 | 
| +				}
 | 
| +				else {
 | 
| +					code.textContent = "JSONP adapter function '" + adapterfn + "' doesn't exist";
 | 
| +					return;
 | 
| +				}
 | 
| +			}
 | 
| +
 | 
| +			var cb = "prismjsonp" + ( jsonpcb++ );
 | 
| +			
 | 
| +			var uri = document.createElement("a");
 | 
| +			var src = uri.href = pre.getAttribute("data-jsonp");
 | 
| +			uri.href += ( uri.search ? "&" : "?" ) + ( pre.getAttribute("data-callback") || "callback" ) + "=" + cb;
 | 
| +
 | 
| +			var timeout = setTimeout(function() {
 | 
| +				// we could clean up window[cb], but if the request finally succeeds, keeping it around is a good thing
 | 
| +				if ( code.textContent === loadstr )
 | 
| +					code.textContent = "Timeout loading '" + src + "'";
 | 
| +			}, 5000);
 | 
| +			
 | 
| +			var script = document.createElement("script");
 | 
| +			script.src = uri.href;
 | 
| +
 | 
| +			window[cb] = function(rsp) {
 | 
| +				document.head.removeChild(script);
 | 
| +				clearTimeout(timeout);
 | 
| +				delete window[cb];
 | 
| +
 | 
| +				var data = "";
 | 
| +				
 | 
| +				if ( adapter ) {
 | 
| +					data = adapter(rsp, pre);
 | 
| +				}
 | 
| +				else {
 | 
| +					for ( var p in adapters ) {
 | 
| +						data = adapters[p](rsp, pre);
 | 
| +						if ( data !== null ) break;
 | 
| +					}
 | 
| +				}
 | 
| +
 | 
| +				if (data === null) {
 | 
| +					code.textContent = "Cannot parse response (perhaps you need an adapter function?)";
 | 
| +				}
 | 
| +				else {
 | 
| +					code.textContent = data;
 | 
| +					Prism.highlightElement(code);
 | 
| +				}
 | 
| +			};
 | 
| +
 | 
| +			document.head.appendChild(script);
 | 
| +		});
 | 
| +	}
 | 
| +
 | 
| +	highlight();
 | 
| +})();
 | 
| 
 |