From 5126d1e118f42e14ff1608e7328c91278f5732d2 Mon Sep 17 00:00:00 2001 From: Michael Schmidt Date: Thu, 12 Aug 2021 15:10:40 +0200 Subject: [PATCH] JSONP Highlight: Refactored JSONP logic (#3018) --- .../jsonp-highlight/prism-jsonp-highlight.js | 121 +++++++++++------- .../prism-jsonp-highlight.min.js | 2 +- 2 files changed, 75 insertions(+), 48 deletions(-) diff --git a/plugins/jsonp-highlight/prism-jsonp-highlight.js b/plugins/jsonp-highlight/prism-jsonp-highlight.js index ba07b58f27..28541a3f3d 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 dde26c0144..b6303a827d 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