Skip to content

Commit 2848969

Browse files
RunDevelopmentmAAdhaTTah
authored andcommitted
Cleanup JSONP highlight code (#1674)
Document, refactor and format the JSONP Highlighting plugin.
1 parent dbd3555 commit 2848969

File tree

2 files changed

+97
-60
lines changed

2 files changed

+97
-60
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,167 @@
1-
(function() {
2-
if ( !self.Prism || !self.document || !document.querySelectorAll || ![].filter) return;
1+
(function () {
2+
if (!self.Prism || !self.document || !document.querySelectorAll || ![].filter) return;
33

4+
/**
5+
* The list of adapter which will be used if `data-adapter` is not specified.
6+
*
7+
* @type {Array.<(response: any, pre?: HTMLPreElement) => string>}
8+
*/
49
var adapters = [];
10+
11+
/**
12+
* Adds a new function to the list of adapters.
13+
*
14+
* If the given adapter is already registered or not a function, nothing will happen.
15+
*
16+
* @param {(response: any, pre?: HTMLPreElement) => string} adapter The adapter to be registered.
17+
*/
518
function registerAdapter(adapter) {
619
if (typeof adapter === "function" && !getAdapter(adapter)) {
720
adapters.push(adapter);
821
}
922
}
23+
/**
24+
* Returns the given adapter itself, if registered, or a registered adapter with the given function name.
25+
*
26+
* If no fitting adapter is registered, `null` will be returned.
27+
*
28+
* @param {string|Function} adapter The adapter itself or the function name of an adapter.
29+
* @returns {(response: any, pre?: HTMLPreElement) => string} A registered adapter or `null`.
30+
*/
1031
function getAdapter(adapter) {
1132
if (typeof adapter === "function") {
12-
return adapters.filter(function(fn) { return fn.valueOf() === adapter.valueOf()})[0];
33+
return adapters.filter(function (fn) { return fn.valueOf() === adapter.valueOf(); })[0];
1334
}
1435
else if (typeof adapter === "string" && adapter.length > 0) {
15-
return adapters.filter(function(fn) { return fn.name === adapter})[0];
36+
return adapters.filter(function (fn) { return fn.name === adapter; })[0];
1637
}
1738
return null;
1839
}
40+
/**
41+
* Remove the given adapter or the first registered adapter with the given function name from the list of
42+
* registered adapters.
43+
*
44+
* @param {string|Function} adapter The adapter itself or the function name of an adapter.
45+
*/
1946
function removeAdapter(adapter) {
20-
if (typeof adapter === "string")
47+
if (typeof adapter === "string") {
2148
adapter = getAdapter(adapter);
49+
}
2250
if (typeof adapter === "function") {
2351
var index = adapters.indexOf(adapter);
24-
if (index >=0) {
25-
adapters.splice(index,1);
52+
if (index >= 0) {
53+
adapters.splice(index, 1);
2654
}
2755
}
2856
}
2957

30-
Prism.plugins.jsonphighlight = {
31-
registerAdapter: registerAdapter,
32-
removeAdapter: removeAdapter,
33-
highlight: highlight
34-
};
3558
registerAdapter(function github(rsp, el) {
36-
if ( rsp && rsp.meta && rsp.data ) {
37-
if ( rsp.meta.status && rsp.meta.status >= 400 ) {
38-
return "Error: " + ( rsp.data.message || rsp.meta.status );
59+
if (rsp && rsp.meta && rsp.data) {
60+
if (rsp.meta.status && rsp.meta.status >= 400) {
61+
return "Error: " + (rsp.data.message || rsp.meta.status);
3962
}
40-
else if ( typeof(rsp.data.content) === "string" ) {
41-
return typeof(atob) === "function"
63+
else if (typeof (rsp.data.content) === "string") {
64+
return typeof (atob) === "function"
4265
? atob(rsp.data.content.replace(/\s/g, ""))
4366
: "Your browser cannot decode base64";
4467
}
4568
}
4669
return null;
4770
});
4871
registerAdapter(function gist(rsp, el) {
49-
if ( rsp && rsp.meta && rsp.data && rsp.data.files ) {
50-
if ( rsp.meta.status && rsp.meta.status >= 400 ) {
51-
return "Error: " + ( rsp.data.message || rsp.meta.status );
72+
if (rsp && rsp.meta && rsp.data && rsp.data.files) {
73+
if (rsp.meta.status && rsp.meta.status >= 400) {
74+
return "Error: " + (rsp.data.message || rsp.meta.status);
5275
}
53-
else {
54-
var filename = el.getAttribute("data-filename");
55-
if (filename == null) {
56-
// Maybe in the future we can somehow render all files
57-
// But the standard <script> include for gists does that nicely already,
58-
// so that might be getting beyond the scope of this plugin
59-
for (var key in rsp.data.files) {
60-
if (rsp.data.files.hasOwnProperty(key)) {
61-
filename = key;
62-
break;
63-
}
76+
77+
var files = rsp.data.files;
78+
var filename = el.getAttribute("data-filename");
79+
if (filename == null) {
80+
// Maybe in the future we can somehow render all files
81+
// But the standard <script> include for gists does that nicely already,
82+
// so that might be getting beyond the scope of this plugin
83+
for (var key in files) {
84+
if (files.hasOwnProperty(key)) {
85+
filename = key;
86+
break;
6487
}
6588
}
66-
if (rsp.data.files[filename] !== undefined) {
67-
return rsp.data.files[filename].content;
68-
}
69-
else {
70-
return "Error: unknown or missing gist file " + filename;
71-
}
7289
}
90+
91+
if (files[filename] !== undefined) {
92+
return files[filename].content;
93+
}
94+
return "Error: unknown or missing gist file " + filename;
7395
}
7496
return null;
7597
});
7698
registerAdapter(function bitbucket(rsp, el) {
77-
return rsp && rsp.node && typeof(rsp.data) === "string"
78-
? rsp.data
79-
: null;
99+
if (rsp && rsp.node && typeof (rsp.data) === "string") {
100+
return rsp.data;
101+
}
102+
return null;
80103
});
81104

82105
var jsonpcb = 0,
83-
loadstr = "Loading";
106+
loadMsg = "Loading\u2026";
84107

108+
/**
109+
* Highlights all `pre` elements with an `data-jsonp` by requesting the specified JSON and using the specified adapter
110+
* or a registered adapter to extract the code to highlight from the response. The highlighted code will be inserted
111+
* into the `pre` element.
112+
*/
85113
function highlight() {
86-
Array.prototype.slice.call(document.querySelectorAll("pre[data-jsonp]")).forEach(function(pre) {
114+
Array.prototype.slice.call(document.querySelectorAll("pre[data-jsonp]")).forEach(function (pre) {
87115
pre.textContent = "";
88116

89117
var code = document.createElement("code");
90-
code.textContent = loadstr;
118+
code.textContent = loadMsg;
91119
pre.appendChild(code);
92120

93-
var adapterfn = pre.getAttribute("data-adapter");
121+
var adapterName = pre.getAttribute("data-adapter");
94122
var adapter = null;
95-
if ( adapterfn ) {
96-
if ( typeof(window[adapterfn]) === "function" ) {
97-
adapter = window[adapterfn];
123+
if (adapterName) {
124+
if (typeof window[adapterName] === "function") {
125+
adapter = window[adapterName];
98126
}
99127
else {
100-
code.textContent = "JSONP adapter function '" + adapterfn + "' doesn't exist";
128+
code.textContent = "JSONP adapter function '" + adapterName + "' doesn't exist";
101129
return;
102130
}
103131
}
104132

105-
var cb = "prismjsonp" + ( jsonpcb++ );
106-
133+
var cb = "prismjsonp" + jsonpcb++;
134+
107135
var uri = document.createElement("a");
108136
var src = uri.href = pre.getAttribute("data-jsonp");
109-
uri.href += ( uri.search ? "&" : "?" ) + ( pre.getAttribute("data-callback") || "callback" ) + "=" + cb;
137+
uri.href += (uri.search ? "&" : "?") + (pre.getAttribute("data-callback") || "callback") + "=" + cb;
110138

111-
var timeout = setTimeout(function() {
139+
var timeout = setTimeout(function () {
112140
// we could clean up window[cb], but if the request finally succeeds, keeping it around is a good thing
113-
if ( code.textContent === loadstr )
141+
if (code.textContent === loadMsg) {
114142
code.textContent = "Timeout loading '" + src + "'";
143+
}
115144
}, 5000);
116-
145+
117146
var script = document.createElement("script");
118147
script.src = uri.href;
119148

120-
window[cb] = function(rsp) {
149+
window[cb] = function (rsp) {
121150
document.head.removeChild(script);
122151
clearTimeout(timeout);
123152
delete window[cb];
124153

125154
var data = "";
126-
127-
if ( adapter ) {
155+
156+
if (adapter) {
128157
data = adapter(rsp, pre);
129158
}
130159
else {
131-
for ( var p in adapters ) {
160+
for (var p in adapters) {
132161
data = adapters[p](rsp, pre);
133-
if ( data !== null ) break;
162+
if (data !== null) {
163+
break;
164+
}
134165
}
135166
}
136167

@@ -147,5 +178,11 @@
147178
});
148179
}
149180

181+
Prism.plugins.jsonphighlight = {
182+
registerAdapter: registerAdapter,
183+
removeAdapter: removeAdapter,
184+
highlight: highlight
185+
};
186+
150187
highlight();
151188
})();

plugins/jsonp-highlight/prism-jsonp-highlight.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)