{"version":3,"file":"vendor~dynamic-render.bundle.js","mappings":";;;;;;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP,wBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,GAAG;AACpC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,EAAE;AACrB;AACA,wBAAwB,EAAE;AAC1B;AACA;AACA;AACA,kBAAkB,SAAS,IAAI,aAAa,EAAE,EAAE;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,gCAAgC;AAC3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB,yBAAyB,IAAI,WAAW;AAC1D;AACA;;;;;;;;;;;;;;;;;ACjGuC;;AAEvC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO;AACP;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,uDAAS;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,uDAAS;AACzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEO;AACP;AACA;;;;;;;;;;;;;;;AC3JO;AACP;AACA;AACA;;AAEA,MAAM;AACN;AACA,MAAM;AACN;AACA;AACA,UAAU;AACV;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;ACnCgC;AACF;;;;;;;;;;;;;;;;ACDG;;AAEjC;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,gBAAgB;AAChB;;AAEA;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA,YAAY,kDAAS;AACrB;AACA;AACA;AACA;;AAEA;;AAEO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;;;;;;;;;;;;;;;;;;ACxF6C;AACH;AACY;;AAEtD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,gCAAgC,MAAM;AACtC,4BAA4B;AAC5B,6BAA6B;AAC7B,qBAAqB;AACrB,sBAAsB;AACtB;AACA;AACA;AACA;AACA;;;AAGO;AACP,4BAA4B;;AAE5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;;AAEA,0BAA0B,sDAAU;;AAEpC;;AAEA;AACA,eAAe,oDAAQ;AACvB;;AAEA;AACA,eAAe,mDAAO;AACtB;;AAEA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;;;;;AC1EkC;;AAElC;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,oBAAoB;AACpB;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,cAAc;AACd;AACA,cAAc;AACd;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,cAAc;AACd;AACA,cAAc;AACd;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,kDAAQ;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA,sBAAsB;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA,sBAAsB;AACtB;AACA;AACA,iBAAiB;AACjB;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB;AACA,sBAAsB;AACtB;AACA;AACA,0BAA0B;AAC1B;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB,kDAAQ;AAC9B;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB;AACA,sBAAsB;AACtB;AACA;AACA,0BAA0B;AAC1B;AACA;AACA;AACA;AACA,6BAA6B;AAC7B;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA,iBAAiB;AACjB;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEO;AACP;AACA;AACA,KAAK;AACL;AACA;;;;;;;;;;;;;;;;;;;ACjSyH;AACrF;AACD;AACK;;AAExC;;AAEO;AACP;AACA;AACA,oDAAoD,mDAAS,wDAAwD,wDAAW;AAChI,oDAAoD,mDAAS,wDAAwD,wDAAW;AAChI;AACA;AACA;AACA,0BAA0B,mDAAS;AACnC,0BAA0B,mDAAS;AACnC;;AAEA,2BAA2B,iDAAW;AACtC;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yDAAyD,6BAA6B,KAAK,4BAA4B;AACvH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,qBAAqB,iDAAO;AAC5B;AACA;AACA,sBAAsB;AACtB;AACA,wBAAwB,qDAAU;AAClC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAgB,qDAAY;AAC5B;AACA,UAAU;;AAEV;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,0CAAI;AAC5B;AACA,wDAAwD,kDAAQ;AAChE,wDAAwD,kDAAQ;AAChE;AACA;AACA;AACA;AACA,wBAAwB,0CAAI;AAC5B;AACA,wDAAwD,kDAAQ;AAChE,wDAAwD,kDAAQ;AAChE;AACA;AACA;;AAEA;AACA;AACA;AACA,4BAA4B,0CAAI;AAChC;AACA;AACA;AACA;AACA;AACA,cAAc;AACd,4BAA4B,0CAAI;AAChC;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA,oBAAoB,gBAAgB;AACpC;AACA;AACA;AACA,+BAA+B,0CAAI;AACnC;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA,mCAAmC,0CAAI;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,oBAAoB,gBAAgB;AACpC;AACA,2BAA2B,0CAAI;AAC/B;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6GAA6G,sDAAY;;AAEzH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEA,wBAAwB,UAAU;AAClC;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,uCAAuC,0CAAI;AAC3C;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB,uCAAuC,0CAAI;AAC3C;AACA;AACA,mEAAmE,kDAAQ;AAC3E;AACA;AACA;;AAEA,kBAAkB;AAClB;AACA,uCAAuC,0CAAI;AAC3C;AACA;AACA;AACA;AACA,sBAAsB;AACtB,uCAAuC,0CAAI;AAC3C;AACA;AACA,mEAAmE,kDAAQ;AAC3E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kBAAkB,UAAU,iDAAO;AACnC;AACA;AACA,2CAA2C,0CAAI;AAC/C;AACA;AACA;AACA;AACA,0BAA0B;AAC1B;AACA,oCAAoC,0CAAI;AACxC;AACA,2EAA2E,kDAAQ;AACnF;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,sBAAsB;AACtB;AACA,gCAAgC,0CAAI;AACpC;AACA,uEAAuE,kDAAQ;AAC/E;AACA;AACA,oDAAoD;AACpD;AACA,sBAAsB;AACtB;AACA,gCAAgC,0CAAI;AACpC;AACA,wEAAwE,kDAAQ;AAChF,wEAAwE,kDAAQ;AAChF;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,2DAAiB;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA,yCAAyC,mBAAmB;AAC5D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+CAA+C,0CAAI;AACnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,sBAAsB;AACtB,uCAAuC,0CAAI;AAC3C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB;AAClB,mCAAmC,0CAAI;AACvC;AACA;AACA,+DAA+D,kDAAQ;AACvE;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA,mCAAmC,0CAAI;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAkB;AAClB,mCAAmC,0CAAI;AACvC;AACA;AACA,+DAA+D,kDAAQ;AACvE;AACA;AACA;AACA;AACA;;AAEA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC,kBAAkB;AACtD,6BAA6B,sDAAY;AACzC;AACA;AACA;AACA;AACA,oCAAoC,0CAAI;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,2BAA2B,0CAAI;AAC/B;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,2BAA2B,0CAAI;AAC/B;AACA;AACA;AACA;AACA;AACA;AACA;AACA,2BAA2B,0CAAI;AAC/B;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;;;;;;;;;;;;;;ACleO,sCAAsC;AAC7C;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;AC9BA;;AAEA;AACA;AACA;AACA;;;AAGA;AACA,+BAA+B,sBAAsB;AACrD,eAAe;AACf;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAU;AACV;AACA;AACA;;AAEA;;AAEA;AACA;AACA,cAAc;AACd;AACA;;AAEA;AACA;;AAEA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,8BAA8B,iBAAiB;AAC/C;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;AACA,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEO;AACP;AACA;;;;;;;;;;;;;;;;;;;;;;AClMO;AACP,4BAA4B;AAC5B;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,YAAY,GAAG,0CAA0C;AACxF;AACA;AACA,+BAA+B,YAAY,GAAG,iBAAiB;AAC/D;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;;AAEL;AACA;;AAEO;AACP;AACA;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;AACA;;AAEO;AACP;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;;AAGO;;AAEP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA,cAAc;AACd,wCAAwC,YAAY,GAAG,iBAAiB;AACxE;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,YAAY,GAAG,0CAA0C;AAChG;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;;;AAGO,yBAAyB;AAChC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA,SAAS;AACT;;AAEA;AACA,0BAA0B,oBAAoB;AAC9C;AACA,8BAA8B,oBAAoB;AAClD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,sCAAsC,YAAY;AAClD;AACA;AACA,sCAAsC,YAAY;AAClD;AACA;AACA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACO;AACP;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;;;;;;;;;ACxWiC;AACE;AACK;;;;;;;;;;;;;;;;;;;;ACFuB;AACtB;;;;;;;;;;;;;;;ACDzC;AACA,8BAA8B,WAAW;AACzC;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,kCAAkC;AAClC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa;AACb,YAAY;AACZ,YAAY;AACZ,cAAc;AACd,aAAa;AACb,cAAc;AACd,cAAc;AACd,cAAc;AACd;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,oBAAoB;AACpB,yBAAyB;;AAEzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,oCAAoC,SAAS;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB,yBAAyB;AACzB,yBAAyB;AACzB,yBAAyB,gBAAgB,MAAM;AAC/C,yBAAyB;AACzB,yBAAyB;AACzB,yBAAyB;;AAEzB;AACA,sBAAsB,OAAO;AAC7B;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,wDAAwD;AACxD;;AAEA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,kDAAkD,iBAAiB;AACnE;;AAEA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,MAAM,oBAAoB;AAC1B;AACA;AACA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;;AAEA;AACA;AACA,MAAM,uCAAuC;AAC7C;AACA,MAAM;AACN;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6CAA6C,eAAe;AAC5D;;AAEA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6CAA6C,eAAe;AAC5D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB;AACjB;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,IAAI;AACJ;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,QAAQ;AACR;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,gEAAgE,WAAW,UAAU,SAAS,KAAK,oBAAoB;AACvH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA,KAAK;AACL;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,6CAA6C,eAAe;AAC5D;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA,gDAAgD,iBAAiB;AACjE;AACA;AACA,IAAI;AACJ;AACA,IAAI;AACJ;AACA;;AAEA;AACA;;AAEA;AACA;AACA,IAAI;AACJ;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,kBAAkB,wBAAwB;AAC1C;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,MAAM;AACnB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,iEAAe,QAAQ,EAAC","sources":["webpack://sfra-boilerplate/./node_modules/diff-dom/src/TraceLogger.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/dom/apply.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/dom/fromVirtual.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/dom/index.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/dom/undo.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/index.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/apply.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/diff.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/fromDOM.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/fromString.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/helpers.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/diffDOM/virtual/index.js","webpack://sfra-boilerplate/./node_modules/diff-dom/src/index.js","webpack://sfra-boilerplate/./node_modules/mustache/mustache.mjs"],"sourcesContent":["/**\n * Use TraceLogger to figure out function calls inside\n * JS objects by wrapping an object with a TraceLogger\n * instance.\n *\n * Pretty-prints the call trace (using unicode box code)\n * when tracelogger.toString() is called.\n */\n\n/**\n * Wrap an object by calling new TraceLogger(obj)\n *\n * If you're familiar with Python decorators, this\n * does roughly the same thing, adding pre/post\n * call hook logging calls so that you can see\n * what's going on.\n */\nexport class TraceLogger {\n constructor(obj = {}) {\n this.pad = \"│ \"\n this.padding = \"\"\n this.tick = 1\n this.messages = []\n const wrapkey = (obj, key) => {\n // trace this function\n const oldfn = obj[key]\n obj[key] = (...args) => {\n this.fin(key, Array.prototype.slice.call(args))\n const result = oldfn.apply(obj, args)\n this.fout(key, result)\n return result\n }\n }\n // can't use Object.keys for prototype walking\n for (let key in obj) {\n if (typeof obj[key] === \"function\") {\n wrapkey(obj, key)\n }\n }\n this.log(\"┌ TRACELOG START\")\n }\n // called when entering a function\n fin(fn, args) {\n this.padding += this.pad\n this.log(`├─> entering ${fn}`, args)\n }\n // called when exiting a function\n fout(fn, result) {\n this.log(\"│<──┘ generated return value\", result)\n this.padding = this.padding.substring(0, this.padding.length - this.pad.length)\n }\n // log message formatting\n format(s, tick) {\n let nf = function(t) {\n t = `${t}`\n while (t.length < 4) {\n t = `0${t}`\n }\n return t\n }\n return `${nf(tick)}> ${this.padding}${s}`\n }\n // log a trace message\n log() {\n let s = Array.prototype.slice.call(arguments)\n const stringCollapse = function(v) {\n if (!v) {\n return \"<falsey>\"\n }\n if (typeof v === \"string\") {\n return v\n }\n if (v instanceof HTMLElement) {\n return v.outerHTML || \"<empty>\"\n }\n if (v instanceof Array) {\n return `[${v.map(stringCollapse).join(\",\")}]`\n }\n return v.toString() || v.valueOf() || \"<unknown>\"\n }\n s = s.map(stringCollapse).join(\", \")\n this.messages.push(this.format(s, this.tick++))\n }\n // turn the log into a structured string with\n // unicode box codes to make it a sensible trace.\n toString() {\n let cap = \"× \"\n let terminator = \"└───\"\n while (terminator.length <= this.padding.length + this.pad.length) {\n terminator += cap\n }\n let _ = this.padding\n this.padding = \"\"\n terminator = this.format(terminator, this.tick)\n this.padding = _\n return `${this.messages.join(\"\\n\")}\\n${terminator}`\n }\n}\n","import {objToNode} from \"./fromVirtual\"\n\n// ===== Apply a diff =====\n\nfunction getFromRoute(node, route) {\n route = route.slice()\n while (route.length > 0) {\n if (!node.childNodes) {\n return false\n }\n const c = route.splice(0, 1)[0]\n node = node.childNodes[c]\n }\n return node\n}\n\nexport function applyDiff(\n tree,\n diff,\n options // {preDiffApply, postDiffApply, textDiff, valueDiffing, _const}\n ) {\n let node = getFromRoute(tree, diff[options._const.route])\n let newNode\n let reference\n let route\n let nodeArray\n let c\n\n // pre-diff hook\n const info = {\n diff,\n node\n }\n\n if (options.preDiffApply(info)) {\n return true\n }\n\n switch (diff[options._const.action]) {\n case options._const.addAttribute:\n if (!node || !node.setAttribute) {\n return false\n }\n node.setAttribute(diff[options._const.name], diff[options._const.value])\n break\n case options._const.modifyAttribute:\n if (!node || !node.setAttribute) {\n return false\n }\n node.setAttribute(diff[options._const.name], diff[options._const.newValue])\n if (node.nodeName === 'INPUT' && diff[options._const.name] === 'value') {\n node.value = diff[options._const.newValue]\n }\n break\n case options._const.removeAttribute:\n if (!node || !node.removeAttribute) {\n return false\n }\n node.removeAttribute(diff[options._const.name])\n break\n case options._const.modifyTextElement:\n if (!node || node.nodeType !== 3) {\n return false\n }\n options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue])\n break\n case options._const.modifyValue:\n if (!node || typeof node.value === 'undefined') {\n return false\n }\n node.value = diff[options._const.newValue]\n break\n case options._const.modifyComment:\n if (!node || typeof node.data === 'undefined') {\n return false\n }\n options.textDiff(node, node.data, diff[options._const.oldValue], diff[options._const.newValue])\n break\n case options._const.modifyChecked:\n if (!node || typeof node.checked === 'undefined') {\n return false\n }\n node.checked = diff[options._const.newValue]\n break\n case options._const.modifySelected:\n if (!node || typeof node.selected === 'undefined') {\n return false\n }\n node.selected = diff[options._const.newValue]\n break\n case options._const.replaceElement:\n node.parentNode.replaceChild(\n objToNode(\n diff[options._const.newValue],\n node.namespaceURI === 'http://www.w3.org/2000/svg',\n options\n ),\n node\n )\n break\n case options._const.relocateGroup:\n nodeArray = Array(...new Array(diff.groupLength)).map(() => node.removeChild(node.childNodes[diff[options._const.from]]))\n nodeArray.forEach((childNode, index) => {\n if (index === 0) {\n reference = node.childNodes[diff[options._const.to]]\n }\n node.insertBefore(childNode, reference || null)\n })\n break\n case options._const.removeElement:\n node.parentNode.removeChild(node)\n break\n case options._const.addElement:\n route = diff[options._const.route].slice()\n c = route.splice(route.length - 1, 1)[0]\n node = getFromRoute(tree, route)\n node.insertBefore(\n objToNode(\n diff[options._const.element],\n node.namespaceURI === 'http://www.w3.org/2000/svg',\n options\n ),\n node.childNodes[c] || null\n )\n break\n case options._const.removeTextElement:\n if (!node || node.nodeType !== 3) {\n return false\n }\n node.parentNode.removeChild(node)\n break\n case options._const.addTextElement:\n route = diff[options._const.route].slice()\n c = route.splice(route.length - 1, 1)[0]\n newNode = options.document.createTextNode(diff[options._const.value])\n node = getFromRoute(tree, route)\n if (!node || !node.childNodes) {\n return false\n }\n node.insertBefore(newNode, node.childNodes[c] || null)\n break\n default:\n console.log('unknown action')\n }\n\n // if a new node was created, we might be interested in its\n // post diff hook\n info.newNode = newNode\n options.postDiffApply(info)\n\n return true\n}\n\nexport function applyDOM(tree, diffs, options) {\n return diffs.every(diff => applyDiff(tree, diff, options))\n}\n","export function objToNode(objNode, insideSvg, options) {\n let node\n if (objNode.nodeName === '#text') {\n node = options.document.createTextNode(objNode.data)\n\n } else if (objNode.nodeName === '#comment') {\n node = options.document.createComment(objNode.data)\n } else {\n if (insideSvg) {\n node = options.document.createElementNS('http://www.w3.org/2000/svg', objNode.nodeName)\n } else if (objNode.nodeName.toLowerCase() === 'svg') {\n node = options.document.createElementNS('http://www.w3.org/2000/svg', 'svg')\n insideSvg = true\n } else {\n node = options.document.createElement(objNode.nodeName)\n }\n if (objNode.attributes) {\n Object.entries(objNode.attributes).forEach(([key, value]) => node.setAttribute(key, value))\n }\n if (objNode.childNodes) {\n objNode.childNodes.forEach(childNode => node.appendChild(objToNode(childNode, insideSvg, options)))\n }\n if (options.valueDiffing) {\n if (objNode.value) {\n node.value = objNode.value\n }\n if (objNode.checked) {\n node.checked = objNode.checked\n }\n if (objNode.selected) {\n node.selected = objNode.selected\n }\n }\n }\n return node\n}\n","export {applyDOM} from \"./apply\"\nexport {undoDOM} from \"./undo\"\n","import {applyDiff} from \"./apply\"\n\n// ===== Undo a diff =====\n\nfunction swap(obj, p1, p2) {\n const tmp = obj[p1]\n obj[p1] = obj[p2]\n obj[p2] = tmp\n}\n\nfunction undoDiff(\n tree,\n diff,\n options // {preDiffApply, postDiffApply, textDiff, valueDiffing, _const}\n) {\n\n switch (diff[options._const.action]) {\n case options._const.addAttribute:\n diff[options._const.action] = options._const.removeAttribute\n applyDiff(tree, diff, options)\n break\n case options._const.modifyAttribute:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.removeAttribute:\n diff[options._const.action] = options._const.addAttribute\n applyDiff(tree, diff, options)\n break\n case options._const.modifyTextElement:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.modifyValue:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.modifyComment:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.modifyChecked:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.modifySelected:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.replaceElement:\n swap(diff, options._const.oldValue, options._const.newValue)\n applyDiff(tree, diff, options)\n break\n case options._const.relocateGroup:\n swap(diff, options._const.from, options._const.to)\n applyDiff(tree, diff, options)\n break\n case options._const.removeElement:\n diff[options._const.action] = options._const.addElement\n applyDiff(tree, diff, options)\n break\n case options._const.addElement:\n diff[options._const.action] = options._const.removeElement\n applyDiff(tree, diff, options)\n break\n case options._const.removeTextElement:\n diff[options._const.action] = options._const.addTextElement\n applyDiff(tree, diff, options)\n break\n case options._const.addTextElement:\n diff[options._const.action] = options._const.removeTextElement\n applyDiff(tree, diff, options)\n break\n default:\n console.log('unknown action')\n }\n\n}\n\nexport function undoDOM(tree, diffs, options) {\n if (!diffs.length) {\n diffs = [diffs]\n }\n diffs = diffs.slice()\n diffs.reverse()\n diffs.forEach(diff => {\n undoDiff(tree, diff, options)\n })\n}\n","import {applyDOM, undoDOM} from \"./dom/index\"\nimport {DiffFinder} from \"./virtual/index\"\nexport {nodeToObj, stringToObj} from \"./virtual/index\"\n\nconst DEFAULT_OPTIONS = {\n debug: false,\n diffcap: 10, // Limit for how many diffs are accepting when debugging. Inactive when debug is false.\n maxDepth: false, // False or a numeral. If set to a numeral, limits the level of depth that the the diff mechanism looks for differences. If false, goes through the entire tree.\n maxChildCount: 50, // False or a numeral. If set to a numeral, only does a simplified form of diffing of contents so that the number of diffs cannot be higher than the number of child nodes.\n valueDiffing: true, // Whether to take into consideration the values of forms that differ from auto assigned values (when a user fills out a form).\n // syntax: textDiff: function (node, currentValue, expectedValue, newValue)\n textDiff(node, currentValue, expectedValue, newValue) {\n node.data = newValue\n return\n },\n // empty functions were benchmarked as running faster than both\n // `f && f()` and `if (f) { f(); }`\n preVirtualDiffApply() {},\n postVirtualDiffApply() {},\n preDiffApply() {},\n postDiffApply() {},\n filterOuterDiff: null,\n compress: false, // Whether to work with compressed diffs\n _const: false, // object with strings for every change types to be used in diffs.\n document: window && window.document ? window.document : false\n}\n\n\nexport class DiffDOM {\n constructor(options = {}) {\n\n this.options = options\n // IE11 doesn't have Object.assign and buble doesn't translate object spreaders\n // by default, so this is the safest way of doing it currently.\n Object.entries(DEFAULT_OPTIONS).forEach(([key, value]) => {\n if (!Object.prototype.hasOwnProperty.call(this.options, key)) {\n this.options[key] = value\n }\n })\n\n if (!this.options._const) {\n const varNames = [\"addAttribute\", \"modifyAttribute\", \"removeAttribute\",\n \"modifyTextElement\", \"relocateGroup\", \"removeElement\", \"addElement\",\n \"removeTextElement\", \"addTextElement\", \"replaceElement\", \"modifyValue\",\n \"modifyChecked\", \"modifySelected\", \"modifyComment\", \"action\", \"route\",\n \"oldValue\", \"newValue\", \"element\", \"group\", \"from\", \"to\", \"name\",\n \"value\", \"data\", \"attributes\", \"nodeName\", \"childNodes\", \"checked\",\n \"selected\"\n ]\n this.options._const = {}\n if (this.options.compress) {\n varNames.forEach((varName, index) => this.options._const[varName] = index)\n } else {\n varNames.forEach(varName => this.options._const[varName] = varName)\n }\n }\n\n this.DiffFinder = DiffFinder\n\n }\n\n apply(tree, diffs) {\n return applyDOM(tree, diffs, this.options)\n }\n\n undo(tree, diffs) {\n return undoDOM(tree, diffs, this.options)\n }\n\n diff(t1Node, t2Node) {\n const finder = new this.DiffFinder(t1Node, t2Node, this.options)\n return finder.init()\n }\n\n}\n","import {cloneObj} from \"./helpers\"\n\n// ===== Apply a virtual diff =====\n\nfunction getFromVirtualRoute(tree, route) {\n let node = tree\n let parentNode\n let nodeIndex\n\n route = route.slice()\n while (route.length > 0) {\n if (!node.childNodes) {\n return false\n }\n nodeIndex = route.splice(0, 1)[0]\n parentNode = node\n node = node.childNodes[nodeIndex]\n }\n return {\n node,\n parentNode,\n nodeIndex\n }\n}\n\nfunction applyVirtualDiff(\n tree,\n diff,\n options // {preVirtualDiffApply, postVirtualDiffApply, _const}\n ) {\n const routeInfo = getFromVirtualRoute(tree, diff[options._const.route])\n let node = routeInfo.node\n const parentNode = routeInfo.parentNode\n const nodeIndex = routeInfo.nodeIndex\n const newSubsets = []\n\n // pre-diff hook\n const info = {\n diff,\n node\n }\n\n if (options.preVirtualDiffApply(info)) {\n return true\n }\n\n let newNode\n let nodeArray\n let route\n let c\n switch (diff[options._const.action]) {\n case options._const.addAttribute:\n if (!node.attributes) {\n node.attributes = {}\n }\n\n node.attributes[diff[options._const.name]] = diff[options._const.value]\n\n if (diff[options._const.name] === 'checked') {\n node.checked = true\n } else if (diff[options._const.name] === 'selected') {\n node.selected = true\n } else if (node.nodeName === 'INPUT' && diff[options._const.name] === 'value') {\n node.value = diff[options._const.value]\n }\n\n break\n case options._const.modifyAttribute:\n node.attributes[diff[options._const.name]] = diff[options._const.newValue]\n break\n case options._const.removeAttribute:\n\n delete node.attributes[diff[options._const.name]]\n\n if (Object.keys(node.attributes).length === 0) {\n delete node.attributes\n }\n\n if (diff[options._const.name] === 'checked') {\n node.checked = false\n } else if (diff[options._const.name] === 'selected') {\n delete node.selected\n } else if (node.nodeName === 'INPUT' && diff[options._const.name] === 'value') {\n delete node.value\n }\n\n break\n case options._const.modifyTextElement:\n node.data = diff[options._const.newValue]\n break\n case options._const.modifyValue:\n node.value = diff[options._const.newValue]\n break\n case options._const.modifyComment:\n node.data = diff[options._const.newValue]\n break\n case options._const.modifyChecked:\n node.checked = diff[options._const.newValue]\n break\n case options._const.modifySelected:\n node.selected = diff[options._const.newValue]\n break\n case options._const.replaceElement:\n newNode = cloneObj(diff[options._const.newValue])\n newNode.outerDone = true\n newNode.innerDone = true\n newNode.valueDone = true\n parentNode.childNodes[nodeIndex] = newNode\n break\n case options._const.relocateGroup:\n nodeArray = node.childNodes.splice(diff[options._const.from], diff.groupLength).reverse()\n nodeArray.forEach(movedNode => node.childNodes.splice(diff[options._const.to], 0, movedNode))\n if (node.subsets) {\n node.subsets.forEach(map => {\n if (diff[options._const.from] < diff[options._const.to] && map.oldValue <= diff[options._const.to] && map.oldValue > diff[options._const.from]) {\n map.oldValue -= diff.groupLength\n const splitLength = map.oldValue + map.length - diff[options._const.to]\n if (splitLength > 0) {\n // new insertion splits map.\n newSubsets.push({\n oldValue: diff[options._const.to] + diff.groupLength,\n newValue: map.newValue + map.length - splitLength,\n length: splitLength\n })\n map.length -= splitLength\n }\n } else if (diff[options._const.from] > diff[options._const.to] && map.oldValue > diff[options._const.to] && map.oldValue < diff[options._const.from]) {\n map.oldValue += diff.groupLength\n const splitLength = map.oldValue + map.length - diff[options._const.to]\n if (splitLength > 0) {\n // new insertion splits map.\n newSubsets.push({\n oldValue: diff[options._const.to] + diff.groupLength,\n newValue: map.newValue + map.length - splitLength,\n length: splitLength\n })\n map.length -= splitLength\n }\n } else if (map.oldValue === diff[options._const.from]) {\n map.oldValue = diff[options._const.to]\n }\n })\n }\n\n break\n case options._const.removeElement:\n parentNode.childNodes.splice(nodeIndex, 1)\n if (parentNode.subsets) {\n parentNode.subsets.forEach(map => {\n if (map.oldValue > nodeIndex) {\n map.oldValue -= 1\n } else if (map.oldValue === nodeIndex) {\n map.delete = true\n } else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) {\n if (map.oldValue + map.length - 1 === nodeIndex) {\n map.length--\n } else {\n newSubsets.push({\n newValue: map.newValue + nodeIndex - map.oldValue,\n oldValue: nodeIndex,\n length: map.length - nodeIndex + map.oldValue - 1\n })\n map.length = nodeIndex - map.oldValue\n }\n }\n })\n }\n node = parentNode\n break\n case options._const.addElement:\n route = diff[options._const.route].slice()\n c = route.splice(route.length - 1, 1)[0]\n node = getFromVirtualRoute(tree, route).node\n newNode = cloneObj(diff[options._const.element])\n newNode.outerDone = true\n newNode.innerDone = true\n newNode.valueDone = true\n\n if (!node.childNodes) {\n node.childNodes = []\n }\n\n if (c >= node.childNodes.length) {\n node.childNodes.push(newNode)\n } else {\n node.childNodes.splice(c, 0, newNode)\n }\n if (node.subsets) {\n node.subsets.forEach(map => {\n if (map.oldValue >= c) {\n map.oldValue += 1\n } else if (map.oldValue < c && (map.oldValue + map.length) > c) {\n const splitLength = map.oldValue + map.length - c\n newSubsets.push({\n newValue: map.newValue + map.length - splitLength,\n oldValue: c + 1,\n length: splitLength\n })\n map.length -= splitLength\n }\n })\n }\n break\n case options._const.removeTextElement:\n parentNode.childNodes.splice(nodeIndex, 1)\n if (parentNode.nodeName === 'TEXTAREA') {\n delete parentNode.value\n }\n if (parentNode.subsets) {\n parentNode.subsets.forEach(map => {\n if (map.oldValue > nodeIndex) {\n map.oldValue -= 1\n } else if (map.oldValue === nodeIndex) {\n map.delete = true\n } else if (map.oldValue < nodeIndex && (map.oldValue + map.length) > nodeIndex) {\n if (map.oldValue + map.length - 1 === nodeIndex) {\n map.length--\n } else {\n newSubsets.push({\n newValue: map.newValue + nodeIndex - map.oldValue,\n oldValue: nodeIndex,\n length: map.length - nodeIndex + map.oldValue - 1\n })\n map.length = nodeIndex - map.oldValue\n }\n }\n })\n }\n node = parentNode\n break\n case options._const.addTextElement:\n route = diff[options._const.route].slice()\n c = route.splice(route.length - 1, 1)[0]\n newNode = {}\n newNode.nodeName = '#text'\n newNode.data = diff[options._const.value]\n node = getFromVirtualRoute(tree, route).node\n if (!node.childNodes) {\n node.childNodes = []\n }\n\n if (c >= node.childNodes.length) {\n node.childNodes.push(newNode)\n } else {\n node.childNodes.splice(c, 0, newNode)\n }\n if (node.nodeName === 'TEXTAREA') {\n node.value = diff[options._const.newValue]\n }\n if (node.subsets) {\n node.subsets.forEach(map => {\n if (map.oldValue >= c) {\n map.oldValue += 1\n }\n if (map.oldValue < c && (map.oldValue + map.length) > c) {\n const splitLength = map.oldValue + map.length - c\n newSubsets.push({\n newValue: map.newValue + map.length - splitLength,\n oldValue: c + 1,\n length: splitLength\n })\n map.length -= splitLength\n }\n })\n }\n break\n default:\n console.log('unknown action')\n }\n\n if (node.subsets) {\n node.subsets = node.subsets.filter(map => !map.delete && map.oldValue !== map.newValue)\n if (newSubsets.length) {\n node.subsets = node.subsets.concat(newSubsets)\n }\n }\n\n // capture newNode for the callback\n info.newNode = newNode\n options.postVirtualDiffApply(info)\n\n return\n}\n\nexport function applyVirtual(tree, diffs, options) {\n diffs.forEach(diff => {\n applyVirtualDiff(tree, diff, options)\n })\n return true\n}\n","import {Diff, DiffTracker, cloneObj, getGapInformation, isEqual, markSubTrees, removeDone, roughlyEqual} from \"./helpers\"\nimport {applyVirtual} from \"./apply\"\nimport {nodeToObj} from \"./fromDOM\"\nimport {stringToObj} from \"./fromString\"\n\n// ===== Create a diff =====\n\nexport class DiffFinder {\n constructor(t1Node, t2Node, options) {\n this.options = options\n this.t1 = (t1Node instanceof HTMLElement) ? nodeToObj(t1Node, this.options) : (typeof t1Node === 'string') ? stringToObj(t1Node, this.options) : JSON.parse(JSON.stringify(t1Node))\n this.t2 = (t2Node instanceof HTMLElement) ? nodeToObj(t2Node, this.options) : (typeof t2Node === 'string') ? stringToObj(t2Node, this.options) : JSON.parse(JSON.stringify(t2Node))\n this.diffcount = 0\n this.foundAll = false\n if (this.debug) {\n this.t1Orig = nodeToObj(t1Node, this.options)\n this.t2Orig = nodeToObj(t2Node, this.options)\n }\n\n this.tracker = new DiffTracker()\n }\n\n init() {\n return this.findDiffs(this.t1, this.t2)\n }\n\n findDiffs(t1, t2) {\n let diffs\n do {\n if (this.options.debug) {\n this.diffcount += 1\n if (this.diffcount > this.options.diffcap) {\n window.diffError = [this.t1Orig, this.t2Orig]\n throw new Error(`surpassed diffcap:${JSON.stringify(this.t1Orig)} -> ${JSON.stringify(this.t2Orig)}`)\n }\n }\n diffs = this.findNextDiff(t1, t2, [])\n\n if (diffs.length === 0) {\n // Last check if the elements really are the same now.\n // If not, remove all info about being done and start over.\n // Sometimes a node can be marked as done, but the creation of subsequent diffs means that it has to be changed again.\n if (!isEqual(t1, t2)) {\n if (this.foundAll) {\n console.error('Could not find remaining diffs!')\n } else {\n this.foundAll = true\n removeDone(t1)\n diffs = this.findNextDiff(t1, t2, [])\n }\n }\n }\n if (diffs.length > 0) {\n this.foundAll = false\n this.tracker.add(diffs)\n applyVirtual(t1, diffs, this.options)\n }\n } while (diffs.length > 0)\n\n return this.tracker.list\n }\n\n findNextDiff(t1, t2, route) {\n let diffs\n let fdiffs\n\n if (this.options.maxDepth && route.length > this.options.maxDepth) {\n return []\n }\n // outer differences?\n if (!t1.outerDone) {\n diffs = this.findOuterDiff(t1, t2, route)\n if (this.options.filterOuterDiff) {\n fdiffs = this.options.filterOuterDiff(t1, t2, diffs)\n if (fdiffs) diffs = fdiffs\n }\n if (diffs.length > 0) {\n t1.outerDone = true\n return diffs\n } else {\n t1.outerDone = true\n }\n }\n // inner differences?\n if (!t1.innerDone) {\n diffs = this.findInnerDiff(t1, t2, route)\n if (diffs.length > 0) {\n return diffs\n } else {\n t1.innerDone = true\n }\n }\n\n if (this.options.valueDiffing && !t1.valueDone) {\n // value differences?\n diffs = this.findValueDiff(t1, t2, route)\n\n if (diffs.length > 0) {\n t1.valueDone = true\n return diffs\n } else {\n t1.valueDone = true\n }\n }\n\n // no differences\n return []\n }\n\n findOuterDiff(t1, t2, route) {\n const diffs = []\n let attr\n let attr1\n let attr2\n let attrLength\n let pos\n let i\n if (t1.nodeName !== t2.nodeName) {\n if (!route.length) {\n throw new Error('Top level nodes have to be of the same kind.')\n }\n return [new Diff()\n .setValue(this.options._const.action, this.options._const.replaceElement)\n .setValue(this.options._const.oldValue, cloneObj(t1))\n .setValue(this.options._const.newValue, cloneObj(t2))\n .setValue(this.options._const.route, route)\n ]\n }\n if (route.length && this.options.maxNodeDiffCount < Math.abs((t1.childNodes || []).length - (t2.childNodes || []).length)) {\n return [new Diff()\n .setValue(this.options._const.action, this.options._const.replaceElement)\n .setValue(this.options._const.oldValue, cloneObj(t1))\n .setValue(this.options._const.newValue, cloneObj(t2))\n .setValue(this.options._const.route, route)\n ]\n }\n\n if (t1.data !== t2.data) {\n // Comment or text node.\n if (t1.nodeName === '#text') {\n return [new Diff()\n .setValue(this.options._const.action, this.options._const.modifyTextElement)\n .setValue(this.options._const.route, route)\n .setValue(this.options._const.oldValue, t1.data)\n .setValue(this.options._const.newValue, t2.data)\n ]\n } else {\n return [new Diff()\n .setValue(this.options._const.action, this.options._const.modifyComment)\n .setValue(this.options._const.route, route)\n .setValue(this.options._const.oldValue, t1.data)\n .setValue(this.options._const.newValue, t2.data)\n ]\n }\n\n }\n\n attr1 = t1.attributes ? Object.keys(t1.attributes).sort() : []\n attr2 = t2.attributes ? Object.keys(t2.attributes).sort() : []\n\n attrLength = attr1.length\n for (i = 0; i < attrLength; i++) {\n attr = attr1[i]\n pos = attr2.indexOf(attr)\n if (pos === -1) {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeAttribute)\n .setValue(this.options._const.route, route)\n .setValue(this.options._const.name, attr)\n .setValue(this.options._const.value, t1.attributes[attr])\n )\n } else {\n attr2.splice(pos, 1)\n if (t1.attributes[attr] !== t2.attributes[attr]) {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.modifyAttribute)\n .setValue(this.options._const.route, route)\n .setValue(this.options._const.name, attr)\n .setValue(this.options._const.oldValue, t1.attributes[attr])\n .setValue(this.options._const.newValue, t2.attributes[attr])\n )\n }\n }\n }\n\n attrLength = attr2.length\n for (i = 0; i < attrLength; i++) {\n attr = attr2[i]\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.addAttribute)\n .setValue(this.options._const.route, route)\n .setValue(this.options._const.name, attr)\n .setValue(this.options._const.value, t2.attributes[attr])\n )\n }\n\n return diffs\n }\n\n findInnerDiff(t1, t2, route) {\n const t1ChildNodes = t1.childNodes ? t1.childNodes.slice() : []\n const t2ChildNodes = t2.childNodes ? t2.childNodes.slice() : []\n const last = Math.max(t1ChildNodes.length, t2ChildNodes.length)\n let childNodesLengthDifference = Math.abs(t1ChildNodes.length - t2ChildNodes.length)\n let diffs = []\n let index = 0\n if (!this.options.maxChildCount || last < this.options.maxChildCount) {\n const subtrees = t1.subsets && t1.subsetsAge-- ? t1.subsets : (t1.childNodes && t2.childNodes) ? markSubTrees(t1, t2) : []\n\n if (subtrees.length > 0) {\n /* One or more groups have been identified among the childnodes of t1\n * and t2.\n */\n diffs = this.attemptGroupRelocation(t1, t2, subtrees, route)\n if (diffs.length > 0) {\n return diffs\n }\n }\n }\n\n\n /* 0 or 1 groups of similar child nodes have been found\n * for t1 and t2. 1 If there is 1, it could be a sign that the\n * contents are the same. When the number of groups is below 2,\n * t1 and t2 are made to have the same length and each of the\n * pairs of child nodes are diffed.\n */\n\n for (let i = 0; i < last; i += 1) {\n const e1 = t1ChildNodes[i]\n const e2 = t2ChildNodes[i]\n\n if (childNodesLengthDifference) {\n /* t1 and t2 have different amounts of childNodes. Add\n * and remove as necessary to obtain the same length */\n if (e1 && !e2) {\n if (e1.nodeName === '#text') {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeTextElement)\n .setValue(this.options._const.route, route.concat(index))\n .setValue(this.options._const.value, e1.data)\n )\n index -= 1\n } else {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeElement)\n .setValue(this.options._const.route, route.concat(index))\n .setValue(this.options._const.element, cloneObj(e1))\n )\n index -= 1\n }\n\n } else if (e2 && !e1) {\n if (e2.nodeName === '#text') {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.addTextElement)\n .setValue(this.options._const.route, route.concat(index))\n .setValue(this.options._const.value, e2.data)\n )\n } else {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.addElement)\n .setValue(this.options._const.route, route.concat(index))\n .setValue(this.options._const.element, cloneObj(e2))\n )\n }\n }\n }\n /* We are now guaranteed that childNodes e1 and e2 exist,\n * and that they can be diffed.\n */\n /* Diffs in child nodes should not affect the parent node,\n * so we let these diffs be submitted together with other\n * diffs.\n */\n\n if (e1 && e2) {\n if (!this.options.maxChildCount || last < this.options.maxChildCount) {\n diffs = diffs.concat(this.findNextDiff(e1, e2, route.concat(index)))\n } else if (!isEqual(e1, e2)) {\n if (t1ChildNodes.length > t2ChildNodes.length) {\n if (e1.nodeName === '#text') {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeTextElement)\n .setValue(this.options._const.route, route.concat(index))\n .setValue(this.options._const.value, e1.data)\n )\n } else {\n diffs.push(\n new Diff()\n .setValue(this.options._const.action, this.options._const.removeElement)\n .setValue(this.options._const.element, cloneObj(e1))\n .setValue(this.options._const.route, route.concat(index))\n )\n }\n t1ChildNodes.splice(i, 1)\n i -= 1\n index -= 1\n\n childNodesLengthDifference -= 1\n } else if (t1ChildNodes.length < t2ChildNodes.length) {\n diffs = diffs.concat([\n new Diff()\n .setValue(this.options._const.action, this.options._const.addElement)\n .setValue(this.options._const.element, cloneObj(e2))\n .setValue(this.options._const.route, route.concat(index))\n ])\n t1ChildNodes.splice(i, 0, {})\n childNodesLengthDifference -= 1\n } else {\n diffs = diffs.concat([\n new Diff()\n .setValue(this.options._const.action, this.options._const.replaceElement)\n .setValue(this.options._const.oldValue, cloneObj(e1))\n .setValue(this.options._const.newValue, cloneObj(e2))\n .setValue(this.options._const.route, route.concat(index))\n ])\n }\n\n }\n\n }\n index += 1\n\n }\n t1.innerDone = true\n return diffs\n }\n\n attemptGroupRelocation(t1, t2, subtrees, route) {\n /* Either t1.childNodes and t2.childNodes have the same length, or\n * there are at least two groups of similar elements can be found.\n * attempts are made at equalizing t1 with t2. First all initial\n * elements with no group affiliation (gaps=true) are removed (if\n * only in t1) or added (if only in t2). Then the creation of a group\n * relocation diff is attempted.\n */\n const gapInformation = getGapInformation(t1, t2, subtrees)\n const gaps1 = gapInformation.gaps1\n const gaps2 = gapInformation.gaps2\n let shortest = Math.min(gaps1.length, gaps2.length)\n let destinationDifferent\n let toGroup\n let group\n let node\n let similarNode\n let testI\n const diffs = []\n\n\n for (let index2 = 0, index1 = 0; index2 < shortest; index1 += 1, index2 += 1) {\n if (gaps1[index2] === true) {\n node = t1.childNodes[index1]\n if (node.nodeName === '#text') {\n if (t2.childNodes[index2].nodeName === '#text') {\n if (node.data !== t2.childNodes[index2].data) {\n testI = index1\n while (t1.childNodes.length > testI + 1 && t1.childNodes[testI + 1].nodeName === '#text') {\n testI += 1\n if (t2.childNodes[index2].data === t1.childNodes[testI].data) {\n similarNode = true\n break\n }\n }\n if (!similarNode) {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.modifyTextElement)\n .setValue(this.options._const.route, route.concat(index2))\n .setValue(this.options._const.oldValue, node.data)\n .setValue(this.options._const.newValue, t2.childNodes[index2].data)\n )\n return diffs\n }\n }\n } else {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeTextElement)\n .setValue(this.options._const.route, route.concat(index2))\n .setValue(this.options._const.value, node.data)\n )\n gaps1.splice(index2, 1)\n shortest = Math.min(gaps1.length, gaps2.length)\n index2 -= 1\n }\n } else {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.removeElement)\n .setValue(this.options._const.route, route.concat(index2))\n .setValue(this.options._const.element, cloneObj(node))\n )\n gaps1.splice(index2, 1)\n shortest = Math.min(gaps1.length, gaps2.length)\n index2 -= 1\n }\n\n } else if (gaps2[index2] === true) {\n node = t2.childNodes[index2]\n if (node.nodeName === '#text') {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.addTextElement)\n .setValue(this.options._const.route, route.concat(index2))\n .setValue(this.options._const.value, node.data)\n )\n gaps1.splice(index2, 0, true)\n shortest = Math.min(gaps1.length, gaps2.length)\n index1 -= 1\n } else {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.addElement)\n .setValue(this.options._const.route, route.concat(index2))\n .setValue(this.options._const.element, cloneObj(node))\n )\n gaps1.splice(index2, 0, true)\n shortest = Math.min(gaps1.length, gaps2.length)\n index1 -= 1\n }\n\n } else if (gaps1[index2] !== gaps2[index2]) {\n if (diffs.length > 0) {\n return diffs\n }\n // group relocation\n group = subtrees[gaps1[index2]]\n toGroup = Math.min(group.newValue, (t1.childNodes.length - group.length))\n if (toGroup !== group.oldValue) {\n // Check whether destination nodes are different than originating ones.\n destinationDifferent = false\n for (let j = 0; j < group.length; j += 1) {\n if (!roughlyEqual(t1.childNodes[toGroup + j], t1.childNodes[group.oldValue + j], [], false, true)) {\n destinationDifferent = true\n }\n }\n if (destinationDifferent) {\n return [new Diff()\n .setValue(this.options._const.action, this.options._const.relocateGroup)\n .setValue('groupLength', group.length)\n .setValue(this.options._const.from, group.oldValue)\n .setValue(this.options._const.to, toGroup)\n .setValue(this.options._const.route, route)\n ]\n }\n }\n }\n }\n return diffs\n }\n\n findValueDiff(t1, t2, route) {\n // Differences of value. Only useful if the value/selection/checked value\n // differs from what is represented in the DOM. For example in the case\n // of filled out forms, etc.\n const diffs = []\n\n if (t1.selected !== t2.selected) {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.modifySelected)\n .setValue(this.options._const.oldValue, t1.selected)\n .setValue(this.options._const.newValue, t2.selected)\n .setValue(this.options._const.route, route)\n )\n }\n\n if ((t1.value || t2.value) && t1.value !== t2.value && t1.nodeName !== 'OPTION') {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.modifyValue)\n .setValue(this.options._const.oldValue, t1.value || \"\")\n .setValue(this.options._const.newValue, t2.value || \"\")\n .setValue(this.options._const.route, route)\n )\n }\n if (t1.checked !== t2.checked) {\n diffs.push(new Diff()\n .setValue(this.options._const.action, this.options._const.modifyChecked)\n .setValue(this.options._const.oldValue, t1.checked)\n .setValue(this.options._const.newValue, t2.checked)\n .setValue(this.options._const.route, route)\n )\n }\n\n return diffs\n }\n\n}\n","export function nodeToObj(aNode, options = {}) {\n const objNode = {}\n objNode.nodeName = aNode.nodeName\n if (objNode.nodeName === '#text' || objNode.nodeName === '#comment') {\n objNode.data = aNode.data\n } else {\n if (aNode.attributes && aNode.attributes.length > 0) {\n objNode.attributes = {}\n const nodeArray = Array.prototype.slice.call(aNode.attributes)\n nodeArray.forEach(attribute => objNode.attributes[attribute.name] = attribute.value)\n }\n if (objNode.nodeName === 'TEXTAREA') {\n objNode.value = aNode.value\n } else if (aNode.childNodes && aNode.childNodes.length > 0) {\n objNode.childNodes = []\n const nodeArray = Array.prototype.slice.call(aNode.childNodes)\n nodeArray.forEach(childNode => objNode.childNodes.push(nodeToObj(childNode, options)))\n }\n if (options.valueDiffing) {\n if (aNode.checked !== undefined && aNode.type && ['radio', 'checkbox'].includes(aNode.type.toLowerCase())) {\n objNode.checked = aNode.checked\n } else if (aNode.value !== undefined) {\n objNode.value = aNode.value\n }\n if (aNode.selected !== undefined) {\n objNode.selected = aNode.selected\n }\n }\n }\n return objNode\n}\n","// from html-parse-stringify (MIT)\n\nconst tagRE = /<(?:\"[^\"]*\"['\"]*|'[^']*'['\"]*|[^'\">])+>/g\n// re-used obj for quick lookups of components\nconst empty = Object.create ? Object.create(null) : {}\nconst attrRE = /\\s([^'\"/\\s><]+?)[\\s/>]|([^\\s=]+)=\\s?(\".*?\"|'.*?')/g\n\n\nfunction unescape(string) {\n return string.replace(/</g, '<').replace(/>/g, '>')\n.replace(/&/g, '&')\n}\n\n// create optimized lookup object for\n// void elements as listed here:\n// http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements\nconst lookup = {\n area: true,\n base: true,\n br: true,\n col: true,\n embed: true,\n hr: true,\n img: true,\n input: true,\n keygen: true,\n link: true,\n menuItem: true,\n meta: true,\n param: true,\n source: true,\n track: true,\n wbr: true\n}\n\n\nfunction parseTag(tag) {\n const res = {\n nodeName: '',\n attributes: {}\n }\n\n let tagMatch = tag.match(/<\\/?([^\\s]+?)[/\\s>]/)\n if (tagMatch) {\n res.nodeName = tagMatch[1].toUpperCase()\n if (lookup[tagMatch[1].toLowerCase()] || tag.charAt(tag.length - 2) === '/') {\n res.voidElement = true\n }\n\n // handle comment tag\n if (res.nodeName.startsWith('!--')) {\n const endIndex = tag.indexOf('-->')\n return {\n type: 'comment',\n data: endIndex !== -1 ? tag.slice(4, endIndex) : ''\n }\n }\n }\n\n let reg = new RegExp(attrRE)\n let result = null\n let done = false\n while (!done) {\n result = reg.exec(tag)\n\n if (result === null) {\n done = true\n } else if (result[0].trim()) {\n if (result[1]) {\n let attr = result[1].trim()\n let arr = [attr, \"\"]\n\n if (attr.indexOf(\"=\") > -1) arr = attr.split(\"=\")\n\n res.attributes[arr[0]] = arr[1]\n reg.lastIndex--\n } else if (result[2]) res.attributes[result[2]] = result[3].trim().substring(1, result[3].length - 1)\n }\n }\n\n return res\n}\n\nfunction parse(\n html,\n options = {components: empty}\n) {\n const result = []\n let current\n let level = -1\n const arr = []\n let inComponent = false\n\n html.replace(tagRE, (tag, index) => {\n if (inComponent) {\n if (tag !== (`</${current.nodeName}>`)) {\n return\n } else {\n inComponent = false\n }\n }\n const isOpen = tag.charAt(1) !== '/'\n const isComment = tag.startsWith('<!--')\n const start = index + tag.length\n const nextChar = html.charAt(start)\n let parent\n\n if (isComment) {\n const comment = parseTag(tag)\n\n // if we're at root, push new base node\n if (level < 0) {\n result.push(comment)\n return result\n }\n parent = arr[level]\n if (parent) {\n if (!parent.childNodes) {\n parent.childNodes = []\n }\n parent.childNodes.push(comment)\n }\n\n return result\n }\n\n if (isOpen) {\n current = parseTag(tag)\n level++\n if (current.type === 'tag' && options.components[current.nodeName]) {\n current.type = 'component'\n inComponent = true\n }\n\n if (!current.voidElement && !inComponent && nextChar && nextChar !== '<') {\n if (!current.childNodes) {\n current.childNodes = []\n }\n current.childNodes.push({\n nodeName: '#text',\n data: unescape(html.slice(start, html.indexOf('<', start)))\n })\n }\n\n // if we're at root, push new base node\n if (level === 0) {\n result.push(current)\n }\n\n parent = arr[level - 1]\n\n if (parent) {\n if (!parent.childNodes) {\n parent.childNodes = []\n }\n parent.childNodes.push(current)\n }\n\n arr[level] = current\n }\n\n if (!isOpen || current.voidElement) {\n level--\n if (!inComponent && nextChar !== '<' && nextChar) {\n // trailing text node\n // if we're at the root, push a base text node. otherwise add as\n // a child to the current node.\n parent = level === -1 ? result : arr[level].childNodes || []\n\n // calculate correct end of the data slice in case there's\n // no tag after the text node.\n const end = html.indexOf('<', start)\n const data = unescape(html.slice(start, end === -1 ? undefined : end))\n parent.push({\n nodeName: '#text',\n data\n })\n }\n }\n })\n\n return result[0]\n}\n\nfunction cleanObj(obj) {\n delete obj.voidElement\n if (obj.childNodes) {\n obj.childNodes.forEach(child => cleanObj(child))\n }\n return obj\n}\n\nexport function stringToObj(string) {\n return cleanObj(parse(string))\n}\n","export class Diff {\n constructor(options = {}) {\n Object.entries(options).forEach(([key, value]) => this[key] = value)\n }\n\n toString() {\n return JSON.stringify(this)\n }\n\n setValue(aKey, aValue) {\n this[aKey] = aValue\n return this\n }\n}\n\nfunction elementDescriptors(el) {\n const output = []\n output.push(el.nodeName)\n if (el.nodeName !== '#text' && el.nodeName !== '#comment') {\n if (el.attributes) {\n if (el.attributes['class']) {\n output.push(`${el.nodeName}.${el.attributes['class'].replace(/ /g, '.')}`)\n }\n if (el.attributes.id) {\n output.push(`${el.nodeName}#${el.attributes.id}`)\n }\n }\n\n }\n return output\n}\n\nfunction findUniqueDescriptors(li) {\n const uniqueDescriptors = {}\n const duplicateDescriptors = {}\n\n li.forEach(node => {\n elementDescriptors(node).forEach(descriptor => {\n const inUnique = descriptor in uniqueDescriptors\n const inDupes = descriptor in duplicateDescriptors\n if (!inUnique && !inDupes) {\n uniqueDescriptors[descriptor] = true\n } else if (inUnique) {\n delete uniqueDescriptors[descriptor]\n duplicateDescriptors[descriptor] = true\n }\n })\n })\n\n return uniqueDescriptors\n}\n\nfunction uniqueInBoth(l1, l2) {\n const l1Unique = findUniqueDescriptors(l1)\n const l2Unique = findUniqueDescriptors(l2)\n const inBoth = {}\n\n Object.keys(l1Unique).forEach(key => {\n if (l2Unique[key]) {\n inBoth[key] = true\n }\n })\n\n return inBoth\n}\n\nexport function removeDone(tree) {\n delete tree.outerDone\n delete tree.innerDone\n delete tree.valueDone\n if (tree.childNodes) {\n return tree.childNodes.every(removeDone)\n } else {\n return true\n }\n}\n\nexport function isEqual(e1, e2) {\n if (!['nodeName', 'value', 'checked', 'selected', 'data'].every(element => {\n if (e1[element] !== e2[element]) {\n return false\n }\n return true\n })) {\n return false\n }\n\n if (Boolean(e1.attributes) !== Boolean(e2.attributes)) {\n return false\n }\n\n if (Boolean(e1.childNodes) !== Boolean(e2.childNodes)) {\n return false\n }\n if (e1.attributes) {\n const e1Attributes = Object.keys(e1.attributes)\n const e2Attributes = Object.keys(e2.attributes)\n\n if (e1Attributes.length !== e2Attributes.length) {\n return false\n }\n if (!e1Attributes.every(attribute => {\n if (e1.attributes[attribute] !== e2.attributes[attribute]) {\n return false\n }\n return true\n })) {\n return false\n }\n }\n if (e1.childNodes) {\n if (e1.childNodes.length !== e2.childNodes.length) {\n return false\n }\n if (!e1.childNodes.every((childNode, index) => isEqual(childNode, e2.childNodes[index]))) {\n\n return false\n }\n\n }\n\n return true\n}\n\n\nexport function roughlyEqual(e1, e2, uniqueDescriptors, sameSiblings, preventRecursion) {\n\n if (!e1 || !e2) {\n return false\n }\n\n if (e1.nodeName !== e2.nodeName) {\n return false\n }\n\n if (e1.nodeName === '#text') {\n // Note that we initially don't care what the text content of a node is,\n // the mere fact that it's the same tag and \"has text\" means it's roughly\n // equal, and then we can find out the true text difference later.\n return preventRecursion ? true : e1.data === e2.data\n }\n\n\n if (e1.nodeName in uniqueDescriptors) {\n return true\n }\n\n if (e1.attributes && e2.attributes) {\n\n if (e1.attributes.id) {\n if (e1.attributes.id !== e2.attributes.id) {\n return false\n } else {\n const idDescriptor = `${e1.nodeName}#${e1.attributes.id}`\n if (idDescriptor in uniqueDescriptors) {\n return true\n }\n }\n }\n if (e1.attributes['class'] && e1.attributes['class'] === e2.attributes['class']) {\n const classDescriptor = `${e1.nodeName}.${e1.attributes['class'].replace(/ /g, '.')}`\n if (classDescriptor in uniqueDescriptors) {\n return true\n }\n }\n }\n\n if (sameSiblings) {\n return true\n }\n\n const nodeList1 = e1.childNodes ? e1.childNodes.slice().reverse() : []\n const nodeList2 = e2.childNodes ? e2.childNodes.slice().reverse() : []\n\n if (nodeList1.length !== nodeList2.length) {\n return false\n }\n\n if (preventRecursion) {\n return nodeList1.every((element, index) => element.nodeName === nodeList2[index].nodeName)\n } else {\n // note: we only allow one level of recursion at any depth. If 'preventRecursion'\n // was not set, we must explicitly force it to true for child iterations.\n const childUniqueDescriptors = uniqueInBoth(nodeList1, nodeList2)\n return nodeList1.every((element, index) => roughlyEqual(element, nodeList2[index], childUniqueDescriptors, true, true))\n }\n}\n\n\nexport function cloneObj(obj) { // TODO: Do we really need to clone here? Is it not enough to just return the original object?\n return JSON.parse(JSON.stringify(obj))\n}\n/**\n * based on https://en.wikibooks.org/wiki/Algorithm_implementation/Strings/Longest_common_substring#JavaScript\n */\nfunction findCommonSubsets(c1, c2, marked1, marked2) {\n let lcsSize = 0\n let index = []\n const c1Length = c1.length\n const c2Length = c2.length\n\n const // set up the matching table\n matches = Array(...new Array(c1Length + 1)).map(() => [])\n\n const uniqueDescriptors = uniqueInBoth(c1, c2)\n\n let // If all of the elements are the same tag, id and class, then we can\n // consider them roughly the same even if they have a different number of\n // children. This will reduce removing and re-adding similar elements.\n subsetsSame = c1Length === c2Length\n\n if (subsetsSame) {\n\n c1.some((element, i) => {\n const c1Desc = elementDescriptors(element)\n const c2Desc = elementDescriptors(c2[i])\n if (c1Desc.length !== c2Desc.length) {\n subsetsSame = false\n return true\n }\n c1Desc.some((description, i) => {\n if (description !== c2Desc[i]) {\n subsetsSame = false\n return true\n }\n })\n if (!subsetsSame) {\n return true\n }\n })\n }\n\n // fill the matches with distance values\n for (let c1Index = 0; c1Index < c1Length; c1Index++) {\n const c1Element = c1[c1Index]\n for (let c2Index = 0; c2Index < c2Length; c2Index++) {\n const c2Element = c2[c2Index]\n if (!marked1[c1Index] && !marked2[c2Index] && roughlyEqual(c1Element, c2Element, uniqueDescriptors, subsetsSame)) {\n matches[c1Index + 1][c2Index + 1] = (matches[c1Index][c2Index] ? matches[c1Index][c2Index] + 1 : 1)\n if (matches[c1Index + 1][c2Index + 1] >= lcsSize) {\n lcsSize = matches[c1Index + 1][c2Index + 1]\n index = [c1Index + 1, c2Index + 1]\n }\n } else {\n matches[c1Index + 1][c2Index + 1] = 0\n }\n }\n }\n\n if (lcsSize === 0) {\n return false\n }\n\n return {\n oldValue: index[0] - lcsSize,\n newValue: index[1] - lcsSize,\n length: lcsSize\n }\n}\n\n/**\n * This should really be a predefined function in Array...\n */\nfunction makeArray(n, v) {\n return Array(...new Array(n)).map(() => v)\n}\n\n/**\n * Generate arrays that indicate which node belongs to which subset,\n * or whether it's actually an orphan node, existing in only one\n * of the two trees, rather than somewhere in both.\n *\n * So if t1 = <img><canvas><br>, t2 = <canvas><br><img>.\n * The longest subset is \"<canvas><br>\" (length 2), so it will group 0.\n * The second longest is \"<img>\" (length 1), so it will be group 1.\n * gaps1 will therefore be [1,0,0] and gaps2 [0,0,1].\n *\n * If an element is not part of any group, it will stay being 'true', which\n * is the initial value. For example:\n * t1 = <img><p></p><br><canvas>, t2 = <b></b><br><canvas><img>\n *\n * The \"<p></p>\" and \"<b></b>\" do only show up in one of the two and will\n * therefore be marked by \"true\". The remaining parts are parts of the\n * groups 0 and 1:\n * gaps1 = [1, true, 0, 0], gaps2 = [true, 0, 0, 1]\n *\n */\nexport function getGapInformation(t1, t2, stable) {\n const gaps1 = t1.childNodes ? makeArray(t1.childNodes.length, true) : []\n const gaps2 = t2.childNodes ? makeArray(t2.childNodes.length, true) : []\n let group = 0\n\n // give elements from the same subset the same group number\n stable.forEach(subset => {\n const endOld = subset.oldValue + subset.length\n const endNew = subset.newValue + subset.length\n\n for (let j = subset.oldValue; j < endOld; j += 1) {\n gaps1[j] = group\n }\n for (let j = subset.newValue; j < endNew; j += 1) {\n gaps2[j] = group\n }\n group += 1\n })\n\n return {\n gaps1,\n gaps2\n }\n}\n\n/**\n * Find all matching subsets, based on immediate child differences only.\n */\nexport function markSubTrees(oldTree, newTree) {\n // note: the child lists are views, and so update as we update old/newTree\n const oldChildren = oldTree.childNodes ? oldTree.childNodes : []\n\n const newChildren = newTree.childNodes ? newTree.childNodes : []\n const marked1 = makeArray(oldChildren.length, false)\n const marked2 = makeArray(newChildren.length, false)\n const subsets = []\n let subset = true\n\n const returnIndex = function() {\n return arguments[1]\n }\n\n const markBoth = i => {\n marked1[subset.oldValue + i] = true\n marked2[subset.newValue + i] = true\n }\n\n while (subset) {\n subset = findCommonSubsets(oldChildren, newChildren, marked1, marked2)\n if (subset) {\n subsets.push(subset)\n const subsetArray = Array(...new Array(subset.length)).map(returnIndex)\n subsetArray.forEach(item => markBoth(item))\n }\n }\n\n oldTree.subsets = subsets\n oldTree.subsetsAge = 100\n return subsets\n}\n\nexport class DiffTracker {\n constructor() {\n this.list = []\n }\n\n add(diffs) {\n this.list.push(...diffs)\n }\n forEach(fn) {\n this.list.forEach(li => fn(li))\n }\n\n}\n","export {DiffFinder} from \"./diff\"\nexport {nodeToObj} from \"./fromDOM\"\nexport {stringToObj} from \"./fromString\"\n","export {DiffDOM, nodeToObj, stringToObj} from \"./diffDOM/index\"\nexport {TraceLogger} from \"./TraceLogger\"\n","/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n\nvar objectToString = Object.prototype.toString;\nvar isArray = Array.isArray || function isArrayPolyfill (object) {\n return objectToString.call(object) === '[object Array]';\n};\n\nfunction isFunction (object) {\n return typeof object === 'function';\n}\n\n/**\n * More correct typeof string handling array\n * which normally returns typeof 'object'\n */\nfunction typeStr (obj) {\n return isArray(obj) ? 'array' : typeof obj;\n}\n\nfunction escapeRegExp (string) {\n return string.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n}\n\n/**\n * Null safe way of checking whether or not an object,\n * including its prototype, has a given property\n */\nfunction hasProperty (obj, propName) {\n return obj != null && typeof obj === 'object' && (propName in obj);\n}\n\n/**\n * Safe way of detecting whether or not the given thing is a primitive and\n * whether it has the given property\n */\nfunction primitiveHasOwnProperty (primitive, propName) {\n return (\n primitive != null\n && typeof primitive !== 'object'\n && primitive.hasOwnProperty\n && primitive.hasOwnProperty(propName)\n );\n}\n\n// Workaround for https://issues.apache.org/jira/browse/COUCHDB-577\n// See https://github.com/janl/mustache.js/issues/189\nvar regExpTest = RegExp.prototype.test;\nfunction testRegExp (re, string) {\n return regExpTest.call(re, string);\n}\n\nvar nonSpaceRe = /\\S/;\nfunction isWhitespace (string) {\n return !testRegExp(nonSpaceRe, string);\n}\n\nvar entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n};\n\nfunction escapeHtml (string) {\n return String(string).replace(/[&<>\"'`=\\/]/g, function fromEntityMap (s) {\n return entityMap[s];\n });\n}\n\nvar whiteRe = /\\s*/;\nvar spaceRe = /\\s+/;\nvar equalsRe = /\\s*=/;\nvar curlyRe = /\\s*\\}/;\nvar tagRe = /#|\\^|\\/|>|\\{|&|=|!/;\n\n/**\n * Breaks up the given `template` string into a tree of tokens. If the `tags`\n * argument is given here it must be an array with two string values: the\n * opening and closing tags used in the template (e.g. [ \"<%\", \"%>\" ]). Of\n * course, the default is to use mustaches (i.e. mustache.tags).\n *\n * A token is an array with at least 4 elements. The first element is the\n * mustache symbol that was used inside the tag, e.g. \"#\" or \"&\". If the tag\n * did not contain a symbol (i.e. {{myValue}}) this element is \"name\". For\n * all text that appears outside a symbol this element is \"text\".\n *\n * The second element of a token is its \"value\". For mustache tags this is\n * whatever else was inside the tag besides the opening symbol. For text tokens\n * this is the text itself.\n *\n * The third and fourth elements of the token are the start and end indices,\n * respectively, of the token in the original template.\n *\n * Tokens that are the root node of a subtree contain two more elements: 1) an\n * array of tokens in the subtree and 2) the index in the original template at\n * which the closing tag for that section begins.\n *\n * Tokens for partials also contain two more elements: 1) a string value of\n * indendation prior to that tag and 2) the index of that tag on that line -\n * eg a value of 2 indicates the partial is the third tag on this line.\n */\nfunction parseTemplate (template, tags) {\n if (!template)\n return [];\n var lineHasNonSpace = false;\n var sections = []; // Stack to hold section tokens\n var tokens = []; // Buffer to hold the tokens\n var spaces = []; // Indices of whitespace tokens on the current line\n var hasTag = false; // Is there a {{tag}} on the current line?\n var nonSpace = false; // Is there a non-space char on the current line?\n var indentation = ''; // Tracks indentation for tags that use it\n var tagIndex = 0; // Stores a count of number of tags encountered on a line\n\n // Strips all whitespace tokens array for the current line\n // if there was a {{#tag}} on it and otherwise only space.\n function stripSpace () {\n if (hasTag && !nonSpace) {\n while (spaces.length)\n delete tokens[spaces.pop()];\n } else {\n spaces = [];\n }\n\n hasTag = false;\n nonSpace = false;\n }\n\n var openingTagRe, closingTagRe, closingCurlyRe;\n function compileTags (tagsToCompile) {\n if (typeof tagsToCompile === 'string')\n tagsToCompile = tagsToCompile.split(spaceRe, 2);\n\n if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)\n throw new Error('Invalid tags: ' + tagsToCompile);\n\n openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\\\s*');\n closingTagRe = new RegExp('\\\\s*' + escapeRegExp(tagsToCompile[1]));\n closingCurlyRe = new RegExp('\\\\s*' + escapeRegExp('}' + tagsToCompile[1]));\n }\n\n compileTags(tags || mustache.tags);\n\n var scanner = new Scanner(template);\n\n var start, type, value, chr, token, openSection;\n while (!scanner.eos()) {\n start = scanner.pos;\n\n // Match any text between tags.\n value = scanner.scanUntil(openingTagRe);\n\n if (value) {\n for (var i = 0, valueLength = value.length; i < valueLength; ++i) {\n chr = value.charAt(i);\n\n if (isWhitespace(chr)) {\n spaces.push(tokens.length);\n indentation += chr;\n } else {\n nonSpace = true;\n lineHasNonSpace = true;\n indentation += ' ';\n }\n\n tokens.push([ 'text', chr, start, start + 1 ]);\n start += 1;\n\n // Check for whitespace on the current line.\n if (chr === '\\n') {\n stripSpace();\n indentation = '';\n tagIndex = 0;\n lineHasNonSpace = false;\n }\n }\n }\n\n // Match the opening tag.\n if (!scanner.scan(openingTagRe))\n break;\n\n hasTag = true;\n\n // Get the tag type.\n type = scanner.scan(tagRe) || 'name';\n scanner.scan(whiteRe);\n\n // Get the tag value.\n if (type === '=') {\n value = scanner.scanUntil(equalsRe);\n scanner.scan(equalsRe);\n scanner.scanUntil(closingTagRe);\n } else if (type === '{') {\n value = scanner.scanUntil(closingCurlyRe);\n scanner.scan(curlyRe);\n scanner.scanUntil(closingTagRe);\n type = '&';\n } else {\n value = scanner.scanUntil(closingTagRe);\n }\n\n // Match the closing tag.\n if (!scanner.scan(closingTagRe))\n throw new Error('Unclosed tag at ' + scanner.pos);\n\n if (type == '>') {\n token = [ type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace ];\n } else {\n token = [ type, value, start, scanner.pos ];\n }\n tagIndex++;\n tokens.push(token);\n\n if (type === '#' || type === '^') {\n sections.push(token);\n } else if (type === '/') {\n // Check section nesting.\n openSection = sections.pop();\n\n if (!openSection)\n throw new Error('Unopened section \"' + value + '\" at ' + start);\n\n if (openSection[1] !== value)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + start);\n } else if (type === 'name' || type === '{' || type === '&') {\n nonSpace = true;\n } else if (type === '=') {\n // Set the tags for the next time around.\n compileTags(value);\n }\n }\n\n stripSpace();\n\n // Make sure there are no open sections when we're done.\n openSection = sections.pop();\n\n if (openSection)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + scanner.pos);\n\n return nestTokens(squashTokens(tokens));\n}\n\n/**\n * Combines the values of consecutive text tokens in the given `tokens` array\n * to a single token.\n */\nfunction squashTokens (tokens) {\n var squashedTokens = [];\n\n var token, lastToken;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n if (token) {\n if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {\n lastToken[1] += token[1];\n lastToken[3] = token[3];\n } else {\n squashedTokens.push(token);\n lastToken = token;\n }\n }\n }\n\n return squashedTokens;\n}\n\n/**\n * Forms the given array of `tokens` into a nested tree structure where\n * tokens that represent a section have two additional items: 1) an array of\n * all tokens that appear in that section and 2) the index in the original\n * template that represents the end of that section.\n */\nfunction nestTokens (tokens) {\n var nestedTokens = [];\n var collector = nestedTokens;\n var sections = [];\n\n var token, section;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n switch (token[0]) {\n case '#':\n case '^':\n collector.push(token);\n sections.push(token);\n collector = token[4] = [];\n break;\n case '/':\n section = sections.pop();\n section[5] = token[2];\n collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;\n break;\n default:\n collector.push(token);\n }\n }\n\n return nestedTokens;\n}\n\n/**\n * A simple string scanner that is used by the template parser to find\n * tokens in template strings.\n */\nfunction Scanner (string) {\n this.string = string;\n this.tail = string;\n this.pos = 0;\n}\n\n/**\n * Returns `true` if the tail is empty (end of string).\n */\nScanner.prototype.eos = function eos () {\n return this.tail === '';\n};\n\n/**\n * Tries to match the given regular expression at the current position.\n * Returns the matched text if it can match, the empty string otherwise.\n */\nScanner.prototype.scan = function scan (re) {\n var match = this.tail.match(re);\n\n if (!match || match.index !== 0)\n return '';\n\n var string = match[0];\n\n this.tail = this.tail.substring(string.length);\n this.pos += string.length;\n\n return string;\n};\n\n/**\n * Skips all text until the given regular expression can be matched. Returns\n * the skipped string, which is the entire tail if no match can be made.\n */\nScanner.prototype.scanUntil = function scanUntil (re) {\n var index = this.tail.search(re), match;\n\n switch (index) {\n case -1:\n match = this.tail;\n this.tail = '';\n break;\n case 0:\n match = '';\n break;\n default:\n match = this.tail.substring(0, index);\n this.tail = this.tail.substring(index);\n }\n\n this.pos += match.length;\n\n return match;\n};\n\n/**\n * Represents a rendering context by wrapping a view object and\n * maintaining a reference to the parent context.\n */\nfunction Context (view, parentContext) {\n this.view = view;\n this.cache = { '.': this.view };\n this.parent = parentContext;\n}\n\n/**\n * Creates a new context using the given view with this context\n * as the parent.\n */\nContext.prototype.push = function push (view) {\n return new Context(view, this);\n};\n\n/**\n * Returns the value of the given name in this context, traversing\n * up the context hierarchy if the value is absent in this context's view.\n */\nContext.prototype.lookup = function lookup (name) {\n var cache = this.cache;\n\n var value;\n if (cache.hasOwnProperty(name)) {\n value = cache[name];\n } else {\n var context = this, intermediateValue, names, index, lookupHit = false;\n\n while (context) {\n if (name.indexOf('.') > 0) {\n intermediateValue = context.view;\n names = name.split('.');\n index = 0;\n\n /**\n * Using the dot notion path in `name`, we descend through the\n * nested objects.\n *\n * To be certain that the lookup has been successful, we have to\n * check if the last object in the path actually has the property\n * we are looking for. We store the result in `lookupHit`.\n *\n * This is specially necessary for when the value has been set to\n * `undefined` and we want to avoid looking up parent contexts.\n *\n * In the case where dot notation is used, we consider the lookup\n * to be successful even if the last \"object\" in the path is\n * not actually an object but a primitive (e.g., a string, or an\n * integer), because it is sometimes useful to access a property\n * of an autoboxed primitive, such as the length of a string.\n **/\n while (intermediateValue != null && index < names.length) {\n if (index === names.length - 1)\n lookupHit = (\n hasProperty(intermediateValue, names[index])\n || primitiveHasOwnProperty(intermediateValue, names[index])\n );\n\n intermediateValue = intermediateValue[names[index++]];\n }\n } else {\n intermediateValue = context.view[name];\n\n /**\n * Only checking against `hasProperty`, which always returns `false` if\n * `context.view` is not an object. Deliberately omitting the check\n * against `primitiveHasOwnProperty` if dot notation is not used.\n *\n * Consider this example:\n * ```\n * Mustache.render(\"The length of a football field is {{#length}}{{length}}{{/length}}.\", {length: \"100 yards\"})\n * ```\n *\n * If we were to check also against `primitiveHasOwnProperty`, as we do\n * in the dot notation case, then render call would return:\n *\n * \"The length of a football field is 9.\"\n *\n * rather than the expected:\n *\n * \"The length of a football field is 100 yards.\"\n **/\n lookupHit = hasProperty(context.view, name);\n }\n\n if (lookupHit) {\n value = intermediateValue;\n break;\n }\n\n context = context.parent;\n }\n\n cache[name] = value;\n }\n\n if (isFunction(value))\n value = value.call(this.view);\n\n return value;\n};\n\n/**\n * A Writer knows how to take a stream of tokens and render them to a\n * string, given a context. It also maintains a cache of templates to\n * avoid the need to parse the same template twice.\n */\nfunction Writer () {\n this.templateCache = {\n _cache: {},\n set: function set (key, value) {\n this._cache[key] = value;\n },\n get: function get (key) {\n return this._cache[key];\n },\n clear: function clear () {\n this._cache = {};\n }\n };\n}\n\n/**\n * Clears all cached templates in this writer.\n */\nWriter.prototype.clearCache = function clearCache () {\n if (typeof this.templateCache !== 'undefined') {\n this.templateCache.clear();\n }\n};\n\n/**\n * Parses and caches the given `template` according to the given `tags` or\n * `mustache.tags` if `tags` is omitted, and returns the array of tokens\n * that is generated from the parse.\n */\nWriter.prototype.parse = function parse (template, tags) {\n var cache = this.templateCache;\n var cacheKey = template + ':' + (tags || mustache.tags).join(':');\n var isCacheEnabled = typeof cache !== 'undefined';\n var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined;\n\n if (tokens == undefined) {\n tokens = parseTemplate(template, tags);\n isCacheEnabled && cache.set(cacheKey, tokens);\n }\n return tokens;\n};\n\n/**\n * High-level method that is used to render the given `template` with\n * the given `view`.\n *\n * The optional `partials` argument may be an object that contains the\n * names and templates of partials that are used in the template. It may\n * also be a function that is used to load partial templates on the fly\n * that takes a single argument: the name of the partial.\n *\n * If the optional `config` argument is given here, then it should be an\n * object with a `tags` attribute or an `escape` attribute or both.\n * If an array is passed, then it will be interpreted the same way as\n * a `tags` attribute on a `config` object.\n *\n * The `tags` attribute of a `config` object must be an array with two\n * string values: the opening and closing tags used in the template (e.g.\n * [ \"<%\", \"%>\" ]). The default is to mustache.tags.\n *\n * The `escape` attribute of a `config` object must be a function which\n * accepts a string as input and outputs a safely escaped string.\n * If an `escape` function is not provided, then an HTML-safe string\n * escaping function is used as the default.\n */\nWriter.prototype.render = function render (template, view, partials, config) {\n var tags = this.getConfigTags(config);\n var tokens = this.parse(template, tags);\n var context = (view instanceof Context) ? view : new Context(view, undefined);\n return this.renderTokens(tokens, context, partials, template, config);\n};\n\n/**\n * Low-level method that renders the given array of `tokens` using\n * the given `context` and `partials`.\n *\n * Note: The `originalTemplate` is only ever used to extract the portion\n * of the original template that was contained in a higher-order section.\n * If the template doesn't use higher-order sections, this argument may\n * be omitted.\n */\nWriter.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, config) {\n var buffer = '';\n\n var token, symbol, value;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n value = undefined;\n token = tokens[i];\n symbol = token[0];\n\n if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate, config);\n else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate, config);\n else if (symbol === '>') value = this.renderPartial(token, context, partials, config);\n else if (symbol === '&') value = this.unescapedValue(token, context);\n else if (symbol === 'name') value = this.escapedValue(token, context, config);\n else if (symbol === 'text') value = this.rawValue(token);\n\n if (value !== undefined)\n buffer += value;\n }\n\n return buffer;\n};\n\nWriter.prototype.renderSection = function renderSection (token, context, partials, originalTemplate, config) {\n var self = this;\n var buffer = '';\n var value = context.lookup(token[1]);\n\n // This function is used to render an arbitrary template\n // in the current context by higher-order sections.\n function subRender (template) {\n return self.render(template, context, partials, config);\n }\n\n if (!value) return;\n\n if (isArray(value)) {\n for (var j = 0, valueLength = value.length; j < valueLength; ++j) {\n buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config);\n }\n } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {\n buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config);\n } else if (isFunction(value)) {\n if (typeof originalTemplate !== 'string')\n throw new Error('Cannot use higher-order sections without the original template');\n\n // Extract the portion of the original template that the section contains.\n value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);\n\n if (value != null)\n buffer += value;\n } else {\n buffer += this.renderTokens(token[4], context, partials, originalTemplate, config);\n }\n return buffer;\n};\n\nWriter.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate, config) {\n var value = context.lookup(token[1]);\n\n // Use JavaScript's definition of falsy. Include empty arrays.\n // See https://github.com/janl/mustache.js/issues/186\n if (!value || (isArray(value) && value.length === 0))\n return this.renderTokens(token[4], context, partials, originalTemplate, config);\n};\n\nWriter.prototype.indentPartial = function indentPartial (partial, indentation, lineHasNonSpace) {\n var filteredIndentation = indentation.replace(/[^ \\t]/g, '');\n var partialByNl = partial.split('\\n');\n for (var i = 0; i < partialByNl.length; i++) {\n if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) {\n partialByNl[i] = filteredIndentation + partialByNl[i];\n }\n }\n return partialByNl.join('\\n');\n};\n\nWriter.prototype.renderPartial = function renderPartial (token, context, partials, config) {\n if (!partials) return;\n var tags = this.getConfigTags(config);\n\n var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];\n if (value != null) {\n var lineHasNonSpace = token[6];\n var tagIndex = token[5];\n var indentation = token[4];\n var indentedValue = value;\n if (tagIndex == 0 && indentation) {\n indentedValue = this.indentPartial(value, indentation, lineHasNonSpace);\n }\n var tokens = this.parse(indentedValue, tags);\n return this.renderTokens(tokens, context, partials, indentedValue, config);\n }\n};\n\nWriter.prototype.unescapedValue = function unescapedValue (token, context) {\n var value = context.lookup(token[1]);\n if (value != null)\n return value;\n};\n\nWriter.prototype.escapedValue = function escapedValue (token, context, config) {\n var escape = this.getConfigEscape(config) || mustache.escape;\n var value = context.lookup(token[1]);\n if (value != null)\n return (typeof value === 'number' && escape === mustache.escape) ? String(value) : escape(value);\n};\n\nWriter.prototype.rawValue = function rawValue (token) {\n return token[1];\n};\n\nWriter.prototype.getConfigTags = function getConfigTags (config) {\n if (isArray(config)) {\n return config;\n }\n else if (config && typeof config === 'object') {\n return config.tags;\n }\n else {\n return undefined;\n }\n};\n\nWriter.prototype.getConfigEscape = function getConfigEscape (config) {\n if (config && typeof config === 'object' && !isArray(config)) {\n return config.escape;\n }\n else {\n return undefined;\n }\n};\n\nvar mustache = {\n name: 'mustache.js',\n version: '4.2.0',\n tags: [ '{{', '}}' ],\n clearCache: undefined,\n escape: undefined,\n parse: undefined,\n render: undefined,\n Scanner: undefined,\n Context: undefined,\n Writer: undefined,\n /**\n * Allows a user to override the default caching strategy, by providing an\n * object with set, get and clear methods. This can also be used to disable\n * the cache by setting it to the literal `undefined`.\n */\n set templateCache (cache) {\n defaultWriter.templateCache = cache;\n },\n /**\n * Gets the default or overridden caching object from the default writer.\n */\n get templateCache () {\n return defaultWriter.templateCache;\n }\n};\n\n// All high-level mustache.* functions use this writer.\nvar defaultWriter = new Writer();\n\n/**\n * Clears all cached templates in the default writer.\n */\nmustache.clearCache = function clearCache () {\n return defaultWriter.clearCache();\n};\n\n/**\n * Parses and caches the given template in the default writer and returns the\n * array of tokens it contains. Doing this ahead of time avoids the need to\n * parse templates on the fly as they are rendered.\n */\nmustache.parse = function parse (template, tags) {\n return defaultWriter.parse(template, tags);\n};\n\n/**\n * Renders the `template` with the given `view`, `partials`, and `config`\n * using the default writer.\n */\nmustache.render = function render (template, view, partials, config) {\n if (typeof template !== 'string') {\n throw new TypeError('Invalid template! Template should be a \"string\" ' +\n 'but \"' + typeStr(template) + '\" was given as the first ' +\n 'argument for mustache#render(template, view, partials)');\n }\n\n return defaultWriter.render(template, view, partials, config);\n};\n\n// Export the escaping function so that the user may override it.\n// See https://github.com/janl/mustache.js/issues/244\nmustache.escape = escapeHtml;\n\n// Export these mainly for testing, but also for advanced usage.\nmustache.Scanner = Scanner;\nmustache.Context = Context;\nmustache.Writer = Writer;\n\nexport default mustache;\n"],"names":[],"sourceRoot":""}