JSONP Highlight: Refactored JSONP logic (#3018)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
diff --git a/plugins/jsonp-highlight/prism-jsonp-highlight.js b/plugins/jsonp-highlight/prism-jsonp-highlight.js
index ba07b58..28541a3 100644
--- a/plugins/jsonp-highlight/prism-jsonp-highlight.js
+++ b/plugins/jsonp-highlight/prism-jsonp-highlight.js
@@ -126,6 +126,49 @@
var jsonpCallbackCounter = 0;
+ /**
+ * Makes a JSONP request.
+ *
+ * @param {string} src The URL of the resource to request.
+ * @param {string | undefined | null} callbackParameter The name of the callback parameter. If falsy, `"callback"`
+ * will be used.
+ * @param {(data: unknown) => void} onSuccess
+ * @param {(reason: "timeout" | "network") => void} onError
+ * @returns {void}
+ */
+ function jsonp(src, callbackParameter, onSuccess, onError) {
+ var callbackName = 'prismjsonp' + jsonpCallbackCounter++;
+
+ var uri = document.createElement('a');
+ uri.href = src;
+ uri.href += (uri.search ? '&' : '?') + (callbackParameter || 'callback') + '=' + callbackName;
+
+ var script = document.createElement('script');
+ script.src = uri.href;
+ script.onerror = function () {
+ cleanup();
+ onError('network');
+ };
+
+ var timeoutId = setTimeout(function () {
+ cleanup();
+ onError('timeout');
+ }, Prism.plugins.jsonphighlight.timeout);
+
+ function cleanup() {
+ clearTimeout(timeoutId);
+ document.head.removeChild(script);
+ delete window[callbackName];
+ }
+
+ // the JSONP callback function
+ window[callbackName] = function (response) {
+ cleanup();
+ onSuccess(response);
+ };
+
+ document.head.appendChild(script);
+ }
var LOADING_MESSAGE = 'Loading…';
var MISSING_ADAPTER_MESSAGE = function (name) {
@@ -185,61 +228,45 @@
}
}
- var callbackName = 'prismjsonp' + jsonpCallbackCounter++;
-
- var uri = document.createElement('a');
- var src = uri.href = pre.getAttribute('data-jsonp');
- uri.href += (uri.search ? '&' : '?') + (pre.getAttribute('data-callback') || 'callback') + '=' + callbackName;
-
-
- var timeout = setTimeout(function () {
- // we could clean up window[cb], but if the request finally succeeds, keeping it around is a good thing
-
- // mark as failed
- pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
-
- code.textContent = TIMEOUT_MESSAGE(src);
- }, Prism.plugins.jsonphighlight.timeout);
-
+ var src = pre.getAttribute('data-jsonp');
+
+ jsonp(
+ src,
+ pre.getAttribute('data-callback'),
+ function (response) {
+ // interpret the received data using the adapter(s)
+ var data = null;
+ if (adapter) {
+ data = adapter(response, pre);
+ } else {
+ for (var i = 0, l = adapters.length; i < l; i++) {
+ data = adapters[i].adapter(response, pre);
+ if (data !== null) {
+ break;
+ }
+ }
+ }
- var script = document.createElement('script');
- script.src = uri.href;
+ if (data === null) {
+ // mark as failed
+ pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
- // the JSONP callback function
- window[callbackName] = function (response) {
- // clean up
- document.head.removeChild(script);
- clearTimeout(timeout);
- delete window[callbackName];
+ code.textContent = UNKNOWN_FAILURE_MESSAGE;
+ } else {
+ // mark as loaded
+ pre.setAttribute(STATUS_ATTR, STATUS_LOADED);
- // interpret the received data using the adapter(s)
- var data = null;
- if (adapter) {
- data = adapter(response, pre);
- } else {
- for (var i = 0, l = adapters.length; i < l; i++) {
- data = adapters[i].adapter(response, pre);
- if (data !== null) {
- break;
- }
+ code.textContent = data;
+ Prism.highlightElement(code);
}
- }
-
- if (data === null) {
+ },
+ function () {
// mark as failed
pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
- code.textContent = UNKNOWN_FAILURE_MESSAGE;
- } else {
- // mark as loaded
- pre.setAttribute(STATUS_ATTR, STATUS_LOADED);
-
- code.textContent = data;
- Prism.highlightElement(code);
+ code.textContent = TIMEOUT_MESSAGE(src);
}
- };
-
- document.head.appendChild(script);
+ );
}
});
diff --git a/plugins/jsonp-highlight/prism-jsonp-highlight.min.js b/plugins/jsonp-highlight/prism-jsonp-highlight.min.js
index dde26c0..b6303a8 100644
--- a/plugins/jsonp-highlight/prism-jsonp-highlight.min.js
+++ b/plugins/jsonp-highlight/prism-jsonp-highlight.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var c=[];t(function(t){if(t&&t.meta&&t.data){if(t.meta.status&&400<=t.meta.status)return"Error: "+(t.data.message||t.meta.status);if("string"==typeof t.data.content)return"function"==typeof atob?atob(t.data.content.replace(/\s/g,"")):"Your browser cannot decode base64"}return null},"github"),t(function(t,e){if(t&&t.meta&&t.data&&t.data.files){if(t.meta.status&&400<=t.meta.status)return"Error: "+(t.data.message||t.meta.status);var n=t.data.files,a=e.getAttribute("data-filename");if(null==a)for(var r in n)if(n.hasOwnProperty(r)){a=r;break}return void 0!==n[a]?n[a].content:"Error: unknown or missing gist file "+a}return null},"gist"),t(function(t){return t&&t.node&&"string"==typeof t.data?t.data:null},"bitbucket");var m=0,p="data-jsonp-status",g="loading",h="loaded",v="failed",b="pre[data-jsonp]:not(["+p+'="'+h+'"]):not(['+p+'="'+g+'"])';Prism.hooks.add("before-highlightall",function(t){t.selector+=", "+b}),Prism.hooks.add("before-sanity-check",function(t){var r=t.element;if(r.matches(b)){t.code="",r.setAttribute(p,g);var i=r.appendChild(document.createElement("CODE"));i.textContent="Loading…";var e=t.language;i.className="language-"+e;var n=Prism.plugins.autoloader;n&&n.loadLanguages(e);var a=r.getAttribute("data-adapter"),o=null;if(a){if("function"!=typeof window[a])return r.setAttribute(p,v),void(i.textContent=function(t){return'✖ Error: JSONP adapter function "'+t+"\" doesn't exist"}(a));o=window[a]}var u="prismjsonp"+m++,s=document.createElement("a"),d=s.href=r.getAttribute("data-jsonp");s.href+=(s.search?"&":"?")+(r.getAttribute("data-callback")||"callback")+"="+u;var f=setTimeout(function(){r.setAttribute(p,v),i.textContent=function(t){return"✖ Error: Timeout loading "+t}(d)},Prism.plugins.jsonphighlight.timeout),l=document.createElement("script");l.src=s.href,window[u]=function(t){document.head.removeChild(l),clearTimeout(f),delete window[u];var e=null;if(o)e=o(t,r);else for(var n=0,a=c.length;n<a&&null===(e=c[n].adapter(t,r));n++);null===e?(r.setAttribute(p,v),i.textContent="✖ Error: Cannot parse response (perhaps you need an adapter function?)"):(r.setAttribute(p,h),i.textContent=e,Prism.highlightElement(i))},document.head.appendChild(l)}}),Prism.plugins.jsonphighlight={timeout:5e3,registerAdapter:t,removeAdapter:function(e){if("string"==typeof e&&(e=n(e)),"function"==typeof e){var t=c.findIndex(function(t){return t.adapter===e});0<=t&&c.splice(t,1)}},highlight:function(t){for(var e,n=(t||document).querySelectorAll(b),a=0;e=n[a++];)Prism.highlightElement(e)}}}function t(t,e){e=e||t.name,"function"!=typeof t||n(t)||n(e)||c.push({adapter:t,name:e})}function n(t){if("function"==typeof t){for(var e=0;n=c[e++];)if(n.adapter.valueOf()===t.valueOf())return n.adapter}else if("string"==typeof t){var n;for(e=0;n=c[e++];)if(n.name===t)return n.adapter}return null}}();
\ No newline at end of file
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var s=[];t(function(t){if(t&&t.meta&&t.data){if(t.meta.status&&400<=t.meta.status)return"Error: "+(t.data.message||t.meta.status);if("string"==typeof t.data.content)return"function"==typeof atob?atob(t.data.content.replace(/\s/g,"")):"Your browser cannot decode base64"}return null},"github"),t(function(t,e){if(t&&t.meta&&t.data&&t.data.files){if(t.meta.status&&400<=t.meta.status)return"Error: "+(t.data.message||t.meta.status);var n=t.data.files,a=e.getAttribute("data-filename");if(null==a)for(var r in n)if(n.hasOwnProperty(r)){a=r;break}return void 0!==n[a]?n[a].content:"Error: unknown or missing gist file "+a}return null},"gist"),t(function(t){return t&&t.node&&"string"==typeof t.data?t.data:null},"bitbucket");var f=0,d="data-jsonp-status",l="loading",c="loaded",m="failed",p="pre[data-jsonp]:not(["+d+'="'+c+'"]):not(['+d+'="'+l+'"])';Prism.hooks.add("before-highlightall",function(t){t.selector+=", "+p}),Prism.hooks.add("before-sanity-check",function(t){var r=t.element;if(r.matches(p)){t.code="",r.setAttribute(d,l);var i=r.appendChild(document.createElement("CODE"));i.textContent="Loading…";var e=t.language;i.className="language-"+e;var n=Prism.plugins.autoloader;n&&n.loadLanguages(e);var a=r.getAttribute("data-adapter"),o=null;if(a){if("function"!=typeof window[a])return r.setAttribute(d,m),void(i.textContent=function(t){return'✖ Error: JSONP adapter function "'+t+"\" doesn't exist"}(a));o=window[a]}var u=r.getAttribute("data-jsonp");!function(t,e,n,a){var r="prismjsonp"+f++,i=document.createElement("a");i.href=t,i.href+=(i.search?"&":"?")+(e||"callback")+"="+r;var o=document.createElement("script");o.src=i.href,o.onerror=function(){s(),a("network")};var u=setTimeout(function(){s(),a("timeout")},Prism.plugins.jsonphighlight.timeout);function s(){clearTimeout(u),document.head.removeChild(o),delete window[r]}window[r]=function(t){s(),n(t)},document.head.appendChild(o)}(u,r.getAttribute("data-callback"),function(t){var e=null;if(o)e=o(t,r);else for(var n=0,a=s.length;n<a&&null===(e=s[n].adapter(t,r));n++);null===e?(r.setAttribute(d,m),i.textContent="✖ Error: Cannot parse response (perhaps you need an adapter function?)"):(r.setAttribute(d,c),i.textContent=e,Prism.highlightElement(i))},function(){r.setAttribute(d,m),i.textContent=function(t){return"✖ Error: Timeout loading "+t}(u)})}}),Prism.plugins.jsonphighlight={timeout:5e3,registerAdapter:t,removeAdapter:function(e){if("string"==typeof e&&(e=n(e)),"function"==typeof e){var t=s.findIndex(function(t){return t.adapter===e});0<=t&&s.splice(t,1)}},highlight:function(t){for(var e,n=(t||document).querySelectorAll(p),a=0;e=n[a++];)Prism.highlightElement(e)}}}function t(t,e){e=e||t.name,"function"!=typeof t||n(t)||n(e)||s.push({adapter:t,name:e})}function n(t){if("function"==typeof t){for(var e=0;n=s[e++];)if(n.adapter.valueOf()===t.valueOf())return n.adapter}else if("string"==typeof t){var n;for(e=0;n=s[e++];)if(n.name===t)return n.adapter}return null}}();
\ No newline at end of file