From 241313ba47232797a78661bd4859bfa0df3e3688 Mon Sep 17 00:00:00 2001 From: Ken Date: Wed, 11 Sep 2019 17:59:11 +0800 Subject: [PATCH 1/4] add: add 'favicon.ico' for web page. update: update web page title. Use `project name` + `build time` instead of 'Webpack Bundle Analyzer'. --- package-lock.json | 109 ++++++++++++++++++++++++++++++++++++++-------- package.json | 3 +- src/utils.js | 14 ++++++ src/viewer.js | 5 +++ views/favicon.ico | Bin 0 -> 8456 bytes views/viewer.ejs | 3 +- webpack.config.js | 9 ++++ 7 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 views/favicon.ico diff --git a/package-lock.json b/package-lock.json index bf353a80..3f122e74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2588,6 +2588,54 @@ "is-plain-object": "^2.0.1" } }, + "copy-webpack-plugin": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz", + "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==", + "dev": true, + "requires": { + "cacache": "^11.3.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.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^1.7.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "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" + } + }, + "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 + } + } + }, "core-js": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", @@ -3156,6 +3204,32 @@ "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" + }, + "dependencies": { + "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" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -6653,9 +6727,9 @@ } }, "mocha": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.2.tgz", - "integrity": "sha512-BgD2/RozoSC3uQK5R0isDcxjqaWw2n5HWdk8njYUyZf2NC79ErO5FtYVX52+rfqGoEgMfJf4fuG0IWh2TMzFoA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", + "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -6667,12 +6741,12 @@ "glob": "7.1.3", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.0", + "js-yaml": "3.13.1", "log-symbols": "2.2.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", "ms": "2.1.1", - "node-environment-flags": "1.0.4", + "node-environment-flags": "1.0.5", "object.assign": "4.1.0", "strip-json-comments": "2.0.1", "supports-color": "6.0.0", @@ -6753,16 +6827,6 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "js-yaml": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", - "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -7011,12 +7075,13 @@ } }, "node-environment-flags": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", - "integrity": "sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", "dev": true, "requires": { - "object.getownpropertydescriptors": "^2.0.3" + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" } }, "node-forge": { @@ -9219,6 +9284,12 @@ } } }, + "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", diff --git a/package.json b/package.json index 68af49f8..b9c4f75b 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "chai": "4.2.0", "chai-subset": "1.6.0", "classnames": "2.2.6", + "copy-webpack-plugin": "^5.0.4", "core-js": "2.6.5", "css-loader": "2.1.1", "cssnano": "4.1.10", @@ -77,7 +78,7 @@ "gulp-babel": "8.0.0", "mobx": "5.9.4", "mobx-preact": "3.0.0", - "mocha": "6.1.2", + "mocha": "^6.2.0", "nightmare": "3.0.1", "postcss-icss-values": "2.0.2", "postcss-loader": "3.0.0", diff --git a/src/utils.js b/src/utils.js index f826d9a5..c42f77b7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -32,3 +32,17 @@ function createAssetsFilter(excludePatterns) { return () => true; } } + +/** + * @desc get string of current time + * format: MM/dd/yyyy HH:mm + * */ +exports.getCurrentTime = function () { + const time = new Date(); + const year = time.getFullYear(); + const month = time.getMonth() + 1; + const day = time.getDate(); + const hour = time.getHours(); + const minute = time.getMinutes(); + return `${month}/${day}/${year} ${hour}:${minute}`; +}; diff --git a/src/viewer.js b/src/viewer.js index 2c6fd5fc..47c620a0 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -10,6 +10,7 @@ const opener = require('opener'); const mkdir = require('mkdirp'); const {bold} = require('chalk'); +const utils = require('./utils'); const Logger = require('./Logger'); const analyzer = require('./analyzer'); @@ -23,6 +24,8 @@ module.exports = { start: startServer }; +const title = `${process.env.npm_package_name || 'Webpack Bundle Analyzer'} [${utils.getCurrentTime()}]`; + async function startServer(bundleStats, opts) { const { port = 8888, @@ -52,6 +55,7 @@ async function startServer(bundleStats, opts) { app.use('/', (req, res) => { res.render('viewer', { mode: 'server', + title, get chartData() { return chartData }, defaultSizes, enableWebSocket: true, @@ -133,6 +137,7 @@ async function generateReport(bundleStats, opts) { `${projectRoot}/views/viewer.ejs`, { mode: 'static', + title, chartData, defaultSizes, enableWebSocket: false, diff --git a/views/favicon.ico b/views/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4a90d9aca83c5a65224ea447ead03475036d01a7 GIT binary patch literal 8456 zcmX9^2Uru&)4mWS(ve6JLhmX~dhZHI7X|4*1f+%Dqy`WnG-=YiAVqo!AT0<8h=MeM zMClR)LXj4!U;O@e&ptP^``q5_?#;~Y`yK#*i08ip1aJa>I01l>C?kyw9#B)TP!L6G z9c@jMf35$@bu!|`%BRxlpXO`wKpiwcayNpgkb7xA^#uS*=)VF2a`Tx1fHO-+Q_VCe zA74N|Z94d7$oiY}{bqS@NeQRvM5m_g9L?s$bRGM9BiY{c!ZKE9Y6clnO)FJ8&BS8v zgyGUS?(0#MpScA|NVwxE^EjCq7&6#MNlmvqPC|YXoP(<@>unY{cdoAT7v+$#yWQ2n z{+_*N{#y$_1EQ-<*2~h5d1wTZ`3(3)_~fBs$QuKX1}F!(?Qb=vnLiBG4Al!&cW83w zk%qFyNzF%$Ml`2n>m&-WbMJ6_@a94V=zDo-_>O1TX|Gp5O^w8>!L+Qj4|zV_@NFh5 zFm__tzrD{p5i6TTU~lX^ZdWs!K~mv3;(F<1ps%3^NMR83hYbAzn7!$7?Q+lxD`u5a zO%0j2Vyky}s(jaNyNJxL%cb#6Pz-Z^*dxLN{C;e4d_4cf;*ICo8wz1hf%{cou>)X! zi${dC~sS>s&Fo+))ICl*}qE?^@$k=GZA8NU@35XbMpQ%WvAIDJfFBk1*oWJq=| zx33U0&Qbj+$JzFh-QFL#Z(P5}?J635L{e!|Iubx4{&k5#g_i*RkHov?_#EMC#2-JP zP-ISrc7T*G@8KR@$GdyVDY(BGCtTLbXDa)fwoOwv~{1dVV(6AtX^^OLlcn z$S7l4g@e&55_6-F!54+H>LG>dg<7=!qNTC(a%UOY*9>Zdm6 z&MWe*aM9?-M86y&n;oqQYW)fwxWpW=#gAw*xTgHaWEw9+g`(`IQ;JK_Gu_k;F+rT# zv+WDu|Jt_Qn@Ih6NtW{h!Jdzdo6T?eTGHcC`Y~G;4OU+kx95O&R#N5&9v!a$?DBxO z4R=o!oI^?&`sSkz1G=BAn9lRYRW)2dN{D6d6aQ_t@{1IZ;2_yb8|K*LQ7H(nAIgaC zzlJ8G;ZoMedbq0dS5vnsAz~>Iq?diJ@8Bwrg;~&+RH(nIM<0Dp?!gtRb#p4$(vQKU zXb8RqUsbIMmKHQ9m&ZJq1}WOZsA<8)^zub=i%E2(ZSKHq?eZ1OH(cI9&2>-d2#r1 z!!n06wj{oCH8!u3JKGY#6#2 zOh@0Zr!>u9W^hbp*8sYn`o0A(@i@nMkOLbA+ zgDV8kONDyc>j2T$Riz}7oXgYCW$QP5o7}Az}~eY*m)Jo+7iif z>Ih}?`o=B^xFS2=u_#~DGi@{rX#gs<>b|3P(@M!M^9hoONRnd4dEHPm>=@-|&5HAN zQZa2{`ko;av)=Q*(zt+x83t@dO0?p`1dO9;#EgS^@R6Wmc5|KWdiaTgX3{NsbTMFL z_@fejLS6a_1~>Y^iqP%n8>XE_MFap-U}h>{GxY}M)1o9o4Ja=BTb{YUYe0O%K}017 zE}4d$)E6Z$J^&E9X3V9mJ1!|JlnA3GUy=~hNl*(_@f3g%l`S#()XUVUh@b%jJqRfB zU4%u7$D}l3j06byHPDh&WOliar&Z1VBH^-goq78VOef!KFa=s_7X|*45EoumQAUh` zfX@eSC1L0_K%NW`9PjQ)y1E`+-2<3X=4bBO710zM0tF<%oNuG(Dz3Jd0pxcbu%k8m zrQ5@&%_Jv<7z2Q{^B=L`AbvzLQKZsyJ%{889;F040018povr=~vEOgx079XH&l{*G z{RSe6t5!)@UeOf2fT==$XL)`r!B9lK$R%|gMk znJ-R$210KVRVD;#Zc zn>D~*r|`kI&IbR+QRA`iPs&M^DC7`)M0>kW7PcfSdG06fVUqJY{cg1VcX4`TgZ0`J zs&G&~+m`TFn0qmAr6LKTn?2j@E&4rGVYu$_tcBVhvO4toWU@`5Fi5>ylrQ^@=lNM~ zWxkOX3%Wi^B==(Sp$%62Rgb0hnlBq7Vx)X!))l)IyAAjR;|c=rnOS+qpo}H=`XC%Z zzo#B>gk{M6T1%ffdqg_M*!BDe2=-`%Y!4m!XGCB{?U$!S5#GGTId!TZAFx%sfce%L z=(&GE9J|ZbmRU5|F02V|`7W^Drux;ypU-!?kAGv_>WuM*w`dX+5Tkc~BFZ0T$y0C6 zKQH+8>vH=g%H!we^eb^g<==1^!NTOIdrO4aO#*n>g|N5mdS5*F(78VBmXuGKh3#EJ zQ9GE~^f#H})%k%zbnwh$vlkr^om=&R;SHmi!UxhcqT_|aJrN;&Bo?i5K<2p2UGh2= z-NCi9q!|g}RT?|{a#k_-4WpTn{b8Qhyus}~#~q6yyGr}r<0@C7#HYRm&owzdTwh5L zson@(^DiJ){|K?IbNy*CiXNR1-2v9kK7h{etaC3I9(zY*b)U4$2kvZ_vvrw?OuV9I z)ts%r4?zcy97K7_v4<0uO;4BIdfuU%y&(qC$OrFqw^(l!Js$|Y# znU-bagCz8r^jAKCpk3#i90%9m^2#PH8o9TI{`Jx45glwI+ydU*-&@jdwI7ThIDupeVW$J_OmmPX)$m(g{w5AT^=EnE?{Y0w8~6i7p`mPp6Ym1@yfPKW+ABmcj4a^ ztq$EU{RiU;<%`MDM}bCu=|_GwwJq^O(;zU0E6x4O`|MPu4$oWp60zh+-mA+fA_YV$DKrEuR@Jg zc335~2Yc?yX0WM3YsnH>q;%y4Sf+0;zvmiycb4KH)k7!oeC+1pLHwvF(@%|2(AttX zrt3xXBUbY)n_!pCgT13!+cuB!g209OJ(;vNGiA?G$7hZN!vJ8`Sqfp;(y@_g>7nDd zIP>02;iru42`zhmC7WmWQRYTC?A~1^hm~OF;ViHnVG8~Dyv=1yP5HmuRMkd_YBZYiax--qX1Uti!`H7^!hT+%nfA2NzEF7l8< z&|MpZ@BU^*%2i{1po=rhwiu>l-y+^nF@0|3fI7$Le6p|E(BRx8^H!g7KLdw%`g!Z2 zz2O(9$XzqN(6qh7DFa_uh^V5@;B%(3lZi{x;gW8=W#a5G66=cb9mf+CY_3wfR+|1d!cxPB7(qk*sQRuz9viEmN;_O0*>m~$UGCTQpwq}SU zs0A6^=_50X`MWc{;h-x=gIjY^f>DkluZ7RA2n{-4!V@_o-~A6ubLX1@5)uZtu1`9 ze#_VrLs?gl?xw0INQ3@$$hSLDA%!EzVO{aLQd%kp1gIAGg8bo|=}+L%d64^ek2pW6 z%)wY0USn?*)}#6PxCi0nxul0X+t65!2j2yoq;pDpZ{3UQ8eTwG7(W9mMK7{kd{Lg9 z2Rihc)$Gt>vX%77r1q27HBOKQ{Z1~CA^WFUz<`omFugnw|uFa8k&sMCU?vC7}Y&gAz`1jQnJl!!^vfHI;>H8_Ccaj}m!WkiN$ z9PIL&M(LKfx>b1pG)m5%RRMtqNe=v``uj6*5$+GaJZjMgf*lhW6)p|vH@M_FdrX)w z&xb3G$5t(LAn5vjqUFx!#cx8N;U2Ecm0JniJ>O3r)KSiI|LAgTjDEfiph&-^ywc&B z89+j7>%uPlXP;V&Mp#F-g}V=ST)1OC&Sp8Of54-#`9m{DP{iv_%yi$Xu1@H;Sg7lV zvfyzhoU5L1p$=sP6|3}@%@31p@f90GTG;itq-{W&jM#NlqDi+)&YS0J!>LbZE%O60 z2Ejhx_=o$;1$EN~(q=N~6BkP-4FGQ8^FDDd>DdDDXRkIsL{8IM)uz!l(22NwATSNR zJN*nB6|S5({F-~!mS*-eZ}vk^*jfBp&RR$#3k(pY_sMX=d=d?NjDtVJN(iL24d#oK^o6uxEWe&W4kGQ=quX5f;`*vV~GS{HEcEz2~uQZhYmgA{>9C32X;m zjrrJuI{TB#c$v+29kVRyKgseML^S0i%~IH}``fC)U1@^}2IX}^`=_;(U9JzKGJ?38 ztvGC7{9-V^;wO(z{6jtu@_O2$J0@CJCFokzV4CAc^q12}-x*r);Ibx%$r}aXV}zr& zXCu$2P_o4*(n$4ki2dowR+h7#bs*?A-@>2O!5{V|s2(q*R4QtOZ{)qt1v+aU)b(x- zQNXMi)DQ%W&ir1Tb7N&lP{08k$e_F`(~z>W6`fwFMmTtwX-I)^`y%so%O2!GpzbU$ z#wM(_ef)=rR$d;O#;(a891zuAVhVd^vzeQ(G<^Tr!!qoO)gEfol3OiqI;TNIJ6r2r zE=<)R-)l;0#zLGoM#a3#dc%if#OgnxS=ugQxL%E?o+DpiOnsMR(HkB%v9-V1fiFD6 zUtp1lc?T!e7D&u<;%!W**9gHFMBdOlr)ateC%;|7+kj zTVs*JnFOk9xV%%j(-$}g+IAxuAy4T)&QhpQ$NlQO?(=OPw(?te*rKILmHdD*PYQZ8 za$NjKPTdEf>ZNYaXK}y@S<_`OUVh7T`!4WcZvA8-N$cv_8`Q+mi@(3Jw7^3l^?zrB zwkICcUS_`T#!z$LbrVwTqG zgQdY?#JV$Ucf$UsH$~3-k4LjZMmn}&$3EB?mLYPTcNQ-5C^kd%UZQkAA4Tw{62KZ zI6n3jb#sr$rBIKVZP?>!4qIcd5_tp!7Ue7JS%yCD)eSFpq zCZwYJa1v(Ou5yK)Kc)T5ENW8UUgHz0Tiv2ho1M5dRWaKIZr5oS%zf1C^tGn0S6t1+ zM1TMLk=&aqjv(zHAjx~6X-J%e(--Cmw6J-D-OwT?{Jn2tdy92i87+(&XaBO!5nVk3 zI`q;m8C)^K`poX!y?cHm_qLHr$^l}h$I|MMgVB{W42IS1k@LpX|5(JlvR@#2WxI76 zm0CyQy~#hu=Ue7mGJNr>w*vd0n5Ol0z2W7CI3DtA!tWThTn;TU+|!j(UKw zzCGR)h+?Sty54(>lj=ct*^7hRKw#4MhTMG3y!PyC^R9>ea^SFj1tycn#o=~s>NLd( zs0kd8u*k%R$9J~UL+(&$Zq1_=s8C#=LgkaMoPM->e-9H3yw}JG0~8hv*-Ak#xLSX- z!rfE{20JNTeywkDhMtWI{W^_IB5qw*O}a{;lh5+4iJQhsq31l>_zJ?mNpR@kVvFm-@G&o=x>q%)que{lD&%l`m;U=K{8n^BMZQ)aT@KM*~#Ryr} zIGb{R3ej8j2W&cJ5jD^tsjrbKA1D0i_v=5vX;d$*yx>{9Ta+hie}sHHaU;xW;H5$R zEZsi2{TGQQvw>9;LrwEfwWGG?V+~{$vhRm{Vv@Y90W)W;t7>ZzDRqE zs)K&L-_yMEY6&1n#L>#|Rk1mzv*XGCTc&*yj()=873|GaZmQDYCtkR2y8k-41?k7Ep1s(QH*B5HeAetr zDYxw-ciOQRE160)%EvemL)>vI9Cdduo<`<_m)x}2RKJtoosd42RV)d8-yDnCo|N~M zUMVZ-8LH21Cc!!Q+Kozs+^t}uCUt4)qQS@8zo!E)Yxd`opYkQCYymq{#9O4a@mZ-1l_w(h)dsWY>fc?LUr=WGEOF8T5QQOL)&gfU-i+`v8X< zYd8%}*GBlD4$)zn;K_yq+}r=mOoU`L>CMbBpwy zD{FXupyFEQxQ@l2j+-LCixPCww$=Y-$T|Ve7x-UV52_}qu7qE;p!Ez2|7cJ(-6O8` zMkUdyoPzXrmYQi;aaSjN1}}3z%{?ZXD5&fr<&gD}qo##cfgy@5c?%V=wRZ4b8;1Um zzu0uS3y#x(0c*{hcZ)Cw<^QpNMlh5Tzms+Yef{_<_A`$?Im3oJhXV)7h3hIfq2FnL z7=(^uKn?}y(OlxRgmnfOL}%6qP14!cShkHl#D@M$CBrm`18J&_MU{ys`EJX!v$`5O zw>H~tQX9gT%v1NDv!SV3z@~9izq9&|03ECTSJVd!sM(hz$_Z7(P+OH~?M!3$d$K&| z2G4y-7*_w3ddGs$k7CqhX@7OCSypmkzo+7ZERalbuIE<#XE_^R_9w?hU}!j%2ii7j zcB?_%Ssu~q_Fa;oMD%5NoqPUdqt``q{GYgl`7_>5(%`@9&xi(HFrsA$&l6S0$? z*^W^EJZX^=*53~2Pa$3f>#87t{s6~Iv-Ex-6Oac1Dg7fVJ=@zrlYyN(zy<<_f2R%; znrW5@fIJD1a`23U#xBs_1tS_lK!8AjpS#vSmkN4dX9E;KiVI(4R<>W@^3l6s zA`iEj^VYBCic&y~>mMl0-eEcOZ{XLVj_fn+M7)^XU?wmHbs-bSGAV-qfr<;AtNtHr zo-Z=L^$%^P?b6tOPplc?)MQ5JdUv6^ce!0}O7I~1K*gE2JX%l}pOGv9yp2)_wSVBY z9;^nA%#6s{?~~F^Wxq z-hXKYAfrdPuF+zSx3s2HACNHX0o6!sEB^RkrGwpxqNg6_11T~CldqDlG~pqXCX!;c zBtfb`*~o890Aq_Y0&{II1<;Q6ZN zPM}-G=GcH4N{$`!miPy6hBYl;4vSG$Q;)5kJ%FE8kx!@=dKg8)Olhsywq`K_kBBtU zg{Zv-K+A+Mso_kXL}lgPq~1P>D+eh$02F;Ld%d+pen}Wwz#Ynkh^1D|7eHRL;@^sB zg1c$=y#QJ^;2l$A7Rq}1jWarDiyB29$=;>lpWJ6qROr0-T0oh??jGVa>izM#UdW|J zr<80YPn;G=kHUyU(GXUnv|EzB5xH%cNM+}Pz`T=btUnHojgMm=dpht5;HRh*{?4p< z{5W<)?Se=sAaua4(L;K*PqwNaPk^!M&Tu+)svq;}`46{Cl!~|>O!S}K5LZBqkX9!k z2TCvpOn*3oQlp0m%ymC*Qsl$)l3=fTZAL>!trA3M@TbD(*;DjZ+fQh@$|BzstutZ44+ZC|)@hADqA4?$R54uPcBJ-EJ48EqRXNIfxd zDkT1c6KbsO-4M(n!L*8+<3 z-L7t~Y+=TsQTbX>f?a7Nl95&hVrNy-w4hmJa{lm2ACDtbThM}@JsfD%d=RboiAun& zBUkoQaXXo*XQ@sE-9Dt0ZNH`pKZVS9e+HX)C7Ud(8gkAhD44TBy}TGF5$D0LYu6+M ztiEX)(@ZFlxluvCD8S - Webpack Bundle Analyzer + <%- title %> + <%- include('script', { filename: 'viewer.js' }) %> diff --git a/webpack.config.js b/webpack.config.js index cc01a28a..428bf09a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ const compact = require('lodash/compact'); const webpack = require('webpack'); const TerserPlugin = require('terser-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); const BundleAnalyzePlugin = require('./lib/BundleAnalyzerPlugin'); module.exports = opts => { @@ -143,6 +144,14 @@ module.exports = opts => { ); } + plugins.push(new CopyWebpackPlugin([ + { + from: `${__dirname}/views/favicon.ico`, + to: `${__dirname}/public`, + } + ]) + ); + return plugins; })([]) }; From 50ea0014d353b41ff74911a7fb95442d368a3324 Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 12 Sep 2019 11:19:28 +0800 Subject: [PATCH 2/4] Apply suggestions from code review Co-Authored-By: Yuriy Grunin --- views/viewer.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/viewer.ejs b/views/viewer.ejs index 49bb4ed1..eb348b43 100644 --- a/views/viewer.ejs +++ b/views/viewer.ejs @@ -3,7 +3,7 @@ - <%- title %> + <%= title %> <%- include('script', { filename: 'viewer.js' }) %> From 49a36f2eeb92210c64ea176381e0ae38dacd696e Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 12 Sep 2019 11:49:32 +0800 Subject: [PATCH 3/4] use base64 favicon. update datetime format to : 12/Sep 14:40. --- package-lock.json | 80 ----------------------------------------------- package.json | 3 +- src/utils.js | 9 +++--- views/viewer.ejs | 2 +- webpack.config.js | 9 ------ 5 files changed, 7 insertions(+), 96 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f122e74..e1247d95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2588,54 +2588,6 @@ "is-plain-object": "^2.0.1" } }, - "copy-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==", - "dev": true, - "requires": { - "cacache": "^11.3.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.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "webpack-log": "^2.0.0" - }, - "dependencies": { - "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" - } - }, - "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 - } - } - }, "core-js": { "version": "2.6.5", "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", @@ -3204,32 +3156,6 @@ "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" - }, - "dependencies": { - "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" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, "dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -9284,12 +9210,6 @@ } } }, - "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", diff --git a/package.json b/package.json index b9c4f75b..1d295b24 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,6 @@ "chai": "4.2.0", "chai-subset": "1.6.0", "classnames": "2.2.6", - "copy-webpack-plugin": "^5.0.4", "core-js": "2.6.5", "css-loader": "2.1.1", "cssnano": "4.1.10", @@ -78,7 +77,7 @@ "gulp-babel": "8.0.0", "mobx": "5.9.4", "mobx-preact": "3.0.0", - "mocha": "^6.2.0", + "mocha": "6.2.0", "nightmare": "3.0.1", "postcss-icss-values": "2.0.2", "postcss-loader": "3.0.0", diff --git a/src/utils.js b/src/utils.js index c42f77b7..375e28c5 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,8 @@ const {inspect} = require('util'); const _ = require('lodash'); +const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + exports.createAssetsFilter = createAssetsFilter; function createAssetsFilter(excludePatterns) { @@ -35,14 +37,13 @@ function createAssetsFilter(excludePatterns) { /** * @desc get string of current time - * format: MM/dd/yyyy HH:mm + * format: dd/MMM HH:mm * */ exports.getCurrentTime = function () { const time = new Date(); - const year = time.getFullYear(); - const month = time.getMonth() + 1; + const month = MONTHS[time.getMonth()]; const day = time.getDate(); const hour = time.getHours(); const minute = time.getMinutes(); - return `${month}/${day}/${year} ${hour}:${minute}`; + return `${day}/${month} ${hour}:${minute}`; }; diff --git a/views/viewer.ejs b/views/viewer.ejs index eb348b43..a66eef42 100644 --- a/views/viewer.ejs +++ b/views/viewer.ejs @@ -4,7 +4,7 @@ <%= title %> - + <%- include('script', { filename: 'viewer.js' }) %> diff --git a/webpack.config.js b/webpack.config.js index 428bf09a..cc01a28a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,7 +1,6 @@ const compact = require('lodash/compact'); const webpack = require('webpack'); const TerserPlugin = require('terser-webpack-plugin'); -const CopyWebpackPlugin = require('copy-webpack-plugin'); const BundleAnalyzePlugin = require('./lib/BundleAnalyzerPlugin'); module.exports = opts => { @@ -144,14 +143,6 @@ module.exports = opts => { ); } - plugins.push(new CopyWebpackPlugin([ - { - from: `${__dirname}/views/favicon.ico`, - to: `${__dirname}/public`, - } - ]) - ); - return plugins; })([]) }; From fe488671f83580b9626f152d1393a9bdb1fec206 Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 12 Sep 2019 16:51:01 +0800 Subject: [PATCH 4/4] remove favicon file. use webpack icon as favicon. update datetime format to : 12 Sep 2019 at 14:40. withdraw mocha version change. --- package-lock.json | 29 +++++++++++++++++++---------- package.json | 2 +- src/utils.js | 3 ++- views/favicon.ico | Bin 8456 -> 0 bytes views/viewer.ejs | 2 +- 5 files changed, 23 insertions(+), 13 deletions(-) delete mode 100644 views/favicon.ico diff --git a/package-lock.json b/package-lock.json index e1247d95..bf353a80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6653,9 +6653,9 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.2.tgz", + "integrity": "sha512-BgD2/RozoSC3uQK5R0isDcxjqaWw2n5HWdk8njYUyZf2NC79ErO5FtYVX52+rfqGoEgMfJf4fuG0IWh2TMzFoA==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -6667,12 +6667,12 @@ "glob": "7.1.3", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.1", + "js-yaml": "3.13.0", "log-symbols": "2.2.0", "minimatch": "3.0.4", "mkdirp": "0.5.1", "ms": "2.1.1", - "node-environment-flags": "1.0.5", + "node-environment-flags": "1.0.4", "object.assign": "4.1.0", "strip-json-comments": "2.0.1", "supports-color": "6.0.0", @@ -6753,6 +6753,16 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, + "js-yaml": { + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.0.tgz", + "integrity": "sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -7001,13 +7011,12 @@ } }, "node-environment-flags": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", - "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", + "integrity": "sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q==", "dev": true, "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" + "object.getownpropertydescriptors": "^2.0.3" } }, "node-forge": { diff --git a/package.json b/package.json index 1d295b24..68af49f8 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "gulp-babel": "8.0.0", "mobx": "5.9.4", "mobx-preact": "3.0.0", - "mocha": "6.2.0", + "mocha": "6.1.2", "nightmare": "3.0.1", "postcss-icss-values": "2.0.2", "postcss-loader": "3.0.0", diff --git a/src/utils.js b/src/utils.js index 375e28c5..2b579e54 100644 --- a/src/utils.js +++ b/src/utils.js @@ -41,9 +41,10 @@ function createAssetsFilter(excludePatterns) { * */ exports.getCurrentTime = function () { const time = new Date(); + const year = time.getFullYear(); const month = MONTHS[time.getMonth()]; const day = time.getDate(); const hour = time.getHours(); const minute = time.getMinutes(); - return `${day}/${month} ${hour}:${minute}`; + return `${day} ${month} ${year} at ${hour}:${minute}`; }; diff --git a/views/favicon.ico b/views/favicon.ico deleted file mode 100644 index 4a90d9aca83c5a65224ea447ead03475036d01a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8456 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 <%= title %> - + <%- include('script', { filename: 'viewer.js' }) %>