UNPKG

react-kiwi-dropdown

Version:

A minimal, easy-to-use and highly adjustable dropdown component made with ReactJS.

207 lines (185 loc) 5.86 kB
(function () { if (!self.Prism || !self.document || !document.querySelectorAll || ![].filter) return; /** * @callback Adapter * @param {any} response * @param {HTMLPreElement} [pre] * @returns {string} */ /** * The list of adapter which will be used if `data-adapter` is not specified. * * @type {Array.<{adapter: Adapter, name: string}>} */ var adapters = []; /** * Adds a new function to the list of adapters. * * If the given adapter is already registered or not a function or there is an adapter with the given name already, * nothing will happen. * * @param {Adapter} adapter The adapter to be registered. * @param {string} [name] The name of the adapter. Defaults to the function name of `adapter`. */ function registerAdapter(adapter, name) { name = name || adapter.name; if (typeof adapter === "function" && !getAdapter(adapter) && !getAdapter(name)) { adapters.push({ adapter: adapter, name: name }); } } /** * Returns the given adapter itself, if registered, or a registered adapter with the given name. * * If no fitting adapter is registered, `null` will be returned. * * @param {string|Function} adapter The adapter itself or the name of an adapter. * @returns {Adapter} A registered adapter or `null`. */ function getAdapter(adapter) { if (typeof adapter === "function") { for (var i = 0, item; item = adapters[i++];) { if (item.adapter.valueOf() === adapter.valueOf()) { return item.adapter; } } } else if (typeof adapter === "string") { for (var i = 0, item; item = adapters[i++];) { if (item.name === adapter) { return item.adapter; } } } return null; } /** * Remove the given adapter or the first registered adapter with the given name from the list of * registered adapters. * * @param {string|Function} adapter The adapter itself or the name of an adapter. */ function removeAdapter(adapter) { if (typeof adapter === "string") { adapter = getAdapter(adapter); } if (typeof adapter === "function") { var index = adapters.map(function (item) { return item.adapter; }).indexOf(adapter); if (index >= 0) { adapters.splice(index, 1); } } } 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; }, 'github'); 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); } var files = rsp.data.files; 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 files) { if (files.hasOwnProperty(key)) { filename = key; break; } } } if (files[filename] !== undefined) { return files[filename].content; } return "Error: unknown or missing gist file " + filename; } return null; }, 'gist'); registerAdapter(function bitbucket(rsp, el) { if (rsp && rsp.node && typeof (rsp.data) === "string") { return rsp.data; } return null; }, 'bitbucket'); var jsonpcb = 0, loadMsg = "Loading\u2026"; /** * Highlights all `pre` elements with an `data-jsonp` by requesting the specified JSON and using the specified adapter * or a registered adapter to extract the code to highlight from the response. The highlighted code will be inserted * into the `pre` element. */ function highlight() { Array.prototype.slice.call(document.querySelectorAll("pre[data-jsonp]")).forEach(function (pre) { pre.textContent = ""; var code = document.createElement("code"); code.textContent = loadMsg; pre.appendChild(code); var adapterName = pre.getAttribute("data-adapter"); var adapter = null; if (adapterName) { if (typeof window[adapterName] === "function") { adapter = window[adapterName]; } else { code.textContent = "JSONP adapter function '" + adapterName + "' 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 === loadMsg) { 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].adapter(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); }); } Prism.plugins.jsonphighlight = { registerAdapter: registerAdapter, removeAdapter: removeAdapter, highlight: highlight }; highlight(); })();