From 716d1e1804497293a735e0bc6a0580355f4e4060 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Tue, 31 May 2022 09:54:41 +0200 Subject: [PATCH] Kick jsonp - fixes #2682 --- README.md | 2 +- docs/api.md | 15 ---- docs/buildPathname.md | 2 +- docs/jsonp.md | 103 --------------------------- docs/nav-methods.md | 1 - docs/paths.md | 6 +- docs/redraw.md | 2 +- docs/request.md | 2 +- index.js | 1 - mithril.js | 19 ----- mithril.min.js | 2 +- request/request.js | 20 ------ request/tests/test-jsonp.js | 116 ------------------------------- test-utils/tests/test-xhrMock.js | 71 ------------------- test-utils/xhrMock.js | 3 - tests/test-api.js | 5 -- 16 files changed, 8 insertions(+), 362 deletions(-) delete mode 100644 docs/jsonp.md delete mode 100644 request/tests/test-jsonp.js diff --git a/README.md b/README.md index f0c53553d..a1291709f 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ ## What is Mithril.js? -A modern client-side JavaScript framework for building Single Page Applications. It's small (9.34 KB gzipped), fast and provides routing and XHR utilities out of the box. +A modern client-side JavaScript framework for building Single Page Applications. It's small (9.18 KB gzipped), fast and provides routing and XHR utilities out of the box. Mithril.js is used by companies like Vimeo and Nike, and open source platforms like Lichess 👍. diff --git a/docs/api.md b/docs/api.md index 758b0cce7..6141fb58a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -92,21 +92,6 @@ m.request({ --- -#### m.jsonp(options) - [docs](jsonp.md) - -```javascript -m.jsonp({ - url: "/api/v1/users/:id", - params: {id: 1}, - callbackKey: "callback", -}) -.then(function(result) { - console.log(result) -}) -``` - ---- - #### m.parseQueryString(querystring) - [docs](parseQueryString.md) ```javascript diff --git a/docs/buildPathname.md b/docs/buildPathname.md index dfc087e9a..df1220e88 100644 --- a/docs/buildPathname.md +++ b/docs/buildPathname.md @@ -36,7 +36,7 @@ Argument | Type | Required | Descripti ### How it works -The `m.buildPathname` creates a [path name](paths.md) from a path template and a parameters object. It's useful for building URLs, and it's what [`m.route`](route.md), [`m.request`](request.md), and [`m.jsonp`](jsonp.md) all use internally to interpolate paths. It uses [`m.buildQueryString`](buildQueryString.md) to generate the query parameters to append to the path name. +The `m.buildPathname` creates a [path name](paths.md) from a path template and a parameters object. It's useful for building URLs, and it's what [`m.route`](route.md) and [`m.request`](request.md) use internally to interpolate paths. It uses [`m.buildQueryString`](buildQueryString.md) to generate the query parameters to append to the path name. ```javascript var pathname = m.buildPathname("/path/:id", {id: "user", a: 1, b: 2}) diff --git a/docs/jsonp.md b/docs/jsonp.md deleted file mode 100644 index b46c48ddd..000000000 --- a/docs/jsonp.md +++ /dev/null @@ -1,103 +0,0 @@ - - -# jsonp(options) - -- [Description](#description) -- [Signature](#signature) -- [How it works](#how-it-works) -- [Typical usage](#typical-usage) - ---- - -### Description - -Makes JSON-P requests. Typically, it's useful to interact with servers that allow JSON-P but that don't have CORS enabled. - -```javascript -m.jsonp({ - url: "/api/v1/users/:id", - params: {id: 1}, - callbackKey: "callback", -}) -.then(function(result) { - console.log(result) -}) -``` - ---- - -### Signature - -`promise = m.jsonp(options)` - -Argument | Type | Required | Description ----------------------- | --------------------------------- | -------- | --- -`options` | `Object` | Yes | The request options to pass. -`options.url` | `String` | Yes | The [path name](paths.md) to send the request to, optionally interpolated with values from `options.params`. -`options.params` | `Object` | No | The data to be interpolated into the URL and serialized into the querystring. -`options.type` | `any = Function(any)` | No | A constructor to be applied to each object in the response. Defaults to the [identity function](https://en.wikipedia.org/wiki/Identity_function). -`options.callbackName` | `String` | No | The name of the function that will be called as the callback. Defaults to a randomized string (e.g. `_mithril_6888197422121285_0({a: 1})` -`options.callbackKey` | `String` | No | The name of the querystring parameter name that specifies the callback name. Defaults to `callback` (e.g. `/someapi?callback=_mithril_6888197422121285_0`) -`options.background` | `Boolean` | No | If `false`, redraws mounted components upon completion of the request. If `true`, it does not. Defaults to `false`. -**returns** | `Promise` | | A promise that resolves to the response data, after it has been piped through `type` method - -`promise = m.jsonp(url, options)` - -Argument | Type | Required | Description ------------ | --------- | -------- | --- -`url` | `String` | Yes | The [path name](paths.md) to send the request to. `options.url` overrides this when present. -`options` | `Object` | No | The request options to pass. -**returns** | `Promise` | | A promise that resolves to the response data, after it has been piped through the `type` method - -This second form is mostly equivalent to `m.jsonp(Object.assign({url: url}, options))`, just it does not depend on the ES6 global `Object.assign` internally. - -[How to read signatures](signatures.md) - ---- - -#### How it works - -The `m.jsonp` utility is useful for third party APIs that can return data in [JSON-P](https://en.wikipedia.org/wiki/JSONP) format. - -In a nutshell, JSON-P consists of creating a `script` tag whose `src` attribute points to a script that lives in the server outside of your control. Typically, you are required to define a global function and specify its name in the querystring of the script's URL. The response will return code that calls your global function, passing the server's data as the first parameter. - -JSON-P has several limitations: it can only use GET requests, it implicitly trusts that the third party server won't serve malicious code and it requires polluting the global JavaScript scope. Nonetheless, it is sometimes the only available way to retrieve data from a service (for example, if the service doesn't support [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)). - ---- - -### Typical usage - -Some services follow the de-facto convention of responding with JSON-P if a `callback` querystring key is provided, thus making `m.jsonp` automatically work without any effort: - -```javascript -m.jsonp({url: "https://api.github.com/users/lhorie"}).then(function(response) { - console.log(response.data.login) // logs "lhorie" -}) -``` - -Some services do not follow conventions and therefore you must specify the callback key that the service expects: - -```javascript -m.jsonp({ - url: "https://api.flickr.com/services/feeds/photos_public.gne?tags=kitten&format=json", - callbackKey: "jsoncallback", -}) -.then(function(response) { - console.log(response.link) // logs "https://www.flickr.com/photos/tags/kitten/" -}) -``` - -And sometimes, you just want to take advantage of HTTP caching for GET requests for rarely-modified data: - -```javascript -// this request is always called with the same querystring, and therefore it is cached -m.jsonp({ - url: "https://api.github.com/users/lhorie", - callbackName: "__callback", -}) -.then(function(response) { - console.log(response.data.login) // logs "lhorie" -}) -``` diff --git a/docs/nav-methods.md b/docs/nav-methods.md index 9e829de57..b553c77ef 100644 --- a/docs/nav-methods.md +++ b/docs/nav-methods.md @@ -4,7 +4,6 @@ - [m.mount](mount.md) - [m.route](route.md) - [m.request](request.md) - - [m.jsonp](jsonp.md) - [m.parseQueryString](parseQueryString.md) - [m.buildQueryString](buildQueryString.md) - [m.buildPathname](buildPathname.md) diff --git a/docs/paths.md b/docs/paths.md index f81a42d41..5dfccbe4f 100644 --- a/docs/paths.md +++ b/docs/paths.md @@ -11,7 +11,7 @@ Documentation on how to work with paths in Mithril.js ----- -[`m.route`](route.md), [`m.request`](request.md), and [`m.jsonp`](jsonp.md) each have a concept called a path. This is used to generate the URL you route to or fetch from. +[`m.route`](route.md) and [`m.request`](request.md) each have a concept called a path. This is used to generate the URL you route to or fetch from. ### Path types @@ -20,7 +20,7 @@ There are two general types of paths: raw paths and parameterized paths. - Raw paths are simply strings used directly as URLs. Nothing is substituted or even split. It's just normalized with all the parameters appended to the end. - Parameterized paths let you insert values into paths, escaped by default for convenience and safety against URL injection. -For [`m.request`](request.md) and [`m.jsonp`](jsonp.md), these can be pretty much any URL, but for [routes](route.md), these can only be absolute URL path names without schemes or domains. +For [`m.request`](request.md) these can be pretty much any URL, but for [routes](route.md), these can only be absolute URL path names without schemes or domains. ### Path parameters @@ -29,7 +29,7 @@ Path parameters are themselves pretty simple. They come in two forms: - `:foo` - This injects a simple `params.foo` into the URL, escaping its value first. - `:foo...` - This injects a raw `params.foo` path into the URL without escaping anything. -You're probably wondering what that `params` object is supposed to be. It's pretty simple: it's the `params` in either [`m.route.set(path, params)`](route.md#mrouteset), [`m.request({url, params})`](request.md#signature), or [`m.jsonp({url, params})`](jsonp.md#signature). +You're probably wondering what that `params` object is supposed to be. It's pretty simple: it's the `params` in either [`m.route.set(path, params)`](route.md#mrouteset), [`m.request({url, params})`](request.md#signature). When receiving routes via [`m.route(root, defaultRoute, routes)`](route.md#signature), you can use these parameters to *extract* values from routes. They work basically the same way as generating the paths, just in the opposite direction. diff --git a/docs/redraw.md b/docs/redraw.md index 57d3e9b85..a224de8f7 100644 --- a/docs/redraw.md +++ b/docs/redraw.md @@ -16,7 +16,7 @@ Documentation on m.redraw(), which schedules an update of all components mounted Updates the DOM after a change in the application data layer. -You DON'T need to call it if data is modified within the execution context of an event handler defined in a Mithril.js view, or after request completion when using `m.request`/`m.jsonp`. The [autoredraw](autoredraw.md) system, which is built on top of `m.redraw()` will take care of it. +You DON'T need to call it if data is modified within the execution context of an event handler defined in a Mithril.js view, or after request completion when using `m.request`. The [autoredraw](autoredraw.md) system, which is built on top of `m.redraw()` will take care of it. You DO need to call it in `setTimeout`/`setInterval`/`requestAnimationFrame` callbacks, or callbacks from 3rd party libraries. diff --git a/docs/request.md b/docs/request.md index 4f5945f17..262e9a172 100644 --- a/docs/request.md +++ b/docs/request.md @@ -502,7 +502,7 @@ Mithril.js' `m.request` uses `XMLHttpRequest` instead of `fetch()` for a number Currently, due to lack of browser support, `fetch()` typically requires a [polyfill](https://github.com/github/fetch), which is over 11kb uncompressed - nearly three times larger than Mithril.js' XHR module. -Despite being much smaller, Mithril.js' XHR module supports many important and not-so-trivial-to-implement features like [URL interpolation](#dynamic-urls), querystring serialization and [JSON-P requests](jsonp.md), in addition to its ability to integrate seamlessly to Mithril.js' autoredrawing subsystem. The `fetch` polyfill does not support any of those, and requires extra libraries and boilerplates to achieve the same level of functionality. +Despite being much smaller, Mithril.js' XHR module supports many important and not-so-trivial-to-implement features like [URL interpolation](#dynamic-urls) and querystring serialization in addition to its ability to integrate seamlessly to Mithril.js' autoredrawing subsystem. The `fetch` polyfill does not support any of those, and requires extra libraries and boilerplates to achieve the same level of functionality. In addition, Mithril.js' XHR module is optimized for JSON-based endpoints and makes that most common case appropriately terse - i.e. `m.request(url)` - whereas `fetch` requires an additional explicit step to parse the response data as JSON: `fetch(url).then(function(response) {return response.json()})` diff --git a/index.js b/index.js index cf797acd0..34e849814 100644 --- a/index.js +++ b/index.js @@ -14,7 +14,6 @@ m.route = require("./route") m.render = require("./render") m.redraw = mountRedraw.redraw m.request = request.request -m.jsonp = request.jsonp m.parseQueryString = require("./querystring/parse") m.buildQueryString = require("./querystring/build") m.parsePathname = require("./pathname/parse") diff --git a/mithril.js b/mithril.js index 1382c4b20..300bebd64 100644 --- a/mithril.js +++ b/mithril.js @@ -1379,24 +1379,6 @@ var _17 = function($window, oncompletion) { else if (body instanceof $window.FormData || body instanceof $window.URLSearchParams) xhr.send(body) else xhr.send(JSON.stringify(body)) }), - jsonp: makeRequest(function(url, args, resolve, reject) { - var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ - var script = $window.document.createElement("script") - $window[callbackName] = function(data) { - delete $window[callbackName] - script.parentNode.removeChild(script) - resolve(data) - } - script.onerror = function() { - delete $window[callbackName] - script.parentNode.removeChild(script) - reject(new Error("JSONP request failed")) - } - script.src = url + (url.indexOf("?") < 0 ? "?" : "&") + - encodeURIComponent(args.callbackKey || "callback") + "=" + - encodeURIComponent(callbackName) - $window.document.documentElement.appendChild(script) - }), } } var request = _17(typeof window !== "undefined" ? window : null, mountRedraw0.redraw) @@ -1799,7 +1781,6 @@ m.route = _26(typeof window !== "undefined" ? window : null, mountRedraw) m.render = render m.redraw = mountRedraw.redraw m.request = request.request -m.jsonp = request.jsonp m.parseQueryString = parseQueryString m.buildQueryString = buildQueryString m.parsePathname = parsePathname diff --git a/mithril.min.js b/mithril.min.js index aba736267..9a07cf4c9 100644 --- a/mithril.min.js +++ b/mithril.min.js @@ -1 +1 @@ -!function(){"use strict";function e(e,t,n,r,o,l){return{tag:e,key:t,attrs:n,children:r,text:o,dom:l,domSize:void 0,state:void 0,events:void 0,instance:void 0}}e.normalize=function(t){return Array.isArray(t)?e("[",void 0,void 0,e.normalizeChildren(t),void 0,void 0):null==t||"boolean"==typeof t?null:"object"==typeof t?t:e("#",void 0,void 0,String(t),void 0,void 0)},e.normalizeChildren=function(t){var n=[];if(t.length){for(var r=null!=t[0]&&null!=t[0].key,o=1;o0&&(i.className=l.join(" ")),o[e]={tag:n,attrs:i}}(i),a):(a.tag=i,a)}i.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},i.fragment=function(){var n=t.apply(0,arguments);return n.tag="[",n.children=e.normalizeChildren(n.children),n};var a=function(t){var n,r=t&&t.document,o={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"};function l(e){return e.attrs&&e.attrs.xmlns||o[e.tag]}function i(e,t){if(e.state!==t)throw new Error("'vnode.state' must not be modified.")}function a(e){var t=e.state;try{return this.apply(t,arguments)}finally{i(e,t)}}function u(){try{return r.activeElement}catch(e){return null}}function s(e,t,n,r,o,l,i){for(var a=n;a'+t.children+"",i=i.firstChild):i.innerHTML=t.children,t.dom=i.firstChild,t.domSize=i.childNodes.length,t.instance=[];for(var a,u=r.createDocumentFragment();a=i.firstChild;)t.instance.push(a),u.appendChild(a);w(e,u,o)}function p(e,t,n,r,o,l){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)s(e,n,0,n.length,r,o,l);else if(null==n||0===n.length)k(e,t,0,t.length);else{var i=null!=t[0]&&null!=t[0].key,a=null!=n[0]&&null!=n[0].key,u=0,f=0;if(!i)for(;f=f&&C>=u&&(w=t[E],b=n[C],w.key===b.key);)w!==b&&h(e,w,b,r,o,l),null!=b.dom&&(o=b.dom),E--,C--;for(;E>=f&&C>=u&&(d=t[f],p=n[u],d.key===p.key);)f++,u++,d!==p&&h(e,d,p,r,y(t,f,o),l);for(;E>=f&&C>=u&&u!==C&&d.key===b.key&&w.key===p.key;)g(e,w,S=y(t,f,o)),w!==p&&h(e,w,p,r,S,l),++u<=--C&&g(e,d,o),d!==b&&h(e,d,b,r,o,l),null!=b.dom&&(o=b.dom),f++,w=t[--E],b=n[C],d=t[f],p=n[u];for(;E>=f&&C>=u&&w.key===b.key;)w!==b&&h(e,w,b,r,o,l),null!=b.dom&&(o=b.dom),C--,w=t[--E],b=n[C];if(u>C)k(e,t,f,E+1);else if(f>E)s(e,n,u,C+1,r,o,l);else{var j,z,A=o,N=C-u+1,O=new Array(N),T=0,$=0,L=2147483647,I=0;for($=0;$=u;$--){null==j&&(j=m(t,f,E+1));var R=j[(b=n[$]).key];null!=R&&(L=R>>1)+(r>>>1)+(n&r&1);e[t[a]]0&&(v[o]=t[n-1]),t[n]=o)}}n=t.length,r=t[n-1];for(;n-- >0;)t[n]=r,r=v[r];return v.length=0,t}(O)).length-1,$=C;$>=u;$--)p=n[$],-1===O[$-u]?c(e,p,r,l,o):z[T]===$-u?T--:g(e,p,o),null!=p.dom&&(o=n[$].dom);else for($=C;$>=u;$--)p=n[$],-1===O[$-u]&&c(e,p,r,l,o),null!=p.dom&&(o=n[$].dom)}}else{var P=t.lengthP&&k(e,t,u,t.length),n.length>P&&s(e,n,u,n.length,r,o,l)}}}function h(t,n,r,o,i,u){var s=n.tag;if(s===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{var n;if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate)if(void 0!==(n=a.call(e.attrs.onbeforeupdate,e,t))&&!n)break;if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate)if(void 0!==(n=a.call(e.state.onbeforeupdate,e,t))&&!n)break;return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,e.attrs=t.attrs,e.children=t.children,e.text=t.text,!0}(r,n))return;if("string"==typeof s)switch(null!=r.attrs&&D(r.attrs,r,o),s){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(S(e,t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize,n.instance=t.instance)}(t,n,r,u,i);break;case"[":!function(e,t,n,r,o,l){p(e,t.children,n.children,r,o,l);var i=0,a=n.children;if(n.dom=null,null!=a){for(var u=0;u-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var O,T=/[A-Z]/g;function $(e){return"-"+e.toLowerCase()}function L(e){return"-"===e[0]&&"-"===e[1]?e:"cssFloat"===e?"float":e.replace(T,$)}function I(e,t,n){if(t===n);else if(null==n)e.style.cssText="";else if("object"!=typeof n)e.style.cssText=n;else if(null==t||"object"!=typeof t)for(var r in e.style.cssText="",n){null!=(o=n[r])&&e.style.setProperty(L(r),String(o))}else{for(var r in n){var o;null!=(o=n[r])&&(o=String(o))!==String(t[r])&&e.style.setProperty(L(r),o)}for(var r in t)null!=t[r]&&null==n[r]&&e.style.removeProperty(L(r))}}function R(){this._=n}function P(e,t,r){if(null!=e.events){if(e.events._=n,e.events[t]===r)return;null==r||"function"!=typeof r&&"object"!=typeof r?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}else null==r||"function"!=typeof r&&"object"!=typeof r||(e.events=new R,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}function _(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function D(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return R.prototype=Object.create(null),R.prototype.handleEvent=function(e){var t,n=this["on"+e.type];"function"==typeof n?t=n.call(e.currentTarget,e):"function"==typeof n.handleEvent&&n.handleEvent(e),this._&&!1!==e.redraw&&(0,this._)(),!1===t&&(e.preventDefault(),e.stopPropagation())},function(t,r,o){if(!t)throw new TypeError("DOM element being rendered to does not exist.");if(null!=O&&t.contains(O))throw new TypeError("Node is currently being rendered to and thus is locked.");var l=n,i=O,a=[],s=u(),c=t.namespaceURI;O=t,n="function"==typeof o?o:void 0;try{null==t.vnodes&&(t.textContent=""),r=e.normalizeChildren(Array.isArray(r)?r:[r]),p(t,t.vnodes,r,a,null,"http://www.w3.org/1999/xhtml"===c?void 0:c),t.vnodes=r,null!=s&&u()!==s&&"function"==typeof s.focus&&s.focus();for(var f=0;f=0&&(o.splice(l,2),l<=i&&(i-=2),t(n,[])),null!=r&&(o.push(n,r),t(n,e(r),u))},redraw:u}}(a,"undefined"!=typeof requestAnimationFrame?requestAnimationFrame:null,"undefined"!=typeof console?console:null),s=function(e){if("[object Object]"!==Object.prototype.toString.call(e))return"";var t=[];for(var n in e)r(n,e[n]);return t.join("&");function r(e,n){if(Array.isArray(n))for(var o=0;o=0&&(m+=e.slice(n,o)),f>=0&&(m+=(n<0?"?":"&")+u.slice(f,p));var v=s(a);return v&&(m+=(n<0&&f<0?"?":"&")+v),r>=0&&(m+=e.slice(r)),d>=0&&(m+=(r<0?"":"&")+u.slice(d)),m},d=function(e,t){var r=0;function o(e){return new Promise(e)}function l(e){return function(n,r){"string"!=typeof n?(r=n,n=n.url):null==r&&(r={});var l=new Promise((function(t,o){e(f(n,r.params),r,(function(e){if("function"==typeof r.type)if(Array.isArray(e))for(var n=0;n=200&&e.target.status<300||304===e.target.status||/^file:\/\//i.test(t),a=e.target.response;if("json"===f){if(!e.target.responseType&&"function"!=typeof r.extract)try{a=JSON.parse(e.target.responseText)}catch(e){a=null}}else f&&"text"!==f||null==a&&(a=e.target.responseText);if("function"==typeof r.extract?(a=r.extract(e.target,r),i=!0):"function"==typeof r.deserialize&&(a=r.deserialize(a)),i)o(a);else{var u=function(){try{n=e.target.responseText}catch(e){n=a}var t=new Error(n);t.code=e.target.status,t.response=a,l(t)};0===d.status?setTimeout((function(){h||u()})):u()}}catch(e){l(e)}},d.ontimeout=function(e){h=!0;var t=new Error("Request timed out");t.code=e.target.status,l(t)},"function"==typeof r.config&&(d=r.config(d,r,t)||d)!==m&&(a=d.abort,d.abort=function(){p=!0,a.call(this)}),null==s?d.send():"function"==typeof r.serialize?d.send(r.serialize(s)):s instanceof e.FormData||s instanceof e.URLSearchParams?d.send(s):d.send(JSON.stringify(s))})),jsonp:l((function(t,n,o,l){var i=n.callbackName||"_mithril_"+Math.round(1e16*Math.random())+"_"+r++,a=e.document.createElement("script");e[i]=function(t){delete e[i],a.parentNode.removeChild(a),o(t)},a.onerror=function(){delete e[i],a.parentNode.removeChild(a),l(new Error("JSONP request failed"))},a.src=t+(t.indexOf("?")<0?"?":"&")+encodeURIComponent(n.callbackKey||"callback")+"="+encodeURIComponent(i),e.document.documentElement.appendChild(a)}))}}("undefined"!=typeof window?window:null,u.redraw),p=u,h=function(){return i.apply(this,arguments)};h.m=i,h.trust=i.trust,h.fragment=i.fragment,h.Fragment="[",h.mount=p.mount;var m=i;function v(e){try{return decodeURIComponent(e)}catch(t){return e}}var y=function(e){if(""===e||null==e)return{};"?"===e.charAt(0)&&(e=e.slice(1));for(var t=e.split("&"),n={},r={},o=0;o-1&&u.pop();for(var c=0;c0&&(i.className=l.join(" ")),o[e]={tag:n,attrs:i}}(i),a):(a.tag=i,a)}i.trust=function(t){return null==t&&(t=""),e("<",void 0,void 0,t,void 0,void 0)},i.fragment=function(){var n=t.apply(0,arguments);return n.tag="[",n.children=e.normalizeChildren(n.children),n};var a=function(t){var n,r=t&&t.document,o={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"};function l(e){return e.attrs&&e.attrs.xmlns||o[e.tag]}function i(e,t){if(e.state!==t)throw new Error("'vnode.state' must not be modified.")}function a(e){var t=e.state;try{return this.apply(t,arguments)}finally{i(e,t)}}function s(){try{return r.activeElement}catch(e){return null}}function u(e,t,n,r,o,l,i){for(var a=n;a'+t.children+"",i=i.firstChild):i.innerHTML=t.children,t.dom=i.firstChild,t.domSize=i.childNodes.length,t.instance=[];for(var a,s=r.createDocumentFragment();a=i.firstChild;)t.instance.push(a),s.appendChild(a);w(e,s,o)}function p(e,t,n,r,o,l){if(t!==n&&(null!=t||null!=n))if(null==t||0===t.length)u(e,n,0,n.length,r,o,l);else if(null==n||0===n.length)k(e,t,0,t.length);else{var i=null!=t[0]&&null!=t[0].key,a=null!=n[0]&&null!=n[0].key,s=0,f=0;if(!i)for(;f=f&&z>=s&&(w=t[E],b=n[z],w.key===b.key);)w!==b&&h(e,w,b,r,o,l),null!=b.dom&&(o=b.dom),E--,z--;for(;E>=f&&z>=s&&(d=t[f],p=n[s],d.key===p.key);)f++,s++,d!==p&&h(e,d,p,r,y(t,f,o),l);for(;E>=f&&z>=s&&s!==z&&d.key===b.key&&w.key===p.key;)g(e,w,S=y(t,f,o)),w!==p&&h(e,w,p,r,S,l),++s<=--z&&g(e,d,o),d!==b&&h(e,d,b,r,o,l),null!=b.dom&&(o=b.dom),f++,w=t[--E],b=n[z],d=t[f],p=n[s];for(;E>=f&&z>=s&&w.key===b.key;)w!==b&&h(e,w,b,r,o,l),null!=b.dom&&(o=b.dom),z--,w=t[--E],b=n[z];if(s>z)k(e,t,f,E+1);else if(f>E)u(e,n,s,z+1,r,o,l);else{var A,j,C=o,O=z-s+1,T=new Array(O),N=0,$=0,L=2147483647,I=0;for($=0;$=s;$--){null==A&&(A=v(t,f,E+1));var R=A[(b=n[$]).key];null!=R&&(L=R>>1)+(r>>>1)+(n&r&1);e[t[a]]0&&(m[o]=t[n-1]),t[n]=o)}}n=t.length,r=t[n-1];for(;n-- >0;)t[n]=r,r=m[r];return m.length=0,t}(T)).length-1,$=z;$>=s;$--)p=n[$],-1===T[$-s]?c(e,p,r,l,o):j[N]===$-s?N--:g(e,p,o),null!=p.dom&&(o=n[$].dom);else for($=z;$>=s;$--)p=n[$],-1===T[$-s]&&c(e,p,r,l,o),null!=p.dom&&(o=n[$].dom)}}else{var P=t.lengthP&&k(e,t,s,t.length),n.length>P&&u(e,n,s,n.length,r,o,l)}}}function h(t,n,r,o,i,s){var u=n.tag;if(u===r.tag){if(r.state=n.state,r.events=n.events,function(e,t){do{var n;if(null!=e.attrs&&"function"==typeof e.attrs.onbeforeupdate)if(void 0!==(n=a.call(e.attrs.onbeforeupdate,e,t))&&!n)break;if("string"!=typeof e.tag&&"function"==typeof e.state.onbeforeupdate)if(void 0!==(n=a.call(e.state.onbeforeupdate,e,t))&&!n)break;return!1}while(0);return e.dom=t.dom,e.domSize=t.domSize,e.instance=t.instance,e.attrs=t.attrs,e.children=t.children,e.text=t.text,!0}(r,n))return;if("string"==typeof u)switch(null!=r.attrs&&D(r.attrs,r,o),u){case"#":!function(e,t){e.children.toString()!==t.children.toString()&&(e.dom.nodeValue=t.children);t.dom=e.dom}(n,r);break;case"<":!function(e,t,n,r,o){t.children!==n.children?(S(e,t),d(e,n,r,o)):(n.dom=t.dom,n.domSize=t.domSize,n.instance=t.instance)}(t,n,r,s,i);break;case"[":!function(e,t,n,r,o,l){p(e,t.children,n.children,r,o,l);var i=0,a=n.children;if(n.dom=null,null!=a){for(var s=0;s-1||null!=e.attrs&&e.attrs.is||"href"!==t&&"list"!==t&&"form"!==t&&"width"!==t&&"height"!==t)&&t in e.dom}var T,N=/[A-Z]/g;function $(e){return"-"+e.toLowerCase()}function L(e){return"-"===e[0]&&"-"===e[1]?e:"cssFloat"===e?"float":e.replace(N,$)}function I(e,t,n){if(t===n);else if(null==n)e.style.cssText="";else if("object"!=typeof n)e.style.cssText=n;else if(null==t||"object"!=typeof t)for(var r in e.style.cssText="",n){null!=(o=n[r])&&e.style.setProperty(L(r),String(o))}else{for(var r in n){var o;null!=(o=n[r])&&(o=String(o))!==String(t[r])&&e.style.setProperty(L(r),o)}for(var r in t)null!=t[r]&&null==n[r]&&e.style.removeProperty(L(r))}}function R(){this._=n}function P(e,t,r){if(null!=e.events){if(e.events._=n,e.events[t]===r)return;null==r||"function"!=typeof r&&"object"!=typeof r?(null!=e.events[t]&&e.dom.removeEventListener(t.slice(2),e.events,!1),e.events[t]=void 0):(null==e.events[t]&&e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}else null==r||"function"!=typeof r&&"object"!=typeof r||(e.events=new R,e.dom.addEventListener(t.slice(2),e.events,!1),e.events[t]=r)}function _(e,t,n){"function"==typeof e.oninit&&a.call(e.oninit,t),"function"==typeof e.oncreate&&n.push(a.bind(e.oncreate,t))}function D(e,t,n){"function"==typeof e.onupdate&&n.push(a.bind(e.onupdate,t))}return R.prototype=Object.create(null),R.prototype.handleEvent=function(e){var t,n=this["on"+e.type];"function"==typeof n?t=n.call(e.currentTarget,e):"function"==typeof n.handleEvent&&n.handleEvent(e),this._&&!1!==e.redraw&&(0,this._)(),!1===t&&(e.preventDefault(),e.stopPropagation())},function(t,r,o){if(!t)throw new TypeError("DOM element being rendered to does not exist.");if(null!=T&&t.contains(T))throw new TypeError("Node is currently being rendered to and thus is locked.");var l=n,i=T,a=[],u=s(),c=t.namespaceURI;T=t,n="function"==typeof o?o:void 0;try{null==t.vnodes&&(t.textContent=""),r=e.normalizeChildren(Array.isArray(r)?r:[r]),p(t,t.vnodes,r,a,null,"http://www.w3.org/1999/xhtml"===c?void 0:c),t.vnodes=r,null!=u&&s()!==u&&"function"==typeof u.focus&&u.focus();for(var f=0;f=0&&(o.splice(l,2),l<=i&&(i-=2),t(n,[])),null!=r&&(o.push(n,r),t(n,e(r),s))},redraw:s}}(a,"undefined"!=typeof requestAnimationFrame?requestAnimationFrame:null,"undefined"!=typeof console?console:null),u=function(e){if("[object Object]"!==Object.prototype.toString.call(e))return"";var t=[];for(var n in e)r(n,e[n]);return t.join("&");function r(e,n){if(Array.isArray(n))for(var o=0;o=0&&(v+=e.slice(n,o)),f>=0&&(v+=(n<0?"?":"&")+s.slice(f,p));var m=u(a);return m&&(v+=(n<0&&f<0?"?":"&")+m),r>=0&&(v+=e.slice(r)),d>=0&&(v+=(r<0?"":"&")+s.slice(d)),v},d=function(e,t){var r;function o(e){return new Promise(e)}function l(e,t){for(var r in e.headers)if(n.call(e.headers,r)&&r.toLowerCase()===t)return!0;return!1}return o.prototype=Promise.prototype,o.__proto__=Promise,{request:(r=function(t,r,o,i){var a,s=null!=r.method?r.method.toUpperCase():"GET",u=r.body,c=(null==r.serialize||r.serialize===JSON.serialize)&&!(u instanceof e.FormData||u instanceof e.URLSearchParams),f=r.responseType||("function"==typeof r.extract?"":"json"),d=new e.XMLHttpRequest,p=!1,h=!1,v=d,m=d.abort;for(var y in d.abort=function(){p=!0,m.call(this)},d.open(s,t,!1!==r.async,"string"==typeof r.user?r.user:void 0,"string"==typeof r.password?r.password:void 0),c&&null!=u&&!l(r,"content-type")&&d.setRequestHeader("Content-Type","application/json; charset=utf-8"),"function"==typeof r.deserialize||l(r,"accept")||d.setRequestHeader("Accept","application/json, text/*"),r.withCredentials&&(d.withCredentials=r.withCredentials),r.timeout&&(d.timeout=r.timeout),d.responseType=f,r.headers)n.call(r.headers,y)&&d.setRequestHeader(y,r.headers[y]);d.onreadystatechange=function(e){if(!p&&4===e.target.readyState)try{var n,l=e.target.status>=200&&e.target.status<300||304===e.target.status||/^file:\/\//i.test(t),a=e.target.response;if("json"===f){if(!e.target.responseType&&"function"!=typeof r.extract)try{a=JSON.parse(e.target.responseText)}catch(e){a=null}}else f&&"text"!==f||null==a&&(a=e.target.responseText);if("function"==typeof r.extract?(a=r.extract(e.target,r),l=!0):"function"==typeof r.deserialize&&(a=r.deserialize(a)),l)o(a);else{var s=function(){try{n=e.target.responseText}catch(e){n=a}var t=new Error(n);t.code=e.target.status,t.response=a,i(t)};0===d.status?setTimeout((function(){h||s()})):s()}}catch(e){i(e)}},d.ontimeout=function(e){h=!0;var t=new Error("Request timed out");t.code=e.target.status,i(t)},"function"==typeof r.config&&(d=r.config(d,r,t)||d)!==v&&(a=d.abort,d.abort=function(){p=!0,a.call(this)}),null==u?d.send():"function"==typeof r.serialize?d.send(r.serialize(u)):u instanceof e.FormData||u instanceof e.URLSearchParams?d.send(u):d.send(JSON.stringify(u))},function(e,n){"string"!=typeof e?(n=e,e=e.url):null==n&&(n={});var l=new Promise((function(t,o){r(f(e,n.params),n,(function(e){if("function"==typeof n.type)if(Array.isArray(e))for(var r=0;r-1&&s.pop();for(var c=0;c