@borgar/fx 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,6 +22,7 @@ The library is also provided as an ES6 module in an NPM package:
22
22
  |- | - | -
23
23
  | `emitRanges` | `false` | Adds offset ranges on the tokens: `{ range: [ start, end ] }`
24
24
  | `mergeRanges` | `true` | Should ranges be returned as whole references (`Sheet1!A1:B2`) or as separate tokens for each part: (`Sheet1`,`!`,`A1`,`:`,`B2`).
25
+ | `negativeNumbers` | `false` | Merges all unary minuses with their immediately following number tokens (`-`,`1`) => `-1`
25
26
  | `r1c1` | `false` | Ranges are expected to be in the R1C1 style format rather than the more popular A1 style.
26
27
 
27
28
  The returned output will be an array of objects representing the tokens:
@@ -106,13 +107,13 @@ The returned output will be the same array of tokens but the following propertie
106
107
 
107
108
  Matching parens will be tagged with `.groupId` string identifier as well as a `.depth` number value (indicating the level of nesting).
108
109
 
109
- Parens without a counterpart will be tagged with `.error` (boolean true).
110
+ Closing parens without a counterpart will be tagged with `.error` (boolean true).
110
111
 
111
112
  #### Curly brackets { }
112
113
 
113
114
  Matching curly brackets will be tagged with `.groupId` string identifier. These may not be nested in Excel.
114
115
 
115
- Curly brackets without a counterpart will be tagged with `.error` (boolean `true`).
116
+ Closing curly brackets without a counterpart will be tagged with `.error` (boolean `true`).
116
117
 
117
118
  #### Ranges (`RANGE` or `RANGE_BEAM` type tokens)
118
119
 
package/dist/fx.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";function t(t){return t.split(/(\d+|[a-zA-Z]+)/).every((t=>{const e=parseInt(t,36);return!!isNaN(e)||(isFinite(t)?e<=2183880786:e<=43321)}))}Object.defineProperty(exports,"__esModule",{value:!0});const e={R:1048577,"R[":1048576,C:16385,"C[":16384};function r(t){const r=/([RC]\[?)(-?\d+)/gi;let n;for(;null!==(n=r.exec(t));){const t=e[n[1]],r=parseInt(n[2],10);if(r>=t||r<=-t)return!1}return!0}const n="range",o="range-beam",a=/^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!)/i,i=/^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/,l=/^(TRUE|FALSE)\b/i,c=/^[A-Z_]+[A-Z\d_.]+(?=\s*\()/i,u=/^\n+/,p=/^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,s=/^"(?:""|[^"])*("|$)/,f=/^'(?:''|[^'])*('|$)/,$=/^\[(?:[^\]])+(\]|$)/,g=/^([^ \t\n$!"`'#%&(){}<>,;:^@|~=*+-]+)(?=!)/,h=/^\$?[A-Z]{1,3}:\$?[A-Z]{1,3}/i,m=/^\$?[1-9][0-9]{0,6}:\$?[1-9][0-9]{0,6}/i,b=/^\$?[A-Z]{1,3}\$?[1-9][0-9]{0,6}/i,d="(?:R(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,6})?)",v="(?:C(?:\\[[+-]?\\d+\\]|[1-9][0-9]{0,4})?)",R=new RegExp("^".concat(v,"(:").concat(v,")?(?=\\W|$)"),"i"),x=new RegExp("^".concat(d,"(:").concat(d,")?(?=\\W|$)"),"i"),N=new RegExp("^(?:(?=[RC])".concat(d).concat(v,")"),"i"),A=/^(?:\d+(\.\d+)?(?:[eE][+-]?\d+)?|\d+)/,E=/^[A-Z\d\\_.?]+/i,y=[["error",a],["operator",i],["bool",l],["function",c],["newline",u],["whitespace",p],["string",s],["path-quote",f],["path-brace",$],["path-prefix",g],[n,b,t],[o,h,t],[o,m,t],["number",A],["range-named",E]],C=[["error",a],["operator",i],["bool",l],["function",c],["newline",u],["whitespace",p],["string",s],["path-quote",f],["path-brace",$],["path-prefix",g],[n,N,r],[o,x,r],[o,R,r],["number",A],["range-named",E]],I=[["operator",/^[!:]/],["path-quote",f],["path-brace",$],["path-prefix",g],[n,b,t],[o,h,t],[o,m,t],["range-named",E]],w=[["operator",/^!/],["path-quote",f],["path-brace",$],["path-prefix",g],[n,N,r],[o,x,r],[o,R,r],["range-named",E]],k=(t,e)=>t&&t.type===e,T=t=>t&&":"===t.value,O=t=>t&&"!"===t.value,L={emitRanges:!1,mergeRanges:!0,negativeNumbers:!1,r1c1:!1};function M(t,e){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};const{emitRanges:a,mergeRanges:i,negativeNumbers:l}=Object.assign({},L,r),c=[];let u=0;const p=t=>c[c.length-t],s=t=>{const e=c.filter((t=>!k(t,"whitespace")&&!k(t,"newline")));return e[e.length-t]};if(/^=/.test(t)){const t={type:"fx-prefix",value:"=",...a?{range:[0,1]}:{}};u++,c.push(t)}for(;u<t.length;){const r=u,f=t.slice(u);let $="",g="";for(let t=0;t<e.length;t++){const[r,n,o]=e[t],a=n.exec(f);if(a&&(!o||o(a[0]))){$=r,g=a[0],u+=a[0].length;break}}$||($="unknown",g=t[u],u++);let h={type:$,value:g,...a?{range:[r,u]}:{}};if("string"!==$||g.endsWith('"')||(h.unterminated=!0),l&&"number"===$){const t=p(1);if(t&&k(t,"operator")&&"-"===t.value){const t=s(2);(!t||k(t,"fx-prefix")||k(t,"operator")&&!["%","}",")","#"].includes(t.value))&&(c.pop(),h.value="-"+g)}}if(i&&($===n||"range-named"===$||$===o)){const t=[];if(T(p(1))&&k(p(2),n)&&$===n&&t.unshift(...c.splice(-2,2)),O(p(1)))if(k(p(2),"path-quote")||k(p(2),"path-brace"))t.unshift(...c.splice(-2,2));else if(k(p(2),"path-prefix")){const e=k(p(3),"path-brace")?3:2;t.unshift(...c.splice(-e,e))}t.length&&(h={type:$,value:t.map((t=>t.value)).join("")+g,...a?{range:[t[0].range[0],u]}:{}})}c.push(h)}return c}function _(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const r=e.r1c1?C:y;return M(t,r,e)}const Z=t=>t.slice(1,-1).replace(/''/g,"'"),S=t=>t&&":"===t.value&&{},U=t=>t&&t.type===n&&{r0:t.value},F=t=>t&&t.type===n&&{r1:t.value},P=t=>t&&"!"===t.value&&{},q=t=>t&&t.type===o&&{r0:t.value},W=t=>t&&"path-prefix"===t.type&&/^[^:\\/?*[\]]{0,31}$/.test(t.value)&&{sheetName:t.value},j=t=>t&&"path-brace"===t.type&&{workbookName:t.value.slice(1,-1)},G=t=>t&&"range-named"===t.type&&{name:t.value},X=t=>{if(t&&"path-quote"===t.type){const e=/(?:\[(.+?)\])?([^[\]]+?)$/.exec(Z(t.value));if(e){const[,t,r]=e;if(!r||/^[^:\\/?*[\]]{0,31}$/.test(r))return{workbookName:t||"",sheetName:r||""}}}},D=[[U],[U,S,F],[q],[X,P,U],[X,P,U,S,F],[X,P,q],[W,P,U],[W,P,U,S,F],[W,P,q],[j,W,P,U],[j,W,P,U,S,F],[j,W,P,q]],B=D.concat([[G],[t=>t&&"path-prefix"===t.type&&{workbookName:t.value},P,G],[t=>t&&"path-quote"===t.type&&{workbookName:Z(t.value)},P,G]]);function H(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];const n=M(t,r,{emitRanges:!1,mergeRanges:!1}),o={sheetName:"",workbookName:"",r0:"",r1:"",name:""};n.length&&"fx-prefix"===n[0].type&&n.shift();const a=e?B:D;for(let t=0;t<a.length;t++){const e={...o};if(a[t].length===n.length){if(a[t].every(((t,r)=>{const o=t(n[r]);return Object.assign(e,o),o})))return e}}return null}function z(t){const e=(t||"").toUpperCase();let r=0,n=0;for(;n!==e.length;++n){const t=e.charCodeAt(n);t>=65&&t<=90&&(r=26*r+t-64)}return r-1}function K(t){let e=t,r="";for(;e>=0;)r=String.fromCharCode(e%26+65)+r,e=Math.floor(e/26)-1;return r}function V(t){return+t-1}function Q(t){return String(t+1)}function Y(t){const{top:e,left:r,bottom:n,right:o}=t;return{top:e,left:r,bottom:n,right:o,$left:!1,$right:!1,$top:!1,$bottom:!1}}function J(t){const e=t=>t?"$":"",{top:r,left:n,bottom:o,right:a,$left:i,$right:l,$top:c,$bottom:u}=t;return 0===r&&1048575===o?e(i)+K(n)+":"+e(l)+K(a):0===n&&16383===a?e(c)+Q(r)+":"+e(u)+Q(o):null==a||null==o||a===n&&o===r?e(i)+K(n)+e(c)+Q(r):e(i)+K(n)+e(c)+Q(r)+":"+e(l)+K(a)+e(u)+Q(o)}function tt(t){let e,r=0,n=0,o=1048575,a=16383,i=!1,l=!1,c=!1,u=!1;if(e=/^(\$?)([A-Z]{1,3}):(\$?)([A-Z]{1,3})$/.exec(t)){const t=z(e[2]),p=z(e[4]);return n=Math.min(t,p),a=Math.max(t,p),l=!!e[t<=p?1:3],u=!!e[t<=p?3:1],i=!0,c=!0,{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}if(e=/^(\$?)([1-9]\d{0,6}):(\$?)([1-9]\d{0,6})$/.exec(t)){const t=V(e[2]),p=V(e[4]);return r=Math.min(t,p),o=Math.max(t,p),i=!!e[t<=p?1:3],c=!!e[t<=p?3:1],l=!0,u=!0,{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}{const[p,s]=t.split(":");if(e=/^(\$?)([A-Z]{1,3})(\$?)([1-9]\d{0,6})$/i.exec(p))return n=z(e[2]),r=V(e[4]),l=!!e[1],i=!!e[3],s&&(e=/^(\$?)([A-Z]{1,3})(\$?)([1-9]\d{0,6})$/i.exec(s))?(a=z(e[2]),o=V(e[4]),u=!!e[1],c=!!e[3],o<r&&([r,o,i,c]=[o,r,c,i]),a<n&&([n,a,l,u]=[a,n,u,l])):(o=r,a=n,c=i,u=l),{top:r,left:n,bottom:o,right:a,$top:i,$left:l,$bottom:c,$right:u}}return null}function et(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];const r=H(t,e,I);if(r&&(r.r0||r.name)){let t=null;return r.r0&&(t=r.r1?tt(r.r0+":"+r.r1):tt(r.r0)),r.name||t?(r.range=t,delete r.r0,delete r.r1,r):null}return null}var rt={fromCol:z,toCol:K,toRelative:Y,toAbsolute:function(t){const{top:e,left:r,bottom:n,right:o}=t;return{top:e,left:r,bottom:n,right:o,$left:!0,$right:!0,$top:!0,$bottom:!0}},to:J,from:tt,parse:et};function nt(){let t=1;return()=>"fxg"+t++}function ot(t,e){return e?String(t+1):t?"["+t+"]":""}function at(t){const{r0:e,c0:r,r1:n,c1:o,$c0:a,$c1:i,$r0:l,$r1:c}=t;if(0===e&&1048575===n){const t=ot(r,a),e=ot(o,i);return"C"+(t===e?t:t+":C"+e)}if(0===r&&16383===o){const t=ot(e,l),r=ot(n,c);return"R"+(t===r?t:t+":R"+r)}const u=ot(e,l),p=ot(n,c),s=ot(r,a),f=ot(o,i);return u!==p||s!==f?"R"+u+"C"+s+":R"+p+"C"+f:"R"+u+"C"+s}function it(t){let e=0,r=0,n=1048575,o=16383,a=!1,i=!1,l=!1,c=!1;const u=/^R(?:\[([+-]?\d+)\]|(\d+))?/.exec(t);u?(u[1]?e=parseInt(u[1],10):u[2]&&(e=parseInt(u[2],10)-1,a=!0),n=e,l=a,t=t.slice(u[0].length)):(a=!0,l=!0);const p=/^C(?:\[([+-]?\d+)\]|(\d+))?/.exec(t);return p?(p[1]?r=parseInt(p[1],10):p[2]&&(r=parseInt(p[2],10)-1,i=!0),o=r,c=i,t=t.slice(p[0].length)):(i=!0,c=!0),!u&&!p||t.length?null:{r0:e,c0:r,r1:n,c1:o,$r0:a,$c0:i,$r1:l,$c1:c}}function lt(t){const[e,r]=t.split(":",2),n=it(e);if(!n)return null;if(n&&r){const t=it(r);if(!t)return null;n.r1=t.r1,n.c1=t.c1,n.$r1=t.$r1,n.$c1=t.$c1}return n}var ct={to:at,from:lt,parse:function(t){let e=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];const r=H(t,e,w);if(r&&(r.r0||r.name)){const t=r.r1?lt(r.r0+":"+r.r1):lt(r.r0);return r.name||t?(r.range=t,delete r.r0,delete r.r1,r):null}return null}};function ut(t,e,r,n){let o=t;return e||(o=r+t,o<0&&(o=n+o+1),o>n&&(o-=n+1)),o}const pt={OPERATOR:"operator",BOOLEAN:"bool",ERROR:"error",NUMBER:"number",FUNCTION:"function",NEWLINE:"newline",WHITESPACE:"whitespace",STRING:"string",PATH_QUOTE:"path-quote",PATH_BRACE:"path-brace",PATH_PREFIX:"path-prefix",RANGE:n,RANGE_BEAM:o,RANGE_NAMED:"range-named",FX_PREFIX:"fx-prefix",UNKNOWN:"unknown"};exports.MAX_COLS=16383,exports.MAX_ROWS=1048575,exports.a1=rt,exports.addMeta=function(t){let{sheetName:e="",workbookName:r=""}=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};const a=[];let i=null;const l={},c=nt();return t.forEach(((t,u)=>{if(t.index=u,t.depth=a.length,"("===t.value)t.depth=a.length+1,a.push(t);else if(")"===t.value){const e=a.pop();if(e){const r=c();t.groupId=r,t.depth=e.depth,e.groupId=r}else t.error=!0}else if("{"===t.value)i?t.error=!0:i=t;else if("}"===t.value){if(i){const e=c();t.groupId=e,i.groupId=e}else t.error=!0;i=null}else if(t.type===n||t.type===o){const n=et(t.value,!1),o=n&&"[".concat(n.workbookName||r,"]").concat(n.sheetName||e,"!").concat(n.range?J(Y(n.range)):n.name).toLowerCase();o&&(o in l?t.groupId=l[o]:(t.groupId=c(),l[o]=t.groupId))}else"unknown"===t.type&&(t.error=!0)})),t},exports.rc=ct,exports.tokenTypes=pt,exports.tokenize=_,exports.translateToA1=function(t,e){const r=tt(e),a="string"==typeof t,i=a?_(t,{emitRanges:!1,mergeRanges:!1,r1c1:!0}):t;return i.forEach((t=>{if(t.type===n||t.type===o){const e={},n=lt(t.value),o=ut(n.r0,n.$r0,r.top,1048575),a=ut(n.r1,n.$r1,r.top,1048575);o>a?(e.top=a,e.$top=n.$r1,e.bottom=o,e.$bottom=n.$r0):(e.top=o,e.$top=n.$r0,e.bottom=a,e.$bottom=n.$r1);const i=ut(n.c0,n.$c0,r.left,16383),l=ut(n.c1,n.$c1,r.left,16383);i>l?(e.left=l,e.$left=n.$c1,e.right=i,e.$right=n.$c0):(e.left=i,e.$left=n.$c0,e.right=l,e.$right=n.$c1),t.value=J(e)}})),a?i.map((t=>t.value)).join(""):i},exports.translateToRC=function(t,e){const{top:r,left:a}=tt(e),i="string"==typeof t,l=i?_(t,{emitRanges:!1,mergeRanges:!1,r1c2:!1}):t;return l.forEach((t=>{if(t.type===n){const e={},n=tt(t.value);e.r0=n.$top?n.top:n.top-r,e.$r0=n.$top,e.r1=n.$bottom?n.bottom:n.bottom-r,e.$r1=n.$bottom,e.c0=n.$left?n.left:n.left-a,e.$c0=n.$left,e.c1=n.$right?n.right:n.right-a,e.$c1=n.$right,t.value=at(e)}else if(t.type===o){const e={},n=tt(t.value);e.r0=n.$top?n.top:n.top-r,e.$r0=n.$top,e.r1=n.$bottom?n.bottom:n.bottom-r,e.$r1=n.$bottom,e.c0=n.$left?n.left:n.left-a,e.$c0=n.$left,e.c1=n.$right?n.right:n.right-a,e.$c1=n.$right,t.value=at(e)}})),i?l.map((t=>t.value)).join(""):l};
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnguanMiLCJzb3VyY2VzIjpbIi4uL2xpYi9xdWlja1ZlcmlmeS5qcyIsIi4uL2xpYi9jb25zdGFudHMuanMiLCIuLi9saWIvbGV4ZXIuanMiLCIuLi9saWIvcGFyc2VSZWYuanMiLCIuLi9saWIvYTEuanMiLCIuLi9saWIvYWRkTWV0YS5qcyIsIi4uL2xpYi9yYy5qcyIsIi4uL2xpYi90cmFuc2xhdGUuanMiLCIuLi9saWIvaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGZ1bmN0aW9uIHF1aWNrVmVyaWZ5UmFuZ2VBMSAodG9rZW5WYWx1ZSkge1xuICAvLyBRdWlja2x5IGRldGVybWluZSBpZiByYW5nZSB2YWx1cyBhcmUgb3V0IG9mIGJvdW5kczogU3BsaXQgdGhlIHN0cmluZyBpbnRvXG4gIC8vIG51bWVyaWMsIGFscGhhYmV0aWNhbCwgYW5kIFwib3RoZXJcIiBjaHVua3MgYW5kIHBhcnNlIHRoZW0gYXMgYmFzZSAzNiBudW1iZXJzLlxuICAvLyBCb3RoIHJvd3MgYW5kIGNvbHMgY2FuIGJlIHJlcHJlc2VudGVkIGluIGJhc2UgMzYgYW5kIHdlIGNhbiBkZWNpZGUgd2hpY2ggd2VcbiAgLy8gaG9sZCBieSBjaGVja2luZyBpZiB0aGUgY2h1bmsgd2FzIGFscmVhZHkgYSBmaW5pdGUgbnVtYmVyLiBTbyB3ZSBjYW4gc2ltcGx5XG4gIC8vIGNvbXBhcmUgYWdhaW5zdCB0aGUgYmFzZSAzNiBwYXJzZWQgdmVyc2lvbnMgb2YgWEZEIGFuZCAxMDQ4NTc2LlxuICByZXR1cm4gdG9rZW5WYWx1ZS5zcGxpdCgvKFxcZCt8W2EtekEtWl0rKS8pLmV2ZXJ5KGQgPT4ge1xuICAgIGNvbnN0IG4gPSBwYXJzZUludChkLCAzNik7XG4gICAgaWYgKCFpc05hTihuKSkge1xuICAgICAgcmV0dXJuIGlzRmluaXRlKGQpXG4gICAgICAgID8gbiA8PSAyMTgzODgwNzg2IC8vIG1heCByb3dzXG4gICAgICAgIDogbiA8PSA0MzMyMTsgICAgIC8vIG1heCBjb2xzXG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuY29uc3QgYm91bmRzID0ge1xuICAnUic6IDEwNDg1NzcsXG4gICdSWyc6IDEwNDg1NzYsXG4gICdDJzogMTYzODUsXG4gICdDWyc6IDE2Mzg0XG59O1xuZXhwb3J0IGZ1bmN0aW9uIHF1aWNrVmVyaWZ5UmFuZ2VSQyAodG9rZW5WYWx1ZSkge1xuICBjb25zdCByZU51bXMgPSAvKFtSQ11cXFs/KSgtP1xcZCspL2dpO1xuICBsZXQgbTtcbiAgd2hpbGUgKChtID0gcmVOdW1zLmV4ZWModG9rZW5WYWx1ZSkpICE9PSBudWxsKSB7XG4gICAgY29uc3QgeCA9IGJvdW5kc1ttWzFdXTtcbiAgICBjb25zdCB2YWwgPSBwYXJzZUludChtWzJdLCAxMCk7XG4gICAgaWYgKHZhbCA+PSB4IHx8IHZhbCA8PSAteCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cbiIsImltcG9ydCB7IHF1aWNrVmVyaWZ5UmFuZ2VBMSwgcXVpY2tWZXJpZnlSYW5nZVJDIH0gZnJvbSAnLi9xdWlja1ZlcmlmeS5qcyc7XG5cbmV4cG9ydCBjb25zdCBPUEVSQVRPUiA9ICdvcGVyYXRvcic7XG5leHBvcnQgY29uc3QgQk9PTEVBTiA9ICdib29sJztcbmV4cG9ydCBjb25zdCBFUlJPUiA9ICdlcnJvcic7XG5leHBvcnQgY29uc3QgTlVNQkVSID0gJ251bWJlcic7XG5leHBvcnQgY29uc3QgRlVOQ1RJT04gPSAnZnVuY3Rpb24nO1xuZXhwb3J0IGNvbnN0IE5FV0xJTkUgPSAnbmV3bGluZSc7XG5leHBvcnQgY29uc3QgV0hJVEVTUEFDRSA9ICd3aGl0ZXNwYWNlJztcbmV4cG9ydCBjb25zdCBTVFJJTkcgPSAnc3RyaW5nJztcbmV4cG9ydCBjb25zdCBQQVRIX1FVT1RFID0gJ3BhdGgtcXVvdGUnO1xuZXhwb3J0IGNvbnN0IFBBVEhfQlJBQ0UgPSAncGF0aC1icmFjZSc7XG5leHBvcnQgY29uc3QgUEFUSF9QUkVGSVggPSAncGF0aC1wcmVmaXgnO1xuZXhwb3J0IGNvbnN0IFJBTkdFID0gJ3JhbmdlJztcbmV4cG9ydCBjb25zdCBSQU5HRV9CRUFNID0gJ3JhbmdlLWJlYW0nO1xuZXhwb3J0IGNvbnN0IFJBTkdFX05BTUVEID0gJ3JhbmdlLW5hbWVkJztcbmV4cG9ydCBjb25zdCBGWF9QUkVGSVggPSAnZngtcHJlZml4JztcbmV4cG9ydCBjb25zdCBVTktOT1dOID0gJ3Vua25vd24nO1xuXG5leHBvcnQgY29uc3QgTUFYX0NPTFMgPSAyICoqIDE0IC0gMTsgLy8gMTYzODNcbmV4cG9ydCBjb25zdCBNQVhfUk9XUyA9IDIgKiogMjAgLSAxOyAvLyAxMDQ4NTc1XG5cbmNvbnN0IHJlX0VSUk9SID0gL14jKE5BTUVcXD98RklFTEQhfENBTEMhfFZBTFVFIXxSRUYhfERJVlxcLzAhfE5VTEwhfE5VTSF8TlxcL0F8R0VUVElOR19EQVRBXFxifFNQSUxMIXxVTktOT1dOIXxGSUVMRFxcYnxDQUxDXFxifFNZTlRBWFxcP3xFUlJPUiEpL2k7XG5jb25zdCByZV9PUEVSQVRPUiA9IC9eKDw9fD49fDw+fFstKy8qXiUmPD49XXxbe30sO118WygpXXxAfDp8IXwjKS87XG5jb25zdCByZV9CT09MRUFOID0gL14oVFJVRXxGQUxTRSlcXGIvaTtcbmNvbnN0IHJlX0ZVTkNUSU9OID0gL15bQS1aX10rW0EtWlxcZF8uXSsoPz1cXHMqXFwoKS9pO1xuY29uc3QgcmVfTkVXTElORSA9IC9eXFxuKy87XG5jb25zdCByZV9XSElURVNQQUNFID0gL15bIFxcZlxcclxcdFxcdlxcdTAwYTBcXHUxNjgwXFx1MjAwMC1cXHUyMDBhXFx1MjAyOFxcdTIwMjlcXHUyMDJmXFx1MjA1ZlxcdTMwMDBcXHVmZWZmXSsvO1xuY29uc3QgcmVfU1RSSU5HID0gL15cIig/OlwiXCJ8W15cIl0pKihcInwkKS87XG5jb25zdCByZV9QQVRIX1FVT1RFID0gL14nKD86Jyd8W14nXSkqKCd8JCkvO1xuY29uc3QgcmVfUEFUSF9CUkFDRSA9IC9eXFxbKD86W15cXF1dKSsoXFxdfCQpLztcbmNvbnN0IHJlX1BBVEhfUFJFRklYID0gL14oW14gXFx0XFxuJCFcImAnIyUmKCl7fTw+LDs6XkB8fj0qKy1dKykoPz0hKS87IC8vIFNoZWV0czogW146XFxcXC8/KltcXF1dezAsMzF9IChidXQgV0IgbmFtZXM/KVxuY29uc3QgcmVfQTFDT0wgPSAvXlxcJD9bQS1aXXsxLDN9OlxcJD9bQS1aXXsxLDN9L2k7XG5jb25zdCByZV9BMVJPVyA9IC9eXFwkP1sxLTldWzAtOV17MCw2fTpcXCQ/WzEtOV1bMC05XXswLDZ9L2k7XG5jb25zdCByZV9BMVJBTkdFID0gL15cXCQ/W0EtWl17MSwzfVxcJD9bMS05XVswLTldezAsNn0vaTtcbmNvbnN0IHJQYXJ0ID0gJyg/OlIoPzpcXFxcW1srLV0/XFxcXGQrXFxcXF18WzEtOV1bMC05XXswLDZ9KT8pJztcbmNvbnN0IGNQYXJ0ID0gJyg/OkMoPzpcXFxcW1srLV0/XFxcXGQrXFxcXF18WzEtOV1bMC05XXswLDR9KT8pJztcbmNvbnN0IHJlX1JDQ09MID0gbmV3IFJlZ0V4cChgXiR7Y1BhcnR9KDoke2NQYXJ0fSk/KD89XFxcXFd8JClgLCAnaScpO1xuY29uc3QgcmVfUkNST1cgPSBuZXcgUmVnRXhwKGBeJHtyUGFydH0oOiR7clBhcnR9KT8oPz1cXFxcV3wkKWAsICdpJyk7XG5jb25zdCByZV9SQ1JBTkdFID0gbmV3IFJlZ0V4cChgXig/Oig/PVtSQ10pJHtyUGFydH0ke2NQYXJ0fSlgLCAnaScpO1xuY29uc3QgcmVfTlVNQkVSID0gL14oPzpcXGQrKFxcLlxcZCspPyg/OltlRV1bKy1dP1xcZCspP3xcXGQrKS87XG5jb25zdCByZV9OQU1FRCA9IC9eW0EtWlxcZFxcXFxfLj9dKy9pOyAvLyBGSVhNRSB0aGVyZSBhcmUgc3RyaWN0ZXIgcnVsZXMgZm9yIHRoaXMhXG4vLyBjb25zdCByZV9OQU1FRCA9IC9eKD8hW1JDXSQpW0EtWsOALcizX1xcXFxdW1xcXFw/XFx3w4AtyLMuXXswLDI1NX0kL2k7XG5cbmV4cG9ydCBjb25zdCB0b2tlbkhhbmRsZXJzQTEgPSBbXG4gIFsgRVJST1IsICAgICAgIHJlX0VSUk9SIF0sXG4gIFsgT1BFUkFUT1IsICAgIHJlX09QRVJBVE9SIF0sXG4gIFsgQk9PTEVBTiwgICAgIHJlX0JPT0xFQU4gXSxcbiAgWyBGVU5DVElPTiwgICAgcmVfRlVOQ1RJT04gXSxcbiAgWyBORVdMSU5FLCAgICAgcmVfTkVXTElORSBdLFxuICBbIFdISVRFU1BBQ0UsICByZV9XSElURVNQQUNFIF0sXG4gIFsgU1RSSU5HLCAgICAgIHJlX1NUUklORyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfQTFSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZUExIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX0ExQ09MLCBxdWlja1ZlcmlmeVJhbmdlQTEgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfQTFST1csIHF1aWNrVmVyaWZ5UmFuZ2VBMSBdLFxuICBbIE5VTUJFUiwgICAgICByZV9OVU1CRVIgXSxcbiAgWyBSQU5HRV9OQU1FRCwgcmVfTkFNRUQgXVxuXTtcblxuZXhwb3J0IGNvbnN0IHRva2VuSGFuZGxlcnNSQyA9IFtcbiAgWyBFUlJPUiwgICAgICAgcmVfRVJST1IgXSxcbiAgWyBPUEVSQVRPUiwgICAgcmVfT1BFUkFUT1IgXSxcbiAgWyBCT09MRUFOLCAgICAgcmVfQk9PTEVBTiBdLFxuICBbIEZVTkNUSU9OLCAgICByZV9GVU5DVElPTiBdLFxuICBbIE5FV0xJTkUsICAgICByZV9ORVdMSU5FIF0sXG4gIFsgV0hJVEVTUEFDRSwgIHJlX1dISVRFU1BBQ0UgXSxcbiAgWyBTVFJJTkcsICAgICAgcmVfU1RSSU5HIF0sXG4gIFsgUEFUSF9RVU9URSwgIHJlX1BBVEhfUVVPVEUgXSxcbiAgWyBQQVRIX0JSQUNFLCAgcmVfUEFUSF9CUkFDRSBdLFxuICBbIFBBVEhfUFJFRklYLCByZV9QQVRIX1BSRUZJWCBdLFxuICBbIFJBTkdFLCAgICAgICByZV9SQ1JBTkdFLCBxdWlja1ZlcmlmeVJhbmdlUkMgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfUkNST1csIHF1aWNrVmVyaWZ5UmFuZ2VSQyBdLFxuICBbIFJBTkdFX0JFQU0sICByZV9SQ0NPTCwgcXVpY2tWZXJpZnlSYW5nZVJDIF0sXG4gIFsgTlVNQkVSLCAgICAgIHJlX05VTUJFUiBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuXG5leHBvcnQgY29uc3QgdG9rZW5IYW5kbGVyc1JlZnNBMSA9IFtcbiAgWyBPUEVSQVRPUiwgICAgL15bITpdLyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfQTFSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZUExIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX0ExQ09MLCBxdWlja1ZlcmlmeVJhbmdlQTEgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfQTFST1csIHF1aWNrVmVyaWZ5UmFuZ2VBMSBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuXG5leHBvcnQgY29uc3QgdG9rZW5IYW5kbGVyc1JlZnNSQyA9IFtcbiAgWyBPUEVSQVRPUiwgICAgL14hLyBdLFxuICBbIFBBVEhfUVVPVEUsICByZV9QQVRIX1FVT1RFIF0sXG4gIFsgUEFUSF9CUkFDRSwgIHJlX1BBVEhfQlJBQ0UgXSxcbiAgWyBQQVRIX1BSRUZJWCwgcmVfUEFUSF9QUkVGSVggXSxcbiAgWyBSQU5HRSwgICAgICAgcmVfUkNSQU5HRSwgcXVpY2tWZXJpZnlSYW5nZVJDIF0sXG4gIFsgUkFOR0VfQkVBTSwgIHJlX1JDUk9XLCBxdWlja1ZlcmlmeVJhbmdlUkMgXSxcbiAgWyBSQU5HRV9CRUFNLCAgcmVfUkNDT0wsIHF1aWNrVmVyaWZ5UmFuZ2VSQyBdLFxuICBbIFJBTkdFX05BTUVELCByZV9OQU1FRCBdXG5dO1xuIiwiaW1wb3J0IHtcbiAgRlhfUFJFRklYLFxuICBORVdMSU5FLFxuICBOVU1CRVIsXG4gIE9QRVJBVE9SLFxuICBQQVRIX0JSQUNFLFxuICBQQVRIX1BSRUZJWCxcbiAgUEFUSF9RVU9URSxcbiAgUkFOR0UsXG4gIFJBTkdFX0JFQU0sXG4gIFJBTkdFX05BTUVELFxuICBTVFJJTkcsXG4gIFVOS05PV04sXG4gIFdISVRFU1BBQ0UsXG4gIHRva2VuSGFuZGxlcnNBMSxcbiAgdG9rZW5IYW5kbGVyc1JDXG59IGZyb20gJy4vY29uc3RhbnRzLmpzJztcblxuY29uc3QgaXNUeXBlID0gKHQsIHR5cGUpID0+IHQgJiYgdC50eXBlID09PSB0eXBlO1xuY29uc3QgaXNSYW5nZU9wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICc6JztcbmNvbnN0IGlzQmFuZ09wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICchJztcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gIGVtaXRSYW5nZXM6IGZhbHNlLFxuICBtZXJnZVJhbmdlczogdHJ1ZSxcbiAgbmVnYXRpdmVOdW1iZXJzOiBmYWxzZSxcbiAgcjFjMTogZmFsc2Vcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUb2tlbnMgKGZ4LCB0b2tlbkhhbmRsZXJzLCBvcHRpb25zID0ge30pIHtcbiAgY29uc3QgeyBlbWl0UmFuZ2VzLCBtZXJnZVJhbmdlcywgbmVnYXRpdmVOdW1iZXJzIH0gPSBPYmplY3QuYXNzaWduKHt9LCBkZWZhdWx0T3B0aW9ucywgb3B0aW9ucyk7XG4gIGNvbnN0IHRva2VucyA9IFtdO1xuICBsZXQgcG9zID0gMDtcbiAgY29uc3QgbG9va0JlaGluZCA9IG4gPT4gdG9rZW5zW3Rva2Vucy5sZW5ndGggLSBuXTtcbiAgY29uc3QgbG9va0JlaGluZElnbm9yZVdTID0gbiA9PiB7XG4gICAgY29uc3Qgbm9XcyA9IHRva2Vucy5maWx0ZXIodCA9PiAhaXNUeXBlKHQsIFdISVRFU1BBQ0UpICYmICFpc1R5cGUodCwgTkVXTElORSkpO1xuICAgIHJldHVybiBub1dzW25vV3MubGVuZ3RoIC0gbl07XG4gIH07XG5cbiAgaWYgKC9ePS8udGVzdChmeCkpIHtcbiAgICBjb25zdCB0b2tlbiA9IHtcbiAgICAgIHR5cGU6IEZYX1BSRUZJWCxcbiAgICAgIHZhbHVlOiAnPScsXG4gICAgICAuLi4oZW1pdFJhbmdlcyA/IHsgcmFuZ2U6IFsgMCwgMSBdIH0gOiB7fSlcbiAgICB9O1xuICAgIHBvcysrO1xuICAgIHRva2Vucy5wdXNoKHRva2VuKTtcbiAgfVxuXG4gIHdoaWxlIChwb3MgPCBmeC5sZW5ndGgpIHtcbiAgICBjb25zdCBzdGFydFBvcyA9IHBvcztcbiAgICBjb25zdCBzID0gZnguc2xpY2UocG9zKTtcbiAgICBsZXQgdG9rZW5UeXBlID0gJyc7XG4gICAgbGV0IHRva2VuVmFsdWUgPSAnJztcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRva2VuSGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IFsgdHlwZSwgcmVUZXN0LCBmblRlc3QgXSA9IHRva2VuSGFuZGxlcnNbaV07XG4gICAgICBjb25zdCBtID0gcmVUZXN0LmV4ZWMocyk7XG4gICAgICBpZiAobSAmJiAoIWZuVGVzdCB8fCBmblRlc3QobVswXSkpKSB7XG4gICAgICAgIHRva2VuVHlwZSA9IHR5cGU7XG4gICAgICAgIHRva2VuVmFsdWUgPSBtWzBdO1xuICAgICAgICBwb3MgKz0gbVswXS5sZW5ndGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghdG9rZW5UeXBlKSB7XG4gICAgICB0b2tlblR5cGUgPSBVTktOT1dOO1xuICAgICAgdG9rZW5WYWx1ZSA9IGZ4W3Bvc107XG4gICAgICBwb3MrKztcbiAgICB9XG5cbiAgICBsZXQgdG9rZW4gPSB7XG4gICAgICB0eXBlOiB0b2tlblR5cGUsXG4gICAgICB2YWx1ZTogdG9rZW5WYWx1ZSxcbiAgICAgIC4uLihlbWl0UmFuZ2VzID8geyByYW5nZTogWyBzdGFydFBvcywgcG9zIF0gfSA6IHt9KVxuICAgIH07XG5cbiAgICBpZiAodG9rZW5UeXBlID09PSBTVFJJTkcgJiYgIXRva2VuVmFsdWUuZW5kc1dpdGgoJ1wiJykpIHtcbiAgICAgIHRva2VuLnVudGVybWluYXRlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKG5lZ2F0aXZlTnVtYmVycyAmJiB0b2tlblR5cGUgPT09IE5VTUJFUikge1xuICAgICAgY29uc3QgbGFzdDEgPSBsb29rQmVoaW5kKDEpO1xuICAgICAgaWYgKGxhc3QxICYmIGlzVHlwZShsYXN0MSwgT1BFUkFUT1IpICYmIGxhc3QxLnZhbHVlID09PSAnLScpIHtcbiAgICAgICAgLy8gd2UgaGF2ZSBhIG51bWJlciBwcmVjZWRlZCBieSBhIG1pbnVzXG4gICAgICAgIGNvbnN0IGxhc3QyID0gbG9va0JlaGluZElnbm9yZVdTKDIpO1xuICAgICAgICAvLyBtaXNzaW5nIGxhc3QyIG1lYW5zIHdlIGFyZSBhdCB0aGUgc3RhcnQgb2YgdGhlIHN0cmVhbVxuICAgICAgICBpZiAoIWxhc3QyIHx8IGlzVHlwZShsYXN0MiwgRlhfUFJFRklYKSB8fCAoaXNUeXBlKGxhc3QyLCBPUEVSQVRPUikgJiYgIVsgJyUnLCAnfScsICcpJywgJyMnIF0uaW5jbHVkZXMobGFzdDIudmFsdWUpKSkge1xuICAgICAgICAgIHRva2Vucy5wb3AoKTtcbiAgICAgICAgICB0b2tlbi52YWx1ZSA9ICctJyArIHRva2VuVmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobWVyZ2VSYW5nZXMpIHtcbiAgICAgIGlmICh0b2tlblR5cGUgPT09IFJBTkdFIHx8IHRva2VuVHlwZSA9PT0gUkFOR0VfTkFNRUQgfHwgdG9rZW5UeXBlID09PSBSQU5HRV9CRUFNKSB7XG4gICAgICAgIGNvbnN0IG1lcmdlID0gW107XG4gICAgICAgIC8vIGpvaW4gQTE6QTEgb3IgUkM6UkMtXG4gICAgICAgIGlmIChpc1JhbmdlT3AobG9va0JlaGluZCgxKSkgJiYgaXNUeXBlKGxvb2tCZWhpbmQoMiksIFJBTkdFKSAmJiB0b2tlblR5cGUgPT09IFJBTkdFKSB7XG4gICAgICAgICAgLy8gc2hvdWxkIG5vdCBiZSBkb25lIHRoaXMgaWYgY3VycmVudCBvciBsYXN0IHJhbmdlcyBhcmUgQTpBIG9yIDE6MSwgb3IgUiBvciBDKVxuICAgICAgICAgIG1lcmdlLnVuc2hpZnQoLi4udG9rZW5zLnNwbGljZSgtMiwgMikpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGpvaW4gcHJlZml4ZXNcbiAgICAgICAgaWYgKGlzQmFuZ09wKGxvb2tCZWhpbmQoMSkpKSB7XG4gICAgICAgICAgaWYgKGlzVHlwZShsb29rQmVoaW5kKDIpLCBQQVRIX1FVT1RFKSB8fCBpc1R5cGUobG9va0JlaGluZCgyKSwgUEFUSF9CUkFDRSkpIHtcbiAgICAgICAgICAgIG1lcmdlLnVuc2hpZnQoLi4udG9rZW5zLnNwbGljZSgtMiwgMikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmIChpc1R5cGUobG9va0JlaGluZCgyKSwgUEFUSF9QUkVGSVgpKSB7XG4gICAgICAgICAgICBjb25zdCBuID0gaXNUeXBlKGxvb2tCZWhpbmQoMyksIFBBVEhfQlJBQ0UpID8gMyA6IDI7XG4gICAgICAgICAgICBtZXJnZS51bnNoaWZ0KC4uLnRva2Vucy5zcGxpY2UoLW4sIG4pKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gd2FudCB0byBtZXJnZT9cbiAgICAgICAgaWYgKG1lcmdlLmxlbmd0aCkge1xuICAgICAgICAgIHRva2VuID0ge1xuICAgICAgICAgICAgdHlwZTogdG9rZW5UeXBlLFxuICAgICAgICAgICAgdmFsdWU6IG1lcmdlLm1hcChkID0+IGQudmFsdWUpLmpvaW4oJycpICsgdG9rZW5WYWx1ZSxcbiAgICAgICAgICAgIC4uLihlbWl0UmFuZ2VzID8geyByYW5nZTogWyBtZXJnZVswXS5yYW5nZVswXSwgcG9zIF0gfSA6IHt9KVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdG9rZW5zLnB1c2godG9rZW4pO1xuICB9XG5cbiAgcmV0dXJuIHRva2Vucztcbn1cblxuLy8gRm9ybXVsYXMgY2FuIGVpdGhlciBoYXZlIFJDIG9yIEExIHN0eWxlIHJlZnMsIG5vdCBib3RoOiBiZWNhdXNlIEMxIGFuZCBSMSBhcmUgYm90aCFcbi8vIFJlZm1vZGU6IEExIHwgUkMgfCBBbm9zdGljIGVtaXQgcmFuZ2VzIHdpdGggUkFOR0VcbmV4cG9ydCBmdW5jdGlvbiB0b2tlbml6ZSAoZngsIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB0b2tlbkhhbmRsZXJzID0gb3B0aW9ucy5yMWMxID8gdG9rZW5IYW5kbGVyc1JDIDogdG9rZW5IYW5kbGVyc0ExO1xuICByZXR1cm4gZ2V0VG9rZW5zKGZ4LCB0b2tlbkhhbmRsZXJzLCBvcHRpb25zKTtcbn1cbiIsImltcG9ydCB7IEZYX1BSRUZJWCwgUEFUSF9CUkFDRSwgUEFUSF9QUkVGSVgsIFBBVEhfUVVPVEUsIFJBTkdFLCBSQU5HRV9OQU1FRCwgUkFOR0VfQkVBTSB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGdldFRva2VucyB9IGZyb20gJy4vbGV4ZXIuanMnO1xuXG5jb25zdCB1bnF1b3RlID0gZCA9PiBkLnNsaWNlKDEsIC0xKS5yZXBsYWNlKC8nJy9nLCBcIidcIik7XG5cbmNvbnN0IHBSYW5nZU9wID0gdCA9PiB0ICYmIHQudmFsdWUgPT09ICc6JyAmJiB7fTtcbmNvbnN0IHBSYW5nZSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFJBTkdFICYmIHsgcjA6IHQudmFsdWUgfTtcbmNvbnN0IHBSYW5nZTIgPSB0ID0+IHQgJiYgdC50eXBlID09PSBSQU5HRSAmJiB7IHIxOiB0LnZhbHVlIH07XG5jb25zdCBwQmFuZyA9IHQgPT4gdCAmJiB0LnZhbHVlID09PSAnIScgJiYge307XG5jb25zdCBwQmVhbSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFJBTkdFX0JFQU0gJiYgeyByMDogdC52YWx1ZSB9O1xuY29uc3QgcFNoZWV0ID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUEFUSF9QUkVGSVggJiYgL15bXjpcXFxcLz8qW1xcXV17MCwzMX0kLy50ZXN0KHQudmFsdWUpICYmIHsgc2hlZXROYW1lOiB0LnZhbHVlIH07XG5jb25zdCBwRmlsZSA9IHQgPT4gdCAmJiB0LnR5cGUgPT09IFBBVEhfQlJBQ0UgJiYgeyB3b3JrYm9va05hbWU6IHQudmFsdWUuc2xpY2UoMSwgLTEpIH07XG5jb25zdCBwRmlsZTIgPSB0ID0+IHQgJiYgdC50eXBlID09PSBQQVRIX1BSRUZJWCAmJiB7IHdvcmtib29rTmFtZTogdC52YWx1ZSB9O1xuY29uc3QgcE5hbWVkID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUkFOR0VfTkFNRUQgJiYgeyBuYW1lOiB0LnZhbHVlIH07XG5cbmNvbnN0IHBRdW90ZWQgPSB0ID0+IHtcbiAgaWYgKHQgJiYgdC50eXBlID09PSBQQVRIX1FVT1RFKSB7XG4gICAgY29uc3QgbSA9IC8oPzpcXFsoLis/KVxcXSk/KFteW1xcXV0rPykkLy5leGVjKHVucXVvdGUodC52YWx1ZSkpO1xuICAgIGlmIChtKSB7XG4gICAgICBjb25zdCBbICwgZmlsZSwgc2hlZXQgXSA9IG07XG4gICAgICBpZiAoIXNoZWV0IHx8IC9eW146XFxcXC8/KltcXF1dezAsMzF9JC8udGVzdChzaGVldCkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB3b3JrYm9va05hbWU6IGZpbGUgfHwgJycsXG4gICAgICAgICAgc2hlZXROYW1lOiBzaGVldCB8fCAnJ1xuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcbmNvbnN0IHBRdW90ZWQyID0gdCA9PiB0ICYmIHQudHlwZSA9PT0gUEFUSF9RVU9URSAmJiB7IHdvcmtib29rTmFtZTogdW5xdW90ZSh0LnZhbHVlKSB9O1xuXG5jb25zdCB2YWxpZFJ1bnMgPSBbXG4gIFsgcFJhbmdlIF0sXG4gIFsgcFJhbmdlLCBwUmFuZ2VPcCwgcFJhbmdlMiBdLFxuICBbIHBCZWFtIF0sXG4gIFsgcFF1b3RlZCwgcEJhbmcsIHBSYW5nZSBdLFxuICBbIHBRdW90ZWQsIHBCYW5nLCBwUmFuZ2UsIHBSYW5nZU9wLCBwUmFuZ2UyIF0sXG4gIFsgcFF1b3RlZCwgcEJhbmcsIHBCZWFtIF0sXG4gIFsgcFNoZWV0LCBwQmFuZywgcFJhbmdlIF0sXG4gIFsgcFNoZWV0LCBwQmFuZywgcFJhbmdlLCBwUmFuZ2VPcCwgcFJhbmdlMiBdLFxuICBbIHBTaGVldCwgcEJhbmcsIHBCZWFtIF0sXG4gIFsgcEZpbGUsIHBTaGVldCwgcEJhbmcsIHBSYW5nZSBdLFxuICBbIHBGaWxlLCBwU2hlZXQsIHBCYW5nLCBwUmFuZ2UsIHBSYW5nZU9wLCBwUmFuZ2UyIF0sXG4gIFsgcEZpbGUsIHBTaGVldCwgcEJhbmcsIHBCZWFtIF1cbl07XG5cbmNvbnN0IHZhbGlkUnVuc05hbWVkID0gdmFsaWRSdW5zLmNvbmNhdChbXG4gIFsgcE5hbWVkIF0sXG4gIFsgcEZpbGUyLCBwQmFuZywgcE5hbWVkIF0sXG4gIFsgcFF1b3RlZDIsIHBCYW5nLCBwTmFtZWQgXVxuXSk7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJlZiAocmVmLCBhbGxvd19uYW1lZCA9IHRydWUsIHRva2VuSGFuZGxlcnMgPSBbXSkge1xuICBjb25zdCB0b2tlbnMgPSBnZXRUb2tlbnMocmVmLCB0b2tlbkhhbmRsZXJzLCB7XG4gICAgZW1pdFJhbmdlczogZmFsc2UsXG4gICAgbWVyZ2VSYW5nZXM6IGZhbHNlXG4gIH0pO1xuICBjb25zdCByZWZEYXRhID0ge1xuICAgIHNoZWV0TmFtZTogJycsXG4gICAgd29ya2Jvb2tOYW1lOiAnJyxcbiAgICByMDogJycsXG4gICAgcjE6ICcnLFxuICAgIG5hbWU6ICcnXG4gIH07XG4gIC8vIGRpc2NhcmQgdGhlIFwiPVwiLXByZWZpeCBpZiBpdCBpcyB0aGVyZVxuICBpZiAodG9rZW5zLmxlbmd0aCAmJiB0b2tlbnNbMF0udHlwZSA9PT0gRlhfUFJFRklYKSB7XG4gICAgdG9rZW5zLnNoaWZ0KCk7XG4gIH1cbiAgY29uc3QgcnVucyA9IGFsbG93X25hbWVkID8gdmFsaWRSdW5zTmFtZWQgOiB2YWxpZFJ1bnM7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcnVucy5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IGRhdGEgPSB7IC4uLnJlZkRhdGEgfTtcbiAgICBpZiAocnVuc1tpXS5sZW5ndGggPT09IHRva2Vucy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHZhbGlkID0gcnVuc1tpXS5ldmVyeSgocGFyc2UsIGopID0+IHtcbiAgICAgICAgY29uc3QgZCA9IHBhcnNlKHRva2Vuc1tqXSk7XG4gICAgICAgIE9iamVjdC5hc3NpZ24oZGF0YSwgZCk7XG4gICAgICAgIHJldHVybiBkO1xuICAgICAgfSk7XG4gICAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuIiwiaW1wb3J0IHsgTUFYX1JPV1MsIE1BWF9DT0xTLCB0b2tlbkhhbmRsZXJzUmVmc0ExIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgcGFyc2VSZWYgfSBmcm9tICcuL3BhcnNlUmVmLmpzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGZyb21Db2wgKGNvbFN0cikge1xuICBjb25zdCBjID0gKGNvbFN0ciB8fCAnJykudG9VcHBlckNhc2UoKTtcbiAgbGV0IGQgPSAwO1xuICBsZXQgaSA9IDA7XG4gIGZvciAoOyBpICE9PSBjLmxlbmd0aDsgKytpKSB7XG4gICAgY29uc3QgY2hyID0gYy5jaGFyQ29kZUF0KGkpO1xuICAgIGlmIChjaHIgPj0gNjUgJiYgY2hyIDw9IDkwKSB7IC8vIG9taXRzIGFueSBub24gQS1aIGNoYXJhY3RlclxuICAgICAgZCA9IDI2ICogZCArIGNociAtIDY0O1xuICAgIH1cbiAgfVxuICByZXR1cm4gZCAtIDE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB0b0NvbCAobGVmdCkge1xuICBsZXQgbiA9IGxlZnQ7XG4gIGxldCBjID0gJyc7XG4gIHdoaWxlIChuID49IDApIHtcbiAgICBjID0gU3RyaW5nLmZyb21DaGFyQ29kZShuICUgMjYgKyA2NSkgKyBjO1xuICAgIG4gPSBNYXRoLmZsb29yKG4gLyAyNikgLSAxO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJvdyAocm93U3RyKSB7XG4gIHJldHVybiArcm93U3RyIC0gMTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUm93ICh0b3ApIHtcbiAgcmV0dXJuIFN0cmluZyh0b3AgKyAxKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUmVsYXRpdmUgKHJhbmdlKSB7XG4gIGNvbnN0IHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0IH0gPSByYW5nZTtcbiAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkbGVmdDogZmFsc2UsICRyaWdodDogZmFsc2UsICR0b3A6IGZhbHNlLCAkYm90dG9tOiBmYWxzZSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9BYnNvbHV0ZSAocmFuZ2UpIHtcbiAgY29uc3QgeyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQgfSA9IHJhbmdlO1xuICByZXR1cm4geyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsICRsZWZ0OiB0cnVlLCAkcmlnaHQ6IHRydWUsICR0b3A6IHRydWUsICRib3R0b206IHRydWUgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvQTEgKHJhbmdlKSB7XG4gIGNvbnN0IHRvQWJzID0gZCA9PiAoZCA/ICckJyA6ICcnKTtcbiAgY29uc3QgeyB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsICRsZWZ0LCAkcmlnaHQsICR0b3AsICRib3R0b20gfSA9IHJhbmdlO1xuICAvLyBBOkFcbiAgaWYgKHRvcCA9PT0gMCAmJiBib3R0b20gPT09IE1BWF9ST1dTKSB7XG4gICAgcmV0dXJuIHRvQWJzKCRsZWZ0KSArIHRvQ29sKGxlZnQpICsgJzonICsgdG9BYnMoJHJpZ2h0KSArIHRvQ29sKHJpZ2h0KTtcbiAgfVxuICAvLyAxOjFcbiAgaWYgKGxlZnQgPT09IDAgJiYgcmlnaHQgPT09IE1BWF9DT0xTKSB7XG4gICAgcmV0dXJuIHRvQWJzKCR0b3ApICsgdG9Sb3codG9wKSArICc6JyArIHRvQWJzKCRib3R0b20pICsgdG9Sb3coYm90dG9tKTtcbiAgfVxuICAvLyBBMTpBMVxuICBpZiAocmlnaHQgIT0gbnVsbCAmJiBib3R0b20gIT0gbnVsbCAmJiAocmlnaHQgIT09IGxlZnQgfHwgYm90dG9tICE9PSB0b3ApKSB7XG4gICAgcmV0dXJuIHRvQWJzKCRsZWZ0KSArIHRvQ29sKGxlZnQpICsgdG9BYnMoJHRvcCkgKyB0b1Jvdyh0b3ApICsgJzonICsgdG9BYnMoJHJpZ2h0KSArIHRvQ29sKHJpZ2h0KSArIHRvQWJzKCRib3R0b20pICsgdG9Sb3coYm90dG9tKTtcbiAgfVxuICAvLyBBMVxuICByZXR1cm4gdG9BYnMoJGxlZnQpICsgdG9Db2wobGVmdCkgKyB0b0FicygkdG9wKSArIHRvUm93KHRvcCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tQTEgKHJhbmdlU3RyKSB7XG4gIGxldCBtO1xuICBsZXQgdG9wID0gMDtcbiAgbGV0IGxlZnQgPSAwO1xuICBsZXQgYm90dG9tID0gTUFYX1JPV1M7XG4gIGxldCByaWdodCA9IE1BWF9DT0xTO1xuICBsZXQgJHRvcCA9IGZhbHNlO1xuICBsZXQgJGxlZnQgPSBmYWxzZTtcbiAgbGV0ICRib3R0b20gPSBmYWxzZTtcbiAgbGV0ICRyaWdodCA9IGZhbHNlO1xuICAvLyBBOkFcbiAgaWYgKChtID0gL14oXFwkPykoW0EtWl17MSwzfSk6KFxcJD8pKFtBLVpdezEsM30pJC8uZXhlYyhyYW5nZVN0cikpKSB7XG4gICAgY29uc3QgYSA9IGZyb21Db2wobVsyXSk7XG4gICAgY29uc3QgYiA9IGZyb21Db2wobVs0XSk7XG4gICAgbGVmdCA9IE1hdGgubWluKGEsIGIpO1xuICAgIHJpZ2h0ID0gTWF0aC5tYXgoYSwgYik7XG4gICAgJGxlZnQgPSAhIW1bYSA8PSBiID8gMSA6IDNdO1xuICAgICRyaWdodCA9ICEhbVthIDw9IGIgPyAzIDogMV07XG4gICAgJHRvcCA9IHRydWU7XG4gICAgJGJvdHRvbSA9IHRydWU7XG4gICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gIH1cbiAgLy8gMToxXG4gIGVsc2UgaWYgKChtID0gL14oXFwkPykoWzEtOV1cXGR7MCw2fSk6KFxcJD8pKFsxLTldXFxkezAsNn0pJC8uZXhlYyhyYW5nZVN0cikpKSB7XG4gICAgY29uc3QgYSA9IGZyb21Sb3cobVsyXSk7XG4gICAgY29uc3QgYiA9IGZyb21Sb3cobVs0XSk7XG4gICAgdG9wID0gTWF0aC5taW4oYSwgYik7XG4gICAgYm90dG9tID0gTWF0aC5tYXgoYSwgYik7XG4gICAgJHRvcCA9ICEhbVthIDw9IGIgPyAxIDogM107XG4gICAgJGJvdHRvbSA9ICEhbVthIDw9IGIgPyAzIDogMV07XG4gICAgJGxlZnQgPSB0cnVlO1xuICAgICRyaWdodCA9IHRydWU7XG4gICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gIH1cbiAgLy8gQTEgfCBBMTpCMlxuICBlbHNlIHtcbiAgICBjb25zdCBbIHBhcnQxLCBwYXJ0MiBdID0gcmFuZ2VTdHIuc3BsaXQoJzonKTtcbiAgICBpZiAoKG0gPSAvXihcXCQ/KShbQS1aXXsxLDN9KShcXCQ/KShbMS05XVxcZHswLDZ9KSQvaS5leGVjKHBhcnQxKSkpIHtcbiAgICAgIGxlZnQgPSBmcm9tQ29sKG1bMl0pO1xuICAgICAgdG9wID0gZnJvbVJvdyhtWzRdKTtcbiAgICAgICRsZWZ0ID0gISFtWzFdO1xuICAgICAgJHRvcCA9ICEhbVszXTtcbiAgICAgIGlmIChwYXJ0MiAmJiAobSA9IC9eKFxcJD8pKFtBLVpdezEsM30pKFxcJD8pKFsxLTldXFxkezAsNn0pJC9pLmV4ZWMocGFydDIpKSkge1xuICAgICAgICByaWdodCA9IGZyb21Db2wobVsyXSk7XG4gICAgICAgIGJvdHRvbSA9IGZyb21Sb3cobVs0XSk7XG4gICAgICAgICRyaWdodCA9ICEhbVsxXTtcbiAgICAgICAgJGJvdHRvbSA9ICEhbVszXTtcbiAgICAgICAgLy8gbmVlZCB0byBmbGlwP1xuICAgICAgICBpZiAoYm90dG9tIDwgdG9wKSB7XG4gICAgICAgICAgWyB0b3AsIGJvdHRvbSwgJHRvcCwgJGJvdHRvbSBdID0gWyBib3R0b20sIHRvcCwgJGJvdHRvbSwgJHRvcCBdO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyaWdodCA8IGxlZnQpIHtcbiAgICAgICAgICBbIGxlZnQsIHJpZ2h0LCAkbGVmdCwgJHJpZ2h0IF0gPSBbIHJpZ2h0LCBsZWZ0LCAkcmlnaHQsICRsZWZ0IF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBib3R0b20gPSB0b3A7XG4gICAgICAgIHJpZ2h0ID0gbGVmdDtcbiAgICAgICAgJGJvdHRvbSA9ICR0b3A7XG4gICAgICAgICRyaWdodCA9ICRsZWZ0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHsgdG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0LCAkdG9wLCAkbGVmdCwgJGJvdHRvbSwgJHJpZ2h0IH07XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBMVJlZiAocmVmLCBhbGxvd19uYW1lZCA9IHRydWUpIHtcbiAgY29uc3QgZCA9IHBhcnNlUmVmKHJlZiwgYWxsb3dfbmFtZWQsIHRva2VuSGFuZGxlcnNSZWZzQTEpO1xuICBpZiAoZCAmJiAoZC5yMCB8fCBkLm5hbWUpKSB7XG4gICAgbGV0IHJhbmdlID0gbnVsbDtcbiAgICBpZiAoZC5yMCkge1xuICAgICAgcmFuZ2UgPSBkLnIxID8gZnJvbUExKGQucjAgKyAnOicgKyBkLnIxKSA6IGZyb21BMShkLnIwKTtcbiAgICB9XG4gICAgaWYgKGQubmFtZSB8fCByYW5nZSkge1xuICAgICAgZC5yYW5nZSA9IHJhbmdlO1xuICAgICAgZGVsZXRlIGQucjA7XG4gICAgICBkZWxldGUgZC5yMTtcbiAgICAgIHJldHVybiBkO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVsbDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBmcm9tQ29sLFxuICB0b0NvbCxcbiAgdG9SZWxhdGl2ZSxcbiAgdG9BYnNvbHV0ZSxcbiAgdG86IHRvQTEsXG4gIGZyb206IGZyb21BMSxcbiAgcGFyc2U6IHBhcnNlQTFSZWZcbn07XG4iLCJpbXBvcnQgeyBSQU5HRSwgUkFOR0VfQkVBTSwgVU5LTk9XTiB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHBhcnNlQTFSZWYsIHRvUmVsYXRpdmUsIHRvQTEgfSBmcm9tICcuL2ExLmpzJztcblxuZnVuY3Rpb24gZ2V0SURlciAoKSB7XG4gIGxldCBpID0gMTtcbiAgcmV0dXJuICgpID0+ICdmeGcnICsgKGkrKyk7XG59XG5cbi8vIHdoZW4gY29udGV4dCBpcyBTaGVldDEsIHdlIHNob3VsZCBjb25zaWRlciBTaGVldCFBMSA9PSBBMVxuZXhwb3J0IGZ1bmN0aW9uIGFkZE1ldGEgKHRva2VucywgeyBzaGVldE5hbWUgPSAnJywgd29ya2Jvb2tOYW1lID0gJycgfSA9IHt9KSB7XG4gIGNvbnN0IHBhcmVuU3RhY2sgPSBbXTtcbiAgbGV0IGFycmF5U3RhcnQgPSBudWxsO1xuICBjb25zdCBhMU1hcCA9IHt9O1xuICBjb25zdCB1aWQgPSBnZXRJRGVyKCk7XG5cbiAgdG9rZW5zLmZvckVhY2goKHRva2VuLCBpKSA9PiB7XG4gICAgdG9rZW4uaW5kZXggPSBpO1xuICAgIHRva2VuLmRlcHRoID0gcGFyZW5TdGFjay5sZW5ndGg7XG4gICAgaWYgKHRva2VuLnZhbHVlID09PSAnKCcpIHtcbiAgICAgIHRva2VuLmRlcHRoID0gcGFyZW5TdGFjay5sZW5ndGggKyAxO1xuICAgICAgcGFyZW5TdGFjay5wdXNoKHRva2VuKTtcbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udmFsdWUgPT09ICcpJykge1xuICAgICAgY29uc3QgY291bnRlciA9IHBhcmVuU3RhY2sucG9wKCk7XG4gICAgICBpZiAoY291bnRlcikge1xuICAgICAgICBjb25zdCBwYWlySWQgPSB1aWQoKTtcbiAgICAgICAgdG9rZW4uZ3JvdXBJZCA9IHBhaXJJZDtcbiAgICAgICAgdG9rZW4uZGVwdGggPSBjb3VudGVyLmRlcHRoO1xuICAgICAgICBjb3VudGVyLmdyb3VwSWQgPSBwYWlySWQ7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdG9rZW4uZXJyb3IgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh0b2tlbi52YWx1ZSA9PT0gJ3snKSB7XG4gICAgICBpZiAoIWFycmF5U3RhcnQpIHtcbiAgICAgICAgYXJyYXlTdGFydCA9IHRva2VuO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHRva2VuLmVycm9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udmFsdWUgPT09ICd9Jykge1xuICAgICAgaWYgKGFycmF5U3RhcnQpIHtcbiAgICAgICAgY29uc3QgcGFpcklkID0gdWlkKCk7XG4gICAgICAgIHRva2VuLmdyb3VwSWQgPSBwYWlySWQ7XG4gICAgICAgIGFycmF5U3RhcnQuZ3JvdXBJZCA9IHBhaXJJZDtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0b2tlbi5lcnJvciA9IHRydWU7XG4gICAgICB9XG4gICAgICBhcnJheVN0YXJ0ID0gbnVsbDtcbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udHlwZSA9PT0gUkFOR0UgfHwgdG9rZW4udHlwZSA9PT0gUkFOR0VfQkVBTSkge1xuICAgICAgY29uc3QgcmVmID0gcGFyc2VBMVJlZih0b2tlbi52YWx1ZSwgZmFsc2UpO1xuICAgICAgY29uc3QgYTEgPSByZWYgJiYgKGBbJHtyZWYud29ya2Jvb2tOYW1lIHx8IHdvcmtib29rTmFtZX1dJHtyZWYuc2hlZXROYW1lIHx8IHNoZWV0TmFtZX0hJHtyZWYucmFuZ2UgPyB0b0ExKHRvUmVsYXRpdmUocmVmLnJhbmdlKSkgOiByZWYubmFtZX1gKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKGExKSB7XG4gICAgICAgIGlmIChhMSBpbiBhMU1hcCkge1xuICAgICAgICAgIHRva2VuLmdyb3VwSWQgPSBhMU1hcFthMV07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdG9rZW4uZ3JvdXBJZCA9IHVpZCgpO1xuICAgICAgICAgIGExTWFwW2ExXSA9IHRva2VuLmdyb3VwSWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAodG9rZW4udHlwZSA9PT0gVU5LTk9XTikge1xuICAgICAgdG9rZW4uZXJyb3IgPSB0cnVlO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiB0b2tlbnM7XG59XG4iLCIvKlxuICBSQyBub3RhdGlvbiB3b3JrcyBkaWZmZXJlbnRseSBmcm9tIEExIGluIHRoYXQgd2UgY2FuJ3QgbWVyZ2Ugc3RhdGljIHJlZmVyZW5jZXMgam9pbmVkIGJ5IGA6YC5cbiAgTWVyZ2luZyBjYW4gb25seSB3b3JrIGJldHdlZW4gcmVmZXJlbmNlcyB0aGF0IGFyZSByZWxhdGl2ZS9hYnNvbHV0ZSBvbiB0aGUgc2FtZSBheGVzLCBzbzpcbiAgUjFDMTpSMkMyIHdpbGwgd29yaywgUlsxXUMxOlJbMl1DMiB3aWxsIGFsc28gd29yaywgYnV0IFJbMV1DWzFdOlIyQzIgY2Fubm90IGJlIHJlcHJlc2VudGVkXG4gIHNpbXBseSBieSBhIHJlY3RhbmdsZSBhcyB3aXRob3V0IGtub3dpbmcgdGhlIGNlbGwgY29udGV4dC5cbiovXG5cbmltcG9ydCB7IE1BWF9ST1dTLCBNQVhfQ09MUywgdG9rZW5IYW5kbGVyc1JlZnNSQyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IHBhcnNlUmVmIH0gZnJvbSAnLi9wYXJzZVJlZi5qcyc7XG5cbmZ1bmN0aW9uIHRvQ29vcmQgKHZhbHVlLCBpc0Ficykge1xuICBpZiAoaXNBYnMpIHtcbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlICsgMSk7XG4gIH1cbiAgcmV0dXJuIHZhbHVlID8gJ1snICsgdmFsdWUgKyAnXScgOiAnJztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvUkMgKHJhbmdlKSB7XG4gIGNvbnN0IHsgcjAsIGMwLCByMSwgYzEsICRjMCwgJGMxLCAkcjAsICRyMSB9ID0gcmFuZ2U7XG4gIC8vIEM6Q1xuICBpZiAocjAgPT09IDAgJiYgcjEgPT09IE1BWF9ST1dTKSB7XG4gICAgY29uc3QgYSA9IHRvQ29vcmQoYzAsICRjMCk7XG4gICAgY29uc3QgYiA9IHRvQ29vcmQoYzEsICRjMSk7XG4gICAgcmV0dXJuICdDJyArIChhID09PSBiID8gYSA6IGEgKyAnOkMnICsgYik7XG4gIH1cbiAgLy8gUjpSXG4gIGlmIChjMCA9PT0gMCAmJiBjMSA9PT0gTUFYX0NPTFMpIHtcbiAgICBjb25zdCBhID0gdG9Db29yZChyMCwgJHIwKTtcbiAgICBjb25zdCBiID0gdG9Db29yZChyMSwgJHIxKTtcbiAgICByZXR1cm4gJ1InICsgKGEgPT09IGIgPyBhIDogYSArICc6UicgKyBiKTtcbiAgfVxuICAvLyBSQzpSQ1xuICBjb25zdCBzX3IwID0gdG9Db29yZChyMCwgJHIwKTtcbiAgY29uc3Qgc19yMSA9IHRvQ29vcmQocjEsICRyMSk7XG4gIGNvbnN0IHNfYzAgPSB0b0Nvb3JkKGMwLCAkYzApO1xuICBjb25zdCBzX2MxID0gdG9Db29yZChjMSwgJGMxKTtcbiAgaWYgKHNfcjAgIT09IHNfcjEgfHwgc19jMCAhPT0gc19jMSkge1xuICAgIHJldHVybiAnUicgKyBzX3IwICsgJ0MnICsgc19jMCArICc6UicgKyBzX3IxICsgJ0MnICsgc19jMTtcbiAgfVxuICAvLyBSQ1xuICByZXR1cm4gJ1InICsgc19yMCArICdDJyArIHNfYzA7XG59XG5cbmZ1bmN0aW9uIHBhcnNlUkNQYXJ0IChyZWYpIHtcbiAgbGV0IHIwID0gMDtcbiAgbGV0IGMwID0gMDtcbiAgbGV0IHIxID0gTUFYX1JPV1M7XG4gIGxldCBjMSA9IE1BWF9DT0xTO1xuICBsZXQgJHIwID0gZmFsc2U7XG4gIGxldCAkYzAgPSBmYWxzZTtcbiAgbGV0ICRyMSA9IGZhbHNlO1xuICBsZXQgJGMxID0gZmFsc2U7XG4gIC8vIFIgcGFydFxuICBjb25zdCBybSA9IC9eUig/OlxcWyhbKy1dP1xcZCspXFxdfChcXGQrKSk/Ly5leGVjKHJlZik7XG4gIGlmIChybSkge1xuICAgIGlmIChybVsxXSkge1xuICAgICAgcjAgPSBwYXJzZUludChybVsxXSwgMTApO1xuICAgIH1cbiAgICBlbHNlIGlmIChybVsyXSkge1xuICAgICAgcjAgPSBwYXJzZUludChybVsyXSwgMTApIC0gMTtcbiAgICAgICRyMCA9IHRydWU7XG4gICAgfVxuICAgIHIxID0gcjA7XG4gICAgJHIxID0gJHIwO1xuICAgIHJlZiA9IHJlZi5zbGljZShybVswXS5sZW5ndGgpO1xuICB9XG4gIGVsc2Uge1xuICAgIC8vIHIwID0gMCwgcjEgPSBNQVhfUk9XU1xuICAgICRyMCA9IHRydWU7XG4gICAgJHIxID0gdHJ1ZTtcbiAgfVxuICAvLyBDIHBhcnRcbiAgY29uc3QgY20gPSAvXkMoPzpcXFsoWystXT9cXGQrKVxcXXwoXFxkKykpPy8uZXhlYyhyZWYpO1xuICBpZiAoY20pIHtcbiAgICBpZiAoY21bMV0pIHtcbiAgICAgIGMwID0gcGFyc2VJbnQoY21bMV0sIDEwKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoY21bMl0pIHtcbiAgICAgIGMwID0gcGFyc2VJbnQoY21bMl0sIDEwKSAtIDE7XG4gICAgICAkYzAgPSB0cnVlO1xuICAgIH1cbiAgICBjMSA9IGMwO1xuICAgICRjMSA9ICRjMDtcbiAgICByZWYgPSByZWYuc2xpY2UoY21bMF0ubGVuZ3RoKTtcbiAgfVxuICBlbHNlIHtcbiAgICAvLyBjMCA9IDAsIGMxID0gTUFYX0NPTFNcbiAgICAkYzAgPSB0cnVlO1xuICAgICRjMSA9IHRydWU7XG4gIH1cbiAgLy8gbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBwYXJ0IChhbmQgbm90aGluZyBtb3JlKVxuICBpZiAoKCFybSAmJiAhY20pIHx8IHJlZi5sZW5ndGgpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICByZXR1cm4geyByMCwgYzAsIHIxLCBjMSwgJHIwLCAkYzAsICRyMSwgJGMxIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmcm9tUkMgKHJlZikge1xuICBjb25zdCBbIHBhcnQxLCBwYXJ0MiBdID0gcmVmLnNwbGl0KCc6JywgMik7XG4gIGNvbnN0IHJhbmdlID0gcGFyc2VSQ1BhcnQocGFydDEpO1xuICBpZiAoIXJhbmdlKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgaWYgKHJhbmdlICYmIHBhcnQyKSB7XG4gICAgY29uc3QgZXh0ZW5kVG8gPSBwYXJzZVJDUGFydChwYXJ0Mik7XG4gICAgaWYgKGV4dGVuZFRvKSB7XG4gICAgICAvLyBOb3RlOiBSWy0xXUNbLTFdOlIxQzEgaXMgb25seSBtZWFuaW5nZnVsIG9uY2Ugd2UgaGF2ZSBhbiBhbmNob3JcbiAgICAgIHJhbmdlLnIxID0gZXh0ZW5kVG8ucjE7XG4gICAgICByYW5nZS5jMSA9IGV4dGVuZFRvLmMxO1xuICAgICAgcmFuZ2UuJHIxID0gZXh0ZW5kVG8uJHIxO1xuICAgICAgcmFuZ2UuJGMxID0gZXh0ZW5kVG8uJGMxO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmFuZ2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJDUmVmIChyZWYsIGFsbG93X25hbWVkID0gdHJ1ZSkge1xuICBjb25zdCBkID0gcGFyc2VSZWYocmVmLCBhbGxvd19uYW1lZCwgdG9rZW5IYW5kbGVyc1JlZnNSQyk7XG4gIGlmIChkICYmIChkLnIwIHx8IGQubmFtZSkpIHtcbiAgICBjb25zdCByYW5nZSA9IGQucjEgPyBmcm9tUkMoZC5yMCArICc6JyArIGQucjEpIDogZnJvbVJDKGQucjApO1xuICAgIGlmIChkLm5hbWUgfHwgcmFuZ2UpIHtcbiAgICAgIGQucmFuZ2UgPSByYW5nZTtcbiAgICAgIGRlbGV0ZSBkLnIwO1xuICAgICAgZGVsZXRlIGQucjE7XG4gICAgICByZXR1cm4gZDtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgdG86IHRvUkMsXG4gIGZyb206IGZyb21SQyxcbiAgcGFyc2U6IHBhcnNlUkNSZWZcbn07XG4iLCJpbXBvcnQgeyBSQU5HRSwgUkFOR0VfQkVBTSwgTUFYX1JPV1MsIE1BWF9DT0xTIH0gZnJvbSAnLi9jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgZnJvbUExLCB0b0ExIH0gZnJvbSAnLi9hMS5qcyc7XG5pbXBvcnQgeyBmcm9tUkMsIHRvUkMgfSBmcm9tICcuL3JjLmpzJztcbmltcG9ydCB7IHRva2VuaXplIH0gZnJvbSAnLi9sZXhlci5qcyc7XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2xhdGVUb1JDIChmeCwgYW5jaG9yQ2VsbCkge1xuICBjb25zdCB7IHRvcCwgbGVmdCB9ID0gZnJvbUExKGFuY2hvckNlbGwpO1xuICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBmeCA9PT0gJ3N0cmluZyc7XG5cbiAgY29uc3QgdG9rZW5zID0gaXNTdHJpbmdcbiAgICA/IHRva2VuaXplKGZ4LCB7IGVtaXRSYW5nZXM6IGZhbHNlLCBtZXJnZVJhbmdlczogZmFsc2UsIHIxYzI6IGZhbHNlIH0pXG4gICAgOiBmeDtcblxuICB0b2tlbnMuZm9yRWFjaCh0b2tlbiA9PiB7XG4gICAgaWYgKHRva2VuLnR5cGUgPT09IFJBTkdFKSB7XG4gICAgICBjb25zdCByYW5nZSA9IHt9O1xuICAgICAgY29uc3QgZCA9IGZyb21BMSh0b2tlbi52YWx1ZSk7XG5cbiAgICAgIHJhbmdlLnIwID0gZC4kdG9wID8gZC50b3AgOiBkLnRvcCAtIHRvcDtcbiAgICAgIHJhbmdlLiRyMCA9IGQuJHRvcDtcbiAgICAgIHJhbmdlLnIxID0gZC4kYm90dG9tID8gZC5ib3R0b20gOiBkLmJvdHRvbSAtIHRvcDtcbiAgICAgIHJhbmdlLiRyMSA9IGQuJGJvdHRvbTtcblxuICAgICAgcmFuZ2UuYzAgPSBkLiRsZWZ0ID8gZC5sZWZ0IDogZC5sZWZ0IC0gbGVmdDtcbiAgICAgIHJhbmdlLiRjMCA9IGQuJGxlZnQ7XG4gICAgICByYW5nZS5jMSA9IGQuJHJpZ2h0ID8gZC5yaWdodCA6IGQucmlnaHQgLSBsZWZ0O1xuICAgICAgcmFuZ2UuJGMxID0gZC4kcmlnaHQ7XG5cbiAgICAgIC8vIGNvbnNvbGUuZXJyb3IodG9rZW4udmFsdWUsIGQsIHJhbmdlLCBbIHRvcCwgbGVmdCBdKTtcbiAgICAgIHRva2VuLnZhbHVlID0gdG9SQyhyYW5nZSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHRva2VuLnR5cGUgPT09IFJBTkdFX0JFQU0pIHtcbiAgICAgIGNvbnN0IHJhbmdlID0ge307XG4gICAgICBjb25zdCBkID0gZnJvbUExKHRva2VuLnZhbHVlKTtcblxuICAgICAgcmFuZ2UucjAgPSBkLiR0b3AgPyBkLnRvcCA6IGQudG9wIC0gdG9wO1xuICAgICAgcmFuZ2UuJHIwID0gZC4kdG9wO1xuICAgICAgcmFuZ2UucjEgPSBkLiRib3R0b20gPyBkLmJvdHRvbSA6IGQuYm90dG9tIC0gdG9wO1xuICAgICAgcmFuZ2UuJHIxID0gZC4kYm90dG9tO1xuXG4gICAgICByYW5nZS5jMCA9IGQuJGxlZnQgPyBkLmxlZnQgOiBkLmxlZnQgLSBsZWZ0O1xuICAgICAgcmFuZ2UuJGMwID0gZC4kbGVmdDtcbiAgICAgIHJhbmdlLmMxID0gZC4kcmlnaHQgPyBkLnJpZ2h0IDogZC5yaWdodCAtIGxlZnQ7XG4gICAgICByYW5nZS4kYzEgPSBkLiRyaWdodDtcblxuICAgICAgdG9rZW4udmFsdWUgPSB0b1JDKHJhbmdlKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBpc1N0cmluZ1xuICAgID8gdG9rZW5zLm1hcChkID0+IGQudmFsdWUpLmpvaW4oJycpXG4gICAgOiB0b2tlbnM7XG59XG5cbmZ1bmN0aW9uIHRvRml4ZWQgKHZhbCwgYWJzLCBiYXNlLCBtYXgpIHtcbiAgbGV0IHYgPSB2YWw7XG4gIGlmICghYWJzKSB7XG4gICAgdiA9IGJhc2UgKyB2YWw7XG4gICAgLy8gRXhjZWwgXCJ3cmFwcyBhcm91bmRcIiB3aGVuIHZhbHVlIGdvZXMgb3V0IG9mIGxvd2VyIGJvdW5kcy5cbiAgICAvLyBJdCdzIGEgYml0IHF1aXJreSBvbiBlbnRyeSBhcyBFeGNlbCB3YW50cyB0byByZS1yZXdpdGUgdGhlXG4gICAgLy8gcmVmZXJlbmNlcyBidXQgYmVoYXZpb3VyIGlzIGNvbnNpc3RlbnQgd2l0aCBJTkRJUkVDVDpcbiAgICAvLyAuLi4gSW4gQTE6IFJDWy0xXSA9PiBSMUNbMTYzODNdLlxuICAgIGlmICh2IDwgMCkge1xuICAgICAgdiA9IG1heCArIHYgKyAxO1xuICAgIH1cbiAgICAvLyAuLi4gSW4gQjE6ID1SQ1sxNjM4M10gPT4gPVJDWy0xXVxuICAgIGlmICh2ID4gbWF4KSB7XG4gICAgICB2IC09IG1heCArIDE7XG4gICAgfVxuICB9XG4gIHJldHVybiB2O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNsYXRlVG9BMSAoZngsIGFuY2hvckNlbGwpIHtcbiAgY29uc3QgYW5jaG9yID0gZnJvbUExKGFuY2hvckNlbGwpO1xuICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBmeCA9PT0gJ3N0cmluZyc7XG5cbiAgY29uc3QgdG9rZW5zID0gaXNTdHJpbmdcbiAgICA/IHRva2VuaXplKGZ4LCB7IGVtaXRSYW5nZXM6IGZhbHNlLCBtZXJnZVJhbmdlczogZmFsc2UsIHIxYzE6IHRydWUgfSlcbiAgICA6IGZ4O1xuXG4gIHRva2Vucy5mb3JFYWNoKHRva2VuID0+IHtcbiAgICBpZiAodG9rZW4udHlwZSA9PT0gUkFOR0UgfHwgdG9rZW4udHlwZSA9PT0gUkFOR0VfQkVBTSkge1xuICAgICAgY29uc3QgcmFuZ2UgPSB7fTtcbiAgICAgIGNvbnN0IGQgPSBmcm9tUkModG9rZW4udmFsdWUpO1xuICAgICAgY29uc3QgcjAgPSB0b0ZpeGVkKGQucjAsIGQuJHIwLCBhbmNob3IudG9wLCBNQVhfUk9XUyk7XG4gICAgICBjb25zdCByMSA9IHRvRml4ZWQoZC5yMSwgZC4kcjEsIGFuY2hvci50b3AsIE1BWF9ST1dTKTtcbiAgICAgIGlmIChyMCA+IHIxKSB7XG4gICAgICAgIHJhbmdlLnRvcCA9IHIxO1xuICAgICAgICByYW5nZS4kdG9wID0gZC4kcjE7XG4gICAgICAgIHJhbmdlLmJvdHRvbSA9IHIwO1xuICAgICAgICByYW5nZS4kYm90dG9tID0gZC4kcjA7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmFuZ2UudG9wID0gcjA7XG4gICAgICAgIHJhbmdlLiR0b3AgPSBkLiRyMDtcbiAgICAgICAgcmFuZ2UuYm90dG9tID0gcjE7XG4gICAgICAgIHJhbmdlLiRib3R0b20gPSBkLiRyMTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGMwID0gdG9GaXhlZChkLmMwLCBkLiRjMCwgYW5jaG9yLmxlZnQsIE1BWF9DT0xTKTtcbiAgICAgIGNvbnN0IGMxID0gdG9GaXhlZChkLmMxLCBkLiRjMSwgYW5jaG9yLmxlZnQsIE1BWF9DT0xTKTtcbiAgICAgIGlmIChjMCA+IGMxKSB7XG4gICAgICAgIHJhbmdlLmxlZnQgPSBjMTtcbiAgICAgICAgcmFuZ2UuJGxlZnQgPSBkLiRjMTtcbiAgICAgICAgcmFuZ2UucmlnaHQgPSBjMDtcbiAgICAgICAgcmFuZ2UuJHJpZ2h0ID0gZC4kYzA7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgcmFuZ2UubGVmdCA9IGMwO1xuICAgICAgICByYW5nZS4kbGVmdCA9IGQuJGMwO1xuICAgICAgICByYW5nZS5yaWdodCA9IGMxO1xuICAgICAgICByYW5nZS4kcmlnaHQgPSBkLiRjMTtcbiAgICAgIH1cbiAgICAgIHRva2VuLnZhbHVlID0gdG9BMShyYW5nZSk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gaXNTdHJpbmdcbiAgICA/IHRva2Vucy5tYXAoZCA9PiBkLnZhbHVlKS5qb2luKCcnKVxuICAgIDogdG9rZW5zO1xufVxuIiwiZXhwb3J0IHsgdG9rZW5pemUgfSBmcm9tICcuL2xleGVyLmpzJztcbmV4cG9ydCB7IGFkZE1ldGEgfSBmcm9tICcuL2FkZE1ldGEuanMnO1xuZXhwb3J0IHsgdHJhbnNsYXRlVG9SQywgdHJhbnNsYXRlVG9BMSB9IGZyb20gJy4vdHJhbnNsYXRlLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgYTEgfSBmcm9tICcuL2ExLmpzJztcbmV4cG9ydCB7IGRlZmF1bHQgYXMgcmMgfSBmcm9tICcuL3JjLmpzJztcbmV4cG9ydCB7IE1BWF9DT0xTLCBNQVhfUk9XUyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcblxuaW1wb3J0IHtcbiAgT1BFUkFUT1IsXG4gIEJPT0xFQU4sXG4gIEVSUk9SLFxuICBOVU1CRVIsXG4gIEZVTkNUSU9OLFxuICBORVdMSU5FLFxuICBXSElURVNQQUNFLFxuICBTVFJJTkcsXG4gIFBBVEhfUVVPVEUsXG4gIFBBVEhfQlJBQ0UsXG4gIFBBVEhfUFJFRklYLFxuICBSQU5HRSxcbiAgUkFOR0VfQkVBTSxcbiAgUkFOR0VfTkFNRUQsXG4gIEZYX1BSRUZJWCxcbiAgVU5LTk9XTlxufSBmcm9tICcuL2NvbnN0YW50cy5qcyc7XG5cbmV4cG9ydCBjb25zdCB0b2tlblR5cGVzID0ge1xuICBPUEVSQVRPUixcbiAgQk9PTEVBTixcbiAgRVJST1IsXG4gIE5VTUJFUixcbiAgRlVOQ1RJT04sXG4gIE5FV0xJTkUsXG4gIFdISVRFU1BBQ0UsXG4gIFNUUklORyxcbiAgUEFUSF9RVU9URSxcbiAgUEFUSF9CUkFDRSxcbiAgUEFUSF9QUkVGSVgsXG4gIFJBTkdFLFxuICBSQU5HRV9CRUFNLFxuICBSQU5HRV9OQU1FRCxcbiAgRlhfUFJFRklYLFxuICBVTktOT1dOXG59O1xuIl0sIm5hbWVzIjpbInF1aWNrVmVyaWZ5UmFuZ2VBMSIsInRva2VuVmFsdWUiLCJzcGxpdCIsImV2ZXJ5IiwiZCIsIm4iLCJwYXJzZUludCIsImlzTmFOIiwiaXNGaW5pdGUiLCJib3VuZHMiLCJSIiwiQyIsInF1aWNrVmVyaWZ5UmFuZ2VSQyIsInJlTnVtcyIsIm0iLCJleGVjIiwieCIsInZhbCIsIlJBTkdFIiwiUkFOR0VfQkVBTSIsInJlX0VSUk9SIiwicmVfT1BFUkFUT1IiLCJyZV9CT09MRUFOIiwicmVfRlVOQ1RJT04iLCJyZV9ORVdMSU5FIiwicmVfV0hJVEVTUEFDRSIsInJlX1NUUklORyIsInJlX1BBVEhfUVVPVEUiLCJyZV9QQVRIX0JSQUNFIiwicmVfUEFUSF9QUkVGSVgiLCJyZV9BMUNPTCIsInJlX0ExUk9XIiwicmVfQTFSQU5HRSIsInJQYXJ0IiwiY1BhcnQiLCJyZV9SQ0NPTCIsIlJlZ0V4cCIsImNvbmNhdCIsInJlX1JDUk9XIiwicmVfUkNSQU5HRSIsInJlX05VTUJFUiIsInJlX05BTUVEIiwidG9rZW5IYW5kbGVyc0ExIiwidG9rZW5IYW5kbGVyc1JDIiwidG9rZW5IYW5kbGVyc1JlZnNBMSIsInRva2VuSGFuZGxlcnNSZWZzUkMiLCJpc1R5cGUiLCJ0IiwidHlwZSIsImlzUmFuZ2VPcCIsInZhbHVlIiwiaXNCYW5nT3AiLCJkZWZhdWx0T3B0aW9ucyIsImVtaXRSYW5nZXMiLCJtZXJnZVJhbmdlcyIsIm5lZ2F0aXZlTnVtYmVycyIsInIxYzEiLCJnZXRUb2tlbnMiLCJmeCIsInRva2VuSGFuZGxlcnMiLCJvcHRpb25zIiwiT2JqZWN0IiwiYXNzaWduIiwidG9rZW5zIiwicG9zIiwibG9va0JlaGluZCIsImxlbmd0aCIsImxvb2tCZWhpbmRJZ25vcmVXUyIsIm5vV3MiLCJmaWx0ZXIiLCJ0ZXN0IiwidG9rZW4iLCJyYW5nZSIsInB1c2giLCJzdGFydFBvcyIsInMiLCJzbGljZSIsInRva2VuVHlwZSIsImkiLCJyZVRlc3QiLCJmblRlc3QiLCJlbmRzV2l0aCIsInVudGVybWluYXRlZCIsImxhc3QxIiwibGFzdDIiLCJpbmNsdWRlcyIsInBvcCIsIm1lcmdlIiwidW5zaGlmdCIsInNwbGljZSIsIm1hcCIsImpvaW4iLCJ0b2tlbml6ZSIsInVucXVvdGUiLCJyZXBsYWNlIiwicFJhbmdlT3AiLCJwUmFuZ2UiLCJyMCIsInBSYW5nZTIiLCJyMSIsInBCYW5nIiwicEJlYW0iLCJwU2hlZXQiLCJzaGVldE5hbWUiLCJwRmlsZSIsIndvcmtib29rTmFtZSIsInBOYW1lZCIsIm5hbWUiLCJwUXVvdGVkIiwiZmlsZSIsInNoZWV0IiwidmFsaWRSdW5zIiwidmFsaWRSdW5zTmFtZWQiLCJwYXJzZVJlZiIsInJlZiIsImFsbG93X25hbWVkIiwicmVmRGF0YSIsInNoaWZ0IiwicnVucyIsImRhdGEiLCJwYXJzZSIsImoiLCJmcm9tQ29sIiwiY29sU3RyIiwiYyIsInRvVXBwZXJDYXNlIiwiY2hyIiwiY2hhckNvZGVBdCIsInRvQ29sIiwibGVmdCIsIlN0cmluZyIsImZyb21DaGFyQ29kZSIsIk1hdGgiLCJmbG9vciIsImZyb21Sb3ciLCJyb3dTdHIiLCJ0b1JvdyIsInRvcCIsInRvUmVsYXRpdmUiLCJib3R0b20iLCJyaWdodCIsIiRsZWZ0IiwiJHJpZ2h0IiwiJHRvcCIsIiRib3R0b20iLCJ0b0ExIiwidG9BYnMiLCJmcm9tQTEiLCJyYW5nZVN0ciIsImEiLCJiIiwibWluIiwibWF4IiwicGFydDEiLCJwYXJ0MiIsInBhcnNlQTFSZWYiLCJhMSIsInRvQWJzb2x1dGUiLCJ0byIsImZyb20iLCJnZXRJRGVyIiwidG9Db29yZCIsImlzQWJzIiwidG9SQyIsImMwIiwiYzEiLCIkYzAiLCIkYzEiLCIkcjAiLCIkcjEiLCJzX3IwIiwic19yMSIsInNfYzAiLCJzX2MxIiwicGFyc2VSQ1BhcnQiLCJybSIsImNtIiwiZnJvbVJDIiwiZXh0ZW5kVG8iLCJyYyIsInRvRml4ZWQiLCJhYnMiLCJiYXNlIiwidiIsInRva2VuVHlwZXMiLCJPUEVSQVRPUiIsIkJPT0xFQU4iLCJFUlJPUiIsIk5VTUJFUiIsIkZVTkNUSU9OIiwiTkVXTElORSIsIldISVRFU1BBQ0UiLCJTVFJJTkciLCJQQVRIX1FVT1RFIiwiUEFUSF9CUkFDRSIsIlBBVEhfUFJFRklYIiwiUkFOR0VfTkFNRUQiLCJGWF9QUkVGSVgiLCJVTktOT1dOIiwicGFyZW5TdGFjayIsImFycmF5U3RhcnQiLCJhMU1hcCIsInVpZCIsImZvckVhY2giLCJpbmRleCIsImRlcHRoIiwiY291bnRlciIsInBhaXJJZCIsImdyb3VwSWQiLCJlcnJvciIsInRvTG93ZXJDYXNlIiwiYW5jaG9yQ2VsbCIsImFuY2hvciIsImlzU3RyaW5nIiwicjFjMiJdLCJtYXBwaW5ncyI6ImFBQU8sU0FBU0EsRUFBb0JDLEdBTWxDLE9BQU9BLEVBQVdDLE1BQU0sbUJBQW1CQyxPQUFNQyxJQUMvQyxNQUFNQyxFQUFJQyxTQUFTRixFQUFHLElBQ3RCLFFBQUtHLE1BQU1GLEtBQ0ZHLFNBQVNKLEdBQ1pDLEdBQUssV0FDTEEsR0FBSyxNQUVYLEdBRUgsd0RBRUQsTUFBTUksRUFBUyxDQUNiQyxFQUFLLFFBQ0wsS0FBTSxRQUNOQyxFQUFLLE1BQ0wsS0FBTSxPQUVELFNBQVNDLEVBQW9CWCxHQUNsQyxNQUFNWSxFQUFTLHFCQUNmLElBQUlDLEVBQ0osS0FBeUMsUUFBakNBLEVBQUlELEVBQU9FLEtBQUtkLEtBQXVCLENBQzdDLE1BQU1lLEVBQUlQLEVBQU9LLEVBQUUsSUFDYkcsRUFBTVgsU0FBU1EsRUFBRSxHQUFJLElBQzNCLEdBQUlHLEdBQU9ELEdBQUtDLElBQVFELEVBQ3RCLE9BQU8sQ0FFVixDQUNELE9BQU8sQ0FDUixDQ2hDTSxNQVdNRSxFQUFRLFFBQ1JDLEVBQWEsYUFRcEJDLEVBQVcsNkhBQ1hDLEVBQWMsK0NBQ2RDLEVBQWEsbUJBQ2JDLEVBQWMsK0JBQ2RDLEVBQWEsT0FDYkMsRUFBZ0IsNkVBQ2hCQyxFQUFZLHNCQUNaQyxFQUFnQixzQkFDaEJDLEVBQWdCLHNCQUNoQkMsRUFBaUIsNkNBQ2pCQyxFQUFX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
@@ -0,0 +1 @@
1
+ { "type": "commonjs" }
File without changes
File without changes
@@ -0,0 +1,77 @@
1
+ import { test, Test } from 'tape';
2
+ import { FX_PREFIX, OPERATOR, NUMBER, RANGE, RANGE_BEAM } from './constants.js';
3
+ import { addMeta } from './addMeta.js';
4
+ import { tokenize } from './lexer.js';
5
+
6
+ Test.prototype.isMetaTokens = function isTokens (expr, result, opts) {
7
+ this.deepEqual(addMeta(tokenize(expr), opts), result, expr);
8
+ };
9
+
10
+ test('add extra meta to operators', t => {
11
+ // parens should be grouped and tagged with depth
12
+ t.isMetaTokens('=((1)+(1))', [
13
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
14
+ { index: 1, depth: 1, type: OPERATOR, value: '(', groupId: 'fxg3' },
15
+ { index: 2, depth: 2, type: OPERATOR, value: '(', groupId: 'fxg1' },
16
+ { index: 3, depth: 2, type: NUMBER, value: '1' },
17
+ { index: 4, depth: 2, type: OPERATOR, value: ')', groupId: 'fxg1' },
18
+ { index: 5, depth: 1, type: OPERATOR, value: '+' },
19
+ { index: 6, depth: 2, type: OPERATOR, value: '(', groupId: 'fxg2' },
20
+ { index: 7, depth: 2, type: NUMBER, value: '1' },
21
+ { index: 8, depth: 2, type: OPERATOR, value: ')', groupId: 'fxg2' },
22
+ { index: 9, depth: 1, type: OPERATOR, value: ')', groupId: 'fxg3' }
23
+ ]);
24
+
25
+ // don't be fooled by imbalanced parens
26
+ t.isMetaTokens('=)())', [
27
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
28
+ { index: 1, depth: 0, type: OPERATOR, value: ')', error: true },
29
+ { index: 2, depth: 1, type: OPERATOR, value: '(', groupId: 'fxg1' },
30
+ { index: 3, depth: 1, type: OPERATOR, value: ')', groupId: 'fxg1' },
31
+ { index: 4, depth: 0, type: OPERATOR, value: ')', error: true }
32
+ ]);
33
+
34
+ // don't be fooled by nested curlys
35
+ t.isMetaTokens('={{}}', [
36
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
37
+ { index: 1, depth: 0, type: OPERATOR, value: '{', groupId: 'fxg1' },
38
+ { index: 2, depth: 0, type: OPERATOR, value: '{', error: true },
39
+ { index: 3, depth: 0, type: OPERATOR, value: '}', groupId: 'fxg1' },
40
+ { index: 4, depth: 0, type: OPERATOR, value: '}', error: true }
41
+ ]);
42
+
43
+ // group ranges if they are equivalent
44
+ t.isMetaTokens("=B11,B11:B12,'Sheet11'!B11,SHEET1!$B11,sheet1!$b$11,A1:B11,[foo]Sheet1!B11,'[foo]Sheet1'!B11", [
45
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
46
+ { index: 1, depth: 0, type: RANGE, value: 'B11', groupId: 'fxg1' },
47
+ { index: 2, depth: 0, type: OPERATOR, value: ',' },
48
+ { index: 3, depth: 0, type: RANGE, value: 'B11:B12', groupId: 'fxg2' },
49
+ { index: 4, depth: 0, type: OPERATOR, value: ',' },
50
+ { index: 5, depth: 0, type: RANGE, value: "'Sheet11'!B11", groupId: 'fxg3' },
51
+ { index: 6, depth: 0, type: OPERATOR, value: ',' },
52
+ { index: 7, depth: 0, type: RANGE, value: 'SHEET1!$B11', groupId: 'fxg1' },
53
+ { index: 8, depth: 0, type: OPERATOR, value: ',' },
54
+ { index: 9, depth: 0, type: RANGE, value: 'sheet1!$b$11', groupId: 'fxg1' },
55
+ { index: 10, depth: 0, type: OPERATOR, value: ',' },
56
+ { index: 11, depth: 0, type: RANGE, value: 'A1:B11', groupId: 'fxg4' },
57
+ { index: 12, depth: 0, type: OPERATOR, value: ',' },
58
+ { index: 13, depth: 0, type: RANGE, value: '[foo]Sheet1!B11', groupId: 'fxg1' },
59
+ { index: 14, depth: 0, type: OPERATOR, value: ',' },
60
+ { index: 15, depth: 0, type: RANGE, value: "'[foo]Sheet1'!B11", groupId: 'fxg1' }
61
+ ], { sheetName: 'Sheet1', workbookName: 'foo' });
62
+
63
+ t.isMetaTokens('=A:A,1:1,Sheet1!A:A:1:1,[foo]Sheet1!1:1', [
64
+ { index: 0, depth: 0, type: FX_PREFIX, value: '=' },
65
+ { index: 1, depth: 0, type: RANGE_BEAM, value: 'A:A', groupId: 'fxg1' },
66
+ { index: 2, depth: 0, type: OPERATOR, value: ',' },
67
+ { index: 3, depth: 0, type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
68
+ { index: 4, depth: 0, type: OPERATOR, value: ',' },
69
+ { index: 5, depth: 0, type: RANGE_BEAM, value: 'Sheet1!A:A', groupId: 'fxg1' },
70
+ { index: 6, depth: 0, type: OPERATOR, value: ':' },
71
+ { index: 7, depth: 0, type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
72
+ { index: 8, depth: 0, type: OPERATOR, value: ',' },
73
+ { index: 9, depth: 0, type: RANGE_BEAM, value: '[foo]Sheet1!1:1', groupId: 'fxg2' }
74
+ ], { sheetName: 'Sheet1', workbookName: 'foo' });
75
+
76
+ t.end();
77
+ });
@@ -13,9 +13,11 @@ export function addMeta (tokens, { sheetName = '', workbookName = '' } = {}) {
13
13
  const a1Map = {};
14
14
  const uid = getIDer();
15
15
 
16
- tokens.forEach(token => {
16
+ tokens.forEach((token, i) => {
17
+ token.index = i;
18
+ token.depth = parenStack.length;
17
19
  if (token.value === '(') {
18
- token.depth = parenStack.length;
20
+ token.depth = parenStack.length + 1;
19
21
  parenStack.push(token);
20
22
  }
21
23
  else if (token.value === ')') {
@@ -23,9 +23,9 @@ export const MAX_ROWS = 2 ** 20 - 1; // 1048575
23
23
  const re_ERROR = /^#(NAME\?|FIELD!|CALC!|VALUE!|REF!|DIV\/0!|NULL!|NUM!|N\/A|GETTING_DATA\b|SPILL!|UNKNOWN!|FIELD\b|CALC\b|SYNTAX\?|ERROR!)/i;
24
24
  const re_OPERATOR = /^(<=|>=|<>|[-+/*^%&<>=]|[{},;]|[()]|@|:|!|#)/;
25
25
  const re_BOOLEAN = /^(TRUE|FALSE)\b/i;
26
- const re_FUNCTION = /^[A-Z]+(?=\s*\()/i;
26
+ const re_FUNCTION = /^[A-Z_]+[A-Z\d_.]+(?=\s*\()/i;
27
27
  const re_NEWLINE = /^\n+/;
28
- const re_WHITESPACE = /^\s+/;
28
+ const re_WHITESPACE = /^[ \f\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/;
29
29
  const re_STRING = /^"(?:""|[^"])*("|$)/;
30
30
  const re_PATH_QUOTE = /^'(?:''|[^'])*('|$)/;
31
31
  const re_PATH_BRACE = /^\[(?:[^\]])+(\]|$)/;
File without changes
@@ -5,6 +5,9 @@ import { tokenize } from './lexer.js';
5
5
  Test.prototype.isTokens = function isTokens (expr, result, opts) {
6
6
  this.deepEqual(tokenize(expr, (opts || {})), result, expr);
7
7
  };
8
+ Test.prototype.isTokensNeg = function isTokensNeg (expr, result, opts) {
9
+ this.deepEqual(tokenize(expr, { ...opts, negativeNumbers: true }), result, expr);
10
+ };
8
11
 
9
12
  test('tokenize operators', t => {
10
13
  t.isTokens('=1>1', [
@@ -269,6 +272,56 @@ test('tokenize functions', t => {
269
272
  { type: BOOLEAN, value: 'TRUE' },
270
273
  { type: OPERATOR, value: ')' }
271
274
  ]);
275
+ t.isTokens('=BINOM.DIST.RANGE(1)', [
276
+ { type: FX_PREFIX, value: '=' },
277
+ { type: FUNCTION, value: 'BINOM.DIST.RANGE' },
278
+ { type: OPERATOR, value: '(' },
279
+ { type: NUMBER, value: '1' },
280
+ { type: OPERATOR, value: ')' }
281
+ ]);
282
+ t.isTokens('=OCT2BIN(1)', [
283
+ { type: FX_PREFIX, value: '=' },
284
+ { type: FUNCTION, value: 'OCT2BIN' },
285
+ { type: OPERATOR, value: '(' },
286
+ { type: NUMBER, value: '1' },
287
+ { type: OPERATOR, value: ')' }
288
+ ]);
289
+ t.isTokens('=TEST_FUNC(1)', [
290
+ { type: FX_PREFIX, value: '=' },
291
+ { type: FUNCTION, value: 'TEST_FUNC' },
292
+ { type: OPERATOR, value: '(' },
293
+ { type: NUMBER, value: '1' },
294
+ { type: OPERATOR, value: ')' }
295
+ ]);
296
+ t.isTokens('=_xlfn.FOO(1)', [
297
+ { type: FX_PREFIX, value: '=' },
298
+ { type: FUNCTION, value: '_xlfn.FOO' },
299
+ { type: OPERATOR, value: '(' },
300
+ { type: NUMBER, value: '1' },
301
+ { type: OPERATOR, value: ')' }
302
+ ]);
303
+ t.isTokens('=_FOO(1)', [
304
+ { type: FX_PREFIX, value: '=' },
305
+ { type: FUNCTION, value: '_FOO' },
306
+ { type: OPERATOR, value: '(' },
307
+ { type: NUMBER, value: '1' },
308
+ { type: OPERATOR, value: ')' }
309
+ ]);
310
+ t.isTokens('=.FOO(1)', [
311
+ { type: FX_PREFIX, value: '=' },
312
+ { type: RANGE_NAMED, value: '.FOO' },
313
+ { type: OPERATOR, value: '(' },
314
+ { type: NUMBER, value: '1' },
315
+ { type: OPERATOR, value: ')' }
316
+ ]);
317
+ t.isTokens('=9FOO(1)', [
318
+ { type: FX_PREFIX, value: '=' },
319
+ { type: NUMBER, value: '9' },
320
+ { type: FUNCTION, value: 'FOO' },
321
+ { type: OPERATOR, value: '(' },
322
+ { type: NUMBER, value: '1' },
323
+ { type: OPERATOR, value: ')' }
324
+ ]);
272
325
  t.end();
273
326
  });
274
327
 
@@ -277,9 +330,9 @@ test('tokenize numbers', t => {
277
330
  { type: FX_PREFIX, value: '=' },
278
331
  { type: NUMBER, value: '0' }
279
332
  ]);
280
- t.isTokens('=-0', [
333
+ t.isTokens('=+0', [
281
334
  { type: FX_PREFIX, value: '=' },
282
- { type: OPERATOR, value: '-' },
335
+ { type: OPERATOR, value: '+' },
283
336
  { type: NUMBER, value: '0' }
284
337
  ]);
285
338
  t.isTokens('=+1', [
@@ -338,6 +391,231 @@ test('tokenize numbers', t => {
338
391
  t.end();
339
392
  });
340
393
 
394
+ test('tokenize negative numbers', t => {
395
+ t.isTokensNeg('=-0', [
396
+ { type: FX_PREFIX, value: '=' },
397
+ { type: NUMBER, value: '-0' }
398
+ ]);
399
+ t.isTokensNeg('=-1123', [
400
+ { type: FX_PREFIX, value: '=' },
401
+ { type: NUMBER, value: '-1123' }
402
+ ]);
403
+ t.isTokensNeg('=-1.5', [
404
+ { type: FX_PREFIX, value: '=' },
405
+ { type: NUMBER, value: '-1.5' }
406
+ ]);
407
+ t.isTokensNeg('=-1234.5678', [
408
+ { type: FX_PREFIX, value: '=' },
409
+ { type: NUMBER, value: '-1234.5678' }
410
+ ]);
411
+ t.isTokensNeg('=1E-1', [
412
+ { type: FX_PREFIX, value: '=' },
413
+ { type: NUMBER, value: '1E-1' }
414
+ ]);
415
+ t.isTokensNeg('=-1E-1', [
416
+ { type: FX_PREFIX, value: '=' },
417
+ { type: NUMBER, value: '-1E-1' }
418
+ ]);
419
+ t.isTokensNeg('=1.5E-10', [
420
+ { type: FX_PREFIX, value: '=' },
421
+ { type: NUMBER, value: '1.5E-10' }
422
+ ]);
423
+ t.isTokensNeg('=-1.5E-10', [
424
+ { type: FX_PREFIX, value: '=' },
425
+ { type: NUMBER, value: '-1.5E-10' }
426
+ ]);
427
+ t.isTokensNeg('-1', [
428
+ { type: 'number', value: '-1' }
429
+ ]);
430
+
431
+ //
432
+ t.isTokensNeg('=1-1', [
433
+ { type: FX_PREFIX, value: '=' },
434
+ { type: NUMBER, value: '1' },
435
+ { type: OPERATOR, value: '-' },
436
+ { type: NUMBER, value: '1' }
437
+ ]);
438
+ t.isTokensNeg('1--1', [
439
+ { type: 'number', value: '1' },
440
+ { type: 'operator', value: '-' },
441
+ { type: 'number', value: '-1' }
442
+ ]);
443
+ t.isTokensNeg('1 - -1', [
444
+ { type: 'number', value: '1' },
445
+ { type: 'whitespace', value: ' ' },
446
+ { type: 'operator', value: '-' },
447
+ { type: 'whitespace', value: ' ' },
448
+ { type: 'number', value: '-1' }
449
+ ]);
450
+ t.isTokensNeg('1 - - 1', [
451
+ { type: 'number', value: '1' },
452
+ { type: 'whitespace', value: ' ' },
453
+ { type: 'operator', value: '-' },
454
+ { type: 'whitespace', value: ' ' },
455
+ { type: 'operator', value: '-' },
456
+ { type: 'whitespace', value: ' ' },
457
+ { type: 'number', value: '1' }
458
+ ]);
459
+ t.isTokensNeg('1 \n - \n -1', [
460
+ { type: 'number', value: '1' },
461
+ { type: 'whitespace', value: ' ' },
462
+ { type: 'newline', value: '\n' },
463
+ { type: 'whitespace', value: ' ' },
464
+ { type: 'operator', value: '-' },
465
+ { type: 'whitespace', value: ' ' },
466
+ { type: 'newline', value: '\n' },
467
+ { type: 'whitespace', value: ' ' },
468
+ { type: 'number', value: '-1' }
469
+ ]);
470
+ t.isTokensNeg('-(-1)', [
471
+ { type: 'operator', value: '-' },
472
+ { type: 'operator', value: '(' },
473
+ { type: 'number', value: '-1' },
474
+ { type: 'operator', value: ')' }
475
+ ]);
476
+ t.isTokensNeg('-( -1 )', [
477
+ { type: 'operator', value: '-' },
478
+ { type: 'operator', value: '(' },
479
+ { type: 'whitespace', value: ' ' },
480
+ { type: 'number', value: '-1' },
481
+ { type: 'whitespace', value: ' ' },
482
+ { type: 'operator', value: ')' }
483
+ ]);
484
+
485
+ t.isTokensNeg('=true-1', [
486
+ { type: 'fx-prefix', value: '=' },
487
+ { type: 'bool', value: 'true' },
488
+ { type: 'operator', value: '-' },
489
+ { type: 'number', value: '1' }
490
+ ]);
491
+ t.isTokensNeg('=true -1', [
492
+ { type: 'fx-prefix', value: '=' },
493
+ { type: 'bool', value: 'true' },
494
+ { type: 'whitespace', value: ' ' },
495
+ { type: 'operator', value: '-' },
496
+ { type: 'number', value: '1' }
497
+ ]);
498
+ t.isTokensNeg('=true - 1', [
499
+ { type: 'fx-prefix', value: '=' },
500
+ { type: 'bool', value: 'true' },
501
+ { type: 'whitespace', value: ' ' },
502
+ { type: 'operator', value: '-' },
503
+ { type: 'whitespace', value: ' ' },
504
+ { type: 'number', value: '1' }
505
+ ]);
506
+ t.isTokensNeg('=#VALUE!-1', [
507
+ { type: 'fx-prefix', value: '=' },
508
+ { type: 'error', value: '#VALUE!' },
509
+ { type: 'operator', value: '-' },
510
+ { type: 'number', value: '1' }
511
+ ]);
512
+ t.isTokensNeg('=#VALUE! -1', [
513
+ { type: 'fx-prefix', value: '=' },
514
+ { type: 'error', value: '#VALUE!' },
515
+ { type: 'whitespace', value: ' ' },
516
+ { type: 'operator', value: '-' },
517
+ { type: 'number', value: '1' }
518
+ ]);
519
+ t.isTokensNeg('=SUM(-1) -1', [
520
+ { type: 'fx-prefix', value: '=' },
521
+ { type: 'function', value: 'SUM' },
522
+ { type: 'operator', value: '(' },
523
+ { type: 'number', value: '-1' },
524
+ { type: 'operator', value: ')' },
525
+ { type: 'whitespace', value: ' ' },
526
+ { type: 'operator', value: '-' },
527
+ { type: 'number', value: '1' }
528
+ ]);
529
+ t.isTokensNeg('=SUM( -1)-1', [
530
+ { type: 'fx-prefix', value: '=' },
531
+ { type: 'function', value: 'SUM' },
532
+ { type: 'operator', value: '(' },
533
+ { type: 'whitespace', value: ' ' },
534
+ { type: 'number', value: '-1' },
535
+ { type: 'operator', value: ')' },
536
+ { type: 'operator', value: '-' },
537
+ { type: 'number', value: '1' }
538
+ ]);
539
+ t.isTokensNeg('=A1-1', [
540
+ { type: 'fx-prefix', value: '=' },
541
+ { type: 'range', value: 'A1' },
542
+ { type: 'operator', value: '-' },
543
+ { type: 'number', value: '1' }
544
+ ]);
545
+ t.isTokensNeg('=A1 -1', [
546
+ { type: 'fx-prefix', value: '=' },
547
+ { type: 'range', value: 'A1' },
548
+ { type: 'whitespace', value: ' ' },
549
+ { type: 'operator', value: '-' },
550
+ { type: 'number', value: '1' }
551
+ ]);
552
+ t.isTokensNeg('=foo-1', [
553
+ { type: 'fx-prefix', value: '=' },
554
+ { type: 'range-named', value: 'foo' },
555
+ { type: 'operator', value: '-' },
556
+ { type: 'number', value: '1' }
557
+ ]);
558
+ t.isTokensNeg('=foo -1', [
559
+ { type: 'fx-prefix', value: '=' },
560
+ { type: 'range-named', value: 'foo' },
561
+ { type: 'whitespace', value: ' ' },
562
+ { type: 'operator', value: '-' },
563
+ { type: 'number', value: '1' }
564
+ ]);
565
+ t.isTokensNeg('="true"-1', [
566
+ { type: 'fx-prefix', value: '=' },
567
+ { type: 'string', value: '"true"' },
568
+ { type: 'operator', value: '-' },
569
+ { type: 'number', value: '1' }
570
+ ]);
571
+ t.isTokensNeg('="true" -1', [
572
+ { type: 'fx-prefix', value: '=' },
573
+ { type: 'string', value: '"true"' },
574
+ { type: 'whitespace', value: ' ' },
575
+ { type: 'operator', value: '-' },
576
+ { type: 'number', value: '1' }
577
+ ]);
578
+
579
+ t.isTokensNeg('=SUM(1)-1', [
580
+ { type: FX_PREFIX, value: '=' },
581
+ { type: FUNCTION, value: 'SUM' },
582
+ { type: OPERATOR, value: '(' },
583
+ { type: NUMBER, value: '1' },
584
+ { type: OPERATOR, value: ')' },
585
+ { type: OPERATOR, value: '-' },
586
+ { type: NUMBER, value: '1' }
587
+ ]);
588
+ t.isTokensNeg('={1, 2, 3}-4', [
589
+ { type: FX_PREFIX, value: '=' },
590
+ { type: OPERATOR, value: '{' },
591
+ { type: NUMBER, value: '1' },
592
+ { type: OPERATOR, value: ',' },
593
+ { type: WHITESPACE, value: ' ' },
594
+ { type: NUMBER, value: '2' },
595
+ { type: OPERATOR, value: ',' },
596
+ { type: WHITESPACE, value: ' ' },
597
+ { type: NUMBER, value: '3' },
598
+ { type: OPERATOR, value: '}' },
599
+ { type: OPERATOR, value: '-' },
600
+ { type: NUMBER, value: '4' }
601
+ ]);
602
+ t.isTokensNeg('=10%-1', [
603
+ { type: FX_PREFIX, value: '=' },
604
+ { type: NUMBER, value: '10' },
605
+ { type: OPERATOR, value: '%' },
606
+ { type: OPERATOR, value: '-' },
607
+ { type: NUMBER, value: '1' }
608
+ ]);
609
+ t.isTokensNeg('=A1#-1', [
610
+ { type: FX_PREFIX, value: '=' },
611
+ { type: RANGE, value: 'A1' },
612
+ { type: OPERATOR, value: '#' },
613
+ { type: OPERATOR, value: '-' },
614
+ { type: NUMBER, value: '1' }
615
+ ]);
616
+ t.end();
617
+ });
618
+
341
619
  test('tokenize simple equations', t => {
342
620
  t.isTokens('=1 + 2', [
343
621
  { type: FX_PREFIX, value: '=' },
@@ -700,6 +978,13 @@ test('tokenize A1 style references', t => {
700
978
  { type: RANGE_BEAM, value: 'AA:JJ' }
701
979
  ]);
702
980
 
981
+ t.isTokens('=XFD:XFF', [
982
+ { type: FX_PREFIX, value: '=' },
983
+ { type: RANGE_NAMED, value: 'XFD' },
984
+ { type: OPERATOR, value: ':' },
985
+ { type: RANGE_NAMED, value: 'XFF' }
986
+ ]);
987
+
703
988
  t.isTokens('=Sheetname!A1', [
704
989
  { type: FX_PREFIX, value: '=' },
705
990
  { type: RANGE, value: 'Sheetname!A1' }
@@ -852,12 +1137,11 @@ test('tokenize A1 style references', t => {
852
1137
  { type: RANGE, value: 'X4' }
853
1138
  ], { mergeRanges: false });
854
1139
 
855
- // largest possible A1 ref
1140
+ // largest possible A1 ref (in Excel)
856
1141
  t.isTokens('=XFD1048576', [
857
1142
  { type: FX_PREFIX, value: '=' },
858
1143
  { type: RANGE, value: 'XFD1048576' }
859
1144
  ]);
860
-
861
1145
  t.isTokens('=XFD1048577', [
862
1146
  { type: FX_PREFIX, value: '=' },
863
1147
  { type: RANGE_NAMED, value: 'XFD1048577' }
@@ -1055,7 +1339,7 @@ test('tokenize strings', t => {
1055
1339
  // so open ended strings at the end of output are tagged.
1056
1340
  t.isTokens('="incomple', [
1057
1341
  { type: FX_PREFIX, value: '=' },
1058
- { type: STRING, value: '"incomple' }
1342
+ { type: STRING, value: '"incomple', unterminated: true }
1059
1343
  ]);
1060
1344
 
1061
1345
  t.end();
@@ -1,12 +1,17 @@
1
1
  import {
2
2
  FX_PREFIX,
3
+ NEWLINE,
4
+ NUMBER,
5
+ OPERATOR,
3
6
  PATH_BRACE,
4
7
  PATH_PREFIX,
5
8
  PATH_QUOTE,
6
9
  RANGE,
7
- RANGE_NAMED,
8
10
  RANGE_BEAM,
11
+ RANGE_NAMED,
12
+ STRING,
9
13
  UNKNOWN,
14
+ WHITESPACE,
10
15
  tokenHandlersA1,
11
16
  tokenHandlersRC
12
17
  } from './constants.js';
@@ -15,10 +20,22 @@ const isType = (t, type) => t && t.type === type;
15
20
  const isRangeOp = t => t && t.value === ':';
16
21
  const isBangOp = t => t && t.value === '!';
17
22
 
18
- export function getTokens (fx, tokenHandlers = [], emitRanges = false, mergeRanges = false) {
23
+ const defaultOptions = {
24
+ emitRanges: false,
25
+ mergeRanges: true,
26
+ negativeNumbers: false,
27
+ r1c1: false
28
+ };
29
+
30
+ export function getTokens (fx, tokenHandlers, options = {}) {
31
+ const { emitRanges, mergeRanges, negativeNumbers } = Object.assign({}, defaultOptions, options);
19
32
  const tokens = [];
20
33
  let pos = 0;
21
34
  const lookBehind = n => tokens[tokens.length - n];
35
+ const lookBehindIgnoreWS = n => {
36
+ const noWs = tokens.filter(t => !isType(t, WHITESPACE) && !isType(t, NEWLINE));
37
+ return noWs[noWs.length - n];
38
+ };
22
39
 
23
40
  if (/^=/.test(fx)) {
24
41
  const token = {
@@ -58,6 +75,23 @@ export function getTokens (fx, tokenHandlers = [], emitRanges = false, mergeRang
58
75
  ...(emitRanges ? { range: [ startPos, pos ] } : {})
59
76
  };
60
77
 
78
+ if (tokenType === STRING && !tokenValue.endsWith('"')) {
79
+ token.unterminated = true;
80
+ }
81
+
82
+ if (negativeNumbers && tokenType === NUMBER) {
83
+ const last1 = lookBehind(1);
84
+ if (last1 && isType(last1, OPERATOR) && last1.value === '-') {
85
+ // we have a number preceded by a minus
86
+ const last2 = lookBehindIgnoreWS(2);
87
+ // missing last2 means we are at the start of the stream
88
+ if (!last2 || isType(last2, FX_PREFIX) || (isType(last2, OPERATOR) && ![ '%', '}', ')', '#' ].includes(last2.value))) {
89
+ tokens.pop();
90
+ token.value = '-' + tokenValue;
91
+ }
92
+ }
93
+ }
94
+
61
95
  if (mergeRanges) {
62
96
  if (tokenType === RANGE || tokenType === RANGE_NAMED || tokenType === RANGE_BEAM) {
63
97
  const merge = [];
@@ -94,7 +128,7 @@ export function getTokens (fx, tokenHandlers = [], emitRanges = false, mergeRang
94
128
 
95
129
  // Formulas can either have RC or A1 style refs, not both: because C1 and R1 are both!
96
130
  // Refmode: A1 | RC | Anostic emit ranges with RANGE
97
- export function tokenize (fx, { emitRanges = false, mergeRanges = true, r1c1 = false } = {}) {
98
- const tokenHandlers = r1c1 ? tokenHandlersRC : tokenHandlersA1;
99
- return getTokens(fx, tokenHandlers, emitRanges, mergeRanges);
131
+ export function tokenize (fx, options = {}) {
132
+ const tokenHandlers = options.r1c1 ? tokenHandlersRC : tokenHandlersA1;
133
+ return getTokens(fx, tokenHandlers, options);
100
134
  }
@@ -0,0 +1 @@
1
+ { "type": "module" }
@@ -51,7 +51,10 @@ const validRunsNamed = validRuns.concat([
51
51
  ]);
52
52
 
53
53
  export function parseRef (ref, allow_named = true, tokenHandlers = []) {
54
- const tokens = getTokens(ref, tokenHandlers, false, false);
54
+ const tokens = getTokens(ref, tokenHandlers, {
55
+ emitRanges: false,
56
+ mergeRanges: false
57
+ });
55
58
  const refData = {
56
59
  sheetName: '',
57
60
  workbookName: '',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/package.json CHANGED
@@ -1,38 +1,53 @@
1
1
  {
2
2
  "name": "@borgar/fx",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Utilities for working with Excel formulas",
5
- "main": "src/index.js",
6
- "type": "module",
5
+ "main": "dist/fx.js",
6
+ "module": "lib/index.js",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/fx.js",
10
+ "default": "./lib/index.js"
11
+ }
12
+ },
7
13
  "scripts": {
8
- "lint": "eslint index.js src/*.js",
9
- "test": "tape run src/*-test.js | tap-min"
14
+ "lint": "eslint index.js lib/*.js",
15
+ "test": "tape lib/*-test.js | tap-min",
16
+ "build": "NODE_ENV=production rollup -c"
10
17
  },
11
18
  "repository": {
12
19
  "type": "git",
13
- "url": "git+https://github.com/borgar/xlsx-reader.git"
20
+ "url": "git+https://github.com/borgar/fx.git"
14
21
  },
15
22
  "bugs": {
16
- "url": "https://github.com/borgar/xlsx-reader/issues"
23
+ "url": "https://github.com/borgar/fx/issues"
17
24
  },
25
+ "browserslist": [
26
+ "defaults",
27
+ "not IE 11",
28
+ "maintained node versions"
29
+ ],
18
30
  "keywords": [
19
31
  "excel",
20
- "json",
21
32
  "xlsx",
22
- "csf",
23
- "office",
24
- "spreadsheet",
25
- "workbook"
33
+ "formula",
34
+ "spreadsheet"
26
35
  ],
27
36
  "author": "Borgar Þorsteinsson <borgar@borgar.net> (http://borgar.net/)",
28
37
  "license": "MIT",
29
38
  "devDependencies": {
30
- "@babel/core": "~7.15.5",
31
- "@babel/eslint-parser": "~7.15.4",
39
+ "@babel/core": "~7.18.13",
40
+ "@babel/eslint-parser": "~7.18.9",
41
+ "@babel/preset-env": "~7.18.10",
32
42
  "@borgar/eslint-config": "~2.2.1",
43
+ "@rollup/plugin-babel": "~5.3.1",
33
44
  "babel-eslint": "~10.1.0",
34
- "eslint": "~7.32.0",
45
+ "eslint": "~8.23.0",
46
+ "rollup": "~2.79.0",
35
47
  "tap-min": "~2.0.0",
36
- "tape": "~5.3.1"
48
+ "tape": "~5.6.0"
49
+ },
50
+ "dependencies": {
51
+ "rollup-plugin-terser": "~7.0.2"
37
52
  }
38
53
  }
@@ -0,0 +1,21 @@
1
+ import babel from '@rollup/plugin-babel';
2
+ import { terser } from 'rollup-plugin-terser';
3
+ import pkg from './package.json';
4
+
5
+ const isProd = process.env.NODE_ENV === 'production';
6
+
7
+ export default {
8
+ input: pkg.module,
9
+ plugins: [
10
+ babel({
11
+ babelHelpers: 'bundled',
12
+ presets: [ '@babel/preset-env' ]
13
+ })
14
+ ],
15
+ output: {
16
+ file: pkg.main,
17
+ format: 'cjs',
18
+ sourcemap: 'inline',
19
+ plugins: [ isProd && terser() ]
20
+ }
21
+ };
@@ -1,77 +0,0 @@
1
- import { test, Test } from 'tape';
2
- import { FX_PREFIX, OPERATOR, NUMBER, RANGE, RANGE_BEAM } from './constants.js';
3
- import { addMeta } from './addMeta.js';
4
- import { tokenize } from './lexer.js';
5
-
6
- Test.prototype.isMetaTokens = function isTokens (expr, result, opts) {
7
- this.deepEqual(addMeta(tokenize(expr), opts), result, expr);
8
- };
9
-
10
- test('add extra meta to operators', t => {
11
- // parens should be grouped and tagged with depth
12
- t.isMetaTokens('=((1)+(1))', [
13
- { type: FX_PREFIX, value: '=' },
14
- { type: OPERATOR, value: '(', depth: 0, groupId: 'fxg3' },
15
- { type: OPERATOR, value: '(', depth: 1, groupId: 'fxg1' },
16
- { type: NUMBER, value: '1' },
17
- { type: OPERATOR, value: ')', depth: 1, groupId: 'fxg1' },
18
- { type: OPERATOR, value: '+' },
19
- { type: OPERATOR, value: '(', depth: 1, groupId: 'fxg2' },
20
- { type: NUMBER, value: '1' },
21
- { type: OPERATOR, value: ')', depth: 1, groupId: 'fxg2' },
22
- { type: OPERATOR, value: ')', depth: 0, groupId: 'fxg3' }
23
- ]);
24
-
25
- // don't be fooled by imbalanced parens
26
- t.isMetaTokens('=)())', [
27
- { type: FX_PREFIX, value: '=' },
28
- { type: OPERATOR, value: ')', error: true },
29
- { type: OPERATOR, value: '(', depth: 0, groupId: 'fxg1' },
30
- { type: OPERATOR, value: ')', depth: 0, groupId: 'fxg1' },
31
- { type: OPERATOR, value: ')', error: true }
32
- ]);
33
-
34
- // don't be fooled by nested curlys
35
- t.isMetaTokens('={{}}', [
36
- { type: FX_PREFIX, value: '=' },
37
- { type: OPERATOR, value: '{', groupId: 'fxg1' },
38
- { type: OPERATOR, value: '{', error: true },
39
- { type: OPERATOR, value: '}', groupId: 'fxg1' },
40
- { type: OPERATOR, value: '}', error: true }
41
- ]);
42
-
43
- // group ranges if they are equivalent
44
- t.isMetaTokens("=B11,B11:B12,'Sheet11'!B11,SHEET1!$B11,sheet1!$b$11,A1:B11,[foo]Sheet1!B11,'[foo]Sheet1'!B11", [
45
- { type: FX_PREFIX, value: '=' },
46
- { type: RANGE, value: 'B11', groupId: 'fxg1' },
47
- { type: OPERATOR, value: ',' },
48
- { type: RANGE, value: 'B11:B12', groupId: 'fxg2' },
49
- { type: OPERATOR, value: ',' },
50
- { type: RANGE, value: "'Sheet11'!B11", groupId: 'fxg3' },
51
- { type: OPERATOR, value: ',' },
52
- { type: RANGE, value: 'SHEET1!$B11', groupId: 'fxg1' },
53
- { type: OPERATOR, value: ',' },
54
- { type: RANGE, value: 'sheet1!$b$11', groupId: 'fxg1' },
55
- { type: OPERATOR, value: ',' },
56
- { type: RANGE, value: 'A1:B11', groupId: 'fxg4' },
57
- { type: OPERATOR, value: ',' },
58
- { type: RANGE, value: '[foo]Sheet1!B11', groupId: 'fxg1' },
59
- { type: OPERATOR, value: ',' },
60
- { type: RANGE, value: "'[foo]Sheet1'!B11", groupId: 'fxg1' }
61
- ], { sheetName: 'Sheet1', workbookName: 'foo' });
62
-
63
- t.isMetaTokens('=A:A,1:1,Sheet1!A:A:1:1,[foo]Sheet1!1:1', [
64
- { type: FX_PREFIX, value: '=' },
65
- { type: RANGE_BEAM, value: 'A:A', groupId: 'fxg1' },
66
- { type: OPERATOR, value: ',' },
67
- { type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
68
- { type: OPERATOR, value: ',' },
69
- { type: RANGE_BEAM, value: 'Sheet1!A:A', groupId: 'fxg1' },
70
- { type: OPERATOR, value: ':' },
71
- { type: RANGE_BEAM, value: '1:1', groupId: 'fxg2' },
72
- { type: OPERATOR, value: ',' },
73
- { type: RANGE_BEAM, value: '[foo]Sheet1!1:1', groupId: 'fxg2' }
74
- ], { sheetName: 'Sheet1', workbookName: 'foo' });
75
-
76
- t.end();
77
- });