From 03836b69f296df8edef412fcb00876dc72fc6eb3 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 28 Jan 2020 22:16:48 -0500 Subject: [PATCH 01/30] Started conversion to TypeScript. --- .gitignore | 2 + icon.png | Bin 4554 -> 0 bytes jest.config.js | 8 + package-lock.json | 5237 ++++++++++++++++- package.json | 23 +- .../_locales}/de/messages.json | 0 .../_locales}/en/messages.json | 0 .../_locales}/fr/messages.json | 0 .../_locales}/it/messages.json | 0 .../_locales}/pl_PL/messages.json | 0 .../_locales}/pt_BR/messages.json | 0 .../_locales}/pt_pt/messages.json | 0 .../_locales}/ru/messages.json | 0 content.css => public/content.css | 0 .../firefox_manifest-extra.json | 0 {help => public/help}/index_en.html | 0 {help => public/help}/styles.css | 0 .../icons}/IconSponsorBlocker16px.png | Bin .../icons}/IconSponsorBlocker256px.png | Bin .../icons}/IconSponsorBlocker32px.png | Bin .../icons}/LogoSponsorBlocker128px.png | Bin .../icons}/LogoSponsorBlocker256px.png | Bin .../icons}/LogoSponsorBlocker64px.png | Bin .../PlayerDeleteIconSponsorBlocker256px.png | Bin .../PlayerInfoIconSponsorBlocker256px.png | Bin .../PlayerStartIconSponsorBlocker256px.png | Bin .../PlayerStopIconSponsorBlocker256px.png | Bin ...yerUploadFailedIconSponsorBlocker256px.png | Bin .../PlayerUploadIconSponsorBlocker256px.png | Bin {icons => public/icons}/close.png | Bin {icons => public/icons}/downvote.png | Bin {icons => public/icons}/newprofilepic.jpg | Bin {icons => public/icons}/report.png | Bin {icons => public/icons}/upvote.png | Bin {icons => public/icons}/upvote.svg | 0 {libs => public/libs}/Source+Sans+Pro.css | 0 manifest.json => public/manifest.json | 0 popup.css => public/popup.css | 0 popup.html => public/popup.html | 0 SB.js => src/SB.ts | 141 +- background.js => src/background.js | 0 src/config.js.example | 3 + content.js => src/content.ts | 75 +- .../js-components/previewBar.ts | 13 +- .../js-components/skipNotice.ts | 27 +- popup.js => src/popup.js | 0 src/utils.ts | 279 + tsconfig.json | 12 + utils.js | 271 - webpack/webpack.common.js | 43 + webpack/webpack.dev.js | 7 + webpack/webpack.prod.js | 6 + 52 files changed, 5729 insertions(+), 418 deletions(-) delete mode 100644 icon.png create mode 100644 jest.config.js rename {_locales => public/_locales}/de/messages.json (100%) rename {_locales => public/_locales}/en/messages.json (100%) rename {_locales => public/_locales}/fr/messages.json (100%) rename {_locales => public/_locales}/it/messages.json (100%) rename {_locales => public/_locales}/pl_PL/messages.json (100%) rename {_locales => public/_locales}/pt_BR/messages.json (100%) rename {_locales => public/_locales}/pt_pt/messages.json (100%) rename {_locales => public/_locales}/ru/messages.json (100%) rename content.css => public/content.css (100%) rename firefox_manifest-extra.json => public/firefox_manifest-extra.json (100%) rename {help => public/help}/index_en.html (100%) rename {help => public/help}/styles.css (100%) rename {icons => public/icons}/IconSponsorBlocker16px.png (100%) rename {icons => public/icons}/IconSponsorBlocker256px.png (100%) rename {icons => public/icons}/IconSponsorBlocker32px.png (100%) rename {icons => public/icons}/LogoSponsorBlocker128px.png (100%) rename {icons => public/icons}/LogoSponsorBlocker256px.png (100%) rename {icons => public/icons}/LogoSponsorBlocker64px.png (100%) rename {icons => public/icons}/PlayerDeleteIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/PlayerInfoIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/PlayerStartIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/PlayerStopIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/PlayerUploadFailedIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/PlayerUploadIconSponsorBlocker256px.png (100%) rename {icons => public/icons}/close.png (100%) rename {icons => public/icons}/downvote.png (100%) rename {icons => public/icons}/newprofilepic.jpg (100%) rename {icons => public/icons}/report.png (100%) rename {icons => public/icons}/upvote.png (100%) rename {icons => public/icons}/upvote.svg (100%) rename {libs => public/libs}/Source+Sans+Pro.css (100%) rename manifest.json => public/manifest.json (100%) rename popup.css => public/popup.css (100%) rename popup.html => public/popup.html (100%) rename SB.js => src/SB.ts (54%) rename background.js => src/background.js (100%) create mode 100644 src/config.js.example rename content.js => src/content.ts (93%) rename utils/previewBar.js => src/js-components/previewBar.ts (89%) rename utils/skipNotice.js => src/js-components/skipNotice.ts (96%) rename popup.js => src/popup.js (100%) create mode 100644 src/utils.ts create mode 100644 tsconfig.json delete mode 100644 utils.js create mode 100644 webpack/webpack.common.js create mode 100644 webpack/webpack.dev.js create mode 100644 webpack/webpack.prod.js diff --git a/.gitignore b/.gitignore index 4ff2c144..c97afe49 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ ignored node_modules web-ext-artifacts .vscode/ +dist/ +tmp/ \ No newline at end of file diff --git a/icon.png b/icon.png deleted file mode 100644 index 242daa29cf2a90304cea847d33023b45221509a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4554 zcmV;*5jF0KP)W)*gnPXn>g3Tw zMt^TFEy*%2OK`9S-~dZbvHFY47CH$Mmq{GRmkWf+1wg_uZ;zWgymwcMD2hZ;L5`(- zVd*SOveAqzfEPr*v8BE3gO7Jr_4WlqW=pEScvvJ3c>^B!on_|8F=4+N;IDgm-qK#qS;p*BCwtaOvYsyqtVbLr%%~6n}D2NkR zFaS22jjKBRwRw7eZt5L3|D+<41cwTb{@%Xp$eC@G2WxZl3!VA-g>Fv8h*vfMP{Mt^ zz0~fV+tOHuQa}CZT{kc^Ma2jKSTMwkPdxL-uY?fqFP*p0X0fLFIhGQU6-;&<7@rGB z7$yio+~syM`a}aylgu!=L`lMfA%Qr0Xs@}`Zr5a{TazEUXU$>+!hkEt80Pl&2A}=i zma1;2w-K%k`b48IIoaT6C{lpXFViFe2|!BzJ|6|4vgLrRIDyM%lf_>$cadwN#3?=i zBn%4)0kC_=C#f2(n#oSJB-Nj5b$fjQ0h48g+{hR{KypL~aVSazFN$P#MrzU>KV4ap zl5EgMghBXyUinSypFgZ@U}(V86vb0C5Ezma0SO>U5HgO*gRE;-VXmq9yxrB;7YHq0 zaecc=&B2Kfr?>z>k=@~FXR8h$G!;(IvEH&~#meZ+D6`+EHTNRX4|uw|rMl9Qvg zKGa`29M0aF+GYnq;83Gh5mvK7hj7F(OinT+BvKK#>0kJltzYh{sjcrQDO=QOwx$IT zdmL}9hz|fL;dS5F=;~|F7=BVQzhKE##dAi=>qEFswA;tb=3zY#3ndpmiTdiD_jl|$ zUEA0(yX-25)sh~d844=QaU7gs>;Ry^CyU_wQzsG{8_p))cwKq%Ri%Y9MoVp@X??&A z1_T={{0JW_TmI?Y&-Q;;*JPVjvY^wNp5|v+N@Pev8V_fP4*)2FGpA1^Hq|2lmK4vQ zQ&bpRZ-bRNT(AAG#i8}+Js$jrfB%%G2)_K98_ug$EI$#>5ElTvAQ076-x`{l8}&cC zX=Pc-%xQVC@_KZTi)HWen0qXM?|tlr&pDdrm#$pZqE&PJ0B0b`fs{E`);wkaPyh@G z5FFmO%iPu3sd;R}Ez6bQ7X9i+VHQ4(JYb04ntFmjQ-?|k_Aof?h`E?RbNt2RL$ z(sHc8u#`9eKpb7AxGW&R3&fGVl__1_PW9st-m*O1nw%6l)nscudjC5&{pL#*O9dBR zy{Z+4dazJm4^B}4avTi}MsvtuH1Puj=^{*VTmW=-IW>R(;4Kvj05OwS{6X$wT95X$ zr=EN3fYa^vm`rA0DAjq#SOsG1A9z%heP{| zyKY*Nlbvdfoz!Fd`e>ai-yA>F#?ge3kzuBn%$uEo;g~G&Jiq^& zQ;q(n|tw6tfyt>}@ z!W-|^LMQ=A#(>pgWS{)Sy28{Hqxw>5eJDw^ce#9KrLGvBdb&Mc&u?G(^G;oYKCqyC zrJZI7I8uvk%m84B2|^Ksf&zJXUu8(^@k9O=mot>TIo<5_*#i^*69j3SdKwaLD2!Y7+gvaNnJzY*F z1VuulGeAkgFj0a4iV(D&tJAf&HS5-|UOs*Kl9HU^Y;oiur?_$qL-@KpWB z+rK`Ym6PW#oKfslX&50^i*4)xpo2jP7eok-9o=tq*g7;4lmL_@Krc+sCkFfh=HH&UyTX)| zs0+t|(NkNDN_a$b|E%&z+kd@R*}86Zx#i{?7H1Ct+%LSN)9w4^Z~wGEL8tGVyJ%^9 zf=0zp9Dx3djstru%^sJFyZ?^W%hFR*($SCC*0-E{bIYgSqW1_8D9K=6X+ip}Ygf#R z2!AQH{?q%OIRpSM0UVQ7t+>j3`%TNIMfSIMx_aMvf9L7u^X<;m)J$*TtdcHNFiqSA z`uhQ2eDYzs3`OwFQxDw{9pRf=Y_>gzPSm4DPF{9~scd$B4nu|W^Q8`Q>mGRa07>8? zNsvmjP^(oDc~jCf!9YN)YijdSBoGsH`oQdYi|tws8`5x$V*V3~0jL@jp@e_&$p@JN zl!#wHz2UZ)L??pEXoO}&UymK#h5~rohUfNDBq8MFmpGmFb6g z1*M(3BtsCBASML-fMO`9)g=f7K|zKkAxAMH!&2~)5FrFWxEkD@(%s#qdh~(y%dLa@ z0T(AU=mO-gAAQxl|45C~=MM-vor+vsR%Beawmh4qN1)C_%nX6}>RVfne^=LJpH@)Z zm29#4X_6Faq+J4+2^q*Fx>zL%iDd`~&>iC_x6NbD0ucZr#n6Ly-nb+utG^f;Lxe}d zKli(LYwDWXdWil21^~b$Ny74S(sfU6TwlyGGi>WAO}mr)gXv5S*&0npf3Z&-cJ(pih<&6qyc2>-$x?^U0wY3!ad zwa{rarzmENOxD)iptajtbn8}MoqzS>k|~2MKBhUy*zWzuo3?(o=ex}8TxUUHu~VgH z1w?fb*GKh#WRI~-nZyMEDu>UvG;59@J(QB4o1J>kt*aJ~wRm~)_wQF%f7j$lHko>J z3yZrsni8FzZEQ=!S-l8F;vXNrZBa(5*$|aPhHQNSje|$ew7&cP7uD%mS?(D#=X7Z` zEU!{AB27^+-hqlS1AwYQ)D?EvJGjFK_E^(Xt)`9l-q?TT-Jk16;qV;}SMP6L{mZvJ zAM8ud$Z?x3R)1~HQ3E1P_uP8@+`?(u86(vJ(M$sUL`$2){lcs79!fSQ`N|e7wIKjl z6(h2f4M4aY4w2ip{Vg-ZL;B@s9=0_3r1iju6=J+olG<1)lT94imz2EdtFK=UM z5Gr4}x;0_}lM6t9HP{yjkyS?zCE42B64tL-QJQQ_OiWKTDKo~SRc)aVFP=Qpc>b>+ zesL<%VDu*%lLH;?O`0{=md}`5QmEW8gou3N=O`l!&~XG@XiN zm0>6xS8mJYrWTtg7z_q!k`iee2-6FTyI77DYHN-eA(X+K*##LXrX)jWmpf#0xOho| zL|sE$Z;#IpF@VdsEXx1@84y4s2|}bvLe%QifuiC$oo16cfT-@ky+9my0_comcL8PS zLBdgAkmp6BwdI`J(P>w^x?L)d*TspVL`ot?2$BRMvjWP42mq4^f{6j^zYSqX}s> zI^JYS?o)9bA1QRkJ60DL07_p_76Af55=0OPiljdjBKZJMh6ITa1(E3SdT2r52a+)X zFifq}^D0gyFcg3^M~e(iK?;ONU;KeSvfI(Yc|9H$2Q-coq*79IY8}K$QbI6LI4%Pc zF*{142mqD!6bY3(L7IZfNFBNz9-;L;Jic7`ByIrEpfjop1*9cG1i=s_g1kVWc9px$AdU}!jMgLa z6sEn%s!+F=lm^CYCv`p`0$P7#1PwtU5TGdG$d4fuab+$D%?m{VfTRF&SO^mNFiFTL zHsEB~NDvB2uMt@ll!1uWM(%j~*8&h8MM47*1flGu@Og9YUm$_A4qyb)<$W6(Ap?SFU5FVWbcUq zFb>2=T@pRs5NA3Y?@|750We-ECa_Kc;K%yVlq5s(u7_U#7|$u+ocr4I_g|Z!Q~jtO zoAdVcIX6A|<_>&n`R1gJ4_>#VbXMNX30Tt=x3ub1ef8`Av3=kFKRSz4r#w8Zw`MWi#D}%w7>l3_L@YG?Of#H>BxU0cQ8soOn^A4{(;Cm oNDM+2{XinUXTRR;jMU!$3xBCAox2$&F#rGn07*qoM6N<$f+i_>@c;k- diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..641bafac --- /dev/null +++ b/jest.config.js @@ -0,0 +1,8 @@ +module.exports = { + "roots": [ + "src" + ], + "transform": { + "^.+\\.ts$": "ts-jest" + }, +}; diff --git a/package-lock.json b/package-lock.json index 0faa1e03..821e2bb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,144 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/core": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.3.tgz", + "integrity": "sha512-4XFkf8AwyrEG7Ziu3L2L0Cv+WyY47Tcsp70JFmpftbAA1K7YL/sgE9jh9HyNj08Y/U50ItUchpN0w6HxAoX1rA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helpers": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.3.tgz", + "integrity": "sha512-WjoPk8hRpDRqqzRpvaR8/gDUPkrnOOeuT2m8cNICJtZH6mwaCo3v0OKMI7Y6SM1pBtyijnLtAL0HDi41pf41ug==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", + "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "dev": true + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.3.tgz", + "integrity": "sha512-LmU3q9Pah/XyZU89QvBgGt+BCsTPoQa+73RxAQh8fb8qkDyIfeQnmgs+hvzhTCKTzqOyk7JTkS3MS1S8Mq5yrQ==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, "@babel/highlight": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", @@ -24,6 +162,21 @@ "js-tokens": "^4.0.0" } }, + "@babel/parser": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.3.tgz", + "integrity": "sha512-/V72F4Yp/qmHaTALizEm9Gf2eQHV3QyTL3K0cNfijwnMnb1L+LDlAubb/ZnSdGAVzVSWakujHYs1I26x66sMeQ==", + "dev": true + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, "@babel/polyfill": { "version": "7.7.0", "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.7.0.tgz", @@ -53,6 +206,89 @@ "regenerator-runtime": "^0.13.2" } }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + } + } + }, + "@babel/traverse": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.3.tgz", + "integrity": "sha512-we+a2lti+eEImHmEXp7bM9cTxGzxPmBiVJlLVD+FuuQMeeO7RaDbutbgeheDkw+Xe3mCfJHnGOWLswT74m2IPg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.3", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + } + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, "@cliqz-oss/firefox-client": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@cliqz-oss/firefox-client/-/firefox-client-0.3.1.tgz", @@ -73,6 +309,244 @@ "es6-promise": "^2.0.1" } }, + "@cnakazawa/watch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", + "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "dev": true, + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -88,12 +562,126 @@ "defer-to-connect": "^1.0.1" } }, + "@types/babel__core": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", + "integrity": "sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz", + "integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz", + "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", + "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "dev": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/chrome": { + "version": "0.0.91", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.91.tgz", + "integrity": "sha512-vNvo9lJkp1AvViWrUwe1bxhoMwr5dRZWlgr1DTuaNkz97LsG56lDX1sceWeZir2gRACJ5vdHtoRdVAvm8C75Ug==", + "dev": true, + "requires": { + "@types/filesystem": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/filesystem": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.29.tgz", + "integrity": "sha512-85/1KfRedmfPGsbK8YzeaQUyV1FQAvMPMTuWFQ5EkLd2w7szhNO96bk3Rh/SKmOfd9co2rCLf0Voy4o7ECBOvw==", + "dev": true, + "requires": { + "@types/filewriter": "*" + } + }, + "@types/filewriter": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.28.tgz", + "integrity": "sha1-wFTor02d11205jq8dviFFocU1LM=", + "dev": true + }, + "@types/firefox-webext-browser": { + "version": "70.0.1", + "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-70.0.1.tgz", + "integrity": "sha512-hjHsTR9vKs+yikWbNS/s7TVCx15M/MEn+VYx47wtT/W/wORsIZDD75gfUfP7lkzi+IxRvKMQBB/5/wMFlfgvgQ==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", + "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "dev": true, + "requires": { + "jest-diff": "^24.3.0" + } + }, + "@types/jquery": { + "version": "3.3.31", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz", + "integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -106,24 +694,269 @@ "integrity": "sha512-hx6zWtudh3Arsbl3cXay+JnkvVgCKzCWKv42C9J01N2T2np4h8w5X8u6Tpz5mj38kE3M9FM0Pazx8vKFFMnjLQ==", "dev": true }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "dev": true + }, + "@types/yargs": { + "version": "13.0.7", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.7.tgz", + "integrity": "sha512-Sg9kNeJz+V+W+0fugcVhHC+mNHnydDR1RJrW5Qn2jVrDQARF8wfPVqIqwEzZp+bneuEBIm2ClsJ1/je42ZBzSg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", + "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz", + "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz", + "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz", + "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz", + "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz", + "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz", + "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "mamacro": "^0.0.3" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz", + "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz", + "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz", + "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz", + "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz", + "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz", + "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/helper-wasm-section": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-opt": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "@webassemblyjs/wast-printer": "1.8.5" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz", + "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz", + "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-buffer": "1.8.5", + "@webassemblyjs/wasm-gen": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz", + "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-wasm-bytecode": "1.8.5", + "@webassemblyjs/ieee754": "1.8.5", + "@webassemblyjs/leb128": "1.8.5", + "@webassemblyjs/utf8": "1.8.5" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz", + "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/floating-point-hex-parser": "1.8.5", + "@webassemblyjs/helper-api-error": "1.8.5", + "@webassemblyjs/helper-code-frame": "1.8.5", + "@webassemblyjs/helper-fsm": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz", + "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/wast-parser": "1.8.5", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, "JSONSelect": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.2.1.tgz", "integrity": "sha1-QVQYpSbTP+MddLTe+jyDbUhewgM=", "dev": true }, + "abab": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", + "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "dev": true + }, "acorn": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + } + } + }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", "dev": true }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==", + "dev": true + }, "adbkit": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/adbkit/-/adbkit-2.11.1.tgz", @@ -189,6 +1022,12 @@ "uri-js": "^4.2.2" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, "ajv-keywords": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", @@ -239,6 +1078,18 @@ } } }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -270,6 +1121,12 @@ "normalize-path": "^2.1.1" } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archiver": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/archiver/-/archiver-2.1.1.tgz", @@ -406,6 +1263,12 @@ "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, "array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", @@ -430,6 +1293,12 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -451,6 +1320,44 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -481,6 +1388,12 @@ "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -564,6 +1477,60 @@ } } }, + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", + "dev": true, + "requires": { + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + } + }, + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", + "dev": true, + "requires": { + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", + "dev": true, + "requires": { + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -640,6 +1607,12 @@ "tweetnacl": "^0.14.3" } }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -714,6 +1687,12 @@ "integrity": "sha1-L3tOyAIWMoqf3evfacjUlC/v99g=", "dev": true }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -827,6 +1806,124 @@ } } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, "buffer": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", @@ -877,6 +1974,18 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, "bunyan": { "version": "1.8.12", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", @@ -927,6 +2036,46 @@ } } }, + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1005,6 +2154,15 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -1083,8 +2241,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -1105,14 +2262,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1127,20 +2282,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -1257,8 +2409,7 @@ "inherits": { "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -1270,7 +2421,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -1285,7 +2435,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -1293,14 +2442,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -1319,7 +2466,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -1409,8 +2555,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -1422,7 +2567,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -1508,8 +2652,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -1545,7 +2688,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -1565,7 +2707,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -1609,14 +2750,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -1649,12 +2788,37 @@ } } }, + "chownr": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", + "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", "dev": true }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", @@ -1824,6 +2988,12 @@ "integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -1949,12 +3119,94 @@ } } }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-webpack-plugin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", + "dev": true, + "requires": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, "core-js": { "version": "2.6.11", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", @@ -2018,6 +3270,43 @@ } } }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -2039,6 +3328,25 @@ } } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, "crypto-random-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", @@ -2063,6 +3371,27 @@ "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", "dev": true }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -2082,6 +3411,17 @@ "assert-plus": "^1.0.0" } }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, "debounce": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", @@ -2233,6 +3573,54 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2252,12 +3640,27 @@ "entities": "^1.1.1" } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, "domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", @@ -2302,6 +3705,50 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -2321,12 +3768,33 @@ "safe-buffer": "^5.0.1" } }, + "elliptic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -2336,12 +3804,32 @@ "once": "^1.4.0" } }, + "enhanced-resolve": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2488,6 +3976,19 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "escodegen": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.13.0.tgz", + "integrity": "sha512-eYk2dCkxR07DsHA/X2hRBj0CFAZeri/LyDMc0C8JT1Hqi6JnVpMhJ7XFITbb0+yZS3lVkaPL2oCkZ3AVmeVbMw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -2500,6 +4001,16 @@ "estraverse": "^4.1.1" } }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, "eslint-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", @@ -2578,6 +4089,28 @@ "integrity": "sha1-S4TxF3K28l93Uvx02XFTGsb1tiY=", "dev": true }, + "events": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.4.tgz", + "integrity": "sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A==", + "dev": true + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -2593,6 +4126,12 @@ "strip-eof": "^1.0.0" } }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, "exit-hook": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", @@ -2649,6 +4188,29 @@ } } }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" + } + }, "ext": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", @@ -2814,6 +4376,15 @@ "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", "dev": true }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -2823,6 +4394,12 @@ "pend": "~1.2.0" } }, + "figgy-pudding": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", + "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "dev": true + }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -2862,6 +4439,38 @@ } } }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, "first-chunk-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-3.0.0.tgz", @@ -2877,6 +4486,17 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "flatstr": { @@ -2897,6 +4517,48 @@ "integrity": "sha512-0Bk1AsliuYB550zr4JV9AYhsETsD3ELXUQzdXGJfIc1Ni/ukAfBdQInDhVMYJUaT2QxoamNslwkYF7MlOrPUwg==", "dev": true }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -2929,6 +4591,48 @@ "map-cache": "^0.2.2" } }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2946,6 +4650,50 @@ "universalify": "^0.1.0" } }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2989,6 +4737,12 @@ "is-property": "^1.0.0" } }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3033,6 +4787,27 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, "global-dirs": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", @@ -3042,6 +4817,84 @@ "ini": "^1.3.5" } }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -3171,6 +5024,67 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-escaper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "dev": true + }, "htmlparser2": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", @@ -3191,6 +5105,23 @@ "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", "dev": true }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3206,6 +5137,12 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -3228,12 +5165,28 @@ "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", "dev": true }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3262,6 +5215,15 @@ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, "invert-kv": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.0.tgz", @@ -3402,6 +5364,12 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -3595,12 +5563,1229 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "istanbul-reports": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0" + } + }, "jed": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/jed/-/jed-1.1.1.tgz", "integrity": "sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=", "dev": true }, + "jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", + "dev": true, + "requires": { + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "jest-cli": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", + "dev": true, + "requires": { + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "import-local": "^2.0.0", + "is-ci": "^2.0.0", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "prompts": "^2.0.1", + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "jest-changed-files": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" + } + }, + "jest-config": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", + "glob": "^7.1.1", + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", + "dev": true, + "requires": { + "detect-newline": "^2.1.0" + } + }, + "jest-each": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-environment-jsdom": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" + } + }, + "jest-environment-node": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", + "dev": true, + "requires": { + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "fsevents": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "3.2.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.24", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.9.0", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.14.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.4.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.1", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.13", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.1.1", + "bundled": true, + "dev": true + } + } + } + } + }, + "jest-jasmine2": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "co": "^4.6.0", + "expect": "^24.9.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" + } + }, + "jest-leak-detector": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", + "dev": true, + "requires": { + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", + "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "dev": true + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", + "dev": true + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" + } + }, + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", + "dev": true, + "requires": { + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "jetpack-id": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/jetpack-id/-/jetpack-id-1.0.0.tgz", @@ -3639,6 +6824,80 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", + "dev": true + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", @@ -3693,6 +6952,23 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -3771,6 +7047,12 @@ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -3863,6 +7145,18 @@ "invert-kv": "^3.0.0" } }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -3906,6 +7200,53 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", "dev": true }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", @@ -3948,6 +7289,12 @@ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -3960,12 +7307,69 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", "dev": true }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "dev": true + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, "map-age-cleaner": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", @@ -3996,6 +7400,17 @@ "integrity": "sha512-md9k+Gxa3qLH6sUKpeC2CNkJK/Ld+bEz5X96nYwloqphQE0CKCVEKco/6jxEZixinqNdz5RFi/KaCyfbMDMAXQ==", "dev": true }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "mdn-browser-compat-data": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdn-browser-compat-data/-/mdn-browser-compat-data-1.0.1.tgz", @@ -4016,6 +7431,54 @@ "p-is-promise": "^2.1.0" } }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -4037,6 +7500,16 @@ "to-regex": "^3.0.2" } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, "mime-db": { "version": "1.42.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", @@ -4064,6 +7537,18 @@ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -4079,6 +7564,24 @@ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, "mixin-deep": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", @@ -4116,6 +7619,31 @@ "dev": true, "optional": true }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -4215,6 +7743,147 @@ "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==", "dev": true }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", + "dev": true, + "requires": { + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", @@ -4254,6 +7923,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -4336,6 +8011,16 @@ "object-keys": "^1.0.11" } }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -4377,6 +8062,12 @@ "word-wrap": "~1.2.3" } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4418,6 +8109,15 @@ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -4430,12 +8130,85 @@ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", "dev": true }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "pako": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==", "dev": true }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4445,6 +8218,36 @@ "callsites": "^3.0.0" } }, + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, "parse5": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", @@ -4460,6 +8263,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", @@ -4496,6 +8305,36 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4508,6 +8347,18 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", + "integrity": "sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pino": { "version": "5.14.0", "resolved": "https://registry.npmjs.org/pino/-/pino-5.14.0.tgz", @@ -4528,12 +8379,36 @@ "integrity": "sha512-WaL504dO8eGs+vrK+j4BuQQq6GLKeCCcHaMB2ItygzVURcL1CycwNEUHTD/lHFHs/NL5qAz2UKrjYWXKSf4aMQ==", "dev": true }, + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "dev": true, + "requires": { + "node-modules-regexp": "^1.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, "pluralize": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", "dev": true }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -4574,6 +8449,26 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, "probe-image-size": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-5.0.0.tgz", @@ -4628,6 +8523,12 @@ } } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4640,12 +8541,48 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prompts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", + "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.3" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, "psl": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", "dev": true }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4656,6 +8593,29 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -4668,12 +8628,43 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, "quick-format-unescaped": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-3.0.3.tgz", "integrity": "sha512-dy1yjycmn9blucmJLXOfZDx1ikZJUi6E8bBZLnhPG5gBrVhHXx2xVyqqgKBubVNEXmx51dBACMHpoMQK/N/AXQ==", "dev": true }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4700,6 +8691,33 @@ } } }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + }, "readable-stream": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", @@ -4782,6 +8800,15 @@ } } }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -4851,6 +8878,54 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", + "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "request-promise-native": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", + "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "dev": true, + "requires": { + "request-promise-core": "1.1.3", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4890,6 +8965,46 @@ "path-parse": "^1.0.6" } }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4918,14 +9033,30 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.1.tgz", + "integrity": "sha512-IQ4ikL8SjBiEDZfk+DFVwqRK8md24RWMEJkdSlgNLkyyAImcjf8SWvU1qFMDOb4igBClbTQ/ugPqXcRwdFTxZw==", "dev": true, "requires": { "glob": "^7.1.3" } }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -4935,6 +9066,15 @@ "is-promise": "^2.1.0" } }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, "rx-lite": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", @@ -4978,18 +9118,68 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "dependencies": { + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + } + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -5019,6 +9209,12 @@ } } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -5168,6 +9364,18 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "sisteransi": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", + "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "slice-ansi": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", @@ -5337,6 +9545,12 @@ "flatstr": "^1.0.12" } }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5369,6 +9583,38 @@ "os-shim": "^0.1.2" } }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -5410,6 +9656,21 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -5431,6 +9692,109 @@ } } }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "stream-parser": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", @@ -5457,6 +9821,12 @@ } } }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "stream-to-array": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", @@ -5497,6 +9867,33 @@ } } }, + "string-length": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "dev": true, + "requires": { + "astral-regex": "^1.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -5565,6 +9962,12 @@ } } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "strip-bom-buf": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz", @@ -5605,6 +10008,12 @@ "has-flag": "^3.0.0" } }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "table": { "version": "5.4.6", "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", @@ -5642,6 +10051,12 @@ } } }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, "tar-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", @@ -5695,6 +10110,54 @@ "integrity": "sha512-UqvQSch04R+69g4RDhrslmGvGL3ucDRX/U+snYW0Mab4uCAyKSndUksaoqlJ81QKSpRnIsuOYQCbC2ZWx2896A==", "dev": true }, + "terser": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5719,12 +10182,69 @@ "thenify": ">= 3.1.0 < 4" } }, + "throat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "timers-browserify": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -5734,12 +10254,30 @@ "os-tmpdir": "~1.0.2" } }, + "tmpl": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", + "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", "dev": true }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -5827,12 +10365,132 @@ "integrity": "sha1-0EsigOTHkqWBVCnve4tgxkyczDQ=", "dev": true }, + "ts-jest": { + "version": "24.3.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.3.0.tgz", + "integrity": "sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "mkdirp": "0.x", + "resolve": "1.x", + "semver": "^5.5", + "yargs-parser": "10.x" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "ts-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-6.2.1.tgz", + "integrity": "sha512-Dd9FekWuABGgjE1g0TlQJ+4dFUfYGbYcs52/HQObE0ZmUNjQlmLAS7xXsSzy23AMaMwipsx5sNHvoEpT2CZq1g==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^1.0.2", + "micromatch": "^4.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", "dev": true }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5890,6 +10548,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", + "dev": true + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -5902,6 +10566,24 @@ "set-value": "^2.0.1" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -5978,6 +10660,24 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -6002,18 +10702,84 @@ "os-homedir": "^1.0.0" } }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + } + } + }, "uuid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", "dev": true }, + "v8-compile-cache": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz", + "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -6025,6 +10791,30 @@ "extsprintf": "^1.2.0" } }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "walker": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", + "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "dev": true, + "requires": { + "makeerror": "1.0.x" + } + }, "watchpack": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", @@ -6224,6 +11014,17 @@ "lighthouse-logger": "^1.0.0", "mkdirp": "0.5.1", "rimraf": "^2.6.1" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "cli-cursor": { @@ -6768,6 +11569,17 @@ "graceful-fs": "^4.1.2", "rimraf": "~2.6.2", "write": "^0.2.1" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "fx-runner": { @@ -7087,6 +11899,17 @@ "dev": true, "requires": { "rimraf": "^2.6.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "update-notifier": { @@ -7242,6 +12065,333 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", "dev": true }, + "webpack": { + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.8.5", + "@webassemblyjs/helper-module-context": "1.8.5", + "@webassemblyjs/wasm-edit": "1.8.5", + "@webassemblyjs/wasm-parser": "1.8.5", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.1.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.10.tgz", + "integrity": "sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg==", + "dev": true, + "requires": { + "chalk": "2.4.2", + "cross-spawn": "6.0.5", + "enhanced-resolve": "4.1.0", + "findup-sync": "3.0.0", + "global-modules": "2.0.0", + "import-local": "2.0.0", + "interpret": "1.2.0", + "loader-utils": "1.2.3", + "supports-color": "6.1.0", + "v8-compile-cache": "2.0.3", + "yargs": "13.2.4" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "enhanced-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", + "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.4.0", + "tapable": "^1.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, "whatwg-url": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", @@ -7295,6 +12445,15 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7381,6 +12540,12 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, "xml2js": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", @@ -7418,6 +12583,12 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "yargs": { "version": "15.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", diff --git a/package.json b/package.json index c5dadd4a..5780b5b2 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,27 @@ "main": "background.js", "dependencies": {}, "devDependencies": { - "web-ext": "^4.0.0" + "web-ext": "^4.0.0", + "@types/chrome": "0.0.91", + "@types/firefox-webext-browser": "70.0.1", + "@types/jest": "^24.0.23", + "@types/jquery": "^3.3.31", + "copy-webpack-plugin": "^5.0.5", + "jest": "^24.9.0", + "ts-jest": "^24.2.0", + "rimraf": "^3.0.0", + "ts-loader": "^6.2.1", + "typescript": "~3.7.3", + "webpack": "~4.41.2", + "webpack-cli": "~3.3.10", + "webpack-merge": "~4.2.2" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "dev": "web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm", - "build": "web-ext build --overwrite-dest -i \"*(package-lock.json|README.md|package.json|config.js.example|firefox_manifest-extra.json|manifest.json.original|ignored|crowdin.yml)\"" + "dev": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm", + "watch": "webpack --config webpack/webpack.dev.js --watch", + "build": "webpack --config webpack/webpack.prod.js", + "clean": "rimraf dist", + "test": "npx jest" }, "repository": { "type": "git", diff --git a/_locales/de/messages.json b/public/_locales/de/messages.json similarity index 100% rename from _locales/de/messages.json rename to public/_locales/de/messages.json diff --git a/_locales/en/messages.json b/public/_locales/en/messages.json similarity index 100% rename from _locales/en/messages.json rename to public/_locales/en/messages.json diff --git a/_locales/fr/messages.json b/public/_locales/fr/messages.json similarity index 100% rename from _locales/fr/messages.json rename to public/_locales/fr/messages.json diff --git a/_locales/it/messages.json b/public/_locales/it/messages.json similarity index 100% rename from _locales/it/messages.json rename to public/_locales/it/messages.json diff --git a/_locales/pl_PL/messages.json b/public/_locales/pl_PL/messages.json similarity index 100% rename from _locales/pl_PL/messages.json rename to public/_locales/pl_PL/messages.json diff --git a/_locales/pt_BR/messages.json b/public/_locales/pt_BR/messages.json similarity index 100% rename from _locales/pt_BR/messages.json rename to public/_locales/pt_BR/messages.json diff --git a/_locales/pt_pt/messages.json b/public/_locales/pt_pt/messages.json similarity index 100% rename from _locales/pt_pt/messages.json rename to public/_locales/pt_pt/messages.json diff --git a/_locales/ru/messages.json b/public/_locales/ru/messages.json similarity index 100% rename from _locales/ru/messages.json rename to public/_locales/ru/messages.json diff --git a/content.css b/public/content.css similarity index 100% rename from content.css rename to public/content.css diff --git a/firefox_manifest-extra.json b/public/firefox_manifest-extra.json similarity index 100% rename from firefox_manifest-extra.json rename to public/firefox_manifest-extra.json diff --git a/help/index_en.html b/public/help/index_en.html similarity index 100% rename from help/index_en.html rename to public/help/index_en.html diff --git a/help/styles.css b/public/help/styles.css similarity index 100% rename from help/styles.css rename to public/help/styles.css diff --git a/icons/IconSponsorBlocker16px.png b/public/icons/IconSponsorBlocker16px.png similarity index 100% rename from icons/IconSponsorBlocker16px.png rename to public/icons/IconSponsorBlocker16px.png diff --git a/icons/IconSponsorBlocker256px.png b/public/icons/IconSponsorBlocker256px.png similarity index 100% rename from icons/IconSponsorBlocker256px.png rename to public/icons/IconSponsorBlocker256px.png diff --git a/icons/IconSponsorBlocker32px.png b/public/icons/IconSponsorBlocker32px.png similarity index 100% rename from icons/IconSponsorBlocker32px.png rename to public/icons/IconSponsorBlocker32px.png diff --git a/icons/LogoSponsorBlocker128px.png b/public/icons/LogoSponsorBlocker128px.png similarity index 100% rename from icons/LogoSponsorBlocker128px.png rename to public/icons/LogoSponsorBlocker128px.png diff --git a/icons/LogoSponsorBlocker256px.png b/public/icons/LogoSponsorBlocker256px.png similarity index 100% rename from icons/LogoSponsorBlocker256px.png rename to public/icons/LogoSponsorBlocker256px.png diff --git a/icons/LogoSponsorBlocker64px.png b/public/icons/LogoSponsorBlocker64px.png similarity index 100% rename from icons/LogoSponsorBlocker64px.png rename to public/icons/LogoSponsorBlocker64px.png diff --git a/icons/PlayerDeleteIconSponsorBlocker256px.png b/public/icons/PlayerDeleteIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerDeleteIconSponsorBlocker256px.png rename to public/icons/PlayerDeleteIconSponsorBlocker256px.png diff --git a/icons/PlayerInfoIconSponsorBlocker256px.png b/public/icons/PlayerInfoIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerInfoIconSponsorBlocker256px.png rename to public/icons/PlayerInfoIconSponsorBlocker256px.png diff --git a/icons/PlayerStartIconSponsorBlocker256px.png b/public/icons/PlayerStartIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerStartIconSponsorBlocker256px.png rename to public/icons/PlayerStartIconSponsorBlocker256px.png diff --git a/icons/PlayerStopIconSponsorBlocker256px.png b/public/icons/PlayerStopIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerStopIconSponsorBlocker256px.png rename to public/icons/PlayerStopIconSponsorBlocker256px.png diff --git a/icons/PlayerUploadFailedIconSponsorBlocker256px.png b/public/icons/PlayerUploadFailedIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerUploadFailedIconSponsorBlocker256px.png rename to public/icons/PlayerUploadFailedIconSponsorBlocker256px.png diff --git a/icons/PlayerUploadIconSponsorBlocker256px.png b/public/icons/PlayerUploadIconSponsorBlocker256px.png similarity index 100% rename from icons/PlayerUploadIconSponsorBlocker256px.png rename to public/icons/PlayerUploadIconSponsorBlocker256px.png diff --git a/icons/close.png b/public/icons/close.png similarity index 100% rename from icons/close.png rename to public/icons/close.png diff --git a/icons/downvote.png b/public/icons/downvote.png similarity index 100% rename from icons/downvote.png rename to public/icons/downvote.png diff --git a/icons/newprofilepic.jpg b/public/icons/newprofilepic.jpg similarity index 100% rename from icons/newprofilepic.jpg rename to public/icons/newprofilepic.jpg diff --git a/icons/report.png b/public/icons/report.png similarity index 100% rename from icons/report.png rename to public/icons/report.png diff --git a/icons/upvote.png b/public/icons/upvote.png similarity index 100% rename from icons/upvote.png rename to public/icons/upvote.png diff --git a/icons/upvote.svg b/public/icons/upvote.svg similarity index 100% rename from icons/upvote.svg rename to public/icons/upvote.svg diff --git a/libs/Source+Sans+Pro.css b/public/libs/Source+Sans+Pro.css similarity index 100% rename from libs/Source+Sans+Pro.css rename to public/libs/Source+Sans+Pro.css diff --git a/manifest.json b/public/manifest.json similarity index 100% rename from manifest.json rename to public/manifest.json diff --git a/popup.css b/public/popup.css similarity index 100% rename from popup.css rename to public/popup.css diff --git a/popup.html b/public/popup.html similarity index 100% rename from popup.html rename to public/popup.html diff --git a/SB.js b/src/SB.ts similarity index 54% rename from SB.js rename to src/SB.ts index 86582311..751137f1 100644 --- a/SB.js +++ b/src/SB.ts @@ -1,82 +1,118 @@ -SB = { + +interface SBObject { + configListeners: Array; + defaults: any; + localConfig: any; + config: any; +} + +// Allows a SBMap to be conveted into json form +// Currently used for local storage +class SBMap extends Map { + toJSON() { + return Array.from(this.entries()); + } +} + + +// TODO: Rename to something more meaningful +var SB: SBObject = { /** * Callback function when an option is updated - * - * @type {CallableFunction} */ - configListeners: [] + configListeners: [], + defaults: { + "sponsorTimes": new SBMap(), + "startSponsorKeybind": ";", + "submitKeybind": "'", + "minutesSaved": 0, + "skipCount": 0, + "sponsorTimesContributed": 0, + "disableSkipping": false, + "disableAutoSkip": false, + "trackViewCount": true, + "dontShowNotice": false, + "hideVideoPlayerControls": false, + "hideInfoButtonPlayerControls": false, + "hideDeleteButtonPlayerControls": false, + "hideDiscordLaunches": 0, + "hideDiscordLink": false, + "invidiousInstances": ["invidio.us", "invidiou.sh", "invidious.snopyta.org"], + "invidiousUpdateInfoShowCount": 0, + "autoUpvote": true + }, + localConfig: {}, + config: {} }; // Function setup -// Allows a map to be conveted into json form -// Currently used for local storage -Map.prototype.toJSON = function() { - return Array.from(this.entries()); -}; - // Proxy Map changes to Map in SB.localConfig // Saves the changes to chrome.storage in json form class MapIO { + id: string; + SBMap: SBMap; + constructor(id) { - // The name of the item in the array + // The name of the item in the array this.id = id; - // A local copy of the map (SB.config.mapname.map) - this.map = SB.localConfig[this.id]; + // A local copy of the SBMap (SB.config.SBMapname.SBMap) + this.SBMap = SB.localConfig[this.id]; } + set(key, value) { - // Proxy to map - this.map.set(key, value); - // Store updated map locally + // Proxy to SBMap + this.SBMap.set(key, value); + // Store updated SBMap locally chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.map) + [this.id]: encodeStoredItem(this.SBMap) }); - return this.map; + return this.SBMap; } get(key) { - return this.map.get(key); + return this.SBMap.get(key); } has(key) { - return this.map.has(key); + return this.SBMap.has(key); } size() { - return this.map.size; + return this.SBMap.size; } delete(key) { - // Proxy to map - this.map.delete(key); - // Store updated map locally - chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.map) + // Proxy to SBMap + this.SBMap.delete(key); + // Store updated SBMap locally + chrome.storage.sync.set({ + [this.id]: encodeStoredItem(this.SBMap) }); } clear() { - this.map.clear(); - chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.map) + this.SBMap.clear(); + chrome.storage.sync.set({ + [this.id]: encodeStoredItem(this.SBMap) }); } } /** - * A Map cannot be stored in the chrome storage. + * A SBMap cannot be stored in the chrome storage. * This data will be encoded into an array instead as specified by the toJSON function. * * @param {*} data */ function encodeStoredItem(data) { - // if data is Map convert to json for storing - if(!(data instanceof Map)) return data; + // if data is SBMap convert to json for storing + if(!(data instanceof SBMap)) return data; return JSON.stringify(data); } /** - * A Map cannot be stored in the chrome storage. + * A SBMap cannot be stored in the chrome storage. * This data will be decoded from the array it is stored in * * @param {*} data @@ -88,7 +124,7 @@ function decodeStoredItem(data) { let str = JSON.parse(data); if(!Array.isArray(str)) return data; - return new Map(str); + return new SBMap(str); } catch(e) { // If all else fails, return the data @@ -96,7 +132,7 @@ function decodeStoredItem(data) { } } -function configProxy() { +function configProxy(): void { chrome.storage.onChanged.addListener((changes, namespace) => { for (const key in changes) { SB.localConfig[key] = decodeStoredItem(changes[key].newValue); @@ -107,24 +143,28 @@ function configProxy() { } }); - var handler = { + var handler: ProxyHandler = { set(obj, prop, value) { SB.localConfig[prop] = value; chrome.storage.sync.set({ [prop]: encodeStoredItem(value) }); + + return true; }, - get(obj, prop) { + get(obj, prop): any { let data = SB.localConfig[prop]; - if(data instanceof Map) data = new MapIO(prop); + if(data instanceof SBMap) data = new MapIO(prop); return obj[prop] || data; }, deleteProperty(obj, prop) { - chrome.storage.sync.remove(prop); + chrome.storage.sync.remove( prop); + + return true; } }; @@ -158,27 +198,6 @@ async function setupConfig() { migrateOldFormats(); } -SB.defaults = { - "sponsorTimes": new Map(), - "startSponsorKeybind": ";", - "submitKeybind": "'", - "minutesSaved": 0, - "skipCount": 0, - "sponsorTimesContributed": 0, - "disableSkipping": false, - "disableAutoSkip": false, - "trackViewCount": true, - "dontShowNotice": false, - "hideVideoPlayerControls": false, - "hideInfoButtonPlayerControls": false, - "hideDeleteButtonPlayerControls": false, - "hideDiscordLaunches": 0, - "hideDiscordLink": false, - "invidiousInstances": ["invidio.us", "invidiou.sh", "invidious.snopyta.org"], - "invidiousUpdateInfoShowCount": 0, - "autoUpvote": true -} - // Reset config function resetConfig() { SB.config = SB.defaults; @@ -201,3 +220,5 @@ function addDefaults() { // Sync config setupConfig(); + +export default SB; \ No newline at end of file diff --git a/background.js b/src/background.js similarity index 100% rename from background.js rename to src/background.js diff --git a/src/config.js.example b/src/config.js.example new file mode 100644 index 00000000..23cc0be3 --- /dev/null +++ b/src/config.js.example @@ -0,0 +1,3 @@ +//this file is loaded along iwth content.js +//this file sets the server to connect to, and is gitignored +var serverAddress = "https://sponsor.ajay.app"; \ No newline at end of file diff --git a/content.js b/src/content.ts similarity index 93% rename from content.js rename to src/content.ts index fd36a886..43c6849b 100644 --- a/content.js +++ b/src/content.ts @@ -1,3 +1,9 @@ +import Utils from "./utils"; +import SB from "./SB"; + +import PreviewBar from "./js-components/previewBar"; +import SkipNotice from "./js-components/previewBar"; + //was sponsor data found when doing SponsorsLookup var sponsorDataFound = false; var previousVideoID = null; @@ -40,7 +46,7 @@ var previewBar = null; var controls = null; // Direct Links -videoIDChange(getYouTubeVideoID(document.URL)); +videoIDChange(Utils.getYouTubeVideoID(document.URL)); //the last time looked at (used to see if this time is in the interval) var lastTime = -1; @@ -72,7 +78,7 @@ function messageListener(request, sender, sendResponse) { //messages from popup script switch(request.message){ case "update": - videoIDChange(getYouTubeVideoID(document.URL)); + videoIDChange(Utils.getYouTubeVideoID(document.URL)); break; case "sponsorStart": sponsorMessageStarted(sendResponse); @@ -166,7 +172,6 @@ if (!SB.configListeners.includes(contentConfigUpdateListener)) { //check for hotkey pressed document.onkeydown = async function(e){ - e = e || window.event; var key = e.key; let video = document.getElementById("movie_player"); @@ -217,13 +222,13 @@ function videoIDChange(id) { //id is not valid if (!id) return; - let channelIDPromise = wait(getChannelID); + let channelIDPromise = Utils.wait(getChannelID); channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true); //setup the preview bar if (previewBar == null) { //create it - wait(getControls).then(result => { + Utils.wait(getControls).then(result => { const progressElementSelectors = [ // For YouTube "ytp-progress-bar-container", @@ -274,7 +279,7 @@ function videoIDChange(id) { sponsorTimesSubmitting = []; //see if the onvideo control image needs to be changed - wait(getControls).then(result => { + Utils.wait(getControls).then(result => { chrome.runtime.sendMessage({ message: "getSponsorTimes", videoID: id @@ -299,12 +304,12 @@ function videoIDChange(id) { }); }); //see if video controls buttons should be added - if (!onInvidious) { + if (!Utils.onInvidious) { updateVisibilityOfPlayerControlsButton(); } } -function sponsorsLookup(id, channelIDPromise) { +function sponsorsLookup(id: string, channelIDPromise = null) { v = document.querySelector('video') // Youtube video player //there is no video here if (v == null) { @@ -324,7 +329,7 @@ function sponsorsLookup(id, channelIDPromise) { whitelistCheck(); } else if (channelIDPromise.isRejected) { //try again - wait(getChannelID).then(whitelistCheck).catch(); + Utils.wait(getChannelID).then(whitelistCheck).catch(); } else { //add it as a then statement channelIDPromise.then(whitelistCheck); @@ -410,7 +415,7 @@ function updatePreviewBar() { types.push("previewSponsor"); } - wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); + Utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); //update last video id lastPreviewBarUpdate = sponsorVideoID; @@ -423,7 +428,7 @@ function getChannelID() { channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text"); if (channelURLContainer !== null) { channelURLContainer = channelURLContainer.firstElementChild; - } else if (onInvidious) { + } else if (Utils.onInvidious) { // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a"); } else { @@ -443,8 +448,8 @@ function getChannelID() { let titleInfoContainer = document.getElementById("info-contents"); let currentTitle = ""; if (titleInfoContainer != null) { - currentTitle = titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild.innerText; - } else if (onInvidious) { + currentTitle = ( titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild).innerText; + } else if (Utils.onInvidious) { // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent; } else { @@ -637,7 +642,7 @@ function getControls() { //adds all the player controls buttons async function createButtons() { - let result = await wait(getControls).catch(); + let result = await Utils.wait(getControls).catch(); //set global controls variable controls = result; @@ -655,7 +660,7 @@ async function updateVisibilityOfPlayerControlsButton() { await createButtons(); - if (SB.config.hideVideoPlayerControls || onInvidious) { + if (SB.config.hideVideoPlayerControls || Utils.onInvidious) { document.getElementById("startSponsorButton").style.display = "none"; document.getElementById("submitButton").style.display = "none"; } else { @@ -663,13 +668,13 @@ async function updateVisibilityOfPlayerControlsButton() { } //don't show the info button on embeds - if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious) { + if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || Utils.onInvidious) { document.getElementById("infoButton").style.display = "none"; } else { document.getElementById("infoButton").style.removeProperty("display"); } - if (SB.config.hideDeleteButtonPlayerControls || onInvidious) { + if (SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious) { document.getElementById("deleteButton").style.display = "none"; } } @@ -718,15 +723,15 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { if(!sponsorVideoID) return false; //make sure submit button is loaded - await wait(isSubmitButtonLoaded); + await Utils.wait(isSubmitButtonLoaded); //if it isn't visible, there is no data - let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none" + let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious)) ? "unset" : "none" document.getElementById("deleteButton").style.display = shouldHide; if (showStartSponsor) { showingStartSponsor = true; - document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png"); + ( document.getElementById("startSponsorImage")).src = chrome.extension.getURL("icons/PlayerStartIconSponsorBlocker256px.png"); document.getElementById("startSponsorButton").setAttribute("title", chrome.i18n.getMessage("sponsorStart")); if (document.getElementById("startSponsorImage").style.display != "none" && uploadButtonVisible && !SB.config.hideInfoButtonPlayerControls) { @@ -737,7 +742,7 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { } } else { showingStartSponsor = false; - document.getElementById("startSponsorImage").src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png"); + ( document.getElementById("startSponsorImage")).src = chrome.extension.getURL("icons/PlayerStopIconSponsorBlocker256px.png"); document.getElementById("startSponsorButton").setAttribute("title", chrome.i18n.getMessage("sponsorEND")); //disable submit button @@ -769,7 +774,7 @@ function openInfoMenu() { //close button let closeButton = document.createElement("div"); closeButton.innerText = "Close Popup"; - closeButton.classList = "smallLink"; + closeButton.classList.add("smallLink"); closeButton.setAttribute("align", "center"); closeButton.addEventListener("click", closeInfoMenu); @@ -791,7 +796,7 @@ function openInfoMenu() { //make the logo source not 404 //query selector must be used since getElementByID doesn't work on a node and this isn't added to the document yet - let logo = popup.querySelector("#sponsorBlockPopupLogo"); + let logo = popup.querySelector("#sponsorBlockPopupLogo"); logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png"); //remove the style sheet and font that are not necessary @@ -889,7 +894,7 @@ function vote(type, UUID, skipNotice) { skipNotice.addNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail")) skipNotice.resetVoteButtonInfo.bind(skipNotice)(); } else if (response.successType == -1) { - skipNotice.addNoticeInfoMessage.bind(skipNotice)(getErrorMessage(response.statusCode)) + skipNotice.addNoticeInfoMessage.bind(skipNotice)(Utils.getErrorMessage(response.statusCode)) skipNotice.resetVoteButtonInfo.bind(skipNotice)(); } } @@ -961,7 +966,7 @@ function submitSponsorTimes() { //called after all the checks have been made that it's okay to do so function sendSubmitMessage(){ //add loading animation - document.getElementById("submitImage").src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png"); + ( document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadIconSponsorBlocker256px.png"); document.getElementById("submitButton").style.animation = "rotate 1s 0s infinite"; let currentVideoID = sponsorVideoID; @@ -994,7 +999,7 @@ function sendSubmitMessage(){ sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting); for (let i = 0; i < sponsorTimesSubmitting.length; i++) { // Add some random IDs - UUIDs.push(generateUserID()); + UUIDs.push(Utils.generateUserID()); } // Empty the submitting times @@ -1004,9 +1009,9 @@ function sendSubmitMessage(){ } else { //show that the upload failed document.getElementById("submitButton").style.animation = "unset"; - document.getElementById("submitImage").src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); + ( document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); - alert(getErrorMessage(response.statusCode)); + alert(Utils.getErrorMessage(response.statusCode)); } } }); @@ -1037,23 +1042,25 @@ function getSponsorTimesMessage(sponsorTimes) { //converts time in seconds to minutes:seconds function getFormattedTime(seconds) { let minutes = Math.floor(seconds / 60); - let secondsDisplay = Math.round(seconds - minutes * 60); - if (secondsDisplay < 10) { + let secondsNum: number = Math.round(seconds - minutes * 60); + let secondsDisplay: string = String(secondsNum); + + if (secondsNum < 10) { //add a zero - secondsDisplay = "0" + secondsDisplay; + secondsDisplay = "0" + secondsNum; } - let formatted = minutes+ ":" + secondsDisplay; + let formatted = minutes + ":" + secondsDisplay; return formatted; } -function sendRequestToServer(type, address, callback) { +function sendRequestToServer(type: string, address: string, callback = null) { let xmlhttp = new XMLHttpRequest(); xmlhttp.open(type, serverAddress + address, true); - if (callback != undefined) { + if (callback !== null) { xmlhttp.onreadystatechange = function () { callback(xmlhttp, false); }; diff --git a/utils/previewBar.js b/src/js-components/previewBar.ts similarity index 89% rename from utils/previewBar.js rename to src/js-components/previewBar.ts index e5a74b62..5c43c984 100644 --- a/utils/previewBar.js +++ b/src/js-components/previewBar.ts @@ -21,11 +21,13 @@ let barTypes = { }; class PreviewBar { + container: HTMLUListElement; + parent: any; + constructor(parent) { this.container = document.createElement('ul'); this.container.id = 'previewbar'; this.parent = parent; - this.bars = [] this.updatePosition(); } @@ -39,7 +41,7 @@ class PreviewBar { } updateColor(segment, color, opacity) { - let bars = document.querySelectorAll('[data-vs-segment-type=' + segment + ']'); + let bars = > document.querySelectorAll('[data-vs-segment-type=' + segment + ']'); for (let bar of bars) { bar.style.backgroundColor = color; bar.style.opacity = opacity; @@ -73,8 +75,7 @@ class PreviewBar { bar.style.left = (timestamps[i][0] / duration * 100) + "%"; bar.style.position = "absolute" - this.container.insertAdjacentElement('beforeEnd', bar); - this.bars[i] = bar; + this.container.insertAdjacentElement("beforeEnd", bar); } } @@ -89,4 +90,6 @@ class PreviewBar { this.container.remove(); this.container = undefined; } -} \ No newline at end of file +} + +export default PreviewBar; \ No newline at end of file diff --git a/utils/skipNotice.js b/src/js-components/skipNotice.ts similarity index 96% rename from utils/skipNotice.js rename to src/js-components/skipNotice.ts index cea3a8ad..27d8425b 100644 --- a/utils/skipNotice.js +++ b/src/js-components/skipNotice.ts @@ -4,13 +4,16 @@ * The notice that tells the user that a sponsor was just skipped */ class SkipNotice { - /** - * @param {HTMLElement} parent - * @param {String} UUID - * @param {String} noticeTitle - * @param {boolean} manualSkip - */ - constructor(parent, UUID, manualSkip = false) { + parent: HTMLElement; + UUID: string; + manualSkip: boolean; + maxCountdownTime: () => number; + countdownTime: any; + countdownInterval: number; + unskipCallback: any; + idSuffix: any; + + constructor(parent: HTMLElement, UUID: string, manualSkip: boolean = false) { this.parent = parent; this.UUID = UUID; this.manualSkip = manualSkip; @@ -48,7 +51,7 @@ class SkipNotice { noticeElement.id = "sponsorSkipNotice" + this.idSuffix; noticeElement.classList.add("sponsorSkipObject"); noticeElement.classList.add("sponsorSkipNotice"); - noticeElement.style.zIndex = 50 + amountOfPreviousNotices; + noticeElement.style.zIndex = String(50 + amountOfPreviousNotices); //add mouse enter and leave listeners noticeElement.addEventListener("mouseenter", this.pauseCountdown.bind(this)); @@ -170,12 +173,12 @@ class SkipNotice { if (referenceNode == null) { //for embeds let player = document.getElementById("player"); - referenceNode = player.firstChild; + referenceNode = player.firstChild; let index = 1; //find the child that is the video player (sometimes it is not the first) while (!referenceNode.classList.contains("html5-video-player") || !referenceNode.classList.contains("ytp-embed")) { - referenceNode = player.children[index]; + referenceNode = player.children[index]; index++; } @@ -336,7 +339,7 @@ class SkipNotice { noticeElement.innerText = title; } - addNoticeInfoMessage(message, message2) { + addNoticeInfoMessage(message: string, message2: string = "") { let previousInfoMessage = document.getElementById("sponsorTimesInfoMessage" + this.idSuffix); if (previousInfoMessage != null) { //remove it @@ -426,3 +429,5 @@ class SkipNotice { } } + +export default SkipNotice; \ No newline at end of file diff --git a/popup.js b/src/popup.js similarity index 100% rename from popup.js rename to src/popup.js diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..81f76be6 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,279 @@ +import SB from "./SB"; + +class Utils { + + static isBackgroundScript = false; + static onInvidious = false; + + // Function that can be used to wait for a condition before returning + static async wait(condition, timeout = 5000, check = 100) { + return await new Promise((resolve, reject) => { + setTimeout(() => reject("TIMEOUT"), timeout); + + let intervalCheck = () => { + let result = condition(); + if (result !== false) { + resolve(result); + clearInterval(interval); + }; + }; + + let interval = setInterval(intervalCheck, check); + + //run the check once first, this speeds it up a lot + intervalCheck(); + }); + } + + static getYouTubeVideoID(url: string) { + // For YouTube TV support + if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", ""); + + //Attempt to parse url + let urlObject = null; + try { + urlObject = new URL(url); + } catch (e) { + console.error("[SB] Unable to parse URL: " + url); + return false; + } + + //Check if valid hostname + if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) { + onInvidious = true; + } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { + if (!SB.config) { + // Call this later, in case this is an Invidious tab + this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); + } + + return false + } + + //Get ID from searchParam + if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) { + let id = urlObject.searchParams.get("v"); + return id.length == 11 ? id : false; + } else if (urlObject.pathname.startsWith("/embed/")) { + try { + return urlObject.pathname.substr(7, 11); + } catch (e) { + console.error("[SB] Video ID not valid for " + url); + return false; + } + } + return false; + } + + /** + * Asks for the optional permissions required for all extra sites. + * It also starts the content script registrations. + * + * For now, it is just SB.config.invidiousInstances. + * + * @param {CallableFunction} callback + */ + static setupExtraSitePermissions(callback) { + // Request permission + let permissions = ["declarativeContent"]; + if (this.isFirefox()) permissions = []; + + chrome.permissions.request({ + origins: this.getInvidiousInstancesRegex(), + permissions: permissions + }, async function (granted) { + if (granted) { + this.setupExtraSiteContentScripts(); + } else { + this.removeExtraSiteRegistration(); + } + + callback(granted); + }); + } + + /** + * Registers the content scripts for the extra sites. + * Will use a different method depending on the browser. + * This is called by setupExtraSitePermissions(). + * + * For now, it is just SB.config.invidiousInstances. + */ + static setupExtraSiteContentScripts() { + let js = [ + "config.js", + "SB.js", + "utils/previewBar.js", + "utils/skipNotice.js", + "utils.js", + "content.js", + "popup.js" + ]; + let css = [ + "content.css", + "./libs/Source+Sans+Pro.css", + "popup.css" + ]; + + if (this.isFirefox()) { + let firefoxJS = []; + for (const file of js) { + firefoxJS.push({file}); + } + let firefoxCSS = []; + for (const file of css) { + firefoxCSS.push({file}); + } + + let registration = { + message: "registerContentScript", + id: "invidious", + allFrames: true, + js: firefoxJS, + css: firefoxCSS, + matches: this.getInvidiousInstancesRegex() + }; + + if (isBackgroundScript) { + registerFirefoxContentScript(registration); + } else { + chrome.runtime.sendMessage(registration); + } + } else { + chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() { + let conditions = []; + for (const regex of this.getInvidiousInstancesRegex()) { + conditions.push(new chrome.declarativeContent.PageStateMatcher({ + pageUrl: { urlMatches: regex } + })); + } + + // Add page rule + let rule = { + id: "invidious", + conditions, + // This API is experimental and not visible by the TypeScript compiler + actions: [new ( chrome.declarativeContent).RequestContentScript({ + allFrames: true, + js, + css + })] + }; + + chrome.declarativeContent.onPageChanged.addRules([rule]); + }); + } + } + + /** + * Removes the permission and content script registration. + */ + static removeExtraSiteRegistration() { + if (this.isFirefox()) { + let id = "invidious"; + + if (isBackgroundScript) { + if (contentScriptRegistrations[id]) { + contentScriptRegistrations[id].unregister(); + delete contentScriptRegistrations[id]; + } + } else { + chrome.runtime.sendMessage({ + message: "unregisterContentScript", + id: id + }); + } + } else { + chrome.declarativeContent.onPageChanged.removeRules(["invidious"]); + } + + chrome.permissions.remove({ + origins: this.getInvidiousInstancesRegex() + }); + } + + static localizeHtmlPage() { + //Localize by replacing __MSG_***__ meta tags + var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; + for (var j = 0; j < objects.length; j++) { + var obj = objects[j]; + + let localizedMessage = this.getLocalizedMessage(obj.innerHTML.toString()); + if (localizedMessage) obj.innerHTML = localizedMessage; + } + } + + static getLocalizedMessage(text) { + var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) { + return v1 ? chrome.i18n.getMessage(v1) : ""; + }); + + if(valNewH != text) { + return valNewH; + } else { + return false; + } + } + + /** + * @returns {String[]} Invidious Instances in regex form + */ + static getInvidiousInstancesRegex() { + var invidiousInstancesRegex = []; + for (const url of SB.config.invidiousInstances) { + invidiousInstancesRegex.push("https://*." + url + "/*"); + invidiousInstancesRegex.push("http://*." + url + "/*"); + } + + return invidiousInstancesRegex; + } + + static generateUserID(length = 36) { + let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let result = ""; + if (window.crypto && window.crypto.getRandomValues) { + let values = new Uint32Array(length); + window.crypto.getRandomValues(values); + for (let i = 0; i < length; i++) { + result += charset[values[i] % charset.length]; + } + return result; + } else { + for (let i = 0; i < length; i++) { + result += charset[Math.floor(Math.random() * charset.length)]; + } + return result; + } + } + + /** + * Gets the error message in a nice string + * + * @param {int} statusCode + * @returns {string} errorMessage + */ + static getErrorMessage(statusCode) { + let errorMessage = ""; + + if([400, 429, 409, 502, 0].includes(statusCode)) { + //treat them the same + if (statusCode == 503) statusCode = 502; + + errorMessage = chrome.i18n.getMessage(statusCode + "") + " " + chrome.i18n.getMessage("errorCode") + statusCode + + "\n\n" + chrome.i18n.getMessage("statusReminder"); + } else { + errorMessage = chrome.i18n.getMessage("connectionError") + statusCode; + } + + return errorMessage; + } + + /** + * Is this Firefox (web-extensions) + */ + static isFirefox() { + return typeof(browser) !== "undefined"; + } +} + +export default Utils; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..21b02419 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": false, + "sourceMap": false, + "rootDir": "src", + "outDir": "dist/js", + "noEmitOnError": true, + "typeRoots": [ "node_modules/@types" ] + } +} \ No newline at end of file diff --git a/utils.js b/utils.js deleted file mode 100644 index 3ded0c96..00000000 --- a/utils.js +++ /dev/null @@ -1,271 +0,0 @@ -var isBackgroundScript = false; -var onInvidious = false; - -// Function that can be used to wait for a condition before returning -async function wait(condition, timeout = 5000, check = 100) { - return await new Promise((resolve, reject) => { - setTimeout(() => reject("TIMEOUT"), timeout); - - let intervalCheck = () => { - let result = condition(); - if (result !== false) { - resolve(result); - clearInterval(interval); - }; - }; - - let interval = setInterval(intervalCheck, check); - - //run the check once first, this speeds it up a lot - intervalCheck(); - }); -} - -function getYouTubeVideoID(url) { - // For YouTube TV support - if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", ""); - - //Attempt to parse url - let urlObject = null; - try { - urlObject = new URL(url); - } catch (e) { - console.error("[SB] Unable to parse URL: " + url); - return false; - } - - //Check if valid hostname - if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) { - onInvidious = true; - } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { - if (!SB.config) { - // Call this later, in case this is an Invidious tab - wait(() => SB.config !== undefined).then(() => videoIDChange(getYouTubeVideoID(url))); - } - - return false - } - - //Get ID from searchParam - if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) { - id = urlObject.searchParams.get("v"); - return id.length == 11 ? id : false; - } else if (urlObject.pathname.startsWith("/embed/")) { - try { - return urlObject.pathname.substr(7, 11); - } catch (e) { - console.error("[SB] Video ID not valid for " + url); - return false; - } - } - return false; -} - -/** - * Asks for the optional permissions required for all extra sites. - * It also starts the content script registrations. - * - * For now, it is just SB.config.invidiousInstances. - * - * @param {CallableFunction} callback - */ -function setupExtraSitePermissions(callback) { - // Request permission - let permissions = ["declarativeContent"]; - if (isFirefox()) permissions = []; - - chrome.permissions.request({ - origins: getInvidiousInstancesRegex(), - permissions: permissions - }, async function (granted) { - if (granted) { - setupExtraSiteContentScripts(); - } else { - removeExtraSiteRegistration(); - } - - callback(granted); - }); -} - -/** - * Registers the content scripts for the extra sites. - * Will use a different method depending on the browser. - * This is called by setupExtraSitePermissions(). - * - * For now, it is just SB.config.invidiousInstances. - */ -function setupExtraSiteContentScripts() { - let js = [ - "config.js", - "SB.js", - "utils/previewBar.js", - "utils/skipNotice.js", - "utils.js", - "content.js", - "popup.js" - ]; - let css = [ - "content.css", - "./libs/Source+Sans+Pro.css", - "popup.css" - ]; - - if (isFirefox()) { - let firefoxJS = []; - for (const file of js) { - firefoxJS.push({file}); - } - let firefoxCSS = []; - for (const file of css) { - firefoxCSS.push({file}); - } - - let registration = { - message: "registerContentScript", - id: "invidious", - allFrames: true, - js: firefoxJS, - css: firefoxCSS, - matches: getInvidiousInstancesRegex() - }; - - if (isBackgroundScript) { - registerFirefoxContentScript(registration); - } else { - chrome.runtime.sendMessage(registration); - } - } else { - chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() { - let conditions = []; - for (const regex of getInvidiousInstancesRegex()) { - conditions.push(new chrome.declarativeContent.PageStateMatcher({ - pageUrl: { urlMatches: regex } - })); - } - - // Add page rule - let rule = { - id: "invidious", - conditions, - actions: [new chrome.declarativeContent.RequestContentScript({ - allFrames: true, - js, - css - })] - }; - - chrome.declarativeContent.onPageChanged.addRules([rule]); - }); - } -} - -/** - * Removes the permission and content script registration. - */ -function removeExtraSiteRegistration() { - if (isFirefox()) { - let id = "invidious"; - - if (isBackgroundScript) { - if (contentScriptRegistrations[id]) { - contentScriptRegistrations[id].unregister(); - delete contentScriptRegistrations[id]; - } - } else { - chrome.runtime.sendMessage({ - message: "unregisterContentScript", - id: id - }); - } - } else { - chrome.declarativeContent.onPageChanged.removeRules(["invidious"]); - } - - chrome.permissions.remove({ - origins: getInvidiousInstancesRegex() - }); -} - -function localizeHtmlPage() { - //Localize by replacing __MSG_***__ meta tags - var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; - for (var j = 0; j < objects.length; j++) { - var obj = objects[j]; - - let localizedMessage = getLocalizedMessage(obj.innerHTML.toString()); - if (localizedMessage) obj.innerHTML = localizedMessage; - } -} - -function getLocalizedMessage(text) { - var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) { - return v1 ? chrome.i18n.getMessage(v1) : ""; - }); - - if(valNewH != text) { - return valNewH; - } else { - return false; - } -} - -/** - * @returns {String[]} Invidious Instances in regex form - */ -function getInvidiousInstancesRegex() { - var invidiousInstancesRegex = []; - for (const url of SB.config.invidiousInstances) { - invidiousInstancesRegex.push("https://*." + url + "/*"); - invidiousInstancesRegex.push("http://*." + url + "/*"); - } - - return invidiousInstancesRegex; -} - -function generateUserID(length = 36) { - let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let result = ""; - if (window.crypto && window.crypto.getRandomValues) { - values = new Uint32Array(length); - window.crypto.getRandomValues(values); - for (i = 0; i < length; i++) { - result += charset[values[i] % charset.length]; - } - return result; - } else { - for (let i = 0; i < length; i++) { - result += charset[Math.floor(Math.random() * charset.length)]; - } - return result; - } -} - -/** - * Gets the error message in a nice string - * - * @param {int} statusCode - * @returns {string} errorMessage - */ -function getErrorMessage(statusCode) { - let errorMessage = ""; - - if([400, 429, 409, 502, 0].includes(statusCode)) { - //treat them the same - if (statusCode == 503) statusCode = 502; - - errorMessage = chrome.i18n.getMessage(statusCode + "") + " " + chrome.i18n.getMessage("errorCode") + statusCode - + "\n\n" + chrome.i18n.getMessage("statusReminder"); - } else { - errorMessage = chrome.i18n.getMessage("connectionError") + statusCode; - } - - return errorMessage; -} - -/** - * Is this Firefox (web-extensions) - */ -function isFirefox() { - return typeof(browser) !== "undefined"; -} diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js new file mode 100644 index 00000000..b70636ad --- /dev/null +++ b/webpack/webpack.common.js @@ -0,0 +1,43 @@ +const webpack = require("webpack"); +const path = require('path'); +const CopyPlugin = require('copy-webpack-plugin'); +const srcDir = '../src/'; + +module.exports = { + entry: { + popup: path.join(__dirname, srcDir + 'popup.ts'), + background: path.join(__dirname, srcDir + 'background.ts'), + content_script: path.join(__dirname, srcDir + 'content_script.ts') + }, + output: { + path: path.join(__dirname, '../dist/js'), + filename: '[name].js' + }, + optimization: { + splitChunks: { + name: 'vendor', + chunks: "initial" + } + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] + }, + resolve: { + extensions: ['.ts', '.tsx', '.js'] + }, + plugins: [ + // exclude locale files in moment + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + new CopyPlugin([ + { from: '.', to: '../' } + ], + {context: 'public' } + ), + ] +}; diff --git a/webpack/webpack.dev.js b/webpack/webpack.dev.js new file mode 100644 index 00000000..274eb28d --- /dev/null +++ b/webpack/webpack.dev.js @@ -0,0 +1,7 @@ +const merge = require('webpack-merge'); +const common = require('./webpack.common.js'); + +module.exports = merge(common, { + devtool: 'inline-source-map', + mode: 'development' +}); \ No newline at end of file diff --git a/webpack/webpack.prod.js b/webpack/webpack.prod.js new file mode 100644 index 00000000..daa65f51 --- /dev/null +++ b/webpack/webpack.prod.js @@ -0,0 +1,6 @@ +const merge = require('webpack-merge'); +const common = require('./webpack.common.js'); + +module.exports = merge(common, { + mode: 'production' +}); \ No newline at end of file From d77f8abf428d8b1e1c2e5975e3f7f73cde2b8156 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 28 Jan 2020 23:52:15 -0500 Subject: [PATCH 02/30] Converted more code to TypeScript. --- src/{background.js => background.ts} | 49 +- src/content.ts | 2 +- src/js-components/previewBar.ts | 2 +- src/popup.js | 1123 -------------------------- src/types.ts | 7 + src/utils.ts | 4 +- 6 files changed, 37 insertions(+), 1150 deletions(-) rename src/{background.js => background.ts} (83%) delete mode 100644 src/popup.js create mode 100644 src/types.ts diff --git a/src/background.js b/src/background.ts similarity index 83% rename from src/background.js rename to src/background.ts index 686da3cc..cd259b7d 100644 --- a/src/background.js +++ b/src/background.ts @@ -1,12 +1,17 @@ -isBackgroundScript = true; +import Utils from "./utils"; +import SB from "./SB"; + +import * as Types from "./types"; + +Utils.isBackgroundScript = true; // Used only on Firefox, which does not support non persistent background pages. var contentScriptRegistrations = {}; // Register content script if needed -if (isFirefox()) { - wait(() => SB.config !== undefined).then(function() { - if (SB.config.supportInvidious) setupExtraSiteContentScripts(); +if (Utils.isFirefox()) { + Utils.wait(() => SB.config !== undefined).then(function() { + if (SB.config.supportInvidious) Utils.setupExtraSiteContentScripts(); }); } @@ -77,7 +82,7 @@ chrome.runtime.onInstalled.addListener(function (object) { chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")}); //generate a userID - const newUserID = generateUserID(); + const newUserID = Utils.generateUserID(); //save this UUID SB.config.userID = newUserID; @@ -143,7 +148,7 @@ function submitVote(type, UUID, callback) { if (userID == undefined || userID === "undefined") { //generate one - userID = generateUserID(); + userID = Utils.generateUserID(); SB.config.userID = userID; } @@ -176,7 +181,7 @@ async function submitTimes(videoID, callback) { let userID = SB.config.userID; if (sponsorTimes != undefined && sponsorTimes.length > 0) { - let durationResult = await new Promise((resolve, reject) => { + let durationResult = await new Promise((resolve, reject) => { chrome.tabs.query({ active: true, currentWindow: true @@ -196,31 +201,29 @@ async function submitTimes(videoID, callback) { //submit these times for (let i = 0; i < sponsorTimes.length; i++) { - //to prevent it from happeneing twice - let increasedContributionAmount = false; + //to prevent it from happeneing twice + let increasedContributionAmount = false; - //submit the sponsorTime - sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] - + "&userID=" + userID, function(xmlhttp, error) { - if (xmlhttp.readyState == 4 && !error) { - callback({ - statusCode: xmlhttp.status - }); + //submit the sponsorTime + sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + + "&userID=" + userID, function(xmlhttp, error) { + if (xmlhttp.readyState == 4 && !error) { + callback({ + statusCode: xmlhttp.status + }); if (xmlhttp.status == 200) { - //add these to the storage log - currentContributionAmount = SB.config.sponsorTimesContributed; - //save the amount contributed - if (!increasedContributionAmount) { - increasedContributionAmount = true; - SB.config.sponsorTimesContributed = currentContributionAmount + sponsorTimes.length; - } + //save the amount contributed + if (!increasedContributionAmount) { + increasedContributionAmount = true; + SB.config.sponsorTimesContributed = SB.config.sponsorTimesContribute + sponsorTimes.length; } } else if (error) { callback({ statusCode: -1 }); } + } }); } } diff --git a/src/content.ts b/src/content.ts index 43c6849b..8890329c 100644 --- a/src/content.ts +++ b/src/content.ts @@ -112,7 +112,7 @@ function messageListener(request, sender, sendResponse) { break; case "getVideoDuration": sendResponse({ - duration: v.duration + duration: v.duration }); break; diff --git a/src/js-components/previewBar.ts b/src/js-components/previewBar.ts index 5c43c984..a70659b5 100644 --- a/src/js-components/previewBar.ts +++ b/src/js-components/previewBar.ts @@ -75,7 +75,7 @@ class PreviewBar { bar.style.left = (timestamps[i][0] / duration * 100) + "%"; bar.style.position = "absolute" - this.container.insertAdjacentElement("beforeEnd", bar); + this.container.insertAdjacentElement("beforeend", bar); } } diff --git a/src/popup.js b/src/popup.js deleted file mode 100644 index af594e1b..00000000 --- a/src/popup.js +++ /dev/null @@ -1,1123 +0,0 @@ -//make this a function to allow this to run on the content page -async function runThePopup() { - localizeHtmlPage(); - //is it in the popup or content script - var inPopup = true; - if (chrome.tabs == undefined) { - //this is on the content script, use direct communication - chrome.tabs = {}; - chrome.tabs.sendMessage = function(id, request, callback) { - messageListener(request, null, callback); - } - - //add a dummy query method - chrome.tabs.query = function(config, callback) { - callback([{ - url: document.URL, - id: -1 - }]); - } - - inPopup = false; - } - - await wait(() => SB.config !== undefined); - - ["sponsorStart", - // Top toggles - "whitelistChannel", - "unwhitelistChannel", - "disableSkipping", - "enableSkipping", - // Options - "showNoticeAgain", - "optionsButton", - // More controls - "clearTimes", - "submitTimes", - "reportAnIssue", - // sponsorTimesContributions - "sponsorTimesContributionsContainer", - "sponsorTimesContributionsDisplay", - "sponsorTimesContributionsDisplayEndWord", - // sponsorTimesViewsDisplay - "sponsorTimesViewsContainer", - "sponsorTimesViewsDisplay", - "sponsorTimesViewsDisplayEndWord", - // sponsorTimesOthersTimeSaved - "sponsorTimesOthersTimeSavedContainer", - "sponsorTimesOthersTimeSavedDisplay", - "sponsorTimesOthersTimeSavedEndWord", - // sponsorTimesSkipsDone - "sponsorTimesSkipsDoneContainer", - "sponsorTimesSkipsDoneDisplay", - "sponsorTimesSkipsDoneEndWord", - // sponsorTimeSaved - "sponsorTimeSavedContainer", - "sponsorTimeSavedDisplay", - "sponsorTimeSavedEndWord", - // discordButtons - "discordButtonContainer", - "hideDiscordButton", - // submitTimesInfoMessage - "submitTimesInfoMessageContainer", - "submitTimesInfoMessage", - // Username - "setUsernameContainer", - "setUsernameButton", - "setUsernameStatusContainer", - "setUsernameStatus", - "setUsername", - "usernameInput", - "submitUsername", - // More - "submissionSection", - "mainControls", - "loadingIndicator", - "videoFound", - "sponsorMessageTimes", - "downloadedSponsorMessageTimes", - ].forEach(id => SB[id] = document.getElementById(id)); - - //setup click listeners - SB.sponsorStart.addEventListener("click", sendSponsorStartMessage); - SB.whitelistChannel.addEventListener("click", whitelistChannel); - SB.unwhitelistChannel.addEventListener("click", unwhitelistChannel); - SB.disableSkipping.addEventListener("click", () => toggleSkipping(true)); - SB.enableSkipping.addEventListener("click", () => toggleSkipping(false)); - SB.clearTimes.addEventListener("click", clearTimes); - SB.submitTimes.addEventListener("click", submitTimes); - SB.showNoticeAgain.addEventListener("click", showNoticeAgain); - SB.setUsernameButton.addEventListener("click", setUsernameButton); - SB.submitUsername.addEventListener("click", submitUsername); - SB.optionsButton.addEventListener("click", openOptions); - SB.reportAnIssue.addEventListener("click", reportAnIssue); - SB.hideDiscordButton.addEventListener("click", hideDiscordButton); - - //if true, the button now selects the end time - let startTimeChosen = false; - - //the start and end time pairs (2d) - let sponsorTimes = []; - - //current video ID of this tab - let currentVideoID = null; - - //see if discord link can be shown - let hideDiscordLink = SB.config.hideDiscordLink; - if (hideDiscordLink == undefined || !hideDiscordLink) { - let hideDiscordLaunches = SB.config.hideDiscordLaunches; - //only if less than 10 launches - if (hideDiscordLaunches == undefined || hideDiscordLaunches < 10) { - SB.discordButtonContainer.style.display = null; - - if (hideDiscordLaunches == undefined) { - hideDiscordLaunches = 1; - } - SB.config.hideDiscordLaunches = hideDiscordLaunches + 1; - } - } - - //show proper disable skipping button - let disableSkipping = SB.config.disableSkipping; - if (disableSkipping != undefined && disableSkipping) { - SB.disableSkipping.style.display = "none"; - SB.enableSkipping.style.display = "unset"; - } - - //if the don't show notice again variable is true, an option to - // disable should be available - let dontShowNotice = SB.config.dontShowNotice; - if (dontShowNotice != undefined && dontShowNotice) { - SB.showNoticeAgain.style.display = "unset"; - } - - //get the amount of times this user has contributed and display it to thank them - if (SB.config.sponsorTimesContributed != undefined) { - if (SB.config.sponsorTimesContributed > 1) { - SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors"); - } else { - SB.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor"); - } - SB.sponsorTimesContributionsDisplay.innerText = SB.config.sponsorTimesContributed; - SB.sponsorTimesContributionsContainer.style.display = "unset"; - - //get the userID - let userID = SB.config.userID; - if (userID != undefined) { - //there are probably some views on these submissions then - //get the amount of views from the sponsors submitted - sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - let viewCount = JSON.parse(xmlhttp.responseText).viewCount; - if (viewCount != 0) { - if (viewCount > 1) { - SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); - } else { - SB.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); - } - - SB.sponsorTimesViewsDisplay.innerText = viewCount; - SB.sponsorTimesViewsContainer.style.display = "unset"; - } - } - }); - - //get this time in minutes - sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; - if (minutesSaved != 0) { - if (minutesSaved != 1) { - SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); - } else { - SB.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); - } - - SB.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); - SB.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; - } - } - }); - } - } - - //get the amount of times this user has skipped a sponsor - if (SB.config.skipCount != undefined) { - if (SB.config.skipCount != 1) { - SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors"); - } else { - SB.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor"); - } - - SB.sponsorTimesSkipsDoneDisplay.innerText = SB.config.skipCount; - SB.sponsorTimesSkipsDoneContainer.style.display = "unset"; - } - - //get the amount of time this user has saved. - if (SB.config.minutesSaved != undefined) { - if (SB.config.minutesSaved != 1) { - SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); - } else { - SB.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); - } - - SB.sponsorTimeSavedDisplay.innerText = getFormattedHours(SB.config.minutesSaved); - SB.sponsorTimeSavedContainer.style.display = "unset"; - } - - chrome.tabs.query({ - active: true, - currentWindow: true - }, onTabs); - - function onTabs(tabs) { - chrome.tabs.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) { - if (result != undefined && result.videoID) { - currentVideoID = result.videoID; - loadTabData(tabs); - } else if (result == undefined && chrome.runtime.lastError) { - //this isn't a YouTube video then, or at least the content script is not loaded - displayNoVideo(); - } - }); - } - - function loadTabData(tabs) { - if (!currentVideoID) { - //this isn't a YouTube video then - displayNoVideo(); - return; - } - - //load video times for this video - let sponsorTimesStorage = SB.config.sponsorTimes.get(currentVideoID); - if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { - if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) { - startTimeChosen = true; - SB.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); - } - - sponsorTimes = sponsorTimesStorage; - - displaySponsorTimes(); - - //show submission section - SB.submissionSection.style.display = "unset"; - - showSubmitTimesIfNecessary(); - } - - //check if this video's sponsors are known - chrome.tabs.sendMessage( - tabs[0].id, - {message: 'isInfoFound'}, - infoFound - ); - } - - function infoFound(request) { - if(chrome.runtime.lastError) { - //This page doesn't have the injected content script, or at least not yet - displayNoVideo(); - return; - } - - //if request is undefined, then the page currently being browsed is not YouTube - if (request != undefined) { - //this must be a YouTube video - //set letiable - isYouTubeTab = true; - - //remove loading text - SB.mainControls.style.display = "unset" - SB.loadingIndicator.style.display = "none"; - - if (request.found) { - SB.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound"); - - displayDownloadedSponsorTimes(request); - } else { - SB.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404"); - } - } - - //see if whitelist button should be swapped - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: 'isChannelWhitelisted'}, - function(response) { - if (response.value) { - SB.whitelistChannel.style.display = "none"; - SB.unwhitelistChannel.style.display = "unset"; - - SB.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); - SB.downloadedSponsorMessageTimes.style.fontWeight = "bold"; - } - }); - } - ); - } - - function sendSponsorStartMessage() { - //the content script will get the message if a YouTube page is open - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {from: 'popup', message: 'sponsorStart'}, - startSponsorCallback - ); - }); - } - - function startSponsorCallback(response) { - let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); - - if (sponsorTimes[sponsorTimesIndex] == undefined) { - sponsorTimes[sponsorTimesIndex] = []; - } - - sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time; - - let localStartTimeChosen = startTimeChosen; - SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); - //send a message to the client script - if (localStartTimeChosen) { - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: "sponsorDataChanged"} - ); - }); - } - - updateStartTimeChosen(); - - //display video times on screen - displaySponsorTimes(); - - //show submission section - SB.submissionSection.style.display = "unset"; - - showSubmitTimesIfNecessary(); - } - - //display the video times from the array - function displaySponsorTimes() { - //remove all children - while (SB.sponsorMessageTimes.firstChild) { - SB.sponsorMessageTimes.removeChild(SB.sponsorMessageTimes.firstChild); - } - - //add sponsor times - SB.sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes)); - } - - //display the video times from the array at the top, in a different section - function displayDownloadedSponsorTimes(request) { - if (request.sponsorTimes != undefined) { - //set it to the message - if (SB.downloadedSponsorMessageTimes.innerText != chrome.i18n.getMessage("channelWhitelisted")) { - SB.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); - } - - //add them as buttons to the issue reporting container - let container = document.getElementById("issueReporterTimeButtons"); - for (let i = 0; i < request.sponsorTimes.length; i++) { - let sponsorTimeButton = document.createElement("button"); - sponsorTimeButton.className = "warningButton popupElement"; - - let extraInfo = ""; - if (request.hiddenSponsorTimes.includes(i)) { - //this one is hidden - extraInfo = " (hidden)"; - } - - sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]) + extraInfo; - - let votingButtons = document.createElement("div"); - - let UUID = request.UUIDs[i]; - - //thumbs up and down buttons - let voteButtonsContainer = document.createElement("div"); - voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID; - voteButtonsContainer.setAttribute("align", "center"); - voteButtonsContainer.style.display = "none" - - let upvoteButton = document.createElement("img"); - upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID; - upvoteButton.className = "voteButton popupElement"; - upvoteButton.src = chrome.extension.getURL("icons/upvote.png"); - upvoteButton.addEventListener("click", () => vote(1, UUID)); - - let downvoteButton = document.createElement("img"); - downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID; - downvoteButton.className = "voteButton popupElement"; - downvoteButton.src = chrome.extension.getURL("icons/downvote.png"); - downvoteButton.addEventListener("click", () => vote(0, UUID)); - - //add thumbs up and down buttons to the container - voteButtonsContainer.appendChild(document.createElement("br")); - voteButtonsContainer.appendChild(document.createElement("br")); - voteButtonsContainer.appendChild(upvoteButton); - voteButtonsContainer.appendChild(downvoteButton); - - //add click listener to open up vote panel - sponsorTimeButton.addEventListener("click", function() { - voteButtonsContainer.style.display = "unset"; - }); - - container.appendChild(sponsorTimeButton); - container.appendChild(voteButtonsContainer); - - //if it is not the last iteration - if (i != request.sponsorTimes.length - 1) { - container.appendChild(document.createElement("br")); - container.appendChild(document.createElement("br")); - } - } - } - } - - //get the message that visually displays the video times - function getSponsorTimesMessage(sponsorTimes) { - let sponsorTimesMessage = ""; - - for (let i = 0; i < sponsorTimes.length; i++) { - for (let s = 0; s < sponsorTimes[i].length; s++) { - let timeMessage = getFormattedTime(sponsorTimes[i][s]); - //if this is an end time - if (s == 1) { - timeMessage = " to " + timeMessage; - } else if (i > 0) { - //add commas if necessary - timeMessage = ", " + timeMessage; - } - - sponsorTimesMessage += timeMessage; - } - } - - return sponsorTimesMessage; - } - - //get the message that visually displays the video times - //this version is a div that contains each with delete buttons - function getSponsorTimesMessageDiv(sponsorTimes) { - // let sponsorTimesMessage = ""; - let sponsorTimesContainer = document.createElement("div"); - sponsorTimesContainer.id = "sponsorTimesContainer"; - - for (let i = 0; i < sponsorTimes.length; i++) { - let currentSponsorTimeContainer = document.createElement("div"); - currentSponsorTimeContainer.id = "sponsorTimeContainer" + i; - currentSponsorTimeContainer.className = "sponsorTime popupElement"; - let currentSponsorTimeMessage = ""; - - let deleteButton = document.createElement("span"); - deleteButton.id = "sponsorTimeDeleteButton" + i; - deleteButton.innerText = "Delete"; - deleteButton.className = "mediumLink popupElement"; - let index = i; - deleteButton.addEventListener("click", () => deleteSponsorTime(index)); - - let previewButton = document.createElement("span"); - previewButton.id = "sponsorTimePreviewButton" + i; - previewButton.innerText = "Preview"; - previewButton.className = "mediumLink popupElement"; - previewButton.addEventListener("click", () => previewSponsorTime(index)); - - let editButton = document.createElement("span"); - editButton.id = "sponsorTimeEditButton" + i; - editButton.innerText = "Edit"; - editButton.className = "mediumLink popupElement"; - editButton.addEventListener("click", () => editSponsorTime(index)); - - for (let s = 0; s < sponsorTimes[i].length; s++) { - let timeMessage = getFormattedTime(sponsorTimes[i][s]); - //if this is an end time - if (s == 1) { - timeMessage = " to " + timeMessage; - } else if (i > 0) { - //add commas if necessary - timeMessage = timeMessage; - } - - currentSponsorTimeMessage += timeMessage; - } - - currentSponsorTimeContainer.innerText = currentSponsorTimeMessage; - - sponsorTimesContainer.appendChild(currentSponsorTimeContainer); - sponsorTimesContainer.appendChild(deleteButton); - - //only if it is a complete sponsor time - if (sponsorTimes[i].length > 1) { - sponsorTimesContainer.appendChild(previewButton); - sponsorTimesContainer.appendChild(editButton); - - currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index)); - } - } - - return sponsorTimesContainer; - } - - function previewSponsorTime(index) { - let skipTime = sponsorTimes[index][0]; - - if (document.getElementById("startTimeMinutes" + index) != null) { - //edit is currently open, use that time - - skipTime = getSponsorTimeEditTimes("startTime", index); - - //save the edit - saveSponsorTimeEdit(index, false); - } - - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, { - message: "skipToTime", - time: skipTime - 2 - } - ); - }); - } - - function editSponsorTime(index) { - if (document.getElementById("startTimeMinutes" + index) != null) { - //already open - return; - } - - //hide submit button - document.getElementById("submitTimesContainer").style.display = "none"; - - let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index); - - //the button to set the current time - let startTimeNowButton = document.createElement("span"); - startTimeNowButton.id = "startTimeNowButton" + index; - startTimeNowButton.innerText = "(Now)"; - startTimeNowButton.className = "tinyLink popupElement"; - startTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("startTime", index)); - - //get sponsor time minutes and seconds boxes - let startTimeMinutes = document.createElement("input"); - startTimeMinutes.id = "startTimeMinutes" + index; - startTimeMinutes.className = "sponsorTime popupElement"; - startTimeMinutes.type = "text"; - startTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][0]); - startTimeMinutes.style.width = "45px"; - - let startTimeSeconds = document.createElement("input"); - startTimeSeconds.id = "startTimeSeconds" + index; - startTimeSeconds.className = "sponsorTime popupElement"; - startTimeSeconds.type = "text"; - startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]); - startTimeSeconds.style.width = "60px"; - - let endTimeMinutes = document.createElement("input"); - endTimeMinutes.id = "endTimeMinutes" + index; - endTimeMinutes.className = "sponsorTime popupElement"; - endTimeMinutes.type = "text"; - endTimeMinutes.value = getTimeInMinutes(sponsorTimes[index][1]); - endTimeMinutes.style.width = "45px"; - - let endTimeSeconds = document.createElement("input"); - endTimeSeconds.id = "endTimeSeconds" + index; - endTimeSeconds.className = "sponsorTime popupElement"; - endTimeSeconds.type = "text"; - endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]); - endTimeSeconds.style.width = "60px"; - - //the button to set the current time - let endTimeNowButton = document.createElement("span"); - endTimeNowButton.id = "endTimeNowButton" + index; - endTimeNowButton.innerText = "(Now)"; - endTimeNowButton.className = "tinyLink popupElement"; - endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index)); - - let colonText = document.createElement("span"); - colonText.innerText = ":"; - - let toText = document.createElement("span"); - toText.innerText = " to "; - - //remove all children to replace - while (sponsorTimeContainer.firstChild) { - sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild); - } - - sponsorTimeContainer.appendChild(startTimeNowButton); - sponsorTimeContainer.appendChild(startTimeMinutes); - sponsorTimeContainer.appendChild(colonText); - sponsorTimeContainer.appendChild(startTimeSeconds); - sponsorTimeContainer.appendChild(toText); - sponsorTimeContainer.appendChild(endTimeMinutes); - sponsorTimeContainer.appendChild(colonText); - sponsorTimeContainer.appendChild(endTimeSeconds); - sponsorTimeContainer.appendChild(endTimeNowButton); - - //add save button and remove edit button - let saveButton = document.createElement("span"); - saveButton.id = "sponsorTimeSaveButton" + index; - saveButton.innerText = "Save"; - saveButton.className = "mediumLink popupElement"; - saveButton.addEventListener("click", () => saveSponsorTimeEdit(index)); - - let editButton = document.getElementById("sponsorTimeEditButton" + index); - let sponsorTimesContainer = document.getElementById("sponsorTimesContainer"); - - sponsorTimesContainer.replaceChild(saveButton, editButton); - } - - function setEditTimeToCurrentTime(idStartName, index) { - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: "getCurrentTime"}, - function (response) { - let minutes = document.getElementById(idStartName + "Minutes" + index); - let seconds = document.getElementById(idStartName + "Seconds" + index); - - minutes.value = getTimeInMinutes(response.currentTime); - seconds.value = getTimeInFormattedSeconds(response.currentTime); - }); - }); - } - - //id start name is whether it is the startTime or endTime - //gives back the time in seconds - function getSponsorTimeEditTimes(idStartName, index) { - let minutes = document.getElementById(idStartName + "Minutes" + index); - let seconds = document.getElementById(idStartName + "Seconds" + index); - - return parseInt(minutes.value) * 60 + parseFloat(seconds.value); - } - - function saveSponsorTimeEdit(index, closeEditMode = true) { - sponsorTimes[index][0] = getSponsorTimeEditTimes("startTime", index); - sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index); - - //save this - SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: "sponsorDataChanged"} - ); - }); - - if (closeEditMode) { - displaySponsorTimes(); - - showSubmitTimesIfNecessary(); - } - } - - //deletes the sponsor time submitted at an index - function deleteSponsorTime(index) { - //if it is not a complete sponsor time - if (sponsorTimes[index].length < 2) { - chrome.tabs.query({ - active: true, - currentWindow: true - }, function(tabs) { - chrome.tabs.sendMessage(tabs[0].id, { - message: "changeStartSponsorButton", - showStartSponsor: true, - uploadButtonVisible: false - }); - }); - - resetStartTimeChosen(); - } - - sponsorTimes.splice(index, 1); - - //save this - SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: "sponsorDataChanged"} - ); - }); - - //update display - displaySponsorTimes(); - - //if they are all removed - if (sponsorTimes.length == 0) { - //update chrome tab - chrome.tabs.query({ - active: true, - currentWindow: true - }, function(tabs) { - chrome.tabs.sendMessage(tabs[0].id, { - message: "changeStartSponsorButton", - showStartSponsor: true, - uploadButtonVisible: false - }); - }); - - //hide submission section - document.getElementById("submissionSection").style.display = "none"; - } - } - - function clearTimes() { - //send new sponsor time state to tab - if (sponsorTimes.length > 0) { - chrome.tabs.query({ - active: true, - currentWindow: true - }, function(tabs) { - chrome.tabs.sendMessage(tabs[0].id, { - message: "changeStartSponsorButton", - showStartSponsor: true, - uploadButtonVisible: false - }); - }); - } - - //reset sponsorTimes - sponsorTimes = []; - - SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: "sponsorDataChanged"} - ); - }); - - displaySponsorTimes(); - - //hide submission section - document.getElementById("submissionSection").style.display = "none"; - - resetStartTimeChosen(); - } - - function submitTimes() { - //make info message say loading - SB.submitTimesInfoMessage.innerText = chrome.i18n.getMessage("Loading"); - SB.submitTimesInfoMessageContainer.style.display = "unset"; - - if (sponsorTimes.length > 0) { - chrome.runtime.sendMessage({ - message: "submitTimes", - videoID: currentVideoID - }, function(response) { - if (response != undefined) { - if (response.statusCode == 200) { - //hide loading message - SB.submitTimesInfoMessageContainer.style.display = "none"; - - clearTimes(); - } else { - document.getElementById("submitTimesInfoMessage").innerText = getErrorMessage(response.statusCode); - document.getElementById("submitTimesInfoMessageContainer").style.display = "unset"; - - SB.submitTimesInfoMessageContainer.style.display = "unset"; - } - } - }); - } - } - - function showNoticeAgain() { - SB.config.dontShowNotice = false; - - SB.showNoticeAgain.style.display = "none"; - } - - function updateStartTimeChosen() { - //update startTimeChosen letiable - if (!startTimeChosen) { - startTimeChosen = true; - SB.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); - } else { - resetStartTimeChosen(); - } - } - - //set it to false - function resetStartTimeChosen() { - startTimeChosen = false; - SB.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorStart"); - } - - //hides and shows the submit times button when needed - function showSubmitTimesIfNecessary() { - //check if an end time has been specified for the latest sponsor time - if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length > 1) { - //show submit times button - document.getElementById("submitTimesContainer").style.display = "unset"; - } else { - //hide submit times button - document.getElementById("submitTimesContainer").style.display = "none"; - } - } - - //make the options div visible - function openOptions() { - chrome.runtime.sendMessage({"message": "openConfig"}); - } - - //make the options username setting option visible - function setUsernameButton() { - //get username from the server - sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - SB.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; - - SB.submitUsername.style.display = "unset"; - SB.usernameInput.style.display = "unset"; - - SB.setUsernameContainer.style.display = "none"; - SB.setUsername.style.display = "unset"; - - SB.setUsernameStatusContainer.style.display = "none"; - } else if (xmlhttp.readyState == 4) { - SB.setUsername.style.display = "unset"; - SB.submitUsername.style.display = "none"; - SB.usernameInput.style.display = "none"; - - SB.setUsernameStatusContainer.style.display = "unset"; - SB.setUsernameStatus.innerText = getErrorMessage(xmlhttp.status); - } - }); - } - - //submit the new username - function submitUsername() { - //add loading indicator - SB.setUsernameStatusContainer.style.display = "unset"; - SB.setUsernameStatus.innerText = "Loading..."; - - //get the userID - sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + SB.usernameInput.value, function (xmlhttp, error) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - //submitted - SB.submitUsername.style.display = "none"; - SB.usernameInput.style.display = "none"; - - SB.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); - } else if (xmlhttp.readyState == 4) { - SB.setUsernameStatus.innerText = getErrorMessageI(xmlhttp.status); - } - }); - - - SB.setUsernameContainer.style.display = "none"; - SB.setUsername.style.display = "unset"; - } - - //this is not a YouTube video page - function displayNoVideo() { - document.getElementById("loadingIndicator").innerText = chrome.i18n.getMessage("noVideoID"); - } - - function reportAnIssue() { - document.getElementById("issueReporterContainer").style.display = "unset"; - SB.reportAnIssue.style.display = "none"; - } - - function addVoteMessage(message, UUID) { - let container = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID); - //remove all children - while (container.firstChild) { - container.removeChild(container.firstChild); - } - - let thanksForVotingText = document.createElement("h2"); - thanksForVotingText.innerText = message; - //there are already breaks there - thanksForVotingText.style.marginBottom = "0px"; - - container.appendChild(thanksForVotingText); - } - - function vote(type, UUID) { - //add loading info - addVoteMessage("Loading...", UUID) - - //send the vote message to the tab - chrome.runtime.sendMessage({ - message: "submitVote", - type: type, - UUID: UUID - }, function(response) { - if (response != undefined) { - //see if it was a success or failure - if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) { - //success (treat rate limits as a success) - addVoteMessage(chrome.i18n.getMessage("voted"), UUID) - } else if (response.successType == 0) { - //failure: duplicate vote - addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID) - } else if (response.successType == -1) { - addVoteMessage(getErrorMessage(response.statusCode), UUID) - } - } - }); - } - - function hideDiscordButton() { - SB.config.hideDiscordLink = true; - SB.discordButtonContainer.style.display = "none"; - } - - //converts time in seconds to minutes:seconds - function getFormattedTime(seconds) { - let minutes = Math.floor(seconds / 60); - let secondsDisplay = Math.round(seconds - minutes * 60); - if (secondsDisplay < 10) { - //add a zero - secondsDisplay = "0" + secondsDisplay; - } - - let formatted = minutes+ ":" + secondsDisplay; - - return formatted; - } - - function whitelistChannel() { - //get the channel url - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: 'getChannelURL'}, - function(response) { - //get whitelisted channels - let whitelistedChannels = SB.config.whitelistedChannels; - if (whitelistedChannels == undefined) { - whitelistedChannels = []; - } - - //add on this channel - whitelistedChannels.push(response.channelURL); - - //change button - SB.whitelistChannel.style.display = "none"; - SB.unwhitelistChannel.style.display = "unset"; - - SB.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); - SB.downloadedSponsorMessageTimes.style.fontWeight = "bold"; - - //save this - SB.config.whitelistedChannels = whitelistedChannels; - - //send a message to the client - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, { - message: 'whitelistChange', - value: true - }); - } - ); - } - ); - }); - } - - function unwhitelistChannel() { - //get the channel url - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, - {message: 'getChannelURL'}, - function(response) { - //get whitelisted channels - let whitelistedChannels = SB.config.whitelistedChannels; - if (whitelistedChannels == undefined) { - whitelistedChannels = []; - } - - //remove this channel - let index = whitelistedChannels.indexOf(response.channelURL); - whitelistedChannels.splice(index, 1); - - //change button - SB.whitelistChannel.style.display = "unset"; - SB.unwhitelistChannel.style.display = "none"; - - SB.downloadedSponsorMessageTimes.innerText = ""; - SB.downloadedSponsorMessageTimes.style.fontWeight = "unset"; - - //save this - SB.config.whitelistedChannels = whitelistedChannels; - - //send a message to the client - chrome.tabs.query({ - active: true, - currentWindow: true - }, tabs => { - chrome.tabs.sendMessage( - tabs[0].id, { - message: 'whitelistChange', - value: false - }); - } - ); - } - ); - }); - } - - /** - * Should skipping be disabled (visuals stay) - */ - function toggleSkipping(disabled) { - SB.config.disableSkipping = disabled; - - let hiddenButton = SB.disableSkipping; - let shownButton = SB.enableSkipping; - - if (!disabled) { - hiddenButton = SB.enableSkipping; - shownButton = SB.disableSkipping; - } - - shownButton.style.display = "unset"; - hiddenButton.style.display = "none"; - } - - //converts time in seconds to minutes - function getTimeInMinutes(seconds) { - let minutes = Math.floor(seconds / 60); - - return minutes; - } - - //converts time in seconds to seconds past the last minute - function getTimeInFormattedSeconds(seconds) { - let secondsFormatted = (seconds % 60).toFixed(3); - - if (secondsFormatted < 10) { - secondsFormatted = "0" + secondsFormatted; - } - - return secondsFormatted; - } - - function sendRequestToServer(type, address, callback) { - let xmlhttp = new XMLHttpRequest(); - - xmlhttp.open(type, serverAddress + address, true); - - if (callback != undefined) { - xmlhttp.onreadystatechange = function () { - callback(xmlhttp, false); - }; - - xmlhttp.onerror = function(ev) { - callback(xmlhttp, true); - }; - } - - //submit this request - xmlhttp.send(); - } - - /** - * Converts time in hours to 5h 25.1 - * If less than 1 hour, just returns minutes - * - * @param {float} seconds - * @returns {string} - */ - function getFormattedHours(minues) { - let hours = Math.floor(minues / 60); - return (hours > 0 ? hours + "h " : "") + (minues % 60).toFixed(1); - } - -//end of function -} - -if (chrome.tabs != undefined) { - //add the width restriction (because Firefox) - document.getElementById("sponorBlockStyleSheet").sheet.insertRule('.popupBody { width: 325 }', 0); - //this means it is actually opened in the popup - runThePopup(); -} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..7b50adab --- /dev/null +++ b/src/types.ts @@ -0,0 +1,7 @@ +interface videoDurationResponse { + duration: number; +} + +export { + videoDurationResponse +}; \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index 81f76be6..912e7cd0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -134,7 +134,7 @@ class Utils { matches: this.getInvidiousInstancesRegex() }; - if (isBackgroundScript) { + if (this.isBackgroundScript) { registerFirefoxContentScript(registration); } else { chrome.runtime.sendMessage(registration); @@ -172,7 +172,7 @@ class Utils { if (this.isFirefox()) { let id = "invidious"; - if (isBackgroundScript) { + if (this.isBackgroundScript) { if (contentScriptRegistrations[id]) { contentScriptRegistrations[id].unregister(); delete contentScriptRegistrations[id]; From 16c720e50021f29dd42057e658be2c362a0f4f6d Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 16:26:57 -0500 Subject: [PATCH 03/30] Setup new config.json and fixed typescript errors in the popup --- config.json | 3 + config.json.example.json | 4 + public/popup.html | 4 +- src/config.js.example | 3 - src/content.ts | 4 +- src/popup.ts | 1150 +++++++++++++++++++++++++++++++++++++ tsconfig.json | 4 +- webpack/webpack.common.js | 2 +- 8 files changed, 1164 insertions(+), 10 deletions(-) create mode 100644 config.json create mode 100644 config.json.example.json delete mode 100644 src/config.js.example create mode 100644 src/popup.ts diff --git a/config.json b/config.json new file mode 100644 index 00000000..d5f188ed --- /dev/null +++ b/config.json @@ -0,0 +1,3 @@ +{ + "serverAddress": "http://localhost" +} \ No newline at end of file diff --git a/config.json.example.json b/config.json.example.json new file mode 100644 index 00000000..34c3d2a6 --- /dev/null +++ b/config.json.example.json @@ -0,0 +1,4 @@ +{ + "serverAddress": "https://sponsor.ajay.app", + "serverAddressComment": "This specifies the default SponsorBlock server to conect to": +} \ No newline at end of file diff --git a/public/popup.html b/public/popup.html index 2c3c1f18..68e9cba2 100644 --- a/public/popup.html +++ b/public/popup.html @@ -2,8 +2,8 @@ __MSG_openPopup__ - - + + diff --git a/src/config.js.example b/src/config.js.example deleted file mode 100644 index 23cc0be3..00000000 --- a/src/config.js.example +++ /dev/null @@ -1,3 +0,0 @@ -//this file is loaded along iwth content.js -//this file sets the server to connect to, and is gitignored -var serverAddress = "https://sponsor.ajay.app"; \ No newline at end of file diff --git a/src/content.ts b/src/content.ts index 8890329c..2e3f7c73 100644 --- a/src/content.ts +++ b/src/content.ts @@ -800,8 +800,8 @@ function openInfoMenu() { logo.src = chrome.extension.getURL("icons/LogoSponsorBlocker256px.png"); //remove the style sheet and font that are not necessary - popup.querySelector("#sponorBlockPopupFont").remove(); - popup.querySelector("#sponorBlockStyleSheet").remove(); + popup.querySelector("#sponsorBlockPopupFont").remove(); + popup.querySelector("#sponsorBlockStyleSheet").remove(); parentNode.insertBefore(popup, parentNode.firstChild); diff --git a/src/popup.ts b/src/popup.ts new file mode 100644 index 00000000..2c1b2ac7 --- /dev/null +++ b/src/popup.ts @@ -0,0 +1,1150 @@ +import * as CompileConfig from "../config.json"; +import Utils from "./utils"; +import SB from "./SB"; + +class MessageHandler { + onContentScript: boolean; + + constructor (onContentScript: boolean = false) { + this.onContentScript = onContentScript; + } + + sendMessage(id: number, request, callback?) { + if (this.onContentScript) { + messageListener(request, null, callback); + } else { + chrome.tabs.sendMessage(id, request. callback); + } + } + + query(config, callback) { + if (this.onContentScript) { + // Send back dummy info + callback([{ + url: document.URL, + id: -1 + }]); + } else { + chrome.tabs.query(config, callback); + } + + } +} + +var messageHandler = new MessageHandler(); + +//make this a function to allow this to run on the content page +async function runThePopup() { + Utils.localizeHtmlPage(); + + //is it in the popup or content script + var inPopup = true; + if (chrome.tabs == undefined) { + //this is on the content script, use direct communication + messageHandler = new MessageHandler(true); + + inPopup = false; + } + + await Utils.wait(() => SB.config !== undefined); + + var OptionsElements: any = {}; + + ["sponsorStart", + // Top toggles + "whitelistChannel", + "unwhitelistChannel", + "disableSkipping", + "enableSkipping", + // Options + "showNoticeAgain", + "optionsButton", + // More controls + "clearTimes", + "submitTimes", + "reportAnIssue", + // sponsorTimesContributions + "sponsorTimesContributionsContainer", + "sponsorTimesContributionsDisplay", + "sponsorTimesContributionsDisplayEndWord", + // sponsorTimesViewsDisplay + "sponsorTimesViewsContainer", + "sponsorTimesViewsDisplay", + "sponsorTimesViewsDisplayEndWord", + // sponsorTimesOthersTimeSaved + "sponsorTimesOthersTimeSavedContainer", + "sponsorTimesOthersTimeSavedDisplay", + "sponsorTimesOthersTimeSavedEndWord", + // sponsorTimesSkipsDone + "sponsorTimesSkipsDoneContainer", + "sponsorTimesSkipsDoneDisplay", + "sponsorTimesSkipsDoneEndWord", + // sponsorTimeSaved + "sponsorTimeSavedContainer", + "sponsorTimeSavedDisplay", + "sponsorTimeSavedEndWord", + // discordButtons + "discordButtonContainer", + "hideDiscordButton", + // submitTimesInfoMessage + "submitTimesInfoMessageContainer", + "submitTimesInfoMessage", + // Username + "setUsernameContainer", + "setUsernameButton", + "setUsernameStatusContainer", + "setUsernameStatus", + "setUsername", + "usernameInput", + "submitUsername", + // More + "submissionSection", + "mainControls", + "loadingIndicator", + "videoFound", + "sponsorMessageTimes", + "downloadedSponsorMessageTimes", + ].forEach(id => OptionsElements[id] = document.getElementById(id)); + + //setup click listeners + OptionsElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); + OptionsElements.whitelistChannel.addEventListener("click", whitelistChannel); + OptionsElements.unwhitelistChannel.addEventListener("click", unwhitelistChannel); + OptionsElements.disableSkipping.addEventListener("click", () => toggleSkipping(true)); + OptionsElements.enableSkipping.addEventListener("click", () => toggleSkipping(false)); + OptionsElements.clearTimes.addEventListener("click", clearTimes); + OptionsElements.submitTimes.addEventListener("click", submitTimes); + OptionsElements.showNoticeAgain.addEventListener("click", showNoticeAgain); + OptionsElements.setUsernameButton.addEventListener("click", setUsernameButton); + OptionsElements.submitUsername.addEventListener("click", submitUsername); + OptionsElements.optionsButton.addEventListener("click", openOptions); + OptionsElements.reportAnIssue.addEventListener("click", reportAnIssue); + OptionsElements.hideDiscordButton.addEventListener("click", hideDiscordButton); + + //if true, the button now selects the end time + let startTimeChosen = false; + + //the start and end time pairs (2d) + let sponsorTimes = []; + + //current video ID of this tab + let currentVideoID = null; + + //see if discord link can be shown + let hideDiscordLink = SB.config.hideDiscordLink; + if (hideDiscordLink == undefined || !hideDiscordLink) { + let hideDiscordLaunches = SB.config.hideDiscordLaunches; + //only if less than 10 launches + if (hideDiscordLaunches == undefined || hideDiscordLaunches < 10) { + OptionsElements.discordButtonContainer.style.display = null; + + if (hideDiscordLaunches == undefined) { + hideDiscordLaunches = 1; + } + SB.config.hideDiscordLaunches = hideDiscordLaunches + 1; + } + } + + //show proper disable skipping button + let disableSkipping = SB.config.disableSkipping; + if (disableSkipping != undefined && disableSkipping) { + OptionsElements.disableSkipping.style.display = "none"; + OptionsElements.enableSkipping.style.display = "unset"; + } + + //if the don't show notice again variable is true, an option to + // disable should be available + let dontShowNotice = SB.config.dontShowNotice; + if (dontShowNotice != undefined && dontShowNotice) { + OptionsElements.showNoticeAgain.style.display = "unset"; + } + + //get the amount of times this user has contributed and display it to thank them + if (SB.config.sponsorTimesContributed != undefined) { + if (SB.config.sponsorTimesContributed > 1) { + OptionsElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors"); + } else { + OptionsElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor"); + } + OptionsElements.sponsorTimesContributionsDisplay.innerText = SB.config.sponsorTimesContributed; + OptionsElements.sponsorTimesContributionsContainer.style.display = "unset"; + + //get the userID + let userID = SB.config.userID; + if (userID != undefined) { + //there are probably some views on these submissions then + //get the amount of views from the sponsors submitted + sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + let viewCount = JSON.parse(xmlhttp.responseText).viewCount; + if (viewCount != 0) { + if (viewCount > 1) { + OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); + } else { + OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); + } + + OptionsElements.sponsorTimesViewsDisplay.innerText = viewCount; + OptionsElements.sponsorTimesViewsContainer.style.display = "unset"; + } + } + }); + + //get this time in minutes + sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; + if (minutesSaved != 0) { + if (minutesSaved != 1) { + OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); + } else { + OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); + } + + OptionsElements.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); + OptionsElements.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; + } + } + }); + } + } + + //get the amount of times this user has skipped a sponsor + if (SB.config.skipCount != undefined) { + if (SB.config.skipCount != 1) { + OptionsElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors"); + } else { + OptionsElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor"); + } + + OptionsElements.sponsorTimesSkipsDoneDisplay.innerText = SB.config.skipCount; + OptionsElements.sponsorTimesSkipsDoneContainer.style.display = "unset"; + } + + //get the amount of time this user has saved. + if (SB.config.minutesSaved != undefined) { + if (SB.config.minutesSaved != 1) { + OptionsElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); + } else { + OptionsElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); + } + + OptionsElements.sponsorTimeSavedDisplay.innerText = getFormattedHours(SB.config.minutesSaved); + OptionsElements.sponsorTimeSavedContainer.style.display = "unset"; + } + + messageHandler.query({ + active: true, + currentWindow: true + }, onTabs); + + function onTabs(tabs) { + messageHandler.sendMessage(tabs[0].id, {message: 'getVideoID'}, function(result) { + if (result != undefined && result.videoID) { + currentVideoID = result.videoID; + loadTabData(tabs); + } else if (result == undefined && chrome.runtime.lastError) { + //this isn't a YouTube video then, or at least the content script is not loaded + displayNoVideo(); + } + }); + } + + function loadTabData(tabs) { + if (!currentVideoID) { + //this isn't a YouTube video then + displayNoVideo(); + return; + } + + //load video times for this video + let sponsorTimesStorage = SB.config.sponsorTimes.get(currentVideoID); + if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { + if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) { + startTimeChosen = true; + OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); + } + + sponsorTimes = sponsorTimesStorage; + + displaySponsorTimes(); + + //show submission section + OptionsElements.submissionSection.style.display = "unset"; + + showSubmitTimesIfNecessary(); + } + + //check if this video's sponsors are known + messageHandler.sendMessage( + tabs[0].id, + {message: 'isInfoFound'}, + infoFound + ); + } + + function infoFound(request) { + if(chrome.runtime.lastError) { + //This page doesn't have the injected content script, or at least not yet + displayNoVideo(); + return; + } + + //if request is undefined, then the page currently being browsed is not YouTube + if (request != undefined) { + //remove loading text + OptionsElements.mainControls.style.display = "unset" + OptionsElements.loadingIndicator.style.display = "none"; + + if (request.found) { + OptionsElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound"); + + displayDownloadedSponsorTimes(request); + } else { + OptionsElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404"); + } + } + + //see if whitelist button should be swapped + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: 'isChannelWhitelisted'}, + function(response) { + if (response.value) { + OptionsElements.whitelistChannel.style.display = "none"; + OptionsElements.unwhitelistChannel.style.display = "unset"; + + OptionsElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); + OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + } + }); + } + ); + } + + function sendSponsorStartMessage() { + //the content script will get the message if a YouTube page is open + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {from: 'popup', message: 'sponsorStart'}, + startSponsorCallback + ); + }); + } + + function startSponsorCallback(response) { + let sponsorTimesIndex = sponsorTimes.length - (startTimeChosen ? 1 : 0); + + if (sponsorTimes[sponsorTimesIndex] == undefined) { + sponsorTimes[sponsorTimesIndex] = []; + } + + sponsorTimes[sponsorTimesIndex][startTimeChosen ? 1 : 0] = response.time; + + let localStartTimeChosen = startTimeChosen; + SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); + //send a message to the client script + if (localStartTimeChosen) { + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "sponsorDataChanged"} + ); + }); + } + + updateStartTimeChosen(); + + //display video times on screen + displaySponsorTimes(); + + //show submission section + OptionsElements.submissionSection.style.display = "unset"; + + showSubmitTimesIfNecessary(); + } + + //display the video times from the array + function displaySponsorTimes() { + //remove all children + while (OptionsElements.sponsorMessageTimes.firstChild) { + OptionsElements.sponsorMessageTimes.removeChild(OptionsElements.sponsorMessageTimes.firstChild); + } + + //add sponsor times + OptionsElements.sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes)); + } + + //display the video times from the array at the top, in a different section + function displayDownloadedSponsorTimes(request) { + if (request.sponsorTimes != undefined) { + //set it to the message + if (OptionsElements.downloadedSponsorMessageTimes.innerText != chrome.i18n.getMessage("channelWhitelisted")) { + OptionsElements.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); + } + + //add them as buttons to the issue reporting container + let container = document.getElementById("issueReporterTimeButtons"); + for (let i = 0; i < request.sponsorTimes.length; i++) { + let sponsorTimeButton = document.createElement("button"); + sponsorTimeButton.className = "warningButton popupElement"; + + let extraInfo = ""; + if (request.hiddenSponsorTimes.includes(i)) { + //this one is hidden + extraInfo = " (hidden)"; + } + + sponsorTimeButton.innerText = getFormattedTime(request.sponsorTimes[i][0]) + " to " + getFormattedTime(request.sponsorTimes[i][1]) + extraInfo; + + let votingButtons = document.createElement("div"); + + let UUID = request.UUIDs[i]; + + //thumbs up and down buttons + let voteButtonsContainer = document.createElement("div"); + voteButtonsContainer.id = "sponsorTimesVoteButtonsContainer" + UUID; + voteButtonsContainer.setAttribute("align", "center"); + voteButtonsContainer.style.display = "none" + + let upvoteButton = document.createElement("img"); + upvoteButton.id = "sponsorTimesUpvoteButtonsContainer" + UUID; + upvoteButton.className = "voteButton popupElement"; + upvoteButton.src = chrome.extension.getURL("icons/upvote.png"); + upvoteButton.addEventListener("click", () => vote(1, UUID)); + + let downvoteButton = document.createElement("img"); + downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + UUID; + downvoteButton.className = "voteButton popupElement"; + downvoteButton.src = chrome.extension.getURL("icons/downvote.png"); + downvoteButton.addEventListener("click", () => vote(0, UUID)); + + //add thumbs up and down buttons to the container + voteButtonsContainer.appendChild(document.createElement("br")); + voteButtonsContainer.appendChild(document.createElement("br")); + voteButtonsContainer.appendChild(upvoteButton); + voteButtonsContainer.appendChild(downvoteButton); + + //add click listener to open up vote panel + sponsorTimeButton.addEventListener("click", function() { + voteButtonsContainer.style.display = "unset"; + }); + + container.appendChild(sponsorTimeButton); + container.appendChild(voteButtonsContainer); + + //if it is not the last iteration + if (i != request.sponsorTimes.length - 1) { + container.appendChild(document.createElement("br")); + container.appendChild(document.createElement("br")); + } + } + } + } + + //get the message that visually displays the video times + function getSponsorTimesMessage(sponsorTimes) { + let sponsorTimesMessage = ""; + + for (let i = 0; i < sponsorTimes.length; i++) { + for (let s = 0; s < sponsorTimes[i].length; s++) { + let timeMessage = getFormattedTime(sponsorTimes[i][s]); + //if this is an end time + if (s == 1) { + timeMessage = " to " + timeMessage; + } else if (i > 0) { + //add commas if necessary + timeMessage = ", " + timeMessage; + } + + sponsorTimesMessage += timeMessage; + } + } + + return sponsorTimesMessage; + } + + //get the message that visually displays the video times + //this version is a div that contains each with delete buttons + function getSponsorTimesMessageDiv(sponsorTimes) { + // let sponsorTimesMessage = ""; + let sponsorTimesContainer = document.createElement("div"); + sponsorTimesContainer.id = "sponsorTimesContainer"; + + for (let i = 0; i < sponsorTimes.length; i++) { + let currentSponsorTimeContainer = document.createElement("div"); + currentSponsorTimeContainer.id = "sponsorTimeContainer" + i; + currentSponsorTimeContainer.className = "sponsorTime popupElement"; + let currentSponsorTimeMessage = ""; + + let deleteButton = document.createElement("span"); + deleteButton.id = "sponsorTimeDeleteButton" + i; + deleteButton.innerText = "Delete"; + deleteButton.className = "mediumLink popupElement"; + let index = i; + deleteButton.addEventListener("click", () => deleteSponsorTime(index)); + + let previewButton = document.createElement("span"); + previewButton.id = "sponsorTimePreviewButton" + i; + previewButton.innerText = "Preview"; + previewButton.className = "mediumLink popupElement"; + previewButton.addEventListener("click", () => previewSponsorTime(index)); + + let editButton = document.createElement("span"); + editButton.id = "sponsorTimeEditButton" + i; + editButton.innerText = "Edit"; + editButton.className = "mediumLink popupElement"; + editButton.addEventListener("click", () => editSponsorTime(index)); + + for (let s = 0; s < sponsorTimes[i].length; s++) { + let timeMessage = getFormattedTime(sponsorTimes[i][s]); + //if this is an end time + if (s == 1) { + timeMessage = " to " + timeMessage; + } else if (i > 0) { + //add commas if necessary + timeMessage = timeMessage; + } + + currentSponsorTimeMessage += timeMessage; + } + + currentSponsorTimeContainer.innerText = currentSponsorTimeMessage; + + sponsorTimesContainer.appendChild(currentSponsorTimeContainer); + sponsorTimesContainer.appendChild(deleteButton); + + //only if it is a complete sponsor time + if (sponsorTimes[i].length > 1) { + sponsorTimesContainer.appendChild(previewButton); + sponsorTimesContainer.appendChild(editButton); + + currentSponsorTimeContainer.addEventListener("click", () => editSponsorTime(index)); + } + } + + return sponsorTimesContainer; + } + + function previewSponsorTime(index) { + let skipTime = sponsorTimes[index][0]; + + if (document.getElementById("startTimeMinutes" + index) != null) { + //edit is currently open, use that time + + skipTime = getSponsorTimeEditTimes("startTime", index); + + //save the edit + saveSponsorTimeEdit(index, false); + } + + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, { + message: "skipToTime", + time: skipTime - 2 + } + ); + }); + } + + function editSponsorTime(index) { + if (document.getElementById("startTimeMinutes" + index) != null) { + //already open + return; + } + + //hide submit button + document.getElementById("submitTimesContainer").style.display = "none"; + + let sponsorTimeContainer = document.getElementById("sponsorTimeContainer" + index); + + //the button to set the current time + let startTimeNowButton = document.createElement("span"); + startTimeNowButton.id = "startTimeNowButton" + index; + startTimeNowButton.innerText = "(Now)"; + startTimeNowButton.className = "tinyLink popupElement"; + startTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("startTime", index)); + + //get sponsor time minutes and seconds boxes + let startTimeMinutes = document.createElement("input"); + startTimeMinutes.id = "startTimeMinutes" + index; + startTimeMinutes.className = "sponsorTime popupElement"; + startTimeMinutes.type = "text"; + startTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index][0])); + startTimeMinutes.style.width = "45px"; + + let startTimeSeconds = document.createElement("input"); + startTimeSeconds.id = "startTimeSeconds" + index; + startTimeSeconds.className = "sponsorTime popupElement"; + startTimeSeconds.type = "text"; + startTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][0]); + startTimeSeconds.style.width = "60px"; + + let endTimeMinutes = document.createElement("input"); + endTimeMinutes.id = "endTimeMinutes" + index; + endTimeMinutes.className = "sponsorTime popupElement"; + endTimeMinutes.type = "text"; + endTimeMinutes.value = String(getTimeInMinutes(sponsorTimes[index][1])); + endTimeMinutes.style.width = "45px"; + + let endTimeSeconds = document.createElement("input"); + endTimeSeconds.id = "endTimeSeconds" + index; + endTimeSeconds.className = "sponsorTime popupElement"; + endTimeSeconds.type = "text"; + endTimeSeconds.value = getTimeInFormattedSeconds(sponsorTimes[index][1]); + endTimeSeconds.style.width = "60px"; + + //the button to set the current time + let endTimeNowButton = document.createElement("span"); + endTimeNowButton.id = "endTimeNowButton" + index; + endTimeNowButton.innerText = "(Now)"; + endTimeNowButton.className = "tinyLink popupElement"; + endTimeNowButton.addEventListener("click", () => setEditTimeToCurrentTime("endTime", index)); + + let colonText = document.createElement("span"); + colonText.innerText = ":"; + + let toText = document.createElement("span"); + toText.innerText = " to "; + + //remove all children to replace + while (sponsorTimeContainer.firstChild) { + sponsorTimeContainer.removeChild(sponsorTimeContainer.firstChild); + } + + sponsorTimeContainer.appendChild(startTimeNowButton); + sponsorTimeContainer.appendChild(startTimeMinutes); + sponsorTimeContainer.appendChild(colonText); + sponsorTimeContainer.appendChild(startTimeSeconds); + sponsorTimeContainer.appendChild(toText); + sponsorTimeContainer.appendChild(endTimeMinutes); + sponsorTimeContainer.appendChild(colonText); + sponsorTimeContainer.appendChild(endTimeSeconds); + sponsorTimeContainer.appendChild(endTimeNowButton); + + //add save button and remove edit button + let saveButton = document.createElement("span"); + saveButton.id = "sponsorTimeSaveButton" + index; + saveButton.innerText = "Save"; + saveButton.className = "mediumLink popupElement"; + saveButton.addEventListener("click", () => saveSponsorTimeEdit(index)); + + let editButton = document.getElementById("sponsorTimeEditButton" + index); + let sponsorTimesContainer = document.getElementById("sponsorTimesContainer"); + + sponsorTimesContainer.replaceChild(saveButton, editButton); + } + + function setEditTimeToCurrentTime(idStartName, index) { + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "getCurrentTime"}, + function (response) { + let minutes = document.getElementById(idStartName + "Minutes" + index); + let seconds = document.getElementById(idStartName + "Seconds" + index); + + minutes.value = String(getTimeInMinutes(response.currentTime)); + seconds.value = getTimeInFormattedSeconds(response.currentTime); + }); + }); + } + + //id start name is whether it is the startTime or endTime + //gives back the time in seconds + function getSponsorTimeEditTimes(idStartName, index) { + let minutes = document.getElementById(idStartName + "Minutes" + index); + let seconds = document.getElementById(idStartName + "Seconds" + index); + + return parseInt(minutes.value) * 60 + seconds.value; + } + + function saveSponsorTimeEdit(index, closeEditMode = true) { + sponsorTimes[index][0] = getSponsorTimeEditTimes("startTime", index); + sponsorTimes[index][1] = getSponsorTimeEditTimes("endTime", index); + + //save this + SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "sponsorDataChanged"} + ); + }); + + if (closeEditMode) { + displaySponsorTimes(); + + showSubmitTimesIfNecessary(); + } + } + + //deletes the sponsor time submitted at an index + function deleteSponsorTime(index) { + //if it is not a complete sponsor time + if (sponsorTimes[index].length < 2) { + messageHandler.query({ + active: true, + currentWindow: true + }, function(tabs) { + messageHandler.sendMessage(tabs[0].id, { + message: "changeStartSponsorButton", + showStartSponsor: true, + uploadButtonVisible: false + }); + }); + + resetStartTimeChosen(); + } + + sponsorTimes.splice(index, 1); + + //save this + SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "sponsorDataChanged"} + ); + }); + + //update display + displaySponsorTimes(); + + //if they are all removed + if (sponsorTimes.length == 0) { + //update chrome tab + messageHandler.query({ + active: true, + currentWindow: true + }, function(tabs) { + messageHandler.sendMessage(tabs[0].id, { + message: "changeStartSponsorButton", + showStartSponsor: true, + uploadButtonVisible: false + }); + }); + + //hide submission section + document.getElementById("submissionSection").style.display = "none"; + } + } + + function clearTimes() { + //send new sponsor time state to tab + if (sponsorTimes.length > 0) { + messageHandler.query({ + active: true, + currentWindow: true + }, function(tabs) { + messageHandler.sendMessage(tabs[0].id, { + message: "changeStartSponsorButton", + showStartSponsor: true, + uploadButtonVisible: false + }); + }); + } + + //reset sponsorTimes + sponsorTimes = []; + + SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "sponsorDataChanged"} + ); + }); + + displaySponsorTimes(); + + //hide submission section + document.getElementById("submissionSection").style.display = "none"; + + resetStartTimeChosen(); + } + + function submitTimes() { + //make info message say loading + OptionsElements.submitTimesInfoMessage.innerText = chrome.i18n.getMessage("Loading"); + OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; + + if (sponsorTimes.length > 0) { + chrome.runtime.sendMessage({ + message: "submitTimes", + videoID: currentVideoID + }, function(response) { + if (response != undefined) { + if (response.statusCode == 200) { + //hide loading message + OptionsElements.submitTimesInfoMessageContainer.style.display = "none"; + + clearTimes(); + } else { + document.getElementById("submitTimesInfoMessage").innerText = Utils.getErrorMessage(response.statusCode); + document.getElementById("submitTimesInfoMessageContainer").style.display = "unset"; + + OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; + } + } + }); + } + } + + function showNoticeAgain() { + SB.config.dontShowNotice = false; + + OptionsElements.showNoticeAgain.style.display = "none"; + } + + function updateStartTimeChosen() { + //update startTimeChosen letiable + if (!startTimeChosen) { + startTimeChosen = true; + OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); + } else { + resetStartTimeChosen(); + } + } + + //set it to false + function resetStartTimeChosen() { + startTimeChosen = false; + OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorStart"); + } + + //hides and shows the submit times button when needed + function showSubmitTimesIfNecessary() { + //check if an end time has been specified for the latest sponsor time + if (sponsorTimes.length > 0 && sponsorTimes[sponsorTimes.length - 1].length > 1) { + //show submit times button + document.getElementById("submitTimesContainer").style.display = "unset"; + } else { + //hide submit times button + document.getElementById("submitTimesContainer").style.display = "none"; + } + } + + //make the options div visible + function openOptions() { + chrome.runtime.sendMessage({"message": "openConfig"}); + } + + //make the options username setting option visible + function setUsernameButton() { + //get username from the server + sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; + + OptionsElements.submitUsername.style.display = "unset"; + OptionsElements.usernameInput.style.display = "unset"; + + OptionsElements.setUsernameContainer.style.display = "none"; + OptionsElements.setUsername.style.display = "unset"; + OptionsElements + OptionsElements.setUsernameStatusContainer.style.display = "none"; + } else if (xmlhttp.readyState == 4) { + OptionsElements.setUsername.style.display = "unset"; + OptionsElements.submitUsername.style.display = "none"; + OptionsElements.usernameInput.style.display = "none"; + + OptionsElements.setUsernameStatusContainer.style.display = "unset"; + OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + } + }); + } + + //submit the new username + function submitUsername() { + //add loading indicator + OptionsElements.setUsernameStatusContainer.style.display = "unset"; + OptionsElements.setUsernameStatus.innerText = "Loading..."; + + //get the userID + sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + //submitted + OptionsElements.submitUsername.style.display = "none"; + OptionsElements.usernameInput.style.display = "none"; + + OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); + } else if (xmlhttp.readyState == 4) { + OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + } + }); + + + OptionsElements.setUsernameContainer.style.display = "none"; + OptionsElements.setUsername.style.display = "unset"; + } + + //this is not a YouTube video page + function displayNoVideo() { + document.getElementById("loadingIndicator").innerText = chrome.i18n.getMessage("noVideoID"); + } + + function reportAnIssue() { + document.getElementById("issueReporterContainer").style.display = "unset"; + OptionsElements.reportAnIssue.style.display = "none"; + } + + function addVoteMessage(message, UUID) { + let container = document.getElementById("sponsorTimesVoteButtonsContainer" + UUID); + //remove all children + while (container.firstChild) { + container.removeChild(container.firstChild); + } + + let thanksForVotingText = document.createElement("h2"); + thanksForVotingText.innerText = message; + //there are already breaks there + thanksForVotingText.style.marginBottom = "0px"; + + container.appendChild(thanksForVotingText); + } + + function vote(type, UUID) { + //add loading info + addVoteMessage("Loading...", UUID) + + //send the vote message to the tab + chrome.runtime.sendMessage({ + message: "submitVote", + type: type, + UUID: UUID + }, function(response) { + if (response != undefined) { + //see if it was a success or failure + if (response.successType == 1 || (response.successType == -1 && response.statusCode == 429)) { + //success (treat rate limits as a success) + addVoteMessage(chrome.i18n.getMessage("voted"), UUID) + } else if (response.successType == 0) { + //failure: duplicate vote + addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID) + } else if (response.successType == -1) { + addVoteMessage(Utils.getErrorMessage(response.statusCode), UUID) + } + } + }); + } + + function hideDiscordButton() { + SB.config.hideDiscordLink = true; + OptionsElements.discordButtonContainer.style.display = "none"; + } + + //converts time in seconds to minutes:seconds + function getFormattedTime(seconds) { + let minutes = Math.floor(seconds / 60); + let secondsDisplayNumber = Math.round(seconds - minutes * 60); + let secondsDisplay = String(secondsDisplayNumber); + if (secondsDisplayNumber < 10) { + //add a zero + secondsDisplay = "0" + secondsDisplay; + } + + let formatted = minutes+ ":" + secondsDisplay; + + return formatted; + } + + function whitelistChannel() { + //get the channel url + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: 'getChannelURL'}, + function(response) { + //get whitelisted channels + let whitelistedChannels = SB.config.whitelistedChannels; + if (whitelistedChannels == undefined) { + whitelistedChannels = []; + } + + //add on this channel + whitelistedChannels.push(response.channelURL); + + //change button + OptionsElements.whitelistChannel.style.display = "none"; + OptionsElements.unwhitelistChannel.style.display = "unset"; + + OptionsElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); + OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + + //save this + OptionsElements.config.whitelistedChannels = whitelistedChannels; + + //send a message to the client + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, { + message: 'whitelistChange', + value: true + }); + } + ); + } + ); + }); + } + + function unwhitelistChannel() { + //get the channel url + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: 'getChannelURL'}, + function(response) { + //get whitelisted channels + let whitelistedChannels = SB.config.whitelistedChannels; + if (whitelistedChannels == undefined) { + whitelistedChannels = []; + } + + //remove this channel + let index = whitelistedChannels.indexOf(response.channelURL); + whitelistedChannels.splice(index, 1); + + //change button + OptionsElements.whitelistChannel.style.display = "unset"; + OptionsElements.unwhitelistChannel.style.display = "none"; + + OptionsElements.downloadedSponsorMessageTimes.innerText = ""; + OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "unset"; + + //save this + OptionsElements.config.whitelistedChannels = whitelistedChannels; + + //send a message to the client + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, { + message: 'whitelistChange', + value: false + }); + } + ); + } + ); + }); + } + + /** + * Should skipping be disabled (visuals stay) + */ + function toggleSkipping(disabled) { + OptionsElements.config.disableSkipping = disabled; + + let hiddenButton = OptionsElements.disableSkipping; + let shownButton = OptionsElements.enableSkipping; + + if (!disabled) { + hiddenButton = OptionsElements.enableSkipping; + shownButton = OptionsElements.disableSkipping; + } + + shownButton.style.display = "unset"; + hiddenButton.style.display = "none"; + } + + //converts time in seconds to minutes + function getTimeInMinutes(seconds) { + let minutes = Math.floor(seconds / 60); + + return minutes; + } + + //converts time in seconds to seconds past the last minute + function getTimeInFormattedSeconds(seconds) { + let minutes = seconds % 60; + let secondsFormatted = minutes.toFixed(3); + + if (minutes < 10) { + secondsFormatted = "0" + secondsFormatted; + } + + return secondsFormatted; + } + + function sendRequestToServer(type, address, callback) { + let xmlhttp = new XMLHttpRequest(); + + xmlhttp.open(type, CompileConfig.serverAddress + address, true); + + if (callback != undefined) { + xmlhttp.onreadystatechange = function () { + callback(xmlhttp, false); + }; + + xmlhttp.onerror = function(ev) { + callback(xmlhttp, true); + }; + } + + //submit this request + xmlhttp.send(); + } + + /** + * Converts time in hours to 5h 25.1 + * If less than 1 hour, just returns minutes + * + * @param {float} seconds + * @returns {string} + */ + function getFormattedHours(minues) { + let hours = Math.floor(minues / 60); + return (hours > 0 ? hours + "h " : "") + (minues % 60).toFixed(1); + } + +//end of function +} + +if (chrome.tabs != undefined) { + //add the width restriction (because Firefox) + let link = document.getElementById("sponsorBlockStyleSheet"); + ( link.sheet).insertRule('.popupBody { width: 325 }', 0); + + //this means it is actually opened in the popup + runThePopup(); +} diff --git a/tsconfig.json b/tsconfig.json index 21b02419..cc0b77e6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,9 +4,9 @@ "target": "es6", "noImplicitAny": false, "sourceMap": false, - "rootDir": "src", "outDir": "dist/js", "noEmitOnError": true, - "typeRoots": [ "node_modules/@types" ] + "typeRoots": [ "node_modules/@types" ], + "resolveJsonModule": true } } \ No newline at end of file diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index b70636ad..27d7fc1a 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -7,7 +7,7 @@ module.exports = { entry: { popup: path.join(__dirname, srcDir + 'popup.ts'), background: path.join(__dirname, srcDir + 'background.ts'), - content_script: path.join(__dirname, srcDir + 'content_script.ts') + content_script: path.join(__dirname, srcDir + 'content.ts') }, output: { path: path.join(__dirname, '../dist/js'), From 5ebdfd84669d40a7c48685a3906fb17b7ae53b54 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 16:27:58 -0500 Subject: [PATCH 04/30] Added config to gitignore. --- .gitignore | 2 +- config.json | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 config.json diff --git a/.gitignore b/.gitignore index c97afe49..a3112c1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -config.js +config.json ignored .idea/ node_modules diff --git a/config.json b/config.json deleted file mode 100644 index d5f188ed..00000000 --- a/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "serverAddress": "http://localhost" -} \ No newline at end of file From 4a491f1ebf0702125eca60aea42dc21b2832bc0e Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 16:41:08 -0500 Subject: [PATCH 05/30] Moved server code to utils --- src/background.ts | 25 +-------- src/popup.ts | 140 ++++++++++++++++++++-------------------------- src/utils.ts | 20 +++++++ 3 files changed, 83 insertions(+), 102 deletions(-) diff --git a/src/background.ts b/src/background.ts index cd259b7d..29f63c51 100644 --- a/src/background.ts +++ b/src/background.ts @@ -153,7 +153,7 @@ function submitVote(type, UUID, callback) { } //publish this vote - sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { + Utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { callback({ successType: 1 @@ -205,7 +205,7 @@ async function submitTimes(videoID, callback) { let increasedContributionAmount = false; //submit the sponsorTime - sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + Utils.sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + "&userID=" + userID, function(xmlhttp, error) { if (xmlhttp.readyState == 4 && !error) { callback({ @@ -227,23 +227,4 @@ async function submitTimes(videoID, callback) { }); } } -} - -function sendRequestToServer(type, address, callback) { - let xmlhttp = new XMLHttpRequest(); - - xmlhttp.open(type, serverAddress + address, true); - - if (callback != undefined) { - xmlhttp.onreadystatechange = function () { - callback(xmlhttp, false); - }; - - xmlhttp.onerror = function(ev) { - callback(xmlhttp, true); - }; - } - - //submit this request - xmlhttp.send(); -} +} \ No newline at end of file diff --git a/src/popup.ts b/src/popup.ts index 2c1b2ac7..e5e0bfc2 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -1,4 +1,3 @@ -import * as CompileConfig from "../config.json"; import Utils from "./utils"; import SB from "./SB"; @@ -170,43 +169,43 @@ async function runThePopup() { OptionsElements.sponsorTimesContributionsContainer.style.display = "unset"; //get the userID - let userID = SB.config.userID; - if (userID != undefined) { - //there are probably some views on these submissions then - //get the amount of views from the sponsors submitted - sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - let viewCount = JSON.parse(xmlhttp.responseText).viewCount; - if (viewCount != 0) { - if (viewCount > 1) { - OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); - } else { - OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); - } - - OptionsElements.sponsorTimesViewsDisplay.innerText = viewCount; - OptionsElements.sponsorTimesViewsContainer.style.display = "unset"; + let userID = SB.config.userID; + if (userID != undefined) { + //there are probably some views on these submissions then + //get the amount of views from the sponsors submitted + Utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + let viewCount = JSON.parse(xmlhttp.responseText).viewCount; + if (viewCount != 0) { + if (viewCount > 1) { + OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); + } else { + OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); } + + OptionsElements.sponsorTimesViewsDisplay.innerText = viewCount; + OptionsElements.sponsorTimesViewsContainer.style.display = "unset"; } - }); + } + }); - //get this time in minutes - sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; - if (minutesSaved != 0) { - if (minutesSaved != 1) { - OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); - } else { - OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); - } - - OptionsElements.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); - OptionsElements.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; + //get this time in minutes + Utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; + if (minutesSaved != 0) { + if (minutesSaved != 1) { + OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); + } else { + OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); } + + OptionsElements.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); + OptionsElements.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; } - }); - } + } + }); + } } //get the amount of times this user has skipped a sponsor @@ -859,27 +858,27 @@ async function runThePopup() { //make the options username setting option visible function setUsernameButton() { - //get username from the server - sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; + //get username from the server + Utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; - OptionsElements.submitUsername.style.display = "unset"; - OptionsElements.usernameInput.style.display = "unset"; + OptionsElements.submitUsername.style.display = "unset"; + OptionsElements.usernameInput.style.display = "unset"; - OptionsElements.setUsernameContainer.style.display = "none"; - OptionsElements.setUsername.style.display = "unset"; - OptionsElements - OptionsElements.setUsernameStatusContainer.style.display = "none"; - } else if (xmlhttp.readyState == 4) { - OptionsElements.setUsername.style.display = "unset"; - OptionsElements.submitUsername.style.display = "none"; - OptionsElements.usernameInput.style.display = "none"; + OptionsElements.setUsernameContainer.style.display = "none"; + OptionsElements.setUsername.style.display = "unset"; + OptionsElements + OptionsElements.setUsernameStatusContainer.style.display = "none"; + } else if (xmlhttp.readyState == 4) { + OptionsElements.setUsername.style.display = "unset"; + OptionsElements.submitUsername.style.display = "none"; + OptionsElements.usernameInput.style.display = "none"; - OptionsElements.setUsernameStatusContainer.style.display = "unset"; - OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); - } - }); + OptionsElements.setUsernameStatusContainer.style.display = "unset"; + OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + } + }); } //submit the new username @@ -889,17 +888,17 @@ async function runThePopup() { OptionsElements.setUsernameStatus.innerText = "Loading..."; //get the userID - sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - //submitted - OptionsElements.submitUsername.style.display = "none"; - OptionsElements.usernameInput.style.display = "none"; + Utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + //submitted + OptionsElements.submitUsername.style.display = "none"; + OptionsElements.usernameInput.style.display = "none"; - OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); - } else if (xmlhttp.readyState == 4) { - OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); - } - }); + OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); + } else if (xmlhttp.readyState == 4) { + OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + } + }); OptionsElements.setUsernameContainer.style.display = "none"; @@ -1106,25 +1105,6 @@ async function runThePopup() { return secondsFormatted; } - function sendRequestToServer(type, address, callback) { - let xmlhttp = new XMLHttpRequest(); - - xmlhttp.open(type, CompileConfig.serverAddress + address, true); - - if (callback != undefined) { - xmlhttp.onreadystatechange = function () { - callback(xmlhttp, false); - }; - - xmlhttp.onerror = function(ev) { - callback(xmlhttp, true); - }; - } - - //submit this request - xmlhttp.send(); - } - /** * Converts time in hours to 5h 25.1 * If less than 1 hour, just returns minutes diff --git a/src/utils.ts b/src/utils.ts index 912e7cd0..838e1996 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,4 @@ +import * as CompileConfig from "../config.json"; import SB from "./SB"; class Utils { @@ -268,6 +269,25 @@ class Utils { return errorMessage; } + static sendRequestToServer(type, address, callback) { + let xmlhttp = new XMLHttpRequest(); + + xmlhttp.open(type, CompileConfig.serverAddress + address, true); + + if (callback != undefined) { + xmlhttp.onreadystatechange = function () { + callback(xmlhttp, false); + }; + + xmlhttp.onerror = function(ev) { + callback(xmlhttp, true); + }; + } + + //submit this request + xmlhttp.send(); + } + /** * Is this Firefox (web-extensions) */ From 932cf8ecf180506fafec28e717ba03e89cb3bcb3 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 16:53:33 -0500 Subject: [PATCH 06/30] Fixed SBMap not importing entries. --- src/SB.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/SB.ts b/src/SB.ts index 751137f1..48edab13 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -9,6 +9,17 @@ interface SBObject { // Allows a SBMap to be conveted into json form // Currently used for local storage class SBMap extends Map { + constructor(entries?: [T, U][]) { + super(); + + // Import all entries if they were given + if (entries !== undefined) { + for (const item of entries) { + this.set(entries[0], entries[1]) + } + } + } + toJSON() { return Array.from(this.entries()); } @@ -205,7 +216,7 @@ function resetConfig() { function convertJSON() { Object.keys(SB.defaults).forEach(key => { - SB.localConfig[key] = decodeStoredItem(SB.localConfig[key], key); + SB.localConfig[key] = decodeStoredItem(SB.localConfig[key]); }); } From de66e21d148e9a59b835b1c9c48aebbb5dbe522d Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 17:36:02 -0500 Subject: [PATCH 07/30] Added support for the on page popup. --- src/content.ts | 27 +++++---------------------- src/popup.ts | 37 +++++++++++++++++-------------------- src/utils.ts | 9 ++++++++- 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/src/content.ts b/src/content.ts index 2e3f7c73..88eba234 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1,6 +1,8 @@ import Utils from "./utils"; import SB from "./SB"; +import runThePopup from "./popup.js"; + import PreviewBar from "./js-components/previewBar"; import SkipNotice from "./js-components/previewBar"; @@ -74,7 +76,7 @@ var popupInitialised = false; //get messages from the background script and the popup chrome.runtime.onMessage.addListener(messageListener); -function messageListener(request, sender, sendResponse) { +function messageListener(request: any, sender: any, sendResponse: (response: any) => void): void { //messages from popup script switch(request.message){ case "update": @@ -578,7 +580,7 @@ function skipToTime(v, index, sponsorTimes, openNotice) { //send telemetry that a this sponsor was skipped if (SB.config.trackViewCount && !sponsorSkipped[index]) { - sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); + Utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); if (!SB.config.disableAutoSkip) { // Count this as a skip @@ -806,7 +808,7 @@ function openInfoMenu() { parentNode.insertBefore(popup, parentNode.firstChild); //run the popup init script - runThePopup(); + runThePopup(messageListener); } }); } @@ -1055,25 +1057,6 @@ function getFormattedTime(seconds) { return formatted; } -function sendRequestToServer(type: string, address: string, callback = null) { - let xmlhttp = new XMLHttpRequest(); - - xmlhttp.open(type, serverAddress + address, true); - - if (callback !== null) { - xmlhttp.onreadystatechange = function () { - callback(xmlhttp, false); - }; - - xmlhttp.onerror = function(ev) { - callback(xmlhttp, true); - }; - } - - //submit this request - xmlhttp.send(); -} - function sendRequestToCustomServer(type, fullAddress, callback) { let xmlhttp = new XMLHttpRequest(); diff --git a/src/popup.ts b/src/popup.ts index e5e0bfc2..a2c46c5f 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -1,23 +1,27 @@ import Utils from "./utils"; import SB from "./SB"; -class MessageHandler { - onContentScript: boolean; +interface MessageListener { + (request: any, sender: any, callback: (response: any) => void): void; +} - constructor (onContentScript: boolean = false) { - this.onContentScript = onContentScript; +class MessageHandler { + messageListener: MessageListener; + + constructor (messageListener?: MessageListener) { + this.messageListener = messageListener; } sendMessage(id: number, request, callback?) { - if (this.onContentScript) { - messageListener(request, null, callback); + if (this.messageListener) { + this.messageListener(request, null, callback); } else { - chrome.tabs.sendMessage(id, request. callback); + chrome.tabs.sendMessage(id, request, callback); } } query(config, callback) { - if (this.onContentScript) { + if (this.messageListener) { // Send back dummy info callback([{ url: document.URL, @@ -30,21 +34,12 @@ class MessageHandler { } } -var messageHandler = new MessageHandler(); - //make this a function to allow this to run on the content page -async function runThePopup() { +async function runThePopup(messageListener?: MessageListener) { + var messageHandler = new MessageHandler(); + Utils.localizeHtmlPage(); - //is it in the popup or content script - var inPopup = true; - if (chrome.tabs == undefined) { - //this is on the content script, use direct communication - messageHandler = new MessageHandler(true); - - inPopup = false; - } - await Utils.wait(() => SB.config !== undefined); var OptionsElements: any = {}; @@ -1128,3 +1123,5 @@ if (chrome.tabs != undefined) { //this means it is actually opened in the popup runThePopup(); } + +export default runThePopup; \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts index 838e1996..ad8bcfac 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -269,7 +269,14 @@ class Utils { return errorMessage; } - static sendRequestToServer(type, address, callback) { + /** + * Sends a request to the SponsorBlock server with address added as a query + * + * @param type The request type. "GET", "POST", etc. + * @param address The address to add to the SponsorBlock server address + * @param callback + */ + static sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) { let xmlhttp = new XMLHttpRequest(); xmlhttp.open(type, CompileConfig.serverAddress + address, true); From 070a51954abb51a7bd36c5af27e255925992a5ea Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 17:38:58 -0500 Subject: [PATCH 08/30] Fixed channel ID promise --- src/content.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/content.ts b/src/content.ts index 88eba234..20820ae8 100644 --- a/src/content.ts +++ b/src/content.ts @@ -224,7 +224,9 @@ function videoIDChange(id) { //id is not valid if (!id) return; - let channelIDPromise = Utils.wait(getChannelID); + // TODO: Use a better method here than using type any + // This is done to be able to do channelIDPromise.isFulfilled and channelIDPromise.isRejected + let channelIDPromise: any = Utils.wait(getChannelID); channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true); //setup the preview bar @@ -341,7 +343,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { //check database for sponsor times //made true once a setTimeout has been created to try again after a server error let recheckStarted = false; - sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { + Utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { sponsorDataFound = true; From 7716827a981a8cbdd811ff63144a6b475cdcfd02 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 17:40:12 -0500 Subject: [PATCH 09/30] Fixed incorrect import. --- src/content.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content.ts b/src/content.ts index 20820ae8..782beaf5 100644 --- a/src/content.ts +++ b/src/content.ts @@ -4,7 +4,7 @@ import SB from "./SB"; import runThePopup from "./popup.js"; import PreviewBar from "./js-components/previewBar"; -import SkipNotice from "./js-components/previewBar"; +import SkipNotice from "./js-components/skipNotice"; //was sponsor data found when doing SponsorsLookup var sponsorDataFound = false; From 98b36380b51d4d878328110023d2e8118aace900 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 17:46:55 -0500 Subject: [PATCH 10/30] Update readme to new config name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fcbfe7a..cc70e1e0 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ You can read the API docs [here](https://github.com/ajayyy/SponsorBlockServer#ap # Build Yourself -You can load this project as an unpacked extension. Make sure to rename the `config.js.example` file to `config.js` before installing. +You can load this project as an unpacked extension. Make sure to rename the `config.json.example` file to `config.json` before installing. There are also other build scripts available. Install `npm`, then run `npm install` in the repository. From 20a09d3d279deef6c15cd12a7130686b9cd02538 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 17:51:42 -0500 Subject: [PATCH 11/30] Fixed type errors. --- src/js-components/skipNotice.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/js-components/skipNotice.ts b/src/js-components/skipNotice.ts index 27d8425b..446cacd3 100644 --- a/src/js-components/skipNotice.ts +++ b/src/js-components/skipNotice.ts @@ -9,7 +9,7 @@ class SkipNotice { manualSkip: boolean; maxCountdownTime: () => number; countdownTime: any; - countdownInterval: number; + countdownInterval: NodeJS.Timeout; unskipCallback: any; idSuffix: any; @@ -28,7 +28,7 @@ class SkipNotice { //the countdown until this notice closes this.countdownTime = this.maxCountdownTime(); //the id for the setInterval running the countdown - this.countdownInterval = -1; + this.countdownInterval = null; //the unskip button's callback this.unskipCallback = this.unskip.bind(this); @@ -220,7 +220,7 @@ class SkipNotice { pauseCountdown() { //remove setInterval clearInterval(this.countdownInterval); - this.countdownInterval = -1; + this.countdownInterval = null; //reset countdown this.countdownTime = this.maxCountdownTime(); @@ -237,7 +237,7 @@ class SkipNotice { startCountdown() { //if it has already started, don't start it again - if (this.countdownInterval != -1) return; + if (this.countdownInterval !== null) return; this.countdownInterval = setInterval(this.countdown.bind(this), 1000); @@ -425,7 +425,7 @@ class SkipNotice { } //remove setInterval - if (this.countdownInterval != -1) clearInterval(this.countdownInterval); + if (this.countdownInterval !== null) clearInterval(this.countdownInterval); } } From 4bd410f04e46127f528cf47ada9f499069fde71e Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 18:17:48 -0500 Subject: [PATCH 12/30] Made the skip notice work with TypeScript. --- src/content.ts | 15 ++++++++++++++- src/js-components/skipNotice.ts | 28 ++++++++++++++++------------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/content.ts b/src/content.ts index 782beaf5..06d5fba6 100644 --- a/src/content.ts +++ b/src/content.ts @@ -73,6 +73,19 @@ var sponsorTimesSubmitting = []; //this is used to close the popup on YouTube when the other popup opens var popupInitialised = false; +// Contains all of the functions and variables needed by the skip notice +var skipNoticeContentContainer = { + vote, + dontShowNoticeAgain, + unskipSponsorTime, + sponsorTimes, + UUIDs, + v, + reskipSponsorTime, + hiddenSponsorTimes, + updatePreviewBar +}; + //get messages from the background script and the popup chrome.runtime.onMessage.addListener(messageListener); @@ -564,7 +577,7 @@ function skipToTime(v, index, sponsorTimes, openNotice) { if (openNotice) { //send out the message saying that a sponsor message was skipped if (!SB.config.dontShowNotice) { - let skipNotice = new SkipNotice(this, currentUUID, SB.config.disableAutoSkip); + let skipNotice = new SkipNotice(this, currentUUID, SB.config.disableAutoSkip, skipNoticeContentContainer); //TODO: Remove this when Invidious support is old if (SB.config.invidiousUpdateInfoShowCount < 5) { diff --git a/src/js-components/skipNotice.ts b/src/js-components/skipNotice.ts index 446cacd3..fd675d6e 100644 --- a/src/js-components/skipNotice.ts +++ b/src/js-components/skipNotice.ts @@ -7,16 +7,20 @@ class SkipNotice { parent: HTMLElement; UUID: string; manualSkip: boolean; + // Contains functions and variables from the content script needed by the skip notice + contentContainer: any; + maxCountdownTime: () => number; countdownTime: any; countdownInterval: NodeJS.Timeout; unskipCallback: any; idSuffix: any; - constructor(parent: HTMLElement, UUID: string, manualSkip: boolean = false) { + constructor(parent: HTMLElement, UUID: string, manualSkip: boolean = false, contentContainer) { this.parent = parent; this.UUID = UUID; this.manualSkip = manualSkip; + this.contentContainer = contentContainer; let noticeTitle = chrome.i18n.getMessage("noticeTitle"); @@ -124,7 +128,7 @@ class SkipNotice { downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + this.idSuffix; downvoteButton.className = "sponsorSkipObject voteButton"; downvoteButton.src = chrome.extension.getURL("icons/report.png"); - downvoteButton.addEventListener("click", () => vote(0, this.UUID, this)); + downvoteButton.addEventListener("click", () => this.contentContainer.vote(0, this.UUID, this)); downvoteButton.setAttribute("title", chrome.i18n.getMessage("reportButtonInfo")); //add downvote and report text to container @@ -152,7 +156,7 @@ class SkipNotice { let dontShowAgainButton = document.createElement("button"); dontShowAgainButton.innerText = chrome.i18n.getMessage("Hide"); dontShowAgainButton.className = "sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"; - dontShowAgainButton.addEventListener("click", dontShowNoticeAgain); + dontShowAgainButton.addEventListener("click", this.contentContainer.dontShowNoticeAgain); // Don't let them hide it if manually skipping if (!this.manualSkip) { @@ -251,7 +255,7 @@ class SkipNotice { } unskip() { - unskipSponsorTime(this.UUID); + this.contentContainer.unskipSponsorTime(this.UUID); this.unskippedMode(chrome.i18n.getMessage("reskip")); } @@ -267,8 +271,8 @@ class SkipNotice { //change max duration to however much of the sponsor is left this.maxCountdownTime = function() { - let sponsorTime = sponsorTimes[UUIDs.indexOf(this.UUID)]; - let duration = Math.round(sponsorTime[1] - v.currentTime); + let sponsorTime = this.contentContainer.sponsorTimes[this.contentContainer.UUIDs.indexOf(this.UUID)]; + let duration = Math.round(sponsorTime[1] - this.contentContainer.v.currentTime); return Math.max(duration, 4); }; @@ -278,7 +282,7 @@ class SkipNotice { } reskip() { - reskipSponsorTime(this.UUID); + this.contentContainer.reskipSponsorTime(this.UUID); //change reskip button to a unskip button let unskipButton = this.changeUnskipButton(chrome.i18n.getMessage("unskip")); @@ -296,7 +300,7 @@ class SkipNotice { if (this.manualSkip) { this.changeNoticeTitle(chrome.i18n.getMessage("noticeTitle")); - vote(1, this.UUID, this); + this.contentContainer.vote(1, this.UUID, this); } } @@ -320,14 +324,14 @@ class SkipNotice { //remove this sponsor from the sponsors looked up //find which one it is - for (let i = 0; i < sponsorTimes.length; i++) { - if (UUIDs[i] == this.UUID) { + for (let i = 0; i < this.contentContainer.sponsorTimes.length; i++) { + if (this.contentContainer.UUIDs[i] == this.UUID) { //this one is the one to hide //add this as a hidden sponsorTime - hiddenSponsorTimes.push(i); + this.contentContainer.hiddenSponsorTimes.push(i); - updatePreviewBar(); + this.contentContainer.updatePreviewBar(); break; } } From 17381e7debba87863b91d2bdaf75932882a02298 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 18:47:36 -0500 Subject: [PATCH 13/30] Moved Utils away from a static class. Moved Firefox content script registration to the background script. Moved onInvidious to the content script. --- src/SB.ts | 1 - src/background.ts | 38 +++++++++----- src/content.ts | 128 ++++++++++++++++++++++++++++++---------------- src/popup.ts | 24 +++++---- src/utils.ts | 81 ++++++++--------------------- 5 files changed, 143 insertions(+), 129 deletions(-) diff --git a/src/SB.ts b/src/SB.ts index 48edab13..9f816ae2 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -1,4 +1,3 @@ - interface SBObject { configListeners: Array; defaults: any; diff --git a/src/background.ts b/src/background.ts index 29f63c51..a5650135 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1,17 +1,19 @@ -import Utils from "./utils"; +import * as Types from "./types"; import SB from "./SB"; -import * as Types from "./types"; - -Utils.isBackgroundScript = true; +import Utils from "./utils"; +var utils = new Utils({ + registerFirefoxContentScript, + unregisterFirefoxContentScript +}); // Used only on Firefox, which does not support non persistent background pages. var contentScriptRegistrations = {}; // Register content script if needed -if (Utils.isFirefox()) { - Utils.wait(() => SB.config !== undefined).then(function() { - if (SB.config.supportInvidious) Utils.setupExtraSiteContentScripts(); +if (utils.isFirefox()) { + utils.wait(() => SB.config !== undefined).then(function() { + if (SB.config.supportInvidious) utils.setupExtraSiteContentScripts(); }); } @@ -62,9 +64,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { registerFirefoxContentScript(request); return false; case "unregisterContentScript": - contentScriptRegistrations[request.id].unregister(); - delete contentScriptRegistrations[request.id]; - + unregisterFirefoxContentScript(request.id) return false; } }); @@ -82,7 +82,7 @@ chrome.runtime.onInstalled.addListener(function (object) { chrome.tabs.create({url: chrome.extension.getURL("/help/index_en.html")}); //generate a userID - const newUserID = Utils.generateUserID(); + const newUserID = utils.generateUserID(); //save this UUID SB.config.userID = newUserID; @@ -111,6 +111,16 @@ function registerFirefoxContentScript(options) { }).then((registration) => void (contentScriptRegistrations[options.id] = registration)); } +/** + * Only works on Firefox. + * Firefox requires that this is handled by the background script + * + */ +function unregisterFirefoxContentScript(id: string) { + contentScriptRegistrations[id].unregister(); + delete contentScriptRegistrations[id]; +} + //gets the sponsor times from memory function getSponsorTimes(videoID, callback) { let sponsorTimes = []; @@ -148,12 +158,12 @@ function submitVote(type, UUID, callback) { if (userID == undefined || userID === "undefined") { //generate one - userID = Utils.generateUserID(); + userID = utils.generateUserID(); SB.config.userID = userID; } //publish this vote - Utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { + utils.sendRequestToServer("POST", "/api/voteOnSponsorTime?UUID=" + UUID + "&userID=" + userID + "&type=" + type, function(xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { callback({ successType: 1 @@ -205,7 +215,7 @@ async function submitTimes(videoID, callback) { let increasedContributionAmount = false; //submit the sponsorTime - Utils.sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + utils.sendRequestToServer("GET", "/api/postVideoSponsorTimes?videoID=" + videoID + "&startTime=" + sponsorTimes[i][0] + "&endTime=" + sponsorTimes[i][1] + "&userID=" + userID, function(xmlhttp, error) { if (xmlhttp.readyState == 4 && !error) { callback({ diff --git a/src/content.ts b/src/content.ts index 06d5fba6..ed53100c 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1,7 +1,9 @@ -import Utils from "./utils"; import SB from "./SB"; -import runThePopup from "./popup.js"; +import Utils from "./utils"; +var utils = new Utils(); + +import runThePopup from "./popup"; import PreviewBar from "./js-components/previewBar"; import SkipNotice from "./js-components/skipNotice"; @@ -24,7 +26,7 @@ var sponsorSkipped = []; //the video var v; -var listenerAdded; +var onInvidious; //the video id of the last preview bar update var lastPreviewBarUpdate; @@ -48,7 +50,7 @@ var previewBar = null; var controls = null; // Direct Links -videoIDChange(Utils.getYouTubeVideoID(document.URL)); +videoIDChange(getYouTubeVideoID(document.URL)); //the last time looked at (used to see if this time is in the interval) var lastTime = -1; @@ -93,7 +95,7 @@ function messageListener(request: any, sender: any, sendResponse: (response: any //messages from popup script switch(request.message){ case "update": - videoIDChange(Utils.getYouTubeVideoID(document.URL)); + videoIDChange(getYouTubeVideoID(document.URL)); break; case "sponsorStart": sponsorMessageStarted(sendResponse); @@ -239,13 +241,13 @@ function videoIDChange(id) { // TODO: Use a better method here than using type any // This is done to be able to do channelIDPromise.isFulfilled and channelIDPromise.isRejected - let channelIDPromise: any = Utils.wait(getChannelID); + let channelIDPromise: any = utils.wait(getChannelID); channelIDPromise.then(() => channelIDPromise.isFulfilled = true).catch(() => channelIDPromise.isRejected = true); //setup the preview bar if (previewBar == null) { //create it - Utils.wait(getControls).then(result => { + utils.wait(getControls).then(result => { const progressElementSelectors = [ // For YouTube "ytp-progress-bar-container", @@ -296,7 +298,7 @@ function videoIDChange(id) { sponsorTimesSubmitting = []; //see if the onvideo control image needs to be changed - Utils.wait(getControls).then(result => { + utils.wait(getControls).then(result => { chrome.runtime.sendMessage({ message: "getSponsorTimes", videoID: id @@ -321,7 +323,7 @@ function videoIDChange(id) { }); }); //see if video controls buttons should be added - if (!Utils.onInvidious) { + if (!onInvidious) { updateVisibilityOfPlayerControlsButton(); } } @@ -346,7 +348,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { whitelistCheck(); } else if (channelIDPromise.isRejected) { //try again - Utils.wait(getChannelID).then(whitelistCheck).catch(); + utils.wait(getChannelID).then(whitelistCheck).catch(); } else { //add it as a then statement channelIDPromise.then(whitelistCheck); @@ -356,7 +358,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { //check database for sponsor times //made true once a setTimeout has been created to try again after a server error let recheckStarted = false; - Utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { + utils.sendRequestToServer('GET', "/api/getVideoSponsorTimes?videoID=" + id, function(xmlhttp) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { sponsorDataFound = true; @@ -412,30 +414,44 @@ function sponsorsLookup(id: string, channelIDPromise = null) { } } -function updatePreviewBar() { - let localSponsorTimes = sponsorTimes; - if (localSponsorTimes == null) localSponsorTimes = []; +function getYouTubeVideoID(url: string) { + // For YouTube TV support + if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", ""); + + //Attempt to parse url + let urlObject = null; + try { + urlObject = new URL(url); + } catch (e) { + console.error("[SB] Unable to parse URL: " + url); + return false; + } - let allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting); - - //create an array of the sponsor types - let types = []; - for (let i = 0; i < localSponsorTimes.length; i++) { - if (!hiddenSponsorTimes.includes(i)) { - types.push("sponsor"); - } else { - // Don't show this sponsor - types.push(null); + //Check if valid hostname + if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) { + onInvidious = true; + } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { + if (!SB.config) { + // Call this later, in case this is an Invidious tab + this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); } - } - for (let i = 0; i < sponsorTimesSubmitting.length; i++) { - types.push("previewSponsor"); + + return false } - Utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); - - //update last video id - lastPreviewBarUpdate = sponsorVideoID; + //Get ID from searchParam + if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) { + let id = urlObject.searchParams.get("v"); + return id.length == 11 ? id : false; + } else if (urlObject.pathname.startsWith("/embed/")) { + try { + return urlObject.pathname.substr(7, 11); + } catch (e) { + console.error("[SB] Video ID not valid for " + url); + return false; + } + } + return false; } function getChannelID() { @@ -445,7 +461,7 @@ function getChannelID() { channelURLContainer = document.querySelector("#channel-name > #container > #text-container > #text"); if (channelURLContainer !== null) { channelURLContainer = channelURLContainer.firstElementChild; - } else if (Utils.onInvidious) { + } else if (onInvidious) { // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... channelURLContainer = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a"); } else { @@ -466,7 +482,7 @@ function getChannelID() { let currentTitle = ""; if (titleInfoContainer != null) { currentTitle = ( titleInfoContainer.firstElementChild.firstElementChild.querySelector(".title").firstElementChild).innerText; - } else if (Utils.onInvidious) { + } else if (onInvidious) { // Unfortunately, the Invidious HTML doesn't have much in the way of element identifiers... currentTitle = document.querySelector("body > div > div.pure-u-1.pure-u-md-20-24 div.pure-u-1.pure-u-lg-3-5 > div > a > div > span").textContent; } else { @@ -487,6 +503,32 @@ function getChannelID() { channelWhitelisted = false; } +function updatePreviewBar() { + let localSponsorTimes = sponsorTimes; + if (localSponsorTimes == null) localSponsorTimes = []; + + let allSponsorTimes = localSponsorTimes.concat(sponsorTimesSubmitting); + + //create an array of the sponsor types + let types = []; + for (let i = 0; i < localSponsorTimes.length; i++) { + if (!hiddenSponsorTimes.includes(i)) { + types.push("sponsor"); + } else { + // Don't show this sponsor + types.push(null); + } + } + for (let i = 0; i < sponsorTimesSubmitting.length; i++) { + types.push("previewSponsor"); + } + + utils.wait(() => previewBar !== null).then((result) => previewBar.set(allSponsorTimes, types, v.duration)); + + //update last video id + lastPreviewBarUpdate = sponsorVideoID; +} + //checks if this channel is whitelisted, should be done only after the channelID has been loaded function whitelistCheck() { //see if this is a whitelisted channel @@ -595,7 +637,7 @@ function skipToTime(v, index, sponsorTimes, openNotice) { //send telemetry that a this sponsor was skipped if (SB.config.trackViewCount && !sponsorSkipped[index]) { - Utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); + utils.sendRequestToServer("POST", "/api/viewedVideoSponsorTime?UUID=" + currentUUID); if (!SB.config.disableAutoSkip) { // Count this as a skip @@ -659,7 +701,7 @@ function getControls() { //adds all the player controls buttons async function createButtons() { - let result = await Utils.wait(getControls).catch(); + let result = await utils.wait(getControls).catch(); //set global controls variable controls = result; @@ -677,7 +719,7 @@ async function updateVisibilityOfPlayerControlsButton() { await createButtons(); - if (SB.config.hideVideoPlayerControls || Utils.onInvidious) { + if (SB.config.hideVideoPlayerControls || onInvidious) { document.getElementById("startSponsorButton").style.display = "none"; document.getElementById("submitButton").style.display = "none"; } else { @@ -685,13 +727,13 @@ async function updateVisibilityOfPlayerControlsButton() { } //don't show the info button on embeds - if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || Utils.onInvidious) { + if (SB.config.hideInfoButtonPlayerControls || document.URL.includes("/embed/") || onInvidious) { document.getElementById("infoButton").style.display = "none"; } else { document.getElementById("infoButton").style.removeProperty("display"); } - if (SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious) { + if (SB.config.hideDeleteButtonPlayerControls || onInvidious) { document.getElementById("deleteButton").style.display = "none"; } } @@ -740,10 +782,10 @@ async function changeStartSponsorButton(showStartSponsor, uploadButtonVisible) { if(!sponsorVideoID) return false; //make sure submit button is loaded - await Utils.wait(isSubmitButtonLoaded); + await utils.wait(isSubmitButtonLoaded); //if it isn't visible, there is no data - let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || Utils.onInvidious)) ? "unset" : "none" + let shouldHide = (uploadButtonVisible && !(SB.config.hideDeleteButtonPlayerControls || onInvidious)) ? "unset" : "none" document.getElementById("deleteButton").style.display = shouldHide; if (showStartSponsor) { @@ -911,7 +953,7 @@ function vote(type, UUID, skipNotice) { skipNotice.addNoticeInfoMessage.bind(skipNotice)(chrome.i18n.getMessage("voteFail")) skipNotice.resetVoteButtonInfo.bind(skipNotice)(); } else if (response.successType == -1) { - skipNotice.addNoticeInfoMessage.bind(skipNotice)(Utils.getErrorMessage(response.statusCode)) + skipNotice.addNoticeInfoMessage.bind(skipNotice)(utils.getErrorMessage(response.statusCode)) skipNotice.resetVoteButtonInfo.bind(skipNotice)(); } } @@ -1016,7 +1058,7 @@ function sendSubmitMessage(){ sponsorTimes = sponsorTimes.concat(sponsorTimesSubmitting); for (let i = 0; i < sponsorTimesSubmitting.length; i++) { // Add some random IDs - UUIDs.push(Utils.generateUserID()); + UUIDs.push(utils.generateUserID()); } // Empty the submitting times @@ -1028,7 +1070,7 @@ function sendSubmitMessage(){ document.getElementById("submitButton").style.animation = "unset"; ( document.getElementById("submitImage")).src = chrome.extension.getURL("icons/PlayerUploadFailedIconSponsorBlocker256px.png"); - alert(Utils.getErrorMessage(response.statusCode)); + alert(utils.getErrorMessage(response.statusCode)); } } }); diff --git a/src/popup.ts b/src/popup.ts index a2c46c5f..f53aded2 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -1,6 +1,8 @@ -import Utils from "./utils"; import SB from "./SB"; +import Utils from "./utils"; +var utils = new Utils(); + interface MessageListener { (request: any, sender: any, callback: (response: any) => void): void; } @@ -38,9 +40,9 @@ class MessageHandler { async function runThePopup(messageListener?: MessageListener) { var messageHandler = new MessageHandler(); - Utils.localizeHtmlPage(); + utils.localizeHtmlPage(); - await Utils.wait(() => SB.config !== undefined); + await utils.wait(() => SB.config !== undefined); var OptionsElements: any = {}; @@ -168,7 +170,7 @@ async function runThePopup(messageListener?: MessageListener) { if (userID != undefined) { //there are probably some views on these submissions then //get the amount of views from the sponsors submitted - Utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { + utils.sendRequestToServer("GET", "/api/getViewsForUser?userID=" + userID, function(xmlhttp) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { let viewCount = JSON.parse(xmlhttp.responseText).viewCount; if (viewCount != 0) { @@ -185,7 +187,7 @@ async function runThePopup(messageListener?: MessageListener) { }); //get this time in minutes - Utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { + utils.sendRequestToServer("GET", "/api/getSavedTimeForUser?userID=" + userID, function(xmlhttp) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; if (minutesSaved != 0) { @@ -802,7 +804,7 @@ async function runThePopup(messageListener?: MessageListener) { clearTimes(); } else { - document.getElementById("submitTimesInfoMessage").innerText = Utils.getErrorMessage(response.statusCode); + document.getElementById("submitTimesInfoMessage").innerText = utils.getErrorMessage(response.statusCode); document.getElementById("submitTimesInfoMessageContainer").style.display = "unset"; OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; @@ -854,7 +856,7 @@ async function runThePopup(messageListener?: MessageListener) { //make the options username setting option visible function setUsernameButton() { //get username from the server - Utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { + utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; @@ -871,7 +873,7 @@ async function runThePopup(messageListener?: MessageListener) { OptionsElements.usernameInput.style.display = "none"; OptionsElements.setUsernameStatusContainer.style.display = "unset"; - OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); } }); } @@ -883,7 +885,7 @@ async function runThePopup(messageListener?: MessageListener) { OptionsElements.setUsernameStatus.innerText = "Loading..."; //get the userID - Utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { + utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { //submitted OptionsElements.submitUsername.style.display = "none"; @@ -891,7 +893,7 @@ async function runThePopup(messageListener?: MessageListener) { OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); } else if (xmlhttp.readyState == 4) { - OptionsElements.setUsernameStatus.innerText = Utils.getErrorMessage(xmlhttp.status); + OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); } }); @@ -944,7 +946,7 @@ async function runThePopup(messageListener?: MessageListener) { //failure: duplicate vote addVoteMessage(chrome.i18n.getMessage("voteFail"), UUID) } else if (response.successType == -1) { - addVoteMessage(Utils.getErrorMessage(response.statusCode), UUID) + addVoteMessage(utils.getErrorMessage(response.statusCode), UUID) } } }); diff --git a/src/utils.ts b/src/utils.ts index ad8bcfac..a73004d1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -3,11 +3,15 @@ import SB from "./SB"; class Utils { - static isBackgroundScript = false; - static onInvidious = false; + // Contains functions needed from the background script + backgroundScriptContainer: any = null; + + constructor(backgroundScriptContainer?: any) { + this.backgroundScriptContainer = backgroundScriptContainer; + } // Function that can be used to wait for a condition before returning - static async wait(condition, timeout = 5000, check = 100) { + async wait(condition, timeout = 5000, check = 100) { return await new Promise((resolve, reject) => { setTimeout(() => reject("TIMEOUT"), timeout); @@ -26,46 +30,6 @@ class Utils { }); } - static getYouTubeVideoID(url: string) { - // For YouTube TV support - if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", ""); - - //Attempt to parse url - let urlObject = null; - try { - urlObject = new URL(url); - } catch (e) { - console.error("[SB] Unable to parse URL: " + url); - return false; - } - - //Check if valid hostname - if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) { - onInvidious = true; - } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { - if (!SB.config) { - // Call this later, in case this is an Invidious tab - this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); - } - - return false - } - - //Get ID from searchParam - if (urlObject.searchParams.has("v") && ["/watch", "/watch/"].includes(urlObject.pathname) || urlObject.pathname.startsWith("/tv/watch")) { - let id = urlObject.searchParams.get("v"); - return id.length == 11 ? id : false; - } else if (urlObject.pathname.startsWith("/embed/")) { - try { - return urlObject.pathname.substr(7, 11); - } catch (e) { - console.error("[SB] Video ID not valid for " + url); - return false; - } - } - return false; - } - /** * Asks for the optional permissions required for all extra sites. * It also starts the content script registrations. @@ -74,7 +38,7 @@ class Utils { * * @param {CallableFunction} callback */ - static setupExtraSitePermissions(callback) { + setupExtraSitePermissions(callback) { // Request permission let permissions = ["declarativeContent"]; if (this.isFirefox()) permissions = []; @@ -100,7 +64,7 @@ class Utils { * * For now, it is just SB.config.invidiousInstances. */ - static setupExtraSiteContentScripts() { + setupExtraSiteContentScripts() { let js = [ "config.js", "SB.js", @@ -135,8 +99,8 @@ class Utils { matches: this.getInvidiousInstancesRegex() }; - if (this.isBackgroundScript) { - registerFirefoxContentScript(registration); + if (this.backgroundScriptContainer) { + this.backgroundScriptContainer.registerFirefoxContentScript(registration); } else { chrome.runtime.sendMessage(registration); } @@ -169,15 +133,12 @@ class Utils { /** * Removes the permission and content script registration. */ - static removeExtraSiteRegistration() { + removeExtraSiteRegistration() { if (this.isFirefox()) { let id = "invidious"; - if (this.isBackgroundScript) { - if (contentScriptRegistrations[id]) { - contentScriptRegistrations[id].unregister(); - delete contentScriptRegistrations[id]; - } + if (this.backgroundScriptContainer) { + this.backgroundScriptContainer.unregisterFirefoxContentScript(id); } else { chrome.runtime.sendMessage({ message: "unregisterContentScript", @@ -193,7 +154,7 @@ class Utils { }); } - static localizeHtmlPage() { + localizeHtmlPage() { //Localize by replacing __MSG_***__ meta tags var objects = document.getElementsByClassName("sponsorBlockPageBody")[0].children; for (var j = 0; j < objects.length; j++) { @@ -204,7 +165,7 @@ class Utils { } } - static getLocalizedMessage(text) { + getLocalizedMessage(text) { var valNewH = text.replace(/__MSG_(\w+)__/g, function(match, v1) { return v1 ? chrome.i18n.getMessage(v1) : ""; }); @@ -219,7 +180,7 @@ class Utils { /** * @returns {String[]} Invidious Instances in regex form */ - static getInvidiousInstancesRegex() { + getInvidiousInstancesRegex() { var invidiousInstancesRegex = []; for (const url of SB.config.invidiousInstances) { invidiousInstancesRegex.push("https://*." + url + "/*"); @@ -229,7 +190,7 @@ class Utils { return invidiousInstancesRegex; } - static generateUserID(length = 36) { + generateUserID(length = 36) { let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; let result = ""; if (window.crypto && window.crypto.getRandomValues) { @@ -253,7 +214,7 @@ class Utils { * @param {int} statusCode * @returns {string} errorMessage */ - static getErrorMessage(statusCode) { + getErrorMessage(statusCode) { let errorMessage = ""; if([400, 429, 409, 502, 0].includes(statusCode)) { @@ -276,7 +237,7 @@ class Utils { * @param address The address to add to the SponsorBlock server address * @param callback */ - static sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) { + sendRequestToServer(type: string, address: string, callback?: (xmlhttp: XMLHttpRequest, err: boolean) => any) { let xmlhttp = new XMLHttpRequest(); xmlhttp.open(type, CompileConfig.serverAddress + address, true); @@ -298,7 +259,7 @@ class Utils { /** * Is this Firefox (web-extensions) */ - static isFirefox() { + isFirefox() { return typeof(browser) !== "undefined"; } } From 23141aa624c94d2164f8cb0a250ef1ba50287155 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 19:18:53 -0500 Subject: [PATCH 14/30] Made the extension successfully build --- public/manifest.json | 15 +- {options => public/options}/options.css | 0 {options => public/options}/options.html | 0 {options => public/options}/options.js | 2 +- public/popup.html | 6 +- src/SB.ts | 8 +- src/background.ts | 2 +- src/content.ts | 4 +- src/popup.ts | 202 +++++++++++------------ src/utils.ts | 8 +- webpack/webpack.common.js | 2 +- 11 files changed, 117 insertions(+), 132 deletions(-) rename {options => public/options}/options.css (100%) rename {options => public/options}/options.html (100%) rename {options => public/options}/options.js (99%) diff --git a/public/manifest.json b/public/manifest.json index b2098124..7331e54b 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -13,13 +13,8 @@ ], "all_frames": true, "js": [ - "config.js", - "SB.js", - "utils/previewBar.js", - "utils/skipNotice.js", - "utils.js", - "content.js", - "popup.js" + "./js/vendor.js", + "./js/content.js" ], "css": [ "content.css", @@ -58,10 +53,8 @@ }, "background": { "scripts":[ - "config.js", - "SB.js", - "utils.js", - "background.js" + "./js/vendor.js", + "./js/background.js" ], "persistent": false }, diff --git a/options/options.css b/public/options/options.css similarity index 100% rename from options/options.css rename to public/options/options.css diff --git a/options/options.html b/public/options/options.html similarity index 100% rename from options/options.html rename to public/options/options.html diff --git a/options/options.js b/public/options/options.js similarity index 99% rename from options/options.js rename to public/options/options.js index bc173d25..2feeb17a 100644 --- a/options/options.js +++ b/public/options/options.js @@ -7,7 +7,7 @@ async function init() { SB.configListeners.push(optionsConfigUpdateListener); } - await wait(() => SB.config !== undefined); + await wait(() => SB.config !== null); // Set all of the toggle options to the correct option let optionsContainer = document.getElementById("options"); diff --git a/public/popup.html b/public/popup.html index 68e9cba2..81dcf62c 100644 --- a/public/popup.html +++ b/public/popup.html @@ -1,7 +1,6 @@ __MSG_openPopup__ - @@ -210,7 +209,6 @@ - - - + + diff --git a/src/SB.ts b/src/SB.ts index 9f816ae2..2cbb9266 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -51,8 +51,8 @@ var SB: SBObject = { "invidiousUpdateInfoShowCount": 0, "autoUpvote": true }, - localConfig: {}, - config: {} + localConfig: null, + config: null }; // Function setup @@ -113,7 +113,7 @@ class MapIO { * A SBMap cannot be stored in the chrome storage. * This data will be encoded into an array instead as specified by the toJSON function. * - * @param {*} data + * @param data */ function encodeStoredItem(data) { // if data is SBMap convert to json for storing @@ -223,7 +223,7 @@ function convertJSON() { function addDefaults() { for (const key in SB.defaults) { if(!SB.localConfig.hasOwnProperty(key)) { - SB.localConfig[key] = SB.defaults[key]; + SB.localConfig[key] = SB.defaults[key]; } } }; diff --git a/src/background.ts b/src/background.ts index a5650135..e1c4f1ac 100644 --- a/src/background.ts +++ b/src/background.ts @@ -12,7 +12,7 @@ var contentScriptRegistrations = {}; // Register content script if needed if (utils.isFirefox()) { - utils.wait(() => SB.config !== undefined).then(function() { + utils.wait(() => SB.config !== null).then(function() { if (SB.config.supportInvidious) utils.setupExtraSiteContentScripts(); }); } diff --git a/src/content.ts b/src/content.ts index ed53100c..8d92bef5 100644 --- a/src/content.ts +++ b/src/content.ts @@ -427,13 +427,13 @@ function getYouTubeVideoID(url: string) { return false; } - //Check if valid hostname + // Check if valid hostname if (SB.config && SB.config.invidiousInstances.includes(urlObject.host)) { onInvidious = true; } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { if (!SB.config) { // Call this later, in case this is an Invidious tab - this.wait(() => SB.config !== undefined).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); + this.wait(() => SB.config !== null).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); } return false diff --git a/src/popup.ts b/src/popup.ts index f53aded2..f477c15d 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -42,9 +42,9 @@ async function runThePopup(messageListener?: MessageListener) { utils.localizeHtmlPage(); - await utils.wait(() => SB.config !== undefined); + await utils.wait(() => SB.config !== null); - var OptionsElements: any = {}; + var PageElements: any = {}; ["sponsorStart", // Top toggles @@ -100,22 +100,22 @@ async function runThePopup(messageListener?: MessageListener) { "videoFound", "sponsorMessageTimes", "downloadedSponsorMessageTimes", - ].forEach(id => OptionsElements[id] = document.getElementById(id)); + ].forEach(id => PageElements[id] = document.getElementById(id)); //setup click listeners - OptionsElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); - OptionsElements.whitelistChannel.addEventListener("click", whitelistChannel); - OptionsElements.unwhitelistChannel.addEventListener("click", unwhitelistChannel); - OptionsElements.disableSkipping.addEventListener("click", () => toggleSkipping(true)); - OptionsElements.enableSkipping.addEventListener("click", () => toggleSkipping(false)); - OptionsElements.clearTimes.addEventListener("click", clearTimes); - OptionsElements.submitTimes.addEventListener("click", submitTimes); - OptionsElements.showNoticeAgain.addEventListener("click", showNoticeAgain); - OptionsElements.setUsernameButton.addEventListener("click", setUsernameButton); - OptionsElements.submitUsername.addEventListener("click", submitUsername); - OptionsElements.optionsButton.addEventListener("click", openOptions); - OptionsElements.reportAnIssue.addEventListener("click", reportAnIssue); - OptionsElements.hideDiscordButton.addEventListener("click", hideDiscordButton); + PageElements.sponsorStart.addEventListener("click", sendSponsorStartMessage); + PageElements.whitelistChannel.addEventListener("click", whitelistChannel); + PageElements.unwhitelistChannel.addEventListener("click", unwhitelistChannel); + PageElements.disableSkipping.addEventListener("click", () => toggleSkipping(true)); + PageElements.enableSkipping.addEventListener("click", () => toggleSkipping(false)); + PageElements.clearTimes.addEventListener("click", clearTimes); + PageElements.submitTimes.addEventListener("click", submitTimes); + PageElements.showNoticeAgain.addEventListener("click", showNoticeAgain); + PageElements.setUsernameButton.addEventListener("click", setUsernameButton); + PageElements.submitUsername.addEventListener("click", submitUsername); + PageElements.optionsButton.addEventListener("click", openOptions); + PageElements.reportAnIssue.addEventListener("click", reportAnIssue); + PageElements.hideDiscordButton.addEventListener("click", hideDiscordButton); //if true, the button now selects the end time let startTimeChosen = false; @@ -132,7 +132,7 @@ async function runThePopup(messageListener?: MessageListener) { let hideDiscordLaunches = SB.config.hideDiscordLaunches; //only if less than 10 launches if (hideDiscordLaunches == undefined || hideDiscordLaunches < 10) { - OptionsElements.discordButtonContainer.style.display = null; + PageElements.discordButtonContainer.style.display = null; if (hideDiscordLaunches == undefined) { hideDiscordLaunches = 1; @@ -144,26 +144,26 @@ async function runThePopup(messageListener?: MessageListener) { //show proper disable skipping button let disableSkipping = SB.config.disableSkipping; if (disableSkipping != undefined && disableSkipping) { - OptionsElements.disableSkipping.style.display = "none"; - OptionsElements.enableSkipping.style.display = "unset"; + PageElements.disableSkipping.style.display = "none"; + PageElements.enableSkipping.style.display = "unset"; } //if the don't show notice again variable is true, an option to // disable should be available let dontShowNotice = SB.config.dontShowNotice; if (dontShowNotice != undefined && dontShowNotice) { - OptionsElements.showNoticeAgain.style.display = "unset"; + PageElements.showNoticeAgain.style.display = "unset"; } //get the amount of times this user has contributed and display it to thank them if (SB.config.sponsorTimesContributed != undefined) { if (SB.config.sponsorTimesContributed > 1) { - OptionsElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors"); + PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsors"); } else { - OptionsElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor"); + PageElements.sponsorTimesContributionsDisplayEndWord.innerText = chrome.i18n.getMessage("Sponsor"); } - OptionsElements.sponsorTimesContributionsDisplay.innerText = SB.config.sponsorTimesContributed; - OptionsElements.sponsorTimesContributionsContainer.style.display = "unset"; + PageElements.sponsorTimesContributionsDisplay.innerText = SB.config.sponsorTimesContributed; + PageElements.sponsorTimesContributionsContainer.style.display = "unset"; //get the userID let userID = SB.config.userID; @@ -175,13 +175,13 @@ async function runThePopup(messageListener?: MessageListener) { let viewCount = JSON.parse(xmlhttp.responseText).viewCount; if (viewCount != 0) { if (viewCount > 1) { - OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); + PageElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segments"); } else { - OptionsElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); + PageElements.sponsorTimesViewsDisplayEndWord.innerText = chrome.i18n.getMessage("Segment"); } - OptionsElements.sponsorTimesViewsDisplay.innerText = viewCount; - OptionsElements.sponsorTimesViewsContainer.style.display = "unset"; + PageElements.sponsorTimesViewsDisplay.innerText = viewCount; + PageElements.sponsorTimesViewsContainer.style.display = "unset"; } } }); @@ -192,13 +192,13 @@ async function runThePopup(messageListener?: MessageListener) { let minutesSaved = JSON.parse(xmlhttp.responseText).timeSaved; if (minutesSaved != 0) { if (minutesSaved != 1) { - OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); + PageElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); } else { - OptionsElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); + PageElements.sponsorTimesOthersTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); } - OptionsElements.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); - OptionsElements.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; + PageElements.sponsorTimesOthersTimeSavedDisplay.innerText = getFormattedHours(minutesSaved); + PageElements.sponsorTimesOthersTimeSavedContainer.style.display = "unset"; } } }); @@ -208,25 +208,25 @@ async function runThePopup(messageListener?: MessageListener) { //get the amount of times this user has skipped a sponsor if (SB.config.skipCount != undefined) { if (SB.config.skipCount != 1) { - OptionsElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors"); + PageElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsors"); } else { - OptionsElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor"); + PageElements.sponsorTimesSkipsDoneEndWord.innerText = chrome.i18n.getMessage("Sponsor"); } - OptionsElements.sponsorTimesSkipsDoneDisplay.innerText = SB.config.skipCount; - OptionsElements.sponsorTimesSkipsDoneContainer.style.display = "unset"; + PageElements.sponsorTimesSkipsDoneDisplay.innerText = SB.config.skipCount; + PageElements.sponsorTimesSkipsDoneContainer.style.display = "unset"; } //get the amount of time this user has saved. if (SB.config.minutesSaved != undefined) { if (SB.config.minutesSaved != 1) { - OptionsElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); + PageElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minsLower"); } else { - OptionsElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); + PageElements.sponsorTimeSavedEndWord.innerText = chrome.i18n.getMessage("minLower"); } - OptionsElements.sponsorTimeSavedDisplay.innerText = getFormattedHours(SB.config.minutesSaved); - OptionsElements.sponsorTimeSavedContainer.style.display = "unset"; + PageElements.sponsorTimeSavedDisplay.innerText = getFormattedHours(SB.config.minutesSaved); + PageElements.sponsorTimeSavedContainer.style.display = "unset"; } messageHandler.query({ @@ -258,7 +258,7 @@ async function runThePopup(messageListener?: MessageListener) { if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { if (sponsorTimesStorage[sponsorTimesStorage.length - 1] != undefined && sponsorTimesStorage[sponsorTimesStorage.length - 1].length < 2) { startTimeChosen = true; - OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); + PageElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); } sponsorTimes = sponsorTimesStorage; @@ -266,7 +266,7 @@ async function runThePopup(messageListener?: MessageListener) { displaySponsorTimes(); //show submission section - OptionsElements.submissionSection.style.display = "unset"; + PageElements.submissionSection.style.display = "unset"; showSubmitTimesIfNecessary(); } @@ -289,15 +289,15 @@ async function runThePopup(messageListener?: MessageListener) { //if request is undefined, then the page currently being browsed is not YouTube if (request != undefined) { //remove loading text - OptionsElements.mainControls.style.display = "unset" - OptionsElements.loadingIndicator.style.display = "none"; + PageElements.mainControls.style.display = "unset" + PageElements.loadingIndicator.style.display = "none"; if (request.found) { - OptionsElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound"); + PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsorFound"); displayDownloadedSponsorTimes(request); } else { - OptionsElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404"); + PageElements.videoFound.innerHTML = chrome.i18n.getMessage("sponsor404"); } } @@ -311,11 +311,11 @@ async function runThePopup(messageListener?: MessageListener) { {message: 'isChannelWhitelisted'}, function(response) { if (response.value) { - OptionsElements.whitelistChannel.style.display = "none"; - OptionsElements.unwhitelistChannel.style.display = "unset"; + PageElements.whitelistChannel.style.display = "none"; + PageElements.unwhitelistChannel.style.display = "unset"; - OptionsElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); - OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + PageElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); + PageElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; } }); } @@ -366,7 +366,7 @@ async function runThePopup(messageListener?: MessageListener) { displaySponsorTimes(); //show submission section - OptionsElements.submissionSection.style.display = "unset"; + PageElements.submissionSection.style.display = "unset"; showSubmitTimesIfNecessary(); } @@ -374,20 +374,20 @@ async function runThePopup(messageListener?: MessageListener) { //display the video times from the array function displaySponsorTimes() { //remove all children - while (OptionsElements.sponsorMessageTimes.firstChild) { - OptionsElements.sponsorMessageTimes.removeChild(OptionsElements.sponsorMessageTimes.firstChild); + while (PageElements.sponsorMessageTimes.firstChild) { + PageElements.sponsorMessageTimes.removeChild(PageElements.sponsorMessageTimes.firstChild); } //add sponsor times - OptionsElements.sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes)); + PageElements.sponsorMessageTimes.appendChild(getSponsorTimesMessageDiv(sponsorTimes)); } //display the video times from the array at the top, in a different section function displayDownloadedSponsorTimes(request) { if (request.sponsorTimes != undefined) { //set it to the message - if (OptionsElements.downloadedSponsorMessageTimes.innerText != chrome.i18n.getMessage("channelWhitelisted")) { - OptionsElements.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); + if (PageElements.downloadedSponsorMessageTimes.innerText != chrome.i18n.getMessage("channelWhitelisted")) { + PageElements.downloadedSponsorMessageTimes.innerText = getSponsorTimesMessage(request.sponsorTimes); } //add them as buttons to the issue reporting container @@ -789,8 +789,8 @@ async function runThePopup(messageListener?: MessageListener) { function submitTimes() { //make info message say loading - OptionsElements.submitTimesInfoMessage.innerText = chrome.i18n.getMessage("Loading"); - OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; + PageElements.submitTimesInfoMessage.innerText = chrome.i18n.getMessage("Loading"); + PageElements.submitTimesInfoMessageContainer.style.display = "unset"; if (sponsorTimes.length > 0) { chrome.runtime.sendMessage({ @@ -800,14 +800,14 @@ async function runThePopup(messageListener?: MessageListener) { if (response != undefined) { if (response.statusCode == 200) { //hide loading message - OptionsElements.submitTimesInfoMessageContainer.style.display = "none"; + PageElements.submitTimesInfoMessageContainer.style.display = "none"; clearTimes(); } else { document.getElementById("submitTimesInfoMessage").innerText = utils.getErrorMessage(response.statusCode); document.getElementById("submitTimesInfoMessageContainer").style.display = "unset"; - OptionsElements.submitTimesInfoMessageContainer.style.display = "unset"; + PageElements.submitTimesInfoMessageContainer.style.display = "unset"; } } }); @@ -817,14 +817,14 @@ async function runThePopup(messageListener?: MessageListener) { function showNoticeAgain() { SB.config.dontShowNotice = false; - OptionsElements.showNoticeAgain.style.display = "none"; + PageElements.showNoticeAgain.style.display = "none"; } function updateStartTimeChosen() { //update startTimeChosen letiable if (!startTimeChosen) { startTimeChosen = true; - OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); + PageElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorEnd"); } else { resetStartTimeChosen(); } @@ -833,7 +833,7 @@ async function runThePopup(messageListener?: MessageListener) { //set it to false function resetStartTimeChosen() { startTimeChosen = false; - OptionsElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorStart"); + PageElements.sponsorStart.innerHTML = chrome.i18n.getMessage("sponsorStart"); } //hides and shows the submit times button when needed @@ -858,22 +858,22 @@ async function runThePopup(messageListener?: MessageListener) { //get username from the server utils.sendRequestToServer("GET", "/api/getUsername?userID=" + SB.config.userID, function (xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - OptionsElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; + PageElements.usernameInput.value = JSON.parse(xmlhttp.responseText).userName; - OptionsElements.submitUsername.style.display = "unset"; - OptionsElements.usernameInput.style.display = "unset"; + PageElements.submitUsername.style.display = "unset"; + PageElements.usernameInput.style.display = "unset"; - OptionsElements.setUsernameContainer.style.display = "none"; - OptionsElements.setUsername.style.display = "unset"; - OptionsElements - OptionsElements.setUsernameStatusContainer.style.display = "none"; + PageElements.setUsernameContainer.style.display = "none"; + PageElements.setUsername.style.display = "unset"; + PageElements + PageElements.setUsernameStatusContainer.style.display = "none"; } else if (xmlhttp.readyState == 4) { - OptionsElements.setUsername.style.display = "unset"; - OptionsElements.submitUsername.style.display = "none"; - OptionsElements.usernameInput.style.display = "none"; + PageElements.setUsername.style.display = "unset"; + PageElements.submitUsername.style.display = "none"; + PageElements.usernameInput.style.display = "none"; - OptionsElements.setUsernameStatusContainer.style.display = "unset"; - OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); + PageElements.setUsernameStatusContainer.style.display = "unset"; + PageElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); } }); } @@ -881,25 +881,25 @@ async function runThePopup(messageListener?: MessageListener) { //submit the new username function submitUsername() { //add loading indicator - OptionsElements.setUsernameStatusContainer.style.display = "unset"; - OptionsElements.setUsernameStatus.innerText = "Loading..."; + PageElements.setUsernameStatusContainer.style.display = "unset"; + PageElements.setUsernameStatus.innerText = "Loading..."; //get the userID - utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + OptionsElements.usernameInput.value, function (xmlhttp, error) { + utils.sendRequestToServer("POST", "/api/setUsername?userID=" + SB.config.userID + "&username=" + PageElements.usernameInput.value, function (xmlhttp, error) { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { //submitted - OptionsElements.submitUsername.style.display = "none"; - OptionsElements.usernameInput.style.display = "none"; + PageElements.submitUsername.style.display = "none"; + PageElements.usernameInput.style.display = "none"; - OptionsElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); + PageElements.setUsernameStatus.innerText = chrome.i18n.getMessage("success"); } else if (xmlhttp.readyState == 4) { - OptionsElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); + PageElements.setUsernameStatus.innerText = utils.getErrorMessage(xmlhttp.status); } }); - OptionsElements.setUsernameContainer.style.display = "none"; - OptionsElements.setUsername.style.display = "unset"; + PageElements.setUsernameContainer.style.display = "none"; + PageElements.setUsername.style.display = "unset"; } //this is not a YouTube video page @@ -909,7 +909,7 @@ async function runThePopup(messageListener?: MessageListener) { function reportAnIssue() { document.getElementById("issueReporterContainer").style.display = "unset"; - OptionsElements.reportAnIssue.style.display = "none"; + PageElements.reportAnIssue.style.display = "none"; } function addVoteMessage(message, UUID) { @@ -954,7 +954,7 @@ async function runThePopup(messageListener?: MessageListener) { function hideDiscordButton() { SB.config.hideDiscordLink = true; - OptionsElements.discordButtonContainer.style.display = "none"; + PageElements.discordButtonContainer.style.display = "none"; } //converts time in seconds to minutes:seconds @@ -992,14 +992,14 @@ async function runThePopup(messageListener?: MessageListener) { whitelistedChannels.push(response.channelURL); //change button - OptionsElements.whitelistChannel.style.display = "none"; - OptionsElements.unwhitelistChannel.style.display = "unset"; + PageElements.whitelistChannel.style.display = "none"; + PageElements.unwhitelistChannel.style.display = "unset"; - OptionsElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); - OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; + PageElements.downloadedSponsorMessageTimes.innerText = chrome.i18n.getMessage("channelWhitelisted"); + PageElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; //save this - OptionsElements.config.whitelistedChannels = whitelistedChannels; + PageElements.config.whitelistedChannels = whitelistedChannels; //send a message to the client messageHandler.query({ @@ -1039,14 +1039,14 @@ async function runThePopup(messageListener?: MessageListener) { whitelistedChannels.splice(index, 1); //change button - OptionsElements.whitelistChannel.style.display = "unset"; - OptionsElements.unwhitelistChannel.style.display = "none"; + PageElements.whitelistChannel.style.display = "unset"; + PageElements.unwhitelistChannel.style.display = "none"; - OptionsElements.downloadedSponsorMessageTimes.innerText = ""; - OptionsElements.downloadedSponsorMessageTimes.style.fontWeight = "unset"; + PageElements.downloadedSponsorMessageTimes.innerText = ""; + PageElements.downloadedSponsorMessageTimes.style.fontWeight = "unset"; //save this - OptionsElements.config.whitelistedChannels = whitelistedChannels; + PageElements.config.whitelistedChannels = whitelistedChannels; //send a message to the client messageHandler.query({ @@ -1069,14 +1069,14 @@ async function runThePopup(messageListener?: MessageListener) { * Should skipping be disabled (visuals stay) */ function toggleSkipping(disabled) { - OptionsElements.config.disableSkipping = disabled; + PageElements.config.disableSkipping = disabled; - let hiddenButton = OptionsElements.disableSkipping; - let shownButton = OptionsElements.enableSkipping; + let hiddenButton = PageElements.disableSkipping; + let shownButton = PageElements.enableSkipping; if (!disabled) { - hiddenButton = OptionsElements.enableSkipping; - shownButton = OptionsElements.disableSkipping; + hiddenButton = PageElements.enableSkipping; + shownButton = PageElements.disableSkipping; } shownButton.style.display = "unset"; diff --git a/src/utils.ts b/src/utils.ts index a73004d1..8f91dc21 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -66,13 +66,7 @@ class Utils { */ setupExtraSiteContentScripts() { let js = [ - "config.js", - "SB.js", - "utils/previewBar.js", - "utils/skipNotice.js", - "utils.js", - "content.js", - "popup.js" + "content.js" ]; let css = [ "content.css", diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 27d7fc1a..55488488 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -7,7 +7,7 @@ module.exports = { entry: { popup: path.join(__dirname, srcDir + 'popup.ts'), background: path.join(__dirname, srcDir + 'background.ts'), - content_script: path.join(__dirname, srcDir + 'content.ts') + content: path.join(__dirname, srcDir + 'content.ts') }, output: { path: path.join(__dirname, '../dist/js'), From 4907be7738102f30f1c893c5784c31231f83fc9b Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sat, 1 Feb 2020 19:25:40 -0500 Subject: [PATCH 15/30] Fixed maps not being handled properly --- src/SB.ts | 6 +++--- src/popup.ts | 53 ++++++++++++++++++++++++++-------------------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/src/SB.ts b/src/SB.ts index 2cbb9266..019ef8e1 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -14,7 +14,7 @@ class SBMap extends Map { // Import all entries if they were given if (entries !== undefined) { for (const item of entries) { - this.set(entries[0], entries[1]) + this.set(item[0], item[1]) } } } @@ -142,7 +142,7 @@ function decodeStoredItem(data) { } } -function configProxy(): void { +function configProxy(): any { chrome.storage.onChanged.addListener((changes, namespace) => { for (const key in changes) { SB.localConfig[key] = decodeStoredItem(changes[key].newValue); @@ -179,7 +179,7 @@ function configProxy(): void { }; - return new Proxy({handler}, handler); + return new Proxy({}, handler); } function fetchConfig() { diff --git a/src/popup.ts b/src/popup.ts index f477c15d..e07650a8 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -323,17 +323,17 @@ async function runThePopup(messageListener?: MessageListener) { } function sendSponsorStartMessage() { - //the content script will get the message if a YouTube page is open - messageHandler.query({ - active: true, - currentWindow: true - }, tabs => { - messageHandler.sendMessage( - tabs[0].id, - {from: 'popup', message: 'sponsorStart'}, - startSponsorCallback - ); - }); + //the content script will get the message if a YouTube page is open + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {from: 'popup', message: 'sponsorStart'}, + startSponsorCallback + ); + }); } function startSponsorCallback(response) { @@ -347,18 +347,19 @@ async function runThePopup(messageListener?: MessageListener) { let localStartTimeChosen = startTimeChosen; SB.config.sponsorTimes.set(currentVideoID, sponsorTimes); - //send a message to the client script - if (localStartTimeChosen) { - messageHandler.query({ - active: true, - currentWindow: true - }, tabs => { - messageHandler.sendMessage( - tabs[0].id, - {message: "sponsorDataChanged"} - ); - }); - } + + //send a message to the client script + if (localStartTimeChosen) { + messageHandler.query({ + active: true, + currentWindow: true + }, tabs => { + messageHandler.sendMessage( + tabs[0].id, + {message: "sponsorDataChanged"} + ); + }); + } updateStartTimeChosen(); @@ -999,7 +1000,7 @@ async function runThePopup(messageListener?: MessageListener) { PageElements.downloadedSponsorMessageTimes.style.fontWeight = "bold"; //save this - PageElements.config.whitelistedChannels = whitelistedChannels; + SB.config.whitelistedChannels = whitelistedChannels; //send a message to the client messageHandler.query({ @@ -1046,7 +1047,7 @@ async function runThePopup(messageListener?: MessageListener) { PageElements.downloadedSponsorMessageTimes.style.fontWeight = "unset"; //save this - PageElements.config.whitelistedChannels = whitelistedChannels; + SB.config.whitelistedChannels = whitelistedChannels; //send a message to the client messageHandler.query({ @@ -1069,7 +1070,7 @@ async function runThePopup(messageListener?: MessageListener) { * Should skipping be disabled (visuals stay) */ function toggleSkipping(disabled) { - PageElements.config.disableSkipping = disabled; + SB.config.disableSkipping = disabled; let hiddenButton = PageElements.disableSkipping; let shownButton = PageElements.enableSkipping; From bb9de357226fe456d80fbb220b12e42c3448f865 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Sun, 2 Feb 2020 18:26:43 -0500 Subject: [PATCH 16/30] Fixed naming issue --- src/SB.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/SB.ts b/src/SB.ts index 019ef8e1..8a581068 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -61,50 +61,50 @@ var SB: SBObject = { // Saves the changes to chrome.storage in json form class MapIO { id: string; - SBMap: SBMap; + map: SBMap; constructor(id) { // The name of the item in the array this.id = id; // A local copy of the SBMap (SB.config.SBMapname.SBMap) - this.SBMap = SB.localConfig[this.id]; + this.map = SB.localConfig[this.id]; } set(key, value) { // Proxy to SBMap - this.SBMap.set(key, value); + this.map.set(key, value); // Store updated SBMap locally chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.SBMap) + [this.id]: encodeStoredItem(this.map) }); - return this.SBMap; + return this.map; } get(key) { - return this.SBMap.get(key); + return this.map.get(key); } has(key) { - return this.SBMap.has(key); + return this.map.has(key); } size() { - return this.SBMap.size; + return this.map.size; } delete(key) { // Proxy to SBMap - this.SBMap.delete(key); + this.map.delete(key); // Store updated SBMap locally chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.SBMap) + [this.id]: encodeStoredItem(this.map) }); } clear() { - this.SBMap.clear(); + this.map.clear(); chrome.storage.sync.set({ - [this.id]: encodeStoredItem(this.SBMap) + [this.id]: encodeStoredItem(this.map) }); } } From 5bb5dae20ef0f6d03842f4b439420726880579e3 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 14:11:52 -0500 Subject: [PATCH 17/30] Added config types and added back handler to proxy --- src/SB.ts | 61 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/SB.ts b/src/SB.ts index 8a581068..85da4d6c 100644 --- a/src/SB.ts +++ b/src/SB.ts @@ -1,6 +1,27 @@ +interface SBConfig { + sponsorTimes: SBMap, + startSponsorKeybind: string, + submitKeybind: string, + minutesSaved: number, + skipCount: number, + sponsorTimesContributed: number, + disableSkipping: boolean, + disableAutoSkip: boolean, + trackViewCount: boolean, + dontShowNotice: boolean, + hideVideoPlayerControls: boolean, + hideInfoButtonPlayerControls: boolean, + hideDeleteButtonPlayerControls: boolean, + hideDiscordLaunches: number, + hideDiscordLink: boolean, + invidiousInstances: string[], + invidiousUpdateInfoShowCount: number, + autoUpvote: boolean +} + interface SBObject { configListeners: Array; - defaults: any; + defaults: SBConfig; localConfig: any; config: any; } @@ -32,24 +53,24 @@ var SB: SBObject = { */ configListeners: [], defaults: { - "sponsorTimes": new SBMap(), - "startSponsorKeybind": ";", - "submitKeybind": "'", - "minutesSaved": 0, - "skipCount": 0, - "sponsorTimesContributed": 0, - "disableSkipping": false, - "disableAutoSkip": false, - "trackViewCount": true, - "dontShowNotice": false, - "hideVideoPlayerControls": false, - "hideInfoButtonPlayerControls": false, - "hideDeleteButtonPlayerControls": false, - "hideDiscordLaunches": 0, - "hideDiscordLink": false, - "invidiousInstances": ["invidio.us", "invidiou.sh", "invidious.snopyta.org"], - "invidiousUpdateInfoShowCount": 0, - "autoUpvote": true + sponsorTimes: new SBMap(), + startSponsorKeybind: ";", + submitKeybind: "'", + minutesSaved: 0, + skipCount: 0, + sponsorTimesContributed: 0, + disableSkipping: false, + disableAutoSkip: false, + trackViewCount: true, + dontShowNotice: false, + hideVideoPlayerControls: false, + hideInfoButtonPlayerControls: false, + hideDeleteButtonPlayerControls: false, + hideDiscordLaunches: 0, + hideDiscordLink: false, + invidiousInstances: ["invidio.us", "invidiou.sh", "invidious.snopyta.org"], + invidiousUpdateInfoShowCount: 0, + autoUpvote: true }, localConfig: null, config: null @@ -179,7 +200,7 @@ function configProxy(): any { }; - return new Proxy({}, handler); + return new Proxy({handler}, handler); } function fetchConfig() { From b0a23a5c4e8660b619d2d433e0e9fe17ba53b98a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 22:34:43 -0500 Subject: [PATCH 18/30] Converted options page to TypeScript --- public/options/options.html | 5 +- src/background.ts | 2 +- src/content.ts | 8 +-- public/options/options.js => src/options.ts | 78 +++++++++++---------- src/utils.ts | 13 ++-- webpack/webpack.common.js | 3 +- 6 files changed, 59 insertions(+), 50 deletions(-) rename public/options/options.js => src/options.ts (79%) diff --git a/public/options/options.html b/public/options/options.html index 19354139..0e7c155f 100644 --- a/public/options/options.html +++ b/public/options/options.html @@ -6,9 +6,8 @@ - - - + + diff --git a/src/background.ts b/src/background.ts index e1c4f1ac..967f221a 100644 --- a/src/background.ts +++ b/src/background.ts @@ -125,7 +125,7 @@ function unregisterFirefoxContentScript(id: string) { function getSponsorTimes(videoID, callback) { let sponsorTimes = []; let sponsorTimesStorage = SB.config.sponsorTimes.get(videoID); - + if (sponsorTimesStorage != undefined && sponsorTimesStorage.length > 0) { sponsorTimes = sponsorTimesStorage; } diff --git a/src/content.ts b/src/content.ts index 8d92bef5..833fcc8d 100644 --- a/src/content.ts +++ b/src/content.ts @@ -49,8 +49,8 @@ var previewBar = null; //the player controls on the YouTube player var controls = null; -// Direct Links -videoIDChange(getYouTubeVideoID(document.URL)); +// Direct Links after the config is loaded +utils.wait(() => SB.config !== null).then(() => videoIDChange(getYouTubeVideoID(document.URL))); //the last time looked at (used to see if this time is in the interval) var lastTime = -1; @@ -417,7 +417,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { function getYouTubeVideoID(url: string) { // For YouTube TV support if(url.startsWith("https://www.youtube.com/tv#/")) url = url.replace("#", ""); - + //Attempt to parse url let urlObject = null; try { @@ -433,7 +433,7 @@ function getYouTubeVideoID(url: string) { } else if (!["www.youtube.com", "www.youtube-nocookie.com"].includes(urlObject.host)) { if (!SB.config) { // Call this later, in case this is an Invidious tab - this.wait(() => SB.config !== null).then(() => this.videoIDChange(this.getYouTubeVideoID(url))); + utils.wait(() => SB.config !== null).then(() => videoIDChange(getYouTubeVideoID(url))); } return false diff --git a/public/options/options.js b/src/options.ts similarity index 79% rename from public/options/options.js rename to src/options.ts index 2feeb17a..3cf1acd5 100644 --- a/public/options/options.js +++ b/src/options.ts @@ -1,13 +1,18 @@ +import SB from "./SB"; + +import Utils from "./utils"; +var utils = new Utils(); + window.addEventListener('DOMContentLoaded', init); async function init() { - localizeHtmlPage(); + utils.localizeHtmlPage(); if (!SB.configListeners.includes(optionsConfigUpdateListener)) { SB.configListeners.push(optionsConfigUpdateListener); } - await wait(() => SB.config !== null); + await utils.wait(() => SB.config !== null); // Set all of the toggle options to the correct option let optionsContainer = document.getElementById("options"); @@ -51,23 +56,23 @@ async function init() { break; case "text-change": let button = optionsElements[i].querySelector(".trigger-button"); - button.addEventListener("click", () => activateTextChange(optionsElements[i])); + button.addEventListener("click", () => activateTextChange( optionsElements[i])); let textChangeOption = optionsElements[i].getAttribute("sync-option"); // See if anything extra must be done switch (textChangeOption) { case "invidiousInstances": - invidiousInstanceAddInit(optionsElements[i], textChangeOption); + invidiousInstanceAddInit( optionsElements[i], textChangeOption); } break; case "keybind-change": let keybindButton = optionsElements[i].querySelector(".trigger-button"); - keybindButton.addEventListener("click", () => activateKeybindChange(optionsElements[i])); + keybindButton.addEventListener("click", () => activateKeybindChange( optionsElements[i])); break; case "display": - updateDisplayElement(optionsElements[i]) + updateDisplayElement( optionsElements[i]) } } @@ -87,7 +92,7 @@ function optionsConfigUpdateListener(changes) { for (let i = 0; i < optionsElements.length; i++) { switch (optionsElements[i].getAttribute("option-type")) { case "display": - updateDisplayElement(optionsElements[i]) + updateDisplayElement( optionsElements[i]) } } } @@ -95,9 +100,9 @@ function optionsConfigUpdateListener(changes) { /** * Will set display elements to the proper text * - * @param {HTMLElement} element + * @param element */ -function updateDisplayElement(element) { +function updateDisplayElement(element: HTMLElement) { let displayOption = element.getAttribute("sync-option") let displayText = SB.config[displayOption]; element.innerText = displayText; @@ -113,11 +118,11 @@ function updateDisplayElement(element) { /** * Initializes the option to add Invidious instances * - * @param {HTMLElement} element - * @param {String} option + * @param element + * @param option */ -function invidiousInstanceAddInit(element, option) { - let textBox = element.querySelector(".option-text-box"); +function invidiousInstanceAddInit(element: HTMLElement, option: string) { + let textBox = element.querySelector(".option-text-box"); let button = element.querySelector(".trigger-button"); let setButton = element.querySelector(".text-change-set"); @@ -133,7 +138,7 @@ function invidiousInstanceAddInit(element, option) { SB.config[option] = instanceList; - let checkbox = document.querySelector("#support-invidious input"); + let checkbox = document.querySelector("#support-invidious input"); checkbox.checked = true; invidiousOnClick(checkbox, "supportInvidious"); @@ -158,15 +163,15 @@ function invidiousInstanceAddInit(element, option) { /** * Run when the invidious button is being initialized * - * @param {HTMLElement} checkbox - * @param {string} option + * @param checkbox + * @param option */ -function invidiousInit(checkbox, option) { +function invidiousInit(checkbox: HTMLInputElement, option: string) { let permissions = ["declarativeContent"]; - if (isFirefox()) permissions = []; + if (utils.isFirefox()) permissions = []; chrome.permissions.contains({ - origins: getInvidiousInstancesRegex(), + origins: utils.getInvidiousInstancesRegex(), permissions: permissions }, function (result) { if (result != checkbox.checked) { @@ -180,28 +185,28 @@ function invidiousInit(checkbox, option) { /** * Run whenever the invidious checkbox is clicked * - * @param {HTMLElement} checkbox - * @param {string} option + * @param checkbox + * @param option */ -function invidiousOnClick(checkbox, option) { +function invidiousOnClick(checkbox: HTMLInputElement, option: string) { if (checkbox.checked) { - setupExtraSitePermissions(function (granted) { + utils.setupExtraSitePermissions(function (granted) { if (!granted) { SB.config[option] = false; checkbox.checked = false; } }); } else { - removeExtraSiteRegistration(); + utils.removeExtraSiteRegistration(); } } /** * Will trigger the container to ask the user for a keybind. * - * @param {HTMLElement} element + * @param element */ -function activateKeybindChange(element) { +function activateKeybindChange(element: HTMLElement) { let button = element.querySelector(".trigger-button"); if (button.classList.contains("disabled")) return; @@ -211,11 +216,11 @@ function activateKeybindChange(element) { let currentlySet = SB.config[option] !== null ? chrome.i18n.getMessage("keybindCurrentlySet") : ""; - let status = element.querySelector(".option-hidden-section > .keybind-status"); + let status = element.querySelector(".option-hidden-section > .keybind-status"); status.innerText = chrome.i18n.getMessage("keybindDescription") + currentlySet; if (SB.config[option] !== null) { - let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key"); + let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key"); statusKey.innerText = SB.config[option]; } @@ -227,11 +232,10 @@ function activateKeybindChange(element) { /** * Called when a key is pressed in an activiated keybind change option. * - * @param {HTMLElement} element - * @param {KeyboardEvent} e + * @param element + * @param e */ -function keybindKeyPressed(element, e) { - e = e || window.event; +function keybindKeyPressed(element: HTMLElement, e: KeyboardEvent) { var key = e.key; let button = element.querySelector(".trigger-button"); @@ -247,10 +251,10 @@ function keybindKeyPressed(element, e) { SB.config[option] = key; - let status = element.querySelector(".option-hidden-section > .keybind-status"); + let status = element.querySelector(".option-hidden-section > .keybind-status"); status.innerText = chrome.i18n.getMessage("keybindDescriptionComplete"); - let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key"); + let statusKey = element.querySelector(".option-hidden-section > .keybind-status-key"); statusKey.innerText = key; button.classList.remove("disabled"); @@ -259,15 +263,15 @@ function keybindKeyPressed(element, e) { /** * Will trigger the textbox to appear to be able to change an option's text. * - * @param {HTMLElement} element + * @param element */ -function activateTextChange(element) { +function activateTextChange(element: HTMLElement) { let button = element.querySelector(".trigger-button"); if (button.classList.contains("disabled")) return; button.classList.add("disabled"); - let textBox = element.querySelector(".option-text-box"); + let textBox = element.querySelector(".option-text-box"); let option = element.getAttribute("sync-option"); // See if anything extra must be done diff --git a/src/utils.ts b/src/utils.ts index 8f91dc21..e031c8f0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -42,15 +42,17 @@ class Utils { // Request permission let permissions = ["declarativeContent"]; if (this.isFirefox()) permissions = []; + + let self = this; chrome.permissions.request({ origins: this.getInvidiousInstancesRegex(), permissions: permissions }, async function (granted) { if (granted) { - this.setupExtraSiteContentScripts(); + self.setupExtraSiteContentScripts(); } else { - this.removeExtraSiteRegistration(); + self.removeExtraSiteRegistration(); } callback(granted); @@ -66,7 +68,8 @@ class Utils { */ setupExtraSiteContentScripts() { let js = [ - "content.js" + "./js/vendor.js", + "./js/content.js" ]; let css = [ "content.css", @@ -74,6 +77,8 @@ class Utils { "popup.css" ]; + let self = this; + if (this.isFirefox()) { let firefoxJS = []; for (const file of js) { @@ -101,7 +106,7 @@ class Utils { } else { chrome.declarativeContent.onPageChanged.removeRules(["invidious"], function() { let conditions = []; - for (const regex of this.getInvidiousInstancesRegex()) { + for (const regex of self.getInvidiousInstancesRegex()) { conditions.push(new chrome.declarativeContent.PageStateMatcher({ pageUrl: { urlMatches: regex } })); diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 55488488..70ea347a 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -7,7 +7,8 @@ module.exports = { entry: { popup: path.join(__dirname, srcDir + 'popup.ts'), background: path.join(__dirname, srcDir + 'background.ts'), - content: path.join(__dirname, srcDir + 'content.ts') + content: path.join(__dirname, srcDir + 'content.ts'), + options: path.join(__dirname, srcDir + 'options.ts') }, output: { path: path.join(__dirname, '../dist/js'), From e3be54cbe73c3e7836828c95a2a240807c1ea30a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:10:04 -0500 Subject: [PATCH 19/30] Updated build commands --- README.md | 2 +- package-lock.json | 210 ++++++++++++++++++++++++++++++++-------------- package.json | 12 ++- 3 files changed, 159 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index cc70e1e0..aea7741a 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ There are also other build scripts available. Install `npm`, then run `npm insta ## Developing with a clean profile -Run `npm run dev` to run the extension using a clean browser profile with hot reloading [(by default Firefox)](https://hacks.mozilla.org/2019/10/developing-cross-browser-extensions-with-web-ext-3-2-0/). This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands). +Run `npm run dev` to run the extension using a clean browser profile with hot reloading. Use `npm run dev:firefox` for Firefox. This uses [`web-ext run`](https://extensionworkshop.com/documentation/develop/web-ext-command-reference/#commands). ## Packing diff --git a/package-lock.json b/package-lock.json index 821e2bb6..1521214b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1100,7 +1100,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -2151,8 +2150,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "capture-exit": { "version": "2.0.0", @@ -2173,7 +2171,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2923,7 +2920,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -2931,8 +2927,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "colors": { "version": "0.5.1", @@ -3094,6 +3089,118 @@ } } }, + "concurrently": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.1.0.tgz", + "integrity": "sha512-9ViZMu3OOCID3rBgU31mjBftro2chOop0G2u1olq1OuwRBVRw/GxHTg80TVJBUTJfoswMmEUeuOg1g1yu1X2dA==", + "requires": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^6.1.0", + "tree-kill": "^1.2.2", + "yargs": "^13.3.0" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "configstore": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.0.tgz", @@ -3422,6 +3529,11 @@ "whatwg-url": "^7.0.0" } }, + "date-fns": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.9.0.tgz", + "integrity": "sha512-khbFLu/MlzLjEzy9Gh8oY1hNt/Dvxw3J6Rbc28cVoYWQaC1S3YI4xwkF9ZWcjDLscbZlY9hISMr66RFzZagLsA==" + }, "debounce": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz", @@ -3834,7 +3946,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -3973,8 +4084,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "1.13.0", @@ -4454,7 +4564,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -4746,8 +4855,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-stream": { "version": "4.1.0", @@ -4977,8 +5085,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.1", @@ -5067,8 +5174,7 @@ "hosted-git-info": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", - "dev": true + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" }, "html-encoding-sniffer": { "version": "1.0.2", @@ -5268,8 +5374,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-binary-path": { "version": "1.0.1", @@ -6916,8 +7021,7 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-schema": { "version": "0.2.3", @@ -7241,7 +7345,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -7250,8 +7353,7 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash.includes": { "version": "4.3.0", @@ -7868,7 +7970,6 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -7879,8 +7980,7 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -8134,7 +8234,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -8143,7 +8242,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -8157,8 +8255,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "pako": { "version": "1.0.10", @@ -8236,7 +8333,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, "requires": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -8278,8 +8374,7 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "path-is-absolute": { "version": "1.0.1", @@ -8302,8 +8397,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, "path-type": { "version": "3.0.0", @@ -8929,14 +9023,12 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "require-uncached": { "version": "1.0.3", @@ -8960,7 +9052,6 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", - "dev": true, "requires": { "path-parse": "^1.0.6" } @@ -9085,7 +9176,6 @@ "version": "6.5.4", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", - "dev": true, "requires": { "tslib": "^1.9.0" } @@ -9183,8 +9273,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -9573,6 +9662,11 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=" + }, "spawn-sync": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", @@ -9587,7 +9681,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -9596,14 +9689,12 @@ "spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -9612,8 +9703,7 @@ "spdx-license-ids": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" }, "split": { "version": "0.3.3", @@ -9949,7 +10039,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" }, @@ -9957,8 +10046,7 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" } } }, @@ -10003,7 +10091,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -10365,6 +10452,11 @@ "integrity": "sha1-0EsigOTHkqWBVCnve4tgxkyczDQ=", "dev": true }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" + }, "ts-jest": { "version": "24.3.0", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-24.3.0.tgz", @@ -10482,8 +10574,7 @@ "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", - "dev": true + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "tty-browserify": { "version": "0.0.0", @@ -10774,7 +10865,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -12421,8 +12511,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "widest-line": { "version": "3.1.0", @@ -12580,8 +12669,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "3.1.1", diff --git a/package.json b/package.json index 5780b5b2..3d7bb426 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,9 @@ "version": "1.0.0", "description": "", "main": "background.js", - "dependencies": {}, + "dependencies": { + "concurrently": "^5.1.0" + }, "devDependencies": { "web-ext": "^4.0.0", "@types/chrome": "0.0.91", @@ -21,8 +23,12 @@ "webpack-merge": "~4.2.2" }, "scripts": { - "dev": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm", - "watch": "webpack --config webpack/webpack.dev.js --watch", + "web-run": "npm run web-run:chrome", + "web-run:firefox": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm", + "web-run:chrome": "cd dist && web-ext run --start-url https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm -t chromium", + "build:watch": "webpack --config webpack/webpack.dev.js --watch", + "dev": "concurrently \"npm run web-run\" \"npm run build:watch\"", + "dev:firefox": "concurrently \"npm run web-run:firefox\" \"npm run build:watch\"", "build": "webpack --config webpack/webpack.prod.js", "clean": "rimraf dist", "test": "npx jest" From 7404e0831b74649a933f765e2a60e7bc15868871 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:11:01 -0500 Subject: [PATCH 20/30] Updated CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f8758a2..04a246be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/upload-artifact@v1 with: name: Chrome Extension - path: web-ext-artifacts + path: dist # Create Firefox artifacts - name: Move manifest @@ -34,5 +34,5 @@ jobs: - uses: actions/upload-artifact@v1 with: name: Firefox Extension - path: web-ext-artifacts + path: dist From 7f22687c248bc2fce288519e699439708c1383fc Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:13:40 -0500 Subject: [PATCH 21/30] Updated CI to use config.json --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04a246be..bc7a3123 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: - uses: actions/setup-node@v1 - run: npm install - name: Copy configuration - run: cp config.js.example config.js + run: cp config.json.example config.json # Create Chrome artifacts - name: Create Chrome artifacts From 0a0d4d3e0f5c436e7fe41a61b2d5c824fa323c60 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:16:05 -0500 Subject: [PATCH 22/30] Fixed config.json.example naming --- config.json.example.json => config.json.example | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config.json.example.json => config.json.example (100%) diff --git a/config.json.example.json b/config.json.example similarity index 100% rename from config.json.example.json rename to config.json.example From 1eaf4f44c23b36704f46700fac301e765c1351d9 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:20:57 -0500 Subject: [PATCH 23/30] Fixed incorrect syntax in example config --- config.json.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json.example b/config.json.example index 34c3d2a6..2f7f0520 100644 --- a/config.json.example +++ b/config.json.example @@ -1,4 +1,4 @@ { "serverAddress": "https://sponsor.ajay.app", - "serverAddressComment": "This specifies the default SponsorBlock server to conect to": + "serverAddressComment": "This specifies the default SponsorBlock server to conect to" } \ No newline at end of file From 26f3560e97abe3e5ec5b71f918051c52cf67229d Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:23:26 -0500 Subject: [PATCH 24/30] CI uses new manifest location --- .github/workflows/ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc7a3123..3e7497af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,11 +26,9 @@ jobs: # Create Firefox artifacts - name: Move manifest - run: mv manifest.json manifest.json.original + run: mv ./dist/manifest.json ./dist/manifest.json.original - name: Combine manifest for Firefox run: jq -s '.[0] * .[1]' manifest.json.original firefox_manifest-extra.json > manifest.json - - name: Create Firefox artifacts - run: npm run build - uses: actions/upload-artifact@v1 with: name: Firefox Extension From db7ac02c7d95a8e02b2a93d1985a5ae3412d64b2 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:25:50 -0500 Subject: [PATCH 25/30] Fix CI filepath --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e7497af..4a1ed900 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: - name: Move manifest run: mv ./dist/manifest.json ./dist/manifest.json.original - name: Combine manifest for Firefox - run: jq -s '.[0] * .[1]' manifest.json.original firefox_manifest-extra.json > manifest.json + run: jq -s '.[0] * .[1]' ./dist/manifest.json.original ./dist/firefox_manifest-extra.json > manifest.json - uses: actions/upload-artifact@v1 with: name: Firefox Extension From 4049d2d1ab68c59eaf1a0e24efd03efdc24dd6c3 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:39:41 -0500 Subject: [PATCH 26/30] Fixed keybind not working --- src/content.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/content.ts b/src/content.ts index 833fcc8d..015a4ffb 100644 --- a/src/content.ts +++ b/src/content.ts @@ -188,7 +188,7 @@ if (!SB.configListeners.includes(contentConfigUpdateListener)) { } //check for hotkey pressed -document.onkeydown = async function(e){ +document.onkeydown = function(e: KeyboardEvent){ var key = e.key; let video = document.getElementById("movie_player"); @@ -199,10 +199,10 @@ document.onkeydown = async function(e){ //is the video in focus, otherwise they could be typing a comment if (document.activeElement === video) { - if(key == startSponsorKey.startSponsorKeybind){ + if(key == startSponsorKey){ //semicolon startSponsorClicked(); - } else if (key == submitKey.submitKeybind) { + } else if (key == submitKey) { //single quote submitSponsorTimes(); } From 13cef5ff149af191c9b1cf38f21bbfa255fb416a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Mon, 3 Feb 2020 23:40:44 -0500 Subject: [PATCH 27/30] Remove invidious message --- src/content.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/content.ts b/src/content.ts index 015a4ffb..1d035630 100644 --- a/src/content.ts +++ b/src/content.ts @@ -621,13 +621,6 @@ function skipToTime(v, index, sponsorTimes, openNotice) { if (!SB.config.dontShowNotice) { let skipNotice = new SkipNotice(this, currentUUID, SB.config.disableAutoSkip, skipNoticeContentContainer); - //TODO: Remove this when Invidious support is old - if (SB.config.invidiousUpdateInfoShowCount < 5) { - skipNotice.addNoticeInfoMessage(chrome.i18n.getMessage("invidiousInfo1"), chrome.i18n.getMessage("invidiousInfo2")); - - SB.config.invidiousUpdateInfoShowCount += 1; - } - //auto-upvote this sponsor if (SB.config.trackViewCount && !SB.config.disableAutoSkip && SB.config.autoUpvote) { vote(1, currentUUID, null); From 3582f45fd8af4fcb5708c3c5151869ad3bba212a Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 4 Feb 2020 00:05:03 -0500 Subject: [PATCH 28/30] Fixed skip notice references fixing manual skip notices. --- src/background.ts | 4 ++-- src/content.ts | 8 ++++---- src/js-components/skipNotice.ts | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/background.ts b/src/background.ts index 967f221a..92e1ee50 100644 --- a/src/background.ts +++ b/src/background.ts @@ -42,8 +42,8 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { case "getSponsorTimes": getSponsorTimes(request.videoID, function(sponsorTimes) { callback({ - sponsorTimes: sponsorTimes - }) + sponsorTimes + }); }); //this allows the callback to be called later diff --git a/src/content.ts b/src/content.ts index 1d035630..79ef2da1 100644 --- a/src/content.ts +++ b/src/content.ts @@ -76,7 +76,7 @@ var sponsorTimesSubmitting = []; var popupInitialised = false; // Contains all of the functions and variables needed by the skip notice -var skipNoticeContentContainer = { +var skipNoticeContentContainer = () => ({ vote, dontShowNoticeAgain, unskipSponsorTime, @@ -86,7 +86,7 @@ var skipNoticeContentContainer = { reskipSponsorTime, hiddenSponsorTimes, updatePreviewBar -}; +}); //get messages from the background script and the popup chrome.runtime.onMessage.addListener(messageListener); @@ -573,12 +573,12 @@ function sponsorCheck() { } //don't keep track until they are loaded in - if (sponsorTimes != null || sponsorTimesSubmitting.length > 0) { + if (sponsorTimes !== null || sponsorTimesSubmitting.length > 0) { lastTime = v.currentTime; } } -function checkSponsorTime(sponsorTimes, index, openNotice) { +function checkSponsorTime(sponsorTimes, index, openNotice): boolean { //this means part of the video was just skipped if (Math.abs(v.currentTime - lastTime) > 1 && lastTime != -1) { //make lastTime as if the video was playing normally diff --git a/src/js-components/skipNotice.ts b/src/js-components/skipNotice.ts index fd675d6e..b3e9c944 100644 --- a/src/js-components/skipNotice.ts +++ b/src/js-components/skipNotice.ts @@ -8,7 +8,7 @@ class SkipNotice { UUID: string; manualSkip: boolean; // Contains functions and variables from the content script needed by the skip notice - contentContainer: any; + contentContainer: () => any; maxCountdownTime: () => number; countdownTime: any; @@ -128,7 +128,7 @@ class SkipNotice { downvoteButton.id = "sponsorTimesDownvoteButtonsContainer" + this.idSuffix; downvoteButton.className = "sponsorSkipObject voteButton"; downvoteButton.src = chrome.extension.getURL("icons/report.png"); - downvoteButton.addEventListener("click", () => this.contentContainer.vote(0, this.UUID, this)); + downvoteButton.addEventListener("click", () => this.contentContainer().vote(0, this.UUID, this)); downvoteButton.setAttribute("title", chrome.i18n.getMessage("reportButtonInfo")); //add downvote and report text to container @@ -156,7 +156,7 @@ class SkipNotice { let dontShowAgainButton = document.createElement("button"); dontShowAgainButton.innerText = chrome.i18n.getMessage("Hide"); dontShowAgainButton.className = "sponsorSkipObject sponsorSkipNoticeButton sponsorSkipNoticeRightButton"; - dontShowAgainButton.addEventListener("click", this.contentContainer.dontShowNoticeAgain); + dontShowAgainButton.addEventListener("click", this.contentContainer().dontShowNoticeAgain); // Don't let them hide it if manually skipping if (!this.manualSkip) { @@ -255,7 +255,7 @@ class SkipNotice { } unskip() { - this.contentContainer.unskipSponsorTime(this.UUID); + this.contentContainer().unskipSponsorTime(this.UUID); this.unskippedMode(chrome.i18n.getMessage("reskip")); } @@ -271,8 +271,8 @@ class SkipNotice { //change max duration to however much of the sponsor is left this.maxCountdownTime = function() { - let sponsorTime = this.contentContainer.sponsorTimes[this.contentContainer.UUIDs.indexOf(this.UUID)]; - let duration = Math.round(sponsorTime[1] - this.contentContainer.v.currentTime); + let sponsorTime = this.contentContainer().sponsorTimes[this.contentContainer().UUIDs.indexOf(this.UUID)]; + let duration = Math.round(sponsorTime[1] - this.contentContainer().v.currentTime); return Math.max(duration, 4); }; @@ -282,7 +282,7 @@ class SkipNotice { } reskip() { - this.contentContainer.reskipSponsorTime(this.UUID); + this.contentContainer().reskipSponsorTime(this.UUID); //change reskip button to a unskip button let unskipButton = this.changeUnskipButton(chrome.i18n.getMessage("unskip")); @@ -300,7 +300,7 @@ class SkipNotice { if (this.manualSkip) { this.changeNoticeTitle(chrome.i18n.getMessage("noticeTitle")); - this.contentContainer.vote(1, this.UUID, this); + this.contentContainer().vote(1, this.UUID, this); } } @@ -324,14 +324,14 @@ class SkipNotice { //remove this sponsor from the sponsors looked up //find which one it is - for (let i = 0; i < this.contentContainer.sponsorTimes.length; i++) { - if (this.contentContainer.UUIDs[i] == this.UUID) { + for (let i = 0; i < this.contentContainer().sponsorTimes.length; i++) { + if (this.contentContainer().UUIDs[i] == this.UUID) { //this one is the one to hide //add this as a hidden sponsorTime - this.contentContainer.hiddenSponsorTimes.push(i); + this.contentContainer().hiddenSponsorTimes.push(i); - this.contentContainer.updatePreviewBar(); + this.contentContainer().updatePreviewBar(); break; } } From f6f416b89981d3efd099f26a08296ed93751bba4 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 4 Feb 2020 00:13:38 -0500 Subject: [PATCH 29/30] Fixed direct link channel whitelisting --- src/content.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/content.ts b/src/content.ts index 79ef2da1..ca8dcb29 100644 --- a/src/content.ts +++ b/src/content.ts @@ -328,11 +328,12 @@ function videoIDChange(id) { } } -function sponsorsLookup(id: string, channelIDPromise = null) { +function sponsorsLookup(id: string, channelIDPromise?) { + v = document.querySelector('video') // Youtube video player //there is no video here if (v == null) { - setTimeout(() => sponsorsLookup(id), 100); + setTimeout(() => sponsorsLookup(id, channelIDPromise), 100); return; } @@ -343,7 +344,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { v.addEventListener('durationchange', updatePreviewBar); } - if (channelIDPromise != null) { + if (channelIDPromise !== undefined) { if (channelIDPromise.isFulfilled) { whitelistCheck(); } else if (channelIDPromise.isRejected) { @@ -389,7 +390,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { //if less than 3 days old if ((Date.now() / 1000) - unixTimePublished < 259200) { //TODO lower when server becomes better - setTimeout(() => sponsorsLookup(id), 180000); + setTimeout(() => sponsorsLookup(id, channelIDPromise), 180000); } } }); @@ -400,7 +401,7 @@ function sponsorsLookup(id: string, channelIDPromise = null) { //TODO lower when server becomes better (back to 1 second) //some error occurred, try again in a second - setTimeout(() => sponsorsLookup(id), 10000); + setTimeout(() => sponsorsLookup(id, channelIDPromise), 10000); sponsorLookupRetries++; } From da364b49f01f4af913319f83d4adeef8a9312132 Mon Sep 17 00:00:00 2001 From: Ajay Ramachandran Date: Tue, 4 Feb 2020 00:16:46 -0500 Subject: [PATCH 30/30] Removed old config example --- config.js.example | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 config.js.example diff --git a/config.js.example b/config.js.example deleted file mode 100644 index 4bab5967..00000000 --- a/config.js.example +++ /dev/null @@ -1,3 +0,0 @@ -//this file is loaded along iwth content.js -//this file sets the server to connect to, and is gitignored -var serverAddress = "https://api.sponsor.ajay.app";