diff --git a/CHANGELOG.md b/CHANGELOG.md index a0d3a98..ead8d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [6.0.0] - 2026-03-01 + +- Complete refactoring of the library and how the color conversion is managed +- Fix conversions round trip +- Fix a bug in CMYK to RGB conversion + ## [5.0.0] - 2025-06-06 - Add support for HWB colors (hue, whiteness and blackness) diff --git a/dist/web/colortranslator.js b/dist/web/colortranslator.js index 0d71a8c..ff9ab91 100644 --- a/dist/web/colortranslator.js +++ b/dist/web/colortranslator.js @@ -1 +1 @@ -var colortranslator=function(t){"use strict";const e=255,s=100,r=125,a=150;var i,n,c,o;!function(t){t.HEX="HEX",t.RGB="RGB",t.HWB="HWB",t.HSL="HSL",t.CIELab="CIELab",t.LCH="LCH",t.CMYK="CMYK"}(i||(i={})),t.Harmony=void 0,(n=t.Harmony||(t.Harmony={})).ANALOGOUS="ANALOGOUS",n.COMPLEMENTARY="COMPLEMENTARY",n.SPLIT_COMPLEMENTARY="SPLIT_COMPLEMENTARY",n.TRIADIC="TRIADIC",n.TETRADIC="TETRADIC",n.SQUARE="SQUARE",t.Mix=void 0,(c=t.Mix||(t.Mix={})).ADDITIVE="ADDITIVE",c.SUBTRACTIVE="SUBTRACTIVE",function(t){t.black="#000000",t.silver="#C0C0C0",t.gray="#808080",t.white="#FFFFFF",t.maroon="#800000",t.red="#FF0000",t.purple="#800080",t.fuchsia="#FF00FF",t.green="#008000",t.lime="#00FF00",t.olive="#808000",t.yellow="#FFFF00",t.navy="#000080",t.blue="#0000FF",t.teal="#008080",t.aqua="#00FFFF",t.orange="#FFA500",t.aliceblue="#F0F8FF",t.antiquewhite="#FAEBD7",t.aquamarine="#7FFFD4",t.azure="#F0FFFF",t.beige="#F5F5DC",t.bisque="#FFE4C4",t.blanchedalmond="#FFEBCD",t.blueviolet="#8A2BE2",t.brown="#A52A2A",t.burlywood="#DEB887",t.cadetblue="#5F9EA0",t.chartreuse="#7FFF00",t.chocolate="#D2691E",t.coral="#FF7F50",t.cornflowerblue="#6495ED",t.cornsilk="#FFF8DC",t.crimson="#DC143C",t.cyan="#00FFFF",t.darkblue="#00008B",t.darkcyan="#008B8B",t.darkgoldenrod="#B8860B",t.darkgray="#A9A9A9",t.darkgreen="#006400",t.darkgrey="#A9A9A9",t.darkkhaki="#BDB76B",t.darkmagenta="#8B008B",t.darkolivegreen="#556B2F",t.darkorange="#FF8C00",t.darkorchid="#9932CC",t.darkred="#8B0000",t.darksalmon="#E9967A",t.darkseagreen="#8FBC8F",t.darkslateblue="#483D8B",t.darkslategray="#2F4F4F",t.darkslategrey="#2F4F4F",t.darkturquoise="#00CED1",t.darkviolet="#9400D3",t.deeppink="#FF1493",t.deepskyblue="#00BFFF",t.dimgray="#696969",t.dimgrey="#696969",t.dodgerblue="#1E90FF",t.firebrick="#B22222",t.floralwhite="#FFFAF0",t.forestgreen="#228B22",t.gainsboro="#DCDCDC",t.ghostwhite="#F8F8FF",t.gold="#FFD700",t.goldenrod="#DAA520",t.greenyellow="#ADFF2F",t.grey="#808080",t.honeydew="#F0FFF0",t.hotpink="#FF69B4",t.indianred="#CD5C5C",t.indigo="#4B0082",t.ivory="#FFFFF0",t.khaki="#F0E68C",t.lavender="#E6E6FA",t.lavenderblush="#FFF0F5",t.lawngreen="#7CFC00",t.lemonchiffon="#FFFACD",t.lightblue="#ADD8E6",t.lightcoral="#F08080",t.lightcyan="#E0FFFF",t.lightgoldenrodyellow="#FAFAD2",t.lightgray="#D3D3D3",t.lightgreen="#90EE90",t.lightgrey="#D3D3D3",t.lightpink="#FFB6C1",t.lightsalmon="#FFA07A",t.lightseagreen="#20B2AA",t.lightskyblue="#87CEFA",t.lightslategray="#778899",t.lightslategrey="#778899",t.lightsteelblue="#B0C4DE",t.lightyellow="#FFFFE0",t.limegreen="#32CD32",t.linen="#FAF0E6",t.magenta="#FF00FF",t.mediumaquamarine="#66CDAA",t.mediumblue="#0000CD",t.mediumorchid="#BA55D3",t.mediumpurple="#9370DB",t.mediumseagreen="#3CB371",t.mediumslateblue="#7B68EE",t.mediumspringgreen="#00FA9A",t.mediumturquoise="#48D1CC",t.mediumvioletred="#C71585",t.midnightblue="#191970",t.mintcream="#F5FFFA",t.mistyrose="#FFE4E1",t.moccasin="#FFE4B5",t.navajowhite="#FFDEAD",t.oldlace="#FDF5E6",t.olivedrab="#6B8E23",t.orangered="#FF4500",t.orchid="#DA70D6",t.palegoldenrod="#EEE8AA",t.palegreen="#98FB98",t.paleturquoise="#AFEEEE",t.palevioletred="#DB7093",t.papayawhip="#FFEFD5",t.peachpuff="#FFDAB9",t.peru="#CD853F",t.pink="#FFC0CB",t.plum="#DDA0DD",t.powderblue="#B0E0E6",t.rosybrown="#BC8F8F",t.royalblue="#4169E1",t.saddlebrown="#8B4513",t.salmon="#FA8072",t.sandybrown="#F4A460",t.seagreen="#2E8B57",t.seashell="#FFF5EE",t.sienna="#A0522D",t.skyblue="#87CEEB",t.slateblue="#6A5ACD",t.slategray="#708090",t.slategrey="#708090",t.snow="#FFFAFA",t.springgreen="#00FF7F",t.steelblue="#4682B4",t.tan="#D2B48C",t.thistle="#D8BFD8",t.tomato="#FF6347",t.turquoise="#40E0D0",t.violet="#EE82EE",t.wheat="#F5DEB3",t.whitesmoke="#F5F5F5",t.yellowgreen="#9ACD32",t.rebeccapurple="#663399"}(o||(o={}));const h=Object.keys(o),l={HEX:["R","G","B","A"],RGB:["R","G","B","A"],HSL:["H","S","L","A"],HWB:["H","W","B","A"],CIELab:["L","a","b","A"],LCH:["L","C","H","A"],CMYK:["C","M","Y","K","A"]},u={ABGR:i.RGB,ABHW:i.HWB,ACHL:i.LCH,ACKMY:i.CMYK,AHLS:i.HSL,ALAB:i.CIELab,BGR:i.RGB,BHW:i.HWB,CHL:i.LCH,CKMY:i.CMYK,HLS:i.HSL,LAB:i.CIELab};var d;!function(t){t.NUMBER="number",t.BOOLEAN="boolean"}(d||(d={}));const A={[i.HEX]:/^#(?:(?[a-f\d])(?[a-f\d])(?[a-f\d])(?[a-f\d])?|(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})?)$/i,[i.RGB]:/^rgba?\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[i.HWB]:/^hwb\s*\(\s*(?:(?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s+(?(?:\d*\.)?\d+)%\s+(?(?:\d*\.)?\d+)%(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))%?\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))%?(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[i.HSL]:/^hsla?\s*\(\s*(?:(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s*,\s*(?(?:\d*\.)?\d+)%\s*,\s*(?(?:\d*\.)?\d+)%(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s+(?(?:\d*\.)?\d+)%?\s+(?(?:\d*\.)?\d+)%?(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))%?\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))%?(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[i.CIELab]:/^lab\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[i.LCH]:/^lch\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[i.CMYK]:/^(?:device-cmyk|cmyk)\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?)\s*\)$/},m={REGEXP:/^calc\(\s*(?[\d./*+-\w\s]+)\s*\)$/,SCOPED:/\(\s*([^()]+)\s*\)/g,DIVISION:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,MULTIPLICATION:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\*\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,SUM:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\+\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,REST:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*-\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/},b=/^(?-?(?:\d*\.)?\d+)(?(?:deg|grad|rad|turn)?)$/,g=/^(-?\d+(?:\.\d+)?|-?\.\d+)%$/,H=/^0x([a-f\d]{1,2})$/i,C=/\{(\d+)\}/g,L=/,( +|\d+)/g,B=/ +/,E="The provided string color doesn't have a correct format",p="The provided color object doesn't have the proper keys or format",F="is not a valid operation for a relative color";var R,_,f;!function(t){t.NONE="none",t.DEGREES="deg",t.GRADIANS="grad",t.RADIANS="rad",t.TURNS="turn"}(R||(R={})),function(t){t.NONE="none",t.PERCENT="percent"}(_||(_={})),function(t){t.DEVICE_CMYK="device-cmyk",t.CMYK="cmyk"}(f||(f={}));const M={decimals:6,legacyCSS:!1,spacesAfterCommas:!1,anglesUnit:R.NONE,rgbUnit:_.NONE,labUnit:_.NONE,lchUnit:_.NONE,cmykUnit:_.PERCENT,alphaUnit:_.NONE,cmykFunction:f.DEVICE_CMYK},S=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),G=t=>+`${t}`.replace(g,"$1"),y=t=>g.test(`${t}`)?G(t):Math.min(+t,100),I=t=>(1===t.length&&(t+=t),parseInt(t,16)),w=t=>{const e=W(t,0).toString(16).toUpperCase();return 1===e.length?`0x0${e}`:`0x${e}`},P=(t,s=!1)=>!s&&g.test(t)?Math.min(e*G(t)/100,e):H.test(t)?(3===t.length&&(t+=t.slice(-1)),s?W(t)/e:W(t)):Math.min(+t,s?1:e),O=t=>g.test(t)?j(r*G(t)/100,-125,r):j(+t,-125,r),D=t=>g.test(t)?j(a*G(t)/100,-150,a):j(+t,-150,a),x=t=>Math.min(g.test(t)?G(t)/100:+t,1),k=t=>[...t].sort().join("").toUpperCase(),W=(t,e=6)=>{const s=Math.pow(10,e);return Math.round(+t*s)/s},j=(t,e,s)=>Math.max(e,Math.min(t,s)),v=t=>180*t/Math.PI,N=t=>t*Math.PI/180,$=360,X=t=>{if("string"==typeof t){const e=t.match(b).groups,s=+e.number;switch(e.units){case R.RADIANS:t=W(v(s));break;case R.TURNS:t=W(s*$);break;case R.GRADIANS:t=W(.9*s);break;case R.DEGREES:default:t=s}}return(t>360||t<0)&&(t-=Math.floor(t/$)*$),t},Y=t=>("string"==typeof t&&(t=g.test(t)?G(t)/100:+t),isNaN(+t)||t>1?1:W(t)),U=(t,e)=>{let s;switch(e){case R.RADIANS:s=W(N(t));break;case R.TURNS:s=W(t/$);break;case R.GRADIANS:s=W(10/9*t);break;case R.DEGREES:case R.NONE:default:s=t}return s},T=e=>`${e}`in t.Mix,K=[[.4360747,.3850649,.1430804],[.2225045,.7168786,.0606169],[.0139322,.0971045,.7141733]],V=[[3.1338561,-1.6168667,-.4906146],[-.9787684,1.9161415,.033454],[.0719453,-.2289914,1.4052427]],q=K.map((t=>t.reduce(((t,e)=>t+e),0))),z=(t,s,r)=>(r<0&&(r+=6),r>=6&&(r-=6),W(r<1?((s-t)*r+t)*e:r<3?s*e:r<4?((s-t)*(4-r)+t)*e:t*e)),Q=t=>t<=.04045?t/12.92:((t+.055)/1.055)**2.4,J=t=>t<=.0031308?12.92*t:1.055*t**(1/2.4)-.055,Z=(t,e,s,r)=>{const a=[0,0,0],i=[t,e,s];return r.forEach(((t,e)=>{t.forEach(((t,s)=>{a[e]+=t*i[s]}))})),a},tt=(t,e,s)=>{e/=100;const r=(s/=100)<=.5?s*(e+1):s+e-s*e,a=2*s-r;return{R:z(a,r,(t/=60)+2),G:z(a,r,t),B:z(a,r,t-2)}},et=(t,s,r,a=1)=>{t/=e,s/=e,r/=e,a=Math.min(a,1);const i=Math.max(t,s,r),n=Math.min(t,s,r),c=i-n;let o=0,h=0;const l=(i+n)/2;if(0!==c){switch(i){case t:o=(s-r)/c%6;break;case s:o=(r-t)/c+2;break;case r:o=(t-s)/c+4}o=W(60*o),o<0&&(o+=360),h=c/(1-Math.abs(2*l-1))}return{H:o,S:W(100*h),L:W(100*l),A:a}},st=(t,s,r)=>{const a=[t/e,s/e,r/e].map(Q),i=Z(a[0],a[1],a[2],K),n=((t,e,s)=>{const r=t=>t>(6/29)**3?Math.cbrt(t):t/(3*(6/29)**2)+4/29,a=r(t/q[0]),i=r(e/q[1]);return[116*i-16,500*(a-i),200*(i-r(s/q[2]))]})(i[0],i[1],i[2]);return{L:n[0],a:n[1],b:n[2]}},rt=(t,s,r)=>{const a=((t,e,s)=>{const r=t=>t>6/29?t**3:3*(6/29)**2*(t-4/29),a=(t+16)/116,i=e/500,n=s/200;return[q[0]*r(a+i),q[1]*r(a),q[2]*r(a-n)]})(t,s,r),i=Z(a[0],a[1],a[2],V).map(J);return{R:j(i[0]*e,0,e),G:j(i[1]*e,0,e),B:j(i[2]*e,0,e)}},at=(t,e,s)=>{const r=Math.sqrt(e**2+s**2),a=v(Math.atan2(s,e));return{L:t,C:r,H:X(a)}},it=(t,e,s)=>{const r=N(s);return{L:t,a:e*Math.cos(r),b:e*Math.sin(r)}},nt=(t,e,s)=>{const r=st(t,e,s);return at(r.L,r.a,r.b)},ct=(t,e,s)=>{const r=it(t,e,s);return rt(r.L,r.a,r.b)},ot=(t,s,r,a=1)=>({H:et(t,s,r,a).H,W:W(Math.min(t,s,r)/e*100),B:W(100*(1-Math.max(t,s,r)/e)),A:a}),ht=(t,s,r)=>{const a=1-(r/=100)-(s/=100),i=a*(1-Math.abs(t/60%2-1));let n=0,c=0,o=0;return t<60?(n=a,c=i,o=0):t>=60&&t<120?(n=i,c=a,o=0):t>=120&&t<180?(n=0,c=a,o=i):t>=180&&t<240?(n=0,c=i,o=a):t>=240&&t<300?(n=i,c=0,o=a):(n=a,c=0,o=i),n+=s,c+=s,o+=s,{R:j(n*e,0,e),G:j(c*e,0,e),B:j(o*e,0,e)}},lt=(t,s,r,a)=>({R:W(e*(1-t)*(a=1-a)),G:W(e*(1-s)*a),B:W(e*(1-r)*a)}),ut=(t,s,r)=>{t/=e,s/=e,r/=e;const a=1-Math.max(t,s,r),i=1-a,n=i&&(i-s)/i,c=i&&(i-r)/i;return{C:W(100*(i&&(i-t)/i)),M:W(100*n),Y:W(100*c),K:W(100*a)}},dt=(t,e)=>{if(t<0&&(t+=360),t>360&&(t-=360),360===t||0===t)return t;const s=[[0,120],[120,180],[180,240],[240,360]],r=[[0,60],[60,120],[120,240],[240,360]],a=e?r:s;let i=0,n=0,c=0,o=0;return(e?s:r).find(((e,s)=>t>=e[0]&&tthis._calculate(e,s).toString())),m.REGEXP.test(r)){m.REGEXP.lastIndex=0;break}a++}this._result=this._getCalcValue(r,s)}else this._result=+e}_division(t,e){return t/e}_multiplication(t,e){return t*e}_sum(t,e){return t+e}_rest(t,e){return t-e}_getCalcValue(t,e){const s=t.match(m.REGEXP).groups.operation,r=this._calculate(s,e);if(Number.isNaN(r))throw new Error(`Invalid value for ${this._colorIndex}. ${s} ${F}`);return r}_calculate(t,e){return this._operations.forEach(((s,r)=>{let a=0;for(;r.test(t)&&a<100;)t=t.replace(r,((t,r,a)=>s(e[r]??+r,e[a]??+a).toString())),a++})),+t}get result(){return this._result}}class gt extends At{get hasPercentageAlpha(){return g.test(this._a)}}class Ht extends gt{constructor(t,s){super();const r=t.match(A.RGB).groups,{r_legacy:a,g_legacy:i,b_legacy:n,a_legacy:c,r:o,g:h,b:l,a:u,from:d,relative_r:m,relative_g:b,relative_b:g,relative_a:H}=r;if(d){const t=s(d),r={r:t.R,g:t.G,b:t.B,alpha:t.A??1},a=new bt("r",m,r).result,i=new bt("g",b,r).result,n=new bt("b",g,r).result,c={R:Math.min(a,e),G:Math.min(i,e),B:Math.min(n,e)};if(H){const t=new bt("alpha",H,r).result;c.A=Math.min(t,1)}this._rgb=c}else{this._r=a??o,this._g=i??h,this._b=n??l,this._a=c??u;const t={R:Math.min(P(this._r),e),G:Math.min(P(this._g),e),B:Math.min(P(this._b),e)};void 0!==this._a&&(t.A=Y(this._a)),this._rgb=t}}get hasPercentageValues(){return g.test(this._r)&&g.test(this._g)&&g.test(this._b)}static test(t){return A.RGB.test(t)}}class Ct extends gt{get angleUnit(){if(this._h){const t=this._h.match(b).groups.units;return""===t?R.NONE:t}return R.NONE}}class Lt extends Ct{constructor(t,e){super();const r=t.match(A.HSL).groups,{h_legacy:a,s_legacy:i,l_legacy:n,a_legacy:c,h:o,s:h,l:l,a:u,from:d,relative_h:m,relative_s:b,relative_l:g,relative_a:H}=r;if(d){const t=e(d),r=et(t.R,t.G,t.B,t.A),a={h:r.H,s:r.S,l:r.L,alpha:r.A},i=new bt("h",m,a).result,n=new bt("s",b,a).result,c=new bt("l",g,a).result,o=tt(j(i,0,360),j(n,0,s),j(c,0,s));if(H){const t=new bt("alpha",H,a).result;o.A=j(t,0,1)}this._rgb=o}else{this._h=a??o,this._s=i??h,this._l=n??l,this._a=c??u;const t=tt(X(this._h),y(this._s),y(this._l));void 0!==this._a&&(t.A=Y(this._a)),this._rgb=t}}static test(t){return A.HSL.test(t)}}class Bt extends Ct{constructor(t,e){super();const r=t.match(A.HWB).groups,{h:a,w:i,b:n,a:c,from:o,relative_h:h,relative_w:l,relative_b:u,relative_a:d}=r;if(o){const t=e(o),r=ot(t.R,t.G,t.B,t.A),a={h:r.H,w:r.W,b:r.B,alpha:r.A},i=new bt("h",h,a).result,n=new bt("w",l,a).result,c=new bt("b",u,a).result,A=ht(j(i,0,360),j(n,0,s),j(c,0,s));if(d){const t=new bt("alpha",d,a).result;A.A=j(t,0,1)}this._rgb=A}else{this._h=a,this._w=i,this._b=n,this._a=c;const t=ht(X(this._h),y(this._w),y(this._b));void 0!==this._a&&(t.A=Y(this._a)),this._rgb=t}}static test(t){return A.HWB.test(t)}}class Et extends gt{constructor(t,e){super();const a=t.match(A.CIELab).groups,{L:i,a:n,b:c,A:o,from:h,relative_L:l,relative_a:u,relative_b:d,relative_A:m}=a;if(h){const t=e(h),a=st(t.R,t.G,t.B),i={l:a.L,a:a.a,b:a.b,alpha:t.A??1},n=new bt("l",l,i).result,c=new bt("a",u,i).result,o=new bt("b",d,i).result,A=rt(j(n,0,s),j(c,-125,r),j(o,-125,r));if(m){const t=new bt("alpha",m,i).result;A.A=j(t,0,1)}this._rgb=A}else{this._L=i,this._A=n,this._B=c,this._a=o;const t=rt(y(this._L),O(this._A),O(this._B));void 0!==this._a&&(t.A=Y(this._a)),this._rgb=t}}get hasPercentageValues(){return g.test(this._L)&&g.test(this._A)&&g.test(this._B)}static test(t){return A.CIELab.test(t)}}class pt extends Ct{constructor(t,e){super();const r=t.match(A.LCH).groups,{l:i,c:n,h:c,a:o,from:h,relative_l:l,relative_c:u,relative_h:d,relative_a:m}=r;if(h){const t=e(h),r=nt(t.R,t.G,t.B),i={l:r.L,c:r.C,h:r.H,alpha:t.A??1},n=new bt("l",l,i).result,c=new bt("c",u,i).result,o=new bt("h",d,i).result,A=ct(j(n,0,s),j(c,-150,a),X(o));if(m){const t=new bt("alpha",m,i).result;A.A=j(t,0,1)}this._rgb=A}else{this._l=i,this._c=n,this._h=c,this._a=o;const t=ct(y(this._l),D(this._c),X(this._h));void 0!==this._a&&(t.A=Y(this._a)),this._rgb=t}}get hasPercentageValues(){return g.test(this._l)&&g.test(this._c)}static test(t){return A.LCH.test(t)}}class Ft extends gt{constructor(t){super();const e=t.match(A.CMYK).groups;this._c=e.c_legacy??e.c,this._m=e.m_legacy??e.m,this._y=e.y_legacy??e.y,this._k=e.k_legacy??e.k,this._a=e.a_legacy??e.a;const s=lt(x(this._c),x(this._m),x(this._y),x(this._k));void 0!==this._a&&(s.A=Y(this._a)),this._rgb=s}get hasPercentageValues(){return g.test(this._c)&&g.test(this._m)&&g.test(this._y)&&g.test(this._k)}static test(t){return A.CMYK.test(t)}}const Rt=t=>"string"==typeof t?(t=>{let e;if(Object.keys(i).some((s=>{if(A[s].test(t))return e=s,!0})),!e&&~h.indexOf(t)&&(e=i.HEX),!e)throw new Error(E);return e})(t):(t=>{let s,r=!1;const a=k(Object.keys(t));if(u[a]&&(s=u[a]),s&&s===i.RGB){const a=Object.entries(t).some((t=>!H.test(`${t[1]}`))),n=Object.entries(t).some((t=>!(g.test(`${t[1]}`)||!H.test(`${t[1]}`)&&!isNaN(+t[1])&&+t[1]<=e)));a&&n&&(r=!0),a||(s=i.HEX)}if(!s||r)throw new Error(p);return s})(t),_t={[i.HEX](t){const e=~h.indexOf(t)?o[t]:t;return new mt(e).rgb},[i.RGB]:t=>new Ht(t,Mt).rgb,[i.HSL]:t=>new Lt(t,Mt).rgb,[i.HWB]:t=>new Bt(t,Mt).rgb,[i.CIELab]:t=>new Et(t,Mt).rgb,[i.LCH]:t=>new pt(t,Mt).rgb,[i.CMYK]:t=>new Ft(t).rgb},ft={[i.HEX](t){const e={R:P(`${t.R}`),G:P(`${t.G}`),B:P(`${t.B}`)};return S(t,"A")&&(e.A=Math.min(P(`${t.A}`,!0),1)),e},[i.RGB](t){return this.HEX(t)},[i.HSL](t){const e=y(`${t.S}`),s=y(`${t.L}`),r=tt(X(t.H),e,s);return S(t,"A")&&(r.A=Y(t.A)),r},[i.HWB](t){const e=y(`${t.W}`),s=y(`${t.B}`),r=ht(X(t.H),e,s);return S(t,"A")&&(r.A=Y(t.A)),r},[i.CIELab](t){const e=y(`${t.L}`),s=O(`${t.a}`),r=O(`${t.b}`),a=rt(e,s,r);return S(t,"A")&&(a.A=Y(t.A)),a},[i.LCH](t){const e=y(`${t.L}`),s=D(`${t.C}`),r=X(`${t.H}`),a=ct(e,s,r);return S(t,"A")&&(a.A=Y(t.A)),a},[i.CMYK](t){const e=x(`${t.C}`),s=x(`${t.M}`),r=x(`${t.Y}`),a=x(`${t.K}`),i=lt(e,s,r,a);return S(t,"A")&&(i.A=Y(t.A)),i}},Mt=(t,e=Rt(t))=>"string"==typeof t?_t[e](t):ft[e](t),St=(t,...e)=>{const s=[],r=[],a=[],i=[],n=[],c=[],o=[],h=Object.values(R),l=Object.values(_),u=Object.values(f),A={legacyCSS:0,spacesAfterCommas:0,cmykFunction:0};for(const t of e)if("string"==typeof t){if(s.push(t),t.includes(",")){A.legacyCSS++;const e=t.match(L);1===new Set(e).size&&B.test(e[0].slice(1))&&A.spacesAfterCommas++}if(Lt.test(t)){const e=new Lt(t,Mt);r.push(e.angleUnit),o.push(e.hasPercentageAlpha);continue}if(Bt.test(t)){const e=new Bt(t,Mt);r.push(e.angleUnit),o.push(e.hasPercentageAlpha);continue}if(Ht.test(t)){const e=new Ht(t,Mt);a.push(e.hasPercentageValues),o.push(e.hasPercentageAlpha);continue}if(Et.test(t)){const e=new Et(t,Mt);i.push(e.hasPercentageValues),o.push(e.hasPercentageAlpha);continue}if(pt.test(t)){const e=new pt(t,Mt);r.push(e.angleUnit),n.push(e.hasPercentageValues),o.push(e.hasPercentageAlpha);continue}if(Ft.test(t)){const e=new Ft(t);c.push(e.hasPercentageValues),t.startsWith("cmyk")&&A.cmykFunction++,o.push(e.hasPercentageAlpha)}}return{decimals:typeof t.decimals===d.NUMBER?t.decimals:M.decimals,legacyCSS:typeof t.legacyCSS===d.BOOLEAN?t.legacyCSS:Boolean(s.length&&A.legacyCSS===s.length)||M.legacyCSS,spacesAfterCommas:typeof t.spacesAfterCommas===d.BOOLEAN?t.spacesAfterCommas:Boolean(s.length&&A.spacesAfterCommas===s.length)||M.spacesAfterCommas,anglesUnit:t.anglesUnit&&h.includes(t.anglesUnit)?t.anglesUnit:1===new Set(r).size?r[0]:M.anglesUnit,rgbUnit:t.rgbUnit&&l.includes(t.rgbUnit)?t.rgbUnit:1===new Set(a).size&&a[0]?_.PERCENT:M.rgbUnit,labUnit:t.labUnit&&l.includes(t.labUnit)?t.labUnit:1===new Set(i).size&&i[0]?_.PERCENT:M.labUnit,lchUnit:t.lchUnit&&l.includes(t.lchUnit)?t.lchUnit:1===new Set(n).size&&n[0]?_.PERCENT:M.lchUnit,cmykUnit:t.cmykUnit&&l.includes(t.cmykUnit)?t.cmykUnit:1!==new Set(c).size||c[0]?M.cmykUnit:_.NONE,alphaUnit:t.alphaUnit&&l.includes(t.alphaUnit)?t.alphaUnit:1===new Set(o).size&&o[0]?_.PERCENT:M.alphaUnit,cmykFunction:t.cmykFunction&&u.includes(t.cmykFunction)?t.cmykFunction:c.length&&c.length===A.cmykFunction?f.CMYK:M.cmykFunction}},Gt=(t,e)=>({H:W(t.H,e),S:W(t.S,e),L:W(t.L,e)}),yt=t=>t?", ":",",It=(t,e)=>{const s=k(Object.keys(t));return l[u[s]].reduce(((s,r,a)=>{const i=t[r];return void 0!==i&&s.push(e(i,a)),s}),[])},wt=(t,e)=>t.replace(C,((t,s)=>`${e[+s-1]}`)),Pt=(t,e,s=!1)=>{const{alphaUnit:r,legacyCSS:a,decimals:i}=e;return r!==_.PERCENT||a&&!s?W(t,i):`${W(100*t,i)}%`},Ot=t=>{const{anglesUnit:e,decimals:s}=t;return(r,a)=>{if(0===a&&e!==R.NONE){return`${W(U(r,e),s)}${e}`}return 3===a?Pt(r,t):W(r,s)}},Dt={[i.HEX]:t=>{const e=It(t,(t=>(t=>{let e=W(t,0).toString(16).toUpperCase();return 1===e.length&&(e=`0${e}`),e})(W(t)))),s=4===e.length?"#{1}{2}{3}{4}":"#{1}{2}{3}";return wt(s,e)},[i.RGB]:(t,s)=>{const{decimals:r,legacyCSS:a,spacesAfterCommas:i,rgbUnit:n}=s,c=yt(i),o=It(t,((t,a)=>n===_.PERCENT&&a<3?`${((t,s)=>W(t/e*100,s))(t,r)}%`:3===a?Pt(t,s):W(t,r))),h=a?4===o.length?`rgba({1}${c}{2}${c}{3}${c}{4})`:`rgb({1}${c}{2}${c}{3})`:4===o.length?"rgb({1} {2} {3} / {4})":"rgb({1} {2} {3})";return wt(h,o)},[i.HSL]:(t,e)=>{const{legacyCSS:s,spacesAfterCommas:r}=e,a=yt(r),i=Ot(e),n=It(t,i),c=s?4===n.length?`hsla({1}${a}{2}%${a}{3}%${a}{4})`:`hsl({1}${a}{2}%${a}{3}%)`:4===n.length?"hsl({1} {2}% {3}% / {4})":"hsl({1} {2}% {3}%)";return wt(c,n)},[i.HWB]:(t,e)=>{const s=Ot(e),r=It(t,s),a=4===r.length?"hwb({1} {2}% {3}% / {4})":"hwb({1} {2}% {3}%)";return wt(a,r)},[i.CIELab]:(t,e)=>{const{decimals:s,labUnit:a}=e,i=It(t,((t,i)=>{if(0===i){const e=W(y(t),s);return a===_.PERCENT?`${e}%`:`${e}`}return i<3?a===_.PERCENT?`${((t,e)=>W(t/r*100,e))(t,s)}%`:W(t,s):Pt(t,e,!0)})),n=4===i.length?"lab({1} {2} {3} / {4})":"lab({1} {2} {3})";return wt(n,i)},[i.LCH]:(t,e)=>{const{decimals:s,lchUnit:r,anglesUnit:i}=e,n=It(t,((t,n)=>{if(0===n){const e=W(y(t),s);return r===_.PERCENT?`${e}%`:`${e}`}if(1===n)return r===_.PERCENT?`${((t,e)=>W(t/a*100,e))(t,s)}%`:W(t,s);if(2===n){if(i!==R.NONE){return`${W(U(t,i),s)}${i}`}return W(t,s)}return Pt(t,e,!0)})),c=4===n.length?"lch({1} {2} {3} / {4})":"lch({1} {2} {3})";return wt(c,n)},[i.CMYK]:(t,e)=>{const{decimals:s,legacyCSS:r,spacesAfterCommas:a,cmykUnit:i,cmykFunction:n}=e,c=yt(a),o=It(t,((t,r)=>i===_.PERCENT&&r<4?`${W(t,s)}%`:4===r?Pt(t,e):W(t/100,s))),h=r?5===o.length?`${n}({1}${c}{2}${c}{3}${c}{4}${c}{5})`:`${n}({1}${c}{2}${c}{3}${c}{4})`:5===o.length?`${n}({1} {2} {3} {4} / {5})`:`${n}({1} {2} {3} {4})`;return wt(h,o)}},xt=(e,s,r)=>s.reduce(((s,a)=>[...s,{...e,H:r===t.Mix.ADDITIVE?X(e.H+a):X(dt(dt(e.H,!1)+a,!0))}]),[{...e}]),kt=(t,e)=>xt(t,[30,-30],e),Wt=(t,e)=>xt(t,[180],e),jt=(t,e)=>xt(t,[150,-150],e),vt=(t,e)=>xt(t,[120,-120],e),Nt=(t,e)=>xt(t,[60,-120,180],e),$t=(t,e)=>xt(t,[90,-90,180],e),Xt={[i.HEX]:t=>({R:w(t.R),G:w(t.G),B:w(t.B)}),HEXA(t){const s=Xt.HEX(t);return s.A=S(t,"A")?w(t.A*e):"0xFF",s},[i.RGB](t,e){const s=Kt(t,e);return S(s,"A")&&delete s.A,s},RGBA(t,e){const s=Xt.RGB(t,e);return s.A=S(t,"A")?W(t.A):1,s},[i.HSL](t,e){const s=et(t.R,t.G,t.B);return delete s.A,Gt(s,e)},HSLA(t,e){const s=Xt.HSL(t,e);return s.A=S(t,"A")?W(t.A,e):1,s},[i.HWB](t,e){const s=ot(t.R,t.G,t.B);return delete s.A,((t,e)=>({H:W(t.H,e),W:W(t.W,e),B:W(t.B,e)}))(s,e)},HWBA(t,e){const s=Xt.HWB(t,e);return s.A=S(t,"A")?W(t.A,e):1,s},[i.CIELab]:(t,e)=>((t,e)=>({L:W(t.L,e),a:W(t.a,e),b:W(t.b,e)}))(st(t.R,t.G,t.B),e),CIELabA(t,e){const s=Xt.CIELab(t,e);return s.A=S(t,"A")?W(t.A,e):1,s},[i.LCH]:(t,e)=>((t,e)=>({L:W(t.L,e),C:W(t.C,e),H:W(t.H,e)}))(nt(t.R,t.G,t.B),e),LCHA(t,e){const s=Xt.LCH(t,e);return s.A=S(t,"A")?W(t.A,e):1,s},[i.CMYK]:(t,e)=>((t,e)=>({C:W(t.C,e),M:W(t.M,e),Y:W(t.Y,e),K:W(t.K,e)}))(ut(t.R,t.G,t.B),e),CMYKA(t,e){const s=Xt.CMYK(t,e);return s.A=S(t,"A")?W(t.A,e):1,s}},Yt=(t,s,r,a)=>{const n=Rt(t),c="string"==typeof t,o=Mt(t,n),h="string"==typeof t&&S(o,"A")||"string"!=typeof t&&S(t,"A"),l=et(o.R,o.G,o.B,o.A);h||delete l.A;const u=r?l.L/(s+1):(100-l.L)/(s+1),d=Array(s).fill(null).map(((t,e)=>({...l,L:l.L+u*(e+1)*(1-2*+r)})));switch(n){case i.HEX:default:return d.map((t=>{const s=tt(t.H,t.S,t.L);return h&&(s.A=t.A),c?h?Dt.HEX({...s,A:W(s.A*e)}):Dt.HEX(s):h?Xt.HEXA(s):Xt.HEX(s)}));case i.RGB:return d.map((t=>{const e=tt(t.H,t.S,t.L);return h&&(e.A=t.A),c?Dt.RGB(e,a):h?Xt.RGBA(e,a.decimals):Xt.RGB(e,a.decimals)}));case i.HSL:return d.map((t=>c?Dt.HSL(t,a):h?Xt.HSLA({...tt(t.H,t.S,t.L),A:t.A},a.decimals):Xt.HSL(tt(t.H,t.S,t.L),a.decimals)));case i.HWB:return d.map((t=>{const e=tt(t.H,t.S,t.L);h&&(e.A=t.A);const s=h?Xt.HWBA(e,a.decimals):Xt.HWB(e,a.decimals);return c?Dt.HWB(s,a):s}));case i.CIELab:return d.map((t=>{const e=tt(t.H,t.S,t.L);h&&(e.A=t.A);const s=h?Xt.CIELabA(e,a.decimals):Xt.CIELab(e,a.decimals);return c?Dt.CIELab(s,a):s}));case i.LCH:return d.map((t=>{const e=tt(t.H,t.S,t.L),s=nt(e.R,e.G,e.B);return h&&(s.A=t.A),c?Dt.LCH(s,a):h?Xt.LCHA({...e,A:t.A},a.decimals):Xt.LCH(e,a.decimals)}))}},Ut={buildHarmony(t,e,s,r){const a=Rt(t),n=Mt(t,a),c=et(n.R,n.G,n.B,n.A),o="string"==typeof t&&S(n,"A")||"string"!=typeof t&&S(t,"A"),h="string"==typeof t;switch(a){case i.HEX:default:return o?this.HEXA(Gt(c,0),e,s,h):this.HEX(Gt(c,0),e,s,h);case i.HSL:return o?this.HSLA(c,e,s,h,r):this.HSL(c,e,s,h,r);case i.HWB:return o?this.HWBA(c,e,s,h,r):this.HWB(c,e,s,h,r);case i.RGB:return o?this.RGBA(c,e,s,h,r):this.RGB(c,e,s,h,r);case i.CIELab:return o?this.CIELabA(c,e,s,h,r):this.CIELab(c,e,s,h,r);case i.LCH:return o?this.LCHA(c,e,s,h,r):this.LCH(c,e,s,h,r)}},[i.HEX]:(t,e,s,r)=>e(t,s).map((t=>r?Dt.HEX(tt(t.H,t.S,t.L)):Xt.HEX(tt(t.H,t.S,t.L)))),HEXA:(t,s,r,a)=>s(t,r).map((t=>a?Dt.HEX({...tt(t.H,t.S,t.L),A:Y(t.A)*e}):Xt.HEXA({...tt(t.H,t.S,t.L),A:Y(t.A)}))),[i.RGB]:(t,e,s,r,a)=>e(t,s).map((t=>r?Dt.RGB(tt(t.H,t.S,t.L),a):Xt.RGB(tt(t.H,t.S,t.L),a.decimals))),RGBA:(t,e,s,r,a)=>e(t,s).map((t=>r?Dt.RGB({...tt(t.H,t.S,t.L),A:Y(t.A)},a):Xt.RGBA({...tt(t.H,t.S,t.L),A:Y(t.A)},a.decimals))),[i.HSL]:(t,e,s,r,a)=>e(t,s).map((t=>r?Dt.HSL({H:t.H,S:t.S,L:t.L},a):Xt.HSL(tt(t.H,t.S,t.L),a.decimals))),HSLA:(t,e,s,r,a)=>e(t,s).map((t=>r?Dt.HSL({...t,A:Y(t.A)},a):Xt.HSLA({...tt(t.H,t.S,t.L),A:Y(t.A)},a.decimals))),[i.HWB]:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L),s=ot(e.R,e.G,e.B);return r?Dt.HWB({H:s.H,W:s.W,B:s.B},a):Xt.HWB(e,a.decimals)})),HWBA:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L),s=ot(e.R,e.G,e.B);return r?Dt.HWB({...s,A:Y(t.A)},a):Xt.HWBA({...e,A:Y(t.A)},a.decimals)})),[i.CIELab]:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L);return r?Dt.CIELab(st(e.R,e.G,e.B),a):Xt.CIELab(e,a.decimals)})),CIELabA:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L);return r?Dt.CIELab({...st(e.R,e.G,e.B),A:Y(t.A)},a):Xt.CIELabA({...e,A:Y(t.A)},a.decimals)})),[i.LCH]:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L);return r?Dt.LCH(nt(e.R,e.G,e.B),a):Xt.LCH(e,a.decimals)})),LCHA:(t,e,s,r,a)=>e(t,s).map((t=>{const e=tt(t.H,t.S,t.L);return r?Dt.LCH({...nt(e.R,e.G,e.B),A:Y(t.A)},a):Xt.LCHA({...e,A:Y(t.A)},a.decimals)}))},Tt={mix(s,r){const a=s.map((t=>{const e=Rt(t);return Mt(t,e)})),i=r===t.Mix.SUBTRACTIVE?a.map((t=>{const s=((t,s,r)=>{const a=Math.min(t,s,r),i=Math.min(e-t,e-s,e-r),n=t-a,c=s-a,o=r-a,h=Math.min(n,c),l=n-h,u=(c+h)/2,d=(o+c-h)/2,A=Math.max(l,u,d)/Math.max(n,c,o),m=isNaN(A)||A===1/0||A<=0?1:A;return{R:l/m+i,Y:u/m+i,B:d/m+i}})(t.R,t.G,t.B);return S(t,"A")&&(s.A=t.A),s})):null;function n(s){const a=r===t.Mix.ADDITIVE?{R:0,G:0,B:0,A:0}:{R:0,Y:0,B:0,A:0};return s.reduce(((s,a)=>{const i=S(a,"A")?a.A:1,n={R:Math.min(s.R+a.R*i,e),B:Math.min(s.B+a.B*i,e),A:1-(1-i)*(1-s.A)},c="G"in s?s.G:s.Y,o="G"in a?a.G:a.Y;return{...n,...r===t.Mix.ADDITIVE?{G:Math.min(c+o*i,e)}:{Y:Math.min(c+o*i,e)}}}),a)}let c;if(r===t.Mix.ADDITIVE)c=n(a);else{const t=n(i);c=((t,s,r)=>{const a=Math.min(t,s,r),i=Math.min(e-t,e-s,e-r),n=t-a,c=s-a,o=r-a,h=Math.min(c,o),l=n+c-h,u=c+h,d=2*(o-h),A=Math.max(l,u,d)/Math.max(n,c,o),m=isNaN(A)||A===1/0||A<=0?1:A;return{R:l/m+i,G:u/m+i,B:d/m+i}})(t.R,t.Y,t.B),c.A=t.A}return{R:W(c.R),G:W(c.G),B:W(c.B),A:j(c.A,0,1)}},[i.HEX](t,e,s){const r=this.mix(t,e);return delete r.A,s?Dt.HEX(r):Xt.HEX(r)},HEXA(t,s,r){const a=this.mix(t,s);return a.A=r?Y(a.A)*e:Y(a.A),r?Dt.HEX(a):Xt.HEXA(a)},[i.RGB](t,e,s,r){const a=this.mix(t,e);return delete a.A,s?Dt.RGB(a,r):Xt.RGB(a,r.decimals)},RGBA(t,e,s,r){const a=this.mix(t,e);return s?Dt.RGB(a,r):Xt.RGBA(a,r.decimals)},[i.HSL](t,e,s,r){const a=this.mix(t,e),i=et(a.R,a.G,a.B);return delete a.A,delete i.A,s?Dt.HSL(i,r):Xt.HSL(a,r.decimals)},HSLA(t,e,s,r){const a=this.mix(t,e),i=et(a.R,a.G,a.B,a.A);return s?Dt.HSL(i,r):Xt.HSLA(a,r.decimals)},[i.HWB](t,e,s,r){const a=this.mix(t,e),i=ot(a.R,a.G,a.B);return delete a.A,delete i.A,s?Dt.HWB(i,r):Xt.HWB(a,r.decimals)},HWBA(t,e,s,r){const a=this.mix(t,e),i=ot(a.R,a.G,a.B,a.A);return s?Dt.HWB(i,r):Xt.HWBA(a,r.decimals)},[i.CIELab](t,e,s,r){const a=this.mix(t,e),i=st(a.R,a.G,a.B);return delete a.A,s?Dt.CIELab(i,r):Xt.CIELab(a,r.decimals)},CIELabA(t,e,s,r){const a=this.mix(t,e),i=st(a.R,a.G,a.B);return i.A=a.A,s?Dt.CIELab(i,r):Xt.CIELabA(a,r.decimals)},[i.LCH](t,e,s,r){const a=this.mix(t,e),i=nt(a.R,a.G,a.B);return delete a.A,s?Dt.LCH(i,r):Xt.LCH(a,r.decimals)},LCHA(t,e,s,r){const a=this.mix(t,e),i=nt(a.R,a.G,a.B);return i.A=a.A,s?Dt.LCH(i,r):Xt.LCHA(a,r.decimals)}},Kt=(t,e)=>({R:W(t.R,e),G:W(t.G,e),B:W(t.B,e),...S(t,"A")?{A:W(t.A,e)}:{}}),Vt=(t,e,s,r)=>r(Mt(t,e),s),qt=(t,e,s,r,a)=>{s<1&&(s=5);const i=((t,e,s)=>{const r=s-1,a=(e.R-t.R)/r,i=(e.G-t.G)/r,n=(e.B-t.B)/r,c=Y(t.A),o=(Y(e.A)-c)/r;return Array(s).fill(null).map(((s,h)=>0===h?t:h===r?e:{R:W(t.R+a*h),G:W(t.G+i*h),B:W(t.B+n*h),A:W(c+o*h)}))})(Mt(t),Mt(e),s);return i.map((t=>a(t,r)))};function zt(t){const{from:e,to:s,thirdParameter:r,fourthParameter:a,translateFunction:i,cssFunction:n}=t,c="number"==typeof r?qt(e,s,r,a?.decimals,i):qt(e,s,5,r?.decimals,i);return n?c.map((t=>n(t,St(("number"==typeof r?a:r)??{},e,s)))):c}function Qt(e){const{colors:s,secondParameter:r,thirdParameter:a,colorMixerFunction:i,css:n}=e,c=St(("string"==typeof r?a:r)??{},...s);return i(s,"string"==typeof r?r:t.Mix.ADDITIVE,n,c)}const Jt=(e,s,r,a)=>({[t.Harmony.ANALOGOUS]:Ut.buildHarmony(s,kt,r,a),[t.Harmony.COMPLEMENTARY]:Ut.buildHarmony(s,Wt,r,a),[t.Harmony.SPLIT_COMPLEMENTARY]:Ut.buildHarmony(s,jt,r,a),[t.Harmony.TRIADIC]:Ut.buildHarmony(s,vt,r,a),[t.Harmony.TETRADIC]:Ut.buildHarmony(s,Nt,r,a),[t.Harmony.SQUARE]:Ut.buildHarmony(s,$t,r,a)}[e]),Zt=Object.fromEntries(Object.entries(Tt).map((t=>{const[e,s]=t;return[e,s.bind(Tt)]})));class te{constructor(t,e={}){this._options=St(e,t),this.rgb=Mt(t),this.update("rgb")}update(...t){t.includes("rgb")||this.updateRGB(),t.includes("hsl")||this.updateHSL(),t.includes("hwb")||this.updateHWB(),t.includes("lab")||this.updateLAB(),t.includes("lch")||this.updateLCH(),t.includes("cmyk")||this.updateCMYK()}updateRGB(){this.rgb={...tt(this.hsl.H,this.hsl.S,this.hsl.L),A:this.hsl.A}}updateHSL(){this.hsl=et(this.rgb.R,this.rgb.G,this.rgb.B,this.rgb.A)}updateHWB(){this.hwb=ot(this.rgb.R,this.rgb.G,this.rgb.B,this.rgb.A)}updateLAB(){this.lab={...st(this.rgb.R,this.rgb.G,this.rgb.B),A:this.rgb.A}}updateLCH(){this.lch={...nt(this.rgb.R,this.rgb.G,this.rgb.B),A:this.rgb.A}}updateCMYK(){this.cmyk=ut(this.rgb.R,this.rgb.G,this.rgb.B)}updateRGBFromHWB(){this.rgb={...ht(this.hwb.H,this.hwb.W,this.hwb.B),A:this.rgb.A}}updateRGBFromLCH(){this.rgb={...ct(this.lch.L,this.lch.C,this.lch.H),A:this.rgb.A}}updateRGBFromCMYK(){this.rgb={...lt(this.cmyk.C,this.cmyk.M,this.cmyk.Y,this.cmyk.K),A:this.rgb.A}}updateRGBFromLAB(){this.rgb={...rt(this.lab.L,this.lab.a,this.lab.b),A:this.rgb.A}}updateLCHFromLAB(){this.lch={...at(this.lab.L,this.lab.a,this.lab.b),A:this.lab.A}}updateLABromLCH(){this.lab={...it(this.lch.L,this.lch.C,this.lch.H),A:this.lch.A}}setOptions(t={}){return this._options={...this._options,...t},this}setR(t){this.rgb.R=j(t,0,e),this.update("rgb")}setG(t){return this.rgb.G=j(t,0,e),this.update("rgb"),this}setB(t){return this.rgb.B=j(t,0,e),this.update("rgb"),this}setH(t){return this.hsl.H=X(t),this.update("hsl"),this}setS(t){return this.hsl.S=j(t,0,s),this.update("hsl"),this}setL(t){return this.hsl.L=j(t,0,s),this.update("hsl"),this}setWhiteness(t){return this.hwb.W=j(t,0,s),this.updateRGBFromHWB(),this.update("rgb","hwb"),this}setBlackness(t){return this.hwb.B=j(t,0,s),this.updateRGBFromHWB(),this.update("rgb","hwb"),this}setCIEL(t){return this.lab.L=j(t,0,s),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setCIEa(t){return this.lab.a=j(t,-125,r),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setCIEb(t){return this.lab.b=j(t,-125,r),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setLCHL(t){return this.lch.L=j(t,0,s),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setLCHC(t){return this.lch.C=j(t,0,a),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setLCHH(t){return this.lch.H=X(t),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setA(t){const e=j(t,0,1);return this.rgb.A=e,this.hsl.A=e,this.hwb.A=e,this.lab.A=e,this.lch.A=e,this.cmyk.A=e,this}setC(t){return this.cmyk.C=j(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setM(t){return this.cmyk.M=j(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setY(t){return this.cmyk.Y=j(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setK(t){return this.cmyk.K=j(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}get options(){return this._options}get R(){return W(this.rgb.R,this.options.decimals)}get G(){return W(this.rgb.G,this.options.decimals)}get B(){return W(this.rgb.B,this.options.decimals)}get H(){return W(this.hsl.H,this.options.decimals)}get S(){return W(this.hsl.S,this.options.decimals)}get L(){return W(this.hsl.L,this.options.decimals)}get Whiteness(){return W(this.hwb.W,this.options.decimals)}get Blackness(){return W(this.hwb.B,this.options.decimals)}get CIEL(){return W(this.lab.L,this.options.decimals)}get CIEa(){return W(this.lab.a,this.options.decimals)}get CIEb(){return W(this.lab.b,this.options.decimals)}get LCHL(){return W(this.lch.L,this.options.decimals)}get LCHC(){return W(this.lch.C,this.options.decimals)}get LCHH(){return W(this.lch.H,this.options.decimals)}get A(){return W(this.hsl.A,this.options.decimals)}get C(){return W(this.cmyk.C,this.options.decimals)}get M(){return W(this.cmyk.M,this.options.decimals)}get Y(){return W(this.cmyk.Y,this.options.decimals)}get K(){return W(this.cmyk.K,this.options.decimals)}get HEXObject(){return Xt.HEX(this.rgb)}get HEXAObject(){return Xt.HEXA(this.rgb)}get RGBObject(){return{R:this.R,G:this.G,B:this.B}}get RGBAObject(){return{...this.RGBObject,A:this.A}}get HSLObject(){return{H:this.H,S:this.S,L:this.L}}get HSLAObject(){return{...this.HSLObject,A:this.A}}get HWBObject(){return{H:this.H,W:this.Whiteness,B:this.Blackness}}get HWBAObject(){return{...this.HWBObject,A:this.A}}get CIELabObject(){return{L:this.CIEL,a:this.CIEa,b:this.CIEb}}get CIELabAObject(){return{...this.CIELabObject,A:this.A}}get LCHObject(){return{L:this.LCHL,C:this.LCHC,H:this.LCHH}}get LCHAObject(){return{...this.LCHObject,A:this.A}}get CMYKObject(){return{C:this.C,M:this.M,Y:this.Y,K:this.K}}get CMYKAObject(){return{...this.CMYKObject,A:this.A}}get HEX(){return Dt.HEX({R:this.R,G:this.G,B:this.B})}get HEXA(){return Dt.HEX({R:this.R,G:this.G,B:this.B,A:this.A*e})}get RGB(){return Dt.RGB({R:this.R,G:this.G,B:this.B},this.options)}get RGBA(){return Dt.RGB({R:this.R,G:this.G,B:this.B,A:this.A},this.options)}get HSL(){return Dt.HSL({H:this.H,S:this.S,L:this.L},this.options)}get HSLA(){return Dt.HSL({H:this.H,S:this.S,L:this.L,A:this.A},this.options)}get HWB(){return Dt.HWB({H:this.H,W:this.Whiteness,B:this.Blackness},this.options)}get HWBA(){return Dt.HWB({H:this.H,W:this.Whiteness,B:this.Blackness,A:this.A},this.options)}get CIELab(){return Dt.CIELab({L:this.CIEL,a:this.CIEa,b:this.CIEb},this.options)}get CIELabA(){return Dt.CIELab({L:this.CIEL,a:this.CIEa,b:this.CIEb,A:this.A},this.options)}get LCH(){return Dt.LCH({L:this.LCHL,C:this.LCHC,H:this.LCHH},this.options)}get LCHA(){return Dt.LCH({L:this.LCHL,C:this.LCHC,H:this.LCHH,A:this.A},this.options)}get CMYK(){return Dt.CMYK({C:this.C,M:this.M,Y:this.Y,K:this.K},this.options)}get CMYKA(){return Dt.CMYK({C:this.C,M:this.M,Y:this.Y,K:this.K,A:this.A},this.options)}static toHEXObject(t){const e=Rt(t);return Vt(t,e,0,Xt.HEX)}static toHEX(t){return Dt.HEX(te.toHEXObject(t))}static toHEXAObject(t){const e=Rt(t);return Vt(t,e,0,Xt.HEXA)}static toHEXA(t){return Dt.HEX(te.toHEXAObject(t))}static toRGBObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.RGB)}static toRGB(t,e={}){const s=te.toRGBObject(t,e),r=St(e,t);return Dt.RGB(s,r)}static toRGBAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.RGBA)}static toRGBA(t,e={}){const s=te.toRGBAObject(t,e),r=St(e,t);return Dt.RGB(s,r)}static toHSLObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.HSL)}static toHSL(t,e={}){const s=te.toHSLObject(t,e),r=St(e,t);return Dt.HSL(s,r)}static toHSLAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.HSLA)}static toHSLA(t,e={}){const s=te.toHSLAObject(t,e),r=St(e,t);return Dt.HSL(s,r)}static toHWBObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.HWB)}static toHWB(t,e={}){const s=te.toHWBObject(t,e),r=St(e,t);return Dt.HWB(s,r)}static toHWBAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.HWBA)}static toHWBA(t,e={}){const s=te.toHWBAObject(t,e),r=St(e,t);return Dt.HWB(s,r)}static toCIELabObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.CIELab)}static toCIELab(t,e={}){const s=te.toCIELabObject(t,e),r=St(e,t);return Dt.CIELab(s,r)}static toCIELabAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.CIELabA)}static toCIELabA(t,e={}){const s=te.toCIELabAObject(t,e),r=St(e,t);return Dt.CIELab(s,r)}static toLCHObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.LCH)}static toLCH(t,e={}){const s=te.toLCHObject(t,e),r=St(e,t);return Dt.LCH(s,r)}static toLCHAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.LCHA)}static toLCHA(t,e={}){const s=te.toLCHAObject(t,e),r=St(e,t);return Dt.LCH(s,r)}static toCMYKObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.CMYK)}static toCMYK(t,e={}){const s=te.toCMYKObject(t,e),r=St(e,t);return Dt.CMYK(s,r)}static toCMYKAObject(t,e={}){const s=Rt(t);return Vt(t,s,e.decimals,Xt.CMYKA)}static toCMYKA(t,e={}){const s=te.toCMYKAObject(t,e),r=St(e,t);return Dt.CMYK(s,r)}static getBlendHEXObject(t,e,s=5){return qt(t,e,s,0,Xt.HEX)}static getBlendHEX(t,e,s=5){return te.getBlendHEXObject(t,e,s).map((t=>Dt.HEX(t)))}static getBlendHEXAObject(t,e,s=5){return qt(t,e,s,0,Xt.HEXA)}static getBlendHEXA(t,e,s=5){return te.getBlendHEXAObject(t,e,s).map((t=>Dt.HEX(t)))}static getBlendRGBObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.RGB})}static getBlendRGB(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.RGB,cssFunction:Dt.RGB})}static getBlendRGBAObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.RGBA})}static getBlendRGBA(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.RGBA,cssFunction:Dt.RGB})}static getBlendHSLObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HSL})}static getBlendHSL(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HSL,cssFunction:Dt.HSL})}static getBlendHSLAObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HSLA})}static getBlendHSLA(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HSLA,cssFunction:Dt.HSL})}static getBlendHWBObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HWB})}static getBlendHWB(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HWB,cssFunction:Dt.HWB})}static getBlendHWBAObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HWBA})}static getBlendHWBA(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.HWBA,cssFunction:Dt.HWB})}static getBlendCIELabObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.CIELab})}static getBlendCIELab(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.CIELab,cssFunction:Dt.CIELab})}static getBlendCIELabAObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.CIELabA})}static getBlendCIELabA(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.CIELabA,cssFunction:Dt.CIELab})}static getBlendLCHObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.LCH})}static getBlendLCH(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.LCH,cssFunction:Dt.LCH})}static getBlendLCHAObject(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.LCHA})}static getBlendLCHA(t,e,s,r){return zt({from:t,to:e,thirdParameter:s,fourthParameter:r,translateFunction:Xt.LCHA,cssFunction:Dt.LCH})}static getMixHEXObject(e,s=t.Mix.ADDITIVE){return Tt.HEX(e,s,!1)}static getMixHEX(e,s=t.Mix.ADDITIVE){return Tt.HEX(e,s,!0)}static getMixHEXAObject(e,s=t.Mix.ADDITIVE){return Tt.HEXA(e,s,!1)}static getMixHEXA(e,s=t.Mix.ADDITIVE){return Tt.HEXA(e,s,!0)}static getMixRGBObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.RGB,css:!1})}static getMixRGB(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.RGB,css:!0})}static getMixRGBAObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.RGBA,css:!1})}static getMixRGBA(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.RGBA,css:!0})}static getMixHSLObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HSL,css:!1})}static getMixHSL(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HSL,css:!0})}static getMixHSLAObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HSLA,css:!1})}static getMixHSLA(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HSLA,css:!0})}static getMixHWBObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HWB,css:!1})}static getMixHWB(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HWB,css:!0})}static getMixHWBAObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HWBA,css:!1})}static getMixHWBA(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.HWBA,css:!0})}static getMixCIELabObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.CIELab,css:!1})}static getMixCIELab(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.CIELab,css:!0})}static getMixCIELabAObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.CIELabA,css:!1})}static getMixCIELabA(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.CIELabA,css:!0})}static getMixLCHObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.LCH,css:!1})}static getMixLCH(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.LCH,css:!0})}static getMixLCHAObject(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.LCHA,css:!1})}static getMixLCHA(t,e,s){return Qt({colors:t,secondParameter:e,thirdParameter:s,colorMixerFunction:Zt.LCHA,css:!0})}static getShades(t,e,s){return"number"==typeof e?Yt(t,e,!0,St(s||{},t)):Yt(t,5,!0,St(e||{},t))}static getTints(t,e,s){return"number"==typeof e?Yt(t,e,!1,St(s||{},t)):Yt(t,5,!1,St(e||{},t))}static getHarmony(e,s,r,a){return`${s}`in t.Harmony?Jt(s,e,T(r)?r:t.Mix.ADDITIVE,St(T(r)?a||{}:r||{},e)):T(s)?Jt(t.Harmony.COMPLEMENTARY,e,s,St(r||{},e)):Jt(t.Harmony.COMPLEMENTARY,e,t.Mix.ADDITIVE,St(s||{},e))}}return t.ColorTranslator=te,t}({}); +var colortranslator=function(t){"use strict";var e,s,r,a,n,i,c;!function(t){t.NONE="none",t.DEGREES="deg",t.GRADIANS="grad",t.RADIANS="rad",t.TURNS="turn"}(e||(e={})),function(t){t.NONE="none",t.PERCENT="percent"}(s||(s={})),function(t){t.DEVICE_CMYK="device-cmyk",t.CMYK="cmyk"}(r||(r={})),function(t){t.HEX="HEX",t.RGB="RGB",t.HWB="HWB",t.HSL="HSL",t.CIELab="CIELab",t.LCH="LCH",t.CMYK="CMYK"}(a||(a={})),t.Harmony=void 0,(n=t.Harmony||(t.Harmony={})).ANALOGOUS="ANALOGOUS",n.COMPLEMENTARY="COMPLEMENTARY",n.SPLIT_COMPLEMENTARY="SPLIT_COMPLEMENTARY",n.TRIADIC="TRIADIC",n.TETRADIC="TETRADIC",n.SQUARE="SQUARE",t.Mix=void 0,(i=t.Mix||(t.Mix={})).ADDITIVE="ADDITIVE",i.SUBTRACTIVE="SUBTRACTIVE",function(t){t.black="#000000",t.silver="#C0C0C0",t.gray="#808080",t.white="#FFFFFF",t.maroon="#800000",t.red="#FF0000",t.purple="#800080",t.fuchsia="#FF00FF",t.green="#008000",t.lime="#00FF00",t.olive="#808000",t.yellow="#FFFF00",t.navy="#000080",t.blue="#0000FF",t.teal="#008080",t.aqua="#00FFFF",t.orange="#FFA500",t.aliceblue="#F0F8FF",t.antiquewhite="#FAEBD7",t.aquamarine="#7FFFD4",t.azure="#F0FFFF",t.beige="#F5F5DC",t.bisque="#FFE4C4",t.blanchedalmond="#FFEBCD",t.blueviolet="#8A2BE2",t.brown="#A52A2A",t.burlywood="#DEB887",t.cadetblue="#5F9EA0",t.chartreuse="#7FFF00",t.chocolate="#D2691E",t.coral="#FF7F50",t.cornflowerblue="#6495ED",t.cornsilk="#FFF8DC",t.crimson="#DC143C",t.cyan="#00FFFF",t.darkblue="#00008B",t.darkcyan="#008B8B",t.darkgoldenrod="#B8860B",t.darkgray="#A9A9A9",t.darkgreen="#006400",t.darkgrey="#A9A9A9",t.darkkhaki="#BDB76B",t.darkmagenta="#8B008B",t.darkolivegreen="#556B2F",t.darkorange="#FF8C00",t.darkorchid="#9932CC",t.darkred="#8B0000",t.darksalmon="#E9967A",t.darkseagreen="#8FBC8F",t.darkslateblue="#483D8B",t.darkslategray="#2F4F4F",t.darkslategrey="#2F4F4F",t.darkturquoise="#00CED1",t.darkviolet="#9400D3",t.deeppink="#FF1493",t.deepskyblue="#00BFFF",t.dimgray="#696969",t.dimgrey="#696969",t.dodgerblue="#1E90FF",t.firebrick="#B22222",t.floralwhite="#FFFAF0",t.forestgreen="#228B22",t.gainsboro="#DCDCDC",t.ghostwhite="#F8F8FF",t.gold="#FFD700",t.goldenrod="#DAA520",t.greenyellow="#ADFF2F",t.grey="#808080",t.honeydew="#F0FFF0",t.hotpink="#FF69B4",t.indianred="#CD5C5C",t.indigo="#4B0082",t.ivory="#FFFFF0",t.khaki="#F0E68C",t.lavender="#E6E6FA",t.lavenderblush="#FFF0F5",t.lawngreen="#7CFC00",t.lemonchiffon="#FFFACD",t.lightblue="#ADD8E6",t.lightcoral="#F08080",t.lightcyan="#E0FFFF",t.lightgoldenrodyellow="#FAFAD2",t.lightgray="#D3D3D3",t.lightgreen="#90EE90",t.lightgrey="#D3D3D3",t.lightpink="#FFB6C1",t.lightsalmon="#FFA07A",t.lightseagreen="#20B2AA",t.lightskyblue="#87CEFA",t.lightslategray="#778899",t.lightslategrey="#778899",t.lightsteelblue="#B0C4DE",t.lightyellow="#FFFFE0",t.limegreen="#32CD32",t.linen="#FAF0E6",t.magenta="#FF00FF",t.mediumaquamarine="#66CDAA",t.mediumblue="#0000CD",t.mediumorchid="#BA55D3",t.mediumpurple="#9370DB",t.mediumseagreen="#3CB371",t.mediumslateblue="#7B68EE",t.mediumspringgreen="#00FA9A",t.mediumturquoise="#48D1CC",t.mediumvioletred="#C71585",t.midnightblue="#191970",t.mintcream="#F5FFFA",t.mistyrose="#FFE4E1",t.moccasin="#FFE4B5",t.navajowhite="#FFDEAD",t.oldlace="#FDF5E6",t.olivedrab="#6B8E23",t.orangered="#FF4500",t.orchid="#DA70D6",t.palegoldenrod="#EEE8AA",t.palegreen="#98FB98",t.paleturquoise="#AFEEEE",t.palevioletred="#DB7093",t.papayawhip="#FFEFD5",t.peachpuff="#FFDAB9",t.peru="#CD853F",t.pink="#FFC0CB",t.plum="#DDA0DD",t.powderblue="#B0E0E6",t.rosybrown="#BC8F8F",t.royalblue="#4169E1",t.saddlebrown="#8B4513",t.salmon="#FA8072",t.sandybrown="#F4A460",t.seagreen="#2E8B57",t.seashell="#FFF5EE",t.sienna="#A0522D",t.skyblue="#87CEEB",t.slateblue="#6A5ACD",t.slategray="#708090",t.slategrey="#708090",t.snow="#FFFAFA",t.springgreen="#00FF7F",t.steelblue="#4682B4",t.tan="#D2B48C",t.thistle="#D8BFD8",t.tomato="#FF6347",t.turquoise="#40E0D0",t.violet="#EE82EE",t.wheat="#F5DEB3",t.whitesmoke="#F5F5F5",t.yellowgreen="#9ACD32",t.rebeccapurple="#663399"}(c||(c={}));const l={[a.HEX]:/^#(?:(?[a-f\d])(?[a-f\d])(?[a-f\d])(?[a-f\d])?|(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})?)$/i,[a.RGB]:/^rgba?\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))\s+(?(?:[rgb]|(?:\d*\.)?\d+|calc\([rgb()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[a.HWB]:/^hwb\s*\(\s*(?:(?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s+(?(?:\d*\.)?\d+)%\s+(?(?:\d*\.)?\d+)%(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))%?\s+(?(?:[hwb]|(?:\d*\.)?\d+|calc\([hwb()/*\-+\d.\s]+\)))%?(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[a.HSL]:/^hsla?\s*\(\s*(?:(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s*,\s*(?(?:\d*\.)?\d+)%\s*,\s*(?(?:\d*\.)?\d+)%(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)\s+(?(?:\d*\.)?\d+)%?\s+(?(?:\d*\.)?\d+)%?(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))%?\s+(?(?:[hsl]|(?:\d*\.)?\d+|calc\([hsl()/*\-+\d.\s]+\)))%?(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[a.CIELab]:/^lab\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))\s+(?(?:[lab]|(?:\d*\.)?\d+|calc\([lab()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[a.LCH]:/^lch\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+%?)\s+(?-?(?:\d*\.)?\d+(?:deg|grad|rad|turn)?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?|from\s+(?(?:\w+|\w+\(\s*[^())]+\s*\)|\w+\(from\s+\w+\(.*\)\s*\)|#[a-fA-F\d]+))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))\s+(?(?:[lch]|(?:\d*\.)?\d+|calc\([lch()/*\-+\d.\s]+\)))(?:\s*\/\s*(?(?:(?:\d*\.)?\d+%?|calc\([()/*\-+\d.\s\w]*(?:alpha)?[()/*\-+\d.\s\w]*\)|alpha)))?)\s*\)$/,[a.CMYK]:/^(?:device-cmyk|cmyk)\s*\(\s*(?:(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)\s*,\s*(?(?:\d*\.)?\d+%?)(?:\s*,\s*(?(?:\d*\.)?\d+))?|(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)\s+(?(?:\d*\.)?\d+%?)(?:\s*\/\s*(?(?:\d*\.)?\d+%?))?)\s*\)$/},h={REGEXP:/^calc\(\s*(?[\d./*+-\w\s]+)\s*\)$/,SCOPED:/\(\s*([^()]+)\s*\)/g,DIVISION:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,MULTIPLICATION:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\*\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,SUM:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*\+\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/,REST:/\s*(?(?:(?:\d*\.)?\d+|\w+))\s*-\s*(?(?:(?:\d*\.)?\d+|\w+))\s*/},o=/^(?-?(?:\d*\.)?\d+)(?(?:deg|grad|rad|turn)?)$/,u=/^(-?\d+(?:\.\d+)?|-?\.\d+)%$/,d=/^0x([a-f\d]{1,2})$/i,g=/\{(\d+)\}/g,b=/,( +|\d+)/g,C=/ +/,A=255,p=360,m=100,B=125,H=150,L=Object.keys(c),E=Object.freeze({HEX:["R","G","B","A"],RGB:["R","G","B","A"],HSL:["H","S","L","A"],HWB:["H","W","B","A"],CIELab:["L","a","b","A"],LCH:["L","C","H","A"],CMYK:["C","M","Y","K","A"]}),S=Object.freeze({ABGR:a.RGB,ABHW:a.HWB,ACHL:a.LCH,ACKMY:a.CMYK,AHLS:a.HSL,ALAB:a.CIELab,BGR:a.RGB,BHW:a.HWB,CHL:a.LCH,CKMY:a.CMYK,HLS:a.HSL,LAB:a.CIELab}),F=Object.freeze({decimals:6,legacyCSS:!1,spacesAfterCommas:!1,anglesUnit:e.NONE,rgbUnit:s.NONE,labUnit:s.NONE,lchUnit:s.NONE,cmykUnit:s.PERCENT,alphaUnit:s.NONE,cmykFunction:r.DEVICE_CMYK}),R=Object.freeze({NOT_ACCEPTED_INPUT:"The provided string color doesn't have a correct format",NOT_A_VALID_RELATIVE_COLOR:"is not a valid operation for a relative color"}),v=t=>[...t].sort().join("").toUpperCase(),M=t=>"string"==typeof t,y=t=>"number"==typeof t,_=t=>"boolean"==typeof t,f=t=>void 0===t,w=t=>S[v(Object.keys(t))],O=t=>w(t)===a.RGB,G=t=>w(t)===a.HSL,I=t=>w(t)===a.HWB,D=t=>w(t)===a.CIELab,k=t=>w(t)===a.LCH,x=t=>w(t)===a.CMYK,N=t=>+`${t}`.replace(u,"$1"),j=t=>u.test(`${t}`)?N(t):Math.min(+t,100),$=t=>(1===t.length&&(t+=t),parseInt(t,16)),Y=t=>{const e=K(t,0).toString(16).toUpperCase();return 1===e.length?`0x0${e}`:`0x${e}`},T=(t,e=!1)=>!e&&u.test(t)?Math.min(A*N(t)/100,A):d.test(t)?(3===t.length&&(t+=t.slice(-1)),e?K(t)/A:K(t)):Math.min(+t,e?1:A),W=t=>u.test(t)?X(B*N(t)/100,-125,B):X(+t,-125,B),U=t=>u.test(t)?X(H*N(t)/100,-150,H):X(+t,-150,H),P=(t,e)=>{const s=u.test(t)?N(t):+t;return e?Math.min(100*s,100):Math.min(s,100)},K=(t,e=6)=>{const s=Math.pow(10,e);return Math.round(+t*s)/s},X=(t,e,s)=>Math.max(e,Math.min(t,s)),V=t=>180*t/Math.PI,z=t=>t*Math.PI/180,q=t=>{if(M(t)){const s=t.match(o).groups,r=+s.number;switch(s.units){case e.RADIANS:t=K(V(r));break;case e.TURNS:t=K(r*p);break;case e.GRADIANS:t=K(.9*r);break;case e.DEGREES:default:t=r}}return(t>=p||t<0)&&(t-=Math.floor(t/p)*p),t},Q=t=>(M(t)&&(t=u.test(t)?N(t)/100:+t),isNaN(+t)||t>1?1:K(t)),J=(t,s)=>{let r;switch(s){case e.RADIANS:r=K(z(t));break;case e.TURNS:r=K(t/p);break;case e.GRADIANS:r=K(1.1111111111111112*t);break;case e.DEGREES:case e.NONE:default:r=t}return r},Z=e=>`${e}`in t.Mix,tt=t=>{if(t){const s=t.match(o).groups.units;return""===s?e.NONE:s}return e.NONE},et=[[.4360747,.3850649,.1430804],[.2225045,.7168786,.0606169],[.0139322,.0971045,.7141733]],st=[[3.1338561,-1.6168667,-.4906146],[-.9787684,1.9161415,.033454],[.0719453,-.2289914,1.4052427]],rt=et.map((t=>t.reduce(((t,e)=>t+e),0))),at=(t,e,s)=>(s<0&&(s+=6),s>=6&&(s-=6),K(s<1?((e-t)*s+t)*A:s<3?e*A:s<4?((e-t)*(4-s)+t)*A:t*A)),nt=t=>t<=.04045?t/12.92:((t+.055)/1.055)**2.4,it=t=>t<=.0031308?12.92*t:1.055*t**(1/2.4)-.055,ct=(t,e,s,r)=>{const a=[0,0,0],n=[t,e,s];return r.forEach(((t,e)=>{t.forEach(((t,s)=>{a[e]+=t*n[s]}))})),a},lt=(t,e,s)=>{e/=100;const r=(s/=100)<=.5?s*(e+1):s+e-s*e,a=2*s-r;return{R:at(a,r,(t/=60)+2),G:at(a,r,t),B:at(a,r,t-2)}},ht=(t,e,s,r=1)=>{t/=A,e/=A,s/=A,r=Math.min(r,1);const a=Math.max(t,e,s),n=Math.min(t,e,s),i=a-n;let c=0,l=0;const h=(a+n)/2;if(0!==i){switch(a){case t:c=(e-s)/i%6;break;case e:c=(s-t)/i+2;break;case s:c=(t-e)/i+4}c=K(60*c),c<0&&(c+=360),l=i/(1-Math.abs(2*h-1))}return{H:c,S:K(100*l),L:K(100*h),A:r}},ot=(t,e,s)=>{const r=[t/A,e/A,s/A].map(nt),a=ct(r[0],r[1],r[2],et),n=((t,e,s)=>{const r=t=>t>(6/29)**3?Math.cbrt(t):t/(3*(6/29)**2)+4/29,a=r(t/rt[0]),n=r(e/rt[1]);return[116*n-16,500*(a-n),200*(n-r(s/rt[2]))]})(a[0],a[1],a[2]);return{L:n[0],a:n[1],b:n[2]}},ut=(t,e,s)=>{const r=((t,e,s)=>{const r=t=>t>6/29?t**3:3*(6/29)**2*(t-4/29),a=(t+16)/116,n=e/500,i=s/200;return[rt[0]*r(a+n),rt[1]*r(a),rt[2]*r(a-i)]})(t,e,s),a=ct(r[0],r[1],r[2],st).map(it);return{R:X(a[0]*A,0,A),G:X(a[1]*A,0,A),B:X(a[2]*A,0,A)}},dt=(t,e,s)=>{const r=Math.sqrt(e**2+s**2),a=V(Math.atan2(s,e));return{L:t,C:r,H:q(a)}},gt=(t,e,s)=>{const r=z(s);return{L:t,a:e*Math.cos(r),b:e*Math.sin(r)}},bt=(t,e,s)=>{const r=ot(t,e,s);return dt(r.L,r.a,r.b)},Ct=(t,e,s)=>{const r=gt(t,e,s);return ut(r.L,r.a,r.b)},At=(t,e,s,r=1)=>({H:ht(t,e,s,r).H,W:K(Math.min(t,e,s)/A*100),B:K(100*(1-Math.max(t,e,s)/A)),A:r}),pt=(t,e,s)=>{const r=1-(s/=100)-(e/=100),a=r*(1-Math.abs(t/60%2-1));let n,i,c;return t<60?(n=r,i=a,c=0):t>=60&&t<120?(n=a,i=r,c=0):t>=120&&t<180?(n=0,i=r,c=a):t>=180&&t<240?(n=0,i=a,c=r):t>=240&&t<300?(n=a,i=0,c=r):(n=r,i=0,c=a),n+=e,i+=e,c+=e,{R:X(n*A,0,A),G:X(i*A,0,A),B:X(c*A,0,A)}},mt=(t,e,s,r)=>({R:X(K(A*(1-t)*(r=1-r)),0,A),G:X(K(A*(1-e)*r),0,A),B:X(K(A*(1-s)*r),0,A)}),Bt=(t,e,s)=>{t/=A,e/=A,s/=A;const r=1-Math.max(t,e,s),a=1-r,n=a&&(a-e)/a,i=a&&(a-s)/a;return{C:K(100*(a&&(a-t)/a)),M:K(100*n),Y:K(100*i),K:K(100*r)}},Ht=(t,e)=>{if(t<0&&(t+=360),t>360&&(t-=360),360===t||0===t)return t;const s=[[0,120],[120,180],[180,240],[240,360]],r=[[0,60],[60,120],[120,240],[240,360]],a=e?r:s;let n=0,i=0,c=0,l=0;return(e?s:r).find(((e,s)=>t>=e[0]&&t{const e=(t=>f(t.A)?{}:{A:+t.A})(t);return G(t)?{...lt(t.H,t.S,t.L),...e}:I(t)?{...pt(t.H,t.W,t.B),...e}:D(t)?{...ut(t.L,t.a,t.b),...e}:k(t)?{...Ct(t.L,t.C,t.H),...e}:x(t)?{...mt(t.C,t.M,t.Y,t.K),...e}:t},St=t=>t?", ":",",Ft=(t,e)=>{const s=v(Object.keys(t)),r=S[s];return E[r].reduce(((s,r,a)=>{const n=t[r];return void 0!==n&&s.push(e(n,a)),s}),[])},Rt=(t,e)=>t.replace(g,((t,s)=>`${e[+s-1]}`)),vt=(t,e,r=!1)=>{const{alphaUnit:a,legacyCSS:n,decimals:i}=e;return a!==s.PERCENT||n&&!r?K(t,i):`${K(100*t,i)}%`},Mt=t=>{const{anglesUnit:s,decimals:r}=t;return(a,n)=>{if(0===n&&s!==e.NONE){return`${K(J(a,s),r)}${s}`}return 3===n?vt(a,t):K(a,r)}};class yt{constructor(t,e,s){this._operations=new Map([[h.DIVISION,this._division],[h.MULTIPLICATION,this._multiplication],[h.SUM,this._sum],[h.REST,this._rest]]),this._colorIndex=t;let r=e,a=0;if(Number.isNaN(+e))if(e in s)this._result=s[e];else if(h.REGEXP.test(r))h.REGEXP.lastIndex=0,this._result=this._getCalcValue(r,s);else{for(;h.SCOPED.test(r)&&a<100;){if(h.SCOPED.lastIndex=0,r=r.replace(h.SCOPED,((t,e)=>this._calculate(e,s).toString())),h.REGEXP.test(r)){h.REGEXP.lastIndex=0;break}a++}this._result=this._getCalcValue(r,s)}else this._result=+e}_division(t,e){return t/e}_multiplication(t,e){return t*e}_sum(t,e){return t+e}_rest(t,e){return t-e}_getCalcValue(t,e){const s=t.match(h.REGEXP).groups.operation,r=this._calculate(s,e);if(Number.isNaN(r))throw new Error(`Invalid value for ${this._colorIndex}. ${s} ${R.NOT_A_VALID_RELATIVE_COLOR}`);return r}_calculate(t,e){return this._operations.forEach(((s,r)=>{let a=0;for(;r.test(t)&&a<100;)t=t.replace(r,((t,r,a)=>s(e[r]??+r,e[a]??+a).toString())),a++})),+t}get result(){return this._result}}const _t=new class extends Lt{_extract(t){return(~L.indexOf(t)?c[t]:t).match(l.HEX).groups}supports(t){if(M(t))return l.HEX.test(t)||!!~L.indexOf(t);const e=Object.entries(t).some((t=>!d.test(`${t[1]}`)));return O(t)&&!e}parse(t){if(M(t)){const e=this._extract(t),s=e.r??e.rr,r=e.g??e.gg,a=e.b??e.bb,n=e.a??e.aa;return{R:$(s),G:$(r),B:$(a),...f(n)?{}:{A:$(n)/A}}}return{R:T(`${t.R}`),G:T(`${t.G}`),B:T(`${t.B}`),...f(t.A)?{}:{A:Math.min(T(`${t.A}`,!0),1)}}}convert(t,e,s){const r=O(t)?t:Et(t);return{R:Y(r.R),G:Y(r.G),B:Y(r.B),...s?{A:f(r.A)?"0xFF":Y(r.A*A)}:{}}}convertCSS(t,e,s){const r=this.convert(t,e.decimals,s),a=Ft(r,(t=>(t=>{let e=K(t,0).toString(16).toUpperCase();return 1===e.length&&(e=`0${e}`),e})(K(t)))),n=4===a.length?"#{1}{2}{3}{4}":"#{1}{2}{3}";return Rt(n,a)}getCSSOptions(t){const e=this._extract(t);return{hasAlpha:!f(e.a??e.aa)}}get model(){return a.HEX}},ft=new class extends Lt{_extract(t){return t.match(l.RGB).groups}supports(t){if(M(t))return l.RGB.test(t);const e=Object.entries(t).some((t=>!(u.test(`${t[1]}`)||!d.test(`${t[1]}`)&&!isNaN(+t[1])&&+t[1]<=A)));return O(t)&&!e}parse(t,e){if(M(t)){const s=this._extract(t),{r_legacy:r,g_legacy:a,b_legacy:n,a_legacy:i,r:c,g:l,b:h,a:o,from:u,relative_r:d,relative_g:g,relative_b:b,relative_a:C}=s;if(u){const t=e.parse(u),s=Et(t),r={r:s.R,g:s.G,b:s.B,alpha:s.A??1},a=new yt("r",d,r).result,n=new yt("g",g,r).result,i=new yt("b",b,r).result,c={R:Math.min(a,A),G:Math.min(n,A),B:Math.min(i,A)};if(C){const t=new yt("alpha",C,r).result;c.A=Math.min(t,1)}return c}{const t=r??c,e=a??l,s=n??h,u=i??o;return{R:Math.min(T(t),A),G:Math.min(T(e),A),B:Math.min(T(s),A),...f(u)?{}:{A:Q(u)}}}}return{R:T(`${t.R}`),G:T(`${t.G}`),B:T(`${t.B}`),...f(t.A)?{}:{A:Math.min(T(`${t.A}`,!0),1)}}}convert(t,e,s){const r=O(t)?t:Et(t);return this._roundRGBObject({R:r.R,G:r.G,B:r.B,...s?{A:r.A??1}:{}},e)}convertCSS(t,e,r){const{decimals:a,legacyCSS:n,spacesAfterCommas:i,rgbUnit:c}=e,l=this.convert(t,e.decimals,r),h=St(i),o=Ft(l,((t,r)=>c===s.PERCENT&&r<3?`${((t,e)=>K(t/A*100,e))(t,a)}%`:3===r?vt(t,e):K(t,a))),u=n?4===o.length?`rgba({1}${h}{2}${h}{3}${h}{4})`:`rgb({1}${h}{2}${h}{3})`:4===o.length?"rgb({1} {2} {3} / {4})":"rgb({1} {2} {3})";return Rt(u,o)}_roundRGBObject(t,e){return{R:K(t.R,e),G:K(t.G,e),B:K(t.B,e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t),{r_legacy:s,g_legacy:r,b_legacy:a,a_legacy:n,r:i,g:c,b:l,a:h}=e;return{hasPercentageValues:u.test(s??i)&&u.test(r??c)&&u.test(a??l),hasPercentageAlpha:u.test(n??h),hasAlpha:!f(n??h)}}get model(){return a.RGB}},wt=new class extends Lt{_extract(t){return t.match(l.HSL).groups}supports(t){return M(t)?l.HSL.test(t):G(t)}parse(t,e){if(M(t)){const s=this._extract(t),{h_legacy:r,s_legacy:a,l_legacy:n,a_legacy:i,h:c,s:l,l:h,a:o,from:u,relative_h:d,relative_s:g,relative_l:b,relative_a:C}=s;if(u){const t=e.parse(u),s=Et(t),r=ht(s.R,s.G,s.B,s.A),a={h:r.H,s:r.S,l:r.L,alpha:r.A},n=new yt("h",d,a).result,i=new yt("s",g,a).result,c=new yt("l",b,a).result,l={H:q(n),S:j(i),L:j(c)};if(C){const t=new yt("alpha",C,a).result;l.A=X(t,0,1)}return l}{const t=a??l,e=n??h,s=i??o;return{H:q(r??c),S:j(t),L:j(e),...f(s)?{}:{A:Q(s)}}}}return{H:q(t.H),S:j(`${t.S}`),L:j(`${t.L}`),...f(t.A)?{}:{A:X(+t.A,0,1)}}}convert(t,e,s){let r;if(G(t))r=t;else{const e=Et(t);r=ht(e.R,e.G,e.B,e.A)}return this._roundHSLObject({H:r.H,S:r.S,L:r.L,...s?{A:r.A??1}:{}},e)}convertCSS(t,e,s){const{legacyCSS:r,spacesAfterCommas:a}=e,n=St(a),i=this.convert(t,e.decimals,s),c=Mt(e),l=Ft(i,c),h=r?4===l.length?`hsla({1}${n}{2}%${n}{3}%${n}{4})`:`hsl({1}${n}{2}%${n}{3}%)`:4===l.length?"hsl({1} {2}% {3}% / {4})":"hsl({1} {2}% {3}%)";return Rt(h,l)}_roundHSLObject(t,e){return{H:K(q(t.H),e),S:K(t.S,e),L:K(t.L,e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t),{h_legacy:s,h:r,a_legacy:a,a:n}=e;return{angleUnit:tt(s??r),hasPercentageAlpha:u.test(a??n),hasAlpha:!f(a??n)}}get model(){return a.HSL}},Ot=new class extends Lt{_extract(t){return t.match(l.HWB).groups}supports(t){return M(t)?l.HWB.test(t):I(t)}parse(t,e){if(M(t)){const s=this._extract(t),{h:r,w:a,b:n,a:i,from:c,relative_h:l,relative_w:h,relative_b:o,relative_a:u}=s;if(c){const t=e.parse(c),s=Et(t),r=At(s.R,s.G,s.B,s.A),a={h:r.H,w:r.W,b:r.B,alpha:r.A},n=new yt("h",l,a).result,i=new yt("w",h,a).result,d=new yt("b",o,a).result,g={H:X(n,0,p),W:X(i,0,m),B:X(d,0,m)};if(u){const t=new yt("alpha",u,a).result;g.A=X(t,0,1)}return g}return{H:q(r),W:j(a),B:j(n),...f(i)?{}:{A:Q(i)}}}return{H:q(t.H),W:j(t.W),B:j(t.B),...f(t.A)?{}:{A:Q(t.A)}}}convert(t,e,s){let r;if(I(t))r=t;else{const e=Et(t);r=At(e.R,e.G,e.B,e.A)}return this._roundHWBObject({H:r.H,W:r.W,B:r.B,...s?{A:r.A??1}:{}},e)}convertCSS(t,e,s){const r=this.convert(t,e.decimals,s),a=Mt(e),n=Ft(r,a),i=4===n.length?"hwb({1} {2}% {3}% / {4})":"hwb({1} {2}% {3}%)";return Rt(i,n)}_roundHWBObject(t,e){return{H:K(q(t.H),e),W:K(t.W,e),B:K(t.B,e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t);return{angleUnit:tt(e.h),hasPercentageAlpha:u.test(e.a),hasAlpha:!f(e.a)}}get model(){return a.HWB}},Gt=new class extends Lt{_extract(t){return t.match(l.CIELab).groups}supports(t){return M(t)?l.CIELab.test(t):D(t)}parse(t,e){if(M(t)){const s=this._extract(t),{L:r,a:a,b:n,A:i,from:c,relative_L:l,relative_a:h,relative_b:o,relative_A:u}=s;if(c){const t=e.parse(c),s=Et(t),r=ot(s.R,s.G,s.B),a={l:r.L,a:r.a,b:r.b,alpha:s.A??1},n=new yt("l",l,a).result,i=new yt("a",h,a).result,d=new yt("b",o,a).result,g={L:X(n,0,m),a:X(i,-125,B),b:X(d,-125,B)};if(u){const t=new yt("alpha",u,a).result;g.A=X(t,0,1)}return g}return{L:j(r),a:W(a),b:W(n),...f(i)?{}:{A:Q(i)}}}return{L:j(t.L),a:W(`${t.a}`),b:W(`${t.b}`),...f(t.A)?{}:{A:Q(t.A)}}}convert(t,e,s){let r;if(D(t))r=t;else{const e=Et(t);r=ot(e.R,e.G,e.B)}return this._roundCIELabObject({L:r.L,a:r.a,b:r.b,...s?{A:+(t.A??1)}:{}},e)}convertCSS(t,e,r){const{decimals:a,labUnit:n}=e,i=this.convert(t,e.decimals,r),c=Ft(i,((t,r)=>{if(0===r){const e=K(j(t),a);return n===s.PERCENT?`${e}%`:`${e}`}return r<3?n===s.PERCENT?`${((t,e)=>K(t/B*100,e))(t,a)}%`:K(t,a):vt(t,e,!0)})),l=4===c.length?"lab({1} {2} {3} / {4})":"lab({1} {2} {3})";return Rt(l,c)}_roundCIELabObject(t,e){return{L:K(t.L,e),a:K(t.a,e),b:K(t.b,e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t),{L:s,a:r,b:a,A:n}=e;return{hasPercentageValues:u.test(s)&&u.test(r)&&u.test(a),hasPercentageAlpha:u.test(n),hasAlpha:!f(n)}}get model(){return a.CIELab}},It=new class extends Lt{_extract(t){return t.match(l.LCH).groups}supports(t){return M(t)?l.LCH.test(t):k(t)}parse(t,e){if(M(t)){const s=this._extract(t),{l:r,c:a,h:n,a:i,from:c,relative_l:l,relative_c:h,relative_h:o,relative_a:u}=s;if(c){const t=e.parse(c),s=Et(t),r=bt(s.R,s.G,s.B),a={l:r.L,c:r.C,h:r.H,alpha:s.A??1},n=new yt("l",l,a).result,i=new yt("c",h,a).result,d=new yt("h",o,a).result,g={L:X(n,0,m),C:X(i,-150,H),H:q(d)};if(u){const t=new yt("alpha",u,a).result;g.A=X(t,0,1)}return g}return{L:j(r),C:U(a),H:q(n),...f(i)?{}:{A:Q(i)}}}return{L:j(t.L),C:U(`${t.C}`),H:q(t.H),...f(t.A)?{}:{A:Q(t.A)}}}convert(t,e,s){let r;if(k(t))r=t;else{const e=Et(t);r=bt(e.R,e.G,e.B)}return this._roundLCHObject({L:r.L,C:r.C,H:r.H,...s?{A:+(t.A??1)}:{}},e)}convertCSS(t,r,a){const{decimals:n,lchUnit:i,anglesUnit:c}=r,l=this.convert(t,r.decimals,a),h=Ft(l,((t,a)=>{if(0===a){const e=K(j(t),n);return i===s.PERCENT?`${e}%`:`${e}`}if(1===a)return i===s.PERCENT?`${((t,e)=>K(t/H*100,e))(t,n)}%`:K(t,n);if(2===a){if(c!==e.NONE){return`${K(J(t,c),n)}${c}`}return K(t,n)}return vt(t,r,!0)})),o=4===h.length?"lch({1} {2} {3} / {4})":"lch({1} {2} {3})";return Rt(o,h)}_roundLCHObject(t,e){return{L:K(t.L,e),C:K(t.C,e),H:K(q(t.H),e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t);return{angleUnit:tt(e.h),hasPercentageValues:u.test(e.l)&&u.test(e.c),hasPercentageAlpha:u.test(e.a),hasAlpha:!f(e.a)}}get model(){return a.LCH}},Dt=new class extends Lt{_extract(t){return t.match(l.CMYK).groups}_shouldMultiplyBy100(...t){return!t.some((t=>+t>1))}supports(t){return M(t)?l.CMYK.test(t):x(t)}parse(t){if(M(t)){const e=this._extract(t),s=e.c_legacy??e.c,r=e.m_legacy??e.m,a=e.y_legacy??e.y,n=e.k_legacy??e.k,i=e.a_legacy??e.a,c=this._shouldMultiplyBy100(s,r,a,n);return{C:P(s,c),M:P(r,c),Y:P(a,c),K:P(n,c),...f(i)?{}:{A:Q(i)}}}const e=this._shouldMultiplyBy100(t.C,t.M,t.Y,t.K);return{C:P(`${t.C}`,e),M:P(`${t.M}`,e),Y:P(`${t.Y}`,e),K:P(`${t.K}`,e),...f(t.A)?{}:{A:Q(t.A)}}}convert(t,e,s){let r;if(x(t))r=t;else{const e=Et(t);r=Bt(e.R,e.G,e.B)}return this._roundCMYKObject({C:r.C,M:r.M,Y:r.Y,K:r.K,...s?{A:+(t.A??1)}:{}},e)}convertCSS(t,e,r){const{decimals:a,legacyCSS:n,spacesAfterCommas:i,cmykUnit:c,cmykFunction:l}=e,h=St(i),o=this.convert(t,e.decimals,r),u=Ft(o,((t,r)=>c===s.PERCENT&&r<4?`${K(t,a)}%`:4===r?vt(t,e):K(t/100,a))),d=n?5===u.length?`${l}({1}${h}{2}${h}{3}${h}{4}${h}{5})`:`${l}({1}${h}{2}${h}{3}${h}{4})`:5===u.length?`${l}({1} {2} {3} {4} / {5})`:`${l}({1} {2} {3} {4})`;return Rt(d,u)}_roundCMYKObject(t,e){return{C:K(t.C,e),M:K(t.M,e),Y:K(t.Y,e),K:K(t.K,e),...f(t.A)?{}:{A:K(t.A,e)}}}getCSSOptions(t){const e=this._extract(t),{c_legacy:s,m_legacy:r,y_legacy:a,k_legacy:n,a_legacy:i,c:c,m:l,y:h,k:o,a:d}=e;return{hasPercentageValues:u.test(s??c)&&u.test(r??l)&&u.test(a??h)&&u.test(n??o),hasPercentageAlpha:u.test(i??d),hasAlpha:!f(i??d)}}get model(){return a.CMYK}},kt=new class{constructor(t){this._parsers=t}getParser(t){const e=Object.values(this._parsers).find((e=>e.supports(t)));if(e)return e;throw new Error(R.NOT_ACCEPTED_INPUT)}parse(t){return this.getParser(t).parse(t,this)}convert(t,e,s=F.decimals,r=!1){const a=this.parse(t);return this._parsers[e].convert(a,s,r)}convertCSS(t,e,s={},r=!1){const a=this.parse(t);return this._parsers[e].convertCSS(a,s,r)}}({[a.HEX]:_t,[a.RGB]:ft,[a.HSL]:wt,[a.HWB]:Ot,[a.CIELab]:Gt,[a.LCH]:It,[a.CMYK]:Dt}),xt=(t,...a)=>{const n=[],i=[],c=[],l=[],h=[],o=[],u=[],d=Object.values(e),g=Object.values(s),A=Object.values(r),p={legacyCSS:0,spacesAfterCommas:0,cmykFunction:0};for(const t of a)if(M(t)){if(n.push(t),t.includes(",")){p.legacyCSS++;const e=t.match(b);1===new Set(e).size&&C.test(e[0].slice(1))&&p.spacesAfterCommas++}if(wt.supports(t)){const e=wt.getCSSOptions(t);i.push(e.angleUnit),u.push(e.hasPercentageAlpha);continue}if(Ot.supports(t)){const e=Ot.getCSSOptions(t);i.push(e.angleUnit),u.push(e.hasPercentageAlpha);continue}if(ft.supports(t)){const e=ft.getCSSOptions(t);c.push(e.hasPercentageValues),u.push(e.hasPercentageAlpha);continue}if(Gt.supports(t)){const e=Gt.getCSSOptions(t);l.push(e.hasPercentageValues),u.push(e.hasPercentageAlpha);continue}if(It.supports(t)){const e=It.getCSSOptions(t);i.push(e.angleUnit),h.push(e.hasPercentageValues),u.push(e.hasPercentageAlpha);continue}if(Dt.supports(t)){const e=Dt.getCSSOptions(t);o.push(e.hasPercentageValues),t.startsWith("cmyk")&&p.cmykFunction++,u.push(e.hasPercentageAlpha)}}return{decimals:y(t.decimals)?t.decimals:F.decimals,legacyCSS:_(t.legacyCSS)?t.legacyCSS:Boolean(n.length&&p.legacyCSS===n.length)||F.legacyCSS,spacesAfterCommas:_(t.spacesAfterCommas)?t.spacesAfterCommas:Boolean(n.length&&p.spacesAfterCommas===n.length)||F.spacesAfterCommas,anglesUnit:t.anglesUnit&&d.includes(t.anglesUnit)?t.anglesUnit:1===new Set(i).size?i[0]:F.anglesUnit,rgbUnit:t.rgbUnit&&g.includes(t.rgbUnit)?t.rgbUnit:1===new Set(c).size&&c[0]?s.PERCENT:F.rgbUnit,labUnit:t.labUnit&&g.includes(t.labUnit)?t.labUnit:1===new Set(l).size&&l[0]?s.PERCENT:F.labUnit,lchUnit:t.lchUnit&&g.includes(t.lchUnit)?t.lchUnit:1===new Set(h).size&&h[0]?s.PERCENT:F.lchUnit,cmykUnit:t.cmykUnit&&g.includes(t.cmykUnit)?t.cmykUnit:1!==new Set(o).size||o[0]?F.cmykUnit:s.NONE,alphaUnit:t.alphaUnit&&g.includes(t.alphaUnit)?t.alphaUnit:1===new Set(u).size&&u[0]?s.PERCENT:F.alphaUnit,cmykFunction:t.cmykFunction&&A.includes(t.cmykFunction)?t.cmykFunction:o.length&&o.length===p.cmykFunction?r.CMYK:F.cmykFunction}};function Nt(t,e,s,r,a,n=5,i={}){n<1&&(n=5);const c=kt.parse(t),l=kt.parse(e),h=((t,e,s)=>{const r=s-1,a=(e.R-t.R)/r,n=(e.G-t.G)/r,i=(e.B-t.B)/r,c=Q(t.A),l=(Q(e.A)-c)/r;return Array(s).fill(null).map(((s,h)=>0===h?t:h===r?e:{R:K(t.R+a*h),G:K(t.G+n*h),B:K(t.B+i*h),A:K(c+l*h)}))})(Et(c),Et(l),n);return h.map((n=>r?kt.convertCSS(n,s,xt(i,t,e),a):kt.convert(n,s,i.decimals,a)))}const jt=(t,e)=>[y(t)?t:void 0,y(t)?e:t];function $t(e,s,r,n,i=t.Mix.ADDITIVE,c={}){const l=e.map((t=>kt.convert(t,a.RGB,c.decimals,n))),h=i===t.Mix.SUBTRACTIVE?l.map((t=>{const e=((t,e,s)=>{const r=Math.min(t,e,s),a=Math.min(A-t,A-e,A-s),n=t-r,i=e-r,c=s-r,l=Math.min(n,i),h=n-l,o=(i+l)/2,u=(c+i-l)/2,d=Math.max(h,o,u)/Math.max(n,i,c),g=isNaN(d)||d===1/0||d<=0?1:d;return{R:h/g+a,Y:o/g+a,B:u/g+a}})(t.R,t.G,t.B);return f(t.A)||(e.A=t.A),e})):null;function o(e){const s=i===t.Mix.ADDITIVE?{R:0,G:0,B:0,A:0}:{R:0,Y:0,B:0,A:0};return e.reduce(((e,s)=>{const r=f(s.A)?1:s.A,a={R:Math.min(e.R+s.R*r,A),B:Math.min(e.B+s.B*r,A),A:1-(1-r)*(1-e.A)},n="G"in e?e.G:e.Y,c="G"in s?s.G:s.Y;return{...a,...i===t.Mix.ADDITIVE?{G:Math.min(n+c*r,A)}:{Y:Math.min(n+c*r,A)}}}),s)}let u;if(i===t.Mix.ADDITIVE)u=o(l);else{const t=o(h);u=((t,e,s)=>{const r=Math.min(t,e,s),a=Math.min(A-t,A-e,A-s),n=t-r,i=e-r,c=s-r,l=Math.min(i,c),h=n+i-l,o=i+l,u=2*(c-l),d=Math.max(h,o,u)/Math.max(n,i,c),g=isNaN(d)||d===1/0||d<=0?1:d;return{R:h/g+a,G:o/g+a,B:u/g+a}})(t.R,t.Y,t.B),u.A=t.A}return r?kt.convertCSS(u,s,xt(c,...e),n):kt.convert(u,s,c.decimals,n)}const Yt=(t,e)=>[M(t)?t:void 0,M(t)?e:t];function Tt(t,e,s=5,r={}){const n=M(e),i=kt.getParser(e),c=i.model,l=i.hasAlpha(e),h=kt.convert(e,a.HSL,void 0,l),o=t?h.L/(s+1):(100-h.L)/(s+1),u=Array.from(Array(s)).map(((e,s)=>({...h,L:h.L+o*(s+1)*(1-2*+t)})));return n?u.map((t=>kt.convertCSS(t,c,xt(r,e),l))):u.map((t=>kt.convert(t,c,r.decimals,l)))}const Wt=(t,e)=>[y(t)?t:void 0,y(t)?e:t],Ut=(e,s,r)=>s.reduce(((s,a)=>[...s,{...e,H:r===t.Mix.ADDITIVE?q(e.H+a):q(Ht(Ht(e.H,!1)+a,!0))}]),[{...e}]),Pt=new Map([[t.Harmony.ANALOGOUS,(t,e)=>Ut(t,[30,-30],e)],[t.Harmony.COMPLEMENTARY,(t,e)=>Ut(t,[180],e)],[t.Harmony.SPLIT_COMPLEMENTARY,(t,e)=>Ut(t,[150,-150],e)],[t.Harmony.TRIADIC,(t,e)=>Ut(t,[120,-120],e)],[t.Harmony.TETRADIC,(t,e)=>Ut(t,[60,-120,180],e)],[t.Harmony.SQUARE,(t,e)=>Ut(t,[90,-90,180],e)]]),Kt=(e,s,r)=>`${e}`in t.Harmony?[e,Z(s)?s:t.Mix.ADDITIVE,Z(s)?r:s]:Z(e)?[t.Harmony.COMPLEMENTARY,e,s]:[t.Harmony.COMPLEMENTARY,t.Mix.ADDITIVE,e];return t.ColorTranslator=class{constructor(t,e={}){this._options=xt(e,t);const s=kt.parse(t);switch(w(s)){case a.HSL:this.hsl=s,this.update("hsl");break;case a.HWB:this.hwb=s,this.updateRGBFromHWB(),this.update("hwb","rgb");break;case a.CIELab:this.lab=s,this.updateRGBFromLAB(),this.update("lab","rgb");break;case a.LCH:this.lch=s,this.updateRGBFromLCH(),this.update("lch","rgb");break;case a.CMYK:this.cmyk=s,this.updateRGBFromCMYK(),this.update("cmyk","rgb");break;default:this.rgb=s,this.update("rgb")}}update(...t){t.includes("rgb")||this.updateRGB(),t.includes("hsl")||this.updateHSL(),t.includes("hwb")||this.updateHWB(),t.includes("lab")||this.updateLAB(),t.includes("lch")||this.updateLCH(),t.includes("cmyk")||this.updateCMYK()}updateRGB(){this.rgb={...lt(this.hsl.H,this.hsl.S,this.hsl.L),A:this.hsl.A??1}}updateHSL(){this.hsl=ht(this.rgb.R,this.rgb.G,this.rgb.B,this.rgb.A)}updateHWB(){this.hwb=At(this.rgb.R,this.rgb.G,this.rgb.B,this.rgb.A)}updateLAB(){this.lab={...ot(this.rgb.R,this.rgb.G,this.rgb.B),A:this.rgb.A??1}}updateLCH(){this.lch={...bt(this.rgb.R,this.rgb.G,this.rgb.B),A:this.rgb.A??1}}updateCMYK(){this.cmyk={...Bt(this.rgb.R,this.rgb.G,this.rgb.B),A:this.rgb.A??1}}updateRGBFromHWB(){this.rgb={...pt(this.hwb.H,this.hwb.W,this.hwb.B),A:this.hwb?.A??1}}updateRGBFromLCH(){this.rgb={...Ct(this.lch.L,this.lch.C,this.lch.H),A:this.lch.A??1}}updateRGBFromCMYK(){this.rgb={...mt(this.cmyk.C,this.cmyk.M,this.cmyk.Y,this.cmyk.K),A:this.cmyk.A??1}}updateRGBFromLAB(){this.rgb={...ut(this.lab.L,this.lab.a,this.lab.b),A:this.lab.A??1}}updateLCHFromLAB(){this.lch={...dt(this.lab.L,this.lab.a,this.lab.b),A:this.lab.A}}updateLABromLCH(){this.lab={...gt(this.lch.L,this.lch.C,this.lch.H),A:this.lch.A}}setOptions(t={}){return this._options={...this._options,...t},this}setR(t){this.rgb.R=X(t,0,A),this.update("rgb")}setG(t){return this.rgb.G=X(t,0,A),this.update("rgb"),this}setB(t){return this.rgb.B=X(t,0,A),this.update("rgb"),this}setH(t){return this.hsl.H=q(t),this.update("hsl"),this}setS(t){return this.hsl.S=X(t,0,m),this.update("hsl"),this}setL(t){return this.hsl.L=X(t,0,m),this.update("hsl"),this}setWhiteness(t){return this.hwb.W=X(t,0,m),this.updateRGBFromHWB(),this.update("rgb","hwb"),this}setBlackness(t){return this.hwb.B=X(t,0,m),this.updateRGBFromHWB(),this.update("rgb","hwb"),this}setCIEL(t){return this.lab.L=X(t,0,m),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setCIEa(t){return this.lab.a=X(t,-125,B),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setCIEb(t){return this.lab.b=X(t,-125,B),this.updateRGBFromLAB(),this.updateLCHFromLAB(),this.update("rgb","lab","lch"),this}setLCHL(t){return this.lch.L=X(t,0,m),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setLCHC(t){return this.lch.C=X(t,0,H),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setLCHH(t){return this.lch.H=q(t),this.updateRGBFromLCH(),this.updateLABromLCH(),this.update("rgb","lab","lch"),this}setA(t){const e=X(t,0,1);return this.rgb.A=e,this.hsl.A=e,this.hwb.A=e,this.lab.A=e,this.lch.A=e,this.cmyk.A=e,this}setC(t){return this.cmyk.C=X(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setM(t){return this.cmyk.M=X(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setY(t){return this.cmyk.Y=X(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}setK(t){return this.cmyk.K=X(t,0,100),this.updateRGBFromCMYK(),this.update("cmyk"),this}get options(){return this._options}get R(){return K(this.rgb.R,this.options.decimals)}get G(){return K(this.rgb.G,this.options.decimals)}get B(){return K(this.rgb.B,this.options.decimals)}get H(){return K(this.hsl.H,this.options.decimals)}get S(){return K(this.hsl.S,this.options.decimals)}get L(){return K(this.hsl.L,this.options.decimals)}get Whiteness(){return K(this.hwb.W,this.options.decimals)}get Blackness(){return K(this.hwb.B,this.options.decimals)}get CIEL(){return K(this.lab.L,this.options.decimals)}get CIEa(){return K(this.lab.a,this.options.decimals)}get CIEb(){return K(this.lab.b,this.options.decimals)}get LCHL(){return K(this.lch.L,this.options.decimals)}get LCHC(){return K(this.lch.C,this.options.decimals)}get LCHH(){return K(this.lch.H,this.options.decimals)}get A(){return K(this.hsl.A,this.options.decimals)}get C(){return K(this.cmyk.C,this.options.decimals)}get M(){return K(this.cmyk.M,this.options.decimals)}get Y(){return K(this.cmyk.Y,this.options.decimals)}get K(){return K(this.cmyk.K,this.options.decimals)}get HEXObject(){return kt.convert(this.rgb,a.HEX)}get HEXAObject(){return kt.convert(this.rgb,a.HEX,0,!0)}get RGBObject(){return kt.convert(this.rgb,a.RGB,this.options.decimals)}get RGBAObject(){return kt.convert(this.rgb,a.RGB,this.options.decimals,!0)}get HSLObject(){return kt.convert(this.hsl,a.HSL,this.options.decimals)}get HSLAObject(){return kt.convert(this.hsl,a.HSL,this.options.decimals,!0)}get HWBObject(){return kt.convert(this.hwb,a.HWB,this.options.decimals)}get HWBAObject(){return kt.convert(this.hwb,a.HWB,this.options.decimals,!0)}get CIELabObject(){return kt.convert(this.lab,a.CIELab,this.options.decimals)}get CIELabAObject(){return kt.convert(this.lab,a.CIELab,this.options.decimals,!0)}get LCHObject(){return kt.convert(this.lch,a.LCH,this.options.decimals)}get LCHAObject(){return kt.convert(this.lch,a.LCH,this.options.decimals,!0)}get CMYKObject(){return kt.convert(this.cmyk,a.CMYK,this.options.decimals)}get CMYKAObject(){return kt.convert(this.cmyk,a.CMYK,this.options.decimals,!0)}get HEX(){return kt.convertCSS(this.rgb,a.HEX)}get HEXA(){return kt.convertCSS(this.rgb,a.HEX,{},!0)}get RGB(){return kt.convertCSS(this.rgb,a.RGB,this.options)}get RGBA(){return kt.convertCSS(this.rgb,a.RGB,this.options,!0)}get HSL(){return kt.convertCSS(this.hsl,a.HSL,this.options)}get HSLA(){return kt.convertCSS(this.hsl,a.HSL,this.options,!0)}get HWB(){return kt.convertCSS(this.hwb,a.HWB,this.options)}get HWBA(){return kt.convertCSS(this.hwb,a.HWB,this.options,!0)}get CIELab(){return kt.convertCSS(this.lab,a.CIELab,this.options)}get CIELabA(){return kt.convertCSS(this.lab,a.CIELab,this.options,!0)}get LCH(){return kt.convertCSS(this.lch,a.LCH,this.options)}get LCHA(){return kt.convertCSS(this.lch,a.LCH,this.options,!0)}get CMYK(){return kt.convertCSS(this.cmyk,a.CMYK,this.options)}get CMYKA(){return kt.convertCSS(this.cmyk,a.CMYK,this.options,!0)}static toHEXObject(t){return kt.convert(t,a.HEX)}static toHEX(t){return kt.convertCSS(t,a.HEX)}static toHEXAObject(t){return kt.convert(t,a.HEX,void 0,!0)}static toHEXA(t){return kt.convertCSS(t,a.HEX,void 0,!0)}static toRGBObject(t,e={}){return kt.convert(t,a.RGB,e.decimals)}static toRGB(t,e={}){return kt.convertCSS(t,a.RGB,xt(e,t))}static toRGBAObject(t,e={}){return kt.convert(t,a.RGB,e.decimals,!0)}static toRGBA(t,e={}){return kt.convertCSS(t,a.RGB,xt(e,t),!0)}static toHSLObject(t,e={}){return kt.convert(t,a.HSL,e.decimals)}static toHSL(t,e={}){return kt.convertCSS(t,a.HSL,xt(e,t))}static toHSLAObject(t,e={}){return kt.convert(t,a.HSL,e.decimals,!0)}static toHSLA(t,e={}){return kt.convertCSS(t,a.HSL,xt(e,t),!0)}static toHWBObject(t,e={}){return kt.convert(t,a.HWB,e.decimals)}static toHWB(t,e={}){return kt.convertCSS(t,a.HWB,xt(e,t))}static toHWBAObject(t,e={}){return kt.convert(t,a.HWB,e.decimals,!0)}static toHWBA(t,e={}){return kt.convertCSS(t,a.HWB,xt(e,t),!0)}static toCIELabObject(t,e={}){return kt.convert(t,a.CIELab,e.decimals)}static toCIELab(t,e={}){return kt.convertCSS(t,a.CIELab,xt(e,t))}static toCIELabAObject(t,e={}){return kt.convert(t,a.CIELab,e.decimals,!0)}static toCIELabA(t,e={}){return kt.convertCSS(t,a.CIELab,xt(e,t),!0)}static toLCHObject(t,e={}){return kt.convert(t,a.LCH,e.decimals)}static toLCH(t,e={}){return kt.convertCSS(t,a.LCH,xt(e,t))}static toLCHAObject(t,e={}){return kt.convert(t,a.LCH,e.decimals,!0)}static toLCHA(t,e={}){return kt.convertCSS(t,a.LCH,xt(e,t),!0)}static toCMYKObject(t,e={}){return kt.convert(t,a.CMYK,e.decimals)}static toCMYK(t,e={}){return kt.convertCSS(t,a.CMYK,xt(e,t))}static toCMYKAObject(t,e={}){return kt.convert(t,a.CMYK,e.decimals,!0)}static toCMYKA(t,e={}){return kt.convertCSS(t,a.CMYK,xt(e,t),!0)}static getBlendHEXObject(t,e,s){return Nt(t,e,a.HEX,!1,!1,s)}static getBlendHEX(t,e,s){return Nt(t,e,a.HEX,!0,!1,s)}static getBlendHEXAObject(t,e,s){return Nt(t,e,a.HEX,!1,!0,s)}static getBlendHEXA(t,e,s){return Nt(t,e,a.HEX,!0,!0,s)}static getBlendRGBObject(t,e,s,r){return Nt(t,e,a.RGB,!1,!1,...jt(s,r))}static getBlendRGB(t,e,s,r){return Nt(t,e,a.RGB,!0,!1,...jt(s,r))}static getBlendRGBAObject(t,e,s,r){return Nt(t,e,a.RGB,!1,!0,...jt(s,r))}static getBlendRGBA(t,e,s,r){return Nt(t,e,a.RGB,!0,!0,...jt(s,r))}static getBlendHSLObject(t,e,s,r){return Nt(t,e,a.HSL,!1,!1,...jt(s,r))}static getBlendHSL(t,e,s,r){return Nt(t,e,a.HSL,!0,!1,...jt(s,r))}static getBlendHSLAObject(t,e,s,r){return Nt(t,e,a.HSL,!1,!0,...jt(s,r))}static getBlendHSLA(t,e,s,r){return Nt(t,e,a.HSL,!0,!0,...jt(s,r))}static getBlendHWBObject(t,e,s,r){return Nt(t,e,a.HWB,!1,!1,...jt(s,r))}static getBlendHWB(t,e,s,r){return Nt(t,e,a.HWB,!0,!1,...jt(s,r))}static getBlendHWBAObject(t,e,s,r){return Nt(t,e,a.HWB,!1,!0,...jt(s,r))}static getBlendHWBA(t,e,s,r){return Nt(t,e,a.HWB,!0,!0,...jt(s,r))}static getBlendCIELabObject(t,e,s,r){return Nt(t,e,a.CIELab,!1,!1,...jt(s,r))}static getBlendCIELab(t,e,s,r){return Nt(t,e,a.CIELab,!0,!1,...jt(s,r))}static getBlendCIELabAObject(t,e,s,r){return Nt(t,e,a.CIELab,!1,!0,...jt(s,r))}static getBlendCIELabA(t,e,s,r){return Nt(t,e,a.CIELab,!0,!0,...jt(s,r))}static getBlendLCHObject(t,e,s,r){return Nt(t,e,a.LCH,!1,!1,...jt(s,r))}static getBlendLCH(t,e,s,r){return Nt(t,e,a.LCH,!0,!1,...jt(s,r))}static getBlendLCHAObject(t,e,s,r){return Nt(t,e,a.LCH,!1,!0,...jt(s,r))}static getBlendLCHA(t,e,s,r){return Nt(t,e,a.LCH,!0,!0,...jt(s,r))}static getMixHEXObject(t,e){return $t(t,a.HEX,!1,!1,e)}static getMixHEX(e,s=t.Mix.ADDITIVE){return $t(e,a.HEX,!0,!1,s)}static getMixHEXAObject(e,s=t.Mix.ADDITIVE){return $t(e,a.HEX,!1,!0,s)}static getMixHEXA(e,s=t.Mix.ADDITIVE){return $t(e,a.HEX,!0,!0,s)}static getMixRGBObject(t,e,s){return $t(t,a.RGB,!1,!1,...Yt(e,s))}static getMixRGB(t,e,s){return $t(t,a.RGB,!0,!1,...Yt(e,s))}static getMixRGBAObject(t,e,s){return $t(t,a.RGB,!1,!0,...Yt(e,s))}static getMixRGBA(t,e,s){return $t(t,a.RGB,!0,!0,...Yt(e,s))}static getMixHSLObject(t,e,s){return $t(t,a.HSL,!1,!1,...Yt(e,s))}static getMixHSL(t,e,s){return $t(t,a.HSL,!0,!1,...Yt(e,s))}static getMixHSLAObject(t,e,s){return $t(t,a.HSL,!1,!0,...Yt(e,s))}static getMixHSLA(t,e,s){return $t(t,a.HSL,!0,!0,...Yt(e,s))}static getMixHWBObject(t,e,s){return $t(t,a.HWB,!1,!1,...Yt(e,s))}static getMixHWB(t,e,s){return $t(t,a.HWB,!0,!1,...Yt(e,s))}static getMixHWBAObject(t,e,s){return $t(t,a.HWB,!1,!0,...Yt(e,s))}static getMixHWBA(t,e,s){return $t(t,a.HWB,!0,!0,...Yt(e,s))}static getMixCIELabObject(t,e,s){return $t(t,a.CIELab,!1,!1,...Yt(e,s))}static getMixCIELab(t,e,s){return $t(t,a.CIELab,!0,!1,...Yt(e,s))}static getMixCIELabAObject(t,e,s){return $t(t,a.CIELab,!1,!0,...Yt(e,s))}static getMixCIELabA(t,e,s){return $t(t,a.CIELab,!0,!0,...Yt(e,s))}static getMixLCHObject(t,e,s){return $t(t,a.LCH,!1,!1,...Yt(e,s))}static getMixLCH(t,e,s){return $t(t,a.LCH,!0,!1,...Yt(e,s))}static getMixLCHAObject(t,e,s){return $t(t,a.LCH,!1,!0,...Yt(e,s))}static getMixLCHA(t,e,s){return $t(t,a.LCH,!0,!0,...Yt(e,s))}static getShades(t,e,s){return Tt(!0,t,...Wt(e,s))}static getTints(t,e,s){return Tt(!1,t,...Wt(e,s))}static getHarmony(t,e,s,r){return((t,e,s,r={})=>{const n=Pt.get(e),i=M(t),c=kt.getParser(t),l=c.model,h=c.hasAlpha(t),o=n(kt.convert(t,a.HSL),s);return i?o.map((e=>kt.convertCSS(e,l,xt(r,t),h))):o.map((t=>kt.convert(t,l,r.decimals,h)))})(t,...Kt(e,s,r))}},t}({}); diff --git a/docs/scripts/bundle.js b/docs/scripts/bundle.js index 3ee5aba..f996133 100644 --- a/docs/scripts/bundle.js +++ b/docs/scripts/bundle.js @@ -1 +1 @@ -(()=>{var __webpack_modules__={966(module,exports){eval('{var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!function(){var r=null;\n(function(){function X(e){function j(){try{J.doScroll("left")}catch(e){P(j,50);return}w("poll")}function w(j){if(!(j.type=="readystatechange"&&x.readyState!="complete")&&((j.type=="load"?n:x)[z](i+j.type,w,!1),!m&&(m=!0)))e.call(n,j.type||j)}var Y=x.addEventListener,m=!1,C=!0,t=Y?"addEventListener":"attachEvent",z=Y?"removeEventListener":"detachEvent",i=Y?"":"on";if(x.readyState=="complete")e.call(n,"lazy");else{if(x.createEventObject&&J.doScroll){try{C=!n.frameElement}catch(A){}C&&j()}x[t](i+"DOMContentLoaded",\nw,!1);x[t](i+"readystatechange",w,!1);n[t](i+"load",w,!1)}}function Q(){S&&X(function(){var e=K.length;$(e?function(){for(var j=0;j=0;){var M=A[m],T=M.src.match(/^[^#?]*\\/run_prettify\\.js(\\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||"";M.parentNode.removeChild(M);break}}var S=!0,D=\n[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j=="autorun"?S=!/^[0fn]/i.test(w):j=="lang"?D.push(w):j=="skin"?N.push(w):j=="callback"&&K.push(w)});m=0;for(z=D.length;m122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f,a){return f[0]-\na[0]||a[1]-f[1]});b=[];g=[];for(a=0;ak[0]&&(k[1]+1>k[0]&&c.push("-"),c.push(h(k[1])));c.push("]");return c.join("")}function e(f){for(var a=f.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),c=a.length,d=[],g=0,k=0;g=2&&f==="["?a[g]=b(o):f!=="\\\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I=5&&"lang-"===y.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,y="src";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h,j);n(l+k+o,g,A(y,\ng),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c=0;)b[q.charAt(f)]=m;m=m[1];q=""+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\\S\\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\\\]|\\\\[\\S\\s]|\'\'?(?=[^\']))*(?:\'\'\'|$)|"""(?:[^"\\\\]|\\\\[\\S\\s]|""?(?=[^"]))*(?:"""|$)|\'(?:[^\'\\\\]|\\\\[\\S\\s])*(?:\'|$)|"(?:[^"\\\\]|\\\\[\\S\\s])*(?:"|$))/,\nr,"\'\\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\'\\\\]|\\\\[\\S\\s])*(?:\'|$)|"(?:[^"\\\\]|\\\\[\\S\\s])*(?:"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,r,"\'\\"`"]):d.push(["str",/^(?:\'(?:[^\\n\\r\'\\\\]|\\\\.)*(?:\'|$)|"(?:[^\\n\\r"\\\\]|\\\\.)*(?:"|$))/,r,"\\"\'"]);a.verbatimStrings&&h.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,\nr,"#"]),h.push(["str",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,r])):d.push(["com",/^#[^\\n\\r]*/,r,"#"]));a.cStyleComments&&(h.push(["com",/^\\/\\/[^\\n\\r]*/,r]),h.push(["com",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?"":"\\n\\r")?".":"[\\\\S\\\\s]";h.push(["lang-regex",RegExp("^(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*("+\n("/(?=[^/*"+b+"])(?:[^/\\\\x5B\\\\x5C"+b+"]|\\\\x5C"+e+"|\\\\x5B(?:[^\\\\x5C\\\\x5D"+b+"]|\\\\x5C"+e+")*(?:\\\\x5D|$))+/")+")")])}(b=a.types)&&h.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&h.push(["kwd",RegExp("^(?:"+b.replace(/[\\s,]+/g,"|")+")\\\\b"),r]);d.push(["pln",/^\\s+/,r," \\r\\n\\t\\u00a0"]);b="^.[^\\\\s\\\\w.$@\'\\"`/\\\\\\\\]*";a.regexLiterals&&(b+="(?!s*/)");h.push(["lit",/^@[$_a-z][\\w$@]*/i,r],["typ",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,r],["pln",/^[$_a-z][\\w$@]*/i,r],["lit",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,\nr,"0123456789"],["pln",/^\\\\[\\S\\s]?/,r],["pun",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if("br"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}}\nfunction e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\\s)nocode(?:\\s|$)/,m=/\\r\\n?|\\n/,l=a.ownerDocument,i=l.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn("cannot override language handler %s",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\\s*=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=["break,continue,do,else,for,if,return,while"],O=[[G,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],\n"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],J=[O,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],K=[O,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],\nL=[K,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],O=[O,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],M=[G,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],\nN=[G,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],R=[G,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],G=[G,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/,\nS=/\\S/,T=t({keywords:[J,L,O,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,["default-code"]);i(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],["lang-",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],["lang-",/^<%([\\S\\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",\n/^]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],["lang-js",/^]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],["lang-css",/^]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],["lang-in.tag",/^(<\\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);i(C([["pln",/^\\s+/,r," \\t\\r\\n"],["atv",/^(?:"[^"]*"?|\'[^\']*\'?)/,r,"\\"\'"]],[["tag",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],["atn",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],["lang-uq.val",/^=\\s*([^\\s"\'>]*(?:[^\\s"\'/>]|\\/(?=\\s)))/],["pun",/^[/<->]+/],\n["lang-js",/^on\\w+\\s*=\\s*"([^"]+)"/i],["lang-js",/^on\\w+\\s*=\\s*\'([^\']+)\'/i],["lang-js",/^on\\w+\\s*=\\s*([^\\s"\'>]+)/i],["lang-css",/^style\\s*=\\s*"([^"]+)"/i],["lang-css",/^style\\s*=\\s*\'([^\']+)\'/i],["lang-css",/^style\\s*=\\s*([^\\s"\'>]+)/i]]),["in.tag"]);i(C([],[["atv",/^[\\S\\s]+/]]),["uq.val"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);i(t({keywords:"null,true,false"}),["json"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),\n["cs"]);i(t({keywords:K,cStyleComments:!0}),["java"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);i(t({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);i(t({keywords:N,\nhashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);i(t({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);\ni(C([],[["str",/^[\\S\\s]+/]]),["regex"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,e){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML},\nprettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p -1\n }\n}\n\nfunction normalizeName(name) {\n if (typeof name !== 'string') {\n name = String(name)\n }\n if (/[^a-z0-9\\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {\n throw new TypeError('Invalid character in header field name: \"' + name + '\"')\n }\n return name.toLowerCase()\n}\n\nfunction normalizeValue(value) {\n if (typeof value !== 'string') {\n value = String(value)\n }\n return value\n}\n\n// Build a destructive iterator for the value list\nfunction iteratorFor(items) {\n var iterator = {\n next: function() {\n var value = items.shift()\n return {done: value === undefined, value: value}\n }\n }\n\n if (support.iterable) {\n iterator[Symbol.iterator] = function() {\n return iterator\n }\n }\n\n return iterator\n}\n\nfunction Headers(headers) {\n this.map = {}\n\n if (headers instanceof Headers) {\n headers.forEach(function(value, name) {\n this.append(name, value)\n }, this)\n } else if (Array.isArray(headers)) {\n headers.forEach(function(header) {\n if (header.length != 2) {\n throw new TypeError('Headers constructor: expected name/value pair to be length 2, found' + header.length)\n }\n this.append(header[0], header[1])\n }, this)\n } else if (headers) {\n Object.getOwnPropertyNames(headers).forEach(function(name) {\n this.append(name, headers[name])\n }, this)\n }\n}\n\nHeaders.prototype.append = function(name, value) {\n name = normalizeName(name)\n value = normalizeValue(value)\n var oldValue = this.map[name]\n this.map[name] = oldValue ? oldValue + ', ' + value : value\n}\n\nHeaders.prototype['delete'] = function(name) {\n delete this.map[normalizeName(name)]\n}\n\nHeaders.prototype.get = function(name) {\n name = normalizeName(name)\n return this.has(name) ? this.map[name] : null\n}\n\nHeaders.prototype.has = function(name) {\n return this.map.hasOwnProperty(normalizeName(name))\n}\n\nHeaders.prototype.set = function(name, value) {\n this.map[normalizeName(name)] = normalizeValue(value)\n}\n\nHeaders.prototype.forEach = function(callback, thisArg) {\n for (var name in this.map) {\n if (this.map.hasOwnProperty(name)) {\n callback.call(thisArg, this.map[name], name, this)\n }\n }\n}\n\nHeaders.prototype.keys = function() {\n var items = []\n this.forEach(function(value, name) {\n items.push(name)\n })\n return iteratorFor(items)\n}\n\nHeaders.prototype.values = function() {\n var items = []\n this.forEach(function(value) {\n items.push(value)\n })\n return iteratorFor(items)\n}\n\nHeaders.prototype.entries = function() {\n var items = []\n this.forEach(function(value, name) {\n items.push([name, value])\n })\n return iteratorFor(items)\n}\n\nif (support.iterable) {\n Headers.prototype[Symbol.iterator] = Headers.prototype.entries\n}\n\nfunction consumed(body) {\n if (body._noBody) return\n if (body.bodyUsed) {\n return Promise.reject(new TypeError('Already read'))\n }\n body.bodyUsed = true\n}\n\nfunction fileReaderReady(reader) {\n return new Promise(function(resolve, reject) {\n reader.onload = function() {\n resolve(reader.result)\n }\n reader.onerror = function() {\n reject(reader.error)\n }\n })\n}\n\nfunction readBlobAsArrayBuffer(blob) {\n var reader = new FileReader()\n var promise = fileReaderReady(reader)\n reader.readAsArrayBuffer(blob)\n return promise\n}\n\nfunction readBlobAsText(blob) {\n var reader = new FileReader()\n var promise = fileReaderReady(reader)\n var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type)\n var encoding = match ? match[1] : 'utf-8'\n reader.readAsText(blob, encoding)\n return promise\n}\n\nfunction readArrayBufferAsText(buf) {\n var view = new Uint8Array(buf)\n var chars = new Array(view.length)\n\n for (var i = 0; i < view.length; i++) {\n chars[i] = String.fromCharCode(view[i])\n }\n return chars.join('')\n}\n\nfunction bufferClone(buf) {\n if (buf.slice) {\n return buf.slice(0)\n } else {\n var view = new Uint8Array(buf.byteLength)\n view.set(new Uint8Array(buf))\n return view.buffer\n }\n}\n\nfunction Body() {\n this.bodyUsed = false\n\n this._initBody = function(body) {\n /*\n fetch-mock wraps the Response object in an ES6 Proxy to\n provide useful test harness features such as flush. However, on\n ES5 browsers without fetch or Proxy support pollyfills must be used;\n the proxy-pollyfill is unable to proxy an attribute unless it exists\n on the object before the Proxy is created. This change ensures\n Response.bodyUsed exists on the instance, while maintaining the\n semantic of setting Request.bodyUsed in the constructor before\n _initBody is called.\n */\n // eslint-disable-next-line no-self-assign\n this.bodyUsed = this.bodyUsed\n this._bodyInit = body\n if (!body) {\n this._noBody = true;\n this._bodyText = ''\n } else if (typeof body === 'string') {\n this._bodyText = body\n } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {\n this._bodyBlob = body\n } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {\n this._bodyFormData = body\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n this._bodyText = body.toString()\n } else if (support.arrayBuffer && support.blob && isDataView(body)) {\n this._bodyArrayBuffer = bufferClone(body.buffer)\n // IE 10-11 can't handle a DataView body.\n this._bodyInit = new Blob([this._bodyArrayBuffer])\n } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {\n this._bodyArrayBuffer = bufferClone(body)\n } else {\n this._bodyText = body = Object.prototype.toString.call(body)\n }\n\n if (!this.headers.get('content-type')) {\n if (typeof body === 'string') {\n this.headers.set('content-type', 'text/plain;charset=UTF-8')\n } else if (this._bodyBlob && this._bodyBlob.type) {\n this.headers.set('content-type', this._bodyBlob.type)\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')\n }\n }\n }\n\n if (support.blob) {\n this.blob = function() {\n var rejected = consumed(this)\n if (rejected) {\n return rejected\n }\n\n if (this._bodyBlob) {\n return Promise.resolve(this._bodyBlob)\n } else if (this._bodyArrayBuffer) {\n return Promise.resolve(new Blob([this._bodyArrayBuffer]))\n } else if (this._bodyFormData) {\n throw new Error('could not read FormData body as blob')\n } else {\n return Promise.resolve(new Blob([this._bodyText]))\n }\n }\n }\n\n this.arrayBuffer = function() {\n if (this._bodyArrayBuffer) {\n var isConsumed = consumed(this)\n if (isConsumed) {\n return isConsumed\n } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {\n return Promise.resolve(\n this._bodyArrayBuffer.buffer.slice(\n this._bodyArrayBuffer.byteOffset,\n this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength\n )\n )\n } else {\n return Promise.resolve(this._bodyArrayBuffer)\n }\n } else if (support.blob) {\n return this.blob().then(readBlobAsArrayBuffer)\n } else {\n throw new Error('could not read as ArrayBuffer')\n }\n }\n\n this.text = function() {\n var rejected = consumed(this)\n if (rejected) {\n return rejected\n }\n\n if (this._bodyBlob) {\n return readBlobAsText(this._bodyBlob)\n } else if (this._bodyArrayBuffer) {\n return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))\n } else if (this._bodyFormData) {\n throw new Error('could not read FormData body as text')\n } else {\n return Promise.resolve(this._bodyText)\n }\n }\n\n if (support.formData) {\n this.formData = function() {\n return this.text().then(decode)\n }\n }\n\n this.json = function() {\n return this.text().then(JSON.parse)\n }\n\n return this\n}\n\n// HTTP methods whose capitalization should be normalized\nvar methods = ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE']\n\nfunction normalizeMethod(method) {\n var upcased = method.toUpperCase()\n return methods.indexOf(upcased) > -1 ? upcased : method\n}\n\nfunction Request(input, options) {\n if (!(this instanceof Request)) {\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n }\n\n options = options || {}\n var body = options.body\n\n if (input instanceof Request) {\n if (input.bodyUsed) {\n throw new TypeError('Already read')\n }\n this.url = input.url\n this.credentials = input.credentials\n if (!options.headers) {\n this.headers = new Headers(input.headers)\n }\n this.method = input.method\n this.mode = input.mode\n this.signal = input.signal\n if (!body && input._bodyInit != null) {\n body = input._bodyInit\n input.bodyUsed = true\n }\n } else {\n this.url = String(input)\n }\n\n this.credentials = options.credentials || this.credentials || 'same-origin'\n if (options.headers || !this.headers) {\n this.headers = new Headers(options.headers)\n }\n this.method = normalizeMethod(options.method || this.method || 'GET')\n this.mode = options.mode || this.mode || null\n this.signal = options.signal || this.signal || (function () {\n if ('AbortController' in g) {\n var ctrl = new AbortController();\n return ctrl.signal;\n }\n }());\n this.referrer = null\n\n if ((this.method === 'GET' || this.method === 'HEAD') && body) {\n throw new TypeError('Body not allowed for GET or HEAD requests')\n }\n this._initBody(body)\n\n if (this.method === 'GET' || this.method === 'HEAD') {\n if (options.cache === 'no-store' || options.cache === 'no-cache') {\n // Search for a '_' parameter in the query string\n var reParamSearch = /([?&])_=[^&]*/\n if (reParamSearch.test(this.url)) {\n // If it already exists then set the value with the current time\n this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime())\n } else {\n // Otherwise add a new '_' parameter to the end with the current time\n var reQueryString = /\\?/\n this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime()\n }\n }\n }\n}\n\nRequest.prototype.clone = function() {\n return new Request(this, {body: this._bodyInit})\n}\n\nfunction decode(body) {\n var form = new FormData()\n body\n .trim()\n .split('&')\n .forEach(function(bytes) {\n if (bytes) {\n var split = bytes.split('=')\n var name = split.shift().replace(/\\+/g, ' ')\n var value = split.join('=').replace(/\\+/g, ' ')\n form.append(decodeURIComponent(name), decodeURIComponent(value))\n }\n })\n return form\n}\n\nfunction parseHeaders(rawHeaders) {\n var headers = new Headers()\n // Replace instances of \\r\\n and \\n followed by at least one space or horizontal tab with a space\n // https://tools.ietf.org/html/rfc7230#section-3.2\n var preProcessedHeaders = rawHeaders.replace(/\\r?\\n[\\t ]+/g, ' ')\n // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill\n // https://github.com/github/fetch/issues/748\n // https://github.com/zloirock/core-js/issues/751\n preProcessedHeaders\n .split('\\r')\n .map(function(header) {\n return header.indexOf('\\n') === 0 ? header.substr(1, header.length) : header\n })\n .forEach(function(line) {\n var parts = line.split(':')\n var key = parts.shift().trim()\n if (key) {\n var value = parts.join(':').trim()\n try {\n headers.append(key, value)\n } catch (error) {\n console.warn('Response ' + error.message)\n }\n }\n })\n return headers\n}\n\nBody.call(Request.prototype)\n\nfunction Response(bodyInit, options) {\n if (!(this instanceof Response)) {\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n }\n if (!options) {\n options = {}\n }\n\n this.type = 'default'\n this.status = options.status === undefined ? 200 : options.status\n if (this.status < 200 || this.status > 599) {\n throw new RangeError(\"Failed to construct 'Response': The status provided (0) is outside the range [200, 599].\")\n }\n this.ok = this.status >= 200 && this.status < 300\n this.statusText = options.statusText === undefined ? '' : '' + options.statusText\n this.headers = new Headers(options.headers)\n this.url = options.url || ''\n this._initBody(bodyInit)\n}\n\nBody.call(Response.prototype)\n\nResponse.prototype.clone = function() {\n return new Response(this._bodyInit, {\n status: this.status,\n statusText: this.statusText,\n headers: new Headers(this.headers),\n url: this.url\n })\n}\n\nResponse.error = function() {\n var response = new Response(null, {status: 200, statusText: ''})\n response.ok = false\n response.status = 0\n response.type = 'error'\n return response\n}\n\nvar redirectStatuses = [301, 302, 303, 307, 308]\n\nResponse.redirect = function(url, status) {\n if (redirectStatuses.indexOf(status) === -1) {\n throw new RangeError('Invalid status code')\n }\n\n return new Response(null, {status: status, headers: {location: url}})\n}\n\nvar DOMException = g.DOMException\ntry {\n new DOMException()\n} catch (err) {\n DOMException = function(message, name) {\n this.message = message\n this.name = name\n var error = Error(message)\n this.stack = error.stack\n }\n DOMException.prototype = Object.create(Error.prototype)\n DOMException.prototype.constructor = DOMException\n}\n\nfunction fetch_fetch(input, init) {\n return new Promise(function(resolve, reject) {\n var request = new Request(input, init)\n\n if (request.signal && request.signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n var xhr = new XMLHttpRequest()\n\n function abortXhr() {\n xhr.abort()\n }\n\n xhr.onload = function() {\n var options = {\n statusText: xhr.statusText,\n headers: parseHeaders(xhr.getAllResponseHeaders() || '')\n }\n // This check if specifically for when a user fetches a file locally from the file system\n // Only if the status is out of a normal range\n if (request.url.indexOf('file://') === 0 && (xhr.status < 200 || xhr.status > 599)) {\n options.status = 200;\n } else {\n options.status = xhr.status;\n }\n options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')\n var body = 'response' in xhr ? xhr.response : xhr.responseText\n setTimeout(function() {\n resolve(new Response(body, options))\n }, 0)\n }\n\n xhr.onerror = function() {\n setTimeout(function() {\n reject(new TypeError('Network request failed'))\n }, 0)\n }\n\n xhr.ontimeout = function() {\n setTimeout(function() {\n reject(new TypeError('Network request timed out'))\n }, 0)\n }\n\n xhr.onabort = function() {\n setTimeout(function() {\n reject(new DOMException('Aborted', 'AbortError'))\n }, 0)\n }\n\n function fixUrl(url) {\n try {\n return url === '' && g.location.href ? g.location.href : url\n } catch (e) {\n return url\n }\n }\n\n xhr.open(request.method, fixUrl(request.url), true)\n\n if (request.credentials === 'include') {\n xhr.withCredentials = true\n } else if (request.credentials === 'omit') {\n xhr.withCredentials = false\n }\n\n if ('responseType' in xhr) {\n if (support.blob) {\n xhr.responseType = 'blob'\n } else if (\n support.arrayBuffer\n ) {\n xhr.responseType = 'arraybuffer'\n }\n }\n\n if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers || (g.Headers && init.headers instanceof g.Headers))) {\n var names = [];\n Object.getOwnPropertyNames(init.headers).forEach(function(name) {\n names.push(normalizeName(name))\n xhr.setRequestHeader(name, normalizeValue(init.headers[name]))\n })\n request.headers.forEach(function(value, name) {\n if (names.indexOf(name) === -1) {\n xhr.setRequestHeader(name, value)\n }\n })\n } else {\n request.headers.forEach(function(value, name) {\n xhr.setRequestHeader(name, value)\n })\n }\n\n if (request.signal) {\n request.signal.addEventListener('abort', abortXhr)\n\n xhr.onreadystatechange = function() {\n // DONE (success or failure)\n if (xhr.readyState === 4) {\n request.signal.removeEventListener('abort', abortXhr)\n }\n }\n }\n\n xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)\n })\n}\n\nfetch_fetch.polyfill = true\n\nif (!g.fetch) {\n g.fetch = fetch_fetch\n g.Headers = Headers\n g.Request = Request\n g.Response = Response\n}\n\n;// ./src/constants/numbers.ts\nconst MAX_DECIMALS = 6;\nconst DEFAULT_BLEND_STEPS = 5;\nconst DEFAULT_SHADES_TINTS_STEPS = 5;\nconst BASE_255 = 255;\nconst MAX_HUE = 360;\nconst MAX_PCENT = 100;\nconst MAX_ALPHA = 1;\nconst MAX_LAB = 125;\nconst MAX_LCH_C = 150;\n\n;// ./src/constants/enums.ts\nvar ColorModel;\n(function (ColorModel) {\n ColorModel[\"HEX\"] = \"HEX\";\n ColorModel[\"RGB\"] = \"RGB\";\n ColorModel[\"HWB\"] = \"HWB\";\n ColorModel[\"HSL\"] = \"HSL\";\n ColorModel[\"CIELab\"] = \"CIELab\";\n ColorModel[\"LCH\"] = \"LCH\";\n ColorModel[\"CMYK\"] = \"CMYK\";\n})(ColorModel || (ColorModel = {}));\nvar Harmony;\n(function (Harmony) {\n Harmony[\"ANALOGOUS\"] = \"ANALOGOUS\";\n Harmony[\"COMPLEMENTARY\"] = \"COMPLEMENTARY\";\n Harmony[\"SPLIT_COMPLEMENTARY\"] = \"SPLIT_COMPLEMENTARY\";\n Harmony[\"TRIADIC\"] = \"TRIADIC\";\n Harmony[\"TETRADIC\"] = \"TETRADIC\";\n Harmony[\"SQUARE\"] = \"SQUARE\";\n})(Harmony || (Harmony = {}));\nvar Mix;\n(function (Mix) {\n Mix[\"ADDITIVE\"] = \"ADDITIVE\";\n Mix[\"SUBTRACTIVE\"] = \"SUBTRACTIVE\";\n})(Mix || (Mix = {}));\nvar ColorKeywords;\n(function (ColorKeywords) {\n ColorKeywords[\"black\"] = \"#000000\";\n ColorKeywords[\"silver\"] = \"#C0C0C0\";\n ColorKeywords[\"gray\"] = \"#808080\";\n ColorKeywords[\"white\"] = \"#FFFFFF\";\n ColorKeywords[\"maroon\"] = \"#800000\";\n ColorKeywords[\"red\"] = \"#FF0000\";\n ColorKeywords[\"purple\"] = \"#800080\";\n ColorKeywords[\"fuchsia\"] = \"#FF00FF\";\n ColorKeywords[\"green\"] = \"#008000\";\n ColorKeywords[\"lime\"] = \"#00FF00\";\n ColorKeywords[\"olive\"] = \"#808000\";\n ColorKeywords[\"yellow\"] = \"#FFFF00\";\n ColorKeywords[\"navy\"] = \"#000080\";\n ColorKeywords[\"blue\"] = \"#0000FF\";\n ColorKeywords[\"teal\"] = \"#008080\";\n ColorKeywords[\"aqua\"] = \"#00FFFF\";\n ColorKeywords[\"orange\"] = \"#FFA500\";\n ColorKeywords[\"aliceblue\"] = \"#F0F8FF\";\n ColorKeywords[\"antiquewhite\"] = \"#FAEBD7\";\n ColorKeywords[\"aquamarine\"] = \"#7FFFD4\";\n ColorKeywords[\"azure\"] = \"#F0FFFF\";\n ColorKeywords[\"beige\"] = \"#F5F5DC\";\n ColorKeywords[\"bisque\"] = \"#FFE4C4\";\n ColorKeywords[\"blanchedalmond\"] = \"#FFEBCD\";\n ColorKeywords[\"blueviolet\"] = \"#8A2BE2\";\n ColorKeywords[\"brown\"] = \"#A52A2A\";\n ColorKeywords[\"burlywood\"] = \"#DEB887\";\n ColorKeywords[\"cadetblue\"] = \"#5F9EA0\";\n ColorKeywords[\"chartreuse\"] = \"#7FFF00\";\n ColorKeywords[\"chocolate\"] = \"#D2691E\";\n ColorKeywords[\"coral\"] = \"#FF7F50\";\n ColorKeywords[\"cornflowerblue\"] = \"#6495ED\";\n ColorKeywords[\"cornsilk\"] = \"#FFF8DC\";\n ColorKeywords[\"crimson\"] = \"#DC143C\";\n ColorKeywords[\"cyan\"] = \"#00FFFF\";\n ColorKeywords[\"darkblue\"] = \"#00008B\";\n ColorKeywords[\"darkcyan\"] = \"#008B8B\";\n ColorKeywords[\"darkgoldenrod\"] = \"#B8860B\";\n ColorKeywords[\"darkgray\"] = \"#A9A9A9\";\n ColorKeywords[\"darkgreen\"] = \"#006400\";\n ColorKeywords[\"darkgrey\"] = \"#A9A9A9\";\n ColorKeywords[\"darkkhaki\"] = \"#BDB76B\";\n ColorKeywords[\"darkmagenta\"] = \"#8B008B\";\n ColorKeywords[\"darkolivegreen\"] = \"#556B2F\";\n ColorKeywords[\"darkorange\"] = \"#FF8C00\";\n ColorKeywords[\"darkorchid\"] = \"#9932CC\";\n ColorKeywords[\"darkred\"] = \"#8B0000\";\n ColorKeywords[\"darksalmon\"] = \"#E9967A\";\n ColorKeywords[\"darkseagreen\"] = \"#8FBC8F\";\n ColorKeywords[\"darkslateblue\"] = \"#483D8B\";\n ColorKeywords[\"darkslategray\"] = \"#2F4F4F\";\n ColorKeywords[\"darkslategrey\"] = \"#2F4F4F\";\n ColorKeywords[\"darkturquoise\"] = \"#00CED1\";\n ColorKeywords[\"darkviolet\"] = \"#9400D3\";\n ColorKeywords[\"deeppink\"] = \"#FF1493\";\n ColorKeywords[\"deepskyblue\"] = \"#00BFFF\";\n ColorKeywords[\"dimgray\"] = \"#696969\";\n ColorKeywords[\"dimgrey\"] = \"#696969\";\n ColorKeywords[\"dodgerblue\"] = \"#1E90FF\";\n ColorKeywords[\"firebrick\"] = \"#B22222\";\n ColorKeywords[\"floralwhite\"] = \"#FFFAF0\";\n ColorKeywords[\"forestgreen\"] = \"#228B22\";\n ColorKeywords[\"gainsboro\"] = \"#DCDCDC\";\n ColorKeywords[\"ghostwhite\"] = \"#F8F8FF\";\n ColorKeywords[\"gold\"] = \"#FFD700\";\n ColorKeywords[\"goldenrod\"] = \"#DAA520\";\n ColorKeywords[\"greenyellow\"] = \"#ADFF2F\";\n ColorKeywords[\"grey\"] = \"#808080\";\n ColorKeywords[\"honeydew\"] = \"#F0FFF0\";\n ColorKeywords[\"hotpink\"] = \"#FF69B4\";\n ColorKeywords[\"indianred\"] = \"#CD5C5C\";\n ColorKeywords[\"indigo\"] = \"#4B0082\";\n ColorKeywords[\"ivory\"] = \"#FFFFF0\";\n ColorKeywords[\"khaki\"] = \"#F0E68C\";\n ColorKeywords[\"lavender\"] = \"#E6E6FA\";\n ColorKeywords[\"lavenderblush\"] = \"#FFF0F5\";\n ColorKeywords[\"lawngreen\"] = \"#7CFC00\";\n ColorKeywords[\"lemonchiffon\"] = \"#FFFACD\";\n ColorKeywords[\"lightblue\"] = \"#ADD8E6\";\n ColorKeywords[\"lightcoral\"] = \"#F08080\";\n ColorKeywords[\"lightcyan\"] = \"#E0FFFF\";\n ColorKeywords[\"lightgoldenrodyellow\"] = \"#FAFAD2\";\n ColorKeywords[\"lightgray\"] = \"#D3D3D3\";\n ColorKeywords[\"lightgreen\"] = \"#90EE90\";\n ColorKeywords[\"lightgrey\"] = \"#D3D3D3\";\n ColorKeywords[\"lightpink\"] = \"#FFB6C1\";\n ColorKeywords[\"lightsalmon\"] = \"#FFA07A\";\n ColorKeywords[\"lightseagreen\"] = \"#20B2AA\";\n ColorKeywords[\"lightskyblue\"] = \"#87CEFA\";\n ColorKeywords[\"lightslategray\"] = \"#778899\";\n ColorKeywords[\"lightslategrey\"] = \"#778899\";\n ColorKeywords[\"lightsteelblue\"] = \"#B0C4DE\";\n ColorKeywords[\"lightyellow\"] = \"#FFFFE0\";\n ColorKeywords[\"limegreen\"] = \"#32CD32\";\n ColorKeywords[\"linen\"] = \"#FAF0E6\";\n ColorKeywords[\"magenta\"] = \"#FF00FF\";\n ColorKeywords[\"mediumaquamarine\"] = \"#66CDAA\";\n ColorKeywords[\"mediumblue\"] = \"#0000CD\";\n ColorKeywords[\"mediumorchid\"] = \"#BA55D3\";\n ColorKeywords[\"mediumpurple\"] = \"#9370DB\";\n ColorKeywords[\"mediumseagreen\"] = \"#3CB371\";\n ColorKeywords[\"mediumslateblue\"] = \"#7B68EE\";\n ColorKeywords[\"mediumspringgreen\"] = \"#00FA9A\";\n ColorKeywords[\"mediumturquoise\"] = \"#48D1CC\";\n ColorKeywords[\"mediumvioletred\"] = \"#C71585\";\n ColorKeywords[\"midnightblue\"] = \"#191970\";\n ColorKeywords[\"mintcream\"] = \"#F5FFFA\";\n ColorKeywords[\"mistyrose\"] = \"#FFE4E1\";\n ColorKeywords[\"moccasin\"] = \"#FFE4B5\";\n ColorKeywords[\"navajowhite\"] = \"#FFDEAD\";\n ColorKeywords[\"oldlace\"] = \"#FDF5E6\";\n ColorKeywords[\"olivedrab\"] = \"#6B8E23\";\n ColorKeywords[\"orangered\"] = \"#FF4500\";\n ColorKeywords[\"orchid\"] = \"#DA70D6\";\n ColorKeywords[\"palegoldenrod\"] = \"#EEE8AA\";\n ColorKeywords[\"palegreen\"] = \"#98FB98\";\n ColorKeywords[\"paleturquoise\"] = \"#AFEEEE\";\n ColorKeywords[\"palevioletred\"] = \"#DB7093\";\n ColorKeywords[\"papayawhip\"] = \"#FFEFD5\";\n ColorKeywords[\"peachpuff\"] = \"#FFDAB9\";\n ColorKeywords[\"peru\"] = \"#CD853F\";\n ColorKeywords[\"pink\"] = \"#FFC0CB\";\n ColorKeywords[\"plum\"] = \"#DDA0DD\";\n ColorKeywords[\"powderblue\"] = \"#B0E0E6\";\n ColorKeywords[\"rosybrown\"] = \"#BC8F8F\";\n ColorKeywords[\"royalblue\"] = \"#4169E1\";\n ColorKeywords[\"saddlebrown\"] = \"#8B4513\";\n ColorKeywords[\"salmon\"] = \"#FA8072\";\n ColorKeywords[\"sandybrown\"] = \"#F4A460\";\n ColorKeywords[\"seagreen\"] = \"#2E8B57\";\n ColorKeywords[\"seashell\"] = \"#FFF5EE\";\n ColorKeywords[\"sienna\"] = \"#A0522D\";\n ColorKeywords[\"skyblue\"] = \"#87CEEB\";\n ColorKeywords[\"slateblue\"] = \"#6A5ACD\";\n ColorKeywords[\"slategray\"] = \"#708090\";\n ColorKeywords[\"slategrey\"] = \"#708090\";\n ColorKeywords[\"snow\"] = \"#FFFAFA\";\n ColorKeywords[\"springgreen\"] = \"#00FF7F\";\n ColorKeywords[\"steelblue\"] = \"#4682B4\";\n ColorKeywords[\"tan\"] = \"#D2B48C\";\n ColorKeywords[\"thistle\"] = \"#D8BFD8\";\n ColorKeywords[\"tomato\"] = \"#FF6347\";\n ColorKeywords[\"turquoise\"] = \"#40E0D0\";\n ColorKeywords[\"violet\"] = \"#EE82EE\";\n ColorKeywords[\"wheat\"] = \"#F5DEB3\";\n ColorKeywords[\"whitesmoke\"] = \"#F5F5F5\";\n ColorKeywords[\"yellowgreen\"] = \"#9ACD32\";\n ColorKeywords[\"rebeccapurple\"] = \"#663399\";\n})(ColorKeywords || (ColorKeywords = {}));\nconst COLOR_KEYS = Object.keys(ColorKeywords);\nconst COLOR_PROPS = {\n HEX: ['R', 'G', 'B', 'A'],\n RGB: ['R', 'G', 'B', 'A'],\n HSL: ['H', 'S', 'L', 'A'],\n HWB: ['H', 'W', 'B', 'A'],\n CIELab: ['L', 'a', 'b', 'A'],\n LCH: ['L', 'C', 'H', 'A'],\n CMYK: ['C', 'M', 'Y', 'K', 'A']\n};\nconst VALID_COLOR_OBJECTS = {\n ABGR: ColorModel.RGB,\n ABHW: ColorModel.HWB,\n ACHL: ColorModel.LCH,\n ACKMY: ColorModel.CMYK,\n AHLS: ColorModel.HSL,\n ALAB: ColorModel.CIELab,\n BGR: ColorModel.RGB,\n BHW: ColorModel.HWB,\n CHL: ColorModel.LCH,\n CKMY: ColorModel.CMYK,\n HLS: ColorModel.HSL,\n LAB: ColorModel.CIELab\n};\nvar TypeOf;\n(function (TypeOf) {\n TypeOf[\"NUMBER\"] = \"number\";\n TypeOf[\"BOOLEAN\"] = \"boolean\";\n})(TypeOf || (TypeOf = {}));\n\n;// ./src/constants/regexps.ts\n\nconst COLORREGS = {\n [ColorModel.HEX]: /^#(?:(?[a-f\\d])(?[a-f\\d])(?[a-f\\d])(?
[a-f\\d])?|(?[a-f\\d]{2})(?[a-f\\d]{2})(?[a-f\\d]{2})(?[a-f\\d]{2})?)$/i,\n [ColorModel.RGB]: /^rgba?\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.HWB]: /^hwb\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s+(?(?:\\d*\\.)?\\d+)%\\s+(?(?:\\d*\\.)?\\d+)%(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))%?\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))%?(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.HSL]: /^hsla?\\s*\\(\\s*(?:(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s*,\\s*(?(?:\\d*\\.)?\\d+)%\\s*,\\s*(?(?:\\d*\\.)?\\d+)%(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s+(?(?:\\d*\\.)?\\d+)%?\\s+(?(?:\\d*\\.)?\\d+)%?(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))%?\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))%?(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.CIELab]: /^lab\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.LCH]: /^lch\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.CMYK]: /^(?:device-cmyk|cmyk)\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?)\\s*\\)$/\n};\nconst CALC = {\n REGEXP: /^calc\\(\\s*(?[\\d./*+-\\w\\s]+)\\s*\\)$/,\n SCOPED: /\\(\\s*([^()]+)\\s*\\)/g,\n DIVISION: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n MULTIPLICATION: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\*\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n SUM: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\+\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n REST: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*-\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/\n};\nconst HSL_HUE = /^(?-?(?:\\d*\\.)?\\d+)(?(?:deg|grad|rad|turn)?)$/;\nconst PCENT = /^(-?\\d+(?:\\.\\d+)?|-?\\.\\d+)%$/;\nconst HEX = /^0x([a-f\\d]{1,2})$/i;\nconst TEMPLATE_VAR = /\\{(\\d+)\\}/g;\nconst COMMAS_AND_NEXT_CHARS = /,( +|\\d+)/g;\nconst SPACES = / +/;\n\n;// ./src/constants/errors.ts\nconst ERRORS = {\n NOT_ACCEPTED_STRING_INPUT: 'The provided string color doesn\\'t have a correct format',\n NOT_ACCEPTED_OBJECT_INPUT: 'The provided color object doesn\\'t have the proper keys or format',\n NOT_A_VALID_RELATIVE_COLOR: 'is not a valid operation for a relative color'\n};\n\n;// ./src/@types/index.ts\nvar AnglesUnitEnum;\n(function (AnglesUnitEnum) {\n AnglesUnitEnum[\"NONE\"] = \"none\";\n AnglesUnitEnum[\"DEGREES\"] = \"deg\";\n AnglesUnitEnum[\"GRADIANS\"] = \"grad\";\n AnglesUnitEnum[\"RADIANS\"] = \"rad\";\n AnglesUnitEnum[\"TURNS\"] = \"turn\";\n})(AnglesUnitEnum || (AnglesUnitEnum = {}));\nvar ColorUnitEnum;\n(function (ColorUnitEnum) {\n ColorUnitEnum[\"NONE\"] = \"none\";\n ColorUnitEnum[\"PERCENT\"] = \"percent\";\n})(ColorUnitEnum || (ColorUnitEnum = {}));\nvar CMYKFunctionEnum;\n(function (CMYKFunctionEnum) {\n CMYKFunctionEnum[\"DEVICE_CMYK\"] = \"device-cmyk\";\n CMYKFunctionEnum[\"CMYK\"] = \"cmyk\";\n})(CMYKFunctionEnum || (CMYKFunctionEnum = {}));\n\n;// ./src/constants/options.ts\n\n\nconst DEFAULT_OPTIONS = {\n decimals: MAX_DECIMALS,\n legacyCSS: false,\n spacesAfterCommas: false,\n anglesUnit: AnglesUnitEnum.NONE,\n rgbUnit: ColorUnitEnum.NONE,\n labUnit: ColorUnitEnum.NONE,\n lchUnit: ColorUnitEnum.NONE,\n cmykUnit: ColorUnitEnum.PERCENT,\n alphaUnit: ColorUnitEnum.NONE,\n cmykFunction: CMYKFunctionEnum.DEVICE_CMYK\n};\n\n;// ./src/constants/index.ts\n\n\n\n\n\n\n\n;// ./src/helpers/index.ts\n\n\nconst hasProp = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);\nconst percentNumber = (percent) => {\n return +`${percent}`.replace(PCENT, '$1');\n};\nconst percent = (percent) => PCENT.test(`${percent}`)\n ? percentNumber(percent)\n : Math.min(+percent, 100);\nconst getDEC = (hex) => {\n if (hex.length === 1) {\n hex += hex;\n }\n return parseInt(hex, 16);\n};\nconst getHEX = (number) => {\n const hex = round(number, 0).toString(16).toUpperCase();\n if (hex.length === 1) {\n return `0x0${hex}`;\n }\n return `0x${hex}`;\n};\nconst toHEX = (h) => {\n let hex = round(h, 0).toString(16).toUpperCase();\n if (hex.length === 1) {\n hex = `0${hex}`;\n }\n return hex;\n};\nconst from255NumberToPercent = (value, decimals) => round(value / BASE_255 * 100, decimals);\nconst from125NumberToPercent = (value, decimals) => round(value / MAX_LAB * 100, decimals);\nconst from150NumberToPercent = (value, decimals) => round(value / MAX_LCH_C * 100, decimals);\nconst getBase255Number = (color, alpha = false) => {\n if (!alpha && PCENT.test(color)) {\n return Math.min(BASE_255 * percentNumber(color) / 100, BASE_255);\n }\n if (HEX.test(color)) {\n if (color.length === 3) {\n color += color.slice(-1);\n }\n return alpha\n ? round(color) / BASE_255\n : round(color);\n }\n return Math.min(+color, alpha ? 1 : BASE_255);\n};\nconst getBase125Number = (color) => {\n if (PCENT.test(color)) {\n return minmax(MAX_LAB * percentNumber(color) / 100, -MAX_LAB, MAX_LAB);\n }\n return minmax(+color, -MAX_LAB, MAX_LAB);\n};\nconst getBase150Number = (color) => {\n if (PCENT.test(color)) {\n return minmax(MAX_LCH_C * percentNumber(color) / 100, -MAX_LCH_C, MAX_LCH_C);\n }\n return minmax(+color, -MAX_LCH_C, MAX_LCH_C);\n};\nconst getCMYKNumber = (color) => Math.min(PCENT.test(color) ? percentNumber(color) / 100 : +color, 1);\nconst getOrderedArrayString = (keys) => [...keys].sort().join('').toUpperCase();\nconst round = (value, decimals = MAX_DECIMALS) => {\n const exp = Math.pow(10, decimals);\n return Math.round(+value * exp) / exp;\n};\nconst minmax = (n, min, max) => Math.max(min, Math.min(n, max));\nconst degrees = (radian) => radian * 180 / Math.PI;\nconst radians = (degrees) => degrees * Math.PI / 180;\nconst pi2 = 360;\nconst normalizeHue = (hue) => {\n if (typeof hue === 'string') {\n const matches = hue.match(HSL_HUE);\n const groups = matches.groups;\n const value = +groups.number;\n const units = groups.units;\n switch (units) {\n case AnglesUnitEnum.RADIANS:\n hue = round(degrees(value));\n break;\n case AnglesUnitEnum.TURNS:\n hue = round(value * pi2);\n break;\n case AnglesUnitEnum.GRADIANS:\n hue = round(9 / 10 * value);\n break;\n case AnglesUnitEnum.DEGREES:\n default:\n hue = value;\n }\n }\n if (hue > 360 || hue < 0) {\n hue -= Math.floor(hue / pi2) * pi2;\n }\n return hue;\n};\nconst normalizeAlpha = (alpha) => {\n if (typeof alpha === 'string') {\n if (PCENT.test(alpha)) {\n alpha = percentNumber(alpha) / 100;\n }\n else {\n alpha = +alpha;\n }\n }\n return (isNaN(+alpha) || alpha > MAX_ALPHA) ? MAX_ALPHA : round(alpha);\n};\nconst translateDegrees = (degrees, units) => {\n let hue;\n switch (units) {\n case AnglesUnitEnum.RADIANS:\n hue = round(radians(degrees));\n break;\n case AnglesUnitEnum.TURNS:\n hue = round(degrees / pi2);\n break;\n case AnglesUnitEnum.GRADIANS:\n hue = round(10 / 9 * degrees);\n break;\n case AnglesUnitEnum.DEGREES:\n case AnglesUnitEnum.NONE:\n default:\n hue = degrees;\n }\n return hue;\n};\nconst isHarmony = (param) => {\n return `${param}` in Harmony;\n};\nconst isMix = (param) => {\n return `${param}` in Mix;\n};\n\n;// ./src/color/translators.ts\n\n\nconst MATRIX_LRGB_XYZ_D50 = [\n [0.4360747, 0.3850649, 0.1430804],\n [0.2225045, 0.7168786, 0.0606169],\n [0.0139322, 0.0971045, 0.7141733]\n];\nconst MATRIX_XYZ_D50_LRGB = [\n [3.1338561, -1.6168667, -0.4906146],\n [-0.9787684, 1.9161415, 0.033454],\n [0.0719453, -0.2289914, 1.4052427]\n];\nconst TRISTIMULUS_D50 = MATRIX_LRGB_XYZ_D50.map((matrix) => {\n return matrix.reduce((sum, value) => sum + value, 0);\n});\nconst hueToRgb = (t1, t2, hue) => {\n if (hue < 0) {\n hue += 6;\n }\n if (hue >= 6) {\n hue -= 6;\n }\n if (hue < 1) {\n return round(((t2 - t1) * hue + t1) * BASE_255);\n }\n else if (hue < 3) {\n return round(t2 * BASE_255);\n }\n else if (hue < 4) {\n return round(((t2 - t1) * (4 - hue) + t1) * BASE_255);\n }\n else {\n return round(t1 * BASE_255);\n }\n};\nconst rgbToLinearLightRgb = (value) => {\n return value <= 0.04045\n ? value / 12.92\n : ((value + 0.055) / 1.055) ** 2.4;\n};\nconst linearLightRgbToRgb = (value) => {\n return value <= 0.0031308\n ? 12.92 * value\n : 1.055 * (value ** (1 / 2.4)) - 0.055;\n};\nconst matrixVectorMultiplication = (v1, v2, v3, matrix) => {\n const result = [0, 0, 0];\n const linearRgb = [v1, v2, v3];\n matrix.forEach((array, index) => {\n array.forEach((value, mindex) => {\n result[index] += value * linearRgb[mindex];\n });\n });\n return result;\n};\nconst from_CIE_XYZ_D50_to_CIE_LAB = (x, y, z) => {\n const f = (t) => {\n return t > (6 / 29) ** 3\n ? Math.cbrt(t)\n : t / (3 * (6 / 29) ** 2) + (4 / 29);\n };\n const fx = f(x / TRISTIMULUS_D50[0]);\n const fy = f(y / TRISTIMULUS_D50[1]);\n const fz = f(z / TRISTIMULUS_D50[2]);\n return [\n 116 * fy - 16,\n 500 * (fx - fy),\n 200 * (fy - fz)\n ];\n};\nconst from_CIE_LAB_to_CIE_XYZ_D50 = (L, a, b) => {\n const f = (t) => {\n return t > 6 / 29\n ? t ** 3\n : 3 * (6 / 29) ** 2 * (t - 4 / 29);\n };\n const fl = (L + 16) / 116;\n const fa = a / 500;\n const fb = b / 200;\n return [\n TRISTIMULUS_D50[0] * f(fl + fa),\n TRISTIMULUS_D50[1] * f(fl),\n TRISTIMULUS_D50[2] * f(fl - fb)\n ];\n};\nconst hslToRgb = (H, S, L) => {\n H /= 60;\n S /= 100;\n L /= 100;\n const t2 = (L <= .5)\n ? L * (S + 1)\n : L + S - (L * S);\n const t1 = L * 2 - t2;\n const R = hueToRgb(t1, t2, H + 2);\n const G = hueToRgb(t1, t2, H);\n const B = hueToRgb(t1, t2, H - 2);\n return { R, G, B };\n};\nconst rgbToHsl = (R, G, B, A = 1) => {\n R /= BASE_255;\n G /= BASE_255;\n B /= BASE_255;\n A = Math.min(A, MAX_ALPHA);\n const MAX = Math.max(R, G, B);\n const MIN = Math.min(R, G, B);\n const D = MAX - MIN;\n let H = 0;\n let S = 0;\n const L = (MAX + MIN) / 2;\n if (D !== 0) {\n switch (MAX) {\n case R:\n H = ((G - B) / D) % 6;\n break;\n case G:\n H = (B - R) / D + 2;\n break;\n case B:\n H = (R - G) / D + 4;\n break;\n }\n H = round(H * 60);\n if (H < 0) {\n H += 360;\n }\n S = D / (1 - Math.abs(2 * L - 1));\n }\n return {\n H,\n S: round(S * 100),\n L: round(L * 100),\n A\n };\n};\nconst rgbToLab = (R, G, B) => {\n const LINEAR_LIGHT_RGB = [\n R / BASE_255,\n G / BASE_255,\n B / BASE_255\n ].map(rgbToLinearLightRgb);\n const CIE_XYZ_D50 = matrixVectorMultiplication(LINEAR_LIGHT_RGB[0], LINEAR_LIGHT_RGB[1], LINEAR_LIGHT_RGB[2], MATRIX_LRGB_XYZ_D50);\n const CIE_LAB = from_CIE_XYZ_D50_to_CIE_LAB(CIE_XYZ_D50[0], CIE_XYZ_D50[1], CIE_XYZ_D50[2]);\n return {\n L: CIE_LAB[0],\n a: CIE_LAB[1],\n b: CIE_LAB[2]\n };\n};\nconst labToRgb = (L, a, b) => {\n const CIE_XYZ_D50 = from_CIE_LAB_to_CIE_XYZ_D50(L, a, b);\n const LINEAR_LIGHT_RGB = matrixVectorMultiplication(CIE_XYZ_D50[0], CIE_XYZ_D50[1], CIE_XYZ_D50[2], MATRIX_XYZ_D50_LRGB);\n const rgb = LINEAR_LIGHT_RGB.map(linearLightRgbToRgb);\n return {\n R: minmax(rgb[0] * BASE_255, 0, BASE_255),\n G: minmax(rgb[1] * BASE_255, 0, BASE_255),\n B: minmax(rgb[2] * BASE_255, 0, BASE_255)\n };\n};\nconst labToLch = (L, a, b) => {\n const C = Math.sqrt(a ** 2 + b ** 2);\n const H = degrees(Math.atan2(b, a));\n return {\n L,\n C,\n H: normalizeHue(H)\n };\n};\nconst lchToLab = (L, C, H) => {\n const radH = radians(H);\n const a = C * Math.cos(radH);\n const b = C * Math.sin(radH);\n return {\n L,\n a,\n b\n };\n};\nconst rgbToLch = (R, G, B) => {\n const lab = rgbToLab(R, G, B);\n return labToLch(lab.L, lab.a, lab.b);\n};\nconst lchToRgb = (L, C, H) => {\n const lab = lchToLab(L, C, H);\n return labToRgb(lab.L, lab.a, lab.b);\n};\nconst rgbToHwb = (R, G, B, A = 1) => {\n const hsl = rgbToHsl(R, G, B, A);\n return {\n H: hsl.H,\n W: round(Math.min(R, G, B) / BASE_255 * 100),\n B: round((1 - Math.max(R, G, B) / BASE_255) * 100),\n A\n };\n};\nconst hwbToRgb = (H, W, B) => {\n W /= 100;\n B /= 100;\n const v = 1 - B;\n const c = v - W;\n const x = c * (1 - Math.abs((H / 60) % 2 - 1));\n let rgbR = 0;\n let rgbG = 0;\n let rgbB = 0;\n if (H < 60) {\n rgbR = c;\n rgbG = x;\n rgbB = 0;\n }\n else if (H >= 60 && H < 120) {\n rgbR = x;\n rgbG = c;\n rgbB = 0;\n }\n else if (H >= 120 && H < 180) {\n rgbR = 0;\n rgbG = c;\n rgbB = x;\n }\n else if (H >= 180 && H < 240) {\n rgbR = 0;\n rgbG = x;\n rgbB = c;\n }\n else if (H >= 240 && H < 300) {\n rgbR = x;\n rgbG = 0;\n rgbB = c;\n }\n else {\n rgbR = c;\n rgbG = 0;\n rgbB = x;\n }\n rgbR += W;\n rgbG += W;\n rgbB += W;\n return {\n R: minmax(rgbR * BASE_255, 0, BASE_255),\n G: minmax(rgbG * BASE_255, 0, BASE_255),\n B: minmax(rgbB * BASE_255, 0, BASE_255)\n };\n};\nconst cmykToRgb = (C, M, Y, K) => {\n K = 1 - K;\n return {\n R: round(BASE_255 * (1 - C) * K),\n G: round(BASE_255 * (1 - M) * K),\n B: round(BASE_255 * (1 - Y) * K)\n };\n};\nconst rgbToCmyk = (R, G, B) => {\n R /= BASE_255;\n G /= BASE_255;\n B /= BASE_255;\n const K = 1 - Math.max(R, G, B);\n const K1 = 1 - K;\n const C = K1 && (K1 - R) / K1;\n const M = K1 && (K1 - G) / K1;\n const Y = K1 && (K1 - B) / K1;\n return {\n C: round(C * 100),\n M: round(M * 100),\n Y: round(Y * 100),\n K: round(K * 100)\n };\n};\nconst rgbToRyb = (R, G, B) => {\n const Iw = Math.min(R, G, B);\n const Ib = Math.min(BASE_255 - R, BASE_255 - G, BASE_255 - B);\n const rRgb = R - Iw;\n const gRgb = G - Iw;\n const bRgb = B - Iw;\n const minRg = Math.min(rRgb, gRgb);\n const rRyb = rRgb - minRg;\n const yRyb = (gRgb + minRg) / 2;\n const bRyb = (bRgb + gRgb - minRg) / 2;\n const n = Math.max(rRyb, yRyb, bRyb) / Math.max(rRgb, gRgb, bRgb);\n const N = isNaN(n) || n === Infinity || n <= 0 ? 1 : n;\n return {\n R: rRyb / N + Ib,\n Y: yRyb / N + Ib,\n B: bRyb / N + Ib\n };\n};\nconst rybToRgb = (R, Y, B) => {\n const Iw = Math.min(R, Y, B);\n const Ib = Math.min(BASE_255 - R, BASE_255 - Y, BASE_255 - B);\n const rRyb = R - Iw;\n const yRyb = Y - Iw;\n const bRyb = B - Iw;\n const minYb = Math.min(yRyb, bRyb);\n const rRgb = rRyb + yRyb - minYb;\n const gRgb = yRyb + minYb;\n const bRgb = 2 * (bRyb - minYb);\n const n = Math.max(rRgb, gRgb, bRgb) / Math.max(rRyb, yRyb, bRyb);\n const N = isNaN(n) || n === Infinity || n <= 0 ? 1 : n;\n return {\n R: rRgb / N + Ib,\n G: gRgb / N + Ib,\n B: bRgb / N + Ib\n };\n};\nconst hueRyb = (hue, toRyb) => {\n if (hue < 0)\n hue += 360;\n if (hue > 360)\n hue -= 360;\n if (hue === 360 || hue === 0)\n return hue;\n const map1 = [\n [0, 120],\n [120, 180],\n [180, 240],\n [240, 360]\n ];\n const map2 = [\n [0, 60],\n [60, 120],\n [120, 240],\n [240, 360]\n ];\n const from = toRyb ? map1 : map2;\n const to = toRyb ? map2 : map1;\n let A = 0;\n let B = 0;\n let C = 0;\n let D = 0;\n from.find((arr, index) => {\n if (hue >= arr[0] && hue < arr[1]) {\n A = arr[0];\n B = arr[1];\n C = to[index][0];\n D = to[index][1];\n return true;\n }\n return false;\n });\n return C + (hue - A) * ((D - C) / (B - A));\n};\n\n;// ./src/parsers/baseClasses/_RgbClass.ts\nclass RgbClass {\n get rgb() {\n return this._rgb;\n }\n}\n\n;// ./src/parsers/_HEXStringParser.ts\n\n\n\nclass HEXStringParser extends RgbClass {\n constructor(colorString) {\n super();\n const match = colorString.match(COLORREGS.HEX);\n const groups = match.groups;\n this._r = groups.r ?? groups.rr;\n this._g = groups.g ?? groups.gg;\n this._b = groups.b ?? groups.bb;\n this._a = groups.a ?? groups.aa;\n const rgb = {\n R: getDEC(this._r),\n G: getDEC(this._g),\n B: getDEC(this._b)\n };\n if (this._a !== undefined) {\n rgb.A = getDEC(this._a) / BASE_255;\n }\n this._rgb = rgb;\n }\n}\n\n;// ./src/parsers/_CalcParser.ts\n\nconst MAX_STACK = 100;\nclass CalcParser {\n constructor(colorIndex, calc, vars) {\n this._operations = new Map([\n [CALC.DIVISION, this._division],\n [CALC.MULTIPLICATION, this._multiplication],\n [CALC.SUM, this._sum],\n [CALC.REST, this._rest]\n ]);\n this._colorIndex = colorIndex;\n let calcString = calc;\n let stack = 0;\n if (!Number.isNaN(+calc)) {\n this._result = +calc;\n }\n else if (calc in vars) {\n this._result = vars[calc];\n }\n else if (CALC.REGEXP.test(calcString)) {\n CALC.REGEXP.lastIndex = 0;\n this._result = this._getCalcValue(calcString, vars);\n }\n else {\n while (CALC.SCOPED.test(calcString) && stack < MAX_STACK) {\n CALC.SCOPED.lastIndex = 0;\n calcString = calcString.replace(CALC.SCOPED, (__match, operation) => {\n return this._calculate(operation, vars).toString();\n });\n if (CALC.REGEXP.test(calcString)) {\n CALC.REGEXP.lastIndex = 0;\n break;\n }\n stack++;\n }\n this._result = this._getCalcValue(calcString, vars);\n }\n }\n _division(left, right) {\n return left / right;\n }\n _multiplication(left, right) {\n return left * right;\n }\n _sum(left, right) {\n return left + right;\n }\n _rest(left, right) {\n return left - right;\n }\n _getCalcValue(calc, vars) {\n const match = calc.match(CALC.REGEXP);\n const operation = match.groups.operation;\n const value = this._calculate(operation, vars);\n if (Number.isNaN(value)) {\n throw new Error(`Invalid value for ${this._colorIndex}. ${operation} ${ERRORS.NOT_A_VALID_RELATIVE_COLOR}`);\n }\n return value;\n }\n _calculate(operation, vars) {\n this._operations.forEach((method, regExp) => {\n let stack = 0;\n while (regExp.test(operation) && stack < MAX_STACK) {\n operation = operation.replace(regExp, (__match, left, right) => {\n return method(vars[left] ?? +left, vars[right] ?? +right).toString();\n });\n stack++;\n }\n });\n return +operation;\n }\n get result() {\n return this._result;\n }\n}\n\n;// ./src/parsers/baseClasses/_AlphaBaseClass.ts\n\n\nclass AlphaBaseClass extends RgbClass {\n get hasPercentageAlpha() {\n return PCENT.test(this._a);\n }\n}\n\n;// ./src/parsers/_RGBStringParser.ts\n\n\n\n\nclass RGBStringParser extends AlphaBaseClass {\n constructor(colorString, getRGBObject) {\n super();\n const match = colorString.match(COLORREGS.RGB);\n const groups = match.groups;\n const { r_legacy, g_legacy, b_legacy, a_legacy, r, g, b, a, from, relative_r, relative_g, relative_b, relative_a } = groups;\n if (from) {\n const fromRGB = getRGBObject(from);\n const fromRGBVars = {\n r: fromRGB.R,\n g: fromRGB.G,\n b: fromRGB.B,\n alpha: fromRGB.A ?? 1\n };\n const R = new CalcParser('r', relative_r, fromRGBVars).result;\n const G = new CalcParser('g', relative_g, fromRGBVars).result;\n const B = new CalcParser('b', relative_b, fromRGBVars).result;\n const rgb = {\n R: Math.min(R, BASE_255),\n G: Math.min(G, BASE_255),\n B: Math.min(B, BASE_255)\n };\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromRGBVars).result;\n rgb.A = Math.min(A, 1);\n }\n this._rgb = rgb;\n }\n else {\n this._r = r_legacy ?? r;\n this._g = g_legacy ?? g;\n this._b = b_legacy ?? b;\n this._a = a_legacy ?? a;\n const rgb = {\n R: Math.min(getBase255Number(this._r), BASE_255),\n G: Math.min(getBase255Number(this._g), BASE_255),\n B: Math.min(getBase255Number(this._b), BASE_255)\n };\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n }\n get hasPercentageValues() {\n return (PCENT.test(this._r) &&\n PCENT.test(this._g) &&\n PCENT.test(this._b));\n }\n static test(colorString) {\n return COLORREGS.RGB.test(colorString);\n }\n}\n\n;// ./src/parsers/baseClasses/_HueBaseClass.ts\n\n\n\nclass HueBaseClass extends AlphaBaseClass {\n get angleUnit() {\n if (this._h) {\n const angleUnitMatch = this._h.match(HSL_HUE);\n const angleUnit = angleUnitMatch.groups.units;\n return angleUnit === ''\n ? AnglesUnitEnum.NONE\n : angleUnit;\n }\n return AnglesUnitEnum.NONE;\n }\n}\n\n;// ./src/parsers/_HSLStringParser.ts\n\n\n\n\n\nclass HSLStringParser extends HueBaseClass {\n constructor(colorString, getRGBObject) {\n super();\n const match = colorString.match(COLORREGS.HSL);\n const groups = match.groups;\n const { h_legacy, s_legacy, l_legacy, a_legacy, h, s, l, a, from, relative_h, relative_s, relative_l, relative_a } = groups;\n if (from) {\n const fromRGB = getRGBObject(from);\n const fromHSL = rgbToHsl(fromRGB.R, fromRGB.G, fromRGB.B, fromRGB.A);\n const fromHSLVars = {\n h: fromHSL.H,\n s: fromHSL.S,\n l: fromHSL.L,\n alpha: fromHSL.A\n };\n const H = new CalcParser('h', relative_h, fromHSLVars).result;\n const S = new CalcParser('s', relative_s, fromHSLVars).result;\n const L = new CalcParser('l', relative_l, fromHSLVars).result;\n const rgb = hslToRgb(minmax(H, 0, MAX_HUE), minmax(S, 0, MAX_PCENT), minmax(L, 0, MAX_PCENT));\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromHSLVars).result;\n rgb.A = minmax(A, 0, MAX_ALPHA);\n }\n this._rgb = rgb;\n }\n else {\n this._h = h_legacy ?? h;\n this._s = s_legacy ?? s;\n this._l = l_legacy ?? l;\n this._a = a_legacy ?? a;\n const rgb = hslToRgb(normalizeHue(this._h), percent(this._s), percent(this._l));\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n }\n static test(colorString) {\n return COLORREGS.HSL.test(colorString);\n }\n}\n\n;// ./src/parsers/_HWBStringParser.ts\n\n\n\n\n\nclass HWBStringParser extends HueBaseClass {\n constructor(colorString, getRGBObject) {\n super();\n const match = colorString.match(COLORREGS.HWB);\n const groups = match.groups;\n const { h, w, b, a, from, relative_h, relative_w, relative_b, relative_a } = groups;\n if (from) {\n const fromRGB = getRGBObject(from);\n const fromHWB = rgbToHwb(fromRGB.R, fromRGB.G, fromRGB.B, fromRGB.A);\n const fromHWBVars = {\n h: fromHWB.H,\n w: fromHWB.W,\n b: fromHWB.B,\n alpha: fromHWB.A\n };\n const H = new CalcParser('h', relative_h, fromHWBVars).result;\n const W = new CalcParser('w', relative_w, fromHWBVars).result;\n const B = new CalcParser('b', relative_b, fromHWBVars).result;\n const rgb = hwbToRgb(minmax(H, 0, MAX_HUE), minmax(W, 0, MAX_PCENT), minmax(B, 0, MAX_PCENT));\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromHWBVars).result;\n rgb.A = minmax(A, 0, MAX_ALPHA);\n }\n this._rgb = rgb;\n }\n else {\n this._h = h;\n this._w = w;\n this._b = b;\n this._a = a;\n const rgb = hwbToRgb(normalizeHue(this._h), percent(this._w), percent(this._b));\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n }\n static test(colorString) {\n return COLORREGS.HWB.test(colorString);\n }\n}\n\n;// ./src/parsers/_CIELabStringParser.ts\n\n\n\n\n\nclass CIELabStringParser extends AlphaBaseClass {\n constructor(colorString, getRGBObject) {\n super();\n const match = colorString.match(COLORREGS.CIELab);\n const groups = match.groups;\n const { L, a, b, A, from, relative_L, relative_a, relative_b, relative_A } = groups;\n if (from) {\n const fromRGB = getRGBObject(from);\n const fromLab = rgbToLab(fromRGB.R, fromRGB.G, fromRGB.B);\n const fromLabVars = {\n l: fromLab.L,\n a: fromLab.a,\n b: fromLab.b,\n alpha: fromRGB.A ?? 1\n };\n const L = new CalcParser('l', relative_L, fromLabVars).result;\n const a = new CalcParser('a', relative_a, fromLabVars).result;\n const b = new CalcParser('b', relative_b, fromLabVars).result;\n const rgb = labToRgb(minmax(L, 0, MAX_PCENT), minmax(a, -MAX_LAB, MAX_LAB), minmax(b, -MAX_LAB, MAX_LAB));\n if (relative_A) {\n const A = new CalcParser('alpha', relative_A, fromLabVars).result;\n rgb.A = minmax(A, 0, MAX_ALPHA);\n }\n this._rgb = rgb;\n }\n else {\n this._L = L;\n this._A = a;\n this._B = b;\n this._a = A;\n const rgb = labToRgb(percent(this._L), getBase125Number(this._A), getBase125Number(this._B));\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n }\n get hasPercentageValues() {\n return (PCENT.test(this._L) &&\n PCENT.test(this._A) &&\n PCENT.test(this._B));\n }\n static test(colorString) {\n return COLORREGS.CIELab.test(colorString);\n }\n}\n\n;// ./src/parsers/_LCHStringParser.ts\n\n\n\n\n\nclass LCHStringParser extends HueBaseClass {\n constructor(colorString, getRGBObject) {\n super();\n const match = colorString.match(COLORREGS.LCH);\n const groups = match.groups;\n const { l, c, h, a, from, relative_l, relative_c, relative_h, relative_a } = groups;\n if (from) {\n const fromRGB = getRGBObject(from);\n const fromLCH = rgbToLch(fromRGB.R, fromRGB.G, fromRGB.B);\n const fromLCHVars = {\n l: fromLCH.L,\n c: fromLCH.C,\n h: fromLCH.H,\n alpha: fromRGB.A ?? 1\n };\n const L = new CalcParser('l', relative_l, fromLCHVars).result;\n const C = new CalcParser('c', relative_c, fromLCHVars).result;\n const H = new CalcParser('h', relative_h, fromLCHVars).result;\n const rgb = lchToRgb(minmax(L, 0, MAX_PCENT), minmax(C, -MAX_LCH_C, MAX_LCH_C), normalizeHue(H));\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromLCHVars).result;\n rgb.A = minmax(A, 0, MAX_ALPHA);\n }\n this._rgb = rgb;\n }\n else {\n this._l = l;\n this._c = c;\n this._h = h;\n this._a = a;\n const rgb = lchToRgb(percent(this._l), getBase150Number(this._c), normalizeHue(this._h));\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n }\n get hasPercentageValues() {\n return (PCENT.test(this._l) &&\n PCENT.test(this._c));\n }\n static test(colorString) {\n return COLORREGS.LCH.test(colorString);\n }\n}\n\n;// ./src/parsers/_CMYKStringParser.ts\n\n\n\n\nclass CMYKStringParser extends AlphaBaseClass {\n constructor(colorString) {\n super();\n const match = colorString.match(COLORREGS.CMYK);\n const groups = match.groups;\n this._c = groups.c_legacy ?? groups.c;\n this._m = groups.m_legacy ?? groups.m;\n this._y = groups.y_legacy ?? groups.y;\n this._k = groups.k_legacy ?? groups.k;\n this._a = groups.a_legacy ?? groups.a;\n const rgb = cmykToRgb(getCMYKNumber(this._c), getCMYKNumber(this._m), getCMYKNumber(this._y), getCMYKNumber(this._k));\n if (this._a !== undefined) {\n rgb.A = normalizeAlpha(this._a);\n }\n this._rgb = rgb;\n }\n get hasPercentageValues() {\n return (PCENT.test(this._c) &&\n PCENT.test(this._m) &&\n PCENT.test(this._y) &&\n PCENT.test(this._k));\n }\n static test(colorString) {\n return COLORREGS.CMYK.test(colorString);\n }\n}\n\n;// ./src/parsers/index.ts\n\n\n\n\n\n\n\n\n;// ./src/color/extractors.ts\n\n\n\n\n\nconst getColorModelFromString = (color) => {\n let model;\n Object.keys(ColorModel).some((p) => {\n const reg = COLORREGS[p];\n if (reg.test(color)) {\n model = p;\n return true;\n }\n });\n if (!model &&\n !!~COLOR_KEYS.indexOf(color)) {\n model = ColorModel.HEX;\n }\n if (!model) {\n throw new Error(ERRORS.NOT_ACCEPTED_STRING_INPUT);\n }\n return model;\n};\nconst getColorModelFromObject = (color) => {\n let model;\n let invalid = false;\n const props = getOrderedArrayString(Object.keys(color));\n if (VALID_COLOR_OBJECTS[props]) {\n model = VALID_COLOR_OBJECTS[props];\n }\n if (model && model === ColorModel.RGB) {\n const hasInvalidHex = Object.entries(color).some((item) => {\n return !HEX.test(`${item[1]}`);\n });\n const hasInvalidRegb = Object.entries(color).some((item) => {\n return !(PCENT.test(`${item[1]}`) ||\n (!HEX.test(`${item[1]}`) &&\n !isNaN(+item[1]) &&\n +item[1] <= BASE_255));\n });\n if (hasInvalidHex && hasInvalidRegb) {\n invalid = true;\n }\n if (!hasInvalidHex) {\n model = ColorModel.HEX;\n }\n }\n if (!model || invalid) {\n throw new Error(ERRORS.NOT_ACCEPTED_OBJECT_INPUT);\n }\n return model;\n};\nconst getColorModel = (color) => typeof color === 'string'\n ? getColorModelFromString(color)\n : getColorModelFromObject(color);\nconst getRGBObjectFromString = {\n [ColorModel.HEX](color) {\n const colorStr = !~COLOR_KEYS.indexOf(color)\n ? color\n : ColorKeywords[color];\n return new HEXStringParser(colorStr).rgb;\n },\n [ColorModel.RGB](color) {\n return new RGBStringParser(color, getRGBObject).rgb;\n },\n [ColorModel.HSL](color) {\n return new HSLStringParser(color, getRGBObject).rgb;\n },\n [ColorModel.HWB](color) {\n return new HWBStringParser(color, getRGBObject).rgb;\n },\n [ColorModel.CIELab](color) {\n return new CIELabStringParser(color, getRGBObject).rgb;\n },\n [ColorModel.LCH](color) {\n return new LCHStringParser(color, getRGBObject).rgb;\n },\n [ColorModel.CMYK](color) {\n return new CMYKStringParser(color).rgb;\n }\n};\nconst getRGBObjectFromObject = {\n [ColorModel.HEX](color) {\n const object = {\n R: getBase255Number(`${color.R}`),\n G: getBase255Number(`${color.G}`),\n B: getBase255Number(`${color.B}`)\n };\n if (hasProp(color, 'A')) {\n object.A = Math.min(getBase255Number(`${color.A}`, true), 1);\n }\n return object;\n },\n [ColorModel.RGB](color) {\n return this.HEX(color);\n },\n [ColorModel.HSL](color) {\n const S = percent(`${color.S}`);\n const L = percent(`${color.L}`);\n const RGB = hslToRgb(normalizeHue(color.H), S, L);\n if (hasProp(color, 'A')) {\n RGB.A = normalizeAlpha(color.A);\n }\n return RGB;\n },\n [ColorModel.HWB](color) {\n const W = percent(`${color.W}`);\n const B = percent(`${color.B}`);\n const RGB = hwbToRgb(normalizeHue(color.H), W, B);\n if (hasProp(color, 'A')) {\n RGB.A = normalizeAlpha(color.A);\n }\n return RGB;\n },\n [ColorModel.CIELab](color) {\n const L = percent(`${color.L}`);\n const a = getBase125Number(`${color.a}`);\n const b = getBase125Number(`${color.b}`);\n const RGB = labToRgb(L, a, b);\n if (hasProp(color, 'A')) {\n RGB.A = normalizeAlpha(color.A);\n }\n return RGB;\n },\n [ColorModel.LCH](color) {\n const L = percent(`${color.L}`);\n const C = getBase150Number(`${color.C}`);\n const H = normalizeHue(`${color.H}`);\n const RGB = lchToRgb(L, C, H);\n if (hasProp(color, 'A')) {\n RGB.A = normalizeAlpha(color.A);\n }\n return RGB;\n },\n [ColorModel.CMYK](color) {\n const C = getCMYKNumber(`${color.C}`);\n const M = getCMYKNumber(`${color.M}`);\n const Y = getCMYKNumber(`${color.Y}`);\n const K = getCMYKNumber(`${color.K}`);\n const RGB = cmykToRgb(C, M, Y, K);\n if (hasProp(color, 'A')) {\n RGB.A = normalizeAlpha(color.A);\n }\n return RGB;\n }\n};\nconst getRGBObject = (color, model = getColorModel(color)) => {\n return typeof color === 'string'\n ? getRGBObjectFromString[model](color)\n : getRGBObjectFromObject[model](color);\n};\nconst getOptionsFromColorInput = (options, ...colors) => {\n const cssColors = [];\n const anglesUnits = [];\n const rgbColors = [];\n const labColors = [];\n const lchColors = [];\n const cmykColors = [];\n const alphaValues = [];\n const anglesUnitValues = Object.values(AnglesUnitEnum);\n const colorUnitValues = Object.values(ColorUnitEnum);\n const cmykFunctionValues = Object.values(CMYKFunctionEnum);\n const matchOptions = {\n legacyCSS: 0,\n spacesAfterCommas: 0,\n cmykFunction: 0\n };\n for (const color of colors) {\n if (typeof color === 'string') {\n cssColors.push(color);\n if (color.includes(',')) {\n matchOptions.legacyCSS++;\n const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS);\n if (new Set(commasWithNextCharacter).size === 1 &&\n SPACES.test(commasWithNextCharacter[0].slice(1))) {\n matchOptions.spacesAfterCommas++;\n }\n }\n if (HSLStringParser.test(color)) {\n const parser = new HSLStringParser(color, getRGBObject);\n anglesUnits.push(parser.angleUnit);\n alphaValues.push(parser.hasPercentageAlpha);\n continue;\n }\n if (HWBStringParser.test(color)) {\n const parser = new HWBStringParser(color, getRGBObject);\n anglesUnits.push(parser.angleUnit);\n alphaValues.push(parser.hasPercentageAlpha);\n continue;\n }\n if (RGBStringParser.test(color)) {\n const parser = new RGBStringParser(color, getRGBObject);\n rgbColors.push(parser.hasPercentageValues);\n alphaValues.push(parser.hasPercentageAlpha);\n continue;\n }\n if (CIELabStringParser.test(color)) {\n const parser = new CIELabStringParser(color, getRGBObject);\n labColors.push(parser.hasPercentageValues);\n alphaValues.push(parser.hasPercentageAlpha);\n continue;\n }\n if (LCHStringParser.test(color)) {\n const parser = new LCHStringParser(color, getRGBObject);\n anglesUnits.push(parser.angleUnit);\n lchColors.push(parser.hasPercentageValues);\n alphaValues.push(parser.hasPercentageAlpha);\n continue;\n }\n if (CMYKStringParser.test(color)) {\n const parser = new CMYKStringParser(color);\n cmykColors.push(parser.hasPercentageValues);\n if (color.startsWith('cmyk')) {\n matchOptions.cmykFunction++;\n }\n alphaValues.push(parser.hasPercentageAlpha);\n }\n }\n }\n return {\n decimals: typeof options.decimals === TypeOf.NUMBER\n ? options.decimals\n : DEFAULT_OPTIONS.decimals,\n legacyCSS: typeof options.legacyCSS === TypeOf.BOOLEAN\n ? options.legacyCSS\n : Boolean(cssColors.length &&\n matchOptions.legacyCSS === cssColors.length) || DEFAULT_OPTIONS.legacyCSS,\n spacesAfterCommas: typeof options.spacesAfterCommas === TypeOf.BOOLEAN\n ? options.spacesAfterCommas\n : Boolean(cssColors.length &&\n matchOptions.spacesAfterCommas === cssColors.length) || DEFAULT_OPTIONS.spacesAfterCommas,\n anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit)\n ? options.anglesUnit\n : (new Set(anglesUnits).size === 1\n ? anglesUnits[0]\n : DEFAULT_OPTIONS.anglesUnit),\n rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit)\n ? options.rgbUnit\n : (new Set(rgbColors).size === 1 && rgbColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.rgbUnit),\n labUnit: options.labUnit && colorUnitValues.includes(options.labUnit)\n ? options.labUnit\n : (new Set(labColors).size === 1 && labColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.labUnit),\n lchUnit: options.lchUnit && colorUnitValues.includes(options.lchUnit)\n ? options.lchUnit\n : (new Set(lchColors).size === 1 && lchColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.lchUnit),\n cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit)\n ? options.cmykUnit\n : (new Set(cmykColors).size === 1 && !cmykColors[0]\n ? ColorUnitEnum.NONE\n : DEFAULT_OPTIONS.cmykUnit),\n alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit)\n ? options.alphaUnit\n : (new Set(alphaValues).size === 1 && alphaValues[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.alphaUnit),\n cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction)\n ? options.cmykFunction\n : (cmykColors.length && cmykColors.length === matchOptions.cmykFunction\n ? CMYKFunctionEnum.CMYK\n : DEFAULT_OPTIONS.cmykFunction)\n };\n};\n\n;// ./src/color/rounders.ts\n\nconst roundHSLObject = (color, decimals) => {\n return {\n H: round(color.H, decimals),\n S: round(color.S, decimals),\n L: round(color.L, decimals)\n };\n};\nconst roundHWBObject = (color, decimals) => {\n return {\n H: round(color.H, decimals),\n W: round(color.W, decimals),\n B: round(color.B, decimals)\n };\n};\nconst roundCIELabObject = (color, decimals) => {\n return {\n L: round(color.L, decimals),\n a: round(color.a, decimals),\n b: round(color.b, decimals)\n };\n};\nconst roundLCHObject = (color, decimals) => {\n return {\n L: round(color.L, decimals),\n C: round(color.C, decimals),\n H: round(color.H, decimals)\n };\n};\nconst roundCMYKObject = (color, decimals) => {\n return {\n C: round(color.C, decimals),\n M: round(color.M, decimals),\n Y: round(color.Y, decimals),\n K: round(color.K, decimals)\n };\n};\n\n;// ./src/color/css.ts\n\n\n\nconst getComma = (withSpace) => withSpace\n ? ', '\n : ',';\nconst prepareColorForCss = (color, transformer) => {\n const props = getOrderedArrayString(Object.keys(color));\n const model = VALID_COLOR_OBJECTS[props];\n const keys = COLOR_PROPS[model];\n return keys.reduce((result, key, index) => {\n const value = color[key];\n if (typeof value !== 'undefined') {\n result.push(transformer(value, index));\n }\n return result;\n }, []);\n};\nconst getResultFromTemplate = (template, vars) => {\n return template.replace(TEMPLATE_VAR, (__match, indexStr) => {\n const index = +indexStr - 1;\n return `${vars[index]}`;\n });\n};\nconst getAlpha = (value, options, ignoreLegacy = false) => {\n const { alphaUnit, legacyCSS, decimals } = options;\n if (alphaUnit === ColorUnitEnum.PERCENT &&\n (!legacyCSS ||\n ignoreLegacy)) {\n return `${round(value * 100, decimals)}%`;\n }\n return round(value, decimals);\n};\nconst buildHueTransformer = (options) => {\n const { anglesUnit, decimals } = options;\n return (value, index) => {\n if (index === 0 &&\n anglesUnit !== AnglesUnitEnum.NONE) {\n const translated = round(translateDegrees(value, anglesUnit), decimals);\n return `${translated}${anglesUnit}`;\n }\n return index === 3\n ? getAlpha(value, options)\n : round(value, decimals);\n };\n};\nconst CSS = {\n [ColorModel.HEX]: (color) => {\n const transformer = (value) => toHEX(round(value));\n const values = prepareColorForCss(color, transformer);\n const template = values.length === 4\n ? '#{1}{2}{3}{4}'\n : '#{1}{2}{3}';\n return getResultFromTemplate(template, values);\n },\n [ColorModel.RGB]: (color, options) => {\n const { decimals, legacyCSS, spacesAfterCommas, rgbUnit } = options;\n const comma = getComma(spacesAfterCommas);\n const transformer = (value, index) => {\n return rgbUnit === ColorUnitEnum.PERCENT && index < 3\n ? `${from255NumberToPercent(value, decimals)}%`\n : (index === 3\n ? getAlpha(value, options)\n : round(value, decimals));\n };\n const values = prepareColorForCss(color, transformer);\n const template = legacyCSS\n ? (values.length === 4\n ? `rgba({1}${comma}{2}${comma}{3}${comma}{4})`\n : `rgb({1}${comma}{2}${comma}{3})`)\n : (values.length === 4\n ? `rgb({1} {2} {3} / {4})`\n : `rgb({1} {2} {3})`);\n return getResultFromTemplate(template, values);\n },\n [ColorModel.HSL]: (color, options) => {\n const { legacyCSS, spacesAfterCommas } = options;\n const comma = getComma(spacesAfterCommas);\n const transformer = buildHueTransformer(options);\n const values = prepareColorForCss(color, transformer);\n const template = legacyCSS\n ? (values.length === 4\n ? `hsla({1}${comma}{2}%${comma}{3}%${comma}{4})`\n : `hsl({1}${comma}{2}%${comma}{3}%)`)\n : (values.length === 4\n ? `hsl({1} {2}% {3}% / {4})`\n : `hsl({1} {2}% {3}%)`);\n return getResultFromTemplate(template, values);\n },\n [ColorModel.HWB]: (color, options) => {\n const transformer = buildHueTransformer(options);\n const values = prepareColorForCss(color, transformer);\n const template = values.length === 4\n ? `hwb({1} {2}% {3}% / {4})`\n : `hwb({1} {2}% {3}%)`;\n return getResultFromTemplate(template, values);\n },\n [ColorModel.CIELab]: (color, options) => {\n const { decimals, labUnit } = options;\n const transformer = (value, index) => {\n if (index === 0) {\n const L = round(percent(value), decimals);\n return labUnit === ColorUnitEnum.PERCENT\n ? `${L}%`\n : `${L}`;\n }\n if (index < 3) {\n return labUnit === ColorUnitEnum.PERCENT\n ? `${from125NumberToPercent(value, decimals)}%`\n : round(value, decimals);\n }\n return getAlpha(value, options, true);\n };\n const values = prepareColorForCss(color, transformer);\n const template = values.length === 4\n ? `lab({1} {2} {3} / {4})`\n : `lab({1} {2} {3})`;\n return getResultFromTemplate(template, values);\n },\n [ColorModel.LCH]: (color, options) => {\n const { decimals, lchUnit, anglesUnit } = options;\n const transformer = (value, index) => {\n if (index === 0) {\n const L = round(percent(value), decimals);\n return lchUnit === ColorUnitEnum.PERCENT\n ? `${L}%`\n : `${L}`;\n }\n if (index === 1) {\n return lchUnit === ColorUnitEnum.PERCENT\n ? `${from150NumberToPercent(value, decimals)}%`\n : round(value, decimals);\n }\n if (index === 2) {\n if (anglesUnit !== AnglesUnitEnum.NONE) {\n const translated = round(translateDegrees(value, anglesUnit), decimals);\n return `${translated}${anglesUnit}`;\n }\n return round(value, decimals);\n }\n return getAlpha(value, options, true);\n };\n const values = prepareColorForCss(color, transformer);\n const template = values.length === 4\n ? `lch({1} {2} {3} / {4})`\n : `lch({1} {2} {3})`;\n return getResultFromTemplate(template, values);\n },\n [ColorModel.CMYK]: (color, options) => {\n const { decimals, legacyCSS, spacesAfterCommas, cmykUnit, cmykFunction } = options;\n const comma = getComma(spacesAfterCommas);\n const transformer = (value, index) => {\n if (cmykUnit === ColorUnitEnum.PERCENT &&\n index < 4) {\n return `${round(value, decimals)}%`;\n }\n return index === 4\n ? getAlpha(value, options)\n : round(value / 100, decimals);\n };\n const values = prepareColorForCss(color, transformer);\n const template = legacyCSS\n ? (values.length === 5\n ? `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4}${comma}{5})`\n : `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4})`)\n : (values.length === 5\n ? `${cmykFunction}({1} {2} {3} {4} / {5})`\n : `${cmykFunction}({1} {2} {3} {4})`);\n return getResultFromTemplate(template, values);\n }\n};\n\n;// ./src/color/utils.ts\n\n\n\n\n\n\nconst harmony = (color, angles, mode) => angles.reduce((arr, num) => ([\n ...arr,\n {\n ...color,\n H: mode === Mix.ADDITIVE\n ? normalizeHue(color.H + num)\n : normalizeHue(hueRyb(hueRyb(color.H, false) + num, true))\n }\n]), [{ ...color }]);\nconst analogous = (color, mode) => harmony(color, [30, -30], mode);\nconst complementary = (color, mode) => harmony(color, [180], mode);\nconst splitComplementary = (color, mode) => harmony(color, [150, -150], mode);\nconst triadic = (color, mode) => harmony(color, [120, -120], mode);\nconst tetradic = (color, mode) => harmony(color, [60, -120, 180], mode);\nconst square = (color, mode) => harmony(color, [90, -90, 180], mode);\nconst translateColor = {\n [ColorModel.HEX](color) {\n return {\n R: getHEX(color.R),\n G: getHEX(color.G),\n B: getHEX(color.B)\n };\n },\n HEXA(color) {\n const RGB = translateColor.HEX(color);\n RGB.A = hasProp(color, 'A')\n ? getHEX(color.A * BASE_255)\n : '0xFF';\n return RGB;\n },\n [ColorModel.RGB](color, decimals) {\n const RGB = roundRGBObject(color, decimals);\n if (hasProp(RGB, 'A')) {\n delete RGB.A;\n }\n return RGB;\n },\n RGBA(color, decimals) {\n const RGB = translateColor.RGB(color, decimals);\n RGB.A = hasProp(color, 'A')\n ? round(color.A)\n : 1;\n return RGB;\n },\n [ColorModel.HSL](color, decimals) {\n const HSL = rgbToHsl(color.R, color.G, color.B);\n delete HSL.A;\n return roundHSLObject(HSL, decimals);\n },\n HSLA(color, decimals) {\n const HSL = translateColor.HSL(color, decimals);\n HSL.A = hasProp(color, 'A')\n ? round(color.A, decimals)\n : 1;\n return HSL;\n },\n [ColorModel.HWB](color, decimals) {\n const HWB = rgbToHwb(color.R, color.G, color.B);\n delete HWB.A;\n return roundHWBObject(HWB, decimals);\n },\n HWBA(color, decimals) {\n const HWB = translateColor.HWB(color, decimals);\n HWB.A = hasProp(color, 'A')\n ? round(color.A, decimals)\n : 1;\n return HWB;\n },\n [ColorModel.CIELab](color, decimals) {\n const Lab = rgbToLab(color.R, color.G, color.B);\n return roundCIELabObject(Lab, decimals);\n },\n CIELabA(color, decimals) {\n const Lab = translateColor.CIELab(color, decimals);\n Lab.A = hasProp(color, 'A')\n ? round(color.A, decimals)\n : 1;\n return Lab;\n },\n [ColorModel.LCH](color, decimals) {\n const lch = rgbToLch(color.R, color.G, color.B);\n return roundLCHObject(lch, decimals);\n },\n LCHA(color, decimals) {\n const lch = translateColor.LCH(color, decimals);\n lch.A = hasProp(color, 'A')\n ? round(color.A, decimals)\n : 1;\n return lch;\n },\n [ColorModel.CMYK](color, decimals) {\n return roundCMYKObject(rgbToCmyk(color.R, color.G, color.B), decimals);\n },\n CMYKA(color, decimals) {\n const CMYK = translateColor.CMYK(color, decimals);\n CMYK.A = hasProp(color, 'A')\n ? round(color.A, decimals)\n : 1;\n return CMYK;\n }\n};\nconst blend = (from, to, steps) => {\n const div = steps - 1;\n const diffR = (to.R - from.R) / div;\n const diffG = (to.G - from.G) / div;\n const diffB = (to.B - from.B) / div;\n const fromA = normalizeAlpha(from.A);\n const toA = normalizeAlpha(to.A);\n const diffA = (toA - fromA) / div;\n return Array(steps).fill(null).map((__n, i) => {\n if (i === 0) {\n return from;\n }\n if (i === div) {\n return to;\n }\n return {\n R: round(from.R + diffR * i),\n G: round(from.G + diffG * i),\n B: round(from.B + diffB * i),\n A: round(fromA + diffA * i)\n };\n });\n};\nconst getColorMixture = (color, steps, shades, options) => {\n const model = getColorModel(color);\n const isCSS = typeof color === 'string';\n const RGB = getRGBObject(color, model);\n const hasAlpha = ((typeof color === 'string' && hasProp(RGB, 'A')) ||\n (typeof color !== 'string' &&\n hasProp(color, 'A')));\n const HSL = rgbToHsl(RGB.R, RGB.G, RGB.B, RGB.A);\n if (!hasAlpha)\n delete HSL.A;\n const increment = shades\n ? HSL.L / (steps + 1)\n : (100 - HSL.L) / (steps + 1);\n const hslMap = Array(steps).fill(null).map((__n, i) => ({\n ...HSL,\n L: HSL.L + increment * (i + 1) * (1 - +shades * 2)\n }));\n switch (model) {\n case ColorModel.HEX:\n default:\n return hslMap.map((HSLColor) => {\n const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L);\n if (hasAlpha)\n RGBColor.A = HSLColor.A;\n return isCSS\n ? hasAlpha\n ? CSS.HEX({\n ...RGBColor,\n A: round(RGBColor.A * BASE_255)\n })\n : CSS.HEX(RGBColor)\n : hasAlpha\n ? translateColor.HEXA(RGBColor)\n : translateColor.HEX(RGBColor);\n });\n case ColorModel.RGB:\n return hslMap.map((HSLColor) => {\n const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L);\n if (hasAlpha)\n RGBColor.A = HSLColor.A;\n return isCSS\n ? CSS.RGB(RGBColor, options)\n : hasAlpha\n ? translateColor.RGBA(RGBColor, options.decimals)\n : translateColor.RGB(RGBColor, options.decimals);\n // removed by dead control flow\n\n });\n case ColorModel.HSL:\n return hslMap.map((HSLColor) => {\n return isCSS\n ? CSS.HSL(HSLColor, options)\n : hasAlpha\n ? translateColor.HSLA({\n ...hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L),\n A: HSLColor.A\n }, options.decimals)\n : translateColor.HSL(hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L), options.decimals);\n });\n case ColorModel.HWB:\n return hslMap.map((HSLColor) => {\n const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L);\n if (hasAlpha)\n RGBColor.A = HSLColor.A;\n const hwb = hasAlpha\n ? translateColor.HWBA(RGBColor, options.decimals)\n : translateColor.HWB(RGBColor, options.decimals);\n return isCSS\n ? CSS.HWB(hwb, options)\n : hwb;\n });\n case ColorModel.CIELab:\n return hslMap.map((HSLColor) => {\n const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L);\n if (hasAlpha)\n RGBColor.A = HSLColor.A;\n const lab = hasAlpha\n ? translateColor.CIELabA(RGBColor, options.decimals)\n : translateColor.CIELab(RGBColor, options.decimals);\n return isCSS\n ? CSS.CIELab(lab, options)\n : lab;\n });\n case ColorModel.LCH:\n return hslMap.map((HSLColor) => {\n const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L);\n const LCHColor = rgbToLch(RGBColor.R, RGBColor.G, RGBColor.B);\n if (hasAlpha)\n LCHColor.A = HSLColor.A;\n return isCSS\n ? CSS.LCH(LCHColor, options)\n : hasAlpha\n ? translateColor.LCHA({\n ...RGBColor,\n A: HSLColor.A\n }, options.decimals)\n : translateColor.LCH(RGBColor, options.decimals);\n });\n }\n};\nconst colorHarmony = {\n buildHarmony(color, harmonyFunction, mode, options) {\n const model = getColorModel(color);\n const RGB = getRGBObject(color, model);\n const HSL = rgbToHsl(RGB.R, RGB.G, RGB.B, RGB.A);\n const hasAlpha = ((typeof color === 'string' && hasProp(RGB, 'A')) ||\n (typeof color !== 'string' &&\n hasProp(color, 'A')));\n const isCSS = typeof color === 'string';\n switch (model) {\n case ColorModel.HEX:\n default:\n return hasAlpha\n ? this.HEXA(roundHSLObject(HSL, 0), harmonyFunction, mode, isCSS)\n : this.HEX(roundHSLObject(HSL, 0), harmonyFunction, mode, isCSS);\n case ColorModel.HSL:\n return hasAlpha\n ? this.HSLA(HSL, harmonyFunction, mode, isCSS, options)\n : this.HSL(HSL, harmonyFunction, mode, isCSS, options);\n case ColorModel.HWB:\n return hasAlpha\n ? this.HWBA(HSL, harmonyFunction, mode, isCSS, options)\n : this.HWB(HSL, harmonyFunction, mode, isCSS, options);\n case ColorModel.RGB:\n return hasAlpha\n ? this.RGBA(HSL, harmonyFunction, mode, isCSS, options)\n : this.RGB(HSL, harmonyFunction, mode, isCSS, options);\n case ColorModel.CIELab:\n return hasAlpha\n ? this.CIELabA(HSL, harmonyFunction, mode, isCSS, options)\n : this.CIELab(HSL, harmonyFunction, mode, isCSS, options);\n case ColorModel.LCH:\n return hasAlpha\n ? this.LCHA(HSL, harmonyFunction, mode, isCSS, options)\n : this.LCH(HSL, harmonyFunction, mode, isCSS, options);\n }\n },\n [ColorModel.HEX](color, harmonyFunction, mode, css) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.HEX(hslToRgb(c.H, c.S, c.L))\n : translateColor.HEX(hslToRgb(c.H, c.S, c.L))));\n },\n HEXA(color, harmonyFunction, mode, css) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.HEX({\n ...hslToRgb(c.H, c.S, c.L),\n A: normalizeAlpha(c.A) * BASE_255\n })\n : translateColor.HEXA({\n ...hslToRgb(c.H, c.S, c.L),\n A: normalizeAlpha(c.A)\n })));\n },\n [ColorModel.RGB](color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.RGB(hslToRgb(c.H, c.S, c.L), options)\n : translateColor.RGB(hslToRgb(c.H, c.S, c.L), options.decimals)));\n },\n RGBA(color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.RGB({\n ...hslToRgb(c.H, c.S, c.L),\n A: normalizeAlpha(c.A)\n }, options)\n : translateColor.RGBA({\n ...hslToRgb(c.H, c.S, c.L),\n A: normalizeAlpha(c.A)\n }, options.decimals)));\n },\n [ColorModel.HSL](color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.HSL({\n H: c.H,\n S: c.S,\n L: c.L\n }, options)\n : translateColor.HSL(hslToRgb(c.H, c.S, c.L), options.decimals)));\n },\n HSLA(color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => (css\n ? CSS.HSL({\n ...c,\n A: normalizeAlpha(c.A)\n }, options)\n : translateColor.HSLA({\n ...hslToRgb(c.H, c.S, c.L),\n A: normalizeAlpha(c.A)\n }, options.decimals)));\n },\n [ColorModel.HWB](color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const rgb = hslToRgb(c.H, c.S, c.L);\n const hwb = rgbToHwb(rgb.R, rgb.G, rgb.B);\n return css\n ? CSS.HWB({\n H: hwb.H,\n W: hwb.W,\n B: hwb.B\n }, options)\n : translateColor.HWB(rgb, options.decimals);\n });\n },\n HWBA(color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const rgb = hslToRgb(c.H, c.S, c.L);\n const hwb = rgbToHwb(rgb.R, rgb.G, rgb.B);\n return css\n ? CSS.HWB({\n ...hwb,\n A: normalizeAlpha(c.A)\n }, options)\n : translateColor.HWBA({\n ...rgb,\n A: normalizeAlpha(c.A)\n }, options.decimals);\n });\n },\n [ColorModel.CIELab](color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const RGB = hslToRgb(c.H, c.S, c.L);\n return (css\n ? CSS.CIELab(rgbToLab(RGB.R, RGB.G, RGB.B), options)\n : translateColor.CIELab(RGB, options.decimals));\n });\n },\n CIELabA(color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const RGB = hslToRgb(c.H, c.S, c.L);\n return (css\n ? CSS.CIELab({\n ...rgbToLab(RGB.R, RGB.G, RGB.B),\n A: normalizeAlpha(c.A)\n }, options)\n : translateColor.CIELabA({\n ...RGB,\n A: normalizeAlpha(c.A)\n }, options.decimals));\n });\n },\n [ColorModel.LCH](color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const RGB = hslToRgb(c.H, c.S, c.L);\n return (css\n ? CSS.LCH(rgbToLch(RGB.R, RGB.G, RGB.B), options)\n : translateColor.LCH(RGB, options.decimals));\n });\n },\n LCHA(color, harmonyFunction, mode, css, options) {\n const array = harmonyFunction(color, mode);\n return array.map((c) => {\n const RGB = hslToRgb(c.H, c.S, c.L);\n return (css\n ? CSS.LCH({\n ...rgbToLch(RGB.R, RGB.G, RGB.B),\n A: normalizeAlpha(c.A)\n }, options)\n : translateColor.LCHA({\n ...RGB,\n A: normalizeAlpha(c.A)\n }, options.decimals));\n });\n }\n};\nconst colorMixer = {\n mix(colors, mode) {\n const rgbMap = colors.map((color) => {\n const model = getColorModel(color);\n return getRGBObject(color, model);\n });\n const rybMap = mode === Mix.SUBTRACTIVE\n ? rgbMap.map((color) => {\n const RYB = rgbToRyb(color.R, color.G, color.B);\n if (hasProp(color, 'A')) {\n RYB.A = color.A;\n }\n return RYB;\n })\n : null;\n function createMix(items) {\n const initial = mode === Mix.ADDITIVE\n ? { R: 0, G: 0, B: 0, A: 0 }\n : { R: 0, Y: 0, B: 0, A: 0 };\n return items.reduce((mix, color) => {\n const colorA = hasProp(color, 'A') ? color.A : 1;\n const common = {\n R: Math.min(mix.R + color.R * colorA, BASE_255),\n B: Math.min(mix.B + color.B * colorA, BASE_255),\n A: 1 - (1 - colorA) * (1 - mix.A)\n };\n const mixGY = 'G' in mix\n ? mix.G\n : mix.Y;\n const colorGY = 'G' in color\n ? color.G\n : color.Y;\n return {\n ...common,\n ...(mode === Mix.ADDITIVE\n ? { G: Math.min(mixGY + colorGY * colorA, BASE_255) }\n : { Y: Math.min(mixGY + colorGY * colorA, BASE_255) })\n };\n }, initial);\n }\n let mix;\n if (mode === Mix.ADDITIVE) {\n mix = createMix(rgbMap);\n }\n else {\n const RYB = createMix(rybMap);\n mix = rybToRgb(RYB.R, RYB.Y, RYB.B);\n mix.A = RYB.A;\n }\n return {\n R: round(mix.R),\n G: round(mix.G),\n B: round(mix.B),\n A: minmax(mix.A, 0, 1)\n };\n },\n [ColorModel.HEX](colors, mode, css) {\n const mix = this.mix(colors, mode);\n delete mix.A;\n return (css\n ? CSS.HEX(mix)\n : translateColor.HEX(mix));\n },\n HEXA(colors, mode, css) {\n const mix = this.mix(colors, mode);\n mix.A = css\n ? normalizeAlpha(mix.A) * BASE_255\n : normalizeAlpha(mix.A);\n return (css\n ? CSS.HEX(mix)\n : translateColor.HEXA(mix));\n },\n [ColorModel.RGB](colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n delete mix.A;\n return (css\n ? CSS.RGB(mix, options)\n : translateColor.RGB(mix, options.decimals));\n },\n RGBA(colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n return (css\n ? CSS.RGB(mix, options)\n : translateColor.RGBA(mix, options.decimals));\n },\n [ColorModel.HSL](colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const HSL = rgbToHsl(mix.R, mix.G, mix.B);\n delete mix.A;\n delete HSL.A;\n return (css\n ? CSS.HSL(HSL, options)\n : translateColor.HSL(mix, options.decimals));\n },\n HSLA(colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const HSL = rgbToHsl(mix.R, mix.G, mix.B, mix.A);\n return (css\n ? CSS.HSL(HSL, options)\n : translateColor.HSLA(mix, options.decimals));\n },\n [ColorModel.HWB](colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const HWB = rgbToHwb(mix.R, mix.G, mix.B);\n delete mix.A;\n delete HWB.A;\n return (css\n ? CSS.HWB(HWB, options)\n : translateColor.HWB(mix, options.decimals));\n },\n HWBA(colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const HWB = rgbToHwb(mix.R, mix.G, mix.B, mix.A);\n return (css\n ? CSS.HWB(HWB, options)\n : translateColor.HWBA(mix, options.decimals));\n },\n [ColorModel.CIELab](colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const Lab = rgbToLab(mix.R, mix.G, mix.B);\n delete mix.A;\n return (css\n ? CSS.CIELab(Lab, options)\n : translateColor.CIELab(mix, options.decimals));\n },\n CIELabA(colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const Lab = rgbToLab(mix.R, mix.G, mix.B);\n Lab.A = mix.A;\n return (css\n ? CSS.CIELab(Lab, options)\n : translateColor.CIELabA(mix, options.decimals));\n },\n [ColorModel.LCH](colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const lch = rgbToLch(mix.R, mix.G, mix.B);\n delete mix.A;\n return (css\n ? CSS.LCH(lch, options)\n : translateColor.LCH(mix, options.decimals));\n },\n LCHA(colors, mode, css, options) {\n const mix = this.mix(colors, mode);\n const lch = rgbToLch(mix.R, mix.G, mix.B);\n lch.A = mix.A;\n return (css\n ? CSS.LCH(lch, options)\n : translateColor.LCHA(mix, options.decimals));\n }\n};\nconst roundRGBObject = (color, decimals) => {\n const R = round(color.R, decimals);\n const G = round(color.G, decimals);\n const B = round(color.B, decimals);\n return {\n R,\n G,\n B,\n ...(hasProp(color, 'A')\n ? {\n A: round(color.A, decimals)\n }\n : {})\n };\n};\n\n;// ./src/returns/index.ts\n\n\n\nconst getColorReturn = (color, model, decimals, translateFunction) => {\n const rgbObject = getRGBObject(color, model);\n return translateFunction(rgbObject, decimals);\n};\nconst getBlendReturn = (from, to, steps, decimals, translateFunction) => {\n if (steps < 1)\n steps = DEFAULT_BLEND_STEPS;\n const fromRGBObject = getRGBObject(from);\n const toRGBObject = getRGBObject(to);\n const blendArray = blend(fromRGBObject, toRGBObject, steps);\n return blendArray.map((color) => {\n return translateFunction(color, decimals);\n });\n};\nfunction getBlendReturnWithParameters(params) {\n const { from, to, thirdParameter, fourthParameter, translateFunction, cssFunction } = params;\n const result = typeof thirdParameter === 'number'\n ? getBlendReturn(from, to, thirdParameter, fourthParameter?.decimals, translateFunction)\n : getBlendReturn(from, to, DEFAULT_BLEND_STEPS, thirdParameter?.decimals, translateFunction);\n if (cssFunction) {\n return result.map((color) => cssFunction(color, getOptionsFromColorInput((typeof thirdParameter === 'number'\n ? fourthParameter\n : thirdParameter) ?? {}, from, to)));\n }\n return result;\n}\nfunction getMixReturn(params) {\n const { colors, secondParameter, thirdParameter, colorMixerFunction, css } = params;\n const options = getOptionsFromColorInput((typeof secondParameter === 'string'\n ? thirdParameter\n : secondParameter) ?? {}, ...colors);\n if (typeof secondParameter === 'string') {\n return colorMixerFunction(colors, secondParameter, css, options);\n }\n return colorMixerFunction(colors, Mix.ADDITIVE, css, options);\n}\nconst getHarmonyReturn = (harmony, color, mode, options) => {\n return ({\n [Harmony.ANALOGOUS]: colorHarmony.buildHarmony(color, analogous, mode, options),\n [Harmony.COMPLEMENTARY]: colorHarmony.buildHarmony(color, complementary, mode, options),\n [Harmony.SPLIT_COMPLEMENTARY]: colorHarmony.buildHarmony(color, splitComplementary, mode, options),\n [Harmony.TRIADIC]: colorHarmony.buildHarmony(color, triadic, mode, options),\n [Harmony.TETRADIC]: colorHarmony.buildHarmony(color, tetradic, mode, options),\n [Harmony.SQUARE]: colorHarmony.buildHarmony(color, square, mode, options)\n })[harmony];\n};\n\n;// ./src/index.ts\n\n\n\n\n\n\n\nconst bindedMixers = Object.fromEntries(Object.entries(colorMixer).map((entry) => {\n const [key, fn] = entry;\n return [key, fn.bind(colorMixer)];\n}));\nclass ColorTranslator {\n constructor(color, options = {}) {\n this._options = getOptionsFromColorInput(options, color);\n this.rgb = getRGBObject(color);\n this.update('rgb');\n }\n update(...exclude) {\n if (!exclude.includes('rgb')) {\n this.updateRGB();\n }\n if (!exclude.includes('hsl')) {\n this.updateHSL();\n }\n if (!exclude.includes('hwb')) {\n this.updateHWB();\n }\n if (!exclude.includes('lab')) {\n this.updateLAB();\n }\n if (!exclude.includes('lch')) {\n this.updateLCH();\n }\n if (!exclude.includes('cmyk')) {\n this.updateCMYK();\n }\n }\n updateRGB() {\n this.rgb = {\n ...hslToRgb(this.hsl.H, this.hsl.S, this.hsl.L),\n A: this.hsl.A\n };\n }\n updateHSL() {\n this.hsl = rgbToHsl(this.rgb.R, this.rgb.G, this.rgb.B, this.rgb.A);\n }\n updateHWB() {\n this.hwb = rgbToHwb(this.rgb.R, this.rgb.G, this.rgb.B, this.rgb.A);\n }\n updateLAB() {\n this.lab = {\n ...rgbToLab(this.rgb.R, this.rgb.G, this.rgb.B),\n A: this.rgb.A\n };\n }\n updateLCH() {\n this.lch = {\n ...rgbToLch(this.rgb.R, this.rgb.G, this.rgb.B),\n A: this.rgb.A\n };\n }\n updateCMYK() {\n this.cmyk = rgbToCmyk(this.rgb.R, this.rgb.G, this.rgb.B);\n }\n updateRGBFromHWB() {\n this.rgb = {\n ...hwbToRgb(this.hwb.H, this.hwb.W, this.hwb.B),\n A: this.rgb.A\n };\n }\n updateRGBFromLCH() {\n this.rgb = {\n ...lchToRgb(this.lch.L, this.lch.C, this.lch.H),\n A: this.rgb.A\n };\n }\n updateRGBFromCMYK() {\n this.rgb = {\n ...cmykToRgb(this.cmyk.C, this.cmyk.M, this.cmyk.Y, this.cmyk.K),\n A: this.rgb.A\n };\n }\n updateRGBFromLAB() {\n this.rgb = {\n ...labToRgb(this.lab.L, this.lab.a, this.lab.b),\n A: this.rgb.A\n };\n }\n updateLCHFromLAB() {\n this.lch = {\n ...labToLch(this.lab.L, this.lab.a, this.lab.b),\n A: this.lab.A\n };\n }\n updateLABromLCH() {\n this.lab = {\n ...lchToLab(this.lch.L, this.lch.C, this.lch.H),\n A: this.lch.A\n };\n }\n setOptions(options = {}) {\n this._options = {\n ...this._options,\n ...options\n };\n return this;\n }\n setR(R) {\n this.rgb.R = minmax(R, 0, BASE_255);\n this.update('rgb');\n return;\n }\n setG(G) {\n this.rgb.G = minmax(G, 0, BASE_255);\n this.update('rgb');\n return this;\n }\n setB(B) {\n this.rgb.B = minmax(B, 0, BASE_255);\n this.update('rgb');\n return this;\n }\n setH(H) {\n this.hsl.H = normalizeHue(H);\n this.update('hsl');\n return this;\n }\n setS(S) {\n this.hsl.S = minmax(S, 0, MAX_PCENT);\n this.update('hsl');\n return this;\n }\n setL(L) {\n this.hsl.L = minmax(L, 0, MAX_PCENT);\n this.update('hsl');\n return this;\n }\n setWhiteness(W) {\n this.hwb.W = minmax(W, 0, MAX_PCENT);\n this.updateRGBFromHWB();\n this.update('rgb', 'hwb');\n return this;\n }\n setBlackness(B) {\n this.hwb.B = minmax(B, 0, MAX_PCENT);\n this.updateRGBFromHWB();\n this.update('rgb', 'hwb');\n return this;\n }\n setCIEL(L) {\n this.lab.L = minmax(L, 0, MAX_PCENT);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setCIEa(a) {\n this.lab.a = minmax(a, -MAX_LAB, MAX_LAB);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setCIEb(b) {\n this.lab.b = minmax(b, -MAX_LAB, MAX_LAB);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHL(l) {\n this.lch.L = minmax(l, 0, MAX_PCENT);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHC(c) {\n this.lch.C = minmax(c, 0, MAX_LCH_C);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHH(h) {\n this.lch.H = normalizeHue(h);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setA(A) {\n const alpha = minmax(A, 0, MAX_ALPHA);\n this.rgb.A = alpha;\n this.hsl.A = alpha;\n this.hwb.A = alpha;\n this.lab.A = alpha;\n this.lch.A = alpha;\n this.cmyk.A = alpha;\n return this;\n }\n setC(C) {\n this.cmyk.C = minmax(C, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setM(M) {\n this.cmyk.M = minmax(M, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setY(Y) {\n this.cmyk.Y = minmax(Y, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setK(K) {\n this.cmyk.K = minmax(K, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n get options() {\n return this._options;\n }\n get R() {\n return round(this.rgb.R, this.options.decimals);\n }\n get G() {\n return round(this.rgb.G, this.options.decimals);\n }\n get B() {\n return round(this.rgb.B, this.options.decimals);\n }\n get H() {\n return round(this.hsl.H, this.options.decimals);\n }\n get S() {\n return round(this.hsl.S, this.options.decimals);\n }\n get L() {\n return round(this.hsl.L, this.options.decimals);\n }\n get Whiteness() {\n return round(this.hwb.W, this.options.decimals);\n }\n get Blackness() {\n return round(this.hwb.B, this.options.decimals);\n }\n get CIEL() {\n return round(this.lab.L, this.options.decimals);\n }\n get CIEa() {\n return round(this.lab.a, this.options.decimals);\n }\n get CIEb() {\n return round(this.lab.b, this.options.decimals);\n }\n get LCHL() {\n return round(this.lch.L, this.options.decimals);\n }\n get LCHC() {\n return round(this.lch.C, this.options.decimals);\n }\n get LCHH() {\n return round(this.lch.H, this.options.decimals);\n }\n get A() {\n return round(this.hsl.A, this.options.decimals);\n }\n get C() {\n return round(this.cmyk.C, this.options.decimals);\n }\n get M() {\n return round(this.cmyk.M, this.options.decimals);\n }\n get Y() {\n return round(this.cmyk.Y, this.options.decimals);\n }\n get K() {\n return round(this.cmyk.K, this.options.decimals);\n }\n get HEXObject() {\n return translateColor.HEX(this.rgb);\n }\n get HEXAObject() {\n return translateColor.HEXA(this.rgb);\n }\n get RGBObject() {\n return {\n R: this.R,\n G: this.G,\n B: this.B\n };\n }\n get RGBAObject() {\n return {\n ...this.RGBObject,\n A: this.A\n };\n }\n get HSLObject() {\n return {\n H: this.H,\n S: this.S,\n L: this.L\n };\n }\n get HSLAObject() {\n return {\n ...this.HSLObject,\n A: this.A\n };\n }\n get HWBObject() {\n return {\n H: this.H,\n W: this.Whiteness,\n B: this.Blackness\n };\n }\n get HWBAObject() {\n return {\n ...this.HWBObject,\n A: this.A\n };\n }\n get CIELabObject() {\n return {\n L: this.CIEL,\n a: this.CIEa,\n b: this.CIEb\n };\n }\n get CIELabAObject() {\n return {\n ...this.CIELabObject,\n A: this.A\n };\n }\n get LCHObject() {\n return {\n L: this.LCHL,\n C: this.LCHC,\n H: this.LCHH\n };\n }\n get LCHAObject() {\n return {\n ...this.LCHObject,\n A: this.A\n };\n }\n get CMYKObject() {\n return {\n C: this.C,\n M: this.M,\n Y: this.Y,\n K: this.K\n };\n }\n get CMYKAObject() {\n return {\n ...this.CMYKObject,\n A: this.A\n };\n }\n get HEX() {\n return CSS.HEX({\n R: this.R,\n G: this.G,\n B: this.B\n });\n }\n get HEXA() {\n return CSS.HEX({\n R: this.R,\n G: this.G,\n B: this.B,\n A: this.A * BASE_255\n });\n }\n get RGB() {\n return CSS.RGB({\n R: this.R,\n G: this.G,\n B: this.B\n }, this.options);\n }\n get RGBA() {\n return CSS.RGB({\n R: this.R,\n G: this.G,\n B: this.B,\n A: this.A\n }, this.options);\n }\n get HSL() {\n return CSS.HSL({\n H: this.H,\n S: this.S,\n L: this.L\n }, this.options);\n }\n get HSLA() {\n return CSS.HSL({\n H: this.H,\n S: this.S,\n L: this.L,\n A: this.A\n }, this.options);\n }\n get HWB() {\n return CSS.HWB({\n H: this.H,\n W: this.Whiteness,\n B: this.Blackness\n }, this.options);\n }\n get HWBA() {\n return CSS.HWB({\n H: this.H,\n W: this.Whiteness,\n B: this.Blackness,\n A: this.A\n }, this.options);\n }\n get CIELab() {\n return CSS.CIELab({\n L: this.CIEL,\n a: this.CIEa,\n b: this.CIEb\n }, this.options);\n }\n get CIELabA() {\n return CSS.CIELab({\n L: this.CIEL,\n a: this.CIEa,\n b: this.CIEb,\n A: this.A\n }, this.options);\n }\n get LCH() {\n return CSS.LCH({\n L: this.LCHL,\n C: this.LCHC,\n H: this.LCHH\n }, this.options);\n }\n get LCHA() {\n return CSS.LCH({\n L: this.LCHL,\n C: this.LCHC,\n H: this.LCHH,\n A: this.A\n }, this.options);\n }\n get CMYK() {\n return CSS.CMYK({\n C: this.C,\n M: this.M,\n Y: this.Y,\n K: this.K\n }, this.options);\n }\n get CMYKA() {\n return CSS.CMYK({\n C: this.C,\n M: this.M,\n Y: this.Y,\n K: this.K,\n A: this.A\n }, this.options);\n }\n static toHEXObject(color) {\n const model = getColorModel(color);\n return getColorReturn(color, model, 0, translateColor.HEX);\n }\n static toHEX(color) {\n return CSS.HEX(ColorTranslator.toHEXObject(color));\n }\n static toHEXAObject(color) {\n const model = getColorModel(color);\n return getColorReturn(color, model, 0, translateColor.HEXA);\n }\n static toHEXA(color) {\n return CSS.HEX(ColorTranslator.toHEXAObject(color));\n }\n static toRGBObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.RGB);\n }\n static toRGB(color, options = {}) {\n const rgb = ColorTranslator.toRGBObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.RGB(rgb, detectedOptions);\n }\n static toRGBAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.RGBA);\n }\n static toRGBA(color, options = {}) {\n const rgba = ColorTranslator.toRGBAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.RGB(rgba, detectedOptions);\n }\n static toHSLObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.HSL);\n }\n static toHSL(color, options = {}) {\n const hsl = ColorTranslator.toHSLObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.HSL(hsl, detectedOptions);\n }\n static toHSLAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.HSLA);\n }\n static toHSLA(color, options = {}) {\n const hsla = ColorTranslator.toHSLAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.HSL(hsla, detectedOptions);\n }\n static toHWBObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.HWB);\n }\n static toHWB(color, options = {}) {\n const hwb = ColorTranslator.toHWBObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.HWB(hwb, detectedOptions);\n }\n static toHWBAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.HWBA);\n }\n static toHWBA(color, options = {}) {\n const hwb = ColorTranslator.toHWBAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.HWB(hwb, detectedOptions);\n }\n static toCIELabObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.CIELab);\n }\n static toCIELab(color, options = {}) {\n const lab = ColorTranslator.toCIELabObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.CIELab(lab, detectedOptions);\n }\n static toCIELabAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.CIELabA);\n }\n static toCIELabA(color, options = {}) {\n const lab = ColorTranslator.toCIELabAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.CIELab(lab, detectedOptions);\n }\n static toLCHObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.LCH);\n }\n static toLCH(color, options = {}) {\n const lch = ColorTranslator.toLCHObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.LCH(lch, detectedOptions);\n }\n static toLCHAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.LCHA);\n }\n static toLCHA(color, options = {}) {\n const lch = ColorTranslator.toLCHAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.LCH(lch, detectedOptions);\n }\n static toCMYKObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.CMYK);\n }\n static toCMYK(color, options = {}) {\n const cmyk = ColorTranslator.toCMYKObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.CMYK(cmyk, detectedOptions);\n }\n static toCMYKAObject(color, options = {}) {\n const model = getColorModel(color);\n return getColorReturn(color, model, options.decimals, translateColor.CMYKA);\n }\n static toCMYKA(color, options = {}) {\n const cmyka = ColorTranslator.toCMYKAObject(color, options);\n const detectedOptions = getOptionsFromColorInput(options, color);\n return CSS.CMYK(cmyka, detectedOptions);\n }\n static getBlendHEXObject(from, to, steps = DEFAULT_BLEND_STEPS) {\n return getBlendReturn(from, to, steps, 0, translateColor.HEX);\n }\n static getBlendHEX(from, to, steps = DEFAULT_BLEND_STEPS) {\n return ColorTranslator.getBlendHEXObject(from, to, steps)\n .map((color) => CSS.HEX(color));\n }\n static getBlendHEXAObject(from, to, steps = DEFAULT_BLEND_STEPS) {\n return getBlendReturn(from, to, steps, 0, translateColor.HEXA);\n }\n static getBlendHEXA(from, to, steps = DEFAULT_BLEND_STEPS) {\n return ColorTranslator.getBlendHEXAObject(from, to, steps)\n .map((color) => CSS.HEX(color));\n }\n static getBlendRGBObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.RGB\n });\n }\n static getBlendRGB(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.RGB,\n cssFunction: CSS.RGB\n });\n }\n static getBlendRGBAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.RGBA\n });\n }\n static getBlendRGBA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.RGBA,\n cssFunction: CSS.RGB\n });\n }\n static getBlendHSLObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HSL\n });\n }\n static getBlendHSL(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HSL,\n cssFunction: CSS.HSL\n });\n }\n static getBlendHSLAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HSLA\n });\n }\n static getBlendHSLA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HSLA,\n cssFunction: CSS.HSL\n });\n }\n static getBlendHWBObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HWB\n });\n }\n static getBlendHWB(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HWB,\n cssFunction: CSS.HWB\n });\n }\n static getBlendHWBAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HWBA\n });\n }\n static getBlendHWBA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.HWBA,\n cssFunction: CSS.HWB\n });\n }\n static getBlendCIELabObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.CIELab\n });\n }\n static getBlendCIELab(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.CIELab,\n cssFunction: CSS.CIELab\n });\n }\n static getBlendCIELabAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.CIELabA\n });\n }\n static getBlendCIELabA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.CIELabA,\n cssFunction: CSS.CIELab\n });\n }\n static getBlendLCHObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.LCH\n });\n }\n static getBlendLCH(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.LCH,\n cssFunction: CSS.LCH\n });\n }\n static getBlendLCHAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.LCHA\n });\n }\n static getBlendLCHA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturnWithParameters({\n from,\n to,\n thirdParameter,\n fourthParameter,\n translateFunction: translateColor.LCHA,\n cssFunction: CSS.LCH\n });\n }\n static getMixHEXObject(colors, mode = Mix.ADDITIVE) {\n return colorMixer.HEX(colors, mode, false);\n }\n static getMixHEX(colors, mode = Mix.ADDITIVE) {\n return colorMixer.HEX(colors, mode, true);\n }\n static getMixHEXAObject(colors, mode = Mix.ADDITIVE) {\n return colorMixer.HEXA(colors, mode, false);\n }\n static getMixHEXA(colors, mode = Mix.ADDITIVE) {\n return colorMixer.HEXA(colors, mode, true);\n }\n static getMixRGBObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.RGB,\n css: false\n });\n }\n static getMixRGB(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.RGB,\n css: true\n });\n }\n static getMixRGBAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.RGBA,\n css: false\n });\n }\n static getMixRGBA(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.RGBA,\n css: true\n });\n }\n static getMixHSLObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HSL,\n css: false\n });\n }\n static getMixHSL(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HSL,\n css: true\n });\n }\n static getMixHSLAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HSLA,\n css: false\n });\n }\n static getMixHSLA(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HSLA,\n css: true\n });\n }\n static getMixHWBObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HWB,\n css: false\n });\n }\n static getMixHWB(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HWB,\n css: true\n });\n }\n static getMixHWBAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HWBA,\n css: false\n });\n }\n static getMixHWBA(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.HWBA,\n css: true\n });\n }\n static getMixCIELabObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.CIELab,\n css: false\n });\n }\n static getMixCIELab(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.CIELab,\n css: true\n });\n }\n static getMixCIELabAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.CIELabA,\n css: false\n });\n }\n static getMixCIELabA(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.CIELabA,\n css: true\n });\n }\n static getMixLCHObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.LCH,\n css: false\n });\n }\n static getMixLCH(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.LCH,\n css: true\n });\n }\n static getMixLCHAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.LCHA,\n css: false\n });\n }\n static getMixLCHA(colors, secondParameter, thirdParameter) {\n return getMixReturn({\n colors,\n secondParameter,\n thirdParameter,\n colorMixerFunction: bindedMixers.LCHA,\n css: true\n });\n }\n static getShades(color, secondParameter, thirdParameter) {\n if (typeof secondParameter === 'number') {\n return getColorMixture(color, secondParameter, true, getOptionsFromColorInput(thirdParameter || {}, color));\n }\n return getColorMixture(color, DEFAULT_SHADES_TINTS_STEPS, true, getOptionsFromColorInput(secondParameter || {}, color));\n }\n static getTints(color, secondParameter, thirdParameter) {\n if (typeof secondParameter === 'number') {\n return getColorMixture(color, secondParameter, false, getOptionsFromColorInput(thirdParameter || {}, color));\n }\n return getColorMixture(color, DEFAULT_SHADES_TINTS_STEPS, false, getOptionsFromColorInput(secondParameter || {}, color));\n }\n static getHarmony(color, secondParam, thirdParam, fourthParam) {\n if (isHarmony(secondParam)) {\n return getHarmonyReturn(secondParam, color, isMix(thirdParam)\n ? thirdParam\n : Mix.ADDITIVE, getOptionsFromColorInput(isMix(thirdParam)\n ? (fourthParam || {})\n : thirdParam || {}, color));\n }\n else if (isMix(secondParam)) {\n return getHarmonyReturn(Harmony.COMPLEMENTARY, color, secondParam, getOptionsFromColorInput(thirdParam || {}, color));\n }\n return getHarmonyReturn(Harmony.COMPLEMENTARY, color, Mix.ADDITIVE, getOptionsFromColorInput(secondParam || {}, color));\n }\n}\n\n\n;// ./src/@demo/demo1/index.js\n\n\n/* harmony default export */ const demo1 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const color = new ColorTranslator('hsl(180 100% 50%)', { decimals: 0 });\n\n for (let row = 0; row < 10; row++) {\n\n for (let col = 0; col < 10; col++) {\n\n color\n .setS(row * 10)\n .setL(col * 5 + 30);\n\n const box = document.createElement('div');\n\n box.classList.add('box');\n box.style.background = color.HEX;\n\n box.innerText =\n `R:${color.R}\n G:${color.G}\n B:${color.B}`;\n container.appendChild(box);\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo2/index.js\n\n\n/* harmony default export */ const demo2 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const color = new ColorTranslator({ R: 255, G: 0, B: 0 });\n const hue = [0, 30, 60, 120, 240, 280, 320, 0];\n let rainbow;\n\n for (let r = 0; r < hue.length; r++) {\n\n color.setH(hue[r]);\n\n const bow = document.createElement('div');\n\n bow.classList.add('rainbow');\n bow.style.background = color.HEX;\n\n if (rainbow) {\n rainbow.appendChild(bow);\n } else {\n container.appendChild(bow);\n }\n\n rainbow = bow;\n }\n\n rainbow.style.background = '#333';\n\n return container;\n\n});\n;// ./src/@demo/demo3/index.js\n\n\n/* harmony default export */ const demo3 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const hsl = { H: 0, S: '90%', L: '50%' };\n const hue = [undefined, 55, 30, 0, 290, 220, 130];\n const total = hue.length;\n\n for (let row = 0; row < total; row++) {\n\n for (let col = 0; col < total; col++) {\n\n let index = total - row + col;\n if (index >= total) {\n index -= total;\n }\n hsl.H = hue[index];\n const rgb = hue[index] === undefined\n ? '#FFF'\n : ColorTranslator.toHEX(hsl);\n const box = document.createElement('div');\n\n box.classList.add('flag');\n box.style.background = rgb;\n\n container.appendChild(box);\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo4/index.js\n\n\n/* harmony default export */ const demo4 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const hexColors = [\n '#FE2712', '#FE5409', '#FB9902',\n '#FABD03', '#FFFE32', '#D1EA2C',\n '#66B132', '#0392CE', '#0247FE',\n '#3D00A5', '#8601B0', '#A7194B'\n ];\n\n hexColors.forEach((color) => {\n\n const rgb = ColorTranslator.toRGB(color);\n const hsl = ColorTranslator.toHSL(color, { decimals: 0 });\n const hwb = ColorTranslator.toHWB(color, { decimals: 0 });\n const lab = ColorTranslator.toCIELab(color, { decimals: 0 });\n const lch = ColorTranslator.toLCH(color, { decimals: 0 });\n\n const rgbDiv = document.createElement('div');\n const hslDiv = document.createElement('div');\n const hwbDiv = document.createElement('div');\n const labDiv = document.createElement('div');\n const lchDiv = document.createElement('div');\n\n rgbDiv.style.backgroundColor = rgb;\n rgbDiv.textContent = rgb;\n\n hslDiv.style.backgroundColor = hsl;\n hslDiv.textContent = hsl;\n\n hwbDiv.style.backgroundColor = hwb;\n hwbDiv.textContent = hwb;\n\n labDiv.style.backgroundColor = lab;\n labDiv.textContent = lab;\n\n lchDiv.style.backgroundColor = lch;\n lchDiv.textContent = lch;\n\n container.appendChild(rgbDiv);\n container.appendChild(hslDiv);\n container.appendChild(hwbDiv);\n container.appendChild(labDiv);\n container.appendChild(lchDiv);\n\n });\n\n return container;\n\n});\n;// ./src/@demo/demo5/index.js\n\n\n/* harmony default export */ const demo5 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const colors = [\n 'red',\n 'lime',\n 'blue',\n 'aqua',\n 'yellow',\n 'fuchsia'\n ];\n const total = colors.length;\n\n for (let row = 0; row < total; row++) {\n\n const hsl = ColorTranslator.toHSLObject(colors[row]);\n const step = hsl.S / (total - 1);\n\n for (let col = 0; col < total; col++) {\n\n const rgb = ColorTranslator.toHEX(hsl);\n const cmyk = ColorTranslator.toCMYKObject(hsl, { decimals: 0 });\n\n const box = document.createElement('div');\n box.classList.add('box');\n box.style.background = rgb;\n box.innerText = `C:${cmyk.C}\n M:${cmyk.M}\n Y:${cmyk.Y}\n K:${cmyk.K}`;\n\n container.appendChild(box);\n\n hsl.S -= step;\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo6/index.js\n\n\n/* harmony default export */ const demo6 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const rows = 11;\n const mult = 3;\n\n for (let i = 0; i < rows; i++) {\n\n const blends = ColorTranslator.getBlendHEX('#F00', '#FF0', mult + i * mult);\n\n blends.forEach((blend, index) => {\n const box = document.createElement('div');\n box.classList.add('box', `file${i}`);\n box.style.background = blend;\n box.innerText = index + 1;\n container.appendChild(box);\n });\n\n }\n\n return container;\n\n});\n;// ./src/@demo/demo7/index.js\n\n\n/* harmony default export */ const demo7 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n\n const colors = ['#F00', '#FF8000', '#FF0', '#0F0', '#00F', '#A0F', '#F0A'];\n\n const createBox = (color, type) => {\n const box = document.createElement('div');\n box.classList.add('box');\n box.style.backgroundColor = color;\n if (type) box.dataset.type = type;\n container.appendChild(box);\n };\n\n colors.forEach((color) => {\n const shades = ColorTranslator.getShades(color, 3).reverse();\n const tints = ColorTranslator.getTints(color, 3);\n shades.forEach((shade) => createBox(shade, 'shade'));\n createBox(color);\n tints.forEach((tint) => createBox(tint, 'tint'));\n });\n\n return container;\n\n});\n;// ./src/@demo/demo8/index.js\n\n\n\n/* harmony default export */ const demo8 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n\n const mixes = [\n '#F00',\n '#0F0',\n '#00F',\n [1, 3],\n [1, 2],\n [2, 3],\n [1, 2, 3]\n ];\n\n const fillPlanes = () => {\n const planes = container.querySelectorAll('#planes path');\n planes.forEach((plane, index) => {\n let color = '#CCC';\n if (typeof mixes[index] === 'string') {\n color = mixes[index];\n } else if(mixes[index]) {\n const colors = mixes[index].map((i) => mixes[i - 1]);\n color = mixes[index] = ColorTranslator.getMixHEX(colors);\n }\n plane.setAttribute('fill', color);\n });\n };\n\n fetch('images/color-mixes.svg')\n .then(result => result.text())\n .then((svgCode) => {\n container.innerHTML = svgCode;\n fillPlanes();\n });\n\n return container;\n\n});\n;// ./src/@demo/demo9/index.js\n\n\n/* harmony default export */ const demo9 = ((ColorTranslator, { Mix }) => {\n\n const container = document.createElement('div');\n\n const mixes = [\n '#F00',\n '#FF0',\n '#00F',\n [1, 3],\n [1, 2],\n [2, 3],\n [1, 2, 3]\n ];\n\n const fillPlanes = () => {\n const planes = container.querySelectorAll('#planes path');\n planes.forEach((plane, index) => {\n let color = '#CCC';\n if (typeof mixes[index] === 'string') {\n color = mixes[index];\n } else if(mixes[index]) {\n const colors = mixes[index].map((i) => mixes[i - 1]);\n color = mixes[index] = ColorTranslator.getMixHEX(colors, Mix.SUBTRACTIVE);\n }\n plane.setAttribute('fill', color);\n });\n };\n\n fetch('images/color-mixes.svg')\n .then(result => result.text())\n .then((svgCode) => {\n container.innerHTML = svgCode;\n fillPlanes();\n });\n\n return container;\n\n});\n;// ./src/@demo/demo10/index.js\n\n\n/* harmony default export */ const demo10 = ((ColorTranslator, { Harmony }) => {\n\n const container = document.createElement('div');\n\n const harmonies = [\n { label: 'Complementary', value: Harmony.COMPLEMENTARY },\n { label: 'Split Complementary', value: Harmony.SPLIT_COMPLEMENTARY },\n { label: 'Analogous', value: Harmony.ANALOGOUS },\n { label: 'Triadic', value: Harmony.TRIADIC },\n { label: 'Tetradic', value: Harmony.TETRADIC },\n { label: 'Square', value: Harmony.SQUARE }\n ];\n\n const baseColor = '#F00';\n\n const createElement = (className, parent) => {\n const div = document.createElement('div');\n div.classList.add(className);\n parent.appendChild(div);\n return div;\n };\n\n const createHarmony = (item) => {\n\n const wrapper = createElement('wrapper', container);\n const wheel = createElement('wheel', wrapper);\n const harmony = createElement('harmony', wrapper);\n createElement('label', wrapper).innerText = item.label;\n\n fetch('images/wheel-additive.svg')\n .then(result => result.text())\n .then((svgCode) => {\n const harmonyColors = ColorTranslator.getHarmony(baseColor, item.value);\n const selector = 'path' + harmonyColors.map((color) => `:not([fill=\"${color}\"])`).join('');\n wheel.innerHTML = svgCode;\n harmonyColors.forEach((hex) => createElement('box', harmony).style.background = hex);\n wheel.querySelectorAll(selector).forEach((path) => path.setAttribute('fill-opacity', '0.25'));\n });\n\n };\n\n harmonies.forEach((item) => createHarmony(item));\n\n return container;\n\n});\n;// ./src/@demo/demo11/index.js\n\n\n/* harmony default export */ const demo11 = ((ColorTranslator, { Harmony, Mix }) => {\n\n const container = document.createElement('div');\n\n const harmonies = [\n { label: 'Complementary', value: Harmony.COMPLEMENTARY },\n { label: 'Split Complementary', value: Harmony.SPLIT_COMPLEMENTARY },\n { label: 'Analogous', value: Harmony.ANALOGOUS },\n { label: 'Triadic', value: Harmony.TRIADIC },\n { label: 'Tetradic', value: Harmony.TETRADIC },\n { label: 'Square', value: Harmony.SQUARE }\n ];\n\n const baseColor = '#F00';\n\n const createElement = (className, parent) => {\n const div = document.createElement('div');\n div.classList.add(className);\n parent.appendChild(div);\n return div;\n };\n\n const createHarmony = (item) => {\n\n const wrapper = createElement('wrapper', container);\n const wheel = createElement('wheel', wrapper);\n const harmony = createElement('harmony', wrapper);\n createElement('label', wrapper).innerText = item.label;\n\n fetch('images/wheel-subtractive.svg')\n .then(result => result.text())\n .then((svgCode) => {\n const harmonyColors = ColorTranslator.getHarmony(baseColor, item.value, Mix.SUBTRACTIVE);\n const selector = 'path' + harmonyColors.map((color) => `:not([fill=\"${color}\"])`).join('');\n wheel.innerHTML = svgCode;\n harmonyColors.forEach((hex) => createElement('box', harmony).style.background = hex);\n wheel.querySelectorAll(selector).forEach((path) => path.setAttribute('fill-opacity', '0.25'));\n });\n\n };\n\n harmonies.forEach((item) => createHarmony(item));\n\n return container;\n\n});\n;// ./src/@demo/demo.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst functioToString = (fn) => {\n const article = document.createElement('article');\n const pre = document.createElement('pre');\n article.classList.add('function-container');\n pre.classList.add('prettyprint');\n article.appendChild(pre);\n pre.innerHTML = fn.toString().replace('(ColorTranslator)', '()');\n return article;\n};\n\nconst demos = new Map([\n ['demo1', demo1],\n ['demo2', demo2],\n ['demo3', demo3],\n ['demo4', demo4],\n ['demo5', demo5],\n ['demo6', demo6],\n ['demo7', demo7],\n ['demo8', demo8],\n ['demo9', demo9],\n ['demo10', demo10],\n ['demo11', demo11]\n]);\n\ndocument.addEventListener('DOMContentLoaded', () => {\n demos.forEach((module, div) => {\n const demo = document.getElementById(div);\n const container = document.createElement('div');\n const wrapper = document.createElement('div');\n\n container.classList.add('demo-container');\n wrapper.classList.add('demo-wrapper');\n\n wrapper.appendChild(module(ColorTranslator, { Harmony: Harmony, Mix: Mix }));\n container.appendChild(wrapper);\n demo.appendChild(container);\n demo.appendChild(functioToString(module));\n });\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiOTY3LmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxxQkFBTSxvQkFBb0IscUJBQU07QUFDMUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JELFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUiw0RUFBNEU7QUFDNUU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLHNDQUFzQztBQUNoQztBQUNBO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDTztBQUNQO0FBQ0E7QUFDQTtBQUNBLENBQUMsd0JBQXdCOzs7QUMzTVk7QUFDOUI7QUFDUCxL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QUNwQjtBQUNBO0FBQ0EsZUFBZSxLQUFLO0FBQ3BCO0FBQ0E7QUFDQSxlQUFlLEtBQUs7QUFDcEI7QUFDQTtBQUNBLGVBQWUsS0FBSztBQUNwQjtBQUNBO0FBQ0EsZUFBZSxLQUFLO0FBQ3BCO0FBQ0E7QUFDQSxlQUFlLEtBQUs7QUFDcEI7QUFDQTtBQUNBLGVBQWUsY0FBb0I7QUFDbkM7QUFDQTtBQUNBLGVBQWUsY0FBb0I7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxHQUFHO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxHQUFHO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QixRQUFRO0FBQ2hDLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxHQUFHO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxHQUFHO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLEdBQUc7QUFDbEI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLEdBQUc7QUFDbEI7QUFDQTtBQUNBO0FB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QUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGVBQWUsWUFBWTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLFlBQVk7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGVBQWUsWUFBWTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLFlBQVk7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGVBQWUsWUFBWTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLFlBQVk7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGVBQWUsWUFBWTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLFlBQVk7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLGVBQWUsWUFBWTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxlQUFlLFlBQVk7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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Q2xFLFVBQVUsc0RBQXNEO0FBQ2hFLFVBQVUsdURBQXVEO0FBQ2pFLFVBQVU7QUFDVjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRkFBc0YsTUFBTTtBQUM1RjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViOztBQUVBOztBQUVBOztBQUVBLENBQUMsRTs7QUMvQ3FFO0FBQ0E7QUFDSDtBQUM3QztBQUNDO0FBQzZCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNFO0FBQ0E7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGVBQWUsTUFBTTtBQUNyQixlQUFlLE1BQU07QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1DQUFtQyxlQUFlLElBQUksT0FBTyxjQUFLLE9BQUU7QUFDcEU7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9ub2RlX21vZHVsZXMvLnBucG0vd2hhdHdnLWZldGNoQDMuNi4yMC9ub2RlX21vZHVsZXMvd2hhdHdnLWZldGNoL2ZldGNoLmpzP2Q0Y2IiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2NvbnN0YW50cy9udW1iZXJzLnRzPzBmNTkiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2NvbnN0YW50cy9lbnVtcy50cz8yMTMzIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb25zdGFudHMvcmVnZXhwcy50cz80YmI2Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb25zdGFudHMvZXJyb3JzLnRzP2RkNjMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0B0eXBlcy9pbmRleC50cz8xYzE1Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb25zdGFudHMvb3B0aW9ucy50cz8xYWRlIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb25zdGFudHMvaW5kZXgudHM/OWUzZSIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvaGVscGVycy9pbmRleC50cz8wYjZjIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb2xvci90cmFuc2xhdG9ycy50cz9mZmFmIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL2Jhc2VDbGFzc2VzL19SZ2JDbGFzcy50cz9jMzYwIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL19IRVhTdHJpbmdQYXJzZXIudHM/ZmE2OSIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvcGFyc2Vycy9fQ2FsY1BhcnNlci50cz82OTRlIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL2Jhc2VDbGFzc2VzL19BbHBoYUJhc2VDbGFzcy50cz8zZjM3Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL19SR0JTdHJpbmdQYXJzZXIudHM/MDVlNCIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvcGFyc2Vycy9iYXNlQ2xhc3Nlcy9fSHVlQmFzZUNsYXNzLnRzPzQwMjgiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL3BhcnNlcnMvX0hTTFN0cmluZ1BhcnNlci50cz84MjBhIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL19IV0JTdHJpbmdQYXJzZXIudHM/MTc3NyIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvcGFyc2Vycy9fQ0lFTGFiU3RyaW5nUGFyc2VyLnRzPzIzYWMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL3BhcnNlcnMvX0xDSFN0cmluZ1BhcnNlci50cz85NzQ0Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9wYXJzZXJzL19DTVlLU3RyaW5nUGFyc2VyLnRzPzM1NWUiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL3BhcnNlcnMvaW5kZXgudHM/NjJjZSIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvY29sb3IvZXh0cmFjdG9ycy50cz81MmEyIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb2xvci9yb3VuZGVycy50cz81NzhiIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb2xvci9jc3MudHM/OTY2MyIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvY29sb3IvdXRpbHMudHM/ZDI2MyIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvcmV0dXJucy9pbmRleC50cz9hMGQyIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9pbmRleC50cz8wZmNhIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vMS9pbmRleC5qcz8zOTY1Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vMi9pbmRleC5qcz9kOGRjIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vMy9pbmRleC5qcz9kMzg2Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vNC9pbmRleC5qcz82MTlmIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vNS9pbmRleC5qcz9kOGNjIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vNi9pbmRleC5qcz8zYTMyIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vNy9pbmRleC5qcz84MzQzIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vOC9pbmRleC5qcz83NzI1Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vOS9pbmRleC5qcz84NTMyIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vMTAvaW5kZXguanM/NGY2NyIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvQGRlbW8vZGVtbzExL2luZGV4LmpzP2RiZTYiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW8uanM/OWI3ZCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90b3R5cGUtYnVpbHRpbnMgKi9cbnZhciBnID1cbiAgKHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyAmJiBnbG9iYWxUaGlzKSB8fFxuICAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnICYmIHNlbGYpIHx8XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZlxuICAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcgJiYgZ2xvYmFsKSB8fFxuICB7fVxuXG52YXIgc3VwcG9ydCA9IHtcbiAgc2VhcmNoUGFyYW1zOiAnVVJMU2VhcmNoUGFyYW1zJyBpbiBnLFxuICBpdGVyYWJsZTogJ1N5bWJvbCcgaW4gZyAmJiAnaXRlcmF0b3InIGluIFN5bWJvbCxcbiAgYmxvYjpcbiAgICAnRmlsZVJlYWRlcicgaW4gZyAmJlxuICAgICdCbG9iJyBpbiBnICYmXG4gICAgKGZ1bmN0aW9uKCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgbmV3IEJsb2IoKVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIH1cbiAgICB9KSgpLFxuICBmb3JtRGF0YTogJ0Zvcm1EYXRhJyBpbiBnLFxuICBhcnJheUJ1ZmZlcjogJ0FycmF5QnVmZmVyJyBpbiBnXG59XG5cbmZ1bmN0aW9uIGlzRGF0YVZpZXcob2JqKSB7XG4gIHJldHVybiBvYmogJiYgRGF0YVZpZXcucHJvdG90eXBlLmlzUHJvdG90eXBlT2Yob2JqKVxufVxuXG5pZiAoc3VwcG9ydC5hcnJheUJ1ZmZlcikge1xuICB2YXIgdmlld0NsYXNzZXMgPSBbXG4gICAgJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgJ1tvYmplY3QgVWludDhBcnJheV0nLFxuICAgICdbb2JqZWN0IFVpbnQ4Q2xhbXBlZEFycmF5XScsXG4gICAgJ1tvYmplY3QgSW50MTZBcnJheV0nLFxuICAgICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgJ1tvYmplY3QgSW50MzJBcnJheV0nLFxuICAgICdbb2JqZWN0IFVpbnQzMkFycmF5XScsXG4gICAgJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgJ1tvYmplY3QgRmxvYXQ2NEFycmF5XSdcbiAgXVxuXG4gIHZhciBpc0FycmF5QnVmZmVyVmlldyA9XG4gICAgQXJyYXlCdWZmZXIuaXNWaWV3IHx8XG4gICAgZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIHZpZXdDbGFzc2VzLmluZGV4T2YoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikpID4gLTFcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZU5hbWUobmFtZSkge1xuICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgbmFtZSA9IFN0cmluZyhuYW1lKVxuICB9XG4gIGlmICgvW15hLXowLTlcXC0jJCUmJyorLl5fYHx+IV0vaS50ZXN0KG5hbWUpIHx8IG5hbWUgPT09ICcnKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCBjaGFyYWN0ZXIgaW4gaGVhZGVyIGZpZWxkIG5hbWU6IFwiJyArIG5hbWUgKyAnXCInKVxuICB9XG4gIHJldHVybiBuYW1lLnRvTG93ZXJDYXNlKClcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplVmFsdWUodmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICB2YWx1ZSA9IFN0cmluZyh2YWx1ZSlcbiAgfVxuICByZXR1cm4gdmFsdWVcbn1cblxuLy8gQnVpbGQgYSBkZXN0cnVjdGl2ZSBpdGVyYXRvciBmb3IgdGhlIHZhbHVlIGxpc3RcbmZ1bmN0aW9uIGl0ZXJhdG9yRm9yKGl0ZW1zKSB7XG4gIHZhciBpdGVyYXRvciA9IHtcbiAgICBuZXh0OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB2YWx1ZSA9IGl0ZW1zLnNoaWZ0KClcbiAgICAgIHJldHVybiB7ZG9uZTogdmFsdWUgPT09IHVuZGVmaW5lZCwgdmFsdWU6IHZhbHVlfVxuICAgIH1cbiAgfVxuXG4gIGlmIChzdXBwb3J0Lml0ZXJhYmxlKSB7XG4gICAgaXRlcmF0b3JbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGl0ZXJhdG9yXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGl0ZXJhdG9yXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBIZWFkZXJzKGhlYWRlcnMpIHtcbiAgdGhpcy5tYXAgPSB7fVxuXG4gIGlmIChoZWFkZXJzIGluc3RhbmNlb2YgSGVhZGVycykge1xuICAgIGhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgdGhpcy5hcHBlbmQobmFtZSwgdmFsdWUpXG4gICAgfSwgdGhpcylcbiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGhlYWRlcnMpKSB7XG4gICAgaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uKGhlYWRlcikge1xuICAgICAgaWYgKGhlYWRlci5sZW5ndGggIT0gMikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdIZWFkZXJzIGNvbnN0cnVjdG9yOiBleHBlY3RlZCBuYW1lL3ZhbHVlIHBhaXIgdG8gYmUgbGVuZ3RoIDIsIGZvdW5kJyArIGhlYWRlci5sZW5ndGgpXG4gICAgICB9XG4gICAgICB0aGlzLmFwcGVuZChoZWFkZXJbMF0sIGhlYWRlclsxXSlcbiAgICB9LCB0aGlzKVxuICB9IGVsc2UgaWYgKGhlYWRlcnMpIHtcbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhoZWFkZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHRoaXMuYXBwZW5kKG5hbWUsIGhlYWRlcnNbbmFtZV0pXG4gICAgfSwgdGhpcylcbiAgfVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5hcHBlbmQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICBuYW1lID0gbm9ybWFsaXplTmFtZShuYW1lKVxuICB2YWx1ZSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKVxuICB2YXIgb2xkVmFsdWUgPSB0aGlzLm1hcFtuYW1lXVxuICB0aGlzLm1hcFtuYW1lXSA9IG9sZFZhbHVlID8gb2xkVmFsdWUgKyAnLCAnICsgdmFsdWUgOiB2YWx1ZVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBmdW5jdGlvbihuYW1lKSB7XG4gIGRlbGV0ZSB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbihuYW1lKSB7XG4gIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gIHJldHVybiB0aGlzLmhhcyhuYW1lKSA/IHRoaXMubWFwW25hbWVdIDogbnVsbFxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5oYXMgPSBmdW5jdGlvbihuYW1lKSB7XG4gIHJldHVybiB0aGlzLm1hcC5oYXNPd25Qcm9wZXJ0eShub3JtYWxpemVOYW1lKG5hbWUpKVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICB0aGlzLm1hcFtub3JtYWxpemVOYW1lKG5hbWUpXSA9IG5vcm1hbGl6ZVZhbHVlKHZhbHVlKVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2ssIHRoaXNBcmcpIHtcbiAgZm9yICh2YXIgbmFtZSBpbiB0aGlzLm1hcCkge1xuICAgIGlmICh0aGlzLm1hcC5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgY2FsbGJhY2suY2FsbCh0aGlzQXJnLCB0aGlzLm1hcFtuYW1lXSwgbmFtZSwgdGhpcylcbiAgICB9XG4gIH1cbn1cblxuSGVhZGVycy5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaXRlbXMgPSBbXVxuICB0aGlzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICBpdGVtcy5wdXNoKG5hbWUpXG4gIH0pXG4gIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbn1cblxuSGVhZGVycy5wcm90b3R5cGUudmFsdWVzID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpdGVtcyA9IFtdXG4gIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSkge1xuICAgIGl0ZW1zLnB1c2godmFsdWUpXG4gIH0pXG4gIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbn1cblxuSGVhZGVycy5wcm90b3R5cGUuZW50cmllcyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaXRlbXMgPSBbXVxuICB0aGlzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICBpdGVtcy5wdXNoKFtuYW1lLCB2YWx1ZV0pXG4gIH0pXG4gIHJldHVybiBpdGVyYXRvckZvcihpdGVtcylcbn1cblxuaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgSGVhZGVycy5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IEhlYWRlcnMucHJvdG90eXBlLmVudHJpZXNcbn1cblxuZnVuY3Rpb24gY29uc3VtZWQoYm9keSkge1xuICBpZiAoYm9keS5fbm9Cb2R5KSByZXR1cm5cbiAgaWYgKGJvZHkuYm9keVVzZWQpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFR5cGVFcnJvcignQWxyZWFkeSByZWFkJykpXG4gIH1cbiAgYm9keS5ib2R5VXNlZCA9IHRydWVcbn1cblxuZnVuY3Rpb24gZmlsZVJlYWRlclJlYWR5KHJlYWRlcikge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgcmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmVzb2x2ZShyZWFkZXIucmVzdWx0KVxuICAgIH1cbiAgICByZWFkZXIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmVqZWN0KHJlYWRlci5lcnJvcilcbiAgICB9XG4gIH0pXG59XG5cbmZ1bmN0aW9uIHJlYWRCbG9iQXNBcnJheUJ1ZmZlcihibG9iKSB7XG4gIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpXG4gIHZhciBwcm9taXNlID0gZmlsZVJlYWRlclJlYWR5KHJlYWRlcilcbiAgcmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKGJsb2IpXG4gIHJldHVybiBwcm9taXNlXG59XG5cbmZ1bmN0aW9uIHJlYWRCbG9iQXNUZXh0KGJsb2IpIHtcbiAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgdmFyIHByb21pc2UgPSBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKVxuICB2YXIgbWF0Y2ggPSAvY2hhcnNldD0oW0EtWmEtejAtOV8tXSspLy5leGVjKGJsb2IudHlwZSlcbiAgdmFyIGVuY29kaW5nID0gbWF0Y2ggPyBtYXRjaFsxXSA6ICd1dGYtOCdcbiAgcmVhZGVyLnJlYWRBc1RleHQoYmxvYiwgZW5jb2RpbmcpXG4gIHJldHVybiBwcm9taXNlXG59XG5cbmZ1bmN0aW9uIHJlYWRBcnJheUJ1ZmZlckFzVGV4dChidWYpIHtcbiAgdmFyIHZpZXcgPSBuZXcgVWludDhBcnJheShidWYpXG4gIHZhciBjaGFycyA9IG5ldyBBcnJheSh2aWV3Lmxlbmd0aClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHZpZXcubGVuZ3RoOyBpKyspIHtcbiAgICBjaGFyc1tpXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUodmlld1tpXSlcbiAgfVxuICByZXR1cm4gY2hhcnMuam9pbignJylcbn1cblxuZnVuY3Rpb24gYnVmZmVyQ2xvbmUoYnVmKSB7XG4gIGlmIChidWYuc2xpY2UpIHtcbiAgICByZXR1cm4gYnVmLnNsaWNlKDApXG4gIH0gZWxzZSB7XG4gICAgdmFyIHZpZXcgPSBuZXcgVWludDhBcnJheShidWYuYnl0ZUxlbmd0aClcbiAgICB2aWV3LnNldChuZXcgVWludDhBcnJheShidWYpKVxuICAgIHJldHVybiB2aWV3LmJ1ZmZlclxuICB9XG59XG5cbmZ1bmN0aW9uIEJvZHkoKSB7XG4gIHRoaXMuYm9keVVzZWQgPSBmYWxzZVxuXG4gIHRoaXMuX2luaXRCb2R5ID0gZnVuY3Rpb24oYm9keSkge1xuICAgIC8qXG4gICAgICBmZXRjaC1tb2NrIHdyYXBzIHRoZSBSZXNwb25zZSBvYmplY3QgaW4gYW4gRVM2IFByb3h5IHRvXG4gICAgICBwcm92aWRlIHVzZWZ1bCB0ZXN0IGhhcm5lc3MgZmVhdHVyZXMgc3VjaCBhcyBmbHVzaC4gSG93ZXZlciwgb25cbiAgICAgIEVTNSBicm93c2VycyB3aXRob3V0IGZldGNoIG9yIFByb3h5IHN1cHBvcnQgcG9sbHlmaWxscyBtdXN0IGJlIHVzZWQ7XG4gICAgICB0aGUgcHJveHktcG9sbHlmaWxsIGlzIHVuYWJsZSB0byBwcm94eSBhbiBhdHRyaWJ1dGUgdW5sZXNzIGl0IGV4aXN0c1xuICAgICAgb24gdGhlIG9iamVjdCBiZWZvcmUgdGhlIFByb3h5IGlzIGNyZWF0ZWQuIFRoaXMgY2hhbmdlIGVuc3VyZXNcbiAgICAgIFJlc3BvbnNlLmJvZHlVc2VkIGV4aXN0cyBvbiB0aGUgaW5zdGFuY2UsIHdoaWxlIG1haW50YWluaW5nIHRoZVxuICAgICAgc2VtYW50aWMgb2Ygc2V0dGluZyBSZXF1ZXN0LmJvZHlVc2VkIGluIHRoZSBjb25zdHJ1Y3RvciBiZWZvcmVcbiAgICAgIF9pbml0Qm9keSBpcyBjYWxsZWQuXG4gICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1hc3NpZ25cbiAgICB0aGlzLmJvZHlVc2VkID0gdGhpcy5ib2R5VXNlZFxuICAgIHRoaXMuX2JvZHlJbml0ID0gYm9keVxuICAgIGlmICghYm9keSkge1xuICAgICAgdGhpcy5fbm9Cb2R5ID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2JvZHlUZXh0ID0gJydcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBib2R5ID09PSAnc3RyaW5nJykge1xuICAgICAgdGhpcy5fYm9keVRleHQgPSBib2R5XG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LmJsb2IgJiYgQmxvYi5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgdGhpcy5fYm9keUJsb2IgPSBib2R5XG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LmZvcm1EYXRhICYmIEZvcm1EYXRhLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICB0aGlzLl9ib2R5Rm9ybURhdGEgPSBib2R5XG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LnNlYXJjaFBhcmFtcyAmJiBVUkxTZWFyY2hQYXJhbXMucHJvdG90eXBlLmlzUHJvdG90eXBlT2YoYm9keSkpIHtcbiAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keS50b1N0cmluZygpXG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIHN1cHBvcnQuYmxvYiAmJiBpc0RhdGFWaWV3KGJvZHkpKSB7XG4gICAgICB0aGlzLl9ib2R5QXJyYXlCdWZmZXIgPSBidWZmZXJDbG9uZShib2R5LmJ1ZmZlcilcbiAgICAgIC8vIElFIDEwLTExIGNhbid0IGhhbmRsZSBhIERhdGFWaWV3IGJvZHkuXG4gICAgICB0aGlzLl9ib2R5SW5pdCA9IG5ldyBCbG9iKFt0aGlzLl9ib2R5QXJyYXlCdWZmZXJdKVxuICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5hcnJheUJ1ZmZlciAmJiAoQXJyYXlCdWZmZXIucHJvdG90eXBlLmlzUHJvdG90eXBlT2YoYm9keSkgfHwgaXNBcnJheUJ1ZmZlclZpZXcoYm9keSkpKSB7XG4gICAgICB0aGlzLl9ib2R5QXJyYXlCdWZmZXIgPSBidWZmZXJDbG9uZShib2R5KVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9ib2R5VGV4dCA9IGJvZHkgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoYm9keSlcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpKSB7XG4gICAgICBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICd0ZXh0L3BsYWluO2NoYXJzZXQ9VVRGLTgnKVxuICAgICAgfSBlbHNlIGlmICh0aGlzLl9ib2R5QmxvYiAmJiB0aGlzLl9ib2R5QmxvYi50eXBlKSB7XG4gICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsIHRoaXMuX2JvZHlCbG9iLnR5cGUpXG4gICAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgICB0aGlzLmhlYWRlcnMuc2V0KCdjb250ZW50LXR5cGUnLCAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkO2NoYXJzZXQ9VVRGLTgnKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChzdXBwb3J0LmJsb2IpIHtcbiAgICB0aGlzLmJsb2IgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciByZWplY3RlZCA9IGNvbnN1bWVkKHRoaXMpXG4gICAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgICAgcmV0dXJuIHJlamVjdGVkXG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9ib2R5QmxvYikge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlCbG9iKVxuICAgICAgfSBlbHNlIGlmICh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShuZXcgQmxvYihbdGhpcy5fYm9keUFycmF5QnVmZmVyXSkpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCByZWFkIEZvcm1EYXRhIGJvZHkgYXMgYmxvYicpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBCbG9iKFt0aGlzLl9ib2R5VGV4dF0pKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuYXJyYXlCdWZmZXIgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICB2YXIgaXNDb25zdW1lZCA9IGNvbnN1bWVkKHRoaXMpXG4gICAgICBpZiAoaXNDb25zdW1lZCkge1xuICAgICAgICByZXR1cm4gaXNDb25zdW1lZFxuICAgICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcodGhpcy5fYm9keUFycmF5QnVmZmVyKSkge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFxuICAgICAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlci5idWZmZXIuc2xpY2UoXG4gICAgICAgICAgICB0aGlzLl9ib2R5QXJyYXlCdWZmZXIuYnl0ZU9mZnNldCxcbiAgICAgICAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlci5ieXRlT2Zmc2V0ICsgdGhpcy5fYm9keUFycmF5QnVmZmVyLmJ5dGVMZW5ndGhcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUFycmF5QnVmZmVyKVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5ibG9iKSB7XG4gICAgICByZXR1cm4gdGhpcy5ibG9iKCkudGhlbihyZWFkQmxvYkFzQXJyYXlCdWZmZXIpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgYXMgQXJyYXlCdWZmZXInKVxuICAgIH1cbiAgfVxuXG4gIHRoaXMudGV4dCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciByZWplY3RlZCA9IGNvbnN1bWVkKHRoaXMpXG4gICAgaWYgKHJlamVjdGVkKSB7XG4gICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fYm9keUJsb2IpIHtcbiAgICAgIHJldHVybiByZWFkQmxvYkFzVGV4dCh0aGlzLl9ib2R5QmxvYilcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZWFkQXJyYXlCdWZmZXJBc1RleHQodGhpcy5fYm9keUFycmF5QnVmZmVyKSlcbiAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlGb3JtRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcmVhZCBGb3JtRGF0YSBib2R5IGFzIHRleHQnKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuX2JvZHlUZXh0KVxuICAgIH1cbiAgfVxuXG4gIGlmIChzdXBwb3J0LmZvcm1EYXRhKSB7XG4gICAgdGhpcy5mb3JtRGF0YSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oZGVjb2RlKVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuanNvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnRleHQoKS50aGVuKEpTT04ucGFyc2UpXG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vLyBIVFRQIG1ldGhvZHMgd2hvc2UgY2FwaXRhbGl6YXRpb24gc2hvdWxkIGJlIG5vcm1hbGl6ZWRcbnZhciBtZXRob2RzID0gWydDT05ORUNUJywgJ0RFTEVURScsICdHRVQnLCAnSEVBRCcsICdPUFRJT05TJywgJ1BBVENIJywgJ1BPU1QnLCAnUFVUJywgJ1RSQUNFJ11cblxuZnVuY3Rpb24gbm9ybWFsaXplTWV0aG9kKG1ldGhvZCkge1xuICB2YXIgdXBjYXNlZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gIHJldHVybiBtZXRob2RzLmluZGV4T2YodXBjYXNlZCkgPiAtMSA/IHVwY2FzZWQgOiBtZXRob2Rcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFJlcXVlc3QoaW5wdXQsIG9wdGlvbnMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFJlcXVlc3QpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignUGxlYXNlIHVzZSB0aGUgXCJuZXdcIiBvcGVyYXRvciwgdGhpcyBET00gb2JqZWN0IGNvbnN0cnVjdG9yIGNhbm5vdCBiZSBjYWxsZWQgYXMgYSBmdW5jdGlvbi4nKVxuICB9XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgdmFyIGJvZHkgPSBvcHRpb25zLmJvZHlcblxuICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBSZXF1ZXN0KSB7XG4gICAgaWYgKGlucHV0LmJvZHlVc2VkKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBbHJlYWR5IHJlYWQnKVxuICAgIH1cbiAgICB0aGlzLnVybCA9IGlucHV0LnVybFxuICAgIHRoaXMuY3JlZGVudGlhbHMgPSBpbnB1dC5jcmVkZW50aWFsc1xuICAgIGlmICghb3B0aW9ucy5oZWFkZXJzKSB7XG4gICAgICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhpbnB1dC5oZWFkZXJzKVxuICAgIH1cbiAgICB0aGlzLm1ldGhvZCA9IGlucHV0Lm1ldGhvZFxuICAgIHRoaXMubW9kZSA9IGlucHV0Lm1vZGVcbiAgICB0aGlzLnNpZ25hbCA9IGlucHV0LnNpZ25hbFxuICAgIGlmICghYm9keSAmJiBpbnB1dC5fYm9keUluaXQgIT0gbnVsbCkge1xuICAgICAgYm9keSA9IGlucHV0Ll9ib2R5SW5pdFxuICAgICAgaW5wdXQuYm9keVVzZWQgPSB0cnVlXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRoaXMudXJsID0gU3RyaW5nKGlucHV0KVxuICB9XG5cbiAgdGhpcy5jcmVkZW50aWFscyA9IG9wdGlvbnMuY3JlZGVudGlhbHMgfHwgdGhpcy5jcmVkZW50aWFscyB8fCAnc2FtZS1vcmlnaW4nXG4gIGlmIChvcHRpb25zLmhlYWRlcnMgfHwgIXRoaXMuaGVhZGVycykge1xuICAgIHRoaXMuaGVhZGVycyA9IG5ldyBIZWFkZXJzKG9wdGlvbnMuaGVhZGVycylcbiAgfVxuICB0aGlzLm1ldGhvZCA9IG5vcm1hbGl6ZU1ldGhvZChvcHRpb25zLm1ldGhvZCB8fCB0aGlzLm1ldGhvZCB8fCAnR0VUJylcbiAgdGhpcy5tb2RlID0gb3B0aW9ucy5tb2RlIHx8IHRoaXMubW9kZSB8fCBudWxsXG4gIHRoaXMuc2lnbmFsID0gb3B0aW9ucy5zaWduYWwgfHwgdGhpcy5zaWduYWwgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoJ0Fib3J0Q29udHJvbGxlcicgaW4gZykge1xuICAgICAgdmFyIGN0cmwgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgICByZXR1cm4gY3RybC5zaWduYWw7XG4gICAgfVxuICB9KCkpO1xuICB0aGlzLnJlZmVycmVyID0gbnVsbFxuXG4gIGlmICgodGhpcy5tZXRob2QgPT09ICdHRVQnIHx8IHRoaXMubWV0aG9kID09PSAnSEVBRCcpICYmIGJvZHkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdCb2R5IG5vdCBhbGxvd2VkIGZvciBHRVQgb3IgSEVBRCByZXF1ZXN0cycpXG4gIH1cbiAgdGhpcy5faW5pdEJvZHkoYm9keSlcblxuICBpZiAodGhpcy5tZXRob2QgPT09ICdHRVQnIHx8IHRoaXMubWV0aG9kID09PSAnSEVBRCcpIHtcbiAgICBpZiAob3B0aW9ucy5jYWNoZSA9PT0gJ25vLXN0b3JlJyB8fCBvcHRpb25zLmNhY2hlID09PSAnbm8tY2FjaGUnKSB7XG4gICAgICAvLyBTZWFyY2ggZm9yIGEgJ18nIHBhcmFtZXRlciBpbiB0aGUgcXVlcnkgc3RyaW5nXG4gICAgICB2YXIgcmVQYXJhbVNlYXJjaCA9IC8oWz8mXSlfPVteJl0qL1xuICAgICAgaWYgKHJlUGFyYW1TZWFyY2gudGVzdCh0aGlzLnVybCkpIHtcbiAgICAgICAgLy8gSWYgaXQgYWxyZWFkeSBleGlzdHMgdGhlbiBzZXQgdGhlIHZhbHVlIHdpdGggdGhlIGN1cnJlbnQgdGltZVxuICAgICAgICB0aGlzLnVybCA9IHRoaXMudXJsLnJlcGxhY2UocmVQYXJhbVNlYXJjaCwgJyQxXz0nICsgbmV3IERhdGUoKS5nZXRUaW1lKCkpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBPdGhlcndpc2UgYWRkIGEgbmV3ICdfJyBwYXJhbWV0ZXIgdG8gdGhlIGVuZCB3aXRoIHRoZSBjdXJyZW50IHRpbWVcbiAgICAgICAgdmFyIHJlUXVlcnlTdHJpbmcgPSAvXFw/L1xuICAgICAgICB0aGlzLnVybCArPSAocmVRdWVyeVN0cmluZy50ZXN0KHRoaXMudXJsKSA/ICcmJyA6ICc/JykgKyAnXz0nICsgbmV3IERhdGUoKS5nZXRUaW1lKClcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuUmVxdWVzdC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIG5ldyBSZXF1ZXN0KHRoaXMsIHtib2R5OiB0aGlzLl9ib2R5SW5pdH0pXG59XG5cbmZ1bmN0aW9uIGRlY29kZShib2R5KSB7XG4gIHZhciBmb3JtID0gbmV3IEZvcm1EYXRhKClcbiAgYm9keVxuICAgIC50cmltKClcbiAgICAuc3BsaXQoJyYnKVxuICAgIC5mb3JFYWNoKGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgICBpZiAoYnl0ZXMpIHtcbiAgICAgICAgdmFyIHNwbGl0ID0gYnl0ZXMuc3BsaXQoJz0nKVxuICAgICAgICB2YXIgbmFtZSA9IHNwbGl0LnNoaWZ0KCkucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgdmFyIHZhbHVlID0gc3BsaXQuam9pbignPScpLnJlcGxhY2UoL1xcKy9nLCAnICcpXG4gICAgICAgIGZvcm0uYXBwZW5kKGRlY29kZVVSSUNvbXBvbmVudChuYW1lKSwgZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSlcbiAgICAgIH1cbiAgICB9KVxuICByZXR1cm4gZm9ybVxufVxuXG5mdW5jdGlvbiBwYXJzZUhlYWRlcnMocmF3SGVhZGVycykge1xuICB2YXIgaGVhZGVycyA9IG5ldyBIZWFkZXJzKClcbiAgLy8gUmVwbGFjZSBpbnN0YW5jZXMgb2YgXFxyXFxuIGFuZCBcXG4gZm9sbG93ZWQgYnkgYXQgbGVhc3Qgb25lIHNwYWNlIG9yIGhvcml6b250YWwgdGFiIHdpdGggYSBzcGFjZVxuICAvLyBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzIzMCNzZWN0aW9uLTMuMlxuICB2YXIgcHJlUHJvY2Vzc2VkSGVhZGVycyA9IHJhd0hlYWRlcnMucmVwbGFjZSgvXFxyP1xcbltcXHQgXSsvZywgJyAnKVxuICAvLyBBdm9pZGluZyBzcGxpdCB2aWEgcmVnZXggdG8gd29yayBhcm91bmQgYSBjb21tb24gSUUxMSBidWcgd2l0aCB0aGUgY29yZS1qcyAzLjYuMCByZWdleCBwb2x5ZmlsbFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2l0aHViL2ZldGNoL2lzc3Vlcy83NDhcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzc1MVxuICBwcmVQcm9jZXNzZWRIZWFkZXJzXG4gICAgLnNwbGl0KCdcXHInKVxuICAgIC5tYXAoZnVuY3Rpb24oaGVhZGVyKSB7XG4gICAgICByZXR1cm4gaGVhZGVyLmluZGV4T2YoJ1xcbicpID09PSAwID8gaGVhZGVyLnN1YnN0cigxLCBoZWFkZXIubGVuZ3RoKSA6IGhlYWRlclxuICAgIH0pXG4gICAgLmZvckVhY2goZnVuY3Rpb24obGluZSkge1xuICAgICAgdmFyIHBhcnRzID0gbGluZS5zcGxpdCgnOicpXG4gICAgICB2YXIga2V5ID0gcGFydHMuc2hpZnQoKS50cmltKClcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gcGFydHMuam9pbignOicpLnRyaW0oKVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGhlYWRlcnMuYXBwZW5kKGtleSwgdmFsdWUpXG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdSZXNwb25zZSAnICsgZXJyb3IubWVzc2FnZSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pXG4gIHJldHVybiBoZWFkZXJzXG59XG5cbkJvZHkuY2FsbChSZXF1ZXN0LnByb3RvdHlwZSlcblxuZXhwb3J0IGZ1bmN0aW9uIFJlc3BvbnNlKGJvZHlJbml0LCBvcHRpb25zKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSZXNwb25zZSkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdQbGVhc2UgdXNlIHRoZSBcIm5ld1wiIG9wZXJhdG9yLCB0aGlzIERPTSBvYmplY3QgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLicpXG4gIH1cbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHt9XG4gIH1cblxuICB0aGlzLnR5cGUgPSAnZGVmYXVsdCdcbiAgdGhpcy5zdGF0dXMgPSBvcHRpb25zLnN0YXR1cyA9PT0gdW5kZWZpbmVkID8gMjAwIDogb3B0aW9ucy5zdGF0dXNcbiAgaWYgKHRoaXMuc3RhdHVzIDwgMjAwIHx8IHRoaXMuc3RhdHVzID4gNTk5KSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJGYWlsZWQgdG8gY29uc3RydWN0ICdSZXNwb25zZSc6IFRoZSBzdGF0dXMgcHJvdmlkZWQgKDApIGlzIG91dHNpZGUgdGhlIHJhbmdlIFsyMDAsIDU5OV0uXCIpXG4gIH1cbiAgdGhpcy5vayA9IHRoaXMuc3RhdHVzID49IDIwMCAmJiB0aGlzLnN0YXR1cyA8IDMwMFxuICB0aGlzLnN0YXR1c1RleHQgPSBvcHRpb25zLnN0YXR1c1RleHQgPT09IHVuZGVmaW5lZCA/ICcnIDogJycgKyBvcHRpb25zLnN0YXR1c1RleHRcbiAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICB0aGlzLnVybCA9IG9wdGlvbnMudXJsIHx8ICcnXG4gIHRoaXMuX2luaXRCb2R5KGJvZHlJbml0KVxufVxuXG5Cb2R5LmNhbGwoUmVzcG9uc2UucHJvdG90eXBlKVxuXG5SZXNwb25zZS5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIG5ldyBSZXNwb25zZSh0aGlzLl9ib2R5SW5pdCwge1xuICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgc3RhdHVzVGV4dDogdGhpcy5zdGF0dXNUZXh0LFxuICAgIGhlYWRlcnM6IG5ldyBIZWFkZXJzKHRoaXMuaGVhZGVycyksXG4gICAgdXJsOiB0aGlzLnVybFxuICB9KVxufVxuXG5SZXNwb25zZS5lcnJvciA9IGZ1bmN0aW9uKCkge1xuICB2YXIgcmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UobnVsbCwge3N0YXR1czogMjAwLCBzdGF0dXNUZXh0OiAnJ30pXG4gIHJlc3BvbnNlLm9rID0gZmFsc2VcbiAgcmVzcG9uc2Uuc3RhdHVzID0gMFxuICByZXNwb25zZS50eXBlID0gJ2Vycm9yJ1xuICByZXR1cm4gcmVzcG9uc2Vcbn1cblxudmFyIHJlZGlyZWN0U3RhdHVzZXMgPSBbMzAxLCAzMDIsIDMwMywgMzA3LCAzMDhdXG5cblJlc3BvbnNlLnJlZGlyZWN0ID0gZnVuY3Rpb24odXJsLCBzdGF0dXMpIHtcbiAgaWYgKHJlZGlyZWN0U3RhdHVzZXMuaW5kZXhPZihzdGF0dXMpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbnZhbGlkIHN0YXR1cyBjb2RlJylcbiAgfVxuXG4gIHJldHVybiBuZXcgUmVzcG9uc2UobnVsbCwge3N0YXR1czogc3RhdHVzLCBoZWFkZXJzOiB7bG9jYXRpb246IHVybH19KVxufVxuXG5leHBvcnQgdmFyIERPTUV4Y2VwdGlvbiA9IGcuRE9NRXhjZXB0aW9uXG50cnkge1xuICBuZXcgRE9NRXhjZXB0aW9uKClcbn0gY2F0Y2ggKGVycikge1xuICBET01FeGNlcHRpb24gPSBmdW5jdGlvbihtZXNzYWdlLCBuYW1lKSB7XG4gICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZVxuICAgIHRoaXMubmFtZSA9IG5hbWVcbiAgICB2YXIgZXJyb3IgPSBFcnJvcihtZXNzYWdlKVxuICAgIHRoaXMuc3RhY2sgPSBlcnJvci5zdGFja1xuICB9XG4gIERPTUV4Y2VwdGlvbi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSlcbiAgRE9NRXhjZXB0aW9uLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IERPTUV4Y2VwdGlvblxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmV0Y2goaW5wdXQsIGluaXQpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHZhciByZXF1ZXN0ID0gbmV3IFJlcXVlc3QoaW5wdXQsIGluaXQpXG5cbiAgICBpZiAocmVxdWVzdC5zaWduYWwgJiYgcmVxdWVzdC5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgcmV0dXJuIHJlamVjdChuZXcgRE9NRXhjZXB0aW9uKCdBYm9ydGVkJywgJ0Fib3J0RXJyb3InKSlcbiAgICB9XG5cbiAgICB2YXIgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KClcblxuICAgIGZ1bmN0aW9uIGFib3J0WGhyKCkge1xuICAgICAgeGhyLmFib3J0KClcbiAgICB9XG5cbiAgICB4aHIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHtcbiAgICAgICAgc3RhdHVzVGV4dDogeGhyLnN0YXR1c1RleHQsXG4gICAgICAgIGhlYWRlcnM6IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkgfHwgJycpXG4gICAgICB9XG4gICAgICAvLyBUaGlzIGNoZWNrIGlmIHNwZWNpZmljYWxseSBmb3Igd2hlbiBhIHVzZXIgZmV0Y2hlcyBhIGZpbGUgbG9jYWxseSBmcm9tIHRoZSBmaWxlIHN5c3RlbVxuICAgICAgLy8gT25seSBpZiB0aGUgc3RhdHVzIGlzIG91dCBvZiBhIG5vcm1hbCByYW5nZVxuICAgICAgaWYgKHJlcXVlc3QudXJsLmluZGV4T2YoJ2ZpbGU6Ly8nKSA9PT0gMCAmJiAoeGhyLnN0YXR1cyA8IDIwMCB8fCB4aHIuc3RhdHVzID4gNTk5KSkge1xuICAgICAgICBvcHRpb25zLnN0YXR1cyA9IDIwMDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9wdGlvbnMuc3RhdHVzID0geGhyLnN0YXR1cztcbiAgICAgIH1cbiAgICAgIG9wdGlvbnMudXJsID0gJ3Jlc3BvbnNlVVJMJyBpbiB4aHIgPyB4aHIucmVzcG9uc2VVUkwgOiBvcHRpb25zLmhlYWRlcnMuZ2V0KCdYLVJlcXVlc3QtVVJMJylcbiAgICAgIHZhciBib2R5ID0gJ3Jlc3BvbnNlJyBpbiB4aHIgPyB4aHIucmVzcG9uc2UgOiB4aHIucmVzcG9uc2VUZXh0XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICByZXNvbHZlKG5ldyBSZXNwb25zZShib2R5LCBvcHRpb25zKSlcbiAgICAgIH0sIDApXG4gICAgfVxuXG4gICAgeGhyLm9uZXJyb3IgPSBmdW5jdGlvbigpIHtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChuZXcgVHlwZUVycm9yKCdOZXR3b3JrIHJlcXVlc3QgZmFpbGVkJykpXG4gICAgICB9LCAwKVxuICAgIH1cblxuICAgIHhoci5vbnRpbWVvdXQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChuZXcgVHlwZUVycm9yKCdOZXR3b3JrIHJlcXVlc3QgdGltZWQgb3V0JykpXG4gICAgICB9LCAwKVxuICAgIH1cblxuICAgIHhoci5vbmFib3J0ID0gZnVuY3Rpb24oKSB7XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICByZWplY3QobmV3IERPTUV4Y2VwdGlvbignQWJvcnRlZCcsICdBYm9ydEVycm9yJykpXG4gICAgICB9LCAwKVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZpeFVybCh1cmwpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB1cmwgPT09ICcnICYmIGcubG9jYXRpb24uaHJlZiA/IGcubG9jYXRpb24uaHJlZiA6IHVybFxuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gdXJsXG4gICAgICB9XG4gICAgfVxuXG4gICAgeGhyLm9wZW4ocmVxdWVzdC5tZXRob2QsIGZpeFVybChyZXF1ZXN0LnVybCksIHRydWUpXG5cbiAgICBpZiAocmVxdWVzdC5jcmVkZW50aWFscyA9PT0gJ2luY2x1ZGUnKSB7XG4gICAgICB4aHIud2l0aENyZWRlbnRpYWxzID0gdHJ1ZVxuICAgIH0gZWxzZSBpZiAocmVxdWVzdC5jcmVkZW50aWFscyA9PT0gJ29taXQnKSB7XG4gICAgICB4aHIud2l0aENyZWRlbnRpYWxzID0gZmFsc2VcbiAgICB9XG5cbiAgICBpZiAoJ3Jlc3BvbnNlVHlwZScgaW4geGhyKSB7XG4gICAgICBpZiAoc3VwcG9ydC5ibG9iKSB7XG4gICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYmxvYidcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHN1cHBvcnQuYXJyYXlCdWZmZXJcbiAgICAgICkge1xuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gJ2FycmF5YnVmZmVyJ1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpbml0ICYmIHR5cGVvZiBpbml0LmhlYWRlcnMgPT09ICdvYmplY3QnICYmICEoaW5pdC5oZWFkZXJzIGluc3RhbmNlb2YgSGVhZGVycyB8fCAoZy5IZWFkZXJzICYmIGluaXQuaGVhZGVycyBpbnN0YW5jZW9mIGcuSGVhZGVycykpKSB7XG4gICAgICB2YXIgbmFtZXMgPSBbXTtcbiAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGluaXQuaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbihuYW1lKSB7XG4gICAgICAgIG5hbWVzLnB1c2gobm9ybWFsaXplTmFtZShuYW1lKSlcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIobmFtZSwgbm9ybWFsaXplVmFsdWUoaW5pdC5oZWFkZXJzW25hbWVdKSlcbiAgICAgIH0pXG4gICAgICByZXF1ZXN0LmhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgICBpZiAobmFtZXMuaW5kZXhPZihuYW1lKSA9PT0gLTEpIHtcbiAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihuYW1lLCB2YWx1ZSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgcmVxdWVzdC5oZWFkZXJzLmZvckVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgICAgICAgeGhyLnNldFJlcXVlc3RIZWFkZXIobmFtZSwgdmFsdWUpXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChyZXF1ZXN0LnNpZ25hbCkge1xuICAgICAgcmVxdWVzdC5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBhYm9ydFhocilcblxuICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAvLyBET05FIChzdWNjZXNzIG9yIGZhaWx1cmUpXG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgIHJlcXVlc3Quc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgYWJvcnRYaHIpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB4aHIuc2VuZCh0eXBlb2YgcmVxdWVzdC5fYm9keUluaXQgPT09ICd1bmRlZmluZWQnID8gbnVsbCA6IHJlcXVlc3QuX2JvZHlJbml0KVxuICB9KVxufVxuXG5mZXRjaC5wb2x5ZmlsbCA9IHRydWVcblxuaWYgKCFnLmZldGNoKSB7XG4gIGcuZmV0Y2ggPSBmZXRjaFxuICBnLkhlYWRlcnMgPSBIZWFkZXJzXG4gIGcuUmVxdWVzdCA9IFJlcXVlc3RcbiAgZy5SZXNwb25zZSA9IFJlc3BvbnNlXG59XG4iLCJleHBvcnQgY29uc3QgTUFYX0RFQ0lNQUxTID0gNjtcbmV4cG9ydCBjb25zdCBERUZBVUxUX0JMRU5EX1NURVBTID0gNTtcbmV4cG9ydCBjb25zdCBERUZBVUxUX1NIQURFU19USU5UU19TVEVQUyA9IDU7XG5leHBvcnQgY29uc3QgQkFTRV8yNTUgPSAyNTU7XG5leHBvcnQgY29uc3QgTUFYX0hVRSA9IDM2MDtcbmV4cG9ydCBjb25zdCBNQVhfUENFTlQgPSAxMDA7XG5leHBvcnQgY29uc3QgTUFYX0FMUEhBID0gMTtcbmV4cG9ydCBjb25zdCBNQVhfTEFCID0gMTI1O1xuZXhwb3J0IGNvbnN0IE1BWF9MQ0hfQyA9IDE1MDtcbiIsImV4cG9ydCB2YXIgQ29sb3JNb2RlbDtcbihmdW5jdGlvbiAoQ29sb3JNb2RlbCkge1xuICAgIENvbG9yTW9kZWxbXCJIRVhcIl0gPSBcIkhFWFwiO1xuICAgIENvbG9yTW9kZWxbXCJSR0JcIl0gPSBcIlJHQlwiO1xuICAgIENvbG9yTW9kZWxbXCJIV0JcIl0gPSBcIkhXQlwiO1xuICAgIENvbG9yTW9kZWxbXCJIU0xcIl0gPSBcIkhTTFwiO1xuICAgIENvbG9yTW9kZWxbXCJDSUVMYWJcIl0gPSBcIkNJRUxhYlwiO1xuICAgIENvbG9yTW9kZWxbXCJMQ0hcIl0gPSBcIkxDSFwiO1xuICAgIENvbG9yTW9kZWxbXCJDTVlLXCJdID0gXCJDTVlLXCI7XG59KShDb2xvck1vZGVsIHx8IChDb2xvck1vZGVsID0ge30pKTtcbmV4cG9ydCB2YXIgSGFybW9ueTtcbihmdW5jdGlvbiAoSGFybW9ueSkge1xuICAgIEhhcm1vbnlbXCJBTkFMT0dPVVNcIl0gPSBcIkFOQUxPR09VU1wiO1xuICAgIEhhcm1vbnlbXCJDT01QTEVNRU5UQVJZXCJdID0gXCJDT01QTEVNRU5UQVJZXCI7XG4gICAgSGFybW9ueVtcIlNQTElUX0NPTVBMRU1FTlRBUllcIl0gPSBcIlNQTElUX0NPTVBMRU1FTlRBUllcIjtcbiAgICBIYXJtb255W1wiVFJJQURJQ1wiXSA9IFwiVFJJQURJQ1wiO1xuICAgIEhhcm1vbnlbXCJURVRSQURJQ1wiXSA9IFwiVEVUUkFESUNcIjtcbiAgICBIYXJtb255W1wiU1FVQVJFXCJdID0gXCJTUVVBUkVcIjtcbn0pKEhhcm1vbnkgfHwgKEhhcm1vbnkgPSB7fSkpO1xuZXhwb3J0IHZhciBNaXg7XG4oZnVuY3Rpb24gKE1peCkge1xuICAgIE1peFtcIkFERElUSVZFXCJdID0gXCJBRERJVElWRVwiO1xuICAgIE1peFtcIlNVQlRSQUNUSVZFXCJdID0gXCJTVUJUUkFDVElWRVwiO1xufSkoTWl4IHx8IChNaXggPSB7fSkpO1xuZXhwb3J0IHZhciBDb2xvcktleXdvcmRzO1xuKGZ1bmN0aW9uIChDb2xvcktleXdvcmRzKSB7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJsYWNrXCJdID0gXCIjMDAwMDAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNpbHZlclwiXSA9IFwiI0MwQzBDMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJncmF5XCJdID0gXCIjODA4MDgwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIndoaXRlXCJdID0gXCIjRkZGRkZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1hcm9vblwiXSA9IFwiIzgwMDAwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJyZWRcIl0gPSBcIiNGRjAwMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicHVycGxlXCJdID0gXCIjODAwMDgwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImZ1Y2hzaWFcIl0gPSBcIiNGRjAwRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ3JlZW5cIl0gPSBcIiMwMDgwMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGltZVwiXSA9IFwiIzAwRkYwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJvbGl2ZVwiXSA9IFwiIzgwODAwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ5ZWxsb3dcIl0gPSBcIiNGRkZGMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibmF2eVwiXSA9IFwiIzAwMDA4MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJibHVlXCJdID0gXCIjMDAwMEZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInRlYWxcIl0gPSBcIiMwMDgwODBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYXF1YVwiXSA9IFwiIzAwRkZGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJvcmFuZ2VcIl0gPSBcIiNGRkE1MDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYWxpY2VibHVlXCJdID0gXCIjRjBGOEZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImFudGlxdWV3aGl0ZVwiXSA9IFwiI0ZBRUJEN1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJhcXVhbWFyaW5lXCJdID0gXCIjN0ZGRkQ0XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImF6dXJlXCJdID0gXCIjRjBGRkZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJlaWdlXCJdID0gXCIjRjVGNURDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJpc3F1ZVwiXSA9IFwiI0ZGRTRDNFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJibGFuY2hlZGFsbW9uZFwiXSA9IFwiI0ZGRUJDRFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJibHVldmlvbGV0XCJdID0gXCIjOEEyQkUyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJyb3duXCJdID0gXCIjQTUyQTJBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJ1cmx5d29vZFwiXSA9IFwiI0RFQjg4N1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjYWRldGJsdWVcIl0gPSBcIiM1RjlFQTBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiY2hhcnRyZXVzZVwiXSA9IFwiIzdGRkYwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjaG9jb2xhdGVcIl0gPSBcIiNEMjY5MUVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiY29yYWxcIl0gPSBcIiNGRjdGNTBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiY29ybmZsb3dlcmJsdWVcIl0gPSBcIiM2NDk1RURcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiY29ybnNpbGtcIl0gPSBcIiNGRkY4RENcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiY3JpbXNvblwiXSA9IFwiI0RDMTQzQ1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjeWFuXCJdID0gXCIjMDBGRkZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtibHVlXCJdID0gXCIjMDAwMDhCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtjeWFuXCJdID0gXCIjMDA4QjhCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtnb2xkZW5yb2RcIl0gPSBcIiNCODg2MEJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2dyYXlcIl0gPSBcIiNBOUE5QTlcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2dyZWVuXCJdID0gXCIjMDA2NDAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtncmV5XCJdID0gXCIjQTlBOUE5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtraGFraVwiXSA9IFwiI0JEQjc2QlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrbWFnZW50YVwiXSA9IFwiIzhCMDA4QlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrb2xpdmVncmVlblwiXSA9IFwiIzU1NkIyRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrb3JhbmdlXCJdID0gXCIjRkY4QzAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtvcmNoaWRcIl0gPSBcIiM5OTMyQ0NcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya3JlZFwiXSA9IFwiIzhCMDAwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrc2FsbW9uXCJdID0gXCIjRTk5NjdBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtzZWFncmVlblwiXSA9IFwiIzhGQkM4RlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrc2xhdGVibHVlXCJdID0gXCIjNDgzRDhCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtzbGF0ZWdyYXlcIl0gPSBcIiMyRjRGNEZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya3NsYXRlZ3JleVwiXSA9IFwiIzJGNEY0RlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrdHVycXVvaXNlXCJdID0gXCIjMDBDRUQxXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmt2aW9sZXRcIl0gPSBcIiM5NDAwRDNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGVlcHBpbmtcIl0gPSBcIiNGRjE0OTNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGVlcHNreWJsdWVcIl0gPSBcIiMwMEJGRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGltZ3JheVwiXSA9IFwiIzY5Njk2OVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkaW1ncmV5XCJdID0gXCIjNjk2OTY5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRvZGdlcmJsdWVcIl0gPSBcIiMxRTkwRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZmlyZWJyaWNrXCJdID0gXCIjQjIyMjIyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImZsb3JhbHdoaXRlXCJdID0gXCIjRkZGQUYwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImZvcmVzdGdyZWVuXCJdID0gXCIjMjI4QjIyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdhaW5zYm9yb1wiXSA9IFwiI0RDRENEQ1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJnaG9zdHdoaXRlXCJdID0gXCIjRjhGOEZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdvbGRcIl0gPSBcIiNGRkQ3MDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ29sZGVucm9kXCJdID0gXCIjREFBNTIwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdyZWVueWVsbG93XCJdID0gXCIjQURGRjJGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdyZXlcIl0gPSBcIiM4MDgwODBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiaG9uZXlkZXdcIl0gPSBcIiNGMEZGRjBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiaG90cGlua1wiXSA9IFwiI0ZGNjlCNFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJpbmRpYW5yZWRcIl0gPSBcIiNDRDVDNUNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiaW5kaWdvXCJdID0gXCIjNEIwMDgyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIml2b3J5XCJdID0gXCIjRkZGRkYwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImtoYWtpXCJdID0gXCIjRjBFNjhDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxhdmVuZGVyXCJdID0gXCIjRTZFNkZBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxhdmVuZGVyYmx1c2hcIl0gPSBcIiNGRkYwRjVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGF3bmdyZWVuXCJdID0gXCIjN0NGQzAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxlbW9uY2hpZmZvblwiXSA9IFwiI0ZGRkFDRFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGJsdWVcIl0gPSBcIiNBREQ4RTZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRjb3JhbFwiXSA9IFwiI0YwODA4MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGN5YW5cIl0gPSBcIiNFMEZGRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRnb2xkZW5yb2R5ZWxsb3dcIl0gPSBcIiNGQUZBRDJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRncmF5XCJdID0gXCIjRDNEM0QzXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0Z3JlZW5cIl0gPSBcIiM5MEVFOTBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRncmV5XCJdID0gXCIjRDNEM0QzXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0cGlua1wiXSA9IFwiI0ZGQjZDMVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHNhbG1vblwiXSA9IFwiI0ZGQTA3QVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHNlYWdyZWVuXCJdID0gXCIjMjBCMkFBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c2t5Ymx1ZVwiXSA9IFwiIzg3Q0VGQVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHNsYXRlZ3JheVwiXSA9IFwiIzc3ODg5OVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHNsYXRlZ3JleVwiXSA9IFwiIzc3ODg5OVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHN0ZWVsYmx1ZVwiXSA9IFwiI0IwQzRERVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodHllbGxvd1wiXSA9IFwiI0ZGRkZFMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaW1lZ3JlZW5cIl0gPSBcIiMzMkNEMzJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGluZW5cIl0gPSBcIiNGQUYwRTZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWFnZW50YVwiXSA9IFwiI0ZGMDBGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW1hcXVhbWFyaW5lXCJdID0gXCIjNjZDREFBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bWJsdWVcIl0gPSBcIiMwMDAwQ0RcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtb3JjaGlkXCJdID0gXCIjQkE1NUQzXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bXB1cnBsZVwiXSA9IFwiIzkzNzBEQlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW1zZWFncmVlblwiXSA9IFwiIzNDQjM3MVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW1zbGF0ZWJsdWVcIl0gPSBcIiM3QjY4RUVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtc3ByaW5nZ3JlZW5cIl0gPSBcIiMwMEZBOUFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtdHVycXVvaXNlXCJdID0gXCIjNDhEMUNDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bXZpb2xldHJlZFwiXSA9IFwiI0M3MTU4NVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtaWRuaWdodGJsdWVcIl0gPSBcIiMxOTE5NzBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWludGNyZWFtXCJdID0gXCIjRjVGRkZBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1pc3R5cm9zZVwiXSA9IFwiI0ZGRTRFMVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtb2NjYXNpblwiXSA9IFwiI0ZGRTRCNVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJuYXZham93aGl0ZVwiXSA9IFwiI0ZGREVBRFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJvbGRsYWNlXCJdID0gXCIjRkRGNUU2XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm9saXZlZHJhYlwiXSA9IFwiIzZCOEUyM1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJvcmFuZ2VyZWRcIl0gPSBcIiNGRjQ1MDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wib3JjaGlkXCJdID0gXCIjREE3MEQ2XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBhbGVnb2xkZW5yb2RcIl0gPSBcIiNFRUU4QUFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGFsZWdyZWVuXCJdID0gXCIjOThGQjk4XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBhbGV0dXJxdW9pc2VcIl0gPSBcIiNBRkVFRUVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGFsZXZpb2xldHJlZFwiXSA9IFwiI0RCNzA5M1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwYXBheWF3aGlwXCJdID0gXCIjRkZFRkQ1XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBlYWNocHVmZlwiXSA9IFwiI0ZGREFCOVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwZXJ1XCJdID0gXCIjQ0Q4NTNGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBpbmtcIl0gPSBcIiNGRkMwQ0JcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGx1bVwiXSA9IFwiI0REQTBERFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwb3dkZXJibHVlXCJdID0gXCIjQjBFMEU2XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInJvc3licm93blwiXSA9IFwiI0JDOEY4RlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJyb3lhbGJsdWVcIl0gPSBcIiM0MTY5RTFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2FkZGxlYnJvd25cIl0gPSBcIiM4QjQ1MTNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2FsbW9uXCJdID0gXCIjRkE4MDcyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNhbmR5YnJvd25cIl0gPSBcIiNGNEE0NjBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2VhZ3JlZW5cIl0gPSBcIiMyRThCNTdcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2Vhc2hlbGxcIl0gPSBcIiNGRkY1RUVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2llbm5hXCJdID0gXCIjQTA1MjJEXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNreWJsdWVcIl0gPSBcIiM4N0NFRUJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2xhdGVibHVlXCJdID0gXCIjNkE1QUNEXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNsYXRlZ3JheVwiXSA9IFwiIzcwODA5MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzbGF0ZWdyZXlcIl0gPSBcIiM3MDgwOTBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic25vd1wiXSA9IFwiI0ZGRkFGQVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzcHJpbmdncmVlblwiXSA9IFwiIzAwRkY3RlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzdGVlbGJsdWVcIl0gPSBcIiM0NjgyQjRcIjtcbiAgICBDb2xvcktleXdvcmRzW1widGFuXCJdID0gXCIjRDJCNDhDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInRoaXN0bGVcIl0gPSBcIiNEOEJGRDhcIjtcbiAgICBDb2xvcktleXdvcmRzW1widG9tYXRvXCJdID0gXCIjRkY2MzQ3XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInR1cnF1b2lzZVwiXSA9IFwiIzQwRTBEMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ2aW9sZXRcIl0gPSBcIiNFRTgyRUVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wid2hlYXRcIl0gPSBcIiNGNURFQjNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wid2hpdGVzbW9rZVwiXSA9IFwiI0Y1RjVGNVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ5ZWxsb3dncmVlblwiXSA9IFwiIzlBQ0QzMlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJyZWJlY2NhcHVycGxlXCJdID0gXCIjNjYzMzk5XCI7XG59KShDb2xvcktleXdvcmRzIHx8IChDb2xvcktleXdvcmRzID0ge30pKTtcbmV4cG9ydCBjb25zdCBDT0xPUl9LRVlTID0gT2JqZWN0LmtleXMoQ29sb3JLZXl3b3Jkcyk7XG5leHBvcnQgY29uc3QgQ09MT1JfUFJPUFMgPSB7XG4gICAgSEVYOiBbJ1InLCAnRycsICdCJywgJ0EnXSxcbiAgICBSR0I6IFsnUicsICdHJywgJ0InLCAnQSddLFxuICAgIEhTTDogWydIJywgJ1MnLCAnTCcsICdBJ10sXG4gICAgSFdCOiBbJ0gnLCAnVycsICdCJywgJ0EnXSxcbiAgICBDSUVMYWI6IFsnTCcsICdhJywgJ2InLCAnQSddLFxuICAgIExDSDogWydMJywgJ0MnLCAnSCcsICdBJ10sXG4gICAgQ01ZSzogWydDJywgJ00nLCAnWScsICdLJywgJ0EnXVxufTtcbmV4cG9ydCBjb25zdCBWQUxJRF9DT0xPUl9PQkpFQ1RTID0ge1xuICAgIEFCR1I6IENvbG9yTW9kZWwuUkdCLFxuICAgIEFCSFc6IENvbG9yTW9kZWwuSFdCLFxuICAgIEFDSEw6IENvbG9yTW9kZWwuTENILFxuICAgIEFDS01ZOiBDb2xvck1vZGVsLkNNWUssXG4gICAgQUhMUzogQ29sb3JNb2RlbC5IU0wsXG4gICAgQUxBQjogQ29sb3JNb2RlbC5DSUVMYWIsXG4gICAgQkdSOiBDb2xvck1vZGVsLlJHQixcbiAgICBCSFc6IENvbG9yTW9kZWwuSFdCLFxuICAgIENITDogQ29sb3JNb2RlbC5MQ0gsXG4gICAgQ0tNWTogQ29sb3JNb2RlbC5DTVlLLFxuICAgIEhMUzogQ29sb3JNb2RlbC5IU0wsXG4gICAgTEFCOiBDb2xvck1vZGVsLkNJRUxhYlxufTtcbmV4cG9ydCB2YXIgVHlwZU9mO1xuKGZ1bmN0aW9uIChUeXBlT2YpIHtcbiAgICBUeXBlT2ZbXCJOVU1CRVJcIl0gPSBcIm51bWJlclwiO1xuICAgIFR5cGVPZltcIkJPT0xFQU5cIl0gPSBcImJvb2xlYW5cIjtcbn0pKFR5cGVPZiB8fCAoVHlwZU9mID0ge30pKTtcbiIsImltcG9ydCB7IENvbG9yTW9kZWwgfSBmcm9tICcuL2VudW1zJztcbmV4cG9ydCBjb25zdCBDT0xPUlJFR1MgPSB7XG4gICAgW0NvbG9yTW9kZWwuSEVYXTogL14jKD86KD88cj5bYS1mXFxkXSkoPzxnPlthLWZcXGRdKSg/PGI+W2EtZlxcZF0pKD88YT5bYS1mXFxkXSk/fCg/PHJyPlthLWZcXGRdezJ9KSg/PGdnPlthLWZcXGRdezJ9KSg/PGJiPlthLWZcXGRdezJ9KSg/PGFhPlthLWZcXGRdezJ9KT8pJC9pLFxuICAgIFtDb2xvck1vZGVsLlJHQl06IC9ecmdiYT9cXHMqXFwoXFxzKig/Oig/PHJfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCslPylcXHMqLFxccyooPzxnX2xlZ2FjeT4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKixcXHMqKD88Yl9sZWdhY3k+KD86XFxkKlxcLik/XFxkKyU/KSg/OlxccyosXFxzKig/PGFfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCspKT98KD88cj4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PGc+KD86XFxkKlxcLik/XFxkKyU/KVxccysoPzxiPig/OlxcZCpcXC4pP1xcZCslPykoPzpcXHMqXFwvXFxzKig/PGE+KD86XFxkKlxcLik/XFxkKyU/KSk/fGZyb21cXHMrKD88ZnJvbT4oPzpcXHcrfFxcdytcXChcXHMqW14oKSldK1xccypcXCl8XFx3K1xcKGZyb21cXHMrXFx3K1xcKC4qXFwpXFxzKlxcKXwjW2EtZkEtRlxcZF0rKSlcXHMrKD88cmVsYXRpdmVfcj4oPzpbcmdiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbcmdiKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV9nPig/OltyZ2JdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtyZ2IoKS8qXFwtK1xcZC5cXHNdK1xcKSkpXFxzKyg/PHJlbGF0aXZlX2I+KD86W3JnYl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW3JnYigpLypcXC0rXFxkLlxcc10rXFwpKSkoPzpcXHMqXFwvXFxzKig/PHJlbGF0aXZlX2E+KD86KD86XFxkKlxcLik/XFxkKyU/fGNhbGNcXChbKCkvKlxcLStcXGQuXFxzXFx3XSooPzphbHBoYSk/WygpLypcXC0rXFxkLlxcc1xcd10qXFwpfGFscGhhKSkpPylcXHMqXFwpJC8sXG4gICAgW0NvbG9yTW9kZWwuSFdCXTogL15od2JcXHMqXFwoXFxzKig/Oig/PGg+KD86XFxkKlxcLik/XFxkKyg/OmRlZ3xncmFkfHJhZHx0dXJuKT8pXFxzKyg/PHc+KD86XFxkKlxcLik/XFxkKyklXFxzKyg/PGI+KD86XFxkKlxcLik/XFxkKyklKD86XFxzKlxcL1xccyooPzxhPig/OlxcZCpcXC4pP1xcZCslPykpP3xmcm9tXFxzKyg/PGZyb20+KD86XFx3K3xcXHcrXFwoXFxzKlteKCkpXStcXHMqXFwpfFxcdytcXChmcm9tXFxzK1xcdytcXCguKlxcKVxccypcXCl8I1thLWZBLUZcXGRdKykpXFxzKyg/PHJlbGF0aXZlX2g+KD86W2h3Yl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2h3YigpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfdz4oPzpbaHdiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHdiKCkvKlxcLStcXGQuXFxzXStcXCkpKSU/XFxzKyg/PHJlbGF0aXZlX2I+KD86W2h3Yl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2h3YigpLypcXC0rXFxkLlxcc10rXFwpKSklPyg/OlxccypcXC9cXHMqKD88cmVsYXRpdmVfYT4oPzooPzpcXGQqXFwuKT9cXGQrJT98Y2FsY1xcKFsoKS8qXFwtK1xcZC5cXHNcXHddKig/OmFscGhhKT9bKCkvKlxcLStcXGQuXFxzXFx3XSpcXCl8YWxwaGEpKSk/KVxccypcXCkkLyxcbiAgICBbQ29sb3JNb2RlbC5IU0xdOiAvXmhzbGE/XFxzKlxcKFxccyooPzooPzxoX2xlZ2FjeT4tPyg/OlxcZCpcXC4pP1xcZCsoPzpkZWd8Z3JhZHxyYWR8dHVybik/KVxccyosXFxzKig/PHNfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCspJVxccyosXFxzKig/PGxfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCspJSg/OlxccyosXFxzKig/PGFfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCspKT98KD88aD4tPyg/OlxcZCpcXC4pP1xcZCsoPzpkZWd8Z3JhZHxyYWR8dHVybik/KVxccysoPzxzPig/OlxcZCpcXC4pP1xcZCspJT9cXHMrKD88bD4oPzpcXGQqXFwuKT9cXGQrKSU/KD86XFxzKlxcL1xccyooPzxhPig/OlxcZCpcXC4pP1xcZCslPykpP3xmcm9tXFxzKyg/PGZyb20+KD86XFx3K3xcXHcrXFwoXFxzKlteKCkpXStcXHMqXFwpfFxcdytcXChmcm9tXFxzK1xcdytcXCguKlxcKVxccypcXCl8I1thLWZBLUZcXGRdKykpXFxzKyg/PHJlbGF0aXZlX2g+KD86W2hzbF18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2hzbCgpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfcz4oPzpbaHNsXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHNsKCkvKlxcLStcXGQuXFxzXStcXCkpKSU/XFxzKyg/PHJlbGF0aXZlX2w+KD86W2hzbF18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2hzbCgpLypcXC0rXFxkLlxcc10rXFwpKSklPyg/OlxccypcXC9cXHMqKD88cmVsYXRpdmVfYT4oPzooPzpcXGQqXFwuKT9cXGQrJT98Y2FsY1xcKFsoKS8qXFwtK1xcZC5cXHNcXHddKig/OmFscGhhKT9bKCkvKlxcLStcXGQuXFxzXFx3XSpcXCl8YWxwaGEpKSk/KVxccypcXCkkLyxcbiAgICBbQ29sb3JNb2RlbC5DSUVMYWJdOiAvXmxhYlxccypcXChcXHMqKD86KD88TD4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PGE+LT8oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PGI+LT8oPzpcXGQqXFwuKT9cXGQrJT8pKD86XFxzKlxcL1xccyooPzxBPig/OlxcZCpcXC4pP1xcZCslPykpP3xmcm9tXFxzKyg/PGZyb20+KD86XFx3K3xcXHcrXFwoXFxzKlteKCkpXStcXHMqXFwpfFxcdytcXChmcm9tXFxzK1xcdytcXCguKlxcKVxccypcXCl8I1thLWZBLUZcXGRdKykpXFxzKyg/PHJlbGF0aXZlX0w+KD86W2xhYl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2xhYigpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfYT4oPzpbbGFiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbbGFiKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV9iPig/OltsYWJdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtsYWIoKS8qXFwtK1xcZC5cXHNdK1xcKSkpKD86XFxzKlxcL1xccyooPzxyZWxhdGl2ZV9BPig/Oig/OlxcZCpcXC4pP1xcZCslP3xjYWxjXFwoWygpLypcXC0rXFxkLlxcc1xcd10qKD86YWxwaGEpP1soKS8qXFwtK1xcZC5cXHNcXHddKlxcKXxhbHBoYSkpKT8pXFxzKlxcKSQvLFxuICAgIFtDb2xvck1vZGVsLkxDSF06IC9ebGNoXFxzKlxcKFxccyooPzooPzxsPig/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88Yz4tPyg/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88aD4tPyg/OlxcZCpcXC4pP1xcZCsoPzpkZWd8Z3JhZHxyYWR8dHVybik/KSg/OlxccypcXC9cXHMqKD88YT4oPzpcXGQqXFwuKT9cXGQrJT8pKT98ZnJvbVxccysoPzxmcm9tPig/Olxcdyt8XFx3K1xcKFxccypbXigpKV0rXFxzKlxcKXxcXHcrXFwoZnJvbVxccytcXHcrXFwoLipcXClcXHMqXFwpfCNbYS1mQS1GXFxkXSspKVxccysoPzxyZWxhdGl2ZV9sPig/OltsY2hdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtsY2goKS8qXFwtK1xcZC5cXHNdK1xcKSkpXFxzKyg/PHJlbGF0aXZlX2M+KD86W2xjaF18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2xjaCgpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfaD4oPzpbbGNoXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbbGNoKCkvKlxcLStcXGQuXFxzXStcXCkpKSg/OlxccypcXC9cXHMqKD88cmVsYXRpdmVfYT4oPzooPzpcXGQqXFwuKT9cXGQrJT98Y2FsY1xcKFsoKS8qXFwtK1xcZC5cXHNcXHddKig/OmFscGhhKT9bKCkvKlxcLStcXGQuXFxzXFx3XSpcXCl8YWxwaGEpKSk/KVxccypcXCkkLyxcbiAgICBbQ29sb3JNb2RlbC5DTVlLXTogL14oPzpkZXZpY2UtY215a3xjbXlrKVxccypcXChcXHMqKD86KD88Y19sZWdhY3k+KD86XFxkKlxcLik/XFxkKyU/KVxccyosXFxzKig/PG1fbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCslPylcXHMqLFxccyooPzx5X2xlZ2FjeT4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKixcXHMqKD88a19sZWdhY3k+KD86XFxkKlxcLik/XFxkKyU/KSg/OlxccyosXFxzKig/PGFfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCspKT98KD88Yz4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PG0+KD86XFxkKlxcLik/XFxkKyU/KVxccysoPzx5Pig/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88az4oPzpcXGQqXFwuKT9cXGQrJT8pKD86XFxzKlxcL1xccyooPzxhPig/OlxcZCpcXC4pP1xcZCslPykpPylcXHMqXFwpJC9cbn07XG5leHBvcnQgY29uc3QgQ0FMQyA9IHtcbiAgICBSRUdFWFA6IC9eY2FsY1xcKFxccyooPzxvcGVyYXRpb24+W1xcZC4vKistXFx3XFxzXSspXFxzKlxcKSQvLFxuICAgIFNDT1BFRDogL1xcKFxccyooW14oKV0rKVxccypcXCkvZyxcbiAgICBESVZJU0lPTjogL1xccyooPzxsZWZ0Pig/Oig/OlxcZCpcXC4pP1xcZCt8XFx3KykpXFxzKlxcL1xccyooPzxyaWdodD4oPzooPzpcXGQqXFwuKT9cXGQrfFxcdyspKVxccyovLFxuICAgIE1VTFRJUExJQ0FUSU9OOiAvXFxzKig/PGxlZnQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqXFwqXFxzKig/PHJpZ2h0Pig/Oig/OlxcZCpcXC4pP1xcZCt8XFx3KykpXFxzKi8sXG4gICAgU1VNOiAvXFxzKig/PGxlZnQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqXFwrXFxzKig/PHJpZ2h0Pig/Oig/OlxcZCpcXC4pP1xcZCt8XFx3KykpXFxzKi8sXG4gICAgUkVTVDogL1xccyooPzxsZWZ0Pig/Oig/OlxcZCpcXC4pP1xcZCt8XFx3KykpXFxzKi1cXHMqKD88cmlnaHQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqL1xufTtcbmV4cG9ydCBjb25zdCBIU0xfSFVFID0gL14oPzxudW1iZXI+LT8oPzpcXGQqXFwuKT9cXGQrKSg/PHVuaXRzPig/OmRlZ3xncmFkfHJhZHx0dXJuKT8pJC87XG5leHBvcnQgY29uc3QgUENFTlQgPSAvXigtP1xcZCsoPzpcXC5cXGQrKT98LT9cXC5cXGQrKSUkLztcbmV4cG9ydCBjb25zdCBIRVggPSAvXjB4KFthLWZcXGRdezEsMn0pJC9pO1xuZXhwb3J0IGNvbnN0IFRFTVBMQVRFX1ZBUiA9IC9cXHsoXFxkKylcXH0vZztcbmV4cG9ydCBjb25zdCBDT01NQVNfQU5EX05FWFRfQ0hBUlMgPSAvLCggK3xcXGQrKS9nO1xuZXhwb3J0IGNvbnN0IFNQQUNFUyA9IC8gKy87XG4iLCJleHBvcnQgY29uc3QgRVJST1JTID0ge1xuICAgIE5PVF9BQ0NFUFRFRF9TVFJJTkdfSU5QVVQ6ICdUaGUgcHJvdmlkZWQgc3RyaW5nIGNvbG9yIGRvZXNuXFwndCBoYXZlIGEgY29ycmVjdCBmb3JtYXQnLFxuICAgIE5PVF9BQ0NFUFRFRF9PQkpFQ1RfSU5QVVQ6ICdUaGUgcHJvdmlkZWQgY29sb3Igb2JqZWN0IGRvZXNuXFwndCBoYXZlIHRoZSBwcm9wZXIga2V5cyBvciBmb3JtYXQnLFxuICAgIE5PVF9BX1ZBTElEX1JFTEFUSVZFX0NPTE9SOiAnaXMgbm90IGEgdmFsaWQgb3BlcmF0aW9uIGZvciBhIHJlbGF0aXZlIGNvbG9yJ1xufTtcbiIsImV4cG9ydCB2YXIgQW5nbGVzVW5pdEVudW07XG4oZnVuY3Rpb24gKEFuZ2xlc1VuaXRFbnVtKSB7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJOT05FXCJdID0gXCJub25lXCI7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJERUdSRUVTXCJdID0gXCJkZWdcIjtcbiAgICBBbmdsZXNVbml0RW51bVtcIkdSQURJQU5TXCJdID0gXCJncmFkXCI7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJSQURJQU5TXCJdID0gXCJyYWRcIjtcbiAgICBBbmdsZXNVbml0RW51bVtcIlRVUk5TXCJdID0gXCJ0dXJuXCI7XG59KShBbmdsZXNVbml0RW51bSB8fCAoQW5nbGVzVW5pdEVudW0gPSB7fSkpO1xuZXhwb3J0IHZhciBDb2xvclVuaXRFbnVtO1xuKGZ1bmN0aW9uIChDb2xvclVuaXRFbnVtKSB7XG4gICAgQ29sb3JVbml0RW51bVtcIk5PTkVcIl0gPSBcIm5vbmVcIjtcbiAgICBDb2xvclVuaXRFbnVtW1wiUEVSQ0VOVFwiXSA9IFwicGVyY2VudFwiO1xufSkoQ29sb3JVbml0RW51bSB8fCAoQ29sb3JVbml0RW51bSA9IHt9KSk7XG5leHBvcnQgdmFyIENNWUtGdW5jdGlvbkVudW07XG4oZnVuY3Rpb24gKENNWUtGdW5jdGlvbkVudW0pIHtcbiAgICBDTVlLRnVuY3Rpb25FbnVtW1wiREVWSUNFX0NNWUtcIl0gPSBcImRldmljZS1jbXlrXCI7XG4gICAgQ01ZS0Z1bmN0aW9uRW51bVtcIkNNWUtcIl0gPSBcImNteWtcIjtcbn0pKENNWUtGdW5jdGlvbkVudW0gfHwgKENNWUtGdW5jdGlvbkVudW0gPSB7fSkpO1xuIiwiaW1wb3J0IHsgQW5nbGVzVW5pdEVudW0sIENNWUtGdW5jdGlvbkVudW0sIENvbG9yVW5pdEVudW0gfSBmcm9tICdAdHlwZXMnO1xuaW1wb3J0IHsgTUFYX0RFQ0lNQUxTIH0gZnJvbSAnLi9udW1iZXJzJztcbmV4cG9ydCBjb25zdCBERUZBVUxUX09QVElPTlMgPSB7XG4gICAgZGVjaW1hbHM6IE1BWF9ERUNJTUFMUyxcbiAgICBsZWdhY3lDU1M6IGZhbHNlLFxuICAgIHNwYWNlc0FmdGVyQ29tbWFzOiBmYWxzZSxcbiAgICBhbmdsZXNVbml0OiBBbmdsZXNVbml0RW51bS5OT05FLFxuICAgIHJnYlVuaXQ6IENvbG9yVW5pdEVudW0uTk9ORSxcbiAgICBsYWJVbml0OiBDb2xvclVuaXRFbnVtLk5PTkUsXG4gICAgbGNoVW5pdDogQ29sb3JVbml0RW51bS5OT05FLFxuICAgIGNteWtVbml0OiBDb2xvclVuaXRFbnVtLlBFUkNFTlQsXG4gICAgYWxwaGFVbml0OiBDb2xvclVuaXRFbnVtLk5PTkUsXG4gICAgY215a0Z1bmN0aW9uOiBDTVlLRnVuY3Rpb25FbnVtLkRFVklDRV9DTVlLXG59O1xuIiwiZXhwb3J0ICogZnJvbSAnLi9udW1iZXJzJztcbmV4cG9ydCAqIGZyb20gJy4vZW51bXMnO1xuZXhwb3J0ICogZnJvbSAnLi9lbnVtcy1zdHJpbmdzJztcbmV4cG9ydCAqIGZyb20gJy4vcmVnZXhwcyc7XG5leHBvcnQgKiBmcm9tICcuL2Vycm9ycyc7XG5leHBvcnQgKiBmcm9tICcuL29wdGlvbnMnO1xuIiwiaW1wb3J0IHsgQW5nbGVzVW5pdEVudW0gfSBmcm9tICdAdHlwZXMnO1xuaW1wb3J0IHsgQkFTRV8yNTUsIEhhcm1vbnksIEhFWCwgSFNMX0hVRSwgTUFYX0FMUEhBLCBNQVhfREVDSU1BTFMsIE1BWF9MQUIsIE1BWF9MQ0hfQywgTWl4LCBQQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuZXhwb3J0IGNvbnN0IGhhc1Byb3AgPSAob2JqLCBwcm9wKSA9PiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbmV4cG9ydCBjb25zdCBwZXJjZW50TnVtYmVyID0gKHBlcmNlbnQpID0+IHtcbiAgICByZXR1cm4gK2Ake3BlcmNlbnR9YC5yZXBsYWNlKFBDRU5ULCAnJDEnKTtcbn07XG5leHBvcnQgY29uc3QgcGVyY2VudCA9IChwZXJjZW50KSA9PiBQQ0VOVC50ZXN0KGAke3BlcmNlbnR9YClcbiAgICA/IHBlcmNlbnROdW1iZXIocGVyY2VudClcbiAgICA6IE1hdGgubWluKCtwZXJjZW50LCAxMDApO1xuZXhwb3J0IGNvbnN0IGdldERFQyA9IChoZXgpID0+IHtcbiAgICBpZiAoaGV4Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBoZXggKz0gaGV4O1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VJbnQoaGV4LCAxNik7XG59O1xuZXhwb3J0IGNvbnN0IGdldEhFWCA9IChudW1iZXIpID0+IHtcbiAgICBjb25zdCBoZXggPSByb3VuZChudW1iZXIsIDApLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmIChoZXgubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHJldHVybiBgMHgwJHtoZXh9YDtcbiAgICB9XG4gICAgcmV0dXJuIGAweCR7aGV4fWA7XG59O1xuZXhwb3J0IGNvbnN0IHRvSEVYID0gKGgpID0+IHtcbiAgICBsZXQgaGV4ID0gcm91bmQoaCwgMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7XG4gICAgaWYgKGhleC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgaGV4ID0gYDAke2hleH1gO1xuICAgIH1cbiAgICByZXR1cm4gaGV4O1xufTtcbmV4cG9ydCBjb25zdCBmcm9tMjU1TnVtYmVyVG9QZXJjZW50ID0gKHZhbHVlLCBkZWNpbWFscykgPT4gcm91bmQodmFsdWUgLyBCQVNFXzI1NSAqIDEwMCwgZGVjaW1hbHMpO1xuZXhwb3J0IGNvbnN0IGZyb20xMjVOdW1iZXJUb1BlcmNlbnQgPSAodmFsdWUsIGRlY2ltYWxzKSA9PiByb3VuZCh2YWx1ZSAvIE1BWF9MQUIgKiAxMDAsIGRlY2ltYWxzKTtcbmV4cG9ydCBjb25zdCBmcm9tMTUwTnVtYmVyVG9QZXJjZW50ID0gKHZhbHVlLCBkZWNpbWFscykgPT4gcm91bmQodmFsdWUgLyBNQVhfTENIX0MgKiAxMDAsIGRlY2ltYWxzKTtcbmV4cG9ydCBjb25zdCBnZXRCYXNlMjU1TnVtYmVyID0gKGNvbG9yLCBhbHBoYSA9IGZhbHNlKSA9PiB7XG4gICAgaWYgKCFhbHBoYSAmJiBQQ0VOVC50ZXN0KGNvbG9yKSkge1xuICAgICAgICByZXR1cm4gTWF0aC5taW4oQkFTRV8yNTUgKiBwZXJjZW50TnVtYmVyKGNvbG9yKSAvIDEwMCwgQkFTRV8yNTUpO1xuICAgIH1cbiAgICBpZiAoSEVYLnRlc3QoY29sb3IpKSB7XG4gICAgICAgIGlmIChjb2xvci5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgICAgIGNvbG9yICs9IGNvbG9yLnNsaWNlKC0xKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWxwaGFcbiAgICAgICAgICAgID8gcm91bmQoY29sb3IpIC8gQkFTRV8yNTVcbiAgICAgICAgICAgIDogcm91bmQoY29sb3IpO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5taW4oK2NvbG9yLCBhbHBoYSA/IDEgOiBCQVNFXzI1NSk7XG59O1xuZXhwb3J0IGNvbnN0IGdldEJhc2UxMjVOdW1iZXIgPSAoY29sb3IpID0+IHtcbiAgICBpZiAoUENFTlQudGVzdChjb2xvcikpIHtcbiAgICAgICAgcmV0dXJuIG1pbm1heChNQVhfTEFCICogcGVyY2VudE51bWJlcihjb2xvcikgLyAxMDAsIC1NQVhfTEFCLCBNQVhfTEFCKTtcbiAgICB9XG4gICAgcmV0dXJuIG1pbm1heCgrY29sb3IsIC1NQVhfTEFCLCBNQVhfTEFCKTtcbn07XG5leHBvcnQgY29uc3QgZ2V0QmFzZTE1ME51bWJlciA9IChjb2xvcikgPT4ge1xuICAgIGlmIChQQ0VOVC50ZXN0KGNvbG9yKSkge1xuICAgICAgICByZXR1cm4gbWlubWF4KE1BWF9MQ0hfQyAqIHBlcmNlbnROdW1iZXIoY29sb3IpIC8gMTAwLCAtTUFYX0xDSF9DLCBNQVhfTENIX0MpO1xuICAgIH1cbiAgICByZXR1cm4gbWlubWF4KCtjb2xvciwgLU1BWF9MQ0hfQywgTUFYX0xDSF9DKTtcbn07XG5leHBvcnQgY29uc3QgZ2V0Q01ZS051bWJlciA9IChjb2xvcikgPT4gTWF0aC5taW4oUENFTlQudGVzdChjb2xvcikgPyBwZXJjZW50TnVtYmVyKGNvbG9yKSAvIDEwMCA6ICtjb2xvciwgMSk7XG5leHBvcnQgY29uc3QgZ2V0T3JkZXJlZEFycmF5U3RyaW5nID0gKGtleXMpID0+IFsuLi5rZXlzXS5zb3J0KCkuam9pbignJykudG9VcHBlckNhc2UoKTtcbmV4cG9ydCBjb25zdCByb3VuZCA9ICh2YWx1ZSwgZGVjaW1hbHMgPSBNQVhfREVDSU1BTFMpID0+IHtcbiAgICBjb25zdCBleHAgPSBNYXRoLnBvdygxMCwgZGVjaW1hbHMpO1xuICAgIHJldHVybiBNYXRoLnJvdW5kKCt2YWx1ZSAqIGV4cCkgLyBleHA7XG59O1xuZXhwb3J0IGNvbnN0IG1pbm1heCA9IChuLCBtaW4sIG1heCkgPT4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihuLCBtYXgpKTtcbmV4cG9ydCBjb25zdCBkZWdyZWVzID0gKHJhZGlhbikgPT4gcmFkaWFuICogMTgwIC8gTWF0aC5QSTtcbmV4cG9ydCBjb25zdCByYWRpYW5zID0gKGRlZ3JlZXMpID0+IGRlZ3JlZXMgKiBNYXRoLlBJIC8gMTgwO1xuY29uc3QgcGkyID0gMzYwO1xuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZUh1ZSA9IChodWUpID0+IHtcbiAgICBpZiAodHlwZW9mIGh1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IGh1ZS5tYXRjaChIU0xfSFVFKTtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gbWF0Y2hlcy5ncm91cHM7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gK2dyb3Vwcy5udW1iZXI7XG4gICAgICAgIGNvbnN0IHVuaXRzID0gZ3JvdXBzLnVuaXRzO1xuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlIEFuZ2xlc1VuaXRFbnVtLlJBRElBTlM6XG4gICAgICAgICAgICAgICAgaHVlID0gcm91bmQoZGVncmVlcyh2YWx1ZSkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5UVVJOUzpcbiAgICAgICAgICAgICAgICBodWUgPSByb3VuZCh2YWx1ZSAqIHBpMik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEFuZ2xlc1VuaXRFbnVtLkdSQURJQU5TOlxuICAgICAgICAgICAgICAgIGh1ZSA9IHJvdW5kKDkgLyAxMCAqIHZhbHVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uREVHUkVFUzpcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgaHVlID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGh1ZSA+IDM2MCB8fCBodWUgPCAwKSB7XG4gICAgICAgIGh1ZSAtPSBNYXRoLmZsb29yKGh1ZSAvIHBpMikgKiBwaTI7XG4gICAgfVxuICAgIHJldHVybiBodWU7XG59O1xuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZUFscGhhID0gKGFscGhhKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBhbHBoYSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKFBDRU5ULnRlc3QoYWxwaGEpKSB7XG4gICAgICAgICAgICBhbHBoYSA9IHBlcmNlbnROdW1iZXIoYWxwaGEpIC8gMTAwO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYWxwaGEgPSArYWxwaGE7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIChpc05hTigrYWxwaGEpIHx8IGFscGhhID4gTUFYX0FMUEhBKSA/IE1BWF9BTFBIQSA6IHJvdW5kKGFscGhhKTtcbn07XG5leHBvcnQgY29uc3QgdHJhbnNsYXRlRGVncmVlcyA9IChkZWdyZWVzLCB1bml0cykgPT4ge1xuICAgIGxldCBodWU7XG4gICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICBjYXNlIEFuZ2xlc1VuaXRFbnVtLlJBRElBTlM6XG4gICAgICAgICAgICBodWUgPSByb3VuZChyYWRpYW5zKGRlZ3JlZXMpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIEFuZ2xlc1VuaXRFbnVtLlRVUk5TOlxuICAgICAgICAgICAgaHVlID0gcm91bmQoZGVncmVlcyAvIHBpMik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5HUkFESUFOUzpcbiAgICAgICAgICAgIGh1ZSA9IHJvdW5kKDEwIC8gOSAqIGRlZ3JlZXMpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uREVHUkVFUzpcbiAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5OT05FOlxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaHVlID0gZGVncmVlcztcbiAgICB9XG4gICAgcmV0dXJuIGh1ZTtcbn07XG5leHBvcnQgY29uc3QgaXNIYXJtb255ID0gKHBhcmFtKSA9PiB7XG4gICAgcmV0dXJuIGAke3BhcmFtfWAgaW4gSGFybW9ueTtcbn07XG5leHBvcnQgY29uc3QgaXNNaXggPSAocGFyYW0pID0+IHtcbiAgICByZXR1cm4gYCR7cGFyYW19YCBpbiBNaXg7XG59O1xuIiwiaW1wb3J0IHsgQkFTRV8yNTUsIE1BWF9BTFBIQSB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZGVncmVlcywgbWlubWF4LCBub3JtYWxpemVIdWUsIHJhZGlhbnMsIHJvdW5kIH0gZnJvbSAnI2hlbHBlcnMnO1xuY29uc3QgTUFUUklYX0xSR0JfWFlaX0Q1MCA9IFtcbiAgICBbMC40MzYwNzQ3LCAwLjM4NTA2NDksIDAuMTQzMDgwNF0sXG4gICAgWzAuMjIyNTA0NSwgMC43MTY4Nzg2LCAwLjA2MDYxNjldLFxuICAgIFswLjAxMzkzMjIsIDAuMDk3MTA0NSwgMC43MTQxNzMzXVxuXTtcbmNvbnN0IE1BVFJJWF9YWVpfRDUwX0xSR0IgPSBbXG4gICAgWzMuMTMzODU2MSwgLTEuNjE2ODY2NywgLTAuNDkwNjE0Nl0sXG4gICAgWy0wLjk3ODc2ODQsIDEuOTE2MTQxNSwgMC4wMzM0NTRdLFxuICAgIFswLjA3MTk0NTMsIC0wLjIyODk5MTQsIDEuNDA1MjQyN11cbl07XG5jb25zdCBUUklTVElNVUxVU19ENTAgPSBNQVRSSVhfTFJHQl9YWVpfRDUwLm1hcCgobWF0cml4KSA9PiB7XG4gICAgcmV0dXJuIG1hdHJpeC5yZWR1Y2UoKHN1bSwgdmFsdWUpID0+IHN1bSArIHZhbHVlLCAwKTtcbn0pO1xuY29uc3QgaHVlVG9SZ2IgPSAodDEsIHQyLCBodWUpID0+IHtcbiAgICBpZiAoaHVlIDwgMCkge1xuICAgICAgICBodWUgKz0gNjtcbiAgICB9XG4gICAgaWYgKGh1ZSA+PSA2KSB7XG4gICAgICAgIGh1ZSAtPSA2O1xuICAgIH1cbiAgICBpZiAoaHVlIDwgMSkge1xuICAgICAgICByZXR1cm4gcm91bmQoKCh0MiAtIHQxKSAqIGh1ZSArIHQxKSAqIEJBU0VfMjU1KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoaHVlIDwgMykge1xuICAgICAgICByZXR1cm4gcm91bmQodDIgKiBCQVNFXzI1NSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGh1ZSA8IDQpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKCgodDIgLSB0MSkgKiAoNCAtIGh1ZSkgKyB0MSkgKiBCQVNFXzI1NSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcm91bmQodDEgKiBCQVNFXzI1NSk7XG4gICAgfVxufTtcbmNvbnN0IHJnYlRvTGluZWFyTGlnaHRSZ2IgPSAodmFsdWUpID0+IHtcbiAgICByZXR1cm4gdmFsdWUgPD0gMC4wNDA0NVxuICAgICAgICA/IHZhbHVlIC8gMTIuOTJcbiAgICAgICAgOiAoKHZhbHVlICsgMC4wNTUpIC8gMS4wNTUpICoqIDIuNDtcbn07XG5jb25zdCBsaW5lYXJMaWdodFJnYlRvUmdiID0gKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIHZhbHVlIDw9IDAuMDAzMTMwOFxuICAgICAgICA/IDEyLjkyICogdmFsdWVcbiAgICAgICAgOiAxLjA1NSAqICh2YWx1ZSAqKiAoMSAvIDIuNCkpIC0gMC4wNTU7XG59O1xuY29uc3QgbWF0cml4VmVjdG9yTXVsdGlwbGljYXRpb24gPSAodjEsIHYyLCB2MywgbWF0cml4KSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gWzAsIDAsIDBdO1xuICAgIGNvbnN0IGxpbmVhclJnYiA9IFt2MSwgdjIsIHYzXTtcbiAgICBtYXRyaXguZm9yRWFjaCgoYXJyYXksIGluZGV4KSA9PiB7XG4gICAgICAgIGFycmF5LmZvckVhY2goKHZhbHVlLCBtaW5kZXgpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdFtpbmRleF0gKz0gdmFsdWUgKiBsaW5lYXJSZ2JbbWluZGV4XTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5jb25zdCBmcm9tX0NJRV9YWVpfRDUwX3RvX0NJRV9MQUIgPSAoeCwgeSwgeikgPT4ge1xuICAgIGNvbnN0IGYgPSAodCkgPT4ge1xuICAgICAgICByZXR1cm4gdCA+ICg2IC8gMjkpICoqIDNcbiAgICAgICAgICAgID8gTWF0aC5jYnJ0KHQpXG4gICAgICAgICAgICA6IHQgLyAoMyAqICg2IC8gMjkpICoqIDIpICsgKDQgLyAyOSk7XG4gICAgfTtcbiAgICBjb25zdCBmeCA9IGYoeCAvIFRSSVNUSU1VTFVTX0Q1MFswXSk7XG4gICAgY29uc3QgZnkgPSBmKHkgLyBUUklTVElNVUxVU19ENTBbMV0pO1xuICAgIGNvbnN0IGZ6ID0gZih6IC8gVFJJU1RJTVVMVVNfRDUwWzJdKTtcbiAgICByZXR1cm4gW1xuICAgICAgICAxMTYgKiBmeSAtIDE2LFxuICAgICAgICA1MDAgKiAoZnggLSBmeSksXG4gICAgICAgIDIwMCAqIChmeSAtIGZ6KVxuICAgIF07XG59O1xuY29uc3QgZnJvbV9DSUVfTEFCX3RvX0NJRV9YWVpfRDUwID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBmID0gKHQpID0+IHtcbiAgICAgICAgcmV0dXJuIHQgPiA2IC8gMjlcbiAgICAgICAgICAgID8gdCAqKiAzXG4gICAgICAgICAgICA6IDMgKiAoNiAvIDI5KSAqKiAyICogKHQgLSA0IC8gMjkpO1xuICAgIH07XG4gICAgY29uc3QgZmwgPSAoTCArIDE2KSAvIDExNjtcbiAgICBjb25zdCBmYSA9IGEgLyA1MDA7XG4gICAgY29uc3QgZmIgPSBiIC8gMjAwO1xuICAgIHJldHVybiBbXG4gICAgICAgIFRSSVNUSU1VTFVTX0Q1MFswXSAqIGYoZmwgKyBmYSksXG4gICAgICAgIFRSSVNUSU1VTFVTX0Q1MFsxXSAqIGYoZmwpLFxuICAgICAgICBUUklTVElNVUxVU19ENTBbMl0gKiBmKGZsIC0gZmIpXG4gICAgXTtcbn07XG5leHBvcnQgY29uc3QgaHNsVG9SZ2IgPSAoSCwgUywgTCkgPT4ge1xuICAgIEggLz0gNjA7XG4gICAgUyAvPSAxMDA7XG4gICAgTCAvPSAxMDA7XG4gICAgY29uc3QgdDIgPSAoTCA8PSAuNSlcbiAgICAgICAgPyBMICogKFMgKyAxKVxuICAgICAgICA6IEwgKyBTIC0gKEwgKiBTKTtcbiAgICBjb25zdCB0MSA9IEwgKiAyIC0gdDI7XG4gICAgY29uc3QgUiA9IGh1ZVRvUmdiKHQxLCB0MiwgSCArIDIpO1xuICAgIGNvbnN0IEcgPSBodWVUb1JnYih0MSwgdDIsIEgpO1xuICAgIGNvbnN0IEIgPSBodWVUb1JnYih0MSwgdDIsIEggLSAyKTtcbiAgICByZXR1cm4geyBSLCBHLCBCIH07XG59O1xuZXhwb3J0IGNvbnN0IHJnYlRvSHNsID0gKFIsIEcsIEIsIEEgPSAxKSA9PiB7XG4gICAgUiAvPSBCQVNFXzI1NTtcbiAgICBHIC89IEJBU0VfMjU1O1xuICAgIEIgLz0gQkFTRV8yNTU7XG4gICAgQSA9IE1hdGgubWluKEEsIE1BWF9BTFBIQSk7XG4gICAgY29uc3QgTUFYID0gTWF0aC5tYXgoUiwgRywgQik7XG4gICAgY29uc3QgTUlOID0gTWF0aC5taW4oUiwgRywgQik7XG4gICAgY29uc3QgRCA9IE1BWCAtIE1JTjtcbiAgICBsZXQgSCA9IDA7XG4gICAgbGV0IFMgPSAwO1xuICAgIGNvbnN0IEwgPSAoTUFYICsgTUlOKSAvIDI7XG4gICAgaWYgKEQgIT09IDApIHtcbiAgICAgICAgc3dpdGNoIChNQVgpIHtcbiAgICAgICAgICAgIGNhc2UgUjpcbiAgICAgICAgICAgICAgICBIID0gKChHIC0gQikgLyBEKSAlIDY7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEc6XG4gICAgICAgICAgICAgICAgSCA9IChCIC0gUikgLyBEICsgMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQjpcbiAgICAgICAgICAgICAgICBIID0gKFIgLSBHKSAvIEQgKyA0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIEggPSByb3VuZChIICogNjApO1xuICAgICAgICBpZiAoSCA8IDApIHtcbiAgICAgICAgICAgIEggKz0gMzYwO1xuICAgICAgICB9XG4gICAgICAgIFMgPSBEIC8gKDEgLSBNYXRoLmFicygyICogTCAtIDEpKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgSCxcbiAgICAgICAgUzogcm91bmQoUyAqIDEwMCksXG4gICAgICAgIEw6IHJvdW5kKEwgKiAxMDApLFxuICAgICAgICBBXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9MYWIgPSAoUiwgRywgQikgPT4ge1xuICAgIGNvbnN0IExJTkVBUl9MSUdIVF9SR0IgPSBbXG4gICAgICAgIFIgLyBCQVNFXzI1NSxcbiAgICAgICAgRyAvIEJBU0VfMjU1LFxuICAgICAgICBCIC8gQkFTRV8yNTVcbiAgICBdLm1hcChyZ2JUb0xpbmVhckxpZ2h0UmdiKTtcbiAgICBjb25zdCBDSUVfWFlaX0Q1MCA9IG1hdHJpeFZlY3Rvck11bHRpcGxpY2F0aW9uKExJTkVBUl9MSUdIVF9SR0JbMF0sIExJTkVBUl9MSUdIVF9SR0JbMV0sIExJTkVBUl9MSUdIVF9SR0JbMl0sIE1BVFJJWF9MUkdCX1hZWl9ENTApO1xuICAgIGNvbnN0IENJRV9MQUIgPSBmcm9tX0NJRV9YWVpfRDUwX3RvX0NJRV9MQUIoQ0lFX1hZWl9ENTBbMF0sIENJRV9YWVpfRDUwWzFdLCBDSUVfWFlaX0Q1MFsyXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgTDogQ0lFX0xBQlswXSxcbiAgICAgICAgYTogQ0lFX0xBQlsxXSxcbiAgICAgICAgYjogQ0lFX0xBQlsyXVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGxhYlRvUmdiID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBDSUVfWFlaX0Q1MCA9IGZyb21fQ0lFX0xBQl90b19DSUVfWFlaX0Q1MChMLCBhLCBiKTtcbiAgICBjb25zdCBMSU5FQVJfTElHSFRfUkdCID0gbWF0cml4VmVjdG9yTXVsdGlwbGljYXRpb24oQ0lFX1hZWl9ENTBbMF0sIENJRV9YWVpfRDUwWzFdLCBDSUVfWFlaX0Q1MFsyXSwgTUFUUklYX1hZWl9ENTBfTFJHQik7XG4gICAgY29uc3QgcmdiID0gTElORUFSX0xJR0hUX1JHQi5tYXAobGluZWFyTGlnaHRSZ2JUb1JnYik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUjogbWlubWF4KHJnYlswXSAqIEJBU0VfMjU1LCAwLCBCQVNFXzI1NSksXG4gICAgICAgIEc6IG1pbm1heChyZ2JbMV0gKiBCQVNFXzI1NSwgMCwgQkFTRV8yNTUpLFxuICAgICAgICBCOiBtaW5tYXgocmdiWzJdICogQkFTRV8yNTUsIDAsIEJBU0VfMjU1KVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGxhYlRvTGNoID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBDID0gTWF0aC5zcXJ0KGEgKiogMiArIGIgKiogMik7XG4gICAgY29uc3QgSCA9IGRlZ3JlZXMoTWF0aC5hdGFuMihiLCBhKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgTCxcbiAgICAgICAgQyxcbiAgICAgICAgSDogbm9ybWFsaXplSHVlKEgpXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgbGNoVG9MYWIgPSAoTCwgQywgSCkgPT4ge1xuICAgIGNvbnN0IHJhZEggPSByYWRpYW5zKEgpO1xuICAgIGNvbnN0IGEgPSBDICogTWF0aC5jb3MocmFkSCk7XG4gICAgY29uc3QgYiA9IEMgKiBNYXRoLnNpbihyYWRIKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBMLFxuICAgICAgICBhLFxuICAgICAgICBiXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9MY2ggPSAoUiwgRywgQikgPT4ge1xuICAgIGNvbnN0IGxhYiA9IHJnYlRvTGFiKFIsIEcsIEIpO1xuICAgIHJldHVybiBsYWJUb0xjaChsYWIuTCwgbGFiLmEsIGxhYi5iKTtcbn07XG5leHBvcnQgY29uc3QgbGNoVG9SZ2IgPSAoTCwgQywgSCkgPT4ge1xuICAgIGNvbnN0IGxhYiA9IGxjaFRvTGFiKEwsIEMsIEgpO1xuICAgIHJldHVybiBsYWJUb1JnYihsYWIuTCwgbGFiLmEsIGxhYi5iKTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9Id2IgPSAoUiwgRywgQiwgQSA9IDEpID0+IHtcbiAgICBjb25zdCBoc2wgPSByZ2JUb0hzbChSLCBHLCBCLCBBKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBIOiBoc2wuSCxcbiAgICAgICAgVzogcm91bmQoTWF0aC5taW4oUiwgRywgQikgLyBCQVNFXzI1NSAqIDEwMCksXG4gICAgICAgIEI6IHJvdW5kKCgxIC0gTWF0aC5tYXgoUiwgRywgQikgLyBCQVNFXzI1NSkgKiAxMDApLFxuICAgICAgICBBXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgaHdiVG9SZ2IgPSAoSCwgVywgQikgPT4ge1xuICAgIFcgLz0gMTAwO1xuICAgIEIgLz0gMTAwO1xuICAgIGNvbnN0IHYgPSAxIC0gQjtcbiAgICBjb25zdCBjID0gdiAtIFc7XG4gICAgY29uc3QgeCA9IGMgKiAoMSAtIE1hdGguYWJzKChIIC8gNjApICUgMiAtIDEpKTtcbiAgICBsZXQgcmdiUiA9IDA7XG4gICAgbGV0IHJnYkcgPSAwO1xuICAgIGxldCByZ2JCID0gMDtcbiAgICBpZiAoSCA8IDYwKSB7XG4gICAgICAgIHJnYlIgPSBjO1xuICAgICAgICByZ2JHID0geDtcbiAgICAgICAgcmdiQiA9IDA7XG4gICAgfVxuICAgIGVsc2UgaWYgKEggPj0gNjAgJiYgSCA8IDEyMCkge1xuICAgICAgICByZ2JSID0geDtcbiAgICAgICAgcmdiRyA9IGM7XG4gICAgICAgIHJnYkIgPSAwO1xuICAgIH1cbiAgICBlbHNlIGlmIChIID49IDEyMCAmJiBIIDwgMTgwKSB7XG4gICAgICAgIHJnYlIgPSAwO1xuICAgICAgICByZ2JHID0gYztcbiAgICAgICAgcmdiQiA9IHg7XG4gICAgfVxuICAgIGVsc2UgaWYgKEggPj0gMTgwICYmIEggPCAyNDApIHtcbiAgICAgICAgcmdiUiA9IDA7XG4gICAgICAgIHJnYkcgPSB4O1xuICAgICAgICByZ2JCID0gYztcbiAgICB9XG4gICAgZWxzZSBpZiAoSCA+PSAyNDAgJiYgSCA8IDMwMCkge1xuICAgICAgICByZ2JSID0geDtcbiAgICAgICAgcmdiRyA9IDA7XG4gICAgICAgIHJnYkIgPSBjO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmdiUiA9IGM7XG4gICAgICAgIHJnYkcgPSAwO1xuICAgICAgICByZ2JCID0geDtcbiAgICB9XG4gICAgcmdiUiArPSBXO1xuICAgIHJnYkcgKz0gVztcbiAgICByZ2JCICs9IFc7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUjogbWlubWF4KHJnYlIgKiBCQVNFXzI1NSwgMCwgQkFTRV8yNTUpLFxuICAgICAgICBHOiBtaW5tYXgocmdiRyAqIEJBU0VfMjU1LCAwLCBCQVNFXzI1NSksXG4gICAgICAgIEI6IG1pbm1heChyZ2JCICogQkFTRV8yNTUsIDAsIEJBU0VfMjU1KVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGNteWtUb1JnYiA9IChDLCBNLCBZLCBLKSA9PiB7XG4gICAgSyA9IDEgLSBLO1xuICAgIHJldHVybiB7XG4gICAgICAgIFI6IHJvdW5kKEJBU0VfMjU1ICogKDEgLSBDKSAqIEspLFxuICAgICAgICBHOiByb3VuZChCQVNFXzI1NSAqICgxIC0gTSkgKiBLKSxcbiAgICAgICAgQjogcm91bmQoQkFTRV8yNTUgKiAoMSAtIFkpICogSylcbiAgICB9O1xufTtcbmV4cG9ydCBjb25zdCByZ2JUb0NteWsgPSAoUiwgRywgQikgPT4ge1xuICAgIFIgLz0gQkFTRV8yNTU7XG4gICAgRyAvPSBCQVNFXzI1NTtcbiAgICBCIC89IEJBU0VfMjU1O1xuICAgIGNvbnN0IEsgPSAxIC0gTWF0aC5tYXgoUiwgRywgQik7XG4gICAgY29uc3QgSzEgPSAxIC0gSztcbiAgICBjb25zdCBDID0gSzEgJiYgKEsxIC0gUikgLyBLMTtcbiAgICBjb25zdCBNID0gSzEgJiYgKEsxIC0gRykgLyBLMTtcbiAgICBjb25zdCBZID0gSzEgJiYgKEsxIC0gQikgLyBLMTtcbiAgICByZXR1cm4ge1xuICAgICAgICBDOiByb3VuZChDICogMTAwKSxcbiAgICAgICAgTTogcm91bmQoTSAqIDEwMCksXG4gICAgICAgIFk6IHJvdW5kKFkgKiAxMDApLFxuICAgICAgICBLOiByb3VuZChLICogMTAwKVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IHJnYlRvUnliID0gKFIsIEcsIEIpID0+IHtcbiAgICBjb25zdCBJdyA9IE1hdGgubWluKFIsIEcsIEIpO1xuICAgIGNvbnN0IEliID0gTWF0aC5taW4oQkFTRV8yNTUgLSBSLCBCQVNFXzI1NSAtIEcsIEJBU0VfMjU1IC0gQik7XG4gICAgY29uc3QgclJnYiA9IFIgLSBJdztcbiAgICBjb25zdCBnUmdiID0gRyAtIEl3O1xuICAgIGNvbnN0IGJSZ2IgPSBCIC0gSXc7XG4gICAgY29uc3QgbWluUmcgPSBNYXRoLm1pbihyUmdiLCBnUmdiKTtcbiAgICBjb25zdCByUnliID0gclJnYiAtIG1pblJnO1xuICAgIGNvbnN0IHlSeWIgPSAoZ1JnYiArIG1pblJnKSAvIDI7XG4gICAgY29uc3QgYlJ5YiA9IChiUmdiICsgZ1JnYiAtIG1pblJnKSAvIDI7XG4gICAgY29uc3QgbiA9IE1hdGgubWF4KHJSeWIsIHlSeWIsIGJSeWIpIC8gTWF0aC5tYXgoclJnYiwgZ1JnYiwgYlJnYik7XG4gICAgY29uc3QgTiA9IGlzTmFOKG4pIHx8IG4gPT09IEluZmluaXR5IHx8IG4gPD0gMCA/IDEgOiBuO1xuICAgIHJldHVybiB7XG4gICAgICAgIFI6IHJSeWIgLyBOICsgSWIsXG4gICAgICAgIFk6IHlSeWIgLyBOICsgSWIsXG4gICAgICAgIEI6IGJSeWIgLyBOICsgSWJcbiAgICB9O1xufTtcbmV4cG9ydCBjb25zdCByeWJUb1JnYiA9IChSLCBZLCBCKSA9PiB7XG4gICAgY29uc3QgSXcgPSBNYXRoLm1pbihSLCBZLCBCKTtcbiAgICBjb25zdCBJYiA9IE1hdGgubWluKEJBU0VfMjU1IC0gUiwgQkFTRV8yNTUgLSBZLCBCQVNFXzI1NSAtIEIpO1xuICAgIGNvbnN0IHJSeWIgPSBSIC0gSXc7XG4gICAgY29uc3QgeVJ5YiA9IFkgLSBJdztcbiAgICBjb25zdCBiUnliID0gQiAtIEl3O1xuICAgIGNvbnN0IG1pblliID0gTWF0aC5taW4oeVJ5YiwgYlJ5Yik7XG4gICAgY29uc3QgclJnYiA9IHJSeWIgKyB5UnliIC0gbWluWWI7XG4gICAgY29uc3QgZ1JnYiA9IHlSeWIgKyBtaW5ZYjtcbiAgICBjb25zdCBiUmdiID0gMiAqIChiUnliIC0gbWluWWIpO1xuICAgIGNvbnN0IG4gPSBNYXRoLm1heChyUmdiLCBnUmdiLCBiUmdiKSAvIE1hdGgubWF4KHJSeWIsIHlSeWIsIGJSeWIpO1xuICAgIGNvbnN0IE4gPSBpc05hTihuKSB8fCBuID09PSBJbmZpbml0eSB8fCBuIDw9IDAgPyAxIDogbjtcbiAgICByZXR1cm4ge1xuICAgICAgICBSOiByUmdiIC8gTiArIEliLFxuICAgICAgICBHOiBnUmdiIC8gTiArIEliLFxuICAgICAgICBCOiBiUmdiIC8gTiArIEliXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgaHVlUnliID0gKGh1ZSwgdG9SeWIpID0+IHtcbiAgICBpZiAoaHVlIDwgMClcbiAgICAgICAgaHVlICs9IDM2MDtcbiAgICBpZiAoaHVlID4gMzYwKVxuICAgICAgICBodWUgLT0gMzYwO1xuICAgIGlmIChodWUgPT09IDM2MCB8fCBodWUgPT09IDApXG4gICAgICAgIHJldHVybiBodWU7XG4gICAgY29uc3QgbWFwMSA9IFtcbiAgICAgICAgWzAsIDEyMF0sXG4gICAgICAgIFsxMjAsIDE4MF0sXG4gICAgICAgIFsxODAsIDI0MF0sXG4gICAgICAgIFsyNDAsIDM2MF1cbiAgICBdO1xuICAgIGNvbnN0IG1hcDIgPSBbXG4gICAgICAgIFswLCA2MF0sXG4gICAgICAgIFs2MCwgMTIwXSxcbiAgICAgICAgWzEyMCwgMjQwXSxcbiAgICAgICAgWzI0MCwgMzYwXVxuICAgIF07XG4gICAgY29uc3QgZnJvbSA9IHRvUnliID8gbWFwMSA6IG1hcDI7XG4gICAgY29uc3QgdG8gPSB0b1J5YiA/IG1hcDIgOiBtYXAxO1xuICAgIGxldCBBID0gMDtcbiAgICBsZXQgQiA9IDA7XG4gICAgbGV0IEMgPSAwO1xuICAgIGxldCBEID0gMDtcbiAgICBmcm9tLmZpbmQoKGFyciwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGh1ZSA+PSBhcnJbMF0gJiYgaHVlIDwgYXJyWzFdKSB7XG4gICAgICAgICAgICBBID0gYXJyWzBdO1xuICAgICAgICAgICAgQiA9IGFyclsxXTtcbiAgICAgICAgICAgIEMgPSB0b1tpbmRleF1bMF07XG4gICAgICAgICAgICBEID0gdG9baW5kZXhdWzFdO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuICAgIHJldHVybiBDICsgKGh1ZSAtIEEpICogKChEIC0gQykgLyAoQiAtIEEpKTtcbn07XG4iLCJleHBvcnQgY2xhc3MgUmdiQ2xhc3Mge1xuICAgIGdldCByZ2IoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yZ2I7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQkFTRV8yNTUsIENPTE9SUkVHUyB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0REVDIH0gZnJvbSAnI2hlbHBlcnMnO1xuaW1wb3J0IHsgUmdiQ2xhc3MgfSBmcm9tICcuL2Jhc2VDbGFzc2VzL19SZ2JDbGFzcyc7XG5leHBvcnQgY2xhc3MgSEVYU3RyaW5nUGFyc2VyIGV4dGVuZHMgUmdiQ2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKGNvbG9yU3RyaW5nKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gY29sb3JTdHJpbmcubWF0Y2goQ09MT1JSRUdTLkhFWCk7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IG1hdGNoLmdyb3VwcztcbiAgICAgICAgdGhpcy5fciA9IGdyb3Vwcy5yID8/IGdyb3Vwcy5ycjtcbiAgICAgICAgdGhpcy5fZyA9IGdyb3Vwcy5nID8/IGdyb3Vwcy5nZztcbiAgICAgICAgdGhpcy5fYiA9IGdyb3Vwcy5iID8/IGdyb3Vwcy5iYjtcbiAgICAgICAgdGhpcy5fYSA9IGdyb3Vwcy5hID8/IGdyb3Vwcy5hYTtcbiAgICAgICAgY29uc3QgcmdiID0ge1xuICAgICAgICAgICAgUjogZ2V0REVDKHRoaXMuX3IpLFxuICAgICAgICAgICAgRzogZ2V0REVDKHRoaXMuX2cpLFxuICAgICAgICAgICAgQjogZ2V0REVDKHRoaXMuX2IpXG4gICAgICAgIH07XG4gICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJnYi5BID0gZ2V0REVDKHRoaXMuX2EpIC8gQkFTRV8yNTU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENBTEMsIEVSUk9SUyB9IGZyb20gJyNjb25zdGFudHMnO1xuY29uc3QgTUFYX1NUQUNLID0gMTAwO1xuZXhwb3J0IGNsYXNzIENhbGNQYXJzZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbG9ySW5kZXgsIGNhbGMsIHZhcnMpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9ucyA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgW0NBTEMuRElWSVNJT04sIHRoaXMuX2RpdmlzaW9uXSxcbiAgICAgICAgICAgIFtDQUxDLk1VTFRJUExJQ0FUSU9OLCB0aGlzLl9tdWx0aXBsaWNhdGlvbl0sXG4gICAgICAgICAgICBbQ0FMQy5TVU0sIHRoaXMuX3N1bV0sXG4gICAgICAgICAgICBbQ0FMQy5SRVNULCB0aGlzLl9yZXN0XVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5fY29sb3JJbmRleCA9IGNvbG9ySW5kZXg7XG4gICAgICAgIGxldCBjYWxjU3RyaW5nID0gY2FsYztcbiAgICAgICAgbGV0IHN0YWNrID0gMDtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNOYU4oK2NhbGMpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXN1bHQgPSArY2FsYztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjYWxjIGluIHZhcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc3VsdCA9IHZhcnNbY2FsY107XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoQ0FMQy5SRUdFWFAudGVzdChjYWxjU3RyaW5nKSkge1xuICAgICAgICAgICAgQ0FMQy5SRUdFWFAubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIHRoaXMuX3Jlc3VsdCA9IHRoaXMuX2dldENhbGNWYWx1ZShjYWxjU3RyaW5nLCB2YXJzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHdoaWxlIChDQUxDLlNDT1BFRC50ZXN0KGNhbGNTdHJpbmcpICYmIHN0YWNrIDwgTUFYX1NUQUNLKSB7XG4gICAgICAgICAgICAgICAgQ0FMQy5TQ09QRUQubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICBjYWxjU3RyaW5nID0gY2FsY1N0cmluZy5yZXBsYWNlKENBTEMuU0NPUEVELCAoX19tYXRjaCwgb3BlcmF0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jYWxjdWxhdGUob3BlcmF0aW9uLCB2YXJzKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChDQUxDLlJFR0VYUC50ZXN0KGNhbGNTdHJpbmcpKSB7XG4gICAgICAgICAgICAgICAgICAgIENBTEMuUkVHRVhQLmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdGFjaysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmVzdWx0ID0gdGhpcy5fZ2V0Q2FsY1ZhbHVlKGNhbGNTdHJpbmcsIHZhcnMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIF9kaXZpc2lvbihsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xuICAgIH1cbiAgICBfbXVsdGlwbGljYXRpb24obGVmdCwgcmlnaHQpIHtcbiAgICAgICAgcmV0dXJuIGxlZnQgKiByaWdodDtcbiAgICB9XG4gICAgX3N1bShsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCArIHJpZ2h0O1xuICAgIH1cbiAgICBfcmVzdChsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCAtIHJpZ2h0O1xuICAgIH1cbiAgICBfZ2V0Q2FsY1ZhbHVlKGNhbGMsIHZhcnMpIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBjYWxjLm1hdGNoKENBTEMuUkVHRVhQKTtcbiAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gbWF0Y2guZ3JvdXBzLm9wZXJhdGlvbjtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jYWxjdWxhdGUob3BlcmF0aW9uLCB2YXJzKTtcbiAgICAgICAgaWYgKE51bWJlci5pc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgJHt0aGlzLl9jb2xvckluZGV4fS4gJHtvcGVyYXRpb259ICR7RVJST1JTLk5PVF9BX1ZBTElEX1JFTEFUSVZFX0NPTE9SfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgX2NhbGN1bGF0ZShvcGVyYXRpb24sIHZhcnMpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9ucy5mb3JFYWNoKChtZXRob2QsIHJlZ0V4cCkgPT4ge1xuICAgICAgICAgICAgbGV0IHN0YWNrID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChyZWdFeHAudGVzdChvcGVyYXRpb24pICYmIHN0YWNrIDwgTUFYX1NUQUNLKSB7XG4gICAgICAgICAgICAgICAgb3BlcmF0aW9uID0gb3BlcmF0aW9uLnJlcGxhY2UocmVnRXhwLCAoX19tYXRjaCwgbGVmdCwgcmlnaHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1ldGhvZCh2YXJzW2xlZnRdID8/ICtsZWZ0LCB2YXJzW3JpZ2h0XSA/PyArcmlnaHQpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc3RhY2srKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiArb3BlcmF0aW9uO1xuICAgIH1cbiAgICBnZXQgcmVzdWx0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVzdWx0O1xuICAgIH1cbn1cbiIsImltcG9ydCB7IFBDRU5UIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBSZ2JDbGFzcyB9IGZyb20gJy4vX1JnYkNsYXNzJztcbmV4cG9ydCBjbGFzcyBBbHBoYUJhc2VDbGFzcyBleHRlbmRzIFJnYkNsYXNzIHtcbiAgICBnZXQgaGFzUGVyY2VudGFnZUFscGhhKCkge1xuICAgICAgICByZXR1cm4gUENFTlQudGVzdCh0aGlzLl9hKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBCQVNFXzI1NSwgQ09MT1JSRUdTLCBQQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0QmFzZTI1NU51bWJlciwgbm9ybWFsaXplQWxwaGEgfSBmcm9tICcjaGVscGVycyc7XG5pbXBvcnQgeyBDYWxjUGFyc2VyIH0gZnJvbSAnLi9fQ2FsY1BhcnNlcic7XG5pbXBvcnQgeyBBbHBoYUJhc2VDbGFzcyB9IGZyb20gJy4vYmFzZUNsYXNzZXMvX0FscGhhQmFzZUNsYXNzJztcbmV4cG9ydCBjbGFzcyBSR0JTdHJpbmdQYXJzZXIgZXh0ZW5kcyBBbHBoYUJhc2VDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoY29sb3JTdHJpbmcsIGdldFJHQk9iamVjdCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IGNvbG9yU3RyaW5nLm1hdGNoKENPTE9SUkVHUy5SR0IpO1xuICAgICAgICBjb25zdCBncm91cHMgPSBtYXRjaC5ncm91cHM7XG4gICAgICAgIGNvbnN0IHsgcl9sZWdhY3ksIGdfbGVnYWN5LCBiX2xlZ2FjeSwgYV9sZWdhY3ksIHIsIGcsIGIsIGEsIGZyb20sIHJlbGF0aXZlX3IsIHJlbGF0aXZlX2csIHJlbGF0aXZlX2IsIHJlbGF0aXZlX2EgfSA9IGdyb3VwcztcbiAgICAgICAgaWYgKGZyb20pIHtcbiAgICAgICAgICAgIGNvbnN0IGZyb21SR0IgPSBnZXRSR0JPYmplY3QoZnJvbSk7XG4gICAgICAgICAgICBjb25zdCBmcm9tUkdCVmFycyA9IHtcbiAgICAgICAgICAgICAgICByOiBmcm9tUkdCLlIsXG4gICAgICAgICAgICAgICAgZzogZnJvbVJHQi5HLFxuICAgICAgICAgICAgICAgIGI6IGZyb21SR0IuQixcbiAgICAgICAgICAgICAgICBhbHBoYTogZnJvbVJHQi5BID8/IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBSID0gbmV3IENhbGNQYXJzZXIoJ3InLCByZWxhdGl2ZV9yLCBmcm9tUkdCVmFycykucmVzdWx0O1xuICAgICAgICAgICAgY29uc3QgRyA9IG5ldyBDYWxjUGFyc2VyKCdnJywgcmVsYXRpdmVfZywgZnJvbVJHQlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgIGNvbnN0IEIgPSBuZXcgQ2FsY1BhcnNlcignYicsIHJlbGF0aXZlX2IsIGZyb21SR0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICBjb25zdCByZ2IgPSB7XG4gICAgICAgICAgICAgICAgUjogTWF0aC5taW4oUiwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgIEc6IE1hdGgubWluKEcsIEJBU0VfMjU1KSxcbiAgICAgICAgICAgICAgICBCOiBNYXRoLm1pbihCLCBCQVNFXzI1NSlcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAocmVsYXRpdmVfYSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEEgPSBuZXcgQ2FsY1BhcnNlcignYWxwaGEnLCByZWxhdGl2ZV9hLCBmcm9tUkdCVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIHJnYi5BID0gTWF0aC5taW4oQSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9yZ2IgPSByZ2I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9yID0gcl9sZWdhY3kgPz8gcjtcbiAgICAgICAgICAgIHRoaXMuX2cgPSBnX2xlZ2FjeSA/PyBnO1xuICAgICAgICAgICAgdGhpcy5fYiA9IGJfbGVnYWN5ID8/IGI7XG4gICAgICAgICAgICB0aGlzLl9hID0gYV9sZWdhY3kgPz8gYTtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IHtcbiAgICAgICAgICAgICAgICBSOiBNYXRoLm1pbihnZXRCYXNlMjU1TnVtYmVyKHRoaXMuX3IpLCBCQVNFXzI1NSksXG4gICAgICAgICAgICAgICAgRzogTWF0aC5taW4oZ2V0QmFzZTI1NU51bWJlcih0aGlzLl9nKSwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgIEI6IE1hdGgubWluKGdldEJhc2UyNTVOdW1iZXIodGhpcy5fYiksIEJBU0VfMjU1KVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZ2IuQSA9IG5vcm1hbGl6ZUFscGhhKHRoaXMuX2EpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBoYXNQZXJjZW50YWdlVmFsdWVzKCkge1xuICAgICAgICByZXR1cm4gKFBDRU5ULnRlc3QodGhpcy5fcikgJiZcbiAgICAgICAgICAgIFBDRU5ULnRlc3QodGhpcy5fZykgJiZcbiAgICAgICAgICAgIFBDRU5ULnRlc3QodGhpcy5fYikpO1xuICAgIH1cbiAgICBzdGF0aWMgdGVzdChjb2xvclN0cmluZykge1xuICAgICAgICByZXR1cm4gQ09MT1JSRUdTLlJHQi50ZXN0KGNvbG9yU3RyaW5nKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBBbmdsZXNVbml0RW51bSB9IGZyb20gJ0B0eXBlcyc7XG5pbXBvcnQgeyBIU0xfSFVFIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBBbHBoYUJhc2VDbGFzcyB9IGZyb20gJy4vX0FscGhhQmFzZUNsYXNzJztcbmV4cG9ydCBjbGFzcyBIdWVCYXNlQ2xhc3MgZXh0ZW5kcyBBbHBoYUJhc2VDbGFzcyB7XG4gICAgZ2V0IGFuZ2xlVW5pdCgpIHtcbiAgICAgICAgaWYgKHRoaXMuX2gpIHtcbiAgICAgICAgICAgIGNvbnN0IGFuZ2xlVW5pdE1hdGNoID0gdGhpcy5faC5tYXRjaChIU0xfSFVFKTtcbiAgICAgICAgICAgIGNvbnN0IGFuZ2xlVW5pdCA9IGFuZ2xlVW5pdE1hdGNoLmdyb3Vwcy51bml0cztcbiAgICAgICAgICAgIHJldHVybiBhbmdsZVVuaXQgPT09ICcnXG4gICAgICAgICAgICAgICAgPyBBbmdsZXNVbml0RW51bS5OT05FXG4gICAgICAgICAgICAgICAgOiBhbmdsZVVuaXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIEFuZ2xlc1VuaXRFbnVtLk5PTkU7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQ09MT1JSRUdTLCBNQVhfQUxQSEEsIE1BWF9IVUUsIE1BWF9QQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgbWlubWF4LCBub3JtYWxpemVBbHBoYSwgbm9ybWFsaXplSHVlLCBwZXJjZW50IH0gZnJvbSAnI2hlbHBlcnMnO1xuaW1wb3J0IHsgaHNsVG9SZ2IsIHJnYlRvSHNsIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IENhbGNQYXJzZXIgfSBmcm9tICcuL19DYWxjUGFyc2VyJztcbmltcG9ydCB7IEh1ZUJhc2VDbGFzcyB9IGZyb20gJy4vYmFzZUNsYXNzZXMvX0h1ZUJhc2VDbGFzcyc7XG5leHBvcnQgY2xhc3MgSFNMU3RyaW5nUGFyc2VyIGV4dGVuZHMgSHVlQmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcihjb2xvclN0cmluZywgZ2V0UkdCT2JqZWN0KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gY29sb3JTdHJpbmcubWF0Y2goQ09MT1JSRUdTLkhTTCk7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IG1hdGNoLmdyb3VwcztcbiAgICAgICAgY29uc3QgeyBoX2xlZ2FjeSwgc19sZWdhY3ksIGxfbGVnYWN5LCBhX2xlZ2FjeSwgaCwgcywgbCwgYSwgZnJvbSwgcmVsYXRpdmVfaCwgcmVsYXRpdmVfcywgcmVsYXRpdmVfbCwgcmVsYXRpdmVfYSB9ID0gZ3JvdXBzO1xuICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgY29uc3QgZnJvbVJHQiA9IGdldFJHQk9iamVjdChmcm9tKTtcbiAgICAgICAgICAgIGNvbnN0IGZyb21IU0wgPSByZ2JUb0hzbChmcm9tUkdCLlIsIGZyb21SR0IuRywgZnJvbVJHQi5CLCBmcm9tUkdCLkEpO1xuICAgICAgICAgICAgY29uc3QgZnJvbUhTTFZhcnMgPSB7XG4gICAgICAgICAgICAgICAgaDogZnJvbUhTTC5ILFxuICAgICAgICAgICAgICAgIHM6IGZyb21IU0wuUyxcbiAgICAgICAgICAgICAgICBsOiBmcm9tSFNMLkwsXG4gICAgICAgICAgICAgICAgYWxwaGE6IGZyb21IU0wuQVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IEggPSBuZXcgQ2FsY1BhcnNlcignaCcsIHJlbGF0aXZlX2gsIGZyb21IU0xWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICBjb25zdCBTID0gbmV3IENhbGNQYXJzZXIoJ3MnLCByZWxhdGl2ZV9zLCBmcm9tSFNMVmFycykucmVzdWx0O1xuICAgICAgICAgICAgY29uc3QgTCA9IG5ldyBDYWxjUGFyc2VyKCdsJywgcmVsYXRpdmVfbCwgZnJvbUhTTFZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGhzbFRvUmdiKG1pbm1heChILCAwLCBNQVhfSFVFKSwgbWlubWF4KFMsIDAsIE1BWF9QQ0VOVCksIG1pbm1heChMLCAwLCBNQVhfUENFTlQpKTtcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZV9hKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgQSA9IG5ldyBDYWxjUGFyc2VyKCdhbHBoYScsIHJlbGF0aXZlX2EsIGZyb21IU0xWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgcmdiLkEgPSBtaW5tYXgoQSwgMCwgTUFYX0FMUEhBKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3JnYiA9IHJnYjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2ggPSBoX2xlZ2FjeSA/PyBoO1xuICAgICAgICAgICAgdGhpcy5fcyA9IHNfbGVnYWN5ID8/IHM7XG4gICAgICAgICAgICB0aGlzLl9sID0gbF9sZWdhY3kgPz8gbDtcbiAgICAgICAgICAgIHRoaXMuX2EgPSBhX2xlZ2FjeSA/PyBhO1xuICAgICAgICAgICAgY29uc3QgcmdiID0gaHNsVG9SZ2Iobm9ybWFsaXplSHVlKHRoaXMuX2gpLCBwZXJjZW50KHRoaXMuX3MpLCBwZXJjZW50KHRoaXMuX2wpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZ2IuQSA9IG5vcm1hbGl6ZUFscGhhKHRoaXMuX2EpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgICAgICB9XG4gICAgfVxuICAgIHN0YXRpYyB0ZXN0KGNvbG9yU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBDT0xPUlJFR1MuSFNMLnRlc3QoY29sb3JTdHJpbmcpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENPTE9SUkVHUywgTUFYX0FMUEhBLCBNQVhfSFVFLCBNQVhfUENFTlQgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IG1pbm1heCwgbm9ybWFsaXplQWxwaGEsIG5vcm1hbGl6ZUh1ZSwgcGVyY2VudCB9IGZyb20gJyNoZWxwZXJzJztcbmltcG9ydCB7IGh3YlRvUmdiLCByZ2JUb0h3YiB9IGZyb20gJyNjb2xvci90cmFuc2xhdG9ycyc7XG5pbXBvcnQgeyBDYWxjUGFyc2VyIH0gZnJvbSAnLi9fQ2FsY1BhcnNlcic7XG5pbXBvcnQgeyBIdWVCYXNlQ2xhc3MgfSBmcm9tICcuL2Jhc2VDbGFzc2VzL19IdWVCYXNlQ2xhc3MnO1xuZXhwb3J0IGNsYXNzIEhXQlN0cmluZ1BhcnNlciBleHRlbmRzIEh1ZUJhc2VDbGFzcyB7XG4gICAgY29uc3RydWN0b3IoY29sb3JTdHJpbmcsIGdldFJHQk9iamVjdCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IGNvbG9yU3RyaW5nLm1hdGNoKENPTE9SUkVHUy5IV0IpO1xuICAgICAgICBjb25zdCBncm91cHMgPSBtYXRjaC5ncm91cHM7XG4gICAgICAgIGNvbnN0IHsgaCwgdywgYiwgYSwgZnJvbSwgcmVsYXRpdmVfaCwgcmVsYXRpdmVfdywgcmVsYXRpdmVfYiwgcmVsYXRpdmVfYSB9ID0gZ3JvdXBzO1xuICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgY29uc3QgZnJvbVJHQiA9IGdldFJHQk9iamVjdChmcm9tKTtcbiAgICAgICAgICAgIGNvbnN0IGZyb21IV0IgPSByZ2JUb0h3Yihmcm9tUkdCLlIsIGZyb21SR0IuRywgZnJvbVJHQi5CLCBmcm9tUkdCLkEpO1xuICAgICAgICAgICAgY29uc3QgZnJvbUhXQlZhcnMgPSB7XG4gICAgICAgICAgICAgICAgaDogZnJvbUhXQi5ILFxuICAgICAgICAgICAgICAgIHc6IGZyb21IV0IuVyxcbiAgICAgICAgICAgICAgICBiOiBmcm9tSFdCLkIsXG4gICAgICAgICAgICAgICAgYWxwaGE6IGZyb21IV0IuQVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IEggPSBuZXcgQ2FsY1BhcnNlcignaCcsIHJlbGF0aXZlX2gsIGZyb21IV0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICBjb25zdCBXID0gbmV3IENhbGNQYXJzZXIoJ3cnLCByZWxhdGl2ZV93LCBmcm9tSFdCVmFycykucmVzdWx0O1xuICAgICAgICAgICAgY29uc3QgQiA9IG5ldyBDYWxjUGFyc2VyKCdiJywgcmVsYXRpdmVfYiwgZnJvbUhXQlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGh3YlRvUmdiKG1pbm1heChILCAwLCBNQVhfSFVFKSwgbWlubWF4KFcsIDAsIE1BWF9QQ0VOVCksIG1pbm1heChCLCAwLCBNQVhfUENFTlQpKTtcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZV9hKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgQSA9IG5ldyBDYWxjUGFyc2VyKCdhbHBoYScsIHJlbGF0aXZlX2EsIGZyb21IV0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgcmdiLkEgPSBtaW5tYXgoQSwgMCwgTUFYX0FMUEhBKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3JnYiA9IHJnYjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2ggPSBoO1xuICAgICAgICAgICAgdGhpcy5fdyA9IHc7XG4gICAgICAgICAgICB0aGlzLl9iID0gYjtcbiAgICAgICAgICAgIHRoaXMuX2EgPSBhO1xuICAgICAgICAgICAgY29uc3QgcmdiID0gaHdiVG9SZ2Iobm9ybWFsaXplSHVlKHRoaXMuX2gpLCBwZXJjZW50KHRoaXMuX3cpLCBwZXJjZW50KHRoaXMuX2IpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZ2IuQSA9IG5vcm1hbGl6ZUFscGhhKHRoaXMuX2EpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgICAgICB9XG4gICAgfVxuICAgIHN0YXRpYyB0ZXN0KGNvbG9yU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBDT0xPUlJFR1MuSFdCLnRlc3QoY29sb3JTdHJpbmcpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENPTE9SUkVHUywgTUFYX0FMUEhBLCBNQVhfTEFCLCBNQVhfUENFTlQsIFBDRU5UIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRCYXNlMTI1TnVtYmVyLCBtaW5tYXgsIG5vcm1hbGl6ZUFscGhhLCBwZXJjZW50IH0gZnJvbSAnI2hlbHBlcnMnO1xuaW1wb3J0IHsgbGFiVG9SZ2IsIHJnYlRvTGFiIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IENhbGNQYXJzZXIgfSBmcm9tICcuL19DYWxjUGFyc2VyJztcbmltcG9ydCB7IEFscGhhQmFzZUNsYXNzIH0gZnJvbSAnLi9iYXNlQ2xhc3Nlcy9fQWxwaGFCYXNlQ2xhc3MnO1xuZXhwb3J0IGNsYXNzIENJRUxhYlN0cmluZ1BhcnNlciBleHRlbmRzIEFscGhhQmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcihjb2xvclN0cmluZywgZ2V0UkdCT2JqZWN0KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gY29sb3JTdHJpbmcubWF0Y2goQ09MT1JSRUdTLkNJRUxhYik7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IG1hdGNoLmdyb3VwcztcbiAgICAgICAgY29uc3QgeyBMLCBhLCBiLCBBLCBmcm9tLCByZWxhdGl2ZV9MLCByZWxhdGl2ZV9hLCByZWxhdGl2ZV9iLCByZWxhdGl2ZV9BIH0gPSBncm91cHM7XG4gICAgICAgIGlmIChmcm9tKSB7XG4gICAgICAgICAgICBjb25zdCBmcm9tUkdCID0gZ2V0UkdCT2JqZWN0KGZyb20pO1xuICAgICAgICAgICAgY29uc3QgZnJvbUxhYiA9IHJnYlRvTGFiKGZyb21SR0IuUiwgZnJvbVJHQi5HLCBmcm9tUkdCLkIpO1xuICAgICAgICAgICAgY29uc3QgZnJvbUxhYlZhcnMgPSB7XG4gICAgICAgICAgICAgICAgbDogZnJvbUxhYi5MLFxuICAgICAgICAgICAgICAgIGE6IGZyb21MYWIuYSxcbiAgICAgICAgICAgICAgICBiOiBmcm9tTGFiLmIsXG4gICAgICAgICAgICAgICAgYWxwaGE6IGZyb21SR0IuQSA/PyAxXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3QgTCA9IG5ldyBDYWxjUGFyc2VyKCdsJywgcmVsYXRpdmVfTCwgZnJvbUxhYlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgIGNvbnN0IGEgPSBuZXcgQ2FsY1BhcnNlcignYScsIHJlbGF0aXZlX2EsIGZyb21MYWJWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICBjb25zdCBiID0gbmV3IENhbGNQYXJzZXIoJ2InLCByZWxhdGl2ZV9iLCBmcm9tTGFiVmFycykucmVzdWx0O1xuICAgICAgICAgICAgY29uc3QgcmdiID0gbGFiVG9SZ2IobWlubWF4KEwsIDAsIE1BWF9QQ0VOVCksIG1pbm1heChhLCAtTUFYX0xBQiwgTUFYX0xBQiksIG1pbm1heChiLCAtTUFYX0xBQiwgTUFYX0xBQikpO1xuICAgICAgICAgICAgaWYgKHJlbGF0aXZlX0EpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBBID0gbmV3IENhbGNQYXJzZXIoJ2FscGhhJywgcmVsYXRpdmVfQSwgZnJvbUxhYlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICByZ2IuQSA9IG1pbm1heChBLCAwLCBNQVhfQUxQSEEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fTCA9IEw7XG4gICAgICAgICAgICB0aGlzLl9BID0gYTtcbiAgICAgICAgICAgIHRoaXMuX0IgPSBiO1xuICAgICAgICAgICAgdGhpcy5fYSA9IEE7XG4gICAgICAgICAgICBjb25zdCByZ2IgPSBsYWJUb1JnYihwZXJjZW50KHRoaXMuX0wpLCBnZXRCYXNlMTI1TnVtYmVyKHRoaXMuX0EpLCBnZXRCYXNlMTI1TnVtYmVyKHRoaXMuX0IpKTtcbiAgICAgICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZ2IuQSA9IG5vcm1hbGl6ZUFscGhhKHRoaXMuX2EpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgICAgICB9XG4gICAgfVxuICAgIGdldCBoYXNQZXJjZW50YWdlVmFsdWVzKCkge1xuICAgICAgICByZXR1cm4gKFBDRU5ULnRlc3QodGhpcy5fTCkgJiZcbiAgICAgICAgICAgIFBDRU5ULnRlc3QodGhpcy5fQSkgJiZcbiAgICAgICAgICAgIFBDRU5ULnRlc3QodGhpcy5fQikpO1xuICAgIH1cbiAgICBzdGF0aWMgdGVzdChjb2xvclN0cmluZykge1xuICAgICAgICByZXR1cm4gQ09MT1JSRUdTLkNJRUxhYi50ZXN0KGNvbG9yU3RyaW5nKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBDT0xPUlJFR1MsIE1BWF9BTFBIQSwgTUFYX0xDSF9DLCBNQVhfUENFTlQsIFBDRU5UIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRCYXNlMTUwTnVtYmVyLCBtaW5tYXgsIG5vcm1hbGl6ZUFscGhhLCBub3JtYWxpemVIdWUsIHBlcmNlbnQgfSBmcm9tICcjaGVscGVycyc7XG5pbXBvcnQgeyBsY2hUb1JnYiwgcmdiVG9MY2ggfSBmcm9tICcjY29sb3IvdHJhbnNsYXRvcnMnO1xuaW1wb3J0IHsgQ2FsY1BhcnNlciB9IGZyb20gJy4vX0NhbGNQYXJzZXInO1xuaW1wb3J0IHsgSHVlQmFzZUNsYXNzIH0gZnJvbSAnLi9iYXNlQ2xhc3Nlcy9fSHVlQmFzZUNsYXNzJztcbmV4cG9ydCBjbGFzcyBMQ0hTdHJpbmdQYXJzZXIgZXh0ZW5kcyBIdWVCYXNlQ2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKGNvbG9yU3RyaW5nLCBnZXRSR0JPYmplY3QpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBjb2xvclN0cmluZy5tYXRjaChDT0xPUlJFR1MuTENIKTtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gbWF0Y2guZ3JvdXBzO1xuICAgICAgICBjb25zdCB7IGwsIGMsIGgsIGEsIGZyb20sIHJlbGF0aXZlX2wsIHJlbGF0aXZlX2MsIHJlbGF0aXZlX2gsIHJlbGF0aXZlX2EgfSA9IGdyb3VwcztcbiAgICAgICAgaWYgKGZyb20pIHtcbiAgICAgICAgICAgIGNvbnN0IGZyb21SR0IgPSBnZXRSR0JPYmplY3QoZnJvbSk7XG4gICAgICAgICAgICBjb25zdCBmcm9tTENIID0gcmdiVG9MY2goZnJvbVJHQi5SLCBmcm9tUkdCLkcsIGZyb21SR0IuQik7XG4gICAgICAgICAgICBjb25zdCBmcm9tTENIVmFycyA9IHtcbiAgICAgICAgICAgICAgICBsOiBmcm9tTENILkwsXG4gICAgICAgICAgICAgICAgYzogZnJvbUxDSC5DLFxuICAgICAgICAgICAgICAgIGg6IGZyb21MQ0guSCxcbiAgICAgICAgICAgICAgICBhbHBoYTogZnJvbVJHQi5BID8/IDFcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCBMID0gbmV3IENhbGNQYXJzZXIoJ2wnLCByZWxhdGl2ZV9sLCBmcm9tTENIVmFycykucmVzdWx0O1xuICAgICAgICAgICAgY29uc3QgQyA9IG5ldyBDYWxjUGFyc2VyKCdjJywgcmVsYXRpdmVfYywgZnJvbUxDSFZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgIGNvbnN0IEggPSBuZXcgQ2FsY1BhcnNlcignaCcsIHJlbGF0aXZlX2gsIGZyb21MQ0hWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICBjb25zdCByZ2IgPSBsY2hUb1JnYihtaW5tYXgoTCwgMCwgTUFYX1BDRU5UKSwgbWlubWF4KEMsIC1NQVhfTENIX0MsIE1BWF9MQ0hfQyksIG5vcm1hbGl6ZUh1ZShIKSk7XG4gICAgICAgICAgICBpZiAocmVsYXRpdmVfYSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEEgPSBuZXcgQ2FsY1BhcnNlcignYWxwaGEnLCByZWxhdGl2ZV9hLCBmcm9tTENIVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIHJnYi5BID0gbWlubWF4KEEsIDAsIE1BWF9BTFBIQSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLl9yZ2IgPSByZ2I7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9sID0gbDtcbiAgICAgICAgICAgIHRoaXMuX2MgPSBjO1xuICAgICAgICAgICAgdGhpcy5faCA9IGg7XG4gICAgICAgICAgICB0aGlzLl9hID0gYTtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGxjaFRvUmdiKHBlcmNlbnQodGhpcy5fbCksIGdldEJhc2UxNTBOdW1iZXIodGhpcy5fYyksIG5vcm1hbGl6ZUh1ZSh0aGlzLl9oKSk7XG4gICAgICAgICAgICBpZiAodGhpcy5fYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmdiLkEgPSBub3JtYWxpemVBbHBoYSh0aGlzLl9hKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX3JnYiA9IHJnYjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBnZXQgaGFzUGVyY2VudGFnZVZhbHVlcygpIHtcbiAgICAgICAgcmV0dXJuIChQQ0VOVC50ZXN0KHRoaXMuX2wpICYmXG4gICAgICAgICAgICBQQ0VOVC50ZXN0KHRoaXMuX2MpKTtcbiAgICB9XG4gICAgc3RhdGljIHRlc3QoY29sb3JTdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIENPTE9SUkVHUy5MQ0gudGVzdChjb2xvclN0cmluZyk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQ09MT1JSRUdTLCBQQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0Q01ZS051bWJlciwgbm9ybWFsaXplQWxwaGEgfSBmcm9tICcjaGVscGVycyc7XG5pbXBvcnQgeyBjbXlrVG9SZ2IgfSBmcm9tICcjY29sb3IvdHJhbnNsYXRvcnMnO1xuaW1wb3J0IHsgQWxwaGFCYXNlQ2xhc3MgfSBmcm9tICcuL2Jhc2VDbGFzc2VzL19BbHBoYUJhc2VDbGFzcyc7XG5leHBvcnQgY2xhc3MgQ01ZS1N0cmluZ1BhcnNlciBleHRlbmRzIEFscGhhQmFzZUNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcihjb2xvclN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICBjb25zdCBtYXRjaCA9IGNvbG9yU3RyaW5nLm1hdGNoKENPTE9SUkVHUy5DTVlLKTtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gbWF0Y2guZ3JvdXBzO1xuICAgICAgICB0aGlzLl9jID0gZ3JvdXBzLmNfbGVnYWN5ID8/IGdyb3Vwcy5jO1xuICAgICAgICB0aGlzLl9tID0gZ3JvdXBzLm1fbGVnYWN5ID8/IGdyb3Vwcy5tO1xuICAgICAgICB0aGlzLl95ID0gZ3JvdXBzLnlfbGVnYWN5ID8/IGdyb3Vwcy55O1xuICAgICAgICB0aGlzLl9rID0gZ3JvdXBzLmtfbGVnYWN5ID8/IGdyb3Vwcy5rO1xuICAgICAgICB0aGlzLl9hID0gZ3JvdXBzLmFfbGVnYWN5ID8/IGdyb3Vwcy5hO1xuICAgICAgICBjb25zdCByZ2IgPSBjbXlrVG9SZ2IoZ2V0Q01ZS051bWJlcih0aGlzLl9jKSwgZ2V0Q01ZS051bWJlcih0aGlzLl9tKSwgZ2V0Q01ZS051bWJlcih0aGlzLl95KSwgZ2V0Q01ZS051bWJlcih0aGlzLl9rKSk7XG4gICAgICAgIGlmICh0aGlzLl9hICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJnYi5BID0gbm9ybWFsaXplQWxwaGEodGhpcy5fYSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fcmdiID0gcmdiO1xuICAgIH1cbiAgICBnZXQgaGFzUGVyY2VudGFnZVZhbHVlcygpIHtcbiAgICAgICAgcmV0dXJuIChQQ0VOVC50ZXN0KHRoaXMuX2MpICYmXG4gICAgICAgICAgICBQQ0VOVC50ZXN0KHRoaXMuX20pICYmXG4gICAgICAgICAgICBQQ0VOVC50ZXN0KHRoaXMuX3kpICYmXG4gICAgICAgICAgICBQQ0VOVC50ZXN0KHRoaXMuX2spKTtcbiAgICB9XG4gICAgc3RhdGljIHRlc3QoY29sb3JTdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIENPTE9SUkVHUy5DTVlLLnRlc3QoY29sb3JTdHJpbmcpO1xuICAgIH1cbn1cbiIsImV4cG9ydCB7IEhFWFN0cmluZ1BhcnNlciB9IGZyb20gJy4vX0hFWFN0cmluZ1BhcnNlcic7XG5leHBvcnQgeyBSR0JTdHJpbmdQYXJzZXIgfSBmcm9tICcuL19SR0JTdHJpbmdQYXJzZXInO1xuZXhwb3J0IHsgSFNMU3RyaW5nUGFyc2VyIH0gZnJvbSAnLi9fSFNMU3RyaW5nUGFyc2VyJztcbmV4cG9ydCB7IEhXQlN0cmluZ1BhcnNlciB9IGZyb20gJy4vX0hXQlN0cmluZ1BhcnNlcic7XG5leHBvcnQgeyBDSUVMYWJTdHJpbmdQYXJzZXIgfSBmcm9tICcuL19DSUVMYWJTdHJpbmdQYXJzZXInO1xuZXhwb3J0IHsgTENIU3RyaW5nUGFyc2VyIH0gZnJvbSAnLi9fTENIU3RyaW5nUGFyc2VyJztcbmV4cG9ydCB7IENNWUtTdHJpbmdQYXJzZXIgfSBmcm9tICcuL19DTVlLU3RyaW5nUGFyc2VyJztcbiIsImltcG9ydCB7IEFuZ2xlc1VuaXRFbnVtLCBDTVlLRnVuY3Rpb25FbnVtLCBDb2xvclVuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IEJBU0VfMjU1LCBDT0xPUl9LRVlTLCBDb2xvcktleXdvcmRzLCBDb2xvck1vZGVsLCBDT0xPUlJFR1MsIENPTU1BU19BTkRfTkVYVF9DSEFSUywgREVGQVVMVF9PUFRJT05TLCBFUlJPUlMsIEhFWCwgUENFTlQsIFNQQUNFUywgVHlwZU9mLCBWQUxJRF9DT0xPUl9PQkpFQ1RTIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRCYXNlMTI1TnVtYmVyLCBnZXRCYXNlMTUwTnVtYmVyLCBnZXRCYXNlMjU1TnVtYmVyLCBnZXRDTVlLTnVtYmVyLCBnZXRPcmRlcmVkQXJyYXlTdHJpbmcsIGhhc1Byb3AsIG5vcm1hbGl6ZUFscGhhLCBub3JtYWxpemVIdWUsIHBlcmNlbnQgfSBmcm9tICcjaGVscGVycyc7XG5pbXBvcnQgeyBDSUVMYWJTdHJpbmdQYXJzZXIsIENNWUtTdHJpbmdQYXJzZXIsIEhFWFN0cmluZ1BhcnNlciwgSFNMU3RyaW5nUGFyc2VyLCBIV0JTdHJpbmdQYXJzZXIsIExDSFN0cmluZ1BhcnNlciwgUkdCU3RyaW5nUGFyc2VyIH0gZnJvbSAnI3BhcnNlcnMnO1xuaW1wb3J0IHsgY215a1RvUmdiLCBoc2xUb1JnYiwgaHdiVG9SZ2IsIGxhYlRvUmdiLCBsY2hUb1JnYiB9IGZyb20gJyNjb2xvci90cmFuc2xhdG9ycyc7XG5jb25zdCBnZXRDb2xvck1vZGVsRnJvbVN0cmluZyA9IChjb2xvcikgPT4ge1xuICAgIGxldCBtb2RlbDtcbiAgICBPYmplY3Qua2V5cyhDb2xvck1vZGVsKS5zb21lKChwKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlZyA9IENPTE9SUkVHU1twXTtcbiAgICAgICAgaWYgKHJlZy50ZXN0KGNvbG9yKSkge1xuICAgICAgICAgICAgbW9kZWwgPSBwO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIW1vZGVsICYmXG4gICAgICAgICEhfkNPTE9SX0tFWVMuaW5kZXhPZihjb2xvcikpIHtcbiAgICAgICAgbW9kZWwgPSBDb2xvck1vZGVsLkhFWDtcbiAgICB9XG4gICAgaWYgKCFtb2RlbCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoRVJST1JTLk5PVF9BQ0NFUFRFRF9TVFJJTkdfSU5QVVQpO1xuICAgIH1cbiAgICByZXR1cm4gbW9kZWw7XG59O1xuY29uc3QgZ2V0Q29sb3JNb2RlbEZyb21PYmplY3QgPSAoY29sb3IpID0+IHtcbiAgICBsZXQgbW9kZWw7XG4gICAgbGV0IGludmFsaWQgPSBmYWxzZTtcbiAgICBjb25zdCBwcm9wcyA9IGdldE9yZGVyZWRBcnJheVN0cmluZyhPYmplY3Qua2V5cyhjb2xvcikpO1xuICAgIGlmIChWQUxJRF9DT0xPUl9PQkpFQ1RTW3Byb3BzXSkge1xuICAgICAgICBtb2RlbCA9IFZBTElEX0NPTE9SX09CSkVDVFNbcHJvcHNdO1xuICAgIH1cbiAgICBpZiAobW9kZWwgJiYgbW9kZWwgPT09IENvbG9yTW9kZWwuUkdCKSB7XG4gICAgICAgIGNvbnN0IGhhc0ludmFsaWRIZXggPSBPYmplY3QuZW50cmllcyhjb2xvcikuc29tZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICFIRVgudGVzdChgJHtpdGVtWzFdfWApO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgaGFzSW52YWxpZFJlZ2IgPSBPYmplY3QuZW50cmllcyhjb2xvcikuc29tZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICEoUENFTlQudGVzdChgJHtpdGVtWzFdfWApIHx8XG4gICAgICAgICAgICAgICAgKCFIRVgudGVzdChgJHtpdGVtWzFdfWApICYmXG4gICAgICAgICAgICAgICAgICAgICFpc05hTigraXRlbVsxXSkgJiZcbiAgICAgICAgICAgICAgICAgICAgK2l0ZW1bMV0gPD0gQkFTRV8yNTUpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChoYXNJbnZhbGlkSGV4ICYmIGhhc0ludmFsaWRSZWdiKSB7XG4gICAgICAgICAgICBpbnZhbGlkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWhhc0ludmFsaWRIZXgpIHtcbiAgICAgICAgICAgIG1vZGVsID0gQ29sb3JNb2RlbC5IRVg7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFtb2RlbCB8fCBpbnZhbGlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihFUlJPUlMuTk9UX0FDQ0VQVEVEX09CSkVDVF9JTlBVVCk7XG4gICAgfVxuICAgIHJldHVybiBtb2RlbDtcbn07XG5leHBvcnQgY29uc3QgZ2V0Q29sb3JNb2RlbCA9IChjb2xvcikgPT4gdHlwZW9mIGNvbG9yID09PSAnc3RyaW5nJ1xuICAgID8gZ2V0Q29sb3JNb2RlbEZyb21TdHJpbmcoY29sb3IpXG4gICAgOiBnZXRDb2xvck1vZGVsRnJvbU9iamVjdChjb2xvcik7XG5leHBvcnQgY29uc3QgZ2V0UkdCT2JqZWN0RnJvbVN0cmluZyA9IHtcbiAgICBbQ29sb3JNb2RlbC5IRVhdKGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IGNvbG9yU3RyID0gIX5DT0xPUl9LRVlTLmluZGV4T2YoY29sb3IpXG4gICAgICAgICAgICA/IGNvbG9yXG4gICAgICAgICAgICA6IENvbG9yS2V5d29yZHNbY29sb3JdO1xuICAgICAgICByZXR1cm4gbmV3IEhFWFN0cmluZ1BhcnNlcihjb2xvclN0cikucmdiO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuUkdCXShjb2xvcikge1xuICAgICAgICByZXR1cm4gbmV3IFJHQlN0cmluZ1BhcnNlcihjb2xvciwgZ2V0UkdCT2JqZWN0KS5yZ2I7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IU0xdKGNvbG9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgSFNMU3RyaW5nUGFyc2VyKGNvbG9yLCBnZXRSR0JPYmplY3QpLnJnYjtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkhXQl0oY29sb3IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBIV0JTdHJpbmdQYXJzZXIoY29sb3IsIGdldFJHQk9iamVjdCkucmdiO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuQ0lFTGFiXShjb2xvcikge1xuICAgICAgICByZXR1cm4gbmV3IENJRUxhYlN0cmluZ1BhcnNlcihjb2xvciwgZ2V0UkdCT2JqZWN0KS5yZ2I7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5MQ0hdKGNvbG9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgTENIU3RyaW5nUGFyc2VyKGNvbG9yLCBnZXRSR0JPYmplY3QpLnJnYjtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkNNWUtdKGNvbG9yKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ01ZS1N0cmluZ1BhcnNlcihjb2xvcikucmdiO1xuICAgIH1cbn07XG5leHBvcnQgY29uc3QgZ2V0UkdCT2JqZWN0RnJvbU9iamVjdCA9IHtcbiAgICBbQ29sb3JNb2RlbC5IRVhdKGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IG9iamVjdCA9IHtcbiAgICAgICAgICAgIFI6IGdldEJhc2UyNTVOdW1iZXIoYCR7Y29sb3IuUn1gKSxcbiAgICAgICAgICAgIEc6IGdldEJhc2UyNTVOdW1iZXIoYCR7Y29sb3IuR31gKSxcbiAgICAgICAgICAgIEI6IGdldEJhc2UyNTVOdW1iZXIoYCR7Y29sb3IuQn1gKVxuICAgICAgICB9O1xuICAgICAgICBpZiAoaGFzUHJvcChjb2xvciwgJ0EnKSkge1xuICAgICAgICAgICAgb2JqZWN0LkEgPSBNYXRoLm1pbihnZXRCYXNlMjU1TnVtYmVyKGAke2NvbG9yLkF9YCwgdHJ1ZSksIDEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5SR0JdKGNvbG9yKSB7XG4gICAgICAgIHJldHVybiB0aGlzLkhFWChjb2xvcik7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IU0xdKGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IFMgPSBwZXJjZW50KGAke2NvbG9yLlN9YCk7XG4gICAgICAgIGNvbnN0IEwgPSBwZXJjZW50KGAke2NvbG9yLkx9YCk7XG4gICAgICAgIGNvbnN0IFJHQiA9IGhzbFRvUmdiKG5vcm1hbGl6ZUh1ZShjb2xvci5IKSwgUywgTCk7XG4gICAgICAgIGlmIChoYXNQcm9wKGNvbG9yLCAnQScpKSB7XG4gICAgICAgICAgICBSR0IuQSA9IG5vcm1hbGl6ZUFscGhhKGNvbG9yLkEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSR0I7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IV0JdKGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IFcgPSBwZXJjZW50KGAke2NvbG9yLld9YCk7XG4gICAgICAgIGNvbnN0IEIgPSBwZXJjZW50KGAke2NvbG9yLkJ9YCk7XG4gICAgICAgIGNvbnN0IFJHQiA9IGh3YlRvUmdiKG5vcm1hbGl6ZUh1ZShjb2xvci5IKSwgVywgQik7XG4gICAgICAgIGlmIChoYXNQcm9wKGNvbG9yLCAnQScpKSB7XG4gICAgICAgICAgICBSR0IuQSA9IG5vcm1hbGl6ZUFscGhhKGNvbG9yLkEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSR0I7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5DSUVMYWJdKGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IEwgPSBwZXJjZW50KGAke2NvbG9yLkx9YCk7XG4gICAgICAgIGNvbnN0IGEgPSBnZXRCYXNlMTI1TnVtYmVyKGAke2NvbG9yLmF9YCk7XG4gICAgICAgIGNvbnN0IGIgPSBnZXRCYXNlMTI1TnVtYmVyKGAke2NvbG9yLmJ9YCk7XG4gICAgICAgIGNvbnN0IFJHQiA9IGxhYlRvUmdiKEwsIGEsIGIpO1xuICAgICAgICBpZiAoaGFzUHJvcChjb2xvciwgJ0EnKSkge1xuICAgICAgICAgICAgUkdCLkEgPSBub3JtYWxpemVBbHBoYShjb2xvci5BKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUkdCO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuTENIXShjb2xvcikge1xuICAgICAgICBjb25zdCBMID0gcGVyY2VudChgJHtjb2xvci5MfWApO1xuICAgICAgICBjb25zdCBDID0gZ2V0QmFzZTE1ME51bWJlcihgJHtjb2xvci5DfWApO1xuICAgICAgICBjb25zdCBIID0gbm9ybWFsaXplSHVlKGAke2NvbG9yLkh9YCk7XG4gICAgICAgIGNvbnN0IFJHQiA9IGxjaFRvUmdiKEwsIEMsIEgpO1xuICAgICAgICBpZiAoaGFzUHJvcChjb2xvciwgJ0EnKSkge1xuICAgICAgICAgICAgUkdCLkEgPSBub3JtYWxpemVBbHBoYShjb2xvci5BKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUkdCO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuQ01ZS10oY29sb3IpIHtcbiAgICAgICAgY29uc3QgQyA9IGdldENNWUtOdW1iZXIoYCR7Y29sb3IuQ31gKTtcbiAgICAgICAgY29uc3QgTSA9IGdldENNWUtOdW1iZXIoYCR7Y29sb3IuTX1gKTtcbiAgICAgICAgY29uc3QgWSA9IGdldENNWUtOdW1iZXIoYCR7Y29sb3IuWX1gKTtcbiAgICAgICAgY29uc3QgSyA9IGdldENNWUtOdW1iZXIoYCR7Y29sb3IuS31gKTtcbiAgICAgICAgY29uc3QgUkdCID0gY215a1RvUmdiKEMsIE0sIFksIEspO1xuICAgICAgICBpZiAoaGFzUHJvcChjb2xvciwgJ0EnKSkge1xuICAgICAgICAgICAgUkdCLkEgPSBub3JtYWxpemVBbHBoYShjb2xvci5BKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUkdCO1xuICAgIH1cbn07XG5leHBvcnQgY29uc3QgZ2V0UkdCT2JqZWN0ID0gKGNvbG9yLCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpKSA9PiB7XG4gICAgcmV0dXJuIHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZydcbiAgICAgICAgPyBnZXRSR0JPYmplY3RGcm9tU3RyaW5nW21vZGVsXShjb2xvcilcbiAgICAgICAgOiBnZXRSR0JPYmplY3RGcm9tT2JqZWN0W21vZGVsXShjb2xvcik7XG59O1xuZXhwb3J0IGNvbnN0IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dCA9IChvcHRpb25zLCAuLi5jb2xvcnMpID0+IHtcbiAgICBjb25zdCBjc3NDb2xvcnMgPSBbXTtcbiAgICBjb25zdCBhbmdsZXNVbml0cyA9IFtdO1xuICAgIGNvbnN0IHJnYkNvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGxhYkNvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGxjaENvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGNteWtDb2xvcnMgPSBbXTtcbiAgICBjb25zdCBhbHBoYVZhbHVlcyA9IFtdO1xuICAgIGNvbnN0IGFuZ2xlc1VuaXRWYWx1ZXMgPSBPYmplY3QudmFsdWVzKEFuZ2xlc1VuaXRFbnVtKTtcbiAgICBjb25zdCBjb2xvclVuaXRWYWx1ZXMgPSBPYmplY3QudmFsdWVzKENvbG9yVW5pdEVudW0pO1xuICAgIGNvbnN0IGNteWtGdW5jdGlvblZhbHVlcyA9IE9iamVjdC52YWx1ZXMoQ01ZS0Z1bmN0aW9uRW51bSk7XG4gICAgY29uc3QgbWF0Y2hPcHRpb25zID0ge1xuICAgICAgICBsZWdhY3lDU1M6IDAsXG4gICAgICAgIHNwYWNlc0FmdGVyQ29tbWFzOiAwLFxuICAgICAgICBjbXlrRnVuY3Rpb246IDBcbiAgICB9O1xuICAgIGZvciAoY29uc3QgY29sb3Igb2YgY29sb3JzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgY29sb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjc3NDb2xvcnMucHVzaChjb2xvcik7XG4gICAgICAgICAgICBpZiAoY29sb3IuaW5jbHVkZXMoJywnKSkge1xuICAgICAgICAgICAgICAgIG1hdGNoT3B0aW9ucy5sZWdhY3lDU1MrKztcbiAgICAgICAgICAgICAgICBjb25zdCBjb21tYXNXaXRoTmV4dENoYXJhY3RlciA9IGNvbG9yLm1hdGNoKENPTU1BU19BTkRfTkVYVF9DSEFSUyk7XG4gICAgICAgICAgICAgICAgaWYgKG5ldyBTZXQoY29tbWFzV2l0aE5leHRDaGFyYWN0ZXIpLnNpemUgPT09IDEgJiZcbiAgICAgICAgICAgICAgICAgICAgU1BBQ0VTLnRlc3QoY29tbWFzV2l0aE5leHRDaGFyYWN0ZXJbMF0uc2xpY2UoMSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoT3B0aW9ucy5zcGFjZXNBZnRlckNvbW1hcysrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChIU0xTdHJpbmdQYXJzZXIudGVzdChjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgSFNMU3RyaW5nUGFyc2VyKGNvbG9yLCBnZXRSR0JPYmplY3QpO1xuICAgICAgICAgICAgICAgIGFuZ2xlc1VuaXRzLnB1c2gocGFyc2VyLmFuZ2xlVW5pdCk7XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChwYXJzZXIuaGFzUGVyY2VudGFnZUFscGhhKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChIV0JTdHJpbmdQYXJzZXIudGVzdChjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgSFdCU3RyaW5nUGFyc2VyKGNvbG9yLCBnZXRSR0JPYmplY3QpO1xuICAgICAgICAgICAgICAgIGFuZ2xlc1VuaXRzLnB1c2gocGFyc2VyLmFuZ2xlVW5pdCk7XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChwYXJzZXIuaGFzUGVyY2VudGFnZUFscGhhKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChSR0JTdHJpbmdQYXJzZXIudGVzdChjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgUkdCU3RyaW5nUGFyc2VyKGNvbG9yLCBnZXRSR0JPYmplY3QpO1xuICAgICAgICAgICAgICAgIHJnYkNvbG9ycy5wdXNoKHBhcnNlci5oYXNQZXJjZW50YWdlVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBhbHBoYVZhbHVlcy5wdXNoKHBhcnNlci5oYXNQZXJjZW50YWdlQWxwaGEpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKENJRUxhYlN0cmluZ1BhcnNlci50ZXN0KGNvbG9yKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBDSUVMYWJTdHJpbmdQYXJzZXIoY29sb3IsIGdldFJHQk9iamVjdCk7XG4gICAgICAgICAgICAgICAgbGFiQ29sb3JzLnB1c2gocGFyc2VyLmhhc1BlcmNlbnRhZ2VWYWx1ZXMpO1xuICAgICAgICAgICAgICAgIGFscGhhVmFsdWVzLnB1c2gocGFyc2VyLmhhc1BlcmNlbnRhZ2VBbHBoYSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoTENIU3RyaW5nUGFyc2VyLnRlc3QoY29sb3IpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IExDSFN0cmluZ1BhcnNlcihjb2xvciwgZ2V0UkdCT2JqZWN0KTtcbiAgICAgICAgICAgICAgICBhbmdsZXNVbml0cy5wdXNoKHBhcnNlci5hbmdsZVVuaXQpO1xuICAgICAgICAgICAgICAgIGxjaENvbG9ycy5wdXNoKHBhcnNlci5oYXNQZXJjZW50YWdlVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBhbHBoYVZhbHVlcy5wdXNoKHBhcnNlci5oYXNQZXJjZW50YWdlQWxwaGEpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKENNWUtTdHJpbmdQYXJzZXIudGVzdChjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgQ01ZS1N0cmluZ1BhcnNlcihjb2xvcik7XG4gICAgICAgICAgICAgICAgY215a0NvbG9ycy5wdXNoKHBhcnNlci5oYXNQZXJjZW50YWdlVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBpZiAoY29sb3Iuc3RhcnRzV2l0aCgnY215aycpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoT3B0aW9ucy5jbXlrRnVuY3Rpb24rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChwYXJzZXIuaGFzUGVyY2VudGFnZUFscGhhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBkZWNpbWFsczogdHlwZW9mIG9wdGlvbnMuZGVjaW1hbHMgPT09IFR5cGVPZi5OVU1CRVJcbiAgICAgICAgICAgID8gb3B0aW9ucy5kZWNpbWFsc1xuICAgICAgICAgICAgOiBERUZBVUxUX09QVElPTlMuZGVjaW1hbHMsXG4gICAgICAgIGxlZ2FjeUNTUzogdHlwZW9mIG9wdGlvbnMubGVnYWN5Q1NTID09PSBUeXBlT2YuQk9PTEVBTlxuICAgICAgICAgICAgPyBvcHRpb25zLmxlZ2FjeUNTU1xuICAgICAgICAgICAgOiBCb29sZWFuKGNzc0NvbG9ycy5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICBtYXRjaE9wdGlvbnMubGVnYWN5Q1NTID09PSBjc3NDb2xvcnMubGVuZ3RoKSB8fCBERUZBVUxUX09QVElPTlMubGVnYWN5Q1NTLFxuICAgICAgICBzcGFjZXNBZnRlckNvbW1hczogdHlwZW9mIG9wdGlvbnMuc3BhY2VzQWZ0ZXJDb21tYXMgPT09IFR5cGVPZi5CT09MRUFOXG4gICAgICAgICAgICA/IG9wdGlvbnMuc3BhY2VzQWZ0ZXJDb21tYXNcbiAgICAgICAgICAgIDogQm9vbGVhbihjc3NDb2xvcnMubGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgbWF0Y2hPcHRpb25zLnNwYWNlc0FmdGVyQ29tbWFzID09PSBjc3NDb2xvcnMubGVuZ3RoKSB8fCBERUZBVUxUX09QVElPTlMuc3BhY2VzQWZ0ZXJDb21tYXMsXG4gICAgICAgIGFuZ2xlc1VuaXQ6IG9wdGlvbnMuYW5nbGVzVW5pdCAmJiBhbmdsZXNVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMuYW5nbGVzVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5hbmdsZXNVbml0XG4gICAgICAgICAgICA6IChuZXcgU2V0KGFuZ2xlc1VuaXRzKS5zaXplID09PSAxXG4gICAgICAgICAgICAgICAgPyBhbmdsZXNVbml0c1swXVxuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmFuZ2xlc1VuaXQpLFxuICAgICAgICByZ2JVbml0OiBvcHRpb25zLnJnYlVuaXQgJiYgY29sb3JVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMucmdiVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5yZ2JVbml0XG4gICAgICAgICAgICA6IChuZXcgU2V0KHJnYkNvbG9ycykuc2l6ZSA9PT0gMSAmJiByZ2JDb2xvcnNbMF1cbiAgICAgICAgICAgICAgICA/IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLnJnYlVuaXQpLFxuICAgICAgICBsYWJVbml0OiBvcHRpb25zLmxhYlVuaXQgJiYgY29sb3JVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMubGFiVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5sYWJVbml0XG4gICAgICAgICAgICA6IChuZXcgU2V0KGxhYkNvbG9ycykuc2l6ZSA9PT0gMSAmJiBsYWJDb2xvcnNbMF1cbiAgICAgICAgICAgICAgICA/IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmxhYlVuaXQpLFxuICAgICAgICBsY2hVbml0OiBvcHRpb25zLmxjaFVuaXQgJiYgY29sb3JVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMubGNoVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5sY2hVbml0XG4gICAgICAgICAgICA6IChuZXcgU2V0KGxjaENvbG9ycykuc2l6ZSA9PT0gMSAmJiBsY2hDb2xvcnNbMF1cbiAgICAgICAgICAgICAgICA/IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmxjaFVuaXQpLFxuICAgICAgICBjbXlrVW5pdDogb3B0aW9ucy5jbXlrVW5pdCAmJiBjb2xvclVuaXRWYWx1ZXMuaW5jbHVkZXMob3B0aW9ucy5jbXlrVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5jbXlrVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChjbXlrQ29sb3JzKS5zaXplID09PSAxICYmICFjbXlrQ29sb3JzWzBdXG4gICAgICAgICAgICAgICAgPyBDb2xvclVuaXRFbnVtLk5PTkVcbiAgICAgICAgICAgICAgICA6IERFRkFVTFRfT1BUSU9OUy5jbXlrVW5pdCksXG4gICAgICAgIGFscGhhVW5pdDogb3B0aW9ucy5hbHBoYVVuaXQgJiYgY29sb3JVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMuYWxwaGFVbml0KVxuICAgICAgICAgICAgPyBvcHRpb25zLmFscGhhVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChhbHBoYVZhbHVlcykuc2l6ZSA9PT0gMSAmJiBhbHBoYVZhbHVlc1swXVxuICAgICAgICAgICAgICAgID8gQ29sb3JVbml0RW51bS5QRVJDRU5UXG4gICAgICAgICAgICAgICAgOiBERUZBVUxUX09QVElPTlMuYWxwaGFVbml0KSxcbiAgICAgICAgY215a0Z1bmN0aW9uOiBvcHRpb25zLmNteWtGdW5jdGlvbiAmJiBjbXlrRnVuY3Rpb25WYWx1ZXMuaW5jbHVkZXMob3B0aW9ucy5jbXlrRnVuY3Rpb24pXG4gICAgICAgICAgICA/IG9wdGlvbnMuY215a0Z1bmN0aW9uXG4gICAgICAgICAgICA6IChjbXlrQ29sb3JzLmxlbmd0aCAmJiBjbXlrQ29sb3JzLmxlbmd0aCA9PT0gbWF0Y2hPcHRpb25zLmNteWtGdW5jdGlvblxuICAgICAgICAgICAgICAgID8gQ01ZS0Z1bmN0aW9uRW51bS5DTVlLXG4gICAgICAgICAgICAgICAgOiBERUZBVUxUX09QVElPTlMuY215a0Z1bmN0aW9uKVxuICAgIH07XG59O1xuIiwiaW1wb3J0IHsgcm91bmQgfSBmcm9tICcjaGVscGVycyc7XG5leHBvcnQgY29uc3Qgcm91bmRIU0xPYmplY3QgPSAoY29sb3IsIGRlY2ltYWxzKSA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgSDogcm91bmQoY29sb3IuSCwgZGVjaW1hbHMpLFxuICAgICAgICBTOiByb3VuZChjb2xvci5TLCBkZWNpbWFscyksXG4gICAgICAgIEw6IHJvdW5kKGNvbG9yLkwsIGRlY2ltYWxzKVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IHJvdW5kSFdCT2JqZWN0ID0gKGNvbG9yLCBkZWNpbWFscykgPT4ge1xuICAgIHJldHVybiB7XG4gICAgICAgIEg6IHJvdW5kKGNvbG9yLkgsIGRlY2ltYWxzKSxcbiAgICAgICAgVzogcm91bmQoY29sb3IuVywgZGVjaW1hbHMpLFxuICAgICAgICBCOiByb3VuZChjb2xvci5CLCBkZWNpbWFscylcbiAgICB9O1xufTtcbmV4cG9ydCBjb25zdCByb3VuZENJRUxhYk9iamVjdCA9IChjb2xvciwgZGVjaW1hbHMpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBMOiByb3VuZChjb2xvci5MLCBkZWNpbWFscyksXG4gICAgICAgIGE6IHJvdW5kKGNvbG9yLmEsIGRlY2ltYWxzKSxcbiAgICAgICAgYjogcm91bmQoY29sb3IuYiwgZGVjaW1hbHMpXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3Qgcm91bmRMQ0hPYmplY3QgPSAoY29sb3IsIGRlY2ltYWxzKSA9PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgTDogcm91bmQoY29sb3IuTCwgZGVjaW1hbHMpLFxuICAgICAgICBDOiByb3VuZChjb2xvci5DLCBkZWNpbWFscyksXG4gICAgICAgIEg6IHJvdW5kKGNvbG9yLkgsIGRlY2ltYWxzKVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IHJvdW5kQ01ZS09iamVjdCA9IChjb2xvciwgZGVjaW1hbHMpID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgICBDOiByb3VuZChjb2xvci5DLCBkZWNpbWFscyksXG4gICAgICAgIE06IHJvdW5kKGNvbG9yLk0sIGRlY2ltYWxzKSxcbiAgICAgICAgWTogcm91bmQoY29sb3IuWSwgZGVjaW1hbHMpLFxuICAgICAgICBLOiByb3VuZChjb2xvci5LLCBkZWNpbWFscylcbiAgICB9O1xufTtcbiIsImltcG9ydCB7IEFuZ2xlc1VuaXRFbnVtLCBDb2xvclVuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IENPTE9SX1BST1BTLCBDb2xvck1vZGVsLCBURU1QTEFURV9WQVIsIFZBTElEX0NPTE9SX09CSkVDVFMgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IGZyb20xMjVOdW1iZXJUb1BlcmNlbnQsIGZyb20xNTBOdW1iZXJUb1BlcmNlbnQsIGZyb20yNTVOdW1iZXJUb1BlcmNlbnQsIGdldE9yZGVyZWRBcnJheVN0cmluZywgcGVyY2VudCwgcm91bmQsIHRvSEVYLCB0cmFuc2xhdGVEZWdyZWVzIH0gZnJvbSAnI2hlbHBlcnMnO1xuY29uc3QgZ2V0Q29tbWEgPSAod2l0aFNwYWNlKSA9PiB3aXRoU3BhY2VcbiAgICA/ICcsICdcbiAgICA6ICcsJztcbmNvbnN0IHByZXBhcmVDb2xvckZvckNzcyA9IChjb2xvciwgdHJhbnNmb3JtZXIpID0+IHtcbiAgICBjb25zdCBwcm9wcyA9IGdldE9yZGVyZWRBcnJheVN0cmluZyhPYmplY3Qua2V5cyhjb2xvcikpO1xuICAgIGNvbnN0IG1vZGVsID0gVkFMSURfQ09MT1JfT0JKRUNUU1twcm9wc107XG4gICAgY29uc3Qga2V5cyA9IENPTE9SX1BST1BTW21vZGVsXTtcbiAgICByZXR1cm4ga2V5cy5yZWR1Y2UoKHJlc3VsdCwga2V5LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbG9yW2tleV07XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh0cmFuc2Zvcm1lcih2YWx1ZSwgaW5kZXgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIFtdKTtcbn07XG5jb25zdCBnZXRSZXN1bHRGcm9tVGVtcGxhdGUgPSAodGVtcGxhdGUsIHZhcnMpID0+IHtcbiAgICByZXR1cm4gdGVtcGxhdGUucmVwbGFjZShURU1QTEFURV9WQVIsIChfX21hdGNoLCBpbmRleFN0cikgPT4ge1xuICAgICAgICBjb25zdCBpbmRleCA9ICtpbmRleFN0ciAtIDE7XG4gICAgICAgIHJldHVybiBgJHt2YXJzW2luZGV4XX1gO1xuICAgIH0pO1xufTtcbmNvbnN0IGdldEFscGhhID0gKHZhbHVlLCBvcHRpb25zLCBpZ25vcmVMZWdhY3kgPSBmYWxzZSkgPT4ge1xuICAgIGNvbnN0IHsgYWxwaGFVbml0LCBsZWdhY3lDU1MsIGRlY2ltYWxzIH0gPSBvcHRpb25zO1xuICAgIGlmIChhbHBoYVVuaXQgPT09IENvbG9yVW5pdEVudW0uUEVSQ0VOVCAmJlxuICAgICAgICAoIWxlZ2FjeUNTUyB8fFxuICAgICAgICAgICAgaWdub3JlTGVnYWN5KSkge1xuICAgICAgICByZXR1cm4gYCR7cm91bmQodmFsdWUgKiAxMDAsIGRlY2ltYWxzKX0lYDtcbiAgICB9XG4gICAgcmV0dXJuIHJvdW5kKHZhbHVlLCBkZWNpbWFscyk7XG59O1xuY29uc3QgYnVpbGRIdWVUcmFuc2Zvcm1lciA9IChvcHRpb25zKSA9PiB7XG4gICAgY29uc3QgeyBhbmdsZXNVbml0LCBkZWNpbWFscyB9ID0gb3B0aW9ucztcbiAgICByZXR1cm4gKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaW5kZXggPT09IDAgJiZcbiAgICAgICAgICAgIGFuZ2xlc1VuaXQgIT09IEFuZ2xlc1VuaXRFbnVtLk5PTkUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zbGF0ZWQgPSByb3VuZCh0cmFuc2xhdGVEZWdyZWVzKHZhbHVlLCBhbmdsZXNVbml0KSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgcmV0dXJuIGAke3RyYW5zbGF0ZWR9JHthbmdsZXNVbml0fWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGluZGV4ID09PSAzXG4gICAgICAgICAgICA/IGdldEFscGhhKHZhbHVlLCBvcHRpb25zKVxuICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpO1xuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IENTUyA9IHtcbiAgICBbQ29sb3JNb2RlbC5IRVhdOiAoY29sb3IpID0+IHtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSAodmFsdWUpID0+IHRvSEVYKHJvdW5kKHZhbHVlKSk7XG4gICAgICAgIGNvbnN0IHZhbHVlcyA9IHByZXBhcmVDb2xvckZvckNzcyhjb2xvciwgdHJhbnNmb3JtZXIpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IHZhbHVlcy5sZW5ndGggPT09IDRcbiAgICAgICAgICAgID8gJyN7MX17Mn17M317NH0nXG4gICAgICAgICAgICA6ICcjezF9ezJ9ezN9JztcbiAgICAgICAgcmV0dXJuIGdldFJlc3VsdEZyb21UZW1wbGF0ZSh0ZW1wbGF0ZSwgdmFsdWVzKTtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLlJHQl06IChjb2xvciwgb3B0aW9ucykgPT4ge1xuICAgICAgICBjb25zdCB7IGRlY2ltYWxzLCBsZWdhY3lDU1MsIHNwYWNlc0FmdGVyQ29tbWFzLCByZ2JVbml0IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBjb21tYSA9IGdldENvbW1hKHNwYWNlc0FmdGVyQ29tbWFzKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSAodmFsdWUsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcmdiVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UICYmIGluZGV4IDwgM1xuICAgICAgICAgICAgICAgID8gYCR7ZnJvbTI1NU51bWJlclRvUGVyY2VudCh2YWx1ZSwgZGVjaW1hbHMpfSVgXG4gICAgICAgICAgICAgICAgOiAoaW5kZXggPT09IDNcbiAgICAgICAgICAgICAgICAgICAgPyBnZXRBbHBoYSh2YWx1ZSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGNvbG9yLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gbGVnYWN5Q1NTXG4gICAgICAgICAgICA/ICh2YWx1ZXMubGVuZ3RoID09PSA0XG4gICAgICAgICAgICAgICAgPyBgcmdiYSh7MX0ke2NvbW1hfXsyfSR7Y29tbWF9ezN9JHtjb21tYX17NH0pYFxuICAgICAgICAgICAgICAgIDogYHJnYih7MX0ke2NvbW1hfXsyfSR7Y29tbWF9ezN9KWApXG4gICAgICAgICAgICA6ICh2YWx1ZXMubGVuZ3RoID09PSA0XG4gICAgICAgICAgICAgICAgPyBgcmdiKHsxfSB7Mn0gezN9IC8gezR9KWBcbiAgICAgICAgICAgICAgICA6IGByZ2IoezF9IHsyfSB7M30pYCk7XG4gICAgICAgIHJldHVybiBnZXRSZXN1bHRGcm9tVGVtcGxhdGUodGVtcGxhdGUsIHZhbHVlcyk7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IU0xdOiAoY29sb3IsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgeyBsZWdhY3lDU1MsIHNwYWNlc0FmdGVyQ29tbWFzIH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBjb21tYSA9IGdldENvbW1hKHNwYWNlc0FmdGVyQ29tbWFzKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBidWlsZEh1ZVRyYW5zZm9ybWVyKG9wdGlvbnMpO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MoY29sb3IsIHRyYW5zZm9ybWVyKTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGUgPSBsZWdhY3lDU1NcbiAgICAgICAgICAgID8gKHZhbHVlcy5sZW5ndGggPT09IDRcbiAgICAgICAgICAgICAgICA/IGBoc2xhKHsxfSR7Y29tbWF9ezJ9JSR7Y29tbWF9ezN9JSR7Y29tbWF9ezR9KWBcbiAgICAgICAgICAgICAgICA6IGBoc2woezF9JHtjb21tYX17Mn0lJHtjb21tYX17M30lKWApXG4gICAgICAgICAgICA6ICh2YWx1ZXMubGVuZ3RoID09PSA0XG4gICAgICAgICAgICAgICAgPyBgaHNsKHsxfSB7Mn0lIHszfSUgLyB7NH0pYFxuICAgICAgICAgICAgICAgIDogYGhzbCh7MX0gezJ9JSB7M30lKWApO1xuICAgICAgICByZXR1cm4gZ2V0UmVzdWx0RnJvbVRlbXBsYXRlKHRlbXBsYXRlLCB2YWx1ZXMpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuSFdCXTogKGNvbG9yLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gYnVpbGRIdWVUcmFuc2Zvcm1lcihvcHRpb25zKTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGNvbG9yLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gdmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgPyBgaHdiKHsxfSB7Mn0lIHszfSUgLyB7NH0pYFxuICAgICAgICAgICAgOiBgaHdiKHsxfSB7Mn0lIHszfSUpYDtcbiAgICAgICAgcmV0dXJuIGdldFJlc3VsdEZyb21UZW1wbGF0ZSh0ZW1wbGF0ZSwgdmFsdWVzKTtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkNJRUxhYl06IChjb2xvciwgb3B0aW9ucykgPT4ge1xuICAgICAgICBjb25zdCB7IGRlY2ltYWxzLCBsYWJVbml0IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9ICh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEwgPSByb3VuZChwZXJjZW50KHZhbHVlKSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJVbml0ID09PSBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICAgICAgPyBgJHtMfSVgXG4gICAgICAgICAgICAgICAgICAgIDogYCR7TH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZGV4IDwgMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJVbml0ID09PSBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICAgICAgPyBgJHtmcm9tMTI1TnVtYmVyVG9QZXJjZW50KHZhbHVlLCBkZWNpbWFscyl9JWBcbiAgICAgICAgICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGdldEFscGhhKHZhbHVlLCBvcHRpb25zLCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGNvbG9yLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gdmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgPyBgbGFiKHsxfSB7Mn0gezN9IC8gezR9KWBcbiAgICAgICAgICAgIDogYGxhYih7MX0gezJ9IHszfSlgO1xuICAgICAgICByZXR1cm4gZ2V0UmVzdWx0RnJvbVRlbXBsYXRlKHRlbXBsYXRlLCB2YWx1ZXMpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuTENIXTogKGNvbG9yLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZGVjaW1hbHMsIGxjaFVuaXQsIGFuZ2xlc1VuaXQgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgTCA9IHJvdW5kKHBlcmNlbnQodmFsdWUpLCBkZWNpbWFscyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxjaFVuaXQgPT09IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgICAgICA/IGAke0x9JWBcbiAgICAgICAgICAgICAgICAgICAgOiBgJHtMfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5kZXggPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGNoVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UXG4gICAgICAgICAgICAgICAgICAgID8gYCR7ZnJvbTE1ME51bWJlclRvUGVyY2VudCh2YWx1ZSwgZGVjaW1hbHMpfSVgXG4gICAgICAgICAgICAgICAgICAgIDogcm91bmQodmFsdWUsIGRlY2ltYWxzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMikge1xuICAgICAgICAgICAgICAgIGlmIChhbmdsZXNVbml0ICE9PSBBbmdsZXNVbml0RW51bS5OT05FKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zbGF0ZWQgPSByb3VuZCh0cmFuc2xhdGVEZWdyZWVzKHZhbHVlLCBhbmdsZXNVbml0KSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7dHJhbnNsYXRlZH0ke2FuZ2xlc1VuaXR9YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvdW5kKHZhbHVlLCBkZWNpbWFscyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZ2V0QWxwaGEodmFsdWUsIG9wdGlvbnMsIHRydWUpO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MoY29sb3IsIHRyYW5zZm9ybWVyKTtcbiAgICAgICAgY29uc3QgdGVtcGxhdGUgPSB2YWx1ZXMubGVuZ3RoID09PSA0XG4gICAgICAgICAgICA/IGBsY2goezF9IHsyfSB7M30gLyB7NH0pYFxuICAgICAgICAgICAgOiBgbGNoKHsxfSB7Mn0gezN9KWA7XG4gICAgICAgIHJldHVybiBnZXRSZXN1bHRGcm9tVGVtcGxhdGUodGVtcGxhdGUsIHZhbHVlcyk7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5DTVlLXTogKGNvbG9yLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZGVjaW1hbHMsIGxlZ2FjeUNTUywgc3BhY2VzQWZ0ZXJDb21tYXMsIGNteWtVbml0LCBjbXlrRnVuY3Rpb24gfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGNvbW1hID0gZ2V0Q29tbWEoc3BhY2VzQWZ0ZXJDb21tYXMpO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9ICh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmIChjbXlrVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UICYmXG4gICAgICAgICAgICAgICAgaW5kZXggPCA0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGAke3JvdW5kKHZhbHVlLCBkZWNpbWFscyl9JWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW5kZXggPT09IDRcbiAgICAgICAgICAgICAgICA/IGdldEFscGhhKHZhbHVlLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIDogcm91bmQodmFsdWUgLyAxMDAsIGRlY2ltYWxzKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGNvbG9yLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gbGVnYWN5Q1NTXG4gICAgICAgICAgICA/ICh2YWx1ZXMubGVuZ3RoID09PSA1XG4gICAgICAgICAgICAgICAgPyBgJHtjbXlrRnVuY3Rpb259KHsxfSR7Y29tbWF9ezJ9JHtjb21tYX17M30ke2NvbW1hfXs0fSR7Y29tbWF9ezV9KWBcbiAgICAgICAgICAgICAgICA6IGAke2NteWtGdW5jdGlvbn0oezF9JHtjb21tYX17Mn0ke2NvbW1hfXszfSR7Y29tbWF9ezR9KWApXG4gICAgICAgICAgICA6ICh2YWx1ZXMubGVuZ3RoID09PSA1XG4gICAgICAgICAgICAgICAgPyBgJHtjbXlrRnVuY3Rpb259KHsxfSB7Mn0gezN9IHs0fSAvIHs1fSlgXG4gICAgICAgICAgICAgICAgOiBgJHtjbXlrRnVuY3Rpb259KHsxfSB7Mn0gezN9IHs0fSlgKTtcbiAgICAgICAgcmV0dXJuIGdldFJlc3VsdEZyb21UZW1wbGF0ZSh0ZW1wbGF0ZSwgdmFsdWVzKTtcbiAgICB9XG59O1xuIiwiaW1wb3J0IHsgQkFTRV8yNTUsIENvbG9yTW9kZWwsIE1peCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0SEVYLCBoYXNQcm9wLCBtaW5tYXgsIG5vcm1hbGl6ZUFscGhhLCBub3JtYWxpemVIdWUsIHJvdW5kIH0gZnJvbSAnI2hlbHBlcnMnO1xuaW1wb3J0IHsgaHNsVG9SZ2IsIGh1ZVJ5YiwgcmdiVG9DbXlrLCByZ2JUb0hzbCwgcmdiVG9Id2IsIHJnYlRvTGFiLCByZ2JUb0xjaCwgcmdiVG9SeWIsIHJ5YlRvUmdiIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IGdldENvbG9yTW9kZWwsIGdldFJHQk9iamVjdCB9IGZyb20gJy4vZXh0cmFjdG9ycyc7XG5pbXBvcnQgeyByb3VuZENJRUxhYk9iamVjdCwgcm91bmRDTVlLT2JqZWN0LCByb3VuZEhTTE9iamVjdCwgcm91bmRIV0JPYmplY3QsIHJvdW5kTENIT2JqZWN0IH0gZnJvbSAnLi9yb3VuZGVycyc7XG5pbXBvcnQgeyBDU1MgfSBmcm9tICcjY29sb3IvY3NzJztcbmNvbnN0IGhhcm1vbnkgPSAoY29sb3IsIGFuZ2xlcywgbW9kZSkgPT4gYW5nbGVzLnJlZHVjZSgoYXJyLCBudW0pID0+IChbXG4gICAgLi4uYXJyLFxuICAgIHtcbiAgICAgICAgLi4uY29sb3IsXG4gICAgICAgIEg6IG1vZGUgPT09IE1peC5BRERJVElWRVxuICAgICAgICAgICAgPyBub3JtYWxpemVIdWUoY29sb3IuSCArIG51bSlcbiAgICAgICAgICAgIDogbm9ybWFsaXplSHVlKGh1ZVJ5YihodWVSeWIoY29sb3IuSCwgZmFsc2UpICsgbnVtLCB0cnVlKSlcbiAgICB9XG5dKSwgW3sgLi4uY29sb3IgfV0pO1xuZXhwb3J0IGNvbnN0IGFuYWxvZ291cyA9IChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzMwLCAtMzBdLCBtb2RlKTtcbmV4cG9ydCBjb25zdCBjb21wbGVtZW50YXJ5ID0gKGNvbG9yLCBtb2RlKSA9PiBoYXJtb255KGNvbG9yLCBbMTgwXSwgbW9kZSk7XG5leHBvcnQgY29uc3Qgc3BsaXRDb21wbGVtZW50YXJ5ID0gKGNvbG9yLCBtb2RlKSA9PiBoYXJtb255KGNvbG9yLCBbMTUwLCAtMTUwXSwgbW9kZSk7XG5leHBvcnQgY29uc3QgdHJpYWRpYyA9IChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzEyMCwgLTEyMF0sIG1vZGUpO1xuZXhwb3J0IGNvbnN0IHRldHJhZGljID0gKGNvbG9yLCBtb2RlKSA9PiBoYXJtb255KGNvbG9yLCBbNjAsIC0xMjAsIDE4MF0sIG1vZGUpO1xuZXhwb3J0IGNvbnN0IHNxdWFyZSA9IChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzkwLCAtOTAsIDE4MF0sIG1vZGUpO1xuZXhwb3J0IGNvbnN0IHRyYW5zbGF0ZUNvbG9yID0ge1xuICAgIFtDb2xvck1vZGVsLkhFWF0oY29sb3IpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFI6IGdldEhFWChjb2xvci5SKSxcbiAgICAgICAgICAgIEc6IGdldEhFWChjb2xvci5HKSxcbiAgICAgICAgICAgIEI6IGdldEhFWChjb2xvci5CKVxuICAgICAgICB9O1xuICAgIH0sXG4gICAgSEVYQShjb2xvcikge1xuICAgICAgICBjb25zdCBSR0IgPSB0cmFuc2xhdGVDb2xvci5IRVgoY29sb3IpO1xuICAgICAgICBSR0IuQSA9IGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8gZ2V0SEVYKGNvbG9yLkEgKiBCQVNFXzI1NSlcbiAgICAgICAgICAgIDogJzB4RkYnO1xuICAgICAgICByZXR1cm4gUkdCO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuUkdCXShjb2xvciwgZGVjaW1hbHMpIHtcbiAgICAgICAgY29uc3QgUkdCID0gcm91bmRSR0JPYmplY3QoY29sb3IsIGRlY2ltYWxzKTtcbiAgICAgICAgaWYgKGhhc1Byb3AoUkdCLCAnQScpKSB7XG4gICAgICAgICAgICBkZWxldGUgUkdCLkE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFJHQjtcbiAgICB9LFxuICAgIFJHQkEoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IFJHQiA9IHRyYW5zbGF0ZUNvbG9yLlJHQihjb2xvciwgZGVjaW1hbHMpO1xuICAgICAgICBSR0IuQSA9IGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8gcm91bmQoY29sb3IuQSlcbiAgICAgICAgICAgIDogMTtcbiAgICAgICAgcmV0dXJuIFJHQjtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkhTTF0oY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IEhTTCA9IHJnYlRvSHNsKGNvbG9yLlIsIGNvbG9yLkcsIGNvbG9yLkIpO1xuICAgICAgICBkZWxldGUgSFNMLkE7XG4gICAgICAgIHJldHVybiByb3VuZEhTTE9iamVjdChIU0wsIGRlY2ltYWxzKTtcbiAgICB9LFxuICAgIEhTTEEoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IEhTTCA9IHRyYW5zbGF0ZUNvbG9yLkhTTChjb2xvciwgZGVjaW1hbHMpO1xuICAgICAgICBIU0wuQSA9IGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8gcm91bmQoY29sb3IuQSwgZGVjaW1hbHMpXG4gICAgICAgICAgICA6IDE7XG4gICAgICAgIHJldHVybiBIU0w7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IV0JdKGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICBjb25zdCBIV0IgPSByZ2JUb0h3Yihjb2xvci5SLCBjb2xvci5HLCBjb2xvci5CKTtcbiAgICAgICAgZGVsZXRlIEhXQi5BO1xuICAgICAgICByZXR1cm4gcm91bmRIV0JPYmplY3QoSFdCLCBkZWNpbWFscyk7XG4gICAgfSxcbiAgICBIV0JBKGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICBjb25zdCBIV0IgPSB0cmFuc2xhdGVDb2xvci5IV0IoY29sb3IsIGRlY2ltYWxzKTtcbiAgICAgICAgSFdCLkEgPSBoYXNQcm9wKGNvbG9yLCAnQScpXG4gICAgICAgICAgICA/IHJvdW5kKGNvbG9yLkEsIGRlY2ltYWxzKVxuICAgICAgICAgICAgOiAxO1xuICAgICAgICByZXR1cm4gSFdCO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuQ0lFTGFiXShjb2xvciwgZGVjaW1hbHMpIHtcbiAgICAgICAgY29uc3QgTGFiID0gcmdiVG9MYWIoY29sb3IuUiwgY29sb3IuRywgY29sb3IuQik7XG4gICAgICAgIHJldHVybiByb3VuZENJRUxhYk9iamVjdChMYWIsIGRlY2ltYWxzKTtcbiAgICB9LFxuICAgIENJRUxhYkEoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IExhYiA9IHRyYW5zbGF0ZUNvbG9yLkNJRUxhYihjb2xvciwgZGVjaW1hbHMpO1xuICAgICAgICBMYWIuQSA9IGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8gcm91bmQoY29sb3IuQSwgZGVjaW1hbHMpXG4gICAgICAgICAgICA6IDE7XG4gICAgICAgIHJldHVybiBMYWI7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5MQ0hdKGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICBjb25zdCBsY2ggPSByZ2JUb0xjaChjb2xvci5SLCBjb2xvci5HLCBjb2xvci5CKTtcbiAgICAgICAgcmV0dXJuIHJvdW5kTENIT2JqZWN0KGxjaCwgZGVjaW1hbHMpO1xuICAgIH0sXG4gICAgTENIQShjb2xvciwgZGVjaW1hbHMpIHtcbiAgICAgICAgY29uc3QgbGNoID0gdHJhbnNsYXRlQ29sb3IuTENIKGNvbG9yLCBkZWNpbWFscyk7XG4gICAgICAgIGxjaC5BID0gaGFzUHJvcChjb2xvciwgJ0EnKVxuICAgICAgICAgICAgPyByb3VuZChjb2xvci5BLCBkZWNpbWFscylcbiAgICAgICAgICAgIDogMTtcbiAgICAgICAgcmV0dXJuIGxjaDtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkNNWUtdKGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICByZXR1cm4gcm91bmRDTVlLT2JqZWN0KHJnYlRvQ215ayhjb2xvci5SLCBjb2xvci5HLCBjb2xvci5CKSwgZGVjaW1hbHMpO1xuICAgIH0sXG4gICAgQ01ZS0EoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IENNWUsgPSB0cmFuc2xhdGVDb2xvci5DTVlLKGNvbG9yLCBkZWNpbWFscyk7XG4gICAgICAgIENNWUsuQSA9IGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8gcm91bmQoY29sb3IuQSwgZGVjaW1hbHMpXG4gICAgICAgICAgICA6IDE7XG4gICAgICAgIHJldHVybiBDTVlLO1xuICAgIH1cbn07XG5leHBvcnQgY29uc3QgYmxlbmQgPSAoZnJvbSwgdG8sIHN0ZXBzKSA9PiB7XG4gICAgY29uc3QgZGl2ID0gc3RlcHMgLSAxO1xuICAgIGNvbnN0IGRpZmZSID0gKHRvLlIgLSBmcm9tLlIpIC8gZGl2O1xuICAgIGNvbnN0IGRpZmZHID0gKHRvLkcgLSBmcm9tLkcpIC8gZGl2O1xuICAgIGNvbnN0IGRpZmZCID0gKHRvLkIgLSBmcm9tLkIpIC8gZGl2O1xuICAgIGNvbnN0IGZyb21BID0gbm9ybWFsaXplQWxwaGEoZnJvbS5BKTtcbiAgICBjb25zdCB0b0EgPSBub3JtYWxpemVBbHBoYSh0by5BKTtcbiAgICBjb25zdCBkaWZmQSA9ICh0b0EgLSBmcm9tQSkgLyBkaXY7XG4gICAgcmV0dXJuIEFycmF5KHN0ZXBzKS5maWxsKG51bGwpLm1hcCgoX19uLCBpKSA9PiB7XG4gICAgICAgIGlmIChpID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gZnJvbTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaSA9PT0gZGl2KSB7XG4gICAgICAgICAgICByZXR1cm4gdG87XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFI6IHJvdW5kKGZyb20uUiArIGRpZmZSICogaSksXG4gICAgICAgICAgICBHOiByb3VuZChmcm9tLkcgKyBkaWZmRyAqIGkpLFxuICAgICAgICAgICAgQjogcm91bmQoZnJvbS5CICsgZGlmZkIgKiBpKSxcbiAgICAgICAgICAgIEE6IHJvdW5kKGZyb21BICsgZGlmZkEgKiBpKVxuICAgICAgICB9O1xuICAgIH0pO1xufTtcbmV4cG9ydCBjb25zdCBnZXRDb2xvck1peHR1cmUgPSAoY29sb3IsIHN0ZXBzLCBzaGFkZXMsIG9wdGlvbnMpID0+IHtcbiAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgIGNvbnN0IGlzQ1NTID0gdHlwZW9mIGNvbG9yID09PSAnc3RyaW5nJztcbiAgICBjb25zdCBSR0IgPSBnZXRSR0JPYmplY3QoY29sb3IsIG1vZGVsKTtcbiAgICBjb25zdCBoYXNBbHBoYSA9ICgodHlwZW9mIGNvbG9yID09PSAnc3RyaW5nJyAmJiBoYXNQcm9wKFJHQiwgJ0EnKSkgfHxcbiAgICAgICAgKHR5cGVvZiBjb2xvciAhPT0gJ3N0cmluZycgJiZcbiAgICAgICAgICAgIGhhc1Byb3AoY29sb3IsICdBJykpKTtcbiAgICBjb25zdCBIU0wgPSByZ2JUb0hzbChSR0IuUiwgUkdCLkcsIFJHQi5CLCBSR0IuQSk7XG4gICAgaWYgKCFoYXNBbHBoYSlcbiAgICAgICAgZGVsZXRlIEhTTC5BO1xuICAgIGNvbnN0IGluY3JlbWVudCA9IHNoYWRlc1xuICAgICAgICA/IEhTTC5MIC8gKHN0ZXBzICsgMSlcbiAgICAgICAgOiAoMTAwIC0gSFNMLkwpIC8gKHN0ZXBzICsgMSk7XG4gICAgY29uc3QgaHNsTWFwID0gQXJyYXkoc3RlcHMpLmZpbGwobnVsbCkubWFwKChfX24sIGkpID0+ICh7XG4gICAgICAgIC4uLkhTTCxcbiAgICAgICAgTDogSFNMLkwgKyBpbmNyZW1lbnQgKiAoaSArIDEpICogKDEgLSArc2hhZGVzICogMilcbiAgICB9KSk7XG4gICAgc3dpdGNoIChtb2RlbCkge1xuICAgICAgICBjYXNlIENvbG9yTW9kZWwuSEVYOlxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGhzbE1hcC5tYXAoKEhTTENvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUkdCQ29sb3IgPSBoc2xUb1JnYihIU0xDb2xvci5ILCBIU0xDb2xvci5TLCBIU0xDb2xvci5MKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzQWxwaGEpXG4gICAgICAgICAgICAgICAgICAgIFJHQkNvbG9yLkEgPSBIU0xDb2xvci5BO1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0NTU1xuICAgICAgICAgICAgICAgICAgICA/IGhhc0FscGhhXG4gICAgICAgICAgICAgICAgICAgICAgICA/IENTUy5IRVgoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLlJHQkNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEE6IHJvdW5kKFJHQkNvbG9yLkEgKiBCQVNFXzI1NSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICA6IENTUy5IRVgoUkdCQ29sb3IpXG4gICAgICAgICAgICAgICAgICAgIDogaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlQ29sb3IuSEVYQShSR0JDb2xvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuSEVYKFJHQkNvbG9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIENvbG9yTW9kZWwuUkdCOlxuICAgICAgICAgICAgcmV0dXJuIGhzbE1hcC5tYXAoKEhTTENvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUkdCQ29sb3IgPSBoc2xUb1JnYihIU0xDb2xvci5ILCBIU0xDb2xvci5TLCBIU0xDb2xvci5MKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzQWxwaGEpXG4gICAgICAgICAgICAgICAgICAgIFJHQkNvbG9yLkEgPSBIU0xDb2xvci5BO1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0NTU1xuICAgICAgICAgICAgICAgICAgICA/IENTUy5SR0IoUkdCQ29sb3IsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIDogaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlQ29sb3IuUkdCQShSR0JDb2xvciwgb3B0aW9ucy5kZWNpbWFscylcbiAgICAgICAgICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuUkdCKFJHQkNvbG9yLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSBDb2xvck1vZGVsLkhTTDpcbiAgICAgICAgICAgIHJldHVybiBoc2xNYXAubWFwKChIU0xDb2xvcikgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0NTU1xuICAgICAgICAgICAgICAgICAgICA/IENTUy5IU0woSFNMQ29sb3IsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIDogaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlQ29sb3IuSFNMQSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uaHNsVG9SZ2IoSFNMQ29sb3IuSCwgSFNMQ29sb3IuUywgSFNMQ29sb3IuTCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQTogSFNMQ29sb3IuQVxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgb3B0aW9ucy5kZWNpbWFscylcbiAgICAgICAgICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuSFNMKGhzbFRvUmdiKEhTTENvbG9yLkgsIEhTTENvbG9yLlMsIEhTTENvbG9yLkwpLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIENvbG9yTW9kZWwuSFdCOlxuICAgICAgICAgICAgcmV0dXJuIGhzbE1hcC5tYXAoKEhTTENvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUkdCQ29sb3IgPSBoc2xUb1JnYihIU0xDb2xvci5ILCBIU0xDb2xvci5TLCBIU0xDb2xvci5MKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzQWxwaGEpXG4gICAgICAgICAgICAgICAgICAgIFJHQkNvbG9yLkEgPSBIU0xDb2xvci5BO1xuICAgICAgICAgICAgICAgIGNvbnN0IGh3YiA9IGhhc0FscGhhXG4gICAgICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlQ29sb3IuSFdCQShSR0JDb2xvciwgb3B0aW9ucy5kZWNpbWFscylcbiAgICAgICAgICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IV0IoUkdCQ29sb3IsIG9wdGlvbnMuZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0NTU1xuICAgICAgICAgICAgICAgICAgICA/IENTUy5IV0IoaHdiLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICA6IGh3YjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIENvbG9yTW9kZWwuQ0lFTGFiOlxuICAgICAgICAgICAgcmV0dXJuIGhzbE1hcC5tYXAoKEhTTENvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUkdCQ29sb3IgPSBoc2xUb1JnYihIU0xDb2xvci5ILCBIU0xDb2xvci5TLCBIU0xDb2xvci5MKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzQWxwaGEpXG4gICAgICAgICAgICAgICAgICAgIFJHQkNvbG9yLkEgPSBIU0xDb2xvci5BO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhYiA9IGhhc0FscGhhXG4gICAgICAgICAgICAgICAgICAgID8gdHJhbnNsYXRlQ29sb3IuQ0lFTGFiQShSR0JDb2xvciwgb3B0aW9ucy5kZWNpbWFscylcbiAgICAgICAgICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5DSUVMYWIoUkdCQ29sb3IsIG9wdGlvbnMuZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0NTU1xuICAgICAgICAgICAgICAgICAgICA/IENTUy5DSUVMYWIobGFiLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICA6IGxhYjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBjYXNlIENvbG9yTW9kZWwuTENIOlxuICAgICAgICAgICAgcmV0dXJuIGhzbE1hcC5tYXAoKEhTTENvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUkdCQ29sb3IgPSBoc2xUb1JnYihIU0xDb2xvci5ILCBIU0xDb2xvci5TLCBIU0xDb2xvci5MKTtcbiAgICAgICAgICAgICAgICBjb25zdCBMQ0hDb2xvciA9IHJnYlRvTGNoKFJHQkNvbG9yLlIsIFJHQkNvbG9yLkcsIFJHQkNvbG9yLkIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNBbHBoYSlcbiAgICAgICAgICAgICAgICAgICAgTENIQ29sb3IuQSA9IEhTTENvbG9yLkE7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzQ1NTXG4gICAgICAgICAgICAgICAgICAgID8gQ1NTLkxDSChMQ0hDb2xvciwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgOiBoYXNBbHBoYVxuICAgICAgICAgICAgICAgICAgICAgICAgPyB0cmFuc2xhdGVDb2xvci5MQ0hBKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5SR0JDb2xvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBOiBIU0xDb2xvci5BXG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBvcHRpb25zLmRlY2ltYWxzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5MQ0goUkdCQ29sb3IsIG9wdGlvbnMuZGVjaW1hbHMpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxufTtcbmV4cG9ydCBjb25zdCBjb2xvckhhcm1vbnkgPSB7XG4gICAgYnVpbGRIYXJtb255KGNvbG9yLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbW9kZWwgPSBnZXRDb2xvck1vZGVsKGNvbG9yKTtcbiAgICAgICAgY29uc3QgUkdCID0gZ2V0UkdCT2JqZWN0KGNvbG9yLCBtb2RlbCk7XG4gICAgICAgIGNvbnN0IEhTTCA9IHJnYlRvSHNsKFJHQi5SLCBSR0IuRywgUkdCLkIsIFJHQi5BKTtcbiAgICAgICAgY29uc3QgaGFzQWxwaGEgPSAoKHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZycgJiYgaGFzUHJvcChSR0IsICdBJykpIHx8XG4gICAgICAgICAgICAodHlwZW9mIGNvbG9yICE9PSAnc3RyaW5nJyAmJlxuICAgICAgICAgICAgICAgIGhhc1Byb3AoY29sb3IsICdBJykpKTtcbiAgICAgICAgY29uc3QgaXNDU1MgPSB0eXBlb2YgY29sb3IgPT09ICdzdHJpbmcnO1xuICAgICAgICBzd2l0Y2ggKG1vZGVsKSB7XG4gICAgICAgICAgICBjYXNlIENvbG9yTW9kZWwuSEVYOlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgPyB0aGlzLkhFWEEocm91bmRIU0xPYmplY3QoSFNMLCAwKSwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBpc0NTUylcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLkhFWChyb3VuZEhTTE9iamVjdChIU0wsIDApLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGlzQ1NTKTtcbiAgICAgICAgICAgIGNhc2UgQ29sb3JNb2RlbC5IU0w6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc0FscGhhXG4gICAgICAgICAgICAgICAgICAgID8gdGhpcy5IU0xBKEhTTCwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBpc0NTUywgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLkhTTChIU0wsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgaXNDU1MsIG9wdGlvbnMpO1xuICAgICAgICAgICAgY2FzZSBDb2xvck1vZGVsLkhXQjpcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgPyB0aGlzLkhXQkEoSFNMLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGlzQ1NTLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICA6IHRoaXMuSFdCKEhTTCwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBpc0NTUywgb3B0aW9ucyk7XG4gICAgICAgICAgICBjYXNlIENvbG9yTW9kZWwuUkdCOlxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNBbHBoYVxuICAgICAgICAgICAgICAgICAgICA/IHRoaXMuUkdCQShIU0wsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgaXNDU1MsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgICAgIDogdGhpcy5SR0IoSFNMLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGlzQ1NTLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGNhc2UgQ29sb3JNb2RlbC5DSUVMYWI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc0FscGhhXG4gICAgICAgICAgICAgICAgICAgID8gdGhpcy5DSUVMYWJBKEhTTCwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBpc0NTUywgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgOiB0aGlzLkNJRUxhYihIU0wsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgaXNDU1MsIG9wdGlvbnMpO1xuICAgICAgICAgICAgY2FzZSBDb2xvck1vZGVsLkxDSDpcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzQWxwaGFcbiAgICAgICAgICAgICAgICAgICAgPyB0aGlzLkxDSEEoSFNMLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGlzQ1NTLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgICAgICA6IHRoaXMuTENIKEhTTCwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBpc0NTUywgb3B0aW9ucyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkhFWF0oY29sb3IsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgY3NzKSB7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gaGFybW9ueUZ1bmN0aW9uKGNvbG9yLCBtb2RlKTtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoYykgPT4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuSEVYKGhzbFRvUmdiKGMuSCwgYy5TLCBjLkwpKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IRVgoaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCkpKSk7XG4gICAgfSxcbiAgICBIRVhBKGNvbG9yLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGNzcykge1xuICAgICAgICBjb25zdCBhcnJheSA9IGhhcm1vbnlGdW5jdGlvbihjb2xvciwgbW9kZSk7XG4gICAgICAgIHJldHVybiBhcnJheS5tYXAoKGMpID0+IChjc3NcbiAgICAgICAgICAgID8gQ1NTLkhFWCh7XG4gICAgICAgICAgICAgICAgLi4uaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCksXG4gICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoYy5BKSAqIEJBU0VfMjU1XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IRVhBKHtcbiAgICAgICAgICAgICAgICAuLi5oc2xUb1JnYihjLkgsIGMuUywgYy5MKSxcbiAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICB9KSkpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuUkdCXShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiAoY3NzXG4gICAgICAgICAgICA/IENTUy5SR0IoaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCksIG9wdGlvbnMpXG4gICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLlJHQihoc2xUb1JnYihjLkgsIGMuUywgYy5MKSwgb3B0aW9ucy5kZWNpbWFscykpKTtcbiAgICB9LFxuICAgIFJHQkEoY29sb3IsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gaGFybW9ueUZ1bmN0aW9uKGNvbG9yLCBtb2RlKTtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoYykgPT4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuUkdCKHtcbiAgICAgICAgICAgICAgICAuLi5oc2xUb1JnYihjLkgsIGMuUywgYy5MKSxcbiAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICB9LCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5SR0JBKHtcbiAgICAgICAgICAgICAgICAuLi5oc2xUb1JnYihjLkgsIGMuUywgYy5MKSxcbiAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICB9LCBvcHRpb25zLmRlY2ltYWxzKSkpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuSFNMXShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiAoY3NzXG4gICAgICAgICAgICA/IENTUy5IU0woe1xuICAgICAgICAgICAgICAgIEg6IGMuSCxcbiAgICAgICAgICAgICAgICBTOiBjLlMsXG4gICAgICAgICAgICAgICAgTDogYy5MXG4gICAgICAgICAgICB9LCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IU0woaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCksIG9wdGlvbnMuZGVjaW1hbHMpKSk7XG4gICAgfSxcbiAgICBIU0xBKGNvbG9yLCBoYXJtb255RnVuY3Rpb24sIG1vZGUsIGNzcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBhcnJheSA9IGhhcm1vbnlGdW5jdGlvbihjb2xvciwgbW9kZSk7XG4gICAgICAgIHJldHVybiBhcnJheS5tYXAoKGMpID0+IChjc3NcbiAgICAgICAgICAgID8gQ1NTLkhTTCh7XG4gICAgICAgICAgICAgICAgLi4uYyxcbiAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICB9LCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IU0xBKHtcbiAgICAgICAgICAgICAgICAuLi5oc2xUb1JnYihjLkgsIGMuUywgYy5MKSxcbiAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICB9LCBvcHRpb25zLmRlY2ltYWxzKSkpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuSFdCXShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZ2IgPSBoc2xUb1JnYihjLkgsIGMuUywgYy5MKTtcbiAgICAgICAgICAgIGNvbnN0IGh3YiA9IHJnYlRvSHdiKHJnYi5SLCByZ2IuRywgcmdiLkIpO1xuICAgICAgICAgICAgcmV0dXJuIGNzc1xuICAgICAgICAgICAgICAgID8gQ1NTLkhXQih7XG4gICAgICAgICAgICAgICAgICAgIEg6IGh3Yi5ILFxuICAgICAgICAgICAgICAgICAgICBXOiBod2IuVyxcbiAgICAgICAgICAgICAgICAgICAgQjogaHdiLkJcbiAgICAgICAgICAgICAgICB9LCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuSFdCKHJnYiwgb3B0aW9ucy5kZWNpbWFscyk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgSFdCQShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZ2IgPSBoc2xUb1JnYihjLkgsIGMuUywgYy5MKTtcbiAgICAgICAgICAgIGNvbnN0IGh3YiA9IHJnYlRvSHdiKHJnYi5SLCByZ2IuRywgcmdiLkIpO1xuICAgICAgICAgICAgcmV0dXJuIGNzc1xuICAgICAgICAgICAgICAgID8gQ1NTLkhXQih7XG4gICAgICAgICAgICAgICAgICAgIC4uLmh3YixcbiAgICAgICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoYy5BKVxuICAgICAgICAgICAgICAgIH0sIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IV0JBKHtcbiAgICAgICAgICAgICAgICAgICAgLi4ucmdiLFxuICAgICAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICAgICAgfSwgb3B0aW9ucy5kZWNpbWFscyk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuQ0lFTGFiXShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBSR0IgPSBoc2xUb1JnYihjLkgsIGMuUywgYy5MKTtcbiAgICAgICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICAgICAgPyBDU1MuQ0lFTGFiKHJnYlRvTGFiKFJHQi5SLCBSR0IuRywgUkdCLkIpLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuQ0lFTGFiKFJHQiwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIENJRUxhYkEoY29sb3IsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gaGFybW9ueUZ1bmN0aW9uKGNvbG9yLCBtb2RlKTtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoYykgPT4ge1xuICAgICAgICAgICAgY29uc3QgUkdCID0gaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCk7XG4gICAgICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgICAgID8gQ1NTLkNJRUxhYih7XG4gICAgICAgICAgICAgICAgICAgIC4uLnJnYlRvTGFiKFJHQi5SLCBSR0IuRywgUkdCLkIpLFxuICAgICAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICAgICAgfSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLkNJRUxhYkEoe1xuICAgICAgICAgICAgICAgICAgICAuLi5SR0IsXG4gICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKGMuQSlcbiAgICAgICAgICAgICAgICB9LCBvcHRpb25zLmRlY2ltYWxzKSk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuTENIXShjb2xvciwgaGFybW9ueUZ1bmN0aW9uLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oY29sb3IsIG1vZGUpO1xuICAgICAgICByZXR1cm4gYXJyYXkubWFwKChjKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBSR0IgPSBoc2xUb1JnYihjLkgsIGMuUywgYy5MKTtcbiAgICAgICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICAgICAgPyBDU1MuTENIKHJnYlRvTGNoKFJHQi5SLCBSR0IuRywgUkdCLkIpLCBvcHRpb25zKVxuICAgICAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuTENIKFJHQiwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIExDSEEoY29sb3IsIGhhcm1vbnlGdW5jdGlvbiwgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGFycmF5ID0gaGFybW9ueUZ1bmN0aW9uKGNvbG9yLCBtb2RlKTtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoYykgPT4ge1xuICAgICAgICAgICAgY29uc3QgUkdCID0gaHNsVG9SZ2IoYy5ILCBjLlMsIGMuTCk7XG4gICAgICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgICAgID8gQ1NTLkxDSCh7XG4gICAgICAgICAgICAgICAgICAgIC4uLnJnYlRvTGNoKFJHQi5SLCBSR0IuRywgUkdCLkIpLFxuICAgICAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShjLkEpXG4gICAgICAgICAgICAgICAgfSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLkxDSEEoe1xuICAgICAgICAgICAgICAgICAgICAuLi5SR0IsXG4gICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKGMuQSlcbiAgICAgICAgICAgICAgICB9LCBvcHRpb25zLmRlY2ltYWxzKSk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5leHBvcnQgY29uc3QgY29sb3JNaXhlciA9IHtcbiAgICBtaXgoY29sb3JzLCBtb2RlKSB7XG4gICAgICAgIGNvbnN0IHJnYk1hcCA9IGNvbG9ycy5tYXAoKGNvbG9yKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICAgICAgcmV0dXJuIGdldFJHQk9iamVjdChjb2xvciwgbW9kZWwpO1xuICAgICAgICB9KTtcbiAgICAgICAgY29uc3QgcnliTWFwID0gbW9kZSA9PT0gTWl4LlNVQlRSQUNUSVZFXG4gICAgICAgICAgICA/IHJnYk1hcC5tYXAoKGNvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgUllCID0gcmdiVG9SeWIoY29sb3IuUiwgY29sb3IuRywgY29sb3IuQik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1Byb3AoY29sb3IsICdBJykpIHtcbiAgICAgICAgICAgICAgICAgICAgUllCLkEgPSBjb2xvci5BO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gUllCO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIDogbnVsbDtcbiAgICAgICAgZnVuY3Rpb24gY3JlYXRlTWl4KGl0ZW1zKSB7XG4gICAgICAgICAgICBjb25zdCBpbml0aWFsID0gbW9kZSA9PT0gTWl4LkFERElUSVZFXG4gICAgICAgICAgICAgICAgPyB7IFI6IDAsIEc6IDAsIEI6IDAsIEE6IDAgfVxuICAgICAgICAgICAgICAgIDogeyBSOiAwLCBZOiAwLCBCOiAwLCBBOiAwIH07XG4gICAgICAgICAgICByZXR1cm4gaXRlbXMucmVkdWNlKChtaXgsIGNvbG9yKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29sb3JBID0gaGFzUHJvcChjb2xvciwgJ0EnKSA/IGNvbG9yLkEgOiAxO1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbW1vbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgUjogTWF0aC5taW4obWl4LlIgKyBjb2xvci5SICogY29sb3JBLCBCQVNFXzI1NSksXG4gICAgICAgICAgICAgICAgICAgIEI6IE1hdGgubWluKG1peC5CICsgY29sb3IuQiAqIGNvbG9yQSwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgICAgICBBOiAxIC0gKDEgLSBjb2xvckEpICogKDEgLSBtaXguQSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGNvbnN0IG1peEdZID0gJ0cnIGluIG1peFxuICAgICAgICAgICAgICAgICAgICA/IG1peC5HXG4gICAgICAgICAgICAgICAgICAgIDogbWl4Llk7XG4gICAgICAgICAgICAgICAgY29uc3QgY29sb3JHWSA9ICdHJyBpbiBjb2xvclxuICAgICAgICAgICAgICAgICAgICA/IGNvbG9yLkdcbiAgICAgICAgICAgICAgICAgICAgOiBjb2xvci5ZO1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIC4uLmNvbW1vbixcbiAgICAgICAgICAgICAgICAgICAgLi4uKG1vZGUgPT09IE1peC5BRERJVElWRVxuICAgICAgICAgICAgICAgICAgICAgICAgPyB7IEc6IE1hdGgubWluKG1peEdZICsgY29sb3JHWSAqIGNvbG9yQSwgQkFTRV8yNTUpIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDogeyBZOiBNYXRoLm1pbihtaXhHWSArIGNvbG9yR1kgKiBjb2xvckEsIEJBU0VfMjU1KSB9KVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LCBpbml0aWFsKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgbWl4O1xuICAgICAgICBpZiAobW9kZSA9PT0gTWl4LkFERElUSVZFKSB7XG4gICAgICAgICAgICBtaXggPSBjcmVhdGVNaXgocmdiTWFwKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IFJZQiA9IGNyZWF0ZU1peChyeWJNYXApO1xuICAgICAgICAgICAgbWl4ID0gcnliVG9SZ2IoUllCLlIsIFJZQi5ZLCBSWUIuQik7XG4gICAgICAgICAgICBtaXguQSA9IFJZQi5BO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSOiByb3VuZChtaXguUiksXG4gICAgICAgICAgICBHOiByb3VuZChtaXguRyksXG4gICAgICAgICAgICBCOiByb3VuZChtaXguQiksXG4gICAgICAgICAgICBBOiBtaW5tYXgobWl4LkEsIDAsIDEpXG4gICAgICAgIH07XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5IRVhdKGNvbG9ycywgbW9kZSwgY3NzKSB7XG4gICAgICAgIGNvbnN0IG1peCA9IHRoaXMubWl4KGNvbG9ycywgbW9kZSk7XG4gICAgICAgIGRlbGV0ZSBtaXguQTtcbiAgICAgICAgcmV0dXJuIChjc3NcbiAgICAgICAgICAgID8gQ1NTLkhFWChtaXgpXG4gICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLkhFWChtaXgpKTtcbiAgICB9LFxuICAgIEhFWEEoY29sb3JzLCBtb2RlLCBjc3MpIHtcbiAgICAgICAgY29uc3QgbWl4ID0gdGhpcy5taXgoY29sb3JzLCBtb2RlKTtcbiAgICAgICAgbWl4LkEgPSBjc3NcbiAgICAgICAgICAgID8gbm9ybWFsaXplQWxwaGEobWl4LkEpICogQkFTRV8yNTVcbiAgICAgICAgICAgIDogbm9ybWFsaXplQWxwaGEobWl4LkEpO1xuICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuSEVYKG1peClcbiAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuSEVYQShtaXgpKTtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLlJHQl0oY29sb3JzLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWl4ID0gdGhpcy5taXgoY29sb3JzLCBtb2RlKTtcbiAgICAgICAgZGVsZXRlIG1peC5BO1xuICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuUkdCKG1peCwgb3B0aW9ucylcbiAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuUkdCKG1peCwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgIH0sXG4gICAgUkdCQShjb2xvcnMsIG1vZGUsIGNzcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBtaXggPSB0aGlzLm1peChjb2xvcnMsIG1vZGUpO1xuICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuUkdCKG1peCwgb3B0aW9ucylcbiAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuUkdCQShtaXgsIG9wdGlvbnMuZGVjaW1hbHMpKTtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkhTTF0oY29sb3JzLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWl4ID0gdGhpcy5taXgoY29sb3JzLCBtb2RlKTtcbiAgICAgICAgY29uc3QgSFNMID0gcmdiVG9Ic2wobWl4LlIsIG1peC5HLCBtaXguQik7XG4gICAgICAgIGRlbGV0ZSBtaXguQTtcbiAgICAgICAgZGVsZXRlIEhTTC5BO1xuICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuSFNMKEhTTCwgb3B0aW9ucylcbiAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuSFNMKG1peCwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgIH0sXG4gICAgSFNMQShjb2xvcnMsIG1vZGUsIGNzcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBtaXggPSB0aGlzLm1peChjb2xvcnMsIG1vZGUpO1xuICAgICAgICBjb25zdCBIU0wgPSByZ2JUb0hzbChtaXguUiwgbWl4LkcsIG1peC5CLCBtaXguQSk7XG4gICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICA/IENTUy5IU0woSFNMLCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IU0xBKG1peCwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgIH0sXG4gICAgW0NvbG9yTW9kZWwuSFdCXShjb2xvcnMsIG1vZGUsIGNzcywgb3B0aW9ucykge1xuICAgICAgICBjb25zdCBtaXggPSB0aGlzLm1peChjb2xvcnMsIG1vZGUpO1xuICAgICAgICBjb25zdCBIV0IgPSByZ2JUb0h3YihtaXguUiwgbWl4LkcsIG1peC5CKTtcbiAgICAgICAgZGVsZXRlIG1peC5BO1xuICAgICAgICBkZWxldGUgSFdCLkE7XG4gICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICA/IENTUy5IV0IoSFdCLCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5IV0IobWl4LCBvcHRpb25zLmRlY2ltYWxzKSk7XG4gICAgfSxcbiAgICBIV0JBKGNvbG9ycywgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IG1peCA9IHRoaXMubWl4KGNvbG9ycywgbW9kZSk7XG4gICAgICAgIGNvbnN0IEhXQiA9IHJnYlRvSHdiKG1peC5SLCBtaXguRywgbWl4LkIsIG1peC5BKTtcbiAgICAgICAgcmV0dXJuIChjc3NcbiAgICAgICAgICAgID8gQ1NTLkhXQihIV0IsIG9wdGlvbnMpXG4gICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLkhXQkEobWl4LCBvcHRpb25zLmRlY2ltYWxzKSk7XG4gICAgfSxcbiAgICBbQ29sb3JNb2RlbC5DSUVMYWJdKGNvbG9ycywgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IG1peCA9IHRoaXMubWl4KGNvbG9ycywgbW9kZSk7XG4gICAgICAgIGNvbnN0IExhYiA9IHJnYlRvTGFiKG1peC5SLCBtaXguRywgbWl4LkIpO1xuICAgICAgICBkZWxldGUgbWl4LkE7XG4gICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICA/IENTUy5DSUVMYWIoTGFiLCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5DSUVMYWIobWl4LCBvcHRpb25zLmRlY2ltYWxzKSk7XG4gICAgfSxcbiAgICBDSUVMYWJBKGNvbG9ycywgbW9kZSwgY3NzLCBvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IG1peCA9IHRoaXMubWl4KGNvbG9ycywgbW9kZSk7XG4gICAgICAgIGNvbnN0IExhYiA9IHJnYlRvTGFiKG1peC5SLCBtaXguRywgbWl4LkIpO1xuICAgICAgICBMYWIuQSA9IG1peC5BO1xuICAgICAgICByZXR1cm4gKGNzc1xuICAgICAgICAgICAgPyBDU1MuQ0lFTGFiKExhYiwgb3B0aW9ucylcbiAgICAgICAgICAgIDogdHJhbnNsYXRlQ29sb3IuQ0lFTGFiQShtaXgsIG9wdGlvbnMuZGVjaW1hbHMpKTtcbiAgICB9LFxuICAgIFtDb2xvck1vZGVsLkxDSF0oY29sb3JzLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWl4ID0gdGhpcy5taXgoY29sb3JzLCBtb2RlKTtcbiAgICAgICAgY29uc3QgbGNoID0gcmdiVG9MY2gobWl4LlIsIG1peC5HLCBtaXguQik7XG4gICAgICAgIGRlbGV0ZSBtaXguQTtcbiAgICAgICAgcmV0dXJuIChjc3NcbiAgICAgICAgICAgID8gQ1NTLkxDSChsY2gsIG9wdGlvbnMpXG4gICAgICAgICAgICA6IHRyYW5zbGF0ZUNvbG9yLkxDSChtaXgsIG9wdGlvbnMuZGVjaW1hbHMpKTtcbiAgICB9LFxuICAgIExDSEEoY29sb3JzLCBtb2RlLCBjc3MsIG9wdGlvbnMpIHtcbiAgICAgICAgY29uc3QgbWl4ID0gdGhpcy5taXgoY29sb3JzLCBtb2RlKTtcbiAgICAgICAgY29uc3QgbGNoID0gcmdiVG9MY2gobWl4LlIsIG1peC5HLCBtaXguQik7XG4gICAgICAgIGxjaC5BID0gbWl4LkE7XG4gICAgICAgIHJldHVybiAoY3NzXG4gICAgICAgICAgICA/IENTUy5MQ0gobGNoLCBvcHRpb25zKVxuICAgICAgICAgICAgOiB0cmFuc2xhdGVDb2xvci5MQ0hBKG1peCwgb3B0aW9ucy5kZWNpbWFscykpO1xuICAgIH1cbn07XG5leHBvcnQgY29uc3Qgcm91bmRSR0JPYmplY3QgPSAoY29sb3IsIGRlY2ltYWxzKSA9PiB7XG4gICAgY29uc3QgUiA9IHJvdW5kKGNvbG9yLlIsIGRlY2ltYWxzKTtcbiAgICBjb25zdCBHID0gcm91bmQoY29sb3IuRywgZGVjaW1hbHMpO1xuICAgIGNvbnN0IEIgPSByb3VuZChjb2xvci5CLCBkZWNpbWFscyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUixcbiAgICAgICAgRyxcbiAgICAgICAgQixcbiAgICAgICAgLi4uKGhhc1Byb3AoY29sb3IsICdBJylcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIEE6IHJvdW5kKGNvbG9yLkEsIGRlY2ltYWxzKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB7fSlcbiAgICB9O1xufTtcbiIsImltcG9ydCB7IERFRkFVTFRfQkxFTkRfU1RFUFMsIEhhcm1vbnksIE1peCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0ICogYXMgdXRpbHMgZnJvbSAnI2NvbG9yL3V0aWxzJztcbmltcG9ydCB7IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dCwgZ2V0UkdCT2JqZWN0IH0gZnJvbSAnI2NvbG9yL2V4dHJhY3RvcnMnO1xuZXhwb3J0IGNvbnN0IGdldENvbG9yUmV0dXJuID0gKGNvbG9yLCBtb2RlbCwgZGVjaW1hbHMsIHRyYW5zbGF0ZUZ1bmN0aW9uKSA9PiB7XG4gICAgY29uc3QgcmdiT2JqZWN0ID0gZ2V0UkdCT2JqZWN0KGNvbG9yLCBtb2RlbCk7XG4gICAgcmV0dXJuIHRyYW5zbGF0ZUZ1bmN0aW9uKHJnYk9iamVjdCwgZGVjaW1hbHMpO1xufTtcbmV4cG9ydCBjb25zdCBnZXRCbGVuZFJldHVybiA9IChmcm9tLCB0bywgc3RlcHMsIGRlY2ltYWxzLCB0cmFuc2xhdGVGdW5jdGlvbikgPT4ge1xuICAgIGlmIChzdGVwcyA8IDEpXG4gICAgICAgIHN0ZXBzID0gREVGQVVMVF9CTEVORF9TVEVQUztcbiAgICBjb25zdCBmcm9tUkdCT2JqZWN0ID0gZ2V0UkdCT2JqZWN0KGZyb20pO1xuICAgIGNvbnN0IHRvUkdCT2JqZWN0ID0gZ2V0UkdCT2JqZWN0KHRvKTtcbiAgICBjb25zdCBibGVuZEFycmF5ID0gdXRpbHMuYmxlbmQoZnJvbVJHQk9iamVjdCwgdG9SR0JPYmplY3QsIHN0ZXBzKTtcbiAgICByZXR1cm4gYmxlbmRBcnJheS5tYXAoKGNvbG9yKSA9PiB7XG4gICAgICAgIHJldHVybiB0cmFuc2xhdGVGdW5jdGlvbihjb2xvciwgZGVjaW1hbHMpO1xuICAgIH0pO1xufTtcbmV4cG9ydCBmdW5jdGlvbiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHBhcmFtcykge1xuICAgIGNvbnN0IHsgZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIsIHRyYW5zbGF0ZUZ1bmN0aW9uLCBjc3NGdW5jdGlvbiB9ID0gcGFyYW1zO1xuICAgIGNvbnN0IHJlc3VsdCA9IHR5cGVvZiB0aGlyZFBhcmFtZXRlciA9PT0gJ251bWJlcidcbiAgICAgICAgPyBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcj8uZGVjaW1hbHMsIHRyYW5zbGF0ZUZ1bmN0aW9uKVxuICAgICAgICA6IGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBERUZBVUxUX0JMRU5EX1NURVBTLCB0aGlyZFBhcmFtZXRlcj8uZGVjaW1hbHMsIHRyYW5zbGF0ZUZ1bmN0aW9uKTtcbiAgICBpZiAoY3NzRnVuY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdC5tYXAoKGNvbG9yKSA9PiBjc3NGdW5jdGlvbihjb2xvciwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KCh0eXBlb2YgdGhpcmRQYXJhbWV0ZXIgPT09ICdudW1iZXInXG4gICAgICAgICAgICA/IGZvdXJ0aFBhcmFtZXRlclxuICAgICAgICAgICAgOiB0aGlyZFBhcmFtZXRlcikgPz8ge30sIGZyb20sIHRvKSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdldE1peFJldHVybihwYXJhbXMpIHtcbiAgICBjb25zdCB7IGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlciwgY29sb3JNaXhlckZ1bmN0aW9uLCBjc3MgfSA9IHBhcmFtcztcbiAgICBjb25zdCBvcHRpb25zID0gZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KCh0eXBlb2Ygc2Vjb25kUGFyYW1ldGVyID09PSAnc3RyaW5nJ1xuICAgICAgICA/IHRoaXJkUGFyYW1ldGVyXG4gICAgICAgIDogc2Vjb25kUGFyYW1ldGVyKSA/PyB7fSwgLi4uY29sb3JzKTtcbiAgICBpZiAodHlwZW9mIHNlY29uZFBhcmFtZXRlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yTWl4ZXJGdW5jdGlvbihjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgY3NzLCBvcHRpb25zKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbG9yTWl4ZXJGdW5jdGlvbihjb2xvcnMsIE1peC5BRERJVElWRSwgY3NzLCBvcHRpb25zKTtcbn1cbmV4cG9ydCBjb25zdCBnZXRIYXJtb255UmV0dXJuID0gKGhhcm1vbnksIGNvbG9yLCBtb2RlLCBvcHRpb25zKSA9PiB7XG4gICAgcmV0dXJuICh7XG4gICAgICAgIFtIYXJtb255LkFOQUxPR09VU106IHV0aWxzLmNvbG9ySGFybW9ueS5idWlsZEhhcm1vbnkoY29sb3IsIHV0aWxzLmFuYWxvZ291cywgbW9kZSwgb3B0aW9ucyksXG4gICAgICAgIFtIYXJtb255LkNPTVBMRU1FTlRBUlldOiB1dGlscy5jb2xvckhhcm1vbnkuYnVpbGRIYXJtb255KGNvbG9yLCB1dGlscy5jb21wbGVtZW50YXJ5LCBtb2RlLCBvcHRpb25zKSxcbiAgICAgICAgW0hhcm1vbnkuU1BMSVRfQ09NUExFTUVOVEFSWV06IHV0aWxzLmNvbG9ySGFybW9ueS5idWlsZEhhcm1vbnkoY29sb3IsIHV0aWxzLnNwbGl0Q29tcGxlbWVudGFyeSwgbW9kZSwgb3B0aW9ucyksXG4gICAgICAgIFtIYXJtb255LlRSSUFESUNdOiB1dGlscy5jb2xvckhhcm1vbnkuYnVpbGRIYXJtb255KGNvbG9yLCB1dGlscy50cmlhZGljLCBtb2RlLCBvcHRpb25zKSxcbiAgICAgICAgW0hhcm1vbnkuVEVUUkFESUNdOiB1dGlscy5jb2xvckhhcm1vbnkuYnVpbGRIYXJtb255KGNvbG9yLCB1dGlscy50ZXRyYWRpYywgbW9kZSwgb3B0aW9ucyksXG4gICAgICAgIFtIYXJtb255LlNRVUFSRV06IHV0aWxzLmNvbG9ySGFybW9ueS5idWlsZEhhcm1vbnkoY29sb3IsIHV0aWxzLnNxdWFyZSwgbW9kZSwgb3B0aW9ucylcbiAgICB9KVtoYXJtb255XTtcbn07XG4iLCJpbXBvcnQgeyBCQVNFXzI1NSwgREVGQVVMVF9CTEVORF9TVEVQUywgREVGQVVMVF9TSEFERVNfVElOVFNfU1RFUFMsIEhhcm1vbnksIE1BWF9BTFBIQSwgTUFYX0xBQiwgTUFYX0xDSF9DLCBNQVhfUENFTlQsIE1peCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgY215a1RvUmdiLCBoc2xUb1JnYiwgaHdiVG9SZ2IsIGxhYlRvTGNoLCBsYWJUb1JnYiwgbGNoVG9MYWIsIGxjaFRvUmdiLCByZ2JUb0NteWssIHJnYlRvSHNsLCByZ2JUb0h3YiwgcmdiVG9MYWIsIHJnYlRvTGNoIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCAqIGFzIHV0aWxzIGZyb20gJyNjb2xvci91dGlscyc7XG5pbXBvcnQgeyBnZXRDb2xvck1vZGVsLCBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQsIGdldFJHQk9iamVjdCB9IGZyb20gJyNjb2xvci9leHRyYWN0b3JzJztcbmltcG9ydCB7IENTUyB9IGZyb20gJyNjb2xvci9jc3MnO1xuaW1wb3J0IHsgaXNIYXJtb255LCBpc01peCwgbWlubWF4LCBub3JtYWxpemVIdWUsIHJvdW5kIH0gZnJvbSAnI2hlbHBlcnMnO1xuaW1wb3J0IHsgZ2V0QmxlbmRSZXR1cm4sIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMsIGdldENvbG9yUmV0dXJuLCBnZXRIYXJtb255UmV0dXJuLCBnZXRNaXhSZXR1cm4gfSBmcm9tICcjcmV0dXJucyc7XG5jb25zdCBiaW5kZWRNaXhlcnMgPSBPYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXModXRpbHMuY29sb3JNaXhlcikubWFwKChlbnRyeSkgPT4ge1xuICAgIGNvbnN0IFtrZXksIGZuXSA9IGVudHJ5O1xuICAgIHJldHVybiBba2V5LCBmbi5iaW5kKHV0aWxzLmNvbG9yTWl4ZXIpXTtcbn0pKTtcbmV4cG9ydCBjbGFzcyBDb2xvclRyYW5zbGF0b3Ige1xuICAgIGNvbnN0cnVjdG9yKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucyA9IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcik7XG4gICAgICAgIHRoaXMucmdiID0gZ2V0UkdCT2JqZWN0KGNvbG9yKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicpO1xuICAgIH1cbiAgICB1cGRhdGUoLi4uZXhjbHVkZSkge1xuICAgICAgICBpZiAoIWV4Y2x1ZGUuaW5jbHVkZXMoJ3JnYicpKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZVJHQigpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZXhjbHVkZS5pbmNsdWRlcygnaHNsJykpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlSFNMKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFleGNsdWRlLmluY2x1ZGVzKCdod2InKSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVIV0IoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4Y2x1ZGUuaW5jbHVkZXMoJ2xhYicpKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUxBQigpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZXhjbHVkZS5pbmNsdWRlcygnbGNoJykpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTENIKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFleGNsdWRlLmluY2x1ZGVzKCdjbXlrJykpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQ01ZSygpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZVJHQigpIHtcbiAgICAgICAgdGhpcy5yZ2IgPSB7XG4gICAgICAgICAgICAuLi5oc2xUb1JnYih0aGlzLmhzbC5ILCB0aGlzLmhzbC5TLCB0aGlzLmhzbC5MKSxcbiAgICAgICAgICAgIEE6IHRoaXMuaHNsLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlSFNMKCkge1xuICAgICAgICB0aGlzLmhzbCA9IHJnYlRvSHNsKHRoaXMucmdiLlIsIHRoaXMucmdiLkcsIHRoaXMucmdiLkIsIHRoaXMucmdiLkEpO1xuICAgIH1cbiAgICB1cGRhdGVIV0IoKSB7XG4gICAgICAgIHRoaXMuaHdiID0gcmdiVG9Id2IodGhpcy5yZ2IuUiwgdGhpcy5yZ2IuRywgdGhpcy5yZ2IuQiwgdGhpcy5yZ2IuQSk7XG4gICAgfVxuICAgIHVwZGF0ZUxBQigpIHtcbiAgICAgICAgdGhpcy5sYWIgPSB7XG4gICAgICAgICAgICAuLi5yZ2JUb0xhYih0aGlzLnJnYi5SLCB0aGlzLnJnYi5HLCB0aGlzLnJnYi5CKSxcbiAgICAgICAgICAgIEE6IHRoaXMucmdiLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlTENIKCkge1xuICAgICAgICB0aGlzLmxjaCA9IHtcbiAgICAgICAgICAgIC4uLnJnYlRvTGNoKHRoaXMucmdiLlIsIHRoaXMucmdiLkcsIHRoaXMucmdiLkIpLFxuICAgICAgICAgICAgQTogdGhpcy5yZ2IuQVxuICAgICAgICB9O1xuICAgIH1cbiAgICB1cGRhdGVDTVlLKCkge1xuICAgICAgICB0aGlzLmNteWsgPSByZ2JUb0NteWsodGhpcy5yZ2IuUiwgdGhpcy5yZ2IuRywgdGhpcy5yZ2IuQik7XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21IV0IoKSB7XG4gICAgICAgIHRoaXMucmdiID0ge1xuICAgICAgICAgICAgLi4uaHdiVG9SZ2IodGhpcy5od2IuSCwgdGhpcy5od2IuVywgdGhpcy5od2IuQiksXG4gICAgICAgICAgICBBOiB0aGlzLnJnYi5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21MQ0goKSB7XG4gICAgICAgIHRoaXMucmdiID0ge1xuICAgICAgICAgICAgLi4ubGNoVG9SZ2IodGhpcy5sY2guTCwgdGhpcy5sY2guQywgdGhpcy5sY2guSCksXG4gICAgICAgICAgICBBOiB0aGlzLnJnYi5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21DTVlLKCkge1xuICAgICAgICB0aGlzLnJnYiA9IHtcbiAgICAgICAgICAgIC4uLmNteWtUb1JnYih0aGlzLmNteWsuQywgdGhpcy5jbXlrLk0sIHRoaXMuY215ay5ZLCB0aGlzLmNteWsuSyksXG4gICAgICAgICAgICBBOiB0aGlzLnJnYi5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21MQUIoKSB7XG4gICAgICAgIHRoaXMucmdiID0ge1xuICAgICAgICAgICAgLi4ubGFiVG9SZ2IodGhpcy5sYWIuTCwgdGhpcy5sYWIuYSwgdGhpcy5sYWIuYiksXG4gICAgICAgICAgICBBOiB0aGlzLnJnYi5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZUxDSEZyb21MQUIoKSB7XG4gICAgICAgIHRoaXMubGNoID0ge1xuICAgICAgICAgICAgLi4ubGFiVG9MY2godGhpcy5sYWIuTCwgdGhpcy5sYWIuYSwgdGhpcy5sYWIuYiksXG4gICAgICAgICAgICBBOiB0aGlzLmxhYi5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZUxBQnJvbUxDSCgpIHtcbiAgICAgICAgdGhpcy5sYWIgPSB7XG4gICAgICAgICAgICAuLi5sY2hUb0xhYih0aGlzLmxjaC5MLCB0aGlzLmxjaC5DLCB0aGlzLmxjaC5IKSxcbiAgICAgICAgICAgIEE6IHRoaXMubGNoLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgc2V0T3B0aW9ucyhvcHRpb25zID0ge30pIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucyA9IHtcbiAgICAgICAgICAgIC4uLnRoaXMuX29wdGlvbnMsXG4gICAgICAgICAgICAuLi5vcHRpb25zXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRSKFIpIHtcbiAgICAgICAgdGhpcy5yZ2IuUiA9IG1pbm1heChSLCAwLCBCQVNFXzI1NSk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzZXRHKEcpIHtcbiAgICAgICAgdGhpcy5yZ2IuRyA9IG1pbm1heChHLCAwLCBCQVNFXzI1NSk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEIoQikge1xuICAgICAgICB0aGlzLnJnYi5CID0gbWlubWF4KEIsIDAsIEJBU0VfMjU1KTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0SChIKSB7XG4gICAgICAgIHRoaXMuaHNsLkggPSBub3JtYWxpemVIdWUoSCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdoc2wnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldFMoUykge1xuICAgICAgICB0aGlzLmhzbC5TID0gbWlubWF4KFMsIDAsIE1BWF9QQ0VOVCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdoc2wnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEwoTCkge1xuICAgICAgICB0aGlzLmhzbC5MID0gbWlubWF4KEwsIDAsIE1BWF9QQ0VOVCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdoc2wnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldFdoaXRlbmVzcyhXKSB7XG4gICAgICAgIHRoaXMuaHdiLlcgPSBtaW5tYXgoVywgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tSFdCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnaHdiJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRCbGFja25lc3MoQikge1xuICAgICAgICB0aGlzLmh3Yi5CID0gbWlubWF4KEIsIDAsIE1BWF9QQ0VOVCk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUhXQigpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2h3YicpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0Q0lFTChMKSB7XG4gICAgICAgIHRoaXMubGFiLkwgPSBtaW5tYXgoTCwgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTENIRnJvbUxBQigpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldENJRWEoYSkge1xuICAgICAgICB0aGlzLmxhYi5hID0gbWlubWF4KGEsIC1NQVhfTEFCLCBNQVhfTEFCKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTENIRnJvbUxBQigpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldENJRWIoYikge1xuICAgICAgICB0aGlzLmxhYi5iID0gbWlubWF4KGIsIC1NQVhfTEFCLCBNQVhfTEFCKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTENIRnJvbUxBQigpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldExDSEwobCkge1xuICAgICAgICB0aGlzLmxjaC5MID0gbWlubWF4KGwsIDAsIE1BWF9QQ0VOVCk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxBQnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldExDSEMoYykge1xuICAgICAgICB0aGlzLmxjaC5DID0gbWlubWF4KGMsIDAsIE1BWF9MQ0hfQyk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxBQnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldExDSEgoaCkge1xuICAgICAgICB0aGlzLmxjaC5IID0gbm9ybWFsaXplSHVlKGgpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21MQ0goKTtcbiAgICAgICAgdGhpcy51cGRhdGVMQUJyb21MQ0goKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicsICdsYWInLCAnbGNoJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRBKEEpIHtcbiAgICAgICAgY29uc3QgYWxwaGEgPSBtaW5tYXgoQSwgMCwgTUFYX0FMUEhBKTtcbiAgICAgICAgdGhpcy5yZ2IuQSA9IGFscGhhO1xuICAgICAgICB0aGlzLmhzbC5BID0gYWxwaGE7XG4gICAgICAgIHRoaXMuaHdiLkEgPSBhbHBoYTtcbiAgICAgICAgdGhpcy5sYWIuQSA9IGFscGhhO1xuICAgICAgICB0aGlzLmxjaC5BID0gYWxwaGE7XG4gICAgICAgIHRoaXMuY215ay5BID0gYWxwaGE7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRDKEMpIHtcbiAgICAgICAgdGhpcy5jbXlrLkMgPSBtaW5tYXgoQywgMCwgMTAwKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tQ01ZSygpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgnY215aycpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0TShNKSB7XG4gICAgICAgIHRoaXMuY215ay5NID0gbWlubWF4KE0sIDAsIDEwMCk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUNNWUsoKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ2NteWsnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldFkoWSkge1xuICAgICAgICB0aGlzLmNteWsuWSA9IG1pbm1heChZLCAwLCAxMDApO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21DTVlLKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdjbXlrJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRLKEspIHtcbiAgICAgICAgdGhpcy5jbXlrLksgPSBtaW5tYXgoSywgMCwgMTAwKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tQ01ZSygpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgnY215aycpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZ2V0IG9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9vcHRpb25zO1xuICAgIH1cbiAgICBnZXQgUigpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMucmdiLlIsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBHKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5yZ2IuRywgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEIoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLnJnYi5CLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgSCgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuaHNsLkgsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBTKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5oc2wuUywgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEwoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmhzbC5MLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgV2hpdGVuZXNzKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5od2IuVywgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEJsYWNrbmVzcygpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuaHdiLkIsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBDSUVMKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5sYWIuTCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IENJRWEoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmxhYi5hLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQ0lFYigpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMubGFiLmIsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBMQ0hMKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5sY2guTCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IExDSEMoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmxjaC5DLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgTENISCgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMubGNoLkgsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBBKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5oc2wuQSwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEMoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmNteWsuQywgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IE0oKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmNteWsuTSwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IFkoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmNteWsuWSwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEsoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmNteWsuSywgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEhFWE9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhFWCh0aGlzLnJnYik7XG4gICAgfVxuICAgIGdldCBIRVhBT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gdXRpbHMudHJhbnNsYXRlQ29sb3IuSEVYQSh0aGlzLnJnYik7XG4gICAgfVxuICAgIGdldCBSR0JPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSOiB0aGlzLlIsXG4gICAgICAgICAgICBHOiB0aGlzLkcsXG4gICAgICAgICAgICBCOiB0aGlzLkJcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0IFJHQkFPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi50aGlzLlJHQk9iamVjdCxcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgSFNMT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgSDogdGhpcy5ILFxuICAgICAgICAgICAgUzogdGhpcy5TLFxuICAgICAgICAgICAgTDogdGhpcy5MXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBIU0xBT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4udGhpcy5IU0xPYmplY3QsXG4gICAgICAgICAgICBBOiB0aGlzLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0IEhXQk9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEg6IHRoaXMuSCxcbiAgICAgICAgICAgIFc6IHRoaXMuV2hpdGVuZXNzLFxuICAgICAgICAgICAgQjogdGhpcy5CbGFja25lc3NcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0IEhXQkFPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi50aGlzLkhXQk9iamVjdCxcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgQ0lFTGFiT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgTDogdGhpcy5DSUVMLFxuICAgICAgICAgICAgYTogdGhpcy5DSUVhLFxuICAgICAgICAgICAgYjogdGhpcy5DSUViXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBDSUVMYWJBT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4udGhpcy5DSUVMYWJPYmplY3QsXG4gICAgICAgICAgICBBOiB0aGlzLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0IExDSE9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEw6IHRoaXMuTENITCxcbiAgICAgICAgICAgIEM6IHRoaXMuTENIQyxcbiAgICAgICAgICAgIEg6IHRoaXMuTENISFxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgTENIQU9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnRoaXMuTENIT2JqZWN0LFxuICAgICAgICAgICAgQTogdGhpcy5BXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBDTVlLT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgQzogdGhpcy5DLFxuICAgICAgICAgICAgTTogdGhpcy5NLFxuICAgICAgICAgICAgWTogdGhpcy5ZLFxuICAgICAgICAgICAgSzogdGhpcy5LXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBDTVlLQU9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnRoaXMuQ01ZS09iamVjdCxcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgSEVYKCkge1xuICAgICAgICByZXR1cm4gQ1NTLkhFWCh7XG4gICAgICAgICAgICBSOiB0aGlzLlIsXG4gICAgICAgICAgICBHOiB0aGlzLkcsXG4gICAgICAgICAgICBCOiB0aGlzLkJcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGdldCBIRVhBKCkge1xuICAgICAgICByZXR1cm4gQ1NTLkhFWCh7XG4gICAgICAgICAgICBSOiB0aGlzLlIsXG4gICAgICAgICAgICBHOiB0aGlzLkcsXG4gICAgICAgICAgICBCOiB0aGlzLkIsXG4gICAgICAgICAgICBBOiB0aGlzLkEgKiBCQVNFXzI1NVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZ2V0IFJHQigpIHtcbiAgICAgICAgcmV0dXJuIENTUy5SR0Ioe1xuICAgICAgICAgICAgUjogdGhpcy5SLFxuICAgICAgICAgICAgRzogdGhpcy5HLFxuICAgICAgICAgICAgQjogdGhpcy5CXG4gICAgICAgIH0sIHRoaXMub3B0aW9ucyk7XG4gICAgfVxuICAgIGdldCBSR0JBKCkge1xuICAgICAgICByZXR1cm4gQ1NTLlJHQih7XG4gICAgICAgICAgICBSOiB0aGlzLlIsXG4gICAgICAgICAgICBHOiB0aGlzLkcsXG4gICAgICAgICAgICBCOiB0aGlzLkIsXG4gICAgICAgICAgICBBOiB0aGlzLkFcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IEhTTCgpIHtcbiAgICAgICAgcmV0dXJuIENTUy5IU0woe1xuICAgICAgICAgICAgSDogdGhpcy5ILFxuICAgICAgICAgICAgUzogdGhpcy5TLFxuICAgICAgICAgICAgTDogdGhpcy5MXG4gICAgICAgIH0sIHRoaXMub3B0aW9ucyk7XG4gICAgfVxuICAgIGdldCBIU0xBKCkge1xuICAgICAgICByZXR1cm4gQ1NTLkhTTCh7XG4gICAgICAgICAgICBIOiB0aGlzLkgsXG4gICAgICAgICAgICBTOiB0aGlzLlMsXG4gICAgICAgICAgICBMOiB0aGlzLkwsXG4gICAgICAgICAgICBBOiB0aGlzLkFcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IEhXQigpIHtcbiAgICAgICAgcmV0dXJuIENTUy5IV0Ioe1xuICAgICAgICAgICAgSDogdGhpcy5ILFxuICAgICAgICAgICAgVzogdGhpcy5XaGl0ZW5lc3MsXG4gICAgICAgICAgICBCOiB0aGlzLkJsYWNrbmVzc1xuICAgICAgICB9LCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgSFdCQSgpIHtcbiAgICAgICAgcmV0dXJuIENTUy5IV0Ioe1xuICAgICAgICAgICAgSDogdGhpcy5ILFxuICAgICAgICAgICAgVzogdGhpcy5XaGl0ZW5lc3MsXG4gICAgICAgICAgICBCOiB0aGlzLkJsYWNrbmVzcyxcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9LCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgQ0lFTGFiKCkge1xuICAgICAgICByZXR1cm4gQ1NTLkNJRUxhYih7XG4gICAgICAgICAgICBMOiB0aGlzLkNJRUwsXG4gICAgICAgICAgICBhOiB0aGlzLkNJRWEsXG4gICAgICAgICAgICBiOiB0aGlzLkNJRWJcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IENJRUxhYkEoKSB7XG4gICAgICAgIHJldHVybiBDU1MuQ0lFTGFiKHtcbiAgICAgICAgICAgIEw6IHRoaXMuQ0lFTCxcbiAgICAgICAgICAgIGE6IHRoaXMuQ0lFYSxcbiAgICAgICAgICAgIGI6IHRoaXMuQ0lFYixcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9LCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgTENIKCkge1xuICAgICAgICByZXR1cm4gQ1NTLkxDSCh7XG4gICAgICAgICAgICBMOiB0aGlzLkxDSEwsXG4gICAgICAgICAgICBDOiB0aGlzLkxDSEMsXG4gICAgICAgICAgICBIOiB0aGlzLkxDSEhcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IExDSEEoKSB7XG4gICAgICAgIHJldHVybiBDU1MuTENIKHtcbiAgICAgICAgICAgIEw6IHRoaXMuTENITCxcbiAgICAgICAgICAgIEM6IHRoaXMuTENIQyxcbiAgICAgICAgICAgIEg6IHRoaXMuTENISCxcbiAgICAgICAgICAgIEE6IHRoaXMuQVxuICAgICAgICB9LCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgQ01ZSygpIHtcbiAgICAgICAgcmV0dXJuIENTUy5DTVlLKHtcbiAgICAgICAgICAgIEM6IHRoaXMuQyxcbiAgICAgICAgICAgIE06IHRoaXMuTSxcbiAgICAgICAgICAgIFk6IHRoaXMuWSxcbiAgICAgICAgICAgIEs6IHRoaXMuS1xuICAgICAgICB9LCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgQ01ZS0EoKSB7XG4gICAgICAgIHJldHVybiBDU1MuQ01ZSyh7XG4gICAgICAgICAgICBDOiB0aGlzLkMsXG4gICAgICAgICAgICBNOiB0aGlzLk0sXG4gICAgICAgICAgICBZOiB0aGlzLlksXG4gICAgICAgICAgICBLOiB0aGlzLkssXG4gICAgICAgICAgICBBOiB0aGlzLkFcbiAgICAgICAgfSwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSEVYT2JqZWN0KGNvbG9yKSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIDAsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhFWCk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hFWChjb2xvcikge1xuICAgICAgICByZXR1cm4gQ1NTLkhFWChDb2xvclRyYW5zbGF0b3IudG9IRVhPYmplY3QoY29sb3IpKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSEVYQU9iamVjdChjb2xvcikge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCAwLCB1dGlscy50cmFuc2xhdGVDb2xvci5IRVhBKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSEVYQShjb2xvcikge1xuICAgICAgICByZXR1cm4gQ1NTLkhFWChDb2xvclRyYW5zbGF0b3IudG9IRVhBT2JqZWN0KGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b1JHQk9iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLlJHQik7XG4gICAgfVxuICAgIHN0YXRpYyB0b1JHQihjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IHJnYiA9IENvbG9yVHJhbnNsYXRvci50b1JHQk9iamVjdChjb2xvciwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGRldGVjdGVkT3B0aW9ucyA9IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcik7XG4gICAgICAgIHJldHVybiBDU1MuUkdCKHJnYiwgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvUkdCQU9iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLlJHQkEpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9SR0JBKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgcmdiYSA9IENvbG9yVHJhbnNsYXRvci50b1JHQkFPYmplY3QoY29sb3IsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkZXRlY3RlZE9wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICByZXR1cm4gQ1NTLlJHQihyZ2JhLCBkZXRlY3RlZE9wdGlvbnMpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IU0xPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB1dGlscy50cmFuc2xhdGVDb2xvci5IU0wpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IU0woY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBoc2wgPSBDb2xvclRyYW5zbGF0b3IudG9IU0xPYmplY3QoY29sb3IsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkZXRlY3RlZE9wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICByZXR1cm4gQ1NTLkhTTChoc2wsIGRldGVjdGVkT3B0aW9ucyk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hTTEFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB1dGlscy50cmFuc2xhdGVDb2xvci5IU0xBKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFNMQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IGhzbGEgPSBDb2xvclRyYW5zbGF0b3IudG9IU0xBT2JqZWN0KGNvbG9yLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgZGV0ZWN0ZWRPcHRpb25zID0gZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKTtcbiAgICAgICAgcmV0dXJuIENTUy5IU0woaHNsYSwgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFdCT2JqZWN0KGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgbW9kZWwgPSBnZXRDb2xvck1vZGVsKGNvbG9yKTtcbiAgICAgICAgcmV0dXJuIGdldENvbG9yUmV0dXJuKGNvbG9yLCBtb2RlbCwgb3B0aW9ucy5kZWNpbWFscywgdXRpbHMudHJhbnNsYXRlQ29sb3IuSFdCKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFdCKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgaHdiID0gQ29sb3JUcmFuc2xhdG9yLnRvSFdCT2JqZWN0KGNvbG9yLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgZGV0ZWN0ZWRPcHRpb25zID0gZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKTtcbiAgICAgICAgcmV0dXJuIENTUy5IV0IoaHdiLCBkZXRlY3RlZE9wdGlvbnMpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IV0JBT2JqZWN0KGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgbW9kZWwgPSBnZXRDb2xvck1vZGVsKGNvbG9yKTtcbiAgICAgICAgcmV0dXJuIGdldENvbG9yUmV0dXJuKGNvbG9yLCBtb2RlbCwgb3B0aW9ucy5kZWNpbWFscywgdXRpbHMudHJhbnNsYXRlQ29sb3IuSFdCQSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hXQkEoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBod2IgPSBDb2xvclRyYW5zbGF0b3IudG9IV0JBT2JqZWN0KGNvbG9yLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgZGV0ZWN0ZWRPcHRpb25zID0gZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKTtcbiAgICAgICAgcmV0dXJuIENTUy5IV0IoaHdiLCBkZXRlY3RlZE9wdGlvbnMpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DSUVMYWJPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB1dGlscy50cmFuc2xhdGVDb2xvci5DSUVMYWIpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DSUVMYWIoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBsYWIgPSBDb2xvclRyYW5zbGF0b3IudG9DSUVMYWJPYmplY3QoY29sb3IsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkZXRlY3RlZE9wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICByZXR1cm4gQ1NTLkNJRUxhYihsYWIsIGRldGVjdGVkT3B0aW9ucyk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0NJRUxhYkFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB1dGlscy50cmFuc2xhdGVDb2xvci5DSUVMYWJBKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ0lFTGFiQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IGxhYiA9IENvbG9yVHJhbnNsYXRvci50b0NJRUxhYkFPYmplY3QoY29sb3IsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkZXRlY3RlZE9wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICByZXR1cm4gQ1NTLkNJRUxhYihsYWIsIGRldGVjdGVkT3B0aW9ucyk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0xDSE9iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkxDSCk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0xDSChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IGxjaCA9IENvbG9yVHJhbnNsYXRvci50b0xDSE9iamVjdChjb2xvciwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGRldGVjdGVkT3B0aW9ucyA9IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcik7XG4gICAgICAgIHJldHVybiBDU1MuTENIKGxjaCwgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvTENIQU9iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkxDSEEpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9MQ0hBKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgbGNoID0gQ29sb3JUcmFuc2xhdG9yLnRvTENIQU9iamVjdChjb2xvciwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGRldGVjdGVkT3B0aW9ucyA9IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcik7XG4gICAgICAgIHJldHVybiBDU1MuTENIKGxjaCwgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ01ZS09iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChjb2xvcik7XG4gICAgICAgIHJldHVybiBnZXRDb2xvclJldHVybihjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkNNWUspO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DTVlLKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgY215ayA9IENvbG9yVHJhbnNsYXRvci50b0NNWUtPYmplY3QoY29sb3IsIG9wdGlvbnMpO1xuICAgICAgICBjb25zdCBkZXRlY3RlZE9wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICByZXR1cm4gQ1NTLkNNWUsoY215aywgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ01ZS0FPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICBjb25zdCBtb2RlbCA9IGdldENvbG9yTW9kZWwoY29sb3IpO1xuICAgICAgICByZXR1cm4gZ2V0Q29sb3JSZXR1cm4oY29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB1dGlscy50cmFuc2xhdGVDb2xvci5DTVlLQSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0NNWUtBKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgY215a2EgPSBDb2xvclRyYW5zbGF0b3IudG9DTVlLQU9iamVjdChjb2xvciwgb3B0aW9ucyk7XG4gICAgICAgIGNvbnN0IGRldGVjdGVkT3B0aW9ucyA9IGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcik7XG4gICAgICAgIHJldHVybiBDU1MuQ01ZSyhjbXlrYSwgZGV0ZWN0ZWRPcHRpb25zKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSEVYT2JqZWN0KGZyb20sIHRvLCBzdGVwcyA9IERFRkFVTFRfQkxFTkRfU1RFUFMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBzdGVwcywgMCwgdXRpbHMudHJhbnNsYXRlQ29sb3IuSEVYKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSEVYKGZyb20sIHRvLCBzdGVwcyA9IERFRkFVTFRfQkxFTkRfU1RFUFMpIHtcbiAgICAgICAgcmV0dXJuIENvbG9yVHJhbnNsYXRvci5nZXRCbGVuZEhFWE9iamVjdChmcm9tLCB0bywgc3RlcHMpXG4gICAgICAgICAgICAubWFwKChjb2xvcikgPT4gQ1NTLkhFWChjb2xvcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIRVhBT2JqZWN0KGZyb20sIHRvLCBzdGVwcyA9IERFRkFVTFRfQkxFTkRfU1RFUFMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBzdGVwcywgMCwgdXRpbHMudHJhbnNsYXRlQ29sb3IuSEVYQSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhFWEEoZnJvbSwgdG8sIHN0ZXBzID0gREVGQVVMVF9CTEVORF9TVEVQUykge1xuICAgICAgICByZXR1cm4gQ29sb3JUcmFuc2xhdG9yLmdldEJsZW5kSEVYQU9iamVjdChmcm9tLCB0bywgc3RlcHMpXG4gICAgICAgICAgICAubWFwKChjb2xvcikgPT4gQ1NTLkhFWChjb2xvcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRSR0JPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuUkdCXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRSR0IoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuUkdCLFxuICAgICAgICAgICAgY3NzRnVuY3Rpb246IENTUy5SR0JcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZFJHQkFPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuUkdCQVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kUkdCQShmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5SR0JBLFxuICAgICAgICAgICAgY3NzRnVuY3Rpb246IENTUy5SR0JcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhTTE9iamVjdChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5IU0xcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhTTChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5IU0wsXG4gICAgICAgICAgICBjc3NGdW5jdGlvbjogQ1NTLkhTTFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSFNMQU9iamVjdChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5IU0xBXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIU0xBKGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHtcbiAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgZm91cnRoUGFyYW1ldGVyLFxuICAgICAgICAgICAgdHJhbnNsYXRlRnVuY3Rpb246IHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhTTEEsXG4gICAgICAgICAgICBjc3NGdW5jdGlvbjogQ1NTLkhTTFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSFdCT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHtcbiAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgZm91cnRoUGFyYW1ldGVyLFxuICAgICAgICAgICAgdHJhbnNsYXRlRnVuY3Rpb246IHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhXQlxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSFdCKGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHtcbiAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgZm91cnRoUGFyYW1ldGVyLFxuICAgICAgICAgICAgdHJhbnNsYXRlRnVuY3Rpb246IHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhXQixcbiAgICAgICAgICAgIGNzc0Z1bmN0aW9uOiBDU1MuSFdCXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIV0JBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHtcbiAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgZm91cnRoUGFyYW1ldGVyLFxuICAgICAgICAgICAgdHJhbnNsYXRlRnVuY3Rpb246IHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkhXQkFcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhXQkEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuSFdCQSxcbiAgICAgICAgICAgIGNzc0Z1bmN0aW9uOiBDU1MuSFdCXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRDSUVMYWJPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuQ0lFTGFiXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRDSUVMYWIoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuQ0lFTGFiLFxuICAgICAgICAgICAgY3NzRnVuY3Rpb246IENTUy5DSUVMYWJcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZENJRUxhYkFPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuV2l0aFBhcmFtZXRlcnMoe1xuICAgICAgICAgICAgZnJvbSxcbiAgICAgICAgICAgIHRvLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBmb3VydGhQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0cmFuc2xhdGVGdW5jdGlvbjogdXRpbHMudHJhbnNsYXRlQ29sb3IuQ0lFTGFiQVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kQ0lFTGFiQShmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5DSUVMYWJBLFxuICAgICAgICAgICAgY3NzRnVuY3Rpb246IENTUy5DSUVMYWJcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZExDSE9iamVjdChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5MQ0hcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZExDSChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5MQ0gsXG4gICAgICAgICAgICBjc3NGdW5jdGlvbjogQ1NTLkxDSFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kTENIQU9iamVjdChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm5XaXRoUGFyYW1ldGVycyh7XG4gICAgICAgICAgICBmcm9tLFxuICAgICAgICAgICAgdG8sXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGZvdXJ0aFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRyYW5zbGF0ZUZ1bmN0aW9uOiB1dGlscy50cmFuc2xhdGVDb2xvci5MQ0hBXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRMQ0hBKGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybldpdGhQYXJhbWV0ZXJzKHtcbiAgICAgICAgICAgIGZyb20sXG4gICAgICAgICAgICB0byxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgZm91cnRoUGFyYW1ldGVyLFxuICAgICAgICAgICAgdHJhbnNsYXRlRnVuY3Rpb246IHV0aWxzLnRyYW5zbGF0ZUNvbG9yLkxDSEEsXG4gICAgICAgICAgICBjc3NGdW5jdGlvbjogQ1NTLkxDSFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgc3RhdGljIGdldE1peEhFWE9iamVjdChjb2xvcnMsIG1vZGUgPSBNaXguQURESVRJVkUpIHtcbiAgICAgICAgcmV0dXJuIHV0aWxzLmNvbG9yTWl4ZXIuSEVYKGNvbG9ycywgbW9kZSwgZmFsc2UpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SEVYKGNvbG9ycywgbW9kZSA9IE1peC5BRERJVElWRSkge1xuICAgICAgICByZXR1cm4gdXRpbHMuY29sb3JNaXhlci5IRVgoY29sb3JzLCBtb2RlLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIGdldE1peEhFWEFPYmplY3QoY29sb3JzLCBtb2RlID0gTWl4LkFERElUSVZFKSB7XG4gICAgICAgIHJldHVybiB1dGlscy5jb2xvck1peGVyLkhFWEEoY29sb3JzLCBtb2RlLCBmYWxzZSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIRVhBKGNvbG9ycywgbW9kZSA9IE1peC5BRERJVElWRSkge1xuICAgICAgICByZXR1cm4gdXRpbHMuY29sb3JNaXhlci5IRVhBKGNvbG9ycywgbW9kZSwgdHJ1ZSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhSR0JPYmplY3QoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oe1xuICAgICAgICAgICAgY29sb3JzLFxuICAgICAgICAgICAgc2Vjb25kUGFyYW1ldGVyLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBjb2xvck1peGVyRnVuY3Rpb246IGJpbmRlZE1peGVycy5SR0IsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4UkdCKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKHtcbiAgICAgICAgICAgIGNvbG9ycyxcbiAgICAgICAgICAgIHNlY29uZFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgY29sb3JNaXhlckZ1bmN0aW9uOiBiaW5kZWRNaXhlcnMuUkdCLFxuICAgICAgICAgICAgY3NzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4UkdCQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLlJHQkEsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4UkdCQShjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLlJHQkEsXG4gICAgICAgICAgICBjc3M6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIU0xPYmplY3QoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oe1xuICAgICAgICAgICAgY29sb3JzLFxuICAgICAgICAgICAgc2Vjb25kUGFyYW1ldGVyLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBjb2xvck1peGVyRnVuY3Rpb246IGJpbmRlZE1peGVycy5IU0wsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFNMKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKHtcbiAgICAgICAgICAgIGNvbG9ycyxcbiAgICAgICAgICAgIHNlY29uZFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgY29sb3JNaXhlckZ1bmN0aW9uOiBiaW5kZWRNaXhlcnMuSFNMLFxuICAgICAgICAgICAgY3NzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFNMQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkhTTEEsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFNMQShjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkhTTEEsXG4gICAgICAgICAgICBjc3M6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIV0JPYmplY3QoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oe1xuICAgICAgICAgICAgY29sb3JzLFxuICAgICAgICAgICAgc2Vjb25kUGFyYW1ldGVyLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBjb2xvck1peGVyRnVuY3Rpb246IGJpbmRlZE1peGVycy5IV0IsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFdCKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKHtcbiAgICAgICAgICAgIGNvbG9ycyxcbiAgICAgICAgICAgIHNlY29uZFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgY29sb3JNaXhlckZ1bmN0aW9uOiBiaW5kZWRNaXhlcnMuSFdCLFxuICAgICAgICAgICAgY3NzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFdCQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkhXQkEsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFdCQShjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkhXQkEsXG4gICAgICAgICAgICBjc3M6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhDSUVMYWJPYmplY3QoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oe1xuICAgICAgICAgICAgY29sb3JzLFxuICAgICAgICAgICAgc2Vjb25kUGFyYW1ldGVyLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBjb2xvck1peGVyRnVuY3Rpb246IGJpbmRlZE1peGVycy5DSUVMYWIsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4Q0lFTGFiKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKHtcbiAgICAgICAgICAgIGNvbG9ycyxcbiAgICAgICAgICAgIHNlY29uZFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgY29sb3JNaXhlckZ1bmN0aW9uOiBiaW5kZWRNaXhlcnMuQ0lFTGFiLFxuICAgICAgICAgICAgY3NzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4Q0lFTGFiQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkNJRUxhYkEsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4Q0lFTGFiQShjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkNJRUxhYkEsXG4gICAgICAgICAgICBjc3M6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhMQ0hPYmplY3QoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oe1xuICAgICAgICAgICAgY29sb3JzLFxuICAgICAgICAgICAgc2Vjb25kUGFyYW1ldGVyLFxuICAgICAgICAgICAgdGhpcmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICBjb2xvck1peGVyRnVuY3Rpb246IGJpbmRlZE1peGVycy5MQ0gsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4TENIKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKHtcbiAgICAgICAgICAgIGNvbG9ycyxcbiAgICAgICAgICAgIHNlY29uZFBhcmFtZXRlcixcbiAgICAgICAgICAgIHRoaXJkUGFyYW1ldGVyLFxuICAgICAgICAgICAgY29sb3JNaXhlckZ1bmN0aW9uOiBiaW5kZWRNaXhlcnMuTENILFxuICAgICAgICAgICAgY3NzOiB0cnVlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4TENIQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkxDSEEsXG4gICAgICAgICAgICBjc3M6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4TENIQShjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybih7XG4gICAgICAgICAgICBjb2xvcnMsXG4gICAgICAgICAgICBzZWNvbmRQYXJhbWV0ZXIsXG4gICAgICAgICAgICB0aGlyZFBhcmFtZXRlcixcbiAgICAgICAgICAgIGNvbG9yTWl4ZXJGdW5jdGlvbjogYmluZGVkTWl4ZXJzLkxDSEEsXG4gICAgICAgICAgICBjc3M6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRTaGFkZXMoY29sb3IsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBzZWNvbmRQYXJhbWV0ZXIgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gdXRpbHMuZ2V0Q29sb3JNaXh0dXJlKGNvbG9yLCBzZWNvbmRQYXJhbWV0ZXIsIHRydWUsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dCh0aGlyZFBhcmFtZXRlciB8fCB7fSwgY29sb3IpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdXRpbHMuZ2V0Q29sb3JNaXh0dXJlKGNvbG9yLCBERUZBVUxUX1NIQURFU19USU5UU19TVEVQUywgdHJ1ZSwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KHNlY29uZFBhcmFtZXRlciB8fCB7fSwgY29sb3IpKTtcbiAgICB9XG4gICAgc3RhdGljIGdldFRpbnRzKGNvbG9yLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2Vjb25kUGFyYW1ldGVyID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcmV0dXJuIHV0aWxzLmdldENvbG9yTWl4dHVyZShjb2xvciwgc2Vjb25kUGFyYW1ldGVyLCBmYWxzZSwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KHRoaXJkUGFyYW1ldGVyIHx8IHt9LCBjb2xvcikpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1dGlscy5nZXRDb2xvck1peHR1cmUoY29sb3IsIERFRkFVTFRfU0hBREVTX1RJTlRTX1NURVBTLCBmYWxzZSwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KHNlY29uZFBhcmFtZXRlciB8fCB7fSwgY29sb3IpKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEhhcm1vbnkoY29sb3IsIHNlY29uZFBhcmFtLCB0aGlyZFBhcmFtLCBmb3VydGhQYXJhbSkge1xuICAgICAgICBpZiAoaXNIYXJtb255KHNlY29uZFBhcmFtKSkge1xuICAgICAgICAgICAgcmV0dXJuIGdldEhhcm1vbnlSZXR1cm4oc2Vjb25kUGFyYW0sIGNvbG9yLCBpc01peCh0aGlyZFBhcmFtKVxuICAgICAgICAgICAgICAgID8gdGhpcmRQYXJhbVxuICAgICAgICAgICAgICAgIDogTWl4LkFERElUSVZFLCBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQoaXNNaXgodGhpcmRQYXJhbSlcbiAgICAgICAgICAgICAgICA/IChmb3VydGhQYXJhbSB8fCB7fSlcbiAgICAgICAgICAgICAgICA6IHRoaXJkUGFyYW0gfHwge30sIGNvbG9yKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNNaXgoc2Vjb25kUGFyYW0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0SGFybW9ueVJldHVybihIYXJtb255LkNPTVBMRU1FTlRBUlksIGNvbG9yLCBzZWNvbmRQYXJhbSwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KHRoaXJkUGFyYW0gfHwge30sIGNvbG9yKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGdldEhhcm1vbnlSZXR1cm4oSGFybW9ueS5DT01QTEVNRU5UQVJZLCBjb2xvciwgTWl4LkFERElUSVZFLCBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQoc2Vjb25kUGFyYW0gfHwge30sIGNvbG9yKSk7XG4gICAgfVxufVxuZXhwb3J0IHsgSGFybW9ueSwgTWl4IH07XG4iLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCBjb2xvciA9IG5ldyBDb2xvclRyYW5zbGF0b3IoJ2hzbCgxODAgMTAwJSA1MCUpJywgeyBkZWNpbWFsczogMCB9KTtcblxuICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IDEwOyByb3crKykge1xuXG4gICAgICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IDEwOyBjb2wrKykge1xuXG4gICAgICAgICAgICBjb2xvclxuICAgICAgICAgICAgICAgIC5zZXRTKHJvdyAqIDEwKVxuICAgICAgICAgICAgICAgIC5zZXRMKGNvbCAqIDUgKyAzMCk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICAgICAgICBib3guY2xhc3NMaXN0LmFkZCgnYm94Jyk7XG4gICAgICAgICAgICBib3guc3R5bGUuYmFja2dyb3VuZCA9IGNvbG9yLkhFWDtcblxuICAgICAgICAgICAgYm94LmlubmVyVGV4dCA9XG4gICAgICAgICAgICAgICAgYFI6JHtjb2xvci5SfVxuICAgICAgICAgICAgICAgICBHOiR7Y29sb3IuR31cbiAgICAgICAgICAgICAgICAgQjoke2NvbG9yLkJ9YDtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChib3gpO1xuXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IpID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnN0IGNvbG9yID0gbmV3IENvbG9yVHJhbnNsYXRvcih7IFI6IDI1NSwgRzogMCwgQjogMCB9KTtcbiAgICBjb25zdCBodWUgPSBbMCwgMzAsIDYwLCAxMjAsIDI0MCwgMjgwLCAzMjAsIDBdO1xuICAgIGxldCByYWluYm93O1xuXG4gICAgZm9yIChsZXQgciA9IDA7IHIgPCBodWUubGVuZ3RoOyByKyspIHtcblxuICAgICAgICBjb2xvci5zZXRIKGh1ZVtyXSk7XG5cbiAgICAgICAgY29uc3QgYm93ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgICAgYm93LmNsYXNzTGlzdC5hZGQoJ3JhaW5ib3cnKTtcbiAgICAgICAgYm93LnN0eWxlLmJhY2tncm91bmQgPSBjb2xvci5IRVg7XG5cbiAgICAgICAgaWYgKHJhaW5ib3cpIHtcbiAgICAgICAgICAgIHJhaW5ib3cuYXBwZW5kQ2hpbGQoYm93KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChib3cpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmFpbmJvdyA9IGJvdztcbiAgICB9XG5cbiAgICByYWluYm93LnN0eWxlLmJhY2tncm91bmQgPSAnIzMzMyc7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IpID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnN0IGhzbCA9IHsgSDogMCwgUzogJzkwJScsIEw6ICc1MCUnIH07XG4gICAgY29uc3QgaHVlID0gW3VuZGVmaW5lZCwgNTUsIDMwLCAwLCAyOTAsIDIyMCwgMTMwXTtcbiAgICBjb25zdCB0b3RhbCA9IGh1ZS5sZW5ndGg7XG5cbiAgICBmb3IgKGxldCByb3cgPSAwOyByb3cgPCB0b3RhbDsgcm93KyspIHtcblxuICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCB0b3RhbDsgY29sKyspIHtcblxuICAgICAgICAgICAgbGV0IGluZGV4ID0gdG90YWwgLSByb3cgKyBjb2w7XG4gICAgICAgICAgICBpZiAoaW5kZXggPj0gdG90YWwpIHtcbiAgICAgICAgICAgICAgICBpbmRleCAtPSB0b3RhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGhzbC5IID0gaHVlW2luZGV4XTtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGh1ZVtpbmRleF0gPT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgID8gJyNGRkYnXG4gICAgICAgICAgICAgICAgOiBDb2xvclRyYW5zbGF0b3IudG9IRVgoaHNsKTtcbiAgICAgICAgICAgIGNvbnN0IGJveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICAgICAgICBib3guY2xhc3NMaXN0LmFkZCgnZmxhZycpO1xuICAgICAgICAgICAgYm94LnN0eWxlLmJhY2tncm91bmQgPSByZ2I7XG5cbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChib3gpO1xuXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IpID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnN0IGhleENvbG9ycyA9IFtcbiAgICAgICAgJyNGRTI3MTInLCAnI0ZFNTQwOScsICcjRkI5OTAyJyxcbiAgICAgICAgJyNGQUJEMDMnLCAnI0ZGRkUzMicsICcjRDFFQTJDJyxcbiAgICAgICAgJyM2NkIxMzInLCAnIzAzOTJDRScsICcjMDI0N0ZFJyxcbiAgICAgICAgJyMzRDAwQTUnLCAnIzg2MDFCMCcsICcjQTcxOTRCJ1xuICAgIF07XG5cbiAgICBoZXhDb2xvcnMuZm9yRWFjaCgoY29sb3IpID0+IHtcblxuICAgICAgICBjb25zdCByZ2IgPSBDb2xvclRyYW5zbGF0b3IudG9SR0IoY29sb3IpO1xuICAgICAgICBjb25zdCBoc2wgPSBDb2xvclRyYW5zbGF0b3IudG9IU0woY29sb3IsIHsgZGVjaW1hbHM6IDAgfSk7XG4gICAgICAgIGNvbnN0IGh3YiA9IENvbG9yVHJhbnNsYXRvci50b0hXQihjb2xvciwgeyBkZWNpbWFsczogMCB9KTtcbiAgICAgICAgY29uc3QgbGFiID0gQ29sb3JUcmFuc2xhdG9yLnRvQ0lFTGFiKGNvbG9yLCB7IGRlY2ltYWxzOiAwIH0pO1xuICAgICAgICBjb25zdCBsY2ggPSBDb2xvclRyYW5zbGF0b3IudG9MQ0goY29sb3IsIHsgZGVjaW1hbHM6IDAgfSk7XG5cbiAgICAgICAgY29uc3QgcmdiRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnN0IGhzbERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBjb25zdCBod2JEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29uc3QgbGFiRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnN0IGxjaERpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICAgIHJnYkRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSByZ2I7XG4gICAgICAgIHJnYkRpdi50ZXh0Q29udGVudCA9IHJnYjtcblxuICAgICAgICBoc2xEaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gaHNsO1xuICAgICAgICBoc2xEaXYudGV4dENvbnRlbnQgPSBoc2w7XG5cbiAgICAgICAgaHdiRGl2LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGh3YjtcbiAgICAgICAgaHdiRGl2LnRleHRDb250ZW50ID0gaHdiO1xuXG4gICAgICAgIGxhYkRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBsYWI7XG4gICAgICAgIGxhYkRpdi50ZXh0Q29udGVudCA9IGxhYjtcblxuICAgICAgICBsY2hEaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gbGNoO1xuICAgICAgICBsY2hEaXYudGV4dENvbnRlbnQgPSBsY2g7XG5cbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHJnYkRpdik7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChoc2xEaXYpO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoaHdiRGl2KTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGxhYkRpdik7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChsY2hEaXYpO1xuXG4gICAgfSk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IpID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGNvbnN0IGNvbG9ycyA9IFtcbiAgICAgICAgJ3JlZCcsXG4gICAgICAgICdsaW1lJyxcbiAgICAgICAgJ2JsdWUnLFxuICAgICAgICAnYXF1YScsXG4gICAgICAgICd5ZWxsb3cnLFxuICAgICAgICAnZnVjaHNpYSdcbiAgICBdO1xuICAgIGNvbnN0IHRvdGFsID0gY29sb3JzLmxlbmd0aDtcblxuICAgIGZvciAobGV0IHJvdyA9IDA7IHJvdyA8IHRvdGFsOyByb3crKykge1xuXG4gICAgICAgIGNvbnN0IGhzbCA9IENvbG9yVHJhbnNsYXRvci50b0hTTE9iamVjdChjb2xvcnNbcm93XSk7XG4gICAgICAgIGNvbnN0IHN0ZXAgPSBoc2wuUyAvICh0b3RhbCAtIDEpO1xuXG4gICAgICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8IHRvdGFsOyBjb2wrKykge1xuXG4gICAgICAgICAgICBjb25zdCByZ2IgPSBDb2xvclRyYW5zbGF0b3IudG9IRVgoaHNsKTtcbiAgICAgICAgICAgIGNvbnN0IGNteWsgPSBDb2xvclRyYW5zbGF0b3IudG9DTVlLT2JqZWN0KGhzbCwgeyBkZWNpbWFsczogMCB9KTtcblxuICAgICAgICAgICAgY29uc3QgYm94ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBib3guY2xhc3NMaXN0LmFkZCgnYm94Jyk7XG4gICAgICAgICAgICBib3guc3R5bGUuYmFja2dyb3VuZCA9IHJnYjtcbiAgICAgICAgICAgIGJveC5pbm5lclRleHQgPSBgQzoke2NteWsuQ31cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTToke2NteWsuTX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWToke2NteWsuWX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSzoke2NteWsuS31gO1xuXG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm94KTtcblxuICAgICAgICAgICAgaHNsLlMgLT0gc3RlcDtcblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCByb3dzID0gMTE7XG4gICAgY29uc3QgbXVsdCA9IDM7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJvd3M7IGkrKykge1xuXG4gICAgICAgIGNvbnN0IGJsZW5kcyA9IENvbG9yVHJhbnNsYXRvci5nZXRCbGVuZEhFWCgnI0YwMCcsICcjRkYwJywgbXVsdCArIGkgKiBtdWx0KTtcblxuICAgICAgICBibGVuZHMuZm9yRWFjaCgoYmxlbmQsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBib3ggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIGJveC5jbGFzc0xpc3QuYWRkKCdib3gnLCBgZmlsZSR7aX1gKTtcbiAgICAgICAgICAgIGJveC5zdHlsZS5iYWNrZ3JvdW5kID0gYmxlbmQ7XG4gICAgICAgICAgICBib3guaW5uZXJUZXh0ID0gaW5kZXggKyAxO1xuICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGJveCk7XG4gICAgICAgIH0pO1xuXG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIGNvbnN0IGNvbG9ycyA9IFsnI0YwMCcsICcjRkY4MDAwJywgJyNGRjAnLCAnIzBGMCcsICcjMDBGJywgJyNBMEYnLCAnI0YwQSddO1xuXG4gICAgY29uc3QgY3JlYXRlQm94ID0gKGNvbG9yLCB0eXBlKSA9PiB7XG4gICAgICAgIGNvbnN0IGJveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBib3guY2xhc3NMaXN0LmFkZCgnYm94Jyk7XG4gICAgICAgIGJveC5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBjb2xvcjtcbiAgICAgICAgaWYgKHR5cGUpIGJveC5kYXRhc2V0LnR5cGUgPSB0eXBlO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm94KTtcbiAgICB9O1xuXG4gICAgY29sb3JzLmZvckVhY2goKGNvbG9yKSA9PiB7XG4gICAgICAgIGNvbnN0IHNoYWRlcyA9IENvbG9yVHJhbnNsYXRvci5nZXRTaGFkZXMoY29sb3IsIDMpLnJldmVyc2UoKTtcbiAgICAgICAgY29uc3QgdGludHMgPSBDb2xvclRyYW5zbGF0b3IuZ2V0VGludHMoY29sb3IsIDMpO1xuICAgICAgICBzaGFkZXMuZm9yRWFjaCgoc2hhZGUpID0+IGNyZWF0ZUJveChzaGFkZSwgJ3NoYWRlJykpO1xuICAgICAgICBjcmVhdGVCb3goY29sb3IpO1xuICAgICAgICB0aW50cy5mb3JFYWNoKCh0aW50KSA9PiBjcmVhdGVCb3godGludCwgJ3RpbnQnKSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cblxuZXhwb3J0IGRlZmF1bHQgKENvbG9yVHJhbnNsYXRvcikgPT4ge1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICBjb25zdCBtaXhlcyA9IFtcbiAgICAgICAgJyNGMDAnLFxuICAgICAgICAnIzBGMCcsXG4gICAgICAgICcjMDBGJyxcbiAgICAgICAgWzEsIDNdLFxuICAgICAgICBbMSwgMl0sXG4gICAgICAgIFsyLCAzXSxcbiAgICAgICAgWzEsIDIsIDNdXG4gICAgXTtcblxuICAgIGNvbnN0IGZpbGxQbGFuZXMgPSAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHBsYW5lcyA9IGNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCcjcGxhbmVzIHBhdGgnKTtcbiAgICAgICAgcGxhbmVzLmZvckVhY2goKHBsYW5lLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgbGV0IGNvbG9yID0gJyNDQ0MnO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaXhlc1tpbmRleF0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgY29sb3IgPSBtaXhlc1tpbmRleF07XG4gICAgICAgICAgICB9IGVsc2UgaWYobWl4ZXNbaW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY29sb3JzID0gbWl4ZXNbaW5kZXhdLm1hcCgoaSkgPT4gbWl4ZXNbaSAtIDFdKTtcbiAgICAgICAgICAgICAgICBjb2xvciA9IG1peGVzW2luZGV4XSA9IENvbG9yVHJhbnNsYXRvci5nZXRNaXhIRVgoY29sb3JzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBsYW5lLnNldEF0dHJpYnV0ZSgnZmlsbCcsIGNvbG9yKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGZldGNoKCdpbWFnZXMvY29sb3ItbWl4ZXMuc3ZnJylcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHJlc3VsdC50ZXh0KCkpXG4gICAgICAgIC50aGVuKChzdmdDb2RlKSA9PiB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gc3ZnQ29kZTtcbiAgICAgICAgICAgIGZpbGxQbGFuZXMoKTtcbiAgICAgICAgfSk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IsIHsgTWl4IH0pID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgY29uc3QgbWl4ZXMgPSBbXG4gICAgICAgICcjRjAwJyxcbiAgICAgICAgJyNGRjAnLFxuICAgICAgICAnIzAwRicsXG4gICAgICAgIFsxLCAzXSxcbiAgICAgICAgWzEsIDJdLFxuICAgICAgICBbMiwgM10sXG4gICAgICAgIFsxLCAyLCAzXVxuICAgIF07XG5cbiAgICBjb25zdCBmaWxsUGxhbmVzID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBwbGFuZXMgPSBjb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnI3BsYW5lcyBwYXRoJyk7XG4gICAgICAgIHBsYW5lcy5mb3JFYWNoKChwbGFuZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGxldCBjb2xvciA9ICcjQ0NDJztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWl4ZXNbaW5kZXhdID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGNvbG9yID0gbWl4ZXNbaW5kZXhdO1xuICAgICAgICAgICAgfSBlbHNlIGlmKG1peGVzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9ycyA9IG1peGVzW2luZGV4XS5tYXAoKGkpID0+IG1peGVzW2kgLSAxXSk7XG4gICAgICAgICAgICAgICAgY29sb3IgPSBtaXhlc1tpbmRleF0gPSBDb2xvclRyYW5zbGF0b3IuZ2V0TWl4SEVYKGNvbG9ycywgTWl4LlNVQlRSQUNUSVZFKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBsYW5lLnNldEF0dHJpYnV0ZSgnZmlsbCcsIGNvbG9yKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGZldGNoKCdpbWFnZXMvY29sb3ItbWl4ZXMuc3ZnJylcbiAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHJlc3VsdC50ZXh0KCkpXG4gICAgICAgIC50aGVuKChzdmdDb2RlKSA9PiB7XG4gICAgICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gc3ZnQ29kZTtcbiAgICAgICAgICAgIGZpbGxQbGFuZXMoKTtcbiAgICAgICAgfSk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IsIHsgSGFybW9ueSB9KSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIGNvbnN0IGhhcm1vbmllcyA9IFtcbiAgICAgICAgeyBsYWJlbDogJ0NvbXBsZW1lbnRhcnknLCAgICAgICB2YWx1ZTogSGFybW9ueS5DT01QTEVNRU5UQVJZIH0sXG4gICAgICAgIHsgbGFiZWw6ICdTcGxpdCBDb21wbGVtZW50YXJ5JywgdmFsdWU6IEhhcm1vbnkuU1BMSVRfQ09NUExFTUVOVEFSWSB9LFxuICAgICAgICB7IGxhYmVsOiAnQW5hbG9nb3VzJywgICAgICAgICAgIHZhbHVlOiBIYXJtb255LkFOQUxPR09VUyB9LFxuICAgICAgICB7IGxhYmVsOiAnVHJpYWRpYycsICAgICAgICAgICAgIHZhbHVlOiBIYXJtb255LlRSSUFESUMgfSxcbiAgICAgICAgeyBsYWJlbDogJ1RldHJhZGljJywgICAgICAgICAgICB2YWx1ZTogSGFybW9ueS5URVRSQURJQyB9LFxuICAgICAgICB7IGxhYmVsOiAnU3F1YXJlJywgICAgICAgICAgICAgIHZhbHVlOiBIYXJtb255LlNRVUFSRSB9XG4gICAgXTtcblxuICAgIGNvbnN0IGJhc2VDb2xvciA9ICcjRjAwJztcblxuICAgIGNvbnN0IGNyZWF0ZUVsZW1lbnQgPSAoY2xhc3NOYW1lLCBwYXJlbnQpID0+IHtcbiAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGRpdi5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICByZXR1cm4gZGl2O1xuICAgIH07XG5cbiAgICBjb25zdCBjcmVhdGVIYXJtb255ID0gKGl0ZW0pID0+IHtcblxuICAgICAgICBjb25zdCB3cmFwcGVyID0gY3JlYXRlRWxlbWVudCgnd3JhcHBlcicsIGNvbnRhaW5lcik7XG4gICAgICAgIGNvbnN0IHdoZWVsID0gY3JlYXRlRWxlbWVudCgnd2hlZWwnLCB3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgaGFybW9ueSA9IGNyZWF0ZUVsZW1lbnQoJ2hhcm1vbnknLCB3cmFwcGVyKTtcbiAgICAgICAgY3JlYXRlRWxlbWVudCgnbGFiZWwnLCB3cmFwcGVyKS5pbm5lclRleHQgPSBpdGVtLmxhYmVsO1xuXG4gICAgICAgIGZldGNoKCdpbWFnZXMvd2hlZWwtYWRkaXRpdmUuc3ZnJylcbiAgICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiByZXN1bHQudGV4dCgpKVxuICAgICAgICAgICAgLnRoZW4oKHN2Z0NvZGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBoYXJtb255Q29sb3JzID0gQ29sb3JUcmFuc2xhdG9yLmdldEhhcm1vbnkoYmFzZUNvbG9yLCBpdGVtLnZhbHVlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3RvciA9ICdwYXRoJyArIGhhcm1vbnlDb2xvcnMubWFwKChjb2xvcikgPT4gYDpub3QoW2ZpbGw9XCIke2NvbG9yfVwiXSlgKS5qb2luKCcnKTtcbiAgICAgICAgICAgICAgICB3aGVlbC5pbm5lckhUTUwgPSBzdmdDb2RlO1xuICAgICAgICAgICAgICAgIGhhcm1vbnlDb2xvcnMuZm9yRWFjaCgoaGV4KSA9PiBjcmVhdGVFbGVtZW50KCdib3gnLCBoYXJtb255KS5zdHlsZS5iYWNrZ3JvdW5kID0gaGV4KTtcbiAgICAgICAgICAgICAgICB3aGVlbC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKS5mb3JFYWNoKChwYXRoKSA9PiBwYXRoLnNldEF0dHJpYnV0ZSgnZmlsbC1vcGFjaXR5JywgJzAuMjUnKSk7XG4gICAgICAgICAgICB9KTtcblxuICAgIH07XG5cbiAgICBoYXJtb25pZXMuZm9yRWFjaCgoaXRlbSkgPT4gY3JlYXRlSGFybW9ueShpdGVtKSk7XG5cbiAgICByZXR1cm4gY29udGFpbmVyO1xuXG59OyIsImltcG9ydCAnLi9zdHlsZXMuc2Nzcyc7XG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IsIHsgSGFybW9ueSwgTWl4IH0pID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgY29uc3QgaGFybW9uaWVzID0gW1xuICAgICAgICB7IGxhYmVsOiAnQ29tcGxlbWVudGFyeScsICAgICAgIHZhbHVlOiBIYXJtb255LkNPTVBMRU1FTlRBUlkgfSxcbiAgICAgICAgeyBsYWJlbDogJ1NwbGl0IENvbXBsZW1lbnRhcnknLCB2YWx1ZTogSGFybW9ueS5TUExJVF9DT01QTEVNRU5UQVJZIH0sXG4gICAgICAgIHsgbGFiZWw6ICdBbmFsb2dvdXMnLCAgICAgICAgICAgdmFsdWU6IEhhcm1vbnkuQU5BTE9HT1VTIH0sXG4gICAgICAgIHsgbGFiZWw6ICdUcmlhZGljJywgICAgICAgICAgICAgdmFsdWU6IEhhcm1vbnkuVFJJQURJQyB9LFxuICAgICAgICB7IGxhYmVsOiAnVGV0cmFkaWMnLCAgICAgICAgICAgIHZhbHVlOiBIYXJtb255LlRFVFJBRElDIH0sXG4gICAgICAgIHsgbGFiZWw6ICdTcXVhcmUnLCAgICAgICAgICAgICAgdmFsdWU6IEhhcm1vbnkuU1FVQVJFIH1cbiAgICBdO1xuXG4gICAgY29uc3QgYmFzZUNvbG9yID0gJyNGMDAnO1xuXG4gICAgY29uc3QgY3JlYXRlRWxlbWVudCA9IChjbGFzc05hbWUsIHBhcmVudCkgPT4ge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZGl2LmNsYXNzTGlzdC5hZGQoY2xhc3NOYW1lKTtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgIHJldHVybiBkaXY7XG4gICAgfTtcblxuICAgIGNvbnN0IGNyZWF0ZUhhcm1vbnkgPSAoaXRlbSkgPT4ge1xuXG4gICAgICAgIGNvbnN0IHdyYXBwZXIgPSBjcmVhdGVFbGVtZW50KCd3cmFwcGVyJywgY29udGFpbmVyKTtcbiAgICAgICAgY29uc3Qgd2hlZWwgPSBjcmVhdGVFbGVtZW50KCd3aGVlbCcsIHdyYXBwZXIpO1xuICAgICAgICBjb25zdCBoYXJtb255ID0gY3JlYXRlRWxlbWVudCgnaGFybW9ueScsIHdyYXBwZXIpO1xuICAgICAgICBjcmVhdGVFbGVtZW50KCdsYWJlbCcsIHdyYXBwZXIpLmlubmVyVGV4dCA9IGl0ZW0ubGFiZWw7XG5cbiAgICAgICAgZmV0Y2goJ2ltYWdlcy93aGVlbC1zdWJ0cmFjdGl2ZS5zdmcnKVxuICAgICAgICAgICAgLnRoZW4ocmVzdWx0ID0+IHJlc3VsdC50ZXh0KCkpXG4gICAgICAgICAgICAudGhlbigoc3ZnQ29kZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhcm1vbnlDb2xvcnMgPSBDb2xvclRyYW5zbGF0b3IuZ2V0SGFybW9ueShiYXNlQ29sb3IsIGl0ZW0udmFsdWUsIE1peC5TVUJUUkFDVElWRSk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSAncGF0aCcgKyBoYXJtb255Q29sb3JzLm1hcCgoY29sb3IpID0+IGA6bm90KFtmaWxsPVwiJHtjb2xvcn1cIl0pYCkuam9pbignJyk7XG4gICAgICAgICAgICAgICAgd2hlZWwuaW5uZXJIVE1MID0gc3ZnQ29kZTtcbiAgICAgICAgICAgICAgICBoYXJtb255Q29sb3JzLmZvckVhY2goKGhleCkgPT4gY3JlYXRlRWxlbWVudCgnYm94JywgaGFybW9ueSkuc3R5bGUuYmFja2dyb3VuZCA9IGhleCk7XG4gICAgICAgICAgICAgICAgd2hlZWwucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikuZm9yRWFjaCgocGF0aCkgPT4gcGF0aC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtb3BhY2l0eScsICcwLjI1JykpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICB9O1xuXG4gICAgaGFybW9uaWVzLmZvckVhY2goKGl0ZW0pID0+IGNyZWF0ZUhhcm1vbnkoaXRlbSkpO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4uLy4uL25vZGVfbW9kdWxlcy9nb29nbGUtY29kZS1wcmV0dGlmeS9iaW4vcnVuX3ByZXR0aWZ5Lm1pbic7XG5pbXBvcnQgJy4uLy4uL25vZGVfbW9kdWxlcy9nb29nbGUtY29kZS1wcmV0dGlmeS9iaW4vcHJldHRpZnkubWluLmNzcyc7XG5pbXBvcnQgJy4uLy4uL25vZGVfbW9kdWxlcy9nb29nbGUtY29kZS1wcmV0dGlmeS9zdHlsZXMvZGVzZXJ0LmNzcyc7XG5pbXBvcnQgJ3doYXR3Zy1mZXRjaCc7XG5pbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuaW1wb3J0IHsgQ29sb3JUcmFuc2xhdG9yLCBIYXJtb255LCBNaXggfSBmcm9tICcuLi8nO1xuaW1wb3J0IGRlbW8xIGZyb20gJy4vZGVtbzEnO1xuaW1wb3J0IGRlbW8yIGZyb20gJy4vZGVtbzInO1xuaW1wb3J0IGRlbW8zIGZyb20gJy4vZGVtbzMnO1xuaW1wb3J0IGRlbW80IGZyb20gJy4vZGVtbzQnO1xuaW1wb3J0IGRlbW81IGZyb20gJy4vZGVtbzUnO1xuaW1wb3J0IGRlbW82IGZyb20gJy4vZGVtbzYnO1xuaW1wb3J0IGRlbW83IGZyb20gJy4vZGVtbzcnO1xuaW1wb3J0IGRlbW84IGZyb20gJy4vZGVtbzgnO1xuaW1wb3J0IGRlbW85IGZyb20gJy4vZGVtbzknO1xuaW1wb3J0IGRlbW8xMCBmcm9tICcuL2RlbW8xMCc7XG5pbXBvcnQgZGVtbzExIGZyb20gJy4vZGVtbzExJztcblxuY29uc3QgZnVuY3Rpb1RvU3RyaW5nID0gKGZuKSA9PiB7XG4gICAgY29uc3QgYXJ0aWNsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2FydGljbGUnKTtcbiAgICBjb25zdCBwcmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdwcmUnKTtcbiAgICBhcnRpY2xlLmNsYXNzTGlzdC5hZGQoJ2Z1bmN0aW9uLWNvbnRhaW5lcicpO1xuICAgIHByZS5jbGFzc0xpc3QuYWRkKCdwcmV0dHlwcmludCcpO1xuICAgIGFydGljbGUuYXBwZW5kQ2hpbGQocHJlKTtcbiAgICBwcmUuaW5uZXJIVE1MID0gZm4udG9TdHJpbmcoKS5yZXBsYWNlKCcoQ29sb3JUcmFuc2xhdG9yKScsICcoKScpO1xuICAgIHJldHVybiBhcnRpY2xlO1xufTtcblxuY29uc3QgZGVtb3MgPSBuZXcgTWFwKFtcbiAgICBbJ2RlbW8xJywgZGVtbzFdLFxuICAgIFsnZGVtbzInLCBkZW1vMl0sXG4gICAgWydkZW1vMycsIGRlbW8zXSxcbiAgICBbJ2RlbW80JywgZGVtbzRdLFxuICAgIFsnZGVtbzUnLCBkZW1vNV0sXG4gICAgWydkZW1vNicsIGRlbW82XSxcbiAgICBbJ2RlbW83JywgZGVtbzddLFxuICAgIFsnZGVtbzgnLCBkZW1vOF0sXG4gICAgWydkZW1vOScsIGRlbW85XSxcbiAgICBbJ2RlbW8xMCcsIGRlbW8xMF0sXG4gICAgWydkZW1vMTEnLCBkZW1vMTFdXG5dKTtcblxuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHtcbiAgICBkZW1vcy5mb3JFYWNoKChtb2R1bGUsIGRpdikgPT4ge1xuICAgICAgICBjb25zdCBkZW1vID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoZGl2KTtcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnN0IHdyYXBwZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgICBjb250YWluZXIuY2xhc3NMaXN0LmFkZCgnZGVtby1jb250YWluZXInKTtcbiAgICAgICAgd3JhcHBlci5jbGFzc0xpc3QuYWRkKCdkZW1vLXdyYXBwZXInKTtcblxuICAgICAgICB3cmFwcGVyLmFwcGVuZENoaWxkKG1vZHVsZShDb2xvclRyYW5zbGF0b3IsIHsgSGFybW9ueSwgTWl4IH0pKTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKHdyYXBwZXIpO1xuICAgICAgICBkZW1vLmFwcGVuZENoaWxkKGNvbnRhaW5lcik7XG4gICAgICAgIGRlbW8uYXBwZW5kQ2hpbGQoZnVuY3Rpb1RvU3RyaW5nKG1vZHVsZSkpO1xuICAgIH0pO1xufSk7Il0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///967\n\n}")}},__webpack_module_cache__={};function __webpack_require__(I){var g=__webpack_module_cache__[I];if(void 0!==g)return g.exports;var C=__webpack_module_cache__[I]={exports:{}};return __webpack_modules__[I](C,C.exports,__webpack_require__),C.exports}__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(I){if("object"==typeof window)return window}}();var __webpack_exports__=__webpack_require__(967),__webpack_export_target__=window;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0})})(); \ No newline at end of file +(()=>{var __webpack_modules__={966(module,exports){eval('{var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!function(){var r=null;\n(function(){function X(e){function j(){try{J.doScroll("left")}catch(e){P(j,50);return}w("poll")}function w(j){if(!(j.type=="readystatechange"&&x.readyState!="complete")&&((j.type=="load"?n:x)[z](i+j.type,w,!1),!m&&(m=!0)))e.call(n,j.type||j)}var Y=x.addEventListener,m=!1,C=!0,t=Y?"addEventListener":"attachEvent",z=Y?"removeEventListener":"detachEvent",i=Y?"":"on";if(x.readyState=="complete")e.call(n,"lazy");else{if(x.createEventObject&&J.doScroll){try{C=!n.frameElement}catch(A){}C&&j()}x[t](i+"DOMContentLoaded",\nw,!1);x[t](i+"readystatechange",w,!1);n[t](i+"load",w,!1)}}function Q(){S&&X(function(){var e=K.length;$(e?function(){for(var j=0;j=0;){var M=A[m],T=M.src.match(/^[^#?]*\\/run_prettify\\.js(\\?[^#]*)?(?:#.*)?$/);if(T){z=T[1]||"";M.parentNode.removeChild(M);break}}var S=!0,D=\n[],N=[],K=[];z.replace(/[&?]([^&=]+)=([^&]+)/g,function(e,j,w){w=decodeURIComponent(w);j=decodeURIComponent(j);j=="autorun"?S=!/^[0fn]/i.test(w):j=="lang"?D.push(w):j=="skin"?N.push(w):j=="callback"&&K.push(w)});m=0;for(z=D.length;m122||(o<65||k>90||f.push([Math.max(65,k)|32,Math.min(o,90)|32]),o<97||k>122||f.push([Math.max(97,k)&-33,Math.min(o,122)&-33]))}}f.sort(function(f,a){return f[0]-\na[0]||a[1]-f[1]});b=[];g=[];for(a=0;ak[0]&&(k[1]+1>k[0]&&c.push("-"),c.push(h(k[1])));c.push("]");return c.join("")}function e(f){for(var a=f.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),c=a.length,d=[],g=0,k=0;g=2&&f==="["?a[g]=b(o):f!=="\\\\"&&(a[g]=o.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var j=0,F=!1,l=!1,I=0,c=a.length;I=5&&"lang-"===y.substring(0,5))&&!(u&&typeof u[1]==="string"))g=!1,y="src";g||(m[B]=y)}k=c;c+=B.length;if(g){g=u[1];var o=B.indexOf(g),H=o+g.length;u[2]&&(H=B.length-u[2].length,o=H-g.length);y=y.substring(5);n(l+k,B.substring(0,o),h,j);n(l+k+o,g,A(y,\ng),j);n(l+k+H,B.substring(H),h,j)}else j.push(l+k,y)}a.g=j}var b={},e;(function(){for(var h=a.concat(d),l=[],i={},c=0,p=h.length;c=0;)b[q.charAt(f)]=m;m=m[1];q=""+m;i.hasOwnProperty(q)||(l.push(m),i[q]=r)}l.push(/[\\S\\s]/);e=j(l)})();var i=d.length;return h}function t(a){var d=[],h=[];a.tripleQuotedStrings?d.push(["str",/^(?:\'\'\'(?:[^\'\\\\]|\\\\[\\S\\s]|\'\'?(?=[^\']))*(?:\'\'\'|$)|"""(?:[^"\\\\]|\\\\[\\S\\s]|""?(?=[^"]))*(?:"""|$)|\'(?:[^\'\\\\]|\\\\[\\S\\s])*(?:\'|$)|"(?:[^"\\\\]|\\\\[\\S\\s])*(?:"|$))/,\nr,"\'\\""]):a.multiLineStrings?d.push(["str",/^(?:\'(?:[^\'\\\\]|\\\\[\\S\\s])*(?:\'|$)|"(?:[^"\\\\]|\\\\[\\S\\s])*(?:"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,r,"\'\\"`"]):d.push(["str",/^(?:\'(?:[^\\n\\r\'\\\\]|\\\\.)*(?:\'|$)|"(?:[^\\n\\r"\\\\]|\\\\.)*(?:"|$))/,r,"\\"\'"]);a.verbatimStrings&&h.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,r]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,r,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,\nr,"#"]),h.push(["str",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h(?:h|pp|\\+\\+)?|[a-z]\\w*)>/,r])):d.push(["com",/^#[^\\n\\r]*/,r,"#"]));a.cStyleComments&&(h.push(["com",/^\\/\\/[^\\n\\r]*/,r]),h.push(["com",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,r]));if(b=a.regexLiterals){var e=(b=b>1?"":"\\n\\r")?".":"[\\\\S\\\\s]";h.push(["lang-regex",RegExp("^(?:^^\\\\.?|[+-]|[!=]=?=?|\\\\#|%=?|&&?=?|\\\\(|\\\\*=?|[+\\\\-]=|->|\\\\/=?|::?|<>?>?=?|,|;|\\\\?|@|\\\\[|~|{|\\\\^\\\\^?=?|\\\\|\\\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\\\s*("+\n("/(?=[^/*"+b+"])(?:[^/\\\\x5B\\\\x5C"+b+"]|\\\\x5C"+e+"|\\\\x5B(?:[^\\\\x5C\\\\x5D"+b+"]|\\\\x5C"+e+")*(?:\\\\x5D|$))+/")+")")])}(b=a.types)&&h.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&h.push(["kwd",RegExp("^(?:"+b.replace(/[\\s,]+/g,"|")+")\\\\b"),r]);d.push(["pln",/^\\s+/,r," \\r\\n\\t\\u00a0"]);b="^.[^\\\\s\\\\w.$@\'\\"`/\\\\\\\\]*";a.regexLiterals&&(b+="(?!s*/)");h.push(["lit",/^@[$_a-z][\\w$@]*/i,r],["typ",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,r],["pln",/^[$_a-z][\\w$@]*/i,r],["lit",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,\nr,"0123456789"],["pln",/^\\\\[\\S\\s]?/,r],["pun",RegExp(b),r]);return C(d,h)}function z(a,d,h){function b(a){var c=a.nodeType;if(c==1&&!j.test(a.className))if("br"===a.nodeName)e(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&h){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(l.createTextNode(d),a.nextSibling),e(a),c||a.parentNode.removeChild(a)}}\nfunction e(a){function b(a,c){var d=c?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),h=a.nextSibling;f.appendChild(d);for(var e=h;e;e=h)h=e.nextSibling,f.appendChild(e)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var j=/(?:^|\\s)nocode(?:\\s|$)/,m=/\\r\\n?|\\n/,l=a.ownerDocument,i=l.createElement("li");a.firstChild;)i.appendChild(a.firstChild);for(var c=[i],p=0;p=0;){var b=d[h];U.hasOwnProperty(b)?V.console&&console.warn("cannot override language handler %s",b):U[b]=a}}function A(a,d){if(!a||!U.hasOwnProperty(a))a=/^\\s*=o&&(b+=2);h>=H&&(t+=2)}}finally{if(g)g.style.display=k}}catch(v){V.console&&console.log(v&&v.stack||v)}}var V=window,G=["break,continue,do,else,for,if,return,while"],O=[[G,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],\n"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],J=[O,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],K=[O,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],\nL=[K,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],O=[O,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],M=[G,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],\nN=[G,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],R=[G,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],G=[G,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],Q=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)\\b/,\nS=/\\S/,T=t({keywords:[J,L,O,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",M,N,G],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),U={};i(T,["default-code"]);i(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],["lang-",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],["lang-",/^<%([\\S\\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",\n/^]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],["lang-js",/^]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],["lang-css",/^]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],["lang-in.tag",/^(<\\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);i(C([["pln",/^\\s+/,r," \\t\\r\\n"],["atv",/^(?:"[^"]*"?|\'[^\']*\'?)/,r,"\\"\'"]],[["tag",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],["atn",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],["lang-uq.val",/^=\\s*([^\\s"\'>]*(?:[^\\s"\'/>]|\\/(?=\\s)))/],["pun",/^[/<->]+/],\n["lang-js",/^on\\w+\\s*=\\s*"([^"]+)"/i],["lang-js",/^on\\w+\\s*=\\s*\'([^\']+)\'/i],["lang-js",/^on\\w+\\s*=\\s*([^\\s"\'>]+)/i],["lang-css",/^style\\s*=\\s*"([^"]+)"/i],["lang-css",/^style\\s*=\\s*\'([^\']+)\'/i],["lang-css",/^style\\s*=\\s*([^\\s"\'>]+)/i]]),["in.tag"]);i(C([],[["atv",/^[\\S\\s]+/]]),["uq.val"]);i(t({keywords:J,hashComments:!0,cStyleComments:!0,types:Q}),["c","cc","cpp","cxx","cyc","m"]);i(t({keywords:"null,true,false"}),["json"]);i(t({keywords:L,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:Q}),\n["cs"]);i(t({keywords:K,cStyleComments:!0}),["java"]);i(t({keywords:G,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);i(t({keywords:M,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);i(t({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);i(t({keywords:N,\nhashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);i(t({keywords:O,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);i(t({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);i(t({keywords:R,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);\ni(C([],[["str",/^[\\S\\s]+/]]),["regex"]);var X=V.PR={createSimpleLexer:C,registerLangHandler:i,sourceDecorator:t,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:function(a,d,e){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;e&&z(b,e,!0);D({h:d,j:e,c:b,i:1});return b.innerHTML},\nprettyPrint:e=e=function(a,d){function e(){for(var b=V.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;p -1\n }\n}\n\nfunction normalizeName(name) {\n if (typeof name !== 'string') {\n name = String(name)\n }\n if (/[^a-z0-9\\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {\n throw new TypeError('Invalid character in header field name: \"' + name + '\"')\n }\n return name.toLowerCase()\n}\n\nfunction normalizeValue(value) {\n if (typeof value !== 'string') {\n value = String(value)\n }\n return value\n}\n\n// Build a destructive iterator for the value list\nfunction iteratorFor(items) {\n var iterator = {\n next: function() {\n var value = items.shift()\n return {done: value === undefined, value: value}\n }\n }\n\n if (support.iterable) {\n iterator[Symbol.iterator] = function() {\n return iterator\n }\n }\n\n return iterator\n}\n\nfunction Headers(headers) {\n this.map = {}\n\n if (headers instanceof Headers) {\n headers.forEach(function(value, name) {\n this.append(name, value)\n }, this)\n } else if (Array.isArray(headers)) {\n headers.forEach(function(header) {\n if (header.length != 2) {\n throw new TypeError('Headers constructor: expected name/value pair to be length 2, found' + header.length)\n }\n this.append(header[0], header[1])\n }, this)\n } else if (headers) {\n Object.getOwnPropertyNames(headers).forEach(function(name) {\n this.append(name, headers[name])\n }, this)\n }\n}\n\nHeaders.prototype.append = function(name, value) {\n name = normalizeName(name)\n value = normalizeValue(value)\n var oldValue = this.map[name]\n this.map[name] = oldValue ? oldValue + ', ' + value : value\n}\n\nHeaders.prototype['delete'] = function(name) {\n delete this.map[normalizeName(name)]\n}\n\nHeaders.prototype.get = function(name) {\n name = normalizeName(name)\n return this.has(name) ? this.map[name] : null\n}\n\nHeaders.prototype.has = function(name) {\n return this.map.hasOwnProperty(normalizeName(name))\n}\n\nHeaders.prototype.set = function(name, value) {\n this.map[normalizeName(name)] = normalizeValue(value)\n}\n\nHeaders.prototype.forEach = function(callback, thisArg) {\n for (var name in this.map) {\n if (this.map.hasOwnProperty(name)) {\n callback.call(thisArg, this.map[name], name, this)\n }\n }\n}\n\nHeaders.prototype.keys = function() {\n var items = []\n this.forEach(function(value, name) {\n items.push(name)\n })\n return iteratorFor(items)\n}\n\nHeaders.prototype.values = function() {\n var items = []\n this.forEach(function(value) {\n items.push(value)\n })\n return iteratorFor(items)\n}\n\nHeaders.prototype.entries = function() {\n var items = []\n this.forEach(function(value, name) {\n items.push([name, value])\n })\n return iteratorFor(items)\n}\n\nif (support.iterable) {\n Headers.prototype[Symbol.iterator] = Headers.prototype.entries\n}\n\nfunction consumed(body) {\n if (body._noBody) return\n if (body.bodyUsed) {\n return Promise.reject(new TypeError('Already read'))\n }\n body.bodyUsed = true\n}\n\nfunction fileReaderReady(reader) {\n return new Promise(function(resolve, reject) {\n reader.onload = function() {\n resolve(reader.result)\n }\n reader.onerror = function() {\n reject(reader.error)\n }\n })\n}\n\nfunction readBlobAsArrayBuffer(blob) {\n var reader = new FileReader()\n var promise = fileReaderReady(reader)\n reader.readAsArrayBuffer(blob)\n return promise\n}\n\nfunction readBlobAsText(blob) {\n var reader = new FileReader()\n var promise = fileReaderReady(reader)\n var match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type)\n var encoding = match ? match[1] : 'utf-8'\n reader.readAsText(blob, encoding)\n return promise\n}\n\nfunction readArrayBufferAsText(buf) {\n var view = new Uint8Array(buf)\n var chars = new Array(view.length)\n\n for (var i = 0; i < view.length; i++) {\n chars[i] = String.fromCharCode(view[i])\n }\n return chars.join('')\n}\n\nfunction bufferClone(buf) {\n if (buf.slice) {\n return buf.slice(0)\n } else {\n var view = new Uint8Array(buf.byteLength)\n view.set(new Uint8Array(buf))\n return view.buffer\n }\n}\n\nfunction Body() {\n this.bodyUsed = false\n\n this._initBody = function(body) {\n /*\n fetch-mock wraps the Response object in an ES6 Proxy to\n provide useful test harness features such as flush. However, on\n ES5 browsers without fetch or Proxy support pollyfills must be used;\n the proxy-pollyfill is unable to proxy an attribute unless it exists\n on the object before the Proxy is created. This change ensures\n Response.bodyUsed exists on the instance, while maintaining the\n semantic of setting Request.bodyUsed in the constructor before\n _initBody is called.\n */\n // eslint-disable-next-line no-self-assign\n this.bodyUsed = this.bodyUsed\n this._bodyInit = body\n if (!body) {\n this._noBody = true;\n this._bodyText = ''\n } else if (typeof body === 'string') {\n this._bodyText = body\n } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {\n this._bodyBlob = body\n } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {\n this._bodyFormData = body\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n this._bodyText = body.toString()\n } else if (support.arrayBuffer && support.blob && isDataView(body)) {\n this._bodyArrayBuffer = bufferClone(body.buffer)\n // IE 10-11 can't handle a DataView body.\n this._bodyInit = new Blob([this._bodyArrayBuffer])\n } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {\n this._bodyArrayBuffer = bufferClone(body)\n } else {\n this._bodyText = body = Object.prototype.toString.call(body)\n }\n\n if (!this.headers.get('content-type')) {\n if (typeof body === 'string') {\n this.headers.set('content-type', 'text/plain;charset=UTF-8')\n } else if (this._bodyBlob && this._bodyBlob.type) {\n this.headers.set('content-type', this._bodyBlob.type)\n } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {\n this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')\n }\n }\n }\n\n if (support.blob) {\n this.blob = function() {\n var rejected = consumed(this)\n if (rejected) {\n return rejected\n }\n\n if (this._bodyBlob) {\n return Promise.resolve(this._bodyBlob)\n } else if (this._bodyArrayBuffer) {\n return Promise.resolve(new Blob([this._bodyArrayBuffer]))\n } else if (this._bodyFormData) {\n throw new Error('could not read FormData body as blob')\n } else {\n return Promise.resolve(new Blob([this._bodyText]))\n }\n }\n }\n\n this.arrayBuffer = function() {\n if (this._bodyArrayBuffer) {\n var isConsumed = consumed(this)\n if (isConsumed) {\n return isConsumed\n } else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {\n return Promise.resolve(\n this._bodyArrayBuffer.buffer.slice(\n this._bodyArrayBuffer.byteOffset,\n this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength\n )\n )\n } else {\n return Promise.resolve(this._bodyArrayBuffer)\n }\n } else if (support.blob) {\n return this.blob().then(readBlobAsArrayBuffer)\n } else {\n throw new Error('could not read as ArrayBuffer')\n }\n }\n\n this.text = function() {\n var rejected = consumed(this)\n if (rejected) {\n return rejected\n }\n\n if (this._bodyBlob) {\n return readBlobAsText(this._bodyBlob)\n } else if (this._bodyArrayBuffer) {\n return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))\n } else if (this._bodyFormData) {\n throw new Error('could not read FormData body as text')\n } else {\n return Promise.resolve(this._bodyText)\n }\n }\n\n if (support.formData) {\n this.formData = function() {\n return this.text().then(decode)\n }\n }\n\n this.json = function() {\n return this.text().then(JSON.parse)\n }\n\n return this\n}\n\n// HTTP methods whose capitalization should be normalized\nvar methods = ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE']\n\nfunction normalizeMethod(method) {\n var upcased = method.toUpperCase()\n return methods.indexOf(upcased) > -1 ? upcased : method\n}\n\nfunction Request(input, options) {\n if (!(this instanceof Request)) {\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n }\n\n options = options || {}\n var body = options.body\n\n if (input instanceof Request) {\n if (input.bodyUsed) {\n throw new TypeError('Already read')\n }\n this.url = input.url\n this.credentials = input.credentials\n if (!options.headers) {\n this.headers = new Headers(input.headers)\n }\n this.method = input.method\n this.mode = input.mode\n this.signal = input.signal\n if (!body && input._bodyInit != null) {\n body = input._bodyInit\n input.bodyUsed = true\n }\n } else {\n this.url = String(input)\n }\n\n this.credentials = options.credentials || this.credentials || 'same-origin'\n if (options.headers || !this.headers) {\n this.headers = new Headers(options.headers)\n }\n this.method = normalizeMethod(options.method || this.method || 'GET')\n this.mode = options.mode || this.mode || null\n this.signal = options.signal || this.signal || (function () {\n if ('AbortController' in g) {\n var ctrl = new AbortController();\n return ctrl.signal;\n }\n }());\n this.referrer = null\n\n if ((this.method === 'GET' || this.method === 'HEAD') && body) {\n throw new TypeError('Body not allowed for GET or HEAD requests')\n }\n this._initBody(body)\n\n if (this.method === 'GET' || this.method === 'HEAD') {\n if (options.cache === 'no-store' || options.cache === 'no-cache') {\n // Search for a '_' parameter in the query string\n var reParamSearch = /([?&])_=[^&]*/\n if (reParamSearch.test(this.url)) {\n // If it already exists then set the value with the current time\n this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime())\n } else {\n // Otherwise add a new '_' parameter to the end with the current time\n var reQueryString = /\\?/\n this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime()\n }\n }\n }\n}\n\nRequest.prototype.clone = function() {\n return new Request(this, {body: this._bodyInit})\n}\n\nfunction decode(body) {\n var form = new FormData()\n body\n .trim()\n .split('&')\n .forEach(function(bytes) {\n if (bytes) {\n var split = bytes.split('=')\n var name = split.shift().replace(/\\+/g, ' ')\n var value = split.join('=').replace(/\\+/g, ' ')\n form.append(decodeURIComponent(name), decodeURIComponent(value))\n }\n })\n return form\n}\n\nfunction parseHeaders(rawHeaders) {\n var headers = new Headers()\n // Replace instances of \\r\\n and \\n followed by at least one space or horizontal tab with a space\n // https://tools.ietf.org/html/rfc7230#section-3.2\n var preProcessedHeaders = rawHeaders.replace(/\\r?\\n[\\t ]+/g, ' ')\n // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill\n // https://github.com/github/fetch/issues/748\n // https://github.com/zloirock/core-js/issues/751\n preProcessedHeaders\n .split('\\r')\n .map(function(header) {\n return header.indexOf('\\n') === 0 ? header.substr(1, header.length) : header\n })\n .forEach(function(line) {\n var parts = line.split(':')\n var key = parts.shift().trim()\n if (key) {\n var value = parts.join(':').trim()\n try {\n headers.append(key, value)\n } catch (error) {\n console.warn('Response ' + error.message)\n }\n }\n })\n return headers\n}\n\nBody.call(Request.prototype)\n\nfunction Response(bodyInit, options) {\n if (!(this instanceof Response)) {\n throw new TypeError('Please use the \"new\" operator, this DOM object constructor cannot be called as a function.')\n }\n if (!options) {\n options = {}\n }\n\n this.type = 'default'\n this.status = options.status === undefined ? 200 : options.status\n if (this.status < 200 || this.status > 599) {\n throw new RangeError(\"Failed to construct 'Response': The status provided (0) is outside the range [200, 599].\")\n }\n this.ok = this.status >= 200 && this.status < 300\n this.statusText = options.statusText === undefined ? '' : '' + options.statusText\n this.headers = new Headers(options.headers)\n this.url = options.url || ''\n this._initBody(bodyInit)\n}\n\nBody.call(Response.prototype)\n\nResponse.prototype.clone = function() {\n return new Response(this._bodyInit, {\n status: this.status,\n statusText: this.statusText,\n headers: new Headers(this.headers),\n url: this.url\n })\n}\n\nResponse.error = function() {\n var response = new Response(null, {status: 200, statusText: ''})\n response.ok = false\n response.status = 0\n response.type = 'error'\n return response\n}\n\nvar redirectStatuses = [301, 302, 303, 307, 308]\n\nResponse.redirect = function(url, status) {\n if (redirectStatuses.indexOf(status) === -1) {\n throw new RangeError('Invalid status code')\n }\n\n return new Response(null, {status: status, headers: {location: url}})\n}\n\nvar DOMException = g.DOMException\ntry {\n new DOMException()\n} catch (err) {\n DOMException = function(message, name) {\n this.message = message\n this.name = name\n var error = Error(message)\n this.stack = error.stack\n }\n DOMException.prototype = Object.create(Error.prototype)\n DOMException.prototype.constructor = DOMException\n}\n\nfunction fetch_fetch(input, init) {\n return new Promise(function(resolve, reject) {\n var request = new Request(input, init)\n\n if (request.signal && request.signal.aborted) {\n return reject(new DOMException('Aborted', 'AbortError'))\n }\n\n var xhr = new XMLHttpRequest()\n\n function abortXhr() {\n xhr.abort()\n }\n\n xhr.onload = function() {\n var options = {\n statusText: xhr.statusText,\n headers: parseHeaders(xhr.getAllResponseHeaders() || '')\n }\n // This check if specifically for when a user fetches a file locally from the file system\n // Only if the status is out of a normal range\n if (request.url.indexOf('file://') === 0 && (xhr.status < 200 || xhr.status > 599)) {\n options.status = 200;\n } else {\n options.status = xhr.status;\n }\n options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')\n var body = 'response' in xhr ? xhr.response : xhr.responseText\n setTimeout(function() {\n resolve(new Response(body, options))\n }, 0)\n }\n\n xhr.onerror = function() {\n setTimeout(function() {\n reject(new TypeError('Network request failed'))\n }, 0)\n }\n\n xhr.ontimeout = function() {\n setTimeout(function() {\n reject(new TypeError('Network request timed out'))\n }, 0)\n }\n\n xhr.onabort = function() {\n setTimeout(function() {\n reject(new DOMException('Aborted', 'AbortError'))\n }, 0)\n }\n\n function fixUrl(url) {\n try {\n return url === '' && g.location.href ? g.location.href : url\n } catch (e) {\n return url\n }\n }\n\n xhr.open(request.method, fixUrl(request.url), true)\n\n if (request.credentials === 'include') {\n xhr.withCredentials = true\n } else if (request.credentials === 'omit') {\n xhr.withCredentials = false\n }\n\n if ('responseType' in xhr) {\n if (support.blob) {\n xhr.responseType = 'blob'\n } else if (\n support.arrayBuffer\n ) {\n xhr.responseType = 'arraybuffer'\n }\n }\n\n if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers || (g.Headers && init.headers instanceof g.Headers))) {\n var names = [];\n Object.getOwnPropertyNames(init.headers).forEach(function(name) {\n names.push(normalizeName(name))\n xhr.setRequestHeader(name, normalizeValue(init.headers[name]))\n })\n request.headers.forEach(function(value, name) {\n if (names.indexOf(name) === -1) {\n xhr.setRequestHeader(name, value)\n }\n })\n } else {\n request.headers.forEach(function(value, name) {\n xhr.setRequestHeader(name, value)\n })\n }\n\n if (request.signal) {\n request.signal.addEventListener('abort', abortXhr)\n\n xhr.onreadystatechange = function() {\n // DONE (success or failure)\n if (xhr.readyState === 4) {\n request.signal.removeEventListener('abort', abortXhr)\n }\n }\n }\n\n xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)\n })\n}\n\nfetch_fetch.polyfill = true\n\nif (!g.fetch) {\n g.fetch = fetch_fetch\n g.Headers = Headers\n g.Request = Request\n g.Response = Response\n}\n\n;// ./src/@types/index.ts\nvar AnglesUnitEnum;\n(function (AnglesUnitEnum) {\n AnglesUnitEnum[\"NONE\"] = \"none\";\n AnglesUnitEnum[\"DEGREES\"] = \"deg\";\n AnglesUnitEnum[\"GRADIANS\"] = \"grad\";\n AnglesUnitEnum[\"RADIANS\"] = \"rad\";\n AnglesUnitEnum[\"TURNS\"] = \"turn\";\n})(AnglesUnitEnum || (AnglesUnitEnum = {}));\nvar ColorUnitEnum;\n(function (ColorUnitEnum) {\n ColorUnitEnum[\"NONE\"] = \"none\";\n ColorUnitEnum[\"PERCENT\"] = \"percent\";\n})(ColorUnitEnum || (ColorUnitEnum = {}));\nvar CMYKFunctionEnum;\n(function (CMYKFunctionEnum) {\n CMYKFunctionEnum[\"DEVICE_CMYK\"] = \"device-cmyk\";\n CMYKFunctionEnum[\"CMYK\"] = \"cmyk\";\n})(CMYKFunctionEnum || (CMYKFunctionEnum = {}));\n\n;// ./src/constants/enums.ts\nvar ColorModel;\n(function (ColorModel) {\n ColorModel[\"HEX\"] = \"HEX\";\n ColorModel[\"RGB\"] = \"RGB\";\n ColorModel[\"HWB\"] = \"HWB\";\n ColorModel[\"HSL\"] = \"HSL\";\n ColorModel[\"CIELab\"] = \"CIELab\";\n ColorModel[\"LCH\"] = \"LCH\";\n ColorModel[\"CMYK\"] = \"CMYK\";\n})(ColorModel || (ColorModel = {}));\nvar Harmony;\n(function (Harmony) {\n Harmony[\"ANALOGOUS\"] = \"ANALOGOUS\";\n Harmony[\"COMPLEMENTARY\"] = \"COMPLEMENTARY\";\n Harmony[\"SPLIT_COMPLEMENTARY\"] = \"SPLIT_COMPLEMENTARY\";\n Harmony[\"TRIADIC\"] = \"TRIADIC\";\n Harmony[\"TETRADIC\"] = \"TETRADIC\";\n Harmony[\"SQUARE\"] = \"SQUARE\";\n})(Harmony || (Harmony = {}));\nvar Mix;\n(function (Mix) {\n Mix[\"ADDITIVE\"] = \"ADDITIVE\";\n Mix[\"SUBTRACTIVE\"] = \"SUBTRACTIVE\";\n})(Mix || (Mix = {}));\nvar ColorKeywords;\n(function (ColorKeywords) {\n ColorKeywords[\"black\"] = \"#000000\";\n ColorKeywords[\"silver\"] = \"#C0C0C0\";\n ColorKeywords[\"gray\"] = \"#808080\";\n ColorKeywords[\"white\"] = \"#FFFFFF\";\n ColorKeywords[\"maroon\"] = \"#800000\";\n ColorKeywords[\"red\"] = \"#FF0000\";\n ColorKeywords[\"purple\"] = \"#800080\";\n ColorKeywords[\"fuchsia\"] = \"#FF00FF\";\n ColorKeywords[\"green\"] = \"#008000\";\n ColorKeywords[\"lime\"] = \"#00FF00\";\n ColorKeywords[\"olive\"] = \"#808000\";\n ColorKeywords[\"yellow\"] = \"#FFFF00\";\n ColorKeywords[\"navy\"] = \"#000080\";\n ColorKeywords[\"blue\"] = \"#0000FF\";\n ColorKeywords[\"teal\"] = \"#008080\";\n ColorKeywords[\"aqua\"] = \"#00FFFF\";\n ColorKeywords[\"orange\"] = \"#FFA500\";\n ColorKeywords[\"aliceblue\"] = \"#F0F8FF\";\n ColorKeywords[\"antiquewhite\"] = \"#FAEBD7\";\n ColorKeywords[\"aquamarine\"] = \"#7FFFD4\";\n ColorKeywords[\"azure\"] = \"#F0FFFF\";\n ColorKeywords[\"beige\"] = \"#F5F5DC\";\n ColorKeywords[\"bisque\"] = \"#FFE4C4\";\n ColorKeywords[\"blanchedalmond\"] = \"#FFEBCD\";\n ColorKeywords[\"blueviolet\"] = \"#8A2BE2\";\n ColorKeywords[\"brown\"] = \"#A52A2A\";\n ColorKeywords[\"burlywood\"] = \"#DEB887\";\n ColorKeywords[\"cadetblue\"] = \"#5F9EA0\";\n ColorKeywords[\"chartreuse\"] = \"#7FFF00\";\n ColorKeywords[\"chocolate\"] = \"#D2691E\";\n ColorKeywords[\"coral\"] = \"#FF7F50\";\n ColorKeywords[\"cornflowerblue\"] = \"#6495ED\";\n ColorKeywords[\"cornsilk\"] = \"#FFF8DC\";\n ColorKeywords[\"crimson\"] = \"#DC143C\";\n ColorKeywords[\"cyan\"] = \"#00FFFF\";\n ColorKeywords[\"darkblue\"] = \"#00008B\";\n ColorKeywords[\"darkcyan\"] = \"#008B8B\";\n ColorKeywords[\"darkgoldenrod\"] = \"#B8860B\";\n ColorKeywords[\"darkgray\"] = \"#A9A9A9\";\n ColorKeywords[\"darkgreen\"] = \"#006400\";\n ColorKeywords[\"darkgrey\"] = \"#A9A9A9\";\n ColorKeywords[\"darkkhaki\"] = \"#BDB76B\";\n ColorKeywords[\"darkmagenta\"] = \"#8B008B\";\n ColorKeywords[\"darkolivegreen\"] = \"#556B2F\";\n ColorKeywords[\"darkorange\"] = \"#FF8C00\";\n ColorKeywords[\"darkorchid\"] = \"#9932CC\";\n ColorKeywords[\"darkred\"] = \"#8B0000\";\n ColorKeywords[\"darksalmon\"] = \"#E9967A\";\n ColorKeywords[\"darkseagreen\"] = \"#8FBC8F\";\n ColorKeywords[\"darkslateblue\"] = \"#483D8B\";\n ColorKeywords[\"darkslategray\"] = \"#2F4F4F\";\n ColorKeywords[\"darkslategrey\"] = \"#2F4F4F\";\n ColorKeywords[\"darkturquoise\"] = \"#00CED1\";\n ColorKeywords[\"darkviolet\"] = \"#9400D3\";\n ColorKeywords[\"deeppink\"] = \"#FF1493\";\n ColorKeywords[\"deepskyblue\"] = \"#00BFFF\";\n ColorKeywords[\"dimgray\"] = \"#696969\";\n ColorKeywords[\"dimgrey\"] = \"#696969\";\n ColorKeywords[\"dodgerblue\"] = \"#1E90FF\";\n ColorKeywords[\"firebrick\"] = \"#B22222\";\n ColorKeywords[\"floralwhite\"] = \"#FFFAF0\";\n ColorKeywords[\"forestgreen\"] = \"#228B22\";\n ColorKeywords[\"gainsboro\"] = \"#DCDCDC\";\n ColorKeywords[\"ghostwhite\"] = \"#F8F8FF\";\n ColorKeywords[\"gold\"] = \"#FFD700\";\n ColorKeywords[\"goldenrod\"] = \"#DAA520\";\n ColorKeywords[\"greenyellow\"] = \"#ADFF2F\";\n ColorKeywords[\"grey\"] = \"#808080\";\n ColorKeywords[\"honeydew\"] = \"#F0FFF0\";\n ColorKeywords[\"hotpink\"] = \"#FF69B4\";\n ColorKeywords[\"indianred\"] = \"#CD5C5C\";\n ColorKeywords[\"indigo\"] = \"#4B0082\";\n ColorKeywords[\"ivory\"] = \"#FFFFF0\";\n ColorKeywords[\"khaki\"] = \"#F0E68C\";\n ColorKeywords[\"lavender\"] = \"#E6E6FA\";\n ColorKeywords[\"lavenderblush\"] = \"#FFF0F5\";\n ColorKeywords[\"lawngreen\"] = \"#7CFC00\";\n ColorKeywords[\"lemonchiffon\"] = \"#FFFACD\";\n ColorKeywords[\"lightblue\"] = \"#ADD8E6\";\n ColorKeywords[\"lightcoral\"] = \"#F08080\";\n ColorKeywords[\"lightcyan\"] = \"#E0FFFF\";\n ColorKeywords[\"lightgoldenrodyellow\"] = \"#FAFAD2\";\n ColorKeywords[\"lightgray\"] = \"#D3D3D3\";\n ColorKeywords[\"lightgreen\"] = \"#90EE90\";\n ColorKeywords[\"lightgrey\"] = \"#D3D3D3\";\n ColorKeywords[\"lightpink\"] = \"#FFB6C1\";\n ColorKeywords[\"lightsalmon\"] = \"#FFA07A\";\n ColorKeywords[\"lightseagreen\"] = \"#20B2AA\";\n ColorKeywords[\"lightskyblue\"] = \"#87CEFA\";\n ColorKeywords[\"lightslategray\"] = \"#778899\";\n ColorKeywords[\"lightslategrey\"] = \"#778899\";\n ColorKeywords[\"lightsteelblue\"] = \"#B0C4DE\";\n ColorKeywords[\"lightyellow\"] = \"#FFFFE0\";\n ColorKeywords[\"limegreen\"] = \"#32CD32\";\n ColorKeywords[\"linen\"] = \"#FAF0E6\";\n ColorKeywords[\"magenta\"] = \"#FF00FF\";\n ColorKeywords[\"mediumaquamarine\"] = \"#66CDAA\";\n ColorKeywords[\"mediumblue\"] = \"#0000CD\";\n ColorKeywords[\"mediumorchid\"] = \"#BA55D3\";\n ColorKeywords[\"mediumpurple\"] = \"#9370DB\";\n ColorKeywords[\"mediumseagreen\"] = \"#3CB371\";\n ColorKeywords[\"mediumslateblue\"] = \"#7B68EE\";\n ColorKeywords[\"mediumspringgreen\"] = \"#00FA9A\";\n ColorKeywords[\"mediumturquoise\"] = \"#48D1CC\";\n ColorKeywords[\"mediumvioletred\"] = \"#C71585\";\n ColorKeywords[\"midnightblue\"] = \"#191970\";\n ColorKeywords[\"mintcream\"] = \"#F5FFFA\";\n ColorKeywords[\"mistyrose\"] = \"#FFE4E1\";\n ColorKeywords[\"moccasin\"] = \"#FFE4B5\";\n ColorKeywords[\"navajowhite\"] = \"#FFDEAD\";\n ColorKeywords[\"oldlace\"] = \"#FDF5E6\";\n ColorKeywords[\"olivedrab\"] = \"#6B8E23\";\n ColorKeywords[\"orangered\"] = \"#FF4500\";\n ColorKeywords[\"orchid\"] = \"#DA70D6\";\n ColorKeywords[\"palegoldenrod\"] = \"#EEE8AA\";\n ColorKeywords[\"palegreen\"] = \"#98FB98\";\n ColorKeywords[\"paleturquoise\"] = \"#AFEEEE\";\n ColorKeywords[\"palevioletred\"] = \"#DB7093\";\n ColorKeywords[\"papayawhip\"] = \"#FFEFD5\";\n ColorKeywords[\"peachpuff\"] = \"#FFDAB9\";\n ColorKeywords[\"peru\"] = \"#CD853F\";\n ColorKeywords[\"pink\"] = \"#FFC0CB\";\n ColorKeywords[\"plum\"] = \"#DDA0DD\";\n ColorKeywords[\"powderblue\"] = \"#B0E0E6\";\n ColorKeywords[\"rosybrown\"] = \"#BC8F8F\";\n ColorKeywords[\"royalblue\"] = \"#4169E1\";\n ColorKeywords[\"saddlebrown\"] = \"#8B4513\";\n ColorKeywords[\"salmon\"] = \"#FA8072\";\n ColorKeywords[\"sandybrown\"] = \"#F4A460\";\n ColorKeywords[\"seagreen\"] = \"#2E8B57\";\n ColorKeywords[\"seashell\"] = \"#FFF5EE\";\n ColorKeywords[\"sienna\"] = \"#A0522D\";\n ColorKeywords[\"skyblue\"] = \"#87CEEB\";\n ColorKeywords[\"slateblue\"] = \"#6A5ACD\";\n ColorKeywords[\"slategray\"] = \"#708090\";\n ColorKeywords[\"slategrey\"] = \"#708090\";\n ColorKeywords[\"snow\"] = \"#FFFAFA\";\n ColorKeywords[\"springgreen\"] = \"#00FF7F\";\n ColorKeywords[\"steelblue\"] = \"#4682B4\";\n ColorKeywords[\"tan\"] = \"#D2B48C\";\n ColorKeywords[\"thistle\"] = \"#D8BFD8\";\n ColorKeywords[\"tomato\"] = \"#FF6347\";\n ColorKeywords[\"turquoise\"] = \"#40E0D0\";\n ColorKeywords[\"violet\"] = \"#EE82EE\";\n ColorKeywords[\"wheat\"] = \"#F5DEB3\";\n ColorKeywords[\"whitesmoke\"] = \"#F5F5F5\";\n ColorKeywords[\"yellowgreen\"] = \"#9ACD32\";\n ColorKeywords[\"rebeccapurple\"] = \"#663399\";\n})(ColorKeywords || (ColorKeywords = {}));\n\n;// ./src/constants/regexps.ts\n\nconst COLORREGS = {\n [ColorModel.HEX]: /^#(?:(?[a-f\\d])(?[a-f\\d])(?[a-f\\d])(?
[a-f\\d])?|(?[a-f\\d]{2})(?[a-f\\d]{2})(?[a-f\\d]{2})(?[a-f\\d]{2})?)$/i,\n [ColorModel.RGB]: /^rgba?\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[rgb]|(?:\\d*\\.)?\\d+|calc\\([rgb()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.HWB]: /^hwb\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s+(?(?:\\d*\\.)?\\d+)%\\s+(?(?:\\d*\\.)?\\d+)%(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))%?\\s+(?(?:[hwb]|(?:\\d*\\.)?\\d+|calc\\([hwb()/*\\-+\\d.\\s]+\\)))%?(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.HSL]: /^hsla?\\s*\\(\\s*(?:(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s*,\\s*(?(?:\\d*\\.)?\\d+)%\\s*,\\s*(?(?:\\d*\\.)?\\d+)%(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)\\s+(?(?:\\d*\\.)?\\d+)%?\\s+(?(?:\\d*\\.)?\\d+)%?(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))%?\\s+(?(?:[hsl]|(?:\\d*\\.)?\\d+|calc\\([hsl()/*\\-+\\d.\\s]+\\)))%?(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.CIELab]: /^lab\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lab]|(?:\\d*\\.)?\\d+|calc\\([lab()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.LCH]: /^lch\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+%?)\\s+(?-?(?:\\d*\\.)?\\d+(?:deg|grad|rad|turn)?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?|from\\s+(?(?:\\w+|\\w+\\(\\s*[^())]+\\s*\\)|\\w+\\(from\\s+\\w+\\(.*\\)\\s*\\)|#[a-fA-F\\d]+))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))\\s+(?(?:[lch]|(?:\\d*\\.)?\\d+|calc\\([lch()/*\\-+\\d.\\s]+\\)))(?:\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+%?|calc\\([()/*\\-+\\d.\\s\\w]*(?:alpha)?[()/*\\-+\\d.\\s\\w]*\\)|alpha)))?)\\s*\\)$/,\n [ColorModel.CMYK]: /^(?:device-cmyk|cmyk)\\s*\\(\\s*(?:(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)\\s*,\\s*(?(?:\\d*\\.)?\\d+%?)(?:\\s*,\\s*(?(?:\\d*\\.)?\\d+))?|(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)\\s+(?(?:\\d*\\.)?\\d+%?)(?:\\s*\\/\\s*(?(?:\\d*\\.)?\\d+%?))?)\\s*\\)$/\n};\nconst CALC = {\n REGEXP: /^calc\\(\\s*(?[\\d./*+-\\w\\s]+)\\s*\\)$/,\n SCOPED: /\\(\\s*([^()]+)\\s*\\)/g,\n DIVISION: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\/\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n MULTIPLICATION: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\*\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n SUM: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*\\+\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/,\n REST: /\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*-\\s*(?(?:(?:\\d*\\.)?\\d+|\\w+))\\s*/\n};\nconst HSL_HUE = /^(?-?(?:\\d*\\.)?\\d+)(?(?:deg|grad|rad|turn)?)$/;\nconst PCENT = /^(-?\\d+(?:\\.\\d+)?|-?\\.\\d+)%$/;\nconst HEX = /^0x([a-f\\d]{1,2})$/i;\nconst TEMPLATE_VAR = /\\{(\\d+)\\}/g;\nconst COMMAS_AND_NEXT_CHARS = /,( +|\\d+)/g;\nconst SPACES = / +/;\n\n;// ./src/constants/index.ts\n\n\nconst MAX_DECIMALS = 6;\nconst DEFAULT_BLEND_STEPS = 5;\nconst DEFAULT_SHADES_TINTS_STEPS = 5;\nconst BASE_255 = 255;\nconst MAX_HUE = 360;\nconst MAX_PCENT = 100;\nconst MAX_ALPHA = 1;\nconst MAX_LAB = 125;\nconst MAX_LCH_C = 150;\nconst GRADIANS = 10 / 9;\nconst COLOR_KEYS = Object.keys(ColorKeywords);\nconst COLOR_PROPS = Object.freeze({\n HEX: ['R', 'G', 'B', 'A'],\n RGB: ['R', 'G', 'B', 'A'],\n HSL: ['H', 'S', 'L', 'A'],\n HWB: ['H', 'W', 'B', 'A'],\n CIELab: ['L', 'a', 'b', 'A'],\n LCH: ['L', 'C', 'H', 'A'],\n CMYK: ['C', 'M', 'Y', 'K', 'A']\n});\nconst VALID_COLOR_OBJECTS = Object.freeze({\n ABGR: ColorModel.RGB,\n ABHW: ColorModel.HWB,\n ACHL: ColorModel.LCH,\n ACKMY: ColorModel.CMYK,\n AHLS: ColorModel.HSL,\n ALAB: ColorModel.CIELab,\n BGR: ColorModel.RGB,\n BHW: ColorModel.HWB,\n CHL: ColorModel.LCH,\n CKMY: ColorModel.CMYK,\n HLS: ColorModel.HSL,\n LAB: ColorModel.CIELab\n});\nconst DEFAULT_OPTIONS = Object.freeze({\n decimals: MAX_DECIMALS,\n legacyCSS: false,\n spacesAfterCommas: false,\n anglesUnit: AnglesUnitEnum.NONE,\n rgbUnit: ColorUnitEnum.NONE,\n labUnit: ColorUnitEnum.NONE,\n lchUnit: ColorUnitEnum.NONE,\n cmykUnit: ColorUnitEnum.PERCENT,\n alphaUnit: ColorUnitEnum.NONE,\n cmykFunction: CMYKFunctionEnum.DEVICE_CMYK\n});\nconst ERRORS = Object.freeze({\n NOT_ACCEPTED_INPUT: `The provided string color doesn't have a correct format`,\n NOT_A_VALID_RELATIVE_COLOR: 'is not a valid operation for a relative color'\n});\n\n\n\n;// ./src/utilities/index.ts\n\n\nconst getOrderedArrayString = (keys) => [...keys].sort().join('').toUpperCase();\nconst isString = (input) => typeof input === 'string';\nconst isNumber = (input) => typeof input === 'number';\nconst isBoolean = (input) => typeof input === 'boolean';\nconst isUndefined = (input) => input === undefined;\nconst getColorModel = (color) => {\n return VALID_COLOR_OBJECTS[getOrderedArrayString(Object.keys(color))];\n};\nconst isRGBObject = (color) => getColorModel(color) === ColorModel.RGB;\nconst isHSLObject = (color) => getColorModel(color) === ColorModel.HSL;\nconst isHWBObject = (color) => getColorModel(color) === ColorModel.HWB;\nconst isCIELabObject = (color) => getColorModel(color) === ColorModel.CIELab;\nconst isLCHObject = (color) => getColorModel(color) === ColorModel.LCH;\nconst isCMYKObject = (color) => getColorModel(color) === ColorModel.CMYK;\nconst percentNumber = (percent) => {\n return +`${percent}`.replace(PCENT, '$1');\n};\nconst percent = (percent) => PCENT.test(`${percent}`)\n ? percentNumber(percent)\n : Math.min(+percent, 100);\nconst getDEC = (hex) => {\n if (hex.length === 1) {\n hex += hex;\n }\n return parseInt(hex, 16);\n};\nconst getHEX = (number) => {\n const hex = round(number, 0).toString(16).toUpperCase();\n if (hex.length === 1) {\n return `0x0${hex}`;\n }\n return `0x${hex}`;\n};\nconst toHEX = (h) => {\n let hex = round(h, 0).toString(16).toUpperCase();\n if (hex.length === 1) {\n hex = `0${hex}`;\n }\n return hex;\n};\nconst from255NumberToPercent = (value, decimals) => round(value / BASE_255 * 100, decimals);\nconst from125NumberToPercent = (value, decimals) => round(value / MAX_LAB * 100, decimals);\nconst from150NumberToPercent = (value, decimals) => round(value / MAX_LCH_C * 100, decimals);\nconst getBase255Number = (color, alpha = false) => {\n if (!alpha && PCENT.test(color)) {\n return Math.min(BASE_255 * percentNumber(color) / 100, BASE_255);\n }\n if (HEX.test(color)) {\n if (color.length === 3) {\n color += color.slice(-1);\n }\n return alpha\n ? round(color) / BASE_255\n : round(color);\n }\n return Math.min(+color, alpha ? 1 : BASE_255);\n};\nconst getBase125Number = (color) => {\n if (PCENT.test(color)) {\n return minmax(MAX_LAB * percentNumber(color) / 100, -MAX_LAB, MAX_LAB);\n }\n return minmax(+color, -MAX_LAB, MAX_LAB);\n};\nconst getBase150Number = (color) => {\n if (PCENT.test(color)) {\n return minmax(MAX_LCH_C * percentNumber(color) / 100, -MAX_LCH_C, MAX_LCH_C);\n }\n return minmax(+color, -MAX_LCH_C, MAX_LCH_C);\n};\nconst getCMYKNumber = (color, base100) => {\n const value = PCENT.test(color)\n ? percentNumber(color)\n : +color;\n if (base100) {\n return Math.min(value * 100, 100);\n }\n return Math.min(value, 100);\n};\nconst round = (value, decimals = MAX_DECIMALS) => {\n const exp = Math.pow(10, decimals);\n return Math.round(+value * exp) / exp;\n};\nconst minmax = (n, min, max) => Math.max(min, Math.min(n, max));\nconst degrees = (radian) => radian * 180 / Math.PI;\nconst radians = (degrees) => degrees * Math.PI / 180;\nconst normalizeHue = (hue) => {\n if (isString(hue)) {\n const matches = hue.match(HSL_HUE);\n const groups = matches.groups;\n const value = +groups.number;\n const units = groups.units;\n switch (units) {\n case AnglesUnitEnum.RADIANS:\n hue = round(degrees(value));\n break;\n case AnglesUnitEnum.TURNS:\n hue = round(value * MAX_HUE);\n break;\n case AnglesUnitEnum.GRADIANS:\n hue = round(9 / 10 * value);\n break;\n case AnglesUnitEnum.DEGREES:\n default:\n hue = value;\n }\n }\n if (hue >= MAX_HUE || hue < 0) {\n hue -= Math.floor(hue / MAX_HUE) * MAX_HUE;\n }\n return hue;\n};\nconst normalizeAlpha = (alpha) => {\n if (isString(alpha)) {\n if (PCENT.test(alpha)) {\n alpha = percentNumber(alpha) / 100;\n }\n else {\n alpha = +alpha;\n }\n }\n return (isNaN(+alpha) || alpha > MAX_ALPHA) ? MAX_ALPHA : round(alpha);\n};\nconst translateDegrees = (degrees, units) => {\n let hue;\n switch (units) {\n case AnglesUnitEnum.RADIANS:\n hue = round(radians(degrees));\n break;\n case AnglesUnitEnum.TURNS:\n hue = round(degrees / MAX_HUE);\n break;\n case AnglesUnitEnum.GRADIANS:\n hue = round(GRADIANS * degrees);\n break;\n case AnglesUnitEnum.DEGREES:\n case AnglesUnitEnum.NONE:\n default:\n hue = degrees;\n }\n return hue;\n};\nconst isHarmony = (param) => {\n return `${param}` in Harmony;\n};\nconst isMix = (param) => {\n return `${param}` in Mix;\n};\nconst getAngleUnit = (unit) => {\n if (unit) {\n const angleUnitMatch = unit.match(HSL_HUE);\n const angleUnit = angleUnitMatch.groups.units;\n return angleUnit === ''\n ? AnglesUnitEnum.NONE\n : angleUnit;\n }\n return AnglesUnitEnum.NONE;\n};\n\n;// ./src/color/translators.ts\n\n\nconst MATRIX_LRGB_XYZ_D50 = [\n [0.4360747, 0.3850649, 0.1430804],\n [0.2225045, 0.7168786, 0.0606169],\n [0.0139322, 0.0971045, 0.7141733]\n];\nconst MATRIX_XYZ_D50_LRGB = [\n [3.1338561, -1.6168667, -0.4906146],\n [-0.9787684, 1.9161415, 0.033454],\n [0.0719453, -0.2289914, 1.4052427]\n];\nconst TRISTIMULUS_D50 = MATRIX_LRGB_XYZ_D50.map((matrix) => {\n return matrix.reduce((sum, value) => sum + value, 0);\n});\nconst hueToRgb = (t1, t2, hue) => {\n if (hue < 0) {\n hue += 6;\n }\n if (hue >= 6) {\n hue -= 6;\n }\n if (hue < 1) {\n return round(((t2 - t1) * hue + t1) * BASE_255);\n }\n else if (hue < 3) {\n return round(t2 * BASE_255);\n }\n else if (hue < 4) {\n return round(((t2 - t1) * (4 - hue) + t1) * BASE_255);\n }\n else {\n return round(t1 * BASE_255);\n }\n};\nconst rgbToLinearLightRgb = (value) => {\n return value <= 0.04045\n ? value / 12.92\n : ((value + 0.055) / 1.055) ** 2.4;\n};\nconst linearLightRgbToRgb = (value) => {\n return value <= 0.0031308\n ? 12.92 * value\n : 1.055 * (value ** (1 / 2.4)) - 0.055;\n};\nconst matrixVectorMultiplication = (v1, v2, v3, matrix) => {\n const result = [0, 0, 0];\n const linearRgb = [v1, v2, v3];\n matrix.forEach((array, index) => {\n array.forEach((value, mindex) => {\n result[index] += value * linearRgb[mindex];\n });\n });\n return result;\n};\nconst from_CIE_XYZ_D50_to_CIE_LAB = (x, y, z) => {\n const f = (t) => {\n return t > (6 / 29) ** 3\n ? Math.cbrt(t)\n : t / (3 * (6 / 29) ** 2) + (4 / 29);\n };\n const fx = f(x / TRISTIMULUS_D50[0]);\n const fy = f(y / TRISTIMULUS_D50[1]);\n const fz = f(z / TRISTIMULUS_D50[2]);\n return [\n 116 * fy - 16,\n 500 * (fx - fy),\n 200 * (fy - fz)\n ];\n};\nconst from_CIE_LAB_to_CIE_XYZ_D50 = (L, a, b) => {\n const f = (t) => {\n return t > 6 / 29\n ? t ** 3\n : 3 * (6 / 29) ** 2 * (t - 4 / 29);\n };\n const fl = (L + 16) / 116;\n const fa = a / 500;\n const fb = b / 200;\n return [\n TRISTIMULUS_D50[0] * f(fl + fa),\n TRISTIMULUS_D50[1] * f(fl),\n TRISTIMULUS_D50[2] * f(fl - fb)\n ];\n};\nconst hslToRgb = (H, S, L) => {\n H /= 60;\n S /= 100;\n L /= 100;\n const t2 = (L <= .5)\n ? L * (S + 1)\n : L + S - (L * S);\n const t1 = L * 2 - t2;\n const R = hueToRgb(t1, t2, H + 2);\n const G = hueToRgb(t1, t2, H);\n const B = hueToRgb(t1, t2, H - 2);\n return { R, G, B };\n};\nconst rgbToHsl = (R, G, B, A = 1) => {\n R /= BASE_255;\n G /= BASE_255;\n B /= BASE_255;\n A = Math.min(A, MAX_ALPHA);\n const MAX = Math.max(R, G, B);\n const MIN = Math.min(R, G, B);\n const D = MAX - MIN;\n let H = 0;\n let S = 0;\n const L = (MAX + MIN) / 2;\n if (D !== 0) {\n switch (MAX) {\n case R:\n H = ((G - B) / D) % 6;\n break;\n case G:\n H = (B - R) / D + 2;\n break;\n case B:\n H = (R - G) / D + 4;\n break;\n }\n H = round(H * 60);\n if (H < 0) {\n H += 360;\n }\n S = D / (1 - Math.abs(2 * L - 1));\n }\n return {\n H,\n S: round(S * 100),\n L: round(L * 100),\n A\n };\n};\nconst rgbToLab = (R, G, B) => {\n const LINEAR_LIGHT_RGB = [\n R / BASE_255,\n G / BASE_255,\n B / BASE_255\n ].map(rgbToLinearLightRgb);\n const CIE_XYZ_D50 = matrixVectorMultiplication(LINEAR_LIGHT_RGB[0], LINEAR_LIGHT_RGB[1], LINEAR_LIGHT_RGB[2], MATRIX_LRGB_XYZ_D50);\n const CIE_LAB = from_CIE_XYZ_D50_to_CIE_LAB(CIE_XYZ_D50[0], CIE_XYZ_D50[1], CIE_XYZ_D50[2]);\n return {\n L: CIE_LAB[0],\n a: CIE_LAB[1],\n b: CIE_LAB[2]\n };\n};\nconst labToRgb = (L, a, b) => {\n const CIE_XYZ_D50 = from_CIE_LAB_to_CIE_XYZ_D50(L, a, b);\n const LINEAR_LIGHT_RGB = matrixVectorMultiplication(CIE_XYZ_D50[0], CIE_XYZ_D50[1], CIE_XYZ_D50[2], MATRIX_XYZ_D50_LRGB);\n const rgb = LINEAR_LIGHT_RGB.map(linearLightRgbToRgb);\n return {\n R: minmax(rgb[0] * BASE_255, 0, BASE_255),\n G: minmax(rgb[1] * BASE_255, 0, BASE_255),\n B: minmax(rgb[2] * BASE_255, 0, BASE_255)\n };\n};\nconst labToLch = (L, a, b) => {\n const C = Math.sqrt(a ** 2 + b ** 2);\n const H = degrees(Math.atan2(b, a));\n return {\n L,\n C,\n H: normalizeHue(H)\n };\n};\nconst lchToLab = (L, C, H) => {\n const radH = radians(H);\n const a = C * Math.cos(radH);\n const b = C * Math.sin(radH);\n return {\n L,\n a,\n b\n };\n};\nconst rgbToLch = (R, G, B) => {\n const lab = rgbToLab(R, G, B);\n return labToLch(lab.L, lab.a, lab.b);\n};\nconst lchToRgb = (L, C, H) => {\n const lab = lchToLab(L, C, H);\n return labToRgb(lab.L, lab.a, lab.b);\n};\nconst rgbToHwb = (R, G, B, A = 1) => {\n const hsl = rgbToHsl(R, G, B, A);\n return {\n H: hsl.H,\n W: round(Math.min(R, G, B) / BASE_255 * 100),\n B: round((1 - Math.max(R, G, B) / BASE_255) * 100),\n A\n };\n};\nconst hwbToRgb = (H, W, B) => {\n W /= 100;\n B /= 100;\n const v = 1 - B;\n const c = v - W;\n const x = c * (1 - Math.abs((H / 60) % 2 - 1));\n let rgbR;\n let rgbG;\n let rgbB;\n if (H < 60) {\n rgbR = c;\n rgbG = x;\n rgbB = 0;\n }\n else if (H >= 60 && H < 120) {\n rgbR = x;\n rgbG = c;\n rgbB = 0;\n }\n else if (H >= 120 && H < 180) {\n rgbR = 0;\n rgbG = c;\n rgbB = x;\n }\n else if (H >= 180 && H < 240) {\n rgbR = 0;\n rgbG = x;\n rgbB = c;\n }\n else if (H >= 240 && H < 300) {\n rgbR = x;\n rgbG = 0;\n rgbB = c;\n }\n else {\n rgbR = c;\n rgbG = 0;\n rgbB = x;\n }\n rgbR += W;\n rgbG += W;\n rgbB += W;\n return {\n R: minmax(rgbR * BASE_255, 0, BASE_255),\n G: minmax(rgbG * BASE_255, 0, BASE_255),\n B: minmax(rgbB * BASE_255, 0, BASE_255)\n };\n};\nconst cmykToRgb = (C, M, Y, K) => {\n K = 1 - K;\n return {\n R: minmax(round(BASE_255 * (1 - C) * K), 0, BASE_255),\n G: minmax(round(BASE_255 * (1 - M) * K), 0, BASE_255),\n B: minmax(round(BASE_255 * (1 - Y) * K), 0, BASE_255)\n };\n};\nconst rgbToCmyk = (R, G, B) => {\n R /= BASE_255;\n G /= BASE_255;\n B /= BASE_255;\n const K = 1 - Math.max(R, G, B);\n const K1 = 1 - K;\n const C = K1 && (K1 - R) / K1;\n const M = K1 && (K1 - G) / K1;\n const Y = K1 && (K1 - B) / K1;\n return {\n C: round(C * 100),\n M: round(M * 100),\n Y: round(Y * 100),\n K: round(K * 100)\n };\n};\nconst rgbToRyb = (R, G, B) => {\n const Iw = Math.min(R, G, B);\n const Ib = Math.min(BASE_255 - R, BASE_255 - G, BASE_255 - B);\n const rRgb = R - Iw;\n const gRgb = G - Iw;\n const bRgb = B - Iw;\n const minRg = Math.min(rRgb, gRgb);\n const rRyb = rRgb - minRg;\n const yRyb = (gRgb + minRg) / 2;\n const bRyb = (bRgb + gRgb - minRg) / 2;\n const n = Math.max(rRyb, yRyb, bRyb) / Math.max(rRgb, gRgb, bRgb);\n const N = isNaN(n) || n === Infinity || n <= 0 ? 1 : n;\n return {\n R: rRyb / N + Ib,\n Y: yRyb / N + Ib,\n B: bRyb / N + Ib\n };\n};\nconst rybToRgb = (R, Y, B) => {\n const Iw = Math.min(R, Y, B);\n const Ib = Math.min(BASE_255 - R, BASE_255 - Y, BASE_255 - B);\n const rRyb = R - Iw;\n const yRyb = Y - Iw;\n const bRyb = B - Iw;\n const minYb = Math.min(yRyb, bRyb);\n const rRgb = rRyb + yRyb - minYb;\n const gRgb = yRyb + minYb;\n const bRgb = 2 * (bRyb - minYb);\n const n = Math.max(rRgb, gRgb, bRgb) / Math.max(rRyb, yRyb, bRyb);\n const N = isNaN(n) || n === Infinity || n <= 0 ? 1 : n;\n return {\n R: rRgb / N + Ib,\n G: gRgb / N + Ib,\n B: bRgb / N + Ib\n };\n};\nconst hueRyb = (hue, toRyb) => {\n if (hue < 0)\n hue += 360;\n if (hue > 360)\n hue -= 360;\n if (hue === 360 || hue === 0)\n return hue;\n const map1 = [\n [0, 120],\n [120, 180],\n [180, 240],\n [240, 360]\n ];\n const map2 = [\n [0, 60],\n [60, 120],\n [120, 240],\n [240, 360]\n ];\n const from = toRyb ? map1 : map2;\n const to = toRyb ? map2 : map1;\n let A = 0;\n let B = 0;\n let C = 0;\n let D = 0;\n from.find((arr, index) => {\n if (hue >= arr[0] && hue < arr[1]) {\n A = arr[0];\n B = arr[1];\n C = to[index][0];\n D = to[index][1];\n return true;\n }\n return false;\n });\n return C + (hue - A) * ((D - C) / (B - A));\n};\n\n;// ./src/classes/ColorParserContext.ts\n\n\nclass ColorParserContext {\n constructor(parsers) {\n this._parsers = parsers;\n }\n getParser(input) {\n const parser = Object.values(this._parsers).find(parser => parser.supports(input));\n if (parser) {\n return parser;\n }\n throw new Error(ERRORS.NOT_ACCEPTED_INPUT);\n }\n parse(input) {\n const parser = this.getParser(input);\n return parser.parse(input, this);\n }\n convert(input, model, decimals = DEFAULT_OPTIONS.decimals, withAlpha = false) {\n const color = this.parse(input);\n const parser = this._parsers[model];\n return parser.convert(color, decimals, withAlpha);\n }\n convertCSS(input, model, options = {}, withAlpha = false) {\n const color = this.parse(input);\n const parser = this._parsers[model];\n return parser.convertCSS(color, options, withAlpha);\n }\n}\nclass ColorParser {\n hasAlpha(input) {\n if (isString(input)) {\n return this.getCSSOptions(input).hasAlpha;\n }\n return !isUndefined(input.A);\n }\n ;\n}\n\n;// ./src/color/rgb.ts\n\n\nconst getAlpha = (color) => {\n if (isUndefined(color.A)) {\n return {};\n }\n return {\n A: +color.A\n };\n};\nconst getRGB = (color) => {\n const alpha = getAlpha(color);\n if (isHSLObject(color)) {\n return {\n ...hslToRgb(color.H, color.S, color.L),\n ...alpha\n };\n }\n if (isHWBObject(color)) {\n return {\n ...hwbToRgb(color.H, color.W, color.B),\n ...alpha\n };\n }\n if (isCIELabObject(color)) {\n return {\n ...labToRgb(color.L, color.a, color.b),\n ...alpha\n };\n }\n if (isLCHObject(color)) {\n return {\n ...lchToRgb(color.L, color.C, color.H),\n ...alpha\n };\n }\n if (isCMYKObject(color)) {\n return {\n ...cmykToRgb(color.C, color.M, color.Y, color.K),\n ...alpha\n };\n }\n return color;\n};\n\n;// ./src/css/index.ts\n\n\n\nconst getCSSComma = (withSpace) => withSpace\n ? ', '\n : ',';\nconst prepareColorForCss = (color, transformer) => {\n const props = getOrderedArrayString(Object.keys(color));\n const model = VALID_COLOR_OBJECTS[props];\n const keys = COLOR_PROPS[model];\n return keys.reduce((result, key, index) => {\n const value = color[key];\n if (typeof value !== 'undefined') {\n result.push(transformer(value, index));\n }\n return result;\n }, []);\n};\nconst getResultFromCSSTemplate = (template, vars) => {\n return template.replace(TEMPLATE_VAR, (__match, indexStr) => {\n const index = +indexStr - 1;\n return `${vars[index]}`;\n });\n};\nconst getCSSAlpha = (value, options, ignoreLegacy = false) => {\n const { alphaUnit, legacyCSS, decimals } = options;\n if (alphaUnit === ColorUnitEnum.PERCENT &&\n (!legacyCSS ||\n ignoreLegacy)) {\n return `${round(value * 100, decimals)}%`;\n }\n return round(value, decimals);\n};\nconst buildCSSHueTransformer = (options) => {\n const { anglesUnit, decimals } = options;\n return (value, index) => {\n if (index === 0 &&\n anglesUnit !== AnglesUnitEnum.NONE) {\n const translated = round(translateDegrees(value, anglesUnit), decimals);\n return `${translated}${anglesUnit}`;\n }\n return index === 3\n ? getCSSAlpha(value, options)\n : round(value, decimals);\n };\n};\n\n;// ./src/classes/HEXParser.ts\n\n\n\n\n\nclass HEXParser extends ColorParser {\n _extract(input) {\n const colorStr = !~COLOR_KEYS.indexOf(input)\n ? input\n : ColorKeywords[input];\n const match = colorStr.match(COLORREGS.HEX);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return (COLORREGS.HEX.test(input) ||\n !!~COLOR_KEYS.indexOf(input));\n }\n const hasInvalidHex = Object.entries(input).some((item) => {\n return !HEX.test(`${item[1]}`);\n });\n return isRGBObject(input) && !hasInvalidHex;\n }\n parse(input) {\n if (isString(input)) {\n const groups = this._extract(input);\n const r = groups.r ?? groups.rr;\n const g = groups.g ?? groups.gg;\n const b = groups.b ?? groups.bb;\n const a = groups.a ?? groups.aa;\n return {\n R: getDEC(r),\n G: getDEC(g),\n B: getDEC(b),\n ...(isUndefined(a)\n ? {}\n : {\n A: getDEC(a) / BASE_255\n })\n };\n }\n return {\n R: getBase255Number(`${input.R}`),\n G: getBase255Number(`${input.G}`),\n B: getBase255Number(`${input.B}`),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: Math.min(getBase255Number(`${input.A}`, true), 1)\n })\n };\n }\n convert(color, __decimals, withAlpha) {\n const rgb = isRGBObject(color)\n ? color\n : getRGB(color);\n return {\n R: getHEX(rgb.R),\n G: getHEX(rgb.G),\n B: getHEX(rgb.B),\n ...(withAlpha\n ? {\n A: isUndefined(rgb.A)\n ? '0xFF'\n : getHEX(rgb.A * BASE_255)\n }\n : {})\n };\n }\n convertCSS(color, options, withAlpha) {\n const rgb = this.convert(color, options.decimals, withAlpha);\n const transformer = (value) => toHEX(round(value));\n const values = prepareColorForCss(rgb, transformer);\n const template = values.length === 4\n ? '#{1}{2}{3}{4}'\n : '#{1}{2}{3}';\n return getResultFromCSSTemplate(template, values);\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n return {\n hasAlpha: !isUndefined(groups.a ?? groups.aa)\n };\n }\n get model() {\n return ColorModel.HEX;\n }\n}\n\n;// ./src/classes/CalcParser.ts\n\nconst MAX_STACK = 100;\nclass CalcParser {\n constructor(colorIndex, calc, vars) {\n this._operations = new Map([\n [CALC.DIVISION, this._division],\n [CALC.MULTIPLICATION, this._multiplication],\n [CALC.SUM, this._sum],\n [CALC.REST, this._rest]\n ]);\n this._colorIndex = colorIndex;\n let calcString = calc;\n let stack = 0;\n if (!Number.isNaN(+calc)) {\n this._result = +calc;\n }\n else if (calc in vars) {\n this._result = vars[calc];\n }\n else if (CALC.REGEXP.test(calcString)) {\n CALC.REGEXP.lastIndex = 0;\n this._result = this._getCalcValue(calcString, vars);\n }\n else {\n while (CALC.SCOPED.test(calcString) && stack < MAX_STACK) {\n CALC.SCOPED.lastIndex = 0;\n calcString = calcString.replace(CALC.SCOPED, (__match, operation) => {\n return this._calculate(operation, vars).toString();\n });\n if (CALC.REGEXP.test(calcString)) {\n CALC.REGEXP.lastIndex = 0;\n break;\n }\n stack++;\n }\n this._result = this._getCalcValue(calcString, vars);\n }\n }\n _division(left, right) {\n return left / right;\n }\n _multiplication(left, right) {\n return left * right;\n }\n _sum(left, right) {\n return left + right;\n }\n _rest(left, right) {\n return left - right;\n }\n _getCalcValue(calc, vars) {\n const match = calc.match(CALC.REGEXP);\n const operation = match.groups.operation;\n const value = this._calculate(operation, vars);\n if (Number.isNaN(value)) {\n throw new Error(`Invalid value for ${this._colorIndex}. ${operation} ${ERRORS.NOT_A_VALID_RELATIVE_COLOR}`);\n }\n return value;\n }\n _calculate(operation, vars) {\n this._operations.forEach((method, regExp) => {\n let stack = 0;\n while (regExp.test(operation) && stack < MAX_STACK) {\n operation = operation.replace(regExp, (__match, left, right) => {\n return method(vars[left] ?? +left, vars[right] ?? +right).toString();\n });\n stack++;\n }\n });\n return +operation;\n }\n get result() {\n return this._result;\n }\n}\n\n;// ./src/classes/RGBParser.ts\n\n\n\n\n\n\n\nclass RGBParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.RGB);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.RGB.test(input);\n }\n const hasInvalidRegb = Object.entries(input).some((item) => {\n return !(PCENT.test(`${item[1]}`) ||\n (!HEX.test(`${item[1]}`) &&\n !isNaN(+item[1]) &&\n +item[1] <= BASE_255));\n });\n return isRGBObject(input) && !hasInvalidRegb;\n }\n parse(input, context) {\n if (isString(input)) {\n const groups = this._extract(input);\n const { r_legacy, g_legacy, b_legacy, a_legacy, r, g, b, a, from, relative_r, relative_g, relative_b, relative_a } = groups;\n if (from) {\n const fromColor = context.parse(from);\n const fromRGB = getRGB(fromColor);\n const fromRGBVars = {\n r: fromRGB.R,\n g: fromRGB.G,\n b: fromRGB.B,\n alpha: fromRGB.A ?? 1\n };\n const R = new CalcParser('r', relative_r, fromRGBVars).result;\n const G = new CalcParser('g', relative_g, fromRGBVars).result;\n const B = new CalcParser('b', relative_b, fromRGBVars).result;\n const rgb = {\n R: Math.min(R, BASE_255),\n G: Math.min(G, BASE_255),\n B: Math.min(B, BASE_255)\n };\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromRGBVars).result;\n rgb.A = Math.min(A, 1);\n }\n return rgb;\n }\n else {\n const R = r_legacy ?? r;\n const G = g_legacy ?? g;\n const B = b_legacy ?? b;\n const A = a_legacy ?? a;\n return {\n R: Math.min(getBase255Number(R), BASE_255),\n G: Math.min(getBase255Number(G), BASE_255),\n B: Math.min(getBase255Number(B), BASE_255),\n ...(isUndefined(A)\n ? {}\n : {\n A: normalizeAlpha(A)\n })\n };\n }\n }\n return {\n R: getBase255Number(`${input.R}`),\n G: getBase255Number(`${input.G}`),\n B: getBase255Number(`${input.B}`),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: Math.min(getBase255Number(`${input.A}`, true), 1)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n const rgb = isRGBObject(color)\n ? color\n : getRGB(color);\n return this._roundRGBObject({\n R: rgb.R,\n G: rgb.G,\n B: rgb.B,\n ...(withAlpha\n ? {\n A: rgb.A ?? 1\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const { decimals, legacyCSS, spacesAfterCommas, rgbUnit } = options;\n const rgb = this.convert(color, options.decimals, withAlpha);\n const comma = getCSSComma(spacesAfterCommas);\n const transformer = (value, index) => {\n return rgbUnit === ColorUnitEnum.PERCENT && index < 3\n ? `${from255NumberToPercent(value, decimals)}%`\n : (index === 3\n ? getCSSAlpha(value, options)\n : round(value, decimals));\n };\n const values = prepareColorForCss(rgb, transformer);\n const template = legacyCSS\n ? (values.length === 4\n ? `rgba({1}${comma}{2}${comma}{3}${comma}{4})`\n : `rgb({1}${comma}{2}${comma}{3})`)\n : (values.length === 4\n ? `rgb({1} {2} {3} / {4})`\n : `rgb({1} {2} {3})`);\n return getResultFromCSSTemplate(template, values);\n }\n _roundRGBObject(color, decimals) {\n const R = round(color.R, decimals);\n const G = round(color.G, decimals);\n const B = round(color.B, decimals);\n return {\n R,\n G,\n B,\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n const { r_legacy, g_legacy, b_legacy, a_legacy, r, g, b, a } = groups;\n return {\n hasPercentageValues: (PCENT.test(r_legacy ?? r) &&\n PCENT.test(g_legacy ?? g) &&\n PCENT.test(b_legacy ?? b)),\n hasPercentageAlpha: PCENT.test(a_legacy ?? a),\n hasAlpha: !isUndefined(a_legacy ?? a)\n };\n }\n get model() {\n return ColorModel.RGB;\n }\n}\n\n;// ./src/classes/HSLParser.ts\n\n\n\n\n\n\n\nclass HSLParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.HSL);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.HSL.test(input);\n }\n return isHSLObject(input);\n }\n parse(input, context) {\n if (isString(input)) {\n const groups = this._extract(input);\n const { h_legacy, s_legacy, l_legacy, a_legacy, h, s, l, a, from, relative_h, relative_s, relative_l, relative_a } = groups;\n if (from) {\n const fromColor = context.parse(from);\n const fromRGB = getRGB(fromColor);\n const fromHSL = rgbToHsl(fromRGB.R, fromRGB.G, fromRGB.B, fromRGB.A);\n const fromHSLVars = {\n h: fromHSL.H,\n s: fromHSL.S,\n l: fromHSL.L,\n alpha: fromHSL.A\n };\n const H = new CalcParser('h', relative_h, fromHSLVars).result;\n const S = new CalcParser('s', relative_s, fromHSLVars).result;\n const L = new CalcParser('l', relative_l, fromHSLVars).result;\n const hsl = {\n H: normalizeHue(H),\n S: percent(S),\n L: percent(L)\n };\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromHSLVars).result;\n hsl.A = minmax(A, 0, MAX_ALPHA);\n }\n return hsl;\n }\n else {\n const H = h_legacy ?? h;\n const S = s_legacy ?? s;\n const L = l_legacy ?? l;\n const A = a_legacy ?? a;\n return {\n H: normalizeHue(H),\n S: percent(S),\n L: percent(L),\n ...(isUndefined(A)\n ? {}\n : {\n A: normalizeAlpha(A)\n })\n };\n }\n }\n return {\n H: normalizeHue(input.H),\n S: percent(`${input.S}`),\n L: percent(`${input.L}`),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: minmax(+input.A, 0, MAX_ALPHA)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n let hsl;\n if (isHSLObject(color)) {\n hsl = color;\n }\n else {\n const rgb = getRGB(color);\n hsl = rgbToHsl(rgb.R, rgb.G, rgb.B, rgb.A);\n }\n return this._roundHSLObject({\n H: hsl.H,\n S: hsl.S,\n L: hsl.L,\n ...(withAlpha\n ? {\n A: hsl.A ?? 1\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const { legacyCSS, spacesAfterCommas } = options;\n const comma = getCSSComma(spacesAfterCommas);\n const hsl = this.convert(color, options.decimals, withAlpha);\n const transformer = buildCSSHueTransformer(options);\n const values = prepareColorForCss(hsl, transformer);\n const template = legacyCSS\n ? (values.length === 4\n ? `hsla({1}${comma}{2}%${comma}{3}%${comma}{4})`\n : `hsl({1}${comma}{2}%${comma}{3}%)`)\n : (values.length === 4\n ? `hsl({1} {2}% {3}% / {4})`\n : `hsl({1} {2}% {3}%)`);\n return getResultFromCSSTemplate(template, values);\n }\n _roundHSLObject(color, decimals) {\n return {\n H: round(normalizeHue(color.H), decimals),\n S: round(color.S, decimals),\n L: round(color.L, decimals),\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n const { h_legacy, h, a_legacy, a } = groups;\n return {\n angleUnit: getAngleUnit(h_legacy ?? h),\n hasPercentageAlpha: PCENT.test(a_legacy ?? a),\n hasAlpha: !isUndefined(a_legacy ?? a)\n };\n }\n get model() {\n return ColorModel.HSL;\n }\n}\n\n;// ./src/classes/HWBParser.ts\n\n\n\n\n\n\n\nclass HWBParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.HWB);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.HWB.test(input);\n }\n return isHWBObject(input);\n }\n parse(input, context) {\n if (isString(input)) {\n const groups = this._extract(input);\n const { h, w, b, a, from, relative_h, relative_w, relative_b, relative_a } = groups;\n if (from) {\n const fromColor = context.parse(from);\n const fromRGB = getRGB(fromColor);\n const fromHWB = rgbToHwb(fromRGB.R, fromRGB.G, fromRGB.B, fromRGB.A);\n const fromHWBVars = {\n h: fromHWB.H,\n w: fromHWB.W,\n b: fromHWB.B,\n alpha: fromHWB.A\n };\n const H = new CalcParser('h', relative_h, fromHWBVars).result;\n const W = new CalcParser('w', relative_w, fromHWBVars).result;\n const B = new CalcParser('b', relative_b, fromHWBVars).result;\n const hwb = {\n H: minmax(H, 0, MAX_HUE),\n W: minmax(W, 0, MAX_PCENT),\n B: minmax(B, 0, MAX_PCENT)\n };\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromHWBVars).result;\n hwb.A = minmax(A, 0, MAX_ALPHA);\n }\n return hwb;\n }\n else {\n return {\n H: normalizeHue(h),\n W: percent(w),\n B: percent(b),\n ...(isUndefined(a)\n ? {}\n : {\n A: normalizeAlpha(a)\n })\n };\n }\n }\n return {\n H: normalizeHue(input.H),\n W: percent(input.W),\n B: percent(input.B),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: normalizeAlpha(input.A)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n let hwb;\n if (isHWBObject(color)) {\n hwb = color;\n }\n else {\n const rgb = getRGB(color);\n hwb = rgbToHwb(rgb.R, rgb.G, rgb.B, rgb.A);\n }\n return this._roundHWBObject({\n H: hwb.H,\n W: hwb.W,\n B: hwb.B,\n ...(withAlpha\n ? {\n A: hwb.A ?? 1\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const hwb = this.convert(color, options.decimals, withAlpha);\n const transformer = buildCSSHueTransformer(options);\n const values = prepareColorForCss(hwb, transformer);\n const template = values.length === 4\n ? `hwb({1} {2}% {3}% / {4})`\n : `hwb({1} {2}% {3}%)`;\n return getResultFromCSSTemplate(template, values);\n }\n _roundHWBObject(color, decimals) {\n return {\n H: round(normalizeHue(color.H), decimals),\n W: round(color.W, decimals),\n B: round(color.B, decimals),\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n return {\n angleUnit: getAngleUnit(groups.h),\n hasPercentageAlpha: PCENT.test(groups.a),\n hasAlpha: !isUndefined(groups.a)\n };\n }\n get model() {\n return ColorModel.HWB;\n }\n}\n\n;// ./src/classes/CIELabParser.ts\n\n\n\n\n\n\n\n\nclass CIELabParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.CIELab);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.CIELab.test(input);\n }\n return isCIELabObject(input);\n }\n parse(input, context) {\n if (isString(input)) {\n const groups = this._extract(input);\n const { L, a, b, A, from, relative_L, relative_a, relative_b, relative_A } = groups;\n if (from) {\n const fromColor = context.parse(from);\n const fromRGB = getRGB(fromColor);\n const fromCIELab = rgbToLab(fromRGB.R, fromRGB.G, fromRGB.B);\n const fromCIELabVars = {\n l: fromCIELab.L,\n a: fromCIELab.a,\n b: fromCIELab.b,\n alpha: fromRGB.A ?? 1\n };\n const L = new CalcParser('l', relative_L, fromCIELabVars).result;\n const a = new CalcParser('a', relative_a, fromCIELabVars).result;\n const b = new CalcParser('b', relative_b, fromCIELabVars).result;\n const CIELab = {\n L: minmax(L, 0, MAX_PCENT),\n a: minmax(a, -MAX_LAB, MAX_LAB),\n b: minmax(b, -MAX_LAB, MAX_LAB)\n };\n if (relative_A) {\n const A = new CalcParser('alpha', relative_A, fromCIELabVars).result;\n CIELab.A = minmax(A, 0, MAX_ALPHA);\n }\n return CIELab;\n }\n else {\n return {\n L: percent(L),\n a: getBase125Number(a),\n b: getBase125Number(b),\n ...(isUndefined(A)\n ? {}\n : {\n A: normalizeAlpha(A)\n })\n };\n }\n }\n return {\n L: percent(input.L),\n a: getBase125Number(`${input.a}`),\n b: getBase125Number(`${input.b}`),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: normalizeAlpha(input.A)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n let lab;\n if (isCIELabObject(color)) {\n lab = color;\n }\n else {\n const rgb = getRGB(color);\n lab = rgbToLab(rgb.R, rgb.G, rgb.B);\n }\n return this._roundCIELabObject({\n L: lab.L,\n a: lab.a,\n b: lab.b,\n ...(withAlpha\n ? {\n A: +(color.A ?? 1)\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const { decimals, labUnit } = options;\n const lab = this.convert(color, options.decimals, withAlpha);\n const transformer = (value, index) => {\n if (index === 0) {\n const L = round(percent(value), decimals);\n return labUnit === ColorUnitEnum.PERCENT\n ? `${L}%`\n : `${L}`;\n }\n if (index < 3) {\n return labUnit === ColorUnitEnum.PERCENT\n ? `${from125NumberToPercent(value, decimals)}%`\n : round(value, decimals);\n }\n return getCSSAlpha(value, options, true);\n };\n const values = prepareColorForCss(lab, transformer);\n const template = values.length === 4\n ? `lab({1} {2} {3} / {4})`\n : `lab({1} {2} {3})`;\n return getResultFromCSSTemplate(template, values);\n }\n _roundCIELabObject(color, decimals) {\n return {\n L: round(color.L, decimals),\n a: round(color.a, decimals),\n b: round(color.b, decimals),\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n const { L, a, b, A } = groups;\n return {\n hasPercentageValues: (PCENT.test(L) &&\n PCENT.test(a) &&\n PCENT.test(b)),\n hasPercentageAlpha: PCENT.test(A),\n hasAlpha: !isUndefined(A)\n };\n }\n get model() {\n return ColorModel.CIELab;\n }\n}\n\n;// ./src/classes/LCHParser.ts\n\n\n\n\n\n\n\n\nclass LCHParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.LCH);\n return match.groups;\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.LCH.test(input);\n }\n return isLCHObject(input);\n }\n parse(input, context) {\n if (isString(input)) {\n const groups = this._extract(input);\n const { l, c, h, a, from, relative_l, relative_c, relative_h, relative_a } = groups;\n if (from) {\n const fromColor = context.parse(from);\n const fromRGB = getRGB(fromColor);\n const fromLCH = rgbToLch(fromRGB.R, fromRGB.G, fromRGB.B);\n const fromLCHVars = {\n l: fromLCH.L,\n c: fromLCH.C,\n h: fromLCH.H,\n alpha: fromRGB.A ?? 1\n };\n const L = new CalcParser('l', relative_l, fromLCHVars).result;\n const C = new CalcParser('c', relative_c, fromLCHVars).result;\n const H = new CalcParser('h', relative_h, fromLCHVars).result;\n const lch = {\n L: minmax(L, 0, MAX_PCENT),\n C: minmax(C, -MAX_LCH_C, MAX_LCH_C),\n H: normalizeHue(H)\n };\n if (relative_a) {\n const A = new CalcParser('alpha', relative_a, fromLCHVars).result;\n lch.A = minmax(A, 0, MAX_ALPHA);\n }\n return lch;\n }\n else {\n return {\n L: percent(l),\n C: getBase150Number(c),\n H: normalizeHue(h),\n ...(isUndefined(a)\n ? {}\n : {\n A: normalizeAlpha(a)\n })\n };\n }\n }\n return {\n L: percent(input.L),\n C: getBase150Number(`${input.C}`),\n H: normalizeHue(input.H),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: normalizeAlpha(input.A)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n let lch;\n if (isLCHObject(color)) {\n lch = color;\n }\n else {\n const rgb = getRGB(color);\n lch = rgbToLch(rgb.R, rgb.G, rgb.B);\n }\n return this._roundLCHObject({\n L: lch.L,\n C: lch.C,\n H: lch.H,\n ...(withAlpha\n ? {\n A: +(color.A ?? 1)\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const { decimals, lchUnit, anglesUnit } = options;\n const lch = this.convert(color, options.decimals, withAlpha);\n const transformer = (value, index) => {\n if (index === 0) {\n const L = round(percent(value), decimals);\n return lchUnit === ColorUnitEnum.PERCENT\n ? `${L}%`\n : `${L}`;\n }\n if (index === 1) {\n return lchUnit === ColorUnitEnum.PERCENT\n ? `${from150NumberToPercent(value, decimals)}%`\n : round(value, decimals);\n }\n if (index === 2) {\n if (anglesUnit !== AnglesUnitEnum.NONE) {\n const translated = round(translateDegrees(value, anglesUnit), decimals);\n return `${translated}${anglesUnit}`;\n }\n return round(value, decimals);\n }\n return getCSSAlpha(value, options, true);\n };\n const values = prepareColorForCss(lch, transformer);\n const template = values.length === 4\n ? `lch({1} {2} {3} / {4})`\n : `lch({1} {2} {3})`;\n return getResultFromCSSTemplate(template, values);\n }\n _roundLCHObject(color, decimals) {\n return {\n L: round(color.L, decimals),\n C: round(color.C, decimals),\n H: round(normalizeHue(color.H), decimals),\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n return {\n angleUnit: getAngleUnit(groups.h),\n hasPercentageValues: (PCENT.test(groups.l) &&\n PCENT.test(groups.c)),\n hasPercentageAlpha: PCENT.test(groups.a),\n hasAlpha: !isUndefined(groups.a)\n };\n }\n get model() {\n return ColorModel.LCH;\n }\n}\n\n;// ./src/classes/CMYKParser.ts\n\n\n\n\n\n\n\nclass CMYKParser extends ColorParser {\n _extract(input) {\n const match = input.match(COLORREGS.CMYK);\n return match.groups;\n }\n _shouldMultiplyBy100(...colors) {\n return !colors.some((color) => +color > 1);\n }\n supports(input) {\n if (isString(input)) {\n return COLORREGS.CMYK.test(input);\n }\n return isCMYKObject(input);\n }\n parse(input) {\n if (isString(input)) {\n const groups = this._extract(input);\n const c = groups.c_legacy ?? groups.c;\n const m = groups.m_legacy ?? groups.m;\n const y = groups.y_legacy ?? groups.y;\n const k = groups.k_legacy ?? groups.k;\n const a = groups.a_legacy ?? groups.a;\n const shouldMultiplyBy100 = this._shouldMultiplyBy100(c, m, y, k);\n return {\n C: getCMYKNumber(c, shouldMultiplyBy100),\n M: getCMYKNumber(m, shouldMultiplyBy100),\n Y: getCMYKNumber(y, shouldMultiplyBy100),\n K: getCMYKNumber(k, shouldMultiplyBy100),\n ...(isUndefined(a)\n ? {}\n : {\n A: normalizeAlpha(a)\n })\n };\n }\n const shouldMultiplyBy100 = this._shouldMultiplyBy100(input.C, input.M, input.Y, input.K);\n return {\n C: getCMYKNumber(`${input.C}`, shouldMultiplyBy100),\n M: getCMYKNumber(`${input.M}`, shouldMultiplyBy100),\n Y: getCMYKNumber(`${input.Y}`, shouldMultiplyBy100),\n K: getCMYKNumber(`${input.K}`, shouldMultiplyBy100),\n ...(isUndefined(input.A)\n ? {}\n : {\n A: normalizeAlpha(input.A)\n })\n };\n }\n convert(color, decimals, withAlpha) {\n let cmyk;\n if (isCMYKObject(color)) {\n cmyk = color;\n }\n else {\n const rgb = getRGB(color);\n cmyk = rgbToCmyk(rgb.R, rgb.G, rgb.B);\n }\n return this._roundCMYKObject({\n C: cmyk.C,\n M: cmyk.M,\n Y: cmyk.Y,\n K: cmyk.K,\n ...(withAlpha\n ? {\n A: +(color.A ?? 1)\n }\n : {})\n }, decimals);\n }\n convertCSS(color, options, withAlpha) {\n const { decimals, legacyCSS, spacesAfterCommas, cmykUnit, cmykFunction } = options;\n const comma = getCSSComma(spacesAfterCommas);\n const cmyk = this.convert(color, options.decimals, withAlpha);\n const transformer = (value, index) => {\n if (cmykUnit === ColorUnitEnum.PERCENT &&\n index < 4) {\n return `${round(value, decimals)}%`;\n }\n return index === 4\n ? getCSSAlpha(value, options)\n : round(value / 100, decimals);\n };\n const values = prepareColorForCss(cmyk, transformer);\n const template = legacyCSS\n ? (values.length === 5\n ? `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4}${comma}{5})`\n : `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4})`)\n : (values.length === 5\n ? `${cmykFunction}({1} {2} {3} {4} / {5})`\n : `${cmykFunction}({1} {2} {3} {4})`);\n return getResultFromCSSTemplate(template, values);\n }\n _roundCMYKObject(color, decimals) {\n return {\n C: round(color.C, decimals),\n M: round(color.M, decimals),\n Y: round(color.Y, decimals),\n K: round(color.K, decimals),\n ...(isUndefined(color.A)\n ? {}\n : {\n A: round(color.A, decimals)\n })\n };\n }\n getCSSOptions(input) {\n const groups = this._extract(input);\n const { c_legacy, m_legacy, y_legacy, k_legacy, a_legacy, c, m, y, k, a } = groups;\n return {\n hasPercentageValues: (PCENT.test(c_legacy ?? c) &&\n PCENT.test(m_legacy ?? m) &&\n PCENT.test(y_legacy ?? y) &&\n PCENT.test(k_legacy ?? k)),\n hasPercentageAlpha: PCENT.test(a_legacy ?? a),\n hasAlpha: !isUndefined(a_legacy ?? a)\n };\n }\n get model() {\n return ColorModel.CMYK;\n }\n}\n\n;// ./src/parsers/index.ts\n\n\n\n\n\n\n\n\n\n\n\nconst hexParser = new HEXParser();\nconst rgbParser = new RGBParser();\nconst hslParser = new HSLParser();\nconst hwbParser = new HWBParser();\nconst cieLabParser = new CIELabParser();\nconst lchParser = new LCHParser();\nconst cmykParser = new CMYKParser();\nconst colorParserContext = new ColorParserContext({\n [ColorModel.HEX]: hexParser,\n [ColorModel.RGB]: rgbParser,\n [ColorModel.HSL]: hslParser,\n [ColorModel.HWB]: hwbParser,\n [ColorModel.CIELab]: cieLabParser,\n [ColorModel.LCH]: lchParser,\n [ColorModel.CMYK]: cmykParser\n});\nconst getOptionsFromColorInput = (options, ...colors) => {\n const cssColors = [];\n const anglesUnits = [];\n const rgbColors = [];\n const labColors = [];\n const lchColors = [];\n const cmykColors = [];\n const alphaValues = [];\n const anglesUnitValues = Object.values(AnglesUnitEnum);\n const colorUnitValues = Object.values(ColorUnitEnum);\n const cmykFunctionValues = Object.values(CMYKFunctionEnum);\n const matchOptions = {\n legacyCSS: 0,\n spacesAfterCommas: 0,\n cmykFunction: 0\n };\n for (const color of colors) {\n if (isString(color)) {\n cssColors.push(color);\n if (color.includes(',')) {\n matchOptions.legacyCSS++;\n const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS);\n if (new Set(commasWithNextCharacter).size === 1 &&\n SPACES.test(commasWithNextCharacter[0].slice(1))) {\n matchOptions.spacesAfterCommas++;\n }\n }\n if (hslParser.supports(color)) {\n const options = hslParser.getCSSOptions(color);\n anglesUnits.push(options.angleUnit);\n alphaValues.push(options.hasPercentageAlpha);\n continue;\n }\n if (hwbParser.supports(color)) {\n const options = hwbParser.getCSSOptions(color);\n anglesUnits.push(options.angleUnit);\n alphaValues.push(options.hasPercentageAlpha);\n continue;\n }\n if (rgbParser.supports(color)) {\n const options = rgbParser.getCSSOptions(color);\n rgbColors.push(options.hasPercentageValues);\n alphaValues.push(options.hasPercentageAlpha);\n continue;\n }\n if (cieLabParser.supports(color)) {\n const options = cieLabParser.getCSSOptions(color);\n labColors.push(options.hasPercentageValues);\n alphaValues.push(options.hasPercentageAlpha);\n continue;\n }\n if (lchParser.supports(color)) {\n const options = lchParser.getCSSOptions(color);\n anglesUnits.push(options.angleUnit);\n lchColors.push(options.hasPercentageValues);\n alphaValues.push(options.hasPercentageAlpha);\n continue;\n }\n if (cmykParser.supports(color)) {\n const options = cmykParser.getCSSOptions(color);\n cmykColors.push(options.hasPercentageValues);\n if (color.startsWith('cmyk')) {\n matchOptions.cmykFunction++;\n }\n alphaValues.push(options.hasPercentageAlpha);\n }\n }\n }\n return {\n decimals: isNumber(options.decimals)\n ? options.decimals\n : DEFAULT_OPTIONS.decimals,\n legacyCSS: isBoolean(options.legacyCSS)\n ? options.legacyCSS\n : Boolean(cssColors.length &&\n matchOptions.legacyCSS === cssColors.length) || DEFAULT_OPTIONS.legacyCSS,\n spacesAfterCommas: isBoolean(options.spacesAfterCommas)\n ? options.spacesAfterCommas\n : Boolean(cssColors.length &&\n matchOptions.spacesAfterCommas === cssColors.length) || DEFAULT_OPTIONS.spacesAfterCommas,\n anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit)\n ? options.anglesUnit\n : (new Set(anglesUnits).size === 1\n ? anglesUnits[0]\n : DEFAULT_OPTIONS.anglesUnit),\n rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit)\n ? options.rgbUnit\n : (new Set(rgbColors).size === 1 && rgbColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.rgbUnit),\n labUnit: options.labUnit && colorUnitValues.includes(options.labUnit)\n ? options.labUnit\n : (new Set(labColors).size === 1 && labColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.labUnit),\n lchUnit: options.lchUnit && colorUnitValues.includes(options.lchUnit)\n ? options.lchUnit\n : (new Set(lchColors).size === 1 && lchColors[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.lchUnit),\n cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit)\n ? options.cmykUnit\n : (new Set(cmykColors).size === 1 && !cmykColors[0]\n ? ColorUnitEnum.NONE\n : DEFAULT_OPTIONS.cmykUnit),\n alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit)\n ? options.alphaUnit\n : (new Set(alphaValues).size === 1 && alphaValues[0]\n ? ColorUnitEnum.PERCENT\n : DEFAULT_OPTIONS.alphaUnit),\n cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction)\n ? options.cmykFunction\n : (cmykColors.length && cmykColors.length === matchOptions.cmykFunction\n ? CMYKFunctionEnum.CMYK\n : DEFAULT_OPTIONS.cmykFunction)\n };\n};\n\n;// ./src/returns/index.ts\n\n\n\n\n\nconst blend = (from, to, steps) => {\n const div = steps - 1;\n const diffR = (to.R - from.R) / div;\n const diffG = (to.G - from.G) / div;\n const diffB = (to.B - from.B) / div;\n const fromA = normalizeAlpha(from.A);\n const toA = normalizeAlpha(to.A);\n const diffA = (toA - fromA) / div;\n return Array(steps).fill(null).map((__n, i) => {\n if (i === 0) {\n return from;\n }\n if (i === div) {\n return to;\n }\n return {\n R: round(from.R + diffR * i),\n G: round(from.G + diffG * i),\n B: round(from.B + diffB * i),\n A: round(fromA + diffA * i)\n };\n });\n};\nfunction getBlendReturn(from, to, model, css, withAlpha, steps = DEFAULT_BLEND_STEPS, options = {}) {\n if (steps < 1)\n steps = DEFAULT_BLEND_STEPS;\n const fromParsed = colorParserContext.parse(from);\n const toParsed = colorParserContext.parse(to);\n const fromRGBObject = getRGB(fromParsed);\n const toRGBObject = getRGB(toParsed);\n const blendArray = blend(fromRGBObject, toRGBObject, steps);\n return blendArray.map((color) => {\n if (css) {\n return colorParserContext.convertCSS(color, model, getOptionsFromColorInput(options, from, to), withAlpha);\n }\n return colorParserContext.convert(color, model, options.decimals, withAlpha);\n });\n}\nconst getBlendReturnParams = (thirdParameter, fourthParameter) => {\n const stepsParameter = isNumber(thirdParameter)\n ? thirdParameter\n : undefined;\n const optionsParameter = isNumber(thirdParameter)\n ? fourthParameter\n : thirdParameter;\n return [\n stepsParameter,\n optionsParameter\n ];\n};\nfunction getMixReturn(colors, model, css, withAlpha, mode = Mix.ADDITIVE, options = {}) {\n const rgbMap = colors.map((color) => {\n return colorParserContext.convert(color, ColorModel.RGB, options.decimals, withAlpha);\n });\n const rybMap = mode === Mix.SUBTRACTIVE\n ? rgbMap.map((color) => {\n const RYB = rgbToRyb(color.R, color.G, color.B);\n if (!isUndefined(color.A)) {\n RYB.A = color.A;\n }\n return RYB;\n })\n : null;\n function createMix(items) {\n const initial = mode === Mix.ADDITIVE\n ? { R: 0, G: 0, B: 0, A: 0 }\n : { R: 0, Y: 0, B: 0, A: 0 };\n return items.reduce((mix, color) => {\n const colorA = isUndefined(color.A)\n ? 1\n : color.A;\n const common = {\n R: Math.min(mix.R + color.R * colorA, BASE_255),\n B: Math.min(mix.B + color.B * colorA, BASE_255),\n A: 1 - (1 - colorA) * (1 - mix.A)\n };\n const mixGY = 'G' in mix\n ? mix.G\n : mix.Y;\n const colorGY = 'G' in color\n ? color.G\n : color.Y;\n return {\n ...common,\n ...(mode === Mix.ADDITIVE\n ? { G: Math.min(mixGY + colorGY * colorA, BASE_255) }\n : { Y: Math.min(mixGY + colorGY * colorA, BASE_255) })\n };\n }, initial);\n }\n let mix;\n if (mode === Mix.ADDITIVE) {\n mix = createMix(rgbMap);\n }\n else {\n const RYB = createMix(rybMap);\n mix = rybToRgb(RYB.R, RYB.Y, RYB.B);\n mix.A = RYB.A;\n }\n if (css) {\n return colorParserContext.convertCSS(mix, model, getOptionsFromColorInput(options, ...colors), withAlpha);\n }\n return colorParserContext.convert(mix, model, options.decimals, withAlpha);\n}\n;\nconst getMixReturnParameters = (secondParameter, thirdParameter) => {\n const modeParam = isString(secondParameter)\n ? secondParameter\n : undefined;\n const optionsParam = isString(secondParameter)\n ? thirdParameter\n : secondParameter;\n return [\n modeParam,\n optionsParam\n ];\n};\nfunction getShadesOrTintsReturn(shades, color, steps = DEFAULT_SHADES_TINTS_STEPS, options = {}) {\n const isCSS = isString(color);\n const parser = colorParserContext.getParser(color);\n const model = parser.model;\n const withAlpha = parser.hasAlpha(color);\n const hsl = colorParserContext.convert(color, ColorModel.HSL, undefined, withAlpha);\n const increment = shades\n ? hsl.L / (steps + 1)\n : (100 - hsl.L) / (steps + 1);\n const hslMap = Array.from(Array(steps)).map((__n, i) => ({\n ...hsl,\n L: hsl.L + increment * (i + 1) * (1 - +shades * 2)\n }));\n if (isCSS) {\n return hslMap.map((hslColor) => {\n return colorParserContext.convertCSS(hslColor, model, getOptionsFromColorInput(options, color), withAlpha);\n });\n }\n return hslMap.map((hslColor) => {\n return colorParserContext.convert(hslColor, model, options.decimals, withAlpha);\n });\n}\nconst getShadesOrTintsReturnParameters = (secondParameter, thirdParameter) => {\n const stepsParam = isNumber(secondParameter)\n ? secondParameter\n : undefined;\n const optionsParam = isNumber(secondParameter)\n ? thirdParameter\n : secondParameter;\n return [\n stepsParam,\n optionsParam\n ];\n};\nconst harmony = (color, angles, mode) => angles.reduce((arr, num) => {\n return [\n ...arr,\n {\n ...color,\n H: mode === Mix.ADDITIVE\n ? normalizeHue(color.H + num)\n : normalizeHue(hueRyb(hueRyb(color.H, false) + num, true))\n }\n ];\n}, [{ ...color }]);\nconst HARMONIES = new Map([\n [\n Harmony.ANALOGOUS,\n (color, mode) => harmony(color, [30, -30], mode)\n ],\n [\n Harmony.COMPLEMENTARY,\n (color, mode) => harmony(color, [180], mode)\n ],\n [\n Harmony.SPLIT_COMPLEMENTARY,\n (color, mode) => harmony(color, [150, -150], mode)\n ],\n [\n Harmony.TRIADIC,\n (color, mode) => harmony(color, [120, -120], mode)\n ],\n [\n Harmony.TETRADIC,\n (color, mode) => harmony(color, [60, -120, 180], mode)\n ],\n [\n Harmony.SQUARE,\n (color, mode) => harmony(color, [90, -90, 180], mode)\n ]\n]);\nconst getHarmonyReturn = (color, harmony, mode, options = {}) => {\n const harmonyFunction = HARMONIES.get(harmony);\n const isCSS = isString(color);\n const parser = colorParserContext.getParser(color);\n const model = parser.model;\n const withAlpha = parser.hasAlpha(color);\n const hsl = colorParserContext.convert(color, ColorModel.HSL);\n const array = harmonyFunction(hsl, mode);\n if (isCSS) {\n return array.map((harmonyColor) => {\n return colorParserContext.convertCSS(harmonyColor, model, getOptionsFromColorInput(options, color), withAlpha);\n });\n }\n return array.map((harmonyColor) => {\n return colorParserContext.convert(harmonyColor, model, options.decimals, withAlpha);\n });\n};\nconst getHarmonyReturnParameters = (secondParam, thirdParam, fourthParam) => {\n if (isHarmony(secondParam)) {\n return [\n secondParam,\n isMix(thirdParam)\n ? thirdParam\n : Mix.ADDITIVE,\n isMix(thirdParam)\n ? fourthParam\n : thirdParam\n ];\n }\n if (isMix(secondParam)) {\n return [\n Harmony.COMPLEMENTARY,\n secondParam,\n thirdParam\n ];\n }\n return [\n Harmony.COMPLEMENTARY,\n Mix.ADDITIVE,\n secondParam\n ];\n};\n\n;// ./src/classes/ColorTranslator.ts\n\n\n\n\n\nclass ColorTranslator {\n constructor(color, options = {}) {\n this._options = getOptionsFromColorInput(options, color);\n const parsedColor = colorParserContext.parse(color);\n const model = getColorModel(parsedColor);\n switch (model) {\n case ColorModel.HSL:\n this.hsl = parsedColor;\n this.update('hsl');\n break;\n case ColorModel.HWB:\n this.hwb = parsedColor;\n this.updateRGBFromHWB();\n this.update('hwb', 'rgb');\n break;\n case ColorModel.CIELab:\n this.lab = parsedColor;\n this.updateRGBFromLAB();\n this.update('lab', 'rgb');\n break;\n case ColorModel.LCH:\n this.lch = parsedColor;\n this.updateRGBFromLCH();\n this.update('lch', 'rgb');\n break;\n case ColorModel.CMYK:\n this.cmyk = parsedColor;\n this.updateRGBFromCMYK();\n this.update('cmyk', 'rgb');\n break;\n default:\n this.rgb = parsedColor;\n this.update('rgb');\n }\n }\n update(...exclude) {\n if (!exclude.includes('rgb')) {\n this.updateRGB();\n }\n if (!exclude.includes('hsl')) {\n this.updateHSL();\n }\n if (!exclude.includes('hwb')) {\n this.updateHWB();\n }\n if (!exclude.includes('lab')) {\n this.updateLAB();\n }\n if (!exclude.includes('lch')) {\n this.updateLCH();\n }\n if (!exclude.includes('cmyk')) {\n this.updateCMYK();\n }\n }\n updateRGB() {\n this.rgb = {\n ...hslToRgb(this.hsl.H, this.hsl.S, this.hsl.L),\n A: this.hsl.A ?? 1\n };\n }\n updateHSL() {\n this.hsl = rgbToHsl(this.rgb.R, this.rgb.G, this.rgb.B, this.rgb.A);\n }\n updateHWB() {\n this.hwb = rgbToHwb(this.rgb.R, this.rgb.G, this.rgb.B, this.rgb.A);\n }\n updateLAB() {\n this.lab = {\n ...rgbToLab(this.rgb.R, this.rgb.G, this.rgb.B),\n A: this.rgb.A ?? 1\n };\n }\n updateLCH() {\n this.lch = {\n ...rgbToLch(this.rgb.R, this.rgb.G, this.rgb.B),\n A: this.rgb.A ?? 1\n };\n }\n updateCMYK() {\n this.cmyk = {\n ...rgbToCmyk(this.rgb.R, this.rgb.G, this.rgb.B),\n A: this.rgb.A ?? 1\n };\n }\n updateRGBFromHWB() {\n this.rgb = {\n ...hwbToRgb(this.hwb.H, this.hwb.W, this.hwb.B),\n A: this.hwb?.A ?? 1\n };\n }\n updateRGBFromLCH() {\n this.rgb = {\n ...lchToRgb(this.lch.L, this.lch.C, this.lch.H),\n A: this.lch.A ?? 1\n };\n }\n updateRGBFromCMYK() {\n this.rgb = {\n ...cmykToRgb(this.cmyk.C, this.cmyk.M, this.cmyk.Y, this.cmyk.K),\n A: this.cmyk.A ?? 1\n };\n }\n updateRGBFromLAB() {\n this.rgb = {\n ...labToRgb(this.lab.L, this.lab.a, this.lab.b),\n A: this.lab.A ?? 1\n };\n }\n updateLCHFromLAB() {\n this.lch = {\n ...labToLch(this.lab.L, this.lab.a, this.lab.b),\n A: this.lab.A\n };\n }\n updateLABromLCH() {\n this.lab = {\n ...lchToLab(this.lch.L, this.lch.C, this.lch.H),\n A: this.lch.A\n };\n }\n setOptions(options = {}) {\n this._options = {\n ...this._options,\n ...options\n };\n return this;\n }\n setR(R) {\n this.rgb.R = minmax(R, 0, BASE_255);\n this.update('rgb');\n return;\n }\n setG(G) {\n this.rgb.G = minmax(G, 0, BASE_255);\n this.update('rgb');\n return this;\n }\n setB(B) {\n this.rgb.B = minmax(B, 0, BASE_255);\n this.update('rgb');\n return this;\n }\n setH(H) {\n this.hsl.H = normalizeHue(H);\n this.update('hsl');\n return this;\n }\n setS(S) {\n this.hsl.S = minmax(S, 0, MAX_PCENT);\n this.update('hsl');\n return this;\n }\n setL(L) {\n this.hsl.L = minmax(L, 0, MAX_PCENT);\n this.update('hsl');\n return this;\n }\n setWhiteness(W) {\n this.hwb.W = minmax(W, 0, MAX_PCENT);\n this.updateRGBFromHWB();\n this.update('rgb', 'hwb');\n return this;\n }\n setBlackness(B) {\n this.hwb.B = minmax(B, 0, MAX_PCENT);\n this.updateRGBFromHWB();\n this.update('rgb', 'hwb');\n return this;\n }\n setCIEL(L) {\n this.lab.L = minmax(L, 0, MAX_PCENT);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setCIEa(a) {\n this.lab.a = minmax(a, -MAX_LAB, MAX_LAB);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setCIEb(b) {\n this.lab.b = minmax(b, -MAX_LAB, MAX_LAB);\n this.updateRGBFromLAB();\n this.updateLCHFromLAB();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHL(l) {\n this.lch.L = minmax(l, 0, MAX_PCENT);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHC(c) {\n this.lch.C = minmax(c, 0, MAX_LCH_C);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setLCHH(h) {\n this.lch.H = normalizeHue(h);\n this.updateRGBFromLCH();\n this.updateLABromLCH();\n this.update('rgb', 'lab', 'lch');\n return this;\n }\n setA(A) {\n const alpha = minmax(A, 0, MAX_ALPHA);\n this.rgb.A = alpha;\n this.hsl.A = alpha;\n this.hwb.A = alpha;\n this.lab.A = alpha;\n this.lch.A = alpha;\n this.cmyk.A = alpha;\n return this;\n }\n setC(C) {\n this.cmyk.C = minmax(C, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setM(M) {\n this.cmyk.M = minmax(M, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setY(Y) {\n this.cmyk.Y = minmax(Y, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n setK(K) {\n this.cmyk.K = minmax(K, 0, 100);\n this.updateRGBFromCMYK();\n this.update('cmyk');\n return this;\n }\n get options() {\n return this._options;\n }\n get R() {\n return round(this.rgb.R, this.options.decimals);\n }\n get G() {\n return round(this.rgb.G, this.options.decimals);\n }\n get B() {\n return round(this.rgb.B, this.options.decimals);\n }\n get H() {\n return round(this.hsl.H, this.options.decimals);\n }\n get S() {\n return round(this.hsl.S, this.options.decimals);\n }\n get L() {\n return round(this.hsl.L, this.options.decimals);\n }\n get Whiteness() {\n return round(this.hwb.W, this.options.decimals);\n }\n get Blackness() {\n return round(this.hwb.B, this.options.decimals);\n }\n get CIEL() {\n return round(this.lab.L, this.options.decimals);\n }\n get CIEa() {\n return round(this.lab.a, this.options.decimals);\n }\n get CIEb() {\n return round(this.lab.b, this.options.decimals);\n }\n get LCHL() {\n return round(this.lch.L, this.options.decimals);\n }\n get LCHC() {\n return round(this.lch.C, this.options.decimals);\n }\n get LCHH() {\n return round(this.lch.H, this.options.decimals);\n }\n get A() {\n return round(this.hsl.A, this.options.decimals);\n }\n get C() {\n return round(this.cmyk.C, this.options.decimals);\n }\n get M() {\n return round(this.cmyk.M, this.options.decimals);\n }\n get Y() {\n return round(this.cmyk.Y, this.options.decimals);\n }\n get K() {\n return round(this.cmyk.K, this.options.decimals);\n }\n get HEXObject() {\n return colorParserContext.convert(this.rgb, ColorModel.HEX);\n }\n get HEXAObject() {\n return colorParserContext.convert(this.rgb, ColorModel.HEX, 0, true);\n }\n get RGBObject() {\n return colorParserContext.convert(this.rgb, ColorModel.RGB, this.options.decimals);\n }\n get RGBAObject() {\n return colorParserContext.convert(this.rgb, ColorModel.RGB, this.options.decimals, true);\n }\n get HSLObject() {\n return colorParserContext.convert(this.hsl, ColorModel.HSL, this.options.decimals);\n }\n get HSLAObject() {\n return colorParserContext.convert(this.hsl, ColorModel.HSL, this.options.decimals, true);\n }\n get HWBObject() {\n return colorParserContext.convert(this.hwb, ColorModel.HWB, this.options.decimals);\n }\n get HWBAObject() {\n return colorParserContext.convert(this.hwb, ColorModel.HWB, this.options.decimals, true);\n }\n get CIELabObject() {\n return colorParserContext.convert(this.lab, ColorModel.CIELab, this.options.decimals);\n }\n get CIELabAObject() {\n return colorParserContext.convert(this.lab, ColorModel.CIELab, this.options.decimals, true);\n }\n get LCHObject() {\n return colorParserContext.convert(this.lch, ColorModel.LCH, this.options.decimals);\n }\n get LCHAObject() {\n return colorParserContext.convert(this.lch, ColorModel.LCH, this.options.decimals, true);\n }\n get CMYKObject() {\n return colorParserContext.convert(this.cmyk, ColorModel.CMYK, this.options.decimals);\n }\n get CMYKAObject() {\n return colorParserContext.convert(this.cmyk, ColorModel.CMYK, this.options.decimals, true);\n }\n get HEX() {\n return colorParserContext.convertCSS(this.rgb, ColorModel.HEX);\n }\n get HEXA() {\n return colorParserContext.convertCSS(this.rgb, ColorModel.HEX, {}, true);\n }\n get RGB() {\n return colorParserContext.convertCSS(this.rgb, ColorModel.RGB, this.options);\n }\n get RGBA() {\n return colorParserContext.convertCSS(this.rgb, ColorModel.RGB, this.options, true);\n }\n get HSL() {\n return colorParserContext.convertCSS(this.hsl, ColorModel.HSL, this.options);\n }\n get HSLA() {\n return colorParserContext.convertCSS(this.hsl, ColorModel.HSL, this.options, true);\n }\n get HWB() {\n return colorParserContext.convertCSS(this.hwb, ColorModel.HWB, this.options);\n }\n get HWBA() {\n return colorParserContext.convertCSS(this.hwb, ColorModel.HWB, this.options, true);\n }\n get CIELab() {\n return colorParserContext.convertCSS(this.lab, ColorModel.CIELab, this.options);\n }\n get CIELabA() {\n return colorParserContext.convertCSS(this.lab, ColorModel.CIELab, this.options, true);\n }\n get LCH() {\n return colorParserContext.convertCSS(this.lch, ColorModel.LCH, this.options);\n }\n get LCHA() {\n return colorParserContext.convertCSS(this.lch, ColorModel.LCH, this.options, true);\n }\n get CMYK() {\n return colorParserContext.convertCSS(this.cmyk, ColorModel.CMYK, this.options);\n }\n get CMYKA() {\n return colorParserContext.convertCSS(this.cmyk, ColorModel.CMYK, this.options, true);\n }\n static toHEXObject(color) {\n return colorParserContext.convert(color, ColorModel.HEX);\n }\n static toHEX(color) {\n return colorParserContext.convertCSS(color, ColorModel.HEX);\n }\n static toHEXAObject(color) {\n return colorParserContext.convert(color, ColorModel.HEX, undefined, true);\n }\n static toHEXA(color) {\n return colorParserContext.convertCSS(color, ColorModel.HEX, undefined, true);\n }\n static toRGBObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.RGB, options.decimals);\n }\n static toRGB(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.RGB, getOptionsFromColorInput(options, color));\n }\n static toRGBAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.RGB, options.decimals, true);\n }\n static toRGBA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.RGB, getOptionsFromColorInput(options, color), true);\n }\n static toHSLObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.HSL, options.decimals);\n }\n static toHSL(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.HSL, getOptionsFromColorInput(options, color));\n }\n static toHSLAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.HSL, options.decimals, true);\n }\n static toHSLA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.HSL, getOptionsFromColorInput(options, color), true);\n }\n static toHWBObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.HWB, options.decimals);\n }\n static toHWB(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.HWB, getOptionsFromColorInput(options, color));\n }\n static toHWBAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.HWB, options.decimals, true);\n }\n static toHWBA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.HWB, getOptionsFromColorInput(options, color), true);\n }\n static toCIELabObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.CIELab, options.decimals);\n }\n static toCIELab(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.CIELab, getOptionsFromColorInput(options, color));\n }\n static toCIELabAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.CIELab, options.decimals, true);\n }\n static toCIELabA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.CIELab, getOptionsFromColorInput(options, color), true);\n }\n static toLCHObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.LCH, options.decimals);\n }\n static toLCH(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.LCH, getOptionsFromColorInput(options, color));\n }\n static toLCHAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.LCH, options.decimals, true);\n }\n static toLCHA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.LCH, getOptionsFromColorInput(options, color), true);\n }\n static toCMYKObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.CMYK, options.decimals);\n }\n static toCMYK(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.CMYK, getOptionsFromColorInput(options, color));\n }\n static toCMYKAObject(color, options = {}) {\n return colorParserContext.convert(color, ColorModel.CMYK, options.decimals, true);\n }\n static toCMYKA(color, options = {}) {\n return colorParserContext.convertCSS(color, ColorModel.CMYK, getOptionsFromColorInput(options, color), true);\n }\n static getBlendHEXObject(from, to, steps) {\n return getBlendReturn(from, to, ColorModel.HEX, false, false, steps);\n }\n static getBlendHEX(from, to, steps) {\n return getBlendReturn(from, to, ColorModel.HEX, true, false, steps);\n }\n static getBlendHEXAObject(from, to, steps) {\n return getBlendReturn(from, to, ColorModel.HEX, false, true, steps);\n }\n static getBlendHEXA(from, to, steps) {\n return getBlendReturn(from, to, ColorModel.HEX, true, true, steps);\n }\n static getBlendRGBObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.RGB, false, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendRGB(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.RGB, true, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendRGBAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.RGB, false, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendRGBA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.RGB, true, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHSLObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HSL, false, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHSL(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HSL, true, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHSLAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HSL, false, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHSLA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HSL, true, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHWBObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HWB, false, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHWB(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HWB, true, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHWBAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HWB, false, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendHWBA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.HWB, true, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendCIELabObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.CIELab, false, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendCIELab(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.CIELab, true, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendCIELabAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.CIELab, false, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendCIELabA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.CIELab, true, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendLCHObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.LCH, false, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendLCH(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.LCH, true, false, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendLCHAObject(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.LCH, false, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getBlendLCHA(from, to, thirdParameter, fourthParameter) {\n return getBlendReturn(from, to, ColorModel.LCH, true, true, ...getBlendReturnParams(thirdParameter, fourthParameter));\n }\n static getMixHEXObject(colors, mode) {\n return getMixReturn(colors, ColorModel.HEX, false, false, mode);\n }\n static getMixHEX(colors, mode = Mix.ADDITIVE) {\n return getMixReturn(colors, ColorModel.HEX, true, false, mode);\n }\n static getMixHEXAObject(colors, mode = Mix.ADDITIVE) {\n return getMixReturn(colors, ColorModel.HEX, false, true, mode);\n }\n static getMixHEXA(colors, mode = Mix.ADDITIVE) {\n return getMixReturn(colors, ColorModel.HEX, true, true, mode);\n }\n static getMixRGBObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.RGB, false, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixRGB(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.RGB, true, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixRGBAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.RGB, false, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixRGBA(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.RGB, true, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHSLObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HSL, false, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHSL(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HSL, true, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHSLAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HSL, false, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHSLA(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HSL, true, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHWBObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HWB, false, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHWB(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HWB, true, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHWBAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HWB, false, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixHWBA(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.HWB, true, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixCIELabObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.CIELab, false, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixCIELab(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.CIELab, true, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixCIELabAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.CIELab, false, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixCIELabA(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.CIELab, true, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixLCHObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.LCH, false, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixLCH(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.LCH, true, false, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixLCHAObject(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.LCH, false, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getMixLCHA(colors, secondParameter, thirdParameter) {\n return getMixReturn(colors, ColorModel.LCH, true, true, ...getMixReturnParameters(secondParameter, thirdParameter));\n }\n static getShades(color, secondParameter, thirdParameter) {\n return getShadesOrTintsReturn(true, color, ...getShadesOrTintsReturnParameters(secondParameter, thirdParameter));\n }\n static getTints(color, secondParameter, thirdParameter) {\n return getShadesOrTintsReturn(false, color, ...getShadesOrTintsReturnParameters(secondParameter, thirdParameter));\n }\n static getHarmony(color, secondParam, thirdParam, fourthParam) {\n return getHarmonyReturn(color, ...getHarmonyReturnParameters(secondParam, thirdParam, fourthParam));\n }\n}\n\n;// ./src/index.ts\n\n\n\n;// ./src/@demo/demo1/index.js\n\n\n/* harmony default export */ const demo1 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const color = new ColorTranslator('hsl(180 100% 50%)', { decimals: 0 });\n\n for (let row = 0; row < 10; row++) {\n\n for (let col = 0; col < 10; col++) {\n\n color\n .setS(row * 10)\n .setL(col * 5 + 30);\n\n const box = document.createElement('div');\n\n box.classList.add('box');\n box.style.background = color.HEX;\n\n box.innerText =\n `R:${color.R}\n G:${color.G}\n B:${color.B}`;\n container.appendChild(box);\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo2/index.js\n\n\n/* harmony default export */ const demo2 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const color = new ColorTranslator({ R: 255, G: 0, B: 0 });\n const hue = [0, 30, 60, 120, 240, 280, 320, 0];\n let rainbow;\n\n for (let r = 0; r < hue.length; r++) {\n\n color.setH(hue[r]);\n\n const bow = document.createElement('div');\n\n bow.classList.add('rainbow');\n bow.style.background = color.HEX;\n\n if (rainbow) {\n rainbow.appendChild(bow);\n } else {\n container.appendChild(bow);\n }\n\n rainbow = bow;\n }\n\n rainbow.style.background = '#333';\n\n return container;\n\n});\n;// ./src/@demo/demo3/index.js\n\n\n/* harmony default export */ const demo3 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const hsl = { H: 0, S: '90%', L: '50%' };\n const hue = [undefined, 55, 30, 0, 290, 220, 130];\n const total = hue.length;\n\n for (let row = 0; row < total; row++) {\n\n for (let col = 0; col < total; col++) {\n\n let index = total - row + col;\n if (index >= total) {\n index -= total;\n }\n hsl.H = hue[index];\n const rgb = hue[index] === undefined\n ? '#FFF'\n : ColorTranslator.toHEX(hsl);\n const box = document.createElement('div');\n\n box.classList.add('flag');\n box.style.background = rgb;\n\n container.appendChild(box);\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo4/index.js\n\n\n/* harmony default export */ const demo4 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const hexColors = [\n '#FE2712', '#FE5409', '#FB9902',\n '#FABD03', '#FFFE32', '#D1EA2C',\n '#66B132', '#0392CE', '#0247FE',\n '#3D00A5', '#8601B0', '#A7194B'\n ];\n\n hexColors.forEach((color) => {\n\n const rgb = ColorTranslator.toRGB(color);\n const hsl = ColorTranslator.toHSL(color, { decimals: 0 });\n const hwb = ColorTranslator.toHWB(color, { decimals: 0 });\n const lab = ColorTranslator.toCIELab(color, { decimals: 0 });\n const lch = ColorTranslator.toLCH(color, { decimals: 0 });\n\n const rgbDiv = document.createElement('div');\n const hslDiv = document.createElement('div');\n const hwbDiv = document.createElement('div');\n const labDiv = document.createElement('div');\n const lchDiv = document.createElement('div');\n\n rgbDiv.style.backgroundColor = rgb;\n rgbDiv.textContent = rgb;\n\n hslDiv.style.backgroundColor = hsl;\n hslDiv.textContent = hsl;\n\n hwbDiv.style.backgroundColor = hwb;\n hwbDiv.textContent = hwb;\n\n labDiv.style.backgroundColor = lab;\n labDiv.textContent = lab;\n\n lchDiv.style.backgroundColor = lch;\n lchDiv.textContent = lch;\n\n container.appendChild(rgbDiv);\n container.appendChild(hslDiv);\n container.appendChild(hwbDiv);\n container.appendChild(labDiv);\n container.appendChild(lchDiv);\n\n });\n\n return container;\n\n});\n;// ./src/@demo/demo5/index.js\n\n\n/* harmony default export */ const demo5 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const colors = [\n 'red',\n 'lime',\n 'blue',\n 'aqua',\n 'yellow',\n 'fuchsia'\n ];\n const total = colors.length;\n\n for (let row = 0; row < total; row++) {\n\n const hsl = ColorTranslator.toHSLObject(colors[row]);\n const step = hsl.S / (total - 1);\n\n for (let col = 0; col < total; col++) {\n\n const rgb = ColorTranslator.toHEX(hsl);\n const cmyk = ColorTranslator.toCMYKObject(hsl, { decimals: 0 });\n\n const box = document.createElement('div');\n box.classList.add('box');\n box.style.background = rgb;\n box.innerText = `C:${cmyk.C}\n M:${cmyk.M}\n Y:${cmyk.Y}\n K:${cmyk.K}`;\n\n container.appendChild(box);\n\n hsl.S -= step;\n\n }\n }\n\n return container;\n\n});\n;// ./src/@demo/demo6/index.js\n\n\n/* harmony default export */ const demo6 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n const rows = 11;\n const mult = 3;\n\n for (let i = 0; i < rows; i++) {\n\n const blends = ColorTranslator.getBlendHEX('#F00', '#FF0', mult + i * mult);\n\n blends.forEach((blend, index) => {\n const box = document.createElement('div');\n box.classList.add('box', `file${i}`);\n box.style.background = blend;\n box.innerText = index + 1;\n container.appendChild(box);\n });\n\n }\n\n return container;\n\n});\n;// ./src/@demo/demo7/index.js\n\n\n/* harmony default export */ const demo7 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n\n const colors = ['#F00', '#FF8000', '#FF0', '#0F0', '#00F', '#A0F', '#F0A'];\n\n const createBox = (color, type) => {\n const box = document.createElement('div');\n box.classList.add('box');\n box.style.backgroundColor = color;\n if (type) box.dataset.type = type;\n container.appendChild(box);\n };\n\n colors.forEach((color) => {\n const shades = ColorTranslator.getShades(color, 3).reverse();\n const tints = ColorTranslator.getTints(color, 3);\n shades.forEach((shade) => createBox(shade, 'shade'));\n createBox(color);\n tints.forEach((tint) => createBox(tint, 'tint'));\n });\n\n return container;\n\n});\n;// ./src/@demo/demo8/index.js\n\n\n\n/* harmony default export */ const demo8 = ((ColorTranslator) => {\n\n const container = document.createElement('div');\n\n const mixes = [\n '#F00',\n '#0F0',\n '#00F',\n [1, 3],\n [1, 2],\n [2, 3],\n [1, 2, 3]\n ];\n\n const fillPlanes = () => {\n const planes = container.querySelectorAll('#planes path');\n planes.forEach((plane, index) => {\n let color = '#CCC';\n if (typeof mixes[index] === 'string') {\n color = mixes[index];\n } else if(mixes[index]) {\n const colors = mixes[index].map((i) => mixes[i - 1]);\n color = mixes[index] = ColorTranslator.getMixHEX(colors);\n }\n plane.setAttribute('fill', color);\n });\n };\n\n fetch('images/color-mixes.svg')\n .then(result => result.text())\n .then((svgCode) => {\n container.innerHTML = svgCode;\n fillPlanes();\n });\n\n return container;\n\n});\n;// ./src/@demo/demo9/index.js\n\n\n/* harmony default export */ const demo9 = ((ColorTranslator, { Mix }) => {\n\n const container = document.createElement('div');\n\n const mixes = [\n '#F00',\n '#FF0',\n '#00F',\n [1, 3],\n [1, 2],\n [2, 3],\n [1, 2, 3]\n ];\n\n const fillPlanes = () => {\n const planes = container.querySelectorAll('#planes path');\n planes.forEach((plane, index) => {\n let color = '#CCC';\n if (typeof mixes[index] === 'string') {\n color = mixes[index];\n } else if(mixes[index]) {\n const colors = mixes[index].map((i) => mixes[i - 1]);\n color = mixes[index] = ColorTranslator.getMixHEX(colors, Mix.SUBTRACTIVE);\n }\n plane.setAttribute('fill', color);\n });\n };\n\n fetch('images/color-mixes.svg')\n .then(result => result.text())\n .then((svgCode) => {\n container.innerHTML = svgCode;\n fillPlanes();\n });\n\n return container;\n\n});\n;// ./src/@demo/demo10/index.js\n\n\n/* harmony default export */ const demo10 = ((ColorTranslator, { Harmony }) => {\n\n const container = document.createElement('div');\n\n const harmonies = [\n { label: 'Complementary', value: Harmony.COMPLEMENTARY },\n { label: 'Split Complementary', value: Harmony.SPLIT_COMPLEMENTARY },\n { label: 'Analogous', value: Harmony.ANALOGOUS },\n { label: 'Triadic', value: Harmony.TRIADIC },\n { label: 'Tetradic', value: Harmony.TETRADIC },\n { label: 'Square', value: Harmony.SQUARE }\n ];\n\n const baseColor = '#F00';\n\n const createElement = (className, parent) => {\n const div = document.createElement('div');\n div.classList.add(className);\n parent.appendChild(div);\n return div;\n };\n\n const createHarmony = (item) => {\n\n const wrapper = createElement('wrapper', container);\n const wheel = createElement('wheel', wrapper);\n const harmony = createElement('harmony', wrapper);\n createElement('label', wrapper).innerText = item.label;\n\n fetch('images/wheel-additive.svg')\n .then(result => result.text())\n .then((svgCode) => {\n const harmonyColors = ColorTranslator.getHarmony(baseColor, item.value);\n const selector = 'path' + harmonyColors.map((color) => `:not([fill=\"${color}\"])`).join('');\n wheel.innerHTML = svgCode;\n harmonyColors.forEach((hex) => createElement('box', harmony).style.background = hex);\n wheel.querySelectorAll(selector).forEach((path) => path.setAttribute('fill-opacity', '0.25'));\n });\n\n };\n\n harmonies.forEach((item) => createHarmony(item));\n\n return container;\n\n});\n;// ./src/@demo/demo11/index.js\n\n\n/* harmony default export */ const demo11 = ((ColorTranslator, { Harmony, Mix }) => {\n\n const container = document.createElement('div');\n\n const harmonies = [\n { label: 'Complementary', value: Harmony.COMPLEMENTARY },\n { label: 'Split Complementary', value: Harmony.SPLIT_COMPLEMENTARY },\n { label: 'Analogous', value: Harmony.ANALOGOUS },\n { label: 'Triadic', value: Harmony.TRIADIC },\n { label: 'Tetradic', value: Harmony.TETRADIC },\n { label: 'Square', value: Harmony.SQUARE }\n ];\n\n const baseColor = '#F00';\n\n const createElement = (className, parent) => {\n const div = document.createElement('div');\n div.classList.add(className);\n parent.appendChild(div);\n return div;\n };\n\n const createHarmony = (item) => {\n\n const wrapper = createElement('wrapper', container);\n const wheel = createElement('wheel', wrapper);\n const harmony = createElement('harmony', wrapper);\n createElement('label', wrapper).innerText = item.label;\n\n fetch('images/wheel-subtractive.svg')\n .then(result => result.text())\n .then((svgCode) => {\n const harmonyColors = ColorTranslator.getHarmony(baseColor, item.value, Mix.SUBTRACTIVE);\n const selector = 'path' + harmonyColors.map((color) => `:not([fill=\"${color}\"])`).join('');\n wheel.innerHTML = svgCode;\n harmonyColors.forEach((hex) => createElement('box', harmony).style.background = hex);\n wheel.querySelectorAll(selector).forEach((path) => path.setAttribute('fill-opacity', '0.25'));\n });\n\n };\n\n harmonies.forEach((item) => createHarmony(item));\n\n return container;\n\n});\n;// ./src/@demo/demo.js\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nconst functioToString = (fn) => {\n const article = document.createElement('article');\n const pre = document.createElement('pre');\n article.classList.add('function-container');\n pre.classList.add('prettyprint');\n article.appendChild(pre);\n pre.innerHTML = fn.toString().replace('(ColorTranslator)', '()');\n return article;\n};\n\nconst demos = new Map([\n ['demo1', demo1],\n ['demo2', demo2],\n ['demo3', demo3],\n ['demo4', demo4],\n ['demo5', demo5],\n ['demo6', demo6],\n ['demo7', demo7],\n ['demo8', demo8],\n ['demo9', demo9],\n ['demo10', demo10],\n ['demo11', demo11]\n]);\n\ndocument.addEventListener('DOMContentLoaded', () => {\n demos.forEach((module, div) => {\n const demo = document.getElementById(div);\n const container = document.createElement('div');\n const wrapper = document.createElement('div');\n\n container.classList.add('demo-container');\n wrapper.classList.add('demo-wrapper');\n\n wrapper.appendChild(module(ColorTranslator, { Harmony: Harmony, Mix: Mix }));\n container.appendChild(wrapper);\n demo.appendChild(container);\n demo.appendChild(functioToString(module));\n });\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTE3LmpzIiwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxxQkFBTSxvQkFBb0IscUJBQU07QUFDMUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYztBQUNkO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQkFBa0IsaUJBQWlCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JELFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUiw0RUFBNEU7QUFDNUU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7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QjtBQUNwQjtBQUNQO0FBQ0E7QUFDQTtBQUNBLENBQUMsa0JBQWtCO0FBQ1o7QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQyxzQ0FBc0M7OztBQzlLRjtBQUM5QjtBQUNQLEtBQUssVUFBVSxpRkFBaUYsRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRTtBQUNySixLQUFLLFVBQVU7QUFDZixL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QUNBLFVBQVUsNERBQTREO0FBQ3RFLFVBQVUsa0VBQWtFO0FBQzVFLFVBQVUsd0RBQXdEO0FBQ2xFLFVBQVUsc0RBQXNEO0FBQ2hFLFVBQVUsdURBQXVEO0FBQ2pFLFVBQVU7QUFDVjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzRkFBc0YsTUFBTTtBQUM1RjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViOztBQUVBOztBQUVBOztBQUVBLENBQUMsRTs7QUMvQ3FFO0FBQ0E7QUFDSDtBQUM3QztBQUNDO0FBQzZCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNFO0FBQ0E7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGVBQWUsTUFBTTtBQUNyQixlQUFlLE1BQU07QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG1DQUFtQyxlQUFlLElBQUksT0FBTyxjQUFLLE9BQUU7QUFDcEU7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9ub2RlX21vZHVsZXMvLnBucG0vd2hhdHdnLWZldGNoQDMuNi4yMC9ub2RlX21vZHVsZXMvd2hhdHdnLWZldGNoL2ZldGNoLmpzP2Q0Y2IiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0B0eXBlcy9pbmRleC50cz9lNGJkIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb25zdGFudHMvZW51bXMudHM/NjRmYiIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvY29uc3RhbnRzL3JlZ2V4cHMudHM/ODU2ZSIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvY29uc3RhbnRzL2luZGV4LnRzPzY2MWMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL3V0aWxpdGllcy9pbmRleC50cz9kMTJlIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb2xvci90cmFuc2xhdG9ycy50cz8yNTU5Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0NvbG9yUGFyc2VyQ29udGV4dC50cz8xZGI0Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jb2xvci9yZ2IudHM/M2UyNiIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvY3NzL2luZGV4LnRzPzIwOGYiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2NsYXNzZXMvSEVYUGFyc2VyLnRzPzY2ZWEiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2NsYXNzZXMvQ2FsY1BhcnNlci50cz8zN2FjIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL1JHQlBhcnNlci50cz83MzU5Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0hTTFBhcnNlci50cz8wYTlmIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0hXQlBhcnNlci50cz9kMTc2Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0NJRUxhYlBhcnNlci50cz82NDlkIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0xDSFBhcnNlci50cz9hNTRkIiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9jbGFzc2VzL0NNWUtQYXJzZXIudHM/OGI3MyIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvcGFyc2Vycy9pbmRleC50cz80MDE0Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9yZXR1cm5zL2luZGV4LnRzPzE3ZDQiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2NsYXNzZXMvQ29sb3JUcmFuc2xhdG9yLnRzPzE2ZTMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL2luZGV4LnRzP2E1OGYiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW8xL2luZGV4LmpzPzM5NjUiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW8yL2luZGV4LmpzP2Q4ZGMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW8zL2luZGV4LmpzP2QzODYiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW80L2luZGV4LmpzPzYxOWYiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW81L2luZGV4LmpzP2Q4Y2MiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW82L2luZGV4LmpzPzNhMzIiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW83L2luZGV4LmpzPzgzNDMiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW84L2luZGV4LmpzPzc3MjUiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW85L2luZGV4LmpzPzg1MzIiLCJ3ZWJwYWNrOi8vY29sb3J0cmFuc2xhdG9yLy4vc3JjL0BkZW1vL2RlbW8xMC9pbmRleC5qcz80ZjY3Iiwid2VicGFjazovL2NvbG9ydHJhbnNsYXRvci8uL3NyYy9AZGVtby9kZW1vMTEvaW5kZXguanM/ZGJlNiIsIndlYnBhY2s6Ly9jb2xvcnRyYW5zbGF0b3IvLi9zcmMvQGRlbW8vZGVtby5qcz85YjdkIl0sInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvdHlwZS1idWlsdGlucyAqL1xudmFyIGcgPVxuICAodHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnICYmIGdsb2JhbFRoaXMpIHx8XG4gICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcgJiYgc2VsZikgfHxcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVmXG4gICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyAmJiBnbG9iYWwpIHx8XG4gIHt9XG5cbnZhciBzdXBwb3J0ID0ge1xuICBzZWFyY2hQYXJhbXM6ICdVUkxTZWFyY2hQYXJhbXMnIGluIGcsXG4gIGl0ZXJhYmxlOiAnU3ltYm9sJyBpbiBnICYmICdpdGVyYXRvcicgaW4gU3ltYm9sLFxuICBibG9iOlxuICAgICdGaWxlUmVhZGVyJyBpbiBnICYmXG4gICAgJ0Jsb2InIGluIGcgJiZcbiAgICAoZnVuY3Rpb24oKSB7XG4gICAgICB0cnkge1xuICAgICAgICBuZXcgQmxvYigpXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgfVxuICAgIH0pKCksXG4gIGZvcm1EYXRhOiAnRm9ybURhdGEnIGluIGcsXG4gIGFycmF5QnVmZmVyOiAnQXJyYXlCdWZmZXInIGluIGdcbn1cblxuZnVuY3Rpb24gaXNEYXRhVmlldyhvYmopIHtcbiAgcmV0dXJuIG9iaiAmJiBEYXRhVmlldy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihvYmopXG59XG5cbmlmIChzdXBwb3J0LmFycmF5QnVmZmVyKSB7XG4gIHZhciB2aWV3Q2xhc3NlcyA9IFtcbiAgICAnW29iamVjdCBJbnQ4QXJyYXldJyxcbiAgICAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgJ1tvYmplY3QgVWludDE2QXJyYXldJyxcbiAgICAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgJ1tvYmplY3QgVWludDMyQXJyYXldJyxcbiAgICAnW29iamVjdCBGbG9hdDMyQXJyYXldJyxcbiAgICAnW29iamVjdCBGbG9hdDY0QXJyYXldJ1xuICBdXG5cbiAgdmFyIGlzQXJyYXlCdWZmZXJWaWV3ID1cbiAgICBBcnJheUJ1ZmZlci5pc1ZpZXcgfHxcbiAgICBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogJiYgdmlld0NsYXNzZXMuaW5kZXhPZihPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSkgPiAtMVxuICAgIH1cbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplTmFtZShuYW1lKSB7XG4gIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICBuYW1lID0gU3RyaW5nKG5hbWUpXG4gIH1cbiAgaWYgKC9bXmEtejAtOVxcLSMkJSYnKisuXl9gfH4hXS9pLnRlc3QobmFtZSkgfHwgbmFtZSA9PT0gJycpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGNoYXJhY3RlciBpbiBoZWFkZXIgZmllbGQgbmFtZTogXCInICsgbmFtZSArICdcIicpXG4gIH1cbiAgcmV0dXJuIG5hbWUudG9Mb3dlckNhc2UoKVxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVWYWx1ZSh2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykge1xuICAgIHZhbHVlID0gU3RyaW5nKHZhbHVlKVxuICB9XG4gIHJldHVybiB2YWx1ZVxufVxuXG4vLyBCdWlsZCBhIGRlc3RydWN0aXZlIGl0ZXJhdG9yIGZvciB0aGUgdmFsdWUgbGlzdFxuZnVuY3Rpb24gaXRlcmF0b3JGb3IoaXRlbXMpIHtcbiAgdmFyIGl0ZXJhdG9yID0ge1xuICAgIG5leHQ6IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHZhbHVlID0gaXRlbXMuc2hpZnQoKVxuICAgICAgcmV0dXJuIHtkb25lOiB2YWx1ZSA9PT0gdW5kZWZpbmVkLCB2YWx1ZTogdmFsdWV9XG4gICAgfVxuICB9XG5cbiAgaWYgKHN1cHBvcnQuaXRlcmFibGUpIHtcbiAgICBpdGVyYXRvcltTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gaXRlcmF0b3JcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaXRlcmF0b3Jcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEhlYWRlcnMoaGVhZGVycykge1xuICB0aGlzLm1hcCA9IHt9XG5cbiAgaWYgKGhlYWRlcnMgaW5zdGFuY2VvZiBIZWFkZXJzKSB7XG4gICAgaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7XG4gICAgICB0aGlzLmFwcGVuZChuYW1lLCB2YWx1ZSlcbiAgICB9LCB0aGlzKVxuICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoaGVhZGVycykpIHtcbiAgICBoZWFkZXJzLmZvckVhY2goZnVuY3Rpb24oaGVhZGVyKSB7XG4gICAgICBpZiAoaGVhZGVyLmxlbmd0aCAhPSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0hlYWRlcnMgY29uc3RydWN0b3I6IGV4cGVjdGVkIG5hbWUvdmFsdWUgcGFpciB0byBiZSBsZW5ndGggMiwgZm91bmQnICsgaGVhZGVyLmxlbmd0aClcbiAgICAgIH1cbiAgICAgIHRoaXMuYXBwZW5kKGhlYWRlclswXSwgaGVhZGVyWzFdKVxuICAgIH0sIHRoaXMpXG4gIH0gZWxzZSBpZiAoaGVhZGVycykge1xuICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGhlYWRlcnMpLmZvckVhY2goZnVuY3Rpb24obmFtZSkge1xuICAgICAgdGhpcy5hcHBlbmQobmFtZSwgaGVhZGVyc1tuYW1lXSlcbiAgICB9LCB0aGlzKVxuICB9XG59XG5cbkhlYWRlcnMucHJvdG90eXBlLmFwcGVuZCA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gIG5hbWUgPSBub3JtYWxpemVOYW1lKG5hbWUpXG4gIHZhbHVlID0gbm9ybWFsaXplVmFsdWUodmFsdWUpXG4gIHZhciBvbGRWYWx1ZSA9IHRoaXMubWFwW25hbWVdXG4gIHRoaXMubWFwW25hbWVdID0gb2xkVmFsdWUgPyBvbGRWYWx1ZSArICcsICcgKyB2YWx1ZSA6IHZhbHVlXG59XG5cbkhlYWRlcnMucHJvdG90eXBlWydkZWxldGUnXSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgZGVsZXRlIHRoaXMubWFwW25vcm1hbGl6ZU5hbWUobmFtZSldXG59XG5cbkhlYWRlcnMucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgbmFtZSA9IG5vcm1hbGl6ZU5hbWUobmFtZSlcbiAgcmV0dXJuIHRoaXMuaGFzKG5hbWUpID8gdGhpcy5tYXBbbmFtZV0gOiBudWxsXG59XG5cbkhlYWRlcnMucHJvdG90eXBlLmhhcyA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgcmV0dXJuIHRoaXMubWFwLmhhc093blByb3BlcnR5KG5vcm1hbGl6ZU5hbWUobmFtZSkpXG59XG5cbkhlYWRlcnMucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gIHRoaXMubWFwW25vcm1hbGl6ZU5hbWUobmFtZSldID0gbm9ybWFsaXplVmFsdWUodmFsdWUpXG59XG5cbkhlYWRlcnMucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbihjYWxsYmFjaywgdGhpc0FyZykge1xuICBmb3IgKHZhciBuYW1lIGluIHRoaXMubWFwKSB7XG4gICAgaWYgKHRoaXMubWFwLmhhc093blByb3BlcnR5KG5hbWUpKSB7XG4gICAgICBjYWxsYmFjay5jYWxsKHRoaXNBcmcsIHRoaXMubWFwW25hbWVdLCBuYW1lLCB0aGlzKVxuICAgIH1cbiAgfVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5rZXlzID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpdGVtcyA9IFtdXG4gIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgIGl0ZW1zLnB1c2gobmFtZSlcbiAgfSlcbiAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS52YWx1ZXMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGl0ZW1zID0gW11cbiAgdGhpcy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgaXRlbXMucHVzaCh2YWx1ZSlcbiAgfSlcbiAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxufVxuXG5IZWFkZXJzLnByb3RvdHlwZS5lbnRyaWVzID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpdGVtcyA9IFtdXG4gIHRoaXMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgIGl0ZW1zLnB1c2goW25hbWUsIHZhbHVlXSlcbiAgfSlcbiAgcmV0dXJuIGl0ZXJhdG9yRm9yKGl0ZW1zKVxufVxuXG5pZiAoc3VwcG9ydC5pdGVyYWJsZSkge1xuICBIZWFkZXJzLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gSGVhZGVycy5wcm90b3R5cGUuZW50cmllc1xufVxuXG5mdW5jdGlvbiBjb25zdW1lZChib2R5KSB7XG4gIGlmIChib2R5Ll9ub0JvZHkpIHJldHVyblxuICBpZiAoYm9keS5ib2R5VXNlZCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKCdBbHJlYWR5IHJlYWQnKSlcbiAgfVxuICBib2R5LmJvZHlVc2VkID0gdHJ1ZVxufVxuXG5mdW5jdGlvbiBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QpIHtcbiAgICByZWFkZXIub25sb2FkID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXNvbHZlKHJlYWRlci5yZXN1bHQpXG4gICAgfVxuICAgIHJlYWRlci5vbmVycm9yID0gZnVuY3Rpb24oKSB7XG4gICAgICByZWplY3QocmVhZGVyLmVycm9yKVxuICAgIH1cbiAgfSlcbn1cblxuZnVuY3Rpb24gcmVhZEJsb2JBc0FycmF5QnVmZmVyKGJsb2IpIHtcbiAgdmFyIHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKClcbiAgdmFyIHByb21pc2UgPSBmaWxlUmVhZGVyUmVhZHkocmVhZGVyKVxuICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoYmxvYilcbiAgcmV0dXJuIHByb21pc2Vcbn1cblxuZnVuY3Rpb24gcmVhZEJsb2JBc1RleHQoYmxvYikge1xuICB2YXIgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKVxuICB2YXIgcHJvbWlzZSA9IGZpbGVSZWFkZXJSZWFkeShyZWFkZXIpXG4gIHZhciBtYXRjaCA9IC9jaGFyc2V0PShbQS1aYS16MC05Xy1dKykvLmV4ZWMoYmxvYi50eXBlKVxuICB2YXIgZW5jb2RpbmcgPSBtYXRjaCA/IG1hdGNoWzFdIDogJ3V0Zi04J1xuICByZWFkZXIucmVhZEFzVGV4dChibG9iLCBlbmNvZGluZylcbiAgcmV0dXJuIHByb21pc2Vcbn1cblxuZnVuY3Rpb24gcmVhZEFycmF5QnVmZmVyQXNUZXh0KGJ1Zikge1xuICB2YXIgdmlldyA9IG5ldyBVaW50OEFycmF5KGJ1ZilcbiAgdmFyIGNoYXJzID0gbmV3IEFycmF5KHZpZXcubGVuZ3RoKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdmlldy5sZW5ndGg7IGkrKykge1xuICAgIGNoYXJzW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZSh2aWV3W2ldKVxuICB9XG4gIHJldHVybiBjaGFycy5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBidWZmZXJDbG9uZShidWYpIHtcbiAgaWYgKGJ1Zi5zbGljZSkge1xuICAgIHJldHVybiBidWYuc2xpY2UoMClcbiAgfSBlbHNlIHtcbiAgICB2YXIgdmlldyA9IG5ldyBVaW50OEFycmF5KGJ1Zi5ieXRlTGVuZ3RoKVxuICAgIHZpZXcuc2V0KG5ldyBVaW50OEFycmF5KGJ1ZikpXG4gICAgcmV0dXJuIHZpZXcuYnVmZmVyXG4gIH1cbn1cblxuZnVuY3Rpb24gQm9keSgpIHtcbiAgdGhpcy5ib2R5VXNlZCA9IGZhbHNlXG5cbiAgdGhpcy5faW5pdEJvZHkgPSBmdW5jdGlvbihib2R5KSB7XG4gICAgLypcbiAgICAgIGZldGNoLW1vY2sgd3JhcHMgdGhlIFJlc3BvbnNlIG9iamVjdCBpbiBhbiBFUzYgUHJveHkgdG9cbiAgICAgIHByb3ZpZGUgdXNlZnVsIHRlc3QgaGFybmVzcyBmZWF0dXJlcyBzdWNoIGFzIGZsdXNoLiBIb3dldmVyLCBvblxuICAgICAgRVM1IGJyb3dzZXJzIHdpdGhvdXQgZmV0Y2ggb3IgUHJveHkgc3VwcG9ydCBwb2xseWZpbGxzIG11c3QgYmUgdXNlZDtcbiAgICAgIHRoZSBwcm94eS1wb2xseWZpbGwgaXMgdW5hYmxlIHRvIHByb3h5IGFuIGF0dHJpYnV0ZSB1bmxlc3MgaXQgZXhpc3RzXG4gICAgICBvbiB0aGUgb2JqZWN0IGJlZm9yZSB0aGUgUHJveHkgaXMgY3JlYXRlZC4gVGhpcyBjaGFuZ2UgZW5zdXJlc1xuICAgICAgUmVzcG9uc2UuYm9keVVzZWQgZXhpc3RzIG9uIHRoZSBpbnN0YW5jZSwgd2hpbGUgbWFpbnRhaW5pbmcgdGhlXG4gICAgICBzZW1hbnRpYyBvZiBzZXR0aW5nIFJlcXVlc3QuYm9keVVzZWQgaW4gdGhlIGNvbnN0cnVjdG9yIGJlZm9yZVxuICAgICAgX2luaXRCb2R5IGlzIGNhbGxlZC5cbiAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWFzc2lnblxuICAgIHRoaXMuYm9keVVzZWQgPSB0aGlzLmJvZHlVc2VkXG4gICAgdGhpcy5fYm9keUluaXQgPSBib2R5XG4gICAgaWYgKCFib2R5KSB7XG4gICAgICB0aGlzLl9ub0JvZHkgPSB0cnVlO1xuICAgICAgdGhpcy5fYm9keVRleHQgPSAnJ1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aGlzLl9ib2R5VGV4dCA9IGJvZHlcbiAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYmxvYiAmJiBCbG9iLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICB0aGlzLl9ib2R5QmxvYiA9IGJvZHlcbiAgICB9IGVsc2UgaWYgKHN1cHBvcnQuZm9ybURhdGEgJiYgRm9ybURhdGEucHJvdG90eXBlLmlzUHJvdG90eXBlT2YoYm9keSkpIHtcbiAgICAgIHRoaXMuX2JvZHlGb3JtRGF0YSA9IGJvZHlcbiAgICB9IGVsc2UgaWYgKHN1cHBvcnQuc2VhcmNoUGFyYW1zICYmIFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSkge1xuICAgICAgdGhpcy5fYm9keVRleHQgPSBib2R5LnRvU3RyaW5nKClcbiAgICB9IGVsc2UgaWYgKHN1cHBvcnQuYXJyYXlCdWZmZXIgJiYgc3VwcG9ydC5ibG9iICYmIGlzRGF0YVZpZXcoYm9keSkpIHtcbiAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlciA9IGJ1ZmZlckNsb25lKGJvZHkuYnVmZmVyKVxuICAgICAgLy8gSUUgMTAtMTEgY2FuJ3QgaGFuZGxlIGEgRGF0YVZpZXcgYm9keS5cbiAgICAgIHRoaXMuX2JvZHlJbml0ID0gbmV3IEJsb2IoW3RoaXMuX2JvZHlBcnJheUJ1ZmZlcl0pXG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LmFycmF5QnVmZmVyICYmIChBcnJheUJ1ZmZlci5wcm90b3R5cGUuaXNQcm90b3R5cGVPZihib2R5KSB8fCBpc0FycmF5QnVmZmVyVmlldyhib2R5KSkpIHtcbiAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlciA9IGJ1ZmZlckNsb25lKGJvZHkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2JvZHlUZXh0ID0gYm9keSA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChib2R5KVxuICAgIH1cblxuICAgIGlmICghdGhpcy5oZWFkZXJzLmdldCgnY29udGVudC10eXBlJykpIHtcbiAgICAgIGlmICh0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgJ3RleHQvcGxhaW47Y2hhcnNldD1VVEYtOCcpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlCbG9iICYmIHRoaXMuX2JvZHlCbG9iLnR5cGUpIHtcbiAgICAgICAgdGhpcy5oZWFkZXJzLnNldCgnY29udGVudC10eXBlJywgdGhpcy5fYm9keUJsb2IudHlwZSlcbiAgICAgIH0gZWxzZSBpZiAoc3VwcG9ydC5zZWFyY2hQYXJhbXMgJiYgVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZS5pc1Byb3RvdHlwZU9mKGJvZHkpKSB7XG4gICAgICAgIHRoaXMuaGVhZGVycy5zZXQoJ2NvbnRlbnQtdHlwZScsICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7Y2hhcnNldD1VVEYtOCcpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHN1cHBvcnQuYmxvYikge1xuICAgIHRoaXMuYmxvYiA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICAgIGlmIChyZWplY3RlZCkge1xuICAgICAgICByZXR1cm4gcmVqZWN0ZWRcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2JvZHlCbG9iKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keUJsb2IpXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuX2JvZHlBcnJheUJ1ZmZlcikge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBCbG9iKFt0aGlzLl9ib2R5QXJyYXlCdWZmZXJdKSlcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY291bGQgbm90IHJlYWQgRm9ybURhdGEgYm9keSBhcyBibG9iJylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IEJsb2IoW3RoaXMuX2JvZHlUZXh0XSkpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhpcy5hcnJheUJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpIHtcbiAgICAgIHZhciBpc0NvbnN1bWVkID0gY29uc3VtZWQodGhpcylcbiAgICAgIGlmIChpc0NvbnN1bWVkKSB7XG4gICAgICAgIHJldHVybiBpc0NvbnN1bWVkXG4gICAgICB9IGVsc2UgaWYgKEFycmF5QnVmZmVyLmlzVmlldyh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoXG4gICAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyLmJ1ZmZlci5zbGljZShcbiAgICAgICAgICAgIHRoaXMuX2JvZHlBcnJheUJ1ZmZlci5ieXRlT2Zmc2V0LFxuICAgICAgICAgICAgdGhpcy5fYm9keUFycmF5QnVmZmVyLmJ5dGVPZmZzZXQgKyB0aGlzLl9ib2R5QXJyYXlCdWZmZXIuYnl0ZUxlbmd0aFxuICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChzdXBwb3J0LmJsb2IpIHtcbiAgICAgIHJldHVybiB0aGlzLmJsb2IoKS50aGVuKHJlYWRCbG9iQXNBcnJheUJ1ZmZlcilcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjb3VsZCBub3QgcmVhZCBhcyBBcnJheUJ1ZmZlcicpXG4gICAgfVxuICB9XG5cbiAgdGhpcy50ZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHJlamVjdGVkID0gY29uc3VtZWQodGhpcylcbiAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgIHJldHVybiByZWplY3RlZFxuICAgIH1cblxuICAgIGlmICh0aGlzLl9ib2R5QmxvYikge1xuICAgICAgcmV0dXJuIHJlYWRCbG9iQXNUZXh0KHRoaXMuX2JvZHlCbG9iKVxuICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHJlYWRBcnJheUJ1ZmZlckFzVGV4dCh0aGlzLl9ib2R5QXJyYXlCdWZmZXIpKVxuICAgIH0gZWxzZSBpZiAodGhpcy5fYm9keUZvcm1EYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCByZWFkIEZvcm1EYXRhIGJvZHkgYXMgdGV4dCcpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5fYm9keVRleHQpXG4gICAgfVxuICB9XG5cbiAgaWYgKHN1cHBvcnQuZm9ybURhdGEpIHtcbiAgICB0aGlzLmZvcm1EYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy50ZXh0KCkudGhlbihkZWNvZGUpXG4gICAgfVxuICB9XG5cbiAgdGhpcy5qc29uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudGV4dCgpLnRoZW4oSlNPTi5wYXJzZSlcbiAgfVxuXG4gIHJldHVybiB0aGlzXG59XG5cbi8vIEhUVFAgbWV0aG9kcyB3aG9zZSBjYXBpdGFsaXphdGlvbiBzaG91bGQgYmUgbm9ybWFsaXplZFxudmFyIG1ldGhvZHMgPSBbJ0NPTk5FQ1QnLCAnREVMRVRFJywgJ0dFVCcsICdIRUFEJywgJ09QVElPTlMnLCAnUEFUQ0gnLCAnUE9TVCcsICdQVVQnLCAnVFJBQ0UnXVxuXG5mdW5jdGlvbiBub3JtYWxpemVNZXRob2QobWV0aG9kKSB7XG4gIHZhciB1cGNhc2VkID0gbWV0aG9kLnRvVXBwZXJDYXNlKClcbiAgcmV0dXJuIG1ldGhvZHMuaW5kZXhPZih1cGNhc2VkKSA+IC0xID8gdXBjYXNlZCA6IG1ldGhvZFxufVxuXG5leHBvcnQgZnVuY3Rpb24gUmVxdWVzdChpbnB1dCwgb3B0aW9ucykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmVxdWVzdCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdQbGVhc2UgdXNlIHRoZSBcIm5ld1wiIG9wZXJhdG9yLCB0aGlzIERPTSBvYmplY3QgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLicpXG4gIH1cblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fVxuICB2YXIgYm9keSA9IG9wdGlvbnMuYm9keVxuXG4gIGlmIChpbnB1dCBpbnN0YW5jZW9mIFJlcXVlc3QpIHtcbiAgICBpZiAoaW5wdXQuYm9keVVzZWQpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FscmVhZHkgcmVhZCcpXG4gICAgfVxuICAgIHRoaXMudXJsID0gaW5wdXQudXJsXG4gICAgdGhpcy5jcmVkZW50aWFscyA9IGlucHV0LmNyZWRlbnRpYWxzXG4gICAgaWYgKCFvcHRpb25zLmhlYWRlcnMpIHtcbiAgICAgIHRoaXMuaGVhZGVycyA9IG5ldyBIZWFkZXJzKGlucHV0LmhlYWRlcnMpXG4gICAgfVxuICAgIHRoaXMubWV0aG9kID0gaW5wdXQubWV0aG9kXG4gICAgdGhpcy5tb2RlID0gaW5wdXQubW9kZVxuICAgIHRoaXMuc2lnbmFsID0gaW5wdXQuc2lnbmFsXG4gICAgaWYgKCFib2R5ICYmIGlucHV0Ll9ib2R5SW5pdCAhPSBudWxsKSB7XG4gICAgICBib2R5ID0gaW5wdXQuX2JvZHlJbml0XG4gICAgICBpbnB1dC5ib2R5VXNlZCA9IHRydWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhpcy51cmwgPSBTdHJpbmcoaW5wdXQpXG4gIH1cblxuICB0aGlzLmNyZWRlbnRpYWxzID0gb3B0aW9ucy5jcmVkZW50aWFscyB8fCB0aGlzLmNyZWRlbnRpYWxzIHx8ICdzYW1lLW9yaWdpbidcbiAgaWYgKG9wdGlvbnMuaGVhZGVycyB8fCAhdGhpcy5oZWFkZXJzKSB7XG4gICAgdGhpcy5oZWFkZXJzID0gbmV3IEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKVxuICB9XG4gIHRoaXMubWV0aG9kID0gbm9ybWFsaXplTWV0aG9kKG9wdGlvbnMubWV0aG9kIHx8IHRoaXMubWV0aG9kIHx8ICdHRVQnKVxuICB0aGlzLm1vZGUgPSBvcHRpb25zLm1vZGUgfHwgdGhpcy5tb2RlIHx8IG51bGxcbiAgdGhpcy5zaWduYWwgPSBvcHRpb25zLnNpZ25hbCB8fCB0aGlzLnNpZ25hbCB8fCAoZnVuY3Rpb24gKCkge1xuICAgIGlmICgnQWJvcnRDb250cm9sbGVyJyBpbiBnKSB7XG4gICAgICB2YXIgY3RybCA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICAgIHJldHVybiBjdHJsLnNpZ25hbDtcbiAgICB9XG4gIH0oKSk7XG4gIHRoaXMucmVmZXJyZXIgPSBudWxsXG5cbiAgaWYgKCh0aGlzLm1ldGhvZCA9PT0gJ0dFVCcgfHwgdGhpcy5tZXRob2QgPT09ICdIRUFEJykgJiYgYm9keSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0JvZHkgbm90IGFsbG93ZWQgZm9yIEdFVCBvciBIRUFEIHJlcXVlc3RzJylcbiAgfVxuICB0aGlzLl9pbml0Qm9keShib2R5KVxuXG4gIGlmICh0aGlzLm1ldGhvZCA9PT0gJ0dFVCcgfHwgdGhpcy5tZXRob2QgPT09ICdIRUFEJykge1xuICAgIGlmIChvcHRpb25zLmNhY2hlID09PSAnbm8tc3RvcmUnIHx8IG9wdGlvbnMuY2FjaGUgPT09ICduby1jYWNoZScpIHtcbiAgICAgIC8vIFNlYXJjaCBmb3IgYSAnXycgcGFyYW1ldGVyIGluIHRoZSBxdWVyeSBzdHJpbmdcbiAgICAgIHZhciByZVBhcmFtU2VhcmNoID0gLyhbPyZdKV89W14mXSovXG4gICAgICBpZiAocmVQYXJhbVNlYXJjaC50ZXN0KHRoaXMudXJsKSkge1xuICAgICAgICAvLyBJZiBpdCBhbHJlYWR5IGV4aXN0cyB0aGVuIHNldCB0aGUgdmFsdWUgd2l0aCB0aGUgY3VycmVudCB0aW1lXG4gICAgICAgIHRoaXMudXJsID0gdGhpcy51cmwucmVwbGFjZShyZVBhcmFtU2VhcmNoLCAnJDFfPScgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE90aGVyd2lzZSBhZGQgYSBuZXcgJ18nIHBhcmFtZXRlciB0byB0aGUgZW5kIHdpdGggdGhlIGN1cnJlbnQgdGltZVxuICAgICAgICB2YXIgcmVRdWVyeVN0cmluZyA9IC9cXD8vXG4gICAgICAgIHRoaXMudXJsICs9IChyZVF1ZXJ5U3RyaW5nLnRlc3QodGhpcy51cmwpID8gJyYnIDogJz8nKSArICdfPScgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5SZXF1ZXN0LnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbmV3IFJlcXVlc3QodGhpcywge2JvZHk6IHRoaXMuX2JvZHlJbml0fSlcbn1cblxuZnVuY3Rpb24gZGVjb2RlKGJvZHkpIHtcbiAgdmFyIGZvcm0gPSBuZXcgRm9ybURhdGEoKVxuICBib2R5XG4gICAgLnRyaW0oKVxuICAgIC5zcGxpdCgnJicpXG4gICAgLmZvckVhY2goZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAgIGlmIChieXRlcykge1xuICAgICAgICB2YXIgc3BsaXQgPSBieXRlcy5zcGxpdCgnPScpXG4gICAgICAgIHZhciBuYW1lID0gc3BsaXQuc2hpZnQoKS5yZXBsYWNlKC9cXCsvZywgJyAnKVxuICAgICAgICB2YXIgdmFsdWUgPSBzcGxpdC5qb2luKCc9JykucmVwbGFjZSgvXFwrL2csICcgJylcbiAgICAgICAgZm9ybS5hcHBlbmQoZGVjb2RlVVJJQ29tcG9uZW50KG5hbWUpLCBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpKVxuICAgICAgfVxuICAgIH0pXG4gIHJldHVybiBmb3JtXG59XG5cbmZ1bmN0aW9uIHBhcnNlSGVhZGVycyhyYXdIZWFkZXJzKSB7XG4gIHZhciBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKVxuICAvLyBSZXBsYWNlIGluc3RhbmNlcyBvZiBcXHJcXG4gYW5kIFxcbiBmb2xsb3dlZCBieSBhdCBsZWFzdCBvbmUgc3BhY2Ugb3IgaG9yaXpvbnRhbCB0YWIgd2l0aCBhIHNwYWNlXG4gIC8vIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3MjMwI3NlY3Rpb24tMy4yXG4gIHZhciBwcmVQcm9jZXNzZWRIZWFkZXJzID0gcmF3SGVhZGVycy5yZXBsYWNlKC9cXHI/XFxuW1xcdCBdKy9nLCAnICcpXG4gIC8vIEF2b2lkaW5nIHNwbGl0IHZpYSByZWdleCB0byB3b3JrIGFyb3VuZCBhIGNvbW1vbiBJRTExIGJ1ZyB3aXRoIHRoZSBjb3JlLWpzIDMuNi4wIHJlZ2V4IHBvbHlmaWxsXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9naXRodWIvZmV0Y2gvaXNzdWVzLzc0OFxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNzUxXG4gIHByZVByb2Nlc3NlZEhlYWRlcnNcbiAgICAuc3BsaXQoJ1xccicpXG4gICAgLm1hcChmdW5jdGlvbihoZWFkZXIpIHtcbiAgICAgIHJldHVybiBoZWFkZXIuaW5kZXhPZignXFxuJykgPT09IDAgPyBoZWFkZXIuc3Vic3RyKDEsIGhlYWRlci5sZW5ndGgpIDogaGVhZGVyXG4gICAgfSlcbiAgICAuZm9yRWFjaChmdW5jdGlvbihsaW5lKSB7XG4gICAgICB2YXIgcGFydHMgPSBsaW5lLnNwbGl0KCc6JylcbiAgICAgIHZhciBrZXkgPSBwYXJ0cy5zaGlmdCgpLnRyaW0oKVxuICAgICAgaWYgKGtleSkge1xuICAgICAgICB2YXIgdmFsdWUgPSBwYXJ0cy5qb2luKCc6JykudHJpbSgpXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaGVhZGVycy5hcHBlbmQoa2V5LCB2YWx1ZSlcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1Jlc3BvbnNlICcgKyBlcnJvci5tZXNzYWdlKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSlcbiAgcmV0dXJuIGhlYWRlcnNcbn1cblxuQm9keS5jYWxsKFJlcXVlc3QucHJvdG90eXBlKVxuXG5leHBvcnQgZnVuY3Rpb24gUmVzcG9uc2UoYm9keUluaXQsIG9wdGlvbnMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFJlc3BvbnNlKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1BsZWFzZSB1c2UgdGhlIFwibmV3XCIgb3BlcmF0b3IsIHRoaXMgRE9NIG9iamVjdCBjb25zdHJ1Y3RvciBjYW5ub3QgYmUgY2FsbGVkIGFzIGEgZnVuY3Rpb24uJylcbiAgfVxuICBpZiAoIW9wdGlvbnMpIHtcbiAgICBvcHRpb25zID0ge31cbiAgfVxuXG4gIHRoaXMudHlwZSA9ICdkZWZhdWx0J1xuICB0aGlzLnN0YXR1cyA9IG9wdGlvbnMuc3RhdHVzID09PSB1bmRlZmluZWQgPyAyMDAgOiBvcHRpb25zLnN0YXR1c1xuICBpZiAodGhpcy5zdGF0dXMgPCAyMDAgfHwgdGhpcy5zdGF0dXMgPiA1OTkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkZhaWxlZCB0byBjb25zdHJ1Y3QgJ1Jlc3BvbnNlJzogVGhlIHN0YXR1cyBwcm92aWRlZCAoMCkgaXMgb3V0c2lkZSB0aGUgcmFuZ2UgWzIwMCwgNTk5XS5cIilcbiAgfVxuICB0aGlzLm9rID0gdGhpcy5zdGF0dXMgPj0gMjAwICYmIHRoaXMuc3RhdHVzIDwgMzAwXG4gIHRoaXMuc3RhdHVzVGV4dCA9IG9wdGlvbnMuc3RhdHVzVGV4dCA9PT0gdW5kZWZpbmVkID8gJycgOiAnJyArIG9wdGlvbnMuc3RhdHVzVGV4dFxuICB0aGlzLmhlYWRlcnMgPSBuZXcgSGVhZGVycyhvcHRpb25zLmhlYWRlcnMpXG4gIHRoaXMudXJsID0gb3B0aW9ucy51cmwgfHwgJydcbiAgdGhpcy5faW5pdEJvZHkoYm9keUluaXQpXG59XG5cbkJvZHkuY2FsbChSZXNwb25zZS5wcm90b3R5cGUpXG5cblJlc3BvbnNlLnByb3RvdHlwZS5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbmV3IFJlc3BvbnNlKHRoaXMuX2JvZHlJbml0LCB7XG4gICAgc3RhdHVzOiB0aGlzLnN0YXR1cyxcbiAgICBzdGF0dXNUZXh0OiB0aGlzLnN0YXR1c1RleHQsXG4gICAgaGVhZGVyczogbmV3IEhlYWRlcnModGhpcy5oZWFkZXJzKSxcbiAgICB1cmw6IHRoaXMudXJsXG4gIH0pXG59XG5cblJlc3BvbnNlLmVycm9yID0gZnVuY3Rpb24oKSB7XG4gIHZhciByZXNwb25zZSA9IG5ldyBSZXNwb25zZShudWxsLCB7c3RhdHVzOiAyMDAsIHN0YXR1c1RleHQ6ICcnfSlcbiAgcmVzcG9uc2Uub2sgPSBmYWxzZVxuICByZXNwb25zZS5zdGF0dXMgPSAwXG4gIHJlc3BvbnNlLnR5cGUgPSAnZXJyb3InXG4gIHJldHVybiByZXNwb25zZVxufVxuXG52YXIgcmVkaXJlY3RTdGF0dXNlcyA9IFszMDEsIDMwMiwgMzAzLCAzMDcsIDMwOF1cblxuUmVzcG9uc2UucmVkaXJlY3QgPSBmdW5jdGlvbih1cmwsIHN0YXR1cykge1xuICBpZiAocmVkaXJlY3RTdGF0dXNlcy5pbmRleE9mKHN0YXR1cykgPT09IC0xKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0ludmFsaWQgc3RhdHVzIGNvZGUnKVxuICB9XG5cbiAgcmV0dXJuIG5ldyBSZXNwb25zZShudWxsLCB7c3RhdHVzOiBzdGF0dXMsIGhlYWRlcnM6IHtsb2NhdGlvbjogdXJsfX0pXG59XG5cbmV4cG9ydCB2YXIgRE9NRXhjZXB0aW9uID0gZy5ET01FeGNlcHRpb25cbnRyeSB7XG4gIG5ldyBET01FeGNlcHRpb24oKVxufSBjYXRjaCAoZXJyKSB7XG4gIERPTUV4Y2VwdGlvbiA9IGZ1bmN0aW9uKG1lc3NhZ2UsIG5hbWUpIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlXG4gICAgdGhpcy5uYW1lID0gbmFtZVxuICAgIHZhciBlcnJvciA9IEVycm9yKG1lc3NhZ2UpXG4gICAgdGhpcy5zdGFjayA9IGVycm9yLnN0YWNrXG4gIH1cbiAgRE9NRXhjZXB0aW9uLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKVxuICBET01FeGNlcHRpb24ucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRE9NRXhjZXB0aW9uXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmZXRjaChpbnB1dCwgaW5pdCkge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHJlcXVlc3QgPSBuZXcgUmVxdWVzdChpbnB1dCwgaW5pdClcblxuICAgIGlmIChyZXF1ZXN0LnNpZ25hbCAmJiByZXF1ZXN0LnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICByZXR1cm4gcmVqZWN0KG5ldyBET01FeGNlcHRpb24oJ0Fib3J0ZWQnLCAnQWJvcnRFcnJvcicpKVxuICAgIH1cblxuICAgIHZhciB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKVxuXG4gICAgZnVuY3Rpb24gYWJvcnRYaHIoKSB7XG4gICAgICB4aHIuYWJvcnQoKVxuICAgIH1cblxuICAgIHhoci5vbmxvYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgICBzdGF0dXNUZXh0OiB4aHIuc3RhdHVzVGV4dCxcbiAgICAgICAgaGVhZGVyczogcGFyc2VIZWFkZXJzKHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKSB8fCAnJylcbiAgICAgIH1cbiAgICAgIC8vIFRoaXMgY2hlY2sgaWYgc3BlY2lmaWNhbGx5IGZvciB3aGVuIGEgdXNlciBmZXRjaGVzIGEgZmlsZSBsb2NhbGx5IGZyb20gdGhlIGZpbGUgc3lzdGVtXG4gICAgICAvLyBPbmx5IGlmIHRoZSBzdGF0dXMgaXMgb3V0IG9mIGEgbm9ybWFsIHJhbmdlXG4gICAgICBpZiAocmVxdWVzdC51cmwuaW5kZXhPZignZmlsZTovLycpID09PSAwICYmICh4aHIuc3RhdHVzIDwgMjAwIHx8IHhoci5zdGF0dXMgPiA1OTkpKSB7XG4gICAgICAgIG9wdGlvbnMuc3RhdHVzID0gMjAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9ucy5zdGF0dXMgPSB4aHIuc3RhdHVzO1xuICAgICAgfVxuICAgICAgb3B0aW9ucy51cmwgPSAncmVzcG9uc2VVUkwnIGluIHhociA/IHhoci5yZXNwb25zZVVSTCA6IG9wdGlvbnMuaGVhZGVycy5nZXQoJ1gtUmVxdWVzdC1VUkwnKVxuICAgICAgdmFyIGJvZHkgPSAncmVzcG9uc2UnIGluIHhociA/IHhoci5yZXNwb25zZSA6IHhoci5yZXNwb25zZVRleHRcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlc29sdmUobmV3IFJlc3BvbnNlKGJvZHksIG9wdGlvbnMpKVxuICAgICAgfSwgMClcbiAgICB9XG5cbiAgICB4aHIub25lcnJvciA9IGZ1bmN0aW9uKCkge1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSlcbiAgICAgIH0sIDApXG4gICAgfVxuXG4gICAgeGhyLm9udGltZW91dCA9IGZ1bmN0aW9uKCkge1xuICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgcmVqZWN0KG5ldyBUeXBlRXJyb3IoJ05ldHdvcmsgcmVxdWVzdCB0aW1lZCBvdXQnKSlcbiAgICAgIH0sIDApXG4gICAgfVxuXG4gICAgeGhyLm9uYWJvcnQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgIHJlamVjdChuZXcgRE9NRXhjZXB0aW9uKCdBYm9ydGVkJywgJ0Fib3J0RXJyb3InKSlcbiAgICAgIH0sIDApXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZml4VXJsKHVybCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHVybCA9PT0gJycgJiYgZy5sb2NhdGlvbi5ocmVmID8gZy5sb2NhdGlvbi5ocmVmIDogdXJsXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB1cmxcbiAgICAgIH1cbiAgICB9XG5cbiAgICB4aHIub3BlbihyZXF1ZXN0Lm1ldGhvZCwgZml4VXJsKHJlcXVlc3QudXJsKSwgdHJ1ZSlcblxuICAgIGlmIChyZXF1ZXN0LmNyZWRlbnRpYWxzID09PSAnaW5jbHVkZScpIHtcbiAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSB0cnVlXG4gICAgfSBlbHNlIGlmIChyZXF1ZXN0LmNyZWRlbnRpYWxzID09PSAnb21pdCcpIHtcbiAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSBmYWxzZVxuICAgIH1cblxuICAgIGlmICgncmVzcG9uc2VUeXBlJyBpbiB4aHIpIHtcbiAgICAgIGlmIChzdXBwb3J0LmJsb2IpIHtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9ICdibG9iJ1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgc3VwcG9ydC5hcnJheUJ1ZmZlclxuICAgICAgKSB7XG4gICAgICAgIHhoci5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGluaXQgJiYgdHlwZW9mIGluaXQuaGVhZGVycyA9PT0gJ29iamVjdCcgJiYgIShpbml0LmhlYWRlcnMgaW5zdGFuY2VvZiBIZWFkZXJzIHx8IChnLkhlYWRlcnMgJiYgaW5pdC5oZWFkZXJzIGluc3RhbmNlb2YgZy5IZWFkZXJzKSkpIHtcbiAgICAgIHZhciBuYW1lcyA9IFtdO1xuICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoaW5pdC5oZWFkZXJzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgICAgbmFtZXMucHVzaChub3JtYWxpemVOYW1lKG5hbWUpKVxuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihuYW1lLCBub3JtYWxpemVWYWx1ZShpbml0LmhlYWRlcnNbbmFtZV0pKVxuICAgICAgfSlcbiAgICAgIHJlcXVlc3QuaGVhZGVycy5mb3JFYWNoKGZ1bmN0aW9uKHZhbHVlLCBuYW1lKSB7XG4gICAgICAgIGlmIChuYW1lcy5pbmRleE9mKG5hbWUpID09PSAtMSkge1xuICAgICAgICAgIHhoci5zZXRSZXF1ZXN0SGVhZGVyKG5hbWUsIHZhbHVlKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0gZWxzZSB7XG4gICAgICByZXF1ZXN0LmhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbih2YWx1ZSwgbmFtZSkge1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihuYW1lLCB2YWx1ZSlcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgaWYgKHJlcXVlc3Quc2lnbmFsKSB7XG4gICAgICByZXF1ZXN0LnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIGFib3J0WGhyKVxuXG4gICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIC8vIERPTkUgKHN1Y2Nlc3Mgb3IgZmFpbHVyZSlcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICAgICAgcmVxdWVzdC5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBhYm9ydFhocilcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHhoci5zZW5kKHR5cGVvZiByZXF1ZXN0Ll9ib2R5SW5pdCA9PT0gJ3VuZGVmaW5lZCcgPyBudWxsIDogcmVxdWVzdC5fYm9keUluaXQpXG4gIH0pXG59XG5cbmZldGNoLnBvbHlmaWxsID0gdHJ1ZVxuXG5pZiAoIWcuZmV0Y2gpIHtcbiAgZy5mZXRjaCA9IGZldGNoXG4gIGcuSGVhZGVycyA9IEhlYWRlcnNcbiAgZy5SZXF1ZXN0ID0gUmVxdWVzdFxuICBnLlJlc3BvbnNlID0gUmVzcG9uc2Vcbn1cbiIsImV4cG9ydCB2YXIgQW5nbGVzVW5pdEVudW07XG4oZnVuY3Rpb24gKEFuZ2xlc1VuaXRFbnVtKSB7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJOT05FXCJdID0gXCJub25lXCI7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJERUdSRUVTXCJdID0gXCJkZWdcIjtcbiAgICBBbmdsZXNVbml0RW51bVtcIkdSQURJQU5TXCJdID0gXCJncmFkXCI7XG4gICAgQW5nbGVzVW5pdEVudW1bXCJSQURJQU5TXCJdID0gXCJyYWRcIjtcbiAgICBBbmdsZXNVbml0RW51bVtcIlRVUk5TXCJdID0gXCJ0dXJuXCI7XG59KShBbmdsZXNVbml0RW51bSB8fCAoQW5nbGVzVW5pdEVudW0gPSB7fSkpO1xuZXhwb3J0IHZhciBDb2xvclVuaXRFbnVtO1xuKGZ1bmN0aW9uIChDb2xvclVuaXRFbnVtKSB7XG4gICAgQ29sb3JVbml0RW51bVtcIk5PTkVcIl0gPSBcIm5vbmVcIjtcbiAgICBDb2xvclVuaXRFbnVtW1wiUEVSQ0VOVFwiXSA9IFwicGVyY2VudFwiO1xufSkoQ29sb3JVbml0RW51bSB8fCAoQ29sb3JVbml0RW51bSA9IHt9KSk7XG5leHBvcnQgdmFyIENNWUtGdW5jdGlvbkVudW07XG4oZnVuY3Rpb24gKENNWUtGdW5jdGlvbkVudW0pIHtcbiAgICBDTVlLRnVuY3Rpb25FbnVtW1wiREVWSUNFX0NNWUtcIl0gPSBcImRldmljZS1jbXlrXCI7XG4gICAgQ01ZS0Z1bmN0aW9uRW51bVtcIkNNWUtcIl0gPSBcImNteWtcIjtcbn0pKENNWUtGdW5jdGlvbkVudW0gfHwgKENNWUtGdW5jdGlvbkVudW0gPSB7fSkpO1xuIiwiZXhwb3J0IHZhciBDb2xvck1vZGVsO1xuKGZ1bmN0aW9uIChDb2xvck1vZGVsKSB7XG4gICAgQ29sb3JNb2RlbFtcIkhFWFwiXSA9IFwiSEVYXCI7XG4gICAgQ29sb3JNb2RlbFtcIlJHQlwiXSA9IFwiUkdCXCI7XG4gICAgQ29sb3JNb2RlbFtcIkhXQlwiXSA9IFwiSFdCXCI7XG4gICAgQ29sb3JNb2RlbFtcIkhTTFwiXSA9IFwiSFNMXCI7XG4gICAgQ29sb3JNb2RlbFtcIkNJRUxhYlwiXSA9IFwiQ0lFTGFiXCI7XG4gICAgQ29sb3JNb2RlbFtcIkxDSFwiXSA9IFwiTENIXCI7XG4gICAgQ29sb3JNb2RlbFtcIkNNWUtcIl0gPSBcIkNNWUtcIjtcbn0pKENvbG9yTW9kZWwgfHwgKENvbG9yTW9kZWwgPSB7fSkpO1xuZXhwb3J0IHZhciBIYXJtb255O1xuKGZ1bmN0aW9uIChIYXJtb255KSB7XG4gICAgSGFybW9ueVtcIkFOQUxPR09VU1wiXSA9IFwiQU5BTE9HT1VTXCI7XG4gICAgSGFybW9ueVtcIkNPTVBMRU1FTlRBUllcIl0gPSBcIkNPTVBMRU1FTlRBUllcIjtcbiAgICBIYXJtb255W1wiU1BMSVRfQ09NUExFTUVOVEFSWVwiXSA9IFwiU1BMSVRfQ09NUExFTUVOVEFSWVwiO1xuICAgIEhhcm1vbnlbXCJUUklBRElDXCJdID0gXCJUUklBRElDXCI7XG4gICAgSGFybW9ueVtcIlRFVFJBRElDXCJdID0gXCJURVRSQURJQ1wiO1xuICAgIEhhcm1vbnlbXCJTUVVBUkVcIl0gPSBcIlNRVUFSRVwiO1xufSkoSGFybW9ueSB8fCAoSGFybW9ueSA9IHt9KSk7XG5leHBvcnQgdmFyIE1peDtcbihmdW5jdGlvbiAoTWl4KSB7XG4gICAgTWl4W1wiQURESVRJVkVcIl0gPSBcIkFERElUSVZFXCI7XG4gICAgTWl4W1wiU1VCVFJBQ1RJVkVcIl0gPSBcIlNVQlRSQUNUSVZFXCI7XG59KShNaXggfHwgKE1peCA9IHt9KSk7XG5leHBvcnQgdmFyIENvbG9yS2V5d29yZHM7XG4oZnVuY3Rpb24gKENvbG9yS2V5d29yZHMpIHtcbiAgICBDb2xvcktleXdvcmRzW1wiYmxhY2tcIl0gPSBcIiMwMDAwMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2lsdmVyXCJdID0gXCIjQzBDMEMwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdyYXlcIl0gPSBcIiM4MDgwODBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wid2hpdGVcIl0gPSBcIiNGRkZGRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWFyb29uXCJdID0gXCIjODAwMDAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInJlZFwiXSA9IFwiI0ZGMDAwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwdXJwbGVcIl0gPSBcIiM4MDAwODBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZnVjaHNpYVwiXSA9IFwiI0ZGMDBGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJncmVlblwiXSA9IFwiIzAwODAwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaW1lXCJdID0gXCIjMDBGRjAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm9saXZlXCJdID0gXCIjODA4MDAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInllbGxvd1wiXSA9IFwiI0ZGRkYwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJuYXZ5XCJdID0gXCIjMDAwMDgwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJsdWVcIl0gPSBcIiMwMDAwRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1widGVhbFwiXSA9IFwiIzAwODA4MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJhcXVhXCJdID0gXCIjMDBGRkZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm9yYW5nZVwiXSA9IFwiI0ZGQTUwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJhbGljZWJsdWVcIl0gPSBcIiNGMEY4RkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYW50aXF1ZXdoaXRlXCJdID0gXCIjRkFFQkQ3XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImFxdWFtYXJpbmVcIl0gPSBcIiM3RkZGRDRcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYXp1cmVcIl0gPSBcIiNGMEZGRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYmVpZ2VcIl0gPSBcIiNGNUY1RENcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYmlzcXVlXCJdID0gXCIjRkZFNEM0XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJsYW5jaGVkYWxtb25kXCJdID0gXCIjRkZFQkNEXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImJsdWV2aW9sZXRcIl0gPSBcIiM4QTJCRTJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYnJvd25cIl0gPSBcIiNBNTJBMkFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiYnVybHl3b29kXCJdID0gXCIjREVCODg3XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImNhZGV0Ymx1ZVwiXSA9IFwiIzVGOUVBMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjaGFydHJldXNlXCJdID0gXCIjN0ZGRjAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImNob2NvbGF0ZVwiXSA9IFwiI0QyNjkxRVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjb3JhbFwiXSA9IFwiI0ZGN0Y1MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjb3JuZmxvd2VyYmx1ZVwiXSA9IFwiIzY0OTVFRFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjb3Juc2lsa1wiXSA9IFwiI0ZGRjhEQ1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJjcmltc29uXCJdID0gXCIjREMxNDNDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImN5YW5cIl0gPSBcIiMwMEZGRkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2JsdWVcIl0gPSBcIiMwMDAwOEJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2N5YW5cIl0gPSBcIiMwMDhCOEJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2dvbGRlbnJvZFwiXSA9IFwiI0I4ODYwQlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrZ3JheVwiXSA9IFwiI0E5QTlBOVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrZ3JlZW5cIl0gPSBcIiMwMDY0MDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2dyZXlcIl0gPSBcIiNBOUE5QTlcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya2toYWtpXCJdID0gXCIjQkRCNzZCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmttYWdlbnRhXCJdID0gXCIjOEIwMDhCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtvbGl2ZWdyZWVuXCJdID0gXCIjNTU2QjJGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtvcmFuZ2VcIl0gPSBcIiNGRjhDMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya29yY2hpZFwiXSA9IFwiIzk5MzJDQ1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrcmVkXCJdID0gXCIjOEIwMDAwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtzYWxtb25cIl0gPSBcIiNFOTk2N0FcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya3NlYWdyZWVuXCJdID0gXCIjOEZCQzhGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmtzbGF0ZWJsdWVcIl0gPSBcIiM0ODNEOEJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya3NsYXRlZ3JheVwiXSA9IFwiIzJGNEY0RlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkYXJrc2xhdGVncmV5XCJdID0gXCIjMkY0RjRGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRhcmt0dXJxdW9pc2VcIl0gPSBcIiMwMENFRDFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZGFya3Zpb2xldFwiXSA9IFwiIzk0MDBEM1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkZWVwcGlua1wiXSA9IFwiI0ZGMTQ5M1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkZWVwc2t5Ymx1ZVwiXSA9IFwiIzAwQkZGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJkaW1ncmF5XCJdID0gXCIjNjk2OTY5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImRpbWdyZXlcIl0gPSBcIiM2OTY5NjlcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZG9kZ2VyYmx1ZVwiXSA9IFwiIzFFOTBGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJmaXJlYnJpY2tcIl0gPSBcIiNCMjIyMjJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZmxvcmFsd2hpdGVcIl0gPSBcIiNGRkZBRjBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZm9yZXN0Z3JlZW5cIl0gPSBcIiMyMjhCMjJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ2FpbnNib3JvXCJdID0gXCIjRENEQ0RDXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImdob3N0d2hpdGVcIl0gPSBcIiNGOEY4RkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ29sZFwiXSA9IFwiI0ZGRDcwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJnb2xkZW5yb2RcIl0gPSBcIiNEQUE1MjBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ3JlZW55ZWxsb3dcIl0gPSBcIiNBREZGMkZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiZ3JleVwiXSA9IFwiIzgwODA4MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJob25leWRld1wiXSA9IFwiI0YwRkZGMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJob3RwaW5rXCJdID0gXCIjRkY2OUI0XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImluZGlhbnJlZFwiXSA9IFwiI0NENUM1Q1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJpbmRpZ29cIl0gPSBcIiM0QjAwODJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wiaXZvcnlcIl0gPSBcIiNGRkZGRjBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wia2hha2lcIl0gPSBcIiNGMEU2OENcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGF2ZW5kZXJcIl0gPSBcIiNFNkU2RkFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGF2ZW5kZXJibHVzaFwiXSA9IFwiI0ZGRjBGNVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsYXduZ3JlZW5cIl0gPSBcIiM3Q0ZDMDBcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGVtb25jaGlmZm9uXCJdID0gXCIjRkZGQUNEXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0Ymx1ZVwiXSA9IFwiI0FERDhFNlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGNvcmFsXCJdID0gXCIjRjA4MDgwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0Y3lhblwiXSA9IFwiI0UwRkZGRlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGdvbGRlbnJvZHllbGxvd1wiXSA9IFwiI0ZBRkFEMlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGdyYXlcIl0gPSBcIiNEM0QzRDNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRncmVlblwiXSA9IFwiIzkwRUU5MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaWdodGdyZXlcIl0gPSBcIiNEM0QzRDNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRwaW5rXCJdID0gXCIjRkZCNkMxXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c2FsbW9uXCJdID0gXCIjRkZBMDdBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c2VhZ3JlZW5cIl0gPSBcIiMyMEIyQUFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibGlnaHRza3libHVlXCJdID0gXCIjODdDRUZBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c2xhdGVncmF5XCJdID0gXCIjNzc4ODk5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c2xhdGVncmV5XCJdID0gXCIjNzc4ODk5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0c3RlZWxibHVlXCJdID0gXCIjQjBDNERFXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpZ2h0eWVsbG93XCJdID0gXCIjRkZGRkUwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcImxpbWVncmVlblwiXSA9IFwiIzMyQ0QzMlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJsaW5lblwiXSA9IFwiI0ZBRjBFNlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtYWdlbnRhXCJdID0gXCIjRkYwMEZGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bWFxdWFtYXJpbmVcIl0gPSBcIiM2NkNEQUFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtYmx1ZVwiXSA9IFwiIzAwMDBDRFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW1vcmNoaWRcIl0gPSBcIiNCQTU1RDNcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtcHVycGxlXCJdID0gXCIjOTM3MERCXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bXNlYWdyZWVuXCJdID0gXCIjM0NCMzcxXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1lZGl1bXNsYXRlYmx1ZVwiXSA9IFwiIzdCNjhFRVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW1zcHJpbmdncmVlblwiXSA9IFwiIzAwRkE5QVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtZWRpdW10dXJxdW9pc2VcIl0gPSBcIiM0OEQxQ0NcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWVkaXVtdmlvbGV0cmVkXCJdID0gXCIjQzcxNTg1XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1pZG5pZ2h0Ymx1ZVwiXSA9IFwiIzE5MTk3MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJtaW50Y3JlYW1cIl0gPSBcIiNGNUZGRkFcIjtcbiAgICBDb2xvcktleXdvcmRzW1wibWlzdHlyb3NlXCJdID0gXCIjRkZFNEUxXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm1vY2Nhc2luXCJdID0gXCIjRkZFNEI1XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm5hdmFqb3doaXRlXCJdID0gXCIjRkZERUFEXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm9sZGxhY2VcIl0gPSBcIiNGREY1RTZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wib2xpdmVkcmFiXCJdID0gXCIjNkI4RTIzXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcIm9yYW5nZXJlZFwiXSA9IFwiI0ZGNDUwMFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJvcmNoaWRcIl0gPSBcIiNEQTcwRDZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGFsZWdvbGRlbnJvZFwiXSA9IFwiI0VFRThBQVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwYWxlZ3JlZW5cIl0gPSBcIiM5OEZCOThcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGFsZXR1cnF1b2lzZVwiXSA9IFwiI0FGRUVFRVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwYWxldmlvbGV0cmVkXCJdID0gXCIjREI3MDkzXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBhcGF5YXdoaXBcIl0gPSBcIiNGRkVGRDVcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGVhY2hwdWZmXCJdID0gXCIjRkZEQUI5XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBlcnVcIl0gPSBcIiNDRDg1M0ZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicGlua1wiXSA9IFwiI0ZGQzBDQlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJwbHVtXCJdID0gXCIjRERBMEREXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInBvd2RlcmJsdWVcIl0gPSBcIiNCMEUwRTZcIjtcbiAgICBDb2xvcktleXdvcmRzW1wicm9zeWJyb3duXCJdID0gXCIjQkM4RjhGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInJveWFsYmx1ZVwiXSA9IFwiIzQxNjlFMVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzYWRkbGVicm93blwiXSA9IFwiIzhCNDUxM1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzYWxtb25cIl0gPSBcIiNGQTgwNzJcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2FuZHlicm93blwiXSA9IFwiI0Y0QTQ2MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzZWFncmVlblwiXSA9IFwiIzJFOEI1N1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzZWFzaGVsbFwiXSA9IFwiI0ZGRjVFRVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzaWVubmFcIl0gPSBcIiNBMDUyMkRcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2t5Ymx1ZVwiXSA9IFwiIzg3Q0VFQlwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzbGF0ZWJsdWVcIl0gPSBcIiM2QTVBQ0RcIjtcbiAgICBDb2xvcktleXdvcmRzW1wic2xhdGVncmF5XCJdID0gXCIjNzA4MDkwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNsYXRlZ3JleVwiXSA9IFwiIzcwODA5MFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJzbm93XCJdID0gXCIjRkZGQUZBXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInNwcmluZ2dyZWVuXCJdID0gXCIjMDBGRjdGXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInN0ZWVsYmx1ZVwiXSA9IFwiIzQ2ODJCNFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ0YW5cIl0gPSBcIiNEMkI0OENcIjtcbiAgICBDb2xvcktleXdvcmRzW1widGhpc3RsZVwiXSA9IFwiI0Q4QkZEOFwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ0b21hdG9cIl0gPSBcIiNGRjYzNDdcIjtcbiAgICBDb2xvcktleXdvcmRzW1widHVycXVvaXNlXCJdID0gXCIjNDBFMEQwXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInZpb2xldFwiXSA9IFwiI0VFODJFRVwiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ3aGVhdFwiXSA9IFwiI0Y1REVCM1wiO1xuICAgIENvbG9yS2V5d29yZHNbXCJ3aGl0ZXNtb2tlXCJdID0gXCIjRjVGNUY1XCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInllbGxvd2dyZWVuXCJdID0gXCIjOUFDRDMyXCI7XG4gICAgQ29sb3JLZXl3b3Jkc1tcInJlYmVjY2FwdXJwbGVcIl0gPSBcIiM2NjMzOTlcIjtcbn0pKENvbG9yS2V5d29yZHMgfHwgKENvbG9yS2V5d29yZHMgPSB7fSkpO1xuIiwiaW1wb3J0IHsgQ29sb3JNb2RlbCB9IGZyb20gJy4vZW51bXMnO1xuZXhwb3J0IGNvbnN0IENPTE9SUkVHUyA9IHtcbiAgICBbQ29sb3JNb2RlbC5IRVhdOiAvXiMoPzooPzxyPlthLWZcXGRdKSg/PGc+W2EtZlxcZF0pKD88Yj5bYS1mXFxkXSkoPzxhPlthLWZcXGRdKT98KD88cnI+W2EtZlxcZF17Mn0pKD88Z2c+W2EtZlxcZF17Mn0pKD88YmI+W2EtZlxcZF17Mn0pKD88YWE+W2EtZlxcZF17Mn0pPykkL2ksXG4gICAgW0NvbG9yTW9kZWwuUkdCXTogL15yZ2JhP1xccypcXChcXHMqKD86KD88cl9sZWdhY3k+KD86XFxkKlxcLik/XFxkKyU/KVxccyosXFxzKig/PGdfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCslPylcXHMqLFxccyooPzxiX2xlZ2FjeT4oPzpcXGQqXFwuKT9cXGQrJT8pKD86XFxzKixcXHMqKD88YV9sZWdhY3k+KD86XFxkKlxcLik/XFxkKykpP3woPzxyPig/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88Zz4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PGI+KD86XFxkKlxcLik/XFxkKyU/KSg/OlxccypcXC9cXHMqKD88YT4oPzpcXGQqXFwuKT9cXGQrJT8pKT98ZnJvbVxccysoPzxmcm9tPig/Olxcdyt8XFx3K1xcKFxccypbXigpKV0rXFxzKlxcKXxcXHcrXFwoZnJvbVxccytcXHcrXFwoLipcXClcXHMqXFwpfCNbYS1mQS1GXFxkXSspKVxccysoPzxyZWxhdGl2ZV9yPig/OltyZ2JdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtyZ2IoKS8qXFwtK1xcZC5cXHNdK1xcKSkpXFxzKyg/PHJlbGF0aXZlX2c+KD86W3JnYl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW3JnYigpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfYj4oPzpbcmdiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbcmdiKCkvKlxcLStcXGQuXFxzXStcXCkpKSg/OlxccypcXC9cXHMqKD88cmVsYXRpdmVfYT4oPzooPzpcXGQqXFwuKT9cXGQrJT98Y2FsY1xcKFsoKS8qXFwtK1xcZC5cXHNcXHddKig/OmFscGhhKT9bKCkvKlxcLStcXGQuXFxzXFx3XSpcXCl8YWxwaGEpKSk/KVxccypcXCkkLyxcbiAgICBbQ29sb3JNb2RlbC5IV0JdOiAvXmh3YlxccypcXChcXHMqKD86KD88aD4oPzpcXGQqXFwuKT9cXGQrKD86ZGVnfGdyYWR8cmFkfHR1cm4pPylcXHMrKD88dz4oPzpcXGQqXFwuKT9cXGQrKSVcXHMrKD88Yj4oPzpcXGQqXFwuKT9cXGQrKSUoPzpcXHMqXFwvXFxzKig/PGE+KD86XFxkKlxcLik/XFxkKyU/KSk/fGZyb21cXHMrKD88ZnJvbT4oPzpcXHcrfFxcdytcXChcXHMqW14oKSldK1xccypcXCl8XFx3K1xcKGZyb21cXHMrXFx3K1xcKC4qXFwpXFxzKlxcKXwjW2EtZkEtRlxcZF0rKSlcXHMrKD88cmVsYXRpdmVfaD4oPzpbaHdiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHdiKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV93Pig/Oltod2JdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtod2IoKS8qXFwtK1xcZC5cXHNdK1xcKSkpJT9cXHMrKD88cmVsYXRpdmVfYj4oPzpbaHdiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHdiKCkvKlxcLStcXGQuXFxzXStcXCkpKSU/KD86XFxzKlxcL1xccyooPzxyZWxhdGl2ZV9hPig/Oig/OlxcZCpcXC4pP1xcZCslP3xjYWxjXFwoWygpLypcXC0rXFxkLlxcc1xcd10qKD86YWxwaGEpP1soKS8qXFwtK1xcZC5cXHNcXHddKlxcKXxhbHBoYSkpKT8pXFxzKlxcKSQvLFxuICAgIFtDb2xvck1vZGVsLkhTTF06IC9eaHNsYT9cXHMqXFwoXFxzKig/Oig/PGhfbGVnYWN5Pi0/KD86XFxkKlxcLik/XFxkKyg/OmRlZ3xncmFkfHJhZHx0dXJuKT8pXFxzKixcXHMqKD88c19sZWdhY3k+KD86XFxkKlxcLik/XFxkKyklXFxzKixcXHMqKD88bF9sZWdhY3k+KD86XFxkKlxcLik/XFxkKyklKD86XFxzKixcXHMqKD88YV9sZWdhY3k+KD86XFxkKlxcLik/XFxkKykpP3woPzxoPi0/KD86XFxkKlxcLik/XFxkKyg/OmRlZ3xncmFkfHJhZHx0dXJuKT8pXFxzKyg/PHM+KD86XFxkKlxcLik/XFxkKyklP1xccysoPzxsPig/OlxcZCpcXC4pP1xcZCspJT8oPzpcXHMqXFwvXFxzKig/PGE+KD86XFxkKlxcLik/XFxkKyU/KSk/fGZyb21cXHMrKD88ZnJvbT4oPzpcXHcrfFxcdytcXChcXHMqW14oKSldK1xccypcXCl8XFx3K1xcKGZyb21cXHMrXFx3K1xcKC4qXFwpXFxzKlxcKXwjW2EtZkEtRlxcZF0rKSlcXHMrKD88cmVsYXRpdmVfaD4oPzpbaHNsXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHNsKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV9zPig/Oltoc2xdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtoc2woKS8qXFwtK1xcZC5cXHNdK1xcKSkpJT9cXHMrKD88cmVsYXRpdmVfbD4oPzpbaHNsXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbaHNsKCkvKlxcLStcXGQuXFxzXStcXCkpKSU/KD86XFxzKlxcL1xccyooPzxyZWxhdGl2ZV9hPig/Oig/OlxcZCpcXC4pP1xcZCslP3xjYWxjXFwoWygpLypcXC0rXFxkLlxcc1xcd10qKD86YWxwaGEpP1soKS8qXFwtK1xcZC5cXHNcXHddKlxcKXxhbHBoYSkpKT8pXFxzKlxcKSQvLFxuICAgIFtDb2xvck1vZGVsLkNJRUxhYl06IC9ebGFiXFxzKlxcKFxccyooPzooPzxMPig/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88YT4tPyg/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88Yj4tPyg/OlxcZCpcXC4pP1xcZCslPykoPzpcXHMqXFwvXFxzKig/PEE+KD86XFxkKlxcLik/XFxkKyU/KSk/fGZyb21cXHMrKD88ZnJvbT4oPzpcXHcrfFxcdytcXChcXHMqW14oKSldK1xccypcXCl8XFx3K1xcKGZyb21cXHMrXFx3K1xcKC4qXFwpXFxzKlxcKXwjW2EtZkEtRlxcZF0rKSlcXHMrKD88cmVsYXRpdmVfTD4oPzpbbGFiXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbbGFiKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV9hPig/OltsYWJdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtsYWIoKS8qXFwtK1xcZC5cXHNdK1xcKSkpXFxzKyg/PHJlbGF0aXZlX2I+KD86W2xhYl18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2xhYigpLypcXC0rXFxkLlxcc10rXFwpKSkoPzpcXHMqXFwvXFxzKig/PHJlbGF0aXZlX0E+KD86KD86XFxkKlxcLik/XFxkKyU/fGNhbGNcXChbKCkvKlxcLStcXGQuXFxzXFx3XSooPzphbHBoYSk/WygpLypcXC0rXFxkLlxcc1xcd10qXFwpfGFscGhhKSkpPylcXHMqXFwpJC8sXG4gICAgW0NvbG9yTW9kZWwuTENIXTogL15sY2hcXHMqXFwoXFxzKig/Oig/PGw+KD86XFxkKlxcLik/XFxkKyU/KVxccysoPzxjPi0/KD86XFxkKlxcLik/XFxkKyU/KVxccysoPzxoPi0/KD86XFxkKlxcLik/XFxkKyg/OmRlZ3xncmFkfHJhZHx0dXJuKT8pKD86XFxzKlxcL1xccyooPzxhPig/OlxcZCpcXC4pP1xcZCslPykpP3xmcm9tXFxzKyg/PGZyb20+KD86XFx3K3xcXHcrXFwoXFxzKlteKCkpXStcXHMqXFwpfFxcdytcXChmcm9tXFxzK1xcdytcXCguKlxcKVxccypcXCl8I1thLWZBLUZcXGRdKykpXFxzKyg/PHJlbGF0aXZlX2w+KD86W2xjaF18KD86XFxkKlxcLik/XFxkK3xjYWxjXFwoW2xjaCgpLypcXC0rXFxkLlxcc10rXFwpKSlcXHMrKD88cmVsYXRpdmVfYz4oPzpbbGNoXXwoPzpcXGQqXFwuKT9cXGQrfGNhbGNcXChbbGNoKCkvKlxcLStcXGQuXFxzXStcXCkpKVxccysoPzxyZWxhdGl2ZV9oPig/OltsY2hdfCg/OlxcZCpcXC4pP1xcZCt8Y2FsY1xcKFtsY2goKS8qXFwtK1xcZC5cXHNdK1xcKSkpKD86XFxzKlxcL1xccyooPzxyZWxhdGl2ZV9hPig/Oig/OlxcZCpcXC4pP1xcZCslP3xjYWxjXFwoWygpLypcXC0rXFxkLlxcc1xcd10qKD86YWxwaGEpP1soKS8qXFwtK1xcZC5cXHNcXHddKlxcKXxhbHBoYSkpKT8pXFxzKlxcKSQvLFxuICAgIFtDb2xvck1vZGVsLkNNWUtdOiAvXig/OmRldmljZS1jbXlrfGNteWspXFxzKlxcKFxccyooPzooPzxjX2xlZ2FjeT4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKixcXHMqKD88bV9sZWdhY3k+KD86XFxkKlxcLik/XFxkKyU/KVxccyosXFxzKig/PHlfbGVnYWN5Pig/OlxcZCpcXC4pP1xcZCslPylcXHMqLFxccyooPzxrX2xlZ2FjeT4oPzpcXGQqXFwuKT9cXGQrJT8pKD86XFxzKixcXHMqKD88YV9sZWdhY3k+KD86XFxkKlxcLik/XFxkKykpP3woPzxjPig/OlxcZCpcXC4pP1xcZCslPylcXHMrKD88bT4oPzpcXGQqXFwuKT9cXGQrJT8pXFxzKyg/PHk+KD86XFxkKlxcLik/XFxkKyU/KVxccysoPzxrPig/OlxcZCpcXC4pP1xcZCslPykoPzpcXHMqXFwvXFxzKig/PGE+KD86XFxkKlxcLik/XFxkKyU/KSk/KVxccypcXCkkL1xufTtcbmV4cG9ydCBjb25zdCBDQUxDID0ge1xuICAgIFJFR0VYUDogL15jYWxjXFwoXFxzKig/PG9wZXJhdGlvbj5bXFxkLi8qKy1cXHdcXHNdKylcXHMqXFwpJC8sXG4gICAgU0NPUEVEOiAvXFwoXFxzKihbXigpXSspXFxzKlxcKS9nLFxuICAgIERJVklTSU9OOiAvXFxzKig/PGxlZnQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqXFwvXFxzKig/PHJpZ2h0Pig/Oig/OlxcZCpcXC4pP1xcZCt8XFx3KykpXFxzKi8sXG4gICAgTVVMVElQTElDQVRJT046IC9cXHMqKD88bGVmdD4oPzooPzpcXGQqXFwuKT9cXGQrfFxcdyspKVxccypcXCpcXHMqKD88cmlnaHQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqLyxcbiAgICBTVU06IC9cXHMqKD88bGVmdD4oPzooPzpcXGQqXFwuKT9cXGQrfFxcdyspKVxccypcXCtcXHMqKD88cmlnaHQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqLyxcbiAgICBSRVNUOiAvXFxzKig/PGxlZnQ+KD86KD86XFxkKlxcLik/XFxkK3xcXHcrKSlcXHMqLVxccyooPzxyaWdodD4oPzooPzpcXGQqXFwuKT9cXGQrfFxcdyspKVxccyovXG59O1xuZXhwb3J0IGNvbnN0IEhTTF9IVUUgPSAvXig/PG51bWJlcj4tPyg/OlxcZCpcXC4pP1xcZCspKD88dW5pdHM+KD86ZGVnfGdyYWR8cmFkfHR1cm4pPykkLztcbmV4cG9ydCBjb25zdCBQQ0VOVCA9IC9eKC0/XFxkKyg/OlxcLlxcZCspP3wtP1xcLlxcZCspJSQvO1xuZXhwb3J0IGNvbnN0IEhFWCA9IC9eMHgoW2EtZlxcZF17MSwyfSkkL2k7XG5leHBvcnQgY29uc3QgVEVNUExBVEVfVkFSID0gL1xceyhcXGQrKVxcfS9nO1xuZXhwb3J0IGNvbnN0IENPTU1BU19BTkRfTkVYVF9DSEFSUyA9IC8sKCArfFxcZCspL2c7XG5leHBvcnQgY29uc3QgU1BBQ0VTID0gLyArLztcbiIsImltcG9ydCB7IEFuZ2xlc1VuaXRFbnVtLCBDTVlLRnVuY3Rpb25FbnVtLCBDb2xvclVuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IENvbG9yS2V5d29yZHMsIENvbG9yTW9kZWwgfSBmcm9tICcuL2VudW1zJztcbmV4cG9ydCBjb25zdCBNQVhfREVDSU1BTFMgPSA2O1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfQkxFTkRfU1RFUFMgPSA1O1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfU0hBREVTX1RJTlRTX1NURVBTID0gNTtcbmV4cG9ydCBjb25zdCBCQVNFXzI1NSA9IDI1NTtcbmV4cG9ydCBjb25zdCBNQVhfSFVFID0gMzYwO1xuZXhwb3J0IGNvbnN0IE1BWF9QQ0VOVCA9IDEwMDtcbmV4cG9ydCBjb25zdCBNQVhfQUxQSEEgPSAxO1xuZXhwb3J0IGNvbnN0IE1BWF9MQUIgPSAxMjU7XG5leHBvcnQgY29uc3QgTUFYX0xDSF9DID0gMTUwO1xuZXhwb3J0IGNvbnN0IEdSQURJQU5TID0gMTAgLyA5O1xuZXhwb3J0IGNvbnN0IENPTE9SX0tFWVMgPSBPYmplY3Qua2V5cyhDb2xvcktleXdvcmRzKTtcbmV4cG9ydCBjb25zdCBDT0xPUl9QUk9QUyA9IE9iamVjdC5mcmVlemUoe1xuICAgIEhFWDogWydSJywgJ0cnLCAnQicsICdBJ10sXG4gICAgUkdCOiBbJ1InLCAnRycsICdCJywgJ0EnXSxcbiAgICBIU0w6IFsnSCcsICdTJywgJ0wnLCAnQSddLFxuICAgIEhXQjogWydIJywgJ1cnLCAnQicsICdBJ10sXG4gICAgQ0lFTGFiOiBbJ0wnLCAnYScsICdiJywgJ0EnXSxcbiAgICBMQ0g6IFsnTCcsICdDJywgJ0gnLCAnQSddLFxuICAgIENNWUs6IFsnQycsICdNJywgJ1knLCAnSycsICdBJ11cbn0pO1xuZXhwb3J0IGNvbnN0IFZBTElEX0NPTE9SX09CSkVDVFMgPSBPYmplY3QuZnJlZXplKHtcbiAgICBBQkdSOiBDb2xvck1vZGVsLlJHQixcbiAgICBBQkhXOiBDb2xvck1vZGVsLkhXQixcbiAgICBBQ0hMOiBDb2xvck1vZGVsLkxDSCxcbiAgICBBQ0tNWTogQ29sb3JNb2RlbC5DTVlLLFxuICAgIEFITFM6IENvbG9yTW9kZWwuSFNMLFxuICAgIEFMQUI6IENvbG9yTW9kZWwuQ0lFTGFiLFxuICAgIEJHUjogQ29sb3JNb2RlbC5SR0IsXG4gICAgQkhXOiBDb2xvck1vZGVsLkhXQixcbiAgICBDSEw6IENvbG9yTW9kZWwuTENILFxuICAgIENLTVk6IENvbG9yTW9kZWwuQ01ZSyxcbiAgICBITFM6IENvbG9yTW9kZWwuSFNMLFxuICAgIExBQjogQ29sb3JNb2RlbC5DSUVMYWJcbn0pO1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfT1BUSU9OUyA9IE9iamVjdC5mcmVlemUoe1xuICAgIGRlY2ltYWxzOiBNQVhfREVDSU1BTFMsXG4gICAgbGVnYWN5Q1NTOiBmYWxzZSxcbiAgICBzcGFjZXNBZnRlckNvbW1hczogZmFsc2UsXG4gICAgYW5nbGVzVW5pdDogQW5nbGVzVW5pdEVudW0uTk9ORSxcbiAgICByZ2JVbml0OiBDb2xvclVuaXRFbnVtLk5PTkUsXG4gICAgbGFiVW5pdDogQ29sb3JVbml0RW51bS5OT05FLFxuICAgIGxjaFVuaXQ6IENvbG9yVW5pdEVudW0uTk9ORSxcbiAgICBjbXlrVW5pdDogQ29sb3JVbml0RW51bS5QRVJDRU5ULFxuICAgIGFscGhhVW5pdDogQ29sb3JVbml0RW51bS5OT05FLFxuICAgIGNteWtGdW5jdGlvbjogQ01ZS0Z1bmN0aW9uRW51bS5ERVZJQ0VfQ01ZS1xufSk7XG5leHBvcnQgY29uc3QgRVJST1JTID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgTk9UX0FDQ0VQVEVEX0lOUFVUOiBgVGhlIHByb3ZpZGVkIHN0cmluZyBjb2xvciBkb2Vzbid0IGhhdmUgYSBjb3JyZWN0IGZvcm1hdGAsXG4gICAgTk9UX0FfVkFMSURfUkVMQVRJVkVfQ09MT1I6ICdpcyBub3QgYSB2YWxpZCBvcGVyYXRpb24gZm9yIGEgcmVsYXRpdmUgY29sb3InXG59KTtcbmV4cG9ydCAqIGZyb20gJy4vcmVnZXhwcyc7XG5leHBvcnQgKiBmcm9tICcuL2VudW1zJztcbiIsImltcG9ydCB7IEFuZ2xlc1VuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IEJBU0VfMjU1LCBDb2xvck1vZGVsLCBHUkFESUFOUywgSGFybW9ueSwgSEVYLCBIU0xfSFVFLCBNQVhfQUxQSEEsIE1BWF9ERUNJTUFMUywgTUFYX0hVRSwgTUFYX0xBQiwgTUFYX0xDSF9DLCBNaXgsIFBDRU5ULCBWQUxJRF9DT0xPUl9PQkpFQ1RTIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5leHBvcnQgY29uc3QgZ2V0T3JkZXJlZEFycmF5U3RyaW5nID0gKGtleXMpID0+IFsuLi5rZXlzXS5zb3J0KCkuam9pbignJykudG9VcHBlckNhc2UoKTtcbmV4cG9ydCBjb25zdCBpc1N0cmluZyA9IChpbnB1dCkgPT4gdHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJztcbmV4cG9ydCBjb25zdCBpc051bWJlciA9IChpbnB1dCkgPT4gdHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJztcbmV4cG9ydCBjb25zdCBpc0Jvb2xlYW4gPSAoaW5wdXQpID0+IHR5cGVvZiBpbnB1dCA9PT0gJ2Jvb2xlYW4nO1xuZXhwb3J0IGNvbnN0IGlzVW5kZWZpbmVkID0gKGlucHV0KSA9PiBpbnB1dCA9PT0gdW5kZWZpbmVkO1xuZXhwb3J0IGNvbnN0IGdldENvbG9yTW9kZWwgPSAoY29sb3IpID0+IHtcbiAgICByZXR1cm4gVkFMSURfQ09MT1JfT0JKRUNUU1tnZXRPcmRlcmVkQXJyYXlTdHJpbmcoT2JqZWN0LmtleXMoY29sb3IpKV07XG59O1xuZXhwb3J0IGNvbnN0IGlzUkdCT2JqZWN0ID0gKGNvbG9yKSA9PiBnZXRDb2xvck1vZGVsKGNvbG9yKSA9PT0gQ29sb3JNb2RlbC5SR0I7XG5leHBvcnQgY29uc3QgaXNIU0xPYmplY3QgPSAoY29sb3IpID0+IGdldENvbG9yTW9kZWwoY29sb3IpID09PSBDb2xvck1vZGVsLkhTTDtcbmV4cG9ydCBjb25zdCBpc0hXQk9iamVjdCA9IChjb2xvcikgPT4gZ2V0Q29sb3JNb2RlbChjb2xvcikgPT09IENvbG9yTW9kZWwuSFdCO1xuZXhwb3J0IGNvbnN0IGlzQ0lFTGFiT2JqZWN0ID0gKGNvbG9yKSA9PiBnZXRDb2xvck1vZGVsKGNvbG9yKSA9PT0gQ29sb3JNb2RlbC5DSUVMYWI7XG5leHBvcnQgY29uc3QgaXNMQ0hPYmplY3QgPSAoY29sb3IpID0+IGdldENvbG9yTW9kZWwoY29sb3IpID09PSBDb2xvck1vZGVsLkxDSDtcbmV4cG9ydCBjb25zdCBpc0NNWUtPYmplY3QgPSAoY29sb3IpID0+IGdldENvbG9yTW9kZWwoY29sb3IpID09PSBDb2xvck1vZGVsLkNNWUs7XG5leHBvcnQgY29uc3QgcGVyY2VudE51bWJlciA9IChwZXJjZW50KSA9PiB7XG4gICAgcmV0dXJuICtgJHtwZXJjZW50fWAucmVwbGFjZShQQ0VOVCwgJyQxJyk7XG59O1xuZXhwb3J0IGNvbnN0IHBlcmNlbnQgPSAocGVyY2VudCkgPT4gUENFTlQudGVzdChgJHtwZXJjZW50fWApXG4gICAgPyBwZXJjZW50TnVtYmVyKHBlcmNlbnQpXG4gICAgOiBNYXRoLm1pbigrcGVyY2VudCwgMTAwKTtcbmV4cG9ydCBjb25zdCBnZXRERUMgPSAoaGV4KSA9PiB7XG4gICAgaWYgKGhleC5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgaGV4ICs9IGhleDtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlSW50KGhleCwgMTYpO1xufTtcbmV4cG9ydCBjb25zdCBnZXRIRVggPSAobnVtYmVyKSA9PiB7XG4gICAgY29uc3QgaGV4ID0gcm91bmQobnVtYmVyLCAwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcbiAgICBpZiAoaGV4Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gYDB4MCR7aGV4fWA7XG4gICAgfVxuICAgIHJldHVybiBgMHgke2hleH1gO1xufTtcbmV4cG9ydCBjb25zdCB0b0hFWCA9IChoKSA9PiB7XG4gICAgbGV0IGhleCA9IHJvdW5kKGgsIDApLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmIChoZXgubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIGhleCA9IGAwJHtoZXh9YDtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbn07XG5leHBvcnQgY29uc3QgZnJvbTI1NU51bWJlclRvUGVyY2VudCA9ICh2YWx1ZSwgZGVjaW1hbHMpID0+IHJvdW5kKHZhbHVlIC8gQkFTRV8yNTUgKiAxMDAsIGRlY2ltYWxzKTtcbmV4cG9ydCBjb25zdCBmcm9tMTI1TnVtYmVyVG9QZXJjZW50ID0gKHZhbHVlLCBkZWNpbWFscykgPT4gcm91bmQodmFsdWUgLyBNQVhfTEFCICogMTAwLCBkZWNpbWFscyk7XG5leHBvcnQgY29uc3QgZnJvbTE1ME51bWJlclRvUGVyY2VudCA9ICh2YWx1ZSwgZGVjaW1hbHMpID0+IHJvdW5kKHZhbHVlIC8gTUFYX0xDSF9DICogMTAwLCBkZWNpbWFscyk7XG5leHBvcnQgY29uc3QgZ2V0QmFzZTI1NU51bWJlciA9IChjb2xvciwgYWxwaGEgPSBmYWxzZSkgPT4ge1xuICAgIGlmICghYWxwaGEgJiYgUENFTlQudGVzdChjb2xvcikpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKEJBU0VfMjU1ICogcGVyY2VudE51bWJlcihjb2xvcikgLyAxMDAsIEJBU0VfMjU1KTtcbiAgICB9XG4gICAgaWYgKEhFWC50ZXN0KGNvbG9yKSkge1xuICAgICAgICBpZiAoY29sb3IubGVuZ3RoID09PSAzKSB7XG4gICAgICAgICAgICBjb2xvciArPSBjb2xvci5zbGljZSgtMSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFscGhhXG4gICAgICAgICAgICA/IHJvdW5kKGNvbG9yKSAvIEJBU0VfMjU1XG4gICAgICAgICAgICA6IHJvdW5kKGNvbG9yKTtcbiAgICB9XG4gICAgcmV0dXJuIE1hdGgubWluKCtjb2xvciwgYWxwaGEgPyAxIDogQkFTRV8yNTUpO1xufTtcbmV4cG9ydCBjb25zdCBnZXRCYXNlMTI1TnVtYmVyID0gKGNvbG9yKSA9PiB7XG4gICAgaWYgKFBDRU5ULnRlc3QoY29sb3IpKSB7XG4gICAgICAgIHJldHVybiBtaW5tYXgoTUFYX0xBQiAqIHBlcmNlbnROdW1iZXIoY29sb3IpIC8gMTAwLCAtTUFYX0xBQiwgTUFYX0xBQik7XG4gICAgfVxuICAgIHJldHVybiBtaW5tYXgoK2NvbG9yLCAtTUFYX0xBQiwgTUFYX0xBQik7XG59O1xuZXhwb3J0IGNvbnN0IGdldEJhc2UxNTBOdW1iZXIgPSAoY29sb3IpID0+IHtcbiAgICBpZiAoUENFTlQudGVzdChjb2xvcikpIHtcbiAgICAgICAgcmV0dXJuIG1pbm1heChNQVhfTENIX0MgKiBwZXJjZW50TnVtYmVyKGNvbG9yKSAvIDEwMCwgLU1BWF9MQ0hfQywgTUFYX0xDSF9DKTtcbiAgICB9XG4gICAgcmV0dXJuIG1pbm1heCgrY29sb3IsIC1NQVhfTENIX0MsIE1BWF9MQ0hfQyk7XG59O1xuZXhwb3J0IGNvbnN0IGdldENNWUtOdW1iZXIgPSAoY29sb3IsIGJhc2UxMDApID0+IHtcbiAgICBjb25zdCB2YWx1ZSA9IFBDRU5ULnRlc3QoY29sb3IpXG4gICAgICAgID8gcGVyY2VudE51bWJlcihjb2xvcilcbiAgICAgICAgOiArY29sb3I7XG4gICAgaWYgKGJhc2UxMDApIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWluKHZhbHVlICogMTAwLCAxMDApO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5taW4odmFsdWUsIDEwMCk7XG59O1xuZXhwb3J0IGNvbnN0IHJvdW5kID0gKHZhbHVlLCBkZWNpbWFscyA9IE1BWF9ERUNJTUFMUykgPT4ge1xuICAgIGNvbnN0IGV4cCA9IE1hdGgucG93KDEwLCBkZWNpbWFscyk7XG4gICAgcmV0dXJuIE1hdGgucm91bmQoK3ZhbHVlICogZXhwKSAvIGV4cDtcbn07XG5leHBvcnQgY29uc3QgbWlubWF4ID0gKG4sIG1pbiwgbWF4KSA9PiBNYXRoLm1heChtaW4sIE1hdGgubWluKG4sIG1heCkpO1xuZXhwb3J0IGNvbnN0IGRlZ3JlZXMgPSAocmFkaWFuKSA9PiByYWRpYW4gKiAxODAgLyBNYXRoLlBJO1xuZXhwb3J0IGNvbnN0IHJhZGlhbnMgPSAoZGVncmVlcykgPT4gZGVncmVlcyAqIE1hdGguUEkgLyAxODA7XG5leHBvcnQgY29uc3Qgbm9ybWFsaXplSHVlID0gKGh1ZSkgPT4ge1xuICAgIGlmIChpc1N0cmluZyhodWUpKSB7XG4gICAgICAgIGNvbnN0IG1hdGNoZXMgPSBodWUubWF0Y2goSFNMX0hVRSk7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IG1hdGNoZXMuZ3JvdXBzO1xuICAgICAgICBjb25zdCB2YWx1ZSA9ICtncm91cHMubnVtYmVyO1xuICAgICAgICBjb25zdCB1bml0cyA9IGdyb3Vwcy51bml0cztcbiAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5SQURJQU5TOlxuICAgICAgICAgICAgICAgIGh1ZSA9IHJvdW5kKGRlZ3JlZXModmFsdWUpKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uVFVSTlM6XG4gICAgICAgICAgICAgICAgaHVlID0gcm91bmQodmFsdWUgKiBNQVhfSFVFKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uR1JBRElBTlM6XG4gICAgICAgICAgICAgICAgaHVlID0gcm91bmQoOSAvIDEwICogdmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5ERUdSRUVTOlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBodWUgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoaHVlID49IE1BWF9IVUUgfHwgaHVlIDwgMCkge1xuICAgICAgICBodWUgLT0gTWF0aC5mbG9vcihodWUgLyBNQVhfSFVFKSAqIE1BWF9IVUU7XG4gICAgfVxuICAgIHJldHVybiBodWU7XG59O1xuZXhwb3J0IGNvbnN0IG5vcm1hbGl6ZUFscGhhID0gKGFscGhhKSA9PiB7XG4gICAgaWYgKGlzU3RyaW5nKGFscGhhKSkge1xuICAgICAgICBpZiAoUENFTlQudGVzdChhbHBoYSkpIHtcbiAgICAgICAgICAgIGFscGhhID0gcGVyY2VudE51bWJlcihhbHBoYSkgLyAxMDA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhbHBoYSA9ICthbHBoYTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gKGlzTmFOKCthbHBoYSkgfHwgYWxwaGEgPiBNQVhfQUxQSEEpID8gTUFYX0FMUEhBIDogcm91bmQoYWxwaGEpO1xufTtcbmV4cG9ydCBjb25zdCB0cmFuc2xhdGVEZWdyZWVzID0gKGRlZ3JlZXMsIHVuaXRzKSA9PiB7XG4gICAgbGV0IGh1ZTtcbiAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uUkFESUFOUzpcbiAgICAgICAgICAgIGh1ZSA9IHJvdW5kKHJhZGlhbnMoZGVncmVlcykpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgQW5nbGVzVW5pdEVudW0uVFVSTlM6XG4gICAgICAgICAgICBodWUgPSByb3VuZChkZWdyZWVzIC8gTUFYX0hVRSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5HUkFESUFOUzpcbiAgICAgICAgICAgIGh1ZSA9IHJvdW5kKEdSQURJQU5TICogZGVncmVlcyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBBbmdsZXNVbml0RW51bS5ERUdSRUVTOlxuICAgICAgICBjYXNlIEFuZ2xlc1VuaXRFbnVtLk5PTkU6XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBodWUgPSBkZWdyZWVzO1xuICAgIH1cbiAgICByZXR1cm4gaHVlO1xufTtcbmV4cG9ydCBjb25zdCBpc0hhcm1vbnkgPSAocGFyYW0pID0+IHtcbiAgICByZXR1cm4gYCR7cGFyYW19YCBpbiBIYXJtb255O1xufTtcbmV4cG9ydCBjb25zdCBpc01peCA9IChwYXJhbSkgPT4ge1xuICAgIHJldHVybiBgJHtwYXJhbX1gIGluIE1peDtcbn07XG5leHBvcnQgY29uc3QgZ2V0QW5nbGVVbml0ID0gKHVuaXQpID0+IHtcbiAgICBpZiAodW5pdCkge1xuICAgICAgICBjb25zdCBhbmdsZVVuaXRNYXRjaCA9IHVuaXQubWF0Y2goSFNMX0hVRSk7XG4gICAgICAgIGNvbnN0IGFuZ2xlVW5pdCA9IGFuZ2xlVW5pdE1hdGNoLmdyb3Vwcy51bml0cztcbiAgICAgICAgcmV0dXJuIGFuZ2xlVW5pdCA9PT0gJydcbiAgICAgICAgICAgID8gQW5nbGVzVW5pdEVudW0uTk9ORVxuICAgICAgICAgICAgOiBhbmdsZVVuaXQ7XG4gICAgfVxuICAgIHJldHVybiBBbmdsZXNVbml0RW51bS5OT05FO1xufTtcbiIsImltcG9ydCB7IEJBU0VfMjU1LCBNQVhfQUxQSEEgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IGRlZ3JlZXMsIG1pbm1heCwgbm9ybWFsaXplSHVlLCByYWRpYW5zLCByb3VuZCB9IGZyb20gJyN1dGlsaXRpZXMnO1xuY29uc3QgTUFUUklYX0xSR0JfWFlaX0Q1MCA9IFtcbiAgICBbMC40MzYwNzQ3LCAwLjM4NTA2NDksIDAuMTQzMDgwNF0sXG4gICAgWzAuMjIyNTA0NSwgMC43MTY4Nzg2LCAwLjA2MDYxNjldLFxuICAgIFswLjAxMzkzMjIsIDAuMDk3MTA0NSwgMC43MTQxNzMzXVxuXTtcbmNvbnN0IE1BVFJJWF9YWVpfRDUwX0xSR0IgPSBbXG4gICAgWzMuMTMzODU2MSwgLTEuNjE2ODY2NywgLTAuNDkwNjE0Nl0sXG4gICAgWy0wLjk3ODc2ODQsIDEuOTE2MTQxNSwgMC4wMzM0NTRdLFxuICAgIFswLjA3MTk0NTMsIC0wLjIyODk5MTQsIDEuNDA1MjQyN11cbl07XG5jb25zdCBUUklTVElNVUxVU19ENTAgPSBNQVRSSVhfTFJHQl9YWVpfRDUwLm1hcCgobWF0cml4KSA9PiB7XG4gICAgcmV0dXJuIG1hdHJpeC5yZWR1Y2UoKHN1bSwgdmFsdWUpID0+IHN1bSArIHZhbHVlLCAwKTtcbn0pO1xuY29uc3QgaHVlVG9SZ2IgPSAodDEsIHQyLCBodWUpID0+IHtcbiAgICBpZiAoaHVlIDwgMCkge1xuICAgICAgICBodWUgKz0gNjtcbiAgICB9XG4gICAgaWYgKGh1ZSA+PSA2KSB7XG4gICAgICAgIGh1ZSAtPSA2O1xuICAgIH1cbiAgICBpZiAoaHVlIDwgMSkge1xuICAgICAgICByZXR1cm4gcm91bmQoKCh0MiAtIHQxKSAqIGh1ZSArIHQxKSAqIEJBU0VfMjU1KTtcbiAgICB9XG4gICAgZWxzZSBpZiAoaHVlIDwgMykge1xuICAgICAgICByZXR1cm4gcm91bmQodDIgKiBCQVNFXzI1NSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGh1ZSA8IDQpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKCgodDIgLSB0MSkgKiAoNCAtIGh1ZSkgKyB0MSkgKiBCQVNFXzI1NSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gcm91bmQodDEgKiBCQVNFXzI1NSk7XG4gICAgfVxufTtcbmNvbnN0IHJnYlRvTGluZWFyTGlnaHRSZ2IgPSAodmFsdWUpID0+IHtcbiAgICByZXR1cm4gdmFsdWUgPD0gMC4wNDA0NVxuICAgICAgICA/IHZhbHVlIC8gMTIuOTJcbiAgICAgICAgOiAoKHZhbHVlICsgMC4wNTUpIC8gMS4wNTUpICoqIDIuNDtcbn07XG5jb25zdCBsaW5lYXJMaWdodFJnYlRvUmdiID0gKHZhbHVlKSA9PiB7XG4gICAgcmV0dXJuIHZhbHVlIDw9IDAuMDAzMTMwOFxuICAgICAgICA/IDEyLjkyICogdmFsdWVcbiAgICAgICAgOiAxLjA1NSAqICh2YWx1ZSAqKiAoMSAvIDIuNCkpIC0gMC4wNTU7XG59O1xuY29uc3QgbWF0cml4VmVjdG9yTXVsdGlwbGljYXRpb24gPSAodjEsIHYyLCB2MywgbWF0cml4KSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gWzAsIDAsIDBdO1xuICAgIGNvbnN0IGxpbmVhclJnYiA9IFt2MSwgdjIsIHYzXTtcbiAgICBtYXRyaXguZm9yRWFjaCgoYXJyYXksIGluZGV4KSA9PiB7XG4gICAgICAgIGFycmF5LmZvckVhY2goKHZhbHVlLCBtaW5kZXgpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdFtpbmRleF0gKz0gdmFsdWUgKiBsaW5lYXJSZ2JbbWluZGV4XTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5jb25zdCBmcm9tX0NJRV9YWVpfRDUwX3RvX0NJRV9MQUIgPSAoeCwgeSwgeikgPT4ge1xuICAgIGNvbnN0IGYgPSAodCkgPT4ge1xuICAgICAgICByZXR1cm4gdCA+ICg2IC8gMjkpICoqIDNcbiAgICAgICAgICAgID8gTWF0aC5jYnJ0KHQpXG4gICAgICAgICAgICA6IHQgLyAoMyAqICg2IC8gMjkpICoqIDIpICsgKDQgLyAyOSk7XG4gICAgfTtcbiAgICBjb25zdCBmeCA9IGYoeCAvIFRSSVNUSU1VTFVTX0Q1MFswXSk7XG4gICAgY29uc3QgZnkgPSBmKHkgLyBUUklTVElNVUxVU19ENTBbMV0pO1xuICAgIGNvbnN0IGZ6ID0gZih6IC8gVFJJU1RJTVVMVVNfRDUwWzJdKTtcbiAgICByZXR1cm4gW1xuICAgICAgICAxMTYgKiBmeSAtIDE2LFxuICAgICAgICA1MDAgKiAoZnggLSBmeSksXG4gICAgICAgIDIwMCAqIChmeSAtIGZ6KVxuICAgIF07XG59O1xuY29uc3QgZnJvbV9DSUVfTEFCX3RvX0NJRV9YWVpfRDUwID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBmID0gKHQpID0+IHtcbiAgICAgICAgcmV0dXJuIHQgPiA2IC8gMjlcbiAgICAgICAgICAgID8gdCAqKiAzXG4gICAgICAgICAgICA6IDMgKiAoNiAvIDI5KSAqKiAyICogKHQgLSA0IC8gMjkpO1xuICAgIH07XG4gICAgY29uc3QgZmwgPSAoTCArIDE2KSAvIDExNjtcbiAgICBjb25zdCBmYSA9IGEgLyA1MDA7XG4gICAgY29uc3QgZmIgPSBiIC8gMjAwO1xuICAgIHJldHVybiBbXG4gICAgICAgIFRSSVNUSU1VTFVTX0Q1MFswXSAqIGYoZmwgKyBmYSksXG4gICAgICAgIFRSSVNUSU1VTFVTX0Q1MFsxXSAqIGYoZmwpLFxuICAgICAgICBUUklTVElNVUxVU19ENTBbMl0gKiBmKGZsIC0gZmIpXG4gICAgXTtcbn07XG5leHBvcnQgY29uc3QgaHNsVG9SZ2IgPSAoSCwgUywgTCkgPT4ge1xuICAgIEggLz0gNjA7XG4gICAgUyAvPSAxMDA7XG4gICAgTCAvPSAxMDA7XG4gICAgY29uc3QgdDIgPSAoTCA8PSAuNSlcbiAgICAgICAgPyBMICogKFMgKyAxKVxuICAgICAgICA6IEwgKyBTIC0gKEwgKiBTKTtcbiAgICBjb25zdCB0MSA9IEwgKiAyIC0gdDI7XG4gICAgY29uc3QgUiA9IGh1ZVRvUmdiKHQxLCB0MiwgSCArIDIpO1xuICAgIGNvbnN0IEcgPSBodWVUb1JnYih0MSwgdDIsIEgpO1xuICAgIGNvbnN0IEIgPSBodWVUb1JnYih0MSwgdDIsIEggLSAyKTtcbiAgICByZXR1cm4geyBSLCBHLCBCIH07XG59O1xuZXhwb3J0IGNvbnN0IHJnYlRvSHNsID0gKFIsIEcsIEIsIEEgPSAxKSA9PiB7XG4gICAgUiAvPSBCQVNFXzI1NTtcbiAgICBHIC89IEJBU0VfMjU1O1xuICAgIEIgLz0gQkFTRV8yNTU7XG4gICAgQSA9IE1hdGgubWluKEEsIE1BWF9BTFBIQSk7XG4gICAgY29uc3QgTUFYID0gTWF0aC5tYXgoUiwgRywgQik7XG4gICAgY29uc3QgTUlOID0gTWF0aC5taW4oUiwgRywgQik7XG4gICAgY29uc3QgRCA9IE1BWCAtIE1JTjtcbiAgICBsZXQgSCA9IDA7XG4gICAgbGV0IFMgPSAwO1xuICAgIGNvbnN0IEwgPSAoTUFYICsgTUlOKSAvIDI7XG4gICAgaWYgKEQgIT09IDApIHtcbiAgICAgICAgc3dpdGNoIChNQVgpIHtcbiAgICAgICAgICAgIGNhc2UgUjpcbiAgICAgICAgICAgICAgICBIID0gKChHIC0gQikgLyBEKSAlIDY7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEc6XG4gICAgICAgICAgICAgICAgSCA9IChCIC0gUikgLyBEICsgMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQjpcbiAgICAgICAgICAgICAgICBIID0gKFIgLSBHKSAvIEQgKyA0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIEggPSByb3VuZChIICogNjApO1xuICAgICAgICBpZiAoSCA8IDApIHtcbiAgICAgICAgICAgIEggKz0gMzYwO1xuICAgICAgICB9XG4gICAgICAgIFMgPSBEIC8gKDEgLSBNYXRoLmFicygyICogTCAtIDEpKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgSCxcbiAgICAgICAgUzogcm91bmQoUyAqIDEwMCksXG4gICAgICAgIEw6IHJvdW5kKEwgKiAxMDApLFxuICAgICAgICBBXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9MYWIgPSAoUiwgRywgQikgPT4ge1xuICAgIGNvbnN0IExJTkVBUl9MSUdIVF9SR0IgPSBbXG4gICAgICAgIFIgLyBCQVNFXzI1NSxcbiAgICAgICAgRyAvIEJBU0VfMjU1LFxuICAgICAgICBCIC8gQkFTRV8yNTVcbiAgICBdLm1hcChyZ2JUb0xpbmVhckxpZ2h0UmdiKTtcbiAgICBjb25zdCBDSUVfWFlaX0Q1MCA9IG1hdHJpeFZlY3Rvck11bHRpcGxpY2F0aW9uKExJTkVBUl9MSUdIVF9SR0JbMF0sIExJTkVBUl9MSUdIVF9SR0JbMV0sIExJTkVBUl9MSUdIVF9SR0JbMl0sIE1BVFJJWF9MUkdCX1hZWl9ENTApO1xuICAgIGNvbnN0IENJRV9MQUIgPSBmcm9tX0NJRV9YWVpfRDUwX3RvX0NJRV9MQUIoQ0lFX1hZWl9ENTBbMF0sIENJRV9YWVpfRDUwWzFdLCBDSUVfWFlaX0Q1MFsyXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgTDogQ0lFX0xBQlswXSxcbiAgICAgICAgYTogQ0lFX0xBQlsxXSxcbiAgICAgICAgYjogQ0lFX0xBQlsyXVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGxhYlRvUmdiID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBDSUVfWFlaX0Q1MCA9IGZyb21fQ0lFX0xBQl90b19DSUVfWFlaX0Q1MChMLCBhLCBiKTtcbiAgICBjb25zdCBMSU5FQVJfTElHSFRfUkdCID0gbWF0cml4VmVjdG9yTXVsdGlwbGljYXRpb24oQ0lFX1hZWl9ENTBbMF0sIENJRV9YWVpfRDUwWzFdLCBDSUVfWFlaX0Q1MFsyXSwgTUFUUklYX1hZWl9ENTBfTFJHQik7XG4gICAgY29uc3QgcmdiID0gTElORUFSX0xJR0hUX1JHQi5tYXAobGluZWFyTGlnaHRSZ2JUb1JnYik7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUjogbWlubWF4KHJnYlswXSAqIEJBU0VfMjU1LCAwLCBCQVNFXzI1NSksXG4gICAgICAgIEc6IG1pbm1heChyZ2JbMV0gKiBCQVNFXzI1NSwgMCwgQkFTRV8yNTUpLFxuICAgICAgICBCOiBtaW5tYXgocmdiWzJdICogQkFTRV8yNTUsIDAsIEJBU0VfMjU1KVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGxhYlRvTGNoID0gKEwsIGEsIGIpID0+IHtcbiAgICBjb25zdCBDID0gTWF0aC5zcXJ0KGEgKiogMiArIGIgKiogMik7XG4gICAgY29uc3QgSCA9IGRlZ3JlZXMoTWF0aC5hdGFuMihiLCBhKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgTCxcbiAgICAgICAgQyxcbiAgICAgICAgSDogbm9ybWFsaXplSHVlKEgpXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgbGNoVG9MYWIgPSAoTCwgQywgSCkgPT4ge1xuICAgIGNvbnN0IHJhZEggPSByYWRpYW5zKEgpO1xuICAgIGNvbnN0IGEgPSBDICogTWF0aC5jb3MocmFkSCk7XG4gICAgY29uc3QgYiA9IEMgKiBNYXRoLnNpbihyYWRIKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBMLFxuICAgICAgICBhLFxuICAgICAgICBiXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9MY2ggPSAoUiwgRywgQikgPT4ge1xuICAgIGNvbnN0IGxhYiA9IHJnYlRvTGFiKFIsIEcsIEIpO1xuICAgIHJldHVybiBsYWJUb0xjaChsYWIuTCwgbGFiLmEsIGxhYi5iKTtcbn07XG5leHBvcnQgY29uc3QgbGNoVG9SZ2IgPSAoTCwgQywgSCkgPT4ge1xuICAgIGNvbnN0IGxhYiA9IGxjaFRvTGFiKEwsIEMsIEgpO1xuICAgIHJldHVybiBsYWJUb1JnYihsYWIuTCwgbGFiLmEsIGxhYi5iKTtcbn07XG5leHBvcnQgY29uc3QgcmdiVG9Id2IgPSAoUiwgRywgQiwgQSA9IDEpID0+IHtcbiAgICBjb25zdCBoc2wgPSByZ2JUb0hzbChSLCBHLCBCLCBBKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBIOiBoc2wuSCxcbiAgICAgICAgVzogcm91bmQoTWF0aC5taW4oUiwgRywgQikgLyBCQVNFXzI1NSAqIDEwMCksXG4gICAgICAgIEI6IHJvdW5kKCgxIC0gTWF0aC5tYXgoUiwgRywgQikgLyBCQVNFXzI1NSkgKiAxMDApLFxuICAgICAgICBBXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgaHdiVG9SZ2IgPSAoSCwgVywgQikgPT4ge1xuICAgIFcgLz0gMTAwO1xuICAgIEIgLz0gMTAwO1xuICAgIGNvbnN0IHYgPSAxIC0gQjtcbiAgICBjb25zdCBjID0gdiAtIFc7XG4gICAgY29uc3QgeCA9IGMgKiAoMSAtIE1hdGguYWJzKChIIC8gNjApICUgMiAtIDEpKTtcbiAgICBsZXQgcmdiUjtcbiAgICBsZXQgcmdiRztcbiAgICBsZXQgcmdiQjtcbiAgICBpZiAoSCA8IDYwKSB7XG4gICAgICAgIHJnYlIgPSBjO1xuICAgICAgICByZ2JHID0geDtcbiAgICAgICAgcmdiQiA9IDA7XG4gICAgfVxuICAgIGVsc2UgaWYgKEggPj0gNjAgJiYgSCA8IDEyMCkge1xuICAgICAgICByZ2JSID0geDtcbiAgICAgICAgcmdiRyA9IGM7XG4gICAgICAgIHJnYkIgPSAwO1xuICAgIH1cbiAgICBlbHNlIGlmIChIID49IDEyMCAmJiBIIDwgMTgwKSB7XG4gICAgICAgIHJnYlIgPSAwO1xuICAgICAgICByZ2JHID0gYztcbiAgICAgICAgcmdiQiA9IHg7XG4gICAgfVxuICAgIGVsc2UgaWYgKEggPj0gMTgwICYmIEggPCAyNDApIHtcbiAgICAgICAgcmdiUiA9IDA7XG4gICAgICAgIHJnYkcgPSB4O1xuICAgICAgICByZ2JCID0gYztcbiAgICB9XG4gICAgZWxzZSBpZiAoSCA+PSAyNDAgJiYgSCA8IDMwMCkge1xuICAgICAgICByZ2JSID0geDtcbiAgICAgICAgcmdiRyA9IDA7XG4gICAgICAgIHJnYkIgPSBjO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmdiUiA9IGM7XG4gICAgICAgIHJnYkcgPSAwO1xuICAgICAgICByZ2JCID0geDtcbiAgICB9XG4gICAgcmdiUiArPSBXO1xuICAgIHJnYkcgKz0gVztcbiAgICByZ2JCICs9IFc7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgUjogbWlubWF4KHJnYlIgKiBCQVNFXzI1NSwgMCwgQkFTRV8yNTUpLFxuICAgICAgICBHOiBtaW5tYXgocmdiRyAqIEJBU0VfMjU1LCAwLCBCQVNFXzI1NSksXG4gICAgICAgIEI6IG1pbm1heChyZ2JCICogQkFTRV8yNTUsIDAsIEJBU0VfMjU1KVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IGNteWtUb1JnYiA9IChDLCBNLCBZLCBLKSA9PiB7XG4gICAgSyA9IDEgLSBLO1xuICAgIHJldHVybiB7XG4gICAgICAgIFI6IG1pbm1heChyb3VuZChCQVNFXzI1NSAqICgxIC0gQykgKiBLKSwgMCwgQkFTRV8yNTUpLFxuICAgICAgICBHOiBtaW5tYXgocm91bmQoQkFTRV8yNTUgKiAoMSAtIE0pICogSyksIDAsIEJBU0VfMjU1KSxcbiAgICAgICAgQjogbWlubWF4KHJvdW5kKEJBU0VfMjU1ICogKDEgLSBZKSAqIEspLCAwLCBCQVNFXzI1NSlcbiAgICB9O1xufTtcbmV4cG9ydCBjb25zdCByZ2JUb0NteWsgPSAoUiwgRywgQikgPT4ge1xuICAgIFIgLz0gQkFTRV8yNTU7XG4gICAgRyAvPSBCQVNFXzI1NTtcbiAgICBCIC89IEJBU0VfMjU1O1xuICAgIGNvbnN0IEsgPSAxIC0gTWF0aC5tYXgoUiwgRywgQik7XG4gICAgY29uc3QgSzEgPSAxIC0gSztcbiAgICBjb25zdCBDID0gSzEgJiYgKEsxIC0gUikgLyBLMTtcbiAgICBjb25zdCBNID0gSzEgJiYgKEsxIC0gRykgLyBLMTtcbiAgICBjb25zdCBZID0gSzEgJiYgKEsxIC0gQikgLyBLMTtcbiAgICByZXR1cm4ge1xuICAgICAgICBDOiByb3VuZChDICogMTAwKSxcbiAgICAgICAgTTogcm91bmQoTSAqIDEwMCksXG4gICAgICAgIFk6IHJvdW5kKFkgKiAxMDApLFxuICAgICAgICBLOiByb3VuZChLICogMTAwKVxuICAgIH07XG59O1xuZXhwb3J0IGNvbnN0IHJnYlRvUnliID0gKFIsIEcsIEIpID0+IHtcbiAgICBjb25zdCBJdyA9IE1hdGgubWluKFIsIEcsIEIpO1xuICAgIGNvbnN0IEliID0gTWF0aC5taW4oQkFTRV8yNTUgLSBSLCBCQVNFXzI1NSAtIEcsIEJBU0VfMjU1IC0gQik7XG4gICAgY29uc3QgclJnYiA9IFIgLSBJdztcbiAgICBjb25zdCBnUmdiID0gRyAtIEl3O1xuICAgIGNvbnN0IGJSZ2IgPSBCIC0gSXc7XG4gICAgY29uc3QgbWluUmcgPSBNYXRoLm1pbihyUmdiLCBnUmdiKTtcbiAgICBjb25zdCByUnliID0gclJnYiAtIG1pblJnO1xuICAgIGNvbnN0IHlSeWIgPSAoZ1JnYiArIG1pblJnKSAvIDI7XG4gICAgY29uc3QgYlJ5YiA9IChiUmdiICsgZ1JnYiAtIG1pblJnKSAvIDI7XG4gICAgY29uc3QgbiA9IE1hdGgubWF4KHJSeWIsIHlSeWIsIGJSeWIpIC8gTWF0aC5tYXgoclJnYiwgZ1JnYiwgYlJnYik7XG4gICAgY29uc3QgTiA9IGlzTmFOKG4pIHx8IG4gPT09IEluZmluaXR5IHx8IG4gPD0gMCA/IDEgOiBuO1xuICAgIHJldHVybiB7XG4gICAgICAgIFI6IHJSeWIgLyBOICsgSWIsXG4gICAgICAgIFk6IHlSeWIgLyBOICsgSWIsXG4gICAgICAgIEI6IGJSeWIgLyBOICsgSWJcbiAgICB9O1xufTtcbmV4cG9ydCBjb25zdCByeWJUb1JnYiA9IChSLCBZLCBCKSA9PiB7XG4gICAgY29uc3QgSXcgPSBNYXRoLm1pbihSLCBZLCBCKTtcbiAgICBjb25zdCBJYiA9IE1hdGgubWluKEJBU0VfMjU1IC0gUiwgQkFTRV8yNTUgLSBZLCBCQVNFXzI1NSAtIEIpO1xuICAgIGNvbnN0IHJSeWIgPSBSIC0gSXc7XG4gICAgY29uc3QgeVJ5YiA9IFkgLSBJdztcbiAgICBjb25zdCBiUnliID0gQiAtIEl3O1xuICAgIGNvbnN0IG1pblliID0gTWF0aC5taW4oeVJ5YiwgYlJ5Yik7XG4gICAgY29uc3QgclJnYiA9IHJSeWIgKyB5UnliIC0gbWluWWI7XG4gICAgY29uc3QgZ1JnYiA9IHlSeWIgKyBtaW5ZYjtcbiAgICBjb25zdCBiUmdiID0gMiAqIChiUnliIC0gbWluWWIpO1xuICAgIGNvbnN0IG4gPSBNYXRoLm1heChyUmdiLCBnUmdiLCBiUmdiKSAvIE1hdGgubWF4KHJSeWIsIHlSeWIsIGJSeWIpO1xuICAgIGNvbnN0IE4gPSBpc05hTihuKSB8fCBuID09PSBJbmZpbml0eSB8fCBuIDw9IDAgPyAxIDogbjtcbiAgICByZXR1cm4ge1xuICAgICAgICBSOiByUmdiIC8gTiArIEliLFxuICAgICAgICBHOiBnUmdiIC8gTiArIEliLFxuICAgICAgICBCOiBiUmdiIC8gTiArIEliXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgaHVlUnliID0gKGh1ZSwgdG9SeWIpID0+IHtcbiAgICBpZiAoaHVlIDwgMClcbiAgICAgICAgaHVlICs9IDM2MDtcbiAgICBpZiAoaHVlID4gMzYwKVxuICAgICAgICBodWUgLT0gMzYwO1xuICAgIGlmIChodWUgPT09IDM2MCB8fCBodWUgPT09IDApXG4gICAgICAgIHJldHVybiBodWU7XG4gICAgY29uc3QgbWFwMSA9IFtcbiAgICAgICAgWzAsIDEyMF0sXG4gICAgICAgIFsxMjAsIDE4MF0sXG4gICAgICAgIFsxODAsIDI0MF0sXG4gICAgICAgIFsyNDAsIDM2MF1cbiAgICBdO1xuICAgIGNvbnN0IG1hcDIgPSBbXG4gICAgICAgIFswLCA2MF0sXG4gICAgICAgIFs2MCwgMTIwXSxcbiAgICAgICAgWzEyMCwgMjQwXSxcbiAgICAgICAgWzI0MCwgMzYwXVxuICAgIF07XG4gICAgY29uc3QgZnJvbSA9IHRvUnliID8gbWFwMSA6IG1hcDI7XG4gICAgY29uc3QgdG8gPSB0b1J5YiA/IG1hcDIgOiBtYXAxO1xuICAgIGxldCBBID0gMDtcbiAgICBsZXQgQiA9IDA7XG4gICAgbGV0IEMgPSAwO1xuICAgIGxldCBEID0gMDtcbiAgICBmcm9tLmZpbmQoKGFyciwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGh1ZSA+PSBhcnJbMF0gJiYgaHVlIDwgYXJyWzFdKSB7XG4gICAgICAgICAgICBBID0gYXJyWzBdO1xuICAgICAgICAgICAgQiA9IGFyclsxXTtcbiAgICAgICAgICAgIEMgPSB0b1tpbmRleF1bMF07XG4gICAgICAgICAgICBEID0gdG9baW5kZXhdWzFdO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuICAgIHJldHVybiBDICsgKGh1ZSAtIEEpICogKChEIC0gQykgLyAoQiAtIEEpKTtcbn07XG4iLCJpbXBvcnQgeyBERUZBVUxUX09QVElPTlMsIEVSUk9SUyB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgaXNTdHJpbmcsIGlzVW5kZWZpbmVkIH0gZnJvbSAnI3V0aWxpdGllcyc7XG5leHBvcnQgY2xhc3MgQ29sb3JQYXJzZXJDb250ZXh0IHtcbiAgICBjb25zdHJ1Y3RvcihwYXJzZXJzKSB7XG4gICAgICAgIHRoaXMuX3BhcnNlcnMgPSBwYXJzZXJzO1xuICAgIH1cbiAgICBnZXRQYXJzZXIoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgcGFyc2VyID0gT2JqZWN0LnZhbHVlcyh0aGlzLl9wYXJzZXJzKS5maW5kKHBhcnNlciA9PiBwYXJzZXIuc3VwcG9ydHMoaW5wdXQpKTtcbiAgICAgICAgaWYgKHBhcnNlcikge1xuICAgICAgICAgICAgcmV0dXJuIHBhcnNlcjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoRVJST1JTLk5PVF9BQ0NFUFRFRF9JTlBVVCk7XG4gICAgfVxuICAgIHBhcnNlKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IHBhcnNlciA9IHRoaXMuZ2V0UGFyc2VyKGlucHV0KTtcbiAgICAgICAgcmV0dXJuIHBhcnNlci5wYXJzZShpbnB1dCwgdGhpcyk7XG4gICAgfVxuICAgIGNvbnZlcnQoaW5wdXQsIG1vZGVsLCBkZWNpbWFscyA9IERFRkFVTFRfT1BUSU9OUy5kZWNpbWFscywgd2l0aEFscGhhID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgY29sb3IgPSB0aGlzLnBhcnNlKGlucHV0KTtcbiAgICAgICAgY29uc3QgcGFyc2VyID0gdGhpcy5fcGFyc2Vyc1ttb2RlbF07XG4gICAgICAgIHJldHVybiBwYXJzZXIuY29udmVydChjb2xvciwgZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgfVxuICAgIGNvbnZlcnRDU1MoaW5wdXQsIG1vZGVsLCBvcHRpb25zID0ge30sIHdpdGhBbHBoYSA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IGNvbG9yID0gdGhpcy5wYXJzZShpbnB1dCk7XG4gICAgICAgIGNvbnN0IHBhcnNlciA9IHRoaXMuX3BhcnNlcnNbbW9kZWxdO1xuICAgICAgICByZXR1cm4gcGFyc2VyLmNvbnZlcnRDU1MoY29sb3IsIG9wdGlvbnMsIHdpdGhBbHBoYSk7XG4gICAgfVxufVxuZXhwb3J0IGNsYXNzIENvbG9yUGFyc2VyIHtcbiAgICBoYXNBbHBoYShpbnB1dCkge1xuICAgICAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRDU1NPcHRpb25zKGlucHV0KS5oYXNBbHBoYTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gIWlzVW5kZWZpbmVkKGlucHV0LkEpO1xuICAgIH1cbiAgICA7XG59XG4iLCJpbXBvcnQgeyBjbXlrVG9SZ2IsIGhzbFRvUmdiLCBod2JUb1JnYiwgbGFiVG9SZ2IsIGxjaFRvUmdiIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IGlzQ0lFTGFiT2JqZWN0LCBpc0NNWUtPYmplY3QsIGlzSFNMT2JqZWN0LCBpc0hXQk9iamVjdCwgaXNMQ0hPYmplY3QsIGlzVW5kZWZpbmVkIH0gZnJvbSAnI3V0aWxpdGllcyc7XG5jb25zdCBnZXRBbHBoYSA9IChjb2xvcikgPT4ge1xuICAgIGlmIChpc1VuZGVmaW5lZChjb2xvci5BKSkge1xuICAgICAgICByZXR1cm4ge307XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIEE6ICtjb2xvci5BXG4gICAgfTtcbn07XG5leHBvcnQgY29uc3QgZ2V0UkdCID0gKGNvbG9yKSA9PiB7XG4gICAgY29uc3QgYWxwaGEgPSBnZXRBbHBoYShjb2xvcik7XG4gICAgaWYgKGlzSFNMT2JqZWN0KGNvbG9yKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uaHNsVG9SZ2IoY29sb3IuSCwgY29sb3IuUywgY29sb3IuTCksXG4gICAgICAgICAgICAuLi5hbHBoYVxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoaXNIV0JPYmplY3QoY29sb3IpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5od2JUb1JnYihjb2xvci5ILCBjb2xvci5XLCBjb2xvci5CKSxcbiAgICAgICAgICAgIC4uLmFscGhhXG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChpc0NJRUxhYk9iamVjdChjb2xvcikpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLmxhYlRvUmdiKGNvbG9yLkwsIGNvbG9yLmEsIGNvbG9yLmIpLFxuICAgICAgICAgICAgLi4uYWxwaGFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgaWYgKGlzTENIT2JqZWN0KGNvbG9yKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubGNoVG9SZ2IoY29sb3IuTCwgY29sb3IuQywgY29sb3IuSCksXG4gICAgICAgICAgICAuLi5hbHBoYVxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoaXNDTVlLT2JqZWN0KGNvbG9yKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uY215a1RvUmdiKGNvbG9yLkMsIGNvbG9yLk0sIGNvbG9yLlksIGNvbG9yLkspLFxuICAgICAgICAgICAgLi4uYWxwaGFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbG9yO1xufTtcbiIsImltcG9ydCB7IEFuZ2xlc1VuaXRFbnVtLCBDb2xvclVuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IENPTE9SX1BST1BTLCBURU1QTEFURV9WQVIsIFZBTElEX0NPTE9SX09CSkVDVFMgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IGdldE9yZGVyZWRBcnJheVN0cmluZywgcm91bmQsIHRyYW5zbGF0ZURlZ3JlZXMgfSBmcm9tICcjdXRpbGl0aWVzJztcbmV4cG9ydCBjb25zdCBnZXRDU1NDb21tYSA9ICh3aXRoU3BhY2UpID0+IHdpdGhTcGFjZVxuICAgID8gJywgJ1xuICAgIDogJywnO1xuZXhwb3J0IGNvbnN0IHByZXBhcmVDb2xvckZvckNzcyA9IChjb2xvciwgdHJhbnNmb3JtZXIpID0+IHtcbiAgICBjb25zdCBwcm9wcyA9IGdldE9yZGVyZWRBcnJheVN0cmluZyhPYmplY3Qua2V5cyhjb2xvcikpO1xuICAgIGNvbnN0IG1vZGVsID0gVkFMSURfQ09MT1JfT0JKRUNUU1twcm9wc107XG4gICAgY29uc3Qga2V5cyA9IENPTE9SX1BST1BTW21vZGVsXTtcbiAgICByZXR1cm4ga2V5cy5yZWR1Y2UoKHJlc3VsdCwga2V5LCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbG9yW2tleV07XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICByZXN1bHQucHVzaCh0cmFuc2Zvcm1lcih2YWx1ZSwgaW5kZXgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIFtdKTtcbn07XG5leHBvcnQgY29uc3QgZ2V0UmVzdWx0RnJvbUNTU1RlbXBsYXRlID0gKHRlbXBsYXRlLCB2YXJzKSA9PiB7XG4gICAgcmV0dXJuIHRlbXBsYXRlLnJlcGxhY2UoVEVNUExBVEVfVkFSLCAoX19tYXRjaCwgaW5kZXhTdHIpID0+IHtcbiAgICAgICAgY29uc3QgaW5kZXggPSAraW5kZXhTdHIgLSAxO1xuICAgICAgICByZXR1cm4gYCR7dmFyc1tpbmRleF19YDtcbiAgICB9KTtcbn07XG5leHBvcnQgY29uc3QgZ2V0Q1NTQWxwaGEgPSAodmFsdWUsIG9wdGlvbnMsIGlnbm9yZUxlZ2FjeSA9IGZhbHNlKSA9PiB7XG4gICAgY29uc3QgeyBhbHBoYVVuaXQsIGxlZ2FjeUNTUywgZGVjaW1hbHMgfSA9IG9wdGlvbnM7XG4gICAgaWYgKGFscGhhVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UICYmXG4gICAgICAgICghbGVnYWN5Q1NTIHx8XG4gICAgICAgICAgICBpZ25vcmVMZWdhY3kpKSB7XG4gICAgICAgIHJldHVybiBgJHtyb3VuZCh2YWx1ZSAqIDEwMCwgZGVjaW1hbHMpfSVgO1xuICAgIH1cbiAgICByZXR1cm4gcm91bmQodmFsdWUsIGRlY2ltYWxzKTtcbn07XG5leHBvcnQgY29uc3QgYnVpbGRDU1NIdWVUcmFuc2Zvcm1lciA9IChvcHRpb25zKSA9PiB7XG4gICAgY29uc3QgeyBhbmdsZXNVbml0LCBkZWNpbWFscyB9ID0gb3B0aW9ucztcbiAgICByZXR1cm4gKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICBpZiAoaW5kZXggPT09IDAgJiZcbiAgICAgICAgICAgIGFuZ2xlc1VuaXQgIT09IEFuZ2xlc1VuaXRFbnVtLk5PTkUpIHtcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zbGF0ZWQgPSByb3VuZCh0cmFuc2xhdGVEZWdyZWVzKHZhbHVlLCBhbmdsZXNVbml0KSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgcmV0dXJuIGAke3RyYW5zbGF0ZWR9JHthbmdsZXNVbml0fWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGluZGV4ID09PSAzXG4gICAgICAgICAgICA/IGdldENTU0FscGhhKHZhbHVlLCBvcHRpb25zKVxuICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpO1xuICAgIH07XG59O1xuIiwiaW1wb3J0IHsgQkFTRV8yNTUsIENPTE9SX0tFWVMsIENvbG9yS2V5d29yZHMsIENvbG9yTW9kZWwsIENPTE9SUkVHUywgSEVYIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRSR0IgfSBmcm9tICcjY29sb3IvcmdiJztcbmltcG9ydCB7IGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSwgcHJlcGFyZUNvbG9yRm9yQ3NzIH0gZnJvbSAnI2Nzcyc7XG5pbXBvcnQgeyBnZXRERUMsIGdldEhFWCwgZ2V0QmFzZTI1NU51bWJlciwgaXNTdHJpbmcsIGlzVW5kZWZpbmVkLCBpc1JHQk9iamVjdCwgcm91bmQsIHRvSEVYIH0gZnJvbSAnI3V0aWxpdGllcyc7XG5pbXBvcnQgeyBDb2xvclBhcnNlciB9IGZyb20gJy4vQ29sb3JQYXJzZXJDb250ZXh0JztcbmV4cG9ydCBjbGFzcyBIRVhQYXJzZXIgZXh0ZW5kcyBDb2xvclBhcnNlciB7XG4gICAgX2V4dHJhY3QoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgY29sb3JTdHIgPSAhfkNPTE9SX0tFWVMuaW5kZXhPZihpbnB1dClcbiAgICAgICAgICAgID8gaW5wdXRcbiAgICAgICAgICAgIDogQ29sb3JLZXl3b3Jkc1tpbnB1dF07XG4gICAgICAgIGNvbnN0IG1hdGNoID0gY29sb3JTdHIubWF0Y2goQ09MT1JSRUdTLkhFWCk7XG4gICAgICAgIHJldHVybiBtYXRjaC5ncm91cHM7XG4gICAgfVxuICAgIHN1cHBvcnRzKGlucHV0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiAoQ09MT1JSRUdTLkhFWC50ZXN0KGlucHV0KSB8fFxuICAgICAgICAgICAgICAgICEhfkNPTE9SX0tFWVMuaW5kZXhPZihpbnB1dCkpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc0ludmFsaWRIZXggPSBPYmplY3QuZW50cmllcyhpbnB1dCkuc29tZSgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuICFIRVgudGVzdChgJHtpdGVtWzFdfWApO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGlzUkdCT2JqZWN0KGlucHV0KSAmJiAhaGFzSW52YWxpZEhleDtcbiAgICB9XG4gICAgcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgaWYgKGlzU3RyaW5nKGlucHV0KSkge1xuICAgICAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgICAgICBjb25zdCByID0gZ3JvdXBzLnIgPz8gZ3JvdXBzLnJyO1xuICAgICAgICAgICAgY29uc3QgZyA9IGdyb3Vwcy5nID8/IGdyb3Vwcy5nZztcbiAgICAgICAgICAgIGNvbnN0IGIgPSBncm91cHMuYiA/PyBncm91cHMuYmI7XG4gICAgICAgICAgICBjb25zdCBhID0gZ3JvdXBzLmEgPz8gZ3JvdXBzLmFhO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBSOiBnZXRERUMociksXG4gICAgICAgICAgICAgICAgRzogZ2V0REVDKGcpLFxuICAgICAgICAgICAgICAgIEI6IGdldERFQyhiKSxcbiAgICAgICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoYSlcbiAgICAgICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEE6IGdldERFQyhhKSAvIEJBU0VfMjU1XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSOiBnZXRCYXNlMjU1TnVtYmVyKGAke2lucHV0LlJ9YCksXG4gICAgICAgICAgICBHOiBnZXRCYXNlMjU1TnVtYmVyKGAke2lucHV0Lkd9YCksXG4gICAgICAgICAgICBCOiBnZXRCYXNlMjU1TnVtYmVyKGAke2lucHV0LkJ9YCksXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoaW5wdXQuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IE1hdGgubWluKGdldEJhc2UyNTVOdW1iZXIoYCR7aW5wdXQuQX1gLCB0cnVlKSwgMSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb252ZXJ0KGNvbG9yLCBfX2RlY2ltYWxzLCB3aXRoQWxwaGEpIHtcbiAgICAgICAgY29uc3QgcmdiID0gaXNSR0JPYmplY3QoY29sb3IpXG4gICAgICAgICAgICA/IGNvbG9yXG4gICAgICAgICAgICA6IGdldFJHQihjb2xvcik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSOiBnZXRIRVgocmdiLlIpLFxuICAgICAgICAgICAgRzogZ2V0SEVYKHJnYi5HKSxcbiAgICAgICAgICAgIEI6IGdldEhFWChyZ2IuQiksXG4gICAgICAgICAgICAuLi4od2l0aEFscGhhXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIEE6IGlzVW5kZWZpbmVkKHJnYi5BKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnMHhGRidcbiAgICAgICAgICAgICAgICAgICAgICAgIDogZ2V0SEVYKHJnYi5BICogQkFTRV8yNTUpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pXG4gICAgICAgIH07XG4gICAgfVxuICAgIGNvbnZlcnRDU1MoY29sb3IsIG9wdGlvbnMsIHdpdGhBbHBoYSkge1xuICAgICAgICBjb25zdCByZ2IgPSB0aGlzLmNvbnZlcnQoY29sb3IsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gKHZhbHVlKSA9PiB0b0hFWChyb3VuZCh2YWx1ZSkpO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MocmdiLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gdmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgPyAnI3sxfXsyfXszfXs0fSdcbiAgICAgICAgICAgIDogJyN7MX17Mn17M30nO1xuICAgICAgICByZXR1cm4gZ2V0UmVzdWx0RnJvbUNTU1RlbXBsYXRlKHRlbXBsYXRlLCB2YWx1ZXMpO1xuICAgIH1cbiAgICBnZXRDU1NPcHRpb25zKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuX2V4dHJhY3QoaW5wdXQpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaGFzQWxwaGE6ICFpc1VuZGVmaW5lZChncm91cHMuYSA/PyBncm91cHMuYWEpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBtb2RlbCgpIHtcbiAgICAgICAgcmV0dXJuIENvbG9yTW9kZWwuSEVYO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENBTEMsIEVSUk9SUyB9IGZyb20gJyNjb25zdGFudHMnO1xuY29uc3QgTUFYX1NUQUNLID0gMTAwO1xuZXhwb3J0IGNsYXNzIENhbGNQYXJzZXIge1xuICAgIGNvbnN0cnVjdG9yKGNvbG9ySW5kZXgsIGNhbGMsIHZhcnMpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9ucyA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgW0NBTEMuRElWSVNJT04sIHRoaXMuX2RpdmlzaW9uXSxcbiAgICAgICAgICAgIFtDQUxDLk1VTFRJUExJQ0FUSU9OLCB0aGlzLl9tdWx0aXBsaWNhdGlvbl0sXG4gICAgICAgICAgICBbQ0FMQy5TVU0sIHRoaXMuX3N1bV0sXG4gICAgICAgICAgICBbQ0FMQy5SRVNULCB0aGlzLl9yZXN0XVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5fY29sb3JJbmRleCA9IGNvbG9ySW5kZXg7XG4gICAgICAgIGxldCBjYWxjU3RyaW5nID0gY2FsYztcbiAgICAgICAgbGV0IHN0YWNrID0gMDtcbiAgICAgICAgaWYgKCFOdW1iZXIuaXNOYU4oK2NhbGMpKSB7XG4gICAgICAgICAgICB0aGlzLl9yZXN1bHQgPSArY2FsYztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjYWxjIGluIHZhcnMpIHtcbiAgICAgICAgICAgIHRoaXMuX3Jlc3VsdCA9IHZhcnNbY2FsY107XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoQ0FMQy5SRUdFWFAudGVzdChjYWxjU3RyaW5nKSkge1xuICAgICAgICAgICAgQ0FMQy5SRUdFWFAubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIHRoaXMuX3Jlc3VsdCA9IHRoaXMuX2dldENhbGNWYWx1ZShjYWxjU3RyaW5nLCB2YXJzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHdoaWxlIChDQUxDLlNDT1BFRC50ZXN0KGNhbGNTdHJpbmcpICYmIHN0YWNrIDwgTUFYX1NUQUNLKSB7XG4gICAgICAgICAgICAgICAgQ0FMQy5TQ09QRUQubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICBjYWxjU3RyaW5nID0gY2FsY1N0cmluZy5yZXBsYWNlKENBTEMuU0NPUEVELCAoX19tYXRjaCwgb3BlcmF0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jYWxjdWxhdGUob3BlcmF0aW9uLCB2YXJzKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmIChDQUxDLlJFR0VYUC50ZXN0KGNhbGNTdHJpbmcpKSB7XG4gICAgICAgICAgICAgICAgICAgIENBTEMuUkVHRVhQLmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdGFjaysrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5fcmVzdWx0ID0gdGhpcy5fZ2V0Q2FsY1ZhbHVlKGNhbGNTdHJpbmcsIHZhcnMpO1xuICAgICAgICB9XG4gICAgfVxuICAgIF9kaXZpc2lvbihsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xuICAgIH1cbiAgICBfbXVsdGlwbGljYXRpb24obGVmdCwgcmlnaHQpIHtcbiAgICAgICAgcmV0dXJuIGxlZnQgKiByaWdodDtcbiAgICB9XG4gICAgX3N1bShsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCArIHJpZ2h0O1xuICAgIH1cbiAgICBfcmVzdChsZWZ0LCByaWdodCkge1xuICAgICAgICByZXR1cm4gbGVmdCAtIHJpZ2h0O1xuICAgIH1cbiAgICBfZ2V0Q2FsY1ZhbHVlKGNhbGMsIHZhcnMpIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBjYWxjLm1hdGNoKENBTEMuUkVHRVhQKTtcbiAgICAgICAgY29uc3Qgb3BlcmF0aW9uID0gbWF0Y2guZ3JvdXBzLm9wZXJhdGlvbjtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLl9jYWxjdWxhdGUob3BlcmF0aW9uLCB2YXJzKTtcbiAgICAgICAgaWYgKE51bWJlci5pc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCB2YWx1ZSBmb3IgJHt0aGlzLl9jb2xvckluZGV4fS4gJHtvcGVyYXRpb259ICR7RVJST1JTLk5PVF9BX1ZBTElEX1JFTEFUSVZFX0NPTE9SfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgX2NhbGN1bGF0ZShvcGVyYXRpb24sIHZhcnMpIHtcbiAgICAgICAgdGhpcy5fb3BlcmF0aW9ucy5mb3JFYWNoKChtZXRob2QsIHJlZ0V4cCkgPT4ge1xuICAgICAgICAgICAgbGV0IHN0YWNrID0gMDtcbiAgICAgICAgICAgIHdoaWxlIChyZWdFeHAudGVzdChvcGVyYXRpb24pICYmIHN0YWNrIDwgTUFYX1NUQUNLKSB7XG4gICAgICAgICAgICAgICAgb3BlcmF0aW9uID0gb3BlcmF0aW9uLnJlcGxhY2UocmVnRXhwLCAoX19tYXRjaCwgbGVmdCwgcmlnaHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1ldGhvZCh2YXJzW2xlZnRdID8/ICtsZWZ0LCB2YXJzW3JpZ2h0XSA/PyArcmlnaHQpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc3RhY2srKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiArb3BlcmF0aW9uO1xuICAgIH1cbiAgICBnZXQgcmVzdWx0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fcmVzdWx0O1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENvbG9yVW5pdEVudW0gfSBmcm9tICdAdHlwZXMnO1xuaW1wb3J0IHsgQkFTRV8yNTUsIENPTE9SUkVHUywgQ29sb3JNb2RlbCwgSEVYLCBQQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZnJvbTI1NU51bWJlclRvUGVyY2VudCwgZ2V0QmFzZTI1NU51bWJlciwgaXNTdHJpbmcsIGlzUkdCT2JqZWN0LCBpc1VuZGVmaW5lZCwgbm9ybWFsaXplQWxwaGEsIHJvdW5kIH0gZnJvbSAnI3V0aWxpdGllcyc7XG5pbXBvcnQgeyBnZXRDU1NBbHBoYSwgZ2V0Q1NTQ29tbWEsIGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSwgcHJlcGFyZUNvbG9yRm9yQ3NzIH0gZnJvbSAnI2Nzcyc7XG5pbXBvcnQgeyBnZXRSR0IgfSBmcm9tICcjY29sb3IvcmdiJztcbmltcG9ydCB7IENhbGNQYXJzZXIgfSBmcm9tICcuL0NhbGNQYXJzZXInO1xuaW1wb3J0IHsgQ29sb3JQYXJzZXIgfSBmcm9tICcuL0NvbG9yUGFyc2VyQ29udGV4dCc7XG5leHBvcnQgY2xhc3MgUkdCUGFyc2VyIGV4dGVuZHMgQ29sb3JQYXJzZXIge1xuICAgIF9leHRyYWN0KGlucHV0KSB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gaW5wdXQubWF0Y2goQ09MT1JSRUdTLlJHQik7XG4gICAgICAgIHJldHVybiBtYXRjaC5ncm91cHM7XG4gICAgfVxuICAgIHN1cHBvcnRzKGlucHV0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBDT0xPUlJFR1MuUkdCLnRlc3QoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGhhc0ludmFsaWRSZWdiID0gT2JqZWN0LmVudHJpZXMoaW5wdXQpLnNvbWUoKGl0ZW0pID0+IHtcbiAgICAgICAgICAgIHJldHVybiAhKFBDRU5ULnRlc3QoYCR7aXRlbVsxXX1gKSB8fFxuICAgICAgICAgICAgICAgICghSEVYLnRlc3QoYCR7aXRlbVsxXX1gKSAmJlxuICAgICAgICAgICAgICAgICAgICAhaXNOYU4oK2l0ZW1bMV0pICYmXG4gICAgICAgICAgICAgICAgICAgICtpdGVtWzFdIDw9IEJBU0VfMjU1KSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gaXNSR0JPYmplY3QoaW5wdXQpICYmICFoYXNJbnZhbGlkUmVnYjtcbiAgICB9XG4gICAgcGFyc2UoaW5wdXQsIGNvbnRleHQpIHtcbiAgICAgICAgaWYgKGlzU3RyaW5nKGlucHV0KSkge1xuICAgICAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgICAgICBjb25zdCB7IHJfbGVnYWN5LCBnX2xlZ2FjeSwgYl9sZWdhY3ksIGFfbGVnYWN5LCByLCBnLCBiLCBhLCBmcm9tLCByZWxhdGl2ZV9yLCByZWxhdGl2ZV9nLCByZWxhdGl2ZV9iLCByZWxhdGl2ZV9hIH0gPSBncm91cHM7XG4gICAgICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21Db2xvciA9IGNvbnRleHQucGFyc2UoZnJvbSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZnJvbVJHQiA9IGdldFJHQihmcm9tQ29sb3IpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21SR0JWYXJzID0ge1xuICAgICAgICAgICAgICAgICAgICByOiBmcm9tUkdCLlIsXG4gICAgICAgICAgICAgICAgICAgIGc6IGZyb21SR0IuRyxcbiAgICAgICAgICAgICAgICAgICAgYjogZnJvbVJHQi5CLFxuICAgICAgICAgICAgICAgICAgICBhbHBoYTogZnJvbVJHQi5BID8/IDFcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGNvbnN0IFIgPSBuZXcgQ2FsY1BhcnNlcigncicsIHJlbGF0aXZlX3IsIGZyb21SR0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgRyA9IG5ldyBDYWxjUGFyc2VyKCdnJywgcmVsYXRpdmVfZywgZnJvbVJHQlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBCID0gbmV3IENhbGNQYXJzZXIoJ2InLCByZWxhdGl2ZV9iLCBmcm9tUkdCVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHJnYiA9IHtcbiAgICAgICAgICAgICAgICAgICAgUjogTWF0aC5taW4oUiwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgICAgICBHOiBNYXRoLm1pbihHLCBCQVNFXzI1NSksXG4gICAgICAgICAgICAgICAgICAgIEI6IE1hdGgubWluKEIsIEJBU0VfMjU1KVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHJlbGF0aXZlX2EpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgQSA9IG5ldyBDYWxjUGFyc2VyKCdhbHBoYScsIHJlbGF0aXZlX2EsIGZyb21SR0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIHJnYi5BID0gTWF0aC5taW4oQSwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZ2I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBSID0gcl9sZWdhY3kgPz8gcjtcbiAgICAgICAgICAgICAgICBjb25zdCBHID0gZ19sZWdhY3kgPz8gZztcbiAgICAgICAgICAgICAgICBjb25zdCBCID0gYl9sZWdhY3kgPz8gYjtcbiAgICAgICAgICAgICAgICBjb25zdCBBID0gYV9sZWdhY3kgPz8gYTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBSOiBNYXRoLm1pbihnZXRCYXNlMjU1TnVtYmVyKFIpLCBCQVNFXzI1NSksXG4gICAgICAgICAgICAgICAgICAgIEc6IE1hdGgubWluKGdldEJhc2UyNTVOdW1iZXIoRyksIEJBU0VfMjU1KSxcbiAgICAgICAgICAgICAgICAgICAgQjogTWF0aC5taW4oZ2V0QmFzZTI1NU51bWJlcihCKSwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoQSlcbiAgICAgICAgICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKEEpXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFI6IGdldEJhc2UyNTVOdW1iZXIoYCR7aW5wdXQuUn1gKSxcbiAgICAgICAgICAgIEc6IGdldEJhc2UyNTVOdW1iZXIoYCR7aW5wdXQuR31gKSxcbiAgICAgICAgICAgIEI6IGdldEJhc2UyNTVOdW1iZXIoYCR7aW5wdXQuQn1gKSxcbiAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChpbnB1dC5BKVxuICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgQTogTWF0aC5taW4oZ2V0QmFzZTI1NU51bWJlcihgJHtpbnB1dC5BfWAsIHRydWUpLCAxKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgfVxuICAgIGNvbnZlcnQoY29sb3IsIGRlY2ltYWxzLCB3aXRoQWxwaGEpIHtcbiAgICAgICAgY29uc3QgcmdiID0gaXNSR0JPYmplY3QoY29sb3IpXG4gICAgICAgICAgICA/IGNvbG9yXG4gICAgICAgICAgICA6IGdldFJHQihjb2xvcik7XG4gICAgICAgIHJldHVybiB0aGlzLl9yb3VuZFJHQk9iamVjdCh7XG4gICAgICAgICAgICBSOiByZ2IuUixcbiAgICAgICAgICAgIEc6IHJnYi5HLFxuICAgICAgICAgICAgQjogcmdiLkIsXG4gICAgICAgICAgICAuLi4od2l0aEFscGhhXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIEE6IHJnYi5BID8/IDFcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgOiB7fSlcbiAgICAgICAgfSwgZGVjaW1hbHMpO1xuICAgIH1cbiAgICBjb252ZXJ0Q1NTKGNvbG9yLCBvcHRpb25zLCB3aXRoQWxwaGEpIHtcbiAgICAgICAgY29uc3QgeyBkZWNpbWFscywgbGVnYWN5Q1NTLCBzcGFjZXNBZnRlckNvbW1hcywgcmdiVW5pdCB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgcmdiID0gdGhpcy5jb252ZXJ0KGNvbG9yLCBvcHRpb25zLmRlY2ltYWxzLCB3aXRoQWxwaGEpO1xuICAgICAgICBjb25zdCBjb21tYSA9IGdldENTU0NvbW1hKHNwYWNlc0FmdGVyQ29tbWFzKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSAodmFsdWUsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gcmdiVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UICYmIGluZGV4IDwgM1xuICAgICAgICAgICAgICAgID8gYCR7ZnJvbTI1NU51bWJlclRvUGVyY2VudCh2YWx1ZSwgZGVjaW1hbHMpfSVgXG4gICAgICAgICAgICAgICAgOiAoaW5kZXggPT09IDNcbiAgICAgICAgICAgICAgICAgICAgPyBnZXRDU1NBbHBoYSh2YWx1ZSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKHJnYiwgdHJhbnNmb3JtZXIpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGxlZ2FjeUNTU1xuICAgICAgICAgICAgPyAodmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgICAgID8gYHJnYmEoezF9JHtjb21tYX17Mn0ke2NvbW1hfXszfSR7Y29tbWF9ezR9KWBcbiAgICAgICAgICAgICAgICA6IGByZ2IoezF9JHtjb21tYX17Mn0ke2NvbW1hfXszfSlgKVxuICAgICAgICAgICAgOiAodmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgICAgID8gYHJnYih7MX0gezJ9IHszfSAvIHs0fSlgXG4gICAgICAgICAgICAgICAgOiBgcmdiKHsxfSB7Mn0gezN9KWApO1xuICAgICAgICByZXR1cm4gZ2V0UmVzdWx0RnJvbUNTU1RlbXBsYXRlKHRlbXBsYXRlLCB2YWx1ZXMpO1xuICAgIH1cbiAgICBfcm91bmRSR0JPYmplY3QoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIGNvbnN0IFIgPSByb3VuZChjb2xvci5SLCBkZWNpbWFscyk7XG4gICAgICAgIGNvbnN0IEcgPSByb3VuZChjb2xvci5HLCBkZWNpbWFscyk7XG4gICAgICAgIGNvbnN0IEIgPSByb3VuZChjb2xvci5CLCBkZWNpbWFscyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSLFxuICAgICAgICAgICAgRyxcbiAgICAgICAgICAgIEIsXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoY29sb3IuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IHJvdW5kKGNvbG9yLkEsIGRlY2ltYWxzKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldENTU09wdGlvbnMoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgIGNvbnN0IHsgcl9sZWdhY3ksIGdfbGVnYWN5LCBiX2xlZ2FjeSwgYV9sZWdhY3ksIHIsIGcsIGIsIGEgfSA9IGdyb3VwcztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGhhc1BlcmNlbnRhZ2VWYWx1ZXM6IChQQ0VOVC50ZXN0KHJfbGVnYWN5ID8/IHIpICYmXG4gICAgICAgICAgICAgICAgUENFTlQudGVzdChnX2xlZ2FjeSA/PyBnKSAmJlxuICAgICAgICAgICAgICAgIFBDRU5ULnRlc3QoYl9sZWdhY3kgPz8gYikpLFxuICAgICAgICAgICAgaGFzUGVyY2VudGFnZUFscGhhOiBQQ0VOVC50ZXN0KGFfbGVnYWN5ID8/IGEpLFxuICAgICAgICAgICAgaGFzQWxwaGE6ICFpc1VuZGVmaW5lZChhX2xlZ2FjeSA/PyBhKVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgbW9kZWwoKSB7XG4gICAgICAgIHJldHVybiBDb2xvck1vZGVsLlJHQjtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBDT0xPUlJFR1MsIENvbG9yTW9kZWwsIE1BWF9BTFBIQSwgUENFTlQgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IGdldEFuZ2xlVW5pdCwgaXNIU0xPYmplY3QsIGlzU3RyaW5nLCBpc1VuZGVmaW5lZCwgbWlubWF4LCBub3JtYWxpemVBbHBoYSwgbm9ybWFsaXplSHVlLCBwZXJjZW50LCByb3VuZCB9IGZyb20gJyN1dGlsaXRpZXMnO1xuaW1wb3J0IHsgYnVpbGRDU1NIdWVUcmFuc2Zvcm1lciwgZ2V0Q1NTQ29tbWEsIGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSwgcHJlcGFyZUNvbG9yRm9yQ3NzIH0gZnJvbSAnI2Nzcyc7XG5pbXBvcnQgeyBnZXRSR0IgfSBmcm9tICcjY29sb3IvcmdiJztcbmltcG9ydCB7IHJnYlRvSHNsIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IENhbGNQYXJzZXIgfSBmcm9tICcuL0NhbGNQYXJzZXInO1xuaW1wb3J0IHsgQ29sb3JQYXJzZXIgfSBmcm9tICcuL0NvbG9yUGFyc2VyQ29udGV4dCc7XG5leHBvcnQgY2xhc3MgSFNMUGFyc2VyIGV4dGVuZHMgQ29sb3JQYXJzZXIge1xuICAgIF9leHRyYWN0KGlucHV0KSB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gaW5wdXQubWF0Y2goQ09MT1JSRUdTLkhTTCk7XG4gICAgICAgIHJldHVybiBtYXRjaC5ncm91cHM7XG4gICAgfVxuICAgIHN1cHBvcnRzKGlucHV0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBDT0xPUlJFR1MuSFNMLnRlc3QoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0hTTE9iamVjdChpbnB1dCk7XG4gICAgfVxuICAgIHBhcnNlKGlucHV0LCBjb250ZXh0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuX2V4dHJhY3QoaW5wdXQpO1xuICAgICAgICAgICAgY29uc3QgeyBoX2xlZ2FjeSwgc19sZWdhY3ksIGxfbGVnYWN5LCBhX2xlZ2FjeSwgaCwgcywgbCwgYSwgZnJvbSwgcmVsYXRpdmVfaCwgcmVsYXRpdmVfcywgcmVsYXRpdmVfbCwgcmVsYXRpdmVfYSB9ID0gZ3JvdXBzO1xuICAgICAgICAgICAgaWYgKGZyb20pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tQ29sb3IgPSBjb250ZXh0LnBhcnNlKGZyb20pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21SR0IgPSBnZXRSR0IoZnJvbUNvbG9yKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tSFNMID0gcmdiVG9Ic2woZnJvbVJHQi5SLCBmcm9tUkdCLkcsIGZyb21SR0IuQiwgZnJvbVJHQi5BKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tSFNMVmFycyA9IHtcbiAgICAgICAgICAgICAgICAgICAgaDogZnJvbUhTTC5ILFxuICAgICAgICAgICAgICAgICAgICBzOiBmcm9tSFNMLlMsXG4gICAgICAgICAgICAgICAgICAgIGw6IGZyb21IU0wuTCxcbiAgICAgICAgICAgICAgICAgICAgYWxwaGE6IGZyb21IU0wuQVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY29uc3QgSCA9IG5ldyBDYWxjUGFyc2VyKCdoJywgcmVsYXRpdmVfaCwgZnJvbUhTTFZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBTID0gbmV3IENhbGNQYXJzZXIoJ3MnLCByZWxhdGl2ZV9zLCBmcm9tSFNMVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IEwgPSBuZXcgQ2FsY1BhcnNlcignbCcsIHJlbGF0aXZlX2wsIGZyb21IU0xWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgaHNsID0ge1xuICAgICAgICAgICAgICAgICAgICBIOiBub3JtYWxpemVIdWUoSCksXG4gICAgICAgICAgICAgICAgICAgIFM6IHBlcmNlbnQoUyksXG4gICAgICAgICAgICAgICAgICAgIEw6IHBlcmNlbnQoTClcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmIChyZWxhdGl2ZV9hKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IEEgPSBuZXcgQ2FsY1BhcnNlcignYWxwaGEnLCByZWxhdGl2ZV9hLCBmcm9tSFNMVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICBoc2wuQSA9IG1pbm1heChBLCAwLCBNQVhfQUxQSEEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gaHNsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgSCA9IGhfbGVnYWN5ID8/IGg7XG4gICAgICAgICAgICAgICAgY29uc3QgUyA9IHNfbGVnYWN5ID8/IHM7XG4gICAgICAgICAgICAgICAgY29uc3QgTCA9IGxfbGVnYWN5ID8/IGw7XG4gICAgICAgICAgICAgICAgY29uc3QgQSA9IGFfbGVnYWN5ID8/IGE7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgSDogbm9ybWFsaXplSHVlKEgpLFxuICAgICAgICAgICAgICAgICAgICBTOiBwZXJjZW50KFMpLFxuICAgICAgICAgICAgICAgICAgICBMOiBwZXJjZW50KEwpLFxuICAgICAgICAgICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoQSlcbiAgICAgICAgICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKEEpXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEg6IG5vcm1hbGl6ZUh1ZShpbnB1dC5IKSxcbiAgICAgICAgICAgIFM6IHBlcmNlbnQoYCR7aW5wdXQuU31gKSxcbiAgICAgICAgICAgIEw6IHBlcmNlbnQoYCR7aW5wdXQuTH1gKSxcbiAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChpbnB1dC5BKVxuICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgQTogbWlubWF4KCtpbnB1dC5BLCAwLCBNQVhfQUxQSEEpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY29udmVydChjb2xvciwgZGVjaW1hbHMsIHdpdGhBbHBoYSkge1xuICAgICAgICBsZXQgaHNsO1xuICAgICAgICBpZiAoaXNIU0xPYmplY3QoY29sb3IpKSB7XG4gICAgICAgICAgICBoc2wgPSBjb2xvcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGdldFJHQihjb2xvcik7XG4gICAgICAgICAgICBoc2wgPSByZ2JUb0hzbChyZ2IuUiwgcmdiLkcsIHJnYi5CLCByZ2IuQSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kSFNMT2JqZWN0KHtcbiAgICAgICAgICAgIEg6IGhzbC5ILFxuICAgICAgICAgICAgUzogaHNsLlMsXG4gICAgICAgICAgICBMOiBoc2wuTCxcbiAgICAgICAgICAgIC4uLih3aXRoQWxwaGFcbiAgICAgICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICAgICAgQTogaHNsLkEgPz8gMVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA6IHt9KVxuICAgICAgICB9LCBkZWNpbWFscyk7XG4gICAgfVxuICAgIGNvbnZlcnRDU1MoY29sb3IsIG9wdGlvbnMsIHdpdGhBbHBoYSkge1xuICAgICAgICBjb25zdCB7IGxlZ2FjeUNTUywgc3BhY2VzQWZ0ZXJDb21tYXMgfSA9IG9wdGlvbnM7XG4gICAgICAgIGNvbnN0IGNvbW1hID0gZ2V0Q1NTQ29tbWEoc3BhY2VzQWZ0ZXJDb21tYXMpO1xuICAgICAgICBjb25zdCBoc2wgPSB0aGlzLmNvbnZlcnQoY29sb3IsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gYnVpbGRDU1NIdWVUcmFuc2Zvcm1lcihvcHRpb25zKTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGhzbCwgdHJhbnNmb3JtZXIpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGxlZ2FjeUNTU1xuICAgICAgICAgICAgPyAodmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgICAgID8gYGhzbGEoezF9JHtjb21tYX17Mn0lJHtjb21tYX17M30lJHtjb21tYX17NH0pYFxuICAgICAgICAgICAgICAgIDogYGhzbCh7MX0ke2NvbW1hfXsyfSUke2NvbW1hfXszfSUpYClcbiAgICAgICAgICAgIDogKHZhbHVlcy5sZW5ndGggPT09IDRcbiAgICAgICAgICAgICAgICA/IGBoc2woezF9IHsyfSUgezN9JSAvIHs0fSlgXG4gICAgICAgICAgICAgICAgOiBgaHNsKHsxfSB7Mn0lIHszfSUpYCk7XG4gICAgICAgIHJldHVybiBnZXRSZXN1bHRGcm9tQ1NTVGVtcGxhdGUodGVtcGxhdGUsIHZhbHVlcyk7XG4gICAgfVxuICAgIF9yb3VuZEhTTE9iamVjdChjb2xvciwgZGVjaW1hbHMpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEg6IHJvdW5kKG5vcm1hbGl6ZUh1ZShjb2xvci5IKSwgZGVjaW1hbHMpLFxuICAgICAgICAgICAgUzogcm91bmQoY29sb3IuUywgZGVjaW1hbHMpLFxuICAgICAgICAgICAgTDogcm91bmQoY29sb3IuTCwgZGVjaW1hbHMpLFxuICAgICAgICAgICAgLi4uKGlzVW5kZWZpbmVkKGNvbG9yLkEpXG4gICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICBBOiByb3VuZChjb2xvci5BLCBkZWNpbWFscylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRDU1NPcHRpb25zKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuX2V4dHJhY3QoaW5wdXQpO1xuICAgICAgICBjb25zdCB7IGhfbGVnYWN5LCBoLCBhX2xlZ2FjeSwgYSB9ID0gZ3JvdXBzO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYW5nbGVVbml0OiBnZXRBbmdsZVVuaXQoaF9sZWdhY3kgPz8gaCksXG4gICAgICAgICAgICBoYXNQZXJjZW50YWdlQWxwaGE6IFBDRU5ULnRlc3QoYV9sZWdhY3kgPz8gYSksXG4gICAgICAgICAgICBoYXNBbHBoYTogIWlzVW5kZWZpbmVkKGFfbGVnYWN5ID8/IGEpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBtb2RlbCgpIHtcbiAgICAgICAgcmV0dXJuIENvbG9yTW9kZWwuSFNMO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IENPTE9SUkVHUywgQ29sb3JNb2RlbCwgTUFYX0FMUEhBLCBNQVhfSFVFLCBNQVhfUENFTlQsIFBDRU5UIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBnZXRBbmdsZVVuaXQsIGlzSFdCT2JqZWN0LCBpc1N0cmluZywgaXNVbmRlZmluZWQsIG1pbm1heCwgbm9ybWFsaXplQWxwaGEsIG5vcm1hbGl6ZUh1ZSwgcGVyY2VudCwgcm91bmQgfSBmcm9tICcjdXRpbGl0aWVzJztcbmltcG9ydCB7IGJ1aWxkQ1NTSHVlVHJhbnNmb3JtZXIsIGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSwgcHJlcGFyZUNvbG9yRm9yQ3NzIH0gZnJvbSAnI2Nzcyc7XG5pbXBvcnQgeyBnZXRSR0IgfSBmcm9tICcjY29sb3IvcmdiJztcbmltcG9ydCB7IHJnYlRvSHdiIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IENhbGNQYXJzZXIgfSBmcm9tICcuL0NhbGNQYXJzZXInO1xuaW1wb3J0IHsgQ29sb3JQYXJzZXIgfSBmcm9tICcuL0NvbG9yUGFyc2VyQ29udGV4dCc7XG5leHBvcnQgY2xhc3MgSFdCUGFyc2VyIGV4dGVuZHMgQ29sb3JQYXJzZXIge1xuICAgIF9leHRyYWN0KGlucHV0KSB7XG4gICAgICAgIGNvbnN0IG1hdGNoID0gaW5wdXQubWF0Y2goQ09MT1JSRUdTLkhXQik7XG4gICAgICAgIHJldHVybiBtYXRjaC5ncm91cHM7XG4gICAgfVxuICAgIHN1cHBvcnRzKGlucHV0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBDT0xPUlJFR1MuSFdCLnRlc3QoaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0hXQk9iamVjdChpbnB1dCk7XG4gICAgfVxuICAgIHBhcnNlKGlucHV0LCBjb250ZXh0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuX2V4dHJhY3QoaW5wdXQpO1xuICAgICAgICAgICAgY29uc3QgeyBoLCB3LCBiLCBhLCBmcm9tLCByZWxhdGl2ZV9oLCByZWxhdGl2ZV93LCByZWxhdGl2ZV9iLCByZWxhdGl2ZV9hIH0gPSBncm91cHM7XG4gICAgICAgICAgICBpZiAoZnJvbSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21Db2xvciA9IGNvbnRleHQucGFyc2UoZnJvbSk7XG4gICAgICAgICAgICAgICAgY29uc3QgZnJvbVJHQiA9IGdldFJHQihmcm9tQ29sb3IpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21IV0IgPSByZ2JUb0h3Yihmcm9tUkdCLlIsIGZyb21SR0IuRywgZnJvbVJHQi5CLCBmcm9tUkdCLkEpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21IV0JWYXJzID0ge1xuICAgICAgICAgICAgICAgICAgICBoOiBmcm9tSFdCLkgsXG4gICAgICAgICAgICAgICAgICAgIHc6IGZyb21IV0IuVyxcbiAgICAgICAgICAgICAgICAgICAgYjogZnJvbUhXQi5CLFxuICAgICAgICAgICAgICAgICAgICBhbHBoYTogZnJvbUhXQi5BXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBjb25zdCBIID0gbmV3IENhbGNQYXJzZXIoJ2gnLCByZWxhdGl2ZV9oLCBmcm9tSFdCVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IFcgPSBuZXcgQ2FsY1BhcnNlcigndycsIHJlbGF0aXZlX3csIGZyb21IV0JWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgQiA9IG5ldyBDYWxjUGFyc2VyKCdiJywgcmVsYXRpdmVfYiwgZnJvbUhXQlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBod2IgPSB7XG4gICAgICAgICAgICAgICAgICAgIEg6IG1pbm1heChILCAwLCBNQVhfSFVFKSxcbiAgICAgICAgICAgICAgICAgICAgVzogbWlubWF4KFcsIDAsIE1BWF9QQ0VOVCksXG4gICAgICAgICAgICAgICAgICAgIEI6IG1pbm1heChCLCAwLCBNQVhfUENFTlQpXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAocmVsYXRpdmVfYSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBBID0gbmV3IENhbGNQYXJzZXIoJ2FscGhhJywgcmVsYXRpdmVfYSwgZnJvbUhXQlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgaHdiLkEgPSBtaW5tYXgoQSwgMCwgTUFYX0FMUEhBKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGh3YjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIEg6IG5vcm1hbGl6ZUh1ZShoKSxcbiAgICAgICAgICAgICAgICAgICAgVzogcGVyY2VudCh3KSxcbiAgICAgICAgICAgICAgICAgICAgQjogcGVyY2VudChiKSxcbiAgICAgICAgICAgICAgICAgICAgLi4uKGlzVW5kZWZpbmVkKGEpXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBOiBub3JtYWxpemVBbHBoYShhKVxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBIOiBub3JtYWxpemVIdWUoaW5wdXQuSCksXG4gICAgICAgICAgICBXOiBwZXJjZW50KGlucHV0LlcpLFxuICAgICAgICAgICAgQjogcGVyY2VudChpbnB1dC5CKSxcbiAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChpbnB1dC5BKVxuICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoaW5wdXQuQSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb252ZXJ0KGNvbG9yLCBkZWNpbWFscywgd2l0aEFscGhhKSB7XG4gICAgICAgIGxldCBod2I7XG4gICAgICAgIGlmIChpc0hXQk9iamVjdChjb2xvcikpIHtcbiAgICAgICAgICAgIGh3YiA9IGNvbG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcmdiID0gZ2V0UkdCKGNvbG9yKTtcbiAgICAgICAgICAgIGh3YiA9IHJnYlRvSHdiKHJnYi5SLCByZ2IuRywgcmdiLkIsIHJnYi5BKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRIV0JPYmplY3Qoe1xuICAgICAgICAgICAgSDogaHdiLkgsXG4gICAgICAgICAgICBXOiBod2IuVyxcbiAgICAgICAgICAgIEI6IGh3Yi5CLFxuICAgICAgICAgICAgLi4uKHdpdGhBbHBoYVxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBBOiBod2IuQSA/PyAxXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pXG4gICAgICAgIH0sIGRlY2ltYWxzKTtcbiAgICB9XG4gICAgY29udmVydENTUyhjb2xvciwgb3B0aW9ucywgd2l0aEFscGhhKSB7XG4gICAgICAgIGNvbnN0IGh3YiA9IHRoaXMuY29udmVydChjb2xvciwgb3B0aW9ucy5kZWNpbWFscywgd2l0aEFscGhhKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBidWlsZENTU0h1ZVRyYW5zZm9ybWVyKG9wdGlvbnMpO1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MoaHdiLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gdmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgPyBgaHdiKHsxfSB7Mn0lIHszfSUgLyB7NH0pYFxuICAgICAgICAgICAgOiBgaHdiKHsxfSB7Mn0lIHszfSUpYDtcbiAgICAgICAgcmV0dXJuIGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSh0ZW1wbGF0ZSwgdmFsdWVzKTtcbiAgICB9XG4gICAgX3JvdW5kSFdCT2JqZWN0KGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgSDogcm91bmQobm9ybWFsaXplSHVlKGNvbG9yLkgpLCBkZWNpbWFscyksXG4gICAgICAgICAgICBXOiByb3VuZChjb2xvci5XLCBkZWNpbWFscyksXG4gICAgICAgICAgICBCOiByb3VuZChjb2xvci5CLCBkZWNpbWFscyksXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoY29sb3IuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IHJvdW5kKGNvbG9yLkEsIGRlY2ltYWxzKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldENTU09wdGlvbnMoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbmdsZVVuaXQ6IGdldEFuZ2xlVW5pdChncm91cHMuaCksXG4gICAgICAgICAgICBoYXNQZXJjZW50YWdlQWxwaGE6IFBDRU5ULnRlc3QoZ3JvdXBzLmEpLFxuICAgICAgICAgICAgaGFzQWxwaGE6ICFpc1VuZGVmaW5lZChncm91cHMuYSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0IG1vZGVsKCkge1xuICAgICAgICByZXR1cm4gQ29sb3JNb2RlbC5IV0I7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgQ29sb3JVbml0RW51bSB9IGZyb20gJ0B0eXBlcyc7XG5pbXBvcnQgeyBDb2xvck1vZGVsLCBDT0xPUlJFR1MsIE1BWF9BTFBIQSwgTUFYX0xBQiwgTUFYX1BDRU5ULCBQQ0VOVCB9IGZyb20gJyNjb25zdGFudHMnO1xuaW1wb3J0IHsgZnJvbTEyNU51bWJlclRvUGVyY2VudCwgZ2V0QmFzZTEyNU51bWJlciwgaXNDSUVMYWJPYmplY3QsIGlzU3RyaW5nLCBpc1VuZGVmaW5lZCwgbWlubWF4LCBub3JtYWxpemVBbHBoYSwgcGVyY2VudCwgcm91bmQgfSBmcm9tICcjdXRpbGl0aWVzJztcbmltcG9ydCB7IGdldENTU0FscGhhLCBnZXRSZXN1bHRGcm9tQ1NTVGVtcGxhdGUsIHByZXBhcmVDb2xvckZvckNzcyB9IGZyb20gJyNjc3MnO1xuaW1wb3J0IHsgZ2V0UkdCIH0gZnJvbSAnI2NvbG9yL3JnYic7XG5pbXBvcnQgeyByZ2JUb0xhYiB9IGZyb20gJyNjb2xvci90cmFuc2xhdG9ycyc7XG5pbXBvcnQgeyBDYWxjUGFyc2VyIH0gZnJvbSAnLi9DYWxjUGFyc2VyJztcbmltcG9ydCB7IENvbG9yUGFyc2VyIH0gZnJvbSAnLi9Db2xvclBhcnNlckNvbnRleHQnO1xuZXhwb3J0IGNsYXNzIENJRUxhYlBhcnNlciBleHRlbmRzIENvbG9yUGFyc2VyIHtcbiAgICBfZXh0cmFjdChpbnB1dCkge1xuICAgICAgICBjb25zdCBtYXRjaCA9IGlucHV0Lm1hdGNoKENPTE9SUkVHUy5DSUVMYWIpO1xuICAgICAgICByZXR1cm4gbWF0Y2guZ3JvdXBzO1xuICAgIH1cbiAgICBzdXBwb3J0cyhpbnB1dCkge1xuICAgICAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gQ09MT1JSRUdTLkNJRUxhYi50ZXN0KGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNDSUVMYWJPYmplY3QoaW5wdXQpO1xuICAgIH1cbiAgICBwYXJzZShpbnB1dCwgY29udGV4dCkge1xuICAgICAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25zdCBncm91cHMgPSB0aGlzLl9leHRyYWN0KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IHsgTCwgYSwgYiwgQSwgZnJvbSwgcmVsYXRpdmVfTCwgcmVsYXRpdmVfYSwgcmVsYXRpdmVfYiwgcmVsYXRpdmVfQSB9ID0gZ3JvdXBzO1xuICAgICAgICAgICAgaWYgKGZyb20pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tQ29sb3IgPSBjb250ZXh0LnBhcnNlKGZyb20pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21SR0IgPSBnZXRSR0IoZnJvbUNvbG9yKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tQ0lFTGFiID0gcmdiVG9MYWIoZnJvbVJHQi5SLCBmcm9tUkdCLkcsIGZyb21SR0IuQik7XG4gICAgICAgICAgICAgICAgY29uc3QgZnJvbUNJRUxhYlZhcnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGw6IGZyb21DSUVMYWIuTCxcbiAgICAgICAgICAgICAgICAgICAgYTogZnJvbUNJRUxhYi5hLFxuICAgICAgICAgICAgICAgICAgICBiOiBmcm9tQ0lFTGFiLmIsXG4gICAgICAgICAgICAgICAgICAgIGFscGhhOiBmcm9tUkdCLkEgPz8gMVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY29uc3QgTCA9IG5ldyBDYWxjUGFyc2VyKCdsJywgcmVsYXRpdmVfTCwgZnJvbUNJRUxhYlZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBhID0gbmV3IENhbGNQYXJzZXIoJ2EnLCByZWxhdGl2ZV9hLCBmcm9tQ0lFTGFiVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBuZXcgQ2FsY1BhcnNlcignYicsIHJlbGF0aXZlX2IsIGZyb21DSUVMYWJWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgQ0lFTGFiID0ge1xuICAgICAgICAgICAgICAgICAgICBMOiBtaW5tYXgoTCwgMCwgTUFYX1BDRU5UKSxcbiAgICAgICAgICAgICAgICAgICAgYTogbWlubWF4KGEsIC1NQVhfTEFCLCBNQVhfTEFCKSxcbiAgICAgICAgICAgICAgICAgICAgYjogbWlubWF4KGIsIC1NQVhfTEFCLCBNQVhfTEFCKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHJlbGF0aXZlX0EpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgQSA9IG5ldyBDYWxjUGFyc2VyKCdhbHBoYScsIHJlbGF0aXZlX0EsIGZyb21DSUVMYWJWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIENJRUxhYi5BID0gbWlubWF4KEEsIDAsIE1BWF9BTFBIQSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBDSUVMYWI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBMOiBwZXJjZW50KEwpLFxuICAgICAgICAgICAgICAgICAgICBhOiBnZXRCYXNlMTI1TnVtYmVyKGEpLFxuICAgICAgICAgICAgICAgICAgICBiOiBnZXRCYXNlMTI1TnVtYmVyKGIpLFxuICAgICAgICAgICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoQSlcbiAgICAgICAgICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKEEpXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEw6IHBlcmNlbnQoaW5wdXQuTCksXG4gICAgICAgICAgICBhOiBnZXRCYXNlMTI1TnVtYmVyKGAke2lucHV0LmF9YCksXG4gICAgICAgICAgICBiOiBnZXRCYXNlMTI1TnVtYmVyKGAke2lucHV0LmJ9YCksXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoaW5wdXQuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKGlucHV0LkEpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY29udmVydChjb2xvciwgZGVjaW1hbHMsIHdpdGhBbHBoYSkge1xuICAgICAgICBsZXQgbGFiO1xuICAgICAgICBpZiAoaXNDSUVMYWJPYmplY3QoY29sb3IpKSB7XG4gICAgICAgICAgICBsYWIgPSBjb2xvcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGdldFJHQihjb2xvcik7XG4gICAgICAgICAgICBsYWIgPSByZ2JUb0xhYihyZ2IuUiwgcmdiLkcsIHJnYi5CKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRDSUVMYWJPYmplY3Qoe1xuICAgICAgICAgICAgTDogbGFiLkwsXG4gICAgICAgICAgICBhOiBsYWIuYSxcbiAgICAgICAgICAgIGI6IGxhYi5iLFxuICAgICAgICAgICAgLi4uKHdpdGhBbHBoYVxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBBOiArKGNvbG9yLkEgPz8gMSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgOiB7fSlcbiAgICAgICAgfSwgZGVjaW1hbHMpO1xuICAgIH1cbiAgICBjb252ZXJ0Q1NTKGNvbG9yLCBvcHRpb25zLCB3aXRoQWxwaGEpIHtcbiAgICAgICAgY29uc3QgeyBkZWNpbWFscywgbGFiVW5pdCB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgbGFiID0gdGhpcy5jb252ZXJ0KGNvbG9yLCBvcHRpb25zLmRlY2ltYWxzLCB3aXRoQWxwaGEpO1xuICAgICAgICBjb25zdCB0cmFuc2Zvcm1lciA9ICh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEwgPSByb3VuZChwZXJjZW50KHZhbHVlKSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJVbml0ID09PSBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICAgICAgPyBgJHtMfSVgXG4gICAgICAgICAgICAgICAgICAgIDogYCR7TH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGluZGV4IDwgMykge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYWJVbml0ID09PSBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICAgICAgPyBgJHtmcm9tMTI1TnVtYmVyVG9QZXJjZW50KHZhbHVlLCBkZWNpbWFscyl9JWBcbiAgICAgICAgICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGdldENTU0FscGhhKHZhbHVlLCBvcHRpb25zLCB0cnVlKTtcbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gcHJlcGFyZUNvbG9yRm9yQ3NzKGxhYiwgdHJhbnNmb3JtZXIpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IHZhbHVlcy5sZW5ndGggPT09IDRcbiAgICAgICAgICAgID8gYGxhYih7MX0gezJ9IHszfSAvIHs0fSlgXG4gICAgICAgICAgICA6IGBsYWIoezF9IHsyfSB7M30pYDtcbiAgICAgICAgcmV0dXJuIGdldFJlc3VsdEZyb21DU1NUZW1wbGF0ZSh0ZW1wbGF0ZSwgdmFsdWVzKTtcbiAgICB9XG4gICAgX3JvdW5kQ0lFTGFiT2JqZWN0KGNvbG9yLCBkZWNpbWFscykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgTDogcm91bmQoY29sb3IuTCwgZGVjaW1hbHMpLFxuICAgICAgICAgICAgYTogcm91bmQoY29sb3IuYSwgZGVjaW1hbHMpLFxuICAgICAgICAgICAgYjogcm91bmQoY29sb3IuYiwgZGVjaW1hbHMpLFxuICAgICAgICAgICAgLi4uKGlzVW5kZWZpbmVkKGNvbG9yLkEpXG4gICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICBBOiByb3VuZChjb2xvci5BLCBkZWNpbWFscylcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXRDU1NPcHRpb25zKGlucHV0KSB7XG4gICAgICAgIGNvbnN0IGdyb3VwcyA9IHRoaXMuX2V4dHJhY3QoaW5wdXQpO1xuICAgICAgICBjb25zdCB7IEwsIGEsIGIsIEEgfSA9IGdyb3VwcztcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGhhc1BlcmNlbnRhZ2VWYWx1ZXM6IChQQ0VOVC50ZXN0KEwpICYmXG4gICAgICAgICAgICAgICAgUENFTlQudGVzdChhKSAmJlxuICAgICAgICAgICAgICAgIFBDRU5ULnRlc3QoYikpLFxuICAgICAgICAgICAgaGFzUGVyY2VudGFnZUFscGhhOiBQQ0VOVC50ZXN0KEEpLFxuICAgICAgICAgICAgaGFzQWxwaGE6ICFpc1VuZGVmaW5lZChBKVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgbW9kZWwoKSB7XG4gICAgICAgIHJldHVybiBDb2xvck1vZGVsLkNJRUxhYjtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBBbmdsZXNVbml0RW51bSwgQ29sb3JVbml0RW51bSB9IGZyb20gJ0B0eXBlcyc7XG5pbXBvcnQgeyBDT0xPUlJFR1MsIENvbG9yTW9kZWwsIE1BWF9BTFBIQSwgTUFYX0xDSF9DLCBNQVhfUENFTlQsIFBDRU5UIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBmcm9tMTUwTnVtYmVyVG9QZXJjZW50LCBnZXRBbmdsZVVuaXQsIGdldEJhc2UxNTBOdW1iZXIsIGlzTENIT2JqZWN0LCBpc1N0cmluZywgaXNVbmRlZmluZWQsIG1pbm1heCwgbm9ybWFsaXplQWxwaGEsIG5vcm1hbGl6ZUh1ZSwgcGVyY2VudCwgcm91bmQsIHRyYW5zbGF0ZURlZ3JlZXMgfSBmcm9tICcjdXRpbGl0aWVzJztcbmltcG9ydCB7IGdldENTU0FscGhhLCBnZXRSZXN1bHRGcm9tQ1NTVGVtcGxhdGUsIHByZXBhcmVDb2xvckZvckNzcyB9IGZyb20gJyNjc3MnO1xuaW1wb3J0IHsgZ2V0UkdCIH0gZnJvbSAnI2NvbG9yL3JnYic7XG5pbXBvcnQgeyByZ2JUb0xjaCB9IGZyb20gJyNjb2xvci90cmFuc2xhdG9ycyc7XG5pbXBvcnQgeyBDYWxjUGFyc2VyIH0gZnJvbSAnLi9DYWxjUGFyc2VyJztcbmltcG9ydCB7IENvbG9yUGFyc2VyIH0gZnJvbSAnLi9Db2xvclBhcnNlckNvbnRleHQnO1xuZXhwb3J0IGNsYXNzIExDSFBhcnNlciBleHRlbmRzIENvbG9yUGFyc2VyIHtcbiAgICBfZXh0cmFjdChpbnB1dCkge1xuICAgICAgICBjb25zdCBtYXRjaCA9IGlucHV0Lm1hdGNoKENPTE9SUkVHUy5MQ0gpO1xuICAgICAgICByZXR1cm4gbWF0Y2guZ3JvdXBzO1xuICAgIH1cbiAgICBzdXBwb3J0cyhpbnB1dCkge1xuICAgICAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gQ09MT1JSRUdTLkxDSC50ZXN0KGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNMQ0hPYmplY3QoaW5wdXQpO1xuICAgIH1cbiAgICBwYXJzZShpbnB1dCwgY29udGV4dCkge1xuICAgICAgICBpZiAoaXNTdHJpbmcoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25zdCBncm91cHMgPSB0aGlzLl9leHRyYWN0KGlucHV0KTtcbiAgICAgICAgICAgIGNvbnN0IHsgbCwgYywgaCwgYSwgZnJvbSwgcmVsYXRpdmVfbCwgcmVsYXRpdmVfYywgcmVsYXRpdmVfaCwgcmVsYXRpdmVfYSB9ID0gZ3JvdXBzO1xuICAgICAgICAgICAgaWYgKGZyb20pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tQ29sb3IgPSBjb250ZXh0LnBhcnNlKGZyb20pO1xuICAgICAgICAgICAgICAgIGNvbnN0IGZyb21SR0IgPSBnZXRSR0IoZnJvbUNvbG9yKTtcbiAgICAgICAgICAgICAgICBjb25zdCBmcm9tTENIID0gcmdiVG9MY2goZnJvbVJHQi5SLCBmcm9tUkdCLkcsIGZyb21SR0IuQik7XG4gICAgICAgICAgICAgICAgY29uc3QgZnJvbUxDSFZhcnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGw6IGZyb21MQ0guTCxcbiAgICAgICAgICAgICAgICAgICAgYzogZnJvbUxDSC5DLFxuICAgICAgICAgICAgICAgICAgICBoOiBmcm9tTENILkgsXG4gICAgICAgICAgICAgICAgICAgIGFscGhhOiBmcm9tUkdCLkEgPz8gMVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgY29uc3QgTCA9IG5ldyBDYWxjUGFyc2VyKCdsJywgcmVsYXRpdmVfbCwgZnJvbUxDSFZhcnMpLnJlc3VsdDtcbiAgICAgICAgICAgICAgICBjb25zdCBDID0gbmV3IENhbGNQYXJzZXIoJ2MnLCByZWxhdGl2ZV9jLCBmcm9tTENIVmFycykucmVzdWx0O1xuICAgICAgICAgICAgICAgIGNvbnN0IEggPSBuZXcgQ2FsY1BhcnNlcignaCcsIHJlbGF0aXZlX2gsIGZyb21MQ0hWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgY29uc3QgbGNoID0ge1xuICAgICAgICAgICAgICAgICAgICBMOiBtaW5tYXgoTCwgMCwgTUFYX1BDRU5UKSxcbiAgICAgICAgICAgICAgICAgICAgQzogbWlubWF4KEMsIC1NQVhfTENIX0MsIE1BWF9MQ0hfQyksXG4gICAgICAgICAgICAgICAgICAgIEg6IG5vcm1hbGl6ZUh1ZShIKVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgaWYgKHJlbGF0aXZlX2EpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgQSA9IG5ldyBDYWxjUGFyc2VyKCdhbHBoYScsIHJlbGF0aXZlX2EsIGZyb21MQ0hWYXJzKS5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIGxjaC5BID0gbWlubWF4KEEsIDAsIE1BWF9BTFBIQSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBsY2g7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBMOiBwZXJjZW50KGwpLFxuICAgICAgICAgICAgICAgICAgICBDOiBnZXRCYXNlMTUwTnVtYmVyKGMpLFxuICAgICAgICAgICAgICAgICAgICBIOiBub3JtYWxpemVIdWUoaCksXG4gICAgICAgICAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChhKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoYSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgTDogcGVyY2VudChpbnB1dC5MKSxcbiAgICAgICAgICAgIEM6IGdldEJhc2UxNTBOdW1iZXIoYCR7aW5wdXQuQ31gKSxcbiAgICAgICAgICAgIEg6IG5vcm1hbGl6ZUh1ZShpbnB1dC5IKSxcbiAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChpbnB1dC5BKVxuICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoaW5wdXQuQSlcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb252ZXJ0KGNvbG9yLCBkZWNpbWFscywgd2l0aEFscGhhKSB7XG4gICAgICAgIGxldCBsY2g7XG4gICAgICAgIGlmIChpc0xDSE9iamVjdChjb2xvcikpIHtcbiAgICAgICAgICAgIGxjaCA9IGNvbG9yO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcmdiID0gZ2V0UkdCKGNvbG9yKTtcbiAgICAgICAgICAgIGxjaCA9IHJnYlRvTGNoKHJnYi5SLCByZ2IuRywgcmdiLkIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9yb3VuZExDSE9iamVjdCh7XG4gICAgICAgICAgICBMOiBsY2guTCxcbiAgICAgICAgICAgIEM6IGxjaC5DLFxuICAgICAgICAgICAgSDogbGNoLkgsXG4gICAgICAgICAgICAuLi4od2l0aEFscGhhXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIEE6ICsoY29sb3IuQSA/PyAxKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA6IHt9KVxuICAgICAgICB9LCBkZWNpbWFscyk7XG4gICAgfVxuICAgIGNvbnZlcnRDU1MoY29sb3IsIG9wdGlvbnMsIHdpdGhBbHBoYSkge1xuICAgICAgICBjb25zdCB7IGRlY2ltYWxzLCBsY2hVbml0LCBhbmdsZXNVbml0IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBsY2ggPSB0aGlzLmNvbnZlcnQoY29sb3IsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgaWYgKGluZGV4ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgTCA9IHJvdW5kKHBlcmNlbnQodmFsdWUpLCBkZWNpbWFscyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxjaFVuaXQgPT09IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgICAgICA/IGAke0x9JWBcbiAgICAgICAgICAgICAgICAgICAgOiBgJHtMfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW5kZXggPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGNoVW5pdCA9PT0gQ29sb3JVbml0RW51bS5QRVJDRU5UXG4gICAgICAgICAgICAgICAgICAgID8gYCR7ZnJvbTE1ME51bWJlclRvUGVyY2VudCh2YWx1ZSwgZGVjaW1hbHMpfSVgXG4gICAgICAgICAgICAgICAgICAgIDogcm91bmQodmFsdWUsIGRlY2ltYWxzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMikge1xuICAgICAgICAgICAgICAgIGlmIChhbmdsZXNVbml0ICE9PSBBbmdsZXNVbml0RW51bS5OT05FKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zbGF0ZWQgPSByb3VuZCh0cmFuc2xhdGVEZWdyZWVzKHZhbHVlLCBhbmdsZXNVbml0KSwgZGVjaW1hbHMpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYCR7dHJhbnNsYXRlZH0ke2FuZ2xlc1VuaXR9YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvdW5kKHZhbHVlLCBkZWNpbWFscyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZ2V0Q1NTQWxwaGEodmFsdWUsIG9wdGlvbnMsIHRydWUpO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MobGNoLCB0cmFuc2Zvcm1lcik7XG4gICAgICAgIGNvbnN0IHRlbXBsYXRlID0gdmFsdWVzLmxlbmd0aCA9PT0gNFxuICAgICAgICAgICAgPyBgbGNoKHsxfSB7Mn0gezN9IC8gezR9KWBcbiAgICAgICAgICAgIDogYGxjaCh7MX0gezJ9IHszfSlgO1xuICAgICAgICByZXR1cm4gZ2V0UmVzdWx0RnJvbUNTU1RlbXBsYXRlKHRlbXBsYXRlLCB2YWx1ZXMpO1xuICAgIH1cbiAgICBfcm91bmRMQ0hPYmplY3QoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBMOiByb3VuZChjb2xvci5MLCBkZWNpbWFscyksXG4gICAgICAgICAgICBDOiByb3VuZChjb2xvci5DLCBkZWNpbWFscyksXG4gICAgICAgICAgICBIOiByb3VuZChub3JtYWxpemVIdWUoY29sb3IuSCksIGRlY2ltYWxzKSxcbiAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChjb2xvci5BKVxuICAgICAgICAgICAgICAgID8ge31cbiAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgQTogcm91bmQoY29sb3IuQSwgZGVjaW1hbHMpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZ2V0Q1NTT3B0aW9ucyhpbnB1dCkge1xuICAgICAgICBjb25zdCBncm91cHMgPSB0aGlzLl9leHRyYWN0KGlucHV0KTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGFuZ2xlVW5pdDogZ2V0QW5nbGVVbml0KGdyb3Vwcy5oKSxcbiAgICAgICAgICAgIGhhc1BlcmNlbnRhZ2VWYWx1ZXM6IChQQ0VOVC50ZXN0KGdyb3Vwcy5sKSAmJlxuICAgICAgICAgICAgICAgIFBDRU5ULnRlc3QoZ3JvdXBzLmMpKSxcbiAgICAgICAgICAgIGhhc1BlcmNlbnRhZ2VBbHBoYTogUENFTlQudGVzdChncm91cHMuYSksXG4gICAgICAgICAgICBoYXNBbHBoYTogIWlzVW5kZWZpbmVkKGdyb3Vwcy5hKVxuICAgICAgICB9O1xuICAgIH1cbiAgICBnZXQgbW9kZWwoKSB7XG4gICAgICAgIHJldHVybiBDb2xvck1vZGVsLkxDSDtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBDb2xvclVuaXRFbnVtIH0gZnJvbSAnQHR5cGVzJztcbmltcG9ydCB7IENvbG9yTW9kZWwsIENPTE9SUkVHUywgUENFTlQgfSBmcm9tICcjY29uc3RhbnRzJztcbmltcG9ydCB7IGdldENNWUtOdW1iZXIsIGlzQ01ZS09iamVjdCwgaXNTdHJpbmcsIGlzVW5kZWZpbmVkLCBub3JtYWxpemVBbHBoYSwgcm91bmQgfSBmcm9tICcjdXRpbGl0aWVzJztcbmltcG9ydCB7IGdldENTU0FscGhhLCBnZXRDU1NDb21tYSwgZ2V0UmVzdWx0RnJvbUNTU1RlbXBsYXRlLCBwcmVwYXJlQ29sb3JGb3JDc3MgfSBmcm9tICcjY3NzJztcbmltcG9ydCB7IGdldFJHQiB9IGZyb20gJyNjb2xvci9yZ2InO1xuaW1wb3J0IHsgcmdiVG9DbXlrIH0gZnJvbSAnI2NvbG9yL3RyYW5zbGF0b3JzJztcbmltcG9ydCB7IENvbG9yUGFyc2VyIH0gZnJvbSAnLi9Db2xvclBhcnNlckNvbnRleHQnO1xuZXhwb3J0IGNsYXNzIENNWUtQYXJzZXIgZXh0ZW5kcyBDb2xvclBhcnNlciB7XG4gICAgX2V4dHJhY3QoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgbWF0Y2ggPSBpbnB1dC5tYXRjaChDT0xPUlJFR1MuQ01ZSyk7XG4gICAgICAgIHJldHVybiBtYXRjaC5ncm91cHM7XG4gICAgfVxuICAgIF9zaG91bGRNdWx0aXBseUJ5MTAwKC4uLmNvbG9ycykge1xuICAgICAgICByZXR1cm4gIWNvbG9ycy5zb21lKChjb2xvcikgPT4gK2NvbG9yID4gMSk7XG4gICAgfVxuICAgIHN1cHBvcnRzKGlucHV0KSB7XG4gICAgICAgIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBDT0xPUlJFR1MuQ01ZSy50ZXN0KGlucHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNDTVlLT2JqZWN0KGlucHV0KTtcbiAgICB9XG4gICAgcGFyc2UoaW5wdXQpIHtcbiAgICAgICAgaWYgKGlzU3RyaW5nKGlucHV0KSkge1xuICAgICAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgICAgICBjb25zdCBjID0gZ3JvdXBzLmNfbGVnYWN5ID8/IGdyb3Vwcy5jO1xuICAgICAgICAgICAgY29uc3QgbSA9IGdyb3Vwcy5tX2xlZ2FjeSA/PyBncm91cHMubTtcbiAgICAgICAgICAgIGNvbnN0IHkgPSBncm91cHMueV9sZWdhY3kgPz8gZ3JvdXBzLnk7XG4gICAgICAgICAgICBjb25zdCBrID0gZ3JvdXBzLmtfbGVnYWN5ID8/IGdyb3Vwcy5rO1xuICAgICAgICAgICAgY29uc3QgYSA9IGdyb3Vwcy5hX2xlZ2FjeSA/PyBncm91cHMuYTtcbiAgICAgICAgICAgIGNvbnN0IHNob3VsZE11bHRpcGx5QnkxMDAgPSB0aGlzLl9zaG91bGRNdWx0aXBseUJ5MTAwKGMsIG0sIHksIGspO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBDOiBnZXRDTVlLTnVtYmVyKGMsIHNob3VsZE11bHRpcGx5QnkxMDApLFxuICAgICAgICAgICAgICAgIE06IGdldENNWUtOdW1iZXIobSwgc2hvdWxkTXVsdGlwbHlCeTEwMCksXG4gICAgICAgICAgICAgICAgWTogZ2V0Q01ZS051bWJlcih5LCBzaG91bGRNdWx0aXBseUJ5MTAwKSxcbiAgICAgICAgICAgICAgICBLOiBnZXRDTVlLTnVtYmVyKGssIHNob3VsZE11bHRpcGx5QnkxMDApLFxuICAgICAgICAgICAgICAgIC4uLihpc1VuZGVmaW5lZChhKVxuICAgICAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgQTogbm9ybWFsaXplQWxwaGEoYSlcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc2hvdWxkTXVsdGlwbHlCeTEwMCA9IHRoaXMuX3Nob3VsZE11bHRpcGx5QnkxMDAoaW5wdXQuQywgaW5wdXQuTSwgaW5wdXQuWSwgaW5wdXQuSyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBDOiBnZXRDTVlLTnVtYmVyKGAke2lucHV0LkN9YCwgc2hvdWxkTXVsdGlwbHlCeTEwMCksXG4gICAgICAgICAgICBNOiBnZXRDTVlLTnVtYmVyKGAke2lucHV0Lk19YCwgc2hvdWxkTXVsdGlwbHlCeTEwMCksXG4gICAgICAgICAgICBZOiBnZXRDTVlLTnVtYmVyKGAke2lucHV0Lll9YCwgc2hvdWxkTXVsdGlwbHlCeTEwMCksXG4gICAgICAgICAgICBLOiBnZXRDTVlLTnVtYmVyKGAke2lucHV0Lkt9YCwgc2hvdWxkTXVsdGlwbHlCeTEwMCksXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoaW5wdXQuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IG5vcm1hbGl6ZUFscGhhKGlucHV0LkEpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY29udmVydChjb2xvciwgZGVjaW1hbHMsIHdpdGhBbHBoYSkge1xuICAgICAgICBsZXQgY215aztcbiAgICAgICAgaWYgKGlzQ01ZS09iamVjdChjb2xvcikpIHtcbiAgICAgICAgICAgIGNteWsgPSBjb2xvcjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHJnYiA9IGdldFJHQihjb2xvcik7XG4gICAgICAgICAgICBjbXlrID0gcmdiVG9DbXlrKHJnYi5SLCByZ2IuRywgcmdiLkIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl9yb3VuZENNWUtPYmplY3Qoe1xuICAgICAgICAgICAgQzogY215ay5DLFxuICAgICAgICAgICAgTTogY215ay5NLFxuICAgICAgICAgICAgWTogY215ay5ZLFxuICAgICAgICAgICAgSzogY215ay5LLFxuICAgICAgICAgICAgLi4uKHdpdGhBbHBoYVxuICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICBBOiArKGNvbG9yLkEgPz8gMSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgOiB7fSlcbiAgICAgICAgfSwgZGVjaW1hbHMpO1xuICAgIH1cbiAgICBjb252ZXJ0Q1NTKGNvbG9yLCBvcHRpb25zLCB3aXRoQWxwaGEpIHtcbiAgICAgICAgY29uc3QgeyBkZWNpbWFscywgbGVnYWN5Q1NTLCBzcGFjZXNBZnRlckNvbW1hcywgY215a1VuaXQsIGNteWtGdW5jdGlvbiB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgY29tbWEgPSBnZXRDU1NDb21tYShzcGFjZXNBZnRlckNvbW1hcyk7XG4gICAgICAgIGNvbnN0IGNteWsgPSB0aGlzLmNvbnZlcnQoY29sb3IsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgaWYgKGNteWtVbml0ID09PSBDb2xvclVuaXRFbnVtLlBFUkNFTlQgJiZcbiAgICAgICAgICAgICAgICBpbmRleCA8IDQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYCR7cm91bmQodmFsdWUsIGRlY2ltYWxzKX0lYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpbmRleCA9PT0gNFxuICAgICAgICAgICAgICAgID8gZ2V0Q1NTQWxwaGEodmFsdWUsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgOiByb3VuZCh2YWx1ZSAvIDEwMCwgZGVjaW1hbHMpO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCB2YWx1ZXMgPSBwcmVwYXJlQ29sb3JGb3JDc3MoY215aywgdHJhbnNmb3JtZXIpO1xuICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGxlZ2FjeUNTU1xuICAgICAgICAgICAgPyAodmFsdWVzLmxlbmd0aCA9PT0gNVxuICAgICAgICAgICAgICAgID8gYCR7Y215a0Z1bmN0aW9ufSh7MX0ke2NvbW1hfXsyfSR7Y29tbWF9ezN9JHtjb21tYX17NH0ke2NvbW1hfXs1fSlgXG4gICAgICAgICAgICAgICAgOiBgJHtjbXlrRnVuY3Rpb259KHsxfSR7Y29tbWF9ezJ9JHtjb21tYX17M30ke2NvbW1hfXs0fSlgKVxuICAgICAgICAgICAgOiAodmFsdWVzLmxlbmd0aCA9PT0gNVxuICAgICAgICAgICAgICAgID8gYCR7Y215a0Z1bmN0aW9ufSh7MX0gezJ9IHszfSB7NH0gLyB7NX0pYFxuICAgICAgICAgICAgICAgIDogYCR7Y215a0Z1bmN0aW9ufSh7MX0gezJ9IHszfSB7NH0pYCk7XG4gICAgICAgIHJldHVybiBnZXRSZXN1bHRGcm9tQ1NTVGVtcGxhdGUodGVtcGxhdGUsIHZhbHVlcyk7XG4gICAgfVxuICAgIF9yb3VuZENNWUtPYmplY3QoY29sb3IsIGRlY2ltYWxzKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBDOiByb3VuZChjb2xvci5DLCBkZWNpbWFscyksXG4gICAgICAgICAgICBNOiByb3VuZChjb2xvci5NLCBkZWNpbWFscyksXG4gICAgICAgICAgICBZOiByb3VuZChjb2xvci5ZLCBkZWNpbWFscyksXG4gICAgICAgICAgICBLOiByb3VuZChjb2xvci5LLCBkZWNpbWFscyksXG4gICAgICAgICAgICAuLi4oaXNVbmRlZmluZWQoY29sb3IuQSlcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIEE6IHJvdW5kKGNvbG9yLkEsIGRlY2ltYWxzKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldENTU09wdGlvbnMoaW5wdXQpIHtcbiAgICAgICAgY29uc3QgZ3JvdXBzID0gdGhpcy5fZXh0cmFjdChpbnB1dCk7XG4gICAgICAgIGNvbnN0IHsgY19sZWdhY3ksIG1fbGVnYWN5LCB5X2xlZ2FjeSwga19sZWdhY3ksIGFfbGVnYWN5LCBjLCBtLCB5LCBrLCBhIH0gPSBncm91cHM7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoYXNQZXJjZW50YWdlVmFsdWVzOiAoUENFTlQudGVzdChjX2xlZ2FjeSA/PyBjKSAmJlxuICAgICAgICAgICAgICAgIFBDRU5ULnRlc3QobV9sZWdhY3kgPz8gbSkgJiZcbiAgICAgICAgICAgICAgICBQQ0VOVC50ZXN0KHlfbGVnYWN5ID8/IHkpICYmXG4gICAgICAgICAgICAgICAgUENFTlQudGVzdChrX2xlZ2FjeSA/PyBrKSksXG4gICAgICAgICAgICBoYXNQZXJjZW50YWdlQWxwaGE6IFBDRU5ULnRlc3QoYV9sZWdhY3kgPz8gYSksXG4gICAgICAgICAgICBoYXNBbHBoYTogIWlzVW5kZWZpbmVkKGFfbGVnYWN5ID8/IGEpXG4gICAgICAgIH07XG4gICAgfVxuICAgIGdldCBtb2RlbCgpIHtcbiAgICAgICAgcmV0dXJuIENvbG9yTW9kZWwuQ01ZSztcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBBbmdsZXNVbml0RW51bSwgQ01ZS0Z1bmN0aW9uRW51bSwgQ29sb3JVbml0RW51bSB9IGZyb20gJ0B0eXBlcyc7XG5pbXBvcnQgeyBDb2xvck1vZGVsLCBDT01NQVNfQU5EX05FWFRfQ0hBUlMsIERFRkFVTFRfT1BUSU9OUywgU1BBQ0VTIH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBpc0Jvb2xlYW4sIGlzTnVtYmVyLCBpc1N0cmluZyB9IGZyb20gJyN1dGlsaXRpZXMnO1xuaW1wb3J0IHsgQ29sb3JQYXJzZXJDb250ZXh0IH0gZnJvbSAnI2NsYXNzZXMvQ29sb3JQYXJzZXJDb250ZXh0JztcbmltcG9ydCB7IEhFWFBhcnNlciB9IGZyb20gJyNjbGFzc2VzL0hFWFBhcnNlcic7XG5pbXBvcnQgeyBSR0JQYXJzZXIgfSBmcm9tICcjY2xhc3Nlcy9SR0JQYXJzZXInO1xuaW1wb3J0IHsgSFNMUGFyc2VyIH0gZnJvbSAnI2NsYXNzZXMvSFNMUGFyc2VyJztcbmltcG9ydCB7IEhXQlBhcnNlciB9IGZyb20gJyNjbGFzc2VzL0hXQlBhcnNlcic7XG5pbXBvcnQgeyBDSUVMYWJQYXJzZXIgfSBmcm9tICcjY2xhc3Nlcy9DSUVMYWJQYXJzZXInO1xuaW1wb3J0IHsgTENIUGFyc2VyIH0gZnJvbSAnI2NsYXNzZXMvTENIUGFyc2VyJztcbmltcG9ydCB7IENNWUtQYXJzZXIgfSBmcm9tICcjY2xhc3Nlcy9DTVlLUGFyc2VyJztcbmV4cG9ydCBjb25zdCBoZXhQYXJzZXIgPSBuZXcgSEVYUGFyc2VyKCk7XG5leHBvcnQgY29uc3QgcmdiUGFyc2VyID0gbmV3IFJHQlBhcnNlcigpO1xuZXhwb3J0IGNvbnN0IGhzbFBhcnNlciA9IG5ldyBIU0xQYXJzZXIoKTtcbmV4cG9ydCBjb25zdCBod2JQYXJzZXIgPSBuZXcgSFdCUGFyc2VyKCk7XG5leHBvcnQgY29uc3QgY2llTGFiUGFyc2VyID0gbmV3IENJRUxhYlBhcnNlcigpO1xuZXhwb3J0IGNvbnN0IGxjaFBhcnNlciA9IG5ldyBMQ0hQYXJzZXIoKTtcbmV4cG9ydCBjb25zdCBjbXlrUGFyc2VyID0gbmV3IENNWUtQYXJzZXIoKTtcbmV4cG9ydCBjb25zdCBjb2xvclBhcnNlckNvbnRleHQgPSBuZXcgQ29sb3JQYXJzZXJDb250ZXh0KHtcbiAgICBbQ29sb3JNb2RlbC5IRVhdOiBoZXhQYXJzZXIsXG4gICAgW0NvbG9yTW9kZWwuUkdCXTogcmdiUGFyc2VyLFxuICAgIFtDb2xvck1vZGVsLkhTTF06IGhzbFBhcnNlcixcbiAgICBbQ29sb3JNb2RlbC5IV0JdOiBod2JQYXJzZXIsXG4gICAgW0NvbG9yTW9kZWwuQ0lFTGFiXTogY2llTGFiUGFyc2VyLFxuICAgIFtDb2xvck1vZGVsLkxDSF06IGxjaFBhcnNlcixcbiAgICBbQ29sb3JNb2RlbC5DTVlLXTogY215a1BhcnNlclxufSk7XG5leHBvcnQgY29uc3QgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0ID0gKG9wdGlvbnMsIC4uLmNvbG9ycykgPT4ge1xuICAgIGNvbnN0IGNzc0NvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGFuZ2xlc1VuaXRzID0gW107XG4gICAgY29uc3QgcmdiQ29sb3JzID0gW107XG4gICAgY29uc3QgbGFiQ29sb3JzID0gW107XG4gICAgY29uc3QgbGNoQ29sb3JzID0gW107XG4gICAgY29uc3QgY215a0NvbG9ycyA9IFtdO1xuICAgIGNvbnN0IGFscGhhVmFsdWVzID0gW107XG4gICAgY29uc3QgYW5nbGVzVW5pdFZhbHVlcyA9IE9iamVjdC52YWx1ZXMoQW5nbGVzVW5pdEVudW0pO1xuICAgIGNvbnN0IGNvbG9yVW5pdFZhbHVlcyA9IE9iamVjdC52YWx1ZXMoQ29sb3JVbml0RW51bSk7XG4gICAgY29uc3QgY215a0Z1bmN0aW9uVmFsdWVzID0gT2JqZWN0LnZhbHVlcyhDTVlLRnVuY3Rpb25FbnVtKTtcbiAgICBjb25zdCBtYXRjaE9wdGlvbnMgPSB7XG4gICAgICAgIGxlZ2FjeUNTUzogMCxcbiAgICAgICAgc3BhY2VzQWZ0ZXJDb21tYXM6IDAsXG4gICAgICAgIGNteWtGdW5jdGlvbjogMFxuICAgIH07XG4gICAgZm9yIChjb25zdCBjb2xvciBvZiBjb2xvcnMpIHtcbiAgICAgICAgaWYgKGlzU3RyaW5nKGNvbG9yKSkge1xuICAgICAgICAgICAgY3NzQ29sb3JzLnB1c2goY29sb3IpO1xuICAgICAgICAgICAgaWYgKGNvbG9yLmluY2x1ZGVzKCcsJykpIHtcbiAgICAgICAgICAgICAgICBtYXRjaE9wdGlvbnMubGVnYWN5Q1NTKys7XG4gICAgICAgICAgICAgICAgY29uc3QgY29tbWFzV2l0aE5leHRDaGFyYWN0ZXIgPSBjb2xvci5tYXRjaChDT01NQVNfQU5EX05FWFRfQ0hBUlMpO1xuICAgICAgICAgICAgICAgIGlmIChuZXcgU2V0KGNvbW1hc1dpdGhOZXh0Q2hhcmFjdGVyKS5zaXplID09PSAxICYmXG4gICAgICAgICAgICAgICAgICAgIFNQQUNFUy50ZXN0KGNvbW1hc1dpdGhOZXh0Q2hhcmFjdGVyWzBdLnNsaWNlKDEpKSkge1xuICAgICAgICAgICAgICAgICAgICBtYXRjaE9wdGlvbnMuc3BhY2VzQWZ0ZXJDb21tYXMrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaHNsUGFyc2VyLnN1cHBvcnRzKGNvbG9yKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSBoc2xQYXJzZXIuZ2V0Q1NTT3B0aW9ucyhjb2xvcik7XG4gICAgICAgICAgICAgICAgYW5nbGVzVW5pdHMucHVzaChvcHRpb25zLmFuZ2xlVW5pdCk7XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChvcHRpb25zLmhhc1BlcmNlbnRhZ2VBbHBoYSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaHdiUGFyc2VyLnN1cHBvcnRzKGNvbG9yKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSBod2JQYXJzZXIuZ2V0Q1NTT3B0aW9ucyhjb2xvcik7XG4gICAgICAgICAgICAgICAgYW5nbGVzVW5pdHMucHVzaChvcHRpb25zLmFuZ2xlVW5pdCk7XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChvcHRpb25zLmhhc1BlcmNlbnRhZ2VBbHBoYSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmdiUGFyc2VyLnN1cHBvcnRzKGNvbG9yKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSByZ2JQYXJzZXIuZ2V0Q1NTT3B0aW9ucyhjb2xvcik7XG4gICAgICAgICAgICAgICAgcmdiQ29sb3JzLnB1c2gob3B0aW9ucy5oYXNQZXJjZW50YWdlVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBhbHBoYVZhbHVlcy5wdXNoKG9wdGlvbnMuaGFzUGVyY2VudGFnZUFscGhhKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjaWVMYWJQYXJzZXIuc3VwcG9ydHMoY29sb3IpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IGNpZUxhYlBhcnNlci5nZXRDU1NPcHRpb25zKGNvbG9yKTtcbiAgICAgICAgICAgICAgICBsYWJDb2xvcnMucHVzaChvcHRpb25zLmhhc1BlcmNlbnRhZ2VWYWx1ZXMpO1xuICAgICAgICAgICAgICAgIGFscGhhVmFsdWVzLnB1c2gob3B0aW9ucy5oYXNQZXJjZW50YWdlQWxwaGEpO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGxjaFBhcnNlci5zdXBwb3J0cyhjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25zID0gbGNoUGFyc2VyLmdldENTU09wdGlvbnMoY29sb3IpO1xuICAgICAgICAgICAgICAgIGFuZ2xlc1VuaXRzLnB1c2gob3B0aW9ucy5hbmdsZVVuaXQpO1xuICAgICAgICAgICAgICAgIGxjaENvbG9ycy5wdXNoKG9wdGlvbnMuaGFzUGVyY2VudGFnZVZhbHVlcyk7XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChvcHRpb25zLmhhc1BlcmNlbnRhZ2VBbHBoYSk7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY215a1BhcnNlci5zdXBwb3J0cyhjb2xvcikpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcHRpb25zID0gY215a1BhcnNlci5nZXRDU1NPcHRpb25zKGNvbG9yKTtcbiAgICAgICAgICAgICAgICBjbXlrQ29sb3JzLnB1c2gob3B0aW9ucy5oYXNQZXJjZW50YWdlVmFsdWVzKTtcbiAgICAgICAgICAgICAgICBpZiAoY29sb3Iuc3RhcnRzV2l0aCgnY215aycpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoT3B0aW9ucy5jbXlrRnVuY3Rpb24rKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYWxwaGFWYWx1ZXMucHVzaChvcHRpb25zLmhhc1BlcmNlbnRhZ2VBbHBoYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGVjaW1hbHM6IGlzTnVtYmVyKG9wdGlvbnMuZGVjaW1hbHMpXG4gICAgICAgICAgICA/IG9wdGlvbnMuZGVjaW1hbHNcbiAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmRlY2ltYWxzLFxuICAgICAgICBsZWdhY3lDU1M6IGlzQm9vbGVhbihvcHRpb25zLmxlZ2FjeUNTUylcbiAgICAgICAgICAgID8gb3B0aW9ucy5sZWdhY3lDU1NcbiAgICAgICAgICAgIDogQm9vbGVhbihjc3NDb2xvcnMubGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgbWF0Y2hPcHRpb25zLmxlZ2FjeUNTUyA9PT0gY3NzQ29sb3JzLmxlbmd0aCkgfHwgREVGQVVMVF9PUFRJT05TLmxlZ2FjeUNTUyxcbiAgICAgICAgc3BhY2VzQWZ0ZXJDb21tYXM6IGlzQm9vbGVhbihvcHRpb25zLnNwYWNlc0FmdGVyQ29tbWFzKVxuICAgICAgICAgICAgPyBvcHRpb25zLnNwYWNlc0FmdGVyQ29tbWFzXG4gICAgICAgICAgICA6IEJvb2xlYW4oY3NzQ29sb3JzLmxlbmd0aCAmJlxuICAgICAgICAgICAgICAgIG1hdGNoT3B0aW9ucy5zcGFjZXNBZnRlckNvbW1hcyA9PT0gY3NzQ29sb3JzLmxlbmd0aCkgfHwgREVGQVVMVF9PUFRJT05TLnNwYWNlc0FmdGVyQ29tbWFzLFxuICAgICAgICBhbmdsZXNVbml0OiBvcHRpb25zLmFuZ2xlc1VuaXQgJiYgYW5nbGVzVW5pdFZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLmFuZ2xlc1VuaXQpXG4gICAgICAgICAgICA/IG9wdGlvbnMuYW5nbGVzVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChhbmdsZXNVbml0cykuc2l6ZSA9PT0gMVxuICAgICAgICAgICAgICAgID8gYW5nbGVzVW5pdHNbMF1cbiAgICAgICAgICAgICAgICA6IERFRkFVTFRfT1BUSU9OUy5hbmdsZXNVbml0KSxcbiAgICAgICAgcmdiVW5pdDogb3B0aW9ucy5yZ2JVbml0ICYmIGNvbG9yVW5pdFZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLnJnYlVuaXQpXG4gICAgICAgICAgICA/IG9wdGlvbnMucmdiVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChyZ2JDb2xvcnMpLnNpemUgPT09IDEgJiYgcmdiQ29sb3JzWzBdXG4gICAgICAgICAgICAgICAgPyBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICA6IERFRkFVTFRfT1BUSU9OUy5yZ2JVbml0KSxcbiAgICAgICAgbGFiVW5pdDogb3B0aW9ucy5sYWJVbml0ICYmIGNvbG9yVW5pdFZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLmxhYlVuaXQpXG4gICAgICAgICAgICA/IG9wdGlvbnMubGFiVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChsYWJDb2xvcnMpLnNpemUgPT09IDEgJiYgbGFiQ29sb3JzWzBdXG4gICAgICAgICAgICAgICAgPyBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICA6IERFRkFVTFRfT1BUSU9OUy5sYWJVbml0KSxcbiAgICAgICAgbGNoVW5pdDogb3B0aW9ucy5sY2hVbml0ICYmIGNvbG9yVW5pdFZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLmxjaFVuaXQpXG4gICAgICAgICAgICA/IG9wdGlvbnMubGNoVW5pdFxuICAgICAgICAgICAgOiAobmV3IFNldChsY2hDb2xvcnMpLnNpemUgPT09IDEgJiYgbGNoQ29sb3JzWzBdXG4gICAgICAgICAgICAgICAgPyBDb2xvclVuaXRFbnVtLlBFUkNFTlRcbiAgICAgICAgICAgICAgICA6IERFRkFVTFRfT1BUSU9OUy5sY2hVbml0KSxcbiAgICAgICAgY215a1VuaXQ6IG9wdGlvbnMuY215a1VuaXQgJiYgY29sb3JVbml0VmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMuY215a1VuaXQpXG4gICAgICAgICAgICA/IG9wdGlvbnMuY215a1VuaXRcbiAgICAgICAgICAgIDogKG5ldyBTZXQoY215a0NvbG9ycykuc2l6ZSA9PT0gMSAmJiAhY215a0NvbG9yc1swXVxuICAgICAgICAgICAgICAgID8gQ29sb3JVbml0RW51bS5OT05FXG4gICAgICAgICAgICAgICAgOiBERUZBVUxUX09QVElPTlMuY215a1VuaXQpLFxuICAgICAgICBhbHBoYVVuaXQ6IG9wdGlvbnMuYWxwaGFVbml0ICYmIGNvbG9yVW5pdFZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLmFscGhhVW5pdClcbiAgICAgICAgICAgID8gb3B0aW9ucy5hbHBoYVVuaXRcbiAgICAgICAgICAgIDogKG5ldyBTZXQoYWxwaGFWYWx1ZXMpLnNpemUgPT09IDEgJiYgYWxwaGFWYWx1ZXNbMF1cbiAgICAgICAgICAgICAgICA/IENvbG9yVW5pdEVudW0uUEVSQ0VOVFxuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmFscGhhVW5pdCksXG4gICAgICAgIGNteWtGdW5jdGlvbjogb3B0aW9ucy5jbXlrRnVuY3Rpb24gJiYgY215a0Z1bmN0aW9uVmFsdWVzLmluY2x1ZGVzKG9wdGlvbnMuY215a0Z1bmN0aW9uKVxuICAgICAgICAgICAgPyBvcHRpb25zLmNteWtGdW5jdGlvblxuICAgICAgICAgICAgOiAoY215a0NvbG9ycy5sZW5ndGggJiYgY215a0NvbG9ycy5sZW5ndGggPT09IG1hdGNoT3B0aW9ucy5jbXlrRnVuY3Rpb25cbiAgICAgICAgICAgICAgICA/IENNWUtGdW5jdGlvbkVudW0uQ01ZS1xuICAgICAgICAgICAgICAgIDogREVGQVVMVF9PUFRJT05TLmNteWtGdW5jdGlvbilcbiAgICB9O1xufTtcbiIsImltcG9ydCB7IEJBU0VfMjU1LCBDb2xvck1vZGVsLCBERUZBVUxUX0JMRU5EX1NURVBTLCBERUZBVUxUX1NIQURFU19USU5UU19TVEVQUywgSGFybW9ueSwgTWl4IH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBpc0hhcm1vbnksIGlzTnVtYmVyLCBpc1N0cmluZywgaXNNaXgsIGlzVW5kZWZpbmVkLCBub3JtYWxpemVBbHBoYSwgbm9ybWFsaXplSHVlLCByb3VuZCB9IGZyb20gJyN1dGlsaXRpZXMnO1xuaW1wb3J0IHsgaHVlUnliLCByZ2JUb1J5YiwgcnliVG9SZ2IgfSBmcm9tICcjY29sb3IvdHJhbnNsYXRvcnMnO1xuaW1wb3J0IHsgZ2V0UkdCIH0gZnJvbSAnI2NvbG9yL3JnYic7XG5pbXBvcnQgeyBjb2xvclBhcnNlckNvbnRleHQsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dCB9IGZyb20gJyNwYXJzZXJzJztcbmNvbnN0IGJsZW5kID0gKGZyb20sIHRvLCBzdGVwcykgPT4ge1xuICAgIGNvbnN0IGRpdiA9IHN0ZXBzIC0gMTtcbiAgICBjb25zdCBkaWZmUiA9ICh0by5SIC0gZnJvbS5SKSAvIGRpdjtcbiAgICBjb25zdCBkaWZmRyA9ICh0by5HIC0gZnJvbS5HKSAvIGRpdjtcbiAgICBjb25zdCBkaWZmQiA9ICh0by5CIC0gZnJvbS5CKSAvIGRpdjtcbiAgICBjb25zdCBmcm9tQSA9IG5vcm1hbGl6ZUFscGhhKGZyb20uQSk7XG4gICAgY29uc3QgdG9BID0gbm9ybWFsaXplQWxwaGEodG8uQSk7XG4gICAgY29uc3QgZGlmZkEgPSAodG9BIC0gZnJvbUEpIC8gZGl2O1xuICAgIHJldHVybiBBcnJheShzdGVwcykuZmlsbChudWxsKS5tYXAoKF9fbiwgaSkgPT4ge1xuICAgICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGZyb207XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGkgPT09IGRpdikge1xuICAgICAgICAgICAgcmV0dXJuIHRvO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBSOiByb3VuZChmcm9tLlIgKyBkaWZmUiAqIGkpLFxuICAgICAgICAgICAgRzogcm91bmQoZnJvbS5HICsgZGlmZkcgKiBpKSxcbiAgICAgICAgICAgIEI6IHJvdW5kKGZyb20uQiArIGRpZmZCICogaSksXG4gICAgICAgICAgICBBOiByb3VuZChmcm9tQSArIGRpZmZBICogaSlcbiAgICAgICAgfTtcbiAgICB9KTtcbn07XG5leHBvcnQgZnVuY3Rpb24gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIG1vZGVsLCBjc3MsIHdpdGhBbHBoYSwgc3RlcHMgPSBERUZBVUxUX0JMRU5EX1NURVBTLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAoc3RlcHMgPCAxKVxuICAgICAgICBzdGVwcyA9IERFRkFVTFRfQkxFTkRfU1RFUFM7XG4gICAgY29uc3QgZnJvbVBhcnNlZCA9IGNvbG9yUGFyc2VyQ29udGV4dC5wYXJzZShmcm9tKTtcbiAgICBjb25zdCB0b1BhcnNlZCA9IGNvbG9yUGFyc2VyQ29udGV4dC5wYXJzZSh0byk7XG4gICAgY29uc3QgZnJvbVJHQk9iamVjdCA9IGdldFJHQihmcm9tUGFyc2VkKTtcbiAgICBjb25zdCB0b1JHQk9iamVjdCA9IGdldFJHQih0b1BhcnNlZCk7XG4gICAgY29uc3QgYmxlbmRBcnJheSA9IGJsZW5kKGZyb21SR0JPYmplY3QsIHRvUkdCT2JqZWN0LCBzdGVwcyk7XG4gICAgcmV0dXJuIGJsZW5kQXJyYXkubWFwKChjb2xvcikgPT4ge1xuICAgICAgICBpZiAoY3NzKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1MoY29sb3IsIG1vZGVsLCBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgZnJvbSwgdG8pLCB3aXRoQWxwaGEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydChjb2xvciwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG4gICAgfSk7XG59XG5leHBvcnQgY29uc3QgZ2V0QmxlbmRSZXR1cm5QYXJhbXMgPSAodGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikgPT4ge1xuICAgIGNvbnN0IHN0ZXBzUGFyYW1ldGVyID0gaXNOdW1iZXIodGhpcmRQYXJhbWV0ZXIpXG4gICAgICAgID8gdGhpcmRQYXJhbWV0ZXJcbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb3B0aW9uc1BhcmFtZXRlciA9IGlzTnVtYmVyKHRoaXJkUGFyYW1ldGVyKVxuICAgICAgICA/IGZvdXJ0aFBhcmFtZXRlclxuICAgICAgICA6IHRoaXJkUGFyYW1ldGVyO1xuICAgIHJldHVybiBbXG4gICAgICAgIHN0ZXBzUGFyYW1ldGVyLFxuICAgICAgICBvcHRpb25zUGFyYW1ldGVyXG4gICAgXTtcbn07XG5leHBvcnQgZnVuY3Rpb24gZ2V0TWl4UmV0dXJuKGNvbG9ycywgbW9kZWwsIGNzcywgd2l0aEFscGhhLCBtb2RlID0gTWl4LkFERElUSVZFLCBvcHRpb25zID0ge30pIHtcbiAgICBjb25zdCByZ2JNYXAgPSBjb2xvcnMubWFwKChjb2xvcikgPT4ge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuUkdCLCBvcHRpb25zLmRlY2ltYWxzLCB3aXRoQWxwaGEpO1xuICAgIH0pO1xuICAgIGNvbnN0IHJ5Yk1hcCA9IG1vZGUgPT09IE1peC5TVUJUUkFDVElWRVxuICAgICAgICA/IHJnYk1hcC5tYXAoKGNvbG9yKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBSWUIgPSByZ2JUb1J5Yihjb2xvci5SLCBjb2xvci5HLCBjb2xvci5CKTtcbiAgICAgICAgICAgIGlmICghaXNVbmRlZmluZWQoY29sb3IuQSkpIHtcbiAgICAgICAgICAgICAgICBSWUIuQSA9IGNvbG9yLkE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gUllCO1xuICAgICAgICB9KVxuICAgICAgICA6IG51bGw7XG4gICAgZnVuY3Rpb24gY3JlYXRlTWl4KGl0ZW1zKSB7XG4gICAgICAgIGNvbnN0IGluaXRpYWwgPSBtb2RlID09PSBNaXguQURESVRJVkVcbiAgICAgICAgICAgID8geyBSOiAwLCBHOiAwLCBCOiAwLCBBOiAwIH1cbiAgICAgICAgICAgIDogeyBSOiAwLCBZOiAwLCBCOiAwLCBBOiAwIH07XG4gICAgICAgIHJldHVybiBpdGVtcy5yZWR1Y2UoKG1peCwgY29sb3IpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbG9yQSA9IGlzVW5kZWZpbmVkKGNvbG9yLkEpXG4gICAgICAgICAgICAgICAgPyAxXG4gICAgICAgICAgICAgICAgOiBjb2xvci5BO1xuICAgICAgICAgICAgY29uc3QgY29tbW9uID0ge1xuICAgICAgICAgICAgICAgIFI6IE1hdGgubWluKG1peC5SICsgY29sb3IuUiAqIGNvbG9yQSwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgIEI6IE1hdGgubWluKG1peC5CICsgY29sb3IuQiAqIGNvbG9yQSwgQkFTRV8yNTUpLFxuICAgICAgICAgICAgICAgIEE6IDEgLSAoMSAtIGNvbG9yQSkgKiAoMSAtIG1peC5BKVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IG1peEdZID0gJ0cnIGluIG1peFxuICAgICAgICAgICAgICAgID8gbWl4LkdcbiAgICAgICAgICAgICAgICA6IG1peC5ZO1xuICAgICAgICAgICAgY29uc3QgY29sb3JHWSA9ICdHJyBpbiBjb2xvclxuICAgICAgICAgICAgICAgID8gY29sb3IuR1xuICAgICAgICAgICAgICAgIDogY29sb3IuWTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4uY29tbW9uLFxuICAgICAgICAgICAgICAgIC4uLihtb2RlID09PSBNaXguQURESVRJVkVcbiAgICAgICAgICAgICAgICAgICAgPyB7IEc6IE1hdGgubWluKG1peEdZICsgY29sb3JHWSAqIGNvbG9yQSwgQkFTRV8yNTUpIH1cbiAgICAgICAgICAgICAgICAgICAgOiB7IFk6IE1hdGgubWluKG1peEdZICsgY29sb3JHWSAqIGNvbG9yQSwgQkFTRV8yNTUpIH0pXG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCBpbml0aWFsKTtcbiAgICB9XG4gICAgbGV0IG1peDtcbiAgICBpZiAobW9kZSA9PT0gTWl4LkFERElUSVZFKSB7XG4gICAgICAgIG1peCA9IGNyZWF0ZU1peChyZ2JNYXApO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgY29uc3QgUllCID0gY3JlYXRlTWl4KHJ5Yk1hcCk7XG4gICAgICAgIG1peCA9IHJ5YlRvUmdiKFJZQi5SLCBSWUIuWSwgUllCLkIpO1xuICAgICAgICBtaXguQSA9IFJZQi5BO1xuICAgIH1cbiAgICBpZiAoY3NzKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhtaXgsIG1vZGVsLCBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgLi4uY29sb3JzKSwgd2l0aEFscGhhKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KG1peCwgbW9kZWwsIG9wdGlvbnMuZGVjaW1hbHMsIHdpdGhBbHBoYSk7XG59XG47XG5leHBvcnQgY29uc3QgZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyA9IChzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSA9PiB7XG4gICAgY29uc3QgbW9kZVBhcmFtID0gaXNTdHJpbmcoc2Vjb25kUGFyYW1ldGVyKVxuICAgICAgICA/IHNlY29uZFBhcmFtZXRlclxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBvcHRpb25zUGFyYW0gPSBpc1N0cmluZyhzZWNvbmRQYXJhbWV0ZXIpXG4gICAgICAgID8gdGhpcmRQYXJhbWV0ZXJcbiAgICAgICAgOiBzZWNvbmRQYXJhbWV0ZXI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgbW9kZVBhcmFtLFxuICAgICAgICBvcHRpb25zUGFyYW1cbiAgICBdO1xufTtcbmV4cG9ydCBmdW5jdGlvbiBnZXRTaGFkZXNPclRpbnRzUmV0dXJuKHNoYWRlcywgY29sb3IsIHN0ZXBzID0gREVGQVVMVF9TSEFERVNfVElOVFNfU1RFUFMsIG9wdGlvbnMgPSB7fSkge1xuICAgIGNvbnN0IGlzQ1NTID0gaXNTdHJpbmcoY29sb3IpO1xuICAgIGNvbnN0IHBhcnNlciA9IGNvbG9yUGFyc2VyQ29udGV4dC5nZXRQYXJzZXIoY29sb3IpO1xuICAgIGNvbnN0IG1vZGVsID0gcGFyc2VyLm1vZGVsO1xuICAgIGNvbnN0IHdpdGhBbHBoYSA9IHBhcnNlci5oYXNBbHBoYShjb2xvcik7XG4gICAgY29uc3QgaHNsID0gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuSFNMLCB1bmRlZmluZWQsIHdpdGhBbHBoYSk7XG4gICAgY29uc3QgaW5jcmVtZW50ID0gc2hhZGVzXG4gICAgICAgID8gaHNsLkwgLyAoc3RlcHMgKyAxKVxuICAgICAgICA6ICgxMDAgLSBoc2wuTCkgLyAoc3RlcHMgKyAxKTtcbiAgICBjb25zdCBoc2xNYXAgPSBBcnJheS5mcm9tKEFycmF5KHN0ZXBzKSkubWFwKChfX24sIGkpID0+ICh7XG4gICAgICAgIC4uLmhzbCxcbiAgICAgICAgTDogaHNsLkwgKyBpbmNyZW1lbnQgKiAoaSArIDEpICogKDEgLSArc2hhZGVzICogMilcbiAgICB9KSk7XG4gICAgaWYgKGlzQ1NTKSB7XG4gICAgICAgIHJldHVybiBoc2xNYXAubWFwKChoc2xDb2xvcikgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGhzbENvbG9yLCBtb2RlbCwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSwgd2l0aEFscGhhKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBoc2xNYXAubWFwKChoc2xDb2xvcikgPT4ge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoaHNsQ29sb3IsIG1vZGVsLCBvcHRpb25zLmRlY2ltYWxzLCB3aXRoQWxwaGEpO1xuICAgIH0pO1xufVxuZXhwb3J0IGNvbnN0IGdldFNoYWRlc09yVGludHNSZXR1cm5QYXJhbWV0ZXJzID0gKHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpID0+IHtcbiAgICBjb25zdCBzdGVwc1BhcmFtID0gaXNOdW1iZXIoc2Vjb25kUGFyYW1ldGVyKVxuICAgICAgICA/IHNlY29uZFBhcmFtZXRlclxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBvcHRpb25zUGFyYW0gPSBpc051bWJlcihzZWNvbmRQYXJhbWV0ZXIpXG4gICAgICAgID8gdGhpcmRQYXJhbWV0ZXJcbiAgICAgICAgOiBzZWNvbmRQYXJhbWV0ZXI7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgc3RlcHNQYXJhbSxcbiAgICAgICAgb3B0aW9uc1BhcmFtXG4gICAgXTtcbn07XG5jb25zdCBoYXJtb255ID0gKGNvbG9yLCBhbmdsZXMsIG1vZGUpID0+IGFuZ2xlcy5yZWR1Y2UoKGFyciwgbnVtKSA9PiB7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgLi4uYXJyLFxuICAgICAgICB7XG4gICAgICAgICAgICAuLi5jb2xvcixcbiAgICAgICAgICAgIEg6IG1vZGUgPT09IE1peC5BRERJVElWRVxuICAgICAgICAgICAgICAgID8gbm9ybWFsaXplSHVlKGNvbG9yLkggKyBudW0pXG4gICAgICAgICAgICAgICAgOiBub3JtYWxpemVIdWUoaHVlUnliKGh1ZVJ5Yihjb2xvci5ILCBmYWxzZSkgKyBudW0sIHRydWUpKVxuICAgICAgICB9XG4gICAgXTtcbn0sIFt7IC4uLmNvbG9yIH1dKTtcbmNvbnN0IEhBUk1PTklFUyA9IG5ldyBNYXAoW1xuICAgIFtcbiAgICAgICAgSGFybW9ueS5BTkFMT0dPVVMsXG4gICAgICAgIChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzMwLCAtMzBdLCBtb2RlKVxuICAgIF0sXG4gICAgW1xuICAgICAgICBIYXJtb255LkNPTVBMRU1FTlRBUlksXG4gICAgICAgIChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzE4MF0sIG1vZGUpXG4gICAgXSxcbiAgICBbXG4gICAgICAgIEhhcm1vbnkuU1BMSVRfQ09NUExFTUVOVEFSWSxcbiAgICAgICAgKGNvbG9yLCBtb2RlKSA9PiBoYXJtb255KGNvbG9yLCBbMTUwLCAtMTUwXSwgbW9kZSlcbiAgICBdLFxuICAgIFtcbiAgICAgICAgSGFybW9ueS5UUklBRElDLFxuICAgICAgICAoY29sb3IsIG1vZGUpID0+IGhhcm1vbnkoY29sb3IsIFsxMjAsIC0xMjBdLCBtb2RlKVxuICAgIF0sXG4gICAgW1xuICAgICAgICBIYXJtb255LlRFVFJBRElDLFxuICAgICAgICAoY29sb3IsIG1vZGUpID0+IGhhcm1vbnkoY29sb3IsIFs2MCwgLTEyMCwgMTgwXSwgbW9kZSlcbiAgICBdLFxuICAgIFtcbiAgICAgICAgSGFybW9ueS5TUVVBUkUsXG4gICAgICAgIChjb2xvciwgbW9kZSkgPT4gaGFybW9ueShjb2xvciwgWzkwLCAtOTAsIDE4MF0sIG1vZGUpXG4gICAgXVxuXSk7XG5leHBvcnQgY29uc3QgZ2V0SGFybW9ueVJldHVybiA9IChjb2xvciwgaGFybW9ueSwgbW9kZSwgb3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgY29uc3QgaGFybW9ueUZ1bmN0aW9uID0gSEFSTU9OSUVTLmdldChoYXJtb255KTtcbiAgICBjb25zdCBpc0NTUyA9IGlzU3RyaW5nKGNvbG9yKTtcbiAgICBjb25zdCBwYXJzZXIgPSBjb2xvclBhcnNlckNvbnRleHQuZ2V0UGFyc2VyKGNvbG9yKTtcbiAgICBjb25zdCBtb2RlbCA9IHBhcnNlci5tb2RlbDtcbiAgICBjb25zdCB3aXRoQWxwaGEgPSBwYXJzZXIuaGFzQWxwaGEoY29sb3IpO1xuICAgIGNvbnN0IGhzbCA9IGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KGNvbG9yLCBDb2xvck1vZGVsLkhTTCk7XG4gICAgY29uc3QgYXJyYXkgPSBoYXJtb255RnVuY3Rpb24oaHNsLCBtb2RlKTtcbiAgICBpZiAoaXNDU1MpIHtcbiAgICAgICAgcmV0dXJuIGFycmF5Lm1hcCgoaGFybW9ueUNvbG9yKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1MoaGFybW9ueUNvbG9yLCBtb2RlbCwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSwgd2l0aEFscGhhKTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBhcnJheS5tYXAoKGhhcm1vbnlDb2xvcikgPT4ge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoaGFybW9ueUNvbG9yLCBtb2RlbCwgb3B0aW9ucy5kZWNpbWFscywgd2l0aEFscGhhKTtcbiAgICB9KTtcbn07XG5leHBvcnQgY29uc3QgZ2V0SGFybW9ueVJldHVyblBhcmFtZXRlcnMgPSAoc2Vjb25kUGFyYW0sIHRoaXJkUGFyYW0sIGZvdXJ0aFBhcmFtKSA9PiB7XG4gICAgaWYgKGlzSGFybW9ueShzZWNvbmRQYXJhbSkpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIHNlY29uZFBhcmFtLFxuICAgICAgICAgICAgaXNNaXgodGhpcmRQYXJhbSlcbiAgICAgICAgICAgICAgICA/IHRoaXJkUGFyYW1cbiAgICAgICAgICAgICAgICA6IE1peC5BRERJVElWRSxcbiAgICAgICAgICAgIGlzTWl4KHRoaXJkUGFyYW0pXG4gICAgICAgICAgICAgICAgPyBmb3VydGhQYXJhbVxuICAgICAgICAgICAgICAgIDogdGhpcmRQYXJhbVxuICAgICAgICBdO1xuICAgIH1cbiAgICBpZiAoaXNNaXgoc2Vjb25kUGFyYW0pKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBIYXJtb255LkNPTVBMRU1FTlRBUlksXG4gICAgICAgICAgICBzZWNvbmRQYXJhbSxcbiAgICAgICAgICAgIHRoaXJkUGFyYW1cbiAgICAgICAgXTtcbiAgICB9XG4gICAgcmV0dXJuIFtcbiAgICAgICAgSGFybW9ueS5DT01QTEVNRU5UQVJZLFxuICAgICAgICBNaXguQURESVRJVkUsXG4gICAgICAgIHNlY29uZFBhcmFtXG4gICAgXTtcbn07XG4iLCJpbXBvcnQgeyBCQVNFXzI1NSwgQ29sb3JNb2RlbCwgTUFYX0FMUEhBLCBNQVhfTEFCLCBNQVhfTENIX0MsIE1BWF9QQ0VOVCwgTWl4IH0gZnJvbSAnI2NvbnN0YW50cyc7XG5pbXBvcnQgeyBjbXlrVG9SZ2IsIGhzbFRvUmdiLCBod2JUb1JnYiwgbGFiVG9MY2gsIGxhYlRvUmdiLCBsY2hUb0xhYiwgbGNoVG9SZ2IsIHJnYlRvQ215aywgcmdiVG9Ic2wsIHJnYlRvSHdiLCByZ2JUb0xhYiwgcmdiVG9MY2ggfSBmcm9tICcjY29sb3IvdHJhbnNsYXRvcnMnO1xuaW1wb3J0IHsgZ2V0Q29sb3JNb2RlbCwgbWlubWF4LCBub3JtYWxpemVIdWUsIHJvdW5kIH0gZnJvbSAnI3V0aWxpdGllcyc7XG5pbXBvcnQgeyBjb2xvclBhcnNlckNvbnRleHQsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dCB9IGZyb20gJyNwYXJzZXJzJztcbmltcG9ydCB7IGdldEJsZW5kUmV0dXJuLCBnZXRCbGVuZFJldHVyblBhcmFtcywgZ2V0TWl4UmV0dXJuLCBnZXRNaXhSZXR1cm5QYXJhbWV0ZXJzLCBnZXRTaGFkZXNPclRpbnRzUmV0dXJuLCBnZXRTaGFkZXNPclRpbnRzUmV0dXJuUGFyYW1ldGVycywgZ2V0SGFybW9ueVJldHVybiwgZ2V0SGFybW9ueVJldHVyblBhcmFtZXRlcnMgfSBmcm9tICcjcmV0dXJucyc7XG5leHBvcnQgY2xhc3MgQ29sb3JUcmFuc2xhdG9yIHtcbiAgICBjb25zdHJ1Y3Rvcihjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHRoaXMuX29wdGlvbnMgPSBnZXRPcHRpb25zRnJvbUNvbG9ySW5wdXQob3B0aW9ucywgY29sb3IpO1xuICAgICAgICBjb25zdCBwYXJzZWRDb2xvciA9IGNvbG9yUGFyc2VyQ29udGV4dC5wYXJzZShjb2xvcik7XG4gICAgICAgIGNvbnN0IG1vZGVsID0gZ2V0Q29sb3JNb2RlbChwYXJzZWRDb2xvcik7XG4gICAgICAgIHN3aXRjaCAobW9kZWwpIHtcbiAgICAgICAgICAgIGNhc2UgQ29sb3JNb2RlbC5IU0w6XG4gICAgICAgICAgICAgICAgdGhpcy5oc2wgPSBwYXJzZWRDb2xvcjtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSgnaHNsJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIENvbG9yTW9kZWwuSFdCOlxuICAgICAgICAgICAgICAgIHRoaXMuaHdiID0gcGFyc2VkQ29sb3I7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tSFdCKCk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoJ2h3YicsICdyZ2InKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ29sb3JNb2RlbC5DSUVMYWI6XG4gICAgICAgICAgICAgICAgdGhpcy5sYWIgPSBwYXJzZWRDb2xvcjtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21MQUIoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSgnbGFiJywgJ3JnYicpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBDb2xvck1vZGVsLkxDSDpcbiAgICAgICAgICAgICAgICB0aGlzLmxjaCA9IHBhcnNlZENvbG9yO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUxDSCgpO1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKCdsY2gnLCAncmdiJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIENvbG9yTW9kZWwuQ01ZSzpcbiAgICAgICAgICAgICAgICB0aGlzLmNteWsgPSBwYXJzZWRDb2xvcjtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21DTVlLKCk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoJ2NteWsnLCAncmdiJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHRoaXMucmdiID0gcGFyc2VkQ29sb3I7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHVwZGF0ZSguLi5leGNsdWRlKSB7XG4gICAgICAgIGlmICghZXhjbHVkZS5pbmNsdWRlcygncmdiJykpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlUkdCKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFleGNsdWRlLmluY2x1ZGVzKCdoc2wnKSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVIU0woKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4Y2x1ZGUuaW5jbHVkZXMoJ2h3YicpKSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUhXQigpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghZXhjbHVkZS5pbmNsdWRlcygnbGFiJykpIHtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlTEFCKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFleGNsdWRlLmluY2x1ZGVzKCdsY2gnKSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVMQ0goKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWV4Y2x1ZGUuaW5jbHVkZXMoJ2NteWsnKSkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVDTVlLKCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdXBkYXRlUkdCKCkge1xuICAgICAgICB0aGlzLnJnYiA9IHtcbiAgICAgICAgICAgIC4uLmhzbFRvUmdiKHRoaXMuaHNsLkgsIHRoaXMuaHNsLlMsIHRoaXMuaHNsLkwpLFxuICAgICAgICAgICAgQTogdGhpcy5oc2wuQSA/PyAxXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZUhTTCgpIHtcbiAgICAgICAgdGhpcy5oc2wgPSByZ2JUb0hzbCh0aGlzLnJnYi5SLCB0aGlzLnJnYi5HLCB0aGlzLnJnYi5CLCB0aGlzLnJnYi5BKTtcbiAgICB9XG4gICAgdXBkYXRlSFdCKCkge1xuICAgICAgICB0aGlzLmh3YiA9IHJnYlRvSHdiKHRoaXMucmdiLlIsIHRoaXMucmdiLkcsIHRoaXMucmdiLkIsIHRoaXMucmdiLkEpO1xuICAgIH1cbiAgICB1cGRhdGVMQUIoKSB7XG4gICAgICAgIHRoaXMubGFiID0ge1xuICAgICAgICAgICAgLi4ucmdiVG9MYWIodGhpcy5yZ2IuUiwgdGhpcy5yZ2IuRywgdGhpcy5yZ2IuQiksXG4gICAgICAgICAgICBBOiB0aGlzLnJnYi5BID8/IDFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlTENIKCkge1xuICAgICAgICB0aGlzLmxjaCA9IHtcbiAgICAgICAgICAgIC4uLnJnYlRvTGNoKHRoaXMucmdiLlIsIHRoaXMucmdiLkcsIHRoaXMucmdiLkIpLFxuICAgICAgICAgICAgQTogdGhpcy5yZ2IuQSA/PyAxXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZUNNWUsoKSB7XG4gICAgICAgIHRoaXMuY215ayA9IHtcbiAgICAgICAgICAgIC4uLnJnYlRvQ215ayh0aGlzLnJnYi5SLCB0aGlzLnJnYi5HLCB0aGlzLnJnYi5CKSxcbiAgICAgICAgICAgIEE6IHRoaXMucmdiLkEgPz8gMVxuICAgICAgICB9O1xuICAgIH1cbiAgICB1cGRhdGVSR0JGcm9tSFdCKCkge1xuICAgICAgICB0aGlzLnJnYiA9IHtcbiAgICAgICAgICAgIC4uLmh3YlRvUmdiKHRoaXMuaHdiLkgsIHRoaXMuaHdiLlcsIHRoaXMuaHdiLkIpLFxuICAgICAgICAgICAgQTogdGhpcy5od2I/LkEgPz8gMVxuICAgICAgICB9O1xuICAgIH1cbiAgICB1cGRhdGVSR0JGcm9tTENIKCkge1xuICAgICAgICB0aGlzLnJnYiA9IHtcbiAgICAgICAgICAgIC4uLmxjaFRvUmdiKHRoaXMubGNoLkwsIHRoaXMubGNoLkMsIHRoaXMubGNoLkgpLFxuICAgICAgICAgICAgQTogdGhpcy5sY2guQSA/PyAxXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21DTVlLKCkge1xuICAgICAgICB0aGlzLnJnYiA9IHtcbiAgICAgICAgICAgIC4uLmNteWtUb1JnYih0aGlzLmNteWsuQywgdGhpcy5jbXlrLk0sIHRoaXMuY215ay5ZLCB0aGlzLmNteWsuSyksXG4gICAgICAgICAgICBBOiB0aGlzLmNteWsuQSA/PyAxXG4gICAgICAgIH07XG4gICAgfVxuICAgIHVwZGF0ZVJHQkZyb21MQUIoKSB7XG4gICAgICAgIHRoaXMucmdiID0ge1xuICAgICAgICAgICAgLi4ubGFiVG9SZ2IodGhpcy5sYWIuTCwgdGhpcy5sYWIuYSwgdGhpcy5sYWIuYiksXG4gICAgICAgICAgICBBOiB0aGlzLmxhYi5BID8/IDFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlTENIRnJvbUxBQigpIHtcbiAgICAgICAgdGhpcy5sY2ggPSB7XG4gICAgICAgICAgICAuLi5sYWJUb0xjaCh0aGlzLmxhYi5MLCB0aGlzLmxhYi5hLCB0aGlzLmxhYi5iKSxcbiAgICAgICAgICAgIEE6IHRoaXMubGFiLkFcbiAgICAgICAgfTtcbiAgICB9XG4gICAgdXBkYXRlTEFCcm9tTENIKCkge1xuICAgICAgICB0aGlzLmxhYiA9IHtcbiAgICAgICAgICAgIC4uLmxjaFRvTGFiKHRoaXMubGNoLkwsIHRoaXMubGNoLkMsIHRoaXMubGNoLkgpLFxuICAgICAgICAgICAgQTogdGhpcy5sY2guQVxuICAgICAgICB9O1xuICAgIH1cbiAgICBzZXRPcHRpb25zKG9wdGlvbnMgPSB7fSkge1xuICAgICAgICB0aGlzLl9vcHRpb25zID0ge1xuICAgICAgICAgICAgLi4udGhpcy5fb3B0aW9ucyxcbiAgICAgICAgICAgIC4uLm9wdGlvbnNcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldFIoUikge1xuICAgICAgICB0aGlzLnJnYi5SID0gbWlubWF4KFIsIDAsIEJBU0VfMjU1KTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHNldEcoRykge1xuICAgICAgICB0aGlzLnJnYi5HID0gbWlubWF4KEcsIDAsIEJBU0VfMjU1KTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0QihCKSB7XG4gICAgICAgIHRoaXMucmdiLkIgPSBtaW5tYXgoQiwgMCwgQkFTRV8yNTUpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRIKEgpIHtcbiAgICAgICAgdGhpcy5oc2wuSCA9IG5vcm1hbGl6ZUh1ZShIKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ2hzbCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0UyhTKSB7XG4gICAgICAgIHRoaXMuaHNsLlMgPSBtaW5tYXgoUywgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ2hzbCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0TChMKSB7XG4gICAgICAgIHRoaXMuaHNsLkwgPSBtaW5tYXgoTCwgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ2hzbCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0V2hpdGVuZXNzKFcpIHtcbiAgICAgICAgdGhpcy5od2IuVyA9IG1pbm1heChXLCAwLCBNQVhfUENFTlQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21IV0IoKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ3JnYicsICdod2InKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEJsYWNrbmVzcyhCKSB7XG4gICAgICAgIHRoaXMuaHdiLkIgPSBtaW5tYXgoQiwgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tSFdCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnaHdiJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRDSUVMKEwpIHtcbiAgICAgICAgdGhpcy5sYWIuTCA9IG1pbm1heChMLCAwLCBNQVhfUENFTlQpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21MQUIoKTtcbiAgICAgICAgdGhpcy51cGRhdGVMQ0hGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnbGFiJywgJ2xjaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0Q0lFYShhKSB7XG4gICAgICAgIHRoaXMubGFiLmEgPSBtaW5tYXgoYSwgLU1BWF9MQUIsIE1BWF9MQUIpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21MQUIoKTtcbiAgICAgICAgdGhpcy51cGRhdGVMQ0hGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnbGFiJywgJ2xjaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0Q0lFYihiKSB7XG4gICAgICAgIHRoaXMubGFiLmIgPSBtaW5tYXgoYiwgLU1BWF9MQUIsIE1BWF9MQUIpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21MQUIoKTtcbiAgICAgICAgdGhpcy51cGRhdGVMQ0hGcm9tTEFCKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnbGFiJywgJ2xjaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0TENITChsKSB7XG4gICAgICAgIHRoaXMubGNoLkwgPSBtaW5tYXgobCwgMCwgTUFYX1BDRU5UKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tTENIKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTEFCcm9tTENIKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnbGFiJywgJ2xjaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0TENIQyhjKSB7XG4gICAgICAgIHRoaXMubGNoLkMgPSBtaW5tYXgoYywgMCwgTUFYX0xDSF9DKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tTENIKCk7XG4gICAgICAgIHRoaXMudXBkYXRlTEFCcm9tTENIKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdyZ2InLCAnbGFiJywgJ2xjaCcpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0TENISChoKSB7XG4gICAgICAgIHRoaXMubGNoLkggPSBub3JtYWxpemVIdWUoaCk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZUxBQnJvbUxDSCgpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgncmdiJywgJ2xhYicsICdsY2gnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEEoQSkge1xuICAgICAgICBjb25zdCBhbHBoYSA9IG1pbm1heChBLCAwLCBNQVhfQUxQSEEpO1xuICAgICAgICB0aGlzLnJnYi5BID0gYWxwaGE7XG4gICAgICAgIHRoaXMuaHNsLkEgPSBhbHBoYTtcbiAgICAgICAgdGhpcy5od2IuQSA9IGFscGhhO1xuICAgICAgICB0aGlzLmxhYi5BID0gYWxwaGE7XG4gICAgICAgIHRoaXMubGNoLkEgPSBhbHBoYTtcbiAgICAgICAgdGhpcy5jbXlrLkEgPSBhbHBoYTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEMoQykge1xuICAgICAgICB0aGlzLmNteWsuQyA9IG1pbm1heChDLCAwLCAxMDApO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21DTVlLKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdjbXlrJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBzZXRNKE0pIHtcbiAgICAgICAgdGhpcy5jbXlrLk0gPSBtaW5tYXgoTSwgMCwgMTAwKTtcbiAgICAgICAgdGhpcy51cGRhdGVSR0JGcm9tQ01ZSygpO1xuICAgICAgICB0aGlzLnVwZGF0ZSgnY215aycpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgc2V0WShZKSB7XG4gICAgICAgIHRoaXMuY215ay5ZID0gbWlubWF4KFksIDAsIDEwMCk7XG4gICAgICAgIHRoaXMudXBkYXRlUkdCRnJvbUNNWUsoKTtcbiAgICAgICAgdGhpcy51cGRhdGUoJ2NteWsnKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHNldEsoSykge1xuICAgICAgICB0aGlzLmNteWsuSyA9IG1pbm1heChLLCAwLCAxMDApO1xuICAgICAgICB0aGlzLnVwZGF0ZVJHQkZyb21DTVlLKCk7XG4gICAgICAgIHRoaXMudXBkYXRlKCdjbXlrJyk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgICBnZXQgb3B0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29wdGlvbnM7XG4gICAgfVxuICAgIGdldCBSKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5yZ2IuUiwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEcoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLnJnYi5HLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQigpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMucmdiLkIsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBIKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5oc2wuSCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IFMoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmhzbC5TLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgTCgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuaHNsLkwsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBXaGl0ZW5lc3MoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmh3Yi5XLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQmxhY2tuZXNzKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5od2IuQiwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IENJRUwoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmxhYi5MLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQ0lFYSgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMubGFiLmEsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBDSUViKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5sYWIuYiwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IExDSEwoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmxjaC5MLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgTENIQygpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMubGNoLkMsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBMQ0hIKCkge1xuICAgICAgICByZXR1cm4gcm91bmQodGhpcy5sY2guSCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEEoKSB7XG4gICAgICAgIHJldHVybiByb3VuZCh0aGlzLmhzbC5BLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQygpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuY215ay5DLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgTSgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuY215ay5NLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgWSgpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuY215ay5ZLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgSygpIHtcbiAgICAgICAgcmV0dXJuIHJvdW5kKHRoaXMuY215ay5LLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgSEVYT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQodGhpcy5yZ2IsIENvbG9yTW9kZWwuSEVYKTtcbiAgICB9XG4gICAgZ2V0IEhFWEFPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydCh0aGlzLnJnYiwgQ29sb3JNb2RlbC5IRVgsIDAsIHRydWUpO1xuICAgIH1cbiAgICBnZXQgUkdCT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQodGhpcy5yZ2IsIENvbG9yTW9kZWwuUkdCLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgUkdCQU9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KHRoaXMucmdiLCBDb2xvck1vZGVsLlJHQiwgdGhpcy5vcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgZ2V0IEhTTE9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KHRoaXMuaHNsLCBDb2xvck1vZGVsLkhTTCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IEhTTEFPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydCh0aGlzLmhzbCwgQ29sb3JNb2RlbC5IU0wsIHRoaXMub3B0aW9ucy5kZWNpbWFscywgdHJ1ZSk7XG4gICAgfVxuICAgIGdldCBIV0JPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydCh0aGlzLmh3YiwgQ29sb3JNb2RlbC5IV0IsIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBIV0JBT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQodGhpcy5od2IsIENvbG9yTW9kZWwuSFdCLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMsIHRydWUpO1xuICAgIH1cbiAgICBnZXQgQ0lFTGFiT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQodGhpcy5sYWIsIENvbG9yTW9kZWwuQ0lFTGFiLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBnZXQgQ0lFTGFiQU9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KHRoaXMubGFiLCBDb2xvck1vZGVsLkNJRUxhYiwgdGhpcy5vcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgZ2V0IExDSE9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KHRoaXMubGNoLCBDb2xvck1vZGVsLkxDSCwgdGhpcy5vcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgZ2V0IExDSEFPYmplY3QoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydCh0aGlzLmxjaCwgQ29sb3JNb2RlbC5MQ0gsIHRoaXMub3B0aW9ucy5kZWNpbWFscywgdHJ1ZSk7XG4gICAgfVxuICAgIGdldCBDTVlLT2JqZWN0KCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQodGhpcy5jbXlrLCBDb2xvck1vZGVsLkNNWUssIHRoaXMub3B0aW9ucy5kZWNpbWFscyk7XG4gICAgfVxuICAgIGdldCBDTVlLQU9iamVjdCgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KHRoaXMuY215aywgQ29sb3JNb2RlbC5DTVlLLCB0aGlzLm9wdGlvbnMuZGVjaW1hbHMsIHRydWUpO1xuICAgIH1cbiAgICBnZXQgSEVYKCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1ModGhpcy5yZ2IsIENvbG9yTW9kZWwuSEVYKTtcbiAgICB9XG4gICAgZ2V0IEhFWEEoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLnJnYiwgQ29sb3JNb2RlbC5IRVgsIHt9LCB0cnVlKTtcbiAgICB9XG4gICAgZ2V0IFJHQigpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKHRoaXMucmdiLCBDb2xvck1vZGVsLlJHQiwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IFJHQkEoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLnJnYiwgQ29sb3JNb2RlbC5SR0IsIHRoaXMub3B0aW9ucywgdHJ1ZSk7XG4gICAgfVxuICAgIGdldCBIU0woKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLmhzbCwgQ29sb3JNb2RlbC5IU0wsIHRoaXMub3B0aW9ucyk7XG4gICAgfVxuICAgIGdldCBIU0xBKCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1ModGhpcy5oc2wsIENvbG9yTW9kZWwuSFNMLCB0aGlzLm9wdGlvbnMsIHRydWUpO1xuICAgIH1cbiAgICBnZXQgSFdCKCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1ModGhpcy5od2IsIENvbG9yTW9kZWwuSFdCLCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgSFdCQSgpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKHRoaXMuaHdiLCBDb2xvck1vZGVsLkhXQiwgdGhpcy5vcHRpb25zLCB0cnVlKTtcbiAgICB9XG4gICAgZ2V0IENJRUxhYigpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKHRoaXMubGFiLCBDb2xvck1vZGVsLkNJRUxhYiwgdGhpcy5vcHRpb25zKTtcbiAgICB9XG4gICAgZ2V0IENJRUxhYkEoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLmxhYiwgQ29sb3JNb2RlbC5DSUVMYWIsIHRoaXMub3B0aW9ucywgdHJ1ZSk7XG4gICAgfVxuICAgIGdldCBMQ0goKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLmxjaCwgQ29sb3JNb2RlbC5MQ0gsIHRoaXMub3B0aW9ucyk7XG4gICAgfVxuICAgIGdldCBMQ0hBKCkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1ModGhpcy5sY2gsIENvbG9yTW9kZWwuTENILCB0aGlzLm9wdGlvbnMsIHRydWUpO1xuICAgIH1cbiAgICBnZXQgQ01ZSygpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKHRoaXMuY215aywgQ29sb3JNb2RlbC5DTVlLLCB0aGlzLm9wdGlvbnMpO1xuICAgIH1cbiAgICBnZXQgQ01ZS0EoKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyh0aGlzLmNteWssIENvbG9yTW9kZWwuQ01ZSywgdGhpcy5vcHRpb25zLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSEVYT2JqZWN0KGNvbG9yKSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydChjb2xvciwgQ29sb3JNb2RlbC5IRVgpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IRVgoY29sb3IpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkhFWCk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hFWEFPYmplY3QoY29sb3IpIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KGNvbG9yLCBDb2xvck1vZGVsLkhFWCwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSEVYQShjb2xvcikge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1MoY29sb3IsIENvbG9yTW9kZWwuSEVYLCB1bmRlZmluZWQsIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9SR0JPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuUkdCLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgc3RhdGljIHRvUkdCKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLlJHQiwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b1JHQkFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuUkdCLCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvUkdCQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhjb2xvciwgQ29sb3JNb2RlbC5SR0IsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvciksIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IU0xPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuSFNMLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFNMKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkhTTCwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hTTEFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuSFNMLCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFNMQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhjb2xvciwgQ29sb3JNb2RlbC5IU0wsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvciksIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9IV0JPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuSFdCLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFdCKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkhXQiwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0hXQkFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuSFdCLCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvSFdCQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhjb2xvciwgQ29sb3JNb2RlbC5IV0IsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvciksIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DSUVMYWJPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuQ0lFTGFiLCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ0lFTGFiKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkNJRUxhYiwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0NJRUxhYkFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuQ0lFTGFiLCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ0lFTGFiQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhjb2xvciwgQ29sb3JNb2RlbC5DSUVMYWIsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvciksIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9MQ0hPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuTENILCBvcHRpb25zLmRlY2ltYWxzKTtcbiAgICB9XG4gICAgc3RhdGljIHRvTENIKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkxDSCwgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSk7XG4gICAgfVxuICAgIHN0YXRpYyB0b0xDSEFPYmplY3QoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnQoY29sb3IsIENvbG9yTW9kZWwuTENILCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvTENIQShjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydENTUyhjb2xvciwgQ29sb3JNb2RlbC5MQ0gsIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvciksIHRydWUpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DTVlLT2JqZWN0KGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0KGNvbG9yLCBDb2xvck1vZGVsLkNNWUssIG9wdGlvbnMuZGVjaW1hbHMpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DTVlLKGNvbG9yLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgcmV0dXJuIGNvbG9yUGFyc2VyQ29udGV4dC5jb252ZXJ0Q1NTKGNvbG9yLCBDb2xvck1vZGVsLkNNWUssIGdldE9wdGlvbnNGcm9tQ29sb3JJbnB1dChvcHRpb25zLCBjb2xvcikpO1xuICAgIH1cbiAgICBzdGF0aWMgdG9DTVlLQU9iamVjdChjb2xvciwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIHJldHVybiBjb2xvclBhcnNlckNvbnRleHQuY29udmVydChjb2xvciwgQ29sb3JNb2RlbC5DTVlLLCBvcHRpb25zLmRlY2ltYWxzLCB0cnVlKTtcbiAgICB9XG4gICAgc3RhdGljIHRvQ01ZS0EoY29sb3IsIG9wdGlvbnMgPSB7fSkge1xuICAgICAgICByZXR1cm4gY29sb3JQYXJzZXJDb250ZXh0LmNvbnZlcnRDU1MoY29sb3IsIENvbG9yTW9kZWwuQ01ZSywgZ2V0T3B0aW9uc0Zyb21Db2xvcklucHV0KG9wdGlvbnMsIGNvbG9yKSwgdHJ1ZSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhFWE9iamVjdChmcm9tLCB0bywgc3RlcHMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhFWCwgZmFsc2UsIGZhbHNlLCBzdGVwcyk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhFWChmcm9tLCB0bywgc3RlcHMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhFWCwgdHJ1ZSwgZmFsc2UsIHN0ZXBzKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSEVYQU9iamVjdChmcm9tLCB0bywgc3RlcHMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhFWCwgZmFsc2UsIHRydWUsIHN0ZXBzKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEJsZW5kSEVYQShmcm9tLCB0bywgc3RlcHMpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhFWCwgdHJ1ZSwgdHJ1ZSwgc3RlcHMpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRSR0JPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLlJHQiwgZmFsc2UsIGZhbHNlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZFJHQihmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIENvbG9yTW9kZWwuUkdCLCB0cnVlLCBmYWxzZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRSR0JBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgQ29sb3JNb2RlbC5SR0IsIGZhbHNlLCB0cnVlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZFJHQkEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLlJHQiwgdHJ1ZSwgdHJ1ZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIU0xPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhTTCwgZmFsc2UsIGZhbHNlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhTTChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIENvbG9yTW9kZWwuSFNMLCB0cnVlLCBmYWxzZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIU0xBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgQ29sb3JNb2RlbC5IU0wsIGZhbHNlLCB0cnVlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhTTEEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhTTCwgdHJ1ZSwgdHJ1ZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIV0JPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhXQiwgZmFsc2UsIGZhbHNlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhXQihmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIENvbG9yTW9kZWwuSFdCLCB0cnVlLCBmYWxzZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRIV0JBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgQ29sb3JNb2RlbC5IV0IsIGZhbHNlLCB0cnVlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZEhXQkEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkhXQiwgdHJ1ZSwgdHJ1ZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRDSUVMYWJPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkNJRUxhYiwgZmFsc2UsIGZhbHNlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZENJRUxhYihmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIENvbG9yTW9kZWwuQ0lFTGFiLCB0cnVlLCBmYWxzZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRDSUVMYWJBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgQ29sb3JNb2RlbC5DSUVMYWIsIGZhbHNlLCB0cnVlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZENJRUxhYkEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkNJRUxhYiwgdHJ1ZSwgdHJ1ZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRMQ0hPYmplY3QoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkxDSCwgZmFsc2UsIGZhbHNlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZExDSChmcm9tLCB0bywgdGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0QmxlbmRSZXR1cm4oZnJvbSwgdG8sIENvbG9yTW9kZWwuTENILCB0cnVlLCBmYWxzZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0QmxlbmRMQ0hBT2JqZWN0KGZyb20sIHRvLCB0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRCbGVuZFJldHVybihmcm9tLCB0bywgQ29sb3JNb2RlbC5MQ0gsIGZhbHNlLCB0cnVlLCAuLi5nZXRCbGVuZFJldHVyblBhcmFtcyh0aGlyZFBhcmFtZXRlciwgZm91cnRoUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRCbGVuZExDSEEoZnJvbSwgdG8sIHRoaXJkUGFyYW1ldGVyLCBmb3VydGhQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldEJsZW5kUmV0dXJuKGZyb20sIHRvLCBDb2xvck1vZGVsLkxDSCwgdHJ1ZSwgdHJ1ZSwgLi4uZ2V0QmxlbmRSZXR1cm5QYXJhbXModGhpcmRQYXJhbWV0ZXIsIGZvdXJ0aFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SEVYT2JqZWN0KGNvbG9ycywgbW9kZSkge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IRVgsIGZhbHNlLCBmYWxzZSwgbW9kZSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIRVgoY29sb3JzLCBtb2RlID0gTWl4LkFERElUSVZFKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLkhFWCwgdHJ1ZSwgZmFsc2UsIG1vZGUpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SEVYQU9iamVjdChjb2xvcnMsIG1vZGUgPSBNaXguQURESVRJVkUpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuSEVYLCBmYWxzZSwgdHJ1ZSwgbW9kZSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIRVhBKGNvbG9ycywgbW9kZSA9IE1peC5BRERJVElWRSkge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IRVgsIHRydWUsIHRydWUsIG1vZGUpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4UkdCT2JqZWN0KGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5SR0IsIGZhbHNlLCBmYWxzZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhSR0IoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLlJHQiwgdHJ1ZSwgZmFsc2UsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4UkdCQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuUkdCLCBmYWxzZSwgdHJ1ZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhSR0JBKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5SR0IsIHRydWUsIHRydWUsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFNMT2JqZWN0KGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IU0wsIGZhbHNlLCBmYWxzZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIU0woY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLkhTTCwgdHJ1ZSwgZmFsc2UsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFNMQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuSFNMLCBmYWxzZSwgdHJ1ZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIU0xBKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IU0wsIHRydWUsIHRydWUsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFdCT2JqZWN0KGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IV0IsIGZhbHNlLCBmYWxzZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIV0IoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLkhXQiwgdHJ1ZSwgZmFsc2UsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4SFdCQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuSFdCLCBmYWxzZSwgdHJ1ZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhIV0JBKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5IV0IsIHRydWUsIHRydWUsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4Q0lFTGFiT2JqZWN0KGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5DSUVMYWIsIGZhbHNlLCBmYWxzZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhDSUVMYWIoY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLkNJRUxhYiwgdHJ1ZSwgZmFsc2UsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4Q0lFTGFiQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuQ0lFTGFiLCBmYWxzZSwgdHJ1ZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhDSUVMYWJBKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5DSUVMYWIsIHRydWUsIHRydWUsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4TENIT2JqZWN0KGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5MQ0gsIGZhbHNlLCBmYWxzZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhMQ0goY29sb3JzLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRNaXhSZXR1cm4oY29sb3JzLCBDb2xvck1vZGVsLkxDSCwgdHJ1ZSwgZmFsc2UsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0TWl4TENIQU9iamVjdChjb2xvcnMsIHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGdldE1peFJldHVybihjb2xvcnMsIENvbG9yTW9kZWwuTENILCBmYWxzZSwgdHJ1ZSwgLi4uZ2V0TWl4UmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRNaXhMQ0hBKGNvbG9ycywgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0TWl4UmV0dXJuKGNvbG9ycywgQ29sb3JNb2RlbC5MQ0gsIHRydWUsIHRydWUsIC4uLmdldE1peFJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikpO1xuICAgIH1cbiAgICBzdGF0aWMgZ2V0U2hhZGVzKGNvbG9yLCBzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSB7XG4gICAgICAgIHJldHVybiBnZXRTaGFkZXNPclRpbnRzUmV0dXJuKHRydWUsIGNvbG9yLCAuLi5nZXRTaGFkZXNPclRpbnRzUmV0dXJuUGFyYW1ldGVycyhzZWNvbmRQYXJhbWV0ZXIsIHRoaXJkUGFyYW1ldGVyKSk7XG4gICAgfVxuICAgIHN0YXRpYyBnZXRUaW50cyhjb2xvciwgc2Vjb25kUGFyYW1ldGVyLCB0aGlyZFBhcmFtZXRlcikge1xuICAgICAgICByZXR1cm4gZ2V0U2hhZGVzT3JUaW50c1JldHVybihmYWxzZSwgY29sb3IsIC4uLmdldFNoYWRlc09yVGludHNSZXR1cm5QYXJhbWV0ZXJzKHNlY29uZFBhcmFtZXRlciwgdGhpcmRQYXJhbWV0ZXIpKTtcbiAgICB9XG4gICAgc3RhdGljIGdldEhhcm1vbnkoY29sb3IsIHNlY29uZFBhcmFtLCB0aGlyZFBhcmFtLCBmb3VydGhQYXJhbSkge1xuICAgICAgICByZXR1cm4gZ2V0SGFybW9ueVJldHVybihjb2xvciwgLi4uZ2V0SGFybW9ueVJldHVyblBhcmFtZXRlcnMoc2Vjb25kUGFyYW0sIHRoaXJkUGFyYW0sIGZvdXJ0aFBhcmFtKSk7XG4gICAgfVxufVxuIiwiZXhwb3J0IHsgSGFybW9ueSwgTWl4IH0gZnJvbSAnI2NvbnN0YW50cyc7XG5leHBvcnQgeyBDb2xvclRyYW5zbGF0b3IgfSBmcm9tICcjY2xhc3Nlcy9Db2xvclRyYW5zbGF0b3InO1xuIiwiaW1wb3J0ICcuL3N0eWxlcy5zY3NzJztcblxuZXhwb3J0IGRlZmF1bHQgKENvbG9yVHJhbnNsYXRvcikgPT4ge1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgY29uc3QgY29sb3IgPSBuZXcgQ29sb3JUcmFuc2xhdG9yKCdoc2woMTgwIDEwMCUgNTAlKScsIHsgZGVjaW1hbHM6IDAgfSk7XG5cbiAgICBmb3IgKGxldCByb3cgPSAwOyByb3cgPCAxMDsgcm93KyspIHtcblxuICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCAxMDsgY29sKyspIHtcblxuICAgICAgICAgICAgY29sb3JcbiAgICAgICAgICAgICAgICAuc2V0Uyhyb3cgKiAxMClcbiAgICAgICAgICAgICAgICAuc2V0TChjb2wgKiA1ICsgMzApO1xuXG4gICAgICAgICAgICBjb25zdCBib3ggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ2JveCcpO1xuICAgICAgICAgICAgYm94LnN0eWxlLmJhY2tncm91bmQgPSBjb2xvci5IRVg7XG5cbiAgICAgICAgICAgIGJveC5pbm5lclRleHQgPVxuICAgICAgICAgICAgICAgIGBSOiR7Y29sb3IuUn1cbiAgICAgICAgICAgICAgICAgRzoke2NvbG9yLkd9XG4gICAgICAgICAgICAgICAgIEI6JHtjb2xvci5CfWA7XG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm94KTtcblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCBjb2xvciA9IG5ldyBDb2xvclRyYW5zbGF0b3IoeyBSOiAyNTUsIEc6IDAsIEI6IDAgfSk7XG4gICAgY29uc3QgaHVlID0gWzAsIDMwLCA2MCwgMTIwLCAyNDAsIDI4MCwgMzIwLCAwXTtcbiAgICBsZXQgcmFpbmJvdztcblxuICAgIGZvciAobGV0IHIgPSAwOyByIDwgaHVlLmxlbmd0aDsgcisrKSB7XG5cbiAgICAgICAgY29sb3Iuc2V0SChodWVbcl0pO1xuXG4gICAgICAgIGNvbnN0IGJvdyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgICAgIGJvdy5jbGFzc0xpc3QuYWRkKCdyYWluYm93Jyk7XG4gICAgICAgIGJvdy5zdHlsZS5iYWNrZ3JvdW5kID0gY29sb3IuSEVYO1xuXG4gICAgICAgIGlmIChyYWluYm93KSB7XG4gICAgICAgICAgICByYWluYm93LmFwcGVuZENoaWxkKGJvdyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm93KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJhaW5ib3cgPSBib3c7XG4gICAgfVxuXG4gICAgcmFpbmJvdy5zdHlsZS5iYWNrZ3JvdW5kID0gJyMzMzMnO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCBoc2wgPSB7IEg6IDAsIFM6ICc5MCUnLCBMOiAnNTAlJyB9O1xuICAgIGNvbnN0IGh1ZSA9IFt1bmRlZmluZWQsIDU1LCAzMCwgMCwgMjkwLCAyMjAsIDEzMF07XG4gICAgY29uc3QgdG90YWwgPSBodWUubGVuZ3RoO1xuXG4gICAgZm9yIChsZXQgcm93ID0gMDsgcm93IDwgdG90YWw7IHJvdysrKSB7XG5cbiAgICAgICAgZm9yIChsZXQgY29sID0gMDsgY29sIDwgdG90YWw7IGNvbCsrKSB7XG5cbiAgICAgICAgICAgIGxldCBpbmRleCA9IHRvdGFsIC0gcm93ICsgY29sO1xuICAgICAgICAgICAgaWYgKGluZGV4ID49IHRvdGFsKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggLT0gdG90YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBoc2wuSCA9IGh1ZVtpbmRleF07XG4gICAgICAgICAgICBjb25zdCByZ2IgPSBodWVbaW5kZXhdID09PSB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICA/ICcjRkZGJ1xuICAgICAgICAgICAgICAgIDogQ29sb3JUcmFuc2xhdG9yLnRvSEVYKGhzbCk7XG4gICAgICAgICAgICBjb25zdCBib3ggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ2ZsYWcnKTtcbiAgICAgICAgICAgIGJveC5zdHlsZS5iYWNrZ3JvdW5kID0gcmdiO1xuXG4gICAgICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoYm94KTtcblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCBoZXhDb2xvcnMgPSBbXG4gICAgICAgICcjRkUyNzEyJywgJyNGRTU0MDknLCAnI0ZCOTkwMicsXG4gICAgICAgICcjRkFCRDAzJywgJyNGRkZFMzInLCAnI0QxRUEyQycsXG4gICAgICAgICcjNjZCMTMyJywgJyMwMzkyQ0UnLCAnIzAyNDdGRScsXG4gICAgICAgICcjM0QwMEE1JywgJyM4NjAxQjAnLCAnI0E3MTk0QidcbiAgICBdO1xuXG4gICAgaGV4Q29sb3JzLmZvckVhY2goKGNvbG9yKSA9PiB7XG5cbiAgICAgICAgY29uc3QgcmdiID0gQ29sb3JUcmFuc2xhdG9yLnRvUkdCKGNvbG9yKTtcbiAgICAgICAgY29uc3QgaHNsID0gQ29sb3JUcmFuc2xhdG9yLnRvSFNMKGNvbG9yLCB7IGRlY2ltYWxzOiAwIH0pO1xuICAgICAgICBjb25zdCBod2IgPSBDb2xvclRyYW5zbGF0b3IudG9IV0IoY29sb3IsIHsgZGVjaW1hbHM6IDAgfSk7XG4gICAgICAgIGNvbnN0IGxhYiA9IENvbG9yVHJhbnNsYXRvci50b0NJRUxhYihjb2xvciwgeyBkZWNpbWFsczogMCB9KTtcbiAgICAgICAgY29uc3QgbGNoID0gQ29sb3JUcmFuc2xhdG9yLnRvTENIKGNvbG9yLCB7IGRlY2ltYWxzOiAwIH0pO1xuXG4gICAgICAgIGNvbnN0IHJnYkRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBjb25zdCBoc2xEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgY29uc3QgaHdiRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGNvbnN0IGxhYkRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBjb25zdCBsY2hEaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgICAgICByZ2JEaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gcmdiO1xuICAgICAgICByZ2JEaXYudGV4dENvbnRlbnQgPSByZ2I7XG5cbiAgICAgICAgaHNsRGl2LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGhzbDtcbiAgICAgICAgaHNsRGl2LnRleHRDb250ZW50ID0gaHNsO1xuXG4gICAgICAgIGh3YkRpdi5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBod2I7XG4gICAgICAgIGh3YkRpdi50ZXh0Q29udGVudCA9IGh3YjtcblxuICAgICAgICBsYWJEaXYuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gbGFiO1xuICAgICAgICBsYWJEaXYudGV4dENvbnRlbnQgPSBsYWI7XG5cbiAgICAgICAgbGNoRGl2LnN0eWxlLmJhY2tncm91bmRDb2xvciA9IGxjaDtcbiAgICAgICAgbGNoRGl2LnRleHRDb250ZW50ID0gbGNoO1xuXG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChyZ2JEaXYpO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQoaHNsRGl2KTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGh3YkRpdik7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChsYWJEaXYpO1xuICAgICAgICBjb250YWluZXIuYXBwZW5kQ2hpbGQobGNoRGl2KTtcblxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yKSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICBjb25zdCBjb2xvcnMgPSBbXG4gICAgICAgICdyZWQnLFxuICAgICAgICAnbGltZScsXG4gICAgICAgICdibHVlJyxcbiAgICAgICAgJ2FxdWEnLFxuICAgICAgICAneWVsbG93JyxcbiAgICAgICAgJ2Z1Y2hzaWEnXG4gICAgXTtcbiAgICBjb25zdCB0b3RhbCA9IGNvbG9ycy5sZW5ndGg7XG5cbiAgICBmb3IgKGxldCByb3cgPSAwOyByb3cgPCB0b3RhbDsgcm93KyspIHtcblxuICAgICAgICBjb25zdCBoc2wgPSBDb2xvclRyYW5zbGF0b3IudG9IU0xPYmplY3QoY29sb3JzW3Jvd10pO1xuICAgICAgICBjb25zdCBzdGVwID0gaHNsLlMgLyAodG90YWwgLSAxKTtcblxuICAgICAgICBmb3IgKGxldCBjb2wgPSAwOyBjb2wgPCB0b3RhbDsgY29sKyspIHtcblxuICAgICAgICAgICAgY29uc3QgcmdiID0gQ29sb3JUcmFuc2xhdG9yLnRvSEVYKGhzbCk7XG4gICAgICAgICAgICBjb25zdCBjbXlrID0gQ29sb3JUcmFuc2xhdG9yLnRvQ01ZS09iamVjdChoc2wsIHsgZGVjaW1hbHM6IDAgfSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGJveCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ2JveCcpO1xuICAgICAgICAgICAgYm94LnN0eWxlLmJhY2tncm91bmQgPSByZ2I7XG4gICAgICAgICAgICBib3guaW5uZXJUZXh0ID0gYEM6JHtjbXlrLkN9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIE06JHtjbXlrLk19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIFk6JHtjbXlrLll9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIEs6JHtjbXlrLkt9YDtcblxuICAgICAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGJveCk7XG5cbiAgICAgICAgICAgIGhzbC5TIC09IHN0ZXA7XG5cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb250YWluZXI7XG5cbn07IiwiaW1wb3J0ICcuL3N0eWxlcy5zY3NzJztcblxuZXhwb3J0IGRlZmF1bHQgKENvbG9yVHJhbnNsYXRvcikgPT4ge1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgY29uc3Qgcm93cyA9IDExO1xuICAgIGNvbnN0IG11bHQgPSAzO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByb3dzOyBpKyspIHtcblxuICAgICAgICBjb25zdCBibGVuZHMgPSBDb2xvclRyYW5zbGF0b3IuZ2V0QmxlbmRIRVgoJyNGMDAnLCAnI0ZGMCcsIG11bHQgKyBpICogbXVsdCk7XG5cbiAgICAgICAgYmxlbmRzLmZvckVhY2goKGJsZW5kLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgYm94ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBib3guY2xhc3NMaXN0LmFkZCgnYm94JywgYGZpbGUke2l9YCk7XG4gICAgICAgICAgICBib3guc3R5bGUuYmFja2dyb3VuZCA9IGJsZW5kO1xuICAgICAgICAgICAgYm94LmlubmVyVGV4dCA9IGluZGV4ICsgMTtcbiAgICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChib3gpO1xuICAgICAgICB9KTtcblxuICAgIH1cblxuICAgIHJldHVybiBjb250YWluZXI7XG5cbn07IiwiaW1wb3J0ICcuL3N0eWxlcy5zY3NzJztcblxuZXhwb3J0IGRlZmF1bHQgKENvbG9yVHJhbnNsYXRvcikgPT4ge1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICBjb25zdCBjb2xvcnMgPSBbJyNGMDAnLCAnI0ZGODAwMCcsICcjRkYwJywgJyMwRjAnLCAnIzAwRicsICcjQTBGJywgJyNGMEEnXTtcblxuICAgIGNvbnN0IGNyZWF0ZUJveCA9IChjb2xvciwgdHlwZSkgPT4ge1xuICAgICAgICBjb25zdCBib3ggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgYm94LmNsYXNzTGlzdC5hZGQoJ2JveCcpO1xuICAgICAgICBib3guc3R5bGUuYmFja2dyb3VuZENvbG9yID0gY29sb3I7XG4gICAgICAgIGlmICh0eXBlKSBib3guZGF0YXNldC50eXBlID0gdHlwZTtcbiAgICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGJveCk7XG4gICAgfTtcblxuICAgIGNvbG9ycy5mb3JFYWNoKChjb2xvcikgPT4ge1xuICAgICAgICBjb25zdCBzaGFkZXMgPSBDb2xvclRyYW5zbGF0b3IuZ2V0U2hhZGVzKGNvbG9yLCAzKS5yZXZlcnNlKCk7XG4gICAgICAgIGNvbnN0IHRpbnRzID0gQ29sb3JUcmFuc2xhdG9yLmdldFRpbnRzKGNvbG9yLCAzKTtcbiAgICAgICAgc2hhZGVzLmZvckVhY2goKHNoYWRlKSA9PiBjcmVhdGVCb3goc2hhZGUsICdzaGFkZScpKTtcbiAgICAgICAgY3JlYXRlQm94KGNvbG9yKTtcbiAgICAgICAgdGludHMuZm9yRWFjaCgodGludCkgPT4gY3JlYXRlQm94KHRpbnQsICd0aW50JykpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5cbmV4cG9ydCBkZWZhdWx0IChDb2xvclRyYW5zbGF0b3IpID0+IHtcblxuICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuXG4gICAgY29uc3QgbWl4ZXMgPSBbXG4gICAgICAgICcjRjAwJyxcbiAgICAgICAgJyMwRjAnLFxuICAgICAgICAnIzAwRicsXG4gICAgICAgIFsxLCAzXSxcbiAgICAgICAgWzEsIDJdLFxuICAgICAgICBbMiwgM10sXG4gICAgICAgIFsxLCAyLCAzXVxuICAgIF07XG5cbiAgICBjb25zdCBmaWxsUGxhbmVzID0gKCkgPT4ge1xuICAgICAgICBjb25zdCBwbGFuZXMgPSBjb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnI3BsYW5lcyBwYXRoJyk7XG4gICAgICAgIHBsYW5lcy5mb3JFYWNoKChwbGFuZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGxldCBjb2xvciA9ICcjQ0NDJztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWl4ZXNbaW5kZXhdID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIGNvbG9yID0gbWl4ZXNbaW5kZXhdO1xuICAgICAgICAgICAgfSBlbHNlIGlmKG1peGVzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbG9ycyA9IG1peGVzW2luZGV4XS5tYXAoKGkpID0+IG1peGVzW2kgLSAxXSk7XG4gICAgICAgICAgICAgICAgY29sb3IgPSBtaXhlc1tpbmRleF0gPSBDb2xvclRyYW5zbGF0b3IuZ2V0TWl4SEVYKGNvbG9ycyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwbGFuZS5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCBjb2xvcik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBmZXRjaCgnaW1hZ2VzL2NvbG9yLW1peGVzLnN2ZycpXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiByZXN1bHQudGV4dCgpKVxuICAgICAgICAudGhlbigoc3ZnQ29kZSkgPT4ge1xuICAgICAgICAgICAgY29udGFpbmVyLmlubmVySFRNTCA9IHN2Z0NvZGU7XG4gICAgICAgICAgICBmaWxsUGxhbmVzKCk7XG4gICAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yLCB7IE1peCB9KSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIGNvbnN0IG1peGVzID0gW1xuICAgICAgICAnI0YwMCcsXG4gICAgICAgICcjRkYwJyxcbiAgICAgICAgJyMwMEYnLFxuICAgICAgICBbMSwgM10sXG4gICAgICAgIFsxLCAyXSxcbiAgICAgICAgWzIsIDNdLFxuICAgICAgICBbMSwgMiwgM11cbiAgICBdO1xuXG4gICAgY29uc3QgZmlsbFBsYW5lcyA9ICgpID0+IHtcbiAgICAgICAgY29uc3QgcGxhbmVzID0gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoJyNwbGFuZXMgcGF0aCcpO1xuICAgICAgICBwbGFuZXMuZm9yRWFjaCgocGxhbmUsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBsZXQgY29sb3IgPSAnI0NDQyc7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1peGVzW2luZGV4XSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBjb2xvciA9IG1peGVzW2luZGV4XTtcbiAgICAgICAgICAgIH0gZWxzZSBpZihtaXhlc1tpbmRleF0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjb2xvcnMgPSBtaXhlc1tpbmRleF0ubWFwKChpKSA9PiBtaXhlc1tpIC0gMV0pO1xuICAgICAgICAgICAgICAgIGNvbG9yID0gbWl4ZXNbaW5kZXhdID0gQ29sb3JUcmFuc2xhdG9yLmdldE1peEhFWChjb2xvcnMsIE1peC5TVUJUUkFDVElWRSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwbGFuZS5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCBjb2xvcik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBmZXRjaCgnaW1hZ2VzL2NvbG9yLW1peGVzLnN2ZycpXG4gICAgICAgIC50aGVuKHJlc3VsdCA9PiByZXN1bHQudGV4dCgpKVxuICAgICAgICAudGhlbigoc3ZnQ29kZSkgPT4ge1xuICAgICAgICAgICAgY29udGFpbmVyLmlubmVySFRNTCA9IHN2Z0NvZGU7XG4gICAgICAgICAgICBmaWxsUGxhbmVzKCk7XG4gICAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yLCB7IEhhcm1vbnkgfSkgPT4ge1xuXG4gICAgY29uc3QgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICBjb25zdCBoYXJtb25pZXMgPSBbXG4gICAgICAgIHsgbGFiZWw6ICdDb21wbGVtZW50YXJ5JywgICAgICAgdmFsdWU6IEhhcm1vbnkuQ09NUExFTUVOVEFSWSB9LFxuICAgICAgICB7IGxhYmVsOiAnU3BsaXQgQ29tcGxlbWVudGFyeScsIHZhbHVlOiBIYXJtb255LlNQTElUX0NPTVBMRU1FTlRBUlkgfSxcbiAgICAgICAgeyBsYWJlbDogJ0FuYWxvZ291cycsICAgICAgICAgICB2YWx1ZTogSGFybW9ueS5BTkFMT0dPVVMgfSxcbiAgICAgICAgeyBsYWJlbDogJ1RyaWFkaWMnLCAgICAgICAgICAgICB2YWx1ZTogSGFybW9ueS5UUklBRElDIH0sXG4gICAgICAgIHsgbGFiZWw6ICdUZXRyYWRpYycsICAgICAgICAgICAgdmFsdWU6IEhhcm1vbnkuVEVUUkFESUMgfSxcbiAgICAgICAgeyBsYWJlbDogJ1NxdWFyZScsICAgICAgICAgICAgICB2YWx1ZTogSGFybW9ueS5TUVVBUkUgfVxuICAgIF07XG5cbiAgICBjb25zdCBiYXNlQ29sb3IgPSAnI0YwMCc7XG5cbiAgICBjb25zdCBjcmVhdGVFbGVtZW50ID0gKGNsYXNzTmFtZSwgcGFyZW50KSA9PiB7XG4gICAgICAgIGNvbnN0IGRpdiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBkaXYuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQoZGl2KTtcbiAgICAgICAgcmV0dXJuIGRpdjtcbiAgICB9O1xuXG4gICAgY29uc3QgY3JlYXRlSGFybW9ueSA9IChpdGVtKSA9PiB7XG5cbiAgICAgICAgY29uc3Qgd3JhcHBlciA9IGNyZWF0ZUVsZW1lbnQoJ3dyYXBwZXInLCBjb250YWluZXIpO1xuICAgICAgICBjb25zdCB3aGVlbCA9IGNyZWF0ZUVsZW1lbnQoJ3doZWVsJywgd3JhcHBlcik7XG4gICAgICAgIGNvbnN0IGhhcm1vbnkgPSBjcmVhdGVFbGVtZW50KCdoYXJtb255Jywgd3JhcHBlcik7XG4gICAgICAgIGNyZWF0ZUVsZW1lbnQoJ2xhYmVsJywgd3JhcHBlcikuaW5uZXJUZXh0ID0gaXRlbS5sYWJlbDtcblxuICAgICAgICBmZXRjaCgnaW1hZ2VzL3doZWVsLWFkZGl0aXZlLnN2ZycpXG4gICAgICAgICAgICAudGhlbihyZXN1bHQgPT4gcmVzdWx0LnRleHQoKSlcbiAgICAgICAgICAgIC50aGVuKChzdmdDb2RlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgaGFybW9ueUNvbG9ycyA9IENvbG9yVHJhbnNsYXRvci5nZXRIYXJtb255KGJhc2VDb2xvciwgaXRlbS52YWx1ZSk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0b3IgPSAncGF0aCcgKyBoYXJtb255Q29sb3JzLm1hcCgoY29sb3IpID0+IGA6bm90KFtmaWxsPVwiJHtjb2xvcn1cIl0pYCkuam9pbignJyk7XG4gICAgICAgICAgICAgICAgd2hlZWwuaW5uZXJIVE1MID0gc3ZnQ29kZTtcbiAgICAgICAgICAgICAgICBoYXJtb255Q29sb3JzLmZvckVhY2goKGhleCkgPT4gY3JlYXRlRWxlbWVudCgnYm94JywgaGFybW9ueSkuc3R5bGUuYmFja2dyb3VuZCA9IGhleCk7XG4gICAgICAgICAgICAgICAgd2hlZWwucXVlcnlTZWxlY3RvckFsbChzZWxlY3RvcikuZm9yRWFjaCgocGF0aCkgPT4gcGF0aC5zZXRBdHRyaWJ1dGUoJ2ZpbGwtb3BhY2l0eScsICcwLjI1JykpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICB9O1xuXG4gICAgaGFybW9uaWVzLmZvckVhY2goKGl0ZW0pID0+IGNyZWF0ZUhhcm1vbnkoaXRlbSkpO1xuXG4gICAgcmV0dXJuIGNvbnRhaW5lcjtcblxufTsiLCJpbXBvcnQgJy4vc3R5bGVzLnNjc3MnO1xuXG5leHBvcnQgZGVmYXVsdCAoQ29sb3JUcmFuc2xhdG9yLCB7IEhhcm1vbnksIE1peCB9KSA9PiB7XG5cbiAgICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuICAgIGNvbnN0IGhhcm1vbmllcyA9IFtcbiAgICAgICAgeyBsYWJlbDogJ0NvbXBsZW1lbnRhcnknLCAgICAgICB2YWx1ZTogSGFybW9ueS5DT01QTEVNRU5UQVJZIH0sXG4gICAgICAgIHsgbGFiZWw6ICdTcGxpdCBDb21wbGVtZW50YXJ5JywgdmFsdWU6IEhhcm1vbnkuU1BMSVRfQ09NUExFTUVOVEFSWSB9LFxuICAgICAgICB7IGxhYmVsOiAnQW5hbG9nb3VzJywgICAgICAgICAgIHZhbHVlOiBIYXJtb255LkFOQUxPR09VUyB9LFxuICAgICAgICB7IGxhYmVsOiAnVHJpYWRpYycsICAgICAgICAgICAgIHZhbHVlOiBIYXJtb255LlRSSUFESUMgfSxcbiAgICAgICAgeyBsYWJlbDogJ1RldHJhZGljJywgICAgICAgICAgICB2YWx1ZTogSGFybW9ueS5URVRSQURJQyB9LFxuICAgICAgICB7IGxhYmVsOiAnU3F1YXJlJywgICAgICAgICAgICAgIHZhbHVlOiBIYXJtb255LlNRVUFSRSB9XG4gICAgXTtcblxuICAgIGNvbnN0IGJhc2VDb2xvciA9ICcjRjAwJztcblxuICAgIGNvbnN0IGNyZWF0ZUVsZW1lbnQgPSAoY2xhc3NOYW1lLCBwYXJlbnQpID0+IHtcbiAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGRpdi5jbGFzc0xpc3QuYWRkKGNsYXNzTmFtZSk7XG4gICAgICAgIHBhcmVudC5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICByZXR1cm4gZGl2O1xuICAgIH07XG5cbiAgICBjb25zdCBjcmVhdGVIYXJtb255ID0gKGl0ZW0pID0+IHtcblxuICAgICAgICBjb25zdCB3cmFwcGVyID0gY3JlYXRlRWxlbWVudCgnd3JhcHBlcicsIGNvbnRhaW5lcik7XG4gICAgICAgIGNvbnN0IHdoZWVsID0gY3JlYXRlRWxlbWVudCgnd2hlZWwnLCB3cmFwcGVyKTtcbiAgICAgICAgY29uc3QgaGFybW9ueSA9IGNyZWF0ZUVsZW1lbnQoJ2hhcm1vbnknLCB3cmFwcGVyKTtcbiAgICAgICAgY3JlYXRlRWxlbWVudCgnbGFiZWwnLCB3cmFwcGVyKS5pbm5lclRleHQgPSBpdGVtLmxhYmVsO1xuXG4gICAgICAgIGZldGNoKCdpbWFnZXMvd2hlZWwtc3VidHJhY3RpdmUuc3ZnJylcbiAgICAgICAgICAgIC50aGVuKHJlc3VsdCA9PiByZXN1bHQudGV4dCgpKVxuICAgICAgICAgICAgLnRoZW4oKHN2Z0NvZGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBoYXJtb255Q29sb3JzID0gQ29sb3JUcmFuc2xhdG9yLmdldEhhcm1vbnkoYmFzZUNvbG9yLCBpdGVtLnZhbHVlLCBNaXguU1VCVFJBQ1RJVkUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdG9yID0gJ3BhdGgnICsgaGFybW9ueUNvbG9ycy5tYXAoKGNvbG9yKSA9PiBgOm5vdChbZmlsbD1cIiR7Y29sb3J9XCJdKWApLmpvaW4oJycpO1xuICAgICAgICAgICAgICAgIHdoZWVsLmlubmVySFRNTCA9IHN2Z0NvZGU7XG4gICAgICAgICAgICAgICAgaGFybW9ueUNvbG9ycy5mb3JFYWNoKChoZXgpID0+IGNyZWF0ZUVsZW1lbnQoJ2JveCcsIGhhcm1vbnkpLnN0eWxlLmJhY2tncm91bmQgPSBoZXgpO1xuICAgICAgICAgICAgICAgIHdoZWVsLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpLmZvckVhY2goKHBhdGgpID0+IHBhdGguc2V0QXR0cmlidXRlKCdmaWxsLW9wYWNpdHknLCAnMC4yNScpKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgfTtcblxuICAgIGhhcm1vbmllcy5mb3JFYWNoKChpdGVtKSA9PiBjcmVhdGVIYXJtb255KGl0ZW0pKTtcblxuICAgIHJldHVybiBjb250YWluZXI7XG5cbn07IiwiaW1wb3J0ICcuLi8uLi9ub2RlX21vZHVsZXMvZ29vZ2xlLWNvZGUtcHJldHRpZnkvYmluL3J1bl9wcmV0dGlmeS5taW4nO1xuaW1wb3J0ICcuLi8uLi9ub2RlX21vZHVsZXMvZ29vZ2xlLWNvZGUtcHJldHRpZnkvYmluL3ByZXR0aWZ5Lm1pbi5jc3MnO1xuaW1wb3J0ICcuLi8uLi9ub2RlX21vZHVsZXMvZ29vZ2xlLWNvZGUtcHJldHRpZnkvc3R5bGVzL2Rlc2VydC5jc3MnO1xuaW1wb3J0ICd3aGF0d2ctZmV0Y2gnO1xuaW1wb3J0ICcuL3N0eWxlcy5zY3NzJztcbmltcG9ydCB7IENvbG9yVHJhbnNsYXRvciwgSGFybW9ueSwgTWl4IH0gZnJvbSAnLi4vJztcbmltcG9ydCBkZW1vMSBmcm9tICcuL2RlbW8xJztcbmltcG9ydCBkZW1vMiBmcm9tICcuL2RlbW8yJztcbmltcG9ydCBkZW1vMyBmcm9tICcuL2RlbW8zJztcbmltcG9ydCBkZW1vNCBmcm9tICcuL2RlbW80JztcbmltcG9ydCBkZW1vNSBmcm9tICcuL2RlbW81JztcbmltcG9ydCBkZW1vNiBmcm9tICcuL2RlbW82JztcbmltcG9ydCBkZW1vNyBmcm9tICcuL2RlbW83JztcbmltcG9ydCBkZW1vOCBmcm9tICcuL2RlbW84JztcbmltcG9ydCBkZW1vOSBmcm9tICcuL2RlbW85JztcbmltcG9ydCBkZW1vMTAgZnJvbSAnLi9kZW1vMTAnO1xuaW1wb3J0IGRlbW8xMSBmcm9tICcuL2RlbW8xMSc7XG5cbmNvbnN0IGZ1bmN0aW9Ub1N0cmluZyA9IChmbikgPT4ge1xuICAgIGNvbnN0IGFydGljbGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhcnRpY2xlJyk7XG4gICAgY29uc3QgcHJlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgncHJlJyk7XG4gICAgYXJ0aWNsZS5jbGFzc0xpc3QuYWRkKCdmdW5jdGlvbi1jb250YWluZXInKTtcbiAgICBwcmUuY2xhc3NMaXN0LmFkZCgncHJldHR5cHJpbnQnKTtcbiAgICBhcnRpY2xlLmFwcGVuZENoaWxkKHByZSk7XG4gICAgcHJlLmlubmVySFRNTCA9IGZuLnRvU3RyaW5nKCkucmVwbGFjZSgnKENvbG9yVHJhbnNsYXRvciknLCAnKCknKTtcbiAgICByZXR1cm4gYXJ0aWNsZTtcbn07XG5cbmNvbnN0IGRlbW9zID0gbmV3IE1hcChbXG4gICAgWydkZW1vMScsIGRlbW8xXSxcbiAgICBbJ2RlbW8yJywgZGVtbzJdLFxuICAgIFsnZGVtbzMnLCBkZW1vM10sXG4gICAgWydkZW1vNCcsIGRlbW80XSxcbiAgICBbJ2RlbW81JywgZGVtbzVdLFxuICAgIFsnZGVtbzYnLCBkZW1vNl0sXG4gICAgWydkZW1vNycsIGRlbW83XSxcbiAgICBbJ2RlbW84JywgZGVtbzhdLFxuICAgIFsnZGVtbzknLCBkZW1vOV0sXG4gICAgWydkZW1vMTAnLCBkZW1vMTBdLFxuICAgIFsnZGVtbzExJywgZGVtbzExXVxuXSk7XG5cbmRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ0RPTUNvbnRlbnRMb2FkZWQnLCAoKSA9PiB7XG4gICAgZGVtb3MuZm9yRWFjaCgobW9kdWxlLCBkaXYpID0+IHtcbiAgICAgICAgY29uc3QgZGVtbyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGRpdik7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgICAgICBjb25zdCB3cmFwcGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG5cbiAgICAgICAgY29udGFpbmVyLmNsYXNzTGlzdC5hZGQoJ2RlbW8tY29udGFpbmVyJyk7XG4gICAgICAgIHdyYXBwZXIuY2xhc3NMaXN0LmFkZCgnZGVtby13cmFwcGVyJyk7XG5cbiAgICAgICAgd3JhcHBlci5hcHBlbmRDaGlsZChtb2R1bGUoQ29sb3JUcmFuc2xhdG9yLCB7IEhhcm1vbnksIE1peCB9KSk7XG4gICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh3cmFwcGVyKTtcbiAgICAgICAgZGVtby5hcHBlbmRDaGlsZChjb250YWluZXIpO1xuICAgICAgICBkZW1vLmFwcGVuZENoaWxkKGZ1bmN0aW9Ub1N0cmluZyhtb2R1bGUpKTtcbiAgICB9KTtcbn0pOyJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///117\n\n}")}},__webpack_module_cache__={};function __webpack_require__(I){var g=__webpack_module_cache__[I];if(void 0!==g)return g.exports;var C=__webpack_module_cache__[I]={exports:{}};return __webpack_modules__[I](C,C.exports,__webpack_require__),C.exports}__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(I){if("object"==typeof window)return window}}();var __webpack_exports__=__webpack_require__(117),__webpack_export_target__=window;for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__]=__webpack_exports__[__webpack_i__];__webpack_exports__.__esModule&&Object.defineProperty(__webpack_export_target__,"__esModule",{value:!0})})(); \ No newline at end of file diff --git a/package.json b/package.json index 144f0c3..61ed953 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "scripts": { "test:ts": "tsc --noEmit", "test": "jest --verbose", + "test:tag": "jest -t @testing", "lint": "eslint \"src/**/*.{js,ts}\" \"tests/**/*.ts\"", "clean": "./scripts/clean.sh", "finish": "./scripts/finish.sh", diff --git a/src/@types/index.ts b/src/@types/index.ts index 8765277..3802cc3 100644 --- a/src/@types/index.ts +++ b/src/@types/index.ts @@ -104,6 +104,15 @@ export interface RYBObject { export type RGYBObject = RGBObject | RYBObject; +export type ColorObject = + | HEXObject + | RGBObject + | HSLObject + | HWBObject + | CIELabObject + | LCHObject + | CMYKObject; + export type Color = | RGBObjectGeneric | HSLObjectGeneric @@ -302,4 +311,6 @@ export type MatchOptions = { [K in keyof Pick]: number; }; -export type ParserGetRgbObject = (color: string) => RGBObject; \ No newline at end of file +export interface CSSOptionsBase { + hasAlpha: boolean; +} diff --git a/src/classes/CIELabParser.ts b/src/classes/CIELabParser.ts new file mode 100644 index 0000000..00fba7c --- /dev/null +++ b/src/classes/CIELabParser.ts @@ -0,0 +1,252 @@ +import { + CIELabObject, + CIELabObjectGeneric, + CIELabRegExpMatchArray, + ColorInput, + ColorObject, + ColorUnitEnum, + CSSOptionsBase, + NumberOrString, + Options +} from '@types'; +import { + ColorModel, + COLORREGS, + MAX_ALPHA, + MAX_LAB, + MAX_PCENT, + PCENT +} from '#constants'; +import { + from125NumberToPercent, + getBase125Number, + isCIELabObject, + isString, + isUndefined, + minmax, + normalizeAlpha, + percent, + round +} from '#utilities'; +import { + getCSSAlpha, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { rgbToLab } from '#color/translators'; +import { CalcParser } from './CalcParser'; +import { ColorParserContext, ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + hasPercentageValues: boolean; + hasPercentageAlpha: boolean; +} + +export class CIELabParser extends ColorParser { + + private _extract(input: string): CIELabRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.CIELab) as CIELabRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + if (isString(input)) { + return COLORREGS.CIELab.test(input); + } + return isCIELabObject(input); + } + + parse(input: string | CIELabObjectGeneric, context: ColorParserContext): CIELabObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const { + // Lab values + L, + a, + b, + A, + // Relative values + from, + relative_L, + relative_a, + relative_b, + relative_A + } = groups; + + if (from) { + + const fromColor = context.parse(from); + const fromRGB = getRGB(fromColor); + const fromCIELab = rgbToLab( + fromRGB.R, + fromRGB.G, + fromRGB.B + ); + const fromCIELabVars = { + l: fromCIELab.L, + a: fromCIELab.a, + b: fromCIELab.b, + alpha: fromRGB.A ?? 1 + }; + + const L = new CalcParser('l', relative_L, fromCIELabVars).result; + const a = new CalcParser('a', relative_a, fromCIELabVars).result; + const b = new CalcParser('b', relative_b, fromCIELabVars).result; + + const CIELab: CIELabObject = { + L: minmax(L, 0, MAX_PCENT), + a: minmax(a, - MAX_LAB, MAX_LAB), + b: minmax(b, - MAX_LAB, MAX_LAB) + }; + + if (relative_A) { + const A = new CalcParser('alpha', relative_A, fromCIELabVars).result; + CIELab.A = minmax(A, 0, MAX_ALPHA); + } + + return CIELab; + + } else { + + return { + L: percent(L), + a: getBase125Number(a), + b: getBase125Number(b), + ...( + isUndefined(A) + ? {} + : { + A: normalizeAlpha(A) + } + ) + }; + + } + + } + + return { + L: percent(input.L), + a: getBase125Number(`${input.a}`), + b: getBase125Number(`${input.b}`), + ...( + isUndefined(input.A) + ? {} + : { + A: normalizeAlpha(input.A) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): CIELabObject { + let lab: CIELabObject; + if (isCIELabObject(color)) { + lab = color as CIELabObject; + } else { + const rgb = getRGB(color); + lab = rgbToLab( + rgb.R, + rgb.G, + rgb.B + ); + } + return this._roundCIELabObject( + { + L: lab.L, + a: lab.a, + b: lab.b, + ...( + withAlpha + ? { + A: +(color.A ?? 1) + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const { + decimals, + labUnit + } = options; + const lab = this.convert(color, options.decimals, withAlpha); + const transformer = (value: number, index: number): NumberOrString => { + if (index === 0) { + const L = round( + percent(value), + decimals + ); + return labUnit === ColorUnitEnum.PERCENT + ? `${L}%` + : `${L}`; + } + if (index < 3) { + return labUnit === ColorUnitEnum.PERCENT + ? `${from125NumberToPercent(value, decimals)}%` + : round(value, decimals); + } + return getCSSAlpha(value, options, true); + }; + const values = prepareColorForCss(lab, transformer); + const template = values.length === 4 + ? `lab({1} {2} {3} / {4})` + : `lab({1} {2} {3})`; + return getResultFromCSSTemplate(template, values); + } + + private _roundCIELabObject(color: CIELabObject, decimals: number): CIELabObject { + return { + L: round(color.L, decimals), + a: round(color.a, decimals), + b: round(color.b, decimals), + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + const { + L, + a, + b, + A + } = groups; + return { + hasPercentageValues: ( + PCENT.test(L) && + PCENT.test(a) && + PCENT.test(b) + ), + hasPercentageAlpha: PCENT.test(A), + hasAlpha: !isUndefined(A) + }; + } + + public get model(): ColorModel { + return ColorModel.CIELab; + } + +} \ No newline at end of file diff --git a/src/classes/CMYKParser.ts b/src/classes/CMYKParser.ts new file mode 100644 index 0000000..93dec17 --- /dev/null +++ b/src/classes/CMYKParser.ts @@ -0,0 +1,235 @@ +import { + CMYKObject, + CMYKObjectGeneric, + CMYKRegExpMatchArray, + ColorInput, + ColorUnitEnum, + ColorObject, + CSSOptionsBase, + NumberOrString, + Options +} from '@types'; +import { + ColorModel, + COLORREGS, + PCENT +} from '#constants'; +import { + getCMYKNumber, + isCMYKObject, + isString, + isUndefined, + normalizeAlpha, + round +} from '#utilities'; +import { + getCSSAlpha, + getCSSComma, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { rgbToCmyk } from '#color/translators'; +import { ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + hasPercentageValues: boolean; + hasPercentageAlpha: boolean; +} + +export class CMYKParser extends ColorParser { + + private _extract(input: string): CMYKRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.CMYK) as CMYKRegExpMatchArray; + return match.groups; + } + + private _shouldMultiplyBy100(...colors: NumberOrString[]): boolean { + return !colors.some((color: string) => +color > 1); + } + + supports(input: ColorInput): boolean { + if (isString(input)) { + return COLORREGS.CMYK.test(input); + } + return isCMYKObject(input); + } + + parse(input: string | CMYKObjectGeneric): CMYKObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const c = groups.c_legacy ?? groups.c; + const m = groups.m_legacy ?? groups.m; + const y = groups.y_legacy ?? groups.y; + const k = groups.k_legacy ?? groups.k; + const a = groups.a_legacy ?? groups.a; + const shouldMultiplyBy100 = this._shouldMultiplyBy100(c, m, y, k); + + return { + C: getCMYKNumber(c, shouldMultiplyBy100), + M: getCMYKNumber(m, shouldMultiplyBy100), + Y: getCMYKNumber(y, shouldMultiplyBy100), + K: getCMYKNumber(k, shouldMultiplyBy100), + ...( + isUndefined(a) + ? {} + : { + A: normalizeAlpha(a) + } + ) + }; + + } + + const shouldMultiplyBy100 = this._shouldMultiplyBy100( + input.C, + input.M, + input.Y, + input.K + ); + + return { + C: getCMYKNumber(`${input.C}`, shouldMultiplyBy100), + M: getCMYKNumber(`${input.M}`, shouldMultiplyBy100), + Y: getCMYKNumber(`${input.Y}`, shouldMultiplyBy100), + K: getCMYKNumber(`${input.K}`, shouldMultiplyBy100), + ...( + isUndefined(input.A) + ? {} + : { + A: normalizeAlpha(input.A) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): CMYKObject { + let cmyk: CMYKObject; + if (isCMYKObject(color)) { + cmyk = color as CMYKObject; + } else { + const rgb = getRGB(color); + cmyk = rgbToCmyk( + rgb.R, + rgb.G, + rgb.B + ); + } + return this._roundCMYKObject( + { + C: cmyk.C, + M: cmyk.M, + Y: cmyk.Y, + K: cmyk.K, + ...( + withAlpha + ? { + A: +(color.A ?? 1) + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const { + decimals, + legacyCSS, + spacesAfterCommas, + cmykUnit, + cmykFunction + } = options; + const comma = getCSSComma(spacesAfterCommas); + const cmyk = this.convert(color, options.decimals, withAlpha); + const transformer = (value: number, index: number): NumberOrString => { + if ( + cmykUnit === ColorUnitEnum.PERCENT && + index < 4 + ) { + return `${round(value, decimals)}%`; + } + return index === 4 + ? getCSSAlpha(value, options) + : round(value / 100, decimals); + }; + const values = prepareColorForCss(cmyk, transformer); + const template = legacyCSS + ? ( + values.length === 5 + ? `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4}${comma}{5})` + : `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4})` + ) + : ( + values.length === 5 + ? `${cmykFunction}({1} {2} {3} {4} / {5})` + : `${cmykFunction}({1} {2} {3} {4})` + ); + return getResultFromCSSTemplate(template, values); + } + + private _roundCMYKObject(color: CMYKObject, decimals: number): CMYKObject { + return { + C: round(color.C, decimals), + M: round(color.M, decimals), + Y: round(color.Y, decimals), + K: round(color.K, decimals), + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + const { + c_legacy, + m_legacy, + y_legacy, + k_legacy, + a_legacy, + c, + m, + y, + k, + a + } = groups; + + return { + hasPercentageValues: ( + PCENT.test(c_legacy ?? c) && + PCENT.test(m_legacy ?? m) && + PCENT.test(y_legacy ?? y) && + PCENT.test(k_legacy ?? k) + ), + hasPercentageAlpha: PCENT.test(a_legacy ?? a), + hasAlpha: !isUndefined(a_legacy ?? a) + }; + } + + /* the getter is here to comply with the abstract class but it is not used for CMYK */ + /* istanbul ignore next */ + public get model(): ColorModel { + /* the getter is here to comply with the abstract class but it is not used for CMYK */ + /* istanbul ignore next */ + return ColorModel.CMYK; + } + +} \ No newline at end of file diff --git a/src/parsers/_CalcParser.ts b/src/classes/CalcParser.ts similarity index 100% rename from src/parsers/_CalcParser.ts rename to src/classes/CalcParser.ts diff --git a/src/classes/ColorParserContext.ts b/src/classes/ColorParserContext.ts new file mode 100644 index 0000000..9a2462f --- /dev/null +++ b/src/classes/ColorParserContext.ts @@ -0,0 +1,72 @@ +import { + ColorInput, + ColorObject, + CSSOptionsBase, + InputOptions +} from '@types'; +import { + ColorModel, + DEFAULT_OPTIONS, + ERRORS +} from '#constants'; +import { isString, isUndefined } from '#utilities'; + +export class ColorParserContext { + + constructor(parsers: Record) { + this._parsers = parsers; + } + + private _parsers: Record; + + getParser(input: ColorInput): ColorParser { + const parser = Object.values(this._parsers).find(parser => parser.supports(input)); + if (parser) { + return parser; + } + throw new Error(ERRORS.NOT_ACCEPTED_INPUT); + } + + parse(input: ColorInput): ColorObject { + const parser = this.getParser(input); + return parser.parse(input, this); + } + + convert( + input: ColorInput, + model: ColorModel, + decimals: number = DEFAULT_OPTIONS.decimals, + withAlpha = false + ): T { + const color = this.parse(input); + const parser = this._parsers[model]; + return parser.convert(color, decimals, withAlpha) as T; + } + + convertCSS( + input: ColorInput, + model: ColorModel, + options: InputOptions = {}, + withAlpha = false + ): string { + const color = this.parse(input); + const parser = this._parsers[model]; + return parser.convertCSS(color, options, withAlpha); + } + +} + +export abstract class ColorParser { + public abstract supports(input: ColorInput): boolean + public abstract parse(input: ColorInput, context: ColorParserContext): ColorObject; + public abstract convert(input: ColorObject, decimals: number, withAlpha: boolean): ColorObject; + public abstract convertCSS(input: ColorObject, options: InputOptions, withAlpha: boolean): string; + public abstract getCSSOptions(input: ColorInput): CSSOptionsBase; + public abstract get model(): ColorModel; + public hasAlpha(input: ColorInput): boolean { + if (isString(input)) { + return this.getCSSOptions(input).hasAlpha; + } + return !isUndefined(input.A); + }; +} \ No newline at end of file diff --git a/src/classes/ColorTranslator.ts b/src/classes/ColorTranslator.ts new file mode 100644 index 0000000..17f35e9 --- /dev/null +++ b/src/classes/ColorTranslator.ts @@ -0,0 +1,2311 @@ +import { + CIELabObject, + CIELabObjectGeneric, + CMYKObject, + ColorInput, + ColorInputWithoutCMYK, + ColorOutput, + HEXObject, + HSLObject, + HSLObjectGeneric, + HWBObject, + HWBObjectGeneric, + InputOptions, + LCHObject, + LCHObjectGeneric, + Options, + RGBObject +} from '@types'; +import { + BASE_255, + ColorModel, + Harmony, + HarmonyString, + MAX_ALPHA, + MAX_LAB, + MAX_LCH_C, + MAX_PCENT, + Mix, + MixString +} from '#constants'; +import { + cmykToRgb, + hslToRgb, + hwbToRgb, + labToLch, + labToRgb, + lchToLab, + lchToRgb, + rgbToCmyk, + rgbToHsl, + rgbToHwb, + rgbToLab, + rgbToLch +} from '#color/translators'; +import { + getColorModel, + minmax, + normalizeHue, + round +} from '#utilities'; +import { colorParserContext, getOptionsFromColorInput } from '#parsers'; +import { + getBlendReturn, + getBlendReturnParams, + getMixReturn, + getMixReturnParameters, + getShadesOrTintsReturn, + getShadesOrTintsReturnParameters, + getHarmonyReturn, + getHarmonyReturnParameters +} from '#returns'; + +export class ColorTranslator { + + // Constructor + public constructor(color: ColorInput, options: InputOptions = {}) { + this._options = getOptionsFromColorInput(options, color); + const parsedColor = colorParserContext.parse(color); + const model = getColorModel(parsedColor); + switch (model) { + case ColorModel.HSL: + this.hsl = parsedColor as HSLObject; + this.update('hsl'); + break; + case ColorModel.HWB: + this.hwb = parsedColor as HWBObject; + this.updateRGBFromHWB(); + this.update('hwb', 'rgb'); + break; + case ColorModel.CIELab: + this.lab = parsedColor as CIELabObject; + this.updateRGBFromLAB(); + this.update('lab', 'rgb'); + break; + case ColorModel.LCH: + this.lch = parsedColor as LCHObject; + this.updateRGBFromLCH(); + this.update('lch', 'rgb'); + break; + case ColorModel.CMYK: + this.cmyk = parsedColor as CMYKObject; + this.updateRGBFromCMYK(); + this.update('cmyk', 'rgb'); + break; + default: + this.rgb = parsedColor as RGBObject; + this.update('rgb'); + } + } + + // Private properties + private _options: Options; + private rgb: RGBObject; + private hsl: HSLObject; + private hwb: HWBObject; + private lab: CIELabObject; + private lch: LCHObject; + private cmyk: CMYKObject; + + // Private methods + private update(...exclude: ('rgb' | 'hsl' | 'hwb' | 'lab' | 'lch' | 'cmyk')[]): void { + if (!exclude.includes('rgb')) { + this.updateRGB(); + } + if (!exclude.includes('hsl')) { + this.updateHSL(); + } + if (!exclude.includes('hwb')) { + this.updateHWB(); + } + if (!exclude.includes('lab')) { + this.updateLAB(); + } + if (!exclude.includes('lch')) { + this.updateLCH(); + } + if (!exclude.includes('cmyk')) { + this.updateCMYK(); + } + } + + private updateRGB(): void { + this.rgb = { + ...hslToRgb( + this.hsl.H, + this.hsl.S, + this.hsl.L + ), + A: this.hsl.A ?? 1 + }; + } + + private updateHSL(): void { + this.hsl = rgbToHsl( + this.rgb.R, + this.rgb.G, + this.rgb.B, + this.rgb.A + ); + } + + private updateHWB(): void { + this.hwb = rgbToHwb( + this.rgb.R, + this.rgb.G, + this.rgb.B, + this.rgb.A + ); + } + + private updateLAB(): void { + this.lab = { + ...rgbToLab( + this.rgb.R, + this.rgb.G, + this.rgb.B + ), + A: this.rgb.A ?? 1 + }; + } + + private updateLCH(): void { + this.lch = { + ...rgbToLch( + this.rgb.R, + this.rgb.G, + this.rgb.B + ), + A: this.rgb.A ?? 1 + }; + } + + private updateCMYK(): void { + this.cmyk = { + ...rgbToCmyk( + this.rgb.R, + this.rgb.G, + this.rgb.B + ), + A: this.rgb.A ?? 1 + }; + } + + private updateRGBFromHWB(): void { + this.rgb = { + ...hwbToRgb( + this.hwb.H, + this.hwb.W, + this.hwb.B + ), + A: this.hwb?.A ?? 1 + }; + } + + private updateRGBFromLCH(): void { + this.rgb = { + ...lchToRgb( + this.lch.L, + this.lch.C, + this.lch.H + ), + A: this.lch.A ?? 1 + }; + } + + private updateRGBFromCMYK(): void { + this.rgb = { + ...cmykToRgb( + this.cmyk.C, + this.cmyk.M, + this.cmyk.Y, + this.cmyk.K + ), + A: this.cmyk.A ?? 1 + }; + } + + private updateRGBFromLAB(): void { + this.rgb = { + ...labToRgb( + this.lab.L, + this.lab.a, + this.lab.b + ), + A: this.lab.A ?? 1 + }; + } + + private updateLCHFromLAB(): void { + this.lch = { + ...labToLch( + this.lab.L, + this.lab.a, + this.lab.b + ), + A: this.lab.A + }; + } + + private updateLABromLCH(): void { + this.lab = { + ...lchToLab( + this.lch.L, + this.lch.C, + this.lch.H + ), + A: this.lch.A + }; + } + + // Public options method + public setOptions(options: InputOptions = {}): ColorTranslator { + this._options = { + ...this._options, + ...options + } as Options; + return this; + } + + // Public RGB methods + public setR(R: number): ColorTranslator { + this.rgb.R = minmax(R, 0, BASE_255); + this.update('rgb'); + return; + } + + public setG(G: number): ColorTranslator { + this.rgb.G = minmax(G, 0, BASE_255); + this.update('rgb'); + return this; + } + + public setB(B: number): ColorTranslator { + this.rgb.B = minmax(B, 0, BASE_255); + this.update('rgb'); + return this; + } + + // Public HSL methods + public setH(H: number): ColorTranslator { + this.hsl.H = normalizeHue(H); + this.update('hsl'); + return this; + } + + public setS(S: number): ColorTranslator { + this.hsl.S = minmax(S, 0, MAX_PCENT); + this.update('hsl'); + return this; + } + + public setL(L: number): ColorTranslator { + this.hsl.L = minmax(L, 0, MAX_PCENT); + this.update('hsl'); + return this; + } + + // Public HWB methods + public setWhiteness(W: number): ColorTranslator { + this.hwb.W = minmax(W, 0, MAX_PCENT); + this.updateRGBFromHWB(); + this.update('rgb', 'hwb'); + return this; + } + + public setBlackness(B: number): ColorTranslator { + this.hwb.B = minmax(B, 0, MAX_PCENT); + this.updateRGBFromHWB(); + this.update('rgb', 'hwb'); + return this; + } + + // Public Lab methods + public setCIEL(L: number): ColorTranslator { + this.lab.L = minmax(L, 0, MAX_PCENT); + this.updateRGBFromLAB(); + this.updateLCHFromLAB(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + public setCIEa(a: number): ColorTranslator { + this.lab.a = minmax(a, -MAX_LAB, MAX_LAB); + this.updateRGBFromLAB(); + this.updateLCHFromLAB(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + public setCIEb(b: number): ColorTranslator { + this.lab.b = minmax(b, -MAX_LAB, MAX_LAB); + this.updateRGBFromLAB(); + this.updateLCHFromLAB(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + // Puclic LCH methods + public setLCHL(l: number): ColorTranslator { + this.lch.L = minmax(l, 0, MAX_PCENT); + this.updateRGBFromLCH(); + this.updateLABromLCH(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + public setLCHC(c: number): ColorTranslator { + this.lch.C = minmax(c, 0, MAX_LCH_C); + this.updateRGBFromLCH(); + this.updateLABromLCH(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + public setLCHH(h: number): ColorTranslator { + this.lch.H = normalizeHue(h); + this.updateRGBFromLCH(); + this.updateLABromLCH(); + this.update('rgb', 'lab', 'lch'); + return this; + } + + // Public alpha method + public setA(A: number): ColorTranslator { + const alpha = minmax(A, 0, MAX_ALPHA); + this.rgb.A = alpha; + this.hsl.A = alpha; + this.hwb.A = alpha; + this.lab.A = alpha; + this.lch.A = alpha; + this.cmyk.A = alpha; + return this; + } + + // Public CMYK methods + public setC(C: number): ColorTranslator { + this.cmyk.C = minmax(C, 0, 100); + this.updateRGBFromCMYK(); + this.update('cmyk'); + return this; + } + + public setM(M: number): ColorTranslator { + this.cmyk.M = minmax(M, 0, 100); + this.updateRGBFromCMYK(); + this.update('cmyk'); + return this; + } + + public setY(Y: number): ColorTranslator { + this.cmyk.Y = minmax(Y, 0, 100); + this.updateRGBFromCMYK(); + this.update('cmyk'); + return this; + } + + public setK(K: number): ColorTranslator { + this.cmyk.K = minmax(K, 0, 100); + this.updateRGBFromCMYK(); + this.update('cmyk'); + return this; + } + + // Public options property + public get options(): Options { + return this._options; + } + + // Public RGB properties + public get R(): number { + return round(this.rgb.R, this.options.decimals); + } + + public get G(): number { + return round(this.rgb.G, this.options.decimals); + } + + public get B(): number { + return round(this.rgb.B, this.options.decimals); + } + + // Public HSL properties + public get H(): number { + return round(this.hsl.H, this.options.decimals); + } + + public get S(): number { + return round(this.hsl.S, this.options.decimals); + } + + public get L(): number { + return round(this.hsl.L, this.options.decimals); + } + + // Public HWB properties + public get Whiteness(): number { + return round(this.hwb.W, this.options.decimals); + } + + public get Blackness(): number { + return round(this.hwb.B, this.options.decimals); + } + + // Public Lab properties + public get CIEL(): number { + return round(this.lab.L, this.options.decimals); + } + + public get CIEa(): number { + return round(this.lab.a, this.options.decimals); + } + + public get CIEb(): number { + return round(this.lab.b, this.options.decimals); + } + + // Pulic LCH properties + public get LCHL(): number { + return round(this.lch.L, this.options.decimals); + } + + public get LCHC(): number { + return round(this.lch.C, this.options.decimals); + } + + public get LCHH(): number { + return round(this.lch.H, this.options.decimals); + } + + // Public alpha property + public get A(): number { + return round(this.hsl.A, this.options.decimals); + } + + // Public CMYK properties + public get C(): number { + return round(this.cmyk.C, this.options.decimals); + } + + public get M(): number { + return round(this.cmyk.M, this.options.decimals); + } + + public get Y(): number { + return round(this.cmyk.Y, this.options.decimals); + } + + public get K(): number { + return round(this.cmyk.K, this.options.decimals); + } + + // Object public properties + public get HEXObject(): HEXObject { + return colorParserContext.convert( + this.rgb, + ColorModel.HEX + ); + } + + public get HEXAObject(): HEXObject { + return colorParserContext.convert( + this.rgb, + ColorModel.HEX, + 0, + true + ); + } + + public get RGBObject(): RGBObject { + return colorParserContext.convert( + this.rgb, + ColorModel.RGB, + this.options.decimals + ); + } + + public get RGBAObject(): RGBObject { + return colorParserContext.convert( + this.rgb, + ColorModel.RGB, + this.options.decimals, + true + ); + } + + public get HSLObject(): HSLObject { + return colorParserContext.convert( + this.hsl, + ColorModel.HSL, + this.options.decimals + ); + } + + public get HSLAObject(): HSLObject { + return colorParserContext.convert( + this.hsl, + ColorModel.HSL, + this.options.decimals, + true + ); + } + + public get HWBObject(): HWBObject { + return colorParserContext.convert( + this.hwb, + ColorModel.HWB, + this.options.decimals + ); + } + + public get HWBAObject(): HWBObject { + return colorParserContext.convert( + this.hwb, + ColorModel.HWB, + this.options.decimals, + true + ); + } + + public get CIELabObject(): CIELabObject { + return colorParserContext.convert( + this.lab, + ColorModel.CIELab, + this.options.decimals + ); + } + + public get CIELabAObject(): CIELabObject { + return colorParserContext.convert( + this.lab, + ColorModel.CIELab, + this.options.decimals, + true + ); + } + + public get LCHObject(): LCHObject { + return colorParserContext.convert( + this.lch, + ColorModel.LCH, + this.options.decimals + ); + } + + public get LCHAObject(): LCHObject { + return colorParserContext.convert( + this.lch, + ColorModel.LCH, + this.options.decimals, + true + ); + } + + public get CMYKObject(): CMYKObject { + return colorParserContext.convert( + this.cmyk, + ColorModel.CMYK, + this.options.decimals + ); + } + + public get CMYKAObject(): CMYKObject { + return colorParserContext.convert( + this.cmyk, + ColorModel.CMYK, + this.options.decimals, + true + ); + } + + // CSS public properties + public get HEX(): string { + return colorParserContext.convertCSS( + this.rgb, + ColorModel.HEX + ); + } + + public get HEXA(): string { + return colorParserContext.convertCSS( + this.rgb, + ColorModel.HEX, + {}, + true + ); + } + + public get RGB(): string { + return colorParserContext.convertCSS( + this.rgb, + ColorModel.RGB, + this.options + ); + } + + public get RGBA(): string { + return colorParserContext.convertCSS( + this.rgb, + ColorModel.RGB, + this.options, + true + ); + } + + public get HSL(): string { + return colorParserContext.convertCSS( + this.hsl, + ColorModel.HSL, + this.options + ); + } + + public get HSLA(): string { + return colorParserContext.convertCSS( + this.hsl, + ColorModel.HSL, + this.options, + true + ); + } + + public get HWB(): string { + return colorParserContext.convertCSS( + this.hwb, + ColorModel.HWB, + this.options + ); + } + + public get HWBA(): string { + return colorParserContext.convertCSS( + this.hwb, + ColorModel.HWB, + this.options, + true + ); + } + + public get CIELab(): string { + return colorParserContext.convertCSS( + this.lab, + ColorModel.CIELab, + this.options + ); + } + + public get CIELabA(): string { + return colorParserContext.convertCSS( + this.lab, + ColorModel.CIELab, + this.options, + true + ); + } + + public get LCH(): string { + return colorParserContext.convertCSS( + this.lch, + ColorModel.LCH, + this.options + ); + } + + public get LCHA(): string { + return colorParserContext.convertCSS( + this.lch, + ColorModel.LCH, + this.options, + true + ); + } + + public get CMYK(): string { + return colorParserContext.convertCSS( + this.cmyk, + ColorModel.CMYK, + this.options + ); + } + + public get CMYKA(): string { + return colorParserContext.convertCSS( + this.cmyk, + ColorModel.CMYK, + this.options, + true + ); + } + + // Color Conversion Static Methods + public static toHEXObject(color: ColorInput): HEXObject { + return colorParserContext.convert( + color, + ColorModel.HEX + ); + } + + public static toHEX(color: ColorInput): string { + return colorParserContext.convertCSS( + color, + ColorModel.HEX + ); + } + + public static toHEXAObject(color: ColorInput): HEXObject { + return colorParserContext.convert( + color, + ColorModel.HEX, + undefined, + true + ); + } + + public static toHEXA(color: ColorInput): string { + return colorParserContext.convertCSS( + color, + ColorModel.HEX, + undefined, + true + ); + } + + public static toRGBObject(color: ColorInput, options: InputOptions = {}): RGBObject { + return colorParserContext.convert( + color, + ColorModel.RGB, + options.decimals + ); + } + + public static toRGB(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.RGB, + getOptionsFromColorInput(options, color) + ); + } + + public static toRGBAObject(color: ColorInput, options: InputOptions = {}): RGBObject { + return colorParserContext.convert( + color, + ColorModel.RGB, + options.decimals, + true + ); + } + + public static toRGBA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.RGB, + getOptionsFromColorInput(options, color), + true + ); + } + + public static toHSLObject(color: ColorInput, options: InputOptions = {}): HSLObject { + return colorParserContext.convert( + color, + ColorModel.HSL, + options.decimals + ); + } + + public static toHSL(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.HSL, + getOptionsFromColorInput(options, color) + ); + } + + public static toHSLAObject(color: ColorInput, options: InputOptions = {}): HSLObject { + return colorParserContext.convert( + color, + ColorModel.HSL, + options.decimals, + true + ); + } + + public static toHSLA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.HSL, + getOptionsFromColorInput(options, color), + true + ); + } + + public static toHWBObject(color: ColorInput, options: InputOptions = {}): HWBObject { + return colorParserContext.convert( + color, + ColorModel.HWB, + options.decimals + ); + } + + public static toHWB(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.HWB, + getOptionsFromColorInput(options, color) + ); + } + + public static toHWBAObject(color: ColorInput, options: InputOptions = {}): HWBObject { + return colorParserContext.convert( + color, + ColorModel.HWB, + options.decimals, + true + ); + } + + public static toHWBA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.HWB, + getOptionsFromColorInput(options, color), + true + ); + } + + public static toCIELabObject(color: ColorInput, options: InputOptions = {}): CIELabObject { + return colorParserContext.convert( + color, + ColorModel.CIELab, + options.decimals + ); + } + + public static toCIELab(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.CIELab, + getOptionsFromColorInput(options, color) + ); + } + + public static toCIELabAObject(color: ColorInput, options: InputOptions = {}): CIELabObject { + return colorParserContext.convert( + color, + ColorModel.CIELab, + options.decimals, + true + ); + } + + public static toCIELabA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.CIELab, + getOptionsFromColorInput(options, color), + true + ); + } + + public static toLCHObject(color: ColorInput, options: InputOptions = {}): LCHObject { + return colorParserContext.convert( + color, + ColorModel.LCH, + options.decimals + ); + } + + public static toLCH(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.LCH, + getOptionsFromColorInput(options, color) + ); + } + + public static toLCHAObject(color: ColorInput, options: InputOptions = {}): LCHObject { + return colorParserContext.convert( + color, + ColorModel.LCH, + options.decimals, + true + ); + } + + public static toLCHA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.LCH, + getOptionsFromColorInput(options, color), + true + ); + } + + public static toCMYKObject(color: ColorInput, options: InputOptions = {}): CMYKObject { + return colorParserContext.convert( + color, + ColorModel.CMYK, + options.decimals + ); + } + + public static toCMYK(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.CMYK, + getOptionsFromColorInput(options, color) + ); + } + + public static toCMYKAObject(color: ColorInput, options: InputOptions = {}): CMYKObject { + return colorParserContext.convert( + color, + ColorModel.CMYK, + options.decimals, + true + ); + } + + public static toCMYKA(color: ColorInput, options: InputOptions = {}): string { + return colorParserContext.convertCSS( + color, + ColorModel.CMYK, + getOptionsFromColorInput(options, color), + true + ); + } + + // Color Blending Static Methods + public static getBlendHEXObject( + from: ColorInput, + to: ColorInput, + steps?: number + ): RGBObject[] { + return getBlendReturn( + from, + to, + ColorModel.HEX, + false, + false, + steps + ); + } + + public static getBlendHEX( + from: ColorInput, + to: ColorInput, + steps?: number + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HEX, + true, + false, + steps + ); + } + + public static getBlendHEXAObject( + from: ColorInput, + to: ColorInput, + steps?: number + ): RGBObject[] { + return getBlendReturn( + from, + to, + ColorModel.HEX, + false, + true, + steps + ); + } + + public static getBlendHEXA( + from: ColorInput, + to: ColorInput, + steps?: number + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HEX, + true, + true, + steps + ); + } + + public static getBlendRGBObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): RGBObject[]; + public static getBlendRGBObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): RGBObject[]; + public static getBlendRGBObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): RGBObject[] { + return getBlendReturn( + from, + to, + ColorModel.RGB, + false, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendRGB( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendRGB( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendRGB( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.RGB, + true, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendRGBAObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): RGBObject[]; + public static getBlendRGBAObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): RGBObject[]; + public static getBlendRGBAObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): RGBObject[] { + return getBlendReturn( + from, + to, + ColorModel.RGB, + false, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendRGBA( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendRGBA( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendRGBA( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.RGB, + true, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHSLObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): HSLObject[]; + public static getBlendHSLObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): HSLObject[]; + public static getBlendHSLObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): HSLObject[] { + return getBlendReturn( + from, + to, + ColorModel.HSL, + false, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHSL( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendHSL( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendHSL( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HSL, + true, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHSLAObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): HSLObject[]; + public static getBlendHSLAObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): HSLObject[]; + public static getBlendHSLAObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): HSLObject[] { + return getBlendReturn( + from, + to, + ColorModel.HSL, + false, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHSLA( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendHSLA( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendHSLA( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HSL, + true, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHWBObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): HWBObject[]; + public static getBlendHWBObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): HWBObject[]; + public static getBlendHWBObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): HWBObject[] { + return getBlendReturn( + from, + to, + ColorModel.HWB, + false, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHWB( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendHWB( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendHWB( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HWB, + true, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHWBAObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): HWBObject[]; + public static getBlendHWBAObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): HWBObject[]; + public static getBlendHWBAObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): HWBObject[] { + return getBlendReturn( + from, + to, + ColorModel.HWB, + false, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendHWBA( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendHWBA( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendHWBA( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.HWB, + true, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendCIELabObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): CIELabObject[]; + public static getBlendCIELabObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): CIELabObject[]; + public static getBlendCIELabObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): CIELabObject[] { + return getBlendReturn( + from, + to, + ColorModel.CIELab, + false, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendCIELab( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendCIELab( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendCIELab( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.CIELab, + true, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendCIELabAObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): CIELabObject[]; + public static getBlendCIELabAObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): CIELabObject[]; + public static getBlendCIELabAObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): CIELabObject[] { + return getBlendReturn( + from, + to, + ColorModel.CIELab, + false, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendCIELabA( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendCIELabA( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendCIELabA( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.CIELab, + true, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendLCHObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): LCHObject[]; + public static getBlendLCHObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): LCHObject[]; + public static getBlendLCHObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): LCHObject[] { + return getBlendReturn( + from, + to, + ColorModel.LCH, + false, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendLCH( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendLCH( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendLCH( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.LCH, + true, + false, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendLCHAObject( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): LCHObject[]; + public static getBlendLCHAObject( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): LCHObject[]; + public static getBlendLCHAObject( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): LCHObject[] { + return getBlendReturn( + from, + to, + ColorModel.LCH, + false, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + public static getBlendLCHA( + from: ColorInput, + to: ColorInput, + options?: InputOptions + ): string[]; + public static getBlendLCHA( + from: ColorInput, + to: ColorInput, + steps?: number, + options?: InputOptions + ): string[]; + public static getBlendLCHA( + from: ColorInput, + to: ColorInput, + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions + ): string[] { + return getBlendReturn( + from, + to, + ColorModel.LCH, + true, + true, + ...getBlendReturnParams( + thirdParameter, + fourthParameter + ) + ); + } + + // Color Mix Static Methods + public static getMixHEXObject(colors: ColorInput[], mode?: MixString): HEXObject { + return getMixReturn( + colors, + ColorModel.HEX, + false, + false, + mode + ); + } + + public static getMixHEX(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): string { + return getMixReturn( + colors, + ColorModel.HEX, + true, + false, + mode + ); + } + + public static getMixHEXAObject(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): HEXObject { + return getMixReturn( + colors, + ColorModel.HEX, + false, + true, + mode + ); + } + + public static getMixHEXA(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): string { + return getMixReturn( + colors, + ColorModel.HEX, + true, + true, + mode + ); + } + + public static getMixRGBObject( + colors: ColorInput[], + options?: InputOptions + ): RGBObject; + public static getMixRGBObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): RGBObject; + public static getMixRGBObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): RGBObject { + return getMixReturn( + colors, + ColorModel.RGB, + false, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixRGB( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixRGB( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixRGB( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.RGB, + true, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixRGBAObject( + colors: ColorInput[], + options?: InputOptions + ): RGBObject; + public static getMixRGBAObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): RGBObject; + public static getMixRGBAObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): RGBObject { + return getMixReturn( + colors, + ColorModel.RGB, + false, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixRGBA( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixRGBA( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixRGBA( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.RGB, + true, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHSLObject( + colors: ColorInput[], + options?: InputOptions + ): HSLObject; + public static getMixHSLObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): HSLObject; + public static getMixHSLObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): HSLObject { + return getMixReturn( + colors, + ColorModel.HSL, + false, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHSL( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixHSL( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixHSL( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.HSL, + true, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHSLAObject( + colors: ColorInput[], + options?: InputOptions + ): HSLObject; + public static getMixHSLAObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): HSLObject; + public static getMixHSLAObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): HSLObject { + return getMixReturn( + colors, + ColorModel.HSL, + false, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHSLA( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixHSLA( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixHSLA( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.HSL, + true, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHWBObject( + colors: ColorInput[], + options?: InputOptions + ): HWBObject; + public static getMixHWBObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): HWBObject; + public static getMixHWBObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): HWBObject { + return getMixReturn( + colors, + ColorModel.HWB, + false, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHWB( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixHWB( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixHWB( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.HWB, + true, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHWBAObject( + colors: ColorInput[], + options?: InputOptions + ): HWBObject; + public static getMixHWBAObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): HWBObject; + public static getMixHWBAObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): HWBObject { + return getMixReturn( + colors, + ColorModel.HWB, + false, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixHWBA( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixHWBA( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixHWBA( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.HWB, + true, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixCIELabObject( + colors: ColorInput[], + options?: InputOptions + ): CIELabObject; + public static getMixCIELabObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): CIELabObject; + public static getMixCIELabObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): CIELabObject { + return getMixReturn( + colors, + ColorModel.CIELab, + false, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixCIELab( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixCIELab( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixCIELab( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.CIELab, + true, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixCIELabAObject( + colors: ColorInput[], + options?: InputOptions + ): CIELabObject; + public static getMixCIELabAObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): CIELabObject; + public static getMixCIELabAObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): CIELabObject { + return getMixReturn( + colors, + ColorModel.CIELab, + false, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixCIELabA( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixCIELabA( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixCIELabA( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.CIELab, + true, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixLCHObject( + colors: ColorInput[], + options?: InputOptions + ): LCHObject; + public static getMixLCHObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): LCHObject; + public static getMixLCHObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): LCHObject { + return getMixReturn( + colors, + ColorModel.LCH, + false, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixLCH( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixLCH( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixLCH( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.LCH, + true, + false, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixLCHAObject( + colors: ColorInput[], + options?: InputOptions + ): LCHObject; + public static getMixLCHAObject( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): LCHObject; + public static getMixLCHAObject( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): LCHObject { + return getMixReturn( + colors, + ColorModel.LCH, + false, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + public static getMixLCHA( + colors: ColorInput[], + options?: InputOptions + ): string; + public static getMixLCHA( + colors: ColorInput[], + mode?: MixString, + options?: InputOptions + ): string; + public static getMixLCHA( + colors: ColorInput[], + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions + ): string { + return getMixReturn( + colors, + ColorModel.LCH, + true, + true, + ...getMixReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + // Get shades static method + public static getShades(color: string, options?: InputOptions): string[]; + public static getShades(color: HEXObject, options?: InputOptions): HEXObject[]; + public static getShades(color: RGBObject, options?: InputOptions): RGBObject[]; + public static getShades(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; + public static getShades(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; + public static getShades(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; + public static getShades(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; + + public static getShades(color: string, shades?: number, options?: InputOptions): string[]; + public static getShades(color: HEXObject, shades?: number, options?: InputOptions): HEXObject[]; + public static getShades(color: RGBObject, shades?: number, options?: InputOptions): RGBObject[]; + public static getShades(color: HSLObjectGeneric, shades?: number, options?: InputOptions): HSLObject[]; + public static getShades(color: HWBObjectGeneric, shades?: number, options?: InputOptions): HWBObject[]; + public static getShades(color: CIELabObjectGeneric, shades?: number, options?: InputOptions): CIELabObject[]; + public static getShades(color: LCHObjectGeneric, shades?: number, options?: InputOptions): LCHObject[]; + + public static getShades( + color: ColorInputWithoutCMYK, + secondParameter?: number | InputOptions, + thirdParameter?: InputOptions + ): ColorOutput[] { + return getShadesOrTintsReturn( + true, + color, + ...getShadesOrTintsReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + // Get tints static method + public static getTints(color: string, options?: InputOptions): string[]; + public static getTints(color: HEXObject, options?: InputOptions): HEXObject[]; + public static getTints(color: RGBObject, options?: InputOptions): RGBObject[]; + public static getTints(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; + public static getTints(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; + public static getTints(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; + public static getTints(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; + + public static getTints(color: string, tints?: number, options?: InputOptions): string[]; + public static getTints(color: HEXObject, tints?: number, options?: InputOptions): HEXObject[]; + public static getTints(color: RGBObject, tints?: number, options?: InputOptions): RGBObject[]; + public static getTints(color: HSLObjectGeneric, tints?: number, options?: InputOptions): HSLObject[]; + public static getTints(color: HWBObjectGeneric, tints?: number, options?: InputOptions): HWBObject[]; + public static getTints(color: CIELabObjectGeneric, tints?: number, options?: InputOptions): CIELabObject[]; + public static getTints(color: LCHObjectGeneric, tints?: number, options?: InputOptions): LCHObject[]; + + public static getTints( + color: ColorInputWithoutCMYK, + secondParameter?: number | InputOptions, + thirdParameter?: InputOptions + ): ColorOutput[] { + return getShadesOrTintsReturn( + false, + color, + ...getShadesOrTintsReturnParameters( + secondParameter, + thirdParameter + ) + ); + } + + // Color Harmony Static Method + public static getHarmony(color: string, options?: InputOptions): string[]; + public static getHarmony(color: HEXObject, options?: InputOptions): HEXObject[]; + public static getHarmony(color: RGBObject, options?: InputOptions): RGBObject[]; + public static getHarmony(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; + public static getHarmony(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; + public static getHarmony(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; + public static getHarmony(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; + + public static getHarmony(color: string, mode?: MixString, options?: InputOptions): string[]; + public static getHarmony(color: HEXObject, mode?: MixString, options?: InputOptions): HEXObject[]; + public static getHarmony(color: RGBObject, mode?: MixString, options?: InputOptions): RGBObject[]; + public static getHarmony(color: HSLObjectGeneric, mode?: MixString, options?: InputOptions): HSLObject[]; + public static getHarmony(color: HWBObjectGeneric, mode?: MixString, options?: InputOptions): HWBObject[]; + public static getHarmony(color: CIELabObjectGeneric, mode?: MixString, options?: InputOptions): CIELabObject[]; + public static getHarmony(color: LCHObjectGeneric, mode?: MixString, options?: InputOptions): LCHObject[]; + + public static getHarmony(color: string, harmony?: Harmony, options?: InputOptions): string[]; + public static getHarmony(color: HEXObject, harmony?: Harmony, options?: InputOptions): HEXObject[]; + public static getHarmony(color: RGBObject, harmony?: Harmony, options?: InputOptions): RGBObject[]; + public static getHarmony(color: HSLObjectGeneric, harmony?: Harmony, options?: InputOptions): HSLObject[]; + public static getHarmony(color: HWBObjectGeneric, harmony?: Harmony, options?: InputOptions): HWBObject[]; + public static getHarmony(color: CIELabObjectGeneric, harmony?: Harmony, options?: InputOptions): CIELabObject[]; + public static getHarmony(color: LCHObjectGeneric, harmony?: Harmony, options?: InputOptions): LCHObject[]; + + public static getHarmony(color: string, harmony?: Harmony, mode?: MixString, options?: InputOptions): string[]; + public static getHarmony(color: HEXObject, harmony?: Harmony, mode?: MixString, options?: InputOptions): HEXObject[]; + public static getHarmony(color: RGBObject, harmony?: Harmony, mode?: MixString, options?: InputOptions): RGBObject[]; + public static getHarmony(color: HSLObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): HSLObject[]; + public static getHarmony(color: HWBObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): HWBObject[]; + public static getHarmony(color: CIELabObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): CIELabObject[]; + public static getHarmony(color: LCHObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): LCHObject[]; + + public static getHarmony( + color: ColorInputWithoutCMYK, + secondParam?: HarmonyString | MixString | InputOptions, + thirdParam?: MixString | InputOptions, + fourthParam?: InputOptions + ): ColorOutput[] { + return getHarmonyReturn( + color, + ...getHarmonyReturnParameters( + secondParam, + thirdParam, + fourthParam + ) + ); + } +} \ No newline at end of file diff --git a/src/classes/HEXParser.ts b/src/classes/HEXParser.ts new file mode 100644 index 0000000..58089ce --- /dev/null +++ b/src/classes/HEXParser.ts @@ -0,0 +1,150 @@ +import { + ColorInput, + ColorObject, + CSSOptionsBase, + HEXObject, + HEXRegExpMatchArray, + NumberOrString, + Options, + RGBObject, + RGBObjectGeneric +} from '@types'; +import { + BASE_255, + COLOR_KEYS, + ColorKeywords, + ColorModel, + COLORREGS, + HEX +} from '#constants'; +import { getRGB } from '#color/rgb'; +import { getResultFromCSSTemplate, prepareColorForCss } from '#css'; +import { + getDEC, + getHEX, + getBase255Number, + isString, + isUndefined, + isRGBObject, + round, + toHEX +} from '#utilities'; +import { ColorParser } from './ColorParserContext'; + +export class HEXParser extends ColorParser { + + private _extract(input: string): HEXRegExpMatchArray['groups'] { + const colorStr = !~COLOR_KEYS.indexOf(input) + ? input + : ColorKeywords[input as keyof typeof ColorKeywords]; + const match = colorStr.match(COLORREGS.HEX) as HEXRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + + if (isString(input)) { + return ( + COLORREGS.HEX.test(input) || + !!~COLOR_KEYS.indexOf(input) + ); + } + + const hasInvalidHex = Object.entries(input).some((item: [string, string | number]): boolean => { + return !HEX.test(`${item[1]}`); + }); + + return isRGBObject(input) && !hasInvalidHex; + } + + parse(input: string | RGBObjectGeneric): RGBObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const r = groups.r ?? groups.rr; + const g = groups.g ?? groups.gg; + const b = groups.b ?? groups.bb; + const a = groups.a ?? groups.aa; + + return { + R: getDEC(r), + G: getDEC(g), + B: getDEC(b), + ...( + isUndefined(a) + ? {} + : { + A: getDEC(a) / BASE_255 + } + ) + }; + + } + + return { + R: getBase255Number(`${input.R}`), + G: getBase255Number(`${input.G}`), + B: getBase255Number(`${input.B}`), + ...( + isUndefined(input.A) + ? {} + : { + A: Math.min(getBase255Number(`${input.A}`, true), 1) + } + ) + }; + + } + + convert( + color: ColorObject, + __decimals: number, + withAlpha: boolean + ): HEXObject { + const rgb: RGBObject = isRGBObject(color) + ? color as RGBObject + : getRGB(color); + return { + R: getHEX(rgb.R), + G: getHEX(rgb.G), + B: getHEX(rgb.B), + ...( + withAlpha + ? { + A: isUndefined(rgb.A) + ? '0xFF' + : getHEX(rgb.A * BASE_255) + } + : {} + ) + }; + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const rgb = this.convert(color, options.decimals, withAlpha); + const transformer = (value: NumberOrString): string => toHEX(round(value)); + const values = prepareColorForCss(rgb, transformer); + const template = values.length === 4 + ? '#{1}{2}{3}{4}' + : '#{1}{2}{3}'; + return getResultFromCSSTemplate(template, values); + } + + public getCSSOptions(input: string): CSSOptionsBase { + const groups = this._extract(input); + return { + hasAlpha: !isUndefined(groups.a ?? groups.aa) + }; + } + + public get model(): ColorModel { + return ColorModel.HEX; + } + +} \ No newline at end of file diff --git a/src/classes/HSLParser.ts b/src/classes/HSLParser.ts new file mode 100644 index 0000000..0b3f102 --- /dev/null +++ b/src/classes/HSLParser.ts @@ -0,0 +1,254 @@ +import { + AnglesUnitEnum, + ColorObject, + ColorInput, + CSSOptionsBase, + HSLObject, + HSLObjectGeneric, + HSLRegExpMatchArray, + Options +} from '@types'; +import { + COLORREGS, + ColorModel, + MAX_ALPHA, + PCENT +} from '#constants'; +import { + getAngleUnit, + isHSLObject, + isString, + isUndefined, + minmax, + normalizeAlpha, + normalizeHue, + percent, + round +} from '#utilities'; +import { + buildCSSHueTransformer, + getCSSComma, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { rgbToHsl } from '#color/translators'; +import { CalcParser } from './CalcParser'; +import { ColorParserContext, ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + angleUnit: AnglesUnitEnum; + hasPercentageAlpha: boolean; +} + +export class HSLParser extends ColorParser { + + private _extract(input: string): HSLRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.HSL) as HSLRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + if (isString(input)) { + return COLORREGS.HSL.test(input); + } + return isHSLObject(input); + } + + parse( + input: string | HSLObjectGeneric, + context: ColorParserContext + ): HSLObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const { + // Legacy values + h_legacy, + s_legacy, + l_legacy, + a_legacy, + // HSL values + h, + s, + l, + a, + // Relative values + from, + relative_h, + relative_s, + relative_l, + relative_a + } = groups; + + if (from) { + + const fromColor = context.parse(from); + const fromRGB = getRGB(fromColor); + const fromHSL = rgbToHsl( + fromRGB.R, + fromRGB.G, + fromRGB.B, + fromRGB.A + ); + const fromHSLVars = { + h: fromHSL.H, + s: fromHSL.S, + l: fromHSL.L, + alpha: fromHSL.A + }; + + const H = new CalcParser('h', relative_h, fromHSLVars).result; + const S = new CalcParser('s', relative_s, fromHSLVars).result; + const L = new CalcParser('l', relative_l, fromHSLVars).result; + + const hsl: HSLObject = { + H: normalizeHue(H), + S: percent(S), + L: percent(L) + }; + + if (relative_a) { + const A = new CalcParser('alpha', relative_a, fromHSLVars).result; + hsl.A = minmax(A, 0, MAX_ALPHA); + } + + return hsl; + + } else { + + const H = h_legacy ?? h; + const S = s_legacy ?? s; + const L = l_legacy ?? l; + const A = a_legacy ?? a; + + return { + H: normalizeHue(H), + S: percent(S), + L: percent(L), + ...( + isUndefined(A) + ? {} + : { + A: normalizeAlpha(A) + } + ) + }; + + } + + } + + return { + H: normalizeHue(input.H), + S: percent(`${input.S}`), + L: percent(`${input.L}`), + ...( + isUndefined(input.A) + ? {} + : { + A: minmax(+input.A, 0, MAX_ALPHA) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): HSLObject { + let hsl: HSLObject; + if (isHSLObject(color)) { + hsl = color as HSLObject; + } else { + const rgb = getRGB(color); + hsl = rgbToHsl( + rgb.R, + rgb.G, + rgb.B, + rgb.A + ); + } + return this._roundHSLObject( + { + H: hsl.H, + S: hsl.S, + L: hsl.L, + ...( + withAlpha + ? { + A: hsl.A ?? 1 + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const { legacyCSS, spacesAfterCommas } = options; + const comma = getCSSComma(spacesAfterCommas); + const hsl = this.convert(color, options.decimals, withAlpha); + const transformer = buildCSSHueTransformer(options); + const values = prepareColorForCss(hsl, transformer); + const template = legacyCSS + ? ( + values.length === 4 + ? `hsla({1}${comma}{2}%${comma}{3}%${comma}{4})` + : `hsl({1}${comma}{2}%${comma}{3}%)` + ) + : ( + values.length === 4 + ? `hsl({1} {2}% {3}% / {4})` + : `hsl({1} {2}% {3}%)` + ); + return getResultFromCSSTemplate(template, values); + } + + private _roundHSLObject(color: HSLObject, decimals: number): HSLObject { + return { + H: round( + normalizeHue(color.H), + decimals + ), + S: round(color.S, decimals), + L: round(color.L, decimals), + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + const { + h_legacy, + h, + a_legacy, + a + } = groups; + return { + angleUnit: getAngleUnit(h_legacy ?? h), + hasPercentageAlpha: PCENT.test(a_legacy ?? a), + hasAlpha: !isUndefined(a_legacy ?? a) + }; + } + + public get model(): ColorModel { + return ColorModel.HSL; + } + +} \ No newline at end of file diff --git a/src/classes/HWBParser.ts b/src/classes/HWBParser.ts new file mode 100644 index 0000000..7b05c70 --- /dev/null +++ b/src/classes/HWBParser.ts @@ -0,0 +1,226 @@ +import { + AnglesUnitEnum, + ColorInput, + ColorObject, + CSSOptionsBase, + HWBObject, + HWBObjectGeneric, + HWBRegExpMatchArray, + Options +} from '@types'; +import { + COLORREGS, + ColorModel, + MAX_ALPHA, + MAX_HUE, + MAX_PCENT, + PCENT +} from '#constants'; +import { + getAngleUnit, + isHWBObject, + isString, + isUndefined, + minmax, + normalizeAlpha, + normalizeHue, + percent, + round +} from '#utilities'; +import { + buildCSSHueTransformer, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { rgbToHwb } from '#color/translators'; +import { CalcParser } from './CalcParser'; +import { ColorParserContext, ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + angleUnit: AnglesUnitEnum; + hasPercentageAlpha: boolean; +} + +export class HWBParser extends ColorParser { + + private _extract(input: string): HWBRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.HWB) as HWBRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + if (isString(input)) { + return COLORREGS.HWB.test(input); + } + return isHWBObject(input); + } + + parse(input: string | HWBObjectGeneric, context: ColorParserContext): HWBObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const { + // HWB values + h, + w, + b, + a, + // Relative values + from, + relative_h, + relative_w, + relative_b, + relative_a + } = groups; + + if (from) { + + const fromColor = context.parse(from); + const fromRGB = getRGB(fromColor); + const fromHWB = rgbToHwb( + fromRGB.R, + fromRGB.G, + fromRGB.B, + fromRGB.A + ); + const fromHWBVars = { + h: fromHWB.H, + w: fromHWB.W, + b: fromHWB.B, + alpha: fromHWB.A + }; + + const H = new CalcParser('h', relative_h, fromHWBVars).result; + const W = new CalcParser('w', relative_w, fromHWBVars).result; + const B = new CalcParser('b', relative_b, fromHWBVars).result; + + const hwb: HWBObject = { + H: minmax(H, 0, MAX_HUE), + W: minmax(W, 0, MAX_PCENT), + B: minmax(B, 0, MAX_PCENT) + }; + + if (relative_a) { + const A = new CalcParser('alpha', relative_a, fromHWBVars).result; + hwb.A = minmax(A, 0, MAX_ALPHA); + } + + return hwb; + + } else { + + return { + H: normalizeHue(h), + W: percent(w), + B: percent(b), + ...( + isUndefined(a) + ? {} + : { + A: normalizeAlpha(a) + } + ) + }; + + } + + } + + return { + H: normalizeHue(input.H), + W: percent(input.W), + B: percent(input.B), + ...( + isUndefined(input.A) + ? {} + : { + A: normalizeAlpha(input.A) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): HWBObject { + let hwb: HWBObject; + if (isHWBObject(color)) { + hwb = color as HWBObject; + } else { + const rgb = getRGB(color); + hwb = rgbToHwb( + rgb.R, + rgb.G, + rgb.B, + rgb.A + ); + } + return this._roundHWBObject( + { + H: hwb.H, + W: hwb.W, + B: hwb.B, + ...( + withAlpha + ? { + A: hwb.A ?? 1 + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const hwb = this.convert(color, options.decimals, withAlpha); + const transformer = buildCSSHueTransformer(options); + const values = prepareColorForCss(hwb, transformer); + const template = values.length === 4 + ? `hwb({1} {2}% {3}% / {4})` + : `hwb({1} {2}% {3}%)`; + return getResultFromCSSTemplate(template, values); + } + + private _roundHWBObject(color: HWBObject, decimals: number): HWBObject { + return { + H: round( + normalizeHue(color.H), + decimals + ), + W: round(color.W, decimals), + B: round(color.B, decimals), + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + return { + angleUnit: getAngleUnit(groups.h), + hasPercentageAlpha: PCENT.test(groups.a), + hasAlpha: !isUndefined(groups.a) + }; + } + + public get model(): ColorModel { + return ColorModel.HWB; + } + +} \ No newline at end of file diff --git a/src/classes/LCHParser.ts b/src/classes/LCHParser.ts new file mode 100644 index 0000000..b80d2b3 --- /dev/null +++ b/src/classes/LCHParser.ts @@ -0,0 +1,269 @@ +import { + AnglesUnitEnum, + ColorInput, + ColorObject, + ColorUnitEnum, + CSSOptionsBase, + LCHObject, + LCHObjectGeneric, + LCHRegExpMatchArray, + NumberOrString, + Options +} from '@types'; +import { + COLORREGS, + ColorModel, + MAX_ALPHA, + MAX_LCH_C, + MAX_PCENT, + PCENT +} from '#constants'; +import { + from150NumberToPercent, + getAngleUnit, + getBase150Number, + isLCHObject, + isString, + isUndefined, + minmax, + normalizeAlpha, + normalizeHue, + percent, + round, + translateDegrees +} from '#utilities'; +import { + getCSSAlpha, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { rgbToLch } from '#color/translators'; +import { CalcParser } from './CalcParser'; +import { ColorParserContext, ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + angleUnit: AnglesUnitEnum; + hasPercentageValues: boolean; + hasPercentageAlpha: boolean; +} + +export class LCHParser extends ColorParser { + + private _extract(input: string): LCHRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.LCH) as LCHRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + if (isString(input)) { + return COLORREGS.LCH.test(input); + } + return isLCHObject(input); + } + + parse(input: string | LCHObjectGeneric, context: ColorParserContext): LCHObject { + + if (isString(input)) { + + const groups = this._extract(input); + + const { + // LCH values + l, + c, + h, + a, + // Relative values + from, + relative_l, + relative_c, + relative_h, + relative_a + } = groups; + + if (from) { + + const fromColor = context.parse(from); + const fromRGB = getRGB(fromColor); + + const fromLCH = rgbToLch( + fromRGB.R, + fromRGB.G, + fromRGB.B + ); + const fromLCHVars = { + l: fromLCH.L, + c: fromLCH.C, + h: fromLCH.H, + alpha: fromRGB.A ?? 1 + }; + + const L = new CalcParser('l', relative_l, fromLCHVars).result; + const C = new CalcParser('c', relative_c, fromLCHVars).result; + const H = new CalcParser('h', relative_h, fromLCHVars).result; + + const lch: LCHObject = { + L: minmax(L, 0, MAX_PCENT), + C: minmax(C, - MAX_LCH_C, MAX_LCH_C), + H: normalizeHue(H) + }; + + if (relative_a) { + const A = new CalcParser('alpha', relative_a, fromLCHVars).result; + lch.A = minmax(A, 0, MAX_ALPHA); + } + + return lch; + + } else { + + return { + L: percent(l), + C: getBase150Number(c), + H: normalizeHue(h), + ...( + isUndefined(a) + ? {} + : { + A: normalizeAlpha(a) + } + ) + }; + + } + + } + + return { + L: percent(input.L), + C: getBase150Number(`${input.C}`), + H: normalizeHue(input.H), + ...( + isUndefined(input.A) + ? {} + : { + A: normalizeAlpha(input.A) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): LCHObject { + let lch: LCHObject; + if (isLCHObject(color)) { + lch = color as LCHObject; + } else { + const rgb = getRGB(color); + lch = rgbToLch( + rgb.R, + rgb.G, + rgb.B + ); + } + return this._roundLCHObject( + { + L: lch.L, + C: lch.C, + H: lch.H, + ...( + withAlpha + ? { + A: +(color.A ?? 1) + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const { + decimals, + lchUnit, + anglesUnit + } = options; + const lch = this.convert(color, options.decimals, withAlpha); + const transformer = (value: number, index: number): NumberOrString => { + if (index === 0) { + const L = round( + percent(value), + decimals + ); + return lchUnit === ColorUnitEnum.PERCENT + ? `${L}%` + : `${L}`; + } + if (index === 1) { + return lchUnit === ColorUnitEnum.PERCENT + ? `${from150NumberToPercent(value, decimals)}%` + : round(value, decimals); + } + if (index === 2) { + if (anglesUnit !== AnglesUnitEnum.NONE) { + const translated = round( + translateDegrees( + value, + anglesUnit + ), + decimals + ); + return `${translated}${anglesUnit}`; + } + return round(value, decimals); + } + return getCSSAlpha(value, options, true); + }; + const values = prepareColorForCss(lch, transformer); + const template = values.length === 4 + ? `lch({1} {2} {3} / {4})` + : `lch({1} {2} {3})`; + return getResultFromCSSTemplate(template, values); + } + + private _roundLCHObject(color: LCHObject, decimals: number): LCHObject { + return { + L: round(color.L, decimals), + C: round(color.C, decimals), + H: round( + normalizeHue(color.H), + decimals + ), + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + return { + angleUnit: getAngleUnit(groups.h), + hasPercentageValues: ( + PCENT.test(groups.l) && + PCENT.test(groups.c) + ), + hasPercentageAlpha: PCENT.test(groups.a), + hasAlpha: !isUndefined(groups.a) + }; + } + + public get model(): ColorModel { + return ColorModel.LCH; + } + +} \ No newline at end of file diff --git a/src/classes/RGBParser.ts b/src/classes/RGBParser.ts new file mode 100644 index 0000000..4215726 --- /dev/null +++ b/src/classes/RGBParser.ts @@ -0,0 +1,286 @@ +import { + ColorInput, + ColorObject, + ColorUnitEnum, + CSSOptionsBase, + NumberOrString, + Options, + RGBObject, + RGBObjectGeneric, + RGBRegExpMatchArray +} from '@types'; +import { + BASE_255, + COLORREGS, + ColorModel, + HEX, + PCENT +} from '#constants'; +import { + from255NumberToPercent, + getBase255Number, + isString, + isRGBObject, + isUndefined, + normalizeAlpha, + round +} from '#utilities'; +import { + getCSSAlpha, + getCSSComma, + getResultFromCSSTemplate, + prepareColorForCss +} from '#css'; +import { getRGB } from '#color/rgb'; +import { CalcParser } from './CalcParser'; +import { ColorParserContext, ColorParser } from './ColorParserContext'; + +interface CSSOptions extends CSSOptionsBase { + hasPercentageValues: boolean; + hasPercentageAlpha: boolean; +} + +export class RGBParser extends ColorParser { + + private _extract(input: string): RGBRegExpMatchArray['groups'] { + const match = input.match(COLORREGS.RGB) as RGBRegExpMatchArray; + return match.groups; + } + + supports(input: ColorInput): boolean { + + if (isString(input)) { + return COLORREGS.RGB.test(input); + } + + const hasInvalidRegb = Object.entries(input).some((item: [string, string | number]): boolean => { + return !( + PCENT.test(`${item[1]}`) || + ( + !HEX.test(`${item[1]}`) && + !isNaN(+item[1]) && + +item[1] <= BASE_255 + ) + ); + }); + + return isRGBObject(input) && !hasInvalidRegb; + + } + + parse(input: string | RGBObjectGeneric, context: ColorParserContext): RGBObject { + + if (isString(input)) { + + const groups = this._extract(input); + const { + // Legacy values + r_legacy, + g_legacy, + b_legacy, + a_legacy, + // RGB values + r, + g, + b, + a, + // Relative values + from, + relative_r, + relative_g, + relative_b, + relative_a + } = groups; + + if (from) { + + const fromColor = context.parse(from); + const fromRGB = getRGB(fromColor as ColorObject); + const fromRGBVars = { + r: fromRGB.R, + g: fromRGB.G, + b: fromRGB.B, + alpha: fromRGB.A ?? 1 + }; + const R = new CalcParser('r', relative_r, fromRGBVars).result; + const G = new CalcParser('g', relative_g, fromRGBVars).result; + const B = new CalcParser('b', relative_b, fromRGBVars).result; + + const rgb: RGBObject = { + R: Math.min( + R, + BASE_255 + ), + G: Math.min( + G, + BASE_255 + ), + B: Math.min( + B, + BASE_255 + ) + }; + + if (relative_a) { + const A = new CalcParser('alpha', relative_a, fromRGBVars).result; + rgb.A = Math.min(A, 1); + } + + return rgb; + + } else { + + const R = r_legacy ?? r; + const G = g_legacy ?? g; + const B = b_legacy ?? b; + const A = a_legacy ?? a; + + return { + R: Math.min( + getBase255Number(R), + BASE_255 + ), + G: Math.min( + getBase255Number(G), + BASE_255 + ), + B: Math.min( + getBase255Number(B), + BASE_255 + ), + ...( + isUndefined(A) + ? {} + : { + A: normalizeAlpha(A) + } + ) + }; + + } + + } + + return { + R: getBase255Number(`${input.R}`), + G: getBase255Number(`${input.G}`), + B: getBase255Number(`${input.B}`), + ...( + isUndefined(input.A) + ? {} + : { + A: Math.min(getBase255Number(`${input.A}`, true), 1) + } + ) + }; + + } + + convert( + color: ColorObject, + decimals: number, + withAlpha: boolean + ): RGBObject { + const rgb: RGBObject = isRGBObject(color) + ? color as RGBObject + : getRGB(color); + return this._roundRGBObject( + { + R: rgb.R, + G: rgb.G, + B: rgb.B, + ...( + withAlpha + ? { + A: rgb.A ?? 1 + } + : {} + ) + }, + decimals + ); + } + + convertCSS( + color: ColorObject, + options: Options, + withAlpha: boolean + ): string { + const { + decimals, + legacyCSS, + spacesAfterCommas, + rgbUnit + } = options; + const rgb = this.convert(color, options.decimals, withAlpha); + const comma = getCSSComma(spacesAfterCommas); + const transformer = (value: number, index: number): NumberOrString => { + return rgbUnit === ColorUnitEnum.PERCENT && index < 3 + ? `${from255NumberToPercent(value, decimals)}%` + : ( + index === 3 + ? getCSSAlpha(value, options) + : round(value, decimals) + ); + }; + const values = prepareColorForCss(rgb, transformer); + const template = legacyCSS + ? ( + values.length === 4 + ? `rgba({1}${comma}{2}${comma}{3}${comma}{4})` + : `rgb({1}${comma}{2}${comma}{3})` + ) + : ( + values.length === 4 + ? `rgb({1} {2} {3} / {4})` + : `rgb({1} {2} {3})` + ); + return getResultFromCSSTemplate(template, values); + } + + private _roundRGBObject(color: RGBObject, decimals: number): RGBObject { + const R = round(color.R, decimals); + const G = round(color.G, decimals); + const B = round(color.B, decimals); + return { + R, + G, + B, + ...( + isUndefined(color.A) + ? {} + : { + A: round(color.A, decimals) + } + ) + }; + } + + public getCSSOptions(input: string): CSSOptions { + const groups = this._extract(input); + const { + r_legacy, + g_legacy, + b_legacy, + a_legacy, + r, + g, + b, + a + } = groups; + return { + hasPercentageValues: ( + PCENT.test(r_legacy ?? r) && + PCENT.test(g_legacy ?? g) && + PCENT.test(b_legacy ?? b) + ), + hasPercentageAlpha: PCENT.test(a_legacy ?? a), + hasAlpha: !isUndefined(a_legacy ?? a) + }; + } + + public get model(): ColorModel { + return ColorModel.RGB; + } + +} \ No newline at end of file diff --git a/src/color/css.ts b/src/color/css.ts deleted file mode 100644 index d492a0d..0000000 --- a/src/color/css.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { - AnglesUnitEnum, - CIELabObject, - CMYKObject, - Color, - ColorUnitEnum, - HEXObject, - HSLObject, - HWBObject, - LCHObject, - NumberOrString, - Options, - RGBObject -} from '@types'; -import { - COLOR_PROPS, - ColorModel, - TEMPLATE_VAR, - VALID_COLOR_OBJECTS -} from '#constants'; -import { - from125NumberToPercent, - from150NumberToPercent, - from255NumberToPercent, - getOrderedArrayString, - percent, - round, - toHEX, - translateDegrees -} from '#helpers'; - -const getComma = (withSpace: boolean): string => withSpace - ? ', ' - : ','; - -type Transformer = (value: NumberOrString, index?: number) => NumberOrString; - -const prepareColorForCss = ( - color: Color, - transformer: Transformer -): NumberOrString[] => { - const props = getOrderedArrayString(Object.keys(color)); - const model = VALID_COLOR_OBJECTS[props]; - const keys = COLOR_PROPS[model]; - return keys.reduce((result: NumberOrString[], key: keyof typeof color, index: number): NumberOrString[] => { - const value = color[key]; - if (typeof value !== 'undefined') { - result.push(transformer(value, index)); - } - return result; - }, []); -}; - -const getResultFromTemplate = (template: string, vars: NumberOrString[]): string => { - return template.replace(TEMPLATE_VAR, (__match: string, indexStr: string): string => { - const index = +indexStr - 1; - return `${vars[index]}`; - }); -}; - -const getAlpha = (value: number, options: Options, ignoreLegacy = false): NumberOrString => { - const { alphaUnit, legacyCSS, decimals } = options; - if ( - alphaUnit === ColorUnitEnum.PERCENT && - ( - !legacyCSS || - ignoreLegacy - ) - ) { - return `${round(value * 100, decimals)}%`; - } - return round(value, decimals); -}; - -const buildHueTransformer = (options: Options) => { - const { anglesUnit, decimals } = options; - return (value: number, index: number): NumberOrString => { - if ( - index === 0 && - anglesUnit !== AnglesUnitEnum.NONE - ) { - const translated = round( - translateDegrees( - value, - anglesUnit - ), - decimals - ); - return `${translated}${anglesUnit}`; - } - return index === 3 - ? getAlpha(value, options) - : round(value, decimals); - }; -}; - -export const CSS = { - [ColorModel.HEX]: (color: HEXObject | RGBObject): string => { - const transformer = (value: NumberOrString): string => toHEX(round(value)); - const values = prepareColorForCss(color, transformer); - const template = values.length === 4 - ? '#{1}{2}{3}{4}' - : '#{1}{2}{3}'; - return getResultFromTemplate(template, values); - }, - [ColorModel.RGB]: (color: RGBObject, options: Options): string => { - const { - decimals, - legacyCSS, - spacesAfterCommas, - rgbUnit - } = options; - const comma = getComma(spacesAfterCommas); - const transformer = (value: number, index: number): NumberOrString => { - return rgbUnit === ColorUnitEnum.PERCENT && index < 3 - ? `${from255NumberToPercent(value, decimals)}%` - : ( - index === 3 - ? getAlpha(value, options) - : round(value, decimals) - ); - }; - const values = prepareColorForCss(color, transformer); - const template = legacyCSS - ? ( - values.length === 4 - ? `rgba({1}${comma}{2}${comma}{3}${comma}{4})` - : `rgb({1}${comma}{2}${comma}{3})` - ) - : ( - values.length === 4 - ? `rgb({1} {2} {3} / {4})` - : `rgb({1} {2} {3})` - ); - return getResultFromTemplate(template, values); - }, - [ColorModel.HSL]: (color: HSLObject, options: Options): string => { - const { legacyCSS, spacesAfterCommas } = options; - const comma = getComma(spacesAfterCommas); - const transformer = buildHueTransformer(options); - const values = prepareColorForCss(color, transformer); - const template = legacyCSS - ? ( - values.length === 4 - ? `hsla({1}${comma}{2}%${comma}{3}%${comma}{4})` - : `hsl({1}${comma}{2}%${comma}{3}%)` - ) - : ( - values.length === 4 - ? `hsl({1} {2}% {3}% / {4})` - : `hsl({1} {2}% {3}%)` - ); - return getResultFromTemplate(template, values); - }, - [ColorModel.HWB]: (color: HWBObject, options: Options) => { - const transformer = buildHueTransformer(options); - const values = prepareColorForCss(color, transformer); - const template = values.length === 4 - ? `hwb({1} {2}% {3}% / {4})` - : `hwb({1} {2}% {3}%)`; - return getResultFromTemplate(template, values); - }, - [ColorModel.CIELab]: (color: CIELabObject, options: Options) => { - const { - decimals, - labUnit - } = options; - const transformer = (value: number, index: number): NumberOrString => { - if (index === 0) { - const L = round( - percent(value), - decimals - ); - return labUnit === ColorUnitEnum.PERCENT - ? `${L}%` - : `${L}`; - } - if (index < 3) { - return labUnit === ColorUnitEnum.PERCENT - ? `${from125NumberToPercent(value, decimals)}%` - : round(value, decimals); - } - return getAlpha(value, options, true); - }; - const values = prepareColorForCss(color, transformer); - const template = values.length === 4 - ? `lab({1} {2} {3} / {4})` - : `lab({1} {2} {3})`; - return getResultFromTemplate(template, values); - }, - [ColorModel.LCH]: (color: LCHObject, options: Options) => { - const { - decimals, - lchUnit, - anglesUnit - } = options; - const transformer = (value: number, index: number): NumberOrString => { - if (index === 0) { - const L = round( - percent(value), - decimals - ); - return lchUnit === ColorUnitEnum.PERCENT - ? `${L}%` - : `${L}`; - } - if (index === 1) { - return lchUnit === ColorUnitEnum.PERCENT - ? `${from150NumberToPercent(value, decimals)}%` - : round(value, decimals); - } - if (index === 2) { - if (anglesUnit !== AnglesUnitEnum.NONE) { - const translated = round( - translateDegrees( - value, - anglesUnit - ), - decimals - ); - return `${translated}${anglesUnit}`; - } - return round(value, decimals); - } - return getAlpha(value, options, true); - }; - const values = prepareColorForCss(color, transformer); - const template = values.length === 4 - ? `lch({1} {2} {3} / {4})` - : `lch({1} {2} {3})`; - return getResultFromTemplate(template, values); - }, - [ColorModel.CMYK]: (color: CMYKObject, options: Options): string => { - const { - decimals, - legacyCSS, - spacesAfterCommas, - cmykUnit, - cmykFunction - } = options; - const comma = getComma(spacesAfterCommas); - const transformer = (value: number, index: number): NumberOrString => { - if ( - cmykUnit === ColorUnitEnum.PERCENT && - index < 4 - ) { - return `${round(value, decimals)}%`; - } - return index === 4 - ? getAlpha(value, options) - : round(value / 100, decimals); - }; - const values = prepareColorForCss(color, transformer); - const template = legacyCSS - ? ( - values.length === 5 - ? `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4}${comma}{5})` - : `${cmykFunction}({1}${comma}{2}${comma}{3}${comma}{4})` - ) - : ( - values.length === 5 - ? `${cmykFunction}({1} {2} {3} {4} / {5})` - : `${cmykFunction}({1} {2} {3} {4})` - ); - return getResultFromTemplate(template, values); - } -}; \ No newline at end of file diff --git a/src/color/extractors.ts b/src/color/extractors.ts deleted file mode 100644 index 2c77862..0000000 --- a/src/color/extractors.ts +++ /dev/null @@ -1,410 +0,0 @@ -import { - AnglesUnitEnum, - CIELabObjectGeneric, - CMYKFunctionEnum, - CMYKObjectGeneric, - Color, - ColorInput, - ColorUnitEnum, - HSLObjectGeneric, - HWBObjectGeneric, - InputOptions, - LCHObjectGeneric, - MatchOptions, - Options, - RGBObject, - RGBObjectGeneric -} from '@types'; -import { - BASE_255, - COLOR_KEYS, - ColorKeywords, - ColorModel, - COLORREGS, - COMMAS_AND_NEXT_CHARS, - DEFAULT_OPTIONS, - ERRORS, - HEX, - PCENT, - SPACES, - TypeOf, - VALID_COLOR_OBJECTS -} from '#constants'; -import { - getBase125Number, - getBase150Number, - getBase255Number, - getCMYKNumber, - getOrderedArrayString, - hasProp, - normalizeAlpha, - normalizeHue, - percent -} from '#helpers'; -import { - CIELabStringParser, - CMYKStringParser, - HEXStringParser, - HSLStringParser, - HWBStringParser, - LCHStringParser, - RGBStringParser -} from '#parsers'; -import { - cmykToRgb, - hslToRgb, - hwbToRgb, - labToRgb, - lchToRgb -} from '#color/translators'; - -//---Detect the color model from an string -const getColorModelFromString = (color: string): ColorModel => { - let model; - Object.keys(ColorModel).some((p: ColorModel): boolean => { - const reg = COLORREGS[p]; - if (reg.test(color)) { - model = p; - return true; - } - }); - if ( - !model && - !!~COLOR_KEYS.indexOf(color) - ) { - model = ColorModel.HEX; - } - if (!model) { - throw new Error(ERRORS.NOT_ACCEPTED_STRING_INPUT); - } - return model; -}; - -//---Detect the color model from an object -const getColorModelFromObject = (color: Color): ColorModel => { - - let model: ColorModel; - let invalid = false; - const props = getOrderedArrayString(Object.keys(color)); - - if(VALID_COLOR_OBJECTS[props]) { - model = VALID_COLOR_OBJECTS[props]; - } - - if (model && model === ColorModel.RGB) { - - const hasInvalidHex = Object.entries(color).some((item: [string, string | number]): boolean => { - return !HEX.test(`${item[1]}`); - }); - - const hasInvalidRegb = Object.entries(color).some((item: [string, string | number]): boolean => { - return !( - PCENT.test(`${item[1]}`) || - ( - !HEX.test(`${item[1]}`) && - !isNaN(+item[1]) && - +item[1] <= BASE_255 - ) - ); - }); - - if (hasInvalidHex && hasInvalidRegb) { - invalid = true; - } - - if (!hasInvalidHex) { - model = ColorModel.HEX; - } - - } - if (!model || invalid) { - throw new Error(ERRORS.NOT_ACCEPTED_OBJECT_INPUT); - } - return model; -}; - -//---Detect the color model -export const getColorModel = (color: string | Color): ColorModel => typeof color === 'string' - ? getColorModelFromString(color) - : getColorModelFromObject(color); - -//---Convert a color string to an RGB object -export const getRGBObjectFromString = { - [ColorModel.HEX](color: string): RGBObject { - const colorStr = !~COLOR_KEYS.indexOf(color) - ? color - : ColorKeywords[color as keyof typeof ColorKeywords]; - return new HEXStringParser(colorStr).rgb; - }, - [ColorModel.RGB](color: string): RGBObject { - return new RGBStringParser(color, getRGBObject).rgb; - }, - [ColorModel.HSL](color: string): RGBObject { - return new HSLStringParser(color, getRGBObject).rgb; - }, - [ColorModel.HWB](color: string): RGBObject { - return new HWBStringParser(color, getRGBObject).rgb; - }, - [ColorModel.CIELab](color: string): RGBObject { - return new CIELabStringParser(color, getRGBObject).rgb; - }, - [ColorModel.LCH](color: string): RGBObject { - return new LCHStringParser(color, getRGBObject).rgb; - }, - [ColorModel.CMYK](color: string): RGBObject { - return new CMYKStringParser(color).rgb; - } -}; - -//---Convert a color object to an RGB object -export const getRGBObjectFromObject = { - [ColorModel.HEX](color: RGBObjectGeneric): RGBObject { - const object: RGBObject = { - R: getBase255Number(`${color.R}`), - G: getBase255Number(`${color.G}`), - B: getBase255Number(`${color.B}`) - }; - if (hasProp(color, 'A')) { - object.A = Math.min(getBase255Number(`${color.A}`, true), 1); - } - return object; - }, - [ColorModel.RGB](color: RGBObjectGeneric): RGBObject { - return this.HEX(color); - }, - [ColorModel.HSL](color: HSLObjectGeneric): RGBObject { - const S = percent(`${color.S}`); - const L = percent(`${color.L}`); - const RGB = hslToRgb(normalizeHue(color.H), S, L); - if (hasProp(color, 'A')) { - RGB.A = normalizeAlpha(color.A); - } - return RGB; - }, - [ColorModel.HWB](color: HWBObjectGeneric): RGBObject { - const W = percent(`${color.W}`); - const B = percent(`${color.B}`); - const RGB = hwbToRgb(normalizeHue(color.H), W, B); - if (hasProp(color, 'A')) { - RGB.A = normalizeAlpha(color.A); - } - return RGB; - }, - [ColorModel.CIELab](color: CIELabObjectGeneric): RGBObject { - const L = percent(`${color.L}`); - const a = getBase125Number(`${color.a}`); - const b = getBase125Number(`${color.b}`); - const RGB = labToRgb(L, a, b); - if (hasProp(color, 'A')) { - RGB.A = normalizeAlpha(color.A); - } - return RGB; - }, - [ColorModel.LCH](color: LCHObjectGeneric): RGBObject { - const L = percent(`${color.L}`); - const C = getBase150Number(`${color.C}`); - const H = normalizeHue(`${color.H}`); - const RGB = lchToRgb(L, C, H); - if (hasProp(color, 'A')) { - RGB.A = normalizeAlpha(color.A); - } - return RGB; - }, - [ColorModel.CMYK](color: CMYKObjectGeneric): RGBObject { - const C = getCMYKNumber(`${color.C}`); - const M = getCMYKNumber(`${color.M}`); - const Y = getCMYKNumber(`${color.Y}`); - const K = getCMYKNumber(`${color.K}`); - const RGB = cmykToRgb(C, M, Y, K); - if (hasProp(color, 'A')) { - RGB.A = normalizeAlpha(color.A); - } - return RGB; - } -}; - -export const getRGBObject = (color: ColorInput, model: ColorModel = getColorModel(color)): RGBObject => { - return typeof color === 'string' - ? getRGBObjectFromString[model](color) - : getRGBObjectFromObject[model]( - color as ( - RGBObjectGeneric & - HSLObjectGeneric & - HWBObjectGeneric & - CIELabObjectGeneric & - LCHObjectGeneric & - CMYKObjectGeneric - ) - ); -}; - -export const getOptionsFromColorInput = (options: InputOptions, ...colors: ColorInput[]): Options => { - const cssColors: string[] = []; - const anglesUnits: AnglesUnitEnum[] = []; - const rgbColors: boolean[] = []; - const labColors: boolean[] = []; - const lchColors: boolean[] = []; - const cmykColors: boolean[] = []; - const alphaValues: boolean[] = []; - const anglesUnitValues = Object.values(AnglesUnitEnum); - const colorUnitValues = Object.values(ColorUnitEnum); - const cmykFunctionValues = Object.values(CMYKFunctionEnum); - - const matchOptions: MatchOptions = { - legacyCSS: 0, - spacesAfterCommas: 0, - cmykFunction: 0 - }; - - for(const color of colors) { - - if (typeof color === 'string') { - - cssColors.push(color); - - if (color.includes(',')){ - matchOptions.legacyCSS ++; - const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS); - if ( - new Set(commasWithNextCharacter).size === 1 && - SPACES.test(commasWithNextCharacter[0].slice(1)) - ) { - matchOptions.spacesAfterCommas ++; - } - } - - if (HSLStringParser.test(color)) { - const parser = new HSLStringParser(color, getRGBObject); - anglesUnits.push(parser.angleUnit); - alphaValues.push( - parser.hasPercentageAlpha - ); - continue; - } - - if (HWBStringParser.test(color)) { - const parser = new HWBStringParser(color, getRGBObject); - anglesUnits.push(parser.angleUnit); - alphaValues.push( - parser.hasPercentageAlpha - ); - continue; - } - - if (RGBStringParser.test(color)) { - const parser = new RGBStringParser(color, getRGBObject); - rgbColors.push( - parser.hasPercentageValues - ); - alphaValues.push( - parser.hasPercentageAlpha - ); - continue; - } - - if (CIELabStringParser.test(color)) { - const parser = new CIELabStringParser(color, getRGBObject); - labColors.push( - parser.hasPercentageValues - ); - alphaValues.push( - parser.hasPercentageAlpha - ); - continue; - } - - if (LCHStringParser.test(color)) { - const parser = new LCHStringParser(color, getRGBObject); - anglesUnits.push(parser.angleUnit); - lchColors.push( - parser.hasPercentageValues - ); - alphaValues.push( - parser.hasPercentageAlpha - ); - continue; - } - - if (CMYKStringParser.test(color)) { - const parser = new CMYKStringParser(color); - cmykColors.push( - parser.hasPercentageValues - ); - if (color.startsWith('cmyk')) { - matchOptions.cmykFunction ++; - } - alphaValues.push( - parser.hasPercentageAlpha - ); - } - - } - - } - return { - decimals: typeof options.decimals === TypeOf.NUMBER - ? options.decimals - : DEFAULT_OPTIONS.decimals, - legacyCSS: typeof options.legacyCSS === TypeOf.BOOLEAN - ? options.legacyCSS - : Boolean( - cssColors.length && - matchOptions.legacyCSS === cssColors.length - ) || DEFAULT_OPTIONS.legacyCSS, - spacesAfterCommas: typeof options.spacesAfterCommas === TypeOf.BOOLEAN - ? options.spacesAfterCommas - : Boolean( - cssColors.length && - matchOptions.spacesAfterCommas === cssColors.length - ) || DEFAULT_OPTIONS.spacesAfterCommas, - anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit) - ? options.anglesUnit as AnglesUnitEnum - : ( - new Set(anglesUnits).size === 1 - ? anglesUnits[0] - : DEFAULT_OPTIONS.anglesUnit - ), - rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit) - ? options.rgbUnit as ColorUnitEnum - : ( - new Set(rgbColors).size === 1 && rgbColors[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.rgbUnit - ), - labUnit: options.labUnit && colorUnitValues.includes(options.labUnit) - ? options.labUnit as ColorUnitEnum - : ( - new Set(labColors).size === 1 && labColors[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.labUnit - ), - lchUnit: options.lchUnit && colorUnitValues.includes(options.lchUnit) - ? options.lchUnit as ColorUnitEnum - : ( - new Set(lchColors).size === 1 && lchColors[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.lchUnit - ), - cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit) - ? options.cmykUnit as ColorUnitEnum - : ( - new Set(cmykColors).size === 1 && !cmykColors[0] - ? ColorUnitEnum.NONE - : DEFAULT_OPTIONS.cmykUnit - ), - alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit) - ? options.alphaUnit as ColorUnitEnum - : ( - new Set(alphaValues).size === 1 && alphaValues[0] - ? ColorUnitEnum.PERCENT - : DEFAULT_OPTIONS.alphaUnit - ), - cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction) - ? options.cmykFunction as CMYKFunctionEnum - : ( - cmykColors.length && cmykColors.length === matchOptions.cmykFunction - ? CMYKFunctionEnum.CMYK - : DEFAULT_OPTIONS.cmykFunction - ) - }; -}; \ No newline at end of file diff --git a/src/color/rgb.ts b/src/color/rgb.ts new file mode 100644 index 0000000..e94a0b4 --- /dev/null +++ b/src/color/rgb.ts @@ -0,0 +1,92 @@ +import { + ColorObject, + RGBObject +} from '@types'; +import { + cmykToRgb, + hslToRgb, + hwbToRgb, + labToRgb, + lchToRgb +} from '#color/translators'; +import { + isCIELabObject, + isCMYKObject, + isHSLObject, + isHWBObject, + isLCHObject, + isUndefined +} from '#utilities'; + +const getAlpha = (color: ColorObject): { A?: number} => { + if (isUndefined(color.A)) { + return {}; + } + return { + A: +color.A + }; +}; + +export const getRGB = (color: ColorObject): RGBObject => { + + const alpha = getAlpha(color); + + if (isHSLObject(color)) { + return { + ...hslToRgb( + color.H, + color.S, + color.L + ), + ...alpha + }; + } + + if (isHWBObject(color)) { + return { + ...hwbToRgb( + color.H, + color.W, + color.B + ), + ...alpha + }; + } + + if (isCIELabObject(color)) { + return { + ...labToRgb( + color.L, + color.a, + color.b + ), + ...alpha + }; + } + + if (isLCHObject(color)) { + return { + ...lchToRgb( + color.L, + color.C, + color.H + ), + ...alpha + }; + } + + if (isCMYKObject(color)) { + return { + ...cmykToRgb( + color.C, + color.M, + color.Y, + color.K + ), + ...alpha + }; + } + + return color as RGBObject; + +}; \ No newline at end of file diff --git a/src/color/rounders.ts b/src/color/rounders.ts deleted file mode 100644 index 0d495c1..0000000 --- a/src/color/rounders.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { - CIELabObject, - CMYKObject, - HSLObject, - HWBObject, - LCHObject -} from '@types'; -import { round } from '#helpers'; - -export const roundHSLObject = ( - color: HSLObject, - decimals: number -): HSLObject => { - return { - H: round(color.H, decimals), - S: round(color.S, decimals), - L: round(color.L, decimals) - }; -}; - -export const roundHWBObject = ( - color: HWBObject, - decimals: number -): HWBObject => { - return { - H: round(color.H, decimals), - W: round(color.W, decimals), - B: round(color.B, decimals) - }; -}; - -export const roundCIELabObject = ( - color: CIELabObject, - decimals: number -): CIELabObject => { - return { - L: round(color.L, decimals), - a: round(color.a, decimals), - b: round(color.b, decimals) - }; -}; - -export const roundLCHObject = ( - color: LCHObject, - decimals: number -): LCHObject => { - return { - L: round(color.L, decimals), - C: round(color.C, decimals), - H: round(color.H, decimals) - }; -}; - -export const roundCMYKObject = ( - color: CMYKObject, - decimals: number -): CMYKObject => { - return { - C: round(color.C, decimals), - M: round(color.M, decimals), - Y: round(color.Y, decimals), - K: round(color.K, decimals) - }; -}; \ No newline at end of file diff --git a/src/color/translators.ts b/src/color/translators.ts index 6a4fd81..8479564 100644 --- a/src/color/translators.ts +++ b/src/color/translators.ts @@ -15,7 +15,7 @@ import { normalizeHue, radians, round -} from '#helpers'; +} from '#utilities'; const MATRIX_LRGB_XYZ_D50: [ColorArray, ColorArray, ColorArray] = [ [0.4360747, 0.3850649, 0.1430804], @@ -320,9 +320,21 @@ export const hwbToRgb = (H: number, W: number, B: number): RGBObject => { export const cmykToRgb = (C: number, M: number, Y: number, K: number): RGBObject => { K = 1 - K; return { - R: round(BASE_255 * (1 - C) * K), - G: round(BASE_255 * (1 - M) * K), - B: round(BASE_255 * (1 - Y) * K) + R: minmax( + round(BASE_255 * (1 - C) * K), + 0, + BASE_255 + ), + G: minmax( + round(BASE_255 * (1 - M) * K), + 0, + BASE_255 + ), + B: minmax( + round(BASE_255 * (1 - Y) * K), + 0, + BASE_255 + ) }; }; diff --git a/src/color/utils.ts b/src/color/utils.ts deleted file mode 100644 index 572102b..0000000 --- a/src/color/utils.ts +++ /dev/null @@ -1,1013 +0,0 @@ -import { - CIELabObject, - CIELabObjectGeneric, - CIELabOutput, - CMYKObject, - ColorInput, - ColorInputWithoutCMYK, - ColorOutput, - HEXObject, - HEXOutput, - HSLObject, - HSLObjectGeneric, - HSLOutput, - HWBObject, - HWBObjectGeneric, - HWBOutput, - LCHObject, - LCHObjectGeneric, - LCHOutput, - Options, - RGBObject, - RGBObjectGeneric, - RGBOutput, - RGYBObject, - RYBObject -} from '@types'; -import { - BASE_255, - ColorModel, - Mix, - MixString -} from '#constants'; -import { - getHEX, - hasProp, - minmax, - normalizeAlpha, - normalizeHue, - round -} from '#helpers'; -import { - hslToRgb, - hueRyb, - rgbToCmyk, - rgbToHsl, - rgbToHwb, - rgbToLab, - rgbToLch, - rgbToRyb, - rybToRgb -} from '#color/translators'; -import { - getColorModel, - getRGBObject -} from './extractors'; -import { - roundCIELabObject, - roundCMYKObject, - roundHSLObject, - roundHWBObject, - roundLCHObject -} from './rounders'; -import { CSS } from '#color/css'; - -type HarmonyFunction = (color: HSLObject, mode: MixString) => HSLObject[]; - -//---Harmony -const harmony = ( - color: HSLObject, - angles: number[], - mode: MixString -): HSLObject[] => - angles.reduce( - (arr: HSLObject[], num: number): HSLObject[] => - ( - [ - ...arr, - { - ...color, - H: mode === Mix.ADDITIVE - ? normalizeHue(color.H + num) - : normalizeHue(hueRyb(hueRyb(color.H, false) + num, true)) - } - ] - ), [{...color}] - ); - -export const analogous = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [30, -30], mode); -export const complementary = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [180], mode); -export const splitComplementary = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [150, -150], mode); -export const triadic = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [120, -120], mode); -export const tetradic = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [60, -120, 180], mode); -export const square = (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [90, -90, 180], mode); - -//---Get the color values from an object -export const translateColor = { - - [ColorModel.HEX](color: RGBObject): HEXObject { - return { - R: getHEX(color.R), - G: getHEX(color.G), - B: getHEX(color.B) - }; - }, - - HEXA(color: RGBObject): HEXObject { - const RGB = translateColor.HEX(color); - RGB.A = hasProp(color, 'A') - ? getHEX(color.A * BASE_255) - : '0xFF'; - return RGB; - }, - - [ColorModel.RGB](color: RGBObject, decimals: number): RGBObject { - const RGB = roundRGBObject(color, decimals); - if (hasProp(RGB, 'A')) { - delete RGB.A; - } - return RGB; - }, - - RGBA(color: RGBObject, decimals: number): RGBObject { - const RGB = translateColor.RGB(color, decimals); - RGB.A = hasProp(color, 'A') - ? round(color.A) - : 1; - return RGB; - }, - - [ColorModel.HSL](color: RGBObject, decimals: number): HSLObject { - const HSL = rgbToHsl(color.R, color.G, color.B); - delete HSL.A; - return roundHSLObject(HSL, decimals); - }, - - HSLA(color: RGBObject, decimals: number): HSLObject { - const HSL = translateColor.HSL(color, decimals); - HSL.A = hasProp(color, 'A') - ? round(color.A, decimals) - : 1; - return HSL; - }, - - [ColorModel.HWB](color: RGBObject, decimals: number): HWBObject { - const HWB = rgbToHwb(color.R, color.G, color.B); - delete HWB.A; - return roundHWBObject(HWB, decimals); - }, - - HWBA(color: RGBObject, decimals: number): HWBObject { - const HWB = translateColor.HWB(color, decimals); - HWB.A = hasProp(color, 'A') - ? round(color.A, decimals) - : 1; - return HWB; - }, - - [ColorModel.CIELab](color: RGBObject, decimals: number): CIELabObject { - const Lab = rgbToLab(color.R, color.G, color.B); - return roundCIELabObject(Lab, decimals); - }, - - CIELabA(color: RGBObject, decimals: number): CIELabObject { - const Lab = translateColor.CIELab(color, decimals); - Lab.A = hasProp(color, 'A') - ? round(color.A, decimals) - : 1; - return Lab; - }, - - [ColorModel.LCH](color: RGBObject, decimals: number): LCHObject { - const lch = rgbToLch(color.R, color.G, color.B); - return roundLCHObject(lch, decimals); - }, - - LCHA(color: RGBObject, decimals: number): LCHObject { - const lch = translateColor.LCH(color, decimals); - lch.A = hasProp(color, 'A') - ? round(color.A, decimals) - : 1; - return lch; - }, - - [ColorModel.CMYK](color: RGBObject, decimals: number): CMYKObject { - return roundCMYKObject( - rgbToCmyk(color.R, color.G, color.B), - decimals - ); - }, - - CMYKA(color: RGBObject, decimals: number): CMYKObject { - const CMYK = translateColor.CMYK(color, decimals); - CMYK.A = hasProp(color, 'A') - ? round(color.A, decimals) - : 1; - return CMYK; - } -}; - -//---Blending -export const blend = (from: RGBObject, to: RGBObject, steps: number): RGBObject[] => { - const div = steps - 1; - const diffR = (to.R - from.R) / div; - const diffG = (to.G - from.G) / div; - const diffB = (to.B - from.B) / div; - const fromA = normalizeAlpha(from.A); - const toA = normalizeAlpha(to.A); - const diffA = (toA - fromA) / div; - return Array(steps).fill(null).map((__n, i): RGBObject => { - if (i === 0) { return from; } - if (i === div) { return to; } - return { - R: round(from.R + diffR * i), - G: round(from.G + diffG * i), - B: round(from.B + diffB * i), - A: round(fromA + diffA * i) - }; - }); -}; - -//---Shades -export const getColorMixture = ( - color: ColorInputWithoutCMYK, - steps: number, - shades: boolean, - options: Options -): ColorOutput[] => { - const model = getColorModel(color); - const isCSS = typeof color === 'string'; - const RGB = getRGBObject(color, model); - const hasAlpha = ( - (typeof color === 'string' && hasProp(RGB, 'A')) || - (typeof color !== 'string' && - hasProp< - | RGBObjectGeneric - | HSLObjectGeneric - | HWBObjectGeneric - | CIELabObjectGeneric - | LCHObjectGeneric - >(color, 'A')) - ); - const HSL: HSLObject = rgbToHsl(RGB.R, RGB.G, RGB.B, RGB.A); - if (!hasAlpha) delete HSL.A; - const increment = shades - ? HSL.L / (steps + 1) - : (100 - HSL.L) / (steps + 1); - const hslMap = Array(steps).fill(null).map((__n, i): HSLObject => ({ - ...HSL, - L: HSL.L + increment * (i + 1) * (1 - +shades * 2) - })); - switch(model) { - case ColorModel.HEX: - default: - return hslMap.map((HSLColor: HSLObject): HEXOutput => { - const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L); - if (hasAlpha) RGBColor.A = HSLColor.A; - return isCSS - ? hasAlpha - ? CSS.HEX( - { - ...RGBColor, - A: round(RGBColor.A * BASE_255) - } - ) - : CSS.HEX(RGBColor) - : hasAlpha - ? translateColor.HEXA(RGBColor) - : translateColor.HEX(RGBColor); - }); - case ColorModel.RGB: - return hslMap.map((HSLColor: HSLObject): RGBOutput => { - const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L); - if (hasAlpha) RGBColor.A = HSLColor.A; - return isCSS - ? CSS.RGB(RGBColor, options) - : hasAlpha - ? translateColor.RGBA(RGBColor, options.decimals) - : translateColor.RGB(RGBColor, options.decimals);; - }); - case ColorModel.HSL: - return hslMap.map((HSLColor: HSLObject): HSLOutput => { - return isCSS - ? CSS.HSL(HSLColor, options) - : hasAlpha - ? translateColor.HSLA( - { - ...hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L), - A: HSLColor.A - }, - options.decimals - ) - : translateColor.HSL( - hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L), - options.decimals - ); - }); - case ColorModel.HWB: - return hslMap.map((HSLColor: HSLObject): HWBOutput => { - const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L); - if (hasAlpha) RGBColor.A = HSLColor.A; - const hwb = hasAlpha - ? translateColor.HWBA(RGBColor, options.decimals) - : translateColor.HWB(RGBColor, options.decimals); - return isCSS - ? CSS.HWB(hwb, options) - : hwb; - }); - case ColorModel.CIELab: - return hslMap.map((HSLColor: HSLObject): CIELabOutput => { - const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L); - if (hasAlpha) RGBColor.A = HSLColor.A; - const lab = hasAlpha - ? translateColor.CIELabA(RGBColor, options.decimals) - : translateColor.CIELab(RGBColor, options.decimals); - return isCSS - ? CSS.CIELab(lab, options) - : lab; - }); - case ColorModel.LCH: - return hslMap.map((HSLColor: HSLObject): LCHOutput => { - const RGBColor = hslToRgb(HSLColor.H, HSLColor.S, HSLColor.L); - const LCHColor = rgbToLch(RGBColor.R, RGBColor.G, RGBColor.B); - if (hasAlpha) LCHColor.A = HSLColor.A; - return isCSS - ? CSS.LCH(LCHColor, options) - : hasAlpha - ? translateColor.LCHA( - { - ...RGBColor, - A: HSLColor.A - }, - options.decimals - ) - : translateColor.LCH( - RGBColor, - options.decimals - ); - }); - } -}; - -//---Harmony -export const colorHarmony = { - - buildHarmony( - color: ColorInputWithoutCMYK, - harmonyFunction: HarmonyFunction, - mode: MixString, - options: Options - ): ColorOutput[] { - const model = getColorModel(color); - const RGB = getRGBObject(color, model); - const HSL = rgbToHsl(RGB.R, RGB.G, RGB.B, RGB.A); - const hasAlpha = ( - (typeof color === 'string' && hasProp(RGB, 'A')) || - ( - typeof color !== 'string' && - hasProp< - | RGBObjectGeneric - | HSLObjectGeneric - | HWBObjectGeneric - | CIELabObjectGeneric - | LCHObjectGeneric - >(color, 'A') - ) - ); - const isCSS = typeof color === 'string'; - switch(model) { - case ColorModel.HEX: - default: - return hasAlpha - ? this.HEXA( - roundHSLObject(HSL, 0), - harmonyFunction, - mode, - isCSS - ) - : this.HEX( - roundHSLObject(HSL, 0), - harmonyFunction, - mode, - isCSS - ); - case ColorModel.HSL: - return hasAlpha - ? this.HSLA(HSL, harmonyFunction, mode, isCSS, options) - : this.HSL(HSL, harmonyFunction, mode, isCSS, options); - case ColorModel.HWB: - return hasAlpha - ? this.HWBA(HSL, harmonyFunction, mode, isCSS, options) - : this.HWB(HSL, harmonyFunction, mode, isCSS, options); - case ColorModel.RGB: - return hasAlpha - ? this.RGBA(HSL, harmonyFunction, mode, isCSS, options) - : this.RGB(HSL, harmonyFunction, mode, isCSS, options); - case ColorModel.CIELab: - return hasAlpha - ? this.CIELabA(HSL, harmonyFunction, mode, isCSS, options) - : this.CIELab(HSL, harmonyFunction, mode, isCSS, options); - case ColorModel.LCH: - return hasAlpha - ? this.LCHA(HSL, harmonyFunction, mode, isCSS, options) - : this.LCH(HSL, harmonyFunction, mode, isCSS, options); - } - }, - - [ColorModel.HEX]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean - ): HEXOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HEXOutput => ( - css - ? CSS.HEX( - hslToRgb(c.H, c.S, c.L) - ) - : translateColor.HEX( - hslToRgb(c.H, c.S, c.L) - ) - ) - ); - }, - - HEXA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean - ): HEXOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HEXOutput => ( - css - ? CSS.HEX( - { - ...hslToRgb(c.H, c.S, c.L), - A: normalizeAlpha(c.A) * BASE_255 - } - ) - : translateColor.HEXA({ - ...hslToRgb(c.H, c.S, c.L), - A: normalizeAlpha(c.A) - }) - ) - ); - }, - - [ColorModel.RGB]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): RGBOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): RGBOutput => ( - css - ? CSS.RGB( - hslToRgb(c.H, c.S, c.L), - options - ) - : translateColor.RGB( - hslToRgb(c.H, c.S, c.L), - options.decimals - ) - ) - ); - }, - - RGBA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): RGBOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): RGBOutput => ( - css - ? CSS.RGB( - { - ...hslToRgb(c.H, c.S, c.L), - A: normalizeAlpha(c.A) - }, - options - ) - : translateColor.RGBA( - { - ...hslToRgb(c.H, c.S, c.L), - A: normalizeAlpha(c.A) - }, - options.decimals - ) - ) - ); - }, - - [ColorModel.HSL]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): HSLOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HSLOutput => ( - css - ? CSS.HSL( - { - H: c.H, - S: c.S, - L: c.L - }, - options - ) - : translateColor.HSL( - hslToRgb(c.H, c.S, c.L), - options.decimals - ) - ) - ); - }, - - HSLA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): HSLOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HSLOutput => ( - css - ? CSS.HSL( - { - ...c, - A: normalizeAlpha(c.A) - }, - options - ) - : translateColor.HSLA( - { - ...hslToRgb(c.H, c.S, c.L), - A: normalizeAlpha(c.A) - }, - options.decimals - ) - ) - ); - }, - - [ColorModel.HWB]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): HWBOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HWBOutput => { - const rgb = hslToRgb(c.H, c.S, c.L); - const hwb = rgbToHwb(rgb.R, rgb.G, rgb.B); - return css - ? CSS.HWB( - { - H: hwb.H, - W: hwb.W, - B: hwb.B - }, - options - ) - : translateColor.HWB( - rgb, - options.decimals - ); - } - ); - }, - - HWBA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): HWBOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): HWBOutput => { - const rgb = hslToRgb(c.H, c.S, c.L); - const hwb = rgbToHwb(rgb.R, rgb.G, rgb.B); - return css - ? CSS.HWB( - { - ...hwb, - A: normalizeAlpha(c.A) - }, - options - ) - : translateColor.HWBA( - { - ...rgb, - A: normalizeAlpha(c.A) - }, - options.decimals - ); - } - ); - }, - - [ColorModel.CIELab]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): CIELabOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): CIELabOutput => { - const RGB = hslToRgb(c.H, c.S, c.L); - return ( - css - ? CSS.CIELab( - rgbToLab( - RGB.R, - RGB.G, - RGB.B - ), - options - ) - : translateColor.CIELab( - RGB, - options.decimals - ) - ); - } - ); - }, - - CIELabA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): CIELabOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): CIELabOutput => { - const RGB = hslToRgb(c.H, c.S, c.L); - return ( - css - ? CSS.CIELab( - { - ...rgbToLab( - RGB.R, - RGB.G, - RGB.B - ), - A: normalizeAlpha(c.A) - }, - options - ) - : translateColor.CIELabA( - { - ...RGB, - A: normalizeAlpha(c.A) - }, - options.decimals - ) - ); - } - ); - }, - - [ColorModel.LCH]( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): LCHOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): LCHOutput => { - const RGB = hslToRgb(c.H, c.S, c.L); - return ( - css - ? CSS.LCH( - rgbToLch( - RGB.R, - RGB.G, - RGB.B - ), - options - ) - : translateColor.LCH( - RGB, - options.decimals - ) - ); - } - ); - }, - - LCHA( - color: HSLObject, - harmonyFunction: HarmonyFunction, - mode: MixString, - css: boolean, - options: Options - ): LCHOutput[] { - const array = harmonyFunction(color, mode); - return array.map( - (c: HSLObject): LCHOutput => { - const RGB = hslToRgb(c.H, c.S, c.L); - return ( - css - ? CSS.LCH( - { - ...rgbToLch( - RGB.R, - RGB.G, - RGB.B - ), - A: normalizeAlpha(c.A) - }, - options - ) - : translateColor.LCHA( - { - ...RGB, - A: normalizeAlpha(c.A) - }, - options.decimals - ) - ); - } - ); - } -}; - -export const colorMixer = { - - mix(colors: ColorInput[], mode: MixString): RGBObject { - - const rgbMap = colors.map((color: ColorInput): RGBObject => { - const model = getColorModel(color); - return getRGBObject(color, model); - }); - - const rybMap = mode === Mix.SUBTRACTIVE - ? rgbMap.map((color: RGBObject): RYBObject => { - const RYB = rgbToRyb(color.R, color.G, color.B); - if (hasProp(color, 'A')) { - RYB.A = color.A; - } - return RYB; - }) - : null; - - function createMix(items: RGBObject[]): RGBObject; - function createMix(items: RYBObject[]): RYBObject; - function createMix(items: RGYBObject[]): RGYBObject { - const initial = mode === Mix.ADDITIVE - ? {R: 0, G: 0, B: 0, A: 0} - : {R: 0, Y: 0, B: 0, A: 0}; - return items.reduce((mix: RGYBObject, color: RGYBObject): RGYBObject => { - const colorA = hasProp(color, 'A') ? color.A : 1; - const common = { - R: Math.min(mix.R + color.R * colorA, BASE_255), - B: Math.min(mix.B + color.B * colorA, BASE_255), - A: 1 - (1 - colorA) * (1 - mix.A) - }; - const mixGY = 'G' in mix - ? mix.G - : mix.Y; - const colorGY = 'G' in color - ? color.G - : color.Y; - return { - ...common, - ...(mode === Mix.ADDITIVE - ? { G: Math.min(mixGY + colorGY * colorA, BASE_255) } - : { Y: Math.min(mixGY + colorGY * colorA, BASE_255) } - ) - }; - }, initial); - } - - let mix: RGBObject; - - if (mode === Mix.ADDITIVE) { - mix = createMix(rgbMap); - } else { - const RYB = createMix(rybMap); - mix = rybToRgb(RYB.R, RYB.Y, RYB.B); - mix.A = RYB.A; - } - - return { - R: round(mix.R), - G: round(mix.G), - B: round(mix.B), - A: minmax(mix.A, 0, 1) - }; - }, - [ColorModel.HEX]( - colors: ColorInput[], - mode: MixString, - css: CSS - ): R { - const mix = this.mix(colors, mode); - delete mix.A; - return ( - css - ? CSS.HEX(mix) - : translateColor.HEX(mix) - ) as R; - }, - HEXA( - colors: ColorInput[], - mode: MixString, - css: CSS - ): R { - const mix = this.mix(colors, mode); - mix.A = css - ? normalizeAlpha(mix.A) * BASE_255 - : normalizeAlpha(mix.A); - return ( - css - ? CSS.HEX(mix) - : translateColor.HEXA(mix) - ) as R; - }, - [ColorModel.RGB]( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - delete mix.A; - return ( - css - ? CSS.RGB(mix, options) - : translateColor.RGB(mix, options.decimals) - ) as R; - }, - RGBA( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - return ( - css - ? CSS.RGB(mix, options) - : translateColor.RGBA(mix, options.decimals) - ) as R; - }, - [ColorModel.HSL]( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const HSL = rgbToHsl(mix.R, mix.G, mix.B); - delete mix.A; - delete HSL.A; - return ( - css - ? CSS.HSL(HSL, options) - : translateColor.HSL(mix, options.decimals) - ) as R; - }, - HSLA( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const HSL = rgbToHsl(mix.R, mix.G, mix.B, mix.A); - return ( - css - ? CSS.HSL(HSL, options) - : translateColor.HSLA(mix, options.decimals) - ) as R; - }, - [ColorModel.HWB]( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const HWB = rgbToHwb(mix.R, mix.G, mix.B); - delete mix.A; - delete HWB.A; - return ( - css - ? CSS.HWB(HWB, options) - : translateColor.HWB(mix, options.decimals) - ) as R; - }, - HWBA( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const HWB = rgbToHwb(mix.R, mix.G, mix.B, mix.A); - return ( - css - ? CSS.HWB(HWB, options) - : translateColor.HWBA(mix, options.decimals) - ) as R; - }, - [ColorModel.CIELab]( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const Lab = rgbToLab(mix.R, mix.G, mix.B); - delete mix.A; - return ( - css - ? CSS.CIELab(Lab, options) - : translateColor.CIELab(mix, options.decimals) - ) as R; - }, - CIELabA( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const Lab = rgbToLab(mix.R, mix.G, mix.B); - Lab.A = mix.A; - return ( - css - ? CSS.CIELab(Lab, options) - : translateColor.CIELabA(mix, options.decimals) - ) as R; - }, - [ColorModel.LCH]( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const lch = rgbToLch(mix.R, mix.G, mix.B); - delete mix.A; - return ( - css - ? CSS.LCH(lch, options) - : translateColor.LCH(mix, options.decimals) - ) as R; - }, - LCHA( - colors: ColorInput[], - mode: MixString, - css: CSS, - options: Options - ): R { - const mix = this.mix(colors, mode); - const lch = rgbToLch(mix.R, mix.G, mix.B); - lch.A = mix.A; - return ( - css - ? CSS.LCH(lch, options) - : translateColor.LCHA(mix, options.decimals) - ) as R; - } -}; - -export const roundRGBObject = ( - color: RGBObject, - decimals: number -): RGBObject => { - const R = round(color.R, decimals); - const G = round(color.G, decimals); - const B = round(color.B, decimals); - return { - R, - G, - B, - ...( - hasProp(color, 'A') - ? { - A: round(color.A, decimals) - } - : {} - ) - }; -}; \ No newline at end of file diff --git a/src/constants/enums-strings.ts b/src/constants/enums-strings.ts deleted file mode 100644 index 3dfc7de..0000000 --- a/src/constants/enums-strings.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { Harmony, Mix } from './enums'; - -export type HarmonyString = `${Harmony}`; -export type MixString = `${Mix}`; \ No newline at end of file diff --git a/src/constants/enums.ts b/src/constants/enums.ts index 68a3996..1948be5 100644 --- a/src/constants/enums.ts +++ b/src/constants/enums.ts @@ -172,33 +172,3 @@ export enum ColorKeywords { 'yellowgreen' = '#9ACD32', 'rebeccapurple' = '#663399' } - -export const COLOR_KEYS = Object.keys(ColorKeywords); -export const COLOR_PROPS = { - HEX: ['R', 'G', 'B', 'A'], - RGB: ['R', 'G', 'B', 'A'], - HSL: ['H', 'S', 'L', 'A'], - HWB: ['H', 'W', 'B', 'A'], - CIELab: ['L', 'a', 'b', 'A'], - LCH: ['L', 'C', 'H', 'A'], - CMYK: ['C', 'M', 'Y', 'K', 'A'] -}; -export const VALID_COLOR_OBJECTS: Record = { - ABGR: ColorModel.RGB, - ABHW: ColorModel.HWB, - ACHL: ColorModel.LCH, - ACKMY: ColorModel.CMYK, - AHLS: ColorModel.HSL, - ALAB: ColorModel.CIELab, - BGR: ColorModel.RGB, - BHW: ColorModel.HWB, - CHL: ColorModel.LCH, - CKMY: ColorModel.CMYK, - HLS: ColorModel.HSL, - LAB: ColorModel.CIELab -}; - -export enum TypeOf { - NUMBER = 'number', - BOOLEAN = 'boolean' -} \ No newline at end of file diff --git a/src/constants/errors.ts b/src/constants/errors.ts deleted file mode 100644 index b327107..0000000 --- a/src/constants/errors.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const ERRORS = { - NOT_ACCEPTED_STRING_INPUT: 'The provided string color doesn\'t have a correct format', - NOT_ACCEPTED_OBJECT_INPUT: 'The provided color object doesn\'t have the proper keys or format', - NOT_A_VALID_RELATIVE_COLOR: 'is not a valid operation for a relative color' -}; \ No newline at end of file diff --git a/src/constants/index.ts b/src/constants/index.ts index 2d02536..b55f38c 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,6 +1,74 @@ -export * from './numbers'; -export * from './enums'; -export * from './enums-strings'; +import { + AnglesUnitEnum, + CMYKFunctionEnum, + ColorUnitEnum, + Options +} from '@types'; +import { + ColorKeywords, + ColorModel, + Harmony, + Mix +} from './enums'; + +export const MAX_DECIMALS = 6; +export const DEFAULT_BLEND_STEPS = 5; +export const DEFAULT_SHADES_TINTS_STEPS = 5; +export const BASE_255 = 255; +export const MAX_HUE = 360; +export const MAX_PCENT = 100; +export const MAX_ALPHA = 1; +export const MAX_LAB = 125; +export const MAX_LCH_C = 150; +export const GRADIANS = 10 / 9; + +export const COLOR_KEYS = Object.keys(ColorKeywords); + +export const COLOR_PROPS = Object.freeze({ + HEX: ['R', 'G', 'B', 'A'], + RGB: ['R', 'G', 'B', 'A'], + HSL: ['H', 'S', 'L', 'A'], + HWB: ['H', 'W', 'B', 'A'], + CIELab: ['L', 'a', 'b', 'A'], + LCH: ['L', 'C', 'H', 'A'], + CMYK: ['C', 'M', 'Y', 'K', 'A'] +}); + +export const VALID_COLOR_OBJECTS: Record = Object.freeze({ + ABGR: ColorModel.RGB, + ABHW: ColorModel.HWB, + ACHL: ColorModel.LCH, + ACKMY: ColorModel.CMYK, + AHLS: ColorModel.HSL, + ALAB: ColorModel.CIELab, + BGR: ColorModel.RGB, + BHW: ColorModel.HWB, + CHL: ColorModel.LCH, + CKMY: ColorModel.CMYK, + HLS: ColorModel.HSL, + LAB: ColorModel.CIELab +}); + +export type HarmonyString = `${Harmony}`; +export type MixString = `${Mix}`; + +export const DEFAULT_OPTIONS: Options = Object.freeze({ + decimals: MAX_DECIMALS, + legacyCSS: false, + spacesAfterCommas: false, + anglesUnit: AnglesUnitEnum.NONE, + rgbUnit: ColorUnitEnum.NONE, + labUnit: ColorUnitEnum.NONE, + lchUnit: ColorUnitEnum.NONE, + cmykUnit: ColorUnitEnum.PERCENT, + alphaUnit: ColorUnitEnum.NONE, + cmykFunction: CMYKFunctionEnum.DEVICE_CMYK +}); + +export const ERRORS = Object.freeze({ + NOT_ACCEPTED_INPUT: `The provided string color doesn't have a correct format`, + NOT_A_VALID_RELATIVE_COLOR: 'is not a valid operation for a relative color' +}); + export * from './regexps'; -export * from './errors'; -export * from './options'; \ No newline at end of file +export * from './enums'; \ No newline at end of file diff --git a/src/constants/numbers.ts b/src/constants/numbers.ts deleted file mode 100644 index 0abc1dc..0000000 --- a/src/constants/numbers.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const MAX_DECIMALS = 6; -export const DEFAULT_BLEND_STEPS = 5; -export const DEFAULT_SHADES_TINTS_STEPS = 5; -export const BASE_255 = 255; -export const MAX_HUE = 360; -export const MAX_PCENT = 100; -export const MAX_ALPHA = 1; -export const MAX_LAB = 125; -export const MAX_LCH_C = 150; diff --git a/src/constants/options.ts b/src/constants/options.ts deleted file mode 100644 index 7aaefe8..0000000 --- a/src/constants/options.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - AnglesUnitEnum, - CMYKFunctionEnum, - ColorUnitEnum, - Options -} from '@types'; -import { MAX_DECIMALS } from './numbers'; - -export const DEFAULT_OPTIONS: Options = { - decimals: MAX_DECIMALS, - legacyCSS: false, - spacesAfterCommas: false, - anglesUnit: AnglesUnitEnum.NONE, - rgbUnit: ColorUnitEnum.NONE, - labUnit: ColorUnitEnum.NONE, - lchUnit: ColorUnitEnum.NONE, - cmykUnit: ColorUnitEnum.PERCENT, - alphaUnit: ColorUnitEnum.NONE, - cmykFunction: CMYKFunctionEnum.DEVICE_CMYK -}; \ No newline at end of file diff --git a/src/css/index.ts b/src/css/index.ts new file mode 100644 index 0000000..a054fd8 --- /dev/null +++ b/src/css/index.ts @@ -0,0 +1,82 @@ +import { + AnglesUnitEnum, + Color, + ColorUnitEnum, + NumberOrString, + Options +} from '@types'; +import { + COLOR_PROPS, + TEMPLATE_VAR, + VALID_COLOR_OBJECTS +} from '#constants'; +import { + getOrderedArrayString, + round, + translateDegrees +} from '#utilities'; + +type Transformer = (value: NumberOrString, index?: number) => NumberOrString; + +export const getCSSComma = (withSpace: boolean): string => withSpace + ? ', ' + : ','; + +export const prepareColorForCss = ( + color: Color, + transformer: Transformer +): NumberOrString[] => { + const props = getOrderedArrayString(Object.keys(color)); + const model = VALID_COLOR_OBJECTS[props]; + const keys = COLOR_PROPS[model]; + return keys.reduce((result: NumberOrString[], key: keyof typeof color, index: number): NumberOrString[] => { + const value = color[key]; + if (typeof value !== 'undefined') { + result.push(transformer(value, index)); + } + return result; + }, []); +}; + +export const getResultFromCSSTemplate = (template: string, vars: NumberOrString[]): string => { + return template.replace(TEMPLATE_VAR, (__match: string, indexStr: string): string => { + const index = +indexStr - 1; + return `${vars[index]}`; + }); +}; + +export const getCSSAlpha = (value: number, options: Options, ignoreLegacy = false): NumberOrString => { + const { alphaUnit, legacyCSS, decimals } = options; + if ( + alphaUnit === ColorUnitEnum.PERCENT && + ( + !legacyCSS || + ignoreLegacy + ) + ) { + return `${round(value * 100, decimals)}%`; + } + return round(value, decimals); +}; + +export const buildCSSHueTransformer = (options: Options) => { + const { anglesUnit, decimals } = options; + return (value: number, index: number): NumberOrString => { + if ( + index === 0 && + anglesUnit !== AnglesUnitEnum.NONE + ) { + const translated = round( + translateDegrees( + value, + anglesUnit + ), + decimals + ); + return `${translated}${anglesUnit}`; + } + return index === 3 + ? getCSSAlpha(value, options) + : round(value, decimals); + }; +}; diff --git a/src/index.ts b/src/index.ts index 3cc1efc..e4cf600 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2194 +1,11 @@ -import { +export { CIELabObject, - CIELabObjectGeneric, CMYKObject, - ColorInput, - ColorInputWithoutCMYK, - ColorOutput, - HEXObject, HSLObject, - HSLObjectGeneric, HWBObject, - HWBObjectGeneric, InputOptions, LCHObject, - LCHObjectGeneric, - Options, RGBObject } from '@types'; -import { - BASE_255, - DEFAULT_BLEND_STEPS, - DEFAULT_SHADES_TINTS_STEPS, - Harmony, - HarmonyString, - MAX_ALPHA, - MAX_LAB, - MAX_LCH_C, - MAX_PCENT, - Mix, - MixString -} from '#constants'; -import { - cmykToRgb, - hslToRgb, - hwbToRgb, - labToLch, - labToRgb, - lchToLab, - lchToRgb, - rgbToCmyk, - rgbToHsl, - rgbToHwb, - rgbToLab, - rgbToLch -} from '#color/translators'; -import * as utils from '#color/utils'; -import { - getColorModel, - getOptionsFromColorInput, - getRGBObject -} from '#color/extractors'; -import { CSS } from '#color/css'; -import { - isHarmony, - isMix, - minmax, - normalizeHue, - round -} from '#helpers'; -import { - getBlendReturn, - getBlendReturnWithParameters, - getColorReturn, - getHarmonyReturn, - getMixReturn -} from '#returns'; - -const bindedMixers = Object.fromEntries( - Object.entries(utils.colorMixer).map((entry) => { - const [key, fn] = entry; - return [key, fn.bind(utils.colorMixer)]; - }) -) as typeof utils.colorMixer; - -export class ColorTranslator { - - // Constructor - public constructor(color: ColorInput, options: InputOptions = {}) { - this._options = getOptionsFromColorInput(options, color); - this.rgb = getRGBObject(color); - this.update('rgb'); - } - - // Private properties - private _options: Options; - private rgb: RGBObject; - private hsl: HSLObject; - private hwb: HWBObject; - private lab: CIELabObject; - private lch: LCHObject; - private cmyk: CMYKObject; - - // Private methods - private update(...exclude: ('rgb' | 'hsl' | 'hwb' | 'lab' | 'lch' | 'cmyk')[]): void { - if (!exclude.includes('rgb')) { - this.updateRGB(); - } - if (!exclude.includes('hsl')) { - this.updateHSL(); - } - if (!exclude.includes('hwb')) { - this.updateHWB(); - } - if (!exclude.includes('lab')) { - this.updateLAB(); - } - if (!exclude.includes('lch')) { - this.updateLCH(); - } - if (!exclude.includes('cmyk')) { - this.updateCMYK(); - } - } - - private updateRGB(): void { - this.rgb = { - ...hslToRgb( - this.hsl.H, - this.hsl.S, - this.hsl.L - ), - A: this.hsl.A - }; - } - - private updateHSL(): void { - this.hsl = rgbToHsl( - this.rgb.R, - this.rgb.G, - this.rgb.B, - this.rgb.A - ); - } - - private updateHWB(): void { - this.hwb = rgbToHwb( - this.rgb.R, - this.rgb.G, - this.rgb.B, - this.rgb.A - ); - } - - private updateLAB(): void { - this.lab = { - ...rgbToLab( - this.rgb.R, - this.rgb.G, - this.rgb.B - ), - A: this.rgb.A - }; - } - - private updateLCH(): void { - this.lch = { - ...rgbToLch( - this.rgb.R, - this.rgb.G, - this.rgb.B - ), - A: this.rgb.A - }; - } - - private updateCMYK(): void { - this.cmyk = rgbToCmyk( - this.rgb.R, - this.rgb.G, - this.rgb.B - ); - } - - private updateRGBFromHWB(): void { - this.rgb = { - ...hwbToRgb( - this.hwb.H, - this.hwb.W, - this.hwb.B - ), - A: this.rgb.A - }; - } - - private updateRGBFromLCH(): void { - this.rgb = { - ...lchToRgb( - this.lch.L, - this.lch.C, - this.lch.H - ), - A: this.rgb.A - }; - } - - private updateRGBFromCMYK(): void { - this.rgb = { - ...cmykToRgb( - this.cmyk.C, - this.cmyk.M, - this.cmyk.Y, - this.cmyk.K - ), - A: this.rgb.A - }; - } - - private updateRGBFromLAB(): void { - this.rgb = { - ...labToRgb( - this.lab.L, - this.lab.a, - this.lab.b - ), - A: this.rgb.A - }; - } - - private updateLCHFromLAB(): void { - this.lch = { - ...labToLch( - this.lab.L, - this.lab.a, - this.lab.b - ), - A: this.lab.A - }; - } - - private updateLABromLCH(): void { - this.lab = { - ...lchToLab( - this.lch.L, - this.lch.C, - this.lch.H - ), - A: this.lch.A - }; - } - - // Public options method - public setOptions(options: InputOptions = {}): ColorTranslator { - this._options = { - ...this._options, - ...options - } as Options; - return this; - } - - // Public RGB methods - public setR(R: number): ColorTranslator { - this.rgb.R = minmax(R, 0, BASE_255); - this.update('rgb'); - return; - } - - public setG(G: number): ColorTranslator { - this.rgb.G = minmax(G, 0, BASE_255); - this.update('rgb'); - return this; - } - - public setB(B: number): ColorTranslator { - this.rgb.B = minmax(B, 0, BASE_255); - this.update('rgb'); - return this; - } - - // Public HSL methods - public setH(H: number): ColorTranslator { - this.hsl.H = normalizeHue(H); - this.update('hsl'); - return this; - } - - public setS(S: number): ColorTranslator { - this.hsl.S = minmax(S, 0, MAX_PCENT); - this.update('hsl'); - return this; - } - - public setL(L: number): ColorTranslator { - this.hsl.L = minmax(L, 0, MAX_PCENT); - this.update('hsl'); - return this; - } - - // Public HWB methods - public setWhiteness(W: number): ColorTranslator { - this.hwb.W = minmax(W, 0, MAX_PCENT); - this.updateRGBFromHWB(); - this.update('rgb', 'hwb'); - return this; - } - - public setBlackness(B: number): ColorTranslator { - this.hwb.B = minmax(B, 0, MAX_PCENT); - this.updateRGBFromHWB(); - this.update('rgb', 'hwb'); - return this; - } - - // Public Lab methods - public setCIEL(L: number): ColorTranslator { - this.lab.L = minmax(L, 0, MAX_PCENT); - this.updateRGBFromLAB(); - this.updateLCHFromLAB(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - public setCIEa(a: number): ColorTranslator { - this.lab.a = minmax(a, -MAX_LAB, MAX_LAB); - this.updateRGBFromLAB(); - this.updateLCHFromLAB(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - public setCIEb(b: number): ColorTranslator { - this.lab.b = minmax(b, -MAX_LAB, MAX_LAB); - this.updateRGBFromLAB(); - this.updateLCHFromLAB(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - // Puclic LCH methods - public setLCHL(l: number): ColorTranslator { - this.lch.L = minmax(l, 0, MAX_PCENT); - this.updateRGBFromLCH(); - this.updateLABromLCH(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - public setLCHC(c: number): ColorTranslator { - this.lch.C = minmax(c, 0, MAX_LCH_C); - this.updateRGBFromLCH(); - this.updateLABromLCH(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - public setLCHH(h: number): ColorTranslator { - this.lch.H = normalizeHue(h); - this.updateRGBFromLCH(); - this.updateLABromLCH(); - this.update('rgb', 'lab', 'lch'); - return this; - } - - // Public alpha method - public setA(A: number): ColorTranslator { - const alpha = minmax(A, 0, MAX_ALPHA); - this.rgb.A = alpha; - this.hsl.A = alpha; - this.hwb.A = alpha; - this.lab.A = alpha; - this.lch.A = alpha; - this.cmyk.A = alpha; - return this; - } - - // Public CMYK methods - public setC(C: number): ColorTranslator { - this.cmyk.C = minmax(C, 0, 100); - this.updateRGBFromCMYK(); - this.update('cmyk'); - return this; - } - - public setM(M: number): ColorTranslator { - this.cmyk.M = minmax(M, 0, 100); - this.updateRGBFromCMYK(); - this.update('cmyk'); - return this; - } - - public setY(Y: number): ColorTranslator { - this.cmyk.Y = minmax(Y, 0, 100); - this.updateRGBFromCMYK(); - this.update('cmyk'); - return this; - } - - public setK(K: number): ColorTranslator { - this.cmyk.K = minmax(K, 0, 100); - this.updateRGBFromCMYK(); - this.update('cmyk'); - return this; - } - - // Public options property - public get options(): Options { - return this._options; - } - - // Public RGB properties - public get R(): number { - return round(this.rgb.R, this.options.decimals); - } - - public get G(): number { - return round(this.rgb.G, this.options.decimals); - } - - public get B(): number { - return round(this.rgb.B, this.options.decimals); - } - - // Public HSL properties - public get H(): number { - return round(this.hsl.H, this.options.decimals); - } - - public get S(): number { - return round(this.hsl.S, this.options.decimals); - } - - public get L(): number { - return round(this.hsl.L, this.options.decimals); - } - - // Public HWB properties - public get Whiteness(): number { - return round(this.hwb.W, this.options.decimals); - } - - public get Blackness(): number { - return round(this.hwb.B, this.options.decimals); - } - - // Public Lab properties - public get CIEL(): number { - return round(this.lab.L, this.options.decimals); - } - - public get CIEa(): number { - return round(this.lab.a, this.options.decimals); - } - - public get CIEb(): number { - return round(this.lab.b, this.options.decimals); - } - - // Pulic LCH properties - public get LCHL(): number { - return round(this.lch.L, this.options.decimals); - } - - public get LCHC(): number { - return round(this.lch.C, this.options.decimals); - } - - public get LCHH(): number { - return round(this.lch.H, this.options.decimals); - } - - // Public alpha property - public get A(): number { - return round(this.hsl.A, this.options.decimals); - } - - // Public CMYK properties - public get C(): number { - return round(this.cmyk.C, this.options.decimals); - } - - public get M(): number { - return round(this.cmyk.M, this.options.decimals); - } - - public get Y(): number { - return round(this.cmyk.Y, this.options.decimals); - } - - public get K(): number { - return round(this.cmyk.K, this.options.decimals); - } - - // Object public properties - public get HEXObject(): HEXObject { - return utils.translateColor.HEX(this.rgb); - } - - public get HEXAObject(): HEXObject { - return utils.translateColor.HEXA(this.rgb); - } - - public get RGBObject(): RGBObject { - return { - R: this.R, - G: this.G, - B: this.B - }; - } - - public get RGBAObject(): RGBObject { - return { - ...this.RGBObject, - A: this.A - }; - } - - public get HSLObject(): HSLObject { - return { - H: this.H, - S: this.S, - L: this.L - }; - } - - public get HSLAObject(): HSLObject { - return { - ...this.HSLObject, - A: this.A - }; - } - - public get HWBObject(): HWBObject { - return { - H: this.H, - W: this.Whiteness, - B: this.Blackness - }; - } - - public get HWBAObject(): HWBObject { - return { - ...this.HWBObject, - A: this.A - }; - } - - public get CIELabObject(): CIELabObject { - return { - L: this.CIEL, - a: this.CIEa, - b: this.CIEb - }; - } - - public get CIELabAObject(): CIELabObject { - return { - ...this.CIELabObject, - A: this.A - }; - } - - public get LCHObject(): LCHObject { - return { - L: this.LCHL, - C: this.LCHC, - H: this.LCHH - }; - } - - public get LCHAObject(): LCHObject { - return { - ...this.LCHObject, - A: this.A - }; - } - - public get CMYKObject(): CMYKObject { - return { - C: this.C, - M: this.M, - Y: this.Y, - K: this.K - }; - } - - public get CMYKAObject(): CMYKObject { - return { - ...this.CMYKObject, - A: this.A - }; - } - - // CSS public properties - public get HEX(): string { - return CSS.HEX({ - R: this.R, - G: this.G, - B: this.B - }); - } - - public get HEXA(): string { - return CSS.HEX({ - R: this.R, - G: this.G, - B: this.B, - A: this.A * BASE_255 - }); - } - - public get RGB(): string { - return CSS.RGB( - { - R: this.R, - G: this.G, - B: this.B - }, - this.options - ); - } - - public get RGBA(): string { - return CSS.RGB( - { - R: this.R, - G: this.G, - B: this.B, - A: this.A - }, - this.options - ); - } - - public get HSL(): string { - return CSS.HSL( - { - H: this.H, - S: this.S, - L: this.L - }, - this.options - ); - } - - public get HSLA(): string { - return CSS.HSL( - { - H: this.H, - S: this.S, - L: this.L, - A: this.A - }, - this.options - ); - } - - public get HWB(): string { - return CSS.HWB( - { - H: this.H, - W: this.Whiteness, - B: this.Blackness - }, - this.options - ); - } - - public get HWBA(): string { - return CSS.HWB( - { - H: this.H, - W: this.Whiteness, - B: this.Blackness, - A: this.A - }, - this.options - ); - } - - public get CIELab(): string { - return CSS.CIELab( - { - L: this.CIEL, - a: this.CIEa, - b: this.CIEb - }, - this.options - ); - } - - public get CIELabA(): string { - return CSS.CIELab( - { - L: this.CIEL, - a: this.CIEa, - b: this.CIEb, - A: this.A - }, - this.options - ); - } - - public get LCH(): string { - return CSS.LCH( - { - L: this.LCHL, - C: this.LCHC, - H: this.LCHH - }, - this.options - ); - } - - public get LCHA(): string { - return CSS.LCH( - { - L: this.LCHL, - C: this.LCHC, - H: this.LCHH, - A: this.A - }, - this.options - ); - } - - public get CMYK(): string { - return CSS.CMYK( - { - C: this.C, - M: this.M, - Y: this.Y, - K: this.K - }, - this.options - ); - } - - public get CMYKA(): string { - return CSS.CMYK( - { - C: this.C, - M: this.M, - Y: this.Y, - K: this.K, - A: this.A - }, - this.options - ); - } - - // Color Conversion Static Methods - public static toHEXObject(color: ColorInput): HEXObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - 0, - utils.translateColor.HEX - ); - } - - public static toHEX(color: ColorInput): string { - return CSS.HEX( - ColorTranslator.toHEXObject(color) - ); - } - - public static toHEXAObject(color: ColorInput): HEXObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - 0, - utils.translateColor.HEXA - ); - } - - public static toHEXA(color: ColorInput): string { - return CSS.HEX( - ColorTranslator.toHEXAObject(color) - ); - } - - public static toRGBObject(color: ColorInput, options: InputOptions = {}): RGBObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.RGB - ); - } - - public static toRGB(color: ColorInput, options: InputOptions = {}): string { - const rgb = ColorTranslator.toRGBObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.RGB(rgb, detectedOptions); - } - - public static toRGBAObject(color: ColorInput, options: InputOptions = {}): RGBObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.RGBA - ); - } - - public static toRGBA(color: ColorInput, options: InputOptions = {}): string { - const rgba = ColorTranslator.toRGBAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.RGB(rgba, detectedOptions); - } - - public static toHSLObject(color: ColorInput, options: InputOptions = {}): HSLObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.HSL - ); - } - - public static toHSL(color: ColorInput, options: InputOptions = {}): string { - const hsl = ColorTranslator.toHSLObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.HSL(hsl, detectedOptions); - } - - public static toHSLAObject(color: ColorInput, options: InputOptions = {}): HSLObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.HSLA - ); - } - - public static toHSLA(color: ColorInput, options: InputOptions = {}): string { - const hsla = ColorTranslator.toHSLAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.HSL(hsla, detectedOptions); - } - - public static toHWBObject(color: ColorInput, options: InputOptions = {}): HWBObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.HWB - ); - } - - public static toHWB(color: ColorInput, options: InputOptions = {}): string { - const hwb = ColorTranslator.toHWBObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.HWB(hwb, detectedOptions); - } - - public static toHWBAObject(color: ColorInput, options: InputOptions = {}): HWBObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.HWBA - ); - } - - public static toHWBA(color: ColorInput, options: InputOptions = {}): string { - const hwb = ColorTranslator.toHWBAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.HWB(hwb, detectedOptions); - } - - public static toCIELabObject(color: ColorInput, options: InputOptions = {}): CIELabObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.CIELab - ); - } - - public static toCIELab(color: ColorInput, options: InputOptions = {}): string { - const lab = ColorTranslator.toCIELabObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.CIELab(lab, detectedOptions); - } - - public static toCIELabAObject(color: ColorInput, options: InputOptions = {}): CIELabObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.CIELabA - ); - } - - public static toCIELabA(color: ColorInput, options: InputOptions = {}): string { - const lab = ColorTranslator.toCIELabAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.CIELab(lab, detectedOptions); - } - - public static toLCHObject(color: ColorInput, options: InputOptions = {}): LCHObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.LCH - ); - } - - public static toLCH(color: ColorInput, options: InputOptions = {}): string { - const lch = ColorTranslator.toLCHObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.LCH(lch, detectedOptions); - } - - public static toLCHAObject(color: ColorInput, options: InputOptions = {}): LCHObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.LCHA - ); - } - - public static toLCHA(color: ColorInput, options: InputOptions = {}): string { - const lch = ColorTranslator.toLCHAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.LCH(lch, detectedOptions); - } - - public static toCMYKObject(color: ColorInput, options: InputOptions = {}): CMYKObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.CMYK - ); - } - - public static toCMYK(color: ColorInput, options: InputOptions = {}): string { - const cmyk = ColorTranslator.toCMYKObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.CMYK(cmyk, detectedOptions); - } - - public static toCMYKAObject(color: ColorInput, options: InputOptions = {}): CMYKObject { - const model = getColorModel(color); - return getColorReturn( - color, - model, - options.decimals, - utils.translateColor.CMYKA - ); - } - - public static toCMYKA(color: ColorInput, options: InputOptions = {}): string { - const cmyka = ColorTranslator.toCMYKAObject(color, options); - const detectedOptions = getOptionsFromColorInput(options, color); - return CSS.CMYK(cmyka, detectedOptions); - } - - // Color Blending Static Methods - public static getBlendHEXObject( - from: ColorInput, - to: ColorInput, - steps: number = DEFAULT_BLEND_STEPS - ): HEXObject[] { - return getBlendReturn( - from, - to, - steps, - 0, - utils.translateColor.HEX - ); - } - - public static getBlendHEX( - from: ColorInput, - to: ColorInput, - steps: number = DEFAULT_BLEND_STEPS - ): string[] { - return ColorTranslator.getBlendHEXObject(from, to, steps) - .map((color: HEXObject): string => CSS.HEX(color)); - } - - public static getBlendHEXAObject( - from: ColorInput, - to: ColorInput, - steps: number = DEFAULT_BLEND_STEPS - ): HEXObject[] { - return getBlendReturn( - from, - to, - steps, - 0, - utils.translateColor.HEXA - ); - } - - public static getBlendHEXA( - from: ColorInput, - to: ColorInput, - steps: number = DEFAULT_BLEND_STEPS - ): string[] { - return ColorTranslator.getBlendHEXAObject(from, to, steps) - .map((color: HEXObject): string => CSS.HEX(color)); - } - - public static getBlendRGBObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): RGBObject[]; - public static getBlendRGBObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): RGBObject[]; - public static getBlendRGBObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): RGBObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.RGB - }); - } - - public static getBlendRGB( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendRGB( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendRGB( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.RGB, - cssFunction: CSS.RGB - }); - } - - public static getBlendRGBAObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): RGBObject[]; - public static getBlendRGBAObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): RGBObject[]; - public static getBlendRGBAObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): RGBObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.RGBA - }); - } - - public static getBlendRGBA( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendRGBA( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendRGBA( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.RGBA, - cssFunction: CSS.RGB - }); - } - - public static getBlendHSLObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): HSLObject[]; - public static getBlendHSLObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): HSLObject[]; - public static getBlendHSLObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): HSLObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HSL - }); - } - - public static getBlendHSL( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendHSL( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendHSL( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HSL, - cssFunction: CSS.HSL - }); - } - - public static getBlendHSLAObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): HSLObject[]; - public static getBlendHSLAObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): HSLObject[]; - public static getBlendHSLAObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): HSLObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HSLA - }); - } - - public static getBlendHSLA( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendHSLA( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendHSLA( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HSLA, - cssFunction: CSS.HSL - }); - } - - public static getBlendHWBObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): HWBObject[]; - public static getBlendHWBObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): HWBObject[]; - public static getBlendHWBObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): HWBObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HWB - }); - } - - public static getBlendHWB( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendHWB( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendHWB( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HWB, - cssFunction: CSS.HWB - }); - } - - public static getBlendHWBAObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): HWBObject[]; - public static getBlendHWBAObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): HWBObject[]; - public static getBlendHWBAObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): HWBObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HWBA - }); - } - - public static getBlendHWBA( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendHWBA( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendHWBA( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.HWBA, - cssFunction: CSS.HWB - }); - } - - public static getBlendCIELabObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): CIELabObject[]; - public static getBlendCIELabObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): CIELabObject[]; - public static getBlendCIELabObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): CIELabObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.CIELab - }); - } - - public static getBlendCIELab( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendCIELab( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendCIELab( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.CIELab, - cssFunction: CSS.CIELab - }); - } - - public static getBlendCIELabAObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): CIELabObject[]; - public static getBlendCIELabAObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): CIELabObject[]; - public static getBlendCIELabAObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): CIELabObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.CIELabA - }); - } - - public static getBlendCIELabA( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendCIELabA( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendCIELabA( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.CIELabA, - cssFunction: CSS.CIELab - }); - } - - public static getBlendLCHObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): LCHObject[]; - public static getBlendLCHObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): LCHObject[]; - public static getBlendLCHObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): LCHObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.LCH - }); - } - - public static getBlendLCH( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendLCH( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendLCH( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.LCH, - cssFunction: CSS.LCH - }); - } - - public static getBlendLCHAObject( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): LCHObject[]; - public static getBlendLCHAObject( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): LCHObject[]; - public static getBlendLCHAObject( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): LCHObject[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.LCHA - }); - } - - public static getBlendLCHA( - from: ColorInput, - to: ColorInput, - options?: InputOptions - ): string[]; - public static getBlendLCHA( - from: ColorInput, - to: ColorInput, - steps?: number, - options?: InputOptions - ): string[]; - public static getBlendLCHA( - from: ColorInput, - to: ColorInput, - thirdParameter?: number | InputOptions, - fourthParameter?: InputOptions - ): string[] { - return getBlendReturnWithParameters({ - from, - to, - thirdParameter, - fourthParameter, - translateFunction: utils.translateColor.LCHA, - cssFunction: CSS.LCH - }); - } - - // Color Mix Static Methods - public static getMixHEXObject(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): HEXObject { - return utils.colorMixer.HEX(colors, mode, false); - } - - public static getMixHEX(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): string { - return utils.colorMixer.HEX(colors, mode, true); - } - - public static getMixHEXAObject(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): HEXObject { - return utils.colorMixer.HEXA(colors, mode, false); - } - - public static getMixHEXA(colors: ColorInput[], mode: MixString = Mix.ADDITIVE): string { - return utils.colorMixer.HEXA(colors, mode, true); - } - - public static getMixRGBObject( - colors: ColorInput[], - options?: InputOptions - ): RGBObject; - public static getMixRGBObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): RGBObject; - public static getMixRGBObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): RGBObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.RGB, - css: false - }); - } - - public static getMixRGB( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixRGB( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixRGB( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.RGB, - css: true - }); - } - - public static getMixRGBAObject( - colors: ColorInput[], - options?: InputOptions - ): RGBObject; - public static getMixRGBAObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): RGBObject; - public static getMixRGBAObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): RGBObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.RGBA, - css: false - }); - } - - public static getMixRGBA( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixRGBA( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixRGBA( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.RGBA, - css: true - }); - } - - public static getMixHSLObject( - colors: ColorInput[], - options?: InputOptions - ): HSLObject; - public static getMixHSLObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): HSLObject; - public static getMixHSLObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): HSLObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HSL, - css: false - }); - } - - public static getMixHSL( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixHSL( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixHSL( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HSL, - css: true - }); - } - - public static getMixHSLAObject( - colors: ColorInput[], - options?: InputOptions - ): HSLObject; - public static getMixHSLAObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): HSLObject; - public static getMixHSLAObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): HSLObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HSLA, - css: false - }); - } - - public static getMixHSLA( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixHSLA( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixHSLA( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HSLA, - css: true - }); - } - - public static getMixHWBObject( - colors: ColorInput[], - options?: InputOptions - ): HWBObject; - public static getMixHWBObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): HWBObject; - public static getMixHWBObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): HWBObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HWB, - css: false - }); - } - - public static getMixHWB( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixHWB( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixHWB( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HWB, - css: true - }); - } - - public static getMixHWBAObject( - colors: ColorInput[], - options?: InputOptions - ): HWBObject; - public static getMixHWBAObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): HWBObject; - public static getMixHWBAObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): HWBObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HWBA, - css: false - }); - } - - public static getMixHWBA( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixHWBA( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixHWBA( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.HWBA, - css: true - }); - } - - public static getMixCIELabObject( - colors: ColorInput[], - options?: InputOptions - ): CIELabObject; - public static getMixCIELabObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): CIELabObject; - public static getMixCIELabObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): CIELabObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.CIELab, - css: false - }); - } - - public static getMixCIELab( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixCIELab( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixCIELab( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.CIELab, - css: true - }); - } - - public static getMixCIELabAObject( - colors: ColorInput[], - options?: InputOptions - ): CIELabObject; - public static getMixCIELabAObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): CIELabObject; - public static getMixCIELabAObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): CIELabObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.CIELabA, - css: false - }); - } - - public static getMixCIELabA( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixCIELabA( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixCIELabA( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.CIELabA, - css: true - }); - } - - public static getMixLCHObject( - colors: ColorInput[], - options?: InputOptions - ): LCHObject; - public static getMixLCHObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): LCHObject; - public static getMixLCHObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): LCHObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.LCH, - css: false - }); - } - - public static getMixLCH( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixLCH( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixLCH( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.LCH, - css: true - }); - } - - public static getMixLCHAObject( - colors: ColorInput[], - options?: InputOptions - ): LCHObject; - public static getMixLCHAObject( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): LCHObject; - public static getMixLCHAObject( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): LCHObject { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.LCHA, - css: false - }); - } - - public static getMixLCHA( - colors: ColorInput[], - options?: InputOptions - ): string; - public static getMixLCHA( - colors: ColorInput[], - mode?: MixString, - options?: InputOptions - ): string; - public static getMixLCHA( - colors: ColorInput[], - secondParameter?: MixString | InputOptions, - thirdParameter?: InputOptions - ): string { - return getMixReturn({ - colors, - secondParameter, - thirdParameter, - colorMixerFunction: bindedMixers.LCHA, - css: true - }); - } - - // Get shades static method - public static getShades(color: string, options?: InputOptions): string[]; - public static getShades(color: HEXObject, options?: InputOptions): HEXObject[]; - public static getShades(color: RGBObject, options?: InputOptions): RGBObject[]; - public static getShades(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; - public static getShades(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; - public static getShades(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; - public static getShades(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; - - public static getShades(color: string, shades?: number, options?: InputOptions): string[]; - public static getShades(color: HEXObject, shades?: number, options?: InputOptions): HEXObject[]; - public static getShades(color: RGBObject, shades?: number, options?: InputOptions): RGBObject[]; - public static getShades(color: HSLObjectGeneric, shades?: number, options?: InputOptions): HSLObject[]; - public static getShades(color: HWBObjectGeneric, shades?: number, options?: InputOptions): HWBObject[]; - public static getShades(color: CIELabObjectGeneric, shades?: number, options?: InputOptions): CIELabObject[]; - public static getShades(color: LCHObjectGeneric, shades?: number, options?: InputOptions): LCHObject[]; - - public static getShades( - color: ColorInputWithoutCMYK, - secondParameter?: number | InputOptions, - thirdParameter?: InputOptions - ): ColorOutput[] { - if (typeof secondParameter === 'number') { - return utils.getColorMixture( - color, - secondParameter, - true, - getOptionsFromColorInput( - thirdParameter || {}, - color - ) - ); - } - return utils.getColorMixture( - color, - DEFAULT_SHADES_TINTS_STEPS, - true, - getOptionsFromColorInput( - secondParameter || {}, - color - ) - ); - } - - // Get tints static method - public static getTints(color: string, options?: InputOptions): string[]; - public static getTints(color: HEXObject, options?: InputOptions): HEXObject[]; - public static getTints(color: RGBObject, options?: InputOptions): RGBObject[]; - public static getTints(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; - public static getTints(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; - public static getTints(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; - public static getTints(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; - - public static getTints(color: string, tints?: number, options?: InputOptions): string[]; - public static getTints(color: HEXObject, tints?: number, options?: InputOptions): HEXObject[]; - public static getTints(color: RGBObject, tints?: number, options?: InputOptions): RGBObject[]; - public static getTints(color: HSLObjectGeneric, tints?: number, options?: InputOptions): HSLObject[]; - public static getTints(color: HWBObjectGeneric, tints?: number, options?: InputOptions): HWBObject[]; - public static getTints(color: CIELabObjectGeneric, tints?: number, options?: InputOptions): CIELabObject[]; - public static getTints(color: LCHObjectGeneric, tints?: number, options?: InputOptions): LCHObject[]; - - public static getTints( - color: ColorInputWithoutCMYK, - secondParameter?: number | InputOptions, - thirdParameter?: InputOptions - ): ColorOutput[] { - if (typeof secondParameter === 'number') { - return utils.getColorMixture( - color, - secondParameter, - false, - getOptionsFromColorInput( - thirdParameter || {}, - color - ) - ); - } - return utils.getColorMixture( - color, - DEFAULT_SHADES_TINTS_STEPS, - false, - getOptionsFromColorInput( - secondParameter || {}, - color - ) - ); - } - - // Color Harmony Static Method - public static getHarmony(color: string, options?: InputOptions): string[]; - public static getHarmony(color: HEXObject, options?: InputOptions): HEXObject[]; - public static getHarmony(color: RGBObject, options?: InputOptions): RGBObject[]; - public static getHarmony(color: HSLObjectGeneric, options?: InputOptions): HSLObject[]; - public static getHarmony(color: HWBObjectGeneric, options?: InputOptions): HWBObject[]; - public static getHarmony(color: CIELabObjectGeneric, options?: InputOptions): CIELabObject[]; - public static getHarmony(color: LCHObjectGeneric, options?: InputOptions): LCHObject[]; - - public static getHarmony(color: string, mode?: MixString, options?: InputOptions): string[]; - public static getHarmony(color: HEXObject, mode?: MixString, options?: InputOptions): HEXObject[]; - public static getHarmony(color: RGBObject, mode?: MixString, options?: InputOptions): RGBObject[]; - public static getHarmony(color: HSLObjectGeneric, mode?: MixString, options?: InputOptions): HSLObject[]; - public static getHarmony(color: HWBObjectGeneric, mode?: MixString, options?: InputOptions): HWBObject[]; - public static getHarmony(color: CIELabObjectGeneric, mode?: MixString, options?: InputOptions): CIELabObject[]; - public static getHarmony(color: LCHObjectGeneric, mode?: MixString, options?: InputOptions): LCHObject[]; - - public static getHarmony(color: string, harmony?: Harmony, options?: InputOptions): string[]; - public static getHarmony(color: HEXObject, harmony?: Harmony, options?: InputOptions): HEXObject[]; - public static getHarmony(color: RGBObject, harmony?: Harmony, options?: InputOptions): RGBObject[]; - public static getHarmony(color: HSLObjectGeneric, harmony?: Harmony, options?: InputOptions): HSLObject[]; - public static getHarmony(color: HWBObjectGeneric, harmony?: Harmony, options?: InputOptions): HWBObject[]; - public static getHarmony(color: CIELabObjectGeneric, harmony?: Harmony, options?: InputOptions): CIELabObject[]; - public static getHarmony(color: LCHObjectGeneric, harmony?: Harmony, options?: InputOptions): LCHObject[]; - - public static getHarmony(color: string, harmony?: Harmony, mode?: MixString, options?: InputOptions): string[]; - public static getHarmony(color: HEXObject, harmony?: Harmony, mode?: MixString, options?: InputOptions): HEXObject[]; - public static getHarmony(color: RGBObject, harmony?: Harmony, mode?: MixString, options?: InputOptions): RGBObject[]; - public static getHarmony(color: HSLObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): HSLObject[]; - public static getHarmony(color: HWBObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): HWBObject[]; - public static getHarmony(color: CIELabObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): CIELabObject[]; - public static getHarmony(color: LCHObjectGeneric, harmony?: Harmony, mode?: MixString, options?: InputOptions): LCHObject[]; - - public static getHarmony( - color: ColorInputWithoutCMYK, - secondParam?: HarmonyString | MixString | InputOptions, - thirdParam?: MixString | InputOptions, - fourthParam?: InputOptions - ): ColorOutput[] { - if (isHarmony(secondParam)) { - return getHarmonyReturn( - secondParam, - color, - isMix(thirdParam) - ? thirdParam - : Mix.ADDITIVE, - getOptionsFromColorInput( - isMix(thirdParam) - ? (fourthParam || {}) - : thirdParam || {}, - color - ) - ); - } else if (isMix(secondParam)) { - return getHarmonyReturn( - Harmony.COMPLEMENTARY, - color, - secondParam, - getOptionsFromColorInput( - thirdParam as InputOptions || {}, - color - ) - ); - } - return getHarmonyReturn( - Harmony.COMPLEMENTARY, - color, - Mix.ADDITIVE, - getOptionsFromColorInput( - secondParam || {}, - color - ) - ); - } -} - -export { - InputOptions, - Harmony, - Mix, - HEXObject, - RGBObject, - HSLObject, - HWBObject, - CIELabObject, - LCHObject, - CMYKObject -}; \ No newline at end of file +export { Harmony, Mix } from '#constants'; +export { ColorTranslator } from '#classes/ColorTranslator'; \ No newline at end of file diff --git a/src/parsers/_CIELabStringParser.ts b/src/parsers/_CIELabStringParser.ts deleted file mode 100644 index 5475b1f..0000000 --- a/src/parsers/_CIELabStringParser.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { - CIELabRegExpMatchArray, - ParserGetRgbObject, - RGBObject -} from '@types'; -import { - COLORREGS, - MAX_ALPHA, - MAX_LAB, - MAX_PCENT, - PCENT -} from '#constants'; -import { - getBase125Number, - minmax, - normalizeAlpha, - percent -} from '#helpers'; -import { labToRgb, rgbToLab } from '#color/translators'; -import { CalcParser } from './_CalcParser'; -import { AlphaBaseClass } from './baseClasses/_AlphaBaseClass'; - -export class CIELabStringParser extends AlphaBaseClass { - - constructor(colorString: string, getRGBObject: ParserGetRgbObject) { - - super(); - - const match = colorString.match(COLORREGS.CIELab) as CIELabRegExpMatchArray; - const groups = match.groups; - - const { - // Lab values - L, - a, - b, - A, - // Relative values - from, - relative_L, - relative_a, - relative_b, - relative_A - } = groups; - - if (from) { - - const fromRGB = getRGBObject(from); - const fromLab = rgbToLab( - fromRGB.R, - fromRGB.G, - fromRGB.B - ); - const fromLabVars = { - l: fromLab.L, - a: fromLab.a, - b: fromLab.b, - alpha: fromRGB.A ?? 1 - }; - - const L = new CalcParser('l', relative_L, fromLabVars).result; - const a = new CalcParser('a', relative_a, fromLabVars).result; - const b = new CalcParser('b', relative_b, fromLabVars).result; - - const rgb = labToRgb( - minmax(L, 0, MAX_PCENT), - minmax(a, - MAX_LAB, MAX_LAB), - minmax(b, - MAX_LAB, MAX_LAB) - ); - - if (relative_A) { - const A = new CalcParser('alpha', relative_A, fromLabVars).result; - rgb.A = minmax(A, 0, MAX_ALPHA); - } - - this._rgb = rgb; - - } else { - - this._L = L; - this._A = a; - this._B = b; - this._a = A; - const rgb: RGBObject = labToRgb( - percent(this._L), - getBase125Number(this._A), - getBase125Number(this._B) - ); - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - this._rgb = rgb; - - } - } - - private _L: string; - private _A: string; - private _B: string; - - public get hasPercentageValues(): boolean { - return ( - PCENT.test(this._L) && - PCENT.test(this._A) && - PCENT.test(this._B) - ); - } - - static test(colorString: string): boolean { - return COLORREGS.CIELab.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/_CMYKStringParser.ts b/src/parsers/_CMYKStringParser.ts deleted file mode 100644 index c2a63aa..0000000 --- a/src/parsers/_CMYKStringParser.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { CMYKRegExpMatchArray, RGBObject } from '@types'; -import { COLORREGS, PCENT } from '#constants'; -import { getCMYKNumber, normalizeAlpha } from '#helpers'; -import { cmykToRgb } from '#color/translators'; -import { AlphaBaseClass } from './baseClasses/_AlphaBaseClass'; - -export class CMYKStringParser extends AlphaBaseClass { - - constructor(colorString: string) { - - super(); - - const match = colorString.match(COLORREGS.CMYK) as CMYKRegExpMatchArray; - const groups = match.groups; - this._c = groups.c_legacy ?? groups.c; - this._m = groups.m_legacy ?? groups.m; - this._y = groups.y_legacy ?? groups.y; - this._k = groups.k_legacy ?? groups.k; - this._a = groups.a_legacy ?? groups.a; - const rgb: RGBObject = cmykToRgb( - getCMYKNumber(this._c), - getCMYKNumber(this._m), - getCMYKNumber(this._y), - getCMYKNumber(this._k) - ); - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - this._rgb = rgb; - } - - private _c: string; - private _m: string; - private _y: string; - private _k: string; - - public get hasPercentageValues(): boolean { - return ( - PCENT.test(this._c) && - PCENT.test(this._m) && - PCENT.test(this._y) && - PCENT.test(this._k) - ); - } - - static test(colorString: string): boolean { - return COLORREGS.CMYK.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/_HEXStringParser.ts b/src/parsers/_HEXStringParser.ts deleted file mode 100644 index d77ada9..0000000 --- a/src/parsers/_HEXStringParser.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { RGBObject, HEXRegExpMatchArray } from '@types'; -import { BASE_255, COLORREGS } from '#constants'; -import { getDEC } from '#helpers'; -import { RgbClass } from './baseClasses/_RgbClass'; - -export class HEXStringParser extends RgbClass { - - constructor(colorString: string) { - - super(); - - const match = colorString.match(COLORREGS.HEX) as HEXRegExpMatchArray; - const groups = match.groups; - this._r = groups.r ?? groups.rr; - this._g = groups.g ?? groups.gg; - this._b = groups.b ?? groups.bb; - this._a = groups.a ?? groups.aa; - const rgb: RGBObject = { - R: getDEC(this._r), - G: getDEC(this._g), - B: getDEC(this._b) - }; - if (this._a !== undefined) { - rgb.A = getDEC(this._a) / BASE_255; - } - this._rgb = rgb; - } - - private _r: string; - private _g: string; - private _b: string; - private _a: string | undefined; - -} \ No newline at end of file diff --git a/src/parsers/_HSLStringParser.ts b/src/parsers/_HSLStringParser.ts deleted file mode 100644 index 40e22e0..0000000 --- a/src/parsers/_HSLStringParser.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { - HSLRegExpMatchArray, - ParserGetRgbObject, - RGBObject -} from '@types'; -import { - COLORREGS, - MAX_ALPHA, - MAX_HUE, - MAX_PCENT -} from '#constants'; -import { - minmax, - normalizeAlpha, - normalizeHue, - percent -} from '#helpers'; -import { hslToRgb, rgbToHsl } from '#color/translators'; -import { CalcParser } from './_CalcParser'; -import { HueBaseClass } from './baseClasses/_HueBaseClass'; - -export class HSLStringParser extends HueBaseClass { - - constructor(colorString: string, getRGBObject: ParserGetRgbObject) { - - super(); - - const match = colorString.match(COLORREGS.HSL) as HSLRegExpMatchArray; - const groups = match.groups; - - const { - // Legacy values - h_legacy, - s_legacy, - l_legacy, - a_legacy, - // HSL values - h, - s, - l, - a, - // Relative values - from, - relative_h, - relative_s, - relative_l, - relative_a - } = groups; - - if (from) { - - const fromRGB = getRGBObject(from); - const fromHSL = rgbToHsl( - fromRGB.R, - fromRGB.G, - fromRGB.B, - fromRGB.A - ); - const fromHSLVars = { - h: fromHSL.H, - s: fromHSL.S, - l: fromHSL.L, - alpha: fromHSL.A - }; - - const H = new CalcParser('h', relative_h, fromHSLVars).result; - const S = new CalcParser('s', relative_s, fromHSLVars).result; - const L = new CalcParser('l', relative_l, fromHSLVars).result; - - const rgb = hslToRgb( - minmax(H, 0, MAX_HUE), - minmax(S, 0, MAX_PCENT), - minmax(L, 0, MAX_PCENT) - ); - - if (relative_a) { - const A = new CalcParser('alpha', relative_a, fromHSLVars).result; - rgb.A = minmax(A, 0, MAX_ALPHA); - } - - this._rgb = rgb; - - } else { - - this._h = h_legacy ?? h; - this._s = s_legacy ?? s; - this._l = l_legacy ?? l; - this._a = a_legacy ?? a; - const rgb: RGBObject = hslToRgb( - normalizeHue(this._h), - percent(this._s), - percent(this._l) - ); - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - this._rgb = rgb; - - } - - } - - private _s: string; - private _l: string; - - static test(colorString: string): boolean { - return COLORREGS.HSL.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/_HWBStringParser.ts b/src/parsers/_HWBStringParser.ts deleted file mode 100644 index 6c1182f..0000000 --- a/src/parsers/_HWBStringParser.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { - HWBRegExpMatchArray, - ParserGetRgbObject, - RGBObject -} from '@types'; -import { - COLORREGS, - MAX_ALPHA, - MAX_HUE, - MAX_PCENT -} from '#constants'; -import { - minmax, - normalizeAlpha, - normalizeHue, - percent -} from '#helpers'; -import { hwbToRgb, rgbToHwb } from '#color/translators'; -import { CalcParser } from './_CalcParser'; -import { HueBaseClass } from './baseClasses/_HueBaseClass'; - -export class HWBStringParser extends HueBaseClass { - - constructor(colorString: string, getRGBObject: ParserGetRgbObject) { - - super(); - - const match = colorString.match(COLORREGS.HWB) as HWBRegExpMatchArray; - const groups = match.groups; - - const { - // HWB values - h, - w, - b, - a, - // Relative values - from, - relative_h, - relative_w, - relative_b, - relative_a - } = groups; - - if (from) { - - const fromRGB = getRGBObject(from); - const fromHWB = rgbToHwb( - fromRGB.R, - fromRGB.G, - fromRGB.B, - fromRGB.A - ); - const fromHWBVars = { - h: fromHWB.H, - w: fromHWB.W, - b: fromHWB.B, - alpha: fromHWB.A - }; - - const H = new CalcParser('h', relative_h, fromHWBVars).result; - const W = new CalcParser('w', relative_w, fromHWBVars).result; - const B = new CalcParser('b', relative_b, fromHWBVars).result; - - const rgb = hwbToRgb( - minmax(H, 0, MAX_HUE), - minmax(W, 0, MAX_PCENT), - minmax(B, 0, MAX_PCENT) - ); - - if (relative_a) { - const A = new CalcParser('alpha', relative_a, fromHWBVars).result; - rgb.A = minmax(A, 0, MAX_ALPHA); - } - - this._rgb = rgb; - - } else { - - this._h = h; - this._w = w; - this._b = b; - this._a = a; - const rgb: RGBObject = hwbToRgb( - normalizeHue(this._h), - percent(this._w), - percent(this._b) - ); - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - this._rgb = rgb; - - } - } - - private _w: string; - private _b: string; - - static test(colorString: string): boolean { - return COLORREGS.HWB.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/_LCHStringParser.ts b/src/parsers/_LCHStringParser.ts deleted file mode 100644 index 4955ead..0000000 --- a/src/parsers/_LCHStringParser.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { - LCHRegExpMatchArray, - ParserGetRgbObject, - RGBObject -} from '@types'; -import { - COLORREGS, - MAX_ALPHA, - MAX_LCH_C, - MAX_PCENT, - PCENT -} from '#constants'; -import { - getBase150Number, - minmax, - normalizeAlpha, - normalizeHue, - percent -} from '#helpers'; -import { lchToRgb, rgbToLch } from '#color/translators'; -import { CalcParser } from './_CalcParser'; -import { HueBaseClass } from './baseClasses/_HueBaseClass'; - -export class LCHStringParser extends HueBaseClass { - - constructor(colorString: string, getRGBObject: ParserGetRgbObject) { - - super(); - - const match = colorString.match(COLORREGS.LCH) as LCHRegExpMatchArray; - const groups = match.groups; - - const { - // LCH values - l, - c, - h, - a, - // Relative values - from, - relative_l, - relative_c, - relative_h, - relative_a - } = groups; - - if (from) { - - const fromRGB = getRGBObject(from); - const fromLCH = rgbToLch( - fromRGB.R, - fromRGB.G, - fromRGB.B - ); - const fromLCHVars = { - l: fromLCH.L, - c: fromLCH.C, - h: fromLCH.H, - alpha: fromRGB.A ?? 1 - }; - - const L = new CalcParser('l', relative_l, fromLCHVars).result; - const C = new CalcParser('c', relative_c, fromLCHVars).result; - const H = new CalcParser('h', relative_h, fromLCHVars).result; - - const rgb = lchToRgb( - minmax(L, 0, MAX_PCENT), - minmax(C, - MAX_LCH_C, MAX_LCH_C), - normalizeHue(H) - ); - - if (relative_a) { - const A = new CalcParser('alpha', relative_a, fromLCHVars).result; - rgb.A = minmax(A, 0, MAX_ALPHA); - } - - this._rgb = rgb; - - } else { - - this._l = l; - this._c = c; - this._h = h; - this._a = a; - const rgb: RGBObject = lchToRgb( - percent(this._l), - getBase150Number(this._c), - normalizeHue(this._h) - ); - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - this._rgb = rgb; - - } - } - - private _l: string; - private _c: string; - - public get hasPercentageValues(): boolean { - return ( - PCENT.test(this._l) && - PCENT.test(this._c) - ); - } - - static test(colorString: string): boolean { - return COLORREGS.LCH.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/_RGBStringParser.ts b/src/parsers/_RGBStringParser.ts deleted file mode 100644 index 0d99373..0000000 --- a/src/parsers/_RGBStringParser.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { - ParserGetRgbObject, - RGBObject, - RGBRegExpMatchArray -} from '@types'; -import { - BASE_255, - COLORREGS, - PCENT -} from '#constants'; -import { getBase255Number, normalizeAlpha } from '#helpers'; -import { CalcParser } from './_CalcParser'; -import { AlphaBaseClass } from './baseClasses/_AlphaBaseClass'; - -export class RGBStringParser extends AlphaBaseClass { - - constructor(colorString: string, getRGBObject: ParserGetRgbObject) { - - super(); - - const match = colorString.match(COLORREGS.RGB) as RGBRegExpMatchArray; - const groups = match.groups; - const { - // Legacy values - r_legacy, - g_legacy, - b_legacy, - a_legacy, - // RGB values - r, - g, - b, - a, - // Relative values - from, - relative_r, - relative_g, - relative_b, - relative_a - } = groups; - - if (from) { - - const fromRGB = getRGBObject(from); - const fromRGBVars = { - r: fromRGB.R, - g: fromRGB.G, - b: fromRGB.B, - alpha: fromRGB.A ?? 1 - }; - - const R = new CalcParser('r', relative_r, fromRGBVars).result; - const G = new CalcParser('g', relative_g, fromRGBVars).result; - const B = new CalcParser('b', relative_b, fromRGBVars).result; - - const rgb: RGBObject = { - R: Math.min( - R, - BASE_255 - ), - G: Math.min( - G, - BASE_255 - ), - B: Math.min( - B, - BASE_255 - ) - }; - - if (relative_a) { - const A = new CalcParser('alpha', relative_a, fromRGBVars).result; - rgb.A = Math.min(A, 1); - } - - this._rgb = rgb; - - } else { - - this._r = r_legacy ?? r; - this._g = g_legacy ?? g; - this._b = b_legacy ?? b; - this._a = a_legacy ?? a; - - const rgb: RGBObject = { - R: Math.min( - getBase255Number(this._r), - BASE_255 - ), - G: Math.min( - getBase255Number(this._g), - BASE_255 - ), - B: Math.min( - getBase255Number(this._b), - BASE_255 - ) - }; - - if (this._a !== undefined) { - rgb.A = normalizeAlpha(this._a); - } - - this._rgb = rgb; - - } - } - - private _r: string; - private _g: string; - private _b: string; - - public get hasPercentageValues(): boolean { - return ( - PCENT.test(this._r) && - PCENT.test(this._g) && - PCENT.test(this._b) - ); - } - - static test(colorString: string): boolean { - return COLORREGS.RGB.test(colorString); - } - -} \ No newline at end of file diff --git a/src/parsers/baseClasses/_AlphaBaseClass.ts b/src/parsers/baseClasses/_AlphaBaseClass.ts deleted file mode 100644 index 396a3c8..0000000 --- a/src/parsers/baseClasses/_AlphaBaseClass.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { PCENT } from '#constants'; -import { RgbClass } from './_RgbClass'; - -export class AlphaBaseClass extends RgbClass { - protected _a: string | undefined; - public get hasPercentageAlpha(): boolean { - return PCENT.test(this._a); - } -} \ No newline at end of file diff --git a/src/parsers/baseClasses/_HueBaseClass.ts b/src/parsers/baseClasses/_HueBaseClass.ts deleted file mode 100644 index 8d512b3..0000000 --- a/src/parsers/baseClasses/_HueBaseClass.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AnglesUnitEnum, AngleUnitRegExpMatchArray } from '@types'; -import { HSL_HUE } from '#constants'; -import { AlphaBaseClass } from './_AlphaBaseClass'; - -export class HueBaseClass extends AlphaBaseClass { - protected _h: string; - public get angleUnit(): AnglesUnitEnum { - if (this._h) { - const angleUnitMatch = this._h.match(HSL_HUE) as AngleUnitRegExpMatchArray; - const angleUnit = angleUnitMatch.groups.units; - return angleUnit === '' - ? AnglesUnitEnum.NONE - : angleUnit as AnglesUnitEnum; - } - return AnglesUnitEnum.NONE; - } -} \ No newline at end of file diff --git a/src/parsers/baseClasses/_RgbClass.ts b/src/parsers/baseClasses/_RgbClass.ts deleted file mode 100644 index 5fb21aa..0000000 --- a/src/parsers/baseClasses/_RgbClass.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { RGBObject } from '@types'; - -export class RgbClass { - protected _rgb: RGBObject; - public get rgb(): RGBObject { - return this._rgb; - } -} \ No newline at end of file diff --git a/src/parsers/index.ts b/src/parsers/index.ts index 04a494b..a29f8b4 100644 --- a/src/parsers/index.ts +++ b/src/parsers/index.ts @@ -1,7 +1,197 @@ -export { HEXStringParser } from './_HEXStringParser'; -export { RGBStringParser } from './_RGBStringParser'; -export { HSLStringParser } from './_HSLStringParser'; -export { HWBStringParser } from './_HWBStringParser'; -export { CIELabStringParser } from './_CIELabStringParser'; -export { LCHStringParser } from './_LCHStringParser'; -export { CMYKStringParser } from './_CMYKStringParser'; \ No newline at end of file +import { + AnglesUnitEnum, + CMYKFunctionEnum, + ColorInput, + ColorUnitEnum, + InputOptions, + MatchOptions, + Options +} from '@types'; +import { + ColorModel, + COMMAS_AND_NEXT_CHARS, + DEFAULT_OPTIONS, + SPACES +} from '#constants'; +import { + isBoolean, + isNumber, + isString +} from '#utilities'; +import { ColorParserContext } from '#classes/ColorParserContext'; +import { HEXParser } from '#classes/HEXParser'; +import { RGBParser } from '#classes/RGBParser'; +import { HSLParser } from '#classes/HSLParser'; +import { HWBParser } from '#classes/HWBParser'; +import { CIELabParser } from '#classes/CIELabParser'; +import { LCHParser } from '#classes/LCHParser'; +import { CMYKParser } from '#classes/CMYKParser'; + +export const hexParser = new HEXParser(); +export const rgbParser = new RGBParser(); +export const hslParser = new HSLParser(); +export const hwbParser = new HWBParser(); +export const cieLabParser = new CIELabParser(); +export const lchParser = new LCHParser(); +export const cmykParser = new CMYKParser(); + +export const colorParserContext = new ColorParserContext({ + [ColorModel.HEX]: hexParser, + [ColorModel.RGB]: rgbParser, + [ColorModel.HSL]: hslParser, + [ColorModel.HWB]: hwbParser, + [ColorModel.CIELab]: cieLabParser, + [ColorModel.LCH]: lchParser, + [ColorModel.CMYK]: cmykParser +}); + +export const getOptionsFromColorInput = (options: InputOptions, ...colors: ColorInput[]): Options => { + const cssColors: string[] = []; + const anglesUnits: AnglesUnitEnum[] = []; + const rgbColors: boolean[] = []; + const labColors: boolean[] = []; + const lchColors: boolean[] = []; + const cmykColors: boolean[] = []; + const alphaValues: boolean[] = []; + const anglesUnitValues = Object.values(AnglesUnitEnum); + const colorUnitValues = Object.values(ColorUnitEnum); + const cmykFunctionValues = Object.values(CMYKFunctionEnum); + + const matchOptions: MatchOptions = { + legacyCSS: 0, + spacesAfterCommas: 0, + cmykFunction: 0 + }; + + for(const color of colors) { + + if (isString(color)) { + + cssColors.push(color); + + if (color.includes(',')) { + matchOptions.legacyCSS ++; + const commasWithNextCharacter = color.match(COMMAS_AND_NEXT_CHARS); + if ( + new Set(commasWithNextCharacter).size === 1 && + SPACES.test(commasWithNextCharacter[0].slice(1)) + ) { + matchOptions.spacesAfterCommas ++; + } + } + + if (hslParser.supports(color)) { + const options = hslParser.getCSSOptions(color); + anglesUnits.push(options.angleUnit); + alphaValues.push(options.hasPercentageAlpha); + continue; + } + + if (hwbParser.supports(color)) { + const options = hwbParser.getCSSOptions(color); + anglesUnits.push(options.angleUnit); + alphaValues.push(options.hasPercentageAlpha); + continue; + } + + if (rgbParser.supports(color)) { + const options = rgbParser.getCSSOptions(color); + rgbColors.push(options.hasPercentageValues); + alphaValues.push(options.hasPercentageAlpha); + continue; + } + + if (cieLabParser.supports(color)) { + const options = cieLabParser.getCSSOptions(color); + labColors.push(options.hasPercentageValues); + alphaValues.push(options.hasPercentageAlpha); + continue; + } + + if (lchParser.supports(color)) { + const options = lchParser.getCSSOptions(color); + anglesUnits.push(options.angleUnit); + lchColors.push(options.hasPercentageValues); + alphaValues.push(options.hasPercentageAlpha); + continue; + } + + if (cmykParser.supports(color)) { + const options = cmykParser.getCSSOptions(color); + cmykColors.push(options.hasPercentageValues); + if (color.startsWith('cmyk')) { + matchOptions.cmykFunction ++; + } + alphaValues.push(options.hasPercentageAlpha); + } + + } + + } + return { + decimals: isNumber(options.decimals) + ? options.decimals + : DEFAULT_OPTIONS.decimals, + legacyCSS: isBoolean(options.legacyCSS) + ? options.legacyCSS + : Boolean( + cssColors.length && + matchOptions.legacyCSS === cssColors.length + ) || DEFAULT_OPTIONS.legacyCSS, + spacesAfterCommas: isBoolean(options.spacesAfterCommas) + ? options.spacesAfterCommas + : Boolean( + cssColors.length && + matchOptions.spacesAfterCommas === cssColors.length + ) || DEFAULT_OPTIONS.spacesAfterCommas, + anglesUnit: options.anglesUnit && anglesUnitValues.includes(options.anglesUnit) + ? options.anglesUnit as AnglesUnitEnum + : ( + new Set(anglesUnits).size === 1 + ? anglesUnits[0] + : DEFAULT_OPTIONS.anglesUnit + ), + rgbUnit: options.rgbUnit && colorUnitValues.includes(options.rgbUnit) + ? options.rgbUnit as ColorUnitEnum + : ( + new Set(rgbColors).size === 1 && rgbColors[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.rgbUnit + ), + labUnit: options.labUnit && colorUnitValues.includes(options.labUnit) + ? options.labUnit as ColorUnitEnum + : ( + new Set(labColors).size === 1 && labColors[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.labUnit + ), + lchUnit: options.lchUnit && colorUnitValues.includes(options.lchUnit) + ? options.lchUnit as ColorUnitEnum + : ( + new Set(lchColors).size === 1 && lchColors[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.lchUnit + ), + cmykUnit: options.cmykUnit && colorUnitValues.includes(options.cmykUnit) + ? options.cmykUnit as ColorUnitEnum + : ( + new Set(cmykColors).size === 1 && !cmykColors[0] + ? ColorUnitEnum.NONE + : DEFAULT_OPTIONS.cmykUnit + ), + alphaUnit: options.alphaUnit && colorUnitValues.includes(options.alphaUnit) + ? options.alphaUnit as ColorUnitEnum + : ( + new Set(alphaValues).size === 1 && alphaValues[0] + ? ColorUnitEnum.PERCENT + : DEFAULT_OPTIONS.alphaUnit + ), + cmykFunction: options.cmykFunction && cmykFunctionValues.includes(options.cmykFunction) + ? options.cmykFunction as CMYKFunctionEnum + : ( + cmykColors.length && cmykColors.length === matchOptions.cmykFunction + ? CMYKFunctionEnum.CMYK + : DEFAULT_OPTIONS.cmykFunction + ) + }; +}; diff --git a/src/returns/index.ts b/src/returns/index.ts index e1d5c6e..4460f86 100644 --- a/src/returns/index.ts +++ b/src/returns/index.ts @@ -1,174 +1,446 @@ import { - Color, ColorInput, ColorInputWithoutCMYK, - ColorOutput, + ColorObject, InputOptions, - Options, - RGBObject + RGBObject, + RYBObject, + RGYBObject, + HSLObject, + CMYKObjectGeneric, + CMYKObject } from '@types'; import { + BASE_255, ColorModel, DEFAULT_BLEND_STEPS, + DEFAULT_SHADES_TINTS_STEPS, Harmony, HarmonyString, Mix, MixString } from '#constants'; -import * as utils from '#color/utils'; -import { getOptionsFromColorInput, getRGBObject } from '#color/extractors'; +import { + isHarmony, + isNumber, + isString, + isMix, + isUndefined, + normalizeAlpha, + normalizeHue, + round +} from '#utilities'; +import { + hueRyb, + rgbToRyb, + rybToRgb +} from '#color/translators'; +import { getRGB } from '#color/rgb'; +import { colorParserContext, getOptionsFromColorInput } from '#parsers'; -export const getColorReturn = ( - color: ColorInput, - model: ColorModel, - decimals: number, - translateFunction: (color: Color, decimals: number) => T -): T => { - const rgbObject = getRGBObject(color, model); - return translateFunction(rgbObject, decimals); +//---Blending +const blend = (from: RGBObject, to: RGBObject, steps: number): RGBObject[] => { + const div = steps - 1; + const diffR = (to.R - from.R) / div; + const diffG = (to.G - from.G) / div; + const diffB = (to.B - from.B) / div; + const fromA = normalizeAlpha(from.A); + const toA = normalizeAlpha(to.A); + const diffA = (toA - fromA) / div; + return Array(steps).fill(null).map((__n, i): RGBObject => { + if (i === 0) { return from; } + if (i === div) { return to; } + return { + R: round(from.R + diffR * i), + G: round(from.G + diffG * i), + B: round(from.B + diffB * i), + A: round(fromA + diffA * i) + }; + }); }; -export const getBlendReturn = ( +export function getBlendReturn( + from: ColorInput, + to: ColorInput, + model: ColorModel, + css: false, + withAlpha?: boolean, + steps?: number, + options?: InputOptions +): T[]; +export function getBlendReturn( + from: ColorInput, + to: ColorInput, + model: ColorModel, + css: true, + withAlpha?: boolean, + steps?: number, + options?: InputOptions +): string[]; +export function getBlendReturn( from: ColorInput, to: ColorInput, - steps: number, - decimals: number, - translateFunction: (color: Color, decimals: number) => T -): T[] => { + model: ColorModel, + css: boolean, + withAlpha: boolean, + steps: number = DEFAULT_BLEND_STEPS, + options: InputOptions = {} +) { if (steps < 1) steps = DEFAULT_BLEND_STEPS; - const fromRGBObject = getRGBObject(from); - const toRGBObject = getRGBObject(to); - const blendArray = utils.blend(fromRGBObject, toRGBObject, steps); - return blendArray.map((color: RGBObject): T => { - return translateFunction(color, decimals); + const fromParsed = colorParserContext.parse(from); + const toParsed = colorParserContext.parse(to); + const fromRGBObject = getRGB(fromParsed); + const toRGBObject = getRGB(toParsed); + const blendArray = blend(fromRGBObject, toRGBObject, steps); + return blendArray.map((color: RGBObject) => { + if (css) { + return colorParserContext.convertCSS( + color, + model, + getOptionsFromColorInput( + options, + from, + to + ), + withAlpha + ); + } + return colorParserContext.convert( + color, + model, + options.decimals, + withAlpha + ); }); -}; - -interface GetBlendReturnObjectWithParameters{ - from: ColorInput; - to: ColorInput; - thirdParameter?: number | InputOptions; - fourthParameter?: InputOptions; - translateFunction: (color: Color, decimals: number) => T; } -interface GetBlendReturnStringWithParameters extends GetBlendReturnObjectWithParameters { - cssFunction?: (color: T, options: Options) => string; -} +export const getBlendReturnParams = ( + thirdParameter?: number | InputOptions, + fourthParameter?: InputOptions +): [number | undefined, InputOptions] => { + const stepsParameter = isNumber(thirdParameter) + ? thirdParameter + : undefined; + const optionsParameter = isNumber(thirdParameter) + ? fourthParameter + : thirdParameter; + return [ + stepsParameter, + optionsParameter + ]; +}; -export function getBlendReturnWithParameters( - params: GetBlendReturnObjectWithParameters -): T[]; -export function getBlendReturnWithParameters( - params: GetBlendReturnStringWithParameters -): string[]; -export function getBlendReturnWithParameters( - params: GetBlendReturnStringWithParameters -): T[] | string[] { - const { - from, - to, - thirdParameter, - fourthParameter, - translateFunction, - cssFunction - } = params; - const result = typeof thirdParameter === 'number' - ? getBlendReturn( - from, - to, - thirdParameter, - fourthParameter?.decimals, - translateFunction - ) - : getBlendReturn( - from, - to, - DEFAULT_BLEND_STEPS, - thirdParameter?.decimals, - translateFunction - ); - if (cssFunction) { - return result.map((color: T): string => cssFunction( +export function getMixReturn( + colors: ColorInput[], + model: ColorModel, + css?: false, + withAlpha?: boolean, + mode?: MixString, + options?: InputOptions +): T; +export function getMixReturn( + colors: ColorInput[], + model: ColorModel, + css: true, + withAlpha?: boolean, + mode?: MixString, + options?: InputOptions +): string; +export function getMixReturn( + colors: ColorInput[], + model: ColorModel, + css: boolean, + withAlpha: boolean, + mode: MixString = Mix.ADDITIVE, + options: InputOptions = {} +): T | string { + + const rgbMap = colors.map((color: ColorInput): RGBObject => { + return colorParserContext.convert( color, - getOptionsFromColorInput( - ( - typeof thirdParameter === 'number' - ? fourthParameter - : thirdParameter - ) ?? {}, - from, - to - ) - )); - } - return result; + ColorModel.RGB, + options.decimals, + withAlpha + ); + }); -} + const rybMap = mode === Mix.SUBTRACTIVE + ? rgbMap.map((color: RGBObject): RYBObject => { + const RYB = rgbToRyb(color.R, color.G, color.B); + if (!isUndefined(color.A)) { + RYB.A = color.A; + } + return RYB; + }) + : null; -interface GetMixReturn { - colors: ColorInput[]; - secondParameter?: MixString | InputOptions; - thirdParameter?: InputOptions; - colorMixerFunction: (color: ColorInput[], mix: MixString, isCSS: boolean, options: Options) => string; -} + function createMix(items: RGBObject[]): RGBObject; + function createMix(items: RYBObject[]): RYBObject; + function createMix(items: RGYBObject[]): RGYBObject { + const initial = mode === Mix.ADDITIVE + ? {R: 0, G: 0, B: 0, A: 0} + : {R: 0, Y: 0, B: 0, A: 0}; + return items.reduce((mix: RGYBObject, color: RGYBObject): RGYBObject => { + const colorA = isUndefined(color.A) + ? 1 + : color.A; + const common = { + R: Math.min(mix.R + color.R * colorA, BASE_255), + B: Math.min(mix.B + color.B * colorA, BASE_255), + A: 1 - (1 - colorA) * (1 - mix.A) + }; + const mixGY = 'G' in mix + ? mix.G + : mix.Y; + const colorGY = 'G' in color + ? color.G + : color.Y; + return { + ...common, + ...(mode === Mix.ADDITIVE + ? { G: Math.min(mixGY + colorGY * colorA, BASE_255) } + : { Y: Math.min(mixGY + colorGY * colorA, BASE_255) } + ) + }; + }, initial); + } -interface GetMixObjectReturn extends GetMixReturn { - css: false; -} + let mix: RGBObject; -interface GetMixCssReturn extends GetMixReturn { - css: true; -} + if (mode === Mix.ADDITIVE) { + mix = createMix(rgbMap); + } else { + const RYB = createMix(rybMap); + mix = rybToRgb(RYB.R, RYB.Y, RYB.B); + mix.A = RYB.A; + } -export function getMixReturn(params: GetMixObjectReturn): T; -export function getMixReturn(params: GetMixCssReturn): string; -export function getMixReturn( - params: GetMixObjectReturn | GetMixCssReturn -): T | string { - const { - colors, - secondParameter, - thirdParameter, - colorMixerFunction, - css - } = params; - const options = getOptionsFromColorInput( - ( - typeof secondParameter === 'string' - ? thirdParameter - : secondParameter - ) ?? {}, - ...colors - ); - if (typeof secondParameter === 'string') { - return colorMixerFunction( - colors, - secondParameter, - css, - options + if (css) { + return colorParserContext.convertCSS( + mix, + model, + getOptionsFromColorInput(options, ...colors), + withAlpha ); } - return colorMixerFunction( - colors, - Mix.ADDITIVE, - css, - options + + return colorParserContext.convert( + mix, + model, + options.decimals, + withAlpha ); +}; + +export const getMixReturnParameters = ( + secondParameter?: MixString | InputOptions, + thirdParameter?: InputOptions +): [MixString | undefined, InputOptions] => { + const modeParam = isString(secondParameter) + ? secondParameter + : undefined; + const optionsParam = isString(secondParameter) + ? thirdParameter + : secondParameter; + return [ + modeParam, + optionsParam + ]; +}; + +export function getShadesOrTintsReturn( + shades: boolean, + color: string, + steps?: number, + options?: InputOptions +): string[]; +export function getShadesOrTintsReturn>( + shades: boolean, + color: ColorInputWithoutCMYK, + steps?: number, + options?: InputOptions +): T[]; +export function getShadesOrTintsReturn>( + shades: boolean, + color: ColorInputWithoutCMYK, + steps = DEFAULT_SHADES_TINTS_STEPS, + options: InputOptions = {} +): T[] | string[] { + const isCSS = isString(color); + const parser = colorParserContext.getParser(color); + const model = parser.model; + const withAlpha = parser.hasAlpha(color); + const hsl = colorParserContext.convert( + color, + ColorModel.HSL, + undefined, + withAlpha + ) as HSLObject; + const increment = shades + ? hsl.L / (steps + 1) + : (100 - hsl.L) / (steps + 1); + const hslMap = Array.from(Array(steps)).map((__n, i): HSLObject => ({ + ...hsl, + L: hsl.L + increment * (i + 1) * (1 - +shades * 2) + })); + if (isCSS) { + return hslMap.map((hslColor: HSLObject): string => { + return colorParserContext.convertCSS( + hslColor, + model, + getOptionsFromColorInput(options, color), + withAlpha + ); + }); + } + return hslMap.map((hslColor: HSLObject): T => { + return colorParserContext.convert( + hslColor, + model, + options.decimals, + withAlpha + ); + }); } -export const getHarmonyReturn = ( - harmony: HarmonyString, +export const getShadesOrTintsReturnParameters = ( + secondParameter?: number | InputOptions, + thirdParameter?: InputOptions +): [number | undefined, InputOptions] => { + const stepsParam = isNumber(secondParameter) + ? secondParameter + : undefined; + const optionsParam = isNumber(secondParameter) + ? thirdParameter + : secondParameter; + return [ + stepsParam, + optionsParam + ]; +}; + +//---Harmony +const harmony = ( + color: HSLObject, + angles: number[], + mode: MixString +): HSLObject[] => + angles.reduce( + (arr: HSLObject[], num: number): HSLObject[] => { + return [ + ...arr, + { + ...color, + H: mode === Mix.ADDITIVE + ? normalizeHue(color.H + num) + : normalizeHue( + hueRyb( + hueRyb( + color.H, + false + ) + num, + true + ) + ) + } + ]; + }, + [{...color}] + ); + +type HarmonyFunction = (color: HSLObject, mode: MixString) => HSLObject[]; + +const HARMONIES = new Map<`${Harmony}`, HarmonyFunction>([ + [ + Harmony.ANALOGOUS, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [30, -30], mode) + ], + [ + Harmony.COMPLEMENTARY, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [180], mode) + ], + [ + Harmony.SPLIT_COMPLEMENTARY, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [150, -150], mode) + ], + [ + Harmony.TRIADIC, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [120, -120], mode) + ], + [ + Harmony.TETRADIC, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [60, -120, 180], mode) + ], + [ + Harmony.SQUARE, + (color: HSLObject, mode: MixString): HSLObject[] => harmony(color, [90, -90, 180], mode) + ] +]); + +export const getHarmonyReturn = >( color: ColorInputWithoutCMYK, + harmony: HarmonyString, mode: MixString, - options: Options -): ColorOutput[] => { - return ({ - [Harmony.ANALOGOUS]: utils.colorHarmony.buildHarmony(color, utils.analogous, mode, options), - [Harmony.COMPLEMENTARY]: utils.colorHarmony.buildHarmony(color, utils.complementary, mode, options), - [Harmony.SPLIT_COMPLEMENTARY]: utils.colorHarmony.buildHarmony(color, utils.splitComplementary, mode, options), - [Harmony.TRIADIC]: utils.colorHarmony.buildHarmony(color, utils.triadic, mode, options), - [Harmony.TETRADIC]: utils.colorHarmony.buildHarmony(color, utils.tetradic, mode, options), - [Harmony.SQUARE]: utils.colorHarmony.buildHarmony(color, utils.square, mode, options) - })[harmony]; + options: InputOptions = {} +): T[] | string[] => { + const harmonyFunction = HARMONIES.get(harmony); + const isCSS = isString(color); + const parser = colorParserContext.getParser(color); + const model = parser.model; + const withAlpha = parser.hasAlpha(color); + const hsl = colorParserContext.convert( + color, + ColorModel.HSL + ); + const array = harmonyFunction(hsl, mode); + if (isCSS) { + return array.map((harmonyColor: HSLObject): string => { + return colorParserContext.convertCSS( + harmonyColor, + model, + getOptionsFromColorInput(options, color), + withAlpha + ); + }); + } + return array.map( + (harmonyColor: HSLObject) => { + return colorParserContext.convert( + harmonyColor, + model, + options.decimals, + withAlpha + ); + } + ); +}; + +export const getHarmonyReturnParameters = ( + secondParam?: HarmonyString | MixString | InputOptions, + thirdParam?: MixString | InputOptions, + fourthParam?: InputOptions +): [HarmonyString, MixString, InputOptions | undefined] => { + if (isHarmony(secondParam)) { + return [ + secondParam, + isMix(thirdParam) + ? thirdParam + : Mix.ADDITIVE, + isMix(thirdParam) + ? fourthParam + : thirdParam + ]; + } + if (isMix(secondParam)) { + return [ + Harmony.COMPLEMENTARY, + secondParam, + thirdParam as InputOptions + ]; + } + return [ + Harmony.COMPLEMENTARY, + Mix.ADDITIVE, + secondParam + ]; }; \ No newline at end of file diff --git a/src/helpers/index.ts b/src/utilities/index.ts similarity index 69% rename from src/helpers/index.ts rename to src/utilities/index.ts index a706766..7706e99 100644 --- a/src/helpers/index.ts +++ b/src/utilities/index.ts @@ -1,26 +1,57 @@ import { AnglesUnitEnum, AngleUnitRegExpMatchArray, + CIELabObject, + CMYKObject, + Color, + HSLObject, + HWBObject, InputOptions, - NumberOrString + LCHObject, + NumberOrString, + RGBObject } from '@types'; import { BASE_255, + ColorModel, + GRADIANS, Harmony, HarmonyString, HEX, HSL_HUE, MAX_ALPHA, MAX_DECIMALS, + MAX_HUE, MAX_LAB, MAX_LCH_C, Mix, MixString, - PCENT + PCENT, + VALID_COLOR_OBJECTS } from '#constants'; -//---Has property -export const hasProp = (obj: T, prop: K): boolean => Object.prototype.hasOwnProperty.call(obj, prop); +//---Return an ordered string from an array values +export const getOrderedArrayString = (keys: string[]): string => [...keys].sort().join('').toUpperCase(); + +// Primitive predicates +export const isString = (input: unknown): input is string => typeof input === 'string'; +export const isNumber = (input: unknown): input is number => typeof input === 'number'; +export const isBoolean = (input: unknown): input is boolean => typeof input === 'boolean'; +export const isUndefined = (input: unknown): input is undefined => input === undefined; + +// Color predicates +export const getColorModel = (color: Color): ColorModel => { + return VALID_COLOR_OBJECTS[ + getOrderedArrayString(Object.keys(color)) + ]; +}; + +export const isRGBObject = (color: Color): color is RGBObject => getColorModel(color) === ColorModel.RGB; +export const isHSLObject = (color: Color): color is HSLObject => getColorModel(color) === ColorModel.HSL; +export const isHWBObject = (color: Color): color is HWBObject => getColorModel(color) === ColorModel.HWB; +export const isCIELabObject = (color: Color): color is CIELabObject => getColorModel(color) === ColorModel.CIELab; +export const isLCHObject = (color: Color): color is LCHObject => getColorModel(color) === ColorModel.LCH; +export const isCMYKObject = (color: Color): color is CMYKObject => getColorModel(color) === ColorModel.CMYK; //---Get percent number export const percentNumber = (percent: NumberOrString): number => { @@ -96,10 +127,15 @@ export const getBase150Number = (color: string): number => { }; //---Calculate a decimal 0-1 value from CMYK value -export const getCMYKNumber = (color: string): number => Math.min(PCENT.test(color) ? percentNumber(color) / 100 : +color, 1); - -//---Return an ordered string from an array values -export const getOrderedArrayString = (keys: string[]): string => [...keys].sort().join('').toUpperCase(); +export const getCMYKNumber = (color: string, base100: boolean): number => { + const value = PCENT.test(color) + ? percentNumber(color) + : +color; + if (base100) { + return Math.min(value * 100, 100); + } + return Math.min(value, 100); +}; //---Round value export const round = (value: NumberOrString, decimals = MAX_DECIMALS): number => { @@ -117,11 +153,9 @@ export const degrees = (radian: number): number => radian * 180 / Math.PI; export const radians = (degrees: number): number => degrees * Math.PI / 180; //---Normalize hue -const pi2 = 360; - export const normalizeHue = (hue: number | string): number => { - if (typeof hue === 'string') { + if (isString(hue)) { const matches = hue.match(HSL_HUE) as AngleUnitRegExpMatchArray; const groups = matches.groups; @@ -132,7 +166,7 @@ export const normalizeHue = (hue: number | string): number => { hue = round(degrees(value)); break; case AnglesUnitEnum.TURNS: - hue = round(value * pi2); + hue = round(value * MAX_HUE); break; case AnglesUnitEnum.GRADIANS: hue = round(9 / 10 * value); @@ -143,8 +177,8 @@ export const normalizeHue = (hue: number | string): number => { } } - if (hue > 360 || hue < 0) { - hue -= Math.floor(hue / pi2) * pi2; + if (hue >= MAX_HUE || hue < 0) { + hue -= Math.floor(hue / MAX_HUE) * MAX_HUE; } return hue; @@ -152,7 +186,7 @@ export const normalizeHue = (hue: number | string): number => { //---Normalize alpha export const normalizeAlpha = (alpha: number | string | undefined | null): number => { - if (typeof alpha === 'string') { + if (isString(alpha)) { if(PCENT.test(alpha)) { alpha = percentNumber(alpha) / 100; } else { @@ -171,10 +205,10 @@ export const translateDegrees = (degrees: number, units: `${AnglesUnitEnum}`): n hue = round(radians(degrees)); break; case AnglesUnitEnum.TURNS: - hue = round(degrees / pi2); + hue = round(degrees / MAX_HUE); break; case AnglesUnitEnum.GRADIANS: - hue = round(10 / 9 * degrees); + hue = round(GRADIANS * degrees); break; case AnglesUnitEnum.DEGREES: case AnglesUnitEnum.NONE: @@ -191,4 +225,15 @@ export const isHarmony = (param: HarmonyString | MixString | InputOptions): para export const isMix = (param: MixString | InputOptions): param is MixString => { return `${param}` in Mix; -}; \ No newline at end of file +}; + +export const getAngleUnit = (unit: string | undefined): AnglesUnitEnum => { + if (unit) { + const angleUnitMatch = unit.match(HSL_HUE) as AngleUnitRegExpMatchArray; + const angleUnit = angleUnitMatch.groups.units; + return angleUnit === '' + ? AnglesUnitEnum.NONE + : angleUnit as AnglesUnitEnum; + } + return AnglesUnitEnum.NONE; +}; diff --git a/tests/01 - instance-get-properties.test.ts b/tests/01 - instance-get-properties.test.ts index 482f92f..4ef2bef 100644 --- a/tests/01 - instance-get-properties.test.ts +++ b/tests/01 - instance-get-properties.test.ts @@ -34,12 +34,12 @@ COLORS.forEach((color): void => { // HEXObject it(`HEXObject property => ${JSON.stringify(color.HEXObject)}`, () => { - expect(instance.HEXObject).toMatchObject(color.HEXObject); + expect(instance.HEXObject).toEqual(color.HEXObject); }); // HEXAObject it(`HEXAObject property => ${JSON.stringify(color.HEXAObject)}`, () => { - expect(instance.HEXAObject).toMatchObject(color.HEXAObject); + expect(instance.HEXAObject).toEqual(color.HEXAObject); }); // RGB @@ -56,12 +56,12 @@ COLORS.forEach((color): void => { // RGBObject it(`RGBObject property => ${JSON.stringify(color.RGBObject)}`, () => { - expect(instance.RGBObject).toMatchObject(color.RGBObject); + expect(instance.RGBObject).toEqual(color.RGBObject); }); // RGBAObject it(`RGBAObject property => ${JSON.stringify(color.RGBAObject)}`, () => { - expect(instance.RGBAObject).toMatchObject(color.RGBAObject); + expect(instance.RGBAObject).toEqual(color.RGBAObject); }); // HSL @@ -78,12 +78,12 @@ COLORS.forEach((color): void => { // HSLObject it(`HSLObject property => ${JSON.stringify(color.HSLObject)}`, () => { - expect(instance.HSLObject).toMatchObject(color.HSLObject); + expect(instance.HSLObject).toEqual(color.HSLObject); }); // HSLAObject it(`HSLAObject property => ${JSON.stringify(color.HSLAObject)}`, () => { - expect(instance.HSLAObject).toMatchObject(color.HSLAObject); + expect(instance.HSLAObject).toEqual(color.HSLAObject); }); // HWB @@ -100,12 +100,12 @@ COLORS.forEach((color): void => { // HWBObject it(`HWBObject property => ${JSON.stringify(color.HWBObject)}`, () => { - expect(instance.HWBObject).toMatchObject(color.HWBObject); + expect(instance.HWBObject).toEqual(color.HWBObject); }); // HWBAObject it(`HWBAObject property => ${JSON.stringify(color.HWBAObject)}`, () => { - expect(instance.HWBAObject).toMatchObject(color.HWBAObject); + expect(instance.HWBAObject).toEqual(color.HWBAObject); }); // H @@ -188,12 +188,12 @@ CMYK_COLORS.forEach((color) => { // CMYKObject it(`CMYKObject property => ${JSON.stringify(color.CMYKIntObject100)}`, () => { - expect(instance.CMYKObject).toMatchObject(color.CMYKIntObject100); + expect(instance.CMYKObject).toEqual(color.CMYKIntObject100); }); // CMYKAObject it(`CMYKAObject property => ${JSON.stringify(color.CMYKIntObject100WithAlpha)}`, () => { - expect(instance.CMYKAObject).toMatchObject(color.CMYKIntObject100WithAlpha); + expect(instance.CMYKAObject).toEqual(color.CMYKIntObject100WithAlpha); }); // C @@ -252,16 +252,16 @@ LAB_AND_LCH_COLORS.forEach((color) => { expect(instanceKeywordPercentages.CIELab).toBe(color.CIELabInPrcentage); }); - it(`CIELabA property in percentages => ${ color.CIELabAInPrcentage }`, () => { - expect(instanceKeywordPercentages.CIELabA).toBe(color.CIELabAInPrcentage); + it(`CIELabA property in percentages => ${ color.CIELabAInPercentage }`, () => { + expect(instanceKeywordPercentages.CIELabA).toBe(color.CIELabAInPercentage); }); it(`CIELabObject property => ${ JSON.stringify(color.CIELabObject) }`, () => { - expect(instanceKeyword.CIELabObject).toMatchObject(color.CIELabObject); + expect(instanceKeyword.CIELabObject).toEqual(color.CIELabObject); }); it(`CIELabAObject property => ${ JSON.stringify(color.CIELabAObject) }`, () => { - expect(instanceKeyword.CIELabAObject).toMatchObject(color.CIELabAObject); + expect(instanceKeyword.CIELabAObject).toEqual(color.CIELabAObject); }); it(`CIEL property => ${ color.CIELabObject.L }`, () => { @@ -297,11 +297,11 @@ LAB_AND_LCH_COLORS.forEach((color) => { }); it(`LCHObject property => ${ JSON.stringify(color.LCHObject) }`, () => { - expect(instanceKeyword.LCHObject).toMatchObject(color.LCHObject); + expect(instanceKeyword.LCHObject).toEqual(color.LCHObject); }); it(`LCHAObject property => ${ JSON.stringify(color.LCHAObject) }`, () => { - expect(instanceKeyword.LCHAObject).toMatchObject(color.LCHAObject); + expect(instanceKeyword.LCHAObject).toEqual(color.LCHAObject); }); it(`LCHL property => ${ color.LCHObject.L }`, () => { @@ -318,4 +318,40 @@ LAB_AND_LCH_COLORS.forEach((color) => { }); + describe('CIELab and LCH round trip', () => { + + it('CIELab round trip', () => { + const instance = new ColorTranslator(color.CIELab); + const instancePercentages = new ColorTranslator(color.CIELabInPrcentage); + const instanceAlpha = new ColorTranslator(color.CIELabA); + const instanceAlphaPercentages = new ColorTranslator(color.CIELabAInPercentage); + const instanceObject = new ColorTranslator(color.CIELabObject); + const instanceAlphaObject = new ColorTranslator(color.CIELabAObject); + + expect(instance.CIELab).toBe(color.CIELab); + expect(instancePercentages.CIELab).toBe(color.CIELabInPrcentage); + expect(instanceAlpha.CIELabA).toBe(color.CIELabA); + expect(instanceAlphaPercentages.CIELabA).toBe(color.CIELabAInPercentage); + expect(instanceObject.CIELabObject).toEqual(color.CIELabObject); + expect(instanceAlphaObject.CIELabAObject).toEqual(color.CIELabAObject); + }); + + it('LCH round trip', () => { + const instance = new ColorTranslator(color.LCH); + const instancePercentages = new ColorTranslator(color.LCHInPercentage); + const instanceAlpha = new ColorTranslator(color.LCHA); + const instanceAlphaPercentages = new ColorTranslator(color.LCHAInPercentage); + const instanceObject = new ColorTranslator(color.LCHObject); + const instanceAlphaObject = new ColorTranslator(color.LCHAObject); + + expect(instance.LCH).toBe(color.LCH); + expect(instancePercentages.LCH).toBe(color.LCHInPercentage); + expect(instanceAlpha.LCHA).toBe(color.LCHA); + expect(instanceAlphaPercentages.LCHA).toBe(color.LCHAInPercentage); + expect(instanceObject.LCHObject).toEqual(color.LCHObject); + expect(instanceAlphaObject.LCHAObject).toEqual(color.LCHAObject); + }); + + }); + }); \ No newline at end of file diff --git a/tests/02 - instance-set-properties.test.ts b/tests/02 - instance-set-properties.test.ts index 0be8833..1199071 100644 --- a/tests/02 - instance-set-properties.test.ts +++ b/tests/02 - instance-set-properties.test.ts @@ -111,29 +111,29 @@ describe('ColorTranslator set instance properties', () => { expect(instance.A).toBe(0.5); expect(instance.HEX).toBe(TEST_COLORS.red.HEX); expect(instance.HEXA).toBe(TEST_COLORS.red.HEX + '80'); - expect(instance.HEXObject).toMatchObject(TEST_COLORS.red.HEXObject); - expect(instance.HEXAObject).toMatchObject({ + expect(instance.HEXObject).toEqual(TEST_COLORS.red.HEXObject); + expect(instance.HEXAObject).toEqual({ ...TEST_COLORS.red.HEXObject, A: '0x80' }); expect(instance.RGB).toBe(TEST_COLORS.red.RGB); expect(instance.RGBA).toBe(TEST_COLORS.red.RGBA.replace(REG, '$10.5$3')); - expect(instance.RGBObject).toMatchObject(TEST_COLORS.red.RGBObject); - expect(instance.RGBAObject).toMatchObject({ + expect(instance.RGBObject).toEqual(TEST_COLORS.red.RGBObject); + expect(instance.RGBAObject).toEqual({ ...TEST_COLORS.red.RGBObject, A: 0.5 }); expect(instance.HSL).toBe(TEST_COLORS.red.HSL); expect(instance.HSLA).toBe(TEST_COLORS.red.HSLA.replace(REG, '$10.5$3')); - expect(instance.HSLObject).toMatchObject(TEST_COLORS.red.HSLObject); - expect(instance.HSLAObject).toMatchObject({ + expect(instance.HSLObject).toEqual(TEST_COLORS.red.HSLObject); + expect(instance.HSLAObject).toEqual({ ...TEST_COLORS.red.HSLObject, A: 0.5 }); expect(instance.HWB).toBe(TEST_COLORS.red.HWB); expect(instance.HWBA).toBe(TEST_COLORS.red.HWBA.replace(REG, '$10.5$3')); - expect(instance.HWBObject).toMatchObject(TEST_COLORS.red.HWBObject); - expect(instance.HWBAObject).toMatchObject({ + expect(instance.HWBObject).toEqual(TEST_COLORS.red.HWBObject); + expect(instance.HWBAObject).toEqual({ ...TEST_COLORS.red.HWBObject, A: 0.5 }); diff --git a/tests/03 - static-color-conversion.test.ts b/tests/03 - static-color-conversion.test.ts index ae2002c..f380a11 100644 --- a/tests/03 - static-color-conversion.test.ts +++ b/tests/03 - static-color-conversion.test.ts @@ -32,7 +32,7 @@ COLORS.forEach((color): void => { }); it(`toHEXObject method from ${colorValueStr} => ${JSON.stringify(color.HEXObject)}`, () => { - expect(ColorTranslator.toHEXObject(colorValue)).toMatchObject(color.HEXObject); + expect(ColorTranslator.toHEXObject(colorValue)).toEqual(color.HEXObject); }); // toHEXA @@ -41,7 +41,7 @@ COLORS.forEach((color): void => { }); it(`toHEXAObject method from ${colorValueStr} => ${JSON.stringify(color.HEXAObject)}`, () => { - expect(ColorTranslator.toHEXAObject(colorValue)).toMatchObject(color.HEXAObject); + expect(ColorTranslator.toHEXAObject(colorValue)).toEqual(color.HEXAObject); }); // toRGB @@ -50,7 +50,7 @@ COLORS.forEach((color): void => { }); it(`toRGBObject method from ${colorValueStr} => ${JSON.stringify(color.RGBObject)}`, () => { - expect(ColorTranslator.toRGBObject(colorValue, options)).toMatchObject(color.RGBObject); + expect(ColorTranslator.toRGBObject(colorValue, options)).toEqual(color.RGBObject); }); // toRGBA @@ -59,7 +59,7 @@ COLORS.forEach((color): void => { }); it(`toRGBAObject method from ${colorValueStr} => ${JSON.stringify(color.RGBAObject)}`, () => { - expect(ColorTranslator.toRGBAObject(colorValue, options)).toMatchObject(color.RGBAObject); + expect(ColorTranslator.toRGBAObject(colorValue, options)).toEqual(color.RGBAObject); }); // toHSL @@ -68,7 +68,7 @@ COLORS.forEach((color): void => { }); it(`toHSLObject method from ${colorValueStr} => ${JSON.stringify(color.HSLObject)}`, () => { - expect(ColorTranslator.toHSLObject(colorValue, options)).toMatchObject(color.HSLObject); + expect(ColorTranslator.toHSLObject(colorValue, options)).toEqual(color.HSLObject); }); // toHSLA @@ -77,7 +77,7 @@ COLORS.forEach((color): void => { }); it(`toHSLAObject method from ${colorValueStr} => ${JSON.stringify(color.HSLAObject)}`, () => { - expect(ColorTranslator.toHSLAObject(colorValue, options)).toMatchObject(color.HSLAObject); + expect(ColorTranslator.toHSLAObject(colorValue, options)).toEqual(color.HSLAObject); }); // toHWB @@ -86,7 +86,7 @@ COLORS.forEach((color): void => { }); it(`toHWBObject method from ${colorValueStr} => ${JSON.stringify(color.HWBObject)}`, () => { - expect(ColorTranslator.toHWBObject(colorValue, options)).toMatchObject(color.HWBObject); + expect(ColorTranslator.toHWBObject(colorValue, options)).toEqual(color.HWBObject); }); // toHWBA @@ -95,7 +95,7 @@ COLORS.forEach((color): void => { }); it(`toHWBAObject method from ${colorValueStr} => ${JSON.stringify(color.HWBAObject)}`, () => { - expect(ColorTranslator.toHWBAObject(colorValue, options)).toMatchObject(color.HWBAObject); + expect(ColorTranslator.toHWBAObject(colorValue, options)).toEqual(color.HWBAObject); }); }); @@ -133,18 +133,18 @@ LAB_AND_LCH_COLORS.forEach((color) => { expect(ColorTranslator.toCIELabA(keyword, options)).toBe(color.CIELabA); }); - it(`toCIELabA with parcentages => ${ color.CIELabAInPrcentage }`, () => { + it(`toCIELabA with parcentages => ${ color.CIELabAInPercentage }`, () => { expect( ColorTranslator.toCIELabA(keyword, optionsWithPercentage) - ).toBe(color.CIELabAInPrcentage); + ).toBe(color.CIELabAInPercentage); }); it(`toCIELabObject => ${ JSON.stringify(color.CIELabObject) }`, () => { - expect(ColorTranslator.toCIELabObject(keyword, options)).toMatchObject(color.CIELabObject); + expect(ColorTranslator.toCIELabObject(keyword, options)).toEqual(color.CIELabObject); }); it(`toCIELabAObject => ${ JSON.stringify(color.CIELabAObject) }`, () => { - expect(ColorTranslator.toCIELabAObject(keyword, options)).toMatchObject(color.CIELabAObject); + expect(ColorTranslator.toCIELabAObject(keyword, options)).toEqual(color.CIELabAObject); }); // LCH @@ -169,11 +169,57 @@ LAB_AND_LCH_COLORS.forEach((color) => { }); it(`toLCHObject => ${ JSON.stringify(color.LCHObject) }`, () => { - expect(ColorTranslator.toLCHObject(keyword, options)).toMatchObject(color.LCHObject); + expect(ColorTranslator.toLCHObject(keyword, options)).toEqual(color.LCHObject); }); it(`toLCHAObject => ${ JSON.stringify(color.LCHAObject) }`, () => { - expect(ColorTranslator.toLCHAObject(keyword, options)).toMatchObject(color.LCHAObject); + expect(ColorTranslator.toLCHAObject(keyword, options)).toEqual(color.LCHAObject); + }); + + }); + + describe('CIELab and LCH static methods round trip', () => { + + it('CIELab round trip', () => { + expect( + ColorTranslator.toCIELab(color.CIELab) + ).toBe(color.CIELab); + expect( + ColorTranslator.toCIELab(color.CIELabInPrcentage) + ).toBe(color.CIELabInPrcentage); + expect( + ColorTranslator.toCIELabA(color.CIELabA) + ).toBe(color.CIELabA); + expect( + ColorTranslator.toCIELabA(color.CIELabAInPercentage) + ).toBe(color.CIELabAInPercentage); + expect( + ColorTranslator.toCIELabObject(color.CIELabObject) + ).toEqual(color.CIELabObject); + expect( + ColorTranslator.toCIELabAObject(color.CIELabAObject) + ).toEqual(color.CIELabAObject); + }); + + it('LCH round trip', () => { + expect( + ColorTranslator.toLCH(color.LCH) + ).toBe(color.LCH); + expect( + ColorTranslator.toLCH(color.LCHInPercentage) + ).toBe(color.LCHInPercentage); + expect( + ColorTranslator.toLCHA(color.LCHA) + ).toBe(color.LCHA); + expect( + ColorTranslator.toLCHA(color.LCHAInPercentage) + ).toBe(color.LCHAInPercentage); + expect( + ColorTranslator.toLCHObject(color.LCHObject) + ).toEqual(color.LCHObject); + expect( + ColorTranslator.toLCHAObject(color.LCHAObject) + ).toEqual(color.LCHAObject); }); }); @@ -193,7 +239,7 @@ COLORS.forEach((color): void => { expect(ColorTranslator.toHWBA(color.RGBObject, optionsNoDecimals)).toBe(color.HWBA); }); - it('Legacy conversion', () => { + it(' Legacy conversion', () => { expect(ColorTranslator.toRGB(color.HSLLegacy, optionsNoDecimals)).toBe(color.RGBLegacy); expect(ColorTranslator.toRGBA(color.HSLALegacy, optionsNoDecimals)).toBe(color.RGBALegacy); expect(ColorTranslator.toHSL(color.RGBALegacy, optionsNoDecimals)).toBe(color.HSLLegacy); @@ -218,7 +264,7 @@ CMYK_COLORS.forEach((color) => { }); it(`toCMYKObject method from ${colorValueStr} => ${JSON.stringify(color.CMYKIntObject100)}`, () => { - expect(ColorTranslator.toCMYKObject(colorValue, options)).toMatchObject(color.CMYKIntObject100); + expect(ColorTranslator.toCMYKObject(colorValue, options)).toEqual(color.CMYKIntObject100); }); // toCMYKA @@ -227,7 +273,7 @@ CMYK_COLORS.forEach((color) => { }); it(`toCMYKAObject method from ${colorValueStr} => ${JSON.stringify(color.CMYKIntObject100WithAlpha)}`, () => { - expect(ColorTranslator.toCMYKAObject(colorValue, options)).toMatchObject(color.CMYKIntObject100WithAlpha); + expect(ColorTranslator.toCMYKAObject(colorValue, options)).toEqual(color.CMYKIntObject100WithAlpha); }); it(`toCMYK method with decimals from ${colorValueStr}`, () => { @@ -256,6 +302,12 @@ CMYK_COLORS.forEach((color) => { }); + describe('Conversion from CMYK', () => { + expect(ColorTranslator.toHEX(colorValue)).toBe( + ColorTranslator.toHEX(color.RGB) + ); + }); + }); }); \ No newline at end of file diff --git a/tests/04 - relative-colors.test.ts b/tests/04 - relative-colors.test.ts index c9b5854..cac3a05 100644 --- a/tests/04 - relative-colors.test.ts +++ b/tests/04 - relative-colors.test.ts @@ -84,11 +84,11 @@ describe('Relative colors', () => { // RGB { input: 'rgb(from #FF0000 h s l)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'rgb(from rgb(255 0 0) r g b alpha)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { @@ -102,11 +102,11 @@ describe('Relative colors', () => { // HSL { input: 'hsl(from #FF0000 r g b)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'hsl(from hsl(0 100% 50%) h s l alpha)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'hsl(from hsl(0 100% 50%) h s calc(hsl * 2))', @@ -119,11 +119,11 @@ describe('Relative colors', () => { // HWB { input: 'hwb(from #FF0000 h s l)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'hwb(from hwb(0 0% 0%) h w b alpha)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'hwb(from hwb(0 0% 0%) calc(hwb - 50) w b)', @@ -136,11 +136,11 @@ describe('Relative colors', () => { // Lab { input: 'lab(from #FF0000 h w b)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'lab(from #FF0000 h w b alpha)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'lab(from #FF0000 l a calc(lab / 2))', @@ -153,11 +153,11 @@ describe('Relative colors', () => { // LCH { input: 'lch(from #FF0000 l a b)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'lch(from #FF0000 l c h alpha)', - error: ERRORS.NOT_ACCEPTED_STRING_INPUT + error: ERRORS.NOT_ACCEPTED_INPUT }, { input: 'lch(from #FF0000 l c calc(lch / 2))', diff --git a/tests/05 - config-options.test.ts b/tests/05 - config-options.test.ts index 7c73bab..56e9eb1 100644 --- a/tests/05 - config-options.test.ts +++ b/tests/05 - config-options.test.ts @@ -655,16 +655,16 @@ describe('ColorTranslator CSS config options autodetection', () => { const instancePercentage = new ColorTranslator('device-cmyk(100% 100% 100% 100%)'); - expect(instancePercentage.CMYK).toBe('device-cmyk(0% 0% 0% 100%)'); - expect(instancePercentage.CMYKA).toBe('device-cmyk(0% 0% 0% 100% / 1)'); + expect(instancePercentage.CMYK).toBe('device-cmyk(100% 100% 100% 100%)'); + expect(instancePercentage.CMYKA).toBe('device-cmyk(100% 100% 100% 100% / 1)'); const instanceNone = new ColorTranslator('device-cmyk(1 1 1 1)'); - expect(instanceNone.CMYK).toBe('device-cmyk(0 0 0 1)'); - expect(instanceNone.CMYKA).toBe('device-cmyk(0 0 0 1 / 1)'); + expect(instanceNone.CMYK).toBe('device-cmyk(1 1 1 1)'); + expect(instanceNone.CMYKA).toBe('device-cmyk(1 1 1 1 / 1)'); - expect(ColorTranslator.toCMYK('device-cmyk(100% 100% 100% 100% / 0.5)')).toBe('device-cmyk(0% 0% 0% 100%)'); - expect(ColorTranslator.toCMYKA('device-cmyk(1 1 1 1)')).toBe('device-cmyk(0 0 0 1 / 1)'); + expect(ColorTranslator.toCMYK('device-cmyk(100% 100% 100% 100% / 0.5)')).toBe('device-cmyk(100% 100% 100% 100%)'); + expect(ColorTranslator.toCMYKA('device-cmyk(1 1 1 1)')).toBe('device-cmyk(1 1 1 1 / 1)'); }); @@ -753,7 +753,7 @@ describe('ColorTranslator CSS config options autodetection', () => { } ); - expect(instanceWrong.options).toMatchObject(DEFAULT_OPTIONS); + expect(instanceWrong.options).toEqual(DEFAULT_OPTIONS); }); diff --git a/tests/06 - hex3.test.ts b/tests/06 - hex3.test.ts index 2af3385..f3595ca 100644 --- a/tests/06 - hex3.test.ts +++ b/tests/06 - hex3.test.ts @@ -25,8 +25,8 @@ HEX3.forEach((item: HexProps): void => { }); it('Object RGB', (): void => { - expect(ColorTranslator.toRGBObject(item[prop])).toMatchObject(item.RGBObject); - expect(ColorTranslator.toRGBObject(item.KEYWORD)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(item[prop])).toEqual(item.RGBObject); + expect(ColorTranslator.toRGBObject(item.KEYWORD)).toEqual(item.RGBObject); }); it('CSS RGBA', (): void => { @@ -37,8 +37,8 @@ HEX3.forEach((item: HexProps): void => { }); it('Object RGBA', (): void => { - expect(ColorTranslator.toRGBAObject(item[prop])).toMatchObject(item.RGBAObject); - expect(ColorTranslator.toRGBAObject(item.KEYWORD)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(item[prop])).toEqual(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(item.KEYWORD)).toEqual(item.RGBAObject); }); it('CSS HSL', (): void => { @@ -49,8 +49,8 @@ HEX3.forEach((item: HexProps): void => { }); it('Object HSL', (): void => { - expect(ColorTranslator.toHSLObject(item[prop])).toMatchObject(item.HSLObject); - expect(ColorTranslator.toHSLObject(item.KEYWORD)).toMatchObject(item.HSLObject); + expect(ColorTranslator.toHSLObject(item[prop])).toEqual(item.HSLObject); + expect(ColorTranslator.toHSLObject(item.KEYWORD)).toEqual(item.HSLObject); }); it('CSS HSLA', (): void => { @@ -61,8 +61,8 @@ HEX3.forEach((item: HexProps): void => { }); it('Object HSLA', (): void => { - expect(ColorTranslator.toHSLAObject(item[prop])).toMatchObject(item.HSLAObject); - expect(ColorTranslator.toHSLAObject(item.KEYWORD)).toMatchObject(item.HSLAObject); + expect(ColorTranslator.toHSLAObject(item[prop])).toEqual(item.HSLAObject); + expect(ColorTranslator.toHSLAObject(item.KEYWORD)).toEqual(item.HSLAObject); }); }); diff --git a/tests/07 - hsl.test.ts b/tests/07 - hsl.test.ts index 75426dc..6ba4c1c 100644 --- a/tests/07 - hsl.test.ts +++ b/tests/07 - hsl.test.ts @@ -20,11 +20,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HSLPercentages, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HSLPercentages, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HSLPercentages, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HSLPercentages, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHSL(HSLPercentages, options)).toBe(item.HSL); expect(ColorTranslator.toHSL(HSLPercentages, legacyOptions)).toBe(item.HSLLegacy); - expect(ColorTranslator.toHSLObject(HSLPercentages, options)).toMatchObject(item.HSLObject); + expect(ColorTranslator.toHSLObject(HSLPercentages, options)).toEqual(item.HSLObject); expect(ColorTranslator.toRGB(HSLPercentages)).toMatchSnapshot(); expect(ColorTranslator.toHSL(HSLPercentages)).toMatchSnapshot(); @@ -35,11 +35,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HSLAPercentages, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HSLAPercentages, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HSLAPercentages, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HSLAPercentages, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHSLA(HSLAPercentages, options)).toBe(item.HSLA); expect(ColorTranslator.toHSLA(HSLAPercentages, legacyOptions)).toBe(item.HSLALegacy); - expect(ColorTranslator.toHSLAObject(HSLAPercentages, options)).toMatchObject(item.HSLAObject); + expect(ColorTranslator.toHSLAObject(HSLAPercentages, options)).toEqual(item.HSLAObject); expect(ColorTranslator.toRGBA(HSLAPercentages)).toMatchSnapshot(); expect(ColorTranslator.toHSLA(HSLAPercentages)).toMatchSnapshot(); @@ -50,11 +50,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HSLBigHue, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HSLBigHue, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HSLBigHue, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HSLBigHue, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHSL(HSLBigHue, options)).toBe(item.HSL); expect(ColorTranslator.toHSL(HSLBigHue, legacyOptions)).toBe(item.HSLLegacy); - expect(ColorTranslator.toHSLObject(HSLBigHue, options)).toMatchObject(item.HSLObject); + expect(ColorTranslator.toHSLObject(HSLBigHue, options)).toEqual(item.HSLObject); }); @@ -62,11 +62,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HSLABigHue, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HSLABigHue, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HSLABigHue, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HSLABigHue, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHSLA(HSLABigHue, options)).toBe(item.HSLA); expect(ColorTranslator.toHSLA(HSLABigHue, legacyOptions)).toBe(item.HSLALegacy); - expect(ColorTranslator.toHSLAObject(HSLABigHue, options)).toMatchObject(item.HSLAObject); + expect(ColorTranslator.toHSLAObject(HSLABigHue, options)).toEqual(item.HSLAObject); }); @@ -74,11 +74,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HSLLowHue, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HSLLowHue, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HSLLowHue, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HSLLowHue, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHSL(HSLLowHue, options)).toBe(item.HSL); expect(ColorTranslator.toHSL(HSLLowHue, legacyOptions)).toBe(item.HSLLegacy); - expect(ColorTranslator.toHSLObject(HSLLowHue, options)).toMatchObject(item.HSLObject); + expect(ColorTranslator.toHSLObject(HSLLowHue, options)).toEqual(item.HSLObject); }); @@ -86,11 +86,11 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HSLALowHue, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HSLALowHue, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HSLALowHue, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HSLALowHue, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHSLA(HSLALowHue, options)).toBe(item.HSLA); expect(ColorTranslator.toHSLA(HSLALowHue, legacyOptions)).toBe(item.HSLALegacy); - expect(ColorTranslator.toHSLAObject(HSLALowHue, options)).toMatchObject(item.HSLAObject); + expect(ColorTranslator.toHSLAObject(HSLALowHue, options)).toEqual(item.HSLAObject); }); diff --git a/tests/08 - hwb.test.ts b/tests/08 - hwb.test.ts index ed632f1..9b462af 100644 --- a/tests/08 - hwb.test.ts +++ b/tests/08 - hwb.test.ts @@ -20,10 +20,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HWBPercentages, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HWBPercentages, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HWBPercentages, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HWBPercentages, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHWB(HWBPercentages, options)).toBe(item.HWB); - expect(ColorTranslator.toHWBObject(HWBPercentages, options)).toMatchObject(item.HWBObject); + expect(ColorTranslator.toHWBObject(HWBPercentages, options)).toEqual(item.HWBObject); expect(ColorTranslator.toRGB(HWBPercentages)).toMatchSnapshot(); expect(ColorTranslator.toHWB(HWBPercentages)).toMatchSnapshot(); @@ -34,10 +34,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HWBAPercentages, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HWBAPercentages, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HWBAPercentages, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HWBAPercentages, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHWBA(HWBAPercentages, options)).toBe(item.HWBA); - expect(ColorTranslator.toHWBAObject(HWBAPercentages, options)).toMatchObject(item.HWBAObject); + expect(ColorTranslator.toHWBAObject(HWBAPercentages, options)).toEqual(item.HWBAObject); expect(ColorTranslator.toRGBA(HWBAPercentages)).toMatchSnapshot(); expect(ColorTranslator.toHWB(HWBAPercentages)).toMatchSnapshot(); @@ -48,10 +48,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HWBBigHue, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HWBBigHue, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HWBBigHue, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HWBBigHue, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHWB(HWBBigHue, options)).toBe(item.HWB); - expect(ColorTranslator.toHWBObject(HWBBigHue, options)).toMatchObject(item.HWBObject); + expect(ColorTranslator.toHWBObject(HWBBigHue, options)).toEqual(item.HWBObject); }); @@ -59,10 +59,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HWBABigHue, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HWBABigHue, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HWBABigHue, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HWBABigHue, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHWBA(HWBABigHue, options)).toBe(item.HWBA); - expect(ColorTranslator.toHWBAObject(HWBABigHue, options)).toMatchObject(item.HWBAObject); + expect(ColorTranslator.toHWBAObject(HWBABigHue, options)).toEqual(item.HWBAObject); }); @@ -70,10 +70,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGB(HWBLowHue, options)).toBe(item.RGB); expect(ColorTranslator.toRGB(HWBLowHue, legacyOptions)).toBe(item.RGBLegacy); - expect(ColorTranslator.toRGBObject(HWBLowHue, options)).toMatchObject(item.RGBObject); + expect(ColorTranslator.toRGBObject(HWBLowHue, options)).toEqual(item.RGBObject); expect(ColorTranslator.toHWB(HWBLowHue, options)).toBe(item.HWB); - expect(ColorTranslator.toHWBObject(HWBLowHue, options)).toMatchObject(item.HWBObject); + expect(ColorTranslator.toHWBObject(HWBLowHue, options)).toEqual(item.HWBObject); }); @@ -81,10 +81,10 @@ COLORS.forEach((item): void => { expect(ColorTranslator.toRGBA(HWBALowHue, options)).toBe(item.RGBA); expect(ColorTranslator.toRGBA(HWBALowHue, legacyOptions)).toBe(item.RGBALegacy); - expect(ColorTranslator.toRGBAObject(HWBALowHue, options)).toMatchObject(item.RGBAObject); + expect(ColorTranslator.toRGBAObject(HWBALowHue, options)).toEqual(item.RGBAObject); expect(ColorTranslator.toHWBA(HWBALowHue, options)).toBe(item.HWBA); - expect(ColorTranslator.toHWBAObject(HWBALowHue, options)).toMatchObject(item.HWBAObject); + expect(ColorTranslator.toHWBAObject(HWBALowHue, options)).toEqual(item.HWBAObject); }); diff --git a/tests/09 - lab.test.ts b/tests/09 - lab.test.ts index d0dad04..1edba86 100644 --- a/tests/09 - lab.test.ts +++ b/tests/09 - lab.test.ts @@ -1,5 +1,5 @@ import { ColorTranslator } from '../src'; -import { COLORS } from './tests.constants'; +import { COLORS, LAB_AND_LCH_COLORS } from './tests.constants'; COLORS.forEach((item): void => { @@ -22,8 +22,8 @@ COLORS.forEach((item): void => { const laba = ColorTranslator.toCIELabAObject(item.HEX); const hex = ColorTranslator.toHEXObject(lab); const hexa = ColorTranslator.toHEXAObject(laba); - expect(hex).toMatchObject(item.HEXObject); - expect(hexa).toMatchObject(item.HEXAObject); + expect(hex).toEqual(item.HEXObject); + expect(hexa).toEqual(item.HEXAObject); }); @@ -39,6 +39,43 @@ COLORS.forEach((item): void => { }); + describe('CIE L*a*b round trip', () => { + + LAB_AND_LCH_COLORS.forEach((color) => { + + it.each([ + color.CIELab, + color.CIELabInPrcentage, + color.CIELabObject, + color.CIELabA, + color.CIELabAInPercentage, + color.CIELabAObject + ])('round trip of %s', (lab) => { + expect( + new ColorTranslator(lab, { legacyCSS: false, labUnit: 'none', decimals: 0 }).CIELab + ).toBe(color.CIELab); + expect( + new ColorTranslator(lab, { legacyCSS: false, labUnit: 'percent', decimals: 0 }).CIELab + ).toBe(color.CIELabInPrcentage); + expect( + new ColorTranslator(lab, { decimals: 0 }).CIELabObject + ).toEqual(color.CIELabObject); + + expect( + new ColorTranslator(lab, { legacyCSS: false, labUnit: 'none', decimals: 0, alphaUnit: 'none' }).CIELabA + ).toBe(color.CIELabA); + expect( + new ColorTranslator(lab, { legacyCSS: false, labUnit: 'percent', decimals: 0, alphaUnit: 'percent' }).CIELabA + ).toBe(color.CIELabAInPercentage); + expect( + new ColorTranslator(lab, { decimals: 0 }).CIELabAObject + ).toEqual(color.CIELabAObject); + }); + + }); + + }); + }); describe('L*a*b with percentages', (): void => { diff --git a/tests/10 - lch.test.ts b/tests/10 - lch.test.ts index 599637b..55a069c 100644 --- a/tests/10 - lch.test.ts +++ b/tests/10 - lch.test.ts @@ -22,8 +22,8 @@ COLORS.forEach((item): void => { const lcha = ColorTranslator.toLCHAObject(item.HEX); const hex = ColorTranslator.toHEXObject(lch); const hexa = ColorTranslator.toHEXAObject(lcha); - expect(hex).toMatchObject(item.HEXObject); - expect(hexa).toMatchObject(item.HEXAObject); + expect(hex).toEqual(item.HEXObject); + expect(hexa).toEqual(item.HEXAObject); }); diff --git a/tests/11 - blending.test.ts b/tests/11 - blending.test.ts index 83fa43b..6525181 100644 --- a/tests/11 - blending.test.ts +++ b/tests/11 - blending.test.ts @@ -54,46 +54,46 @@ describe('ColorTranslator blending tests', (): void => { const r2 = result2.map(c => obj.colorFn(c)); const r3 = result3.map(c => obj.colorFn(c)); - expect(obj.blendFn(from, to, r1.length)).toMatchObject(r1); - expect(obj.blendFn(from, to, r2.length)).toMatchObject(r2); - expect(obj.blendFn(from, to)).toMatchObject(r3); - expect(obj.blendFn(from, to, 0)).toMatchObject(r3); + expect(obj.blendFn(from, to, r1.length)).toEqual(r1); + expect(obj.blendFn(from, to, r2.length)).toEqual(r2); + expect(obj.blendFn(from, to)).toEqual(r3); + expect(obj.blendFn(from, to, 0)).toEqual(r3); }); blendFunctions.forEach((obj): void => { const r1 = result1.map(c => obj.colorFn(c, options)); const r2 = result2.map(c => obj.colorFn(c, options)); - expect(obj.blendFn(from, to, r1.length, options)).toMatchObject(r1); - expect(obj.blendFn(from, to, r2.length, options)).toMatchObject(r2); + expect(obj.blendFn(from, to, r1.length, options)).toEqual(r1); + expect(obj.blendFn(from, to, r2.length, options)).toEqual(r2); expect(obj.blendFn(from, to).length).toBe(5); expect( obj.blendFn(from, to, { decimals: 6 }) - ).toMatchObject( + ).toEqual( obj.blendFn(from, to) ); expect( obj.blendFn(from, to, 4, { decimals: 6 }) - ).toMatchObject( + ).toEqual( obj.blendFn(from, to, 4) ); expect( obj.blendFn(from, to, { cmykUnit: 'percent' }) - ).toMatchObject( + ).toEqual( obj.blendFn(from, to) ); expect( obj.blendFn(from, to, 3, { cmykUnit: 'percent' }) - ).toMatchObject( + ).toEqual( obj.blendFn(from, to, 3) ); }); // Check default steps - expect(ColorTranslator.getBlendHEX(from, to)).toMatchObject(ColorTranslator.getBlendHEX(from, to, 5)); - expect(ColorTranslator.getBlendHEX(from, to, -5)).toMatchObject(ColorTranslator.getBlendHEX(from, to, 5)); + expect(ColorTranslator.getBlendHEX(from, to)).toEqual(ColorTranslator.getBlendHEX(from, to, 5)); + expect(ColorTranslator.getBlendHEX(from, to, -5)).toEqual(ColorTranslator.getBlendHEX(from, to, 5)); }); diff --git a/tests/12 - color-mixing.test.ts b/tests/12 - color-mixing.test.ts index b61ed32..64f9376 100644 --- a/tests/12 - color-mixing.test.ts +++ b/tests/12 - color-mixing.test.ts @@ -34,7 +34,7 @@ describe('Additive Color mixing', (): void => { if (typeof mix === 'string') { expect(mix).toBe(fnObject.fn(item.mix, options)); } else { - expect(mix).toMatchObject(fnObject.fn(item.mix, options)); + expect(mix).toEqual(fnObject.fn(item.mix, options)); } }); it('Default mixing should be ADDITIVE', () => { @@ -43,7 +43,7 @@ describe('Additive Color mixing', (): void => { if (typeof mixAdditive === 'string') { expect(mixAdditive).toBe(mixDefault); } else { - expect(mixAdditive).toMatchObject(mixDefault); + expect(mixAdditive).toEqual(mixDefault); } }); }); @@ -141,7 +141,7 @@ describe('Color mixing with L*a*b colors', (): void => { Mix.ADDITIVE, { decimals: 0 } ) - ).toMatchObject( + ).toEqual( { L: 60, a: 94, b: -60 } ); }); @@ -153,7 +153,7 @@ describe('Color mixing with L*a*b colors', (): void => { { R: 0, G: 0, B: 255 } ] ) - ).toMatchObject( + ).toEqual( { L: 60.169696, a: 93.550025, b: -60.498556 } ); }); @@ -166,7 +166,7 @@ describe('Color mixing with L*a*b colors', (): void => { ], Mix.SUBTRACTIVE ) - ).toMatchObject( + ).toEqual( { L: 39.282789, a: 74.659748, b: -95.543967 } ); }); @@ -201,7 +201,7 @@ describe('Color mixing with L*a*b colors', (): void => { Mix.ADDITIVE, { decimals: 0 } ) - ).toMatchObject( + ).toEqual( { L: 60, a: 94, b: -60, A: 1 } ); }); @@ -214,7 +214,7 @@ describe('Color mixing with L*a*b colors', (): void => { ], Mix.SUBTRACTIVE ) - ).toMatchObject( + ).toEqual( { L: 39.282789, a: 74.659748, b: -95.543967, A: 1 } ); }); @@ -226,7 +226,7 @@ describe('Color mixing with L*a*b colors', (): void => { { R: 0, G: 0, B: 255 } ] ) - ).toMatchObject( + ).toEqual( { L: 60.169696, a: 93.550025, b: -60.498556, A: 1 } ); }); @@ -269,7 +269,7 @@ describe('Color mixing with lch colors', (): void => { Mix.ADDITIVE, { decimals: 0 } ) - ).toMatchObject( + ).toEqual( { L: 60, C: 111, H: 327 } ); }); @@ -281,7 +281,7 @@ describe('Color mixing with lch colors', (): void => { { R: 0, G: 0, B: 255 } ] ) - ).toMatchObject( + ).toEqual( { L: 60.169696, C: 111.407731, H: 327.109357 } ); }); @@ -294,7 +294,7 @@ describe('Color mixing with lch colors', (): void => { ], Mix.SUBTRACTIVE ) - ).toMatchObject( + ).toEqual( { L: 39.282789, C: 121.254804, H: 308.004699 } ); }); @@ -329,7 +329,7 @@ describe('Color mixing with lch colors', (): void => { Mix.ADDITIVE, { decimals: 0 } ) - ).toMatchObject( + ).toEqual( { L: 60, C: 111, H: 327, A: 1 } ); }); @@ -342,7 +342,7 @@ describe('Color mixing with lch colors', (): void => { ], Mix.SUBTRACTIVE ) - ).toMatchObject( + ).toEqual( { L: 39.282789, C: 121.254804, H: 308.004699, A: 1 } ); }); @@ -354,7 +354,7 @@ describe('Color mixing with lch colors', (): void => { { R: 0, G: 0, B: 255 } ] ) - ).toMatchObject( + ).toEqual( { L: 60.169696, C: 111.407731, H: 327.109357, A: 1 } ); }); diff --git a/tests/13 - shades-tints.test.ts b/tests/13 - shades-tints.test.ts index 2b17a79..1cefb7a 100644 --- a/tests/13 - shades-tints.test.ts +++ b/tests/13 - shades-tints.test.ts @@ -60,32 +60,32 @@ describe('ColorTranslator shades and tints tests', (): void => { it(`Shades tests from ${JSON.stringify(input)}`, (): void => { const output = shades_results.map((color: string) => fn(color)); const shades = ColorTranslator.getShades(input, 5); - expect(shades).toMatchObject(output); + expect(shades).toEqual(output); }); it(`Shades tests without number of shades is equal to 5 from ${JSON.stringify(input)}`, (): void => { const shades = ColorTranslator.getShades(input, 5); const shadesDefault = ColorTranslator.getShades(input); - expect(shades).toMatchObject(shadesDefault); + expect(shades).toEqual(shadesDefault); }); it(`Shades tests with alpha from ${JSON.stringify(inputWithAlpha)}`, (): void => { const output = shades_results.map((color: string) => fn(color + alpha)); const shades = ColorTranslator.getShades(inputWithAlpha, 5); - expect(shades).toMatchObject(output); + expect(shades).toEqual(output); }); it(`Tints tests from ${JSON.stringify(input)}`, (): void => { const output = tints_results.map((color: string) => fn(color)); const tints = ColorTranslator.getTints(input, 5); - expect(tints).toMatchObject(output); + expect(tints).toEqual(output); }); it(`Tints tests without number of tints from ${JSON.stringify(input)}`, (): void => { const tints = ColorTranslator.getTints(input, 5); const tintsDefault = ColorTranslator.getTints(input); - expect(tints).toMatchObject(tintsDefault); + expect(tints).toEqual(tintsDefault); }); it(`Tints tests with alpha from ${JSON.stringify(inputWithAlpha)}`, (): void => { const output = tints_results.map((color: string) => fn(color + alpha)); const tints = ColorTranslator.getTints(inputWithAlpha, 5); - expect(tints).toMatchObject(output); + expect(tints).toEqual(output); }); }); @@ -97,22 +97,22 @@ describe('ColorTranslator shades and tints tests', (): void => { it(`Shades tests from ${JSON.stringify(input)}`, (): void => { const output = shades_results.map((color: string) => fn(color, options)); const shades = ColorTranslator.getShades(input, 5, options); - expect(shades).toMatchObject(output); + expect(shades).toEqual(output); }); it(`Shades tests with alpha from ${JSON.stringify(inputWithAlpha)}`, (): void => { const output = shades_results.map((color: string) => fn(color + alpha, options)); const shades = ColorTranslator.getShades(inputWithAlpha, 5, options); - expect(shades).toMatchObject(output); + expect(shades).toEqual(output); }); it(`Tints tests from ${JSON.stringify(input)}`, (): void => { const output = tints_results.map((color: string) => fn(color, options)); const tints = ColorTranslator.getTints(input, 5, options); - expect(tints).toMatchObject(output); + expect(tints).toEqual(output); }); it(`Tints tests with alpha from ${JSON.stringify(inputWithAlpha)}`, (): void => { const output = tints_results.map((color: string) => fn(color + alpha, options)); const tints = ColorTranslator.getTints(inputWithAlpha, 5, options); - expect(tints).toMatchObject(output); + expect(tints).toEqual(output); }); it(`Shades tests from ${JSON.stringify(input)} with decimals`, (): void => { const shades = ColorTranslator.getShades(input, 5, options); diff --git a/tests/14 - harmony.test.ts b/tests/14 - harmony.test.ts index e9bf12b..1cb414a 100644 --- a/tests/14 - harmony.test.ts +++ b/tests/14 - harmony.test.ts @@ -80,12 +80,12 @@ describe('ColorTranslator harmony tests', (): void => { const colors = harmony === Harmony.COMPLEMENTARY ? ColorTranslator.getHarmony(color, Harmony.COMPLEMENTARY, Mix.ADDITIVE, options) : ColorTranslator.getHarmony(color, Harmony[harmony as Harmony], Mix.ADDITIVE, options); - expect(colors).toMatchObject(additiveResult[index]); + expect(colors).toEqual(additiveResult[index]); }); it(`Subtractive Harmony deep equals: ${harmony} for ${color} => ${JSON.stringify(subtractiveResult[index])}`, (): void => { const colors = ColorTranslator.getHarmony(color, Harmony[harmony as Harmony], Mix.SUBTRACTIVE, options); - expect(colors).toMatchObject(subtractiveResult[index]); + expect(colors).toEqual(subtractiveResult[index]); }); it('Additive Complementary > 360ยบ', (): void => { @@ -105,7 +105,7 @@ describe('ColorTranslator harmony tests', (): void => { it(`Additive Harmony deep equals: ${harmony} for ${color} => ${JSON.stringify(additiveResult[index])}`, (): void => { const colors = ColorTranslator.getHarmony(color, Harmony[harmony as Harmony], Mix.ADDITIVE, options); - expect(colors).toMatchObject(additiveResult[index]); + expect(colors).toEqual(additiveResult[index]); }); it(`Additive Harmony with decimals for ${JSON.stringify(color)}`, (): void => { @@ -115,7 +115,7 @@ describe('ColorTranslator harmony tests', (): void => { it(`Subtractive Harmony deep equals: ${harmony} for ${color} => ${JSON.stringify(subtractiveResult[index])}`, (): void => { const colors = ColorTranslator.getHarmony(color, Harmony[harmony as Harmony], Mix.SUBTRACTIVE, options); - expect(colors).toMatchObject(subtractiveResult[index]); + expect(colors).toEqual(subtractiveResult[index]); }); it(`Subtractive Harmony with decimals and auto legacyCSS for ${JSON.stringify(color)}`, (): void => { @@ -164,31 +164,31 @@ describe('ColorTranslator harmony tests', (): void => { it('Harmony excluding optional parameters', (): void => { expect( ColorTranslator.getHarmony(base, Harmony.COMPLEMENTARY, Mix.ADDITIVE) - ).toMatchObject( + ).toEqual( ColorTranslator.getHarmony(base, Harmony.COMPLEMENTARY) ); expect( ColorTranslator.getHarmony(base, Harmony.COMPLEMENTARY, Mix.ADDITIVE) - ).toMatchObject( + ).toEqual( ColorTranslator.getHarmony(base) ); expect( ColorTranslator.getHarmony(base, Harmony.COMPLEMENTARY, { decimals: 0 }) - ).toMatchObject( + ).toEqual( ColorTranslator.getHarmony(base, { decimals: 0 }) ); expect( ColorTranslator.getHarmony(base, Mix.ADDITIVE) - ).toMatchObject( + ).toEqual( ColorTranslator.getHarmony(base) ); expect( ColorTranslator.getHarmony(base, Mix.ADDITIVE, { decimals: 0 }) - ).toMatchObject( + ).toEqual( ColorTranslator.getHarmony(base, { decimals: 0 }) ); }); diff --git a/tests/15 - error.test.ts b/tests/15 - error.test.ts index dda21e4..7e42714 100644 --- a/tests/15 - error.test.ts +++ b/tests/15 - error.test.ts @@ -8,7 +8,7 @@ describe('Wrong inputs', (): void => { expect(() => { ColorTranslator.toHEX('AAA'); - }).toThrow(ERRORS.NOT_ACCEPTED_STRING_INPUT); + }).toThrow(ERRORS.NOT_ACCEPTED_INPUT); }); @@ -16,7 +16,7 @@ describe('Wrong inputs', (): void => { expect(() => { ColorTranslator.toHEX({P: 100, H: 20, T: 360} as unknown as ColorInput); - }).toThrow(ERRORS.NOT_ACCEPTED_OBJECT_INPUT); + }).toThrow(ERRORS.NOT_ACCEPTED_INPUT); }); @@ -24,7 +24,7 @@ describe('Wrong inputs', (): void => { expect(() => { ColorTranslator.toHEX({R: '0x25', G: 20, B: '0xFF'} as unknown as ColorInput); - }).toThrow(ERRORS.NOT_ACCEPTED_OBJECT_INPUT); + }).toThrow(ERRORS.NOT_ACCEPTED_INPUT); }); @@ -32,7 +32,7 @@ describe('Wrong inputs', (): void => { expect(() => { ColorTranslator.toHEX({R: '0x255', G: '0x128', B: '0xFFF'} as unknown as ColorInput); - }).toThrow(ERRORS.NOT_ACCEPTED_OBJECT_INPUT); + }).toThrow(ERRORS.NOT_ACCEPTED_INPUT); }); diff --git a/tests/16 - package-exports.test.ts b/tests/16 - package-exports.test.ts new file mode 100644 index 0000000..33fee1e --- /dev/null +++ b/tests/16 - package-exports.test.ts @@ -0,0 +1,13 @@ +import * as Library from '../src'; +import { ColorTranslator } from '../src/classes/ColorTranslator'; +import { Harmony, Mix } from '../src/constants'; + +describe('exports from the main package', () => { + it('@testing should match exports', () => { + expect(Library).toEqual({ + ColorTranslator, + Harmony, + Mix + }); + }); +}); \ No newline at end of file diff --git a/tests/tests.constants.ts b/tests/tests.constants.ts index b5d2e87..d271a3b 100644 --- a/tests/tests.constants.ts +++ b/tests/tests.constants.ts @@ -342,7 +342,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(54 81 70)', CIELabA: 'lab(54 81 70 / 1)', CIELabInPrcentage: 'lab(54% 65% 56%)', - CIELabAInPrcentage: 'lab(54% 65% 56% / 100%)', + CIELabAInPercentage: 'lab(54% 65% 56% / 100%)', CIELabObject: { L: 54, a: 81, b: 70 }, CIELabAObject: { L: 54, a: 81, b: 70, A: 1 }, LCH: 'lch(54 107 41)', @@ -357,7 +357,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(88 -79 81)', CIELabA: 'lab(88 -79 81 / 1)', CIELabInPrcentage: 'lab(88% -63% 65%)', - CIELabAInPrcentage: 'lab(88% -63% 65% / 100%)', + CIELabAInPercentage: 'lab(88% -63% 65% / 100%)', CIELabObject: { L: 88, a: -79, b: 81 }, CIELabAObject: { L: 88, a: -79, b: 81, A: 1 }, LCH: 'lch(88 113 134)', @@ -372,7 +372,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(30 68 -112)', CIELabA: 'lab(30 68 -112 / 1)', CIELabInPrcentage: 'lab(30% 54% -90%)', - CIELabAInPrcentage: 'lab(30% 54% -90% / 100%)', + CIELabAInPercentage: 'lab(30% 54% -90% / 100%)', CIELabObject: { L: 30, a: 68, b: -112 }, CIELabAObject: { L: 30, a: 68, b: -112, A: 1 }, LCH: 'lch(30 131 301)', @@ -387,7 +387,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(60 94 -60)', CIELabA: 'lab(60 94 -60 / 1)', CIELabInPrcentage: 'lab(60% 75% -48%)', - CIELabAInPrcentage: 'lab(60% 75% -48% / 100%)', + CIELabAInPercentage: 'lab(60% 75% -48% / 100%)', CIELabObject: { L: 60, a: 94, b: -60 }, CIELabAObject: { L: 60, a: 94, b: -60, A: 1 }, LCH: 'lch(60 111 327)', @@ -402,7 +402,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(100 0 0)', CIELabA: 'lab(100 0 0 / 1)', CIELabInPrcentage: 'lab(100% 0% 0%)', - CIELabAInPrcentage: 'lab(100% 0% 0% / 100%)', + CIELabAInPercentage: 'lab(100% 0% 0% / 100%)', CIELabObject: { L: 100, a: 0, b: 0 }, CIELabAObject: { L: 100, a: 0, b: 0, A: 1 }, LCH: 'lch(100 0 0)', @@ -417,7 +417,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(0 0 0)', CIELabA: 'lab(0 0 0 / 1)', CIELabInPrcentage: 'lab(0% 0% 0%)', - CIELabAInPrcentage: 'lab(0% 0% 0% / 100%)', + CIELabAInPercentage: 'lab(0% 0% 0% / 100%)', CIELabObject: { L: 0, a: 0, b: 0 }, CIELabAObject: { L: 0, a: 0, b: 0, A: 1 }, LCH: 'lch(0 0 0)', @@ -432,7 +432,7 @@ export const LAB_AND_LCH_COLORS = [ CIELab: 'lab(54 0 0)', CIELabA: 'lab(54 0 0 / 1)', CIELabInPrcentage: 'lab(54% 0% 0%)', - CIELabAInPrcentage: 'lab(54% 0% 0% / 100%)', + CIELabAInPercentage: 'lab(54% 0% 0% / 100%)', CIELabObject: { L: 54, a: 0, b: 0 }, CIELabAObject: { L: 54, a: 0, b: 0, A: 1 }, LCH: 'lch(54 0 0)', diff --git a/tsconfig.json b/tsconfig.json index b799e0a..ed20533 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,11 +12,13 @@ "baseUrl": "./src", "paths": { "@types": ["@types"], - "#helpers": ["helpers"], "#constants": ["constants"], + "#classes/*": ["classes/*"], "#color/*": ["color/*"], + "#css": ["css"], "#parsers": ["parsers"], - "#returns": ["returns"] + "#returns": ["returns"], + "#utilities": ["utilities"] } }, "include": ["src/**/*.ts"],