diff --git a/PlexRequests.UI/Jobs/PlexRegistry.cs b/PlexRequests.Api.Interfaces/ISlackApi.cs similarity index 82% rename from PlexRequests.UI/Jobs/PlexRegistry.cs rename to PlexRequests.Api.Interfaces/ISlackApi.cs index f124cfaf0..812419f69 100644 --- a/PlexRequests.UI/Jobs/PlexRegistry.cs +++ b/PlexRequests.Api.Interfaces/ISlackApi.cs @@ -1,41 +1,37 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: PlexRegistry.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion - -using FluentScheduler; - -using PlexRequests.Services; - -namespace PlexRequests.UI.Jobs -{ - public class PlexRegistry : Registry - { - public PlexRegistry() - { - Schedule().ToRunNow(); - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ISlackApi.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Threading.Tasks; + +using PlexRequests.Api.Models.Notifications; + +namespace PlexRequests.Api.Interfaces +{ + public interface ISlackApi + { + Task PushAsync(string team, string token, string service, SlackNotificationBody message); + } } \ No newline at end of file diff --git a/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj b/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj index 52b7980a0..8512ca932 100644 --- a/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj +++ b/PlexRequests.Api.Interfaces/PlexRequests.Api.Interfaces.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,7 +9,7 @@ Properties PlexRequests.Api.Interfaces PlexRequests.Api.Interfaces - v4.5.2 + v4.5 512 @@ -32,7 +32,7 @@ - ..\packages\RestSharp.105.2.3\lib\net452\RestSharp.dll + ..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll True @@ -51,20 +51,21 @@ + - - - {CB37A5F8-6DFC-4554-99D3-A42B502E4591} PlexRequests.Api.Models + + + ",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"|$)",e:">",k:{title:"style"},c:[b],starts:{e:"",rE:true,sL:"css"}},{cN:"tag",b:"|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},{cN:"tag",b:"",c:[{cN:"title",b:"[^ />]+"},b]}]}}(hljs);hljs.LANGUAGES.json=function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}}(hljs); \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/jquery-1.8.0.min.js b/PlexRequests.UI/Content/swagger/jquery-1.8.0.min.js new file mode 100644 index 000000000..066d72c7e --- /dev/null +++ b/PlexRequests.UI/Content/swagger/jquery-1.8.0.min.js @@ -0,0 +1,2 @@ +/*! jQuery v@1.8.0 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bR[a]=c,c}function ch(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||cd.test(a)?d(a,e):ch(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ch(a+"["+e+"]",b[e],c,d);else d(a,b)}function cy(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.0",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return typeof a=="object"?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length||!d)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
t
",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/^(?:\{.*\}|\[.*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||++p.uuid:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.shift(),e=p._queueHooks(a,b),f=function(){p.dequeue(a,b)};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),delete e.stop,d.call(a,f,e)),!c.length&&e&&e.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c-1)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c-1)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,""+d),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;jq&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bd(a,b,c,d){var e=0,f=b.length;for(;e0?h(g,c,f):[]}function bf(a,c,d,e,f){var g,h,i,j,k,l,m,n,p=0,q=f.length,s=L.POS,t=new RegExp("^"+s.source+"(?!"+r+")","i"),u=function(){var a=1,c=arguments.length-2;for(;ai){m=a.slice(i,g.index),i=n,l=[c],B.test(m)&&(k&&(l=k),k=e);if(h=H.test(m))m=m.slice(0,-5).replace(B,"$&*");g.length>1&&g[0].replace(t,u),k=be(m,g[1],g[2],l,k,h)}}k?(j=j.concat(k),(m=a.slice(i))&&m!==")"?B.test(m)?bd(m,j,d,e):Z(m,c,d,e?e.concat(k):k):o.apply(d,j)):Z(a,c,d,e)}return q===1?d:Z.uniqueSort(d)}function bg(a,b,c){var d,e,f,g=[],i=0,j=D.exec(a),k=!j.pop()&&!j.pop(),l=k&&a.match(C)||[""],m=$.preFilter,n=$.filter,o=!c&&b!==h;for(;(e=l[i])!=null&&k;i++){g.push(d=[]),o&&(e=" "+e);while(e){k=!1;if(j=B.exec(e))e=e.slice(j[0].length),k=d.push({part:j.pop().replace(A," "),captures:j});for(f in n)(j=L[f].exec(e))&&(!m[f]||(j=m[f](j,b,c)))&&(e=e.slice(j.shift().length),k=d.push({part:f,captures:j}));if(!k)break}}return k||Z.error(a),g}function bh(a,b,e){var f=b.dir,g=m++;return a||(a=function(a){return a===e}),b.first?function(b,c){while(b=b[f])if(b.nodeType===1)return a(b,c)&&b}:function(b,e){var h,i=g+"."+d,j=i+"."+c;while(b=b[f])if(b.nodeType===1){if((h=b[q])===j)return b.sizset;if(typeof h=="string"&&h.indexOf(i)===0){if(b.sizset)return b}else{b[q]=j;if(a(b,e))return b.sizset=!0,b;b.sizset=!1}}}}function bi(a,b){return a?function(c,d){var e=b(c,d);return e&&a(e===!0?c:e,d)}:b}function bj(a,b,c){var d,e,f=0;for(;d=a[f];f++)$.relative[d.part]?e=bh(e,$.relative[d.part],b):(d.captures.push(b,c),e=bi(e,$.filter[d.part].apply(null,d.captures)));return e}function bk(a){return function(b,c){var d,e=0;for(;d=a[e];e++)if(d(b,c))return!0;return!1}}var c,d,e,f,g,h=a.document,i=h.documentElement,j="undefined",k=!1,l=!0,m=0,n=[].slice,o=[].push,q=("sizcache"+Math.random()).replace(".",""),r="[\\x20\\t\\r\\n\\f]",s="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",t=s.replace("w","w#"),u="([*^$|!~]?=)",v="\\["+r+"*("+s+")"+r+"*(?:"+u+r+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+t+")|)|)"+r+"*\\]",w=":("+s+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|((?:[^,]|\\\\,|(?:,(?=[^\\[]*\\]))|(?:,(?=[^\\(]*\\))))*))\\)|)",x=":(nth|eq|gt|lt|first|last|even|odd)(?:\\((\\d*)\\)|)(?=[^-]|$)",y=r+"*([\\x20\\t\\r\\n\\f>+~])"+r+"*",z="(?=[^\\x20\\t\\r\\n\\f])(?:\\\\.|"+v+"|"+w.replace(2,7)+"|[^\\\\(),])+",A=new RegExp("^"+r+"+|((?:^|[^\\\\])(?:\\\\.)*)"+r+"+$","g"),B=new RegExp("^"+y),C=new RegExp(z+"?(?="+r+"*,|$)","g"),D=new RegExp("^(?:(?!,)(?:(?:^|,)"+r+"*"+z+")*?|"+r+"*(.*?))(\\)|$)"),E=new RegExp(z.slice(19,-6)+"\\x20\\t\\r\\n\\f>+~])+|"+y,"g"),F=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,G=/[\x20\t\r\n\f]*[+~]/,H=/:not\($/,I=/h\d/i,J=/input|select|textarea|button/i,K=/\\(?!\\)/g,L={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),NAME:new RegExp("^\\[name=['\"]?("+s+")['\"]?\\]"),TAG:new RegExp("^("+s.replace("[-","[-\\*")+")"),ATTR:new RegExp("^"+v),PSEUDO:new RegExp("^"+w),CHILD:new RegExp("^:(only|nth|last|first)-child(?:\\("+r+"*(even|odd|(([+-]|)(\\d*)n|)"+r+"*(?:([+-]|)"+r+"*(\\d+)|))"+r+"*\\)|)","i"),POS:new RegExp(x,"ig"),needsContext:new RegExp("^"+r+"*[>+~]|"+x,"i")},M={},N=[],O={},P=[],Q=function(a){return a.sizzleFilter=!0,a},R=function(a){return function(b){return b.nodeName.toLowerCase()==="input"&&b.type===a}},S=function(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}},T=function(a){var b=!1,c=h.createElement("div");try{b=a(c)}catch(d){}return c=null,b},U=T(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),V=T(function(a){a.id=q+0,a.innerHTML="
",i.insertBefore(a,i.firstChild);var b=h.getElementsByName&&h.getElementsByName(q).length===2+h.getElementsByName(q+0).length;return g=!h.getElementById(q),i.removeChild(a),b}),W=T(function(a){return a.appendChild(h.createComment("")),a.getElementsByTagName("*").length===0}),X=T(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==j&&a.firstChild.getAttribute("href")==="#"}),Y=T(function(a){return a.innerHTML="",!a.getElementsByClassName||a.getElementsByClassName("e").length===0?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length!==1)}),Z=function(a,b,c,d){c=c||[],b=b||h;var e,f,g,i,j=b.nodeType;if(j!==1&&j!==9)return[];if(!a||typeof a!="string")return c;g=ba(b);if(!g&&!d)if(e=F.exec(a))if(i=e[1]){if(j===9){f=b.getElementById(i);if(!f||!f.parentNode)return c;if(f.id===i)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(i))&&bb(b,f)&&f.id===i)return c.push(f),c}else{if(e[2])return o.apply(c,n.call(b.getElementsByTagName(a),0)),c;if((i=e[3])&&Y&&b.getElementsByClassName)return o.apply(c,n.call(b.getElementsByClassName(i),0)),c}return bm(a,b,c,d,g)},$=Z.selectors={cacheLength:50,match:L,order:["ID","TAG"],attrHandle:{},createPseudo:Q,find:{ID:g?function(a,b,c){if(typeof b.getElementById!==j&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==j&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==j&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:W?function(a,b){if(typeof b.getElementsByTagName!==j)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(K,""),a[3]=(a[4]||a[5]||"").replace(K,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||Z.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&Z.error(a[0]),a},PSEUDO:function(a){var b,c=a[4];return L.CHILD.test(a[0])?null:(c&&(b=D.exec(c))&&b.pop()&&(a[0]=a[0].slice(0,b[0].length-c.length-1),c=b[0].slice(0,-1)),a.splice(2,3,c||a[3]),a)}},filter:{ID:g?function(a){return a=a.replace(K,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(K,""),function(b){var c=typeof b.getAttributeNode!==j&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(K,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=M[a];return b||(b=M[a]=new RegExp("(^|"+r+")"+a+"("+r+"|$)"),N.push(a),N.length>$.cacheLength&&delete M[N.shift()]),function(a){return b.test(a.className||typeof a.getAttribute!==j&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return b?function(d){var e=Z.attr(d,a),f=e+"";if(e==null)return b==="!=";switch(b){case"=":return f===c;case"!=":return f!==c;case"^=":return c&&f.indexOf(c)===0;case"*=":return c&&f.indexOf(c)>-1;case"$=":return c&&f.substr(f.length-c.length)===c;case"~=":return(" "+f+" ").indexOf(c)>-1;case"|=":return f===c||f.substr(0,c.length+1)===c+"-"}}:function(b){return Z.attr(b,a)!=null}},CHILD:function(a,b,c,d){if(a==="nth"){var e=m++;return function(a){var b,f,g=0,h=a;if(c===1&&d===0)return!0;b=a.parentNode;if(b&&(b[q]!==e||!a.sizset)){for(h=b.firstChild;h;h=h.nextSibling)if(h.nodeType===1){h.sizset=++g;if(h===a)break}b[q]=e}return f=a.sizset-d,c===0?f===0:f%c===0&&f/c>=0}}return function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b,c,d){var e=$.pseudos[a]||$.pseudos[a.toLowerCase()];return e||Z.error("unsupported pseudo: "+a),e.sizzleFilter?e(b,c,d):e}},pseudos:{not:Q(function(a,b,c){var d=bl(a.replace(A,"$1"),b,c);return function(a){return!d(a)}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!$.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},contains:Q(function(a){return function(b){return(b.textContent||b.innerText||bc(b)).indexOf(a)>-1}}),has:Q(function(a){return function(b){return Z(a,b).length>0}}),header:function(a){return I.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:R("radio"),checkbox:R("checkbox"),file:R("file"),password:R("password"),image:R("image"),submit:S("submit"),reset:S("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return J.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b,c){return c?a.slice(1):[a[0]]},last:function(a,b,c){var d=a.pop();return c?a:[d]},even:function(a,b,c){var d=[],e=c?1:0,f=a.length;for(;e$.cacheLength&&delete O[P.shift()],g};Z.matches=function(a,b){return Z(a,null,null,b)},Z.matchesSelector=function(a,b){return Z(b,null,null,[a]).length>0};var bm=function(a,b,e,f,g){a=a.replace(A,"$1");var h,i,j,k,l,m,p,q,r,s=a.match(C),t=a.match(E),u=b.nodeType;if(L.POS.test(a))return bf(a,b,e,f,s);if(f)h=n.call(f,0);else if(s&&s.length===1){if(t.length>1&&u===9&&!g&&(s=L.ID.exec(t[0]))){b=$.find.ID(s[1],b,g)[0];if(!b)return e;a=a.slice(t.shift().length)}q=(s=G.exec(t[0]))&&!s.index&&b.parentNode||b,r=t.pop(),m=r.split(":not")[0];for(j=0,k=$.order.length;j",a.querySelectorAll("[selected]").length||e.push("\\["+r+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),T(function(a){a.innerHTML="

",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+r+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=e.length&&new RegExp(e.join("|")),bm=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a)))if(d.nodeType===9)try{return o.apply(f,n.call(d.querySelectorAll(a),0)),f}catch(i){}else if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){var j=d.getAttribute("id"),k=j||q,l=G.test(a)&&d.parentNode||d;j?k=k.replace(c,"\\$&"):d.setAttribute("id",k);try{return o.apply(f,n.call(l.querySelectorAll(a.replace(C,"[id='"+k+"'] $&")),0)),f}catch(i){}finally{j||d.removeAttribute("id")}}return b(a,d,f,g,h)},g&&(T(function(b){a=g.call(b,"div");try{g.call(b,"[test!='']:sizzle"),f.push($.match.PSEUDO)}catch(c){}}),f=new RegExp(f.join("|")),Z.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!ba(b)&&!f.test(c)&&(!e||!e.test(c)))try{var h=g.call(b,c);if(h||a||b.document&&b.document.nodeType!==11)return h}catch(i){}return Z(c,null,null,[b]).length>0})}(),Z.attr=p.attr,p.find=Z,p.expr=Z.selectors,p.expr[":"]=p.expr.pseudos,p.unique=Z.uniqueSort,p.text=Z.getText,p.isXMLDoc=Z.isXML,p.contains=Z.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
","
"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=0,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(g=b===e&&bA;(h=a[s])!=null;s++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{g=g||bk(b),l=l||g.appendChild(b.createElement("div")),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(f=n.length-1;f>=0;--f)p.nodeName(n[f],"tbody")&&!n[f].childNodes.length&&n[f].parentNode.removeChild(n[f])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l=g.lastChild}h.nodeType?t.push(h):t=p.merge(t,h)}l&&(g.removeChild(l),h=l=g=null);if(!p.support.appendChecked)for(s=0;(h=t[s])!=null;s++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(s=0;(h=t[s])!=null;s++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[s+1,0].concat(r)),s+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^margin/,bO=new RegExp("^("+q+")(.*)$","i"),bP=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bQ=new RegExp("^([-+])=("+q+")","i"),bR={},bS={position:"absolute",visibility:"hidden",display:"block"},bT={letterSpacing:0,fontWeight:400,lineHeight:1},bU=["Top","Right","Bottom","Left"],bV=["Webkit","O","Moz","ms"],bW=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return bZ(this,!0)},hide:function(){return bZ(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bW.apply(this,arguments):this.each(function(){(c?a:bY(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bX(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bQ.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bX(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bT&&(f=bT[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(a,b){var c,d,e,f,g=getComputedStyle(a,null),h=a.style;return g&&(c=g[b],c===""&&!p.contains(a.ownerDocument.documentElement,a)&&(c=p.style(a,b)),bP.test(c)&&bN.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=c,c=g.width,h.width=d,h.minWidth=e,h.maxWidth=f)),c}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bP.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0||bH(a,"display")!=="none"?ca(a,b,d):p.swap(a,bS,function(){return ca(a,b,d)})},set:function(a,c,d){return b$(a,c,d?b_(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bP.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bU[d]+b]=e[d]||e[d-2]||e[0];return f}},bN.test(a)||(p.cssHooks[a+b].set=b$)});var cc=/%20/g,cd=/\[\]$/,ce=/\r?\n/g,cf=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,cg=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||cg.test(this.nodeName)||cf.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(ce,"\r\n")}}):{name:b.name,value:c.replace(ce,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ch(d,a[d],c,f);return e.join("&").replace(cc,"+")};var ci,cj,ck=/#.*$/,cl=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cm=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,cn=/^(?:GET|HEAD)$/,co=/^\/\//,cp=/\?/,cq=/)<[^<]*)*<\/script>/gi,cr=/([?&])_=[^&]*/,cs=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,ct=p.fn.load,cu={},cv={},cw=["*/"]+["*"];try{ci=f.href}catch(cx){ci=e.createElement("a"),ci.href="",ci=ci.href}cj=cs.exec(ci.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&ct)return ct.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
").append(a.replace(cq,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cA(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cA(a,b),a},ajaxSettings:{url:ci,isLocal:cm.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cw},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cy(cu),ajaxTransport:cy(cv),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cB(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cC(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=""+(c||y),k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cl.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(ck,"").replace(co,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=cs.exec(l.url.toLowerCase()),l.crossDomain=!(!i||i[1]==cj[1]&&i[2]==cj[2]&&(i[3]||(i[1]==="http:"?80:443))==(cj[3]||(cj[1]==="http:"?80:443)))),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cz(cu,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!cn.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cp.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cr,"$1_="+z);l.url=A+(A===l.url?(cp.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cw+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cz(cv,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cD=[],cE=/\?/,cF=/(=)\?(?=&|$)|\?\?/,cG=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cD.pop()||p.expando+"_"+cG++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cF.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cF.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cF,"$1"+f):m?c.data=i.replace(cF,"$1"+f):k&&(c.url+=(cE.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cD.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cH,cI=a.ActiveXObject?function(){for(var a in cH)cH[a](0,1)}:!1,cJ=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cK()||cL()}:cK,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cI&&delete cH[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cJ,cI&&(cH||(cH={},p(a).unload(cI)),cH[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cM,cN,cO=/^(?:toggle|show|hide)$/,cP=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cQ=/queueHooks$/,cR=[cX],cS={"*":[function(a,b){var c,d,e,f=this.createTween(a,b),g=cP.exec(b),h=f.cur(),i=+h||0,j=1;if(g){c=+g[2],d=g[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&i){i=p.css(f.elem,a,!0)||c||1;do e=j=j||".5",i=i/j,p.style(f.elem,a,i+d),j=f.cur()/h;while(j!==1&&j!==e)}f.unit=d,f.start=i,f.end=g[1]?i+(g[1]+1)*c:c}return f}]};p.Animation=p.extend(cV,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c$.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c$.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=c_(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/jquery.ba-bbq.min.js b/PlexRequests.UI/Content/swagger/jquery.ba-bbq.min.js new file mode 100644 index 000000000..bcbf24834 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/jquery.ba-bbq.min.js @@ -0,0 +1,18 @@ +/* + * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010 + * http://benalman.com/projects/jquery-bbq-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this); \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/jquery.slideto.min.js b/PlexRequests.UI/Content/swagger/jquery.slideto.min.js new file mode 100644 index 000000000..ba32cff36 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/jquery.slideto.min.js @@ -0,0 +1 @@ +(function(b){b.fn.slideto=function(a){a=b.extend({slide_duration:"slow",highlight_duration:3E3,highlight:true,highlight_color:"#FFFF99"},a);return this.each(function(){obj=b(this);b("body").animate({scrollTop:obj.offset().top},a.slide_duration,function(){a.highlight&&b.ui.version&&obj.effect("highlight",{color:a.highlight_color},a.highlight_duration)})})}})(jQuery); diff --git a/PlexRequests.UI/Content/swagger/jquery.wiggle.min.js b/PlexRequests.UI/Content/swagger/jquery.wiggle.min.js new file mode 100644 index 000000000..2adb0d6d5 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/jquery.wiggle.min.js @@ -0,0 +1,8 @@ +/* +jQuery Wiggle +Author: WonderGroup, Jordan Thomas +URL: http://labs.wondergroup.com/demos/mini-ui/index.html +License: MIT (http://en.wikipedia.org/wiki/MIT_License) +*/ +jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('
').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);} +if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});}; \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/jsoneditor.min.js b/PlexRequests.UI/Content/swagger/jsoneditor.min.js new file mode 100644 index 000000000..343397f95 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/jsoneditor.min.js @@ -0,0 +1,11 @@ +/*! JSON Editor v0.7.22 - JSON Schema -> HTML Editor + * By Jeremy Dorn - https://github.com/jdorn/json-editor/ + * Released under the MIT license + * + * Date: 2015-08-12 + */ +!function(){var a;!function(){var b=!1,c=/xyz/.test(function(){window.postMessage("xyz")})?/\b_super\b/:/.*/;return a=function(){},a.extend=function(a){function d(){!b&&this.init&&this.init.apply(this,arguments)}var e=this.prototype;b=!0;var f=new this;b=!1;for(var g in a)f[g]="function"==typeof a[g]&&"function"==typeof e[g]&&c.test(a[g])?function(a,b){return function(){var c=this._super;this._super=e[a];var d=b.apply(this,arguments);return this._super=c,d}}(g,a[g]):a[g];return d.prototype=f,d.prototype.constructor=d,d.extend=arguments.callee,d},a}(),function(){function a(a,b){b=b||{bubbles:!1,cancelable:!1,detail:void 0};var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,b.bubbles,b.cancelable,b.detail),c}a.prototype=window.Event.prototype,window.CustomEvent=a}(),function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c0&&a.length-1 in a){for(c=0;c=g&&!h&&(h=!0,b())})}},d.send()}}),g||b()},expandRefs:function(a){for(a=c({},a);a.$ref;){var b=a.$ref;delete a.$ref,this.refs[b]||(b=decodeURIComponent(b)),a=this.extendSchemas(a,this.refs[b])}return a},expandSchema:function(a){var b,e=this,f=c({},a);if("object"==typeof a.type&&(Array.isArray(a.type)?d(a.type,function(b,c){"object"==typeof c&&(a.type[b]=e.expandSchema(c))}):a.type=e.expandSchema(a.type)),"object"==typeof a.disallow&&(Array.isArray(a.disallow)?d(a.disallow,function(b,c){"object"==typeof c&&(a.disallow[b]=e.expandSchema(c))}):a.disallow=e.expandSchema(a.disallow)),a.anyOf&&d(a.anyOf,function(b,c){a.anyOf[b]=e.expandSchema(c)}),a.dependencies&&d(a.dependencies,function(b,c){"object"!=typeof c||Array.isArray(c)||(a.dependencies[b]=e.expandSchema(c))}),a.not&&(a.not=this.expandSchema(a.not)),a.allOf){for(b=0;b=a.maximum?k.push({path:e,property:"maximum",message:this.translate("error_maximum_excl",[a.maximum])}):!a.exclusiveMaximum&&b>a.maximum&&k.push({path:e,property:"maximum",message:this.translate("error_maximum_incl",[a.maximum])})),a.hasOwnProperty("minimum")&&(a.exclusiveMinimum&&b<=a.minimum?k.push({path:e,property:"minimum",message:this.translate("error_minimum_excl",[a.minimum])}):!a.exclusiveMinimum&&ba.maxLength&&k.push({path:e,property:"maxLength",message:this.translate("error_maxLength",[a.maxLength])}),a.minLength&&(b+"").lengtha.maxItems&&k.push({path:e,property:"maxItems",message:this.translate("error_maxItems",[a.maxItems])}),a.minItems&&b.lengtha.maxProperties&&k.push({path:e,property:"maxProperties",message:this.translate("error_maxProperties",[a.maxProperties])})}if(a.minProperties){g=0;for(h in b)b.hasOwnProperty(h)&&g++;g=0){b=this.theme.getBlockLinkHolder(),c=this.theme.getBlockLink(),c.setAttribute("target","_blank");var h=document.createElement(e);h.setAttribute("controls","controls"),this.theme.createMediaLink(b,c,h),this.link_watchers.push(function(b){var d=f(b);c.setAttribute("href",d),c.textContent=a.rel||d,h.setAttribute("src",d)})}else b=this.theme.getBlockLink(),b.setAttribute("target","_blank"),b.textContent=a.rel,this.link_watchers.push(function(c){var d=f(c);b.setAttribute("href",d),b.textContent=a.rel||d});return b},refreshWatchedFieldValues:function(){if(this.watched_values){var a={},b=!1,c=this;if(this.watched){var d,e;for(var f in this.watched)this.watched.hasOwnProperty(f)&&(e=c.jsoneditor.getEditor(this.watched[f]),d=e?e.getValue():null,c.watched_values[f]!==d&&(b=!0),a[f]=d)}return a.self=this.getValue(),this.watched_values.self!==a.self&&(b=!0),this.watched_values=a,b}},getWatchedFieldValues:function(){return this.watched_values},updateHeaderText:function(){if(this.header)if(this.header.children.length){for(var a=0;a-1:this.jsoneditor.options.required_by_default?!0:!1},getDisplayText:function(a){var b=[],c={};d(a,function(a,b){b.title&&(c[b.title]=c[b.title]||0,c[b.title]++),b.description&&(c[b.description]=c[b.description]||0,c[b.description]++),b.format&&(c[b.format]=c[b.format]||0,c[b.format]++),b.type&&(c[b.type]=c[b.type]||0,c[b.type]++)}),d(a,function(a,d){var e;e="string"==typeof d?d:d.title&&c[d.title]<=1?d.title:d.format&&c[d.format]<=1?d.format:d.type&&c[d.type]<=1?d.type:d.description&&c[d.description]<=1?d.descripton:d.title?d.title:d.format?d.format:d.type?d.type:d.description?d.description:JSON.stringify(d).length<50?JSON.stringify(d):"type",b.push(e)});var e={};return d(b,function(a,d){e[d]=e[d]||0,e[d]++,c[d]>1&&(b[a]=d+" "+e[d])}),b},getOption:function(a){try{throw"getOption is deprecated"}catch(b){window.console.error(b)}return this.options[a]},showValidationErrors:function(a){}}),f.defaults.editors["null"]=f.AbstractEditor.extend({getValue:function(){return null},setValue:function(){this.onChange()},getNumColumns:function(){return 2}}),f.defaults.editors.string=f.AbstractEditor.extend({register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},setValue:function(a,b,c){if((!this.template||c)&&(null===a||"undefined"==typeof a?a="":"object"==typeof a?a=JSON.stringify(a):"string"!=typeof a&&(a=""+a),a!==this.serialized)){var d=this.sanitize(a);if(this.input.value!==d){this.input.value=d,this.sceditor_instance?this.sceditor_instance.val(d):this.epiceditor?this.epiceditor.importFile(null,d):this.ace_editor&&this.ace_editor.setValue(d);var e=c||this.getValue()!==a;this.refreshValue(),b?this.is_dirty=!1:"change"===this.jsoneditor.options.show_errors&&(this.is_dirty=!0),this.adjust_height&&this.adjust_height(this.input),this.onChange(e)}}},getNumColumns:function(){var a,b=Math.ceil(Math.max(this.getTitle().length,this.schema.maxLength||0,this.schema.minLength||0)/5);return a="textarea"===this.input_type?6:["text","email"].indexOf(this.input_type)>=0?4:2,Math.min(12,Math.max(b,a))},build:function(){var a=this;if(this.options.compact||(this.header=this.label=this.theme.getFormInputLabel(this.getTitle(),this.isRequired())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.format=this.schema.format,!this.format&&this.schema.media&&this.schema.media.type&&(this.format=this.schema.media.type.replace(/(^(application|text)\/(x-)?(script\.)?)|(-source$)/g,"")),!this.format&&this.options.default_format&&(this.format=this.options.default_format),this.options.format&&(this.format=this.options.format),this.format)if("textarea"===this.format)this.input_type="textarea",this.input=this.theme.getTextareaInput();else if("range"===this.format){this.input_type="range";var b=this.schema.minimum||0,c=this.schema.maximum||Math.max(100,b+1),d=1;this.schema.multipleOf&&(b%this.schema.multipleOf&&(b=Math.ceil(b/this.schema.multipleOf)*this.schema.multipleOf),c%this.schema.multipleOf&&(c=Math.floor(c/this.schema.multipleOf)*this.schema.multipleOf),d=this.schema.multipleOf),this.input=this.theme.getRangeInput(b,c,d)}else["actionscript","batchfile","bbcode","c","c++","cpp","coffee","csharp","css","dart","django","ejs","erlang","golang","handlebars","haskell","haxe","html","ini","jade","java","javascript","json","less","lisp","lua","makefile","markdown","matlab","mysql","objectivec","pascal","perl","pgsql","php","python","r","ruby","sass","scala","scss","smarty","sql","stylus","svg","twig","vbscript","xml","yaml"].indexOf(this.format)>=0?(this.input_type=this.format,this.source_code=!0,this.input=this.theme.getTextareaInput()):(this.input_type=this.format,this.input=this.theme.getFormInputField(this.input_type));else this.input_type="text",this.input=this.theme.getFormInputField(this.input_type);"undefined"!=typeof this.schema.maxLength&&this.input.setAttribute("maxlength",this.schema.maxLength),"undefined"!=typeof this.schema.pattern?this.input.setAttribute("pattern",this.schema.pattern):"undefined"!=typeof this.schema.minLength&&this.input.setAttribute("pattern",".{"+this.schema.minLength+",}"),this.options.compact?this.container.className+=" compact":this.options.input_width&&(this.input.style.width=this.options.input_width),(this.schema.readOnly||this.schema.readonly||this.schema.template)&&(this.always_disabled=!0,this.input.disabled=!0),this.input.addEventListener("change",function(b){if(b.preventDefault(),b.stopPropagation(),a.schema.template)return void(this.value=a.value);var c=this.value,d=a.sanitize(c);c!==d&&(this.value=d),a.is_dirty=!0,a.refreshValue(),a.onChange(!0)}),this.options.input_height&&(this.input.style.height=this.options.input_height),this.options.expand_height&&(this.adjust_height=function(a){if(a){var b,c=a.offsetHeight;if(a.offsetHeight100);)b++,c++,a.style.height=c+"px";else{for(b=0;a.offsetHeight>=a.scrollHeight+3&&!(b>100);)b++,c--,a.style.height=c+"px";a.style.height=c+1+"px"}}},this.input.addEventListener("keyup",function(b){a.adjust_height(this)}),this.input.addEventListener("change",function(b){a.adjust_height(this)}),this.adjust_height()),this.format&&this.input.setAttribute("data-schemaformat",this.format),this.control=this.theme.getFormControl(this.label,this.input,this.description),this.container.appendChild(this.control),window.requestAnimationFrame(function(){a.input.parentNode&&a.afterInputReady(),a.adjust_height&&a.adjust_height(a.input)}),this.schema.template?(this.template=this.jsoneditor.compileTemplate(this.schema.template,this.template_engine),this.refreshValue()):this.refreshValue()},enable:function(){this.always_disabled||(this.input.disabled=!1),this._super()},disable:function(){this.input.disabled=!0,this._super()},afterInputReady:function(){var a,b=this;if(this.source_code)if(this.options.wysiwyg&&["html","bbcode"].indexOf(this.input_type)>=0&&window.jQuery&&window.jQuery.fn&&window.jQuery.fn.sceditor)a=c({},{plugins:"html"===b.input_type?"xhtml":"bbcode",emoticonsEnabled:!1,width:"100%",height:300},f.plugins.sceditor,b.options.sceditor_options||{}),window.jQuery(b.input).sceditor(a),b.sceditor_instance=window.jQuery(b.input).sceditor("instance"),b.sceditor_instance.blur(function(){var a=window.jQuery("
"+b.sceditor_instance.val()+"
");window.jQuery("#sceditor-start-marker,#sceditor-end-marker,.sceditor-nlf",a).remove(),b.input.value=a.html(),b.value=b.input.value,b.is_dirty=!0,b.onChange(!0)});else if("markdown"===this.input_type&&window.EpicEditor)this.epiceditor_container=document.createElement("div"),this.input.parentNode.insertBefore(this.epiceditor_container,this.input),this.input.style.display="none",a=c({},f.plugins.epiceditor,{container:this.epiceditor_container,clientSideStorage:!1}),this.epiceditor=new window.EpicEditor(a).load(),this.epiceditor.importFile(null,this.getValue()),this.epiceditor.on("update",function(){var a=b.epiceditor.exportFile();b.input.value=a,b.value=a,b.is_dirty=!0,b.onChange(!0); +});else if(window.ace){var d=this.input_type;("cpp"===d||"c++"===d||"c"===d)&&(d="c_cpp"),this.ace_container=document.createElement("div"),this.ace_container.style.width="100%",this.ace_container.style.position="relative",this.ace_container.style.height="400px",this.input.parentNode.insertBefore(this.ace_container,this.input),this.input.style.display="none",this.ace_editor=window.ace.edit(this.ace_container),this.ace_editor.setValue(this.getValue()),f.plugins.ace.theme&&this.ace_editor.setTheme("ace/theme/"+f.plugins.ace.theme),d=window.ace.require("ace/mode/"+d),d&&this.ace_editor.getSession().setMode(new d.Mode),this.ace_editor.on("change",function(){var a=b.ace_editor.getValue();b.input.value=a,b.refreshValue(),b.is_dirty=!0,b.onChange(!0)})}b.theme.afterInputReady(b.input)},refreshValue:function(){this.value=this.input.value,"string"!=typeof this.value&&(this.value=""),this.serialized=this.value},destroy:function(){this.sceditor_instance?this.sceditor_instance.destroy():this.epiceditor?this.epiceditor.unload():this.ace_editor&&this.ace_editor.destroy(),this.template=null,this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this._super()},sanitize:function(a){return a},onWatchedFieldChange:function(){var a;this.template&&(a=this.getWatchedFieldValues(),this.setValue(this.template(a),!1,!0)),this._super()},showValidationErrors:function(a){var b=this;if("always"===this.jsoneditor.options.show_errors);else if(!this.is_dirty&&this.previous_error_setting===this.jsoneditor.options.show_errors)return;this.previous_error_setting=this.jsoneditor.options.show_errors;var c=[];d(a,function(a,d){d.path===b.path&&c.push(d.message)}),c.length?this.theme.addInputError(this.input,c.join(". ")+"."):this.theme.removeInputError(this.input)}}),f.defaults.editors.number=f.defaults.editors.string.extend({sanitize:function(a){return(a+"").replace(/[^0-9\.\-eE]/g,"")},getNumColumns:function(){return 2},getValue:function(){return 1*this.value}}),f.defaults.editors.integer=f.defaults.editors.number.extend({sanitize:function(a){return a+="",a.replace(/[^0-9\-]/g,"")},getNumColumns:function(){return 2}}),f.defaults.editors.object=f.AbstractEditor.extend({getDefault:function(){return c({},this.schema["default"]||{})},getChildEditors:function(){return this.editors},register:function(){if(this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].register()},unregister:function(){if(this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].unregister()},getNumColumns:function(){return Math.max(Math.min(12,this.maxwidth),3)},enable:function(){if(this.editjson_button&&(this.editjson_button.disabled=!1),this.addproperty_button&&(this.addproperty_button.disabled=!1),this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].enable()},disable:function(){if(this.editjson_button&&(this.editjson_button.disabled=!0),this.addproperty_button&&(this.addproperty_button.disabled=!0),this.hideEditJSON(),this._super(),this.editors)for(var a in this.editors)this.editors.hasOwnProperty(a)&&this.editors[a].disable()},layoutEditors:function(){var a,b,c=this;if(this.row_container){this.property_order=Object.keys(this.editors),this.property_order=this.property_order.sort(function(a,b){var d=c.editors[a].schema.propertyOrder,e=c.editors[b].schema.propertyOrder;return"number"!=typeof d&&(d=1e3),"number"!=typeof e&&(e=1e3),d-e});var e;if("grid"===this.format){var f=[];for(d(this.property_order,function(a,b){var d=c.editors[b];if(!d.property_removed){for(var e=!1,g=d.options.hidden?0:d.options.grid_columns||d.getNumColumns(),h=d.options.hidden?0:d.container.offsetHeight,i=0;ih)&&(e=i);e===!1&&(f.push({width:0,minh:999999,maxh:0,editors:[]}),e=f.length-1),f[e].editors.push({key:b,width:g,height:h}),f[e].width+=g,f[e].minh=Math.min(f[e].minh,h),f[e].maxh=Math.max(f[e].maxh,h)}}),a=0;af[a].editors[g].width&&(g=b),f[a].editors[b].width*=12/f[a].width,f[a].editors[b].width=Math.floor(f[a].editors[b].width),h+=f[a].editors[b].width;12>h&&(f[a].editors[g].width+=12-h),f[a].width=12}if(this.layout===JSON.stringify(f))return!1;for(this.layout=JSON.stringify(f),e=document.createElement("div"),a=0;a=this.schema.maxProperties),this.addproperty_checkboxes&&(this.addproperty_list.innerHTML=""),this.addproperty_checkboxes={};for(a in this.cached_editors)this.cached_editors.hasOwnProperty(a)&&(this.addPropertyCheckbox(a),this.isRequired(this.cached_editors[a])&&a in this.editors&&(this.addproperty_checkboxes[a].disabled=!0),"undefined"!=typeof this.schema.minProperties&&d<=this.schema.minProperties?(this.addproperty_checkboxes[a].disabled=this.addproperty_checkboxes[a].checked,this.addproperty_checkboxes[a].checked||(e=!0)):a in this.editors?(e=!0,c=!0):b||this.schema.properties.hasOwnProperty(a)?(this.addproperty_checkboxes[a].disabled=!1,e=!0):this.addproperty_checkboxes[a].disabled=!0);this.canHaveAdditionalProperties()&&(e=!0);for(a in this.schema.properties)this.schema.properties.hasOwnProperty(a)&&(this.cached_editors[a]||(e=!0,this.addPropertyCheckbox(a)));e?this.canHaveAdditionalProperties()?b?this.addproperty_add.disabled=!1:this.addproperty_add.disabled=!0:(this.addproperty_add.style.display="none",this.addproperty_input.style.display="none"):(this.hideAddProperty(),this.addproperty_controls.style.display="none")},isRequired:function(a){return"boolean"==typeof a.schema.required?a.schema.required:Array.isArray(this.schema.required)?this.schema.required.indexOf(a.key)>-1:this.jsoneditor.options.required_by_default?!0:!1},setValue:function(a,b){var c=this;a=a||{},("object"!=typeof a||Array.isArray(a))&&(a={}),d(this.cached_editors,function(d,e){"undefined"!=typeof a[d]?(c.addObjectProperty(d),e.setValue(a[d],b)):b||c.isRequired(e)?e.setValue(e.getDefault(),b):c.removeObjectProperty(d)}),d(a,function(a,d){c.cached_editors[a]||(c.addObjectProperty(a),c.editors[a]&&c.editors[a].setValue(d,b))}),this.refreshValue(),this.layoutEditors(),this.onChange()},showValidationErrors:function(a){var b=this,c=[],e=[];if(d(a,function(a,d){d.path===b.path?c.push(d):e.push(d)}),this.error_holder)if(c.length){this.error_holder.innerHTML="",this.error_holder.style.display="",d(c,function(a,c){b.error_holder.appendChild(b.theme.getErrorMessage(c.message))})}else this.error_holder.style.display="none";this.options.table_row&&(c.length?this.theme.addTableRowError(this.container):this.theme.removeTableRowError(this.container)),d(this.editors,function(a,b){b.showValidationErrors(e)})}}),f.defaults.editors.array=f.AbstractEditor.extend({getDefault:function(){return this.schema["default"]||[]},register:function(){if(this._super(),this.rows)for(var a=0;a=this.schema.items.length?this.schema.additionalItems===!0?{}:this.schema.additionalItems?c({},this.schema.additionalItems):void 0:c({},this.schema.items[a]):this.schema.items?c({},this.schema.items):{}},getItemInfo:function(a){var b=this.getItemSchema(a);this.item_info=this.item_info||{};var c=JSON.stringify(b);return"undefined"!=typeof this.item_info[c]?this.item_info[c]:(b=this.jsoneditor.expandRefs(b),this.item_info[c]={title:b.title||"item","default":b["default"],width:12,child_editors:b.properties||b.items},this.item_info[c])},getElementEditor:function(a){var b=this.getItemInfo(a),c=this.getItemSchema(a);c=this.jsoneditor.expandRefs(c),c.title=b.title+" "+(a+1);var d,e=this.jsoneditor.getEditorClass(c);d=this.tabs_holder?this.theme.getTabContent():b.child_editors?this.theme.getChildEditorHolder():this.theme.getIndentedPanel(),this.row_holder.appendChild(d);var f=this.jsoneditor.createEditor(e,{jsoneditor:this.jsoneditor,schema:c,container:d,path:this.path+"."+a,parent:this,required:!0});return f.preBuild(),f.build(),f.postBuild(),f.title_controls||(f.array_controls=this.theme.getButtonHolder(),d.appendChild(f.array_controls)),f},destroy:function(){this.empty(!0),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.row_holder&&this.row_holder.parentNode&&this.row_holder.parentNode.removeChild(this.row_holder),this.controls&&this.controls.parentNode&&this.controls.parentNode.removeChild(this.controls),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.rows=this.row_cache=this.title=this.description=this.row_holder=this.panel=this.controls=null,this._super()},empty:function(a){if(this.rows){var b=this;d(this.rows,function(c,d){a&&(d.tab&&d.tab.parentNode&&d.tab.parentNode.removeChild(d.tab),b.destroyRow(d,!0),b.row_cache[c]=null),b.rows[c]=null}),b.rows=[],a&&(b.row_cache=[])}},destroyRow:function(a,b){var c=a.container;b?(a.destroy(),c.parentNode&&c.parentNode.removeChild(c),a.tab&&a.tab.parentNode&&a.tab.parentNode.removeChild(a.tab)):(a.tab&&(a.tab.style.display="none"),c.style.display="none",a.unregister())},getMax:function(){return Array.isArray(this.schema.items)&&this.schema.additionalItems===!1?Math.min(this.schema.items.length,this.schema.maxItems||1/0):this.schema.maxItems||1/0},refreshTabs:function(a){var b=this;d(this.rows,function(c,d){d.tab&&(a?d.tab_text.textContent=d.getHeaderText():d.tab===b.active_tab?(b.theme.markTabActive(d.tab),d.container.style.display=""):(b.theme.markTabInactive(d.tab),d.container.style.display="none"))})},setValue:function(a,b){a=a||[],Array.isArray(a)||(a=[a]);var c=JSON.stringify(a);if(c!==this.serialized){if(this.schema.minItems)for(;a.lengththis.getMax()&&(a=a.slice(0,this.getMax()));var e=this;d(a,function(a,c){e.rows[a]?e.rows[a].setValue(c,b):e.row_cache[a]?(e.rows[a]=e.row_cache[a],e.rows[a].setValue(c,b),e.rows[a].container.style.display="",e.rows[a].tab&&(e.rows[a].tab.style.display=""),e.rows[a].register()):e.addRow(c,b)});for(var f=a.length;f=this.rows.length;d(this.rows,function(a,c){c.movedown_button&&(a===b.rows.length-1?c.movedown_button.style.display="none":c.movedown_button.style.display=""),c.delete_button&&(e?c.delete_button.style.display="none":c.delete_button.style.display=""),b.value[a]=c.getValue()});var f=!1;this.value.length?1===this.value.length?(this.remove_all_rows_button.style.display="none",e||this.hide_delete_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",f=!0)):e||this.hide_delete_buttons?(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none"):(this.delete_last_row_button.style.display="",this.remove_all_rows_button.style.display="",f=!0):(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none"),this.getMax()&&this.getMax()<=this.rows.length||this.hide_add_button?this.add_row_button.style.display="none":(this.add_row_button.style.display="",f=!0),!this.collapsed&&f?this.controls.style.display="inline-block":this.controls.style.display="none"}},addRow:function(a,b){var c=this,e=this.rows.length;c.rows[e]=this.getElementEditor(e),c.row_cache[e]=c.rows[e],c.tabs_holder&&(c.rows[e].tab_text=document.createElement("span"),c.rows[e].tab_text.textContent=c.rows[e].getHeaderText(),c.rows[e].tab=c.theme.getTab(c.rows[e].tab_text),c.rows[e].tab.addEventListener("click",function(a){c.active_tab=c.rows[e].tab,c.refreshTabs(),a.preventDefault(),a.stopPropagation()}),c.theme.addTab(c.tabs_holder,c.rows[e].tab));var f=c.rows[e].title_controls||c.rows[e].array_controls;c.hide_delete_buttons||(c.rows[e].delete_button=this.getButton(c.getItemTitle(),"delete","Delete "+c.getItemTitle()),c.rows[e].delete_button.className+=" delete",c.rows[e].delete_button.setAttribute("data-i",e),c.rows[e].delete_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var b=1*this.getAttribute("data-i"),e=c.getValue(),f=[],g=null;d(e,function(a,d){return a===b?void(c.rows[a].tab===c.active_tab&&(c.rows[a+1]?g=c.rows[a].tab:a&&(g=c.rows[a-1].tab))):void f.push(d)}),c.setValue(f),g&&(c.active_tab=g,c.refreshTabs()),c.onChange(!0)}),f&&f.appendChild(c.rows[e].delete_button)),e&&!c.hide_move_buttons&&(c.rows[e].moveup_button=this.getButton("","moveup","Move up"),c.rows[e].moveup_button.className+=" moveup",c.rows[e].moveup_button.setAttribute("data-i",e),c.rows[e].moveup_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var b=1*this.getAttribute("data-i");if(!(0>=b)){var d=c.getValue(),e=d[b-1];d[b-1]=d[b],d[b]=e,c.setValue(d),c.active_tab=c.rows[b-1].tab,c.refreshTabs(),c.onChange(!0)}}),f&&f.appendChild(c.rows[e].moveup_button)),c.hide_move_buttons||(c.rows[e].movedown_button=this.getButton("","movedown","Move down"),c.rows[e].movedown_button.className+=" movedown",c.rows[e].movedown_button.setAttribute("data-i",e),c.rows[e].movedown_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var b=1*this.getAttribute("data-i"),d=c.getValue();if(!(b>=d.length-1)){var e=d[b+1];d[b+1]=d[b],d[b]=e,c.setValue(d),c.active_tab=c.rows[b+1].tab,c.refreshTabs(),c.onChange(!0)}}),f&&f.appendChild(c.rows[e].movedown_button)),a&&c.rows[e].setValue(a,b),c.refreshTabs()},addControls:function(){var a=this;this.collapsed=!1,this.toggle_button=this.getButton("","collapse","Collapse"),this.title_controls.appendChild(this.toggle_button);var b=a.row_holder.style.display,c=a.controls.style.display;this.toggle_button.addEventListener("click",function(d){d.preventDefault(),d.stopPropagation(),a.collapsed?(a.collapsed=!1,a.panel&&(a.panel.style.display=""),a.row_holder.style.display=b,a.tabs_holder&&(a.tabs_holder.style.display=""),a.controls.style.display=c,a.setButtonText(this,"","collapse","Collapse")):(a.collapsed=!0,a.row_holder.style.display="none",a.tabs_holder&&(a.tabs_holder.style.display="none"),a.controls.style.display="none",a.panel&&(a.panel.style.display="none"),a.setButtonText(this,"","expand","Expand"))}),this.options.collapsed&&e(this.toggle_button,"click"),this.schema.options&&"undefined"!=typeof this.schema.options.disable_collapse?this.schema.options.disable_collapse&&(this.toggle_button.style.display="none"):this.jsoneditor.options.disable_collapse&&(this.toggle_button.style.display="none"),this.add_row_button=this.getButton(this.getItemTitle(),"add","Add "+this.getItemTitle()),this.add_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.rows.length;a.row_cache[c]?(a.rows[c]=a.row_cache[c],a.rows[c].setValue(a.rows[c].getDefault()),a.rows[c].container.style.display="",a.rows[c].tab&&(a.rows[c].tab.style.display=""),a.rows[c].register()):a.addRow(),a.active_tab=a.rows[c].tab,a.refreshTabs(),a.refreshValue(),a.onChange(!0)}),a.controls.appendChild(this.add_row_button),this.delete_last_row_button=this.getButton("Last "+this.getItemTitle(),"delete","Delete Last "+this.getItemTitle()), +this.delete_last_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.getValue(),d=null;a.rows.length>1&&a.rows[a.rows.length-1].tab===a.active_tab&&(d=a.rows[a.rows.length-2].tab),c.pop(),a.setValue(c),d&&(a.active_tab=d,a.refreshTabs()),a.onChange(!0)}),a.controls.appendChild(this.delete_last_row_button),this.remove_all_rows_button=this.getButton("All","delete","Delete All"),this.remove_all_rows_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.setValue([]),a.onChange(!0)}),a.controls.appendChild(this.remove_all_rows_button),a.tabs&&(this.add_row_button.style.width="100%",this.add_row_button.style.textAlign="left",this.add_row_button.style.marginBottom="3px",this.delete_last_row_button.style.width="100%",this.delete_last_row_button.style.textAlign="left",this.delete_last_row_button.style.marginBottom="3px",this.remove_all_rows_button.style.width="100%",this.remove_all_rows_button.style.textAlign="left",this.remove_all_rows_button.style.marginBottom="3px")},showValidationErrors:function(a){var b=this,c=[],e=[];if(d(a,function(a,d){d.path===b.path?c.push(d):e.push(d)}),this.error_holder)if(c.length){this.error_holder.innerHTML="",this.error_holder.style.display="",d(c,function(a,c){b.error_holder.appendChild(b.theme.getErrorMessage(c.message))})}else this.error_holder.style.display="none";d(this.rows,function(a,b){b.showValidationErrors(e)})}}),f.defaults.editors.table=f.defaults.editors.array.extend({register:function(){if(this._super(),this.rows)for(var a=0;athis.schema.maxItems&&(a=a.slice(0,this.schema.maxItems));var c=JSON.stringify(a);if(c!==this.serialized){var e=!1,f=this;d(a,function(a,b){f.rows[a]?f.rows[a].setValue(b):(f.addRow(b),e=!0)});for(var g=a.length;g=this.rows.length,c=!1;d(this.rows,function(d,e){e.movedown_button&&(d===a.rows.length-1?e.movedown_button.style.display="none":(c=!0,e.movedown_button.style.display="")),e.delete_button&&(b?e.delete_button.style.display="none":(c=!0,e.delete_button.style.display="")),e.moveup_button&&(c=!0)}),d(this.rows,function(a,b){c?b.controls_cell.style.display="":b.controls_cell.style.display="none"}),c?this.controls_header_cell.style.display="":this.controls_header_cell.style.display="none";var e=!1;this.value.length?1===this.value.length||this.hide_delete_buttons?(this.table.style.display="",this.remove_all_rows_button.style.display="none",b||this.hide_delete_buttons?this.delete_last_row_button.style.display="none":(this.delete_last_row_button.style.display="",e=!0)):(this.table.style.display="",b||this.hide_delete_buttons?(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none"):(this.delete_last_row_button.style.display="",this.remove_all_rows_button.style.display="",e=!0)):(this.delete_last_row_button.style.display="none",this.remove_all_rows_button.style.display="none",this.table.style.display="none"),this.schema.maxItems&&this.schema.maxItems<=this.rows.length||this.hide_add_button?this.add_row_button.style.display="none":(this.add_row_button.style.display="",e=!0),e?this.controls.style.display="":this.controls.style.display="none"},refreshValue:function(){var a=this;this.value=[],d(this.rows,function(b,c){a.value[b]=c.getValue()}),this.serialized=JSON.stringify(this.value)},addRow:function(a){var b=this,c=this.rows.length;b.rows[c]=this.getElementEditor(c);var e=b.rows[c].table_controls;this.hide_delete_buttons||(b.rows[c].delete_button=this.getButton("","delete","Delete"),b.rows[c].delete_button.className+=" delete",b.rows[c].delete_button.setAttribute("data-i",c),b.rows[c].delete_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var c=1*this.getAttribute("data-i"),e=b.getValue(),f=[];d(e,function(a,b){a!==c&&f.push(b)}),b.setValue(f),b.onChange(!0)}),e.appendChild(b.rows[c].delete_button)),c&&!this.hide_move_buttons&&(b.rows[c].moveup_button=this.getButton("","moveup","Move up"),b.rows[c].moveup_button.className+=" moveup",b.rows[c].moveup_button.setAttribute("data-i",c),b.rows[c].moveup_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var c=1*this.getAttribute("data-i");if(!(0>=c)){var d=b.getValue(),e=d[c-1];d[c-1]=d[c],d[c]=e,b.setValue(d),b.onChange(!0)}}),e.appendChild(b.rows[c].moveup_button)),this.hide_move_buttons||(b.rows[c].movedown_button=this.getButton("","movedown","Move down"),b.rows[c].movedown_button.className+=" movedown",b.rows[c].movedown_button.setAttribute("data-i",c),b.rows[c].movedown_button.addEventListener("click",function(a){a.preventDefault(),a.stopPropagation();var c=1*this.getAttribute("data-i"),d=b.getValue();if(!(c>=d.length-1)){var e=d[c+1];d[c+1]=d[c],d[c]=e,b.setValue(d),b.onChange(!0)}}),e.appendChild(b.rows[c].movedown_button)),a&&b.rows[c].setValue(a)},addControls:function(){var a=this;this.collapsed=!1,this.toggle_button=this.getButton("","collapse","Collapse"),this.title_controls&&(this.title_controls.appendChild(this.toggle_button),this.toggle_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.collapsed?(a.collapsed=!1,a.panel.style.display="",a.setButtonText(this,"","collapse","Collapse")):(a.collapsed=!0,a.panel.style.display="none",a.setButtonText(this,"","expand","Expand"))}),this.options.collapsed&&e(this.toggle_button,"click"),this.schema.options&&"undefined"!=typeof this.schema.options.disable_collapse?this.schema.options.disable_collapse&&(this.toggle_button.style.display="none"):this.jsoneditor.options.disable_collapse&&(this.toggle_button.style.display="none")),this.add_row_button=this.getButton(this.getItemTitle(),"add","Add "+this.getItemTitle()),this.add_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.addRow(),a.refreshValue(),a.refreshRowButtons(),a.onChange(!0)}),a.controls.appendChild(this.add_row_button),this.delete_last_row_button=this.getButton("Last "+this.getItemTitle(),"delete","Delete Last "+this.getItemTitle()),this.delete_last_row_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation();var c=a.getValue();c.pop(),a.setValue(c),a.onChange(!0)}),a.controls.appendChild(this.delete_last_row_button),this.remove_all_rows_button=this.getButton("All","delete","Delete All"),this.remove_all_rows_button.addEventListener("click",function(b){b.preventDefault(),b.stopPropagation(),a.setValue([]),a.onChange(!0)}),a.controls.appendChild(this.remove_all_rows_button)}}),f.defaults.editors.multiple=f.AbstractEditor.extend({register:function(){if(this.editors){for(var a=0;anull";if("object"==typeof a){var c="";return d(a,function(d,e){var f=b.getHTML(e);Array.isArray(a)||(f="
"+d+": "+f+"
"),c+="
  • "+f+"
  • "}),c=Array.isArray(a)?"
      "+c+"
    ":"
      "+c+"
    "}return"boolean"==typeof a?a?"true":"false":"string"==typeof a?a.replace(/&/g,"&").replace(//g,">"):a},setValue:function(a){this.value!==a&&(this.value=a,this.refreshValue(),this.onChange())},destroy:function(){this.display_area&&this.display_area.parentNode&&this.display_area.parentNode.removeChild(this.display_area),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.switcher&&this.switcher.parentNode&&this.switcher.parentNode.removeChild(this.switcher),this._super()}}),f.defaults.editors.select=f.AbstractEditor.extend({setValue:function(a,b){a=this.typecast(a||"");var c=a;this.enum_values.indexOf(c)<0&&(c=this.enum_values[0]),this.value!==c&&(this.input.value=this.enum_options[this.enum_values.indexOf(c)],this.select2&&this.select2.select2("val",this.input.value),this.value=c,this.onChange())},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){if(!this.enum_options)return 3;for(var a=this.getTitle().length,b=0;b2||this.enum_options.length&&this.enumSource)){var a=c({},f.plugins.select2);this.schema.options&&this.schema.options.select2_options&&(a=c(a,this.schema.options.select2_options)),this.select2=window.jQuery(this.input).select2(a);var b=this;this.select2.on("select2-blur",function(){b.input.value=b.select2.select2("val"),b.onInputChange()})}else this.select2=null},postBuild:function(){this._super(),this.theme.afterInputReady(this.input),this.setupSelect2()},onWatchedFieldChange:function(){var a,b;if(this.enumSource){a=this.getWatchedFieldValues();for(var c=[],d=[],e=0;eType: "+a+", Size: "+Math.floor((this.value.length-this.value.split(",")[0].length-1)/1.33333)+" bytes","image"===a.substr(0,5)){this.preview.innerHTML+="
    ";var b=document.createElement("img");b.style.maxWidth="100%",b.style.maxHeight="100px",b.src=this.value,this.preview.appendChild(b)}}else this.preview.innerHTML="Invalid data URI"}},enable:function(){this.uploader&&(this.uploader.disabled=!1),this._super()},disable:function(){this.uploader&&(this.uploader.disabled=!0),this._super()},setValue:function(a){this.value!==a&&(this.value=a,this.input.value=this.value,this.refreshPreview(),this.onChange())},destroy:function(){this.preview&&this.preview.parentNode&&this.preview.parentNode.removeChild(this.preview),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.uploader&&this.uploader.parentNode&&this.uploader.parentNode.removeChild(this.uploader),this._super()}}),f.defaults.editors.upload=f.AbstractEditor.extend({getNumColumns:function(){return 4},build:function(){var a=this;if(this.title=this.header=this.label=this.theme.getFormInputLabel(this.getTitle(),this.isRequired()),this.input=this.theme.getFormInputField("hidden"),this.container.appendChild(this.input),!this.schema.readOnly&&!this.schema.readonly){if(!this.jsoneditor.options.upload)throw"Upload handler required for upload editor";this.uploader=this.theme.getFormInputField("file"),this.uploader.addEventListener("change",function(b){if(b.preventDefault(),b.stopPropagation(),this.files&&this.files.length){var c=new FileReader;c.onload=function(b){a.preview_value=b.target.result,a.refreshPreview(),a.onChange(!0),c=null},c.readAsDataURL(this.files[0])}})}var b=this.schema.description;b||(b=""),this.preview=this.theme.getFormInputDescription(b),this.container.appendChild(this.preview),this.control=this.theme.getFormControl(this.label,this.uploader||this.input,this.preview),this.container.appendChild(this.control)},refreshPreview:function(){if(this.last_preview!==this.preview_value&&(this.last_preview=this.preview_value,this.preview.innerHTML="",this.preview_value)){var a=this,b=this.preview_value.match(/^data:([^;,]+)[;,]/);b&&(b=b[1]),b||(b="unknown");var c=this.uploader.files[0];if(this.preview.innerHTML="Type: "+b+", Size: "+c.size+" bytes","image"===b.substr(0,5)){this.preview.innerHTML+="
    ";var d=document.createElement("img");d.style.maxWidth="100%",d.style.maxHeight="100px",d.src=this.preview_value, +this.preview.appendChild(d)}this.preview.innerHTML+="
    ";var e=this.getButton("Upload","upload","Upload");this.preview.appendChild(e),e.addEventListener("click",function(b){b.preventDefault(),e.setAttribute("disabled","disabled"),a.theme.removeInputError(a.uploader),a.theme.getProgressBar&&(a.progressBar=a.theme.getProgressBar(),a.preview.appendChild(a.progressBar)),a.jsoneditor.options.upload(a.path,c,{success:function(b){a.setValue(b),a.parent?a.parent.onChildEditorChange(a):a.jsoneditor.onChange(),a.progressBar&&a.preview.removeChild(a.progressBar),e.removeAttribute("disabled")},failure:function(b){a.theme.addInputError(a.uploader,b),a.progressBar&&a.preview.removeChild(a.progressBar),e.removeAttribute("disabled")},updateProgress:function(b){a.progressBar&&(b?a.theme.updateProgressBar(a.progressBar,b):a.theme.updateProgressBarUnknown(a.progressBar))}})})}},enable:function(){this.uploader&&(this.uploader.disabled=!1),this._super()},disable:function(){this.uploader&&(this.uploader.disabled=!0),this._super()},setValue:function(a){this.value!==a&&(this.value=a,this.input.value=this.value,this.onChange())},destroy:function(){this.preview&&this.preview.parentNode&&this.preview.parentNode.removeChild(this.preview),this.title&&this.title.parentNode&&this.title.parentNode.removeChild(this.title),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this.uploader&&this.uploader.parentNode&&this.uploader.parentNode.removeChild(this.uploader),this._super()}}),f.defaults.editors.checkbox=f.AbstractEditor.extend({setValue:function(a,b){this.value=!!a,this.input.checked=this.value,this.onChange()},register:function(){this._super(),this.input&&this.input.setAttribute("name",this.formname)},unregister:function(){this._super(),this.input&&this.input.removeAttribute("name")},getNumColumns:function(){return Math.min(12,Math.max(this.getTitle().length/7,2))},build:function(){var a=this;this.options.compact||(this.label=this.header=this.theme.getCheckboxLabel(this.getTitle())),this.schema.description&&(this.description=this.theme.getFormInputDescription(this.schema.description)),this.options.compact&&(this.container.className+=" compact"),this.input=this.theme.getCheckbox(),this.control=this.theme.getFormControl(this.label,this.input,this.description),(this.schema.readOnly||this.schema.readonly)&&(this.always_disabled=!0,this.input.disabled=!0),this.input.addEventListener("change",function(b){b.preventDefault(),b.stopPropagation(),a.value=this.checked,a.onChange(!0)}),this.container.appendChild(this.control)},enable:function(){this.always_disabled||(this.input.disabled=!1),this._super()},disable:function(){this.input.disabled=!0,this._super()},destroy:function(){this.label&&this.label.parentNode&&this.label.parentNode.removeChild(this.label),this.description&&this.description.parentNode&&this.description.parentNode.removeChild(this.description),this.input&&this.input.parentNode&&this.input.parentNode.removeChild(this.input),this._super()}});var g=function(){var a=document.documentElement;return a.matches?"matches":a.webkitMatchesSelector?"webkitMatchesSelector":a.mozMatchesSelector?"mozMatchesSelector":a.msMatchesSelector?"msMatchesSelector":a.oMatchesSelector?"oMatchesSelector":void 0}();f.AbstractTheme=a.extend({getContainer:function(){return document.createElement("div")},getFloatRightLinkHolder:function(){var a=document.createElement("div");return a.style=a.style||{},a.style.cssFloat="right",a.style.marginLeft="10px",a},getModal:function(){var a=document.createElement("div");return a.style.backgroundColor="white",a.style.border="1px solid black",a.style.boxShadow="3px 3px black",a.style.position="absolute",a.style.zIndex="10",a.style.display="none",a},getGridContainer:function(){var a=document.createElement("div");return a},getGridRow:function(){var a=document.createElement("div");return a.className="row",a},getGridColumn:function(){var a=document.createElement("div");return a},setGridColumnSize:function(a,b){},getLink:function(a){var b=document.createElement("a");return b.setAttribute("href","#"),b.appendChild(document.createTextNode(a)),b},disableHeader:function(a){a.style.color="#ccc"},disableLabel:function(a){a.style.color="#ccc"},enableHeader:function(a){a.style.color=""},enableLabel:function(a){a.style.color=""},getFormInputLabel:function(a){var b=document.createElement("label");return b.appendChild(document.createTextNode(a)),b},getCheckboxLabel:function(a){var b=this.getFormInputLabel(a);return b.style.fontWeight="normal",b},getHeader:function(a,b){var c=document.createElement("h3");return"string"==typeof a?c.textContent=a:c.appendChild(a),b&&(c.className+=" required"),c},getCheckbox:function(){var a=this.getFormInputField("checkbox");return a.style.display="inline-block",a.style.width="auto",a},getMultiCheckboxHolder:function(a,b,c){var d=document.createElement("div");b&&(b.style.display="block",d.appendChild(b));for(var e in a)a.hasOwnProperty(e)&&(a[e].style.display="inline-block",a[e].style.marginRight="20px",d.appendChild(a[e]));return c&&d.appendChild(c),d},getSelectInput:function(a){var b=document.createElement("select");return a&&this.setSelectOptions(b,a),b},getSwitcher:function(a){var b=this.getSelectInput(a);return b.style.backgroundColor="transparent",b.style.display="inline-block",b.style.fontStyle="italic",b.style.fontWeight="normal",b.style.height="auto",b.style.marginBottom=0,b.style.marginLeft="5px",b.style.padding="0 0 0 3px",b.style.width="auto",b},getSwitcherOptions:function(a){return a.getElementsByTagName("option")},setSwitcherOptions:function(a,b,c){this.setSelectOptions(a,b,c)},setSelectOptions:function(a,b,c){c=c||[],a.innerHTML="";for(var d=0;d'),a.errmsg=a.parentNode.getElementsByClassName("error")[0]),a.errmsg.textContent=b)},removeInputError:function(a){a.errmsg&&(a.group.className=a.group.className.replace(/ error/g,""),a.errmsg.style.display="none")},getProgressBar:function(){var a=document.createElement("div");a.className="progress";var b=document.createElement("span");return b.className="meter",b.style.width="0%",a.appendChild(b),a},updateProgressBar:function(a,b){a&&(a.firstChild.style.width=b+"%")},updateProgressBarUnknown:function(a){a&&(a.firstChild.style.width="100%")}}),f.defaults.themes.foundation3=f.defaults.themes.foundation.extend({getHeaderButtonHolder:function(){var a=this._super();return a.style.fontSize=".6em",a},getFormInputLabel:function(a,b){var c=this._super(a);return c.style.fontWeight="bold",b&&(c.className+=" required"),c},getTabHolder:function(){var a=document.createElement("div");return a.className="row",a.innerHTML="
    ",a},setGridColumnSize:function(a,b){var c=["zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve"];a.className="columns "+c[b]},getTab:function(a){var b=document.createElement("dd"),c=document.createElement("a");return c.setAttribute("href","#"),c.appendChild(a),b.appendChild(c),b},getTabContentHolder:function(a){return a.children[1]},getTabContent:function(){var a=document.createElement("div");return a.className="content active",a.style.paddingLeft="5px",a},markTabActive:function(a){a.className+=" active"},markTabInactive:function(a){a.className=a.className.replace(/\s*active/g,"")},addTab:function(a,b){a.children[0].appendChild(b)}}),f.defaults.themes.foundation4=f.defaults.themes.foundation.extend({getHeaderButtonHolder:function(){var a=this._super();return a.style.fontSize=".6em",a},setGridColumnSize:function(a,b){a.className="columns large-"+b},getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8rem",b},getFormInputLabel:function(a,b){var c=this._super(a);return c.style.fontWeight="bold",b&&(c.className+=" required"),c}}),f.defaults.themes.foundation5=f.defaults.themes.foundation.extend({getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8rem",b},setGridColumnSize:function(a,b){a.className="columns medium-"+b},getButton:function(a,b,c){var d=this._super(a,b,c);return d.className=d.className.replace(/\s*small/g,"")+" tiny",d},getTabHolder:function(){var a=document.createElement("div");return a.innerHTML="
    ",a},getTab:function(a){var b=document.createElement("dd"),c=document.createElement("a");return c.setAttribute("href","#"),c.appendChild(a),b.appendChild(c),b},getTabContentHolder:function(a){return a.children[1]},getTabContent:function(){var a=document.createElement("div");return a.className="content active",a.style.paddingLeft="5px",a},markTabActive:function(a){a.className+=" active"},markTabInactive:function(a){a.className=a.className.replace(/\s*active/g,"")},addTab:function(a,b){a.children[0].appendChild(b)}}),f.defaults.themes.html=f.AbstractTheme.extend({getFormInputLabel:function(a,b){var c=this._super(a);return c.style.display="block",c.style.marginBottom="3px",c.style.fontWeight="bold",b&&(c.className+=" required"),c},getFormInputDescription:function(a){var b=this._super(a);return b.style.fontSize=".8em",b.style.margin=0,b.style.display="inline-block",b.style.fontStyle="italic",b},getIndentedPanel:function(){var a=this._super();return a.style.border="1px solid #ddd",a.style.padding="5px",a.style.margin="5px",a.style.borderRadius="3px",a},getChildEditorHolder:function(){var a=this._super();return a.style.marginBottom="8px",a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.display="inline-block",a.style.marginLeft="10px",a.style.fontSize=".8em",a.style.verticalAlign="middle",a},getTable:function(){var a=this._super();return a.style.borderBottom="1px solid #ccc",a.style.marginBottom="5px",a},addInputError:function(a,b){if(a.style.borderColor="red",a.errmsg)a.errmsg.style.display="block";else{var c=this.closest(a,".form-control");a.errmsg=document.createElement("div"),a.errmsg.setAttribute("class","errmsg"),a.errmsg.style=a.errmsg.style||{},a.errmsg.style.color="red",c.appendChild(a.errmsg)}a.errmsg.innerHTML="",a.errmsg.appendChild(document.createTextNode(b))},removeInputError:function(a){a.style.borderColor="",a.errmsg&&(a.errmsg.style.display="none")},getProgressBar:function(){var a=100,b=0,c=document.createElement("progress");return c.setAttribute("max",a),c.setAttribute("value",b),c},updateProgressBar:function(a,b){a&&a.setAttribute("value",b)},updateProgressBarUnknown:function(a){a&&a.removeAttribute("value")}}),f.defaults.themes.jqueryui=f.AbstractTheme.extend({getTable:function(){var a=this._super();return a.setAttribute("cellpadding",5),a.setAttribute("cellspacing",0),a},getTableHeaderCell:function(a){var b=this._super(a);return b.className="ui-state-active",b.style.fontWeight="bold",b},getTableCell:function(){var a=this._super();return a.className="ui-widget-content",a},getHeaderButtonHolder:function(){var a=this.getButtonHolder();return a.style.marginLeft="10px",a.style.fontSize=".6em",a.style.display="inline-block",a},getFormInputDescription:function(a){var b=this.getDescription(a);return b.style.marginLeft="10px",b.style.display="inline-block",b},getFormControl:function(a,b,c){var d=this._super(a,b,c);return"checkbox"===b.type?(d.style.lineHeight="25px",d.style.padding="3px 0"):d.style.padding="4px 0 8px 0",d},getDescription:function(a){var b=document.createElement("span");return b.style.fontSize=".8em",b.style.fontStyle="italic",b.textContent=a,b},getButtonHolder:function(){var a=document.createElement("div");return a.className="ui-buttonset",a.style.fontSize=".7em",a},getFormInputLabel:function(a,b){var c=document.createElement("label");return c.style.fontWeight="bold",c.style.display="block",b&&(c.className+=" required"),c.textContent=a,c},getButton:function(a,b,c){var d=document.createElement("button");d.className="ui-button ui-widget ui-state-default ui-corner-all",b&&!a?(d.className+=" ui-button-icon-only",b.className+=" ui-button-icon-primary ui-icon-primary",d.appendChild(b)):b?(d.className+=" ui-button-text-icon-primary",b.className+=" ui-button-icon-primary ui-icon-primary",d.appendChild(b)):d.className+=" ui-button-text-only";var e=document.createElement("span");return e.className="ui-button-text",e.textContent=a||c||".",d.appendChild(e),d.setAttribute("title",c),d},setButtonText:function(a,b,c,d){a.innerHTML="",a.className="ui-button ui-widget ui-state-default ui-corner-all",c&&!b?(a.className+=" ui-button-icon-only",c.className+=" ui-button-icon-primary ui-icon-primary",a.appendChild(c)):c?(a.className+=" ui-button-text-icon-primary",c.className+=" ui-button-icon-primary ui-icon-primary",a.appendChild(c)):a.className+=" ui-button-text-only";var e=document.createElement("span");e.className="ui-button-text",e.textContent=b||d||".",a.appendChild(e),a.setAttribute("title",d)},getIndentedPanel:function(){var a=document.createElement("div");return a.className="ui-widget-content ui-corner-all",a.style.padding="1em 1.4em",a.style.marginBottom="20px",a},afterInputReady:function(a){a.controls||(a.controls=this.closest(a,".form-control"))},addInputError:function(a,b){a.controls&&(a.errmsg?a.errmsg.style.display="":(a.errmsg=document.createElement("div"),a.errmsg.className="ui-state-error",a.controls.appendChild(a.errmsg)),a.errmsg.textContent=b)},removeInputError:function(a){a.errmsg&&(a.errmsg.style.display="none")},markTabActive:function(a){a.className=a.className.replace(/\s*ui-widget-header/g,"")+" ui-state-active"},markTabInactive:function(a){a.className=a.className.replace(/\s*ui-state-active/g,"")+" ui-widget-header"}}),f.AbstractIconLib=a.extend({mapping:{collapse:"",expand:"","delete":"",edit:"",add:"",cancel:"",save:"",moveup:"",movedown:""},icon_prefix:"",getIconClass:function(a){return this.mapping[a]?this.icon_prefix+this.mapping[a]:null},getIcon:function(a){var b=this.getIconClass(a);if(!b)return null;var c=document.createElement("i");return c.className=b,c}}),f.defaults.iconlibs.bootstrap2=f.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-up","delete":"trash",edit:"pencil",add:"plus",cancel:"ban-circle",save:"ok",moveup:"arrow-up",movedown:"arrow-down"},icon_prefix:"icon-"}),f.defaults.iconlibs.bootstrap3=f.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-right","delete":"remove",edit:"pencil",add:"plus",cancel:"floppy-remove",save:"floppy-saved",moveup:"arrow-up",movedown:"arrow-down"},icon_prefix:"glyphicon glyphicon-"}),f.defaults.iconlibs.fontawesome3=f.AbstractIconLib.extend({mapping:{collapse:"chevron-down",expand:"chevron-right","delete":"remove",edit:"pencil",add:"plus",cancel:"ban-circle",save:"save",moveup:"arrow-up",movedown:"arrow-down"},icon_prefix:"icon-"}),f.defaults.iconlibs.fontawesome4=f.AbstractIconLib.extend({mapping:{collapse:"caret-square-o-down",expand:"caret-square-o-right","delete":"times",edit:"pencil",add:"plus",cancel:"ban",save:"save",moveup:"arrow-up",movedown:"arrow-down"},icon_prefix:"fa fa-"}),f.defaults.iconlibs.foundation2=f.AbstractIconLib.extend({mapping:{collapse:"minus",expand:"plus","delete":"remove",edit:"edit",add:"add-doc",cancel:"error",save:"checkmark",moveup:"up-arrow",movedown:"down-arrow"},icon_prefix:"foundicon-"}),f.defaults.iconlibs.foundation3=f.AbstractIconLib.extend({mapping:{collapse:"minus",expand:"plus","delete":"x",edit:"pencil",add:"page-add",cancel:"x-circle",save:"save",moveup:"arrow-up",movedown:"arrow-down"},icon_prefix:"fi-"}),f.defaults.iconlibs.jqueryui=f.AbstractIconLib.extend({mapping:{collapse:"triangle-1-s",expand:"triangle-1-e","delete":"trash",edit:"pencil",add:"plusthick",cancel:"closethick",save:"disk",moveup:"arrowthick-1-n",movedown:"arrowthick-1-s"},icon_prefix:"ui-icon ui-icon-"}),f.defaults.templates["default"]=function(){return{compile:function(a){var b=a.match(/{{\s*([a-zA-Z0-9\-_ \.]+)\s*}}/g),c=b&&b.length;if(!c)return function(){return a};for(var d=[],e=function(a){var c,e=b[a].replace(/[{}]+/g,"").trim().split("."),f=e.length;if(f>1){var g;c=function(b){for(g=b,a=0;f>a&&(g=g[e[a]],g);a++);return g}}else e=e[0],c=function(a){return a[e]};d.push({s:b[a],r:c})},f=0;c>f;f++)e(f);return function(b){var e,g=a+"";for(f=0;c>f;f++)e=d[f],g=g.replace(e.s,e.r(b));return g}}}},f.defaults.templates.ejs=function(){return window.EJS?{compile:function(a){var b=new window.EJS({text:a});return function(a){return b.render(a)}}}:!1},f.defaults.templates.handlebars=function(){return window.Handlebars},f.defaults.templates.hogan=function(){return window.Hogan?{compile:function(a){var b=window.Hogan.compile(a);return function(a){return b.render(a)}}}:!1},f.defaults.templates.markup=function(){return window.Mark&&window.Mark.up?{compile:function(a){return function(b){return window.Mark.up(a,b)}}}:!1},f.defaults.templates.mustache=function(){return window.Mustache?{compile:function(a){return function(b){return window.Mustache.render(a,b)}}}:!1},f.defaults.templates.swig=function(){return window.swig},f.defaults.templates.underscore=function(){return window._?{compile:function(a){return function(b){return window._.template(a,b)}}}:!1},f.defaults.theme="html",f.defaults.template="default",f.defaults.options={},f.defaults.translate=function(a,b){var c=f.defaults.languages[f.defaults.language];if(!c)throw"Unknown language "+f.defaults.language;var d=c[a]||f.defaults.languages[f.defaults.default_language][a];if("undefined"==typeof d)throw"Unknown translate string "+a;if(b)for(var e=0;e=0?"multiselect":void 0}),f.defaults.resolvers.unshift(function(a){return a.oneOf?"multiple":void 0}),function(){if(window.jQuery||window.Zepto){var a=window.jQuery||window.Zepto;a.jsoneditor=f.defaults,a.fn.jsoneditor=function(a){var b=this,c=this.data("jsoneditor");if("value"===a){if(!c)throw"Must initialize jsoneditor before getting/setting the value";if(!(arguments.length>1))return c.getValue();c.setValue(arguments[1])}else{if("validate"===a){if(!c)throw"Must initialize jsoneditor before validating";return arguments.length>1?c.validate(arguments[1]):c.validate()}"destroy"===a?c&&(c.destroy(),this.data("jsoneditor",null)):(c&&c.destroy(),c=new f(this.get(0),a),this.data("jsoneditor",c),c.on("change",function(){b.trigger("change")}),c.on("ready",function(){b.trigger("ready")}))}return this}}}(),window.JSONEditor=f}(); \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/marked.js b/PlexRequests.UI/Content/swagger/marked.js new file mode 100644 index 000000000..c2a678d55 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/marked.js @@ -0,0 +1,1272 @@ +/** + * marked - a markdown parser + * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) + * https://github.com/chjj/marked + */ + +;(function() { + +/** + * Block-Level Grammar + */ + +var block = { + newline: /^\n+/, + code: /^( {4}[^\n]+\n*)+/, + fences: noop, + hr: /^( *[-*_]){3,} *(?:\n+|$)/, + heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, + nptable: noop, + lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, + blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, + list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, + html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, + def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, + table: noop, + paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, + text: /^[^\n]+/ +}; + +block.bullet = /(?:[*+-]|\d+\.)/; +block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; +block.item = replace(block.item, 'gm') + (/bull/g, block.bullet) + (); + +block.list = replace(block.list) + (/bull/g, block.bullet) + ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') + ('def', '\\n+(?=' + block.def.source + ')') + (); + +block.blockquote = replace(block.blockquote) + ('def', block.def) + (); + +block._tag = '(?!(?:' + + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' + + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' + + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; + +block.html = replace(block.html) + ('comment', //) + ('closed', /<(tag)[\s\S]+?<\/\1>/) + ('closing', /])*?>/) + (/tag/g, block._tag) + (); + +block.paragraph = replace(block.paragraph) + ('hr', block.hr) + ('heading', block.heading) + ('lheading', block.lheading) + ('blockquote', block.blockquote) + ('tag', '<' + block._tag) + ('def', block.def) + (); + +/** + * Normal Block Grammar + */ + +block.normal = merge({}, block); + +/** + * GFM Block Grammar + */ + +block.gfm = merge({}, block.normal, { + fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, + paragraph: /^/ +}); + +block.gfm.paragraph = replace(block.paragraph) + ('(?!', '(?!' + + block.gfm.fences.source.replace('\\1', '\\2') + '|' + + block.list.source.replace('\\1', '\\3') + '|') + (); + +/** + * GFM + Tables Block Grammar + */ + +block.tables = merge({}, block.gfm, { + nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, + table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ +}); + +/** + * Block Lexer + */ + +function Lexer(options) { + this.tokens = []; + this.tokens.links = {}; + this.options = options || marked.defaults; + this.rules = block.normal; + + if (this.options.gfm) { + if (this.options.tables) { + this.rules = block.tables; + } else { + this.rules = block.gfm; + } + } +} + +/** + * Expose Block Rules + */ + +Lexer.rules = block; + +/** + * Static Lex Method + */ + +Lexer.lex = function(src, options) { + var lexer = new Lexer(options); + return lexer.lex(src); +}; + +/** + * Preprocessing + */ + +Lexer.prototype.lex = function(src) { + src = src + .replace(/\r\n|\r/g, '\n') + .replace(/\t/g, ' ') + .replace(/\u00a0/g, ' ') + .replace(/\u2424/g, '\n'); + + return this.token(src, true); +}; + +/** + * Lexing + */ + +Lexer.prototype.token = function(src, top, bq) { + var src = src.replace(/^ +$/gm, '') + , next + , loose + , cap + , bull + , b + , item + , space + , i + , l; + + while (src) { + // newline + if (cap = this.rules.newline.exec(src)) { + src = src.substring(cap[0].length); + if (cap[0].length > 1) { + this.tokens.push({ + type: 'space' + }); + } + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + cap = cap[0].replace(/^ {4}/gm, ''); + this.tokens.push({ + type: 'code', + text: !this.options.pedantic + ? cap.replace(/\n+$/, '') + : cap + }); + continue; + } + + // fences (gfm) + if (cap = this.rules.fences.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'code', + lang: cap[2], + text: cap[3] + }); + continue; + } + + // heading + if (cap = this.rules.heading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[1].length, + text: cap[2] + }); + continue; + } + + // table no leading pipe (gfm) + if (top && (cap = this.rules.nptable.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i].split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // lheading + if (cap = this.rules.lheading.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'heading', + depth: cap[2] === '=' ? 1 : 2, + text: cap[1] + }); + continue; + } + + // hr + if (cap = this.rules.hr.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'hr' + }); + continue; + } + + // blockquote + if (cap = this.rules.blockquote.exec(src)) { + src = src.substring(cap[0].length); + + this.tokens.push({ + type: 'blockquote_start' + }); + + cap = cap[0].replace(/^ *> ?/gm, ''); + + // Pass `top` to keep the current + // "toplevel" state. This is exactly + // how markdown.pl works. + this.token(cap, top, true); + + this.tokens.push({ + type: 'blockquote_end' + }); + + continue; + } + + // list + if (cap = this.rules.list.exec(src)) { + src = src.substring(cap[0].length); + bull = cap[2]; + + this.tokens.push({ + type: 'list_start', + ordered: bull.length > 1 + }); + + // Get each top-level item. + cap = cap[0].match(this.rules.item); + + next = false; + l = cap.length; + i = 0; + + for (; i < l; i++) { + item = cap[i]; + + // Remove the list item's bullet + // so it is seen as the next token. + space = item.length; + item = item.replace(/^ *([*+-]|\d+\.) +/, ''); + + // Outdent whatever the + // list item contains. Hacky. + if (~item.indexOf('\n ')) { + space -= item.length; + item = !this.options.pedantic + ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') + : item.replace(/^ {1,4}/gm, ''); + } + + // Determine whether the next list item belongs here. + // Backpedal if it does not belong in this list. + if (this.options.smartLists && i !== l - 1) { + b = block.bullet.exec(cap[i + 1])[0]; + if (bull !== b && !(bull.length > 1 && b.length > 1)) { + src = cap.slice(i + 1).join('\n') + src; + i = l - 1; + } + } + + // Determine whether item is loose or not. + // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ + // for discount behavior. + loose = next || /\n\n(?!\s*$)/.test(item); + if (i !== l - 1) { + next = item.charAt(item.length - 1) === '\n'; + if (!loose) loose = next; + } + + this.tokens.push({ + type: loose + ? 'loose_item_start' + : 'list_item_start' + }); + + // Recurse. + this.token(item, false, bq); + + this.tokens.push({ + type: 'list_item_end' + }); + } + + this.tokens.push({ + type: 'list_end' + }); + + continue; + } + + // html + if (cap = this.rules.html.exec(src)) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: this.options.sanitize + ? 'paragraph' + : 'html', + pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + text: cap[0] + }); + continue; + } + + // def + if ((!bq && top) && (cap = this.rules.def.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.links[cap[1].toLowerCase()] = { + href: cap[2], + title: cap[3] + }; + continue; + } + + // table (gfm) + if (top && (cap = this.rules.table.exec(src))) { + src = src.substring(cap[0].length); + + item = { + type: 'table', + header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), + align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), + cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') + }; + + for (i = 0; i < item.align.length; i++) { + if (/^ *-+: *$/.test(item.align[i])) { + item.align[i] = 'right'; + } else if (/^ *:-+: *$/.test(item.align[i])) { + item.align[i] = 'center'; + } else if (/^ *:-+ *$/.test(item.align[i])) { + item.align[i] = 'left'; + } else { + item.align[i] = null; + } + } + + for (i = 0; i < item.cells.length; i++) { + item.cells[i] = item.cells[i] + .replace(/^ *\| *| *\| *$/g, '') + .split(/ *\| */); + } + + this.tokens.push(item); + + continue; + } + + // top-level paragraph + if (top && (cap = this.rules.paragraph.exec(src))) { + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'paragraph', + text: cap[1].charAt(cap[1].length - 1) === '\n' + ? cap[1].slice(0, -1) + : cap[1] + }); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + // Top-level should never reach here. + src = src.substring(cap[0].length); + this.tokens.push({ + type: 'text', + text: cap[0] + }); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return this.tokens; +}; + +/** + * Inline-Level Grammar + */ + +var inline = { + escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, + autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, + url: noop, + tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, + link: /^!?\[(inside)\]\(href\)/, + reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, + nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, + strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, + em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, + br: /^ {2,}\n(?!\s*$)/, + del: noop, + text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; + +inline.link = replace(inline.link) + ('inside', inline._inside) + ('href', inline._href) + (); + +inline.reflink = replace(inline.reflink) + ('inside', inline._inside) + (); + +/** + * Normal Inline Grammar + */ + +inline.normal = merge({}, inline); + +/** + * Pedantic Inline Grammar + */ + +inline.pedantic = merge({}, inline.normal, { + strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, + em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ +}); + +/** + * GFM Inline Grammar + */ + +inline.gfm = merge({}, inline.normal, { + escape: replace(inline.escape)('])', '~|])')(), + url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, + del: /^~~(?=\S)([\s\S]*?\S)~~/, + text: replace(inline.text) + (']|', '~]|') + ('|', '|https?://|') + () +}); + +/** + * GFM + Line Breaks Inline Grammar + */ + +inline.breaks = merge({}, inline.gfm, { + br: replace(inline.br)('{2,}', '*')(), + text: replace(inline.gfm.text)('{2,}', '*')() +}); + +/** + * Inline Lexer & Compiler + */ + +function InlineLexer(links, options) { + this.options = options || marked.defaults; + this.links = links; + this.rules = inline.normal; + this.renderer = this.options.renderer || new Renderer; + this.renderer.options = this.options; + + if (!this.links) { + throw new + Error('Tokens array requires a `links` property.'); + } + + if (this.options.gfm) { + if (this.options.breaks) { + this.rules = inline.breaks; + } else { + this.rules = inline.gfm; + } + } else if (this.options.pedantic) { + this.rules = inline.pedantic; + } +} + +/** + * Expose Inline Rules + */ + +InlineLexer.rules = inline; + +/** + * Static Lexing/Compiling Method + */ + +InlineLexer.output = function(src, links, options) { + var inline = new InlineLexer(links, options); + return inline.output(src); +}; + +/** + * Lexing/Compiling + */ + +InlineLexer.prototype.output = function(src) { + var out = '' + , link + , text + , href + , cap; + + while (src) { + // escape + if (cap = this.rules.escape.exec(src)) { + src = src.substring(cap[0].length); + out += cap[1]; + continue; + } + + // autolink + if (cap = this.rules.autolink.exec(src)) { + src = src.substring(cap[0].length); + if (cap[2] === '@') { + text = cap[1].charAt(6) === ':' + ? this.mangle(cap[1].substring(7)) + : this.mangle(cap[1]); + href = this.mangle('mailto:') + text; + } else { + text = escape(cap[1]); + href = text; + } + out += this.renderer.link(href, null, text); + continue; + } + + // url (gfm) + if (!this.inLink && (cap = this.rules.url.exec(src))) { + src = src.substring(cap[0].length); + text = escape(cap[1]); + href = text; + out += this.renderer.link(href, null, text); + continue; + } + + // tag + if (cap = this.rules.tag.exec(src)) { + if (!this.inLink && /^/i.test(cap[0])) { + this.inLink = false; + } + src = src.substring(cap[0].length); + out += this.options.sanitize + ? escape(cap[0]) + : cap[0]; + continue; + } + + // link + if (cap = this.rules.link.exec(src)) { + src = src.substring(cap[0].length); + this.inLink = true; + out += this.outputLink(cap, { + href: cap[2], + title: cap[3] + }); + this.inLink = false; + continue; + } + + // reflink, nolink + if ((cap = this.rules.reflink.exec(src)) + || (cap = this.rules.nolink.exec(src))) { + src = src.substring(cap[0].length); + link = (cap[2] || cap[1]).replace(/\s+/g, ' '); + link = this.links[link.toLowerCase()]; + if (!link || !link.href) { + out += cap[0].charAt(0); + src = cap[0].substring(1) + src; + continue; + } + this.inLink = true; + out += this.outputLink(cap, link); + this.inLink = false; + continue; + } + + // strong + if (cap = this.rules.strong.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.strong(this.output(cap[2] || cap[1])); + continue; + } + + // em + if (cap = this.rules.em.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.em(this.output(cap[2] || cap[1])); + continue; + } + + // code + if (cap = this.rules.code.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.codespan(escape(cap[2], true)); + continue; + } + + // br + if (cap = this.rules.br.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.br(); + continue; + } + + // del (gfm) + if (cap = this.rules.del.exec(src)) { + src = src.substring(cap[0].length); + out += this.renderer.del(this.output(cap[1])); + continue; + } + + // text + if (cap = this.rules.text.exec(src)) { + src = src.substring(cap[0].length); + out += escape(this.smartypants(cap[0])); + continue; + } + + if (src) { + throw new + Error('Infinite loop on byte: ' + src.charCodeAt(0)); + } + } + + return out; +}; + +/** + * Compile Link + */ + +InlineLexer.prototype.outputLink = function(cap, link) { + var href = escape(link.href) + , title = link.title ? escape(link.title) : null; + + return cap[0].charAt(0) !== '!' + ? this.renderer.link(href, title, this.output(cap[1])) + : this.renderer.image(href, title, escape(cap[1])); +}; + +/** + * Smartypants Transformations + */ + +InlineLexer.prototype.smartypants = function(text) { + if (!this.options.smartypants) return text; + return text + // em-dashes + .replace(/--/g, '\u2014') + // opening singles + .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') + // closing singles & apostrophes + .replace(/'/g, '\u2019') + // opening doubles + .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') + // closing doubles + .replace(/"/g, '\u201d') + // ellipses + .replace(/\.{3}/g, '\u2026'); +}; + +/** + * Mangle Links + */ + +InlineLexer.prototype.mangle = function(text) { + var out = '' + , l = text.length + , i = 0 + , ch; + + for (; i < l; i++) { + ch = text.charCodeAt(i); + if (Math.random() > 0.5) { + ch = 'x' + ch.toString(16); + } + out += '&#' + ch + ';'; + } + + return out; +}; + +/** + * Renderer + */ + +function Renderer(options) { + this.options = options || {}; +} + +Renderer.prototype.code = function(code, lang, escaped) { + if (this.options.highlight) { + var out = this.options.highlight(code, lang); + if (out != null && out !== code) { + escaped = true; + code = out; + } + } + + if (!lang) { + return '
    '
    +      + (escaped ? code : escape(code, true))
    +      + '\n
    '; + } + + return '
    '
    +    + (escaped ? code : escape(code, true))
    +    + '\n
    \n'; +}; + +Renderer.prototype.blockquote = function(quote) { + return '
    \n' + quote + '
    \n'; +}; + +Renderer.prototype.html = function(html) { + return html; +}; + +Renderer.prototype.heading = function(text, level, raw) { + return '' + + text + + '\n'; +}; + +Renderer.prototype.hr = function() { + return this.options.xhtml ? '
    \n' : '
    \n'; +}; + +Renderer.prototype.list = function(body, ordered) { + var type = ordered ? 'ol' : 'ul'; + return '<' + type + '>\n' + body + '\n'; +}; + +Renderer.prototype.listitem = function(text) { + return '
  • ' + text + '
  • \n'; +}; + +Renderer.prototype.paragraph = function(text) { + return '

    ' + text + '

    \n'; +}; + +Renderer.prototype.table = function(header, body) { + return '
    \n' + + '\n' + + header + + '\n' + + '\n' + + body + + '\n' + + '
    \n'; +}; + +Renderer.prototype.tablerow = function(content) { + return '\n' + content + '\n'; +}; + +Renderer.prototype.tablecell = function(content, flags) { + var type = flags.header ? 'th' : 'td'; + var tag = flags.align + ? '<' + type + ' style="text-align:' + flags.align + '">' + : '<' + type + '>'; + return tag + content + '\n'; +}; + +// span level renderer +Renderer.prototype.strong = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.em = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.codespan = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.br = function() { + return this.options.xhtml ? '
    ' : '
    '; +}; + +Renderer.prototype.del = function(text) { + return '' + text + ''; +}; + +Renderer.prototype.link = function(href, title, text) { + if (this.options.sanitize) { + try { + var prot = decodeURIComponent(unescape(href)) + .replace(/[^\w:]/g, '') + .toLowerCase(); + } catch (e) { + return ''; + } + if (prot.indexOf('javascript:') === 0) { + return ''; + } + } + var out = '
    '; + return out; +}; + +Renderer.prototype.image = function(href, title, text) { + var out = '' + text + '' : '>'; + return out; +}; + +/** + * Parsing & Compiling + */ + +function Parser(options) { + this.tokens = []; + this.token = null; + this.options = options || marked.defaults; + this.options.renderer = this.options.renderer || new Renderer; + this.renderer = this.options.renderer; + this.renderer.options = this.options; +} + +/** + * Static Parse Method + */ + +Parser.parse = function(src, options, renderer) { + var parser = new Parser(options, renderer); + return parser.parse(src); +}; + +/** + * Parse Loop + */ + +Parser.prototype.parse = function(src) { + this.inline = new InlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; +}; + +/** + * Next Token + */ + +Parser.prototype.next = function() { + return this.token = this.tokens.pop(); +}; + +/** + * Preview Next Token + */ + +Parser.prototype.peek = function() { + return this.tokens[this.tokens.length - 1] || 0; +}; + +/** + * Parse Text Tokens + */ + +Parser.prototype.parseText = function() { + var body = this.token.text; + + while (this.peek().type === 'text') { + body += '\n' + this.next().text; + } + + return this.inline.output(body); +}; + +/** + * Parse Current Token + */ + +Parser.prototype.tok = function() { + switch (this.token.type) { + case 'space': { + return ''; + } + case 'hr': { + return this.renderer.hr(); + } + case 'heading': { + return this.renderer.heading( + this.inline.output(this.token.text), + this.token.depth, + this.token.text); + } + case 'code': { + return this.renderer.code(this.token.text, + this.token.lang, + this.token.escaped); + } + case 'table': { + var header = '' + , body = '' + , i + , row + , cell + , flags + , j; + + // header + cell = ''; + for (i = 0; i < this.token.header.length; i++) { + flags = { header: true, align: this.token.align[i] }; + cell += this.renderer.tablecell( + this.inline.output(this.token.header[i]), + { header: true, align: this.token.align[i] } + ); + } + header += this.renderer.tablerow(cell); + + for (i = 0; i < this.token.cells.length; i++) { + row = this.token.cells[i]; + + cell = ''; + for (j = 0; j < row.length; j++) { + cell += this.renderer.tablecell( + this.inline.output(row[j]), + { header: false, align: this.token.align[j] } + ); + } + + body += this.renderer.tablerow(cell); + } + return this.renderer.table(header, body); + } + case 'blockquote_start': { + var body = ''; + + while (this.next().type !== 'blockquote_end') { + body += this.tok(); + } + + return this.renderer.blockquote(body); + } + case 'list_start': { + var body = '' + , ordered = this.token.ordered; + + while (this.next().type !== 'list_end') { + body += this.tok(); + } + + return this.renderer.list(body, ordered); + } + case 'list_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.token.type === 'text' + ? this.parseText() + : this.tok(); + } + + return this.renderer.listitem(body); + } + case 'loose_item_start': { + var body = ''; + + while (this.next().type !== 'list_item_end') { + body += this.tok(); + } + + return this.renderer.listitem(body); + } + case 'html': { + var html = !this.token.pre && !this.options.pedantic + ? this.inline.output(this.token.text) + : this.token.text; + return this.renderer.html(html); + } + case 'paragraph': { + return this.renderer.paragraph(this.inline.output(this.token.text)); + } + case 'text': { + return this.renderer.paragraph(this.parseText()); + } + } +}; + +/** + * Helpers + */ + +function escape(html, encode) { + return html + .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function unescape(html) { + return html.replace(/&([#\w]+);/g, function(_, n) { + n = n.toLowerCase(); + if (n === 'colon') return ':'; + if (n.charAt(0) === '#') { + return n.charAt(1) === 'x' + ? String.fromCharCode(parseInt(n.substring(2), 16)) + : String.fromCharCode(+n.substring(1)); + } + return ''; + }); +} + +function replace(regex, opt) { + regex = regex.source; + opt = opt || ''; + return function self(name, val) { + if (!name) return new RegExp(regex, opt); + val = val.source || val; + val = val.replace(/(^|[^\[])\^/g, '$1'); + regex = regex.replace(name, val); + return self; + }; +} + +function noop() {} +noop.exec = noop; + +function merge(obj) { + var i = 1 + , target + , key; + + for (; i < arguments.length; i++) { + target = arguments[i]; + for (key in target) { + if (Object.prototype.hasOwnProperty.call(target, key)) { + obj[key] = target[key]; + } + } + } + + return obj; +} + + +/** + * Marked + */ + +function marked(src, opt, callback) { + if (callback || typeof opt === 'function') { + if (!callback) { + callback = opt; + opt = null; + } + + opt = merge({}, marked.defaults, opt || {}); + + var highlight = opt.highlight + , tokens + , pending + , i = 0; + + try { + tokens = Lexer.lex(src, opt) + } catch (e) { + return callback(e); + } + + pending = tokens.length; + + var done = function(err) { + if (err) { + opt.highlight = highlight; + return callback(err); + } + + var out; + + try { + out = Parser.parse(tokens, opt); + } catch (e) { + err = e; + } + + opt.highlight = highlight; + + return err + ? callback(err) + : callback(null, out); + }; + + if (!highlight || highlight.length < 3) { + return done(); + } + + delete opt.highlight; + + if (!pending) return done(); + + for (; i < tokens.length; i++) { + (function(token) { + if (token.type !== 'code') { + return --pending || done(); + } + return highlight(token.text, token.lang, function(err, code) { + if (err) return done(err); + if (code == null || code === token.text) { + return --pending || done(); + } + token.text = code; + token.escaped = true; + --pending || done(); + }); + })(tokens[i]); + } + + return; + } + try { + if (opt) opt = merge({}, marked.defaults, opt); + return Parser.parse(Lexer.lex(src, opt), opt); + } catch (e) { + e.message += '\nPlease report this to https://github.com/chjj/marked.'; + if ((opt || marked.defaults).silent) { + return '

    An error occured:

    '
    +        + escape(e.message + '', true)
    +        + '
    '; + } + throw e; + } +} + +/** + * Options + */ + +marked.options = +marked.setOptions = function(opt) { + merge(marked.defaults, opt); + return marked; +}; + +marked.defaults = { + gfm: true, + tables: true, + breaks: false, + pedantic: false, + sanitize: false, + smartLists: false, + silent: false, + highlight: null, + langPrefix: 'lang-', + smartypants: false, + headerPrefix: '', + renderer: new Renderer, + xhtml: false +}; + +/** + * Expose + */ + +marked.Parser = Parser; +marked.parser = Parser.parse; + +marked.Renderer = Renderer; + +marked.Lexer = Lexer; +marked.lexer = Lexer.lex; + +marked.InlineLexer = InlineLexer; +marked.inlineLexer = InlineLexer.output; + +marked.parse = marked; + +if (typeof module !== 'undefined' && typeof exports === 'object') { + module.exports = marked; +} else if (typeof define === 'function' && define.amd) { + define(function() { return marked; }); +} else { + this.marked = marked; +} + +}).call(function() { + return this || (typeof window !== 'undefined' ? window : global); +}()); \ No newline at end of file diff --git a/PlexRequests.UI/Content/swagger/print.css b/PlexRequests.UI/Content/swagger/print.css new file mode 100644 index 000000000..2e6b31030 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/print.css @@ -0,0 +1,1187 @@ +/* Original style from softwaremaniacs.org (c) Ivan Sagalaev */ +.swagger-section pre code { + display: block; + padding: 0.5em; + background: #F0F0F0; +} +.swagger-section pre code, +.swagger-section pre .subst, +.swagger-section pre .tag .title, +.swagger-section pre .lisp .title, +.swagger-section pre .clojure .built_in, +.swagger-section pre .nginx .title { + color: black; +} +.swagger-section pre .string, +.swagger-section pre .title, +.swagger-section pre .constant, +.swagger-section pre .parent, +.swagger-section pre .tag .value, +.swagger-section pre .rules .value, +.swagger-section pre .rules .value .number, +.swagger-section pre .preprocessor, +.swagger-section pre .ruby .symbol, +.swagger-section pre .ruby .symbol .string, +.swagger-section pre .aggregate, +.swagger-section pre .template_tag, +.swagger-section pre .django .variable, +.swagger-section pre .smalltalk .class, +.swagger-section pre .addition, +.swagger-section pre .flow, +.swagger-section pre .stream, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .apache .cbracket, +.swagger-section pre .tex .command, +.swagger-section pre .tex .special, +.swagger-section pre .erlang_repl .function_or_atom, +.swagger-section pre .markdown .header { + color: #800; +} +.swagger-section pre .comment, +.swagger-section pre .annotation, +.swagger-section pre .template_comment, +.swagger-section pre .diff .header, +.swagger-section pre .chunk, +.swagger-section pre .markdown .blockquote { + color: #888; +} +.swagger-section pre .number, +.swagger-section pre .date, +.swagger-section pre .regexp, +.swagger-section pre .literal, +.swagger-section pre .smalltalk .symbol, +.swagger-section pre .smalltalk .char, +.swagger-section pre .go .constant, +.swagger-section pre .change, +.swagger-section pre .markdown .bullet, +.swagger-section pre .markdown .link_url { + color: #080; +} +.swagger-section pre .label, +.swagger-section pre .javadoc, +.swagger-section pre .ruby .string, +.swagger-section pre .decorator, +.swagger-section pre .filter .argument, +.swagger-section pre .localvars, +.swagger-section pre .array, +.swagger-section pre .attr_selector, +.swagger-section pre .important, +.swagger-section pre .pseudo, +.swagger-section pre .pi, +.swagger-section pre .doctype, +.swagger-section pre .deletion, +.swagger-section pre .envvar, +.swagger-section pre .shebang, +.swagger-section pre .apache .sqbracket, +.swagger-section pre .nginx .built_in, +.swagger-section pre .tex .formula, +.swagger-section pre .erlang_repl .reserved, +.swagger-section pre .prompt, +.swagger-section pre .markdown .link_label, +.swagger-section pre .vhdl .attribute, +.swagger-section pre .clojure .attribute, +.swagger-section pre .coffeescript .property { + color: #8888ff; +} +.swagger-section pre .keyword, +.swagger-section pre .id, +.swagger-section pre .phpdoc, +.swagger-section pre .title, +.swagger-section pre .built_in, +.swagger-section pre .aggregate, +.swagger-section pre .css .tag, +.swagger-section pre .javadoctag, +.swagger-section pre .phpdoc, +.swagger-section pre .yardoctag, +.swagger-section pre .smalltalk .class, +.swagger-section pre .winutils, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .go .typename, +.swagger-section pre .tex .command, +.swagger-section pre .markdown .strong, +.swagger-section pre .request, +.swagger-section pre .status { + font-weight: bold; +} +.swagger-section pre .markdown .emphasis { + font-style: italic; +} +.swagger-section pre .nginx .built_in { + font-weight: normal; +} +.swagger-section pre .coffeescript .javascript, +.swagger-section pre .javascript .xml, +.swagger-section pre .tex .formula, +.swagger-section pre .xml .javascript, +.swagger-section pre .xml .vbscript, +.swagger-section pre .xml .css, +.swagger-section pre .xml .cdata { + opacity: 0.5; +} +.swagger-section .swagger-ui-wrap { + line-height: 1; + font-family: "Droid Sans", sans-serif; + max-width: 960px; + margin-left: auto; + margin-right: auto; + /* JSONEditor specific styling */ +} +.swagger-section .swagger-ui-wrap b, +.swagger-section .swagger-ui-wrap strong { + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap q, +.swagger-section .swagger-ui-wrap blockquote { + quotes: none; +} +.swagger-section .swagger-ui-wrap p { + line-height: 1.4em; + padding: 0 0 10px; + color: #333333; +} +.swagger-section .swagger-ui-wrap q:before, +.swagger-section .swagger-ui-wrap q:after, +.swagger-section .swagger-ui-wrap blockquote:before, +.swagger-section .swagger-ui-wrap blockquote:after { + content: none; +} +.swagger-section .swagger-ui-wrap .heading_with_menu h1, +.swagger-section .swagger-ui-wrap .heading_with_menu h2, +.swagger-section .swagger-ui-wrap .heading_with_menu h3, +.swagger-section .swagger-ui-wrap .heading_with_menu h4, +.swagger-section .swagger-ui-wrap .heading_with_menu h5, +.swagger-section .swagger-ui-wrap .heading_with_menu h6 { + display: block; + clear: none; + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 60%; +} +.swagger-section .swagger-ui-wrap table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-section .swagger-ui-wrap table thead tr th { + padding: 5px; + font-size: 0.9em; + color: #666666; + border-bottom: 1px solid #999999; +} +.swagger-section .swagger-ui-wrap table tbody tr:last-child td { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap table tbody tr.offset { + background-color: #f0f0f0; +} +.swagger-section .swagger-ui-wrap table tbody tr td { + padding: 6px; + font-size: 0.9em; + border-bottom: 1px solid #cccccc; + vertical-align: top; + line-height: 1.3em; +} +.swagger-section .swagger-ui-wrap ol { + margin: 0px 0 10px; + padding: 0 0 0 18px; + list-style-type: decimal; +} +.swagger-section .swagger-ui-wrap ol li { + padding: 5px 0px; + font-size: 0.9em; + color: #333333; +} +.swagger-section .swagger-ui-wrap ol, +.swagger-section .swagger-ui-wrap ul { + list-style: none; +} +.swagger-section .swagger-ui-wrap h1 a, +.swagger-section .swagger-ui-wrap h2 a, +.swagger-section .swagger-ui-wrap h3 a, +.swagger-section .swagger-ui-wrap h4 a, +.swagger-section .swagger-ui-wrap h5 a, +.swagger-section .swagger-ui-wrap h6 a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap h1 a:hover, +.swagger-section .swagger-ui-wrap h2 a:hover, +.swagger-section .swagger-ui-wrap h3 a:hover, +.swagger-section .swagger-ui-wrap h4 a:hover, +.swagger-section .swagger-ui-wrap h5 a:hover, +.swagger-section .swagger-ui-wrap h6 a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap h1 span.divider, +.swagger-section .swagger-ui-wrap h2 span.divider, +.swagger-section .swagger-ui-wrap h3 span.divider, +.swagger-section .swagger-ui-wrap h4 span.divider, +.swagger-section .swagger-ui-wrap h5 span.divider, +.swagger-section .swagger-ui-wrap h6 span.divider { + color: #aaaaaa; +} +.swagger-section .swagger-ui-wrap a { + color: #547f00; +} +.swagger-section .swagger-ui-wrap a img { + border: none; +} +.swagger-section .swagger-ui-wrap article, +.swagger-section .swagger-ui-wrap aside, +.swagger-section .swagger-ui-wrap details, +.swagger-section .swagger-ui-wrap figcaption, +.swagger-section .swagger-ui-wrap figure, +.swagger-section .swagger-ui-wrap footer, +.swagger-section .swagger-ui-wrap header, +.swagger-section .swagger-ui-wrap hgroup, +.swagger-section .swagger-ui-wrap menu, +.swagger-section .swagger-ui-wrap nav, +.swagger-section .swagger-ui-wrap section, +.swagger-section .swagger-ui-wrap summary { + display: block; +} +.swagger-section .swagger-ui-wrap pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; +} +.swagger-section .swagger-ui-wrap pre code { + line-height: 1.6em; + background: none; +} +.swagger-section .swagger-ui-wrap .content > .content-type > div > label { + clear: both; + display: block; + color: #0F6AB4; + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap .content pre { + font-size: 12px; + margin-top: 5px; + padding: 5px; +} +.swagger-section .swagger-ui-wrap .icon-btn { + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .info_title { + padding-bottom: 10px; + font-weight: bold; + font-size: 25px; +} +.swagger-section .swagger-ui-wrap .footer { + margin-top: 20px; +} +.swagger-section .swagger-ui-wrap p.big, +.swagger-section .swagger-ui-wrap div.big p { + font-size: 1em; + margin-bottom: 10px; +} +.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input { + width: 500px !important; +} +.swagger-section .swagger-ui-wrap .info_license { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_tos { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .message-fail { + color: #cc0000; +} +.swagger-section .swagger-ui-wrap .info_url { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_email { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_name { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_description { + padding-bottom: 10px; + font-size: 15px; +} +.swagger-section .swagger-ui-wrap .markdown ol li, +.swagger-section .swagger-ui-wrap .markdown ul li { + padding: 3px 0px; + line-height: 1.4em; + color: #333333; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input { + display: block; + padding: 4px; + width: auto; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title { + font-size: 1.3em; +} +.swagger-section .swagger-ui-wrap table.fullwidth { + width: 100%; +} +.swagger-section .swagger-ui-wrap .model-signature { + font-family: "Droid Sans", sans-serif; + font-size: 1em; + line-height: 1.5em; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap .model-signature .propType { + color: #5555aa; +} +.swagger-section .swagger-ui-wrap .model-signature pre:hover { + background-color: #ffffdd; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav { + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li { + float: left; + margin: 0 5px 5px 0; + padding: 2px 5px 2px 0; + border-right: 1px solid #ddd; +} +.swagger-section .swagger-ui-wrap .model-signature .propOpt { + color: #555; +} +.swagger-section .swagger-ui-wrap .model-signature .snippet small { + font-size: 0.75em; +} +.swagger-section .swagger-ui-wrap .model-signature .propOptKey { + font-style: italic; +} +.swagger-section .swagger-ui-wrap .model-signature .description .strong { + font-weight: bold; + color: #000; + font-size: .9em; +} +.swagger-section .swagger-ui-wrap .model-signature .description div { + font-size: 0.9em; + line-height: 1.5em; + margin-left: 1em; +} +.swagger-section .swagger-ui-wrap .model-signature .description .stronger { + font-weight: bold; + color: #000; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper { + border-spacing: 0; + position: absolute; + background-color: #ffffff; + border: 1px solid #bbbbbb; + display: none; + font-size: 11px; + max-width: 400px; + line-height: 30px; + color: black; + padding: 5px; + margin-left: 10px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th { + text-align: center; + background-color: #eeeeee; + border: 1px solid #bbbbbb; + font-size: 11px; + color: #666666; + font-weight: bold; + padding: 5px; + line-height: 15px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:first-child, +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:last-child { + display: inline; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:not(:first-child):before { + display: block; + content: ''; +} +.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown > p:only-child { + margin-right: -3px; +} +.swagger-section .swagger-ui-wrap .model-signature .propName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-container { + clear: both; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 300px; + height: 100px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap .markdown p code, +.swagger-section .swagger-ui-wrap .markdown li code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #f0f0f0; + color: black; + padding: 1px 3px; +} +.swagger-section .swagger-ui-wrap .required { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .editor_holder { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap .editor_holder label { + font-weight: normal!important; + /* JSONEditor uses bold by default for all labels, we revert that back to normal to not give the impression that by default fields are required */ +} +.swagger-section .swagger-ui-wrap .editor_holder label.required { + font-weight: bold!important; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 300px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap h1 { + color: black; + font-size: 1.5em; + line-height: 1.3em; + padding: 10px 0 10px 0; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .heading_with_menu { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap .heading_with_menu ul { + display: block; + clear: none; + float: right; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + margin-top: 10px; +} +.swagger-section .swagger-ui-wrap h2 { + color: black; + font-size: 1.3em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap h2 span.sub { + font-size: 0.7em; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap h2 span.sub a { + color: #777777; +} +.swagger-section .swagger-ui-wrap span.weak { + color: #666666; +} +.swagger-section .swagger-ui-wrap .message-success { + color: #89BF04; +} +.swagger-section .swagger-ui-wrap caption, +.swagger-section .swagger-ui-wrap th, +.swagger-section .swagger-ui-wrap td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +.swagger-section .swagger-ui-wrap .code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea { + font-family: "Droid Sans", sans-serif; + height: 250px; + padding: 4px; + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select { + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label { + display: block; + float: left; + clear: none; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input { + display: block; + float: left; + clear: none; + margin: 0 5px 0 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label { + color: black; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label { + display: block; + clear: both; + width: auto; + padding: 0 0 3px; + color: #666666; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr { + padding-left: 3px; + color: #888888; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints { + margin-left: 0; + font-style: italic; + font-size: 0.9em; + margin: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap span.blank, +.swagger-section .swagger-ui-wrap span.empty { + color: #888888; + font-style: italic; +} +.swagger-section .swagger-ui-wrap .markdown h3 { + color: #547f00; +} +.swagger-section .swagger-ui-wrap .markdown h4 { + color: #666666; +} +.swagger-section .swagger-ui-wrap .markdown pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; + margin: 0 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown pre code { + line-height: 1.6em; +} +.swagger-section .swagger-ui-wrap div.gist { + margin: 20px 0 25px 0 !important; +} +.swagger-section .swagger-ui-wrap ul#resources { + font-family: "Droid Sans", sans-serif; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource { + border-bottom: 1px solid #dddddd; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a { + color: #555555; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading { + border: 1px solid transparent; + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 14px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; + color: #666666; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a { + color: #aaaaaa; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #999999; + padding-left: 0; + display: block; + clear: none; + float: left; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #999999; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0 0 10px; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 { + display: block; + clear: none; + float: left; + width: auto; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path { + padding-left: 10px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a { + text-transform: uppercase; + text-decoration: none; + color: white; + display: inline-block; + width: 50px; + font-size: 0.7em; + text-align: center; + padding: 7px 0 4px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 6px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + border-top: none; + padding: 10px; + -moz-border-radius-bottomleft: 6px; + -webkit-border-bottom-left-radius: 6px; + -o-border-bottom-left-radius: 6px; + -ms-border-bottom-left-radius: 6px; + -khtml-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -webkit-border-bottom-right-radius: 6px; + -o-border-bottom-right-radius: 6px; + -ms-border-bottom-right-radius: 6px; + -khtml-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + margin: 0 0 20px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4 { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a { + padding: 4px 0 0 10px; + display: inline-block; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit { + display: block; + clear: none; + float: left; + padding: 6px 8px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber { + background-image: url('../images/throbber.gif'); + width: 128px; + height: 16px; + display: block; + clear: none; + float: right; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error { + outline: 2px solid black; + outline-color: #cc0000; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name='parameterContentType'] { + max-width: 300px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + padding: 10px; + font-size: 0.9em; + max-height: 400px; + overflow-y: auto; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading { + background-color: #f9f2e9; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a { + background-color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0e0ca; + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content { + background-color: #faf5ee; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #ffd20f; + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4 { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading { + background-color: #f5e8e8; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #e8c6c7; + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + background-color: #f7eded; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a { + color: #c8787a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading { + background-color: #e7f6ec; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a { + background-color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3e8d1; + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content { + background-color: #ebf7f0; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading { + background-color: #FCE9E3; + border: 1px solid #F5D5C3; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a { + background-color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0cecb; + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content { + background-color: #faf0ef; + border: 1px solid #f0cecb; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4 { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + border-top: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap p#colophon { + margin: 0 15px 40px 15px; + padding: 10px 0; + font-size: 0.8em; + border-top: 1px solid #dddddd; + font-family: "Droid Sans", sans-serif; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap p#colophon a { + text-decoration: none; + color: #547f00; +} +.swagger-section .swagger-ui-wrap h3 { + color: black; + font-size: 1.1em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown ol, +.swagger-section .swagger-ui-wrap .markdown ul { + font-family: "Droid Sans", sans-serif; + margin: 5px 0 10px; + padding: 0 0 0 18px; + list-style-type: disc; +} +.swagger-section .swagger-ui-wrap form.form_box { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box label { + color: #0f6ab4 !important; +} +.swagger-section .swagger-ui-wrap form.form_box input[type=submit] { + display: block; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box p.weak { + font-size: 0.8em; +} +.swagger-section .swagger-ui-wrap form.form_box p { + font-size: 0.9em; + padding: 0 0 15px; + color: #7e7b6d; +} +.swagger-section .swagger-ui-wrap form.form_box p a { + color: #646257; +} +.swagger-section .swagger-ui-wrap form.form_box p strong { + color: black; +} +.swagger-section .swagger-ui-wrap .operation-status td.markdown > p:last-child { + padding-bottom: 0; +} +.swagger-section .title { + font-style: bold; +} +.swagger-section .secondary_form { + display: none; +} +.swagger-section .main_image { + display: block; + margin-left: auto; + margin-right: auto; +} +.swagger-section .oauth_body { + margin-left: 100px; + margin-right: 100px; +} +.swagger-section .oauth_submit { + text-align: center; +} +.swagger-section .api-popup-dialog { + z-index: 10000; + position: absolute; + width: 500px; + background: #FFF; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + color: #777; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .error-msg { + padding-left: 5px; + padding-bottom: 5px; +} +.swagger-section .api-popup-dialog .api-popup-authbtn { + height: 30px; +} +.swagger-section .api-popup-dialog .api-popup-cancel { + height: 30px; +} +.swagger-section .api-popup-scopes { + padding: 10px 20px; +} +.swagger-section .api-popup-scopes li { + padding: 5px 0; + line-height: 20px; +} +.swagger-section .api-popup-scopes li input { + position: relative; + top: 2px; +} +.swagger-section .api-popup-scopes .api-scope-desc { + padding-left: 20px; + font-style: italic; +} +.swagger-section .api-popup-actions { + padding-top: 10px; +} +#header { + display: none; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + max-height: none; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 100px; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 100px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + display: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints { + display: block !important; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + display: block !important; +} diff --git a/PlexRequests.UI/Content/swagger/reset.css b/PlexRequests.UI/Content/swagger/reset.css new file mode 100644 index 000000000..b2b078943 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/reset.css @@ -0,0 +1,125 @@ +/* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} +body { + line-height: 1; +} +ol, +ul { + list-style: none; +} +blockquote, +q { + quotes: none; +} +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/PlexRequests.UI/Content/swagger/screen.css b/PlexRequests.UI/Content/swagger/screen.css new file mode 100644 index 000000000..ef4673db9 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/screen.css @@ -0,0 +1,1300 @@ +/* Original style from softwaremaniacs.org (c) Ivan Sagalaev */ +.swagger-section pre code { + display: block; + padding: 0.5em; + background: #F0F0F0; +} +.swagger-section pre code, +.swagger-section pre .subst, +.swagger-section pre .tag .title, +.swagger-section pre .lisp .title, +.swagger-section pre .clojure .built_in, +.swagger-section pre .nginx .title { + color: black; +} +.swagger-section pre .string, +.swagger-section pre .title, +.swagger-section pre .constant, +.swagger-section pre .parent, +.swagger-section pre .tag .value, +.swagger-section pre .rules .value, +.swagger-section pre .rules .value .number, +.swagger-section pre .preprocessor, +.swagger-section pre .ruby .symbol, +.swagger-section pre .ruby .symbol .string, +.swagger-section pre .aggregate, +.swagger-section pre .template_tag, +.swagger-section pre .django .variable, +.swagger-section pre .smalltalk .class, +.swagger-section pre .addition, +.swagger-section pre .flow, +.swagger-section pre .stream, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .apache .cbracket, +.swagger-section pre .tex .command, +.swagger-section pre .tex .special, +.swagger-section pre .erlang_repl .function_or_atom, +.swagger-section pre .markdown .header { + color: #800; +} +.swagger-section pre .comment, +.swagger-section pre .annotation, +.swagger-section pre .template_comment, +.swagger-section pre .diff .header, +.swagger-section pre .chunk, +.swagger-section pre .markdown .blockquote { + color: #888; +} +.swagger-section pre .number, +.swagger-section pre .date, +.swagger-section pre .regexp, +.swagger-section pre .literal, +.swagger-section pre .smalltalk .symbol, +.swagger-section pre .smalltalk .char, +.swagger-section pre .go .constant, +.swagger-section pre .change, +.swagger-section pre .markdown .bullet, +.swagger-section pre .markdown .link_url { + color: #080; +} +.swagger-section pre .label, +.swagger-section pre .javadoc, +.swagger-section pre .ruby .string, +.swagger-section pre .decorator, +.swagger-section pre .filter .argument, +.swagger-section pre .localvars, +.swagger-section pre .array, +.swagger-section pre .attr_selector, +.swagger-section pre .important, +.swagger-section pre .pseudo, +.swagger-section pre .pi, +.swagger-section pre .doctype, +.swagger-section pre .deletion, +.swagger-section pre .envvar, +.swagger-section pre .shebang, +.swagger-section pre .apache .sqbracket, +.swagger-section pre .nginx .built_in, +.swagger-section pre .tex .formula, +.swagger-section pre .erlang_repl .reserved, +.swagger-section pre .prompt, +.swagger-section pre .markdown .link_label, +.swagger-section pre .vhdl .attribute, +.swagger-section pre .clojure .attribute, +.swagger-section pre .coffeescript .property { + color: #8888ff; +} +.swagger-section pre .keyword, +.swagger-section pre .id, +.swagger-section pre .phpdoc, +.swagger-section pre .title, +.swagger-section pre .built_in, +.swagger-section pre .aggregate, +.swagger-section pre .css .tag, +.swagger-section pre .javadoctag, +.swagger-section pre .phpdoc, +.swagger-section pre .yardoctag, +.swagger-section pre .smalltalk .class, +.swagger-section pre .winutils, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .go .typename, +.swagger-section pre .tex .command, +.swagger-section pre .markdown .strong, +.swagger-section pre .request, +.swagger-section pre .status { + font-weight: bold; +} +.swagger-section pre .markdown .emphasis { + font-style: italic; +} +.swagger-section pre .nginx .built_in { + font-weight: normal; +} +.swagger-section pre .coffeescript .javascript, +.swagger-section pre .javascript .xml, +.swagger-section pre .tex .formula, +.swagger-section pre .xml .javascript, +.swagger-section pre .xml .vbscript, +.swagger-section pre .xml .css, +.swagger-section pre .xml .cdata { + opacity: 0.5; +} +.swagger-section .swagger-ui-wrap { + line-height: 1; + font-family: "Droid Sans", sans-serif; + max-width: 960px; + margin-left: auto; + margin-right: auto; + /* JSONEditor specific styling */ +} +.swagger-section .swagger-ui-wrap b, +.swagger-section .swagger-ui-wrap strong { + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap q, +.swagger-section .swagger-ui-wrap blockquote { + quotes: none; +} +.swagger-section .swagger-ui-wrap p { + line-height: 1.4em; + padding: 0 0 10px; + color: #333333; +} +.swagger-section .swagger-ui-wrap q:before, +.swagger-section .swagger-ui-wrap q:after, +.swagger-section .swagger-ui-wrap blockquote:before, +.swagger-section .swagger-ui-wrap blockquote:after { + content: none; +} +.swagger-section .swagger-ui-wrap .heading_with_menu h1, +.swagger-section .swagger-ui-wrap .heading_with_menu h2, +.swagger-section .swagger-ui-wrap .heading_with_menu h3, +.swagger-section .swagger-ui-wrap .heading_with_menu h4, +.swagger-section .swagger-ui-wrap .heading_with_menu h5, +.swagger-section .swagger-ui-wrap .heading_with_menu h6 { + display: block; + clear: none; + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 60%; +} +.swagger-section .swagger-ui-wrap table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-section .swagger-ui-wrap table thead tr th { + padding: 5px; + font-size: 0.9em; + color: #666666; + border-bottom: 1px solid #999999; +} +.swagger-section .swagger-ui-wrap table tbody tr:last-child td { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap table tbody tr.offset { + background-color: #f0f0f0; +} +.swagger-section .swagger-ui-wrap table tbody tr td { + padding: 6px; + font-size: 0.9em; + border-bottom: 1px solid #cccccc; + vertical-align: top; + line-height: 1.3em; +} +.swagger-section .swagger-ui-wrap ol { + margin: 0px 0 10px; + padding: 0 0 0 18px; + list-style-type: decimal; +} +.swagger-section .swagger-ui-wrap ol li { + padding: 5px 0px; + font-size: 0.9em; + color: #333333; +} +.swagger-section .swagger-ui-wrap ol, +.swagger-section .swagger-ui-wrap ul { + list-style: none; +} +.swagger-section .swagger-ui-wrap h1 a, +.swagger-section .swagger-ui-wrap h2 a, +.swagger-section .swagger-ui-wrap h3 a, +.swagger-section .swagger-ui-wrap h4 a, +.swagger-section .swagger-ui-wrap h5 a, +.swagger-section .swagger-ui-wrap h6 a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap h1 a:hover, +.swagger-section .swagger-ui-wrap h2 a:hover, +.swagger-section .swagger-ui-wrap h3 a:hover, +.swagger-section .swagger-ui-wrap h4 a:hover, +.swagger-section .swagger-ui-wrap h5 a:hover, +.swagger-section .swagger-ui-wrap h6 a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap h1 span.divider, +.swagger-section .swagger-ui-wrap h2 span.divider, +.swagger-section .swagger-ui-wrap h3 span.divider, +.swagger-section .swagger-ui-wrap h4 span.divider, +.swagger-section .swagger-ui-wrap h5 span.divider, +.swagger-section .swagger-ui-wrap h6 span.divider { + color: #aaaaaa; +} +.swagger-section .swagger-ui-wrap a { + color: #547f00; +} +.swagger-section .swagger-ui-wrap a img { + border: none; +} +.swagger-section .swagger-ui-wrap article, +.swagger-section .swagger-ui-wrap aside, +.swagger-section .swagger-ui-wrap details, +.swagger-section .swagger-ui-wrap figcaption, +.swagger-section .swagger-ui-wrap figure, +.swagger-section .swagger-ui-wrap footer, +.swagger-section .swagger-ui-wrap header, +.swagger-section .swagger-ui-wrap hgroup, +.swagger-section .swagger-ui-wrap menu, +.swagger-section .swagger-ui-wrap nav, +.swagger-section .swagger-ui-wrap section, +.swagger-section .swagger-ui-wrap summary { + display: block; +} +.swagger-section .swagger-ui-wrap pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; +} +.swagger-section .swagger-ui-wrap pre code { + line-height: 1.6em; + background: none; +} +.swagger-section .swagger-ui-wrap .content > .content-type > div > label { + clear: both; + display: block; + color: #0F6AB4; + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap .content pre { + font-size: 12px; + margin-top: 5px; + padding: 5px; +} +.swagger-section .swagger-ui-wrap .icon-btn { + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .info_title { + padding-bottom: 10px; + font-weight: bold; + font-size: 25px; +} +.swagger-section .swagger-ui-wrap .footer { + margin-top: 20px; +} +.swagger-section .swagger-ui-wrap p.big, +.swagger-section .swagger-ui-wrap div.big p { + font-size: 1em; + margin-bottom: 10px; +} +.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input { + width: 500px !important; +} +.swagger-section .swagger-ui-wrap .info_license { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_tos { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .message-fail { + color: #cc0000; +} +.swagger-section .swagger-ui-wrap .info_url { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_email { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_name { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_description { + padding-bottom: 10px; + font-size: 15px; +} +.swagger-section .swagger-ui-wrap .markdown ol li, +.swagger-section .swagger-ui-wrap .markdown ul li { + padding: 3px 0px; + line-height: 1.4em; + color: #333333; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input { + display: block; + padding: 4px; + width: auto; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title { + font-size: 1.3em; +} +.swagger-section .swagger-ui-wrap table.fullwidth { + width: 100%; +} +.swagger-section .swagger-ui-wrap .model-signature { + font-family: "Droid Sans", sans-serif; + font-size: 1em; + line-height: 1.5em; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap .model-signature .propType { + color: #5555aa; +} +.swagger-section .swagger-ui-wrap .model-signature pre:hover { + background-color: #ffffdd; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav { + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li { + float: left; + margin: 0 5px 5px 0; + padding: 2px 5px 2px 0; + border-right: 1px solid #ddd; +} +.swagger-section .swagger-ui-wrap .model-signature .propOpt { + color: #555; +} +.swagger-section .swagger-ui-wrap .model-signature .snippet small { + font-size: 0.75em; +} +.swagger-section .swagger-ui-wrap .model-signature .propOptKey { + font-style: italic; +} +.swagger-section .swagger-ui-wrap .model-signature .description .strong { + font-weight: bold; + color: #000; + font-size: .9em; +} +.swagger-section .swagger-ui-wrap .model-signature .description div { + font-size: 0.9em; + line-height: 1.5em; + margin-left: 1em; +} +.swagger-section .swagger-ui-wrap .model-signature .description .stronger { + font-weight: bold; + color: #000; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper { + border-spacing: 0; + position: absolute; + background-color: #ffffff; + border: 1px solid #bbbbbb; + display: none; + font-size: 11px; + max-width: 400px; + line-height: 30px; + color: black; + padding: 5px; + margin-left: 10px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th { + text-align: center; + background-color: #eeeeee; + border: 1px solid #bbbbbb; + font-size: 11px; + color: #666666; + font-weight: bold; + padding: 5px; + line-height: 15px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:first-child, +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:last-child { + display: inline; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:not(:first-child):before { + display: block; + content: ''; +} +.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown > p:only-child { + margin-right: -3px; +} +.swagger-section .swagger-ui-wrap .model-signature .propName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-container { + clear: both; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 300px; + height: 100px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap .markdown p code, +.swagger-section .swagger-ui-wrap .markdown li code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #f0f0f0; + color: black; + padding: 1px 3px; +} +.swagger-section .swagger-ui-wrap .required { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .editor_holder { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap .editor_holder label { + font-weight: normal!important; + /* JSONEditor uses bold by default for all labels, we revert that back to normal to not give the impression that by default fields are required */ +} +.swagger-section .swagger-ui-wrap .editor_holder label.required { + font-weight: bold!important; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 300px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap h1 { + color: black; + font-size: 1.5em; + line-height: 1.3em; + padding: 10px 0 10px 0; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .heading_with_menu { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap .heading_with_menu ul { + display: block; + clear: none; + float: right; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + margin-top: 10px; +} +.swagger-section .swagger-ui-wrap h2 { + color: black; + font-size: 1.3em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap h2 span.sub { + font-size: 0.7em; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap h2 span.sub a { + color: #777777; +} +.swagger-section .swagger-ui-wrap span.weak { + color: #666666; +} +.swagger-section .swagger-ui-wrap .message-success { + color: #89BF04; +} +.swagger-section .swagger-ui-wrap caption, +.swagger-section .swagger-ui-wrap th, +.swagger-section .swagger-ui-wrap td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +.swagger-section .swagger-ui-wrap .code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea { + font-family: "Droid Sans", sans-serif; + height: 250px; + padding: 4px; + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select { + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label { + display: block; + float: left; + clear: none; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input { + display: block; + float: left; + clear: none; + margin: 0 5px 0 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label { + color: black; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label { + display: block; + clear: both; + width: auto; + padding: 0 0 3px; + color: #666666; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr { + padding-left: 3px; + color: #888888; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints { + margin-left: 0; + font-style: italic; + font-size: 0.9em; + margin: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap span.blank, +.swagger-section .swagger-ui-wrap span.empty { + color: #888888; + font-style: italic; +} +.swagger-section .swagger-ui-wrap .markdown h3 { + color: #547f00; +} +.swagger-section .swagger-ui-wrap .markdown h4 { + color: #666666; +} +.swagger-section .swagger-ui-wrap .markdown pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; + margin: 0 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown pre code { + line-height: 1.6em; +} +.swagger-section .swagger-ui-wrap div.gist { + margin: 20px 0 25px 0 !important; +} +.swagger-section .swagger-ui-wrap ul#resources { + font-family: "Droid Sans", sans-serif; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource { + border-bottom: 1px solid #dddddd; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a { + color: #555555; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading { + border: 1px solid transparent; + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 14px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; + color: #666666; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a { + color: #aaaaaa; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #999999; + padding-left: 0; + display: block; + clear: none; + float: left; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #999999; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0 0 10px; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 { + display: block; + clear: none; + float: left; + width: auto; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path { + padding-left: 10px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a { + text-transform: uppercase; + text-decoration: none; + color: white; + display: inline-block; + width: 50px; + font-size: 0.7em; + text-align: center; + padding: 7px 0 4px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 6px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + border-top: none; + padding: 10px; + -moz-border-radius-bottomleft: 6px; + -webkit-border-bottom-left-radius: 6px; + -o-border-bottom-left-radius: 6px; + -ms-border-bottom-left-radius: 6px; + -khtml-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -webkit-border-bottom-right-radius: 6px; + -o-border-bottom-right-radius: 6px; + -ms-border-bottom-right-radius: 6px; + -khtml-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + margin: 0 0 20px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4 { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a { + padding: 4px 0 0 10px; + display: inline-block; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit { + display: block; + clear: none; + float: left; + padding: 6px 8px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber { + background-image: url('../images/throbber.gif'); + width: 128px; + height: 16px; + display: block; + clear: none; + float: right; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error { + outline: 2px solid black; + outline-color: #cc0000; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name='parameterContentType'] { + max-width: 300px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + padding: 10px; + font-size: 0.9em; + max-height: 400px; + overflow-y: auto; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading { + background-color: #f9f2e9; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a { + background-color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0e0ca; + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content { + background-color: #faf5ee; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #ffd20f; + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4 { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading { + background-color: #f5e8e8; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #e8c6c7; + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + background-color: #f7eded; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a { + color: #c8787a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading { + background-color: #e7f6ec; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a { + background-color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3e8d1; + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content { + background-color: #ebf7f0; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading { + background-color: #FCE9E3; + border: 1px solid #F5D5C3; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a { + background-color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0cecb; + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content { + background-color: #faf0ef; + border: 1px solid #f0cecb; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4 { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + border-top: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap p#colophon { + margin: 0 15px 40px 15px; + padding: 10px 0; + font-size: 0.8em; + border-top: 1px solid #dddddd; + font-family: "Droid Sans", sans-serif; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap p#colophon a { + text-decoration: none; + color: #547f00; +} +.swagger-section .swagger-ui-wrap h3 { + color: black; + font-size: 1.1em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown ol, +.swagger-section .swagger-ui-wrap .markdown ul { + font-family: "Droid Sans", sans-serif; + margin: 5px 0 10px; + padding: 0 0 0 18px; + list-style-type: disc; +} +.swagger-section .swagger-ui-wrap form.form_box { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box label { + color: #0f6ab4 !important; +} +.swagger-section .swagger-ui-wrap form.form_box input[type=submit] { + display: block; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box p.weak { + font-size: 0.8em; +} +.swagger-section .swagger-ui-wrap form.form_box p { + font-size: 0.9em; + padding: 0 0 15px; + color: #7e7b6d; +} +.swagger-section .swagger-ui-wrap form.form_box p a { + color: #646257; +} +.swagger-section .swagger-ui-wrap form.form_box p strong { + color: black; +} +.swagger-section .swagger-ui-wrap .operation-status td.markdown > p:last-child { + padding-bottom: 0; +} +.swagger-section .title { + font-style: bold; +} +.swagger-section .secondary_form { + display: none; +} +.swagger-section .main_image { + display: block; + margin-left: auto; + margin-right: auto; +} +.swagger-section .oauth_body { + margin-left: 100px; + margin-right: 100px; +} +.swagger-section .oauth_submit { + text-align: center; +} +.swagger-section .api-popup-dialog { + z-index: 10000; + position: absolute; + width: 500px; + background: #FFF; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + color: #777; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .error-msg { + padding-left: 5px; + padding-bottom: 5px; +} +.swagger-section .api-popup-dialog .api-popup-authbtn { + height: 30px; +} +.swagger-section .api-popup-dialog .api-popup-cancel { + height: 30px; +} +.swagger-section .api-popup-scopes { + padding: 10px 20px; +} +.swagger-section .api-popup-scopes li { + padding: 5px 0; + line-height: 20px; +} +.swagger-section .api-popup-scopes li input { + position: relative; + top: 2px; +} +.swagger-section .api-popup-scopes .api-scope-desc { + padding-left: 20px; + font-style: italic; +} +.swagger-section .api-popup-actions { + padding-top: 10px; +} +.swagger-section .access { + float: right; +} +.swagger-section .auth { + float: right; +} +.swagger-section .api-ic { + height: 18px; + vertical-align: middle; + display: inline-block; + background: url(../images/explorer_icons.png) no-repeat; +} +.swagger-section .api-ic .api_information_panel { + position: relative; + margin-top: 20px; + margin-left: -5px; + background: #FFF; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + max-width: 300px; + line-height: 30px; + color: black; + padding: 5px; +} +.swagger-section .api-ic .api_information_panel p .api-msg-enabled { + color: green; +} +.swagger-section .api-ic .api_information_panel p .api-msg-disabled { + color: red; +} +.swagger-section .api-ic:hover .api_information_panel { + position: absolute; + display: block; +} +.swagger-section .ic-info { + background-position: 0 0; + width: 18px; + margin-top: -6px; + margin-left: 4px; +} +.swagger-section .ic-warning { + background-position: -60px 0; + width: 18px; + margin-top: -6px; + margin-left: 4px; +} +.swagger-section .ic-error { + background-position: -30px 0; + width: 18px; + margin-top: -6px; + margin-left: 4px; +} +.swagger-section .ic-off { + background-position: -90px 0; + width: 58px; + margin-top: -4px; + cursor: pointer; +} +.swagger-section .ic-on { + background-position: -160px 0; + width: 58px; + margin-top: -4px; + cursor: pointer; +} +.swagger-section #header { + background-color: #89bf04; + padding: 14px; +} +.swagger-section #input_baseUrl { + width: 400px; +} +.swagger-section #api_selector { + display: block; + clear: none; + float: right; +} +.swagger-section #api_selector .input { + display: block; + clear: none; + float: left; + margin: 0 10px 0 0; +} +.swagger-section #api_selector input { + font-size: 0.9em; + padding: 3px; + margin: 0; +} +.swagger-section #input_apiKey { + width: 200px; +} +.swagger-section #explore { + display: block; + text-decoration: none; + font-weight: bold; + padding: 6px 8px; + font-size: 0.9em; + color: white; + background-color: #547f00; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -o-border-radius: 4px; + -ms-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} +.swagger-section #explore:hover { + background-color: #547f00; +} +.swagger-section #header #logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo_small.png) no-repeat left center; + padding: 20px 0 20px 40px; + color: white; +} +.swagger-section #content_message { + margin: 10px 15px; + font-style: italic; + color: #999999; +} +.swagger-section #message-bar { + min-height: 30px; + text-align: center; + padding-top: 10px; +} +.swagger-section .swagger-collapse:before { + content: "-"; +} +.swagger-section .swagger-expand:before { + content: "+"; +} diff --git a/PlexRequests.UI/Content/swagger/style.css b/PlexRequests.UI/Content/swagger/style.css new file mode 100644 index 000000000..fc21a31db --- /dev/null +++ b/PlexRequests.UI/Content/swagger/style.css @@ -0,0 +1,250 @@ +.swagger-section #header a#logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo.png) no-repeat left center; + padding: 20px 0 20px 40px; +} +#text-head { + font-size: 80px; + font-family: 'Roboto', sans-serif; + color: #ffffff; + float: right; + margin-right: 20%; +} +.navbar-fixed-top .navbar-nav { + height: auto; +} +.navbar-fixed-top .navbar-brand { + height: auto; +} +.navbar-header { + height: auto; +} +.navbar-inverse { + background-color: #000; + border-color: #000; +} +#navbar-brand { + margin-left: 20%; +} +.navtext { + font-size: 10px; +} +.h1, +h1 { + font-size: 60px; +} +.navbar-default .navbar-header .navbar-brand { + color: #a2dfee; +} +/* tag titles */ +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #393939; + font-family: 'Arvo', serif; + font-size: 1.5em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #525252; + padding-left: 0px; + display: block; + clear: none; + float: left; + font-family: 'Arvo', serif; + font-weight: bold; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #0A0A0A; +} +.container1 { + width: 1500px; + margin: auto; + margin-top: 0; + background-image: url('../images/shield.png'); + background-repeat: no-repeat; + background-position: -40px -20px; + margin-bottom: 210px; +} +.container-inner { + width: 1200px; + margin: auto; + background-color: rgba(223, 227, 228, 0.75); + padding-bottom: 40px; + padding-top: 40px; + border-radius: 15px; +} +.header-content { + padding: 0; + width: 1000px; +} +.title1 { + font-size: 80px; + font-family: 'Vollkorn', serif; + color: #404040; + text-align: center; + padding-top: 40px; + padding-bottom: 100px; +} +#icon { + margin-top: -18px; +} +.subtext { + font-size: 25px; + font-style: italic; + color: #08b; + text-align: right; + padding-right: 250px; +} +.bg-primary { + background-color: #00468b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:focus { + color: #08b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:hover { + color: #08b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:focus:hover { + color: #08b; +} +.text-faded { + font-size: 25px; + font-family: 'Vollkorn', serif; +} +.section-heading { + font-family: 'Vollkorn', serif; + font-size: 45px; + padding-bottom: 10px; +} +hr { + border-color: #00468b; + padding-bottom: 10px; +} +.description { + margin-top: 20px; + padding-bottom: 200px; +} +.description li { + font-family: 'Vollkorn', serif; + font-size: 25px; + color: #525252; + margin-left: 28%; + padding-top: 5px; +} +.gap { + margin-top: 200px; +} +.troubleshootingtext { + color: rgba(255, 255, 255, 0.7); + padding-left: 30%; +} +.troubleshootingtext li { + list-style-type: circle; + font-size: 25px; + padding-bottom: 5px; +} +.overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; +} +.block.response_body.json:hover { + cursor: pointer; +} +.backdrop { + color: blue; +} +#myModal { + height: 100%; +} +.modal-backdrop { + bottom: 0; + position: fixed; +} +.curl { + padding: 10px; + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; + max-height: 400px; + margin-top: 5px; + overflow-y: auto; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + border-radius: 4px; +} +.curl_title { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; + font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; + font-weight: 500; + line-height: 1.1; +} +.footer { + display: none; +} +.swagger-section .swagger-ui-wrap h2 { + padding: 0; +} +h2 { + margin: 0; + margin-bottom: 5px; +} +.markdown p { + font-size: 15px; + font-family: 'Arvo', serif; +} +.swagger-section .swagger-ui-wrap .code { + font-size: 15px; + font-family: 'Arvo', serif; +} +.swagger-section .swagger-ui-wrap b { + font-family: 'Arvo', serif; +} +#signin:hover { + cursor: pointer; +} +.dropdown-menu { + padding: 15px; +} +.navbar-right .dropdown-menu { + left: 0; + right: auto; +} +#signinbutton { + width: 100%; + height: 32px; + font-size: 13px; + font-weight: bold; + color: #08b; +} +.navbar-default .nav > li .details { + color: #000000; + text-transform: none; + font-size: 15px; + font-weight: normal; + font-family: 'Open Sans', sans-serif; + font-style: italic; + line-height: 20px; + top: -2px; +} +.navbar-default .nav > li .details:hover { + color: black; +} +#signout { + width: 100%; + height: 32px; + font-size: 13px; + font-weight: bold; + color: #08b; +} diff --git a/PlexRequests.UI/Content/swagger/swagger-oauth.js b/PlexRequests.UI/Content/swagger/swagger-oauth.js new file mode 100644 index 000000000..576fcd33b --- /dev/null +++ b/PlexRequests.UI/Content/swagger/swagger-oauth.js @@ -0,0 +1,338 @@ +var appName; +var popupMask; +var popupDialog; +var clientId; +var realm; +var redirect_uri; +var clientSecret; +var scopeSeparator; +var additionalQueryStringParams; + +function handleLogin() { + var scopes = []; + + var auths = window.swaggerUi.api.authSchemes || window.swaggerUi.api.securityDefinitions; + if(auths) { + var key; + var defs = auths; + for(key in defs) { + var auth = defs[key]; + if(auth.type === 'oauth2' && auth.scopes) { + var scope; + if(Array.isArray(auth.scopes)) { + // 1.2 support + var i; + for(i = 0; i < auth.scopes.length; i++) { + scopes.push(auth.scopes[i]); + } + } + else { + // 2.0 support + for(scope in auth.scopes) { + scopes.push({scope: scope, description: auth.scopes[scope], OAuthSchemeKey: key}); + } + } + } + } + } + + if(window.swaggerUi.api + && window.swaggerUi.api.info) { + appName = window.swaggerUi.api.info.title; + } + + $('.api-popup-dialog').remove(); + popupDialog = $( + [ + '
    ', + '
    Select OAuth2.0 Scopes
    ', + '
    ', + '

    Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.', + 'Learn how to use', + '

    ', + '

    ' + appName + ' API requires the following scopes. Select which ones you want to grant to Swagger UI.

    ', + '
      ', + '
    ', + '

    ', + '
    ', + '
    ', + '
    '].join('')); + $(document.body).append(popupDialog); + + //TODO: only display applicable scopes (will need to pass them into handleLogin) + popup = popupDialog.find('ul.api-popup-scopes').empty(); + for (i = 0; i < scopes.length; i ++) { + scope = scopes[i]; + str = '
  • ' + '
  • '; + popup.append(str); + } + + var $win = $(window), + dw = $win.width(), + dh = $win.height(), + st = $win.scrollTop(), + dlgWd = popupDialog.outerWidth(), + dlgHt = popupDialog.outerHeight(), + top = (dh -dlgHt)/2 + st, + left = (dw - dlgWd)/2; + + popupDialog.css({ + top: (top < 0? 0 : top) + 'px', + left: (left < 0? 0 : left) + 'px' + }); + + popupDialog.find('button.api-popup-cancel').click(function() { + popupMask.hide(); + popupDialog.hide(); + popupDialog.empty(); + popupDialog = []; + }); + + $('button.api-popup-authbtn').unbind(); + popupDialog.find('button.api-popup-authbtn').click(function() { + popupMask.hide(); + popupDialog.hide(); + + var authSchemes = window.swaggerUi.api.authSchemes; + var host = window.location; + var pathname = location.pathname.substring(0, location.pathname.lastIndexOf("/")); + var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html'; + var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl; + var url = null; + var scopes = [] + var o = popup.find('input:checked'); + var OAuthSchemeKeys = []; + var state; + for(k =0; k < o.length; k++) { + var scope = $(o[k]).attr('scope'); + if (scopes.indexOf(scope) === -1) + scopes.push(scope); + var OAuthSchemeKey = $(o[k]).attr('oauthtype'); + if (OAuthSchemeKeys.indexOf(OAuthSchemeKey) === -1) + OAuthSchemeKeys.push(OAuthSchemeKey); + } + + //TODO: merge not replace if scheme is different from any existing + //(needs to be aware of schemes to do so correctly) + window.enabledScopes=scopes; + + for (var key in authSchemes) { + if (authSchemes.hasOwnProperty(key) && OAuthSchemeKeys.indexOf(key) != -1) { //only look at keys that match this scope. + var flow = authSchemes[key].flow; + + if(authSchemes[key].type === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) { + var dets = authSchemes[key]; + url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code'); + window.swaggerUi.tokenName = dets.tokenName || 'access_token'; + window.swaggerUi.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null); + state = key; + } + else if(authSchemes[key].type === 'oauth2' && flow && (flow === 'application')) { + var dets = authSchemes[key]; + window.swaggerUi.tokenName = dets.tokenName || 'access_token'; + clientCredentialsFlow(scopes, dets.tokenUrl, key); + return; + } + else if(authSchemes[key].grantTypes) { + // 1.2 support + var o = authSchemes[key].grantTypes; + for(var t in o) { + if(o.hasOwnProperty(t) && t === 'implicit') { + var dets = o[t]; + var ep = dets.loginEndpoint.url; + url = dets.loginEndpoint.url + '?response_type=token'; + window.swaggerUi.tokenName = dets.tokenName; + } + else if (o.hasOwnProperty(t) && t === 'accessCode') { + var dets = o[t]; + var ep = dets.tokenRequestEndpoint.url; + url = dets.tokenRequestEndpoint.url + '?response_type=code'; + window.swaggerUi.tokenName = dets.tokenName; + } + } + } + } + } + + redirect_uri = redirectUrl; + + url += '&redirect_uri=' + encodeURIComponent(redirectUrl); + url += '&realm=' + encodeURIComponent(realm); + url += '&client_id=' + encodeURIComponent(clientId); + url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator)); + url += '&state=' + encodeURIComponent(state); + for (var key in additionalQueryStringParams) { + url += '&' + key + '=' + encodeURIComponent(additionalQueryStringParams[key]); + } + + window.open(url); + }); + + popupMask.show(); + popupDialog.show(); + return; +} + + +function handleLogout() { + for(key in window.swaggerUi.api.clientAuthorizations.authz){ + window.swaggerUi.api.clientAuthorizations.remove(key) + } + window.enabledScopes = null; + $('.api-ic.ic-on').addClass('ic-off'); + $('.api-ic.ic-on').removeClass('ic-on'); + + // set the info box + $('.api-ic.ic-warning').addClass('ic-error'); + $('.api-ic.ic-warning').removeClass('ic-warning'); +} + +function initOAuth(opts) { + var o = (opts||{}); + var errors = []; + + appName = (o.appName||errors.push('missing appName')); + popupMask = (o.popupMask||$('#api-common-mask')); + popupDialog = (o.popupDialog||$('.api-popup-dialog')); + clientId = (o.clientId||errors.push('missing client id')); + clientSecret = (o.clientSecret||null); + realm = (o.realm||errors.push('missing realm')); + scopeSeparator = (o.scopeSeparator||' '); + additionalQueryStringParams = (o.additionalQueryStringParams||{}); + + if(errors.length > 0){ + log('auth unable initialize oauth: ' + errors); + return; + } + + $('pre code').each(function(i, e) {hljs.highlightBlock(e)}); + $('.api-ic').unbind(); + $('.api-ic').click(function(s) { + if($(s.target).hasClass('ic-off')) + handleLogin(); + else { + handleLogout(); + } + false; + }); +} + +function clientCredentialsFlow(scopes, tokenUrl, OAuthSchemeKey) { + var params = { + 'client_id': clientId, + 'client_secret': clientSecret, + 'scope': scopes.join(' '), + 'grant_type': 'client_credentials' + } + $.ajax( + { + url : tokenUrl, + type: "POST", + data: params, + success:function(data, textStatus, jqXHR) + { + onOAuthComplete(data,OAuthSchemeKey); + }, + error: function(jqXHR, textStatus, errorThrown) + { + onOAuthComplete(""); + } + }); + + } + +window.processOAuthCode = function processOAuthCode(data) { + var OAuthSchemeKey = data.state; + var params = { + 'client_id': clientId, + 'code': data.code, + 'grant_type': 'authorization_code', + 'redirect_uri': redirect_uri + }; + + if (clientSecret) { + params.client_secret = clientSecret; + } + + $.ajax( + { + url : window.swaggerUi.tokenUrl, + type: "POST", + data: params, + success:function(data, textStatus, jqXHR) + { + onOAuthComplete(data, OAuthSchemeKey); + }, + error: function(jqXHR, textStatus, errorThrown) + { + onOAuthComplete(""); + } + }); +}; + +window.onOAuthComplete = function onOAuthComplete(token,OAuthSchemeKey) { + if(token) { + if(token.error) { + var checkbox = $('input[type=checkbox],.secured') + checkbox.each(function(pos){ + checkbox[pos].checked = false; + }); + alert(token.error); + } + else { + var b = token[window.swaggerUi.tokenName]; + if (!OAuthSchemeKey){ + OAuthSchemeKey = token.state; + } + if(b){ + // if all roles are satisfied + var o = null; + $.each($('.auth .api-ic .api_information_panel'), function(k, v) { + var children = v; + if(children && children.childNodes) { + var requiredScopes = []; + $.each((children.childNodes), function (k1, v1){ + var inner = v1.innerHTML; + if(inner) + requiredScopes.push(inner); + }); + var diff = []; + for(var i=0; i < requiredScopes.length; i++) { + var s = requiredScopes[i]; + if(window.enabledScopes && window.enabledScopes.indexOf(s) == -1) { + diff.push(s); + } + } + if(diff.length > 0){ + o = v.parentNode.parentNode; + $(o.parentNode).find('.api-ic.ic-on').addClass('ic-off'); + $(o.parentNode).find('.api-ic.ic-on').removeClass('ic-on'); + + // sorry, not all scopes are satisfied + $(o).find('.api-ic').addClass('ic-warning'); + $(o).find('.api-ic').removeClass('ic-error'); + } + else { + o = v.parentNode.parentNode; + $(o.parentNode).find('.api-ic.ic-off').addClass('ic-on'); + $(o.parentNode).find('.api-ic.ic-off').removeClass('ic-off'); + + // all scopes are satisfied + $(o).find('.api-ic').addClass('ic-info'); + $(o).find('.api-ic').removeClass('ic-warning'); + $(o).find('.api-ic').removeClass('ic-error'); + } + } + }); + window.swaggerUi.api.clientAuthorizations.add(OAuthSchemeKey, new SwaggerClient.ApiKeyAuthorization('Authorization', 'Bearer ' + b, 'header')); + } + } + } +}; diff --git a/PlexRequests.UI/Content/swagger/swagger-ui.js b/PlexRequests.UI/Content/swagger/swagger-ui.js new file mode 100644 index 000000000..fee54e493 --- /dev/null +++ b/PlexRequests.UI/Content/swagger/swagger-ui.js @@ -0,0 +1,26330 @@ +/** + * swagger-ui - Swagger UI is a dependency-free collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API + * @version v2.1.4 + * @link http://swagger.io + * @license Apache-2.0 + */ +(function(){this["Handlebars"] = this["Handlebars"] || {}; +this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {}; +this["Handlebars"]["templates"]["apikey_button_view"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return "\n
    \n
    \n
    \n \n \n
    \n
    \n"; +},"useData":true}); +this["Handlebars"]["templates"]["basic_auth_button_view"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + return "
    \n
    \n
    \n
    \n \n
    \n \n \n
    \n
    \n\n"; + },"useData":true}); +this["Handlebars"]["templates"]["content_type"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.produces : depth0), {"name":"each","hash":{},"fn":this.program(2, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"2":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = " \n"; +},"4":function(depth0,helpers,partials,data) { + return " \n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; +},"useData":true}); +'use strict'; + + +$(function() { + + // Helper function for vertically aligning DOM elements + // http://www.seodenver.com/simple-vertical-align-plugin-for-jquery/ + $.fn.vAlign = function() { + return this.each(function(){ + var ah = $(this).height(); + var ph = $(this).parent().height(); + var mh = (ph - ah) / 2; + $(this).css('margin-top', mh); + }); + }; + + $.fn.stretchFormtasticInputWidthToParent = function() { + return this.each(function(){ + var p_width = $(this).closest("form").innerWidth(); + var p_padding = parseInt($(this).closest("form").css('padding-left') ,10) + parseInt($(this).closest('form').css('padding-right'), 10); + var this_padding = parseInt($(this).css('padding-left'), 10) + parseInt($(this).css('padding-right'), 10); + $(this).css('width', p_width - p_padding - this_padding); + }); + }; + + $('form.formtastic li.string input, form.formtastic textarea').stretchFormtasticInputWidthToParent(); + + // Vertically center these paragraphs + // Parent may need a min-height for this to work.. + $('ul.downplayed li div.content p').vAlign(); + + // When a sandbox form is submitted.. + $("form.sandbox").submit(function(){ + + var error_free = true; + + // Cycle through the forms required inputs + $(this).find("input.required").each(function() { + + // Remove any existing error styles from the input + $(this).removeClass('error'); + + // Tack the error style on if the input is empty.. + if ($(this).val() === '') { + $(this).addClass('error'); + $(this).wiggle(); + error_free = false; + } + + }); + + return error_free; + }); + +}); + +function clippyCopiedCallback() { + $('#api_key_copied').fadeIn().delay(1000).fadeOut(); + + // var b = $("#clippy_tooltip_" + a); + // b.length != 0 && (b.attr("title", "copied!").trigger("tipsy.reload"), setTimeout(function() { + // b.attr("title", "copy to clipboard") + // }, + // 500)) +} + +// Logging function that accounts for browsers that don't have window.console +function log(){ + log.history = log.history || []; + log.history.push(arguments); + if(this.console){ + console.log( Array.prototype.slice.call(arguments)[0] ); + } +} + +// Handle browsers that do console incorrectly (IE9 and below, see http://stackoverflow.com/a/5539378/7913) +if (Function.prototype.bind && console && typeof console.log === "object") { + [ + "log","info","warn","error","assert","dir","clear","profile","profileEnd" + ].forEach(function (method) { + console[method] = this.bind(console[method], console); + }, Function.prototype.call); +} + +window.Docs = { + + shebang: function() { + + // If shebang has an operation nickname in it.. + // e.g. /docs/#!/words/get_search + var fragments = $.param.fragment().split('/'); + fragments.shift(); // get rid of the bang + + switch (fragments.length) { + case 1: + if (fragments[0].length > 0) { // prevent matching "#/" + // Expand all operations for the resource and scroll to it + var dom_id = 'resource_' + fragments[0]; + + Docs.expandEndpointListForResource(fragments[0]); + $("#"+dom_id).slideto({highlight: false}); + } + break; + case 2: + // Refer to the endpoint DOM element, e.g. #words_get_search + + // Expand Resource + Docs.expandEndpointListForResource(fragments[0]); + $("#"+dom_id).slideto({highlight: false}); + + // Expand operation + var li_dom_id = fragments.join('_'); + var li_content_dom_id = li_dom_id + "_content"; + + + Docs.expandOperation($('#'+li_content_dom_id)); + $('#'+li_dom_id).slideto({highlight: false}); + break; + } + }, + + toggleEndpointListForResource: function(resource) { + var elem = $('li#resource_' + Docs.escapeResourceName(resource) + ' ul.endpoints'); + if (elem.is(':visible')) { + $.bbq.pushState('#/', 2); + Docs.collapseEndpointListForResource(resource); + } else { + $.bbq.pushState('#/' + resource, 2); + Docs.expandEndpointListForResource(resource); + } + }, + + // Expand resource + expandEndpointListForResource: function(resource) { + var resource = Docs.escapeResourceName(resource); + if (resource == '') { + $('.resource ul.endpoints').slideDown(); + return; + } + + $('li#resource_' + resource).addClass('active'); + + var elem = $('li#resource_' + resource + ' ul.endpoints'); + elem.slideDown(); + }, + + // Collapse resource and mark as explicitly closed + collapseEndpointListForResource: function(resource) { + var resource = Docs.escapeResourceName(resource); + if (resource == '') { + $('.resource ul.endpoints').slideUp(); + return; + } + + $('li#resource_' + resource).removeClass('active'); + + var elem = $('li#resource_' + resource + ' ul.endpoints'); + elem.slideUp(); + }, + + expandOperationsForResource: function(resource) { + // Make sure the resource container is open.. + Docs.expandEndpointListForResource(resource); + + if (resource == '') { + $('.resource ul.endpoints li.operation div.content').slideDown(); + return; + } + + $('li#resource_' + Docs.escapeResourceName(resource) + ' li.operation div.content').each(function() { + Docs.expandOperation($(this)); + }); + }, + + collapseOperationsForResource: function(resource) { + // Make sure the resource container is open.. + Docs.expandEndpointListForResource(resource); + + if (resource == '') { + $('.resource ul.endpoints li.operation div.content').slideUp(); + return; + } + + $('li#resource_' + Docs.escapeResourceName(resource) + ' li.operation div.content').each(function() { + Docs.collapseOperation($(this)); + }); + }, + + escapeResourceName: function(resource) { + return resource.replace(/[!"#$%&'()*+,.\/:;<=>?@\[\\\]\^`{|}~]/g, "\\$&"); + }, + + expandOperation: function(elem) { + elem.slideDown(); + }, + + collapseOperation: function(elem) { + elem.slideUp(); + } +}; + +'use strict'; + +Handlebars.registerHelper('sanitize', function(html) { + // Strip the script tags from the html, and return it as a Handlebars.SafeString + html = html.replace(/)<[^<]*)*<\/script>/gi, ''); + return new Handlebars.SafeString(html); +}); + +Handlebars.registerHelper('renderTextParam', function(param) { + var result, type = 'text', idAtt = ''; + var paramType = param.type || param.schema.type || ''; + var isArray = paramType.toLowerCase() === 'array' || param.allowMultiple; + var defaultValue = isArray && Array.isArray(param.default) ? param.default.join('\n') : param.default; + + var dataVendorExtensions = Object.keys(param).filter(function(property) { + // filter X-data- properties + return property.match(/^X-data-/i) !== null; + }).reduce(function(result, property) { + // remove X- from property name, so it results in html attributes like data-foo='bar' + return result += ' ' + property.substring(2, property.length) + '=\'' + param[property] + '\''; + }, ''); + + if (typeof defaultValue === 'undefined') { + defaultValue = ''; + } + + if(param.format && param.format === 'password') { + type = 'password'; + } + + if(param.valueId) { + idAtt = ' id=\'' + param.valueId + '\''; + } + + if (typeof defaultValue === 'string' || defaultValue instanceof String) { + defaultValue = defaultValue.replace(/'/g,'''); + } + + if(isArray) { + result = ''; + } else { + var parameterClass = 'parameter'; + if(param.required) { + parameterClass += ' required'; + } + result = ''; + } + return new Handlebars.SafeString(result); +}); + +this["Handlebars"]["templates"]["main"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = "
    " + + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.title : stack1), depth0)) + + "
    \n
    "; + stack1 = lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.description : stack1), depth0); + if (stack1 != null) { buffer += stack1; } + buffer += "
    \n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.externalDocs : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += " "; + stack1 = helpers['if'].call(depth0, ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.termsOfServiceUrl : stack1), {"name":"if","hash":{},"fn":this.program(4, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n "; + stack1 = helpers['if'].call(depth0, ((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.name : stack1), {"name":"if","hash":{},"fn":this.program(6, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n "; + stack1 = helpers['if'].call(depth0, ((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.url : stack1), {"name":"if","hash":{},"fn":this.program(8, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n "; + stack1 = helpers['if'].call(depth0, ((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.email : stack1), {"name":"if","hash":{},"fn":this.program(10, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n "; + stack1 = helpers['if'].call(depth0, ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.license : stack1), {"name":"if","hash":{},"fn":this.program(12, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n"; +},"2":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return "

    " + + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.externalDocs : depth0)) != null ? stack1.description : stack1), depth0)) + + "

    \n " + + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.externalDocs : depth0)) != null ? stack1.url : stack1), depth0)) + + "\n"; +},"4":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return ""; +},"6":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return "
    Created by " + + escapeExpression(lambda(((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.name : stack1), depth0)) + + "
    "; +},"8":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return ""; +},"10":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return ""; +},"12":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return ""; +},"14":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; + return " , api version: " + + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1), depth0)) + + "\n "; +},"16":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n \n"; +},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "
    \n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.info : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "
    \n
    \n
      \n\n
      \n

      [ base url: " + + escapeExpression(((helper = (helper = helpers.basePath || (depth0 != null ? depth0.basePath : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"basePath","hash":{},"data":data}) : helper))) + + "\n"; + stack1 = helpers['if'].call(depth0, ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1), {"name":"if","hash":{},"fn":this.program(14, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "]\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.validatorUrl : depth0), {"name":"if","hash":{},"fn":this.program(16, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + "

      \n
      \n
      \n"; +},"useData":true}); +this["Handlebars"]["templates"]["operation"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + return "deprecated"; + },"3":function(depth0,helpers,partials,data) { + return "

      Warning: Deprecated

      \n"; + },"5":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, buffer = "

      Implementation Notes

      \n
      "; + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "
      \n"; +},"7":function(depth0,helpers,partials,data) { + return "
      \n "; + },"9":function(depth0,helpers,partials,data) { + var stack1, buffer = "
      \n"; + stack1 = helpers.each.call(depth0, depth0, {"name":"each","hash":{},"fn":this.program(10, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + "
      \n"; +},"10":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = "
      " + + escapeExpression(lambda((depth0 != null ? depth0.scope : depth0), depth0)) + + "
      \n"; +},"12":function(depth0,helpers,partials,data) { + return "
      "; + },"14":function(depth0,helpers,partials,data) { + return "
      \n \n
      \n"; + },"16":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "

      Response Class (Status " + + escapeExpression(((helper = (helper = helpers.successCode || (depth0 != null ? depth0.successCode : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"successCode","hash":{},"data":data}) : helper))) + + ")

      \n "; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.successDescription : depth0), {"name":"if","hash":{},"fn":this.program(17, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n

      \n
      \n
      \n\n"; +},"17":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, buffer = "
      "; + stack1 = ((helper = (helper = helpers.successDescription || (depth0 != null ? depth0.successDescription : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"successDescription","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "
      "; +},"19":function(depth0,helpers,partials,data) { + var stack1, buffer = "

      Headers

      \n \n \n \n \n \n \n \n \n \n \n"; + stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.headers : depth0), {"name":"each","hash":{},"fn":this.program(20, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + " \n
      HeaderDescriptionTypeOther
      \n"; +},"20":function(depth0,helpers,partials,data) { + var lambda=this.lambda, escapeExpression=this.escapeExpression; + return " \n " + + escapeExpression(lambda((data && data.key), depth0)) + + "\n " + + escapeExpression(lambda((depth0 != null ? depth0.description : depth0), depth0)) + + "\n " + + escapeExpression(lambda((depth0 != null ? depth0.type : depth0), depth0)) + + "\n " + + escapeExpression(lambda((depth0 != null ? depth0.other : depth0), depth0)) + + "\n \n"; +},"22":function(depth0,helpers,partials,data) { + return "

      Parameters

      \n \n \n \n \n \n \n \n \n \n \n \n\n \n
      ParameterValueDescriptionParameter TypeData Type
      \n"; + },"24":function(depth0,helpers,partials,data) { + return "
      \n

      Response Messages

      \n \n \n \n \n \n \n \n \n \n \n \n
      HTTP Status CodeReasonResponse ModelHeaders
      \n"; + },"26":function(depth0,helpers,partials,data) { + return ""; +},"28":function(depth0,helpers,partials,data) { + return "
      \n \n \n \n
      \n"; + },"30":function(depth0,helpers,partials,data) { + return "

      Request Headers

      \n
      \n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, options, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, blockHelperMissing=helpers.blockHelperMissing, buffer = "\n
        \n
      • \n \n \n
      • \n
      \n"; +},"useData":true}); +this["Handlebars"]["templates"]["param_list"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + return " required"; + },"3":function(depth0,helpers,partials,data) { + return " multiple=\"multiple\""; + },"5":function(depth0,helpers,partials,data) { + return " required "; + },"7":function(depth0,helpers,partials,data) { + var stack1, buffer = " \n"; +},"8":function(depth0,helpers,partials,data) { + return " selected=\"\" "; + },"10":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n \n\n"; +},"11":function(depth0,helpers,partials,data) { + return " selected=\"\" "; + },"13":function(depth0,helpers,partials,data) { + return " (default) "; + },"15":function(depth0,helpers,partials,data) { + return ""; + },"17":function(depth0,helpers,partials,data) { + return ""; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "" + + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + + "\n\n \n\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.required : depth0), {"name":"if","hash":{},"fn":this.program(15, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.required : depth0), {"name":"if","hash":{},"fn":this.program(17, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.paramType || (depth0 != null ? depth0.paramType : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"paramType","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["param_readonly_required"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n"; +},"3":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0['default'] : depth0), {"name":"if","hash":{},"fn":this.program(4, data),"inverse":this.program(6, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"4":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " " + + escapeExpression(((helper = (helper = helpers['default'] || (depth0 != null ? depth0['default'] : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"default","hash":{},"data":data}) : helper))) + + "\n"; +},"6":function(depth0,helpers,partials,data) { + return " (empty)\n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isBody : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(3, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.paramType || (depth0 != null ? depth0.paramType : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"paramType","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["param_readonly"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n
      \n"; +},"3":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0['default'] : depth0), {"name":"if","hash":{},"fn":this.program(4, data),"inverse":this.program(6, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"4":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " " + + escapeExpression(((helper = (helper = helpers['default'] || (depth0 != null ? depth0['default'] : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"default","hash":{},"data":data}) : helper))) + + "\n"; +},"6":function(depth0,helpers,partials,data) { + return " (empty)\n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isBody : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(3, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.paramType || (depth0 != null ? depth0.paramType : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"paramType","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["param_required"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isFile : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.program(4, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"2":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n"; +},"4":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0['default'] : depth0), {"name":"if","hash":{},"fn":this.program(5, data),"inverse":this.program(7, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"5":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return "
      \n \n
      \n
      \n"; +},"7":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n
      \n
      \n
      \n"; +},"9":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isFile : depth0), {"name":"if","hash":{},"fn":this.program(10, data),"inverse":this.program(12, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"10":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n"; +},"12":function(depth0,helpers,partials,data) { + var stack1, helperMissing=helpers.helperMissing, buffer = ""; + stack1 = ((helpers.renderTextParam || (depth0 && depth0.renderTextParam) || helperMissing).call(depth0, depth0, {"name":"renderTextParam","hash":{},"fn":this.program(13, data),"inverse":this.noop,"data":data})); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"13":function(depth0,helpers,partials,data) { + return ""; +},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isBody : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(9, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n\n "; + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n\n"; + stack1 = ((helper = (helper = helpers.paramType || (depth0 != null ? depth0.paramType : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"paramType","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["param"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isFile : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.program(4, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"2":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n
      \n"; +},"4":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0['default'] : depth0), {"name":"if","hash":{},"fn":this.program(5, data),"inverse":this.program(7, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"5":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return "
      \n \n
      \n
      \n"; +},"7":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return " \n
      \n
      \n
      \n"; +},"9":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isFile : depth0), {"name":"if","hash":{},"fn":this.program(2, data),"inverse":this.program(10, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"10":function(depth0,helpers,partials,data) { + var stack1, helperMissing=helpers.helperMissing, buffer = ""; + stack1 = ((helpers.renderTextParam || (depth0 && depth0.renderTextParam) || helperMissing).call(depth0, depth0, {"name":"renderTextParam","hash":{},"fn":this.program(11, data),"inverse":this.noop,"data":data})); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"11":function(depth0,helpers,partials,data) { + return ""; +},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n\n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.isBody : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.program(9, data),"data":data}); + if (stack1 != null) { buffer += stack1; } + buffer += "\n\n"; + stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"description","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n"; + stack1 = ((helper = (helper = helpers.paramType || (depth0 != null ? depth0.paramType : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"paramType","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n\n \n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["parameter_content_type"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.consumes : depth0), {"name":"each","hash":{},"fn":this.program(2, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"2":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = " \n"; +},"4":function(depth0,helpers,partials,data) { + return " \n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["resource"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + return " : "; + },"3":function(depth0,helpers,partials,data) { + var helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression; + return "
    • \n Raw\n
    • \n"; +},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, options, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, blockHelperMissing=helpers.blockHelperMissing, buffer = "
      \n

      \n " + + escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"name","hash":{},"data":data}) : helper))) + + " "; + stack1 = ((helper = (helper = helpers.summary || (depth0 != null ? depth0.summary : depth0)) != null ? helper : helperMissing),(options={"name":"summary","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data}),(typeof helper === functionType ? helper.call(depth0, options) : helper)); + if (!helpers.summary) { stack1 = blockHelperMissing.call(depth0, stack1, options); } + if (stack1 != null) { buffer += stack1; } + stack1 = ((helper = (helper = helpers.summary || (depth0 != null ? depth0.summary : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"summary","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n

      \n
        \n
      • \n Show/Hide\n
      • \n
      • \n \n List Operations\n \n
      • \n
      • \n \n Expand Operations\n \n
      • \n"; + stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.url : depth0), {"name":"if","hash":{},"fn":this.program(3, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + "
      \n
      \n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["response_content_type"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var stack1, buffer = ""; + stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.produces : depth0), {"name":"each","hash":{},"fn":this.program(2, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer; +},"2":function(depth0,helpers,partials,data) { + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = " \n"; +},"4":function(depth0,helpers,partials,data) { + return " \n"; + },"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "\n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["signature"] = Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "
      \n\n
      \n\n
      \n
      \n "; + stack1 = ((helper = (helper = helpers.signature || (depth0 != null ? depth0.signature : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"signature","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + return buffer + "\n
      \n\n
      \n
      "
      +    + escapeExpression(((helper = (helper = helpers.sampleJSON || (depth0 != null ? depth0.sampleJSON : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"sampleJSON","hash":{},"data":data}) : helper)))
      +    + "
      \n \n
      \n
      \n\n"; +},"useData":true}); +this["Handlebars"]["templates"]["status_code"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { + var lambda=this.lambda, escapeExpression=this.escapeExpression; + return " \n " + + escapeExpression(lambda((data && data.key), depth0)) + + "\n " + + escapeExpression(lambda((depth0 != null ? depth0.description : depth0), depth0)) + + "\n " + + escapeExpression(lambda((depth0 != null ? depth0.type : depth0), depth0)) + + "\n \n"; +},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { + var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "" + + escapeExpression(((helper = (helper = helpers.code || (depth0 != null ? depth0.code : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"code","hash":{},"data":data}) : helper))) + + "\n"; + stack1 = ((helper = (helper = helpers.message || (depth0 != null ? depth0.message : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"message","hash":{},"data":data}) : helper)); + if (stack1 != null) { buffer += stack1; } + buffer += "\n\n\n \n \n"; + stack1 = helpers.each.call(depth0, (depth0 != null ? depth0.headers : depth0), {"name":"each","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data}); + if (stack1 != null) { buffer += stack1; } + return buffer + " \n
      \n"; +},"useData":true}); +/** + * swagger-client - swagger-client is a javascript client for use with swaggering APIs. + * @version v2.1.10 + * @link http://swagger.io + * @license Apache-2.0 + */ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.SwaggerClient = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { + qp = obj.url.substring(obj.url.indexOf('?') + 1); + var parts = qp.split('&'); + if(parts && parts.length > 0) { + for(var i = 0; i < parts.length; i++) { + var kv = parts[i].split('='); + if(kv && kv.length > 0) { + if (kv[0] === this.name) { + // skip it + return false; + } + } + } + } + } + + if (obj.url.indexOf('?') > 0) { + obj.url = obj.url + '&' + this.name + '=' + this.value; + } else { + obj.url = obj.url + '?' + this.name + '=' + this.value; + } + + return true; + } else if (this.type === 'header') { + if(typeof obj.headers[this.name] === 'undefined') { + obj.headers[this.name] = this.value; + } + + return true; + } +}; + +var CookieAuthorization = module.exports.CookieAuthorization = function (cookie) { + this.cookie = cookie; +}; + +CookieAuthorization.prototype.apply = function (obj) { + obj.cookieJar = obj.cookieJar || new CookieJar(); + obj.cookieJar.setCookie(this.cookie); + + return true; +}; + +/** + * Password Authorization is a basic auth implementation + */ +var PasswordAuthorization = module.exports.PasswordAuthorization = function (username, password) { + if (arguments.length === 3) { + helpers.log('PasswordAuthorization: the \'name\' argument has been removed, pass only username and password'); + username = arguments[1]; + password = arguments[2]; + } + this.username = username; + this.password = password; +}; + +PasswordAuthorization.prototype.apply = function (obj) { + if(typeof obj.headers.Authorization === 'undefined') { + obj.headers.Authorization = 'Basic ' + btoa(this.username + ':' + this.password); + } + + return true; +}; + +},{"./helpers":4,"btoa":14,"cookiejar":19,"lodash-compat/collection/each":56,"lodash-compat/collection/includes":59,"lodash-compat/lang/isArray":144,"lodash-compat/lang/isObject":148}],3:[function(require,module,exports){ +'use strict'; + +var _ = { + bind: require('lodash-compat/function/bind'), + cloneDeep: require('lodash-compat/lang/cloneDeep'), + find: require('lodash-compat/collection/find'), + forEach: require('lodash-compat/collection/forEach'), + indexOf: require('lodash-compat/array/indexOf'), + isArray: require('lodash-compat/lang/isArray'), + isObject: require('lodash-compat/lang/isObject'), + isFunction: require('lodash-compat/lang/isFunction'), + isPlainObject: require('lodash-compat/lang/isPlainObject'), + isUndefined: require('lodash-compat/lang/isUndefined') +}; +var auth = require('./auth'); +var helpers = require('./helpers'); +var Model = require('./types/model'); +var Operation = require('./types/operation'); +var OperationGroup = require('./types/operationGroup'); +var Resolver = require('./resolver'); +var SwaggerHttp = require('./http'); +var SwaggerSpecConverter = require('./spec-converter'); +var Q = require('q'); + +// We have to keep track of the function/property names to avoid collisions for tag names which are used to allow the +// following usage: 'client.{tagName}' +var reservedClientTags = [ + 'apis', + 'authorizationScheme', + 'authorizations', + 'basePath', + 'build', + 'buildFrom1_1Spec', + 'buildFrom1_2Spec', + 'buildFromSpec', + 'clientAuthorizations', + 'convertInfo', + 'debug', + 'defaultErrorCallback', + 'defaultSuccessCallback', + 'enableCookies', + 'fail', + 'failure', + 'finish', + 'help', + 'idFromOp', + 'info', + 'initialize', + 'isBuilt', + 'isValid', + 'modelPropertyMacro', + 'models', + 'modelsArray', + 'options', + 'parameterMacro', + 'parseUri', + 'progress', + 'resourceCount', + 'sampleModels', + 'selfReflect', + 'setConsolidatedModels', + 'spec', + 'supportedSubmitMethods', + 'swaggerRequestHeaders', + 'tagFromLabel', + 'title', + 'url', + 'useJQuery' +]; +// We have to keep track of the function/property names to avoid collisions for tag names which are used to allow the +// following usage: 'client.apis.{tagName}' +var reservedApiTags = [ + 'apis', + 'asCurl', + 'description', + 'externalDocs', + 'help', + 'label', + 'name', + 'operation', + 'operations', + 'operationsArray', + 'path', + 'tag' +]; +var supportedOperationMethods = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put']; +var SwaggerClient = module.exports = function (url, options) { + this.authorizations = null; + this.authorizationScheme = null; + this.basePath = null; + this.debug = false; + this.enableCookies = false; + this.info = null; + this.isBuilt = false; + this.isValid = false; + this.modelsArray = []; + this.resourceCount = 0; + this.url = null; + this.useJQuery = false; + this.swaggerObject = {}; + this.deferredClient = Q.defer(); + + this.clientAuthorizations = new auth.SwaggerAuthorizations(); + + if (typeof url !== 'undefined') { + return this.initialize(url, options); + } else { + return this; + } +}; + +SwaggerClient.prototype.initialize = function (url, options) { + this.models = {}; + this.sampleModels = {}; + + if (typeof url === 'string') { + this.url = url; + } else if (_.isObject(url)) { + options = url; + this.url = options.url; + } + + options = options || {}; + this.clientAuthorizations.add(options.authorizations); + this.swaggerRequestHeaders = options.swaggerRequestHeaders || 'application/json;charset=utf-8,*/*'; + this.defaultSuccessCallback = options.defaultSuccessCallback || null; + this.defaultErrorCallback = options.defaultErrorCallback || null; + this.modelPropertyMacro = options.modelPropertyMacro || null; + this.parameterMacro = options.parameterMacro || null; + this.usePromise = options.usePromise || null; + + if (typeof options.success === 'function') { + this.success = options.success; + } + + if (options.useJQuery) { + this.useJQuery = options.useJQuery; + } + + if (options.enableCookies) { + this.enableCookies = options.enableCookies; + } + + this.options = options || {}; + + this.supportedSubmitMethods = options.supportedSubmitMethods || []; + this.failure = options.failure || function (err) { throw err; }; + this.progress = options.progress || function () {}; + this.spec = _.cloneDeep(options.spec); // Clone so we do not alter the provided document + + if (options.scheme) { + this.scheme = options.scheme; + } + + if (this.usePromise || typeof options.success === 'function') { + this.ready = true; + return this.build(); + } +}; + +SwaggerClient.prototype.build = function (mock) { + if (this.isBuilt) { + return this; + } + + var self = this; + + this.progress('fetching resource list: ' + this.url + '; Please wait.'); + + var obj = { + useJQuery: this.useJQuery, + url: this.url, + method: 'get', + headers: { + accept: this.swaggerRequestHeaders + }, + on: { + error: function (response) { + if (self.url.substring(0, 4) !== 'http') { + return self.fail('Please specify the protocol for ' + self.url); + } else if (response.status === 0) { + return self.fail('Can\'t read from server. It may not have the appropriate access-control-origin settings.'); + } else if (response.status === 404) { + return self.fail('Can\'t read swagger JSON from ' + self.url); + } else { + return self.fail(response.status + ' : ' + response.statusText + ' ' + self.url); + } + }, + response: function (resp) { + + var responseObj = resp.obj; + if(!responseObj) { + return self.fail('failed to parse JSON/YAML response'); + } + + self.swaggerVersion = responseObj.swaggerVersion; + self.swaggerObject = responseObj; + + if (responseObj.swagger && parseInt(responseObj.swagger) === 2) { + self.swaggerVersion = responseObj.swagger; + + new Resolver().resolve(responseObj, self.url, self.buildFromSpec, self); + + self.isValid = true; + } else { + var converter = new SwaggerSpecConverter(); + self.oldSwaggerObject = self.swaggerObject; + + converter.setDocumentationLocation(self.url); + converter.convert(responseObj, self.clientAuthorizations, self.options, function(spec) { + self.swaggerObject = spec; + new Resolver().resolve(spec, self.url, self.buildFromSpec, self); + self.isValid = true; + }); + } + } + } + }; + + if (this.spec) { + self.swaggerObject = this.spec; + setTimeout(function () { + new Resolver().resolve(self.spec, self.buildFromSpec, self); + }, 10); + } else { + this.clientAuthorizations.apply(obj); + + if (mock) { + return obj; + } + + new SwaggerHttp().execute(obj, this.options); + } + + return (this.usePromise) ? this.deferredClient.promise : this; +}; + +SwaggerClient.prototype.buildFromSpec = function (response) { + if (this.isBuilt) { + return this; + } + + this.apis = {}; + this.apisArray = []; + this.basePath = response.basePath || ''; + this.consumes = response.consumes; + this.host = response.host || ''; + this.info = response.info || {}; + this.produces = response.produces; + this.schemes = response.schemes || []; + this.securityDefinitions = response.securityDefinitions; + this.title = response.title || ''; + + if (response.externalDocs) { + this.externalDocs = response.externalDocs; + } + + // legacy support + this.authSchemes = response.securityDefinitions; + + var definedTags = {}; + var k; + + if (Array.isArray(response.tags)) { + definedTags = {}; + + for (k = 0; k < response.tags.length; k++) { + var t = response.tags[k]; + definedTags[t.name] = t; + } + } + + var location; + + if (typeof this.url === 'string') { + location = this.parseUri(this.url); + if (typeof this.scheme === 'undefined' && typeof this.schemes === 'undefined' || this.schemes.length === 0) { + this.scheme = location.scheme || 'http'; + } else if (typeof this.scheme === 'undefined') { + this.scheme = this.schemes[0] || location.scheme; + } + + if (typeof this.host === 'undefined' || this.host === '') { + this.host = location.host; + + if (location.port) { + this.host = this.host + ':' + location.port; + } + } + } + else { + if (typeof this.schemes === 'undefined' || this.schemes.length === 0) { + this.scheme = 'http'; + } + else if (typeof this.scheme === 'undefined') { + this.scheme = this.schemes[0]; + } + } + + this.definitions = response.definitions; + + var key; + + for (key in this.definitions) { + var model = new Model(key, this.definitions[key], this.models, this.modelPropertyMacro); + + if (model) { + this.models[key] = model; + } + } + + // get paths, create functions for each operationId + var self = this; + + // Bind help to 'client.apis' + self.apis.help = _.bind(self.help, self); + + _.forEach(response.paths, function (pathObj, path) { + // Only process a path if it's an object + if (!_.isPlainObject(pathObj)) { + return; + } + + _.forEach(supportedOperationMethods, function (method) { + var operation = pathObj[method]; + + if (_.isUndefined(operation)) { + // Operation does not exist + return; + } else if (!_.isPlainObject(operation)) { + // Operation exists but it is not an Operation Object. Since this is invalid, log it. + helpers.log('The \'' + method + '\' operation for \'' + path + '\' path is not an Operation Object'); + + return; + } + + var tags = operation.tags; + + if (_.isUndefined(tags) || !_.isArray(tags) || tags.length === 0) { + tags = operation.tags = [ 'default' ]; + } + + var operationId = self.idFromOp(path, method, operation); + + var operationObject = new Operation(self, + operation.scheme, + operationId, + method, + path, + operation, + self.definitions, + self.models, + self.clientAuthorizations); + + // bind self operation's execute command to the api + _.forEach(tags, function (tag) { + var clientProperty = _.indexOf(reservedClientTags, tag) > -1 ? '_' + tag : tag; + var apiProperty = _.indexOf(reservedApiTags, tag) > -1 ? '_' + tag : tag; + var operationGroup = self[clientProperty]; + + if (clientProperty !== tag) { + helpers.log('The \'' + tag + '\' tag conflicts with a SwaggerClient function/property name. Use \'client.' + + clientProperty + '\' or \'client.apis.' + tag + '\' instead of \'client.' + tag + '\'.'); + } + + if (apiProperty !== tag) { + helpers.log('The \'' + tag + '\' tag conflicts with a SwaggerClient operation function/property name. Use ' + + '\'client.apis.' + apiProperty + '\' instead of \'client.apis.' + tag + '\'.'); + } + + if (_.indexOf(reservedApiTags, operationId) > -1) { + helpers.log('The \'' + operationId + '\' operationId conflicts with a SwaggerClient operation ' + + 'function/property name. Use \'client.apis.' + apiProperty + '._' + operationId + + '\' instead of \'client.apis.' + apiProperty + '.' + operationId + '\'.'); + + operationId = '_' + operationId; + operationObject.nickname = operationId; // So 'client.apis.[tag].operationId.help() works properly + } + + if (_.isUndefined(operationGroup)) { + operationGroup = self[clientProperty] = self.apis[apiProperty] = {}; + + operationGroup.operations = {}; + operationGroup.label = apiProperty; + operationGroup.apis = {}; + + var tagDef = definedTags[tag]; + + if (!_.isUndefined(tagDef)) { + operationGroup.description = tagDef.description; + operationGroup.externalDocs = tagDef.externalDocs; + } + + self[clientProperty].help = _.bind(self.help, operationGroup); + self.apisArray.push(new OperationGroup(tag, operationGroup.description, operationGroup.externalDocs, operationObject)); + } + + operationId = self.makeUniqueOperationId(operationId, self.apis[apiProperty]); + + // Bind tag help + if (!_.isFunction(operationGroup.help)) { + operationGroup.help = _.bind(self.help, operationGroup); + } + + // bind to the apis object + self.apis[apiProperty][operationId] = operationGroup[operationId] = _.bind(operationObject.execute, + operationObject); + self.apis[apiProperty][operationId].help = operationGroup[operationId].help = _.bind(operationObject.help, + operationObject); + self.apis[apiProperty][operationId].asCurl = operationGroup[operationId].asCurl = _.bind(operationObject.asCurl, + operationObject); + + operationGroup.apis[operationId] = operationGroup.operations[operationId] = operationObject; + + // legacy UI feature + var api = _.find(self.apisArray, function (api) { + return api.tag === tag; + }); + + if (api) { + api.operationsArray.push(operationObject); + } + }); + }); + }); + + this.isBuilt = true; + + if (this.usePromise) { + this.isValid = true; + this.isBuilt = true; + this.deferredClient.resolve(this); + + return this.deferredClient.promise; + } + + if (this.success) { + this.success(); + } + + return this; +}; + +SwaggerClient.prototype.makeUniqueOperationId = function(operationId, api) { + var count = 0; + var name = operationId; + + // make unique across this operation group + while(true) { + var matched = false; + _.forEach(api.operations, function (operation) { + if(operation.nickname === name) { + matched = true; + } + }); + if(!matched) { + return name; + } + name = operationId + '_' + count; + count ++; + } + + return operationId; +}; + +SwaggerClient.prototype.parseUri = function (uri) { + var urlParseRE = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/; + var parts = urlParseRE.exec(uri); + + return { + scheme: parts[4] ? parts[4].replace(':','') : undefined, + host: parts[11], + port: parts[12], + path: parts[15] + }; +}; + +SwaggerClient.prototype.help = function (dontPrint) { + var output = ''; + + if (this instanceof SwaggerClient) { + _.forEach(this.apis, function (api, name) { + if (_.isPlainObject(api)) { + output += 'operations for the \'' + name + '\' tag\n'; + + _.forEach(api.operations, function (operation, name) { + output += ' * ' + name + ': ' + operation.summary + '\n'; + }); + } + }); + } else if (this instanceof OperationGroup || _.isPlainObject(this)) { + output += 'operations for the \'' + this.label + '\' tag\n'; + + _.forEach(this.apis, function (operation, name) { + output += ' * ' + name + ': ' + operation.summary + '\n'; + }); + } + + if (dontPrint) { + return output; + } else { + helpers.log(output); + + return output; + } +}; + +SwaggerClient.prototype.tagFromLabel = function (label) { + return label; +}; + +SwaggerClient.prototype.idFromOp = function (path, httpMethod, op) { + if(!op || !op.operationId) { + op = op || {}; + op.operationId = httpMethod + '_' + path; + } + var opId = op.operationId.replace(/[\s!@#$%^&*()_+=\[{\]};:<>|.\/?,\\'""-]/g, '_') || (path.substring(1) + '_' + httpMethod); + + opId = opId.replace(/((_){2,})/g, '_'); + opId = opId.replace(/^(_)*/g, ''); + opId = opId.replace(/([_])*$/g, ''); + + return opId; +}; + +SwaggerClient.prototype.setHost = function (host) { + this.host = host; + + if(this.apis) { + _.forEach(this.apis, function(api) { + if(api.operations) { + _.forEach(api.operations, function(operation) { + operation.host = host; + }); + } + }); + } +}; + +SwaggerClient.prototype.setBasePath = function (basePath) { + this.basePath = basePath; + + if(this.apis) { + _.forEach(this.apis, function(api) { + if(api.operations) { + _.forEach(api.operations, function(operation) { + operation.basePath = basePath; + }); + } + }); + } +}; + +SwaggerClient.prototype.fail = function (message) { + if (this.usePromise) { + this.deferredClient.reject(message); + return this.deferredClient.promise; + } else { + if (this.failure) { + this.failure(message); + } + else { + this.failure(message); + } + } +}; + +},{"./auth":2,"./helpers":4,"./http":5,"./resolver":6,"./spec-converter":8,"./types/model":9,"./types/operation":10,"./types/operationGroup":11,"lodash-compat/array/indexOf":53,"lodash-compat/collection/find":57,"lodash-compat/collection/forEach":58,"lodash-compat/function/bind":62,"lodash-compat/lang/cloneDeep":142,"lodash-compat/lang/isArray":144,"lodash-compat/lang/isFunction":146,"lodash-compat/lang/isObject":148,"lodash-compat/lang/isPlainObject":149,"lodash-compat/lang/isUndefined":152,"q":161}],4:[function(require,module,exports){ +(function (process){ +'use strict'; + +var _ = { + isPlainObject: require('lodash-compat/lang/isPlainObject'), + indexOf: require('lodash-compat/array/indexOf') +}; + +module.exports.__bind = function (fn, me) { + return function(){ + return fn.apply(me, arguments); + }; +}; + +var log = module.exports.log = function() { + // Only log if available and we're not testing + if (console && process.env.NODE_ENV !== 'test') { + console.log(Array.prototype.slice.call(arguments)[0]); + } +}; + +module.exports.fail = function (message) { + log(message); +}; + +var optionHtml = module.exports.optionHtml = function (label, value) { + return '' + label + ':' + value + ''; +}; + +var resolveSchema = module.exports.resolveSchema = function (schema) { + if (_.isPlainObject(schema.schema)) { + schema = resolveSchema(schema.schema); + } + + return schema; +}; + +var simpleRef = module.exports.simpleRef = function (name) { + if (typeof name === 'undefined') { + return null; + } + + if (name.indexOf('#/definitions/') === 0) { + return name.substring('#/definitions/'.length); + } else { + return name; + } +}; + + +}).call(this,require('_process')) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9oZWxwZXJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHtcbiAgaXNQbGFpbk9iamVjdDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzUGxhaW5PYmplY3QnKSxcbiAgaW5kZXhPZjogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9hcnJheS9pbmRleE9mJylcbn07XG5cbm1vZHVsZS5leHBvcnRzLl9fYmluZCA9IGZ1bmN0aW9uIChmbiwgbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCl7XG4gICAgcmV0dXJuIGZuLmFwcGx5KG1lLCBhcmd1bWVudHMpO1xuICB9O1xufTtcblxudmFyIGxvZyA9IG1vZHVsZS5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICAvLyBPbmx5IGxvZyBpZiBhdmFpbGFibGUgYW5kIHdlJ3JlIG5vdCB0ZXN0aW5nXG4gIGlmIChjb25zb2xlICYmIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAndGVzdCcpIHtcbiAgICBjb25zb2xlLmxvZyhBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpWzBdKTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMuZmFpbCA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gIGxvZyhtZXNzYWdlKTtcbn07XG5cbnZhciBvcHRpb25IdG1sID0gbW9kdWxlLmV4cG9ydHMub3B0aW9uSHRtbCA9IGZ1bmN0aW9uIChsYWJlbCwgdmFsdWUpIHtcbiAgcmV0dXJuICc8dHI+PHRkIGNsYXNzPVwib3B0aW9uTmFtZVwiPicgKyBsYWJlbCArICc6PC90ZD48dGQ+JyArIHZhbHVlICsgJzwvdGQ+PC90cj4nO1xufTtcblxudmFyIHJlc29sdmVTY2hlbWEgPSBtb2R1bGUuZXhwb3J0cy5yZXNvbHZlU2NoZW1hID0gZnVuY3Rpb24gKHNjaGVtYSkge1xuICBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5zY2hlbWEpKSB7XG4gICAgc2NoZW1hID0gcmVzb2x2ZVNjaGVtYShzY2hlbWEuc2NoZW1hKTtcbiAgfVxuXG4gIHJldHVybiBzY2hlbWE7XG59O1xuXG52YXIgc2ltcGxlUmVmID0gbW9kdWxlLmV4cG9ydHMuc2ltcGxlUmVmID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgaWYgKHR5cGVvZiBuYW1lID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaWYgKG5hbWUuaW5kZXhPZignIy9kZWZpbml0aW9ucy8nKSA9PT0gMCkge1xuICAgIHJldHVybiBuYW1lLnN1YnN0cmluZygnIy9kZWZpbml0aW9ucy8nLmxlbmd0aCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5hbWU7XG4gIH1cbn07XG5cbiJdfQ== +},{"_process":13,"lodash-compat/array/indexOf":53,"lodash-compat/lang/isPlainObject":149}],5:[function(require,module,exports){ +'use strict'; + +var helpers = require('./helpers'); +var request = require('superagent'); +var jsyaml = require('js-yaml'); +var _ = { + isObject: require('lodash-compat/lang/isObject') +}; + +/* + * JQueryHttpClient is a light-weight, node or browser HTTP client + */ +var JQueryHttpClient = function () {}; + +/* + * SuperagentHttpClient is a light-weight, node or browser HTTP client + */ +var SuperagentHttpClient = function () {}; + +/** + * SwaggerHttp is a wrapper for executing requests + */ +var SwaggerHttp = module.exports = function () {}; + +SwaggerHttp.prototype.execute = function (obj, opts) { + var client; + + if(opts && opts.client) { + client = opts.client; + } + else { + client = new SuperagentHttpClient(opts); + } + client.opts = opts || {}; + + // legacy support + var hasJQuery = false; + if(typeof window !== 'undefined') { + if(typeof window.jQuery !== 'undefined') { + hasJQuery = true; + } + } + if(this.isInternetExplorer() && (obj.useJQuery === false || !hasJQuery )) { + throw new Error('Unsupported configuration! JQuery is required but not available'); + } + if ((obj && obj.useJQuery === true) || this.isInternetExplorer() && hasJQuery) { + client = new JQueryHttpClient(opts); + } + + var success = obj.on.response; + + var requestInterceptor = function(data) { + if(opts && opts.requestInterceptor) { + data = opts.requestInterceptor.apply(data); + } + return data; + }; + + var responseInterceptor = function(data) { + if(opts && opts.responseInterceptor) { + data = opts.responseInterceptor.apply(data); + } + return success(data); + }; + + obj.on.response = function(data) { + responseInterceptor(data); + }; + + + if (_.isObject(obj) && _.isObject(obj.body)) { + // special processing for file uploads via jquery + if (obj.body.type && obj.body.type === 'formData'){ + obj.contentType = false; + obj.processData = false; + + delete obj.headers['Content-Type']; + } else { + obj.body = JSON.stringify(obj.body); + } + } + + client.execute(requestInterceptor(obj)); + + return (obj.deferred) ? obj.deferred.promise : obj; +}; + +SwaggerHttp.prototype.isInternetExplorer = function () { + var detectedIE = false; + + if (typeof navigator !== 'undefined' && navigator.userAgent) { + var nav = navigator.userAgent.toLowerCase(); + + if (nav.indexOf('msie') !== -1) { + var version = parseInt(nav.split('msie')[1]); + + if (version <= 8) { + detectedIE = true; + } + } + } + + return detectedIE; +}; + +JQueryHttpClient.prototype.execute = function (obj) { + var jq = this.jQuery || window.jQuery; + var cb = obj.on; + var request = obj; + + obj.type = obj.method; + obj.cache = false; + delete obj.useJQuery; + + /* + obj.beforeSend = function (xhr) { + var key, results; + if (obj.headers) { + results = []; + for (key in obj.headers) { + if (key.toLowerCase() === 'content-type') { + results.push(obj.contentType = obj.headers[key]); + } else if (key.toLowerCase() === 'accept') { + results.push(obj.accepts = obj.headers[key]); + } else { + results.push(xhr.setRequestHeader(key, obj.headers[key])); + } + } + return results; + } + };*/ + + obj.data = obj.body; + + delete obj.body; + + obj.complete = function (response) { + var headers = {}; + var headerArray = response.getAllResponseHeaders().split('\n'); + + for (var i = 0; i < headerArray.length; i++) { + var toSplit = headerArray[i].trim(); + + if (toSplit.length === 0) { + continue; + } + + var separator = toSplit.indexOf(':'); + + if (separator === -1) { + // Name but no value in the header + headers[toSplit] = null; + + continue; + } + + var name = toSplit.substring(0, separator).trim(); + var value = toSplit.substring(separator + 1).trim(); + + headers[name] = value; + } + + var out = { + url: request.url, + method: request.method, + status: response.status, + statusText: response.statusText, + data: response.responseText, + headers: headers + }; + + try { + var possibleObj = response.responseJSON || jsyaml.safeLoad(response.responseText); + out.obj = (typeof possibleObj === 'string') ? {} : possibleObj; + } catch (ex) { + // do not set out.obj + helpers.log('unable to parse JSON/YAML content'); + } + + // I can throw, or parse null? + out.obj = out.obj || null; + + if (response.status >= 200 && response.status < 300) { + cb.response(out); + } else if (response.status === 0 || (response.status >= 400 && response.status < 599)) { + cb.error(out); + } else { + return cb.response(out); + } + }; + + jq.support.cors = true; + + return jq.ajax(obj); +}; + +SuperagentHttpClient.prototype.execute = function (obj) { + var method = obj.method.toLowerCase(); + + if (method === 'delete') { + method = 'del'; + } + var headers = obj.headers || {}; + var r = request[method](obj.url); + var name; + for (name in headers) { + r.set(name, headers[name]); + } + + if (obj.enableCookies) { + r.withCredentials(); + } + + if (obj.body) { + r.send(obj.body); + } + + if(typeof r.buffer === 'function') { + r.buffer(); // force superagent to populate res.text with the raw response data + } + + r.end(function (err, res) { + res = res || { + status: 0, + headers: {error: 'no response from server'} + }; + var response = { + url: obj.url, + method: obj.method, + headers: res.headers + }; + var cb; + + if (!err && res.error) { + err = res.error; + } + + if (err && obj.on && obj.on.error) { + response.errObj = err; + response.status = res ? res.status : 500; + response.statusText = res ? res.text : err.message; + if(res.headers && res.headers['content-type']) { + if(res.headers['content-type'].indexOf('application/json') >= 0) { + try { + response.obj = JSON.parse(response.statusText); + } + catch (e) { + response.obj = null; + } + } + } + cb = obj.on.error; + } else if (res && obj.on && obj.on.response) { + var possibleObj; + + // Already parsed by by superagent? + if(res.body && Object.keys(res.body).length > 0) { + possibleObj = res.body; + } else { + try { + possibleObj = jsyaml.safeLoad(res.text); + // can parse into a string... which we don't need running around in the system + possibleObj = (typeof possibleObj === 'string') ? null : possibleObj; + } catch(e) { + helpers.log('cannot parse JSON/YAML content'); + } + } + + // null means we can't parse into object + response.obj = (typeof possibleObj === 'object') ? possibleObj : null; + + response.status = res.status; + response.statusText = res.text; + cb = obj.on.response; + } + response.data = response.statusText; + + if (cb) { + cb(response); + } + }); +}; + +},{"./helpers":4,"js-yaml":20,"lodash-compat/lang/isObject":148,"superagent":162}],6:[function(require,module,exports){ +'use strict'; + +var SwaggerHttp = require('./http'); +var _ = { + isObject: require('lodash-compat/lang/isObject'), + cloneDeep: require('lodash-compat/lang/cloneDeep'), + isArray: require('lodash-compat/lang/isArray') +}; + + +/** + * Resolves a spec's remote references + */ +var Resolver = module.exports = function () {}; + +Resolver.prototype.processAllOf = function(root, name, definition, resolutionTable, unresolvedRefs, spec) { + var i, location, property; + + definition['x-resolved-from'] = [ '#/definitions/' + name ]; + var allOf = definition.allOf; + // the refs go first + allOf.sort(function(a, b) { + if(a.$ref && b.$ref) { return 0; } + else if(a.$ref) { return -1; } + else { return 1; } + }); + for (i = 0; i < allOf.length; i++) { + property = allOf[i]; + location = '/definitions/' + name + '/allOf'; + this.resolveInline(root, spec, property, resolutionTable, unresolvedRefs, location); + } +}; + +Resolver.prototype.resolve = function (spec, arg1, arg2, arg3) { + this.spec = spec; + var root = arg1, callback = arg2, scope = arg3, opts = {}, location, i; + if(typeof arg1 === 'function') { + root = null; + callback = arg1; + scope = arg2; + } + var _root = root; + this.scope = (scope || this); + this.iteration = this.iteration || 0; + + if(this.scope.options && this.scope.options.requestInterceptor){ + opts.requestInterceptor = this.scope.options.requestInterceptor; + } + + if(this.scope.options && this.scope.options.responseInterceptor){ + opts.responseInterceptor = this.scope.options.responseInterceptor; + } + + var name, path, property, propertyName; + var processedCalls = 0, resolvedRefs = {}, unresolvedRefs = {}; + var resolutionTable = []; // store objects for dereferencing + + spec.definitions = spec.definitions || {}; + // definitions + for (name in spec.definitions) { + var definition = spec.definitions[name]; + for (propertyName in definition.properties) { + property = definition.properties[propertyName]; + if(_.isArray(property.allOf)) { + this.processAllOf(root, name, property, resolutionTable, unresolvedRefs, spec); + } + else { + this.resolveTo(root, property, resolutionTable, '/definitions'); + } + } + + if(definition.allOf) { + this.processAllOf(root, name, definition, resolutionTable, unresolvedRefs, spec); + } + } + + // operations + for (name in spec.paths) { + var method, operation, responseCode; + path = spec.paths[name]; + + for (method in path) { + // operation reference + if(method === '$ref') { + // location = path[method]; + location = '/paths' + name; + this.resolveInline(root, spec, path, resolutionTable, unresolvedRefs, location); + } + else { + operation = path[method]; + var sharedParameters = path.parameters || []; + var parameters = operation.parameters || []; + + for (i in sharedParameters) { + var parameter = sharedParameters[i]; + parameters.unshift(parameter); + } + if(method !== 'parameters' && _.isObject(operation)) { + operation.parameters = operation.parameters || parameters; + } + + for (i in parameters) { + var parameter = parameters[i]; + location = '/paths' + name + '/' + method + '/parameters'; + + if (parameter.in === 'body' && parameter.schema) { + if(_.isArray(parameter.schema.allOf)) { + // move to a definition + var modelName = 'inline_model'; + var name = modelName; + var done = false; var counter = 0; + while(!done) { + if(typeof spec.definitions[name] === 'undefined') { + done = true; + break; + } + name = modelName + '_' + counter; + counter ++; + } + spec.definitions[name] = { allOf: parameter.schema.allOf }; + delete parameter.schema.allOf; + parameter.schema.$ref = '#/definitions/' + name; + this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec); + } + else { + this.resolveTo(root, parameter.schema, resolutionTable, location); + } + } + + if (parameter.$ref) { + // parameter reference + this.resolveInline(root, spec, parameter, resolutionTable, unresolvedRefs, parameter.$ref); + } + } + + for (responseCode in operation.responses) { + var response = operation.responses[responseCode]; + location = '/paths' + name + '/' + method + '/responses/' + responseCode; + + if(_.isObject(response)) { + if(response.$ref) { + // response reference + this.resolveInline(root, spec, response, resolutionTable, unresolvedRefs, location); + } + if (response.schema) { + this.resolveTo(root, response.schema, resolutionTable, location); + } + } + } + } + } + // clear them out to avoid multiple resolutions + path.parameters = []; + } + + var expectedCalls = 0, toResolve = []; + // if the root is same as obj[i].root we can resolve locally + var all = resolutionTable; + + var parts; + for(i = 0; i < all.length; i++) { + var a = all[i]; + if(root === a.root) { + if(a.resolveAs === 'ref') { + // resolve any path walking + var joined = ((a.root || '') + '/' + a.key).split('/'); + var normalized = []; + var url = ''; + var k; + + if(a.key.indexOf('../') >= 0) { + for(var j = 0; j < joined.length; j++) { + if(joined[j] === '..') { + normalized = normalized.slice(0, normalized.length-1); + } + else { + normalized.push(joined[j]); + } + } + for(k = 0; k < normalized.length; k ++) { + if(k > 0) { + url += '/'; + } + url += normalized[k]; + } + // we now have to remote resolve this because the path has changed + a.root = url; + toResolve.push(a); + } + else { + parts = a.key.split('#'); + if(parts.length === 2) { + if(parts[0].indexOf('http://') === 0 || parts[0].indexOf('https://') === 0) { + a.root = parts[0]; + } + location = parts[1].split('/'); + var r; + var s = spec; + for(k = 0; k < location.length; k++) { + var part = location[k]; + if(part !== '') { + s = s[part]; + if(typeof s !== 'undefined') { + r = s; + } + else { + r = null; + break; + } + } + } + if(r === null) { + // must resolve this too + toResolve.push(a); + } + } + } + } + else { + if (a.resolveAs === 'inline') { + if(a.key && a.key.indexOf('#') === -1 && a.key.charAt(0) !== '/') { + // handle relative schema + parts = a.root.split('/'); + location = ''; + for(i = 0; i < parts.length - 1; i++) { + location += parts[i] + '/'; + } + location += a.key; + a.root = location; + a.location = ''; + } + toResolve.push(a); + } + } + } + else { + toResolve.push(a); + } + } + expectedCalls = toResolve.length; + + // resolve anything that is local + for(var ii = 0; ii < toResolve.length; ii++) { + (function(item, spec, self) { + if(item.root === null || item.root === root) { + // local resolve + self.resolveItem(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, item); + processedCalls += 1; + + if(processedCalls === expectedCalls) { + self.finish(spec, root, resolutionTable, resolvedRefs, unresolvedRefs, callback, true); + } + } + else { + var obj = { + useJQuery: false, // TODO + url: item.root, + method: 'get', + headers: { + accept: self.scope.swaggerRequestHeaders || 'application/json' + }, + on: { + error: function (error) { + processedCalls += 1; + unresolvedRefs[item.key] = { + root: item.root, + location: item.location + }; + + if (processedCalls === expectedCalls) { + self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback); + } + }, // jshint ignore:line + response: function (response) { + var swagger = response.obj; + self.resolveItem(swagger, item.root, resolutionTable, resolvedRefs, unresolvedRefs, item); + processedCalls += 1; + + if (processedCalls === expectedCalls) { + self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback); + } + } + } // jshint ignore:line + }; + + if (scope && scope.clientAuthorizations) { + scope.clientAuthorizations.apply(obj); + } + + new SwaggerHttp().execute(obj, opts); + } + }(toResolve[ii], spec, this)); + } + + if (Object.keys(toResolve).length === 0) { + this.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback); + } +}; + +Resolver.prototype.resolveItem = function(spec, root, resolutionTable, resolvedRefs, unresolvedRefs, item) { + var path = item.location; + var location = spec, parts = path.split('/'); + if(path !== '') { + for (var j = 0; j < parts.length; j++) { + var segment = parts[j]; + if (segment.indexOf('~1') !== -1) { + segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/'); + if (segment.charAt(0) !== '/') { + segment = '/' + segment; + } + } + if (typeof location === 'undefined' || location === null) { + break; + } + if (segment === '' && j === (parts.length - 1) && parts.length > 1) { + location = null; + break; + } + if (segment.length > 0) { + location = location[segment]; + } + } + } + var resolved = item.key; + parts = item.key.split('/'); + var resolvedName = parts[parts.length-1]; + + if(resolvedName.indexOf('#') >= 0) { + resolvedName = resolvedName.split('#')[1]; + } + + if (location !== null && typeof location !== 'undefined') { + resolvedRefs[resolved] = { + name: resolvedName, + obj: location, + key: item.key, + root: item.root + }; + } else { + unresolvedRefs[resolved] = { + root: item.root, + location: item.location + }; + } +}; + +Resolver.prototype.finish = function (spec, root, resolutionTable, resolvedRefs, unresolvedRefs, callback, localResolve) { + // walk resolution table and replace with resolved refs + var ref; + for (ref in resolutionTable) { + var item = resolutionTable[ref]; + + var key = item.key; + var resolvedTo = resolvedRefs[key]; + if (resolvedTo) { + spec.definitions = spec.definitions || {}; + if (item.resolveAs === 'ref') { + if (localResolve !== true) { + // don't retain root for local definitions + for (key in resolvedTo.obj) { + var abs = this.retainRoot(resolvedTo.obj[key], item.root); + } + } + spec.definitions[resolvedTo.name] = resolvedTo.obj; + item.obj.$ref = '#/definitions/' + resolvedTo.name; + } else if (item.resolveAs === 'inline') { + var targetObj = item.obj; + targetObj['x-resolved-from'] = [ item.key ]; + delete targetObj.$ref; + + for (key in resolvedTo.obj) { + var abs = resolvedTo.obj[key]; + + if (localResolve !== true) { + // don't retain root for local definitions + abs = this.retainRoot(resolvedTo.obj[key], item.root); + } + targetObj[key] = abs; + } + } + } + } + var existingUnresolved = this.countUnresolvedRefs(spec); + + if(existingUnresolved === 0 || this.iteration > 5) { + this.resolveAllOf(spec.definitions); + callback.call(this.scope, spec, unresolvedRefs); + } + else { + this.iteration += 1; + this.resolve(spec, root, callback, this.scope); + } +}; + +Resolver.prototype.countUnresolvedRefs = function(spec) { + var i; + var refs = this.getRefs(spec); + var keys = []; + var unresolvedKeys = []; + for(i in refs) { + if(i.indexOf('#') === 0) { + keys.push(i.substring(1)); + } + else { + unresolvedKeys.push(i); + } + } + + // verify possible keys + for (i = 0; i < keys.length; i++) { + var part = keys[i]; + var parts = part.split('/'); + var obj = spec; + + for (var k = 0; k < parts.length; k++) { + var key = parts[k]; + if(key !== '') { + obj = obj[key]; + if(typeof obj === 'undefined') { + unresolvedKeys.push(part); + break; + } + } + } + } + return unresolvedKeys.length; +}; + +Resolver.prototype.getRefs = function(spec, obj) { + obj = obj || spec; + var output = {}; + for(var key in obj) { + if (!obj.hasOwnProperty(key)) { + continue; + } + var item = obj[key]; + if(key === '$ref' && typeof item === 'string') { + output[item] = null; + } + else if(_.isObject(item)) { + var o = this.getRefs(item); + for(var k in o) { + output[k] = null; + } + } + } + return output; +}; + +Resolver.prototype.retainRoot = function(obj, root) { + // walk object and look for relative $refs + for(var key in obj) { + var item = obj[key]; + if(key === '$ref' && typeof item === 'string') { + // stop and inspect + if(item.indexOf('http://') !== 0 && item.indexOf('https://') !== 0) { + if(item.indexOf('#') !== 0) { + item = '#' + item; + } + item = (root || '') + item; + obj[key] = item; + } + } + else if(_.isObject(item)) { + this.retainRoot(item, root); + } + } + return obj; +}; + +/** + * immediately in-lines local refs, queues remote refs + * for inline resolution + */ +Resolver.prototype.resolveInline = function (root, spec, property, resolutionTable, unresolvedRefs, location) { + var key = property.$ref, ref = property.$ref, i, p, p2, rs; + var rootTrimmed = false; + if (ref) { + if(ref.indexOf('../') === 0) { + // reset root + p = ref.split('../'); + p2 = root.split('/'); + ref = ''; + for(i = 0; i < p.length; i++) { + if(p[i] === '') { + p2 = p2.slice(0, p2.length-1); + } + else { + ref += p[i]; + } + } + root = ''; + for(i = 0; i < p2.length - 1; i++) { + if(i > 0) { root += '/'; } + root += p2[i]; + } + rootTrimmed = true; + } + if(ref.indexOf('#') >= 0) { + if(ref.indexOf('/') === 0) { + rs = ref.split('#'); + p = root.split('//'); + p2 = p[1].split('/'); + root = p[0] + '//' + p2[0] + rs[0]; + location = rs[1]; + } + else { + rs = ref.split('#'); + if(rs[0] !== '') { + p2 = root.split('/'); + p2 = p2.slice(0, p2.length - 1); + if(!rootTrimmed) { + root = ''; + for (var k = 0; k < p2.length; k++) { + if(k > 0) { root += '/'; } + root += p2[k]; + } + } + root += '/' + ref.split('#')[0]; + } + location = rs[1]; + } + } + if (ref.indexOf('http') === 0) { + if(ref.indexOf('#') >= 0) { + root = ref.split('#')[0]; + location = ref.split('#')[1]; + } + else { + root = ref; + location = ''; + } + resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location}); + } else if (ref.indexOf('#') === 0) { + location = ref.split('#')[1]; + resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location}); + } + else { + resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location}); + } + } + else if (property.type === 'array') { + this.resolveTo(root, property.items, resolutionTable, location); + } +}; + +Resolver.prototype.resolveTo = function (root, property, resolutionTable, location) { + var sp, i; + var ref = property.$ref; + var lroot = root; + if (typeof ref !== 'undefined') { + if(ref.indexOf('#') >= 0) { + var parts = ref.split('#'); + + // #/definitions/foo + // foo.json#/bar + if(parts[0] && ref.indexOf('/') === 0) { + + } + else if(parts[0] && parts[0].indexOf('http') === 0) { + lroot = parts[0]; + ref = parts[1]; + } + else if(parts[0] && parts[0].length > 0) { + // relative file + sp = root.split('/'); + lroot = ''; + for(i = 0; i < sp.length - 1; i++) { + lroot += sp[i] + '/'; + } + lroot += parts[0]; + } + else { + + } + + location = parts[1]; + } + else if (ref.indexOf('http://') === 0 || ref.indexOf('https://') === 0) { + lroot = ref; + location = ''; + } + else { + // relative file + sp = root.split('/'); + lroot = ''; + for(i = 0; i < sp.length - 1; i++) { + lroot += sp[i] + '/'; + } + lroot += ref; + location = ''; + } + resolutionTable.push({ + obj: property, resolveAs: 'ref', root: lroot, key: ref, location: location + }); + } else if (property.type === 'array') { + var items = property.items; + this.resolveTo(root, items, resolutionTable, location); + } else { + if(property && property.properties) { + var name = this.uniqueName('inline_model'); + this.spec.definitions[name] = _.cloneDeep(property); + property['$ref'] = '#/definitions/' + name; + delete property.type; + delete property.properties; + } + } +}; + +Resolver.prototype.uniqueName = function(base) { + var name = base; + var count = 0; + while(true) { + if(!_.isObject(this.spec.definitions[name])) { + return name; + } + name = base + '_' + count; + count++; + } +}; + +Resolver.prototype.resolveAllOf = function(spec, obj, depth) { + depth = depth || 0; + obj = obj || spec; + var name; + for(var key in obj) { + if (!obj.hasOwnProperty(key)) { + continue; + } + var item = obj[key]; + if(item === null) { + throw new TypeError('Swagger 2.0 does not support null types (' + obj + '). See https://github.com/swagger-api/swagger-spec/issues/229.'); + } + if(typeof item === 'object') { + this.resolveAllOf(spec, item, depth + 1); + } + if(item && typeof item.allOf !== 'undefined') { + var allOf = item.allOf; + if(_.isArray(allOf)) { + var output = _.cloneDeep(item); + delete output.allOf; + + output['x-composed'] = true; + if (typeof item['x-resolved-from'] !== 'undefined') { + output['x-resolved-from'] = item['x-resolved-from']; + } + + for(var i = 0; i < allOf.length; i++) { + var component = allOf[i]; + var source = 'self'; + if(typeof component['x-resolved-from'] !== 'undefined') { + source = component['x-resolved-from'][0]; + } + + for(var part in component) { + if(!output.hasOwnProperty(part)) { + output[part] = _.cloneDeep(component[part]); + if(part === 'properties') { + for(name in output[part]) { + output[part][name]['x-resolved-from'] = source; + } + } + } + else { + if(part === 'properties') { + var properties = component[part]; + for(name in properties) { + output.properties[name] = _.cloneDeep(properties[name]); + var resolvedFrom = properties[name]['x-resolved-from']; + if (typeof resolvedFrom === 'undefined' || resolvedFrom === 'self') { + resolvedFrom = source; + } + output.properties[name]['x-resolved-from'] = resolvedFrom; + } + } + else if(part === 'required') { + // merge & dedup the required array + var a = output.required.concat(component[part]); + for(var k = 0; k < a.length; ++k) { + for(var j = k + 1; j < a.length; ++j) { + if(a[k] === a[j]) { a.splice(j--, 1); } + } + } + output.required = a; + } + else if(part === 'x-resolved-from') { + output['x-resolved-from'].push(source); + } + else { + // TODO: need to merge this property + // console.log('what to do with ' + part) + } + } + } + } + obj[key] = output; + } + } + if(_.isObject(item)) { + this.resolveAllOf(spec, item, depth + 1); + } + } +}; + +},{"./http":5,"lodash-compat/lang/cloneDeep":142,"lodash-compat/lang/isArray":144,"lodash-compat/lang/isObject":148}],7:[function(require,module,exports){ +'use strict'; + +var Helpers = require('./helpers'); + +var _ = { + isPlainObject: require('lodash-compat/lang/isPlainObject'), + isUndefined: require('lodash-compat/lang/isUndefined'), + isArray: require('lodash-compat/lang/isArray'), + isObject: require('lodash-compat/lang/isObject'), + isEmpty: require('lodash-compat/lang/isEmpty'), + map: require('lodash-compat/collection/map'), + indexOf: require('lodash-compat/array/indexOf'), + cloneDeep: require('lodash-compat/lang/cloneDeep'), + keys: require('lodash-compat/object/keys'), + forEach: require('lodash-compat/collection/forEach') +}; + +module.exports.optionHtml = optionHtml; +module.exports.typeFromJsonSchema = typeFromJsonSchema; +module.exports.getStringSignature = getStringSignature; +module.exports.schemaToHTML = schemaToHTML; +module.exports.schemaToJSON = schemaToJSON; + +function optionHtml(label, value) { + return '' + label + ':' + value + ''; +} + +function typeFromJsonSchema(type, format) { + var str; + + if (type === 'integer' && format === 'int32') { + str = 'integer'; + } else if (type === 'integer' && format === 'int64') { + str = 'long'; + } else if (type === 'integer' && typeof format === 'undefined') { + str = 'long'; + } else if (type === 'string' && format === 'date-time') { + str = 'date-time'; + } else if (type === 'string' && format === 'date') { + str = 'date'; + } else if (type === 'number' && format === 'float') { + str = 'float'; + } else if (type === 'number' && format === 'double') { + str = 'double'; + } else if (type === 'number' && typeof format === 'undefined') { + str = 'double'; + } else if (type === 'boolean') { + str = 'boolean'; + } else if (type === 'string') { + str = 'string'; + } + + return str; +} + +function getStringSignature(obj, baseComponent) { + var str = ''; + + if (typeof obj.$ref !== 'undefined') { + str += Helpers.simpleRef(obj.$ref); + } else if (typeof obj.type === 'undefined') { + str += 'object'; + } else if (obj.type === 'array') { + if (baseComponent) { + str += getStringSignature((obj.items || obj.$ref || {})); + } else { + str += 'Array['; + str += getStringSignature((obj.items || obj.$ref || {})); + str += ']'; + } + } else if (obj.type === 'integer' && obj.format === 'int32') { + str += 'integer'; + } else if (obj.type === 'integer' && obj.format === 'int64') { + str += 'long'; + } else if (obj.type === 'integer' && typeof obj.format === 'undefined') { + str += 'long'; + } else if (obj.type === 'string' && obj.format === 'date-time') { + str += 'date-time'; + } else if (obj.type === 'string' && obj.format === 'date') { + str += 'date'; + } else if (obj.type === 'string' && typeof obj.format === 'undefined') { + str += 'string'; + } else if (obj.type === 'number' && obj.format === 'float') { + str += 'float'; + } else if (obj.type === 'number' && obj.format === 'double') { + str += 'double'; + } else if (obj.type === 'number' && typeof obj.format === 'undefined') { + str += 'double'; + } else if (obj.type === 'boolean') { + str += 'boolean'; + } else if (obj.$ref) { + str += Helpers.simpleRef(obj.$ref); + } else { + str += obj.type; + } + + return str; +} + +function schemaToJSON(schema, models, modelsToIgnore, modelPropertyMacro) { + // Resolve the schema (Handle nested schemas) + schema = Helpers.resolveSchema(schema); + + if(typeof modelPropertyMacro !== 'function') { + modelPropertyMacro = function(prop){ + return (prop || {}).default; + }; + } + + modelsToIgnore= modelsToIgnore || {}; + + var type = schema.type || 'object'; + var format = schema.format; + var model; + var output; + + if (!_.isUndefined(schema.example)) { + output = schema.example; + } else if (_.isUndefined(schema.items) && _.isArray(schema.enum)) { + output = schema.enum[0]; + } + + if (_.isUndefined(output)) { + if (schema.$ref) { + model = models[Helpers.simpleRef(schema.$ref)]; + + if (!_.isUndefined(model)) { + if (_.isUndefined(modelsToIgnore[model.name])) { + modelsToIgnore[model.name] = model; + output = schemaToJSON(model.definition, models, modelsToIgnore, modelPropertyMacro); + delete modelsToIgnore[model.name]; + } else { + if (model.type === 'array') { + output = []; + } else { + output = {}; + } + } + } + } else if (!_.isUndefined(schema.default)) { + output = schema.default; + } else if (type === 'string') { + if (format === 'date-time') { + output = new Date().toISOString(); + } else if (format === 'date') { + output = new Date().toISOString().split('T')[0]; + } else { + output = 'string'; + } + } else if (type === 'integer') { + output = 0; + } else if (type === 'number') { + output = 0.0; + } else if (type === 'boolean') { + output = true; + } else if (type === 'object') { + output = {}; + + _.forEach(schema.properties, function (property, name) { + var cProperty = _.cloneDeep(property); + + // Allow macro to set the default value + cProperty.default = modelPropertyMacro(property); + + output[name] = schemaToJSON(cProperty, models, modelsToIgnore, modelPropertyMacro); + }); + } else if (type === 'array') { + output = []; + + if (_.isArray(schema.items)) { + _.forEach(schema.items, function (item) { + output.push(schemaToJSON(item, models, modelsToIgnore, modelPropertyMacro)); + }); + } else if (_.isPlainObject(schema.items)) { + output.push(schemaToJSON(schema.items, models, modelsToIgnore, modelPropertyMacro)); + } else if (_.isUndefined(schema.items)) { + output.push({}); + } else { + Helpers.log('Array type\'s \'items\' property is not an array or an object, cannot process'); + } + } + } + + return output; +} + +function schemaToHTML(name, schema, models, modelPropertyMacro) { + + var strongOpen = ''; + var strongClose = ''; + + // Allow for ignoring the 'name' argument.... shifting the rest + if(_.isObject(arguments[0])) { + name = void 0; + schema = arguments[0]; + models = arguments[1]; + modelPropertyMacro = arguments[2]; + } + + models = models || {}; + + // Resolve the schema (Handle nested schemas) + schema = Helpers.resolveSchema(schema); + + // Return for empty object + if(_.isEmpty(schema)) { + return strongOpen + 'Empty' + strongClose; + } + + // Dereference $ref from 'models' + if(typeof schema.$ref === 'string') { + name = Helpers.simpleRef(schema.$ref); + schema = models[name]; + if(typeof schema === 'undefined') + { + return strongOpen + name + ' is not defined!' + strongClose; + } + } + + if(typeof name !== 'string') { + name = schema.title || 'Inline Model'; + } + + // If we are a Model object... adjust accordingly + if(schema.definition) { + schema = schema.definition; + } + + if(typeof modelPropertyMacro !== 'function') { + modelPropertyMacro = function(prop){ + return (prop || {}).default; + }; + } + + var references = {}; + var seenModels = []; + var inlineModels = 0; + + + + // Generate current HTML + var html = processModel(schema, name); + + // Generate references HTML + while (_.keys(references).length > 0) { + /* jshint ignore:start */ + _.forEach(references, function (schema, name) { + var seenModel = _.indexOf(seenModels, name) > -1; + + delete references[name]; + + if (!seenModel) { + seenModels.push(name); + + html += '
      ' + processModel(schema, name); + } + }); + /* jshint ignore:end */ + } + + return html; + + ///////////////////////////////// + + function addReference(schema, name, skipRef) { + var modelName = name; + var model; + + if (schema.$ref) { + modelName = schema.title || Helpers.simpleRef(schema.$ref); + model = models[modelName]; + } else if (_.isUndefined(name)) { + modelName = schema.title || 'Inline Model ' + (++inlineModels); + model = {definition: schema}; + } + + if (skipRef !== true) { + references[modelName] = _.isUndefined(model) ? {} : model.definition; + } + + return modelName; + } + + function primitiveToHTML(schema) { + var html = ''; + var type = schema.type || 'object'; + + if (schema.$ref) { + html += addReference(schema, Helpers.simpleRef(schema.$ref)); + } else if (type === 'object') { + if (!_.isUndefined(schema.properties)) { + html += addReference(schema); + } else { + html += 'object'; + } + } else if (type === 'array') { + html += 'Array['; + + if (_.isArray(schema.items)) { + html += _.map(schema.items, addReference).join(','); + } else if (_.isPlainObject(schema.items)) { + if (_.isUndefined(schema.items.$ref)) { + if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) { + html += schema.items.type; + } else { + html += addReference(schema.items); + } + } else { + html += addReference(schema.items, Helpers.simpleRef(schema.items.$ref)); + } + } else { + Helpers.log('Array type\'s \'items\' schema is not an array or an object, cannot process'); + html += 'object'; + } + + html += ']'; + } else { + html += schema.type; + } + + html += ''; + + return html; + } + + function primitiveToOptionsHTML(schema, html) { + var options = ''; + var type = schema.type || 'object'; + var isArray = type === 'array'; + + if (isArray) { + if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) { + type = schema.items.type; + } else { + type = 'object'; + } + } + + if (!_.isUndefined(schema.default)) { + options += optionHtml('Default', schema.default); + } + + switch (type) { + case 'string': + if (schema.minLength) { + options += optionHtml('Min. Length', schema.minLength); + } + + if (schema.maxLength) { + options += optionHtml('Max. Length', schema.maxLength); + } + + if (schema.pattern) { + options += optionHtml('Reg. Exp.', schema.pattern); + } + break; + case 'integer': + case 'number': + if (schema.minimum) { + options += optionHtml('Min. Value', schema.minimum); + } + + if (schema.exclusiveMinimum) { + options += optionHtml('Exclusive Min.', 'true'); + } + + if (schema.maximum) { + options += optionHtml('Max. Value', schema.maximum); + } + + if (schema.exclusiveMaximum) { + options += optionHtml('Exclusive Max.', 'true'); + } + + if (schema.multipleOf) { + options += optionHtml('Multiple Of', schema.multipleOf); + } + + break; + } + + if (isArray) { + if (schema.minItems) { + options += optionHtml('Min. Items', schema.minItems); + } + + if (schema.maxItems) { + options += optionHtml('Max. Items', schema.maxItems); + } + + if (schema.uniqueItems) { + options += optionHtml('Unique Items', 'true'); + } + + if (schema.collectionFormat) { + options += optionHtml('Coll. Format', schema.collectionFormat); + } + } + + if (_.isUndefined(schema.items)) { + if (_.isArray(schema.enum)) { + var enumString; + + if (type === 'number' || type === 'integer') { + enumString = schema.enum.join(', '); + } else { + enumString = '"' + schema.enum.join('", "') + '"'; + } + + options += optionHtml('Enum', enumString); + } + } + + if (options.length > 0) { + html = '' + html + '' + options + '
      ' + type + '
      '; + } + + return html; + } + + function processModel(schema, name) { + var type = schema.type || 'object'; + var isArray = schema.type === 'array'; + var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose; + + if (name) { + seenModels.push(name); + } + + if (isArray) { + if (_.isArray(schema.items)) { + html += '
      ' + _.map(schema.items, function (item) { + var type = item.type || 'object'; + + if (_.isUndefined(item.$ref)) { + if (_.indexOf(['array', 'object'], type) > -1) { + if (type === 'object' && _.isUndefined(item.properties)) { + return 'object'; + } else { + return addReference(item); + } + } else { + return primitiveToOptionsHTML(item, type); + } + } else { + return addReference(item, Helpers.simpleRef(item.$ref)); + } + }).join(',
      '); + } else if (_.isPlainObject(schema.items)) { + if (_.isUndefined(schema.items.$ref)) { + if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) { + if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) { + html += '
      object
      '; + } else { + html += '
      ' + addReference(schema.items) + '
      '; + } + } else { + html += '
      ' + primitiveToOptionsHTML(schema.items, schema.items.type) + '
      '; + } + } else { + html += '
      ' + addReference(schema.items, Helpers.simpleRef(schema.items.$ref)) + '
      '; + } + } else { + Helpers.log('Array type\'s \'items\' property is not an array or an object, cannot process'); + html += '
      object
      '; + } + } else { + if (schema.$ref) { + html += '
      ' + addReference(schema, name) + '
      '; + } else if (type === 'object') { + if (_.isPlainObject(schema.properties)) { + var contents = _.map(schema.properties, function (property, name) { + var propertyIsRequired = (_.indexOf(schema.required, name) >= 0); + var cProperty = _.cloneDeep(property); + + var requiredClass = propertyIsRequired ? 'required' : ''; + var html = '' + name + ' ('; + var model; + var propDescription; + + // Allow macro to set the default value + cProperty.default = modelPropertyMacro(cProperty); + + // Resolve the schema (Handle nested schemas) + cProperty = Helpers.resolveSchema(cProperty); + + propDescription = property.description || cProperty.description; + + // We need to handle property references to primitives (Issue 339) + if (!_.isUndefined(cProperty.$ref)) { + model = models[Helpers.simpleRef(cProperty.$ref)]; + + if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) { + // Use referenced schema + cProperty = Helpers.resolveSchema(model.definition); + } + } + + html += primitiveToHTML(cProperty); + + if(!propertyIsRequired) { + html += ', optional'; + } + + if(property.readOnly) { + html += ', read only'; + } + + html += ')'; + + if (!_.isUndefined(propDescription)) { + html += ': ' + '' + propDescription + ''; + } + + if (cProperty.enum) { + html += ' = [\'' + cProperty.enum.join('\', \'') + '\']'; + } + + return primitiveToOptionsHTML(cProperty, html); + }).join(',
      '); + } + + if (contents) { + html += contents + '
      '; + } + } else { + html += '
      ' + primitiveToOptionsHTML(schema, type) + '
      '; + } + } + + return html + strongOpen + (isArray ? ']' : '}') + strongClose; + } +} + +},{"./helpers":4,"lodash-compat/array/indexOf":53,"lodash-compat/collection/forEach":58,"lodash-compat/collection/map":60,"lodash-compat/lang/cloneDeep":142,"lodash-compat/lang/isArray":144,"lodash-compat/lang/isEmpty":145,"lodash-compat/lang/isObject":148,"lodash-compat/lang/isPlainObject":149,"lodash-compat/lang/isUndefined":152,"lodash-compat/object/keys":153}],8:[function(require,module,exports){ +'use strict'; + +var SwaggerHttp = require('./http'); +var _ = { + isObject: require('lodash-compat/lang/isObject') +}; + +var SwaggerSpecConverter = module.exports = function () { + this.errors = []; + this.warnings = []; + this.modelMap = {}; +}; + +SwaggerSpecConverter.prototype.setDocumentationLocation = function (location) { + this.docLocation = location; +}; + +/** + * converts a resource listing OR api declaration + **/ +SwaggerSpecConverter.prototype.convert = function (obj, clientAuthorizations, opts, callback) { + // not a valid spec + if(!obj || !Array.isArray(obj.apis)) { + return this.finish(callback, null); + } + this.clientAuthorizations = clientAuthorizations; + + // create a new swagger object to return + var swagger = { swagger: '2.0' }; + + swagger.originalVersion = obj.swaggerVersion; + + // add the info + this.apiInfo(obj, swagger); + + // add security definitions + this.securityDefinitions(obj, swagger); + + // take basePath into account + if (obj.basePath) { + this.setDocumentationLocation(obj.basePath); + } + + // see if this is a single-file swagger definition + var isSingleFileSwagger = false; + var i; + for(i = 0; i < obj.apis.length; i++) { + var api = obj.apis[i]; + if(Array.isArray(api.operations)) { + isSingleFileSwagger = true; + } + } + if(isSingleFileSwagger) { + this.declaration(obj, swagger); + this.finish(callback, swagger); + } + else { + this.resourceListing(obj, swagger, opts, callback); + } +}; + +SwaggerSpecConverter.prototype.declaration = function(obj, swagger) { + var name, i, p, pos; + if(!obj.apis) { + return; + } + + if (obj.basePath.indexOf('http://') === 0) { + p = obj.basePath.substring('http://'.length); + pos = p.indexOf('/'); + if (pos > 0) { + swagger.host = p.substring(0, pos); + swagger.basePath = p.substring(pos); + } + else { + swagger.host = p; + swagger.basePath = '/'; + } + } else if (obj.basePath.indexOf('https://') === 0) { + p = obj.basePath.substring('https://'.length); + pos = p.indexOf('/'); + if (pos > 0) { + swagger.host = p.substring(0, pos); + swagger.basePath = p.substring(pos); + } + else { + swagger.host = p; + swagger.basePath = '/'; + } + } else { + swagger.basePath = obj.basePath; + } + + var resourceLevelAuth; + if(obj.authorizations) { + resourceLevelAuth = obj.authorizations; + } + if(obj.consumes) { + swagger.consumes = obj.consumes; + } + if(obj.produces) { + swagger.produces = obj.produces; + } + + // build a mapping of id to name for 1.0 model resolutions + if(_.isObject(obj)) { + for(name in obj.models) { + var existingModel = obj.models[name]; + var key = (existingModel.id || name); + this.modelMap[key] = name; + } + } + + for(i = 0; i < obj.apis.length; i++) { + var api = obj.apis[i]; + var path = api.path; + var operations = api.operations; + this.operations(path, obj.resourcePath, operations, resourceLevelAuth, swagger); + } + + var models = obj.models || {}; + this.models(models, swagger); +}; + +SwaggerSpecConverter.prototype.models = function(obj, swagger) { + if(!_.isObject(obj)) { + return; + } + var name; + + swagger.definitions = swagger.definitions || {}; + for(name in obj) { + var existingModel = obj[name]; + var _enum = []; + var schema = { properties: {}}; + var propertyName; + for(propertyName in existingModel.properties) { + var existingProperty = existingModel.properties[propertyName]; + var property = {}; + this.dataType(existingProperty, property); + if(existingProperty.description) { + property.description = existingProperty.description; + } + if(existingProperty['enum']) { + property['enum'] = existingProperty['enum']; + } + if(typeof existingProperty.required === 'boolean' && existingProperty.required === true) { + _enum.push(propertyName); + } + if(typeof existingProperty.required === 'string' && existingProperty.required === 'true') { + _enum.push(propertyName); + } + schema.properties[propertyName] = property; + } + if(_enum.length > 0) { + schema['enum'] = _enum; + } + + schema.required = existingModel.required; + swagger.definitions[name] = schema; + } +}; + +SwaggerSpecConverter.prototype.extractTag = function(resourcePath) { + var pathString = resourcePath || 'default'; + if(pathString.indexOf('http:') === 0 || pathString.indexOf('https:') === 0) { + pathString = pathString.split(['/']); + pathString = pathString[pathString.length -1].substring(); + } + if(pathString.endsWith('.json')) { + pathString = pathString.substring(0, pathString.length - '.json'.length); + } + return pathString.replace('/',''); +}; + +SwaggerSpecConverter.prototype.operations = function(path, resourcePath, obj, resourceLevelAuth, swagger) { + if(!Array.isArray(obj)) { + return; + } + var i; + + if(!swagger.paths) { + swagger.paths = {}; + } + + var pathObj = swagger.paths[path] || {}; + var tag = this.extractTag(resourcePath); + swagger.tags = swagger.tags || []; + var matched = false; + for(i = 0; i < swagger.tags.length; i++) { + var tagObject = swagger.tags[i]; + if(tagObject.name === tag) { + matched = true; + } + } + if(!matched) { + swagger.tags.push({name: tag}); + } + + for(i = 0; i < obj.length; i++) { + var existingOperation = obj[i]; + var method = (existingOperation.method || existingOperation.httpMethod).toLowerCase(); + var operation = {tags: [tag]}; + var existingAuthorizations = existingOperation.authorizations; + + if(existingAuthorizations && Object.keys(existingAuthorizations).length === 0) { + existingAuthorizations = resourceLevelAuth; + } + + if(typeof existingAuthorizations !== 'undefined') { + var scopesObject; + for(var key in existingAuthorizations) { + operation.security = operation.security || []; + var scopes = existingAuthorizations[key]; + if(scopes) { + var securityScopes = []; + for(var j in scopes) { + securityScopes.push(scopes[j].scope); + } + scopesObject = {}; + scopesObject[key] = securityScopes; + operation.security.push(scopesObject); + } + else { + scopesObject = {}; + scopesObject[key] = []; + operation.security.push(scopesObject); + } + } + } + + if(existingOperation.consumes) { + operation.consumes = existingOperation.consumes; + } + else if(swagger.consumes) { + operation.consumes = swagger.consumes; + } + if(existingOperation.produces) { + operation.produces = existingOperation.produces; + } + else if(swagger.produces) { + operation.produces = swagger.produces; + } + if(existingOperation.summary) { + operation.summary = existingOperation.summary; + } + if(existingOperation.notes) { + operation.description = existingOperation.notes; + } + if(existingOperation.nickname) { + operation.operationId = existingOperation.nickname; + } + if(existingOperation.deprecated) { + operation.deprecated = existingOperation.deprecated; + } + + this.authorizations(existingAuthorizations, swagger); + this.parameters(operation, existingOperation.parameters, swagger); + this.responseMessages(operation, existingOperation, swagger); + + pathObj[method] = operation; + } + + swagger.paths[path] = pathObj; +}; + +SwaggerSpecConverter.prototype.responseMessages = function(operation, existingOperation) { + if(!_.isObject(existingOperation)) { + return; + } + // build default response from the operation (1.x) + var defaultResponse = {}; + this.dataType(existingOperation, defaultResponse); + // TODO: look into the real problem of rendering responses in swagger-ui + // ....should reponseType have an implicit schema? + if(!defaultResponse.schema && defaultResponse.type) { + defaultResponse = {schema: defaultResponse}; + } + + operation.responses = operation.responses || {}; + + // grab from responseMessages (1.2) + var has200 = false; + if(Array.isArray(existingOperation.responseMessages)) { + var i; + var existingResponses = existingOperation.responseMessages; + for(i = 0; i < existingResponses.length; i++) { + var existingResponse = existingResponses[i]; + var response = { description: existingResponse.message }; + if(existingResponse.code === 200) { + has200 = true; + } + // Convert responseModel -> schema{$ref: responseModel} + if(existingResponse.responseModel) { + response.schema = {'$ref': '#/definitions/' + existingResponse.responseModel}; + } + operation.responses['' + existingResponse.code] = response; + } + } + + if(has200) { + operation.responses['default'] = defaultResponse; + } + else { + operation.responses['200'] = defaultResponse; + } +}; + +SwaggerSpecConverter.prototype.authorizations = function(obj) { + // TODO + if(!_.isObject(obj)) { + return; + } +}; + +SwaggerSpecConverter.prototype.parameters = function(operation, obj) { + if(!Array.isArray(obj)) { + return; + } + var i; + for(i = 0; i < obj.length; i++) { + var existingParameter = obj[i]; + var parameter = {}; + parameter.name = existingParameter.name; + parameter.description = existingParameter.description; + parameter.required = existingParameter.required; + parameter.in = existingParameter.paramType; + + // per #168 + if(parameter.in === 'body') { + parameter.name = 'body'; + } + if(parameter.in === 'form') { + parameter.in = 'formData'; + } + + if(existingParameter.enum) { + parameter.enum = existingParameter.enum; + } + + if(existingParameter.allowMultiple === true || existingParameter.allowMultiple === 'true') { + var innerType = {}; + this.dataType(existingParameter, innerType); + parameter.type = 'array'; + parameter.items = innerType; + + if(existingParameter.allowableValues) { + var av = existingParameter.allowableValues; + if(av.valueType === 'LIST') { + parameter['enum'] = av.values; + } + } + } + else { + this.dataType(existingParameter, parameter); + } + if(typeof existingParameter.defaultValue !== 'undefined') { + parameter.default = existingParameter.defaultValue; + } + + operation.parameters = operation.parameters || []; + operation.parameters.push(parameter); + } +}; + +SwaggerSpecConverter.prototype.dataType = function(source, target) { + if(!_.isObject(source)) { + return; + } + + if(source.minimum) { + target.minimum = source.minimum; + } + if(source.maximum) { + target.maximum = source.maximum; + } + if (source.format) { + target.format = source.format; + } + + // default can be 'false' + if(typeof source.defaultValue !== 'undefined') { + target.default = source.defaultValue; + } + + var jsonSchemaType = this.toJsonSchema(source); + if(jsonSchemaType) { + target = target || {}; + if(jsonSchemaType.type) { + target.type = jsonSchemaType.type; + } + if(jsonSchemaType.format) { + target.format = jsonSchemaType.format; + } + if(jsonSchemaType.$ref) { + target.schema = {$ref: jsonSchemaType.$ref}; + } + if(jsonSchemaType.items) { + target.items = jsonSchemaType.items; + } + } +}; + +SwaggerSpecConverter.prototype.toJsonSchema = function(source) { + if(!source) { + return 'object'; + } + var detectedType = (source.type || source.dataType || source.responseClass || ''); + var lcType = detectedType.toLowerCase(); + var format = (source.format || '').toLowerCase(); + + if(lcType.indexOf('list[') === 0) { + var innerType = detectedType.substring(5, detectedType.length - 1); + var jsonType = this.toJsonSchema({type: innerType}); + return {type: 'array', items: jsonType}; + } else if(lcType === 'int' || (lcType === 'integer' && format === 'int32')) { + {return {type: 'integer', format: 'int32'};} + } else if(lcType === 'long' || (lcType === 'integer' && format === 'int64')) { + {return {type: 'integer', format: 'int64'};} + } else if(lcType === 'integer') { + {return {type: 'integer', format: 'int64'};} + } else if(lcType === 'float' || (lcType === 'number' && format === 'float')) { + {return {type: 'number', format: 'float'};} + } else if(lcType === 'double' || (lcType === 'number' && format === 'double')) { + {return {type: 'number', format: 'double'};} + } else if((lcType === 'string' && format === 'date-time') || (lcType === 'date')) { + {return {type: 'string', format: 'date-time'};} + } else if(lcType === 'string') { + {return {type: 'string'};} + } else if(lcType === 'file') { + {return {type: 'file'};} + } else if(lcType === 'boolean') { + {return {type: 'boolean'};} + } else if(lcType === 'boolean') { + {return {type: 'boolean'};} + } else if(lcType === 'array' || lcType === 'list') { + if(source.items) { + var it = this.toJsonSchema(source.items); + return {type: 'array', items: it}; + } + else { + return {type: 'array', items: {type: 'object'}}; + } + } else if(source.$ref) { + return {$ref: this.modelMap[source.$ref] ? '#/definitions/' + this.modelMap[source.$ref] : source.$ref}; + } else if(lcType === 'void' || lcType === '') { + {return {};} + } else if (this.modelMap[source.type]) { + // If this a model using `type` instead of `$ref`, that's fine. + return {$ref: '#/definitions/' + this.modelMap[source.type]}; + } else { + // Unknown model type or 'object', pass it along. + return {type: source.type}; + } +}; + +SwaggerSpecConverter.prototype.resourceListing = function(obj, swagger, opts, callback) { + var i; + var processedCount = 0; // jshint ignore:line + var self = this; // jshint ignore:line + var expectedCount = obj.apis.length; + var _swagger = swagger; // jshint ignore:line + var _opts = {}; + + if(opts && opts.requestInterceptor){ + _opts.requestInterceptor = opts.requestInterceptor; + } + + if(opts && opts.responseInterceptor){ + _opts.responseInterceptor = opts.responseInterceptor; + } + + if(expectedCount === 0) { + this.finish(callback, swagger); + } + + for(i = 0; i < expectedCount; i++) { + var api = obj.apis[i]; + var path = api.path; + var absolutePath = this.getAbsolutePath(obj.swaggerVersion, this.docLocation, path); + + if(api.description) { + swagger.tags = swagger.tags || []; + swagger.tags.push({ + name : this.extractTag(api.path), + description : api.description || '' + }); + } + var http = { + url: absolutePath, + headers: {accept: 'application/json'}, + on: {}, + method: 'get' + }; + /* jshint ignore:start */ + http.on.response = function(data) { + processedCount += 1; + var obj = data.obj; + if(obj) { + self.declaration(obj, _swagger); + } + if(processedCount === expectedCount) { + self.finish(callback, _swagger); + } + }; + http.on.error = function(data) { + console.error(data); + processedCount += 1; + if(processedCount === expectedCount) { + self.finish(callback, _swagger); + } + }; + /* jshint ignore:end */ + + if(this.clientAuthorizations && typeof this.clientAuthorizations.apply === 'function') { + this.clientAuthorizations.apply(http); + } + + new SwaggerHttp().execute(http, _opts); + } +}; + +SwaggerSpecConverter.prototype.getAbsolutePath = function(version, docLocation, path) { + if(version === '1.0') { + if(docLocation.endsWith('.json')) { + // get root path + var pos = docLocation.lastIndexOf('/'); + if(pos > 0) { + docLocation = docLocation.substring(0, pos); + } + } + } + + var location = docLocation; + if(path.indexOf('http://') === 0 || path.indexOf('https://') === 0) { + location = path; + } + else { + if(docLocation.endsWith('/')) { + location = docLocation.substring(0, docLocation.length - 1); + } + location += path; + } + location = location.replace('{format}', 'json'); + return location; +}; + +SwaggerSpecConverter.prototype.securityDefinitions = function(obj, swagger) { + if(obj.authorizations) { + var name; + for(name in obj.authorizations) { + var isValid = false; + var securityDefinition = {}; + var definition = obj.authorizations[name]; + if(definition.type === 'apiKey') { + securityDefinition.type = 'apiKey'; + securityDefinition.in = definition.passAs; + securityDefinition.name = definition.keyname || name; + isValid = true; + } + else if(definition.type === 'basicAuth') { + securityDefinition.type = 'basicAuth'; + isValid = true; + } + else if(definition.type === 'oauth2') { + var existingScopes = definition.scopes || []; + var scopes = {}; + var i; + for(i in existingScopes) { + var scope = existingScopes[i]; + scopes[scope.scope] = scope.description; + } + securityDefinition.type = 'oauth2'; + if(i > 0) { + securityDefinition.scopes = scopes; + } + if(definition.grantTypes) { + if(definition.grantTypes.implicit) { + var implicit = definition.grantTypes.implicit; + securityDefinition.flow = 'implicit'; + securityDefinition.authorizationUrl = implicit.loginEndpoint; + isValid = true; + } + /* jshint ignore:start */ + if(definition.grantTypes['authorization_code']) { + if(!securityDefinition.flow) { + // cannot set if flow is already defined + var authCode = definition.grantTypes['authorization_code']; + securityDefinition.flow = 'accessCode'; + securityDefinition.authorizationUrl = authCode.tokenRequestEndpoint.url; + securityDefinition.tokenUrl = authCode.tokenEndpoint.url; + isValid = true; + } + } + /* jshint ignore:end */ + } + } + if(isValid) { + swagger.securityDefinitions = swagger.securityDefinitions || {}; + swagger.securityDefinitions[name] = securityDefinition; + } + } + } +}; + +SwaggerSpecConverter.prototype.apiInfo = function(obj, swagger) { + // info section + if(obj.info) { + var info = obj.info; + swagger.info = {}; + + if(info.contact) { + swagger.info.contact = {}; + swagger.info.contact.email = info.contact; + } + if(info.description) { + swagger.info.description = info.description; + } + if(info.title) { + swagger.info.title = info.title; + } + if(info.termsOfServiceUrl) { + swagger.info.termsOfService = info.termsOfServiceUrl; + } + if(info.license || info.licenseUrl) { + swagger.license = {}; + if(info.license) { + swagger.license.name = info.license; + } + if(info.licenseUrl) { + swagger.license.url = info.licenseUrl; + } + } + } + else { + this.warnings.push('missing info section'); + } +}; + +SwaggerSpecConverter.prototype.finish = function (callback, obj) { + callback(obj); +}; + +},{"./http":5,"lodash-compat/lang/isObject":148}],9:[function(require,module,exports){ +'use strict'; + +var _ = { + isPlainObject: require('lodash-compat/lang/isPlainObject'), + isString: require('lodash-compat/lang/isString'), +}; + +var SchemaMarkup = require('../schema-markup.js'); +var jsyaml = require('js-yaml'); + +var Model = module.exports = function (name, definition, models, modelPropertyMacro) { + this.definition = definition || {}; + this.isArray = definition.type === 'array'; + this.models = models || {}; + this.name = definition.title || name || 'Inline Model'; + this.modelPropertyMacro = modelPropertyMacro || function (property) { + return property.default; + }; + + return this; +}; + +Model.prototype.createJSONSample = Model.prototype.getSampleValue = function (modelsToIgnore) { + modelsToIgnore = modelsToIgnore || {}; + + modelsToIgnore[this.name] = this; + + // Response support + if (this.examples && _.isPlainObject(this.examples) && this.examples['application/json']) { + this.definition.example = this.examples['application/json']; + + if (_.isString(this.definition.example)) { + this.definition.example = jsyaml.safeLoad(this.definition.example); + } + } else if (!this.definition.example) { + this.definition.example = this.examples; + } + + return SchemaMarkup.schemaToJSON(this.definition, this.models, modelsToIgnore, this.modelPropertyMacro); +}; + +Model.prototype.getMockSignature = function () { + return SchemaMarkup.schemaToHTML(this.name, this.definition, this.models, this.modelPropertyMacro); +}; + +},{"../schema-markup.js":7,"js-yaml":20,"lodash-compat/lang/isPlainObject":149,"lodash-compat/lang/isString":150}],10:[function(require,module,exports){ +'use strict'; + +var _ = { + cloneDeep: require('lodash-compat/lang/cloneDeep'), + isUndefined: require('lodash-compat/lang/isUndefined'), + isEmpty: require('lodash-compat/lang/isEmpty'), + isObject: require('lodash-compat/lang/isObject') +}; +var helpers = require('../helpers'); +var Model = require('./model'); +var SwaggerHttp = require('../http'); +var Q = require('q'); + +var Operation = module.exports = function (parent, scheme, operationId, httpMethod, path, args, definitions, models, clientAuthorizations) { + var errors = []; + + parent = parent || {}; + args = args || {}; + + if(parent && parent.options) { + this.client = parent.options.client || null; + this.requestInterceptor = parent.options.requestInterceptor || null; + this.responseInterceptor = parent.options.responseInterceptor || null; + } + this.authorizations = args.security; + this.basePath = parent.basePath || '/'; + this.clientAuthorizations = clientAuthorizations; + this.consumes = args.consumes || parent.consumes || ['application/json']; + this.produces = args.produces || parent.produces || ['application/json']; + this.deprecated = args.deprecated; + this.description = args.description; + this.host = parent.host || 'localhost'; + this.method = (httpMethod || errors.push('Operation ' + operationId + ' is missing method.')); + this.models = models || {}; + this.nickname = (operationId || errors.push('Operations must have a nickname.')); + this.operation = args; + this.operations = {}; + this.parameters = args !== null ? (args.parameters || []) : {}; + this.parent = parent; + this.path = (path || errors.push('Operation ' + this.nickname + ' is missing path.')); + this.responses = (args.responses || {}); + this.scheme = scheme || parent.scheme || 'http'; + this.schemes = args.schemes || parent.schemes; + this.security = args.security; + this.summary = args.summary || ''; + this.type = null; + this.useJQuery = parent.useJQuery; + this.enableCookies = parent.enableCookies; + this.parameterMacro = parent.parameterMacro || function (operation, parameter) { + return parameter.default; + }; + + this.inlineModels = []; + + if (typeof this.deprecated === 'string') { + switch(this.deprecated.toLowerCase()) { + case 'true': case 'yes': case '1': { + this.deprecated = true; + break; + } + + case 'false': case 'no': case '0': case null: { + this.deprecated = false; + break; + } + + default: this.deprecated = Boolean(this.deprecated); + } + } + + var i, model; + + if (definitions) { + // add to global models + var key; + + for (key in definitions) { + model = new Model(key, definitions[key], this.models, parent.modelPropertyMacro); + + if (model) { + this.models[key] = model; + } + } + } + else { + definitions = {}; + } + + for (i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + + // Allow macro to set the default value + param.default = this.parameterMacro(this, param); + + if (param.type === 'array') { + param.isList = true; + param.allowMultiple = true; + // the enum can be defined at the items level + //if (param.items && param.items.enum) { + // param['enum'] = param.items.enum; + //} + } + + var innerType = this.getType(param); + + if (innerType && innerType.toString().toLowerCase() === 'boolean') { + param.allowableValues = {}; + param.isList = true; + param['enum'] = [true, false]; // use actual primitives + } + + if(typeof param['x-example'] !== 'undefined') { + var d = param['x-example']; + param.default = d; + } + if(param['x-examples']) { + var d = param['x-examples'].default; + if(typeof d !== 'undefined') { + param.default = d; + } + } + + if (typeof param['enum'] !== 'undefined') { + var id; + + param.allowableValues = {}; + param.allowableValues.values = []; + param.allowableValues.descriptiveValues = []; + + for (id = 0; id < param['enum'].length; id++) { + var value = param['enum'][id]; + var isDefault = (value === param.default || value+'' === param.default); + + param.allowableValues.values.push(value); + // Always have string for descriptive values.... + param.allowableValues.descriptiveValues.push({value : value+'', isDefault: isDefault}); + } + } + + if (param.type === 'array') { + innerType = [innerType]; + + if (typeof param.allowableValues === 'undefined') { + // can't show as a list if no values to select from + delete param.isList; + delete param.allowMultiple; + } + } + + param.signature = this.getModelSignature(innerType, this.models).toString(); + param.sampleJSON = this.getModelSampleJSON(innerType, this.models); + param.responseClassSignature = param.signature; + } + + var defaultResponseCode, response, responses = this.responses; + + if (responses['200']) { + response = responses['200']; + defaultResponseCode = '200'; + } else if (responses['201']) { + response = responses['201']; + defaultResponseCode = '201'; + } else if (responses['202']) { + response = responses['202']; + defaultResponseCode = '202'; + } else if (responses['203']) { + response = responses['203']; + defaultResponseCode = '203'; + } else if (responses['204']) { + response = responses['204']; + defaultResponseCode = '204'; + } else if (responses['205']) { + response = responses['205']; + defaultResponseCode = '205'; + } else if (responses['206']) { + response = responses['206']; + defaultResponseCode = '206'; + } else if (responses['default']) { + response = responses['default']; + defaultResponseCode = 'default'; + } + + if (response && response.schema) { + var resolvedModel = this.resolveModel(response.schema, definitions); + var successResponse; + + delete responses[defaultResponseCode]; + + if (resolvedModel) { + this.successResponse = {}; + successResponse = this.successResponse[defaultResponseCode] = resolvedModel; + } else if (!response.schema.type || response.schema.type === 'object' || response.schema.type === 'array') { + // Inline model + this.successResponse = {}; + successResponse = this.successResponse[defaultResponseCode] = new Model(undefined, response.schema || {}, this.models, parent.modelPropertyMacro); + } else { + // Primitive + this.successResponse = {}; + successResponse = this.successResponse[defaultResponseCode] = response.schema; + } + + if (successResponse) { + // Attach response properties + if (response.description) { + successResponse.description = response.description; + } + + if (response.examples) { + successResponse.examples = response.examples; + } + + if (response.headers) { + successResponse.headers = response.headers; + } + } + + this.type = response; + } + + if (errors.length > 0) { + if (this.resource && this.resource.api && this.resource.api.fail) { + this.resource.api.fail(errors); + } + } + + return this; +}; + +Operation.prototype.isDefaultArrayItemValue = function(value, param) { + if (param.default && Array.isArray(param.default)) { + return param.default.indexOf(value) !== -1; + } + return value === param.default; +}; + +Operation.prototype.getType = function (param) { + var type = param.type; + var format = param.format; + var isArray = false; + var str; + + if (type === 'integer' && format === 'int32') { + str = 'integer'; + } else if (type === 'integer' && format === 'int64') { + str = 'long'; + } else if (type === 'integer') { + str = 'integer'; + } else if (type === 'string') { + if (format === 'date-time') { + str = 'date-time'; + } else if (format === 'date') { + str = 'date'; + } else { + str = 'string'; + } + } else if (type === 'number' && format === 'float') { + str = 'float'; + } else if (type === 'number' && format === 'double') { + str = 'double'; + } else if (type === 'number') { + str = 'double'; + } else if (type === 'boolean') { + str = 'boolean'; + } else if (type === 'array') { + isArray = true; + + if (param.items) { + str = this.getType(param.items); + } + } else if (type === 'file') { + str = 'file'; + } + + if (param.$ref) { + str = helpers.simpleRef(param.$ref); + } + + var schema = param.schema; + + if (schema) { + var ref = schema.$ref; + + if (ref) { + ref = helpers.simpleRef(ref); + + if (isArray) { + return [ ref ]; + } else { + return ref; + } + } else { + // If inline schema, we add it our interal hash -> which gives us it's ID (int) + if(schema.type === 'object') { + return this.addInlineModel(schema); + } + return this.getType(schema); + } + } + if (isArray) { + return [ str ]; + } else { + return str; + } +}; + +/** + * adds an inline schema (model) to a hash, where we can ref it later + * @param {object} schema a schema + * @return {number} the ID of the schema being added, or null + **/ +Operation.prototype.addInlineModel = function (schema) { + var len = this.inlineModels.length; + var model = this.resolveModel(schema, {}); + if(model) { + this.inlineModels.push(model); + return 'Inline Model '+len; // return string ref of the inline model (used with #getInlineModel) + } + return null; // report errors? +}; + +/** + * gets the internal ref to an inline model + * @param {string} inline_str a string reference to an inline model + * @return {Model} the model being referenced. Or null + **/ +Operation.prototype.getInlineModel = function(inlineStr) { + if(/^Inline Model \d+$/.test(inlineStr)) { + var id = parseInt(inlineStr.substr('Inline Model'.length).trim(),10); // + var model = this.inlineModels[id]; + return model; + } + // I'm returning null here, should I rather throw an error? + return null; +}; + +Operation.prototype.resolveModel = function (schema, definitions) { + if (typeof schema.$ref !== 'undefined') { + var ref = schema.$ref; + + if (ref.indexOf('#/definitions/') === 0) { + ref = ref.substring('#/definitions/'.length); + } + + if (definitions[ref]) { + return new Model(ref, definitions[ref], this.models, this.parent.modelPropertyMacro); + } + // schema must at least be an object to get resolved to an inline Model + } else if (schema && typeof schema === 'object' && + (schema.type === 'object' || _.isUndefined(schema.type))) { + return new Model(undefined, schema, this.models, this.parent.modelPropertyMacro); + } + + return null; +}; + +Operation.prototype.help = function (dontPrint) { + var out = this.nickname + ': ' + this.summary + '\n'; + + for (var i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + var typeInfo = param.signature; + + out += '\n * ' + param.name + ' (' + typeInfo + '): ' + param.description; + } + + if (typeof dontPrint === 'undefined') { + helpers.log(out); + } + + return out; +}; + +Operation.prototype.getModelSignature = function (type, definitions) { + var isPrimitive, listType; + + if (type instanceof Array) { + listType = true; + type = type[0]; + } + + // Convert undefined to string of 'undefined' + if (typeof type === 'undefined') { + type = 'undefined'; + isPrimitive = true; + + } else if (definitions[type]){ + // a model def exists? + type = definitions[type]; /* Model */ + isPrimitive = false; + + } else if (this.getInlineModel(type)) { + type = this.getInlineModel(type); /* Model */ + isPrimitive = false; + + } else { + // We default to primitive + isPrimitive = true; + } + + if (isPrimitive) { + if (listType) { + return 'Array[' + type + ']'; + } else { + return type.toString(); + } + } else { + if (listType) { + return 'Array[' + type.getMockSignature() + ']'; + } else { + return type.getMockSignature(); + } + } +}; + +Operation.prototype.supportHeaderParams = function () { + return true; +}; + +Operation.prototype.supportedSubmitMethods = function () { + return this.parent.supportedSubmitMethods; +}; + +Operation.prototype.getHeaderParams = function (args) { + var headers = this.setContentTypes(args, {}); + + for (var i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + + if (typeof args[param.name] !== 'undefined') { + if (param.in === 'header') { + var value = args[param.name]; + + if (Array.isArray(value)) { + value = value.toString(); + } + + headers[param.name] = value; + } + } + } + + return headers; +}; + +Operation.prototype.urlify = function (args) { + var formParams = {}; + var requestUrl = this.path; + var querystring = ''; // grab params from the args, build the querystring along the way + + for (var i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + + if (typeof args[param.name] !== 'undefined') { + if (param.in === 'path') { + var reg = new RegExp('\{' + param.name + '\}', 'gi'); + var value = args[param.name]; + + if (Array.isArray(value)) { + value = this.encodePathCollection(param.collectionFormat, param.name, value); + } else { + value = this.encodePathParam(value); + } + + requestUrl = requestUrl.replace(reg, value); + } else if (param.in === 'query' && typeof args[param.name] !== 'undefined') { + if (querystring === '') { + querystring += '?'; + } else { + querystring += '&'; + } + + if (typeof param.collectionFormat !== 'undefined') { + var qp = args[param.name]; + + if (Array.isArray(qp)) { + querystring += this.encodeQueryCollection(param.collectionFormat, param.name, qp); + } else { + querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]); + } + } else { + querystring += this.encodeQueryParam(param.name) + '=' + this.encodeQueryParam(args[param.name]); + } + } else if (param.in === 'formData') { + formParams[param.name] = args[param.name]; + } + } + } + var url = this.scheme + '://' + this.host; + + if (this.basePath !== '/') { + url += this.basePath; + } + return url + requestUrl + querystring; +}; + +Operation.prototype.getMissingParams = function (args) { + var missingParams = []; // check required params, track the ones that are missing + var i; + + for (i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + + if (param.required === true) { + if (typeof args[param.name] === 'undefined') { + missingParams = param.name; + } + } + } + + return missingParams; +}; + +Operation.prototype.getBody = function (headers, args, opts) { + var formParams = {}, hasFormParams, body, key, value, hasBody = false; + + // look at each param and put form params in an object + for (var i = 0; i < this.parameters.length; i++) { + var param = this.parameters[i]; + if (typeof args[param.name] !== 'undefined') { + if (param.in === 'body') { + body = args[param.name]; + } else if (param.in === 'formData') { + formParams[param.name] = args[param.name]; + hasFormParams = true; + } + } + else { + if(param.in === 'body') { + hasBody = true; + } + } + } + + // if body is null and hasBody is true, AND a JSON body is requested, send empty {} + if(hasBody && typeof body === 'undefined') { + var contentType = headers['Content-Type']; + if(contentType && contentType.indexOf('application/json') === 0) { + body = '{}'; + } + } + + var isMultiPart = false; + if(headers['Content-Type'] && headers['Content-Type'].indexOf('multipart/form-data') >= 0) { + isMultiPart = true; + } + + // handle form params + if (hasFormParams && !isMultiPart) { + var encoded = ''; + + for (key in formParams) { + value = formParams[key]; + + if (typeof value !== 'undefined') { + if (encoded !== '') { + encoded += '&'; + } + + encoded += encodeURIComponent(key) + '=' + encodeURIComponent(value); + } + } + + body = encoded; + } else if (isMultiPart) { + if (opts.useJQuery) { + var bodyParam = new FormData(); + + bodyParam.type = 'formData'; + + for (key in formParams) { + value = args[key]; + + if (typeof value !== 'undefined') { + // required for jquery file upload + if (value.type === 'file' && value.value) { + delete headers['Content-Type']; + + bodyParam.append(key, value.value); + } else { + bodyParam.append(key, value); + } + } + } + + body = bodyParam; + } + } + + return body; +}; + +/** + * gets sample response for a single operation + **/ +Operation.prototype.getModelSampleJSON = function (type, models) { + var listType, sampleJson, innerType; + models = models || {}; + + listType = (type instanceof Array); + innerType = listType ? type[0] : type; + + if(models[innerType]) { + sampleJson = models[innerType].createJSONSample(); + } else if (this.getInlineModel(innerType)){ + sampleJson = this.getInlineModel(innerType).createJSONSample(); // may return null, if type isn't correct + } + + + if (sampleJson) { + sampleJson = listType ? [sampleJson] : sampleJson; + + if (typeof sampleJson === 'string') { + return sampleJson; + } else if (_.isObject(sampleJson)) { + var t = sampleJson; + + if (sampleJson instanceof Array && sampleJson.length > 0) { + t = sampleJson[0]; + } + + if (t.nodeName && typeof t === 'Node') { + var xmlString = new XMLSerializer().serializeToString(t); + + return this.formatXml(xmlString); + } else { + return JSON.stringify(sampleJson, null, 2); + } + } else { + return sampleJson; + } + } +}; + +/** + * legacy binding + **/ +Operation.prototype.do = function (args, opts, callback, error, parent) { + return this.execute(args, opts, callback, error, parent); +}; + +/** + * executes an operation + **/ +Operation.prototype.execute = function (arg1, arg2, arg3, arg4, parent) { + var args = arg1 || {}; + var opts = {}, success, error, deferred; + + if (_.isObject(arg2)) { + opts = arg2; + success = arg3; + error = arg4; + } + + if(this.client) { + opts.client = this.client; + } + + // add the request interceptor from parent, if none sent from client + if(!opts.requestInterceptor && this.requestInterceptor ) { + opts.requestInterceptor = this.requestInterceptor ; + } + + if(!opts.responseInterceptor && this.responseInterceptor) { + opts.responseInterceptor = this.responseInterceptor; + } + + if (typeof arg2 === 'function') { + success = arg2; + error = arg3; + } + + if (this.parent.usePromise) { + deferred = Q.defer(); + } else { + success = (success || this.parent.defaultSuccessCallback || helpers.log); + error = (error || this.parent.defaultErrorCallback || helpers.log); + } + + + if (typeof opts.useJQuery === 'undefined') { + opts.useJQuery = this.useJQuery; + } + + if (typeof opts.enableCookies === 'undefined') { + opts.enableCookies = this.enableCookies; + } + + var missingParams = this.getMissingParams(args); + + if (missingParams.length > 0) { + var message = 'missing required params: ' + missingParams; + + helpers.fail(message); + + if (this.parent.usePromise) { + deferred.reject(message); + return deferred.promise; + } else { + error(message, parent); + return {}; + } + } + + var allHeaders = this.getHeaderParams(args); + var contentTypeHeaders = this.setContentTypes(args, opts); + var headers = {}, attrname; + + for (attrname in allHeaders) { headers[attrname] = allHeaders[attrname]; } + for (attrname in contentTypeHeaders) { headers[attrname] = contentTypeHeaders[attrname]; } + + var body = this.getBody(contentTypeHeaders, args, opts); + var url = this.urlify(args); + + if(url.indexOf('.{format}') > 0) { + if(headers) { + var format = headers.Accept || headers.accept; + if(format && format.indexOf('json') > 0) { + url = url.replace('.{format}', '.json'); + } + else if(format && format.indexOf('xml') > 0) { + url = url.replace('.{format}', '.xml'); + } + } + } + + var obj = { + url: url, + method: this.method.toUpperCase(), + body: body, + enableCookies: opts.enableCookies, + useJQuery: opts.useJQuery, + deferred: deferred, + headers: headers, + on: { + response: function (response) { + if (deferred) { + deferred.resolve(response); + return deferred.promise; + } else { + return success(response, parent); + } + }, + error: function (response) { + if (deferred) { + deferred.reject(response); + return deferred.promise; + } else { + return error(response, parent); + } + } + } + }; + + this.clientAuthorizations.apply(obj, this.operation.security); + if (opts.mock === true) { + return obj; + } else { + return new SwaggerHttp().execute(obj, opts); + } +}; + +function itemByPriority(col, itemPriority) { + + // No priorities? return first... + if(_.isEmpty(itemPriority)) { + return col[0]; + } + + for (var i = 0, len = itemPriority.length; i < len; i++) { + if(col.indexOf(itemPriority[i]) > -1) { + return itemPriority[i]; + } + } + + // Otherwise return first + return col[0]; +} + +Operation.prototype.setContentTypes = function (args, opts) { + // default type + var allDefinedParams = this.parameters; + var body; + var consumes = args.parameterContentType || itemByPriority(this.consumes, ['application/json', 'application/yaml']); + var accepts = opts.responseContentType || itemByPriority(this.produces, ['application/json', 'application/yaml']); + var definedFileParams = []; + var definedFormParams = []; + var headers = {}; + var i; + + // get params from the operation and set them in definedFileParams, definedFormParams, headers + for (i = 0; i < allDefinedParams.length; i++) { + var param = allDefinedParams[i]; + + if (param.in === 'formData') { + if (param.type === 'file') { + definedFileParams.push(param); + } else { + definedFormParams.push(param); + } + } else if (param.in === 'header' && opts) { + var key = param.name; + var headerValue = opts[param.name]; + + if (typeof opts[param.name] !== 'undefined') { + headers[key] = headerValue; + } + } else if (param.in === 'body' && typeof args[param.name] !== 'undefined') { + body = args[param.name]; + } + } + + // if there's a body, need to set the consumes header via requestContentType + if (this.method === 'post' || this.method === 'put' || this.method === 'patch' || + ((this.method === 'delete' || this.method === 'get') && body) ) { + if (opts.requestContentType) { + consumes = opts.requestContentType; + } + // if any form params, content type must be set + if (definedFormParams.length > 0) { + if (opts.requestContentType) { // override if set + consumes = opts.requestContentType; + } else if (definedFileParams.length > 0) { // if a file, must be multipart/form-data + consumes = 'multipart/form-data'; + } else { // default to x-www-from-urlencoded + consumes = 'application/x-www-form-urlencoded'; + } + } + } + else { + consumes = null; + } + + if (consumes && this.consumes) { + if (this.consumes.indexOf(consumes) === -1) { + helpers.log('server doesn\'t consume ' + consumes + ', try ' + JSON.stringify(this.consumes)); + } + } + + if (!this.matchesAccept(accepts)) { + helpers.log('server can\'t produce ' + accepts); + } + + if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded')) { + headers['Content-Type'] = consumes; + } + + if (accepts) { + headers.Accept = accepts; + } + + return headers; +}; + +/** + * Returns true if the request accepts header matches anything in this.produces. + * If this.produces contains * / *, ignore the accept header. + * @param {string=} accepts The client request accept header. + * @return {boolean} + */ +Operation.prototype.matchesAccept = function(accepts) { + // no accepts or produces, no problem! + if (!accepts || !this.produces) { + return true; + } + return this.produces.indexOf(accepts) !== -1 || this.produces.indexOf('*/*') !== -1; +}; + +Operation.prototype.asCurl = function (args1, args2) { + var opts = {mock: true}; + if (typeof args2 === 'object') { + for (var argKey in args2) { + opts[argKey] = args2[argKey]; + } + } + var obj = this.execute(args1, opts); + + this.clientAuthorizations.apply(obj, this.operation.security); + + var results = []; + + results.push('-X ' + this.method.toUpperCase()); + + if (typeof obj.headers !== 'undefined') { + var key; + + for (key in obj.headers) { + var value = obj.headers[key]; + if(typeof value === 'string'){ + value = value.replace(/\'/g, '\\u0027'); + } + results.push('--header \'' + key + ': ' + value + '\''); + } + } + + if (obj.body) { + var body; + + if (_.isObject(obj.body)) { + body = JSON.stringify(obj.body); + } else { + body = obj.body; + } + + results.push('-d \'' + body.replace(/\'/g, '\\u0027') + '\''); + } + + return 'curl ' + (results.join(' ')) + ' \'' + obj.url + '\''; +}; + +Operation.prototype.encodePathCollection = function (type, name, value) { + var encoded = ''; + var i; + var separator = ''; + + if (type === 'ssv') { + separator = '%20'; + } else if (type === 'tsv') { + separator = '\\t'; + } else if (type === 'pipes') { + separator = '|'; + } else { + separator = ','; + } + + for (i = 0; i < value.length; i++) { + if (i === 0) { + encoded = this.encodeQueryParam(value[i]); + } else { + encoded += separator + this.encodeQueryParam(value[i]); + } + } + + return encoded; +}; + +Operation.prototype.encodeQueryCollection = function (type, name, value) { + var encoded = ''; + var i; + + if (type === 'default' || type === 'multi') { + for (i = 0; i < value.length; i++) { + if (i > 0) {encoded += '&';} + + encoded += this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]); + } + } else { + var separator = ''; + + if (type === 'csv') { + separator = ','; + } else if (type === 'ssv') { + separator = '%20'; + } else if (type === 'tsv') { + separator = '\\t'; + } else if (type === 'pipes') { + separator = '|'; + } else if (type === 'brackets') { + for (i = 0; i < value.length; i++) { + if (i !== 0) { + encoded += '&'; + } + + encoded += this.encodeQueryParam(name) + '[]=' + this.encodeQueryParam(value[i]); + } + } + + if (separator !== '') { + for (i = 0; i < value.length; i++) { + if (i === 0) { + encoded = this.encodeQueryParam(name) + '=' + this.encodeQueryParam(value[i]); + } else { + encoded += separator + this.encodeQueryParam(value[i]); + } + } + } + } + + return encoded; +}; + +Operation.prototype.encodeQueryParam = function (arg) { + return encodeURIComponent(arg); +}; + +/** + * TODO revisit, might not want to leave '/' + **/ +Operation.prototype.encodePathParam = function (pathParam) { + return encodeURIComponent(pathParam); +}; + +},{"../helpers":4,"../http":5,"./model":9,"lodash-compat/lang/cloneDeep":142,"lodash-compat/lang/isEmpty":145,"lodash-compat/lang/isObject":148,"lodash-compat/lang/isUndefined":152,"q":161}],11:[function(require,module,exports){ +'use strict'; + +var OperationGroup = module.exports = function (tag, description, externalDocs, operation) { + this.description = description; + this.externalDocs = externalDocs; + this.name = tag; + this.operation = operation; + this.operationsArray = []; + this.path = tag; + this.tag = tag; +}; + +OperationGroup.prototype.sort = function () { + +}; + + +},{}],12:[function(require,module,exports){ + +},{}],13:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; +var queue = []; +var draining = false; + +function drainQueue() { + if (draining) { + return; + } + draining = true; + var currentQueue; + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + var i = -1; + while (++i < len) { + currentQueue[i](); + } + len = queue.length; + } + draining = false; +} +process.nextTick = function (fun) { + queue.push(fun); + if (!draining) { + setTimeout(drainQueue, 0); + } +}; + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],14:[function(require,module,exports){ +(function (Buffer){ +(function () { + "use strict"; + + function btoa(str) { + var buffer + ; + + if (str instanceof Buffer) { + buffer = str; + } else { + buffer = new Buffer(str.toString(), 'binary'); + } + + return buffer.toString('base64'); + } + + module.exports = btoa; +}()); + +}).call(this,require("buffer").Buffer) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9idG9hL2luZGV4LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uICgpIHtcbiAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgZnVuY3Rpb24gYnRvYShzdHIpIHtcbiAgICB2YXIgYnVmZmVyXG4gICAgICA7XG5cbiAgICBpZiAoc3RyIGluc3RhbmNlb2YgQnVmZmVyKSB7XG4gICAgICBidWZmZXIgPSBzdHI7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJ1ZmZlciA9IG5ldyBCdWZmZXIoc3RyLnRvU3RyaW5nKCksICdiaW5hcnknKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYnVmZmVyLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgfVxuXG4gIG1vZHVsZS5leHBvcnRzID0gYnRvYTtcbn0oKSk7XG4iXX0= +},{"buffer":15}],15:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var isArray = require('is-array') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 // not used by this implementation + +var rootParent = {} + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property + * on objects. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = (function () { + function Bar () {} + try { + var arr = new Uint8Array(1) + arr.foo = function () { return 42 } + arr.constructor = Bar + return arr.foo() === 42 && // typed array instances can be augmented + arr.constructor === Bar && // constructor can be set + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +})() + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (arg) { + if (!(this instanceof Buffer)) { + // Avoid going through an ArgumentsAdaptorTrampoline in the common case. + if (arguments.length > 1) return new Buffer(arg, arguments[1]) + return new Buffer(arg) + } + + this.length = 0 + this.parent = undefined + + // Common case. + if (typeof arg === 'number') { + return fromNumber(this, arg) + } + + // Slightly less common case. + if (typeof arg === 'string') { + return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8') + } + + // Unusual. + return fromObject(this, arg) +} + +function fromNumber (that, length) { + that = allocate(that, length < 0 ? 0 : checked(length) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < length; i++) { + that[i] = 0 + } + } + return that +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8' + + // Assumption: byteLength() return value is always < kMaxLength. + var length = byteLength(string, encoding) | 0 + that = allocate(that, length) + + that.write(string, encoding) + return that +} + +function fromObject (that, object) { + if (Buffer.isBuffer(object)) return fromBuffer(that, object) + + if (isArray(object)) return fromArray(that, object) + + if (object == null) { + throw new TypeError('must start with number, buffer, array or string') + } + + if (typeof ArrayBuffer !== 'undefined') { + if (object.buffer instanceof ArrayBuffer) { + return fromTypedArray(that, object) + } + if (object instanceof ArrayBuffer) { + return fromArrayBuffer(that, object) + } + } + + if (object.length) return fromArrayLike(that, object) + + return fromJsonObject(that, object) +} + +function fromBuffer (that, buffer) { + var length = checked(buffer.length) | 0 + that = allocate(that, length) + buffer.copy(that, 0, 0, length) + return that +} + +function fromArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Duplicate of fromArray() to keep fromArray() monomorphic. +function fromTypedArray (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + // Truncating the elements is probably not what people expect from typed + // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior + // of the old Buffer constructor. + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + array.byteLength + that = Buffer._augment(new Uint8Array(array)) + } else { + // Fallback: Return an object instance of the Buffer class + that = fromTypedArray(that, new Uint8Array(array)) + } + return that +} + +function fromArrayLike (that, array) { + var length = checked(array.length) | 0 + that = allocate(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object. +// Returns a zero-length buffer for inputs that don't conform to the spec. +function fromJsonObject (that, object) { + var array + var length = 0 + + if (object.type === 'Buffer' && isArray(object.data)) { + array = object.data + length = checked(array.length) | 0 + } + that = allocate(that, length) + + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function allocate (that, length) { + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return an object instance of the Buffer class + that.length = length + that._isBuffer = true + } + + var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1 + if (fromPool) that.parent = rootParent + + return that +} + +function checked (length) { + // Note: cannot use `length < kMaxLength` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (subject, encoding) { + if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding) + + var buf = new Buffer(subject, encoding) + delete buf.parent + return buf +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + var i = 0 + var len = Math.min(x, y) + while (i < len) { + if (a[i] !== b[i]) break + + ++i + } + + if (i !== len) { + x = a[i] + y = b[i] + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.') + + if (list.length === 0) { + return new Buffer(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; i++) { + length += list[i].length + } + } + + var buf = new Buffer(length) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +function byteLength (string, encoding) { + if (typeof string !== 'string') string = '' + string + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'binary': + // Deprecated + case 'raw': + case 'raws': + return len + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +// pre-set for values that may exist in the future +Buffer.prototype.length = undefined +Buffer.prototype.parent = undefined + +function slowToString (encoding, start, end) { + var loweredCase = false + + start = start | 0 + end = end === undefined || end === Infinity ? this.length : end | 0 + + if (!encoding) encoding = 'utf8' + if (start < 0) start = 0 + if (end > this.length) end = this.length + if (end <= start) return '' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'binary': + return binarySlice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return 0 + return Buffer.compare(this, b) +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset) { + if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff + else if (byteOffset < -0x80000000) byteOffset = -0x80000000 + byteOffset >>= 0 + + if (this.length === 0) return -1 + if (byteOffset >= this.length) return -1 + + // Negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0) + + if (typeof val === 'string') { + if (val.length === 0) return -1 // special case: looking for empty string always fails + return String.prototype.indexOf.call(this, val, byteOffset) + } + if (Buffer.isBuffer(val)) { + return arrayIndexOf(this, val, byteOffset) + } + if (typeof val === 'number') { + if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') { + return Uint8Array.prototype.indexOf.call(this, val, byteOffset) + } + return arrayIndexOf(this, [ val ], byteOffset) + } + + function arrayIndexOf (arr, val, byteOffset) { + var foundIndex = -1 + for (var i = 0; byteOffset + i < arr.length; i++) { + if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex + } else { + foundIndex = -1 + } + } + return -1 + } + + throw new TypeError('val must be string, number or Buffer') +} + +// `get` is deprecated +Buffer.prototype.get = function get (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` is deprecated +Buffer.prototype.set = function set (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new Error('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) throw new Error('Invalid hex string') + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function binaryWrite (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + var swap = encoding + encoding = offset + offset = length | 0 + length = swap + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'binary': + return binaryWrite(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function binarySlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + } + + if (newBuf.length) newBuf.parent = this.parent || this + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance') + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0) + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = value + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = value + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = value < 0 ? 1 : 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = value + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = value + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = value + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = value + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (value > max || value < min) throw new RangeError('value is out of bounds') + if (offset + ext > buf.length) throw new RangeError('index out of range') + if (offset < 0) throw new RangeError('index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; i--) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; i++) { + target[i + targetStart] = this[i + start] + } + } else { + target._set(this.subarray(start, start + len), targetStart) + } + + return len +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function fill (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (end < start) throw new RangeError('end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + if (start < 0 || start >= this.length) throw new RangeError('start out of bounds') + if (end < 0 || end > this.length) throw new RangeError('end out of bounds') + + var i + if (typeof value === 'number') { + for (i = start; i < end; i++) { + this[i] = value + } + } else { + var bytes = utf8ToBytes(value.toString()) + var len = bytes.length + for (i = start; i < end; i++) { + this[i] = bytes[i % len] + } + } + + return this +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function toArrayBuffer () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer.TYPED_ARRAY_SUPPORT) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) { + buf[i] = this[i] + } + return buf.buffer + } + } else { + throw new TypeError('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function _augment (arr) { + arr.constructor = Buffer + arr._isBuffer = true + + // save reference to original Uint8Array set method before overwriting + arr._set = arr.set + + // deprecated + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.equals = BP.equals + arr.compare = BP.compare + arr.indexOf = BP.indexOf + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUIntLE = BP.readUIntLE + arr.readUIntBE = BP.readUIntBE + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readIntLE = BP.readIntLE + arr.readIntBE = BP.readIntBE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUIntLE = BP.writeUIntLE + arr.writeUIntBE = BP.writeUIntBE + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeIntLE = BP.writeIntLE + arr.writeIntBE = BP.writeIntBE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; i++) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +},{"base64-js":16,"ieee754":17,"is-array":18}],16:[function(require,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + var PLUS_URL_SAFE = '-'.charCodeAt(0) + var SLASH_URL_SAFE = '_'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS || + code === PLUS_URL_SAFE) + return 62 // '+' + if (code === SLASH || + code === SLASH_URL_SAFE) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],17:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = nBytes * 8 - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],18:[function(require,module,exports){ + +/** + * isArray + */ + +var isArray = Array.isArray; + +/** + * toString + */ + +var str = Object.prototype.toString; + +/** + * Whether or not the given `val` + * is an array. + * + * example: + * + * isArray([]); + * // > true + * isArray(arguments); + * // > false + * isArray(''); + * // > false + * + * @param {mixed} val + * @return {bool} + */ + +module.exports = isArray || function (val) { + return !! val && '[object Array]' == str.call(val); +}; + +},{}],19:[function(require,module,exports){ +/* jshint node: true */ +(function () { + "use strict"; + + function CookieAccessInfo(domain, path, secure, script) { + if (this instanceof CookieAccessInfo) { + this.domain = domain || undefined; + this.path = path || "/"; + this.secure = !!secure; + this.script = !!script; + return this; + } + return new CookieAccessInfo(domain, path, secure, script); + } + exports.CookieAccessInfo = CookieAccessInfo; + + function Cookie(cookiestr, request_domain, request_path) { + if (cookiestr instanceof Cookie) { + return cookiestr; + } + if (this instanceof Cookie) { + this.name = null; + this.value = null; + this.expiration_date = Infinity; + this.path = String(request_path || "/"); + this.explicit_path = false; + this.domain = request_domain || null; + this.explicit_domain = false; + this.secure = false; //how to define default? + this.noscript = false; //httponly + if (cookiestr) { + this.parse(cookiestr, request_domain, request_path); + } + return this; + } + return new Cookie(cookiestr, request_domain, request_path); + } + exports.Cookie = Cookie; + + Cookie.prototype.toString = function toString() { + var str = [this.name + "=" + this.value]; + if (this.expiration_date !== Infinity) { + str.push("expires=" + (new Date(this.expiration_date)).toGMTString()); + } + if (this.domain) { + str.push("domain=" + this.domain); + } + if (this.path) { + str.push("path=" + this.path); + } + if (this.secure) { + str.push("secure"); + } + if (this.noscript) { + str.push("httponly"); + } + return str.join("; "); + }; + + Cookie.prototype.toValueString = function toValueString() { + return this.name + "=" + this.value; + }; + + var cookie_str_splitter = /[:](?=\s*[a-zA-Z0-9_\-]+\s*[=])/g; + Cookie.prototype.parse = function parse(str, request_domain, request_path) { + if (this instanceof Cookie) { + var parts = str.split(";").filter(function (value) { + return !!value; + }), + pair = parts[0].match(/([^=]+)=([\s\S]*)/), + key = pair[1], + value = pair[2], + i; + this.name = key; + this.value = value; + + for (i = 1; i < parts.length; i += 1) { + pair = parts[i].match(/([^=]+)(?:=([\s\S]*))?/); + key = pair[1].trim().toLowerCase(); + value = pair[2]; + switch (key) { + case "httponly": + this.noscript = true; + break; + case "expires": + this.expiration_date = value ? + Number(Date.parse(value)) : + Infinity; + break; + case "path": + this.path = value ? + value.trim() : + ""; + this.explicit_path = true; + break; + case "domain": + this.domain = value ? + value.trim() : + ""; + this.explicit_domain = !!this.domain; + break; + case "secure": + this.secure = true; + break; + } + } + + if (!this.explicit_path) { + this.path = request_path || "/"; + } + if (!this.explicit_domain) { + this.domain = request_domain; + } + + return this; + } + return new Cookie().parse(str, request_domain, request_path); + }; + + Cookie.prototype.matches = function matches(access_info) { + if (this.noscript && access_info.script || + this.secure && !access_info.secure || + !this.collidesWith(access_info)) { + return false; + } + return true; + }; + + Cookie.prototype.collidesWith = function collidesWith(access_info) { + if ((this.path && !access_info.path) || (this.domain && !access_info.domain)) { + return false; + } + if (this.path && access_info.path.indexOf(this.path) !== 0) { + return false; + } + if (this.explicit_path && access_info.path.indexOf( this.path ) !== 0) { + return false; + } + var access_domain = access_info.domain && access_info.domain.replace(/^[\.]/,''); + var cookie_domain = this.domain && this.domain.replace(/^[\.]/,''); + if (cookie_domain === access_domain) { + return true; + } + if (cookie_domain) { + if (!this.explicit_domain) { + return false; // we already checked if the domains were exactly the same + } + var wildcard = access_domain.indexOf(cookie_domain); + if (wildcard === -1 || wildcard !== access_domain.length - cookie_domain.length) { + return false; + } + return true; + } + return true; + }; + + function CookieJar() { + var cookies, cookies_list, collidable_cookie; + if (this instanceof CookieJar) { + cookies = Object.create(null); //name: [Cookie] + + this.setCookie = function setCookie(cookie, request_domain, request_path) { + var remove, i; + cookie = new Cookie(cookie, request_domain, request_path); + //Delete the cookie if the set is past the current time + remove = cookie.expiration_date <= Date.now(); + if (cookies[cookie.name] !== undefined) { + cookies_list = cookies[cookie.name]; + for (i = 0; i < cookies_list.length; i += 1) { + collidable_cookie = cookies_list[i]; + if (collidable_cookie.collidesWith(cookie)) { + if (remove) { + cookies_list.splice(i, 1); + if (cookies_list.length === 0) { + delete cookies[cookie.name]; + } + return false; + } + cookies_list[i] = cookie; + return cookie; + } + } + if (remove) { + return false; + } + cookies_list.push(cookie); + return cookie; + } + if (remove) { + return false; + } + cookies[cookie.name] = [cookie]; + return cookies[cookie.name]; + }; + //returns a cookie + this.getCookie = function getCookie(cookie_name, access_info) { + var cookie, i; + cookies_list = cookies[cookie_name]; + if (!cookies_list) { + return; + } + for (i = 0; i < cookies_list.length; i += 1) { + cookie = cookies_list[i]; + if (cookie.expiration_date <= Date.now()) { + if (cookies_list.length === 0) { + delete cookies[cookie.name]; + } + continue; + } + + if (cookie.matches(access_info)) { + return cookie; + } + } + }; + //returns a list of cookies + this.getCookies = function getCookies(access_info) { + var matches = [], cookie_name, cookie; + for (cookie_name in cookies) { + cookie = this.getCookie(cookie_name, access_info); + if (cookie) { + matches.push(cookie); + } + } + matches.toString = function toString() { + return matches.join(":"); + }; + matches.toValueString = function toValueString() { + return matches.map(function (c) { + return c.toValueString(); + }).join(';'); + }; + return matches; + }; + + return this; + } + return new CookieJar(); + } + exports.CookieJar = CookieJar; + + //returns list of cookies that were set correctly. Cookies that are expired and removed are not returned. + CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) { + cookies = Array.isArray(cookies) ? + cookies : + cookies.split(cookie_str_splitter); + var successful = [], + i, + cookie; + cookies = cookies.map(function(item){ + return new Cookie(item, request_domain, request_path); + }); + for (i = 0; i < cookies.length; i += 1) { + cookie = cookies[i]; + if (this.setCookie(cookie, request_domain, request_path)) { + successful.push(cookie); + } + } + return successful; + }; +}()); + +},{}],20:[function(require,module,exports){ +'use strict'; + + +var yaml = require('./lib/js-yaml.js'); + + +module.exports = yaml; + +},{"./lib/js-yaml.js":21}],21:[function(require,module,exports){ +'use strict'; + + +var loader = require('./js-yaml/loader'); +var dumper = require('./js-yaml/dumper'); + + +function deprecated(name) { + return function () { + throw new Error('Function ' + name + ' is deprecated and cannot be used.'); + }; +} + + +module.exports.Type = require('./js-yaml/type'); +module.exports.Schema = require('./js-yaml/schema'); +module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe'); +module.exports.JSON_SCHEMA = require('./js-yaml/schema/json'); +module.exports.CORE_SCHEMA = require('./js-yaml/schema/core'); +module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe'); +module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full'); +module.exports.load = loader.load; +module.exports.loadAll = loader.loadAll; +module.exports.safeLoad = loader.safeLoad; +module.exports.safeLoadAll = loader.safeLoadAll; +module.exports.dump = dumper.dump; +module.exports.safeDump = dumper.safeDump; +module.exports.YAMLException = require('./js-yaml/exception'); + +// Deprecated schema names from JS-YAML 2.0.x +module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe'); +module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe'); +module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full'); + +// Deprecated functions from JS-YAML 1.x.x +module.exports.scan = deprecated('scan'); +module.exports.parse = deprecated('parse'); +module.exports.compose = deprecated('compose'); +module.exports.addConstructor = deprecated('addConstructor'); + +},{"./js-yaml/dumper":23,"./js-yaml/exception":24,"./js-yaml/loader":25,"./js-yaml/schema":27,"./js-yaml/schema/core":28,"./js-yaml/schema/default_full":29,"./js-yaml/schema/default_safe":30,"./js-yaml/schema/failsafe":31,"./js-yaml/schema/json":32,"./js-yaml/type":33}],22:[function(require,module,exports){ +'use strict'; + + +function isNothing(subject) { + return (typeof subject === 'undefined') || (null === subject); +} + + +function isObject(subject) { + return (typeof subject === 'object') && (null !== subject); +} + + +function toArray(sequence) { + if (Array.isArray(sequence)) { + return sequence; + } else if (isNothing(sequence)) { + return []; + } + return [ sequence ]; +} + + +function extend(target, source) { + var index, length, key, sourceKeys; + + if (source) { + sourceKeys = Object.keys(source); + + for (index = 0, length = sourceKeys.length; index < length; index += 1) { + key = sourceKeys[index]; + target[key] = source[key]; + } + } + + return target; +} + + +function repeat(string, count) { + var result = '', cycle; + + for (cycle = 0; cycle < count; cycle += 1) { + result += string; + } + + return result; +} + + +function isNegativeZero(number) { + return (0 === number) && (Number.NEGATIVE_INFINITY === 1 / number); +} + + +module.exports.isNothing = isNothing; +module.exports.isObject = isObject; +module.exports.toArray = toArray; +module.exports.repeat = repeat; +module.exports.isNegativeZero = isNegativeZero; +module.exports.extend = extend; + +},{}],23:[function(require,module,exports){ +'use strict'; + +/*eslint-disable no-use-before-define*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var DEFAULT_FULL_SCHEMA = require('./schema/default_full'); +var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe'); + +var _toString = Object.prototype.toString; +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +var CHAR_TAB = 0x09; /* Tab */ +var CHAR_LINE_FEED = 0x0A; /* LF */ +var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */ +var CHAR_SPACE = 0x20; /* Space */ +var CHAR_EXCLAMATION = 0x21; /* ! */ +var CHAR_DOUBLE_QUOTE = 0x22; /* " */ +var CHAR_SHARP = 0x23; /* # */ +var CHAR_PERCENT = 0x25; /* % */ +var CHAR_AMPERSAND = 0x26; /* & */ +var CHAR_SINGLE_QUOTE = 0x27; /* ' */ +var CHAR_ASTERISK = 0x2A; /* * */ +var CHAR_COMMA = 0x2C; /* , */ +var CHAR_MINUS = 0x2D; /* - */ +var CHAR_COLON = 0x3A; /* : */ +var CHAR_GREATER_THAN = 0x3E; /* > */ +var CHAR_QUESTION = 0x3F; /* ? */ +var CHAR_COMMERCIAL_AT = 0x40; /* @ */ +var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */ +var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */ +var CHAR_GRAVE_ACCENT = 0x60; /* ` */ +var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */ +var CHAR_VERTICAL_LINE = 0x7C; /* | */ +var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */ + +var ESCAPE_SEQUENCES = {}; + +ESCAPE_SEQUENCES[0x00] = '\\0'; +ESCAPE_SEQUENCES[0x07] = '\\a'; +ESCAPE_SEQUENCES[0x08] = '\\b'; +ESCAPE_SEQUENCES[0x09] = '\\t'; +ESCAPE_SEQUENCES[0x0A] = '\\n'; +ESCAPE_SEQUENCES[0x0B] = '\\v'; +ESCAPE_SEQUENCES[0x0C] = '\\f'; +ESCAPE_SEQUENCES[0x0D] = '\\r'; +ESCAPE_SEQUENCES[0x1B] = '\\e'; +ESCAPE_SEQUENCES[0x22] = '\\"'; +ESCAPE_SEQUENCES[0x5C] = '\\\\'; +ESCAPE_SEQUENCES[0x85] = '\\N'; +ESCAPE_SEQUENCES[0xA0] = '\\_'; +ESCAPE_SEQUENCES[0x2028] = '\\L'; +ESCAPE_SEQUENCES[0x2029] = '\\P'; + +var DEPRECATED_BOOLEANS_SYNTAX = [ + 'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON', + 'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF' +]; + +function compileStyleMap(schema, map) { + var result, keys, index, length, tag, style, type; + + if (null === map) { + return {}; + } + + result = {}; + keys = Object.keys(map); + + for (index = 0, length = keys.length; index < length; index += 1) { + tag = keys[index]; + style = String(map[tag]); + + if ('!!' === tag.slice(0, 2)) { + tag = 'tag:yaml.org,2002:' + tag.slice(2); + } + + type = schema.compiledTypeMap[tag]; + + if (type && _hasOwnProperty.call(type.styleAliases, style)) { + style = type.styleAliases[style]; + } + + result[tag] = style; + } + + return result; +} + +function encodeHex(character) { + var string, handle, length; + + string = character.toString(16).toUpperCase(); + + if (character <= 0xFF) { + handle = 'x'; + length = 2; + } else if (character <= 0xFFFF) { + handle = 'u'; + length = 4; + } else if (character <= 0xFFFFFFFF) { + handle = 'U'; + length = 8; + } else { + throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF'); + } + + return '\\' + handle + common.repeat('0', length - string.length) + string; +} + +function State(options) { + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.indent = Math.max(1, (options['indent'] || 2)); + this.skipInvalid = options['skipInvalid'] || false; + this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']); + this.styleMap = compileStyleMap(this.schema, options['styles'] || null); + this.sortKeys = options['sortKeys'] || false; + this.lineWidth = options['lineWidth'] || 80; + + this.implicitTypes = this.schema.compiledImplicit; + this.explicitTypes = this.schema.compiledExplicit; + + this.tag = null; + this.result = ''; + + this.duplicates = []; + this.usedDuplicates = null; +} + +function indentString(string, spaces) { + var ind = common.repeat(' ', spaces), + position = 0, + next = -1, + result = '', + line, + length = string.length; + + while (position < length) { + next = string.indexOf('\n', position); + if (next === -1) { + line = string.slice(position); + position = length; + } else { + line = string.slice(position, next + 1); + position = next + 1; + } + if (line.length && line !== '\n') { + result += ind; + } + result += line; + } + + return result; +} + +function generateNextLine(state, level) { + return '\n' + common.repeat(' ', state.indent * level); +} + +function testImplicitResolving(state, str) { + var index, length, type; + + for (index = 0, length = state.implicitTypes.length; index < length; index += 1) { + type = state.implicitTypes[index]; + + if (type.resolve(str)) { + return true; + } + } + + return false; +} + +function StringBuilder(source) { + this.source = source; + this.result = ''; + this.checkpoint = 0; +} + +StringBuilder.prototype.takeUpTo = function (position) { + var er; + + if (position < this.checkpoint) { + er = new Error('position should be > checkpoint'); + er.position = position; + er.checkpoint = this.checkpoint; + throw er; + } + + this.result += this.source.slice(this.checkpoint, position); + this.checkpoint = position; + return this; +}; + +StringBuilder.prototype.escapeChar = function () { + var character, esc; + + character = this.source.charCodeAt(this.checkpoint); + esc = ESCAPE_SEQUENCES[character] || encodeHex(character); + this.result += esc; + this.checkpoint += 1; + + return this; +}; + +StringBuilder.prototype.finish = function () { + if (this.source.length > this.checkpoint) { + this.takeUpTo(this.source.length); + } +}; + +function writeScalar(state, object, level, iskey) { + var simple, first, spaceWrap, folded, literal, single, double, + sawLineFeed, linePosition, longestLine, indent, max, character, + position, escapeSeq, hexEsc, previous, lineLength, modifier, + trailingLineBreaks, result; + + if (0 === object.length) { + state.dump = "''"; + return; + } + + if (-1 !== DEPRECATED_BOOLEANS_SYNTAX.indexOf(object)) { + state.dump = "'" + object + "'"; + return; + } + + simple = true; + first = object.length ? object.charCodeAt(0) : 0; + spaceWrap = (CHAR_SPACE === first || + CHAR_SPACE === object.charCodeAt(object.length - 1)); + + // Simplified check for restricted first characters + // http://www.yaml.org/spec/1.2/spec.html#ns-plain-first%28c%29 + if (CHAR_MINUS === first || + CHAR_QUESTION === first || + CHAR_COMMERCIAL_AT === first || + CHAR_GRAVE_ACCENT === first) { + simple = false; + } + + // can only use > and | if not wrapped in spaces or is not a key. + if (spaceWrap) { + simple = false; + folded = false; + literal = false; + } else { + folded = !iskey; + literal = !iskey; + } + + single = true; + double = new StringBuilder(object); + + sawLineFeed = false; + linePosition = 0; + longestLine = 0; + + indent = state.indent * level; + max = state.lineWidth; + if (max === -1) { + // Replace -1 with biggest ingeger number according to + // http://ecma262-5.com/ELS5_HTML.htm#Section_8.5 + max = 9007199254740991; + } + + if (indent < 40) { + max -= indent; + } else { + max = 40; + } + + for (position = 0; position < object.length; position++) { + character = object.charCodeAt(position); + if (simple) { + // Characters that can never appear in the simple scalar + if (!simpleChar(character)) { + simple = false; + } else { + // Still simple. If we make it all the way through like + // this, then we can just dump the string as-is. + continue; + } + } + + if (single && character === CHAR_SINGLE_QUOTE) { + single = false; + } + + escapeSeq = ESCAPE_SEQUENCES[character]; + hexEsc = needsHexEscape(character); + + if (!escapeSeq && !hexEsc) { + continue; + } + + if (character !== CHAR_LINE_FEED && + character !== CHAR_DOUBLE_QUOTE && + character !== CHAR_SINGLE_QUOTE) { + folded = false; + literal = false; + } else if (character === CHAR_LINE_FEED) { + sawLineFeed = true; + single = false; + if (position > 0) { + previous = object.charCodeAt(position - 1); + if (previous === CHAR_SPACE) { + literal = false; + folded = false; + } + } + if (folded) { + lineLength = position - linePosition; + linePosition = position; + if (lineLength > longestLine) { + longestLine = lineLength; + } + } + } + + if (character !== CHAR_DOUBLE_QUOTE) { + single = false; + } + + double.takeUpTo(position); + double.escapeChar(); + } + + if (simple && testImplicitResolving(state, object)) { + simple = false; + } + + modifier = ''; + if (folded || literal) { + trailingLineBreaks = 0; + if (object.charCodeAt(object.length - 1) === CHAR_LINE_FEED) { + trailingLineBreaks += 1; + if (object.charCodeAt(object.length - 2) === CHAR_LINE_FEED) { + trailingLineBreaks += 1; + } + } + + if (trailingLineBreaks === 0) { + modifier = '-'; + } else if (trailingLineBreaks === 2) { + modifier = '+'; + } + } + + if (literal && longestLine < max) { + folded = false; + } + + // If it's literally one line, then don't bother with the literal. + // We may still want to do a fold, though, if it's a super long line. + if (!sawLineFeed) { + literal = false; + } + + if (simple) { + state.dump = object; + } else if (single) { + state.dump = '\'' + object + '\''; + } else if (folded) { + result = fold(object, max); + state.dump = '>' + modifier + '\n' + indentString(result, indent); + } else if (literal) { + if (!modifier) { + object = object.replace(/\n$/, ''); + } + state.dump = '|' + modifier + '\n' + indentString(object, indent); + } else if (double) { + double.finish(); + state.dump = '"' + double.result + '"'; + } else { + throw new Error('Failed to dump scalar value'); + } + + return; +} + +// The `trailing` var is a regexp match of any trailing `\n` characters. +// +// There are three cases we care about: +// +// 1. One trailing `\n` on the string. Just use `|` or `>`. +// This is the assumed default. (trailing = null) +// 2. No trailing `\n` on the string. Use `|-` or `>-` to "chomp" the end. +// 3. More than one trailing `\n` on the string. Use `|+` or `>+`. +// +// In the case of `>+`, these line breaks are *not* doubled (like the line +// breaks within the string), so it's important to only end with the exact +// same number as we started. +function fold(object, max) { + var result = '', + position = 0, + length = object.length, + trailing = /\n+$/.exec(object), + newLine; + + if (trailing) { + length = trailing.index + 1; + } + + while (position < length) { + newLine = object.indexOf('\n', position); + if (newLine > length || newLine === -1) { + if (result) { + result += '\n\n'; + } + result += foldLine(object.slice(position, length), max); + position = length; + } else { + if (result) { + result += '\n\n'; + } + result += foldLine(object.slice(position, newLine), max); + position = newLine + 1; + } + } + if (trailing && trailing[0] !== '\n') { + result += trailing[0]; + } + + return result; +} + +function foldLine(line, max) { + if (line === '') { + return line; + } + + var foldRe = /[^\s] [^\s]/g, + result = '', + prevMatch = 0, + foldStart = 0, + match = foldRe.exec(line), + index, + foldEnd, + folded; + + while (match) { + index = match.index; + + // when we cross the max len, if the previous match would've + // been ok, use that one, and carry on. If there was no previous + // match on this fold section, then just have a long line. + if (index - foldStart > max) { + if (prevMatch !== foldStart) { + foldEnd = prevMatch; + } else { + foldEnd = index; + } + + if (result) { + result += '\n'; + } + folded = line.slice(foldStart, foldEnd); + result += folded; + foldStart = foldEnd + 1; + } + prevMatch = index + 1; + match = foldRe.exec(line); + } + + if (result) { + result += '\n'; + } + + // if we end up with one last word at the end, then the last bit might + // be slightly bigger than we wanted, because we exited out of the loop. + if (foldStart !== prevMatch && line.length - foldStart > max) { + result += line.slice(foldStart, prevMatch) + '\n' + + line.slice(prevMatch + 1); + } else { + result += line.slice(foldStart); + } + + return result; +} + +// Returns true if character can be found in a simple scalar +function simpleChar(character) { + return CHAR_TAB !== character && + CHAR_LINE_FEED !== character && + CHAR_CARRIAGE_RETURN !== character && + CHAR_COMMA !== character && + CHAR_LEFT_SQUARE_BRACKET !== character && + CHAR_RIGHT_SQUARE_BRACKET !== character && + CHAR_LEFT_CURLY_BRACKET !== character && + CHAR_RIGHT_CURLY_BRACKET !== character && + CHAR_SHARP !== character && + CHAR_AMPERSAND !== character && + CHAR_ASTERISK !== character && + CHAR_EXCLAMATION !== character && + CHAR_VERTICAL_LINE !== character && + CHAR_GREATER_THAN !== character && + CHAR_SINGLE_QUOTE !== character && + CHAR_DOUBLE_QUOTE !== character && + CHAR_PERCENT !== character && + CHAR_COLON !== character && + !ESCAPE_SEQUENCES[character] && + !needsHexEscape(character); +} + +// Returns true if the character code needs to be escaped. +function needsHexEscape(character) { + return !((0x00020 <= character && character <= 0x00007E) || + (0x00085 === character) || + (0x000A0 <= character && character <= 0x00D7FF) || + (0x0E000 <= character && character <= 0x00FFFD) || + (0x10000 <= character && character <= 0x10FFFF)); +} + +function writeFlowSequence(state, level, object) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level, object[index], false, false)) { + if (0 !== index) { + _result += ', '; + } + _result += state.dump; + } + } + + state.tag = _tag; + state.dump = '[' + _result + ']'; +} + +function writeBlockSequence(state, level, object, compact) { + var _result = '', + _tag = state.tag, + index, + length; + + for (index = 0, length = object.length; index < length; index += 1) { + // Write only valid elements. + if (writeNode(state, level + 1, object[index], true, true)) { + if (!compact || 0 !== index) { + _result += generateNextLine(state, level); + } + _result += '- ' + state.dump; + } + } + + state.tag = _tag; + state.dump = _result || '[]'; // Empty sequence if no valid values. +} + +function writeFlowMapping(state, level, object) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + pairBuffer; + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (0 !== index) { + pairBuffer += ', '; + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level, objectKey, false, false)) { + continue; // Skip this pair because of invalid key; + } + + if (state.dump.length > 1024) { + pairBuffer += '? '; + } + + pairBuffer += state.dump + ': '; + + if (!writeNode(state, level, objectValue, false, false)) { + continue; // Skip this pair because of invalid value. + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = '{' + _result + '}'; +} + +function writeBlockMapping(state, level, object, compact) { + var _result = '', + _tag = state.tag, + objectKeyList = Object.keys(object), + index, + length, + objectKey, + objectValue, + explicitPair, + pairBuffer; + + // Allow sorting keys so that the output file is deterministic + if (state.sortKeys === true) { + // Default sorting + objectKeyList.sort(); + } else if (typeof state.sortKeys === 'function') { + // Custom sort function + objectKeyList.sort(state.sortKeys); + } else if (state.sortKeys) { + // Something is wrong + throw new YAMLException('sortKeys must be a boolean or a function'); + } + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + pairBuffer = ''; + + if (!compact || 0 !== index) { + pairBuffer += generateNextLine(state, level); + } + + objectKey = objectKeyList[index]; + objectValue = object[objectKey]; + + if (!writeNode(state, level + 1, objectKey, true, true, true)) { + continue; // Skip this pair because of invalid key. + } + + explicitPair = (null !== state.tag && '?' !== state.tag) || + (state.dump && state.dump.length > 1024); + + if (explicitPair) { + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += '?'; + } else { + pairBuffer += '? '; + } + } + + pairBuffer += state.dump; + + if (explicitPair) { + pairBuffer += generateNextLine(state, level); + } + + if (!writeNode(state, level + 1, objectValue, true, explicitPair)) { + continue; // Skip this pair because of invalid value. + } + + if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) { + pairBuffer += ':'; + } else { + pairBuffer += ': '; + } + + pairBuffer += state.dump; + + // Both key and value are valid. + _result += pairBuffer; + } + + state.tag = _tag; + state.dump = _result || '{}'; // Empty mapping if no valid pairs. +} + +function detectType(state, object, explicit) { + var _result, typeList, index, length, type, style; + + typeList = explicit ? state.explicitTypes : state.implicitTypes; + + for (index = 0, length = typeList.length; index < length; index += 1) { + type = typeList[index]; + + if ((type.instanceOf || type.predicate) && + (!type.instanceOf || (('object' === typeof object) && (object instanceof type.instanceOf))) && + (!type.predicate || type.predicate(object))) { + + state.tag = explicit ? type.tag : '?'; + + if (type.represent) { + style = state.styleMap[type.tag] || type.defaultStyle; + + if ('[object Function]' === _toString.call(type.represent)) { + _result = type.represent(object, style); + } else if (_hasOwnProperty.call(type.represent, style)) { + _result = type.represent[style](object, style); + } else { + throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style'); + } + + state.dump = _result; + } + + return true; + } + } + + return false; +} + +// Serializes `object` and writes it to global `result`. +// Returns true on success, or false on invalid object. +// +function writeNode(state, level, object, block, compact, iskey) { + state.tag = null; + state.dump = object; + + if (!detectType(state, object, false)) { + detectType(state, object, true); + } + + var type = _toString.call(state.dump); + + if (block) { + block = (0 > state.flowLevel || state.flowLevel > level); + } + + var objectOrArray = '[object Object]' === type || '[object Array]' === type, + duplicateIndex, + duplicate; + + if (objectOrArray) { + duplicateIndex = state.duplicates.indexOf(object); + duplicate = duplicateIndex !== -1; + } + + if ((null !== state.tag && '?' !== state.tag) || duplicate || (2 !== state.indent && level > 0)) { + compact = false; + } + + if (duplicate && state.usedDuplicates[duplicateIndex]) { + state.dump = '*ref_' + duplicateIndex; + } else { + if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) { + state.usedDuplicates[duplicateIndex] = true; + } + if ('[object Object]' === type) { + if (block && (0 !== Object.keys(state.dump).length)) { + writeBlockMapping(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowMapping(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if ('[object Array]' === type) { + if (block && (0 !== state.dump.length)) { + writeBlockSequence(state, level, state.dump, compact); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + state.dump; + } + } else { + writeFlowSequence(state, level, state.dump); + if (duplicate) { + state.dump = '&ref_' + duplicateIndex + ' ' + state.dump; + } + } + } else if ('[object String]' === type) { + if ('?' !== state.tag) { + writeScalar(state, state.dump, level, iskey); + } + } else { + if (state.skipInvalid) { + return false; + } + throw new YAMLException('unacceptable kind of an object to dump ' + type); + } + + if (null !== state.tag && '?' !== state.tag) { + state.dump = '!<' + state.tag + '> ' + state.dump; + } + } + + return true; +} + +function getDuplicateReferences(object, state) { + var objects = [], + duplicatesIndexes = [], + index, + length; + + inspectNode(object, objects, duplicatesIndexes); + + for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) { + state.duplicates.push(objects[duplicatesIndexes[index]]); + } + state.usedDuplicates = new Array(length); +} + +function inspectNode(object, objects, duplicatesIndexes) { + var objectKeyList, + index, + length; + + if (null !== object && 'object' === typeof object) { + index = objects.indexOf(object); + if (-1 !== index) { + if (-1 === duplicatesIndexes.indexOf(index)) { + duplicatesIndexes.push(index); + } + } else { + objects.push(object); + + if (Array.isArray(object)) { + for (index = 0, length = object.length; index < length; index += 1) { + inspectNode(object[index], objects, duplicatesIndexes); + } + } else { + objectKeyList = Object.keys(object); + + for (index = 0, length = objectKeyList.length; index < length; index += 1) { + inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes); + } + } + } + } +} + +function dump(input, options) { + options = options || {}; + + var state = new State(options); + + getDuplicateReferences(input, state); + + if (writeNode(state, 0, input, true, true)) { + return state.dump + '\n'; + } + return ''; +} + +function safeDump(input, options) { + return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + +module.exports.dump = dump; +module.exports.safeDump = safeDump; + +},{"./common":22,"./exception":24,"./schema/default_full":29,"./schema/default_safe":30}],24:[function(require,module,exports){ +// YAML error class. http://stackoverflow.com/questions/8458984 +// +'use strict'; + + +var inherits = require('inherit'); + + +function YAMLException(reason, mark) { + // Super constructor + Error.call(this); + + // Include stack trace in error object + if (Error.captureStackTrace) { + // Chrome and NodeJS + Error.captureStackTrace(this, this.constructor); + } else { + // FF, IE 10+ and Safari 6+. Fallback for others + this.stack = (new Error()).stack || ''; + } + + this.name = 'YAMLException'; + this.reason = reason; + this.mark = mark; + this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : ''); +} + + +// Inherit from Error +inherits(YAMLException, Error); + + +YAMLException.prototype.toString = function toString(compact) { + var result = this.name + ': '; + + result += this.reason || '(unknown reason)'; + + if (!compact && this.mark) { + result += ' ' + this.mark.toString(); + } + + return result; +}; + + +module.exports = YAMLException; + +},{"inherit":51}],25:[function(require,module,exports){ +'use strict'; + +/*eslint-disable max-len,no-use-before-define*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Mark = require('./mark'); +var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe'); +var DEFAULT_FULL_SCHEMA = require('./schema/default_full'); + + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + + +var CONTEXT_FLOW_IN = 1; +var CONTEXT_FLOW_OUT = 2; +var CONTEXT_BLOCK_IN = 3; +var CONTEXT_BLOCK_OUT = 4; + + +var CHOMPING_CLIP = 1; +var CHOMPING_STRIP = 2; +var CHOMPING_KEEP = 3; + + +var PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/; +var PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/; +var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/; +var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i; +var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + + +function is_EOL(c) { + return (c === 0x0A/* LF */) || (c === 0x0D/* CR */); +} + +function is_WHITE_SPACE(c) { + return (c === 0x09/* Tab */) || (c === 0x20/* Space */); +} + +function is_WS_OR_EOL(c) { + return (c === 0x09/* Tab */) || + (c === 0x20/* Space */) || + (c === 0x0A/* LF */) || + (c === 0x0D/* CR */); +} + +function is_FLOW_INDICATOR(c) { + return 0x2C/* , */ === c || + 0x5B/* [ */ === c || + 0x5D/* ] */ === c || + 0x7B/* { */ === c || + 0x7D/* } */ === c; +} + +function fromHexCode(c) { + var lc; + + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + /*eslint-disable no-bitwise*/ + lc = c | 0x20; + + if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) { + return lc - 0x61 + 10; + } + + return -1; +} + +function escapedHexLen(c) { + if (c === 0x78/* x */) { return 2; } + if (c === 0x75/* u */) { return 4; } + if (c === 0x55/* U */) { return 8; } + return 0; +} + +function fromDecimalCode(c) { + if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) { + return c - 0x30; + } + + return -1; +} + +function simpleEscapeSequence(c) { + return (c === 0x30/* 0 */) ? '\x00' : + (c === 0x61/* a */) ? '\x07' : + (c === 0x62/* b */) ? '\x08' : + (c === 0x74/* t */) ? '\x09' : + (c === 0x09/* Tab */) ? '\x09' : + (c === 0x6E/* n */) ? '\x0A' : + (c === 0x76/* v */) ? '\x0B' : + (c === 0x66/* f */) ? '\x0C' : + (c === 0x72/* r */) ? '\x0D' : + (c === 0x65/* e */) ? '\x1B' : + (c === 0x20/* Space */) ? ' ' : + (c === 0x22/* " */) ? '\x22' : + (c === 0x2F/* / */) ? '/' : + (c === 0x5C/* \ */) ? '\x5C' : + (c === 0x4E/* N */) ? '\x85' : + (c === 0x5F/* _ */) ? '\xA0' : + (c === 0x4C/* L */) ? '\u2028' : + (c === 0x50/* P */) ? '\u2029' : ''; +} + +function charFromCodepoint(c) { + if (c <= 0xFFFF) { + return String.fromCharCode(c); + } + // Encode UTF-16 surrogate pair + // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF + return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800, + ((c - 0x010000) & 0x03FF) + 0xDC00); +} + +var simpleEscapeCheck = new Array(256); // integer, for fast access +var simpleEscapeMap = new Array(256); +for (var i = 0; i < 256; i++) { + simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0; + simpleEscapeMap[i] = simpleEscapeSequence(i); +} + + +function State(input, options) { + this.input = input; + + this.filename = options['filename'] || null; + this.schema = options['schema'] || DEFAULT_FULL_SCHEMA; + this.onWarning = options['onWarning'] || null; + this.legacy = options['legacy'] || false; + + this.implicitTypes = this.schema.compiledImplicit; + this.typeMap = this.schema.compiledTypeMap; + + this.length = input.length; + this.position = 0; + this.line = 0; + this.lineStart = 0; + this.lineIndent = 0; + + this.documents = []; + + /* + this.version; + this.checkLineBreaks; + this.tagMap; + this.anchorMap; + this.tag; + this.anchor; + this.kind; + this.result;*/ + +} + + +function generateError(state, message) { + return new YAMLException( + message, + new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart))); +} + +function throwError(state, message) { + throw generateError(state, message); +} + +function throwWarning(state, message) { + if (state.onWarning) { + state.onWarning.call(null, generateError(state, message)); + } +} + + +var directiveHandlers = { + + YAML: function handleYamlDirective(state, name, args) { + + var match, major, minor; + + if (null !== state.version) { + throwError(state, 'duplication of %YAML directive'); + } + + if (1 !== args.length) { + throwError(state, 'YAML directive accepts exactly one argument'); + } + + match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]); + + if (null === match) { + throwError(state, 'ill-formed argument of the YAML directive'); + } + + major = parseInt(match[1], 10); + minor = parseInt(match[2], 10); + + if (1 !== major) { + throwError(state, 'unacceptable YAML version of the document'); + } + + state.version = args[0]; + state.checkLineBreaks = (minor < 2); + + if (1 !== minor && 2 !== minor) { + throwWarning(state, 'unsupported YAML version of the document'); + } + }, + + TAG: function handleTagDirective(state, name, args) { + + var handle, prefix; + + if (2 !== args.length) { + throwError(state, 'TAG directive accepts exactly two arguments'); + } + + handle = args[0]; + prefix = args[1]; + + if (!PATTERN_TAG_HANDLE.test(handle)) { + throwError(state, 'ill-formed tag handle (first argument) of the TAG directive'); + } + + if (_hasOwnProperty.call(state.tagMap, handle)) { + throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle'); + } + + if (!PATTERN_TAG_URI.test(prefix)) { + throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive'); + } + + state.tagMap[handle] = prefix; + } +}; + + +function captureSegment(state, start, end, checkJson) { + var _position, _length, _character, _result; + + if (start < end) { + _result = state.input.slice(start, end); + + if (checkJson) { + for (_position = 0, _length = _result.length; + _position < _length; + _position += 1) { + _character = _result.charCodeAt(_position); + if (!(0x09 === _character || + 0x20 <= _character && _character <= 0x10FFFF)) { + throwError(state, 'expected valid JSON character'); + } + } + } else if (PATTERN_NON_PRINTABLE.test(_result)) { + throwError(state, 'the stream contains non-printable characters'); + } + + state.result += _result; + } +} + +function mergeMappings(state, destination, source) { + var sourceKeys, key, index, quantity; + + if (!common.isObject(source)) { + throwError(state, 'cannot merge mappings; the provided source object is unacceptable'); + } + + sourceKeys = Object.keys(source); + + for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) { + key = sourceKeys[index]; + + if (!_hasOwnProperty.call(destination, key)) { + destination[key] = source[key]; + } + } +} + +function storeMappingPair(state, _result, keyTag, keyNode, valueNode) { + var index, quantity; + + keyNode = String(keyNode); + + if (null === _result) { + _result = {}; + } + + if ('tag:yaml.org,2002:merge' === keyTag) { + if (Array.isArray(valueNode)) { + for (index = 0, quantity = valueNode.length; index < quantity; index += 1) { + mergeMappings(state, _result, valueNode[index]); + } + } else { + mergeMappings(state, _result, valueNode); + } + } else { + _result[keyNode] = valueNode; + } + + return _result; +} + +function readLineBreak(state) { + var ch; + + ch = state.input.charCodeAt(state.position); + + if (0x0A/* LF */ === ch) { + state.position++; + } else if (0x0D/* CR */ === ch) { + state.position++; + if (0x0A/* LF */ === state.input.charCodeAt(state.position)) { + state.position++; + } + } else { + throwError(state, 'a line break is expected'); + } + + state.line += 1; + state.lineStart = state.position; +} + +function skipSeparationSpace(state, allowComments, checkIndent) { + var lineBreaks = 0, + ch = state.input.charCodeAt(state.position); + + while (0 !== ch) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (allowComments && 0x23/* # */ === ch) { + do { + ch = state.input.charCodeAt(++state.position); + } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && 0 !== ch); + } + + if (is_EOL(ch)) { + readLineBreak(state); + + ch = state.input.charCodeAt(state.position); + lineBreaks++; + state.lineIndent = 0; + + while (0x20/* Space */ === ch) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + } else { + break; + } + } + + if (-1 !== checkIndent && 0 !== lineBreaks && state.lineIndent < checkIndent) { + throwWarning(state, 'deficient indentation'); + } + + return lineBreaks; +} + +function testDocumentSeparator(state) { + var _position = state.position, + ch; + + ch = state.input.charCodeAt(_position); + + // Condition state.position === state.lineStart is tested + // in parent on each call, for efficiency. No needs to test here again. + if ((0x2D/* - */ === ch || 0x2E/* . */ === ch) && + state.input.charCodeAt(_position + 1) === ch && + state.input.charCodeAt(_position + 2) === ch) { + + _position += 3; + + ch = state.input.charCodeAt(_position); + + if (ch === 0 || is_WS_OR_EOL(ch)) { + return true; + } + } + + return false; +} + +function writeFoldedLines(state, count) { + if (1 === count) { + state.result += ' '; + } else if (count > 1) { + state.result += common.repeat('\n', count - 1); + } +} + + +function readPlainScalar(state, nodeIndent, withinFlowCollection) { + var preceding, + following, + captureStart, + captureEnd, + hasPendingContent, + _line, + _lineStart, + _lineIndent, + _kind = state.kind, + _result = state.result, + ch; + + ch = state.input.charCodeAt(state.position); + + if (is_WS_OR_EOL(ch) || + is_FLOW_INDICATOR(ch) || + 0x23/* # */ === ch || + 0x26/* & */ === ch || + 0x2A/* * */ === ch || + 0x21/* ! */ === ch || + 0x7C/* | */ === ch || + 0x3E/* > */ === ch || + 0x27/* ' */ === ch || + 0x22/* " */ === ch || + 0x25/* % */ === ch || + 0x40/* @ */ === ch || + 0x60/* ` */ === ch) { + return false; + } + + if (0x3F/* ? */ === ch || 0x2D/* - */ === ch) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + return false; + } + } + + state.kind = 'scalar'; + state.result = ''; + captureStart = captureEnd = state.position; + hasPendingContent = false; + + while (0 !== ch) { + if (0x3A/* : */ === ch) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following) || + withinFlowCollection && is_FLOW_INDICATOR(following)) { + break; + } + + } else if (0x23/* # */ === ch) { + preceding = state.input.charCodeAt(state.position - 1); + + if (is_WS_OR_EOL(preceding)) { + break; + } + + } else if ((state.position === state.lineStart && testDocumentSeparator(state)) || + withinFlowCollection && is_FLOW_INDICATOR(ch)) { + break; + + } else if (is_EOL(ch)) { + _line = state.line; + _lineStart = state.lineStart; + _lineIndent = state.lineIndent; + skipSeparationSpace(state, false, -1); + + if (state.lineIndent >= nodeIndent) { + hasPendingContent = true; + ch = state.input.charCodeAt(state.position); + continue; + } else { + state.position = captureEnd; + state.line = _line; + state.lineStart = _lineStart; + state.lineIndent = _lineIndent; + break; + } + } + + if (hasPendingContent) { + captureSegment(state, captureStart, captureEnd, false); + writeFoldedLines(state, state.line - _line); + captureStart = captureEnd = state.position; + hasPendingContent = false; + } + + if (!is_WHITE_SPACE(ch)) { + captureEnd = state.position + 1; + } + + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, captureEnd, false); + + if (state.result) { + return true; + } + + state.kind = _kind; + state.result = _result; + return false; +} + +function readSingleQuotedScalar(state, nodeIndent) { + var ch, + captureStart, captureEnd; + + ch = state.input.charCodeAt(state.position); + + if (0x27/* ' */ !== ch) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while (0 !== (ch = state.input.charCodeAt(state.position))) { + if (0x27/* ' */ === ch) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (0x27/* ' */ === ch) { + captureStart = captureEnd = state.position; + state.position++; + } else { + return true; + } + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a single quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a single quoted scalar'); +} + +function readDoubleQuotedScalar(state, nodeIndent) { + var captureStart, + captureEnd, + hexLength, + hexResult, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (0x22/* " */ !== ch) { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + state.position++; + captureStart = captureEnd = state.position; + + while (0 !== (ch = state.input.charCodeAt(state.position))) { + if (0x22/* " */ === ch) { + captureSegment(state, captureStart, state.position, true); + state.position++; + return true; + + } else if (0x5C/* \ */ === ch) { + captureSegment(state, captureStart, state.position, true); + ch = state.input.charCodeAt(++state.position); + + if (is_EOL(ch)) { + skipSeparationSpace(state, false, nodeIndent); + + // TODO: rework to inline fn with no type cast? + } else if (ch < 256 && simpleEscapeCheck[ch]) { + state.result += simpleEscapeMap[ch]; + state.position++; + + } else if ((tmp = escapedHexLen(ch)) > 0) { + hexLength = tmp; + hexResult = 0; + + for (; hexLength > 0; hexLength--) { + ch = state.input.charCodeAt(++state.position); + + if ((tmp = fromHexCode(ch)) >= 0) { + hexResult = (hexResult << 4) + tmp; + + } else { + throwError(state, 'expected hexadecimal character'); + } + } + + state.result += charFromCodepoint(hexResult); + + state.position++; + + } else { + throwError(state, 'unknown escape sequence'); + } + + captureStart = captureEnd = state.position; + + } else if (is_EOL(ch)) { + captureSegment(state, captureStart, captureEnd, true); + writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent)); + captureStart = captureEnd = state.position; + + } else if (state.position === state.lineStart && testDocumentSeparator(state)) { + throwError(state, 'unexpected end of the document within a double quoted scalar'); + + } else { + state.position++; + captureEnd = state.position; + } + } + + throwError(state, 'unexpected end of the stream within a double quoted scalar'); +} + +function readFlowCollection(state, nodeIndent) { + var readNext = true, + _line, + _tag = state.tag, + _result, + _anchor = state.anchor, + following, + terminator, + isPair, + isExplicitPair, + isMapping, + keyNode, + keyTag, + valueNode, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x5B/* [ */) { + terminator = 0x5D;/* ] */ + isMapping = false; + _result = []; + } else if (ch === 0x7B/* { */) { + terminator = 0x7D;/* } */ + isMapping = true; + _result = {}; + } else { + return false; + } + + if (null !== state.anchor) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(++state.position); + + while (0 !== ch) { + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (ch === terminator) { + state.position++; + state.tag = _tag; + state.anchor = _anchor; + state.kind = isMapping ? 'mapping' : 'sequence'; + state.result = _result; + return true; + } else if (!readNext) { + throwError(state, 'missed comma between flow collection entries'); + } + + keyTag = keyNode = valueNode = null; + isPair = isExplicitPair = false; + + if (0x3F/* ? */ === ch) { + following = state.input.charCodeAt(state.position + 1); + + if (is_WS_OR_EOL(following)) { + isPair = isExplicitPair = true; + state.position++; + skipSeparationSpace(state, true, nodeIndent); + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + keyTag = state.tag; + keyNode = state.result; + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if ((isExplicitPair || state.line === _line) && 0x3A/* : */ === ch) { + isPair = true; + ch = state.input.charCodeAt(++state.position); + skipSeparationSpace(state, true, nodeIndent); + composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true); + valueNode = state.result; + } + + if (isMapping) { + storeMappingPair(state, _result, keyTag, keyNode, valueNode); + } else if (isPair) { + _result.push(storeMappingPair(state, null, keyTag, keyNode, valueNode)); + } else { + _result.push(keyNode); + } + + skipSeparationSpace(state, true, nodeIndent); + + ch = state.input.charCodeAt(state.position); + + if (0x2C/* , */ === ch) { + readNext = true; + ch = state.input.charCodeAt(++state.position); + } else { + readNext = false; + } + } + + throwError(state, 'unexpected end of the stream within a flow collection'); +} + +function readBlockScalar(state, nodeIndent) { + var captureStart, + folding, + chomping = CHOMPING_CLIP, + detectedIndent = false, + textIndent = nodeIndent, + emptyLines = 0, + atMoreIndented = false, + tmp, + ch; + + ch = state.input.charCodeAt(state.position); + + if (ch === 0x7C/* | */) { + folding = false; + } else if (ch === 0x3E/* > */) { + folding = true; + } else { + return false; + } + + state.kind = 'scalar'; + state.result = ''; + + while (0 !== ch) { + ch = state.input.charCodeAt(++state.position); + + if (0x2B/* + */ === ch || 0x2D/* - */ === ch) { + if (CHOMPING_CLIP === chomping) { + chomping = (0x2B/* + */ === ch) ? CHOMPING_KEEP : CHOMPING_STRIP; + } else { + throwError(state, 'repeat of a chomping mode identifier'); + } + + } else if ((tmp = fromDecimalCode(ch)) >= 0) { + if (tmp === 0) { + throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one'); + } else if (!detectedIndent) { + textIndent = nodeIndent + tmp - 1; + detectedIndent = true; + } else { + throwError(state, 'repeat of an indentation width identifier'); + } + + } else { + break; + } + } + + if (is_WHITE_SPACE(ch)) { + do { ch = state.input.charCodeAt(++state.position); } + while (is_WHITE_SPACE(ch)); + + if (0x23/* # */ === ch) { + do { ch = state.input.charCodeAt(++state.position); } + while (!is_EOL(ch) && (0 !== ch)); + } + } + + while (0 !== ch) { + readLineBreak(state); + state.lineIndent = 0; + + ch = state.input.charCodeAt(state.position); + + while ((!detectedIndent || state.lineIndent < textIndent) && + (0x20/* Space */ === ch)) { + state.lineIndent++; + ch = state.input.charCodeAt(++state.position); + } + + if (!detectedIndent && state.lineIndent > textIndent) { + textIndent = state.lineIndent; + } + + if (is_EOL(ch)) { + emptyLines++; + continue; + } + + // End of the scalar. + if (state.lineIndent < textIndent) { + + // Perform the chomping. + if (chomping === CHOMPING_KEEP) { + state.result += common.repeat('\n', emptyLines); + } else if (chomping === CHOMPING_CLIP) { + if (detectedIndent) { // i.e. only if the scalar is not empty. + state.result += '\n'; + } + } + + // Break this `while` cycle and go to the funciton's epilogue. + break; + } + + // Folded style: use fancy rules to handle line breaks. + if (folding) { + + // Lines starting with white space characters (more-indented lines) are not folded. + if (is_WHITE_SPACE(ch)) { + atMoreIndented = true; + state.result += common.repeat('\n', emptyLines + 1); + + // End of more-indented block. + } else if (atMoreIndented) { + atMoreIndented = false; + state.result += common.repeat('\n', emptyLines + 1); + + // Just one line break - perceive as the same line. + } else if (0 === emptyLines) { + if (detectedIndent) { // i.e. only if we have already read some scalar content. + state.result += ' '; + } + + // Several line breaks - perceive as different lines. + } else { + state.result += common.repeat('\n', emptyLines); + } + + // Literal style: just add exact number of line breaks between content lines. + } else if (detectedIndent) { + // If current line isn't the first one - count line break from the last content line. + state.result += common.repeat('\n', emptyLines + 1); + } else { + // In case of the first content line - count only empty lines. + state.result += common.repeat('\n', emptyLines); + } + + detectedIndent = true; + emptyLines = 0; + captureStart = state.position; + + while (!is_EOL(ch) && (0 !== ch)) { + ch = state.input.charCodeAt(++state.position); + } + + captureSegment(state, captureStart, state.position, false); + } + + return true; +} + +function readBlockSequence(state, nodeIndent) { + var _line, + _tag = state.tag, + _anchor = state.anchor, + _result = [], + following, + detected = false, + ch; + + if (null !== state.anchor) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (0 !== ch) { + + if (0x2D/* - */ !== ch) { + break; + } + + following = state.input.charCodeAt(state.position + 1); + + if (!is_WS_OR_EOL(following)) { + break; + } + + detected = true; + state.position++; + + if (skipSeparationSpace(state, true, -1)) { + if (state.lineIndent <= nodeIndent) { + _result.push(null); + ch = state.input.charCodeAt(state.position); + continue; + } + } + + _line = state.line; + composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true); + _result.push(state.result); + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if ((state.line === _line || state.lineIndent > nodeIndent) && (0 !== ch)) { + throwError(state, 'bad indentation of a sequence entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'sequence'; + state.result = _result; + return true; + } + return false; +} + +function readBlockMapping(state, nodeIndent, flowIndent) { + var following, + allowCompact, + _line, + _tag = state.tag, + _anchor = state.anchor, + _result = {}, + keyTag = null, + keyNode = null, + valueNode = null, + atExplicitKey = false, + detected = false, + ch; + + if (null !== state.anchor) { + state.anchorMap[state.anchor] = _result; + } + + ch = state.input.charCodeAt(state.position); + + while (0 !== ch) { + following = state.input.charCodeAt(state.position + 1); + _line = state.line; // Save the current line. + + // + // Explicit notation case. There are two separate blocks: + // first for the key (denoted by "?") and second for the value (denoted by ":") + // + if ((0x3F/* ? */ === ch || 0x3A/* : */ === ch) && is_WS_OR_EOL(following)) { + + if (0x3F/* ? */ === ch) { + if (atExplicitKey) { + storeMappingPair(state, _result, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = true; + allowCompact = true; + + } else if (atExplicitKey) { + // i.e. 0x3A/* : */ === character after the explicit key. + atExplicitKey = false; + allowCompact = true; + + } else { + throwError(state, 'incomplete explicit mapping pair; a key node is missed'); + } + + state.position += 1; + ch = following; + + // + // Implicit notation case. Flow-style node as the key first, then ":", and the value. + // + } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) { + + if (state.line === _line) { + ch = state.input.charCodeAt(state.position); + + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (0x3A/* : */ === ch) { + ch = state.input.charCodeAt(++state.position); + + if (!is_WS_OR_EOL(ch)) { + throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping'); + } + + if (atExplicitKey) { + storeMappingPair(state, _result, keyTag, keyNode, null); + keyTag = keyNode = valueNode = null; + } + + detected = true; + atExplicitKey = false; + allowCompact = false; + keyTag = state.tag; + keyNode = state.result; + + } else if (detected) { + throwError(state, 'can not read an implicit mapping pair; a colon is missed'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else if (detected) { + throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key'); + + } else { + state.tag = _tag; + state.anchor = _anchor; + return true; // Keep the result of `composeNode`. + } + + } else { + break; // Reading is done. Go to the epilogue. + } + + // + // Common reading code for both explicit and implicit notations. + // + if (state.line === _line || state.lineIndent > nodeIndent) { + if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) { + if (atExplicitKey) { + keyNode = state.result; + } else { + valueNode = state.result; + } + } + + if (!atExplicitKey) { + storeMappingPair(state, _result, keyTag, keyNode, valueNode); + keyTag = keyNode = valueNode = null; + } + + skipSeparationSpace(state, true, -1); + ch = state.input.charCodeAt(state.position); + } + + if (state.lineIndent > nodeIndent && (0 !== ch)) { + throwError(state, 'bad indentation of a mapping entry'); + } else if (state.lineIndent < nodeIndent) { + break; + } + } + + // + // Epilogue. + // + + // Special case: last mapping's node contains only the key in explicit notation. + if (atExplicitKey) { + storeMappingPair(state, _result, keyTag, keyNode, null); + } + + // Expose the resulting mapping. + if (detected) { + state.tag = _tag; + state.anchor = _anchor; + state.kind = 'mapping'; + state.result = _result; + } + + return detected; +} + +function readTagProperty(state) { + var _position, + isVerbatim = false, + isNamed = false, + tagHandle, + tagName, + ch; + + ch = state.input.charCodeAt(state.position); + + if (0x21/* ! */ !== ch) { + return false; + } + + if (null !== state.tag) { + throwError(state, 'duplication of a tag property'); + } + + ch = state.input.charCodeAt(++state.position); + + if (0x3C/* < */ === ch) { + isVerbatim = true; + ch = state.input.charCodeAt(++state.position); + + } else if (0x21/* ! */ === ch) { + isNamed = true; + tagHandle = '!!'; + ch = state.input.charCodeAt(++state.position); + + } else { + tagHandle = '!'; + } + + _position = state.position; + + if (isVerbatim) { + do { ch = state.input.charCodeAt(++state.position); } + while (0 !== ch && 0x3E/* > */ !== ch); + + if (state.position < state.length) { + tagName = state.input.slice(_position, state.position); + ch = state.input.charCodeAt(++state.position); + } else { + throwError(state, 'unexpected end of the stream within a verbatim tag'); + } + } else { + while (0 !== ch && !is_WS_OR_EOL(ch)) { + + if (0x21/* ! */ === ch) { + if (!isNamed) { + tagHandle = state.input.slice(_position - 1, state.position + 1); + + if (!PATTERN_TAG_HANDLE.test(tagHandle)) { + throwError(state, 'named tag handle cannot contain such characters'); + } + + isNamed = true; + _position = state.position + 1; + } else { + throwError(state, 'tag suffix cannot contain exclamation marks'); + } + } + + ch = state.input.charCodeAt(++state.position); + } + + tagName = state.input.slice(_position, state.position); + + if (PATTERN_FLOW_INDICATORS.test(tagName)) { + throwError(state, 'tag suffix cannot contain flow indicator characters'); + } + } + + if (tagName && !PATTERN_TAG_URI.test(tagName)) { + throwError(state, 'tag name cannot contain such characters: ' + tagName); + } + + if (isVerbatim) { + state.tag = tagName; + + } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) { + state.tag = state.tagMap[tagHandle] + tagName; + + } else if ('!' === tagHandle) { + state.tag = '!' + tagName; + + } else if ('!!' === tagHandle) { + state.tag = 'tag:yaml.org,2002:' + tagName; + + } else { + throwError(state, 'undeclared tag handle "' + tagHandle + '"'); + } + + return true; +} + +function readAnchorProperty(state) { + var _position, + ch; + + ch = state.input.charCodeAt(state.position); + + if (0x26/* & */ !== ch) { + return false; + } + + if (null !== state.anchor) { + throwError(state, 'duplication of an anchor property'); + } + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (0 !== ch && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an anchor node must contain at least one character'); + } + + state.anchor = state.input.slice(_position, state.position); + return true; +} + +function readAlias(state) { + var _position, alias, + ch; + + ch = state.input.charCodeAt(state.position); + + if (0x2A/* * */ !== ch) { + return false; + } + + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (0 !== ch && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (state.position === _position) { + throwError(state, 'name of an alias node must contain at least one character'); + } + + alias = state.input.slice(_position, state.position); + + if (!state.anchorMap.hasOwnProperty(alias)) { + throwError(state, 'unidentified alias "' + alias + '"'); + } + + state.result = state.anchorMap[alias]; + skipSeparationSpace(state, true, -1); + return true; +} + +function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) { + var allowBlockStyles, + allowBlockScalars, + allowBlockCollections, + indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } + } + + if (1 === indentStatus) { + while (readTagProperty(state) || readAnchorProperty(state)) { + if (skipSeparationSpace(state, true, -1)) { + atNewLine = true; + allowBlockCollections = allowBlockStyles; + + if (state.lineIndent > parentIndent) { + indentStatus = 1; + } else if (state.lineIndent === parentIndent) { + indentStatus = 0; + } else if (state.lineIndent < parentIndent) { + indentStatus = -1; + } + } else { + allowBlockCollections = false; + } + } + } + + if (allowBlockCollections) { + allowBlockCollections = atNewLine || allowCompact; + } + + if (1 === indentStatus || CONTEXT_BLOCK_OUT === nodeContext) { + if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) { + flowIndent = parentIndent; + } else { + flowIndent = parentIndent + 1; + } + + blockIndent = state.position - state.lineStart; + + if (1 === indentStatus) { + if (allowBlockCollections && + (readBlockSequence(state, blockIndent) || + readBlockMapping(state, blockIndent, flowIndent)) || + readFlowCollection(state, flowIndent)) { + hasContent = true; + } else { + if ((allowBlockScalars && readBlockScalar(state, flowIndent)) || + readSingleQuotedScalar(state, flowIndent) || + readDoubleQuotedScalar(state, flowIndent)) { + hasContent = true; + + } else if (readAlias(state)) { + hasContent = true; + + if (null !== state.tag || null !== state.anchor) { + throwError(state, 'alias node should not have any properties'); + } + + } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) { + hasContent = true; + + if (null === state.tag) { + state.tag = '?'; + } + } + + if (null !== state.anchor) { + state.anchorMap[state.anchor] = state.result; + } + } + } else if (0 === indentStatus) { + // Special case: block sequences are allowed to have same indentation level as the parent. + // http://www.yaml.org/spec/1.2/spec.html#id2799784 + hasContent = allowBlockCollections && readBlockSequence(state, blockIndent); + } + } + + if (null !== state.tag && '!' !== state.tag) { + if ('?' === state.tag) { + for (typeIndex = 0, typeQuantity = state.implicitTypes.length; + typeIndex < typeQuantity; + typeIndex += 1) { + type = state.implicitTypes[typeIndex]; + + // Implicit resolving is not allowed for non-scalar types, and '?' + // non-specific tag is only assigned to plain scalars. So, it isn't + // needed to check for 'kind' conformity. + + if (type.resolve(state.result)) { // `state.result` updated in resolver if matched + state.result = type.construct(state.result); + state.tag = type.tag; + if (null !== state.anchor) { + state.anchorMap[state.anchor] = state.result; + } + break; + } + } + } else if (_hasOwnProperty.call(state.typeMap, state.tag)) { + type = state.typeMap[state.tag]; + + if (null !== state.result && type.kind !== state.kind) { + throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be "' + type.kind + '", not "' + state.kind + '"'); + } + + if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched + throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag'); + } else { + state.result = type.construct(state.result); + if (null !== state.anchor) { + state.anchorMap[state.anchor] = state.result; + } + } + } else { + throwError(state, 'unknown tag !<' + state.tag + '>'); + } + } + + return null !== state.tag || null !== state.anchor || hasContent; +} + +function readDocument(state) { + var documentStart = state.position, + _position, + directiveName, + directiveArgs, + hasDirectives = false, + ch; + + state.version = null; + state.checkLineBreaks = state.legacy; + state.tagMap = {}; + state.anchorMap = {}; + + while (0 !== (ch = state.input.charCodeAt(state.position))) { + skipSeparationSpace(state, true, -1); + + ch = state.input.charCodeAt(state.position); + + if (state.lineIndent > 0 || 0x25/* % */ !== ch) { + break; + } + + hasDirectives = true; + ch = state.input.charCodeAt(++state.position); + _position = state.position; + + while (0 !== ch && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveName = state.input.slice(_position, state.position); + directiveArgs = []; + + if (directiveName.length < 1) { + throwError(state, 'directive name must not be less than one character in length'); + } + + while (0 !== ch) { + while (is_WHITE_SPACE(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + if (0x23/* # */ === ch) { + do { ch = state.input.charCodeAt(++state.position); } + while (0 !== ch && !is_EOL(ch)); + break; + } + + if (is_EOL(ch)) { + break; + } + + _position = state.position; + + while (0 !== ch && !is_WS_OR_EOL(ch)) { + ch = state.input.charCodeAt(++state.position); + } + + directiveArgs.push(state.input.slice(_position, state.position)); + } + + if (0 !== ch) { + readLineBreak(state); + } + + if (_hasOwnProperty.call(directiveHandlers, directiveName)) { + directiveHandlers[directiveName](state, directiveName, directiveArgs); + } else { + throwWarning(state, 'unknown document directive "' + directiveName + '"'); + } + } + + skipSeparationSpace(state, true, -1); + + if (0 === state.lineIndent && + 0x2D/* - */ === state.input.charCodeAt(state.position) && + 0x2D/* - */ === state.input.charCodeAt(state.position + 1) && + 0x2D/* - */ === state.input.charCodeAt(state.position + 2)) { + state.position += 3; + skipSeparationSpace(state, true, -1); + + } else if (hasDirectives) { + throwError(state, 'directives end mark is expected'); + } + + composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true); + skipSeparationSpace(state, true, -1); + + if (state.checkLineBreaks && + PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) { + throwWarning(state, 'non-ASCII line breaks are interpreted as content'); + } + + state.documents.push(state.result); + + if (state.position === state.lineStart && testDocumentSeparator(state)) { + + if (0x2E/* . */ === state.input.charCodeAt(state.position)) { + state.position += 3; + skipSeparationSpace(state, true, -1); + } + return; + } + + if (state.position < (state.length - 1)) { + throwError(state, 'end of the stream or a document separator is expected'); + } else { + return; + } +} + + +function loadDocuments(input, options) { + input = String(input); + options = options || {}; + + if (input.length !== 0) { + + // Add tailing `\n` if not exists + if (0x0A/* LF */ !== input.charCodeAt(input.length - 1) && + 0x0D/* CR */ !== input.charCodeAt(input.length - 1)) { + input += '\n'; + } + + // Strip BOM + if (input.charCodeAt(0) === 0xFEFF) { + input = input.slice(1); + } + } + + var state = new State(input, options); + + // Use 0 as string terminator. That significantly simplifies bounds check. + state.input += '\0'; + + while (0x20/* Space */ === state.input.charCodeAt(state.position)) { + state.lineIndent += 1; + state.position += 1; + } + + while (state.position < (state.length - 1)) { + readDocument(state); + } + + return state.documents; +} + + +function loadAll(input, iterator, options) { + var documents = loadDocuments(input, options), index, length; + + for (index = 0, length = documents.length; index < length; index += 1) { + iterator(documents[index]); + } +} + + +function load(input, options) { + var documents = loadDocuments(input, options); + + if (0 === documents.length) { + /*eslint-disable no-undefined*/ + return undefined; + } else if (1 === documents.length) { + return documents[0]; + } + throw new YAMLException('expected a single document in the stream, but found more'); +} + + +function safeLoadAll(input, output, options) { + loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +function safeLoad(input, options) { + return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options)); +} + + +module.exports.loadAll = loadAll; +module.exports.load = load; +module.exports.safeLoadAll = safeLoadAll; +module.exports.safeLoad = safeLoad; + +},{"./common":22,"./exception":24,"./mark":26,"./schema/default_full":29,"./schema/default_safe":30}],26:[function(require,module,exports){ +'use strict'; + + +var common = require('./common'); + + +function Mark(name, buffer, position, line, column) { + this.name = name; + this.buffer = buffer; + this.position = position; + this.line = line; + this.column = column; +} + + +Mark.prototype.getSnippet = function getSnippet(indent, maxLength) { + var head, start, tail, end, snippet; + + if (!this.buffer) { + return null; + } + + indent = indent || 4; + maxLength = maxLength || 75; + + head = ''; + start = this.position; + + while (start > 0 && -1 === '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1))) { + start -= 1; + if (this.position - start > (maxLength / 2 - 1)) { + head = ' ... '; + start += 5; + break; + } + } + + tail = ''; + end = this.position; + + while (end < this.buffer.length && -1 === '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end))) { + end += 1; + if (end - this.position > (maxLength / 2 - 1)) { + tail = ' ... '; + end -= 5; + break; + } + } + + snippet = this.buffer.slice(start, end); + + return common.repeat(' ', indent) + head + snippet + tail + '\n' + + common.repeat(' ', indent + this.position - start + head.length) + '^'; +}; + + +Mark.prototype.toString = function toString(compact) { + var snippet, where = ''; + + if (this.name) { + where += 'in "' + this.name + '" '; + } + + where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1); + + if (!compact) { + snippet = this.getSnippet(); + + if (snippet) { + where += ':\n' + snippet; + } + } + + return where; +}; + + +module.exports = Mark; + +},{"./common":22}],27:[function(require,module,exports){ +'use strict'; + +/*eslint-disable max-len*/ + +var common = require('./common'); +var YAMLException = require('./exception'); +var Type = require('./type'); + + +function compileList(schema, name, result) { + var exclude = []; + + schema.include.forEach(function (includedSchema) { + result = compileList(includedSchema, name, result); + }); + + schema[name].forEach(function (currentType) { + result.forEach(function (previousType, previousIndex) { + if (previousType.tag === currentType.tag) { + exclude.push(previousIndex); + } + }); + + result.push(currentType); + }); + + return result.filter(function (type, index) { + return -1 === exclude.indexOf(index); + }); +} + + +function compileMap(/* lists... */) { + var result = {}, index, length; + + function collectType(type) { + result[type.tag] = type; + } + + for (index = 0, length = arguments.length; index < length; index += 1) { + arguments[index].forEach(collectType); + } + + return result; +} + + +function Schema(definition) { + this.include = definition.include || []; + this.implicit = definition.implicit || []; + this.explicit = definition.explicit || []; + + this.implicit.forEach(function (type) { + if (type.loadKind && 'scalar' !== type.loadKind) { + throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.'); + } + }); + + this.compiledImplicit = compileList(this, 'implicit', []); + this.compiledExplicit = compileList(this, 'explicit', []); + this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit); +} + + +Schema.DEFAULT = null; + + +Schema.create = function createSchema() { + var schemas, types; + + switch (arguments.length) { + case 1: + schemas = Schema.DEFAULT; + types = arguments[0]; + break; + + case 2: + schemas = arguments[0]; + types = arguments[1]; + break; + + default: + throw new YAMLException('Wrong number of arguments for Schema.create function'); + } + + schemas = common.toArray(schemas); + types = common.toArray(types); + + if (!schemas.every(function (schema) { return schema instanceof Schema; })) { + throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.'); + } + + if (!types.every(function (type) { return type instanceof Type; })) { + throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.'); + } + + return new Schema({ + include: schemas, + explicit: types + }); +}; + + +module.exports = Schema; + +},{"./common":22,"./exception":24,"./type":33}],28:[function(require,module,exports){ +// Standard YAML's Core schema. +// http://www.yaml.org/spec/1.2/spec.html#id2804923 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, Core schema has no distinctions from JSON schema is JS-YAML. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./json') + ] +}); + +},{"../schema":27,"./json":32}],29:[function(require,module,exports){ +// JS-YAML's default schema for `load` function. +// It is not described in the YAML specification. +// +// This schema is based on JS-YAML's default safe schema and includes +// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function. +// +// Also this schema is used as default base schema at `Schema.create` function. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = Schema.DEFAULT = new Schema({ + include: [ + require('./default_safe') + ], + explicit: [ + require('../type/js/undefined'), + require('../type/js/regexp'), + require('../type/js/function') + ] +}); + +},{"../schema":27,"../type/js/function":38,"../type/js/regexp":39,"../type/js/undefined":40,"./default_safe":30}],30:[function(require,module,exports){ +// JS-YAML's default schema for `safeLoad` function. +// It is not described in the YAML specification. +// +// This schema is based on standard YAML's Core schema and includes most of +// extra types described at YAML tag repository. (http://yaml.org/type/) + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./core') + ], + implicit: [ + require('../type/timestamp'), + require('../type/merge') + ], + explicit: [ + require('../type/binary'), + require('../type/omap'), + require('../type/pairs'), + require('../type/set') + ] +}); + +},{"../schema":27,"../type/binary":34,"../type/merge":42,"../type/omap":44,"../type/pairs":45,"../type/set":47,"../type/timestamp":49,"./core":28}],31:[function(require,module,exports){ +// Standard YAML's Failsafe schema. +// http://www.yaml.org/spec/1.2/spec.html#id2802346 + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + explicit: [ + require('../type/str'), + require('../type/seq'), + require('../type/map') + ] +}); + +},{"../schema":27,"../type/map":41,"../type/seq":46,"../type/str":48}],32:[function(require,module,exports){ +// Standard YAML's JSON schema. +// http://www.yaml.org/spec/1.2/spec.html#id2803231 +// +// NOTE: JS-YAML does not support schema-specific tag resolution restrictions. +// So, this schema is not such strict as defined in the YAML specification. +// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc. + + +'use strict'; + + +var Schema = require('../schema'); + + +module.exports = new Schema({ + include: [ + require('./failsafe') + ], + implicit: [ + require('../type/null'), + require('../type/bool'), + require('../type/int'), + require('../type/float') + ] +}); + +},{"../schema":27,"../type/bool":35,"../type/float":36,"../type/int":37,"../type/null":43,"./failsafe":31}],33:[function(require,module,exports){ +'use strict'; + +var YAMLException = require('./exception'); + +var TYPE_CONSTRUCTOR_OPTIONS = [ + 'kind', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'defaultStyle', + 'styleAliases' +]; + +var YAML_NODE_KINDS = [ + 'scalar', + 'sequence', + 'mapping' +]; + +function compileStyleAliases(map) { + var result = {}; + + if (null !== map) { + Object.keys(map).forEach(function (style) { + map[style].forEach(function (alias) { + result[String(alias)] = style; + }); + }); + } + + return result; +} + +function Type(tag, options) { + options = options || {}; + + Object.keys(options).forEach(function (name) { + if (-1 === TYPE_CONSTRUCTOR_OPTIONS.indexOf(name)) { + throw new YAMLException('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.'); + } + }); + + // TODO: Add tag format check. + this.tag = tag; + this.kind = options['kind'] || null; + this.resolve = options['resolve'] || function () { return true; }; + this.construct = options['construct'] || function (data) { return data; }; + this.instanceOf = options['instanceOf'] || null; + this.predicate = options['predicate'] || null; + this.represent = options['represent'] || null; + this.defaultStyle = options['defaultStyle'] || null; + this.styleAliases = compileStyleAliases(options['styleAliases'] || null); + + if (-1 === YAML_NODE_KINDS.indexOf(this.kind)) { + throw new YAMLException('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.'); + } +} + +module.exports = Type; + +},{"./exception":24}],34:[function(require,module,exports){ +'use strict'; + +/*eslint-disable no-bitwise*/ + +// A trick for browserified version. +// Since we make browserifier to ignore `buffer` module, NodeBuffer will be undefined +var NodeBuffer = require('buffer').Buffer; +var Type = require('../type'); + + +// [ 64, 65, 66 ] -> [ padding, CR, LF ] +var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; + + +function resolveYamlBinary(data) { + if (null === data) { + return false; + } + + var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP; + + // Convert one by one. + for (idx = 0; idx < max; idx++) { + code = map.indexOf(data.charAt(idx)); + + // Skip CR/LF + if (code > 64) { continue; } + + // Fail on illegal characters + if (code < 0) { return false; } + + bitlen += 6; + } + + // If there are any bits left, source was corrupted + return (bitlen % 8) === 0; +} + +function constructYamlBinary(data) { + var idx, tailbits, + input = data.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan + max = input.length, + map = BASE64_MAP, + bits = 0, + result = []; + + // Collect by 6*4 bits (3 bytes) + + for (idx = 0; idx < max; idx++) { + if ((idx % 4 === 0) && idx) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } + + bits = (bits << 6) | map.indexOf(input.charAt(idx)); + } + + // Dump tail + + tailbits = (max % 4) * 6; + + if (tailbits === 0) { + result.push((bits >> 16) & 0xFF); + result.push((bits >> 8) & 0xFF); + result.push(bits & 0xFF); + } else if (tailbits === 18) { + result.push((bits >> 10) & 0xFF); + result.push((bits >> 2) & 0xFF); + } else if (tailbits === 12) { + result.push((bits >> 4) & 0xFF); + } + + // Wrap into Buffer for NodeJS and leave Array for browser + if (NodeBuffer) { + return new NodeBuffer(result); + } + + return result; +} + +function representYamlBinary(object /*, style*/) { + var result = '', bits = 0, idx, tail, + max = object.length, + map = BASE64_MAP; + + // Convert every three bytes to 4 ASCII characters. + + for (idx = 0; idx < max; idx++) { + if ((idx % 3 === 0) && idx) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } + + bits = (bits << 8) + object[idx]; + } + + // Dump tail + + tail = max % 3; + + if (tail === 0) { + result += map[(bits >> 18) & 0x3F]; + result += map[(bits >> 12) & 0x3F]; + result += map[(bits >> 6) & 0x3F]; + result += map[bits & 0x3F]; + } else if (tail === 2) { + result += map[(bits >> 10) & 0x3F]; + result += map[(bits >> 4) & 0x3F]; + result += map[(bits << 2) & 0x3F]; + result += map[64]; + } else if (tail === 1) { + result += map[(bits >> 2) & 0x3F]; + result += map[(bits << 4) & 0x3F]; + result += map[64]; + result += map[64]; + } + + return result; +} + +function isBinary(object) { + return NodeBuffer && NodeBuffer.isBuffer(object); +} + +module.exports = new Type('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: resolveYamlBinary, + construct: constructYamlBinary, + predicate: isBinary, + represent: representYamlBinary +}); + +},{"../type":33,"buffer":12}],35:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlBoolean(data) { + if (null === data) { + return false; + } + + var max = data.length; + + return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) || + (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE')); +} + +function constructYamlBoolean(data) { + return data === 'true' || + data === 'True' || + data === 'TRUE'; +} + +function isBoolean(object) { + return '[object Boolean]' === Object.prototype.toString.call(object); +} + +module.exports = new Type('tag:yaml.org,2002:bool', { + kind: 'scalar', + resolve: resolveYamlBoolean, + construct: constructYamlBoolean, + predicate: isBoolean, + represent: { + lowercase: function (object) { return object ? 'true' : 'false'; }, + uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; }, + camelcase: function (object) { return object ? 'True' : 'False'; } + }, + defaultStyle: 'lowercase' +}); + +},{"../type":33}],36:[function(require,module,exports){ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +var YAML_FLOAT_PATTERN = new RegExp( + '^(?:[-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+][0-9]+)?' + + '|\\.[0-9_]+(?:[eE][-+][0-9]+)?' + + '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*' + + '|[-+]?\\.(?:inf|Inf|INF)' + + '|\\.(?:nan|NaN|NAN))$'); + +function resolveYamlFloat(data) { + if (null === data) { + return false; + } + + if (!YAML_FLOAT_PATTERN.test(data)) { + return false; + } + return true; +} + +function constructYamlFloat(data) { + var value, sign, base, digits; + + value = data.replace(/_/g, '').toLowerCase(); + sign = '-' === value[0] ? -1 : 1; + digits = []; + + if (0 <= '+-'.indexOf(value[0])) { + value = value.slice(1); + } + + if ('.inf' === value) { + return (1 === sign) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY; + + } else if ('.nan' === value) { + return NaN; + + } else if (0 <= value.indexOf(':')) { + value.split(':').forEach(function (v) { + digits.unshift(parseFloat(v, 10)); + }); + + value = 0.0; + base = 1; + + digits.forEach(function (d) { + value += d * base; + base *= 60; + }); + + return sign * value; + + } + return sign * parseFloat(value, 10); +} + + +var SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/; + +function representYamlFloat(object, style) { + var res; + + if (isNaN(object)) { + switch (style) { + case 'lowercase': + return '.nan'; + case 'uppercase': + return '.NAN'; + case 'camelcase': + return '.NaN'; + } + } else if (Number.POSITIVE_INFINITY === object) { + switch (style) { + case 'lowercase': + return '.inf'; + case 'uppercase': + return '.INF'; + case 'camelcase': + return '.Inf'; + } + } else if (Number.NEGATIVE_INFINITY === object) { + switch (style) { + case 'lowercase': + return '-.inf'; + case 'uppercase': + return '-.INF'; + case 'camelcase': + return '-.Inf'; + } + } else if (common.isNegativeZero(object)) { + return '-0.0'; + } + + res = object.toString(10); + + // JS stringifier can build scientific format without dots: 5e-100, + // while YAML requres dot: 5.e-100. Fix it with simple hack + + return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res; +} + +function isFloat(object) { + return ('[object Number]' === Object.prototype.toString.call(object)) && + (0 !== object % 1 || common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: resolveYamlFloat, + construct: constructYamlFloat, + predicate: isFloat, + represent: representYamlFloat, + defaultStyle: 'lowercase' +}); + +},{"../common":22,"../type":33}],37:[function(require,module,exports){ +'use strict'; + +var common = require('../common'); +var Type = require('../type'); + +function isHexCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) || + ((0x41/* A */ <= c) && (c <= 0x46/* F */)) || + ((0x61/* a */ <= c) && (c <= 0x66/* f */)); +} + +function isOctCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */)); +} + +function isDecCode(c) { + return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)); +} + +function resolveYamlInteger(data) { + if (null === data) { + return false; + } + + var max = data.length, + index = 0, + hasDigits = false, + ch; + + if (!max) { return false; } + + ch = data[index]; + + // sign + if (ch === '-' || ch === '+') { + ch = data[++index]; + } + + if (ch === '0') { + // 0 + if (index + 1 === max) { return true; } + ch = data[++index]; + + // base 2, base 8, base 16 + + if (ch === 'b') { + // base 2 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') { continue; } + if (ch !== '0' && ch !== '1') { + return false; + } + hasDigits = true; + } + return hasDigits; + } + + + if (ch === 'x') { + // base 16 + index++; + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') { continue; } + if (!isHexCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + return hasDigits; + } + + // base 8 + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') { continue; } + if (!isOctCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + return hasDigits; + } + + // base 10 (except 0) or base 60 + + for (; index < max; index++) { + ch = data[index]; + if (ch === '_') { continue; } + if (ch === ':') { break; } + if (!isDecCode(data.charCodeAt(index))) { + return false; + } + hasDigits = true; + } + + if (!hasDigits) { return false; } + + // if !base60 - done; + if (ch !== ':') { return true; } + + // base60 almost not used, no needs to optimize + return /^(:[0-5]?[0-9])+$/.test(data.slice(index)); +} + +function constructYamlInteger(data) { + var value = data, sign = 1, ch, base, digits = []; + + if (value.indexOf('_') !== -1) { + value = value.replace(/_/g, ''); + } + + ch = value[0]; + + if (ch === '-' || ch === '+') { + if (ch === '-') { sign = -1; } + value = value.slice(1); + ch = value[0]; + } + + if ('0' === value) { + return 0; + } + + if (ch === '0') { + if (value[1] === 'b') { + return sign * parseInt(value.slice(2), 2); + } + if (value[1] === 'x') { + return sign * parseInt(value, 16); + } + return sign * parseInt(value, 8); + + } + + if (value.indexOf(':') !== -1) { + value.split(':').forEach(function (v) { + digits.unshift(parseInt(v, 10)); + }); + + value = 0; + base = 1; + + digits.forEach(function (d) { + value += (d * base); + base *= 60; + }); + + return sign * value; + + } + + return sign * parseInt(value, 10); +} + +function isInteger(object) { + return ('[object Number]' === Object.prototype.toString.call(object)) && + (0 === object % 1 && !common.isNegativeZero(object)); +} + +module.exports = new Type('tag:yaml.org,2002:int', { + kind: 'scalar', + resolve: resolveYamlInteger, + construct: constructYamlInteger, + predicate: isInteger, + represent: { + binary: function (object) { return '0b' + object.toString(2); }, + octal: function (object) { return '0' + object.toString(8); }, + decimal: function (object) { return object.toString(10); }, + hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); } + }, + defaultStyle: 'decimal', + styleAliases: { + binary: [ 2, 'bin' ], + octal: [ 8, 'oct' ], + decimal: [ 10, 'dec' ], + hexadecimal: [ 16, 'hex' ] + } +}); + +},{"../common":22,"../type":33}],38:[function(require,module,exports){ +'use strict'; + +var esprima; + +// Browserified version does not have esprima +// +// 1. For node.js just require module as deps +// 2. For browser try to require mudule via external AMD system. +// If not found - try to fallback to window.esprima. If not +// found too - then fail to parse. +// +try { + esprima = require('esprima'); +} catch (_) { + /*global window */ + if (typeof window !== 'undefined') { esprima = window.esprima; } +} + +var Type = require('../../type'); + +function resolveJavascriptFunction(data) { + if (null === data) { + return false; + } + + try { + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }); + + if ('Program' !== ast.type || + 1 !== ast.body.length || + 'ExpressionStatement' !== ast.body[0].type || + 'FunctionExpression' !== ast.body[0].expression.type) { + return false; + } + + return true; + } catch (err) { + return false; + } +} + +function constructJavascriptFunction(data) { + /*jslint evil:true*/ + + var source = '(' + data + ')', + ast = esprima.parse(source, { range: true }), + params = [], + body; + + if ('Program' !== ast.type || + 1 !== ast.body.length || + 'ExpressionStatement' !== ast.body[0].type || + 'FunctionExpression' !== ast.body[0].expression.type) { + throw new Error('Failed to resolve function'); + } + + ast.body[0].expression.params.forEach(function (param) { + params.push(param.name); + }); + + body = ast.body[0].expression.body.range; + + // Esprima's ranges include the first '{' and the last '}' characters on + // function expressions. So cut them out. + /*eslint-disable no-new-func*/ + return new Function(params, source.slice(body[0] + 1, body[1] - 1)); +} + +function representJavascriptFunction(object /*, style*/) { + return object.toString(); +} + +function isFunction(object) { + return '[object Function]' === Object.prototype.toString.call(object); +} + +module.exports = new Type('tag:yaml.org,2002:js/function', { + kind: 'scalar', + resolve: resolveJavascriptFunction, + construct: constructJavascriptFunction, + predicate: isFunction, + represent: representJavascriptFunction +}); + +},{"../../type":33,"esprima":50}],39:[function(require,module,exports){ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptRegExp(data) { + if (null === data) { + return false; + } + + if (0 === data.length) { + return false; + } + + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // if regexp starts with '/' it can have modifiers and must be properly closed + // `/foo/gim` - modifiers tail can be maximum 3 chars + if ('/' === regexp[0]) { + if (tail) { + modifiers = tail[1]; + } + + if (modifiers.length > 3) { return false; } + // if expression starts with /, is should be properly terminated + if (regexp[regexp.length - modifiers.length - 1] !== '/') { return false; } + + regexp = regexp.slice(1, regexp.length - modifiers.length - 1); + } + + try { + return true; + } catch (error) { + return false; + } +} + +function constructJavascriptRegExp(data) { + var regexp = data, + tail = /\/([gim]*)$/.exec(data), + modifiers = ''; + + // `/foo/gim` - tail can be maximum 4 chars + if ('/' === regexp[0]) { + if (tail) { + modifiers = tail[1]; + } + regexp = regexp.slice(1, regexp.length - modifiers.length - 1); + } + + return new RegExp(regexp, modifiers); +} + +function representJavascriptRegExp(object /*, style*/) { + var result = '/' + object.source + '/'; + + if (object.global) { + result += 'g'; + } + + if (object.multiline) { + result += 'm'; + } + + if (object.ignoreCase) { + result += 'i'; + } + + return result; +} + +function isRegExp(object) { + return '[object RegExp]' === Object.prototype.toString.call(object); +} + +module.exports = new Type('tag:yaml.org,2002:js/regexp', { + kind: 'scalar', + resolve: resolveJavascriptRegExp, + construct: constructJavascriptRegExp, + predicate: isRegExp, + represent: representJavascriptRegExp +}); + +},{"../../type":33}],40:[function(require,module,exports){ +'use strict'; + +var Type = require('../../type'); + +function resolveJavascriptUndefined() { + return true; +} + +function constructJavascriptUndefined() { + /*eslint-disable no-undefined*/ + return undefined; +} + +function representJavascriptUndefined() { + return ''; +} + +function isUndefined(object) { + return 'undefined' === typeof object; +} + +module.exports = new Type('tag:yaml.org,2002:js/undefined', { + kind: 'scalar', + resolve: resolveJavascriptUndefined, + construct: constructJavascriptUndefined, + predicate: isUndefined, + represent: representJavascriptUndefined +}); + +},{"../../type":33}],41:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (data) { return null !== data ? data : {}; } +}); + +},{"../type":33}],42:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlMerge(data) { + return '<<' === data || null === data; +} + +module.exports = new Type('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: resolveYamlMerge +}); + +},{"../type":33}],43:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +function resolveYamlNull(data) { + if (null === data) { + return true; + } + + var max = data.length; + + return (max === 1 && data === '~') || + (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL')); +} + +function constructYamlNull() { + return null; +} + +function isNull(object) { + return null === object; +} + +module.exports = new Type('tag:yaml.org,2002:null', { + kind: 'scalar', + resolve: resolveYamlNull, + construct: constructYamlNull, + predicate: isNull, + represent: { + canonical: function () { return '~'; }, + lowercase: function () { return 'null'; }, + uppercase: function () { return 'NULL'; }, + camelcase: function () { return 'Null'; } + }, + defaultStyle: 'lowercase' +}); + +},{"../type":33}],44:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; +var _toString = Object.prototype.toString; + +function resolveYamlOmap(data) { + if (null === data) { + return true; + } + + var objectKeys = [], index, length, pair, pairKey, pairHasKey, + object = data; + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + pairHasKey = false; + + if ('[object Object]' !== _toString.call(pair)) { + return false; + } + + for (pairKey in pair) { + if (_hasOwnProperty.call(pair, pairKey)) { + if (!pairHasKey) { + pairHasKey = true; + } else { + return false; + } + } + } + + if (!pairHasKey) { + return false; + } + + if (-1 === objectKeys.indexOf(pairKey)) { + objectKeys.push(pairKey); + } else { + return false; + } + } + + return true; +} + +function constructYamlOmap(data) { + return null !== data ? data : []; +} + +module.exports = new Type('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: resolveYamlOmap, + construct: constructYamlOmap +}); + +},{"../type":33}],45:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _toString = Object.prototype.toString; + +function resolveYamlPairs(data) { + if (null === data) { + return true; + } + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + if ('[object Object]' !== _toString.call(pair)) { + return false; + } + + keys = Object.keys(pair); + + if (1 !== keys.length) { + return false; + } + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return true; +} + +function constructYamlPairs(data) { + if (null === data) { + return []; + } + + var index, length, pair, keys, result, + object = data; + + result = new Array(object.length); + + for (index = 0, length = object.length; index < length; index += 1) { + pair = object[index]; + + keys = Object.keys(pair); + + result[index] = [ keys[0], pair[keys[0]] ]; + } + + return result; +} + +module.exports = new Type('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: resolveYamlPairs, + construct: constructYamlPairs +}); + +},{"../type":33}],46:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (data) { return null !== data ? data : []; } +}); + +},{"../type":33}],47:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var _hasOwnProperty = Object.prototype.hasOwnProperty; + +function resolveYamlSet(data) { + if (null === data) { + return true; + } + + var key, object = data; + + for (key in object) { + if (_hasOwnProperty.call(object, key)) { + if (null !== object[key]) { + return false; + } + } + } + + return true; +} + +function constructYamlSet(data) { + return null !== data ? data : {}; +} + +module.exports = new Type('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: resolveYamlSet, + construct: constructYamlSet +}); + +},{"../type":33}],48:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +module.exports = new Type('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (data) { return null !== data ? data : ''; } +}); + +},{"../type":33}],49:[function(require,module,exports){ +'use strict'; + +var Type = require('../type'); + +var YAML_TIMESTAMP_REGEXP = new RegExp( + '^([0-9][0-9][0-9][0-9])' + // [1] year + '-([0-9][0-9]?)' + // [2] month + '-([0-9][0-9]?)' + // [3] day + '(?:(?:[Tt]|[ \\t]+)' + // ... + '([0-9][0-9]?)' + // [4] hour + ':([0-9][0-9])' + // [5] minute + ':([0-9][0-9])' + // [6] second + '(?:\\.([0-9]*))?' + // [7] fraction + '(?:[ \\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour + '(?::([0-9][0-9]))?))?)?$'); // [11] tz_minute + +function resolveYamlTimestamp(data) { + if (null === data) { + return false; + } + + if (YAML_TIMESTAMP_REGEXP.exec(data) === null) { + return false; + } + + return true; +} + +function constructYamlTimestamp(data) { + var match, year, month, day, hour, minute, second, fraction = 0, + delta = null, tz_hour, tz_minute, date; + + match = YAML_TIMESTAMP_REGEXP.exec(data); + + if (null === match) { + throw new Error('Date resolve error'); + } + + // match: [1] year [2] month [3] day + + year = +(match[1]); + month = +(match[2]) - 1; // JS month starts with 0 + day = +(match[3]); + + if (!match[4]) { // no hour + return new Date(Date.UTC(year, month, day)); + } + + // match: [4] hour [5] minute [6] second [7] fraction + + hour = +(match[4]); + minute = +(match[5]); + second = +(match[6]); + + if (match[7]) { + fraction = match[7].slice(0, 3); + while (fraction.length < 3) { // milli-seconds + fraction += '0'; + } + fraction = +fraction; + } + + // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute + + if (match[9]) { + tz_hour = +(match[10]); + tz_minute = +(match[11] || 0); + delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds + if ('-' === match[9]) { + delta = -delta; + } + } + + date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction)); + + if (delta) { + date.setTime(date.getTime() - delta); + } + + return date; +} + +function representYamlTimestamp(object /*, style*/) { + return object.toISOString(); +} + +module.exports = new Type('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: resolveYamlTimestamp, + construct: constructYamlTimestamp, + instanceOf: Date, + represent: representYamlTimestamp +}); + +},{"../type":33}],50:[function(require,module,exports){ +/* + Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + + /* istanbul ignore next */ + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PlaceHolders, + Messages, + Regex, + source, + strict, + index, + lineNumber, + lineStart, + hasLineTerminator, + lastIndex, + lastLineNumber, + lastLineStart, + startIndex, + startLineNumber, + startLineStart, + scanning, + length, + lookahead, + state, + extra, + isBindingElement, + isAssignmentTarget, + firstCoverInitializedNameError; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9, + Template: 10 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + TokenName[Token.Template] = 'Template'; + + // A function following one of those tokens is an expression. + FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', + 'return', 'case', 'delete', 'throw', 'void', + // assignment operators + '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=', + '&=', '|=', '^=', ',', + // binary/unary operators + '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&', + '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', + '<=', '<', '>', '!=', '!==']; + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + AssignmentPattern: 'AssignmentPattern', + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExportAllDeclaration: 'ExportAllDeclaration', + ExportDefaultDeclaration: 'ExportDefaultDeclaration', + ExportNamedDeclaration: 'ExportNamedDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForOfStatement: 'ForOfStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MetaProperty: 'MetaProperty', + MethodDefinition: 'MethodDefinition', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + RestElement: 'RestElement', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + Super: 'Super', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + YieldExpression: 'YieldExpression' + }; + + PlaceHolders = { + ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder' + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalReturn: 'Illegal return statement', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', + ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', + DefaultRestParameter: 'Unexpected token =', + ObjectPatternAsRestParameter: 'Unexpected token {', + DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', + ConstructorSpecialMethod: 'Class constructor may not be an accessor', + DuplicateConstructor: 'A class may only have one constructor', + StaticPrototype: 'Classes may not have static property named prototype', + MissingFromClause: 'Unexpected token', + NoAsAfterImportNamespace: 'Unexpected token', + InvalidModuleSpecifier: 'Unexpected token', + IllegalImportDeclaration: 'Unexpected token', + IllegalExportDeclaration: 'Unexpected token', + DuplicateBinding: 'Duplicate binding %0' + }; + + // See also tools/generate-unicode-regex.js. + Regex = { + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart: + NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/, + + // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart: + NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + /* istanbul ignore if */ + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 0x30 && ch <= 0x39); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + function octalToDecimal(ch) { + // \0 is not octal escape sequence + var octal = (ch !== '0'), code = '01234567'.indexOf(ch); + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + + return { + code: code, + octal: octal + }; + } + + // ECMA-262 11.2 White Space + + function isWhiteSpace(ch) { + return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || + (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); + } + + // ECMA-262 11.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029); + } + + // ECMA-262 11.6 Identifier Names and Identifiers + + function fromCodePoint(cp) { + return (cp < 0x10000) ? String.fromCharCode(cp) : + String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + + String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); + } + + function isIdentifierStart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch >= 0x30 && ch <= 0x39) || // 0..9 + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch))); + } + + // ECMA-262 11.6.2.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'enum': + case 'export': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // ECMA-262 11.6.2.1 Keywords + + function isKeyword(id) { + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // ECMA-262 11.4 Comments + + function addComment(type, value, start, end, loc) { + var comment; + + assert(typeof start === 'number', 'Comment must have valid position'); + + state.lastCommentStart = start; + + comment = { + type: type, + value: value + }; + if (extra.range) { + comment.range = [start, end]; + } + if (extra.loc) { + comment.loc = loc; + } + extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } + if (extra.tokenize) { + comment.type = comment.type + 'Comment'; + if (extra.delegate) { + comment = extra.delegate(comment); + } + extra.tokens.push(comment); + } + } + + function skipSingleLineComment(offset) { + var start, loc, ch, comment; + + start = index - offset; + loc = { + start: { + line: lineNumber, + column: index - lineStart - offset + } + }; + + while (index < length) { + ch = source.charCodeAt(index); + ++index; + if (isLineTerminator(ch)) { + hasLineTerminator = true; + if (extra.comments) { + comment = source.slice(start + offset, index - 1); + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + addComment('Line', comment, start, index - 1, loc); + } + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + return; + } + } + + if (extra.comments) { + comment = source.slice(start + offset, index); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Line', comment, start, index, loc); + } + } + + function skipMultiLineComment() { + var start, loc, ch, comment; + + if (extra.comments) { + start = index - 2; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (isLineTerminator(ch)) { + if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) { + ++index; + } + hasLineTerminator = true; + ++lineNumber; + ++index; + lineStart = index; + } else if (ch === 0x2A) { + // Block comment ends with '*/'. + if (source.charCodeAt(index + 1) === 0x2F) { + ++index; + ++index; + if (extra.comments) { + comment = source.slice(start + 2, index - 2); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + } + return; + } + ++index; + } else { + ++index; + } + } + + // Ran off the end of the file - the whole thing is a comment + if (extra.comments) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + comment = source.slice(start + 2, index); + addComment('Block', comment, start, index, loc); + } + tolerateUnexpectedToken(); + } + + function skipComment() { + var ch, start; + hasLineTerminator = false; + + start = (index === 0); + while (index < length) { + ch = source.charCodeAt(index); + + if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + hasLineTerminator = true; + ++index; + if (ch === 0x0D && source.charCodeAt(index) === 0x0A) { + ++index; + } + ++lineNumber; + lineStart = index; + start = true; + } else if (ch === 0x2F) { // U+002F is '/' + ch = source.charCodeAt(index + 1); + if (ch === 0x2F) { + ++index; + ++index; + skipSingleLineComment(2); + start = true; + } else if (ch === 0x2A) { // U+002A is '*' + ++index; + ++index; + skipMultiLineComment(); + } else { + break; + } + } else if (start && ch === 0x2D) { // U+002D is '-' + // U+003E is '>' + if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) { + // '-->' is a single-line comment + index += 3; + skipSingleLineComment(3); + } else { + break; + } + } else if (ch === 0x3C) { // U+003C is '<' + if (source.slice(index + 1, index + 4) === '!--') { + ++index; // `<` + ++index; // `!` + ++index; // `-` + ++index; // `-` + skipSingleLineComment(4); + } else { + break; + } + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwUnexpectedToken(); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwUnexpectedToken(); + } + + return fromCodePoint(code); + } + + function codePointAt(i) { + var cp, first, second; + + cp = source.charCodeAt(i); + if (cp >= 0xD800 && cp <= 0xDBFF) { + second = source.charCodeAt(i + 1); + if (second >= 0xDC00 && second <= 0xDFFF) { + first = cp; + cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; + } + } + + return cp; + } + + function getComplexIdentifier() { + var cp, ch, id; + + cp = codePointAt(index); + id = fromCodePoint(cp); + index += id.length; + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (cp === 0x5C) { + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + if (source[index] === '{') { + ++index; + ch = scanUnicodeCodePointEscape(); + } else { + ch = scanHexEscape('u'); + cp = ch.charCodeAt(0); + if (!ch || ch === '\\' || !isIdentifierStart(cp)) { + throwUnexpectedToken(); + } + } + id = ch; + } + + while (index < length) { + cp = codePointAt(index); + if (!isIdentifierPart(cp)) { + break; + } + ch = fromCodePoint(cp); + id += ch; + index += ch.length; + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (cp === 0x5C) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + if (source[index] === '{') { + ++index; + ch = scanUnicodeCodePointEscape(); + } else { + ch = scanHexEscape('u'); + cp = ch.charCodeAt(0); + if (!ch || ch === '\\' || !isIdentifierPart(cp)) { + throwUnexpectedToken(); + } + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 0x5C) { + // Blackslash (U+005C) marks Unicode escape sequence. + index = start; + return getComplexIdentifier(); + } else if (ch >= 0xD800 && ch < 0xDFFF) { + // Need to handle surrogate pairs. + index = start; + return getComplexIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (U+005C) starts an escaped character. + id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + + // ECMA-262 11.7 Punctuators + + function scanPunctuator() { + var token, str; + + token = { + type: Token.Punctuator, + value: '', + lineNumber: lineNumber, + lineStart: lineStart, + start: index, + end: index + }; + + // Check for most common single-character punctuators. + str = source[index]; + switch (str) { + + case '(': + if (extra.tokenize) { + extra.openParenToken = extra.tokenValues.length; + } + ++index; + break; + + case '{': + if (extra.tokenize) { + extra.openCurlyToken = extra.tokenValues.length; + } + state.curlyStack.push('{'); + ++index; + break; + + case '.': + ++index; + if (source[index] === '.' && source[index + 1] === '.') { + // Spread operator: ... + index += 2; + str = '...'; + } + break; + + case '}': + ++index; + state.curlyStack.pop(); + break; + case ')': + case ';': + case ',': + case '[': + case ']': + case ':': + case '?': + case '~': + ++index; + break; + + default: + // 4-character punctuator. + str = source.substr(index, 4); + if (str === '>>>=') { + index += 4; + } else { + + // 3-character punctuators. + str = str.substr(0, 3); + if (str === '===' || str === '!==' || str === '>>>' || + str === '<<=' || str === '>>=') { + index += 3; + } else { + + // 2-character punctuators. + str = str.substr(0, 2); + if (str === '&&' || str === '||' || str === '==' || str === '!=' || + str === '+=' || str === '-=' || str === '*=' || str === '/=' || + str === '++' || str === '--' || str === '<<' || str === '>>' || + str === '&=' || str === '|=' || str === '^=' || str === '%=' || + str === '<=' || str === '>=' || str === '=>') { + index += 2; + } else { + + // 1-character punctuators. + str = source[index]; + if ('<>=!+-*%&|^/'.indexOf(str) >= 0) { + ++index; + } + } + } + } + } + + if (index === token.start) { + throwUnexpectedToken(); + } + + token.end = index; + token.value = str; + return token; + } + + // ECMA-262 11.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanBinaryLiteral(start) { + var ch, number; + + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwUnexpectedToken(); + } + + if (index < length) { + ch = source.charCodeAt(index); + /* istanbul ignore else */ + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwUnexpectedToken(); + } + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function isImplicitOctalLiteral() { + var i, ch; + + // Implicit octal, unless there is a non-octal digit. + // (Annex B.1.1 on Numeric Literals) + for (i = index + 1; i < length; ++i) { + ch = source[i]; + if (ch === '8' || ch === '9') { + return false; + } + if (!isOctalDigit(ch)) { + return true; + } + } + + return true; + } + + function scanNumericLiteral() { + var number, start, ch; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + return scanBinaryLiteral(start); + } + if (ch === 'o' || ch === 'O') { + return scanOctalLiteral(ch, start); + } + + if (isOctalDigit(ch)) { + if (isImplicitOctalLiteral()) { + return scanOctalLiteral(ch, start); + } + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwUnexpectedToken(); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, unescaped, octToDec, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + unescaped = scanHexEscape(ch); + if (!unescaped) { + throw throwUnexpectedToken(); + } + str += unescaped; + } + break; + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + case '8': + case '9': + str += ch; + tolerateUnexpectedToken(); + break; + + default: + if (isOctalDigit(ch)) { + octToDec = octalToDecimal(ch); + + octal = octToDec.octal || octal; + str += String.fromCharCode(octToDec.code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwUnexpectedToken(); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: startLineNumber, + lineStart: startLineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.6 Template Literal Lexical Components + + function scanTemplate() { + var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped; + + terminated = false; + tail = false; + start = index; + head = (source[index] === '`'); + rawOffset = 2; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + rawOffset = 1; + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + state.curlyStack.push('${'); + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (ch === '0') { + if (isDecimalDigit(source.charCodeAt(index))) { + // Illegal: \01 \02 and so on + throwError(Messages.TemplateOctalLiteral); + } + cooked += '\0'; + } else if (isOctalDigit(ch)) { + // Illegal: \1 \2 + throwError(Messages.TemplateOctalLiteral); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + cooked += '\n'; + } else { + cooked += ch; + } + } + + if (!terminated) { + throwUnexpectedToken(); + } + + if (!head) { + state.curlyStack.pop(); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - rawOffset) + }, + head: head, + tail: tail, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // ECMA-262 11.8.5 Regular Expression Literals + + function testRegExp(pattern, flags) { + // The BMP character to use as a replacement for astral symbols when + // translating an ES6 "u"-flagged pattern to an ES5-compatible + // approximation. + // Note: replacing with '\uFFFF' enables false positives in unlikely + // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid + // pattern that would not be detected by this substitution. + var astralSubstitute = '\uFFFF', + tmp = pattern; + + if (flags.indexOf('u') >= 0) { + tmp = tmp + // Replace every Unicode escape sequence with the equivalent + // BMP character or a constant ASCII code point in the case of + // astral symbols. (See the above note on `astralSubstitute` + // for more information.) + .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) { + var codePoint = parseInt($1 || $2, 16); + if (codePoint > 0x10FFFF) { + throwUnexpectedToken(null, Messages.InvalidRegExp); + } + if (codePoint <= 0xFFFF) { + return String.fromCharCode(codePoint); + } + return astralSubstitute; + }) + // Replace each paired surrogate with a single ASCII symbol to + // avoid throwing on regular expressions that are only valid in + // combination with the "u" flag. + .replace( + /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + astralSubstitute + ); + } + + // First, detect invalid regular expressions. + try { + RegExp(tmp); + } catch (e) { + throwUnexpectedToken(null, Messages.InvalidRegExp); + } + + // Return a regular expression object for this pattern-flag pair, or + // `null` in case the current environment doesn't support the flags it + // uses. + try { + return new RegExp(pattern, flags); + } catch (exception) { + return null; + } + } + + function scanRegExpBody() { + var ch, str, classMarker, terminated, body; + + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + classMarker = false; + terminated = false; + while (index < length) { + ch = source[index++]; + str += ch; + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } + str += ch; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } else if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } + } + } + + if (!terminated) { + throwUnexpectedToken(null, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + body = str.substr(1, str.length - 2); + return { + value: body, + literal: str + }; + } + + function scanRegExpFlags() { + var ch, str, flags, restore; + + str = ''; + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + tolerateUnexpectedToken(); + } else { + str += '\\'; + tolerateUnexpectedToken(); + } + } else { + flags += ch; + str += ch; + } + } + + return { + value: flags, + literal: str + }; + } + + function scanRegExp() { + var start, body, flags, value; + scanning = true; + + lookahead = null; + skipComment(); + start = index; + + body = scanRegExpBody(); + flags = scanRegExpFlags(); + value = testRegExp(body.value, flags.value); + scanning = false; + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + return { + literal: body.literal + flags.literal, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + start: start, + end: index + }; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = scanRegExp(); + + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + /* istanbul ignore next */ + if (!extra.tokenize) { + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + regex: regex.regex, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + + function advanceSlash() { + var regex, previous, check; + + function testKeyword(value) { + return value && (value.length > 1) && (value[0] >= 'a') && (value[0] <= 'z'); + } + + previous = extra.tokenValues[extra.tokens.length - 1]; + regex = (previous !== null); + + switch (previous) { + case 'this': + case ']': + regex = false; + break; + + case ')': + check = extra.tokenValues[extra.openParenToken - 1]; + regex = (check === 'if' || check === 'while' || check === 'for' || check === 'with'); + break; + + case '}': + // Dividing a function by anything makes little sense, + // but we have to check for that. + regex = false; + if (testKeyword(extra.tokenValues[extra.openCurlyToken - 3])) { + // Anonymous function, e.g. function(){} /42 + check = extra.tokenValues[extra.openCurlyToken - 4]; + regex = check ? (FnExprTokens.indexOf(check) < 0) : false; + } else if (testKeyword(extra.tokenValues[extra.openCurlyToken - 4])) { + // Named function, e.g. function f(){} /42/ + check = extra.tokenValues[extra.openCurlyToken - 5]; + regex = check ? (FnExprTokens.indexOf(check) < 0) : true; + } + } + + return regex ? collectRegex() : scanPunctuator(); + } + + function advance() { + var cp, token; + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + start: index, + end: index + }; + } + + cp = source.charCodeAt(index); + + if (isIdentifierStart(cp)) { + token = scanIdentifier(); + if (strict && isStrictModeReservedWord(token.value)) { + token.type = Token.Keyword; + } + return token; + } + + // Very common: ( and ) and ; + if (cp === 0x28 || cp === 0x29 || cp === 0x3B) { + return scanPunctuator(); + } + + // String literal starts with single quote (U+0027) or double quote (U+0022). + if (cp === 0x27 || cp === 0x22) { + return scanStringLiteral(); + } + + // Dot (.) U+002E can also start a floating-point number, hence the need + // to check the next character. + if (cp === 0x2E) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(cp)) { + return scanNumericLiteral(); + } + + // Slash (/) U+002F can also start a regex. + if (extra.tokenize && cp === 0x2F) { + return advanceSlash(); + } + + // Template literals start with ` (U+0060) for template head + // or } (U+007D) for template middle or template tail. + if (cp === 0x60 || (cp === 0x7D && state.curlyStack[state.curlyStack.length - 1] === '${')) { + return scanTemplate(); + } + + // Possible identifier start in a surrogate pair. + if (cp >= 0xD800 && cp < 0xDFFF) { + cp = codePointAt(index); + if (isIdentifierStart(cp)) { + return scanIdentifier(); + } + } + + return scanPunctuator(); + } + + function collectToken() { + var loc, token, value, entry; + + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + value = source.slice(token.start, token.end); + entry = { + type: TokenName[token.type], + value: value, + range: [token.start, token.end], + loc: loc + }; + if (token.regex) { + entry.regex = { + pattern: token.regex.pattern, + flags: token.regex.flags + }; + } + if (extra.tokenValues) { + extra.tokenValues.push((entry.type === 'Punctuator' || entry.type === 'Keyword') ? entry.value : null); + } + if (extra.tokenize) { + if (!extra.range) { + delete entry.range; + } + if (!extra.loc) { + delete entry.loc; + } + if (extra.delegate) { + entry = extra.delegate(entry); + } + } + extra.tokens.push(entry); + } + + return token; + } + + function lex() { + var token; + scanning = true; + + lastIndex = index; + lastLineNumber = lineNumber; + lastLineStart = lineStart; + + skipComment(); + + token = lookahead; + + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + scanning = false; + return token; + } + + function peek() { + scanning = true; + + skipComment(); + + lastIndex = index; + lastLineNumber = lineNumber; + lastLineStart = lineStart; + + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + scanning = false; + } + + function Position() { + this.line = startLineNumber; + this.column = startIndex - startLineStart; + } + + function SourceLocation() { + this.start = new Position(); + this.end = null; + } + + function WrappingSourceLocation(startToken) { + this.start = { + line: startToken.lineNumber, + column: startToken.start - startToken.lineStart + }; + this.end = null; + } + + function Node() { + if (extra.range) { + this.range = [startIndex, 0]; + } + if (extra.loc) { + this.loc = new SourceLocation(); + } + } + + function WrappingNode(startToken) { + if (extra.range) { + this.range = [startToken.start, 0]; + } + if (extra.loc) { + this.loc = new WrappingSourceLocation(startToken); + } + } + + WrappingNode.prototype = Node.prototype = { + + processComment: function () { + var lastChild, + innerComments, + leadingComments, + trailingComments, + bottomRight = extra.bottomRightStack, + i, + comment, + last = bottomRight[bottomRight.length - 1]; + + if (this.type === Syntax.Program) { + if (this.body.length > 0) { + return; + } + } + /** + * patch innnerComments for properties empty block + * `function a() {/** comments **\/}` + */ + + if (this.type === Syntax.BlockStatement && this.body.length === 0) { + innerComments = []; + for (i = extra.leadingComments.length - 1; i >= 0; --i) { + comment = extra.leadingComments[i]; + if (this.range[1] >= comment.range[1]) { + innerComments.unshift(comment); + extra.leadingComments.splice(i, 1); + extra.trailingComments.splice(i, 1); + } + } + if (innerComments.length) { + this.innerComments = innerComments; + //bottomRight.push(this); + return; + } + } + + if (extra.trailingComments.length > 0) { + trailingComments = []; + for (i = extra.trailingComments.length - 1; i >= 0; --i) { + comment = extra.trailingComments[i]; + if (comment.range[0] >= this.range[1]) { + trailingComments.unshift(comment); + extra.trailingComments.splice(i, 1); + } + } + extra.trailingComments = []; + } else { + if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) { + trailingComments = last.trailingComments; + delete last.trailingComments; + } + } + + // Eating the stack. + while (last && last.range[0] >= this.range[0]) { + lastChild = bottomRight.pop(); + last = bottomRight[bottomRight.length - 1]; + } + + if (lastChild) { + if (lastChild.leadingComments) { + leadingComments = []; + for (i = lastChild.leadingComments.length - 1; i >= 0; --i) { + comment = lastChild.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + lastChild.leadingComments.splice(i, 1); + } + } + + if (!lastChild.leadingComments.length) { + lastChild.leadingComments = undefined; + } + } + } else if (extra.leadingComments.length > 0) { + leadingComments = []; + for (i = extra.leadingComments.length - 1; i >= 0; --i) { + comment = extra.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + extra.leadingComments.splice(i, 1); + } + } + } + + + if (leadingComments && leadingComments.length > 0) { + this.leadingComments = leadingComments; + } + if (trailingComments && trailingComments.length > 0) { + this.trailingComments = trailingComments; + } + + bottomRight.push(this); + }, + + finish: function () { + if (extra.range) { + this.range[1] = lastIndex; + } + if (extra.loc) { + this.loc.end = { + line: lastLineNumber, + column: lastIndex - lastLineStart + }; + if (extra.source) { + this.loc.source = extra.source; + } + } + + if (extra.attachComment) { + this.processComment(); + } + }, + + finishArrayExpression: function (elements) { + this.type = Syntax.ArrayExpression; + this.elements = elements; + this.finish(); + return this; + }, + + finishArrayPattern: function (elements) { + this.type = Syntax.ArrayPattern; + this.elements = elements; + this.finish(); + return this; + }, + + finishArrowFunctionExpression: function (params, defaults, body, expression) { + this.type = Syntax.ArrowFunctionExpression; + this.id = null; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = false; + this.expression = expression; + this.finish(); + return this; + }, + + finishAssignmentExpression: function (operator, left, right) { + this.type = Syntax.AssignmentExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishAssignmentPattern: function (left, right) { + this.type = Syntax.AssignmentPattern; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBinaryExpression: function (operator, left, right) { + this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBlockStatement: function (body) { + this.type = Syntax.BlockStatement; + this.body = body; + this.finish(); + return this; + }, + + finishBreakStatement: function (label) { + this.type = Syntax.BreakStatement; + this.label = label; + this.finish(); + return this; + }, + + finishCallExpression: function (callee, args) { + this.type = Syntax.CallExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishCatchClause: function (param, body) { + this.type = Syntax.CatchClause; + this.param = param; + this.body = body; + this.finish(); + return this; + }, + + finishClassBody: function (body) { + this.type = Syntax.ClassBody; + this.body = body; + this.finish(); + return this; + }, + + finishClassDeclaration: function (id, superClass, body) { + this.type = Syntax.ClassDeclaration; + this.id = id; + this.superClass = superClass; + this.body = body; + this.finish(); + return this; + }, + + finishClassExpression: function (id, superClass, body) { + this.type = Syntax.ClassExpression; + this.id = id; + this.superClass = superClass; + this.body = body; + this.finish(); + return this; + }, + + finishConditionalExpression: function (test, consequent, alternate) { + this.type = Syntax.ConditionalExpression; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishContinueStatement: function (label) { + this.type = Syntax.ContinueStatement; + this.label = label; + this.finish(); + return this; + }, + + finishDebuggerStatement: function () { + this.type = Syntax.DebuggerStatement; + this.finish(); + return this; + }, + + finishDoWhileStatement: function (body, test) { + this.type = Syntax.DoWhileStatement; + this.body = body; + this.test = test; + this.finish(); + return this; + }, + + finishEmptyStatement: function () { + this.type = Syntax.EmptyStatement; + this.finish(); + return this; + }, + + finishExpressionStatement: function (expression) { + this.type = Syntax.ExpressionStatement; + this.expression = expression; + this.finish(); + return this; + }, + + finishForStatement: function (init, test, update, body) { + this.type = Syntax.ForStatement; + this.init = init; + this.test = test; + this.update = update; + this.body = body; + this.finish(); + return this; + }, + + finishForOfStatement: function (left, right, body) { + this.type = Syntax.ForOfStatement; + this.left = left; + this.right = right; + this.body = body; + this.finish(); + return this; + }, + + finishForInStatement: function (left, right, body) { + this.type = Syntax.ForInStatement; + this.left = left; + this.right = right; + this.body = body; + this.each = false; + this.finish(); + return this; + }, + + finishFunctionDeclaration: function (id, params, defaults, body, generator) { + this.type = Syntax.FunctionDeclaration; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = generator; + this.expression = false; + this.finish(); + return this; + }, + + finishFunctionExpression: function (id, params, defaults, body, generator) { + this.type = Syntax.FunctionExpression; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.generator = generator; + this.expression = false; + this.finish(); + return this; + }, + + finishIdentifier: function (name) { + this.type = Syntax.Identifier; + this.name = name; + this.finish(); + return this; + }, + + finishIfStatement: function (test, consequent, alternate) { + this.type = Syntax.IfStatement; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishLabeledStatement: function (label, body) { + this.type = Syntax.LabeledStatement; + this.label = label; + this.body = body; + this.finish(); + return this; + }, + + finishLiteral: function (token) { + this.type = Syntax.Literal; + this.value = token.value; + this.raw = source.slice(token.start, token.end); + if (token.regex) { + this.regex = token.regex; + } + this.finish(); + return this; + }, + + finishMemberExpression: function (accessor, object, property) { + this.type = Syntax.MemberExpression; + this.computed = accessor === '['; + this.object = object; + this.property = property; + this.finish(); + return this; + }, + + finishMetaProperty: function (meta, property) { + this.type = Syntax.MetaProperty; + this.meta = meta; + this.property = property; + this.finish(); + return this; + }, + + finishNewExpression: function (callee, args) { + this.type = Syntax.NewExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishObjectExpression: function (properties) { + this.type = Syntax.ObjectExpression; + this.properties = properties; + this.finish(); + return this; + }, + + finishObjectPattern: function (properties) { + this.type = Syntax.ObjectPattern; + this.properties = properties; + this.finish(); + return this; + }, + + finishPostfixExpression: function (operator, argument) { + this.type = Syntax.UpdateExpression; + this.operator = operator; + this.argument = argument; + this.prefix = false; + this.finish(); + return this; + }, + + finishProgram: function (body, sourceType) { + this.type = Syntax.Program; + this.body = body; + this.sourceType = sourceType; + this.finish(); + return this; + }, + + finishProperty: function (kind, key, computed, value, method, shorthand) { + this.type = Syntax.Property; + this.key = key; + this.computed = computed; + this.value = value; + this.kind = kind; + this.method = method; + this.shorthand = shorthand; + this.finish(); + return this; + }, + + finishRestElement: function (argument) { + this.type = Syntax.RestElement; + this.argument = argument; + this.finish(); + return this; + }, + + finishReturnStatement: function (argument) { + this.type = Syntax.ReturnStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishSequenceExpression: function (expressions) { + this.type = Syntax.SequenceExpression; + this.expressions = expressions; + this.finish(); + return this; + }, + + finishSpreadElement: function (argument) { + this.type = Syntax.SpreadElement; + this.argument = argument; + this.finish(); + return this; + }, + + finishSwitchCase: function (test, consequent) { + this.type = Syntax.SwitchCase; + this.test = test; + this.consequent = consequent; + this.finish(); + return this; + }, + + finishSuper: function () { + this.type = Syntax.Super; + this.finish(); + return this; + }, + + finishSwitchStatement: function (discriminant, cases) { + this.type = Syntax.SwitchStatement; + this.discriminant = discriminant; + this.cases = cases; + this.finish(); + return this; + }, + + finishTaggedTemplateExpression: function (tag, quasi) { + this.type = Syntax.TaggedTemplateExpression; + this.tag = tag; + this.quasi = quasi; + this.finish(); + return this; + }, + + finishTemplateElement: function (value, tail) { + this.type = Syntax.TemplateElement; + this.value = value; + this.tail = tail; + this.finish(); + return this; + }, + + finishTemplateLiteral: function (quasis, expressions) { + this.type = Syntax.TemplateLiteral; + this.quasis = quasis; + this.expressions = expressions; + this.finish(); + return this; + }, + + finishThisExpression: function () { + this.type = Syntax.ThisExpression; + this.finish(); + return this; + }, + + finishThrowStatement: function (argument) { + this.type = Syntax.ThrowStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishTryStatement: function (block, handler, finalizer) { + this.type = Syntax.TryStatement; + this.block = block; + this.guardedHandlers = []; + this.handlers = handler ? [handler] : []; + this.handler = handler; + this.finalizer = finalizer; + this.finish(); + return this; + }, + + finishUnaryExpression: function (operator, argument) { + this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression; + this.operator = operator; + this.argument = argument; + this.prefix = true; + this.finish(); + return this; + }, + + finishVariableDeclaration: function (declarations) { + this.type = Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = 'var'; + this.finish(); + return this; + }, + + finishLexicalDeclaration: function (declarations, kind) { + this.type = Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = kind; + this.finish(); + return this; + }, + + finishVariableDeclarator: function (id, init) { + this.type = Syntax.VariableDeclarator; + this.id = id; + this.init = init; + this.finish(); + return this; + }, + + finishWhileStatement: function (test, body) { + this.type = Syntax.WhileStatement; + this.test = test; + this.body = body; + this.finish(); + return this; + }, + + finishWithStatement: function (object, body) { + this.type = Syntax.WithStatement; + this.object = object; + this.body = body; + this.finish(); + return this; + }, + + finishExportSpecifier: function (local, exported) { + this.type = Syntax.ExportSpecifier; + this.exported = exported || local; + this.local = local; + this.finish(); + return this; + }, + + finishImportDefaultSpecifier: function (local) { + this.type = Syntax.ImportDefaultSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishImportNamespaceSpecifier: function (local) { + this.type = Syntax.ImportNamespaceSpecifier; + this.local = local; + this.finish(); + return this; + }, + + finishExportNamedDeclaration: function (declaration, specifiers, src) { + this.type = Syntax.ExportNamedDeclaration; + this.declaration = declaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishExportDefaultDeclaration: function (declaration) { + this.type = Syntax.ExportDefaultDeclaration; + this.declaration = declaration; + this.finish(); + return this; + }, + + finishExportAllDeclaration: function (src) { + this.type = Syntax.ExportAllDeclaration; + this.source = src; + this.finish(); + return this; + }, + + finishImportSpecifier: function (local, imported) { + this.type = Syntax.ImportSpecifier; + this.local = local || imported; + this.imported = imported; + this.finish(); + return this; + }, + + finishImportDeclaration: function (specifiers, src) { + this.type = Syntax.ImportDeclaration; + this.specifiers = specifiers; + this.source = src; + this.finish(); + return this; + }, + + finishYieldExpression: function (argument, delegate) { + this.type = Syntax.YieldExpression; + this.argument = argument; + this.delegate = delegate; + this.finish(); + return this; + } + }; + + + function recordError(error) { + var e, existing; + + for (e = 0; e < extra.errors.length; e++) { + existing = extra.errors[e]; + // Prevent duplicated error. + /* istanbul ignore next */ + if (existing.index === error.index && existing.message === error.message) { + return; + } + } + + extra.errors.push(error); + } + + function constructError(msg, column) { + var error = new Error(msg); + try { + throw error; + } catch (base) { + /* istanbul ignore else */ + if (Object.create && Object.defineProperty) { + error = Object.create(base); + Object.defineProperty(error, 'column', { value: column }); + } + } finally { + return error; + } + } + + function createError(line, pos, description) { + var msg, column, error; + + msg = 'Line ' + line + ': ' + description; + column = pos - (scanning ? lineStart : lastLineStart) + 1; + error = constructError(msg, column); + error.lineNumber = line; + error.description = description; + error.index = pos; + return error; + } + + // Throw an exception + + function throwError(messageFormat) { + var args, msg; + + args = Array.prototype.slice.call(arguments, 1); + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + throw createError(lastLineNumber, lastIndex, msg); + } + + function tolerateError(messageFormat) { + var args, msg, error; + + args = Array.prototype.slice.call(arguments, 1); + /* istanbul ignore next */ + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + error = createError(lineNumber, lastIndex, msg); + if (extra.errors) { + recordError(error); + } else { + throw error; + } + } + + // Throw an exception because of the token. + + function unexpectedTokenError(token, message) { + var value, msg = message || Messages.UnexpectedToken; + + if (token) { + if (!message) { + msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS : + (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier : + (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber : + (token.type === Token.StringLiteral) ? Messages.UnexpectedString : + (token.type === Token.Template) ? Messages.UnexpectedTemplate : + Messages.UnexpectedToken; + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + msg = Messages.UnexpectedReserved; + } else if (strict && isStrictModeReservedWord(token.value)) { + msg = Messages.StrictReservedWord; + } + } + } + + value = (token.type === Token.Template) ? token.value.raw : token.value; + } else { + value = 'ILLEGAL'; + } + + msg = msg.replace('%0', value); + + return (token && typeof token.lineNumber === 'number') ? + createError(token.lineNumber, token.start, msg) : + createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg); + } + + function throwUnexpectedToken(token, message) { + throw unexpectedTokenError(token, message); + } + + function tolerateUnexpectedToken(token, message) { + var error = unexpectedTokenError(token, message); + if (extra.errors) { + recordError(error); + } else { + throw error; + } + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpectedToken(token); + } + } + + /** + * @name expectCommaSeparator + * @description Quietly expect a comma when in tolerant mode, otherwise delegates + * to expect(value) + * @since 2.0 + */ + function expectCommaSeparator() { + var token; + + if (extra.errors) { + token = lookahead; + if (token.type === Token.Punctuator && token.value === ',') { + lex(); + } else if (token.type === Token.Punctuator && token.value === ';') { + lex(); + tolerateUnexpectedToken(token); + } else { + tolerateUnexpectedToken(token, Messages.UnexpectedToken); + } + } else { + expect(','); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpectedToken(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + // Return true if the next token matches the specified contextual keyword + // (where an identifier is sometimes a keyword depending on the context) + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(startIndex) === 0x3B || match(';')) { + lex(); + return; + } + + if (hasLineTerminator) { + return; + } + + // FIXME(ikarienator): this is seemingly an issue in the previous location info convention. + lastIndex = startIndex; + lastLineNumber = startLineNumber; + lastLineStart = startLineStart; + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpectedToken(lookahead); + } + } + + // Cover grammar support. + // + // When an assignment expression position starts with an left parenthesis, the determination of the type + // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) + // or the first comma. This situation also defers the determination of all the expressions nested in the pair. + // + // There are three productions that can be parsed in a parentheses pair that needs to be determined + // after the outermost pair is closed. They are: + // + // 1. AssignmentExpression + // 2. BindingElements + // 3. AssignmentTargets + // + // In order to avoid exponential backtracking, we use two flags to denote if the production can be + // binding element or assignment target. + // + // The three productions have the relationship: + // + // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression + // + // with a single exception that CoverInitializedName when used directly in an Expression, generates + // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the + // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. + // + // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not + // effect the current flags. This means the production the parser parses is only used as an expression. Therefore + // the CoverInitializedName check is conducted. + // + // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates + // the flags outside of the parser. This means the production the parser parses is used as a part of a potential + // pattern. The CoverInitializedName check is deferred. + function isolateCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + if (firstCoverInitializedNameError !== null) { + throwUnexpectedToken(firstCoverInitializedNameError); + } + isBindingElement = oldIsBindingElement; + isAssignmentTarget = oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError; + return result; + } + + function inheritCoverGrammar(parser) { + var oldIsBindingElement = isBindingElement, + oldIsAssignmentTarget = isAssignmentTarget, + oldFirstCoverInitializedNameError = firstCoverInitializedNameError, + result; + isBindingElement = true; + isAssignmentTarget = true; + firstCoverInitializedNameError = null; + result = parser(); + isBindingElement = isBindingElement && oldIsBindingElement; + isAssignmentTarget = isAssignmentTarget && oldIsAssignmentTarget; + firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError; + return result; + } + + // ECMA-262 13.3.3 Destructuring Binding Patterns + + function parseArrayPattern(params, kind) { + var node = new Node(), elements = [], rest, restNode; + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + if (match('...')) { + restNode = new Node(); + lex(); + params.push(lookahead); + rest = parseVariableIdentifier(kind); + elements.push(restNode.finishRestElement(rest)); + break; + } else { + elements.push(parsePatternWithDefault(params, kind)); + } + if (!match(']')) { + expect(','); + } + } + + } + + expect(']'); + + return node.finishArrayPattern(elements); + } + + function parsePropertyPattern(params, kind) { + var node = new Node(), key, keyToken, computed = match('['), init; + if (lookahead.type === Token.Identifier) { + keyToken = lookahead; + key = parseVariableIdentifier(); + if (match('=')) { + params.push(keyToken); + lex(); + init = parseAssignmentExpression(); + + return node.finishProperty( + 'init', key, false, + new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, false); + } else if (!match(':')) { + params.push(keyToken); + return node.finishProperty('init', key, false, key, false, true); + } + } else { + key = parseObjectPropertyKey(); + } + expect(':'); + init = parsePatternWithDefault(params, kind); + return node.finishProperty('init', key, computed, init, false, false); + } + + function parseObjectPattern(params, kind) { + var node = new Node(), properties = []; + + expect('{'); + + while (!match('}')) { + properties.push(parsePropertyPattern(params, kind)); + if (!match('}')) { + expect(','); + } + } + + lex(); + + return node.finishObjectPattern(properties); + } + + function parsePattern(params, kind) { + if (match('[')) { + return parseArrayPattern(params, kind); + } else if (match('{')) { + return parseObjectPattern(params, kind); + } else if (matchKeyword('let')) { + if (kind === 'const' || kind === 'let') { + tolerateUnexpectedToken(lookahead, Messages.UnexpectedToken); + } + } + + params.push(lookahead); + return parseVariableIdentifier(kind); + } + + function parsePatternWithDefault(params, kind) { + var startToken = lookahead, pattern, previousAllowYield, right; + pattern = parsePattern(params, kind); + if (match('=')) { + lex(); + previousAllowYield = state.allowYield; + state.allowYield = true; + right = isolateCoverGrammar(parseAssignmentExpression); + state.allowYield = previousAllowYield; + pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right); + } + return pattern; + } + + // ECMA-262 12.2.5 Array Initializer + + function parseArrayInitializer() { + var elements = [], node = new Node(), restSpread; + + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else if (match('...')) { + restSpread = new Node(); + lex(); + restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression)); + + if (!match(']')) { + isAssignmentTarget = isBindingElement = false; + expect(','); + } + elements.push(restSpread); + } else { + elements.push(inheritCoverGrammar(parseAssignmentExpression)); + + if (!match(']')) { + expect(','); + } + } + } + + lex(); + + return node.finishArrayExpression(elements); + } + + // ECMA-262 12.2.6 Object Initializer + + function parsePropertyFunction(node, paramInfo, isGenerator) { + var previousStrict, body; + + isAssignmentTarget = isBindingElement = false; + + previousStrict = strict; + body = isolateCoverGrammar(parseFunctionSourceElements); + + if (strict && paramInfo.firstRestricted) { + tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message); + } + if (strict && paramInfo.stricted) { + tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message); + } + + strict = previousStrict; + return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator); + } + + function parsePropertyMethodFunction() { + var params, method, node = new Node(), + previousAllowYield = state.allowYield; + + state.allowYield = false; + params = parseParams(); + state.allowYield = previousAllowYield; + + state.allowYield = false; + method = parsePropertyFunction(node, params, false); + state.allowYield = previousAllowYield; + + return method; + } + + function parseObjectPropertyKey() { + var token, node = new Node(), expr; + + token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + switch (token.type) { + case Token.StringLiteral: + case Token.NumericLiteral: + if (strict && token.octal) { + tolerateUnexpectedToken(token, Messages.StrictOctalLiteral); + } + return node.finishLiteral(token); + case Token.Identifier: + case Token.BooleanLiteral: + case Token.NullLiteral: + case Token.Keyword: + return node.finishIdentifier(token.value); + case Token.Punctuator: + if (token.value === '[') { + expr = isolateCoverGrammar(parseAssignmentExpression); + expect(']'); + return expr; + } + break; + } + throwUnexpectedToken(token); + } + + function lookaheadPropertyName() { + switch (lookahead.type) { + case Token.Identifier: + case Token.StringLiteral: + case Token.BooleanLiteral: + case Token.NullLiteral: + case Token.NumericLiteral: + case Token.Keyword: + return true; + case Token.Punctuator: + return lookahead.value === '['; + } + return false; + } + + // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals, + // it might be called at a position where there is in fact a short hand identifier pattern or a data property. + // This can only be determined after we consumed up to the left parentheses. + // + // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller + // is responsible to visit other options. + function tryParseMethodDefinition(token, key, computed, node) { + var value, options, methodNode, params, + previousAllowYield = state.allowYield; + + if (token.type === Token.Identifier) { + // check for `get` and `set`; + + if (token.value === 'get' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + expect('('); + expect(')'); + + state.allowYield = false; + value = parsePropertyFunction(methodNode, { + params: [], + defaults: [], + stricted: null, + firstRestricted: null, + message: null + }, false); + state.allowYield = previousAllowYield; + + return node.finishProperty('get', key, computed, value, false, false); + } else if (token.value === 'set' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + expect('('); + + options = { + params: [], + defaultCount: 0, + defaults: [], + firstRestricted: null, + paramSet: {} + }; + if (match(')')) { + tolerateUnexpectedToken(lookahead); + } else { + state.allowYield = false; + parseParam(options); + state.allowYield = previousAllowYield; + if (options.defaultCount === 0) { + options.defaults = []; + } + } + expect(')'); + + state.allowYield = false; + value = parsePropertyFunction(methodNode, options, false); + state.allowYield = previousAllowYield; + + return node.finishProperty('set', key, computed, value, false, false); + } + } else if (token.type === Token.Punctuator && token.value === '*' && lookaheadPropertyName()) { + computed = match('['); + key = parseObjectPropertyKey(); + methodNode = new Node(); + + state.allowYield = true; + params = parseParams(); + state.allowYield = previousAllowYield; + + state.allowYield = false; + value = parsePropertyFunction(methodNode, params, true); + state.allowYield = previousAllowYield; + + return node.finishProperty('init', key, computed, value, true, false); + } + + if (key && match('(')) { + value = parsePropertyMethodFunction(); + return node.finishProperty('init', key, computed, value, true, false); + } + + // Not a MethodDefinition. + return null; + } + + function parseObjectProperty(hasProto) { + var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value; + + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } + maybeMethod = tryParseMethodDefinition(token, key, computed, node); + if (maybeMethod) { + return maybeMethod; + } + + if (!key) { + throwUnexpectedToken(lookahead); + } + + // Check for duplicated __proto__ + if (!computed) { + proto = (key.type === Syntax.Identifier && key.name === '__proto__') || + (key.type === Syntax.Literal && key.value === '__proto__'); + if (hasProto.value && proto) { + tolerateError(Messages.DuplicateProtoProperty); + } + hasProto.value |= proto; + } + + if (match(':')) { + lex(); + value = inheritCoverGrammar(parseAssignmentExpression); + return node.finishProperty('init', key, computed, value, false, false); + } + + if (token.type === Token.Identifier) { + if (match('=')) { + firstCoverInitializedNameError = lookahead; + lex(); + value = isolateCoverGrammar(parseAssignmentExpression); + return node.finishProperty('init', key, computed, + new WrappingNode(token).finishAssignmentPattern(key, value), false, true); + } + return node.finishProperty('init', key, computed, key, false, true); + } + + throwUnexpectedToken(lookahead); + } + + function parseObjectInitializer() { + var properties = [], hasProto = {value: false}, node = new Node(); + + expect('{'); + + while (!match('}')) { + properties.push(parseObjectProperty(hasProto)); + + if (!match('}')) { + expectCommaSeparator(); + } + } + + expect('}'); + + return node.finishObjectExpression(properties); + } + + function reinterpretExpressionAsPattern(expr) { + var i; + switch (expr.type) { + case Syntax.Identifier: + case Syntax.MemberExpression: + case Syntax.RestElement: + case Syntax.AssignmentPattern: + break; + case Syntax.SpreadElement: + expr.type = Syntax.RestElement; + reinterpretExpressionAsPattern(expr.argument); + break; + case Syntax.ArrayExpression: + expr.type = Syntax.ArrayPattern; + for (i = 0; i < expr.elements.length; i++) { + if (expr.elements[i] !== null) { + reinterpretExpressionAsPattern(expr.elements[i]); + } + } + break; + case Syntax.ObjectExpression: + expr.type = Syntax.ObjectPattern; + for (i = 0; i < expr.properties.length; i++) { + reinterpretExpressionAsPattern(expr.properties[i].value); + } + break; + case Syntax.AssignmentExpression: + expr.type = Syntax.AssignmentPattern; + reinterpretExpressionAsPattern(expr.left); + break; + default: + // Allow other node type for tolerant parsing. + break; + } + } + + // ECMA-262 12.2.9 Template Literals + + function parseTemplateElement(option) { + var node, token; + + if (lookahead.type !== Token.Template || (option.head && !lookahead.head)) { + throwUnexpectedToken(); + } + + node = new Node(); + token = lex(); + + return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions, node = new Node(); + + quasi = parseTemplateElement({ head: true }); + quasis = [quasi]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return node.finishTemplateLiteral(quasis, expressions); + } + + // ECMA-262 12.2.10 The Grouping Operator + + function parseGroupExpression() { + var expr, expressions, startToken, i, params = []; + + expect('('); + + if (match(')')) { + lex(); + if (!match('=>')) { + expect('=>'); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [], + rawParams: [] + }; + } + + startToken = lookahead; + if (match('...')) { + expr = parseRestElement(params); + expect(')'); + if (!match('=>')) { + expect('=>'); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [expr] + }; + } + + isBindingElement = true; + expr = inheritCoverGrammar(parseAssignmentExpression); + + if (match(',')) { + isAssignmentTarget = false; + expressions = [expr]; + + while (startIndex < length) { + if (!match(',')) { + break; + } + lex(); + + if (match('...')) { + if (!isBindingElement) { + throwUnexpectedToken(lookahead); + } + expressions.push(parseRestElement(params)); + expect(')'); + if (!match('=>')) { + expect('=>'); + } + isBindingElement = false; + for (i = 0; i < expressions.length; i++) { + reinterpretExpressionAsPattern(expressions[i]); + } + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: expressions + }; + } + + expressions.push(inheritCoverGrammar(parseAssignmentExpression)); + } + + expr = new WrappingNode(startToken).finishSequenceExpression(expressions); + } + + + expect(')'); + + if (match('=>')) { + if (expr.type === Syntax.Identifier && expr.name === 'yield') { + return { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: [expr] + }; + } + + if (!isBindingElement) { + throwUnexpectedToken(lookahead); + } + + if (expr.type === Syntax.SequenceExpression) { + for (i = 0; i < expr.expressions.length; i++) { + reinterpretExpressionAsPattern(expr.expressions[i]); + } + } else { + reinterpretExpressionAsPattern(expr); + } + + expr = { + type: PlaceHolders.ArrowParameterPlaceHolder, + params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr] + }; + } + isBindingElement = false; + return expr; + } + + + // ECMA-262 12.2 Primary Expressions + + function parsePrimaryExpression() { + var type, token, expr, node; + + if (match('(')) { + isBindingElement = false; + return inheritCoverGrammar(parseGroupExpression); + } + + if (match('[')) { + return inheritCoverGrammar(parseArrayInitializer); + } + + if (match('{')) { + return inheritCoverGrammar(parseObjectInitializer); + } + + type = lookahead.type; + node = new Node(); + + if (type === Token.Identifier) { + if (state.sourceType === 'module' && lookahead.value === 'await') { + tolerateUnexpectedToken(lookahead); + } + expr = node.finishIdentifier(lex().value); + } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { + isAssignmentTarget = isBindingElement = false; + if (strict && lookahead.octal) { + tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral); + } + expr = node.finishLiteral(lex()); + } else if (type === Token.Keyword) { + if (!strict && state.allowYield && matchKeyword('yield')) { + return parseNonComputedProperty(); + } + if (!strict && matchKeyword('let')) { + return node.finishIdentifier(lex().value); + } + isAssignmentTarget = isBindingElement = false; + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + if (matchKeyword('this')) { + lex(); + return node.finishThisExpression(); + } + if (matchKeyword('class')) { + return parseClassExpression(); + } + throwUnexpectedToken(lex()); + } else if (type === Token.BooleanLiteral) { + isAssignmentTarget = isBindingElement = false; + token = lex(); + token.value = (token.value === 'true'); + expr = node.finishLiteral(token); + } else if (type === Token.NullLiteral) { + isAssignmentTarget = isBindingElement = false; + token = lex(); + token.value = null; + expr = node.finishLiteral(token); + } else if (match('/') || match('/=')) { + isAssignmentTarget = isBindingElement = false; + index = startIndex; + + if (typeof extra.tokens !== 'undefined') { + token = collectRegex(); + } else { + token = scanRegExp(); + } + lex(); + expr = node.finishLiteral(token); + } else if (type === Token.Template) { + expr = parseTemplateLiteral(); + } else { + throwUnexpectedToken(lex()); + } + + return expr; + } + + // ECMA-262 12.3 Left-Hand-Side Expressions + + function parseArguments() { + var args = [], expr; + + expect('('); + + if (!match(')')) { + while (startIndex < length) { + if (match('...')) { + expr = new Node(); + lex(); + expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression)); + } else { + expr = isolateCoverGrammar(parseAssignmentExpression); + } + args.push(expr); + if (match(')')) { + break; + } + expectCommaSeparator(); + } + } + + expect(')'); + + return args; + } + + function parseNonComputedProperty() { + var token, node = new Node(); + + token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpectedToken(token); + } + + return node.finishIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = isolateCoverGrammar(parseExpression); + + expect(']'); + + return expr; + } + + // ECMA-262 12.3.3 The new Operator + + function parseNewExpression() { + var callee, args, node = new Node(); + + expectKeyword('new'); + + if (match('.')) { + lex(); + if (lookahead.type === Token.Identifier && lookahead.value === 'target') { + if (state.inFunctionBody) { + lex(); + return node.finishMetaProperty('new', 'target'); + } + } + throwUnexpectedToken(lookahead); + } + + callee = isolateCoverGrammar(parseLeftHandSideExpression); + args = match('(') ? parseArguments() : []; + + isAssignmentTarget = isBindingElement = false; + + return node.finishNewExpression(callee, args); + } + + // ECMA-262 12.3.4 Function Calls + + function parseLeftHandSideExpressionAllowCall() { + var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn; + + startToken = lookahead; + state.allowIn = true; + + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('(') && !match('.') && !match('[')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } + + for (;;) { + if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (match('(')) { + isBindingElement = false; + isAssignmentTarget = false; + args = parseArguments(); + expr = new WrappingNode(startToken).finishCallExpression(expr, args); + } else if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); + } else { + break; + } + } + state.allowIn = previousAllowIn; + + return expr; + } + + // ECMA-262 12.3 Left-Hand-Side Expressions + + function parseLeftHandSideExpression() { + var quasi, expr, property, startToken; + assert(state.allowIn, 'callee of new expression always allow in keyword.'); + + startToken = lookahead; + + if (matchKeyword('super') && state.inFunctionBody) { + expr = new Node(); + lex(); + expr = expr.finishSuper(); + if (!match('[') && !match('.')) { + throwUnexpectedToken(lookahead); + } + } else { + expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression); + } + + for (;;) { + if (match('[')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (match('.')) { + isBindingElement = false; + isAssignmentTarget = true; + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (lookahead.type === Token.Template && lookahead.head) { + quasi = parseTemplateLiteral(); + expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi); + } else { + break; + } + } + return expr; + } + + // ECMA-262 12.4 Postfix Expressions + + function parsePostfixExpression() { + var expr, token, startToken = lookahead; + + expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall); + + if (!hasLineTerminator && lookahead.type === Token.Punctuator) { + if (match('++') || match('--')) { + // ECMA-262 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPostfix); + } + + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + isAssignmentTarget = isBindingElement = false; + + token = lex(); + expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr); + } + } + + return expr; + } + + // ECMA-262 12.5 Unary Operators + + function parseUnaryExpression() { + var token, expr, startToken; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + expr = parsePostfixExpression(); + } else if (match('++') || match('--')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + // ECMA-262 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPrefix); + } + + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; + } else if (match('+') || match('-') || match('~') || match('!')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + isAssignmentTarget = isBindingElement = false; + } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + startToken = lookahead; + token = lex(); + expr = inheritCoverGrammar(parseUnaryExpression); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + tolerateError(Messages.StrictDelete); + } + isAssignmentTarget = isBindingElement = false; + } else { + expr = parsePostfixExpression(); + } + + return expr; + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // ECMA-262 12.6 Multiplicative Operators + // ECMA-262 12.7 Additive Operators + // ECMA-262 12.8 Bitwise Shift Operators + // ECMA-262 12.9 Relational Operators + // ECMA-262 12.10 Equality Operators + // ECMA-262 12.11 Binary Bitwise Operators + // ECMA-262 12.12 Binary Logical Operators + + function parseBinaryExpression() { + var marker, markers, expr, token, prec, stack, right, operator, left, i; + + marker = lookahead; + left = inheritCoverGrammar(parseUnaryExpression); + + token = lookahead; + prec = binaryPrecedence(token, state.allowIn); + if (prec === 0) { + return left; + } + isAssignmentTarget = isBindingElement = false; + token.prec = prec; + lex(); + + markers = [marker, lookahead]; + right = isolateCoverGrammar(parseUnaryExpression); + + stack = [left, token, right]; + + while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + markers.pop(); + expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right); + stack.push(expr); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + markers.push(lookahead); + expr = isolateCoverGrammar(parseUnaryExpression); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + + return expr; + } + + + // ECMA-262 12.13 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate, startToken; + + startToken = lookahead; + + expr = inheritCoverGrammar(parseBinaryExpression); + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = isolateCoverGrammar(parseAssignmentExpression); + state.allowIn = previousAllowIn; + expect(':'); + alternate = isolateCoverGrammar(parseAssignmentExpression); + + expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate); + isAssignmentTarget = isBindingElement = false; + } + + return expr; + } + + // ECMA-262 14.2 Arrow Function Definitions + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return isolateCoverGrammar(parseAssignmentExpression); + } + + function checkPatternParam(options, param) { + var i; + switch (param.type) { + case Syntax.Identifier: + validateParam(options, param, param.name); + break; + case Syntax.RestElement: + checkPatternParam(options, param.argument); + break; + case Syntax.AssignmentPattern: + checkPatternParam(options, param.left); + break; + case Syntax.ArrayPattern: + for (i = 0; i < param.elements.length; i++) { + if (param.elements[i] !== null) { + checkPatternParam(options, param.elements[i]); + } + } + break; + case Syntax.YieldExpression: + break; + default: + assert(param.type === Syntax.ObjectPattern, 'Invalid type'); + for (i = 0; i < param.properties.length; i++) { + checkPatternParam(options, param.properties[i].value); + } + break; + } + } + function reinterpretAsCoverFormalsList(expr) { + var i, len, param, params, defaults, defaultCount, options, token; + + defaults = []; + defaultCount = 0; + params = [expr]; + + switch (expr.type) { + case Syntax.Identifier: + break; + case PlaceHolders.ArrowParameterPlaceHolder: + params = expr.params; + break; + default: + return null; + } + + options = { + paramSet: {} + }; + + for (i = 0, len = params.length; i < len; i += 1) { + param = params[i]; + switch (param.type) { + case Syntax.AssignmentPattern: + params[i] = param.left; + if (param.right.type === Syntax.YieldExpression) { + if (param.right.argument) { + throwUnexpectedToken(lookahead); + } + param.right.type = Syntax.Identifier; + param.right.name = 'yield'; + delete param.right.argument; + delete param.right.delegate; + } + defaults.push(param.right); + ++defaultCount; + checkPatternParam(options, param.left); + break; + default: + checkPatternParam(options, param); + params[i] = param; + defaults.push(null); + break; + } + } + + if (strict || !state.allowYield) { + for (i = 0, len = params.length; i < len; i += 1) { + param = params[i]; + if (param.type === Syntax.YieldExpression) { + throwUnexpectedToken(lookahead); + } + } + } + + if (options.message === Messages.StrictParamDupe) { + token = strict ? options.stricted : options.firstRestricted; + throwUnexpectedToken(token, options.message); + } + + if (defaultCount === 0) { + defaults = []; + } + + return { + params: params, + defaults: defaults, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseArrowFunctionExpression(options, node) { + var previousStrict, previousAllowYield, body; + + if (hasLineTerminator) { + tolerateUnexpectedToken(lookahead); + } + expect('=>'); + + previousStrict = strict; + previousAllowYield = state.allowYield; + state.allowYield = true; + + body = parseConciseBody(); + + if (strict && options.firstRestricted) { + throwUnexpectedToken(options.firstRestricted, options.message); + } + if (strict && options.stricted) { + tolerateUnexpectedToken(options.stricted, options.message); + } + + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement); + } + + // ECMA-262 14.4 Yield expression + + function parseYieldExpression() { + var argument, expr, delegate, previousAllowYield; + + argument = null; + expr = new Node(); + delegate = false; + + expectKeyword('yield'); + + if (!hasLineTerminator) { + previousAllowYield = state.allowYield; + state.allowYield = false; + delegate = match('*'); + if (delegate) { + lex(); + argument = parseAssignmentExpression(); + } else { + if (!match(';') && !match('}') && !match(')') && lookahead.type !== Token.EOF) { + argument = parseAssignmentExpression(); + } + } + state.allowYield = previousAllowYield; + } + + return expr.finishYieldExpression(argument, delegate); + } + + // ECMA-262 12.14 Assignment Operators + + function parseAssignmentExpression() { + var token, expr, right, list, startToken; + + startToken = lookahead; + token = lookahead; + + if (!state.allowYield && matchKeyword('yield')) { + return parseYieldExpression(); + } + + expr = parseConditionalExpression(); + + if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) { + isAssignmentTarget = isBindingElement = false; + list = reinterpretAsCoverFormalsList(expr); + + if (list) { + firstCoverInitializedNameError = null; + return parseArrowFunctionExpression(list, new WrappingNode(startToken)); + } + + return expr; + } + + if (matchAssign()) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + // ECMA-262 12.1.1 + if (strict && expr.type === Syntax.Identifier) { + if (isRestrictedWord(expr.name)) { + tolerateUnexpectedToken(token, Messages.StrictLHSAssignment); + } + if (isStrictModeReservedWord(expr.name)) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } + } + + if (!match('=')) { + isAssignmentTarget = isBindingElement = false; + } else { + reinterpretExpressionAsPattern(expr); + } + + token = lex(); + right = isolateCoverGrammar(parseAssignmentExpression); + expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right); + firstCoverInitializedNameError = null; + } + + return expr; + } + + // ECMA-262 12.15 Comma Operator + + function parseExpression() { + var expr, startToken = lookahead, expressions; + + expr = isolateCoverGrammar(parseAssignmentExpression); + + if (match(',')) { + expressions = [expr]; + + while (startIndex < length) { + if (!match(',')) { + break; + } + lex(); + expressions.push(isolateCoverGrammar(parseAssignmentExpression)); + } + + expr = new WrappingNode(startToken).finishSequenceExpression(expressions); + } + + return expr; + } + + // ECMA-262 13.2 Block + + function parseStatementListItem() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'export': + if (state.sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration); + } + return parseExportDeclaration(); + case 'import': + if (state.sourceType !== 'module') { + tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration); + } + return parseImportDeclaration(); + case 'const': + return parseLexicalDeclaration({inFor: false}); + case 'function': + return parseFunctionDeclaration(new Node()); + case 'class': + return parseClassDeclaration(); + } + } + + if (matchKeyword('let') && isLexicalDeclaration()) { + return parseLexicalDeclaration({inFor: false}); + } + + return parseStatement(); + } + + function parseStatementList() { + var list = []; + while (startIndex < length) { + if (match('}')) { + break; + } + list.push(parseStatementListItem()); + } + + return list; + } + + function parseBlock() { + var block, node = new Node(); + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return node.finishBlockStatement(block); + } + + // ECMA-262 13.3.2 Variable Statement + + function parseVariableIdentifier(kind) { + var token, node = new Node(); + + token = lex(); + + if (token.type === Token.Keyword && token.value === 'yield') { + if (strict) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } if (!state.allowYield) { + throwUnexpectedToken(token); + } + } else if (token.type !== Token.Identifier) { + if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } else { + if (strict || token.value !== 'let' || kind !== 'var') { + throwUnexpectedToken(token); + } + } + } else if (state.sourceType === 'module' && token.type === Token.Identifier && token.value === 'await') { + tolerateUnexpectedToken(token); + } + + return node.finishIdentifier(token.value); + } + + function parseVariableDeclaration(options) { + var init = null, id, node = new Node(), params = []; + + id = parsePattern(params, 'var'); + + // ECMA-262 12.2.1 + if (strict && isRestrictedWord(id.name)) { + tolerateError(Messages.StrictVarName); + } + + if (match('=')) { + lex(); + init = isolateCoverGrammar(parseAssignmentExpression); + } else if (id.type !== Syntax.Identifier && !options.inFor) { + expect('='); + } + + return node.finishVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(options) { + var opt, list; + + opt = { inFor: options.inFor }; + list = [parseVariableDeclaration(opt)]; + + while (match(',')) { + lex(); + list.push(parseVariableDeclaration(opt)); + } + + return list; + } + + function parseVariableStatement(node) { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList({ inFor: false }); + + consumeSemicolon(); + + return node.finishVariableDeclaration(declarations); + } + + // ECMA-262 13.3.1 Let and Const Declarations + + function parseLexicalBinding(kind, options) { + var init = null, id, node = new Node(), params = []; + + id = parsePattern(params, kind); + + // ECMA-262 12.2.1 + if (strict && id.type === Syntax.Identifier && isRestrictedWord(id.name)) { + tolerateError(Messages.StrictVarName); + } + + if (kind === 'const') { + if (!matchKeyword('in') && !matchContextualKeyword('of')) { + expect('='); + init = isolateCoverGrammar(parseAssignmentExpression); + } + } else if ((!options.inFor && id.type !== Syntax.Identifier) || match('=')) { + expect('='); + init = isolateCoverGrammar(parseAssignmentExpression); + } + + return node.finishVariableDeclarator(id, init); + } + + function parseBindingList(kind, options) { + var list = [parseLexicalBinding(kind, options)]; + + while (match(',')) { + lex(); + list.push(parseLexicalBinding(kind, options)); + } + + return list; + } + + + function tokenizerState() { + return { + index: index, + lineNumber: lineNumber, + lineStart: lineStart, + hasLineTerminator: hasLineTerminator, + lastIndex: lastIndex, + lastLineNumber: lastLineNumber, + lastLineStart: lastLineStart, + startIndex: startIndex, + startLineNumber: startLineNumber, + startLineStart: startLineStart, + lookahead: lookahead, + tokenCount: extra.tokens ? extra.tokens.length : 0 + }; + } + + function resetTokenizerState(ts) { + index = ts.index; + lineNumber = ts.lineNumber; + lineStart = ts.lineStart; + hasLineTerminator = ts.hasLineTerminator; + lastIndex = ts.lastIndex; + lastLineNumber = ts.lastLineNumber; + lastLineStart = ts.lastLineStart; + startIndex = ts.startIndex; + startLineNumber = ts.startLineNumber; + startLineStart = ts.startLineStart; + lookahead = ts.lookahead; + if (extra.tokens) { + extra.tokens.splice(ts.tokenCount, extra.tokens.length); + } + } + + function isLexicalDeclaration() { + var lexical, ts; + + ts = tokenizerState(); + + lex(); + lexical = (lookahead.type === Token.Identifier) || match('[') || match('{') || + matchKeyword('let') || matchKeyword('yield'); + + resetTokenizerState(ts); + + return lexical; + } + + function parseLexicalDeclaration(options) { + var kind, declarations, node = new Node(); + + kind = lex().value; + assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); + + declarations = parseBindingList(kind, options); + + consumeSemicolon(); + + return node.finishLexicalDeclaration(declarations, kind); + } + + function parseRestElement(params) { + var param, node = new Node(); + + lex(); + + if (match('{')) { + throwError(Messages.ObjectPatternAsRestParameter); + } + + params.push(lookahead); + + param = parseVariableIdentifier(); + + if (match('=')) { + throwError(Messages.DefaultRestParameter); + } + + if (!match(')')) { + throwError(Messages.ParameterAfterRestParameter); + } + + return node.finishRestElement(param); + } + + // ECMA-262 13.4 Empty Statement + + function parseEmptyStatement(node) { + expect(';'); + return node.finishEmptyStatement(); + } + + // ECMA-262 12.4 Expression Statement + + function parseExpressionStatement(node) { + var expr = parseExpression(); + consumeSemicolon(); + return node.finishExpressionStatement(expr); + } + + // ECMA-262 13.6 If statement + + function parseIfStatement(node) { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return node.finishIfStatement(test, consequent, alternate); + } + + // ECMA-262 13.7 Iteration Statements + + function parseDoWhileStatement(node) { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return node.finishDoWhileStatement(body, test); + } + + function parseWhileStatement(node) { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return node.finishWhileStatement(test, body); + } + + function parseForStatement(node) { + var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations, + body, oldInIteration, previousAllowIn = state.allowIn; + + init = test = update = null; + forIn = true; + + expectKeyword('for'); + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var')) { + init = new Node(); + lex(); + + state.allowIn = false; + declarations = parseVariableDeclarationList({ inFor: true }); + state.allowIn = previousAllowIn; + + if (declarations.length === 1 && matchKeyword('in')) { + init = init.finishVariableDeclaration(declarations); + lex(); + left = init; + right = parseExpression(); + init = null; + } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) { + init = init.finishVariableDeclaration(declarations); + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + init = init.finishVariableDeclaration(declarations); + expect(';'); + } + } else if (matchKeyword('const') || matchKeyword('let')) { + init = new Node(); + kind = lex().value; + + if (!strict && lookahead.value === 'in') { + init = init.finishIdentifier(kind); + lex(); + left = init; + right = parseExpression(); + init = null; + } else { + state.allowIn = false; + declarations = parseBindingList(kind, {inFor: true}); + state.allowIn = previousAllowIn; + + if (declarations.length === 1 && declarations[0].init === null && matchKeyword('in')) { + init = init.finishLexicalDeclaration(declarations, kind); + lex(); + left = init; + right = parseExpression(); + init = null; + } else if (declarations.length === 1 && declarations[0].init === null && matchContextualKeyword('of')) { + init = init.finishLexicalDeclaration(declarations, kind); + lex(); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + consumeSemicolon(); + init = init.finishLexicalDeclaration(declarations, kind); + } + } + } else { + initStartToken = lookahead; + state.allowIn = false; + init = inheritCoverGrammar(parseAssignmentExpression); + state.allowIn = previousAllowIn; + + if (matchKeyword('in')) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInForIn); + } + + lex(); + reinterpretExpressionAsPattern(init); + left = init; + right = parseExpression(); + init = null; + } else if (matchContextualKeyword('of')) { + if (!isAssignmentTarget) { + tolerateError(Messages.InvalidLHSInForLoop); + } + + lex(); + reinterpretExpressionAsPattern(init); + left = init; + right = parseAssignmentExpression(); + init = null; + forIn = false; + } else { + if (match(',')) { + initSeq = [init]; + while (match(',')) { + lex(); + initSeq.push(isolateCoverGrammar(parseAssignmentExpression)); + } + init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq); + } + expect(';'); + } + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = isolateCoverGrammar(parseStatement); + + state.inIteration = oldInIteration; + + return (typeof left === 'undefined') ? + node.finishForStatement(init, test, update, body) : + forIn ? node.finishForInStatement(left, right, body) : + node.finishForOfStatement(left, right, body); + } + + // ECMA-262 13.8 The continue statement + + function parseContinueStatement(node) { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(startIndex) === 0x3B) { + lex(); + + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (hasLineTerminator) { + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(label); + } + + // ECMA-262 13.9 The break statement + + function parseBreakStatement(node) { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(lastIndex) === 0x3B) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(null); + } + + if (hasLineTerminator) { + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + } else if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(label); + } + + // ECMA-262 13.10 The return statement + + function parseReturnStatement(node) { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + tolerateError(Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(lastIndex) === 0x20) { + if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return node.finishReturnStatement(argument); + } + } + + if (hasLineTerminator) { + // HACK + return node.finishReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return node.finishReturnStatement(argument); + } + + // ECMA-262 13.11 The with statement + + function parseWithStatement(node) { + var object, body; + + if (strict) { + tolerateError(Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return node.finishWithStatement(object, body); + } + + // ECMA-262 13.12 The switch statement + + function parseSwitchCase() { + var test, consequent = [], statement, node = new Node(); + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (startIndex < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + statement = parseStatementListItem(); + consequent.push(statement); + } + + return node.finishSwitchCase(test, consequent); + } + + function parseSwitchStatement(node) { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return node.finishSwitchStatement(discriminant, cases); + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (startIndex < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError(Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return node.finishSwitchStatement(discriminant, cases); + } + + // ECMA-262 13.14 The throw statement + + function parseThrowStatement(node) { + var argument; + + expectKeyword('throw'); + + if (hasLineTerminator) { + throwError(Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return node.finishThrowStatement(argument); + } + + // ECMA-262 13.15 The try statement + + function parseCatchClause() { + var param, params = [], paramMap = {}, key, i, body, node = new Node(); + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpectedToken(lookahead); + } + + param = parsePattern(params); + for (i = 0; i < params.length; i++) { + key = '$' + params[i].value; + if (Object.prototype.hasOwnProperty.call(paramMap, key)) { + tolerateError(Messages.DuplicateBinding, params[i].value); + } + paramMap[key] = true; + } + + // ECMA-262 12.14.1 + if (strict && isRestrictedWord(param.name)) { + tolerateError(Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return node.finishCatchClause(param, body); + } + + function parseTryStatement(node) { + var block, handler = null, finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handler = parseCatchClause(); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (!handler && !finalizer) { + throwError(Messages.NoCatchOrFinally); + } + + return node.finishTryStatement(block, handler, finalizer); + } + + // ECMA-262 13.16 The debugger statement + + function parseDebuggerStatement(node) { + expectKeyword('debugger'); + + consumeSemicolon(); + + return node.finishDebuggerStatement(); + } + + // 13 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key, + node; + + if (type === Token.EOF) { + throwUnexpectedToken(lookahead); + } + + if (type === Token.Punctuator && lookahead.value === '{') { + return parseBlock(); + } + isAssignmentTarget = isBindingElement = true; + node = new Node(); + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(node); + case '(': + return parseExpressionStatement(node); + default: + break; + } + } else if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(node); + case 'continue': + return parseContinueStatement(node); + case 'debugger': + return parseDebuggerStatement(node); + case 'do': + return parseDoWhileStatement(node); + case 'for': + return parseForStatement(node); + case 'function': + return parseFunctionDeclaration(node); + case 'if': + return parseIfStatement(node); + case 'return': + return parseReturnStatement(node); + case 'switch': + return parseSwitchStatement(node); + case 'throw': + return parseThrowStatement(node); + case 'try': + return parseTryStatement(node); + case 'var': + return parseVariableStatement(node); + case 'while': + return parseWhileStatement(node); + case 'with': + return parseWithStatement(node); + default: + break; + } + } + + expr = parseExpression(); + + // ECMA-262 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return node.finishLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return node.finishExpressionStatement(expr); + } + + // ECMA-262 14.1 Function Definition + + function parseFunctionSourceElements() { + var statement, body = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount, + node = new Node(); + + expect('{'); + + while (startIndex < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + statement = parseStatementListItem(); + body.push(statement); + if (statement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + oldParenthesisCount = state.parenthesizedCount; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + state.parenthesizedCount = 0; + + while (startIndex < length) { + if (match('}')) { + break; + } + body.push(parseStatementListItem()); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + state.parenthesizedCount = oldParenthesisCount; + + return node.finishBlockStatement(body); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, param, params = [], i, def; + + token = lookahead; + if (token.value === '...') { + param = parseRestElement(params); + validateParam(options, param.argument, param.argument.name); + options.params.push(param); + options.defaults.push(null); + return false; + } + + param = parsePatternWithDefault(params); + for (i = 0; i < params.length; i++) { + validateParam(options, params[i], params[i].value); + } + + if (param.type === Syntax.AssignmentPattern) { + def = param.right; + param = param.left; + ++options.defaultCount; + } + + options.params.push(param); + options.defaults.push(def); + + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + defaultCount: 0, + defaults: [], + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (startIndex < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + if (options.defaultCount === 0) { + options.defaults = []; + } + + return { + params: options.params, + defaults: options.defaults, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseFunctionDeclaration(node, identifierIsOptional) { + var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, + isGenerator, previousAllowYield; + + previousAllowYield = state.allowYield; + + expectKeyword('function'); + + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + + if (!identifierIsOptional || !match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + state.allowYield = !isGenerator; + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator); + } + + function parseFunctionExpression() { + var token, id = null, stricted, firstRestricted, message, tmp, + params = [], defaults = [], body, previousStrict, node = new Node(), + isGenerator, previousAllowYield; + + previousAllowYield = state.allowYield; + + expectKeyword('function'); + + isGenerator = match('*'); + if (isGenerator) { + lex(); + } + + state.allowYield = !isGenerator; + if (!match('(')) { + token = lookahead; + id = (!strict && !isGenerator && matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + strict = previousStrict; + state.allowYield = previousAllowYield; + + return node.finishFunctionExpression(id, params, defaults, body, isGenerator); + } + + // ECMA-262 14.5 Class Definitions + + function parseClassBody() { + var classBody, token, isStatic, hasConstructor = false, body, method, computed, key; + + classBody = new Node(); + + expect('{'); + body = []; + while (!match('}')) { + if (match(';')) { + lex(); + } else { + method = new Node(); + token = lookahead; + isStatic = false; + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + if (key.name === 'static' && (lookaheadPropertyName() || match('*'))) { + token = lookahead; + isStatic = true; + computed = match('['); + if (match('*')) { + lex(); + } else { + key = parseObjectPropertyKey(); + } + } + } + method = tryParseMethodDefinition(token, key, computed, method); + if (method) { + method['static'] = isStatic; // jscs:ignore requireDotNotation + if (method.kind === 'init') { + method.kind = 'method'; + } + if (!isStatic) { + if (!method.computed && (method.key.name || method.key.value.toString()) === 'constructor') { + if (method.kind !== 'method' || !method.method || method.value.generator) { + throwUnexpectedToken(token, Messages.ConstructorSpecialMethod); + } + if (hasConstructor) { + throwUnexpectedToken(token, Messages.DuplicateConstructor); + } else { + hasConstructor = true; + } + method.kind = 'constructor'; + } + } else { + if (!method.computed && (method.key.name || method.key.value.toString()) === 'prototype') { + throwUnexpectedToken(token, Messages.StaticPrototype); + } + } + method.type = Syntax.MethodDefinition; + delete method.method; + delete method.shorthand; + body.push(method); + } else { + throwUnexpectedToken(lookahead); + } + } + } + lex(); + return classBody.finishClassBody(body); + } + + function parseClassDeclaration(identifierIsOptional) { + var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict; + strict = true; + + expectKeyword('class'); + + if (!identifierIsOptional || lookahead.type === Token.Identifier) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + lex(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); + } + classBody = parseClassBody(); + strict = previousStrict; + + return classNode.finishClassDeclaration(id, superClass, classBody); + } + + function parseClassExpression() { + var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict; + strict = true; + + expectKeyword('class'); + + if (lookahead.type === Token.Identifier) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + lex(); + superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall); + } + classBody = parseClassBody(); + strict = previousStrict; + + return classNode.finishClassExpression(id, superClass, classBody); + } + + // ECMA-262 15.2 Modules + + function parseModuleSpecifier() { + var node = new Node(); + + if (lookahead.type !== Token.StringLiteral) { + throwError(Messages.InvalidModuleSpecifier); + } + return node.finishLiteral(lex()); + } + + // ECMA-262 15.2.3 Exports + + function parseExportSpecifier() { + var exported, local, node = new Node(), def; + if (matchKeyword('default')) { + // export {default} from 'something'; + def = new Node(); + lex(); + local = def.finishIdentifier('default'); + } else { + local = parseVariableIdentifier(); + } + if (matchContextualKeyword('as')) { + lex(); + exported = parseNonComputedProperty(); + } + return node.finishExportSpecifier(local, exported); + } + + function parseExportNamedDeclaration(node) { + var declaration = null, + isExportFromIdentifier, + src = null, specifiers = []; + + // non-default export + if (lookahead.type === Token.Keyword) { + // covers: + // export var f = 1; + switch (lookahead.value) { + case 'let': + case 'const': + declaration = parseLexicalDeclaration({inFor: false}); + return node.finishExportNamedDeclaration(declaration, specifiers, null); + case 'var': + case 'class': + case 'function': + declaration = parseStatementListItem(); + return node.finishExportNamedDeclaration(declaration, specifiers, null); + } + } + + expect('{'); + while (!match('}')) { + isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default'); + specifiers.push(parseExportSpecifier()); + if (!match('}')) { + expect(','); + if (match('}')) { + break; + } + } + } + expect('}'); + + if (matchContextualKeyword('from')) { + // covering: + // export {default} from 'foo'; + // export {foo} from 'foo'; + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + } else if (isExportFromIdentifier) { + // covering: + // export {default}; // missing fromClause + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } else { + // cover + // export {foo}; + consumeSemicolon(); + } + return node.finishExportNamedDeclaration(declaration, specifiers, src); + } + + function parseExportDefaultDeclaration(node) { + var declaration = null, + expression = null; + + // covers: + // export default ... + expectKeyword('default'); + + if (matchKeyword('function')) { + // covers: + // export default function foo () {} + // export default function () {} + declaration = parseFunctionDeclaration(new Node(), true); + return node.finishExportDefaultDeclaration(declaration); + } + if (matchKeyword('class')) { + declaration = parseClassDeclaration(true); + return node.finishExportDefaultDeclaration(declaration); + } + + if (matchContextualKeyword('from')) { + throwError(Messages.UnexpectedToken, lookahead.value); + } + + // covers: + // export default {}; + // export default []; + // export default (1 + 2); + if (match('{')) { + expression = parseObjectInitializer(); + } else if (match('[')) { + expression = parseArrayInitializer(); + } else { + expression = parseAssignmentExpression(); + } + consumeSemicolon(); + return node.finishExportDefaultDeclaration(expression); + } + + function parseExportAllDeclaration(node) { + var src; + + // covers: + // export * from 'foo'; + expect('*'); + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + consumeSemicolon(); + + return node.finishExportAllDeclaration(src); + } + + function parseExportDeclaration() { + var node = new Node(); + if (state.inFunctionBody) { + throwError(Messages.IllegalExportDeclaration); + } + + expectKeyword('export'); + + if (matchKeyword('default')) { + return parseExportDefaultDeclaration(node); + } + if (match('*')) { + return parseExportAllDeclaration(node); + } + return parseExportNamedDeclaration(node); + } + + // ECMA-262 15.2.2 Imports + + function parseImportSpecifier() { + // import {} ...; + var local, imported, node = new Node(); + + imported = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { + lex(); + local = parseVariableIdentifier(); + } + + return node.finishImportSpecifier(local, imported); + } + + function parseNamedImports() { + var specifiers = []; + // {foo, bar as bas} + expect('{'); + while (!match('}')) { + specifiers.push(parseImportSpecifier()); + if (!match('}')) { + expect(','); + if (match('}')) { + break; + } + } + } + expect('}'); + return specifiers; + } + + function parseImportDefaultSpecifier() { + // import ...; + var local, node = new Node(); + + local = parseNonComputedProperty(); + + return node.finishImportDefaultSpecifier(local); + } + + function parseImportNamespaceSpecifier() { + // import <* as foo> ...; + var local, node = new Node(); + + expect('*'); + if (!matchContextualKeyword('as')) { + throwError(Messages.NoAsAfterImportNamespace); + } + lex(); + local = parseNonComputedProperty(); + + return node.finishImportNamespaceSpecifier(local); + } + + function parseImportDeclaration() { + var specifiers = [], src, node = new Node(); + + if (state.inFunctionBody) { + throwError(Messages.IllegalImportDeclaration); + } + + expectKeyword('import'); + + if (lookahead.type === Token.StringLiteral) { + // import 'foo'; + src = parseModuleSpecifier(); + } else { + + if (match('{')) { + // import {bar} + specifiers = specifiers.concat(parseNamedImports()); + } else if (match('*')) { + // import * as foo + specifiers.push(parseImportNamespaceSpecifier()); + } else if (isIdentifierName(lookahead) && !matchKeyword('default')) { + // import foo + specifiers.push(parseImportDefaultSpecifier()); + if (match(',')) { + lex(); + if (match('*')) { + // import foo, * as foo + specifiers.push(parseImportNamespaceSpecifier()); + } else if (match('{')) { + // import foo, {bar} + specifiers = specifiers.concat(parseNamedImports()); + } else { + throwUnexpectedToken(lookahead); + } + } + } else { + throwUnexpectedToken(lex()); + } + + if (!matchContextualKeyword('from')) { + throwError(lookahead.value ? + Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value); + } + lex(); + src = parseModuleSpecifier(); + } + + consumeSemicolon(); + return node.finishImportDeclaration(specifiers, src); + } + + // ECMA-262 15.1 Scripts + + function parseScriptBody() { + var statement, body = [], token, directive, firstRestricted; + + while (startIndex < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + statement = parseStatementListItem(); + body.push(statement); + if (statement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (startIndex < length) { + statement = parseStatementListItem(); + /* istanbul ignore if */ + if (typeof statement === 'undefined') { + break; + } + body.push(statement); + } + return body; + } + + function parseProgram() { + var body, node; + + peek(); + node = new Node(); + + body = parseScriptBody(); + return node.finishProgram(body, state.sourceType); + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (entry.regex) { + token.regex = { + pattern: entry.regex.pattern, + flags: entry.regex.flags + }; + } + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function tokenize(code, options, delegate) { + var toString, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + length = source.length; + lookahead = null; + state = { + allowIn: true, + allowYield: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1, + curlyStack: [] + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenValues = []; + extra.tokenize = true; + extra.delegate = delegate; + + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + lex(); + while (lookahead.type !== Token.EOF) { + try { + lex(); + } catch (lexError) { + if (extra.errors) { + recordError(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + tokens = extra.tokens; + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + startIndex = index; + startLineNumber = lineNumber; + startLineStart = lineStart; + length = source.length; + lookahead = null; + state = { + allowIn: true, + allowYield: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1, + curlyStack: [], + sourceType: 'script' + }; + strict = false; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; + + if (extra.loc && options.source !== null && options.source !== undefined) { + extra.source = toString(options.source); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + if (extra.attachComment) { + extra.range = true; + extra.comments = []; + extra.bottomRightStack = []; + extra.trailingComments = []; + extra.leadingComments = []; + } + if (options.sourceType === 'module') { + // very restrictive condition for now + state.sourceType = options.sourceType; + strict = true; + } + } + + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + + return program; + } + + // Sync with *.json manifests. + exports.version = '2.7.1'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + /* istanbul ignore next */ + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ + +},{}],51:[function(require,module,exports){ +/*! + * node-inherit + * Copyright(c) 2011 Dmitry Filatov + * MIT Licensed + */ + +module.exports = require('./lib/inherit'); + +},{"./lib/inherit":52}],52:[function(require,module,exports){ +/** + * @module inherit + * @version 2.2.2 + * @author Filatov Dmitry + * @description This module provides some syntax sugar for "class" declarations, constructors, mixins, "super" calls and static members. + */ + +(function(global) { + +var hasIntrospection = (function(){'_';}).toString().indexOf('_') > -1, + emptyBase = function() {}, + hasOwnProperty = Object.prototype.hasOwnProperty, + objCreate = Object.create || function(ptp) { + var inheritance = function() {}; + inheritance.prototype = ptp; + return new inheritance(); + }, + objKeys = Object.keys || function(obj) { + var res = []; + for(var i in obj) { + hasOwnProperty.call(obj, i) && res.push(i); + } + return res; + }, + extend = function(o1, o2) { + for(var i in o2) { + hasOwnProperty.call(o2, i) && (o1[i] = o2[i]); + } + + return o1; + }, + toStr = Object.prototype.toString, + isArray = Array.isArray || function(obj) { + return toStr.call(obj) === '[object Array]'; + }, + isFunction = function(obj) { + return toStr.call(obj) === '[object Function]'; + }, + noOp = function() {}, + needCheckProps = true, + testPropObj = { toString : '' }; + +for(var i in testPropObj) { // fucking ie hasn't toString, valueOf in for + testPropObj.hasOwnProperty(i) && (needCheckProps = false); +} + +var specProps = needCheckProps? ['toString', 'valueOf'] : null; + +function getPropList(obj) { + var res = objKeys(obj); + if(needCheckProps) { + var specProp, i = 0; + while(specProp = specProps[i++]) { + obj.hasOwnProperty(specProp) && res.push(specProp); + } + } + + return res; +} + +function override(base, res, add) { + var addList = getPropList(add), + j = 0, len = addList.length, + name, prop; + while(j < len) { + if((name = addList[j++]) === '__self') { + continue; + } + prop = add[name]; + if(isFunction(prop) && + (!hasIntrospection || prop.toString().indexOf('.__base') > -1)) { + res[name] = (function(name, prop) { + var baseMethod = base[name]? + base[name] : + name === '__constructor'? // case of inheritance from plane function + res.__self.__parent : + noOp; + return function() { + var baseSaved = this.__base; + this.__base = baseMethod; + var res = prop.apply(this, arguments); + this.__base = baseSaved; + return res; + }; + })(name, prop); + } else { + res[name] = prop; + } + } +} + +function applyMixins(mixins, res) { + var i = 1, mixin; + while(mixin = mixins[i++]) { + res? + isFunction(mixin)? + inherit.self(res, mixin.prototype, mixin) : + inherit.self(res, mixin) : + res = isFunction(mixin)? + inherit(mixins[0], mixin.prototype, mixin) : + inherit(mixins[0], mixin); + } + return res || mixins[0]; +} + +/** +* Creates class +* @exports +* @param {Function|Array} [baseClass|baseClassAndMixins] class (or class and mixins) to inherit from +* @param {Object} prototypeFields +* @param {Object} [staticFields] +* @returns {Function} class +*/ +function inherit() { + var args = arguments, + withMixins = isArray(args[0]), + hasBase = withMixins || isFunction(args[0]), + base = hasBase? withMixins? applyMixins(args[0]) : args[0] : emptyBase, + props = args[hasBase? 1 : 0] || {}, + staticProps = args[hasBase? 2 : 1], + res = props.__constructor || (hasBase && base.prototype.__constructor)? + function() { + return this.__constructor.apply(this, arguments); + } : + hasBase? + function() { + return base.apply(this, arguments); + } : + function() {}; + + if(!hasBase) { + res.prototype = props; + res.prototype.__self = res.prototype.constructor = res; + return extend(res, staticProps); + } + + extend(res, base); + + res.__parent = base; + + var basePtp = base.prototype, + resPtp = res.prototype = objCreate(basePtp); + + resPtp.__self = resPtp.constructor = res; + + props && override(basePtp, resPtp, props); + staticProps && override(base, res, staticProps); + + return res; +} + +inherit.self = function() { + var args = arguments, + withMixins = isArray(args[0]), + base = withMixins? applyMixins(args[0], args[0][0]) : args[0], + props = args[1], + staticProps = args[2], + basePtp = base.prototype; + + props && override(basePtp, basePtp, props); + staticProps && override(base, base, staticProps); + + return base; +}; + +var defineAsGlobal = true; +if(typeof exports === 'object') { + module.exports = inherit; + defineAsGlobal = false; +} + +if(typeof modules === 'object') { + modules.define('inherit', function(provide) { + provide(inherit); + }); + defineAsGlobal = false; +} + +if(typeof define === 'function') { + define(function(require, exports, module) { + module.exports = inherit; + }); + defineAsGlobal = false; +} + +defineAsGlobal && (global.inherit = inherit); + +})(this); + +},{}],53:[function(require,module,exports){ +var baseIndexOf = require('../internal/baseIndexOf'), + binaryIndex = require('../internal/binaryIndex'); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Gets the index at which the first occurrence of `value` is found in `array` + * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the offset + * from the end of `array`. If `array` is sorted providing `true` for `fromIndex` + * performs a faster binary search. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {boolean|number} [fromIndex=0] The index to search from or `true` + * to perform a binary search on a sorted array. + * @returns {number} Returns the index of the matched value, else `-1`. + * @example + * + * _.indexOf([1, 2, 1, 2], 2); + * // => 1 + * + * // using `fromIndex` + * _.indexOf([1, 2, 1, 2], 2, 2); + * // => 3 + * + * // performing a binary search + * _.indexOf([1, 1, 2, 2], 2, true); + * // => 2 + */ +function indexOf(array, value, fromIndex) { + var length = array ? array.length : 0; + if (!length) { + return -1; + } + if (typeof fromIndex == 'number') { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex; + } else if (fromIndex) { + var index = binaryIndex(array, value); + if (index < length && + (value === value ? (value === array[index]) : (array[index] !== array[index]))) { + return index; + } + return -1; + } + return baseIndexOf(array, value, fromIndex || 0); +} + +module.exports = indexOf; + +},{"../internal/baseIndexOf":82,"../internal/binaryIndex":96}],54:[function(require,module,exports){ +/** + * Gets the last element of `array`. + * + * @static + * @memberOf _ + * @category Array + * @param {Array} array The array to query. + * @returns {*} Returns the last element of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + */ +function last(array) { + var length = array ? array.length : 0; + return length ? array[length - 1] : undefined; +} + +module.exports = last; + +},{}],55:[function(require,module,exports){ +var LazyWrapper = require('../internal/LazyWrapper'), + LodashWrapper = require('../internal/LodashWrapper'), + baseLodash = require('../internal/baseLodash'), + isArray = require('../lang/isArray'), + isObjectLike = require('../internal/isObjectLike'), + wrapperClone = require('../internal/wrapperClone'); + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates a `lodash` object which wraps `value` to enable implicit chaining. + * Methods that operate on and return arrays, collections, and functions can + * be chained together. Methods that retrieve a single value or may return a + * primitive value will automatically end the chain returning the unwrapped + * value. Explicit chaining may be enabled using `_.chain`. The execution of + * chained methods is lazy, that is, execution is deferred until `_#value` + * is implicitly or explicitly called. + * + * Lazy evaluation allows several methods to support shortcut fusion. Shortcut + * fusion is an optimization strategy which merge iteratee calls; this can help + * to avoid the creation of intermediate data structures and greatly reduce the + * number of iteratee executions. + * + * Chaining is supported in custom builds as long as the `_#value` method is + * directly or indirectly included in the build. + * + * In addition to lodash methods, wrappers have `Array` and `String` methods. + * + * The wrapper `Array` methods are: + * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, + * `splice`, and `unshift` + * + * The wrapper `String` methods are: + * `replace` and `split` + * + * The wrapper methods that support shortcut fusion are: + * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`, + * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`, + * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`, + * and `where` + * + * The chainable wrapper methods are: + * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`, + * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`, + * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`, + * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`, + * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`, + * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`, + * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`, + * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, + * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`, + * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`, + * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`, + * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`, + * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`, + * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`, + * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`, + * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith` + * + * The wrapper methods that are **not** chainable by default are: + * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`, + * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`, + * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`, + * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`, + * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, + * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`, + * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`, + * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`, + * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`, + * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`, + * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`, + * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`, + * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`, + * `unescape`, `uniqueId`, `value`, and `words` + * + * The wrapper method `sample` will return a wrapped value when `n` is provided, + * otherwise an unwrapped value is returned. + * + * @name _ + * @constructor + * @category Chain + * @param {*} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns the new `lodash` wrapper instance. + * @example + * + * var wrapped = _([1, 2, 3]); + * + * // returns an unwrapped value + * wrapped.reduce(function(total, n) { + * return total + n; + * }); + * // => 6 + * + * // returns a wrapped value + * var squares = wrapped.map(function(n) { + * return n * n; + * }); + * + * _.isArray(squares); + * // => false + * + * _.isArray(squares.value()); + * // => true + */ +function lodash(value) { + if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { + if (value instanceof LodashWrapper) { + return value; + } + if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) { + return wrapperClone(value); + } + } + return new LodashWrapper(value); +} + +// Ensure wrappers are instances of `baseLodash`. +lodash.prototype = baseLodash.prototype; + +module.exports = lodash; + +},{"../internal/LazyWrapper":64,"../internal/LodashWrapper":65,"../internal/baseLodash":86,"../internal/isObjectLike":130,"../internal/wrapperClone":141,"../lang/isArray":144}],56:[function(require,module,exports){ +module.exports = require('./forEach'); + +},{"./forEach":58}],57:[function(require,module,exports){ +var baseEach = require('../internal/baseEach'), + createFind = require('../internal/createFind'); + +/** + * Iterates over elements of `collection`, returning the first element + * `predicate` returns truthy for. The predicate is bound to `thisArg` and + * invoked with three arguments: (value, index|key, collection). + * + * If a property name is provided for `predicate` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `predicate` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * @static + * @memberOf _ + * @alias detect + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {Function|Object|string} [predicate=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `predicate`. + * @returns {*} Returns the matched element, else `undefined`. + * @example + * + * var users = [ + * { 'user': 'barney', 'age': 36, 'active': true }, + * { 'user': 'fred', 'age': 40, 'active': false }, + * { 'user': 'pebbles', 'age': 1, 'active': true } + * ]; + * + * _.result(_.find(users, function(chr) { + * return chr.age < 40; + * }), 'user'); + * // => 'barney' + * + * // using the `_.matches` callback shorthand + * _.result(_.find(users, { 'age': 1, 'active': true }), 'user'); + * // => 'pebbles' + * + * // using the `_.matchesProperty` callback shorthand + * _.result(_.find(users, 'active', false), 'user'); + * // => 'fred' + * + * // using the `_.property` callback shorthand + * _.result(_.find(users, 'active'), 'user'); + * // => 'barney' + */ +var find = createFind(baseEach); + +module.exports = find; + +},{"../internal/baseEach":75,"../internal/createFind":106}],58:[function(require,module,exports){ +var arrayEach = require('../internal/arrayEach'), + baseEach = require('../internal/baseEach'), + createForEach = require('../internal/createForEach'); + +/** + * Iterates over elements of `collection` invoking `iteratee` for each element. + * The `iteratee` is bound to `thisArg` and invoked with three arguments: + * (value, index|key, collection). Iteratee functions may exit iteration early + * by explicitly returning `false`. + * + * **Note:** As with other "Collections" methods, objects with a "length" property + * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn` + * may be used for object iteration. + * + * @static + * @memberOf _ + * @alias each + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} [iteratee=_.identity] The function invoked per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array|Object|string} Returns `collection`. + * @example + * + * _([1, 2]).forEach(function(n) { + * console.log(n); + * }).value(); + * // => logs each value from left to right and returns the array + * + * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) { + * console.log(n, key); + * }); + * // => logs each value-key pair and returns the object (iteration order is not guaranteed) + */ +var forEach = createForEach(arrayEach, baseEach); + +module.exports = forEach; + +},{"../internal/arrayEach":67,"../internal/baseEach":75,"../internal/createForEach":107}],59:[function(require,module,exports){ +var baseIndexOf = require('../internal/baseIndexOf'), + getLength = require('../internal/getLength'), + isArray = require('../lang/isArray'), + isIterateeCall = require('../internal/isIterateeCall'), + isLength = require('../internal/isLength'), + isString = require('../lang/isString'), + values = require('../object/values'); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Checks if `target` is in `collection` using + * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * for equality comparisons. If `fromIndex` is negative, it's used as the offset + * from the end of `collection`. + * + * @static + * @memberOf _ + * @alias contains, include + * @category Collection + * @param {Array|Object|string} collection The collection to search. + * @param {*} target The value to search for. + * @param {number} [fromIndex=0] The index to search from. + * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`. + * @returns {boolean} Returns `true` if a matching element is found, else `false`. + * @example + * + * _.includes([1, 2, 3], 1); + * // => true + * + * _.includes([1, 2, 3], 1, 2); + * // => false + * + * _.includes({ 'user': 'fred', 'age': 40 }, 'fred'); + * // => true + * + * _.includes('pebbles', 'eb'); + * // => true + */ +function includes(collection, target, fromIndex, guard) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + collection = values(collection); + length = collection.length; + } + if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) { + fromIndex = 0; + } else { + fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0); + } + return (typeof collection == 'string' || !isArray(collection) && isString(collection)) + ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) + : (!!length && baseIndexOf(collection, target, fromIndex) > -1); +} + +module.exports = includes; + +},{"../internal/baseIndexOf":82,"../internal/getLength":116,"../internal/isIterateeCall":126,"../internal/isLength":129,"../lang/isArray":144,"../lang/isString":150,"../object/values":156}],60:[function(require,module,exports){ +var arrayMap = require('../internal/arrayMap'), + baseCallback = require('../internal/baseCallback'), + baseMap = require('../internal/baseMap'), + isArray = require('../lang/isArray'); + +/** + * Creates an array of values by running each element in `collection` through + * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three + * arguments: (value, index|key, collection). + * + * If a property name is provided for `iteratee` the created `_.property` + * style callback returns the property value of the given element. + * + * If a value is also provided for `thisArg` the created `_.matchesProperty` + * style callback returns `true` for elements that have a matching property + * value, else `false`. + * + * If an object is provided for `iteratee` the created `_.matches` style + * callback returns `true` for elements that have the properties of the given + * object, else `false`. + * + * Many lodash methods are guarded to work as iteratees for methods like + * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. + * + * The guarded methods are: + * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`, + * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`, + * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`, + * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`, + * `sum`, `uniq`, and `words` + * + * @static + * @memberOf _ + * @alias collect + * @category Collection + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function|Object|string} [iteratee=_.identity] The function invoked + * per iteration. + * @param {*} [thisArg] The `this` binding of `iteratee`. + * @returns {Array} Returns the new mapped array. + * @example + * + * function timesThree(n) { + * return n * 3; + * } + * + * _.map([1, 2], timesThree); + * // => [3, 6] + * + * _.map({ 'a': 1, 'b': 2 }, timesThree); + * // => [3, 6] (iteration order is not guaranteed) + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * // using the `_.property` callback shorthand + * _.map(users, 'user'); + * // => ['barney', 'fred'] + */ +function map(collection, iteratee, thisArg) { + var func = isArray(collection) ? arrayMap : baseMap; + iteratee = baseCallback(iteratee, thisArg, 3); + return func(collection, iteratee); +} + +module.exports = map; + +},{"../internal/arrayMap":68,"../internal/baseCallback":71,"../internal/baseMap":87,"../lang/isArray":144}],61:[function(require,module,exports){ +var getNative = require('../internal/getNative'); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeNow = getNative(Date, 'now'); + +/** + * Gets the number of milliseconds that have elapsed since the Unix epoch + * (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @category Date + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => logs the number of milliseconds it took for the deferred function to be invoked + */ +var now = nativeNow || function() { + return new Date().getTime(); +}; + +module.exports = now; + +},{"../internal/getNative":118}],62:[function(require,module,exports){ +var createWrapper = require('../internal/createWrapper'), + replaceHolders = require('../internal/replaceHolders'), + restParam = require('./restParam'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1, + PARTIAL_FLAG = 32; + +/** + * Creates a function that invokes `func` with the `this` binding of `thisArg` + * and prepends any additional `_.bind` arguments to those provided to the + * bound function. + * + * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, + * may be used as a placeholder for partially applied arguments. + * + * **Note:** Unlike native `Function#bind` this method does not set the "length" + * property of bound functions. + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {...*} [partials] The arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var greet = function(greeting, punctuation) { + * return greeting + ' ' + this.user + punctuation; + * }; + * + * var object = { 'user': 'fred' }; + * + * var bound = _.bind(greet, object, 'hi'); + * bound('!'); + * // => 'hi fred!' + * + * // using placeholders + * var bound = _.bind(greet, object, _, '!'); + * bound('hi'); + * // => 'hi fred!' + */ +var bind = restParam(function(func, thisArg, partials) { + var bitmask = BIND_FLAG; + if (partials.length) { + var holders = replaceHolders(partials, bind.placeholder); + bitmask |= PARTIAL_FLAG; + } + return createWrapper(func, bitmask, thisArg, partials, holders); +}); + +// Assign default placeholders. +bind.placeholder = {}; + +module.exports = bind; + +},{"../internal/createWrapper":110,"../internal/replaceHolders":136,"./restParam":63}],63:[function(require,module,exports){ +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates a function that invokes `func` with the `this` binding of the + * created function and arguments from `start` and beyond provided as an array. + * + * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/Web/JavaScript/Reference/Functions/rest_parameters). + * + * @static + * @memberOf _ + * @category Function + * @param {Function} func The function to apply a rest parameter to. + * @param {number} [start=func.length-1] The start position of the rest parameter. + * @returns {Function} Returns the new function. + * @example + * + * var say = _.restParam(function(what, names) { + * return what + ' ' + _.initial(names).join(', ') + + * (_.size(names) > 1 ? ', & ' : '') + _.last(names); + * }); + * + * say('hello', 'fred', 'barney', 'pebbles'); + * // => 'hello fred, barney, & pebbles' + */ +function restParam(func, start) { + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0); + return function() { + var args = arguments, + index = -1, + length = nativeMax(args.length - start, 0), + rest = Array(length); + + while (++index < length) { + rest[index] = args[start + index]; + } + switch (start) { + case 0: return func.call(this, rest); + case 1: return func.call(this, args[0], rest); + case 2: return func.call(this, args[0], args[1], rest); + } + var otherArgs = Array(start + 1); + index = -1; + while (++index < start) { + otherArgs[index] = args[index]; + } + otherArgs[start] = rest; + return func.apply(this, otherArgs); + }; +} + +module.exports = restParam; + +},{}],64:[function(require,module,exports){ +var baseCreate = require('./baseCreate'), + baseLodash = require('./baseLodash'); + +/** Used as references for `-Infinity` and `Infinity`. */ +var POSITIVE_INFINITY = Number.POSITIVE_INFINITY; + +/** + * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. + * + * @private + * @param {*} value The value to wrap. + */ +function LazyWrapper(value) { + this.__wrapped__ = value; + this.__actions__ = []; + this.__dir__ = 1; + this.__filtered__ = false; + this.__iteratees__ = []; + this.__takeCount__ = POSITIVE_INFINITY; + this.__views__ = []; +} + +LazyWrapper.prototype = baseCreate(baseLodash.prototype); +LazyWrapper.prototype.constructor = LazyWrapper; + +module.exports = LazyWrapper; + +},{"./baseCreate":74,"./baseLodash":86}],65:[function(require,module,exports){ +var baseCreate = require('./baseCreate'), + baseLodash = require('./baseLodash'); + +/** + * The base constructor for creating `lodash` wrapper objects. + * + * @private + * @param {*} value The value to wrap. + * @param {boolean} [chainAll] Enable chaining for all wrapper methods. + * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value. + */ +function LodashWrapper(value, chainAll, actions) { + this.__wrapped__ = value; + this.__actions__ = actions || []; + this.__chain__ = !!chainAll; +} + +LodashWrapper.prototype = baseCreate(baseLodash.prototype); +LodashWrapper.prototype.constructor = LodashWrapper; + +module.exports = LodashWrapper; + +},{"./baseCreate":74,"./baseLodash":86}],66:[function(require,module,exports){ +/** + * Copies the values of `source` to `array`. + * + * @private + * @param {Array} source The array to copy values from. + * @param {Array} [array=[]] The array to copy values to. + * @returns {Array} Returns `array`. + */ +function arrayCopy(source, array) { + var index = -1, + length = source.length; + + array || (array = Array(length)); + while (++index < length) { + array[index] = source[index]; + } + return array; +} + +module.exports = arrayCopy; + +},{}],67:[function(require,module,exports){ +/** + * A specialized version of `_.forEach` for arrays without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns `array`. + */ +function arrayEach(array, iteratee) { + var index = -1, + length = array.length; + + while (++index < length) { + if (iteratee(array[index], index, array) === false) { + break; + } + } + return array; +} + +module.exports = arrayEach; + +},{}],68:[function(require,module,exports){ +/** + * A specialized version of `_.map` for arrays without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function arrayMap(array, iteratee) { + var index = -1, + length = array.length, + result = Array(length); + + while (++index < length) { + result[index] = iteratee(array[index], index, array); + } + return result; +} + +module.exports = arrayMap; + +},{}],69:[function(require,module,exports){ +/** + * A specialized version of `_.some` for arrays without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} predicate The function invoked per iteration. + * @returns {boolean} Returns `true` if any element passes the predicate check, + * else `false`. + */ +function arraySome(array, predicate) { + var index = -1, + length = array.length; + + while (++index < length) { + if (predicate(array[index], index, array)) { + return true; + } + } + return false; +} + +module.exports = arraySome; + +},{}],70:[function(require,module,exports){ +var baseCopy = require('./baseCopy'), + keys = require('../object/keys'); + +/** + * The base implementation of `_.assign` without support for argument juggling, + * multiple sources, and `customizer` functions. + * + * @private + * @param {Object} object The destination object. + * @param {Object} source The source object. + * @returns {Object} Returns `object`. + */ +function baseAssign(object, source) { + return source == null + ? object + : baseCopy(source, keys(source), object); +} + +module.exports = baseAssign; + +},{"../object/keys":153,"./baseCopy":73}],71:[function(require,module,exports){ +var baseMatches = require('./baseMatches'), + baseMatchesProperty = require('./baseMatchesProperty'), + bindCallback = require('./bindCallback'), + identity = require('../utility/identity'), + property = require('../utility/property'); + +/** + * The base implementation of `_.callback` which supports specifying the + * number of arguments to provide to `func`. + * + * @private + * @param {*} [func=_.identity] The value to convert to a callback. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. + */ +function baseCallback(func, thisArg, argCount) { + var type = typeof func; + if (type == 'function') { + return thisArg === undefined + ? func + : bindCallback(func, thisArg, argCount); + } + if (func == null) { + return identity; + } + if (type == 'object') { + return baseMatches(func); + } + return thisArg === undefined + ? property(func) + : baseMatchesProperty(func, thisArg); +} + +module.exports = baseCallback; + +},{"../utility/identity":158,"../utility/property":160,"./baseMatches":88,"./baseMatchesProperty":89,"./bindCallback":98}],72:[function(require,module,exports){ +var arrayCopy = require('./arrayCopy'), + arrayEach = require('./arrayEach'), + baseAssign = require('./baseAssign'), + baseForOwn = require('./baseForOwn'), + initCloneArray = require('./initCloneArray'), + initCloneByTag = require('./initCloneByTag'), + initCloneObject = require('./initCloneObject'), + isArray = require('../lang/isArray'), + isHostObject = require('./isHostObject'), + isObject = require('../lang/isObject'); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values supported by `_.clone`. */ +var cloneableTags = {}; +cloneableTags[argsTag] = cloneableTags[arrayTag] = +cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = +cloneableTags[dateTag] = cloneableTags[float32Tag] = +cloneableTags[float64Tag] = cloneableTags[int8Tag] = +cloneableTags[int16Tag] = cloneableTags[int32Tag] = +cloneableTags[numberTag] = cloneableTags[objectTag] = +cloneableTags[regexpTag] = cloneableTags[stringTag] = +cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = +cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; +cloneableTags[errorTag] = cloneableTags[funcTag] = +cloneableTags[mapTag] = cloneableTags[setTag] = +cloneableTags[weakMapTag] = false; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * The base implementation of `_.clone` without support for argument juggling + * and `this` binding `customizer` functions. + * + * @private + * @param {*} value The value to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {string} [key] The key of `value`. + * @param {Object} [object] The object `value` belongs to. + * @param {Array} [stackA=[]] Tracks traversed source objects. + * @param {Array} [stackB=[]] Associates clones with source counterparts. + * @returns {*} Returns the cloned value. + */ +function baseClone(value, isDeep, customizer, key, object, stackA, stackB) { + var result; + if (customizer) { + result = object ? customizer(value, key, object) : customizer(value); + } + if (result !== undefined) { + return result; + } + if (!isObject(value)) { + return value; + } + var isArr = isArray(value); + if (isArr) { + result = initCloneArray(value); + if (!isDeep) { + return arrayCopy(value, result); + } + } else { + var tag = objToString.call(value), + isFunc = tag == funcTag; + + if (tag == objectTag || tag == argsTag || (isFunc && !object)) { + if (isHostObject(value)) { + return object ? value : {}; + } + result = initCloneObject(isFunc ? {} : value); + if (!isDeep) { + return baseAssign(result, value); + } + } else { + return cloneableTags[tag] + ? initCloneByTag(value, tag, isDeep) + : (object ? value : {}); + } + } + // Check for circular references and return its corresponding clone. + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // Add the source value to the stack of traversed objects and associate it with its clone. + stackA.push(value); + stackB.push(result); + + // Recursively populate clone (susceptible to call stack limits). + (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) { + result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB); + }); + return result; +} + +module.exports = baseClone; + +},{"../lang/isArray":144,"../lang/isObject":148,"./arrayCopy":66,"./arrayEach":67,"./baseAssign":70,"./baseForOwn":80,"./initCloneArray":120,"./initCloneByTag":121,"./initCloneObject":122,"./isHostObject":124}],73:[function(require,module,exports){ +/** + * Copies properties of `source` to `object`. + * + * @private + * @param {Object} source The object to copy properties from. + * @param {Array} props The property names to copy. + * @param {Object} [object={}] The object to copy properties to. + * @returns {Object} Returns `object`. + */ +function baseCopy(source, props, object) { + object || (object = {}); + + var index = -1, + length = props.length; + + while (++index < length) { + var key = props[index]; + object[key] = source[key]; + } + return object; +} + +module.exports = baseCopy; + +},{}],74:[function(require,module,exports){ +var isObject = require('../lang/isObject'); + +/** + * The base implementation of `_.create` without support for assigning + * properties to the created object. + * + * @private + * @param {Object} prototype The object to inherit from. + * @returns {Object} Returns the new object. + */ +var baseCreate = (function() { + function object() {} + return function(prototype) { + if (isObject(prototype)) { + object.prototype = prototype; + var result = new object; + object.prototype = undefined; + } + return result || {}; + }; +}()); + +module.exports = baseCreate; + +},{"../lang/isObject":148}],75:[function(require,module,exports){ +var baseForOwn = require('./baseForOwn'), + createBaseEach = require('./createBaseEach'); + +/** + * The base implementation of `_.forEach` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array|Object|string} Returns `collection`. + */ +var baseEach = createBaseEach(baseForOwn); + +module.exports = baseEach; + +},{"./baseForOwn":80,"./createBaseEach":102}],76:[function(require,module,exports){ +/** + * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`, + * without support for callback shorthands and `this` binding, which iterates + * over `collection` using the provided `eachFunc`. + * + * @private + * @param {Array|Object|string} collection The collection to search. + * @param {Function} predicate The function invoked per iteration. + * @param {Function} eachFunc The function to iterate over `collection`. + * @param {boolean} [retKey] Specify returning the key of the found element + * instead of the element itself. + * @returns {*} Returns the found element or its key, else `undefined`. + */ +function baseFind(collection, predicate, eachFunc, retKey) { + var result; + eachFunc(collection, function(value, key, collection) { + if (predicate(value, key, collection)) { + result = retKey ? key : value; + return false; + } + }); + return result; +} + +module.exports = baseFind; + +},{}],77:[function(require,module,exports){ +/** + * The base implementation of `_.findIndex` and `_.findLastIndex` without + * support for callback shorthands and `this` binding. + * + * @private + * @param {Array} array The array to search. + * @param {Function} predicate The function invoked per iteration. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseFindIndex(array, predicate, fromRight) { + var length = array.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + if (predicate(array[index], index, array)) { + return index; + } + } + return -1; +} + +module.exports = baseFindIndex; + +},{}],78:[function(require,module,exports){ +var createBaseFor = require('./createBaseFor'); + +/** + * The base implementation of `baseForIn` and `baseForOwn` which iterates + * over `object` properties returned by `keysFunc` invoking `iteratee` for + * each property. Iteratee functions may exit iteration early by explicitly + * returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @param {Function} keysFunc The function to get the keys of `object`. + * @returns {Object} Returns `object`. + */ +var baseFor = createBaseFor(); + +module.exports = baseFor; + +},{"./createBaseFor":103}],79:[function(require,module,exports){ +var baseFor = require('./baseFor'), + keysIn = require('../object/keysIn'); + +/** + * The base implementation of `_.forIn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForIn(object, iteratee) { + return baseFor(object, iteratee, keysIn); +} + +module.exports = baseForIn; + +},{"../object/keysIn":154,"./baseFor":78}],80:[function(require,module,exports){ +var baseFor = require('./baseFor'), + keys = require('../object/keys'); + +/** + * The base implementation of `_.forOwn` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Object} Returns `object`. + */ +function baseForOwn(object, iteratee) { + return baseFor(object, iteratee, keys); +} + +module.exports = baseForOwn; + +},{"../object/keys":153,"./baseFor":78}],81:[function(require,module,exports){ +var toObject = require('./toObject'); + +/** + * The base implementation of `get` without support for string paths + * and default values. + * + * @private + * @param {Object} object The object to query. + * @param {Array} path The path of the property to get. + * @param {string} [pathKey] The key representation of path. + * @returns {*} Returns the resolved value. + */ +function baseGet(object, path, pathKey) { + if (object == null) { + return; + } + object = toObject(object); + if (pathKey !== undefined && pathKey in object) { + path = [pathKey]; + } + var index = 0, + length = path.length; + + while (object != null && index < length) { + object = toObject(object)[path[index++]]; + } + return (index && index == length) ? object : undefined; +} + +module.exports = baseGet; + +},{"./toObject":139}],82:[function(require,module,exports){ +var indexOfNaN = require('./indexOfNaN'); + +/** + * The base implementation of `_.indexOf` without support for binary searches. + * + * @private + * @param {Array} array The array to search. + * @param {*} value The value to search for. + * @param {number} fromIndex The index to search from. + * @returns {number} Returns the index of the matched value, else `-1`. + */ +function baseIndexOf(array, value, fromIndex) { + if (value !== value) { + return indexOfNaN(array, fromIndex); + } + var index = fromIndex - 1, + length = array.length; + + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; +} + +module.exports = baseIndexOf; + +},{"./indexOfNaN":119}],83:[function(require,module,exports){ +var baseIsEqualDeep = require('./baseIsEqualDeep'), + isObject = require('../lang/isObject'), + isObjectLike = require('./isObjectLike'); + +/** + * The base implementation of `_.isEqual` without support for `this` binding + * `customizer` functions. + * + * @private + * @param {*} value The value to compare. + * @param {*} other The other value to compare. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isLoose] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. + */ +function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) { + if (value === other) { + return true; + } + if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) { + return value !== value && other !== other; + } + return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB); +} + +module.exports = baseIsEqual; + +},{"../lang/isObject":148,"./baseIsEqualDeep":84,"./isObjectLike":130}],84:[function(require,module,exports){ +var equalArrays = require('./equalArrays'), + equalByTag = require('./equalByTag'), + equalObjects = require('./equalObjects'), + isArray = require('../lang/isArray'), + isHostObject = require('./isHostObject'), + isTypedArray = require('../lang/isTypedArray'); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + objectTag = '[object Object]'; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * A specialized version of `baseIsEqual` for arrays and objects which performs + * deep comparisons and tracks traversed objects enabling objects with circular + * references to be compared. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing objects. + * @param {boolean} [isLoose] Specify performing partial comparisons. + * @param {Array} [stackA=[]] Tracks traversed `value` objects. + * @param {Array} [stackB=[]] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objIsArr = isArray(object), + othIsArr = isArray(other), + objTag = arrayTag, + othTag = arrayTag; + + if (!objIsArr) { + objTag = objToString.call(object); + if (objTag == argsTag) { + objTag = objectTag; + } else if (objTag != objectTag) { + objIsArr = isTypedArray(object); + } + } + if (!othIsArr) { + othTag = objToString.call(other); + if (othTag == argsTag) { + othTag = objectTag; + } else if (othTag != objectTag) { + othIsArr = isTypedArray(other); + } + } + var objIsObj = objTag == objectTag && !isHostObject(object), + othIsObj = othTag == objectTag && !isHostObject(other), + isSameTag = objTag == othTag; + + if (isSameTag && !(objIsArr || objIsObj)) { + return equalByTag(object, other, objTag); + } + if (!isLoose) { + var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), + othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); + + if (objIsWrapped || othIsWrapped) { + return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB); + } + } + if (!isSameTag) { + return false; + } + // Assume cyclic values are equal. + // For more information on detecting circular references see https://es5.github.io/#JO. + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == object) { + return stackB[length] == other; + } + } + // Add `object` and `other` to the stack of traversed objects. + stackA.push(object); + stackB.push(other); + + var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB); + + stackA.pop(); + stackB.pop(); + + return result; +} + +module.exports = baseIsEqualDeep; + +},{"../lang/isArray":144,"../lang/isTypedArray":151,"./equalArrays":111,"./equalByTag":112,"./equalObjects":113,"./isHostObject":124}],85:[function(require,module,exports){ +var baseIsEqual = require('./baseIsEqual'), + toObject = require('./toObject'); + +/** + * The base implementation of `_.isMatch` without support for callback + * shorthands and `this` binding. + * + * @private + * @param {Object} object The object to inspect. + * @param {Array} matchData The propery names, values, and compare flags to match. + * @param {Function} [customizer] The function to customize comparing objects. + * @returns {boolean} Returns `true` if `object` is a match, else `false`. + */ +function baseIsMatch(object, matchData, customizer) { + var index = matchData.length, + length = index, + noCustomizer = !customizer; + + if (object == null) { + return !length; + } + object = toObject(object); + while (index--) { + var data = matchData[index]; + if ((noCustomizer && data[2]) + ? data[1] !== object[data[0]] + : !(data[0] in object) + ) { + return false; + } + } + while (++index < length) { + data = matchData[index]; + var key = data[0], + objValue = object[key], + srcValue = data[1]; + + if (noCustomizer && data[2]) { + if (objValue === undefined && !(key in object)) { + return false; + } + } else { + var result = customizer ? customizer(objValue, srcValue, key) : undefined; + if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) { + return false; + } + } + } + return true; +} + +module.exports = baseIsMatch; + +},{"./baseIsEqual":83,"./toObject":139}],86:[function(require,module,exports){ +/** + * The function whose prototype all chaining wrappers inherit from. + * + * @private + */ +function baseLodash() { + // No operation performed. +} + +module.exports = baseLodash; + +},{}],87:[function(require,module,exports){ +var baseEach = require('./baseEach'), + isArrayLike = require('./isArrayLike'); + +/** + * The base implementation of `_.map` without support for callback shorthands + * and `this` binding. + * + * @private + * @param {Array|Object|string} collection The collection to iterate over. + * @param {Function} iteratee The function invoked per iteration. + * @returns {Array} Returns the new mapped array. + */ +function baseMap(collection, iteratee) { + var index = -1, + result = isArrayLike(collection) ? Array(collection.length) : []; + + baseEach(collection, function(value, key, collection) { + result[++index] = iteratee(value, key, collection); + }); + return result; +} + +module.exports = baseMap; + +},{"./baseEach":75,"./isArrayLike":123}],88:[function(require,module,exports){ +var baseIsMatch = require('./baseIsMatch'), + getMatchData = require('./getMatchData'), + toObject = require('./toObject'); + +/** + * The base implementation of `_.matches` which does not clone `source`. + * + * @private + * @param {Object} source The object of property values to match. + * @returns {Function} Returns the new function. + */ +function baseMatches(source) { + var matchData = getMatchData(source); + if (matchData.length == 1 && matchData[0][2]) { + var key = matchData[0][0], + value = matchData[0][1]; + + return function(object) { + if (object == null) { + return false; + } + object = toObject(object); + return object[key] === value && (value !== undefined || (key in object)); + }; + } + return function(object) { + return baseIsMatch(object, matchData); + }; +} + +module.exports = baseMatches; + +},{"./baseIsMatch":85,"./getMatchData":117,"./toObject":139}],89:[function(require,module,exports){ +var baseGet = require('./baseGet'), + baseIsEqual = require('./baseIsEqual'), + baseSlice = require('./baseSlice'), + isArray = require('../lang/isArray'), + isKey = require('./isKey'), + isStrictComparable = require('./isStrictComparable'), + last = require('../array/last'), + toObject = require('./toObject'), + toPath = require('./toPath'); + +/** + * The base implementation of `_.matchesProperty` which does not clone `srcValue`. + * + * @private + * @param {string} path The path of the property to get. + * @param {*} srcValue The value to compare. + * @returns {Function} Returns the new function. + */ +function baseMatchesProperty(path, srcValue) { + var isArr = isArray(path), + isCommon = isKey(path) && isStrictComparable(srcValue), + pathKey = (path + ''); + + path = toPath(path); + return function(object) { + if (object == null) { + return false; + } + var key = pathKey; + object = toObject(object); + if ((isArr || !isCommon) && !(key in object)) { + object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1)); + if (object == null) { + return false; + } + key = last(path); + object = toObject(object); + } + return object[key] === srcValue + ? (srcValue !== undefined || (key in object)) + : baseIsEqual(srcValue, object[key], undefined, true); + }; +} + +module.exports = baseMatchesProperty; + +},{"../array/last":54,"../lang/isArray":144,"./baseGet":81,"./baseIsEqual":83,"./baseSlice":93,"./isKey":127,"./isStrictComparable":131,"./toObject":139,"./toPath":140}],90:[function(require,module,exports){ +var toObject = require('./toObject'); + +/** + * The base implementation of `_.property` without support for deep paths. + * + * @private + * @param {string} key The key of the property to get. + * @returns {Function} Returns the new function. + */ +function baseProperty(key) { + return function(object) { + return object == null ? undefined : toObject(object)[key]; + }; +} + +module.exports = baseProperty; + +},{"./toObject":139}],91:[function(require,module,exports){ +var baseGet = require('./baseGet'), + toPath = require('./toPath'); + +/** + * A specialized version of `baseProperty` which supports deep paths. + * + * @private + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new function. + */ +function basePropertyDeep(path) { + var pathKey = (path + ''); + path = toPath(path); + return function(object) { + return baseGet(object, path, pathKey); + }; +} + +module.exports = basePropertyDeep; + +},{"./baseGet":81,"./toPath":140}],92:[function(require,module,exports){ +var identity = require('../utility/identity'), + metaMap = require('./metaMap'); + +/** + * The base implementation of `setData` without support for hot loop detection. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ +var baseSetData = !metaMap ? identity : function(func, data) { + metaMap.set(func, data); + return func; +}; + +module.exports = baseSetData; + +},{"../utility/identity":158,"./metaMap":133}],93:[function(require,module,exports){ +/** + * The base implementation of `_.slice` without an iteratee call guard. + * + * @private + * @param {Array} array The array to slice. + * @param {number} [start=0] The start position. + * @param {number} [end=array.length] The end position. + * @returns {Array} Returns the slice of `array`. + */ +function baseSlice(array, start, end) { + var index = -1, + length = array.length; + + start = start == null ? 0 : (+start || 0); + if (start < 0) { + start = -start > length ? 0 : (length + start); + } + end = (end === undefined || end > length) ? length : (+end || 0); + if (end < 0) { + end += length; + } + length = start > end ? 0 : ((end - start) >>> 0); + start >>>= 0; + + var result = Array(length); + while (++index < length) { + result[index] = array[index + start]; + } + return result; +} + +module.exports = baseSlice; + +},{}],94:[function(require,module,exports){ +/** + * Converts `value` to a string if it's not one. An empty string is returned + * for `null` or `undefined` values. + * + * @private + * @param {*} value The value to process. + * @returns {string} Returns the string. + */ +function baseToString(value) { + return value == null ? '' : (value + ''); +} + +module.exports = baseToString; + +},{}],95:[function(require,module,exports){ +/** + * The base implementation of `_.values` and `_.valuesIn` which creates an + * array of `object` property values corresponding to the property names + * of `props`. + * + * @private + * @param {Object} object The object to query. + * @param {Array} props The property names to get values for. + * @returns {Object} Returns the array of property values. + */ +function baseValues(object, props) { + var index = -1, + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; +} + +module.exports = baseValues; + +},{}],96:[function(require,module,exports){ +var binaryIndexBy = require('./binaryIndexBy'), + identity = require('../utility/identity'); + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295, + HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; + +/** + * Performs a binary search of `array` to determine the index at which `value` + * should be inserted into `array` in order to maintain its sort order. + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ +function binaryIndex(array, value, retHighest) { + var low = 0, + high = array ? array.length : low; + + if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { + while (low < high) { + var mid = (low + high) >>> 1, + computed = array[mid]; + + if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) { + low = mid + 1; + } else { + high = mid; + } + } + return high; + } + return binaryIndexBy(array, value, identity, retHighest); +} + +module.exports = binaryIndex; + +},{"../utility/identity":158,"./binaryIndexBy":97}],97:[function(require,module,exports){ +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeFloor = Math.floor, + nativeMin = Math.min; + +/** Used as references for the maximum length and index of an array. */ +var MAX_ARRAY_LENGTH = 4294967295, + MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1; + +/** + * This function is like `binaryIndex` except that it invokes `iteratee` for + * `value` and each element of `array` to compute their sort ranking. The + * iteratee is invoked with one argument; (value). + * + * @private + * @param {Array} array The sorted array to inspect. + * @param {*} value The value to evaluate. + * @param {Function} iteratee The function invoked per iteration. + * @param {boolean} [retHighest] Specify returning the highest qualified index. + * @returns {number} Returns the index at which `value` should be inserted + * into `array`. + */ +function binaryIndexBy(array, value, iteratee, retHighest) { + value = iteratee(value); + + var low = 0, + high = array ? array.length : 0, + valIsNaN = value !== value, + valIsNull = value === null, + valIsUndef = value === undefined; + + while (low < high) { + var mid = nativeFloor((low + high) / 2), + computed = iteratee(array[mid]), + isDef = computed !== undefined, + isReflexive = computed === computed; + + if (valIsNaN) { + var setLow = isReflexive || retHighest; + } else if (valIsNull) { + setLow = isReflexive && isDef && (retHighest || computed != null); + } else if (valIsUndef) { + setLow = isReflexive && (retHighest || isDef); + } else if (computed == null) { + setLow = false; + } else { + setLow = retHighest ? (computed <= value) : (computed < value); + } + if (setLow) { + low = mid + 1; + } else { + high = mid; + } + } + return nativeMin(high, MAX_ARRAY_INDEX); +} + +module.exports = binaryIndexBy; + +},{}],98:[function(require,module,exports){ +var identity = require('../utility/identity'); + +/** + * A specialized version of `baseCallback` which only supports `this` binding + * and specifying the number of arguments to provide to `func`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} thisArg The `this` binding of `func`. + * @param {number} [argCount] The number of arguments to provide to `func`. + * @returns {Function} Returns the callback. + */ +function bindCallback(func, thisArg, argCount) { + if (typeof func != 'function') { + return identity; + } + if (thisArg === undefined) { + return func; + } + switch (argCount) { + case 1: return function(value) { + return func.call(thisArg, value); + }; + case 3: return function(value, index, collection) { + return func.call(thisArg, value, index, collection); + }; + case 4: return function(accumulator, value, index, collection) { + return func.call(thisArg, accumulator, value, index, collection); + }; + case 5: return function(value, other, key, object, source) { + return func.call(thisArg, value, other, key, object, source); + }; + } + return function() { + return func.apply(thisArg, arguments); + }; +} + +module.exports = bindCallback; + +},{"../utility/identity":158}],99:[function(require,module,exports){ +(function (global){ +/** Native method references. */ +var ArrayBuffer = global.ArrayBuffer, + Uint8Array = global.Uint8Array; + +/** + * Creates a clone of the given array buffer. + * + * @private + * @param {ArrayBuffer} buffer The array buffer to clone. + * @returns {ArrayBuffer} Returns the cloned array buffer. + */ +function bufferClone(buffer) { + var result = new ArrayBuffer(buffer.byteLength), + view = new Uint8Array(result); + + view.set(new Uint8Array(buffer)); + return result; +} + +module.exports = bufferClone; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2J1ZmZlckNsb25lLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgQXJyYXlCdWZmZXIgPSBnbG9iYWwuQXJyYXlCdWZmZXIsXG4gICAgVWludDhBcnJheSA9IGdsb2JhbC5VaW50OEFycmF5O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjbG9uZSBvZiB0aGUgZ2l2ZW4gYXJyYXkgYnVmZmVyLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5QnVmZmVyfSBidWZmZXIgVGhlIGFycmF5IGJ1ZmZlciB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtBcnJheUJ1ZmZlcn0gUmV0dXJucyB0aGUgY2xvbmVkIGFycmF5IGJ1ZmZlci5cbiAqL1xuZnVuY3Rpb24gYnVmZmVyQ2xvbmUoYnVmZmVyKSB7XG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXlCdWZmZXIoYnVmZmVyLmJ5dGVMZW5ndGgpLFxuICAgICAgdmlldyA9IG5ldyBVaW50OEFycmF5KHJlc3VsdCk7XG5cbiAgdmlldy5zZXQobmV3IFVpbnQ4QXJyYXkoYnVmZmVyKSk7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYnVmZmVyQ2xvbmU7XG4iXX0= +},{}],100:[function(require,module,exports){ +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates an array that is the composition of partially applied arguments, + * placeholders, and provided arguments into a single array of arguments. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to prepend to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ +function composeArgs(args, partials, holders) { + var holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + leftIndex = -1, + leftLength = partials.length, + result = Array(leftLength + argsLength); + + while (++leftIndex < leftLength) { + result[leftIndex] = partials[leftIndex]; + } + while (++argsIndex < holdersLength) { + result[holders[argsIndex]] = args[argsIndex]; + } + while (argsLength--) { + result[leftIndex++] = args[argsIndex++]; + } + return result; +} + +module.exports = composeArgs; + +},{}],101:[function(require,module,exports){ +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * This function is like `composeArgs` except that the arguments composition + * is tailored for `_.partialRight`. + * + * @private + * @param {Array|Object} args The provided arguments. + * @param {Array} partials The arguments to append to those provided. + * @param {Array} holders The `partials` placeholder indexes. + * @returns {Array} Returns the new array of composed arguments. + */ +function composeArgsRight(args, partials, holders) { + var holdersIndex = -1, + holdersLength = holders.length, + argsIndex = -1, + argsLength = nativeMax(args.length - holdersLength, 0), + rightIndex = -1, + rightLength = partials.length, + result = Array(argsLength + rightLength); + + while (++argsIndex < argsLength) { + result[argsIndex] = args[argsIndex]; + } + var offset = argsIndex; + while (++rightIndex < rightLength) { + result[offset + rightIndex] = partials[rightIndex]; + } + while (++holdersIndex < holdersLength) { + result[offset + holders[holdersIndex]] = args[argsIndex++]; + } + return result; +} + +module.exports = composeArgsRight; + +},{}],102:[function(require,module,exports){ +var getLength = require('./getLength'), + isLength = require('./isLength'), + toObject = require('./toObject'); + +/** + * Creates a `baseEach` or `baseEachRight` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseEach(eachFunc, fromRight) { + return function(collection, iteratee) { + var length = collection ? getLength(collection) : 0; + if (!isLength(length)) { + return eachFunc(collection, iteratee); + } + var index = fromRight ? length : -1, + iterable = toObject(collection); + + while ((fromRight ? index-- : ++index < length)) { + if (iteratee(iterable[index], index, iterable) === false) { + break; + } + } + return collection; + }; +} + +module.exports = createBaseEach; + +},{"./getLength":116,"./isLength":129,"./toObject":139}],103:[function(require,module,exports){ +var toObject = require('./toObject'); + +/** + * Creates a base function for `_.forIn` or `_.forInRight`. + * + * @private + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new base function. + */ +function createBaseFor(fromRight) { + return function(object, iteratee, keysFunc) { + var iterable = toObject(object), + props = keysFunc(object), + length = props.length, + index = fromRight ? length : -1; + + while ((fromRight ? index-- : ++index < length)) { + var key = props[index]; + if (iteratee(iterable[key], key, iterable) === false) { + break; + } + } + return object; + }; +} + +module.exports = createBaseFor; + +},{"./toObject":139}],104:[function(require,module,exports){ +(function (global){ +var createCtorWrapper = require('./createCtorWrapper'); + +/** + * Creates a function that wraps `func` and invokes it with the `this` + * binding of `thisArg`. + * + * @private + * @param {Function} func The function to bind. + * @param {*} [thisArg] The `this` binding of `func`. + * @returns {Function} Returns the new bound function. + */ +function createBindWrapper(func, thisArg) { + var Ctor = createCtorWrapper(func); + + function wrapper() { + var fn = (this && this !== global && this instanceof wrapper) ? Ctor : func; + return fn.apply(thisArg, arguments); + } + return wrapper; +} + +module.exports = createBindWrapper; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2NyZWF0ZUJpbmRXcmFwcGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgY3JlYXRlQ3RvcldyYXBwZXIgPSByZXF1aXJlKCcuL2NyZWF0ZUN0b3JXcmFwcGVyJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggdGhlIGB0aGlzYFxuICogYmluZGluZyBvZiBgdGhpc0FyZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGJpbmQuXG4gKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJpbmRXcmFwcGVyKGZ1bmMsIHRoaXNBcmcpIHtcbiAgdmFyIEN0b3IgPSBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IGdsb2JhbCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpc0FyZywgYXJndW1lbnRzKTtcbiAgfVxuICByZXR1cm4gd3JhcHBlcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCaW5kV3JhcHBlcjtcbiJdfQ== +},{"./createCtorWrapper":105}],105:[function(require,module,exports){ +var baseCreate = require('./baseCreate'), + isObject = require('../lang/isObject'); + +/** + * Creates a function that produces an instance of `Ctor` regardless of + * whether it was invoked as part of a `new` expression or by `call` or `apply`. + * + * @private + * @param {Function} Ctor The constructor to wrap. + * @returns {Function} Returns the new wrapped function. + */ +function createCtorWrapper(Ctor) { + return function() { + // Use a `switch` statement to work with class constructors. + // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // for more details. + var args = arguments; + switch (args.length) { + case 0: return new Ctor; + case 1: return new Ctor(args[0]); + case 2: return new Ctor(args[0], args[1]); + case 3: return new Ctor(args[0], args[1], args[2]); + case 4: return new Ctor(args[0], args[1], args[2], args[3]); + case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); + case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); + case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + } + var thisBinding = baseCreate(Ctor.prototype), + result = Ctor.apply(thisBinding, args); + + // Mimic the constructor's `return` behavior. + // See https://es5.github.io/#x13.2.2 for more details. + return isObject(result) ? result : thisBinding; + }; +} + +module.exports = createCtorWrapper; + +},{"../lang/isObject":148,"./baseCreate":74}],106:[function(require,module,exports){ +var baseCallback = require('./baseCallback'), + baseFind = require('./baseFind'), + baseFindIndex = require('./baseFindIndex'), + isArray = require('../lang/isArray'); + +/** + * Creates a `_.find` or `_.findLast` function. + * + * @private + * @param {Function} eachFunc The function to iterate over a collection. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {Function} Returns the new find function. + */ +function createFind(eachFunc, fromRight) { + return function(collection, predicate, thisArg) { + predicate = baseCallback(predicate, thisArg, 3); + if (isArray(collection)) { + var index = baseFindIndex(collection, predicate, fromRight); + return index > -1 ? collection[index] : undefined; + } + return baseFind(collection, predicate, eachFunc); + }; +} + +module.exports = createFind; + +},{"../lang/isArray":144,"./baseCallback":71,"./baseFind":76,"./baseFindIndex":77}],107:[function(require,module,exports){ +var bindCallback = require('./bindCallback'), + isArray = require('../lang/isArray'); + +/** + * Creates a function for `_.forEach` or `_.forEachRight`. + * + * @private + * @param {Function} arrayFunc The function to iterate over an array. + * @param {Function} eachFunc The function to iterate over a collection. + * @returns {Function} Returns the new each function. + */ +function createForEach(arrayFunc, eachFunc) { + return function(collection, iteratee, thisArg) { + return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) + ? arrayFunc(collection, iteratee) + : eachFunc(collection, bindCallback(iteratee, thisArg, 3)); + }; +} + +module.exports = createForEach; + +},{"../lang/isArray":144,"./bindCallback":98}],108:[function(require,module,exports){ +(function (global){ +var arrayCopy = require('./arrayCopy'), + composeArgs = require('./composeArgs'), + composeArgsRight = require('./composeArgsRight'), + createCtorWrapper = require('./createCtorWrapper'), + isLaziable = require('./isLaziable'), + reorder = require('./reorder'), + replaceHolders = require('./replaceHolders'), + setData = require('./setData'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + CURRY_RIGHT_FLAG = 16, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64, + ARY_FLAG = 128; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates a function that wraps `func` and invokes it with optional `this` + * binding of, partial application, and currying. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to prepend to those provided to the new function. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [partialsRight] The arguments to append to those provided to the new function. + * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { + var isAry = bitmask & ARY_FLAG, + isBind = bitmask & BIND_FLAG, + isBindKey = bitmask & BIND_KEY_FLAG, + isCurry = bitmask & CURRY_FLAG, + isCurryBound = bitmask & CURRY_BOUND_FLAG, + isCurryRight = bitmask & CURRY_RIGHT_FLAG, + Ctor = isBindKey ? undefined : createCtorWrapper(func); + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it to other functions. + var length = arguments.length, + index = length, + args = Array(length); + + while (index--) { + args[index] = arguments[index]; + } + if (partials) { + args = composeArgs(args, partials, holders); + } + if (partialsRight) { + args = composeArgsRight(args, partialsRight, holdersRight); + } + if (isCurry || isCurryRight) { + var placeholder = wrapper.placeholder, + argsHolders = replaceHolders(args, placeholder); + + length -= argsHolders.length; + if (length < arity) { + var newArgPos = argPos ? arrayCopy(argPos) : undefined, + newArity = nativeMax(arity - length, 0), + newsHolders = isCurry ? argsHolders : undefined, + newHoldersRight = isCurry ? undefined : argsHolders, + newPartials = isCurry ? args : undefined, + newPartialsRight = isCurry ? undefined : args; + + bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG); + bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG); + + if (!isCurryBound) { + bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG); + } + var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity], + result = createHybridWrapper.apply(undefined, newData); + + if (isLaziable(func)) { + setData(result, newData); + } + result.placeholder = placeholder; + return result; + } + } + var thisBinding = isBind ? thisArg : this, + fn = isBindKey ? thisBinding[func] : func; + + if (argPos) { + args = reorder(args, argPos); + } + if (isAry && ary < args.length) { + args.length = ary; + } + if (this && this !== global && this instanceof wrapper) { + fn = Ctor || createCtorWrapper(func); + } + return fn.apply(thisBinding, args); + } + return wrapper; +} + +module.exports = createHybridWrapper; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2NyZWF0ZUh5YnJpZFdyYXBwZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgYXJyYXlDb3B5ID0gcmVxdWlyZSgnLi9hcnJheUNvcHknKSxcbiAgICBjb21wb3NlQXJncyA9IHJlcXVpcmUoJy4vY29tcG9zZUFyZ3MnKSxcbiAgICBjb21wb3NlQXJnc1JpZ2h0ID0gcmVxdWlyZSgnLi9jb21wb3NlQXJnc1JpZ2h0JyksXG4gICAgY3JlYXRlQ3RvcldyYXBwZXIgPSByZXF1aXJlKCcuL2NyZWF0ZUN0b3JXcmFwcGVyJyksXG4gICAgaXNMYXppYWJsZSA9IHJlcXVpcmUoJy4vaXNMYXppYWJsZScpLFxuICAgIHJlb3JkZXIgPSByZXF1aXJlKCcuL3Jlb3JkZXInKSxcbiAgICByZXBsYWNlSG9sZGVycyA9IHJlcXVpcmUoJy4vcmVwbGFjZUhvbGRlcnMnKSxcbiAgICBzZXREYXRhID0gcmVxdWlyZSgnLi9zZXREYXRhJyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHdyYXBwZXIgbWV0YWRhdGEuICovXG52YXIgQklORF9GTEFHID0gMSxcbiAgICBCSU5EX0tFWV9GTEFHID0gMixcbiAgICBDVVJSWV9CT1VORF9GTEFHID0gNCxcbiAgICBDVVJSWV9GTEFHID0gOCxcbiAgICBDVVJSWV9SSUdIVF9GTEFHID0gMTYsXG4gICAgUEFSVElBTF9GTEFHID0gMzIsXG4gICAgUEFSVElBTF9SSUdIVF9GTEFHID0gNjQsXG4gICAgQVJZX0ZMQUcgPSAxMjg7XG5cbi8qIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXg7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggb3B0aW9uYWwgYHRoaXNgXG4gKiBiaW5kaW5nIG9mLCBwYXJ0aWFsIGFwcGxpY2F0aW9uLCBhbmQgY3VycnlpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb258c3RyaW5nfSBmdW5jIFRoZSBmdW5jdGlvbiBvciBtZXRob2QgbmFtZSB0byByZWZlcmVuY2UuXG4gKiBAcGFyYW0ge251bWJlcn0gYml0bWFzayBUaGUgYml0bWFzayBvZiBmbGFncy4gU2VlIGBjcmVhdGVXcmFwcGVyYCBmb3IgbW9yZSBkZXRhaWxzLlxuICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc10gVGhlIGFyZ3VtZW50cyB0byBwcmVwZW5kIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBuZXcgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge0FycmF5fSBbaG9sZGVyc10gVGhlIGBwYXJ0aWFsc2AgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAqIEBwYXJhbSB7QXJyYXl9IFtwYXJ0aWFsc1JpZ2h0XSBUaGUgYXJndW1lbnRzIHRvIGFwcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICogQHBhcmFtIHtBcnJheX0gW2hvbGRlcnNSaWdodF0gVGhlIGBwYXJ0aWFsc1JpZ2h0YCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICogQHBhcmFtIHtBcnJheX0gW2FyZ1Bvc10gVGhlIGFyZ3VtZW50IHBvc2l0aW9ucyBvZiB0aGUgbmV3IGZ1bmN0aW9uLlxuICogQHBhcmFtIHtudW1iZXJ9IFthcnldIFRoZSBhcml0eSBjYXAgb2YgYGZ1bmNgLlxuICogQHBhcmFtIHtudW1iZXJ9IFthcml0eV0gVGhlIGFyaXR5IG9mIGBmdW5jYC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IHdyYXBwZWQgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUh5YnJpZFdyYXBwZXIoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMsIGhvbGRlcnMsIHBhcnRpYWxzUmlnaHQsIGhvbGRlcnNSaWdodCwgYXJnUG9zLCBhcnksIGFyaXR5KSB7XG4gIHZhciBpc0FyeSA9IGJpdG1hc2sgJiBBUllfRkxBRyxcbiAgICAgIGlzQmluZCA9IGJpdG1hc2sgJiBCSU5EX0ZMQUcsXG4gICAgICBpc0JpbmRLZXkgPSBiaXRtYXNrICYgQklORF9LRVlfRkxBRyxcbiAgICAgIGlzQ3VycnkgPSBiaXRtYXNrICYgQ1VSUllfRkxBRyxcbiAgICAgIGlzQ3VycnlCb3VuZCA9IGJpdG1hc2sgJiBDVVJSWV9CT1VORF9GTEFHLFxuICAgICAgaXNDdXJyeVJpZ2h0ID0gYml0bWFzayAmIENVUlJZX1JJR0hUX0ZMQUcsXG4gICAgICBDdG9yID0gaXNCaW5kS2V5ID8gdW5kZWZpbmVkIDogY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG5cbiAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAvLyBBdm9pZCBgYXJndW1lbnRzYCBvYmplY3QgdXNlIGRpc3F1YWxpZnlpbmcgb3B0aW1pemF0aW9ucyBieVxuICAgIC8vIGNvbnZlcnRpbmcgaXQgdG8gYW4gYXJyYXkgYmVmb3JlIHByb3ZpZGluZyBpdCB0byBvdGhlciBmdW5jdGlvbnMuXG4gICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgIGluZGV4ID0gbGVuZ3RoLFxuICAgICAgICBhcmdzID0gQXJyYXkobGVuZ3RoKTtcblxuICAgIHdoaWxlIChpbmRleC0tKSB7XG4gICAgICBhcmdzW2luZGV4XSA9IGFyZ3VtZW50c1tpbmRleF07XG4gICAgfVxuICAgIGlmIChwYXJ0aWFscykge1xuICAgICAgYXJncyA9IGNvbXBvc2VBcmdzKGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzKTtcbiAgICB9XG4gICAgaWYgKHBhcnRpYWxzUmlnaHQpIHtcbiAgICAgIGFyZ3MgPSBjb21wb3NlQXJnc1JpZ2h0KGFyZ3MsIHBhcnRpYWxzUmlnaHQsIGhvbGRlcnNSaWdodCk7XG4gICAgfVxuICAgIGlmIChpc0N1cnJ5IHx8IGlzQ3VycnlSaWdodCkge1xuICAgICAgdmFyIHBsYWNlaG9sZGVyID0gd3JhcHBlci5wbGFjZWhvbGRlcixcbiAgICAgICAgICBhcmdzSG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKGFyZ3MsIHBsYWNlaG9sZGVyKTtcblxuICAgICAgbGVuZ3RoIC09IGFyZ3NIb2xkZXJzLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggPCBhcml0eSkge1xuICAgICAgICB2YXIgbmV3QXJnUG9zID0gYXJnUG9zID8gYXJyYXlDb3B5KGFyZ1BvcykgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBuZXdBcml0eSA9IG5hdGl2ZU1heChhcml0eSAtIGxlbmd0aCwgMCksXG4gICAgICAgICAgICBuZXdzSG9sZGVycyA9IGlzQ3VycnkgPyBhcmdzSG9sZGVycyA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIG5ld0hvbGRlcnNSaWdodCA9IGlzQ3VycnkgPyB1bmRlZmluZWQgOiBhcmdzSG9sZGVycyxcbiAgICAgICAgICAgIG5ld1BhcnRpYWxzID0gaXNDdXJyeSA/IGFyZ3MgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBuZXdQYXJ0aWFsc1JpZ2h0ID0gaXNDdXJyeSA/IHVuZGVmaW5lZCA6IGFyZ3M7XG5cbiAgICAgICAgYml0bWFzayB8PSAoaXNDdXJyeSA/IFBBUlRJQUxfRkxBRyA6IFBBUlRJQUxfUklHSFRfRkxBRyk7XG4gICAgICAgIGJpdG1hc2sgJj0gfihpc0N1cnJ5ID8gUEFSVElBTF9SSUdIVF9GTEFHIDogUEFSVElBTF9GTEFHKTtcblxuICAgICAgICBpZiAoIWlzQ3VycnlCb3VuZCkge1xuICAgICAgICAgIGJpdG1hc2sgJj0gfihCSU5EX0ZMQUcgfCBCSU5EX0tFWV9GTEFHKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmV3RGF0YSA9IFtmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBuZXdQYXJ0aWFscywgbmV3c0hvbGRlcnMsIG5ld1BhcnRpYWxzUmlnaHQsIG5ld0hvbGRlcnNSaWdodCwgbmV3QXJnUG9zLCBhcnksIG5ld0FyaXR5XSxcbiAgICAgICAgICAgIHJlc3VsdCA9IGNyZWF0ZUh5YnJpZFdyYXBwZXIuYXBwbHkodW5kZWZpbmVkLCBuZXdEYXRhKTtcblxuICAgICAgICBpZiAoaXNMYXppYWJsZShmdW5jKSkge1xuICAgICAgICAgIHNldERhdGEocmVzdWx0LCBuZXdEYXRhKTtcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQucGxhY2Vob2xkZXIgPSBwbGFjZWhvbGRlcjtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cbiAgICB9XG4gICAgdmFyIHRoaXNCaW5kaW5nID0gaXNCaW5kID8gdGhpc0FyZyA6IHRoaXMsXG4gICAgICAgIGZuID0gaXNCaW5kS2V5ID8gdGhpc0JpbmRpbmdbZnVuY10gOiBmdW5jO1xuXG4gICAgaWYgKGFyZ1Bvcykge1xuICAgICAgYXJncyA9IHJlb3JkZXIoYXJncywgYXJnUG9zKTtcbiAgICB9XG4gICAgaWYgKGlzQXJ5ICYmIGFyeSA8IGFyZ3MubGVuZ3RoKSB7XG4gICAgICBhcmdzLmxlbmd0aCA9IGFyeTtcbiAgICB9XG4gICAgaWYgKHRoaXMgJiYgdGhpcyAhPT0gZ2xvYmFsICYmIHRoaXMgaW5zdGFuY2VvZiB3cmFwcGVyKSB7XG4gICAgICBmbiA9IEN0b3IgfHwgY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG4gICAgfVxuICAgIHJldHVybiBmbi5hcHBseSh0aGlzQmluZGluZywgYXJncyk7XG4gIH1cbiAgcmV0dXJuIHdyYXBwZXI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlSHlicmlkV3JhcHBlcjtcbiJdfQ== +},{"./arrayCopy":66,"./composeArgs":100,"./composeArgsRight":101,"./createCtorWrapper":105,"./isLaziable":128,"./reorder":135,"./replaceHolders":136,"./setData":137}],109:[function(require,module,exports){ +(function (global){ +var createCtorWrapper = require('./createCtorWrapper'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1; + +/** + * Creates a function that wraps `func` and invokes it with the optional `this` + * binding of `thisArg` and the `partials` prepended to those provided to + * the wrapper. + * + * @private + * @param {Function} func The function to partially apply arguments to. + * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details. + * @param {*} thisArg The `this` binding of `func`. + * @param {Array} partials The arguments to prepend to those provided to the new function. + * @returns {Function} Returns the new bound function. + */ +function createPartialWrapper(func, bitmask, thisArg, partials) { + var isBind = bitmask & BIND_FLAG, + Ctor = createCtorWrapper(func); + + function wrapper() { + // Avoid `arguments` object use disqualifying optimizations by + // converting it to an array before providing it `func`. + var argsIndex = -1, + argsLength = arguments.length, + leftIndex = -1, + leftLength = partials.length, + args = Array(leftLength + argsLength); + + while (++leftIndex < leftLength) { + args[leftIndex] = partials[leftIndex]; + } + while (argsLength--) { + args[leftIndex++] = arguments[++argsIndex]; + } + var fn = (this && this !== global && this instanceof wrapper) ? Ctor : func; + return fn.apply(isBind ? thisArg : this, args); + } + return wrapper; +} + +module.exports = createPartialWrapper; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2NyZWF0ZVBhcnRpYWxXcmFwcGVyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgY3JlYXRlQ3RvcldyYXBwZXIgPSByZXF1aXJlKCcuL2NyZWF0ZUN0b3JXcmFwcGVyJyk7XG5cbi8qKiBVc2VkIHRvIGNvbXBvc2UgYml0bWFza3MgZm9yIHdyYXBwZXIgbWV0YWRhdGEuICovXG52YXIgQklORF9GTEFHID0gMTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCB3cmFwcyBgZnVuY2AgYW5kIGludm9rZXMgaXQgd2l0aCB0aGUgb3B0aW9uYWwgYHRoaXNgXG4gKiBiaW5kaW5nIG9mIGB0aGlzQXJnYCBhbmQgdGhlIGBwYXJ0aWFsc2AgcHJlcGVuZGVkIHRvIHRob3NlIHByb3ZpZGVkIHRvXG4gKiB0aGUgd3JhcHBlci5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcGFydGlhbGx5IGFwcGx5IGFyZ3VtZW50cyB0by5cbiAqIEBwYXJhbSB7bnVtYmVyfSBiaXRtYXNrIFRoZSBiaXRtYXNrIG9mIGZsYWdzLiBTZWUgYGNyZWF0ZVdyYXBwZXJgIGZvciBtb3JlIGRldGFpbHMuXG4gKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBhcnRpYWxXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzKSB7XG4gIHZhciBpc0JpbmQgPSBiaXRtYXNrICYgQklORF9GTEFHLFxuICAgICAgQ3RvciA9IGNyZWF0ZUN0b3JXcmFwcGVyKGZ1bmMpO1xuXG4gIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgLy8gQXZvaWQgYGFyZ3VtZW50c2Agb2JqZWN0IHVzZSBkaXNxdWFsaWZ5aW5nIG9wdGltaXphdGlvbnMgYnlcbiAgICAvLyBjb252ZXJ0aW5nIGl0IHRvIGFuIGFycmF5IGJlZm9yZSBwcm92aWRpbmcgaXQgYGZ1bmNgLlxuICAgIHZhciBhcmdzSW5kZXggPSAtMSxcbiAgICAgICAgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG4gICAgICAgIGxlZnRJbmRleCA9IC0xLFxuICAgICAgICBsZWZ0TGVuZ3RoID0gcGFydGlhbHMubGVuZ3RoLFxuICAgICAgICBhcmdzID0gQXJyYXkobGVmdExlbmd0aCArIGFyZ3NMZW5ndGgpO1xuXG4gICAgd2hpbGUgKCsrbGVmdEluZGV4IDwgbGVmdExlbmd0aCkge1xuICAgICAgYXJnc1tsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgICB9XG4gICAgd2hpbGUgKGFyZ3NMZW5ndGgtLSkge1xuICAgICAgYXJnc1tsZWZ0SW5kZXgrK10gPSBhcmd1bWVudHNbKythcmdzSW5kZXhdO1xuICAgIH1cbiAgICB2YXIgZm4gPSAodGhpcyAmJiB0aGlzICE9PSBnbG9iYWwgJiYgdGhpcyBpbnN0YW5jZW9mIHdyYXBwZXIpID8gQ3RvciA6IGZ1bmM7XG4gICAgcmV0dXJuIGZuLmFwcGx5KGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLCBhcmdzKTtcbiAgfVxuICByZXR1cm4gd3JhcHBlcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQYXJ0aWFsV3JhcHBlcjtcbiJdfQ== +},{"./createCtorWrapper":105}],110:[function(require,module,exports){ +var baseSetData = require('./baseSetData'), + createBindWrapper = require('./createBindWrapper'), + createHybridWrapper = require('./createHybridWrapper'), + createPartialWrapper = require('./createPartialWrapper'), + getData = require('./getData'), + mergeData = require('./mergeData'), + setData = require('./setData'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1, + BIND_KEY_FLAG = 2, + PARTIAL_FLAG = 32, + PARTIAL_RIGHT_FLAG = 64; + +/** Used as the `TypeError` message for "Functions" methods. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max; + +/** + * Creates a function that either curries or invokes `func` with optional + * `this` binding and partially applied arguments. + * + * @private + * @param {Function|string} func The function or method name to reference. + * @param {number} bitmask The bitmask of flags. + * The bitmask may be composed of the following flags: + * 1 - `_.bind` + * 2 - `_.bindKey` + * 4 - `_.curry` or `_.curryRight` of a bound function + * 8 - `_.curry` + * 16 - `_.curryRight` + * 32 - `_.partial` + * 64 - `_.partialRight` + * 128 - `_.rearg` + * 256 - `_.ary` + * @param {*} [thisArg] The `this` binding of `func`. + * @param {Array} [partials] The arguments to be partially applied. + * @param {Array} [holders] The `partials` placeholder indexes. + * @param {Array} [argPos] The argument positions of the new function. + * @param {number} [ary] The arity cap of `func`. + * @param {number} [arity] The arity of `func`. + * @returns {Function} Returns the new wrapped function. + */ +function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { + var isBindKey = bitmask & BIND_KEY_FLAG; + if (!isBindKey && typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + var length = partials ? partials.length : 0; + if (!length) { + bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG); + partials = holders = undefined; + } + length -= (holders ? holders.length : 0); + if (bitmask & PARTIAL_RIGHT_FLAG) { + var partialsRight = partials, + holdersRight = holders; + + partials = holders = undefined; + } + var data = isBindKey ? undefined : getData(func), + newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity]; + + if (data) { + mergeData(newData, data); + bitmask = newData[1]; + arity = newData[9]; + } + newData[9] = arity == null + ? (isBindKey ? 0 : func.length) + : (nativeMax(arity - length, 0) || 0); + + if (bitmask == BIND_FLAG) { + var result = createBindWrapper(newData[0], newData[2]); + } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) { + result = createPartialWrapper.apply(undefined, newData); + } else { + result = createHybridWrapper.apply(undefined, newData); + } + var setter = data ? baseSetData : setData; + return setter(result, newData); +} + +module.exports = createWrapper; + +},{"./baseSetData":92,"./createBindWrapper":104,"./createHybridWrapper":108,"./createPartialWrapper":109,"./getData":114,"./mergeData":132,"./setData":137}],111:[function(require,module,exports){ +var arraySome = require('./arraySome'); + +/** + * A specialized version of `baseIsEqualDeep` for arrays with support for + * partial deep comparisons. + * + * @private + * @param {Array} array The array to compare. + * @param {Array} other The other array to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing arrays. + * @param {boolean} [isLoose] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. + */ +function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) { + var index = -1, + arrLength = array.length, + othLength = other.length; + + if (arrLength != othLength && !(isLoose && othLength > arrLength)) { + return false; + } + // Ignore non-index properties. + while (++index < arrLength) { + var arrValue = array[index], + othValue = other[index], + result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined; + + if (result !== undefined) { + if (result) { + continue; + } + return false; + } + // Recursively compare arrays (susceptible to call stack limits). + if (isLoose) { + if (!arraySome(other, function(othValue) { + return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB); + })) { + return false; + } + } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) { + return false; + } + } + return true; +} + +module.exports = equalArrays; + +},{"./arraySome":69}],112:[function(require,module,exports){ +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + +/** + * A specialized version of `baseIsEqualDeep` for comparing objects of + * the same `toStringTag`. + * + * **Note:** This function only supports comparing values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {string} tag The `toStringTag` of the objects to compare. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalByTag(object, other, tag) { + switch (tag) { + case boolTag: + case dateTag: + // Coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0` treating invalid dates coerced to `NaN` as not equal. + return +object == +other; + + case errorTag: + return object.name == other.name && object.message == other.message; + + case numberTag: + // Treat `NaN` vs. `NaN` as equal. + return (object != +object) + ? other != +other + : object == +other; + + case regexpTag: + case stringTag: + // Coerce regexes to strings and treat strings primitives and string + // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details. + return object == (other + ''); + } + return false; +} + +module.exports = equalByTag; + +},{}],113:[function(require,module,exports){ +var keys = require('../object/keys'); + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A specialized version of `baseIsEqualDeep` for objects with support for + * partial deep comparisons. + * + * @private + * @param {Object} object The object to compare. + * @param {Object} other The other object to compare. + * @param {Function} equalFunc The function to determine equivalents of values. + * @param {Function} [customizer] The function to customize comparing values. + * @param {boolean} [isLoose] Specify performing partial comparisons. + * @param {Array} [stackA] Tracks traversed `value` objects. + * @param {Array} [stackB] Tracks traversed `other` objects. + * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. + */ +function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) { + var objProps = keys(object), + objLength = objProps.length, + othProps = keys(other), + othLength = othProps.length; + + if (objLength != othLength && !isLoose) { + return false; + } + var index = objLength; + while (index--) { + var key = objProps[index]; + if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) { + return false; + } + } + var skipCtor = isLoose; + while (++index < objLength) { + key = objProps[index]; + var objValue = object[key], + othValue = other[key], + result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined; + + // Recursively compare objects (susceptible to call stack limits). + if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) { + return false; + } + skipCtor || (skipCtor = key == 'constructor'); + } + if (!skipCtor) { + var objCtor = object.constructor, + othCtor = other.constructor; + + // Non `Object` object instances with different constructors are not equal. + if (objCtor != othCtor && + ('constructor' in object && 'constructor' in other) && + !(typeof objCtor == 'function' && objCtor instanceof objCtor && + typeof othCtor == 'function' && othCtor instanceof othCtor)) { + return false; + } + } + return true; +} + +module.exports = equalObjects; + +},{"../object/keys":153}],114:[function(require,module,exports){ +var metaMap = require('./metaMap'), + noop = require('../utility/noop'); + +/** + * Gets metadata for `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {*} Returns the metadata for `func`. + */ +var getData = !metaMap ? noop : function(func) { + return metaMap.get(func); +}; + +module.exports = getData; + +},{"../utility/noop":159,"./metaMap":133}],115:[function(require,module,exports){ +var realNames = require('./realNames'); + +/** + * Gets the name of `func`. + * + * @private + * @param {Function} func The function to query. + * @returns {string} Returns the function name. + */ +function getFuncName(func) { + var result = (func.name + ''), + array = realNames[result], + length = array ? array.length : 0; + + while (length--) { + var data = array[length], + otherFunc = data.func; + if (otherFunc == null || otherFunc == func) { + return data.name; + } + } + return result; +} + +module.exports = getFuncName; + +},{"./realNames":134}],116:[function(require,module,exports){ +var baseProperty = require('./baseProperty'); + +/** + * Gets the "length" property value of `object`. + * + * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) + * that affects Safari on at least iOS 8.1-8.3 ARM64. + * + * @private + * @param {Object} object The object to query. + * @returns {*} Returns the "length" value. + */ +var getLength = baseProperty('length'); + +module.exports = getLength; + +},{"./baseProperty":90}],117:[function(require,module,exports){ +var isStrictComparable = require('./isStrictComparable'), + pairs = require('../object/pairs'); + +/** + * Gets the propery names, values, and compare flags of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the match data of `object`. + */ +function getMatchData(object) { + var result = pairs(object), + length = result.length; + + while (length--) { + result[length][2] = isStrictComparable(result[length][1]); + } + return result; +} + +module.exports = getMatchData; + +},{"../object/pairs":155,"./isStrictComparable":131}],118:[function(require,module,exports){ +var isNative = require('../lang/isNative'); + +/** + * Gets the native function at `key` of `object`. + * + * @private + * @param {Object} object The object to query. + * @param {string} key The key of the method to get. + * @returns {*} Returns the function if it's native, else `undefined`. + */ +function getNative(object, key) { + var value = object == null ? undefined : object[key]; + return isNative(value) ? value : undefined; +} + +module.exports = getNative; + +},{"../lang/isNative":147}],119:[function(require,module,exports){ +/** + * Gets the index at which the first occurrence of `NaN` is found in `array`. + * + * @private + * @param {Array} array The array to search. + * @param {number} fromIndex The index to search from. + * @param {boolean} [fromRight] Specify iterating from right to left. + * @returns {number} Returns the index of the matched `NaN`, else `-1`. + */ +function indexOfNaN(array, fromIndex, fromRight) { + var length = array.length, + index = fromIndex + (fromRight ? 0 : -1); + + while ((fromRight ? index-- : ++index < length)) { + var other = array[index]; + if (other !== other) { + return index; + } + } + return -1; +} + +module.exports = indexOfNaN; + +},{}],120:[function(require,module,exports){ +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Initializes an array clone. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the initialized clone. + */ +function initCloneArray(array) { + var length = array.length, + result = new array.constructor(length); + + // Add array properties assigned by `RegExp#exec`. + if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { + result.index = array.index; + result.input = array.input; + } + return result; +} + +module.exports = initCloneArray; + +},{}],121:[function(require,module,exports){ +(function (global){ +var bufferClone = require('./bufferClone'); + +/** `Object#toString` result references. */ +var boolTag = '[object Boolean]', + dateTag = '[object Date]', + numberTag = '[object Number]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + +var arrayBufferTag = '[object ArrayBuffer]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to match `RegExp` flags from their coerced string values. */ +var reFlags = /\w*$/; + +/** Native method references. */ +var Uint8Array = global.Uint8Array; + +/** Used to lookup a type array constructors by `toStringTag`. */ +var ctorByTag = {}; +ctorByTag[float32Tag] = global.Float32Array; +ctorByTag[float64Tag] = global.Float64Array; +ctorByTag[int8Tag] = global.Int8Array; +ctorByTag[int16Tag] = global.Int16Array; +ctorByTag[int32Tag] = global.Int32Array; +ctorByTag[uint8Tag] = Uint8Array; +ctorByTag[uint8ClampedTag] = global.Uint8ClampedArray; +ctorByTag[uint16Tag] = global.Uint16Array; +ctorByTag[uint32Tag] = global.Uint32Array; + +/** + * Initializes an object clone based on its `toStringTag`. + * + * **Note:** This function only supports cloning values with tags of + * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. + * + * @private + * @param {Object} object The object to clone. + * @param {string} tag The `toStringTag` of the object to clone. + * @param {boolean} [isDeep] Specify a deep clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneByTag(object, tag, isDeep) { + var Ctor = object.constructor; + switch (tag) { + case arrayBufferTag: + return bufferClone(object); + + case boolTag: + case dateTag: + return new Ctor(+object); + + case float32Tag: case float64Tag: + case int8Tag: case int16Tag: case int32Tag: + case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: + // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays. + if (Ctor instanceof Ctor) { + Ctor = ctorByTag[tag]; + } + var buffer = object.buffer; + return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length); + + case numberTag: + case stringTag: + return new Ctor(object); + + case regexpTag: + var result = new Ctor(object.source, reFlags.exec(object)); + result.lastIndex = object.lastIndex; + } + return result; +} + +module.exports = initCloneByTag; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2luaXRDbG9uZUJ5VGFnLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgYnVmZmVyQ2xvbmUgPSByZXF1aXJlKCcuL2J1ZmZlckNsb25lJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgc3RyaW5nVGFnID0gJ1tvYmplY3QgU3RyaW5nXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgIGZsb2F0NjRUYWcgPSAnW29iamVjdCBGbG9hdDY0QXJyYXldJyxcbiAgICBpbnQ4VGFnID0gJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgaW50MzJUYWcgPSAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgdWludDhUYWcgPSAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICB1aW50MTZUYWcgPSAnW29iamVjdCBVaW50MTZBcnJheV0nLFxuICAgIHVpbnQzMlRhZyA9ICdbb2JqZWN0IFVpbnQzMkFycmF5XSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgIGZsYWdzIGZyb20gdGhlaXIgY29lcmNlZCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlRmxhZ3MgPSAvXFx3KiQvO1xuXG4vKiogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWwuVWludDhBcnJheTtcblxuLyoqIFVzZWQgdG8gbG9va3VwIGEgdHlwZSBhcnJheSBjb25zdHJ1Y3RvcnMgYnkgYHRvU3RyaW5nVGFnYC4gKi9cbnZhciBjdG9yQnlUYWcgPSB7fTtcbmN0b3JCeVRhZ1tmbG9hdDMyVGFnXSA9IGdsb2JhbC5GbG9hdDMyQXJyYXk7XG5jdG9yQnlUYWdbZmxvYXQ2NFRhZ10gPSBnbG9iYWwuRmxvYXQ2NEFycmF5O1xuY3RvckJ5VGFnW2ludDhUYWddID0gZ2xvYmFsLkludDhBcnJheTtcbmN0b3JCeVRhZ1tpbnQxNlRhZ10gPSBnbG9iYWwuSW50MTZBcnJheTtcbmN0b3JCeVRhZ1tpbnQzMlRhZ10gPSBnbG9iYWwuSW50MzJBcnJheTtcbmN0b3JCeVRhZ1t1aW50OFRhZ10gPSBVaW50OEFycmF5O1xuY3RvckJ5VGFnW3VpbnQ4Q2xhbXBlZFRhZ10gPSBnbG9iYWwuVWludDhDbGFtcGVkQXJyYXk7XG5jdG9yQnlUYWdbdWludDE2VGFnXSA9IGdsb2JhbC5VaW50MTZBcnJheTtcbmN0b3JCeVRhZ1t1aW50MzJUYWddID0gZ2xvYmFsLlVpbnQzMkFycmF5O1xuXG4vKipcbiAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAqXG4gKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNsb25pbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdCB0byBjbG9uZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAqL1xuZnVuY3Rpb24gaW5pdENsb25lQnlUYWcob2JqZWN0LCB0YWcsIGlzRGVlcCkge1xuICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgc3dpdGNoICh0YWcpIHtcbiAgICBjYXNlIGFycmF5QnVmZmVyVGFnOlxuICAgICAgcmV0dXJuIGJ1ZmZlckNsb25lKG9iamVjdCk7XG5cbiAgICBjYXNlIGJvb2xUYWc6XG4gICAgY2FzZSBkYXRlVGFnOlxuICAgICAgcmV0dXJuIG5ldyBDdG9yKCtvYmplY3QpO1xuXG4gICAgY2FzZSBmbG9hdDMyVGFnOiBjYXNlIGZsb2F0NjRUYWc6XG4gICAgY2FzZSBpbnQ4VGFnOiBjYXNlIGludDE2VGFnOiBjYXNlIGludDMyVGFnOlxuICAgIGNhc2UgdWludDhUYWc6IGNhc2UgdWludDhDbGFtcGVkVGFnOiBjYXNlIHVpbnQxNlRhZzogY2FzZSB1aW50MzJUYWc6XG4gICAgICAvLyBTYWZhcmkgNSBtb2JpbGUgaW5jb3JyZWN0bHkgaGFzIGBPYmplY3RgIGFzIHRoZSBjb25zdHJ1Y3RvciBvZiB0eXBlZCBhcnJheXMuXG4gICAgICBpZiAoQ3RvciBpbnN0YW5jZW9mIEN0b3IpIHtcbiAgICAgICAgQ3RvciA9IGN0b3JCeVRhZ1t0YWddO1xuICAgICAgfVxuICAgICAgdmFyIGJ1ZmZlciA9IG9iamVjdC5idWZmZXI7XG4gICAgICByZXR1cm4gbmV3IEN0b3IoaXNEZWVwID8gYnVmZmVyQ2xvbmUoYnVmZmVyKSA6IGJ1ZmZlciwgb2JqZWN0LmJ5dGVPZmZzZXQsIG9iamVjdC5sZW5ndGgpO1xuXG4gICAgY2FzZSBudW1iZXJUYWc6XG4gICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICByZXR1cm4gbmV3IEN0b3Iob2JqZWN0KTtcblxuICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBDdG9yKG9iamVjdC5zb3VyY2UsIHJlRmxhZ3MuZXhlYyhvYmplY3QpKTtcbiAgICAgIHJlc3VsdC5sYXN0SW5kZXggPSBvYmplY3QubGFzdEluZGV4O1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lQnlUYWc7XG4iXX0= +},{"./bufferClone":99}],122:[function(require,module,exports){ +/** + * Initializes an object clone. + * + * @private + * @param {Object} object The object to clone. + * @returns {Object} Returns the initialized clone. + */ +function initCloneObject(object) { + var Ctor = object.constructor; + if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) { + Ctor = Object; + } + return new Ctor; +} + +module.exports = initCloneObject; + +},{}],123:[function(require,module,exports){ +var getLength = require('./getLength'), + isLength = require('./isLength'); + +/** + * Checks if `value` is array-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is array-like, else `false`. + */ +function isArrayLike(value) { + return value != null && isLength(getLength(value)); +} + +module.exports = isArrayLike; + +},{"./getLength":116,"./isLength":129}],124:[function(require,module,exports){ +/** + * Checks if `value` is a host object in IE < 9. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a host object, else `false`. + */ +var isHostObject = (function() { + try { + Object({ 'toString': 0 } + ''); + } catch(e) { + return function() { return false; }; + } + return function(value) { + // IE < 9 presents many host objects as `Object` objects that can coerce + // to strings despite having improperly defined `toString` methods. + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + }; +}()); + +module.exports = isHostObject; + +},{}],125:[function(require,module,exports){ +/** Used to detect unsigned integer values. */ +var reIsUint = /^\d+$/; + +/** + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like index. + * + * @private + * @param {*} value The value to check. + * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. + * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. + */ +function isIndex(value, length) { + value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1; + length = length == null ? MAX_SAFE_INTEGER : length; + return value > -1 && value % 1 == 0 && value < length; +} + +module.exports = isIndex; + +},{}],126:[function(require,module,exports){ +var isArrayLike = require('./isArrayLike'), + isIndex = require('./isIndex'), + isObject = require('../lang/isObject'); + +/** + * Checks if the provided arguments are from an iteratee call. + * + * @private + * @param {*} value The potential iteratee value argument. + * @param {*} index The potential iteratee index or key argument. + * @param {*} object The potential iteratee object argument. + * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`. + */ +function isIterateeCall(value, index, object) { + if (!isObject(object)) { + return false; + } + var type = typeof index; + if (type == 'number' + ? (isArrayLike(object) && isIndex(index, object.length)) + : (type == 'string' && index in object)) { + var other = object[index]; + return value === value ? (value === other) : (other !== other); + } + return false; +} + +module.exports = isIterateeCall; + +},{"../lang/isObject":148,"./isArrayLike":123,"./isIndex":125}],127:[function(require,module,exports){ +var isArray = require('../lang/isArray'), + toObject = require('./toObject'); + +/** Used to match property names within property paths. */ +var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/, + reIsPlainProp = /^\w*$/; + +/** + * Checks if `value` is a property name and not a property path. + * + * @private + * @param {*} value The value to check. + * @param {Object} [object] The object to query keys on. + * @returns {boolean} Returns `true` if `value` is a property name, else `false`. + */ +function isKey(value, object) { + var type = typeof value; + if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') { + return true; + } + if (isArray(value)) { + return false; + } + var result = !reIsDeepProp.test(value); + return result || (object != null && value in toObject(object)); +} + +module.exports = isKey; + +},{"../lang/isArray":144,"./toObject":139}],128:[function(require,module,exports){ +var LazyWrapper = require('./LazyWrapper'), + getData = require('./getData'), + getFuncName = require('./getFuncName'), + lodash = require('../chain/lodash'); + +/** + * Checks if `func` has a lazy counterpart. + * + * @private + * @param {Function} func The function to check. + * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`. + */ +function isLaziable(func) { + var funcName = getFuncName(func), + other = lodash[funcName]; + + if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { + return false; + } + if (func === other) { + return true; + } + var data = getData(other); + return !!data && func === data[0]; +} + +module.exports = isLaziable; + +},{"../chain/lodash":55,"./LazyWrapper":64,"./getData":114,"./getFuncName":115}],129:[function(require,module,exports){ +/** + * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer) + * of an array-like value. + */ +var MAX_SAFE_INTEGER = 9007199254740991; + +/** + * Checks if `value` is a valid array-like length. + * + * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. + */ +function isLength(value) { + return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; +} + +module.exports = isLength; + +},{}],130:[function(require,module,exports){ +/** + * Checks if `value` is object-like. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + */ +function isObjectLike(value) { + return !!value && typeof value == 'object'; +} + +module.exports = isObjectLike; + +},{}],131:[function(require,module,exports){ +var isObject = require('../lang/isObject'); + +/** + * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. + * + * @private + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` if suitable for strict + * equality comparisons, else `false`. + */ +function isStrictComparable(value) { + return value === value && !isObject(value); +} + +module.exports = isStrictComparable; + +},{"../lang/isObject":148}],132:[function(require,module,exports){ +var arrayCopy = require('./arrayCopy'), + composeArgs = require('./composeArgs'), + composeArgsRight = require('./composeArgsRight'), + replaceHolders = require('./replaceHolders'); + +/** Used to compose bitmasks for wrapper metadata. */ +var BIND_FLAG = 1, + CURRY_BOUND_FLAG = 4, + CURRY_FLAG = 8, + ARY_FLAG = 128, + REARG_FLAG = 256; + +/** Used as the internal argument placeholder. */ +var PLACEHOLDER = '__lodash_placeholder__'; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Merges the function metadata of `source` into `data`. + * + * Merging metadata reduces the number of wrappers required to invoke a function. + * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` + * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg` + * augment function arguments, making the order in which they are executed important, + * preventing the merging of metadata. However, we make an exception for a safe + * common case where curried functions have `_.ary` and or `_.rearg` applied. + * + * @private + * @param {Array} data The destination metadata. + * @param {Array} source The source metadata. + * @returns {Array} Returns `data`. + */ +function mergeData(data, source) { + var bitmask = data[1], + srcBitmask = source[1], + newBitmask = bitmask | srcBitmask, + isCommon = newBitmask < ARY_FLAG; + + var isCombo = + (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) || + (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) || + (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG); + + // Exit early if metadata can't be merged. + if (!(isCommon || isCombo)) { + return data; + } + // Use source `thisArg` if available. + if (srcBitmask & BIND_FLAG) { + data[2] = source[2]; + // Set when currying a bound function. + newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG; + } + // Compose partial arguments. + var value = source[3]; + if (value) { + var partials = data[3]; + data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value); + data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]); + } + // Compose partial right arguments. + value = source[5]; + if (value) { + partials = data[5]; + data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value); + data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]); + } + // Use source `argPos` if available. + value = source[7]; + if (value) { + data[7] = arrayCopy(value); + } + // Use source `ary` if it's smaller. + if (srcBitmask & ARY_FLAG) { + data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); + } + // Use source `arity` if one is not provided. + if (data[9] == null) { + data[9] = source[9]; + } + // Use source `func` and merge bitmasks. + data[0] = source[0]; + data[1] = newBitmask; + + return data; +} + +module.exports = mergeData; + +},{"./arrayCopy":66,"./composeArgs":100,"./composeArgsRight":101,"./replaceHolders":136}],133:[function(require,module,exports){ +(function (global){ +var getNative = require('./getNative'); + +/** Native method references. */ +var WeakMap = getNative(global, 'WeakMap'); + +/** Used to store function metadata. */ +var metaMap = WeakMap && new WeakMap; + +module.exports = metaMap; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL21ldGFNYXAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9nZXROYXRpdmUnKTtcblxuLyoqIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBXZWFrTWFwID0gZ2V0TmF0aXZlKGdsb2JhbCwgJ1dlYWtNYXAnKTtcblxuLyoqIFVzZWQgdG8gc3RvcmUgZnVuY3Rpb24gbWV0YWRhdGEuICovXG52YXIgbWV0YU1hcCA9IFdlYWtNYXAgJiYgbmV3IFdlYWtNYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gbWV0YU1hcDtcbiJdfQ== +},{"./getNative":118}],134:[function(require,module,exports){ +/** Used to lookup unminified function names. */ +var realNames = {}; + +module.exports = realNames; + +},{}],135:[function(require,module,exports){ +var arrayCopy = require('./arrayCopy'), + isIndex = require('./isIndex'); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeMin = Math.min; + +/** + * Reorder `array` according to the specified indexes where the element at + * the first index is assigned as the first element, the element at + * the second index is assigned as the second element, and so on. + * + * @private + * @param {Array} array The array to reorder. + * @param {Array} indexes The arranged array indexes. + * @returns {Array} Returns `array`. + */ +function reorder(array, indexes) { + var arrLength = array.length, + length = nativeMin(indexes.length, arrLength), + oldArray = arrayCopy(array); + + while (length--) { + var index = indexes[length]; + array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; + } + return array; +} + +module.exports = reorder; + +},{"./arrayCopy":66,"./isIndex":125}],136:[function(require,module,exports){ +/** Used as the internal argument placeholder. */ +var PLACEHOLDER = '__lodash_placeholder__'; + +/** + * Replaces all `placeholder` elements in `array` with an internal placeholder + * and returns an array of their indexes. + * + * @private + * @param {Array} array The array to modify. + * @param {*} placeholder The placeholder to replace. + * @returns {Array} Returns the new array of placeholder indexes. + */ +function replaceHolders(array, placeholder) { + var index = -1, + length = array.length, + resIndex = -1, + result = []; + + while (++index < length) { + if (array[index] === placeholder) { + array[index] = PLACEHOLDER; + result[++resIndex] = index; + } + } + return result; +} + +module.exports = replaceHolders; + +},{}],137:[function(require,module,exports){ +var baseSetData = require('./baseSetData'), + now = require('../date/now'); + +/** Used to detect when a function becomes hot. */ +var HOT_COUNT = 150, + HOT_SPAN = 16; + +/** + * Sets metadata for `func`. + * + * **Note:** If this function becomes hot, i.e. is invoked a lot in a short + * period of time, it will trip its breaker and transition to an identity function + * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070) + * for more details. + * + * @private + * @param {Function} func The function to associate metadata with. + * @param {*} data The metadata. + * @returns {Function} Returns `func`. + */ +var setData = (function() { + var count = 0, + lastCalled = 0; + + return function(key, value) { + var stamp = now(), + remaining = HOT_SPAN - (stamp - lastCalled); + + lastCalled = stamp; + if (remaining > 0) { + if (++count >= HOT_COUNT) { + return key; + } + } else { + count = 0; + } + return baseSetData(key, value); + }; +}()); + +module.exports = setData; + +},{"../date/now":61,"./baseSetData":92}],138:[function(require,module,exports){ +var isArguments = require('../lang/isArguments'), + isArray = require('../lang/isArray'), + isIndex = require('./isIndex'), + isLength = require('./isLength'), + isString = require('../lang/isString'), + keysIn = require('../object/keysIn'); + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * A fallback implementation of `Object.keys` which creates an array of the + * own enumerable property names of `object`. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function shimKeys(object) { + var props = keysIn(object), + propsLength = props.length, + length = propsLength && object.length; + + var allowIndexes = !!length && isLength(length) && + (isArray(object) || isArguments(object) || isString(object)); + + var index = -1, + result = []; + + while (++index < propsLength) { + var key = props[index]; + if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) { + result.push(key); + } + } + return result; +} + +module.exports = shimKeys; + +},{"../lang/isArguments":143,"../lang/isArray":144,"../lang/isString":150,"../object/keysIn":154,"./isIndex":125,"./isLength":129}],139:[function(require,module,exports){ +var isObject = require('../lang/isObject'), + isString = require('../lang/isString'), + support = require('../support'); + +/** + * Converts `value` to an object if it's not one. + * + * @private + * @param {*} value The value to process. + * @returns {Object} Returns the object. + */ +function toObject(value) { + if (support.unindexedChars && isString(value)) { + var index = -1, + length = value.length, + result = Object(value); + + while (++index < length) { + result[index] = value.charAt(index); + } + return result; + } + return isObject(value) ? value : Object(value); +} + +module.exports = toObject; + +},{"../lang/isObject":148,"../lang/isString":150,"../support":157}],140:[function(require,module,exports){ +var baseToString = require('./baseToString'), + isArray = require('../lang/isArray'); + +/** Used to match property names within property paths. */ +var rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g; + +/** Used to match backslashes in property paths. */ +var reEscapeChar = /\\(\\)?/g; + +/** + * Converts `value` to property path array if it's not one. + * + * @private + * @param {*} value The value to process. + * @returns {Array} Returns the property path array. + */ +function toPath(value) { + if (isArray(value)) { + return value; + } + var result = []; + baseToString(value).replace(rePropName, function(match, number, quote, string) { + result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); + }); + return result; +} + +module.exports = toPath; + +},{"../lang/isArray":144,"./baseToString":94}],141:[function(require,module,exports){ +var LazyWrapper = require('./LazyWrapper'), + LodashWrapper = require('./LodashWrapper'), + arrayCopy = require('./arrayCopy'); + +/** + * Creates a clone of `wrapper`. + * + * @private + * @param {Object} wrapper The wrapper to clone. + * @returns {Object} Returns the cloned wrapper. + */ +function wrapperClone(wrapper) { + return wrapper instanceof LazyWrapper + ? wrapper.clone() + : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__)); +} + +module.exports = wrapperClone; + +},{"./LazyWrapper":64,"./LodashWrapper":65,"./arrayCopy":66}],142:[function(require,module,exports){ +var baseClone = require('../internal/baseClone'), + bindCallback = require('../internal/bindCallback'); + +/** + * Creates a deep clone of `value`. If `customizer` is provided it's invoked + * to produce the cloned values. If `customizer` returns `undefined` cloning + * is handled by the method instead. The `customizer` is bound to `thisArg` + * and invoked with up to three argument; (value [, index|key, object]). + * + * **Note:** This method is loosely based on the + * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm). + * The enumerable properties of `arguments` objects and objects created by + * constructors other than `Object` are cloned to plain `Object` objects. An + * empty object is returned for uncloneable values such as functions, DOM nodes, + * Maps, Sets, and WeakMaps. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to deep clone. + * @param {Function} [customizer] The function to customize cloning values. + * @param {*} [thisArg] The `this` binding of `customizer`. + * @returns {*} Returns the deep cloned value. + * @example + * + * var users = [ + * { 'user': 'barney' }, + * { 'user': 'fred' } + * ]; + * + * var deep = _.cloneDeep(users); + * deep[0] === users[0]; + * // => false + * + * // using a customizer callback + * var el = _.cloneDeep(document.body, function(value) { + * if (_.isElement(value)) { + * return value.cloneNode(true); + * } + * }); + * + * el === document.body + * // => false + * el.nodeName + * // => BODY + * el.childNodes.length; + * // => 20 + */ +function cloneDeep(value, customizer, thisArg) { + return typeof customizer == 'function' + ? baseClone(value, true, bindCallback(customizer, thisArg, 3)) + : baseClone(value, true); +} + +module.exports = cloneDeep; + +},{"../internal/baseClone":72,"../internal/bindCallback":98}],143:[function(require,module,exports){ +var isArrayLike = require('../internal/isArrayLike'), + isObjectLike = require('../internal/isObjectLike'); + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Native method references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable; + +/** + * Checks if `value` is classified as an `arguments` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArguments(function() { return arguments; }()); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ +function isArguments(value) { + return isObjectLike(value) && isArrayLike(value) && + hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee'); +} + +module.exports = isArguments; + +},{"../internal/isArrayLike":123,"../internal/isObjectLike":130}],144:[function(require,module,exports){ +var getNative = require('../internal/getNative'), + isLength = require('../internal/isLength'), + isObjectLike = require('../internal/isObjectLike'); + +/** `Object#toString` result references. */ +var arrayTag = '[object Array]'; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeIsArray = getNative(Array, 'isArray'); + +/** + * Checks if `value` is classified as an `Array` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isArray([1, 2, 3]); + * // => true + * + * _.isArray(function() { return arguments; }()); + * // => false + */ +var isArray = nativeIsArray || function(value) { + return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag; +}; + +module.exports = isArray; + +},{"../internal/getNative":118,"../internal/isLength":129,"../internal/isObjectLike":130}],145:[function(require,module,exports){ +var isArguments = require('./isArguments'), + isArray = require('./isArray'), + isArrayLike = require('../internal/isArrayLike'), + isFunction = require('./isFunction'), + isObjectLike = require('../internal/isObjectLike'), + isString = require('./isString'), + keys = require('../object/keys'); + +/** + * Checks if `value` is empty. A value is considered empty unless it's an + * `arguments` object, array, string, or jQuery-like collection with a length + * greater than `0` or an object with own enumerable properties. + * + * @static + * @memberOf _ + * @category Lang + * @param {Array|Object|string} value The value to inspect. + * @returns {boolean} Returns `true` if `value` is empty, else `false`. + * @example + * + * _.isEmpty(null); + * // => true + * + * _.isEmpty(true); + * // => true + * + * _.isEmpty(1); + * // => true + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({ 'a': 1 }); + * // => false + */ +function isEmpty(value) { + if (value == null) { + return true; + } + if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || + (isObjectLike(value) && isFunction(value.splice)))) { + return !value.length; + } + return !keys(value).length; +} + +module.exports = isEmpty; + +},{"../internal/isArrayLike":123,"../internal/isObjectLike":130,"../object/keys":153,"./isArguments":143,"./isArray":144,"./isFunction":146,"./isString":150}],146:[function(require,module,exports){ +var isObject = require('./isObject'); + +/** `Object#toString` result references. */ +var funcTag = '[object Function]'; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * Checks if `value` is classified as a `Function` object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isFunction(_); + * // => true + * + * _.isFunction(/abc/); + * // => false + */ +function isFunction(value) { + // The use of `Object#toString` avoids issues with the `typeof` operator + // in older versions of Chrome and Safari which return 'function' for regexes + // and Safari 8 which returns 'object' for typed array constructors. + return isObject(value) && objToString.call(value) == funcTag; +} + +module.exports = isFunction; + +},{"./isObject":148}],147:[function(require,module,exports){ +var isFunction = require('./isFunction'), + isHostObject = require('../internal/isHostObject'), + isObjectLike = require('../internal/isObjectLike'); + +/** Used to detect host constructors (Safari > 5). */ +var reIsHostCtor = /^\[object .+?Constructor\]$/; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to resolve the decompiled source of functions. */ +var fnToString = Function.prototype.toString; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** Used to detect if a method is native. */ +var reIsNative = RegExp('^' + + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&') + .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' +); + +/** + * Checks if `value` is a native function. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a native function, else `false`. + * @example + * + * _.isNative(Array.prototype.push); + * // => true + * + * _.isNative(_); + * // => false + */ +function isNative(value) { + if (value == null) { + return false; + } + if (isFunction(value)) { + return reIsNative.test(fnToString.call(value)); + } + return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value); +} + +module.exports = isNative; + +},{"../internal/isHostObject":124,"../internal/isObjectLike":130,"./isFunction":146}],148:[function(require,module,exports){ +/** + * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ +function isObject(value) { + // Avoid a V8 JIT bug in Chrome 19-20. + // See https://code.google.com/p/v8/issues/detail?id=2291 for more details. + var type = typeof value; + return !!value && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + +},{}],149:[function(require,module,exports){ +var baseForIn = require('../internal/baseForIn'), + isArguments = require('./isArguments'), + isHostObject = require('../internal/isHostObject'), + isObjectLike = require('../internal/isObjectLike'), + support = require('../support'); + +/** `Object#toString` result references. */ +var objectTag = '[object Object]'; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * Checks if `value` is a plain object, that is, an object created by the + * `Object` constructor or one with a `[[Prototype]]` of `null`. + * + * **Note:** This method assumes objects created by the `Object` constructor + * have no inherited enumerable properties. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. + * @example + * + * function Foo() { + * this.a = 1; + * } + * + * _.isPlainObject(new Foo); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'x': 0, 'y': 0 }); + * // => true + * + * _.isPlainObject(Object.create(null)); + * // => true + */ +function isPlainObject(value) { + var Ctor; + + // Exit early for non `Object` objects. + if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) || + (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) { + return false; + } + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + var result; + if (support.ownLast) { + baseForIn(value, function(subValue, key, object) { + result = hasOwnProperty.call(object, key); + return false; + }); + return result !== false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + baseForIn(value, function(subValue, key) { + result = key; + }); + return result === undefined || hasOwnProperty.call(value, result); +} + +module.exports = isPlainObject; + +},{"../internal/baseForIn":79,"../internal/isHostObject":124,"../internal/isObjectLike":130,"../support":157,"./isArguments":143}],150:[function(require,module,exports){ +var isObjectLike = require('../internal/isObjectLike'); + +/** `Object#toString` result references. */ +var stringTag = '[object String]'; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * Checks if `value` is classified as a `String` primitive or object. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isString('abc'); + * // => true + * + * _.isString(1); + * // => false + */ +function isString(value) { + return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag); +} + +module.exports = isString; + +},{"../internal/isObjectLike":130}],151:[function(require,module,exports){ +var isLength = require('../internal/isLength'), + isObjectLike = require('../internal/isObjectLike'); + +/** `Object#toString` result references. */ +var argsTag = '[object Arguments]', + arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + mapTag = '[object Map]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + setTag = '[object Set]', + stringTag = '[object String]', + weakMapTag = '[object WeakMap]'; + +var arrayBufferTag = '[object ArrayBuffer]', + float32Tag = '[object Float32Array]', + float64Tag = '[object Float64Array]', + int8Tag = '[object Int8Array]', + int16Tag = '[object Int16Array]', + int32Tag = '[object Int32Array]', + uint8Tag = '[object Uint8Array]', + uint8ClampedTag = '[object Uint8ClampedArray]', + uint16Tag = '[object Uint16Array]', + uint32Tag = '[object Uint32Array]'; + +/** Used to identify `toStringTag` values of typed arrays. */ +var typedArrayTags = {}; +typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = +typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = +typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = +typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = +typedArrayTags[uint32Tag] = true; +typedArrayTags[argsTag] = typedArrayTags[arrayTag] = +typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = +typedArrayTags[dateTag] = typedArrayTags[errorTag] = +typedArrayTags[funcTag] = typedArrayTags[mapTag] = +typedArrayTags[numberTag] = typedArrayTags[objectTag] = +typedArrayTags[regexpTag] = typedArrayTags[setTag] = +typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false; + +/** Used for native method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** + * Checks if `value` is classified as a typed array. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`. + * @example + * + * _.isTypedArray(new Uint8Array); + * // => true + * + * _.isTypedArray([]); + * // => false + */ +function isTypedArray(value) { + return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)]; +} + +module.exports = isTypedArray; + +},{"../internal/isLength":129,"../internal/isObjectLike":130}],152:[function(require,module,exports){ +/** + * Checks if `value` is `undefined`. + * + * @static + * @memberOf _ + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + * + * _.isUndefined(null); + * // => false + */ +function isUndefined(value) { + return value === undefined; +} + +module.exports = isUndefined; + +},{}],153:[function(require,module,exports){ +var getNative = require('../internal/getNative'), + isArrayLike = require('../internal/isArrayLike'), + isObject = require('../lang/isObject'), + shimKeys = require('../internal/shimKeys'), + support = require('../support'); + +/* Native method references for those with the same name as other `lodash` methods. */ +var nativeKeys = getNative(Object, 'keys'); + +/** + * Creates an array of the own enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. See the + * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * for more details. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keys(new Foo); + * // => ['a', 'b'] (iteration order is not guaranteed) + * + * _.keys('hi'); + * // => ['0', '1'] + */ +var keys = !nativeKeys ? shimKeys : function(object) { + var Ctor = object == null ? undefined : object.constructor; + if ((typeof Ctor == 'function' && Ctor.prototype === object) || + (typeof object == 'function' ? support.enumPrototypes : isArrayLike(object))) { + return shimKeys(object); + } + return isObject(object) ? nativeKeys(object) : []; +}; + +module.exports = keys; + +},{"../internal/getNative":118,"../internal/isArrayLike":123,"../internal/shimKeys":138,"../lang/isObject":148,"../support":157}],154:[function(require,module,exports){ +var arrayEach = require('../internal/arrayEach'), + isArguments = require('../lang/isArguments'), + isArray = require('../lang/isArray'), + isFunction = require('../lang/isFunction'), + isIndex = require('../internal/isIndex'), + isLength = require('../internal/isLength'), + isObject = require('../lang/isObject'), + isString = require('../lang/isString'), + support = require('../support'); + +/** `Object#toString` result references. */ +var arrayTag = '[object Array]', + boolTag = '[object Boolean]', + dateTag = '[object Date]', + errorTag = '[object Error]', + funcTag = '[object Function]', + numberTag = '[object Number]', + objectTag = '[object Object]', + regexpTag = '[object RegExp]', + stringTag = '[object String]'; + +/** Used to fix the JScript `[[DontEnum]]` bug. */ +var shadowProps = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' +]; + +/** Used for native method references. */ +var errorProto = Error.prototype, + objectProto = Object.prototype, + stringProto = String.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * of values. + */ +var objToString = objectProto.toString; + +/** Used to avoid iterating over non-enumerable properties in IE < 9. */ +var nonEnumProps = {}; +nonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true }; +nonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true }; +nonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true }; +nonEnumProps[objectTag] = { 'constructor': true }; + +arrayEach(shadowProps, function(key) { + for (var tag in nonEnumProps) { + if (hasOwnProperty.call(nonEnumProps, tag)) { + var props = nonEnumProps[tag]; + props[key] = hasOwnProperty.call(props, key); + } + } +}); + +/** + * Creates an array of the own and inherited enumerable property names of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.keysIn(new Foo); + * // => ['a', 'b', 'c'] (iteration order is not guaranteed) + */ +function keysIn(object) { + if (object == null) { + return []; + } + if (!isObject(object)) { + object = Object(object); + } + var length = object.length; + + length = (length && isLength(length) && + (isArray(object) || isArguments(object) || isString(object)) && length) || 0; + + var Ctor = object.constructor, + index = -1, + proto = (isFunction(Ctor) && Ctor.prototype) || objectProto, + isProto = proto === object, + result = Array(length), + skipIndexes = length > 0, + skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error), + skipProto = support.enumPrototypes && isFunction(object); + + while (++index < length) { + result[index] = (index + ''); + } + // lodash skips the `constructor` property when it infers it's iterating + // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]` + // attribute of an existing property and the `constructor` property of a + // prototype defaults to non-enumerable. + for (var key in object) { + if (!(skipProto && key == 'prototype') && + !(skipErrorProps && (key == 'message' || key == 'name')) && + !(skipIndexes && isIndex(key, length)) && + !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } + } + if (support.nonEnumShadows && object !== objectProto) { + var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)), + nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag]; + + if (tag == objectTag) { + proto = objectProto; + } + length = shadowProps.length; + while (length--) { + key = shadowProps[length]; + var nonEnum = nonEnums[key]; + if (!(isProto && nonEnum) && + (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) { + result.push(key); + } + } + } + return result; +} + +module.exports = keysIn; + +},{"../internal/arrayEach":67,"../internal/isIndex":125,"../internal/isLength":129,"../lang/isArguments":143,"../lang/isArray":144,"../lang/isFunction":146,"../lang/isObject":148,"../lang/isString":150,"../support":157}],155:[function(require,module,exports){ +var keys = require('./keys'), + toObject = require('../internal/toObject'); + +/** + * Creates a two dimensional array of the key-value pairs for `object`, + * e.g. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the new array of key-value pairs. + * @example + * + * _.pairs({ 'barney': 36, 'fred': 40 }); + * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed) + */ +function pairs(object) { + object = toObject(object); + + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; +} + +module.exports = pairs; + +},{"../internal/toObject":139,"./keys":153}],156:[function(require,module,exports){ +var baseValues = require('../internal/baseValues'), + keys = require('./keys'); + +/** + * Creates an array of the own enumerable property values of `object`. + * + * **Note:** Non-object values are coerced to objects. + * + * @static + * @memberOf _ + * @category Object + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property values. + * @example + * + * function Foo() { + * this.a = 1; + * this.b = 2; + * } + * + * Foo.prototype.c = 3; + * + * _.values(new Foo); + * // => [1, 2] (iteration order is not guaranteed) + * + * _.values('hi'); + * // => ['h', 'i'] + */ +function values(object) { + return baseValues(object, keys(object)); +} + +module.exports = values; + +},{"../internal/baseValues":95,"./keys":153}],157:[function(require,module,exports){ +/** Used for native method references. */ +var arrayProto = Array.prototype, + errorProto = Error.prototype, + objectProto = Object.prototype; + +/** Native method references. */ +var propertyIsEnumerable = objectProto.propertyIsEnumerable, + splice = arrayProto.splice; + +/** + * An object environment feature flags. + * + * @static + * @memberOf _ + * @type Object + */ +var support = {}; + +(function(x) { + var Ctor = function() { this.x = x; }, + object = { '0': x, 'length': x }, + props = []; + + Ctor.prototype = { 'valueOf': x, 'y': x }; + for (var key in new Ctor) { props.push(key); } + + /** + * Detect if `name` or `message` properties of `Error.prototype` are + * enumerable by default (IE < 9, Safari < 5.1). + * + * @memberOf _.support + * @type boolean + */ + support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') || + propertyIsEnumerable.call(errorProto, 'name'); + + /** + * Detect if `prototype` properties are enumerable by default. + * + * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + * (if the prototype or a property on the prototype has been set) + * incorrectly set the `[[Enumerable]]` value of a function's `prototype` + * property to `true`. + * + * @memberOf _.support + * @type boolean + */ + support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype'); + + /** + * Detect if properties shadowing those on `Object.prototype` are non-enumerable. + * + * In IE < 9 an object's own properties, shadowing non-enumerable ones, + * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug). + * + * @memberOf _.support + * @type boolean + */ + support.nonEnumShadows = !/valueOf/.test(props); + + /** + * Detect if own properties are iterated after inherited properties (IE < 9). + * + * @memberOf _.support + * @type boolean + */ + support.ownLast = props[0] != 'x'; + + /** + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * correctly. + * + * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array + * `shift()` and `splice()` functions that fail to remove the last element, + * `value[0]`, of array-like objects even though the "length" property is + * set to `0`. The `shift()` method is buggy in compatibility modes of IE 8, + * while `splice()` is buggy regardless of mode in IE < 9. + * + * @memberOf _.support + * @type boolean + */ + support.spliceObjects = (splice.call(object, 0, 1), !object[0]); + + /** + * Detect lack of support for accessing string characters by index. + * + * IE < 8 can't access characters by index. IE 8 can only access characters + * by index on string literals, not string objects. + * + * @memberOf _.support + * @type boolean + */ + support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx'; +}(1, 0)); + +module.exports = support; + +},{}],158:[function(require,module,exports){ +/** + * This method returns the first argument provided to it. + * + * @static + * @memberOf _ + * @category Utility + * @param {*} value Any value. + * @returns {*} Returns `value`. + * @example + * + * var object = { 'user': 'fred' }; + * + * _.identity(object) === object; + * // => true + */ +function identity(value) { + return value; +} + +module.exports = identity; + +},{}],159:[function(require,module,exports){ +/** + * A no-operation function that returns `undefined` regardless of the + * arguments it receives. + * + * @static + * @memberOf _ + * @category Utility + * @example + * + * var object = { 'user': 'fred' }; + * + * _.noop(object) === undefined; + * // => true + */ +function noop() { + // No operation performed. +} + +module.exports = noop; + +},{}],160:[function(require,module,exports){ +var baseProperty = require('../internal/baseProperty'), + basePropertyDeep = require('../internal/basePropertyDeep'), + isKey = require('../internal/isKey'); + +/** + * Creates a function that returns the property value at `path` on a + * given object. + * + * @static + * @memberOf _ + * @category Utility + * @param {Array|string} path The path of the property to get. + * @returns {Function} Returns the new function. + * @example + * + * var objects = [ + * { 'a': { 'b': { 'c': 2 } } }, + * { 'a': { 'b': { 'c': 1 } } } + * ]; + * + * _.map(objects, _.property('a.b.c')); + * // => [2, 1] + * + * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c'); + * // => [1, 2] + */ +function property(path) { + return isKey(path) ? baseProperty(path) : basePropertyDeep(path); +} + +module.exports = property; + +},{"../internal/baseProperty":90,"../internal/basePropertyDeep":91,"../internal/isKey":127}],161:[function(require,module,exports){ +(function (process){ +// vim:ts=4:sts=4:sw=4: +/*! + * + * Copyright 2009-2012 Kris Kowal under the terms of the MIT + * license found at http://github.com/kriskowal/q/raw/master/LICENSE + * + * With parts by Tyler Close + * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found + * at http://www.opensource.org/licenses/mit-license.html + * Forked at ref_send.js version: 2009-05-11 + * + * With parts by Mark Miller + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +(function (definition) { + "use strict"; + + // This file will function properly as a "); sb.AppendLine($""); sb.AppendLine($""); sb.AppendLine($""); - sb.AppendLine($""); + sb.AppendLine($""); sb.AppendLine($""); sb.AppendLine($""); sb.AppendLine($""); @@ -78,7 +84,7 @@ namespace PlexRequests.UI.Helpers var content = GetContentUrl(assetLocation); - sb.AppendLine($""); + sb.AppendLine($""); return helper.Raw(sb.ToString()); } @@ -90,12 +96,12 @@ namespace PlexRequests.UI.Helpers var content = GetContentUrl(assetLocation); - sb.AppendLine($""); + sb.AppendLine($""); return helper.Raw(sb.ToString()); } - public static IHtmlString LoadLogsAssets(this HtmlHelpers helper) + public static IHtmlString LoadTableAssets(this HtmlHelpers helper) { var sb = new StringBuilder(); var assetLocation = GetBaseUrl(); @@ -155,11 +161,15 @@ namespace PlexRequests.UI.Helpers private static string GetBaseUrl() { - var returnValue = Cache.GetOrSet(CacheKeys.GetBaseUrl, () => + return GetSettings().BaseUrl; + } + + private static PlexRequestSettings GetSettings() + { + var returnValue = Cache.GetOrSet(CacheKeys.GetPlexRequestSettings, () => { - var settings = Locator.Resolve>().GetSettings(); - var assetLocation = settings.BaseUrl; - return assetLocation; + var settings = Locator.Resolve>().GetSettings(); + return settings; }); return returnValue; } diff --git a/PlexRequests.UI/Helpers/ServiceLocator.cs b/PlexRequests.UI/Helpers/ServiceLocator.cs index 860cd150b..40e82e434 100644 --- a/PlexRequests.UI/Helpers/ServiceLocator.cs +++ b/PlexRequests.UI/Helpers/ServiceLocator.cs @@ -24,11 +24,13 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion +using System; + using Nancy.TinyIoc; namespace PlexRequests.UI.Helpers { - public class ServiceLocator + public class ServiceLocator : IServiceLocator { static ServiceLocator() { @@ -46,5 +48,16 @@ namespace PlexRequests.UI.Helpers { return Container?.Resolve(); } + + public object Resolve(Type type) + { + return Container.Resolve(type); + } + } + + public interface IServiceLocator + { + T Resolve() where T : class; + object Resolve(Type type); } } \ No newline at end of file diff --git a/PlexRequests.UI/Helpers/Themes.cs b/PlexRequests.UI/Helpers/Themes.cs new file mode 100644 index 000000000..2e7e54fa1 --- /dev/null +++ b/PlexRequests.UI/Helpers/Themes.cs @@ -0,0 +1,34 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: Themes.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace PlexRequests.UI.Helpers +{ + public static class Themes + { + public const string OriginalTheme = "OriginalBootstrap.css"; + public const string PlexTheme = "PlexBootstrap.css"; + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/CustomJobFactory.cs b/PlexRequests.UI/Jobs/CustomJobFactory.cs new file mode 100644 index 000000000..643222844 --- /dev/null +++ b/PlexRequests.UI/Jobs/CustomJobFactory.cs @@ -0,0 +1,94 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: CustomJobFactory.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; + +using NLog; + +using PlexRequests.UI.Helpers; + +using Quartz; +using Quartz.Spi; + +namespace PlexRequests.UI.Jobs +{ + /// + /// The custom job factory we are using so we are able to use our IoC container with DI in our JobNames. + /// + /// + public class CustomJobFactory : IJobFactory + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private IServiceLocator Locator => ServiceLocator.Instance; + + /// + /// Called by the scheduler at the time of the trigger firing, in order to + /// produce a instance on which to call Execute. + /// This will use the to resolve all dependencies of a job. + /// + /// The TriggerFiredBundle from which the + /// and other info relating to the trigger firing can be obtained. + /// a handle to the scheduler that is about to execute the job + /// + /// the newly instantiated Job + /// + /// + /// It should be extremely rare for this method to throw an exception - + /// basically only the case where there is no way at all to instantiate + /// and prepare the Job for execution. When the exception is thrown, the + /// Scheduler will move all triggers associated with the Job into the + /// state, which will require human + /// intervention (e.g. an application restart after fixing whatever + /// configuration problem led to the issue with instantiating the Job). + /// + /// SchedulerException if there is a problem instantiating the Job. + public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) + { + try + { + var jobDetail = bundle.JobDetail; + var jobType = jobDetail.JobType; + + var resolvedType = (IJob)Locator.Resolve(jobType); + return resolvedType; + } + catch (Exception e) + { + Log.Error(e); + throw; + } + } + + /// + /// Allows the job factory to destroy/clean-up the job if needed. + /// + /// + public void ReturnJob(IJob job) + { + // No need to do anything since our jobs do not implement IDisposable. + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/PlexTaskFactory.cs b/PlexRequests.UI/Jobs/PlexTaskFactory.cs deleted file mode 100644 index 5f5b88b89..000000000 --- a/PlexRequests.UI/Jobs/PlexTaskFactory.cs +++ /dev/null @@ -1,23 +0,0 @@ -using FluentScheduler; -using Nancy.TinyIoc; - -using PlexRequests.Services; - -namespace PlexRequests.UI.Jobs -{ - public class PlexTaskFactory : ITaskFactory - { - public ITask GetTaskInstance() where T : ITask - { - //typeof(AvailabilityUpdateService); - var container = TinyIoCContainer.Current; - - var a= container.Resolve(typeof(T)); - - object outT; - container.TryResolve(typeof(T), out outT); - - return (T)a; - } - } -} \ No newline at end of file diff --git a/PlexRequests.UI/Jobs/Scheduler.cs b/PlexRequests.UI/Jobs/Scheduler.cs new file mode 100644 index 000000000..0ccae710b --- /dev/null +++ b/PlexRequests.UI/Jobs/Scheduler.cs @@ -0,0 +1,147 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: Scheduler.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; +using System.Linq; + +using NLog; + +using PlexRequests.Services.Jobs; + +using Quartz; +using Quartz.Impl; + +namespace PlexRequests.UI.Jobs +{ + internal sealed class Scheduler + { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private readonly ISchedulerFactory _factory; + + public Scheduler() + { + _factory = new StdSchedulerFactory(); + } + + private IEnumerable CreateJobs() + { + var jobs = new List(); + + var plex = JobBuilder.Create().WithIdentity("PlexAvailabilityChecker", "Plex").Build(); + var sickrage = JobBuilder.Create().WithIdentity("SickRageCacher", "Cache").Build(); + var sonarr = JobBuilder.Create().WithIdentity("SonarrCacher", "Cache").Build(); + var cp = JobBuilder.Create().WithIdentity("CouchPotatoCacher", "Cache").Build(); + var store = JobBuilder.Create().WithIdentity("StoreBackup", "Backup").Build(); + + jobs.Add(plex); + jobs.Add(sickrage); + jobs.Add(sonarr); + jobs.Add(cp); + jobs.Add(store); + + return jobs; + } + + /// + /// Starts the scheduler. + /// + /// The jobs do not match the triggers, we should have a trigger per job + public void StartScheduler() + { + var scheduler = _factory.GetScheduler(); + scheduler.JobFactory = new CustomJobFactory(); + scheduler.Start(); + + var jobs = CreateJobs(); + var triggers = CreateTriggers(); + + var jobDetails = jobs as IJobDetail[] ?? jobs.ToArray(); + var triggerDetails = triggers as ITrigger[] ?? triggers.ToArray(); + + if (jobDetails.Length != triggerDetails.Length) + { + Log.Error("The jobs do not match the triggers, we should have a trigger per job"); + throw new InvalidProgramException("The jobs do not match the triggers, we should have a trigger per job"); + } + + for (var i = 0; i < jobDetails.Length; i++) + { + scheduler.ScheduleJob(jobDetails[i], triggerDetails[i]); + } + } + + private IEnumerable CreateTriggers() + { + var triggers = new List(); + + var plexAvailabilityChecker = + TriggerBuilder.Create() + .WithIdentity("PlexAvailabilityChecker", "Plex") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var srCacher = + TriggerBuilder.Create() + .WithIdentity("SickRageCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var sonarrCacher = + TriggerBuilder.Create() + .WithIdentity("SonarrCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var cpCacher = + TriggerBuilder.Create() + .WithIdentity("CouchPotatoCacher", "Cache") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInMinutes(10).RepeatForever()) + .Build(); + + var storeBackup = + TriggerBuilder.Create() + .WithIdentity("StoreBackup", "Backup") + .StartNow() + .WithSimpleSchedule(x => x.WithIntervalInHours(24).RepeatForever()) + .Build(); + + + triggers.Add(plexAvailabilityChecker); + triggers.Add(srCacher); + triggers.Add(sonarrCacher); + triggers.Add(cpCacher); + triggers.Add(storeBackup); + + return triggers; + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/AuthSettingsDataProvider.cs b/PlexRequests.UI/ModelDataProviders/AuthSettingsDataProvider.cs new file mode 100644 index 000000000..70cbb91c7 --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/AuthSettingsDataProvider.cs @@ -0,0 +1,61 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: AuthSettingsDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class AuthSettingsDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.DeniedUserList) + .Description("The blacklisted users, this is for internal use by the application, do not modify this list.") + .Required(false); + with.Property(x => x.DeniedUsers).Description("The blacklisted users, comma separated.").Required(false); + with.Property(x => x.PlexAuthToken).Description("The Plex authentication token").Required(false); + with.Property(x => x.UsePassword) + .Description("Require users to use a password to login when authentication is enabled") + .Required(false) + .Default(false); + with.Property(x => x.UserAuthentication) + .Description("Require users to enter their username in, this will check against Plex") + .Required(false) + .Default(false); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/CouchPotatoDataProvider.cs b/PlexRequests.UI/ModelDataProviders/CouchPotatoDataProvider.cs new file mode 100644 index 000000000..2e7a82b56 --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/CouchPotatoDataProvider.cs @@ -0,0 +1,55 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: CouchPotatoDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class CouchPotatoDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Ip).Description("The IP address of CouchPotato").Required(true); + with.Property(x => x.Port).Description("The Port address of CouchPotato").Required(true).Default(5050); + with.Property(x => x.Ssl).Description("Enable SSL").Required(false).Default(false); + with.Property(x => x.FullUri).Description("Internal Property, do not use").Required(false).Default(null); + with.Property(x => x.SubDir).Description("Subdir/BaseUrl of CouchPotato").Required(false); + with.Property(x => x.ApiKey).Description("CouchPotato's API key").Required(true); + with.Property(x => x.ProfileId).Description("CouchPotato's profileId").Required(false); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/HeadphonesDataProvider.cs b/PlexRequests.UI/ModelDataProviders/HeadphonesDataProvider.cs new file mode 100644 index 000000000..36f2acdbf --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/HeadphonesDataProvider.cs @@ -0,0 +1,54 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: HeadphonesDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class HeadphonesDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Ip).Description("The IP address of Headphones").Required(true); + with.Property(x => x.Port).Description("The Port address of Headphones").Required(true).Default(5050); + with.Property(x => x.Ssl).Description("Enable SSL").Required(false).Default(false); + with.Property(x => x.FullUri).Description("Internal Property, do not use").Required(false).Default(null); + with.Property(x => x.SubDir).Description("Subdir/BaseUrl of Headphones").Required(false); + with.Property(x => x.ApiKey).Description("Headphones's API key").Required(true); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/PlexSettingsDataProvider.cs b/PlexRequests.UI/ModelDataProviders/PlexSettingsDataProvider.cs new file mode 100644 index 000000000..742114bdb --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/PlexSettingsDataProvider.cs @@ -0,0 +1,54 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexSettingsDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class PlexSettingsDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Ip).Description("The IP address of the Plex Server").Required(true); + with.Property(x => x.Port).Description("The Port address of the Plex Server").Required(true).Default(32400); + with.Property(x => x.Ssl).Description("Enable SSL").Required(false).Default(false); + with.Property(x => x.FullUri).Description("Internal Property").Required(false); + + with.Property(x => x.SubDir).Description("Subdir/BaseUrl of Plex").Required(false); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/RequestedModelDataProvider.cs b/PlexRequests.UI/ModelDataProviders/RequestedModelDataProvider.cs new file mode 100644 index 000000000..532097590 --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/RequestedModelDataProvider.cs @@ -0,0 +1,72 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: RequestedModelDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Store; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class RequestedModelDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Title).Description("The requests title e.g. Star Wars Episode III").Required(true); + with.Property(x => x.AdminNote).Description("A note left by the administrator"); + with.Property(x => x.Approved).Description("true or false if the request is approved").Required(true).Default(false); + with.Property(x => x.ArtistId).Description("The artist ID (if this request is for Headphones then it is required)"); + with.Property(x => x.ArtistName).Description("The artist name (if this request is for Headphones then it is required)"); + with.Property(x => x.Available).Description("If the request is available on Plex").Default(false); + with.Property(x => x.CanApprove).Description("Ignore"); + with.Property(x => x.ImdbId).Description("The IMDB id of the request").Required(true); + with.Property(x => x.Issues) + .Description( + "The issue type, None = 99, WrongAudio = 0, NoSubtitles = 1, WrongContent = 2, PlaybackIssues = 3, Other = 4. Use Other(4) when leaving an issue note"); + with.Property(x => x.MusicBrainzId).Description("The MusicBrainz ID of the album request (if this request is for Headphones then it is required)"); + with.Property(x => x.OtherMessage) + .Description("The issue message left by the user. The Issues property needs to be set to Other (4) for this to work correctly"); + with.Property(x => x.PosterPath).Description("The poster path for the request").Required(true); + with.Property(x => x.ProviderId) + .Description("The TVMaze/TheMovieDB Id for the request depending if it's a movie request or Tv request") + .Required(true); + with.Property(x => x.ReleaseDate).Description("The release date of the request").Required(true); + with.Property(x => x.RequestedDate) + .Description("The date if the request, if this is not set, the request date will be set at the time of the Api call"); + with.Property(x => x.RequestedUsers).Description("A collection of the requested users").Required(true); + with.Property(x => x.Type).Description("The type of request: Movie = 0, TvShow = 1, Album = 2").Required(true); + with.Property(x => x.Id).Description("The request Id (Only use for deleting)"); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/SickRageDataProvider.cs b/PlexRequests.UI/ModelDataProviders/SickRageDataProvider.cs new file mode 100644 index 000000000..8906a991f --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/SickRageDataProvider.cs @@ -0,0 +1,56 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SickRageDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class SickRageDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Ip).Description("The IP address of SickRage").Required(true); + with.Property(x => x.Port).Description("The Port address of SickRage").Required(true).Default(5050); + with.Property(x => x.Ssl).Description("Enable SSL").Required(false).Default(false); + with.Property(x => x.FullUri).Description("Internal Property").Required(false); + + with.Property(x => x.SubDir).Description("Subdir/BaseUrl of SickRage").Required(false); + with.Property(x => x.ApiKey).Description("SickRage's API key").Required(true); + with.Property(x => x.QualityProfile).Description("SickRage's quality profile").Required(false); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/SonarrSettingsDataProvider.cs b/PlexRequests.UI/ModelDataProviders/SonarrSettingsDataProvider.cs new file mode 100644 index 000000000..b1019eb58 --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/SonarrSettingsDataProvider.cs @@ -0,0 +1,60 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SonarrSettingsDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class SonarrSettingsDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.Ip).Description("The IP address of Sonarr").Required(true); + with.Property(x => x.Port).Description("The Port address of Sonarr").Required(true).Default(5050); + with.Property(x => x.Ssl).Description("Enable SSL").Required(false).Default(false); + with.Property(x => x.FullUri).Description("Internal Property").Required(false); + + with.Property(x => x.SubDir).Description("Subdir/BaseUrl of Sonarr").Required(false); + with.Property(x => x.ApiKey).Description("Sonarr's API key").Required(true); + with.Property(x => x.QualityProfile).Description("Sonarr's quality profile").Required(true); + + with.Property(x => x.SeasonFolders).Description("Sonarr's season folders").Required(false); + + with.Property(x => x.RootPath).Description("Sonarr's root path").Required(false); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/ModelDataProviders/UserUpdateViewModelDataProvider.cs b/PlexRequests.UI/ModelDataProviders/UserUpdateViewModelDataProvider.cs new file mode 100644 index 000000000..5f9823496 --- /dev/null +++ b/PlexRequests.UI/ModelDataProviders/UserUpdateViewModelDataProvider.cs @@ -0,0 +1,51 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UserUpdateViewModelDataProvider.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Swagger; +using Nancy.Swagger.Services; + +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.ModelDataProviders +{ + public class UserUpdateViewModelDataProvider : ISwaggerModelDataProvider + { + /// + /// Gets the model data for the api documentation. + /// + /// + public SwaggerModelData GetModelData() + { + return SwaggerModelData.ForType( + with => + { + with.Property(x => x.CurrentPassword).Description("The users current password").Required(true); + + with.Property(x => x.NewPassword).Description("The users new password that we will change it to").Required(true); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Models/ApiModel.cs b/PlexRequests.UI/Models/ApiModel.cs new file mode 100644 index 000000000..963a2adc6 --- /dev/null +++ b/PlexRequests.UI/Models/ApiModel.cs @@ -0,0 +1,12 @@ +using System; + +namespace PlexRequests.UI +{ + public class ApiModel + { + public T Data{ get; set; } + public bool Error{get;set;} + public string ErrorMessage{ get; set; } + } +} + diff --git a/PlexRequests.UI/Models/JsonResponseModel.cs b/PlexRequests.UI/Models/JsonResponseModel.cs index f272b023b..affaa3bde 100644 --- a/PlexRequests.UI/Models/JsonResponseModel.cs +++ b/PlexRequests.UI/Models/JsonResponseModel.cs @@ -30,7 +30,5 @@ namespace PlexRequests.UI.Models { public bool Result { get; set; } public string Message { get; set; } - public string BaseUrl { get; set; } - public bool HasBase => !string.IsNullOrEmpty(BaseUrl); } } \ No newline at end of file diff --git a/PlexRequests.UI/Models/JsonUpdateAvailableModel.cs b/PlexRequests.UI/Models/JsonUpdateAvailableModel.cs new file mode 100644 index 000000000..38931f86a --- /dev/null +++ b/PlexRequests.UI/Models/JsonUpdateAvailableModel.cs @@ -0,0 +1,33 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: JsonUpdateAvailableModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace PlexRequests.UI.Models +{ + public class JsonUpdateAvailableModel + { + public bool UpdateAvailable { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Models/RequestViewModel.cs b/PlexRequests.UI/Models/RequestViewModel.cs index e5dc09746..136c511aa 100644 --- a/PlexRequests.UI/Models/RequestViewModel.cs +++ b/PlexRequests.UI/Models/RequestViewModel.cs @@ -38,7 +38,8 @@ namespace PlexRequests.UI.Models public string Title { get; set; } public string PosterPath { get; set; } public DateTime ReleaseDate { get; set; } - public long ReleaseDateTicks { get; set; } + public bool Released { get; set; } + public long ReleaseDateTicks { get; set; } public RequestType Type { get; set; } public string Status { get; set; } public bool Approved { get; set; } diff --git a/PlexRequests.UI/Models/UserManagementUsersViewModel.cs b/PlexRequests.UI/Models/UserManagementUsersViewModel.cs new file mode 100644 index 000000000..66bc9974e --- /dev/null +++ b/PlexRequests.UI/Models/UserManagementUsersViewModel.cs @@ -0,0 +1,20 @@ +using System; + +namespace PlexRequests.UI +{ + public class UserManagementUsersViewModel + { + public string Username{get;set;} + public string Claims{get;set;} + public int Id {get;set;} + public string Alias {get;set;} + public UserType Type { get; set;} + } + + public enum UserType + { + PlexUser, + LocalUser + } +} + diff --git a/PlexRequests.UI/Models/UserUpdateViewModel.cs b/PlexRequests.UI/Models/UserUpdateViewModel.cs new file mode 100644 index 000000000..550c2381b --- /dev/null +++ b/PlexRequests.UI/Models/UserUpdateViewModel.cs @@ -0,0 +1,34 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UserUpdateViewModel.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +namespace PlexRequests.UI.Models +{ + public class UserUpdateViewModel + { + public string CurrentPassword { get; set; } + public string NewPassword { get; set; } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/AdminModule.cs b/PlexRequests.UI/Modules/AdminModule.cs index 1650c4ed4..ee7bcb0b8 100644 --- a/PlexRequests.UI/Modules/AdminModule.cs +++ b/PlexRequests.UI/Modules/AdminModule.cs @@ -23,6 +23,10 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ +using System.Net; +using PlexRequests.Helpers.Exceptions; + + #endregion using System.Collections.Generic; @@ -50,6 +54,7 @@ using PlexRequests.Store.Repository; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; using System; +using System.Diagnostics; using Nancy.Json; using Nancy.Security; @@ -68,6 +73,7 @@ namespace PlexRequests.UI.Modules private ISettingsService PushbulletService { get; } private ISettingsService PushoverService { get; } private ISettingsService HeadphonesService { get; } + private ISettingsService LogService { get; } private IPlexApi PlexApi { get; } private ISonarrApi SonarrApi { get; } private IPushbulletApi PushbulletApi { get; } @@ -95,7 +101,8 @@ namespace PlexRequests.UI.Modules IRepository logsRepo, INotificationService notify, ISettingsService headphones, - ICacheProvider cache) : base("admin") + ISettingsService logs, + ICacheProvider cache) : base("admin", prService) { PrService = prService; CpService = cpService; @@ -114,11 +121,11 @@ namespace PlexRequests.UI.Modules PushoverApi = pushoverApi; NotificationService = notify; HeadphonesService = headphones; + LogService = logs; Cache = cache; -#if !DEBUG - this.RequiresAuthentication(); -#endif + this.RequiresClaims(UserClaims.Admin); + Get["/"] = _ => Admin(); Get["/authentication"] = _ => Authentication(); @@ -165,6 +172,10 @@ namespace PlexRequests.UI.Modules Get["/headphones"] = _ => Headphones(); Post["/headphones"] = _ => SaveHeadphones(); + + Post["/createapikey"] = x => CreateApiKey(); + + Post["/autoupdate"] = x => AutoUpdate(); } private Negotiator Authentication() @@ -206,10 +217,23 @@ namespace PlexRequests.UI.Modules private Response SaveAdmin() { var model = this.Bind(); + var valid = this.Validate (model); + if (!valid.IsValid) { + return Response.AsJson(valid.SendJsonError()); + } - PrService.SaveSettings(model); + if (!string.IsNullOrWhiteSpace (model.BaseUrl)) { + if (model.BaseUrl.StartsWith ("/") || model.BaseUrl.StartsWith ("\\")) + { + model.BaseUrl = model.BaseUrl.Remove (0, 1); + } + } + var result = PrService.SaveSettings(model); + if (result) { + return Response.AsJson (new JsonResponseModel{ Result = true }); + } - return Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/admin" : "~/admin"); + return Response.AsJson (new JsonResponseModel{ Result = false, Message = "We could not save to the database, please try again" }); } private Response RequestAuthToken() @@ -254,21 +278,30 @@ namespace PlexRequests.UI.Modules var token = settings?.PlexAuthToken; if (token == null) { - return Response.AsJson(string.Empty); + return Response.AsJson(new { Result = true, Users = string.Empty }); } - var users = PlexApi.GetUsers(token); - if (users == null) - { - return Response.AsJson(string.Empty); - } - if (users.User == null || users.User?.Length == 0) - { - return Response.AsJson(string.Empty); - } + try { + var users = PlexApi.GetUsers(token); + if (users == null) + { + return Response.AsJson(string.Empty); + } + if (users.User == null || users.User?.Length == 0) + { + return Response.AsJson(string.Empty); + } - var usernames = users.User.Select(x => x.Username); - return Response.AsJson(usernames); + var usernames = users.User.Select(x => x.Title); + return Response.AsJson(new {Result = true, Users = usernames}); + } catch (Exception ex) { + Log.Error (ex); + if (ex is WebException || ex is ApiRequestException) { + return Response.AsJson (new { Result = false, Message ="Could not load the user list! We have connectivity problems connecting to Plex, Please ensure we can access Plex.Tv, The error has been logged." }); + } + + return Response.AsJson (new { Result = false, Message = ex.Message}); + } } private Negotiator CouchPotato() @@ -292,8 +325,8 @@ namespace PlexRequests.UI.Modules } var result = CpService.SaveSettings(couchPotatoSettings); - return Response.AsJson(result - ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for CouchPotato!" } + return Response.AsJson(result + ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for CouchPotato!" } : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); } @@ -426,7 +459,7 @@ namespace PlexRequests.UI.Modules finally { NotificationService.UnSubscribe(new EmailMessageNotification(EmailService)); - } + } return Response.AsJson(new JsonResponseModel { Result = true, Message = "Successfully sent a test Email Notification!" }); } @@ -461,11 +494,25 @@ namespace PlexRequests.UI.Modules { var checker = new StatusChecker(); var status = checker.GetStatus(); - var md = new Markdown(); + var md = new Markdown(new MarkdownOptions { AutoNewLines = true }); status.ReleaseNotes = md.Transform(status.ReleaseNotes); return View["Status", status]; } + private Response AutoUpdate() + { + var url = Request.Form["url"]; + + var startInfo = Type.GetType("Mono.Runtime") != null + ? new ProcessStartInfo("mono PlexRequests.Updater.exe") { Arguments = url } + : new ProcessStartInfo("PlexRequests.Updater.exe") { Arguments = url }; + + Process.Start(startInfo); + + Environment.Exit(0); + return Nancy.Response.NoBody; + } + private Negotiator PushbulletNotifications() { var settings = PushbulletService.GetSettings(); @@ -620,7 +667,7 @@ namespace PlexRequests.UI.Modules { JsonSettings.MaxJsonLength = int.MaxValue; var allLogs = LogsRepo.GetAll().OrderByDescending(x => x.Id).Take(200); - var model = new DatatablesModel {Data = new List()}; + var model = new DatatablesModel { Data = new List() }; foreach (var l in allLogs) { l.DateString = l.Date.ToString("G"); @@ -637,9 +684,17 @@ namespace PlexRequests.UI.Modules private Response UpdateLogLevels(int level) { + var settings = LogService.GetSettings(); + + // apply the level var newLevel = LogLevel.FromOrdinal(level); LoggingHelper.ReconfigureLogLevel(newLevel); - return Response.AsJson(new JsonResponseModel { Result = true, Message = $"The new log level is now {newLevel}"}); + + //save the log settings + settings.Level = level; + LogService.SaveSettings(settings); + + return Response.AsJson(new JsonResponseModel { Result = true, Message = $"The new log level is now {newLevel}" }); } private Negotiator Headphones() @@ -662,11 +717,23 @@ namespace PlexRequests.UI.Modules Log.Trace(settings.DumpJson()); var result = HeadphonesService.SaveSettings(settings); - + Log.Info("Saved headphones settings, result: {0}", result); return Response.AsJson(result ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Headphones!" } : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); } + + private Response CreateApiKey() + { + this.RequiresClaims(UserClaims.Admin); + var apiKey = Guid.NewGuid().ToString("N"); + var settings = PrService.GetSettings(); + + settings.ApiKey = apiKey; + PrService.SaveSettings(settings); + + return Response.AsJson(apiKey); + } } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/AdminNotificationsModule.cs b/PlexRequests.UI/Modules/AdminNotificationsModule.cs new file mode 100644 index 000000000..26565bc95 --- /dev/null +++ b/PlexRequests.UI/Modules/AdminNotificationsModule.cs @@ -0,0 +1,130 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: AdminNotificationsModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; + +using Nancy; +using Nancy.ModelBinding; +using Nancy.Responses.Negotiation; +using Nancy.Security; +using Nancy.Validation; + +using NLog; + +using PlexRequests.Api.Interfaces; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.Services.Interfaces; +using PlexRequests.Services.Notification; +using PlexRequests.UI.Helpers; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class AdminNotificationsModule : BaseModule + { + public AdminNotificationsModule(ISettingsService prService, ISettingsService slackSettings, + INotificationService notify, ISlackApi slackApi) : base("admin", prService) + { + this.RequiresClaims(UserClaims.Admin); + + SlackSettings = slackSettings; + NotificationService = notify; + SlackApi = slackApi; + + Post["/testslacknotification"] = _ => TestSlackNotification(); + + Get["/slacknotification"] = _ => SlackNotifications(); + Post["/slacknotification"] = _ => SaveSlackNotifications(); + } + private ISettingsService SlackSettings { get; } + private INotificationService NotificationService { get; } + private ISlackApi SlackApi { get; } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + private Response TestSlackNotification() + { + var settings = this.BindAndValidate(); + if (!ModelValidationResult.IsValid) + { + return Response.AsJson(ModelValidationResult.SendJsonError()); + } + var notificationModel = new NotificationModel + { + NotificationType = NotificationType.Test, + DateTime = DateTime.Now + }; + try + { + NotificationService.Subscribe(new SlackNotification(SlackApi,SlackSettings)); + settings.Enabled = true; + NotificationService.Publish(notificationModel, settings); + Log.Info("Sent slack notification test"); + } + catch (Exception e) + { + Log.Error(e,"Failed to subscribe and publish test Slack Notification"); + } + finally + { + NotificationService.UnSubscribe(new SlackNotification(SlackApi, SlackSettings)); + } + return Response.AsJson(new JsonResponseModel { Result = true, Message = "Successfully sent a test Slack Notification! If you do not receive it please check the logs." }); + } + + private Negotiator SlackNotifications() + { + var settings = SlackSettings.GetSettings(); + return View["SlackNotifications", settings]; + } + + private Response SaveSlackNotifications() + { + var settings = this.BindAndValidate(); + if (!ModelValidationResult.IsValid) + { + return Response.AsJson(ModelValidationResult.SendJsonError()); + } + + var result = SlackSettings.SaveSettings(settings); + if (settings.Enabled) + { + NotificationService.Subscribe(new SlackNotification(SlackApi, SlackSettings)); + } + else + { + NotificationService.UnSubscribe(new SlackNotification(SlackApi, SlackSettings)); + } + + Log.Info("Saved slack settings, result: {0}", result); + return Response.AsJson(result + ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Slack Notifications!" } + : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiDocsModule.cs b/PlexRequests.UI/Modules/ApiDocsModule.cs new file mode 100644 index 000000000..94dbaeda5 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiDocsModule.cs @@ -0,0 +1,46 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiDocsModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy; +using Nancy.Responses.Negotiation; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Modules +{ + public class ApiDocsModule : BaseModule + { + public ApiDocsModule(ISettingsService pr) : base("apidocs", pr) + { + Get["/"] = x => Documentation(); + } + public Negotiator Documentation() + { + return View["Index"]; + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiRequestMetadataModule.cs b/PlexRequests.UI/Modules/ApiRequestMetadataModule.cs new file mode 100644 index 000000000..732ad356e --- /dev/null +++ b/PlexRequests.UI/Modules/ApiRequestMetadataModule.cs @@ -0,0 +1,115 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiRequestMetadataModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Collections.Generic; + +using Nancy.Metadata.Modules; +using Nancy.Swagger; + +using PlexRequests.Store; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiRequestMetadataModule: MetadataModule + { + public ApiRequestMetadataModule() + { + Describe["GetRequests"] = description => description.AsSwagger(with => + { + with.ResourcePath("/requests"); + with.Summary("The list of requests"); + + with.Notes("This returns a list of requests"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.Model>>(); + }); + + Describe["GetRequest"] = description => description.AsSwagger(with => + { + with.ResourcePath("/requests/{id}"); + with.Summary("Get's a single request"); + + with.Notes("This returns a single request"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.PathParam("id"); + with.Model>>(); + }); + + Describe["PostRequests"] = description => description.AsSwagger(with => + { + with.ResourcePath("/requests"); + with.Summary("Create a new request"); + with.Model>(); + with.BodyParam("The request", true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.Notes("Creates a new request"); + }); + + Describe["PutRequests"] = description => description.AsSwagger(with => + { + with.ResourcePath("/requests"); + with.Summary("Updates an existing request"); + with.Model>(); + with.BodyParam("The request", true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.Notes("Updates an existing request e.g. Add a issue to the request"); + }); + + Describe["DeleteRequests"] = description => description.AsSwagger(with => + { + with.ResourcePath("/requests/{id}"); + with.Summary("Deletes an existing request"); + with.Model>(); + with.PathParam("id", required:true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.Notes("Deletes an existing request. If the request doesn't exist we will return an error."); + }); + + Describe["GetApiKey"] = description => description.AsSwagger(with => + { + with.ResourcePath("/apikey"); + with.Summary("Gets the Api Key for Plex Requests"); + with.Model>(); + with.QueryParam("username", required:true ); + with.QueryParam("password", required: true ); + with.Notes("Get's the current api key for the application"); + }); + + Describe["PutCredentials"] = description => description.AsSwagger(with => + { + with.ResourcePath("/credentials/{username}"); + with.Summary("Sets a new password for the user"); + with.Model>(); + with.PathParam("username", required:true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("User update view model", true); + with.Notes("Sets a new password for the user"); + }); + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiRequestModule.cs b/PlexRequests.UI/Modules/ApiRequestModule.cs new file mode 100644 index 000000000..6e56ce6ff --- /dev/null +++ b/PlexRequests.UI/Modules/ApiRequestModule.cs @@ -0,0 +1,167 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiRequestModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; + +using Nancy; +using Nancy.Extensions; +using Nancy.ModelBinding; +using Nancy.Validation; + +using Newtonsoft.Json; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiRequestModule : BaseApiModule + { + public ApiRequestModule(IRequestService service, ISettingsService pr) : base("api", pr) + { + Get["GetRequests","/requests"] = x => GetRequests(); + Get["GetRequest","/requests/{id}"] = x => GetSingleRequests(x); + Post["PostRequests", "/requests"] = x => CreateRequest(); + Put["PutRequests", "/requests"] = x => UpdateRequest(); + Delete["DeleteRequests", "/requests/{id}"] = x => DeleteRequest(x); + + + RequestService = service; + SettingsService = pr; + } + + private IRequestService RequestService { get; } + private ISettingsService SettingsService { get; } + + public Response GetRequests() + { + var apiModel = new ApiModel> { Data = new List() }; + + var requests = RequestService.GetAll(); + apiModel.Data.AddRange(requests); + + return ReturnReponse(apiModel); + } + + public Response GetSingleRequests(dynamic x) + { + var id = (int)x.id; + var apiModel = new ApiModel> { Data = new List() }; + + var requests = RequestService.Get(id); + if (string.IsNullOrEmpty(requests.Title)) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Request does not exist"; + return ReturnReponse(apiModel); + } + apiModel.Data.Add(requests); + + return ReturnReponse(apiModel); + } + + public Response CreateRequest() + { + var request = JsonConvert.DeserializeObject(Request.Body.AsString()); + var a = this.Validate(request); + if (!a.IsValid) + { + return ReturnValidationReponse(a); + } + + var apiModel = new ApiModel(); + var result = RequestService.AddRequest(request); + + if (result == -1) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not insert the new request into the database. Internal error."; + return ReturnReponse(apiModel); + } + + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + + public Response UpdateRequest() + { + var request = JsonConvert.DeserializeObject(Request.Body.AsString()); + var a = this.Validate(request); + if (!a.IsValid) + { + return ReturnValidationReponse(a); + } + + + var apiModel = new ApiModel(); + var result = RequestService.UpdateRequest(request); + + if (!result) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not update the request into the database. Internal error."; + return ReturnReponse(apiModel); + } + + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + + public Response DeleteRequest(dynamic x) + { + var id = (int)x.id; + var apiModel = new ApiModel(); + + try + { + var exisitingRequest = RequestService.Get(id); + if (string.IsNullOrEmpty(exisitingRequest.Title)) + { + apiModel.Error = true; + apiModel.ErrorMessage = $"The request id {id} does not exist"; + return ReturnReponse(apiModel); + } + RequestService.DeleteRequest(exisitingRequest); + apiModel.Data = true; + + return ReturnReponse(apiModel); + } + catch (Exception) + { + apiModel.Error = true; + apiModel.ErrorMessage = "Could not delete the request from the database. Internal error."; + return ReturnReponse(apiModel); + } + } + + + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs b/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs new file mode 100644 index 000000000..1c7e41b38 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiSettingsMetadataModule.cs @@ -0,0 +1,174 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiSettingsMetadataModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Metadata.Modules; +using Nancy.Swagger; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Modules +{ + public class ApiSettingsMetadataModule: MetadataModule + { + public ApiSettingsMetadataModule() + { + Describe["GetAuthSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/authentication"); + with.Summary("Gets the authentication settings saved in the application"); + with.Model>(); + with.Notes("Gets the authentication settings saved in the application"); + + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostAuthSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/authentication"); + with.Summary("Saves the authentication settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("Authentication settings", true); + with.Notes("Saves the authentication settings saved in the application"); + }); + + Describe["GetPlexSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/plex"); + with.Summary("Gets the Plex settings saved in the application"); + with.Model>(); + with.Notes("Gets the Plex settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostPlexSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/plex"); + with.Summary("Saves the Plex settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("Plex settings", true); + with.Notes("Saves the Plex settings saved in the application"); + }); + + + Describe["GetCouchPotatoSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/couchpotato"); + with.Summary("Gets the CouchPotato settings saved in the application"); + with.Model>(); + with.Notes("Gets the CouchPotato settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostCouchPotatoSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/couchpotato"); + with.Summary("Saves the CouchPotato settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("CouchPotato settings", true); + with.Notes("Saves the CouchPotato settings saved in the application"); + }); + + Describe["GetSonarrSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/sonarr"); + with.Summary("Gets the sonarr settings saved in the application"); + with.Model>(); + with.Notes("Gets the sonarr settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostSonarrSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/sonarr"); + with.Summary("Saves the sonarr settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("sonarr settings", true); + with.Notes("Saves the sonarr settings saved in the application"); + }); + + Describe["GetSickRageSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/sickrage"); + with.Summary("Gets the SickRage settings saved in the application"); + with.Model>(); + with.Notes("Gets the SickRage settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostSickRageSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/sickrage"); + with.Summary("Saves the SickRage settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("SickRage settings", true); + with.Notes("Saves the sickrage settings saved in the application"); + }); + + Describe["GetHeadphonesSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/headphones"); + with.Summary("Gets the headphones settings saved in the application"); + with.Model>(); + with.Notes("Gets the headphones settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostHeadphonesSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/sickrage"); + with.Summary("Saves the headphones settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("headphones settings", true); + with.Notes("Saves the headphones settings saved in the application"); + }); + + Describe["GetPlexRequestSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/plexrequest"); + with.Summary("Gets the plexrequest settings saved in the application"); + with.Model>(); + with.Notes("Gets the plexrequest settings saved in the application"); + with.QueryParam("apikey", "The Api Key found in the settings", true); + }); + + Describe["PostPlexRequestSettings"] = description => description.AsSwagger(with => + { + with.ResourcePath("/settings/plexrequest"); + with.Summary("Saves the plexrequest settings saved in the application"); + with.Model>(); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("plexrequest settings", true); + with.Notes("Saves the plexrequest settings saved in the application"); + }); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiSettingsModule.cs b/PlexRequests.UI/Modules/ApiSettingsModule.cs new file mode 100644 index 000000000..4d84a2c4a --- /dev/null +++ b/PlexRequests.UI/Modules/ApiSettingsModule.cs @@ -0,0 +1,358 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Web.UI.WebControls; + +using Nancy; +using Nancy.Extensions; +using Nancy.ModelBinding; +using Nancy.Validation; + +using Newtonsoft.Json; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Modules +{ + public class ApiSettingsModule : BaseApiModule + { + public ApiSettingsModule(ISettingsService pr, ISettingsService auth, + ISettingsService plexSettings, ISettingsService cp, + ISettingsService sonarr, ISettingsService sr, ISettingsService hp) : base("api", pr) + { + Get["GetAuthSettings", "/settings/authentication"] = x => GetAuthSettings(); + Post["PostAuthSettings", "/settings/authentication"] = x => PostAuthSettings(); + + Get["GetPlexRequestSettings", "/settings/plexrequest"] = x => GetPrSettings(); + Post["PostPlexRequestSettings", "/settings/plexrequest"] = x => PostPrSettings(); + + Get["GetPlexSettings", "/settings/plex"] = x => GetPlexSettings(); + Post["PostPlexSettings", "/settings/plex"] = x => PostPlexSettings(); + + Get["GetCouchPotatoSettings", "/settings/couchpotato"] = x => GetCpSettings(); + Post["PostCouchPotatoSettings", "/settings/couchpotato"] = x => PostCpSettings(); + + Get["GetSonarrSettings", "/settings/sonarr"] = x => GetSonarrSettings(); + Post["PostSonarrSettings", "/settings/sonarr"] = x => PostSonarrSettings(); + + Get["GetSickRageSettings", "/settings/sickrage"] = x => GetSickRageSettings(); + Post["PostSickRageSettings", "/settings/sickrage"] = x => PostSickRageSettings(); + + Get["GetHeadphonesSettings", "/settings/headphones"] = x => GetHeadphonesSettings(); + Post["PostHeadphonesSettings", "/settings/headphones"] = x => PostHeadphonesSettings(); + + SettingsService = pr; + AuthSettings = auth; + PlexSettings = plexSettings; + CpSettings = cp; + SonarrSettings = sonarr; + SickRageSettings = sr; + HeadphonesSettings = hp; + } + + private ISettingsService SettingsService { get; } + private ISettingsService AuthSettings { get; } + private ISettingsService PlexSettings { get; } + private ISettingsService CpSettings { get; } + private ISettingsService SonarrSettings { get; } + private ISettingsService SickRageSettings { get; } + private ISettingsService HeadphonesSettings { get; } + + private Response GetPrSettings() + { + var model = new ApiModel(); + try + { + var settings = SettingsService.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostPrSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = SettingsService.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + private Response GetAuthSettings() + { + var model = new ApiModel(); + try + { + var settings = AuthSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostAuthSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = AuthSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + private Response GetPlexSettings() + { + var model = new ApiModel(); + try + { + var settings = PlexSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostPlexSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = PlexSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + private Response GetCpSettings() + { + var model = new ApiModel(); + try + { + var settings = CpSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostCpSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = CpSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + private Response GetSonarrSettings() + { + var model = new ApiModel(); + try + { + var settings = SonarrSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostSonarrSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = SonarrSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + + private Response GetSickRageSettings() + { + var model = new ApiModel(); + try + { + var settings = SickRageSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostSickRageSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = SickRageSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + private Response GetHeadphonesSettings() + { + var model = new ApiModel(); + try + { + var settings = HeadphonesSettings.GetSettings(); + model.Data = settings; + return ReturnReponse(model); + } + catch (Exception e) + { + model.ErrorMessage = e.Message; + model.Error = true; + return ReturnReponse(model); + } + } + + private Response PostHeadphonesSettings() + { + var newSettings = JsonConvert.DeserializeObject(Request.Body.AsString()); + var result = this.Validate(newSettings); + if (!result.IsValid) + { + return ReturnValidationReponse(result); + } + + var model = new ApiModel(); + var settings = HeadphonesSettings.SaveSettings(newSettings); + if (settings) + { + model.Data = true; + return ReturnReponse(model); + } + + model.Error = true; + model.ErrorMessage = "Could not update the settings"; + return ReturnReponse(model); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiUserMetadataModule.cs b/PlexRequests.UI/Modules/ApiUserMetadataModule.cs new file mode 100644 index 000000000..b581e7bcd --- /dev/null +++ b/PlexRequests.UI/Modules/ApiUserMetadataModule.cs @@ -0,0 +1,61 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiUserMetadataModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using Nancy.Metadata.Modules; +using Nancy.Swagger; + +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiUserMetadataModule: MetadataModule + { + public ApiUserMetadataModule() + { + Describe["GetApiKey"] = description => description.AsSwagger(with => + { + with.ResourcePath("/apikey"); + with.Summary("Gets the Api Key for Plex Requests"); + with.Model>(); + with.QueryParam("username", required:true ); + with.QueryParam("password", required: true ); + with.Notes("Get's the current api key for the application"); + }); + + Describe["PutCredentials"] = description => description.AsSwagger(with => + { + with.ResourcePath("/credentials/{username}"); + with.Summary("Sets a new password for the user"); + with.Model>(); + with.PathParam("username", required:true); + with.QueryParam("apikey", "The Api Key found in the settings", true); + with.BodyParam("User update view model", true); + with.Notes("Sets a new password for the user"); + }); + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApiUserModule.cs b/PlexRequests.UI/Modules/ApiUserModule.cs new file mode 100644 index 000000000..545558401 --- /dev/null +++ b/PlexRequests.UI/Modules/ApiUserModule.cs @@ -0,0 +1,104 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: ApiModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Collections.Generic; + +using Nancy; +using Nancy.ModelBinding; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class ApiUserModule : BaseApiModule + { + public ApiUserModule(ISettingsService pr, ICustomUserMapper m) : base("api", pr) + { + + Put["PutCredentials", "/credentials/{username}"] = x => ChangePassword(x); + + Get["GetApiKey", "/apikey"] = x => GetApiKey(); + + SettingsService = pr; + UserMapper = m; + } + + private ISettingsService SettingsService { get; } + private ICustomUserMapper UserMapper { get; } + + public Response ChangePassword(dynamic x) + { + var username = (string)x.username; + var userModel = this.BindAndValidate(); + + if (!ModelValidationResult.IsValid) + { + return ReturnValidationReponse(ModelValidationResult); + } + + var valid = UserMapper.ValidateUser(username, userModel.CurrentPassword); + if (valid == null) + { + var errorModel = new ApiModel { Error = true, ErrorMessage = "Incorrect username or password" }; + return ReturnReponse(errorModel); + } + var result = UserMapper.UpdatePassword(username, userModel.CurrentPassword, userModel.NewPassword); + + if (!result) + { + var errorModel = new ApiModel { Error = true, ErrorMessage = "Could not update the password. " }; + return ReturnReponse(errorModel); + } + + + var model = new ApiModel { Data = "Successfully updated the password"}; + return ReturnReponse(model); + } + public Response GetApiKey() + { + var user = Request.Query["username"]; + var password = Request.Query["password"]; + var result = UserMapper.ValidateUser(user, password); + var model = new ApiModel(); + if (result == null) + { + model.Error = true; + model.ErrorMessage = "Incorrect username or password"; + return ReturnReponse(model); + } + + var settings = SettingsService.GetSettings(); + model.Data = settings.ApiKey; + + return ReturnReponse(model); + } + + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/ApplicationTesterModule.cs b/PlexRequests.UI/Modules/ApplicationTesterModule.cs index 69e2df08d..69cf1575c 100644 --- a/PlexRequests.UI/Modules/ApplicationTesterModule.cs +++ b/PlexRequests.UI/Modules/ApplicationTesterModule.cs @@ -44,7 +44,7 @@ namespace PlexRequests.UI.Modules { public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi, - ISettingsService authSettings, ISickRageApi srApi, IHeadphonesApi hpApi) : base("test") + ISettingsService authSettings, ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService pr) : base("test", pr) { this.RequiresAuthentication(); @@ -87,7 +87,7 @@ namespace PlexRequests.UI.Modules : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to CouchPotato, please check your settings." }); } - catch (ApplicationException e) // Exceptions are expected if we cannot connect so we will just log and swallow them. + catch (Exception e) // Exceptions are expected if we cannot connect so we will just log and swallow them. { Log.Warn("Exception thrown when attempting to get CP's status: "); Log.Warn(e); @@ -116,7 +116,7 @@ namespace PlexRequests.UI.Modules : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Sonarr, please check your settings." }); } - catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. + catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. { Log.Warn("Exception thrown when attempting to get Sonarr's status: "); Log.Warn(e); @@ -150,7 +150,7 @@ namespace PlexRequests.UI.Modules : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." }); } - catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. + catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. { Log.Warn("Exception thrown when attempting to get Plex's status: "); Log.Warn(e); @@ -179,7 +179,7 @@ namespace PlexRequests.UI.Modules : Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to SickRage, please check your settings." }); } - catch (ApplicationException e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. + catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them. { Log.Warn("Exception thrown when attempting to get SickRage's status: "); Log.Warn(e); @@ -214,7 +214,7 @@ namespace PlexRequests.UI.Modules } return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Headphones, please check your settings." }); } - catch (ApplicationException e) + catch (Exception e) { Log.Warn("Exception thrown when attempting to get Headphones's status: "); Log.Warn(e); diff --git a/PlexRequests.UI/Modules/ApprovalModule.cs b/PlexRequests.UI/Modules/ApprovalModule.cs index e6cb97c06..c0546a70c 100644 --- a/PlexRequests.UI/Modules/ApprovalModule.cs +++ b/PlexRequests.UI/Modules/ApprovalModule.cs @@ -48,9 +48,9 @@ namespace PlexRequests.UI.Modules public ApprovalModule(IRequestService service, ISettingsService cpService, ICouchPotatoApi cpApi, ISonarrApi sonarrApi, ISettingsService sonarrSettings, ISickRageApi srApi, ISettingsService srSettings, - ISettingsService hpSettings, IHeadphonesApi hpApi) : base("approval") + ISettingsService hpSettings, IHeadphonesApi hpApi, ISettingsService pr) : base("approval", pr) { - this.RequiresAuthentication(); + this.RequiresClaims(UserClaims.Admin, UserClaims.PowerUser); Service = service; CpService = cpService; @@ -88,10 +88,7 @@ namespace PlexRequests.UI.Modules private Response Approve(int requestId, string qualityId) { Log.Info("approving request {0}", requestId); - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." }); - } + // Get the request from the DB var request = Service.Get(requestId); @@ -258,10 +255,6 @@ namespace PlexRequests.UI.Modules private Response ApproveAllMovies() { - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." }); - } var requests = Service.GetAll().Where(x => x.CanApprove && x.Type == RequestType.Movie); var requestedModels = requests as RequestedModel[] ?? requests.ToArray(); @@ -283,11 +276,6 @@ namespace PlexRequests.UI.Modules private Response ApproveAllTVShows() { - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." }); - } - var requests = Service.GetAll().Where(x => x.CanApprove && x.Type == RequestType.TvShow); var requestedModels = requests as RequestedModel[] ?? requests.ToArray(); if (!requestedModels.Any()) @@ -312,11 +300,6 @@ namespace PlexRequests.UI.Modules /// private Response ApproveAll() { - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot approve any requests." }); - } - var requests = Service.GetAll().Where(x => x.CanApprove); var requestedModels = requests as RequestedModel[] ?? requests.ToArray(); if (!requestedModels.Any()) diff --git a/PlexRequests.UI/Modules/BaseApiModule.cs b/PlexRequests.UI/Modules/BaseApiModule.cs new file mode 100644 index 000000000..c7c1f4fc8 --- /dev/null +++ b/PlexRequests.UI/Modules/BaseApiModule.cs @@ -0,0 +1,121 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: BaseApiModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System.Collections.Generic; +using System.Linq; + +using Nancy; +using Nancy.Validation; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Store; + +namespace PlexRequests.UI.Modules +{ + public abstract class BaseApiModule : BaseModule + { + protected BaseApiModule(ISettingsService s) : base(s) + { + Settings = s; + Before += (ctx) => CheckAuth(); + } + + protected BaseApiModule(string modulePath, ISettingsService s) : base(modulePath, s) + { + Settings = s; + Before += (ctx) => CheckAuth(); + } + + private ISettingsService Settings { get; } + + protected Response ReturnReponse(object result) + { + var queryString = (DynamicDictionary)Context.Request.Query; + dynamic value; + if (queryString.TryGetValue("xml", out value)) + { + if ((bool)value) + { + return Response.AsXml(result); + } + } + return Response.AsJson(result); + } + + protected Response ReturnValidationReponse(ModelValidationResult result) + { + var errors = result.Errors; + var model = new ApiModel> + { + Error = true, + ErrorMessage = "Please view the error messages inside the data node", + Data = new List() + }; + + foreach (var error in errors) + { + model.Data.AddRange(error.Value.Select(x => x.ErrorMessage)); + } + + return ReturnReponse(model); + } + + private Response CheckAuth() + { + if (Request.Path.Contains("api/apikey")) // We do not need the apikey for this call + { + return null; + } + var settings = Settings.GetSettings(); + var apiModel = new ApiModel> { Data = new List() }; + if (!Authenticated(settings)) + { + apiModel.Error = true; + apiModel.ErrorMessage = "ApiKey is invalid or not present, Please use 'apikey' in the querystring."; + return ReturnReponse(apiModel); + } + + return null; + } + + private bool Authenticated(PlexRequestSettings settings) + { + var query = (DynamicDictionary)Context.Request.Query; + dynamic key; + if (!query.TryGetValue("apikey", out key)) + { + return false; + } + if ((string)key == settings.ApiKey) + { + return true; + } + return false; + + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseAuthModule.cs b/PlexRequests.UI/Modules/BaseAuthModule.cs index 3dcf930da..708a4cb49 100644 --- a/PlexRequests.UI/Modules/BaseAuthModule.cs +++ b/PlexRequests.UI/Modules/BaseAuthModule.cs @@ -23,6 +23,9 @@ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ +using System.Linq; + + #endregion using Nancy; @@ -32,10 +35,11 @@ using System; using PlexRequests.Core; using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; namespace PlexRequests.UI.Modules { - public class BaseAuthModule : BaseModule + public abstract class BaseAuthModule : BaseModule { private string _username; private int _dateTimeOffset = -1; @@ -52,6 +56,23 @@ namespace PlexRequests.UI.Modules } } + protected bool IsAdmin + { + get + { + if (Context.CurrentUser == null) + { + return false; + } + var claims = Context.CurrentUser.Claims.ToList(); + if (claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser)) + { + return true; + } + return false; + } + } + protected int DateTimeOffset { get @@ -64,28 +85,30 @@ namespace PlexRequests.UI.Modules } } - public BaseAuthModule() + protected BaseAuthModule(ISettingsService pr) : base(pr) { + Service = pr; Before += (ctx) => CheckAuth(); } - public BaseAuthModule(string modulePath) : base(modulePath) + protected BaseAuthModule(string modulePath, ISettingsService pr) : base(modulePath, pr) { + Service = pr; Before += (ctx) => CheckAuth(); } + private ISettingsService Service { get; } private Response CheckAuth() { - var settings = Locator.Resolve>().GetSettings(); + var settings = Service.GetSettings(); var baseUrl = settings.BaseUrl; var redirectPath = string.IsNullOrEmpty(baseUrl) ? "~/userlogin" : $"~/{baseUrl}/userlogin"; - return Session[SessionKeys.UsernameKey] == null - ? Context.GetRedirect(redirectPath) + return Session[SessionKeys.UsernameKey] == null + ? Context.GetRedirect(redirectPath) : null; } - } } \ No newline at end of file diff --git a/PlexRequests.UI/Modules/BaseModule.cs b/PlexRequests.UI/Modules/BaseModule.cs index 0fbcbd8bb..335fc16f5 100644 --- a/PlexRequests.UI/Modules/BaseModule.cs +++ b/PlexRequests.UI/Modules/BaseModule.cs @@ -28,17 +28,16 @@ using Nancy; using PlexRequests.Core; using PlexRequests.Core.SettingModels; -using PlexRequests.UI.Helpers; namespace PlexRequests.UI.Modules { - public class BaseModule : NancyModule + public abstract class BaseModule : NancyModule { - protected ServiceLocator Locator => ServiceLocator.Instance; protected string BaseUrl { get; set; } - public BaseModule() + + protected BaseModule(ISettingsService settingsService) { - var settings = Locator.Resolve>().GetSettings(); + var settings = settingsService.GetSettings(); var baseUrl = settings.BaseUrl; BaseUrl = baseUrl; @@ -47,9 +46,9 @@ namespace PlexRequests.UI.Modules ModulePath = modulePath; } - public BaseModule(string modulePath) + protected BaseModule(string modulePath, ISettingsService settingsService) { - var settings = Locator.Resolve>().GetSettings(); + var settings = settingsService.GetSettings(); var baseUrl = settings.BaseUrl; BaseUrl = baseUrl; diff --git a/PlexRequests.UI/Modules/IndexModule.cs b/PlexRequests.UI/Modules/IndexModule.cs index 46b54e098..81cdfa7e2 100644 --- a/PlexRequests.UI/Modules/IndexModule.cs +++ b/PlexRequests.UI/Modules/IndexModule.cs @@ -27,11 +27,14 @@ using Nancy; using Nancy.Extensions; +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; + namespace PlexRequests.UI.Modules { public class IndexModule : BaseAuthModule { - public IndexModule() + public IndexModule(ISettingsService pr) : base(pr) { Get["/"] = parameters => Context.GetRedirect(!string.IsNullOrEmpty(BaseUrl) ? $"~/{BaseUrl}/search" : "~/search"); diff --git a/PlexRequests.UI/Modules/LoginModule.cs b/PlexRequests.UI/Modules/LoginModule.cs index 83616a80b..326b7ec13 100644 --- a/PlexRequests.UI/Modules/LoginModule.cs +++ b/PlexRequests.UI/Modules/LoginModule.cs @@ -34,18 +34,21 @@ using Nancy.Responses.Negotiation; using Nancy.Security; using PlexRequests.Core; +using PlexRequests.Core.SettingModels; using PlexRequests.UI.Models; namespace PlexRequests.UI.Modules { public class LoginModule : BaseModule { - public LoginModule() + public LoginModule(ISettingsService pr, ICustomUserMapper m) : base(pr) { + UserMapper = m; Get["/login"] = _ => { { dynamic model = new ExpandoObject(); + model.Redirect = Request.Query.redirect.Value ?? string.Empty; model.Errored = Request.Query.error.HasValue; var adminCreated = UserMapper.DoUsersExist(); model.AdminExists = adminCreated; @@ -61,6 +64,7 @@ namespace PlexRequests.UI.Modules var username = (string)Request.Form.Username; var password = (string)Request.Form.Password; var dtOffset = (int)Request.Form.DateTimeOffset; + var redirect = (string)Request.Form.Redirect; var userId = UserMapper.ValidateUser(username, password); @@ -75,12 +79,10 @@ namespace PlexRequests.UI.Modules } Session[SessionKeys.UsernameKey] = username; Session[SessionKeys.ClientDateTimeOffsetKey] = dtOffset; - if (!string.IsNullOrEmpty(BaseUrl)) - { - - return this.LoginAndRedirect(userId.Value, expiry, $"/{BaseUrl}"); - } - return this.LoginAndRedirect(userId.Value, expiry); + if(redirect.Contains("userlogin")){ + redirect = !string.IsNullOrEmpty(BaseUrl) ? $"/{BaseUrl}/search" : "/search"; + } + return this.LoginAndRedirect(userId.Value, expiry, redirect); }; Get["/register"] = x => @@ -109,6 +111,7 @@ namespace PlexRequests.UI.Modules Get["/changepassword"] = _ => ChangePassword(); Post["/changepassword"] = _ => ChangePasswordPost(); } + private ICustomUserMapper UserMapper { get; } private Negotiator ChangePassword() { diff --git a/PlexRequests.UI/Modules/RequestsModule.cs b/PlexRequests.UI/Modules/RequestsModule.cs index afb98b454..020aab78d 100644 --- a/PlexRequests.UI/Modules/RequestsModule.cs +++ b/PlexRequests.UI/Modules/RequestsModule.cs @@ -59,7 +59,7 @@ namespace PlexRequests.UI.Modules ICouchPotatoApi cpApi, ISonarrApi sonarrApi, ISickRageApi sickRageApi, - ICacheProvider cache) : base("requests") + ICacheProvider cache) : base("requests", prSettings) { Service = service; PrSettings = prSettings; @@ -108,7 +108,6 @@ namespace PlexRequests.UI.Modules private Response GetMovies() // TODO: async await the API calls { var settings = PrSettings.GetSettings(); - var isAdmin = Context.CurrentUser.IsAuthenticated(); List taskList = new List(); @@ -121,7 +120,7 @@ namespace PlexRequests.UI.Modules { dbMovies = t.Result.ToList(); - if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) { dbMovies = dbMovies.Where(x => x.UserHasRequested(Username)).ToList(); } @@ -130,7 +129,7 @@ namespace PlexRequests.UI.Modules List qualities = new List(); - if (isAdmin) + if (IsAdmin) { var cpSettings = CpSettings.GetSettings(); if (cpSettings.Enabled) @@ -163,14 +162,15 @@ namespace PlexRequests.UI.Modules ReleaseDate = movie.ReleaseDate, ReleaseDateTicks = movie.ReleaseDate.Ticks, RequestedDate = movie.RequestedDate, + Released = DateTime.Now > movie.ReleaseDate, RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(movie.RequestedDate, DateTimeOffset).Ticks, Approved = movie.Available || movie.Approved, Title = movie.Title, Overview = movie.Overview, - RequestedUsers = isAdmin ? movie.AllUsers.ToArray() : new string[] { }, + RequestedUsers = IsAdmin ? movie.AllUsers.ToArray() : new string[] { }, ReleaseYear = movie.ReleaseDate.Year.ToString(), Available = movie.Available, - Admin = isAdmin, + Admin = IsAdmin, Issues = movie.Issues.ToString().CamelCaseToWords(), OtherMessage = movie.OtherMessage, AdminNotes = movie.AdminNote, @@ -184,7 +184,6 @@ namespace PlexRequests.UI.Modules private Response GetTvShows() // TODO: async await the API calls { var settings = PrSettings.GetSettings(); - var isAdmin = Context.CurrentUser.IsAuthenticated(); List taskList = new List(); @@ -197,14 +196,14 @@ namespace PlexRequests.UI.Modules { dbTv = t.Result.ToList(); - if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) { dbTv = dbTv.Where(x => x.UserHasRequested(Username)).ToList(); } })); List qualities = new List(); - if (isAdmin) + if (IsAdmin) { var sonarrSettings = SonarrSettings.GetSettings(); if (sonarrSettings.Enabled) @@ -246,13 +245,14 @@ namespace PlexRequests.UI.Modules ReleaseDateTicks = tv.ReleaseDate.Ticks, RequestedDate = tv.RequestedDate, RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(tv.RequestedDate, DateTimeOffset).Ticks, + Released = DateTime.Now > tv.ReleaseDate, Approved = tv.Available || tv.Approved, Title = tv.Title, Overview = tv.Overview, - RequestedUsers = isAdmin ? tv.AllUsers.ToArray() : new string[] { }, + RequestedUsers = IsAdmin ? tv.AllUsers.ToArray() : new string[] { }, ReleaseYear = tv.ReleaseDate.Year.ToString(), Available = tv.Available, - Admin = isAdmin, + Admin = IsAdmin, Issues = tv.Issues.ToString().CamelCaseToWords(), OtherMessage = tv.OtherMessage, AdminNotes = tv.AdminNote, @@ -267,9 +267,8 @@ namespace PlexRequests.UI.Modules private Response GetAlbumRequests() { var settings = PrSettings.GetSettings(); - var isAdmin = Context.CurrentUser.IsAuthenticated(); var dbAlbum = Service.GetAll().Where(x => x.Type == RequestType.Album); - if (settings.UsersCanViewOnlyOwnRequests && !isAdmin) + if (settings.UsersCanViewOnlyOwnRequests && !IsAdmin) { dbAlbum = dbAlbum.Where(x => x.UserHasRequested(Username)); } @@ -288,13 +287,14 @@ namespace PlexRequests.UI.Modules ReleaseDateTicks = album.ReleaseDate.Ticks, RequestedDate = album.RequestedDate, RequestedDateTicks = DateTimeHelper.OffsetUTCDateTime(album.RequestedDate, DateTimeOffset).Ticks, + Released = DateTime.Now > album.ReleaseDate, Approved = album.Available || album.Approved, Title = album.Title, Overview = album.Overview, - RequestedUsers = isAdmin ? album.AllUsers.ToArray() : new string[] { }, + RequestedUsers = IsAdmin ? album.AllUsers.ToArray() : new string[] { }, ReleaseYear = album.ReleaseDate.Year.ToString(), Available = album.Available, - Admin = isAdmin, + Admin = IsAdmin, Issues = album.Issues.ToString().CamelCaseToWords(), OtherMessage = album.OtherMessage, AdminNotes = album.AdminNote, @@ -309,11 +309,8 @@ namespace PlexRequests.UI.Modules } private Response DeleteRequest(int requestid) - { - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot delete any requests." }); - } + { + this.RequiresClaims (UserClaims.Admin); var currentEntity = Service.Get(requestid); Service.DeleteRequest(currentEntity); @@ -360,10 +357,7 @@ namespace PlexRequests.UI.Modules private Response ClearIssue(int requestId) { - if (!Context.CurrentUser.IsAuthenticated()) - { - return Response.AsJson(new JsonResponseModel { Result = false, Message = "You are not an Admin, so you cannot clear any issues." }); - } + this.RequiresClaims (UserClaims.PowerUser, UserClaims.Admin); var originalRequest = Service.Get(requestId); if (originalRequest == null) @@ -380,7 +374,8 @@ namespace PlexRequests.UI.Modules } private Response ChangeRequestAvailability(int requestId, bool available) - { + { + this.RequiresClaims (UserClaims.PowerUser, UserClaims.Admin); var originalRequest = Service.Get(requestId); if (originalRequest == null) { @@ -396,7 +391,8 @@ namespace PlexRequests.UI.Modules } private Response AddNote(int requestId, string noteArea) - { + { + this.RequiresClaims (UserClaims.PowerUser, UserClaims.Admin); var originalRequest = Service.Get(requestId); if (originalRequest == null) { @@ -411,4 +407,4 @@ namespace PlexRequests.UI.Modules : new JsonResponseModel { Result = false, Message = "Could not update the notes, please try again or check the logs" }); } } -} \ No newline at end of file +} diff --git a/PlexRequests.UI/Modules/SearchModule.cs b/PlexRequests.UI/Modules/SearchModule.cs index b7faaa9bc..efae9678a 100644 --- a/PlexRequests.UI/Modules/SearchModule.cs +++ b/PlexRequests.UI/Modules/SearchModule.cs @@ -31,7 +31,6 @@ using System.Linq; using Nancy; using Nancy.Responses.Negotiation; -using Nancy.Security; using NLog; @@ -42,15 +41,18 @@ using PlexRequests.Core; using PlexRequests.Core.SettingModels; using PlexRequests.Helpers; using PlexRequests.Helpers.Exceptions; -using PlexRequests.Services; using PlexRequests.Services.Interfaces; using PlexRequests.Services.Notification; using PlexRequests.Store; using PlexRequests.UI.Helpers; using PlexRequests.UI.Models; using System.Threading.Tasks; -using TMDbLib.Objects.Search; +using System.Windows.Forms; +using Nancy.Extensions; using PlexRequests.Api.Models.Tv; +using PlexRequests.Store.Models; +using PlexRequests.Store.Repository; + using TMDbLib.Objects.General; namespace PlexRequests.UI.Modules @@ -61,9 +63,9 @@ namespace PlexRequests.UI.Modules ISettingsService prSettings, IAvailabilityChecker checker, IRequestService request, ISonarrApi sonarrApi, ISettingsService sonarrSettings, ISettingsService sickRageService, ICouchPotatoApi cpApi, ISickRageApi srApi, - INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi, ISettingsService hpService, - ICouchPotatoCacher cpCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi, - ISettingsService plexService, ISettingsService auth) : base("search") + INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi, ISettingsService hpService, + ICouchPotatoCacher cpCacher, ISonarrCacher sonarrCacher, ISickRageCacher sickRageCacher, IPlexApi plexApi, + ISettingsService plexService, ISettingsService auth, IRepository u, ISettingsService email) : base("search", prSettings) { Auth = auth; PlexService = plexService; @@ -71,7 +73,6 @@ namespace PlexRequests.UI.Modules CpService = cpSettings; PrService = prSettings; MovieApi = new TheMovieDbApi(); - TvApi = new TheTvDbApi(); Cache = cache; Checker = checker; CpCacher = cpCacher; @@ -87,6 +88,8 @@ namespace PlexRequests.UI.Modules MusicBrainzApi = mbApi; HeadphonesApi = hpApi; HeadphonesService = hpService; + UsersToNotifyRepo = u; + EmailNotificationSettings = email; Get["/"] = parameters => RequestLoad(); @@ -102,13 +105,17 @@ namespace PlexRequests.UI.Modules Post["request/movie"] = parameters => RequestMovie((int)Request.Form.movieId); Post["request/tv"] = parameters => RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons); Post["request/album"] = parameters => RequestAlbum((string)Request.Form.albumId); + + Post["/notifyuser"] = x => NotifyUser((bool)Request.Form.notify); + Get["/notifyuser"] = x => GetUserNotificationSettings(); + + Get["/seasons"] = x => GetSeasons(); } private IPlexApi PlexApi { get; } private TheMovieDbApi MovieApi { get; } private INotificationService NotificationService { get; } private ICouchPotatoApi CouchPotatoApi { get; } private ISonarrApi SonarrApi { get; } - private TheTvDbApi TvApi { get; } private ISickRageApi SickrageApi { get; } private IRequestService RequestService { get; } private ICacheProvider Cache { get; } @@ -119,22 +126,16 @@ namespace PlexRequests.UI.Modules private ISettingsService SonarrService { get; } private ISettingsService SickRageService { get; } private ISettingsService HeadphonesService { get; } + private ISettingsService EmailNotificationSettings { get; } private IAvailabilityChecker Checker { get; } private ICouchPotatoCacher CpCacher { get; } private ISonarrCacher SonarrCacher { get; } private ISickRageCacher SickRageCacher { get; } private IMusicBrainzApi MusicBrainzApi { get; } private IHeadphonesApi HeadphonesApi { get; } + private IRepository UsersToNotifyRepo { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); - private bool IsAdmin - { - get - { - return Context.CurrentUser.IsAuthenticated(); - } - } - private Negotiator RequestLoad() { var settings = PrService.GetSettings(); @@ -163,13 +164,12 @@ namespace PlexRequests.UI.Modules private Response ProcessMovies(MovieSearchType searchType, string searchTerm) { - List taskList = new List(); - var cpSettings = CpService.GetSettings(); + var taskList = new List(); - List apiMovies = new List(); - taskList.Add(Task.Factory.StartNew>(() => + var apiMovies = new List(); + taskList.Add(Task.Factory.StartNew(() => { - switch(searchType) + switch (searchType) { case MovieSearchType.Search: return MovieApi.SearchMovie(searchTerm).Result.Select(x => new MovieResult() @@ -208,18 +208,19 @@ namespace PlexRequests.UI.Modules }).ContinueWith((t) => { - dbMovies = t.Result.ToDictionary(x => x.ProviderId); + var distinctResults = t.Result.DistinctBy(x => x.ProviderId); + dbMovies = distinctResults.ToDictionary(x => x.ProviderId); })); Task.WaitAll(taskList.ToArray()); - int[] cpCached = CpCacher.QueuedIds(); + var cpCached = CpCacher.QueuedIds(); var plexMovies = Checker.GetPlexMovies(); - - List viewMovies = new List(); + var settings = PrService.GetSettings(); + var viewMovies = new List(); foreach (MovieResult movie in apiMovies) { - var viewMovie = new SearchMovieViewModel() + var viewMovie = new SearchMovieViewModel { Adult = movie.Adult, BackdropPath = movie.BackdropPath, @@ -236,12 +237,12 @@ namespace PlexRequests.UI.Modules VoteAverage = movie.VoteAverage, VoteCount = movie.VoteCount }; - + var canSee = CanUserSeeThisRequest(viewMovie.Id, settings.UsersCanViewOnlyOwnRequests, dbMovies); if (Checker.IsMovieAvailable(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString())) { viewMovie.Available = true; } - else if (dbMovies.ContainsKey(movie.Id)) // compare to the requests db + else if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db { var dbm = dbMovies[movie.Id]; @@ -249,7 +250,7 @@ namespace PlexRequests.UI.Modules viewMovie.Approved = dbm.Approved; viewMovie.Available = dbm.Available; } - else if (cpCached.Contains(movie.Id)) // compare to the couchpotato db + else if (cpCached.Contains(movie.Id) && canSee) // compare to the couchpotato db { viewMovie.Requested = true; } @@ -260,13 +261,24 @@ namespace PlexRequests.UI.Modules return Response.AsJson(viewMovies); } + private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests, Dictionary moviesInDb) + { + if (usersCanViewOnlyOwnRequests) + { + var result = moviesInDb.FirstOrDefault(x => x.Value.ProviderId == movieId); + return result.Value != null && result.Value.UserHasRequested(Username); + } + + return true; + } + private Response SearchTvShow(string searchTerm) { Log.Trace("Searching for TV Show {0}", searchTerm); - List taskList = new List(); + var taskList = new List(); - List apiTv = new List(); + var apiTv = new List(); taskList.Add(Task.Factory.StartNew(() => { return new TvMazeApi().Search(searchTerm); @@ -276,7 +288,7 @@ namespace PlexRequests.UI.Modules apiTv = t.Result; })); - Dictionary dbTv = new Dictionary(); + var dbTv = new Dictionary(); taskList.Add(Task.Factory.StartNew(() => { return RequestService.GetAll().Where(x => x.Type == RequestType.TvShow); @@ -294,8 +306,8 @@ namespace PlexRequests.UI.Modules return Response.AsJson(""); } - int[] sonarrCached = SonarrCacher.QueuedIds(); - int[] sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays + var sonarrCached = SonarrCacher.QueuedIds(); + var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays var plexTvShows = Checker.GetPlexTvShows(); var viewTv = new List(); @@ -323,7 +335,7 @@ namespace PlexRequests.UI.Modules { viewT.Available = true; } - else if (t.show.externals.thetvdb != null) + else if (t.show?.externals?.thetvdb != null) { int tvdbid = (int)t.show.externals.thetvdb; @@ -351,9 +363,9 @@ namespace PlexRequests.UI.Modules private Response SearchMusic(string searchTerm) { - List taskList = new List(); + var taskList = new List(); - List apiAlbums = new List(); + var apiAlbums = new List(); taskList.Add(Task.Factory.StartNew(() => { return MusicBrainzApi.SearchAlbum(searchTerm); @@ -363,7 +375,7 @@ namespace PlexRequests.UI.Modules apiAlbums = t.Result.releases ?? new List(); })); - Dictionary dbAlbum = new Dictionary(); + var dbAlbum = new Dictionary(); taskList.Add(Task.Factory.StartNew(() => { return RequestService.GetAll().Where(x => x.Type == RequestType.Album); @@ -467,8 +479,9 @@ namespace PlexRequests.UI.Modules Status = movieInfo.Status, RequestedDate = DateTime.UtcNow, Approved = false, - RequestedUsers = new List() { Username }, + RequestedUsers = new List { Username }, Issues = IssueState.None, + }; Log.Trace(settings.DumpJson()); @@ -487,18 +500,21 @@ namespace PlexRequests.UI.Modules if (result) { model.Approved = true; - Log.Debug("Adding movie to database requests (No approval required)"); + Log.Info("Adding movie to database (No approval required)"); RequestService.AddRequest(model); - var notificationModel = new NotificationModel - { - Title = model.Title, - User = Username, - DateTime = DateTime.Now, - NotificationType = NotificationType.NewRequest - }; - NotificationService.Publish(notificationModel); + if (ShouldSendNotification()) + { + var notificationModel = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notificationModel); + } return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" }); } return @@ -512,17 +528,20 @@ namespace PlexRequests.UI.Modules else { model.Approved = true; - Log.Debug("Adding movie to database requests (No approval required)"); + Log.Info("Adding movie to database (No approval required)"); RequestService.AddRequest(model); - var notificationModel = new NotificationModel + if (ShouldSendNotification()) { - Title = model.Title, - User = Username, - DateTime = DateTime.Now, - NotificationType = NotificationType.NewRequest - }; - NotificationService.Publish(notificationModel); + var notificationModel = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notificationModel); + } return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullMovieName} was successfully added!" }); } @@ -530,7 +549,7 @@ namespace PlexRequests.UI.Modules try { - Log.Debug("Adding movie to database requests"); + Log.Info("Adding movie to database"); var id = RequestService.AddRequest(model); var notificationModel = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; @@ -551,6 +570,7 @@ namespace PlexRequests.UI.Modules /// /// The show identifier. /// The seasons. + /// if set to true [notify]. /// private Response RequestTvShow(int showId, string seasons) { @@ -604,11 +624,12 @@ namespace PlexRequests.UI.Modules Status = showInfo.status, RequestedDate = DateTime.UtcNow, Approved = false, - RequestedUsers = new List() { Username }, + RequestedUsers = new List { Username }, Issues = IssueState.None, ImdbId = showInfo.externals?.imdb ?? string.Empty, SeasonCount = showInfo.seasonCount }; + var seasonsList = new List(); switch (seasons) { @@ -620,9 +641,20 @@ namespace PlexRequests.UI.Modules seasonsList.Add(model.SeasonCount); model.SeasonsRequested = "Latest"; break; - default: + case "all": model.SeasonsRequested = "All"; break; + default: + var split = seasons.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + var seasonsCount = new int[split.Length]; + for (var i = 0; i < split.Length; i++) + { + int tryInt; + int.TryParse(split[i], out tryInt); + seasonsCount[i] = tryInt; + } + seasonsList.AddRange(seasonsCount); + break; } model.SeasonList = seasonsList.ToArray(); @@ -639,9 +671,18 @@ namespace PlexRequests.UI.Modules model.Approved = true; Log.Debug("Adding tv to database requests (No approval required & Sonarr)"); RequestService.AddRequest(model); - var notify1 = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; - NotificationService.Publish(notify1); + if (ShouldSendNotification()) + { + var notify1 = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notify1); + } return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" }); } @@ -659,16 +700,24 @@ namespace PlexRequests.UI.Modules model.Approved = true; Log.Debug("Adding tv to database requests (No approval required & SickRage)"); RequestService.AddRequest(model); - - var notify2 = new NotificationModel { Title = model.Title, User = Username, DateTime = DateTime.Now, NotificationType = NotificationType.NewRequest }; - NotificationService.Publish(notify2); + if (ShouldSendNotification()) + { + var notify2 = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notify2); + } return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" }); } return Response.AsJson(new JsonResponseModel { Result = false, Message = result?.message != null ? "Message From SickRage: " + result.message : "Something went wrong adding the movie to SickRage! Please check your settings." }); } - return Response.AsJson("The request of TV Shows is not correctly set up. Please contact your admin."); + return Response.AsJson(new JsonResponseModel { Result = false, Message = "The request of TV Shows is not correctly set up. Please contact your admin." }); } @@ -680,6 +729,21 @@ namespace PlexRequests.UI.Modules return Response.AsJson(new JsonResponseModel { Result = true, Message = $"{fullShowName} was successfully added!" }); } + private bool ShouldSendNotification() + { + var sendNotification = true; + var claims = Context.CurrentUser?.Claims; + if (claims != null) + { + if (claims.Contains(UserClaims.Admin) || claims.Contains(UserClaims.PowerUser)) + { + sendNotification = false; // Don't bother sending a notification if the user is an admin + } + } + return sendNotification; + } + + private Response RequestAlbum(string releaseId) { var settings = PrService.GetSettings(); @@ -691,6 +755,7 @@ namespace PlexRequests.UI.Modules Log.Debug("We do have an existing album request"); if (!existingRequest.UserHasRequested(Username)) { + Log.Debug("Not in the requested list so adding them and updating the request. User: {0}", Username); existingRequest.RequestedUsers.Add(Username); RequestService.UpdateRequest(existingRequest); @@ -748,7 +813,6 @@ namespace PlexRequests.UI.Modules ArtistId = artist.id }; - if (ShouldAutoApprove(RequestType.Album, settings)) { Log.Debug("We don't require approval OR the user is in the whitelist"); @@ -769,10 +833,22 @@ namespace PlexRequests.UI.Modules } var sender = new HeadphonesSender(HeadphonesApi, hpSettings, RequestService); - sender.AddAlbum(model); + sender.AddAlbum(model).Wait(); model.Approved = true; RequestService.AddRequest(model); + if (ShouldSendNotification()) + { + var notify2 = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notify2); + } + return Response.AsJson(new JsonResponseModel { @@ -781,6 +857,17 @@ namespace PlexRequests.UI.Modules }); } + if (ShouldSendNotification()) + { + var notify2 = new NotificationModel + { + Title = model.Title, + User = Username, + DateTime = DateTime.Now, + NotificationType = NotificationType.NewRequest + }; + NotificationService.Publish(notify2); + } var result = RequestService.AddRequest(model); return Response.AsJson(new JsonResponseModel { @@ -821,5 +908,70 @@ namespace PlexRequests.UI.Modules return false; } } + + private Response NotifyUser(bool notify) + { + var auth = Auth.GetSettings().UserAuthentication; + var email = EmailNotificationSettings.GetSettings().EnableUserEmailNotifications; + if (!auth) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but this functionality is currently only for users with Plex accounts"}); + } + if (!email) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "Sorry, but your administrator has not yet enabled this functionality." }); + } + var username = Username; + var originalList = UsersToNotifyRepo.GetAll(); + if (!notify) + { + if (originalList == null) + { + return Response.AsJson(new JsonResponseModel { Result = false, Message = "We could not remove this notification because you never had it!" }); + } + var userToRemove = originalList.FirstOrDefault(x => x.Username == username); + if (userToRemove != null) + { + UsersToNotifyRepo.Delete(userToRemove); + } + return Response.AsJson(new JsonResponseModel { Result = true }); + } + + + if (originalList == null) + { + var userModel = new UsersToNotify { Username = username }; + var insertResult = UsersToNotifyRepo.Insert(userModel); + return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" }); + } + + var existingUser = originalList.FirstOrDefault(x => x.Username == username); + if (existingUser != null) + { + return Response.AsJson(new JsonResponseModel { Result = true }); // It's already enabled + } + else + { + var userModel = new UsersToNotify { Username = username }; + var insertResult = UsersToNotifyRepo.Insert(userModel); + return Response.AsJson(insertResult != -1 ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Could not save, please try again" }); + } + + } + private Response GetUserNotificationSettings() + { + var retval = UsersToNotifyRepo.GetAll().FirstOrDefault(x => x.Username == Username); + return Response.AsJson(retval != null); + } + + private Response GetSeasons() + { + var tv = new TvMazeApi(); + var seriesId = (int)Request.Query.tvId; + var show = tv.ShowLookupByTheTvDbId(seriesId); + var seasons = tv.GetSeasons(show.id); + var model = seasons.Select(x => x.number); + return Response.AsJson(model); + } } } diff --git a/PlexRequests.UI/Modules/UpdateCheckerModule.cs b/PlexRequests.UI/Modules/UpdateCheckerModule.cs new file mode 100644 index 000000000..f1b46a805 --- /dev/null +++ b/PlexRequests.UI/Modules/UpdateCheckerModule.cs @@ -0,0 +1,77 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: UpdateCheckerModule.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; + +using Nancy; + +using NLog; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class UpdateCheckerModule : BaseAuthModule + { + public UpdateCheckerModule(ICacheProvider provider, ISettingsService pr) : base("updatechecker", pr) + { + Cache = provider; + + Get["/"] = _ => CheckLatestVersion(); + } + + private ICacheProvider Cache { get; } + + private static Logger Log = LogManager.GetCurrentClassLogger(); + + private Response CheckLatestVersion() + { + try + { + if (!IsAdmin) + { + return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false }); + } + + var checker = new StatusChecker(); + var release = Cache.GetOrSet(CacheKeys.LastestProductVersion, () => checker.GetStatus(), 30); + + return Response.AsJson(release.UpdateAvailable + ? new JsonUpdateAvailableModel { UpdateAvailable = true} + : new JsonUpdateAvailableModel { UpdateAvailable = false }); + } + catch (Exception e) + { + Log.Warn("Exception Thrown when attempting to check the status"); + Log.Warn(e); + return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false }); + } + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Modules/UserLoginModule.cs b/PlexRequests.UI/Modules/UserLoginModule.cs index 48adb3989..d6acb5343 100644 --- a/PlexRequests.UI/Modules/UserLoginModule.cs +++ b/PlexRequests.UI/Modules/UserLoginModule.cs @@ -46,7 +46,7 @@ namespace PlexRequests.UI.Modules { public class UserLoginModule : BaseModule { - public UserLoginModule(ISettingsService auth, IPlexApi api) : base("userlogin") + public UserLoginModule(ISettingsService auth, IPlexApi api, ISettingsService pr) : base("userlogin", pr) { AuthService = auth; Api = api; @@ -142,7 +142,7 @@ namespace PlexRequests.UI.Modules Session[SessionKeys.ClientDateTimeOffsetKey] = (int)dateTimeOffset; return Response.AsJson(authenticated - ? new JsonResponseModel { Result = true, BaseUrl = BaseUrl} + ? new JsonResponseModel { Result = true } : new JsonResponseModel { Result = false, Message = "Incorrect User or Password"}); } @@ -173,10 +173,10 @@ namespace PlexRequests.UI.Modules private bool CheckIfUserIsInPlexFriends(string username, string authToken) { var users = Api.GetUsers(authToken); - Log.Debug("Plex Users: "); - Log.Debug(users.DumpJson()); - var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Username)); - return allUsers != null && allUsers.Any(x => x.Username.Equals(username, StringComparison.CurrentCultureIgnoreCase)); + Log.Trace("Plex Users: "); + Log.Trace(users.DumpJson()); + var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title)); + return allUsers != null && allUsers.Any(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase)); } private bool IsUserInDeniedList(string username, AuthenticationSettings settings) diff --git a/PlexRequests.UI/Modules/UserManagementModule.cs b/PlexRequests.UI/Modules/UserManagementModule.cs new file mode 100644 index 000000000..c93977cd7 --- /dev/null +++ b/PlexRequests.UI/Modules/UserManagementModule.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; + +using Nancy; +using Nancy.Responses.Negotiation; +using Nancy.Security; + +using PlexRequests.Core; +using PlexRequests.Core.SettingModels; +using PlexRequests.Helpers; +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Modules +{ + public class UserManagementModule : BaseModule + { + public UserManagementModule(ISettingsService pr, ICustomUserMapper m) : base("usermanagement",pr) + { + this.RequiresClaims(UserClaims.Admin); + Get["/"] = x => Load(); + + Get["/users"] = x => LoadUsers(); + UserMapper = m; + } + private ICustomUserMapper UserMapper { get; } + + private Negotiator Load() + { + return View["Index"]; + } + + private Response LoadUsers() + { + var users = UserMapper.GetUsers(); + var model = new List(); + foreach (var user in users) + { + model.Add(new UserManagementUsersViewModel + { + //Claims = ByteConverterHelper.ReturnObject(user.Claims), + Claims = "test", + Id = user.Id, + Username = user.UserName, + //Type = UserType.LocalUser + }); + } + return Response.AsJson(users); + } + + private Response CreateUser(string username, string password, string claims) + { + if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) + { + return Response.AsJson(new JsonResponseModel + { + Result = true, + Message = "Please enter in a valid Username and Password" + }); + } + var user = UserMapper.CreateUser(username, password, new string[] {claims}); + if (user.HasValue) + { + return Response.AsJson(new JsonResponseModel {Result = true}); + } + + return Response.AsJson(new JsonResponseModel {Result = false, Message = "Could not save user"}); + } + } +} + diff --git a/PlexRequests.UI/PlexRequests.UI.csproj b/PlexRequests.UI/PlexRequests.UI.csproj index 024b63942..3e9703a4c 100644 --- a/PlexRequests.UI/PlexRequests.UI.csproj +++ b/PlexRequests.UI/PlexRequests.UI.csproj @@ -9,7 +9,7 @@ Properties PlexRequests.UI PlexRequests - v4.5.2 + v4.5 512 ..\..\ true @@ -52,114 +52,107 @@ prompt 4 - - - - - - ..\packages\Dapper.1.42\lib\net45\Dapper.dll - True - - - ..\packages\FluentScheduler.3.1.46\lib\net40\FluentScheduler.dll - True - - - ..\packages\FluentValidation.6.2.1.0\lib\Net45\FluentValidation.dll - True - - - ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll - True - - - ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll - True - - - ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll - True - - - ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll - True - - - ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll - True - - - False - ..\Assemblies\Mono.Data.Sqlite.dll - - - ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll - True - ..\packages\Nancy.1.4.3\lib\net40\Nancy.dll True - - ..\packages\Nancy.Authentication.Basic.1.4.1\lib\net40\Nancy.Authentication.Basic.dll + + ..\packages\Nancy.Metadata.Modules.1.4.1\lib\net40\Nancy.Metadata.Modules.dll True - - ..\packages\Nancy.Authentication.Forms.1.4.1\lib\net40\Nancy.Authentication.Forms.dll - True - - - ..\packages\Nancy.Hosting.Self.1.4.1\lib\net40\Nancy.Hosting.Self.dll - True - - - ..\packages\Nancy.Owin.1.4.1\lib\net40\Nancy.Owin.dll - True - - - ..\packages\Nancy.Validation.FluentValidation.1.4.1\lib\net40\Nancy.Validation.FluentValidation.dll - True - - - ..\packages\Nancy.Viewengines.Razor.1.4.1\lib\net40\Nancy.ViewEngines.Razor.dll - True - - - ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll - True - - - ..\packages\NLog.4.2.3\lib\net45\NLog.dll - True - - - ..\packages\Owin.1.0\lib\net40\Owin.dll + + ..\packages\Nancy.Swagger.0.1.0-alpha3\lib\net40\Nancy.Swagger.dll True - ..\packages\RestSharp.105.2.3\lib\net452\RestSharp.dll + ..\packages\RestSharp.105.2.3\lib\net45\RestSharp.dll + True + + + ..\packages\Swagger.ObjectModel.0.1.0-alpha3\lib\net40\Swagger.ObjectModel.dll True - - ..\packages\System.Data.SQLite.Core.1.0.99.0\lib\net46\System.Data.SQLite.dll - True - - - ..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll - True - + - + + ..\packages\CommandLineParser.2.0.275-beta\lib\net45\CommandLine.dll + + + ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll + + + ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll + + + ..\packages\Dapper.1.42\lib\net45\Dapper.dll + + + ..\packages\FluentValidation.6.2.1.0\lib\Net45\FluentValidation.dll + + + ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll + + + ..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll + + + ..\packages\Microsoft.Owin.Host.HttpListener.3.0.1\lib\net45\Microsoft.Owin.Host.HttpListener.dll + + + ..\packages\Microsoft.Owin.Host.SystemWeb.3.0.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll + + + ..\packages\Microsoft.Owin.Hosting.3.0.1\lib\net45\Microsoft.Owin.Hosting.dll + + + ..\Assemblies\Mono.Data.Sqlite.dll + + + ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll + + + ..\packages\Nancy.Authentication.Basic.1.4.1\lib\net40\Nancy.Authentication.Basic.dll + + + ..\packages\Nancy.Authentication.Forms.1.4.1\lib\net40\Nancy.Authentication.Forms.dll + + + ..\packages\Nancy.Hosting.Self.1.4.1\lib\net40\Nancy.Hosting.Self.dll + + + ..\packages\Nancy.Owin.1.4.1\lib\net40\Nancy.Owin.dll + + + ..\packages\Nancy.Validation.FluentValidation.1.4.1\lib\net40\Nancy.Validation.FluentValidation.dll + + + ..\packages\Nancy.Viewengines.Razor.1.4.1\lib\net40\Nancy.ViewEngines.Razor.dll + + + ..\packages\Newtonsoft.Json.8.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\NLog.4.2.3\lib\net45\NLog.dll + + + ..\packages\Owin.1.0\lib\net40\Owin.dll + + + ..\packages\Quartz.2.3.3\lib\net40\Quartz.dll + + + ..\packages\Microsoft.AspNet.Razor.2.0.30506.0\lib\net40\System.Web.Razor.dll + + ..\packages\TMDbLib.0.9.0.0-alpha\lib\net45\TMDbLib.dll - True @@ -168,32 +161,59 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + PreserveNewest - + PreserveNewest - - @@ -211,18 +231,96 @@ + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + OriginalBootstrapCustom.scss + + + OriginalBootstrapCustom.css + Always + + + Always + + + PlexBootstrapCustom.scss + + + PlexBootstrapCustom.css + Always + + + PreserveNewest + + + PreserveNewest + + + Always + + + + PreserveNewest - - custom.scss - - - custom.css - Always - PreserveNewest @@ -272,10 +370,10 @@ pace.css Always - + PreserveNewest - + PreserveNewest @@ -287,7 +385,11 @@ compilerconfig.json - + + PreserveNewest + + + Always @@ -304,6 +406,12 @@ PreserveNewest + + PreserveNewest + + + Designer + Designer @@ -391,6 +499,9 @@ Always + + Always + web.config @@ -409,7 +520,7 @@ PlexRequests.Api.Models - {8cb8d235-2674-442d-9c6a-35fcaeeb160d} + {8CB8D235-2674-442D-9C6A-35FCAEEB160D} PlexRequests.Api @@ -428,9 +539,13 @@ {92433867-2B7B-477B-A566-96C382427525} PlexRequests.Store + + {ebe6fc1c-7b4b-47e9-af54-0ee0604a2be5} + PlexRequests.Updater + - + PreserveNewest @@ -477,4 +592,5 @@ --> + \ No newline at end of file diff --git a/PlexRequests.UI/Program.cs b/PlexRequests.UI/Program.cs index c16a08c08..1bb0da24c 100644 --- a/PlexRequests.UI/Program.cs +++ b/PlexRequests.UI/Program.cs @@ -25,7 +25,6 @@ // ************************************************************************/ #endregion using System; -using System.Collections.Generic; using Microsoft.Owin.Hosting; @@ -40,11 +39,13 @@ using PlexRequests.Helpers; using PlexRequests.Store; using PlexRequests.Store.Repository; using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Windows.Forms; -using FluentScheduler; +using CommandLine; -using PlexRequests.Services; -using PlexRequests.UI.Jobs; +using PlexRequests.UI.Start; namespace PlexRequests.UI { @@ -53,37 +54,21 @@ namespace PlexRequests.UI private static Logger Log = LogManager.GetCurrentClassLogger(); static void Main(string[] args) { - var baseUrl = string.Empty; - var port = -1; - if (args.Length > 0) - { - for (int i = 0; i < args.Length; i++) - { - var arg = args[i].ToLowerInvariant().Substring(1); - switch (arg) - { - case "base": - i++; - var value = args[i]; - Console.WriteLine($"Using a Base URL {args[i]}"); - baseUrl = value; - break; - default: - int portResult; - if (!int.TryParse(args[i], out portResult)) - { - Console.WriteLine("Didn't pass in a valid port"); - Console.ReadLine(); - Environment.Exit(1); - } - else - { - port = portResult; - } - break; - } - } - } + + var result = Parser.Default.ParseArguments(args); + var baseUrl = result.MapResult( + o => o.BaseUrl, + e => string.Empty); + + var port = result.MapResult( + x => x.Port, + e => -1); + + var updated = result.MapResult(x => x.Updated, e => UpdateValue.None); + CheckUpdate(updated); + + PrintToConsole("Starting Up! Please wait, this can usually take a few seconds.", ConsoleColor.Yellow); + Log.Trace("Getting product version"); WriteOutVersion(); @@ -91,8 +76,9 @@ namespace PlexRequests.UI var cn = s.SetupDb(baseUrl); s.CacheQualityProfiles(); ConfigureTargets(cn); + SetupLogging(); - if (port == -1) + if (port == -1 || port == 3579) port = GetStartupPort(); var options = new StartOptions(Debugger.IsAttached ? $"http://localhost:{port}" : $"http://+:{port}") @@ -103,21 +89,21 @@ namespace PlexRequests.UI { using (WebApp.Start(options)) { - SetupSchedulers(); - - Console.WriteLine($"Request Plex is running on the following: http://+:{port}/"); + Console.WriteLine($"Plex Requests is running on the following: http://+:{port}/{baseUrl}"); + PrintToConsole("All setup, Plex Requests is now ready!", ConsoleColor.Yellow); if (Type.GetType("Mono.Runtime") != null) { - Log.Trace("We are on Mono!"); + Log.Info("We are on Mono!"); + // on mono, processes will usually run as daemons - this allows you to listen // for termination signals (ctrl+c, shutdown, etc) and finalize correctly UnixSignal.WaitAny( - new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGQUIT), new UnixSignal(Signum.SIGHUP) }); + new[] { new UnixSignal(Signum.SIGINT), new UnixSignal(Signum.SIGTERM), new UnixSignal(Signum.SIGQUIT) }); } else { - Log.Trace("This is not Mono"); + Log.Info("This is not Mono"); Console.WriteLine("Press any key to exit"); Console.ReadLine(); } @@ -126,6 +112,7 @@ namespace PlexRequests.UI catch (Exception e) { Log.Fatal(e); + Console.WriteLine(e); throw; } } @@ -157,11 +144,60 @@ namespace PlexRequests.UI LoggingHelper.ConfigureLogging(connectionString); } - private static void SetupSchedulers() + private static void SetupLogging() { - TaskManager.TaskFactory = new PlexTaskFactory(); - TaskManager.Initialize(new PlexRegistry()); - TaskManager.Initialize(new MediaCacheRegistry()); + var settingsService = new SettingsServiceV2(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider())); + var logSettings = settingsService.GetSettings(); + + if (logSettings != null) + { + LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level)); + } + } + + private static void PrintToConsole(string message, ConsoleColor colour = ConsoleColor.Gray) + { + Console.ForegroundColor = colour; + Console.WriteLine(message); + Console.ForegroundColor = ConsoleColor.Gray; + } + + private static void CheckUpdate(UpdateValue val) + { + if (val == UpdateValue.Failed) + { + PrintToConsole("Update Failed", ConsoleColor.Red); + } + if (val == UpdateValue.Updated) + { + PrintToConsole("Finishing Update", ConsoleColor.Yellow); + var applicationPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath)); + var files = Directory.GetFiles(applicationPath, "PlexRequests.*", SearchOption.TopDirectoryOnly); + var oldUpdater = files.FirstOrDefault(x => x == $"{applicationPath}\\PlexRequests.Updater.exe"); + var newUpdater = files.FirstOrDefault(x => x == $"{applicationPath}\\PlexRequests.Updater.exe_Updated"); + + if (oldUpdater == null || newUpdater == null) + { + PrintToConsole("Looks like there was nothing to update.", ConsoleColor.Yellow); + return; + } + + try + { + File.Copy(oldUpdater, "PlexRequests.Updater.exe_Old", true); + File.Delete(oldUpdater); + File.Copy(newUpdater, "PlexRequests.Updater.exe", true); + File.Delete(newUpdater); + + File.Delete("PlexRequests.Updater.exe_Old"); // Cleanup + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + + PrintToConsole("Finished Update!", ConsoleColor.Yellow); + } } } } diff --git a/PlexRequests.UI/Start/StartupOptions.cs b/PlexRequests.UI/Start/StartupOptions.cs new file mode 100644 index 000000000..0f3dd7d97 --- /dev/null +++ b/PlexRequests.UI/Start/StartupOptions.cs @@ -0,0 +1,63 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: StartupOptions.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using CommandLine; + +namespace PlexRequests.UI.Start +{ + public class StartupOptions + { + /// + /// Gets or sets the base URL. + /// + /// + /// The base URL. + /// + [Option('b',"base", Required = false, HelpText = "Provide a base url for Plex Requests")] + public string BaseUrl { get; set; } + + /// + /// Gets or sets the port. + /// + /// + /// The port. + /// + [Option('p', "port", Required = false, HelpText = "Provide a port for Plex Requests to run on. You can also change this in the settings page in the UI", Default = 3579)] + public int Port { get; set; } + + + /// + /// Gets or sets a value indicating whether this is updated. + /// + /// + /// true if updated; otherwise, false. + /// + [Option('u', "updated", Required = false, HelpText = "This should only be used by the internal application")] + public UpdateValue Updated { get; set; } + + } +} \ No newline at end of file diff --git a/PlexRequests.Services/PlexType.cs b/PlexRequests.UI/Start/UpdateValue.cs similarity index 90% rename from PlexRequests.Services/PlexType.cs rename to PlexRequests.UI/Start/UpdateValue.cs index 27cd0d1da..0a994ed99 100644 --- a/PlexRequests.Services/PlexType.cs +++ b/PlexRequests.UI/Start/UpdateValue.cs @@ -1,7 +1,7 @@ #region Copyright // /************************************************************************ // Copyright (c) 2016 Jamie Rees -// File: PlexType.cs +// File: UpdateValue.cs // Created By: Jamie Rees // // Permission is hereby granted, free of charge, to any person obtaining @@ -24,12 +24,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ************************************************************************/ #endregion -namespace PlexRequests.Services +namespace PlexRequests.UI.Start { - public enum PlexType + public enum UpdateValue : int { - Movie, - TvShow, - Music + None = 0, + Updated = 1, + Failed = 2 } } \ No newline at end of file diff --git a/PlexRequests.UI/Startup.cs b/PlexRequests.UI/Startup.cs index 60a00ac37..a4a3c81cf 100644 --- a/PlexRequests.UI/Startup.cs +++ b/PlexRequests.UI/Startup.cs @@ -25,36 +25,33 @@ // ************************************************************************/ #endregion using System; -using FluentScheduler; using NLog; using Owin; + using PlexRequests.UI.Jobs; -using TaskFactory = FluentScheduler.TaskFactory; namespace PlexRequests.UI { public class Startup { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - private static Logger Log = LogManager.GetCurrentClassLogger(); public void Configuration(IAppBuilder app) { try { app.UseNancy(); - + var scheduler = new Scheduler(); + scheduler.StartScheduler(); } catch (Exception exception) { Log.Fatal(exception); throw; } - } - - } -} +} \ No newline at end of file diff --git a/PlexRequests.UI/Validators/PlexRequestsValidator.cs b/PlexRequests.UI/Validators/PlexRequestsValidator.cs new file mode 100644 index 000000000..6f8ba4d3e --- /dev/null +++ b/PlexRequests.UI/Validators/PlexRequestsValidator.cs @@ -0,0 +1,50 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexRequestsValidator.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using FluentValidation; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Validators +{ + public class PlexRequestsValidator : AbstractValidator + { + public PlexRequestsValidator() + { + RuleFor(x => x.BaseUrl).NotEqual("requests").WithMessage("You cannot use 'requests' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("admin").WithMessage("You cannot use 'admin' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("search").WithMessage("You cannot use 'search' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("issues").WithMessage("You cannot use 'issues' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("userlogin").WithMessage("You cannot use 'userlogin' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("login").WithMessage("You cannot use 'login' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("test").WithMessage("You cannot use 'test' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("approval").WithMessage("You cannot use 'approval' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("updatechecker").WithMessage("You cannot use 'updatechecker' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("usermanagement").WithMessage("You cannot use 'usermanagement' as this is reserved by the application."); + RuleFor(x => x.BaseUrl).NotEqual("api").WithMessage("You cannot use 'api' as this is reserved by the application."); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Validators/PlexValidator.cs b/PlexRequests.UI/Validators/PlexValidator.cs index a686b1b62..53f541855 100644 --- a/PlexRequests.UI/Validators/PlexValidator.cs +++ b/PlexRequests.UI/Validators/PlexValidator.cs @@ -34,8 +34,8 @@ namespace PlexRequests.UI.Validators { public PlexValidator() { - RuleFor(request => request.Ip).NotEmpty().WithMessage("You must specify a IP/Host name."); - RuleFor(request => request.Port).NotEmpty().WithMessage("You must specify a Port."); + RuleFor(request => request.Ip).NotNull().WithMessage("You must specify a IP/Host name."); + RuleFor(request => request.Port).NotNull().WithMessage("You must specify a Port."); } } } \ No newline at end of file diff --git a/PlexRequests.UI/Validators/RequestedModelValidator.cs b/PlexRequests.UI/Validators/RequestedModelValidator.cs new file mode 100644 index 000000000..1f6f1d171 --- /dev/null +++ b/PlexRequests.UI/Validators/RequestedModelValidator.cs @@ -0,0 +1,45 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: RequestedModelValidator.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using FluentValidation; + +using PlexRequests.Store; + +namespace PlexRequests.UI.Validators +{ + public class RequestedModelValidator : AbstractValidator + { + public RequestedModelValidator() + { + RuleFor(x => x.Title).NotNull(); + RuleFor(x => x.ProviderId).NotNull().WithMessage("'ProviderId' must not be empty. Please use either TVMaze Id or TheMovieDb Id"); + RuleFor(x => x.PosterPath).NotNull(); + RuleFor(x => x.ReleaseDate).NotNull(); + RuleFor(x => x.Type).NotNull(); + RuleFor(x => x.RequestedUsers).NotNull(); + } + } +} \ No newline at end of file diff --git a/PlexRequests.Services/ConfigurationReader.cs b/PlexRequests.UI/Validators/SlackSettingsValidator.cs similarity index 79% rename from PlexRequests.Services/ConfigurationReader.cs rename to PlexRequests.UI/Validators/SlackSettingsValidator.cs index 4c35ff2e7..c3c477514 100644 --- a/PlexRequests.Services/ConfigurationReader.cs +++ b/PlexRequests.UI/Validators/SlackSettingsValidator.cs @@ -1,38 +1,40 @@ -#region Copyright -// /************************************************************************ -// Copyright (c) 2016 Jamie Rees -// File: ConfigurationReader.cs -// Created By: Jamie Rees -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// ************************************************************************/ -#endregion -using PlexRequests.Services.Interfaces; - -namespace PlexRequests.Services -{ - public class ConfigurationReader : IConfigurationReader - { - public Configuration Read() - { - return new Configuration(new UpdateInterval()); - } - } +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SlackSettingsValidator.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using FluentValidation; + +using PlexRequests.Core.SettingModels; + +namespace PlexRequests.UI.Validators +{ + public class SlackSettingsValidator : AbstractValidator + { + public SlackSettingsValidator() + { + RuleFor(request => request.WebhookUrl).NotEmpty().WithMessage("You must specify a Webhook Url"); + } + } } \ No newline at end of file diff --git a/PlexRequests.UI/Validators/SonarrValidator.cs b/PlexRequests.UI/Validators/SonarrValidator.cs index e35eb654b..b252bd3b0 100644 --- a/PlexRequests.UI/Validators/SonarrValidator.cs +++ b/PlexRequests.UI/Validators/SonarrValidator.cs @@ -38,7 +38,6 @@ namespace PlexRequests.UI.Validators RuleFor(request => request.Ip).NotEmpty().WithMessage("You must specify a IP/Host name."); RuleFor(request => request.Port).NotEmpty().WithMessage("You must specify a Port."); RuleFor(request => request.QualityProfile).NotEmpty().WithMessage("You must specify a Quality Profile."); - RuleFor(request => request.RootPath).NotEmpty().WithMessage("You must specify a Root Path."); } } } \ No newline at end of file diff --git a/PlexRequests.UI/Validators/UserViewModelValidator.cs b/PlexRequests.UI/Validators/UserViewModelValidator.cs new file mode 100644 index 000000000..0e4388adc --- /dev/null +++ b/PlexRequests.UI/Validators/UserViewModelValidator.cs @@ -0,0 +1,41 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: SonarrValidator.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using FluentValidation; + +using PlexRequests.UI.Models; + +namespace PlexRequests.UI.Validators +{ + public class UserViewModelValidator : AbstractValidator + { + public UserViewModelValidator() + { + RuleFor(request => request.CurrentPassword).NotEmpty().NotNull(); + RuleFor(request => request.NewPassword).NotEmpty().NotNull(); + } + } +} \ No newline at end of file diff --git a/PlexRequests.UI/Views/Admin/Authentication.cshtml b/PlexRequests.UI/Views/Admin/Authentication.cshtml index d223db1b8..d25094b27 100644 --- a/PlexRequests.UI/Views/Admin/Authentication.cshtml +++ b/PlexRequests.UI/Views/Admin/Authentication.cshtml @@ -16,35 +16,35 @@
      - +
      - +
      @@ -58,7 +58,7 @@
      - +

      @@ -126,7 +126,7 @@ var $form = $("#mainForm"); $.ajax({ type: $form.prop("method"), - url: "requestauth", + url: url, data: $form.serialize(), dataType: "json", success: function (response) { @@ -153,11 +153,18 @@ url = createBaseUrl(base, url); $.ajax({ type: "Get", - url: "getusers", + url: url, dataType: "json", success: function (response) { - if (response.length > 1) { - $(response).each(function () { + + $('#users').html(""); + if(!response.result){ + generateNotify(response.message,"danger"); + $('#users').append(""); + return; + } + if (response.users.length > 1) { + $(response.users).each(function () { $('#users').append(""); }); } else { @@ -167,6 +174,8 @@ error: function (e) { console.log(e); generateNotify("Something went wrong!", "danger"); + $('#users').html(""); + $('#users').append(""); } }); diff --git a/PlexRequests.UI/Views/Admin/CouchPotato.cshtml b/PlexRequests.UI/Views/Admin/CouchPotato.cshtml index fb54a6c33..8558534f2 100644 --- a/PlexRequests.UI/Views/Admin/CouchPotato.cshtml +++ b/PlexRequests.UI/Views/Admin/CouchPotato.cshtml @@ -17,16 +17,16 @@ CouchPotato Settings
      - +
      @@ -53,16 +53,16 @@
      - +
      @@ -88,7 +88,7 @@
      - +
      @@ -170,6 +170,8 @@ e.preventDefault(); var $form = $("#mainForm"); var url = createBaseUrl(baseUrl,"/test/cp"); + $('#spinner').attr("class", "fa fa-spinner fa-spin"); + $.ajax({ type: $form.prop("method"), url: url, @@ -178,15 +180,18 @@ success: function (response) { console.log(response); if (response.result === true) { + $('#spinner').attr("class", "fa fa-check"); generateNotify(response.message, "success"); $('#authToken').val(response.authToken); } else { generateNotify(response.message, "warning"); + $('#spinner').attr("class", "fa fa-times"); } }, error: function (e) { console.log(e); - generateNotify("Something went wrong!", "danger"); + generateNotify("Something went wrong!", "danger"); + $('#spinner').attr("class", "fa fa-times"); } }); }); diff --git a/PlexRequests.UI/Views/Admin/EmailNotifications.cshtml b/PlexRequests.UI/Views/Admin/EmailNotifications.cshtml index 45fda1a0e..ce7bddbf2 100644 --- a/PlexRequests.UI/Views/Admin/EmailNotifications.cshtml +++ b/PlexRequests.UI/Views/Admin/EmailNotifications.cshtml @@ -18,34 +18,35 @@
      - +
      - +
      + Please note that if user notifications is enabled, the email will get sent with the SMTP set-up below.
      - +
      @@ -91,7 +92,7 @@
      - +
      @@ -135,7 +136,8 @@ }); }); - $('#testEmail').click(function (e) { + $('#testEmail').click(function (e) { + $('#spinner').attr("class", "fa fa-spinner fa-spin"); var url = createBaseUrl(base, '/admin/testemailnotification'); e.preventDefault(); @@ -152,13 +154,16 @@ dataType: "json", success: function (response) { if (response.result === true) { + $('#spinner').attr("class", "fa fa-check"); generateNotify(response.message, "success"); } else { + $('#spinner').attr("class", "fa fa-times"); generateNotify(response.message, "warning"); } }, error: function (e) { console.log(e); + $('#spinner').attr("class", "fa fa-times"); generateNotify("Something went wrong!", "danger"); } }); diff --git a/PlexRequests.UI/Views/Admin/Headphones.cshtml b/PlexRequests.UI/Views/Admin/Headphones.cshtml index 47629aebc..f95b3ffdf 100644 --- a/PlexRequests.UI/Views/Admin/Headphones.cshtml +++ b/PlexRequests.UI/Views/Admin/Headphones.cshtml @@ -17,30 +17,30 @@ Headphones Settings
      - +
      - +
      @@ -75,7 +75,7 @@
      - +
      @@ -96,6 +96,8 @@ var base = '@Html.GetBaseUrl()'; $('#testHeadphones').click(function (e) { + + $('#spinner').attr("class", "fa fa-spinner fa-spin"); e.preventDefault(); var $form = $("#mainForm"); var url = createBaseUrl(base, '/test/headphones'); @@ -107,13 +109,16 @@ success: function (response) { console.log(response); if (response.result === true) { + $('#spinner').attr("class", "fa fa-check"); generateNotify(response.message, "success"); } else { + $('#spinner').attr("class", "fa fa-times"); generateNotify(response.message, "warning"); } }, error: function (e) { console.log(e); + $('#spinner').attr("class", "fa fa-times"); generateNotify("Something went wrong!", "danger"); } }); diff --git a/PlexRequests.UI/Views/Admin/Logs.cshtml b/PlexRequests.UI/Views/Admin/Logs.cshtml index 50a689d89..9fc58d202 100644 --- a/PlexRequests.UI/Views/Admin/Logs.cshtml +++ b/PlexRequests.UI/Views/Admin/Logs.cshtml @@ -1,6 +1,6 @@ @using PlexRequests.UI.Helpers @Html.Partial("_Sidebar") -@Html.LoadLogsAssets() +@Html.LoadTableAssets() @{ var baseUrl = Html.GetBaseUrl(); @@ -76,11 +76,14 @@ url: logUrl, dataType: "json", success: function (response) { - $("#select > option").each(function (level) { - if (response[0] == level.value) { - $('#' + level.target.id).prop("selected", "selected"); - } - }); + if (response && response.length > 0) { + $("#selected > option").each(function (level) { + var $opt = $(this); + if (response[0].ordinal == level) { + $opt.prop("selected", "selected"); + } + }); + } }, error: function (e) { console.log(e); diff --git a/PlexRequests.UI/Views/Admin/Plex.cshtml b/PlexRequests.UI/Views/Admin/Plex.cshtml index 7282218d1..d50364b02 100644 --- a/PlexRequests.UI/Views/Admin/Plex.cshtml +++ b/PlexRequests.UI/Views/Admin/Plex.cshtml @@ -32,16 +32,16 @@
      - +
      @@ -52,7 +52,7 @@
      - +
      @@ -69,25 +69,34 @@ \ No newline at end of file diff --git a/PlexRequests.UI/Views/Admin/Sickrage.cshtml b/PlexRequests.UI/Views/Admin/Sickrage.cshtml index e2415f74e..6181f0b0e 100644 --- a/PlexRequests.UI/Views/Admin/Sickrage.cshtml +++ b/PlexRequests.UI/Views/Admin/Sickrage.cshtml @@ -17,16 +17,14 @@ SickRage Settings
      -
      @@ -53,16 +51,15 @@
      -
      @@ -86,7 +83,7 @@
      - +
      @@ -147,6 +144,8 @@ }); $('#testSickRage').click(function (e) { + + $('#spinner').attr("class", "fa fa-spinner fa-spin"); e.preventDefault(); var qualityProfile = $("#profiles option:selected").val(); @@ -165,13 +164,16 @@ console.log(response); if (response.result === true) { generateNotify(response.message, "success"); + $('#spinner').attr("class", "fa fa-check"); } else { generateNotify(response.message, "warning"); + $('#spinner').attr("class", "fa fa-times"); } }, error: function (e) { console.log(e); generateNotify("Something went wrong!", "danger"); + $('#spinner').attr("class", "fa fa-times"); } }); }); diff --git a/PlexRequests.UI/Views/Admin/SlackNotifications.cshtml b/PlexRequests.UI/Views/Admin/SlackNotifications.cshtml new file mode 100644 index 000000000..f24d62691 --- /dev/null +++ b/PlexRequests.UI/Views/Admin/SlackNotifications.cshtml @@ -0,0 +1,119 @@ +@using PlexRequests.UI.Helpers +@Html.Partial("_Sidebar") + +
      +
      +
      + Slack Notifications + +
      +
      + + @if (Model.Enabled) + { + + } + else + { + + } + +
      +
      + +
      + + This is the full webhook url. + Slack > Settings > Add app or integration > Build > Make a Custom Integration > Incoming Webhooks > Add Incoming Webhook. You will then have a Webhook Url +
      + +
      +
      + +
      + + You can override the default channel here +
      + +
      +
      + +
      + + You can override the default username (Plex Requests) here +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      + +
      +
      +
      +
      +
      + + \ No newline at end of file diff --git a/PlexRequests.UI/Views/Admin/Sonarr.cshtml b/PlexRequests.UI/Views/Admin/Sonarr.cshtml index 6ca64285d..56f14cb7e 100644 --- a/PlexRequests.UI/Views/Admin/Sonarr.cshtml +++ b/PlexRequests.UI/Views/Admin/Sonarr.cshtml @@ -17,16 +17,14 @@ Sonarr Settings
      -
      @@ -53,16 +51,14 @@
      -
      @@ -73,7 +69,7 @@
      - +
      @@ -93,7 +89,7 @@
      - +
      +
      - +
      @@ -130,34 +126,40 @@ @if (!string.IsNullOrEmpty(Model.QualityProfile)) { - - var qualitySelected = @Model.QualityProfile; - if (!qualitySelected) { - return; - } - var $form = $("#mainForm"); - $.ajax({ - type: $form.prop("method"), - data: $form.serialize(), - url: "sonarrprofiles", - dataType: "json", - success: function(response) { - response.forEach(function(result) { - if (result.id == qualitySelected) { - $("#select").append(""); - } else { - $("#select").append(""); - } - }); - }, - error: function(e) { - console.log(e); - generateNotify("Something went wrong!", "danger"); + + + preLoad(); + + function preLoad() { + var qualitySelected = @Model.QualityProfile; + if (!qualitySelected) { + return; } - }); + var $form = $("#mainForm"); + $.ajax({ + type: $form.prop("method"), + data: $form.serialize(), + url: "sonarrprofiles", + dataType: "json", + success: function(response) { + response.forEach(function(result) { + if (result.id == qualitySelected) { + + $("#select").append(""); + } else { + $("#select").append(""); + } + }); + }, + error: function(e) { + console.log(e); + generateNotify("Something went wrong!", "danger"); + } + }); + } - } + } $('#save').click(function(e) { @@ -194,17 +196,22 @@ }); $('#getProfiles').click(function (e) { + + $('#getSpinner').attr("class", "fa fa-spinner fa-spin"); e.preventDefault(); if (!$('#Ip').val()) { generateNotify("Please enter a valid IP/Hostname.", "warning"); + $('#getSpinner').attr("class", "fa fa-times"); return; } if (!$('#portNumber').val()) { generateNotify("Please enter a valid Port Number.", "warning"); + $('#getSpinner').attr("class", "fa fa-times"); return; } if (!$('#ApiKey').val()) { generateNotify("Please enter a valid ApiKey.", "warning"); + $('#getSpinner').attr("class", "fa fa-times"); return; } var $form = $("#mainForm"); @@ -215,11 +222,13 @@ dataType: "json", success: function (response) { response.forEach(function (result) { + $('#getSpinner').attr("class", "fa fa-check"); $("#select").append(""); }); }, error: function (e) { console.log(e); + $('#getSpinner').attr("class", "fa fa-times"); generateNotify("Something went wrong!", "danger"); } }); @@ -227,6 +236,8 @@ var base = '@Html.GetBaseUrl()'; $('#testSonarr').click(function (e) { + + $('#spinner').attr("class", "fa fa-spinner fa-spin"); e.preventDefault(); var qualityProfile = $("#profiles option:selected").val(); @@ -245,13 +256,16 @@ console.log(response); if (response.result === true) { generateNotify(response.message, "success"); + $('#spinner').attr("class", "fa fa-check"); } else { generateNotify(response.message, "warning"); + $('#spinner').attr("class", "fa fa-times"); } }, error: function (e) { console.log(e); generateNotify("Something went wrong!", "danger"); + $('#spinner').attr("class", "fa fa-times"); } }); }); diff --git a/PlexRequests.UI/Views/Admin/Status.cshtml b/PlexRequests.UI/Views/Admin/Status.cshtml index 05dbf1faf..eb5f1b743 100644 --- a/PlexRequests.UI/Views/Admin/Status.cshtml +++ b/PlexRequests.UI/Views/Admin/Status.cshtml @@ -1,4 +1,5 @@ -@Html.Partial("_Sidebar") +@using PlexRequests.UI.Helpers +@Html.Partial("_Sidebar")
      @@ -15,6 +16,8 @@ @if (Model.UpdateAvailable) { +
      + } else { @@ -28,11 +31,41 @@

      @Model.ReleaseTitle

      -
      +
      @Html.Raw(Model.ReleaseNotes) }
      -
      \ No newline at end of file +
      + + \ No newline at end of file diff --git a/PlexRequests.UI/Views/Admin/_Sidebar.cshtml b/PlexRequests.UI/Views/Admin/_Sidebar.cshtml index 04dc3457a..9b7fee6cc 100644 --- a/PlexRequests.UI/Views/Admin/_Sidebar.cshtml +++ b/PlexRequests.UI/Views/Admin/_Sidebar.cshtml @@ -11,6 +11,7 @@ @Html.GetSidebarUrl(Context, "/admin/emailnotification", "Email Notifications") @Html.GetSidebarUrl(Context, "/admin/pushbulletnotification", "Pushbullet Notifications") @Html.GetSidebarUrl(Context, "/admin/pushovernotification", "Pushover Notifications") + @Html.GetSidebarUrl(Context, "/admin/slacknotification", "Slack Notifications") @Html.GetSidebarUrl(Context, "/admin/logs", "Logs") @Html.GetSidebarUrl(Context, "/admin/status", "Status")
      diff --git a/PlexRequests.UI/Views/ApiDocs/index.html b/PlexRequests.UI/Views/ApiDocs/index.html new file mode 100644 index 000000000..2933091b0 --- /dev/null +++ b/PlexRequests.UI/Views/ApiDocs/index.html @@ -0,0 +1,124 @@ + + + + + + Swagger UI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
       
      +
      + + diff --git a/PlexRequests.UI/Views/ApiDocs/o2c.html b/PlexRequests.UI/Views/ApiDocs/o2c.html new file mode 100644 index 000000000..88e8bf114 --- /dev/null +++ b/PlexRequests.UI/Views/ApiDocs/o2c.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/PlexRequests.UI/Views/Login/Index.cshtml b/PlexRequests.UI/Views/Login/Index.cshtml index 0662e2cb2..bbdf57068 100644 --- a/PlexRequests.UI/Views/Login/Index.cshtml +++ b/PlexRequests.UI/Views/Login/Index.cshtml @@ -1,16 +1,27 @@ -
      - Username -
      - Password -
      - Remember Me -

      - +@using PlexRequests.UI.Helpers +@{ + var baseUrl = Html.GetBaseUrl().ToHtmlString(); + var url = string.Empty; + if (!string.IsNullOrEmpty(baseUrl)) + { + url = "/" + baseUrl; + } +} + + Username +
      + Password +
      + + +
      + +
      @if (!Model.AdminExists) { -
      If you have not yet created an Admin account you can do here: Register
      +
      If you have not yet created an Admin account you can do here: Register
      } @if (Model.Errored) { diff --git a/PlexRequests.UI/Views/Requests/Index.cshtml b/PlexRequests.UI/Views/Requests/Index.cshtml index b6fe26214..cdf45b288 100644 --- a/PlexRequests.UI/Views/Requests/Index.cshtml +++ b/PlexRequests.UI/Views/Requests/Index.cshtml @@ -17,15 +17,15 @@
      @@ -36,7 +36,7 @@
      - @if (Context.CurrentUser.IsAuthenticated()) + @if (Context.CurrentUser.IsAuthenticated()) //TODO replace with IsAdmin { @if (Model.SearchForMovies) { @@ -62,7 +62,9 @@
    • Approved
    • Not Approved
    • Available
    • -
    • Not Available
    • +
    • Not Available
    • +
    • Released
    • +
    • Not Released
    • @@ -125,7 +127,7 @@ + + + @Html.LoadSearchAssets() diff --git a/PlexRequests.UI/Views/Shared/_Layout.cshtml b/PlexRequests.UI/Views/Shared/_Layout.cshtml index a61aae9c3..1ca9c6f48 100644 --- a/PlexRequests.UI/Views/Shared/_Layout.cshtml +++ b/PlexRequests.UI/Views/Shared/_Layout.cshtml @@ -34,7 +34,7 @@ Plex Requests
      - +
      + -
      - @RenderBody() -
      -
      - +
      + @RenderBody() +
      +
      + -
      +
      \ No newline at end of file diff --git a/PlexRequests.UI/app.config b/PlexRequests.UI/app.config index c5d2035eb..747d7cb7a 100644 --- a/PlexRequests.UI/app.config +++ b/PlexRequests.UI/app.config @@ -1,50 +1,50 @@ - + -
      +
      - - + + - + - + - + - - + + - - + + - - + + - + - + diff --git a/PlexRequests.UI/compilerconfig.json b/PlexRequests.UI/compilerconfig.json index f45d98c6d..0fbfabdd4 100644 --- a/PlexRequests.UI/compilerconfig.json +++ b/PlexRequests.UI/compilerconfig.json @@ -10,5 +10,13 @@ { "outputFile": "Content/moment.min.es5.js", "inputFile": "Content/moment.min.js" + }, + { + "outputFile": "Content/Themes/OriginalBootstrapCustom.css", + "inputFile": "Content/Themes/OriginalBootstrapCustom.scss" + }, + { + "outputFile": "Content/Themes/PlexBootstrapCustom.css", + "inputFile": "Content/Themes/PlexBootstrapCustom.scss" } ] \ No newline at end of file diff --git a/PlexRequests.UI/job_scheduling_data_2_0.xsd b/PlexRequests.UI/job_scheduling_data_2_0.xsd new file mode 100644 index 000000000..d1dabc1a9 --- /dev/null +++ b/PlexRequests.UI/job_scheduling_data_2_0.xsd @@ -0,0 +1,361 @@ + + + + + + + Root level node + + + + + + Commands to be executed before scheduling the jobs and triggers in this file. + + + + + Directives to be followed while scheduling the jobs and triggers in this file. + + + + + + + + + + + + + + Version of the XML Schema instance + + + + + + + + + + Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs. + + + + + Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable. + + + + + Delete the identified job if it exists (will also result in deleting all triggers related to it). + + + + + + + + + + + Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable). + + + + + + + + + + + + + + + + Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur. + + + + + If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced. + + + + + If true trigger's start time is calculated based on earlier run time instead of fixed value. Trigger's start time must be undefined for this to work. + + + + + + + + Define a JobDetail + + + + + + + + + + + + + + + + + Define a JobDataMap + + + + + + + + + Define a JobDataMap entry + + + + + + + + + + Define a Trigger + + + + + + + + + + + Common Trigger definitions + + + + + + + + + + + + + + + + + + + + + + + Define a SimpleTrigger + + + + + + + + + + + + + + + + + Define a CronTrigger + + + + + + + + + + + + + + + Define a DateIntervalTrigger + + + + + + + + + + + + + + + + Cron expression (see JavaDoc for examples) + + Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression! + + Regular expressions are not my strong point but I believe this is complete, + with the caveat that order for expressions like 3-0 is not legal but will pass, + and month and day names must be capitalized. + If you want to examine the correctness look for the [\s] to denote the + seperation of individual regular expressions. This is how I break them up visually + to examine them: + + SECONDS: + ( + ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) + | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) + | ([\?]) + | ([\*]) + ) [\s] + MINUTES: + ( + ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?) + | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9])) + | ([\?]) + | ([\*]) + ) [\s] + HOURS: + ( + ((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?) + | (([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3])) + | ([\?]) + | ([\*]) + ) [\s] + DAY OF MONTH: + ( + ((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?) + | (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?) + | (L(-[0-9])?) + | (L(-[1-2][0-9])?) + | (L(-[3][0-1])?) + | (LW) + | ([1-9]W) + | ([1-3][0-9]W) + | ([\?]) + | ([\*]) + )[\s] + MONTH: + ( + ((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?) + | (([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2])) + | (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?) + | ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)) + | ([\?]) + | ([\*]) + )[\s] + DAY OF WEEK: + ( + (([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?) + | ([1-7]/([1-7])) + | (((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?) + | ((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?) + | (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?) + | (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?) + | ([\?]) + | ([\*]) + ) + YEAR (OPTIONAL): + ( + [\s]? + ([\*])? + | ((19[7-9][0-9])|(20[0-9][0-9]))? + | (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))? + | ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)? + ) + + + + + + + + + + Number of times to repeat the Trigger (-1 for indefinite) + + + + + + + + + + Simple Trigger Misfire Instructions + + + + + + + + + + + + + + Cron Trigger Misfire Instructions + + + + + + + + + + + Date Interval Trigger Misfire Instructions + + + + + + + + + + + Interval Units + + + + + + + + + + + + + \ No newline at end of file diff --git a/PlexRequests.UI/packages.config b/PlexRequests.UI/packages.config index 8c2dea7cd..ddcf218f0 100644 --- a/PlexRequests.UI/packages.config +++ b/PlexRequests.UI/packages.config @@ -1,38 +1,45 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PlexRequests.Updater/PlexRequests.Updater.csproj b/PlexRequests.Updater/PlexRequests.Updater.csproj new file mode 100644 index 000000000..86de4fd4a --- /dev/null +++ b/PlexRequests.Updater/PlexRequests.Updater.csproj @@ -0,0 +1,56 @@ + + + + Debug + AnyCPU + {EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5} + Exe + PlexRequests.Updater + PlexRequests.Updater + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + true + + + full + true + bin\Release + prompt + 4 + true + + + + + + + + + + + + + + + + {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581} + PlexRequests.Core + + + {1252336D-42A3-482A-804C-836E60173DFA} + PlexRequests.Helpers + + + + + + + \ No newline at end of file diff --git a/PlexRequests.Updater/Program.cs b/PlexRequests.Updater/Program.cs new file mode 100644 index 000000000..98692c11d --- /dev/null +++ b/PlexRequests.Updater/Program.cs @@ -0,0 +1,14 @@ +using System; + +namespace PlexRequests.Updater +{ + class MainClass + { + public static void Main (string[] args) + { + Console.WriteLine ("Starting PlexRequests .Net updater"); + var s = new Updater(); + s.Start(args[0]); + } + } +} diff --git a/PlexRequests.Updater/Properties/AssemblyInfo.cs b/PlexRequests.Updater/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..c1c129870 --- /dev/null +++ b/PlexRequests.Updater/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("PlexRequests.Updater")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("TidusJar")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] + diff --git a/PlexRequests.Updater/Updater.cs b/PlexRequests.Updater/Updater.cs new file mode 100644 index 000000000..2b32317b0 --- /dev/null +++ b/PlexRequests.Updater/Updater.cs @@ -0,0 +1,205 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: Updater.cs +// Created By: Jamie Rees +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion +using System; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Net; +using System.Windows.Forms; + +namespace PlexRequests.Updater +{ + public class Updater + { + private string BackupPath { get; set; } + private bool Error { get; set; } + private string TempPath { get; set; } + + public void RestoreBackup() + { + Console.WriteLine("Update failed, restoring backup"); + using (var archive = ZipFile.OpenRead(BackupPath)) + { + foreach (var entry in archive.Entries) + { + var fullPath = Path.Combine(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath)), entry.FullName); + + if (string.IsNullOrEmpty(entry.Name)) + { + Directory.CreateDirectory(fullPath); + } + else + { + if (entry.Name.Contains("PlexRequests.Updater")) + { + entry.ExtractToFile(fullPath + "_Updated", true); + continue; + } + + entry.ExtractToFile(fullPath, true); + Console.WriteLine("Update failed, restoring backup"); + } + } + } + } + + public void Start(string downloadPath) + { + try + { + BackupCurrentVersion(); + var dir = CreateTempPath(); + TempPath = Path.Combine(dir.FullName, "PlexRequestsUpdate.zip"); + + CheckAndDelete(TempPath); + Console.WriteLine("Downloading new version"); + using (var client = new WebClient()) + { + client.DownloadFile(downloadPath, TempPath); + } + Console.WriteLine("Downloaded!"); + + + // Replace files + using (var archive = ZipFile.OpenRead(TempPath)) + { + foreach (var entry in archive.Entries) + { + var fullname = string.Empty; + if (entry.FullName.Contains("Release/")) // Don't extract the release folder, we are already in there + { + fullname = entry.FullName.Replace("Release/", string.Empty); + } + + var fullPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), fullname); + + if (string.IsNullOrEmpty(entry.Name)) + { + Directory.CreateDirectory(fullPath); + } + else + { + if (entry.Name.Contains("PlexRequests.Updater")) + { + entry.ExtractToFile(fullPath + "_Updated", true); + continue; + } + + entry.ExtractToFile(fullPath, true); + Console.WriteLine("Restored {0}", entry.FullName); + } + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + Console.WriteLine("Oops... Looks like we cannot update!"); + Console.ReadLine(); + Error = true; + } + finally + { + File.Delete(TempPath); + if (Error) + { + RestoreBackup(); + } + + FinishUpdate(); + } + } + + private void BackupCurrentVersion() + { + Console.WriteLine("Backing up the current version"); + try + { + var dir = Directory.CreateDirectory("BackupSystem"); + var applicationPath = Path.Combine(Path.GetDirectoryName(Application.ExecutablePath)); + + var allfiles = Directory.GetFiles(applicationPath, "*.*", SearchOption.AllDirectories); + BackupPath = Path.Combine(dir.FullName, "PlexRequestsBackup.zip"); + + CheckAndDelete(BackupPath); + using (var fileStream = new FileStream(BackupPath, FileMode.CreateNew)) + using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true)) + { + foreach (var file in allfiles) + { + if (file.Contains("BackupSystem")) + continue; + var info = Path.GetFileName(file); + archive.CreateEntryFromFile(file, info); + } + } + Console.WriteLine("All backed up!"); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine(); + Environment.Exit(1); + } + } + + private void CheckAndDelete(string filePath) + { + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + } + + private DirectoryInfo CreateTempPath() + { + try + { + return Directory.CreateDirectory("UpdateTemp"); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine(); + Environment.Exit(1); + return null; + } + } + + private void FinishUpdate() + { + ProcessStartInfo startInfo; + startInfo = Type.GetType("Mono.Runtime") != null + ? new ProcessStartInfo("mono PlexRequests.exe") { Arguments = Error ? "-u 2" : "-u 1" } + : new ProcessStartInfo("PlexRequests.exe") { Arguments = Error ? "-u 2" : "-u 1" }; + + Process.Start(startInfo); + + Environment.Exit(0); + } + } +} \ No newline at end of file diff --git a/PlexRequests.Updater/app.config b/PlexRequests.Updater/app.config new file mode 100644 index 000000000..de5386a47 --- /dev/null +++ b/PlexRequests.Updater/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/PlexRequests.Updater/packages.config b/PlexRequests.Updater/packages.config new file mode 100644 index 000000000..4d4f826f4 --- /dev/null +++ b/PlexRequests.Updater/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/PlexRequests.sln b/PlexRequests.sln index e3feb5b1d..77eb7e978 100644 --- a/PlexRequests.sln +++ b/PlexRequests.sln @@ -1,6 +1,6 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 +# Visual Studio 2012 VisualStudioVersion = 14.0.25123.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.UI", "PlexRequests.UI\PlexRequests.UI.csproj", "{68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}" @@ -33,12 +33,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Api.Models", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Services.Tests", "PlexRequests.Services.Tests\PlexRequests.Services.Tests.csproj", "{EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlexRequests.Updater", "PlexRequests.Updater\PlexRequests.Updater.csproj", "{EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.Build.0 = Release|Any CPU + {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.Build.0 = Release|Any CPU {68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Debug|Any CPU.Build.0 = Debug|Any CPU {68F5F5F3-B8BB-4911-875F-6F00AAE04EA6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -47,42 +57,40 @@ Global {8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Debug|Any CPU.Build.0 = Debug|Any CPU {8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Release|Any CPU.ActiveCfg = Release|Any CPU {8CB8D235-2674-442D-9C6A-35FCAEEB160D}.Release|Any CPU.Build.0 = Release|Any CPU - {95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.Build.0 = Debug|Any CPU - {95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.ActiveCfg = Release|Any CPU - {95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.Build.0 = Release|Any CPU - {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.Build.0 = Release|Any CPU {92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {92433867-2B7B-477B-A566-96C382427525}.Debug|Any CPU.Build.0 = Debug|Any CPU {92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.ActiveCfg = Release|Any CPU {92433867-2B7B-477B-A566-96C382427525}.Release|Any CPU.Build.0 = Release|Any CPU - {1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1252336D-42A3-482A-804C-836E60173DFA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1252336D-42A3-482A-804C-836E60173DFA}.Release|Any CPU.Build.0 = Release|Any CPU + {95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {95834072-A675-415D-AA8F-877C91623810}.Debug|Any CPU.Build.0 = Debug|Any CPU + {95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.ActiveCfg = Release|Any CPU + {95834072-A675-415D-AA8F-877C91623810}.Release|Any CPU.Build.0 = Release|Any CPU {A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.ActiveCfg = Release|Any CPU {A930E2CF-79E2-45F9-B06A-9A719A254CE4}.Release|Any CPU.Build.0 = Release|Any CPU - {FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.Build.0 = Release|Any CPU - {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {566EFA49-68F8-4716-9693-A6B3F2624DEA}.Release|Any CPU.Build.0 = Release|Any CPU {CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB37A5F8-6DFC-4554-99D3-A42B502E4591}.Release|Any CPU.Build.0 = Release|Any CPU + {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD7DC444-D3BF-4027-8AB9-EFC71F5EC581}.Release|Any CPU.Build.0 = Release|Any CPU {EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {EAADB4AC-064F-4D3A-AFF9-64A33131A9A7}.Release|Any CPU.Build.0 = Release|Any CPU + {EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBE6FC1C-7B4B-47E9-AF54-0EE0604A2BE5}.Release|Any CPU.Build.0 = Release|Any CPU + {FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FCFECD5D-47F6-454D-8692-E27A921BE655}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FCFECD5D-47F6-454D-8692-E27A921BE655}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index c341a273c..f4e8cf5cf 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/tidusjar/plexrequests.net.svg)](http://isitmaintained.com/project/tidusjar/plexrequests.net "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/tidusjar/plexrequests.net.svg)](http://isitmaintained.com/project/tidusjar/plexrequests.net "Percentage of issues still open") [![Github All Releases](https://img.shields.io/github/downloads/tidusjar/PlexRequests.net/total.svg)](https://github.com/tidusjar/PlexRequests.Net) +[![Stories in Progress](https://badge.waffle.io/tidusjar/PlexRequests.Net.svg?label=in progress&title=In Progress)](http://waffle.io/tidusjar/PlexRequests.Net) This is based off [Plex Requests by lokenx](https://github.com/lokenx/plexrequests-meteor) so big props to that guy! I wanted to write a similar application in .Net! @@ -50,4 +51,7 @@ If you feel like donating you can [here!](https://paypal.me/PlexRequestsNet) ## A massive thanks to everyone below for all their help! -[heartisall](https://github.com/heartisall), [Stuke00](https://github.com/Stuke00), [shiitake](https://github.com/shiitake), [Drewster727](https://github.com/Drewster727), Majawat, [EddiYo](https://github.com/EddiYo) +[heartisall](https://github.com/heartisall), [Stuke00](https://github.com/Stuke00), [shiitake](https://github.com/shiitake), [Drewster727](https://github.com/Drewster727), Majawat, [EddiYo](https://github.com/EddiYo), [SaskiFX](https://github.com/SaskiFX) + +## Stats +[![Throughput Graph](https://graphs.waffle.io/tidusjar/PlexRequests.Net/throughput.svg)](https://waffle.io/tidusjar/PlexRequests.Net/metrics/throughput)