wikimedia/mediawiki-extensions-MobileFrontend

View on GitHub
resources/dist/mobile.common.js.map.json

Summary

Maintainability
Test Coverage
{"version":3,"file":"mobile.common.js","mappings":"sHAAA,IAAMA,EAAQC,EAAS,iCAGvBC,EAAOC,QAAU,WAChB,IAAMC,EAAUJ,EAAMK,SAASC,IAGzBC,EAAkBP,EAAMQ,QAAS,CACtCC,QAAS,OACTC,YAAY,EACZC,MAAOC,GAAGC,IAAK,oCACZP,IAeJ,OAZqBQ,EAAG,SACtBC,SAAU,mCACVC,OAAQF,EAAG,SACVC,SAAU,gCAEVA,SAAU,kBACVC,OAAQF,EAAG,SACVC,SAAU,yBACVC,OAAQZ,EAASG,IAKtB,C,y+CC3BA,IACCU,EAAOhB,EAAS,gCAChBiB,EAAOjB,EAAS,gCAQXkB,EAAM,SAAAC,GAAA,sBAAAD,IAAA,O,4FAAAE,CAAA,KAAAF,GAAAG,EAAA,KAAAH,EAAAI,UAAA,Q,qRAAAC,CAAAL,EAAAC,G,EAAAD,G,EAAA,EAAAM,IAAA,iBAAAC,IAIX,WACC,OAAO,CACR,GAEA,CAAAD,IAAA,WAAAC,IAWA,WACC,MAAO,CACNC,iBAAaC,EACbC,iBAAaD,EACbE,qBAAsB,GACtBC,UAAMH,EACNjB,WAAOiB,EAET,GAEA,CAAAH,IAAA,WAAAC,IAGA,WACC,OAAOR,EAAKc,SAAS,uOAMtB,M,6EAAC,CAvCU,CAASf,GA0CrBf,EAAOC,QAAUgB,C,8CCpDjB,IAEIc,EAFEf,EAAOjB,EAAS,gCAYtB,SAASiC,EAASC,GAMjB,IAAMC,EAAW,WAChB,IAAMC,EAAQC,KAAM,UAAYF,EAASG,WACtCD,KAAM,UAAYF,EAASG,SAAY,CAAC,GAC1Cd,EAAM,GAAGe,KAAKC,KAAMlB,UAAW,KAChC,OAAKmB,OAAOC,UAAUC,eAAeH,KAAMJ,EAAOZ,GAC1CY,EAAOZ,GAENY,EAAOZ,GAAQU,EAAOU,MAAOP,KAAMf,UAC7C,EAEA,OADAa,EAASG,QAAUO,KAAKC,MAAMC,WAAaC,KAAKC,SAASF,WAClDZ,CACR,CAUA,SAASe,EAASC,EAAIC,GACrBf,KAAKgB,UAAYF,EACjBd,KAAKhC,IAAM+C,CACZ,CAEAF,EAAQR,UAAY,CAUnBY,MAAOrB,GAAS,SAAWsB,GAC1B,IAAMJ,EAAKd,KAAKgB,UACfG,EAAM,oBAAoBC,KAAMN,GAEjC,IAAKK,IAAOD,EAeX,OAAOC,EAdP,OAASD,GACR,KAAK,EAIJ,MAAO,QAAQE,KAAMN,IAAQ,aAAaM,KAAMN,GACjD,KAAK,EACJ,MAAO,QAAQM,KAAMN,GACtB,KAAK,EACJ,MAAO,QAAQM,KAAMN,GACtB,QACC,OAAO,EAKX,IAQAO,aAAczB,GAAS,WACtB,IAAM0B,EAAMC,SAAUjD,GAAGkD,OAAOpC,IAAK,yBAA2B,IAGhE,OAAOqC,OAAOC,YAAcJ,CAC7B,IAQAK,oBAAqB/B,GAAS,iBAAM,iBAAkB6B,MAAM,KAO7DZ,EAAQe,aAAe,WACtB,IAAIC,EAKJ,OAJMlC,IACLkC,EAAQjD,EAAKkD,cACbnC,EAAU,IAAIkB,EAASY,OAAOM,UAAUf,UAAWa,IAE7ClC,CACR,EAEA/B,EAAOC,QAAUgD,C,6CChHjB,IACCmB,EAAWrE,EAAS,oCACpBiB,EAAOjB,EAAS,gCAChBgB,EAAOhB,EAAS,gCAChBsE,EAAatE,EAAS,sCAavB,SAASuE,EAAQC,GAChBxD,EAAKwB,KAAMH,KAAMmC,EAClB,CAEAH,EAAUE,EAAQvD,EAAM,CAMvByD,UAAS,WAER,IAAIC,EAAS,UACRrC,KAAKmC,QAAQ9C,YACjBgD,EAAS,cACErC,KAAKmC,QAAQ5C,cACxB8C,EAAS,eAEV,IAAIC,EAAStC,KAAKmC,QAAQI,MAAQ,QAAU,UACvCvC,KAAKmC,QAAQ9C,aAAeW,KAAKmC,QAAQ5C,eAC7C+C,EAAS,WAELtC,KAAKmC,QAAQK,QACjBxC,KAAKmC,QAAQ3C,sBAAwB,oBAEtC,IAAM2C,EAAUvD,EAAK6D,OAAQ,CAC5BH,OAAAA,EACAD,OAAAA,EACAjE,YAAY,EACZsE,KAAM,MACJ1C,KAAKmC,SAERnC,KAAK2C,QAAU,IAAIV,EAAYE,GAC/BnC,KAAKmC,QAAQS,YAAc5C,KAAK2C,QAAQ3E,IAAIoB,IAAK,GAAIyD,SACtD,EAMAC,gBAAgB,EAgBhBC,SAAU,CACT5E,QAAS,IACT6E,UAAU,EACVR,WAAOlD,EACPD,iBAAaC,EACbC,iBAAaD,EACbiD,WAAOjD,EACPE,qBAAsB,GACtBC,UAAMH,EACNjB,WAAOiB,EACP2D,KAAM,UAMPvD,SAAUd,EAAKc,SAAU,uBAG1B9B,EAAOC,QAAUqE,C,gDC5FjB,IACCgB,EAASvF,EAAS,kCAClBiB,EAAOjB,EAAS,gCAChBuE,EAASvE,EAAS,kCAClBkB,EAASlB,EAAS,kCAsCnB,SAASwF,IAA0B,IAAfhB,EAAOlD,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,EACxBoE,EAASC,EAAgBnB,EAAQoB,YAAapB,EAAQqB,UAC5D,OAAO,IAAIN,EACVtE,EAAK6D,OAAQ,CACZgB,SAAU,CACT7E,EAAK8E,UAAW,OAAQC,KAAMxB,EAAQyB,SACtC,IAAI1B,EAAQtD,EAAK6D,OAAQ,CACxBpD,aAAa,EACbI,KAAMnB,GAAGM,KAAKiF,OAAQ,oBAAqBR,GAC3ChF,MAAOC,GAAGC,IAAK,+CACb4D,EAAQ2B,oBAAsB9F,IACjCY,EAAK8E,UAAW,SAAUjF,SAAU,uBAAwBC,OAE3D,IAAIG,EAAQD,EAAK6D,OAAQ,CACxBhD,KAAMnB,GAAGM,KAAKiF,OACb,oBAAqBE,EAAcV,EAAQlB,EAAQ6B,oBAEpD3E,aAAa,EACbhB,MAAOC,GAAGC,IAAK,gDACb4D,EAAQ8B,eAAiBjG,OAG5BmE,GAEL,CAUA,SAASmB,EAAgBD,EAAQa,GAChC,OAAOtF,EAAK6D,OAAQ,CAEnB0B,SAAUD,GAAe5F,GAAGkD,OAAOpC,IAAK,eACtCiE,EACJ,CASA,SAASU,IAER,MADA,GAAGK,KAAKjE,KAAMlB,UAAW,CAAEoF,KAAM,WAC1BzF,EAAK6D,OAAOlC,MAAO3B,EAAMK,UACjC,CAEAkE,EAAU9C,UAAUe,KAAO,CAC1BkC,eAAAA,EACAS,aAAAA,GAGDnG,EAAOC,QAAUsF,C,6CCpGjB,IACCnB,EAAWrE,EAAS,oCACpBgB,EAAOhB,EAAS,gCAChBiB,EAAOjB,EAAS,gCAChBsE,EAAatE,EAAS,sCAcvB,SAASuF,EAAQoB,GAChBtE,KAAKuE,gBAAkBD,EAAME,WAAa,GAC1CxE,KAAKyE,aAAe,IAAIxC,EAAY,CACnCS,KAAM,SACNlD,qBAAsB,SACtBnB,MAAOC,GAAGC,IAAK,wCAEhBI,EAAKwB,KAAMH,KACVpB,EAAK6D,OACJ,CACCiC,aAAc,WAAO,EACrBC,kBAAkB,GAEnBL,EACA,CACCE,UAAW,oBAEZ,CAAEI,OAAQhG,EAAK6D,OAAQ,CACtB,gCAAiC,WAChCzC,KAAK6E,MACN,EAAEC,KAAM9E,MACR,gBAAiB,SAAW+E,GAC3BA,EAAGC,iBACHhF,KAAK6E,MACN,EAAEC,KAAM9E,MACRiF,MAAK,SAAEF,GACNA,EAAGG,iBACJ,GACEZ,EAAMM,UAGZ,CAEA5C,EAAUkB,EAAQvE,EAAM,CACvBwG,MAAO,KAUPC,KAAI,WACH,IAAMC,EAAIzG,EAAK0G,WACftF,KAAKhC,IAAIuH,QAASvF,KAAKmF,OAEvBnF,KAAKhC,IAAIwH,QACT,IAAMC,EAAUzF,KAAKhC,IAAI0H,KAAM,WAc/B,OAbA1F,KAAKmF,MAAM1G,SAAU,mCACfgH,EAAQE,SAAU,WAUvBN,EAAEO,WATFH,EAAQhH,SAAU,WAGlBH,GAAGuH,KAAM,iCAAkCC,KAAM9F,KAAKhC,KACjDgC,KAAKmC,QAAQ4D,QACjB/F,KAAKmC,QAAQ4D,OAAQV,GAEtBW,uBAAuB,kBAAMX,EAAEO,SAAS,KAIlCP,EAAEY,SACV,EAQApB,KAAI,WAAG,IAAAqB,EAAA,KACUlG,KAAKhC,IAAI0H,KAAM,WACvBS,YAAa,WACrBnG,KAAKmF,MAAMgB,YAAa,mCAIxBC,YAAY,WACXF,EAAKf,MAAMkB,QACZ,GAAG,KACHL,uBAAuB,WACtBE,EAAK/D,QAAQuC,aAAcwB,EAC5B,GACD,EAOAI,WAAU,WACTtG,KAAKmF,MAAQvG,EAAK8E,UAAW,SAAUjF,SAAU,0BACjD,IAAM6F,EAAQtE,KAAKmC,QAElBsD,EAAU7G,EAAK8E,UAAW,SACxBjF,SAAU,kDAAA8H,OAAmDvG,KAAKuE,iBAAmBiC,QAEnFlC,EAAMK,kBAEVc,EAAQF,QAASvF,KAAKyE,aAAazG,KAG/BsG,EAAMb,UAEVgC,EAAQ/G,OAAQ4F,EAAMb,UAEvBzD,KAAKhC,IAAIU,OAAQ+G,EAClB,IAGD7H,EAAOC,QAAUqF,C,2CClIjB,IACClB,EAAWrE,EAAS,oCACpBiB,EAAOjB,EAAS,gCAChBgB,EAAOhB,EAAS,gCAQjB,SAAS8I,EAAMtE,GACdxD,EAAKwB,KAAMH,KAAMmC,EAClB,CAEAH,EAAUyE,EAAM9H,EAAM,CAMrByD,UAAS,WACRpC,KAAKmC,QAAQuE,aAAe1G,KAAK2G,gBAClC,EASAC,iBAAgB,WACf,IAAIC,EAAgB,GACpB,GAAK7G,KAAKmC,QAAQ2E,SACjB,OAAS9G,KAAKmC,QAAQ2E,UACrB,KAAM,IACN,KAAK,IACJD,EAAgB,sBAChB,MACD,KAAM,GACLA,EAAgB,gCAChB,MACD,KAAK,GACJA,EAAgB,2BAChB,MACD,KAAK,EACJ,MACD,QACC,MAAM,IAAIE,MAAO,yDAGpB,OAAOF,CACR,EAQAF,eAAc,WACb,IAAMK,EAAOhH,KAAKmC,QAAQ6E,KACpBtE,EAAO1C,KAAKmC,QAAQO,KACpBuE,EAAUjH,KAAKmC,QAAQ8E,QACvBC,EAAkBlH,KAAK4G,mBACvBpH,EAAuBQ,KAAKmC,QAAQ3C,qBAEtC2H,EAAUH,EAAO,IAWrB,OAVKtE,IACJyE,GAAWnH,KAAKoH,oBAAsB,KAElCH,IACJE,GAAW,mBAEP3H,IACJ2H,GAAW3H,EAAuB,KAG5B2H,EAAUD,CAClB,EAMApE,gBAAgB,EAgBhBC,SAAU,CACTiE,KAAM,UACNK,YAAa,KACb3E,KAAM,GACNoE,SAAU,EACVG,SAAS,EACTzH,qBAAsB,MASvB8H,aAAY,WACX,OAAOtH,KAAKhC,IAAIuJ,KAAM,QACvB,EAQAH,kBAAiB,WAChB,OAAKpH,KAAKmC,QAAQkF,YACV,WAAarH,KAAKmC,QAAQkF,YAAc,IAAMrH,KAAKmC,QAAQO,KAE5D,WAAa1C,KAAKmC,QAAQO,IAClC,EAEAhD,SAAUd,EAAKc,SACd,6CAIF9B,EAAOC,QAAU4I,C,iDC3IjB,IACCzE,EAAWrE,EAAS,oCACpBiB,EAAOjB,EAAS,gCAChBgB,EAAOhB,EAAS,gCAChB8I,EAAO9I,EAAS,gCAUjB,SAASsE,EAAYE,GACfA,EAAQ1C,OACZ0C,EAAQhE,QAAU,KAEM,WAApBgE,EAAQhE,UACZgE,EAAQqF,cAAe,GAExB7I,EAAKwB,KAAMH,KAAMmC,EAClB,CAEAH,EAAUC,EAAYtD,EAAM,CAM3ByD,UAAS,WACRpC,KAAKmC,QAAQsF,eAAiBzH,KAAK0H,mBACnC1H,KAAKmC,QAAQwF,UAAY,GACpB3H,KAAKmC,QAAQO,OACjB1C,KAAK4H,MAAQ,IAAInB,EAAM,CACtBO,KAAMhH,KAAKmC,QAAQ6E,KACnBK,YAAarH,KAAKmC,QAAQkF,YAC1B3E,KAAM1C,KAAKmC,QAAQO,KACnBoE,SAAU9G,KAAKmC,QAAQ2E,SACvBG,QAASjH,KAAKmC,QAAQ8E,UAEvBjH,KAAKmC,QAAQwF,UAAY3H,KAAK4H,MAAM5J,IAAIoB,IAAK,GAAIyD,UAEnD,EACA6E,iBAAgB,WACf,IAAMlI,EAAuBQ,KAAKmC,QAAQ3C,qBACpCyD,EAAOjD,KAAKmC,QAAQc,KACpBX,EAAStC,KAAKmC,QAAQG,OACtBD,EAASrC,KAAKmC,QAAQE,OACtBjE,EAAa4B,KAAKmC,QAAQ/D,WAC5B+I,EAAU,cAiBd,MAf8B,WAAzBnH,KAAKmC,QAAQhE,UACjBgJ,GAAW,6DAEPlE,IACJkE,GAAW,oBAAJZ,OAAyBtD,EAAI,MAEhCX,IACJ6E,GAAW,sBAAJZ,OAA2BjE,EAAM,MAEpCD,IACJ8E,GAAW,sBAAJZ,OAA2BlE,EAAM,MAEpCjE,IACJ+I,GAAW,0BAELA,EAAU3H,CAClB,EAMAsD,gBAAgB,EA4BhBC,SAAU,CACT5E,QAAS,SACTsB,UAAMH,EACNE,qBAAsB,GACtBqI,MAAO,GACP5E,KAAM,QACNX,OAAQ,QACRD,OAAQ,GACRjE,YAAY,EACZ4E,UAAU,EACVgE,KAAM,UACNtE,KAAM,GACNoE,SAAU,EACVG,SAAS,GASVK,aAAY,WACX,OAAOtH,KAAKhC,IAAIuJ,KAAM,QACvB,EACAO,QAAO,WACN,OAAO9H,KAAK4H,KACb,EACAlI,SAAUd,EAAKc,SAAS,oWAczB9B,EAAOC,QAAUoE,C,iDChJjB,IACCtD,EAAOhB,EAAS,gCAChBiB,EAAOjB,EAAS,gCASjB,SAASoK,IACRpJ,EAAK4B,MAAOP,KAAMf,UACnB,CAVYtB,EAAS,mCAYrBqE,CAAU+F,EAAYpJ,EAAM,CAM3BmE,gBAAgB,EAWhBC,SAAU,CAAC,EAKXrD,SAAUd,EAAKc,SAAS,yWAgBzB9B,EAAOC,QAAUkK,C,8CCrDjB,IACCpJ,EAAOhB,EAAS,gCAChBqK,EAASrK,EAAAA,mCAAAA,OACTkB,EAASlB,EAAS,kCAClBiB,EAAOjB,EAAS,gCAChBgC,EAAUhC,EAAAA,mCAAAA,eA6BX,SAASsK,EAAS3D,GACjBtE,KAAKiB,MAAQtB,EAAQsB,QAErBtC,EAAKwB,KACJH,KACApB,EAAK6D,QACJ,EACA,CACCyF,cAAc,EACd1D,UAAW,WAEZF,EACA,CACCM,OAAQhG,EAAK6D,OACZ,CAEC,iDAAkD,cAClDwC,MAAO,SAAEF,GAAE,OAAMA,EAAGG,iBAAiB,GAEtCZ,EAAMM,UAKX,CApDYjH,EAAS,mCAsDrBqE,CAAUiG,EAAStJ,EAAM,CACxBe,SAAUd,EAAKc,SAAS,6RAYxByI,YAAa,KASbC,YAAW,WACVpI,KAAKhC,IAAI0H,KAAM,YAAaS,YAAa,SAC1C,EASAkC,YAAW,WACVrI,KAAKhC,IAAI0H,KAAM,YAAajH,SAAU,SACvC,EAOA6H,WAAU,WACT,IAAMgC,EAAetI,KAAKmC,QAAQmG,aAClCtI,KAAKuI,gBAAkBvI,KAAKhC,IAAI0H,KAAM,oBACjC1F,KAAKiB,OACTjB,KAAKhC,IAAIS,SAAU,eAEf6J,GACJtI,KAAKhC,IAAI0H,KAAM,6BAA8BhH,OAAQ,IAAIG,EAAQyJ,GAAetK,KAEjF,IAAMwK,EAAUxI,KAAKmC,QAAQqG,SAAW,CACvCR,EACChI,KAAKmC,QAAQsG,QACbzI,KAAKmC,QAAQuG,gBAGf1I,KAAKhC,IAAI0H,KAAM,6BAA8BhH,OAAQ8J,EACtD,EASAG,YAAW,SAAE5D,GACZ,IAAM6D,EAAO,WACZ5I,KAAK6E,MACN,EAAEC,KAAM9E,MACR+E,EAAGC,iBACHD,EAAGG,kBACElF,KAAKmC,QAAQ0G,aACjB7I,KAAKmC,QAAQ0G,aAAcD,GAAM,WACjC,IAEAA,GAGF,EAOAxD,KAAI,WACH,IAAMvD,EAAQjD,EAAKkD,cAEnB9B,KAAK8I,UAAYrH,OAAOsH,YAExBlH,EAAMpD,SAAU,mBAEhBgD,OAAOuH,SAAU,EAAG,GAEpBhJ,KAAKhC,IAAIS,SAAU,WAIO,OAArBuB,KAAKmI,cACTc,aAAcjJ,KAAKmI,aACnBnI,KAAKmI,YAAc,KAErB,EAUAtD,KAAI,WAAG,IAAAqB,EAAA,KAoBN,OAnBAtH,EAAKkD,cAAcqE,YAAa,mBAEhC1E,OAAOuH,SAAUvH,OAAOyH,YAAalJ,KAAK8I,WAK1C9I,KAAKmI,YAAc/B,YAAY,WAC9BF,EAAKlI,IAAIqI,SACTH,EAAKiC,YAAc,IACpB,GAAG,GAOHnI,KAAKmJ,KAAM,SAEJ,CACR,EAaAC,WAAU,SAAE5E,GACXxE,KAAKhC,IAAI0H,KAAM,aAAcjH,SAAU,UACvCuB,KAAKhC,IAAI0H,KAAMlB,GAAY2B,YAAa,SACzC,IAaD8B,EAAQoB,KAAO,SAAWlH,EAASmH,GAClC,IAAMC,EAAU,IAAItB,EAAS9F,GAE7B,OADAoH,EAAQvL,IAAI0H,KAAM,oBAAqBhH,OAAQ4K,EAAKtL,KAC7CuL,CACR,EAEA3L,EAAOC,QAAUoK,C,qDCtOjB,IAAMrJ,EAAOjB,EAAS,gCAElB6L,EAAiB,KAKfC,EAAgB,0CAatB,SAASC,EAAgBC,EAAQC,GAChCD,EAAOE,GAAI,QAAS7J,KAAK8J,YAAYhF,KAAM9E,OAC3CA,KAAK2J,OAASA,EAGd3J,KAAK+J,QAAU,CAAC,EAEhB/J,KAAKgK,MAAQ,GACbhK,KAAKiK,aAAc,EAEnBjK,KAAK4J,UAAYA,CAClB,CAQA,SAASM,EAAiBX,GACzBA,EAAQM,GAAI,QAAQ,kBAAMN,EAAQJ,KAAM,WAAY,GACrD,CAEAO,EAAerJ,UAAY,CAY1B8J,oCAAmC,WAClC,GAAMnK,KAAKgK,MAAM5G,OAAjB,CAGA,IAAMgH,EAAepK,KAAKgK,MAAM,GAAGK,MAClCC,EAAwC,iBAAjBF,EACvBG,EAAcvK,KAAK2J,OAAOa,UAG1BC,EAAgBH,GAAiBC,IAAgBH,GAChDG,EAAYG,MAAON,GAErBpK,KAAKiK,aAAc,EAKdQ,GAEJzK,KAAK2J,OAAOgB,MAhBb,CAkBD,EAUAC,eAAc,SAAErB,GACTA,EAAQvL,IAAI6M,UAAUzH,QAC3BpD,KAAK4J,UAAUkB,YAAavB,EAAQvL,IAAI,GAE1C,EASA+M,MAAK,SAAExB,GAIN9H,OAAOuJ,QAAQC,aAAcxB,EAAe,KAAMhI,OAAOyJ,SAASzL,MAMlE8J,EAAQ4B,KAAM,WAAYnL,KAAKmK,oCAAoCrF,KAAM9E,OAEzEA,KAAK4K,eAAgBrB,GACrBA,EAAQnE,MACT,EAYAgG,aAAY,SAAE7B,EAAS8B,GACtB,IAAIC,EAEJ,SAAS1C,IACR0C,GAAS,EACT/B,EAAQ1E,MACT,CAiBA,OAbA0E,EAAQgC,IAAK,YAERhC,EAAQpH,SAAWoH,EAAQpH,QAAQ0G,aACvCU,EAAQpH,QAAQ0G,aAAcD,EAAMyC,GAEpCzC,IAIK0C,GACL/B,EAAQ4B,KAAM,WAAYnL,KAAKmK,oCAAoCrF,KAAM9E,OAGnEsL,CACR,EAUAE,cAAa,SAAEd,GAGd,GAAKA,EACJ,GAAKA,EAAMnB,QAHCvJ,KAKN+K,MAAOL,EAAMnB,aACZ,CAEN,IAAMkC,EAAgBf,EAAMe,cAIvBA,IACJf,EAAMnB,QAAUkC,EAChBvB,EAAiBQ,EAAMnB,SAdbvJ,KAeL+K,MAAOU,GAEd,CAEF,EAUA3B,YAAW,SAAE/E,GAAK,IAAAmB,EAAA,KACXwF,EAAU1L,KAAKgK,MAAM,GAa3B,GALM0B,IACL1L,KAAK8I,UAAYrH,OAAOsH,cAKxB2C,QACoBpM,IAApBoM,EAAQnC,UACRvJ,KAAKiK,aACJjK,KAAKoL,aAAcM,EAAQnC,SAAS,WAEpCxE,EAAGC,gBACJ,IAPD,CAYA,IAAM0F,EAAQtK,OAAOuL,KAAM3L,KAAK+J,SAAU6B,QAAQ,SAAEC,EAAGC,GAAE,OAAMD,GAC9D3F,EAAK6F,YAAahH,EAAGiH,KAAM9F,EAAK6D,QAAQ+B,GAAK,GAAE,MAE1CpB,IAEL1K,KAAKgK,MAAQ,GAEbvI,OAAOuH,SAAUvH,OAAOyH,YAAalJ,KAAK8I,YAG3C9I,KAAKiK,aAAc,EACnBjK,KAAKwL,cAAed,EAbpB,CAcD,EAcAqB,YAAW,SAAEC,EAAMC,GAClB,IACCC,EACAC,EACAzB,EAGA0B,EAAWpM,KAAKgK,MAAM,GACtBqC,EAAOrM,KA4BR,GA1B4B,iBAAhBiM,EAAM5B,OACjB6B,EAAWD,EAAM5B,QAAU2B,EAC3BG,EAAW,IAIXA,GADAD,KADAxB,EAAQsB,EAAKtB,MAAOuB,EAAM5B,SAEJK,EAAM4B,MAAO,GAAM,GAoBrCJ,EAAW,CAGf,GAAKE,GAAYA,EAASJ,OAASA,EAElC,OADAK,EAAKrC,MAAMuC,QACJH,EAEP,IAAMI,EAhBA,CACNR,KAAAA,EAGA3B,MAAO4B,EAAM5B,MACboB,cAAeQ,EAAMQ,QAAQlM,MAAO8L,EAAMF,IAoB1C,OARKnM,KAAKgK,MAAM,IAAMwC,EAAKR,OAAShM,KAAKgK,MAAM,GAAGgC,KAIjDK,EAAKrC,MAAM,GAAKwC,EAEhBH,EAAKrC,MAAM0C,QAASF,GAEdA,CAET,CAEA,OAAO,IACR,EA6CAG,IAAG,SAAEtC,EAAOoC,GACX,IAAMJ,EAAOrM,KACZiM,EAAQ,CACP5B,MAAAA,EACAoC,QAAAA,GAGFzM,KAAK+J,QAAQM,GAAS4B,EAGtBrN,EAAKgO,UAAU,kBAAMP,EAAKb,cAAea,EAAKN,YAAaM,EAAK1C,OAAOa,UACtEyB,GAAS,GACX,EAWAY,eAAc,SAAEtD,GACf,GAA2B,IAAtBvJ,KAAKgK,MAAM5G,OACf,MAAM,IAAI2D,MAAO,0EAElB,IAAM+F,EAAe9M,KAAKgK,MAAM,GAAGT,QAC9BuD,GACJ9M,KAAKoL,aAAc0B,GAEpB9M,KAAKgK,MAAM,GAAGT,QAAUA,EACxBW,EAAiBX,GACjBvJ,KAAK+K,MAAOxB,EACb,GASDG,EAAe9H,aAAe,WAC7B,IAAM4H,EAAiB,CACtB,IACCG,EAASoD,QAAyB,oBAClCnD,EAAYoD,SAASC,cAAe,OAEpCC,EAAOvD,EAAOa,UAEd2C,EAAQ1L,OAAOuJ,QAAQmC,MACxBvD,EAAUpF,UAAY,wBACtBwI,SAASI,KAAKtC,YAAalB,GAKtBsD,GAAQC,IAAU1D,IAEtBhI,OAAOuJ,QAAQC,aAAc,KAAM,KAAM,KAEzCxJ,OAAOuJ,QAAQqC,UAAW5D,EAAe,KAAM,IAAFlD,OAAO2G,KAErD1D,EAAiB,IAAIE,EAAgBC,EAAQC,EAC9C,CACA,OAAOJ,CACR,EAEAE,EAAetI,KAAO,CACrBqI,cAAAA,EACA6D,aAAc,WACb9D,EAAiB,IAClB,GAED5L,EAAOC,QAAU6L,C,6sBClajB,IACC6D,EAAOjP,GAAGkP,KACV5O,EAAOjB,EAAS,gCAEX8P,EAAI,wBA6DT,O,EA7BA,SAAAA,EAAatL,I,4FAAUpD,CAAA,KAAA0O,GACtB,IAAM5F,EAAQ1F,EAAQ0F,OAAS,GAC/BjJ,EAAK6D,OAAQzC,KAAM,CAClB8L,GAAI3J,EAAQ2J,IAAM,EAGlBjE,MAAAA,EACA6F,cAAevL,EAAQuL,eAAiB7F,EACxC8F,SAAUxL,EAAQwL,SAClBC,aAAczL,EAAQyL,cAAgBL,EAAKM,OAAQhG,GACnDiG,gBAAiB3L,EAAQ2L,iBAAmB,EAC5CC,WAAY5L,EAAQ4L,WACpBC,IAAK7L,EAAQ6L,KAAO1P,GAAGM,KAAKiF,OAAQgE,GACpCoG,oBAAqB9L,EAAQ8L,oBAC7BC,YAAa/L,EAAQgM,aAAc,EACnCC,eAAmC9O,IAAtB6C,EAAQiM,UACpBjM,EAAQiM,UAA2B,IAAfjM,EAAQ2J,GAC7BuC,OAAQlM,EAAQkM,OAChBC,MAAOnM,EAAQmM,MACfC,WAAYpM,EAAQqM,UACpBC,YAAarO,OAAOC,UAAUC,eAAeH,KAAMgC,EAAS,cAC3DA,EAAQsM,YAGLzO,KAAKyO,WAAazO,KAAKyO,UAAUjJ,QACrCxF,KAAKyO,UAAUC,YAAc1O,KAAKyO,UAAUjJ,MAAQxF,KAAKyO,UAAUE,OAErE,G,EAEA,EAAAxP,IAAA,kBAAAyP,MAMA,WACC,OAAO5O,KAAK4N,YACb,GAEA,CAAAzO,IAAA,cAAAyP,MAOA,SAAaC,GACZ,OAAO7O,KAAK8N,kBAAoBxP,GAAGkD,OAAOpC,IAAK,kBAAmByP,EACnE,GAEA,CAAA1P,IAAA,aAAAyP,MAMA,WACC,MAAiD,aAA1CtQ,GAAGkD,OAAOpC,IAAK,qBACvB,GAEA,CAAAD,IAAA,gBAAAyP,MAMA,WACC,QAAStQ,GAAGkD,OAAOpC,IAAK,0BACtBd,GAAGkD,OAAOpC,IAAK,iCAChBY,KAAK8O,YACP,GAEA,CAAA3P,IAAA,sBAAAyP,MAMA,WACC,QAAM5O,KAAK+O,kBAMwE,KAHpEzQ,GAAGkD,OAAOpC,IAAK,wBACQ4P,YAAc,IAEtBC,QAAS3Q,GAAGkD,OAAOpC,IAAK,qBACvD,GAEA,CAAAD,IAAA,sBAAAyP,MAMA,WACC,OAAO5O,KAAK+O,iBACXzQ,GAAGkD,OAAOpC,IAAK,6BACjB,GAEA,CAAAD,IAAA,aAAAyP,MAMA,WACC,OAAO5O,KAAKkO,WACb,GAEA,CAAA/O,IAAA,YAAAyP,MAMA,WACC,OAAO5O,KAAKuO,UACb,GAEA,CAAApP,IAAA,gBAAAyP,MAMA,WACC,OAAO5O,KAAKsO,KACb,GAEA,CAAAnP,IAAA,WAAAyP,MAMA,WACC,OAAO5O,KAAK6H,KACb,GAEA,CAAA1I,IAAA,iBAAAyP,MAMA,WACC,IACMM,EAAOlP,KAAK6H,MAAMsH,MAAO,KAO/B,OALKD,EAAK,IACF5Q,GAAGkD,OAAOpC,IAAK,kBAAoB8P,EAAK,GAAGE,cAAcC,QAAS,IAAK,OAEvE,CAGT,M,6EAAC,CA3LQ,GA8LVzR,EAAOC,QAAU4P,C,utBClMjB,IACC6B,EAAY3R,EAAS,qCACrB4R,EAAmBjR,GAAGkD,OAAOpC,IAAK,8BAA+B,CAAE,KAAM,KAAM,KAAM,KAAM,OAASc,KAAM,KAC1GsP,EAAoC,CAAE,WAAY,YAClDC,EAAgBD,EAAkCE,KAAK,SAAEC,GAAe,eAAApJ,OAAgBoJ,EAAe,QAAOzP,KAAM,IACpH0P,EAAiB,CAAE,UAAW,uCAAwCF,KACrE,SAAEG,GAAQ,SAAAtJ,OAAUsJ,GAAQtJ,OAAKkJ,EAAa,IAC7CvP,KAAM,KAEH4P,EAAc,wBAgBnB,O,EARA,SAAAA,EAAa/O,I,4FAAahC,CAAA,KAAA+Q,GACzB9P,KAAKhC,IAAM+C,EAIXf,KAAK+P,UAAY/P,KAAKhC,IAAI0H,KAAM6J,EACjC,G,EAEA,EAAApQ,IAAA,4BAAAyP,MAaA,SAA2BoB,GAC1B,OAAKA,EAAe,EAIZxR,EAAG,IAEHwB,KAAK+P,UAIVE,OAAQ,qDAAsDC,GAAIF,EAAe,EAErF,GAEA,CAAA7Q,IAAA,yBAAAyP,MAmBA,SAAwBoB,EAAcH,GACrC,IAAIM,EAAUC,EAERC,EAAkBd,EAExB,SAASe,EAAoBC,GAC5B,OAAOA,EAAe7K,KAAMmK,GAAWW,SACxC,CAEA,GAAsB,IAAjBR,EAAqB,CAEzB,IAAMS,EAAQzQ,KAAK0Q,wBACnB,GAAKD,GAASA,EAAMrN,OAAS,CAG5B,IAAMuN,EAAiBF,EAAM/K,KAAM,mCACnC,OAAKiL,EAAevN,OACZkN,EAAoBK,EAAelN,SAAUoM,IAG9CS,EAAoBG,EAAMhN,SAAUoM,GAC5C,CAEC,OADAM,EAAWnQ,KAAK4Q,0BAA2B,IAC3BxN,OAASkN,EAAoBH,EAASU,QAAShB,IAE9D7P,KAAKhC,IAAI0H,KAAMmK,EAElB,CAYA,IALAM,EAAWnQ,KAAK4Q,0BAA2BZ,IAK7BrK,SAAU,mBAAsB,CAE7C,IAAM3H,EAAMmS,EAAS3D,OAGrB,OADA4D,EAAepS,EAAI0H,KAAM2K,GAAkBH,GAAI,IAC3B9M,OAEnBkN,EAAoBF,EAAaS,QAAShB,IAG1CS,EAAoBtS,EAAIyF,SAAUoM,GACpC,CAIC,OADAO,EAAeD,EAASD,GAAI,GAAIY,QAAST,GAAkBH,GAAI,GACxDC,EAASY,UAAWX,EAAcP,EAE3C,GAEA,CAAA1Q,IAAA,wBAAAyP,MAMA,WAYC,IAAMoC,EAAehR,KAAKhC,IAAI0H,KAAM,iBAEpC,OAAKsL,EAAa5N,OACV4N,EAGD,IACR,GAEA,CAAA7R,IAAA,eAAAyP,MAQA,SAAcqC,GACb,IAAMC,EAAc,IAAM1B,EAAkCtP,KAAM,MACjEiR,EAAaF,EAAGvL,KAAM,2BACtBjG,EAAOwR,EAAG1J,KAAM,QAChByG,EAAMvO,GAAQ,IAAI2R,IAAK3R,EAAMyL,SAASzL,MACtC4R,EAAcrD,GAAOA,EAAIsD,aAAalS,IAAK,SAC3CsL,EAAQsD,GAAOA,EAAIuD,SAAS7G,MAAO,UAGhC8G,EAA6C,IAArCP,EAAGpG,QAASqG,GAAc9N,QACH,IAAlC6N,EAAGvL,KAAMwL,GAAc9N,OAUxB,OAPK+N,EAAW/N,QAAUoO,IAGzBA,GAAS,IAAIC,OAAQ,OAASjC,EAAkCtP,KAAM,KAAQ,QAC5EkB,KAAM+P,EAAWO,KAAM,WAGrBF,IAA2B,OAAhBH,GAAwB3G,GAChC,IAAI4E,EAAW,CACrBqC,GAAIV,EACJW,SAAUtT,GAAGM,KAAKiT,sBACD,OAAhBR,EAAuBA,EAAc3G,EAAM,MAKvC,IACR,GAEA,CAAAvL,IAAA,gBAAAyP,MAcA,SAAe5Q,GACd,IACCqO,EAAOrM,KACP8R,EAAS,GAcV,OAZA9T,EAAMA,GAAOgC,KAAKhC,KAEE0H,KAAMkK,GAElBmC,MAAM,WACb,IAAMd,EAAKjT,EAAI0H,KAAM1F,MACfgS,EAAQ3F,EAAK4F,aAAchB,GAE5Be,GACJF,EAAO1N,KAAM4N,EAEf,IACOF,CACR,GAEA,CAAA3S,IAAA,cAAAyP,MAMA,WACC,OAAO5O,KAAKhC,IAAI0H,KAAM,OACvB,GAEA,CAAAvG,IAAA,eAAAyP,MASA,SAAcsD,GACb,IAAMC,EAAuB,SAAEC,GAC9B,IAKIC,EALEC,EAAY,MAEZC,EAAUH,EAAKI,YAIjB3K,EAAQuK,EAAKK,aAAc,UAAaP,EAS5C,OARKrK,EAAMoH,QAASqD,IAAe,IAElCD,GADAxK,EAAQA,EAAMsH,MAAOmD,IACJI,MACjB7K,EAAQA,EAAM3H,KAAMoS,IAEfD,IACLA,EAAWE,GAEL,CACNI,KAAMP,EAAKK,aAAc,YACzBF,QAAAA,EACAF,SAAAA,EACAxK,MAAAA,EACAmG,IAAKoE,EAAKK,aAAc,QAE1B,EACA,MAAO,CACNG,UAAWC,MAAMxS,UAAUqP,IAAIvP,KAC9B6M,SAAS8F,iBAAkB,iCAC3BX,GAEDY,SAAUF,MAAMxS,UAAUqP,IAAIvP,KAC7B6M,SAAS8F,iBAAkB,oBAC3BX,GAGH,M,6EAAC,CApRkB,GA4RpBrC,EAAeP,iBAAmBA,EAOlCO,EAAeF,eAAiBA,EAEhChS,EAAOC,QAAUiS,C,+CC9SjB,IAAMlR,EAAOjB,EAAS,gCACrBqE,EAAWrE,EAAS,oCACpBgB,EAAOhB,EAAS,gCAChBgC,EAAUhC,EAAAA,mCAAAA,eAQX,SAASqV,IACRrU,EAAK4B,MAAOP,KAAMf,UACnB,CAEA+C,EAAUgR,EAAUrU,EAAM,CAyBzBoE,SAAU,CACTkQ,MAAO,IAQRC,iBAAgB,WACf,IAAM7G,EAAOrM,KAEboG,YAAY,WACXiG,EAAKrO,IAAI0H,KAAM,eAAgBqM,MAAM,WACpC,IAAMoB,EAAQ9G,EAAKrO,IAAI0H,KAAM1F,MAAO0R,KAAM,SAC1CrF,EAAKrO,IAAI0H,KAAM1F,MAAOuH,KAAM,QAAS4L,EACtC,GAGD,GAAGxT,EAAQ0B,eAAiB,EAAI,IACjC,EAMAiF,WAAU,WACTtG,KAAKkT,kBACN,EACAxT,SAAUd,EAAKc,SAAS,0GAWxB0T,iBAAkB,CAIjBC,KAAMzU,EAAKc,SAAS,y4BAyBtB9B,EAAOC,QAAUmV,C,2CC7GjB,IAOIM,EAPE3T,EAAUhC,EAAAA,mCAAAA,eACfgB,EAAOhB,EAAS,gCAChBiB,EAAOjB,EAAS,gCAChB4V,EAAc5V,EAAS,uCACvB6V,EAAW7V,EAAS,6CAkBrB,SAAS8V,EAAMpQ,GACd,IAAMlB,EAAUvD,EAAK6D,OAAQ,CAAC,EAAGY,GAEjCrD,KAAK0T,KAAOvR,EAAQuR,KACpB1T,KAAK2T,KAAOxR,EAAQwR,KACpB3T,KAAKwT,SAAWrR,EAAQqR,SACxBrR,EAAQyR,aAAc,EACtBjV,EAAKwB,KAAMH,KAAMmC,EAClB,CAzBYxE,EAAS,mCA2BrBqE,CAAUyR,EAAM9U,EAAM,CAQrBoE,SAAU,CACT2Q,UAAMpU,GAQPgH,WAAU,WAAG,IAAAJ,EAAA,KACNlI,EAAMgC,KAAKhC,IAEZ2B,EAAQgC,uBACZ3D,EAAIS,SAAU,gBAQfuB,KAAKhC,IAAI0H,KAAM,sBAAuBmE,GAAI,SAAS,SAAE9E,GACpDmB,EAAKiD,KAAM,QAASpE,EACrB,GACD,EAOA8O,gBAAe,WACd,IAAMC,EAAgBxV,GAAGyV,QAAS,iCAC5BC,EAAkBF,EAAcG,UAAYH,EAAcnQ,OAEhE,MAAsB,QADDrF,GAAGkD,OAAOpC,IAAK,mBAK5B4U,EAFAF,EAAcI,WAE+BlU,KAAKhC,IAAI0H,KAAM,4BAA6ByO,OAElG,EASAC,cAAa,WACZ,IAEIC,EAFEC,EAAgBtU,KAAK6T,kBAG3B,GAAKS,EAAclR,OAAS,CAC3B,IAAMmR,EAAgBjW,GAAGkW,SAASC,cACjCH,EAAcrE,OAAQ,KAAM7M,QAG7B,GAAKpD,KAAKhC,IAAI0H,KAAM,4BAA6BtC,OAAS,EAAI,CAE7D,IAAMsR,EAAapW,GAAGyV,QACrB,oCACA/T,KAAKhC,IAAI0H,KAAM,8BAA+B6B,KAAM,SACnD2M,WACFG,EAAa/V,GAAGyV,QACf,8CACAW,EACAJ,EACAC,GACCI,OACH,MACCN,EAAa/V,GAAGyV,QACf,mCACAO,EACAC,GACCI,OAEJ,CAEA,OAAON,CACR,IAQDZ,EAAK7R,aAAe,WAQnB,OAPM0R,IACLA,EAAO,IAAIG,EAAM,CAChB9B,GAAI,OACJ+B,KAAMH,IACNC,SAAAA,KAGKF,CACR,EACA1V,EAAOC,QAAU4V,C,gDC3IjB,IACCzR,EAAWrE,EAAS,oCACpBiB,EAAOjB,EAAS,gCAChBgB,EAAOhB,EAAS,gCASjB,SAAS2R,EAAWnN,GACnBxD,EAAKwB,KAAMH,KACVpB,EAAK6D,OAAQ,CAAEmR,aAAa,GAASzR,GAEvC,CAEAH,EAAUsN,EAAW3Q,EAAM,CAS1BoE,SAAU,CACT6O,cAAUtS,GAOXgH,WAAU,WACTtG,KAAKmC,QAAQyS,YAAc5U,KAAKhC,IAAI6W,SAAU,6BAC5CC,KAAM,cAAiB,EAC1B,EAQAC,eAAc,WACb,OAAO/U,KAAKmC,QAAQyS,WACrB,EAQAI,YAAW,WACV,OAAOhV,KAAKmC,QAAQyP,QACrB,IAGDhU,EAAOC,QAAUyR,C,2CC5DjB,IAAM1Q,EAAOjB,EAAS,gCACrBqE,EAAWrE,EAAS,oCAEpBsX,EAAwB,iBAErBC,EAAY,EA+FhB,SAASvW,IACRqB,KAAKmV,WAAW5U,MAAOP,KAAMf,UAC9B,CACAmW,GAAGC,WAAY1W,EAAMyW,GAAGE,cACxBtT,EAAUrD,EAAM,CAQfR,QAAS,MAST2E,gBAAgB,EAOhBpD,cAAUJ,EAoBV8T,iBAAkB,CAAC,EAenBrQ,SAAU,CAAC,EAUXoS,WAAU,SAAEhT,GACX,IA/JiBoT,EACZzJ,EA8JCO,EAAOrM,KAEboV,GAAGE,aAAanV,KAAMH,MACtBmC,EAAUvD,EAAK6D,OAAQ,CAAC,EAAGzC,KAAK+C,SAAUZ,GAC1CnC,KAAKmC,QAAUA,EAEfnC,KAAKwV,KArKYD,EAqKI,OApKhBzJ,KAASoJ,GAAYxU,WACpB6U,EAASA,EAASzJ,EAAKA,GAwKC,iBAAlB9L,KAAKN,WAChBM,KAAKN,SAAWpB,GAAGoB,SAAS+V,QAASzV,KAAKN,WAGtCyC,EAAQwP,GAEZ3R,KAAKhC,IAAMQ,EAAG2D,EAAQwP,IAEtB3R,KAAKhC,IAAMgC,KAAK0D,UAAW,IAAM1D,KAAK7B,QAAU,KAI5C6B,KAAKhC,IAAIoF,OACbpD,KAAK0V,gBAAiBvT,GAEtBvD,EAAKgO,UAAU,WAEdP,EAAKrO,IAAMQ,EAAG2D,EAAQwP,IACtBtF,EAAKqJ,gBAAiBvT,EACvB,GAEF,EAUAuT,gBAAe,SAAEpR,GAEhBtE,KAAKhC,IAAIS,SAAU6F,EAAME,YAEE,IAAtBF,EAAMsP,aACV5T,KAAKhC,IAAIS,SAAU,mBAGpBuB,KAAK2V,OAAQ,CAAC,EACf,EASAvT,UAAS,WACT,EASAkE,WAAU,WACV,EAWAqP,OAAM,SAAEjE,GACP,IAAI1T,EAAKwP,EAgBT,OAfA5O,EAAK6D,OAAQzC,KAAKmC,QAASuP,GAC3B1R,KAAKoC,YACLpC,KAAK4V,mBACA5V,KAAKN,WAAaM,KAAKmC,QAAQ0T,qBACnCrI,EAAOxN,KAAKN,SAASiW,OAAQ3V,KAAKmC,QAASnC,KAAKoT,kBAC3CpT,KAAK8C,gBACT9E,EAAMQ,EAAGgP,GACTxN,KAAKhC,IAAI8X,YAAa9X,GACtBgC,KAAKhC,IAAMA,GAEXgC,KAAKhC,IAAIwP,KAAMA,IAGjBxN,KAAKsG,aACLtG,KAAK+V,iBACE/V,IACR,EAyBA+V,eAAc,SAAEnR,GACf,IAAI8F,EAAOvL,EAAKU,EAEhB,GADA+E,EAASA,GAAU5E,KAAKmC,QAAQyC,OAI/B,IAAMzF,KADNa,KAAK4V,mBACQhR,EAGW,mBAFvB/E,EAAS+E,EAAOzF,MAGfU,EAASG,KAAK4E,EAAOzF,KAEjBU,IAEJ6K,EAAQvL,EAAIuL,MAAOuK,GACnBjV,KAAKgW,SAAUtL,EAAM,GAAIA,EAAM,GAAI7K,EAAOiF,KAAM9E,OAIpD,EAaAgW,SAAQ,SAAEC,EAAWpG,EAAUqG,GAC9BlW,KAAKhC,IAAI6L,GAAIoM,EAAY,kBAAoBjW,KAAKwV,IAAK3F,EACtDqG,EACF,EAUAN,iBAAgB,WACV5V,KAAKhC,KACTgC,KAAKhC,IAAIuN,IAAK,kBAAoBvL,KAAKwV,IAEzC,EAYAW,WAAU,SAAEF,EAAWpG,EAAUqG,GAChClW,KAAKhC,IAAIuN,IAAK0K,EAAY,kBAAoBjW,KAAKwV,IAAK3F,EACvDqG,EACF,EAUAxS,UAAS,SAAE8J,GAIV,OAAO5O,EAAK8E,UAAW8J,EAAMR,SAC9B,IAyHD,CACC,SACA,UACA,WACA,YACA,QACA,SACA,cACA,eACA,SACA,UACCoJ,SAAS,SAAEtB,GACZnW,EAAK0B,UAAUyU,GAAQ,WAEtB,OADA9U,KAAKhC,IAAI8W,GAAMvU,MAAOP,KAAKhC,IAAKiB,WACzBe,IACR,CACD,IASArB,EAAK0K,KAAO,WAAyC,IAAhB5F,EAAQxE,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,GACzCqK,EAAO,IAAI3K,EADYM,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,GAGjC,OADAwE,EAAS2S,SAAS,SAAEC,GAAM,OAAM/M,EAAK5K,OAAQ2X,EAAQ,IAC9C/M,CACR,EAEA1L,EAAOC,QAAUc,C,mDCnhBjB,IAAMC,EAAOjB,EAAS,gCACrB2Y,EAAgB,CACfjU,OAAQ,QACRkU,cAAe,GAUjB3Y,EAAOC,QAAU,SAAuB2Y,GACvC,IAAMC,EAAanY,GAAGkD,OAAOpC,IAAK,kBAClC,OAAOR,EAAK6D,OAAQ,CAAC,EAAG6T,EAAe,CACtCI,OAAQD,EAAa,SAAMnX,GACzBkX,EACJ,C,4/CClBA,IACCtU,EAASvE,EAAS,kCAClBiB,EAAOjB,EAAS,gCAqBXgZ,EAAa,SAAA7X,GAAA,sBAAA6X,IAAA,O,4FAAA5X,CAAA,KAAA4X,GAAA3X,EAAA,KAAA2X,EAAA1X,UAAA,Q,qRAAAC,CAAAyX,EAAA7X,G,EAAA6X,G,EAAA,EAAAxX,IAAA,iBAAAC,IAElB,WACC,OAAO,CACR,GAEA,CAAAD,IAAA,WAAAC,IACA,WACC,OAAOR,EAAKc,SAAS,gLAOtB,GAEA,CAAAP,IAAA,aAAAyP,MACA,WACC5O,KAAKhC,IAAIU,OACR,IAAIwD,EAAQ,CACX/D,QAAS,SACTkB,aAAa,EACbhB,MAAO2B,KAAKmC,QAAQyU,cACjB5Y,IAEN,M,6EAAC,CA1BiB,CApBXL,EAAS,iCAiDjBC,EAAOC,QAAU8Y,C,8DC1CjB,IA0BIE,EAzBHC,EAAQnZ,EAAS,4CACjBoZ,EAAsBpZ,EAAS,uDAC/BqZ,EAAoBrZ,EAAS,yDAe7BsZ,EAAU,CACTC,cAAe,gBACfC,cAAe,gBACfC,WAAY,cAYdxZ,EAAOC,QAAU,CAMhBwZ,aAAc,WACb,OAAKR,IAILA,EAAWE,GAkBV,SAAE1U,EAAQqC,EAAc4S,EAAeC,GACtC,OAAOP,EACN3U,EACAwU,EACAvY,GAAGyV,QACHzV,GAAGM,KACHkY,EACAxY,GAAGkZ,KAAKC,OAAOrY,IAAK,aACpBsF,EACA4S,EACAC,EAEF,GACAN,EApDc,iBAuDZ3Y,GAAGkD,OAAOpC,IAxEmB,2BAyE7Bd,GAAGkD,OAAOpC,IAxEiB,+BAyE7Bd,GAAGoZ,SAIL,EAIAT,QAAAA,E,oEClGD,IACC/T,EAASvF,EAAS,kCAClBkB,EAASlB,EAAS,kCAClBiB,EAAOjB,EAAS,gCAChBgZ,EAAgBhZ,EAAS,qDA6B1BC,EAAOC,QAAU,SAChBwE,EACAsV,EACAC,EACAC,EACAf,EACAgB,EACApT,EACA4S,EACAC,GAEA,OAAO,IAAIrU,EAAQ,CAClBsB,UAAW,sBACXf,SAAU,CACT7E,EAAK8E,UAAW,SAAUjF,SAAU,sBACpCG,EAAK8E,UAAW,OAAQhF,OACvBE,EAAK8E,UAAW,YAAaC,KAC5BiU,EAAW,sCAAuCjU,SAGpD/E,EAAK8E,UAAW,OAAQC,KACvBiU,EAAW,4CAA6CjU,QAEzD,IAAIgT,EAAe,CAClBoB,QAASF,EAAOhU,OAAQ,wBAAyB,CAChDM,SAAUmT,EACVU,cAAeT,GAAiB,KAEjCU,OAAQ,CACP,CACCtE,KAAM,qBACN/E,MA1DmB,aA4DpB,CACC+E,KAAM,YACN/E,MA7DoB,KA+DrB,CACC+E,KAAM,QACN/E,MAAOkJ,IAGTlB,YAAagB,EAAW,uCAAwCjU,OAChEiB,OAAQ,CACPsT,OAAQ,WACPP,EAAcQ,qBAAsB9V,GACpCyU,EAAMsB,iBAAkBR,EAAW,gDAAiDjU,OACrF,KAEE3F,IACJ,IAAIa,EAAQ,CACXY,KAAM,IACND,qBAAsB,SACtBH,aAAa,EACbhB,MAAOuZ,EAAW,0CAA2CjU,SAC1D3F,KAEL0G,aAAc,WACbiT,EAAcQ,qBAAsB9V,GACpCqC,GACD,GAEF,C,kDC9FA,IAGIgP,EAFHjG,EAAO9P,EAAS,gCA4CjBC,EAAOC,QA/BP,WACC,GAAK6V,EACJ,OAAOA,EAGR,IAAM2E,EAAc,GAAG9R,OAAQjI,GAAGkD,OAAOpC,IAAK,oBAAqB,KAClEsO,EAAgBpP,GAAGga,MAAMC,YAAaja,GAAGkD,OAAOpC,IAAK,uBACrDyI,EAAQvJ,GAAGga,MAAMC,YAAaja,GAAGkD,OAAOpC,IAAK,eAqB9C,OAnB4B,IAAvBiZ,EAAYjV,QAChBiV,EAAYjU,KAAM,KAGnBsP,EAAO,IAAIjG,EAAM,CAChB5F,MAAOA,EAAM2Q,kBACb7K,SAAU9F,EACV6F,cAAeA,EAAc8K,kBAC7BzK,WAAY,CACX0K,KAAMJ,GAEP/J,MAAOhQ,GAAGkD,OAAOpC,IAAK,gBACtB+O,WAAY7P,GAAGkD,OAAOpC,IAAK,gBAC3BoP,UAAWhQ,EAAG,aAAcmH,SAAU,WACtCyI,UAA8C,IAAnC9P,GAAGkD,OAAOpC,IAAK,eAC1B0M,GAAIxN,GAAGkD,OAAOpC,IAAK,eACnB0O,gBAAiBxP,GAAGkD,OAAOpC,IAAK,sBAIlC,C,4DC3CA,IAGIsZ,EAFH5I,EAAiBnS,EAAS,0CAwB3BC,EAAOC,QAVP,WACC,OAAK6a,IAILA,EAAiB,IAAI5I,EAAgBtR,EAAG,0BAGzC,C,kDCPAZ,EAAOC,QAAU,IAAIuX,GAAGE,Y,yDCjBxB,IAAM1W,EAAOjB,EAAS,gCACrBgb,EAAehb,EAAS,wCAyBzBC,EAAOC,QAAU,SAA6B+a,GAC7C,IAAMC,EAA8Bva,GAAGkD,OAAOpC,IAAK,oCAAuC,CAGxF0Z,QAAQ,EACRC,WAAW,EACXC,SAAS,GAEVvC,EAAanY,GAAGkD,OAAOpC,IAAK,kBAE7B,IAAMgB,OAAOC,UAAUC,eAAeH,KAAM0Y,EAA6BD,GACxE,MAAM,IAAI7R,MAAO,IAAM6R,EAAU,wDAYlC,IAAM1J,EAAO2D,MAAMxS,UAAUiM,MAAMnM,KAAMlB,UAAW,GACpDiQ,EAAKxC,QAAS,CACboI,KAAM,KAEP5F,EAAK9K,KAAM9F,GAAGkD,OAAOpC,IAAK,wBAE1B,IAAMkM,EAAS1M,EAAK6D,OAAOlC,MAAO,CAAC,EAAG2O,GAatC,OAZA5D,EAAOwJ,KAAOxJ,EAAOwJ,KAAKvO,OAAQjI,GAAGkD,OAAOpC,IAAK,yBAE5CyZ,EAA4BD,KACe,IAA1CtN,EAAOwJ,KAAK7F,QAAS,gBACzB3D,EAAOwJ,KAAK1Q,KAAM,eAIfqS,IAEJnL,EAAOoL,OAAS,KAEViC,EAAcrN,EACtB,C,8CCrEA,IAAM1M,EAAOjB,EAAS,gCACrBuE,EAASvE,EAAS,kCAClBD,EAAQC,EAAS,iCAYlB,SAASsb,EAAYC,EAAexQ,EAAeyQ,EAAc3Z,GAChE,IAAMiJ,EAAmC,iBAAlByQ,EAA6BA,OAAgB5Z,EACnE8Z,EAAe,CACdC,WAAY3Q,GAAiBA,EAActF,OAC3CkW,UAAU,EACV7Q,QAAAA,GAED+E,EAAO5O,EAAKc,SAAS,uCAAD6G,OACe/G,GAAwB,GAAE,gLASzDmW,OAAQyD,GACbD,EAAeA,GAAgBzb,EAAMK,SACrC,IAAMC,EAAMY,EAAK8E,UAAW8J,GAc5B,OAZAxP,EAAI0H,KAAM,WAAYjH,SAAU,kBAChCT,EAAI0H,KAAM,qBAAsBhH,OAC/Bya,EAAanb,UAEGsB,IAAZmJ,GACJyQ,EAAclb,IAAIub,YAAavb,EAAI0H,KAAM,mBAErCgD,GAAiBA,EAActF,QACnCpF,EAAI0H,KAAM,kBAAmBhH,OAC5BgK,EAAcgH,KAAK,SAAE8J,GAAS,OAAMA,EAAUxb,GAAG,KAG5CA,EAAI,EACZ,CAaA,SAASgK,EAAQS,EAASC,EAAeyQ,EAAc3Z,GAEtD,OAAOyZ,EADPxQ,EAAU,kCAAHlC,OAAsCkC,EAAO,eACxBC,EAAeyQ,EAAc3Z,EAC1D,CA6DA5B,EAAOC,QAAU,CAChB4b,aAdD,SAAuBhR,GACtB,OAAOT,EACNS,EACA,CACC/K,EAAMQ,QAAS,CACdsB,qBAAsB,yBAGxB9B,EAAMK,SACN,uBAEF,EAIC2b,WAvCD,SAAqBjR,EAASjJ,GAC7B,OAAOwI,EACNS,EACA,CACC,IAAIvG,EAAQ,CACX/D,QAAS,SACTqB,qBAAsB,cACtBwD,UAAU,EACV3E,MAAOO,EAAK+a,oBACZ1W,KAAM,WAGRvF,EAAMiN,OACNnL,EAEF,EAyBCoa,WApDD,SAAqBC,EAAgBnR,EAAeyQ,EAAc3Z,GACjE,OAAOyZ,EAAYY,EAAgBnR,EAAeyQ,EAAc3Z,EACjE,EAmDCwI,OAAAA,E,4CCjID,IACC8R,EAAe,QACfrT,EAAO9I,EAAS,gCAChBsE,EAAatE,EAAS,sCAajBD,EAAQ,CACboc,aAAAA,EAEArT,KAAAA,EACAxE,WAAAA,EAWA0I,KAAI,WACH,OAAO,IAAIjN,EAAMuE,WAAY,CAC5B9D,QAAS,SACTuE,KAAM,WACNlD,qBAAsB,OACtBnB,MAAOC,GAAGC,IAAK,kCAEjB,EAaAR,OAAM,SAAEgc,GAAsB,IAAbzV,EAAKrF,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,EACnB+a,EAAQD,EAAU,GAAHxT,OAAOuT,EAAY,KAAAvT,OAAMwT,GAAO,GAAAxT,OAAUuT,GAI/D,OAHAxV,EAAM9E,qBAAuB8E,EAAM9E,sBAAwB,GAC3D8E,EAAM9E,sBAAwB,UAEvB,IAAI9B,EAAMuE,WAAY7B,OAAO6Z,OAAQ,CAC3C9b,QAAS,SACTuE,KAAMsX,EACN3b,MAAOC,GAAGC,IAAK,kCACb+F,GACJ,EAaApG,QAAO,WAAe,IAAboG,EAAKrF,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,OACmBK,IAA/BgF,EAAM9E,uBACV8E,EAAM9E,qBAAuB,mBAG9B,IAAMtB,EAAU,IAAIR,EAAMuE,WAAY7B,OAAO6Z,OAAQ,CACpD9b,QAAS,OACTuE,KAAM,UACNrE,MAAOC,GAAGC,IAAK,oCACb+F,IAUH,OAPApG,EAAQF,IAAImI,cAEZjI,EAAQF,IAAIS,SAAU6F,EAAM9E,sBAC5BtB,EAAQF,IAAIuJ,KAAM,OAAQ,IACrBrJ,EAAQiE,QAAQ/D,YACpBF,EAAQF,IAAIS,SAAU,2BAEhBP,CACR,EAQAgc,MAAK,WACJ,OAAO,IAAIxc,EAAMuE,WAAY,CAC5BS,KAAM,eACNlD,qBAAsB,sBAExB,EASA2a,MAAK,WAAe,IAAb7V,EAAKrF,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,EAIf,OAHAqF,EAAM9E,qBAAuB8E,EAAM9E,sBAAwB,GAC3D8E,EAAM9E,sBAAwB,sBAEvB,IAAI9B,EAAMuE,WAAY7B,OAAO6Z,OAAQ,CAC3CvX,KAAM,eACJ4B,GACJ,EASA8V,QAAO,WAAe,IAAb9V,EAAKrF,UAAAmE,OAAA,QAAA9D,IAAAL,UAAA,GAAAA,UAAA,GAAG,CAAC,EAIjB,OAHAqF,EAAM9E,qBAAuB8E,EAAM9E,sBAAwB,GAC3D8E,EAAM9E,sBAAwB,8BAEvB,IAAI9B,EAAMuE,WAAY7B,OAAO6Z,OAAQ,CAC3CvX,KAAM,sBACJ4B,GACJ,GAGD1G,EAAOC,QAAUH,C,iEC9IjB,IACCkB,EAAOjB,EAAS,gCAChB0c,EAAmB,yBAoFpBzc,EAAOC,QAAU,CAChBwc,iBAAAA,EACAC,kBA/ED,SAA4BC,GAC3B,OAAO1H,MAAMxS,UAAUiM,MAAMnM,KAC5Boa,EAAKC,uBAAwBH,GAE/B,EA4ECI,WAnED,SAAqBC,GACpB,OAAO9b,EAAK+b,QAAQC,IACnBF,EAAahL,KAAK,SAAEmL,GAAW,OAAMjd,EAAOC,QAAQid,UAAWD,GAAc5U,OAAO,IAEtF,EAgEC6U,UAvDD,SAAoBD,GACnB,IACCE,EAAWnc,EAAK0G,WAEhBE,EAAQqV,EAAYG,QAAQxV,MAC5BmJ,EAASkM,EAAYG,QAAQrM,OAC7BsM,EAAQ,IAAIC,MAuCb,OArCK1V,GACJyV,EAAME,aAAc,QAAS5Z,SAAUiE,EAAO,KAE1CmJ,GACJsM,EAAME,aAAc,SAAU5Z,SAAUoN,EAAQ,KAIjDsM,EAAMzW,UAAYqW,EAAYG,QAAQI,OAAS,GAC/CH,EAAMI,IAAMR,EAAYG,QAAQK,KAAO,GACvCJ,EAAMK,OAAST,EAAYG,QAAQO,OACnCN,EAAM9H,MAAMqI,QAAUX,EAAY1H,MAAMqI,SAAW,GAGnDP,EAAMQ,iBAAkB,QAAQ,WAG/BR,EAAMS,UAAU/O,IAAK,qBAChBkO,EAAYc,YAChBd,EAAYc,WAAWC,aAAcX,EAAOJ,GAE7CE,EAASnV,QAAS,OACnB,GAAG,CAAEuF,MAAM,IACX8P,EAAMQ,iBAAkB,SAAS,WAE3BZ,EAAYc,YAChBd,EAAYc,WAAWC,aAAcX,EAAOJ,GAI7CE,EAASnV,QAAS,QACnB,GAAG,CAAEuF,MAAM,IAGX8P,EAAMY,IAAMhB,EAAYG,QAAQa,KAAO,GACvCZ,EAAMa,OAASjB,EAAYG,QAAQc,QAAU,GAEtC,CACN7V,QAAS8U,EACTE,MAAAA,EAEF,EAOC7Z,KAAM,CACLiZ,iBAAAA,G,yCCnFFzc,EAAOC,QAAU,SAAmBke,EAAOC,EAAmB3b,GAC7D,IAAIlB,EAOJ,IAAMA,KANDkB,EACJ+U,GAAG6G,aAAcF,EAAOC,IAExB5G,GAAG8G,UAAWH,GACd1b,EAAY2b,GAEA3b,EACZ0b,EAAM1b,UAAUlB,GAAOkB,EAAUlB,EAEnC,C,6CCZA,SAASgd,IAKRnc,KAAKoc,UAAY,CAAC,CACnB,CAEAD,EAAa9b,UAAY,CAWxB1C,QAAO,SAAPA,EAASmO,GACR,IAAMuQ,EAAWrc,KAAKoc,UAKtB,SAASE,IACR,IAAMlc,OAAOE,eAAeH,KAAMkc,EAAUvQ,GAC3C,MAAM,IAAI/E,MAAO,oCAAsC+E,GAExD,OAAOuQ,EAASvQ,EACjB,CAEA,IAAMoD,EAAOpD,EAAGqD,MAAO,KACvB,IACC,IAAMvR,EAASmP,EAAyBmC,EAAK,IAC7C,OAAKtR,EAAOsR,EAAK,IACTtR,EAAOsR,EAAK,IAEZoN,GAET,CAAE,MAAQC,GACT,OAAOD,GACR,CACD,EAWAE,OAAM,SAAE1Q,EAAI2Q,GACX,IAAMpQ,EAAOrM,KAEb,GAAKI,OAAOE,eAAeH,KAAMH,KAAKoc,UAAWtQ,GAChD,MAAM,IAAI/E,MAAO,0BAA4B+E,GAI9C,OAFA9L,KAAKoc,UAAUtQ,GAAM2Q,EAEd,CAMNC,UAAS,SAAEC,GACVtQ,EAAKqQ,UAAWC,EAAcF,EAAK3Q,EACpC,EAEF,EAYA4Q,UAAS,SAAE5Q,EAAI2Q,EAAKG,GACnB,IAAIre,EACCqe,IAEJre,EAAM,OAASqe,EAAc,aAG9Bte,GAAGue,IAAIH,UAAW1c,KAAKoc,UAAWtQ,EAAI2Q,EAAKle,EAC5C,GAGDX,EAAOC,QAAUse,C,4DCvGjB,IAAMA,EAAexe,EAAS,wCAE9BC,EAAOC,QAAU,IAAIse,C,0DCFrB,IAAM1O,EAAO9P,EAAS,gCAChBiB,EAAOjB,EAAS,gCA2CtBC,EAAOC,QAAU,CAAE8W,MAlCnB,SAAgBmI,GACf,IAAIlP,EACEoE,EAAQ8K,EAAKrO,UAClBsO,EAAYD,EAAKC,WAAa,CAC7BC,aAAc1e,GAAGkP,KAAKK,OAAQiP,EAAKjV,QAEpCoV,EAAQH,EAAKG,OAASH,EAAKI,YAkB5B,OAhBKH,GAAaE,KAMjBrP,EAAeqP,GAASA,EAAM5e,MAC7BC,GAAGkP,KAAKK,OAAQoP,EAAM5e,MAAM,IAAO0e,EAAUC,cAG/CF,EAAK7O,oBAAsB6O,EAAKlI,kBAAetV,EAE1C0S,IACJ8K,EAAKrO,UAAUC,YAAcsD,EAAMxM,MAAQwM,EAAMrD,QAG3C,IAAIlB,EACV7O,EAAK6D,OAAQqa,EAAM,CAClBhR,GAAIgR,EAAKK,OACT/O,YAAa0O,EAAKM,QAClBpP,IAAK1P,GAAGM,KAAKiF,OAAQiZ,EAAKjV,OAC1B+F,aAAAA,IAGH,E,4DCiFAhQ,EAAOC,QA5FP,SACCkI,EACAsX,EACAC,EACAC,EACAC,EACAC,GAGA,IAAMC,EAA0B,CAAC,EACjC,IAAM,IAAMve,KAAOke,EAAU,CAC5B,IAAMM,EAAIN,EAASle,GACnBue,EAAwBC,GAAK,mBAAHpX,OAAuB+W,EAAY,gBAAA/W,OAAiBoX,EAC/E,CAKA,SAASC,IACR,OAAOL,CACR,CAMA,SAASM,EAAgBxb,GACxB,KAAQA,KAAUgb,GACjB,MAAM,IAAItW,MAAM,WAADR,OACFlE,EAAM,0KAKrB,CAgBA,MAAO,CAUNyb,eAAc,SAAEzb,GACf,IAnBF,SAA2BA,GAG1B,OAFAwb,EAAgBxb,GAETub,KACNJ,GACqD,OAArDC,EAAUre,IAAKse,EAAwBrb,GACzC,CAaQ0b,CAAkB1b,GAEvB,OAAO,KACP,QAAA2b,EAAA/e,UAAAmE,OAJyB8L,EAAI,IAAA2D,MAAAmL,EAAA,EAAAA,EAAA,KAAAC,EAAA,EAAAA,EAAAD,EAAAC,IAAJ/O,EAAI+O,EAAA,GAAAhf,UAAAgf,GAM9B,OAAOlY,EAAMxF,WAAC,EAAD,CAAE8B,GAAMkE,OAAK2I,GAC3B,EAOAiJ,qBAAoB,SAAE9V,GAKrB,OAJAwb,EAAgBxb,GAITob,EAAUS,IAAKR,EAAwBrb,GAAS,IACxD,EACA8b,yBAAwB,WACvB,IAAIhf,EAAKkD,EACT,IAAMlD,KAAOke,EACZhb,EAASgb,EAAQle,GACjBa,KAAKmY,qBAAsB9V,EAE7B,EACAub,iBAAAA,EAEF,C,iDCzHA,IACCQ,EAAa,uBAkBd9f,GAAG+f,qBATH,WACC,IAAI3M,EAAOpT,GAAGoZ,QAAQtY,IAAKgf,GACtB1M,IACJA,EAAO4M,KAAK3J,MAAOjD,GACnBpT,GAAGigB,OAAQ7M,EAAK9N,QAAS8N,EAAKvP,SAC9B7D,GAAGoZ,QAAQ8G,OAAQJ,GAErB,IAkCAxgB,EAAOC,QAAU,CAAEua,iBAdnB,SAA2BxU,EAASzB,GAC9B7D,GAAGoZ,QAAQtY,IAAKgf,GACpB9f,GAAGue,IAAI4B,KACN,qFAKFngB,GAAGoZ,QAAQwG,IAAKE,EAAYE,KAAKI,UAAW,CAC3C9a,QAAAA,EACAzB,QAAAA,IAEF,E,qCCzCAvE,EAAOC,QAAU,CAOhB8b,kBAAiB,WAChB,OAAOrb,GAAGkD,OAAOpC,IAAK,kCACrBd,GAAGC,IAAK,kCAAqCD,GAAGC,IAAK,8BACvD,EAOAoc,QAAS,CASRC,IAAG,SAAE+D,GACJ,OAAOngB,EAAEogB,KAAKre,MAAO/B,EAAGmgB,EACzB,GAUDE,eAAc,SAAEhP,GACf,OAAOrR,EAAEqgB,eAAgBhP,EAC1B,EASAjD,SAAQ,SAAEkS,GACT,OAAOtgB,EAAGsgB,EACX,EAQAxZ,SAAQ,WACP,OAAO9G,EAAE8G,UACV,EAQAxD,YAAW,WACV,OAAOtD,EAAGwO,SAAS+R,gBACpB,EAQAC,UAAS,WACR,OAAOxgB,EAAGiD,OACX,EAaAiC,UAAS,SAAE8J,EAAMyR,GAEhB,OADAA,EAAMA,GAAOjS,SACNxO,EAAGA,EAAEkF,UAAW8J,EAAMyR,GAC9B,EAYAxc,OAAM,WACL,OAAOjE,EAAEiE,OAAOlC,MAAO/B,EAAGS,UAC3B,EAEAS,SAAQ,SAAEwf,GACT,MAAO,CAKNC,UAAS,WACR,OAAOD,CACR,EAOAvJ,OAAM,SAAEjE,EAAM0N,GACb,IAAMC,EAAgB,CAAC,EASvB,OAPAjf,OAAOuL,KAAMyT,GAAY,CAAC,GAAIhJ,SAAS,SAAEjX,GACxCkgB,EAAclgB,GAAOigB,EAASjgB,GAAKggB,WACpC,IAKOG,SAAS3J,OACfuJ,EAAO1Y,OACPkL,EACA2N,EAEF,EAEF,E,iECzJD,IAAMzgB,EAAOjB,EAAS,gCACrBgb,EAAehb,EAAS,wCA6BzB,SAAS4hB,EAAkBC,GAC1Bxf,KAAKwf,IAAMA,CACZ,CAEAD,EAAiBlf,UAAY,CAuB5Bof,YAAW,SAAEC,EAAKC,GAEjB,OAAO/gB,EAAK+b,QAAQC,IAAK,CACxB5a,KAAK4f,gBAAiBF,GACtB1f,KAAK6f,mBAAoBF,KACtBG,MAAM,WACT,OAAOlhB,EAAK6D,OAAOlC,MAAO3B,EAAMK,UACjC,GACD,EAQA2gB,gBAAe,SAAEF,GAChB,IAAMrT,EAAOrM,KACb,OAAM0f,EAAItc,OAIHpD,KAAKwf,IAAIpgB,IAAK,CACpBmX,cAAe,EACflU,OAAQ,QACRyS,KAAM,OACNiL,OAAQ,UACRC,QAASN,IACNI,MAAM,SAAEG,GAAG,OAAM5T,EAAK6T,sBAAuBD,EAAK,IAT9CrhB,EAAK0G,WAAWM,QAAS,CAAC,EAUnC,EAQAia,mBAAkB,SAAEF,GACnB,IAAMtT,EAAOrM,KACb,OAAM2f,EAAOvc,OAINpD,KAAKwf,IAAIpgB,IAAKuZ,EAAc,CAClC7D,KAAM,OACNiL,OAAQ,UACRJ,OAAAA,KACKG,MAAM,SAAEG,GAAG,OAAM5T,EAAK6T,sBAAuBD,EAAK,IAPhDrhB,EAAK0G,WAAWM,QAAS,CAAC,EAQnC,EASAua,oBAAmB,SAAER,EAAQvF,GAC5B,IAAM/W,EAAS,CACdhB,OAAQ,QACRsd,OAAAA,GAKD,OAHMvF,IACL/W,EAAO+c,SAAWhG,GAEZpa,KAAKwf,IAAIa,cAAe,QAAShd,EACzC,EAWA6c,sBAAqB,SAAED,GAEtB,OADcA,GAAOA,EAAIK,OAASL,EAAIK,MAAMrN,OAAS,IACxCrH,QAAQ,SAAE2U,EAAU7M,GAEhC,OADA6M,EAAS7M,EAAK7L,OAAS6L,EAAK0G,QACrBmG,CACR,GAAG,CAAC,EACL,GAGD3iB,EAAOC,QAAU0hB,C,kEC/IjB,IAAMvM,EAAWrV,EAAS,oCACzB6iB,EAAY7iB,EAAS,+CACrB6Z,EAAOlZ,GAAGkZ,KACV5Y,EAAOjB,EAAS,gCAChB8P,EAAO9P,EAAS,gCAChBqE,EAAWrE,EAAS,oCACpB4hB,EAAmB5hB,EAAS,sDAqB7B,SAAS8iB,EAAmBte,GAC3BnC,KAAK0gB,UAAY,IAAInB,EAAkBpd,EAAQqd,KAC/CxM,EAASzS,MAAOP,KAAMf,UACvB,CAEA+C,EAAUye,EAAmBzN,EAAU,CAQtC1M,WAAU,WACT,IACC+F,EAAOrM,KACP0f,EAAM,GACNC,EAAS,GAEV3M,EAAS3S,UAAUiG,WAAW/F,MAAOP,MAErC,IAAM2gB,EAAS3gB,KAAK4gB,wBACd3N,EAAQjT,KAAK6gB,oBAAqBF,GAexC,OAbAvgB,OAAOuL,KAAMsH,GAAQmD,SAAS,SAAEvO,GAC/B,IAAMiE,EAAKmH,EAAMpL,GAGZiE,GAAa,MAAPA,EAEV4T,EAAItb,KAAM0H,GAGV6T,EAAOvb,KAAMyD,EAEf,IAEO7H,KAAK8gB,SAAUpB,EAAKC,GACzBG,MAAM,SAAES,GAAQ,OAAMlU,EAAK0U,YAAaJ,EAAQJ,EAAU,GAC7D,EAQAK,sBAAqB,WACpB,OAAO5gB,KAAKhC,IAAI0H,KAAM,0BACvB,EAYAob,SAAQ,SAAEpB,EAAKC,GAGd,OAAKnI,EAAKwJ,SACFpiB,EAAK0G,WAAWM,QAAS,CAAC,GAG3B5F,KAAK0gB,UAAUjB,YAAaC,EAAKC,EACzC,EAQAkB,oBAAmB,SAAEF,GACpB,IACCtU,EAAOrM,KACPiT,EAAQ,CAAC,EAKV,OAJA0N,EAAO5O,MAAM,SAAEkP,EAAG5N,GACjB,IAAM6N,EAAQ7U,EAAKrO,IAAI0H,KAAM2N,GAC7BJ,EAAMiO,EAAM3Z,KAAM,UAAa2Z,EAAMxP,KAAM,KAC5C,IACOuB,CACR,EAQA8N,YAAW,SAAEJ,EAAQJ,GACpB,IAAMlU,EAAOrM,KAGRwX,EAAKwJ,UAKVL,EAAO5O,MAAM,SAAEkP,EAAG5N,GACjB,IACC6N,EAAQ7U,EAAKrO,IAAI0H,KAAM2N,GACvBK,EAAO,IAAIjG,EAAM,CAEhB0T,SAAU,GACVtZ,MAAOqZ,EAAM3Z,KAAM,SACnBuE,GAAIoV,EAAMxP,KAAM,QAEjB0I,EAAUmG,EAAS7M,EAAK0N,YAEzB/U,EAAKgV,iBAAkBH,EAAOxN,EAAM0G,GACpC8G,EAAMziB,SAAU,iBACjB,GACD,EAQA4iB,iBAAgB,SAAEH,EAAOxN,EAAM0G,GAC9BoG,EAAW,CAIVhS,UAAW4L,EACX1G,KAAAA,IACG4N,SAAUJ,EACf,IAGDtjB,EAAOC,QAAU4iB,C,0DCnKjB,IAAM/iB,EAAQC,EAAS,iCAWvBC,EAAOC,QAAU,SAAWsE,GAC3B,IAAMqM,EAAYrM,EAAQqM,UACzBgS,EAAYzT,QAAyB,6BAA8ByT,UACnEne,EAASmM,EAAY,UAAY,QACjC+S,EAAY,CACX9hB,KAAMnB,GAAGga,MAAMC,YAAapW,EAAQuR,KAAK7L,OAAQhE,OAAQ,CAAExB,OAAAA,KAE5Dmf,EAAc9jB,EAAMyc,MAAOoH,GAC3BE,EAAgB/jB,EAAM0c,QAASmH,GAC/BG,EAAqBF,EAAYla,eACjCqa,EAAuBF,EAAcna,eACrCsa,EAAcJ,EAAY1Z,UAAUR,eACpCua,EAAgBJ,EAAc3Z,UAAUR,eACxCwa,EAAatT,EAAYiT,EAAgBD,EAU1C,OADAhB,EAAWsB,EAAW9jB,IAAKmE,EAAQuR,KAAK7L,OAR5B,SAAEka,EAAO3H,GACnB2H,EAAMxa,KAAM,QAAS6S,EACpBuH,EAAuBD,GACVK,EAAMrc,KAAM,YACpB6B,KAAM,QAAS6S,EACpByH,EAAgBD,EAClB,IAGME,CACR,C","sources":["webpack://mfModules/./src/mobile.init/fakeToolbar.js","webpack://mfModules/./src/mobile.startup/Anchor.js","webpack://mfModules/./src/mobile.startup/Browser.js","webpack://mfModules/./src/mobile.startup/Button.js","webpack://mfModules/./src/mobile.startup/CtaDrawer.js","webpack://mfModules/./src/mobile.startup/Drawer.js","webpack://mfModules/./src/mobile.startup/Icon.js","webpack://mfModules/./src/mobile.startup/IconButton.js","webpack://mfModules/./src/mobile.startup/MessageBox.js","webpack://mfModules/./src/mobile.startup/Overlay.js","webpack://mfModules/./src/mobile.startup/OverlayManager.js","webpack://mfModules/./src/mobile.startup/Page.js","webpack://mfModules/./src/mobile.startup/PageHTMLParser.js","webpack://mfModules/./src/mobile.startup/PageList.js","webpack://mfModules/./src/mobile.startup/Skin.js","webpack://mfModules/./src/mobile.startup/Thumbnail.js","webpack://mfModules/./src/mobile.startup/View.js","webpack://mfModules/./src/mobile.startup/actionParams.js","webpack://mfModules/./src/mobile.startup/amcOutreach/AmcEnableForm.js","webpack://mfModules/./src/mobile.startup/amcOutreach/amcOutreach.js","webpack://mfModules/./src/mobile.startup/amcOutreach/amcOutreachDrawer.js","webpack://mfModules/./src/mobile.startup/currentPage.js","webpack://mfModules/./src/mobile.startup/currentPageHTMLParser.js","webpack://mfModules/./src/mobile.startup/eventBusSingleton.js","webpack://mfModules/./src/mobile.startup/extendSearchParams.js","webpack://mfModules/./src/mobile.startup/headers.js","webpack://mfModules/./src/mobile.startup/icons.js","webpack://mfModules/./src/mobile.startup/lazyImages/lazyImageLoader.js","webpack://mfModules/./src/mobile.startup/mfExtend.js","webpack://mfModules/./src/mobile.startup/moduleLoader.js","webpack://mfModules/./src/mobile.startup/moduleLoaderSingleton.js","webpack://mfModules/./src/mobile.startup/page/pageJSONParser.js","webpack://mfModules/./src/mobile.startup/promoCampaign/promoCampaign.js","webpack://mfModules/./src/mobile.startup/showOnPageReload.js","webpack://mfModules/./src/mobile.startup/util.js","webpack://mfModules/./src/mobile.startup/watchstar/WatchstarGateway.js","webpack://mfModules/./src/mobile.startup/watchstar/WatchstarPageList.js","webpack://mfModules/./src/mobile.startup/watchstar/watchstar.js"],"sourcesContent":["const icons = require( '../mobile.startup/icons' );\n\n/* global $ */\nmodule.exports = function fakeToolbar() {\n\tconst $goBack = icons.cancel().$el;\n\n\t// FIXME: Should not be a button, instead should be an icon with text\n\tconst $loadingMessage = icons.spinner( {\n\t\ttagName: 'span',\n\t\tisIconOnly: false,\n\t\tlabel: mw.msg( 'mobile-frontend-editor-loading' )\n\t} ).$el;\n\n\t// Wrappers similar to .overlay-header-container, .overlay-header and .oo-ui-toolbar\n\tconst $fakeToolbar = $( '<div>' )\n\t\t.addClass( 've-mobile-fakeToolbar-container' )\n\t\t.append( $( '<div>' )\n\t\t\t.addClass( 've-mobile-fakeToolbar-header' )\n\t\t\t// Minerva has some complicated styling for this class, so we have to include it\n\t\t\t.addClass( 'overlay-header' )\n\t\t\t.append( $( '<div>' )\n\t\t\t\t.addClass( 've-mobile-fakeToolbar' )\n\t\t\t\t.append( $goBack, $loadingMessage )\n\t\t\t)\n\t\t);\n\n\treturn $fakeToolbar;\n};\n","const\n\tView = require( './View' ),\n\tutil = require( './util' );\n\n/**\n * A wrapper for creating an anchor.\n *\n * @extends module:mobile.startup/View\n * @private\n */\nclass Anchor extends View {\n\t/**\n\t * @inheritdoc\n\t */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/**\n\t * @memberof Anchor\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {boolean} defaults.progressive is progressive action\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of anchor\n\t */\n\tget defaults() {\n\t\treturn {\n\t\t\tprogressive: undefined,\n\t\t\tdestructive: undefined,\n\t\t\tadditionalClassNames: '',\n\t\t\thref: undefined,\n\t\t\tlabel: undefined\n\t\t};\n\t}\n\n\t/**\n\t * @inheritdoc\n\t */\n\tget template() {\n\t\treturn util.template( `\n<a {{#href}}href=\"{{href}}\"{{/href}} class=\"mw-mf-anchor\n\t{{#progressive}} mw-mf-anchor-progressive{{/progressive}}\n\t{{#destructive}} mw-mf-anchor-destructive{{/destructive}}\n\t {{additionalClassNames}}\">{{label}}</a>\n\t` );\n\t}\n}\n\nmodule.exports = Anchor;\n","const util = require( './util' );\n\nlet browser;\n\n/**\n * Memoize a class method. Caches the result of the method based on the\n * arguments. Instances do not share a cache.\n *\n * @private\n * @param {Function} method Method to be memoized\n * @return {Function}\n */\nfunction memoize( method ) {\n\t/**\n\t * Memoized version of the method\n\t *\n\t * @return {Function}\n\t */\n\tconst memoized = function () {\n\t\tconst cache = this[ '__cache' + memoized.cacheId ] ||\n\t\t\t( this[ '__cache' + memoized.cacheId ] = {} ),\n\t\t\tkey = [].join.call( arguments, '|' );\n\t\tif ( Object.prototype.hasOwnProperty.call( cache, key ) ) {\n\t\t\treturn cache[ key ];\n\t\t}\n\t\treturn ( cache[ key ] = method.apply( this, arguments ) );\n\t};\n\tmemoized.cacheId = Date.now().toString() + Math.random().toString();\n\treturn memoized;\n}\n\n/**\n * Representation of user's current browser\n *\n * @class Browser\n * @private\n * @param {string} ua the user agent of the current browser\n * @param {jQuery.Object} $container an element to associate with the Browser object\n */\nfunction Browser( ua, $container ) {\n\tthis.userAgent = ua;\n\tthis.$el = $container;\n}\n\nBrowser.prototype = {\n\t/**\n\t * Returns whether the current browser is an ios device.\n\t * FIXME: jquery.client does not support iPad detection so we cannot use it.\n\t *\n\t * @memberof Browser\n\t * @instance\n\t * @param {number} [version] integer describing a specific version you want to test against.\n\t * @return {boolean}\n\t */\n\tisIos: memoize( function ( version ) {\n\t\tconst ua = this.userAgent,\n\t\t\tios = /ipad|iphone|ipod/i.test( ua );\n\n\t\tif ( ios && version ) {\n\t\t\tswitch ( version ) {\n\t\t\t\tcase 8:\n\t\t\t\t\t// Test UA for iOS8. Or for simulator look for Version 8\n\t\t\t\t\t// In the iOS simulator the OS is the host machine OS version\n\t\t\t\t\t// This makes testing in iOS8 simulator work as expected\n\t\t\t\t\treturn /OS 8_/.test( ua ) || /Version\\/8/.test( ua );\n\t\t\t\tcase 4:\n\t\t\t\t\treturn /OS 4_/.test( ua );\n\t\t\t\tcase 5:\n\t\t\t\t\treturn /OS 5_/.test( ua );\n\t\t\t\tdefault:\n\t\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\treturn ios;\n\t\t}\n\t} ),\n\t/**\n\t * Determine if a device has a widescreen.\n\t *\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tisWideScreen: memoize( () => {\n\t\tconst val = parseInt( mw.config.get( 'wgMFDeviceWidthTablet' ), 10 );\n\t\t// Check viewport width to determine mobile vs tablet.\n\t\t// Note: Mobile devices held in landscape mode might receive tablet treatment.\n\t\treturn window.innerWidth >= val;\n\t} ),\n\t/**\n\t * Whether touchstart and other touch events are supported by the current browser.\n\t *\n\t * @memberof Browser\n\t * @instance\n\t * @return {boolean}\n\t */\n\tsupportsTouchEvents: memoize( () => 'ontouchstart' in window )\n};\n\n/**\n * @memberof Browser\n * @return {Browser}\n */\nBrowser.getSingleton = function () {\n\tlet $html;\n\tif ( !browser ) {\n\t\t$html = util.getDocument();\n\t\tbrowser = new Browser( window.navigator.userAgent, $html );\n\t}\n\treturn browser;\n};\n\nmodule.exports = Browser;\n","const\n\tmfExtend = require( './mfExtend' ),\n\tutil = require( './util' ),\n\tView = require( './View' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * A wrapper for creating a button.\n * FIXME: T343036 This file should be combined with IconButton, all gadgets/extentions\n * using Button.js and IconButton.js will need to be updated to reflect this\n *\n * @class Button\n * @private\n * @extends module:mobile.startup/View\n *\n * @param {Object} options Configuration options\n */\nfunction Button( options ) {\n\tView.call( this, options );\n}\n\nmfExtend( Button, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof IconButton\n\t * @instance\n\t */\n\tpreRender() {\n\t\t// Mapping existing props to Codex props used in IconButton\n\t\tlet action = 'default';\n\t\tif ( this.options.progressive ) {\n\t\t\taction = 'progressive';\n\t\t} else if ( this.options.destructive ) {\n\t\t\taction = 'destructive';\n\t\t}\n\t\tlet weight = this.options.quiet ? 'quiet' : 'normal';\n\t\tif ( this.options.progressive || this.options.destructive ) {\n\t\t\tweight = 'primary';\n\t\t}\n\t\tif ( this.options.block ) {\n\t\t\tthis.options.additionalClassNames += ' mf-button-block';\n\t\t}\n\t\tconst options = util.extend( {\n\t\t\tweight,\n\t\t\taction,\n\t\t\tisIconOnly: false,\n\t\t\ticon: null\n\t\t}, this.options );\n\n\t\tthis._button = new IconButton( options );\n\t\tthis.options._buttonHTML = this._button.$el.get( 0 ).outerHTML;\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Button\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof Button\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.tagName The name of the tag in which the button is wrapped.\n\t * @property {boolean} defaults.block is stacked button\n\t * @property {boolean} defaults.progressive is progressive action\n\t * @property {boolean} defaults.quiet is quiet button\n\t * @property {boolean} defaults.destructive is destructive action\n\t * @property {string} defaults.additionalClassNames Additional class name(s).\n\t * @property {string} defaults.href url\n\t * @property {string} defaults.label of button\n\t * @property {boolean} defaults.disabled should only be used with tagName button\n\t */\n\tdefaults: {\n\t\ttagName: 'a',\n\t\tdisabled: false,\n\t\tblock: undefined,\n\t\tprogressive: undefined,\n\t\tdestructive: undefined,\n\t\tquiet: undefined,\n\t\tadditionalClassNames: '',\n\t\thref: undefined,\n\t\tlabel: undefined,\n\t\tsize: 'medium'\n\t},\n\t/**\n\t * @memberof Button\n\t * @instance\n\t */\n\ttemplate: util.template( '{{{_buttonHTML}}}' )\n} );\n\nmodule.exports = Button;\n","const\n\tDrawer = require( './Drawer' ),\n\tutil = require( './util' ),\n\tButton = require( './Button' ),\n\tAnchor = require( './Anchor' );\n\n/**\n * Represents a query string value.\n *\n * @typedef {string|number|boolean|undefined|string[]|boolean[]} module:mobile.startup~QueryVal\n */\n/**\n * Describes a combination of query string parameters.\n *\n * @typedef {Object.<string, module:mobile.startup~QueryVal>} module:mobile.startup~QueryParams\n */\n\n/**\n * Describes a call to action drawer.\n *\n * @memberof module:mobile.startup\n * @typedef {Object} CtaOptions\n * @prop {string} [returnTo]\n * @prop {module:mobile.startup~QueryParams} [queryParams]\n * @prop {module:mobile.startup~QueryParams} [signupQueryParams]\n * @prop {Object} [progressiveButton] button options for Button element for signing in.\n *  If omitted will create a login URL.\n * @prop {Object} [actionAnchor] anchor options for Anchor element for signing up. If omitted\n *   will create a sign up URL\n * @prop {string} content text - what is the call to action?\n */\n\n/**\n * Internal for use inside Minerva only, creates the drawer at the bottom of the screen that appears when an anonymous\n * user tries to perform an action that requires being logged in. It presents the user\n * with options to log in or sign up for a new account.\n *\n * @function CtaDrawer\n * @memberof module:mobile.startup\n * @param {module:mobile.startup.CtaOptions} options Options for drawer.\n * @return {module:mobile.startup/Drawer}\n */\nfunction CtaDrawer( options = {} ) {\n\tconst params = redirectParams( options.queryParams, options.returnTo );\n\treturn new Drawer(\n\t\tutil.extend( {\n\t\t\tchildren: [\n\t\t\t\tutil.parseHTML( '<p>' ).text( options.content ),\n\t\t\t\tnew Button( util.extend( {\n\t\t\t\t\tprogressive: true,\n\t\t\t\t\thref: mw.util.getUrl( 'Special:UserLogin', params ),\n\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-login' )\n\t\t\t\t}, options.progressiveButton ) ).$el,\n\t\t\t\tutil.parseHTML( '<div>' ).addClass( 'cta-drawer__anchors' ).append(\n\t\t\t\t\t// Update Minerva first to avoid needing to keep this closeAnchor\n\t\t\t\t\tnew Anchor( util.extend( {\n\t\t\t\t\t\thref: mw.util.getUrl(\n\t\t\t\t\t\t\t'Special:UserLogin', signUpParams( params, options.signupQueryParams )\n\t\t\t\t\t\t),\n\t\t\t\t\t\tprogressive: true,\n\t\t\t\t\t\tlabel: mw.msg( 'mobile-frontend-watchlist-cta-button-signup' )\n\t\t\t\t\t}, options.actionAnchor ) ).$el\n\t\t\t\t)\n\t\t\t]\n\t\t}, options )\n\t);\n}\n\n/**\n * Special:UserLogin post-request redirect query parameters.\n *\n * @ignore\n * @param {QueryParams} params\n * @param {string} [redirectURL]\n * @return {QueryParams}\n */\nfunction redirectParams( params, redirectURL ) {\n\treturn util.extend( {\n\t\t// use wgPageName as this includes the namespace if outside Main\n\t\treturnto: redirectURL || mw.config.get( 'wgPageName' )\n\t}, params );\n}\n\n/**\n * Special:UserLogin account creation query parameters.\n *\n * @ignore\n * @param {...QueryParams} params\n * @return {QueryParams}\n */\nfunction signUpParams() {\n\t[].push.call( arguments, { type: 'signup' } );\n\treturn util.extend.apply( util, arguments );\n}\n\nCtaDrawer.prototype.test = {\n\tredirectParams,\n\tsignUpParams\n};\n\nmodule.exports = CtaDrawer;\n","const\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * @classdesc A {@link View} that pops up from the bottom of the screen.\n * @class module:mobile.startup/Drawer\n * @extends module:mobile.startup/View\n * @final\n * @param {Object} props\n * @param {string} [props.className] Additional CSS classes to add\n * @param {jQuery.Element[]} [props.children] An array of elements to append to\n * @param {Function} [props.onShow] Callback called before showing the drawer.\n *  It receives a promise given the show process is asynchronous.\n * @param {Function} [props.onBeforeHide] Callback called before hiding the drawer\n */\nfunction Drawer( props ) {\n\tthis.drawerClassName = props.className || '';\n\tthis.collapseIcon = new IconButton( {\n\t\ticon: 'expand',\n\t\tadditionalClassNames: 'cancel',\n\t\tlabel: mw.msg( 'mobile-frontend-drawer-arrow-label' )\n\t} );\n\tView.call( this,\n\t\tutil.extend(\n\t\t\t{\n\t\t\t\tonBeforeHide: () => {},\n\t\t\t\tshowCollapseIcon: true\n\t\t\t},\n\t\t\tprops,\n\t\t\t{\n\t\t\t\tclassName: 'drawer-container'\n\t\t\t},\n\t\t\t{ events: util.extend( {\n\t\t\t\t'click .drawer-container__mask': function () {\n\t\t\t\t\tthis.hide();\n\t\t\t\t}.bind( this ),\n\t\t\t\t'click .cancel': function ( ev ) {\n\t\t\t\t\tev.preventDefault();\n\t\t\t\t\tthis.hide();\n\t\t\t\t}.bind( this ),\n\t\t\t\tclick( ev ) {\n\t\t\t\t\tev.stopPropagation();\n\t\t\t\t}\n\t\t\t}, props.events ) }\n\t\t)\n\t);\n}\n\nmfExtend( Drawer, View, {\n\t$mask: null,\n\n\t/**\n\t * Shows panel after a slight delay\n\t *\n\t * @memberof module:mobile.startup/Drawer\n\t * @instance\n\t * @method\n\t * @return {jQuery.Promise}\n\t */\n\tshow() {\n\t\tconst d = util.Deferred();\n\t\tthis.$el.prepend( this.$mask );\n\t\t// Force redraw by asking the browser to measure the element's width\n\t\tthis.$el.width();\n\t\tconst $drawer = this.$el.find( '.drawer' );\n\t\tthis.$mask.addClass( 'drawer-container__mask--visible' );\n\t\tif ( !$drawer.hasClass( 'visible' ) ) {\n\t\t\t$drawer.addClass( 'visible' );\n\t\t\t// IntersectionObserver doesn't fire for content\n\t\t\t// in drawers, so trigger manually (T361212)\n\t\t\tmw.hook( 'mobileFrontend.loadLazyImages' ).fire( this.$el );\n\t\t\tif ( this.options.onShow ) {\n\t\t\t\tthis.options.onShow( d );\n\t\t\t}\n\t\t\trequestAnimationFrame( () => d.resolve() );\n\t\t} else {\n\t\t\td.resolve();\n\t\t}\n\t\treturn d.promise();\n\t},\n\n\t/**\n\t * Hides panel\n\t *\n\t * @memberof module:mobile.startup/Drawer\n\t * @instance\n\t */\n\thide() {\n\t\tconst $drawer = this.$el.find( '.drawer' );\n\t\t$drawer.removeClass( 'visible' );\n\t\tthis.$mask.removeClass( 'drawer-container__mask--visible' );\n\t\t// Should really use 'transitionend' event here, but as the\n\t\t// parent $drawer element is often detatched as well, this\n\t\t// might not fire until the next show animation.\n\t\tsetTimeout( () => {\n\t\t\tthis.$mask.detach();\n\t\t}, 100 );\n\t\trequestAnimationFrame( () => {\n\t\t\tthis.options.onBeforeHide( this );\n\t\t} );\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof module:mobile.startup/Drawer\n\t * @instance\n\t */\n\tpostRender() {\n\t\tthis.$mask = util.parseHTML( '<div>' ).addClass( 'drawer-container__mask' );\n\t\tconst props = this.options,\n\t\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\t\t$drawer = util.parseHTML( '<div>' )\n\t\t\t\t.addClass( `drawer drawer-container__drawer position-fixed ${ this.drawerClassName }`.trim() );\n\n\t\tif ( props.showCollapseIcon ) {\n\t\t\t// append the collapse icon at the top of the drawer\n\t\t\t$drawer.prepend( this.collapseIcon.$el );\n\t\t}\n\n\t\tif ( props.children ) {\n\t\t\t// append children\n\t\t\t$drawer.append( props.children );\n\t\t}\n\t\tthis.$el.append( $drawer );\n\t}\n} );\n\nmodule.exports = Drawer;\n","const\n\tmfExtend = require( './mfExtend' ),\n\tutil = require( './util' ),\n\tView = require( './View' );\n\n/**\n * @class module:mobile.startup/Icon\n * @classdesc A wrapper for creating an icon.\n * @extends module:mobile.startup/View\n * @param {Object} options Configuration options\n */\nfunction Icon( options ) {\n\tView.call( this, options );\n}\n\nmfExtend( Icon, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof Icon\n\t * @instance\n\t */\n\tpreRender() {\n\t\tthis.options._iconClasses = this.getIconClasses();\n\t},\n\t/**\n\t * Internal method that sets the correct rotation class for the icon\n\t * based on the value of rotation\n\t *\n\t * @memberof Icon\n\t * @instance\n\t * @private\n\t */\n\tgetRotationClass() {\n\t\tlet rotationClass = '';\n\t\tif ( this.options.rotation ) {\n\t\t\tswitch ( this.options.rotation ) {\n\t\t\t\tcase -180:\n\t\t\t\tcase 180:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-flip';\n\t\t\t\t\tbreak;\n\t\t\t\tcase -90:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-anti-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 90:\n\t\t\t\t\trotationClass = 'mf-icon-rotate-clockwise';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0:\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new Error( 'Bad value for rotation given. Must be ±90, 0 or ±180.' );\n\t\t\t}\n\t\t}\n\t\treturn rotationClass;\n\t},\n\t/**\n\t * Set icon glyph class and icon type class\n\t *\n\t * @memberof Icon\n\t * @instance\n\t * @private\n\t */\n\tgetIconClasses() {\n\t\tconst base = this.options.base;\n\t\tconst icon = this.options.icon;\n\t\tconst isSmall = this.options.isSmall;\n\t\tconst rotationClasses = this.getRotationClass();\n\t\tconst additionalClassNames = this.options.additionalClassNames;\n\n\t\tlet classes = base + ' ';\n\t\tif ( icon ) {\n\t\t\tclasses += this.getGlyphClassName() + ' ';\n\t\t}\n\t\tif ( isSmall ) {\n\t\t\tclasses += 'mf-icon--small ';\n\t\t}\n\t\tif ( additionalClassNames ) {\n\t\t\tclasses += additionalClassNames + ' ';\n\t\t}\n\n\t\treturn classes + rotationClasses;\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Icon\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof Icon\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults\n\t * @property {string} defaults.base Base icon class.\n\t * Defaults to 'mf-icon'.\n\t * @property {string} defaults.glyphPrefix Prefix for the icon class\n\t * Defaults to 'mf'.\n\t * @property {string} defaults.icon Name of the icon.\n\t * @property {boolean} defaults.rotation will rotate the icon by a certain number\n\t *  of degrees. Must be ±90, 0 or ±180 or will throw exception.\n\t * @property {boolean} defaults.isSmall If icon is small.\n\t * @property {string} defaults.addtionalClassNames Additional classes to be added to the icon.\n\t */\n\tdefaults: {\n\t\tbase: 'mf-icon',\n\t\tglyphPrefix: null,\n\t\ticon: '',\n\t\trotation: 0,\n\t\tisSmall: false,\n\t\tadditionalClassNames: null\n\t},\n\t/**\n\t * Return the full class name that is required for the icon to render\n\t *\n\t * @memberof Icon\n\t * @instance\n\t * @return {string}\n\t */\n\tgetClassName() {\n\t\treturn this.$el.attr( 'class' );\n\t},\n\t/**\n\t * Return the class that relates to the icon glyph\n\t *\n\t * @memberof Icon\n\t * @instance\n\t * @return {string}\n\t */\n\tgetGlyphClassName() {\n\t\tif ( this.options.glyphPrefix ) {\n\t\t\treturn 'mf-icon-' + this.options.glyphPrefix + '-' + this.options.icon;\n\t\t}\n\t\treturn 'mf-icon-' + this.options.icon;\n\t},\n\n\ttemplate: util.template(\n\t\t'<span class=\"{{_iconClasses}}\"> </span>'\n\t)\n} );\n\nmodule.exports = Icon;\n","const\n\tmfExtend = require( './mfExtend' ),\n\tutil = require( './util' ),\n\tView = require( './View' ),\n\tIcon = require( './Icon' );\n\n/**\n * A wrapper for creating an icon button.\n *\n * @class IconButton\n * @extends module:mobile.startup/View\n *\n * @param {Object} options Configuration options\n */\nfunction IconButton( options ) {\n\tif ( options.href ) {\n\t\toptions.tagName = 'a';\n\t}\n\tif ( options.tagName === 'button' ) {\n\t\toptions.isTypeButton = true;\n\t}\n\tView.call( this, options );\n}\n\nmfExtend( IconButton, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof IconButton\n\t * @instance\n\t */\n\tpreRender() {\n\t\tthis.options._buttonClasses = this.getButtonClasses();\n\t\tthis.options._iconHTML = '';\n\t\tif ( this.options.icon ) {\n\t\t\tthis._icon = new Icon( {\n\t\t\t\tbase: this.options.base,\n\t\t\t\tglyphPrefix: this.options.glyphPrefix,\n\t\t\t\ticon: this.options.icon,\n\t\t\t\trotation: this.options.rotation,\n\t\t\t\tisSmall: this.options.isSmall\n\t\t\t} );\n\t\t\tthis.options._iconHTML = this._icon.$el.get( 0 ).outerHTML;\n\t\t}\n\t},\n\tgetButtonClasses() {\n\t\tconst additionalClassNames = this.options.additionalClassNames;\n\t\tconst size = this.options.size;\n\t\tconst weight = this.options.weight;\n\t\tconst action = this.options.action;\n\t\tconst isIconOnly = this.options.isIconOnly;\n\t\tlet classes = 'cdx-button ';\n\n\t\tif ( this.options.tagName !== 'button' ) {\n\t\t\tclasses += 'cdx-button--fake-button cdx-button--fake-button--enabled ';\n\t\t}\n\t\tif ( size ) {\n\t\t\tclasses += `cdx-button--size-${ size } `;\n\t\t}\n\t\tif ( weight ) {\n\t\t\tclasses += `cdx-button--weight-${ weight } `;\n\t\t}\n\t\tif ( action ) {\n\t\t\tclasses += `cdx-button--action-${ action } `;\n\t\t}\n\t\tif ( isIconOnly ) {\n\t\t\tclasses += 'cdx-button--icon-only ';\n\t\t}\n\t\treturn classes + additionalClassNames;\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof IconButton\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof IconButton\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.tagName The name of the tag in which the button is wrapped.\n\t *  Defaults to 'a' when href option present.\n\t * @property {string} [defaults.href] value of href attribute,\n\t *  when set tagName will default to anchor tag\n\t * @property {string} defaults.additionalClassNames Additional classes to be added to the button\n\t * @property {string} defaults.title Tooltip text.\n\t * @property {string} defaults.size Button size.\n\t * Defaults to 'large'.\n\t * @property {boolean} defaults.weight Button weight.\n\t * Defaults to 'quiet'.\n\t * @property {boolean} defaults.action Button action.\n\t * @property {boolean} defaults.isIconOnly Whether button is an icon only button\n\t * Defaults to true.\n\t * @property {boolean} defaults.disabled should only be used with tagName button\n\t * @property {string} defaults.base String used as a base for generating class names.\n\t * Defaults to 'mf-icon'.\n\t * @property {string} defaults.glyphPrefix Prefix for the icon class\n\t * @property {string} defaults.icon Name of the icon.\n\t * @property {boolean} defaults.rotation will rotate the icon by a certain number\n\t *  of degrees. Must be ±90, 0 or ±180 or will throw exception.\n\t * @property {boolean} defaults.isSmall Whether the icon should be small.\n\t */\n\tdefaults: {\n\t\ttagName: 'button',\n\t\thref: undefined,\n\t\tadditionalClassNames: '',\n\t\ttitle: '',\n\t\tsize: 'large',\n\t\tweight: 'quiet',\n\t\taction: '',\n\t\tisIconOnly: true,\n\t\tdisabled: false,\n\t\tbase: 'mf-icon',\n\t\ticon: '',\n\t\trotation: 0,\n\t\tisSmall: false\n\t},\n\t/**\n\t * Return the full class name that is required for the icon to render\n\t *\n\t * @memberof IconButton\n\t * @instance\n\t * @return {string}\n\t */\n\tgetClassName() {\n\t\treturn this.$el.attr( 'class' );\n\t},\n\tgetIcon() {\n\t\treturn this._icon;\n\t},\n\ttemplate: util.template( `\n\t\t<{{tagName}}\n\t\t\ttype=\"button\"\n\t\t\t{{#isTypeButton}}{{#disabled}}disabled{{/disabled}}{{/isTypeButton}}\n\t\t\tclass=\"{{_buttonClasses}}\"\n\t\t\t{{#id}}id=\"{{id}}\"{{/id}}\n\t\t\t{{#href}}href=\"{{href}}\"{{/href}}\n\t\t\t{{#title}}title=\"{{title}}\"{{/title}}>\n\t\t\t\t{{{_iconHTML}}}\n\t\t\t\t<span>{{label}}</span>\n\t\t</{{tagName}}>\n\t` )\n} );\n\nmodule.exports = IconButton;\n","const\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * Render CSS version of Codex message component.\n *\n * @class MessageBox\n * @extends module:mobile.startup/View\n */\nfunction MessageBox() {\n\tView.apply( this, arguments );\n}\n\nmfExtend( MessageBox, View, {\n\t/**\n\t * @inheritdoc\n\t * @memberof MessageBox\n\t * @instance\n\t */\n\tisTemplateMode: true,\n\t/**\n\t * @memberof MessageBox\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} [defaults.heading] heading to show along with message (text)\n\t * @property {string} defaults.msg message to show (html)\n\t * @property {string} defaults.type either error, notice or warning\n\t * @property {string} defaults.className\n\t */\n\tdefaults: {},\n\t/**\n\t * @memberof MessageBox\n\t * @instance\n\t */\n\ttemplate: util.template( `\n<div\n  class=\"cdx-message cdx-message--block cdx-message--{{type}} {{className}}\"\n  aria-live=\"polite\"\n>\n  <!-- Empty span for message icon. -->\n  <span class=\"cdx-message__icon\"></span>\n  <!-- Div for content. -->\n  <div class=\"cdx-message__content\">\n  {{#heading}}<h2>{{heading}}</h2>{{/heading}}\n  {{{msg}}}\n  </div>\n</div>\n\t` )\n} );\n\nmodule.exports = MessageBox;\n","const\n\tView = require( './View' ),\n\theader = require( './headers' ).header,\n\tAnchor = require( './Anchor' ),\n\tutil = require( './util' ),\n\tbrowser = require( './Browser' ).getSingleton(),\n\tmfExtend = require( './mfExtend' );\n\n/**\n * @class module:mobile.startup/Overlay\n * @classdesc Mobile modal window\n * @extends module:mobile.startup/View\n * @uses Icon\n * @uses Button\n * @fires Overlay#hide\n * @param {Object} props\n * @param {Object} props.events - custom events to be bound to the overlay.\n * @param {boolean} [props.headerChrome] Whether the header has chrome.\n * @param {View[]} [props.headerActions] children (usually buttons or icons)\n *   that should be placed in the header actions. Ignored when `headers` used.\n * @param {string} [props.heading] heading for the overlay header. Use `headers` where\n *  overlays require more than one header. Ignored when `headers` used.\n * @param {boolean} props.noHeader renders an overlay without a header\n * @param {Element[]} [props.headers] allows overlays to have more than one\n *  header. When used it is an array of jQuery Objects representing\n *  headers created via the header util function. It is expected that only one of these\n *  should be visible. If undefined, headerActions and heading is used.\n * @param {Object} [props.footerAnchor] options for an optional Anchor\n *  that can appear in the footer\n * @param {Function} props.onBeforeExit allows a consumer to prevent exits in certain\n *  situations. This callback gets the following parameters:\n *  - 1) the exit function which should be run after the consumer has made their changes.\n *  - 2) the cancel function which should be run if the consumer explicitly changes their mind\n */\nfunction Overlay( props ) {\n\tthis.isIos = browser.isIos();\n\n\tView.call(\n\t\tthis,\n\t\tutil.extend(\n\t\t\ttrue,\n\t\t\t{\n\t\t\t\theaderChrome: false,\n\t\t\t\tclassName: 'overlay'\n\t\t\t},\n\t\t\tprops,\n\t\t\t{\n\t\t\t\tevents: util.extend(\n\t\t\t\t\t{\n\t\t\t\t\t\t// FIXME: Remove .initial-header selector\n\t\t\t\t\t\t'click .cancel, .confirm, .initial-header .back': 'onExitClick',\n\t\t\t\t\t\tclick: ( ev ) => ev.stopPropagation()\n\t\t\t\t\t},\n\t\t\t\t\tprops.events\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t);\n}\n\nmfExtend( Overlay, View, {\n\ttemplate: util.template( `\n{{^noHeader}}\n<div class=\"overlay-header-container header-container{{#headerChrome}}\n\theader-chrome{{/headerChrome}} position-fixed\">\n</div>\n{{/noHeader}}\n<div class=\"overlay-content\">\n\t{{>content}}\n</div>\n<div class=\"overlay-footer-container position-fixed\"></div>\n\t` ),\n\n\thideTimeout: null,\n\n\t/**\n\t * Shows the spinner right to the input field.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @method\n\t */\n\tshowSpinner() {\n\t\tthis.$el.find( '.spinner' ).removeClass( 'hidden' );\n\t},\n\n\t/**\n\t * Hide the spinner near to the input field.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @method\n\t */\n\thideSpinner() {\n\t\tthis.$el.find( '.spinner' ).addClass( 'hidden' );\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t */\n\tpostRender() {\n\t\tconst footerAnchor = this.options.footerAnchor;\n\t\tthis.$overlayContent = this.$el.find( '.overlay-content' );\n\t\tif ( this.isIos ) {\n\t\t\tthis.$el.addClass( 'overlay-ios' );\n\t\t}\n\t\tif ( footerAnchor ) {\n\t\t\tthis.$el.find( '.overlay-footer-container' ).append( new Anchor( footerAnchor ).$el );\n\t\t}\n\t\tconst headers = this.options.headers || [\n\t\t\theader(\n\t\t\t\tthis.options.heading,\n\t\t\t\tthis.options.headerActions\n\t\t\t)\n\t\t];\n\t\tthis.$el.find( '.overlay-header-container' ).append( headers );\n\t},\n\n\t/**\n\t * ClickBack event handler\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @param {Object} ev event object\n\t */\n\tonExitClick( ev ) {\n\t\tconst exit = function () {\n\t\t\tthis.hide();\n\t\t}.bind( this );\n\t\tev.preventDefault();\n\t\tev.stopPropagation();\n\t\tif ( this.options.onBeforeExit ) {\n\t\t\tthis.options.onBeforeExit( exit, () => {\n\t\t\t} );\n\t\t} else {\n\t\t\texit();\n\t\t}\n\n\t},\n\t/**\n\t * Attach overlay to current view and show it.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t */\n\tshow() {\n\t\tconst $html = util.getDocument();\n\n\t\tthis.scrollTop = window.pageYOffset;\n\n\t\t$html.addClass( 'overlay-enabled' );\n\t\t// skip the URL bar if possible\n\t\twindow.scrollTo( 0, 1 );\n\n\t\tthis.$el.addClass( 'visible' );\n\n\t\t// If .hide() was called earlier, and it scheduled an asynchronous detach\n\t\t// but it hasn't happened yet, cancel it\n\t\tif ( this.hideTimeout !== null ) {\n\t\t\tclearTimeout( this.hideTimeout );\n\t\t\tthis.hideTimeout = null;\n\t\t}\n\t},\n\t/**\n\t * Detach the overlay from the current view\n\t * Should not be overriden as soon to be deprecated.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @final\n\t * @return {boolean} Whether the overlay was successfully hidden or not\n\t */\n\thide() {\n\t\tutil.getDocument().removeClass( 'overlay-enabled' );\n\t\t// return to last known scroll position\n\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\n\t\t// Since the hash change event caused by emitting hide will be detected later\n\t\t// and to avoid the article being shown during a transition from one overlay to\n\t\t// another, we regretfully detach the element asynchronously.\n\t\tthis.hideTimeout = setTimeout( () => {\n\t\t\tthis.$el.detach();\n\t\t\tthis.hideTimeout = null;\n\t\t}, 0 );\n\n\t\t/**\n\t\t * Fired when the overlay is closed.\n\t\t *\n\t\t * @event Overlay#hide\n\t\t */\n\t\tthis.emit( 'hide' );\n\n\t\treturn true;\n\t},\n\n\t/**\n\t * Show elements that are selected by the className.\n\t * Also hide .hideable elements\n\t * Can't use jQuery's hide() and show() because show() sets display: block.\n\t * And we want display: table for headers.\n\t *\n\t * @memberof module:mobile.startup/Overlay\n\t * @instance\n\t * @protected\n\t * @param {string} className CSS selector to show\n\t */\n\tshowHidden( className ) {\n\t\tthis.$el.find( '.hideable' ).addClass( 'hidden' );\n\t\tthis.$el.find( className ).removeClass( 'hidden' );\n\t}\n} );\n\n/**\n * Factory method for an overlay with a single child\n *\n * @memberof module:mobile.startup/Overlay\n * @instance\n * @protected\n * @param {Object} options\n * @param {module:mobile.startup/View} view\n * @return {module:mobile.startup/Overlay}\n */\nOverlay.make = function ( options, view ) {\n\tconst overlay = new Overlay( options );\n\toverlay.$el.find( '.overlay-content' ).append( view.$el );\n\treturn overlay;\n};\n\nmodule.exports = Overlay;\n","const util = require( './util' );\n\nlet overlayManager = null;\n\n// We pass this to history.pushState/replaceState to indicate that we're controlling the page URL.\n// Then we look for this marker on page load so that if the page is refreshed, we don't generate an\n// extra history entry (see #getSingleton below and T201852).\nconst MANAGED_STATE = 'MobileFrontend OverlayManager was here!';\n\n/**\n * Manages opening and closing overlays when the URL hash changes to one\n * of the registered values (see OverlayManager.add()).\n *\n * This allows overlays to function like real pages, with similar browser back/forward\n * and refresh behavior.\n *\n * @class module:mobile.startup/OverlayManager\n * @param {Router} router\n * @param {Element} container where overlays should be managed\n */\nfunction OverlayManager( router, container ) {\n\trouter.on( 'route', this._checkRoute.bind( this ) );\n\tthis.router = router;\n\t// use an object instead of an array for entries so that we don't\n\t// duplicate entries that already exist\n\tthis.entries = {};\n\t// stack of all the open overlays, stack[0] is the latest one\n\tthis.stack = [];\n\tthis.hideCurrent = true;\n\t// Set the element that overlays will be appended to\n\tthis.container = container;\n}\n\n/**\n * Attach an event to the overlays hide event\n *\n * @param {module:mobile.startup/Overlay} overlay\n * @private\n */\nfunction attachHideEvent( overlay ) {\n\toverlay.on( 'hide', () => overlay.emit( '_om_hide' ) );\n}\n\nOverlayManager.prototype = {\n\t/**\n\t * Don't try to hide the active overlay on a route change event triggered\n\t * by hiding another overlay.\n\t * Called when something other than OverlayManager calls Overlay.hide\n\t * on an overlay that it itself managed by the OverlayManager.\n\t * MUST be called when the stack is not empty.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t */\n\t_onHideOverlayOutsideOverlayManager() {\n\t\tif ( !this.stack.length ) {\n\t\t\treturn;\n\t\t}\n\t\tconst currentRoute = this.stack[0].route,\n\t\t\trouteIsString = typeof currentRoute === 'string',\n\t\t\tcurrentPath = this.router.getPath(),\n\t\t\t// Since routes can be strings or regexes, it's important to do an equality\n\t\t\t// check BEFORE a match check.\n\t\t\trouteIsSame = ( routeIsString && currentPath === currentRoute ) ||\n\t\t\t\tcurrentPath.match( currentRoute );\n\n\t\tthis.hideCurrent = false;\n\n\t\t// If the path hasn't changed then the user didn't close the overlay by\n\t\t// calling history.back() or triggering a route change. We must go back\n\t\t// to get out of the overlay. See T237677.\n\t\tif ( routeIsSame ) {\n\t\t\t// does the route need to change?\n\t\t\tthis.router.back();\n\t\t}\n\t},\n\n\t/**\n\t * Attach overlay to DOM\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to attach\n\t */\n\t_attachOverlay( overlay ) {\n\t\tif ( !overlay.$el.parents().length ) {\n\t\t\tthis.container.appendChild( overlay.$el[0] );\n\t\t}\n\t},\n\t/**\n\t * Show the overlay and bind the '_om_hide' event to _onHideOverlay.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to show\n\t */\n\t_show( overlay ) {\n\t\t// Mark the state so that if the page is refreshed, we don't generate an extra history entry\n\t\t// (see #getSingleton below and T201852).\n\t\t// eslint-disable-next-line no-restricted-properties\n\t\twindow.history.replaceState( MANAGED_STATE, null, window.location.href );\n\n\t\t// the _om_hide event is added to an overlay that is displayed.\n\t\t// It will fire if an Overlay emits a hide event (See attachHideEvent)\n\t\t// in the case where a route change has not occurred (this event is disabled\n\t\t// inside _hideOverlay which is called inside _checkRoute)\n\t\toverlay.once( '_om_hide', this._onHideOverlayOutsideOverlayManager.bind( this ) );\n\n\t\tthis._attachOverlay( overlay );\n\t\toverlay.show();\n\t},\n\n\t/**\n\t * Hide overlay\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {module:mobile.startup/Overlay} overlay to hide\n\t * @param {Function} onBeforeExitCancel to pass to onBeforeExit\n\t * @return {boolean} Whether the overlay has been hidden\n\t */\n\t_hideOverlay( overlay, onBeforeExitCancel ) {\n\t\tlet result;\n\n\t\tfunction exit() {\n\t\t\tresult = true;\n\t\t\toverlay.hide();\n\t\t}\n\n\t\t// remove the callback for updating state when overlay closed using\n\t\t// overlay close button\n\t\toverlay.off( '_om_hide' );\n\n\t\tif ( overlay.options && overlay.options.onBeforeExit ) {\n\t\t\toverlay.options.onBeforeExit( exit, onBeforeExitCancel );\n\t\t} else {\n\t\t\texit();\n\t\t}\n\n\t\t// if closing prevented, reattach the callback\n\t\tif ( !result ) {\n\t\t\toverlay.once( '_om_hide', this._onHideOverlayOutsideOverlayManager.bind( this ) );\n\t\t}\n\n\t\treturn result;\n\t},\n\n\t/**\n\t * Show match's overlay if match is not null.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {Object|null} match Object with factory function's result. null if no match.\n\t */\n\t_processMatch( match ) {\n\t\tconst self = this;\n\n\t\tif ( match ) {\n\t\t\tif ( match.overlay ) {\n\t\t\t\t// if the match is an overlay that was previously opened, reuse it\n\t\t\t\tself._show( match.overlay );\n\t\t\t} else {\n\t\t\t\t// else create an overlay using the factory function result\n\t\t\t\tconst factoryResult = match.factoryResult;\n\t\t\t\t// We were getting errors relating to no factoryResult.\n\t\t\t\t// This should never happen.\n\t\t\t\t// If it does an error should not be thrown.\n\t\t\t\tif ( factoryResult ) {\n\t\t\t\t\tmatch.overlay = factoryResult;\n\t\t\t\t\tattachHideEvent( match.overlay );\n\t\t\t\t\tself._show( factoryResult );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * A callback for Router's `route` event.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {jQuery.Event} ev Event object.\n\t */\n\t_checkRoute( ev ) {\n\t\tconst current = this.stack[0];\n\n\t\t// When entering an overlay for the first time,\n\t\t// the manager should remember the user's scroll position\n\t\t// overlays always open at top of page\n\t\t// and we'll want to restore it later.\n\t\t// This should happen before the call to _matchRoute which will \"show\" the overlay.\n\t\t// The Overlay has similar logic for overlays that are not managed via the overlay.\n\t\tif ( !current ) {\n\t\t\tthis.scrollTop = window.pageYOffset;\n\t\t}\n\n\t\t// if there is an overlay in the stack and it's opened, try to close it\n\t\tif (\n\t\t\tcurrent &&\n\t\t\tcurrent.overlay !== undefined &&\n\t\t\tthis.hideCurrent &&\n\t\t\t!this._hideOverlay( current.overlay, () => {\n\t\t\t\t// if hide prevented, prevent route change event\n\t\t\t\tev.preventDefault();\n\t\t\t} )\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst match = Object.keys( this.entries ).reduce( ( m, id ) => m ||\n\t\t\tthis._matchRoute( ev.path, this.entries[id] ), null );\n\n\t\tif ( !match ) {\n\t\t\t// if hidden and no new matches, reset the stack\n\t\t\tthis.stack = [];\n\t\t\t// restore the scroll position.\n\t\t\twindow.scrollTo( window.pageXOffset, this.scrollTop );\n\t\t}\n\n\t\tthis.hideCurrent = true;\n\t\tthis._processMatch( match );\n\t},\n\n\t/**\n\t * Check if a given path matches one of the existing entries and\n\t * remove it from the stack.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @private\n\t * @param {string} path Path (hash) to check.\n\t * @param {Object} entry Entry object created in OverlayManager#add.\n\t * @return {Object|null} Match object with factory function's result.\n\t *  Returns null if no match.\n\t */\n\t_matchRoute( path, entry ) {\n\t\tlet\n\t\t\tdidMatch,\n\t\t\tcaptures,\n\t\t\tmatch;\n\n\t\tconst\n\t\t\tprevious = this.stack[1],\n\t\t\tself = this;\n\n\t\tif ( typeof entry.route === 'string' ) {\n\t\t\tdidMatch = entry.route === path;\n\t\t\tcaptures = [];\n\t\t} else {\n\t\t\tmatch = path.match( entry.route );\n\t\t\tdidMatch = !!match;\n\t\t\tcaptures = didMatch ? match.slice( 1 ) : [];\n\t\t}\n\n\t\t/**\n\t\t * Returns object to add to stack\n\t\t *\n\t\t * @method\n\t\t * @ignore\n\t\t * @return {Object}\n\t\t */\n\t\tfunction getNext() {\n\t\t\treturn {\n\t\t\t\tpath,\n\t\t\t\t// Important for managing states of things such as the image overlay which change\n\t\t\t\t// overlay routing parameters during usage.\n\t\t\t\troute: entry.route,\n\t\t\t\tfactoryResult: entry.factory.apply( self, captures )\n\t\t\t};\n\t\t}\n\n\t\tif ( didMatch ) {\n\t\t\t// if previous stacked overlay's path matches, assume we're going back\n\t\t\t// and reuse a previously opened overlay\n\t\t\tif ( previous && previous.path === path ) {\n\t\t\t\tself.stack.shift();\n\t\t\t\treturn previous;\n\t\t\t} else {\n\t\t\t\tconst next = getNext();\n\t\t\t\tif ( this.stack[0] && next.path === this.stack[0].path ) {\n\t\t\t\t\t// current overlay path is same as path to check which means overlay\n\t\t\t\t\t// is attempting to refresh so just replace current overlay with new\n\t\t\t\t\t// overlay\n\t\t\t\t\tself.stack[0] = next;\n\t\t\t\t} else {\n\t\t\t\t\tself.stack.unshift( next );\n\t\t\t\t}\n\t\t\t\treturn next;\n\t\t\t}\n\t\t}\n\n\t\treturn null;\n\t},\n\n\t/**\n\t * Add an overlay that should be shown for a specific fragment identifier.\n\t *\n\t * The following code will display an overlay whenever a user visits a URL that\n\t * ends with '#/hi/name'. The value of `name` will be passed to the overlay.\n\t * Note the factory must return an Overlay.\n\t * If the overlay needs to load code asynchronously that should be done inside\n\t * the overlay.\n\t *\n\t *     @example\n\t *     overlayManager.add( /\\/hi\\/(.*)/, function ( name ) {\n\t *         var HiOverlay = M.require( 'HiOverlay' );\n\t *         return new HiOverlay( { name: name } ) );\n\t *     } );\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @param {RegExp|string} route definition that can be a regular\n\t * expression (optionally with parameters) or a string literal.\n\t *\n\t * T238364: Routes should only contain characters allowed by RFC3986 to ensure\n\t * compatibility across browsers. Encode the route with `encodeURIComponent()`\n\t * prior to registering it with OverlayManager if necessary (should probably\n\t * be done with all routes containing user generated characters) to avoid\n\t * inconsistencies with how different browsers encode illegal URI characters:\n\t *\n\t * ```\n\t *   var encodedRoute = encodeURIComponent('ugc < \" ` >');\n\t *\n\t *   overlayManager.add(\n\t *     encodedRoute,\n\t *     function () { return new Overlay(); }\n\t *   );\n\t *\n\t *   window.location.hash = '#' + encodedRoute;\n\t * ```\n\t * The above example shows how to register a string literal route with illegal\n\t * URI characters. Routes registered as a regex will likely NOT have to\n\t * perform any encoding (unless they explicitly contain illegal URI\n\t * characters) as their user generated content portion will likely just be a\n\t * capturing group (e.g. `/\\/hi\\/(.*)/`).\n\t * @param {Function} factory a function returning an overlay\n\t */\n\tadd( route, factory ) {\n\t\tconst self = this,\n\t\t\tentry = {\n\t\t\t\troute,\n\t\t\t\tfactory\n\t\t\t};\n\n\t\tthis.entries[route] = entry;\n\t\t// Check if overlay should be shown for the current path.\n\t\t// The DOM must fully load before we can show the overlay because Overlay relies on it.\n\t\tutil.docReady( () => self._processMatch( self._matchRoute( self.router.getPath(),\n\t\t\tentry ) ) );\n\t},\n\n\t/**\n\t * Replace the currently displayed overlay with a new overlay without changing the\n\t * URL. This is useful for when you want to switch overlays, but don't want to\n\t * change the back button or close box behavior.\n\t *\n\t * @memberof module:mobile.startup/OverlayManager\n\t * @instance\n\t * @param {Object} overlay The overlay to display\n\t */\n\treplaceCurrent( overlay ) {\n\t\tif ( this.stack.length === 0 ) {\n\t\t\tthrow new Error( \"Trying to replace OverlayManager's current overlay, but stack is empty\" );\n\t\t}\n\t\tconst stackOverlay = this.stack[0].overlay;\n\t\tif ( stackOverlay ) {\n\t\t\tthis._hideOverlay( stackOverlay );\n\t\t}\n\t\tthis.stack[0].overlay = overlay;\n\t\tattachHideEvent( overlay );\n\t\tthis._show( overlay );\n\t}\n};\n\n/**\n * Retrieve a singleton instance using 'mediawiki.router'.\n *\n * @memberof module:mobile.startup/OverlayManager\n * @return {module:mobile.startup/OverlayManager}\n */\nOverlayManager.getSingleton = function () {\n\tif ( !overlayManager ) {\n\t\tconst\n\t\t\trouter = __non_webpack_require__( 'mediawiki.router' ),\n\t\t\tcontainer = document.createElement( 'div' ),\n\t\t\t// Note getPath returns hash minus the '#' character:\n\t\t\thash = router.getPath(),\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\tstate = window.history.state;\n\t\tcontainer.className = 'mw-overlays-container';\n\t\tdocument.body.appendChild( container );\n\t\t// If an overlay was loaded by directly navigating to an URL with a hash (e.g. linked from\n\t\t// another page or browser bookmark), generate an extra history entry to allow closing the\n\t\t// overlay without leaving the page (see T201852). Put our marker into the entry state so\n\t\t// that we can detect it if the page is refreshed and do not generate another entry.\n\t\tif ( hash && state !== MANAGED_STATE ) {\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\twindow.history.replaceState( null, null, '#' );\n\t\t\t// eslint-disable-next-line no-restricted-properties\n\t\t\twindow.history.pushState( MANAGED_STATE, null, `#${ hash }` );\n\t\t}\n\t\toverlayManager = new OverlayManager( router, container );\n\t}\n\treturn overlayManager;\n};\n\nOverlayManager.test = {\n\tMANAGED_STATE,\n\t__clearCache: () => {\n\t\toverlayManager = null;\n\t}\n};\nmodule.exports = OverlayManager;\n","const\n\tHTML = mw.html,\n\tutil = require( './util' );\n\nclass Page {\n\t/**\n\t * @class module:mobile.startup/Page\n\t * @classdesc Mobile page view object\n\t * @param {Object} options Configuration options\n\t * @param {number} options.id Page ID. The default value of 0 represents a\n\t * new or missing page. Be sure to override it to avoid side effects.\n\t * @param {string} options.title Title of the page. It includes prefix where needed and\n\t * is human readable, e.g. Talk:The man who lived.\n\t * @param {Object} options.titleObj\n\t * @param {string} options.displayTitle HTML title of the page for display. Falls back\n\t * to defaults.title (escaped) if no value is provided. Must be safe HTML!\n\t * @param {number} options.namespaceNumber the number of the\n\t *  namespace the page belongs to\n\t * @param {Object} options.protection List of permissions as returned by API,\n\t * e.g. [{ edit: ['*'] }]\n\t * @param {string} options.url\n\t * @param {string} options.wikidataDescription\n\t * @param {boolean} options.isMainPage Whether the page is the Main Page.\n\t * @param {boolean} options.isMissing Whether the page exists in the wiki.\n\t * @param {string} options.anchor\n\t * @param {string} [options.relevantTitle] associated with page.\n\t *  For example Special:WhatLinksHere/Foo would be associated with the page `Foo`.\n\t * @param {number} options.revId  Revision ID. See `wgRevisionId`.\n\t * @param {boolean} options.isWatched Whether the page is being watched\n\t * @param {Object} options.thumbnail thumbnail definition corresponding to page image\n\t * @param {boolean} options.thumbnail.isLandscape whether the image is in\n\t *  landscape format\n\t * @param {number} options.thumbnail.width of image in pixels.\n\t * @param {number} options.thumbnail.height of image in pixels.\n\t * @param {string} options.thumbnail.source url for image\n\t */\n\tconstructor( options ) {\n\t\tconst title = options.title || '';\n\t\tutil.extend( this, {\n\t\t\tid: options.id || 0,\n\t\t\t// FIXME: Deprecate title property as it can be derived from titleObj\n\t\t\t// using getPrefixedText\n\t\t\ttitle,\n\t\t\trelevantTitle: options.relevantTitle || title,\n\t\t\ttitleObj: options.titleObj,\n\t\t\tdisplayTitle: options.displayTitle || HTML.escape( title ),\n\t\t\tnamespaceNumber: options.namespaceNumber || 0,\n\t\t\tprotection: options.protection,\n\t\t\turl: options.url || mw.util.getUrl( title ),\n\t\t\twikidataDescription: options.wikidataDescription,\n\t\t\t_isMainPage: options.isMainPage || false,\n\t\t\tisMissing: ( options.isMissing !== undefined ) ?\n\t\t\t\toptions.isMissing : options.id === 0,\n\t\t\tanchor: options.anchor,\n\t\t\trevId: options.revId,\n\t\t\t_isWatched: options.isWatched,\n\t\t\tthumbnail: ( Object.prototype.hasOwnProperty.call( options, 'thumbnail' ) ) ?\n\t\t\t\toptions.thumbnail : false\n\t\t} );\n\n\t\tif ( this.thumbnail && this.thumbnail.width ) {\n\t\t\tthis.thumbnail.isLandscape = this.thumbnail.width > this.thumbnail.height;\n\t\t}\n\t}\n\n\t/**\n\t * Retrieve the title that should be displayed to the user\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {string} HTML\n\t */\n\tgetDisplayTitle() {\n\t\treturn this.displayTitle;\n\t}\n\n\t/**\n\t * Determine if current page is in a specified namespace\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @param {string} namespace Name of namespace\n\t * @return {boolean}\n\t */\n\tinNamespace( namespace ) {\n\t\treturn this.namespaceNumber === mw.config.get( 'wgNamespaceIds' )[namespace];\n\t}\n\n\t/**\n\t * Determines if content model is wikitext\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisWikiText() {\n\t\treturn mw.config.get( 'wgPageContentModel' ) === 'wikitext';\n\t}\n\n\t/**\n\t * Check if the visual editor is available on this page\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisVEAvailable() {\n\t\treturn !!mw.config.get( 'wgVisualEditorConfig' ) &&\n\t\t\t!mw.config.get( 'wgVisualEditorDisabledByHook' ) &&\n\t\t\tthis.isWikiText();\n\t}\n\n\t/**\n\t * Check if the visual editor in visual mode is available on this page\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisVEVisualAvailable() {\n\t\tif ( !this.isVEAvailable() ) {\n\t\t\treturn false;\n\t\t}\n\t\tconst config = mw.config.get( 'wgVisualEditorConfig' );\n\t\tconst visualEditorNamespaces = config.namespaces || [];\n\n\t\treturn visualEditorNamespaces.indexOf( mw.config.get( 'wgNamespaceNumber' ) ) !== -1;\n\t}\n\n\t/**\n\t * Check if the visual editor in source mode is available on this page\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisVESourceAvailable() {\n\t\treturn this.isVEAvailable() &&\n\t\t\tmw.config.get( 'wgMFEnableVEWikitextEditor' );\n\t}\n\n\t/**\n\t * Checks whether the current page is the main page\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisMainPage() {\n\t\treturn this._isMainPage;\n\t}\n\n\t/**\n\t * Checks whether the current page is watched\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {boolean}\n\t */\n\tisWatched() {\n\t\treturn this._isWatched;\n\t}\n\n\t/**\n\t * Return the latest revision id for this page\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {number}\n\t */\n\tgetRevisionId() {\n\t\treturn this.revId;\n\t}\n\n\t/**\n\t * Return prefixed page title\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {string}\n\t */\n\tgetTitle() {\n\t\treturn this.title;\n\t}\n\n\t/**\n\t * return namespace id\n\t *\n\t * @memberof module:mobile.startup/Page\n\t * @return {number} namespace Number\n\t */\n\tgetNamespaceId() {\n\t\tlet nsId;\n\t\tconst args = this.title.split( ':' );\n\n\t\tif ( args[1] ) {\n\t\t\tnsId = mw.config.get( 'wgNamespaceIds' )[ args[0].toLowerCase().replace( ' ', '_' ) ] || 0;\n\t\t} else {\n\t\t\tnsId = 0;\n\t\t}\n\t\treturn nsId;\n\t}\n}\n\nmodule.exports = Page;\n","const\n\tThumbnail = require( './Thumbnail' ),\n\tHEADING_SELECTOR = mw.config.get( 'wgMFMobileFormatterHeadings', [ 'h1', 'h2', 'h3', 'h4', 'h5' ] ).join( ',' ),\n\tEXCLUDE_THUMBNAIL_CLASS_SELECTORS = [ 'noviewer', 'metadata' ],\n\tNOT_SELECTORS = EXCLUDE_THUMBNAIL_CLASS_SELECTORS.map( ( excludeSelector ) => `:not(.${ excludeSelector })` ).join( '' ),\n\tTHUMB_SELECTOR = [ 'a.image', 'a.thumbimage, a.mw-file-description' ].map(\n\t\t( selector ) => `${ selector }${ NOT_SELECTORS }`\n\t).join( ',' );\n\nclass PageHTMLParser {\n\t/**\n\t * @constructor\n\t * @class module:mobile.startup/PageHTMLParser\n     * @classdesc Parses an article and converts it into a queriable object.\n\t * @param {jQuery.Object} $container Used when parsing to find children within\n\t * this container\n\t */\n\tconstructor( $container ) {\n\t\tthis.$el = $container;\n\n\t\t// T220751: Cache headings as $el.find is a very expensive call.\n\t\t/** @private */\n\t\tthis.$headings = this.$el.find( HEADING_SELECTOR );\n\t}\n\n\t/**\n\t * Find the heading in the page.\n\t * This has the benefit of excluding any additional h2s and h3s that may\n\t * have been added programatically.\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @param {number} sectionIndex as defined by the PHP parser.\n\t *  It should correspond to the section id\n\t *  used in the edit link for the section.\n\t *  Note, confusingly, this is different from section \"ID\" which is\n\t * used in methods\n\t * @return {jQuery.Object}\n\t */\n\tfindSectionHeadingByIndex( sectionIndex ) {\n\t\tif ( sectionIndex < 1 ) {\n\t\t\t// negative indexes will search from the end, which is behaviour we do not want.\n\t\t\t// return an empty set when this happens.\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\treturn $( [] );\n\t\t} else {\n\t\t\treturn this.$headings\n\t\t\t\t// Headings must strictly be a child element of a section element\n\t\t\t\t// or the parser-output.\n\t\t\t\t// Not an ancestor!\n\t\t\t\t.filter( '.mw-parser-output > *, [class^=\"mf-section-\"] > *' ).eq( sectionIndex - 1 );\n\t\t}\n\t}\n\n\t/**\n\t * Finds all child elements that match the selector in a given section or subsection.\n\t * Returns any direct child elements that match the selector,\n\t * (i.e. searches only one level deep)\n\t * as well as any elements that match the selector within those children.\n\t * If the Page has no headings (e.g. a stub),\n\t * then the search will target all nodes within the page.\n\t *\n\t * This code should work on desktop (PHP parser HTML)\n\t * as well as mobile formatted HTML (PHP parser + MobileFormatter)\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @param {number} sectionIndex as defined by the PHP parser. It should correspond to\n\t *  the section id used in the edit link for the section.\n\t *  Note, confusingly, this is different from section \"ID\" which is\n\t *  used in methods\n\t * @param {string} selector to match\n\t * @return {jQuery.Object}\n\t */\n\tfindChildInSectionLead( sectionIndex, selector ) {\n\t\tlet $heading, $nextHeading;\n\n\t\tconst headingSelector = HEADING_SELECTOR;\n\n\t\tfunction withNestedChildren( $matchingNodes ) {\n\t\t\treturn $matchingNodes.find( selector ).addBack();\n\t\t}\n\n\t\tif ( sectionIndex === 0 ) {\n\t\t\t// lead is easy\n\t\t\tconst $lead = this.getLeadSectionElement();\n\t\t\tif ( $lead && $lead.length ) {\n\n\t\t\t\t// Handle nested sections in Parsoid wikitext parset opt-in scenario.\n\t\t\t\tconst $nestedSection = $lead.find( 'section[data-mw-section-id=\"0\"]' );\n\t\t\t\tif ( $nestedSection.length ) {\n\t\t\t\t\treturn withNestedChildren( $nestedSection.children( selector ) );\n\t\t\t\t}\n\n\t\t\t\treturn withNestedChildren( $lead.children( selector ) );\n\t\t\t} else {\n\t\t\t\t$heading = this.findSectionHeadingByIndex( 1 );\n\t\t\t\treturn $heading.length ? withNestedChildren( $heading.prevAll( selector ) ) :\n\t\t\t\t\t// this page is a stub so search entire page\n\t\t\t\t\tthis.$el.find( selector );\n\t\t\t}\n\t\t}\n\n\t\t// find heading associated with the section by looking at its\n\t\t// index position in the article\n\t\t// section ids relate to the element position in the page and the first heading\n\t\t// lead has been dealt with above, so first heading corresponds to section 1,\n\t\t// the first heading in the article.\n\t\t$heading = this.findSectionHeadingByIndex( sectionIndex );\n\n\t\t// If section-heading is present on the heading,\n\t\t// then we know the page has been MobileFormatted\n\t\t// and that this is a wrapped section\n\t\tif ( $heading.hasClass( 'section-heading' ) ) {\n\t\t\t// get content of section\n\t\t\tconst $el = $heading.next();\n\t\t\t// inside section find the first heading\n\t\t\t$nextHeading = $el.find( headingSelector ).eq( 0 );\n\t\t\treturn $nextHeading.length ?\n\t\t\t\t// find all amboxes before the next heading\n\t\t\t\twithNestedChildren( $nextHeading.prevAll( selector ) ) :\n\t\t\t\t// There is no subheadings inside\n\t\t\t\t// Grab all issues in section\n\t\t\t\twithNestedChildren( $el.children( selector ) );\n\t\t} else {\n\t\t\t// the heading relates to a subsection (or unwrapped desktop section),\n\t\t\t// so grab elements between this and the next one\n\t\t\t$nextHeading = $heading.eq( 0 ).nextAll( headingSelector ).eq( 0 );\n\t\t\treturn $heading.nextUntil( $nextHeading, selector );\n\t\t}\n\t}\n\n\t/**\n\t * Get the lead section of the page view.\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @return {jQuery.Object|null}\n\t */\n\tgetLeadSectionElement() {\n\t\t/*\n\t\t * The page is formatted as follows:\n\t\t * <div id=\"bodyContent\">\n\t\t *   <!-- content of the page.. -->\n\t\t *   <div id=\"mw-content-text\">\n\t\t *     <div class=\"mf-section-0\">lead section</div>\n\t\t *     <h2></h2>\n\t\t *     <div class=\"mf-section-1\">second section</div>\n\t\t *   </div>\n\t\t * </div>\n\t\t */\n\t\tconst $leadSection = this.$el.find( '.mf-section-0' );\n\n\t\tif ( $leadSection.length ) {\n\t\t\treturn $leadSection;\n\t\t}\n\t\t// no lead section found\n\t\treturn null;\n\t}\n\n\t/**\n\t * Returns a Thumbnail object from an anchor element containing an image or\n\t * null if not valid.\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @param {jQuery} $a Anchor element that contains the image.\n\t * @return {Thumbnail|null}\n\t */\n\tgetThumbnail( $a ) {\n\t\tconst notSelector = '.' + EXCLUDE_THUMBNAIL_CLASS_SELECTORS.join( ',.' ),\n\t\t\t$lazyImage = $a.find( '.lazy-image-placeholder' ),\n\t\t\thref = $a.attr( 'href' ),\n\t\t\turl = href && new URL( href, location.href ),\n\t\t\tlegacyTitle = url && url.searchParams.get( 'title' ),\n\t\t\tmatch = url && url.pathname.match( /[^/]+$/ );\n\n\t\t// Parents need to be checked as well.\n\t\tlet valid = $a.parents( notSelector ).length === 0 &&\n\t\t\t$a.find( notSelector ).length === 0;\n\n\t\t// filter out invalid lazy loaded images if so far image is valid\n\t\tif ( $lazyImage.length && valid ) {\n\t\t\t// if the regex matches it means the image has one of the classes\n\t\t\t// thus we must invert the result\n\t\t\tvalid = !new RegExp( '\\\\b(' + EXCLUDE_THUMBNAIL_CLASS_SELECTORS.join( '|' ) + ')\\\\b' )\n\t\t\t\t.test( $lazyImage.data( 'class' ) );\n\t\t}\n\n\t\tif ( valid && ( legacyTitle !== null || match ) ) {\n\t\t\treturn new Thumbnail( {\n\t\t\t\tel: $a,\n\t\t\t\tfilename: mw.util.percentDecodeFragment(\n\t\t\t\t\tlegacyTitle !== null ? legacyTitle : match[0]\n\t\t\t\t)\n\t\t\t} );\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Return all the thumbnails in the article.\n\t * Images which have a class or link container (.image|.thumbimage)\n\t * that matches one of the items of the constant EXCLUDE_THUMBNAIL_CLASS_SELECTORS\n\t * will be excluded.\n\t * A thumbnail nested inside one of these classes will still be returned.\n\t * e.g. `<div class=\"noviewer\"><a class=\"image\"><img></a></div>` is not a valid thumbnail\n\t * `<a class=\"image noviewer\"><img></a>` is not a valid thumbnail\n\t * `<a class=\"image\"><img class=\"noviewer\"></a>` is not a valid thumbnail\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @param {jQuery} [$el] Container to search, defaults to this.$el.\n\t * @return {Thumbnail[]}\n\t */\n\tgetThumbnails( $el ) {\n\t\tconst\n\t\t\tself = this,\n\t\t\tthumbs = [];\n\n\t\t$el = $el || this.$el;\n\n\t\tconst $thumbs = $el.find( THUMB_SELECTOR );\n\n\t\t$thumbs.each( function () {\n\t\t\tconst $a = $el.find( this );\n\t\t\tconst thumb = self.getThumbnail( $a );\n\n\t\t\tif ( thumb ) {\n\t\t\t\tthumbs.push( thumb );\n\t\t\t}\n\t\t} );\n\t\treturn thumbs;\n\t}\n\n\t/**\n\t * Returns a jQuery object representing all redlinks on the page.\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @return {jQuery.Object}\n\t */\n\tgetRedLinks() {\n\t\treturn this.$el.find( '.new' );\n\t}\n\n\t/**\n\t * Returns an object consistent with MediaWiki API representing languages\n\t * associated with the page in the user's current language.\n\t *\n\t * @memberof module:mobile.startup/PageHTMLParser\n\t * @param {string} pageTitle to fallback to if none found\n\t * @return {Object} containing langlinks\n\t *   and variant links as defined @ https://en.m.wikipedia.org/w/api.php?action=help&modules=query%2Blanglinks\n\t */\n\tgetLanguages( pageTitle ) {\n\t\tconst mapLinkToLanguageObj = ( node ) => {\n\t\t\tconst DELIMITER = ' – ';\n\t\t\t// Name of language (e.g. עברית for Hebrew)\n\t\t\tconst autonym = node.textContent;\n\t\t\t// The name of the language in the current language\n\t\t\t// e.g. for english this would be Hebrew\n\t\t\tlet langname;\n\t\t\tlet title = node.getAttribute( 'title' ) || pageTitle;\n\t\t\tif ( title.indexOf( DELIMITER ) > -1 ) {\n\t\t\t\ttitle = title.split( DELIMITER );\n\t\t\t\tlangname = title.pop();\n\t\t\t\ttitle = title.join( DELIMITER );\n\t\t\t}\n\t\t\tif ( !langname ) {\n\t\t\t\tlangname = autonym;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tlang: node.getAttribute( 'hreflang' ),\n\t\t\t\tautonym,\n\t\t\t\tlangname,\n\t\t\t\ttitle,\n\t\t\t\turl: node.getAttribute( 'href' )\n\t\t\t};\n\t\t};\n\t\treturn {\n\t\t\tlanguages: Array.prototype.map.call(\n\t\t\t\tdocument.querySelectorAll( '#p-lang .interlanguage-link a' ),\n\t\t\t\tmapLinkToLanguageObj\n\t\t\t),\n\t\t\tvariants: Array.prototype.map.call(\n\t\t\t\tdocument.querySelectorAll( '#p-variants li a' ),\n\t\t\t\tmapLinkToLanguageObj\n\t\t\t)\n\t\t};\n\t}\n}\n\n/**\n * Selector for matching headings\n *\n * @memberof PageHTMLParser\n */\nPageHTMLParser.HEADING_SELECTOR = HEADING_SELECTOR;\n\n/**\n * Selector for thumbnails.\n *\n * @memberof PageHTMLParser\n */\nPageHTMLParser.THUMB_SELECTOR = THUMB_SELECTOR;\n\nmodule.exports = PageHTMLParser;\n","const util = require( './util.js' ),\n\tmfExtend = require( './mfExtend' ),\n\tView = require( './View' ),\n\tbrowser = require( './Browser' ).getSingleton();\n\n/**\n * List of items page view\n *\n * @class PageList\n * @extends module:mobile.startup/View\n */\nfunction PageList() {\n\tView.apply( this, arguments );\n}\n\nmfExtend( PageList, View, {\n\t/**\n\t * @memberof PageList\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Page[]} defaults.pages Array of Page objects. These should match\n\t *                              the Page model and not necessarily the\n\t *                              underlying API format used.\n\t * E.g. [\n\t *   {\n\t *     heading: \"<strong>C</strong>laude Monet\",\n\t *     id: undefined,\n\t *     title: \"Claude Monet\",\n\t *     displayTitle: \"<i>Claude Monet</i>\",\n\t *     url: \"/wiki/Claude_Monet\",\n\t *     thumbnail: {\n\t *       height: 62,\n\t *       source: \"http://127.0.0.1:8080/images/thumb/thumb.jpg\",\n\t *       width: 80,\n\t *       isLandscape: true\n\t *     }\n\t *   }\n\t * ]\n\t */\n\tdefaults: {\n\t\tpages: []\n\t},\n\t/**\n\t * Render page images for the existing page list. Assumes no page images have been loaded.\n\t *\n\t * @memberof PageList\n\t * @instance\n\t */\n\trenderPageImages() {\n\t\tconst self = this;\n\n\t\tsetTimeout( () => {\n\t\t\tself.$el.find( '.list-thumb' ).each( function () {\n\t\t\t\tconst style = self.$el.find( this ).data( 'style' );\n\t\t\t\tself.$el.find( this ).attr( 'style', style );\n\t\t\t} );\n\t\t\t// Delay an unnecessary load of images on mobile (slower?) connections\n\t\t\t// In particular on search results which can be regenerated quickly.\n\t\t}, browser.isWideScreen() ? 0 : 1000 );\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof PageList\n\t * @instance\n\t */\n\tpostRender() {\n\t\tthis.renderPageImages();\n\t},\n\ttemplate: util.template( `\n<ul class=\"mw-mf-page-list thumbs actionable\">\n\t{{#pages}}\n\t\t{{>item}}\n\t{{/pages}}\n</ul>\n\t` ),\n\t/**\n\t * @memberof PageList\n\t * @instance\n\t */\n\ttemplatePartials: {\n\t\t// The server uses a very different structure in\n\t\t// SpecialMobileEditWatchlist.getLineHtml(). Be aware of these differences\n\t\t// when updating server rendered items.\n\t\titem: util.template( `\n<li title=\"{{title}}\" data-id=\"{{id}}\" class=\"page-summary\">\n  <a href=\"{{url}}\" class=\"title {{#isMissing}}new{{/isMissing}}\"\n    {{#anchor}}name=\"{{anchor}}\"{{/anchor}}\n    {{#latitude}}data-latlng=\"{{latitude}},{{longitude}}\"{{/latitude}}\n    data-title=\"{{title}}\">\n    <div class=\"list-thumb\n      {{#thumbnail.isLandscape}}list-thumb-y{{/thumbnail.isLandscape}}\n      {{^thumbnail.isLandscape}}list-thumb-x{{/thumbnail.isLandscape}}\"\n      {{#thumbnail}}data-style=\"background-image: url( {{thumbnail.source}} )\"{{/thumbnail}}>\n      {{^thumbnail}}<span class=\"mf-icon-image\"></span>{{/thumbnail}}\n\t</div>\n    <h3>{{{displayTitle}}}</h3>\n    {{#wikidataDescription}}\n    <div class=\"wikidata-description\">{{wikidataDescription}}</div>\n    {{/wikidataDescription}}\n    {{#proximity}}\n    <div class=\"info proximity\">{{proximity}}</div>\n    {{/proximity}}\n  </a>\n</li>\n\t` )\n\t}\n} );\n\nmodule.exports = PageList;\n","const browser = require( './Browser' ).getSingleton(),\n\tView = require( './View' ),\n\tutil = require( './util' ),\n\tcurrentPage = require( './currentPage' ),\n\teventBus = require( './eventBusSingleton' ),\n\tmfExtend = require( './mfExtend' );\n\nlet skin;\n\n/**\n * Representation of the current skin being rendered.\n *\n * @class Skin\n * @extends module:mobile.startup/View\n * @uses Browser\n * @uses Page\n * @fires Skin#click\n * @param {Object} params Configuration options\n * @param {OO.EventEmitter} params.eventBus Object used to listen for\n * @param {Page} params.page\n * scroll:throttled, resize:throttled, and section-toggled events\n */\nfunction Skin( params ) {\n\tconst options = util.extend( {}, params );\n\n\tthis.page = options.page;\n\tthis.name = options.name;\n\tthis.eventBus = options.eventBus;\n\toptions.isBorderBox = false;\n\tView.call( this, options );\n}\n\nmfExtend( Skin, View, {\n\t/**\n\t * @memberof Skin\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {Page} defaults.page page the skin is currently rendering\n\t */\n\tdefaults: {\n\t\tpage: undefined\n\t},\n\n\t/**\n\t * @inheritdoc\n\t * @memberof Skin\n\t * @instance\n\t */\n\tpostRender() {\n\t\tconst $el = this.$el;\n\n\t\tif ( browser.supportsTouchEvents() ) {\n\t\t\t$el.addClass( 'touch-events' );\n\t\t}\n\n\t\t/**\n\t\t * Fired when the skin is clicked.\n\t\t *\n\t\t * @event Skin#click\n\t\t */\n\t\tthis.$el.find( '#mw-mf-page-center' ).on( 'click', ( ev ) => {\n\t\t\tthis.emit( 'click', ev );\n\t\t} );\n\t},\n\n\t/**\n\t * @memberof Skin\n\t * @throws {Error} if mediawiki message is in unexpected format.\n\t * @return {jQuery.Object} a list of links\n\t */\n\tgetLicenseLinks() {\n\t\tconst mobileLicense = mw.message( 'mobile-frontend-license-links' );\n\t\tconst mobileMsgExists = mobileLicense.exists() && mobileLicense.text();\n\t\tconst userLanguage = mw.config.get( 'wgUserLanguage' );\n\t\tif ( userLanguage === 'qqx' ) {\n\t\t\t// Special handling for qqx code so we can easily debug what's going on here.\n\t\t\treturn mobileLicense.parseDom();\n\t\t} else {\n\t\t\treturn mobileMsgExists ? mobileLicense.parseDom() : this.$el.find( '#footer-info-copyright a' ).clone();\n\t\t}\n\t},\n\t/**\n\t * Returns the appropriate license message including links/name to\n\t * terms of use (if any) and license page\n\t *\n\t * @memberof Skin\n\t * @instance\n\t * @return {string|undefined}\n\t */\n\tgetLicenseMsg() {\n\t\tconst $licenseLinks = this.getLicenseLinks();\n\n\t\tlet licenseMsg;\n\t\tif ( $licenseLinks.length ) {\n\t\t\tconst licensePlural = mw.language.convertNumber(\n\t\t\t\t$licenseLinks.filter( 'a' ).length\n\t\t\t);\n\n\t\t\tif ( this.$el.find( '#footer-places-terms-use' ).length > 0 ) {\n\n\t\t\t\tconst $termsLink = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-terms-link',\n\t\t\t\t\tthis.$el.find( '#footer-places-terms-use a' ).attr( 'href' )\n\t\t\t\t).parseDom();\n\t\t\t\tlicenseMsg = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-licensing-with-terms',\n\t\t\t\t\t$termsLink,\n\t\t\t\t\t$licenseLinks,\n\t\t\t\t\tlicensePlural\n\t\t\t\t).parse();\n\t\t\t} else {\n\t\t\t\tlicenseMsg = mw.message(\n\t\t\t\t\t'mobile-frontend-editor-licensing',\n\t\t\t\t\t$licenseLinks,\n\t\t\t\t\tlicensePlural\n\t\t\t\t).parse();\n\t\t\t}\n\t\t}\n\n\t\treturn licenseMsg;\n\t}\n} );\n\n/**\n * Get a skin singleton\n *\n * @return {Skin}\n */\nSkin.getSingleton = function () {\n\tif ( !skin ) {\n\t\tskin = new Skin( {\n\t\t\tel: 'body',\n\t\t\tpage: currentPage(),\n\t\t\teventBus\n\t\t} );\n\t}\n\treturn skin;\n};\nmodule.exports = Skin;\n","const\n\tmfExtend = require( './mfExtend' ),\n\tutil = require( './util' ),\n\tView = require( './View' );\n\n/**\n * Representation of a thumbnail\n *\n * @class Thumbnail\n * @extends module:mobile.startup/View\n * @param {Object} options\n */\nfunction Thumbnail( options ) {\n\tView.call( this,\n\t\tutil.extend( { isBorderBox: false }, options )\n\t);\n}\n\nmfExtend( Thumbnail, View, {\n\t/**\n\t * @memberof Thumbnail\n\t * @instance\n\t * @mixes module:mobile.startup/View#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {string} defaults.filename uri decoded filename including File: prefix\n\t *  associated with thumbnail\n\t */\n\tdefaults: {\n\t\tfilename: undefined\n\t},\n\t/**\n\t * @inheritdoc\n\t * @memberof Thumbnail\n\t * @instance\n\t */\n\tpostRender() {\n\t\tthis.options.description = this.$el.siblings( '.thumbcaption, figcaption' )\n\t\t\t.prop( 'innerText' ) || '';\n\t},\n\t/**\n\t * Obtain description for thumbnail\n\t *\n\t * @memberof Thumbnail\n\t * @instance\n\t * @return {string}\n\t */\n\tgetDescription() {\n\t\treturn this.options.description;\n\t},\n\t/**\n\t * Return the page title for the thumbnail\n\t *\n\t * @memberof Thumbnail\n\t * @instance\n\t * @return {string}\n\t */\n\tgetFileName() {\n\t\treturn this.options.filename;\n\t}\n} );\n\nmodule.exports = Thumbnail;\n","/* global $ */\nconst util = require( './util' ),\n\tmfExtend = require( './mfExtend' ),\n\t// Cached regex to split keys for `delegate`.\n\tdelegateEventSplitter = /^(\\S+)\\s*(.*)$/;\n\nlet idCounter = 0;\n\n/**\n * Generate a unique integer id (unique within the entire client session).\n * Useful for temporary DOM ids.\n *\n * @private\n * @param {string} prefix Prefix to be used when generating the id.\n * @return {string}\n */\nfunction uniqueId( prefix ) {\n\tconst id = ( ++idCounter ).toString();\n\treturn prefix ? prefix + id : id;\n}\n\n/**\n * Should be extended using extend().\n *\n * When options contains el property, this.$el in the constructed object\n * will be set to the corresponding jQuery object. Otherwise, this.$el\n * will be an empty div.\n *\n * When extended using extend(), if the extended prototype contains\n * template property, this.$el will be filled with rendered template (with\n * options parameter used as template data).\n *\n * template property can be a string which will be passed to mw.template.compile()\n * or an object that has a render() function which accepts an object with\n * template data as its argument (similarly to an object created by\n * mw.template.compile()).\n *\n * You can also define a defaults property which should be an object\n * containing default values for the template (if they're not present in\n * the options parameter).\n *\n * If this.$el is not a jQuery object bound to existing DOM element, the\n * view can be attached to an element using appendTo(), prependTo(),\n * insertBefore(), insertAfter() proxy functions.\n *\n * append(), prepend(), before(), after() can be used to modify $el. on()\n * can be used to bind events.\n *\n * You can also use declarative DOM events binding by specifying an `events`\n * map on the class. The keys will be 'event selector' and the value can be\n * either the name of a method to call, or a function. All methods and\n * functions will be executed on the context of the View.\n *\n * Inspired from Backbone.js\n * https://github.com/jashkenas/backbone/blob/master/backbone.js#L1128\n *\n * Example:\n * ```js\n *     var\n *       MyComponent = View.extend( {\n *         edit: function ( ev ) {\n *           //...\n *         },\n *         save: function ( ev ) {\n *           //...\n *         }\n *       } ),\n *       instance = new MyComponent({\n *         events: {\n *           'mousedown .title': 'edit',\n *           'click .button': 'save',\n *           'click .open': function(e) { ... }\n *         }\n *       });\n * ```\n *\n * Example:\n * ```js\n *     var View, section;\n *     function Section( options ) {\n *       var defaultOptions = {\n *         events: {\n *           // ...\n *         }\n *       }\n *       View.call( this, util.extends( {}, defaultOptions, options ) );\n *     }\n *     View = require( './View' );\n *     require( './mfExtend' )( Section, View, {\n *       template: mw.template.compile( \"&lt;h2&gt;{{title}}&lt;/h2&gt;\" ),\n *     } );\n *     section = new Section( { title: 'Test', text: 'Test section body' } );\n *     section.appendTo( 'body' );\n * ```\n *\n * @class module:mobile.startup/View\n * @memberof module:mobile.startup/View\n * @classdesc Describes a component for rendering.\n * @mixes OO.EventEmitter\n */\n\nfunction View() {\n\tthis.initialize.apply( this, arguments );\n}\nOO.mixinClass( View, OO.EventEmitter );\nmfExtend( View, {\n\t/**\n\t * Name of tag that contains the rendered template\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @property {string} tagName\n\t */\n\ttagName: 'div',\n\t/**\n\t * Tells the View to ignore tagName and className when constructing the element\n\t * and to rely solely on the template\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @property {boolean} isTemplateMode\n\t */\n\tisTemplateMode: false,\n\t/**\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @property {any}\n\t * Specifies the template used in render(). Object|string\n\t */\n\ttemplate: undefined,\n\n\t/**\n\t * Specifies partials (sub-templates) for the main template. Example:\n\t *\n\t *     @example\n\t *     // example content for the \"some\" template (sub-template will be\n\t *     // inserted where {{>content}} is):\n\t *     // <h1>Heading</h1>\n\t *     // {{>content}}\n\t *\n\t *     oo.mfExtend( SomeView, View, {\n\t *       template: util.template( '<source-code>' ),\n\t *       templatePartials: { content: util.template( '<source-code>' ) }\n\t *     }\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @property {Object}\n\t */\n\ttemplatePartials: {},\n\n\t/**\n\t * A set of default options that are merged with options passed into the initialize\n\t * function.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @property {Object} defaults Default options hash.\n\t * @property {jQuery.Object|string} [defaults.el] jQuery selector to use for rendering.\n\t * @property {boolean} [defaults.skipTemplateRender] Whether to enhance views already in\n\t * DOM. When enabled, the template is disabled so that it is not rendered in the DOM.\n\t * Use in conjunction with View::defaults.$el to associate the View with an existing\n\t * already rendered element in the DOM.\n\t */\n\tdefaults: {},\n\n\t/**\n\t * Run once during construction to set up the View\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {Object} options Object passed to the constructor.\n\t * @param {Object.<string, string>} [options.events]\n\t */\n\tinitialize( options ) {\n\t\tconst self = this;\n\n\t\tOO.EventEmitter.call( this );\n\t\toptions = util.extend( {}, this.defaults, options );\n\t\tthis.options = options;\n\t\t// Assign a unique id for dom events binding/unbinding\n\t\tthis.cid = uniqueId( 'view' );\n\n\t\t// TODO: if template compilation is too slow, don't compile them on a\n\t\t// per object basis, but don't worry about it now (maybe add cache to\n\t\t// M.template.compile())\n\t\tif ( typeof this.template === 'string' ) {\n\t\t\tthis.template = mw.template.compile( this.template );\n\t\t}\n\n\t\tif ( options.el ) {\n\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\tthis.$el = $( options.el );\n\t\t} else {\n\t\t\tthis.$el = this.parseHTML( '<' + this.tagName + '>' );\n\t\t}\n\n\t\t// Make sure the element is ready to be manipulated\n\t\tif ( this.$el.length ) {\n\t\t\tthis._postInitialize( options );\n\t\t} else {\n\t\t\tutil.docReady( () => {\n\t\t\t\t// Note the element may not be in the document so must use global jQuery here\n\t\t\t\tself.$el = $( options.el );\n\t\t\t\tself._postInitialize( options );\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Called when this.$el is ready.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @private\n\t * @param {Object} props\n\t */\n\t_postInitialize( props ) {\n\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\tthis.$el.addClass( props.className );\n\t\t// border-box will be added provided this flag is not set\n\t\tif ( props.isBorderBox !== false ) {\n\t\t\tthis.$el.addClass( 'view-border-box' );\n\t\t}\n\n\t\tthis.render( {} );\n\t},\n\n\t/**\n\t * Function called before the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t */\n\tpreRender() {\n\t},\n\n\t/**\n\t * Function called after the view is rendered. Can be redefined in\n\t * objects that extend View.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t */\n\tpostRender() {\n\t},\n\n\t/**\n\t * Fill this.$el with template rendered using data if template is set.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {Object} data Template data. Will be merged into the view's\n\t * options\n\t * @chainable\n\t */\n\trender( data ) {\n\t\tlet $el, html;\n\t\tutil.extend( this.options, data );\n\t\tthis.preRender();\n\t\tthis.undelegateEvents();\n\t\tif ( this.template && !this.options.skipTemplateRender ) {\n\t\t\thtml = this.template.render( this.options, this.templatePartials );\n\t\t\tif ( this.isTemplateMode ) {\n\t\t\t\t$el = $( html );\n\t\t\t\tthis.$el.replaceWith( $el );\n\t\t\t\tthis.$el = $el;\n\t\t\t} else {\n\t\t\t\tthis.$el.html( html );\n\t\t\t}\n\t\t}\n\t\tthis.postRender();\n\t\tthis.delegateEvents();\n\t\treturn this;\n\t},\n\n\t/**\n\t * Set callbacks for events.\n\t *\n\t * `this.options.events` is a hash of pairs:\n\t *\n\t * ```\n\t * { 'event selector': 'callback' }\n\t *\n\t * {\n\t *   'mousedown .title': 'edit',\n\t *   'click .button': 'save',\n\t *   'click .open': function(e) { ... }\n\t * }\n\t * ```\n\t *\n\t * Callbacks will be bound to the view, with `this` set properly.\n\t * Uses event delegation for efficiency.\n\t * Omitting the selector binds the event to `this.el`.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {Object} events Optionally set this events instead of the ones on this.\n\t */\n\tdelegateEvents( events ) {\n\t\tlet match, key, method;\n\t\tevents = events || this.options.events;\n\t\tif ( events ) {\n\t\t\t// Remove current events before re-binding them\n\t\t\tthis.undelegateEvents();\n\t\t\tfor ( key in events ) {\n\t\t\t\tmethod = events[key];\n\t\t\t\t// If the method is a string name of this.method, get it\n\t\t\t\tif ( typeof method !== 'function' ) {\n\t\t\t\t\tmethod = this[events[key]];\n\t\t\t\t}\n\t\t\t\tif ( method ) {\n\t\t\t\t\t// Extract event and selector from the key\n\t\t\t\t\tmatch = key.match( delegateEventSplitter );\n\t\t\t\t\tthis.delegate( match[1], match[2], method.bind( this ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Add a single event listener to the view's element (or a child element\n\t * using `selector`). This only works for delegate-able events: not `focus`\n\t * or `blur`.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tdelegate( eventName, selector, listener ) {\n\t\tthis.$el.on( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t},\n\n\t/**\n\t * Clears all callbacks previously bound to the view by `delegateEvents`.\n\t * You usually don't need to use this, but may wish to if you have multiple\n\t * views attached to the same DOM element.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t */\n\tundelegateEvents() {\n\t\tif ( this.$el ) {\n\t\t\tthis.$el.off( '.delegateEvents' + this.cid );\n\t\t}\n\t},\n\n\t/**\n\t * A finer-grained `undelegateEvents` for removing a single delegated event.\n\t * `selector` and `listener` are both optional.\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {string} eventName\n\t * @param {string} selector\n\t * @param {Function} listener\n\t */\n\tundelegate( eventName, selector, listener ) {\n\t\tthis.$el.off( eventName + '.delegateEvents' + this.cid, selector,\n\t\t\tlistener );\n\t},\n\n\t/**\n\t * See parseHTML method of util singleton\n\t *\n\t * @memberof module:mobile.startup/View\n\t * @instance\n\t * @param {string} html to turn into a jQuery object.\n\t * @return {jQuery.Object}\n\t */\n\tparseHTML( html ) {\n\t\t// document is explicitly passed due to a bug we found in Safari 11.1.2 where failure\n\t\t// to use document resulted in an element without access to the documentElement\n\t\t// this should be redundant, but no problem in being explicit (T214451).\n\t\treturn util.parseHTML( html, document );\n\t}\n} );\n\n/**\n * @memberof View\n * @instance\n * @function append\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function append\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prepend\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prepend\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function appendTo\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function prependTo\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function after\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function after\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @functiontion before\n * @param {...(string|Node|Node[]|jQuery)} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function before\n * @param {function(number, string): string|Node|Node[]|jQuery} contents\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @property {jQuery.Object} $el\n */\n\n/**\n * @memberof View\n * @instance\n * @function insertAfter\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function insertBefore\n * @param {string|Node|Node[]|jQuery} target\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function remove\n * @param {string} [selector]\n * @return {View}\n */\n\n/**\n * @memberof View\n * @instance\n * @function detach\n * @param {string} [selector]\n * @return {View}\n */\n\n[\n\t'append',\n\t'prepend',\n\t'appendTo',\n\t'prependTo',\n\t'after',\n\t'before',\n\t'insertAfter',\n\t'insertBefore',\n\t'remove',\n\t'detach'\n].forEach( ( prop ) => {\n\tView.prototype[prop] = function () {\n\t\tthis.$el[prop].apply( this.$el, arguments );\n\t\treturn this;\n\t};\n} );\n\n/**\n * Generates a view with children\n *\n * @param {Object} options\n * @param {jQuery.Element[]} children\n * @return {module:mobile.startup/View}\n */\nView.make = function ( options = {}, children = [] ) {\n\tconst view = new View( options );\n\tchildren.forEach( ( $child ) => view.append( $child ) );\n\treturn view;\n};\n\nmodule.exports = View;\n","const util = require( './util' ),\n\tdefaultParams = {\n\t\taction: 'query',\n\t\tformatversion: 2\n\t};\n\n/**\n * Extends the default params for an action query with otherParams\n *\n * @ignore\n * @param {Object} otherParams\n * @return {Object}\n */\nmodule.exports = function actionParams( otherParams ) {\n\tconst scriptPath = mw.config.get( 'wgMFScriptPath' );\n\treturn util.extend( {}, defaultParams, {\n\t\torigin: scriptPath ? '*' : undefined\n\t}, otherParams );\n};\n","const\n\tButton = require( '../Button' ),\n\tutil = require( '../util' ),\n\tView = require( '../View' );\n\n/**\n * @typedef {Object} FormField\n * @private\n * @property {string} name\n * @property {string} value\n */\n\n/**\n * A form for enabling the advanced mobile editor mode.\n *\n * @param {Object} options\n * @param {string} options.postUrl Form will POST to this endpoint\n * @param {FormField[]} options.fields An array of hidden form fields\n * @param {string} options.buttonLabel Label for submit button\n * submitted\n * @extends module:mobile.startup/View\n * @ignore\n */\nclass AmcEnableForm extends View {\n\t/** @inheritdoc */\n\tget isTemplateMode() {\n\t\treturn true;\n\t}\n\n\t/** @inheritdoc */\n\tget template() {\n\t\treturn util.template( `\n<form class=\"amc-enable-form\" action=\"{{postUrl}}\" method=\"POST\">\n\t{{#fields}}\n\t\t<input type=\"hidden\" name=\"{{name}}\" value=\"{{value}}\">\n\t{{/fields}}\n</form>\n\t\t` );\n\t}\n\n\t/** @inheritdoc */\n\tpostRender() {\n\t\tthis.$el.append(\n\t\t\tnew Button( {\n\t\t\t\ttagName: 'button',\n\t\t\t\tprogressive: true,\n\t\t\t\tlabel: this.options.buttonLabel\n\t\t\t} ).$el\n\t\t);\n\t}\n}\n\nmodule.exports = AmcEnableForm;\n","/**\n * Describes a promotional campaign for advanced mobile contributions.\n *\n * @typedef {Object} module:mobile.startup/AmcOutreach~PromoCampaign\n * @property {Function} showIfEligible\n * @property {Function} makeActionIneligible\n * @property {Function} makeAllActionsIneligible\n * @property {Function} isCampaignActive\n */\n\nconst\n\ttoast = require( '../showOnPageReload' ),\n\tcreatePromoCampaign = require( '../promoCampaign/promoCampaign' ),\n\tamcOutreachDrawer = require( './amcOutreachDrawer' ),\n\t// MW constants should be kept in sync with onMakeGlobalVariableScript() from\n\t// MobileFrontendHooks.php\n\tMW_CONFIG_CAMPAIGN_ACTIVE_NAME = 'wgMFAmcOutreachActive',\n\tMW_CONFIG_USER_ELIGIBLE_NAME = 'wgMFAmcOutreachUserEligible',\n\t// This object contains arbitrary actions that are meant to only be shown one\n\t// time at most. Each action is either 'eligible' or 'ineligible' at any given\n\t// time.\n\t//\n\t// When a new action is desired, it should be added to this object.\n\t//\n\t// In other languages, this would be an enum. However, because JS doesn't\n\t// support enums, the keys/value names are identical in an attempt to mimic\n\t// some of their functionality. The names in this object are used by\n\t// promoCampaign to mark when an action has become 'ineligible'.\n\tACTIONS = {\n\t\tonDesktopLink: 'onDesktopLink',\n\t\tonHistoryLink: 'onHistoryLink',\n\t\tonTalkLink: 'onTalkLink'\n\t},\n\tCAMPAIGN_NAME = 'amc-outreach';\n\n// singleton;\nlet campaign;\n\n/**\n * Internal for use inside Minerva only. See {@link module:mobile.startup} for access.\n *\n * @exports mobile.startup/AmcOutreach\n */\nmodule.exports = {\n\t/**\n\t * Loads a promotion campaign for advanced mobile contributions if the user is eligible.\n\t *\n\t * @return {module:mobile.startup/AmcOutreach~PromoCampaign}\n\t */\n\tloadCampaign: () => {\n\t\tif ( campaign ) {\n\t\t\treturn campaign;\n\t\t}\n\n\t\tcampaign = createPromoCampaign(\n\t\t\t/**\n\t\t\t * This callback is executed by promoCampaign's `showIfEligible` method.\n\t\t\t * promoCampaign will only execute it when an action is 'eligible'.\n\t\t\t *\n\t\t\t * @param {string} action Name of one of the actions in the ACTIONS\n\t\t\t * object. This is used by the drawer to notify promoCampaign when the\n\t\t\t * action has become 'ineligible' (e.g. after enabling or dismissing the\n\t\t\t * drawer).\n\t\t\t * @param {onBeforeHide} onBeforeHide Callback exected after user\n\t\t\t * dismisses drawer.\n\t\t\t * @param {string} returnToTitle Title of page to redirect to after user enables\n\t\t\t * AMC\n\t\t\t * @param {string} [returnToQuery] Optional query params to add to redirected\n\t\t\t * URL after user enables AMC. Can also include anchor (e.g.\n\t\t\t * `foo=bar#/Talk`\n\t\t\t * @return {module:mobile.startup/Drawer|null}\n\t\t\t */\n\t\t\t( action, onBeforeHide, returnToTitle, returnToQuery ) => {\n\t\t\t\treturn amcOutreachDrawer(\n\t\t\t\t\taction,\n\t\t\t\t\tcampaign,\n\t\t\t\t\tmw.message,\n\t\t\t\t\tmw.util,\n\t\t\t\t\ttoast,\n\t\t\t\t\tmw.user.tokens.get( 'csrfToken' ),\n\t\t\t\t\tonBeforeHide,\n\t\t\t\t\treturnToTitle,\n\t\t\t\t\treturnToQuery\n\t\t\t\t);\n\t\t\t},\n\t\t\tACTIONS,\n\t\t\tCAMPAIGN_NAME,\n\t\t\t// in minerva desktop, this config will not be set\n\t\t\t!!mw.config.get( MW_CONFIG_CAMPAIGN_ACTIVE_NAME ),\n\t\t\t!!mw.config.get( MW_CONFIG_USER_ELIGIBLE_NAME ),\n\t\t\tmw.storage\n\t\t);\n\n\t\treturn campaign;\n\t},\n\t/**\n\t * @private\n\t */\n\tACTIONS\n};\n","const\n\tDrawer = require( '../Drawer' ),\n\tAnchor = require( '../Anchor' ),\n\tutil = require( '../util' ),\n\tAmcEnableForm = require( './AmcEnableForm' ),\n\t// These constants should be kept in sync with SpecialMobileOptions.php\n\tAMC_ENABLE_FIELD_NAME = 'enableAMC',\n\tAMC_ENABLE_FIELD_VALUE = '1';\n\n/**\n * Callback intended to allow the client run extra logic (e.g. show a modal)\n * after the drawer is dismissed.\n *\n * @callback module:mobile.startup~onBeforeHide\n */\n\n/**\n * @ignore\n * @memberof module:mobile.startup\n * @param {string} action Used by the drawer to notify promoCampaign when the\n * action has become 'ineligible' (e.g. after enabling or dismissing the drawer).\n * @param {module:mobile.startup/AmcOutreach~PromoCampaign} promoCampaign\n * @param {mw.message} mwMessage Used for i18n\n * @param {mw.util} mwUtil Used to determine POST url for the enable form\n * @param {Toast} toast Displays success message after user submits enable form\n * @param {string} csrfToken\n * @param {onBeforeHide} onBeforeHide\n * @param {string} returnToTitle Title to redirect to after user enables\n * AMC\n * @param {string} [returnToQuery] Optional query params to add to redirected\n * URL after user enables AMC\n * @return {module:mobile.startup/Drawer} Returns the drawer that is shown\n */\nmodule.exports = function amcOutreachDrawer(\n\taction,\n\tpromoCampaign,\n\tmwMessage,\n\tmwUtil,\n\ttoast,\n\tcsrfToken,\n\tonBeforeHide,\n\treturnToTitle,\n\treturnToQuery\n) {\n\treturn new Drawer( {\n\t\tclassName: 'amc-outreach-drawer',\n\t\tchildren: [\n\t\t\tutil.parseHTML( '<div>' ).addClass( 'amc-outreach-image' ),\n\t\t\tutil.parseHTML( '<p>' ).append(\n\t\t\t\tutil.parseHTML( '<strong>' ).text(\n\t\t\t\t\tmwMessage( 'mobile-frontend-amc-outreach-intro' ).text()\n\t\t\t\t)\n\t\t\t),\n\t\t\tutil.parseHTML( '<p>' ).text(\n\t\t\t\tmwMessage( 'mobile-frontend-amc-outreach-description' ).text()\n\t\t\t),\n\t\t\tnew AmcEnableForm( {\n\t\t\t\tpostUrl: mwUtil.getUrl( 'Special:MobileOptions', {\n\t\t\t\t\treturnto: returnToTitle,\n\t\t\t\t\treturntoquery: returnToQuery || ''\n\t\t\t\t} ),\n\t\t\t\tfields: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'updateSingleOption',\n\t\t\t\t\t\tvalue: AMC_ENABLE_FIELD_NAME\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'enableAMC',\n\t\t\t\t\t\tvalue: AMC_ENABLE_FIELD_VALUE\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'token',\n\t\t\t\t\t\tvalue: csrfToken\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tbuttonLabel: mwMessage( 'mobile-frontend-amc-outreach-enable' ).text(),\n\t\t\t\tevents: {\n\t\t\t\t\tsubmit: () => {\n\t\t\t\t\t\tpromoCampaign.makeActionIneligible( action );\n\t\t\t\t\t\ttoast.showOnPageReload( mwMessage( 'mobile-frontend-amc-outreach-enabled-message' ).text() );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ).$el,\n\t\t\tnew Anchor( {\n\t\t\t\thref: '#',\n\t\t\t\tadditionalClassNames: 'cancel',\n\t\t\t\tprogressive: true,\n\t\t\t\tlabel: mwMessage( 'mobile-frontend-amc-outreach-no-thanks' ).text()\n\t\t\t} ).$el\n\t\t],\n\t\tonBeforeHide: () => {\n\t\t\tpromoCampaign.makeActionIneligible( action );\n\t\t\tonBeforeHide();\n\t\t}\n\t} );\n};\n","/* global $ */\nconst\n\tPage = require( './Page' );\n\nlet page;\n\n/**\n * Constructs an incomplete Page model singleton representing the currently loaded page.\n *\n * Because this depends on the presence of certain DOM elements, it\n * should only be called after the DOMContentLoaded event.\n *\n * @ignore\n * @return {Page}\n */\nfunction loadCurrentPage() {\n\tif ( page ) {\n\t\treturn page;\n\t}\n\n\tconst permissions = [].concat( mw.config.get( 'wgRestrictionEdit', [] ) ),\n\t\trelevantTitle = mw.Title.newFromText( mw.config.get( 'wgRelevantPageName' ) ),\n\t\ttitle = mw.Title.newFromText( mw.config.get( 'wgPageName' ) );\n\n\tif ( permissions.length === 0 ) {\n\t\tpermissions.push( '*' );\n\t}\n\n\tpage = new Page( {\n\t\ttitle: title.getPrefixedText(),\n\t\ttitleObj: title,\n\t\trelevantTitle: relevantTitle.getPrefixedText(),\n\t\tprotection: {\n\t\t\tedit: permissions\n\t\t},\n\t\trevId: mw.config.get( 'wgRevisionId' ),\n\t\tisMainPage: mw.config.get( 'wgIsMainPage' ),\n\t\tisWatched: $( '#ca-watch' ).hasClass( 'watched' ),\n\t\tisMissing: mw.config.get( 'wgArticleId' ) === 0,\n\t\tid: mw.config.get( 'wgArticleId' ),\n\t\tnamespaceNumber: mw.config.get( 'wgNamespaceNumber' )\n\t} );\n\n\treturn page;\n}\n\nmodule.exports = loadCurrentPage;\n","/* global $ */\nconst\n\tPageHTMLParser = require( './PageHTMLParser' );\n\nlet pageHTMLParser;\n\n/**\n * Constructs a page parser singleton specific to the current page to find common child elements\n * more easily.\n *\n * Because this depends on the presence of certain DOM elements, it\n * should only be called after the DOMContentLoaded event.\n *\n * @ignore\n * @return {module:mobile.startup/PageHTMLParser}\n */\nfunction loadCurrentPageHTMLParser() {\n\tif ( pageHTMLParser ) {\n\t\treturn pageHTMLParser;\n\t}\n\n\tpageHTMLParser = new PageHTMLParser( $( '#content #bodyContent' ) );\n\n\treturn pageHTMLParser;\n}\n\nmodule.exports = loadCurrentPageHTMLParser;\n","/**\n * T156186: Please make judicious use of this singleton whose purpose is to\n * allow disparate components the ability to subscribe to a set of events and\n * react to those events.\n *\n * Prefer to use a more localized event bus when possible.\n *\n * Only import this in files at the edges. For example:\n *\n * Good: initialization scripts responsible for initializing classes such as\n * mobile.init/init.js\n * Bad: ImageOverlay.js or in any other component.\n *\n * By doing this, and using dependency injection of the event bus in the\n * components themselves, it will make it easier to switch this event bus out\n * for something more localized later on in our refactoring efforts.\n */\nmodule.exports = new OO.EventEmitter();\n","const util = require( './util' ),\n\tactionParams = require( './actionParams.js' );\n\n/**\n * Extends the API query parameters to include those parameters required to also fetch Wikibase\n * descriptions and appropriately sized thumbnail images as well as those required to make a query.\n *\n * This function wraps `util.extend` with some Wikibase-specific configuration\n * variable management\n * but, like `util.extend`, is variadic and so can be used as a replacement for it in search\n * gateways, e.g.\n *\n * ```\n * var params = extendSearchParams(\n *   'search',\n *   baseParams,\n *   specializedParams,\n *   moreSpecializedParams\n * );\n * ```\n *\n * @param {string} feature The name of the feature\n * @throws {Error} If `feature` isn't one that shows Wikidata descriptions. See the\n *  `wgMFDisplayWikibaseDescriptions` configuration variable for detail\n * @return {Object}\n */\nmodule.exports = function extendSearchParams( feature ) {\n\tconst displayWikibaseDescriptions = mw.config.get( 'wgMFDisplayWikibaseDescriptions' ) || {\n\t\t\t// These must be defined, as these are all the features that this can be used on.\n\t\t\t// If not defined, all these features will see their API calls broken\n\t\t\tsearch: true,\n\t\t\twatchlist: true,\n\t\t\ttagline: false\n\t\t},\n\t\tscriptPath = mw.config.get( 'wgMFScriptPath' );\n\n\tif ( !Object.prototype.hasOwnProperty.call( displayWikibaseDescriptions, feature ) ) {\n\t\tthrow new Error( '\"' + feature + '\" isn\\'t a feature that shows Wikibase descriptions.' );\n\t}\n\n\t// Construct the arguments for a call to `util.extend`\n\t// such that if it were hand-written, then it\n\t// would look like the following:\n\t//\n\t// ```\n\t// var result = util.extend( {\n\t//   prop: []\n\t// }, params, /* ..., */ mw.config.get( 'wgMFSearchAPIParams' ) );\n\t// ```\n\tconst args = Array.prototype.slice.call( arguments, 1 );\n\targs.unshift( {\n\t\tprop: []\n\t} );\n\targs.push( mw.config.get( 'wgMFSearchAPIParams' ) );\n\n\tconst result = util.extend.apply( {}, args );\n\tresult.prop = result.prop.concat( mw.config.get( 'wgMFQueryPropModules' ) );\n\n\tif ( displayWikibaseDescriptions[feature] ) {\n\t\tif ( result.prop.indexOf( 'description' ) === -1 ) {\n\t\t\tresult.prop.push( 'description' );\n\t\t}\n\t}\n\n\tif ( scriptPath ) {\n\t\t// A foreign api is being accessed! Enable anonymous CORS queries!\n\t\tresult.origin = '*';\n\t}\n\treturn actionParams( result );\n};\n","const util = require( './util' ),\n\tButton = require( './Button' ),\n\ticons = require( './icons' );\n\n/**\n * Creates a header\n *\n * @ignore\n * @param {string|View} headingOrView (HTML allowed)\n * @param {View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction makeHeader( headingOrView, headerActions, headerCancel, additionalClassNames ) {\n\tconst heading = typeof headingOrView === 'string' ? headingOrView : undefined,\n\t\ttemplateData = {\n\t\t\thasActions: headerActions && headerActions.length,\n\t\t\tisHidden: false,\n\t\t\theading\n\t\t},\n\t\thtml = util.template( `\n<div class=\"overlay-header header ${ additionalClassNames || '' } hideable\">\n\t<ul class=\"header-cancel\">\n\t\t<li></li>\n\t</ul>\n\t{{{heading}}}\n\t{{#hasActions}}\n\t<div class=\"header-action\"></div>\n\t{{/hasActions}}\n</div>\n\t\t` ).render( templateData );\n\theaderCancel = headerCancel || icons.cancel();\n\tconst $el = util.parseHTML( html );\n\t// Truncate any text inside in the overlay header.\n\t$el.find( 'h2 span' ).addClass( 'truncated-text' );\n\t$el.find( '.header-cancel li' ).append(\n\t\theaderCancel.$el\n\t);\n\tif ( heading === undefined ) {\n\t\theadingOrView.$el.insertAfter( $el.find( '.header-cancel' ) );\n\t}\n\tif ( headerActions && headerActions.length ) {\n\t\t$el.find( '.header-action' ).append(\n\t\t\theaderActions.map( ( component ) => component.$el )\n\t\t);\n\t}\n\treturn $el[0];\n}\n\n/**\n * Creates a header with a h2 heading, internal for use inside GrowthExperiments only.\n *\n * @function\n * @memberof module:mobile.startup\n * @param {string} heading (HTML allowed)\n * @param {module:mobile.startup/View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction header( heading, headerActions, headerCancel, additionalClassNames ) {\n\theading = `<div class=\"overlay-title\"><h2>${ heading }</h2></div>`;\n\treturn makeHeader( heading, headerActions, headerCancel, additionalClassNames );\n}\n\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string|View} formHTMLOrView of the header\n * @param {View[]} headerActions\n * @param {module:mobile.startup/View} [headerCancel] defaults to cancel button\n * @param {string} [additionalClassNames] (should be escaped)\n * @return {Element}\n */\nfunction formHeader( formHTMLOrView, headerActions, headerCancel, additionalClassNames ) {\n\treturn makeHeader( formHTMLOrView, headerActions, headerCancel, additionalClassNames );\n}\n\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string} heading of the header\n * @param {string} additionalClassNames of the header\n * @return {Element}\n */\nfunction saveHeader( heading, additionalClassNames ) {\n\treturn header(\n\t\theading,\n\t\t[\n\t\t\tnew Button( {\n\t\t\t\ttagName: 'button',\n\t\t\t\tadditionalClassNames: 'save submit',\n\t\t\t\tdisabled: true,\n\t\t\t\tlabel: util.saveButtonMessage(),\n\t\t\t\tsize: 'large'\n\t\t\t} )\n\t\t],\n\t\ticons.back(),\n\t\tadditionalClassNames\n\t);\n}\n/**\n * Creates a header with a form\n *\n * @ignore\n * @param {string} heading of the header\n * @param {string} additionalClassNames of the header\n * @return {Element}\n */\nfunction savingHeader( heading ) {\n\treturn header(\n\t\theading,\n\t\t[\n\t\t\ticons.spinner( {\n\t\t\t\tadditionalClassNames: 'savespinner loading'\n\t\t\t} )\n\t\t],\n\t\ticons.cancel(),\n\t\t'saving-header hidden'\n\t);\n}\n\nmodule.exports = {\n\tsavingHeader,\n\tsaveHeader,\n\tformHeader,\n\theader\n};\n","const\n\tCANCEL_GLYPH = 'close',\n\tIcon = require( './Icon' ),\n\tIconButton = require( './IconButton' );\n\n/**\n * A set of shared icons.\n *\n * Factory methods are used to keep separate features that use the same icons\n * from accidentally manipulating one another's DOM when calling methods like\n * `remove`.\n *\n * @class icons\n * @singleton\n * @uses Icon\n */\nconst icons = {\n\tCANCEL_GLYPH,\n\t// Exported to support testing and stubbing\n\tIcon,\n\tIconButton,\n\t/**\n\t * Gets a back icon\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @return {IconButton}\n\t */\n\tback() {\n\t\treturn new icons.IconButton( {\n\t\t\ttagName: 'button',\n\t\t\ticon: 'previous',\n\t\t\tadditionalClassNames: 'back',\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t} );\n\t},\n\t/**\n\t * Gets a cancel icon\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @param {string} [variant]\n\t * @param {Object} [props] to extend\n\t * @return {IconButton}\n\t */\n\tcancel( variant, props = {} ) {\n\t\tconst glyph = variant ? `${ CANCEL_GLYPH }-${ variant }` : `${ CANCEL_GLYPH }`;\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' cancel';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ttagName: 'button',\n\t\t\ticon: glyph,\n\t\t\tlabel: mw.msg( 'mobile-frontend-overlay-close' )\n\t\t}, props ) );\n\t},\n\t/**\n\t * Gets a spinner icon. This uses IconButton but should never actually\n\t * be a button or have full button styles, as its purely presentational\n\t *\n\t * The icon should be used to inform the user that the front-end is\n\t * communicating with the back-end.\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @param {Object} [props] See `Icon` for more details\n\t * @return {IconButton}\n\t */\n\tspinner( props = {} ) {\n\t\tif ( props.additionalClassNames === undefined ) {\n\t\t\tprops.additionalClassNames = 'spinner loading';\n\t\t}\n\n\t\tconst spinner = new icons.IconButton( Object.assign( {\n\t\t\ttagName: 'span',\n\t\t\ticon: 'spinner',\n\t\t\tlabel: mw.msg( 'mobile-frontend-loading-message' )\n\t\t}, props ) );\n\n\t\t// Update the element to not use button classes or attributes\n\t\tspinner.$el.removeClass();\n\t\t// eslint-disable-next-line mediawiki/class-doc\n\t\tspinner.$el.addClass( props.additionalClassNames );\n\t\tspinner.$el.attr( 'type', '' );\n\t\tif ( spinner.options.isIconOnly ) {\n\t\t\tspinner.$el.addClass( 'mf-spinner-icon-element' );\n\t\t}\n\t\treturn spinner;\n\t},\n\t/**\n\t * Gets a failure (error) icon\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @return {IconButton}\n\t */\n\terror() {\n\t\treturn new icons.IconButton( {\n\t\t\ticon: 'alert-invert',\n\t\t\tadditionalClassNames: 'load-fail-msg-icon'\n\t\t} );\n\t},\n\t/**\n\t * Gets a non-filled watch star icon.\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @param {Object} props\n\t * @return {IconButton}\n\t */\n\twatch( props = {} ) {\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' watch-this-article';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ticon: 'star-subtle'\n\t\t}, props ) );\n\t},\n\t/**\n\t * Gets a filled watch star icon.\n\t *\n\t * @memberof icons\n\t * @instance\n\t * @param {Object} props\n\t * @return {IconButton}\n\t */\n\twatched( props = {} ) {\n\t\tprops.additionalClassNames = props.additionalClassNames || '';\n\t\tprops.additionalClassNames += ' watch-this-article watched';\n\n\t\treturn new icons.IconButton( Object.assign( {\n\t\t\ticon: 'unStar-progressive'\n\t\t}, props ) );\n\t}\n};\n\nmodule.exports = icons;\n","const\n\tutil = require( '../util' ),\n\tplaceholderClass = 'lazy-image-placeholder';\n\n/**\n * @ignore\n * @param {HTMLElement} root\n * @return {HTMLElement[]}\n */\nfunction queryPlaceholders( root ) {\n\treturn Array.prototype.slice.call(\n\t\troot.getElementsByClassName( placeholderClass )\n\t);\n}\n\n/**\n * Load an image on demand\n *\n * @ignore\n * @param {HTMLElement[]} placeholders a list of images that have not been loaded.\n * @return {jQuery.Deferred}\n */\nfunction loadImages( placeholders ) {\n\treturn util.Promise.all(\n\t\tplaceholders.map( ( placeholder ) => module.exports.loadImage( placeholder ).promise )\n\t);\n}\n\n/**\n * Load an image on demand\n *\n * @ignore\n * @param {HTMLElement} placeholder\n * @return {{promise: jQuery.Deferred<'load'|'error'>, image: HTMLImageElement}}\n */\nfunction loadImage( placeholder ) {\n\tconst\n\t\tdeferred = util.Deferred(),\n\t\t// data-width and height are attributes and do not specify dimension.\n\t\twidth = placeholder.dataset.width,\n\t\theight = placeholder.dataset.height,\n\t\timage = new Image();\n\n\tif ( width ) {\n\t\timage.setAttribute( 'width', parseInt( width, 10 ) );\n\t}\n\tif ( height ) {\n\t\timage.setAttribute( 'height', parseInt( height, 10 ) );\n\t}\n\n\t// eslint-disable-next-line mediawiki/class-doc\n\timage.className = placeholder.dataset.class || '';\n\timage.alt = placeholder.dataset.alt || '';\n\timage.useMap = placeholder.dataset.usemap;\n\timage.style.cssText = placeholder.style.cssText || '';\n\n\t// When the image has loaded\n\timage.addEventListener( 'load', () => {\n\t\t// Swap the HTML inside the placeholder (to keep the layout and\n\t\t// dimensions the same and not trigger layouts\n\t\timage.classList.add( 'image-lazy-loaded' );\n\t\tif ( placeholder.parentNode ) {\n\t\t\tplaceholder.parentNode.replaceChild( image, placeholder );\n\t\t}\n\t\tdeferred.resolve( 'load' );\n\t}, { once: true } );\n\timage.addEventListener( 'error', () => {\n\t\t// Swap the HTML and let the browser decide what to do with the broken image.\n\t\tif ( placeholder.parentNode ) {\n\t\t\tplaceholder.parentNode.replaceChild( image, placeholder );\n\t\t}\n\t\t// Never reject. Quietly resolve so that Promise.all() awaits for all Deferreds to complete.\n\t\t// Reevaluate using Deferred.reject in T136693.\n\t\tdeferred.resolve( 'error' );\n\t}, { once: true } );\n\n\t// Trigger image download after binding the load handler\n\timage.src = placeholder.dataset.src || '';\n\timage.srcset = placeholder.dataset.srcset || '';\n\n\treturn {\n\t\tpromise: deferred,\n\t\timage\n\t};\n}\n\nmodule.exports = {\n\tplaceholderClass,\n\tqueryPlaceholders,\n\tloadImages,\n\tloadImage,\n\ttest: {\n\t\tplaceholderClass\n\t}\n};\n","/**\n * Extends a class with new methods and member properties.\n *\n * @ignore\n * @param {Function} Child function\n * @param {Object|Function} ParentOrPrototype class to inherit from\n *  OR if no inheriting class a prototype to extend the class with\n * @param {Object} [prototype]\n */\nmodule.exports = function mfExtend( Child, ParentOrPrototype, prototype ) {\n\tlet key;\n\tif ( prototype ) {\n\t\tOO.inheritClass( Child, ParentOrPrototype );\n\t} else {\n\t\tOO.initClass( Child );\n\t\tprototype = ParentOrPrototype;\n\t}\n\tfor ( key in prototype ) {\n\t\tChild.prototype[key] = prototype[key];\n\t}\n};\n","/**\n * Class for managing modules\n *\n * A module in this context is essentially a Javascript class (not to be confused with\n * ResourceLoader modules).\n *\n * @class ModuleLoader\n */\nfunction ModuleLoader() {\n\t/**\n\t * @property {Object} register of defined modules\n\t * @private\n\t */\n\tthis._register = {};\n}\n\nModuleLoader.prototype = {\n\t/**\n\t * Require (import) a module previously defined using define().\n\t * Searches core module registry using ResourceLoader require before consulting\n\t * its own local registry. This method is deprecated, please do not use.\n\t *\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Required module id.\n\t * @return {Object} Required module, can be any JavaScript object.\n\t */\n\trequire( id ) {\n\t\tconst registry = this._register;\n\n\t\t/**\n\t\t * @return {Object} Module\n\t\t */\n\t\tfunction localRequire() {\n\t\t\tif ( !Object.hasOwnProperty.call( registry, id ) ) {\n\t\t\t\tthrow new Error( 'MobileFrontend Module not found: ' + id );\n\t\t\t}\n\t\t\treturn registry[id];\n\t\t}\n\n\t\tconst args = id.split( '/' );\n\t\ttry {\n\t\t\tconst module = __non_webpack_require__( args[0] );\n\t\t\tif ( module[args[1]] ) {\n\t\t\t\treturn module[args[1]];\n\t\t\t} else {\n\t\t\t\treturn localRequire();\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\treturn localRequire();\n\t\t}\n\t},\n\n\t/**\n\t * Define a module which can be later required (imported) using require().\n\t *\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Defined module id.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @return {Object}\n\t */\n\tdefine( id, obj ) {\n\t\tconst self = this;\n\n\t\tif ( Object.hasOwnProperty.call( this._register, id ) ) {\n\t\t\tthrow new Error( 'Module already exists: ' + id );\n\t\t}\n\t\tthis._register[id] = obj;\n\t\t// return an object of additionally functions to do with the registered module\n\t\treturn {\n\t\t\t/**\n\t\t\t * @see ModuleLoader#deprecate\n\t\t\t * @param {string} deprecatedId Defined module id, which is deprecated.\n\t\t\t * @ignore\n\t\t\t */\n\t\t\tdeprecate( deprecatedId ) {\n\t\t\t\tself.deprecate( deprecatedId, obj, id );\n\t\t\t}\n\t\t};\n\t},\n\n\t/**\n\t * Deprecate a module and give an replacement (if there is any).\n\t *\n\t * @memberof ModuleLoader\n\t * @instance\n\t * @param {string} id Defined module id, which is deprecated.\n\t * @param {Object} obj Defined module body, can be any JavaScript object.\n\t * @param {string} [replacement] Give an optional replacement for this module (which\n\t * needs to be already defined!)\n\t */\n\tdeprecate( id, obj, replacement ) {\n\t\tlet msg;\n\t\tif ( replacement ) {\n\t\t\t// add an alternative for this module, if any given\n\t\t\tmsg = 'Use ' + replacement + ' instead.';\n\t\t}\n\t\t// register it as a deprecated one\n\t\tmw.log.deprecate( this._register, id, obj, msg );\n\t}\n};\n\nmodule.exports = ModuleLoader;\n","const ModuleLoader = require( './moduleLoader' );\n\nmodule.exports = new ModuleLoader();\n","const Page = require( '../Page' );\nconst util = require( '../util' );\n\n/**\n * Create a Page object from an API response.\n *\n * @memberof Page\n * @param {Object} resp as representing a page in the API\n * @return {Page}\n */\nfunction parse( resp ) {\n\tlet displayTitle;\n\tconst thumb = resp.thumbnail,\n\t\tpageprops = resp.pageprops || {\n\t\t\tdisplaytitle: mw.html.escape( resp.title )\n\t\t},\n\t\tterms = resp.terms || resp.entityterms;\n\n\tif ( pageprops || terms ) {\n\t\t// The label is either the display title or the label pageprop\n\t\t// (the latter used by Wikidata)\n\t\t// Long term we want to consolidate these.\n\t\t// Note that pageprops.displaytitle is HTML, while\n\t\t// terms.label[0] is plain text.\n\t\tdisplayTitle = terms && terms.label ?\n\t\t\tmw.html.escape( terms.label[0] ) : pageprops.displaytitle;\n\t}\n\t// Add Wikidata descriptions if available (T101719)\n\tresp.wikidataDescription = resp.description || undefined;\n\n\tif ( thumb ) {\n\t\tresp.thumbnail.isLandscape = thumb.width > thumb.height;\n\t}\n\n\treturn new Page(\n\t\tutil.extend( resp, {\n\t\t\tid: resp.pageid,\n\t\t\tisMissing: !!resp.missing,\n\t\t\turl: mw.util.getUrl( resp.title ),\n\t\t\tdisplayTitle // this is HTML!\n\t\t} )\n\t);\n}\n\nmodule.exports = { parse };\n","/**\n * Creates a campaign that makes showing promo drawers, modals, etc that should\n * only be shown once (using localStorage) per action (when page loads, when\n * user clicks on a link, etc) easier. The campaign executes a given callback\n * (e.g. showing a drawer or modal) for a specific action only when it is\n * eligible. A campaign can have multiple arbitrary actions via the supplied\n * `actions` object. An action is either 'eligible' or 'ineligible' at any given\n * time. If `ineligible`, the `showIfEligible` will not execute the `onShow`\n * callback.\n *\n * @ignore\n * @param {Function} onShow A callback intended to show something related to the\n * campaign (drawer, modal, etc) when executed. The callback will only execute\n * after the client calls `showIfEligible` and only if the passed in action is\n * 'eligible'.\n * @param {Object} actions Object of arbitrary actions that are intended to be\n * either \"eligible\" or \"ineligible\" at any given time (onPageLoad,\n * onHistoryLinkClick). The `onShow` callback will only be executed when an\n * action is 'eligible'. For each action, the key and value should be the same\n * (e.g. \"onLoad\":\"onLoad\") to mimic an enum. The client is responsible for\n * notifying when each action becomes \"ineligible\" by calling the\n * `makeActionIneligible` method. All actions can be marked as ineligible by\n * calling the `makeAllActionsIneligible` method.\n * @param {string} campaignName Name of campaign. This is only used to form part\n * of the localStorage key for each action.\n * @param {boolean} campaignActive Is campaign active\n * @param {boolean} userEligible Is current user eligible\n * @param {mw.storage} mwStorage Used to mark actions as ineligible\n * into localStorage\n * @return {mobile.startup/AmcOutreach~PromoCampaign}\n */\nfunction createPromoCampaign(\n\tonShow,\n\tactions,\n\tcampaignName,\n\tcampaignActive,\n\tuserEligible,\n\tmwStorage\n) {\n\t// This object maps actions to localStorage keys\n\tconst ACTIONS_TO_STORAGE_KEYS = {};\n\tfor ( const key in actions ) {\n\t\tconst a = actions[ key ];\n\t\tACTIONS_TO_STORAGE_KEYS[a] = `mobile-frontend-${ campaignName }-ineligible-${ a }`;\n\t}\n\n\t/**\n\t * @return {boolean}\n\t */\n\tfunction isCampaignActive() {\n\t\treturn campaignActive;\n\t}\n\n\t/**\n\t * @param {string} action\n\t * @throws {Error} Throws an error if action is not valid.\n\t */\n\tfunction validateAction( action ) {\n\t\tif ( !( action in actions ) ) {\n\t\t\tthrow new Error(\n\t\t\t\t`Action '${ action }' not found in 'actions' object. Please add this to\n\t\t\t\tthe object when creating a campaign with promoCampaign.js if you believe\n\t\t\t\tthis is a valid action.`\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} action Will check the eligibility of this action. This\n\t * should be a value in the actions object.\n\t * @throws {Error} Throws an error if action is not valid.\n\t * @return {boolean}\n\t */\n\tfunction isActionEligible( action ) {\n\t\tvalidateAction( action );\n\n\t\treturn isCampaignActive() &&\n\t\t\tuserEligible &&\n\t\t\tmwStorage.get( ACTIONS_TO_STORAGE_KEYS[action] ) === null;\n\t}\n\n\treturn {\n\t\t/**\n\t\t * @ignore\n\t\t * @param {string} action Should be one of the values in the\n\t\t * actions param\n\t\t * @param {...*} [args] Args to pass to the onShow callback\n\t\t * @throws {Error} Throws an error if action is not valid.\n\t\t * @return {module:mobile.startup/Drawer|null} Returns Drawer if drawer is eligible to be shown and\n\t\t * null if not.\n\t\t */\n\t\tshowIfEligible( action, ...args ) {\n\t\t\tif ( !isActionEligible( action ) ) {\n\t\t\t\t// If not eligible, there is no sense in continuing.\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn onShow( action, ...args );\n\t\t},\n\t\t/**\n\t\t * @ignore\n\t\t * @param {string} action\n\t\t * @throws {Error} Throws an error if action is not valid.\n\t\t * @return {boolean} Whether the save operation was successful\n\t\t */\n\t\tmakeActionIneligible( action ) {\n\t\t\tvalidateAction( action );\n\n\t\t\t// The value here actually doesn't matter. The only thing that matters is\n\t\t\t// if this key exists in localStorage.\n\t\t\treturn mwStorage.set( ACTIONS_TO_STORAGE_KEYS[action], '~' );\n\t\t},\n\t\tmakeAllActionsIneligible() {\n\t\t\tlet key, action;\n\t\t\tfor ( key in actions ) {\n\t\t\t\taction = actions[key];\n\t\t\t\tthis.makeActionIneligible( action );\n\t\t\t}\n\t\t},\n\t\tisCampaignActive\n\t};\n}\n\nmodule.exports = createPromoCampaign;\n","const\n\tstorageKey = 'mobileFrontend/toast';\n\n/**\n * Show the previously saved toast data and delete it from storage\n *\n * @memberof Toast\n * @instance\n * @private\n */\nfunction showPending() {\n\tlet data = mw.storage.get( storageKey );\n\tif ( data ) {\n\t\tdata = JSON.parse( data );\n\t\tmw.notify( data.content, data.options );\n\t\tmw.storage.remove( storageKey );\n\t}\n}\n\nmw.requestIdleCallback( showPending );\n\n/**\n * Save the toast data in storage so that we can show it on page reload.\n * Also check whether there is a pending message that's not shown yet.\n * If yes, output a warning message and discard this message.\n * This is to ensure that the page needs to be reloaded before adding\n * a new message for showing later.\n *\n * @memberof Toast\n * @instance\n * @param {string} content Content to be placed in element\n * @param {Object|string} [options]\n *  If a string (deprecated) CSS class to add to the element\n *  If an object, more options for the notification see mw.notification.show.\n *  For backwards compatibility reasons if a string is given it will be\n *  treated as options.type\n */\nfunction showOnPageReload( content, options ) {\n\tif ( mw.storage.get( storageKey ) ) {\n\t\tmw.log.warn(\n\t\t\t'A pending toast message already exits. ' +\n\t\t\t\t'The page should have been reloaded by now.'\n\t\t);\n\t\treturn;\n\t}\n\tmw.storage.set( storageKey, JSON.stringify( {\n\t\tcontent,\n\t\toptions\n\t} ) );\n}\n\nmodule.exports = { showOnPageReload };\n","/* global $ */\n\n/**\n * Utility library\n *\n * @class util\n * @singleton\n */\nmodule.exports = {\n\t/**\n\t * Obtains the correct label for the save button which is project specific. It's either\n\t * \"save\" or \"publish\"\n\t *\n\t * @return {string}\n\t */\n\tsaveButtonMessage() {\n\t\treturn mw.config.get( 'wgEditSubmitButtonLabelPublish' ) ?\n\t\t\tmw.msg( 'mobile-frontend-editor-publish' ) : mw.msg( 'mobile-frontend-editor-save' );\n\t},\n\t/**\n\t * Wrapper class for Promises\n\t *\n\t * @memberof util\n\t * @instance\n\t */\n\tPromise: {\n\t\t/**\n\t\t * Wrapper class for the $.when that is compatible with Promise.all\n\t\t *\n\t\t * @memberof util\n\t\t * @param {jQuery.Promise[]} promises\n\t\t * @instance\n\t\t * @return {jQuery.Promise}\n\t\t */\n\t\tall( promises ) {\n\t\t\treturn $.when.apply( $, promises );\n\t\t}\n\t},\n\t/**\n\t * Escape a string for use as a css selector\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {string} selector\n\t * @return {string}\n\t */\n\tescapeSelector( selector ) {\n\t\treturn $.escapeSelector( selector );\n\t},\n\t/**\n\t * Run method when document is ready.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {Function} fn\n\t * @return {jQuery.Object}\n\t */\n\tdocReady( fn ) {\n\t\treturn $( fn );\n\t},\n\t/**\n\t * Wrapper class for the Deferred method\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Deferred}\n\t */\n\tDeferred() {\n\t\treturn $.Deferred();\n\t},\n\t/**\n\t * Adds a class to the document\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object} element representing the documentElement\n\t */\n\tgetDocument() {\n\t\treturn $( document.documentElement );\n\t},\n\t/**\n\t * Get the window object\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {jQuery.Object}\n\t */\n\tgetWindow() {\n\t\treturn $( window );\n\t},\n\t/**\n\t * Given some html, create new element(s).\n\t * Unlike jQuery.parseHTML this will return a jQuery object\n\t * not an array.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @param {string} html\n\t * @param {Element} [ctx] Document element to serve as the context\n\t *  in which the HTML fragment will be created\n\t * @return {jQuery.Object}\n\t */\n\tparseHTML( html, ctx ) {\n\t\tctx = ctx || document;\n\t\treturn $( $.parseHTML( html, ctx ) );\n\t},\n\t/**\n\t * Wrapper for jQuery.extend method. In future this can be bound to Object.assign\n\t * when support allows.\n\t *\n\t * Warning: if only one argument is supplied to util.extend(), this means the target argument\n\t * was omitted. In this case, the jQuery object itself is assumed to be the target.\n\t *\n\t * @memberof util\n\t * @instance\n\t * @return {Object}\n\t */\n\textend() {\n\t\treturn $.extend.apply( $, arguments );\n\t},\n\n\ttemplate( source ) {\n\t\treturn {\n\t\t\t/**\n\t\t\t * @ignore\n\t\t\t * @return {string} The raw source code of the template\n\t\t\t */\n\t\t\tgetSource() {\n\t\t\t\treturn source;\n\t\t\t},\n\t\t\t/**\n\t\t\t * @ignore\n\t\t\t * @param {Object} data Data to render\n\t\t\t * @param {Object} partials Map partial names to Mustache template objects\n\t\t\t * @return {string} Rendered HTML\n\t\t\t */\n\t\t\trender( data, partials ) {\n\t\t\t\tconst partialSource = {};\n\t\t\t\t// Map MobileFrontend templates to partial strings\n\t\t\t\tObject.keys( partials || {} ).forEach( ( key ) => {\n\t\t\t\t\tpartialSource[key] = partials[key].getSource();\n\t\t\t\t} );\n\n\t\t\t\t// Use global Mustache which is loaded by mediawiki.template.mustache (a\n\t\t\t\t// dependency of the mobile.startup module)\n\t\t\t\t// eslint-disable-next-line no-undef\n\t\t\t\treturn Mustache.render(\n\t\t\t\t\tsource.trim(),\n\t\t\t\t\tdata,\n\t\t\t\t\tpartialSource\n\t\t\t\t);\n\t\t\t}\n\t\t};\n\t}\n};\n","const util = require( '../util' ),\n\tactionParams = require( '../actionParams' );\n\n/**\n * @ignore\n * @typedef {string|number} PageID Page ID. 0 / \"0\" is a special no-ID value.\n * {@link https://www.mediawiki.org/wiki/Manual:Page_table#page_id Page ID}\n *\n * @ignore\n * @typedef {string} PageTitle Canonical page title.\n * {@link https://www.mediawiki.org/wiki/Manual:Title.php#Canonical_forms Canonical forms}\n *\n * @ignore\n * @typedef {boolean} WatchStatus Page watch status; true if watched, false if\n *                                unwatched.\n * {@link https://www.mediawiki.org/wiki/API:Info API:Info} (see inprop.watched)\n * {@link https://www.mediawiki.org/wiki/API:Watch API:Watch} (see unwatch)\n *\n * @ignore\n * @typedef {Object.<PageTitle, WatchStatus>} WatchStatusMap\n */\n\n/**\n * API for retrieving and modifying page watch statuses. This module interacts\n * with two endpoints, API:Info for GETs and API:Watch and for POSTs.\n *\n * @class WatchstarGateway\n * @param {mw.Api} api\n * @ignore\n */\nfunction WatchstarGateway( api ) {\n\tthis.api = api;\n}\n\nWatchstarGateway.prototype = {\n\t/**\n\t * Issues zero to two asynchronous HTTP requests for the watch status of\n\t * each page ID and title passed.\n\t *\n\t * Every watch entry has a title but not necessarily a page ID. Entries\n\t * without IDs are missing pages, i.e., pages that do not exist. These\n\t * entries are used to observe when a page with a given title is created.\n\t * Although it is convenient to use titles because they're always present,\n\t * IDs are preferred since they're far less likely to exceed the URL length\n\t * limit.\n\t *\n\t * No request is issued when no IDs and no titles are passed. Given that the\n\t * server state does not change between the two requests, overlapping title\n\t * and ID members will behave as expected but there is no reason to issue\n\t * such a request.\n\t *\n\t * @memberof WatchstarGateway\n\t * @instance\n\t * @param {PageID[]} ids\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatuses( ids, titles ) {\n\t\t// Issue two requests and coalesce the results.\n\t\treturn util.Promise.all( [\n\t\t\tthis.getStatusesByID( ids ),\n\t\t\tthis.getStatusesByTitle( titles )\n\t\t] ).then( function () {\n\t\t\treturn util.extend.apply( util, arguments );\n\t\t} );\n\t},\n\n\t/**\n\t * @memberof WatchstarGateway\n\t * @instance\n\t * @param {PageID[]} ids\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatusesByID( ids ) {\n\t\tconst self = this;\n\t\tif ( !ids.length ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.api.get( {\n\t\t\tformatversion: 2,\n\t\t\taction: 'query',\n\t\t\tprop: 'info',\n\t\t\tinprop: 'watched',\n\t\t\tpageids: ids\n\t\t} ).then( ( rsp ) => self._unmarshalGetResponse( rsp ) );\n\t},\n\n\t/**\n\t * @memberof WatchstarGateway\n\t * @instance\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t */\n\tgetStatusesByTitle( titles ) {\n\t\tconst self = this;\n\t\tif ( !titles.length ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.api.get( actionParams( {\n\t\t\tprop: 'info',\n\t\t\tinprop: 'watched',\n\t\t\ttitles\n\t\t} ) ).then( ( rsp ) => self._unmarshalGetResponse( rsp ) );\n\t},\n\n\t/**\n\t * @memberof WatchstarGateway\n\t * @instance\n\t * @param {PageTitle[]} titles\n\t * @param {WatchStatus} watched\n\t * @return {jQuery.Deferred}\n\t */\n\tpostStatusesByTitle( titles, watched ) {\n\t\tconst params = {\n\t\t\taction: 'watch',\n\t\t\ttitles\n\t\t};\n\t\tif ( !watched ) {\n\t\t\tparams.unwatch = !watched;\n\t\t}\n\t\treturn this.api.postWithToken( 'watch', params );\n\t},\n\n\t/**\n\t * @memberof WatchstarGateway\n\t * @instance\n\t * @param {Object} rsp The API:Info response.\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t * @see getStatusesByID\n\t * @see getStatusesByTitle\n\t * @ignore\n\t */\n\t_unmarshalGetResponse( rsp ) {\n\t\tconst pages = rsp && rsp.query && rsp.query.pages || [];\n\t\treturn pages.reduce( ( statuses, page ) => {\n\t\t\tstatuses[page.title] = page.watched;\n\t\t\treturn statuses;\n\t\t}, {} );\n\t}\n};\n\nmodule.exports = WatchstarGateway;\n","const PageList = require( '../PageList' ),\n\twatchstar = require( './watchstar' ),\n\tuser = mw.user,\n\tutil = require( '../util' ),\n\tPage = require( '../Page' ),\n\tmfExtend = require( '../mfExtend' ),\n\tWatchstarGateway = require( './WatchstarGateway' );\n\n/**\n * @typedef {Object.<PageTitle, PageID>} PageTitleToPageIDMap\n * @ignore\n */\n\n/**\n * List of items page view\n *\n * @class WatchstarPageList\n * @uses Page\n * @uses WatchstarGateway\n * @uses Watchstar\n * @extends PageList\n * @ignore\n *\n * @fires WatchstarPageList#unwatch\n * @fires WatchstarPageList#watch\n * @param {Object} options Configuration options\n */\nfunction WatchstarPageList( options ) {\n\tthis.wsGateway = new WatchstarGateway( options.api );\n\tPageList.apply( this, arguments );\n}\n\nmfExtend( WatchstarPageList, PageList, {\n\t/**\n\t * @memberof WatchstarPageList\n\t * @instance\n\t * @mixes PageList#defaults\n\t * @property {Object} defaults Default options hash.\n\t * @property {mw.Api} defaults.api\n\t */\n\tpostRender() {\n\t\tconst\n\t\t\tself = this,\n\t\t\tids = [],\n\t\t\ttitles = [];\n\n\t\tPageList.prototype.postRender.apply( this );\n\n\t\tconst $items = this.queryUnitializedItems();\n\t\tconst pages = this.parsePagesFromItems( $items );\n\n\t\tObject.keys( pages ).forEach( ( title ) => {\n\t\t\tconst id = pages[title];\n\t\t\t// Favor IDs since they're short and unlikely to exceed URL length\n\t\t\t// limits when batched.\n\t\t\tif ( id && id !== '0' ) {\n\t\t\t\t// ID is present and valid.\n\t\t\t\tids.push( id );\n\t\t\t} else {\n\t\t\t\t// Only titles are available for missing pages.\n\t\t\t\ttitles.push( title );\n\t\t\t}\n\t\t} );\n\n\t\treturn this.getPages( ids, titles )\n\t\t\t.then( ( statuses ) => self.renderItems( $items, statuses ) );\n\t},\n\n\t/**\n\t * @memberof WatchstarPageList\n\t * @param {jQuery.Element} $items\n\t * @param {WatchStatusMap} statuses\n\t * @ignore\n\t */\n\tqueryUnitializedItems() {\n\t\treturn this.$el.find( 'li:not(.with-watchstar)' );\n\t},\n\n\t/**\n\t * Retrieve pages\n\t *\n\t * @memberof WatchstarPageList\n\t * @instance\n\t * @param {PageID[]} ids\n\t * @param {PageTitle[]} titles\n\t * @return {jQuery.Deferred<WatchStatusMap>}\n\t * @ignore\n\t */\n\tgetPages( ids, titles ) {\n\t\t// Rendering Watchstars for anonymous users is not useful. Short-circuit\n\t\t// the request.\n\t\tif ( user.isAnon() ) {\n\t\t\treturn util.Deferred().resolve( {} );\n\t\t}\n\n\t\treturn this.wsGateway.getStatuses( ids, titles );\n\t},\n\n\t/**\n\t * @param {jQuery.Element} $items\n\t * @return {PageTitleToPageIDMap}\n\t * @memberof WatchstarPageList\n\t * @ignore\n\t */\n\tparsePagesFromItems( $items ) {\n\t\tconst\n\t\t\tself = this,\n\t\t\tpages = {};\n\t\t$items.each( ( _, item ) => {\n\t\t\tconst $item = self.$el.find( item );\n\t\t\tpages[$item.attr( 'title' )] = $item.data( 'id' );\n\t\t} );\n\t\treturn pages;\n\t},\n\n\t/**\n\t * @param {jQuery.Element} $items\n\t * @param {WatchStatusMap} statuses\n\t * @memberof WatchstarPageList\n\t * @ignore\n\t */\n\trenderItems( $items, statuses ) {\n\t\tconst self = this;\n\n\t\t// Rendering Watchstars for anonymous users is not useful. Nothing to do.\n\t\tif ( user.isAnon() ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Create watch stars for each entry in list\n\t\t$items.each( ( _, item ) => {\n\t\t\tconst\n\t\t\t\t$item = self.$el.find( item ),\n\t\t\t\tpage = new Page( {\n\t\t\t\t\t// FIXME: Set sections so we don't hit the api (hacky)\n\t\t\t\t\tsections: [],\n\t\t\t\t\ttitle: $item.attr( 'title' ),\n\t\t\t\t\tid: $item.data( 'id' )\n\t\t\t\t} ),\n\t\t\t\twatched = statuses[page.getTitle()];\n\n\t\t\tself._appendWatchstar( $item, page, watched );\n\t\t\t$item.addClass( 'with-watchstar' );\n\t\t} );\n\t},\n\n\t/**\n\t * @param {jQuery.Object} $item\n\t * @param {Page} page\n\t * @param {WatchStatus} watched\n\t * @private\n\t */\n\t_appendWatchstar( $item, page, watched ) {\n\t\twatchstar( {\n\t\t\t// WatchstarPageList.getPages() already retrieved the status of\n\t\t\t// each page. Explicitly set the watch state so another request\n\t\t\t// will not be issued by the Watchstar.\n\t\t\tisWatched: watched,\n\t\t\tpage\n\t\t} ).appendTo( $item );\n\t}\n} );\n\nmodule.exports = WatchstarPageList;\n","const icons = require( '../icons' );\n\n/**\n * A clickable watchstar for logged in users.\n * Should not be used for anonymous users.\n *\n * @param {Object} options Configuration options\n * @param {Page} options.page\n * @param {boolean} options.isWatched is the article watched?\n * @return {IconButton}\n */\nmodule.exports = function ( options ) {\n\tconst isWatched = options.isWatched,\n\t\twatchstar = __non_webpack_require__( 'mediawiki.page.watch.ajax' ).watchstar,\n\t\taction = isWatched ? 'unwatch' : 'watch',\n\t\ticonProps = {\n\t\t\thref: mw.Title.newFromText( options.page.title ).getUrl( { action } )\n\t\t},\n\t\twatchButton = icons.watch( iconProps ),\n\t\twatchedButton = icons.watched( iconProps ),\n\t\tWATCH_BUTTON_CLASS = watchButton.getClassName(),\n\t\tWATCHED_BUTTON_CLASS = watchedButton.getClassName(),\n\t\tWATCH_CLASS = watchButton.getIcon().getClassName(),\n\t\tWATCHED_CLASS = watchedButton.getIcon().getClassName(),\n\t\tactiveIcon = isWatched ? watchedButton : watchButton,\n\t\tcallback = ( $link, watched ) => {\n\t\t\t$link.attr( 'class', watched ?\n\t\t\t\tWATCHED_BUTTON_CLASS : WATCH_BUTTON_CLASS );\n\t\t\tconst $icon = $link.find( '.mf-icon' );\n\t\t\t$icon.attr( 'class', watched ?\n\t\t\t\tWATCHED_CLASS : WATCH_CLASS );\n\t\t};\n\n\twatchstar( activeIcon.$el, options.page.title, callback );\n\treturn activeIcon;\n};\n"],"names":["icons","require","module","exports","$goBack","cancel","$el","$loadingMessage","spinner","tagName","isIconOnly","label","mw","msg","$","addClass","append","View","util","Anchor","_View","_classCallCheck","_callSuper","arguments","_inherits","key","get","progressive","undefined","destructive","additionalClassNames","href","template","browser","memoize","method","memoized","cache","this","cacheId","join","call","Object","prototype","hasOwnProperty","apply","Date","now","toString","Math","random","Browser","ua","$container","userAgent","isIos","version","ios","test","isWideScreen","val","parseInt","config","window","innerWidth","supportsTouchEvents","getSingleton","$html","getDocument","navigator","mfExtend","IconButton","Button","options","preRender","action","weight","quiet","block","extend","icon","_button","_buttonHTML","outerHTML","isTemplateMode","defaults","disabled","size","Drawer","CtaDrawer","length","params","redirectParams","queryParams","returnTo","children","parseHTML","text","content","getUrl","progressiveButton","signUpParams","signupQueryParams","actionAnchor","redirectURL","returnto","push","type","props","drawerClassName","className","collapseIcon","onBeforeHide","showCollapseIcon","events","hide","bind","ev","preventDefault","click","stopPropagation","$mask","show","d","Deferred","prepend","width","$drawer","find","hasClass","resolve","hook","fire","onShow","requestAnimationFrame","promise","_this","removeClass","setTimeout","detach","postRender","concat","trim","Icon","_iconClasses","getIconClasses","getRotationClass","rotationClass","rotation","Error","base","isSmall","rotationClasses","classes","getGlyphClassName","glyphPrefix","getClassName","attr","isTypeButton","_buttonClasses","getButtonClasses","_iconHTML","_icon","title","getIcon","MessageBox","header","Overlay","headerChrome","hideTimeout","showSpinner","hideSpinner","footerAnchor","$overlayContent","headers","heading","headerActions","onExitClick","exit","onBeforeExit","scrollTop","pageYOffset","scrollTo","clearTimeout","pageXOffset","emit","showHidden","make","view","overlay","overlayManager","MANAGED_STATE","OverlayManager","router","container","on","_checkRoute","entries","stack","hideCurrent","attachHideEvent","_onHideOverlayOutsideOverlayManager","currentRoute","route","routeIsString","currentPath","getPath","routeIsSame","match","back","_attachOverlay","parents","appendChild","_show","history","replaceState","location","once","_hideOverlay","onBeforeExitCancel","result","off","_processMatch","factoryResult","current","keys","reduce","m","id","_matchRoute","path","entry","didMatch","captures","previous","self","slice","shift","next","factory","unshift","add","docReady","replaceCurrent","stackOverlay","__non_webpack_require__","document","createElement","hash","state","body","pushState","__clearCache","HTML","html","Page","relevantTitle","titleObj","displayTitle","escape","namespaceNumber","protection","url","wikidataDescription","_isMainPage","isMainPage","isMissing","anchor","revId","_isWatched","isWatched","thumbnail","isLandscape","height","value","namespace","isWikiText","isVEAvailable","namespaces","indexOf","args","split","toLowerCase","replace","Thumbnail","HEADING_SELECTOR","EXCLUDE_THUMBNAIL_CLASS_SELECTORS","NOT_SELECTORS","map","excludeSelector","THUMB_SELECTOR","selector","PageHTMLParser","$headings","sectionIndex","filter","eq","$heading","$nextHeading","headingSelector","withNestedChildren","$matchingNodes","addBack","$lead","getLeadSectionElement","$nestedSection","findSectionHeadingByIndex","prevAll","nextAll","nextUntil","$leadSection","$a","notSelector","$lazyImage","URL","legacyTitle","searchParams","pathname","valid","RegExp","data","el","filename","percentDecodeFragment","thumbs","each","thumb","getThumbnail","pageTitle","mapLinkToLanguageObj","node","langname","DELIMITER","autonym","textContent","getAttribute","pop","lang","languages","Array","querySelectorAll","variants","PageList","pages","renderPageImages","style","templatePartials","item","skin","currentPage","eventBus","Skin","page","name","isBorderBox","getLicenseLinks","mobileLicense","message","mobileMsgExists","exists","parseDom","clone","getLicenseMsg","licenseMsg","$licenseLinks","licensePlural","language","convertNumber","$termsLink","parse","description","siblings","prop","getDescription","getFileName","delegateEventSplitter","idCounter","initialize","OO","mixinClass","EventEmitter","prefix","cid","compile","_postInitialize","render","undelegateEvents","skipTemplateRender","replaceWith","delegateEvents","delegate","eventName","listener","undelegate","forEach","$child","defaultParams","formatversion","otherParams","scriptPath","origin","AmcEnableForm","buttonLabel","campaign","toast","createPromoCampaign","amcOutreachDrawer","ACTIONS","onDesktopLink","onHistoryLink","onTalkLink","loadCampaign","returnToTitle","returnToQuery","user","tokens","storage","promoCampaign","mwMessage","mwUtil","csrfToken","postUrl","returntoquery","fields","submit","makeActionIneligible","showOnPageReload","permissions","Title","newFromText","getPrefixedText","edit","pageHTMLParser","actionParams","feature","displayWikibaseDescriptions","search","watchlist","tagline","makeHeader","headingOrView","headerCancel","templateData","hasActions","isHidden","insertAfter","component","savingHeader","saveHeader","saveButtonMessage","formHeader","formHTMLOrView","CANCEL_GLYPH","variant","glyph","assign","error","watch","watched","placeholderClass","queryPlaceholders","root","getElementsByClassName","loadImages","placeholders","Promise","all","placeholder","loadImage","deferred","dataset","image","Image","setAttribute","class","alt","useMap","usemap","cssText","addEventListener","classList","parentNode","replaceChild","src","srcset","Child","ParentOrPrototype","inheritClass","initClass","ModuleLoader","_register","registry","localRequire","e","define","obj","deprecate","deprecatedId","replacement","log","resp","pageprops","displaytitle","terms","entityterms","pageid","missing","actions","campaignName","campaignActive","userEligible","mwStorage","ACTIONS_TO_STORAGE_KEYS","a","isCampaignActive","validateAction","showIfEligible","isActionEligible","_len","_key","set","makeAllActionsIneligible","storageKey","requestIdleCallback","JSON","notify","remove","warn","stringify","promises","when","escapeSelector","fn","documentElement","getWindow","ctx","source","getSource","partials","partialSource","Mustache","WatchstarGateway","api","getStatuses","ids","titles","getStatusesByID","getStatusesByTitle","then","inprop","pageids","rsp","_unmarshalGetResponse","postStatusesByTitle","unwatch","postWithToken","query","statuses","watchstar","WatchstarPageList","wsGateway","$items","queryUnitializedItems","parsePagesFromItems","getPages","renderItems","isAnon","_","$item","sections","getTitle","_appendWatchstar","appendTo","iconProps","watchButton","watchedButton","WATCH_BUTTON_CLASS","WATCHED_BUTTON_CLASS","WATCH_CLASS","WATCHED_CLASS","activeIcon","$link"],"sourceRoot":""}